0.8.1 version tag - without RC

git-svn-id: https://svn.apache.org/repos/asf/oodt/tags/0.8.1@1684487 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/0.8.1-rc1/CHANGES.txt b/0.8.1-rc1/CHANGES.txt
new file mode 100644
index 0000000..edd4f5b
--- /dev/null
+++ b/0.8.1-rc1/CHANGES.txt
@@ -0,0 +1,1145 @@
+Apache OODT Change Log
+======================
+Release 0.8.1 - 01/28/2015
+-------------------------------------------
+* OODT-804 Broken trunk build on Jenkins
+
+* OODT-699 Mesos cluster manager backend to resource manager
+
+* OODT-780 Spark backend to resource manager
+
+* OODT-802 Create Dockerfile for OODT Radix.
+
+* OODT-761 Update PGE version in Radix.
+
+* OODT-749 Remove old XercesImpl jar from grid pom.
+
+* OODT-771 Fix push_pull_framework.properties path reference for config.external.properties.files in incorrect with a patch from Lewis
+
+* OODT-770 Fix the RADIX Issues with a patch from Lewis McGibbney
+
+Release 0.8 - 12/19/2014
+--------------------------------------------
+
+* OODT-751 OPSUI pages constantly expire (Tom Barber, mattmann)
+
+* OODT-748 Fix Description in agility/setup.py
+
+* OODT-787 PGE_ROOT env variable does not work in PGEConfig.xml and tasks.xml (Yi Sun, Sneha Deshmukh via mattmann)
+
+* OODT-562 Exposing parent-child & element addition/deletion functionality for product types using cas-curator (varunr)
+
+* OODT-563 Modifying Workflow Manager to allow adding new workflows (varunr)
+
+* OODT-786 Change shebang to bash for proper color output (Poojit Sharma via mattmann)
+
+* OODT-785 Update batch stub with legacyMode set to true (meghamsh4 via mattmann)
+
+* OODT-783 RADiX Crawler action bean config refers to WORKFLOWMGR_URL (Angela Wang via mattmann)
+
+* OODT-782 Resource manager port number must be compatible with the one used in workflow.properties (Imran Mammaldi via mattmann)
+
+* OODT-769 The wiki page command installs 0.6 version of the oodt radix installer (lewismc, Santosh SHankar)
+
+* OODT-777 Update fileconcatenator-pge.tar for building fileconcatenator-pge (threeears via mattmann)
+
+* OODT-776 Test fix: log messages can be different for different locales (Tom Tung via mattmann)
+
+* OODT-701 Adding in stream product structure for filemanager. Add in check for valid product structures, and fixed tests breaking from that check.
+
+* OODT-699 Adding in cluster managment scripts for mesos.
+
+* OODT-764 Adding in multiplexing resource manager backend.
+
+* OODT-763 Correcting path to OODT_HOME and FILEMGR_HOME (vishalhemnani via mattmann)
+
+* OODT-385, OODT-630, OODT-631, OODT-632. Upgraded Tika to version 1.6.
+
+* OODT-757 Fixed PGETaskInstance bug that prevented instantiation of AutoDetectProductCrawler (luca)
+
+* OODT-756 HttpClient NoClassDefFoundError For the url-downloader Script (Mengying Wang via mattmann)
+
+* OODT-754 Contribute ProdTypePatternMetExtractor (rickdn)
+
+* OODT-750 Issue with running mvn site:site due to old findbugs plugin (mattmann)
+
+
+Release 0.7 - 09/15/2014
+-------------------------------------------- 
+
+* OODT-669 Make Resource Manager work without Ganglia (mattmann, rajith)
+
+* OODT-644 Fix to FTP protocol tests, abstracting some of the logic to make the code better suited to mocking(magicaltrout)
+
+* OODT-644 Fix to stub FTP client protocol so it doesn't fail when the port is in use
+
+* OODT-644 Partial fix to stub SSH client so it doesn't fail when SSHD is running locally
+
+* OODT-745 Removed trailing spaces in the radix wmgr filex
+
+* OODT-473 Rremove "Deleted" Metadata Flag from Solr Indexer (magicaltrout)
+
+* OODT-736 Clean up test data left by TestTypeHandler test (rlaidlaw)
+
+* OODT-667 CAS-PGE no longer respects writers and file tags from 
+  earlier pgeConfig.xml files (mattmann)
+
+* OODT-741 Remove static modifier from elementMap, subToSuperMap and
+  productTypeElementMap fields in XMLValidationLayer (rlaidlaw)
+
+* OODT-737 Copied over latest cmd-line-options.xml with typeName (rlaidlaw)
+
+* OODT-739 Fix File Manager unit tests (step 12) - fix test classes in
+  'metadata' and 'versioning' packages (rlaidlaw)
+
+* OODT-738 Contribute workflow scripts to kill all by status or kill by instance ID (mattmann)
+
+* OODT-737 Fix File Manager unit tests (step 11) - fix test classes in 'cli'
+  package (rlaidlaw)
+
+* OODT-736 Fix File Manager unit tests (step 10) - fix test classes in 'structs'
+  package (rlaidlaw)
+
+* OODT-735 Fix File Manager unit tests (step 9) - fix test classes in 'tools'
+  package (rlaidlaw)
+
+* OODT-734 Fix File Manager unit tests (step 8) - fix test classes in 'system'
+  package (rlaidlaw)
+
+* OODT-733 Fix File Manager unit tests (step 7) - fix test classes in 'ingest'
+  package (rlaidlaw)
+
+* OODT-732 Fix File Manager unit tests (step 6) - fix test classes in
+  'datatransfer' package (rlaidlaw)
+
+* OODT-731 Fix File Manager unit tests (step 5) - fix test classes in 'catalog'
+  package (rlaidlaw)
+
+* OODT-728 Figure out why certain metadata fields get set twice during pipeline processing (mattmann)
+
+* OODT-729 Fix File Manager unit tests (step 4) - fix test classes in 'util'
+  package (rlaidlaw)
+
+* OODT-690 RADiX example policy for GenericFile missing "<metadata/>" node (rverma via mattmann)
+
+* OODT-718 RADiX Build Failure (tpalsulich, goodale via mattmann)
+
+* OODT-726 Create MetFilter Task Example (mattmann)
+
+* OODT-724 Crawler action bean config refers to WORKFLOWMGR_URL (mattmann)
+
+* OODT-723 Fix File Manager unit tests (step 3) - fix test class in 'validation'
+  package (rlaidlaw)
+
+* OODT-722 Fix File Manager unit tests (step 2) - fix test class in 'repository'
+  package (rlaidlaw)
+
+* OODT-672 OODT Start script does not notify user of status (asumarlidason via mattmann)
+
+* OODT-721 Fix File Manager unit tests (step 1) - remove duplicate XML from test
+  resources (rlaidlaw)
+  
+* OODT-719 Prevent httpclient from spawning closewait tcp connections (Konstantinos Mavrommatis via lewismc)
+
+* OODT-685 ix OODT 0.7-SNAPSHOT Jenkins nightly build on Ubuntu 1st Pass (lewismc)
+
+* OODT-716 Vagrant user on VM unable to start/stop oodt services (sherylj)
+
+* OODT-708 Add PGE RADiX Archetype (skhudiky)
+
+* OODT-593 Dyn workflows in Workflow Manager cause NPEs on restart (mattmann)
+
+* OODT-705 RADIX one step script (mattmann)
+
+* OODT-703 DataUtil.createProductZipFile throws exception when creating a zipfile of a hierarchical product (thomas)
+
+* OODT-674 MoveDatafileToFailureDir fails to move files off an NFS mounted directory (thomas)
+
+* OODT-662 Upgrade cog-jglobus dependency in protocol-ftp (lewismc)
+
+* OODT-668 ProductQueryServlet will now rename zip attachments with proper ".zip" extension,
+  and the conventions used can be overridden by subclasses (luca)
+
+* OODT-217 CAS-PGE User Manual (rverma, bfoster, mattmann)
+
+* OODT-665 CAS RDF and RSS product service doesn't allow product type met to have keys 
+  with spaces (mattmann)
+
+* OODT-664 RADIX deployment of opsui incorrectly uses /pcs-opsui as the web.xml context 
+  and omits 2 key PCS properties from context.xml (mattmann, pramirez, ahart)
+
+* OODT-663 Sample CAS-PGE workflow task should be included in cas-pge (mattmann)
+
+* OODT-661 Enabled case-insensitive specification of "OFSN" and "RT" parameter names
+  (not values!) when issuing a request to the Product Server (luca)
+
+* OODT-656 Provide alternative implementation of QueryServlet that is able 
+  to construct queries from non DIS-style parameters (luca)
+
+* OODT-613 CAS Product web application - configurable content writers for RDF
+  and RSS (rlaidlaw)
+
+* OODT-612 CAS Product web application - add content writers for XML, JSON, RDF,
+  RSS (rlaidlaw)
+
+* OODT-652 New TikaCmdLineMetExtractor (riverma)
+
+* OODT-651 Improve parameter initialization, validation and logging for
+  CAS-Product web application (rlaidlaw)
+
+* OODT-650 Remove duplicate context container example from CAS-Product web
+  application (rlaidlaw)
+
+* OODT-649 Add PathUtils.replaceEnvVariables wrapper around calls to
+  context.getInitParameter to process environment variables (rlaidlaw)
+
+* OODT-611 Implement JAX-RS services to access File Manager products as raw
+  data (rlaidlaw)
+
+* OODT-648 Add license headers to files so that mvn rat:check is successful 
+  (lewismc)
+
+* OODT-642 In CAS-Product, moved tests to src/test/java and test resources to
+  src/test/resources to match Maven standard directory layout (rlaidlaw)
+
+* OODT-619 Implement the capability to pull status of resource 
+  nodes from ganglia (Rajith Siriwardana via mattmann)
+
+
+Release 0.6 - 07/08/2013
+--------------------------------------------
+
+* OODT-633 Update PEAR package.xml files for upcoming release. (gmcdonald)
+
+* OODT-640 Added version number for maven-war-plugin to CAS-Product POM
+  (rlaidlaw)
+
+* OODT-639 Add a versioner based on Product Type Metadata (mattmann)
+
+* OODT-638 Include more provenance metadata in trace product type (mattmann)
+
+* OODT-637 Geo Product Type policy includes duplicative elements (mattmann)
+
+* OODT-635 Fix trivial errors in Basic CAS Curation Example (lewismc via mattmann, Bill Rideout)
+
+* OODT-636 Fixed Javadoc warnings in CAS-Product (rlaidlaw)
+
+* OODT-634 Fixed lingering bug in Solr Catalog implementation that would still not return null
+           if no matching product is found (luca)
+* OODT-628 Multiple cluster Ganglia xml parse error (Rajith Siriwardana via mattmann)
+
+* OODT-610 Added new empty package oodt.cas.product.service for future JAX-RS
+  classes (rlaidlaw)
+
+* OODT-609 Added Apache CXF dependency to the CAS-Product POM (rlaidlaw)
+
+* OODT-624 Updated maven-javadoc-plugin to v2.9 (rlaidlaw)
+
+* OODT-623 Addition of relativePath to the opendapps/pom.xml to help it locate
+  the oodt-core POM (rlaidlaw)
+
+* OODT-618 Implement ganglia XML parser (Rajith Siriwardana via mattmann)
+
+* OODT-625 Bake TraceableFile product policy into FM (mattmann)
+
+* OODT-622 Updated svn:ignore properties for several modules to add Eclipse
+  configuration files to the ignore lists (rlaidlaw)
+
+* OODT-572 Replace mkdir with more multi-thread resilient forceMkdir in 
+  LocalDataTransferer (Tom Barber via mattmann)
+
+* OODT-559 Unit test failure in testDoDynamicReplacement for "Europe/London" 
+  timezone (Tom Barber via mattmann)
+
+* OODT-615 Fixed bug in SolrCatalog that would throw exception if no matching products are found
+           (luca)
+
+* OODT-408 Drop Spring logging levels from WARNING to SEVERE (Lewis John McGibbney
+  via mattmann, bfoster)
+
+* OODT-607 SciPgeWriter that is a simple MetKey template replacer (mattmann)
+
+* OODT-606 SciPgeWriter that uses ApacheVelocity (mattmann, pramirez)
+
+* OODT-592 Provide Solr-based implementation of CAS File Manager (luca)
+
+* OODT-590 modify pcs references in opsui webapp (riverma)
+
+* OODT-589 add pcs_home env variable to env script (riverma)
+
+* OODT-586 RADiX archetype does not properly deploy crawler (riverma)
+
+* OODT-603 Enable Resource Manager start/stop within RADiX (riverma)
+
+* OODT-600 Modularize old OPSUI theme into a separate Wicket "skin" (riverma)
+
+* OODT-599 Modularize new theme into a stand-alone Wicket "skin" (riverma)
+
+* OODT-597 Improve theme/styling of OPSUI (riverma)
+
+* OODT-596 Fix opsui webapp's wicket 'Page Expired' error (riverma)
+
+* OODT-595 Improve styling of Workflow Viewer (webapp/components) (riverma)
+
+* OODT-602 Load not settable for WorkflowTaskJobs in 
+  IterativeWorkflowProcessThread (mattmann)
+
+* OODT-470 Enabled RSSProductTransferServlet to be configured using an XML
+  configuration file (rlaidlaw)
+
+* OODT-560 XmlStructFactory::getProductTypeMapXmlDocument does not 
+  output virtual product types (Varun Ratnakar via mattmann)
+
+* OODT-583 Added JUnit test class for RSSConfigReader (rlaidlaw)
+
+* OODT-582 Fix for oodt.cas.product.rss.RSSConfigReader.readTags() for detection
+  of source attribute for tags defined in the RSS configuration file (rlaidlaw)
+
+* OODT-576 Used try...finally in oodt.commons.database.SqlScript.loadScript() to
+  close BufferedReader (rlaidlaw)
+
+* OODT-537 Push/Pull NullPointerException on startup (mattmann, joyce)
+
+* OODT-578 Workflow Monitor experiences runtime exception (NPE) out 
+  of the box with RADIX (Arni Sumarlidason via mattmann)
+
+* OODT-575 Metadata extractor for parsing filename based on regex 
+  (Nga Chung via mattmann)
+
+* OODT-573 Refactored the return statement in the getTopNProducts method in the
+  LuceneCatalog class (rlaidlaw)
+
+* OODT-571 Updated assignments in setWorkflowInst and setWaitforConditionSatisfy
+  methods in IterativeWorkflowProcessorThread class (rlaidlaw)
+
+* OODT-574 RADiX POM Parent References (Arni Sumarlidason via mattmann)
+
+* OODT-491 Add nextState (determineNextState) function to 
+  WorkflowProcessor (mattmann)
+
+* OODT-558 Introducing optional web-grid servlet init parameter "org.apache.oodt.grid.GridServlet.config" 
+ that can be used to read/write its configuration to a location external to the web app directory (luca).
+
+* OODT-564 XMLPS should provided ordered results based on 
+  requested fields (mattmann, joyce)
+
+* OODT-369 Building with Maven3 (mattmann, Adam Estrada)
+
+* OODT-555, OODT-557 - Changed behavior of Lucene Catalog update methods to retrieve a product from the index to the cache, 
+  instead of failing if it is not found in the cache. At the same time, simplify the Curator updateMetadata() method to just update
+  the metadata, without removing and re-inserting the product before that.
+  (luca, rishi, mattmann)
+
+* OODT-553 Update org.apache.oodt.commons.exec.EnvUtilities to Use System.getEnvironment 
+  (Michael Starch via mattmann)
+
+* OODT-551 Insert primary key in metadata table for database-based File Manager, to always return metadata values in proper order
+           (luca, mattmann, bfoster)
+
+* OODT-548 Be more resilient to table definitions matching the master table 
+  in the Mapping config file (mattmann,joyce)
+
+* OODT-546 XMLPS inner-joins default table with itself (mattmann,joyce)
+
+* OODT-547 Switch newest Curator upudate metadata method to use XML-RPC FileManager client.
+           Switch other Curator update metadata method to use shared instance of Catalog Factory 
+           to minimize use of resources.
+           (luca)
+
+
+Release 0.5 
+--------------------------------------------
+Release Date: December 18, 2012
+
+* OODT-541 Implement a LenientDataSourceCatalog that allows for dynamically named
+  metadata fields, effectively bypassing the validation layer.
+  (luca)
+
+* OODT-544 Implement a DataSourceCatalog back-end to the CAS FileManager 
+  where the "product_id" column is of type string.
+  (luca)
+
+* OODT-545 Allow Curator web app to use a configurable CAS Catalog Factory 
+  as specified in curator.xml.
+  (luca)
+
+* OODT-543 Update ExpImpCatalog tool to allow core Metadata to pass through 
+  when Embedded Catalogs are used (mattmann, cinquini)
+
+* OODT-542 Need to update logging.properties for all servers post CAS CLI
+  (mattmann)
+
+* OODT-535 Provide capability to remove metadata tags through Curator 
+  web app. (luca)
+
+* OODT-533 Allow SolrIndexer to query and ingest products from the File 
+  Manager catalog by name. (luca)
+
+* OODT-534 Better error message when a product is looked by id in the catalog 
+  and not found. (luca)
+                      
+* OODT-529 Allow Lucene Catalog to be "lenient" with respect to XML validation,
+  i.e. allow handling of dynamically named fields if the "lenient" flag is set 
+  (defaults to false). (luca)
+
+* OODT-530 Bug fix: crawler MetExtractorProductCrawler had a list of precondition 
+  beans that was not initialized to an empty list, with would cause a Spring 
+  initialization exception when more than one preconditions was injected. (luca)
+           
+* OODT-531 Bug fix: the legacy Spring configuration file legacy-cmd-line-options.xml 
+  was missing some required configuration for the beans "noRecur" and "crawlForDirs".
+  (luca)
+           
+* OODT-532 Bug fix: pre-condition bean "AprioriUniquessCheckWithFilemgr" was missing 
+ the filemgrUrl property, which was therefore never set at initialization. (luca)
+
+* OODT-522 Provided additional Curator REST endpoint: "/metadata/update" that updated 
+  product metadata in place, i.e. preserves all existing catalog metadata (luca)
+
+* OODT-523 Updated Curator CXF dependency to 2.6.0 and removed FIXME patch to 
+  extract "id" from "/metadata/catalog" request (luca)
+
+* OODT-528 Merged back changed to CuratorLuceneCatalog into File Manager LuceneCatalog,
+  and change Curator to use mainstream File Manager Lucene Catalog (luca)
+
+* OODT-272 Enable Removal of Finished Ingestion Tasks
+  (Michael Joyce via mattmann)
+
+* OODT-328 Remove jpl.nasa.gov references from code 
+  (Michael Joyce via mattmann)
+
+* OODT-520 Default Crawler launcher doesn't reference FileManager 
+  properties (Mike Joyce via mattmann)
+
+* OODT-502: Support pre and post conditions in Workflow Processor 
+  Queue (mattmann)
+
+* OODT-516: Add WorkflowLifecycle tests that check pctComplete for 
+  wengine and w1 style lifecycles (mattmann)
+
+* OODT-501: Method to create Processor from Instance should be based on 
+  Graph structure (mattmann)
+
+* OODT-511: Solr Indexer Date Formatting Removes Metadata (pramirez)
+
+* OODT-510: SolrIndexer fails on ProductTypes that have 0 products (pramirez, ahart)
+
+* OODT-496: Convert EngineRunner interface to take TaskProcessor (mattmann)
+
+* OODT-505: Remove synchronous Runner (mattmann)
+
+* OODT-498: Overwrite and bring back 0.3 ThreadPoolWorkflowEngine plus 
+  patches (mattmann)
+
+* OODT-500: Rename property for max threads in AsyncLocalEngineRunner (mattmann)
+
+* OODT-497: Make WorkflowProcessor PrioritySorters thread-safe (mattmann)
+
+* OODT-492: Refactor Workflow Instance repo to store/retrieve that state 
+  information (mattmann)
+
+* OODT-490: Refactor WorkflowProcessor to push all of its state information 
+  into Workflow Instance (mattmann)
+
+* OODT-432: Add FileSize to know metadata fields set by CAS-Crawler 
+  (bfoster via mattmann)
+
+* OODT-381: Create Runner framework to allow flexible WorkflowTask 
+  execution on different runtimes (mattmann, bfoster)
+
+* OODT-215: Workflow2 Architecture (mattmann, bfoster, sherylj)
+
+* OODT-310: Port WEngine to trunk (mattmann, bfoster, sherylj)
+
+* OODT-487: MetadataBasedProductMover to handle when the source and destinations match (cgoodale)
+
+* OODT-488: Enhanced Solr Indexer capabilities (pramirez)
+
+* OODT-390: Removal of optimize call in Lucene Workflow Instance Repository (pramirez)
+
+* OODT-486: WorkflowInstance tries to cast null strings into dates causing
+  exceptions on getters/setters (mattmann)
+
+* OODT-483: Fix to prevent NumberFormatException in XmlRpcStructFactory (rlaidlaw)
+
+* OODT-471: Added namespace definitions to RSS config files for CAS REST API (rlaidlaw)
+
+* OODT-469: Modified RSSProductServlet to remove hard-coded namespaces and allow 
+configurable namespaces via RSS config files (rlaidlaw)
+
+* OODT-485: Factory out EngineRunner and WorkflowProcessor classes into their own packages (bfoster)
+
+* OODT-481: CAS-Pushpull uniqueMetadataElement is being loaded as empty String instead of null (bfoster)
+
+* OODT-474: Fixed the probem having in a configuration file 
+  ProtocolFactoryInfo.xml (mattmann, YunHee Kang)
+
+* OODT-478: Balance: New hook for hooks.php (nhidalgo via ahart)
+
+* OODT-476: RemoteSiteFile doesn't always set RemoteSite (bfoster)
+
+* OODT-477: CommonsNetFtpProtocol throws exception on successful download (bfoster)
+
+* OODT-329: OODT PEAR Channel (Gavin McDonald via mattmann)
+
+* OODT-472: Puny Module - Return to previous page once the user is done editing  (skhudiky)
+
+* OODT-467: Change SciPgeConfigFileWriter to DynamicConfigFileWriter (bfoster)
+
+* OODT-464: Add file staging support to CAS-PGE's XmlFilePgeConfigBuilder (bfoster)
+
+Release 0.4
+--------------------------------------------
+Release Date: June 13th, 2012
+
+* OODT-446 Addition of Puny module to Balance (skhudiky)
+
+* OODT-462: Include support for special processing instructions in opendap-ps configuration file (luca)
+
+* OODT-463: Ignore container-type DAS attributes when parsing metadata in opendap-ps module (luca)
+
+* OODT-402: Provided default File Manager policy and RSS configuration for 
+products with location metadata.  See subtasks OODT-449, 452 and 453. (rlaidlaw)
+
+* OODT-449: Added default GeoRSS configuration file for the CAS REST RSS service. (rlaidlaw)
+
+* OODT-452: Moved File Manager policy files for GenericFile type (elements.xml, product-types.xml, 
+product-type-element-map.xml) to filemgr/src/main/resources/examples/core subdirectory.  
+Updated six unit tests to use the new subdirectory. (rlaidlaw)
+
+* OODT-453: Added File Manager policy files for simple LocationAwareProduct
+(elements.xml, product-types.xml, product-type-element-map.xml). (rlaidlaw)
+
+* OODT-457: add missing Datatables images for paging through Cas-browser index page (skhudiky)
+
+* OODT-455 Small CSS tweak for the OPSUI Wicket App (cgoodale)
+
+* OODT-451 Implemented CAS metadata precondition class to check for existence of given marker file
+           within product directory (luca)
+
+* OODT-445 Extend env replace support introduced in OODT-343 (ahart)
+
+* OODT-444 Utils class missing from Balance cas-browser module (ahart)
+
+* OODT-448 added missing character (skhudiky)
+
+* OODT-447 changed reference to CAS-SSO directory in the profile management module README.txt (skhudiky)
+
+* OODT-450 Crawler being able to delete a non-empty product directory
+  upon successful product ingestion (luca)
+
+* OODT-421 Make WorkflowLifecycleManager understand 
+  WorkflowStates (mattmann)
+
+* OODT-440 Replace legacy getMetadata("UUID") calls with 
+  getMetadata("CAS." + CoreMetKeys.PRODUCT_ID) (thomas)
+
+* OODT-442 Apache project branding requirements: DOAP
+  file [PATCH] (Shane Curcuru via mattmann)
+
+* OODT-438 Make CAS-Crawlers MimeExtractorConfigReader relative file paths be relative to its
+   XML file (bfoster)
+ 
+* OODT-426 Introduce a CAS-Metadata based renaming interface (bfoster)
+
+* OODT-435 Refactor Graph and ParentChildWorkflow class 
+  outside of PackagedWorkflowRepository (mattmann)
+
+* OODT-157 PCS Operator User Interface web application  
+  (mattmann, ahart, cgoodale, pramirez)
+
+* OODT-401 added profile management module to balance modules directory (skhudiky)
+  
+* OODT-433 Fix retrieveFileByName and retrieveFileById buy setting the product's references 
+  before calling retrieveProduct (thomas)
+
+* OODT-430 Update all boolean type bean properties in the crawler cmd-line-options.xml (thomas)
+
+* OODT-412 Bugfix: MoveMetadataToFailureDir should read MoveMetadataFileToFailureDir (thomas)
+
+* OODT-428 CrawlerBeansPropHandler doesn't set list properties for Spring
+  PropertyOverrideConfigurer correctly (bfoster)
+
+* OODT-429 filemgr query throws NPE when sorting by key with possibly empty values (rickdn)
+
+* OODT-427 filemgr query throws "String index out of range: -1" when some products have undefined
+  metadata values (rickdn)
+
+* OODT-405 Introduced new syntax for environment variable replacement in opendapps module (luca)
+
+* OODT-425 CAS-PGE logger unit-test fails because it sometimes finds logger lock file (bfoster)
+
+* OODT-422 Allow for CAS-PGE PgeMetadata to be dumped to an xml
+  file after initialization (bfoster)
+
+* OODT-410 DataSourceCatalog compatible with HypersonicSQL 
+  (mattmann,rickdn,bfoster,pramirez)
+
+* OODT-413 filemgr query throws NPE when some products have undefined metadata values (rickdn)
+
+* OODT-420 CAS-PGE should fail when product ingests fail (bfoster)
+
+* OODT-419 Make PgeConfigBuilder configuration via PgeTaskMetKeys (bfoster)
+
+* OODT-418 Improve CAS-PGE logging (bfoster)
+
+* OODT-71 Add lifecycle model supporting transition, done 
+  and waiting states (mattmann)
+
+* OODT-414 Create Java Logger Handler for CAS-PGE (bfoster)
+
+* OODT-415 Add support to ExecUtils callProgram to take OutputStreams
+  for forwarding stdout and stderr (bfoster)
+
+* OODT-249 When a node is removed from the Resource Management 
+  system, it should be removed from all of its queues as well (gabe via mattmann)
+
+* OODT-376 Addition of Cas-Browser Balance module (gabe)
+
+* OODT-411 Port CAS-PGE's PcsMetadataKeys to PgeTaskMetKeys (bfoster)
+
+* OODT-409 Convert CAS-PGE metadata keys and workflow statuses from static Strings to enums (bfoster)
+
+* OODT-406 Add CAS-PGE support for multiple Property Adders (bfoster)
+
+* OODT-403 Port wengine ControlMetadata to cas-pge's PgeMetadata (bfoster)
+
+* OODT-34 Ability for File Manager to stage an ingested Product to one of its clients (bfoster)
+
+* OODT-400 Add options for CAS-Crawler's SendNotification CrawlerAction (bfoster)
+
+* OODT-399 cas-cli sub-option requirements for help printing was not
+  using p:required for GroupSubOption (bfoster)
+ 
+* OODT-395 SerializableMetadata.toXml() doesn't set namespace on root element (rickdn)
+
+* OODT-361 Workflow test event fails with NPE (rickdn)
+
+* OODT-373 PCS OpsUI component not listed in OODT pom.xml (ahart)
+
+* OODT-397 XmlRpcWorkflowManager tests don't properly clean up 
+  LuceneCatalog remnants (mattmann)
+
+* OODT-396 Add shutdown hook to the Workflow Manager server (mattmann)
+
+* OODT-394 Integrate CAS-Protocol with CAS-CLI (bfoster)
+
+* OODT-392 Remove old command line option code from commons (bfoster)
+
+* OODT-391 Integrate CAS-Catalog with CAS-CLI (bfoster)
+
+* OODT-352 Integrate CAS-CLI into CAS-Crawler (bfoster)
+
+* OODT-389 Lucene Workflow Instance Repository index now intialized on startup (pramirez)
+
+* OODT-382 Lucene FileManager index now intialized on startup (pramirez)
+
+* OODT-388 Clearly indicate location for loading globally-required Balance modules (ahart)
+
+* OODT-379 Fix CAS-CLI help option sorting and added handler initialization (bfoster)
+
+* OODT-362 Change CmdLineAction names to match their CmdLineOption long option (bfoster)
+
+* OODT-371 Improvements in the richness and consistency of metadata extracted from the THREDDS catalogs
+  in the opendap-ps module (luca)
+
+* OODT-341 XMLPS should be able to stream large results (rickdn)
+
+* OODT-375 Improve ApplicationResponse::includeJavascript to support including 
+  JavaScript snippets in addition to static files (ahart)
+
+* OODT-356 Tool to clean Workflow Instance repositories (mattmann, bfoster)
+
+* OODT-372 Correct LDAPAuthenticationProvider class name (Shakeh Khudikyan via ahart)
+
+* OODT-256 updateMetadata needed in XmlRpcFileManager (mattmann)
+
+* OODT-368 Refactoring of metadata extraction functionality for 
+  opendapps module (Luca Cinquini, mattmann)
+
+* OODT-366 Extension to opendapps module to extract ALL variables 
+  in DDS stream (Luca Cinquini, mattmann)
+
+* OODT-365 Main class to drive opendapps profile generation 
+  (Luca Cinquini, mattmann)
+
+* OODT-367 Integrate CAS protocol into PushPull (mattmann, bfoster)
+
+* OODT-364 Prevent XSS attacks via malformed query string (ahart)
+
+* OODT-363 Add support for LuceneQuery action to optionally return more than
+  just Product ID results (bfoster)
+
+* OODT-351 Integrate CAS-CLI into CAS-Filemgr (bfoster)
+
+* OODT-360 Add supported for CmdLineAction detailed help description (bfoster)
+
+* OODT-359 CmdLineUtility is not printing action messages (bfoster)
+
+* OODT-358 Change CmdLineUtility's run(String[]) method to throw
+  RuntimeException when in debug mode (bfoster)
+
+* OODT-357 Change Print Supported Actions StdCmdLinePrinter output
+  format to more "readable" (bfoster)
+
+* OODT-338 XMLPS unit tests should change constructor to 
+  setUp() (Ricky Nguyen via mattmann)
+
+* OODT-337 XMLPSProductHandler methods should return empty lists instead 
+  of null (Ricky Nguyen via mattmann)
+
+* OODT-336 xmlps should omit joining of tables that are unnecessary to 
+  fulfill query (Ricky Nguyen via mattmann)
+
+* OODT-339 MappingReader should add default join table to DatabaseTable 
+  if none defined (Ricky Nguyen via mattmann)
+
+* OODT-354 CAS-CLI StdCmdLinePrinter doesn't print optional sub-options
+  for group options (bfoster)
+
+* OODT-343 Add support for basic 'environment replacement' in 
+  module config.ini files (ahart)
+
+* OODT-353 getXmlRpcProduct and getProductFromXmlRpc should allow 
+  null values for product member variables since Product is just 
+  a carrier object (bfoster)
+
+* OODT-349 CAS-CLI CmdLineAction should take a printer which
+  it is required to print it's messages to (bfoster)
+
+* OODT-350 File Manager query_tool bug fix for Lucene
+  style queries (goodale, mattmann, bfoster)
+
+* OODT-348 Integration CAS-Resource with CAS-CLI (bfoster)
+
+* OODT-345 Integration CAS-Workflow with CAS-CLI (bfoster)
+
+* OODT-344 Workflow Conditions and Timeout Seconds causes 
+  backwards incompat SerDe issues with XML-RPC (mattmann)
+
+* OODT-330 Factor out command line utility from oodt-commons
+    - check in CAS-CLI... integration to other components to come (bfoster)
+
+* OODT-333 XMLPS query doesn't quote literal string 
+  (Ricky Nguyen, mattmann, Sheryl John)
+
+* OODT-323 Add new command line option in Workflow manager 
+  client to get Workflow Instance Metadata (Sheryl John via mattmann)
+
+* OODT-52 Update the CAS File Manager User Guide (thomas, goodale)
+
+* OODT-322 LDAPAuthenticationProvider class requires 
+  a non-existent path (Shakeh Khudikyan via mattmann)
+
+* OODT-321 PEAR install of PHP filemgr is not working 
+  properly (Shakeh Khudikyan via mattmann)
+
+* OODT-327 Open SSO plug-in client for CAS-SSO (mattmann, pramirez)
+
+* OODT-326 A tool to dump the File Manager catalog metadata 
+  into Solr (mattmann, pramirez)
+
+* OODT-37 Create an Action to Group other Actions Together (pramirez, mattmann)
+
+* OODT-36 Create an Action to Support Simple Branching (pramirez, mattmann)
+
+* OODT-150 ToggleAction addition to crawler (bfoster, mattmann)
+
+* OODT-34 Create an Action to Ingest an Ancillary File (mattmann, pramirez)
+
+* OODT-33 Refactor and Improve File Based Actions (mattmann, pramirez)
+
+* OODT-35 Create an Action to Send an Email (mattmann, pramirez)
+
+* OODT-320 Update OODT About Page (Adam Estrada via mattmann)
+
+* OODT-61 appendTableName property for mapping files in XMLPS 
+  breaks columnname-based lookup in 
+  ResultSet (Ricky Nguyen, mattmann, davekale) 
+
+* OODT-318 Fix for Jenkins builds and java.io.tmpdir issue 
+  for testing via Maven (mattann, Olivier Lamy)
+  
+* OODT-317 Workflow Priority Sorting (mattmann, bfoster)
+
+* OODT-172 Update CAS Curator Tutorial (thomas via mattmann)
+
+* OODT-316 Add the WorkflowManager Use Case Diagram back into 
+  the User Guide (mattmann)
+
+* OODT-43 Add the FileManager Use Case Diagram back into the 
+  User Guide (mattmann, cgoodale)
+
+* OODT-313 Copyright statement on OODT website needs updating 
+  (mattmann, Greg Stein)
+
+* OODT-311 Test failing related to workflow tasks and the 
+  DataSourceWorkflowRepository (mattmann, riverma, Cecilia S. Cheng)
+
+* OODT-299 Rename all Authentication properties to use
+  Authentication instead of Auth (ahart, Shakeh Khudikyan)
+
+* OODT-309 SequentialWorkflowProcessor doesn't need to be a 
+  Thread (mattmann)
+
+* OODT-205 WorkflowInstances should have pre-conditions as 
+  well (mattmann)
+
+* OODT-306 Added FileManager Tool Aliases (mattmann, goodale)
+
+* OODT-208 WorkflowConditions should be identifiable as optional 
+  or required (mattmann)
+
+* OODT-209 Workflow Manager Dynamic Workflows (mattmann)
+
+* OODT-211 Sub Workflows (mattmann, per OODT-70)
+
+* OODT-207 WorkflowConditions should have a timeout (mattmann)
+
+* OODT-308 WEditor save feature is not implemented (bfoster via mattmann)
+
+* OODT-296 Workflow Editor GUI (mattmann, bfoster, ahart)
+
+* OODT-294 Updated website to announce release of 0.3 (goodale)
+
+* OODT-180 Fixed small typo on website (goodale)
+
+* OODT-70 Add ability for sequential and parallel task 
+  specifications for Workflows (mattmann, bfoster)
+
+* OODT-295 BasicVersioner doesn't work with Hierarchical 
+  Products (mattmann, Tim Stough)
+
+
+Release 0.3
+--------------------------------------------
+Release Date: June 20th, 2011
+
+* OODT-292 Updated webapp poms to inherit from core parent pom to allow maven
+  release plugin to function properly (pramirez)
+
+* OODT-279 Make Resource Manager FAILURE and SUCCESS aware instead of just 
+  COMPLETE aware (mattmann, bfoster)
+
+* OODT-278 CAS-PGE returns success even if product file(s) fail to 
+  ingest (mattmann, bfoster)
+
+* OODT-243 Add method is called on already existing jobspec (mattmann, bfoster)
+
+* OODT-199 CoreMetExtractor chokes on Hierarchical Products (mattmann)
+
+* OODT-200 FinalFileLocationExtractor chokes on Hierarchical products
+  (mattmann)
+
+* OODT-186 Common base library for modular OODT web applications built 
+  using PHP (ahart, Gabe Resneck, Shakeh Khudikyan)
+
+* OODT-191 PushPull FileRetrievalSystem NPE if mime comment for type doesn't 
+  include ampersand (mattmann, bfoster) 
+
+* OODT-184 Add ability to poll the load of any particular node (Gabe Resneck via mattmann)
+
+* OODT-60 Annoying build warnings about dependencies that 
+  have "been relocated" (mattmann, davidkale)
+
+* OODT-198 Add test harness for XmlRpcResourceManager (mattmann)
+
+* OODT-182 Add ability to change node capacity during execution (Gabe Resneck via mattmann)
+
+* OODT-162 Parametric Data Model File Manager Catalog (mattmann, ahart, cgoodale)
+
+* OODT-195 XMLValidationLayer: Elements Map and ProductType to Element 
+  Map can become inconsistent (Michael Starch, mattmann, bfoster)
+
+* OODT-197 Null descriptions from elements.xml cause NPE when writing 
+  elements.xml file back out (mattmann, Michael Starch)
+
+* OODT-193 PGE ExternMetExtractor MetWriter (bfoster, mattmann)
+
+* OODT-192 PGE FilenameExtractorMetWriter (mattmann)
+
+* OODT-156 Rewrite Workflow Monitor webapp using Apache Wicket (mattmann)
+
+* OODT-190 WorkflowCondition configuration isn't read (mattmann)
+
+* OODT-189 Refactor and clean up WorkflowCondition 
+  Configuration (mattmann)
+
+* OODT-188 Precondition Comparator to ignore files with 
+  a particular extension (mattmann)
+
+* OODT-129 Integrate with Maven Central (mattmann)
+
+* OODT-177 PHP implementation of sso (ahart)
+
+* OODT-175 cas-wm-webapp javadoc fails maven build (mattmann, bfoster)
+
+* OODT-54 Xml Rpc Serde Casts Longs to Ints (pramirez via mattmann)
+
+* OODT-155 Rewrite File Manager Browser webapp using Apache Wicket (mattmann)
+
+* OODT-185 The File Manager's query_tool script does not handle quoted parameter values. (shardman)
+
+* OODT-181 Add documentation for metFileExt attribute on exec element in
+  ExternMetExtractor (mattmann)
+
+* OODT-179 Upgrade PushPull FTP protocol to use Commons Net 2.2 (mattmann)
+
+* OODT-176 Baked in file manager policy should include example of product type metadata (mattmann)
+
+* OODT-174 TestAcquisitionDateVersioner fails in the later evening (bfoster via mattmann)
+
+* OODT-172 Improvements to the Filename Extractor (mattmann)
+
+* OODT-170 cas-catalog shuffles query results . . . order is lost (bfoster)
+
+* OODT-169 Pushpull dirstruct xml files fail to replace global 
+  variables in name attribute for dir and file elements (bfoster)
+
+* OODT-166 Ability for puspull to dynamically generate ProductName for a given mime-type (bfoster)
+
+* OODT-167 ProcessedPageInfo isLastPage fails for case PageNum = 1 and totalPages = 0 (bfoster)
+
+* OODT-164 AcqusitionDate Versioner (mattmann)
+
+* OODT-163 DirectoryProduct Versioner for the File Manager (mattmann)
+
+* OODT-160 Allow number of session protocol connections in 
+  pushpull to be configurable for each site (bfoster)
+
+* OODT-161 PushPull getTextContext()/getNode() value still poses an issue for some JVMs (bfoster)
+
+* OODT-159 Dynamic Queue/Node was not added to command-line usage printout (bfoster)
+
+* OODT-152 Fixed website and download page.  Reverted back
+  to the same site from OODT-134. (goodale)
+
+* OODT-153 PathUtils [DATE.MONTH] and [DATE.DAY] should pad with 
+  a "0" not a " " (empty space) (bfoster via mattmann)
+
+* OODT-139 PCS JAX-RS services (mattmann, pramirez, bfoster, ahart)
+
+* OODT-151 Add xdocs for modules from old JPL site (mattmann)
+
+* OODT-110 TestExternMetExtractor fails if temp directory is mounted noexec (pramirez, smclees)
+
+* OODT-145 StreamGobbler stopGobblingAndDie() method doesn't wait 
+  until gobble is really dead (bfoster)
+
+* OODT-112 Link to slides on web-grid Maven page is broke (mattmann, goodale)
+
+* OODT-130 Fixed mailing list links for CAS Components maven generated site pages (goodale)
+
+* OODT-144 ExternAction for crawler which executes some external command (bfoster)
+
+* OODT-143 addition of fmprod context.xml and maven servlet-api 
+  dependency scope change to provider (Shakeh Khudikyan, mattmann)
+
+* OODT-142 TypeHandler SerDe is backwards incompat with older 
+  versions of FM (mattmann)
+
+* OODT-141 LuceneCatalog pagination throws LuceneException when 
+  grabbing out of bounds hitNum
+
+* OODT-140 commons-lang version should be standardized on 
+  (2.1. vs 2.3) (bfoster)
+
+* OODT-135 Process Control System Package (mattmann)
+
+* OODT-138 Reference class prints stack trace when mime type repo 
+  cannot be found (mattmann)
+
+* OODT-136 Lack of cataloged mime type causes recoverable exception in 
+  Reference core class (mattmann)
+
+* OODT-134 Update website with News of Release 0.2 and links for download (goodale)
+
+* OODT-128 CAS workflow monitor webapp fails to load due to unparsable 
+  character in JSP file (Rishi Verma via mattmann)
+
+Release 0.2 
+--------------------------------------------
+Release Date: January 17th, 2011
+
+* OODT-119 Curator REST API documentation (mattmann, joshuaga)
+
+* OODT-118 CAS Curator doesn't allow metadata update on file 
+  manager browser (mattmann)
+
+* OODT-116 Cas Curator doesn't ingest (mattmann)
+
+* OODT-117 Final File Location Extractor fails in actual use despite unit test 
+  passing (mattmann)
+
+* OODT-115 TestCatalogServiceLocal fails (mattmann, pramirez)
+
+* OODT-65 Release process now includes publishing to PyPi (pramirez, kelly, mattmann)
+
+* OODT-112 Link to slides on web-grid Maven page is broke (mattmann, kelly)
+
+* OODT-111 Allow a file to be specified in the URL for the 
+  opendapp configurator (Victor Hwang via mattmann)
+
+* OODT-108 Ability for the file manager to ingest a file in 
+  place (Faranak Davoodi via mattmann)
+
+* OODT-73 Update the OODT website @ http://oodt.apache.org  (goodale, kelly) 
+
+* OODT-86 The Product Server Should Have the Capability to Turn Off 
+  Reporting of File Sizes For File Listing Functions (Michael Cayanan via mattmann)
+
+* OODT-41 Product Constructor does not set transfer status (mattmann)
+
+* OODT-72 Unable to set Metadata based off Product Versioning during 
+  Product ingestion (mattmann, bfoster)
+
+* OODT-68 Add Number of Product Hits to ProductPage (bfoster, mattmann)
+
+* OODT-107 Typo identified in filemgr-client usage statement (Rishi Verma via mattmann)
+
+* OODT-58 update file manager to use Tika for mime-type detection (mattmann)
+
+* OODT-106 Logging properties for OPeNDAP ps doesn't include required .level suffix (mattmann)
+
+* OODT-105 Fix GeospatialCoverage in OPeNDAP ps (mattmann)
+
+* OODT-104 Allow const section to plumb information into profile elements (mattmann)
+
+* OODT-90 (cas-crawler patch) CAS-PGE returns success even if product file(s) failed to ingest (bfoster)
+
+* OODT-103 modify cas-common's cmd-line parser to throw a special OptionHelpException if no args 
+  are specified so it can be specifically trapped (bfoster)
+
+* OODT-192 cas-catalog should require a metadata flag for allowing Transaction updates (bfoster)
+
+* OODT-95 cas-catalog throws exceptions with blank messages (bfoster)
+
+* OODT-98 Resource Manager TestXmlQueueRepository test fails on some computers because 
+ <hashmap>.keySet() order is undefined (bfoster, mattmann)
+
+* OODT-97 Allow for unsorted paging across all catalogs to give option of lowering heap footprint (bfoster)
+
+* OODT-96 cas-catalog query parser fails when bucketNames are given (bfoster)
+
+* OODT-94 DataSourceIndex doesn't filter it's query to the bucket names provided in the QueryExpression (bfoster)
+
+* OODT-93 Spring XML resource classpaths are still set to /gov/nasa/jpl... and commons classpaths were not updates to remove 'cas' (bfoster)
+
+* OODT-91 cas-commons command-line help for a given arguments (bfoster)
+
+* OODT-89 (cas-pushpull patch) Synchonize OODT-CAS components, which depend on one another, on a particular Apache-Tika version (bfoster)
+
+* OODT-88 mvn eclipse:eclipse fails to merge resources (bfoster)
+
+* OODT-89 (cas-metadata patch) Synchonize OODT-CAS components, which depend on one another, on a particular Apache-Tika version (bfoster)
+
+* OODT-87 Add date roll dynamic replacement fuction to PathUtils (bfoster)
+
+* OODT-63 Use hard coded version numbers in shared component POMs so that MVN install works (bfoster)
+
+* OODT-85 XML configurator for opendap crashes on null pointer exceptions for some datasets (Victor Hwang via mattmann)
+
+* OODT-78 Ability for Resource Manager to dynamically add/remove nodes and modify queues at run-time (bfoster)
+
+* OODT-79 LRUScheduler removes a job from the JobQueue, but adds it back if can't schedule it, which (in the 
+  JobStack impl) causes JobRepo to create duplicate copies of the same JobSpec with different JobIds (bfoster)
+
+* OODT-77 Make resource manager Queue aware (bfoster)
+
+* OODT-80 Create Cached JobRepository for cas-resource (bfoster)
+
+* OODT-82 Make resource manager's node ip addresses envReplace-able (bfoster)
+
+* OODT-83 the artifactid for pushpull should change to cas-pushpull (Faranak Davoodi via mattmann)
+
+* OODT-76 Commons TimeEventWeightedHash throws a StackOverthrow Error when epsilon is large and event duration is small (bfoster)
+
+* OODT-9 Create a generic OpenDAP profile server (mattmann, Victor Hwang, smcclees)
+
+* OODT-67 All Loggers should be "static final" (bfoster)
+
+* OODT-66 Allow Filemgr XML-RPC connection retries and retry interval to be configurable (bfoster)
+
+* OODT-62 DateTimeVersioner fails on + side of the GMT line (Thomas Bennett via mattmann)
+
+* OODT-57 LuceneCatalog.getNumHits() doesn't properly translate the 
+  given Query object into the equivalent Lucene query (Gabe Resneck via mattmann)
+
+
+
+Release 0.1-incubating 
+--------------------------------------------
+Release Date: 0ct 31, 2010
+
+* OODT-56 Web Grid config contains old caltech licensing header (woollard)
+
+* OODT-55 Latest Tika 0.8-SNAPSHOT broke pushpull (mattmann)
+
+* OODT-51 Workflow unit test fails due to hsql not parsing the apache header correctly (woollard)
+
+* OODT-49 Basic user guide for PushPull (mattmann)
+
+* OODT-22 remove pushpull's jvftp dependency (mattmann)
+
+* OODT-47 Web-grid admin pages reference jpl.eda instead of org.apache.oodt (mattmann)
+
+* OODT-46 XMLPS mapping file doesn't declare XML at top of conf file (mattmann)
+
+* OODT-48 WildcardExpression in XMLPS generates incorrect SQL (mattmann)
+
+* OODT-44 doesn't build in JDK5 because of stringPropertyNames() in 
+  cas/workflow/structs/TaskJobInput.java (mattmann, davekale)
+
+* OODT-42 Fix CAS-Catalog to work in apache and pull over new changes 
+  since apache port (bfoster)
+
+* OODT-3 Update source code to use ASL headers and add NOTICE, etc. 
+  (smcclees, ahart, woollard, mattmann, kelly, pramirez)
+
+* OODT-38 Removed RAT from default build process. Use "mvn -P audit ..." to run RAT (pramirez)
+
+* OODT-40 DataSourceCatalogFactory default validation layer class is incorrect (pramirez via mattmann)
+
+* OODT-39 LuceneCatalogFactory default validation layer class is incorrect (pramirez via mattmann)
+
+* OODT-15 One trunk for all OODT components with top level build (mattmann, bfoster, kelly, woollard)
+
+* OODT-30 updated "grid" svn:ignore property to ignore target folder (David Kale via mattmann)
+
+* OODT-29 Import (ERNE) XMLPS component (David Kale, ahart, woollard, mattmann)
+
+* OODT-27 Import Web Grid component (David Kale, mattmann)
+
+* OODT-26 Typo identified in basic user's guide (Rishi Verma via mattmann)
+
+* OODT-16 OODT website (kelly)
+
+* OODT-24 Fmprod webapp currently depended on the toXML method of the Metadata object 
+  in cas-metadata, which has been removed... (woollard)
+
+* OODT-23 remove pushpull's javamail dependency (mattmann)
+
+* OODT-20 Upgrade oodt-profile's jena dependency to more recent version (kelly)
+
+* OODT-19 Metadata should not use a GPL-licensed XML parser (mattmann)
+
+* OODT-7 Curator adds escaped sequenced spaces when reading extractorBinPath 
+  tag from extractor config files (joshuaga via mattmann)
+
+* OODT-21 Remove jersey dependency from curator and replace with Apache CXF (mattmann)
+
+* OODT-18 Convert curator to use Apache commons rather than jTidy (mattmann)
+
+* OODT-16 - Remove JPL look+feel and web references, as well as dependency on private JPL M2 
+  repository; add relocation tags and disclaimer of Apache Incubation status (kelly)
+
+* OODT-14 User guide pre-requisite to checkout and install oodt-core before attempting to 
+   build cas-filemgr (Cameron Goodale via mattmann)
+
+* OODT-4 - Merge cas-commons and edm-commons (mattmann)
+
+* OODT-8 - grid-product/pom.xml references tika ver. 0.2-SNAPSHOT, which no longer exists (David Kale via mattmann)
+
+* OODT-2 - Import CAS components into OODT SVN (mattmann, joes)
+
+
diff --git a/0.8.1-rc1/HEADER.txt b/0.8.1-rc1/HEADER.txt
new file mode 100644
index 0000000..8c563ab
--- /dev/null
+++ b/0.8.1-rc1/HEADER.txt
@@ -0,0 +1,16 @@
+/**
+ * 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.
+ */
diff --git a/0.8.1-rc1/KEYS b/0.8.1-rc1/KEYS
new file mode 100644
index 0000000..d3856f9
--- /dev/null
+++ b/0.8.1-rc1/KEYS
@@ -0,0 +1,345 @@
+This file contains the PGP keys of various developers.
+Please don't use them for email unless you have to. Their main
+purpose is code signing.
+
+Users:
+    pgp < KEYS
+    gpg --import KEYS
+
+Developers: 
+    pgp -kxa <your name>   # and append to KEYS (this file)
+    (pgpk -ll <your name> && pgpk -xa <your name>) >> KEYS
+    (gpg --list-sigs <your name> && gpg --armor --export <your name>) >> KEYS
+
+----
+
+
+pub   1024D/B876884A 2007-12-24
+uid                  Chris Mattmann (CODE SIGNING KEY) <mattmann@apache.org>
+sig 3        B876884A 2007-12-24  Chris Mattmann (CODE SIGNING KEY) <mattmann@apache.org>
+sub   2048g/D3B4F350 2007-12-24
+sig          B876884A 2007-12-24  Chris Mattmann (CODE SIGNING KEY) <mattmann@apache.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.8 (Darwin)
+
+mQGiBEdvL9QRBACuaV06by+pxZHXIxBsfAFYJk7XJgsqR23m5ClCDPusMeaI4XGB
+eU8Nw4iVwgG3p5VLWLXeMIm/KPz3pmxiNyEP/dHoDxOPR+hAqlP5v03D1iK19H7q
+46BIecIwo8q0ei70fBLvMQN+apIFlvYDqVCTm1lxoCQafagqd9p2JtTf+wCg70yM
+nGtrejB+ZTTcb08f7SAHsLED/11vIdcxViN3u+3klhbb99bd/g9KvCU/I/7+MDx1
+3zrSvJV2b2wrxabUJ1Oxsb4/4BXq8A1FyhC1h/d2PsawqiY0GZ02cucbzEmdXH51
+UnrRLM9/txtZ2b7V6YkDmPf0k6rD0SjqAAy1ERekEVUOxnY4sPGmJoyac4j9+pO9
+1vH/A/9LRoJlPTfv/mFYty6/Egckhv48YoRUBo1dNh6IPQY0oVpAFbcXc3GiTyCu
+5iQp7utxP7hoJTUM2Hn5tF9D7IniRC9wsrcW8Gi/f82O4HlmyV4+Tt75nWx018oI
+ObGmwitT27EkOnFcQc9F+Q53nKr+a22SBbpfffF9Xdbkw7V73bQ3Q2hyaXMgTWF0
+dG1hbm4gKENPREUgU0lHTklORyBLRVkpIDxtYXR0bWFubkBhcGFjaGUub3JnPohg
+BBMRAgAgBQJHby/UAhsDBgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQcPCcxrh2
+iEr8KwCffMIKMu3TBrGZVu1BPLbMBhjsrl8AoI15rg+tzYZZmZJD6tDS40klTsVA
+uQINBEdvL9QQCAClHjwXMu38iDR3nvbYkWmcz5rfBFvDm/KVQGLnnY96C1r890Ir
+cHxAlSpbGb6qPi5n27v87LoS2bYEitqCUUwB7AQLOgqmLvqMJ4qp5HUfTQ/wH9Br
+wK2LX1oGFJXH14lbZ7xW36n9A/JtXHY8vGz3GuDvKYqbdOCFo8fBLwotdFOHhNYy
+bBYS1G4gtmemXwzH8kcuoIW6LuoRNxluHi1tJGFC1F1uBoxKir7F7BC38DDNvhak
+dSJpm3WxFkEEkIUyIERVGVRoFzLlk72W0R3kZVvnXbtgPklTg/2Sy13Gb+MzTBYt
+5TF841neM/kHdgt45EgBhchHN3Ys3ljabihbAAMFB/4ke4Xe573V78UR/WTMUzfw
+pIysMUzEjNKqOfnAoNnR4WDDca4MwIUl62QqGTRrWZxTD8fAGYxc+m0qmygGKtYq
+LUYB5N/pLGu1sg2j23G8aBKthiCCE+jOr3uebU/j0BTzN/BwXCqIGogELFlPC5Tj
+Hr6c8LpkRFIOjVfuYB2TV4o2RfSFzrSFHCbrU82ojxhYSwyqDGAdD6EGtbbqaEMX
+tGZzHaMVm2gDeV9W2veurxOulgndNg2+FXvgUlOa+KZ2J2DxNBcJv1uBtDAWDyR9
+dTgTbK62ZnSjsnRYbgf0HdA+kW9n9XBMEHwgYk0q+doOWUOQFqC84TgrrhyDd1XZ
+iEkEGBECAAkFAkdvL9QCGwwACgkQcPCcxrh2iEplXwCgraY3ELlDStqpJDSUzVsN
+rGuNiwsAoKz92ycEjcMnoLnX8AaPADdo1m/P
+=zEfO
+-----END PGP PUBLIC KEY BLOCK-----
+
+
+pub   4096R/F9D98BFA 2010-04-16
+uid                  Sean Colin-Patrick Kelly (CODE SIGNING KEY) <kelly@apache.org>
+sig 3        F9D98BFA 2010-04-16  Sean Colin-Patrick Kelly (CODE SIGNING KEY) <kelly@apache.org>
+sub   4096R/AC17FFD8 2010-04-16
+sig          F9D98BFA 2010-04-16  Sean Colin-Patrick Kelly (CODE SIGNING KEY) <kelly@apache.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG/MacGPG2 v2.0.14 (Darwin)
+
+mQINBEvImTIBEADICdyOLBPd1Wttdh9+hhX8DSbHHWOz3gtSfxnIWw+4BWqAvPo+
+oRFSd563gLJdJ/bpjfrhj4wQUMLAwmam1KpOJBbI2yBsgkyRkUalDMkq8QqxMJ7b
+AMCwdVoG507B2c+gzcMCWhIfXXMVId+Cc7c+K+ZGnG0F+SH87hLGD15E0tby2blm
+XHKRgiSjmqCPWjPdZpMrgcjjIpCIGaJ/vAr9CUErB3oi/BD+2WzzS1y4fy6kimuR
+3U3HQ1OmGhoNjTh0+eIH/dDsxeLxzYv5+xRAJXYPQRrG1QzWJleGBqAUYaJV+ctY
+L63jEjY4U8AIl5wzEuhq8qzS0hBT7BjK4ffuLsS6QbYRjmFJUAqxYbYOVmoAfsSw
+y8D38Wja1QM4QOvs9RxRQfn1NahpqAFQwI8L7cxGgLXSXX81OzWYabsjy7E/2pn/
+KxJlG9faShLelO2IBdUd/mUmxyUHc9rmYevStGhfKxeFaMXuGXB32n5WlrpizeTU
+SyALoYhSn6uNfg5DD1YwtoPEPgff5YvONy1os/kU+HXNY++9SfEhZW4kp505Q432
+TrEvs5XtdEyJmAFWdqgaWUpHstL3K9kDtmx4BdKVSguFA+NlkaBmIKFl8JZeopcx
+yfn+sB0SEaMIhCSvWMzI7LBF4Mk/3ZxP0iY0S9i8K1Dm+K+rg0dXpNYfvwARAQAB
+tD5TZWFuIENvbGluLVBhdHJpY2sgS2VsbHkgKENPREUgU0lHTklORyBLRVkpIDxr
+ZWxseUBhcGFjaGUub3JnPokCNwQTAQoAIQUCS8iZMgIbAwULCQgHAwUVCgkICwUW
+AgMBAAIeAQIXgAAKCRAXC2V++dmL+te7D/9Atq2uIWOYL5bLQG8zE18Y4Tw4vBPu
+7zFTqRTrIF+GKnRBi0yS//p5suC/8L7nYEeDit4EX69munzKKuDwYZr6aBfS8VH7
+aspN1HZwcq+R7oxuCOfl/GXzvhWwlSy66nPtI2VbwF/Csag/oS1/YRaGawDoilb/
++BSP69Lpw6m07qlKr79/zUlDpNryU3VyioTyAnI8tpKh4jV71LnZolVdbgWTBQyE
+xBCt7YnK0hcmo/efEd+4ziVQAZb8wSK6JzLxI6Q+K796XbvqSN2P6+vmnX5QjjLo
+qXK2C/WJQmpJWOQVi8NLPYTAnlq2rdmwwsdqXCWQVM7QQgQnf91vma8/mH++fGIC
+6clu9B2zLP9ugaMu0H9xgb3uAURuxisGpOuM8HA/cAfH39rGf5dlIjT2/1K77HZk
+rcrgW+kySAKTz3c7bEP+BNK8yEYKoSr+IavxY+SHHsPsVwvZEt7Hpa2GkvJMTIUw
+lTVU+IbRO3xz3iygc5SLGacdbR2V+iUIBCJwZs7Llwt9dqoBts758FwjGqCkBbKH
+0zRiv/tdd4MgMunjlDhtqoLa1zckWw32H7uOg99ZkA2UnijdCL5fFmewPgDf5l/I
+Ck7qGJmPSWZJGdUklzZFfx4X8401TqeAf5l2cNyScy0Tx21P1D7tV7fK0Egl0oZr
+RpzXbnphviLEXbkCDQRLyJkyARAA7/AWqxv38QORuU6hCem9VsGKw9jfkxzeW92h
++fmgfJOwfTsi1gLnA4tGUnPPWeQ4kpPfT1s1vJmdQbH8R0x+oqV+h4w5erUND22Y
+3n/cR6TckurGe/NEYRXrXo2M3CElEp/Fut2v2tqKannG2eGdH9tUaWpN3PBUY86z
+ma3ZLIMuJ2BJ0jtj8LuKV1ZDmrs5llsMpbK1GKYY3Jkc7G6JQgplPEBKVqdNwhoU
+Kp1SmlP90Bp58YetWFtA5VvXIhoWIH3SPCU2NyEF7eBnLwATkiIwqFUD2jwRIqyB
+SQKu//E7jQkMrlTSZfNWVt3qNTqfB42ovDJ/sw5xrrfTe7wFxTse6Xm3JnasXMKw
+yL6RyYz6+vmP5f/OFil3rY7+QUC2ykkGtu448MOQIQsDe+CilyuWY6FiTJVFGvE7
+F8tRb8ESBy7Kq/r9iqZdx/Qf8CTc+4m8Mpj+OP08O79PAmcUcrmWM9NRryOygHx5
+pVJY2PPkKb979RWco8StZK+DmCCNUb75vZ/SYooK6J0tZkYvBaGxQKZzRpjYNOZf
+wMo7lD+hvXOulaDTb6M3kKsrpnfZ6JG3UU2amfHf9fo7brxBy04vwUolpxj0/OEK
+6CJnX23XktPqVSMBd2WDVudh/m+jOZOF9wcWxYT3WQwXUyUQjexEZsM7eo90gQ5f
+BtkKLDUAEQEAAYkCHwQYAQoACQUCS8iZMgIbDAAKCRAXC2V++dmL+l5+EAC/pQXE
+JdKWYM5q9y8piYctWCCQO6DHNj1iY3oZ0MDpd7ZX9K5Y59VeA77JulkEokPMVwXk
+P0nfIoheORXGMd7psHcOcJUSPGSgXxKztx8gzIA0SVnDnCpwdqh2hCtmR8rUW8Ve
+qnSLoPAODA1e9wP8xcUPnKu65+l9FOmO6/Fi1Caeh3uRSJkObGPj3L9V3I4CjZ2W
+7bttRBdHM3UKhJfCpGntiF2A9lf9rMe79dnQhOz0+yX9wU8f58ZBPydgihgDY2Ky
+mp0ENZsG/PbTwfUPNyR4VKEh31Qs1vdbqrUYoBYB/ikARy1Qw3+Xqji/yA5vkBTH
+qthwYQxTAtLslrl3lP5KtNX+8kJg1ok0O/SuSTKoO9RkaKUtuMmU87JTnEZPpsw9
+ZHgWLAIHhGlOe4LunhcGNJNDZCaDI0i/H8lA3eWwZFJpes6l17cWz+88r32T5cOW
+tjZmC73Rpo5+6al5Eae67X7ilT0iFIyJy1W0caZZL785e72Tee415rpsnPp7OpU/
+6CYwZ3WpA9EjsSqHsZRwQNV+qSob59HJ8J5x0Rcs8bn+uI9lnE++vFFU0PfcM9uY
+wubRjONWRytauv9VTLHSFcYG0WTFt8wFNY585WyvZXtV6zwZ1EIt6L2WgLGJPx2i
+sRO6MhTu8oxGJTwZcP0kcpKlw75OybZxKLj+NA==
+=5uzi
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub   4096R/FF5B0BD5 2010-10-18
+uid                  David Woollard (CODE SIGNING KEY) <woollard@apache.org>
+sig 3        FF5B0BD5 2010-10-18  David Woollard (CODE SIGNING KEY) <woollard@apache.org>
+sub   4096R/0996746E 2010-10-18
+sig          FF5B0BD5 2010-10-18  David Woollard (CODE SIGNING KEY) <woollard@apache.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.11 (Darwin)
+
+mQINBEy8kp8BEAC7aWBPvaoAbSy6boQpfbaBCzEZEZLAHPyLTR8M29Z42tdDi4Hn
+WKDb8a6IBccH1vYxM4y6S8amXWXlBk+ncUyEIKlA1+f0m3vPPVtdVAkSZhK5EcJ1
+qJ8Y4uxWjArwnZ/MgP76yyRNlHk9eKw23KL5d0ayTL+aI/P6TBHZ+VrwAXidNZv1
+ZUkvUcwFd7rDuDt3HAP2pir/wP7M8rfw4To1FlLDWVAts+pNTa+RgvMhWm5B20+q
+/w+BJSA93zEOoTYHEgne5CwWPUZ2qpa//uPVnJpL8o8n8rgBXbs/qsFh3DUcnohY
+jMVeoFcrWrdkTEvf4oq8uH54jYqZ/S3TMyWm4Ixi0p9Y2FlM9QcDuv4vd9c59bBa
+okfX95SSjlvC2miFZUDqlmlYEAktE7UIdbo9xseLoU3PfHw45D6qX0LDHgNvCs8h
+7SBGN7z+qw9rlpYnNIq2uvwRS5aLX+IUShwhUYfvl7bV+UYiknfPMvEXfJnHKgZD
+5w43Z7zoloJukkjtTS00/frela7cQdK9M3YJAbPeyj1eq63uKqn/Qhep7r3ed/CL
+yFjWJrn7uhl427bDyo+TTEqHIiEqSTURm7caVrx4L6q9OI9xH7Z+Kt+JTwYT33SS
+XxHyDZ49GEntDRBRR7QY8kPtJO2ZNmWs0+T2hS3UOO0GxJLa4LL+qx6e1wARAQAB
+tDdEYXZpZCBXb29sbGFyZCAoQ09ERSBTSUdOSU5HIEtFWSkgPHdvb2xsYXJkQGFw
+YWNoZS5vcmc+iQI0BBMBCgAeBQJMvJKfAhsDBQsJCAcDBRUKCQgLAhYCAh4BAheA
+AAoJEBGRFnn/WwvVhLYQAJ7GAmv7yyJVPTvq1yuhzPcwS+vzixXvnIFdvMpItL/o
+nNgZoI0anVcJAzQLcc8MpxxrvT+wulvJjvtwkW/UxK0Rky3nEa1NdVvScQ1NVVxM
+CKTHzDF9TEYe3ZxGnoOxJl6XKWPg9qNPP44Jyo1iPCp2CeHej55WUS0XGZwNI/X8
+P6y46CL9bGoY7kCgjY4Ic3pfhKgQfB10EdunoDUzVq9U2cX3AVLhE1p3Pw0S66wI
+XH21tYuJim/CPqL/9gxp6kyDy15E+1w75KV9QAZQyrgRSstITPhjVm8aR6mfuAsq
+1OwNWso2sQDlXORMI7ZHUwD8EbPNvrPytWV4CJ/7lSXBEgOPyvLbHJGL5gTwmCnx
+Nxyc4pjTIuCxp09YF1JkO6jDbCAK3MbV8KguK2N+n0Tu8BDU2o8yvbSqTwTSWahc
+X8DmatzdUBM2jnRmDfc29Sw3KCTVE6e/cG4qAurjcSD4eDG+OnHcHkXrR1txeIa1
+js9CnkC05ntKIC242SiW1DFSuZLEmjdf0DXg/pokyZC4uL9QS6C1lqSEil/VN97c
+bLqOB91qSO6ag5x6MbMprIEi2gjcsaKWS+I5k+pyiOXv8QamQLTpVbVzjxBtLIB+
+bjN/T2dCOBL6jHeIBJgmAzV00qxiqC/GDn2ReECYM5lGSp6buKLqsgutkspaoZs9
+uQINBEy8kp8BEADwX1KYoW71OA94CG7auevZX9Cj+nLKVuYDE+eaN34NCWkc3+n5
+aONgq/bbRkxzcDdZ3QzJFeV3j9q4F9BL1Zpo52eDu2emMzXaAWGOrZuv5tekMVCy
+Ilthnn/06qojSyqpm9UPPlj5mTsJpQWtWQffzTpj30YNgzH8S9C7wUzF0MKKNfa0
+PuU+K9em8JUI8/fUSp3FO7U0GE/uRd3g4nAP2I5tmG6p2yaXX7ey7kvief/Vyhv5
+GkMXEHze45URmfQxD6t/CFOGdaKQCNpV+sINyb3ZdQO1B1qyIaVA9YuSxWABfRRo
+hPU8/LhNVdViNBo6Vzz6cZQir9U/i4NWxtsvo9FyrAfBKn2hE5gD6PP+VZyKhTus
+fW5bcp8KnIM1PBG598Iz+XtMJzIKnivLNNKMvhTg/mPXUx+vCCen82k6IUNIpXWj
+biaZs3dQqSDK7L4LDBHuNxEl1NHffExyQMTx+4YU5fhiqnEgfsmM8n4cTbDL9sQA
+0fviUhrMeFOyKGhcizAAC/yvG7f7yZ8Go8/YHLEBn0V6pWpuCvsqH4U/HE/dHEKx
+0ns/ePgVnJ79QIea7eXZhKN3G3hmJsik0DMsxZStLtk4Pj1clwES+uzm0PttnWPE
+QDTkUlVgIEAyXlY0VGBdFnUjUEihZ9kVWlz7FkHlNanp2LRl8LNR8ycJwwARAQAB
+iQIfBBgBCgAJBQJMvJKfAhsMAAoJEBGRFnn/WwvV+XEP/A2tYJN9u+PEe5OeHU0u
+0+Bpje4E7lmUSj+HzEwZsoVZVw/9gaBAOwIgXy8M8Yr81GAKDfOZk8VncgXewSu1
+oap4tjkykH15lsQVAkOOfwYGvraeHt3unuouhhJIZb7Cb30h0XCneM3/JYabLTIZ
+sFcE+L2b1yNBK6SjlipTx+G5nljTssTczk12Gy9u+GPz2ySX6YXJy+Ywpkyh0IE0
+UWYsnlU9n2NLxmxF0yEf/wk93iuUmguDAaHRiSPrYsWDkXFhDAy7SA1zl1aE+k2O
+8fGDPL6I9bR0a7HL6s5dlUPcFF5NZPfQ6Xd/LngsctVXZZDz0q3e72h6n68FC8VQ
+THGXADwMooOYH55it52TkGX7zLj5HY3QRTFxOdXk/D2f02xncqB3q3E8lkNtfdEa
+HP+LlPDJYqeDBXXT+k7BEMqo0e0uleZl3caADC4YMSIsWXPNEhK5AfyG8TCvLIui
+mvVjf/yeaDFfcX+mvQbSY41ZEnjUxlYlJFY4YX6GnjwvApK1RZFLWCzWIP/Kiica
+jzlDnFVMDRQY2kiqz2r/gOOWe8+c4Ztqy28BxDhPB0UZCqeGQnmlewKRiW4WuBnT
+YAhPjzaghVUv7B0fANq6XxvJCSQ5w+MLmh1fGFYtBHDO/HtMW7TekryUH+4YO6to
+O0L6LH00gHOgmcXsM1UUlPdr
+=hxbO
+-----END PGP PUBLIC KEY BLOCK-----
+pub   4096R/2C47D568 2011-01-18
+uid                  Paul Michael Ramirez (CODE SIGNING KEY) <pramirez@apache.org>
+sig 3        2C47D568 2011-01-18  Paul Michael Ramirez (CODE SIGNING KEY) <pramirez@apache.org>
+sub   4096R/62C7C4E7 2011-01-18
+sig          2C47D568 2011-01-18  Paul Michael Ramirez (CODE SIGNING KEY) <pramirez@apache.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.0.16 (FreeBSD)
+
+mQINBE01H/QBEAC9dDTLoaK/m1x9yKB+GC8iD2kdWKl8eSsn5jaNZYNpO/FTzaEC
+qtq1nu8FyWI5SMmIact6evEeEC5RqEHf/QgcoDOV8oum2OpcX0pKSNoAKUqm+4aB
+vWLkLS5X4R8eLWcrkDOpPUeCsDgeRaZw3clmh4vt9er5/YkCAJYdthmuEBkgaEM2
+u+Uf5e0glyWIbvX+BxdGxDGDyzM/QJzIOqwGI6fHxGFZoVCtw+PK/gLqDsdg2c7J
+vvaRSzyPPKsExAS9VcbgBt+XotFMNWQu65CWz/CuK6YCdfDxi3KiqBSBHbi8nwZm
+NJrKJKoahsfY55dflMrcDAWCgoB3eN/ra/pBFBMQNYMG5usd6ZeleYZBLe2jUbx7
+W4YWj3rnh+8trnVodAaepugQGuHXIyCpUJ2I+W0EdWTkKf/vgwuBJSCypJ6eraBD
+M7gYHAyJ9f+Q3SCslQGYoINmdkugOaV7vOGeFLURVkBJWVTCVri4Pq4kMy+E/BXD
+7Pu0xocbaWmTdbWqiQVXXWodl7fgQrQQ+iSEOOSswNwsITbfHqNDyQzhhGoI81uk
+t4YukxjUF2qawnCmSLJGnBiX+N3xLKmAWA8wAkP6YMhCgre0jeoCW9KVp3Y6r09S
+7omqb169XVz80SDqZ2PA7LyeEdYPE3MTg3P421QveFzMnISdE/kHUtHkSQARAQAB
+tD1QYXVsIE1pY2hhZWwgUmFtaXJleiAoQ09ERSBTSUdOSU5HIEtFWSkgPHByYW1p
+cmV6QGFwYWNoZS5vcmc+iQI3BBMBCgAhBQJNNR/0AhsDBQsJCAcDBRUKCQgLBRYC
+AwEAAh4BAheAAAoJEKXbwBgsR9VooCoQALKwFrjXNQANsDjVsb0FydTcEbqd2fAQ
+tByCTSBAfFNvvsTMvaJHTBfd6F6eU+dZQIUPlWJ5Bx/Vw55bzQ2GZ+igaPpJFG/z
+jlNbqmkIacxpeSfBqZ3CGtsKP3uxbAfRC7bt9HG1G15tFzp45bgAAC4ISlq66jIu
+NBuPjeYbEX+uZzMXoVqzvOPdSJis0qteAe7FuZLay+3JhGOGxm8iU1/9UZkP0FQK
+fneqsL/thCYj1KIIr74y+r7vjvNnoHULD/+zaF0DBZY1QpldONtJn7g4Yhonq4om
+gtlU6mOAgpvhZ9HnjySpcl8XtasWebx4ZUZdqQqeBrCLZet30xFnJhqt1AQwC6PY
+/3TQ0xQkNhV1YJI6V0Xrw9zJ8EosYRiz1bZDCqzLUj9Kvzh9gLJ8fYNVDPwUF4U7
+Mw7WdaK73rlCOrqcdGf13P7vQJTYHB6mCkpY5Qu9QejE2eE3Vrd5k6ktwWFkFqu9
+6i40zya2vs2++CM+R7VuEGdXpESvefVKpb0k5coZYZ5rGSye+BkbM7Qo/IvvUtxr
+ftyscUVuQ70/YL71UB2wk83dcYWtj1pz9fg8oqRGrFwiPWmFewpg7kWCUKomAqn4
+0XK1wG4W23AzKNar4Pn0wqQtKkqTTOmnglGCevl3etpx4VCm1NUnngsutC73Dz5E
+kHmuEKJTZfh6uQINBE01H/QBEAC03btD8DXIIEYCxDJG3G9G5FDi6fYh1wzxmyjV
+GTv6yFRnWHnS+amfWPW7F8zbXhf0OUure+2jj5TeGMGVLkNb1ys88NWwBczS8zeF
+4l8Kx/Jc3SSY/J71oGA2TJaxLs5ya/J9qzhk/9vJyetaGUSTTs+shkQqh4Hqv4WR
+XTpumbnc0rLvj7edm343NgJvItAlPjH2b4bCFtUjgI9BRSwe5yPJaEmUZI4C2C7O
+vk5SMLJC9WW9+7gs17Nh4af5wLNldUJPaLYmerKmA1mXWTAoagELWQufelqwtYVn
+NHdaU9XbUDFrMMr+O0PcJhyDQ2TDBlUNteeMR+O7LLDPc6A7O5tjNW1EZpjlQZxI
+izC+nSkPYjr7szwz5ImXywwsBGN3KTejLkPlOAWdUjt0kUoxhsb1pmJ0dsHlWu04
+yWaixl+c8sICFnKeCAFrU2sqMyxMyUOxFi/Gf4uafKEHklWWc/RD4e3hQkeF9TMW
+tV18nIjszNGWNXjUIPHmArZTwQoJl+vXe2E8smALnjmWmkNJukaYzvX0yr0YOO8l
+C0RmZhf5mb40ZE8nhSoVXvQJOsdTC47lI1FggYXCiIXa9guUt9FJhz3yaGUbAQfn
+jKhAa/kvZ1t31bNBlnl5MzV6/4P7ioEaxH1EHdrnH8vJ6HJsk0a850cJa9GErX8m
+WxUdrQARAQABiQIfBBgBCgAJBQJNNR/0AhsMAAoJEKXbwBgsR9Vo7h0QALfXu13c
+UvWP+g7uV9fEc/923FKsUDJqDXx++mVEphmiOG1d17HSP7l3naA3+WtzCBjobHpE
+vlKex4lsAefGnZt+3GnpCAwAXxPS56Z0D9gOyxNkqSOA8BL/cJ7clcdLFzivCzQw
+fpouBxn8Yd3SR9K8KNggsSwjPLiat0ZvPlml4YlGskGJVz8u7ZmYVpXKW9Hh3tlL
+Ze4Vpwlu1Bb02T50GdvTP3NDXKcjV7HXywz0LqGzI3BZhGX/VMnhbmzWjxHwkCFN
+aFD/D66pvakaMElSPeBJEzK8G6OWlhCfQzRFjUv3eDYt/7Uc0qkHpc59VAvi284v
+EMqjZm5m7IZ9hC5fboxUKkylMg1vKreL33qNpk0cy5zoRCcEselQ/gr7dN4/kmp0
+lDqIDqaVyCJBo+97eS2J1FeW5gCAXpAiWNSgq+LWPbgWQ5kva1gtbECvnXNxeqc2
+2mxjM5FHyqNEaOrIUxE4VapQFSXQXPLnnTr1SHL700rW+RFKVWW/8o/m0D6zOn8K
+QDnKDXRHvjq5l7ClpKRgsg2YWKMcsoHXgmB4QhwLZ5FyQzU9gXgCaUZnJ1dRbUzM
+7i4z6bYGWC517oJPPJz+3NbghByn3KM5lvNO261GMGrMcxEa3KNB4S8NES0DcRGq
+CizdyPOVKDT7Y7Gx7UhKzK2MNG6RvB0UZWl6
+=D1qo
+-----END PGP PUBLIC KEY BLOCK-----
+pub   4096R/80EF652D 2011-06-08
+uid                  Andrew Hart (CODE SIGNING KEY) <ahart@apache.org>
+sig 3        80EF652D 2011-06-08  Andrew Hart (CODE SIGNING KEY) <ahart@apache.org>
+sub   4096R/D4B0286D 2011-06-08
+sig          80EF652D 2011-06-08  Andrew Hart (CODE SIGNING KEY) <ahart@apache.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.0.17 (FreeBSD)
+
+mQINBE3u3zUBEADDkrLBvE1NQZ/0jrracXWXNcaDwNVhDLtLseB/0Y8PUEsj/HyC
+DoVyKpDjNseCVOE8A8JvuWJMZDRxDlpsLFIWX4TZpapnwUy3iRuehZBN+iSG184k
+iyv1nomFOyBsF7PcJlkgwvEX7GkTAvRFfYx1PNHZBWghirM22GMihMauH2y4E8Fo
+s6gJ+hsFeV96xzJATWmhWEO4CJDTFiqdwlGBu85UOeDSkHu0qegrmCj7WuJpHD6t
+IIvmvLJH48+jF374u2Y9QZWGWzkWh91QBYHy8SA+UEcjkeZf7WEuGbrd1roVO+1q
+Wp0adCkzcqDTyRZZuSC3hmh+Rw6miRjcWjquKtET5v6HPMcvvnvcbbEVkpyrGgAR
+JMQMbZxIvJwP5i8e9T6kRzTyh4VAXoh2uidR2xSyF7pFoZu9KpDH99vv0R1h67R9
+uvfsjJuvnjIX5Gbg0T1haF4YseFLDPW3gA0sj366JvMQhVfqo1nvbfQaaVoAMExX
+4TO0j4++rvZKhovHRK1YdCbdxyP1iNmQqLGJjRMOLM1i88DG+/gWPDuPzOc0pyO5
+gbpTa3/Bc49QBJmqwroBnXquoBBbK+0fwhBa4KcIdmthiYpAzw21+F08hlU6R7ik
+G9jK3iaDxO/Wqx4Q25OytXGLsROEbg/kBJcDncSymAdpPq0ImO8pgtlA5wARAQAB
+tDFBbmRyZXcgSGFydCAoQ09ERSBTSUdOSU5HIEtFWSkgPGFoYXJ0QGFwYWNoZS5v
+cmc+iQI3BBMBCgAhBQJN7t81AhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJ
+EHGJcAiA72UtLFkP+wZioDcUoXuZAFbVdgoNI+oR6z/7OGq5Hj5WY/LMQaPJztM3
+kBtY4M7oEBIgz3N7EdTBwmCGLjZD0uMBXQYJxL9eL8exhzafHbMgzmcZvUIRt0H2
+nehzcAbZDHSxG9HM7VXCF5FuEOjVnqUgKeQZI1e3/RWZRjSeZ3vW0rh+DQf0pHQk
+7igBuEGORJH+YBRoLxp3obC0x3sMwv03djLB9oNDBhK0YZn3n7gNeGeYUrJ/7scx
+tLJpPlYMxBaUJIZRF3nEfk0M2UN4XF6Ayj1Ay7v6Hlb25UKJlgeuUz8BxrfW3X9Q
+3wJWNXuO1Q0JH5g5mHoT9AAk+aGAt62KUq885pLuKdigp4lEsYIm8jw9cQ6gRuAI
+8Nt4MwDn4Vura9Rdq8jZWtVeiWFDxD8HzoS0rDflnhc9QnF5GGr6YBU0dyc7akPT
+XGXVAZSShsXWUA82GGsBP+TuxdZblHZKFN53kOPXh7nmnTTbKz64SnNfO5ucgkGQ
+e9pyMcPGIk0/giX3aqW7TV1Dw2ZKdIjnXmF/CB3Yq2feifg+VtI0MaArx0gGLZiC
+9nHYKQz/YuyT+FgGXvj4zgn+l5K0ybDAtSJkfRXBdDrXsIG2joalmxxRIg1NdbbM
+yAp5UJIr67yBMt2c6dOzYycTiS5fWLeFrXSNXjwdKzWHPXvd2xT70Y1HaeZQuQIN
+BE3u3zUBEACw9COP560TW7zvRY9wmaZjk3wqobH+mXE+CT26VaDwoOpr9GT0JiHe
+sKc+/MbVyNJcIjupG++UoWIGu7LHtruPtsgDFBEIKJDPduaMiLiezAqoWOxnsth/
+/nvqcL6zBRvWWOxgjoqkCdIn4XivYpY9F1jXU5BEeEHUYZMlHn86oewfaGxX5htG
+eb8F4txxxxeGAcyn3AeFXT4UvgSIvtdf2jX4u28stjwTm4wvXKlGRy6bBOrfnfu0
+j7Wolhp5KRdJ0yHnFbaUbTeZ78nz0YXmj1vXVoFBpr/gZB1kuWiGyXGEltQkZw7+
+8App9KVEPSTOBJpyLAqMzu7it70oOZLEfMaa/vWhoCOnizs4DW7aJ8ik6gZ5pPaC
+kjpV8S3HFZeRwxslFCBrF47cL4BmleK4bUgNUP6NZpQqV90dt2e267nHBxhXJ0x+
+i/K9p2sfEp0FupptNi0xVMgJJctDSXpPpbr+FyWCwmzGuDf7wp5ixxfi3Vw0yunt
+XAIs+Di5O/nFDALV8TMoDbRLEgAtMI+geZVAYng9RXCf1xc2X0kO4QhJ/6YttV2D
+a5T9yPuBn1maOWY+WwbSKEOYC8dk0+HLE4Hyg6CI+g3AtqR7vN02m3oavgd4hwxT
+KaC75J95Vmky3WY7tlGcm5blJ68Wh8ZotlKaigKchThikCJdpExKtQARAQABiQIf
+BBgBCgAJBQJN7t81AhsMAAoJEHGJcAiA72Ut0OYP/AmhiJvQXH6mJSVQk2pQrfjV
+m/VK/wLcdKPK/gGq//NZzpNVeUOnz2KIzZhQ1VB/vjwkQiPS6lEMpiY6RKNusUEu
+maXWZaFuqq/BiOO6U4S6WUDehT+JxmtdcQ08FqUnWhGT4LtWSBSJ6y3PofKNwMJG
+gpuPrSgMuWKX8/LLMUdY6pr/gvlj1WgOu+6OrR8RaLGvFIbJqYN3cMMx6UbD4dlt
+0unBmewppj8ALF3zDSqxhfks24gvOS43ybMWeeapEy7BtyrNy+TObmbxqvP64QDh
+ZQDHx1PEGpJaO2og3/vdwWsFetVPION/EpJ/IkzJ3mI+UgkPcb/lJ5VvGyi0w+Rt
+vMvfvG/EMd6NzAfEEsR1hFCmhTaF+d5sp6xeKzFIpuc4NQMsQoU/fnDo72EEC7KD
+KC4lu3Gu+zSpTNWIxLP/3Ds4t7rBKXTRXEgnkZbiWc42h5DV8xOqF5gQQh79vEdG
+5zkgD3fQtUSQ/r8e1wgTqTZKZzcV6w3VB9UAskC6zUlo4QumE2VXVcxZOjbLhzHj
+wr2bWN6Yv2P8WfU8GvLcRrfnGumPoPXstHvVU/8oN82HkOl4JWWCZv14yO3G3tJS
+WFNwrLA6AujhiJgEHrqYbuq/2rJyW52C4/y8TwZlWiMfr1oGBEef8p6KEugRjxiG
+YDdbxIVQv3HKn/B7keII
+=ZNn9
+-----END PGP PUBLIC KEY BLOCK-----
+pub   4096R/783CE7BB 2014-12-19
+uid                  Tom Barber (CODE SIGNING KEY) <magicaltrout@apache.org>
+sig 3        783CE7BB 2014-12-19  Tom Barber (CODE SIGNING KEY) <magicaltrout@apache.org>
+sub   4096R/E0D420E1 2014-12-19
+sig          783CE7BB 2014-12-19  Tom Barber (CODE SIGNING KEY) <magicaltrout@apache.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1
+
+mQINBFSUCJUBEADdQ+oIicAHr7W+2hGJR/dVt0Yh6TuK8i6k4JQ3vU0aWbVDC/By
+jTERCvdDGM0xglgwLj06nM1+RVtR4zk+fki49asZInocJG2bWnFz5oe3QCnsKuao
+UeTETVGEM47HKaxAQq4w8v4Kcs/ZftaxV1L0F3yOof5HwvctSrVtfjS5fbi6qVzP
+u9NH1s6Bvj6TxUGzu5LzeS1xRQJWXkxLCtMovKh57uZ2FI6nyoRyVFEKMxw4cFzj
+b4Q/2iJUI6+5QlPRHTeP5NAaocGjTogt7Rkbk/CY5PUZnYT84sxLvKOhFOUnhLMt
+sHBX34Be0fSfhaNLCkIYANV25R+WwFSrgyGfaQCOs/SkybywhAVPRLQxwlIfyZnO
+RvY1w/4EuqpjAyC/K83Fg+4Mlx3mvjSTXtVyVlxQZXxKH2khunwMNWIkEnapBwg+
+jADYLrs3FvxdHASCEZfezpnlEKvlIhg6Week/K9LU2vr9BrYznTT2AuPQxOXIYh8
+Bn2KLIX6PHcV4FnEBo0Y/PUnDHRHmrZpP0LEFuABTtj7RCx+/rFeRMH3g+VJ3bKs
+lKqkI1cqs7fjNRSw+KSb8Ljt7HJNeT+n5a2V9eYgx5hG0GSPw3utXKXGYof+pbeG
+d3CBv1yOD0FqyLrv9TTN+d60ShDjIZPsfy2An2+2trwUAobPqT/+rN+OOwARAQAB
+tDdUb20gQmFyYmVyIChDT0RFIFNJR05JTkcgS0VZKSA8bWFnaWNhbHRyb3V0QGFw
+YWNoZS5vcmc+iQI4BBMBAgAiBQJUlAiVAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIe
+AQIXgAAKCRDYFnFxeDznuxfEEACrAZBU21yrWvPozj16iq1wXYkMMYtpWuaYWnA0
+CWUjYqux690UaczmA/52YRN+1MquI9cjGEOGi6ygThmlUeU5yIfB1p8+jiRXZhbv
+8vsYcW6VpyE8jotG/24WG1p7QMGntUhjYA/uhK9/uhsMF/eG3A2PGfJTJ7+g4Ziu
+8SA1KLKCs/bg3n0uvrysbQ6LQRP0Tp8h+ZSbGI7lSnBytcYEAzHbVidYTUDIMhdz
+fNSwNha4aCfd4MNtbJ1H5gK8kEry31Cv9bzGQ+5TqX/0+Uh23r2hzgnhRNO5ZEBO
+VS8MKceJ6EHxrkzm0/Uk54oe2BkMY3sN0YzjPgOQQdltIE4JHT3wePs0oM1cZ/Ih
+S2agn3Tsq9ZdW7IdJTy3ct4EPpTrYQZoD4q/ZRfGJfP6bQNMnqRYxDgoUZQAMw5r
+QauRz7mtx6aXvAgxIVeDpW0Uj+JW990MvSKaoq/Tit7x69IFj0LCvQ+1lqRN1+CC
+28Cjam2WQcoBbu5fF+RU4FfJA2IPe9xIF/ZrZiMgaBVvArgRj5iheigIN5QQmo23
+/cTNueidsqR0zTuge5nIz6fxBjsrMJAyAOKn5FCw9+gcACDIvHa2aLgs+cWQ0X61
+6ZSjYyLJTOjYOkaHN7+gb0w3j/7HywaZ7WHQPvBx/mgnncaz0gMJj+MKhSxxsKN4
+3N7Au7kCDQRUlAiVARAArZ9t4bWjrI+uYzlNWCYmQOT5Etq0cByrZRJjBianhakW
+r0E1cBSqtynume2bVtCHtOQzoT7vAlDm2IVjZasMD39U2OpaH2RjUguUUsTrzwyN
+3OA+cV/wpbHSoJZPFWzD+V3PpwLGK1FKGQLuegQ9byOMAjReOlqQXvLqU6EHB1nU
+bftkhNcifDCecNrfhLrCcmmY+hLnNZmYqRR5RLyzXF8KMPimysOdrzPMBQnFyq4o
+GPpqubn3TM56faYtRfB4O31Fc1NxIg64xZ9Dq39ROmpsr7ZAQxKol4Tc+CIshMxv
+w+Hc+Qyxj6ZpjAEy2bwgH7czp4MkRi6fwETaQqmYjWyglndVlOCqaR83EMuY6wzg
+SgXYSyI7lHXxRA3P+R9uOR9JseF/NxC2o1TXDKQ9Eyd2pMdZ9txd1182Y6sCD+Ji
+KxELdMZRXT+UhLP6SKjhYQjtTdi8Q9IF9LAl2beF3uTtzjqCsTgtCQ8r+QPY7obW
+z5ZI1qxTIVPaSeBayi22I6mU02QUMTMCmH1piXxsESqyMQ221nuDik0pUVC2exsk
+HnqC4/aVvJSnxLk1H/9dopzyeWp37IFQRH9WzyXc4tcqExx+fCaetPAe7oKOlwzj
+arzAwsOM5GG/bs+rpMB7g9wGaz8fl9onpCcuGReSUheethY1DakW8W5JEp6deZkA
+EQEAAYkCHwQYAQIACQUCVJQIlQIbDAAKCRDYFnFxeDznu6uRD/sFXFwP6PSEt0v8
+Y5h2VFPhcN2nt42+jSyzfY5XEzasuuYYsTPxKEPbZHl5By86i0vLJ1wvJnvoEfEy
+XwMyLLnw87RgsnkHL0NHGDJF7drQpbhIgSZfQV2hY1J3Az1PMWs7rI2tbKeQUmC1
+k7iyyzEyQnphTbRd7FEKYAFPynrmrlRPnG1zNRFYGC2S5VkxCOV/fwN2Vp8PXfo9
+P9Az4Q0tEuowNiW7Pp4KaHundIQtSMdZAM0bj5wRkw4Y96UYGD/huxvAi7MCgOgv
+NB8e656rSxigNiEJ9gOYOwH/6kM44g8BPtcLzeU4tDKzZdfHCxrXzxcBIVa3QZ69
+c7JUJTU89LScJm8rbHBUwQrrf47vSxs8pzUTpFTEoPaBnLD/WOXlPwiJyyOqSh+w
+kZqpC3Jn0aXx4hcmVFtmoaNsNehiJwAl2bX7gwcia6zey0Z1Kljr7N+ikHMhZLjA
+PS3BpMfEc/hcL9+vr74sa32zm9S4bFrd1xCGMv2hcoVWyI38OrFBvvK6uKTxVCPl
+mlgDkcdEboOoQNg5TpVXGnyop0dXICTfx2W/v+7Pq97efFlo7h3ODI7GtltHxqbs
+IGuODo8x0hnGrvAOZYb5BUL7/CRo9PMt91DLPOREFSMHVEsA12OnaTQ2hPZrVOcV
+HSTj1SAfoZ5erxSk3/eMd3H52/6jBg==
+=yBb7
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/0.8.1-rc1/LICENSE.txt b/0.8.1-rc1/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/0.8.1-rc1/LICENSE.txt
@@ -0,0 +1,202 @@
+
+                                 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.
diff --git a/0.8.1-rc1/NOTICE.txt b/0.8.1-rc1/NOTICE.txt
new file mode 100644
index 0000000..e7bfeff
--- /dev/null
+++ b/0.8.1-rc1/NOTICE.txt
@@ -0,0 +1,103 @@
+Apache OODT
+Copyright 2010-2015 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+This product includes the WebAppers Progress Bar, version 0.2, written by
+Ray Cheung. WebAppers Progress Bar is freely distributable under the terms 
+of the Creative Commons license. For details, see the WebAppers web site: 
+    http://www.webappers.com/progressBar/
+
+This product includes the Prototype JavaScript framework, version 1.5.0,
+written by Sam Stephenson. Prototype is freely distributable under the terms 
+of an MIT-style license. For details, see the Prototype web site: 
+    http://prototype.conio.net/
+
+This product includes the jQuery JavaScript Library, version 1.3.1, written
+by John Resig. jQuery is dually licensed under the MIT and GPL licenses, and
+is included in this software distribution under the MIT license. For details,
+see the jQuery web site: 
+    http://jquery.com/
+
+This product includes the jQuery UI, versions 1.2.2b2 and 1.5.3, written by 
+Paul Bakaus. The jQuery UI is dually licensed under the MIT and GPL licenses, 
+and is included in this software distribution under the MIT license. For 
+details, see the jQuery UI web site:
+    http://docs.jquery.com/UI
+
+This product includes the jQuery UI CSS Framework. The jQuery UI CSS 
+Framework is dually licensed under the MIT and GPL licenses, and is included 
+in this software distribution under the MIT license. For details, see the 
+jQuery UI web site:
+    http://jqueryui.com/about
+
+This product includes the jQuery Alert Dialogs Plugin, version 1.1, written
+by Cory S.N. LaViska for A Beautiful Site, LLC. The jQuery Alert Dialogs 
+Plugin is dually licensed under the MIT and GPL licenses, and is included in 
+this software distribution under the MIT license. For details, see the A
+Beautiful Site web site:
+    http://abeautifulsite.net/
+
+This product includes the jQuery PeriodicalUpdater Plugin, version 2.0, 
+written by Robert Fischer for Smokejumper IT and 360innovate. The jQuery
+PeriodicalUpdater Plugin is dually licensed under the MIT and GPL licenses, 
+and is included in this software distribution under the MIT license. For 
+details, see the following websites:
+     Robert Fischer (http://smokejumperit.com)
+     360innovate (http://www.360innovate.co.uk)
+
+This product includes the jQuery blockUI Plugin, version 2.15, written by
+M. Alsup. The jQuery blockUI Plugin is dually licensed under the MIT and 
+GPL licenses, and is included in this software distribution under the MIT 
+license. For details, see:
+     http://malsup.com/jquery/block/
+
+This product includes the jQuery Cookie Plugin, written by Klaus Hartl.
+The jQuery Cookie Plugin is dually licensed under the MIT and GPL licenses, 
+and is included in this software distribution under the MIT license.
+
+This product includes the jQuery Treeview Plugin, version 1.4, and the
+Async Treeview extension, version 0.1, written by Jörn Zaefferer. The 
+jQuery Treeview Plugin and Async Treeview are dually licensed under the MIT 
+and GPL licenses, and is included in this software distribution under the 
+MIT license. For details, see:
+     http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
+     http://docs.jquery.com/Plugins/Treeview
+ 
+This product includes the Dynamic Tree View Control, version 0.4.0, written
+by Martin Wendt. The Dynamic Tree View COntrol is licensed under the MIT
+license. For details, see:
+     http://dynatree.googlecode.com/
+
+This product utilizes using v1.3.4 of Doug Lea's java.util.concurrent.
+
+This product utilizes jsch version 0.1.42.
+
+------------------------------------------------------------------------------
+Copyright (c) 2002-2010 Atsuhiko Yamanaka, JCraft,Inc. 
+All rights reserved.
+
+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. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE 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.
diff --git a/0.8.1-rc1/README.md b/0.8.1-rc1/README.md
new file mode 100644
index 0000000..d090f5e
--- /dev/null
+++ b/0.8.1-rc1/README.md
@@ -0,0 +1,153 @@
+=============================================================
+ Welcome to Apache OODT  <http://oodt.apache.org/>
+=============================================================
+
+OODT is a grid middleware framework used on a number of successful projects at
+NASA's Jet Propulsion Laboratory/California Institute of Technology, and many
+other research institutions and universities, specifically those part of the:
+
+* National Cancer Institute's (NCI's) Early Detection Research Network (EDRN)
+  project - over 40+ institutions all performing research into discovering
+  biomarkers which are early indicators of disease.
+* NASA's Planetary Data System (PDS) - NASA's planetary data archive, a
+  repository and registry for all planetary data collected over the past 30+
+  years.
+* Various Earth Science data processing missions, including
+  Seawinds/QuickSCAT, the Orbiting Carbon Observatory, the NPP Sounder PEATE
+  project, and the Soil Moisture Active Passive (SMAP) mission.
+    
+OODT is a Top Level project of the Apache Software Foundation 
+<http://www.apache.org/>.
+
+Getting Started
+===============
+
+OODT is primarily written in Java, with some components available in Python.
+It requires Java 5 and uses the Maven 2 <http://maven.apache.org/> build
+system.  To build the Java components of OODT, use the following command in
+this directory:
+
+    mvn install
+
+For the Python components, see the "agility" subdirectory.
+
+Contributing
+============
+To contribute a patch, follow these instructions (note that installing
+[Hub](http://hub.github.com) is not strictly required, but is recommended).
+
+```
+0. Download and install hub.github.com
+1. File JIRA issue for your fix at https://issues.apache.org/jira/browse/OODT
+- you will get issue id OODT-xxx where xxx is the issue ID.
+2. git clone http://github.com/apache/oodt.git 
+3. cd oodt
+4. git checkout -b OODT-xxx
+5. edit files
+6. git status (make sure it shows what files you expected to edit)
+7. git add <files>
+8. git commit -m “fix for OODT-xxx contributed by <your username>”
+9. git fork
+10. git push -u <your git username> OODT-xxx
+11. git pull-request
+```
+
+
+License (see also LICENSE.txt)
+==============================
+
+Collective work: Copyright 2010-2012 The Apache Software Foundation.
+
+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.
+
+Apache OODT 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 licenses listed in the LICENSE.txt file.
+
+Export control
+==============
+
+This distribution includes cryptographic software.  The country in which you
+currently reside may have restrictions on the import, possession, use, and/or
+re-export to another country, of encryption software.  BEFORE using any
+encryption software, please check your country's laws, regulations and
+policies concerning the import, possession, or use, and re-export of
+encryption software, to see if this is permitted.  See
+<http://www.wassenaar.org/> for more information.
+
+The U.S.  Government Department of Commerce, Bureau of Industry and Security
+(BIS), has classified this software as Export Commodity Control Number (ECCN)
+5D002.C.1, which includes information security software using or performing
+cryptographic functions with asymmetric algorithms.  The form and manner of
+this Apache Software Foundation distribution makes it eligible for export
+under the License Exception ENC Technology Software Unrestricted (TSU)
+exception (see the BIS Export Administration Regulations, Section 740.13) for
+both object code and source code.
+
+The following provides more details on the included cryptographic software:
+
+    Apache OODT uses Apache Tika which uses the Bouncy Castle generic
+    encryption libraries for extracting text content and metadata from
+    encrypted PDF files.  See http://www.bouncycastle.org/ for more details on
+    Bouncy Castle.
+
+Documentation
+=============
+
+You can build a local copy of the OODT documentation including JavaDocs using
+the following Maven 2 command in the OODT source directory:
+
+    mvn site 
+
+You can then open the OODT Documentation in a web browser: 
+
+    ./target/site/index.html
+
+Note: all OODT source files are encoded with UTF-8.  You must set your
+MAVEN_OPTS environment variable to include "-Dfile.encoding=UTF-8" in order to
+properly generate the web site and other artifacts from source.
+
+Note: generating the documentation requires enormous amounts of memory.  More
+than likely you'll need to add to the MAVEN_OPTS environment variable in order
+to set the Java heap maximum size with "-Xmx512m" or larger before attempting
+to run "mvn site".
+
+Mailing Lists
+=============
+
+Discussion about OODT takes place on the following mailing lists:
+
+    dev@oodt.apache.org    - About using OODT and developing OODT
+
+Notification on all code changes are sent to the following mailing list:
+
+    commits@oodt.apache.org
+
+The mailing lists are open to anyone and publicly archived.
+
+You can subscribe the mailing lists by sending a message to
+<LIST>-subscribe@oodt.apache.org (for example
+dev-subscribe@oodt...).  To unsubscribe, send a message to
+<LIST>-unsubscribe@oodt.apache.org.  For more instructions, send a
+message to <LIST>-help@oodt.apache.org.
+
+Issue Tracker
+=============
+
+If you encounter errors in OODT or want to suggest an improvement or a new
+feature, please visit the OODT issue tracker at
+https://issues.apache.org/jira/browse/OODT.  There you can also find the
+latest information on known issues and recent bug fixes and enhancements.
diff --git a/0.8.1-rc1/agility/MANIFEST.in b/0.8.1-rc1/agility/MANIFEST.in
new file mode 100644
index 0000000..aba871f
--- /dev/null
+++ b/0.8.1-rc1/agility/MANIFEST.in
@@ -0,0 +1,2 @@
+include distribute_setup.py
+recursive-include docs *.txt
diff --git a/0.8.1-rc1/agility/README.txt b/0.8.1-rc1/agility/README.txt
new file mode 100644
index 0000000..c8c45a3
--- /dev/null
+++ b/0.8.1-rc1/agility/README.txt
@@ -0,0 +1,17 @@
+Agile OODT is a new version of `Object Oriented Data Technology`_.  It
+improves upon the previous version by being easier to develop, maintain, and
+extend; simpler to integrate by; and faster to use.
+
+.. This is licensed software; see the files NOTICE.txt and docs/LICENSE.txt.
+
+.. For installation instructions, see docs/INSTALL.txt.
+
+.. References:
+.. _`Object Oriented Data Technology`: http://oodt.apache.org/
+
+.. meta::
+    :keywords: OODT, data, object, OO, discovery, metadata,
+        transfer, transformation, query, search, retrieval
+    :description lang=en: Agile OODT, the nimble version of
+        Object Oriented Data Technology
+
diff --git a/0.8.1-rc1/agility/docs/HISTORY.txt b/0.8.1-rc1/agility/docs/HISTORY.txt
new file mode 100644
index 0000000..094256b
--- /dev/null
+++ b/0.8.1-rc1/agility/docs/HISTORY.txt
@@ -0,0 +1,21 @@
+Changelog
+=========
+
+What follows is a history of changes to this software.
+
+0.2 - Current
+-------------
+
+This is the current release of Agile OODT, representing its migration from the
+Apache Incubator to a full-fledged top-level Apache project.
+
+
+0.1-incubating - Initial Apache Release
+---------------------------------------
+
+This release marks the induction of Agile OODT into the Apache Software
+Foundation's Incubator_.
+
+
+.. References:
+.. _Incubator: http://incubator.apache.org/
\ No newline at end of file
diff --git a/0.8.1-rc1/agility/docs/INSTALL.txt b/0.8.1-rc1/agility/docs/INSTALL.txt
new file mode 100644
index 0000000..eaa074f
--- /dev/null
+++ b/0.8.1-rc1/agility/docs/INSTALL.txt
@@ -0,0 +1,91 @@
+Installation
+============
+
+What follows are the installation instructions for Agile OODT.
+
+
+Quick Instructions
+------------------
+
+As a user with administrative privileges, run either::
+
+    pip oodt
+
+or::
+
+    easy_install oodt
+
+depending on what's available on your system.  You're done!
+
+
+Full Instructions
+-----------------
+
+Agile OODT requires the Python_ programming language.  We recommend version 2.4
+or later.  As of this writing, 2.7 is the latest stable version.  If Python is
+not yet installed on your system, you can find binary and and source
+distributions from the Python website.
+
+To test if a correct version of Python is available on your system, run::
+
+    python -V
+    
+You should see output similar to::
+
+    Python 2.7
+    
+indicating the version of Python installed.  You may then proceed to install
+Agile OODT.
+
+By far the easiest, recommended, and encouraged way to install Agile OODT is
+either with Pip_ or EasyInstall_.  If your Python installation has either of
+these installers available to it, then one command is all you need to run in
+order to download, build, install, and generate command-line tools all in one
+go for all users on your system.  For Pip users, it's::
+
+    pip oodt
+
+And for EasyInstall users, it's::
+
+    easy_install oodt
+    
+Be sure to run that command as an administrative user.  For example, on Mac OS
+X and other Unix systems, you might need to run either of::
+
+    sudo pip oodt
+    sudo easy_install oodt
+
+
+Installing From Source
+~~~~~~~~~~~~~~~~~~~~~~
+
+If neither Pip nor EasyInstall are available, you can still make a proper
+installation of Agile OODT by building it from its source code.  Just follow
+these instructions:
+
+1.  Download the Agile OODT source distribution and extract the source
+    archive.  The source distribution is packaged as a gzip'd tar archive.
+2.  Change the current working directory to the newly extracted directory.
+3.  As an administrative user, run: ``python setup.py install``
+
+
+For More Information
+--------------------
+
+Visit any of the following links for additional information, to ask questions,
+report bugs, and so forth:
+
+OODT Home Page
+    http://oodt.apache.org/
+Mailing List for OODT Development
+    mailto:dev@oodt.apache.org
+Package Page (Cheese Shop)
+    http://pypi.python.org/pypi/oodt/
+Issue Tracker (submit bug reports here)
+    https://issues.apache.org/jira/browse/OODT
+
+
+.. References:
+.. _EasyInstall: http://packages.python.org/distribute/easy_install.html
+.. _Pip: http://pip.openplans.org/
+.. _Python: http://python.org/
diff --git a/0.8.1-rc1/agility/docs/LICENSE.txt b/0.8.1-rc1/agility/docs/LICENSE.txt
new file mode 100644
index 0000000..1a954d6
--- /dev/null
+++ b/0.8.1-rc1/agility/docs/LICENSE.txt
@@ -0,0 +1,179 @@
+License, Terms, and Conditions
+==============================
+
+                                 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
diff --git a/0.8.1-rc1/agility/ez_setup.py b/0.8.1-rc1/agility/ez_setup.py
new file mode 100644
index 0000000..a3e1305
--- /dev/null
+++ b/0.8.1-rc1/agility/ez_setup.py
@@ -0,0 +1,332 @@
+#!/usr/bin/env python
+"""Bootstrap setuptools installation
+
+To use setuptools in your package's setup.py, include this
+file in the same directory and add this to the top of your setup.py::
+
+    from ez_setup import use_setuptools
+    use_setuptools()
+
+To require a specific version of setuptools, set a download
+mirror, or use an alternate download directory, simply supply
+the appropriate options to ``use_setuptools()``.
+
+This file can also be run as a script to install or upgrade setuptools.
+"""
+import os
+import shutil
+import sys
+import tempfile
+import zipfile
+import optparse
+import subprocess
+import platform
+import textwrap
+import contextlib
+
+from distutils import log
+
+try:
+    from urllib.request import urlopen
+except ImportError:
+    from urllib2 import urlopen
+
+try:
+    from site import USER_SITE
+except ImportError:
+    USER_SITE = None
+
+DEFAULT_VERSION = "8.2.1"
+DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
+
+def _python_cmd(*args):
+    """
+    Return True if the command succeeded.
+    """
+    args = (sys.executable,) + args
+    return subprocess.call(args) == 0
+
+
+def _install(archive_filename, install_args=()):
+    with archive_context(archive_filename):
+        # installing
+        log.warn('Installing Setuptools')
+        if not _python_cmd('setup.py', 'install', *install_args):
+            log.warn('Something went wrong during the installation.')
+            log.warn('See the error message above.')
+            # exitcode will be 2
+            return 2
+
+
+def _build_egg(egg, archive_filename, to_dir):
+    with archive_context(archive_filename):
+        # building an egg
+        log.warn('Building a Setuptools egg in %s', to_dir)
+        _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
+    # returning the result
+    log.warn(egg)
+    if not os.path.exists(egg):
+        raise IOError('Could not build the egg.')
+
+
+class ContextualZipFile(zipfile.ZipFile):
+    """
+    Supplement ZipFile class to support context manager for Python 2.6
+    """
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, type, value, traceback):
+        self.close()
+
+    def __new__(cls, *args, **kwargs):
+        """
+        Construct a ZipFile or ContextualZipFile as appropriate
+        """
+        if hasattr(zipfile.ZipFile, '__exit__'):
+            return zipfile.ZipFile(*args, **kwargs)
+        return super(ContextualZipFile, cls).__new__(cls)
+
+
+@contextlib.contextmanager
+def archive_context(filename):
+    # extracting the archive
+    tmpdir = tempfile.mkdtemp()
+    log.warn('Extracting in %s', tmpdir)
+    old_wd = os.getcwd()
+    try:
+        os.chdir(tmpdir)
+        with ContextualZipFile(filename) as archive:
+            archive.extractall()
+
+        # going in the directory
+        subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
+        os.chdir(subdir)
+        log.warn('Now working in %s', subdir)
+        yield
+
+    finally:
+        os.chdir(old_wd)
+        shutil.rmtree(tmpdir)
+
+
+def _do_download(version, download_base, to_dir, download_delay):
+    egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg'
+                       % (version, sys.version_info[0], sys.version_info[1]))
+    if not os.path.exists(egg):
+        archive = download_setuptools(version, download_base,
+                                      to_dir, download_delay)
+        _build_egg(egg, archive, to_dir)
+    sys.path.insert(0, egg)
+
+    # Remove previously-imported pkg_resources if present (see
+    # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details).
+    if 'pkg_resources' in sys.modules:
+        del sys.modules['pkg_resources']
+
+    import setuptools
+    setuptools.bootstrap_install_from = egg
+
+
+def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
+        to_dir=os.curdir, download_delay=15):
+    to_dir = os.path.abspath(to_dir)
+    rep_modules = 'pkg_resources', 'setuptools'
+    imported = set(sys.modules).intersection(rep_modules)
+    try:
+        import pkg_resources
+    except ImportError:
+        return _do_download(version, download_base, to_dir, download_delay)
+    try:
+        pkg_resources.require("setuptools>=" + version)
+        return
+    except pkg_resources.DistributionNotFound:
+        return _do_download(version, download_base, to_dir, download_delay)
+    except pkg_resources.VersionConflict as VC_err:
+        if imported:
+            msg = textwrap.dedent("""
+                The required version of setuptools (>={version}) is not available,
+                and can't be installed while this script is running. Please
+                install a more recent version first, using
+                'easy_install -U setuptools'.
+
+                (Currently using {VC_err.args[0]!r})
+                """).format(VC_err=VC_err, version=version)
+            sys.stderr.write(msg)
+            sys.exit(2)
+
+        # otherwise, reload ok
+        del pkg_resources, sys.modules['pkg_resources']
+        return _do_download(version, download_base, to_dir, download_delay)
+
+def _clean_check(cmd, target):
+    """
+    Run the command to download target. If the command fails, clean up before
+    re-raising the error.
+    """
+    try:
+        subprocess.check_call(cmd)
+    except subprocess.CalledProcessError:
+        if os.access(target, os.F_OK):
+            os.unlink(target)
+        raise
+
+def download_file_powershell(url, target):
+    """
+    Download the file at url to target using Powershell (which will validate
+    trust). Raise an exception if the command cannot complete.
+    """
+    target = os.path.abspath(target)
+    ps_cmd = (
+        "[System.Net.WebRequest]::DefaultWebProxy.Credentials = "
+        "[System.Net.CredentialCache]::DefaultCredentials; "
+        "(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)"
+        % vars()
+    )
+    cmd = [
+        'powershell',
+        '-Command',
+        ps_cmd,
+    ]
+    _clean_check(cmd, target)
+
+def has_powershell():
+    if platform.system() != 'Windows':
+        return False
+    cmd = ['powershell', '-Command', 'echo test']
+    with open(os.path.devnull, 'wb') as devnull:
+        try:
+            subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
+        except Exception:
+            return False
+    return True
+
+download_file_powershell.viable = has_powershell
+
+def download_file_curl(url, target):
+    cmd = ['curl', url, '--silent', '--output', target]
+    _clean_check(cmd, target)
+
+def has_curl():
+    cmd = ['curl', '--version']
+    with open(os.path.devnull, 'wb') as devnull:
+        try:
+            subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
+        except Exception:
+            return False
+    return True
+
+download_file_curl.viable = has_curl
+
+def download_file_wget(url, target):
+    cmd = ['wget', url, '--quiet', '--output-document', target]
+    _clean_check(cmd, target)
+
+def has_wget():
+    cmd = ['wget', '--version']
+    with open(os.path.devnull, 'wb') as devnull:
+        try:
+            subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
+        except Exception:
+            return False
+    return True
+
+download_file_wget.viable = has_wget
+
+def download_file_insecure(url, target):
+    """
+    Use Python to download the file, even though it cannot authenticate the
+    connection.
+    """
+    src = urlopen(url)
+    try:
+        # Read all the data in one block.
+        data = src.read()
+    finally:
+        src.close()
+
+    # Write all the data in one block to avoid creating a partial file.
+    with open(target, "wb") as dst:
+        dst.write(data)
+
+download_file_insecure.viable = lambda: True
+
+def get_best_downloader():
+    downloaders = (
+        download_file_powershell,
+        download_file_curl,
+        download_file_wget,
+        download_file_insecure,
+    )
+    viable_downloaders = (dl for dl in downloaders if dl.viable())
+    return next(viable_downloaders, None)
+
+def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
+        to_dir=os.curdir, delay=15, downloader_factory=get_best_downloader):
+    """
+    Download setuptools from a specified location and return its filename
+
+    `version` should be a valid setuptools version number that is available
+    as an sdist for download under the `download_base` URL (which should end
+    with a '/'). `to_dir` is the directory where the egg will be downloaded.
+    `delay` is the number of seconds to pause before an actual download
+    attempt.
+
+    ``downloader_factory`` should be a function taking no arguments and
+    returning a function for downloading a URL to a target.
+    """
+    # making sure we use the absolute path
+    to_dir = os.path.abspath(to_dir)
+    zip_name = "setuptools-%s.zip" % version
+    url = download_base + zip_name
+    saveto = os.path.join(to_dir, zip_name)
+    if not os.path.exists(saveto):  # Avoid repeated downloads
+        log.warn("Downloading %s", url)
+        downloader = downloader_factory()
+        downloader(url, saveto)
+    return os.path.realpath(saveto)
+
+def _build_install_args(options):
+    """
+    Build the arguments to 'python setup.py install' on the setuptools package
+    """
+    return ['--user'] if options.user_install else []
+
+def _parse_args():
+    """
+    Parse the command line for options
+    """
+    parser = optparse.OptionParser()
+    parser.add_option(
+        '--user', dest='user_install', action='store_true', default=False,
+        help='install in user site package (requires Python 2.6 or later)')
+    parser.add_option(
+        '--download-base', dest='download_base', metavar="URL",
+        default=DEFAULT_URL,
+        help='alternative URL from where to download the setuptools package')
+    parser.add_option(
+        '--insecure', dest='downloader_factory', action='store_const',
+        const=lambda: download_file_insecure, default=get_best_downloader,
+        help='Use internal, non-validating downloader'
+    )
+    parser.add_option(
+        '--version', help="Specify which version to download",
+        default=DEFAULT_VERSION,
+    )
+    options, args = parser.parse_args()
+    # positional arguments are ignored
+    return options
+
+def main():
+    """Install or upgrade setuptools and EasyInstall"""
+    options = _parse_args()
+    archive = download_setuptools(
+        version=options.version,
+        download_base=options.download_base,
+        downloader_factory=options.downloader_factory,
+    )
+    return _install(archive, _build_install_args(options))
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/0.8.1-rc1/agility/oodt/__init__.py b/0.8.1-rc1/agility/oodt/__init__.py
new file mode 100644
index 0000000..5cc91fa
--- /dev/null
+++ b/0.8.1-rc1/agility/oodt/__init__.py
@@ -0,0 +1,27 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+'''Agile Object Oriented Data Technology (OODT).
+
+OODT is a set of software components that permit the discovery, correlation,
+search, and retrieval of data and metadata.  For more information, see the
+OODT web site_.
+
+.. _site: http://oodt.apache.org/
+'''
+
+__docformat__ = 'restructuredtext'
diff --git a/0.8.1-rc1/agility/oodt/oodterrors.py b/0.8.1-rc1/agility/oodt/oodterrors.py
new file mode 100644
index 0000000..46ee999
--- /dev/null
+++ b/0.8.1-rc1/agility/oodt/oodterrors.py
@@ -0,0 +1,26 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+'''Object Oriented Data Technology exceptions.
+'''
+
+__docformat__ = 'restructuredtext'
+
+class OODTException(Exception):
+    '''Common OODT exception base.
+    '''
+    pass
diff --git a/0.8.1-rc1/agility/oodt/profile.py b/0.8.1-rc1/agility/oodt/profile.py
new file mode 100644
index 0000000..aa6f99c
--- /dev/null
+++ b/0.8.1-rc1/agility/oodt/profile.py
@@ -0,0 +1,502 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+'''Profiles.  A profile is a metadata description of a resource.
+
+Profiles capture:
+
+* Inception metadata.  This includes items such as a resouce's title,
+  description, creators, contributors, publishers, language, and so on.  This
+  set of metdata is based on the Dublin Core.  Class `ResourceAttributes`
+  captures this metadata.
+
+* Composition metadata.  This includes data elements that describe what
+  the resource contains, such as ranges of data values (high and low
+  temperature, latitude/longitude) or enumerated data values (zoning code,
+  genus/species, etc.).  Subclasses of `ProfileElement` captures this
+  metadata.
+
+* Profile metadata.  This is metadata describing the profile itself, such
+  as revision notes, ID number, etc.  Class `ProfileAttributes` captures this
+  metadata.
+
+Objects of these classes are unified into a single `Profile` object.
+'''
+
+__docformat__ = 'restructuredtext'
+
+import xmlutils
+import xml.dom
+from xmlutils import DocumentableField
+
+class ProfileAttributes(xmlutils.Documentable):
+    '''Attributes of a profile.  These are attributes not related to the
+    resource that a profile profiles, but rather the profile itself.  In
+    most cases, simply constructing this object with no initializer
+    arguments will suffice.
+    '''
+    def __init__(self, id='UNKNOWN', version='1.0.0', type='profile', statusID='active', securityType='unclassified',
+        parentID='UNKNOWN', childIDs=None, regAuthority='UNKNOWN', revNotes=None, node=None):
+        '''Initialize profile attributes.
+        
+        - `id` unique ID for the profile
+        - `version` number
+        - `type` should always be the string "profile"
+        - `statusID` should always be the string "active"
+        - `securityType` tells whether the profile is secret
+        - `parentID` gives the unique ID for any "parent" profile
+        - `childIDs` should be a sequnece of any "children" profiles
+        - `regAuthority` is a unique ID identifying the registration
+           authority responsible for the profile
+        - `revNotes` is a sequence of comments detailing historical
+           changes to the profile
+        - `node` is an XML DOM node.  If the `node` argument is given,
+           it's used to initialize the object.
+        '''
+        self.id = id
+        self.version = version
+        self.type = type
+        self.statusID = statusID
+        self.securityType = securityType
+        self.parentID = parentID
+        self.childIDs = childIDs
+        self.regAuthority = regAuthority
+        self.revNotes = revNotes
+        if self.childIDs is None:
+            self.childIDs = []
+        if self.revNotes is None:
+            self.revNotes = []
+        if node is not None:
+            self.parse(node)
+    
+    def getDocumentElementName(self):
+        '''Get the XML tag for objects of this class: `profAttributes`.
+        '''
+        return 'profAttributes'
+    
+    def getDocumentableFields(self):
+        '''Get the attributes that are put into XML.
+        '''
+        return (DocumentableField('id', u'profId', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('version', u'profVersion', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('type', u'profType', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('statusID', u'profStatusId', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('securityType', u'profSecurityType', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('parentID', u'profParentId', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('childIDs', u'profChildId', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('regAuthority', u'profRegAuthority', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('revNotes', u'profRevisionNote', DocumentableField.MULTI_VALUED_KIND))
+
+    def __repr__(self):
+        return ('ProfileAttributes(id=%s,version=%s,type=%s,statusID=%s,securityType=%s,parentID=%s,childIDs=%s,' \
+            'regAuthority=%s,revNotes=%s)') % (self.id, self.version, self.type, self.statusID, self.securityType,
+            self.parentID, self.childIDs, self.regAuthority, self.revNotes)
+            
+    def __cmp__(self, other):
+        return cmp(self.id, other.id)
+    
+    def __hash__(self):
+        return hash(self.id)
+    
+
+class ResourceAttributes(xmlutils.Documentable):
+    '''Attributes of the resource.  Objects of this class collect data about the resource's
+    inception and are based on Dublin Core.
+    '''
+    def __init__(self, identifier='UNKNOWN', title='UNKNOWN', formats=None, description='UNKNOWN', creators=None, subjects=None,
+        publishers=None, contributors=None, dates=None, types=None, sources=None, languages=None, relations=None,
+        coverages=None, rights=None, contexts=None, aggregation='UNKNOWN', resClass='UNKNOWN', locations=None, node=None):
+        '''Initialize ResourceAttributes.
+        
+        The following arguments are required:
+        
+        - `identifier` is a URI uniquely identifying the resource
+        - `title` names the resource
+        - `description` gives a summary or abstract of it
+        - `aggregation` tells the gross structure of the resource and
+           should be one of the following values:
+            - data.granule
+            - data.dataSet
+            - data.dataSetCollection
+        - `resClass` gives the kind of the resource (what to expect
+           when connecting to one of its locations)
+        
+        All of the others should be initialized with sequences as the
+        resource attributes follows the Dublin Core recommendation on
+        multiplicity.
+        
+        If `node` is given, it's treated as an XML DOM node and is used to
+        initialize the resource attributes.
+        '''
+        self.identifier = identifier
+        self.title = title
+        self.formats = formats
+        self.description = description
+        self.creators = creators
+        self.subjects = subjects
+        self.publishers = publishers
+        self.contributors = contributors
+        self.dates = dates
+        self.types = types
+        self.sources = sources
+        self.languages = languages
+        self.relations = relations
+        self.coverages = coverages
+        self.rights = rights
+        self.contexts = contexts
+        self.aggregation = aggregation
+        self.resClass = resClass
+        self.locations = locations
+        for attr in ('formats', 'creators', 'subjects', 'publishers', 'contributors', 'dates', 'sources', 'languages',
+            'relations', 'coverages', 'rights', 'contexts', 'locations', 'types'):
+            if getattr(self, attr) is None:
+                setattr(self, attr, [])
+        if node is not None:
+            self.parse(node)
+    
+    def getDocumentElementName(self):
+        '''Give the XML tag name: `resAttributes`.
+        '''
+        return 'resAttributes'
+        
+    def __hash__(self):
+        return hash(self.identifier)
+    
+    def __cmp__(self, other):
+        return cmp(self.identifier, other.identifier)
+    
+    def getDocumentableFields(self):
+        '''Get the attributes that go into XML.
+        '''
+        return (DocumentableField('identifier', u'Identifier', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('title', u'Title', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('formats', u'Format', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('description', u'Description', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('creators', u'Creator', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('subjects', u'Subject', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('publishers', u'Publisher', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('contributors', u'Contributor', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('dates', u'Date', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('types', u'Type', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('sources', u'Source', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('languages', u'Language', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('relations', u'Relation', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('coverages', u'Coverage', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('rights', u'Rights', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('contexts', u'resContext', DocumentableField.MULTI_VALUED_KIND),
+            DocumentableField('aggregation', u'resAggregation', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('resClass', u'resClass', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('locations', u'resLocation', DocumentableField.MULTI_VALUED_KIND))
+    
+
+class Profile(object):
+    '''A profile "profiles" a resource by describing it with metadata.
+    '''
+    def __init__(self, profAttr=None, resAttr=None, profElements=None, node=None):
+        '''Initialize a profile.  The profElements should be a dicitonary that maps
+        from element name to instance of a `ProfileElement`.
+        '''
+        self.profAttr, self.resAttr, self.profElements = profAttr, resAttr, profElements
+        if self.profAttr is None:
+            self.profAttr = ProfileAttributes()
+        if self.resAttr is None:
+            self.resAttr = ResourceAttributes()
+        if self.profElements is None:
+            self.profElements = {}
+        if node is not None:
+            self.parse(node)
+    
+    def parse(self, node):
+        '''Initialize this object from the given XML DOM `node`.
+        '''
+        if node.nodeName != 'profile':
+            raise ValueError('Expected profile element but got "%s"' % node.nodeName)
+        for child in filter(lambda node: node.nodeType == xml.dom.Node.ELEMENT_NODE, node.childNodes):
+            name = child.nodeName
+            if name == u'profAttributes':
+                self.profAttr = ProfileAttributes()
+                self.profAttr.parse(child)
+            elif name == u'resAttributes':
+                self.resAttr = ResourceAttributes()
+                self.resAttr.parse(child)
+            elif name == u'profElement':
+                elem = _parseProfileElement(child)
+                self.profElements[elem.name] = elem
+                
+    def toXML(self, owner):
+        '''Convert this object into XML owned by the given `owner` document.
+        '''
+        root = owner.createElement(u'profile')
+        root.appendChild(self.profAttr.toXML(owner))
+        root.appendChild(self.resAttr.toXML(owner))
+        for elem in self.profElements.itervalues():
+            root.appendChild(elem.toXML(owner))
+        return root
+    
+    def __cmp__(self, other):
+        profAttr = cmp(self.profAttr, other.profAttr)
+        if profAttr < 0:
+            return -1
+        elif profAttr == 0:
+            resAttr = cmp(self.resAttr, other.resAttr)
+            if resAttr < 0:
+                return -1
+            elif resAttr == 0:
+                return cmp(self.profElements, other.profElements)
+        return 1
+    
+    def __hash__(self):
+        return hash(self.profAttr) ^ hash(self.resAttr)
+    
+    def __repr__(self):
+        return 'Profile(profAttr=%s,resAttr=%s,profElements=%s)' % (self.profAttr, self.resAttr, self.profElements)
+    
+
+class ProfileElement(object):
+    '''Abstract profile element.
+    '''
+    def __init__(self, name, description, type, units, synonyms, comment):
+        '''Initialize profile element.
+        '''
+        self.name = name
+        self.description = description
+        self.type = type
+        self.units = units
+        self.synonyms = synonyms
+        self.comment = comment
+    
+    def __repr__(self):
+        return 'ProfileElement(name=%r,description=%r,type=%r,units=%r,synonyms=%r,comment=%r)' % (self.name,
+            self.description, self.type, self.units, self.synonyms, self.comment)
+    
+    def __cmp__(self, other):
+        rc = cmp(self.name, other.name)
+        if rc < 0:
+            return -1
+        elif rc == 0:
+            rc = cmp(self.description, other.description)
+            if rc < 0:
+                return -1
+            elif rc == 0:
+                rc = cmp(self.type, other.type)
+                if rc < 0:
+                    return -1
+                elif rc == 0:
+                    rc = cmp(self.units, other.units)
+                    if rc < 0:
+                        return -1
+                    elif rc == 0:
+                        rc = cmp(self.synonyms, other.synonyms)
+                        if rc < 0:
+                            return -1
+                        elif rc == 0:
+                            return cmp(self.comment, other.comment)
+        return 1
+    
+    def __hash__(self):
+        return reduce(lambda x, y: hash(x) ^ hash(y), [getattr(self, attr) for attr in ('name', 'description', 'type',
+            'units', 'synonyms', 'comment')])
+    
+    def isEnumerated(self):
+        '''Is this an enumerated element?  Enumerated elements include those with
+        discrete values as well unspecified elements.
+        '''
+        return False;
+    
+    def getValues(self):
+        '''Get the discrete values of this element, which may be empty.
+        '''
+        return []
+    
+    def getMinValue(self):
+        '''Get the minimum value of this element, which may be zero.
+        '''
+        return 0.0
+    
+    def getMaxValue(self):
+        '''Get the maximum value of this element, which may be zero.
+        '''
+        return 0.0
+    
+    def toXML(self, owner):
+        '''Convert this object into XML owned by the given `owner` document.
+        '''
+        root = owner.createElement('profElement')
+        xmlutils.add(root, u'elemId', self.name)
+        xmlutils.add(root, u'elemName', self.name)
+        xmlutils.add(root, u'elemDesc', self.description)
+        xmlutils.add(root, u'elemType', self.type)
+        xmlutils.add(root, u'elemUnit', self.units)
+        if self.isEnumerated():
+            flag = 'T'
+        else:
+            flag = 'F'
+        xmlutils.add(root, u'elemEnumFlag', flag)
+        for value in self.getValues():
+            elem = owner.createElement('elemValue')
+            root.appendChild(elem)
+            elem.appendChild(owner.createCDATASection(value))
+        if not self.isEnumerated():
+            xmlutils.add(root, u'elemMinValue', str(self.getMinValue()))
+            xmlutils.add(root, u'elemMaxValue', str(self.getMaxValue()))
+        xmlutils.add(root, u'elemSynonym', self.synonyms)
+        xmlutils.add(root, u'elemComment', self.comment)
+        return root
+    
+
+class UnspecifiedProfileElement(ProfileElement):
+    '''An unspecified profile element merely documents the existence of a element within a
+    dataset but says nothing about its actual values.
+    '''
+    def __init__(self, name, description, type, units, synonyms, comment):
+        '''Initialize an "unspecified" profile element.
+        '''
+        super(UnspecifiedProfileElement, self).__init__(name, description, type, units, synonyms, comment)
+    
+    def isEnumerated(self):
+        '''An unspecified profile element is indeed enumerated.  It just has no enumerated values.
+        '''
+        return True
+    
+
+class EnumeratedProfileElement(ProfileElement):
+    '''An enumerated profile element describes set of discrete values.
+    '''
+    def __init__(self, name, description, type, units, synonyms, comment, values):
+        '''Initialize an enumerated profile element.
+        '''
+        super(EnumeratedProfileElement, self).__init__(name, description, type, units, synonyms, comment)
+        self.values = values
+        
+    def isEnumerated(self):
+        '''An enumerated profile element is indeed enumerated.
+        '''
+        return True
+    
+    def getValues(self):
+        '''Return the sequence of values.
+        '''
+        return self.values
+        
+    def __cmp__(self, other):
+        rc = super(EnumeratedProfileElement, self).__cmp__(other)
+        if rc < 0:
+            return -1
+        elif rc == 0:
+            return cmp(self.values, other.values)
+        return 1
+    
+
+class RangedProfileElement(ProfileElement):
+    '''A ranged profile element describes a value between two numeric ranges.
+    '''
+    def __init__(self, name, description, type, units, synonyms, comment, minValue, maxValue):
+        '''Initialize a ranged profile element.
+        '''
+        super(RangedProfileElement, self).__init__(name, description, type, units, synonyms, comment)
+        self.minValue = minValue
+        self.maxValue = maxValue
+    
+    def getMinValue(self):
+        '''Get the minimum value.
+        '''
+        return self.minValue
+    
+    def getMaxValue(self):
+        '''Get the maximum value.
+        '''
+        return self.maxValue
+    
+    def __repr__(self):
+        return 'RangedProfileElement(%r,minValue=%r,maxValue=%r)' % (super(RangedProfileElement, self).__repr__(),
+            self.minValue, self.maxValue)
+    
+    def __cmp__(self, other):
+        rc = super(RangedProfileElement, self).__cmp__(other)
+        if rc < 0:
+            return -1
+        elif rc == 0:
+            rc = self.minValue - other.minValue
+            if rc < 0:
+                return -1
+            elif rc == 0:
+                return self.maxValue - other.maxValue
+        return 1
+    
+
+def _parseProfileElement(node):
+    '''Construct an appropriate profile element from the given DOM node.
+    '''
+    if node.nodeName != u'profElement':
+        raise ValueError('Expected profElement element but got "%s"' % node.nodeName)
+    settings = dict(elemId=u'UNKNOWN', elemDesc=u'UNKNOWN', elemType=u'UNKNOWN', elemUnit=u'UNKNOWN', elemEnumFlag=u'F',
+        elemComment=u'UNKNOWN')
+    values, syns = [], []
+    for child in filter(lambda node: node.nodeType == xml.dom.Node.ELEMENT_NODE, node.childNodes):
+        text = xmlutils.text(child)
+        if child.nodeName == u'elemValue':
+            values.append(text)
+        elif child.nodeName == u'elemSynonym':
+            syns.append(text)
+        else:
+            settings[str(child.nodeName)] = text
+    if 'elemName' not in settings:
+        raise ValueError('profElement requires elemName but none specified')
+    if 'elemEnumFlag' not in settings:
+        raise ValueError('profElement requires elemEnumFlag but none specified')
+        
+    # Normally I'd treat only those XML elements where elemEnumFlag as T as possibly producing
+    # unspecified or enumerated, and F producing *only* ranged elements.  But PDS profile
+    # servers are producing profile elements with F for elemEnumFlag and yet NO elemMinValue
+    # and elemMaxValue.  If they're using the Java profile code, I'd call that a bug in that
+    # code.  If they're not, then I'd say they're producing profiles incorrectly.
+    if settings['elemEnumFlag'] == 'T':
+        if len(values) == 0:
+            return UnspecifiedProfileElement(settings['elemName'], settings['elemDesc'], settings['elemType'],
+                settings['elemUnit'], syns, settings['elemComment'])
+        else:
+            return EnumeratedProfileElement(settings['elemName'], settings['elemDesc'], settings['elemType'],
+                settings['elemUnit'], syns, settings['elemComment'], values)
+    else:
+        if 'elemMinValue' not in settings or 'elemMaxValue' not in settings:
+            return UnspecifiedProfileElement(settings['elemName'], settings['elemDesc'], settings['elemType'],
+                settings['elemUnit'], syns, settings['elemComment'])
+        else:
+            return RangedProfileElement(settings['elemName'], settings['elemDesc'], settings['elemType'],
+            settings['elemUnit'], syns, settings['elemComment'], float(settings['elemMinValue']),
+            float(settings['elemMaxValue']))
+    
+
+# Some sample code:
+# if __name__ == '__main__':
+#   import urllib2, xml.dom.minidom
+#   x = urllib2.urlopen('http://starbrite.jpl.nasa.gov/q?object=urn%3Aeda%3Armi%3AJPL.PDS.MasterProd&type=profile&keywordQuery=TARGET_NAME+%3D+MARS')
+#   d = xml.dom.minidom.parse(x)
+#   x.close()
+#   profiles = []
+#   for i in d.documentElement.getElementsByTagName(u'profile'):
+#       profiles.append(Profile(node=i))
+#       
+#   doc = xml.dom.minidom.getDOMImplementation().createDocument(None, None, None)
+#   print '<?xml version="1.0" encoding="UTF-8"?>'
+#   print '<!DOCTYPE profiles PUBLIC "-//JPL//DTD Profile 1.1//EN"'
+#   print '  "http://oodt.jpl.nasa.gov/grid-profile/dtd/prof.dtd">'
+#   print '<profiles>'
+#   for profile in profiles:
+#       print profile.toXML(doc).toxml()
+#   print '</profiles>'
+#   
diff --git a/0.8.1-rc1/agility/oodt/query.py b/0.8.1-rc1/agility/oodt/query.py
new file mode 100644
index 0000000..7bd97c0
--- /dev/null
+++ b/0.8.1-rc1/agility/oodt/query.py
@@ -0,0 +1,456 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+'''
+Agile OODT Query Expressions.
+
+Query expressions in OODT are based on the "DIS" style expressions originally
+developed for the Planetary Data System.  They consist of
+keyword/operator/literal-value triples, such as `targetName = Mars`, each
+linked with logical operators (and, or, not) and grouped with parentheses.
+For more information, see OODT_.
+
+This module defines classes that model the aspects of a query.  In general,
+use the `Query` class, passing a string containing your keyword expression as
+the first constructor argument.  From there, you have a `Query` object you can
+pass around to profile servers, product servers, and so forth.
+
+.. _OODT: http://oodt.apache.org/
+'''
+
+__docformat__ = 'restructuredtext'
+
+import oodterrors, shlex, xmlutils, xml.dom
+from xmlutils import DocumentableField
+
+class _QueryExpressionScanner(shlex.shlex):
+    '''Extend the shlex scanner but for the DIS-style query expressions we expect.
+    This means adding a dot to the characters that comprise a word so we can easily parse
+    floating-point numbers.  Also, there's no comment character.
+    '''
+    def __init__(self, str):
+        '''Create scanner.  `str` is the string to scan.
+        '''
+        shlex.shlex.__init__(self, str)
+        self.commenters = ''
+        self.wordchars = self.wordchars + '.-/:'
+        
+
+    def get_token(self):
+        '''Get the next token.  We strip quotes from strings, attach negative signs
+        to the numbers they're negating, and attach the = to <, >, and ! where needed.
+        '''
+        token = shlex.shlex.get_token(self)
+        if token == self.eof or token == None:
+            return None
+        if token[0] in self.quotes:
+            token = token[1:-1]
+        elif token in ('<', '>', '!'):
+            next = shlex.shlex.get_token(self)
+            if next == self.eof or next == None:
+                return None
+            elif next == '=':
+                token = token + next
+            else:
+                self.push_token(next)
+        return token
+    
+
+class QueryException(oodterrors.OODTException):
+    '''Exceptions related to query expression or query services
+    '''
+    pass
+    
+
+class ExpressionParseError(QueryException):
+    '''Error in parsing a query expression.
+    '''
+    pass
+    
+
+class QueryElement(xmlutils.Documentable):
+    '''An element of a query.
+    '''
+    def __init__(self, role='UNKNOWN', value='UNKNOWN', node=None):
+        '''Create a QueryElement.  You can provide role and value settings, or provide an XML
+        DOM node which will be parsed for role/value.
+        '''
+        self.role, self.value = role, value
+        if node != None:
+            self.parse(node)
+
+    def getDocumentElementName(self):
+        '''Give the XML tag name: `queryElement`.
+        '''
+        return 'queryElement'
+    
+    def getDocumentableFields(self):
+        '''Get the attributes that go into XML.
+        '''
+        return (DocumentableField('role', u'tokenRole', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('value', u'tokenValue', DocumentableField.SINGLE_VALUE_KIND))
+    
+    def __repr__(self):
+        return 'QueryElement(role="%s",value="%s")' % (self.role, self.value)
+    
+
+class QueryHeader(xmlutils.Documentable):
+    '''Header of a query.  Captures metadata like data dictionary in use, etc.
+    '''
+    def __init__(self, id='UNKNOWN', title='UNKNOWN', desc='UNKNOWN', type='QUERY', status='ACTIVE', security='UNKNOWN',
+        rev='2005-10-01 SCK v0.0.0 Under Development', dataDict='UNKNOWN', node=None):
+        '''Initialize a QueryHeader.  Provide id, title, desc, type, status, security, rev,
+        and dataDict settings.  Or, provide just an XML DOM node to be parsed.
+        '''
+        self.id, self.title, self.desc, self.type, self.status, self.security, self.rev, self.dataDict = \
+            id, title, desc, type, status, security, rev, dataDict
+        if node != None:
+            self.parse(node)
+    
+    def getDocumentElementName(self):
+        '''Give the XML tag name: `queryAttributes`.
+        '''
+        return 'queryAttributes'
+    
+    def getDocumentableFields(self):
+        '''Get the attributes that go into XML.
+        '''
+        return (DocumentableField('id', u'queryId', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('title', u'queryTitle', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('desc', u'queryDesc', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('type', u'queryType', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('status', u'queryStatusId', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('security', u'querySecurityType', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('rev', u'queryRevisionNote', DocumentableField.SINGLE_VALUE_KIND),
+            DocumentableField('dataDict', u'queryDataDictId', DocumentableField.SINGLE_VALUE_KIND))
+    
+    def __repr__(self):
+        return 'QueryHeader(id="%s",title="%s",desc="%s",type="%s",status="%s",security="%s",rev="%s",dataDict="%s")' % (
+            self.id, self.title, self.desc, self.type, self.status, self.security, self.rev, self.dataDict
+        )
+    
+    def __cmp__(self, other):
+        return cmp((self.id, self.title, self.desc, self.type, self.status, self.security, self.rev, self.dataDict),
+               (other.id, other.title, other.desc, other.type, other.status, other.security, other.rev, other.dataDict))
+    
+
+class QueryResult(object):
+    '''Result of a query.
+    '''
+    def __init__(self, results=[], node=None):
+        '''Results of a query are captured as a sequence of generic objects.
+        '''
+        self.results = results
+        if node != None: self.parse(node)
+    
+    def parse(self, node):
+        '''Initialize this object from the given XML DOM `node`.
+        '''
+        if 'queryResultSet' != node.nodeName:
+            raise ValueError('Expected queryResultSet but got "%s"' % node.nodeName)
+        for child in node.childNodes:
+            if child.nodeType == xml.dom.Node.ELEMENT_NODE and 'resultElement' == child.nodeName:
+                self.results.append(Result(node=child))
+    
+    def toXML(self, owner):
+        '''Convert this object into XML owned by the given `owner` document.
+        '''
+        root = owner.createElement('queryResultSet')
+        for result in self.results:
+            root.appendChild(result.toXML(owner))
+        return root
+    
+    def clear(self):
+        '''Remove all results.
+        '''
+        self.results = []
+    
+    def __getitem__(self, i):
+        return self.results[i]
+    
+    def __len__(self):
+        return len(self.results)
+    
+    def __cmp__(self, other):
+        return cmp(self.results, other.results)
+    
+
+_RELOPS = {
+    'LT':      'LT', 
+    'lt':      'LT', 
+    '<':       'LT',
+    'LE':      'LE',
+    'le':      'LE',
+    '<=':      'LE',
+    'EQ':      'EQ', 
+    'eq':      'EQ', 
+    '=':       'EQ',
+    'GE':      'GE',
+    'ge':      'GE',
+    '>=':      'GE',
+    'GT':      'GT',
+    'gt':      'GT',
+    '>':       'GT',
+    'NE':      'NE',
+    'ne':      'NE',
+    '!=':      'NE',
+    'LIKE':    'LIKE',
+    'like':    'LIKE',
+    'NOTLIKE': 'NOTLIKE',
+    'notlike': 'NOTLIKE',
+    'notLike': 'NOTLIKE',
+    'IS':      'IS',
+    'is':      'is',
+    'ISNOT':   'ISNOT',
+    'isnot':   'isnot',
+    'isNot':   'isnot'
+}
+
+_LOGOPS = {
+    'AND': 'AND',
+    'and': 'AND',
+    '&':   'AND',
+    'OR':  'OR',
+    'or':  'OR',
+    '|':   'OR',
+    'NOT': 'NOT',
+    'not': 'NOT',
+    '!':   'NOT'
+}
+
+_PRECEDENCE = {
+    'NOT': 2,
+    'AND': 1,
+    'OR': 0,
+}
+
+class Query(object):
+    '''Query.  In old OODT, this was called XMLQuery, even though XML was tagential to it.
+    Captures aspects of a query, including header, results, and so forth.  Most importantly, it
+    captures the query expression, which contains the constraints on user's desiderata and
+    range on what to return.
+    
+    As with other classes in this module, you can provide an XML DOM node to be parsed
+    for the query's settings, or provide each of them individually.
+    '''
+    def __init__(self, keywordQuery=None, header=QueryHeader(), resultModeID='ATTRIBUTE', propType='BROADCAST',
+        propLevels='N/A', maxResults=1, mimeAccept=[], parseQuery=True, node=None):
+        '''Initialize a query.  Usually you provide just the `keywordQuery` argument
+        which should be a keyword/query expression in the DIS-style; or you provide
+        the `node` which is an XML DOM node describing a query.
+        '''
+        self.header, self.resultModeID, self.propType, self.propLevels, self.maxResults, self.mimeAccept = \
+            header, resultModeID, propType, propLevels, maxResults, mimeAccept
+        self.wheres, self.selects, self.froms, self.resultSet = [], [], [], QueryResult()
+        if keywordQuery != None:
+            self.keywordQuery = keywordQuery
+            if parseQuery:
+                self.wheres, self.selects = _parseQuery(keywordQuery)
+        else:
+            self.keywordQuery = ''
+        if node != None:
+            self.parse(node)
+        
+    def toXML(self, owner):
+        '''Yield this query as an XML DOM.
+        '''
+        query = owner.createElement('query')
+        query.appendChild(self.header.toXML(owner))
+        xmlutils.add(query, u'queryResultModeId', self.resultModeID)
+        xmlutils.add(query, u'queryPropogationType', self.propType)
+        xmlutils.add(query, u'queryPropogationLevels', self.propLevels)
+        for mimeType in self.mimeAccept:
+            xmlutils.add(query, u'queryMimeAccept', mimeType)
+        xmlutils.add(query, u'queryMaxResults', str(self.maxResults))
+        xmlutils.add(query, u'queryKWQString', self.keywordQuery)
+        selects = owner.createElement(u'querySelectSet')
+        query.appendChild(selects)
+        for select in self.selects:
+            selects.appendChild(select.toXML(owner))
+        fromElement = owner.createElement(u'queryFromSet')
+        query.appendChild(fromElement)
+        for i in self.froms:
+            fromElement.appendChild(i.toXML(owner))
+        wheres = owner.createElement(u'queryWhereSet')
+        query.appendChild(wheres)
+        for where in self.wheres:
+            wheres.appendChild(where.toXML(owner))
+        query.appendChild(self.resultSet.toXML(owner))
+        return query
+        
+    def parse(self, node):
+        '''Parse the XML DOM node as a query document.
+        '''
+        if 'query' != node.nodeName:
+            raise ValueError('Expected query but got "%s"' % node.nodeName)
+        self.mimeAccept, self.results = [], []
+        for child in node.childNodes:
+            if child.nodeType == xml.dom.Node.ELEMENT_NODE:
+                if child.nodeName == u'queryAttributes':
+                    self.header = QueryHeader(node=child)
+                elif child.nodeName == u'resultModeID':
+                    self.resultModeID = xmlutils.text(child)
+                elif child.nodeName == u'queryPropogationType':
+                    self.propType = xmlutils.text(child)
+                elif child.nodeName == u'queryPropogationLevels':
+                    self.propLevels = xmlutils.text(child)
+                elif child.nodeName == u'queryMimeAccept':
+                    self.mimeAccept.append(xmlutils.text(child))
+                elif child.nodeName == u'queryMaxResults':
+                    self.maxResults = int(xmlutils.text(child))
+                elif child.nodeName == u'queryKWQString':
+                    self.keywordQuery = xmlutils.text(child)
+                elif child.nodeName == u'querySelectSet':
+                    self.selects = _parseQueryElements(child)
+                elif child.nodeName == u'queryFromSet':
+                    self.froms = _parseQueryElements(child)
+                elif child.nodeName == u'queryWhereSet':
+                    self.wheres = _parseQueryElements(child)
+                elif child.nodeName == u'queryResultSet':
+                    self.resultSet = QueryResult(node=child)
+    
+    def __cmp__(self, other):
+        header = cmp(self.header, other.header)
+        if header < 0:
+            return -1
+        elif header == 0:
+            resultModeID = cmp(self.resultModeID, other.resultModeID)
+            if resultModeID < 0:
+                return -1
+            elif resultModeID == 0:
+                propType = cmp(self.propType, other.propType)
+                if propType < 0:
+                    return -1
+                elif propType == 0:
+                    propLevels = cmp(self.propLevels, other.propLevels)
+                    if propLevels < 0:
+                        return -1
+                    elif propLevels == 0:
+                        maxResults = self.maxResults - other.maxResults
+                        if maxResults < 0:
+                            return -1
+                        elif maxResults == 0:
+                            mimeAccept = cmp(self.mimeAccept, other.mimeAccept)
+                            if mimeAccept < 0:
+                                return -1
+                            elif mimeAccept == 0:
+                                selects = cmp(self.selects, other.selects)
+                                if selects < 0:
+                                    return -1
+                                elif selects == 0:
+                                    froms = cmp(self.froms, other.froms)
+                                    if froms < 0:
+                                        return -1
+                                    elif froms == 0:
+                                        wheres = cmp(self.wheres, other.wheres)
+                                        if wheres < 0:
+                                            return -1
+                                        elif wheres == 0:
+                                            return cmp(self.resultSet, other.resultSet)
+        return 1
+    
+
+def _parseQueryElements(node):
+    '''The children of the given XML DOM node are a sequence of queryElements.  Parse them
+    and return a list of QueryElement objects.
+    '''
+    a = []
+    for child in node.childNodes:
+        if child.nodeType == xml.dom.Node.ELEMENT_NODE:
+            a.append(QueryElement(node=child))
+    return a
+    
+
+def _parseQuery(s):
+    '''Parse the query expression in `s`.
+    '''
+    if s is None:
+        return [], []
+    if len(s.strip()) == 0:
+        return [], []
+    if s.count('(') != s.count(')'):
+        raise ExpressionParseError('Unbalanced parentheses')
+    scanner = _QueryExpressionScanner(s)
+    return _buildQuery(scanner)
+    
+
+def _buildQuery(scanner):
+    '''Build the query stacks using the given `scanner`.
+    '''
+    operators, expression, selectors = [], [], []
+    while True:
+        token = scanner.get_token()
+        if token is None: break
+        if token in _LOGOPS:
+            op = QueryElement('LOGOP', _LOGOPS[token])
+            if len(operators) == 0:
+                operators.append(op)
+            else:
+                while len(operators) > 0 and _PRECEDENCE[operators[-1].value] > _PRECEDENCE[op.value]:
+                    expression.append(operators.pop())
+                operators.append(op)
+        elif token == '(':
+            subExpr, subSelectors = _buildQuery(scanner)
+            expression.extend(subExpr)
+            selectors.extend(subSelectors)
+        elif token == ')':
+            break
+        else:
+            _addTerm(token, scanner, expression, operators, selectors)
+    if len(operators) > 0 and len(expression) == 0:
+        raise ExpressionParseError('Query contains only logical operators')
+    operators.reverse()
+    expression.extend(operators)
+    return expression, selectors
+    
+
+def _addTerm(elemName, scanner, expression, operators, selectors):
+    '''Add a term to the correct stack.
+    '''
+    relop = scanner.get_token()
+    if relop is None:
+        raise ExpressionParseError('Expected relational operator after element name "%s"' % elemName)
+    if relop not in _RELOPS:
+        raise ExpressionParseError('Unknown relational operator "%s"' % relop)
+    literal = scanner.get_token()
+    if literal is None:
+        raise ExpressionParseError('Expected literal value for "%s %s" comparison' % (elemName, relop))
+    if elemName == 'RETURN':
+        selectors.append(QueryElement('elemName', literal))
+        if len(operators) > 0:
+            operators.pop()
+        else:
+            scanner.get_token()
+    else:
+        expression.append(QueryElement('elemName', elemName))
+        expression.append(QueryElement('LITERAL', literal))
+        expression.append(QueryElement('RELOP', _RELOPS[relop]))
+    
+
+# Sample code:
+# if __name__ == '__main__':
+#   import urllib, xml.dom.minidom
+# 
+#   impl = xml.dom.minidom.getDOMImplementation()
+#   doc = impl.createDocument(None, None, None) # nsURI, qName, docType
+# 
+#   q = Query('track = Innocente')
+#   node = q.toXML(doc)
+#   doc.appendChild(node)
+#   q = doc.toxml()
+#   f = urllib.urlopen('http://localhost:8080/pds/prof', urllib.urlencode(dict(xmlq=q)), {}) # url, postdata, proxies (none)
+#   print f.read()
diff --git a/0.8.1-rc1/agility/oodt/tests/__init__.py b/0.8.1-rc1/agility/oodt/tests/__init__.py
new file mode 100644
index 0000000..de351e1
--- /dev/null
+++ b/0.8.1-rc1/agility/oodt/tests/__init__.py
@@ -0,0 +1,38 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+'''Agile OODT Tests.
+'''
+
+__docformat__ = 'restructuredtext'
+
+import unittest
+import profileTest, queryTest, xmlutilsTest
+
+def test_suite():
+    '''Create the suite of tests.
+    '''
+    suite = unittest.TestSuite()
+    suite.addTest(profileTest.test_suite())
+    suite.addTest(queryTest.test_suite())
+    suite.addTest(xmlutilsTest.test_suite())
+    return suite
+    
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
+    
diff --git a/0.8.1-rc1/agility/oodt/tests/profileTest.py b/0.8.1-rc1/agility/oodt/tests/profileTest.py
new file mode 100644
index 0000000..9fbe92a
--- /dev/null
+++ b/0.8.1-rc1/agility/oodt/tests/profileTest.py
@@ -0,0 +1,239 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+'''Unit tests for the `profile` module.
+'''
+
+__docformat__ = 'restructuredtext'
+
+import unittest, xml.dom.minidom
+from oodt.profile import ProfileAttributes, ResourceAttributes, Profile, UnspecifiedProfileElement, RangedProfileElement,\
+    EnumeratedProfileElement
+
+class ProfileAttributesTest(unittest.TestCase):
+    '''Unit test for the ProfileAttributes class.
+    '''
+    def testDefaults(self):
+        '''Test to see if default values are reasonable.
+        '''
+        pa = ProfileAttributes()
+        self.assertEquals('UNKNOWN', pa.id)
+        self.assertEquals('1.0.0', pa.version)
+        self.assertEquals('profile', pa.type)
+        self.assertEquals('active', pa.statusID)
+        self.assertEquals('unclassified', pa.securityType)
+        self.assertEquals('UNKNOWN', pa.parentID)
+        self.assertEquals(0, len(pa.childIDs))
+        self.assertEquals('UNKNOWN', pa.regAuthority)
+        self.assertEquals(0, len(pa.revNotes))
+
+    def testCmp(self):
+        '''Test comparison operators.
+        '''
+        a = ProfileAttributes('1')
+        b = ProfileAttributes('1')
+        c = ProfileAttributes('2')
+        self.assertEquals(a, a)
+        self.assertEquals(a, b)
+        self.assertNotEquals(a, c)
+        self.assert_(a <= a)
+        self.assert_(a <= b)
+        self.assert_(a <= c)
+        self.assert_(a < c)
+        
+    def testXML(self):
+        '''Test XML serialization and re-composition from XML.
+        '''
+        a = ProfileAttributes('1.3.1.9', '2.0.0', 'profile', 'inactive', 'classified', '1.3.1', ['1.3.1.9.1', '1.3.1.9.2'],
+            'NASA', ['Updated', 'Created'])
+        doc = xml.dom.minidom.getDOMImplementation().createDocument(None, None, None)
+        node = a.toXML(doc)
+        b = ProfileAttributes(node=node)
+        self.assertEquals(a, b)
+        
+    def testXMLValidity(self):
+        '''Test to see if all required XML elements are in there.
+        '''
+        a = ProfileAttributes('1.3.1.9', '2.0.0', 'profile', 'inactive', 'classified', '1.3.1', ['1.3.1.9.1', '1.3.1.9.2'],
+            'NASA', ['Updated', 'Created'])
+        doc = xml.dom.minidom.getDOMImplementation().createDocument(None, None, None)
+        node = a.toXML(doc)
+        self.assertEquals('profAttributes', node.nodeName)
+        childElements = [n.nodeName for n in node.childNodes]
+        self.assertEquals([u'profId', u'profVersion', u'profType', u'profStatusId', u'profSecurityType', u'profParentId',
+            u'profChildId', u'profChildId', u'profRegAuthority', u'profRevisionNote', u'profRevisionNote'],
+            childElements)
+    
+    def testInstances(self):
+        '''Test to ensure instances don't share instance data.
+        '''
+        a = ProfileAttributes(id='1')
+        b = ProfileAttributes(id='2')
+        self.assertNotEquals(a, b)
+        a.childIDs.append('3')
+        self.assertNotEquals(a.childIDs, b.childIDs)
+        a.revNotes.append('Uhhhhh, spam?')
+        self.assertNotEquals(a.revNotes, b.revNotes)
+    
+    
+class ResourceAttributesTest(unittest.TestCase):
+    '''Unit test for the ResourceAttributes class.
+    '''
+    def testDefaults(self):
+        '''Test if default values are reasonable.
+        '''
+        ra = ResourceAttributes()
+        self.assertEquals('UNKNOWN', ra.identifier)
+        self.assertEquals('UNKNOWN', ra.title)
+        self.assertEquals(0, len(ra.formats))
+        self.assertEquals('UNKNOWN', ra.description)
+        self.assertEquals(0, len(ra.creators))
+        self.assertEquals(0, len(ra.subjects))
+        self.assertEquals(0, len(ra.publishers))
+        self.assertEquals(0, len(ra.contributors))
+        self.assertEquals(0, len(ra.dates))
+        self.assertEquals(0, len(ra.types))
+        self.assertEquals(0, len(ra.sources))
+        self.assertEquals(0, len(ra.languages))
+        self.assertEquals(0, len(ra.relations))
+        self.assertEquals(0, len(ra.coverages))
+        self.assertEquals(0, len(ra.rights))
+        self.assertEquals(0, len(ra.contexts))
+        self.assertEquals('UNKNOWN', ra.aggregation)
+        self.assertEquals('UNKNOWN', ra.resClass)
+        self.assertEquals(0, len(ra.locations))
+    
+    def testCmp(self):
+        '''Test comparison operations.
+        '''
+        a = ResourceAttributes('uri:fish', 'Fish', ['text/html'], 'A book about fish.')
+        b = ResourceAttributes('uri:fish', 'Fish', ['text/html'], 'A book about fish.')
+        c = ResourceAttributes('uri:clams', 'Clams', ['text/html'], 'A book about clams.')
+        self.assertEquals(a, a)
+        self.assertEquals(a, b)
+        self.assertNotEquals(a, c)
+        self.assert_(a <= b)
+        self.assert_(a >= c)
+        self.assert_(a > c)
+        self.assert_(a <= a)
+    
+    def testXML(self):
+        '''Test XML serialization and recomposition from XML.
+        '''
+        a = ResourceAttributes('uri:fish', 'Fish', ['text/html'], 'A book about fish.')
+        doc = xml.dom.minidom.getDOMImplementation().createDocument(None, None, None)
+        node = a.toXML(doc)
+        b = ResourceAttributes(node=node)
+        self.assertEquals(a, b)
+    
+    def testXMLValidity(self):
+        '''Test to see if all required XML elements are in there.
+        '''
+        a = ResourceAttributes('uri:anus', 'Anus', ['text/html'], 'The anus, rectum, and other parts of the bum.',
+            ['Buttman'], ['butts', 'henies', 'booties'], ['Butts and Co Publishing'], ['Dr Eugene Bottomman, III'],
+            [], ['reference'], ['The Big Book of Booty'], ['en'], ['Buttholes and other oddities'],
+            ['anatomy'], ['Cannot touch this'], ['system.buttServer'], 'granule', 'system.buttServer',
+            ['http://butt.info/butt'])
+        doc = xml.dom.minidom.getDOMImplementation().createDocument(None, None, None)
+        node = a.toXML(doc)
+        childElements = [n.nodeName for n in node.childNodes]       
+        self.assertEquals([u'Identifier', u'Title', u'Format', u'Description', u'Creator', u'Subject', u'Subject',
+            u'Subject', u'Publisher', u'Contributor', u'Type', u'Source', u'Language', u'Relation', u'Coverage',
+            u'Rights', u'resContext', u'resAggregation', u'resClass', u'resLocation'], childElements)
+    
+    def testInstances(self):
+        '''Test to ensure instances don't share instance data.
+        '''
+        a = ResourceAttributes()
+        b = ResourceAttributes()
+        a.formats.append('text/xml')
+        a.creators.append('Dennis Moore')
+        a.subjects.append('Silliness')
+        a.publishers.append('BBC')
+        a.contributors.append('Nigel')
+        a.types.append('Video')
+        a.languages.append('en')
+        a.relations.append('Fawlty Towers')
+        a.coverages.append('1970')
+        a.rights.append('Abused')
+        a.contexts.append('humor')
+        a.locations.append('http://bbc.co.uk/')
+        self.assertNotEquals(a.formats, b.formats)
+        self.assertNotEquals(a.creators, b.creators)
+        self.assertNotEquals(a.subjects, b.subjects)
+        self.assertNotEquals(a.publishers, b.publishers)
+        self.assertNotEquals(a.contributors, b.contributors)
+        self.assertNotEquals(a.types, b.types)
+        self.assertNotEquals(a.languages, b.languages)
+        self.assertNotEquals(a.relations, b.relations)
+        self.assertNotEquals(a.coverages, b.coverages)
+        self.assertNotEquals(a.rights, b.rights)
+        self.assertNotEquals(a.contexts, b.contexts)
+        self.assertNotEquals(a.locations, b.locations)
+    
+
+class ProfileTest(unittest.TestCase):
+    '''Unit test for class Profile.
+    '''
+    def testCmp(self):
+        a = Profile()
+        b = Profile()
+        self.assertEquals(a, b)
+        
+    def testXML(self):
+        '''Test XML serialization and recomposition from XML.
+        '''
+        a = Profile()
+        doc = xml.dom.minidom.getDOMImplementation().createDocument(None, None, None)
+        node = a.toXML(doc)
+        b = Profile(node=node)
+        self.assertEquals(a, b)
+
+        x = UnspecifiedProfileElement('tastiness', 'How tasty it was', 'char', 'subjective', ['yumminess'],
+            'This is highly subjective.')
+        y = EnumeratedProfileElement('meal', 'What meal was eaten', 'char', 'meal', ['serving'], 'Typical values',
+            ['Breakfast', 'Brunch', 'Lunch', 'Dinner'])
+        z = RangedProfileElement('spicyness', 'How spicy it was', 'float', 'scovilles', ['piquancy'],
+            'Hotter the better, I say', 0.0, 1000000.0)
+        a.profElements['tastiness'], a.profElements['meal'], a.profElements['spicyness'] = x, y, z
+        node = a.toXML(doc)
+        b = Profile(node=node)
+        self.assertEquals(a, b)
+
+    def testInstances(self):
+        '''Test to ensure isntances don't share isntance data.
+        '''
+        a = Profile()
+        b = Profile()
+        self.assertEquals(a, b)
+        a.profElements['a'] = 'b'
+        self.assertNotEquals(a, b)
+    
+
+def test_suite():
+    '''Make the test suite.
+    '''
+    import doctest
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(ProfileAttributesTest))
+    suite.addTest(unittest.makeSuite(ResourceAttributesTest))
+    suite.addTest(unittest.makeSuite(ProfileTest))
+    return suite
+    
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
diff --git a/0.8.1-rc1/agility/oodt/tests/queryTest.py b/0.8.1-rc1/agility/oodt/tests/queryTest.py
new file mode 100644
index 0000000..20d6f32
--- /dev/null
+++ b/0.8.1-rc1/agility/oodt/tests/queryTest.py
@@ -0,0 +1,341 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+'''Unit tests for the query module.
+
+This module tests various query classes and the query expression parser.
+'''
+
+__docformat__ = 'restructuredtext'
+
+import unittest, xml.dom, oodt.xmlutils
+from oodt.query import QueryElement, QueryHeader, QueryResult, Query, _parseQuery, ExpressionParseError
+
+class QueryElementTest(unittest.TestCase):
+    '''Test the `QueryElement` class.
+    '''
+    def testDefaults(self):
+        '''Test to see if defaults are reasonable.
+        '''
+        qe = QueryElement()
+        self.assertEqual('UNKNOWN', qe.role)
+        self.assertEqual('UNKNOWN', qe.value)
+
+    def testArgs(self):
+        '''Test to see if initializer arguments are used.
+        '''
+        qe = QueryElement(role='role', value='value')
+        self.assertEqual('role', qe.role)
+        self.assertEqual('value', qe.value)
+    
+    def testComparisons(self):
+        '''Test comparison operators.
+        '''
+        a = QueryElement('a', '1')
+        b = QueryElement('a', '1')
+        c = QueryElement('b', '1')
+        d = QueryElement('a', '2')
+        self.assertEqual(a, a)
+        self.assertEqual(a, b)
+        self.assertEqual(b, a)
+        self.assertNotEqual(a, c)
+        self.assertNotEqual(c, a)
+        self.assertNotEqual(a, d)
+        self.assertNotEqual(d, a)
+        self.assertNotEqual(c, d)
+        self.assert_(a <= a)
+        self.assert_(a <= c)
+        self.assert_(a < c)
+        self.assert_(a <= d)
+        self.assert_(a < d)
+    
+    def testBadArgs(self):
+        '''Test reactions to bad arugments.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        self.assertRaises(ValueError, QueryElement, node=doc.createElement('notAQueryElement'))
+    
+    def testXML(self):
+        '''Test XML serialization.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        q1 = QueryElement(role='a', value='1')
+        root = q1.toXML(doc)
+        self.assertEqual('queryElement', root.nodeName)
+        for child in root.childNodes:
+            if 'tokenRole' == child.nodeName:
+                self.assertEquals('a', oodt.xmlutils.text(child))
+            elif 'tokenValue' == child.nodeName:
+                self.assertEquals('1', oodt.xmlutils.text(child))
+            else:
+                self.fail('Unknown node "' + child.nodeName + '" in XML result')
+
+        q2 = QueryElement(node=root)
+        self.assertEqual(q1, q2)
+
+        root = doc.createElement('queryElement')
+        doc.appendChild(root)
+        elem = doc.createElement('tokenRole')
+        root.appendChild(elem)
+        elem.appendChild(doc.createTextNode('a'))
+        elem = doc.createElement('tokenValue')
+        root.appendChild(elem)
+        elem.appendChild(doc.createTextNode('2'))
+        q3 = QueryElement(node=root)
+        self.assertNotEqual(q1, q3)
+    
+
+_QUERY_HEADER_ATTRS = {
+    'queryId': 'id',
+    'queryTitle': 'title',
+    'queryDesc': 'desc',
+    'queryType': 'type',
+    'queryStatusId': 'status',
+    'querySecurityType': 'security',
+    'queryRevisionNote': 'rev',
+    'queryDataDictId': 'dataDict'
+}
+
+class QueryHeaderTest(unittest.TestCase):
+    '''Unit test for the `QueryHeader` class.
+    '''
+    def testDefaults(self):
+        '''Test if defaults are reasonable.
+        '''
+        qh = QueryHeader()
+        self.assertEqual('UNKNOWN', qh.id)
+        self.assertEqual('UNKNOWN', qh.title)
+        self.assertEqual('UNKNOWN', qh.desc)
+        self.assertEqual('QUERY', qh.type)
+        self.assertEqual('ACTIVE', qh.status)
+        self.assertEqual('UNKNOWN', qh.security)
+        self.assertEqual('2005-10-01 SCK v0.0.0 Under Development', qh.rev)
+        self.assertEqual('UNKNOWN', qh.dataDict)
+
+    def testArgs(self):
+        '''Test if initializer arguments are used.
+        '''
+        qh = QueryHeader('id', 'title', 'desc', 'type', 'status', 'security', 'rev', 'dataDict')
+        self.assertEqual(qh.id, 'id')
+        self.assertEqual(qh.title, 'title')
+        self.assertEqual(qh.desc, 'desc')
+        self.assertEqual(qh.type, 'type')
+        self.assertEqual(qh.status, 'status')
+        self.assertEqual(qh.security, 'security')
+        self.assertEqual(qh.rev, 'rev')
+        self.assertEqual(qh.dataDict, 'dataDict')
+
+    def testBadArgs(self):
+        '''Test reaction to bad arguments.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        self.assertRaises(ValueError, QueryHeader, node=doc.createElement('notAQueryHeader'))
+
+    def testXML(self):
+        '''Test XML serialization.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        q1 = QueryHeader('id', 'title', 'desc', 'type', 'status', 'security', 'rev', 'dataDict')
+        root = q1.toXML(doc)
+        self.assertEqual('queryAttributes', root.nodeName)
+        for child in root.childNodes:
+            self.check(child.nodeName, oodt.xmlutils.text(child))
+        q2 = QueryHeader(node=root)
+        self.assertEqual(q1, q2)
+
+    def check(self, name, value):
+        '''Check if the given tag name is valid.
+        '''
+        if name in _QUERY_HEADER_ATTRS:
+            self.assertEqual(value, _QUERY_HEADER_ATTRS[name])
+        else:
+            fail('Unknown element ' + name + ' in query header')
+    
+
+class QueryResultTest(unittest.TestCase):
+    '''Unit test for the `QueryResults` class.
+    '''
+    def testDefaults(self):
+        '''Test if defaults are reasonable.
+        '''
+        qr = QueryResult()
+        self.assertEquals(0, len(qr.results))
+        self.assertEquals(0, len(qr))
+        self.assertRaises(IndexError, qr.__getitem__, 0)
+
+    def testBadArgs(self):
+        '''Test reaction to bad arguments.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        self.assertRaises(ValueError, QueryResult, node=doc.createElement('notAQueryResult'))
+
+    def testXML(self):
+        '''Test XML serialization.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        q1 = QueryResult()
+        root = q1.toXML(doc)
+        self.assertEqual('queryResultSet', root.nodeName)
+        q2 = QueryResult(node=root)
+        self.assertEqual(q1, q2)
+    
+
+class QueryTest(unittest.TestCase):
+    '''Unit test for the `Query` class.
+    '''
+    def testDefaults(self):
+        '''Test if defaults are reasonable.
+        '''
+        q = Query()
+        self.assertEqual(QueryHeader(), q.header)
+        self.assertEqual('ATTRIBUTE', q.resultModeID)
+        self.assertEqual('BROADCAST', q.propType)
+        self.assertEqual('N/A', q.propLevels)
+        self.assertEqual(1, q.maxResults)
+        self.assertEqual(0, len(q.mimeAccept))
+
+    def testParser(self):
+        '''Test the query expresion parser.
+        '''
+        # Empty
+        self.assertEqual(([], []), _parseQuery(''))
+        
+        # Simple
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='1'),
+            QueryElement(role='RELOP', value='EQ') ], []), _parseQuery('x = 1'))
+
+        # Logical or
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='1'),      
+            QueryElement(role='RELOP', value='LT'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='-2'), QueryElement(role='RELOP', value='GT'),
+            QueryElement(role='LOGOP', value='OR') ], []), _parseQuery('x < 1 or y > -2'))
+
+        # Logical and has higher precendence
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='1'),
+            QueryElement(role='RELOP', value='LE'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='2'), QueryElement(role='RELOP', value='GE'),
+            QueryElement(role='elemName', value='z'), QueryElement(role='LITERAL', value='-3.96'),
+            QueryElement(role='RELOP', value='NE'), QueryElement(role='LOGOP', value='AND'),
+            QueryElement(role='LOGOP', value='OR') ], []), _parseQuery('x <= 1 | y >= 2 and z != -3.96'))
+        
+        # Logical or has lower precedence
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='1'),
+            QueryElement(role='RELOP', value='LT'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='2'), QueryElement(role='RELOP', value='GT'),
+            QueryElement(role='LOGOP', value='AND'), QueryElement(role='elemName', value='z'),
+            QueryElement(role='LITERAL', value='3'), QueryElement(role='RELOP', value='NE'), 
+            QueryElement(role='LOGOP', value='OR') ], []), _parseQuery('x LT 1 & y GT 2 or z NE 3'))
+
+        # Parenthesis
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='1'),
+            QueryElement(role='RELOP', value='LE'), QueryElement(role='elemName', value='y'), \
+            QueryElement(role='LITERAL', value='2'), QueryElement(role='RELOP', value='GE'),
+            QueryElement(role='LOGOP', value='OR'), QueryElement(role='elemName', value='z'),
+            QueryElement(role='LITERAL', value='3'), QueryElement(role='RELOP', value='EQ'), 
+            QueryElement(role='LOGOP', value='AND') ], []), _parseQuery('(x LE 1 or y GE 2) and z EQ 3'))
+
+        # Logical not
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='1'),
+            QueryElement(role='RELOP', value='LE'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='2'), QueryElement(role='RELOP', value='GE'),
+            QueryElement(role='LOGOP', value='OR'), QueryElement(role='LOGOP', value='NOT'),
+            QueryElement(role='elemName', value='z'), QueryElement(role='LITERAL', value='3'),
+            QueryElement(role='RELOP', value='EQ'), QueryElement(role='LOGOP', value='NOT'),
+            QueryElement(role='LOGOP', value='AND') ], []), _parseQuery('not (x LE 1 or y GE 2) and ! z EQ 3'))
+
+        # Quoted strings
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='Fish Poop'),
+            QueryElement(role='RELOP', value='EQ'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='Monkey Poop'), QueryElement(role='RELOP', value='EQ'),
+            QueryElement(role='LOGOP', value='AND') ], []),
+            _parseQuery("""x = "Fish Poop" and y = 'Monkey Poop'"""))
+                
+        # RETURN elements
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='Fish Poop'),
+            QueryElement(role='RELOP', value='EQ'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='Monkey Poop'), QueryElement(role='RELOP', value='EQ'),
+            QueryElement(role='LOGOP', value='AND') ], [QueryElement(role='elemName', value='fish')]),
+            _parseQuery("""x = "Fish Poop" and RETURN > fish and y = 'Monkey Poop'"""))
+        
+        # RETURN at beginning and middle
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='Fish Poop'),
+            QueryElement(role='RELOP', value='EQ'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='Monkey Poop'), QueryElement(role='RELOP', value='EQ'),
+            QueryElement(role='LOGOP', value='AND') ], [QueryElement(role='elemName', value='fish'),
+            QueryElement(role='elemName', value='poop')]),
+            _parseQuery("""RETURN < fish and x = "Fish Poop" and RETURN > poop and y = 'Monkey Poop'"""))
+            
+        # Bad expressions
+        for expr in ('heya', 'RETURN =', 'AND', 'LAT ~ fish', 'NOT', '(', ')'):
+            self.assertRaises(ExpressionParseError, _parseQuery, expr)
+            
+        # Unusual symbols
+        self.assertEqual(([QueryElement('elemName', 'DATA_SET_ID'), QueryElement('LITERAL', 'ARCB-L-RTLS-3-70CM-V1.0'),
+            QueryElement('RELOP', 'EQ')], []), _parseQuery('''DATA_SET_ID = ARCB-L-RTLS-3-70CM-V1.0'''))
+        self.assertEqual(([QueryElement('elemName', 'file'), QueryElement('LITERAL', '/usr/local/bin/poop'),
+            QueryElement('RELOP', 'EQ')], []), _parseQuery('''file = /usr/local/bin/poop'''))
+        self.assertEqual(([QueryElement('elemName', 'start_time'), QueryElement('LITERAL', '2006-02-06T13:12:13'),
+            QueryElement('RELOP', 'EQ')], []), _parseQuery('''start_time = 2006-02-06T13:12:13'''))
+    
+    def testCmp(self):
+        '''Test comparison operators.
+        '''
+        a = Query('lat > 3 and lon < -92.6')
+        b = Query('lat > 3 and lon < -92.6')
+        c = Query('lat < 3 and lon > -92.6')
+        self.assert_(a == a)
+        self.assert_(a == b)
+        self.assert_(a < c)
+        self.assert_(c > a)
+        self.assert_(a <= b)
+        self.assert_(a >= b)
+        self.assert_(a <= c)
+        self.assert_(c >= a)
+        self.assert_(c != a)
+
+    def testXML(self):
+        '''Test XML serialization.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        q1 = Query('lat > 3 and lon < -92.6')
+        root = q1.toXML(doc)
+        self.assertEqual('query', root.nodeName)
+        q2 = Query(node=root)
+        self.assertEqual(q1, q2)
+    
+
+def test_suite():
+    '''Create the suite of tests.
+    '''
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(QueryElementTest))
+    suite.addTest(unittest.makeSuite(QueryHeaderTest))
+    suite.addTest(unittest.makeSuite(QueryResultTest))
+    suite.addTest(unittest.makeSuite(QueryTest))
+    return suite
+    
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
+    
diff --git a/0.8.1-rc1/agility/oodt/tests/xmlutilsTest.py b/0.8.1-rc1/agility/oodt/tests/xmlutilsTest.py
new file mode 100644
index 0000000..e8f64a4
--- /dev/null
+++ b/0.8.1-rc1/agility/oodt/tests/xmlutilsTest.py
@@ -0,0 +1,109 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+'''Unit tests for the `xmlutils` module.
+'''
+
+__docformat__ = 'restructuredtext'
+
+import unittest, xml.dom, oodt.xmlutils
+from oodt.xmlutils import DocumentableField
+
+class XMLTest(unittest.TestCase):
+    '''Unit test the XML utilities.
+    '''
+    def testText(self):
+        '''Test getting text from nodes.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # ns URI, qual name, doctype
+        root = doc.createElement('root')
+        root.appendChild(doc.createTextNode('Hello'))
+        child = doc.createElement('child')
+        root.appendChild(child)
+        root.appendChild(doc.createCDATASection('world'))
+        child.appendChild(doc.createTextNode('cruel'))
+        empty = doc.createElement('empty')
+        root.appendChild(empty)
+
+        self.assertEquals('cruel', oodt.xmlutils.text(child))
+        self.assertEquals(0, len(oodt.xmlutils.text(empty)))
+        self.assertEquals('Hellocruelworld', oodt.xmlutils.text(root))
+    
+    def testAdds(self):
+        '''Test adding things to nodes.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # ns URI, qual name, doctype
+        root = doc.createElement('root')
+
+        oodt.xmlutils.add(root, 'first')
+        self.assertEquals(0, len(oodt.xmlutils.text(root)))
+        oodt.xmlutils.add(root, 'second', 'with text')
+        self.assertEquals('with text', oodt.xmlutils.text(root))
+        
+        oodt.xmlutils.add(root, 'number', [str(i) for i in range(1, 4)])
+        self.assertEquals('with text123', oodt.xmlutils.text(root))
+    
+
+class DocumentableTest(unittest.TestCase):
+    '''Unit test the `Documentable` and `DocumentableField` classes.
+    '''
+    def testIt(self):
+        '''Test the `Documentable` and `DocumentableField` classes.
+        '''
+        class X(oodt.xmlutils.Documentable):
+            def __init__(self, mission='UNK', target='UNK', measurements=[], node=None):
+                self.mission, self.target, self.measurements = mission, target, measurements
+                if node is not None:
+                    self.parse(node)
+            def computeValueFromDocument(self, attrName, text):
+                if attrName == 'measurements':
+                    return int(text)
+                else:
+                    return text
+            def getDocumentElementName(self):
+                return 'X'
+            def getDocumentableFields(self):
+                return (DocumentableField('mission', u'MISSION', DocumentableField.SINGLE_VALUE_KIND),
+                DocumentableField('target', u'TARGET', DocumentableField.SINGLE_VALUE_KIND),
+                DocumentableField('measurements', u'MZR', DocumentableField.MULTI_VALUED_KIND))
+            def __eq__(self, other):
+                return (self.mission == other.mission and self.target == other.target
+                    and cmp(self.measurements, other.measurements) == 0)
+            def __str__(self):
+                return '%s,%s:%s' % (self.mission, self.target, self.measurements)
+        a = X('Explorer', 'Moon', [1, 2, 3])
+        doc = xml.dom.getDOMImplementation().createDocument(None, None, None)
+        node = a.toXML(doc)
+        b = X(node=node)
+        self.assertEquals(a, b)
+    
+
+def test_suite():
+    '''Create the suite of tests.
+    '''
+    import doctest
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(XMLTest))
+    suite.addTest(unittest.makeSuite(DocumentableTest))
+    suite.addTest(doctest.DocTestSuite(oodt.xmlutils))
+    return suite
+    
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
diff --git a/0.8.1-rc1/agility/oodt/webgrid.py b/0.8.1-rc1/agility/oodt/webgrid.py
new file mode 100644
index 0000000..8f56fe1
--- /dev/null
+++ b/0.8.1-rc1/agility/oodt/webgrid.py
@@ -0,0 +1,226 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+'''Agile Web Grid.  HTTP-based profile and product servers.
+'''
+
+__docformat__ = 'restructuredtext'
+
+from oodt.query import Query
+from xml.dom.minidom import parseString, getDOMImplementation
+from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
+import cgi, os, shutil, stat
+
+_validKinds = ('profile', 'product')
+_doc = getDOMImplementation().createDocument(None, None, None) # qname, nsuri, doctype
+    
+class WebGridRequestHandler(BaseHTTPRequestHandler):
+    '''HTTP request handler for Web-Grid requests.  This request handler accepts GET
+    or POST requests and directs them to profile or product handlers.  Additionally,
+    requests to install new handlers, to list currently installed handlers, and to
+    remove handlers by ID are supported.
+    '''
+    def do_POST(self):
+        '''Handle a POST.
+        '''
+        try:
+            length = int(self.headers['content-length'])
+            kind = self.headers['content-type']
+            if kind.endswith('www-form-urlencoded'):
+                if length > 0:
+                    params = cgi.parse_qs(self.rfile.read(length), True, True) # Keep blanks, strict parse
+                else:
+                    params = {}
+                self.__execute(self.path, params)
+            else:
+                raise ValueError('Unknown encoding "%s"' % kind)
+        except Exception, e:
+            self.send_error(500, str(e))
+    
+    def do_GET(self):
+        '''Handle a GET.
+        '''
+        try:
+            index = self.path.find('?')
+            if index >= 0:
+                params = cgi.parse_qs(self.path[index+1:], True, True) # Keep blanks, strict parse
+                path = self.path[0:index]
+            else:
+                params, path = {}, self.path
+            self.__execute(path, params)
+        except Exception, e:
+            self.send_error(500, str(e))
+    
+    def __execute(self, path, params):
+        '''Execute an HTTP request.
+        '''
+        components = path.split('/')
+        if len(components) == 3:
+            context, command = components[1], components[2]
+            if context != self.server.serverID:
+                raise ValueError('Unknown server ID "%s"' % context)
+            func = getattr(self, command)
+            if callable(func):
+                func(params)
+                return
+        raise KeyError('Unknown command')
+    
+    def echo(self, params):
+        '''Debugging method that echoes back the request parameters.
+        '''
+        u = unicode(params)
+        self.send_response(200)
+        self.send_header('Content-type', 'text/plain;charset=utf-8')
+        self.send_header('Content-length', str(len(u)))
+        self.end_headers()
+        self.wfile.write(u)
+    
+    def sendEmptyResponse(self):
+        '''Send an empty response to the HTTP client.
+        '''
+        self.send_response(200)
+        self.send_header('Content-type', 'text/plain;charset=utf-8')
+        self.send_header('Content-length', '0')
+        self.end_headers()
+    
+    def install(self, params):
+        '''Install a new handler.  This will overwrite existing handlers with the
+        same ID.
+        '''
+        handlers = self.server.getHandlers(params['kind'][0])
+        globs = dict(globals())
+        del globs['__name__']
+        # TODO: use rexec or otherwise limit the code than can be uploaded.
+        exec params['code'][0] in globs, globs
+        handlers[params['id'][0]] = globs['handler']
+        self.sendEmptyResponse()
+    
+    def remove(self, params):
+        '''Remove an existing handler.
+        '''
+        handlers = self.server.getHandlers(params['kind'][0])
+        del handlers[params['id'][0]]
+        self.sendEmptyResponse()
+    
+    def list(self, params):
+        '''List installed handlers.
+        '''
+        handlers = {}
+        for kind in _validKinds:
+            handlers[kind] = self.server.getHandlers(kind).keys()
+        handlers = unicode(handlers)
+        self.send_response(200)
+        self.send_header('Content-type', 'text/plain;charset=utf-8')
+        self.send_header('Content-length', str(len(handlers)))
+        self.end_headers()
+        self.wfile.write(handlers)
+    
+    def __createQuery(self, params):
+        '''Create a Query from the request parameters.  This method prefers the
+        xmlq parameter and parses it as an XML document and into a Query object.
+        However, if it's not provided, or fails to parse, it'll use the q parameter,
+        which is expected to be just a query expression.
+        '''
+        try:
+            doc = parseString(params['xmlq'][0])
+            return Query(node=doc.documentElement)
+        except KeyError:
+            return Query(params['q'][0])
+    
+    def sendProduct(self, match):
+        '''Send a matching product.
+        '''
+        self.send_response(200)
+        self.send_header('Content-type', match.contentType)
+        self.send_header('Content-length', str(match.length))
+        self.end_headers()
+        shutil.copyfileobj(match.data, self.wfile)
+        self.log_request(200, match.length)
+    
+    def prod(self, params):
+        '''Handle a product query.
+        '''
+        query = self.__createQuery(params)
+        for handler in self.server.getHandlers('product'):
+            matches = handler.query(query)
+            if len(matches) > 0:
+                self.sendProduct(matches[0])
+        self.send_error(404, 'No matching products')
+    
+    def prof(self, params):
+        '''Handle a profile query.
+        '''
+        query = self.__createQuery(params)
+        tmp = os.tmpfile()
+        tmp.writelines((u'<?xml version="1.0" encoding="UTF-8"?>\n',
+            u'<!DOCTYPE profiles PUBLIC "-//JPL//DTD Profile 1.1//EN"\n',
+            u'  "http://oodt.jpl.nasa.gov/grid-profile/dtd/prof.dtd">\n',
+            u'<profiles>\n'))
+        for handler in self.server.getHandlers('profile').itervalues():
+            for profile in handler.query(query):
+                node = profile.toXML(_doc)
+                tmp.write(node.toxml())
+        tmp.write(u'</profiles>')
+        tmp.flush()
+        tmp.seek(0L)
+        self.send_response(200)
+        self.send_header('Content-type', 'text/xml;charset=utf-8')
+        size = os.fstat(tmp.fileno())[stat.ST_SIZE]
+        self.send_header('Content-length', str(size))
+        self.end_headers()
+        shutil.copyfileobj(tmp, self.wfile)
+        self.log_request(200, size)
+    
+
+class WebGridServer(HTTPServer):
+    '''Web grid HTTP server.  This server handles incoming HTTP requests and directs them to a
+    WebGridRequestHandler.  It also contains the server's ID, and the sequences of profile and
+    product handlers.
+    '''
+    def __init__(self, addr, serverID):
+        '''Initialize by saving the server ID and creating empty sequences of profile
+        and product handlers.
+        '''
+        HTTPServer.__init__(self, addr, WebGridRequestHandler)
+        self.serverID = serverID
+        self.__handlers = {}
+        for kind in _validKinds:
+            self.__handlers[kind] = {}
+    
+    def getHandlers(self, kind):
+        '''Get the map of handlers for the given kind, which is either "product" or "profile".
+        '''
+        if kind not in _validKinds:
+            raise ValueError('Invalid handler kind "%s"' % kind)
+        return self.__handlers[kind]
+    
+
+def _main():
+    '''Run the web grid server.
+    '''
+    import sys
+    try:
+        serverID = sys.argv[1]
+    except IndexError:
+        serverID = 'oodt'
+    listenAddr = ('', 7576)
+    httpd = WebGridServer(listenAddr, serverID)
+    httpd.serve_forever()
+    
+
+if __name__ == '__main__':
+    _main()
diff --git a/0.8.1-rc1/agility/oodt/xmlutils.py b/0.8.1-rc1/agility/oodt/xmlutils.py
new file mode 100644
index 0000000..44e7ec1
--- /dev/null
+++ b/0.8.1-rc1/agility/oodt/xmlutils.py
@@ -0,0 +1,209 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+'''Object Oriented Data Technology XML utilities. These are some simple utilities
+that make working with rather obtuse DOM API less painful.
+'''
+
+__docformat__ = 'restructuredtext'
+
+import string
+import xml.dom
+    
+def text(node):
+    '''Return the text under the given node.  Text and CDATA nodes simply return
+    their content.  Otherwise, text is gathered in a depth-first left-to-right
+    traversal of the node, building up text as we go along.
+    
+    >>> import xml.dom
+    >>> domImpl = xml.dom.getDOMImplementation()
+    >>> doc = domImpl.createDocument(None, None, None)
+    >>> root = doc.createElement('root')
+    >>> root.appendChild(doc.createTextNode('alpha')) # doctest: +ELLIPSIS
+    <DOM Text node...>
+    >>> text(root)
+    'alpha'
+    >>> child = root.appendChild(doc.createElement('child'))
+    >>> text(child.appendChild(doc.createCDATASection('beta')))
+    'beta'
+    >>> text(root)
+    'alphabeta'
+    '''
+    strings = []
+    _text0(node, strings)
+    return string.join(strings, '') # no separator
+    
+
+def _text0(node, strings):
+    '''Add the text under the given node to the list of strings.
+    '''
+    if node.nodeType == xml.dom.Node.CDATA_SECTION_NODE:
+        strings.append(node.nodeValue)
+    elif node.nodeType == xml.dom.Node.TEXT_NODE:
+        strings.append(node.nodeValue)
+    for child in node.childNodes:
+        _text0(child, strings)
+    
+
+def add(node, elementName, value=None):
+    '''Add an element under the given node.  Optionally, the value text is added to the element.
+    Returns the original node, handy for chaining calls together.  If the value is a sequence,
+    then the element is added multiple times for each item in the sequence, using the item
+    as the text.
+
+    >>> from xml.dom.minidom import getDOMImplementation
+    >>> doc = getDOMImplementation().createDocument(None, None, None)
+    >>> root = doc.createElement('root')
+    >>> root.toxml()
+    '<root/>'
+    >>> add(root, 'empty').toxml()
+    '<root><empty/></root>'
+    >>> add(root, 'full', 'of text').toxml()
+    '<root><empty/><full>of text</full></root>'
+    >>> add(root, 'item', [str(i) for i in range(1, 4)]).toxml()
+    '<root><empty/><full>of text</full><item>1</item><item>2</item><item>3</item></root>'
+    '''
+    owner = node.ownerDocument
+    if isinstance(value, basestring):
+        elem = owner.createElement(elementName)
+        node.appendChild(elem)
+        elem.appendChild(owner.createTextNode(value))
+    elif value is not None:
+        for i in value:
+            elem = owner.createElement(elementName)
+            node.appendChild(elem)
+            elem.appendChild(owner.createTextNode(i))
+    else:
+        node.appendChild(owner.createElement(elementName))
+    return node
+    
+
+class DocumentableField(object):
+    '''A documentable field is an attribute of an object that we can serialize into XML.
+    '''
+    SINGLE_VALUE_KIND = 1
+    MULTI_VALUED_KIND = 2
+    DOCUMENTABLE_KIND = 3
+
+    def __init__(self, attrName, elemName, kind):
+        '''Initialize a documentable field with attrName (name of attribute in object),
+        elemName (name to use for XML element) and kind, which is one of the DOCUMENTABLE_*
+        constants.
+        '''
+        self.attrName = attrName
+        self.elemName = elemName
+        if kind not in (DocumentableField.SINGLE_VALUE_KIND, DocumentableField.MULTI_VALUED_KIND,
+            DocumentableField.DOCUMENTABLE_KIND):
+            raise ValueError('Invalid kind %d' % kind)
+        self.kind = kind
+    
+    def __cmp__(self, other):
+        attrName = cmp(self.attrName, other.attrName)
+        if attrName < 0:
+            return -1
+        elif attrName == 0:
+            elemName = cmp(self.elemName, other.elemName)
+            if elemName < 0:
+                return -1
+            elif elemName == 0:
+                return cmp(self.kind, other.kind)
+        return 1
+    
+    def __hash__(self):
+        return hash(self.attrName) ^ hash(self.elemName) ^ self.kind
+    
+
+class Documentable(object):
+    '''An object that can be documented into XML and parsed from an XML document.
+    '''
+    def getDocumentElementName(self):
+        '''Get the XML tag name.  Subclasses must override this
+        otherwise they get the tag name `UNKNOWN`.
+        '''
+        return 'UNKNOWN'
+        
+    def getDocumentableFields(self):
+        '''Get the sequence of documentable attributes.  Subclasses should override this
+        with a sequence of `DocumentableField` objects.  By default, we return an empty
+        sequence.
+        '''
+        return []
+    
+    def toXML(self, owner):
+        '''Convert this object into XML owned by the given `owner` document.
+        '''
+        root = owner.createElement(self.getDocumentElementName())
+        for df in self.getDocumentableFields():
+            if df.kind == DocumentableField.SINGLE_VALUE_KIND:
+                add(root, df.elemName, str(getattr(self, df.attrName)))
+            elif df.kind == DocumentableField.MULTI_VALUED_KIND:
+                add(root, df.elemName, [str(value) for value in getattr(self, df.attrName)])
+            else:
+                root.appendChild(getattr(self, df.attrName).toXML(owner))
+        return root
+    
+    def computeValueFromDocument(self, attrName, text):
+        '''Compute a value for the attribute named `attrName` from the
+        XML text representation `text`.  Subclasses may wish to
+        override this in order to provide custom typing for certain
+        attributes, such as returning an integer or datetime value by
+        parsing the text.  By default, the `text` is returned
+        unmodified as a string.
+        '''
+        return text
+    
+    def parse(self, node):
+        '''Initialize this object from the given XML DOM `node`.
+        '''
+        if node.nodeName != self.getDocumentElementName():
+            raise ValueError('Expected %s element but got %s' % (self.getDocumentElementName(), node.nodeName))
+        fieldMap = dict(zip([i.elemName for i in self.getDocumentableFields()], self.getDocumentableFields()))
+        for child in filter(lambda n: n.nodeType == xml.dom.Node.ELEMENT_NODE, node.childNodes):
+            name = child.nodeName
+            if name in fieldMap:
+                field = fieldMap[name]
+                if field.kind == DocumentableField.SINGLE_VALUE_KIND:
+                    setattr(self, field.attrName, self.computeValueFromDocument(field.attrName, text(child)))
+                elif field.kind == DocumentableField.MULTI_VALUED_KIND:
+                    if not hasattr(self, field.attrName):
+                        setattr(self, field.attrName, [])
+                    getattr(self, field.attrName).append(self.computeValueFromDocument(field.attrName,
+                        text(child)))
+                else:
+                    getattr(self, field.attrName).parse(child)
+    
+    def __cmp__(self, other):
+        '''The documentable fields provide a bonus: we can use them to do comparisons.
+        '''
+        for field in self.getDocumentableFields():
+            attrName = field.attrName
+            mine = getattr(self, attrName)
+            others = getattr(other, attrName)
+            rc = cmp(mine, others)
+            if rc < 0:
+                return -1
+            elif rc > 0:
+                return 1
+        return 0
+    
+    def __hash__(self):
+        '''The documentable fields provide another bonus: we can use them
+        to do hashing.
+        '''
+        return reduce(lambda x, y: hash(x) ^ hash(y), [getattr(self, i.attrName) for i in self.getDocumentableFields()],
+            0x55555555)
+    
\ No newline at end of file
diff --git a/0.8.1-rc1/agility/setup.cfg b/0.8.1-rc1/agility/setup.cfg
new file mode 100644
index 0000000..51418d4
--- /dev/null
+++ b/0.8.1-rc1/agility/setup.cfg
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+[egg_info]
+tag_build = .dev
+tag_svn_revision = 1
diff --git a/0.8.1-rc1/agility/setup.py b/0.8.1-rc1/agility/setup.py
new file mode 100644
index 0000000..ac9c52b
--- /dev/null
+++ b/0.8.1-rc1/agility/setup.py
@@ -0,0 +1,98 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+import os.path
+from ez_setup import use_setuptools
+use_setuptools()
+from setuptools import find_packages, setup
+
+
+# Package data
+# ------------
+
+_name         = 'oodt'
+_version      = '0.8'
+_description  = 'Apache OODT'
+_url          = 'http://oodt.apache.org/'
+_downloadURL  = 'http://pypi.python.org/pypi/oodt/'
+_author       = 'Sean Kelly'
+_authorEmail  = 'kelly@apache.org'
+_license      = 'Apache 2.0'
+_namespaces   = []
+_testSuite    = 'oodt.tests.test_suite'
+_zipSafe      = True
+_keywords     = 'data grid discovery query optimization object middleware archive catalog index'
+_requirements = []
+_entryPoints  = {
+    'console_scripts': ['webgrid = oodt.webgrid:_main'],
+}
+_classifiers  = [
+    'Environment :: Console',
+    'Environment :: No Input/Output (Daemon)',
+    'Intended Audience :: Developers',
+    'Intended Audience :: Information Technology',
+    'Intended Audience :: Science/Research',
+    'Topic :: Database :: Front-Ends',
+    'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
+    'Topic :: Internet :: WWW/HTTP :: HTTP Servers',
+    'Topic :: Internet :: Z39.50',
+    'Topic :: Scientific/Engineering',
+    'Development Status :: 5 - Production/Stable',
+    'Environment :: Web Environment',
+    'License :: OSI Approved :: Apache Software License',
+    'Operating System :: OS Independent',
+    'Programming Language :: Python',
+    'Topic :: Internet :: WWW/HTTP',
+    'Topic :: Software Development :: Libraries :: Python Modules',
+]
+
+
+# Setup Metadata
+# --------------
+
+def _read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+_header = '*' * len(_name) + '\n' + _name + '\n' + '*' * len(_name)
+_longDescription = '\n\n'.join([
+    _header,
+    _read('README.txt'),
+    _read('docs', 'INSTALL.txt'),
+    _read('docs', 'HISTORY.txt')
+])
+open('doc.txt', 'w').write(_longDescription)
+
+setup(
+    author=_author,
+    author_email=_authorEmail,
+    classifiers=_classifiers,
+    description=_description,
+    download_url=_downloadURL,
+    entry_points=_entryPoints,
+    include_package_data=True,
+    install_requires=_requirements,
+    keywords=_keywords,
+    license=_license,
+    long_description=_longDescription,
+    name=_name,
+    namespace_packages=_namespaces,
+    packages=find_packages(exclude=['ez_setup']),
+    test_suite=_testSuite,
+    url=_url,
+    version=_version,
+    zip_safe=_zipSafe,
+)
diff --git a/0.8.1-rc1/app/fmbrowser/pom.xml b/0.8.1-rc1/app/fmbrowser/pom.xml
new file mode 100644
index 0000000..21d0c3b
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/pom.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>cas-fm-browser</artifactId>
+  <name>Catalog and Archive File Management Browser</name>
+  <description>The graphical front-end interface to the Catalog and Archive Service. This component
+     provides the user of the CAS File Manager with a graphical environment in which they
+     can view archived products' metadata, query for products with particular metadata, 
+     and export results of queries to the MS Excel(c) file format.</description>
+  <scm>
+   	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/app/fmbrowser</connection>
+   	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/app/fmbrowser</developerConnection>
+   	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/app/fmbrowser</url>
+  </scm>
+  <build>
+    <plugins />
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-metadata</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-filemgr</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.poi</groupId>
+      <artifactId>poi</artifactId>
+      <version>3.2-FINAL</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/bin/filemgr-browser b/0.8.1-rc1/app/fmbrowser/src/main/bin/filemgr-browser
new file mode 100644
index 0000000..f6d3881
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/bin/filemgr-browser
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# init script for XmlRpcFileManager
+#
+# chkconfig: 345 88 22
+# description: CAS File Manager Browser
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+# $Id$
+
+[ -f /etc/sysconfig/java ] && . /etc/sysconfig/java
+#[ -f /etc/sysconfig/cas-filemgr] && . /etc/sysconfig/cas-filemgr
+
+JAVA_HOME=/path/to/java/home
+export JAVA_HOME
+FILEMGR_BROWSER_HOME=..
+export FILEMGR_BROWSER_HOME
+
+PATH=${JAVA_HOME}/bin:${FILEMGR_BROWSER_HOME}/bin:/usr/bin:/bin:/usr/sbin:/sbin
+export PATH
+
+$JAVA_HOME/bin/java -Djava.ext.dirs=${FILEMGR_BROWSER_HOME}/lib \
+  org.apache.oodt.cas.filemgr.browser.system.XmlRpcFilemgrBrowser &
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/controller/TableListener.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/controller/TableListener.java
new file mode 100644
index 0000000..9aeb5d7
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/controller/TableListener.java
@@ -0,0 +1,168 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.controller;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.io.FileOutputStream;
+
+import javax.swing.JFileChooser;
+
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+import org.apache.oodt.cas.filemgr.browser.view.menus.RightClickMenu;
+import org.apache.oodt.cas.filemgr.browser.view.panels.HeaderCell;
+import org.apache.oodt.cas.filemgr.browser.view.panels.HeaderSpacer;
+import org.apache.oodt.cas.filemgr.browser.view.panels.Row;
+import org.apache.oodt.cas.filemgr.browser.view.panels.TablePane;
+
+public class TableListener implements MouseListener, ActionListener {
+
+  private Component caller;
+  private TablePane table;
+  private int mousePos;
+  private RightClickMenu rcMenu;
+
+  public TableListener(TablePane t) {
+    table = t;
+    mousePos = -1;
+    caller = null;
+    rcMenu = new RightClickMenu(this);
+
+  }
+
+  public void mouseClicked(MouseEvent arg0) {
+  }
+
+  public void mouseEntered(MouseEvent arg0) {
+  }
+
+  public void mouseExited(MouseEvent e) {
+  }
+
+  public void mousePressed(MouseEvent e) {
+    caller = e.getComponent();
+    mousePos = e.getX() + caller.getX();
+  }
+
+  public void mouseReleased(MouseEvent e) {
+    if (caller != null) {
+      if (caller instanceof HeaderSpacer) {
+        HeaderSpacer hsCaller = (HeaderSpacer) caller;
+        if (e.getModifiers() == 18
+            && table.hiddenCols.contains(new Integer(hsCaller.getColNum() + 1))) {
+          rcMenu.setUnhideMode();
+          rcMenu.show(caller, e.getX(), e.getY());
+
+        } else {
+          int change = e.getX() + caller.getX() - mousePos;
+          int curWidth = table.header.getWidth(hsCaller.getColNum());
+          table.header.changeWidth(hsCaller.getColNum(), curWidth + change);
+
+          for (int i = 1; i < table.getComponentCount(); i++) {
+            ((Row) table.getComponent(i)).changeWidth(((HeaderSpacer) caller)
+                .getColNum(), curWidth + change + 2);
+          }
+          caller = null;
+        }
+      } else {
+        if (caller instanceof HeaderCell && e.getModifiers() == 18) {
+          rcMenu.setHideMode();
+          rcMenu.show(caller, e.getX(), e.getY());
+
+        }
+      }
+    }
+
+  }
+
+  public void actionPerformed(ActionEvent arg0) {
+    if (arg0.getActionCommand().equals("Hide")) {
+      if (caller != null) {
+        int colNum = ((HeaderCell) caller).getColNum();
+        table.hideColumn(colNum);
+        caller = null;
+      }
+    } else if (arg0.getActionCommand().equals("Unhide")) {
+      if (caller != null) {
+        int colNum = ((HeaderSpacer) caller).getColNum() + 1;
+        table.unhideColumn(colNum);
+        caller = null;
+      }
+    } else if (arg0.getActionCommand().equals("Unhide Columns")) {
+      while (!table.hiddenCols.isEmpty()) {
+        table.unhideColumn((table.hiddenCols.firstElement()).intValue());
+      }
+    } else if (arg0.getActionCommand().equals("Export Table")) {
+
+      final JFileChooser fc = new JFileChooser();
+      int returnVal = fc.showSaveDialog(table);
+      if (returnVal == JFileChooser.APPROVE_OPTION) {
+
+        // write out excel file
+        String fullFileName = (fc.getSelectedFile()).getAbsolutePath();
+        if (!fullFileName.endsWith(".xls"))
+          fullFileName += ".xls";
+
+        HSSFWorkbook wb = new HSSFWorkbook();
+        HSSFSheet sheet = wb.createSheet("results");
+        HSSFRow headerRow = sheet.createRow((short) 0);
+
+        int i = 0;
+        for (int j = 0; j < table.getRow(0).getComponentCount(); j++) {
+          if (!table.hiddenCols.contains(new Integer(j))) {
+            headerRow.createCell((short) i).setCellValue(
+                table.header.getText(j));
+            i++;
+          }
+        }
+
+        for (int k = 0; k < table.getComponentCount() - 1; k++) {
+          HSSFRow row = sheet.createRow((short) k + 1);
+          i = 0;
+          for (int j = 0; j < table.getRow(0).getComponentCount(); j++) {
+            if (!table.hiddenCols.contains(new Integer(j))) {
+              row.createCell((short) i).setCellValue(
+                  (table.getRow(k)).getText(j));
+              i++;
+            }
+          }
+        }
+
+        FileOutputStream fileOut;
+        try {
+
+          fileOut = new FileOutputStream(fullFileName);
+          wb.write(fileOut);
+          fileOut.close();
+
+        } catch (Exception e) {
+          e.printStackTrace();
+        }
+      }
+
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/controller/WindowListener.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/controller/WindowListener.java
new file mode 100644
index 0000000..81fd721
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/controller/WindowListener.java
@@ -0,0 +1,166 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.controller;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JOptionPane;
+
+import org.apache.oodt.cas.filemgr.browser.model.CasDB;
+import org.apache.oodt.cas.filemgr.browser.view.MainWindow;
+import org.apache.oodt.cas.filemgr.browser.view.prompts.ConnectPrompt;
+import org.apache.oodt.cas.filemgr.browser.view.prompts.QueryBuilderPrompt;
+import org.apache.oodt.cas.filemgr.browser.view.prompts.SortPrompt;
+
+public class WindowListener implements ActionListener {
+
+  private MainWindow window;
+  private ConnectPrompt prompt;
+  private SortPrompt sort;
+  private QueryBuilderPrompt query;
+
+  private CasDB db;
+
+  public WindowListener(MainWindow m) {
+    window = m;
+    db = new CasDB();
+  }
+
+  public void actionPerformed(ActionEvent arg0) {
+    if (arg0.getActionCommand().equals("About")) {
+      String aboutInfo = "OODT Catalog and Archive Server File Manger Browser.\n"
+          + "Copyright (c) 2010, Apache Software Foundation.";
+      JOptionPane.showMessageDialog(window, aboutInfo);
+    } else if (arg0.getActionCommand().equals("Query Language")) {
+      String aboutQueryLanguage = "The CAS File Manager Browser uses the Lucene Query Language.\n"
+          + "More Information can be found at:\n"
+          + "http://lucene.apache.org/java/docs/queryparsersyntax.html";
+      JOptionPane.showMessageDialog(window, aboutQueryLanguage);
+    } else if (arg0.getActionCommand().equals("Exit")) {
+      String exitWarning = "Are you sure you want to exit the CAS File Manager Browser?\n"
+          + "All unexported queries will be lost.";
+      int returnVal = JOptionPane.showConfirmDialog(window, exitWarning,
+          "Exit", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
+      if (returnVal == JOptionPane.OK_OPTION) {
+        System.exit(0);
+      }
+    } else if (arg0.getActionCommand().equals("Connect...")) {
+      // this is from the main menu
+      window.bar.changeConnectStatus();
+      prompt = new ConnectPrompt(this);
+      prompt.pack();
+      prompt.setVisible(true);
+    } else if (arg0.getActionCommand().equals("Disconnect")) {
+      String disconnectWarning = "Are you sure you want to disconnect from this File Manager?\n"
+          + "All unexported queries will be lost.";
+      int returnVal = JOptionPane.showConfirmDialog(window, disconnectWarning,
+          "Disconnect", JOptionPane.OK_CANCEL_OPTION,
+          JOptionPane.WARNING_MESSAGE);
+      if (returnVal == JOptionPane.OK_OPTION) {
+        window.bar.changeConnectStatus();
+        db.disconnect();
+        window.mPane.tPane.setBlank();
+        window.qPane.updateTypes(new String[] { "" });
+        window.bPane.changeStatus("Disconnected");
+      }
+    } else if (arg0.getActionCommand().equals("Cancel")) {
+      if (((JButton) arg0.getSource()).getName().equals("ConnectCancel")) {
+        prompt.dispose();
+        window.bar.changeConnectStatus();
+      } else if (((JButton) arg0.getSource()).getName().equals("SortCancel")) {
+        sort.dispose();
+      }
+    } else if (arg0.getActionCommand().equals("Connect")) {
+      // this is from the connect prompt
+      boolean connected = db.connect(prompt.getCASUrl());
+      if (connected) {
+        window.qPane.updateTypes(db.getAvailableTypes());
+        window.bPane.changeStatus("Connected to " + prompt.getCASUrl());
+      } else {
+        window.bar.changeConnectStatus();
+        String errorConnectingString = "Error Connecting to CAS File Manager at this following address:"
+            + prompt.getCASUrl();
+        JOptionPane.showMessageDialog(window, errorConnectingString, "Error",
+            JOptionPane.ERROR_MESSAGE);
+      }
+      prompt.dispose();
+    } else if (arg0.getActionCommand().equals("Sort")) {
+      sort = new SortPrompt(window, this);
+      sort.pack();
+      sort.setVisible(true);
+    } else if (arg0.getActionCommand().equals("Query Builder")) {
+      if (db.isConnected()) {
+        query = new QueryBuilderPrompt(db, this);
+        query.pack();
+        query.setVisible(true);
+      } else {
+        String errorQueryString = "You must connect to a CAS File Manager before using the Query Builder.";
+        JOptionPane.showMessageDialog(window, errorQueryString, "Disconnected",
+            JOptionPane.WARNING_MESSAGE);
+      }
+    } else if (arg0.getActionCommand().equals("OK")) {
+      window.mPane.tPane.sortRows(sort.getSortIndex(), sort.getSortType());
+      sort.dispose();
+    } else if (arg0.getActionCommand().equals("Search")) {
+      if (((JButton) arg0.getSource()).getName().equals("AdvancedQuery")) {
+        if (db.isConnected()) {
+          window.bPane.changeStatus("Querying the CAS...");
+          boolean result = db.issueQuery(query.getQuery(), query
+              .getProductType());
+          if (result) {
+            window.mPane.tPane.newTable(db.results.getData());
+            window.bPane.changeStatus("Query: " + query.getQueryString()
+                + " returned " + db.results.getNumRecords() + " records.");
+          } else {
+            window.mPane.tPane.setBlank();
+            window.bPane.changeStatus("Query failed.");
+            window.qPane.clearQuery();
+          }
+        }
+        query.dispose();
+      } else {
+        if (db.isConnected()) {
+          window.bPane.changeStatus("Querying the CAS...");
+          String query = window.qPane.getQuery();
+          boolean result = db.createQuery(query, window.qPane.getType());
+          if (result) {
+            window.mPane.tPane.newTable(db.results.getData());
+            window.bPane.changeStatus("Query: " + query + " returned "
+                + db.results.getNumRecords() + " records.");
+          } else {
+            window.mPane.tPane.setBlank();
+            window.bPane.changeStatus("Query failed.");
+            window.qPane.clearQuery();
+          }
+        }
+      }
+    } else if (arg0.getActionCommand().equals("Clear Query")) {
+      String clearWarning = "Are you sure you want to clear the current Query?\n"
+          + "All unexported queries will be lost.";
+      int returnVal = JOptionPane.showConfirmDialog(window, clearWarning,
+          "Clear", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
+      if (returnVal == JOptionPane.OK_OPTION) {
+        window.mPane.tPane.setBlank();
+        window.bPane.changeStatus("Query cleared.");
+      }
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/model/CasDB.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/model/CasDB.java
new file mode 100644
index 0000000..dcd5346
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/model/CasDB.java
@@ -0,0 +1,215 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.model;
+
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.apache.lucene.analysis.standard.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.Query;
+
+public class CasDB {
+
+  URL filemgrUrl;
+  XmlRpcFileManagerClient client;
+  public Results results;
+
+  private static String freeTextBlock = "__FREE__";
+
+  public CasDB() {
+    filemgrUrl = null;
+  }
+
+  public boolean connect(String cas) {
+    try {
+      filemgrUrl = new URL(cas);
+      client = new XmlRpcFileManagerClient(filemgrUrl);
+    } catch (Exception e) {
+      filemgrUrl = null;
+      return false;
+    }
+    return true;
+  }
+
+  public boolean disconnect() {
+    filemgrUrl = null;
+    return true;
+  }
+
+  public boolean isConnected() {
+    if (filemgrUrl == null) {
+      return false;
+    } else
+      return true;
+  }
+
+  public String[] getAvailableTypes() {
+    String[] types = null;
+    if (filemgrUrl != null) {
+      try {
+        Vector<ProductType> v = (Vector<ProductType>) client.getProductTypes();
+        Vector<String> names = new Vector<String>();
+        types = new String[v.size()];
+
+        for (int i = 0; i < v.size(); i++)
+          names.add(v.get(i).getName());
+
+        Collections.sort(names);
+        names.toArray(types);
+
+      } catch (RepositoryManagerException e) {
+        // e.printStackTrace();
+      }
+
+    } else {
+      types = new String[1];
+      types[0] = "";
+    }
+
+    return types;
+  }
+
+  public String[] getAvailableElements(String productTypeName) {
+    String[] elements = null;
+    if (filemgrUrl != null) {
+      try {
+        ProductType pt = client.getProductTypeByName(productTypeName);
+        Vector<Element> v = (Vector<Element>) client
+            .getElementsByProductType(pt);
+        Vector<String> names = new Vector<String>();
+        elements = new String[v.size()];
+
+        for (int i = 0; i < v.size(); i++)
+          names.add(v.get(i).getElementName());
+
+        Collections.sort(names);
+        names.toArray(elements);
+
+      } catch (Exception e) {
+        e.printStackTrace();
+      }
+    } else {
+      elements = new String[1];
+      elements[0] = "";
+    }
+    return elements;
+  }
+
+  public String getElementID(String elementName) {
+    String elementID = new String();
+    Element e;
+    try {
+      e = client.getElementByName(elementName);
+      elementID = e.getElementId();
+    } catch (ValidationLayerException e1) {
+    }
+    return elementID;
+  }
+
+  public boolean issueQuery(org.apache.oodt.cas.filemgr.structs.Query query,
+      String productType) {
+    results = new Results();
+    try {
+      ProductType type = client.getProductTypeByName(productType);
+      Vector<Product> products = (Vector<Product>) client.query(query, type);
+      int maxVal = 20;
+      if (products.size() < maxVal)
+        maxVal = products.size();
+      for (int i = 0; i < maxVal; i++) {
+        Vector<Element> elements = (Vector<Element>) client
+            .getElementsByProductType(type);
+        Metadata m = client.getMetadata(products.get(i));
+        Hashtable hash = m.getHashtable();
+        results.addProduct(m);
+      }
+    } catch (Exception e) {
+      return false;
+    }
+
+    return true;
+  }
+
+  public boolean createQuery(String queryText, String productType) {
+
+    results = new Results();
+    if (queryText.trim().equals("*")) {
+      ProductType type;
+      try {
+        type = client.getProductTypeByName(productType);
+        Vector<Product> products = (Vector<Product>) client
+            .getProductsByProductType(type);
+        // for(int i=0;i<products.size();i++){
+        int maxVal = 20;
+        if (products.size() < maxVal)
+          maxVal = products.size();
+        for (int i = 0; i < maxVal; i++) {
+          Vector<Element> elements = (Vector<Element>) client
+              .getElementsByProductType(type);
+          Metadata m = client.getMetadata(products.get(i));
+          Hashtable hash = m.getHashtable();
+          results.addProduct(m);
+        }
+      } catch (Exception e) {
+        return false;
+      }
+
+    } else {
+
+      QueryBuilder qb = new QueryBuilder(this);
+      org.apache.oodt.cas.filemgr.structs.Query casQ = qb.ParseQuery(queryText);
+      ProductType type = null;
+      try {
+        type = client.getProductTypeByName(productType);
+        Vector<Product> products = (Vector<Product>) client.query(casQ, type);
+        int maxVal = 20;
+        if (products.size() < maxVal)
+          maxVal = products.size();
+        for (int i = 0; i < maxVal; i++) {
+          Vector<Element> elements = (Vector<Element>) client
+              .getElementsByProductType(type);
+          Metadata m = client.getMetadata(products.get(i));
+          Hashtable hash = m.getHashtable();
+          results.addProduct(m);
+        }
+      } catch (Exception e) {
+        return false;
+      }
+
+    }
+
+    return true;
+  }
+
+  public boolean clearQuery() {
+    results = null;
+    return true;
+  }
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/model/QueryBuilder.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/model/QueryBuilder.java
new file mode 100644
index 0000000..f22df71
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/model/QueryBuilder.java
@@ -0,0 +1,112 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.model;
+
+import org.apache.lucene.analysis.standard.ParseException;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.PhraseQuery;
+import org.apache.lucene.search.RangeQuery;
+import org.apache.lucene.search.TermQuery;
+
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.tools.CASAnalyzer;
+
+public class QueryBuilder {
+
+  private CasDB database;
+
+  public QueryBuilder(CasDB db) {
+    database = db;
+  }
+
+  public Query ParseQuery(String query) {
+    // note that "__FREE__" is a control work for free text searching
+    QueryParser parser = new QueryParser("__FREE__", new CASAnalyzer());
+
+    org.apache.lucene.search.Query luceneQ = null;
+    org.apache.oodt.cas.filemgr.structs.Query casQ = new org.apache.oodt.cas.filemgr.structs.Query();
+
+    try {
+      luceneQ = parser.parse(query);
+    } catch (org.apache.lucene.queryParser.ParseException e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+
+    System.out.println(luceneQ.toString());
+    GenerateCASQuery(casQ, luceneQ);
+
+    return casQ;
+  }
+
+  public void GenerateCASQuery(org.apache.oodt.cas.filemgr.structs.Query casQ,
+      org.apache.lucene.search.Query luceneQ) {
+    if (luceneQ instanceof TermQuery) {
+      Term t = ((TermQuery) luceneQ).getTerm();
+      if (t.field().equals("__FREE__")) {
+        // if(casQuery.getCriteria().isEmpty()) casQuery.addCriterion(new
+        // FreeTextQueryCriteria());
+        // ((FreeTextQueryCriteria)casQuery.getCriteria().get(0)).addValue(t.text());
+      } else {
+        String element = database.getElementID(t.field());
+        if (!element.equals("") && !t.text().equals("")) {
+
+          casQ.addCriterion(new TermQueryCriteria(element, t.text()));
+        }
+      }
+    } else if (luceneQ instanceof PhraseQuery) {
+      Term[] t = ((PhraseQuery) luceneQ).getTerms();
+      if (t[0].field().equals("__FREE__")) {
+        // if(casQuery.getCriteria().isEmpty()) casQuery.addCriterion(new
+        // FreeTextQueryCriteria());
+        // for(int i=0;i<t.length;i++)
+        // ((FreeTextQueryCriteria)casQuery.getCriteria().get(0)).addValue(t[i].text());
+      } else {
+        for (int i = 0; i < t.length; i++) {
+          String element = database.getElementID(t[i].field());
+          if (!element.equals("") && !t[i].text().equals("")) {
+            casQ.addCriterion(new TermQueryCriteria(element, t[i].text()));
+          }
+        }
+      }
+    } else if (luceneQ instanceof RangeQuery) {
+      Term startT = ((RangeQuery) luceneQ).getLowerTerm();
+      Term endT = ((RangeQuery) luceneQ).getUpperTerm();
+      String element = database.getElementID(startT.field());
+      if (!element.equals("") && !startT.text().equals("")
+          && !endT.text().equals("")) {
+        casQ.addCriterion(new RangeQueryCriteria(element, startT.text(), endT
+            .text()));
+      }
+    } else if (luceneQ instanceof BooleanQuery) {
+      BooleanClause[] clauses = ((BooleanQuery) luceneQ).getClauses();
+      for (int i = 0; i < clauses.length; i++) {
+        GenerateCASQuery(casQ, (clauses[i]).getQuery());
+      }
+    } else {
+      System.out.println("Error Parsing Query");
+      System.exit(-1);
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/model/Results.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/model/Results.java
new file mode 100644
index 0000000..1baf0be
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/model/Results.java
@@ -0,0 +1,68 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.model;
+
+import org.apache.oodt.cas.metadata.Metadata;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class Results {
+
+  public Vector<Metadata> products;
+
+  public Results() {
+    products = new Vector<Metadata>();
+  }
+
+  public void addProduct(Metadata m) {
+    products.add(m);
+  }
+
+  public int getNumRecords() {
+    return products.size();
+  }
+
+  public String[][] getData() {
+
+    String[][] data = null;
+    if (products.size() > 0) {
+      data = new String[products.size() + 1][];
+
+      Hashtable hash = products.firstElement().getHashtable();
+      int numCols = hash.size();
+      data[0] = new String[numCols];
+      int i = 0;
+      for (Enumeration e = hash.keys(); e.hasMoreElements();) {
+        data[0][i] = e.nextElement().toString();
+        System.out.println(data[0][i]);
+        i++;
+      }
+
+      for (int j = 0; j < products.size(); j++) {
+        data[j + 1] = new String[i];
+        for (int k = 0; k < i; k++) {
+          data[j + 1][k] = products.get(j).getMetadata(data[0][k]);
+        }
+      }
+
+    }
+    return data;
+  }
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/system/XmlRpcFilemgrBrowser.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/system/XmlRpcFilemgrBrowser.java
new file mode 100644
index 0000000..0ac9caf
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/system/XmlRpcFilemgrBrowser.java
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.system;
+
+import org.apache.oodt.cas.filemgr.browser.view.MainWindow;
+
+public class XmlRpcFilemgrBrowser {
+
+  private static MainWindow window;
+
+  public static void main(String args[]) {
+    javax.swing.SwingUtilities.invokeLater(new Runnable() {
+      public void run() {
+        window = new MainWindow();
+        window.pack();
+        window.setVisible(true);
+      }
+    });
+  }
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/GuiParams.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/GuiParams.java
new file mode 100644
index 0000000..7f12da5
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/GuiParams.java
@@ -0,0 +1,28 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view;
+
+public class GuiParams {
+
+  public static final int WINDOW_WIDTH = 600;
+  public static final int WINDOW_HEIGHT = 400;
+
+  public static final int DEFAULT_CELL_WIDTH = 70;
+  public static final int DEFAULT_CELL_HEIGHT = 20;
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/MainWindow.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/MainWindow.java
new file mode 100644
index 0000000..2034277
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/MainWindow.java
@@ -0,0 +1,84 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+
+import org.apache.oodt.cas.filemgr.browser.controller.TableListener;
+import org.apache.oodt.cas.filemgr.browser.controller.WindowListener;
+import org.apache.oodt.cas.filemgr.browser.model.CasDB;
+import org.apache.oodt.cas.filemgr.browser.view.panels.BottomPane;
+import org.apache.oodt.cas.filemgr.browser.view.panels.HeaderRow;
+import org.apache.oodt.cas.filemgr.browser.view.panels.MiddlePane;
+import org.apache.oodt.cas.filemgr.browser.view.panels.QueryPane;
+import org.apache.oodt.cas.filemgr.browser.view.prompts.ConnectPrompt;
+import org.apache.oodt.cas.filemgr.browser.view.prompts.SortPrompt;
+import org.apache.oodt.cas.filemgr.browser.view.menus.MenuBar;
+
+public class MainWindow extends JFrame {
+
+  public QueryPane qPane;
+  public MiddlePane mPane;
+  public BottomPane bPane;
+  public MenuBar bar;
+
+  private WindowListener wListener;
+
+  public MainWindow() {
+    wListener = new WindowListener(this);
+    // db = new CasDB();
+    setName("CAS File Manager Browser");
+    setDefaultCloseOperation(EXIT_ON_CLOSE);
+    qPane = new QueryPane(wListener);
+    mPane = new MiddlePane();
+    bPane = new BottomPane();
+    Dimension d = new Dimension(GuiParams.WINDOW_WIDTH, GuiParams.WINDOW_HEIGHT);
+    Container p = this.getContentPane();
+    p.setPreferredSize(d);
+    p.setMinimumSize(d);
+    p.setMaximumSize(d);
+    p.setBackground(Color.WHITE);
+    p.setLayout(new BorderLayout());
+    p.add(qPane, BorderLayout.NORTH);
+    p.add(mPane, BorderLayout.CENTER);
+    p.add(bPane, BorderLayout.SOUTH);
+
+    bar = new MenuBar(wListener, mPane.getListener());
+    this.setJMenuBar(bar);
+  }
+
+  public String[] getColHeaders() {
+    HeaderRow h = mPane.tPane.getHeader();
+    String[] heading = new String[h.getNumCols()];
+    for (int i = 0; i < h.getNumCols(); i++) {
+      heading[i] = h.getText(i);
+    }
+    return heading;
+  }
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/menus/MenuBar.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/menus/MenuBar.java
new file mode 100644
index 0000000..2351ec1
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/menus/MenuBar.java
@@ -0,0 +1,102 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.menus;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.KeyStroke;
+
+public class MenuBar extends JMenuBar {
+
+  private JMenu fileMenu;
+  private JMenu queryMenu;
+  private JMenu helpMenu;
+
+  private JMenuItem queryItem;
+  private JMenuItem aboutItem;
+  private JMenuItem clearItem;
+  private JMenuItem unhideItem;
+  private JMenuItem exportItem;
+  private JMenuItem exitItem;
+  private JMenuItem sortItem;
+  private JMenuItem advancedItem;
+  private JMenuItem connectItem;
+
+  public MenuBar(ActionListener windowListener, ActionListener tableListener) {
+    fileMenu = new JMenu("File");
+    fileMenu.setMnemonic(KeyEvent.VK_F);
+    queryMenu = new JMenu("Query");
+    queryMenu.setMnemonic(KeyEvent.VK_Q);
+    helpMenu = new JMenu("Help");
+
+    // build help menu
+    queryItem = new JMenuItem("Query Language");
+    queryItem.addActionListener(windowListener);
+    aboutItem = new JMenuItem("About");
+    aboutItem.addActionListener(windowListener);
+    helpMenu.add(queryItem);
+    helpMenu.addSeparator();
+    helpMenu.add(aboutItem);
+
+    // build query menu
+    clearItem = new JMenuItem("Clear Query");
+    clearItem.addActionListener(windowListener);
+    advancedItem = new JMenuItem("Query Builder");
+    advancedItem.addActionListener(windowListener);
+    sortItem = new JMenuItem("Sort");
+    sortItem.addActionListener(windowListener);
+    unhideItem = new JMenuItem("Unhide Columns");
+    unhideItem.addActionListener(tableListener);
+    queryMenu.add(unhideItem);
+    queryMenu.add(advancedItem);
+    queryMenu.add(sortItem);
+    queryMenu.addSeparator();
+    queryMenu.add(clearItem);
+
+    // build file menu
+    connectItem = new JMenuItem("Connect...");
+    connectItem.addActionListener(windowListener);
+    exportItem = new JMenuItem("Export Table");
+    exportItem.addActionListener(tableListener);
+    exitItem = new JMenuItem("Exit");
+    exitItem.addActionListener(windowListener);
+    fileMenu.add(connectItem);
+    fileMenu.add(exportItem);
+    fileMenu.addSeparator();
+    fileMenu.add(exitItem);
+
+    add(fileMenu);
+    add(queryMenu);
+    add(helpMenu);
+  }
+
+  public void changeConnectStatus() {
+    if (connectItem.getActionCommand().equals("Connect...")) {
+      connectItem.setActionCommand("Disconnect");
+      connectItem.setText("Disconnect");
+    } else {
+      connectItem.setActionCommand("Connect...");
+      connectItem.setText("Connect...");
+    }
+  }
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/menus/RightClickMenu.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/menus/RightClickMenu.java
new file mode 100644
index 0000000..854cfb3
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/menus/RightClickMenu.java
@@ -0,0 +1,59 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.menus;
+
+import java.awt.event.ActionListener;
+
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+
+public class RightClickMenu extends JPopupMenu {
+
+  private JMenuItem hideItem;
+  private JMenuItem unhideItem;
+
+  // private JMenuItem resizeItem;
+
+  public RightClickMenu(ActionListener listener) {
+
+    hideItem = new JMenuItem("Hide");
+    hideItem.addActionListener(listener);
+    unhideItem = new JMenuItem("Unhide");
+    unhideItem.addActionListener(listener);
+    // resizeItem = new JMenuItem("Resize");
+    // resizeItem.addActionListener(listener);
+
+    this.add(hideItem);
+    this.add(unhideItem);
+    // this.addSeparator();
+    // this.add(resizeItem);
+  }
+
+  public void setUnhideMode() {
+    hideItem.setEnabled(false);
+    unhideItem.setEnabled(true);
+    // resizeItem.setEnabled(false);
+  }
+
+  public void setHideMode() {
+    hideItem.setEnabled(true);
+    unhideItem.setEnabled(false);
+    // resizeItem.setEnabled(true);
+  }
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/BottomPane.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/BottomPane.java
new file mode 100644
index 0000000..414fa02
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/BottomPane.java
@@ -0,0 +1,65 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.panels;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+
+import javax.swing.BoxLayout;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.LineBorder;
+
+public class BottomPane extends JPanel {
+
+  public JLabel statusMessage;
+
+  public BottomPane() {
+
+    // set background and panel size
+    setBackground(Color.WHITE);
+    EmptyBorder line1 = new EmptyBorder(4, 10, 4, 2);
+    LineBorder line2 = new LineBorder(Color.BLACK, 1);
+    EmptyBorder line3 = new EmptyBorder(4, 10, 4, 10);
+    CompoundBorder cb1 = new CompoundBorder(line1, line2);
+    CompoundBorder cb2 = new CompoundBorder(cb1, line3);
+    setBorder(cb2);
+
+    JLabel statusLabel = new JLabel(" Status: ");
+    statusLabel.setFont(new Font("san-serif", Font.PLAIN, 10));
+
+    statusMessage = new JLabel(" Disconnected");
+    statusMessage.setFont(new Font("san-serif", Font.PLAIN, 10));
+    statusMessage.setForeground(Color.RED);
+    statusMessage.setBackground(Color.WHITE);
+
+    // set layout
+    setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
+    add(statusLabel);
+    add(statusMessage);
+  }
+
+  public void changeStatus(String status) {
+    statusMessage.setText(status);
+    this.repaint();
+  }
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/Cell.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/Cell.java
new file mode 100644
index 0000000..e5a29ea
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/Cell.java
@@ -0,0 +1,73 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.panels;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.LineBorder;
+
+import org.apache.oodt.cas.filemgr.browser.view.GuiParams;
+
+public class Cell extends JPanel {
+
+  protected JLabel text;
+
+  public Cell() {
+    setLayout(new BorderLayout());
+    setBackground(Color.WHITE);
+    setForeground(Color.BLACK);
+    Dimension size = new Dimension(GuiParams.DEFAULT_CELL_WIDTH,
+        GuiParams.DEFAULT_CELL_HEIGHT);
+    setMinimumSize(size);
+    setMaximumSize(size);
+    setPreferredSize(size);
+    setBorder(new LineBorder(Color.LIGHT_GRAY, 1));
+
+    text = new JLabel("");
+    Font f = new Font("san-sarif", Font.PLAIN, 10);
+    text.setFont(f);
+    this.add(text, BorderLayout.CENTER);
+  }
+
+  public void setText(String newText) {
+    text.setText(newText);
+  }
+
+  public String getText() {
+    return text.getText();
+  }
+
+  public void setWidth(int newWidth) {
+    Dimension size = this.getSize();
+    size.width = newWidth;
+    this.setSize(size);
+    text.setSize(size);
+  }
+
+  public void setHeight(int newHeight) {
+    Dimension size = this.getSize();
+    size.height = newHeight;
+    this.setSize(size);
+    text.setSize(size);
+  }
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/HeaderCell.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/HeaderCell.java
new file mode 100644
index 0000000..6ac5464
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/HeaderCell.java
@@ -0,0 +1,53 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.panels;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.event.MouseListener;
+
+import javax.swing.border.LineBorder;
+
+import org.apache.oodt.cas.filemgr.browser.view.GuiParams;
+
+public class HeaderCell extends Cell {
+
+  private int colNum;
+
+  public HeaderCell(MouseListener listener, int colNum) {
+    super();
+    this.setBackground(Color.LIGHT_GRAY);
+    this.setBorder(null);
+    Dimension size = new Dimension(GuiParams.DEFAULT_CELL_WIDTH - 2,
+        GuiParams.DEFAULT_CELL_HEIGHT);
+    setMinimumSize(size);
+    setMaximumSize(size);
+    setPreferredSize(size);
+    Font f = new Font("san-serif", Font.BOLD, 11);
+    text.setFont(f);
+
+    this.colNum = colNum;
+    this.addMouseListener(listener);
+  }
+
+  public int getColNum() {
+    return colNum;
+  }
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/HeaderRow.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/HeaderRow.java
new file mode 100644
index 0000000..6980edf
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/HeaderRow.java
@@ -0,0 +1,99 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.panels;
+
+import java.awt.Color;
+import java.awt.event.MouseListener;
+
+import javax.swing.BoxLayout;
+import javax.swing.JPanel;
+
+public class HeaderRow extends JPanel {
+
+  private HeaderCell cells[];
+  private int numCells;
+
+  public HeaderRow(MouseListener listener, int numCells) {
+    // create cells
+    this.numCells = numCells;
+    cells = new HeaderCell[numCells];
+    for (int i = 0; i < numCells; i++) {
+      cells[i] = new HeaderCell(listener, i);
+    }
+
+    // set background, etc.
+    this.setBackground(Color.WHITE);
+    this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
+
+    for (int i = 0; i < numCells; i++) {
+      this.add(cells[i]);
+      this.add(new HeaderSpacer(listener, i));
+    }
+  }
+
+  public int getNumCols() {
+    return numCells;
+  }
+
+  public void hideCol(int colNum) {
+    int trueNum = colNum * 2;
+    HeaderCell c = (HeaderCell) this.getComponent(trueNum);
+    c.setVisible(false);
+    HeaderSpacer sp = (HeaderSpacer) this.getComponent(trueNum + 1);
+    sp.setVisible(false);
+  }
+
+  public void unhideCol(int colNum) {
+    int trueNum = colNum * 2;
+    HeaderCell c = (HeaderCell) this.getComponent(trueNum);
+    c.setVisible(true);
+    HeaderSpacer sp = (HeaderSpacer) this.getComponent(trueNum + 1);
+    sp.setVisible(true);
+  }
+
+  public void setText(int colNum, String text) {
+    int trueNum = colNum * 2;
+    HeaderCell c = (HeaderCell) this.getComponent(trueNum);
+    c.setText(text);
+    c.repaint();
+  }
+
+  public String getText(int colNum) {
+    int trueNum = colNum * 2;
+    HeaderCell c = (HeaderCell) this.getComponent(trueNum);
+    return c.getText();
+  }
+
+  public int getWidth(int colNum) {
+    int trueNum = colNum * 2;
+    HeaderCell c = (HeaderCell) this.getComponent(trueNum);
+    return c.getWidth();
+  }
+
+  public void changeWidth(int colNum, int newWidth) {
+    int trueNum = colNum * 2;
+    HeaderCell c = (HeaderCell) this.getComponent(trueNum);
+    int change = c.getWidth() - newWidth;
+    c.setWidth(newWidth);
+    for (int i = trueNum + 1; i < this.getComponentCount(); i++) {
+      this.getComponent(i).setLocation(this.getComponent(i).getX() - change,
+          this.getComponent(i).getY());
+    }
+    this.repaint();
+  }
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/HeaderSpacer.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/HeaderSpacer.java
new file mode 100644
index 0000000..e8f8f19
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/HeaderSpacer.java
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.panels;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.MouseListener;
+
+import javax.swing.JPanel;
+
+import org.apache.oodt.cas.filemgr.browser.view.GuiParams;
+
+public class HeaderSpacer extends JPanel {
+
+  private int col;
+
+  public HeaderSpacer(MouseListener listener, int pos) {
+    // set background, size
+    this.setBackground(Color.WHITE);
+    Dimension d = new Dimension(2, GuiParams.DEFAULT_CELL_HEIGHT);
+    this.setMinimumSize(d);
+    this.setMaximumSize(d);
+    this.setPreferredSize(d);
+
+    col = pos;
+    this.addMouseListener(listener);
+  }
+
+  public int getColNum() {
+    return col;
+  }
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/MiddlePane.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/MiddlePane.java
new file mode 100644
index 0000000..35f4ed2
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/MiddlePane.java
@@ -0,0 +1,52 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.panels;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import org.apache.oodt.cas.filemgr.browser.controller.TableListener;
+
+public class MiddlePane extends JPanel {
+
+  public TablePane tPane;
+
+  public MiddlePane() {
+    this.setBackground(Color.WHITE);
+    this.setLayout(new BorderLayout());
+
+    tPane = new TablePane();
+
+    JPanel inset = new JPanel();
+    inset.setBackground(Color.WHITE);
+    inset.setLayout(new BorderLayout());
+    inset.add(tPane, BorderLayout.WEST);
+
+    JScrollPane scrollPane = new JScrollPane(inset);
+
+    this.add(scrollPane, BorderLayout.CENTER);
+  }
+
+  public TableListener getListener() {
+    return tPane.getListener();
+  }
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/QueryField.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/QueryField.java
new file mode 100644
index 0000000..7f1b4ac
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/QueryField.java
@@ -0,0 +1,109 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.panels;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+public class QueryField extends JPanel implements ActionListener {
+
+  private JTextField text;
+  private JButton button;
+  private JComboBox types;
+
+  public QueryField(ActionListener listener) {
+
+    // setbackground an size for panel
+    setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
+    setBackground(Color.WHITE);
+    setMinimumSize(new Dimension(500, 50));
+    setPreferredSize(new Dimension(500, 50));
+
+    text = new JTextField(30);
+    button = new JButton("Search");
+    String[] blankType = { "" };
+    types = new JComboBox(blankType);
+
+    // set background and size for textbox and combo
+    text.setForeground(Color.BLACK);
+    text.setBackground(Color.WHITE);
+    text.setMinimumSize(new Dimension(100, 25));
+    text.setPreferredSize(new Dimension(100, 25));
+    text.setMaximumSize(new Dimension(100, 25));
+    text.addActionListener(this);
+    Dimension typeDim = new Dimension(100, 25);
+    types.setMaximumSize(typeDim);
+    types.setMinimumSize(typeDim);
+    types.setPreferredSize(typeDim);
+    types.setBackground(Color.WHITE);
+
+    // set button
+    button.setBackground(Color.WHITE);
+    button.addActionListener(listener);
+    button.setName("Query");
+
+    add(new JLabel("ProductType:  "));
+    add(types);
+    add(new JLabel("    Query:  "));
+    add(text);
+    add(button);
+  }
+
+  public String getQueryString() {
+    return text.getText();
+  }
+
+  public void clearQuery() {
+    text.setText("");
+  }
+
+  public String getProductType() {
+    return types.getSelectedItem().toString();
+  }
+
+  public void updateTypes(String[] typeNames) {
+    this.remove(types);
+    types = new JComboBox(typeNames);
+    types.setBackground(Color.WHITE);
+    Dimension typeDim = new Dimension(100, 25);
+    types.setMaximumSize(typeDim);
+    types.setMinimumSize(typeDim);
+    types.setPreferredSize(typeDim);
+    add(types, 1);
+    this.repaint();
+  }
+
+  public void actionPerformed(ActionEvent arg0) {
+    button.doClick();
+  }
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/QueryPane.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/QueryPane.java
new file mode 100644
index 0000000..7211ac7
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/QueryPane.java
@@ -0,0 +1,72 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.panels;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.ActionListener;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.LineBorder;
+
+import org.apache.oodt.cas.filemgr.browser.view.GuiParams;
+
+public class QueryPane extends JPanel {
+
+  private QueryField field;
+
+  public QueryPane(ActionListener listener) {
+    super(new BorderLayout());
+
+    // set background and panel size
+    setBackground(Color.WHITE);
+    Dimension paneSize = new Dimension();
+    paneSize.width = GuiParams.WINDOW_WIDTH;
+    paneSize.height = (int) (GuiParams.WINDOW_HEIGHT * (0.1));
+
+    // set border
+    EmptyBorder line1 = new EmptyBorder(2, 10, 2, 2);
+    LineBorder line2 = new LineBorder(Color.BLACK, 1);
+    CompoundBorder cp = new CompoundBorder(line1, line2);
+    this.setBorder(cp);
+
+    // add query field to pane
+    field = new QueryField(listener);
+    add(field, BorderLayout.EAST);
+  }
+
+  public String getQuery() {
+    return field.getQueryString();
+  }
+
+  public void clearQuery() {
+    field.clearQuery();
+  }
+
+  public String getType() {
+    return field.getProductType();
+  }
+
+  public void updateTypes(String[] types) {
+    field.updateTypes(types);
+  }
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/Row.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/Row.java
new file mode 100644
index 0000000..d127180
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/Row.java
@@ -0,0 +1,83 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.panels;
+
+import java.awt.Color;
+
+import javax.swing.BoxLayout;
+import javax.swing.JPanel;
+
+public class Row extends JPanel {
+
+  private Cell cells[];
+
+  public Row(int numCells) {
+    // create cells
+    cells = new Cell[numCells];
+    for (int i = 0; i < numCells; i++) {
+      cells[i] = new Cell();
+      cells[i].setText("");
+    }
+
+    // set background, etc.
+    this.setBackground(Color.WHITE);
+    this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
+
+    for (int i = 0; i < numCells; i++) {
+      this.add(cells[i]);
+    }
+  }
+
+  public void hideCol(int colNum) {
+    Cell c = (Cell) this.getComponent(colNum);
+    c.setVisible(false);
+  }
+
+  public void unhideCol(int colNum) {
+    Cell c = (Cell) this.getComponent(colNum);
+    c.setVisible(true);
+  }
+
+  public void setText(int colNum, String text) {
+    Cell c = (Cell) this.getComponent(colNum);
+    c.setText(text);
+    c.repaint();
+  }
+
+  public String getText(int colNum) {
+    Cell c = (Cell) this.getComponent(colNum);
+    return c.getText();
+  }
+
+  public int getWidth(int colNum) {
+    Cell c = (Cell) this.getComponent(colNum);
+    return c.getWidth();
+  }
+
+  public void changeWidth(int colNum, int newWidth) {
+    Cell c = (Cell) this.getComponent(colNum);
+    int change = c.getWidth() - newWidth;
+    c.setWidth(newWidth);
+    for (int i = colNum + 1; i < this.getComponentCount(); i++) {
+      this.getComponent(i).setLocation(this.getComponent(i).getX() - change,
+          this.getComponent(i).getY());
+    }
+    this.repaint();
+  }
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/TablePane.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/TablePane.java
new file mode 100644
index 0000000..fcc8f5c
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/panels/TablePane.java
@@ -0,0 +1,169 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.browser.view.panels;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.util.Vector;
+
+import javax.swing.BoxLayout;
+import javax.swing.JFileChooser;
+import javax.swing.JPanel;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.LineBorder;
+import javax.swing.filechooser.FileFilter;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+import org.apache.oodt.cas.filemgr.browser.controller.TableListener;
+import org.apache.oodt.cas.filemgr.browser.view.menus.RightClickMenu;
+
+public class TablePane extends JPanel{ 
+	
+	public Vector<Integer> hiddenCols;
+	public HeaderRow header;
+	
+	private TableListener listener;
+	
+	public TablePane(){
+		listener = new TableListener(this);
+		
+		hiddenCols = new Vector<Integer>();
+		setBackground(Color.WHITE);
+		LineBorder line1 = new LineBorder(Color.WHITE,10);
+		setBorder(line1);
+		
+		setLayout(new BoxLayout(this,BoxLayout.PAGE_AXIS));
+		
+		this.setBlank();
+	}
+	
+	public TableListener getListener(){
+		return listener;
+	}
+	
+	public void setBlank(){
+		this.removeAll();
+		int numColumns = 10;
+		int numRows = 20;
+		header = new HeaderRow(listener,numColumns);
+		add(header);
+		
+		for(int i=0;i<numRows;i++){
+			Row r = new Row(numColumns);
+			add(r);
+		}
+		
+		this.validate();
+		this.repaint();
+	}
+	
+	public void newTable(String[][] data){
+		this.removeAll();
+		if(data.length>1){
+			header = new HeaderRow(listener,data[0].length);
+			for(int j=0;j<data[0].length;j++){
+				header.setText(j, data[0][j]);
+			}
+			this.add(header);
+			
+			for(int j=1;j<data.length;j++){
+				Row r = new Row(data[0].length);
+				for(int k=0;k<data[0].length;k++){
+					r.setText(k, data[j][k]);
+				}
+				this.add(r);
+			}
+		}
+		this.validate();
+		this.repaint();
+	}
+	
+	public HeaderRow getHeader(){
+		return header;
+	}
+
+	public void sortRows(int col, String sortType){
+		int length = this.getComponentCount();
+		int i,j;
+
+	    for (i=length; --i >=1;) {
+	       for (j=1; j<i;j++) {
+	    	   Row jThRow = (Row)this.getComponent(j);
+	    	   Row iThRow = (Row)this.getComponent(i);
+	    	   if(sortType.equals("Accending")){
+	    		   if(jThRow.getText(col).compareTo(iThRow.getText(col))>0){
+	    			   swapRows(j,j+1);
+	    		   }
+	    	   } else {
+	    		   if(jThRow.getText(col).compareTo(iThRow.getText(col))<0){
+	    			   swapRows(j,j+1);
+	    		   }
+	    	   }
+	       }
+	    }
+	    this.validate();
+	    this.repaint();
+	    
+	}
+	
+	public void swapRows(int index1, int index2){
+		Component c1 = this.getComponent(index1);
+		Component c2 = this.getComponent(index2);
+		this.add(c1, index2);
+		this.add(c2, index1);
+	}
+	
+	public Row getRow(int num){
+		Row r = null;
+		if(num<this.getComponentCount()-1){
+			r = (Row)this.getComponent(num+1);
+		}
+		return r;
+	}
+	
+	public void hideColumn(int colNum){
+		header.hideCol(colNum);
+		for(int i=1;i<this.getComponentCount();i++){
+			((Row)this.getComponent(i)).hideCol(colNum);
+		}
+		hiddenCols.add(new Integer(colNum));
+	}
+	
+	public void unhideColumn(int colNum){
+		header.unhideCol(colNum);
+		for(int i=1;i<this.getComponentCount();i++){
+			((Row)this.getComponent(i)).unhideCol(colNum);
+		}
+		hiddenCols.remove(new Integer(colNum));
+		
+	}
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/prompts/ConnectPrompt.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/prompts/ConnectPrompt.java
new file mode 100644
index 0000000..cd08d4e
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/prompts/ConnectPrompt.java
@@ -0,0 +1,115 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.prompts;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.LineBorder;
+
+public class ConnectPrompt extends JFrame implements ActionListener {
+
+  private CASField topPanel;
+  private ConnectButton bottomPanel;
+
+  public ConnectPrompt(ActionListener listener) {
+    this.setName("New Connection");
+    this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+    Dimension d = new Dimension(400, 100);
+    this.setMinimumSize(d);
+    this.setMaximumSize(d);
+    this.setPreferredSize(d);
+
+    this.getContentPane().setLayout(
+        new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS));
+    this.getContentPane().setBackground(Color.WHITE);
+
+    topPanel = new CASField(this);
+    bottomPanel = new ConnectButton(listener);
+    this.add(topPanel);
+    this.add(bottomPanel);
+  }
+
+  public String getCASUrl() {
+    return topPanel.casRef.getText();
+  }
+
+  private class CASField extends JPanel {
+
+    protected JTextField casRef;
+
+    protected CASField(ActionListener listener) {
+      this.setBackground(Color.WHITE);
+      this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
+      Dimension d = new Dimension(400, 30);
+      this.setMaximumSize(d);
+      this.setMinimumSize(d);
+      this.setPreferredSize(d);
+
+      EmptyBorder line1 = new EmptyBorder(5, 10, 5, 5);
+      this.setBorder(line1);
+
+      this.add(new JLabel("CAS File Manager URL:  "));
+      casRef = new JTextField();
+      casRef.addActionListener(listener);
+      this.add(casRef);
+    }
+  }
+
+  private class ConnectButton extends JPanel {
+
+    protected JButton connect;
+    protected JButton cancel;
+
+    protected ConnectButton(ActionListener listener) {
+      this.setBackground(Color.WHITE);
+      this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
+
+      EmptyBorder line1 = new EmptyBorder(5, 20, 5, 5);
+      this.setBorder(line1);
+
+      this.add(new JLabel("                          "));
+      connect = new JButton("Connect");
+      connect.setBackground(Color.WHITE);
+      connect.addActionListener(listener);
+      cancel = new JButton("Cancel");
+      cancel.setBackground(Color.WHITE);
+      cancel.addActionListener(listener);
+      cancel.setName("ConnectCancel");
+      this.add(cancel);
+      this.add(connect);
+    }
+  }
+
+  public void actionPerformed(ActionEvent arg0) {
+    bottomPanel.connect.doClick();
+  }
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/prompts/QueryBuilderPrompt.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/prompts/QueryBuilderPrompt.java
new file mode 100644
index 0000000..5204db5
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/prompts/QueryBuilderPrompt.java
@@ -0,0 +1,453 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.prompts;
+
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.LineBorder;
+
+import org.apache.oodt.cas.filemgr.browser.controller.WindowListener;
+import org.apache.oodt.cas.filemgr.browser.model.CasDB;
+
+public class QueryBuilderPrompt extends JFrame {
+
+  protected CasDB database;
+  protected WindowListener listener;
+
+  protected TypePanel tPanel;
+  protected QuerySelectionPanel qPanel;
+  protected JScrollPane scrollPane;
+  protected BuiltQueryPane builtPanel;
+  protected SearchPanel sPanel;
+
+  public QueryBuilderPrompt(CasDB db, WindowListener l) {
+
+    database = db;
+    listener = l;
+
+    this.setName("Query Builder");
+    this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+    Dimension d = new Dimension(500, 400);
+    this.setMinimumSize(d);
+    this.setMaximumSize(d);
+    this.setPreferredSize(d);
+
+    this.getContentPane().setLayout(
+        new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS));
+    this.getContentPane().setBackground(Color.WHITE);
+
+    tPanel = new TypePanel(this);
+    qPanel = new QuerySelectionPanel(this);
+    sPanel = new SearchPanel(this);
+    builtPanel = new BuiltQueryPane(this);
+
+    scrollPane = new JScrollPane(qPanel);
+    Dimension scrollDim = new Dimension(500, 220);
+    scrollPane.setMaximumSize(scrollDim);
+    scrollPane.setMinimumSize(scrollDim);
+    scrollPane.setPreferredSize(scrollDim);
+
+    this.getContentPane().add(tPanel);
+    this.getContentPane().add(scrollPane);
+    this.getContentPane().add(builtPanel);
+    this.getContentPane().add(sPanel);
+  }
+
+  public org.apache.oodt.cas.filemgr.structs.Query getQuery() {
+    return qPanel.getCasQuery();
+  }
+
+  public String getQueryString() {
+    return qPanel.getQuery();
+  }
+
+  public String getProductType() {
+    return tPanel.getType();
+  }
+
+  private class QueryPanel extends JPanel {
+
+    private JComboBox elements;
+    private JComboBox ops;
+    private JPanel placeholder;
+    private boolean showOp;
+
+    public QueryPanel(QueryBuilderPrompt prompt) {
+      Dimension d = new Dimension(460, 35);
+      this.setMaximumSize(d);
+      this.setMinimumSize(d);
+      this.setPreferredSize(d);
+      this.setBackground(Color.WHITE);
+      this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
+
+      showOp = false;
+      ops = new JComboBox(new String[] { "AND", "OR", "NOT" });
+      Dimension opsDim = new Dimension(75, 25);
+      ops.setMaximumSize(opsDim);
+      ops.setMinimumSize(opsDim);
+      ops.setPreferredSize(opsDim);
+      ops.setBackground(Color.WHITE);
+      ops.setVisible(false);
+
+      placeholder = new JPanel();
+      placeholder.setBackground(Color.WHITE);
+      placeholder.setMaximumSize(opsDim);
+      placeholder.setMinimumSize(opsDim);
+      placeholder.setPreferredSize(opsDim);
+
+      elements = new JComboBox(prompt.database
+          .getAvailableElements(prompt.tPanel.getType()));
+      elements.setBackground(Color.WHITE);
+      Dimension dElem = new Dimension(150, 25);
+      elements.setMaximumSize(dElem);
+      elements.setMinimumSize(dElem);
+      elements.setPreferredSize(dElem);
+
+      this.add(ops);
+      this.add(placeholder);
+      this.add(elements);
+    }
+
+    public void addOp() {
+      showOp = true;
+      ops.setVisible(true);
+      placeholder.setVisible(false);
+    }
+
+    public String getElement() {
+      return elements.getSelectedItem().toString();
+    }
+
+    public String getOp() {
+      String op = "";
+      if (showOp) {
+        op = ops.getSelectedItem().toString();
+      }
+      return op;
+    }
+  }
+
+  private class TermQueryPanel extends QueryPanel {
+
+    private JTextField text;
+
+    public TermQueryPanel(QueryBuilderPrompt prompt) {
+      super(prompt);
+
+      text = new JTextField();
+      Dimension dText = new Dimension(150, 25);
+      text.setPreferredSize(dText);
+      text.setMaximumSize(dText);
+      text.setMinimumSize(dText);
+      text.setBackground(Color.WHITE);
+      text.addFocusListener(prompt.builtPanel);
+      text.addActionListener(prompt.builtPanel);
+
+      this.add(new JLabel("  Matches  "));
+      this.add(text);
+    }
+
+    public String getText() {
+      return text.getText();
+    }
+
+  }
+
+  private class RangeQueryPanel extends QueryPanel {
+
+    private JTextField start;
+    private JTextField stop;
+
+    public RangeQueryPanel(QueryBuilderPrompt prompt) {
+      super(prompt);
+
+      start = new JTextField();
+      stop = new JTextField();
+
+      Dimension dText = new Dimension(60, 25);
+      start.setMaximumSize(dText);
+      start.setMinimumSize(dText);
+      start.setPreferredSize(dText);
+      start.addFocusListener(prompt.builtPanel);
+      start.addActionListener(prompt.builtPanel);
+
+      stop.setMaximumSize(dText);
+      stop.setMinimumSize(dText);
+      stop.setPreferredSize(dText);
+      stop.addFocusListener(prompt.builtPanel);
+      stop.addActionListener(prompt.builtPanel);
+
+      this.add(new JLabel("  Between  "));
+      this.add(start);
+      this.add(new JLabel(" And "));
+      this.add(stop);
+    }
+
+    public String getStart() {
+      return start.getText();
+    }
+
+    public String getStop() {
+      return stop.getText();
+    }
+
+  }
+
+  private class QuerySelectionPanel extends JPanel implements ActionListener {
+
+    private JButton addTerm;
+    private JButton addRange;
+    private QueryBuilderPrompt prompt;
+
+    public QuerySelectionPanel(QueryBuilderPrompt prompt) {
+      this.prompt = prompt;
+      this.setBackground(Color.WHITE);
+
+      EmptyBorder line1 = new EmptyBorder(2, 2, 2, 2);
+      LineBorder line2 = new LineBorder(Color.BLACK, 1);
+      CompoundBorder cp = new CompoundBorder(line1, line2);
+      this.setBorder(cp);
+      this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+
+      JPanel buttonPanel = new JPanel();
+      Dimension buttonDim = new Dimension(460, 30);
+      buttonPanel.setMaximumSize(buttonDim);
+      buttonPanel.setMinimumSize(buttonDim);
+      buttonPanel.setPreferredSize(buttonDim);
+      buttonPanel.setBackground(Color.WHITE);
+      buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
+
+      addTerm = new JButton("Add Term Criteria");
+      addTerm.setBackground(Color.WHITE);
+      addTerm.addActionListener(this);
+
+      addRange = new JButton("Add Range Criteria");
+      addRange.setBackground(Color.WHITE);
+      addRange.addActionListener(this);
+
+      buttonPanel.add(addTerm);
+      buttonPanel.add(addRange);
+      this.add(buttonPanel);
+    }
+
+    public void actionPerformed(ActionEvent arg0) {
+      if (arg0.getActionCommand().equals("Add Term Criteria")) {
+        TermQueryPanel tq = new TermQueryPanel(prompt);
+        if (this.getComponentCount() > 1)
+          tq.addOp();
+        int insertOrder = this.getComponentCount() - 1;
+        if (insertOrder < 0)
+          insertOrder = 0;
+        this.add(tq, insertOrder);
+        this.validate();
+        prompt.scrollPane.validate();
+      } else if (arg0.getActionCommand().equals("Add Range Criteria")) {
+        RangeQueryPanel rq = new RangeQueryPanel(prompt);
+        if (this.getComponentCount() > 1)
+          rq.addOp();
+        int insertOrder = this.getComponentCount() - 1;
+        if (insertOrder < 0)
+          insertOrder = 0;
+        this.add(rq, insertOrder);
+        this.validate();
+        prompt.scrollPane.validate();
+      }
+    }
+
+    public String getQuery() {
+      String q = new String();
+      for (int i = 0; i < this.getComponentCount(); i++) {
+        Component c = this.getComponent(i);
+        if (c instanceof TermQueryPanel) {
+          q += ((TermQueryPanel) c).getOp() + " ";
+          q += ((TermQueryPanel) c).getElement() + ":";
+          q += ((TermQueryPanel) c).getText() + " ";
+        } else if (c instanceof RangeQueryPanel) {
+          q += ((RangeQueryPanel) c).getOp() + " ";
+          q += ((RangeQueryPanel) c).getElement() + ":[";
+          q += ((RangeQueryPanel) c).getStart() + " TO ";
+          q += ((RangeQueryPanel) c).getStop() + "] ";
+        }
+      }
+
+      return q;
+    }
+
+    public org.apache.oodt.cas.filemgr.structs.Query getCasQuery() {
+      org.apache.oodt.cas.filemgr.structs.Query q = new org.apache.oodt.cas.filemgr.structs.Query();
+      for (int i = 0; i < this.getComponentCount(); i++) {
+        Component c = this.getComponent(i);
+        String element;
+        if (c instanceof TermQueryPanel) {
+          element = database.getElementID(((TermQueryPanel) c).getElement());
+          String criteria = ((TermQueryPanel) c).getText();
+          if (!element.equals("") && !criteria.equals("")) {
+            TermQueryCriteria tc = new TermQueryCriteria();
+            tc.setElementName(element);
+            tc.setValue(criteria);
+            q.addCriterion(tc);
+          }
+        } else if (c instanceof RangeQueryPanel) {
+          element = database.getElementID(((RangeQueryPanel) c).getElement());
+          String startCriteria = ((RangeQueryPanel) c).getStart();
+          String stopCriteria = ((RangeQueryPanel) c).getStop();
+          if (!element.equals("") && !startCriteria.equals("")
+              && !stopCriteria.equals("")) {
+            RangeQueryCriteria rt = new RangeQueryCriteria();
+            rt.setElementName(element);
+            rt.setStartValue(startCriteria);
+            rt.setEndValue(stopCriteria);
+            q.addCriterion(rt);
+          }
+        }
+      }
+
+      return q;
+    }
+
+  }
+
+  private class SearchPanel extends JPanel {
+    private JButton search;
+
+    public SearchPanel(QueryBuilderPrompt prompt) {
+      Dimension d = new Dimension(500, 40);
+      this.setMaximumSize(d);
+      this.setMinimumSize(d);
+      this.setPreferredSize(d);
+      EmptyBorder line1 = new EmptyBorder(2, 2, 2, 2);
+      LineBorder line2 = new LineBorder(Color.BLACK, 1);
+      CompoundBorder cp = new CompoundBorder(line1, line2);
+      this.setBorder(cp);
+      this.setLayout(new BorderLayout());
+      this.setBackground(Color.WHITE);
+
+      search = new JButton("Search");
+      search.setName("AdvancedQuery");
+      search.addActionListener(prompt.listener);
+      search.setBackground(Color.WHITE);
+
+      JPanel buttonPanel = new JPanel();
+      buttonPanel.setBackground(Color.WHITE);
+      buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
+      buttonPanel.add(search);
+      this.add(buttonPanel, BorderLayout.EAST);
+    }
+
+  }
+
+  private class TypePanel extends JPanel {
+
+    private JComboBox types;
+
+    public TypePanel(QueryBuilderPrompt prompt) {
+
+      Dimension d = new Dimension(500, 40);
+      this.setMaximumSize(d);
+      this.setMinimumSize(d);
+      this.setPreferredSize(d);
+      EmptyBorder line1 = new EmptyBorder(2, 2, 2, 2);
+      LineBorder line2 = new LineBorder(Color.BLACK, 1);
+      CompoundBorder cp = new CompoundBorder(line1, line2);
+      this.setBorder(cp);
+
+      types = new JComboBox(database.getAvailableTypes());
+      types.setBackground(Color.WHITE);
+      Dimension tDim = new Dimension(200, 30);
+      types.setMaximumSize(tDim);
+      types.setMinimumSize(tDim);
+      types.setPreferredSize(tDim);
+
+      this.setBackground(Color.WHITE);
+      this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
+
+      JLabel label = new JLabel("        Product Type:   ");
+
+      this.add(label);
+      this.add(types);
+    }
+
+    public String getType() {
+      return types.getSelectedItem().toString();
+    }
+  }
+
+  private class BuiltQueryPane extends JPanel implements FocusListener,
+      ActionListener {
+
+    private QueryBuilderPrompt p;
+    private JTextArea field;
+
+    public BuiltQueryPane(QueryBuilderPrompt prompt) {
+
+      Dimension d = new Dimension(500, 75);
+      this.setMaximumSize(d);
+      this.setMinimumSize(d);
+      this.setPreferredSize(d);
+
+      EmptyBorder line1 = new EmptyBorder(2, 2, 2, 2);
+      LineBorder line2 = new LineBorder(Color.BLACK, 1);
+      CompoundBorder cp = new CompoundBorder(line1, line2);
+      this.setBorder(cp);
+      this.setLayout(new BorderLayout());
+
+      field = new JTextArea();
+      Font font = new Font("san-serif", Font.PLAIN, 10);
+      field.setFont(font);
+      field.setBackground(Color.WHITE);
+      field.setLineWrap(true);
+      field.setWrapStyleWord(true);
+
+      this.add(field, BorderLayout.CENTER);
+    }
+
+    public void focusGained(FocusEvent arg0) {
+    }
+
+    public void focusLost(FocusEvent arg0) {
+      field.setText(qPanel.getQuery());
+    }
+
+    public void actionPerformed(ActionEvent arg0) {
+      field.setText(qPanel.getQuery());
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/prompts/SortPrompt.java b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/prompts/SortPrompt.java
new file mode 100644
index 0000000..5da550b
--- /dev/null
+++ b/0.8.1-rc1/app/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/browser/view/prompts/SortPrompt.java
@@ -0,0 +1,153 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.browser.view.prompts;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionListener;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.EmptyBorder;
+
+import org.apache.oodt.cas.filemgr.browser.view.MainWindow;
+
+public class SortPrompt extends JFrame {
+
+  private ColumnPanel cPanel;
+  private ConnectButton cButtons;
+
+  public SortPrompt(MainWindow window, ActionListener listener) {
+    this.setName("Sort");
+    this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+    Dimension d = new Dimension(350, 150);
+    this.setMinimumSize(d);
+    this.setMaximumSize(d);
+    this.setPreferredSize(d);
+
+    this.getContentPane().setLayout(
+        new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS));
+    this.getContentPane().setBackground(Color.WHITE);
+
+    cPanel = new ColumnPanel(window);
+    cButtons = new ConnectButton(listener);
+    this.add(cPanel);
+    this.add(cButtons);
+  }
+
+  public int getSortIndex() {
+    return cPanel.getSortIndex();
+  }
+
+  public String getSortType() {
+    return cPanel.getSortType();
+  }
+
+  protected class ColumnPanel extends JPanel {
+
+    protected JComboBox ColChoices;
+    protected JComboBox SortChoices;
+    protected JButton cancel;
+    protected JButton ok;
+
+    public ColumnPanel(MainWindow window) {
+      ColChoices = new JComboBox(window.getColHeaders());
+      ColChoices.setSelectedIndex(0);
+      ColChoices.setBackground(Color.WHITE);
+      String[] sortPatterns = { "Accending", "Descending" };
+      SortChoices = new JComboBox(sortPatterns);
+      SortChoices.setSelectedIndex(0);
+      SortChoices.setBackground(Color.WHITE);
+
+      Dimension choicesDim = new Dimension(200, 20);
+      ColChoices.setMinimumSize(choicesDim);
+      ColChoices.setMaximumSize(choicesDim);
+      ColChoices.setPreferredSize(choicesDim);
+      SortChoices.setMinimumSize(choicesDim);
+      SortChoices.setMaximumSize(choicesDim);
+      SortChoices.setPreferredSize(choicesDim);
+
+      this.setBackground(Color.WHITE);
+      this.setLayout(new GridBagLayout());
+      GridBagConstraints c = new GridBagConstraints();
+
+      EmptyBorder line1 = new EmptyBorder(5, 10, 5, 5);
+      this.setBorder(line1);
+
+      c.gridx = 0;
+      c.gridy = 0;
+      c.ipadx = 10;
+      c.ipady = 10;
+      this.add(new JLabel("Sort By:  "), c);
+
+      c.gridx = 1;
+      c.gridy = 0;
+      this.add(ColChoices, c);
+
+      c.gridx = 0;
+      c.gridy = 1;
+      this.add(new JLabel("In Order:  "), c);
+
+      c.gridx = 1;
+      c.gridy = 1;
+      this.add(SortChoices, c);
+
+    }
+
+    public int getSortIndex() {
+      return ColChoices.getSelectedIndex();
+    }
+
+    public String getSortType() {
+      return SortChoices.getSelectedItem().toString();
+    }
+
+  }
+
+  private class ConnectButton extends JPanel {
+
+    protected JButton connect;
+    protected JButton cancel;
+
+    protected ConnectButton(ActionListener listener) {
+      this.setBackground(Color.WHITE);
+      this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
+
+      EmptyBorder line1 = new EmptyBorder(5, 20, 5, 5);
+      this.setBorder(line1);
+
+      this.add(new JLabel("                          "));
+      connect = new JButton("OK");
+      connect.setBackground(Color.WHITE);
+      connect.addActionListener(listener);
+      cancel = new JButton("Cancel");
+      cancel.setBackground(Color.WHITE);
+      cancel.addActionListener(listener);
+      cancel.setName("SortCancel");
+      this.add(cancel);
+      this.add(connect);
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/pom.xml b/0.8.1-rc1/app/weditor/pom.xml
new file mode 100644
index 0000000..1e9e1bf
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/pom.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+	<parent>
+		<groupId>org.apache.oodt</groupId>
+		<artifactId>oodt-core</artifactId>
+		<version>0.8.1</version>
+		<relativePath>../../core/pom.xml</relativePath>
+	</parent>
+	<artifactId>weditor</artifactId>
+	<name>Catalog and Archive Workflow Management GUI Editor</name>
+	<description>Apache OODT Workflow Editor GUI</description>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<version>2.2-beta-2</version>
+				<configuration>
+					<descriptors>
+						<descriptor>src/main/assembly/assembly.xml</descriptor>
+					</descriptors>
+				</configuration>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>single</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+		<resources>
+			<resource>
+				<targetPath>org/apache/oodt/cas/workflow/gui/util</targetPath>
+				<directory>${basedir}/src/main/resources/icons</directory>
+				<includes>
+					<include>**</include>
+				</includes>
+			</resource>
+		</resources>
+	</build>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>cas-workflow</artifactId>
+			<version>0.8.1</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.jung</groupId>
+			<artifactId>jung-api</artifactId>
+			<version>2.0.1</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.jung</groupId>
+			<artifactId>jung-visualization</artifactId>
+			<version>2.0.1</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.jung</groupId>
+			<artifactId>jung-algorithms</artifactId>
+			<version>2.0.1</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.jung</groupId>
+			<artifactId>jung-graph-impl</artifactId>
+			<version>2.0.1</version>
+		</dependency>
+        <dependency>
+            <groupId>jgraph</groupId>        
+            <artifactId>jgraph</artifactId>
+            <version>5.13.0.0</version>
+        </dependency>		
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.2</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+</project>
diff --git a/0.8.1-rc1/app/weditor/src/main/assembly/assembly.xml b/0.8.1-rc1/app/weditor/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..f64863d
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/assembly/assembly.xml
@@ -0,0 +1,72 @@
+<!--
+ 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.
+-->
+<assembly>

+  <id>dist</id>

+  <formats>

+    <format>tar.gz</format>
+    <format>zip</format>

+  </formats>

+  <includeBaseDirectory>true</includeBaseDirectory>
+  <baseDirectory>${project.artifactId}-${project.version}</baseDirectory>  
+  <includeSiteDirectory>false</includeSiteDirectory>

+  <fileSets>

+    <fileSet>

+      <directory>${basedir}</directory>

+      <outputDirectory>.</outputDirectory>

+      <includes>

+        <include>LICENSE.txt</include>

+        <include>CHANGES.txt</include>

+      </includes>

+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/bin</directory>
+      <outputDirectory>bin</outputDirectory>
+      <includes/>
+      <fileMode>755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>etc</outputDirectory>
+      <includes>
+        <include>**.properties</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>logs</outputDirectory>
+      <includes>
+        <include>REMOVE.log</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/examples</directory>
+      <outputDirectory>workspace</outputDirectory>
+      <includes>
+        <include>**</include>
+      </includes>
+    </fileSet>

+  </fileSets>

+  <dependencySets>

+    <dependencySet>

+      <outputDirectory>lib</outputDirectory>

+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>

+      <unpackOptions/>

+    </dependencySet>

+  </dependencySets>

+</assembly>

diff --git a/0.8.1-rc1/app/weditor/src/main/bin/weditor b/0.8.1-rc1/app/weditor/src/main/bin/weditor
new file mode 100644
index 0000000..c17df0e
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/bin/weditor
@@ -0,0 +1,22 @@
+#!/bin/csh
+# 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.
+
+${JAVA_HOME}/bin/java \
+	-Djava.ext.dirs=../lib \
+	-Djava.util.logging.config.file=../etc/logging.properties \
+	org.apache.oodt.cas.workflow.gui.WorkflowGUI
+
+
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/WorkflowGUI.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/WorkflowGUI.java
new file mode 100644
index 0000000..954eabe
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/WorkflowGUI.java
@@ -0,0 +1,314 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui;
+
+//JDK imports
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JMenuBar;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowFocusListener;
+import java.io.File;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Vector;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.gui.menu.EditMenu;
+import org.apache.oodt.cas.workflow.gui.menu.FileMenu;
+import org.apache.oodt.cas.workflow.gui.model.ModelGraph;
+import org.apache.oodt.cas.workflow.gui.model.repo.XmlWorkflowModelRepository;
+import org.apache.oodt.cas.workflow.gui.model.repo.XmlWorkflowModelRepositoryFactory;
+import org.apache.oodt.cas.workflow.gui.perspective.MultiStatePerspective;
+import org.apache.oodt.cas.workflow.gui.perspective.build.BuildPerspective;
+import org.apache.oodt.cas.workflow.gui.perspective.view.View;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewState;
+import org.apache.oodt.cas.workflow.gui.toolbox.Tool;
+import org.apache.oodt.cas.workflow.gui.toolbox.ToolBox;
+import org.apache.oodt.cas.workflow.gui.util.IconLoader;
+
+//Commons import
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * 
+ * 
+ * Main driver shell and JFrame for the Workflow Editor GUI.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class WorkflowGUI extends JFrame {
+
+  private static final long serialVersionUID = -8217540440195126377L;
+
+  private ToolBox toolbox;
+
+  private MultiStatePerspective perspective;
+
+  private static AtomicInteger untitledIter = new AtomicInteger(0);
+
+  private JMenuBar menu;
+
+  private File workspace;
+
+  private XmlWorkflowModelRepository repo;
+
+  public WorkflowGUI() throws Exception {
+
+    this.addWindowFocusListener(new WindowFocusListener() {
+
+      public void windowGainedFocus(WindowEvent e) {
+        if (menu != null)
+          menu.revalidate();
+        if (toolbox != null)
+          toolbox.revalidate();
+        if (perspective != null)
+          perspective.refresh();
+      }
+
+      public void windowLostFocus(WindowEvent e) {
+      }
+
+    });
+
+    this.setLayout(new BorderLayout());
+    this.setPreferredSize(new Dimension(1000, 800));
+
+    Vector<Tool> tools = new Vector<Tool>();
+    Tool editTool = new Tool(IconLoader.getIcon(IconLoader.EDIT),
+        IconLoader.getIcon(IconLoader.EDIT_SELECTED)) {
+      private static final long serialVersionUID = 1682845263796161282L;
+
+      @Override
+      public void onClick() {
+        WorkflowGUI.this.perspective.setMode(View.Mode.EDIT);
+      }
+    };
+    tools.add(editTool);
+    Tool deleteTool = new Tool(IconLoader.getIcon(IconLoader.DELETE),
+        IconLoader.getIcon(IconLoader.DELETE_SELECTED)) {
+      private static final long serialVersionUID = 5050127713254634783L;
+
+      @Override
+      public void onClick() {
+        WorkflowGUI.this.perspective.setMode(View.Mode.DELETE);
+      }
+    };
+    tools.add(deleteTool);
+    Tool moveTool = new Tool(IconLoader.getIcon(IconLoader.MOVE),
+        IconLoader.getIcon(IconLoader.MOVE_SELECTED)) {
+      private static final long serialVersionUID = 1682845263796161282L;
+
+      @Override
+      public void onClick() {
+        WorkflowGUI.this.perspective.setMode(View.Mode.MOVE);
+      }
+    };
+    tools.add(moveTool);
+    Tool zoomInTool = new Tool(IconLoader.getIcon(IconLoader.ZOOM_IN),
+        IconLoader.getIcon(IconLoader.ZOOM_IN_SELECTED)) {
+      private static final long serialVersionUID = 1682845263796161282L;
+
+      @Override
+      public void onClick() {
+        WorkflowGUI.this.perspective.setMode(View.Mode.ZOOM_IN);
+      }
+    };
+    tools.add(zoomInTool);
+    Tool zoomOutTool = new Tool(IconLoader.getIcon(IconLoader.ZOOM_OUT),
+        IconLoader.getIcon(IconLoader.ZOOM_OUT_SELECTED)) {
+      private static final long serialVersionUID = 1682845263796161282L;
+
+      @Override
+      public void onClick() {
+        WorkflowGUI.this.perspective.setMode(View.Mode.ZOOM_OUT);
+      }
+    };
+    tools.add(zoomOutTool);
+    toolbox = new ToolBox(tools);
+    toolbox.setSelected(editTool);
+    this.add(toolbox, BorderLayout.NORTH);
+
+    this.setJMenuBar(menu = this.generateMenuBar());
+    perspective = new BuildPerspective();
+    perspective.refresh();
+    this.add(perspective, BorderLayout.CENTER);
+  }
+
+  private void updateWorkspaceText() {
+    if (this.workspace == null)
+      this.setTitle(null);
+    else
+      this.setTitle(StringUtils.leftPad("Workspace: " + this.workspace, 100));
+  }
+
+  private void loadProjects() {
+    try {
+      XmlWorkflowModelRepositoryFactory factory = new XmlWorkflowModelRepositoryFactory();
+      factory.setWorkspace(this.workspace.getAbsolutePath());
+      repo = factory.createModelRepository();
+      repo.loadGraphs(new HashSet<String>(Arrays.asList("sequential",
+          "parallel", "task", "condition")));
+      for (File file : repo.getFiles()) {
+        List<ModelGraph> graphs = new Vector<ModelGraph>();
+        for (ModelGraph graph : repo.getGraphs())
+          if (graph.getModel().getFile().equals(file))
+            graphs.add(graph);
+        System.out.println(graphs);
+        perspective.addState(new ViewState(file, null, graphs, repo
+            .getGlobalConfigGroups()));
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+
+  public JMenuBar generateMenuBar() {
+    JMenuBar bar = new JMenuBar();
+    FileMenu fileMenu = new FileMenu();
+    bar.add(fileMenu);
+    fileMenu.getExit().addActionListener(new ActionListener() {
+      
+      @Override
+      public void actionPerformed(ActionEvent event) {
+        System.exit(1);        
+      }
+    });
+    
+    fileMenu.getOpenWorkspace().addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent event) {
+        try {
+          JFileChooser chooser = new JFileChooser(new File(".")) {
+            boolean acceptFile(File f) {
+              return f.isDirectory();
+            }
+          };
+          chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+          int value = chooser.showOpenDialog(WorkflowGUI.this);
+          if (value == JFileChooser.APPROVE_OPTION) {
+            workspace = chooser.getSelectedFile();
+            updateWorkspaceText();
+            perspective.reset();
+            loadProjects();
+          }
+        } catch (Exception e1) {
+          e1.printStackTrace();
+        }
+      }
+    });
+    fileMenu.getImport().addActionListener(new ActionListener() {
+
+      public void actionPerformed(ActionEvent event) {
+        try {
+          if (workspace == null)
+            return;
+          JFileChooser chooser = new JFileChooser(new File("."));
+          int value = chooser.showOpenDialog(WorkflowGUI.this);
+          if (value == JFileChooser.APPROVE_OPTION) {
+            File file = chooser.getSelectedFile();
+            XmlWorkflowModelRepositoryFactory factory = new XmlWorkflowModelRepositoryFactory();
+            factory.setWorkspace(workspace.getAbsolutePath());
+            View activeView = perspective.getActiveView();
+
+            if (activeView != null) {
+              // TODO: add code for import
+            }
+          }
+        } catch (Exception e) {
+          e.printStackTrace();
+        }
+      }
+
+    });
+    fileMenu.getNewWorkspace().addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent event) {
+        JFileChooser chooser = new JFileChooser(new File(".")) {
+          boolean acceptFile(File f) {
+            return f.isDirectory();
+          }
+        };
+        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+        int value = chooser.showOpenDialog(WorkflowGUI.this);
+        if (value == JFileChooser.APPROVE_OPTION) {
+          workspace = chooser.getSelectedFile();
+          updateWorkspaceText();
+          perspective.reset();
+          loadProjects();
+          perspective.refresh();
+        }
+      }
+    });
+
+    fileMenu.getNewProject().addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent event) {
+        // TODO: add new project code
+      }
+    });
+    fileMenu.getSave().addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent event) {
+      	try {
+      		repo.save();
+      	} catch (Exception e) {
+      		e.printStackTrace();
+      	}
+      }
+    });
+    EditMenu editMenu = new EditMenu();
+    bar.add(editMenu);
+    editMenu.getUndo().addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent event) {
+        try {
+          perspective.undo();
+        } catch (Exception e) {
+          e.printStackTrace();
+        }
+      }
+    });
+    bar.revalidate();
+    return bar;
+  }
+
+  public static void main(String[] args) {
+    UIManager.put("TabbedPane.selected", new Color(238, 238, 238));
+    SwingUtilities.invokeLater(new Runnable() {
+      public void run() {
+        WorkflowGUI gui;
+        try {
+          gui = new WorkflowGUI();
+          gui.pack();
+          gui.setVisible(true);
+        } catch (Exception e) {
+          e.printStackTrace();
+        }
+      }
+    });
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/menu/EditMenu.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/menu/EditMenu.java
new file mode 100644
index 0000000..db10dba
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/menu/EditMenu.java
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.menu;
+
+//JDK imports
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+
+/**
+ * 
+ * 
+ * Edit menu driver for the Workflow Editor GUI.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class EditMenu extends JMenu {
+
+  private static final long serialVersionUID = -8368744697132421274L;
+
+  private JMenuItem undoItem;
+
+  public EditMenu() {
+    super("Edit");
+    this.add(this.undoItem = new JMenuItem("Undo"));
+  }
+
+  public JMenuItem getUndo() {
+    return this.undoItem;
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/menu/FileMenu.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/menu/FileMenu.java
new file mode 100644
index 0000000..599a331
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/menu/FileMenu.java
@@ -0,0 +1,82 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.menu;
+
+//JDK imports
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+
+/**
+ * 
+ * 
+ * File menu driver for the Workflow Editor GUI.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class FileMenu extends JMenu {
+
+  private static final long serialVersionUID = -5702987396916441718L;
+
+  private JMenuItem newWorkspace;
+  private JMenuItem newProject;
+  private JMenuItem openWorkspace;
+  private JMenuItem importItem;
+  private JMenuItem saveItem;
+  private JMenuItem exitItem;
+  private JMenu newMenu, openMenu, importMenu;
+
+  public FileMenu() {
+    super("File");
+    this.add(newMenu = new JMenu("New"));
+    newMenu.add(this.newWorkspace = new JMenuItem("Workspace"));
+    newMenu.add(this.newProject = new JMenuItem("Project"));
+    this.add(openMenu = new JMenu("Open"));
+    openMenu.add(this.openWorkspace = new JMenuItem("Workspace"));
+    this.add(importMenu = new JMenu("Import"));
+    importMenu.add(this.importItem = new JMenuItem("Project"));
+    this.add(this.saveItem = new JMenuItem("Save Project"));
+    this.add(this.exitItem = new JMenuItem("Exit"));
+  }
+
+  public JMenuItem getOpenWorkspace() {
+    return this.openWorkspace;
+  }
+
+  public JMenuItem getImport() {
+    return this.importItem;
+  }
+
+  public JMenuItem getNewWorkspace() {
+    return this.newWorkspace;
+  }
+
+  public JMenuItem getNewProject() {
+    return this.newProject;
+  }
+
+  public JMenuItem getSave() {
+    return this.saveItem;
+  }
+  
+  public JMenuItem getExit(){
+    return this.exitItem;
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/model/ModelGraph.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/model/ModelGraph.java
new file mode 100644
index 0000000..6801340
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/model/ModelGraph.java
@@ -0,0 +1,281 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.model;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewState;
+import org.apache.oodt.cas.workflow.gui.util.GuiUtils;
+
+//JDK imports
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
+
+/**
+ * 
+ * 
+ * The graph to display per workflow in the Workflow Editor GUI.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class ModelGraph {
+
+  private ModelGraph parent;
+  private ModelNode model;
+  private ModelGraph preConditions;
+  private Vector<ModelGraph> children;
+  private ModelGraph postConditions;
+  private boolean isPreCondition;
+  private boolean isPostCondition;
+
+  public ModelGraph(ModelNode model) {
+    this.isPreCondition = isPostCondition = false;
+    this.model = model;
+    this.children = new Vector<ModelGraph>();
+    if (this.model.isParentType())
+      this.addChild(new ModelGraph(GuiUtils.createDummyNode()));
+  }
+
+  public void setIsRef(boolean isRef) {
+    Stack<ModelGraph> stack = new Stack<ModelGraph>();
+    stack.add(this);
+    while (!stack.empty()) {
+      ModelGraph curGraph = stack.pop();
+      curGraph.getModel().setIsRef(isRef);
+      stack.addAll(curGraph.getChildren());
+      if (curGraph.getPreConditions() != null)
+        stack.add(curGraph.getPreConditions());
+      if (curGraph.getPostConditions() != null)
+        stack.add(curGraph.getPostConditions());
+    }
+  }
+
+  public boolean isCondition() {
+    return this.isPreCondition || this.isPostCondition;
+  }
+
+  public boolean isExcused() {
+    return this.parent != null
+        && this.parent.getModel().getExcusedSubProcessorIds()
+            .contains(this.getModel().getModelId());
+  }
+
+  public String getId() {
+    return model.getId();
+  }
+
+  public void setParent(ModelGraph parent) {
+    if (this.parent != null) {
+      if (this.isCondition() && !this.parent.isCondition()) {
+        if (this.isPreCondition)
+          this.parent.preConditions = null;
+        else
+          this.parent.postConditions = null;
+      } else {
+        this.parent.removeChild(this);
+      }
+    }
+    this.parent = parent;
+    if (!this.getModel().isRef() && parent != null && parent.getModel().isRef())
+      this.getModel().setIsRef(true);
+  }
+
+  public ModelGraph getParent() {
+    return this.parent;
+  }
+
+  public ModelGraph getRootParent() {
+    if (this.parent == null)
+      return this;
+    else
+      return this.parent.getRootParent();
+  }
+
+  public List<ModelGraph> getPathFromRootParent() {
+    Vector<ModelGraph> path = new Vector<ModelGraph>();
+    ModelGraph curGraph = this;
+    while (curGraph != null) {
+      path.add(0, curGraph);
+      curGraph = this.parent;
+    }
+    return path;
+  }
+
+  public void addChild(ModelGraph graph) {
+    if (this.children.size() == 1
+        && GuiUtils.isDummyNode(this.children.get(0).getModel()))
+      this.children.clear();
+    this.children.add(graph);
+    graph.setParent(this);
+  }
+
+  public void removeChild(ModelGraph graph) {
+    this.children.remove(graph);
+    this.getModel().getExcusedSubProcessorIds()
+        .remove(graph.getModel().getModelId());
+    graph.parent = null;
+    if (this.children.size() == 0)
+      this.addChild(new ModelGraph(GuiUtils.createDummyNode()));
+  }
+
+  public List<ModelGraph> getChildren() {
+    if (this.getModel().isParentType() && children.size() == 0)
+      this.addChild(new ModelGraph(GuiUtils.createDummyNode()));
+    return children;
+  }
+
+  public boolean hasChildren() {
+    if (this.children.size() == 1
+        && GuiUtils.isDummyNode(this.children.get(0).getModel()))
+      return false;
+    else
+      return this.children.size() > 0;
+  }
+
+  public ModelNode getModel() {
+    return model;
+  }
+
+  public void setModel(ModelNode model) {
+    this.model = model;
+  }
+
+  public Metadata getInheritedStaticMetadata(ViewState state) {
+    Metadata m = new Metadata();
+    if (this.parent != null) {
+      m.replaceMetadata(this.parent.getInheritedStaticMetadata(state));
+      if (this.parent.getModel().getStaticMetadata() != null)
+        m.replaceMetadata(this.parent.getModel().getStaticMetadata());
+      if (this.parent.getModel().getExtendsConfig() != null)
+        for (String configGroup : this.parent.getModel().getExtendsConfig())
+          m.replaceMetadata(state.getGlobalConfigGroups().get(configGroup)
+              .getMetadata());
+    }
+    return m;
+  }
+
+  public ModelGraph getPreConditions() {
+    return preConditions;
+  }
+
+  public void setPreConditions(ModelGraph preConditions) {
+    if (this.preConditions != null)
+      this.preConditions.setParent(null);
+    Stack<ModelGraph> stack = new Stack<ModelGraph>();
+    stack.add(preConditions);
+    while (!stack.empty()) {
+      ModelGraph graph = stack.pop();
+      graph.isPreCondition = true;
+      stack.addAll(graph.getChildren());
+    }
+    (this.preConditions = preConditions).setParent(this);
+  }
+
+  public ModelGraph getPostConditions() {
+    return postConditions;
+  }
+
+  public void setPostConditions(ModelGraph postConditions) {
+    if (this.postConditions != null)
+      this.postConditions.setParent(null);
+    Stack<ModelGraph> stack = new Stack<ModelGraph>();
+    stack.add(postConditions);
+    while (!stack.empty()) {
+      ModelGraph graph = stack.pop();
+      graph.isPostCondition = true;
+      stack.addAll(graph.getChildren());
+    }
+    (this.postConditions = postConditions).setParent(this);
+  }
+
+  public ModelGraph recursiveFind(String id) {
+    Stack<ModelGraph> stack = new Stack<ModelGraph>();
+    stack.add(this);
+    while (!stack.empty()) {
+      ModelGraph curGraph = stack.pop();
+      if (curGraph.getId().equals(id))
+        return curGraph;
+      stack.addAll(curGraph.getChildren());
+      if (curGraph.getPreConditions() != null)
+        stack.add(curGraph.getPreConditions());
+      if (curGraph.getPostConditions() != null)
+        stack.add(curGraph.getPostConditions());
+    }
+    return null;
+  }
+
+  public ModelGraph recursiveFindByModelId(String modelId) {
+    Stack<ModelGraph> stack = new Stack<ModelGraph>();
+    stack.add(this);
+    while (!stack.empty()) {
+      ModelGraph curGraph = stack.pop();
+      if (curGraph.getModel().getModelId().equals(modelId))
+        return curGraph;
+      stack.addAll(curGraph.getChildren());
+      if (curGraph.getPreConditions() != null)
+        stack.add(curGraph.getPreConditions());
+      if (curGraph.getPostConditions() != null)
+        stack.add(curGraph.getPostConditions());
+    }
+    return null;
+  }
+
+  public List<ModelGraph> getLeafNodes() {
+    Vector<ModelGraph> leafNodes = new Vector<ModelGraph>();
+    Stack<ModelGraph> stack = new Stack<ModelGraph>();
+    stack.add(this);
+    while (!stack.empty()) {
+      ModelGraph curGraph = stack.pop();
+      if (curGraph.getChildren().size() == 0)
+        leafNodes.add(curGraph);
+      else
+        stack.addAll(curGraph.getChildren());
+    }
+    return leafNodes;
+  }
+
+  public int hashCode() {
+    return this.getId().hashCode();
+  }
+
+  public boolean equals(Object obj) {
+    if (obj instanceof ModelGraph)
+      return this.getId().equals(((ModelGraph) obj).getId());
+    else
+      return false;
+  }
+
+  public String toString() {
+    return this.getModel().getModelId();
+  }
+
+  public ModelGraph clone() {
+    ModelNode cloneNode = this.model.clone();
+    ModelGraph clone = new ModelGraph(cloneNode);
+    for (ModelGraph child : this.children)
+      clone.addChild(child.clone());
+    if (this.preConditions != null)
+      clone.setPreConditions(this.preConditions.clone());
+    if (this.postConditions != null)
+      clone.setPostConditions(this.postConditions.clone());
+    return clone;
+  }
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/model/ModelNode.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/model/ModelNode.java
new file mode 100644
index 0000000..14283e8
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/model/ModelNode.java
@@ -0,0 +1,367 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.model;
+
+//JDK imports
+import java.awt.Color;
+import java.io.File;
+import java.util.List;
+import java.util.UUID;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * 
+ * Represents a node in the Workflow Model graph.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class ModelNode {
+
+  private String id;
+  private String alias;
+  private boolean isRef;
+  private File file;
+  private boolean textVisible;
+  private boolean entryPoint;
+  private List<String> configGroups;
+  private String executionType;
+  private String modelId;
+  private String modelName;
+  private String instanceClass;
+  private List<String> excusedSubProcessorIds;
+  private Metadata staticMetadata;
+  private long timeout;
+  private boolean optional;
+
+  public ModelNode(File file) {
+    super();
+    this.file = file;
+    this.id = UUID.randomUUID().toString();
+    this.isRef = false;
+    this.executionType = "task";
+    this.textVisible = true;
+    this.entryPoint = false;
+    this.configGroups = new Vector<String>();
+    this.modelId = null;
+    this.modelName = null;
+    this.instanceClass = null;
+    this.excusedSubProcessorIds = new Vector<String>();
+    this.staticMetadata = new Metadata();
+    this.timeout = -1;
+    this.optional = false;
+  }
+
+  public ModelNode(File file, String modelId) {
+    this(file);
+    this.setModelId(modelId);
+    this.setModelName(modelId);
+  }
+
+  public ModelNode(File file, String modelId, boolean isRef) {
+    this(file, modelId);
+    this.isRef = isRef;
+  }
+
+  public String getId() {
+    return this.id;
+  }
+
+  public void setAlias(String alias) {
+  	this.alias = alias;
+  }
+
+  public String getAlias() {
+  	return alias;
+  }
+
+  public void setIsRef(boolean isRef) {
+    this.isRef = isRef;
+  }
+
+  public boolean isRef() {
+    return this.isRef;
+  }
+
+  public File getFile() {
+    return this.file;
+  }
+
+  public void setExtendsConfig(List<String> configGroups) {
+    this.configGroups.clear();
+    this.configGroups.addAll(configGroups);
+  }
+
+  public List<String> getExtendsConfig() {
+    return this.configGroups;
+  }
+
+  public void setTextVisible(boolean textVisible) {
+    this.textVisible = textVisible;
+  }
+
+  public void setEntryPoint(boolean entryPoint) {
+    this.entryPoint = entryPoint;
+  }
+
+  public boolean isEntryPoint() {
+    return this.entryPoint;
+  }
+
+  public boolean isParentType() {
+    return !(this.getExecutionType().equals("task") || this.getExecutionType()
+        .equals("condition"));
+  }
+
+  public Color getColor() {
+    if (this.isParentType()) {
+      if (this.getExecutionType().equals("sequential"))
+        return new Color(100, 149, 237);
+      else if (this.getExecutionType().equals("parallel"))
+        return new Color(143, 188, 143);
+      else
+        return Color.darkGray;
+    } else {
+      if (this.getExecutionType().equals("task"))
+        return Color.orange;
+      else
+        return Color.cyan;
+    }
+  }
+
+  public Color getGradientColor() {
+    if (this.isParentType()) {
+      if (this.getExecutionType().equals("sequential"))
+        return new Color(200, 200, 200);
+      else if (this.getExecutionType().equals("parallel"))
+        return new Color(200, 200, 200);
+      else
+        return Color.white;
+    } else {
+      return Color.darkGray;
+    }
+  }
+
+  public String getModelId() {
+    return modelId;
+  }
+
+  public String getModelName() {
+    if (modelName == null) {
+      return modelId;
+    } else {
+      return modelName;
+    }
+  }
+
+  public String getExecutionType() {
+    return executionType;
+  }
+
+  public String getInstanceClass() {
+    return instanceClass;
+  }
+
+  public List<String> getExcusedSubProcessorIds() {
+    if (this.excusedSubProcessorIds == null)
+      this.excusedSubProcessorIds = new Vector<String>();
+    return this.excusedSubProcessorIds;
+  }
+
+  public Metadata getStaticMetadata() {
+    return staticMetadata != null ? this.staticMetadata
+        : (this.staticMetadata = new Metadata());
+  }
+
+  public int hashCode() {
+    return this.getId().hashCode();
+  }
+
+  public boolean equals(Object obj) {
+    if (obj instanceof ModelNode)
+      return this.getId().equals(((ModelNode) obj).getId());
+    else
+      return false;
+  }
+
+  public String toString() {
+    if (this.textVisible) {
+      if (this.isParentType())
+        return this.getModelName() + " : " + this.getExecutionType();
+      else
+        return this.getModelName();
+    } else {
+      return null;
+    }
+  }
+
+  public ModelNode clone() {
+    ModelNode clone = new ModelNode(this.file);
+    clone.id = this.id;
+    if (this.excusedSubProcessorIds != null)
+      clone.excusedSubProcessorIds = new Vector<String>(
+          this.excusedSubProcessorIds);
+    clone.executionType = this.executionType;
+    clone.instanceClass = this.instanceClass;
+    clone.modelId = this.modelId;
+    clone.modelName = this.modelName;
+    clone.staticMetadata = null;
+    clone.textVisible = this.textVisible;
+    if (this.staticMetadata != null)
+      clone.staticMetadata = new Metadata(this.staticMetadata);
+    return clone;
+  }
+
+  /**
+   * @param modelId
+   *          the modelId to set
+   */
+  public void setModelId(String modelId) {
+    this.modelId = modelId;
+  }
+
+  /**
+   * @param modelName
+   *          the modelName to set
+   */
+  public void setModelName(String modelName) {
+    this.modelName = modelName;
+  }
+
+  /**
+   * @param instanceClass
+   *          the instanceClass to set
+   */
+  public void setInstanceClass(String instanceClass) {
+    this.instanceClass = instanceClass;
+  }
+
+  /**
+   * @param excusedSubProcessorIds
+   *          the excusedSubProcessorIds to set
+   */
+  public void setExcusedSubProcessorIds(List<String> excusedSubProcessorIds) {
+    this.excusedSubProcessorIds = excusedSubProcessorIds;
+  }
+
+
+
+  /**
+   * @return the configGroups
+   */
+  public List<String> getConfigGroups() {
+    return configGroups;
+  }
+
+
+
+  /**
+   * @param configGroups the configGroups to set
+   */
+  public void setConfigGroups(List<String> configGroups) {
+    this.configGroups = configGroups;
+  }
+
+
+
+  /**
+   * @return the textVisible
+   */
+  public boolean isTextVisible() {
+    return textVisible;
+  }
+
+
+
+  /**
+   * @param id the id to set
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+
+
+  /**
+   * @param isRef the isRef to set
+   */
+  public void setRef(boolean isRef) {
+    this.isRef = isRef;
+  }
+
+
+
+  /**
+   * @param file the file to set
+   */
+  public void setFile(File file) {
+    this.file = file;
+  }
+
+
+
+  /**
+   * @param executionType the executionType to set
+   */
+  public void setExecutionType(String executionType) {
+    this.executionType = executionType;
+  }
+
+
+
+  /**
+   * @param staticMetadata the staticMetadata to set
+   */
+  public void setStaticMetadata(Metadata staticMetadata) {
+    this.staticMetadata = staticMetadata;
+  }
+
+  /**
+   * @return the timeout
+   */
+  public long getTimeout() {
+    return timeout;
+  }
+
+  /**
+   * @param timeout the timeout to set
+   */
+  public void setTimeout(long timeout) {
+    this.timeout = timeout;
+  }
+
+  /**
+   * @return the optional
+   */
+  public boolean isOptional() {
+    return optional;
+  }
+
+  /**
+   * @param optional the optional to set
+   */
+  public void setOptional(boolean optional) {
+    this.optional = optional;
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/model/repo/XmlWorkflowModelRepository.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/model/repo/XmlWorkflowModelRepository.java
new file mode 100644
index 0000000..2767d60
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/model/repo/XmlWorkflowModelRepository.java
@@ -0,0 +1,597 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.model.repo;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.gui.model.ModelGraph;
+import org.apache.oodt.cas.workflow.gui.model.ModelNode;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JDK imports
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathFactory;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * 
+ * Model Repository which stores models in xml files
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class XmlWorkflowModelRepository {
+
+  private File workspace;
+  private List<File> files;
+  private Set<ModelGraph> graphs;
+  private Map<String, ConfigGroup> globalConfigGroups;
+  private static final Logger LOG = Logger
+      .getLogger(XmlWorkflowModelRepository.class.getName());
+
+  public XmlWorkflowModelRepository(File workspace) {
+    this.files = new Vector<File>();
+    for (File file : (this.workspace = workspace).listFiles())
+      if (!file.isDirectory())
+        this.files.add(file);
+  }
+
+  public void loadGraphs(Set<String> supportedProcessorIds) throws Exception {
+    this.graphs = new HashSet<ModelGraph>();
+    HashMap<String, ConfigGroup> globalConfGroups = new HashMap<String, ConfigGroup>();
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    factory.setNamespaceAware(true);
+    DocumentBuilder parser = factory.newDocumentBuilder();
+    List<FileBasedElement> rootElements = new Vector<FileBasedElement>();
+    for (File file : files) {
+      System.out.println("Loading: " + file);
+      rootElements.add(new FileBasedElement(file, parser.parse(file)
+          .getDocumentElement()));
+    }
+    for (FileBasedElement root : rootElements) {
+      loadConfiguration(rootElements, root, null, globalConfGroups);
+      NodeList rootChildren = root.getElement().getChildNodes();
+      for (int i = 0; i < rootChildren.getLength(); i++)
+        if (rootChildren.item(i).getNodeType() == Node.ELEMENT_NODE
+            && !rootChildren.item(i).getNodeName().equals("configuration")
+            && !rootChildren.item(i).getNodeName().equals("event")) {
+          System.out.println("node name: ["
+              + rootChildren.item(i).getNodeName() + "]");
+          ModelGraph graph = this.loadGraph(rootElements, new FileBasedElement(
+              root.getFile(), (Element) rootChildren.item(i)), new Metadata(),
+              globalConfGroups, supportedProcessorIds);
+          this.graphs.add(graph);
+        }
+    }
+    ensureUniqueIds(graphs);
+    this.globalConfigGroups = globalConfGroups;
+    System.out.println(this.globalConfigGroups.keySet());
+  }
+
+  public Set<ModelGraph> getGraphs() {
+    return this.graphs;
+  }
+
+  public Map<String, ConfigGroup> getGlobalConfigGroups() {
+    return this.globalConfigGroups;
+  }
+
+  public void setGlobalConfigGroups(Map<String, ConfigGroup> globalConfigGroups) {
+    this.globalConfigGroups = new HashMap<String, ConfigGroup>(
+        globalConfigGroups);
+  }
+
+  public List<File> getFiles() {
+    return this.files;
+  }
+
+  public void save() throws Exception {
+    this.backupCurrentFiles();
+    this.saveGraphs();
+  }
+
+  private void backupCurrentFiles() throws Exception {
+    File backupDir = new File(this.workspace, ".backup");
+    for (File file : this.files) {
+      FileUtils.copyFile(file, new File(backupDir, file.getName()));
+      file.delete();
+    }
+    this.files.clear();
+  }
+
+  private void saveGraphs() throws FileNotFoundException,
+      ParserConfigurationException {
+    Map<File, Document> documents = new HashMap<File, Document>();
+    for (ModelGraph graph : this.graphs) {
+      Document document = documents.get(graph.getModel().getFile());
+      if (document == null) {
+        document = createDocument();
+        document.appendChild(document.createElement("workflows"));
+        documents.put(graph.getModel().getFile(), document);
+      }
+      saveGraph(graph, document.getDocumentElement(), document);
+    }
+    saveGlobalConfigGroups(documents);
+    writeOutDocuments(documents);
+    this.files = new ArrayList<File>(documents.keySet());
+  }
+
+  private void writeOutDocuments(Map<File, Document> documents) {
+    for (File file : documents.keySet()) {
+      XMLUtils.writeXmlFile(documents.get(file), file.getAbsolutePath());
+    }
+  }
+
+  private void saveGlobalConfigGroups(Map<File, Document> documents)
+      throws ParserConfigurationException {
+    File globalConfigGroupsFile = new File(workspace,
+        "shared-configuration.xml");
+    Document document = documents.get(globalConfigGroupsFile);
+    if (document == null) {
+      document = createDocument();
+      document.appendChild(document.createElement("workflows"));
+      documents.put(globalConfigGroupsFile, document);
+    }
+    for (String configName : this.globalConfigGroups.keySet()) {
+      ConfigGroup globalConfig = this.globalConfigGroups.get(configName);
+      Element configElem = document.createElement("configuration");
+      document.getDocumentElement().appendChild(configElem);
+      configElem.setAttribute("name", globalConfig.getName());
+      if (!globalConfig.getExtends().isEmpty()) {
+        configElem.setAttribute("extends",
+            StringUtils.join(globalConfig.getExtends(), ", "));
+      }
+
+      String[] properties = globalConfig.getMetadata().getAllKeys()
+          .toArray(new String[globalConfig.getMetadata().getAllKeys().size()]);
+      Arrays.sort(properties);
+      for (String property : properties) {
+        Element propElem = document.createElement("property");
+        configElem.appendChild(propElem);
+        propElem.setAttribute("name", property);
+        propElem.setAttribute("value",
+            globalConfig.getMetadata().getMetadata(property));
+      }
+    }
+  }
+
+  private void saveGraph(ModelGraph graph, Element parentElem, Document document)
+      throws FileNotFoundException, ParserConfigurationException {
+    ModelNode node = graph.getModel();
+
+    Element workflowElem = document.createElement(node.getExecutionType());
+    parentElem.appendChild(workflowElem);
+
+    if (node.isRef()) {
+      workflowElem.setAttribute("id-ref", node.getModelId());
+      if (node.getAlias() != null) {
+        workflowElem.setAttribute("alias", node.getAlias());
+      }
+      saveConfiguration(node, workflowElem, document);
+    } else {
+      workflowElem.setAttribute("id", node.getModelId());
+      workflowElem.setAttribute("name", node.getModelName());
+      if (node.getInstanceClass() != null) {
+        workflowElem.setAttribute("class", node.getInstanceClass());
+      }
+
+      saveConfiguration(node, workflowElem, document);
+
+      // handle preconditions
+      if (graph.getPreConditions() != null) {
+        Element preConditions = document.createElement("conditions");
+        workflowElem.appendChild(preConditions);
+        preConditions.setAttribute("type", "pre");
+        preConditions.setAttribute("execution", graph.getPreConditions()
+            .getModel().getExecutionType());
+        preConditions.setAttribute("timeout", String.valueOf(graph.getModel().getTimeout()));
+        preConditions.setAttribute("optional", String.valueOf(graph.getModel().isOptional()));
+        for (ModelGraph preCondition : graph.getPreConditions().getChildren()) {
+          saveGraph(preCondition, preConditions, document);
+        }
+      }
+
+      // handle subprocessors
+      for (ModelGraph subProcessor : graph.getChildren()) {
+        saveGraph(subProcessor, workflowElem, document);
+      }
+
+      // handle postconditions
+      if (graph.getPostConditions() != null) {
+        Element postConditions = document.createElement("conditions");
+        workflowElem.appendChild(postConditions);
+        postConditions.setAttribute("type", "post");
+        postConditions.setAttribute("execution", graph.getPostConditions()
+            .getModel().getExecutionType());
+        postConditions.setAttribute("timeout", String.valueOf(graph.getModel().getTimeout()));
+        postConditions.setAttribute("optional", String.valueOf(graph.getModel().isOptional()));
+        for (ModelGraph postCondition : graph.getPostConditions().getChildren()) {
+          saveGraph(postCondition, postConditions, document);
+        }
+      }
+    }
+    if (!node.getExcusedSubProcessorIds().isEmpty()) {
+      workflowElem.setAttribute("excused",
+          StringUtils.join(node.getExcusedSubProcessorIds(), ","));
+    }
+    if (node.isEntryPoint()) {
+      workflowElem.setAttribute("entryPoint", "true");
+    }
+  }
+
+  private void saveConfiguration(ModelNode node, Element workflowElem,
+      Document document) {
+    if (!node.getStaticMetadata().getAllKeys().isEmpty()) {
+      Element configElem = document.createElement("configuration");
+      workflowElem.appendChild(configElem);
+      if (!node.getExtendsConfig().isEmpty()) {
+        configElem.setAttribute("extends",
+            StringUtils.join(node.getExtendsConfig(), ", "));
+      }
+      String[] properties = node.getStaticMetadata().getAllKeys()
+          .toArray(new String[node.getStaticMetadata().getAllKeys().size()]);
+      Arrays.sort(properties);
+      for (String property : properties) {
+        Element propElem = document.createElement("property");
+        configElem.appendChild(propElem);
+        propElem.setAttribute("name", property);
+        propElem.setAttribute("value",
+            node.getStaticMetadata().getMetadata(property));
+      }
+    }
+  }
+
+  private Document createDocument() throws ParserConfigurationException {
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    factory.setNamespaceAware(true);
+    return factory.newDocumentBuilder().newDocument();
+  }
+
+  private void ensureUniqueIds(Set<ModelGraph> graphs) {
+    for (ModelGraph graph : graphs) {
+      HashSet<String> names = new HashSet<String>();
+      Vector<ModelGraph> stack = new Vector<ModelGraph>();
+      stack.add(graph);
+      while (!stack.isEmpty()) {
+        ModelGraph currentGraph = stack.remove(0);
+        String currentId = currentGraph.getId();
+        for (int i = 1; names.contains(currentId); i++)
+          currentId = currentGraph.getId() + "-" + i;
+        names.add(currentId);
+        if (!currentId.equals(currentGraph.getId()))
+          currentGraph.getModel().setModelId(currentId);
+        stack.addAll(currentGraph.getChildren());
+      }
+    }
+  }
+
+  private ModelGraph loadGraph(List<FileBasedElement> rootElements,
+      FileBasedElement workflowNode, Metadata staticMetadata,
+      HashMap<String, ConfigGroup> globalConfGroups,
+      Set<String> supportedProcessorIds) throws Exception {
+
+    String modelIdRef = null;
+    String modelId = null;
+    String modelName = null;
+    String alias = null;
+    String executionType = null;
+    List<String> excused = new Vector<String>();
+    String clazz = null;
+    long timeout = -1;
+    boolean optional = false;
+    boolean entryPoint = false;
+
+    NamedNodeMap attributes = workflowNode.getElement().getAttributes();
+    for (int i = 0; attributes != null && i < attributes.getLength(); i++) {
+      Node node = workflowNode.getElement().getAttributes().item(i);
+      if (node.getNodeName().equals("id")) {
+        modelId = node.getNodeValue();
+      } else if (node.getNodeName().equals("name")) {
+        modelName = node.getNodeValue();
+      } else if (node.getNodeName().equals("class")) {
+        clazz = node.getNodeValue();
+      } else if (node.getNodeName().equals("id-ref")) {
+        modelIdRef = node.getNodeValue();
+      } else if (node.getNodeName().equals("excused")) {
+        excused.addAll(Arrays.asList(node.getNodeValue().split(",")));
+      } else if (node.getNodeName().equals("entryPoint")) {
+        entryPoint = Boolean.parseBoolean(node.getNodeValue());
+      } else if (node.getNodeName().equals("alias")) {
+        alias = node.getNodeValue();
+      } else if (node.getNodeName().equals("execution")) {
+        executionType = node.getNodeValue();
+      } else if (node.getNodeName().equals("timeout")) {
+        timeout = node.getNodeValue() != null
+            && !node.getNodeValue().equals("") ? Long.valueOf(node
+            .getNodeValue()) : -1;
+      } 
+      else if(node.getNodeName().equals("optional")){
+        optional = Boolean.valueOf(node.getNodeValue());
+      }
+        else if (node.getNodeName().startsWith("p:")) {
+        staticMetadata.replaceMetadata(node.getNodeName().substring(2),
+            node.getNodeValue());
+      }
+    }
+
+    if (modelId == null && modelIdRef == null)
+      modelId = UUID.randomUUID().toString();
+
+    ModelGraph graph = null;
+    if (modelId != null) {
+
+      if (workflowNode.getElement().getNodeName().equals("workflow")
+          || workflowNode.getElement().getNodeName().equals("conditions")
+          || workflowNode.getElement().getNodeName().equals("tasks")) {
+        if (executionType == null) {
+          LOG.log(Level.WARNING, "workflow model '"
+              + workflowNode.getElement().getNodeName()
+              + "' missing execution type: assuming sequential");
+          executionType = "sequential";
+        }
+      } else {
+        executionType = workflowNode.getElement().getNodeName();
+      }
+
+      if (!supportedProcessorIds.contains(executionType))
+        LOG.log(Level.WARNING, "Unsupported execution type id '"
+            + executionType + "'");
+
+      ModelNode modelNode = new ModelNode(workflowNode.getFile());
+      modelNode.setModelId(modelId);
+      modelNode.setModelName(modelName);
+      modelNode.setExecutionType(executionType);
+      modelNode.setStaticMetadata(staticMetadata);
+      modelNode.setExcusedSubProcessorIds(excused);
+      modelNode.setInstanceClass(clazz);
+      modelNode.setEntryPoint(entryPoint);
+      modelNode.setTimeout(timeout);
+      modelNode.setOptional(optional);
+
+      loadConfiguration(rootElements, workflowNode, modelNode, globalConfGroups);
+
+      graph = new ModelGraph(modelNode);
+
+      boolean loadedPreConditions = false;
+      NodeList children = workflowNode.getElement().getChildNodes();
+      for (int i = 0; i < children.getLength(); i++) {
+        Node curChild = children.item(i);
+        if (curChild.getNodeType() == Node.ELEMENT_NODE) {
+          if (curChild.getNodeName().equals("conditions")) {
+            boolean isPreCondition = !loadedPreConditions;
+            String type = ((Element) curChild).getAttribute("type");
+            if (type.length() > 0)
+              isPreCondition = type.toLowerCase().equals("pre");
+            if (isPreCondition)
+              graph.setPreConditions(this.loadGraph(rootElements,
+                  new FileBasedElement(workflowNode.getFile(),
+                      (Element) curChild), new Metadata(staticMetadata),
+                  globalConfGroups, supportedProcessorIds));
+            else
+              graph.setPostConditions(this.loadGraph(rootElements,
+                  new FileBasedElement(workflowNode.getFile(),
+                      (Element) curChild), new Metadata(staticMetadata),
+                  globalConfGroups, supportedProcessorIds));
+            loadedPreConditions = true;
+          } else if (!curChild.getNodeName().equals("configuration")
+              && !curChild.getNodeName().equals("requiredMetFields")) {
+            graph.addChild(this.loadGraph(rootElements, new FileBasedElement(
+                workflowNode.getFile(), (Element) curChild), new Metadata(
+                staticMetadata), globalConfGroups, supportedProcessorIds));
+
+          }
+        }
+      }
+
+    } else if (modelIdRef != null) {
+      graph = this.findGraph(rootElements, modelIdRef, new Metadata(
+          staticMetadata), globalConfGroups, supportedProcessorIds);
+      if (graph == null)
+        throw new Exception("Workflow '" + modelIdRef
+            + "' has not been defined in this context");
+      graph.setIsRef(true);
+      graph.getModel().setStaticMetadata(new Metadata());
+      loadConfiguration(rootElements, workflowNode, graph.getModel(),
+          globalConfGroups);
+      graph.getModel().setAlias(alias);
+    }
+
+    if (entryPoint && graph.getParent() != null) {
+      this.graphs.add(graph);
+    }
+
+    return graph;
+  }
+
+  protected ModelGraph findGraph(List<FileBasedElement> rootElements,
+      String modelIdRef, Metadata staticMetadata,
+      HashMap<String, ConfigGroup> globalConfGroups,
+      Set<String> supportedProcessorIds) throws Exception {
+    XPath xpath = XPathFactory.newInstance().newXPath();
+    XPathExpression expr = xpath.compile("//*[@id = '" + modelIdRef + "']");
+    for (FileBasedElement rootElement : rootElements) {
+      Node node = (Node) expr.evaluate(rootElement.getElement(),
+          XPathConstants.NODE);
+      if (node != null) {
+        return this.loadGraph(rootElements,
+            new FileBasedElement(rootElement.getFile(), (Element) node),
+            staticMetadata, globalConfGroups, supportedProcessorIds);
+      }
+    }
+    return null;
+  }
+
+  private void loadConfiguration(List<FileBasedElement> rootElements,
+      FileBasedElement workflowNode, ModelNode modelNode,
+      HashMap<String, ConfigGroup> globalConfGroups) throws Exception {
+    NodeList children = workflowNode.getElement().getChildNodes();
+    for (int i = 0; i < children.getLength(); i++) {
+      Node curChild = children.item(i);
+      if (curChild.getNodeName().equals("configuration")) {
+        Metadata curMetadata = new Metadata();
+        if (modelNode != null
+            && !((Element) curChild).getAttribute("extends").equals(""))
+          modelNode.setExtendsConfig(Arrays.asList(((Element) curChild)
+              .getAttribute("extends").split(",")));
+        curMetadata.replaceMetadata(this.loadConfiguration(rootElements,
+            curChild, globalConfGroups));
+        if (!((Element) curChild).getAttribute("name").equals("")) {
+          ConfigGroup configGroup = new ConfigGroup(
+              ((Element) curChild).getAttribute("name"), curMetadata);
+          if (modelNode != null) {
+            List<String> extendsConfig = new Vector<String>(
+                modelNode.getExtendsConfig());
+            configGroup.addAllExtends(extendsConfig);
+            extendsConfig.add(configGroup.getName());
+            modelNode.setExtendsConfig(extendsConfig);
+          }
+          globalConfGroups.put(((Element) curChild).getAttribute("name"),
+              configGroup);
+        } else if (modelNode != null) {
+          modelNode.setStaticMetadata(curMetadata);
+        }
+      }
+    }
+  }
+
+  private Metadata loadConfiguration(List<FileBasedElement> rootElements,
+      Node configNode, HashMap<String, ConfigGroup> globalConfGroups)
+      throws Exception {
+    Metadata curMetadata = new Metadata();
+    NodeList curGrandChildren = configNode.getChildNodes();
+    for (int k = 0; k < curGrandChildren.getLength(); k++) {
+      if (curGrandChildren.item(k).getNodeName().equals("property")) {
+        Element property = (Element) curGrandChildren.item(k);
+        String delim = property.getAttribute("delim");
+        String envReplace = property.getAttribute("envReplace");
+        String name = property.getAttribute("name");
+        String value = property.getAttribute("value");
+        if (Boolean.parseBoolean(envReplace))
+          curMetadata.replaceMetadata(name + "/envReplace", "true");
+        List<String> values = new Vector<String>();
+        if (delim.length() > 0)
+          values.addAll(Arrays.asList(value.split("\\" + delim)));
+        else
+          values.add(value);
+        curMetadata.replaceMetadata(name, values);
+      }
+    }
+    return curMetadata;
+  }
+
+  private class FileBasedElement {
+
+    private File file;
+    private Element element;
+
+    public FileBasedElement(File file, Element element) {
+      this.file = file;
+      this.element = element;
+    }
+
+    public File getFile() {
+      return this.file;
+    }
+
+    public Element getElement() {
+      return this.element;
+    }
+
+  }
+
+  public class ConfigGroup {
+
+    private String name;
+    private Metadata metadata;
+    private List<String> extendsConfig;
+
+    public ConfigGroup(String name, Metadata metadata) {
+      this.name = name;
+      this.metadata = metadata;
+      this.extendsConfig = new Vector<String>();
+    }
+
+    public String getName() {
+      return this.name;
+    }
+
+    public Metadata getMetadata() {
+      return this.metadata;
+    }
+
+    public void addExtends(String child) {
+      this.extendsConfig.add(child);
+    }
+
+    public void addAllExtends(List<String> children) {
+      this.extendsConfig.addAll(children);
+    }
+
+    public void removeExtends(String child) {
+      this.extendsConfig.remove(child);
+    }
+
+    public List<String> getExtends() {
+      return this.extendsConfig;
+    }
+
+    public int hashCode() {
+      return this.name.hashCode();
+    }
+
+    public boolean equals(Object obj) {
+      if (obj instanceof ConfigGroup) {
+        ConfigGroup comp = (ConfigGroup) obj;
+        return comp.name.equals(this.name);
+      } else
+        return false;
+    }
+
+    public String toString() {
+      return this.name;
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/model/repo/XmlWorkflowModelRepositoryFactory.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/model/repo/XmlWorkflowModelRepositoryFactory.java
new file mode 100644
index 0000000..704b071
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/model/repo/XmlWorkflowModelRepositoryFactory.java
@@ -0,0 +1,47 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.model.repo;
+
+//JDK imports
+import java.io.File;
+
+/**
+ * 
+ * Factory for creating xml model repositories
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class XmlWorkflowModelRepositoryFactory {
+
+  private String workspace;
+
+  public XmlWorkflowModelRepository createModelRepository() {
+    if (workspace == null)
+      return null;
+    if (!new File(workspace).exists())
+      new File(workspace).mkdirs();
+    return new XmlWorkflowModelRepository(new File(workspace));
+  }
+
+  public void setWorkspace(String workspace) {
+    this.workspace = workspace;
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/MultiStatePerspective.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/MultiStatePerspective.java
new file mode 100644
index 0000000..b55f7f5
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/MultiStatePerspective.java
@@ -0,0 +1,102 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective;
+
+//JDK imports
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewState;
+import org.apache.oodt.cas.workflow.gui.perspective.view.View.Mode;
+
+/**
+ * 
+ * A multi-state display perspective.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public abstract class MultiStatePerspective extends Perspective {
+
+  private static final long serialVersionUID = -6410768713084872977L;
+
+  private final Map<String, ViewState> states = new HashMap<String, ViewState>();
+
+  private Mode mode;
+
+  public MultiStatePerspective(String name) {
+    super(name);
+    this.mode = Mode.EDIT;
+  }
+
+  public void addState(ViewState state) {
+    this.setState(state);
+  }
+
+  public void setState(ViewState state) {
+    super.setState(state);
+    state.setMode(this.mode);
+    if (!this.states.containsKey(state.getId())) {
+      this.states.put(state.getId(), state);
+      this.handleAddState(state);
+    }
+  }
+
+  public void removeState(ViewState state) {
+    this.states.remove(state);
+    this.handleRemoveState(state);
+    super.setState(this.getActiveState());
+  }
+
+  public ViewState getState(String stateId) {
+    return this.states.get(stateId);
+  }
+
+  public List<ViewState> getStates() {
+    return new Vector<ViewState>(this.states.values());
+  }
+
+  public Set<String> getStateIds() {
+    return this.states.keySet();
+  }
+
+  public void setMode(Mode mode) {
+    this.mode = mode;
+    for (ViewState state : states.values())
+      state.setMode(mode);
+    this.refresh();
+  }
+
+  public void reset() {
+    super.reset();
+    this.mode = Mode.EDIT;
+    states.clear();
+  }
+
+  public abstract void handleAddState(ViewState state);
+
+  public abstract void handleRemoveState(ViewState state);
+
+  public abstract ViewState getActiveState();
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/Perspective.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/Perspective.java
new file mode 100644
index 0000000..c19eda0
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/Perspective.java
@@ -0,0 +1,86 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective;
+
+//JDK imports
+import javax.swing.JPanel;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.gui.perspective.view.View;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewListener;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewState;
+import org.apache.oodt.cas.workflow.gui.perspective.view.View.Mode;
+
+/**
+ * 
+ * 
+ * A view listener and jpanel for keeping the Workflow perspective in sync.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public abstract class Perspective extends JPanel implements ViewListener {
+
+  private static final long serialVersionUID = -3343805159396435882L;
+
+  private ViewState state;
+  private String name;
+
+  public Perspective(String name) {
+    this.name = name;
+  }
+
+  public String getName() {
+    return this.name;
+  }
+
+  public ViewState getState() {
+    return this.state;
+  }
+
+  public void setState(ViewState state) {
+    this.state = state;
+  }
+
+  public void setMode(Mode mode) {
+    this.state.setMode(mode);
+    this.refresh();
+  }
+
+  public void save() {
+    if (this.state != null)
+      this.state.save();
+  }
+
+  public void undo() {
+    if (this.state != null) {
+      this.state.undo();
+      this.refresh();
+    }
+  }
+
+  public void reset() {
+    this.state = null;
+  }
+
+  public abstract void refresh();
+
+  public abstract View getActiveView();
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/build/BuildPerspective.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/build/BuildPerspective.java
new file mode 100644
index 0000000..2d7416b
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/build/BuildPerspective.java
@@ -0,0 +1,425 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective.build;
+
+//JDK imports
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JSplitPane;
+import javax.swing.JTabbedPane;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.gui.model.ModelGraph;
+import org.apache.oodt.cas.workflow.gui.perspective.MultiStatePerspective;
+import org.apache.oodt.cas.workflow.gui.perspective.view.MultiStateView;
+import org.apache.oodt.cas.workflow.gui.perspective.view.View;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewChange;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewListener;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewState;
+import org.apache.oodt.cas.workflow.gui.perspective.view.impl.DefaultPropView;
+import org.apache.oodt.cas.workflow.gui.perspective.view.impl.DefaultTreeView;
+import org.apache.oodt.cas.workflow.gui.perspective.view.impl.GlobalConfigView;
+import org.apache.oodt.cas.workflow.gui.perspective.view.impl.GraphView;
+import org.apache.oodt.cas.workflow.gui.perspective.view.impl.TreeProjectView;
+import org.apache.oodt.cas.workflow.gui.util.GuiUtils;
+
+/**
+ * 
+ * The default build perspective.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class BuildPerspective extends MultiStatePerspective {
+
+  private static final long serialVersionUID = 3387632819576057527L;
+
+  private View projectView;
+  private View globalConfigView;
+  private Class<? extends View> projectViewClass;
+  private Class<? extends View> mainViewClass;
+  private Class<? extends View> treeViewClass;
+  private Class<? extends View> propViewClass;
+  private Class<? extends View> globalViewClass;
+
+  private HashMap<ViewState, BuildPanel> stateViews;
+  private ViewState activeState;
+
+  public static final int MAIN_VIEW = 1;
+
+  private static final int WIDTH = 1000;
+  private static final int HEIGHT = 700;
+
+  private JSplitPane projectSplitPane;
+
+  private boolean findSelectedInTab = false;
+
+  public BuildPerspective() throws InstantiationException,
+      IllegalAccessException {
+    this(TreeProjectView.class, GraphView.class, DefaultTreeView.class,
+        DefaultPropView.class, GlobalConfigView.class);
+  }
+
+  public BuildPerspective(Class<? extends View> projectViewClass,
+      Class<? extends View> mainViewClass, Class<? extends View> treeViewClass,
+      Class<? extends View> propViewClass, Class<? extends View> globalViewClass)
+      throws InstantiationException, IllegalAccessException {
+    super("Build");
+    this.projectViewClass = projectViewClass;
+    this.mainViewClass = mainViewClass;
+    this.treeViewClass = treeViewClass;
+    this.propViewClass = propViewClass;
+    this.globalViewClass = globalViewClass;
+    this.stateViews = new HashMap<ViewState, BuildPanel>();
+    this.projectView = this.createProjectView();
+    this.projectView.setPreferredSize(new Dimension(WIDTH / 10, HEIGHT / 2));
+    this.globalConfigView = this.createGlobalConfigView();
+    this.globalConfigView
+        .setPreferredSize(new Dimension(WIDTH / 10, HEIGHT / 2));
+  }
+
+  public void reset() {
+    super.reset();
+    this.activeState = null;
+    this.stateViews.clear();
+    this.projectView = this.createProjectView();
+    this.globalConfigView = this.createGlobalConfigView();
+  }
+
+  public void stateChangeNotify(ViewChange<?> change) {
+    if (change instanceof ViewChange.NEW_ACTIVE_STATE) {
+      this.activeState = ((ViewChange.NEW_ACTIVE_STATE) change).getObject();
+      this.refresh();
+    } else if (change instanceof ViewChange.REFRESH_VIEW) {
+      this.refresh();
+    } else if (change instanceof ViewChange.STATE_NAME_CHANGE) {
+      ViewState state = ((ViewChange.STATE_NAME_CHANGE) change).getObject();
+      this.refresh();
+    } else if (change instanceof ViewChange.VIEW_MODEL) {
+      String modelId = ((ViewChange.VIEW_MODEL) change).getObject();
+      for (ViewState state : this.stateViews.keySet()) {
+        for (ModelGraph graph : state.getGraphs()) {
+          ModelGraph found = graph.recursiveFindByModelId(modelId);
+          if (found != null && !found.getModel().isRef()) {
+            this.activeState = state;
+            this.activeState.setSelected(found);
+            break;
+          }
+        }
+      }
+      this.findSelectedInTab = true;
+      this.refresh();
+      this.findSelectedInTab = false;
+    }
+  }
+
+  @Override
+  public ViewState getActiveState() {
+    return this.activeState;
+  }
+
+  public View getActiveView() {
+    if (this.getActiveState() != null)
+      return this.stateViews.get(this.getActiveState()).getActiveView();
+    else
+      return null;
+  }
+
+  @Override
+  public void handleAddState(final ViewState state) {
+    this.activeState = state;
+    BuildPanel buildPanel = new BuildPanel(state);
+    this.stateViews.put(state, buildPanel);
+    this.refresh();
+  }
+
+  @Override
+  public void handleRemoveState(ViewState state) {
+    this.stateViews.remove(state);
+    if (this.stateViews.size() > 0)
+      this.activeState = this.stateViews.keySet().iterator().next();
+    else
+      this.activeState = null;
+    this.refresh();
+  }
+
+  @Override
+  public void refresh() {
+    this.save();
+    this.removeAll();
+    this.setLayout(new BorderLayout());
+    JPanel panel = null;
+    if (this.activeState != null) {
+      BuildPanel buildPanel = this.stateViews.get(this.activeState);
+      buildPanel.refresh();
+      panel = buildPanel;
+    } else {
+      panel = new JPanel();
+    }
+
+    if (this.projectView instanceof MultiStateView)
+      ((MultiStateView) this.projectView).refreshView(this.activeState,
+          this.getStates());
+    else
+      this.projectView.refreshView(this.activeState);
+
+    this.globalConfigView.refreshView(this.activeState);
+
+    JPanel globalPanel = new JPanel();
+    globalPanel.setLayout(new BorderLayout());
+    globalPanel.add(this.projectView, BorderLayout.CENTER);
+    globalPanel.add(this.globalConfigView, BorderLayout.SOUTH);
+
+    int dividerLocation = -1;
+    if (projectSplitPane != null)
+      dividerLocation = projectSplitPane.getDividerLocation();
+    projectSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, globalPanel,
+        panel);
+    if (dividerLocation != -1)
+      projectSplitPane.setDividerLocation(dividerLocation);
+    this.add(projectSplitPane, BorderLayout.CENTER);
+
+    this.revalidate();
+
+  }
+
+  private View createMainView(String name) {
+    try {
+      return this.mainViewClass.getConstructor(String.class).newInstance(name);
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  private View createTreeView() {
+    try {
+      return this.treeViewClass.getConstructor(String.class).newInstance(
+          this.treeViewClass.getSimpleName());
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  private View createGlobalConfigView() {
+    try {
+      return this.globalViewClass.getConstructor(String.class).newInstance(
+          this.globalViewClass.getSimpleName());
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  private View createProjectView() {
+    try {
+      View view = this.projectViewClass.getConstructor(String.class)
+          .newInstance(this.projectViewClass.getSimpleName());
+      view.registerListener(this);
+      return view;
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  private View createPropView() {
+    try {
+      return this.propViewClass.getConstructor(String.class).newInstance(
+          this.propViewClass.getSimpleName());
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  private class BuildPanel extends JPanel implements ViewListener {
+
+    private static final long serialVersionUID = -6120047959962567963L;
+
+    private JTabbedPane tabbedPane;
+    private Map<View, ViewState> mainViews;
+    private View propView;
+    private View treeView;
+
+    private View primaryMainView;
+
+    private JPopupMenu closeTabPopup;
+
+    private ViewState state;
+
+    public BuildPanel(ViewState state) {
+      this.state = state;
+
+      mainViews = new HashMap<View, ViewState>();
+
+      propView = createPropView();
+      propView.registerListener(this);
+
+      treeView = createTreeView();
+      treeView.registerListener(this);
+
+      tabbedPane = new JTabbedPane();
+
+      this.addMainView(createMainView(state.getFile().getName()), state);
+
+      closeTabPopup = new JPopupMenu();
+      JMenuItem closeItem = new JMenuItem("Close");
+      closeItem.addActionListener(new ActionListener() {
+
+        public void actionPerformed(ActionEvent e) {
+          View mainView = (View) BuildPanel.this.tabbedPane
+              .getSelectedComponent();
+          BuildPanel.this.removeMainView(mainView);
+        }
+
+      });
+      closeTabPopup.add(closeItem);
+
+      this.tabbedPane.addMouseListener(new MouseListener() {
+
+        public void mouseClicked(MouseEvent e) {
+          if (e.getButton() == MouseEvent.BUTTON3
+              && !BuildPanel.this.tabbedPane.getSelectedComponent().equals(
+                  BuildPanel.this.primaryMainView)) {
+            closeTabPopup.show(BuildPanel.this.tabbedPane, e.getX(), e.getY());
+          }
+        }
+
+        public void mouseEntered(MouseEvent e) {
+        }
+
+        public void mouseExited(MouseEvent e) {
+        }
+
+        public void mousePressed(MouseEvent e) {
+        }
+
+        public void mouseReleased(MouseEvent e) {
+        }
+
+      });
+
+      this.tabbedPane.addChangeListener(new ChangeListener() {
+
+        public void stateChanged(ChangeEvent e) {
+          View activeView = (View) BuildPanel.this.tabbedPane
+              .getSelectedComponent();
+          activeView.notifyListeners();
+        }
+
+      });
+
+      treeView.setPreferredSize(new Dimension(WIDTH / 10, HEIGHT / 2));
+      propView.setPreferredSize(new Dimension(WIDTH / 10, HEIGHT / 2));
+      JSplitPane treePropPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
+          treeView, propView);
+      treePropPane.setResizeWeight(.25);
+      tabbedPane.setPreferredSize(new Dimension(WIDTH, HEIGHT));
+      JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
+          tabbedPane, treePropPane);
+      mainSplitPane.setResizeWeight(.75);
+      this.setLayout(new BorderLayout());
+      this.add(mainSplitPane, BorderLayout.CENTER);
+    }
+
+    public void addMainView(View mainView, ViewState state) {
+      if (this.mainViews.size() == 0) {
+        this.primaryMainView = mainView;
+        mainView.setPrimary(true);
+      }
+      this.mainViews.put(mainView, state);
+      this.tabbedPane.addTab(mainView.getName(), mainView);
+      this.tabbedPane.setSelectedComponent(mainView);
+      mainView.registerListener(this);
+    }
+
+    public void removeMainView(View mainView) {
+      if (!this.primaryMainView.equals(mainView)) {
+        for (int i = 0; i < this.tabbedPane.getTabCount(); i++) {
+          if (mainView.getName().equals(this.tabbedPane.getTitleAt(i))) {
+            this.tabbedPane.removeTabAt(i);
+            this.mainViews.remove(mainView);
+            return;
+          }
+        }
+      }
+    }
+
+    public View getActiveView() {
+      return (View) this.tabbedPane.getSelectedComponent();
+    }
+
+    public void refresh() {
+      if (this.getActiveView() != null) {
+        ViewState viewState = null;
+        if (this.state.getSelected() != null && findSelectedInTab) {
+          TOP: for (Entry<View, ViewState> entry : this.mainViews.entrySet()) {
+            for (ModelGraph graph : entry.getValue().getGraphs()) {
+              ModelGraph found = graph.recursiveFindByModelId(this.state
+                  .getSelected().getModel().getModelId());
+              if (found != null && !found.getModel().isRef()) {
+                viewState = entry.getValue();
+                viewState.setSelected(found);
+                this.tabbedPane.setSelectedComponent(entry.getKey());
+                break TOP;
+              }
+            }
+          }
+        } else {
+          viewState = this.mainViews.get(this.getActiveView());
+        }
+        this.getActiveView().refreshView(viewState);
+        this.propView.refreshView(viewState);
+        this.treeView.refreshView(viewState);
+      }
+      this.revalidate();
+    }
+
+    public void stateChangeNotify(ViewChange<?> change) {
+      if (change instanceof ViewChange.NEW_VIEW) {
+        this.addMainView(
+            createMainView(((ViewChange.NEW_VIEW) change).getObject()
+                .getModel().getModelId()),
+            new ViewState(this.state.getFile(), null, Collections
+                .singletonList(GuiUtils.find(this.state.getGraphs(),
+                    ((ViewChange.NEW_VIEW) change).getObject().getModel()
+                        .getId())), this.state.getGlobalConfigGroups()));
+        this.refresh();
+      }
+      BuildPerspective.this.stateChangeNotify(change);
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/MultiStateView.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/MultiStateView.java
new file mode 100644
index 0000000..ae34285
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/MultiStateView.java
@@ -0,0 +1,46 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective.view;
+
+//JDK imports
+import java.util.List;
+
+/**
+ * 
+ * A multi-state view.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public abstract class MultiStateView extends View {
+
+  public MultiStateView(String name) {
+    super(name);
+  }
+
+  private static final long serialVersionUID = -6968627851727698540L;
+
+  public void refreshView(ViewState state) {
+    throw new RuntimeException(
+        "This is a mutli-state view -- call multi-state view refreshView method!");
+  }
+
+  public abstract void refreshView(ViewState activeState, List<ViewState> states);
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/View.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/View.java
new file mode 100644
index 0000000..b669267
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/View.java
@@ -0,0 +1,95 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective.view;
+
+//JDK imports
+import java.util.UUID;
+import java.util.Vector;
+import javax.swing.JPanel;
+
+/**
+ * 
+ * 
+ * View abstract base class.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public abstract class View extends JPanel {
+
+  private static final long serialVersionUID = -708692459667309413L;
+
+  public enum Mode {
+    DELETE, EDIT, MOVE, ZOOM_IN, ZOOM_OUT;
+  }
+
+  private Vector<ViewListener> listeners;
+  private String id;
+  private boolean isPrimary;
+
+  public static final String DISPLAY_GRAPH_IDS = "DisplayGraphIds";
+
+  public View(String name) {
+    super();
+    this.id = UUID.randomUUID().toString();
+    if (name != null)
+      this.setName(name);
+    this.listeners = new Vector<ViewListener>();
+  }
+
+  public void setPrimary(boolean isPrimary) {
+    this.isPrimary = isPrimary;
+  }
+
+  public boolean isPrimary() {
+    return this.isPrimary;
+  }
+
+  public String getId() {
+    return this.id;
+  }
+
+  public void registerListener(ViewListener listener) {
+    listeners.add(listener);
+  }
+
+  public void deregisterListener(ViewListener listener) {
+    this.listeners.remove(listener);
+  }
+
+  public void notifyListeners(ViewChange<?> change) {
+    for (ViewListener listener : listeners)
+      listener.stateChangeNotify(change);
+  }
+
+  public void notifyListeners() {
+    this.notifyListeners(new ViewChange.REFRESH_VIEW(this, this));
+  }
+
+  public int hashCode() {
+    return this.id.hashCode();
+  }
+
+  public boolean equals(Object obj) {
+    return obj instanceof View && ((View) obj).id.equals(this.id);
+  }
+
+  public abstract void refreshView(ViewState state);
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/ViewChange.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/ViewChange.java
new file mode 100644
index 0000000..5fd2a15
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/ViewChange.java
@@ -0,0 +1,97 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective.view;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.gui.model.ModelGraph;
+
+/**
+ * 
+ * Represents a change in the Workflow GUI model view.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public abstract class ViewChange<T> {
+
+  private T object;
+  private View source;
+
+  protected ViewChange(T object, View source) {
+    this.object = object;
+    this.source = source;
+  }
+
+  public T getObject() {
+    return this.object;
+  }
+
+  public View getSource() {
+    return this.source;
+  }
+
+  public static final class NEW_VIEW extends ViewChange<ModelGraph> {
+    public NEW_VIEW(ModelGraph object, View source) {
+      super(object, source);
+    }
+  }
+
+  public static final class DELETE_VIEW extends ViewChange<View> {
+    public DELETE_VIEW(View object, View source) {
+      super(object, source);
+    }
+  }
+
+  public static final class REFRESH_VIEW extends ViewChange<View> {
+    public REFRESH_VIEW(View object, View source) {
+      super(object, source);
+    }
+  }
+
+  public static final class NEW_STATE extends ViewChange<ViewState> {
+    public NEW_STATE(ViewState object, View source) {
+      super(object, source);
+    }
+  }
+
+  public static final class REMOVE_STATE extends ViewChange<ViewState> {
+    public REMOVE_STATE(ViewState object, View source) {
+      super(object, source);
+    }
+  }
+
+  public static final class NEW_ACTIVE_STATE extends ViewChange<ViewState> {
+    public NEW_ACTIVE_STATE(ViewState object, View source) {
+      super(object, source);
+    }
+  }
+
+  public static final class STATE_NAME_CHANGE extends ViewChange<ViewState> {
+    public STATE_NAME_CHANGE(ViewState object, View source) {
+      super(object, source);
+    }
+  }
+
+  public static final class VIEW_MODEL extends ViewChange<String> {
+    public VIEW_MODEL(String modelId, View source) {
+      super(modelId, source);
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/ViewListener.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/ViewListener.java
new file mode 100644
index 0000000..da88b27
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/ViewListener.java
@@ -0,0 +1,32 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective.view;
+
+/**
+ * 
+ * Interface for listening/notifying about Workflow View state changes.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public interface ViewListener {
+
+  public void stateChangeNotify(ViewChange<?> change);
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/ViewState.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/ViewState.java
new file mode 100644
index 0000000..1513b7e
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/ViewState.java
@@ -0,0 +1,260 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective.view;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.gui.model.ModelGraph;
+import org.apache.oodt.cas.workflow.gui.model.repo.XmlWorkflowModelRepository.ConfigGroup;
+import org.apache.oodt.cas.workflow.gui.perspective.view.View.Mode;
+import org.apache.oodt.cas.workflow.gui.util.GuiUtils;
+
+//JDK imports
+import java.io.File;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+import java.util.UUID;
+import java.util.Vector;
+
+/**
+ * 
+ * The current state of a particular Workflow GUI editor view.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class ViewState {
+
+  private static final HashMap<String, Stack<ViewState>> undoHistory = new HashMap<String, Stack<ViewState>>();
+
+  private ModelGraph selected;
+  private List<ModelGraph> graphs;
+  private String id;
+  private String currentMetGroup;
+  private Metadata properties;
+  private Mode mode;
+  private File file;
+  private boolean change = false;
+  private Map<String, ConfigGroup> globalConfigGroups;
+
+  public ViewState(File file, ModelGraph selected, List<ModelGraph> graphs,
+      Map<String, ConfigGroup> globalConfigGroups) {
+    this.selected = selected;
+    this.graphs = new Vector<ModelGraph>(graphs);
+    this.id = UUID.randomUUID().toString();
+    this.currentMetGroup = null;
+    this.properties = new Metadata();
+    this.mode = Mode.EDIT;
+    this.file = file;
+    this.globalConfigGroups = globalConfigGroups;
+  }
+
+  public Map<String, ConfigGroup> getGlobalConfigGroups() {
+    return this.globalConfigGroups;
+  }
+
+  public void addGlobalConfigGroup(String groupName, ConfigGroup configGroup) {
+    this.globalConfigGroups.put(groupName, configGroup);
+  }
+
+  public void removeGlobalConfigGroup(String groupName) {
+    this.globalConfigGroups.remove(groupName);
+  }
+
+  public File getFile() {
+    return this.file;
+  }
+
+  public String getId() {
+    return this.id;
+  }
+
+  public boolean containsProperty(String key) {
+    return this.properties.containsGroup(key);
+  }
+
+  public void setProperty(String key, String value) {
+    Vector<String> values = new Vector<String>();
+    values.add(value);
+    this.setProperty(key, values);
+  }
+
+  public void setProperty(String key, List<String> values) {
+    this.properties.replaceMetadata(key, values);
+    this.change = true;
+  }
+
+  public String getFirstPropertyValue(String key) {
+    List<String> values = this.getProperty(key);
+    if (values == null || values.size() == 0)
+      return null;
+    return values.get(0);
+  }
+
+  public List<String> getProperty(String key) {
+    return this.properties.getAllMetadata(key);
+  }
+
+  public void removeProperty(String key) {
+    this.properties.removeMetadata(key);
+    this.change = true;
+  }
+
+  public List<String> getKeysRecur(String subGroup) {
+    Vector<String> keys = new Vector<String>();
+    for (String key : this.properties.getAllKeys())
+      if (key.contains(subGroup))
+        keys.add(key);
+    return keys;
+  }
+
+  public void setSelected(ModelGraph selected) {
+    if (this.selected == null || selected == null
+        || !this.selected.equals(selected)) {
+      this.currentMetGroup = null;
+      this.selected = selected;
+      this.change = true;
+    }
+  }
+
+  public ModelGraph getSelected() {
+    if (this.mode.equals(Mode.EDIT))
+      return this.selected;
+    else
+      return null;
+  }
+
+  public Set<String> getGraphIds() {
+    HashSet<String> graphIds = new HashSet<String>();
+    for (ModelGraph graph : this.getGraphs())
+      graphIds.add(graph.getModel().getModelId());
+    return graphIds;
+  }
+
+  public List<ModelGraph> getGraphs() {
+    return this.graphs;
+  }
+
+  public void removeGraph(ModelGraph graph) {
+    this.graphs.remove(graph);
+  }
+
+  public void addGraph(ModelGraph graph) {
+    this.graphs.add(graph);
+  }
+
+  public void setMode(Mode mode) {
+    this.mode = mode;
+    this.change = true;
+  }
+
+  public Mode getMode() {
+    return this.mode;
+  }
+
+  public void setCurrentMetGroup(String currentMetGroup) {
+    this.currentMetGroup = currentMetGroup;
+    this.change = true;
+  }
+
+  public String getCurrentMetGroup() {
+    return this.currentMetGroup;
+  }
+
+  public boolean hasChanged() {
+    return this.change;
+  }
+
+  public void save() {
+    if (this.change) {
+      Stack<ViewState> stack = undoHistory.get(this.id);
+      if (stack == null)
+        stack = new Stack<ViewState>();
+      if (stack.size() >= 100)
+        stack.remove(stack.size() - 1);
+      stack.push(this.clone());
+      undoHistory.put(this.id, stack);
+      this.change = false;
+    }
+  }
+
+  public void undo() {
+    Stack<ViewState> stack = undoHistory.get(this.id);
+    if (stack != null && !stack.empty()) {
+      this.clone(stack.pop());
+      System.out.println(this.getGraphIds());
+      this.change = false;
+    }
+  }
+
+  public void clone(ViewState state) {
+    this.graphs = null;
+    this.selected = null;
+    if (state.graphs != null) {
+      this.graphs = new Vector<ModelGraph>();
+      for (ModelGraph graph : state.graphs)
+        this.graphs.add(graph.clone());
+      if (state.selected != null)
+        this.selected = GuiUtils.find(this.graphs, state.selected.getModel()
+            .getModelId());
+    }
+    this.properties = new Metadata(state.properties);
+    this.id = state.id;
+    this.currentMetGroup = state.currentMetGroup;
+    this.mode = state.mode;
+  }
+
+  public ViewState clone() {
+    List<ModelGraph> cloneGraphs = null;
+    ModelGraph selected = null;
+    if (this.graphs != null) {
+      cloneGraphs = new Vector<ModelGraph>();
+      for (ModelGraph graph : this.graphs)
+        cloneGraphs.add(graph.clone());
+      if (this.selected != null)
+        selected = GuiUtils.find(cloneGraphs, this.selected.getModel()
+            .getModelId());
+    }
+    ViewState clone = new ViewState(this.file, selected, cloneGraphs,
+        this.globalConfigGroups);
+    clone.id = this.id;
+    clone.file = this.file;
+    clone.currentMetGroup = this.currentMetGroup;
+    clone.properties = new Metadata(this.properties);
+    clone.mode = this.mode;
+    return clone;
+  }
+
+  public int hashCode() {
+    return this.id.hashCode();
+  }
+
+  public boolean equals(Object obj) {
+    return obj instanceof ViewState && this.id.equals(((ViewState) obj).id);
+  }
+
+  public String toString() {
+    return this.getId();
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/DefaultPropView.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/DefaultPropView.java
new file mode 100644
index 0000000..cacfae9
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/DefaultPropView.java
@@ -0,0 +1,853 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective.view.impl;
+
+//JDK imports
+import java.awt.BorderLayout;
+import java.awt.Checkbox;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.text.DecimalFormat;
+import java.text.Format;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Vector;
+import javax.swing.BoxLayout;
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.JSlider;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.ListSelectionModel;
+import javax.swing.border.EtchedBorder;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.table.TableColumn;
+
+//Apache imports
+import org.apache.commons.lang.StringUtils;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.gui.model.ModelGraph;
+import org.apache.oodt.cas.workflow.gui.perspective.view.View;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewState;
+import org.apache.oodt.cas.workflow.gui.util.GuiUtils;
+
+/**
+ * 
+ * 
+ * The default view displaying a workflow property (for a task, or a condition,
+ * or set of workflows).
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class DefaultPropView extends View {
+
+  private static final long serialVersionUID = -5521047300551974898L;
+
+  private JTable table;
+  private JPopupMenu tableMenu;
+  private JMenuItem override;
+  private JMenuItem delete;
+  private static final String OVERRIDE = "Override";
+  private static final String DELETE = "Delete";
+  private int DEFAULT_PRIORITY = 5;
+
+  public DefaultPropView(String name) {
+    super(name);
+    this.setLayout(new BorderLayout());
+  }
+
+  private JTable createTable(final ViewState state) {
+    JTable table = null;
+    final ModelGraph selected = state.getSelected();
+    if (selected != null) {
+      final Vector<Vector<String>> rows = new Vector<Vector<String>>();
+      HashMap<String, String> keyToGroupMap = new HashMap<String, String>();
+      Metadata staticMet = selected.getModel().getStaticMetadata();
+      Metadata inheritedMet = selected.getInheritedStaticMetadata(state);
+      Metadata completeMet = new Metadata();
+      if (staticMet != null) {
+        completeMet.replaceMetadata(staticMet.getSubMetadata(state
+            .getCurrentMetGroup()));
+      }
+      if (selected.getModel().getExtendsConfig() != null) {
+        for (String configGroup : selected.getModel().getExtendsConfig()) {
+          Metadata extendsMetadata = state.getGlobalConfigGroups()
+              .get(configGroup).getMetadata()
+              .getSubMetadata(state.getCurrentMetGroup());
+          for (String key : extendsMetadata.getAllKeys()) {
+            if (!completeMet.containsKey(key)) {
+              keyToGroupMap.put(key, configGroup);
+              completeMet.replaceMetadata(key,
+                  extendsMetadata.getAllMetadata(key));
+            }
+          }
+        }
+      }
+      if (inheritedMet != null) {
+        Metadata inheritedMetadata = inheritedMet.getSubMetadata(state
+            .getCurrentMetGroup());
+        for (String key : inheritedMetadata.getAllKeys()) {
+          if (!completeMet.containsKey(key)) {
+            keyToGroupMap.put(key, "__inherited__");
+            completeMet.replaceMetadata(key,
+                inheritedMetadata.getAllMetadata(key));
+          }
+        }
+      }
+      List<String> keys = completeMet.getAllKeys();
+      Collections.sort(keys);
+      for (String key : keys) {
+        if (key.endsWith("/envReplace"))
+          continue;
+        String values = StringUtils.join(completeMet.getAllMetadata(key), ",");
+        Vector<String> row = new Vector<String>();
+        row.add(keyToGroupMap.get(key));
+        row.add(key);
+        row.add(values);
+        row.add(Boolean.toString(Boolean.parseBoolean(completeMet
+            .getMetadata(key + "/envReplace"))));
+        rows.add(row);
+      }
+      table = new JTable();// rows, new Vector<String>(Arrays.asList(new
+                           // String[] { "key", "values", "envReplace" })));
+      table.setModel(new AbstractTableModel() {
+        public String getColumnName(int col) {
+          switch (col) {
+          case 0:
+            return "group";
+          case 1:
+            return "key";
+          case 2:
+            return "values";
+          case 3:
+            return "envReplace";
+          default:
+            return null;
+          }
+        }
+
+        public int getRowCount() {
+          return rows.size() + 1;
+        }
+
+        public int getColumnCount() {
+          return 4;
+        }
+
+        public Object getValueAt(int row, int col) {
+          if (row >= rows.size())
+            return null;
+          String value = rows.get(row).get(col);
+          if (value == null && col == 3)
+            return "false";
+          if (value == null && col == 0)
+            return "__local__";
+          return value;
+        }
+
+        public boolean isCellEditable(int row, int col) {
+          if (row >= rows.size()) {
+            if (selected.getModel().getStaticMetadata()
+                .containsGroup(state.getCurrentMetGroup()))
+              return true;
+            else
+              return false;
+          }
+          if (col == 0)
+            return false;
+          String key = rows.get(row).get(1);
+          if (key == null
+              || (selected.getModel().getStaticMetadata() != null && selected
+                  .getModel().getStaticMetadata()
+                  .containsKey(getKey(key, state))))
+            return true;
+          return false;
+        }
+
+        public void setValueAt(Object value, int row, int col) {
+          if (row >= rows.size()) {
+            Vector<String> newRow = new Vector<String>(Arrays
+                .asList(new String[] { null, null, null, null }));
+            newRow.add(col, (String) value);
+            rows.add(newRow);
+          } else {
+            Vector<String> rowValues = rows.get(row);
+            rowValues.add(col, (String) value);
+            rowValues.remove(col + 1);
+          }
+          this.fireTableCellUpdated(row, col);
+        }
+
+      });
+      MyTableListener tableListener = new MyTableListener(state);
+      table.getModel().addTableModelListener(tableListener);
+      table.getSelectionModel().addListSelectionListener(tableListener);
+    } else {
+      table = new JTable(new Vector<Vector<String>>(), new Vector<String>(
+          Arrays.asList(new String[] { "key", "values", "envReplace" })));
+    }
+
+    // table.setFillsViewportHeight(true);
+    table.setSelectionBackground(Color.cyan);
+    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
+    TableCellRenderer cellRenderer = new TableCellRenderer() {
+
+      public Component getTableCellRendererComponent(JTable table,
+          Object value, boolean isSelected, boolean hasFocus, int row,
+          int column) {
+        JLabel field = new JLabel((String) value);
+        if (column == 0) {
+          field.setForeground(Color.gray);
+        } else {
+          if (isSelected)
+            field.setBorder(new EtchedBorder(1));
+          if (table.isCellEditable(row, 1))
+            field.setForeground(Color.black);
+          else
+            field.setForeground(Color.gray);
+        }
+        return field;
+      }
+
+    };
+    TableColumn groupCol = table.getColumnModel().getColumn(0);
+    groupCol.setPreferredWidth(75);
+    groupCol.setCellRenderer(cellRenderer);
+    TableColumn keyCol = table.getColumnModel().getColumn(1);
+    keyCol.setPreferredWidth(200);
+    keyCol.setCellRenderer(cellRenderer);
+    TableColumn valuesCol = table.getColumnModel().getColumn(2);
+    valuesCol.setPreferredWidth(300);
+    valuesCol.setCellRenderer(cellRenderer);
+    TableColumn envReplaceCol = table.getColumnModel().getColumn(3);
+    envReplaceCol.setPreferredWidth(75);
+    envReplaceCol.setCellRenderer(cellRenderer);
+
+    table.addMouseListener(new MouseListener() {
+      public void mouseClicked(MouseEvent e) {
+        if (e.getButton() == MouseEvent.BUTTON3
+            && DefaultPropView.this.table.getSelectedRow() != -1) {
+          int row = DefaultPropView.this.table.getSelectedRow();// rowAtPoint(DefaultPropView.this.table.getMousePosition());
+          String key = getKey(
+              (String) DefaultPropView.this.table.getValueAt(row, 1), state);
+          Metadata staticMet = state.getSelected().getModel()
+              .getStaticMetadata();
+          override.setVisible(staticMet == null || !staticMet.containsKey(key));
+          delete.setVisible(staticMet != null && staticMet.containsKey(key));
+          tableMenu.show(DefaultPropView.this.table, e.getX(), e.getY());
+        }
+      }
+
+      public void mouseEntered(MouseEvent e) {
+      }
+
+      public void mouseExited(MouseEvent e) {
+      }
+
+      public void mousePressed(MouseEvent e) {
+      }
+
+      public void mouseReleased(MouseEvent e) {
+      }
+    });
+
+    return table;
+  }
+
+  @Override
+  public void refreshView(final ViewState state) {
+    this.removeAll();
+
+    tableMenu = new JPopupMenu("TableMenu");
+    this.add(tableMenu);
+    override = new JMenuItem(OVERRIDE);
+    override.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        int row = DefaultPropView.this.table.getSelectedRow();// rowAtPoint(DefaultPropView.this.table.getMousePosition());
+        String key = getKey(
+            (String) DefaultPropView.this.table.getValueAt(row, 1), state);
+        Metadata staticMet = state.getSelected().getModel().getStaticMetadata();
+        if (staticMet == null)
+          staticMet = new Metadata();
+        if (e.getActionCommand().equals(OVERRIDE)) {
+          if (!staticMet.containsKey(key)) {
+            staticMet.addMetadata(key,
+                (String) DefaultPropView.this.table.getValueAt(row, 2));
+            String envReplace = (String) DefaultPropView.this.table.getValueAt(
+                row, 3);
+            if (Boolean.valueOf(envReplace))
+              staticMet.addMetadata(key + "/envReplace", envReplace);
+            state.getSelected().getModel().setStaticMetadata(staticMet);
+            DefaultPropView.this.notifyListeners();
+          }
+        }
+      }
+    });
+    delete = new JMenuItem(DELETE);
+    delete.addActionListener(new ActionListener() {
+
+      public void actionPerformed(ActionEvent e) {
+        int row = DefaultPropView.this.table.getSelectedRow();// rowAtPoint(DefaultPropView.this.table.getMousePosition());
+        String key = getKey(
+            (String) DefaultPropView.this.table.getValueAt(row, 1), state);
+        Metadata staticMet = state.getSelected().getModel().getStaticMetadata();
+        if (staticMet == null)
+          staticMet = new Metadata();
+        staticMet.removeMetadata(key);
+        staticMet.removeMetadata(key + "/envReplace");
+        state.getSelected().getModel().setStaticMetadata(staticMet);
+        DefaultPropView.this.notifyListeners();
+      }
+
+    });
+    tableMenu.add(override);
+    tableMenu.add(delete);
+
+    if (state.getSelected() != null) {
+      JPanel masterPanel = new JPanel();
+      masterPanel.setLayout(new BoxLayout(masterPanel, BoxLayout.Y_AXIS));
+      masterPanel.add(this.getModelIdPanel(state.getSelected(), state));
+      masterPanel.add(this.getModelNamePanel(state.getSelected(), state));
+      if (!state.getSelected().getModel().isParentType())
+        masterPanel.add(this.getInstanceClassPanel(state.getSelected(), state));
+      masterPanel.add(this.getExecutionTypePanel(state.getSelected(), state));
+      masterPanel.add(this.getPriorityPanel(state));
+      masterPanel.add(this.getExecusedIds(state.getSelected()));
+      if (state.getSelected().getModel().getExecutionType().equals("condition")) {
+        masterPanel.add(this.getTimeout(state.getSelected(), state));
+        masterPanel.add(this.getOptional(state.getSelected(), state));
+      }
+      JScrollPane scrollPane = new JScrollPane(table = this.createTable(state),
+          JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+          JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+      scrollPane.getHorizontalScrollBar().setUnitIncrement(10);
+      scrollPane.getVerticalScrollBar().setUnitIncrement(10);
+      JPanel panel = new JPanel();
+      panel.setLayout(new BorderLayout());
+      panel.setBorder(new EtchedBorder());
+      final JLabel metLabel = new JLabel("Static Metadata");
+      metLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+      final JLabel extendsLabel = new JLabel("<extends>");
+      extendsLabel.setFont(new Font("Serif", Font.PLAIN, 10));
+      extendsLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+      extendsLabel.addMouseListener(new MouseListener() {
+
+        private JScrollPane availableScroller;
+        private JScrollPane mineScroller;
+        private JList mineList;
+        private JList availableList;
+        private DefaultListModel mineModel;
+        private DefaultListModel availableModel;
+
+        public void mouseClicked(MouseEvent e) {
+          final JPopupMenu popup = new JPopupMenu();
+          popup.setLayout(new BorderLayout());
+
+          JPanel main = new JPanel();
+          main.setLayout(new BoxLayout(main, BoxLayout.X_AXIS));
+
+          JPanel mine = new JPanel();
+          mine.setBorder(new EtchedBorder());
+          mine.setLayout(new BorderLayout());
+          JLabel mineLabel = new JLabel("Mine");
+          mineScroller = new JScrollPane(mineList = createJList(
+              mineModel = new DefaultListModel(), state.getSelected()
+                  .getModel().getExtendsConfig()));
+          mineScroller.setPreferredSize(new Dimension(250, 80));
+          mine.add(mineLabel, BorderLayout.NORTH);
+          mine.add(mineScroller, BorderLayout.CENTER);
+
+          JPanel available = new JPanel();
+          available.setBorder(new EtchedBorder());
+          available.setLayout(new BorderLayout());
+          JLabel availableLabel = new JLabel("Available");
+          Vector<String> availableGroups = new Vector<String>(state
+              .getGlobalConfigGroups().keySet());
+          availableGroups.removeAll(state.getSelected().getModel()
+              .getExtendsConfig());
+          availableScroller = new JScrollPane(availableList = this.createJList(
+              availableModel = new DefaultListModel(), availableGroups));
+          availableScroller.setPreferredSize(new Dimension(250, 80));
+          available.add(availableLabel, BorderLayout.NORTH);
+          available.add(availableScroller, BorderLayout.CENTER);
+
+          JPanel buttons = new JPanel();
+          buttons.setLayout(new BoxLayout(buttons, BoxLayout.Y_AXIS));
+          JButton addButton = new JButton("<---");
+          addButton.addMouseListener(new MouseListener() {
+
+            public void mouseClicked(MouseEvent e) {
+              String selected = availableList.getSelectedValue().toString();
+              Vector<String> extendsConfig = new Vector<String>(state
+                  .getSelected().getModel().getExtendsConfig());
+              extendsConfig.add(selected);
+              state.getSelected().getModel().setExtendsConfig(extendsConfig);
+              availableModel.remove(availableList.getSelectedIndex());
+              mineModel.addElement(selected);
+              popup.revalidate();
+              DefaultPropView.this.notifyListeners();
+            }
+
+            public void mouseEntered(MouseEvent e) {
+            }
+
+            public void mouseExited(MouseEvent e) {
+            }
+
+            public void mousePressed(MouseEvent e) {
+            }
+
+            public void mouseReleased(MouseEvent e) {
+            }
+
+          });
+          JButton removeButton = new JButton("--->");
+          removeButton.addMouseListener(new MouseListener() {
+
+            public void mouseClicked(MouseEvent e) {
+              String selected = mineList.getSelectedValue().toString();
+              Vector<String> extendsConfig = new Vector<String>(state
+                  .getSelected().getModel().getExtendsConfig());
+              extendsConfig.remove(selected);
+              state.getSelected().getModel().setExtendsConfig(extendsConfig);
+              mineModel.remove(mineList.getSelectedIndex());
+              availableModel.addElement(selected);
+              popup.revalidate();
+              DefaultPropView.this.notifyListeners();
+            }
+
+            public void mouseEntered(MouseEvent e) {
+            }
+
+            public void mouseExited(MouseEvent e) {
+            }
+
+            public void mousePressed(MouseEvent e) {
+            }
+
+            public void mouseReleased(MouseEvent e) {
+            }
+
+          });
+          buttons.add(addButton);
+          buttons.add(removeButton);
+
+          main.add(mine);
+          main.add(buttons);
+          main.add(available);
+          popup.add(main, BorderLayout.CENTER);
+          popup.show(extendsLabel, e.getX(), e.getY());
+        }
+
+        public void mouseEntered(MouseEvent e) {
+          extendsLabel.setForeground(Color.blue);
+        }
+
+        public void mouseExited(MouseEvent e) {
+          extendsLabel.setForeground(Color.black);
+        }
+
+        public void mousePressed(MouseEvent e) {
+        }
+
+        public void mouseReleased(MouseEvent e) {
+        }
+
+        private JList createJList(DefaultListModel model,
+            final List<String> list) {
+          for (String value : list)
+            model.addElement(value);
+          JList jList = new JList(model);
+          jList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
+          jList.setLayoutOrientation(JList.VERTICAL);
+          return jList;
+        }
+      });
+      JLabel metGroupLabel = new JLabel("(Sub-Group: "
+          + (state.getCurrentMetGroup() != null ? state.getCurrentMetGroup()
+              : "<base>") + ")");
+      metGroupLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+      JPanel labelPanel = new JPanel();
+      labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.Y_AXIS));
+      JPanel top = new JPanel();
+      top.setLayout(new BoxLayout(top, BoxLayout.Y_AXIS));
+      top.add(extendsLabel);
+      top.add(metLabel);
+      labelPanel.add(top);
+      labelPanel.add(metGroupLabel);
+      panel.add(labelPanel, BorderLayout.NORTH);
+      panel.add(scrollPane, BorderLayout.CENTER);
+      masterPanel.add(panel);
+      this.add(masterPanel);
+    } else {
+      this.add(new JPanel());
+    }
+    this.revalidate();
+  }
+
+  private JPanel getTimeout(final ModelGraph graph, final ViewState state) {
+    JPanel panel = new JPanel();
+    panel.setLayout(new BorderLayout());
+    panel.setBorder(new EtchedBorder());
+    panel.add(new JLabel("Timeout:"), BorderLayout.NORTH);
+    JTextField field = new JTextField(String.valueOf(graph.getModel()
+        .getTimeout()), 50);
+    field.addActionListener(new ActionListener() {
+
+      public void actionPerformed(ActionEvent e) {
+        if (!graph.getModel().getModelId().equals(e.getActionCommand())) {
+          graph.getModel().setTimeout(Long.valueOf(
+              e.getActionCommand() != null && 
+              !e.getActionCommand().equals("") ? 
+                  e.getActionCommand():"-1"));
+          DefaultPropView.this.notifyListeners();
+          DefaultPropView.this.refreshView(state);
+        }
+      }
+
+    });
+    panel.add(field, BorderLayout.CENTER);
+    return panel;
+  }
+
+  private JPanel getModelIdPanel(final ModelGraph graph, final ViewState state) {
+    JPanel panel = new JPanel();
+    panel.setLayout(new BorderLayout());
+    panel.setBorder(new EtchedBorder());
+    panel.add(new JLabel("ModelId:"), BorderLayout.NORTH);
+    JTextField field = new JTextField(graph.getModel().getModelId(), 50);
+    field.addActionListener(new ActionListener() {
+
+      public void actionPerformed(ActionEvent e) {
+        if (!graph.getModel().getModelId().equals(e.getActionCommand())) {
+          GuiUtils.updateGraphModelId(state, graph.getModel().getId(),
+              e.getActionCommand());
+          DefaultPropView.this.notifyListeners();
+          DefaultPropView.this.refreshView(state);
+        }
+      }
+
+    });
+    panel.add(field, BorderLayout.CENTER);
+    return panel;
+  }
+
+  private JPanel getModelNamePanel(final ModelGraph graph, final ViewState state) {
+    JPanel panel = new JPanel();
+    panel.setLayout(new BorderLayout());
+    panel.setBorder(new EtchedBorder());
+    panel.add(new JLabel("ModelName:"), BorderLayout.NORTH);
+    JTextField field = new JTextField(graph.getModel().getModelName(), 50);
+    field.addActionListener(new ActionListener() {
+
+      public void actionPerformed(ActionEvent e) {
+        if (!graph.getModel().getModelName().equals(e.getActionCommand())) {
+          // GuiUtils.updateGraphModelName(getState(),
+          // graph.getModel().getModelId(), e.getActionCommand());
+          graph.getModel().setModelName(e.getActionCommand());
+          DefaultPropView.this.notifyListeners();
+          DefaultPropView.this.refreshView(state);
+        }
+      }
+
+    });
+    panel.add(field, BorderLayout.CENTER);
+    return panel;
+  }
+
+  private JPanel getInstanceClassPanel(final ModelGraph graph,
+      final ViewState state) {
+    JPanel panel = new JPanel();
+    panel.setLayout(new BorderLayout());
+    panel.setBorder(new EtchedBorder());
+    panel.add(new JLabel("InstanceClass:"), BorderLayout.NORTH);
+    JTextField field = new JTextField(graph.getModel().getInstanceClass(), 50);
+    field.addActionListener(new ActionListener() {
+
+      public void actionPerformed(ActionEvent e) {
+        if (graph.getModel().getInstanceClass() == null
+            || !graph.getModel().getInstanceClass()
+                .equals(e.getActionCommand())) {
+          graph.getModel().setInstanceClass(e.getActionCommand());
+          DefaultPropView.this.notifyListeners();
+          DefaultPropView.this.refreshView(state);
+        }
+      }
+
+    });
+    panel.add(field, BorderLayout.CENTER);
+    return panel;
+  }
+
+  private JPanel getPriorityPanel(final ViewState state) {
+    JPanel panel = new JPanel();
+    panel.setBorder(new EtchedBorder());
+    panel.setLayout(new BorderLayout());
+    panel.add(new JLabel("Priority:  "), BorderLayout.WEST);
+    final JLabel priorityLabel = new JLabel(String.valueOf(DEFAULT_PRIORITY));
+    panel.add(priorityLabel, BorderLayout.CENTER);
+    JSlider slider = new JSlider(0, 100, (int) 5 * 10);
+    slider.setMajorTickSpacing(10);
+    slider.setMinorTickSpacing(1);
+    slider.setPaintLabels(true);
+    slider.setPaintTicks(true);
+    slider.setSnapToTicks(false);
+    Format f = new DecimalFormat("0.0");
+    Hashtable<Integer, JComponent> labels = new Hashtable<Integer, JComponent>();
+    for (int i = 0; i <= 10; i += 2) {
+      JLabel label = new JLabel(f.format(i));
+      label.setFont(label.getFont().deriveFont(Font.PLAIN));
+      labels.put(i * 10, label);
+    }
+    slider.setLabelTable(labels);
+    slider.addChangeListener(new ChangeListener() {
+
+      public void stateChanged(ChangeEvent e) {
+        double value = ((JSlider) e.getSource()).getValue() / 10.0;
+        priorityLabel.setText(value + "");
+        priorityLabel.revalidate();
+        if (!((JSlider) e.getSource()).getValueIsAdjusting()) {
+          // FIXME: deal with priorities
+          DefaultPropView.this.notifyListeners();
+        }
+      }
+
+    });
+
+    panel.add(slider, BorderLayout.SOUTH);
+    return panel;
+  }
+
+  private JPanel getExecutionTypePanel(final ModelGraph graph,
+      final ViewState state) {
+    JPanel panel = new JPanel();
+    panel.setBorder(new EtchedBorder());
+    panel.setLayout(new BorderLayout());
+    panel.add(new JLabel("ExecutionType:"), BorderLayout.WEST);
+    JComboBox comboBox = new JComboBox();
+    if (graph.hasChildren()) {
+      comboBox.addItem("parallel");
+      comboBox.addItem("sequential");
+    } else if (graph.getModel().getExecutionType().equals("task")) {
+      comboBox.addItem("parallel");
+      comboBox.addItem("sequential");
+      comboBox.addItem("task");
+    } else if (graph.isCondition()
+        || graph.getModel().getExecutionType().equals("condition")) {
+      comboBox.addItem("parallel");
+      comboBox.addItem("sequential");
+      comboBox.addItem("condition");
+    } else {
+      comboBox.addItem("parallel");
+      comboBox.addItem("sequential");
+      comboBox.addItem("task");
+    }
+    comboBox.setSelectedItem(graph.getModel().getExecutionType());
+    comboBox.addItemListener(new ItemListener() {
+      public void itemStateChanged(ItemEvent e) {
+        if (!graph.getModel().getExecutionType().equals(e.getItem())) {
+          graph.getModel().setExecutionType((String) e.getItem());
+          DefaultPropView.this.notifyListeners();
+          DefaultPropView.this.refreshView(state);
+        }
+      }
+    });
+    panel.add(comboBox, BorderLayout.CENTER);
+    return panel;
+  }
+
+  private JPanel getOptional(final ModelGraph graph, final ViewState state) {
+    JPanel panel = new JPanel();
+    panel.setLayout(new BorderLayout());
+    panel.setBorder(new EtchedBorder());
+    panel.add(new JLabel("Optional:"), BorderLayout.NORTH);
+    JPanel checkBoxes = new JPanel();
+    checkBoxes.setLayout(new GridLayout(1, 1));
+    Checkbox checkbox = new Checkbox("ignore", graph.getModel().isOptional());
+    checkBoxes.add(checkbox);
+        checkbox.addItemListener(new ItemListener() {
+
+          public void itemStateChanged(ItemEvent e) {
+            if (e.getStateChange() == ItemEvent.DESELECTED)
+              graph.getModel().setOptional(false);
+            else if (e.getStateChange() == ItemEvent.SELECTED)
+              graph.getModel().setOptional(true);
+            else
+              return;
+            DefaultPropView.this.notifyListeners();
+            DefaultPropView.this.refreshView(state);
+          }
+
+        });
+    panel.add(checkBoxes, BorderLayout.CENTER);
+    return panel;
+  }  
+  
+  
+  private JPanel getExecusedIds(final ModelGraph graph) {
+    JPanel panel = new JPanel();
+    panel.setLayout(new BorderLayout());
+    panel.setBorder(new EtchedBorder());
+    panel.add(new JLabel("ExcusedSubProcessorIds:"), BorderLayout.NORTH);
+    JPanel checkBoxes = new JPanel();
+    checkBoxes.setLayout(new GridLayout(graph.getChildren().size(), 1));
+    if (graph.hasChildren()) {
+      for (ModelGraph childGraph : graph.getChildren()) {
+        final String modelId = childGraph.getModel().getModelId();
+        Checkbox checkbox = new Checkbox(modelId, graph.getModel()
+            .getExcusedSubProcessorIds().contains(modelId));
+        checkBoxes.add(checkbox);
+        checkbox.addItemListener(new ItemListener() {
+
+          public void itemStateChanged(ItemEvent e) {
+            if (e.getStateChange() == ItemEvent.DESELECTED)
+              graph.getModel().getExcusedSubProcessorIds().remove(modelId);
+            else if (e.getStateChange() == ItemEvent.SELECTED)
+              graph.getModel().getExcusedSubProcessorIds().add(modelId);
+            else
+              return;
+            DefaultPropView.this.notifyListeners();
+          }
+
+        });
+      }
+    }
+    panel.add(checkBoxes, BorderLayout.CENTER);
+    return panel;
+  }
+
+  public class MyTableListener implements TableModelListener,
+      ListSelectionListener {
+
+    String oldKey, oldValue, oldEnvReplace;
+
+    private ViewState state;
+
+    public MyTableListener(ViewState state) {
+      this.state = state;
+    }
+
+    public void tableChanged(TableModelEvent e) {
+      System.out.println(oldKey + " " + oldValue + " " + oldEnvReplace);
+      if (e.getType() == TableModelEvent.UPDATE) {
+        Metadata staticMet = state.getSelected().getModel().getStaticMetadata();
+        if (staticMet == null)
+          staticMet = new Metadata();
+        if (e.getColumn() == 1) {
+          String newGrouplessKey = (String) table.getValueAt(e.getFirstRow(),
+              e.getColumn());
+          if (newGrouplessKey.equals("")
+              || (newGrouplessKey.equals("envReplace") && !state.getSelected()
+                  .getModel().getStaticMetadata()
+                  .containsGroup(state.getCurrentMetGroup()))) {
+            notifyListeners();
+            return;
+          }
+          String newKey = getKey(newGrouplessKey, state);
+          System.out.println("newKey: " + newKey);
+          if (oldKey != null) {
+            staticMet.replaceMetadata(newKey, staticMet.getAllMetadata(oldKey));
+            if (staticMet.containsKey(oldKey + "/envReplace"))
+              staticMet.replaceMetadata(newKey,
+                  staticMet.getAllMetadata(oldKey + "/envReplace"));
+            if (!newKey.equals(oldKey))
+              staticMet.removeMetadata(oldKey);
+            notifyListeners();
+          } else {
+            staticMet.replaceMetadata(oldKey = newKey, (String) null);
+          }
+        } else if (e.getColumn() == 2) {
+          if (oldKey != null) {
+            String newValue = (String) table.getValueAt(e.getFirstRow(),
+                e.getColumn());
+            if (oldKey.endsWith("/envReplace")) {
+              newValue = newValue.toLowerCase();
+              if (newValue.equals("false"))
+                staticMet.removeMetadata(oldKey);
+              else
+                staticMet.replaceMetadata(oldKey,
+                    Arrays.asList(newValue.split(",")));
+            } else {
+              staticMet.replaceMetadata(oldKey,
+                  Arrays.asList(newValue.split(",")));
+            }
+            notifyListeners();
+          }
+        } else if (e.getColumn() == 3) {
+          if (oldKey != null) {
+            String newEnvReplace = ((String) table.getValueAt(e.getFirstRow(),
+                e.getColumn())).toLowerCase();
+            if (newEnvReplace.equals("true"))
+              staticMet.replaceMetadata(oldKey + "/envReplace", newEnvReplace);
+            else
+              staticMet.removeMetadata(oldKey + "/envReplace");
+            notifyListeners();
+          }
+        }
+        state.getSelected().getModel().setStaticMetadata(staticMet);
+      }
+
+    }
+
+    public void valueChanged(ListSelectionEvent e) {
+      oldKey = getKey((String) table.getValueAt(e.getFirstIndex(), 1), state);
+      oldValue = (String) table.getValueAt(e.getFirstIndex(), 2);
+      oldEnvReplace = (String) table.getValueAt(e.getFirstIndex(), 3);
+    }
+
+  }
+
+  private String getKey(String key, ViewState state) {
+    if (key != null && state.getCurrentMetGroup() != null)
+      return state.getCurrentMetGroup() + "/" + key;
+    else
+      return key;
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/DefaultTreeView.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/DefaultTreeView.java
new file mode 100644
index 0000000..b8ac2f5
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/DefaultTreeView.java
@@ -0,0 +1,483 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective.view.impl;
+
+//JDK imports
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.MenuItem;
+import java.awt.PopupMenu;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Stack;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeCellRenderer;
+import javax.swing.tree.TreePath;
+
+//Apache imports
+import org.apache.commons.lang.StringUtils;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.gui.model.ModelGraph;
+import org.apache.oodt.cas.workflow.gui.perspective.view.View;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewChange;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewState;
+import org.apache.oodt.cas.workflow.gui.util.GuiUtils;
+
+/**
+ * 
+ * The default Workflow GUI editor view shell.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class DefaultTreeView extends View {
+
+  private static final long serialVersionUID = -8295070597651190576L;
+
+  private JTree tree;
+  private PopupMenu actionsMenu, orderSubMenu;
+  private JScrollPane scrollPane;
+
+  private static final String EXPAND_STATIC_METADATA = "DefaultTreeView/expand/static-metadata";
+  private static final String EXPAND_PRECONDITIONS = "DefaultTreeView/expand/pre-conditions";
+  private static final String EXPAND_POSTCONDITIONS = "DefaultTreeView/expand/post-conditions";
+
+  public DefaultTreeView(String name) {
+    super(name);
+    this.setLayout(new BorderLayout());
+  }
+
+  public TreePath getTreePath(DefaultMutableTreeNode node, ModelGraph graph) {
+    if (node.getUserObject().equals(graph)) {
+      return new TreePath(node.getPath());
+    } else {
+      for (int i = 0; i < node.getChildCount(); i++) {
+        // System.out.println("i: " + ((DefaultMutableTreeNode)
+        // node.getChildAt(i)).getUserObject());
+        TreePath treePath = this.getTreePath(
+            (DefaultMutableTreeNode) node.getChildAt(i), graph);
+        if (treePath != null)
+          return treePath;
+      }
+      return null;
+    }
+  }
+
+  private TreePath getTreePath(TreePath currentPath, ViewState state) {
+    String lookingForPath = state.getCurrentMetGroup();
+    Stack<DefaultMutableTreeNode> stack = new Stack<DefaultMutableTreeNode>();
+    DefaultMutableTreeNode baseNode = (DefaultMutableTreeNode) currentPath
+        .getLastPathComponent();
+    for (int i = 0; i < baseNode.getChildCount(); i++)
+      stack.push((DefaultMutableTreeNode) baseNode.getChildAt(i));
+    while (!stack.empty()) {
+      DefaultMutableTreeNode node = stack.pop();
+      if (node.getUserObject().equals("static-metadata")) {
+        for (int i = 0; i < node.getChildCount(); i++)
+          stack.push((DefaultMutableTreeNode) node.getChildAt(i));
+      } else if (node.getUserObject() instanceof HashMap) {
+        String key = (String) ((HashMap<String, String>) node.getUserObject())
+            .keySet().iterator().next();
+        if (lookingForPath.equals(key)) {
+          return new TreePath(node.getPath());
+        } else if (lookingForPath.startsWith(key + "/")) {
+          lookingForPath = lookingForPath
+              .substring(lookingForPath.indexOf("/") + 1);
+          stack.clear();
+          for (int i = 0; i < node.getChildCount(); i++)
+            stack.add((DefaultMutableTreeNode) node.getChildAt(i));
+        }
+      }
+    }
+    return currentPath;
+  }
+
+  private void resetProperties(ViewState state) {
+    state.setProperty(EXPAND_STATIC_METADATA, "false");
+    state.setProperty(EXPAND_PRECONDITIONS, "false");
+    state.setProperty(EXPAND_POSTCONDITIONS, "false");
+  }
+
+  @Override
+  public void refreshView(final ViewState state) {
+    Rectangle visibleRect = null;
+    if (this.tree != null)
+      visibleRect = this.tree.getVisibleRect();
+
+    this.removeAll();
+
+    this.actionsMenu = this.createPopupMenu(state);
+
+    DefaultMutableTreeNode root = new DefaultMutableTreeNode("WORKFLOWS");
+    for (ModelGraph graph : state.getGraphs())
+      root.add(this.buildTree(graph, state));
+    tree = new JTree(root);
+    tree.setShowsRootHandles(true);
+    tree.setRootVisible(false);
+    tree.add(this.actionsMenu);
+
+    if (state.getSelected() != null) {
+      // System.out.println("SELECTED: " + state.getSelected());
+      TreePath treePath = this.getTreePath(root, state.getSelected());
+      if (state.getCurrentMetGroup() != null) {
+        treePath = this.getTreePath(treePath, state);
+      } else if (Boolean.parseBoolean(state
+          .getFirstPropertyValue(EXPAND_STATIC_METADATA))) {
+        DefaultMutableTreeNode baseNode = (DefaultMutableTreeNode) treePath
+            .getLastPathComponent();
+        for (int i = 0; i < baseNode.getChildCount(); i++) {
+          if (((DefaultMutableTreeNode) baseNode.getChildAt(i)).getUserObject()
+              .equals("static-metadata")) {
+            treePath = new TreePath(
+                ((DefaultMutableTreeNode) baseNode.getChildAt(i)).getPath());
+            break;
+          }
+        }
+      } else if (Boolean.parseBoolean(state
+          .getFirstPropertyValue(EXPAND_PRECONDITIONS))) {
+        if (treePath == null)
+          treePath = this.getTreePath(root, state.getSelected()
+              .getPreConditions());
+        DefaultMutableTreeNode baseNode = (DefaultMutableTreeNode) treePath
+            .getLastPathComponent();
+        for (int i = 0; i < baseNode.getChildCount(); i++) {
+          if (((DefaultMutableTreeNode) baseNode.getChildAt(i)).getUserObject()
+              .equals("pre-conditions")) {
+            treePath = new TreePath(
+                ((DefaultMutableTreeNode) baseNode.getChildAt(i)).getPath());
+            break;
+          }
+        }
+      } else if (Boolean.parseBoolean(state
+          .getFirstPropertyValue(EXPAND_POSTCONDITIONS))) {
+        if (treePath == null)
+          treePath = this.getTreePath(root, state.getSelected()
+              .getPostConditions());
+        DefaultMutableTreeNode baseNode = (DefaultMutableTreeNode) treePath
+            .getLastPathComponent();
+        for (int i = 0; i < baseNode.getChildCount(); i++) {
+          if (((DefaultMutableTreeNode) baseNode.getChildAt(i)).getUserObject()
+              .equals("post-conditions")) {
+            treePath = new TreePath(
+                ((DefaultMutableTreeNode) baseNode.getChildAt(i)).getPath());
+            break;
+          }
+        }
+      }
+      this.tree.expandPath(treePath);
+      this.tree.setSelectionPath(treePath);
+    }
+
+    tree.addTreeSelectionListener(new TreeSelectionListener() {
+
+      public void valueChanged(TreeSelectionEvent e) {
+        if (e.getPath().getLastPathComponent() instanceof DefaultMutableTreeNode) {
+          DefaultTreeView.this.resetProperties(state);
+          DefaultMutableTreeNode node = (DefaultMutableTreeNode) e.getPath()
+              .getLastPathComponent();
+          if (node.getUserObject() instanceof ModelGraph) {
+            state.setSelected((ModelGraph) node.getUserObject());
+            state.setCurrentMetGroup(null);
+            DefaultTreeView.this.notifyListeners();
+          } else if (node.getUserObject().equals("static-metadata")
+              || node.getUserObject().equals("pre-conditions")
+              || node.getUserObject().equals("post-conditions")) {
+            state.setSelected((ModelGraph) ((DefaultMutableTreeNode) node
+                .getParent()).getUserObject());
+            state.setCurrentMetGroup(null);
+            state.setProperty(EXPAND_STATIC_METADATA, Boolean.toString(node
+                .getUserObject().equals("static-metadata")));
+            state.setProperty(EXPAND_PRECONDITIONS,
+                Boolean.toString(node.getUserObject().equals("pre-conditions")));
+            state.setProperty(EXPAND_POSTCONDITIONS, Boolean.toString(node
+                .getUserObject().equals("post-conditions")));
+            DefaultTreeView.this.notifyListeners();
+          } else if (node.getUserObject() instanceof HashMap) {
+            DefaultMutableTreeNode metNode = null;
+            String group = null;
+            Object[] path = e.getPath().getPath();
+            for (int i = path.length - 1; i >= 0; i--) {
+              if (((DefaultMutableTreeNode) path[i]).getUserObject() instanceof ModelGraph) {
+                metNode = (DefaultMutableTreeNode) path[i];
+                break;
+              } else if (((DefaultMutableTreeNode) path[i]).getUserObject() instanceof HashMap) {
+                if (group == null)
+                  group = (String) ((HashMap<String, String>) ((DefaultMutableTreeNode) path[i])
+                      .getUserObject()).keySet().iterator().next();
+                else
+                  group = (String) ((HashMap<String, String>) ((DefaultMutableTreeNode) path[i])
+                      .getUserObject()).keySet().iterator().next()
+                      + "/"
+                      + group;
+              }
+            }
+            ModelGraph graph = (ModelGraph) metNode.getUserObject();
+            state.setSelected(graph);
+            state.setCurrentMetGroup(group);
+            DefaultTreeView.this.notifyListeners();
+          } else {
+            state.setSelected(null);
+            DefaultTreeView.this.notifyListeners();
+          }
+        }
+      }
+
+    });
+    tree.setCellRenderer(new TreeCellRenderer() {
+
+      public Component getTreeCellRendererComponent(JTree tree, Object value,
+          boolean selected, boolean expanded, boolean leaf, int row,
+          boolean hasFocus) {
+        DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
+        if (node.getUserObject() instanceof String) {
+          JPanel panel = new JPanel();
+          panel.setLayout(new BorderLayout());
+          JLabel label = new JLabel((String) node.getUserObject());
+          label.setForeground(Color.blue);
+          panel.add(label, BorderLayout.CENTER);
+          panel.setBackground(selected ? Color.lightGray : Color.white);
+          return panel;
+        } else if (node.getUserObject() instanceof ModelGraph) {
+          JPanel panel = new JPanel();
+          panel.setLayout(new BorderLayout());
+          JLabel iconLabel = new JLabel(((ModelGraph) node.getUserObject())
+              .getModel().getExecutionType() + ": ");
+          iconLabel.setForeground(((ModelGraph) node.getUserObject())
+              .getModel().getColor());
+          iconLabel.setBackground(Color.white);
+          JLabel idLabel = new JLabel(((ModelGraph) node.getUserObject())
+              .getModel().getModelName());
+          idLabel.setBackground(Color.white);
+          panel.add(iconLabel, BorderLayout.WEST);
+          panel.add(idLabel, BorderLayout.CENTER);
+          panel.setBackground(selected ? Color.lightGray : Color.white);
+          return panel;
+        } else if (node.getUserObject() instanceof HashMap) {
+          JPanel panel = new JPanel();
+          panel.setLayout(new BorderLayout());
+          String group = (String) ((HashMap<String, String>) node
+              .getUserObject()).keySet().iterator().next();
+          JLabel nameLabel = new JLabel(group + " : ");
+          nameLabel.setForeground(Color.blue);
+          nameLabel.setBackground(Color.white);
+          JLabel valueLabel = new JLabel(((HashMap<String, String>) node
+              .getUserObject()).get(group));
+          valueLabel.setForeground(Color.darkGray);
+          valueLabel.setBackground(Color.white);
+          panel.add(nameLabel, BorderLayout.WEST);
+          panel.add(valueLabel, BorderLayout.EAST);
+          panel.setBackground(selected ? Color.lightGray : Color.white);
+          return panel;
+        } else {
+          return new JLabel();
+        }
+      }
+
+    });
+    tree.addMouseListener(new MouseListener() {
+      public void mouseClicked(MouseEvent e) {
+        if (e.getButton() == MouseEvent.BUTTON3
+            && DefaultTreeView.this.tree.getSelectionPath() != null) {
+          DefaultMutableTreeNode node = (DefaultMutableTreeNode) DefaultTreeView.this.tree
+              .getSelectionPath().getLastPathComponent();
+          if (node.getUserObject() instanceof String
+              && !(node.getUserObject().equals("pre-conditions") || node
+                  .getUserObject().equals("post-conditions")))
+            return;
+          orderSubMenu.setEnabled(node.getUserObject() instanceof ModelGraph
+              && !((ModelGraph) node.getUserObject()).isCondition()
+              && ((ModelGraph) node.getUserObject()).getParent() != null);
+          DefaultTreeView.this.actionsMenu.show(DefaultTreeView.this.tree,
+              e.getX(), e.getY());
+        }
+      }
+
+      public void mouseEntered(MouseEvent e) {
+      }
+
+      public void mouseExited(MouseEvent e) {
+      }
+
+      public void mousePressed(MouseEvent e) {
+      }
+
+      public void mouseReleased(MouseEvent e) {
+      }
+    });
+    this.scrollPane = new JScrollPane(tree,
+        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+        JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+    this.add(this.scrollPane, BorderLayout.CENTER);
+    if (visibleRect != null)
+      this.tree.scrollRectToVisible(visibleRect);
+
+    this.revalidate();
+  }
+
+  private DefaultMutableTreeNode buildTree(ModelGraph graph, ViewState state) {
+    DefaultMutableTreeNode node = new DefaultMutableTreeNode(graph);
+    DefaultMutableTreeNode metadataNode = new DefaultMutableTreeNode(
+        "static-metadata");
+    Metadata staticMetadata = new Metadata();
+    if (graph.getInheritedStaticMetadata(state) != null)
+      staticMetadata.replaceMetadata(graph.getInheritedStaticMetadata(state));
+    if (graph.getModel().getStaticMetadata() != null)
+      staticMetadata.replaceMetadata(graph.getModel().getStaticMetadata());
+    this.addMetadataNodes(metadataNode, staticMetadata);
+    if (!metadataNode.isLeaf())
+      node.add(metadataNode);
+
+    if (graph.getPreConditions() != null) {
+      DefaultMutableTreeNode preConditions = new DefaultMutableTreeNode(
+          "pre-conditions");
+      List<ModelGraph> leafNodes = graph.getPreConditions().getLeafNodes();
+      for (ModelGraph cond : leafNodes) {
+        DefaultMutableTreeNode condNode = new DefaultMutableTreeNode(cond);
+        preConditions.add(condNode);
+      }
+      node.add(preConditions);
+    }
+    if (graph.getPostConditions() != null) {
+      DefaultMutableTreeNode postConditions = new DefaultMutableTreeNode(
+          "post-conditions");
+      List<ModelGraph> leafNodes = graph.getPostConditions().getLeafNodes();
+      for (ModelGraph cond : leafNodes) {
+        DefaultMutableTreeNode condNode = new DefaultMutableTreeNode(cond);
+        postConditions.add(condNode);
+      }
+      node.add(postConditions);
+    }
+    for (ModelGraph child : graph.getChildren())
+      if (!GuiUtils.isDummyNode(child.getModel()))
+        node.add(this.buildTree(child, state));
+    return node;
+  }
+
+  private void addMetadataNodes(DefaultMutableTreeNode metadataNode,
+      Metadata staticMetadata) {
+    for (String group : staticMetadata.getGroups()) {
+      Object userObj = null;
+      if (staticMetadata.getMetadata(group) != null) {
+        HashMap<String, String> map = new HashMap<String, String>();
+        map.put(group,
+            StringUtils.join(staticMetadata.getAllMetadata(group), ","));
+        userObj = map;
+      } else {
+        HashMap<String, String> map = new HashMap<String, String>();
+        map.put(group, null);
+        userObj = map;
+      }
+      DefaultMutableTreeNode groupNode = new DefaultMutableTreeNode(userObj);
+      metadataNode.add(groupNode);
+      this.addMetadataNodes(groupNode, staticMetadata.getSubMetadata(group));
+    }
+  }
+
+  private PopupMenu createPopupMenu(final ViewState state) {
+    final String ACTIONS_POP_MENU_NAME = "Actions";
+    final String VIEW_CONDITION_MAP = "View...";
+    PopupMenu actionsMenu = new PopupMenu(ACTIONS_POP_MENU_NAME);
+    actionsMenu.add(new MenuItem(VIEW_CONDITION_MAP));
+    actionsMenu.addActionListener(new ActionListener() {
+
+      public void actionPerformed(ActionEvent e) {
+        if (e.getActionCommand().equals(VIEW_CONDITION_MAP)) {
+          DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
+              .getSelectionPath().getLastPathComponent();
+          ModelGraph graphToFocus = null;
+          if (Boolean.parseBoolean(state
+              .getFirstPropertyValue(EXPAND_PRECONDITIONS))
+              || Boolean.parseBoolean(state
+                  .getFirstPropertyValue(EXPAND_POSTCONDITIONS))) {
+            // if (node.getUserObject() instanceof String &&
+            // (node.getUserObject().equals("pre-conditions") ||
+            // node.getUserObject().equals("post-conditions"))) {
+            ModelGraph graph = state.getSelected();
+            if (Boolean.parseBoolean(state
+                .getFirstPropertyValue(EXPAND_PRECONDITIONS)))
+              graphToFocus = graph.getPreConditions();
+            else
+              graphToFocus = graph.getPostConditions();
+          } else if (node.getUserObject() instanceof ModelGraph) {
+            graphToFocus = (ModelGraph) node.getUserObject();
+          }
+          DefaultTreeView.this.notifyListeners(new ViewChange.NEW_VIEW(
+              graphToFocus, DefaultTreeView.this));
+        }
+      }
+
+    });
+
+    final String ORDER_SUB_POP_MENU_NAME = "Order";
+    final String TO_FRONT_ITEM_NAME = "Move To Front";
+    final String TO_BACK_ITEM_NAME = "Move To Back";
+    final String FORWARD_ITEM_NAME = "Move Forward";
+    final String BACKWARDS_ITEM_NAME = "Move Backwards";
+    actionsMenu.add(orderSubMenu = new PopupMenu(ORDER_SUB_POP_MENU_NAME));
+    orderSubMenu.add(new MenuItem(TO_FRONT_ITEM_NAME));
+    orderSubMenu.add(new MenuItem(TO_BACK_ITEM_NAME));
+    orderSubMenu.add(new MenuItem(FORWARD_ITEM_NAME));
+    orderSubMenu.add(new MenuItem(BACKWARDS_ITEM_NAME));
+    orderSubMenu.addActionListener(new ActionListener() {
+
+      public void actionPerformed(ActionEvent e) {
+        ModelGraph graph = state.getSelected();
+        ModelGraph parent = graph.getParent();
+        if (e.getActionCommand().equals(TO_FRONT_ITEM_NAME)) {
+          if (parent.getChildren().remove(graph))
+            parent.getChildren().add(0, graph);
+        } else if (e.getActionCommand().equals(TO_BACK_ITEM_NAME)) {
+          if (parent.getChildren().remove(graph))
+            parent.getChildren().add(graph);
+        } else if (e.getActionCommand().equals(FORWARD_ITEM_NAME)) {
+          int index = parent.getChildren().indexOf(graph);
+          if (index != -1) {
+            parent.getChildren().remove(index);
+            parent.getChildren().add(Math.max(0, index + 1), graph);
+          }
+        } else if (e.getActionCommand().equals(BACKWARDS_ITEM_NAME)) {
+          int index = parent.getChildren().indexOf(graph);
+          if (index != -1) {
+            parent.getChildren().remove(index);
+            parent.getChildren().add(Math.max(0, index - 1), graph);
+          }
+        }
+        DefaultTreeView.this.notifyListeners();
+        DefaultTreeView.this.refreshView(state);
+      }
+
+    });
+    return actionsMenu;
+  }
+
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/GlobalConfigView.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/GlobalConfigView.java
new file mode 100644
index 0000000..f998e76
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/GlobalConfigView.java
@@ -0,0 +1,267 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective.view.impl;
+
+//JDK imports
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Rectangle;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTree;
+import javax.swing.border.EtchedBorder;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeCellRenderer;
+
+//Apache imports
+import org.apache.commons.lang.StringUtils;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.gui.model.repo.XmlWorkflowModelRepository.ConfigGroup;
+import org.apache.oodt.cas.workflow.gui.perspective.view.View;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewState;
+
+/**
+ * 
+ * Displays information about global config properties loaded from the
+ * Workflows.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class GlobalConfigView extends View {
+
+  private static final long serialVersionUID = 3899104909278232407L;
+  private JTree tree;
+  private JTabbedPane tabbedPane;
+  private Map<String, ConfigGroup> globalConfig;
+
+  public GlobalConfigView(String name) {
+    super(name);
+    this.setLayout(new BorderLayout());
+  }
+
+  @Override
+  public void refreshView(ViewState state) {
+
+    Rectangle visibleRect = null;
+    if (this.tree != null)
+      visibleRect = this.tree.getVisibleRect();
+
+    DefaultMutableTreeNode root = new DefaultMutableTreeNode("GlobalConfig");
+
+    if (state != null && state.getGlobalConfigGroups() != null) {
+      if (globalConfig != null
+          && globalConfig.keySet().equals(
+              state.getGlobalConfigGroups().keySet())
+          && globalConfig.values().equals(
+              state.getGlobalConfigGroups().values()))
+        return;
+
+      this.removeAll();
+
+      for (ConfigGroup group : (globalConfig = state.getGlobalConfigGroups())
+          .values()) {
+        HashSet<String> keys = new HashSet<String>();
+        DefaultMutableTreeNode groupNode = new DefaultMutableTreeNode(
+            new Group(group.getName()));
+        root.add(groupNode);
+        for (String key : group.getMetadata().getAllKeys()) {
+          keys.add(key);
+          DefaultMutableTreeNode keyNode = new DefaultMutableTreeNode(new Key(
+              key));
+          groupNode.add(keyNode);
+          DefaultMutableTreeNode valueNode = new DefaultMutableTreeNode(
+              new Value(StringUtils.join(group.getMetadata()
+                  .getAllMetadata(key), ",")));
+          keyNode.add(valueNode);
+        }
+        if (group.getExtends() != null) {
+          List<String> extendsGroups = new Vector<String>(group.getExtends());
+          Collections.reverse(extendsGroups);
+          for (String extendsGroup : extendsGroups) {
+            List<String> groupKeys = state.getGlobalConfigGroups()
+                .get(extendsGroup).getMetadata().getAllKeys();
+            groupKeys.removeAll(keys);
+            if (groupKeys.size() > 0) {
+              for (String key : groupKeys) {
+                if (!keys.contains(key)) {
+                  keys.add(key);
+                  DefaultMutableTreeNode keyNode = new DefaultMutableTreeNode(
+                      new ExtendsKey(extendsGroup, key));
+                  groupNode.add(keyNode);
+                  DefaultMutableTreeNode valueNode = new DefaultMutableTreeNode(
+                      new ExtendsValue(StringUtils.join(state
+                          .getGlobalConfigGroups().get(extendsGroup)
+                          .getMetadata().getAllMetadata(key), ",")));
+                  keyNode.add(valueNode);
+                }
+              }
+            }
+          }
+        }
+      }
+
+      tree = new JTree(root);
+      tree.setShowsRootHandles(true);
+      tree.setRootVisible(false);
+
+      tree.setCellRenderer(new TreeCellRenderer() {
+
+        public Component getTreeCellRendererComponent(JTree tree, Object value,
+            boolean selected, boolean expanded, boolean leaf, int row,
+            boolean hasFocus) {
+          DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
+          if (node.getUserObject() instanceof Key) {
+            JPanel panel = new JPanel();
+            panel.setLayout(new BorderLayout());
+            JLabel label = new JLabel(node.getUserObject().toString());
+            label.setForeground(Color.darkGray);
+            panel.add(label, BorderLayout.CENTER);
+            panel.setBackground(selected ? Color.lightGray : Color.white);
+            return panel;
+          } else if (node.getUserObject() instanceof ExtendsKey) {
+            JPanel panel = new JPanel();
+            panel.setLayout(new BorderLayout());
+            ExtendsKey key = (ExtendsKey) node.getUserObject();
+            JLabel groupLabel = new JLabel("(" + key.getGroup() + ") ");
+            groupLabel.setForeground(Color.black);
+            JLabel keyLabel = new JLabel(key.getValue());
+            keyLabel.setForeground(Color.gray);
+            panel.add(groupLabel, BorderLayout.WEST);
+            panel.add(keyLabel, BorderLayout.CENTER);
+            panel.setBackground(selected ? Color.lightGray : Color.white);
+            return panel;
+          } else if (node.getUserObject() instanceof Group) {
+            JPanel panel = new JPanel();
+            panel.setLayout(new BorderLayout());
+            JLabel label = new JLabel(node.getUserObject().toString());
+            label.setForeground(Color.black);
+            label.setBackground(Color.white);
+            panel.add(label, BorderLayout.CENTER);
+            panel.setBackground(selected ? Color.lightGray : Color.white);
+            return panel;
+          } else if (node.getUserObject() instanceof Value) {
+            JPanel panel = new JPanel();
+            panel.setLayout(new BorderLayout());
+            panel.setBorder(new EtchedBorder(1));
+            JLabel label = new JLabel(node.getUserObject().toString());
+            label.setForeground(Color.black);
+            panel.add(label, BorderLayout.CENTER);
+            panel.setBackground(selected ? Color.lightGray : Color.white);
+            return panel;
+          } else if (node.getUserObject() instanceof ExtendsValue) {
+            JPanel panel = new JPanel();
+            panel.setLayout(new BorderLayout());
+            panel.setBorder(new EtchedBorder(1));
+            JLabel label = new JLabel(node.getUserObject().toString());
+            label.setForeground(Color.gray);
+            panel.add(label, BorderLayout.CENTER);
+            panel.setBackground(selected ? Color.lightGray : Color.white);
+            return panel;
+          } else {
+            return new JLabel();
+          }
+        }
+
+      });
+    }
+
+    this.setBorder(new EtchedBorder());
+    JLabel panelName = new JLabel("Global-Config Groups");
+    panelName.setBorder(new EtchedBorder());
+    this.add(panelName, BorderLayout.NORTH);
+    JScrollPane scrollPane = new JScrollPane(tree,
+        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+        JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+
+    tabbedPane = new JTabbedPane();
+    tabbedPane.addTab("Tree", scrollPane);
+    tabbedPane.addTab("Table", new JPanel());
+
+    this.add(tabbedPane, BorderLayout.CENTER);
+
+    if (visibleRect != null)
+      this.tree.scrollRectToVisible(visibleRect);
+
+    this.revalidate();
+  }
+
+  public class StringNode {
+    private String value;
+
+    public StringNode(String value) {
+      this.value = value;
+    }
+
+    public String getValue() {
+      return this.value;
+    }
+
+    public String toString() {
+      return this.value;
+    }
+  }
+
+  public class Key extends StringNode {
+    public Key(String value) {
+      super(value);
+    }
+  }
+
+  public class ExtendsKey extends StringNode {
+    private String group;
+
+    public ExtendsKey(String group, String value) {
+      super(value);
+      this.group = group;
+    }
+
+    public String getGroup() {
+      return this.group;
+    }
+  }
+
+  public class ExtendsValue extends StringNode {
+    public ExtendsValue(String value) {
+      super(value);
+    }
+  }
+
+  public class Value extends StringNode {
+    public Value(String value) {
+      super(value);
+    }
+  }
+
+  public class Group extends StringNode {
+    public Group(String group) {
+      super(group);
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/GraphView.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/GraphView.java
new file mode 100644
index 0000000..69469d1
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/GraphView.java
@@ -0,0 +1,1100 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective.view.impl;
+
+//JDK imports
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.Graphics2D;
+import java.awt.MenuItem;
+import java.awt.Point;
+import java.awt.PopupMenu;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.DragSourceDragEvent;
+import java.awt.dnd.DragSourceDropEvent;
+import java.awt.dnd.DragSourceEvent;
+import java.awt.dnd.DragSourceListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelListener;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.Map.Entry;
+import javax.swing.JScrollPane;
+import javax.swing.SwingConstants;
+import javax.swing.border.LineBorder;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+//JGraph imports
+import org.jgraph.JGraph;
+import org.jgraph.graph.AttributeMap;
+import org.jgraph.graph.DefaultGraphCell;
+import org.jgraph.graph.DefaultEdge;
+import org.jgraph.graph.GraphConstants;
+import com.jgraph.layout.JGraphFacade;
+import com.jgraph.layout.hierarchical.JGraphHierarchicalLayout;
+
+//Jung imports
+import edu.uci.ics.jung.graph.DirectedSparseGraph;
+import edu.uci.ics.jung.graph.ObservableGraph;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.gui.model.ModelGraph;
+import org.apache.oodt.cas.workflow.gui.model.ModelNode;
+import org.apache.oodt.cas.workflow.gui.perspective.view.View;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewChange;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewState;
+import org.apache.oodt.cas.workflow.gui.util.GuiUtils;
+import org.apache.oodt.cas.workflow.gui.util.IconLoader;
+import org.apache.oodt.cas.workflow.gui.util.Line;
+
+/**
+ * 
+ * This is where the money happens. The Graph visualization of OODT CAS
+ * workflows is displayed via this view, which magically integrates JGraph,
+ * Jung, and OODT.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class GraphView extends DefaultTreeView {
+
+  private static final long serialVersionUID = 5935578385254884387L;
+
+  private JungJGraphModelAdapter m_jgAdapter;
+  private JGraph jgraph;
+  private ObservableGraph<ModelNode, IdentifiableEdge> directedGraph;
+
+  private MyGraphListener myGraphListener;
+
+  private static final String VIEW_REF_WORKFLOW = "View Referrenced";
+  private static final String ACTIONS_POP_MENU_NAME = "Actions";
+  private static final String NEW_SUB_POP_MENU_NAME = "New";
+  private static final String NEW_TASK_ITEM_NAME = "Task";
+  private static final String NEW_CONDITION_ITEM_NAME = "Condition";
+  private static final String NEW_PARALLEL_ITEM_NAME = "Parallel";
+  private static final String NEW_SEQUENTIAL_ITEM_NAME = "Sequential";
+  private static final String EDGES_SUB_POP_MENU_NAME = "Edges";
+  private static final String TASK_LEVEL = "Task Level";
+  private static final String WORKFLOW_LEVEL = "Workflow Level";
+  private static final String DELETE_ITEM_NAME = "Delete";
+  private static final String FORMAT_ITEM_NAME = "Format";
+  private static final String ORDER_SUB_POP_MENU_NAME = "Order";
+  private static final String TO_FRONT_ITEM_NAME = "Move To Front";
+  private static final String TO_BACK_ITEM_NAME = "Move To Back";
+  private static final String FORWARD_ITEM_NAME = "Move Forward";
+  private static final String BACKWARDS_ITEM_NAME = "Move Backwards";
+
+  private HashMap<String, Pair> edgeMap;
+
+  private static final String SCALE = "GraphView/scale";
+  private static final String EDGE_DISPLAY_MODE = "GraphView/EdgeDisplay/Mode";
+  private static final String TASK_MODE = "Task";
+  private static final String WORKFLOW_MODE = "Workflow";
+
+  private static boolean scrollSelectedToVisible = false;
+
+  public GraphView(String name) {
+    super(name);
+  }
+
+  @Override
+  public void refreshView(final ViewState state) {
+    this.removeAll();
+    this.myGraphListener = new MyGraphListener(state);
+
+    Rectangle visible = null;
+    if (jgraph != null)
+      visible = jgraph.getVisibleRect();
+
+    Cursor cursor = null;
+    if (jgraph != null)
+      cursor = jgraph.getCursor();
+
+    this.edgeMap = new HashMap<String, Pair>();
+
+    directedGraph = new ObservableGraph<ModelNode, IdentifiableEdge>(
+        new DirectedSparseGraph<ModelNode, IdentifiableEdge>());
+    m_jgAdapter = new JungJGraphModelAdapter(directedGraph);
+
+    jgraph = new JGraph(m_jgAdapter);
+    for (MouseListener ml : jgraph.getMouseListeners())
+      jgraph.removeMouseListener(ml);
+    for (MouseMotionListener ml : jgraph.getMouseMotionListeners())
+      jgraph.removeMouseMotionListener(ml);
+    for (MouseWheelListener ml : jgraph.getMouseWheelListeners())
+      jgraph.removeMouseWheelListener(ml);
+    jgraph.setBackground(Color.white);
+    jgraph.setAntiAliased(true);
+    jgraph.setMoveable(false);
+    String scale = state.getFirstPropertyValue(SCALE);
+    if (scale == null)
+      state.setProperty(SCALE, scale = "1.0");
+    jgraph.setScale(Double.parseDouble(scale));
+
+    DragSource dragSource = DragSource.getDefaultDragSource();
+    dragSource.createDefaultDragGestureRecognizer(this.jgraph,
+        DnDConstants.ACTION_MOVE, new DragGestureListener() {
+
+          DefaultGraphCell moveCell = null;
+          ModelGraph moveGraph = null;
+
+          public void dragGestureRecognized(final DragGestureEvent dge) {
+            if (state.getMode() == View.Mode.MOVE
+                || state.getMode() == View.Mode.EDIT) {
+              Object moveOverCell = jgraph.getFirstCellForLocation(dge
+                  .getDragOrigin().getX(), dge.getDragOrigin().getY());
+              if (moveOverCell != null) {
+                if (moveOverCell instanceof DefaultEdge) {
+                  moveCell = null;
+                } else if (moveOverCell instanceof DefaultGraphCell) {
+                  moveCell = (DefaultGraphCell) moveOverCell;
+                  moveGraph = GuiUtils.find(state.getGraphs(),
+                      ((ModelNode) ((DefaultGraphCell) moveCell)
+                          .getUserObject()).getId());
+
+                  if (state.getMode() == View.Mode.MOVE)
+                    moveCell = GraphView.this.m_jgAdapter
+                        .getVertexCell((moveGraph = moveGraph.getRootParent())
+                            .getModel());
+                  else if (GuiUtils.isDummyNode(moveGraph.getModel()))
+                    moveCell = GraphView.this.m_jgAdapter
+                        .getVertexCell((moveGraph = moveGraph.getParent())
+                            .getModel());
+                  else if (moveGraph.getModel().isRef()) {
+                    while (moveGraph.getParent() != null
+                        && moveGraph.getParent().getModel().isRef())
+                      moveGraph = moveGraph.getParent();
+                    moveCell = GraphView.this.m_jgAdapter
+                        .getVertexCell(moveGraph.getModel());
+                  }
+                  final double scale = Double.parseDouble(state
+                      .getFirstPropertyValue(SCALE));
+                  final Rectangle2D bounds = (Rectangle2D) GraphView.this.jgraph
+                      .getAttributes(moveCell).get(GraphConstants.BOUNDS);
+                  Point offset = new Point(
+                      (int) (bounds.getX() * scale - dge.getDragOrigin().getX()),
+                      (int) (bounds.getY() * scale - dge.getDragOrigin().getY()));
+                  BufferedImage image = new BufferedImage((int) (bounds
+                      .getWidth() * scale), (int) (bounds.getHeight() * scale),
+                      BufferedImage.TYPE_INT_ARGB);
+                  Graphics2D g2d = image.createGraphics();
+                  g2d.setColor(Color.black);
+                  g2d.drawRect((int) (2 * scale), (int) (2 * scale),
+                      (int) ((bounds.getWidth() - 4) * scale),
+                      (int) ((bounds.getHeight() - 4) * scale));
+                  dge.startDrag(GraphView.this.getCursor(), image, offset,
+                      new Transferable() {
+
+                        public Object getTransferData(DataFlavor flavor)
+                            throws UnsupportedFlavorException, IOException {
+                          if (flavor.getHumanPresentableName().equals(
+                              DefaultGraphCell.class.getSimpleName()))
+                            return this;
+                          else
+                            throw new UnsupportedFlavorException(flavor);
+                        }
+
+                        public DataFlavor[] getTransferDataFlavors() {
+                          return new DataFlavor[] { new DataFlavor(
+                              DefaultGraphCell.class, DefaultGraphCell.class
+                                  .getSimpleName()) };
+                        }
+
+                        public boolean isDataFlavorSupported(DataFlavor flavor) {
+                          if (flavor.getHumanPresentableName().equals(
+                              DefaultGraphCell.class.getSimpleName()))
+                            return true;
+                          else
+                            return false;
+                        }
+
+                      }, new DragSourceListener() {
+
+                        private ModelGraph mouseOverGraph;
+                        private DefaultGraphCell mouseOverCell;
+
+                        public void dragDropEnd(DragSourceDropEvent dsde) {
+                          System.out.println("DRAG END!!!!");
+                          if (moveCell == null)
+                            return;
+                          Point dropPoint = new Point(dsde.getX()
+                              - jgraph.getLocationOnScreen().x, dsde.getY()
+                              - jgraph.getLocationOnScreen().y);
+                          DefaultGraphCell endCell = (DefaultGraphCell) GraphView.this.jgraph
+                              .getSelectionCell();
+                          if (endCell != null) {
+                            ModelGraph endGraph = GuiUtils.find(
+                                state.getGraphs(),
+                                ((ModelNode) endCell.getUserObject()).getId());
+                            if (!endGraph.getModel().isParentType()
+                                || GuiUtils.isSubGraph(moveGraph, endGraph))
+                              return;
+                            if (moveGraph.getParent() == null)
+                              state.removeGraph(moveGraph);
+                            else
+                              GuiUtils.removeNode(state.getGraphs(),
+                                  moveGraph.getModel());
+                            GraphView.this.removeShift(state, moveGraph);
+                            GuiUtils.addChild(state.getGraphs(), endGraph
+                                .getModel().getId(), moveGraph);
+                            GraphView.this.notifyListeners();
+                          } else {
+                            if (moveGraph.getParent() != null) {
+                              GuiUtils.removeNode(state.getGraphs(),
+                                  moveGraph.getModel());
+                              state.addGraph(moveGraph);
+                            }
+                            Point shiftPoint = new Point(
+                                (int) ((dropPoint.x - (dge.getDragOrigin().x - (bounds
+                                    .getX() * scale))) / scale),
+                                (int) ((dropPoint.y - (dge.getDragOrigin().y - (bounds
+                                    .getY() * scale))) / scale));
+                            GraphView.this.setShift(state, moveGraph,
+                                shiftPoint);
+                            GraphView.this.notifyListeners();
+                          }
+                        }
+
+                        public void dragEnter(DragSourceDragEvent dsde) {
+                          mouseOverCell = (DefaultGraphCell) GraphView.this.jgraph
+                              .getFirstCellForLocation(
+                                  dsde.getX() - jgraph.getLocationOnScreen().x,
+                                  dsde.getY() - jgraph.getLocationOnScreen().y);
+                          mouseOverGraph = GuiUtils.find(state.getGraphs(),
+                              ((ModelNode) mouseOverCell.getUserObject())
+                                  .getId());
+                        }
+
+                        public void dragExit(DragSourceEvent dse) {
+                          System.out.println("DRAG EXIT!!!!");
+                        }
+
+                        public void dragOver(DragSourceDragEvent dsde) {
+                          if (state.getMode().equals(Mode.EDIT)) {
+                            if (mouseOverCell != null) {
+                              Rectangle2D currentBounds = (Rectangle2D) mouseOverCell
+                                  .getAttributes().get(GraphConstants.BOUNDS);
+                              Point currentPoint = new Point(dsde.getX()
+                                  - jgraph.getLocationOnScreen().x, dsde.getY()
+                                  - jgraph.getLocationOnScreen().y);
+                              if (currentBounds.contains(currentPoint)) {
+                                for (ModelGraph child : mouseOverGraph
+                                    .getChildren()) {
+                                  DefaultGraphCell mouseOverCellLoc = GraphView.this.m_jgAdapter
+                                      .getVertexCell(child.getModel());
+                                  currentBounds = (Rectangle2D) mouseOverCellLoc
+                                      .getAttributes().get(
+                                          GraphConstants.BOUNDS);
+                                  if (currentBounds.contains(currentPoint)) {
+                                    mouseOverCell = mouseOverCellLoc;
+                                    mouseOverGraph = child;
+                                    break;
+                                  }
+                                }
+                              } else {
+                                if (mouseOverGraph.getParent() != null
+                                    && (!mouseOverGraph.isCondition() || (mouseOverGraph
+                                        .isCondition() && mouseOverGraph
+                                        .getParent().isCondition()))) {
+                                  mouseOverCell = GraphView.this.m_jgAdapter
+                                      .getVertexCell((mouseOverGraph = mouseOverGraph
+                                          .getParent()).getModel());
+                                  currentBounds = (Rectangle2D) mouseOverCell
+                                      .getAttributes().get(
+                                          GraphConstants.BOUNDS);
+                                } else {
+                                  mouseOverCell = null;
+                                  mouseOverGraph = null;
+                                }
+                              }
+                            } else {
+                              mouseOverCell = (DefaultGraphCell) GraphView.this.jgraph
+                                  .getFirstCellForLocation(
+                                      dsde.getX()
+                                          - jgraph.getLocationOnScreen().x,
+                                      dsde.getY()
+                                          - jgraph.getLocationOnScreen().y);
+                              if (mouseOverCell != null)
+                                mouseOverGraph = GuiUtils.find(state
+                                    .getGraphs(), ((ModelNode) mouseOverCell
+                                    .getUserObject()).getId());
+                              else
+                                mouseOverGraph = null;
+                            }
+                            if (mouseOverGraph != null) {
+                              if (GuiUtils.isDummyNode(mouseOverGraph
+                                  .getModel())) {
+                                mouseOverGraph = mouseOverGraph.getParent();
+                              } else {
+                                while (mouseOverGraph != null
+                                    && mouseOverGraph.getModel().isRef())
+                                  mouseOverGraph = mouseOverGraph.getParent();
+                              }
+                              if (mouseOverGraph != null)
+                                mouseOverCell = GraphView.this.m_jgAdapter
+                                    .getVertexCell(mouseOverGraph.getModel());
+                              else
+                                mouseOverCell = null;
+                            }
+                            GraphView.this.jgraph
+                                .setSelectionCells(new Object[] { mouseOverCell });
+                          }
+                        }
+
+                        public void dropActionChanged(DragSourceDragEvent dsde) {
+                          System.out.println("DRAG CHANGE!!!!");
+                        }
+
+                      });
+                }
+              }
+            }
+          }
+
+        });
+
+    List<Line> lines = GuiUtils.findLines(state.getGraphs());
+    for (Line line : lines) {
+      if (!this.directedGraph.containsVertex(line.getFromModel()))
+        this.directedGraph.addVertex(line.getFromModel());
+
+      if (line.getToModel() != null) {
+        if (!this.directedGraph.containsVertex(line.getToModel()))
+          this.directedGraph.addVertex(line.getToModel());
+        IdentifiableEdge edge = new IdentifiableEdge(line.getFromModel(), line.getToModel());
+        directedGraph.addEdge(edge, line.getFromModel(), line.getToModel());
+        this.edgeMap.put(edge.id, new Pair(line.getFromModel() != null ? line
+            .getFromModel().getId() : null, line.getToModel().getId()));
+      }
+    }
+
+    JGraphFacade facade = new JGraphFacade(jgraph);
+    facade.setIgnoresUnconnectedCells(false);
+    JGraphHierarchicalLayout layout = new JGraphHierarchicalLayout();
+    layout.setOrientation(SwingConstants.WEST);
+    layout.setIntraCellSpacing(70.0);
+    layout.setLayoutFromSinks(false);
+    layout.run(facade);
+    Map nested = facade.createNestedMap(true, true);
+    if (nested != null) {
+      this.hideDummyNodes(nested);
+      this.addGroups(state.getGraphs(), nested, state);
+      this.ensureNoOverlap(nested, state);
+      nested = this.shiftMap(nested, state);
+      jgraph.getGraphLayoutCache().edit(nested);
+    }
+
+    String edgeDisplayMode = state.getFirstPropertyValue(EDGE_DISPLAY_MODE);
+    if (edgeDisplayMode == null)
+      state.setProperty(EDGE_DISPLAY_MODE, edgeDisplayMode = WORKFLOW_MODE);
+    if (edgeDisplayMode.equals(WORKFLOW_MODE)) {
+      this.edgeMap = new HashMap<String, Pair>();
+      removeAllEdges(this.directedGraph);
+      lines = GuiUtils.findSequentialLines(state.getGraphs());
+      for (Line line : lines) {
+        IdentifiableEdge edge = new IdentifiableEdge(line.getFromModel(), line.getToModel());
+        directedGraph.addEdge(edge, line.getFromModel(), line.getToModel());
+        this.edgeMap.put(edge.id, new Pair(line.getFromModel() != null ? line
+            .getFromModel().getId() : null, line.getToModel().getId()));
+      }
+    }
+
+    if (state.getSelected() != null) {
+      ModelGraph graph = GuiUtils.find(state.getGraphs(), state.getSelected()
+          .getModel().getId());
+      if (graph != null) {
+        DefaultGraphCell cell = this.m_jgAdapter
+            .getVertexCell(graph.getModel());
+        if (cell != null)
+          this.jgraph.setSelectionCells(new Object[] { cell });
+        else
+          this.jgraph.setSelectionCells(new Object[] {});
+      } else
+        this.jgraph.setSelectionCells(new Object[] {});
+    } else {
+      this.jgraph.setSelectionCells(new Object[] {});
+    }
+
+    jgraph.addMouseListener(this.myGraphListener);
+
+    this.setLayout(new BorderLayout());
+    this.add(new JScrollPane(jgraph, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+        JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS), BorderLayout.CENTER);
+
+    if (scrollSelectedToVisible && state.getSelected() != null) {
+      this.jgraph.scrollCellToVisible(GraphView.this.m_jgAdapter
+          .getVertexCell(state.getSelected().getModel()));
+      scrollSelectedToVisible = false;
+    } else if (visible != null) {
+      this.jgraph.scrollRectToVisible(visible);
+    }
+
+    if (cursor != null)
+      this.jgraph.setCursor(cursor);
+
+    this.revalidate();
+  }
+
+  private void hideDummyNodes(Map nested) {
+    for (Object cell : nested.keySet()) {
+      if (cell instanceof DefaultEdge) {
+        // do nothing
+      } else if (cell instanceof DefaultGraphCell) {
+        if (GuiUtils.isDummyNode((ModelNode) ((DefaultGraphCell) cell)
+            .getUserObject())) {
+          ((Map<Object, Object>) nested.get(cell)).put("opaque", false);
+          ((Map<Object, Object>) nested.get(cell)).put("backgroundColor",
+              Color.white);
+        }
+      }
+    }
+  }
+
+  private Map shiftMap(Map nested, ViewState state) {
+    Map shiftedNested = new Hashtable(nested);
+    for (Object obj : shiftedNested.entrySet()) {
+      Entry entry = (Entry) obj;
+      if (entry.getKey() instanceof DefaultEdge) {
+        ArrayList<Point2D.Double> points = (ArrayList<Point2D.Double>) ((Map<Object, Object>) entry
+            .getValue()).get("points");
+        ArrayList<Point2D.Double> newPoints = new ArrayList<Point2D.Double>();
+        Point shift = this.getShift(state, (DefaultGraphCell) entry.getKey(),
+            nested);
+        for (Point2D.Double point : points)
+          newPoints
+              .add(new Point2D.Double(point.x + shift.x, point.y + shift.y));
+        ((Map<Object, Object>) entry.getValue()).put("points", newPoints);
+      } else if (entry.getKey() instanceof DefaultGraphCell) {
+        DefaultGraphCell cell = (DefaultGraphCell) entry.getKey();
+        Rectangle2D bounds = (Rectangle2D) ((Map<Object, Object>) entry
+            .getValue()).get("bounds");
+        Point shift = this.getShift(state, cell, nested);
+        AttributeMap.SerializableRectangle2D newBounds = new AttributeMap.SerializableRectangle2D(
+            bounds.getX() + shift.x, bounds.getY() + shift.y,
+            bounds.getWidth(), bounds.getHeight());
+        Map<Object, Object> newMap = new Hashtable<Object, Object>(
+            (Map<Object, Object>) entry.getValue());
+        newMap.put("bounds", newBounds);
+        shiftedNested.put(cell, newMap);
+      }
+    }
+    return shiftedNested;
+  }
+
+  private void ensureNoOverlap(Map nested, ViewState state) {
+    boolean changed;
+    do {
+      changed = false;
+      for (int i = 0; i < state.getGraphs().size(); i++) {
+        ModelGraph currentGraph = state.getGraphs().get(i);
+        if (this.ensureNoInternalOverlap(currentGraph, nested))
+          changed = true;
+        DefaultGraphCell currentCell = this.m_jgAdapter
+            .getVertexCell(currentGraph.getModel());
+        Rectangle2D currentBounds = (Rectangle2D) ((Map) nested
+            .get(currentCell)).get(GraphConstants.BOUNDS);
+        Point currentShift = this.getShift(state, currentCell, nested);
+        Rectangle currentShiftBounds = new Rectangle(
+            (int) (currentBounds.getX() + currentShift.getX()),
+            (int) (currentBounds.getY() + currentShift.getY()),
+            (int) currentBounds.getWidth(), (int) currentBounds.getHeight());
+        for (int j = 0; j < state.getGraphs().size(); j++) {
+          if (i == j)
+            continue;
+          ModelGraph graph = state.getGraphs().get(j);
+          DefaultGraphCell cell = this.m_jgAdapter.getVertexCell(graph
+              .getModel());
+          Rectangle2D bounds = (Rectangle2D) ((Map) nested.get(cell))
+              .get(GraphConstants.BOUNDS);
+          Point shift = this.getShift(state, cell, nested);
+          Rectangle shiftBounds = new Rectangle(
+              (int) (bounds.getX() + shift.getX()),
+              (int) (bounds.getY() + shift.getY()), (int) bounds.getWidth(),
+              (int) bounds.getHeight());
+          if (currentShiftBounds.intersects(shiftBounds)) {
+            changed = true;
+            if (currentShiftBounds.getY() < shiftBounds.getY()) {
+              Rectangle intersection = currentShiftBounds
+                  .intersection(shiftBounds);
+              if (currentShiftBounds.getY() + currentShiftBounds.getHeight() > shiftBounds
+                  .getY() + shiftBounds.getHeight()) {
+                this.setShift(state, graph,
+                    new Point((int) (currentShiftBounds.getX()
+                        + currentShiftBounds.getWidth() + 20.0),
+                        (int) shiftBounds.getY()));
+              } else {
+                this.setShift(
+                    state,
+                    graph,
+                    new Point((int) shiftBounds.getX(), (int) (shiftBounds
+                        .getY() + intersection.getHeight() + 20.0)));
+              }
+            } else {
+              Rectangle intersection = shiftBounds
+                  .intersection(currentShiftBounds);
+              if (shiftBounds.getY() + shiftBounds.getHeight() > currentShiftBounds
+                  .getY() + currentShiftBounds.getHeight()) {
+                this.setShift(
+                    state,
+                    currentGraph,
+                    new Point((int) (shiftBounds.getX()
+                        + shiftBounds.getWidth() + 20.0),
+                        (int) currentShiftBounds.getY()));
+              } else {
+                this.setShift(
+                    state,
+                    currentGraph,
+                    new Point((int) currentShiftBounds.getX(),
+                        (int) (currentShiftBounds.getY()
+                            + intersection.getHeight() + 20.0)));
+              }
+
+              currentShift = this.getShift(state, currentCell, nested);
+              currentShiftBounds = new Rectangle(
+                  (int) (currentBounds.getX() + currentShift.getX()),
+                  (int) (currentBounds.getY() + currentShift.getY()),
+                  (int) currentBounds.getWidth(),
+                  (int) currentBounds.getHeight());
+            }
+          }
+        }
+      }
+    } while (changed);
+  }
+
+  private boolean ensureNoInternalOverlap(final ModelGraph graph,
+      final Map nested) {
+    boolean changed = false;
+    if (graph.getChildren().size() > 1) {
+      List<ModelGraph> sortedChildren = new Vector<ModelGraph>(
+          graph.getChildren());
+      Collections.sort(sortedChildren, new Comparator<ModelGraph>() {
+
+        public int compare(ModelGraph o1, ModelGraph o2) {
+          DefaultGraphCell child1Cell = GraphView.this.m_jgAdapter
+              .getVertexCell(o1.getModel());
+          DefaultGraphCell child2Cell = GraphView.this.m_jgAdapter
+              .getVertexCell(o2.getModel());
+          Rectangle2D child1Bounds = (Rectangle2D) ((Map) nested
+              .get(child1Cell)).get(GraphConstants.BOUNDS);
+          Rectangle2D child2Bounds = (Rectangle2D) ((Map) nested
+              .get(child2Cell)).get(GraphConstants.BOUNDS);
+          if (graph.getModel().getExecutionType().equals("parallel"))
+            return Double.compare(child1Bounds.getMaxY(),
+                child2Bounds.getMaxY());
+          else
+            return Double.compare(child1Bounds.getX(), child2Bounds.getX());
+        }
+
+      });
+      changed = ensureNoInternalOverlap(sortedChildren.get(0), nested);
+      Rectangle2D graphRectangle = (Rectangle2D) ((Map) nested
+          .get(this.m_jgAdapter.getVertexCell(sortedChildren.get(0).getModel())))
+          .get(GraphConstants.BOUNDS);
+      for (int i = 1; i < sortedChildren.size(); i++) {
+        ModelGraph child2 = sortedChildren.get(i);
+        if (ensureNoInternalOverlap(child2, nested))
+          changed = true;
+        DefaultGraphCell child2Cell = this.m_jgAdapter.getVertexCell(child2
+            .getModel());
+        for (int j = i - 1; j >= 0; j--) {
+          ModelGraph child1 = sortedChildren.get(j);
+          DefaultGraphCell child1Cell = this.m_jgAdapter.getVertexCell(child1
+              .getModel());
+          Rectangle2D child1Bounds = (Rectangle2D) ((Map) nested
+              .get(child1Cell)).get(GraphConstants.BOUNDS);
+          Rectangle2D child2Bounds = (Rectangle2D) ((Map) nested
+              .get(child2Cell)).get(GraphConstants.BOUNDS);
+          if (child1Bounds.intersects(child2Bounds)) {
+            changed = true;
+            if (graph.getModel().getExecutionType().equals("parallel")) {
+              ((Map) nested.get(child2Cell)).put(GraphConstants.BOUNDS,
+                  new AttributeMap.SerializableRectangle2D(child2Bounds.getX(),
+                      child1Bounds.getMaxY() + 20.0, child2Bounds.getWidth(),
+                      child2Bounds.getHeight()));
+              this.shift(child2.getChildren(), nested, 0,
+                  child1Bounds.getMaxY() + 20.0 - child2Bounds.getY());
+            } else {
+              ((Map) nested.get(child2Cell)).put(
+                  GraphConstants.BOUNDS,
+                  new AttributeMap.SerializableRectangle2D(child1Bounds
+                      .getMaxX() + 20.0, child2Bounds.getY(), child2Bounds
+                      .getWidth(), child2Bounds.getHeight()));
+              this.shift(child2.getChildren(), nested, child1Bounds.getMaxX()
+                  + 20.0 - child2Bounds.getX(), 0);
+            }
+          }
+        }
+        graphRectangle = graphRectangle.createUnion((Rectangle2D) ((Map) nested
+            .get(child2Cell)).get(GraphConstants.BOUNDS));
+      }
+      ((Map) nested.get(this.m_jgAdapter.getVertexCell(graph.getModel()))).put(
+          GraphConstants.BOUNDS, new AttributeMap.SerializableRectangle2D(
+              graphRectangle.getX() - 5, graphRectangle.getY() - 20,
+              graphRectangle.getWidth() + 10, graphRectangle.getHeight() + 25));
+    }
+    return changed;
+  }
+
+  private void shift(List<ModelGraph> graphs, Map nested, double x, double y) {
+    for (int i = 0; i < graphs.size(); i++) {
+      ModelGraph graph = graphs.get(i);
+      DefaultGraphCell cell = this.m_jgAdapter.getVertexCell(graph.getModel());
+      Rectangle2D bounds = (Rectangle2D) ((Map) nested.get(cell))
+          .get(GraphConstants.BOUNDS);
+      ((Map) nested.get(cell)).put(
+          GraphConstants.BOUNDS,
+          new AttributeMap.SerializableRectangle2D(bounds.getX() + x, bounds
+              .getY() + y, bounds.getWidth(), bounds.getHeight()));
+      this.shift(graph.getChildren(), nested, x, y);
+    }
+  }
+
+  private void addGroups(List<ModelGraph> modelGraphs, Map nested,
+      ViewState state) {
+    for (ModelGraph modelGraph : modelGraphs)
+      this.addGroups(modelGraph, nested, state);
+  }
+
+  private DefaultGraphCell addGroups(ModelGraph modelGraph, Map nested,
+      ViewState state) {
+    if (modelGraph.getModel().isParentType()) {
+      double top_x = Double.MAX_VALUE, top_y = Double.MAX_VALUE, bottom_x = 0.0, bottom_y = 0.0;
+      this.directedGraph.addVertex(modelGraph.getModel());
+      DefaultGraphCell modelCell = this.m_jgAdapter.getVertexCell(modelGraph
+          .getModel());
+      Vector<DefaultGraphCell> group = new Vector<DefaultGraphCell>();
+      group.add(modelCell);
+
+      HashMap<Object, Object> map = new HashMap<Object, Object>();
+      for (int i = 0; i < modelGraph.getChildren().size(); i++) {
+        ModelGraph child = modelGraph.getChildren().get(i);
+        DefaultGraphCell curCell = addGroups(child, nested, state);
+        group.add(curCell);
+        Rectangle2D bounds = (Rectangle2D) ((Map<Object, Object>) nested
+            .get(curCell)).get("bounds");
+        if (bounds.getX() < top_x)
+          top_x = bounds.getX();
+        if (bounds.getY() < top_y)
+          top_y = bounds.getY();
+        if (bounds.getMaxX() > bottom_x)
+          bottom_x = bounds.getMaxX();
+        if (bounds.getMaxY() > bottom_y)
+          bottom_y = bounds.getMaxY();
+      }
+
+      map.put(GraphConstants.BOUNDS, new AttributeMap.SerializableRectangle2D(
+          top_x - 5, top_y - 20, bottom_x - top_x + 10, bottom_y - top_y + 25));
+      map.put(GraphConstants.FOREGROUND, Color.black);
+      if (modelGraph.getModel().isRef())
+        map.put(GraphConstants.BACKGROUND, Color.lightGray);
+      else
+        map.put(GraphConstants.BACKGROUND, Color.white);
+      if (modelGraph.isExcused())
+        map.put(GraphConstants.GRADIENTCOLOR, Color.gray);
+      map.put(GraphConstants.HORIZONTAL_ALIGNMENT, SwingConstants.LEFT);
+      map.put(GraphConstants.VERTICAL_ALIGNMENT, SwingConstants.TOP);
+      map.put(GraphConstants.BORDER, new LineBorder(modelGraph.getModel()
+          .getColor(), 1));
+      jgraph.getGraphLayoutCache().toBack(new Object[] { modelCell });
+      nested.put(modelCell, map);
+      return modelCell;
+    }
+    DefaultGraphCell cell = this.m_jgAdapter.getVertexCell(modelGraph
+        .getModel());
+    ((Map<Object, Object>) nested.get(cell)).put(GraphConstants.FOREGROUND,
+        Color.black);
+    if (modelGraph.isExcused())
+      ((Map<Object, Object>) nested.get(cell)).put(
+          GraphConstants.GRADIENTCOLOR, Color.gray);
+    else
+      ((Map<Object, Object>) nested.get(cell)).put(
+          GraphConstants.GRADIENTCOLOR, Color.white);
+    if (!((ModelNode) ((DefaultGraphCell) cell).getUserObject()).isRef())
+      ((Map<Object, Object>) nested.get(cell)).put(GraphConstants.BACKGROUND,
+          modelGraph.getModel().getColor());
+    else
+      ((Map<Object, Object>) nested.get(cell)).put(GraphConstants.BACKGROUND,
+          Color.lightGray);
+    return cell;
+  }
+  
+  private void removeAllEdges(ObservableGraph<ModelNode, IdentifiableEdge> graph){
+    List<IdentifiableEdge> edges = new Vector<IdentifiableEdge>();
+    
+    for(IdentifiableEdge edge: graph.getEdges()){
+       edges.add(edge);
+     }
+    
+    for(IdentifiableEdge edge: edges){
+       graph.removeEdge(edge);
+    }
+  }
+  
+
+  private class Pair {
+    String first, second;
+
+    public Pair(String first, String second) {
+      this.first = first;
+      this.second = second;
+    }
+
+    public String getFirst() {
+      return this.first;
+    }
+
+    public String getSecond() {
+      return this.second;
+    }
+  }
+
+  public class MyGraphListener implements MouseListener, ActionListener {
+
+    private Point curPoint;
+    private ViewState state;
+
+    public MyGraphListener(ViewState state) {
+      this.state = state;
+    }
+
+    public void mouseClicked(MouseEvent e) {
+      curPoint = e.getPoint();
+      if (e.getButton() == MouseEvent.BUTTON3) {
+        Object mouseOverCell = GraphView.this.jgraph.getFirstCellForLocation(
+            e.getX(), e.getY());
+        ModelGraph mouseOverGraph = null;
+        if (mouseOverCell != null) {
+          mouseOverGraph = (GuiUtils.find(state.getGraphs(),
+              ((ModelNode) ((DefaultMutableTreeNode) mouseOverCell)
+                  .getUserObject()).getId()));
+          if (mouseOverGraph != null) {
+            if (GuiUtils.isDummyNode(mouseOverGraph.getModel())) {
+              mouseOverGraph = mouseOverGraph.getParent();
+            } else {
+              while (mouseOverGraph != null
+                  && mouseOverGraph.getParent() != null
+                  && mouseOverGraph.getParent().getModel().isRef())
+                mouseOverGraph = mouseOverGraph.getParent();
+            }
+            if (mouseOverGraph != null)
+              mouseOverCell = GraphView.this.m_jgAdapter
+                  .getVertexCell(mouseOverGraph.getModel());
+            else
+              mouseOverCell = null;
+          }
+          state.setSelected(mouseOverGraph);
+        } else {
+          state.setSelected(null);
+        }
+        PopupMenu actionsMenu = createActionMenu(state);
+        GraphView.this.notifyListeners();
+        GraphView.this.jgraph.add(actionsMenu);
+        actionsMenu.show(GraphView.this.jgraph, e.getPoint().x, e.getPoint().y);
+      } else if (e.getButton() == MouseEvent.BUTTON1) {
+        if (state.getMode() == View.Mode.ZOOM_IN) {
+          state.setProperty(SCALE, Double.toString(Double.parseDouble(state
+              .getFirstPropertyValue(SCALE)) + 0.1));
+          state.setSelected(null);
+          GraphView.this.notifyListeners();
+        } else if (state.getMode() == View.Mode.ZOOM_OUT) {
+          state.setProperty(SCALE, Double.toString(Double.parseDouble(state
+              .getFirstPropertyValue(SCALE)) - 0.1));
+          state.setSelected(null);
+          GraphView.this.notifyListeners();
+        } else if (state.getMode() == View.Mode.EDIT) {
+          Object cell = GraphView.this.jgraph.getFirstCellForLocation(e.getX(),
+              e.getY());
+          if (cell != null) {
+            if (cell instanceof DefaultEdge) {
+            } else if (cell instanceof DefaultGraphCell) {
+              ModelGraph graph = GuiUtils.find(state.getGraphs(),
+                  ((ModelNode) ((DefaultGraphCell) cell).getUserObject())
+                      .getId());
+              if (graph.getModel().isRef())
+                while (graph.getParent() != null
+                    && graph.getParent().getModel().isRef())
+                  graph = graph.getParent();
+              if (GuiUtils.isDummyNode(graph.getModel()))
+                graph = graph.getParent();
+              state.setSelected(graph);
+              GraphView.this.notifyListeners();
+            }
+          } else if (cell == null && state.getSelected() != null) {
+            state.setSelected(null);
+            GraphView.this.notifyListeners();
+          }
+        } else if (state.getMode() == View.Mode.DELETE
+            && e.getClickCount() == 2) {
+          Object cell = GraphView.this.jgraph.getFirstCellForLocation(e.getX(),
+              e.getY());
+          if (cell != null) {
+            if (cell instanceof DefaultEdge) {
+              // do nothing
+            } else if (cell instanceof DefaultGraphCell) {
+              ModelGraph graph = GuiUtils.removeNode(state.getGraphs(),
+                  (ModelNode) ((DefaultGraphCell) cell).getUserObject());
+              GraphView.this.notifyListeners();
+            }
+          }
+        }
+      }
+    }
+
+    public void mouseEntered(MouseEvent e) {
+      if (state.getMode() == View.Mode.ZOOM_IN
+          || state.getMode() == View.Mode.ZOOM_OUT) {
+        Toolkit toolkit = Toolkit.getDefaultToolkit();
+        try {
+          GraphView.this.jgraph.setCursor(toolkit.createCustomCursor(
+              IconLoader.getIcon(IconLoader.ZOOM_CURSOR), new Point(0, 0),
+              "img"));
+        } catch (Exception e1) {
+          e1.printStackTrace();
+        }
+      } else if (state.getMode() == Mode.MOVE) {
+        GraphView.this.jgraph.setCursor(new Cursor(Cursor.HAND_CURSOR));
+      } else {
+        GraphView.this.jgraph.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+      }
+    }
+
+    public void mouseExited(MouseEvent e) {
+    }
+
+    public void mousePressed(MouseEvent e) {
+    }
+
+    public void mouseReleased(MouseEvent e) {
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      this.createNewGraph(e.getActionCommand());
+    }
+
+    private void createNewGraph(String actionCommand) {
+      ModelGraph newGraph = null;
+      if (actionCommand.equals(NEW_TASK_ITEM_NAME)) {
+        newGraph = new ModelGraph(new ModelNode(state.getFile(),
+            GuiUtils.createUniqueName()));
+      } else if (actionCommand.equals(NEW_PARALLEL_ITEM_NAME)) {
+        ModelNode node = new ModelNode(state.getFile(),
+            GuiUtils.createUniqueName());
+        node.setExecutionType("parallel");
+        newGraph = new ModelGraph(node);
+      } else if (actionCommand.equals(NEW_SEQUENTIAL_ITEM_NAME)) {
+        ModelNode node = new ModelNode(state.getFile(),
+            GuiUtils.createUniqueName());
+        node.setExecutionType("sequential");
+        newGraph = new ModelGraph(node);
+      } else {
+        return;
+      }
+      Object cell = GraphView.this.jgraph.getSelectionCell();
+      if (cell != null) {
+        if (cell instanceof DefaultGraphCell) {
+          ModelGraph graph = GuiUtils.find(state.getGraphs(),
+              ((ModelNode) ((DefaultGraphCell) cell).getUserObject()).getId());
+          if (graph != null)
+            graph.addChild(newGraph);
+        }
+      } else {
+        state.addGraph(newGraph);
+        GraphView.this.setShift(state, newGraph, curPoint);
+      }
+      GraphView.this.notifyListeners();
+    }
+
+  }
+
+  public void setShift(ViewState state, ModelGraph modelGraph, Point point) {
+    state.setProperty(modelGraph.getModel().getId() + "/Shift/x",
+        Integer.toString(point.x));
+    state.setProperty(modelGraph.getModel().getId() + "/Shift/y",
+        Integer.toString(point.y));
+  }
+
+  public void removeShift(ViewState state, ModelGraph modelGraph) {
+    state.removeProperty(modelGraph.getModel().getId() + "/Shift");
+  }
+
+  public Point getShift(ViewState state, DefaultGraphCell cell, Map nested) {
+    ModelGraph graph = null;
+    if (cell instanceof DefaultEdge) {
+      IdentifiableEdge edge = (IdentifiableEdge) cell.getUserObject();
+      Pair pair = GraphView.this.edgeMap.get(edge.id);
+      graph = GuiUtils.find(state.getGraphs(), pair.getFirst());
+    } else {
+      graph = GuiUtils.find(state.getGraphs(),
+          ((ModelNode) cell.getUserObject()).getId());
+    }
+    ModelGraph parent = GuiUtils.findRoot(state.getGraphs(), graph);
+    Point shiftPoint = null;
+    if (state.containsProperty(parent.getModel().getId() + "/Shift"))
+      shiftPoint = new Point(Integer.parseInt(state
+          .getFirstPropertyValue(parent.getModel().getId() + "/Shift/x")),
+          Integer.parseInt(state.getFirstPropertyValue(parent.getModel()
+              .getId() + "/Shift/y")));
+    if (shiftPoint == null) {
+      shiftPoint = new Point(100, 100);
+      this.setShift(state, parent, shiftPoint);
+      return shiftPoint;
+    } else {
+      Rectangle2D bounds = (Rectangle2D) ((Map<Object, Object>) nested
+          .get(GraphView.this.m_jgAdapter.getVertexCell(parent.getModel())))
+          .get(GraphConstants.BOUNDS);
+      return new Point(shiftPoint.x - (int) bounds.getX(), shiftPoint.y
+          - (int) bounds.getY());
+    }
+  }
+
+
+  private PopupMenu createActionMenu(final ViewState state) {
+    PopupMenu actionsMenu = new PopupMenu(ACTIONS_POP_MENU_NAME);
+    PopupMenu newSubMenu = new PopupMenu(NEW_SUB_POP_MENU_NAME);
+    MenuItem taskItem = new MenuItem(NEW_TASK_ITEM_NAME);
+    MenuItem condItem = new MenuItem(NEW_CONDITION_ITEM_NAME);
+    newSubMenu.add(taskItem);
+    newSubMenu.add(condItem);
+    newSubMenu.add(new MenuItem(NEW_PARALLEL_ITEM_NAME));
+    newSubMenu.add(new MenuItem(NEW_SEQUENTIAL_ITEM_NAME));
+    newSubMenu.addActionListener(this.myGraphListener);
+    actionsMenu.add(newSubMenu);
+    MenuItem viewReferrencedWorkflow = new MenuItem(VIEW_REF_WORKFLOW);
+    actionsMenu.add(viewReferrencedWorkflow);
+    MenuItem deleteItem = new MenuItem(DELETE_ITEM_NAME);
+    actionsMenu.add(deleteItem);
+    MenuItem formatItem = new MenuItem(FORMAT_ITEM_NAME);
+    actionsMenu.add(formatItem);
+
+    PopupMenu orderSubMenu = new PopupMenu(ORDER_SUB_POP_MENU_NAME);
+
+    ModelGraph modelGraph = state.getSelected();
+    newSubMenu.setEnabled(modelGraph == null
+        || modelGraph.getModel().isParentType());
+    deleteItem.setEnabled(modelGraph != null);
+    formatItem.setEnabled(true);
+    if (modelGraph != null) {
+      viewReferrencedWorkflow.setEnabled(modelGraph.getModel().isRef());
+      taskItem.setEnabled(!modelGraph.isCondition());
+      condItem.setEnabled(modelGraph.isCondition());
+      orderSubMenu.setEnabled(modelGraph.getParent() != null
+          && !(modelGraph.isCondition() && !modelGraph.getParent()
+              .isCondition()));
+    } else {
+      boolean isCondition = false;
+      if (state.getGraphs().size() > 0)
+        isCondition = state.getGraphs().get(0).isCondition();
+      viewReferrencedWorkflow.setEnabled(false);
+      taskItem.setEnabled(!isCondition);
+      condItem.setEnabled(isCondition);
+    }
+
+    actionsMenu.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        if (e.getActionCommand().equals(DELETE_ITEM_NAME)) {
+          GuiUtils.removeNode(state.getGraphs(), state.getSelected().getModel());
+          state.setSelected(null);
+          GraphView.this.notifyListeners();
+        } else if (e.getActionCommand().equals(FORMAT_ITEM_NAME)) {
+          GraphView.this.refreshView(state);
+        } else if (e.getActionCommand().equals(VIEW_REF_WORKFLOW)) {
+          scrollSelectedToVisible = true;
+          GraphView.this.notifyListeners(new ViewChange.VIEW_MODEL(state
+              .getSelected().getModel().getModelId(), GraphView.this));
+        }
+      }
+    });
+    PopupMenu edgesSubMenu = new PopupMenu(EDGES_SUB_POP_MENU_NAME);
+    edgesSubMenu.add(new MenuItem(TASK_LEVEL));
+    edgesSubMenu.add(new MenuItem(WORKFLOW_LEVEL));
+    actionsMenu.add(edgesSubMenu);
+    edgesSubMenu.addActionListener(new ActionListener() {
+
+      public void actionPerformed(ActionEvent e) {
+        if (e.getActionCommand().equals(TASK_LEVEL)) {
+          state.setProperty(EDGE_DISPLAY_MODE, TASK_MODE);
+        } else if (e.getActionCommand().equals(WORKFLOW_LEVEL)) {
+          state.setProperty(EDGE_DISPLAY_MODE, WORKFLOW_MODE);
+        }
+        GraphView.this.refreshView(state);
+      }
+
+    });
+    actionsMenu.add(orderSubMenu);
+    orderSubMenu.add(new MenuItem(TO_FRONT_ITEM_NAME));
+    orderSubMenu.add(new MenuItem(TO_BACK_ITEM_NAME));
+    orderSubMenu.add(new MenuItem(FORWARD_ITEM_NAME));
+    orderSubMenu.add(new MenuItem(BACKWARDS_ITEM_NAME));
+    orderSubMenu.addActionListener(new ActionListener() {
+
+      public void actionPerformed(ActionEvent e) {
+        ModelGraph graph = state.getSelected();
+        ModelGraph parent = graph.getParent();
+        if (e.getActionCommand().equals(TO_FRONT_ITEM_NAME)) {
+          if (parent.getChildren().remove(graph))
+            parent.getChildren().add(0, graph);
+        } else if (e.getActionCommand().equals(TO_BACK_ITEM_NAME)) {
+          if (parent.getChildren().remove(graph))
+            parent.getChildren().add(graph);
+        } else if (e.getActionCommand().equals(FORWARD_ITEM_NAME)) {
+          int index = parent.getChildren().indexOf(graph);
+          if (index != -1) {
+            parent.getChildren().remove(index);
+            parent.getChildren().add(
+                Math.min(parent.getChildren().size(), index + 1), graph);
+          }
+        } else if (e.getActionCommand().equals(BACKWARDS_ITEM_NAME)) {
+          int index = parent.getChildren().indexOf(graph);
+          if (index != -1) {
+            parent.getChildren().remove(index);
+            parent.getChildren().add(Math.max(0, index - 1), graph);
+          }
+        }
+        GraphView.this.notifyListeners();
+      }
+
+    });
+    return actionsMenu;
+  }
+
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/IdentifiableEdge.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/IdentifiableEdge.java
new file mode 100644
index 0000000..c14175b
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/IdentifiableEdge.java
@@ -0,0 +1,92 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective.view.impl;
+
+//JDK imports
+import java.util.UUID;
+
+import org.apache.oodt.cas.workflow.gui.model.ModelNode;
+
+/**
+ * 
+ * An ID'ed edge identified by {@link UUID#randomUUID()}.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class IdentifiableEdge {
+
+  String id;
+  
+  ModelNode from;
+  
+  ModelNode to;
+
+  public IdentifiableEdge(ModelNode from, ModelNode to) {
+    id = UUID.randomUUID().toString();
+    this.from = from;
+    this.to = to;
+  }
+
+  public String toString() {
+    return "";
+  }
+
+  /**
+   * @return the id
+   */
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * @param id the id to set
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * @return the from
+   */
+  public ModelNode getFrom() {
+    return from;
+  }
+
+  /**
+   * @param from the from to set
+   */
+  public void setFrom(ModelNode from) {
+    this.from = from;
+  }
+
+  /**
+   * @return the to
+   */
+  public ModelNode getTo() {
+    return to;
+  }
+
+  /**
+   * @param to the to to set
+   */
+  public void setTo(ModelNode to) {
+    this.to = to;
+  }
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/JungJGraphModelAdapter.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/JungJGraphModelAdapter.java
new file mode 100644
index 0000000..a9179ef
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/JungJGraphModelAdapter.java
@@ -0,0 +1,246 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective.view.impl;
+
+//JDK imports
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.geom.Rectangle2D;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.swing.BorderFactory;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.gui.model.ModelNode;
+
+//JGraph imports
+import org.jgraph.event.GraphModelEvent;
+import org.jgraph.event.GraphModelListener;
+import org.jgraph.graph.AttributeMap;
+import org.jgraph.graph.ConnectionSet;
+import org.jgraph.graph.DefaultEdge;
+import org.jgraph.graph.DefaultGraphCell;
+import org.jgraph.graph.DefaultGraphModel;
+import org.jgraph.graph.DefaultPort;
+import org.jgraph.graph.GraphConstants;
+
+//Jung imports
+import edu.uci.ics.jung.graph.ObservableGraph;
+import edu.uci.ics.jung.graph.event.GraphEvent;
+import edu.uci.ics.jung.graph.event.GraphEventListener;
+
+/**
+ * 
+ * This class integrates OODT, Jung and JGraph.
+ * 
+ * Not necessarily in that order. It acts as a facade, wrapping a Jung graph
+ * (and its modifications) and then using that to update the current state of
+ * the associated JGraph model.
+ * 
+ * @author mattmann
+ * 
+ */
+public class JungJGraphModelAdapter extends DefaultGraphModel {
+
+  private static final long serialVersionUID = 205647349848965651L;
+
+  private ObservableGraph<ModelNode, IdentifiableEdge> jungGraph;
+
+  private Map<String, DefaultGraphCell> cellMap;
+
+  private static final Logger LOG = Logger
+      .getLogger(JungJGraphModelAdapter.class.getName());
+
+  public JungJGraphModelAdapter(
+      final ObservableGraph<ModelNode, IdentifiableEdge> jungGraph) {
+    this.jungGraph = jungGraph;
+    this.jungGraph.addGraphEventListener(new WorkflowChangeListener(this));
+    this.cellMap = new HashMap<String, DefaultGraphCell>();
+    this.addGraphModelListener(new GraphModelListener() {
+
+      @Override
+      public void graphChanged(GraphModelEvent e) {
+        Object[] added = e.getChange().getInserted();
+        Object[] removed = e.getChange().getRemoved();
+        Object[] changed = e.getChange().getChanged();
+
+        if (added != null && added.length > 0) {
+          for (Object a : added) {
+            LOG.log(Level.FINE, "Jgraph notification of object added: ["
+                + a.getClass().getName() + "]");
+
+            if (a instanceof org.jgraph.graph.DefaultEdge) {
+              LOG.log(Level.FINE, "Edge added to jgraph");
+              org.jgraph.graph.DefaultEdge edge = (org.jgraph.graph.DefaultEdge) a;
+              if (!jungGraph.getEdges().contains(edge.getUserObject())) {
+                jungGraph.addEdge(
+                    new IdentifiableEdge((ModelNode) edge.getSource(),
+                        (ModelNode) edge.getTarget()), (ModelNode) edge
+                        .getSource(), (ModelNode) edge.getTarget());
+              }
+            } else if (a instanceof org.jgraph.graph.DefaultGraphCell) {
+              LOG.log(Level.FINE, "Vertex added to jgraph");
+              org.jgraph.graph.DefaultGraphCell cell = (org.jgraph.graph.DefaultGraphCell) a;
+
+              if (!jungGraph.getVertices().contains(cell.getUserObject())) {
+                jungGraph.addVertex((ModelNode) cell.getUserObject());
+              }
+            }
+          }
+        }
+
+        if (removed != null && removed.length > 0) {
+          for (Object r : removed) {
+            LOG.log(Level.FINE, "Jgraph notification of object removed: ["
+                + r.getClass().getName() + "]");
+
+            if (r instanceof org.jgraph.graph.DefaultEdge) {
+              LOG.log(Level.FINE, "Edge removed from jgraph");
+              org.jgraph.graph.DefaultEdge edge = (org.jgraph.graph.DefaultEdge) r;
+              if (jungGraph.getEdges().contains(edge.getUserObject())) {
+                jungGraph.removeEdge((IdentifiableEdge) edge.getUserObject());
+              }
+            } else if (r instanceof org.jgraph.graph.DefaultGraphCell) {
+              LOG.log(Level.FINE, "Vertex removed from jgraph");
+              org.jgraph.graph.DefaultGraphCell cell = (org.jgraph.graph.DefaultGraphCell) r;
+
+              if (jungGraph.getVertices().contains(cell.getUserObject())) {
+                jungGraph.removeVertex((ModelNode) cell.getUserObject());
+              }
+            }
+          }
+        }
+
+      }
+    });
+
+  }
+
+  public DefaultGraphCell getVertexCell(ModelNode node) {
+    if (cellMap.get(node.getId()) != null) {
+      return cellMap.get(node.getId());
+    }
+
+    DefaultGraphCell cell = new DefaultGraphCell(node);
+    cell.add(new DefaultPort());
+    return cell;
+  }
+
+  private AttributeMap getEdgeAttributes(DefaultEdge edge) {
+    AttributeMap eMap = new AttributeMap();
+    GraphConstants.setLineEnd(eMap, GraphConstants.ARROW_TECHNICAL);
+    GraphConstants.setEndFill(eMap, true);
+    GraphConstants.setEndSize(eMap, 10);
+    GraphConstants.setForeground(eMap, Color.decode("#25507C"));
+    GraphConstants.setFont(eMap,
+        GraphConstants.DEFAULTFONT.deriveFont(Font.BOLD, 12));
+    GraphConstants.setLineColor(eMap, Color.decode("#7AA1E6"));
+    AttributeMap map = new AttributeMap();
+    map.put(edge, eMap);
+    return map;
+  }
+
+  private AttributeMap getVertexAttributes(DefaultGraphCell cell) {
+    AttributeMap vMap = new AttributeMap();
+
+    Color c = Color.decode("#FF9900");
+    GraphConstants.setBounds(vMap, new Rectangle2D.Double(50, 50, 90, 30));
+    GraphConstants.setBorder(vMap, BorderFactory.createRaisedBevelBorder());
+    GraphConstants.setBackground(vMap, c);
+    GraphConstants.setForeground(vMap, Color.white);
+    GraphConstants.setFont(vMap,
+        GraphConstants.DEFAULTFONT.deriveFont(Font.BOLD, 12));
+    GraphConstants.setOpaque(vMap, true);
+
+    AttributeMap map = new AttributeMap();
+    map.put(cell, vMap);
+    return map;
+  }
+
+  private class WorkflowChangeListener implements
+      GraphEventListener<ModelNode, IdentifiableEdge> {
+
+    private JungJGraphModelAdapter adapter;
+
+    public WorkflowChangeListener(JungJGraphModelAdapter adapter) {
+      this.adapter = adapter;
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * edu.uci.ics.jung.graph.event.GraphEventListener#handleGraphEvent(edu.
+     * uci.ics.jung.graph.event.GraphEvent)
+     */
+    @Override
+    public void handleGraphEvent(GraphEvent<ModelNode, IdentifiableEdge> e) {
+      if (e.getType().equals(GraphEvent.Type.EDGE_ADDED)) {
+        LOG.log(Level.FINE, "EDGE ADDED!");
+        GraphEvent.Edge<ModelNode, IdentifiableEdge> event = (GraphEvent.Edge<ModelNode, IdentifiableEdge>) e;
+        addJGraphEdge(event.getEdge());
+      } else if (e.getType().equals(GraphEvent.Type.EDGE_REMOVED)) {
+        LOG.log(Level.FINE, "EDGE REMOVED!");
+      } else if (e.getType().equals(GraphEvent.Type.VERTEX_ADDED)) {
+        LOG.log(Level.FINE, "VERTEX ADDED!");
+        GraphEvent.Vertex<ModelNode, IdentifiableEdge> event = (GraphEvent.Vertex<ModelNode, IdentifiableEdge>) e;
+        addJGraphVertex(event.getVertex());
+      } else if (e.getType().equals(GraphEvent.Type.VERTEX_REMOVED)) {
+        LOG.log(Level.FINE, "VERTEX REMOVED!");
+      }
+
+    }
+
+  }
+
+  private void addJGraphVertex(ModelNode node) {
+    DefaultGraphCell cell = new DefaultGraphCell(node);
+    cell.add(new DefaultPort());
+    insert(new Object[] { cell }, getVertexAttributes(cell), null, null, null);
+    cellMap.put(node.getId(), cell);
+  }
+
+  private void addJGraphEdge(IdentifiableEdge e) {
+    ConnectionSet set = new ConnectionSet();
+    DefaultEdge theEdge = new DefaultEdge(e);
+    DefaultGraphCell from = null;
+    DefaultGraphCell to = null;
+    String fromVertexId = e.getFrom().getId();
+    String toVertexId = e.getTo().getId();
+    if (!cellMap.containsKey(fromVertexId)) {
+      addJGraphVertex(e.getFrom());
+    }
+    from = cellMap.get(fromVertexId);
+
+    if (!cellMap.containsKey(toVertexId)) {
+      addJGraphVertex(e.getTo());
+    }
+
+    to = cellMap.get(toVertexId);
+
+    set.connect(theEdge, (DefaultPort) from.getChildAt(0),
+        (DefaultPort) to.getChildAt(0));
+    insert(new Object[] { theEdge }, getEdgeAttributes(theEdge), set, null,
+        null);
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/TreeProjectView.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/TreeProjectView.java
new file mode 100644
index 0000000..e5a28cf
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/perspective/view/impl/TreeProjectView.java
@@ -0,0 +1,151 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.perspective.view.impl;
+
+//JDK imports
+import java.awt.BorderLayout;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.util.List;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.border.EtchedBorder;
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreePath;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.gui.perspective.view.MultiStateView;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewChange;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewState;
+
+/**
+ * 
+ * 
+ * Shows the files/workflows associated with a project in the Workflow Editor
+ * GUI.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class TreeProjectView extends MultiStateView {
+
+  private static final long serialVersionUID = 1867428699533484861L;
+
+  private JTree tree;
+
+  private ViewState selectedState;
+
+  public TreeProjectView(String name) {
+    super(name);
+    this.setLayout(new BorderLayout());
+  }
+
+  @Override
+  public void refreshView(final ViewState activeState,
+      final List<ViewState> states) {
+    this.removeAll();
+    this.selectedState = activeState;
+    DefaultMutableTreeNode selected = null;
+    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Projects");
+    for (ViewState state : states)
+      if (selectedState != null
+          && state.getFile().equals(selectedState.getFile()))
+        root.add(selected = new DefaultMutableTreeNode(state.getFile()
+            .getName()));
+      else
+        root.add(new DefaultMutableTreeNode(state.getFile().getName()));
+
+    tree = new JTree(root);
+    tree.setEditable(true);
+    tree.getModel().addTreeModelListener(new TreeModelListener() {
+
+      public void treeNodesChanged(TreeModelEvent e) {
+        //TODO: something with the view nodes here
+      }
+
+      public void treeNodesInserted(TreeModelEvent e) {
+      }
+
+      public void treeNodesRemoved(TreeModelEvent e) {
+      }
+
+      public void treeStructureChanged(TreeModelEvent e) {
+      }
+
+    });
+    tree.addMouseListener(new MouseListener() {
+
+      public void mouseClicked(MouseEvent e) {
+        if (e.getButton() == MouseEvent.BUTTON1) {
+          if (tree.getSelectionPath() != null) {
+            DefaultMutableTreeNode selectedComp = (DefaultMutableTreeNode) tree
+                .getSelectionPath().getLastPathComponent();
+            String stateName = (String) ((DefaultMutableTreeNode) selectedComp)
+                .getUserObject();
+            for (ViewState state : states) {
+              if (state.getFile().getName().equals(stateName)) {
+                selectedState = state;
+                if (e.getClickCount() == 2)
+                  TreeProjectView.this
+                      .notifyListeners(new ViewChange.NEW_ACTIVE_STATE(
+                          selectedState, TreeProjectView.this));
+                break;
+              }
+            }
+          }
+        }
+      }
+
+      public void mouseEntered(MouseEvent e) {
+      }
+
+      public void mouseExited(MouseEvent e) {
+      }
+
+      public void mousePressed(MouseEvent e) {
+      }
+
+      public void mouseReleased(MouseEvent e) {
+      }
+
+    });
+    if (selected != null)
+      tree.setSelectionPath(new TreePath(new DefaultMutableTreeNode[] { root,
+          selected }));
+    else if (states.size() > 0)
+      tree.setSelectionPath(new TreePath(new DefaultMutableTreeNode[] { root,
+          (DefaultMutableTreeNode) root.getChildAt(0) }));
+
+    tree.setRootVisible(false);
+    this.setBorder(new EtchedBorder());
+    JLabel panelName = new JLabel("Workspace Explorer");
+    panelName.setBorder(new EtchedBorder());
+    this.add(panelName, BorderLayout.NORTH);
+    JScrollPane scrollPane = new JScrollPane(tree,
+        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+        JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+    this.add(scrollPane, BorderLayout.CENTER);
+
+    this.revalidate();
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/toolbox/Tool.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/toolbox/Tool.java
new file mode 100644
index 0000000..c73a2d7
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/toolbox/Tool.java
@@ -0,0 +1,124 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.toolbox;
+
+//JDK imports
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Image;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+/**
+ * 
+ * 
+ * One of the tool buttons at the top of the Workflow Editor GUI.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public abstract class Tool extends JPanel {
+
+  private static final long serialVersionUID = -373351385009724404L;
+
+  private Image image, selectedImage;
+  private boolean selected = false;
+  private ToolBox toolBox;
+
+  public Tool() {
+    this("?");
+  }
+
+  public Tool(String text) {
+    super();
+    this.setLayout(new BorderLayout());
+    this.add(new JLabel(text), BorderLayout.CENTER);
+    this.setup();
+  }
+
+  public Tool(Image image, Image selectedImage) {
+    super();
+    this.setLayout(new BorderLayout());
+    this.add(new JLabel(new ImageIcon(image)), BorderLayout.CENTER);
+    this.image = image;
+    this.selectedImage = selectedImage;
+    this.setup();
+  }
+
+  public void setToolBox(ToolBox toolBox) {
+    this.toolBox = toolBox;
+  }
+
+  public boolean isSelected() {
+    return this.selected;
+  }
+
+  public void setSelected(boolean selected) {
+    if (image != null) {
+      Tool.this.removeAll();
+      if (this.selected = selected)
+        Tool.this.add(new JLabel(new ImageIcon(selectedImage)),
+            BorderLayout.CENTER);
+      else
+        Tool.this.add(new JLabel(new ImageIcon(image)), BorderLayout.CENTER);
+      Tool.this.revalidate();
+    }
+  }
+
+  private void setup() {
+    this.setPreferredSize(new Dimension(30, 30));
+    this.addMouseListener(new MouseListener() {
+
+      public void mouseClicked(MouseEvent e) {
+        Tool.this.onClick();
+        Tool.this.toolBox.setSelected(Tool.this);
+      }
+
+      public void mouseEntered(MouseEvent e) {
+        if (!selected && selectedImage != null) {
+          Tool.this.removeAll();
+          Tool.this.add(new JLabel(new ImageIcon(selectedImage)),
+              BorderLayout.CENTER);
+          Tool.this.revalidate();
+        }
+      }
+
+      public void mouseExited(MouseEvent e) {
+        if (!selected && image != null) {
+          Tool.this.removeAll();
+          Tool.this.add(new JLabel(new ImageIcon(image)), BorderLayout.CENTER);
+          Tool.this.revalidate();
+        }
+      }
+
+      public void mousePressed(MouseEvent e) {
+      }
+
+      public void mouseReleased(MouseEvent e) {
+      }
+
+    });
+  }
+
+  public abstract void onClick();
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/toolbox/ToolBox.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/toolbox/ToolBox.java
new file mode 100644
index 0000000..6fac807
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/toolbox/ToolBox.java
@@ -0,0 +1,74 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.toolbox;
+
+//JDK imports
+import java.awt.FlowLayout;
+import java.util.List;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.EtchedBorder;
+
+/**
+ * 
+ * 
+ * The box button and its panel that wrap the {@link Tool}.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class ToolBox extends JPanel {
+
+  private static final long serialVersionUID = -2671454524968238519L;
+
+  private JPanel titlePanel;
+  private JPanel boxPanel;
+  private List<Tool> tools;
+  private Tool selectedTool;
+
+  public ToolBox(List<Tool> tools) {
+    super();
+    this.tools = tools;
+    this.titlePanel = new JPanel();
+    this.titlePanel.setBorder(new EtchedBorder());
+    this.titlePanel.add(new JLabel("Toolbox"));
+
+    this.boxPanel = new JPanel();
+    this.boxPanel.setBorder(new EtchedBorder());
+    this.boxPanel.setLayout(new FlowLayout(FlowLayout.LEADING));
+    for (Tool tool : tools) {
+      tool.setToolBox(this);
+      this.boxPanel.add(tool);
+    }
+    this.add(this.boxPanel);
+  }
+
+  public void setSelected(Tool selectedTool) {
+    this.selectedTool = selectedTool;
+    this.selectedTool.setSelected(true);
+    for (Tool tool : tools)
+      if (!this.selectedTool.equals(tool))
+        tool.setSelected(false);
+  }
+
+  public Tool getSelected() {
+    return this.selectedTool;
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/util/GuiUtils.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/util/GuiUtils.java
new file mode 100644
index 0000000..44e4f85
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/util/GuiUtils.java
@@ -0,0 +1,343 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.util;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.gui.model.ModelGraph;
+import org.apache.oodt.cas.workflow.gui.model.ModelNode;
+import org.apache.oodt.cas.workflow.gui.perspective.view.ViewState;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+import java.util.Stack;
+import java.util.Vector;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * 
+ * 
+ * Generic utility functions helpful for the Workflow Editor GUI.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class GuiUtils {
+
+  protected static AtomicInteger untitledIter = new AtomicInteger(0);
+  protected static AtomicInteger dummyUntitledIter = new AtomicInteger(0);
+
+  public static boolean isSubGraph(ModelGraph graph, ModelGraph subGraph) {
+    if (graph.equals(subGraph))
+      return true;
+    for (ModelGraph child : graph.getChildren())
+      if (isSubGraph(child, subGraph))
+        return true;
+    if (graph.getPreConditions() != null)
+      if (isSubGraph(graph.getPreConditions(), subGraph))
+        return true;
+    if (graph.getPostConditions() != null)
+      if (isSubGraph(graph.getPostConditions(), subGraph))
+        return true;
+    return false;
+  }
+
+  public static void updateGraphModelId(ViewState state, String id,
+      String newModelId) {
+    ModelGraph graph = find(state.getGraphs(), id);
+    if (graph.getParent() != null
+        && graph.getParent().getModel().getExcusedSubProcessorIds()
+            .contains(graph.getModel().getModelId())) {
+      graph.getParent().getModel().getExcusedSubProcessorIds()
+          .remove(graph.getModel().getModelId());
+      graph.getParent().getModel().getExcusedSubProcessorIds().add(newModelId);
+    }
+    graph.getModel().setModelId(newModelId);
+  }
+
+  public static void addChild(List<ModelGraph> graphs, String parentId,
+      ModelGraph child) {
+    ModelGraph parent = find(graphs, parentId);
+    if (parent != null)
+      parent.addChild(child);
+  }
+
+  public static List<ModelGraph> findRootGraphs(List<ModelGraph> graphs) {
+    List<ModelGraph> rootGraphs = new Vector<ModelGraph>();
+    for (ModelGraph graph : graphs) {
+      if (rootGraphs.size() == 0) {
+        rootGraphs.add(graph);
+      } else {
+        if (find(rootGraphs, graph.getModel().getModelId()) == null) {
+          rootGraphs.add(graph);
+        }
+      }
+    }
+    for (int i = 0; i < rootGraphs.size(); i++) {
+      ModelGraph rootGraph = rootGraphs.get(i);
+      for (int j = 0; j < rootGraphs.size(); j++) {
+        if (i != j
+            && rootGraphs.get(j).recursiveFind(
+                rootGraph.getModel().getModelId()) != null) {
+          rootGraphs.remove(i--);
+          break;
+        }
+      }
+
+    }
+    return rootGraphs;
+  }
+
+  public static ModelGraph findRoot(List<ModelGraph> rootGraphs,
+      ModelGraph graph) {
+    for (ModelGraph rootGraph : rootGraphs) {
+      if (graph.equals(rootGraph)) {
+        return rootGraph;
+      } else if (graph.getParent() != null) {
+        ModelGraph root = findRoot(rootGraphs, graph.getParent());
+        if (root != null)
+          return root;
+      }
+    }
+    return null;
+  }
+
+  public static List<ModelGraph> find(List<ModelGraph> graphs, Set<String> ids) {
+    Vector<ModelGraph> foundGraphs = new Vector<ModelGraph>();
+    for (String id : ids) {
+      ModelGraph graph = find(graphs, id);
+      if (graph != null)
+        foundGraphs.add(graph);
+    }
+    return foundGraphs;
+  }
+
+  public static ModelGraph find(List<ModelGraph> graphs, String id) {
+    for (ModelGraph graph : graphs) {
+      ModelGraph found = graph.recursiveFind(id);
+      if (found != null)
+        return found;
+    }
+    return null;
+  }
+
+  public static ModelGraph removeNode(List<ModelGraph> graphs, ModelNode node) {
+    for (int i = 0; i < graphs.size(); i++) {
+      if (graphs.get(i).getModel().equals(node)) {
+        return graphs.remove(i);
+      } else {
+        ModelGraph graph = removeNode(graphs.get(i), node);
+        if (graph != null)
+          return graph;
+      }
+    }
+    return null;
+  }
+
+  public static ModelGraph removeNode(ModelGraph graph, ModelNode node) {
+    Stack<ModelGraph> stack = new Stack<ModelGraph>();
+    stack.add(graph);
+    while (!stack.empty()) {
+      ModelGraph curGraph = stack.pop();
+      if (curGraph.getModel().equals(node)) {
+        curGraph.setParent(null);
+        return curGraph;
+      } else {
+        stack.addAll(curGraph.getChildren());
+        if (curGraph.getPreConditions() != null)
+          stack.add(curGraph.getPreConditions());
+        if (curGraph.getPostConditions() != null)
+          stack.add(curGraph.getPostConditions());
+      }
+    }
+    return null;
+  }
+
+  public static List<Line> findSequentialLines(List<ModelGraph> graphs) {
+    Vector<Line> lines = new Vector<Line>();
+    for (ModelGraph graph : graphs)
+      lines.addAll(findSequentialLines(graph));
+    return lines;
+  }
+
+  public static List<Line> findSequentialLines(final ModelGraph graph) {
+    Vector<Line> lines = new Vector<Line>();
+    if (graph.getChildren().size() > 0) {
+      Stack<ModelGraph> stack = new Stack<ModelGraph>();
+      stack.add(graph);
+      while (!stack.empty()) {
+        ModelGraph curGraph = stack.pop();
+        if (curGraph.getModel().getExecutionType().equals("sequential")) {
+          for (int i = 0; i < curGraph.getChildren().size() - 1; i++)
+            lines.add(new Line(curGraph.getChildren().get(i).getModel(),
+                curGraph.getChildren().get(i + 1).getModel()));
+        }
+        stack.addAll(curGraph.getChildren());
+      }
+    }
+    return lines;
+  }
+
+  public static List<Line> findLines(final List<ModelGraph> graphs) {
+    Vector<Line> lines = new Vector<Line>();
+    for (ModelGraph graph : graphs)
+      lines.addAll(findLines(graph));
+    return lines;
+  }
+
+  public static List<Line> findLines(final ModelGraph graph) {
+    Vector<Line> lines = new Vector<Line>();
+    if (graph.getChildren().size() > 0) {
+      Stack<ModelGraph> graphs = new Stack<ModelGraph>();
+      graphs.add(graph);
+      while (!graphs.empty()) {
+        ModelGraph curGraph = graphs.pop();
+        if (curGraph.getModel().isParentType()) {
+
+          if (curGraph.getChildren().size() == 0)
+            curGraph.addChild(new ModelGraph(createDummyNode()));
+
+          List<Line> relaventLines = getRelaventLines(lines, curGraph
+              .getModel().getId());
+          for (Line relaventLine : relaventLines) {
+            int index = lines.indexOf(relaventLine);
+            if (curGraph.getModel().getExecutionType().toLowerCase()
+                .equals("sequential")) {
+              lines.remove(index);
+              if (curGraph.getChildren().size() > 0) {
+                if (relaventLine.getFromModel().equals(curGraph.getModel()))
+                  lines.add(new Line(curGraph.getChildren()
+                      .get(curGraph.getChildren().size() - 1).getModel(),
+                      relaventLine.getToModel()));
+                else
+                  lines.add(new Line(relaventLine.getFromModel(), curGraph
+                      .getChildren().get(0).getModel()));
+              }
+            } else if (curGraph.getModel().getExecutionType().toLowerCase()
+                .equals("parallel")) {
+              lines.remove(index);
+              if (relaventLine.getFromModel().equals(curGraph.getModel()))
+                for (ModelGraph child : curGraph.getChildren())
+                  lines.add(new Line(child.getModel(), relaventLine
+                      .getToModel()));
+              else
+                for (ModelGraph child : curGraph.getChildren())
+                  lines.add(new Line(relaventLine.getFromModel(), child
+                      .getModel()));
+            }
+          }
+
+          if (curGraph.getModel().getExecutionType().toLowerCase()
+              .equals("sequential")) {
+            for (int i = 0; i < curGraph.getChildren().size(); i++) {
+              if (i == curGraph.getChildren().size() - 1)
+                lines.add(new Line(curGraph.getChildren().get(i).getModel(),
+                    null));
+              else
+                lines.add(new Line(curGraph.getChildren().get(i).getModel(),
+                    curGraph.getChildren().get(i + 1).getModel()));
+            }
+          } else if (curGraph.getModel().getExecutionType().toLowerCase()
+              .equals("parallel")) {
+            for (int i = 0; i < curGraph.getChildren().size(); i++)
+              lines
+                  .add(new Line(curGraph.getChildren().get(i).getModel(), null));
+          }
+          graphs.addAll(curGraph.getChildren());
+        }
+      }
+    } else {
+      lines.add(new Line(graph.getModel(), null));
+    }
+    return lines;
+  }
+
+  public static boolean isDummyNode(ModelNode node) {
+    return node.getModelId().startsWith("DUMMY-");
+  }
+
+  public static ModelNode createDummyNode() {
+    ModelNode dummy = new ModelNode(null, "DUMMY-"
+        + dummyUntitledIter.getAndIncrement());
+    dummy.setTextVisible(false);
+    return dummy;
+  }
+
+  public static List<ModelGraph> getGraphsInFile(File file,
+      List<ModelGraph> graphs) {
+    List<ModelGraph> graphsInFile = new Vector<ModelGraph>();
+    for (ModelGraph graph : graphs) {
+      if (graph.getModel().getFile().equals(file)) {
+        graphsInFile.add(graph);
+      } else {
+        graphsInFile.addAll(getGraphsInFile(file, graph.getChildren()));
+      }
+    }
+    return graphsInFile;
+  }
+
+  public static String createUniqueName() {
+    return "Untitled-" + untitledIter.getAndIncrement();
+  }
+
+  public static Line getLine(List<Line> lines, ModelNode fromModel,
+      ModelNode toModel) {
+    for (Line line : lines)
+      if (line.getFromModel().equals(fromModel)
+          && line.getToModel().equals(toModel))
+        return line;
+    return null;
+  }
+
+  public static List<Line> getRelaventLines(List<Line> lines, String id) {
+    List<Line> relaventLines = new Vector<Line>();
+    for (Line line : lines)
+      if ((line.getFromModel() != null && line.getFromModel().getId()
+          .equals(id))
+          || (line.getToModel() != null && line.getToModel().getId().equals(id)))
+        relaventLines.add(line);
+    return relaventLines;
+  }
+
+  public static List<Line> getChildrenLines(List<Line> lines, String id) {
+    List<Line> relaventLines = new Vector<Line>();
+    for (Line line : lines)
+      if (line.getFromModel().getId().equals(id))
+        relaventLines.add(line);
+    return relaventLines;
+  }
+
+  public static List<Line> getParentLines(List<Line> lines, String id) {
+    List<Line> relaventLines = new Vector<Line>();
+    for (Line line : lines)
+      if (line.getToModel().getId().equals(id))
+        relaventLines.add(line);
+    return relaventLines;
+  }
+
+  public static List<Line> getStartingLines(List<Line> lines) {
+    Vector<Line> startingLines = new Vector<Line>();
+    for (Line line : lines)
+      if (getParentLines(lines, line.getFromModel().getId()).size() == 0)
+        startingLines.add(line);
+    return startingLines;
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/util/IconLoader.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/util/IconLoader.java
new file mode 100644
index 0000000..f5dfd0b
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/util/IconLoader.java
@@ -0,0 +1,83 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.util;
+
+//JDK imports
+import java.awt.Image;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+
+/**
+ * 
+ * 
+ * Loads the appropriate classpath-level icon image for Tools, etc., that are
+ * part of the Workflow Editor GUI.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class IconLoader {
+
+  public static final int CREATE = 0;
+  public static final int CREATE_SELECTED = 1;
+  public static final int DELETE = 2;
+  public static final int DELETE_SELECTED = 3;
+  public static final int EDIT = 4;
+  public static final int EDIT_SELECTED = 5;
+  public static final int MOVE = 6;
+  public static final int MOVE_SELECTED = 7;
+  public static final int ZOOM_IN = 8;
+  public static final int ZOOM_IN_SELECTED = 9;
+  public static final int ZOOM_OUT = 10;
+  public static final int ZOOM_OUT_SELECTED = 11;
+  public static final int ZOOM_CURSOR = 12;
+
+  private IconLoader() {
+  }
+
+  public static Image getIcon(int icon) throws IOException {
+    switch (icon) {
+    case DELETE:
+      return ImageIO.read(IconLoader.class.getResource("delete.jpg"));
+    case DELETE_SELECTED:
+      return ImageIO.read(IconLoader.class.getResource("delete-sel.jpg"));
+    case EDIT:
+      return ImageIO.read(IconLoader.class.getResource("edit.jpg"));
+    case EDIT_SELECTED:
+      return ImageIO.read(IconLoader.class.getResource("edit-sel.jpg"));
+    case MOVE:
+      return ImageIO.read(IconLoader.class.getResource("move.jpg"));
+    case MOVE_SELECTED:
+      return ImageIO.read(IconLoader.class.getResource("move-sel.jpg"));
+    case ZOOM_IN:
+      return ImageIO.read(IconLoader.class.getResource("zoom-in.jpg"));
+    case ZOOM_IN_SELECTED:
+      return ImageIO.read(IconLoader.class.getResource("zoom-in-sel.jpg"));
+    case ZOOM_OUT:
+      return ImageIO.read(IconLoader.class.getResource("zoom-out.jpg"));
+    case ZOOM_OUT_SELECTED:
+      return ImageIO.read(IconLoader.class.getResource("zoom-out-sel.jpg"));
+    case ZOOM_CURSOR:
+      return ImageIO.read(IconLoader.class.getResource("cursor-zoom.png"));
+    default:
+      return null;
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/util/Line.java b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/util/Line.java
new file mode 100644
index 0000000..5f4c80a
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/java/org/apache/oodt/cas/workflow/gui/util/Line.java
@@ -0,0 +1,72 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.gui.util;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.gui.model.ModelNode;
+
+/**
+ * 
+ * 
+ * Wrapper class for representing a line between two {@link ModelNode}s.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ */
+public class Line {
+
+  private ModelNode fromModel;
+  private ModelNode toModel;
+
+  public Line(ModelNode fromModel, ModelNode toModel) {
+    this.fromModel = fromModel;
+    this.toModel = toModel;
+  }
+
+  public ModelNode getFromModel() {
+    return fromModel;
+  }
+
+  public ModelNode getToModel() {
+    return toModel;
+  }
+
+  public boolean equals(Object obj) {
+    if (obj instanceof Line) {
+      if (this.fromModel == null && this.toModel == null)
+        return ((Line) obj).fromModel == null && ((Line) obj).toModel == null;
+      else if (this.fromModel == null)
+        return ((Line) obj).fromModel == null
+            && ((Line) obj).toModel.equals(this.toModel);
+      else if (this.toModel == null)
+        return ((Line) obj).fromModel.equals(this.fromModel)
+            && ((Line) obj).toModel == null;
+      else
+        return ((Line) obj).fromModel.equals(this.fromModel)
+            && ((Line) obj).toModel.equals(this.toModel);
+    } else {
+      return false;
+    }
+  }
+
+  public String toString() {
+    return this.fromModel.getModelId() + " -> " + this.toModel.getModelId();
+  }
+
+}
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/REMOVE.log b/0.8.1-rc1/app/weditor/src/main/resources/REMOVE.log
new file mode 100755
index 0000000..dadf8b1
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/REMOVE.log
@@ -0,0 +1,18 @@
+# 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.
+
+This file only exists to ensure that Maven creates 
+this output directory.You may safely remove this 
+file.
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/examples/GranuleMaps.xml b/0.8.1-rc1/app/weditor/src/main/resources/examples/GranuleMaps.xml
new file mode 100644
index 0000000..b7ce68d
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/examples/GranuleMaps.xml
@@ -0,0 +1,238 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<cas:workflows 
+	xmlns="http://oodt.jpl.nasa.gov/2.0/cas"
+	xmlns:cas="http://oodt.jpl.nasa.gov/2.0/cas"
+	xmlns:p="http://oodt.jpl.nasa.gov/2.0/cas/property">
+	
+	<sequential id="urn:npp:GranuleMaps" name="GranuleMaps">
+		<configuration>
+			
+			<!-- PCS properties -->
+			<property name="PGETask/Query/FileManagerUrl" value="[FILEMGR_URL]" envReplace="true"/>
+			<property name="PGETask/Ingest/FileManagerUrl" value="[FILEMGR_URL]" envReplace="true"/>
+			<property name="PGETask/Ingest/ClientTransferServiceFactory" value="gov.nasa.jpl.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory"/>
+			<property name="PGETask/Ingest/MetFileExtension" value="cas"/>
+			<property name="PGETask/Ingest/CrawlerCrawlForDirs" value="false"/>
+			<property name="PGETask/Ingest/CrawlerRecur" value="false"/>
+			<property name="PGETask/Ingest/ActionsIds" value="RmDataFile"/>
+			<property name="PGETask/Ingest/ActionRepoFile" value="file:[PCS_HOME]/core/pge/policy/action-beans.xml" envReplace="true"/>
+			
+			<!-- Timeout properties -->
+			<property name="PGETask/Condition/Timeout" value="30000"/>
+
+			<!-- query properties -->
+			<property name="PGETask/Condition/StartDateTimeKey" value="StartDateTime"/>
+			<property name="PGETask/Condition/EndDateTimeKey" value="EndDateTime"/>
+			<property name="PGETask/Condition/SortByKey" value="StartDateTime"/>
+			<property name="PGETask/Condition/VersioningKey" value="ProductionDateTime"/>
+			<property name="PGETask/Condition/FilterAlgorClass" value="gov.nasa.jpl.oodt.cas.filemgr.structs.query.filter.WeightedHashFilterAlgor"/>
+			<property name="PGETask/Condition/MinNumOfFiles" value="1"/>
+			<property name="PGETask/Condition/MaxGapSize" value="-1"/>
+			<property name="PGETask/Condition/EpsilonInMillis" value="0"/>
+			
+			<!-- Wait time between block and unblock in minutes -->
+			<property name="BlockTimeElapse" value="1"/>
+
+		</configuration>
+
+		<conditions execution="parallel" type="pre">
+			<condition id-ref="urn:npp:MOA_IASI_L1C_Daily"/>			
+			<condition id-ref="urn:npp:MOA_MHS_L1B_Daily"/>			
+			<condition id-ref="urn:npp:MOA_AMSUA_L1B_Daily"/>			
+		</conditions>
+		
+		<parallel>
+			<task id-ref="urn:npp:Orbits"/>
+			<task id-ref="urn:npp:MoaIasiGPolygon"/>
+			<task id-ref="urn:npp:MoaMhsGPolygon"/>
+			<task id-ref="urn:npp:MoaAmsuaGPolygon"/>
+		</parallel>
+		
+		<parallel>		
+			<conditions execution="sequential" type="pre">
+				<condition id-ref="urn:npp:MOA_ORBITS_FileBased"/>
+			</conditions>
+			
+			<task id-ref="urn:npp:MoaIasiMap"/>
+			<task id-ref="urn:npp:MoaMhsMap"/>
+			<task id-ref="urn:npp:MoaAmsuaMap"/>
+			
+			<!--conditions execution="sequential" type="post">  
+				<condition id-ref="urn:npp:VerifyMapsExist" name="VerifyMapsExist"/>				
+			</conditions-->
+
+		</parallel>
+		
+		<workflow id-ref="MSPI_L1_Workflow"/>
+		
+	</sequential>
+
+
+	<!-- CONDITIONS -->
+	<condition id="urn:npp:MOA_IASI_L1C_Daily" name="MOA_IASI_L1C_Daily" class="gov.nasa.jpl.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+		<configuration>
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_IASI_L1C"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="480"/>
+			<property name="PGETask/Condition/EpsilonInMillis" value="30000"/>
+			<property name="PGETask/Condition/SqlQueryKey" value="Runtime/Condition/IASI_L1_Query"/> 
+			<property name="PGETask/Condition/ResultKeyFormats" value="{Runtime/Condition/IASI_L1_FormattedMetadata | $FileLocation/$Filename},{Runtime/Condition/IASI_L1_Filenames | $Filename}"/> 
+			<property name="QueueName" value="java"/>
+		</configuration>
+	</condition>			
+	<condition id="urn:npp:MOA_MHS_L1B_Daily" name="MOA_MHS_L1B_Daily" class="gov.nasa.jpl.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+		<configuration>
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_MHS_L1B"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="15"/>
+			<property name="PGETask/Condition/EpsilonInMillis" value="60000"/> <!--2mins-->
+			<property name="PGETask/Condition/SqlQueryKey" value="Runtime/Condition/MHS_L1_Query"/> 
+			<property name="PGETask/Condition/ResultKeyFormats" value="{Runtime/Condition/MHS_L1_FormattedMetadata | $FileLocation/$Filename},{Runtime/Condition/MHS_L1_Filenames | $Filename}"/> 
+			<property name="QueueName" value="java"/>
+		</configuration>
+	</condition>		
+	<condition id="urn:npp:MOA_AMSUA_L1B_Daily" name="MOA_MHS_L1B_Daily" class="gov.nasa.jpl.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+		<configuration>
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_AMSUA_L1B"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="15"/>
+			<property name="PGETask/Condition/EpsilonInMillis" value="60000"/> <!--2mins-->
+			<property name="PGETask/Condition/SqlQueryKey" value="Runtime/Condition/AMSUA_L1_Query"/> 
+			<property name="PGETask/Condition/ResultKeyFormats" value="{Runtime/Condition/AMSUA_L1_FormattedMetadata | $FileLocation/$Filename},{Runtime/Condition/AMSUA_L1_Filenames | $Filename}"/>
+			<property name="QueueName" value="java"/>
+		</configuration>
+	</condition>	
+	<condition id="urn:npp:MOA_ORBITS_FileBased" name="MOA_ORBITS_FileBased" class="gov.nasa.jpl.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+		<configuration>
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_ORBITS"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="1"/>
+			<property name="PGETask/Condition/SqlQueryKey" value="Runtime/Condition/OrbitsQuery"/> 
+			<property name="PGETask/Condition/ResultKeyFormats" value="{Runtime/Condition/OrbitsFormattedMetadata | $FileLocation/$Filename},{Runtime/Condition/OrbitsFilenames | $Filename}"/>
+			<property name="QueueName" value="java"/>		
+		</configuration>	
+	</condition>	
+	<condition id="urn:npp:MOA_IASI_POLY_FileBased" name="MOA_IASI_POLY_FileBased" class="gov.nasa.jpl.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+		<configuration>
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_IASI_POLY"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="1"/>
+			<property name="PGETask/Condition/SqlQueryKey" value="Runtime/Condition/IASI_GPolyQuery"/> 
+			<property name="PGETask/Condition/ResultKeyFormats" value="{Runtime/Condition/IASI_GPolyFormattedMetadata | $FileLocation/$Filename},{Runtime/Condition/IASI_GPolyFilenames | $Filename}"/>
+			<property name="QueueName" value="java"/>	
+		</configuration>	
+	</condition>			
+	<condition id="urn:npp:MOA_MHS_POLY_FileBased" name="MOA_MHS_POLY_FileBased" class="gov.nasa.jpl.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+		<configuration>
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_MHS_POLY"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="1"/>
+			<property name="PGETask/Condition/SqlQueryKey" value="Runtime/Condition/MHS_GPolyQuery"/> 
+			<property name="PGETask/Condition/ResultKeyFormats" value="{Runtime/Condition/MHS_GPolyFormattedMetadata | $FileLocation/$Filename},{Runtime/Condition/MHS_GPolyFilenames | $Filename}"/>
+			<property name="QueueName" value="java"/>	
+		</configuration>	
+	</condition>			
+	<condition id="urn:npp:MOA_AMSUA_POLY_FileBased" name="MOA_AMSUA_POLY_FileBased" class="gov.nasa.jpl.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+		<configuration>
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_AMSUA_POLY"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="1"/>
+			<property name="PGETask/Condition/SqlQueryKey" value="Runtime/Condition/AMSUA_GPolyQuery"/> 
+			<property name="PGETask/Condition/ResultKeyFormats" value="{Runtime/Condition/AMSUA_GPolyFormattedMetadata | $FileLocation/$Filename},{Runtime/Condition/AMSUA_GPolyFilenames | $Filename}"/>
+			<property name="QueueName" value="java"/>
+		</configuration>	
+	</condition>	
+	<!--condition id="urn:npp:VerifyMapsExist" name="VerifyMapsExist" class="gov.nasa.jpl.oodt.cas.pge.condition.PGETaskWorkflowCondition"/-->				
+	
+	
+	<!-- TASKS -->
+	<task id="urn:npp:Orbits" name="MoaOrbits" class="gov.nasa.jpl.oodt.cas.pge.StdPGETaskInstance">
+		<configuration>
+			<property name="PGETask/Name" value="MoaOrbits" />
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaOrbits/SPSS_Version]/config/PgeConfig_MoaOrbits.xml"/>
+			<property name="Runtime/Condition/L1FormattedMetadata" value="[Runtime/Condition/IASI_L1_FormattedMetadata]"/>
+			<property name="Runtime/Condition/L1Filenames" value="[Runtime/Condition/IASI_L1_Filenames]"/>
+			<property name="Instrument" value="MetOpS"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	<task id="urn:npp:MoaIasiGPolygon" name="MoaIasiGPolygon" class="gov.nasa.jpl.oodt.cas.pge.StdPGETaskInstance">
+		<configuration>
+			<property name="PGETask/Name" value="MoaIasiGPolygon"/>
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaIasiGPolygon/SPSS_Version]/config/PgeConfig_MoaGPolygon.xml"/>
+			<property name="Runtime/Condition/L1FormattedMetadata" value="[Runtime/Condition/IASI_L1_FormattedMetadata]"/>			
+			<property name="Runtime/Condition/L1Filenames" value="[Runtime/Condition/IASI_L1_Filenames]"/>			
+			<property name="Instrument" value="IASI"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	<task id="urn:npp:MoaMhsGPolygon" name="MoaMhsGPolygon" class="gov.nasa.jpl.oodt.cas.pge.StdPGETaskInstance">
+		<configuration>
+			<property name="PGETask/Name" value="MoaAmsuaGPolygon"/>
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaAmsuaGPolygon/SPSS_Version]/config/PgeConfig_MoaGPolygon.xml"/>
+			<property name="Runtime/Condition/L1FormattedMetadata" value="[Runtime/Condition/AMSUA_L1_FormattedMetadata]"/>						
+			<property name="Runtime/Condition/L1Filenames" value="[Runtime/Condition/AMSUA_L1_Filenames]"/>						
+			<property name="Instrument" value="AMSUA"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	<task id="urn:npp:MoaAmsuaGPolygon" name="MoaAmsuaGPolygon" class="gov.nasa.jpl.oodt.cas.pge.StdPGETaskInstance">
+		<configuration>
+			<property name="PGETask/Name" value="MoaMhsGPolygon"/>
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaMhsGPolygon/SPSS_Version]/config/PgeConfig_MoaGPolygon.xml"/>
+			<property name="Runtime/Condition/L1FormattedMetadata" value="[Runtime/Condition/MHS_L1_FormattedMetadata]"/>									
+			<property name="Runtime/Condition/L1Filenames" value="[Runtime/Condition/MHS_L1_Filenames]"/>									
+			<property name="Instrument" value="MHS"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	<task id="urn:npp:MoaIasiMap" name="MoaIasiMap" class="gov.nasa.jpl.oodt.cas.pge.StdPGETaskInstance">
+		<conditions execution="sequential" type="pre">
+			<condition id-ref="urn:npp:MOA_IASI_POLY_FileBased"/>			
+		</conditions>
+		<configuration>
+			<property name="PGETask/Name" value="MoaIasiMap"/>
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaIasiMap/SPSS_Version]/config/PgeConfig_MoaMap.xml"/>
+			<property name="Runtime/Condition/GPolyFormattedMetadata" value="[Runtime/Condition/IASI_GPolyFormattedMetadata]"/>									
+			<property name="Runtime/Condition/GPolyFilenames" value="[Runtime/Condition/IASI_GPolyFilenames]"/>
+			<property name="Instrument" value="IASI"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	<task id="urn:npp:MoaMhsMap" name="MoaMhsMap" class="gov.nasa.jpl.oodt.cas.pge.StdPGETaskInstance">
+		<conditions execution="sequential" type="pre">
+			<condition id-ref="urn:npp:MOA_MHS_POLY_FileBased"/>			
+		</conditions>
+		<configuration>
+			<property name="PGETask/Name" value="MoaMhsMap"/>
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaMhsMap/SPSS_Version]/config/PgeConfig_MoaMap.xml"/>
+			<property name="Runtime/Condition/GPolyFormattedMetadata" value="[Runtime/Condition/MHS_GPolyFormattedMetadata]"/>									
+			<property name="Runtime/Condition/GPolyFilenames" value="[Runtime/Condition/MHS_GPolyFilenames]"/>
+			<property name="Instrument" value="MHS"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	<task id="urn:npp:MoaAmsuaMap" name="MoaAmsuaMap" class="gov.nasa.jpl.oodt.cas.pge.StdPGETaskInstance">
+		<conditions execution="sequential" type="pre">
+			<condition id-ref="urn:npp:MOA_AMSUA_POLY_FileBased"/>			
+		</conditions>
+		<configuration>
+			<property name="PGETask/Name" value="MoaAmsuaMap"/>
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaAmsuaMap/SPSS_Version]/config/PgeConfig_MoaMap.xml"/>
+			<property name="Runtime/Condition/GPolyFormattedMetadata" value="[Runtime/Condition/AMSUA_GPolyFormattedMetadata]"/>									
+			<property name="Runtime/Condition/GPolyFilenames" value="[Runtime/Condition/AMSUA_GPolyFilenames]"/>
+			<property name="Instrument" value="AMSUA"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	
+</cas:workflows>
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/examples/mspi-workflow.xml b/0.8.1-rc1/app/weditor/src/main/resources/examples/mspi-workflow.xml
new file mode 100644
index 0000000..52313f0
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/examples/mspi-workflow.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<workflows> 
+    
+    <sequential id="MSPI_L1_Workflow" name="MSPI L1 Workflow">
+        
+        <configuration extends="global,workflows"/>
+        
+        <task id-ref="MSPI_L1A1_Task"/>
+        <task id-ref="MSPI_L1A2_Task"/>
+        <task id-ref="MSPI_L1B1_Task"/>
+        <task id-ref="MSPI_L1B2_Task"/>
+        
+    </sequential>
+    
+    <!-- CONDITIONS -->
+    <condition id="MSPI_L0_Condition" name="MSPI L0 Condition" class="gov.nasa.jpl.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+        <configuration extends="global,conditions,1-file">
+            <property name="PGETask/Condition/ProductTypeNames" value="MSPI_L0"/>
+            <property name="PGETask/Condition/ResultKeyFormats" value="{Runtime/Condition/L0/Formatted | $FileLocation/$Filename},{Runtime/Condition/L0/Filenames | $Filename},{Runtime/Condition/L0/StartDateTime | $StartDateTime},{Runtime/Condition/L0/EndDat
+                eTime | $EndDateTime},{Runtime/Condition/L0/Latitude | $Latitude},{Runtime/Condition/L0/Longitude | $Longitude},{Runtime/Condition/L0/Azimuth | $Azimuth},{Runtime/Condition/L0/Elevation | $Elevation}"/>
+            <property name="PGETask/Condition/SqlQueryKey" value="Runtime/Condition/L0_Query"/>
+        </configuration>
+    </condition>
+    <condition id="MSPI_L1A1_Condition" name="MSPI L1A1 Condition" class="gov.nasa.jpl.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+        <configuration extends="global,conditions,1-file">
+            <property name="PGETask/Condition/ProductTypeNames" value="MSPI_L1A1"/>
+            <property name="PGETask/Condition/ResultKeyFormats" value="{Runtime/Condition/L1A1/Formatted | $FileLocation/$Filename},{Runtime/Condition/L1A1/Filenames | $Filename},{Runtime/Condition/L1A1/StartDateTime | $StartDateTime},{Runtime/Condition/L1A
+                1/EndDateTime | $EndDateTime},{Runtime/Condition/L1A1/Latitude | $Latitude},{Runtime/Condition/L1A1/Longitude | $Longitude},{Runtime/Condition/L1A1/Azimuth | $Azimuth},{Runtime/Condition/L1A1/Elevation | $Elevation}"/>
+            <property name="PGETask/Condition/SqlQueryKey" value="Runtime/Condition/L1A1_Query"/>
+        </configuration>
+    </condition>
+    <condition id="MSPI_L1A2_Condition" name="MSPI L1A2 Condition" class="gov.nasa.jpl.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+        <configuration name="MSPI_L1A2_Condition" extends="global,conditions,1-file">
+            <property name="PGETask/Condition/ProductTypeNames" value="MSPI_L1A2"/>
+            <property name="PGETask/Condition/ResultKeyFormats" value="{Runtime/Condition/L1A2/Formatted | $FileLocation/$Filename},{Runtime/Condition/L1A2/Filenames | $Filename},{Runtime/Condition/L1A2/StartDateTime | $StartDateTime},{Runtime/Condition/L1A
+                2/EndDateTime | $EndDateTime},{Runtime/Condition/L1A2/Latitude | $Latitude},{Runtime/Condition/L1A2/Longitude | $Longitude},{Runtime/Condition/L1A2/Azimuth | $Azimuth},{Runtime/Condition/L1A2/Elevation | $Elevation}"/>
+            <property name="PGETask/Condition/SqlQueryKey" value="Runtime/Condition/L1A2_Query"/>
+        </configuration>
+    </condition>
+    <condition id="MSPI_L1B1_Condition" name="MSPI L1B1 Condition" class="gov.nasa.jpl.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+        <configuration extends="global,conditions,1-file">
+            <property name="PGETask/Condition/ProductTypeNames" value="MSPI_L1B1"/>
+            <property name="PGETask/Condition/ResultKeyFormats" value="{Runtime/Condition/L1B1/Formatted | $FileLocation/$Filename},{Runtime/Condition/L1B1/Filenames | $Filename},{Runtime/Condition/L1B1/StartDateTime | $StartDateTime},{Runtime/Condition/L1B
+                1/EndDateTime | $EndDateTime},{Runtime/Condition/L1B1/Latitude | $Latitude},{Runtime/Condition/L1B1/Longitude | $Longitude},{Runtime/Condition/L1B1/Azimuth | $Azimuth},{Runtime/Condition/L1B1/Elevation | $Elevation},{Runtime/Condition/L1B1/ref_row | 32}"
+            />
+            <property name="PGETask/Condition/SqlQueryKey" value="Runtime/Condition/L1B1_Query"/>
+        </configuration>
+    </condition>
+    <condition id="MSPI_L1B1_Diag_Condition" name="MSPI L1B1 Diag Condition" class="gov.nasa.jpl.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+        <configuration extends="global,conditions,1-file">
+            <property name="PGETask/Condition/ProductTypeNames" value="MSPI_L1B1_Diag"/>
+            <property name="PGETask/Condition/ResultKeyFormats" value="{Runtime/Condition/L1B1_Diag/Formatted | $FileLocation/$Filename},{Runtime/Condition/L1B1_Diag/Filenames | $Filename}"/>
+            <property name="PGETask/Condition/SqlQueryKey" value="Runtime/Condition/L1B1_Diag_Query"/>
+        </configuration>
+    </condition>
+    
+    <!-- TASKS -->
+    <task id="MSPI_L1A1_Task" name="MSPI L1A1 Task" class="gov.nasa.jpl.oodt.cas.pge.StdPGETaskInstance">
+        <conditions execution="sequential" type="pre">
+            <condition id-ref="MSPI_L0_Condition"/>
+        </conditions>
+        <configuration>
+            <property name="PGETask/Name" value="MSPI_L1A1_Task"/>
+            <property name="PGETask/FileBasedConfig/StageConfigFile" value="true"/>
+            <property name="PGETask/FileBasedConfig/ConfigFilePath" value="[PCS_HOME]/core/pge/policy/mspi/PgeConfig_MSPI_L1.xml" envReplace="true"/>
+            <property name="MSPI/L1Type" value="L1A1"/>
+            <property name="MSPI/L1InputType" value="L0"/>
+        </configuration>
+    </task>
+    <task id="MSPI_L1A2_Task" name="MSPI L1A2 Task" class="gov.nasa.jpl.oodt.cas.pge.StdPGETaskInstance">
+        <conditions execution="sequential" type="pre">
+            <condition id-ref="MSPI_L1A1_Condition"/>
+        </conditions>
+        <configuration>
+            <property name="PGETask/Name" value="MSPI_L1A2_Task"/>
+            <property name="PGETask/FileBasedConfig/StageConfigFile" value="true"/>
+            <property name="PGETask/FileBasedConfig/ConfigFilePath" value="[PCS_HOME]/core/pge/policy/mspi/PgeConfig_MSPI_L1.xml" envReplace="true"/>
+            <property name="MSPI/L1Type" value="L1A2"/>
+            <property name="MSPI/L1InputType" value="L1A1"/>
+        </configuration>
+    </task>
+    <task id="MSPI_L1B1_Task" name="MSPI L1B1 Task" class="gov.nasa.jpl.oodt.cas.pge.StdPGETaskInstance">
+        <conditions execution="sequential" type="pre">
+            <condition id-ref="MSPI_L1A2_Condition"/>
+        </conditions>
+        <configuration>
+            <property name="PGETask/Name" value="MSPI_L1B1_Task"/>
+            <property name="PGETask/FileBasedConfig/StageConfigFile" value="true"/>
+            <property name="PGETask/FileBasedConfig/ConfigFilePath" value="[PCS_HOME]/core/pge/policy/mspi/PgeConfig_MSPI_L1.xml" envReplace="true"/>
+            <property name="MSPI/L1Type" value="L1B1"/>
+            <property name="MSPI/L1InputType" value="L1A2"/>
+        </configuration>
+    </task>
+    <task id="MSPI_L1B2_Task" name="MSPI L1B2 Task" class="gov.nasa.jpl.oodt.cas.pge.StdPGETaskInstance">
+        <conditions execution="parallel" type="pre">
+            <condition id-ref="MSPI_L1B1_Condition"/>
+            <condition id-ref="MSPI_L1B1_Diag_Condition"/>
+        </conditions>
+        <configuration>
+            <property name="PGETask/Name" value="MSPI_L1B2_Task"/>
+            <property name="PGETask/FileBasedConfig/StageConfigFile" value="true"/>
+            <property name="PGETask/FileBasedConfig/ConfigFilePath" value="[PCS_HOME]/core/pge/policy/mspi/PgeConfig_MSPI_L1.xml" envReplace="true"/>
+            <property name="MSPI/L1Type" value="L1B2"/>
+            <property name="MSPI/L1InputType" value="L1B1"/>
+        </configuration>
+    </task>
+    
+</workflows>
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/examples/shared-properties.xml b/0.8.1-rc1/app/weditor/src/main/resources/examples/shared-properties.xml
new file mode 100644
index 0000000..73ae732
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/examples/shared-properties.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<workflows>
+    <configuration name="global">
+        <property name="PGETask/Query/FileManagerUrl" value="[FILEMGR_URL]" envReplace="true"/>
+        <property name="BlockTimeElapse" value="10"/> <!--10mins-->
+    </configuration>
+    <configuration name="workflows">
+        <property name="PGETask/Ingest/FileManagerUrl" value="[FILEMGR_URL]" envReplace="true"/>
+        <property name="PGETask/Ingest/ClientTransferServiceFactory" value="gov.nasa.jpl.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory"/>
+        <property name="PGETask/Ingest/MetFileExtension" value="cas"/>
+        <property name="PGETask/Ingest/CrawlerCrawlForDirs" value="false"/>
+        <property name="PGETask/Ingest/CrawlerRecur" value="false"/>
+        <!--property name="PGETask/Ingest/ActionsIds" value="RmDataFile"/>
+            <property name="PGETask/Ingest/ActionRepoFile" value="file:[PCS_HOME]/cas/pge/policy/action-beans.xml" envReplace="true"/-->
+        
+        <!-- resource runner properties -->
+        <property name="QueueName" value="exe"/>
+        <property name="Load" value="2"/>
+    </configuration>
+    <configuration name="conditions">
+        <property name="PGETask/Condition/Timeout" value="28800"/> <!--8hrs-->
+        <property name="PGETask/Condition/StartDateTimeKey" value="StartDateTime"/>
+        <property name="PGETask/Condition/EndDateTimeKey" value="EndDateTime"/>
+        <property name="PGETask/Condition/SortByKey" value="StartDateTime"/>
+        <property name="PGETask/Condition/VersioningKey" value="ProductionDateTime"/>
+        <property name="PGETask/Condition/MinNumOfFiles" value="1"/>
+        <property name="PGETask/Condition/MaxGap/Size" value="-1"/>
+        <property name="PGETask/Condition/EpsilonInMillis" value="0"/>
+        <property name="PGETask/Condition/FilterAlgorClass" value="gov.nasa.jpl.oodt.cas.filemgr.structs.query.filter.WeightedHashFilterAlgor"/>
+        
+        <!-- resource runner properties -->
+        <property name="QueueName" value="conds"/>
+        <property name="Load" value="1"/>
+    </configuration>
+    <configuration name="airs">
+        <property name="PGETask/Condition/StartDateTimeKey" value="UTC_start_time"/>
+        <property name="PGETask/Condition/EndDateTimeKey" value="UTC_stop_time"/>
+        <property name="PGETask/Condition/SortByKey" value="UTC_start_time"/>
+        <property name="PGETask/Condition/VersioningKey" value="ProductionDatetime"/>
+        <property name="PGETask/Condition/ExpectedNumOfFiles" value="240"/>
+        <property name="PGETask/Condition/EpsilonInMillis" value="10000"/> <!--10secs-->
+    </configuration>
+    <configuration name="14-files">
+        <!-- filter properties -->
+        <property name="PGETask/Condition/ExpectedNumOfFiles" value="14"/>
+        <property name="PGETask/Condition/EpsilonInMillis" value="1000000"/> <!--1000secs-->
+        
+        <!-- gap analysis properties -->
+        <property name="PGETask/Condition/MaxGap/Size" value="6000000"/> <!--100mins-->
+        <property name="PGETask/Condition/MaxGap/StartDateTime" value="[NominalDate]T00:00:00.000Z"/>
+        <property name="PGETask/Condition/MaxGap/EndDateTime" value="[NominalDate]T23:59:59.999Z"/>
+    </configuration>
+    <configuration name="480-files">
+        <!-- filter properties -->
+        <property name="PGETask/Condition/ExpectedNumOfFiles" value="480"/>
+        <property name="PGETask/Condition/EpsilonInMillis" value="30000"/> <!--30secs-->
+    </configuration>
+    <configuration name="1-file">
+        <property name="PGETask/Condition/FilterAlgorClass" value="gov.nasa.jpl.oodt.cas.filemgr.structs.query.filter.TakeEarliestEventFilterAlgor"/>
+        <property name="PGETask/Condition/ExpectedNumOfFiles" value="1"/>
+    </configuration>
+    <configuration name="concat-files">
+        <!-- filter properties -->
+        <property name="PGETask/Condition/ExpectedNumOfFiles" value="28"/>
+        <property name="PGETask/Condition/EpsilonInMillis" value="21600000"/> <!--6hours-->
+        <property name="PGETask/Condition/MinNumOfFiles" value="2"/>
+    </configuration>
+</workflows>
+
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/examples/test.xml b/0.8.1-rc1/app/weditor/src/main/resources/examples/test.xml
new file mode 100644
index 0000000..f2bf057
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/examples/test.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<cas:workflows 
+	xmlns="http://oodt.jpl.nasa.gov/2.0/cas"
+	xmlns:cas="http://oodt.jpl.nasa.gov/2.0/cas"
+	xmlns:p="http://oodt.jpl.nasa.gov/2.0/cas/property">
+	
+	<workflow id="TestWorkflow" execution="sequential">
+		<task id-ref="Orbit"/>
+		<workflow id="tester" execution="sequential">
+			<conditions execution="parallel">
+				<condition id-ref="cond1"/>
+				<condition id-ref="cond2"/>
+			</conditions>
+			
+			<parallel>
+				<workflow id="L0" execution="sequential">
+					<task id-ref="L0a"/>
+					<task id-ref="L0b"/>
+					<task id-ref="L0c"/>
+					<task id-ref="L0d"/>
+				</workflow> 
+				<workflow id-ref="L1a"/>
+			</parallel>
+			<sequential>
+				<task id-ref="Ane"/>
+				<parallel>
+					<workflow id-ref="GeoCal"/>
+					<workflow id-ref="Geo"/>             
+				</parallel>
+			</sequential>
+			
+			<conditions execution="sequential">
+				<condition id-ref="cond3"/>
+			</conditions>
+		</workflow>
+		<workflow id-ref="MSPI_L1_Workflow"/>
+	</workflow>
+	
+	<task id="Orbit" class="gov.nasa.jpl.oodt.cas.workflow.instance.ValidateMetadataInstance"/>
+	<task id="L0a" class="gov.nasa.jpl.oodt.cas.workflow.instance.ValidateMetadataInstance" p:validateKey="Orbit_key,cond1_key,cond2_key"/>
+	<task id="L0b" class="gov.nasa.jpl.oodt.cas.workflow.instance.ValidateMetadataInstance" p:validateKey="Orbit_key,cond1_key,cond2_key,L0a_key"/>
+	<task id="L0c" class="gov.nasa.jpl.oodt.cas.workflow.instance.ValidateMetadataInstance" p:validateKey="Orbit_key,cond1_key,cond2_key,L0a_key,L0b_key"/>
+	<task id="L0d" class="gov.nasa.jpl.oodt.cas.workflow.instance.ValidateMetadataInstance" p:validateKey="Orbit_key,cond1_key,cond2_key,L0a_key,L0b_key,L0c_key"/>
+	<task id="Ane" class="gov.nasa.jpl.oodt.cas.workflow.instance.ValidateMetadataInstance" p:validateKey="Orbit_key,cond1_key,cond2_key,L0a_key,L0b_key,L0c_key,L0d_key"/>
+	
+	<condition id="cond1" p:timeout="200" class="gov.nasa.jpl.oodt.cas.workflow.instance.ValidateMetadataInstance"/>
+	<condition id="cond2" class="gov.nasa.jpl.oodt.cas.workflow.instance.ValidateMetadataInstance"/>
+	<condition id="cond3" class="gov.nasa.jpl.oodt.cas.workflow.instance.ValidateMetadataInstance" p:validateKey="L0a_key,L0b_key,L0c_key,L0d_key,L1aTask_key,Ane_key,GeoCalTask_key,GeoTask_key,cond1_key,cond2_key"/>
+	
+	<sequential id="L1a">
+		<task id="L1aTask" class="gov.nasa.jpl.oodt.cas.workflow.instance.ValidateMetadataInstance" p:validateKey="Orbit_key,cond1_key,cond2_key"/>
+	</sequential>
+	
+	<workflow id="GeoCal" execution="sequential">
+		<task id="GeoCalTask" class="gov.nasa.jpl.oodt.cas.workflow.instance.ValidateMetadataInstance" p:validateKey="Orbit_key,Ane_key,cond1_key,cond2_key,L0b_key,L0c_key,L0d_key"/>
+	</workflow>
+	
+	<workflow id="Geo" execution="sequential">
+		<task id="GeoTask" class="gov.nasa.jpl.oodt.cas.workflow.instance.ValidateMetadataInstance" p:validateKey="Orbit_key,Ane_key,cond1_key,cond2_key,L0b_key,L0c_key,L0d_key"/>
+	</workflow>
+
+</cas:workflows>
\ No newline at end of file
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/icons/cursor-zoom.png b/0.8.1-rc1/app/weditor/src/main/resources/icons/cursor-zoom.png
new file mode 100644
index 0000000..e47f879
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/icons/cursor-zoom.png
Binary files differ
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/icons/delete-sel.jpg b/0.8.1-rc1/app/weditor/src/main/resources/icons/delete-sel.jpg
new file mode 100644
index 0000000..3144ab6
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/icons/delete-sel.jpg
Binary files differ
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/icons/delete.jpg b/0.8.1-rc1/app/weditor/src/main/resources/icons/delete.jpg
new file mode 100644
index 0000000..876c80c
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/icons/delete.jpg
Binary files differ
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/icons/edit-sel.jpg b/0.8.1-rc1/app/weditor/src/main/resources/icons/edit-sel.jpg
new file mode 100644
index 0000000..ef262a4
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/icons/edit-sel.jpg
Binary files differ
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/icons/edit.jpg b/0.8.1-rc1/app/weditor/src/main/resources/icons/edit.jpg
new file mode 100644
index 0000000..e56d6d4
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/icons/edit.jpg
Binary files differ
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/icons/move-sel.jpg b/0.8.1-rc1/app/weditor/src/main/resources/icons/move-sel.jpg
new file mode 100644
index 0000000..b54dcce
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/icons/move-sel.jpg
Binary files differ
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/icons/move.jpg b/0.8.1-rc1/app/weditor/src/main/resources/icons/move.jpg
new file mode 100644
index 0000000..d96e03d
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/icons/move.jpg
Binary files differ
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/icons/zoom-in-sel.jpg b/0.8.1-rc1/app/weditor/src/main/resources/icons/zoom-in-sel.jpg
new file mode 100644
index 0000000..a072e15
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/icons/zoom-in-sel.jpg
Binary files differ
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/icons/zoom-in.jpg b/0.8.1-rc1/app/weditor/src/main/resources/icons/zoom-in.jpg
new file mode 100644
index 0000000..a61decf
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/icons/zoom-in.jpg
Binary files differ
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/icons/zoom-out-sel.jpg b/0.8.1-rc1/app/weditor/src/main/resources/icons/zoom-out-sel.jpg
new file mode 100644
index 0000000..5820b39
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/icons/zoom-out-sel.jpg
Binary files differ
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/icons/zoom-out.jpg b/0.8.1-rc1/app/weditor/src/main/resources/icons/zoom-out.jpg
new file mode 100644
index 0000000..2996af1
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/icons/zoom-out.jpg
Binary files differ
diff --git a/0.8.1-rc1/app/weditor/src/main/resources/logging.properties b/0.8.1-rc1/app/weditor/src/main/resources/logging.properties
new file mode 100644
index 0000000..8d72499
--- /dev/null
+++ b/0.8.1-rc1/app/weditor/src/main/resources/logging.properties
@@ -0,0 +1,40 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.   
+
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
+
+# Set the default logging level for the root logger
+.level = INFO
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.FileHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = ../logs/cas_workflow_gui%g.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 5
+java.util.logging.FileHandler.append = true
+java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging level for the subsystems
+org.apache.oodt.cas.workflow.gui.level = INFO
diff --git a/0.8.1-rc1/balance/etc/skel/.htaccess b/0.8.1-rc1/balance/etc/skel/.htaccess
new file mode 100644
index 0000000..e3a557a
--- /dev/null
+++ b/0.8.1-rc1/balance/etc/skel/.htaccess
@@ -0,0 +1,45 @@
+#
+# 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.
+#
+
+# Rewrite rules for OODT Balance web applications. 
+#
+# Enable the rewrite engine
+RewriteEngine On
+
+# Make sure that the value for RewriteBase exactly matches the 
+# value for site_root in config.ini. This value should point to the 
+# location (relative to the server's document root) of the 
+# Balance webapp directory (the directory containing config.ini). For
+# example, if the application lives at the server's document root, then
+# RewriteBase should be set to '/'. If, on the other hand, the application
+# has been installed into a subdirectory 'foo' underneath the server's 
+# document root, RewriteBase (and site_root in config.ini) should be set
+# to '/foo/'
+RewriteBase /
+
+# This section forwards all requests to the Balance application's front
+# controller. Unless you are modifying the low-level behavior of the 
+# Balance application framework, there should be no need to make any
+# modifications below this line. -----------------------------------------
+#
+# Send all other non-static requests to the main controller
+RewriteCond %{REQUEST_URI} !/static/(.*)$
+RewriteCond %{REQUEST_URI} !/scripts/(.*)$
+RewriteCond %{REQUEST_URI} !/global/(.*)$
+RewriteCond %{REQUEST_URI} !index\.php/.+$
+RewriteRule ^(.+)$ ./index\.php/$1 [L,NC]
+
diff --git a/0.8.1-rc1/balance/etc/skel/README.txt b/0.8.1-rc1/balance/etc/skel/README.txt
new file mode 100644
index 0000000..ce7b2fd
--- /dev/null
+++ b/0.8.1-rc1/balance/etc/skel/README.txt
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+OODT Balance Web Application README File
+
+The OODT Balance web application skeleton is a quick way to get started 
+developing a new Balance application. It provides the necessary directory 
+structure and sane default configuration values that you can customize to 
+suit your needs. These instructions assume you have the necessary access 
+to install files into your web server's document root. These instructions 
+will help you create an application called 'my-application' which will be 
+accessed from http://localhost/my-application. Your environment and/or 
+needs may differ, so adapt the following as necessary.
+
+
+1. Installing the OODT Balance PEAR package ("Balance library")
+
+The Balance library provides core classs that must be in place prior to 
+developing a Balance application. The library only needs to be installed 
+once per system. If you have previously installed the Balance library on 
+your system, you can safely skip this step.
+
+   a. Download the latest stable Balance library release (OODT_ROOT/balance/lib/pear)
+      to a scratch directory on your system
+   b. Build the pear package using the pear command line utility:
+      $ pear package
+   c. Install the resulting package (.tgz file) using the pear installer:
+      $ pear install --force Org_Apache_Oodt_Balance-#.#.#.tgz
+
+2. Setting up the web application skeleton
+
+The files in this directory represent the Balance application skeleton. If
+you have not already done so, move the directory containing this file to
+your web server's directory root, noting the name you use for the path
+(e.g.: /path/to/document/root/my-application). The instructions below assume
+that you have named the directory 'my-application'. Adjust as necessary for 
+your environment.
+
+   a. In the config.ini file, set the url_base configuration variable to /my-application
+   b. In the .htaccess file, set the RewriteBase directive to /my-application
+   c. Visit http://localhost/my-application to see your skeletal Balance application. Note
+      that the URL you use to visit your application may differ slightly from the above 
+      if you have set up virtual hosting or have a domain name other than localhost.
+
+3. Developing your web application
+
+The following is a very high level introduction to developing a web application using Balance.
+
+Balance operates on the concept of application 'views'. Each application url, e.g.: 
+http://localhost/my-application/about, maps to exactly one view, e.g.: HOME/views/about.php, 
+where HOME is the location of the Balance web application files. A view file is a plain vanilla
+PHP file, which, in its simplest form, might only contain static HTML. For more involved tasks,
+functions from the Balance core library can be invoked directly from within the view file.
+
+Most sites incorporate common, site-wide content at the top (header) and bottom (footer) of
+each page. Balance supports header and footer files, which get included with every view unless
+the view file itself explicitly modifies this behavior. By default, the header and footer file
+can be found at HOME/views/common/header.php and HOME/views/common/footer.php, respectively.
+
+Occasionally, such as when a form gets submitted via POST, a script needs to be invoked to handle
+the input. Scripts are generally located at HOME/scripts, and are named according to the url
+that will be used to invoke them. Scripts are differentiated from views from a url standpoint in
+that urls for scripts end in '.do' whereas urls for views generally do not have a file extension.
+As a concrete example, imagine a login view providing inputs for username and password. It might
+theoretically reside at HOME/views/login.php and be accessed via 
+http://localhost/my-application/login. On submission, the login form's target might be set to a 
+login script that processes the submitted user information. That script would reside at 
+HOME/scripts/login.php and be accessed via http://localhost/my-application/login.do. In the 
+event that the script is intended to handle GET parameters, they are appended after the .do using
+the standard url notation (e.g.: ...myscript.do?param1=value1&param2=value2). The '.do' extension is 
+merely a url routing convention meant to imply the execution of some action, the actual script 
+file in HOME/scripts maintains the '.php' extension.
+
+More information can be obtained by visiting the OODT website (http://oodt.apache.org) or posing
+a question to the OODT user mailing list (user@oodt.apache.org).
+
diff --git a/0.8.1-rc1/balance/etc/skel/config.ini b/0.8.1-rc1/balance/etc/skel/config.ini
new file mode 100644
index 0000000..04391b1
--- /dev/null
+++ b/0.8.1-rc1/balance/etc/skel/config.ini
@@ -0,0 +1,82 @@
+;
+; 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.
+;
+
+;
+; OODT Balance
+; Web Application Base Framework
+;
+; Application Configuration File. This file should be called 'config.ini' and 
+; should reside in the root directory of your site. This file follows standard
+; ini file conventions. Lines beginning with ';' are comments and are ignored.
+;
+
+[Application Environment]
+
+; site_root
+; If the site lives at the document root of the server, this will be '/'. On
+; the other hand, if the site lives in a sub-directory of the document root, 
+; this will be the full path (starting from the document root) to the root 
+; directory of the site. Always start with a slash (/) and always omit the
+; trailing slash. 
+;
+; examples: 
+;    (document root) http://domain.com/          (site_root: '/')
+;    (subdirectory)  http://domain.com/apps/site (site_root: '/apps/site')
+;
+; Note: The value for site_root should always match the value for 'RewriteBase'
+;       in the .htaccess file located in the site's root directory.
+;
+site_root = /
+
+
+[Application Content]
+
+; views_dir
+; This is the directory inside your site root where your application's views
+; reside. This should be a relative path (./). If you have set things up
+; according to the instructions, the framework will use the location of this 
+; file (config.ini) as the base.
+;
+; Note: The value provided is simply an example. It is up to you to provide
+;       valid paths for your environment.
+views_dir = ./views
+
+; header_file_path
+; This is the file that contains a site-wide header code/layout to be included
+; in each view. This should be a relative path (./). If you have set things up
+; according to the instructions, the framework will use the location of this 
+; file (config.ini) as the base.
+;
+; Note: The value provided is simply an example. It is up to you to provide
+;       valid paths for your environment.
+header_file_path = ./views/common/header.php
+
+; footer_file_path
+; This is the file that contains a site-wide footer code/layout to be included
+; in each view. This should be a relative path (./). If you have set things up
+; according to the instructions, the framework will use the location of this 
+; file (config.ini) as the base.
+;
+; Note: The value provided is simply an example. It is up to you to provide
+;       valid paths for your environment.
+footer_file_path = ./views/common/footer.php
+
+
+[AUTH & AUTH]
+
+; Authorization error redirect path to login page
+authorization_redirect_url = /
diff --git a/0.8.1-rc1/balance/etc/skel/hooks.php b/0.8.1-rc1/balance/etc/skel/hooks.php
new file mode 100644
index 0000000..b26dd94
--- /dev/null
+++ b/0.8.1-rc1/balance/etc/skel/hooks.php
@@ -0,0 +1,98 @@
+<?php
+/*
+ * 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.
+ *
+*/
+
+/**
+ * HOOKS.PHP
+ *
+ * Hooks provide the ability, as the name implies, to hook into various parts of
+ * the view rendering process and insert customizations. The contents of these
+ * functions are run at the appropriate time *EVERY* time a view is rendered, i.e.
+ * the content of the hooks is not by default view-specific but rather will be
+ * applied to all views. (However, there is nothing that prevents developers from
+ * inserting conditional logic inside a hook that then causes view-specific
+ * them to exhibit view-specific behavior).
+ *
+ * As an example, consider a hook that adds the amount of time Balance took to render
+ * the page as an inline HTML comment at the bottom of each page after it has been sent:
+ *
+ * function hook_after_send() {
+ *     $timeStart = $GLOBALS['balance_request_start'];
+ *     $timeNow   = microtime(true);
+ *     $elapsed   = $timeNow - $timeStart;
+ *     echo "<!-- page rendered in {$elapsed} seconds -->";
+ * }
+ *
+ *
+ * Take a look at the docblock descriptions of each hook to get a sense of where
+ * in the view rendering process the hook is invoked.
+ *
+ */
+
+/**
+ * hook_before_all
+ *
+ * This hook is executed before any other hooks. It can be used for any
+ * pre-processing logic.
+ */
+function hook_before_all() {}
+
+/**
+ * hook_before_header
+ *
+ * This hook is executed before the contents of the header file are processed.
+ */
+function hook_before_header() {}
+
+/**
+ * hook_before_view
+ *
+ * This hook is executed before the contents of the main view are processed.
+ */
+function hook_before_view() {}
+
+/**
+ * hook_before_footer
+ *
+ * This hook is executed before the contents of the footer are processed
+ */
+function hook_before_footer() {}
+
+/**
+ * hook_before_send
+ *
+ * This hook is after all of the view components (header, view, footer) have been
+ * processed but before the processed results are sent out across the wire to the
+ * browser. HTTP headers have not yet been sent to the browser.
+ */
+function hook_before_send() {}
+
+/**
+ * hook_after_send
+ *
+ * This hook is after all of the view components (header, view, footer) have been
+ * processed and sent out across the wire to the browser. It can be used for logging
+ * or analytics purposes, or to append a common trailer to all content.
+ */
+function hook_after_send() {
+	$timeStart = $GLOBALS['balance_request_start'];
+	$timeEnd   = microtime(true);
+	$elapsed   = $timeEnd - $timeStart;
+
+	echo "\r\n<!-- page rendered in {$elapsed} seconds -->";
+}
diff --git a/0.8.1-rc1/balance/etc/skel/index.php b/0.8.1-rc1/balance/etc/skel/index.php
new file mode 100644
index 0000000..e02633d
--- /dev/null
+++ b/0.8.1-rc1/balance/etc/skel/index.php
@@ -0,0 +1,48 @@
+<?php
+/*
+ * 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.
+ */
+
+/*
+ * OODT Balance
+ * Web Application Base Framework
+ *
+ * Front-controller
+ * This file handles the marshalling of requests to the appropriate
+ * application view.
+ *
+ */
+define ("DEBUG", true); // Change this to `false` when no longer debugging
+
+// Application root directory path (should never need to change this)
+define ("HOME",  dirname(__FILE__));
+
+/* Set up application environment ***************************************/
+require_once("Org/Apache/Oodt/Balance/Boot/bootstrap.php");
+
+/* Initialize the application with the settings from config.ini *********/
+$app = $GLOBALS['app'] = App::Create(parse_ini_file(HOME . '/config.ini'));
+
+/* Initialize any globally required modules here ************************/
+// Example:
+// To load a module 'foo', located at ./modules/foo, on every request:
+// App::Get()->loadModule('foo');
+
+/* Generate and send a response to the browser **************************/
+$response = $app->getResponse()->send();
+
+/* Clean up after ourselves *********************************************/
+$app->cleanup();
diff --git a/0.8.1-rc1/balance/etc/skel/scripts/widgets/BreadcrumbsWidget.php b/0.8.1-rc1/balance/etc/skel/scripts/widgets/BreadcrumbsWidget.php
new file mode 100644
index 0000000..571186e
--- /dev/null
+++ b/0.8.1-rc1/balance/etc/skel/scripts/widgets/BreadcrumbsWidget.php
@@ -0,0 +1,101 @@
+<?php
+/*
+ * 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.
+ */
+
+/*
+ * BREADCRUMB DISPLAY WIDGET
+ *
+ * Widget to display basic information about the current page. It allows
+ * users to keep track of their locations within the website.
+ *
+ * These breadcrumbs will allow the user to return to parent pages when a
+ * a link is provided.
+ *
+ * Initialization BreadcrumbsWidget:
+ *      $bcw = new BreadcrumbsWidget( $options = array());
+ *
+ *      supported options:
+ *        'separator' => "(string) specifying the html that should separate breadcrumbs"
+ *
+ *      *NOTE*: the class also recognizes the `breadcrumbs_separator` application config
+ *              setting. If this setting is present within the application config.ini file,
+ *              the value will be used as the separator;
+ *
+ *
+ * Adding a label breadcrumb (no link):
+ * 		$bcw->add('Label');
+ *
+ * Adding a linked label breadcrumb:
+ * 	 	$bcw->add('Label','link_href');
+ *
+ *
+ */
+
+class BreadcrumbsWidget
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationWidget {
+
+	protected $separator = '&nbsp;&rarr;&nbsp;';
+
+	public function __construct($options = array()) {
+
+		// Check if the breadcrumbs_separator config setting has been set
+		if (isset(App::Get()->settings['breadcrumbs_separator'])) {
+			$this->separator = App::Get()->settings['breadcrumbs_separator'];
+		}
+
+		// If the 'separator' option has been passed, prefer it
+		if (isset($options['separator'])) {
+			$this->separator = $options['separator'];
+		}
+	}
+
+	public function add( $label = null, $link = null) {
+		$breadcrumbs = App::Get()->response->data('breadcrumbs');
+		if ( $label != null && $link != null ) {
+
+			// will show up as a linked label
+			$breadcrumbs[] = array($label,$link);
+		} elseif ( $label != null ) {
+
+			// will show up as just text
+			$breadcrumbs[] = $label;
+		} else
+			return 0;
+
+		App::Get()->response->data("breadcrumbs",$breadcrumbs);
+	}
+
+	public function render($bEcho = true) {
+		$str 	= '';
+		$data = App::Get()->response->data('breadcrumbs');
+		if ( !empty($data) ) {
+			foreach ($data as $bc) {
+				if (is_array($bc)) {
+					$str .= '<span class="crumb link"><a href="'.$bc[1].'">'.$bc[0]."</a></span>{$this->separator}";
+				} else {
+					$str .= '<span class="crumb text">'.$bc.'</span>';
+				}
+			}
+		}
+
+		if($bEcho) {
+			echo $str;
+		} else {
+			return $str;
+		}
+	}
+}
diff --git a/0.8.1-rc1/balance/etc/skel/static/css/balance/balance.css b/0.8.1-rc1/balance/etc/skel/static/css/balance/balance.css
new file mode 100644
index 0000000..a67a776
--- /dev/null
+++ b/0.8.1-rc1/balance/etc/skel/static/css/balance/balance.css
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+/***** RESET *************************************************************/
+html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, 
+blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, 
+img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, 
+i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, 
+caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, 
+embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, 
+section, summary, time, mark, audio, video {
+    margin: 0;
+    padding: 0;
+    border: 0;
+    font-size: 100%;
+    font: inherit;
+    vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure, 
+footer, header, hgroup, menu, nav, section {
+    display: block;
+}
+body {
+    line-height: 1;
+}
+ol, ul {
+    list-style: none;
+}
+blockquote, q {
+    quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+    content: '';
+    content: none;
+}
+table {
+    border-collapse: collapse;
+    border-spacing: 0;
+}
+
+/***** BALANCE DEFAULTS *********************************************/
+
+html,body {
+    font-family:arial,verdana,sans-serif;
+    font-size:1em;
+    font-weight:normal;
+    color:#000;
+    line-height:1.5em;
+}
+
+h1, h2, h3, h4, h5 {
+    margin:10px 0px;
+}
+
+h1 {
+    font-size:2.1em;
+    font-weight:bold;
+    margin:15px 0px;
+}
+
+h2 {
+    font-size:1.8em;
+    font-weight:bold;
+    margin:12px 0px;
+}
+
+h3 {
+    font-size:1.4em;
+    font-weight:bold;
+}
+
+h4 {
+    font-size:1.2em;
+    font-weight:bold;
+}
+
+h5 {
+    font-size:1em;
+    font-weight:bold;
+}
+
+div.container {
+    width:960px;
+    margin:10px auto;
+}
+
+
+/**
+ * Balance Widget Styling
+ */
+
+div.bal_widget {
+	border:solid 1px #ccc;
+	padding:5px;
+}
+
+/**
+ * Balance default footer styling
+ */
+div.bal_footer {
+	color:#888;
+	font-size:80%;	
+}
diff --git a/0.8.1-rc1/balance/etc/skel/static/css/site.css b/0.8.1-rc1/balance/etc/skel/static/css/site.css
new file mode 100644
index 0000000..37fd84b
--- /dev/null
+++ b/0.8.1-rc1/balance/etc/skel/static/css/site.css
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+/**
+ * Place site CSS statements here
+ **/
diff --git a/0.8.1-rc1/balance/etc/skel/views/common/footer.php b/0.8.1-rc1/balance/etc/skel/views/common/footer.php
new file mode 100644
index 0000000..bb45547
--- /dev/null
+++ b/0.8.1-rc1/balance/etc/skel/views/common/footer.php
@@ -0,0 +1,38 @@
+<?php
+/*
+ * 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.
+ */
+
+/*
+ * Application Footer File
+ *
+ * This file represents a sample application footer file that will be displayed
+ * with every application view (unless the view has explicitly requested
+ * a different footer file, or no footer at all). To customize the footer
+ * file, you have two options:
+ * 
+ * 1) make changes to this file directly
+ * 2) create a new footer file, and update config.ini to point to it, instead
+ */
+?>
+
+<div class="bal_footer">
+	Created with OODT Balance v.<?php echo BALANCE_VERSION ?>
+</div>
+<!-- html closing statements -->
+</div>
+</body>
+</html>
diff --git a/0.8.1-rc1/balance/etc/skel/views/common/header.php b/0.8.1-rc1/balance/etc/skel/views/common/header.php
new file mode 100644
index 0000000..df5dc1f
--- /dev/null
+++ b/0.8.1-rc1/balance/etc/skel/views/common/header.php
@@ -0,0 +1,56 @@
+<?php
+/*
+ * 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.
+ */
+
+/*
+ * Application Header File
+ *
+ * This file represents a sample application header file that will be displayed
+ * with every application view (unless the view has explicitly requested
+ * a different header file, or no header file at all). To customize the header
+ * file, you have two options:
+ * 
+ * 1) make changes to this file directly
+ * 2) create a new header file, and update config.ini to point to it, instead
+ */
+?>
+<!DOCTYPE html>
+<html>
+<head>
+<title>Untitled OODT Balance Application</title>
+
+<!-- Base stylesheets -->
+<link rel="stylesheet" type="text/css" href="<?php echo SITE_ROOT .'/static/css/balance/balance.css'?>"/>
+
+<!-- Base Javascript -->
+
+<!-- Dynamically Added Stylesheets -->
+<!-- STYLESHEETS -->
+
+<!-- Dynamically Added Javascripts -->
+<!-- JAVASCRIPTS -->
+
+<!-- Site specific stylesheet overrides -->
+<link rel="stylesheet" type="text/css" href="<?php echo SITE_ROOT .'/static/css/site.css'?>"/>
+
+</head>
+<body>
+<div class="container">
+<?php
+	// This retrieves any 'flash' messages that should be displayed to the user
+	echo App::Get()->GetMessages();
+?>
diff --git a/0.8.1-rc1/balance/etc/skel/views/errors/403.php b/0.8.1-rc1/balance/etc/skel/views/errors/403.php
new file mode 100644
index 0000000..9e87eab
--- /dev/null
+++ b/0.8.1-rc1/balance/etc/skel/views/errors/403.php
@@ -0,0 +1,30 @@
+<?php 
+/*
+ * 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.
+ */
+
+// Prepare BreadcrumbsWigdet
+require_once( HOME . '/scripts/widgets/BreadcrumbsWidget.php');
+$bcw = new BreadcrumbsWidget();
+$bcw->add('Home',SITE_ROOT . '/');
+$bcw->add('Access Forbidden');
+?>
+
+<div id="page_content">
+	<h2> 403 Access Forbidden </h2>
+	<h5> You are not authorized to view the requested resource. If you feel this is in error, please
+             contact the webmaster for this site </h5>
+</div>
diff --git a/0.8.1-rc1/balance/etc/skel/views/errors/404.php b/0.8.1-rc1/balance/etc/skel/views/errors/404.php
new file mode 100644
index 0000000..4f40a82
--- /dev/null
+++ b/0.8.1-rc1/balance/etc/skel/views/errors/404.php
@@ -0,0 +1,29 @@
+<?php
+/*
+ * 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.
+ */
+
+// Prepare BreadcrumbsWigdet
+require_once( HOME . '/scripts/widgets/BreadcrumbsWidget.php');
+$bcw = new BreadcrumbsWidget();
+$bcw->add('Home',SITE_ROOT . '/');
+$bcw->add('Not Found');
+?>
+
+<div id="page_content">
+        <h2> 404 Not Found </h2>
+        <h5> The requested resource (<?php echo App::Get()->request->uri?>) does not exist.</h5>
+</div>
diff --git a/0.8.1-rc1/balance/etc/skel/views/index.php b/0.8.1-rc1/balance/etc/skel/views/index.php
new file mode 100644
index 0000000..9d65e00
--- /dev/null
+++ b/0.8.1-rc1/balance/etc/skel/views/index.php
@@ -0,0 +1,35 @@
+<!--
+/*
+ * 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.
+ */
+-->
+<p>&nbsp;</p>
+<h1>Hello from OODT Balance</h1>
+
+<div class="box">
+	<h5>To configure your application:</h5>
+	<code>file://<?php echo HOME?>/config.ini</code>
+</div>
+
+<div class="box">
+	<h5>To edit this view:</h5>
+	<code>file://<?php echo HOME?>/views/index.php</code>
+</div>
+
+<div class="box">
+	<h5>For more information:</h5>
+	<a href="http://oodt.apache.org">http://oodt.apache.org</a>
+</div>
diff --git a/0.8.1-rc1/balance/lib/pear/Boot/bootstrap.php b/0.8.1-rc1/balance/lib/pear/Boot/bootstrap.php
new file mode 100644
index 0000000..abdcb9d
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Boot/bootstrap.php
@@ -0,0 +1,59 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * Bootstrap file to provide all framework base files necessary to 
+ * satisfy a resource request.
+ * 
+ * @author ahart
+ * 
+ */
+
+define("BALANCE_VERSION", '0.3-SNAPSHOT');
+
+// Include Required Framework Interfaces
+include("Org/Apache/Oodt/Balance/Interfaces/IApplicationWidget.php");
+include("Org/Apache/Oodt/Balance/Interfaces/IApplicationDataProvider.php");
+include("Org/Apache/Oodt/Balance/Interfaces/IApplicationAuthenticationProvider.php");
+include("Org/Apache/Oodt/Balance/Interfaces/IApplicationAuthorizationProvider.php");
+
+// Include Required Framework Classes
+include("Org/Apache/Oodt/Balance/Core/Application.class.php");
+include("Org/Apache/Oodt/Balance/Core/ApplicationRequest.class.php");
+include("Org/Apache/Oodt/Balance/Core/ApplicationResponse.class.php");
+include("Org/Apache/Oodt/Balance/Core/ApplicationDataResponse.class.php");
+
+
+class App {
+	
+	protected static $app = null;
+	
+	public static function Create($config) {
+		if (!self::$app) {
+			self::$app = new Org_Apache_Oodt_Balance_Core_Application($config);
+		} 
+		return self::$app;
+	}
+	
+	public static function Get() {
+		return self::$app;
+	}
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Core/Application.class.php b/0.8.1-rc1/balance/lib/pear/Core/Application.class.php
new file mode 100644
index 0000000..9a1f087
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Core/Application.class.php
@@ -0,0 +1,427 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * Main class for OODT Balance web applications. Contains utility
+ * methods and definitions that provide standard functionality across
+ * the site.
+ * 
+ * @author ahart
+ * 
+ */
+class Org_Apache_Oodt_Balance_Core_Application {
+	
+	public $request;
+	
+	public $subrequest;
+	
+	public $authenticationProviderInstance = null;
+	
+	public $authorizationProviderInstance = null;
+	
+	public $response;
+	
+	public $settings;
+	
+	public $modulesLoaded;
+	
+	public function __construct($settings) {
+		
+		// Save the application settings
+		$this->settings = $settings;
+		
+		// Update the PHP include path to include the locations specified in
+		// the application configuration .ini file
+		if (isset($this->settings['classes_dir']) && is_array($this->settings['classes_dir'])) {
+			$customClassPath = implode(';',$this->settings['classes_dirs']);
+			set_include_path(get_include_path() . ';' . $customClassPath);
+		}
+		
+		// Initialize a session
+		session_start();
+		
+		// Define the application base url
+		define ("SITE_ROOT", ($settings['site_root'] == '/') 
+			? '' 
+			: $settings['site_root']);
+			
+	}
+	
+	
+	public function getResponse() {
+		
+		$this->setAuthenticationProviderInstance();
+		$this->setAuthorizationProviderInstance();
+		
+		// Interpret the request uri of the current request
+		$uri = App::Get()->settings['site_root'] != '/'
+			? substr($_SERVER['REQUEST_URI'],strlen(App::Get()->settings['site_root']))
+			: $_SERVER['REQUEST_URI'];
+		$this->request = new Org_Apache_Oodt_Balance_Core_ApplicationRequest(
+			$this->settings,$uri);
+			
+		// Initialize a response object for the request
+		$this->response = new Org_Apache_Oodt_Balance_Core_ApplicationResponse(
+			$this->settings,$this->request);
+			
+		// Process the response
+		$this->response->process();
+			
+		// Return the processed response object
+		return $this->response;
+	}
+	
+	public function cleanup() {
+		
+	}
+	
+	/**
+	 * Determine whether the current request maps to resources associated
+	 * with an application module. 
+	 * 
+	 * If a view, script, or static asset is part of an application module,
+	 * the path to the file will differ than those for regular application
+	 * resources. This function provides a way to determine whether a given
+	 * request should be considered part of a module or of the general 
+	 * application. 
+	 * 
+	 * @param $requestURI - The request uri to test
+	 * @return boolean    - true indicates the request uri belongs to a module
+	 */
+	public function isModule($requestURI) {
+		// Determine whether a module is being requested
+		$filteredURI = $requestURI;
+		$filteredURI = ltrim($filteredURI,'/');
+		$parts = explode('/',$filteredURI);
+
+        if (is_dir(HOME . "/modules")) {
+			$handle = opendir(HOME . "/modules");
+			while (false !== ($dir = readdir($handle))) {
+				if ( $dir == $parts[0] && $module = $this->loadModule($dir) ) {
+					return $module;
+				}
+			}
+		}
+		return false;
+	}
+	
+	public function getAuthenticationProvider() {
+		return $this->authenticationProviderInstance;
+	}
+	
+	public function setAuthenticationProviderInstance() {
+		
+		// Check if the user wants authentication for application 
+		if ( $this->settings['authentication_class_path'] != null &&
+			 $this->settings['authentication_class']      != null   ) {
+			 	
+			 	require_once $this->settings['authentication_class_path'];
+				$authProvider = $this->settings['authentication_class'];
+				$this->authenticationProviderInstance = new $authProvider();
+		}
+	}
+	
+	public function getAuthorizationProvider() {
+		return $this->authorizationProviderInstance;
+	}
+	
+	public function setAuthorizationProviderInstance() {
+		
+		// Check if the user wants authorization for application 
+		if ( $this->settings['authorization_class_path'] != null &&
+			 $this->settings['authorization_class']      != null   ) {
+			 	
+			 	require_once $this->settings['authorization_class_path'];
+				$authProvider 		  				 = $this->settings['authorization_class'];
+				$this->authorizationProviderInstance = new $authProvider();
+		}
+	}
+	
+	public function loadModule($modName = null) {
+		// If the module name is null, a module is requesting that
+		// its own context be loaded
+		if ($modName === null) {
+			return $this->getModuleContext();
+		}
+
+		// If the module has been previously loaded, return its context
+		if (isset($this->modulesLoaded[$modName])) {
+			return $this->modulesLoaded[$modName];
+		}
+
+		// check if module path exists before loading module context
+		$modulePath = HOME . "/modules/{$modName}";
+		if ( is_dir($modulePath) ) {
+			
+			// create stdClass 
+			$modClass = new stdClass();
+			$modClass->modulePath   = $modulePath;
+			$modClass->moduleRoot   = SITE_ROOT . "/{$modName}";
+			$modClass->moduleStatic = SITE_ROOT . "/modules/{$modName}/static";
+
+			$this->modulesLoaded[$modName] = $modClass;
+
+			// Read in the module config file and append to application config
+			if (file_exists($modulePath . '/config.ini')) {
+			   	// Get the raw contents of the config file
+			   	$ini = file_get_contents($modulePath . '/config.ini');
+				// Perform environment replacement
+				$ini = str_replace('[MODULE_PATH]',  $modClass->modulePath,   $ini);
+				$ini = str_replace('[MODULE_ROOT]',  $modClass->moduleRoot,   $ini);
+				$ini = str_replace('[MODULE_STATIC]',$modClass->moduleStatic, $ini);
+
+				$ini = str_replace('[HOME]', HOME, $ini);
+				$ini = str_replace('[SITE_ROOT]', SITE_ROOT, $ini);
+
+				// Parse the env-replaced content
+				$moduleSettings   = parse_ini_string($ini);
+				// Append (union) with global settings. += ensures that
+				// application settings always override module settings.
+				$this->settings  += $moduleSettings;
+			}
+			
+			// Return the configuration object
+			return $modClass;
+		} else {
+			return false;
+		}
+	}
+	
+	public function getModuleContext($which = null) {
+		
+		// If a module is requesting its own context...
+		if ( $which === null ) {
+			$req = ($this->subrequest != null) 
+				? $this->subrequest
+				: $this->request;
+			$uri = ltrim($req->uri,'/');
+			$moduleName = substr($uri,0,strpos($uri,'/'));
+							
+			return (!empty($moduleName)) 
+				? $this->loadModule($moduleName)
+				: false;
+		} 
+				
+		// otherwise, return the result of an attempt to load the module
+		return $this->loadModule($which);
+	}
+	
+	public static function SetMessage($content,$level = CAS_MSG_INFO) {
+		
+		switch ($level) {
+			case CAS_MSG_WARN:
+				$_SESSION['_messages'][] = '<div class="cas_msg warn">'  . $content . '</div>';
+				break;
+			case CAS_MSG_ERROR:
+				$_SESSION['_messages'][] = '<div class="cas_msg error">' . $content . '</div>';
+				break;
+			default:
+				$_SESSION['_messages'][] = '<div class="cas_msg info">'  . $content . '</div>';
+				break;
+		}
+	}
+	
+	public static function GetMessages() {
+		$response = isset($_SESSION['_messages']) 
+			? implode('', $_SESSION['_messages'])
+			: false;
+		unset($_SESSION['_messages']);
+		return $response;
+	}
+	
+	public function fatal($message) {
+		ApplicationResponse::sendFatal($message);
+		exit();
+	}
+	
+	public static function EndUserSession() {
+		// Unset all of the session variables.
+		$_SESSION = array();
+		
+		// Finally, destroy the session.
+		session_destroy();
+	}
+
+	public static function Redirect($newLocation) {
+		header("Location: {$newLocation}");
+		exit();
+	}
+	
+	/**
+	 * Returns an instance of the requested DataProvider class, ensuring
+	 * that all necessary prerequisites are correctly loaded. To load a 
+	 * custom DataProvider. The framework looks for a matching data
+	 * provider according to the following heirarchy, stopping when 
+	 * it first finds a matching class: If the request involves a module,
+	 * that module's /classes/dataProviders directory is checked, 
+	 * otherwise/then the application's classes/dataProviders directory 
+	 * is checked, and finally (if no match found yet) the webapp-base
+	 * /classes/dataProviders directory is checked.
+	 * Data providers must be named <ProviderName>.class.php, and must 
+	 * implement the IApplicationDataProvider interface.
+	 * 
+	 * @param $class        string  The name of the DataProvider class
+	 * @param $options      array   optional array of constructor options.
+	 * 						These are flowed down to the DataProvider's 
+	 * 						constructor function.
+	 * @return the data provider (must implement IApplicationDataProvider)
+	 * 
+	 * Example: to get an instance of a data provider:
+	 * 	  $p = $app->GetDataProvider('<ProviderName>');
+	 * 
+	 * Example 2: to get an instance and pass options to the constructor
+	 *    $p = $app->GetDataProvider('<ProviderName>',array('opt1'=>'val1'));
+	 *    
+	 * Note that this will not attempt to connect to your data provider.
+	 * All implementations of IApplicationDataProvider offer a ::connect()
+	 * function, which should be invoked on the returned class to initiate
+	 * a connection.
+	 * 
+	 */
+	public function getDataProvider($class,$options = array()) {
+		require_once( "Org/Apache/Oodt/Balance/Interfaces/IApplicationDataProvider.php");
+		$dataProviderPath = "/classes/dataProviders/{$class}.class.php";
+		
+		// Check for the requested data provider in one of 3 locations. It could be:
+		// 1) Part of a module
+		if ($this->request->isModule && 
+			is_file($this->request->moduleBase . $dataProviderPath)) {
+			require_once($this->request->moduleBase . $dataProviderPath);
+			
+			return new $class($options);
+		}
+		
+		// 2) Part of the application's widget collection
+		if (is_file(HOME . $dataProviderPath)) {
+			require_once(HOME . $dataProviderPath);
+			return new $class($options);
+		}
+		
+		// 3) Part of the webapp-base widget collection
+		if (is_file(LIB . $dataProviderPath)) {
+			require_once(LIB . $dataProviderPath);
+			return new $class($options);
+		}
+		return false;
+	}
+	
+	public function getErrorProvider(
+		$class = 'Org_Apache_Oodt_Balance_Providers_Error_DefaultErrorProvider',
+		$options = array()) {
+		
+		return new $class;
+	}
+	
+	
+	/**
+	 * Create an instance of the requested widget class. 
+	 * @deprecated
+	 * @param unknown_type $class
+	 * @param unknown_type $options
+	 */
+	public function createWidget($class,$options = array()) {
+		
+		require_once( "Org/Apache/Oodt/Balance/Interfaces/IApplicationWidget.php");
+		
+		$classPath = "/scripts/widgets/{$class}.php";
+		
+		// Check for the requested widget in one of 2 locations. It could be:
+		// 1) Part of a module
+		if ($this->request->isModule && 
+			is_file($this->request->moduleBase . $classPath)) {
+			require_once($this->request->moduleBase . $classPath);
+			return new $class($options);
+		}
+		
+		// 2) Part of the application's widget collection
+		if (is_file(HOME . $classPath)) {
+			require_once(HOME . $classPath);
+			return new $class($options);
+		}
+		
+		// No widget matching $class found...
+		return false;
+	}
+	
+	/**
+	 * Take any application view and 'widgetize' it. This allows developers to nest
+	 * application views, allowing for greater modularity and reuse.
+	 * 
+	 * As an example: given an application with URIs  /foo/bar and foo/baz (corresponding
+	 * to HOME/views/foo/bar.php and HOME/views/foo/baz.php), the content of /foo/baz can
+	 * be 'widgetized' (nested) within /foo/bar simply by calling this function from somewhere
+	 * within the host view (/foo/bar):
+	 * 
+	 * <div>
+	 *   <?php App::Get()->widgetizeView('/foo/baz');
+	 * </div>
+	 * 
+	 * will produce:
+	 * 
+	 * <div>
+	 *   <div class="bal_widget">...contents of HOME/views/foo/baz.php...</div>
+	 * </div>
+	 * 
+	 * The `cssClasses` parameter allows for specifying any css class definitions that should
+	 * be applied to the widget container. For example:
+	 * 
+	 * App::Get()->widgetizeView('/foo/baz','someClass someOtherClass');
+	 * 
+	 * will produce:
+	 * 
+	 * <div>
+	 *   <div class="bal_widget someClass someOtherClass">...contents...</div>
+	 * </div>
+	 * 
+	 * @param string $contentPath  The URI to the view to widgetize
+	 * @param string $cssClasses   Any css classes to append to the widget's `classes` attribute
+	 * @param mixed  $options      An array of options (for the future... none defined yet)
+	 */
+	public function widgetizeView($contentPath,$cssClasses = '',$options = array()) {
+	
+		// Create a request object for the content to be widgetized
+		$request  = $this->subrequest = new Org_Apache_Oodt_Balance_Core_ApplicationRequest(
+			$this->settings,$contentPath);
+			
+		// Store the application request object prior to processing this nested request
+		$parentRequest = $this->request;
+		
+		// Store the nested request in the application so that it can be accessed as
+		// expected via App::Get()->request (for accurate segment processing, for example)
+		$this->request = $request; 	
+		
+		// Generate a response for the nested request
+		$response = new Org_Apache_Oodt_Balance_Core_ApplicationResponse(
+			$this->settings,$request);
+		$response->process(array('skipHeader' => true,'skipFooter' => true,'skipHooks' => true));
+		
+		//TODO: Process any options (still need to define the options available)
+		
+		// send the wigitized content
+		echo '<div class="bal_widget ' . $cssClasses . '">'
+			. $response->getViewContent()
+			. '</div>';
+			
+		// Restore the application request
+		$this->request    = $parentRequest;
+		$this->subrequest = null;
+	}
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Core/ApplicationDataResponse.class.php b/0.8.1-rc1/balance/lib/pear/Core/ApplicationDataResponse.class.php
new file mode 100644
index 0000000..f68d12b
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Core/ApplicationDataResponse.class.php
@@ -0,0 +1,81 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * ApplicationDataResponse provides a standard response object for use by application
+ * data providers. 
+ * 
+ * The ApplicationDataResponse works off of the idea that the KEY=>VALUE paradigm
+ * is more or less universal and suits (or is at least compatible with) a broad array
+ * of data sources. By guaranteeing that all data providers will return objects of this type
+ * in response to data requests, it is possible to simplify the process of integrating
+ * and assimilating data from multiple heterogeneous sources
+ * 
+ * @author ahart
+ * 
+ */
+class Org_Apache_Oodt_Balance_Core_ApplicationDataResponse {
+	
+	public $requestString;
+	public $data;
+	public $errorOccurred;
+	public $errorMessage;
+	
+	public function __construct($seed = array()) {
+		$this->data = $seed;
+		$this->errorOccurred = false;
+	}
+	
+	public function size() {
+		return count($this->data);
+	}
+	
+	public function count() {
+		return count($this->data);
+	}
+	
+	public function add($key,$value) {
+		$this->data[$key] = $value;
+	}
+	
+	public function bulkAdd($data) {
+		$this->data = array_merge($this->data,$data);
+	}
+	
+	public function get($key) {
+		return (isset($this->data['key']))
+			? $this->data['key']
+			: false;
+	}
+	
+	public function setRequestString($request) {
+		$this->requestString = $request;
+	}
+	
+	public function error() {
+		return ($this->errorOccurred);
+	}
+	
+	public function setError($message) {
+		$this->errorOccurred = true;
+		$this->errorMessage  = true;
+	}
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Core/ApplicationRequest.class.php b/0.8.1-rc1/balance/lib/pear/Core/ApplicationRequest.class.php
new file mode 100644
index 0000000..c5d4015
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Core/ApplicationRequest.class.php
@@ -0,0 +1,169 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * ApplicationRequest: Provides methods for interpreting and processing
+ * a resource request.
+ * 
+ * @author ahart
+ * 
+ */
+class Org_Apache_Oodt_Balance_Core_ApplicationRequest {
+	
+	public $isScript;
+	
+	public $config;
+	
+	public $uri;
+	
+	public $segments;
+	
+	public $data;
+	
+	public $viewPath;
+	
+	public $scriptPath;
+	
+	public $isModule;
+	
+	public $modulePath;	// Filesystem path for module
+
+	public $moduleRoot;	// URL base for module
+
+	public $moduleStatic;	// URL base for  static module assests (images,css,js,etc)
+
+	public function __construct($config,$requestURI) {
+		
+		// Determine if this request is a script or a view
+		$this->isScript = $this->isScript($requestURI);
+	
+		// Store the config as provided
+		$this->config = $config;
+		
+		// Store the uri as provided
+		$this->uri = htmlentities($requestURI);
+		
+		// Initialize the segments and view path
+		$this->segments = array();
+		$this->viewPath = false;
+		
+		// Store data associated with the request
+		$this->data = $_GET;
+		$this->data = array_merge($this->data,$_POST);
+		
+		if ($this->isScript) {
+			$this->processAsScript();
+		} else {
+			$this->processAsView();
+		}
+	} 
+	
+	protected function processAsView() {
+		// Determine the view to use
+		list($thePage) = explode('index.php',$this->uri);
+		$thePage = ltrim($thePage,'/');
+
+		if ($thePage == '') { $thePage = 'index'; }	
+		$parts = explode('/',$thePage);
+
+		// Determine whether a module is being requested
+		$module = App::Get()->isModule($thePage);
+		
+		if ($module) {
+			$this->isModule   = true;
+			$this->modulePath   = $module->modulePath;
+            $this->moduleRoot   = $module->moduleRoot;
+            $this->moduleStatic = $module->moduleStatic;
+			array_shift($parts);
+		}
+
+		// Starting with the full request string, test for the existance of
+		// a corresponding view. If none is found in the HOME
+		// directory, chop off the last segment and try again. Add the chopped
+		// segment to the "segments" array since it is likely a parameter.
+		$partCount = count($parts);
+		while ($partCount > 0) {
+			$testPath    = implode('/',$parts);
+			$homeTest    = (($this->isModule) ? "{$this->modulePath}/views" : $this->config['views_dir']) . '/' . $testPath . '.php';
+			$homeIdxTest = (($this->isModule) ? "{$this->modulePath}/views" : $this->config['views_dir']) . '/' . $testPath . '/index.php';
+			
+			
+			if (is_file($homeTest)) { 
+				$this->viewPath = $homeTest;
+				break;
+			}
+			if (is_file($homeIdxTest)) {
+				$this->viewPath = $homeIdxTest;
+				break;
+			}
+			
+			// If here, neither is a valid view, so chop the last segment
+			$this->segments[] = $parts[$partCount - 1];
+			array_pop($parts);
+			$partCount--;
+		}
+		
+		// If no view has been found by this point, display a 404 message
+		if (!$this->viewPath) {
+			$this->viewPath = dirname(dirname(__FILE__)) . "/views/error/404.php";
+		}
+		
+		// Reverse the segments array so that params appear in the proper order
+		$this->segments = array_reverse($this->segments);
+	}
+	
+	protected function processAsScript() {
+		
+		// Determine the desired script
+		list($theScript) = explode("_init.php",$this->uri);
+		if ($GLOBALS['app']->settings['site_root'] != '/') {
+			$theScript   = str_replace($GLOBALS['app']->settings['site_root'],'',$theScript);
+		}
+		$theScript       = str_replace(".do",".php",$theScript);
+		$theScript       = strpos($theScript,'?') 
+			? substr($theScript,0,strpos($theScript,'?'))
+			: $theScript;
+		$theScript       = ltrim($theScript,'/');
+		$module          = $GLOBALS['app']->isModule($theScript);
+		if ($module) {
+			$this->isModule   = true;
+			$this->modulePath   = $module->modulePath;
+            $this->moduleRoot   = $module->moduleRoot;
+            $this->moduleStatic = $module->moduleStatic;
+			$theScript        = substr($theScript,strpos($theScript,'/')+1);
+			$path             = $module->modulePath . "/scripts/{$theScript}";
+		} else {
+			$path = HOME . "/scripts/{$theScript}";
+		}
+		
+		$this->scriptPath   = $path;
+	}
+	
+	
+	protected function isScript($requestURI) {
+		// Is this a script? (does the script filename end in .do?)
+		$test = $requestURI;
+		if (strpos($test,'?')) {
+			$test = substr($test,0,strpos($test,'?'));
+		}
+		return (substr($test,-3,3) == '.do');
+	}
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Core/ApplicationResponse.class.php b/0.8.1-rc1/balance/lib/pear/Core/ApplicationResponse.class.php
new file mode 100644
index 0000000..e2e9b8d
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Core/ApplicationResponse.class.php
@@ -0,0 +1,311 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * ApplicationResponse: Provides functions for dynamically constructing
+ * and delivering a response to a resource request.
+ * 
+ * @author ahart
+ * 
+ */
+class Org_Apache_Oodt_Balance_Core_ApplicationResponse {
+	
+	protected $config;
+	protected $request;
+	
+	protected $headers;
+	
+	protected $header;
+	protected $view;
+	protected $footer;
+	
+	protected $stylesheets = array();
+	protected $javascripts = array();
+	
+	protected $data;
+
+	const DYN_JS_TAG  = '<!-- JAVASCRIPTS -->';
+	const DYN_CSS_TAG = '<!-- STYLESHEETS -->';
+	
+	/**
+	 * Constructor
+	 * 
+	 * @param array $config
+	 * @param Org_Apache_Oodt_Balance_Core_ApplicationRequest $request
+	 */
+	public function __construct($config, 
+		Org_Apache_Oodt_Balance_Core_ApplicationRequest $request) {
+		
+		$this->config   = $config;
+		
+		$this->request = $request;
+		
+		$this->headers  = array();
+		
+		$this->header   = HOME . "/{$config['header_file_path']}";
+		$this->footer   = HOME . "/{$config['footer_file_path']}";
+	}
+	
+	/**
+	 * Generates a response by processing the requested view,
+	 * including any header and footer views (if needed) as specified
+	 * by the application config file.
+	 * 
+	 * Available options:
+	 *   skipHeader: boolean (default = false) If present, omits header processing
+	 *   skipFooter: boolean (default = false) If present, omits footer processing
+	 *   skipHooks:  boolean (default = false) If present, omits hook processing
+	 *
+	 * @param array $options
+	 */
+	public function process($options = array()) {
+		
+		// Merge defaults with provided options
+		$defaults = array(
+			'skipHeader' => false,
+			'skipFooter' => false,
+			'skipHooks'  => false,
+		);
+		$options += $defaults;
+		
+		if (!$options['skipHooks']) {
+		   // Include the appropriate hooks.php file
+		   include ((App::Get()->request->isModule
+		   	   ? App::Get()->request->modulePath
+			   : HOME ) . '/hooks.php');
+
+		   // Run 'before_all' hook for all requests
+		   if (function_exists('hook_before_all')) {
+		      hook_before_all();
+		   }
+		}
+
+		// Preprocessing for a view
+		if (!$this->request->isScript) {
+			ob_start();	// Start buffering the output
+			
+			// Check that the requested view exists
+			if (file_exists($this->request->viewPath)) {
+				
+				// Run the beforeView hook
+				if (!$options['skipHooks'] && function_exists('hook_before_view')) {
+					hook_before_view();
+				}
+				// Process the view
+				include($this->request->viewPath);
+			} else { 
+				include(HOME . "/views/errors/404.php"); // 404 error page
+			}
+			
+			$this->view = ob_get_contents();
+			ob_clean();
+			
+			// Determine the header view (if any) to include
+			if (!$options['skipHeader'] && $this->header && is_file($this->header)) {
+				// Run the beforeHeader hook
+				if (!$options['skipHooks'] && function_exists('hook_before_header')) {
+					hook_before_header();
+				}
+				
+				// Process the header
+				if (!empty($this->header)) {include($this->header);}
+
+				$this->header = ob_get_contents();
+				ob_clean();
+			}
+			
+			// Determine the footer view (if any) to include
+			if (!$options['skipFooter'] && $this->footer && is_file($this->footer)) {
+				// Run the beforeFooter hook
+				if (!$options['skipHooks'] && function_exists('hook_before_footer')) {
+					hook_before_footer();
+				}
+				
+				// Process the footer
+				if (!empty($this->footer)) {include($this->footer);}
+				
+				$this->footer = ob_get_contents();
+				ob_clean();
+			}
+
+			ob_end_clean();	// Stop buffering the output
+		} else {
+			require_once( $this->request->scriptPath );
+			exit();
+		}
+	}
+	
+	/**
+	 * Actually sends the response (using 'echo') out to the 
+	 * client's browser.
+	 */
+	public function send() {
+		
+		if ($this->request->isScript) {	
+			if (is_file($this->request->scriptPath)) {
+				require_once($this->request->scriptPath);
+			} else {
+				header("Location: " . SITE_ROOT . "/errors/404");
+			}
+		} else {
+			// Process any dynamically added content
+			$this->processDynamicContent();
+			
+			// Run the beforeSend hook
+			if (function_exists('hook_before_send')) {
+				hook_before_send();
+			}
+			foreach ($this->headers as $header) {
+				header($header);
+			}
+			if ($this->header) {
+				echo $this->header;
+			}
+			echo $this->view;
+			if ($this->footer) {
+				echo $this->footer;
+			}
+			// Run the afterSend hook
+			if (function_exists('hook_after_send')) {
+				hook_after_send();
+			}
+		}
+	}
+
+	public static function sendFatal($message) {
+		// Store the message in the session
+		$_SESSION['fail_message'] = $message;
+		
+		// Clear any old output and restart buffering the output
+		ob_clean();
+		ob_start();
+	
+		// Build the 404 error page
+		include(LIB . "/views/errors/fail.php");
+		
+		// Get the contents as a string and flush the buffer
+		$content = ob_get_contents();
+		
+		// Stop buffering output
+		ob_end_clean();
+		
+		// Send the response
+		echo $content;
+		
+		exit();
+	}
+	
+	/**
+	 * Replace special tags with their dynamically assigned content. Currently, the only
+	 * special tags are for defining an area for CSS and JavaScript imports.
+	 * 
+	 */
+	protected function processDynamicContent() {
+		
+		// Dynamically insert CSS
+		$this->header = str_replace(self::DYN_CSS_TAG,implode("\r\n",$this->stylesheets),$this->header);
+		$this->view   = str_replace(self::DYN_CSS_TAG,implode("\r\n",$this->stylesheets),$this->view);
+		$this->footer = str_replace(self::DYN_CSS_TAG,implode("\r\n",$this->stylesheets),$this->footer);
+		
+		// Dynamically insert JS
+		$this->header = str_replace(self::DYN_JS_TAG,implode("\r\n",$this->javascripts),$this->header);
+		$this->view   = str_replace(self::DYN_JS_TAG,implode("\r\n",$this->javascripts),$this->view);
+		$this->footer = str_replace(self::DYN_JS_TAG,implode("\r\n",$this->javascripts),$this->footer);
+		
+	}
+	
+	public function useHeaderFile($path) {
+		$this->header = $path;
+	}
+	
+	public function useFooterFile($path) {
+		$this->footer = $path;
+	}
+	
+	public function sendHeader($headerContent) {
+		$this->headers[] = $headerContent;
+	}
+	
+	public function getHeaderContent() {
+		return $this->header;
+	}
+	public function getViewContent() {
+		return $this->view;
+	}
+	public function getFooterContent() {
+		return $this->footer;
+	}
+
+	public function data($key = null, $value = null) {
+	       
+		// Return the data store associated with this request
+		if ($key == null && $value == null) {
+			return $this->data;
+		}
+					
+		// Return the stored value for the provided key
+		if ($value == null) {
+			return isset($this->data[$key]) 
+				? $this->data[$key] 
+				: null;
+		}
+															   
+		// Set the stored value for the key to the provided value
+		$this->data[$key] = $value;
+	}
+	
+	public function addStylesheet($href,$condition='') {
+		// Build the string for the css import
+		$str = "<link rel=\"stylesheet\" type=\"text/css\" href=\"{$href}\"/>";
+		if (!empty($condition)) {
+			$str = "<!--[if {$condition}]>{$str}<![endif]-->";
+		}
+		$this->stylesheets[] = $str;
+	}
+	
+    /**
+     * Add javascript resources to the response
+     *
+     * This function provides a clean way to programmatically include arbitrary
+     * Javascript resources in the response. Depending upon the value
+     * provided for 'isRaw', the contents of 'src' will either be interpreted
+     * as the 'src' attribute or the body content of the generated <script> block. 
+     *
+     * @param string src - Either the url to the resource to include (if 
+     *                     'isRaw' = false) or a string representing the 
+     *                     raw Javascript to include (if 'isRaw' = true)
+     * @param boolean isRaw - Controls how 'src' is interpreted. If set to false 
+     *                     (default), 'src' will be interpreted as a URL to the
+     *                     Javascript resource to include. If set to true, 'src' 
+     *                     will be interpreted as a string of raw Javascript.
+     */
+	public function addJavascript($src, $isRaw = false) {
+        if ($isRaw === true) {
+            // Build a script container for the raw javascript
+            $str = "<script type=\"text/javascript\">{$src}</script>";
+            $this->javascripts[] = $str;
+        } else {
+            // Build the string for the javascript file import
+            $str = "<script type=\"text/javascript\" src=\"{$src}\"></script>";
+            $this->javascripts[] = $str;
+        }
+	}
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationAuthenticationProvider.php b/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationAuthenticationProvider.php
new file mode 100644
index 0000000..23e3975
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationAuthenticationProvider.php
@@ -0,0 +1,162 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * IApplicationAuthenticationProvider defines an interface that should be 
+ * implemented by all authentication providers to simplify the process of 
+ * accessing and retrieving information about the underlying system. 
+ * 
+ * The interface defines five mandatory functions:
+ *    - __construct: Provide any necessary configuration information but do
+ *               not actually establish a connection to the underlying system.
+ *    - connect: This function does the work of actually connecting to the 
+ *               underlying system. Options can be provided either here or in 
+ *               the constructor arguments (or both), but the connection to the 
+ *               underlying system should not be initiated until this function 
+ *               is invoked.
+ *    - disconnect: Disconnect from the underlying system, performing any
+ *               necessary clean up operations in the process.
+ *    - checkLogin: Check if a valid user has logged in.
+ *    - login:   Determine the ability to gain access to the underlying system 
+ *    			 as a legitimate user. The requirements are a valid username 
+ *    			 (or user ID) and password.
+ *    - logout:  Ending the user's session to the underlying system.
+ *               
+ *               
+ *   Framework implementations of common authentication providers can be found in:
+ *   {LIB}/classes/authenticationProviders   and should be named FooAuthenticationProvider.class.php.
+ *   Framework authentication providers can be invoked by doing:
+ *          $app->GetAuthenticationProvider('FooAuthenticationProvider');
+ *   
+ *   Custom authentication providers should be placed in:
+ *   {HOME}/classes/authenticationProviders  and should be named FooAuthenticationProvider.class.php.
+ *   Custom authentication providers can be invoked by doing:
+ *          $app->GetAuthenticationProvider('foo',true); // true --> custom
+ * 
+ * @author s.khudikyan
+ * 
+ */
+interface Org_Apache_Oodt_Balance_Interfaces_IApplicationAuthenticationProvider {
+	
+	/**
+	 * Constructor - Instantiate the provider but do not yet connect
+	 * to the underlying system.
+	 * 
+	 */
+	public function __construct();
+	
+	/**
+	 * Initiate a connection to the underlying system.
+	 * 
+	 * @return boolean            True or false depending on the result
+	 */
+	public function connect();
+	
+	/**
+	 * Disconnect from the underlying system and perform any cleanup 
+	 * operations necessary.
+	 * 
+	 * @return boolean 		      True or false depending on the result
+	 */
+	public function disconnect();
+	
+	/**
+	 * Check if a valid user has logged in.
+	 * 
+	 * @return boolean 		      True or false depending on the result
+	 */	
+	public function isLoggedIn();
+	
+	/**
+	 * Determine whether privileges will be granted to a particular user
+	 * using credentials provided.
+	 * 
+	 * @param $username    mixed  The username is usually a string. 
+	 * @param $password    mixed  The password is usually a string. 
+	 * @return mixed	          True or false depending on the success of login
+	 */
+	public function login( $username, $password );
+	
+	/**
+	 * Ending the user's session to the underlying system.
+	 * 
+	 */
+	public function logout();
+	
+	/**
+	 * Get current user's username.
+	 * 
+	 */
+	public function getCurrentUsername();
+	
+	/**
+	 * Change current user's password.
+	 * 
+	 * @param $newPassword string
+	 * @return boolean			   True or false depending on the success of password change
+	 */
+	public function changePassword( $newPassword );
+
+	/**
+	 * Checks if user is logged in. If true, validates rules from config file and uses 
+	 * {@link changePassword} to change password.
+	 * 
+	 * @param $newPass            string  The new password
+	 * @param $encryptionMethod   string  The encryption method used
+	 */
+	public function validateChangePassword( $newPass, $encryptionMethod = "SHA" );
+	
+	/**
+	 * Retrieves the set of attributes from the user's entry 
+	 * 
+	 * @param $username    string  The user for which attributes will be returned
+	 * @param $attributes  array   Attributes to retrieve
+	 * @return array               An empty array or requested attributes
+	 */
+	public function retrieveUserAttributes( $username, $attributes );
+	
+	/**
+	 * Creates a new account with the user information provided
+	 * 
+	 * @param $userInfo    array  Can include different values depending on provider
+	 * 								i.e. username, firstname, lastname, email
+	 */
+	public function addUser( $userInfo );
+	
+	/**
+	 * Uses {@link retrieveUserAttributes} to retrieve information about the provided 
+	 * user. If count of array returned is > 0 then the username is not available.
+	 * 
+	 * @param $username	   string The username for which a user is checking the 
+	 * 								availability of
+	 */	
+	public function usernameAvailability( $username );
+	
+	/**
+	 * Updates user information with the values of provided attributes
+	 * 
+	 * @param $newInfo     array  (key, value) based array, where keys are the user's 
+ 	 * 								entry attribute ids and the values will replace 
+ 	 * 								the values of those attributes 
+	 */
+	public function updateProfile( $newInfo );
+	
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationAuthorizationProvider.php b/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationAuthorizationProvider.php
new file mode 100644
index 0000000..b5bdf48
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationAuthorizationProvider.php
@@ -0,0 +1,62 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * LDAPAuthorizationProvider defines an interface that will determine what level 
+ * of access a particular user should have to secured resources. 
+ * 
+ * The interface defines five mandatory functions:
+ *    - __construct: Provide any necessary configuration information 
+ *               
+ *               
+ *   Framework implementations of common authorization providers can be found in:
+ *   Balance/Providers/Authorization 
+ *   Framework authorization providers can be invoked by doing:
+ *          App:Get()->getAuthorizationProvider();
+ * 
+ * @author s.khudikyan
+ * 
+ */
+
+interface Org_Apache_Oodt_Balance_Interfaces_IApplicationAuthorizationProvider {
+	
+	/**
+	 * Constructor - Instantiate the provider
+	 * 
+	 */
+	public function __construct();
+	
+	/**
+	 * Initiate a connection to the underlying system.
+	 * 
+	 * @return boolean            True or false depending on the result
+	 */
+	public function connect();
+	
+	/**
+	 * Retrieves the set of groups for specified user
+	 * 
+	 * @param $username    string  The user for which groups will be returned
+	 * @return array               An empty array or groups the user belongs to
+	 */
+	public function retrieveGroupsForUser( $username );
+		
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationDataProvider.php b/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationDataProvider.php
new file mode 100644
index 0000000..b78d7a7
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationDataProvider.php
@@ -0,0 +1,125 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * IApplicationDataProvider defines an interface that should be implemented
+ * by all data providers to simplify the process of integrating and accessing
+ * multiple heterogeneous data sources. A data source could be a relational
+ * SQL-like database, a CAS File Manager, an LDAP server, anything that can
+ * be queried for data. 
+ * 
+ * The interface defines five mandatory functions:
+ *    - __construct: Provide any necessary configuration information but do
+ *               not actually establish a connection to the underlying data
+ *               source.
+ *    - connect: This function does the work of actually connecting to the 
+ *               underlying data source. Options can be provided either here
+ *               or in the constructor arguments (or both), but the connection
+ *               to the underlying data source should not be initiated until
+ *               this function is invoked.
+ *    - disconnect: Disconnect from the underlying data source, performing any
+ *               necessary clean up operations in the process.
+ *    - request: Satisfy a request for data. The format that this request takes
+ *               will likely differ across implementations. An array of further
+ *               options may be provided as an optional second argument. As a 
+ *               concrete  example, an SQL-like data source may support string 
+ *               requests like "SELECT * FROM foo WHERE bar='baz'". The 
+ *               response from this call must be an ApplicationDataResponse object
+ *               containing the (possibly multidimensional) array of response info. 
+ *    - command: Send a command to the underlying data source. As with request,
+ *               the format that this command takes will likely differ across
+ *               implementations. As a concrete example, an SQL-like data source
+ *               may support string commands like "UPDATE foo set bar='baz'". 
+ *               Command should not be expected to return a value, other than
+ *               possibly true/false to indicate the success of the call.
+ *               
+ *               
+ *   Framework implementations of common data providers can be found in:
+ *   {LIB}/classes/dataProviders   and should be named FooDataProvider.class.php.
+ *   Framework data providers can be invoked by doing:
+ *          $app->GetDataProvider('FooDataProvider');
+ *   
+ *   Custom data providers should be placed in:
+ *   {HOME}/classes/dataProviders  and should be named FooDataProvider.class.php.
+ *   Custom data providers can be invoked by doing:
+ *          $app->GetDataProvider('foo',true); // true --> custom
+ * 
+ * @author ahart
+ * 
+ */
+interface Org_Apache_Oodt_Balance_Interfaces_IApplicationDataProvider {
+	
+	/**
+	 * Constructor - Instantiate the provider but do not yet connect
+	 * to the underlying data source.
+	 * 
+	 * @param $options  array   An optional set of configuration values
+	 */
+	public function __construct($options = array());
+	
+	/**
+	 * Initiate a connection to the underlying data source
+	 * 
+	 * @param $options  array  An optional set of configuration values
+	 * @return boolean         True or false depending on the result
+	 */
+	public function connect($options = array());
+	
+	/**
+	 * Disconnect from the underlying data source and perform any
+	 * cleanup operations necessary.
+	 * 
+	 * @param $options  array  An optional set of configuration values
+	 * @return unknown_type    True or false depending on the result
+	 */
+	public function disconnect($options = array());
+	
+	/**
+	 * Request data from the underlying data source.
+	 * 
+	 * @param $request  mixed  The request itself, usually a string. The nature
+	 *                         of the request is necessarily implementation 
+	 *                         specific and will vary across providers. For a 
+	 *                         SQL-like relational provider, this will likely be
+	 *                         a "SELECT ..." string.
+	 * @param $options  array  An array of options to configure the request.
+	 *                         These will be implementation-specific and 
+	 *                         therefore will likely differ across providers.
+	 * @return ApplicationDataResponse  The resulting data retrieved
+	 */
+	public function request($request,$options = array());
+	
+	/**
+	 * Send a command to the underlying data source.
+	 * 
+	 * @param $command mixed   The command itself, usually a string. The nature
+	 *                         of the command is necessarily implementation 
+	 *                         specific and will vary across providers. For a 
+	 *                         SQL-like relational provider, this will likely be
+	 *                         a "UPDATE ...", or "CREATE ..." string.
+	 * @param $options  array  An array of options to configure the command.
+	 *                         These will be implementation-specific and 
+	 *                         therefore will likely differ across providers.
+	 * @return boolean         True or false depending on the success of the command
+	 */
+	public function command($command,$options = array());
+	
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationErrorProvider.php b/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationErrorProvider.php
new file mode 100644
index 0000000..63262a1
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationErrorProvider.php
@@ -0,0 +1,39 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * IApplicationErrorProvider defines an interface that should be implemented
+ * by all error providers to simplify the process of formatting and displaying
+ * application errors.
+ * 
+ * 
+ * @author ahart
+ */
+interface Org_Apache_Oodt_Balance_Interfaces_IApplicationErrorProvider {
+	
+	/**
+	 * Causes an error response to be sent to the sender
+	 * 
+	 * @param integer $httpResponseCode  The HTTP response code to send
+	 * @param string  $message           A contextual message to include or log
+	 */
+	public function error($httpResponseCode,$message = '',$options=array());
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationWidget.php b/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationWidget.php
new file mode 100644
index 0000000..b1e4831
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Interfaces/IApplicationWidget.php
@@ -0,0 +1,67 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * Interface for developing widgets (reusable bits of view code) that can
+ * be placed on different application pages.
+ * 
+ * This interface defines two mandatory functions:
+ *  - construct : Intialize the widget and provide any necessary 
+ *                configuration information
+ *  - render    : Build the HTML output that constitutes the widget. This
+ *                function does not accept arguments (any config should
+ *                be provided either in the controller or via other "set"
+ *                functions. This function should return a string composed
+ *                of the final HTML output of the widget.
+ *        
+ * Framework widgets can be found inside the {LIB}/scripts/widgets directory.              
+ * 
+ * Framework Widgets can be invoked from view code as follows:
+ *    // Create an instance of the widget (will transparently call __construct)
+ *    $myFooWidget = $app->createWidget('FooWidget',array(..config..))
+ *  
+ * Custom widgets should be placed inside the {HOME}/scripts/widgets directory and 
+ * can be named FooWidget.php. All widgets must implement this interface.
+ * 
+ * Custom Widgets can be invoked from view code as follows:
+ *    // Create an instance of the widget (will transparently call __construct)
+ *    $myFooWidget = $app->createWidget('FooWidget',array(..config..),true) // true --> custom
+ * 
+ * <!-- (all widgets, framework or custom): display widget contents -->
+ * <span><?php echo $myFooWidget->render()?></span>
+ * 
+ * @author ahart
+ * 
+ */
+interface Org_Apache_Oodt_Balance_Interfaces_IApplicationWidget {
+	
+	public function __construct($options = array());
+	
+	/**
+	 * Build the HTML output that constitutes the widget.
+	 * 
+	 * @param boolean $bEcho (default = true) If true, the function should
+	 *        echo the contents directly. If false, the contents should be
+	 *        returned as a string.
+	 */
+	public function render($bEcho = true);
+	
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Providers/Authentication/LDAPAuthenticationProvider.class.php b/0.8.1-rc1/balance/lib/pear/Providers/Authentication/LDAPAuthenticationProvider.class.php
new file mode 100644
index 0000000..9e4c6f9
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Providers/Authentication/LDAPAuthenticationProvider.class.php
@@ -0,0 +1,170 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * Implementation of iApplicationAuthenticationProvider, which extends SingleSignOn.
+ * 
+ * Note: This class has a dependency on the OODT CAS-SSO package.
+ *		The necessary files can be found at http://pear.apache.org/oodt/
+ *		along with installation instructions.
+ * 
+ * @author s.khudikyan
+ * @author ahart
+ * 
+ */
+require("Org/Apache/Oodt/Security/SingleSignOn.php");
+
+class Org_Apache_Oodt_Balance_Providers_Authentication_LDAPAuthenticationProvider
+	extends Org_Apache_Oodt_Security_SingleSignOn 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationAuthenticationProvider {
+
+	/**
+	 * If authentication config file exists, require(file_name) file
+	 */
+	public function __construct() {
+		
+		// set LDAP constants
+		define("CAS_SECURITY",true);
+		define("SSO_LDAP_HOST", App::Get()->settings['ldap_host']);
+		define("SSO_LDAP_PORT", App::Get()->settings['ldap_port']);
+		define("SSO_BASE_DN", App::Get()->settings['ldap_base_dn']);
+		define("SSO_GROUPS_DN", App::Get()->settings['ldap_group_dn']);
+		define("SSO_COOKIE_KEY", App::Get()->settings['cookie_key']);
+		
+	}
+	
+	public function connect() {
+		return parent::connect(func_get_arg(0),func_get_arg(1));
+	}
+	
+	public function disconnect() {
+		
+	}
+	
+	public function isLoggedIn() {
+		return parent::isLoggedIn();
+	}
+	
+	public function login( $username, $password ) {
+		return parent::login( $username, $password );
+	}
+	
+	public function logout() {
+		parent::logout();
+	}
+
+	public function getCurrentUsername() {
+		return parent::getCurrentUsername();
+	}
+	
+	public function changePassword( $newPassword ) {
+		if ( App::Get()->settings['authentication_encryption_method'] ) {
+			return parent::changePassword( $newPassword, App::Get()->settings['authentication_encryption_method'] );
+		}
+		return parent::changePassword( $newPassword );
+	}
+	
+	public function validateChangePassword( $newPass, $encryptionMethod = "SHA" ) {
+		$isValid = true;
+		$messages = array();
+		// validate rules from config file
+		$rules = App::Get()->settings['security_password_rules'];
+
+		if ( isset($rules) ) {
+			foreach( $rules as $rule ){
+				
+				// Separate the rule from the error message
+				list($regularExpression,$errorMessage) = explode('|',$rule,2);
+				
+				// Test the rule
+				$rulePassed = preg_match($regularExpression, $newPass);
+				
+				// If the rule failed, append the error message
+				if (!$rulePassed) {
+					$messages[] = $errorMessage;
+					$isValid    = false;
+				}
+			}
+		}
+
+		if ($isValid && $this->connect(SSO_LDAP_HOST,SSO_LDAP_PORT)) {
+		  $result = $this->changePassword($newPass,$encryptionMethod);
+		  return true;
+		} else
+		  return $messages;
+	}
+	
+	public function retrieveUserAttributes( $username, $attributes ) {
+		$rawArray 		= parent::retrieveUserAttributes( $username, $attributes );
+		$userAttributes = array();
+		
+		if ( count($rawArray) > 1 ) {
+			$rawArray = $rawArray[0];
+			// Get only necessary attributes to return
+			foreach ( $rawArray as $key=>$keyValue ) {
+				foreach ( $attributes as $value ) {
+					if ( $key === $value ) {
+						$userAttributes[$key] = $keyValue[0];
+					}
+				}
+			}
+		}
+		return $userAttributes;
+	}
+	
+	public function addUser($userInfo) {
+		$ldapconn = $this->connect(SSO_LDAP_HOST,SSO_LDAP_PORT);
+		if ($ldapconn) {
+			$user  = "uid={$userInfo[ "uid" ]}," . SSO_BASE_DN;
+			return ldap_add($ldapconn,$user,$userInfo);
+		}
+		// connection failed
+		return false;
+	}
+	
+	public function usernameAvailability( $username ) {
+		$justthese = array( App::Get()->settings['username_attr'] );
+		$profile = $this->retrieveUserAttributes($username, $justthese);
+		if (count($profile) > 0) {
+			return false;
+		} else {
+			// available
+			return true;
+		}
+	}
+	
+	public function updateProfile($newInfo) {
+
+		if ($this->isLoggedIn()) {
+			$user  = "uid={$this->getCurrentUsername()}," . SSO_BASE_DN ;
+			$ldapconn = $this->connect(SSO_LDAP_HOST,SSO_LDAP_PORT);
+			
+			if (ldap_mod_replace($ldapconn,$user,$newInfo)) {
+				return true;
+			} else {
+				return false;
+			}
+		} else {
+			return false;
+		}
+	}
+	
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Providers/Authorization/LDAPAuthorizationProvider.class.php b/0.8.1-rc1/balance/lib/pear/Providers/Authorization/LDAPAuthorizationProvider.class.php
new file mode 100644
index 0000000..764dfc8
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Providers/Authorization/LDAPAuthorizationProvider.class.php
@@ -0,0 +1,109 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * IApplicationAuthenticationProvider defines an interface that should be 
+ * implemented by all authentication providers to simplify the process of 
+ * accessing and retrieving information about the underlying system. 
+ * 
+ * The interface defines five mandatory functions:
+ *    - __construct: Provide any necessary configuration information but do
+ *               not actually establish a connection to the underlying system.
+ *    - connect: This function does the work of actually connecting to the 
+ *               underlying system. Options can be provided either here or in 
+ *               the constructor arguments (or both), but the connection to the 
+ *               underlying system should not be initiated until this function 
+ *               is invoked.
+ *    - disconnect: Disconnect from the underlying system, performing any
+ *               necessary clean up operations in the process.
+ *    - checkLogin: Check if a valid user has logged in.
+ *    - login:   Determine the ability to gain access to the underlying system 
+ *    			 as a legitimate user. The requirements are a valid username 
+ *    			 (or user ID) and password.
+ *    - logout:  Ending the user's session to the underlying system.
+ *               
+ *               
+ *   Framework implementations of common authentication providers can be found in:
+ *   {LIB}/classes/authenticationProviders   and should be named FooAuthenticationProvider.class.php.
+ *   Framework authentication providers can be invoked by doing:
+ *          $app->GetAuthenticationProvider('FooAuthenticationProvider');
+ *   
+ *   Custom authentication providers should be placed in:
+ *   {HOME}/classes/authenticationProviders  and should be named FooAuthenticationProvider.class.php.
+ *   Custom authentication providers can be invoked by doing:
+ *          $app->GetAuthenticationProvider('foo',true); // true --> custom
+ * 
+ * @author s.khudikyan
+ * 
+ */
+
+class Org_Apache_Oodt_Balance_Providers_Authorization_LDAPAuthorizationProvider 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationAuthorizationProvider {
+	
+	/**
+	 * If authorization config file exists, require(file_name) file
+	 */
+	public function __construct() {
+		// Set LDAP constants
+		define("AUTH_BASE_DN",   App::Get()->settings['authorization_ldap_base_dn']);
+		define("AUTH_GROUPS_DN", App::Get()->settings['authorization_ldap_group_dn']);
+		define("AUTH_LDAP_HOST", App::Get()->settings['authorization_ldap_host']);
+		define("AUTH_LDAP_PORT", App::Get()->settings['authorization_ldap_port']);
+	}
+	
+	public function retrieveGroupsForUser($username,$searchDirectory = AUTH_GROUPS_DN) {
+		
+		// attempt to connect to ldap server 
+		$ldapconn = $this->connect(AUTH_LDAP_HOST,AUTH_LDAP_PORT);
+		$groups   = array();
+		if ($ldapconn) {
+			$filter = "(&(objectClass=groupOfUniqueNames)"
+				."(uniqueMember=uid={$username}," . AUTH_BASE_DN . "))";
+			$result = ldap_search($ldapconn,$searchDirectory,$filter,array('cn'));
+			
+			if ($result) {
+				$entries = ldap_get_entries($ldapconn,$result);
+				foreach ($entries as $rawGroup) {
+					if (isset($rawGroup['cn'][0]) 
+					&& $rawGroup['cn'][0] != '') {
+						$groups[] = $rawGroup['cn'][0];
+					}
+				}
+			}
+		} 
+		return $groups;
+	}
+			
+	public function connect() {
+		if ($conn = ldap_connect(func_get_arg(0),func_get_arg(1))) {
+			// Connection established
+			$this->connectionStatus = 1;
+			ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3);
+			ldap_set_option($conn, LDAP_OPT_DEBUG_LEVEL, 7);
+			ldap_set_option($conn, LDAP_OPT_REFERRALS, 0);	
+			$this->conn = $conn;
+			return $conn;
+		} else {
+			// Connection failed
+			return false;
+		}
+	}		
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Providers/Data/MDB2DataProvider.class.php b/0.8.1-rc1/balance/lib/pear/Providers/Data/MDB2DataProvider.class.php
new file mode 100644
index 0000000..839c02d
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Providers/Data/MDB2DataProvider.class.php
@@ -0,0 +1,137 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * Implementation of IApplicationDataProvider for PEAR MDB2.
+ * 
+ * @author s.khudikyan
+ * @author ahart
+ * 
+ */
+require_once( 'MDB2.php' );
+
+class Org_Apache_Oodt_Balance_Providers_Data_MDB2DataProvider 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationDataProvider {
+	
+	public $link;
+	
+	public function __construct($options = array()) {
+		
+	}
+	
+	public function connect($options = array()) {
+		$dsn = 'mysql://'.$options['username'].':'.$options['password'].'@'.$options['server'].'/'.$options['database'];
+		$this->link = MDB2::singleton( $dsn );
+		
+		if ( PEAR::isError($this->link) ) {
+
+			die("There was an error connecting to the database: " . $this->link->getMessage());
+		}
+	}
+	
+	public function disconnect($options = array()) {
+		if ($this->link) {
+			$this->link->disconnect();
+		}
+	}
+	
+	public function request($request,$options = array() ) { 
+		$data = new Org_Apache_Oodt_Balance_Core_ApplicationDataResponse();
+		
+		if ($this->link) {
+			
+			// Handle associative array
+			if (isset($options['format']) && 
+				strtolower($options['format']) == 'assoc') {
+					
+					// Execute the request and build a response object
+					$result  = $this->link->queryAll($request,null,MDB2_FETCHMODE_ASSOC);
+			}
+
+			// Handle numeric array
+			else {
+				
+				// Execute the request and build a response object
+				$result  = $this->link->queryAll($request,null,MDB2_FETCHMODE_ORDERED);
+			}
+			
+			if ( PEAR::isError($result) ) {
+				
+				$data->setError($result->getMessage());
+				return $data;
+			} else {
+				
+				// Store the request used to generate the data
+				$data->bulkAdd($result);
+				
+				// Free the request
+				$this->link->free();
+				
+				// Return the requested data
+				return $data;
+			}
+		} else {
+			$data->setError("Unable to establish connection to data source");
+			return $data;
+		}
+	}
+	
+	public function command($command,$options = array()) {
+		$data = new Org_Apache_Oodt_Balance_Core_ApplicationDataResponse();
+		
+		if ($this->link) {
+			
+			$result = $this->link->exec($command);
+			
+			if ( PEAR::isError($result) ) {
+				
+				$data->setError($result->getMessage());
+				return $data;
+			}
+		} else {
+			$data->setError("Unable to establish connection to data source");
+			return $data;
+		}
+	}
+	
+	public function lastInsertedId($options = array()){
+		$data = new Org_Apache_Oodt_Balance_Core_ApplicationDataResponse();
+		
+		if ($this->link) {
+			
+			$result = $this->link->lastInsertId();
+			
+			if ( PEAR::isError($result) ) {
+				
+				$data->setError($result->getMessage());
+				return $data;
+			} else {
+							
+				return $result;
+				
+			}
+		} else {
+			$data->setError("Unable to establish connection to data source");
+			return $data;
+		}
+	}
+	
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Providers/Data/MySqlDataProvider.class.php b/0.8.1-rc1/balance/lib/pear/Providers/Data/MySqlDataProvider.class.php
new file mode 100644
index 0000000..fac93c4
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Providers/Data/MySqlDataProvider.class.php
@@ -0,0 +1,128 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * Implementation of IApplicationDataProvider for a MySql database.
+ * 
+ * @author ahart
+ * 
+ */
+class Org_Apache_Oodt_Balance_Providers_Data_MySqlDataProvider 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationDataProvider {
+	
+	public $link;
+	
+	public function __construct($options = array()) {
+		
+	}
+	
+	public function connect($options = array()) {
+		$this->link = mysql_connect($options['server'],
+			$options['username'],
+			$options['password']) or 
+			die("Could not connect: " . mysql_error());
+			mysql_select_db($options['database'],$this->link) or
+			die("Could not select database: " . mysql_error());
+	}
+	
+	public function disconnect($options = array()) {
+		if ($this->link) {
+			mysql_close($this->link);
+		}
+	}
+	
+	public function request($request,$options = array()) {
+		if ($this->link) {
+			
+			// Execute the request and build a response object
+			$raw  = mysql_query($request,$this->link);
+			$data = new Org_Apache_Oodt_Balance_Core_ApplicationDataResponse();
+			
+			if ('' != ($errMessage = mysql_error($this->link))) {
+				$data->setError($errMessage);
+				return $data;
+			} else {
+			
+				// Handle associative array
+				if (isset($options['format']) && 
+					strtolower($options['format']) == 'assoc') {
+					$idx = 0;
+					while (false !== $row = mysql_fetch_assoc($raw)) {
+						if (isset($options['indexKey'])) {
+							$data->add($raw[$options['indexKey']],$row);
+						} else {
+							$data->add($idx++,$row);
+						}
+					}
+				} 
+				
+				// Handle numeric array
+				else {
+					$idx = 0;
+					while (false !== $row = mysql_fetch_row($raw)) {
+						if (isset($options['indexKey'])) {
+							$data->add($raw[$options['indexKey']],$row);
+						} else {
+							$data->add($idx++,$row);
+						}
+					}
+				}
+				
+				// Store the request used to generate the data
+				$data->setRequestString($request);
+				
+				// Free the request
+				mysql_free_result($raw);
+				
+				// Return the requested data
+				return $data;
+			}
+		} else {
+			$data = new Org_Apache_Oodt_Balance_Core_ApplicationDataResponse();
+			$data->setError("Unable to establish connection to data source");
+			return $data;
+		}
+	}
+	
+	public function command($command,$options = array()) {
+		if ($this->link) {
+			
+			mysql_query($command);
+			
+		} else {
+			$data = Org_Apache_Oodt_Balance_Core_ApplicationDataResponse();
+			$data->setError("Unable to establish connection to data source");
+			return $data;
+		}
+	}
+	
+	public function lastInsertedId($options = array()){
+		if ($this->link) {
+			
+			return mysql_insert_id();
+			
+		} else {
+			$data = Org_Apache_Oodt_Balance_Core_ApplicationDataResponse();
+			$data->setError("Unable to establish connection to data source");
+			return $data;
+		}
+	}
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Providers/Data/PDODataProvider.class.php b/0.8.1-rc1/balance/lib/pear/Providers/Data/PDODataProvider.class.php
new file mode 100644
index 0000000..d32530c
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Providers/Data/PDODataProvider.class.php
@@ -0,0 +1,142 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * Implementation of IApplicationDataProvider for PHP PDO.
+ * 
+ * @author s.khudikyan
+ * @author ahart
+ * 
+ */
+class Org_Apache_Oodt_Balance_Providers_Data_PDODataProvider 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationDataProvider {
+	
+	public $link;
+	
+	public function __construct($options = array()) {
+		
+	}
+	
+	public function connect($options = array()) {
+		try {
+			$dsn = 'mysql:host='.$options['server'].';dbname='.$options['database'];
+			$this->link = new PDO( $dsn, $options['username'], $options['password'] );
+		} catch (PDOException $e) {
+			die("There was an error connecting to the database: " . $e->getMessage());
+		}
+	}
+	
+	public function disconnect($options = array()) {
+		if ($this->link) {
+			/*** close the database connection ***/
+    		$this->link = null;
+		}
+	}
+	
+	public function request($request,$options = array() ) {
+		$data = new Org_Apache_Oodt_Balance_Core_ApplicationDataResponse();
+		
+		if ($this->link) {
+			
+			// Handle associative array
+			if (isset($options['format']) && 
+				strtolower($options['format']) == 'assoc') {
+					
+					try {
+						// fetch into an PDOStatement object
+    					$stmt = $this->link->queryAll($request);
+    					$result = $stmt->fetch(PDO::FETCH_ASSOC);
+					} catch (PDOException $e) {
+						
+						$data->setError( $e->getMessage() );
+						return $data;
+					}
+			}
+
+			// Handle numeric array
+			else {
+					try {	
+						// fetch into an PDOStatement object
+    					$stmt = $this->link->queryAll($request);
+    					$result = $stmt->fetch(PDO::FETCH_NUM);
+					} catch (PDOException $e) {
+						
+						$data->setError( $e->getMessage() );
+						return $data;
+					}
+			}
+				
+			// Store the request used to generate the data
+			$data->bulkAdd($result);
+			
+			// Free the request
+			$this->link->free();
+			
+			// Return the requested data
+			return $data;
+
+		} else {
+			$data->setError("Unable to establish connection to data source");
+			return $data;
+		}
+	}
+	
+	public function command($command,$options = array()) {
+		$data = new Org_Apache_Oodt_Balance_Core_ApplicationDataResponse();
+		
+		if ($this->link) {
+			
+			try {
+				
+				$result = $this->link->exec( $command );
+			} catch (PDOException $e) {
+				
+				$data->setError( $e->getMessage() );
+				return $data;
+			}
+			
+		} else {
+			$data->setError( "Unable to establish connection to data source" );
+			return $data;
+		}
+	}
+	
+	public function lastInsertedId($options = array()){
+		$data = new Org_Apache_Oodt_Balance_Core_ApplicationDataResponse();
+		
+		if ($this->link) {
+			
+			try {
+				$lastId = $this->link->lastInsertId();				
+			} catch (PDOException $e) {
+				
+				$data->setError( $e->getMessage() );
+				return $data;
+			}
+			return $lastId;
+			
+		} else {
+			$data->setError("Unable to establish connection to data source");
+			return $data;
+		}
+	}
+	
+}
diff --git a/0.8.1-rc1/balance/lib/pear/Providers/Error/DefaultErrorProvider.class.php b/0.8.1-rc1/balance/lib/pear/Providers/Error/DefaultErrorProvider.class.php
new file mode 100644
index 0000000..6c929f2
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/Providers/Error/DefaultErrorProvider.class.php
@@ -0,0 +1,38 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ * 
+ * A very simple default implementation of the IApplicationErrorProvider 
+ * interface that simply looks for a view in HOME/views/common/###.php where
+ * ### matches the provided http code.
+ * 
+ * @author ahart
+ */
+class Org_Apache_Oodt_Balance_Providers_Error_DefaultErrorProvider 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationErrorProvider {
+		
+
+	public function error($httpResponseCode,$message = '',$options = array()) {
+		require(HOME . '/views/error/' . $httpResponseCode . '.php');
+		exit();
+	}
+		
+}
diff --git a/0.8.1-rc1/balance/lib/pear/README b/0.8.1-rc1/balance/lib/pear/README
new file mode 100644
index 0000000..5254dd1
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/README
@@ -0,0 +1,34 @@
+OODT Balance - Framework Library
+
+OVERVIEW
+====================
+
+This is the OODT Balance Framework library. It provides a common codebase
+upon which to build PHP web applications utilizing the OODT framework.
+
+More information about the project is available at http://oodt.apache.org/
+
+INSTALLATION
+====================
+
+The library is provided as a PHP Extension and Application Repository (PEAR)
+package. More information on how to install the PEAR package manager on your
+system can be found at: http://pear.php.net/manual/en/installation.php
+
+Assuming you have the PEAR package manager installed correctly:
+
+1) "cd" into the src/pear directory (you should see a package.xml file)
+2) Build the pear package: 
+   $ pear package
+3) Install the resulting tarball:
+   $ (sudo) pear install --force Org_Apache_Oodt_Balance_...tgz
+
+
+USAGE
+=====================
+
+This library forms a codebase upon which applications can be developed. It is a
+prerequisite for Balance application development, but can do nothing on its own.
+For information on creating and developing applications that target this library,
+visit http://oodt.apache.org/
+
diff --git a/0.8.1-rc1/balance/lib/pear/package.xml b/0.8.1-rc1/balance/lib/pear/package.xml
new file mode 100644
index 0000000..dc5c5a3
--- /dev/null
+++ b/0.8.1-rc1/balance/lib/pear/package.xml
@@ -0,0 +1,136 @@
+<?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.
+ */
+-->
+<!-- 
+   @package Org_Apache_Oodt_Balance
+   @author Andrew F. Hart
+   @version $Id$
+-->
+<package version="2.0" xmlns="http://pear.php.net/dtd/package-2.0"
+  xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0.xsd
+         http://pear.php.net/dtd/package-2.0
+         http://pear.php.net/dtd/package-2.0.xsd">
+  <name>Apache_OODT_Balance</name>
+  <channel>pear.apache.org/oodt</channel>
+  <summary>OODT Balance Webapp Base Package</summary>
+  <description>
+    This package provides the OODT Balance webapp-base package required
+    by all Balance-based web applications.
+  </description>
+  <lead>
+    <name>Andrew Hart</name>
+    <user>ahart</user>
+    <email>ahart@apache.org</email>
+    <active>yes</active>
+  </lead>
+  <date>2013-06-29</date>
+  <version>
+    <release>0.6.0</release>
+    <api>0.6.0</api>
+  </version>
+  <stability>
+    <release>stable</release>
+    <api>stable</api>
+  </stability>
+  <license uri="http://www.apache.org/licenses/LICENSE-2.0">ASL 2.0 License</license>
+  <notes>
+    This package provides the OODT Balance webapp-base package required
+    by all Balance-based web applications.
+  </notes>
+  <contents>
+    <dir name="/" baseinstalldir="Org/Apache/Oodt/Balance">
+    <dir name="Boot">
+      <file name="bootstrap.php" role="php"/>
+    </dir>
+    <dir name="Core">
+      <file name="Application.class.php" role="php"/>
+      <file name="ApplicationDataResponse.class.php" role="php"/>
+      <file name="ApplicationRequest.class.php" role="php"/>
+      <file name="ApplicationResponse.class.php" role="php"/>
+    </dir>
+    <dir name="Interfaces">
+      <file name="IApplicationAuthenticationProvider.php" role="php"/>
+      <file name="IApplicationAuthorizationProvider.php"  role="php"/>
+      <file name="IApplicationDataProvider.php" role="php"/>
+      <file name="IApplicationErrorProvider.php" role="php"/>
+      <file name="IApplicationWidget.php" role="php"/>
+    </dir>
+    <dir name="Providers">
+      <dir name="Authentication">
+        <file name="LDAPAuthenticationProvider.class.php" role="php"/>
+      </dir>
+      <dir name="Authorization">
+        <file name="LDAPAuthorizationProvider.class.php" role="php"/>
+      </dir>
+      <dir name="Data">
+        <file name="MySqlDataProvider.class.php" role="php"/>
+      </dir>    
+      <dir name="Error">
+        <file name="DefaultErrorProvider.class.php" role="php"/>
+      </dir> 
+    </dir>
+    </dir><!-- / -->
+  </contents>
+  <dependencies>
+    <required>
+      <php>
+        <min>5.1.6</min>
+      </php>
+      <pearinstaller>
+        <min>1.6.1</min>
+      </pearinstaller>
+    </required>
+  </dependencies>
+  <phprelease />
+  <changelog>
+    <release>
+      <version>
+        <release>0.2.0</release>
+        <api>0.2.0</api>
+      </version>
+      <stability>
+        <release>stable</release>
+        <api>stable</api>
+      </stability>
+      <date>2011-02-03</date>
+      <license uri="http://oodt.jpl.nasa.gov">OODT License</license>
+      <notes>
+      Improvements to the core library to support more flexible use
+      of modules and greater reusability.
+      </notes>     
+    </release>
+    <release>
+      <version>
+        <release>0.1.0</release>
+        <api>0.1.0</api>
+      </version>
+      <stability>
+        <release>stable</release>
+        <api>stable</api>
+      </stability>
+      <date>2010-11-01</date>
+      <license uri="http://oodt.jpl.nasa.gov">OODT License</license>
+      <notes>
+      This release marks the first release of the OODT Balance webapp-base package.
+      </notes>     
+    </release>
+  </changelog>
+</package>
diff --git a/0.8.1-rc1/balance/modules/cas-browser/classes/CasBrowser.class.php b/0.8.1-rc1/balance/modules/cas-browser/classes/CasBrowser.class.php
new file mode 100644
index 0000000..583a6c8
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/classes/CasBrowser.class.php
@@ -0,0 +1,455 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ * $Id$
+ * 
+ * CAS-Browser Module
+ * 
+ * This module provides applications a means for browsing a CAS File 
+ * Manager catalog and obtaining products from a CAS File Manager repository.
+ * 
+ * For complete functionality, the following configuration variables
+ * are expected to be present in the module's config.ini file:
+ * 
+ * browser_filemgr_url    - filemanager host (e.g.: http://somehost:9000)
+ * browser_filemgr_path   - filemanager url on server (e.g.: /)  
+ * browser_datadeliv_url  - the base url to use when downloading products
+ *   
+ * NOTE: This module has a dependency upon the CAS-Filemgr PHP classes
+ * (https://svn.apache.org/repos/asf/oodt/trunk/filemgr/src/main/php)
+ *      
+ *      To build this dependency, check out the above project and then:
+ *      1) cd into the checked out project (you should see a package.xml file)
+ *      2) pear package
+ *      3) (sudo) pear install --force CAS_Filemgr...tar.gz
+ *   
+ * @author ahart
+ * @author resneck
+ *
+ */
+// Require CAS Filemgr Classes
+require_once("CAS/Filemgr/BooleanQueryCriteria.class.php");
+require_once("CAS/Filemgr/Element.class.php");
+require_once("CAS/Filemgr/Metadata.class.php");
+require_once("CAS/Filemgr/Product.class.php");
+require_once("CAS/Filemgr/ProductType.class.php");
+require_once("CAS/Filemgr/ProductPage.class.php");
+require_once("CAS/Filemgr/Query.class.php");
+require_once("CAS/Filemgr/RangeQueryCriteria.class.php");
+require_once("CAS/Filemgr/TermQueryCriteria.class.php");
+require_once("CAS/Filemgr/XmlRpcFilemgrClient.class.php");
+require_once(dirname(__FILE__) . "/Utils.class.php");
+
+
+class CasBrowser {
+	
+	const VIS_INTERPRET_HIDE     = 'hide';
+	const VIS_INTERPRET_SHOW     = 'show';
+	const VIS_AUTH_ANONYMOUS     = false;
+	const VIS_AUTH_AUTHENTICATED = true;
+	const VIS_ALL                = 'all';
+	const VIS_LIMIT              = 'limit';
+	const VIS_NONE               = 'deny';
+	const VIS_DENY               = 'deny';
+	
+	public $client;
+	
+	public function __construct() {
+		try {
+			$this->client = new CAS_Filemgr_XmlRpcFilemgrClient(
+				App::Get()->settings['browser_filemgr_url'],
+				App::Get()->settings['browser_filemgr_path']);
+		} catch (Exception $e) {
+			App::Get()->fatal("Unable to instantiate a connection to "
+				. App::Get()->settings['browser_filemgr_url']
+				. App::Get()->settings['browser_filemgr_path']);
+		}
+	}
+	
+	public function getClient() {
+		return $this->client;
+	}
+	
+	/**
+	 * Use the rules in element-ordering.ini to determine the display order
+	 * for product type metadata elements. See element-ordering.ini for more
+	 * information on how to specify element order rules.
+	 * 
+	 * @param integer $productTypeId  The id of the product type to get met for
+	 * @param array   $metadataTouse  An optional array of metadata key/vals to sort. If
+	 *                this is not provided, the product type metadata will be used.
+	 */
+	public function getSortedMetadata($productTypeId,$metadataToUse = null, $orderingAttribute) {
+		
+		if (!is_array($metadataToUse)) {
+			$pt = $this->client
+				->getProductTypeById($productTypeId)
+				->toAssocArray();
+			$metadataAsArray = $pt['typeMetadata'];
+		} else {
+			$metadataAsArray = $metadataToUse;
+		}
+		
+		$orderingPolicyFilePath = dirname(dirname(__FILE__)) . '/element-ordering.ini';
+		if (file_exists($orderingPolicyFilePath)) {
+			$orderPolicy = parse_ini_file($orderingPolicyFilePath,true);
+
+			$first    = isset($orderPolicy[$productTypeId][$orderingAttribute . '.element.ordering.first']) 
+				? $orderPolicy[$productTypeId][$orderingAttribute . '.element.ordering.first']
+				: $orderPolicy['*'][$orderingAttribute . '.element.ordering.first'];
+			$last     = isset($orderPolicy[$productTypeId][$orderingAttribute . '.element.ordering.last']) 
+				? $orderPolicy[$productTypeId][$orderingAttribute . '.element.ordering.last']
+				: $orderPolicy['*'][$orderingAttribute . '.element.ordering.last'];
+								
+			// Using the odering policy, determine the order in which the metadata will be listed
+			return $this->sortMetadata($metadataAsArray,$first,$last);	
+		} else {
+			return $metadataAsArray;
+		}
+	}
+	
+	/**
+	 * Retreives the set of metadata for the provided productTypeId that should be visible
+	 * to the current user. This function also applies the sorting policy (if it is defined)
+	 * specified in element.ordering.ini.
+	 * 
+	 * @param string $productTypeId - the unique productType identifier
+	 */
+	public function getVisibleMetadataForProductType($productTypeId) {
+		// Get the metadata for the product type
+		$pt = $this->client
+			->getProductTypeById($productTypeId)
+			->toAssocArray();
+			
+		// Determine which metadata should be visible to the current user
+		$visibleMetadata = $this->getVisibleMetadata($pt['typeMetadata'], $productTypeId);
+		
+		// Sort the visible metadata according to the ordering policy
+		$result  = $this->getSortedMetadata($productTypeId,$visibleMetadata, 'pt');
+		
+		return $result;
+	}
+	
+	
+	/**
+	 * Retrieves the set of metadata for the provided productId that should be visible to 
+	 * the current user
+	 * 
+	 * @param string  $productId - the unique product identifier
+	 * @param boolean $authState - whether or not the current user is authenticated
+	 */
+	public function getVisibleMetadataForProduct($productId) {
+		$p  = $this->client->getProductById($productId);
+		$productTypeInfo = $p->getType()->toAssocArray();
+		$productTypeId   = $productTypeInfo[App::Get()->settings['browser_pt_id_key']];
+		$productMetadata = $this->client->getMetadata($p);
+		
+		// Determine which metadata should be visible to the current user
+		$visibleMetadata = $this->getVisibleMetadata($productMetadata->toAssocArray(), $productTypeId);
+				
+		// Sort the visible metadata according to the ordering policy
+		$result  = $this->getSortedMetadata($productTypeId,$visibleMetadata, 'p');
+		
+		return $result;		
+	}
+	
+	
+	/**
+	 * Determine the visibility level for the current product type and current user.
+	 * The level returned is one of VIS_ALL,VIS_LIMIT,VIS_NONE
+	 * 
+	 * @param string $productTypeId - the unique product type identifier
+	 */
+	public function getProductTypeVisibilityLevel( $productTypeId ) {
+		// If the configuration explicitly states that this dataset is to be ignored,
+		// ignore it:
+		if (in_array($productTypeId,App::Get()->settings['browser_dataset_ignores'])) {
+			return CasBrowser::VIS_NONE;
+		}
+		
+		// Get the metadata for the product type
+		$typeInfo = $this->client
+			->getProductTypeById($productTypeId)
+			->toAssocArray();
+		
+		if ( App::Get()->getAuthenticationProvider() ) {
+			
+			// Does the product type define a metadata element matching
+			// the `browser_data_access_key` config setting?
+			$accessKeyExists = isset($typeInfo['typeMetadata'][App::Get()->settings['browser_data_access_key']]);
+			
+			// Obtain the groups for the current resource
+			$resourceGroups = ($accessKeyExists)
+				? $typeInfo['typeMetadata'][App::Get()->settings['browser_data_access_key']]
+				: array();
+			
+			return $this->getResourceVisibility($resourceGroups,
+				App::Get()->settings['browser_pt_auth_policy']);
+		} else {
+			// No authentication provider, everything is public
+			return CasBrowser::VIS_ALL;
+		}
+	}
+	
+	public function getProductVisibilityLevel( $productId ) {
+		
+		$product = $this->client->getProductById( $productId );
+		$productMetadata = $this->client->getMetadata($product);
+
+		// Get metadata for product and productType as associative arrays
+		$productTypeInfo = $product->getType()->toAssocArray();
+		$productInfo     = $productMetadata->toAssocArray();
+		
+		if ( App::Get()->getAuthenticationProvider() ) {
+			
+			// Does the product type define a metadata element matching
+			// the `browser_data_access_key` config setting?
+			$accessKeyExists = isset($productInfo[App::Get()->settings['browser_data_access_key']]);
+			 
+			// Obtain the groups for the current resource
+			$resourceGroups = ($accessKeyExists)
+				? $productInfo[App::Get()->settings['browser_data_access_key']]
+				: array();
+			
+			return $this->getResourceVisibility($resourceGroups, 
+				App::Get()->settings['browser_p_auth_policy']);
+		} else {
+			// No authentication provider, everything is public
+			return CasBrowser::VIS_ALL;
+		}
+	}
+	
+	
+	/**
+	 * Internal helper function for sorting(ordering) a metadata array according to policy. 
+	 * 
+	 * @param array $unsortedMetadata An associative array of unsorted metadta key/(multi)values
+	 * @param array $sortFirst        A scalar array of metadata keys that must be ordered first
+	 * @param array $sortLast         A scalar array of metadata keys that must be ordered last
+	 * @returns array An associative array of sorted(ordered) metadata key/(multi)values
+	 */
+	protected function sortMetadata($unsortedMetadata,$sortFirst,$sortLast) {
+		$orderedMetadata = array();
+		foreach ($sortFirst as $key) {
+			if (isset($unsortedMetadata[$key])) {
+				$orderedMetadata[$key] = $unsortedMetadata[$key];
+				unset($unsortedMetadata[$key]);
+			}
+		}
+		$lastMetadata = array();
+		foreach ($sortLast as $key) {
+			if (isset($unsortedMetadata[$key])) {
+				$lastMetadata[$key] = $unsortedMetadata[$key];
+				unset($unsortedMetadata[$key]);
+			}
+		}
+		$orderedMetadata += $unsortedMetadata;
+		$orderedMetadata += $lastMetadata;
+		
+		return $orderedMetadata;
+	}
+	
+	/**
+	 * Internal helper function for, given an array of metadata, a productTypeID, and an indication of whether or not the 
+	 * current user is authenticated, returning the subset of metadata that should be visible to
+	 * the user. 
+	 * 
+	 * @param array   $metadataAsArray
+	 * @param string  $productTypeId
+	 * @param boolean $longinState - one of VIS_AUTH_AUTHENTICATED|VIS_AUTH_ANONYMOUS
+	 */
+	protected function getVisibleMetadata($metadataAsArray, $productTypeId) {
+		
+		// Determine whether the user is authenticated
+		$authState = (($ap = App::Get()->getAuthenticationProvider()) && $ap->isLoggedIn());
+		
+		$visibilityPolicyFilePath = dirname(dirname(__FILE__)) . '/element-visibility.ini';
+		if (file_exists($visibilityPolicyFilePath)) {
+			$visibilityPolicy = parse_ini_file($visibilityPolicyFilePath,true);
+			
+			$interpretation = $visibilityPolicy['interpretation.policy'];
+			$globalVisibilityPolicy = $visibilityPolicy['*'];
+			$productTypeVisibilityPolicy = isset($visibilityPolicy[$productTypeId])
+				? $visibilityPolicy[$productTypeId]
+				: array("visibility.always" => array(),
+						"visibility.anonymous" => array(),
+						"visibility.authenticated" => array());
+
+			// The visibility of a given metadata element is dependent upon
+			//   (1) the authentication status of the user (VIS_AUTH_AUTHENTICATED|VIS_AUTH_ANONYMOUS)
+			//   (2) the interpretation of the visibility policy (VIS_INTERPRET_SHOW|VIS_INTERPRET_HIDE)
+			//   
+			//   Using these values, determine which metadata to display:
+			switch ($interpretation) {
+				// If the policy defines only those metadata which should be hidden:
+				case self::VIS_INTERPRET_HIDE:
+					$displayMet = $metadataAsArray;                                     // everything is shown unless explicitly hidden via the policy
+					foreach ($globalVisibilityPolicy['visibility.always'] as $elm)      // iterate through the global 'always hide' array...
+						unset($displayMet[$elm]);                                       // and remove all listed elements
+					foreach ($productTypeVisibilityPolicy['visibility.always'] as $elm) // now iterate through the product-type 'always hide' array...
+						unset($displayMet[$elm]);                                       // and remove all listed elements
+							
+					// Determine what to hide given the user's login state 
+					switch ($authState) {                                                             // check the login status of the user
+						case self::VIS_AUTH_ANONYMOUS:                                                 // if the user is anonymous...
+							foreach($globalVisibilityPolicy['visibility.anonymous'] as $elm)           // iterate through the global 'anonymous hide' array...
+								unset($displayMet[$elm]);                                              // and remove all listed elements
+							foreach ($productTypeVisibilityPolicy['visibility.anonymous'] as $elm)     // now iterate through the product-type 'anonymous hide' array...
+								unset($displayMet[$elm]);                                              // and remove all listed elements
+							break;                                                                     // done.
+						case self::VIS_AUTH_AUTHENTICATED:                                             // if the user is authenticated...
+							foreach($globalVisibilityPolicy['visibility.authenticated'] as $elm)       // iterate through the global 'authenticated hide' array...
+								unset($displayMet[$elm]);                                              // and remove all listed elements
+							foreach ($productTypeVisibilityPolicy['visibility.authenticated'] as $elm) // now iterate through the product-type 'authenticated hide' array...
+								unset($displayMet[$elm]);                                              // and remove all listed elements
+							break;                                                                     // done.
+					}
+
+					break;
+				
+				// If the policy defines only those metadata which should be shown:
+				case self::VIS_INTERPRET_SHOW:
+					$displayMet = $globalVisibilityPolicy['visibility.always']                         // merge the global 'always show' array
+						+ $productTypeVisibilityPolicy['visibility.always'];                           // with the product-type specific 'always show' array
+					switch ($authState) {                                                              // check the login status of the user
+						case self::VIS_AUTH_ANONYMOUS:                                                 // if the user is anonymous...
+							$displayMet += $globalVisibilityPolicy['visibility.anonymous'];            // merge the global 'anonymous show' array
+							$displayMet += $productTypeVisibilityPolicy['visibility.anonymous'];       // and the product-type specific 'anonymous show' array
+							break;                                                                     // done.
+						case self::VIS_AUTH_AUTHENTICATED:                                             // if the user is authenticated...
+							$displayMet += $globalVisibilityPolicy['visibility.authenticated'];        // merge the global 'authenticated show' array 
+							$displayMet += $productTypeVisibilityPolicy['visibility.authenticated'];   // and the product-type specific 'authenticated show' array
+							break;                                                                     // done.
+					}
+			}
+			
+			return $displayMet;	
+				
+		} else {
+			return $metadataAsArray;
+		}
+	}
+		
+	/**
+	 * Internal helper function to determine the visibility level of a given resource given
+	 * its array of security groups. The value returned is one of VIS_ALL,VIS_LIMIT,VIS_NONE.
+	 * 
+	 * @param array $resourceGroups - an array of security groups for the resource
+	 * @param string $policy        - one of VIS_LIMIT or VIS_DENY
+	 */	
+	protected function getResourceVisibility( $resourceGroups, $policy = CasBrowser::VIS_DENY ) {
+		
+		// Is the resource considered "public"?
+ 		if (in_array(App::Get()->settings['browser_data_public_access'],$resourceGroups)) { 
+			return CasBrowser::VIS_ALL;
+		}
+		
+		// Get user authentication info
+		$authentication = App::Get()->getAuthenticationProvider();
+		$username = ($authentication)
+		    ? $authentication->getCurrentUsername()
+		    : false;	// no authentication info provided in config file
+		
+		// Does the metadata visibility depend on an access element matching
+ 		// the `browser_data_access_key` in the config setting?
+ 		$accessKeyExists = isset(App::Get()->settings['browser_data_access_key']);
+
+ 		// If key is set then we look into what groups have access to metadata
+ 		if ( $accessKeyExists && !empty($resourceGroups) ) {
+			
+			// Has authentication provider information been specified?
+			if ( $authentication ) {
+				
+			 	// Is the user currently logged in?
+			 	if ( $username ) {
+	 				
+			 		if ( $authorization = App::Get()->getAuthorizationProvider() ) {
+				 		// Obtain the groups for the current user
+				 		$userGroups = $authorization->retrieveGroupsForUser($username);
+				 		
+				 		// Perform a comparison via array intersection to determine overlap
+				 		$x = array_intersect($userGroups,$resourceGroups);
+				 		
+				 		if (empty($x)) { // No intersection found between user and resource groups
+				
+				 			// Examine the policy to determine how to handle the failure
+				 			switch ($policy) {
+				 				case CasBrowser::VIS_LIMIT:
+				 					// Allow the user to proceed, the metadata visibility policy
+				 					// will be used to determine what is visible to non-authorized
+				 					// users.
+				 					return CasBrowser::VIS_LIMIT;
+				 				default:
+				 					// Kick the user out at this point, deny all access. 
+					 				return CasBrowser::VIS_NONE;
+				 			}
+				 		} else {
+				 			// We have an authorized user
+				 			$authorizedUser = true;
+				 		}
+			 		} else {
+			 			
+						// If no authorization provider information exists in the application
+					 	// configuration file, it is assumed that every user is authorized once
+					 	// logged in.
+					 	return CasBrowser::VIS_ALL;				 			
+			 		}
+			 	} else {
+			 		
+			 		// If no logged in user, and policy says DENY, kick the user
+			 		if ($policy == CasBrowser::VIS_DENY) {
+			 			return CasBrowser::VIS_NONE;
+ 			 		} else {
+			 			return CasBrowser::VIS_LIMIT;
+ 			 		}
+			 	}
+		 	} else {
+			 	// If no authentication provider information exists in the application
+			 	// configuration file, it is assumed that authentication and authorization
+			 	// are not needed for this application, and thus every user is authorized
+			 	// by default.
+			 	return CasBrowser::VIS_ALL;	
+			}				
+ 		} else {
+ 			
+ 			// All data is visible to user if logged in
+ 			// Has authentication provider information been specified?
+			if ( $authentication ) {
+				
+			 	// Is the user currently logged in?
+			 	if ( $username ) {
+			 		return CasBrowser::VIS_ALL; // We have an authorized user
+			 	} else {
+			 		// If no logged in user, and policy says DENY, kick the user
+			 		if ($policy == CasBrowser::VIS_DENY) {
+			 			return CasBrowser::VIS_NONE;
+			 		} else {
+			 			return CasBrowser::VIS_LIMIT;
+			 		}
+			 	}
+		 	} else {
+			 	// If no authentication provider information exists in the application
+			 	// configuration file, it is assumed that authentication and authorization
+			 	// are not needed for this application, and thus every user is authorized
+			 	// by default.
+			 	return CasBrowser::VIS_ALL;	
+			}
+ 		}
+	}
+}
diff --git a/0.8.1-rc1/balance/modules/cas-browser/classes/Utils.class.php b/0.8.1-rc1/balance/modules/cas-browser/classes/Utils.class.php
new file mode 100644
index 0000000..e8d608a
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/classes/Utils.class.php
@@ -0,0 +1,388 @@
+<?php
+/*
+ * 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.
+ */
+
+require_once("CasBrowser.class.php");
+
+class Utils{
+	
+	public static $acceptedReturnTypes = array('html', 'json');
+
+	/**
+	 * @param types
+	 *		An array of PoductTypes.
+	 *
+	 * @return 
+	 *		An array of unique names of Metadata and Elements associated with the given 
+	 *		ProductTypes.
+	 */
+	public static function getMetadataElements($types){
+		$cb = new CasBrowser();
+		$client = $cb->getClient();
+		$metadataNames = array();
+		foreach($types as $type){
+			foreach(array_keys($type->getTypeMetadata()->toAssocArray()) as $metadata){
+				if(!in_array($metadata, $metadataNames)){
+					array_push($metadataNames, $metadata);
+				}
+			}
+			foreach($client->getElementsByProductType($type) as $element){
+				$elementName = $element->getElementName();
+				if(!in_array($elementName, $metadataNames)){
+					array_push($metadataNames, $elementName);
+				}
+			}
+		}
+		return $metadataNames;
+	}
+	
+	/**
+	 * @param productType
+	 *		The productType of the ProductPage desired.
+	 *
+	 * @param pageNum
+	 *		The number of the page desired in the set of ProductPages of that ProductType.
+	 *
+	 * @return
+	 *		The requested ProductPage object.
+	 */
+	public static function getPage($productType, $pageNum){
+		$cb = new CasBrowser();
+		$client = $cb->getClient();
+		
+		// Iterate until the proper page is reached
+		for($page = $client->getFirstPage($productType);
+			$page->getPageNum() < $pageNum && $page->getPageNum() < $page->getTotalPages();
+			$page = $client->getNextPage($productType, $page)){}
+			
+		return $page;
+	}
+	
+	public static function getRequestedReturnType($requestedType){
+		$lowerRequestedType = strtolower($requestedType);
+		if(!in_array($lowerRequestedType, self::$acceptedReturnTypes)){
+			throw new CasBrowserException('Error: The requested return type of '. $requestedType . 'is not accepted.');
+		}
+		return $lowerRequestedType;
+	}
+	
+	public static function getProductListMetadata($products){
+		$payload = array();
+		foreach($products as $p){
+			$cb = new CasBrowser();
+			$client = $cb->getClient();
+			$met = $client->getMetadata($p);
+			$payload[$p->getId()] = $met;
+		}
+		return $payload;
+	}
+	
+	// What kind of access should the currently authenticated user have, given the 
+	// provided groups (aka roles, permissions) associated with the resource?
+	//
+	// Possible values are: CasBrowser::{VIS_ALL, VIS_LIMIT, VIS_NONE}. It is up to the 
+	// caller to determine what to do based on the return value
+	//
+	public static function ResourceVisibility( $resourceGroups ) {
+		
+		// Is the resource considered "public"?
+ 		if (in_array(App::Get()->settings['browser_data_public_access'],$resourceGroups)) { 
+			return CasBrowser::VIS_ALL;
+		}
+		
+		// Get user authentication info
+		$authentication = App::Get()->getAuthenticationProvider();
+		$username = ($authentication)
+		    ? $authentication->getCurrentUsername()
+		    : false;	// no authentication info provided in config file
+		
+		// Does the metadata visibility depend on an access element matching
+ 		// the `browser_data_access_key` in the config setting?
+ 		$accessKeyExists = isset(App::Get()->settings['browser_data_access_key']);
+
+ 		// If key is set then we look into what groups have access to metadata
+ 		if ( $accessKeyExists && !empty($resourceGroups) ) {
+			
+			// Has authentication provider information been specified?
+			if ( $authentication ) {
+				
+			 	// Is the user currently logged in?
+			 	if ( $username ) {
+	 		
+			 		// Obtain the groups for the current user
+			 		$userGroups = App::Get()->getAuthorizationProvider()->retrieveGroupsForUser($username);
+			 			 		
+			 		// Perform a comparison via array intersection to determine overlap
+			 		$x = array_intersect($userGroups,$resourceGroups);
+			 		
+			 		if (empty($x)) { // No intersection found between user and resource groups
+			
+			 			// Examine `browser_pt_auth_policy` to determine how to handle the failure
+			 			switch (strtoupper(App::Get()->settings['browser_pt_auth_policy'])) {
+			 				case "LIMIT":
+			 					// Allow the user to proceed, the metadata visibility policy
+			 					// will be used to determine what is visible to non-authorized
+			 					// users.
+			 					return CasBrowser::VIS_LIMIT;				
+			 				case "DENY":
+			 				default:
+			 					// Kick the user out at this point, deny all access. 
+				 				return CasBrowser::VIS_NONE;
+			 			}
+			 		} else {
+			 			// We have an authorized user
+			 			$authorizedUser = true;
+			 		}
+			 	} else {
+			 		// If no logged in user, and policy says DENY, kick the user
+			 		if (strtoupper(App::Get()->settings[$metType]) == "DENY") {
+			 			return CasBrowser::VIS_NONE;
+ 			 		} else {
+			 			return CasBrowser::VIS_LIMIT;
+ 			 		}
+			 	}
+		 	} else {
+			 	// If no authentication provider information exists in the application
+			 	// configuration file, it is assumed that authentication and authorization
+			 	// are not needed for this application, and thus every user is authorized
+			 	// by default.
+			 	return CasBrowser::VIS_ALL;	
+			}				
+ 		} else {
+ 			
+ 			// All data is visible to user if logged in
+ 			// Has authentication provider information been specified?
+			if ( $authentication ) {
+				
+			 	// Is the user currently logged in?
+			 	if ( $username ) {
+			 		return CasBrowser::VIS_ALL; // We have an authorized user
+			 	} else {
+			 		// If no logged in user, and policy says DENY, kick the user
+			 		if (strtoupper(App::Get()->settings[$metType]) == "DENY") {
+			 			return CasBrowser::VIS_NONE;
+			 		}
+			 		return CasBrowser::VIS_LIMIT;
+			 	}
+		 	} else {
+			 	// If no authentication provider information exists in the application
+			 	// configuration file, it is assumed that authentication and authorization
+			 	// are not needed for this application, and thus every user is authorized
+			 	// by default.
+			 	return CasBrowser::VIS_ALL;	
+			}
+ 		}
+	}
+	
+	// Create a criteria subtree that will search for the value at the given criteriaIndex across all 
+	// metadata elements associated with the given productTypes.
+	public static function createBasicSearchSubtree($criteriaIndex, $queryTypes){
+		$criterion = new CAS_Filemgr_BooleanQueryCriteria();
+		$criterion->setOperator(CAS_Filemgr_BooleanQueryCriteria::$OR_OP);
+		$metadataNames = getMetadataElements($queryTypes);
+		foreach($metadataNames as $name){
+			$term = new CAS_Filemgr_TermQueryCriteria();
+			$term->setElementName($name);
+			$term->setValue($_POST['Criteria'][$criteriaIndex]['Value']);
+			$criterion->addTerm($term);
+		}
+		return $criterion;
+	}
+	
+	public static function createTermCriteria($criteriaIndex, $queryTypes){
+		if(!isset($_POST['Criteria'][$criteriaIndex]['ElementName'])){
+			throw new CasBrowserException("Query Term criterion " . $criteriaIndex . " does not contain 'ElementName' specification");
+		}
+		if(!isset($_POST['Criteria'][$criteriaIndex]['Value'])){
+			throw new CasBrowserException("Query Term criterion " . $criteriaIndex . " does not contain 'Value' specification");
+		}
+		if($_POST['Criteria'][$criteriaIndex]['ElementName'] == '*'){
+			$criterion = self::createBasicSearchSubtree($criteriaIndex, $queryTypes);
+		}else{
+			$criterion = new CAS_Filemgr_TermQueryCriteria();
+			$criterion->setElementName($_POST['Criteria'][$criteriaIndex]['ElementName']);
+			$criterion->setValue($_POST['Criteria'][$criteriaIndex]['Value']);
+		}
+		return $criterion;
+	}
+	
+	public static function createRangeCriteria($criteriaIndex){
+		if(!isset($_POST['Criteria'][$criteriaIndex]['ElementName'])){
+			throw new CasBrowserException("Query Term criterion " . $criteriaIndex . " does not contain 'ElementName' specification");
+		}
+		if(!isset($_POST['Criteria'][$criteriaIndex]['Min'])){
+			throw new CasBrowserException("Query Range criterion " . $criteriaIndex . " does not contain 'Min' specification");
+		}
+		if(!isset($_POST['Criteria'][$criteriaIndex]['Max'])){
+			throw new CasBrowserException("Query Range criterion " . $criteriaIndex . " does not contain 'Max' specification");
+		}
+		$criterion = new CAS_Filemgr_RangeQueryCriteria();
+		$criterion->setElementName($_POST['Criteria'][$criteriaIndex]['ElementName']);
+		$criterion->setStartValue($_POST['Criteria'][$criteriaIndex]['Min']);
+		$criterion->setEndValue($_POST['Criteria'][$criteriaIndex]['Max']);
+		if(isset($_POST['Criteria'][$criteriaIndex]['Inclusive'])){
+			$criterion->setInclusive($_POST['Criteria'][$criteriaIndex]['Inclusive']);
+		}
+		return $criterion;
+	}
+	
+	public static function createBooleanCriteria($criteriaIndex, $queryTypes, $createdIndices){
+		if(!isset($_POST['Criteria'][$criteriaIndex]['Operator'])){
+			throw new CasBrowserException("Query Boolean criterion " . $criteriaIndex . " does not contain 'Operator' specification");
+		}
+		if(!isset($_POST['Criteria'][$criteriaIndex]['CriteriaTerms'])){
+			throw new CasBrowserException("Query Boolean criterion " . $criteriaIndex . " does not contain 'CriteriaTerms' specification");
+		}
+		if(!count($_POST['Criteria'][$criteriaIndex]['CriteriaTerms'])){
+			throw new CasBrowserException("Query Boolean criterion " . $criteriaIndex . " does not contain any terms");
+		}
+		$criterion = new CAS_Filemgr_BooleanQueryCriteria();
+		$operator = trim(strtoupper($_POST['Criteria'][$criteriaIndex]['Operator']));
+		if($operator == 'AND'){
+			$criterion->setOperator(CAS_Filemgr_BooleanQueryCriteria::$AND_OP);
+		}elseif($operator == 'OR'){
+			$criterion->setOperator(CAS_Filemgr_BooleanQueryCriteria::$OR_OP);
+		}elseif($operator == 'NOT'){
+			if(count($_POST['Criteria'][$criteriaIndex]['CriteriaTerms']) != 1){
+				throw new CasBrowserException("Query Boolean criterion " . $criteriaIndex . " cannot negate more than one term");
+			}
+			$criterion->setOperator(CAS_Filemgr_BooleanQueryCriteria::$NOT_OP);
+		}else{
+			throw new CasBrowserException("Error: Query Boolean criterion " . $criteriaIndex . " tries to use undefined operator '" . $operator . "'");
+		}
+		foreach(array_map("intval", $_POST['Criteria'][$criteriaIndex]['CriteriaTerms']) as $childIndex){
+			if(in_array($childIndex, $createdIndices)){		// Check for loops in criteria tree
+				throw new CasBrowserException("Criterion " . $criteriaIndex . " lists " . $childIndex . "as a child, making a loop.");
+			}
+			array_push($createdIndices, $childIndex);
+			$child = self::createCriteriaTree($childIndex, $queryTypes);
+			$criterion->addTerm($child);
+		}
+		return $criterion;
+	}
+	
+	public static function createCriteriaTree($criteriaIndex, $queryTypes, $createdIndices=null){
+		if(!isset($createdIndices)){
+			$createdIndices = array();
+		}
+		if(!isset($_POST['Criteria'][$criteriaIndex])){
+			throw new CasBrowserException("Query Boolean criterion " . $criteriaIndex . " does not exist.");
+		}
+		$type = strtolower($_POST['Criteria'][$criteriaIndex]['CriteriaType']);
+		if($type == 'term'){
+			$criterion = self::createTermCriteria($criteriaIndex, $queryTypes);
+		}elseif($type == 'range'){
+			$criterion = self::createRangeCriteria($criteriaIndex);
+		}elseif($type == 'boolean'){
+			$criterion = self::createBooleanCriteria($criteriaIndex, $queryTypes, $createdIndices);
+		}else{
+			throw new CasBrowserException("Query criterion " . $criteriaIndex . " contains an unknown type " . $type . ".  Please use one of 'term', 'range' or 'boolean'");
+		}
+		return $criterion;
+	}
+	
+	public static function getMetadataNamesForTypeProducts($type){
+		$cb = new CasBrowser();
+		$client = $cb->getClient();
+		$elementNames = array();
+		foreach($client->getElementsByProductType($type) as $e){
+			array_push($elementNames, $e->getElementName());
+		}
+		foreach(array_keys($type->getTypeMetadata()->toAssocArray()) as $typeElementName){
+			if(!in_array($typeElementName, $elementNames)){
+				array_push($elementNames, $typeElementName);
+			}
+		}
+		return $elementNames;
+	}
+	
+	public static function getFacets(){
+		$cb = new CasBrowser();
+		$client = $cb->getClient();
+		$types = $client->getProductTypes();
+		$facets = self::getMetadataNamesForTypeProducts(array_pop($types));
+		if(count($types) == 0){
+			return $facets;	// In case there is only one product type
+		}
+		foreach($types as $type){
+			$elementNames = self::getMetadataNamesForTypeProducts($type);
+			$facets = array_intersect($facets, $elementNames);
+		}
+		return $facets;
+	}
+	
+	public static function paginate($allProducts, $pageNum, $pageSize){
+		if(count($allProducts) == 0){
+			return array();
+		}
+		if($pageSize <= 0){
+			throw new CasBrowserException("The given PageSize (" . $pageSize . ") was zero or less.");
+		}
+		$startIndex = ($pageNum - 1) * $pageSize;
+		if($startIndex >= count($allProducts)){
+			throw new CasBrowserException("The starting index of the requested page (" .
+					$startIndex . ") is greater than the last index of all products (" .
+					count($allProducts) . ").");
+		}
+		$endIndex = $startIndex + $pageSize - 1;
+		$endIndex = min($endIndex, count($allProducts) - 1);
+		$requestedProducts = array();
+		for($i = $startIndex; $i <= $endIndex; $i++){
+			array_push($requestedProducts, $allProducts[$i]);
+		}
+		return $requestedProducts;
+	}
+	
+	public static function formatResults($products){
+		$cb = new CasBrowser();
+		$client = $cb->getClient();
+		$results = array();
+		foreach($products as $product){
+			try{
+				$p = array('id'=>$product['product']->getId(),
+						'name'=>urlDecode($product['product']->getName()),
+						'metadata'=>$client->getMetadata($product['product'])->toAssocArray());
+				if(isset($product['typeName'])){
+					$p['type'] = $product['typeName'];
+				}
+				array_push($results, $p);
+			}catch(Exception $e){
+				throw new CasBrowserException("An error occured while formatting product [" .
+						$product['product']->getId() . "] metadata: " . $e->getMessage());
+			}
+		}
+		return $results;
+	}
+	
+	public static function reportError($message, $outputFormat){
+		if($outputFormat == 'html'){
+			echo '<div class="error">' . $message . '</div>';
+		}elseif($outputFormat == 'json'){
+			$payload = array();
+			$payload['Error'] = 1;
+			$payload['ErrorMsg'] = $message;
+			$payload = json_encode($payload);
+			echo $payload;
+		}
+		exit();
+	}
+	
+}
+
+class CasBrowserException extends Exception{}
+
+?>
diff --git a/0.8.1-rc1/balance/modules/cas-browser/config.ini b/0.8.1-rc1/balance/modules/cas-browser/config.ini
new file mode 100644
index 0000000..f397af8
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/config.ini
@@ -0,0 +1,121 @@
+; 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.
+
+
+; CAS-BROWSER module configuration file
+; ------------------------------------------------------------------------
+
+
+; FILE MANAGER CONNECTIVITY
+; -----------------------------------------------------------------------------
+; Specify connection information for an instance of the OODT file manager.
+;
+browser_filemgr_url   = http://localhost:9000
+browser_filemgr_path  = /
+browser_datadeliv_url = http://host:port/path
+
+
+
+; AUTHENTICATION AND AUTHORIZATION
+; -----------------------------------------------------------------------------
+; Customize the behavior of the module for specific auth & auth requirements.
+
+; This key specifies the behavior to take when users attempt to access resources
+; for which they do not have the necessary permissions. There are two options:
+;
+; deny  => force redirect with a 403 Not Authorized error
+;           This option prevents a user from viewing any information about
+;           products or productTypes they are not authorized to see.
+;
+; limit => apply the metadata filtering policy specified in element-visibility.ini
+;           to control access to information on a more granular, element by
+;           element level. This allows users to see publicly available information
+;           about an otherwise protected product or productType.
+;
+; Policy for product types:
+browser_pt_auth_policy = limit
+; Policy for products:
+browser_p_auth_policy  = limit
+
+; This key specifies the productType metadata element that contains
+; the list of security groups (aka roles, permissions,etc) that should
+; be granted access. This key can exist in productType metadata, or
+; product metadata, or both. If it exists in productType metadata only,
+; products will inherit the information.
+;
+browser_data_access_key 	= AccessGrantedTo
+browser_data_public_access 	= public
+
+; LOOK AND FEEL SETTINGS
+; -----------------------------------------------------------------------------
+; Customize aspects of the user interface to suit project needs
+
+browser_index_title_text  = Cas Browser
+
+; These keys identify the metadata keys used to obtain basic product type 
+; information. These rarely need to be manually changed.
+;    browser_pt_name_key: the product type name
+;    browser_pt_desc_key: the key containing a description of the product type 
+;    browser_pt_id_key:   the key containing the unique product type id (urn)
+
+browser_pt_name_key       = name
+browser_pt_desc_key       = description
+browser_pt_id_key         = id
+
+; These keys determine which metadata elements will
+; appear as column headers on the dataset viewer
+
+browser_pt_search_met[]   = name
+browser_pt_search_met[]   = description
+browser_pt_search_met[]   = id
+
+; This key determines which of the `browser_pt_search_met` keys will be used
+; as the clickable link taking the user to the overview page for the given
+; product type
+
+browser_pt_search_linkkey = name
+
+; These keys specify (an array of) product types to exclude from the 
+; product type list displayed on the index page.
+browser_dataset_ignores[] = urn:oodt:GenericFile
+
+
+
+; The browser_products_met[] array key dictates which metadata elements will
+; be displayed in the products view.  One can designate any number of
+; elements to display (including zero), but all of them must be defined for
+; all product types.
+
+browser_products_met[] = CAS.ProductId
+browser_products_met[] = MimeType
+browser_products_met[] = ProductStructure
+browser_products_met[] = CAS.ProductReceivedTime
+
+; The browser_private_products_visibility key dictates whether private products 
+; will be displayed in the products view.
+browser_private_products_visibility = true
+
+; If the browser_show_download_widget key is set to 0, the download widget in
+; the products view won't be displayed.  If the key is set to any other value
+; the widget will be displayed.
+
+browser_show_download_widget=1
+
+; If default_show_all is set to 1, then the typesearch view will, by deafult,
+; display all products of all types when the view is opened.  Otherwise, no
+; products will be shown in the typesearch vie until filters are specified.
+
+default_show_all = 1
+
diff --git a/0.8.1-rc1/balance/modules/cas-browser/element-ordering.ini b/0.8.1-rc1/balance/modules/cas-browser/element-ordering.ini
new file mode 100644
index 0000000..72c51fd
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/element-ordering.ini
@@ -0,0 +1,64 @@
+;
+; 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.
+
+;
+; ELEMENT-ORDERING.INI
+;
+; This file defines the order of metadata keys on a per-product-type basis
+; Elements not explicitly mentioned in this file will be displayed following
+; all of the explicitly ordered elements.
+;
+; The global section [*] can be used to define a default ordering to apply.
+; Note that, if a product type declaration is found, its ordering overrides
+; the default ordering in [*].
+;
+; There are two ordered arrays for each product type:
+;    pt.element.ordering:   specifies product-type metadata order
+;    p.element.ordering:    specifies product metadata order
+;
+
+[*]
+;product type metadata element ordering (global)
+; the '.first' array indicates those elements which should be shown BEFORE
+; all other metadata elements:
+pt.element.ordering.first[] = 
+
+
+; the '.last' array indicates those elements that should be shown AFTER
+; all other metadata elements. The last element in this array will be
+; shown last.
+pt.element.ordering.last[] = 
+
+
+; product metadata element ordering (global)
+; the '.first' array indicates those elements that should be shown BEFORE
+; all other metadata elements:
+p.element.ordering.first[] =
+; the '.last' array indicates those elements that should be shown AFTER
+; all other metadata elements. The last element in this array will be
+; shown last.
+p.element.ordering.last[] =
+
+; It is possible to override the global settings on a per-productType basis
+; simply by defining a productType header and re-defining the pt.element.ordering.*
+; arrays for that productType. ProductType-specific settings do not inherit from 
+;the global settings.
+;
+;[urn:oodt:GenericFile]
+;pt.element.ordering.first[] =
+;pt.element.ordering.last[] = 
+;p.element.ordering.first[] =
+;p.element.ordering.last[] =
diff --git a/0.8.1-rc1/balance/modules/cas-browser/element-visibility.ini b/0.8.1-rc1/balance/modules/cas-browser/element-visibility.ini
new file mode 100644
index 0000000..103f9db
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/element-visibility.ini
@@ -0,0 +1,49 @@
+;
+; ELEMENT-VISIBILITY.INI
+;
+; This file controls the visibility of metadata elements for product types 
+; known to the underlying file manager instance.
+; 
+; Specify the interpretation policy for this file. This can take one of two values:
+;    show: Definitions in this file indicate metadata keys which should be SHOWN
+;    hide: Definitions in this file indicate metadata keys which should be HIDDEN
+;
+;  If the policy is 'show' and an element does NOT appear in this file, it will be 
+;  hidden. Conversely, if the policy is 'hide' and an element does NOT appear in 
+;  this list, it will be shown.
+
+interpretation.policy = hide
+
+; Next, define element visibility on a per-product-type basis.
+; To specify definitions for a particular product type, first declare the product type 
+; by enclosing its URN in square brackets on its own line, e.g.:
+; [urn:oodt:GenericFile]
+; (without the leading ';', obviously) and then add element visibility definitions below. 
+;
+; Element visibility definitions take three forms:
+;     visibility.always:        will be {shown/hidden} regardless of authentication
+;     visibility.anonymous:     will be {shown/hidden} for anonymous users
+;     visibility.authenticated: will be {shown/hidden} for authenticated users
+; Note that {shown/hidden} is determined by the interpretation.policy for the file. That is, 
+; if the interpretation policy is "show", then the keys under visibility.always will always
+; be shown. If the interpretation is "hide", however, those same keys will always be
+; hidden.
+; 
+;
+;
+; Definitions under the product type label [*] will be applied to all product types and 
+; merged with any product-type-specific definitions which may come later in the file.
+[*]
+visibility.always[] = 
+visibility.anonymous[] = 
+visibility.authenticated[] = 
+
+; EXAMPLE of product-type specific override:
+; Definitions for the FHCRC Hanash (Annexin-LAMR) product type
+;
+;[urn:edrn:FHCRCHanashAnnexinLamr]
+;visibility.always[] = 
+;visibility.anonymous[] = 
+;visibility.authenticated[] =  
+
+
diff --git a/0.8.1-rc1/balance/modules/cas-browser/hooks.php b/0.8.1-rc1/balance/modules/cas-browser/hooks.php
new file mode 100644
index 0000000..ba0c212
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/hooks.php
@@ -0,0 +1,74 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * HOOKS.PHP
+ * 
+ * Hooks provide the ability, as the name implies, to hook into various parts of 
+ * the view rendering process and insert customizations. The contents of these 
+ * functions are run at the appropriate time *EVERY* time a view is rendered, i.e.
+ * the content of the hooks is not by default view-specific but rather will be 
+ * applied to all views. (However, there is nothing that prevents developers from 
+ * inserting conditional logic inside a hook that then causes view-specific
+ * them to exhibit view-specific behavior).
+ * 
+ * Take a look at the docblock descriptions of each hook to get a sense of where
+ * in the view rendering process the hook is invoked.
+ * 
+ * @author ahart
+ */
+
+/**
+ * hook_before_header
+ * 
+ * This hook is executed before the contents of the header file are processed.
+ */
+function hook_before_header() {} 
+
+/**
+ * hook_before_view
+ * 
+ * This hook is executed before the contents of the main view are processed.
+ */
+function hook_before_view() {
+	require_once( 'scripts/widgets/BreadcrumbsWidget.php' );
+	
+	$module = App::Get()->loadModule();
+	// Include JavaScript files to be shown with every view in this module
+	App::Get()->response->addJavascript($module->moduleStatic.'/js/jquery-1.4.2-min.js');
+	App::Get()->response->addJavascript($module->moduleStatic.'/js/jcorner.jquery.js');
+	
+	// Include CAS-Browser default CSS stylesheets to be shown with every view in this module
+	App::Get()->response->addStylesheet($module->moduleStatic.'/css/cas-browser.css');
+	App::Get()->response->addStylesheet($module->moduleStatic.'/css/dataTables.css');
+}
+
+/**
+ * hook_before_footer
+ * 
+ * This hook is executed before the contents of the footer are processed
+ */
+function hook_before_footer() {}
+
+/**
+ * hook_before_render
+ * 
+ * This hook is after all of the view components (header, view, footer) have been
+ * processed but before the processed results are sent out across the wire to the 
+ * browser.
+ */
+function hook_before_send() {}
diff --git a/0.8.1-rc1/balance/modules/cas-browser/scripts/allTypeScript.php b/0.8.1-rc1/balance/modules/cas-browser/scripts/allTypeScript.php
new file mode 100644
index 0000000..c366a5a
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/scripts/allTypeScript.php
@@ -0,0 +1,64 @@
+<?php
+/*
+ * 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.
+ */
+
+$module = App::Get()->loadModule();
+require_once(dirname(dirname(__FILE__)) . '/classes/CasBrowser.class.php');
+
+$outputFormat = 'json';	// Hard-coded for now
+
+// Get client handle
+$cb = new CasBrowser();
+$client = $cb->getClient();
+
+$results = array('results'=>array());
+
+// Get all products and their types
+$allProducts = array();
+foreach($client->getProductTypes() as $type){
+	foreach($client->getProductsByProductType($type) as $product){
+		array_push($allProducts, array('product'=>$product, 'typeName'=>$type->getName()));
+	}
+}
+
+// Narrow down the given products to the requested page (if page info is given)
+$requestedProducts = array();
+if(isset($_POST['PageNum']) && isset($_POST['PageSize'])){
+	$pageNum = intval($_POST['PageNum']);
+	$pageSize = intval($_POST['PageSize']);
+	try{
+		$requestedProducts = Utils::paginate($allProducts, $pageNum, $pageSize);
+	}catch(Exception $e){
+		Utils::reportError($e->getMessage(), $outputFormat);
+	}
+	$results['totalPages'] = ceil(count($allProducts) / $pageSize);
+}else{
+	$requestedProducts = $allProducts;
+}
+
+// Get metadata and format requested products
+try{
+	$results['results'] = Utils::formatResults($requestedProducts);
+}catch(Exception $e){
+	Utils::reportError($e->getMessage(), $outputFormat);
+}
+
+$results['totalProducts'] = count($allProducts);
+
+echo json_encode($results);
+
+?>
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/cas-browser/scripts/crossTypeQueryScript.php b/0.8.1-rc1/balance/modules/cas-browser/scripts/crossTypeQueryScript.php
new file mode 100644
index 0000000..d228f2b
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/scripts/crossTypeQueryScript.php
@@ -0,0 +1,246 @@
+<?php
+/*
+ * 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.
+ */
+
+$module = App::Get()->loadModule();
+require_once(dirname(dirname(__FILE__)) . '/classes/CasBrowser.class.php');
+
+global $messages;
+$messages = array();
+
+function searchBooleanMetadata($pts, $booleanCriterion){
+	global $messages;
+	$resultTypes = array();
+	$terms = $booleanCriterion->getTerms();
+	if($booleanCriterion->getOperator() == CAS_Filemgr_BooleanQueryCriteria::$AND_OP){
+		$resultTypes = $pts;
+		foreach($terms as $t){
+			try{
+				$resultTypes = searchTypeMetadata($resultTypes, $t);
+				array_push($messages, count($termResults) . " types returned to boolean type search");
+			}catch(Exception $e){
+				throw new CasBrowserException("Exception occurred while searching type metadata in boolean AND term ("
+						. $t->getElementName() . " = " . $t->getValue() . "): " . $e->getMessage());
+			}
+			if(!count($resultTypes)){
+				array_push($messages, "No types found that match the boolean AND query");
+				return array();
+			}
+		}
+	}elseif($booleanCriterion->getOperator() == CAS_Filemgr_BooleanQueryCriteria::$OR_OP){
+		foreach($terms as $t){
+			try{
+				$termResults = searchTypeMetadata($pts, $t);
+			}catch(Exception $e){
+				throw new CasBrowserException("Exception occurred while searching type metadata in boolean OR term ("
+						. $t->getElementName() . " = " . $t->getValue() . "): " . $e->getMessage());
+			}
+			$resultTypes += $termResults;	// Not sure if this is correct
+			if(count($resultTypes) == count($pts)){
+				array_push($messages, "All types match the boolean OR query");
+				return $pts;
+			}
+		}
+	}elseif($booleanCriterion->getOperator() == CAS_Filemgr_BooleanQueryCriteria::$NOT_OP){
+		try{
+			$termResults = searchTypeMetadata($pts, $terms[0]);
+		}catch(Exception $e){
+			throw new CasBrowserException("Exception occurred while searching type metadata in boolean NOT term: "
+					. $e->getMessage());
+		}
+		$resultTypes = array_merge(array_diff($pts, $termResults));
+	}else{
+		throw new CasBrowserException("A BooleanQueryCriteria object has an invalid operator");
+	}
+	array_push($messages, count($resultTypes) . " types found that match the boolean query");
+	return $resultTypes;
+}
+
+function searchTermMetadata($pts, $termCriterion){
+	global $messages;
+	$key = $termCriterion->getElementName();
+	$value = $termCriterion->getValue();
+	array_push($messages, "Searching type metadata for " . $key . " = " . $value . " in " . count($pts) . " types");
+	$resultTypes = array();
+	foreach($pts as $pt){
+		$ptMet = $pt->getTypeMetadata();
+		if(array_key_exists($key, $ptMet->toAssocArray())){
+			if($ptMet->isMultiValued($key)){
+				$ptMetValues = $ptMet->getAllMetadata($key);
+				for($i = 0; $i < count($ptMetValues); $i++){
+					//array_push($messages, "Comparing type " . $pt->getName() . " key " . $key . " value: " . $ptMetValues[$i]);
+					if($ptMetValues[$i] == $value){
+						array_push($resultTypes, $pt);
+						$i = count($ptMetValues);
+					}
+				}
+			}elseif($ptMet->getMetadata($key) == $value){
+				array_push($resultTypes, $pt);
+			}
+		}
+	}
+	array_push($messages, count($resultTypes) . " types found that match the term");
+	return $resultTypes;
+}
+
+function searchTypeMetadata($pts, $criterion){
+	if($criterion == NULL){
+		throw new CasBrowserException("A null criterion was given to search for type metadata");
+	}
+	if($pts == NULL){
+		throw new CasBrowserException("A null list of product types was given to search for type metadata");
+	}
+	if(!count($pts)){
+		throw new CasBrowserException("An empty list of product types was given to search for type metadata");
+	}
+	if($criterion instanceof CAS_Filemgr_TermQueryCriteria){
+		return searchTermMetadata($pts, $criterion);
+	}elseif($criterion instanceof CAS_Filemgr_RangeQueryCriteria){
+		return array();	// Not yet supported
+	}elseif($criterion instanceof CAS_Filemgr_BooleanQueryCriteria){
+		return searchBooleanMetadata($pts, $criterion);
+	}else{
+		throw new CasBrowserException("An unknown query criteria type was encountered while search product type metadata");
+	}
+}
+
+
+
+
+$outputFormat = 'json';	// Hard-coded for now
+
+// Get client handle
+$cb = new CasBrowser();
+$client = $cb->getClient();
+
+$results = array('results'=>array());
+
+// Ceate an array of ProductTypes to be queried
+try{
+	if(!isset($_POST['Types'])){
+		Utils::reportError("POST does not contain 'Types' sub-array", $outputFormat);
+	}
+	if(count($_POST['Types']) == 0){
+		Utils::reportError("No product types were specified in POST", $outputFormat);
+	}
+	$queryTypes = array();
+	$allTypes = $client->getProductTypes();
+	if($_POST['Types'][0] == '*'){
+		$queryTypes = $allTypes;
+	}else{
+		$allTypeNames = array_map(create_function('$t', 'return $t->getName();'), $allTypes);
+		foreach($_POST['Types'] as $type){
+			if(!in_array($type, $allTypeNames)){
+				$errStr = "Error: The type " . $type . " is not used in the repository.  Please use one of: ";
+				$errStr .= $allTypeNames[0];
+				for($i = 1; $i < count($allTypeNames); $i++){
+					$errStr .= ", " . $allTypeNames[$i];
+				}
+				Utils::reportError($errStr, $outputFormat);
+			}
+			array_push($queryTypes, $client->getProductTypeByName($type));
+		}
+		if(!count($queryTypes)){
+			Utils::reportError("No ProductTypes were given to query", $outputFormat);
+		}
+	}
+}catch(Exception $e){
+	Utils::reportError($e->getMessage(), $outputFormat);
+}
+
+// Create the tree of criteria objects that define the query.  The tree root is returned.
+if(!isset($_POST['Criteria'])){
+	Utils::reportError("POST does not contain 'Criteria' sub-array", $outputFormat);
+}
+if(!count($_POST['Criteria'])){
+	Utils::reportError("POST sub-array 'Criteria' contains no criteria", $outputFormat);
+}
+$rootIndex = (isset($_POST['RootIndex']))
+			? intval($_POST['RootIndex'])
+			: 0;
+try{
+	$criteriaTree = Utils::createCriteriaTree($rootIndex, $queryTypes, null);
+}catch(Exception $e){
+	Utils::reportError($e->getMessage(), $outputFormat);
+}
+
+// Search inside of product type metadata for results to further refine search
+// NOTE: This is all currently a dirty hack!  This needs major refinement!
+$allMatchingProducts = array();
+$typesByName = array();
+foreach($queryTypes as $t){
+	$typesByName[$t->getName()] = $t;
+}
+try{
+	$matchingPTs = searchTypeMetadata($queryTypes, $criteriaTree);
+}catch(Exception $e){
+	Utils::reportError("An exception occurred while searching type metadata: " . $e->getMessage(), $outputFormat);
+}
+foreach($matchingPTs as $matchingType){
+	array_splice($queryTypes, array_search($matchingType, $queryTypes), 1);	// Remove types that match from query
+	foreach($client->getProductsByProductType($matchingType) as $p){	// Add all products of matching types
+		array_push($allMatchingProducts, array('product'=>$p, 'typeName'=>$matchingType->getName()));
+	}
+}
+
+// Add criteria to query object
+$query = new CAS_Filemgr_Query();
+$query->addCriterion($criteriaTree);
+
+// Perform the query and collect results
+try{
+	foreach($queryTypes as $type){
+		$queryResultsOfType = $client->query($query, $type);
+		if(count($queryResultsOfType) > 0){
+			foreach($queryResultsOfType as $matchingProduct){
+				array_push($allMatchingProducts, array('product'=>$matchingProduct, 'typeName'=>$type->getName()));
+			}
+		}
+	}
+}catch(Exception $e){
+	Utils::reportError($e->getMessage(), $outputFormat);
+}
+
+// Narrow down the given products to the requested page (if page info is given)
+$requestedProducts = array();
+if(isset($_POST['PageNum']) && isset($_POST['PageSize'])){
+	$pageNum = intval($_POST['PageNum']);
+	$pageSize = intval($_POST['PageSize']);
+	try{
+		$requestedProducts = Utils::paginate($allMatchingProducts, $pageNum, $pageSize);
+	}catch(Exception $e){
+		Utils::reportError($e->getMessage(), $outputFormat);
+	}
+	$results['totalPages'] = ceil(count($allMatchingProducts) / $pageSize);
+}else{
+	$requestedProducts = $allMatchingProducts;
+}
+
+// Get metadata and format requested products
+try{
+	$results['results'] = Utils::formatResults($requestedProducts);
+}catch(Exception $e){
+	Utils::reportError($e->getMessage(), $outputFormat);
+}
+	
+$results['totalProducts'] = count($allMatchingProducts);
+
+$results['messages'] = $messages;
+
+echo json_encode($results);
+
+?>
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/cas-browser/scripts/pageScript.php b/0.8.1-rc1/balance/modules/cas-browser/scripts/pageScript.php
new file mode 100644
index 0000000..5b4aaec
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/scripts/pageScript.php
@@ -0,0 +1,102 @@
+<?php
+/*
+ * 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.
+ */
+
+$module = App::Get()->loadModule();
+require_once(dirname(dirname(__FILE__)) . '/classes/CasBrowser.class.php');
+
+// Extract desired output format from POST
+if(isset($_POST['OutputFormat'])){
+	try{
+		$outputFormat = Utils::getRequestedReturnType($_POST['OutputFormat']);
+	}catch(Exception $e){
+		Utils::reportError($e->getMessage(), 'html');
+	}
+}else{
+	$outputFormat = 'html';
+}
+
+// Get client handle
+$cb = new CasBrowser();
+$client = $cb->getClient();
+
+// Extract ProductType from POST
+if(!isset($_POST['Type'])){
+	Utils::reportError("POST does not contain 'Type' ProductType", $outputFormat);
+}
+$typeName = $_POST['Type'];
+try{
+	$allTypes = $client->getProductTypes();
+	$allTypeNames = array_map(create_function('$t', 'return $t->getName();'), $allTypes);
+	if(!in_array($typeName, $allTypeNames)){
+		$errStr = "The type " . $typeName . " is not used in the repository.  Please use one of: ";
+		for($i = 0; $i < count($allTypeNames) - 1; $i++){
+			$errStr .= $allTypeNames[i] . ", ";
+		}
+		$errStr .= $allTypeNames[count($allTypeNames) - 1];
+		Utils::reportError($errStr, $outputFormat);
+	}
+	$type = $client->getProductTypeByName($typeName);
+}catch(Exception $e){
+	Utils::reportError($e->getMessage(), $outputFormat);
+}
+
+// Extract page number from POST
+if(!isset($_POST['PageNum'])){
+	Utils::reportError("POST does not contain 'PageNum'", $outputFormat);
+}
+$pageNum = intval($_POST['PageNum']);
+
+// Get the requested page
+try{
+	$page = Utils::getPage($type, $pageNum);
+}catch(Exception $e){
+	Utils::reportError($e->getMessage(), $outputFormat);
+}
+
+// Get the products from the requested page -- what we're really after
+$pageProducts = array();
+foreach($page->getPageProducts() as $p){
+	array_push($pageProducts, array('product'=>$p));
+}
+
+// Format results
+if($outputFormat == 'html'){
+	$payload = '<ul class="pp_productList" id="product_list">';
+	foreach($pageProducts as $p){
+		$payload .= '<li><a href="' . $module->moduleRoot . '/product/' . $p['product']->getId() . '">';
+		$payload .= urlDecode($p['product']->getName()) . '</a></li>';
+	}
+	$payload .= "</ul>\n";
+	$payload .= '<input type="hidden" id="total_pages" value="' . $page->getTotalPages() . '">';
+	$payload .= '<input type="hidden" id="page_size" value="' . $page->getPageSize() . '">';
+}elseif ($outputFormat == 'json') {
+	$payload = array();
+	try{
+		$payload['results'] = Utils::formatResults($pageProducts);
+		$payload['totalProducts'] = $client->getNumProducts($type);
+	}catch(Exception $e){
+		Utils::reportError($e->getMessage(), $outputFormat);
+	}
+	$payload['totalPages'] = $page->getTotalPages();
+	$payload['pageSize'] = $page->getPageSize();
+	$payload = json_encode($payload);
+}
+
+echo $payload;
+
+?>
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/cas-browser/scripts/productTypeFilter.php b/0.8.1-rc1/balance/modules/cas-browser/scripts/productTypeFilter.php
new file mode 100644
index 0000000..5724cdd
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/scripts/productTypeFilter.php
@@ -0,0 +1,70 @@
+<?php
+/*
+ * 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.
+ *
+ *
+ *   PRODUCT-TYPE FILTER
+ *   
+ *   HTTP Method: GET
+ *   Input:
+ *     - key    (string) a ProductType metadata key to search on
+ *     - value  (string) the value to use when determining matches
+ *   Output:
+ *     - json   (default) a json array representing all matching product types
+ *              with their defined metadata
+ *              
+ */
+$module = App::Get()->loadModule();
+require_once( $module->modulePath . "/classes/CasBrowser.class.php");
+require_once( $module->modulePath . "/scripts/widgets/ProductTypeListWidget.php");
+
+// Get a Cas-Browser XML/RPC Client
+$browser = new CasBrowser();
+$client  = $browser->getClient();
+
+// Get a list of the product types managed by this server
+$ptypes = $client->getProductTypes();
+
+// Get the metadata key/val pair that will serve as the needle
+$metKey = urldecode($_GET['key']);
+$needle = urldecode($_GET['value']);
+
+$productTypes = array();
+foreach ($ptypes as $pt) {
+	$ptArray = $pt->toAssocArray();
+	
+	// Check whether the requested met key value matches desired value
+	if ($needle == '*' || (isset($ptArray['typeMetadata'][$metKey]) 
+		&& $ptArray['typeMetadata'][$metKey][0] == $needle)) {
+
+		$merged = array_merge($ptArray['typeMetadata'],array(
+			"name" => array($ptArray[App::Get()->settings['browser_pt_name_key']]),
+			"description" => array($ptArray[App::Get()->settings['browser_pt_desc_key']]),
+			"id"   => array($ptArray[App::Get()->settings['browser_pt_id_key']])));
+		
+		$productTypes[] = $merged;
+	}	
+}
+
+// Format output as json
+$json = json_encode($productTypes);
+
+// Output the json result
+header('Content-Type: application/json');
+echo $json;
+
+// We're done.
+exit();
diff --git a/0.8.1-rc1/balance/modules/cas-browser/scripts/queryScript.php b/0.8.1-rc1/balance/modules/cas-browser/scripts/queryScript.php
new file mode 100644
index 0000000..5566994
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/scripts/queryScript.php
@@ -0,0 +1,155 @@
+<?php
+/*
+ * 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.
+ */
+
+$module = App::Get()->loadModule();
+require_once(dirname(dirname(__FILE__)) . '/classes/CasBrowser.class.php');
+
+// Extract desired output format from POST
+if(isset($_POST['OutputFormat'])){
+	try{
+		$outputFormat = Utils::getRequestedReturnType($_POST['OutputFormat']);
+	}catch(Exception $e){
+		Utils::reportError($e->getMessage(), 'html');
+	}
+}else{
+	$outputFormat = 'html';
+}
+
+// Get client handle
+$cb = new CasBrowser();
+$client = $cb->getClient();
+
+// Ceate an array of ProductTypes to be queried
+try{
+	if(!isset($_POST['Types'])){
+		Utils::reportError("POST does not contain 'Types' sub-array", $outputFormat);
+	}
+	if(count($_POST['Types']) == 0){
+		Utils::reportError("No product types were specified in POST", $outputFormat);
+	}
+	$queryTypes = array();
+	$allTypes = $client->getProductTypes();
+	if($_POST['Types'][0] == '*'){
+		$queryTypes = $allTypes;
+	}else{
+		$allTypeNames = array_map(create_function('$t', 'return $t->getName();'), $allTypes);
+		foreach($_POST['Types'] as $type){
+			if(!in_array($type, $allTypeNames)){
+				$errStr = "Error: The type " . $type . " is not used in the repository.  Please use one of: ";
+				$errStr .= $allTypeNames[0];
+				for($i = 1; $i < count($allTypeNames); $i++){
+					$errStr .= ", " . $allTypeNames[$i];
+				}
+				Utils::reportError($errStr, $outputFormat);
+			}
+			array_push($queryTypes, $client->getProductTypeByName($type));
+		}
+		if(!count($queryTypes)){
+			Utils::reportError("No ProductTypes were given to query", $outputFormat);
+		}
+	}
+}catch(Exception $e){
+	Utils::reportError($e->getMessage(), $outputFormat);
+}
+
+// Check if results are desired in a ProductPage and which page of results is desired
+$pagedResults = false;
+$pageNum = 1;
+if(isset($_POST['PagedResults'])){
+	if($_POST['PagedResults']){
+		if(count($queryTypes) != 1){
+			Utils::reportError("Paged queries can only be performed on one ProductType", $outputFormat);
+		}
+		$pagedResults = true;
+		if(isset($_POST['PageNum'])){
+			$pageNum = intval($_POST['PageNum']);
+		}		
+	}
+}
+
+// Create the tree of criteria objects that define the query
+if(!isset($_POST['Criteria'])){
+	Utils::reportError("POST does not contain 'Criteria' sub-array", $outputFormat);
+}
+if(!count($_POST['Criteria'])){
+	Utils::reportError("POST sub-array 'Criteria' contains no criteria", $outputFormat);
+}
+$rootIndex = (isset($_POST['RootIndex']))
+			? intval($_POST['RootIndex'])
+			: 0;
+try{
+	$criteriaTree = Utils::createCriteriaTree($rootIndex, $queryTypes, null);
+}catch(Exception $e){
+	Utils::reportError($e->getMessage(), $outputFormat);
+}
+	
+// Add criteria to query object
+$query = new CAS_Filemgr_Query();
+$query->addCriterion($criteriaTree);
+
+// Perform the query and collect results
+$results = array();
+try{
+	if($pagedResults){
+		$resultPage = $client->pagedQuery($query, $queryTypes[0], $pageNum);
+		foreach($resultPage->getPageProducts() as $p){
+			array_push($results, array('product'=>$p));
+		}
+	}else{
+		foreach($queryTypes as $type){
+			foreach($client->query($query, $type) as $p){
+				array_push($results, array('product'=>$p));
+			}
+		}
+	}
+}catch(Exception $e){
+	Utils::reportError($e->getMessage(), $outputFormat);
+}
+
+// Format results
+try{
+	if($outputFormat == 'html'){
+		$payload = '<ul class="pp_productList" id="product_list">';
+		foreach($results as $r){
+			$payload .= '<li><a href="' . $module->moduleRoot . '/product/' . $r['product']->getId() . '">';
+			$payload .= urlDecode($r['product']->getName()) . '</a></li>';
+		}
+		$payload .= "</ul>\n";
+		if($pagedResults){
+			$payload .= '<input type="hidden" id="total_pages" value="' . $resultPage->getTotalPages() . '">';
+			$payload .= '<input type="hidden" id="page_size" value="' . $resultPage->getPageSize() . '">';
+			$payload .= '<input type="hidden" id="total_type_products" value="' . $client->getNumProducts($queryTypes[0]) . '">';
+		}
+	}elseif ($outputFormat == 'json') {
+		$payload = array();
+		$payload['results'] = Utils::formatResults($results);
+		if($pagedResults){
+			$payload['totalPages'] = $resultPage->getTotalPages();
+			$payload['pageSize'] = $resultPage->getPageSize();
+			$payload['totalProducts'] = $client->getNumProducts($queryTypes[0]);
+		}
+		$payload = json_encode($payload);
+	}
+}catch(Exception $e){
+	Utils::reportError($e->getMessage(), $outputFormat);
+}
+
+echo $payload;
+
+?>
+
diff --git a/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/BasicSearchWidget.php b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/BasicSearchWidget.php
new file mode 100644
index 0000000..917eaa5
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/BasicSearchWidget.php
@@ -0,0 +1,42 @@
+<?php
+/*
+ * 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.
+ */
+
+class BasicSearchWidget 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationWidget {
+	
+	public function __construct($options = array()){}
+	
+	public function render($bEcho = true){
+		$module = App::Get()->loadModule();
+		$str = '';
+		$str .= '<form action="' . $module->moduleRoot . '/queryScript.do" method="POST">';
+		$str .= '<input type="hidden" name="Types[0]" value="*"/>';
+		$str .= '<input type="hidden" name="Criteria[0][CriteriaType]" value="Term"/>';
+		$str .= '<input type="hidden" name="Criteria[0][ElementName]" value="*"/>';
+		$str .= '<input type="text" name ="Criteria[0][Value]"/>';
+		$str .= '<input type="submit" value="Search"/>';
+		$str .= '</form>';
+		
+		if ($bEcho) {
+			echo $str;
+		} else {
+			return $st;
+		}
+	}
+}
+?>
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/CrossTypeSearchWidget.php b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/CrossTypeSearchWidget.php
new file mode 100644
index 0000000..b50de42
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/CrossTypeSearchWidget.php
@@ -0,0 +1,125 @@
+<?php
+/*
+ * 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.
+ */
+
+class CrossTypeSearchWidget 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationWidget {
+	
+	// The id of the HTMLElement that will be modified by filter results.  This must be set before
+	// calling renderScript().
+	public $htmlID;
+	
+	// The ID of the HTMLElement that contains the loading icon that will be
+	// displayed while getting results
+	public $loadingID;
+	
+	// The url of the site base
+	public $siteUrl;
+
+	public function __construct($options = array()){
+		if(isset($options['htmlID'])){
+			$this->htmlID = $options['htmlID'];
+		}
+		if(isset($options['loadingID'])){
+			$this->loadingID = $options['loadingID'];
+		}
+		if(isset($options['siteUrl'])){
+			$this->siteUrl = $options['siteUrl'];
+		}
+	}
+	
+	public function setHtmlId($htmlID){
+		$this->htmlID = $htmlID;
+	}
+	
+	public function setSiteUrl($siteUrl){
+		$this->siteUrl = $siteUrl;
+	}
+	
+	public function render($bEcho = true){
+		$str = '<div id="filter_widget_exclusive_container">';
+		$str .= '<label>Exclusive:</label><input id="exclusive" type="checkbox" checked="checked" onclick="changeExclusive()"/></div>';
+		$str .= '<select id="filterKey">';
+		$filterKeys = Utils::getFacets();
+		natcasesort($filterKeys);
+		foreach($filterKeys as $label){
+			$str .= '<option value="' . $label . '">' . $label . '</option>';
+		}
+		$str .= '</select>&nbsp;=&nbsp;';
+		$str .= '<input type="text" id="filterValue" size="18" alt="filterValue">&nbsp;';
+		$str .= '<input type="button" value="Add" onclick="addFilter()" />';
+		$str .= '<table id="filters"></table>';
+		$str .= '';
+		$str .= '<div id="permalink"></div>';
+		
+		if ($bEcho) {
+			echo $str;
+		} else {
+			return $str;
+		}
+	}
+	
+	public function renderScript($bEcho = true){
+		$str = '<script type="text/javascript">';
+		$str .= 'var htmlID = "' . $this->htmlID . '";';
+		$str .= 'var loadingID = "' . $this->loadingID . '";';
+		$str .= 'var siteUrl = "'. $this->siteUrl . '";';
+		$str .= 'var resultFormat = "json";';
+		$str .= 'var defaultShowEverything = ' . App::Get()->settings['default_show_all'] . ';';
+		$str .= 'var displayedMetadata = new Array(';
+		if(isset(App::Get()->settings['browser_products_met'])){
+			$metList = '';
+			foreach(App::Get()->settings['browser_products_met'] as $met){
+				if(strlen($metList) > 0){
+					$metList .= ',';
+				}
+				$metList .= '"' . $met . '"';
+			}
+			$str .= $metList;
+		}
+		$str .= ');</script>';
+		$str .= '<script type="text/javascript" src="' . App::Get()->request->moduleStatic . '/js/querywidget.js"></script>';
+		$str .= '<script type="text/javascript" src="' . App::Get()->request->moduleStatic . '/js/crosstypesearchwidget.js"></script>';
+		
+		if ($bEcho) {
+			echo $str;
+		} else {
+			return $str;
+		}
+	}
+	
+	public static function parseSegments(){
+		$results = array();
+		$segments = App::Get()->request->segments;
+		if(isset($segments[1]) && $segments[1] != ""){
+			$filterParams = array();
+			for($index = 1; isset($segments[$index]) && $segments[$index] != ""; $index = $index + 2){
+				array_push($filterParams, array($segments[$index], $segments[$index + 1]));
+			}
+			$results['filterParams'] = $filterParams;
+		}
+		if(isset($segments[0]) && $segments[0] != ""){
+			if(intval($segments[0]) == 1){
+				$results['exclusive'] = array('bool'=>'or', 'checked'=>false);
+			}else{
+				$results['exclusive'] = array('bool'=>'and', 'checked'=>true);
+			}
+		}
+		return $results;
+	}
+}
+?>
diff --git a/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/CustomSearchWidget.php b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/CustomSearchWidget.php
new file mode 100644
index 0000000..4102d7b
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/CustomSearchWidget.php
@@ -0,0 +1,178 @@
+<?php
+ /*
+ * 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.
+ * 
+ * 
+ * This widget is configured by the customSearchConfig array in the config file.  The
+ * widget expects the specifications for the criteria to search in sequence.  Each
+ * criteria should start with either 'term' or 'range' as an element in the config
+ * array, followed by the name of the metadata element that will be searched with the
+ * value given in the field corresponding to that criteria.  Finally the next element
+ * or two elements in the config array will be occupied by labels for the inout fields,
+ * depending upon the criteria type (term or range).
+ * Here is an exmaple of a config array for a term criterion and a range criterion in order:
+ * 
+ * customSearchConfig[]=term
+ * customSearchConfig[]=EUFile
+ * customSearchConfig[]=EUFile
+ * customSearchConfig[]=range
+ * customSearchConfig[]=VideoLength
+ * customSearchConfig[]=Min. Video Length
+ * customSearchConfig[]=Max. Video Length
+ * 
+ */
+class CustomSearchWidget 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationWidget {
+	
+	// This array will specify what criteria we use in our search, what types they are
+	// and how they should be labeled.
+	public $criteria;
+	
+	// The ProductType that the widget is filtering.  This must be set before calling
+	// render() or renderScript().
+	public $productType;
+	
+	// The id of the HTMLElement that will be modified by filter results.  This must be set before
+	// calling renderScript().
+	public $htmlID;
+	
+	// The url of the site base
+	public $siteUrl;
+	
+	// Will results be returned in html or json
+	public $resultFormat;
+	
+	public function __construct($options = array()){
+		
+		if(isset($options['productType'])){
+			$this->productType = $options['productType'];
+		}
+		if(isset($options['htmlID'])){
+			$this->htmlID = $options['htmlID'];
+		}
+		if(isset($options['siteUrl'])){
+			$this->siteUrl = $options['siteUrl'];
+		}
+		if(isset($options['resultFormat'])){
+			$this->resultFormat = $options['resultFormat'];
+		}
+		
+		if(!isset(App::Get()->settings['customSearchConfig'])){
+			echo '<div class="error">No criteria config was found for the CustomSearchWidget.</div>';
+			return;
+		}
+		$criteriaConfig = App::Get()->settings['customSearchConfig'];
+		
+		// Build a representation of the criteria to be searched by the widget.
+		// If, during this process, we encounter config values that don't make
+		// sense or an incomplete config for a criterion, we'll simply skip to
+		// the next index in the config array.
+		$this->criteria = array();
+		$configIndex = 0;
+		while(isset($criteriaConfig[$configIndex])){
+			
+			$newCriterion = array();
+			
+			// Look for a criteria type
+			$newType = strtolower($criteriaConfig[$configIndex]);
+			if($newType == 'term' or $newType == 'range'){
+				$newCriterion['type'] = $newType;
+				$configIndex++;
+			}else{
+				continue;	// Let's skip this one and hope that we
+							// find one that makes more sense later.
+			}
+			
+			// Extract the metadata element associated with the criterion
+			$newElement = $criteriaConfig[$configIndex];
+			if(isset($newElement)){
+				$newCriterion['element'] = $newElement;
+				$configIndex++;
+			}else{
+				continue;	// This criterion wasn't finished.
+			}
+			
+			// Extract the labels for the input field(s)
+			$newLabel = $criteriaConfig[$configIndex];
+			if(isset($newLabel)){
+				if($newType == 'term'){
+					$newCriterion['termLabel'] = $newLabel;
+				}else{
+					$newCriterion['minLabel'] = $newLabel;
+					$configIndex++;
+					$newLabel = $criteriaConfig[$configIndex];
+					if(isset($newLabel)){
+						$newCriterion['maxLabel'] = $newLabel;
+					}else{
+						continue;	// This criterion wasn't finished.
+					}
+				}
+			}else{
+				continue;	// This criterion wasn't finished.
+			}
+			
+			array_push($this->criteria, $newCriterion);
+			$configIndex++;
+			
+		}
+	}
+	
+	// Using the criteria representation at this->criteria, we create the fields for
+	// specifying the criteria values.  We put a hidden input tag with an id of the
+	// form termX or rangeX before the specification fields.  The JS will find these
+	// hidden tags and use them to understand whether the fields specify term or
+	// range criteria.  The number following the criterion type is only so that they
+	// have unique IDs.
+	public function render($bEcho = true){
+		$str = '';
+		for($i = 0; $i < count($this->criteria); $i++){
+			if($this->criteria[$i]['type'] == 'term'){
+				$str .= '<input id="term' . $i . '" type="hidden" value="' . $this->criteria[$i]['element'] . '">';
+				$str .= $this->criteria[$i]['termLabel'] . ':&nbsp;<input type="text" size="18" id="inputTerm' . $i . '"><br/>';
+			}else{
+				$str .= '<input id="range' . $i . '" type="hidden" value="' . $this->criteria[$i]['element'] . '">';
+				$str .= $this->criteria[$i]['minLabel'] . ':&nbsp;<input type="text" size="18" id="inputRangeMin' . $i . '">';
+				$str .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
+				$str .= $this->criteria[$i]['maxLabel'] . ':&nbsp;<input type="text" size="18" id="inputRangeMax' . $i . '"><br/>';
+			}
+		}
+		$str .= '<input type="button" value="Search" onclick="customQuery()" />';
+		
+		if ($bEcho) {
+			echo $str;
+		} else {
+			return $str;
+		}
+	}
+	
+	public function renderScript($bEcho = true){
+		$module = App::Get()->loadModule();
+		$str = '';
+		$str .= '<script type="text/javascript">var htmlID = "' . $this->htmlID . '";</script>';
+		$str .= '<script type="text/javascript">var ptName = "' . $this->productType->getName() . '";</script>';
+		$str .= '<script type="text/javascript">var siteUrl = "' . $this->siteUrl . '";</script>';
+		$str .= '<script type="text/javascript">var resultFormat = "' . $this->resultFormat . '";</script>';
+		$str .= '<script type="text/javascript" src="' . $module->moduleStatic . '/js/querywidget.js"></script>';
+		$str .= '<script type="text/javascript" src="' . $module->moduleStatic . '/js/customsearchwidget.js"></script>';
+		
+		if ($bEcho) {
+			echo $str;
+		} else {
+			return $str;
+		}
+	}
+}
+?>
diff --git a/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/FilterWidget.php b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/FilterWidget.php
new file mode 100644
index 0000000..1b0dd3e
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/FilterWidget.php
@@ -0,0 +1,136 @@
+<?php
+/*
+ * 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.
+ */
+
+class FilterWidget 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationWidget {
+
+	// The ProductType that the widget is filtering.  This must be set before calling
+	// render() or renderScript().
+	public $productType;
+	
+	// The ID of the HTMLElement that will be modified by filter results.  This must be set before
+	// calling renderScript().
+	public $htmlID;
+	
+	// The ID of the HTMLElement that contains the loading icon that will be
+	// displayed while getting results
+	public $loadingID;
+	
+	// The url of the site base
+	public $siteUrl;
+	
+	// Whether filtered results will be displayed all at once or in a paged format
+	public $pagedResults;
+	
+	// Will results be returned in html or json
+	public $resultFormat;
+
+	public function __construct($options = array()){
+		if(isset($options['productType'])){
+			$this->productType = $options['productType'];
+		}
+		if(isset($options['htmlID'])){
+			$this->htmlID = $options['htmlID'];
+		}
+		if(isset($options['loadingID'])){
+			$this->loadingID = $options['loadingID'];
+		}
+		if(isset($options['siteUrl'])){
+			$this->siteUrl = $options['siteUrl'];
+		}
+		if(isset($options['pagedResults'])){
+			$this->pagedResults = $options['pagedResults'];
+		}
+		if(isset($options['resultFormat'])){
+			$this->resultFormat = $options['resultFormat'];
+		}
+		
+	}
+	
+	public function setProductType($productType){
+		$this->productType = $productType;
+	}
+	
+	public function setHtmlId($htmlID){
+		$this->htmlID = $htmlID;
+	}
+	
+	public function setSiteUrl($siteUrl){
+		$this->siteUrl = $siteUrl;
+	}
+	
+	public function setPagedResults($pagedResults){
+		$this->pagedResults = $pagedResults;
+	}
+	
+	public function setResultFormat($resultFormat){
+		$this->resultFormat = resultFormat;
+	}
+	
+	public function render($bEcho = true){
+		$str = '';
+		$str .= '<select id="filterKey">';
+		$filterKeys = Utils::getMetadataElements(array($this->productType));
+		natcasesort($filterKeys);
+		foreach($filterKeys as $label){
+			$str .= '<option value="' . $label . '">' . $label . '</option>';
+		}
+		$str .= '</select>&nbsp;=&nbsp;';
+		$str .= '<input type="text" id="filterValue" size="18" alt="filterValue">&nbsp;';
+		$str .= '<input type="button" value="Add" onclick="addFilter()" />';
+		$str .= '<table id="filters"></table>';
+		$str .= '<div id="permalink"></div>';
+		
+		if ($bEcho) {
+			echo $str;
+		} else {
+			return $str;
+		}
+	}
+	
+	public function renderScript($bEcho = true){
+		$str = '<script type="text/javascript">';
+		$str .= 'var htmlID = "' . $this->htmlID . '";';
+		$str .= 'var loadingID = "' . $this->loadingID . '";';
+		$str .= 'var ptName = "' . $this->productType->getName() . '";';
+		$str .= 'var ptID = "' . $this->productType->getId() . '";';
+		$str .= 'var siteUrl = "'. $this->siteUrl . '";';
+		$str .= 'var resultFormat = "' . $this->resultFormat  . '";';
+		$str .= 'var displayedMetadata = new Array(';
+		if(isset(App::Get()->settings['browser_products_met'])){
+			$metList = '';
+			foreach(App::Get()->settings['browser_products_met'] as $met){
+				if(strlen($metList) > 0){
+					$metList .= ',';
+				}
+				$metList .= '"' . $met . '"';
+			}
+			$str .= $metList;
+		}
+		$str .= ');</script>';
+		$str .= '<script type="text/javascript" src="' . App::Get()->request->moduleStatic . '/js/querywidget.js"></script>';
+		$str .= '<script type="text/javascript" src="' . App::Get()->request->moduleStatic . '/js/filterwidget.js"></script>';
+	
+		if ($bEcho) {
+			echo $str;
+		} else {
+			return $str;
+		}
+	}
+}
+?>
diff --git a/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/MetadataDisplayWidget.php b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/MetadataDisplayWidget.php
new file mode 100644
index 0000000..ade2ae5
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/MetadataDisplayWidget.php
@@ -0,0 +1,90 @@
+<?php
+/*
+ * 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.
+ */
+
+class MetadataDisplayWidget
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationWidget {
+	
+	public $metadata;
+	
+	public function __construct($options = array()) {
+		
+	}
+	
+	public function loadMetadata($metadata) {
+		$this->metadata = $metadata;
+	}
+	
+	
+	public function render($bEcho = true) {
+		$str  = "<table class=\"metwidget\"><tbody>";
+		$str .= $this->renderHelper($this->metadata);
+		$str .= "</tbody></table>";
+		if ($bEcho) {
+			echo $str;
+		} else {
+			return $str;
+		}
+	}
+	
+	protected function renderHelper($metadata) {
+		foreach ($metadata as $key => $values) {
+			if ( !empty($values) ) {
+				// Build nested metadata tables recursively
+				$r .= "<tr><th>{$key}</th>";
+				// Associative array means met contains subkeys
+				if (is_array($values) && self::is_assoc($values)) {
+					$r .= "<td>";
+					$r .= "<table class=\"metwidget multivalue\"><tbody>";
+					$r .= $this->renderHelper($values);
+					$r .= "</tbody></table>";
+				} 
+				// Numeric array means met has multiple values
+				else if (is_array($values)) {
+					$r .= "<td>";
+					$r .= "<table class=\"metwidget\"><tbody>";
+					foreach ($values as $val) {
+						if (is_array($val) && self::is_assoc($val)) {
+							$r .= "<tr class=\"multivalue\"><td>";
+							$r .= "<table class=\"metwidget\">";
+							$r .= $this->renderHelper($val);
+							$r .= "</table>";
+						} else {
+							$r .= "<tr><td class=\"value\">";
+							$r .= "<div>". wordwrap($val, 80, "<br />", true) . "</div>";
+						}
+						$r .= "</td></tr>";
+					}
+					$r .= "</tbody></table>";
+				} 
+				// Scalar value means met has one value 
+				else {
+					$r .= "<td class=\"value\">";
+					$r .= "<div>{$values}</div>";
+				}
+				$r .= "</td></tr>";
+			}
+		}
+		return $r;
+	}
+	
+	protected static function is_assoc($array) {
+    	return (is_array($array) && 
+    		(count($array)==0 || 
+    			0 !== count(array_diff_key($array, array_keys(array_keys($array))) )));
+	}
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/ProductDownloadWidget.php b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/ProductDownloadWidget.php
new file mode 100644
index 0000000..e96e640
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/ProductDownloadWidget.php
@@ -0,0 +1,96 @@
+<?php
+/*
+ * 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.
+ */
+
+class ProductDownloadWidget 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationWidget {
+	
+	public $client;
+	public $product;
+	public $dataDeliveryUrl;
+	
+	public function __construct($options = array()) {
+		$this->dataDeliveryUrl = $options['dataDeliveryUrl'];
+		
+	}
+	
+	public function setClient(&$XmlRpcClient) {
+		$this->client = $XmlRpcClient;
+	}
+	
+	public function load($Product) {
+		$this->product = $Product;
+	}
+	
+	public function render($bEcho = true) {
+		$str = '';
+		$references = $this->client->getProductReferences($this->product);
+		if (isset($references['faultCode'])){
+			$str .=  "<div class=\"error\">";
+			$str .=  "Error encountered while attempting to retrieve product references.<br/>";
+			$str .=  "FAULT CODE: $references[faultCode]<br/>";
+			$str .=  "FAULT STRING: $references[faultString]<br/>";
+			$str .=  "</div>";
+			if ($bEcho) {
+				echo $str;
+			} else {
+				return $str;
+			}
+		}
+		
+		$referenceCounter = 0;
+		$str .=  "<table class=\"pdw_downloadTable\">";
+		foreach ($references as $reference){
+			$fileName = end(explode("/",$reference['dataStoreReference']));
+			$fileSize = $reference['fileSize'];
+			$fileSizeStr = "";
+			($fileSize > (1024*1024)) 
+				? $fileSizeStr = number_format(($fileSize/(1024*1024)),1) . " MB"
+				: (($fileSize > (1024))
+					? $fileSizeStr = number_format(($fileSize / 1024),1) . " KB"
+					: $fileSizeStr = $fileSize . " bytes");
+			$str .=  "<tr>";
+			$str .=  "<td>";
+			if ($reference['mimeType'] == 'image/jpeg') {
+				$str .=  "<img class=\"tn\" src=\"".$this->dataDeliveryUrl."/data?refIndex=$referenceCounter&productID={$this->product->getID()}\">";	
+			} else {
+				$str .=  "<img class=\"tn\" src=\"".App::Get()->request->moduleStatic."/img/download-icon.gif\"/>";
+			}
+			$str .=  "</td>";
+			$str .=  "<td style=\"vertical-align:top;\">".urldecode($fileName)." <br/><span id=\"product_download_span\">$fileSizeStr</span><br/>";
+			$str .=  "Mime Type: $reference[mimeType]<br/>";
+			if($reference['mimeType'] == 'image/jpeg') {
+				$str .=  "&nbsp;<a href=\"".$this->dataDeliveryUrl."/data?refIndex=$referenceCounter&productID={$this->product->getID()}\" target=\"_new\">view</a> &nbsp;";
+				$str .=  "<a href=\"getImage.php?productID={$this->product->getID()}&refNumber=$referenceCounter&fileName=$fileName\">save</a>&nbsp;";	
+			}
+			else{
+				$str .=  "<a href=\"".$this->dataDeliveryUrl."/data?refIndex=$referenceCounter&productID={$this->product->getID()}\">save</a> &nbsp;";		
+			}
+				
+			$str .=  "</td>";
+			$str .=  "</tr>";
+			$referenceCounter++;
+		}
+		$str .=  "</table>";
+		
+		if ($bEcho) {
+			echo $str;
+		} else {
+			return $str;
+		}	
+	}
+}
diff --git a/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/ProductPageWidget.php b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/ProductPageWidget.php
new file mode 100644
index 0000000..5c375e8
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/ProductPageWidget.php
@@ -0,0 +1,133 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * Display a page of product results.
+ * @author ahart
+ *
+ */
+class ProductPageWidget 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationWidget {
+	
+	public $page;
+	public $pageMetadata;
+	public $productTypeId;
+	public $returnPage;
+	public $urlBase;
+	
+	private $pageNum;
+	private $pageProducts;
+	private $pageSize;
+	private $totalPages;
+	
+	public function __construct($options = array() ) {
+		$this->page = false;
+		$this->productTypeId = $options['productTypeId']; 
+		$this->returnPage    = (isset($options['returnPage']))
+			? $options['returnPage']
+			: 1;
+		$this->urlBase       = $options['urlBase'];
+	}
+	
+	public function load($productPage, $productMetadata = NULL) {
+		$this->page 		= $productPage;
+		$this->pageMetadata = $productMetadata;
+		$this->pageNum 		= $this->page->getPageNum();
+		$this->pageProducts = $this->page->getPageProducts();
+		$this->pageSize 	= $this->page->getPageSize();
+		$this->totalPages 	= $this->page->getTotalPages();
+	}
+	
+	public function render($bEcho = true) {
+		$str = '';
+		if ($this->page) {
+			$str .= "<table><tr><th>Product Name</th>";
+			$displayedElements = App::Get()->settings['browser_products_met'];
+			foreach($displayedElements as $elementName){
+				$str .= "<th>{$elementName}</th>";
+			}
+			$str .= "</tr>";
+			
+			if ( !App::Get()->settings['browser_private_products_visibility'] ) {
+			// Get a CAS-Browser XML/RPC client
+			$browser  = new CasBrowser();
+			$client   = $browser->getClient();
+			foreach ($this->pageMetadata as $key => $value) {
+				if ( $browser->getProductVisibilityLevel($key) == "deny") {
+					unset($this->pageMetadata[$key]);
+					foreach ($this->pageProducts as $product) {
+						if ($product->id == $key) {
+							$productKey = array_search($product, $this->pageProducts);
+							unset($this->pageProducts[$productKey]);
+						}
+					}
+				}
+			}
+			}
+			foreach($this->pageProducts as $product){
+				$str .= "<tr><td><a href=\"".$this->urlBase."/product/{$product->getId()}/{$this->returnPage}\">" 
+				  . urlDecode(basename($product->getName())) . "</a></td>";
+				foreach($displayedElements as $elementName){
+					$str .= "<td>" . $this->pageMetadata[$product->getId()]->getMetadata($elementName) . "</td>";
+				}
+				$str .= "</tr>";
+			}
+			$str .= "</table>";
+		} 
+		if ($bEcho) {
+			echo $str;
+		} else {
+			return $str;
+		}
+	}
+	
+	public function renderPageDetails($bEcho = true) {
+		// Variables to determine product range displayed and total count
+		$pageNum    = ($this->pageNum == -1)    ? 0 : $this->pageNum;
+		$totalPages = ($this->totalPages == -1) ? 0 : $this->totalPages;
+		
+		$displayCountStart = ($totalPages == 0) ? 0 : $this->pageSize * ($pageNum - 1) + 1;
+		$displayCountEnd   = ($totalPages == 0) ? 0 : $displayCountStart + count($this->pageProducts) - 1;
+		$displayCountStart = ($totalPages > 0 && $displayCountStart == 0) ? 1 : $displayCountStart;
+		
+
+		// 'Previous' and 'Next' page links
+		$linkBase    = App::Get()->loadModule()->moduleRoot . "/products/{$this->productTypeId}/page";
+		$prevPageNum = $this->pageNum -1;
+		$nextPageNum = $this->pageNum +1;
+		 
+		$prevPageLink = ($prevPageNum >= 1) 
+			? "<a href=\"{$linkBase}/{$prevPageNum}\">&lt;&lt;&nbsp;Previous Page</a>"
+			: '';
+		$nextPageLink = ($nextPageNum <= $this->totalPages)
+			? "<a href=\"{$linkBase}/{$nextPageNum}\">Next Page&nbsp;&gt;&gt;</a>"
+			: '';
+	
+		$rangeInfo = "<span class=\"pp_detail\">Page {$pageNum} of {$totalPages} "
+			."(products {$displayCountStart} - {$displayCountEnd})</span>";
+
+		
+		$str = "<div class=\"pp_pageLinks\">{$rangeInfo}&nbsp;&nbsp;{$prevPageLink}&nbsp;&nbsp;{$nextPageLink}</div>\r\n";	
+	
+		if ($bEcho) {
+			echo $str;
+		} else {
+			return $str;
+		}
+	}
+}
diff --git a/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/ProductTypeListWidget.php b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/ProductTypeListWidget.php
new file mode 100644
index 0000000..ca9d5e1
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/scripts/widgets/ProductTypeListWidget.php
@@ -0,0 +1,92 @@
+<?php
+/*
+ * 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.
+ */
+
+class ProductTypeListWidget 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationWidget {
+	
+	public $productTypes;
+	public $urlBase;
+	
+	public function __construct($options = array()) {
+		$this->productTypes = $options['productTypes'];
+		$this->urlBase      = isset($options['urlBase']) 
+			? $options['urlBase']
+			: '';
+	}
+	
+	public function setUrlBase($base) {
+		$this->urlBase = $base;
+	}
+	
+	public function render($bEcho = true) {
+		$str = '';
+		$str.= "<table id=\"productTypeSearch\" class=\"dataTable\">
+			  <thead>
+			    <tr>";
+		// Display the Column Headers
+		foreach (App::Get()->settings['browser_pt_search_met'] as $metKey) {
+			$str .= "<th>".ucwords($metKey)."</th>";
+		}
+		if (isset(App::Get()->settings['browser_pt_hidden_search_met'])) {
+			foreach (App::Get()->settings['browser_pt_hidden_search_met'] as $metKey) {
+				$str .= "<th class=\"hidden\">{$metKey}</th>";
+			}
+		}
+		$str .= "</tr></thead><tbody>";
+
+		// Display the Data
+		foreach ($this->productTypes as $ptKey => $ptMetadata) {
+			if (isset(App::Get()->settings['browser_product_type_ignores']) && 
+				in_array($ptKey,App::Get()->settings['browser_product_type_ignores'])) { continue; }
+			$str .= "<tr>";
+			foreach (App::Get()->settings['browser_pt_search_met'] as $metKey) {
+				if ($metKey == App::Get()->settings['browser_pt_search_linkkey']) {
+					$str .= "<td><a href=\"{$this->urlBase}/products/{$ptKey}\">{$ptMetadata[$metKey][0]}</a>";
+					if(count($ptMetadata[$metKey]) == 2){
+						$str .= "&nbsp({$ptMetadata[$metKey][1]})";
+					}
+					$str .= "</td>";
+				} else {
+					if (count($ptMetadata[$metKey]) > 1) {
+						$str .= "<td>" . implode(", ", $ptMetadata[$metKey]) . "</td>";
+					} else {
+						$str .= "<td>{$ptMetadata[$metKey][0]}</td>";	
+					}
+				}
+			}
+			if (isset(App::Get()->settings['browser_pt_hidden_search_met'])) {
+				foreach (App::Get()->settings['browser_pt_hidden_search_met'] as $metKey) {
+					if (count($ptMetadata[$metKey]) > 1) {
+						$str .= "<td class=\"hidden\">" . implode(", ", $ptMetadata[$metKey]) . "</td>";
+					} else {
+						$str .= "<td class=\"hidden\">{$ptMetadata[$metKey][0]}</td>";	
+					}
+				}
+			}
+			$str .= "</tr>\r\n";
+		}
+		$str .= "</tbody></table>";	
+		$str .= "<br>";
+			
+		if ($bEcho) {
+			echo $str;
+		} else {
+			return $str;
+		}
+	}
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/css/cas-browser.css b/0.8.1-rc1/balance/modules/cas-browser/static/css/cas-browser.css
new file mode 100644
index 0000000..c0dadba
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/css/cas-browser.css
@@ -0,0 +1,289 @@
+/*
+ * 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.
+ */
+
+@CHARSET "UTF-8";
+
+a {
+	color:#236;
+}
+
+br.fiftyPx{
+	margin-bottom:50px;
+}
+
+table#productTypeSearch {
+		
+}
+table#productTypeSearch th.hidden,
+	table#productTypeSearch td.hidden {
+	display:none;	
+}
+
+div#productTypeSearch_length {
+	float:right;
+	text-align:right;
+	margin-bottom:20px;	
+	margin-top:25px;	
+}
+div#productTypeSearch_filter {
+	float:none;
+	margin-top:-20px;	
+	right:0px;	
+	text-align:left;
+	width:450px;
+}
+
+table.dataTable tr {
+	
+}
+table.dataTable tr td {
+	padding:6px;
+	vertical-align:top
+}
+
+table.dataTable  {
+	margin-top:15px;	
+}
+.dataTables_filter input[type=text] {
+	padding:5px;
+	margin-left:0px;	
+	width:97%;
+}
+table.dataTable thead tr th {
+	border-bottom:solid 1px #888;
+}
+
+table.dataTable tbody tr.odd {
+	background-color:#eee;	
+}
+table.dataTable tbody tr.even {
+	background-color:#fff;
+}
+table.dataTable tbody tr.odd td {
+	background-color:transparent;	
+}
+table.dataTable tbody tr.even td {
+	background-color:transparent;	
+}
+table.dataTable tbody tr td.sorting_1,
+	table.dataTable thead tr th.sorting_asc,
+	table.dataTable thead tr th.sorting_desc {
+	background-color:#f3fff3;	
+}
+table.dataTable tbody tr.odd td.sorting_1 {
+	background-color:#e3f3e3;
+}
+table.dataTable tbody tr td a {
+	color:#222;
+}
+
+/**
+ * DATASET
+ */
+ul.tabs {
+	border-bottom:solid 1px #ccc;
+	margin:0px;
+	padding:0px;
+	padding-bottom:6px;
+}
+ul.tabs li {
+	display:inline;
+	margin:0px;
+	padding:0px;
+}
+ul.tabs li a {
+	border:solid 1px #ccc;
+	padding:8px 12px;
+	margin-right:5px;
+	margin-bottom:0px;
+	background-color:#ccc;
+}
+ul.tabs li a.selected {
+	background-color:#fff;
+	border-bottom:solid 1px #fff;
+}
+
+/**
+ * MET VIEWER
+ */
+h4.toggler {
+	padding:5px 0px;
+	text-decoration:underline;
+	cursor:pointer;
+	_cursor:hand;
+	margin-bottom:0px;
+}
+table.metwidget {
+	
+}
+
+
+table.metwidget tr {
+	
+}
+
+table.metwidget th {
+	background-color:#e3f3e3;
+	border-bottom:solid 1px #b3c3b3;	
+	vertical-align:top;
+	padding-top:15px;
+	width:110px;
+}
+table.metwidget td {
+	vertical-align:top;
+	border-bottom:solid 1px #b3c3b3;
+}
+table.metwidget table td {
+	border-bottom:none;
+}
+
+table.metwidget td.value div {
+	background-color:transparent;
+	border:solid 4px #fff;
+	padding:5px;
+}
+table.metwidget.multivalue td {
+	border:none;	
+}
+table.metwidget table {
+	margin:0px;
+	padding:0px;
+}
+
+div#section_products {
+	position:relative;
+}
+div#cas_browser_dataset_download {
+
+}
+
+ul.pp_productList {
+	margin-top:10px;
+	list-style:none;
+	padding-left:0px;
+}
+ul.pp_productList li {
+	line-height:28px;
+	padding-left:0px;
+	margin-left:0px;
+}
+ul.pp_productList li a {
+	text-decoration:none;
+	display:block;
+	background-color:#fff;
+	padding:0px 8px;
+	width:100%;
+}
+ul.pp_productList li a:hover {
+	text-decoration:underline;
+	background-color:#e3f3e3;
+}
+
+input[type=text] {
+	padding:5px;	
+}
+select {
+ 	padding:3px;
+}
+
+div.breadcrumbs {
+	border-bottom:dotted 1px #ccc;
+	padding-bottom:4px;
+	margin-top:-5px;
+}
+
+
+
+table.metwidget {
+	border-top:dotted 1px #bbb;	
+}
+table.metwidget table {
+	border-top:none;	
+}
+
+table.metwidget tr th {
+	vertical-align:top;
+	padding-top:8px;	
+	background-color:#eee;
+	border-bottom:solid 2px #fff;
+}
+table.metwidget tr td {
+	background-color:#f8f8f8;	
+}
+
+ul.tabmenu {
+	margin:0px;
+	padding:0px;
+	margin-bottom:15px;
+	padding-bottom:7px;
+	border-bottom:solid 1px #ccc;	
+}
+ul.tabmenu li {
+	display:inline;
+	border:solid 1px #ccc;
+	background-color:#eee;
+	padding:10px 15px;
+	font-size:1.6em;
+	margin-right:5px;
+	cursor:pointer;
+	_cursor:hand;
+}
+ul.tabmenu li.selected {
+	border-bottom:solid 1px #fff;
+	background-color:#fff;
+}
+
+div#filter_widget {
+	display:none;
+	border:solid 1px #ccc;
+	background-color:#f8f8f8;
+	padding:5px;	
+}
+
+div#section_filter_tools_container {
+	position:relative;	
+}
+div#section_filter_tools_buttons {
+	text-align:right;
+	position:absolute;
+	top:0px;
+	right:0px;
+}
+div#section_filter_tools {
+	margin-bottom:15px;	
+}
+div#filter_widget_exclusive_container {
+	position:absolute;
+	top:25px;
+	right:0px;
+}
+
+
+
+span#product_download_span {
+	color:#555;
+	font-size:0.9em;
+}
+
+div#loading_icon_container {
+	margin-bottom:50px;
+}
+
+img#zip_icon{
+	float:left;
+	margin-right:15px;
+}
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/css/dataTables.css b/0.8.1-rc1/balance/modules/cas-browser/static/css/dataTables.css
new file mode 100644
index 0000000..e70042c
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/css/dataTables.css
@@ -0,0 +1,469 @@
+/*
+ * 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.
+ *
+ *
+ * General page setup
+ */
+#dt_example {
+	font: 80%/1.45em "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
+	margin: 0;
+	padding: 0;
+	color: #333;
+	background-color: #fff;
+}
+
+
+#dt_example #container {
+	width: 800px;
+	margin: 30px auto;
+	padding: 0;
+}
+
+
+#dt_example #footer {
+	margin: 50px auto 0 auto;
+	padding: 0;
+}
+
+#dt_example #demo {
+	margin: 30px auto 0 auto;
+}
+
+#dt_example .big {
+	font-size: 1.3em;
+	font-weight: bold;
+	line-height: 1.6em;
+	color: #4E6CA3;
+}
+
+#dt_example .spacer {
+	height: 20px;
+	clear: both;
+}
+
+#dt_example .clear {
+	clear: both;
+}
+
+#dt_example pre {
+	padding: 15px;
+	background-color: #F5F5F5;
+	border: 1px solid #CCCCCC;
+}
+
+#dt_example h1 {
+	margin-top: 2em;
+	font-size: 1.3em;
+	font-weight: normal;
+	line-height: 1.6em;
+	color: #4E6CA3;
+	border-bottom: 1px solid #B0BED9;
+	clear: both;
+}
+
+#dt_example h2 {
+	font-size: 1.2em;
+	font-weight: normal;
+	line-height: 1.6em;
+	color: #4E6CA3;
+	clear: both;
+}
+
+#dt_example a {
+	color: #0063DC;
+	text-decoration: none;
+}
+
+#dt_example a:hover {
+	text-decoration: underline;
+}
+
+#dt_example ul {
+	color: #B0BED9;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables features
+ */
+
+.dataTables_wrapper {
+	position: relative;
+	min-height: 302px;
+	_height: 302px;
+	clear: both;
+}
+
+.dataTables_processing {
+	position: absolute;
+	top: 0px;
+	left: 50%;
+	width: 250px;
+	margin-left: -125px;
+	border: 1px solid #ddd;
+	text-align: center;
+	color: #999;
+	font-size: 11px;
+	padding: 2px 0;
+}
+
+.dataTables_length {
+	width: 40%;
+	float: left;
+}
+
+.dataTables_filter {
+	width: 50%;
+	float: right;
+	text-align: right;
+}
+
+.dataTables_info {
+	width: 60%;
+	float: left;
+}
+
+.dataTables_paginate {
+	width: 44px;
+	* width: 50px;
+	float: right;
+	text-align: right;
+}
+
+/* Pagination nested */
+.paginate_disabled_previous, .paginate_enabled_previous, .paginate_disabled_next, .paginate_enabled_next {
+	height: 19px;
+	width: 19px;
+	margin-left: 3px;
+	float: left;
+}
+
+.paginate_disabled_previous {
+	background-image: url('../img/dataTables/back_disabled.png');
+}
+
+.paginate_enabled_previous {
+	background-image: url('../img/dataTables/back_enabled.png');
+}
+
+.paginate_disabled_next {
+	background-image: url('../img/dataTables/forward_disabled.png');
+}
+
+.paginate_enabled_next {
+	background-image: url('../img/dataTables/forward_enabled.png');
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables display
+ */
+table.display {
+	margin: 0 auto;
+	width: 100%;
+	clear: both;
+}
+
+table.display thead th {
+	padding: 3px 10px;
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	cursor: pointer;
+	* cursor: hand;
+}
+
+table.display tfoot th {
+	padding: 3px 10px;
+	border-top: 1px solid black;
+	font-weight: bold;
+}
+
+table.display tr.heading2 td {
+	border-bottom: 1px solid #aaa;
+}
+
+table.display td {
+	padding: 3px 10px;
+}
+
+table.display td.center {
+	text-align: center;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables sorting
+ */
+
+.sorting_asc {
+	background: url('../img/dataTables/sort_asc.png') no-repeat center right;
+}
+
+.sorting_desc {
+	background: url('../img/dataTables/sort_desc.png') no-repeat center right;
+}
+
+.sorting {
+	background: url('../img/dataTables/sort_both.png') no-repeat center right;
+}
+
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables row classes
+ */
+table.display tr.odd.gradeA {
+	background-color: #ddffdd;
+}
+
+table.display tr.even.gradeA {
+	background-color: #eeffee;
+}
+
+
+
+
+table.display tr.odd.gradeA {
+	background-color: #ddffdd;
+}
+
+table.display tr.even.gradeA {
+	background-color: #eeffee;
+}
+
+table.display tr.odd.gradeC {
+	background-color: #ddddff;
+}
+
+table.display tr.even.gradeC {
+	background-color: #eeeeff;
+}
+
+table.display tr.odd.gradeX {
+	background-color: #ffdddd;
+}
+
+table.display tr.even.gradeX {
+	background-color: #ffeeee;
+}
+
+table.display tr.odd.gradeU {
+	background-color: #ddd;
+}
+
+table.display tr.even.gradeU {
+	background-color: #eee;
+}
+
+
+tr.odd {
+	background-color: #E2E4FF;
+}
+
+tr.even {
+	background-color: white;
+}
+
+
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Misc
+ */
+.top, .bottom {
+	padding: 15px;
+	background-color: #F5F5F5;
+	border: 1px solid #CCCCCC;
+}
+
+.top .dataTables_info {
+	float: none;
+}
+
+.clear {
+	clear: both;
+}
+
+tfoot input {
+	margin: 0.5em 0;
+	width: 100%;
+	color: #444;
+}
+
+tfoot input.search_init {
+	color: #999;
+}
+
+
+.example_alt_pagination div.dataTables_info {
+	width: 40%;
+}
+
+.example_alt_pagination .dataTables_paginate {
+	width: 400px;
+}
+
+.example_alt_pagination div.dataTables_paginate span.paginate_button,
+ 	.example_alt_pagination div.dataTables_paginate span.paginate_active {
+	border: 1px solid #aaa;
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	padding: 2px 5px;
+	margin: 0 3px;
+	cursor: pointer;
+	*cursor: hand;
+}
+
+.example_alt_pagination div.dataTables_paginate span.paginate_button {
+	background-color: #ddd;
+}
+
+.example_alt_pagination div.dataTables_paginate span.paginate_button:hover {
+	background-color: #ccc;
+}
+
+.example_alt_pagination div.dataTables_paginate span.paginate_active {
+	background-color: #99B3FF;
+}
+
+
+table.display tr.row_selected.odd td {
+	background-color: #B0BED9;
+}
+
+table.display tr.row_selected.even td {
+	background-color: #9FAFD1;
+}
+
+
+/*
+ * Sorting classes for columns
+ */
+/* For the standard odd/even */
+tr.odd td.sorting_1 {
+	background-color: #D3D6FF;
+}
+
+tr.odd td.sorting_2 {
+	background-color: #DADCFF;
+}
+
+tr.odd td.sorting_3 {
+	background-color: #E0E2FF;
+}
+
+tr.even td.sorting_1 {
+	background-color: #EAEBFF;
+}
+
+tr.even td.sorting_2 {
+	background-color: #F2F3FF;
+}
+
+tr.even td.sorting_3 {
+	background-color: #F9F9FF;
+}
+
+
+/* For the Conditional-CSS grading rows */
+/*
+ 	Colour calculations (based off the main row colours)
+  Level 1:
+		dd > c4
+		ee > d5
+	Level 2:
+	  dd > d1
+	  ee > e2
+ */
+tr.odd.gradeA td.sorting_1 {
+	background-color: #c4ffc4;
+}
+
+tr.odd.gradeA td.sorting_2 {
+	background-color: #d1ffd1;
+}
+
+tr.even.gradeA td.sorting_1 {
+	background-color: #d5ffd5;
+}
+
+tr.even.gradeA td.sorting_2 {
+	background-color: #e2ffe2;
+}
+
+tr.odd.gradeC td.sorting_1 {
+	background-color: #c4c4ff;
+}
+
+tr.odd.gradeC td.sorting_2 {
+	background-color: #d1d1ff;
+}
+
+tr.even.gradeC td.sorting_1 {
+	background-color: #d5d5ff;
+}
+
+tr.even.gradeC td.sorting_2 {
+	background-color: #e2e2ff;
+}
+
+tr.odd.gradeX td.sorting_1 {
+	background-color: #ffc4c4;
+}
+
+tr.odd.gradeX td.sorting_2 {
+	background-color: #ffd1d1;
+}
+
+tr.even.gradeX td.sorting_1 {
+	background-color: #ffd5d5;
+}
+
+tr.even.gradeX td.sorting_2 {
+	background-color: #ffe2e2;
+}
+
+tr.odd.gradeU td.sorting_1 {
+	background-color: #c4c4c4;
+}
+
+tr.odd.gradeU td.sorting_2 {
+	background-color: #d1d1d1;
+}
+
+tr.even.gradeU td.sorting_1 {
+	background-color: #d5d5d5;
+}
+
+tr.even.gradeU td.sorting_2 {
+	background-color: #e2e2e2;
+}
+
+
+/*
+ * Row highlighting example
+ */
+.ex_highlight #example tbody tr.even:hover, #example tbody tr.even td.highlighted {
+	background-color: #ECFFB3;
+}
+
+.ex_highlight #example tbody tr.odd:hover, #example tbody tr.odd td.highlighted {
+	background-color: #E6FF99;
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/Sorting icons.psd b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/Sorting icons.psd
new file mode 100644
index 0000000..53b2e06
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/Sorting icons.psd
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/back_disabled.png b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/back_disabled.png
new file mode 100644
index 0000000..881de79
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/back_disabled.png
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/back_enabled.png b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/back_enabled.png
new file mode 100644
index 0000000..c608682
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/back_enabled.png
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/back_enabled_hover.png b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/back_enabled_hover.png
new file mode 100644
index 0000000..d300f10
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/back_enabled_hover.png
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/favicon.ico b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/favicon.ico
new file mode 100644
index 0000000..6eeaa2a
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/favicon.ico
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/forward_disabled.png b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/forward_disabled.png
new file mode 100644
index 0000000..6a6ded7
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/forward_disabled.png
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/forward_enabled.png b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/forward_enabled.png
new file mode 100644
index 0000000..a4e6b53
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/forward_enabled.png
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/forward_enabled_hover.png b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/forward_enabled_hover.png
new file mode 100644
index 0000000..fc46c5e
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/forward_enabled_hover.png
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_asc.png b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_asc.png
new file mode 100644
index 0000000..a88d797
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_asc.png
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_asc_disabled.png b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_asc_disabled.png
new file mode 100644
index 0000000..4e144cf
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_asc_disabled.png
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_both.png b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_both.png
new file mode 100644
index 0000000..1867040
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_both.png
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_desc.png b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_desc.png
new file mode 100644
index 0000000..def071e
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_desc.png
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_desc_disabled.png b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_desc_disabled.png
new file mode 100644
index 0000000..7824973
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/dataTables/sort_desc_disabled.png
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/download-icon.gif b/0.8.1-rc1/balance/modules/cas-browser/static/img/download-icon.gif
new file mode 100644
index 0000000..1de3a38
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/download-icon.gif
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/loading.gif b/0.8.1-rc1/balance/modules/cas-browser/static/img/loading.gif
new file mode 100644
index 0000000..3596a61
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/loading.gif
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/zip-icon-smaller.gif b/0.8.1-rc1/balance/modules/cas-browser/static/img/zip-icon-smaller.gif
new file mode 100644
index 0000000..3722545
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/zip-icon-smaller.gif
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/img/zip-icon.gif b/0.8.1-rc1/balance/modules/cas-browser/static/img/zip-icon.gif
new file mode 100644
index 0000000..9df05e0
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/img/zip-icon.gif
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/js/crosstypesearchwidget.js b/0.8.1-rc1/balance/modules/cas-browser/static/js/crosstypesearchwidget.js
new file mode 100644
index 0000000..67cd212
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/js/crosstypesearchwidget.js
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+function renderJsonOutput(data){
+	output = '<table id="crossPTSearchTable" class="dataTable"><thead><tr><th>Product Name</th><th>ProductType</th>';
+	for(i = 0; i < displayedMetadata.length; i++){
+		output += '<th>' + displayedMetadata[i] + '</th>';
+	}
+	output += '</tr></thead><tbody>';
+	for(i = 0; i < data['results'].length; i++){
+		output += '<tr><td><a href="' + siteUrl + '/product/' + data['results'][i]['id'] + '">';
+		output += data['results'][i]['name'] + '</a></td>';
+		output += '<td>' + data['results'][i]['type'] + '</td>';
+		for(k = 0; k < displayedMetadata.length; k++){
+			output += '<td>' + data['results'][i]['metadata'][displayedMetadata[k]] + '</td>';
+		}
+		output += '</tr>';
+	}
+	output += '</tbody></table><br />';
+	$("#" + htmlID).html(output);
+}
+
+function displayPermalink(){
+	output = 'To see these filters again, go to:<br />' + siteUrl + '/typesearch/';
+	if($("#exclusive").attr("checked")){
+		output += '0/';
+	}else{
+		output += '1/';
+	}
+	for(i = 0; i < allCriteria[criteriaRoot].criteria.length; i++){
+		termIndex = allCriteria[criteriaRoot].criteria[i];
+		termKey = allCriteria[termIndex].element;
+		termValue = allCriteria[termIndex].value;
+		output += termKey + '/' + termValue + '/';
+	}
+	$("#permalink").html(output);
+}
+
+function clearResults(){
+	$("#" + htmlID).html("");
+}
+
+function createFilter(key, value){
+	index = addTermCriteria(key, value, criteriaRoot);
+	var filterText = '<tr id="filter' + index + '">';
+	filterText += '<td>' + key + '</td><td>=</td><td>' + value + '</td>';
+	filterText += '<td align="right">';
+	filterText += '<input type="button" value="Remove" onclick="removeFilter(\'' + index + '\')" />';
+	filterText += '</td></tr>';
+	$("#filters").append(filterText);
+}
+
+function addFilter(){
+	pCurrPage = 1;
+	key = $("#filterKey").val();
+	value = $("#filterValue").val();
+	if(value!=""){
+		$("#permalink").html("");
+		createFilter(key, value);
+		formatCrossTypeQueryRequest();
+		$("#filterValue").val("");
+    }
+}
+
+function removeFilter(filterIndex){
+	pCurrPage = 1;
+	$("#filter" + filterIndex).remove();
+	$("#permalink").html("");
+	removeCriteria(filterIndex);
+	sendCrossTypeRequest();
+}
+
+function getNextPage(){
+	pCurrPage = pCurrPage + 1;
+	sendCrossTypeRequest();
+}
+
+function getPrevPage(){
+	pCurrPage = pCurrPage - 1;
+	sendCrossTypeRequest();
+}
+
+function changeExclusive(){
+	if($("#exclusive").attr("checked")){
+		setExclusiveQuery(true);
+	}else{
+		setExclusiveQuery(false);
+	}
+	if(determineRequest(criteriaRoot)){
+		formatCrossTypeQueryRequest();
+	}
+}
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/js/customsearchwidget.js b/0.8.1-rc1/balance/modules/cas-browser/static/js/customsearchwidget.js
new file mode 100644
index 0000000..c887431
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/js/customsearchwidget.js
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+// When the document is ready, we need to create a representation of the criteria
+// tree in javascript.  This is done by looking for hidden input tags with ids that
+// start with either 'term' or 'range'.  These precede the text input fields to
+// specify criteria of the corresponding type.  We store the ids of the input fields
+// so we can use thier values when the search button is clicked.  Create criteria
+// that have blank values since they haven't been filled in yet; these values will
+// be updated when the user clicks the search button.
+$(document).ready(function(){
+	var parentIndex = addBooleanCriteria('and', null);
+	$('input[id^="term"]').each(function(){
+		var newTermIndex = addTermCriteria($(this).val(), '', parentIndex);
+		allCriteria[newTermIndex].termInputId = $(this).next().attr("id");
+	})
+	$('input[id^="range"]').each(function(){
+		var newRangeIndex = addRangeCriteria($(this).val(), '', '', parentIndex);
+		allCriteria[newRangeIndex].minInputId = $(this).next().attr("id");
+		allCriteria[newRangeIndex].maxInputId = $(this).next().next().attr("id");
+	})
+});
+
+// Since the criteria in our query tree are originally created with empty values, we
+// must grab the values from the input fields at the stored ids.
+function customUpdateCriteria(index){
+	if(allCriteria[index].type == 'term'){
+		allCriteria[index].value = $('#' + allCriteria[index].termInputId).val();
+		$('#' + allCriteria[index].termInputId).val('');
+	}else if(allCriteria[index].type == 'range'){
+		allCriteria[index].min = $('#' + allCriteria[index].minInputId).val();
+		$('#' + allCriteria[index].minInputId).val('');
+		allCriteria[index].max = $('#' + allCriteria[index].maxInputId).val();
+		$('#' + allCriteria[index].maxInputId).val('');
+	}else if(allCriteria[index].type == 'boolean'){
+		for(i = 0; i < allCriteria[index].criteria.length; i++){
+			customUpdateCriteria(allCriteria[index].criteria[i]);
+		}
+	}
+	return;
+}
+
+// This function is called when the search button is clicked.
+function customQuery(){
+	$("#page_num").val(1);	// Set the value of the desired page to 1 (first in
+							// the set).  The user can fetch later pages by
+							// clicking the links for next and previous pages.
+	customUpdateCriteria(criteriaRoot);	// Update the criteria in the query tree
+										// with the values from the input fields.
+	formatQueryRequest("html");	// Perform the query
+}
+
+function renderJsonOutput(data){
+	output = '<ul class="pp_productList" id="product_list">';
+	for(i = 0; i < data['productList'].length; i++){
+		output += '<li><a href="' + siteUrl + '/product/' + data['productList'][i]['id'] + '">';
+		output += data['productList'][i]['name'] + '</li>';
+	}
+	output += '</ul>';
+	output += '<input type="hidden" id="total_pages" value="' + data['totalPages'] + '">';
+	output += '<input type="hidden" id="page_size" value="' + data['pageSize'] + '">';
+	output += '<input type="hidden" id="total_type_products" value="' + data['totalTypeProducts'] + '">';
+	$("#" + htmlID).html(output);
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/js/filterwidget.js b/0.8.1-rc1/balance/modules/cas-browser/static/js/filterwidget.js
new file mode 100644
index 0000000..9c6b56b
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/js/filterwidget.js
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+function createFilter(key, value){
+	if(!allCriteria[criteriaRoot]){
+		criteriaRoot = addBooleanCriteria('and', null);
+	}
+	index = addTermCriteria(key, value, criteriaRoot);
+	var filterText = '<tr id="filter' + index + '">';
+	filterText += '<td>' + key + '</td><td>=</td><td>' + value + '</td>';
+	filterText += '<td align="right">';
+	filterText += '<input type="button" value="Remove" onclick="removeFilter(\'' + index + '\')" />';
+	filterText += '</td></tr>';
+	$("#filters").append(filterText);
+}
+
+function addFilter(){
+	key = $("#filterKey").val();
+	value = $("#filterValue").val();
+	pCurrPage = 1;
+	if(value!=""){
+		$("#permalink").html("");
+		createFilter(key, value);
+		formatQueryRequest(resultFormat);
+		$("#filterValue").val("");
+    }
+}
+
+function removeFilter(filterIndex){
+	pCurrPage = 1;
+	$("#filter" + filterIndex).remove();
+	$("#permalink").html("");
+	removeCriteria(filterIndex);
+	sendRequest(resultFormat);
+}
+
+function renderJsonOutput(data){
+	output = '';
+	if(displayedMetadata.length > 0){
+		output = '<table><thead><tr><th>Product Name</th>';
+		for(i = 0; i < displayedMetadata.length; i++){
+			output += '<th>' + displayedMetadata[i] + '</th>';
+		}
+		output += '</tr></thead><tbody>';
+		for(i = 0; i < data['results'].length; i++){
+			output += '<tr><td><a href="' + siteUrl + '/product/' + data['results'][i]['id'] + '">';
+			output += data['results'][i]['name'] + '</a></td>';
+			for(j = 0; j < displayedMetadata.length; j++){
+				output += '<td>' + data['results'][i]['metadata'][displayedMetadata[j]] + '</td>';
+			}
+			output += '</tr>';
+		}
+		output += '</tbody></table>';
+	}else{
+		output = '<ul class="pp_productList" id="product_list">';
+		for(i = 0; i < data['results'].length; i++){
+			output += '<li><a href="' + siteUrl + '/product/' + data['results'][i]['id'] + '">';
+			output += data['results'][i]['name'] + '</a></li>';
+		}
+		output += '</ul>';
+	}
+	$("#" + htmlID).html(output);
+}
+
+function displayPermalink(){
+	output = 'To see these filters again, go to:<br />' + siteUrl + '/products/' + ptID + '/';
+	for(i = 0; i < allCriteria[criteriaRoot].criteria.length; i++){
+		termIndex = allCriteria[criteriaRoot].criteria[i];
+		termKey = allCriteria[termIndex].element;
+		termValue = allCriteria[termIndex].value;
+		output += termKey + '/' + termValue + '/';
+	}
+	$("#permalink").html(output);
+}
+
+function getNextPage(){
+	pCurrPage = pCurrPage + 1;
+	sendRequest("json");
+}
+
+function getPrevPage(){
+	pCurrPage = pCurrPage - 1;
+	sendRequest("json");
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/js/jcorner.jquery.js b/0.8.1-rc1/balance/modules/cas-browser/static/js/jcorner.jquery.js
new file mode 100644
index 0000000..f96a17b
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/js/jcorner.jquery.js
@@ -0,0 +1,247 @@
+/*!
+ * jQuery corner plugin: simple corner rounding
+ * Examples and documentation at: http://jquery.malsup.com/corner/
+ * version 2.11 (15-JUN-2010)
+ * Requires jQuery v1.3.2 or later
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ * Authors: Dave Methvin and Mike Alsup
+ */
+
+/**
+ *  corner() takes a single string argument:  $('#myDiv').corner("effect corners width")
+ *
+ *  effect:  name of the effect to apply, such as round, bevel, notch, bite, etc (default is round). 
+ *  corners: one or more of: top, bottom, tr, tl, br, or bl.  (default is all corners)
+ *  width:   width of the effect; in the case of rounded corners this is the radius. 
+ *           specify this value using the px suffix such as 10px (yes, it must be pixels).
+ */
+;(function($) { 
+
+var style = document.createElement('div').style,
+    moz = style['MozBorderRadius'] !== undefined,
+    webkit = style['WebkitBorderRadius'] !== undefined,
+    radius = style['borderRadius'] !== undefined || style['BorderRadius'] !== undefined,
+    mode = document.documentMode || 0,
+    noBottomFold = $.browser.msie && (($.browser.version < 8 && !mode) || mode < 8),
+
+    expr = $.browser.msie && (function() {
+        var div = document.createElement('div');
+        try { div.style.setExpression('width','0+0'); div.style.removeExpression('width'); }
+        catch(e) { return false; }
+        return true;
+    })();
+
+$.support = $.support || {};
+$.support.borderRadius = moz || webkit || radius; // so you can do:  if (!$.support.borderRadius) $('#myDiv').corner();
+
+function sz(el, p) { 
+    return parseInt($.css(el,p))||0; 
+};
+function hex2(s) {
+    var s = parseInt(s).toString(16);
+    return ( s.length < 2 ) ? '0'+s : s;
+};
+function gpc(node) {
+    while(node) {
+        var v = $.css(node,'backgroundColor'), rgb;
+        if (v && v != 'transparent' && v != 'rgba(0, 0, 0, 0)') {
+            if (v.indexOf('rgb') >= 0) { 
+                rgb = v.match(/\d+/g); 
+                return '#'+ hex2(rgb[0]) + hex2(rgb[1]) + hex2(rgb[2]);
+            }
+            return v;
+        }
+        if (node.nodeName.toLowerCase() == 'html')
+            break;
+        node = node.parentNode; // keep walking if transparent
+    }
+    return '#ffffff';
+};
+
+function getWidth(fx, i, width) {
+    switch(fx) {
+    case 'round':  return Math.round(width*(1-Math.cos(Math.asin(i/width))));
+    case 'cool':   return Math.round(width*(1+Math.cos(Math.asin(i/width))));
+    case 'sharp':  return Math.round(width*(1-Math.cos(Math.acos(i/width))));
+    case 'bite':   return Math.round(width*(Math.cos(Math.asin((width-i-1)/width))));
+    case 'slide':  return Math.round(width*(Math.atan2(i,width/i)));
+    case 'jut':    return Math.round(width*(Math.atan2(width,(width-i-1))));
+    case 'curl':   return Math.round(width*(Math.atan(i)));
+    case 'tear':   return Math.round(width*(Math.cos(i)));
+    case 'wicked': return Math.round(width*(Math.tan(i)));
+    case 'long':   return Math.round(width*(Math.sqrt(i)));
+    case 'sculpt': return Math.round(width*(Math.log((width-i-1),width)));
+    case 'dogfold':
+    case 'dog':    return (i&1) ? (i+1) : width;
+    case 'dog2':   return (i&2) ? (i+1) : width;
+    case 'dog3':   return (i&3) ? (i+1) : width;
+    case 'fray':   return (i%2)*width;
+    case 'notch':  return width; 
+    case 'bevelfold':
+    case 'bevel':  return i+1;
+    }
+};
+
+$.fn.corner = function(options) {
+    // in 1.3+ we can fix mistakes with the ready state
+    if (this.length == 0) {
+        if (!$.isReady && this.selector) {
+            var s = this.selector, c = this.context;
+            $(function() {
+                $(s,c).corner(options);
+            });
+        }
+        return this;
+    }
+
+    return this.each(function(index){
+        var $this = $(this),
+            // meta values override options
+            o = [$this.attr($.fn.corner.defaults.metaAttr) || '', options || ''].join(' ').toLowerCase(),
+            keep = /keep/.test(o),                       // keep borders?
+            cc = ((o.match(/cc:(#[0-9a-f]+)/)||[])[1]),  // corner color
+            sc = ((o.match(/sc:(#[0-9a-f]+)/)||[])[1]),  // strip color
+            width = parseInt((o.match(/(\d+)px/)||[])[1]) || 10, // corner width
+            re = /round|bevelfold|bevel|notch|bite|cool|sharp|slide|jut|curl|tear|fray|wicked|sculpt|long|dog3|dog2|dogfold|dog/,
+            fx = ((o.match(re)||['round'])[0]),
+            fold = /dogfold|bevelfold/.test(o),
+            edges = { T:0, B:1 },
+            opts = {
+                TL:  /top|tl|left/.test(o),       TR:  /top|tr|right/.test(o),
+                BL:  /bottom|bl|left/.test(o),    BR:  /bottom|br|right/.test(o)
+            },
+            // vars used in func later
+            strip, pad, cssHeight, j, bot, d, ds, bw, i, w, e, c, common, $horz;
+        
+        if ( !opts.TL && !opts.TR && !opts.BL && !opts.BR )
+            opts = { TL:1, TR:1, BL:1, BR:1 };
+            
+        // support native rounding
+        if ($.fn.corner.defaults.useNative && fx == 'round' && (radius || moz || webkit) && !cc && !sc) {
+            if (opts.TL)
+                $this.css(radius ? 'border-top-left-radius' : moz ? '-moz-border-radius-topleft' : '-webkit-border-top-left-radius', width + 'px');
+            if (opts.TR)
+                $this.css(radius ? 'border-top-right-radius' : moz ? '-moz-border-radius-topright' : '-webkit-border-top-right-radius', width + 'px');
+            if (opts.BL)
+                $this.css(radius ? 'border-bottom-left-radius' : moz ? '-moz-border-radius-bottomleft' : '-webkit-border-bottom-left-radius', width + 'px');
+            if (opts.BR)
+                $this.css(radius ? 'border-bottom-right-radius' : moz ? '-moz-border-radius-bottomright' : '-webkit-border-bottom-right-radius', width + 'px');
+            return;
+        }
+            
+        strip = document.createElement('div');
+        $(strip).css({
+            overflow: 'hidden',
+            height: '1px',
+            minHeight: '1px',
+            fontSize: '1px',
+            backgroundColor: sc || 'transparent',
+            borderStyle: 'solid'
+        });
+    
+        pad = {
+            T: parseInt($.css(this,'paddingTop'))||0,     R: parseInt($.css(this,'paddingRight'))||0,
+            B: parseInt($.css(this,'paddingBottom'))||0,  L: parseInt($.css(this,'paddingLeft'))||0
+        };
+
+        if (typeof this.style.zoom != undefined) this.style.zoom = 1; // force 'hasLayout' in IE
+        if (!keep) this.style.border = 'none';
+        strip.style.borderColor = cc || gpc(this.parentNode);
+        cssHeight = $(this).outerHeight();
+
+        for (j in edges) {
+            bot = edges[j];
+            // only add stips if needed
+            if ((bot && (opts.BL || opts.BR)) || (!bot && (opts.TL || opts.TR))) {
+                strip.style.borderStyle = 'none '+(opts[j+'R']?'solid':'none')+' none '+(opts[j+'L']?'solid':'none');
+                d = document.createElement('div');
+                $(d).addClass('jquery-corner');
+                ds = d.style;
+
+                bot ? this.appendChild(d) : this.insertBefore(d, this.firstChild);
+
+                if (bot && cssHeight != 'auto') {
+                    if ($.css(this,'position') == 'static')
+                        this.style.position = 'relative';
+                    ds.position = 'absolute';
+                    ds.bottom = ds.left = ds.padding = ds.margin = '0';
+                    if (expr)
+                        ds.setExpression('width', 'this.parentNode.offsetWidth');
+                    else
+                        ds.width = '100%';
+                }
+                else if (!bot && $.browser.msie) {
+                    if ($.css(this,'position') == 'static')
+                        this.style.position = 'relative';
+                    ds.position = 'absolute';
+                    ds.top = ds.left = ds.right = ds.padding = ds.margin = '0';
+                    
+                    // fix ie6 problem when blocked element has a border width
+                    if (expr) {
+                        bw = sz(this,'borderLeftWidth') + sz(this,'borderRightWidth');
+                        ds.setExpression('width', 'this.parentNode.offsetWidth - '+bw+'+ "px"');
+                    }
+                    else
+                        ds.width = '100%';
+                }
+                else {
+                    ds.position = 'relative';
+                    ds.margin = !bot ? '-'+pad.T+'px -'+pad.R+'px '+(pad.T-width)+'px -'+pad.L+'px' : 
+                                        (pad.B-width)+'px -'+pad.R+'px -'+pad.B+'px -'+pad.L+'px';                
+                }
+
+                for (i=0; i < width; i++) {
+                    w = Math.max(0,getWidth(fx,i, width));
+                    e = strip.cloneNode(false);
+                    e.style.borderWidth = '0 '+(opts[j+'R']?w:0)+'px 0 '+(opts[j+'L']?w:0)+'px';
+                    bot ? d.appendChild(e) : d.insertBefore(e, d.firstChild);
+                }
+                
+                if (fold && $.support.boxModel) {
+                    if (bot && noBottomFold) continue;
+                    for (c in opts) {
+                        if (!opts[c]) continue;
+                        if (bot && (c == 'TL' || c == 'TR')) continue;
+                        if (!bot && (c == 'BL' || c == 'BR')) continue;
+                        
+                        common = { position: 'absolute', border: 'none', margin: 0, padding: 0, overflow: 'hidden', backgroundColor: strip.style.borderColor };
+                        $horz = $('<div/>').css(common).css({ width: width + 'px', height: '1px' });
+                        switch(c) {
+                        case 'TL': $horz.css({ bottom: 0, left: 0 }); break;
+                        case 'TR': $horz.css({ bottom: 0, right: 0 }); break;
+                        case 'BL': $horz.css({ top: 0, left: 0 }); break;
+                        case 'BR': $horz.css({ top: 0, right: 0 }); break;
+                        }
+                        d.appendChild($horz[0]);
+                        
+                        var $vert = $('<div/>').css(common).css({ top: 0, bottom: 0, width: '1px', height: width + 'px' });
+                        switch(c) {
+                        case 'TL': $vert.css({ left: width }); break;
+                        case 'TR': $vert.css({ right: width }); break;
+                        case 'BL': $vert.css({ left: width }); break;
+                        case 'BR': $vert.css({ right: width }); break;
+                        }
+                        d.appendChild($vert[0]);
+                    }
+                }
+            }
+        }
+    });
+};
+
+$.fn.uncorner = function() { 
+    if (radius || moz || webkit)
+        this.css(radius ? 'border-radius' : moz ? '-moz-border-radius' : '-webkit-border-radius', 0);
+    $('div.jquery-corner', this).remove();
+    return this;
+};
+
+// expose options
+$.fn.corner.defaults = {
+    useNative: true, // true if plugin should attempt to use native browser support for border radius rounding
+    metaAttr:  'data-corner' // name of meta attribute to use for options
+};
+    
+})(jQuery);
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/js/jquery-1.4.2-min.js b/0.8.1-rc1/balance/modules/cas-browser/static/js/jquery-1.4.2-min.js
new file mode 100644
index 0000000..7c24308
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/js/jquery-1.4.2-min.js
@@ -0,0 +1,154 @@
+/*!
+ * jQuery JavaScript Library v1.4.2
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Sat Feb 13 22:33:48 2010 -0500
+ */
+(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
+e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
+j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
+"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
+true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
+Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
+(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
+a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
+"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
+function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
+c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
+L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
+"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
+d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
+a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
+!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
+true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
+parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
+false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
+s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
+applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
+else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
+a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
+w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
+cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
+i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
+" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
+this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
+e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
+c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
+a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
+function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
+k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
+C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
+null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
+e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
+f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
+if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
+"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
+a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
+isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
+{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
+if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
+e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
+"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
+d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
+!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
+toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
+u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
+function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
+if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
+t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
+g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
+for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
+1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
+CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
+relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
+l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
+h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
+CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
+g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
+text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
+setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
+h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
+m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
+"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
+h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
+!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
+h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
+q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
+if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
+(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
+function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
+gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
+c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
+{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
+"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
+d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
+a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
+1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
+a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
+c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
+wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
+prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
+this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
+return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
+""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
+this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
+u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
+1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
+return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
+""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
+c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
+c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
+function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
+Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
+"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
+a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
+a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
+"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
+serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
+function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
+global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
+e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
+"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
+false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
+false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
+c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
+d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
+g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
+1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
+"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
+if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
+this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
+"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
+animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
+j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
+this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
+"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
+c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
+this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
+this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
+e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
+c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
+function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
+this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
+k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
+f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
+a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
+c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
+d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
+f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
+"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
+e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/js/jquery.dataTables.min.js b/0.8.1-rc1/balance/modules/cas-browser/static/js/jquery.dataTables.min.js
new file mode 100644
index 0000000..3d417e4
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/js/jquery.dataTables.min.js
@@ -0,0 +1,388 @@
+/*
+ * File:        jquery.dataTables.min.js
+ * Version:     1.4.3
+ * Author:      Allan Jardine (www.sprymedia.co.uk)
+ * 
+ * Copyright 2008-2009 Allan Jardine, all rights reserved.
+ *
+ * This source file is free software, under either the GPL v2 license or a
+ * BSD style license, as supplied with this software.
+ * 
+ * This source file 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 license files for details.
+ */
+(function($){$.fn.dataTableSettings=[];$.fn.dataTableExt={};$.fn.dataTableExt.oApi={};
+$.fn.dataTableExt.oPagination={two_button:{fnInit:function(oSettings,fnCallbackDraw){oSettings.nPrevious=document.createElement("div");
+oSettings.nNext=document.createElement("div");if(oSettings.sTableId!==""){oSettings.nPaginate.setAttribute("id",oSettings.sTableId+"_paginate");
+oSettings.nPrevious.setAttribute("id",oSettings.sTableId+"_previous");oSettings.nNext.setAttribute("id",oSettings.sTableId+"_next")
+}oSettings.nPrevious.className="paginate_disabled_previous";oSettings.nNext.className="paginate_disabled_next";
+oSettings.nPaginate.appendChild(oSettings.nPrevious);oSettings.nPaginate.appendChild(oSettings.nNext);
+$(oSettings.nPaginate).insertAfter(oSettings.nTable);$(oSettings.nPrevious).click(function(){oSettings.iDisplayStart-=oSettings.iDisplayLength;
+if(oSettings.iDisplayStart<0){oSettings.iDisplayStart=0}fnCallbackDraw(oSettings)
+});$(oSettings.nNext).click(function(){if(oSettings.iDisplayStart+oSettings.iDisplayLength<oSettings.aiDisplay.length){oSettings.iDisplayStart+=oSettings.iDisplayLength
+}fnCallbackDraw(oSettings)})},fnUpdate:function(oSettings,fnCallbackDraw){oSettings.nPrevious.className=(oSettings.iDisplayStart===0)?"paginate_disabled_previous":"paginate_enabled_previous";
+oSettings.nNext.className=(oSettings.iDisplayEnd==oSettings.aiDisplay.length)?"paginate_disabled_next":"paginate_enabled_next"
+}},iFullNumbersShowPages:5,full_numbers:{fnInit:function(oSettings,fnCallbackDraw){var nFirst=document.createElement("span");
+var nPrevious=document.createElement("span");var nList=document.createElement("span");
+var nNext=document.createElement("span");var nLast=document.createElement("span");
+nFirst.innerHTML=oSettings.oLanguage.oPaginate.sFirst;nPrevious.innerHTML=oSettings.oLanguage.oPaginate.sPrevious;
+nNext.innerHTML=oSettings.oLanguage.oPaginate.sNext;nLast.innerHTML=oSettings.oLanguage.oPaginate.sLast;
+nFirst.className="paginate_button first";nPrevious.className="paginate_button previous";
+nNext.className="paginate_button next";nLast.className="paginate_button last";oSettings.nPaginate.appendChild(nFirst);
+oSettings.nPaginate.appendChild(nPrevious);oSettings.nPaginate.appendChild(nList);
+oSettings.nPaginate.appendChild(nNext);oSettings.nPaginate.appendChild(nLast);$(nFirst).click(function(){oSettings.iDisplayStart=0;
+fnCallbackDraw(oSettings)});$(nPrevious).click(function(){oSettings.iDisplayStart-=oSettings.iDisplayLength;
+if(oSettings.iDisplayStart<0){oSettings.iDisplayStart=0}fnCallbackDraw(oSettings)
+});$(nNext).click(function(){if(oSettings.iDisplayStart+oSettings.iDisplayLength<oSettings.aiDisplay.length){oSettings.iDisplayStart+=oSettings.iDisplayLength
+}fnCallbackDraw(oSettings)});$(nLast).click(function(){var iPages=parseInt((oSettings.aiDisplay.length-1)/oSettings.iDisplayLength,10)+1;
+oSettings.iDisplayStart=(iPages-1)*oSettings.iDisplayLength;fnCallbackDraw(oSettings)
+});$("span",oSettings.nPaginate).bind("mousedown",function(){return false});$("span",oSettings.nPaginate).bind("selectstart",function(){return false
+});oSettings.nPaginateList=nList},fnUpdate:function(oSettings,fnCallbackDraw){var iPageCount=jQuery.fn.dataTableExt.oPagination.iFullNumbersShowPages;
+var iPageCountHalf=Math.floor(iPageCount/2);var iPages=parseInt((oSettings.aiDisplay.length-1)/oSettings.iDisplayLength,10)+1;
+var iCurrentPage=parseInt(oSettings.iDisplayStart/oSettings.iDisplayLength,10)+1;
+var sList="";var iStartButton;var iEndButton;if(iPages<iPageCount){iStartButton=1;
+iEndButton=iPages}else{if(iCurrentPage<=iPageCountHalf){iStartButton=1;iEndButton=iPageCount
+}else{if(iCurrentPage>=(iPages-iPageCountHalf)){iStartButton=iPages-iPageCount+1;
+iEndButton=iPages}else{iStartButton=iCurrentPage-Math.ceil(iPageCount/2)+1;iEndButton=iStartButton+iPageCount-1
+}}}for(var i=iStartButton;i<=iEndButton;i++){if(iCurrentPage!=i){sList+='<span class="paginate_button">'+i+"</span>"
+}else{sList+='<span class="paginate_active">'+i+"</span>"}}oSettings.nPaginateList.innerHTML=sList;
+$("span",oSettings.nPaginateList).bind("mousedown",function(){return false});$("span",oSettings.nPaginateList).bind("selectstart",function(){return false
+});$("span",oSettings.nPaginateList).click(function(){var iTarget=(this.innerHTML*1)-1;
+oSettings.iDisplayStart=iTarget*oSettings.iDisplayLength;fnCallbackDraw(oSettings);
+return false})}}};$.fn.dataTableExt.oSort={"string-asc":function(a,b){var x=a.toLowerCase();
+var y=b.toLowerCase();return((x<y)?-1:((x>y)?1:0))},"string-desc":function(a,b){var x=a.toLowerCase();
+var y=b.toLowerCase();return((x<y)?1:((x>y)?-1:0))},"html-asc":function(a,b){var x=a.replace(/<.*?>/g,"").toLowerCase();
+var y=b.replace(/<.*?>/g,"").toLowerCase();return((x<y)?-1:((x>y)?1:0))},"html-desc":function(a,b){var x=a.replace(/<.*?>/g,"").toLowerCase();
+var y=b.replace(/<.*?>/g,"").toLowerCase();return((x<y)?1:((x>y)?-1:0))},"date-asc":function(a,b){var x=Date.parse(a);
+var y=Date.parse(b);if(isNaN(x)){x=Date.parse("01/01/1970 00:00:00")}if(isNaN(y)){y=Date.parse("01/01/1970 00:00:00")
+}return x-y},"date-desc":function(a,b){var x=Date.parse(a);var y=Date.parse(b);if(isNaN(x)){x=Date.parse("01/01/1970 00:00:00")
+}if(isNaN(y)){y=Date.parse("01/01/1970 00:00:00")}return y-x},"numeric-asc":function(a,b){var x=a=="-"?0:a;
+var y=b=="-"?0:b;return x-y},"numeric-desc":function(a,b){var x=a=="-"?0:a;var y=b=="-"?0:b;
+return y-x}};$.fn.dataTableExt.aTypes=[function(sData){var sValidChars="0123456789.-";
+var Char;for(i=0;i<sData.length;i++){Char=sData.charAt(i);if(sValidChars.indexOf(Char)==-1){return null
+}}return"numeric"},function(sData){if(!isNaN(Date.parse(sData))){return"date"}return null
+}];$.fn.dataTableExt._oExternConfig={iNextUnique:0};$.fn.dataTable=function(oInit){var _aoSettings=$.fn.dataTableSettings;
+function classSettings(){this.sInstance=null;this.oFeatures={bPaginate:true,bLengthChange:true,bFilter:true,bSort:true,bInfo:true,bAutoWidth:true,bProcessing:false,bSortClasses:true,bStateSave:false};
+this.oLanguage={sProcessing:"Processing...",sLengthMenu:"Show _MENU_ entries per page",sZeroRecords:"No matching records found",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sSearch:"Search:",sUrl:"",oPaginate:{sFirst:"First",sPrevious:"Previous",sNext:"Next",sLast:"Last"}};
+this.aoData=[];this.aiDisplay=[];this.aiDisplayMaster=[];this.aoColumns=[];this.iNextId=0;
+this.asDataSearch=[];this.oPreviousSearch={sSearch:"",bEscapeRegex:true};this.aoPreSearchCols=[];
+this.nInfo=null;this.nProcessing=null;this.iDisplayLength=100;this.iDisplayStart=0;
+this.iDisplayEnd=10;this.aaSorting=[[0,"asc"]];this.asStripClasses=["odd","even"];
+this.fnRowCallback=null;this.fnHeaderCallback=null;this.fnFooterCallback=null;this.fnDrawCallback=null;
+this.fnInitComplete=null;this.nFooter=null;this.sTableId="";this.nTable=null;this.iDefaultSortIndex=0;
+this.bInitialised=false;this.nOpenRow=null;this.nPaginate=null;this.nPrevious=null;
+this.nNext=null;this.sDomPositioning="lfrtip";this.sPaginationType="two_button";this.sAjaxSource=null;
+this.iCookieDuration=60*60*2}this.oApi={};this.fnDraw=function(){_fnReDraw(_fnSettingsFromNode(this[0]))
+};this.fnFilter=function(sInput,iColumn,bEscapeRegex){var oSettings=_fnSettingsFromNode(this[0]);
+if(typeof bEscapeRegex=="undefined"){bEscapeRegex=true}if(typeof iColumn=="undefined"||iColumn===null){_fnFilterComplete(oSettings,{sSearch:sInput,bEscapeRegex:bEscapeRegex},1)
+}else{oSettings.aoPreSearchCols[iColumn].sSearch=sInput;oSettings.aoPreSearchCols[iColumn].bEscapeRegex=bEscapeRegex;
+_fnFilterComplete(oSettings,oSettings.oPreviousSearch,1)}};this.fnSettings=function(nNode){return _fnSettingsFromNode(this[0])
+};this.fnSort=function(aaSort){var oSettings=_fnSettingsFromNode(this[0]);oSettings.aaSorting=aaSort;
+_fnSort(oSettings)};this.fnAddData=function(mData,bRedraw){var aiReturn=[];var iTest;
+if(typeof bRedraw=="undefined"){bRedraw=true}var oSettings=_fnSettingsFromNode(this[0]);
+if(typeof mData[0]=="object"){for(var i=0;i<mData.length;i++){iTest=_fnAddData(oSettings,mData[i]);
+if(iTest==-1){return aiReturn}aiReturn.push(iTest)}}else{iTest=_fnAddData(oSettings,mData);
+if(iTest==-1){return aiReturn}aiReturn.push(iTest)}oSettings.aiDisplay=oSettings.aiDisplayMaster.slice();
+_fnBuildSearchArray(oSettings,1);if(bRedraw){_fnReDraw(oSettings)}return aiReturn
+};this.fnDeleteRow=function(iAODataIndex,fnCallBack){var oSettings=_fnSettingsFromNode(this[0]);
+var i;for(i=0;i<oSettings.aiDisplayMaster.length;i++){if(oSettings.aiDisplayMaster[i]==iAODataIndex){oSettings.aiDisplayMaster.splice(i,1);
+break}}for(i=0;i<oSettings.aiDisplay.length;i++){if(oSettings.aiDisplay[i]==iAODataIndex){oSettings.aiDisplay.splice(i,1)
+}}_fnBuildSearchArray(oSettings,1);if(typeof fnCallBack=="function"){fnCallBack.call(this)
+}if(oSettings.iDisplayStart>oSettings.aiDisplay.length){oSettings.iDisplayStart-=oSettings.iDisplayLength
+}_fnCalculateEnd(oSettings);_fnDraw(oSettings);return oSettings.aoData[iAODataIndex]._aData.slice()
+};this.fnClearTable=function(){var oSettings=_fnSettingsFromNode(this[0]);oSettings.aoData.length=0;
+oSettings.aiDisplayMaster.length=0;oSettings.aiDisplay.length=0;_fnCalculateEnd(oSettings);
+_fnDraw(oSettings)};this.fnOpen=function(nTr,sHtml,sClass){var oSettings=_fnSettingsFromNode(this[0]);
+if(oSettings.nOpenRow!==null){this.fnClose()}var nNewRow=document.createElement("tr");
+var nNewCell=document.createElement("td");nNewRow.appendChild(nNewCell);nNewRow.className=sClass;
+nNewCell.colSpan=oSettings.aoColumns.length;nNewCell.innerHTML=sHtml;$(nNewRow).insertAfter(nTr);
+oSettings.nOpenRow=nNewRow};this.fnClose=function(){var oSettings=_fnSettingsFromNode(this[0]);
+$(oSettings.nOpenRow).remove();oSettings.nOpenRow=null};this.fnGetData=function(iRow){var oSettings=_fnSettingsFromNode(this[0]);
+if(typeof iRow!="undefined"){return oSettings.aoData[iRow]._aData}return _fnGetDataMaster(oSettings)
+};this.fnGetNodes=function(iRow){var oSettings=_fnSettingsFromNode(this[0]);if(typeof iRow!="undefined"){return oSettings.aoData[iRow].nTr
+}return _fnGetTrNodes(oSettings)};this.fnGetPosition=function(nNode){var oSettings=_fnSettingsFromNode(this[0]);
+var i;if(nNode.nodeName=="TR"){for(i=0;i<oSettings.aoData.length;i++){if(oSettings.aoData[i].nTr==nNode){return i
+}}}else{if(nNode.nodeName=="TD"){for(i=0;i<oSettings.aoData.length;i++){var iCorrector=0;
+for(var j=0;j<oSettings.aoColumns.length;j++){if(oSettings.aoColumns[j].bVisible){if(oSettings.aoData[i].nTr.getElementsByTagName("td")[j-iCorrector]==nNode){return[i,j-iCorrector,j]
+}}else{iCorrector++}}}}}return null};this.fnUpdate=function(mData,iRow,iColumn,bRedraw){var oSettings=_fnSettingsFromNode(this[0]);
+var iVisibleColumn;var sRendered;if(typeof bRedraw=="undefined"){bRedraw=true}if(typeof mData!="object"){oSettings.aoData[iRow]._aData[iColumn]=mData;
+if(oSettings.aoColumns[iColumn].fnRender!==null&&oSettings.aoColumns[iColumn].bUseRendered){sRendered=oSettings.aoColumns[iColumn].fnRender({iDataRow:iRow,iDataColumn:iColumn,aData:oSettings.aoData[iRow]._aData});
+oSettings.aoData[iRow]._aData[iColumn]=sRendered}iVisibleColumn=_fnColumnIndexToVisible(oSettings,iColumn);
+if(iVisibleColumn!==null){oSettings.aoData[iRow].nTr.getElementsByTagName("td")[iVisibleColumn].innerHTML=oSettings.aoData[iRow]._aData[iColumn]
+}}else{if(mData.length!=oSettings.aoColumns.length){alert("Warning: An array passed to fnUpdate must have the same number of columns as the table in question - in this case "+oSettings.aoColumns.length);
+return 1}for(var i=0;i<mData.length;i++){oSettings.aoData[iRow]._aData[i]=mData[i];
+if(oSettings.aoColumns[i].fnRender!==null&&oSettings.aoColumns[i].bUseRendered){sRendered=oSettings.aoColumns[i].fnRender({iDataRow:iRow,iDataColumn:i,aData:oSettings.aoData[iRow]._aData});
+oSettings.aoData[iRow]._aData[i]=sRendered}iVisibleColumn=_fnColumnIndexToVisible(oSettings,i);
+if(iVisibleColumn!==null){oSettings.aoData[iRow].nTr.getElementsByTagName("td")[iVisibleColumn].innerHTML=oSettings.aoData[iRow]._aData[i]
+}}}_fnBuildSearchArray(oSettings,1);if(bRedraw){_fnReDraw(oSettings)}return 0};function _fnExternApiFunc(sFunc){return function(){var aArgs=[_fnSettingsFromNode(this[0])].concat(Array.prototype.slice.call(arguments));
+return $.fn.dataTableExt.oApi[sFunc].apply(this,aArgs)}}var bApi=false;for(var sFunc in $.fn.dataTableExt.oApi){if(sFunc){this[sFunc]=_fnExternApiFunc(sFunc);
+bApi=true}}function _fnInitalise(oSettings){if(oSettings.bInitialised===false){setTimeout(function(){_fnInitalise(oSettings)
+},200);return}_fnAddOptionsHtml(oSettings);_fnDrawHead(oSettings);if(oSettings.oFeatures.bSort){_fnSort(oSettings,false);
+_fnSortingClasses(oSettings)}else{oSettings.aiDisplay=oSettings.aiDisplayMaster.slice();
+_fnCalculateEnd(oSettings);_fnDraw(oSettings)}if(oSettings.sAjaxSource!==null){_fnProcessingDisplay(oSettings,true);
+$.getJSON(oSettings.sAjaxSource,null,function(json){for(var i=0;i<json.aaData.length;
+i++){_fnAddData(oSettings,json.aaData[i])}if(oSettings.oFeatures.bSort){_fnSort(oSettings)
+}else{oSettings.aiDisplay=oSettings.aiDisplayMaster.slice();_fnCalculateEnd(oSettings);
+_fnDraw(oSettings)}_fnProcessingDisplay(oSettings,false);if(typeof oSettings.fnInitComplete=="function"){oSettings.fnInitComplete(oSettings)
+}});return}if(oSettings.oFeatures.bSort){_fnSortingClasses(oSettings)}if(typeof oSettings.fnInitComplete=="function"){oSettings.fnInitComplete(oSettings)
+}}function _fnLanguageProcess(oSettings,oLanguage,bInit){if(typeof oLanguage.sProcessing!="undefined"){oSettings.oLanguage.sProcessing=oLanguage.sProcessing
+}if(typeof oLanguage.sLengthMenu!="undefined"){oSettings.oLanguage.sLengthMenu=oLanguage.sLengthMenu
+}if(typeof oLanguage.sZeroRecords!="undefined"){oSettings.oLanguage.sZeroRecords=oLanguage.sZeroRecords
+}if(typeof oLanguage.sInfo!="undefined"){oSettings.oLanguage.sInfo=oLanguage.sInfo
+}if(typeof oLanguage.sInfoEmpty!="undefined"){oSettings.oLanguage.sInfoEmpty=oLanguage.sInfoEmpty
+}if(typeof oLanguage.sInfoFiltered!="undefined"){oSettings.oLanguage.sInfoFiltered=oLanguage.sInfoFiltered
+}if(typeof oLanguage.sInfoPostFix!="undefined"){oSettings.oLanguage.sInfoPostFix=oLanguage.sInfoPostFix
+}if(typeof oLanguage.sSearch!="undefined"){oSettings.oLanguage.sSearch=oLanguage.sSearch
+}if(typeof oLanguage.oPaginate!="undefined"){if(typeof oLanguage.oPaginate!="undefined"){oSettings.oLanguage.oPaginate.sFirst=oLanguage.oPaginate.sFirst
+}if(typeof oLanguage.oPaginate!="undefined"){oSettings.oLanguage.oPaginate.sPrevious=oLanguage.oPaginate.sPrevious
+}if(typeof oLanguage.oPaginate!="undefined"){oSettings.oLanguage.oPaginate.sNext=oLanguage.oPaginate.sNext
+}if(typeof oLanguage.oPaginate!="undefined"){oSettings.oLanguage.oPaginate.sLast=oLanguage.oPaginate.sLast
+}}if(bInit){_fnInitalise(oSettings)}}function _fnAddColumn(oSettings,oOptions){oSettings.aoColumns[oSettings.aoColumns.length++]={sType:null,_bAutoType:true,bVisible:true,bSearchable:true,bSortable:true,sTitle:null,sWidth:null,sClass:null,fnRender:null,bUseRendered:true,iDataSort:oSettings.aoColumns.length-1};
+if(typeof oOptions!="undefined"&&oOptions!==null){var iLength=oSettings.aoColumns.length-1;
+if(typeof oOptions.sType!="undefined"){oSettings.aoColumns[iLength].sType=oOptions.sType;
+oSettings.aoColumns[iLength]._bAutoType=false}if(typeof oOptions.bVisible!="undefined"){oSettings.aoColumns[iLength].bVisible=oOptions.bVisible
+}if(typeof oOptions.bSearchable!="undefined"){oSettings.aoColumns[iLength].bSearchable=oOptions.bSearchable
+}if(typeof oOptions.bSortable!="undefined"){oSettings.aoColumns[iLength].bSortable=oOptions.bSortable
+}if(typeof oOptions.sTitle!="undefined"){oSettings.aoColumns[iLength].sTitle=oOptions.sTitle
+}if(typeof oOptions.sWidth!="undefined"){oSettings.aoColumns[iLength].sWidth=oOptions.sWidth
+}if(typeof oOptions.sClass!="undefined"){oSettings.aoColumns[iLength].sClass=oOptions.sClass
+}if(typeof oOptions.fnRender!="undefined"){oSettings.aoColumns[iLength].fnRender=oOptions.fnRender
+}if(typeof oOptions.bUseRendered!="undefined"){oSettings.aoColumns[iLength].bUseRendered=oOptions.bUseRendered
+}if(typeof oOptions.iDataSort!="undefined"){oSettings.aoColumns[iLength].iDataSort=oOptions.iDataSort
+}}oSettings.aoPreSearchCols[oSettings.aoPreSearchCols.length++]={sSearch:"",bEscapeRegex:true}
+}function _fnAddData(oSettings,aData){if(aData.length!=oSettings.aoColumns.length){return -1
+}var iThisIndex=oSettings.aoData.length;oSettings.aoData.push({_iId:oSettings.iNextId++,_aData:aData.slice(),nTr:document.createElement("tr")});
+var nTd;for(var i=0;i<aData.length;i++){if(oSettings.aoColumns[i].bVisible){nTd=document.createElement("td");
+if(typeof oSettings.aoColumns[i].fnRender=="function"){var sRendered=oSettings.aoColumns[i].fnRender({iDataRow:iThisIndex,iDataColumn:i,aData:aData});
+nTd.innerHTML=sRendered;if(oSettings.aoColumns[i].bUseRendered){oSettings.aoData[iThisIndex]._aData[i]=sRendered
+}}else{nTd.innerHTML=aData[i]}if(oSettings.aoColumns[i].sClass!==null){nTd.className=oSettings.aoColumns[i].sClass
+}if(oSettings.aoColumns[i]._bAutoType&&oSettings.aoColumns[i].sType!="string"){if(oSettings.aoColumns[i].sType===null){oSettings.aoColumns[i].sType=_fnDetectType(aData[i])
+}else{if(oSettings.aoColumns[i].sType=="date"||oSettings.aoColumns[i].sType=="numeric"){oSettings.aoColumns[i].sType=_fnDetectType(aData[i])
+}}}oSettings.aoData[iThisIndex].nTr.appendChild(nTd)}}oSettings.aiDisplayMaster.push(iThisIndex);
+return iThisIndex}function _fnGatherData(oSettings){var nDataNodes;var iDataLength=$("tbody tr").length;
+var iLoop;var i,j;if($("thead th",oSettings.nTable).length!=oSettings.aoColumns.length){alert("Warning - columns do not match")
+}oSettings.nHeader=$("thead",oSettings.nTable)[0];if(typeof $("tfoot",oSettings.nTable)[0]!="undefined"){oSettings.nFooter=$("tfoot",oSettings.nTable)[0]
+}$("tbody tr",oSettings.nTable).each(function(){var iThisIndex=oSettings.aoData.length;
+oSettings.aoData.push({_iId:oSettings.iNextId++,_aData:[],nTr:this});oSettings.aiDisplayMaster.push(iThisIndex);
+var aLocalData=oSettings.aoData[iThisIndex]._aData;$("td",this).each(function(i){aLocalData[i]=this.innerHTML
+})});var iCorrector=0;for(i=0;i<oSettings.aoColumns.length;i++){if(oSettings.aoColumns[i].sTitle===null){oSettings.aoColumns[i].sTitle=$("thead th:nth-child("+(i+1)+")",oSettings.nTable).html()
+}if(oSettings.aoColumns[i]._bAutoType){iLoop=oSettings.aoData.length;for(j=0;j<iLoop;
+j++){if(oSettings.aoColumns[i].sType===null){oSettings.aoColumns[i].sType=_fnDetectType(oSettings.aoData[j]._aData[i])
+}else{if(oSettings.aoColumns[i].sType=="date"||oSettings.aoColumns[i].sType=="numeric"){oSettings.aoColumns[i].sType=_fnDetectType(oSettings.aoData[j]._aData[i])
+}}}}if(oSettings.aoColumns[i].sClass!==null){iLoop=oSettings.aoData.length;for(j=0;
+j<iLoop;j++){oSettings.aoData[j].nTr.getElementsByTagName("td")[i-iCorrector].className+=" "+oSettings.aoColumns[i].sClass
+}}if(typeof oSettings.aoColumns[i].fnRender=="function"){iLoop=oSettings.aoData.length;
+for(j=0;j<iLoop;j++){var sRendered=oSettings.aoColumns[i].fnRender({iDataRow:j,iDataColumn:i,aData:oSettings.aoData[j]._aData});
+oSettings.aoData[j].nTr.getElementsByTagName("td")[i-iCorrector].innerHTML=sRendered;
+if(oSettings.aoColumns[i].bUseRendered){oSettings.aoData[j]._aData[i]=sRendered}}}if(!oSettings.aoColumns[i].bVisible){iLoop=oSettings.aoData.length;
+for(j=0;j<iLoop;j++){var nRemove=oSettings.aoData[j].nTr.getElementsByTagName("td")[i-iCorrector];
+nRemove.parentNode.removeChild(nRemove)}iCorrector++}}}function _fnDrawHead(oSettings){var i;
+var nThOriginals=$("thead th",oSettings.nTable);if(nThOriginals.length==oSettings.aoColumns.length){for(i=0;
+i<oSettings.aoColumns.length;i++){if(oSettings.aoColumns[i].bVisible){if(oSettings.aoColumns[i].sWidth!==null){nThOriginals[i].style.width=oSettings.aoColumns[i].sWidth
+}if(oSettings.aoColumns[i].sTitle!=nThOriginals[i].innerHTML){nThOriginals[i].innerHTML=oSettings.aoColumns[i].sTitle
+}}else{nThOriginals[i].parentNode.removeChild(nThOriginals[i])}}}else{var nTh;var nTr=document.createElement("tr");
+for(i=0;i<oSettings.aoColumns.length;i++){if(oSettings.aoColumns[i].bVisible){nTh=document.createElement("th");
+if(typeof nThOriginals[i]!="undefined"&&nThOriginals[i].className!==""){nTh.className=nThOriginals[i].className
+}if(oSettings.aoColumns[i].sWidth!==null){nTh.style.width=oSettings.aoColumns[i].sWidth
+}nTh.innerHTML=oSettings.aoColumns[i].sTitle;nTr.appendChild(nTh)}}$("thead",oSettings.nTable).html("")[0].appendChild(nTr)
+}if(oSettings.oFeatures.bSort){$("thead th",oSettings.nTable).click(function(e){var iDataIndex=$("thead th",oSettings.nTable).index(this);
+iDataIndex=_fnVisibleToColumnIndex(oSettings,iDataIndex);if(oSettings.aoColumns[iDataIndex].bSortable===false){return
+}_fnProcessingDisplay(oSettings,true);setTimeout(function(){if(e.shiftKey){var bFound=false;
+for(var i=0;i<oSettings.aaSorting.length;i++){if(oSettings.aaSorting[i][0]==iDataIndex){if(oSettings.aaSorting[i][1]=="asc"){oSettings.aaSorting[i][1]="desc"
+}else{oSettings.aaSorting.splice(i,1)}bFound=true;break}}if(bFound===false){oSettings.aaSorting.push([iDataIndex,"asc"])
+}}else{if(oSettings.aaSorting.length==1&&oSettings.aaSorting[0][0]==iDataIndex){oSettings.aaSorting[0][1]=oSettings.aaSorting[0][1]=="asc"?"desc":"asc"
+}else{oSettings.aaSorting.splice(0,oSettings.aaSorting.length);oSettings.aaSorting.push([iDataIndex,"asc"])
+}}_fnSortingClasses(oSettings);_fnSort(oSettings);_fnProcessingDisplay(oSettings,false)
+},0)});$("thead th",oSettings.nTable).mousedown(function(){this.onselectstart=function(){return false
+};return false})}if(oSettings.oFeatures.bAutoWidth){oSettings.nTable.style.width=oSettings.nTable.offsetWidth+"px"
+}}function _fnDraw(oSettings){var i;var anRows=[];var iRowCount=0;var iStrips=oSettings.asStripClasses.length;
+if(oSettings.aiDisplay.length!==0){for(var j=oSettings.iDisplayStart;j<oSettings.iDisplayEnd;
+j++){var nRow=oSettings.aoData[oSettings.aiDisplay[j]].nTr;$(nRow).removeClass(oSettings.asStripClasses.join(" "));
+$(nRow).addClass(oSettings.asStripClasses[iRowCount%iStrips]);if(typeof oSettings.fnRowCallback=="function"){anRows[iRowCount]=oSettings.fnRowCallback(nRow,oSettings.aoData[oSettings.aiDisplay[j]]._aData,iRowCount,j)
+}anRows.push(nRow);iRowCount++}}else{anRows[0]=document.createElement("tr");if(typeof oSettings.asStripClasses[0]!="undefined"){anRows[0].className=oSettings.asStripClasses[0]
+}var nTd=document.createElement("td");nTd.setAttribute("valign","top");nTd.colSpan=oSettings.aoColumns.length;
+nTd.style.textAlign="center";nTd.className="dataTables_empty";nTd.innerHTML=oSettings.oLanguage.sZeroRecords;
+anRows[iRowCount].appendChild(nTd)}if(typeof oSettings.fnHeaderCallback=="function"){oSettings.fnHeaderCallback($("thead tr",oSettings.nTable)[0],_fnGetDataMaster(oSettings),oSettings.iDisplayStart,oSettings.iDisplayEnd,oSettings.aiDisplay)
+}if(typeof oSettings.fnFooterCallback=="function"){oSettings.fnFooterCallback(oSettings.nFooter,_fnGetDataMaster(oSettings),oSettings.iDisplayStart,oSettings.iDisplayEnd,oSettings.aiDisplay)
+}var nTrs=$("tbody:eq(0)>tr",oSettings.nTable);for(i=0;i<nTrs.length;i++){nTrs[i].parentNode.removeChild(nTrs[i])
+}var nBody=$("tbody:eq(0)",oSettings.nTable);for(i=0;i<anRows.length;i++){nBody[0].appendChild(anRows[i])
+}if(oSettings.oFeatures.bPaginate){$.fn.dataTableExt.oPagination[oSettings.sPaginationType].fnUpdate(oSettings,function(oSettings){_fnCalculateEnd(oSettings);
+_fnDraw(oSettings)})}if(oSettings.oFeatures.bInfo){if(oSettings.aiDisplay.length===0&&oSettings.aiDisplay.length==oSettings.aiDisplayMaster.length){oSettings.nInfo.innerHTML=oSettings.oLanguage.sInfoEmpty+" "+oSettings.oLanguage.sInfoPostFix
+}else{if(oSettings.aiDisplay.length===0){oSettings.nInfo.innerHTML=oSettings.oLanguage.sInfoEmpty+" "+oSettings.oLanguage.sInfoFiltered.replace("_MAX_",oSettings.aiDisplayMaster.length)+" "+oSettings.oLanguage.sInfoPostFix
+}else{if(oSettings.aiDisplay.length==oSettings.aiDisplayMaster.length){oSettings.nInfo.innerHTML=oSettings.oLanguage.sInfo.replace("_START_",oSettings.iDisplayStart+1).replace("_END_",oSettings.iDisplayEnd).replace("_TOTAL_",oSettings.aiDisplay.length)+" "+oSettings.oLanguage.sInfoPostFix
+}else{oSettings.nInfo.innerHTML=oSettings.oLanguage.sInfo.replace("_START_",oSettings.iDisplayStart+1).replace("_END_",oSettings.iDisplayEnd).replace("_TOTAL_",oSettings.aiDisplay.length)+" "+oSettings.oLanguage.sInfoFiltered.replace("_MAX_",oSettings.aiDisplayMaster.length)+" "+oSettings.oLanguage.sInfoPostFix
+}}}}_fnSaveState(oSettings);if(typeof oSettings.fnDrawCallback=="function"){oSettings.fnDrawCallback()
+}}function _fnReDraw(oSettings){if(oSettings.oFeatures.bSort){_fnSort(oSettings,oSettings.oPreviousSearch)
+}else{if(oSettings.oFeatures.bFilter){_fnFilterComplete(oSettings,oSettings.oPreviousSearch)
+}else{_fnCalculateEnd(oSettings);_fnDraw(oSettings)}}}function _fnAddOptionsHtml(oSettings){var nHolding=document.createElement("div");
+oSettings.nTable.parentNode.insertBefore(nHolding,oSettings.nTable);var nWrapper=document.createElement("div");
+nWrapper.className="dataTables_wrapper";if(oSettings.sTableId!==""){nWrapper.setAttribute("id",oSettings.sTableId+"_wrapper")
+}var nInsertNode=nWrapper;var sDom=oSettings.sDomPositioning.split("");for(var i=0;
+i<sDom.length;i++){var cOption=sDom[i];if(cOption=="<"){var nNewNode=document.createElement("div");
+var cNext=sDom[i+1];if(cNext=="'"||cNext=='"'){var sClass="";var j=2;while(sDom[i+j]!=cNext){sClass+=sDom[i+j];
+j++}nNewNode.className=sClass;i+=j}nInsertNode.appendChild(nNewNode);nInsertNode=nNewNode
+}else{if(cOption==">"){nInsertNode=nInsertNode.parentNode}else{if(cOption=="l"&&oSettings.oFeatures.bPaginate&&oSettings.oFeatures.bLengthChange){nInsertNode.appendChild(_fnFeatureHtmlLength(oSettings))
+}else{if(cOption=="f"&&oSettings.oFeatures.bFilter){nInsertNode.appendChild(_fnFeatureHtmlFilter(oSettings))
+}else{if(cOption=="r"&&oSettings.oFeatures.bProcessing){nInsertNode.appendChild(_fnFeatureHtmlProcessing(oSettings))
+}else{if(cOption=="t"){nInsertNode.appendChild(oSettings.nTable)}else{if(cOption=="i"&&oSettings.oFeatures.bInfo){nInsertNode.appendChild(_fnFeatureHtmlInfo(oSettings))
+}else{if(cOption=="p"&&oSettings.oFeatures.bPaginate){nInsertNode.appendChild(_fnFeatureHtmlPaginate(oSettings))
+}}}}}}}}}nHolding.parentNode.replaceChild(nWrapper,nHolding)}function _fnFeatureHtmlFilter(oSettings){var nFilter=document.createElement("div");
+if(oSettings.sTableId!==""){nFilter.setAttribute("id",oSettings.sTableId+"_filter")
+}nFilter.className="dataTables_filter";nFilter.innerHTML=oSettings.oLanguage.sSearch+' <input type="text" value="'+oSettings.oPreviousSearch.sSearch.replace('"',"&quot;")+'" />';
+$("input",nFilter).keyup(function(e){_fnFilterComplete(oSettings,{sSearch:this.value,bEscapeRegex:oSettings.oPreviousSearch.bEscapeRegex})
+});return nFilter}function _fnFeatureHtmlInfo(oSettings){var nInfo=document.createElement("div");
+oSettings.nInfo=nInfo;if(oSettings.sTableId!==""){oSettings.nInfo.setAttribute("id",oSettings.sTableId+"_info")
+}oSettings.nInfo.className="dataTables_info";return nInfo}function _fnFeatureHtmlPaginate(oSettings){var nPaginate=document.createElement("div");
+nPaginate.className="dataTables_paginate";oSettings.nPaginate=nPaginate;$.fn.dataTableExt.oPagination[oSettings.sPaginationType].fnInit(oSettings,function(oSettings){_fnCalculateEnd(oSettings);
+_fnDraw(oSettings)});return nPaginate}function _fnFeatureHtmlLength(oSettings){var sName=(oSettings.sTableId==="")?"":'name="'+oSettings.sTableId+'_length"';
+var sStdMenu='<select size="1" '+sName+'><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select>';
+var nLength=document.createElement("div");if(oSettings.sTableId!==""){nLength.setAttribute("id",oSettings.sTableId+"_length")
+}nLength.className="dataTables_length";nLength.innerHTML=oSettings.oLanguage.sLengthMenu.replace("_MENU_",sStdMenu);
+$('select option[value="'+oSettings.iDisplayLength+'"]',nLength).attr("selected",true);
+$("select",nLength).change(function(){oSettings.iDisplayLength=parseInt($(this).val(),10);
+_fnCalculateEnd(oSettings);if(oSettings.iDisplayEnd==oSettings.aiDisplay.length){oSettings.iDisplayStart=oSettings.iDisplayEnd-oSettings.iDisplayLength;
+if(oSettings.iDisplayStart<0){oSettings.iDisplayStart=0}}_fnDraw(oSettings)});return nLength
+}function _fnFeatureHtmlProcessing(oSettings){var nProcessing=document.createElement("div");
+oSettings.nProcessing=nProcessing;if(oSettings.sTableId!==""){oSettings.nProcessing.setAttribute("id",oSettings.sTableId+"_processing")
+}oSettings.nProcessing.appendChild(document.createTextNode(oSettings.oLanguage.sProcessing));
+oSettings.nProcessing.className="dataTables_processing";oSettings.nProcessing.style.visibility="hidden";
+oSettings.nTable.parentNode.insertBefore(oSettings.nProcessing,oSettings.nTable);
+return nProcessing}function _fnProcessingDisplay(oSettings,bShow){if(oSettings.oFeatures.bProcessing){if(bShow){oSettings.nProcessing.style.visibility="visible"
+}else{oSettings.nProcessing.style.visibility="hidden"}}}function _fnFilterComplete(oSettings,oInput,iForce){_fnFilter(oSettings,oInput.sSearch,iForce,oInput.bEscapeRegex);
+for(var i=0;i<oSettings.aoPreSearchCols.length;i++){_fnFilterColumn(oSettings,oSettings.aoPreSearchCols[i].sSearch,i,oSettings.aoPreSearchCols[i].bEscapeRegex)
+}if(typeof oSettings.iInitDisplayStart!="undefined"&&oSettings.iInitDisplayStart!=-1){oSettings.iDisplayStart=oSettings.iInitDisplayStart;
+oSettings.iInitDisplayStart=-1}else{oSettings.iDisplayStart=0}_fnCalculateEnd(oSettings);
+_fnDraw(oSettings);_fnBuildSearchArray(oSettings,0)}function _fnFilterColumn(oSettings,sInput,iColumn,bEscapeRegex){if(sInput===""){return
+}var iIndexCorrector=0;var sRegexMatch=bEscapeRegex?_fnEscapeRegex(sInput):sInput;
+var rpSearch=new RegExp(sRegexMatch,"i");for(i=oSettings.aiDisplay.length-1;i>=0;
+i--){if(!rpSearch.test(oSettings.aoData[oSettings.aiDisplay[i]]._aData[iColumn])){oSettings.aiDisplay.splice(i,1);
+iIndexCorrector++}}}function _fnFilter(oSettings,sInput,iForce,bEscapeRegex){var flag,i,j;
+if(typeof iForce=="undefined"||iForce===null){iForce=0}if(typeof bRedraw=="undefined"||bRedraw===null){bRedraw=true
+}var asSearch=bEscapeRegex?_fnEscapeRegex(sInput).split(" "):sInput.split(" ");var sRegExpString="^(?=.*?"+asSearch.join(")(?=.*?")+").*$";
+var rpSearch=new RegExp(sRegExpString,"i");if(sInput.length<=0){oSettings.aiDisplay.splice(0,oSettings.aiDisplay.length);
+oSettings.aiDisplay=oSettings.aiDisplayMaster.slice()}else{if(oSettings.aiDisplay.length==oSettings.aiDisplayMaster.length||oSettings.oPreviousSearch.sSearch.length>sInput.length||iForce==1||sInput.indexOf(oSettings.oPreviousSearch.sSearch)!==0){oSettings.aiDisplay.splice(0,oSettings.aiDisplay.length);
+_fnBuildSearchArray(oSettings,1);for(i=0;i<oSettings.aiDisplayMaster.length;i++){if(rpSearch.test(oSettings.asDataSearch[i])){oSettings.aiDisplay.push(oSettings.aiDisplayMaster[i])
+}}}else{var iIndexCorrector=0;for(i=0;i<oSettings.asDataSearch.length;i++){if(!rpSearch.test(oSettings.asDataSearch[i])){oSettings.aiDisplay.splice(i-iIndexCorrector,1);
+iIndexCorrector++}}}}oSettings.oPreviousSearch.sSearch=sInput;oSettings.oPreviousSearch.bEscapeRegex=bEscapeRegex
+}function _fnSort(oSettings,bApplyClasses){var sDynamicSort="var fnLocalSorting = function(a,b){var iTest;var oSort = $.fn.dataTableExt.oSort;var aoData = oSettings.aoData;";
+var aaSort=oSettings.aaSorting;var iDataSort;var iDataType;if(aaSort.length!==0){for(var i=0;
+i<aaSort.length-1;i++){iDataSort=oSettings.aoColumns[aaSort[i][0]].iDataSort;iDataType=oSettings.aoColumns[iDataSort].sType;
+sDynamicSort+="iTest = oSort['"+iDataType+"-"+aaSort[i][1]+"']( aoData[a]._aData["+iDataSort+"], aoData[b]._aData["+iDataSort+"] ); if ( iTest === 0 )"
+}iDataSort=oSettings.aoColumns[aaSort[aaSort.length-1][0]].iDataSort;iDataType=oSettings.aoColumns[iDataSort].sType;
+sDynamicSort+="iTest = oSort['"+iDataType+"-"+aaSort[aaSort.length-1][1]+"']( aoData[a]._aData["+iDataSort+"], aoData[b]._aData["+iDataSort+"] ); return iTest;}";
+eval(sDynamicSort);oSettings.aiDisplayMaster.sort(fnLocalSorting)}if(typeof bApplyClasses=="undefined"||bApplyClasses){_fnSortingClasses(oSettings)
+}if(oSettings.oFeatures.bFilter){_fnFilterComplete(oSettings,oSettings.oPreviousSearch,1)
+}else{oSettings.aiDisplay=oSettings.aiDisplayMaster.slice();_fnCalculateEnd(oSettings);
+_fnDraw(oSettings)}}function _fnSortingClasses(oSettings){$("thead th",oSettings.nTable).removeClass("sorting_asc sorting_desc sorting");
+var iCorrector=0;var i;for(i=0;i<oSettings.aoColumns.length;i++){if(oSettings.aoColumns[i].bSortable&&oSettings.aoColumns[i].bVisible){var sClass="sorting";
+for(var j=0;j<oSettings.aaSorting.length;j++){if(oSettings.aaSorting[j][0]==i){sClass=(oSettings.aaSorting[j][1]=="asc")?"sorting_asc":"sorting_desc";
+break}}$("thead th:eq("+_fnColumnIndexToVisible(oSettings,i)+")",oSettings.nTable).addClass(sClass)
+}}if(oSettings.oFeatures.bSortClasses){var nTrs=_fnGetTrNodes(oSettings);$("td",nTrs).removeClass("sorting_1 sorting_2 sorting_3");
+for(i=0;i<oSettings.aaSorting.length;i++){if(i<=1){$("td:eq("+_fnColumnIndexToVisible(oSettings,oSettings.aaSorting[i][0])+")",nTrs).addClass("sorting_"+(i+1))
+}else{$("td:eq("+_fnColumnIndexToVisible(oSettings,oSettings.aaSorting[i][0])+")",nTrs).addClass("sorting_3")
+}}}}function _fnVisibleToColumnIndex(oSettings,iMatch){var iColumn=-1;for(var i=0;
+i<oSettings.aoColumns.length;i++){if(oSettings.aoColumns[i].bVisible===true){iColumn++
+}if(iColumn==iMatch){return i}}return null}function _fnColumnIndexToVisible(oSettings,iMatch){var iVisible=-1;
+for(var i=0;i<oSettings.aoColumns.length;i++){if(oSettings.aoColumns[i].bVisible===true){iVisible++
+}if(i==iMatch){return oSettings.aoColumns[i].bVisible===true?iVisible:null}}return null
+}function _fnBuildSearchArray(oSettings,iMaster){oSettings.asDataSearch.splice(0,oSettings.asDataSearch.length);
+var aArray=(typeof iMaster!="undefined"&&iMaster==1)?oSettings.aiDisplayMaster:oSettings.aiDisplay;
+for(i=0;i<aArray.length;i++){oSettings.asDataSearch[i]="";for(j=0;j<oSettings.aoColumns.length;
+j++){if(oSettings.aoColumns[j].bSearchable){var sData=oSettings.aoData[aArray[i]]._aData[j];
+if(oSettings.aoColumns[j].sType=="html"){oSettings.asDataSearch[i]+=sData.replace(/\n/g," ").replace(/<.*?>/g,"")+" "
+}else{if(typeof sData=="string"){oSettings.asDataSearch[i]+=sData.replace(/\n/g," ")+" "
+}else{oSettings.asDataSearch[i]+=sData+" "}}}}}}function _fnCalculateEnd(oSettings){if(oSettings.oFeatures.bPaginate===false){oSettings.iDisplayEnd=oSettings.aiDisplay.length
+}else{if(oSettings.iDisplayStart+oSettings.iDisplayLength>oSettings.aiDisplay.length){oSettings.iDisplayEnd=oSettings.aiDisplay.length
+}else{oSettings.iDisplayEnd=oSettings.iDisplayStart+oSettings.iDisplayLength}}}function _fnConvertToWidth(sWidth,nParent){if(!sWidth||sWidth===null||sWidth===""){return 0
+}if(typeof nParent=="undefined"){nParent=document.getElementsByTagName("body")[0]
+}var iWidth;var nTmp=document.createElement("div");nTmp.style.width=sWidth;nParent.appendChild(nTmp);
+iWidth=nTmp.offsetWidth;nParent.removeChild(nTmp);return(iWidth)}function _fnCalculateColumnWidths(oSettings){var iTableWidth=oSettings.nTable.offsetWidth;
+var iTotalUserIpSize=0;var iTmpWidth;var iVisibleColumns=0;var i;var oHeaders=$("thead th",oSettings.nTable);
+for(i=0;i<oSettings.aoColumns.length;i++){if(oSettings.aoColumns[i].bVisible){iVisibleColumns++;
+if(oSettings.aoColumns[i].sWidth!==null){iTmpWidth=_fnConvertToWidth(oSettings.aoColumns[i].sWidth,oSettings.nTable.parentNode);
+iTotalUserIpSize+=iTmpWidth;oSettings.aoColumns[i].sWidth=iTmpWidth+"px"}}}if(oSettings.aoColumns.length==oHeaders.length&&iTotalUserIpSize===0){for(i=0;
+i<oSettings.aoColumns.length;i++){oSettings.aoColumns[i].sWidth=oHeaders[i].offsetWidth+"px"
+}}else{var nCalcTmp=oSettings.nTable.cloneNode(false);nCalcTmp.setAttribute("id","");
+var sTableTmp='<table class="'+nCalcTmp.className+'">';var sCalcHead="<tr>";var sCalcHtml="<tr>";
+for(i=0;i<oSettings.aoColumns.length;i++){if(oSettings.aoColumns[i].bVisible){sCalcHead+="<th>"+oSettings.aoColumns[i].sTitle+"</th>";
+if(oSettings.aoColumns[i].sWidth!==null){var sWidth="";if(oSettings.aoColumns[i].sWidth!==null){sWidth=' style="width:'+oSettings.aoColumns[i].sWidth+';"'
+}sCalcHtml+="<td"+sWidth+' tag_index="'+i+'">'+fnGetMaxLenString(oSettings,i)+"</td>"
+}else{sCalcHtml+='<td tag_index="'+i+'">'+fnGetMaxLenString(oSettings,i)+"</td>"}}}sCalcHead+="</tr>";
+sCalcHtml+="</tr>";nCalcTmp=$(sTableTmp+sCalcHead+sCalcHtml+"</table>")[0];nCalcTmp.style.width=iTableWidth+"px";
+nCalcTmp.style.visibility="hidden";nCalcTmp.style.position="absolute";oSettings.nTable.parentNode.appendChild(nCalcTmp);
+var oNodes=$("td",nCalcTmp);var iIndex;for(i=0;i<oNodes.length;i++){iIndex=oNodes[i].getAttribute("tag_index");
+oSettings.aoColumns[iIndex].sWidth=$("td",nCalcTmp)[i].offsetWidth+"px"}oSettings.nTable.parentNode.removeChild(nCalcTmp)
+}}function fnGetMaxLenString(oSettings,iCol){var iMax=0;var iMaxIndex=-1;for(var i=0;
+i<oSettings.aoData.length;i++){if(oSettings.aoData[i]._aData[iCol].length>iMax){iMax=oSettings.aoData[i]._aData[iCol].length;
+iMaxIndex=i}}if(iMaxIndex>=0){return oSettings.aoData[iMaxIndex]._aData[iCol]}return""
+}function _fnArrayCmp(aArray1,aArray2){if(aArray1.length!=aArray2.length){return 1
+}for(var i=0;i<aArray1.length;i++){if(aArray1[i]!=aArray2[i]){return 2}}return 0}function _fnDetectType(sData){var aTypes=$.fn.dataTableExt.aTypes;
+var iLen=aTypes.length;for(var i=0;i<iLen;i++){var sType=aTypes[i](sData);if(sType!==null){return sType
+}}return"string"}function _fnSettingsFromNode(nTable){for(var i=0;i<_aoSettings.length;
+i++){if(_aoSettings[i].nTable==nTable){return _aoSettings[i]}}return null}function _fnGetDataMaster(oSettings){var aData=[];
+var iLen=oSettings.aoData.length;for(var i=0;i<iLen;i++){aData.push(oSettings.aoData[i]._aData)
+}return aData}function _fnGetTrNodes(oSettings){var aNodes=[];var iLen=oSettings.aoData.length;
+for(var i=0;i<iLen;i++){aNodes.push(oSettings.aoData[i].nTr)}return aNodes}function _fnEscapeRegex(sVal){var acEscape=["/",".","*","+","?","|","(",")","[","]","{","}","\\","$","^"];
+var reReplace=new RegExp("(\\"+acEscape.join("|\\")+")","g");return sVal.replace(reReplace,"\\$1")
+}function _fnSaveState(oSettings){if(!oSettings.oFeatures.bStateSave){return}var sValue="{";
+sValue+='"iStart": '+oSettings.iDisplayStart+",";sValue+='"iEnd": '+oSettings.iDisplayEnd+",";
+sValue+='"iLength": '+oSettings.iDisplayLength+",";sValue+='"sFilter": "'+oSettings.oPreviousSearch.sSearch.replace('"','\\"')+'",';
+sValue+='"sFilterEsc": '+oSettings.oPreviousSearch.bEscapeRegex+",";sValue+='"aaSorting": [ ';
+for(var i=0;i<oSettings.aaSorting.length;i++){sValue+="["+oSettings.aaSorting[i][0]+",'"+oSettings.aaSorting[i][1]+"'],"
+}sValue=sValue.substring(0,sValue.length-1);sValue+="]}";_fnCreateCookie("SpryMedia_DataTables_"+oSettings.sInstance,sValue,oSettings.iCookieDuration)
+}function _fnLoadState(oSettings){if(!oSettings.oFeatures.bStateSave){return}var sData=_fnReadCookie("SpryMedia_DataTables_"+oSettings.sInstance);
+if(sData!==null&&sData!==""){if(typeof JSON=="object"&&typeof JSON.parse=="function"){oData=JSON.parse(sData.replace(/'/g,'"'))
+}else{oData=eval("("+sData+")")}oSettings.iDisplayStart=oData.iStart;oSettings.iInitDisplayStart=oData.iStart;
+oSettings.iDisplayEnd=oData.iEnd;oSettings.iDisplayLength=oData.iLength;oSettings.oPreviousSearch.sSearch=oData.sFilter;
+oSettings.aaSorting=oData.aaSorting.slice();if(typeof oData.sFilterEsc!="undefined"){oSettings.oPreviousSearch.bEscapeRegex=oData.sFilterEsc
+}}}function _fnCreateCookie(sName,sValue,iSecs){var date=new Date();date.setTime(date.getTime()+(iSecs*1000));
+sName+="_"+window.location.pathname.replace(/[\/:]/g,"");document.cookie=sName+"="+sValue+"; expires="+date.toGMTString()+"; path=/"
+}function _fnReadCookie(sName){var sNameEQ=sName+"_"+window.location.pathname.replace(/[\/:]/g,"")+"=";
+var sCookieContents=document.cookie.split(";");for(var i=0;i<sCookieContents.length;
+i++){var c=sCookieContents[i];while(c.charAt(0)==" "){c=c.substring(1,c.length)}if(c.indexOf(sNameEQ)===0){return c.substring(sNameEQ.length,c.length)
+}}return null}if(bApi){this.oApi._fnInitalise=_fnInitalise;this.oApi._fnLanguageProcess=_fnLanguageProcess;
+this.oApi._fnAddColumn=_fnAddColumn;this.oApi._fnAddData=_fnAddData;this.oApi._fnGatherData=_fnGatherData;
+this.oApi._fnDrawHead=_fnDrawHead;this.oApi._fnDraw=_fnDraw;this.oApi._fnAddOptionsHtml=_fnAddOptionsHtml;
+this.oApi._fnFeatureHtmlFilter=_fnFeatureHtmlFilter;this.oApi._fnFeatureHtmlInfo=_fnFeatureHtmlInfo;
+this.oApi._fnFeatureHtmlPaginate=_fnFeatureHtmlPaginate;this.oApi._fnFeatureHtmlLength=_fnFeatureHtmlLength;
+this.oApi._fnFeatureHtmlProcessing=_fnFeatureHtmlProcessing;this.oApi._fnProcessingDisplay=_fnProcessingDisplay;
+this.oApi._fnFilterComplete=_fnFilterComplete;this.oApi._fnFilterColumn=_fnFilterColumn;
+this.oApi._fnFilter=_fnFilter;this.oApi._fnSortingClasses=_fnSortingClasses;this.oApi._fnVisibleToColumnIndex=_fnVisibleToColumnIndex;
+this.oApi._fnColumnIndexToVisible=_fnColumnIndexToVisible;this.oApi._fnBuildSearchArray=_fnBuildSearchArray;
+this.oApi._fnCalculateEnd=_fnCalculateEnd;this.oApi._fnConvertToWidth=_fnConvertToWidth;
+this.oApi._fnCalculateColumnWidths=_fnCalculateColumnWidths;this.oApi._fnArrayCmp=_fnArrayCmp;
+this.oApi._fnDetectType=_fnDetectType;this.oApi._fnGetDataMaster=_fnGetDataMaster;
+this.oApi._fnGetTrNodes=_fnGetTrNodes;this.oApi._fnEscapeRegex=_fnEscapeRegex;this.oApi._fnSaveState=_fnSaveState;
+this.oApi._fnLoadState=_fnLoadState;this.oApi._fnCreateCookie=_fnCreateCookie;this.oApi._fnReadCookie=_fnReadCookie
+}return this.each(function(){var oSettings=new classSettings();_aoSettings.push(oSettings);
+var bInitHandedOff=false;var bUsePassedData=false;var sId=this.getAttribute("id");
+if(sId!==null){oSettings.sTableId=sId;oSettings.sInstance=sId}else{oSettings.sInstance=$.fn.dataTableExt._oExternConfig.iNextUnique++
+}oSettings.nTable=this;if(typeof oInit!="undefined"&&oInit!==null){if(typeof oInit.bPaginate!="undefined"){oSettings.oFeatures.bPaginate=oInit.bPaginate
+}if(typeof oInit.bLengthChange!="undefined"){oSettings.oFeatures.bLengthChange=oInit.bLengthChange
+}if(typeof oInit.bFilter!="undefined"){oSettings.oFeatures.bFilter=oInit.bFilter}if(typeof oInit.bSort!="undefined"){oSettings.oFeatures.bSort=oInit.bSort
+}if(typeof oInit.bInfo!="undefined"){oSettings.oFeatures.bInfo=oInit.bInfo}if(typeof oInit.bProcessing!="undefined"){oSettings.oFeatures.bProcessing=oInit.bProcessing
+}if(typeof oInit.bAutoWidth!="undefined"){oSettings.oFeatures.bAutoWidth=oInit.bAutoWidth
+}if(typeof oInit.bSortClasses!="undefined"){oSettings.oFeatures.bSortClasses=oInit.bSortClasses
+}if(typeof oInit.aaData!="undefined"){bUsePassedData=true}if(typeof oInit.iDisplayLength!="undefined"){oSettings.iDisplayLength=oInit.iDisplayLength
+}if(typeof oInit.asStripClasses!="undefined"){oSettings.asStripClasses=oInit.asStripClasses
+}if(typeof oInit.fnRowCallback!="undefined"){oSettings.fnRowCallback=oInit.fnRowCallback
+}if(typeof oInit.fnHeaderCallback!="undefined"){oSettings.fnHeaderCallback=oInit.fnHeaderCallback
+}if(typeof oInit.fnFooterCallback!="undefined"){oSettings.fnFooterCallback=oInit.fnFooterCallback
+}if(typeof oInit.fnDrawCallback!="undefined"){oSettings.fnDrawCallback=oInit.fnDrawCallback
+}if(typeof oInit.fnInitComplete!="undefined"){oSettings.fnInitComplete=oInit.fnInitComplete
+}if(typeof oInit.aaSorting!="undefined"){oSettings.aaSorting=oInit.aaSorting}if(typeof oInit.sPaginationType!="undefined"){oSettings.sPaginationType=oInit.sPaginationType
+}if(typeof oInit.sDom!="undefined"){oSettings.sDomPositioning=oInit.sDom}if(typeof oInit.sAjaxSource!="undefined"){oSettings.sAjaxSource=oInit.sAjaxSource
+}if(typeof oInit.iCookieDuration!="undefined"){oSettings.iCookieDuration=oInit.iCookieDuration
+}if(typeof oInit.bStateSave!="undefined"){oSettings.oFeatures.bStateSave=oInit.bStateSave;
+_fnLoadState(oSettings)}if(typeof oInit!="undefined"&&typeof oInit.aoData!="undefined"){oInit.aoColumns=oInit.aoData
+}if(typeof oInit.oLanguage!="undefined"){if(typeof oInit.oLanguage.sUrl!="undefined"){oSettings.oLanguage.sUrl=oInit.oLanguage.sUrl;
+$.getJSON(oSettings.oLanguage.sUrl,null,function(json){_fnLanguageProcess(oSettings,json,true)
+});bInitHandedOff=true}else{_fnLanguageProcess(oSettings,oInit.oLanguage,false)}}}if(typeof oInit!="undefined"&&typeof oInit.aoColumns!="undefined"){for(var i=0;
+i<oInit.aoColumns.length;i++){_fnAddColumn(oSettings,oInit.aoColumns[i])}}else{$("thead th",this).each(function(){_fnAddColumn(oSettings,null)
+})}if(bUsePassedData){for(var j=0;j<oInit.aaData.length;j++){_fnAddData(oSettings,oInit.aaData[j])
+}if($("thead",this).length===0){this.appendChild(document.createElement("thead"))
+}if($("tbody",this).length===0){this.appendChild(document.createElement("tbody"))
+}}else{_fnGatherData(oSettings)}oSettings.aiDisplay=oSettings.aiDisplayMaster.slice();
+if(oSettings.oFeatures.bAutoWidth){_fnCalculateColumnWidths(oSettings)}oSettings.bInitialised=true;
+if(bInitHandedOff===false){_fnInitalise(oSettings)}})}})(jQuery);
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/cas-browser/static/js/querywidget.js b/0.8.1-rc1/balance/modules/cas-browser/static/js/querywidget.js
new file mode 100644
index 0000000..cdd2bcd
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/static/js/querywidget.js
@@ -0,0 +1,314 @@
+/*
+ * 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.
+ */
+
+var criteriaNum = 0;
+var allCriteria = new Array();
+var criteriaRoot = 0;
+var pCurrPage = 1;
+var pTotalPages = 0;
+var pPageSize = 0;
+var pNumPageProducts = 0;
+var pTotalProducts = 0;
+
+function encodeRequestData(key, value){
+	return escape(key) + "=" + value;
+}
+
+function displayPageInfo(){
+	pageInfo = '<div class="pp_pageLinks">';
+	if(pNumPageProducts > 0){
+		prodRangeStart = (pCurrPage - 1) * pPageSize + 1;
+		prodRangeEnd = (pCurrPage - 1) * pPageSize + pNumPageProducts;
+		pageInfo += 'Page ' + pCurrPage + ' of ' + pTotalPages + '&nbsp;';
+		pageInfo += '(Products ' + prodRangeStart + ' to ' + prodRangeEnd;
+		if(pTotalProducts > 0){
+			pageInfo += ', out of ' + pTotalProducts;
+		}
+		pageInfo += ')&nbsp;&nbsp;';
+		if(pCurrPage > 1){
+			pageInfo += '<a href="#" onclick="getPrevPage()">&lt;&lt;&nbsp;Previous Page</a>&nbsp;&nbsp;';
+		}
+		if(pCurrPage < pTotalPages){
+			pageInfo += '<a href="#" onclick="getNextPage()">Next Page&nbsp;&gt;&gt;</a>';
+		}
+	}else{
+		pageInfo += 'No products meet given criteria.';
+	}
+	pageInfo += '</div>';
+	$("#" + htmlID).prepend(pageInfo);
+}
+
+function formatCriteria(index){
+	if(allCriteria[index].type == 'term'){
+		requestData = encodeRequestData("Criteria[" + index + "][CriteriaType]", "Term");
+		requestData += '&' + encodeRequestData("Criteria[" + index + "][ElementName]", allCriteria[index].element);
+		requestData += '&' + encodeRequestData("Criteria[" + index + "][Value]", allCriteria[index].value);
+	}else if(allCriteria[index].type == 'range'){
+		requestData = encodeRequestData("Criteria[" + index + "][CriteriaType]", "Range");
+		requestData += '&' + encodeRequestData("Criteria[" + index + "][ElementName]", allCriteria[index].element);
+		requestData += '&' + encodeRequestData("Criteria[" + index + "][Min]", allCriteria[index].min);
+		requestData += '&' + encodeRequestData("Criteria[" + index + "][Max]", allCriteria[index].max);
+	}else if(allCriteria[index].type == 'boolean'){
+		requestData = encodeRequestData("Criteria[" + index + "][CriteriaType]", "Boolean");
+		requestData += '&' + encodeRequestData("Criteria[" + index + "][Operator]", allCriteria[index].operator);
+		for(i = 0; i < allCriteria[index].criteria.length; i++){
+			requestData += '&' + encodeRequestData("Criteria[" + index + "][CriteriaTerms][" + i + "]", allCriteria[index].criteria[i]);
+		}
+		for(i = 0; i < allCriteria[index].criteria.length; i++){
+			requestData +=  '&' + formatCriteria(allCriteria[index].criteria[i]);
+		}
+	}
+	return requestData;
+}
+
+function formatQueryRequest(expectedType){
+	showLoadingIcon();
+	requestData = encodeRequestData("Types[0]", ptName);
+	requestData += '&' + encodeRequestData("PagedResults", "1");
+	requestData += '&' + encodeRequestData("PageNum", pCurrPage);
+	requestData += '&' + encodeRequestData("RootIndex", criteriaRoot);
+	requestData += '&' + encodeRequestData("OutputFormat", expectedType);
+	requestData += '&' + formatCriteria(criteriaRoot);
+	displayPermalink();
+	$.post(siteUrl + "/queryScript.do",
+		requestData,
+		function(data){
+			hideLoadingIcon();
+			if(expectedType == "html"){
+				$("#" + htmlID).html(data);
+				currPage = parseInt($("#page_num").val());
+				totalPages = parseInt($("#total_pages").val());
+				pageSize = parseInt($("#page_size").val());
+				numPageProducts = $("#product_list > li").length;
+				totalTypeProducts = $("#total_type_products").val();
+			}else if(expectedType == "json"){
+				if(parseInt(data['Error']) == 1){
+					$("#" + htmlID).html('<div class="error">' + data['ErrorMsg'] + '</div>');
+					pCurrPage = 0;
+					pTotalPages = 0;
+					pPageSize = 0;
+					pNumPageProducts = 0;
+					pTotalProducts = 0;
+				}else{
+					renderJsonOutput(data);
+					pTotalPages = data['totalPages'];
+					pPageSize = data['pageSize'];
+					pNumPageProducts = data['results'].length;
+					pTotalProducts = data['totalProducts'];
+				}
+			}
+			displayPageInfo();
+		},
+		expectedType);
+}
+
+function formatCrossTypeQueryRequest(){
+	showLoadingIcon();
+	requestData = encodeRequestData("Types[0]", "*");
+	requestData += '&' + encodeRequestData("RootIndex", criteriaRoot);
+	requestData += '&' + formatCriteria(criteriaRoot);
+	requestData += '&' + encodeRequestData("PageNum", pCurrPage);
+	requestData += '&' + encodeRequestData("PageSize", pPageSize);
+	displayPermalink();
+	$.post(siteUrl + "/crossTypeQueryScript.do",
+		requestData,
+		function(data){
+		hideLoadingIcon();
+			if(parseInt(data['Error']) == 1){
+				$("#" + htmlID).html('<div class="error">' + data['ErrorMsg'] + '</div>');
+			}else{
+				renderJsonOutput(data);
+				pTotalPages = data['totalPages'];
+				pTotalProducts = data['totalProducts'];
+				pNumPageProducts = data['results'].length;
+				displayPageInfo();
+			}
+		},
+		"json");
+}
+
+function formatAllTypeRequest(){
+	showLoadingIcon();
+	requestData = encodeRequestData("PageNum", pCurrPage);
+	requestData += '&' + encodeRequestData("PageSize", pPageSize);
+	$.post(siteUrl + "/allTypeScript.do",
+		requestData,
+		function(data){
+			hideLoadingIcon();
+			if(parseInt(data['Error']) == 1){
+				$("#" + htmlID).html('<div class="error">' + data['ErrorMsg'] + '</div>');
+			}else{
+				renderJsonOutput(data);
+				pTotalPages = data['totalPages'];
+				pTotalProducts = data['totalProducts'];
+				pNumPageProducts = data['results'].length;
+				displayPageInfo();
+			}
+		},
+		"json");
+}
+
+function formatProductPageRequest(expectedType){
+	showLoadingIcon();
+	requestData = encodeRequestData("Type", ptName);
+	requestData += '&' + encodeRequestData("PageNum", pCurrPage);
+	requestData += '&' + encodeRequestData("OutputFormat", expectedType);
+	$.post(siteUrl + "/pageScript.do", 
+		requestData, 
+		function(data){
+			hideLoadingIcon();
+			if(expectedType == "html"){
+				$("#" + htmlID).html(data);
+				currPage = parseInt($("#page_num").val());
+				totalPages = parseInt($("#total_pages").val());
+				pageSize = parseInt($("#page_size").val());
+				numPageProducts = $("#product_list > li").length;
+				totalTypeProducts = 0;
+			}else if(expectedType == "json"){
+				if(parseInt(data['Error']) == 1){
+					$("#" + htmlID).html('<div class="error">' + data['ErrorMsg'] + '</div>');
+					pCurrPage = 0;
+					pTotalPages = 0;
+					pPageSize = 0;
+					pNumPageProducts = 0;
+					pTotalProducts = 0;
+				}else{
+					renderJsonOutput(data);
+					pTotalPages = data['totalPages'];
+					pPageSize = data['pageSize'];
+					pNumPageProducts = data['results'].length;
+					pTotalProducts = data['totalProducts'];
+				}
+			}
+			displayPageInfo();
+		},
+		expectedType);
+}
+
+// Determine whether to request a page or query, depending upon the presence
+// of any non-boolean criteria.  Returns 0 for a page and 1 for a query.
+function determineRequest(index){
+	if(allCriteria[index] == null){
+		return 0;
+	}
+	if(allCriteria[index].type != 'boolean'){
+		return 1;
+	}
+	for(i = 0; i < allCriteria[index].criteria.length; i++){
+		if(determineRequest(allCriteria[index].criteria[i])){
+			return 1;
+		}
+	}
+	return 0;
+}
+
+function sendRequest(expectedType){
+	if(determineRequest(criteriaRoot)){
+		formatQueryRequest(expectedType);
+	}else{
+		formatProductPageRequest(expectedType);
+	}
+}
+
+function sendCrossTypeRequest(){
+	if(determineRequest(criteriaRoot)){
+		formatCrossTypeQueryRequest();
+	}else{
+		if(parseInt(defaultShowEverything) == 1){
+			formatAllTypeRequest();
+		}else{
+			clearResults();
+		}
+	}
+}
+
+function addCriteria(){
+	index = criteriaNum;
+	criteriaNum++;
+	allCriteria[index] = new Object();
+	return index;
+}
+
+function addTermCriteria(elementName, value, parentIndex){
+	index = addCriteria();
+	allCriteria[index].type = 'term';
+	allCriteria[index].parentIndex = parentIndex;
+	allCriteria[index].element = elementName;
+	allCriteria[index].value = value;
+	if(parentIndex != null){
+		allCriteria[parentIndex].criteria.push(index);
+	}
+	return index;
+}
+
+function addRangeCriteria(elementName, min, max, parentIndex){
+	index = addCriteria();
+	allCriteria[index].type = 'range';
+	allCriteria[index].parentIndex = parentIndex;
+	allCriteria[index].element = elementName;
+	allCriteria[index].min = min;
+	allCriteria[index].max = max;
+	if(parentIndex != null){
+		allCriteria[parentIndex].criteria.push(index);
+	}
+	return index;
+}
+
+function addBooleanCriteria(operator, parentIndex){
+	index = addCriteria();
+	allCriteria[index].type = 'boolean';
+	allCriteria[index].parentIndex = parentIndex;
+	allCriteria[index].operator = operator;
+	allCriteria[index].criteria = new Array();
+	if(parentIndex != null){
+		allCriteria[parentIndex].criteria.push(allCriteria[index]);
+	}
+	return index;
+}
+
+function removeCriteria(index){
+	if(allCriteria[index].parentIndex != null){
+		parentCriteria = allCriteria[allCriteria[index].parentIndex];
+		for(i = 0; i < parentCriteria.criteria.length; i++){
+			if(parentCriteria.criteria[i] == index){
+				parentCriteria.criteria.splice(i, 1);
+				i = parentCriteria.criteria.length;
+			}
+		}
+	}
+	allCriteria[index] = null;
+}
+
+function showLoadingIcon(){
+	$("#" + htmlID).css("display", "none");
+	$("#" + loadingID).css("display", "block");
+}
+
+function hideLoadingIcon(){
+	$("#" + htmlID).css("display", "block");
+	$("#" + loadingID).css("display", "none");
+}
+
+function setExclusiveQuery(exclusive){
+	if(allCriteria[criteriaRoot]){
+		if(exclusive == true){
+			allCriteria[criteriaRoot].operator = 'and';
+		}else{
+			allCriteria[criteriaRoot].operator = 'or';
+		}
+	}
+}
diff --git a/0.8.1-rc1/balance/modules/cas-browser/views/dataset.php b/0.8.1-rc1/balance/modules/cas-browser/views/dataset.php
new file mode 100644
index 0000000..d92966f
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/views/dataset.php
@@ -0,0 +1,100 @@
+<?php
+/*
+ * 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.
+ */
+
+// Load the module context for this module
+$module  = App::Get()->loadModule();
+
+require_once($module->modulePath . "/classes/CasBrowser.class.php");
+require_once($module->modulePath . "/scripts/widgets/MetadataDisplayWidget.php");
+
+// Get a CAS-Browser XML/RPC client
+$browser  = new CasBrowser();
+$client   = $browser->getClient();
+
+// Get a  Product Type object
+$productType = $client->getProductTypeById(App::Get()->request->segments[0]);
+$ptID = $productType->getId();
+$ptName = $productType->getName();
+
+// Determine the visibility level based on the current user
+$ptVisibilityLevel = $browser->getProductTypeVisibilityLevel($ptID);
+
+// Redirect the user if they are not authorized
+if ($ptVisibilityLevel == CasBrowser::VIS_NONE) {
+	App::Get()->redirect(SITE_ROOT . '/errors/403');
+}
+
+// Load a MetadataDisplayWidget with the visible metadata for this product type
+$typeMetadataWidget = new MetadataDisplayWidget(array());
+$typeMetadataWidget->loadMetadata($browser->getVisibleMetadataForProductType($ptID));
+
+// Create a MetadataDisplayWidget to display system metadata (all except typeMetadata)
+$typeMetadata = $productType->toAssocArray();
+unset($typeMetadata['typeMetadata']);
+$systemMetadataWidget = new MetadataDisplayWidget(array());
+$systemMetadataWidget->loadMetadata($typeMetadata);
+
+
+// Prepare BreadcrumbWigdet
+$bcw = new BreadcrumbsWidget();
+$bcw->add('Home',SITE_ROOT . '/');
+$bcw->add("Browse By Type", $module->moduleRoot . '/');
+$bcw->add($ptName);
+?>
+
+
+<div class="container">
+	<hr class="space" />
+
+	<div id="cas_browser_container">
+		<h2><?php echo $sortedMetadata['DataSetName'][0]?> <?php echo $ptName?></h2>
+		<hr />
+
+		<div id="section_type_metadata">
+			<h3>Description:</h3>
+			<p><?php echo $productType->getDescription()?></p>
+			<hr class="space" />
+
+			<ul class="tabmenu">
+				<li class="selected"><a href="<?php echo $module->moduleRoot?>/dataset/<?php echo $ptID?>">Additional Information</a></li>
+				<li class=""><a href="<?php echo $module->moduleRoot?>/products/<?php echo $ptID?>">Downloadable Files</a></li>
+			</ul>
+
+			<div id="additional-information">
+				<p>The following additional metadata information has been defined for this
+				dataset.</p>
+
+				<?php if ($ptVisibilityLevel == CasBrowser::VIS_LIMIT):?>
+				<div class="notice">Additional information may exist that is not visible
+				due to your current access permissions.</div>
+				<?php endif;?>
+
+				<?php echo $typeMetadataWidget->render()?>
+			</div>
+				
+			<div id="data"></div>
+		</div>
+
+		<?php if (!App::Get()->settings['browser_suppress_system_metadata']):?>
+		<div id="section_system_metadata">
+			<h3>System Metadata:</h3>
+			<?php echo $systemMetadataWidget->render()?>
+		</div>
+		<?php endif;?>
+	</div>
+</div>
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/cas-browser/views/index.php b/0.8.1-rc1/balance/modules/cas-browser/views/index.php
new file mode 100644
index 0000000..24cdf31
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/views/index.php
@@ -0,0 +1,87 @@
+<?php
+/*
+ * 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.
+ */
+
+$module = App::Get()->loadModule();
+require_once( $module->modulePath . "/classes/CasBrowser.class.php");
+require_once( $module->modulePath . "/scripts/widgets/ProductTypeListWidget.php");
+
+// Get a CAS-Browser XML/RPC client
+$browser = new CasBrowser();
+$client  = $browser->getClient();
+$isAlive = $client->isAlive();
+if ( !$isAlive ) {
+	App::Get()->SetMessage("Filemgr at ". $client->serverURL. " is down. Please start it.<br>",CAS_MSG_ERROR);
+} else{
+	
+// Get a list of the product types managed by this server
+$response     = $client->getProductTypes();
+$productTypes = array();
+
+foreach ($response as $pt) {
+	$ptArray = $pt->toAssocArray();
+	
+	$ptVisibility = $browser->getProductTypeVisibilityLevel($pt->getId());
+	
+	if ($ptVisibility == CasBrowser::VIS_NONE) { continue; }
+
+	$merged = array(
+		"name" => array(
+			$ptArray[App::Get()->settings['browser_pt_name_key']],
+			$client->getNumProducts($pt)),
+		"description" => array($ptArray[App::Get()->settings['browser_pt_desc_key']]),
+		"id" => array($ptArray[App::Get()->settings['browser_pt_id_key']]));
+	$merged += $ptArray['typeMetadata'];
+	
+	$productTypes[$ptArray[App::Get()->settings['browser_pt_id_key']]] = $merged;
+}
+$productTypeListWidget = new ProductTypeListWidget(array("productTypes" => $productTypes));
+$productTypeListWidget->setUrlBase($module->moduleRoot);
+}
+
+// Prepare BreadcrumbWigdet
+$bcw = new BreadcrumbsWidget();
+$bcw->add('Home',SITE_ROOT . '/');
+$bcw->add("Browse By Type");
+?>
+
+<script type="text/javascript" src="<?php echo $module->moduleStatic?>/js/jquery.dataTables.min.js"></script>
+<script type="text/javascript">
+$(document).ready(function() {
+	// Turn the table into a sortable, searchable table
+	$("#productTypeSearch").dataTable();
+	// Give the search box the initial focus
+	$("#productTypeSearch_filter > input").focus();
+}); 
+</script>
+
+<div class="container">
+
+<?php if ( $isAlive ) :?>
+<hr class="space"/>
+<div id="cas_browser_container" class="span-22 last prepend-1 append-1">
+	<h2 id="cas_browser_title"><?php echo App::Get()->settings['browser_index_title_text']?></h2>
+	<ul class="tabmenu">
+		<li class="selected"><a href="<?php echo $module->moduleRoot?>/">Browse By Type</a></li>
+		<li class=""><a href="<?php echo $module->moduleRoot?>/typesearch/">Browse Across Types</a></li>
+	</ul>
+	<br class="fiftyPx"/>
+<?php $productTypeListWidget->render();?>
+</div>
+<hr class="space"/>
+</div>
+<?php endif; ?>
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/cas-browser/views/product.php b/0.8.1-rc1/balance/modules/cas-browser/views/product.php
new file mode 100644
index 0000000..34f6174
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/views/product.php
@@ -0,0 +1,84 @@
+<?php
+/*
+ * 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.
+ */
+
+$module = App::Get()->loadModule();
+require_once($module->modulePath . "/classes/CasBrowser.class.php");
+require_once($module->modulePath . "/scripts/widgets/MetadataDisplayWidget.php");
+require_once($module->modulePath . "/scripts/widgets/ProductDownloadWidget.php");
+
+// Get a CAS-Browser XML/RPC client
+$browser  = new CasBrowser();
+$client   = $browser->getClient();
+    
+// Get the specified product
+$productId = App::Get()->request->segments[0];
+$product = $client->getProductById($productId);
+$productName     = $product->getName();
+$productTypeName = $product->getType()->getName();
+$productTypeId   = $product->getType()->getId();
+$productMetadata = $client->getMetadata($product);
+
+// Get metadata for product and productType as associative arrays
+$productTypeInfo = $product->getType()->toAssocArray();
+$productInfo     = $productMetadata->toAssocArray();
+
+$productVisibilityLevel = $browser->getProductVisibilityLevel($productId);
+
+// Redirect the user if they are not authorized 
+if ($productVisibilityLevel == CasBrowser::VIS_NONE) {
+	App::Get()->redirect(SITE_ROOT . '/errors/403');
+}
+
+
+// Create and load a MetadataDisplay widget wit the visible metadata
+$metadataWidget = new MetadataDisplayWidget(array());
+$metadataWidget->loadMetadata($browser->getVisibleMetadataForProduct($productId));
+
+// Record the product page to send the user back to, if provided
+$returnPage = isset(App::Get()->request->segments[1]) ? App::Get()->request->segments[1] : 1;
+
+// Create a ProductDownloadWidget
+$productDownloadWidget = new ProductDownloadWidget(array(
+	"dataDeliveryUrl" => App::Get()->settings['browser_datadeliv_url']));
+$productDownloadWidget->setClient($client);
+$productDownloadWidget->load($product);
+
+// Add the cas-browser styles
+App::Get()->response->addStylesheet($module->moduleStatic . '/css/cas-browser.css');
+
+// Prepare BreadcrumbWigdet
+$bcw = new BreadcrumbsWidget();
+$bcw->add('Home',SITE_ROOT . '/');
+$bcw->add('Browse By Type', $module->moduleRoot . '/');
+$bcw->add($productTypeName, $module->moduleRoot."/dataset/{$productTypeId}");	
+$bcw->add('Products', $module->moduleRoot."/products/{$productTypeId}/page/{$returnPage}");
+$bcw->add(App::Get()->request->segments[0]);
+?>
+
+
+<hr class="space"/>
+<div class="span-22 last prepend-1 append-1">
+	<div id="cas_browser_product_metadata">
+		<h2 class="larger loud">Product Metadata: <?php echo wordwrap($productName, 62, "<br />",true);?></h2>
+		<?php $metadataWidget->render()?>
+	</div>
+	<div id="cas_browser_product_download">
+		<h2 class="larger loud">Download this Product:</h2>
+		<?php $productDownloadWidget->render()?>
+	</div>
+</div>
diff --git a/0.8.1-rc1/balance/modules/cas-browser/views/products.php b/0.8.1-rc1/balance/modules/cas-browser/views/products.php
new file mode 100644
index 0000000..0792c10
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/views/products.php
@@ -0,0 +1,156 @@
+<?php
+/*
+ * 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.
+ */
+
+$module = App::Get()->loadModule();
+require_once($module->modulePath . "/classes/CasBrowser.class.php");
+require_once($module->modulePath . "/scripts/widgets/FilterWidget.php");
+require_once($module->modulePath . "/scripts/widgets/ProductPageWidget.php");
+
+// Get a CAS-Browser XML/RPC client
+$browser  = new CasBrowser();
+$client   = $browser->getClient();
+ 
+// Get a  Product Type object
+$productType = $client->getProductTypeById(App::Get()->request->segments[0]);
+$ptID     = $productType->getId();
+$ptName   = $productType->getName();
+$typeInfo = $productType->toAssocArray();
+
+// Determine the visibility level based on the current user
+$ptVisibilityLevel = $browser->getProductTypeVisibilityLevel($ptID);
+
+// Redirect the user if they are not authorized
+if ($ptVisibilityLevel == CasBrowser::VIS_NONE) {
+	App::Get()->redirect(SITE_ROOT . '/errors/403');
+}
+
+// Store any filter parameters passed in via URL
+$filterParams = array();
+$segments = App::Get()->request->segments;
+for($index = 1; isset($segments[$index]) && $segments[$index] != ""; $index = $index + 2){
+	array_push($filterParams, array($segments[$index], $segments[$index + 1]));
+}
+if(count($filterParams) > 0){
+	$filterButtonValue = "Hide Filters";
+}else{
+	$filterButtonValue = "Show Filters";
+}
+
+// Initialize the FilterWidget
+$querySiteRoot = (isset(App::Get()->settings['query_service_url']))
+	? App::Get()->settings['query_service_url']
+	: 'http://' . $_SERVER['HTTP_HOST'] . $module->moduleRoot;
+$resultFormat = "json";
+$filterWidget = new FilterWidget(array(
+	'productType'  => $productType,
+	'htmlID'       => 'cas_browser_product_list',
+	'loadingID'    => 'loading_icon_container',	
+	'siteUrl'      => $querySiteRoot,
+	'pagedResults' => true,
+	'resultFormat' => $resultFormat));
+$filterWidget->renderScript();
+
+// Determine whether to show the download widget
+$showDownloadWidget = (isset(App::Get()->settings['browser_show_download_widget']) 
+	&& App::Get()->settings['browser_show_download_widget'] == 0)
+	? false
+	: true;
+	
+// Prepare BreadcrumbWigdet
+$bcw = new BreadcrumbsWidget();
+$bcw->add('Home',SITE_ROOT . '/');
+$bcw->add("Browse By Type", $module->moduleRoot . '/');
+$bcw->add($ptName, $module->moduleRoot."/dataset/{$ptID}");	
+$bcw->add("Products");
+?>
+
+<script type="text/javascript">
+$(document).ready(function() {
+
+	$('#showFilters').click(function() {
+		if ($(this).val() == "Show Filters") {
+			$('#filter_widget').fadeIn('slow');
+			$(this).val('Hide Filters');
+		} else {
+			$('#filter_widget').fadeOut('slow');
+			$(this).val('Show Filters');
+		}
+	});
+
+	<?php
+	if(count($filterParams) > 0){
+		foreach($filterParams as $filter){
+			echo "createFilter('" . $filter[0] . "','" . $filter[1] . "');\n";
+		}
+		echo 'displayPermalink();';
+		echo '$("#filter_widget").css("display", "block");';
+	}
+	?>
+
+	sendRequest(<?php echo '"' . $resultFormat . '"'; ?>);
+	
+});
+</script>
+<div class="container">
+<hr class="space"/>
+<div id="cas_browser_container" class="span-24 last">
+
+	<div id="section_products">
+		<h2 ><?php echo $ptName?></h2>
+		<hr/>
+		
+		<div id="section_type_metadata">
+			<h3>Description:</h3>
+			<p><?php echo $typeInfo['description']?></p>
+			<hr class="space"/>
+			
+			<ul class="tabmenu">
+				<li class="">        <a href="<?php echo $module->moduleRoot?>/dataset/<?php echo $ptID?>">Additional Information</a></li>
+				<li class="selected"><a href="<?php echo $module->moduleRoot?>/products/<?php echo $ptID?>">Downloadable Files</a></li>
+			</ul>
+		</div>
+		<?php if ( $ptVisibilityLevel == CasBrowser::VIS_LIMIT ):?>
+		<div class="notice">
+			Additional information may exist that is not visible due to your current access permissions.
+		</div>
+		<?php endif;?>
+		
+		<div id="section_filter_tools_container">
+			<div id="section_filter_tools_buttons">
+				<input type="button" id="showFilters" value=<?php echo '"' . $filterButtonValue . '"';?>/>
+			</div>
+			<div id="section_filter_tools">
+				<div id="filter_widget">
+					Filter: <?php $filterWidget->render(); ?>
+					<input type="hidden" id="page_num" value="1">
+				</div>
+			</div>
+		</div>
+		<?php if ( !App::Get()->settings['browser_private_products_visibility'] && $ptVisibilityLevel == CasBrowser::VIS_LIMIT ):?>
+		<h3>Public Downloadable Files for this Dataset</h3>
+		<?php else :?>
+		<h3>Downloadable Files for this Dataset</h3>
+		<?php endif;?>
+		<div id="loading_icon_container">
+		<img src="<?php echo App::Get()->request->moduleStatic . '/img/loading.gif'; ?>"/>
+		</div>
+		<div id="cas_browser_product_list"></div>
+		
+	</div>
+</div>
+</div>
diff --git a/0.8.1-rc1/balance/modules/cas-browser/views/search.php b/0.8.1-rc1/balance/modules/cas-browser/views/search.php
new file mode 100644
index 0000000..9db6b1e
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/views/search.php
@@ -0,0 +1,89 @@
+<?php
+/*
+ * 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.
+ */
+
+$module = App::Get()->loadModule();
+
+require_once($module->modulePath . "/classes/CasBrowser.class.php");
+
+// Get a CAS-Browser XML/RPC client
+$browser  = new CasBrowser();
+$client   = $browser->getClient();
+ 
+// Get a  Product Type object
+$productType  = $client->getProductTypeById(App::Get()->request->segments[0]);
+$productCount = $client->getNumProducts($productType);
+$ptID = $productType->getId();
+$ptName = $productType->getName();
+
+// Determine which search widget to show
+$widgetClassName = isset(App::Get()->settings['browser_product_search_widget'])
+	? App::Get()->settings['browser_product_search_widget']
+	: 'FilterWidget';
+
+$querySiteRoot = (isset(App::Get()->settings['query_service_url']))
+	? App::Get()->settings['query_service_url']
+	: 'http://' . $_SERVER['HTTP_HOST'] . MODULE_ROOT;
+
+// Create the search widget
+require_once($module->modulePath . "/scripts/widgets/{$widgetClassName}.php");
+$searchWidget = new $widgetClassName(array(
+	'productType'=>$productType,
+	'htmlID'=>'cas_browser_product_list',
+	'siteUrl'=>$querySiteRoot,
+	'pagedResults'=>true,
+	'resultFormat'=>'json'));
+
+// Render search widget javascript
+$searchWidget->renderScript();
+
+// Prepare BreadcrumbWigdet
+$bcw = new BreadcrumbsWidget();
+$bcw->add('Home',SITE_ROOT . '/');
+$bcw->add("Browser", $module->moduleRoot . '/');
+$bcw->add($ptName, $module->moduleRoot."/dataset/{$ptID}");	
+$bcw->add("Product Search");
+?>
+
+<div class="container">
+<hr class="space"/>
+<div id="cas_browser_container" class="span-24 last">
+	<ul class="tabs">
+	  <li><a id="tab_metadata" href="<?php echo MODULE_ROOT?>/dataset/<?php echo $ptID?>">Metadata</a></li>
+	  <li><a id="tab_browse"   href="<?php echo MODULE_ROOT?>/products/<?php echo $ptID?>">Browse</a></li>
+	  <li><a id="tab_search"   href="<?php echo MODULE_ROOT?>/search/<?php echo $ptID?>" class="selected">Search</a></li>
+	</ul>
+	<div id="section_products">
+		<h2 class="larger loud">Product Search: <?php echo $ptName?></h2>
+		<br/>
+		<div id="cas_browser_search_widget" class="span-24 last">
+	  		<?php $searchWidget->render(); ?>
+			<input type="hidden" id="page_num" value="1">
+		</div>
+		<div id="cas_browser_product_list" class="span-16 colborder">
+	  		<h3>Product Search Results</h3>
+		</div>
+		<div id="cas_browser_dataset_download" class="span-6 last">
+			<a href="<?php echo App::Get()->settings['browser_datadeliv_url']?>/dataset?typeID=<?php echo App::Get()->request->segments[0]?>&format=application/x-zip">
+				<img src="<?php echo MODULE_STATIC?>/img/zip-icon-smaller.gif" id="zip_icon" alt="zip-icon"/>
+			</a>
+			Click on the icon to download all <?php echo $productCount ?> data products associated with
+			this search as a single Zip archive.<br/>
+		</div>
+	</div>
+</div>
+</div>
diff --git a/0.8.1-rc1/balance/modules/cas-browser/views/typesearch.php b/0.8.1-rc1/balance/modules/cas-browser/views/typesearch.php
new file mode 100644
index 0000000..35fe3ab
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/cas-browser/views/typesearch.php
@@ -0,0 +1,121 @@
+<?php
+/*
+ * 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.
+ */
+
+$module = App::Get()->loadModule();
+require_once($module->modulePath . "/classes/CasBrowser.class.php");
+require_once($module->modulePath . "/scripts/widgets/CrossTypeSearchWidget.php");
+
+// Get a CAS-Browser XML/RPC client
+$browser  = new CasBrowser();
+$client   = $browser->getClient();
+
+// Initialize the CrossTypeSearchWidget
+$querySiteRoot = (isset(App::Get()->settings['query_service_url']))
+	? App::Get()->settings['query_service_url']
+	: 'http://' . $_SERVER['HTTP_HOST'] . $module->moduleRoot;
+$crossTypeWidget = new CrossTypeSearchWidget(array(
+	'htmlID'       => 'cas_browser_product_list',
+	'loadingID'    => 'loading_icon_container',
+	'siteUrl'      => $querySiteRoot));
+$crossTypeWidget->renderScript();
+	
+// Store any filter and exclusive/inclusive parameters passed in via URL
+$urlParams = CrossTypeSearchWidget::parseSegments();
+$queryBoolValue = 'and';
+$exclusiveChecked = true;
+if(isset($urlParams['filterParams'])){
+	$filterButtonValue = "Hide Filters";
+}else{
+	$filterButtonValue = "Show Filters";
+}
+if(isset($urlParams['exclusive'])){
+	$queryBoolValue = $urlParams['exclusive']['bool'];
+	$exclusiveChecked = $urlParams['exclusive']['checked'];
+}
+
+// Prepare BreadcrumbWigdet
+$bcw = new BreadcrumbsWidget();
+$bcw->add('Home',SITE_ROOT . '/');
+$bcw->add("Browse Across Types");	
+?>
+
+<script type="text/javascript" src="<?php echo $module->moduleStatic?>/js/jquery.dataTables.min.js"></script>
+<script type="text/javascript">
+$(document).ready(function() {
+
+	$('#showFilters').click(function() {
+		if ($(this).val() == "Show Filters") {
+			$('#filter_widget').fadeIn('slow');
+			$(this).val('Hide Filters');
+		} else {
+			$('#filter_widget').fadeOut('slow');
+			$(this).val('Show Filters');
+		}
+	});
+
+	pPageSize = 20;
+
+	addBooleanCriteria(<?php echo "'" . $queryBoolValue . "'"; ?>, null);
+
+	<?php
+	if(isset($urlParams['filterParams'])){
+		foreach($urlParams['filterParams'] as $filter){
+			echo "createFilter('" . $filter[0] . "','" . $filter[1] . "');\n";
+		}
+		if($exclusiveChecked == false){
+			echo '$("#exclusive").attr("checked", false);';
+		}
+		echo 'displayPermalink();';
+		echo '$("#filter_widget").css("display", "block");';
+	}
+	?>
+
+	sendCrossTypeRequest();
+	
+});
+</script>
+<div class="container">
+<hr class="space"/>
+<div id="cas_browser_container" class="span-24 last">
+	<div id="section_products">
+		<h2 ><?php echo "Cross Product Type Search"?></h2>
+		<ul class="tabmenu">
+			<li class=""><a href="<?php echo $module->moduleRoot?>/">Browse By Type</a></li>
+			<li class="selected"><a href="<?php echo $module->moduleRoot?>/typesearch/">Browse Across Types</a></li>
+		</ul>
+		<hr class="space"/>
+		
+		<div id="section_filter_tools_container">
+			<div id="section_filter_tools_buttons">
+				<input type="button" id="showFilters" value=<?php echo '"' . $filterButtonValue . '"';?> />
+			</div>
+			<div id="section_filter_tools">
+				<div id="filter_widget">
+					Filter: <?php $crossTypeWidget->render(); ?>
+				</div>
+			</div>
+		</div>
+		
+		<br/>
+		<div id="loading_icon_container">
+		<img src="<?php echo App::Get()->request->moduleStatic . '/img/loading.gif'; ?>"/>
+		</div>
+		<div id="cas_browser_product_list"></div>
+	</div>
+</div>
+</div>
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/profile/README.txt b/0.8.1-rc1/balance/modules/profile/README.txt
new file mode 100644
index 0000000..f07be3d
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/README.txt
@@ -0,0 +1,88 @@
+Profile Manager - Lightweight profile manager for Balance applications
+======================================================================
+
+Overview
+--------
+
+The Profile Manager provides an interface to simplify the process of accessing and 
+managing the information within the underlying directory services. The module provides 
+views that make it easy to login, browse, and manage profile information for a specified 
+user. It also provides a simplified way to create new profiles. However, an administrative 
+user must grant the new user privileges from within the underlying directory service. The 
+primary use case for this module involves authentication and authorization using LDAP, 
+although it should be possible to support additional back-ends with moderate customization.
+
+
+How it Works
+------------
+
+The Profile Manager has been designed so that it is easy to plug in custom back end 
+directory services (LDAP, MySql, etc). The profile manager comes with a ready-to-use 
+LDAP provider but customizing it is very simple. Once all the attributes in the 
+config.ini file are set, the profile manager will display all attributes defined. 
+These attributes will be displayed on the view.php page and can be modified through 
+the manage.php page. The profile manager also provides the ability to change user 
+passwords. Moreover, user groups can be viewed on the groups.php page if authorization 
+configurations are setup.
+
+
+Installation
+------------
+
+Copy the Profile module (this directory) to the /modules directory of
+your Balance application. 
+
+
+Dependencies
+------------
+
+ CAS-Single Sign On ( For LDAP users )
+: If LDAP is used for authentication and/or authorization, the [CAS-SSO](https://svn.apache.org/repos/asf/oodt/tags/0.3/sso/src/main/php/pear/) 
+  library must be available on the host environment to allow the module to communicate 
+   with LDAP through this library.  
+
+
+Configuration
+-------------
+
+All configuration for the Profile Manager takes place in the module's 'config.ini' file. 
+See the inline documentation in 'config.ini' for detailed information about each
+configuration option. 
+
+
+Developer Guide
+---------------
+
+### Including the Profile Manager in your application
+
+In general, the Profile Manager needs to be available on each application view. To avoid 
+having to load the module at the top of each view, it is possible to include the module once,
+in the Balance index.php at the root of your application. Simply add the following 
+lines to the 'index.php' file where it says 'Initialize any globally required modules here':
+
+// Profile Manager initialization
+$module = App::Get()->loadModule('NAME_OF_PROFILE_DIRECTORY');
+
+
+### Including the Profile Manager in your application views ### 
+
+Before displaying the manager first you must initialize the UserStatusWidget by adding the 
+following:
+
+		// Load profile module for path access 
+		$module 		= App::Get()->loadModule('profile');
+		// Prepare User login details
+		$authentication = App::Get()->getAuthProvider();
+		$username 		= $authentication->getCurrentUsername();
+		require_once( $module->modulePath . '/scripts/widgets/UserStatusWidget.php' );
+		$userStatus = new UserStatusWidget(
+			array( $authentication->isLoggedIn(),
+				   $username,
+				   // Set profile management on. 'false' will disable the link to profile management.
+				   true), true );
+		   
+To display the user status in your application views simply add the following:
+
+		<?php $userStatus->render();?>
+
+
diff --git a/0.8.1-rc1/balance/modules/profile/classes/LDAPAuthenticationProvider.class.php b/0.8.1-rc1/balance/modules/profile/classes/LDAPAuthenticationProvider.class.php
new file mode 100644
index 0000000..ca69159
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/classes/LDAPAuthenticationProvider.class.php
@@ -0,0 +1,263 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * LDAPAuthenticationProvider
+ * 
+ * This class provides an extension of the OODT Security 'Single-sign on'
+ * functionality that complies with the contract specified in the OODT Balance
+ * ApplicationAuthenticationProvider interface.
+ * 
+ * For more information on the functions available here, consult either the
+ * OODT Security package or the Balance ApplicationAuthenticationProvider 
+ * interface documentation.
+ * 
+ * Note: This class has a dependency on the OODT CAS-SSO package 
+ *      (http://oodt.jpl.nasa.gov/repo/framework/cas-sso/trunk/src/php/pear)
+ *      
+ *      To build this dependency, check out the above project and then:
+ *      1) cd into the checked out project (you should see a package.xml file)
+ *      2) pear package
+ *      3) (sudo) pear install --force Gov_Nasa_Jpl...tar.gz
+ * 
+ * @author s.khudikyan
+ * @author ahart
+ * 
+ */
+
+require("Org/Apache/Oodt/Security/SingleSignOn.php");
+
+class LDAPAuthenticationProvider
+	extends Org_Apache_Oodt_Security_SingleSignOn 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationAuthenticationProvider {
+	
+	// The LDAP server name
+	protected $ldapHost;
+	
+	// The port on which the LDAP server listens
+	protected $ldapPort;
+
+
+	/**
+	 * Constructor
+	 */
+	public function __construct() {
+		
+		// set LDAP constants
+		define("CAS_SECURITY",true);
+		define("SSO_LDAP_HOST", App::Get()->settings['ldap_host']);
+		define("SSO_LDAP_PORT", App::Get()->settings['ldap_port']);
+		define("SSO_BASE_DN", App::Get()->settings['ldap_base_dn']);
+		define("SSO_GROUPS_DN", App::Get()->settings['ldap_group_dn']);
+		define("SSO_COOKIE_KEY", App::Get()->settings['cookie_key']);
+		
+		$this->ldapHost = SSO_LDAP_HOST;
+		$this->ldapPort = SSO_LDAP_PORT;
+	}
+	
+	/**
+	 * Connect to the LDAP server
+	 */
+	public function connect() {
+		return parent::connect($this->ldapHost,$this->ldapPort);
+	}
+	
+	/**
+	 * Disconnect from the LDAP server
+	 */
+	public function disconnect() {
+		ldap_close($this->conn);
+	}
+	
+	/**
+	 * Determine whether or not a user has authenticated
+	 * 
+	 * @return boolean Whether or not the current user has authenticated
+	 */
+	public function isLoggedIn() {
+		return parent::isLoggedIn();
+	}
+	
+	/**
+	 * Process a user login
+	 * 
+	 * @param string $username The provided username
+	 * @param string $password The provided password
+	 */
+	public function login( $username, $password ) {
+		return parent::login( $username, $password );
+	}
+	
+	/**
+	 * End an authenticated user's session
+	 */
+	public function logout() {
+		parent::logout();
+	}
+
+	/**
+	 * Return the unique username of the currently authenticated user
+	 */
+	public function getCurrentUsername() {
+		return parent::getCurrentUsername();
+	}
+	
+	/**
+	 * Process a password change request for the currently authenticated
+	 * user
+	 * 
+	 * @param string $newPassword The new password to associate with the user
+	 */
+	public function changePassword( $newPassword ) {
+		if ( App::Get()->settings['auth_encryption_method'] ) {
+			return parent::changePassword( $newPassword, App::Get()->settings['auth_encryption_method'] );
+		}
+		return parent::changePassword( $newPassword );
+	}
+	
+	/**
+	 * Attempt to validate a candidate value for new user password
+	 * 
+	 * @param string $newPass The candidate password value
+	 * @param string $encryptionMethod The encryption method to use
+	 */
+	public function validateChangePassword( $newPass, $encryptionMethod = "SHA" ) {
+		$isValid = true;
+		$messages = array();
+		// validate rules from config file
+		$rules = App::Get()->settings['security_password_rules'];
+
+		if ( isset($rules) ) {
+			foreach( $rules as $rule ){
+				
+				// Separate the rule from the error message
+				list($regularExpression,$errorMessage) = explode('|',$rule,2);
+				
+				// Test the rule
+				$rulePassed = preg_match($regularExpression, $newPass);
+				
+				// If the rule failed, append the error message
+				if (!$rulePassed) {
+					$messages[] = $errorMessage;
+					$isValid    = false;
+				}
+			}
+		}
+
+		if ($isValid && $this->connect(SSO_LDAP_HOST,SSO_LDAP_PORT)) {
+		  $result = $this->changePassword($newPass,$encryptionMethod);
+		  return true;
+		} else
+		  return $messages;
+	}
+	
+	/**
+	 * Obtain detailed information about the specified user. 
+	 * 
+	 * This function accepts both a username and an array of attributes 
+	 * corresponding to the variables in the LDAP user record for which 
+	 * values should be returned. 
+	 * 
+	 * @param string $username   The username to obtain information for
+	 * @param array  $attributes The set of variables to return values for
+	 */
+	public function retrieveUserAttributes( $username, $attributes ) {
+		$rawArray 		= parent::retrieveUserAttributes( $username, $attributes );
+		$userAttributes = array();
+		
+		if ( count($rawArray) > 1 ) {
+			$rawArray = $rawArray[0];
+			// Get only necessary attributes to return
+			foreach ( $rawArray as $key=>$keyValue ) {
+				foreach ( $attributes as $value ) {
+					if ( $key === $value ) {
+						$userAttributes[$key] = $keyValue[0];
+					}
+				}
+			}
+		}
+		return $userAttributes;
+	}
+	
+	/**
+	 * Add a user record to the LDAP directory
+	 * 
+	 * This function accepts an associative array of information about 
+	 * a user. The keys in this array correspond to the named variables
+	 * in the user object in the LDAP directory. At a minimum, this 
+	 * array must contain a key 'uid' which must be unique across users
+	 * so that a proper dn can be generated for the new user.
+	 * 
+	 * @param array $userInfo The information to include in the record
+	 */
+	public function addUser($userInfo) {
+		$ldapconn = $this->connect(SSO_LDAP_HOST,SSO_LDAP_PORT);
+		if ($ldapconn) {
+			$user  = "uid={$userInfo[ "uid" ]}," . SSO_BASE_DN;
+			return ldap_add($ldapconn,$user,$userInfo);
+		}
+		// connection failed
+		return false;
+	}
+	
+	/**
+	 * Determine if the specified username is available
+	 * 
+	 * This function uses the value of the config setting 'username_attr' when
+	 * determining which key in the LDAP user record to use as the username
+	 * attribute. 
+	 * 
+	 * @param string $username The username to test for availability
+	 */
+	public function usernameAvailability( $username ) {
+		$justthese = array( App::Get()->settings['username_attr'] );
+		$profile = $this->retrieveUserAttributes($username, $justthese);
+		if (count($profile) > 0) {
+			return false;
+		} else {
+			// available
+			return true;
+		}
+	}
+	
+	/**
+	 * Update an existing user profile with new information
+	 * 
+	 * This function accepts an associative array containing named key/value
+	 * pairs. The keys in this array correspond to the named variables
+	 * in the user object in the LDAP directory. The function can only update
+	 * the record for the currently authenticated user.
+	 * 
+	 * @param array $newInfo The updated information for the user's profile
+	 */
+	public function updateProfile($newInfo) {
+
+		if ($this->isLoggedIn()) {
+			$user  = "uid={$this->getCurrentUsername()}," . SSO_BASE_DN ;
+			$ldapconn = $this->connect(SSO_LDAP_HOST,SSO_LDAP_PORT);
+			
+			if (ldap_mod_replace($ldapconn,$user,$newInfo)) {
+				return true;
+			} else {
+				return false;
+			}
+		} else {
+			return false;
+		}
+	}
+}
diff --git a/0.8.1-rc1/balance/modules/profile/classes/LDAPAuthorizationProvider.class.php b/0.8.1-rc1/balance/modules/profile/classes/LDAPAuthorizationProvider.class.php
new file mode 100644
index 0000000..1ac95fb
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/classes/LDAPAuthorizationProvider.class.php
@@ -0,0 +1,113 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * LDAPAuthorizationProvider
+ * 
+ * This class provides an implementation of the OODT Balance Application 
+ * Authorization Provider interface that makes use of the Lightweight
+ * Directory Access Protocol (LDAP).
+ * 
+ * For more information on the functions available here, consult the
+ * OODT Balance ApplicationAuthenticationProvider interface documentation.
+ *
+ * @author s.khudikyan
+ * @author ahart
+ * 
+ */
+
+class LDAPAuthorizationProvider 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationAuthorizationProvider {
+
+	
+	// The LDAP server name
+	protected $ldapHost;
+	
+	// The port on which the LDAP server listens
+	protected $ldapPort;
+	
+	/**
+	 * Constructor
+	 */
+	public function __construct() {
+		
+		// Set LDAP constants
+		define("AUTH_BASE_DN",   App::Get()->settings['authorization_ldap_base_dn']);
+		define("AUTH_GROUPS_DN", App::Get()->settings['authorization_ldap_group_dn']);
+		define("AUTH_LDAP_HOST", App::Get()->settings['authorization_ldap_host']);
+		define("AUTH_LDAP_PORT", App::Get()->settings['authorization_ldap_port']);
+		
+		$this->ldapHost = AUTH_LDAP_HOST;
+		$this->ldapPort = AUTH_LDAP_PORT;
+	}
+	
+	/**
+	 * Obtain the groups/roles for the current username
+	 * 
+	 * This function searches {$searchDirectory} for groupOfUniqueName objects whose
+	 * uniqueMember attribute contains {$username}. The cn attribute of all matching
+	 * groups is returned as a numeric array.
+	 * 
+	 * @param string $username The username to test for. Note that just the username 
+	 *                         portion should be specified, as both 'uid=' and AUTH_BASE_DN
+	 *                         are added to the value before searching.
+	 * @param string $searchDirectory The fully qualified DN (e.g.: ou=system,ou=groups)
+	 *                         of the LDAP directory in which to search for groups
+	 */
+	public function retrieveGroupsForUser($username,$searchDirectory = AUTH_GROUPS_DN) {
+		
+		// attempt to connect to ldap server 
+		$ldapconn = $this->connect(AUTH_LDAP_HOST,AUTH_LDAP_PORT);
+		$groups   = array();
+		if ($ldapconn) {
+			$filter = "(&(objectClass=groupOfUniqueNames)"
+				."(uniqueMember=uid={$username}," . AUTH_BASE_DN . "))";
+			$result = ldap_search($ldapconn,$searchDirectory,$filter,array('cn'));
+			
+			if ($result) {
+				$entries = ldap_get_entries($ldapconn,$result);
+				foreach ($entries as $rawGroup) {
+					if (isset($rawGroup['cn'][0]) 
+					&& $rawGroup['cn'][0] != '') {
+						$groups[] = $rawGroup['cn'][0];
+					}
+				}
+			}
+		} 
+		return $groups;
+	}
+			
+	/**
+	 * Connect to the LDAP server
+	 */
+	public function connect() {
+		if ($conn = ldap_connect($this->ldapHost,$this->ldapPort)) {
+			
+			// Connection established
+			$this->connectionStatus = 1;
+			ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3);
+			ldap_set_option($conn, LDAP_OPT_DEBUG_LEVEL, 7);
+			ldap_set_option($conn, LDAP_OPT_REFERRALS, 0);	
+			$this->conn = $conn;
+			return $conn;
+		} else {
+			// Connection failed
+			return false;
+		}
+	}		
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/profile/classes/NullAuthenticationProvider.class.php b/0.8.1-rc1/balance/modules/profile/classes/NullAuthenticationProvider.class.php
new file mode 100644
index 0000000..6449d10
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/classes/NullAuthenticationProvider.class.php
@@ -0,0 +1,96 @@
+<?php
+/*
+ * 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.
+ */ 
+
+/**
+ * NullAuthenticationProvider
+ * 
+ * An implementation of the iApplicationAuthenticationProvider interface with
+ * no external dependencies (and also limited functionality) intended to be used
+ * as a development tool for quickly testing and debugging applications without
+ * having to set up detailed auth&auth dependencies. 
+ * 
+ * This class utilizes the PHP Session construct for storing a provided username.
+ * Any username / password combination is treated as valid.
+ * 
+ */
+class Org_Apache_Oodt_Balance_Providers_Authentication_NullAuthenticationProvider
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationAuthenticationProvider {
+
+	public function __construct() {}
+	
+	public function connect() {
+		return true;
+	}
+	
+	public function disconnect() {
+		return true;
+	}
+	
+	public function isLoggedIn() {
+		return isset($_SESSION['_auth']);
+	}
+	
+	public function login( $username, $password ) {
+        $_SESSION['_auth'] = array(
+            'username' => $username
+        );
+	}
+	
+	public function logout() { 
+        unset($_SESSION['_auth']);
+	}
+
+	public function getCurrentUsername() {
+		return ($this->isLoggedIn())
+            ? $_SESSION['_auth']['username']
+            : false;
+	}
+	
+	public function changePassword( $newPassword ) {
+	       return true;
+	}
+	
+	public function validateChangePassword( $newPass, $encryptionMethod = "SHA" ) {
+	       return true;
+	}
+	
+	public function retrieveUserAttributes( $username, $attributes ) {
+		return ($this->isLoggedIn())
+            ? array(
+		       "cn"        => $this->getCurrentUsername(),
+		       "givenname" => $this->getCurrentUsername(),
+		       "sn"        => '',
+		       "uid"       => $this->getCurrentUsername(),
+		       "mail"      => 'guest@example.org'
+		    )
+            : false;
+	}
+	
+	public function addUser($userInfo) {
+	       return false;
+	}
+	
+	public function usernameAvailability( $username ) {
+	       return false;
+	}
+	
+	public function updateProfile($newInfo) {
+	       return false;
+
+	}	
+}
diff --git a/0.8.1-rc1/balance/modules/profile/classes/NullAuthorizationProvider.class.php b/0.8.1-rc1/balance/modules/profile/classes/NullAuthorizationProvider.class.php
new file mode 100644
index 0000000..3f4a220
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/classes/NullAuthorizationProvider.class.php
@@ -0,0 +1,45 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * NullAuthorizationProvider
+ * 
+ * An implementation of the iApplicationAuthorizationProvider interface with
+ * no external dependencies (and also limited functionality) intended to be used
+ * as a development tool for quickly testing and debugging applications without
+ * having to set up detailed auth&auth dependencies. 
+ * 
+ * This class simply returns an empty array for all usernames, indicating that 
+ * the user is not part of any groups/roles.
+ * 
+ */
+class Org_Apache_Oodt_Balance_Providers_Authorization_NullAuthorizationProvider
+implements Org_Apache_Oodt_Balance_Interfaces_IApplicationAuthorizationProvider {
+
+	public function __construct() {
+
+	}
+
+	public function retrieveGroupsForUser($username) {
+		return array();
+	}
+		
+	public function connect() {
+		return true;
+	}
+}
diff --git a/0.8.1-rc1/balance/modules/profile/config.ini b/0.8.1-rc1/balance/modules/profile/config.ini
new file mode 100644
index 0000000..5e5e24d
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/config.ini
@@ -0,0 +1,180 @@
+ ; 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.
+ 
+
+; Profile module configuration file
+; ---------------------------------------------------------------------------
+;
+; The Profile module simplifies the process of managing users of your web 
+; application. The primary use case for this module involves authentication
+; and authorization using LDAP, although it should be possible to support 
+; additional back-ends with moderate customization.
+;
+
+
+; ***************************************************************************
+; PROFILE AUTHENTICATION SETTINGS
+; ***************************************************************************
+;
+; Responsibility for authentication is delegated to the class specified here.
+; The only requirement of the delegated class is that it implement the 
+; Org_Apache_Oodt_Balance_Interfaces_IApplicationAuthenticationProvider 
+; interface.
+;
+; The following settings define both the class name (authentication_class) and
+; the filesystem path to the class itself (authentication_class_path). Both 
+; are required for authentication to function. 
+;
+; Tip: When specifying the authentication_class_path, the token [MODULE_PATH] 
+; will be expanded to the root directory of this module (i.e.: the location of 
+; this file)
+;
+; If authentication is not required, both of these settings should be left 
+; blank.
+;
+authentication_class      = LDAPAuthenticationProvider
+authentication_class_path = [MODULE_PATH]/classes/LDAPAuthenticationProvider.class.php
+
+
+; LDAP authentication server connection details
+ldap_host            = "host"
+ldap_port            = 686
+ldap_base_dn         = "dc=people,dc=project"
+cookie_key           = "__ac__sc__"
+
+
+; Encryption method used to encrypt user passwords 
+; Supported options are:
+; 		1. SHA
+; 		2. MD5
+auth_encryption_method 	= SHA
+
+
+; ***************************************************************************
+; PROFILE AUTHORIZATION SETTINGS
+; ***************************************************************************
+;
+; Responsibility for authorization is delegated to the class specified here. 
+; The only requirement of the delegated class is that it implement the
+; Org_Apache_Oodt_Balance_Interfaces_IApplicationAuthorizationProvider
+; interface. 
+;
+; The following settings define both the class name (authorization_class) and
+; the filesystem path to the class itself (authorization_class_path). Both 
+; are required for authentication to function. 
+;
+; Tip: When specifying the authorization_class_path, the token [MODULE_PATH] 
+; will be expanded to the root directory of this module (i.e.: the location
+; of this file)
+;
+; If authorization is not required, both of these settings should be left 
+; blank.
+;
+authorization_class		 = LDAPAuthorizationProvider
+authorization_class_path = [MODULE_PATH]/classes/LDAPAuthorizationProvider.class.php
+
+
+; LDAP authorization filter details
+authorization_ldap_filter = '&(objectClass=groupOfUniqueNames)'
+authorization_ldap_filter_userid = 'uniqueMember=uid'
+
+; LDAP authorization server connection details
+authorization_ldap_host            = 'host'
+authorization_ldap_port            = 686
+authorization_ldap_base_dn         = 'dc=people,dc=project'
+authorization_ldap_group_dn        = 'dc=group,dc=project'
+authorization_cookie_key           = '__ac__sc__'
+
+; Page to redirect users to when authorization is required
+authorization_redirect_url = [MODULE_ROOT]/login
+
+
+
+; ***************************************************************************
+; PROFILE ATTRIBUTE SETTINGS
+; ***************************************************************************
+; User profiles consist of various attributes (name, telephone, email, etc.).
+; This section defines the attributes that the profile will expose.
+
+; Attribute Mapping
+; The profile module natively understands the following profile attributes, 
+; which are widely applicable across projects. This section defines a mapping
+; between these profile attributes and your specific environment. 
+;
+; commonname_attr: The common name of the user (usually first and last name)
+commonname_attr = cn
+; firstname_attr: The first (given) name of the user
+firstname_attr  = givenname
+; lastname_attr: The last (surname) name of the user
+lastname_attr   = sn
+; username_attr: The unique id/name of the user
+username_attr   = uid
+; email_attr: The email address of the user
+email_attr      = mail
+
+; Visible Attributes
+; The profile module will expose the profile attributes specified here. 
+; These attributes will be displayed for the user to view.
+; 
+; Specify the profile attributes to expose here:
+profile_attributes[] = givenname
+profile_attributes[] = sn
+profile_attributes[] = uid
+profile_attributes[] = mail
+
+; Attributes allowed to modify
+; The profile module will expose the profile attributes specified here. 
+; These attributes will be displayed for the user to view and the user 
+; will be allowed to change values in the ldap directory.
+; 
+; Specify the profile attributes to modify here:
+profile_modify_attributes[] = givenname
+profile_modify_attributes[] = sn
+profile_modify_attributes[] = mail
+
+; When displaying the attributes specified above, a human readable label can
+; be defined. This will help users better understand which values they are
+; seeing and/or modifying. 
+;
+; Specify an attribute-to-label mapping for each of the above attributes here:
+attr_titles[ 'First name' ] = givenname
+attr_titles[ 'Last name' ]  = sn
+attr_titles[ 'Username' ]   = uid
+attr_titles[ 'Email' ]      = mail
+
+
+; ***************************************************************************
+; PASSWORD VALIDATION SETTINGS
+; ***************************************************************************
+; In the event that there are requirements that define a valid password, they
+; can be specified here as an array of 'tests'. These tests will be invoked
+; whenever the user attempts to set / change his or her password.
+;
+; The general format of these rules is a regular expression followed by a
+; pipe (|) followed by the human-readable exception to display when a password
+; fails to validate.
+; 
+; EXAMPLES:
+; - To require passwords with length of 5 or greater:
+;   security_password_rules[] = "/.{5,}/|Password must have a length of 5 or greater"
+; - To enfoce the presence of at least one uppercase letter
+;   security_password_rules[] = "/[A-Z]+/|Password must contain at least one uppercase letter"
+;
+; The security rules will be enforced in series, and processing will halt
+; after the first failure.
+;
+security_password_rules[] =
+
+
diff --git a/0.8.1-rc1/balance/modules/profile/hooks.php b/0.8.1-rc1/balance/modules/profile/hooks.php
new file mode 100644
index 0000000..ac66c81
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/hooks.php
@@ -0,0 +1,91 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * HOOKS.PHP
+ * 
+ * Hooks provide the ability, as the name implies, to hook into various parts of 
+ * the view rendering process and insert customizations. The contents of these 
+ * functions are run at the appropriate time *EVERY* time a view is rendered, i.e.
+ * the content of the hooks is not by default view-specific but rather will be 
+ * applied to all views. (However, there is nothing that prevents developers from 
+ * inserting conditional logic inside a hook that then causes view-specific
+ * them to exhibit view-specific behavior).
+ * 
+ * As an example, consider a hook that adds the amount of time Balance took to render
+ * the page as an inline HTML comment at the bottom of each page after it has been sent:
+ * 
+ * function hook_after_send() {
+ *     $timeStart = $GLOBALS['balance_request_start'];
+ *     $timeNow   = microtime(true);
+ *     $elapsed   = $timeNow - $timeStart;
+ *     echo "<!-- page rendered in {$elapsed} seconds -->";
+ * }
+ * 
+ * 
+ * Take a look at the docblock descriptions of each hook to get a sense of where
+ * in the view rendering process the hook is invoked.
+ * 
+ */
+
+/**
+ * hook_before_header
+ * 
+ * This hook is executed before the contents of the header file are processed.
+ */
+function hook_before_header() {}
+
+/**
+ * hook_before_view
+ * 
+ * This hook is executed before the contents of the main view are processed.
+ */
+function hook_before_view() {
+	$module = App::Get()->loadModule();
+	App::Get()->response->addStylesheet($module->moduleStatic.'/css/profile.css');
+}
+
+/**
+ * hook_before_footer
+ * 
+ * This hook is executed before the contents of the footer are processed
+ */
+function hook_before_footer() {}
+
+/**
+ * hook_before_send
+ * 
+ * This hook is after all of the view components (header, view, footer) have been
+ * processed but before the processed results are sent out across the wire to the 
+ * browser. HTTP headers have not yet been sent to the browser.
+ */
+function hook_before_send() {}
+
+/**
+ * hook_after_send
+ * 
+ * This hook is after all of the view components (header, view, footer) have been
+ * processed and sent out across the wire to the browser. It can be used for logging
+ * or analytics purposes, or to append a common trailer to all content.
+ */
+function hook_after_send() {
+	$timeStart = $GLOBALS['balance_request_start'];
+	$timeEnd   = microtime(true);
+	$elapsed   = $timeEnd - $timeStart;
+	
+	echo "\r\n<!-- page rendered in {$elapsed} seconds -->";
+}
diff --git a/0.8.1-rc1/balance/modules/profile/scripts/access.php b/0.8.1-rc1/balance/modules/profile/scripts/access.php
new file mode 100644
index 0000000..3167409
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/scripts/access.php
@@ -0,0 +1,107 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * PROFILE MANAGER - CREATE USER
+ * 
+ * Create new user, required attributes:
+ * 
+ * 	1. First name
+ * 	2. Last name
+ * 	3. Username
+ * 	4. Email 
+ * 
+ * 	- password
+ * 	- confirm password
+ * 
+ * @author s.khudikyan
+**/
+$module = App::Get()->loadModule();
+$allSet = true;
+
+
+if ( isset($_POST["firstname"]) && $_POST["firstname"] != "" ) {
+	$info[ App::Get()->settings['firstname_attr'] ] = $_POST["firstname"];
+} else {
+	// first name is required
+	App::Get()->SetMessage("First name cannot be blank",CAS_MSG_ERROR);
+	$allSet = FALSE;
+}
+
+if ( isset($_POST["lastname"]) && $_POST["lastname"] != "" ) {
+	$info[ App::Get()->settings['lastname_attr'] ] = $_POST["lastname"];
+} else {
+	// last name is required
+	App::Get()->SetMessage("Last name cannot be blank",CAS_MSG_ERROR);
+	$allSet = FALSE;
+}
+
+if ( isset($_POST["username"]) && $_POST["username"] != "" ) {
+	
+	// check username availability
+	$isAvailable = App::Get()->getAuthenticationProvider()->usernameAvailability($_POST["username"]);	
+	if ( $isAvailable ) {
+		$info[ App::Get()->settings['username_attr'] ] = $_POST["username"];
+	} else{
+		App::Get()->SetMessage("Username has been taken",CAS_MSG_ERROR);
+		$allSet = FALSE;
+	}
+} else {
+	// username is required
+	App::Get()->SetMessage("Username cannot be blank",CAS_MSG_ERROR);
+	$allSet = FALSE;
+}
+
+if ( isset($_POST["email"]) && $_POST["email"] != "") {
+	$info[ App::Get()->settings['email_attr'] ] = $_POST["email"];
+} else {
+	// email is required
+	App::Get()->SetMessage("Email cannot be blank",CAS_MSG_ERROR);
+	$allSet = FALSE;
+}
+
+if ( !isset($_POST["password_confirm"]) || $_POST["password_confirm"] == "" ) {
+	
+	// password confirm is required
+	App::Get()->SetMessage("Password cannot be blank and must match",CAS_MSG_ERROR);
+	$allSet = FALSE;
+} elseif ( (isset($_POST["password"]) || $_POST["password"] != "") && 
+		   ( $_POST["password"] == $_POST["password_confirm"] ) ) {
+		   	
+	$info['userPassword'] = $_POST["password"];
+} else {
+	
+	// password is required and must match
+	App::Get()->SetMessage("Password cannot be blank and must match",CAS_MSG_ERROR);
+	$allSet = FALSE;
+}
+
+if ($allSet) {
+	
+	$info[ App::Get()->settings['commonname_attr'] ] = $_POST["firstname"] . " " . $_POST["lastname"];
+	$info[ "objectClass" ] = "inetOrgPerson";
+	if ( App::Get()->getAuthenticationProvider()->addUser($info) ) {
+		
+		App::Get()->Redirect($module->moduleRoot . "/login" ); // add account successful	
+	} else {
+		App::Get()->setMessage("Could not add user.",CAS_MSG_ERROR);
+	}
+} else {
+	
+	App::Get()->Redirect($module->moduleRoot . "/createUser" );
+}
diff --git a/0.8.1-rc1/balance/modules/profile/scripts/changePwd.php b/0.8.1-rc1/balance/modules/profile/scripts/changePwd.php
new file mode 100644
index 0000000..140c189
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/scripts/changePwd.php
@@ -0,0 +1,69 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * PROFILE MANAGER - PASSWORD CHANGE
+ * 
+ * Attempt to change password. This script uses config file to 
+ * check for password restrictions.
+ * 
+ * @author s.khudikyan
+**/
+$module = App::Get()->loadModule();
+
+// Get instance of authentication class
+$authentication = App::Get()->getAuthenticationProvider();
+
+
+if ( !isset($_POST["password_confirm"]) || $_POST["password_confirm"] == "" ) {
+	
+	// password confirm is required
+	App::Get()->SetMessage("Please confirm password.",CAS_MSG_ERROR);
+	App::Get()->Redirect($module->moduleRoot . "/changePwd" );
+	
+} elseif ( (isset($_POST["password"]) || $_POST["password"] != "") && 
+		 ( $_POST["password"] == $_POST["password_confirm"] ) ) {
+
+		 	$message = $authentication->validateChangePassword( $_POST["password"] );
+
+		 	if( is_array($message) ) {
+ 		
+		 		foreach ($message as $value) {
+		 			App::Get()->setMessage($value,CAS_MSG_ERROR);
+		 		}
+		   		
+		   		App::Get()->Redirect($module->moduleRoot . "/changePwd" );
+		 	} else{
+		 		
+		 		// Log the user out
+				$authentication->logout();
+				
+				// End user session
+				App::Get()->EndUserSession();
+				
+				// Redirect to confirmation page
+		   		App::Get()->Redirect($module->moduleRoot . "/passwordChangeConfirmed" ); // password change successful
+   		
+   			}
+		 } else {
+	
+			// password is required and must match
+			App::Get()->SetMessage("Password cannot be blank and must match",CAS_MSG_ERROR);
+			App::Get()->Redirect($module->moduleRoot . "/changePwd" );
+		}
+		
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/profile/scripts/login.php b/0.8.1-rc1/balance/modules/profile/scripts/login.php
new file mode 100644
index 0000000..fc6fd43
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/scripts/login.php
@@ -0,0 +1,46 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * PROFILE MANAGER - LOGIN
+ * 
+ * Attempt to login.
+ * 
+ * @author s.khudikyan
+**/
+$module = App::Get()->loadModule();
+
+// Get instance of authentication class
+$authentication = App::Get()->getAuthenticationProvider();
+
+$message = '';
+
+// If a user is already logged in, redirect to home page
+if( $authentication->isLoggedIn() ) App::Get()->Redirect(SITE_ROOT . "/"); 
+
+// Otherwise, if a user is attempting to log in, process:
+else if(isset($_POST["username"]) && isset($_POST["password"])) {
+
+	// Check the provided login credentials:
+	if($authentication->login($_POST["username"], $_POST["password"])){
+  	 	App::Get()->Redirect(SITE_ROOT . "/" ); // login successful
+  	 } else {
+  	 	App::Get()->SetMessage("Invalid Credentials Provided",CAS_MSG_ERROR);
+  	 	App::Get()->Redirect($module->moduleRoot . "/login");
+  	 }
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/profile/scripts/logout.php b/0.8.1-rc1/balance/modules/profile/scripts/logout.php
new file mode 100644
index 0000000..59ccce3
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/scripts/logout.php
@@ -0,0 +1,36 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * PROFILE MANAGER - LOGOUT
+ * 
+ * End an authenticated user session
+ * 
+ * @author ahart
+ * @author davoodi
+ * @author s.khudikyan
+**/
+
+// Log the user out
+App::Get()->getAuthenticationProvider()->logout();
+
+// End user session
+App::Get()->EndUserSession();
+
+// Redirect to the home page
+App::Get()->Redirect(SITE_ROOT . "/");
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/profile/scripts/manage.php b/0.8.1-rc1/balance/modules/profile/scripts/manage.php
new file mode 100644
index 0000000..0615ec6
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/scripts/manage.php
@@ -0,0 +1,59 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * PROFILE MANAGER - MANAGE USER PROFILE
+ * 
+ * Process user's changes to profile information. 
+ * 
+ * @author s.khudikyan
+**/
+$module = App::Get()->loadModule();
+$allSet = true;
+
+foreach ($_POST as $key=>$value) {
+
+	if ( $key != submit_button) {
+		if ( isset($value) && $value != "" ) {
+			$info[$key] = $value;
+		} else {
+			// set error message
+			App::Get()->SetMessage( 
+				array_search( $key, App::Get()->settings['attr_titles'] ) 
+				. " cannot be left blank.", CAS_MSG_ERROR );
+			$allSet = false;
+		}
+	}
+}
+
+if ($allSet) {
+	// method to edit user
+	if( App::Get()->getAuthenticationProvider()->updateProfile($info) ){
+ 		
+		// user info change successful
+   		App::Get()->Redirect($module->moduleRoot . "/" );
+   	} else{
+   		
+   		// if not logged in - cannot change pwd
+   		App::Get()->SetMessage("Invalid entry",CAS_MSG_ERROR);
+   		App::Get()->Redirect($module->moduleRoot . "/manage" );
+   	}
+} else {
+	
+	App::Get()->Redirect($module->moduleRoot . "/manage" );
+}
diff --git a/0.8.1-rc1/balance/modules/profile/scripts/widgets/UserStatusWidget.php b/0.8.1-rc1/balance/modules/profile/scripts/widgets/UserStatusWidget.php
new file mode 100644
index 0000000..8c9dd27
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/scripts/widgets/UserStatusWidget.php
@@ -0,0 +1,91 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * PROFILE MANAGER - User Status Display
+ * 
+ * This widget displays basic information about the user. It provides a link
+ * to log in when user is logged out and displays username with a log-out link
+ * when user is logged in.
+ * 
+ * This widget also allows the developer to decide whether or not the users will
+ * have access to manage their account through the Profile Manager interface.
+ * 
+ * @author s.khudikyan
+ * 
+ */
+
+class UserStatusWidget 
+	implements Org_Apache_Oodt_Balance_Interfaces_IApplicationWidget {
+		
+	public $isLoggedIn;
+	public $username;
+	public $profileLink;
+	protected $moduleName;
+	
+	/**
+	 * Pass boolean true or false as the first parameter in the options array
+	 * to generate either a login link or a logout link, whichever is appropriate.
+	 *  	True:  user is logged in, show logout link
+	 *  	False: user is not logged in, show login link
+	 * 
+	 * Pass username as the second paramerter in the options array
+	 * 
+	 * Pass boolean true or false as the third parameter in the options array
+	 * to generate the username as a link to the porfile module.
+	 *  	True:  link will be created- *Default*
+	 *  	False: link will not be created
+	 *   
+	 * Pass module name as the fourth paramerter in the options array. This way
+	 * the developer has the option to name the module anything.
+	 * 		Default: 'profile'
+	 */ 
+	public function __construct($options = array()) {
+		$this->isLoggedIn  = ( isset($options[0])   && $options[0] === true );
+		$this->username    = ( isset($options[1]) ) ?  $options[1] : false;
+		$this->profileLink = ( isset($options[2]) ) ?  $options[2] : true;
+		$this->moduleName  = ( isset($options[3]) ) ?  $options[3] : 'profile';
+	}
+	
+	public function render($bEcho = true) {
+		
+		$str 	= '';
+		$module = App::Get()->loadModule($this->moduleName);
+		
+		// Display the appropriate information about the user
+		if($this->isLoggedIn) {
+			$str .= "Logged in as ";
+			if ($this->profileLink) {
+				$str .= '<a href="' . $module->moduleRoot . '/">' . $this->username . '</a>&nbsp;|&nbsp;'
+					.'<a href="' . $module->moduleRoot . '/logout.do">Log Out</a>';
+			} else {
+				$str .=  $this->username . '&nbsp;|&nbsp;'
+						.'<a href="' . $module->moduleRoot . '/logout.do">Log Out</a>';
+			}
+		} else {
+			$str .= '<a href="' . $module->moduleRoot . '/login">Log In</a>';
+		}
+		
+		if($bEcho) {
+			echo $str;
+		} else {
+			return $str;
+		}
+	}
+	
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/profile/static/css/profile.css b/0.8.1-rc1/balance/modules/profile/static/css/profile.css
new file mode 100644
index 0000000..a8d95a5
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/static/css/profile.css
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+ 
+/**
+ * PROFILE MANAGER STYLESHEET
+ *
+ * PAGE ELEMENTS 
+ *
+ */
+fieldset  {
+}
+
+label.invalid {
+	color:#BF1B02;
+	font:1em georgia;
+	margin:0 0 2px;
+}
+
+.profile_input {
+	height:23px;
+	width:200px;
+}
+
+/**
+ * DIV.USERDETAILS
+ * This provides information about the login-status of the user.
+ *
+ * top and color can be changed depending on portal
+ */
+#userdetails {
+	position:absolute;
+	top:105px;
+	right:15px;
+	z-index:10;
+}
+#userdetails a {
+	font-size:13px;
+}
+
+/* Unsupported browsers */
+
+.orange_rbcontent { padding: 0.4em; }
+.orange_rbroundbox { width: 100%; }
+
+#unsupported {
+  font-weight: bold;
+  text-align: left;
+}
+
+/* Signup form */
+
+#signupform table {
+  border-spacing: 0px;
+  border-collapse: collapse;
+  empty-cells: show;
+}
+
+#signupform .label {
+  padding-top: 2px;
+  padding-right: 8px;
+  vertical-align: top;
+  text-align: right;
+  width: 125px;
+  white-space: nowrap;
+}
+
+#signupform .field {
+  padding-bottom: 10px;
+  white-space: nowrap;
+}
+
+#signupform .status {
+  padding-top: 2px;
+  padding-left: 8px;
+  vertical-align: top;
+  width: 246px;
+  white-space: nowrap;
+}
+
+#signupform .textfield {
+  width: 150px;
+}
+
+#signupform .error, .notice, .success {
+  padding:0.25em;
+  margin-bottom:0.5em 0;
+  background-color:#FFFFFF;
+  border:1px solid #BBBBBB;
+}
+
+#signupform label.error {
+  background:none;
+  padding-left: 16px;
+  padding-bottom: 2px;
+  font-weight: bold;
+  color: #EA5200;
+  border:none;
+}
+
+#signupform label.checked /*{
+  background:none;
+}
+
+#signupform .success_msg {
+  font-weight: bold;
+  color: #0060BF;
+  margin-left: 19px;
+}
+
+#signupform #dateformatStatus, #signupform #termsStatus {
+  margin-left: 6px;
+}
+
+#signupform #termswrap {
+  float: left;
+}
+
+#signupform #terms {
+  vertical-align: middle;
+  float: left;
+  display: block;
+  margin-right: 5px;
+}
+
+#signupform #lterms {
+  font-weight: normal;
+  vertical-align: middle;
+  float: left;
+  display: block;
+  width: 350px;
+  white-space: normal;
+}
+
+#signupform #lsignupsubmit {
+  visibility: hidden;
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/profile/static/js/additional-methods.js b/0.8.1-rc1/balance/modules/profile/static/js/additional-methods.js
new file mode 100644
index 0000000..db3ad14
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/static/js/additional-methods.js
@@ -0,0 +1,259 @@
+(function() {

+	

+	function stripHtml(value) {

+		// remove html tags and space chars

+		return value.replace(/<.[^<>]*?>/g, ' ').replace(/&nbsp;|&#160;/gi, ' ')

+		// remove numbers and punctuation

+		.replace(/[0-9.(),;:!?%#$'"_+=\/-]*/g,'');

+	}

+	jQuery.validator.addMethod("maxWords", function(value, element, params) { 

+	    return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length < params; 

+	}, jQuery.validator.format("Please enter {0} words or less.")); 

+	 

+	jQuery.validator.addMethod("minWords", function(value, element, params) { 

+	    return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length >= params; 

+	}, jQuery.validator.format("Please enter at least {0} words.")); 

+	 

+	jQuery.validator.addMethod("rangeWords", function(value, element, params) { 

+	    return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length >= params[0] && value.match(/bw+b/g).length < params[1]; 

+	}, jQuery.validator.format("Please enter between {0} and {1} words."));

+

+})();

+

+jQuery.validator.addMethod("letterswithbasicpunc", function(value, element) {

+	return this.optional(element) || /^[a-z-.,()'\"\s]+$/i.test(value);

+}, "Letters or punctuation only please");  

+

+jQuery.validator.addMethod("alphanumeric", function(value, element) {

+	return this.optional(element) || /^\w+$/i.test(value);

+}, "Letters, numbers, spaces or underscores only please");  

+

+jQuery.validator.addMethod("lettersonly", function(value, element) {

+	return this.optional(element) || /^[a-z]+$/i.test(value);

+}, "Letters only please"); 

+

+jQuery.validator.addMethod("nowhitespace", function(value, element) {

+	return this.optional(element) || /^\S+$/i.test(value);

+}, "No white space please"); 

+

+jQuery.validator.addMethod("ziprange", function(value, element) {

+	return this.optional(element) || /^90[2-5]\d\{2}-\d{4}$/.test(value);

+}, "Your ZIP-code must be in the range 902xx-xxxx to 905-xx-xxxx");

+

+jQuery.validator.addMethod("integer", function(value, element) {

+	return this.optional(element) || /^-?\d+$/.test(value);

+}, "A positive or negative non-decimal number please");

+

+/**

+* Return true, if the value is a valid vehicle identification number (VIN).

+*

+* Works with all kind of text inputs.

+*

+* @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />

+* @desc Declares a required input element whose value must be a valid vehicle identification number.

+*

+* @name jQuery.validator.methods.vinUS

+* @type Boolean

+* @cat Plugins/Validate/Methods

+*/ 

+jQuery.validator.addMethod(

+	"vinUS",

+	function(v){

+		if (v.length != 17)

+			return false;

+		var i, n, d, f, cd, cdv;

+		var LL    = ["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"];

+		var VL    = [1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9];

+		var FL    = [8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2];

+		var rs    = 0;

+		for(i = 0; i < 17; i++){

+		    f = FL[i];

+		    d = v.slice(i,i+1);

+		    if(i == 8){

+		        cdv = d;

+		    }

+		    if(!isNaN(d)){

+		        d *= f;

+		    }

+		    else{

+		        for(n = 0; n < LL.length; n++){

+		            if(d.toUpperCase() === LL[n]){

+		                d = VL[n];

+		                d *= f;

+		                if(isNaN(cdv) && n == 8){

+		                    cdv = LL[n];

+		                }

+		                break;

+		            }

+		        }

+		    }

+		    rs += d;

+		}

+		cd = rs % 11;

+		if(cd == 10){cd = "X";}

+		if(cd == cdv){return true;}

+		return false; 

+	},

+	"The specified vehicle identification number (VIN) is invalid."

+);

+

+/**

+  * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.

+  *

+  * @example jQuery.validator.methods.date("01/01/1900")

+  * @result true

+  *

+  * @example jQuery.validator.methods.date("01/13/1990")

+  * @result false

+  *

+  * @example jQuery.validator.methods.date("01.01.1900")

+  * @result false

+  *

+  * @example <input name="pippo" class="{dateITA:true}" />

+  * @desc Declares an optional input element whose value must be a valid date.

+  *

+  * @name jQuery.validator.methods.dateITA

+  * @type Boolean

+  * @cat Plugins/Validate/Methods

+  */

+jQuery.validator.addMethod(

+	"dateITA",

+	function(value, element) {

+		var check = false;

+		var re = /^\d{1,2}\/\d{1,2}\/\d{4}$/;

+		if( re.test(value)){

+			var adata = value.split('/');

+			var gg = parseInt(adata[0],10);

+			var mm = parseInt(adata[1],10);

+			var aaaa = parseInt(adata[2],10);

+			var xdata = new Date(aaaa,mm-1,gg);

+			if ( ( xdata.getFullYear() == aaaa ) && ( xdata.getMonth () == mm - 1 ) && ( xdata.getDate() == gg ) )

+				check = true;

+			else

+				check = false;

+		} else

+			check = false;

+		return this.optional(element) || check;

+	}, 

+	"Please enter a correct date"

+);

+

+jQuery.validator.addMethod("dateNL", function(value, element) {

+		return this.optional(element) || /^\d\d?[\.\/-]\d\d?[\.\/-]\d\d\d?\d?$/.test(value);

+	}, "Vul hier een geldige datum in."

+);

+

+jQuery.validator.addMethod("time", function(value, element) {

+		return this.optional(element) || /^([01][0-9])|(2[0123]):([0-5])([0-9])$/.test(value);

+	}, "Please enter a valid time, between 00:00 and 23:59"

+);

+

+/**

+ * matches US phone number format 

+ * 

+ * where the area code may not start with 1 and the prefix may not start with 1 

+ * allows '-' or ' ' as a separator and allows parens around area code 

+ * some people may want to put a '1' in front of their number 

+ * 

+ * 1(212)-999-2345

+ * or

+ * 212 999 2344

+ * or

+ * 212-999-0983

+ * 

+ * but not

+ * 111-123-5434

+ * and not

+ * 212 123 4567

+ */

+jQuery.validator.addMethod("phoneUS", function(phone_number, element) {

+    phone_number = phone_number.replace(/\s+/g, ""); 

+	return this.optional(element) || phone_number.length > 9 &&

+		phone_number.match(/^(1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/);

+}, "Please specify a valid phone number");

+

+jQuery.validator.addMethod('phoneUK', function(phone_number, element) {

+return this.optional(element) || phone_number.length > 9 &&

+phone_number.match(/^(\(?(0|\+44)[1-9]{1}\d{1,4}?\)?\s?\d{3,4}\s?\d{3,4})$/);

+}, 'Please specify a valid phone number');

+

+jQuery.validator.addMethod('mobileUK', function(phone_number, element) {

+return this.optional(element) || phone_number.length > 9 &&

+phone_number.match(/^((0|\+44)7(5|6|7|8|9){1}\d{2}\s?\d{6})$/);

+}, 'Please specify a valid mobile number');

+

+// TODO check if value starts with <, otherwise don't try stripping anything

+jQuery.validator.addMethod("strippedminlength", function(value, element, param) {

+	return jQuery(value).text().length >= param;

+}, jQuery.validator.format("Please enter at least {0} characters"));

+

+// same as email, but TLD is optional

+jQuery.validator.addMethod("email2", function(value, element, param) {

+	return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value); 

+}, jQuery.validator.messages.email);

+

+// same as url, but TLD is optional

+jQuery.validator.addMethod("url2", function(value, element, param) {

+	return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); 

+}, jQuery.validator.messages.url);

+

+// NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator

+// Redistributed under the the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0

+// Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)

+jQuery.validator.addMethod("creditcardtypes", function(value, element, param) {

+

+	if (/[^0-9-]+/.test(value)) 

+		return false;

+	

+	value = value.replace(/\D/g, "");

+	

+	var validTypes = 0x0000;

+	

+	if (param.mastercard) 

+		validTypes |= 0x0001;

+	if (param.visa) 

+		validTypes |= 0x0002;

+	if (param.amex) 

+		validTypes |= 0x0004;

+	if (param.dinersclub) 

+		validTypes |= 0x0008;

+	if (param.enroute) 

+		validTypes |= 0x0010;

+	if (param.discover) 

+		validTypes |= 0x0020;

+	if (param.jcb) 

+		validTypes |= 0x0040;

+	if (param.unknown) 

+		validTypes |= 0x0080;

+	if (param.all) 

+		validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;

+	

+	if (validTypes & 0x0001 && /^(51|52|53|54|55)/.test(value)) { //mastercard

+		return value.length == 16;

+	}

+	if (validTypes & 0x0002 && /^(4)/.test(value)) { //visa

+		return value.length == 16;

+	}

+	if (validTypes & 0x0004 && /^(34|37)/.test(value)) { //amex

+		return value.length == 15;

+	}

+	if (validTypes & 0x0008 && /^(300|301|302|303|304|305|36|38)/.test(value)) { //dinersclub

+		return value.length == 14;

+	}

+	if (validTypes & 0x0010 && /^(2014|2149)/.test(value)) { //enroute

+		return value.length == 15;

+	}

+	if (validTypes & 0x0020 && /^(6011)/.test(value)) { //discover

+		return value.length == 16;

+	}

+	if (validTypes & 0x0040 && /^(3)/.test(value)) { //jcb

+		return value.length == 16;

+	}

+	if (validTypes & 0x0040 && /^(2131|1800)/.test(value)) { //jcb

+		return value.length == 15;

+	}

+	if (validTypes & 0x0080) { //unknown

+		return true;

+	}

+	return false;

+}, "Please enter a valid credit card number.");

diff --git a/0.8.1-rc1/balance/modules/profile/static/js/jquery.validate.min.js b/0.8.1-rc1/balance/modules/profile/static/js/jquery.validate.min.js
new file mode 100644
index 0000000..6264866
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/static/js/jquery.validate.min.js
@@ -0,0 +1,16 @@
+/*
+ * jQuery validation plug-in 1.7
+ *
+ * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
+ * http://docs.jquery.com/Plugins/Validation
+ *
+ * Copyright (c) 2006 - 2008 Jörn Zaefferer
+ *
+ * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ */
+(function($){$.extend($.fn,{validate:function(options){if(!this.length){options&&options.debug&&window.console&&console.warn("nothing selected, can't validate, returning nothing");return;}var validator=$.data(this[0],'validator');if(validator){return validator;}validator=new $.validator(options,this[0]);$.data(this[0],'validator',validator);if(validator.settings.onsubmit){this.find("input, button").filter(".cancel").click(function(){validator.cancelSubmit=true;});if(validator.settings.submitHandler){this.find("input, button").filter(":submit").click(function(){validator.submitButton=this;});}this.submit(function(event){if(validator.settings.debug)event.preventDefault();function handle(){if(validator.settings.submitHandler){if(validator.submitButton){var hidden=$("<input type='hidden'/>").attr("name",validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);}validator.settings.submitHandler.call(validator,validator.currentForm);if(validator.submitButton){hidden.remove();}return false;}return true;}if(validator.cancelSubmit){validator.cancelSubmit=false;return handle();}if(validator.form()){if(validator.pendingRequest){validator.formSubmitted=true;return false;}return handle();}else{validator.focusInvalid();return false;}});}return validator;},valid:function(){if($(this[0]).is('form')){return this.validate().form();}else{var valid=true;var validator=$(this[0].form).validate();this.each(function(){valid&=validator.element(this);});return valid;}},removeAttrs:function(attributes){var result={},$element=this;$.each(attributes.split(/\s/),function(index,value){result[value]=$element.attr(value);$element.removeAttr(value);});return result;},rules:function(command,argument){var element=this[0];if(command){var settings=$.data(element.form,'validator').settings;var staticRules=settings.rules;var existingRules=$.validator.staticRules(element);switch(command){case"add":$.extend(existingRules,$.validator.normalizeRule(argument));staticRules[element.name]=existingRules;if(argument.messages)settings.messages[element.name]=$.extend(settings.messages[element.name],argument.messages);break;case"remove":if(!argument){delete staticRules[element.name];return existingRules;}var filtered={};$.each(argument.split(/\s/),function(index,method){filtered[method]=existingRules[method];delete existingRules[method];});return filtered;}}var data=$.validator.normalizeRules($.extend({},$.validator.metadataRules(element),$.validator.classRules(element),$.validator.attributeRules(element),$.validator.staticRules(element)),element);if(data.required){var param=data.required;delete data.required;data=$.extend({required:param},data);}return data;}});$.extend($.expr[":"],{blank:function(a){return!$.trim(""+a.value);},filled:function(a){return!!$.trim(""+a.value);},unchecked:function(a){return!a.checked;}});$.validator=function(options,form){this.settings=$.extend(true,{},$.validator.defaults,options);this.currentForm=form;this.init();};$.validator.format=function(source,params){if(arguments.length==1)return function(){var args=$.makeArray(arguments);args.unshift(source);return $.validator.format.apply(this,args);};if(arguments.length>2&&params.constructor!=Array){params=$.makeArray(arguments).slice(1);}if(params.constructor!=Array){params=[params];}$.each(params,function(i,n){source=source.replace(new RegExp("\\{"+i+"\\}","g"),n);});return source;};$.extend($.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:true,errorContainer:$([]),errorLabelContainer:$([]),onsubmit:true,ignore:[],ignoreTitle:false,onfocusin:function(element){this.lastActive=element;if(this.settings.focusCleanup&&!this.blockFocusCleanup){this.settings.unhighlight&&this.settings.unhighlight.call(this,element,this.settings.errorClass,this.settings.validClass);this.errorsFor(element).hide();}},onfocusout:function(element){if(!this.checkable(element)&&(element.name in this.submitted||!this.optional(element))){this.element(element);}},onkeyup:function(element){if(element.name in this.submitted||element==this.lastElement){this.element(element);}},onclick:function(element){if(element.name in this.submitted)this.element(element);else if(element.parentNode.name in this.submitted)this.element(element.parentNode);},highlight:function(element,errorClass,validClass){$(element).addClass(errorClass).removeClass(validClass);},unhighlight:function(element,errorClass,validClass){$(element).removeClass(errorClass).addClass(validClass);}},setDefaults:function(settings){$.extend($.validator.defaults,settings);},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",accept:"Please enter a value with a valid extension.",maxlength:$.validator.format("Please enter no more than {0} characters."),minlength:$.validator.format("Please enter at least {0} characters."),rangelength:$.validator.format("Please enter a value between {0} and {1} characters long."),range:$.validator.format("Please enter a value between {0} and {1}."),max:$.validator.format("Please enter a value less than or equal to {0}."),min:$.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:false,prototype:{init:function(){this.labelContainer=$(this.settings.errorLabelContainer);this.errorContext=this.labelContainer.length&&this.labelContainer||$(this.currentForm);this.containers=$(this.settings.errorContainer).add(this.settings.errorLabelContainer);this.submitted={};this.valueCache={};this.pendingRequest=0;this.pending={};this.invalid={};this.reset();var groups=(this.groups={});$.each(this.settings.groups,function(key,value){$.each(value.split(/\s/),function(index,name){groups[name]=key;});});var rules=this.settings.rules;$.each(rules,function(key,value){rules[key]=$.validator.normalizeRule(value);});function delegate(event){var validator=$.data(this[0].form,"validator"),eventType="on"+event.type.replace(/^validate/,"");validator.settings[eventType]&&validator.settings[eventType].call(validator,this[0]);}$(this.currentForm).validateDelegate(":text, :password, :file, select, textarea","focusin focusout keyup",delegate).validateDelegate(":radio, :checkbox, select, option","click",delegate);if(this.settings.invalidHandler)$(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler);},form:function(){this.checkForm();$.extend(this.submitted,this.errorMap);this.invalid=$.extend({},this.errorMap);if(!this.valid())$(this.currentForm).triggerHandler("invalid-form",[this]);this.showErrors();return this.valid();},checkForm:function(){this.prepareForm();for(var i=0,elements=(this.currentElements=this.elements());elements[i];i++){this.check(elements[i]);}return this.valid();},element:function(element){element=this.clean(element);this.lastElement=element;this.prepareElement(element);this.currentElements=$(element);var result=this.check(element);if(result){delete this.invalid[element.name];}else{this.invalid[element.name]=true;}if(!this.numberOfInvalids()){this.toHide=this.toHide.add(this.containers);}this.showErrors();return result;},showErrors:function(errors){if(errors){$.extend(this.errorMap,errors);this.errorList=[];for(var name in errors){this.errorList.push({message:errors[name],element:this.findByName(name)[0]});}this.successList=$.grep(this.successList,function(element){return!(element.name in errors);});}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors();},resetForm:function(){if($.fn.resetForm)$(this.currentForm).resetForm();this.submitted={};this.prepareForm();this.hideErrors();this.elements().removeClass(this.settings.errorClass);},numberOfInvalids:function(){return this.objectLength(this.invalid);},objectLength:function(obj){var count=0;for(var i in obj)count++;return count;},hideErrors:function(){this.addWrapper(this.toHide).hide();},valid:function(){return this.size()==0;},size:function(){return this.errorList.length;},focusInvalid:function(){if(this.settings.focusInvalid){try{$(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin");}catch(e){}}},findLastActive:function(){var lastActive=this.lastActive;return lastActive&&$.grep(this.errorList,function(n){return n.element.name==lastActive.name;}).length==1&&lastActive;},elements:function(){var validator=this,rulesCache={};return $([]).add(this.currentForm.elements).filter(":input").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){!this.name&&validator.settings.debug&&window.console&&console.error("%o has no name assigned",this);if(this.name in rulesCache||!validator.objectLength($(this).rules()))return false;rulesCache[this.name]=true;return true;});},clean:function(selector){return $(selector)[0];},errors:function(){return $(this.settings.errorElement+"."+this.settings.errorClass,this.errorContext);},reset:function(){this.successList=[];this.errorList=[];this.errorMap={};this.toShow=$([]);this.toHide=$([]);this.currentElements=$([]);},prepareForm:function(){this.reset();this.toHide=this.errors().add(this.containers);},prepareElement:function(element){this.reset();this.toHide=this.errorsFor(element);},check:function(element){element=this.clean(element);if(this.checkable(element)){element=this.findByName(element.name)[0];}var rules=$(element).rules();var dependencyMismatch=false;for(method in rules){var rule={method:method,parameters:rules[method]};try{var result=$.validator.methods[method].call(this,element.value.replace(/\r/g,""),element,rule.parameters);if(result=="dependency-mismatch"){dependencyMismatch=true;continue;}dependencyMismatch=false;if(result=="pending"){this.toHide=this.toHide.not(this.errorsFor(element));return;}if(!result){this.formatAndAdd(element,rule);return false;}}catch(e){this.settings.debug&&window.console&&console.log("exception occured when checking element "+element.id
++", check the '"+rule.method+"' method",e);throw e;}}if(dependencyMismatch)return;if(this.objectLength(rules))this.successList.push(element);return true;},customMetaMessage:function(element,method){if(!$.metadata)return;var meta=this.settings.meta?$(element).metadata()[this.settings.meta]:$(element).metadata();return meta&&meta.messages&&meta.messages[method];},customMessage:function(name,method){var m=this.settings.messages[name];return m&&(m.constructor==String?m:m[method]);},findDefined:function(){for(var i=0;i<arguments.length;i++){if(arguments[i]!==undefined)return arguments[i];}return undefined;},defaultMessage:function(element,method){return this.findDefined(this.customMessage(element.name,method),this.customMetaMessage(element,method),!this.settings.ignoreTitle&&element.title||undefined,$.validator.messages[method],"<strong>Warning: No message defined for "+element.name+"</strong>");},formatAndAdd:function(element,rule){var message=this.defaultMessage(element,rule.method),theregex=/\$?\{(\d+)\}/g;if(typeof message=="function"){message=message.call(this,rule.parameters,element);}else if(theregex.test(message)){message=jQuery.format(message.replace(theregex,'{$1}'),rule.parameters);}this.errorList.push({message:message,element:element});this.errorMap[element.name]=message;this.submitted[element.name]=message;},addWrapper:function(toToggle){if(this.settings.wrapper)toToggle=toToggle.add(toToggle.parent(this.settings.wrapper));return toToggle;},defaultShowErrors:function(){for(var i=0;this.errorList[i];i++){var error=this.errorList[i];this.settings.highlight&&this.settings.highlight.call(this,error.element,this.settings.errorClass,this.settings.validClass);this.showLabel(error.element,error.message);}if(this.errorList.length){this.toShow=this.toShow.add(this.containers);}if(this.settings.success){for(var i=0;this.successList[i];i++){this.showLabel(this.successList[i]);}}if(this.settings.unhighlight){for(var i=0,elements=this.validElements();elements[i];i++){this.settings.unhighlight.call(this,elements[i],this.settings.errorClass,this.settings.validClass);}}this.toHide=this.toHide.not(this.toShow);this.hideErrors();this.addWrapper(this.toShow).show();},validElements:function(){return this.currentElements.not(this.invalidElements());},invalidElements:function(){return $(this.errorList).map(function(){return this.element;});},showLabel:function(element,message){var label=this.errorsFor(element);if(label.length){label.removeClass().addClass(this.settings.errorClass);label.attr("generated")&&label.html(message);}else{label=$("<"+this.settings.errorElement+"/>").attr({"for":this.idOrName(element),generated:true}).addClass(this.settings.errorClass).html(message||"");if(this.settings.wrapper){label=label.hide().show().wrap("<"+this.settings.wrapper+"/>").parent();}if(!this.labelContainer.append(label).length)this.settings.errorPlacement?this.settings.errorPlacement(label,$(element)):label.insertAfter(element);}if(!message&&this.settings.success){label.text("");typeof this.settings.success=="string"?label.addClass(this.settings.success):this.settings.success(label);}this.toShow=this.toShow.add(label);},errorsFor:function(element){var name=this.idOrName(element);return this.errors().filter(function(){return $(this).attr('for')==name;});},idOrName:function(element){return this.groups[element.name]||(this.checkable(element)?element.name:element.id||element.name);},checkable:function(element){return/radio|checkbox/i.test(element.type);},findByName:function(name){var form=this.currentForm;return $(document.getElementsByName(name)).map(function(index,element){return element.form==form&&element.name==name&&element||null;});},getLength:function(value,element){switch(element.nodeName.toLowerCase()){case'select':return $("option:selected",element).length;case'input':if(this.checkable(element))return this.findByName(element.name).filter(':checked').length;}return value.length;},depend:function(param,element){return this.dependTypes[typeof param]?this.dependTypes[typeof param](param,element):true;},dependTypes:{"boolean":function(param,element){return param;},"string":function(param,element){return!!$(param,element.form).length;},"function":function(param,element){return param(element);}},optional:function(element){return!$.validator.methods.required.call(this,$.trim(element.value),element)&&"dependency-mismatch";},startRequest:function(element){if(!this.pending[element.name]){this.pendingRequest++;this.pending[element.name]=true;}},stopRequest:function(element,valid){this.pendingRequest--;if(this.pendingRequest<0)this.pendingRequest=0;delete this.pending[element.name];if(valid&&this.pendingRequest==0&&this.formSubmitted&&this.form()){$(this.currentForm).submit();this.formSubmitted=false;}else if(!valid&&this.pendingRequest==0&&this.formSubmitted){$(this.currentForm).triggerHandler("invalid-form",[this]);this.formSubmitted=false;}},previousValue:function(element){return $.data(element,"previousValue")||$.data(element,"previousValue",{old:null,valid:true,message:this.defaultMessage(element,"remote")});}},classRuleSettings:{required:{required:true},email:{email:true},url:{url:true},date:{date:true},dateISO:{dateISO:true},dateDE:{dateDE:true},number:{number:true},numberDE:{numberDE:true},digits:{digits:true},creditcard:{creditcard:true}},addClassRules:function(className,rules){className.constructor==String?this.classRuleSettings[className]=rules:$.extend(this.classRuleSettings,className);},classRules:function(element){var rules={};var classes=$(element).attr('class');classes&&$.each(classes.split(' '),function(){if(this in $.validator.classRuleSettings){$.extend(rules,$.validator.classRuleSettings[this]);}});return rules;},attributeRules:function(element){var rules={};var $element=$(element);for(method in $.validator.methods){var value=$element.attr(method);if(value){rules[method]=value;}}if(rules.maxlength&&/-1|2147483647|524288/.test(rules.maxlength)){delete rules.maxlength;}return rules;},metadataRules:function(element){if(!$.metadata)return{};var meta=$.data(element.form,'validator').settings.meta;return meta?$(element).metadata()[meta]:$(element).metadata();},staticRules:function(element){var rules={};var validator=$.data(element.form,'validator');if(validator.settings.rules){rules=$.validator.normalizeRule(validator.settings.rules[element.name])||{};}return rules;},normalizeRules:function(rules,element){$.each(rules,function(prop,val){if(val===false){delete rules[prop];return;}if(val.param||val.depends){var keepRule=true;switch(typeof val.depends){case"string":keepRule=!!$(val.depends,element.form).length;break;case"function":keepRule=val.depends.call(element,element);break;}if(keepRule){rules[prop]=val.param!==undefined?val.param:true;}else{delete rules[prop];}}});$.each(rules,function(rule,parameter){rules[rule]=$.isFunction(parameter)?parameter(element):parameter;});$.each(['minlength','maxlength','min','max'],function(){if(rules[this]){rules[this]=Number(rules[this]);}});$.each(['rangelength','range'],function(){if(rules[this]){rules[this]=[Number(rules[this][0]),Number(rules[this][1])];}});if($.validator.autoCreateRanges){if(rules.min&&rules.max){rules.range=[rules.min,rules.max];delete rules.min;delete rules.max;}if(rules.minlength&&rules.maxlength){rules.rangelength=[rules.minlength,rules.maxlength];delete rules.minlength;delete rules.maxlength;}}if(rules.messages){delete rules.messages;}return rules;},normalizeRule:function(data){if(typeof data=="string"){var transformed={};$.each(data.split(/\s/),function(){transformed[this]=true;});data=transformed;}return data;},addMethod:function(name,method,message){$.validator.methods[name]=method;$.validator.messages[name]=message!=undefined?message:$.validator.messages[name];if(method.length<3){$.validator.addClassRules(name,$.validator.normalizeRule(name));}},methods:{required:function(value,element,param){if(!this.depend(param,element))return"dependency-mismatch";switch(element.nodeName.toLowerCase()){case'select':var val=$(element).val();return val&&val.length>0;case'input':if(this.checkable(element))return this.getLength(value,element)>0;default:return $.trim(value).length>0;}},remote:function(value,element,param){if(this.optional(element))return"dependency-mismatch";var previous=this.previousValue(element);if(!this.settings.messages[element.name])this.settings.messages[element.name]={};previous.originalMessage=this.settings.messages[element.name].remote;this.settings.messages[element.name].remote=previous.message;param=typeof param=="string"&&{url:param}||param;if(previous.old!==value){previous.old=value;var validator=this;this.startRequest(element);var data={};data[element.name]=value;$.ajax($.extend(true,{url:param,mode:"abort",port:"validate"+element.name,dataType:"json",data:data,success:function(response){validator.settings.messages[element.name].remote=previous.originalMessage;var valid=response===true;if(valid){var submitted=validator.formSubmitted;validator.prepareElement(element);validator.formSubmitted=submitted;validator.successList.push(element);validator.showErrors();}else{var errors={};var message=(previous.message=response||validator.defaultMessage(element,"remote"));errors[element.name]=$.isFunction(message)?message(value):message;validator.showErrors(errors);}previous.valid=valid;validator.stopRequest(element,valid);}},param));return"pending";}else if(this.pending[element.name]){return"pending";}return previous.valid;},minlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)>=param;},maxlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)<=param;},rangelength:function(value,element,param){var length=this.getLength($.trim(value),element);return this.optional(element)||(length>=param[0]&&length<=param[1]);},min:function(value,element,param){return this.optional(element)||value>=param;},max:function(value,element,param){return this.optional(element)||value<=param;},range:function(value,element,param){return this.optional(element)||(value>=param[0]&&value<=param[1]);},email:function(value,element){return this.optional(element)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);},url:function(value,element){return this.optional(element)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);},date:function(value,element){return this.optional(element)||!/Invalid|NaN/.test(new Date(value));},dateISO:function(value,element){return this.optional(element)||/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);},number:function(value,element){return this.optional(element)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);},digits:function(value,element){return this.optional(element)||/^\d+$/.test(value);},creditcard:function(value,element){if(this.optional(element))return"dependency-mismatch";if(/[^0-9-]+/.test(value))return false;var nCheck=0,nDigit=0,bEven=false;value=value.replace(/\D/g,"");for(var n=value.length-1;n>=0;n--){var cDigit=value.charAt(n);var nDigit=parseInt(cDigit,10);if(bEven){if((nDigit*=2)>9)nDigit-=9;}nCheck+=nDigit;bEven=!bEven;}return(nCheck%10)==0;},accept:function(value,element,param){param=typeof param=="string"?param.replace(/,/g,'|'):"png|jpe?g|gif";return this.optional(element)||value.match(new RegExp(".("+param+")$","i"));},equalTo:function(value,element,param){var target=$(param).unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){$(element).valid();});return value==target.val();}}});$.format=$.validator.format;})(jQuery);;(function($){var ajax=$.ajax;var pendingRequests={};$.ajax=function(settings){settings=$.extend(settings,$.extend({},$.ajaxSettings,settings));var port=settings.port;if(settings.mode=="abort"){if(pendingRequests[port]){pendingRequests[port].abort();}return(pendingRequests[port]=ajax.apply(this,arguments));}return ajax.apply(this,arguments);};})(jQuery);;(function($){if(!jQuery.event.special.focusin&&!jQuery.event.special.focusout&&document.addEventListener){$.each({focus:'focusin',blur:'focusout'},function(original,fix){$.event.special[fix]={setup:function(){this.addEventListener(original,handler,true);},teardown:function(){this.removeEventListener(original,handler,true);},handler:function(e){arguments[0]=$.event.fix(e);arguments[0].type=fix;return $.event.handle.apply(this,arguments);}};function handler(e){e=$.event.fix(e);e.type=fix;return $.event.handle.call(this,e);}});};$.extend($.fn,{validateDelegate:function(delegate,type,handler){return this.bind(type,function(event){var target=$(event.target);if(target.is(delegate)){return handler.apply(target,arguments);}});}});})(jQuery);
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/profile/static/js/jquery.validate.pack.js b/0.8.1-rc1/balance/modules/profile/static/js/jquery.validate.pack.js
new file mode 100644
index 0000000..8ec2fb7
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/static/js/jquery.validate.pack.js
@@ -0,0 +1,15 @@
+/*
+ * jQuery validation plug-in 1.7
+ *
+ * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
+ * http://docs.jquery.com/Plugins/Validation
+ *
+ * Copyright (c) 2006 - 2008 Jörn Zaefferer
+ *
+ * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ */
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(7($){$.H($.2L,{17:7(d){l(!6.F){d&&d.2q&&2T.1z&&1z.52("3y 3p, 4L\'t 17, 64 3y");8}p c=$.19(6[0],\'v\');l(c){8 c}c=2w $.v(d,6[0]);$.19(6[0],\'v\',c);l(c.q.3x){6.3s("1w, 3i").1o(".4E").3e(7(){c.3b=w});l(c.q.35){6.3s("1w, 3i").1o(":2s").3e(7(){c.1Z=6})}6.2s(7(b){l(c.q.2q)b.5J();7 1T(){l(c.q.35){l(c.1Z){p a=$("<1w 1V=\'5r\'/>").1s("u",c.1Z.u).33(c.1Z.Z).51(c.U)}c.q.35.V(c,c.U);l(c.1Z){a.3D()}8 N}8 w}l(c.3b){c.3b=N;8 1T()}l(c.L()){l(c.1b){c.1l=w;8 N}8 1T()}12{c.2l();8 N}})}8 c},J:7(){l($(6[0]).2W(\'L\')){8 6.17().L()}12{p b=w;p a=$(6[0].L).17();6.P(7(){b&=a.I(6)});8 b}},4D:7(c){p d={},$I=6;$.P(c.1I(/\\s/),7(a,b){d[b]=$I.1s(b);$I.6d(b)});8 d},1i:7(h,k){p f=6[0];l(h){p i=$.19(f.L,\'v\').q;p d=i.1i;p c=$.v.36(f);23(h){1e"1d":$.H(c,$.v.1X(k));d[f.u]=c;l(k.G)i.G[f.u]=$.H(i.G[f.u],k.G);31;1e"3D":l(!k){T d[f.u];8 c}p e={};$.P(k.1I(/\\s/),7(a,b){e[b]=c[b];T c[b]});8 e}}p g=$.v.41($.H({},$.v.3Y(f),$.v.3V(f),$.v.3T(f),$.v.36(f)),f);l(g.15){p j=g.15;T g.15;g=$.H({15:j},g)}8 g}});$.H($.5p[":"],{5n:7(a){8!$.1p(""+a.Z)},5g:7(a){8!!$.1p(""+a.Z)},5f:7(a){8!a.4h}});$.v=7(b,a){6.q=$.H(w,{},$.v.3d,b);6.U=a;6.3I()};$.v.W=7(c,b){l(R.F==1)8 7(){p a=$.3F(R);a.4V(c);8 $.v.W.1Q(6,a)};l(R.F>2&&b.2c!=3B){b=$.3F(R).4Q(1)}l(b.2c!=3B){b=[b]}$.P(b,7(i,n){c=c.1u(2w 3t("\\\\{"+i+"\\\\}","g"),n)});8 c};$.H($.v,{3d:{G:{},2a:{},1i:{},1c:"3r",28:"J",2F:"4P",2l:w,3o:$([]),2D:$([]),3x:w,3l:[],3k:N,4O:7(a){6.3U=a;l(6.q.4K&&!6.4J){6.q.1K&&6.q.1K.V(6,a,6.q.1c,6.q.28);6.1M(a).2A()}},4C:7(a){l(!6.1E(a)&&(a.u 11 6.1a||!6.K(a))){6.I(a)}},6c:7(a){l(a.u 11 6.1a||a==6.4A){6.I(a)}},68:7(a){l(a.u 11 6.1a)6.I(a);12 l(a.4x.u 11 6.1a)6.I(a.4x)},39:7(a,c,b){$(a).22(c).2v(b)},1K:7(a,c,b){$(a).2v(c).22(b)}},63:7(a){$.H($.v.3d,a)},G:{15:"61 4r 2W 15.",1q:"M 2O 6 4r.",1J:"M O a J 1J 5X.",1B:"M O a J 5W.",1A:"M O a J 1A.",2j:"M O a J 1A (5Q).",1G:"M O a J 1G.",1P:"M O 5O 1P.",2f:"M O a J 5L 5I 1G.",2o:"M O 47 5F Z 5B.",43:"M O a Z 5z a J 5x.",18:$.v.W("M O 3K 5v 2X {0} 2V."),1y:$.v.W("M O 5t 5s {0} 2V."),2i:$.v.W("M O a Z 3W {0} 3O {1} 2V 5o."),2r:$.v.W("M O a Z 3W {0} 3O {1}."),1C:$.v.W("M O a Z 5j 2X 46 3M 3L {0}."),1t:$.v.W("M O a Z 5d 2X 46 3M 3L {0}.")},3J:N,5a:{3I:7(){6.24=$(6.q.2D);6.4t=6.24.F&&6.24||$(6.U);6.2x=$(6.q.3o).1d(6.q.2D);6.1a={};6.54={};6.1b=0;6.1h={};6.1f={};6.21();p f=(6.2a={});$.P(6.q.2a,7(d,c){$.P(c.1I(/\\s/),7(a,b){f[b]=d})});p e=6.q.1i;$.P(e,7(b,a){e[b]=$.v.1X(a)});7 2N(a){p b=$.19(6[0].L,"v"),3c="4W"+a.1V.1u(/^17/,"");b.q[3c]&&b.q[3c].V(b,6[0])}$(6.U).2K(":3E, :4U, :4T, 2e, 4S","2d 2J 4R",2N).2K(":3C, :3A, 2e, 3z","3e",2N);l(6.q.3w)$(6.U).2I("1f-L.17",6.q.3w)},L:7(){6.3v();$.H(6.1a,6.1v);6.1f=$.H({},6.1v);l(!6.J())$(6.U).3u("1f-L",[6]);6.1m();8 6.J()},3v:7(){6.2H();Q(p i=0,14=(6.2b=6.14());14[i];i++){6.29(14[i])}8 6.J()},I:7(a){a=6.2G(a);6.4A=a;6.2P(a);6.2b=$(a);p b=6.29(a);l(b){T 6.1f[a.u]}12{6.1f[a.u]=w}l(!6.3q()){6.13=6.13.1d(6.2x)}6.1m();8 b},1m:7(b){l(b){$.H(6.1v,b);6.S=[];Q(p c 11 b){6.S.27({1j:b[c],I:6.26(c)[0]})}6.1n=$.3n(6.1n,7(a){8!(a.u 11 b)})}6.q.1m?6.q.1m.V(6,6.1v,6.S):6.3m()},2S:7(){l($.2L.2S)$(6.U).2S();6.1a={};6.2H();6.2Q();6.14().2v(6.q.1c)},3q:7(){8 6.2k(6.1f)},2k:7(a){p b=0;Q(p i 11 a)b++;8 b},2Q:7(){6.2C(6.13).2A()},J:7(){8 6.3j()==0},3j:7(){8 6.S.F},2l:7(){l(6.q.2l){3Q{$(6.3h()||6.S.F&&6.S[0].I||[]).1o(":4N").3g().4M("2d")}3f(e){}}},3h:7(){p a=6.3U;8 a&&$.3n(6.S,7(n){8 n.I.u==a.u}).F==1&&a},14:7(){p a=6,2B={};8 $([]).1d(6.U.14).1o(":1w").1L(":2s, :21, :4I, [4H]").1L(6.q.3l).1o(7(){!6.u&&a.q.2q&&2T.1z&&1z.3r("%o 4G 3K u 4F",6);l(6.u 11 2B||!a.2k($(6).1i()))8 N;2B[6.u]=w;8 w})},2G:7(a){8 $(a)[0]},2z:7(){8 $(6.q.2F+"."+6.q.1c,6.4t)},21:7(){6.1n=[];6.S=[];6.1v={};6.1k=$([]);6.13=$([]);6.2b=$([])},2H:7(){6.21();6.13=6.2z().1d(6.2x)},2P:7(a){6.21();6.13=6.1M(a)},29:7(d){d=6.2G(d);l(6.1E(d)){d=6.26(d.u)[0]}p a=$(d).1i();p c=N;Q(Y 11 a){p b={Y:Y,2n:a[Y]};3Q{p f=$.v.1N[Y].V(6,d.Z.1u(/\\r/g,""),d,b.2n);l(f=="1S-1Y"){c=w;6g}c=N;l(f=="1h"){6.13=6.13.1L(6.1M(d));8}l(!f){6.4B(d,b);8 N}}3f(e){6.q.2q&&2T.1z&&1z.6f("6e 6b 6a 69 I "+d.4z+", 29 47 \'"+b.Y+"\' Y",e);67 e;}}l(c)8;l(6.2k(a))6.1n.27(d);8 w},4y:7(a,b){l(!$.1H)8;p c=6.q.3a?$(a).1H()[6.q.3a]:$(a).1H();8 c&&c.G&&c.G[b]},4w:7(a,b){p m=6.q.G[a];8 m&&(m.2c==4v?m:m[b])},4u:7(){Q(p i=0;i<R.F;i++){l(R[i]!==20)8 R[i]}8 20},2u:7(a,b){8 6.4u(6.4w(a.u,b),6.4y(a,b),!6.q.3k&&a.62||20,$.v.G[b],"<4s>60: 5Z 1j 5Y Q "+a.u+"</4s>")},4B:7(b,a){p c=6.2u(b,a.Y),37=/\\$?\\{(\\d+)\\}/g;l(1g c=="7"){c=c.V(6,a.2n,b)}12 l(37.16(c)){c=1F.W(c.1u(37,\'{$1}\'),a.2n)}6.S.27({1j:c,I:b});6.1v[b.u]=c;6.1a[b.u]=c},2C:7(a){l(6.q.2t)a=a.1d(a.4q(6.q.2t));8 a},3m:7(){Q(p i=0;6.S[i];i++){p a=6.S[i];6.q.39&&6.q.39.V(6,a.I,6.q.1c,6.q.28);6.2E(a.I,a.1j)}l(6.S.F){6.1k=6.1k.1d(6.2x)}l(6.q.1x){Q(p i=0;6.1n[i];i++){6.2E(6.1n[i])}}l(6.q.1K){Q(p i=0,14=6.4p();14[i];i++){6.q.1K.V(6,14[i],6.q.1c,6.q.28)}}6.13=6.13.1L(6.1k);6.2Q();6.2C(6.1k).4o()},4p:7(){8 6.2b.1L(6.4n())},4n:7(){8 $(6.S).4m(7(){8 6.I})},2E:7(a,c){p b=6.1M(a);l(b.F){b.2v().22(6.q.1c);b.1s("4l")&&b.4k(c)}12{b=$("<"+6.q.2F+"/>").1s({"Q":6.34(a),4l:w}).22(6.q.1c).4k(c||"");l(6.q.2t){b=b.2A().4o().5V("<"+6.q.2t+"/>").4q()}l(!6.24.5S(b).F)6.q.4j?6.q.4j(b,$(a)):b.5R(a)}l(!c&&6.q.1x){b.3E("");1g 6.q.1x=="1D"?b.22(6.q.1x):6.q.1x(b)}6.1k=6.1k.1d(b)},1M:7(a){p b=6.34(a);8 6.2z().1o(7(){8 $(6).1s(\'Q\')==b})},34:7(a){8 6.2a[a.u]||(6.1E(a)?a.u:a.4z||a.u)},1E:7(a){8/3C|3A/i.16(a.1V)},26:7(d){p c=6.U;8 $(4i.5P(d)).4m(7(a,b){8 b.L==c&&b.u==d&&b||4g})},1O:7(a,b){23(b.4f.4e()){1e\'2e\':8 $("3z:3p",b).F;1e\'1w\':l(6.1E(b))8 6.26(b.u).1o(\':4h\').F}8 a.F},4d:7(b,a){8 6.32[1g b]?6.32[1g b](b,a):w},32:{"5N":7(b,a){8 b},"1D":7(b,a){8!!$(b,a.L).F},"7":7(b,a){8 b(a)}},K:7(a){8!$.v.1N.15.V(6,$.1p(a.Z),a)&&"1S-1Y"},4c:7(a){l(!6.1h[a.u]){6.1b++;6.1h[a.u]=w}},4b:7(a,b){6.1b--;l(6.1b<0)6.1b=0;T 6.1h[a.u];l(b&&6.1b==0&&6.1l&&6.L()){$(6.U).2s();6.1l=N}12 l(!b&&6.1b==0&&6.1l){$(6.U).3u("1f-L",[6]);6.1l=N}},2h:7(a){8 $.19(a,"2h")||$.19(a,"2h",{2M:4g,J:w,1j:6.2u(a,"1q")})}},1R:{15:{15:w},1J:{1J:w},1B:{1B:w},1A:{1A:w},2j:{2j:w},4a:{4a:w},1G:{1G:w},49:{49:w},1P:{1P:w},2f:{2f:w}},48:7(a,b){a.2c==4v?6.1R[a]=b:$.H(6.1R,a)},3V:7(b){p a={};p c=$(b).1s(\'5H\');c&&$.P(c.1I(\' \'),7(){l(6 11 $.v.1R){$.H(a,$.v.1R[6])}});8 a},3T:7(c){p a={};p d=$(c);Q(Y 11 $.v.1N){p b=d.1s(Y);l(b){a[Y]=b}}l(a.18&&/-1|5G|5C/.16(a.18)){T a.18}8 a},3Y:7(a){l(!$.1H)8{};p b=$.19(a.L,\'v\').q.3a;8 b?$(a).1H()[b]:$(a).1H()},36:7(b){p a={};p c=$.19(b.L,\'v\');l(c.q.1i){a=$.v.1X(c.q.1i[b.u])||{}}8 a},41:7(d,e){$.P(d,7(c,b){l(b===N){T d[c];8}l(b.2R||b.2p){p a=w;23(1g b.2p){1e"1D":a=!!$(b.2p,e.L).F;31;1e"7":a=b.2p.V(e,e);31}l(a){d[c]=b.2R!==20?b.2R:w}12{T d[c]}}});$.P(d,7(a,b){d[a]=$.44(b)?b(e):b});$.P([\'1y\',\'18\',\'1t\',\'1C\'],7(){l(d[6]){d[6]=2Z(d[6])}});$.P([\'2i\',\'2r\'],7(){l(d[6]){d[6]=[2Z(d[6][0]),2Z(d[6][1])]}});l($.v.3J){l(d.1t&&d.1C){d.2r=[d.1t,d.1C];T d.1t;T d.1C}l(d.1y&&d.18){d.2i=[d.1y,d.18];T d.1y;T d.18}}l(d.G){T d.G}8 d},1X:7(a){l(1g a=="1D"){p b={};$.P(a.1I(/\\s/),7(){b[6]=w});a=b}8 a},5A:7(c,a,b){$.v.1N[c]=a;$.v.G[c]=b!=20?b:$.v.G[c];l(a.F<3){$.v.48(c,$.v.1X(c))}},1N:{15:7(c,d,a){l(!6.4d(a,d))8"1S-1Y";23(d.4f.4e()){1e\'2e\':p b=$(d).33();8 b&&b.F>0;1e\'1w\':l(6.1E(d))8 6.1O(c,d)>0;5y:8 $.1p(c).F>0}},1q:7(f,h,j){l(6.K(h))8"1S-1Y";p g=6.2h(h);l(!6.q.G[h.u])6.q.G[h.u]={};g.40=6.q.G[h.u].1q;6.q.G[h.u].1q=g.1j;j=1g j=="1D"&&{1B:j}||j;l(g.2M!==f){g.2M=f;p k=6;6.4c(h);p i={};i[h.u]=f;$.2U($.H(w,{1B:j,3Z:"2Y",3X:"17"+h.u,5w:"5u",19:i,1x:7(d){k.q.G[h.u].1q=g.40;p b=d===w;l(b){p e=k.1l;k.2P(h);k.1l=e;k.1n.27(h);k.1m()}12{p a={};p c=(g.1j=d||k.2u(h,"1q"));a[h.u]=$.44(c)?c(f):c;k.1m(a)}g.J=b;k.4b(h,b)}},j));8"1h"}12 l(6.1h[h.u]){8"1h"}8 g.J},1y:7(b,c,a){8 6.K(c)||6.1O($.1p(b),c)>=a},18:7(b,c,a){8 6.K(c)||6.1O($.1p(b),c)<=a},2i:7(b,d,a){p c=6.1O($.1p(b),d);8 6.K(d)||(c>=a[0]&&c<=a[1])},1t:7(b,c,a){8 6.K(c)||b>=a},1C:7(b,c,a){8 6.K(c)||b<=a},2r:7(b,c,a){8 6.K(c)||(b>=a[0]&&b<=a[1])},1J:7(a,b){8 6.K(b)||/^((([a-z]|\\d|[!#\\$%&\'\\*\\+\\-\\/=\\?\\^X`{\\|}~]|[\\E-\\B\\C-\\x\\A-\\y])+(\\.([a-z]|\\d|[!#\\$%&\'\\*\\+\\-\\/=\\?\\^X`{\\|}~]|[\\E-\\B\\C-\\x\\A-\\y])+)*)|((\\3S)((((\\2m|\\1W)*(\\30\\3R))?(\\2m|\\1W)+)?(([\\3P-\\5q\\45\\42\\5D-\\5E\\3N]|\\5m|[\\5l-\\5k]|[\\5i-\\5K]|[\\E-\\B\\C-\\x\\A-\\y])|(\\\\([\\3P-\\1W\\45\\42\\30-\\3N]|[\\E-\\B\\C-\\x\\A-\\y]))))*(((\\2m|\\1W)*(\\30\\3R))?(\\2m|\\1W)+)?(\\3S)))@((([a-z]|\\d|[\\E-\\B\\C-\\x\\A-\\y])|(([a-z]|\\d|[\\E-\\B\\C-\\x\\A-\\y])([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])*([a-z]|\\d|[\\E-\\B\\C-\\x\\A-\\y])))\\.)+(([a-z]|[\\E-\\B\\C-\\x\\A-\\y])|(([a-z]|[\\E-\\B\\C-\\x\\A-\\y])([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])*([a-z]|[\\E-\\B\\C-\\x\\A-\\y])))\\.?$/i.16(a)},1B:7(a,b){8 6.K(b)||/^(5h?|5M):\\/\\/(((([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])|(%[\\1U-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:)*@)?(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|((([a-z]|\\d|[\\E-\\B\\C-\\x\\A-\\y])|(([a-z]|\\d|[\\E-\\B\\C-\\x\\A-\\y])([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])*([a-z]|\\d|[\\E-\\B\\C-\\x\\A-\\y])))\\.)+(([a-z]|[\\E-\\B\\C-\\x\\A-\\y])|(([a-z]|[\\E-\\B\\C-\\x\\A-\\y])([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])*([a-z]|[\\E-\\B\\C-\\x\\A-\\y])))\\.?)(:\\d*)?)(\\/((([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])|(%[\\1U-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)+(\\/(([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])|(%[\\1U-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)*)*)?)?(\\?((([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])|(%[\\1U-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)|[\\5e-\\5T]|\\/|\\?)*)?(\\#((([a-z]|\\d|-|\\.|X|~|[\\E-\\B\\C-\\x\\A-\\y])|(%[\\1U-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$/i.16(a)},1A:7(a,b){8 6.K(b)||!/5U|5c/.16(2w 5b(a))},2j:7(a,b){8 6.K(b)||/^\\d{4}[\\/-]\\d{1,2}[\\/-]\\d{1,2}$/.16(a)},1G:7(a,b){8 6.K(b)||/^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)(?:\\.\\d+)?$/.16(a)},1P:7(a,b){8 6.K(b)||/^\\d+$/.16(a)},2f:7(b,e){l(6.K(e))8"1S-1Y";l(/[^0-9-]+/.16(b))8 N;p a=0,d=0,2g=N;b=b.1u(/\\D/g,"");Q(p n=b.F-1;n>=0;n--){p c=b.59(n);p d=58(c,10);l(2g){l((d*=2)>9)d-=9}a+=d;2g=!2g}8(a%10)==0},43:7(b,c,a){a=1g a=="1D"?a.1u(/,/g,\'|\'):"57|56?g|55";8 6.K(c)||b.65(2w 3t(".("+a+")$","i"))},2o:7(c,d,a){p b=$(a).66(".17-2o").2I("3H.17-2o",7(){$(d).J()});8 c==b.33()}}});$.W=$.v.W})(1F);(7($){p c=$.2U;p d={};$.2U=7(a){a=$.H(a,$.H({},$.53,a));p b=a.3X;l(a.3Z=="2Y"){l(d[b]){d[b].2Y()}8(d[b]=c.1Q(6,R))}8 c.1Q(6,R)}})(1F);(7($){l(!1F.1r.38.2d&&!1F.1r.38.2J&&4i.3G){$.P({3g:\'2d\',3H:\'2J\'},7(b,a){$.1r.38[a]={50:7(){6.3G(b,2y,w)},4Z:7(){6.4Y(b,2y,w)},2y:7(e){R[0]=$.1r.2O(e);R[0].1V=a;8 $.1r.1T.1Q(6,R)}};7 2y(e){e=$.1r.2O(e);e.1V=a;8 $.1r.1T.V(6,e)}})};$.H($.2L,{2K:7(d,e,c){8 6.2I(e,7(a){p b=$(a.4X);l(b.2W(d)){8 c.1Q(b,R)}})}})})(1F);',62,389,'||||||this|function|return|||||||||||||if||||var|settings||||name|validator|true|uFDCF|uFFEF||uFDF0|uD7FF|uF900||u00A0|length|messages|extend|element|valid|optional|form|Please|false|enter|each|for|arguments|errorList|delete|currentForm|call|format|_|method|value||in|else|toHide|elements|required|test|validate|maxlength|data|submitted|pendingRequest|errorClass|add|case|invalid|typeof|pending|rules|message|toShow|formSubmitted|showErrors|successList|filter|trim|remote|event|attr|min|replace|errorMap|input|success|minlength|console|date|url|max|string|checkable|jQuery|number|metadata|split|email|unhighlight|not|errorsFor|methods|getLength|digits|apply|classRuleSettings|dependency|handle|da|type|x09|normalizeRule|mismatch|submitButton|undefined|reset|addClass|switch|labelContainer||findByName|push|validClass|check|groups|currentElements|constructor|focusin|select|creditcard|bEven|previousValue|rangelength|dateISO|objectLength|focusInvalid|x20|parameters|equalTo|depends|debug|range|submit|wrapper|defaultMessage|removeClass|new|containers|handler|errors|hide|rulesCache|addWrapper|errorLabelContainer|showLabel|errorElement|clean|prepareForm|bind|focusout|validateDelegate|fn|old|delegate|fix|prepareElement|hideErrors|param|resetForm|window|ajax|characters|is|than|abort|Number|x0d|break|dependTypes|val|idOrName|submitHandler|staticRules|theregex|special|highlight|meta|cancelSubmit|eventType|defaults|click|catch|focus|findLastActive|button|size|ignoreTitle|ignore|defaultShowErrors|grep|errorContainer|selected|numberOfInvalids|error|find|RegExp|triggerHandler|checkForm|invalidHandler|onsubmit|nothing|option|checkbox|Array|radio|remove|text|makeArray|addEventListener|blur|init|autoCreateRanges|no|to|equal|x7f|and|x01|try|x0a|x22|attributeRules|lastActive|classRules|between|port|metadataRules|mode|originalMessage|normalizeRules|x0c|accept|isFunction|x0b|or|the|addClassRules|numberDE|dateDE|stopRequest|startRequest|depend|toLowerCase|nodeName|null|checked|document|errorPlacement|html|generated|map|invalidElements|show|validElements|parent|field|strong|errorContext|findDefined|String|customMessage|parentNode|customMetaMessage|id|lastElement|formatAndAdd|onfocusout|removeAttrs|cancel|assigned|has|disabled|image|blockFocusCleanup|focusCleanup|can|trigger|visible|onfocusin|label|slice|keyup|textarea|file|password|unshift|on|target|removeEventListener|teardown|setup|appendTo|warn|ajaxSettings|valueCache|gif|jpe|png|parseInt|charAt|prototype|Date|NaN|greater|uE000|unchecked|filled|https|x5d|less|x5b|x23|x21|blank|long|expr|x08|hidden|least|at|json|more|dataType|extension|default|with|addMethod|again|524288|x0e|x1f|same|2147483647|class|card|preventDefault|x7e|credit|ftp|boolean|only|getElementsByName|ISO|insertAfter|append|uF8FF|Invalid|wrap|URL|address|defined|No|Warning|This|title|setDefaults|returning|match|unbind|throw|onclick|checking|when|occured|onkeyup|removeAttr|exception|log|continue'.split('|'),0,{}))
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/profile/views/changePwd.php b/0.8.1-rc1/balance/modules/profile/views/changePwd.php
new file mode 100644
index 0000000..04abcbb
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/views/changePwd.php
@@ -0,0 +1,76 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * Profile Manager:
+ * This view allows user to change password
+ */
+$module = App::Get()->loadModule();
+
+?>
+	
+	<div class="breadcrumbs">
+		<a href="<?php echo SITE_ROOT?>/">Home</a>
+	</div>
+    
+    <div class='span-22 append-1 prepend-1 last' id='profile_container'>
+		<h1>Change Password</h1>
+		<div id="submenu">
+			<p>
+				<a href="<?php echo $module->moduleRoot?>/manage"> Manage Profile</a>
+				&nbsp;&nbsp;|&nbsp;&nbsp;
+				<a href="<?php echo $module->moduleRoot?>/changePwd">Change Password</a>
+				&nbsp;&nbsp;|&nbsp;&nbsp;
+				<a href="<?php echo $module->moduleRoot?>/groups">Groups</a>
+			</p>
+		</div>
+		
+		<br class="space"/>
+		
+		<fieldset id='profile_fieldset'>
+		<form id="signupform" autocomplete="off" method="post" action="<?php echo $module->moduleRoot?>/changePwd.do">
+    		<br class="space"/>
+    			
+        	<div class="span-4 prepend-1">
+	    		<label for="password">Choose a password</label>
+	    	</div>
+	    	<div id="form_input" class="span-12">
+	    		<input class="profile_input" id="password" name="password" type="password" maxlength="50" value="" />
+	    	</div>
+	    	
+	    	<br class="space"/>
+	    	
+	    	<div class="span-4 prepend-1">
+	    		<label for="password_confirm">Confirm password</label>
+	    	</div>
+	    	<div id="form_input" class="span-12">
+	    		<input class="profile_input" id="password_confirm" name="password_confirm" type="password" maxlength="50" value="" />
+	    	</div>
+	    	
+	    	<br class="space"/>
+	    	<br class="space"/>
+	    	
+	    	<div class="span-10" align="center">
+	    		<input class="profile_input" id="button_passwdReset" type="submit" value="Submit">
+    		</div>
+    		
+			<br class="space"/>
+    	</form>
+    	</fieldset>
+		
+    </div>
diff --git a/0.8.1-rc1/balance/modules/profile/views/createUser.php b/0.8.1-rc1/balance/modules/profile/views/createUser.php
new file mode 100644
index 0000000..ebace80
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/views/createUser.php
@@ -0,0 +1,184 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * Profile Manager:
+ * This view will allow user to create profile 
+ * 		includes validation
+ * 
+ * This depends on the access granted by underlying directory service
+ */
+$module = App::Get()->loadModule();
+
+?>
+
+<script type="text/javascript">
+
+	$(document).ready(function() {
+		// validate signup form on keyup and submit
+		var validator = $("#signupform").validate({
+		rules: {
+			firstname: "required",
+			lastname: "required",
+			username: {
+				required: true,
+				minlength: 2,
+			},
+			password: {
+				required: true,
+				minlength: 5
+			},
+			password_confirm: {
+				required: true,
+				minlength: 5,
+				equalTo: "#password"
+			},
+			email: {
+				required: true,
+				email: true,
+			}
+		},
+		messages: {
+			firstname: "Enter your firstname",
+			lastname: "Enter your lastname",
+			username: {
+				required: "Enter a username",
+				minlength: jQuery.format("Enter at least {0} characters"),
+			},
+			password: {
+				required: "Provide a password",
+				rangelength: jQuery.format("Enter at least {0} characters")
+			},
+			password_confirm: {
+				required: "Repeat your password",
+				minlength: jQuery.format("Enter at least {0} characters"),
+				equalTo: "Enter the same password as above"
+			},
+			email: {
+				required: "Please enter a valid email address",
+				minlength: "Please enter a valid email address",
+			},
+		},
+		// set this class to error-labels to indicate valid fields
+		success: function(label) {
+			// set &nbsp; as text for IE
+			label.html("&nbsp;").addClass("checked");
+		}
+	});
+	
+	// propose username by combining first- and lastname
+	$("#username").focus(function() {
+		var firstname = $("#firstname").val();
+		var lastname = $("#lastname").val();
+		if(firstname && lastname && !this.value) {
+			this.value = firstname + "." + lastname;
+		}
+	});
+
+});
+</script>
+	
+	<div class="breadcrumbs">
+		<a href="<?php echo SITE_ROOT?>/">Home</a>
+	</div>
+	
+    <div class='span-22 append-1 prepend-1 last' id='profile_container'>
+    	<h1>Obtaining Access</h1>
+
+		<br class="space"/>
+		
+ 		<fieldset id='profile_fieldset'>
+		<form id="signupform" autocomplete="off" method="post" action="<?php echo $module->moduleRoot?>/access.do">
+	    	<br class="space"/>
+
+	    	<div class="span-4 prepend-1">
+	    		<label for="firstname">First Name</label>
+	    	</div>
+	    	<div class="span-15">
+	    		<input class="profile_input" id="firstname" name="firstname" type="text" value="" maxlength="100" />
+	    	</div>
+	    	
+	    	<br class="space"/>
+	    	
+	    	<div class="span-4 prepend-1">
+	    		<label for="lastname">Last Name</label>
+	    	</div>
+	    	<div class="span-15">
+	    		<input class="profile_input" id="lastname" name="lastname" type="text" value="" maxlength="100" />
+	    	</div>
+	    	
+	    	<br class="space"/>
+	    	
+	    	<div class="span-4 prepend-1">
+	    		<label for="username">Desired Login Name</label>
+	    	</div>
+	    	<div class="span-15">
+	    		<input class="profile_input" id="username" name="username" type="text" value="" maxlength="50" />
+	    	</div>
+
+	    	<br class="space"/>
+	    	
+	    	<div class="span-4 prepend-1">
+	    		<label for="email">Email</label>
+	    	</div>
+	    	<div class="span-15">
+	    		<input class="profile_input" id="email" name="email" type="text" value="" maxlength="150" />
+	    	</div>
+	    		
+    		<br class="space"/>
+    		<br class="space"/>
+    		    	
+        	<div class="span-4 prepend-1">
+        		<label for="password">Choose a password</label>
+	    	</div>
+	    	<div class="span-15">
+	    		<input class="profile_input" id="password" name="password" type="password" maxlength="50" value="" />
+	    	</div>
+	    	
+	    	<br class="space"/>
+	    	
+	    	<div class="span-4 prepend-1">
+	    		<label for="password_confirm">Confirm password</label>
+	    	</div>
+	    	<div class="span-15">
+	    		<input class="profile_input" id="password_confirm" name="password_confirm" type="password" maxlength="50" value="" />
+	    	</div>
+	    	
+	    	<br class="space"/>
+	    	<br class="space"/>
+	    	
+	    	<div class="span-10" align="center">
+	    		<input class="profile_input" id="button_new_account" type="submit" value="Submit">
+    		</div>
+
+			<br class="space"/>
+    	</form>
+    	</fieldset>
+    </div>
+
+
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+_uacct = "UA-2623402-1";
+urchinTracker();
+</script>
+    
+
+    
+
diff --git a/0.8.1-rc1/balance/modules/profile/views/groups.php b/0.8.1-rc1/balance/modules/profile/views/groups.php
new file mode 100644
index 0000000..284893e
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/views/groups.php
@@ -0,0 +1,82 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * Profile Manager:
+ * This view will expose the user groups and roles for the user.
+ */
+$module = App::Get()->loadModule();
+
+// Get instance of authentication and authorization class
+$authorization 	= App::Get()->getAuthorizationProvider();
+$authentication = App::Get()->getAuthenticationProvider();
+
+if ( $authorization != false) {
+	$groups = $authorization->retrieveGroupsForUser($authentication->getCurrentUsername(),App::Get()->settings['authorization_ldap_group_dn']);
+}
+
+?>
+	
+	<div class="breadcrumbs">
+		<a href="<?php echo SITE_ROOT?>/">Home</a>
+	</div>
+    
+	<div class='span-22 append-1 prepend-1 last' id='profile_container'>
+		<h1><?php echo $authentication->getCurrentUsername() ?>'s Groups </h1>
+		<div id="submenu">
+			<p>
+				<a href="<?php echo $module->moduleRoot ?>/manage"> Manage Profile</a>
+				&nbsp;&nbsp;|&nbsp;&nbsp;
+				<a href="<?php echo $module->moduleRoot?>/changePwd">Change Password</a>
+				&nbsp;&nbsp;|&nbsp;&nbsp;
+				<a href="<?php echo $module->moduleRoot?>/groups">Groups</a>
+			</p>
+		</div>
+			
+		<br class="space"/>
+
+		<fieldset id='profile_fieldset'>
+		<?php 
+			
+		if (count($groups) > 0) {
+			echo "<div class='span-15 prepend-1'>";
+			foreach ($groups as $g) {
+				List($group, $role) =  explode("_", $g);
+				
+				if( $group != $groupIndex ) {
+					echo "</ul></ul>";
+					echo "<br class='space'>";
+					echo "<h3>{$group}</h3>";
+					echo "<ul><ul>";
+					$groupIndex = $group;
+				}		
+			  	echo "<li>";
+			  	echo $role;
+				echo "</li>";
+				echo "<br class='space'>";
+			}
+			
+			echo "</div>";
+		} else{
+			echo "<h4> No Groups found!</h4>";
+		}
+		?>
+		</fieldset>
+		<br class='space'>
+	</div>
+	
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/profile/views/index.php b/0.8.1-rc1/balance/modules/profile/views/index.php
new file mode 100644
index 0000000..a7b70be
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/views/index.php
@@ -0,0 +1,81 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * Profile Manager:
+ * This view will expose the profile attributes specified in the config.ini (profile_attributes).
+ */
+$module = App::Get()->loadModule();
+
+function displayAttributes($userAttr) {
+
+	$str = '';
+ 	foreach ($userAttr as $key=>$keyValue) {
+ 		foreach (App::Get()->settings['attr_titles'] as $attrTitle=>$value) {
+ 			if ( $key === $value) {
+ 				$str .= '<div class="span-13 prepend-1"><h4 align="left">';
+ 				$str .= $attrTitle;
+ 				$str .= '</h4></div>';
+ 				
+ 				$str .= '<div class="span-5"><h6 align="left">';
+ 				$str .= $keyValue;
+ 				$str .= '</h6></div>';
+ 			}
+ 		}
+ 	}
+ 	return $str;	
+}
+
+	// Get user attributes
+	$userAttr = App::Get()->getAuthenticationProvider()->retrieveUserAttributes( 
+				App::Get()->getAuthenticationProvider()->getCurrentUsername(), App::Get()->settings['profile_attributes'] );
+
+?>
+	
+	<div class="breadcrumbs">
+		<a href="<?php echo SITE_ROOT?>/">Home</a>
+	</div>
+    
+	<div class='span-22 append-1 prepend-1 last' id='profile_container'>
+		<h1>Welcome <?php echo $userAttr[ App::Get()->settings['firstname_attr'] ] ?>! </h1>
+		<div id="submenu">
+			<p>
+				<a href="<?php echo $module->moduleRoot ?>/manage"> Manage Profile</a>
+				&nbsp;&nbsp;|&nbsp;&nbsp;
+				<a href="<?php echo $module->moduleRoot?>/changePwd">Change Password</a>
+				&nbsp;&nbsp;|&nbsp;&nbsp;
+				<a href="<?php echo $module->moduleRoot?>/groups">Groups</a>
+			</p>
+		</div>
+		
+ 		<br class="space"/>
+
+		<h3>Profile</h3>		
+ 		<fieldset id='profile_fieldset'>
+ 			<br class="space"/>
+ 			<br class="space"/>
+			
+			<?php 	echo displayAttributes($userAttr) ?>
+			
+			<br class="space"/>
+		</fieldset>
+		
+    	<br class="space"/>
+    	
+	</div>
+	
diff --git a/0.8.1-rc1/balance/modules/profile/views/login.php b/0.8.1-rc1/balance/modules/profile/views/login.php
new file mode 100644
index 0000000..2df3b2c
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/views/login.php
@@ -0,0 +1,71 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * Profile Manager:
+ * Login page
+ */
+$module = App::Get()->loadModule();
+
+// If a user is already logged in, redirect to home page
+if( App::Get()->getAuthenticationProvider()->isLoggedIn() ) App::Get()->Redirect(SITE_ROOT . "/"); 
+
+?>
+	
+	<div class="breadcrumbs">
+		<a href="<?php echo SITE_ROOT?>/">Home</a>
+	</div>
+    
+	<div class='span-22 append-1 prepend-1 last' id='profile_container'> 
+		<h1>Please log in to continue...</h1>
+		
+		<br class="space"/>
+		
+		<fieldset id='profile_fieldset'>
+		<form id="signupform" autocomplete="off" method="post" action="<?php echo $module->moduleRoot ?>/login.do">
+			<br class="space"/>
+		 	<br class="space"/>
+		 	
+			<div class="span-2 prepend-1">
+				<label for="username">Username</label>
+			</div>
+			<div class="span-15">
+				<input class="profile_input" id="username" name="username" type="text" value="" maxlength="50" />
+			</div>
+			
+			<br class="space"/>
+			
+			<div class="span-2 prepend-1">
+	    		<label for="password">Password</label>
+	    	</div>
+	    	<div class="span-15">
+	    		<input class="profile_input" id="password" name="password" type="password" maxlength="50" value="" />
+	    	</div>
+	    	
+	    	<br class="space"/>
+	    	<br class="space"/>
+	    	
+	    	<div class="span-10" align="center">
+	    		<input class="profile_input" id="button_new_account" type="submit" value="Submit">
+    		</div>
+    		
+    		<br class="space"/>
+    		<br class="space"/>
+		</form>
+		</fieldset>
+	</div>
diff --git a/0.8.1-rc1/balance/modules/profile/views/manage.php b/0.8.1-rc1/balance/modules/profile/views/manage.php
new file mode 100644
index 0000000..62178cf
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/views/manage.php
@@ -0,0 +1,87 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * Profile Manager:
+ * This view will expose the profile attributes specified in the config.ini 
+ * (profile_modify_attributes) and will allow user to modify values in the LDAP directory.
+ */
+$module = App::Get()->loadModule();
+
+function manageAttribute() {
+	$userAttr = App::Get()->getAuthenticationProvider()->retrieveUserAttributes( 
+				App::Get()->getAuthenticationProvider()->getCurrentUsername(), App::Get()->settings['profile_modify_attributes'] );
+	$str = '';
+ 	foreach ($userAttr as $key=>$keyValue) {
+ 		foreach (App::Get()->settings['attr_titles'] as $attrTitle=>$value) {
+ 			if ( $key != App::Get()->settings['username_attr']) {
+
+	 			if ( $key === $value) {
+	 				$str .= '<div class="span-3 prepend-1"><label for="';
+	 				$str .= $key . '"> ' . $attrTitle;
+	 				$str .= '</label></div>';
+	 				
+	 				$str .= '<div class="span-12"><input class="profile_input" type="text" maxlength="100" id=';
+	 				$str .= $key . ' name=' . $key . ' value=' . $keyValue;
+	 				$str .= '></div>';
+	 				$str .= '<br class="space"/>';
+	 			}
+ 			}
+ 		}
+ 	}
+
+ 	return $str;
+}
+?>
+	
+	<div class="breadcrumbs">
+		<a href="<?php echo SITE_ROOT?>/">Home</a>
+	</div>
+    
+    <div class='span-22 append-1 prepend-1 last' id='profile_container'>
+    	<h1>Manage Your Profile</h1>
+		<div id="submenu">
+			<p>
+				<a href="<?php echo $module->moduleRoot?>/manage"> Manage Profile</a>
+				&nbsp;&nbsp;|&nbsp;&nbsp;
+				<a href="<?php echo $module->moduleRoot?>/changePwd">Change Password</a>
+				&nbsp;&nbsp;|&nbsp;&nbsp;
+				<a href="<?php echo $module->moduleRoot?>/groups">Groups</a>
+			</p>
+		</div>
+		
+		<br class="space"/>
+
+		<fieldset id='profile_fieldset'>
+		<form id="signupform" autocomplete="off" method="post" action="<?php echo $module->moduleRoot?>/manage.do">
+	    	<br class="space"/>
+
+			<?php echo manageAttribute()?>
+
+	    	<br class="space"/>
+	    	<br class="space"/>
+	    	
+	    	<div class="span-10" align="center">
+	    		<input class="profile_input" type="submit" value="Submit" name="submit_button">
+    		</div>
+    		
+	    	<br class="space"/>
+    	</form>
+		</fieldset>
+		
+    </div>
diff --git a/0.8.1-rc1/balance/modules/profile/views/passwordChangeConfirmed.php b/0.8.1-rc1/balance/modules/profile/views/passwordChangeConfirmed.php
new file mode 100644
index 0000000..de28203
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/profile/views/passwordChangeConfirmed.php
@@ -0,0 +1,44 @@
+<?php 
+/*
+ * 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.
+ */
+
+/**
+ * Profile Manager:
+ * Display confirmation of password change and allow user to log back in
+ */
+$module = App::Get()->loadModule();
+
+?>
+	
+	<div class="breadcrumbs">
+		<a href="<?php echo SITE_ROOT?>/">Home</a>
+	</div>
+    
+    <div class='span-22 append-1 prepend-1 last' id="profile_container">
+    	<div class="span-24">
+    		<br>
+			<h3>Password has been changed.</h3>
+			<br>
+    	</div>
+		
+		<div class="span-22">
+			<h5><a href="<?php echo $module->moduleRoot?>/login">Please log in with new password.</a></h5>
+		</div>
+		<br class="space"/>
+		
+    </div>
+    
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/README.txt b/0.8.1-rc1/balance/modules/puny/README.txt
new file mode 100644
index 0000000..021c530
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/README.txt
@@ -0,0 +1,115 @@
+Puny - Lightweight content editor for Balance applications
+==========================================================
+
+Puny is a lightweight content editing module for Balance applications. Puny makes
+it easy for developers to add user-editable sections of content to their application
+views and supports real-time, in-place editing of the content.
+
+Overview
+--------
+
+Puny makes it easier to separate content from presentation and separate the 
+role of the site developer and the content manager. As its name implies, it
+provides the bare minimum necessary to accomplish this -- based on the 
+understanding that excellent, full-fledged Content Management System options
+are readily available and more appropriate for content-heavy sites. Puny simply 
+provides a way for sites that are not generally suited to a CMS to nevertheless
+reap the benefits of real-time, in-browser content editing by a user not 
+intimately familiar with HTML.
+
+How it Works
+------------
+
+Developers embed 'containers' in their views, and content editors provide the
+content that get displayed in the containers. Puny loads up the most recent 
+version of the content from the data store, renders it using the specified 
+parser, and places the rendered text into the view container. 
+
+By logging in with the editor credentials, a user can visually see the editable
+'containers' on the application views, and, using a javascript-enabled browser,
+can provide inline, real-time edits, creating a new version of the content.
+
+
+
+### Flexibility ###
+
+Puny has been designed so that it is easy to plug in custom back end data
+stores (MySql, MongoDB, SQLite, etc) and template engines (Markdown, Textile,
+bbcode, etc). If a driver for <insert data store or parser here> doesn't exist, 
+there are two primary extension points: Puny_DataStore (a base class for developing 
+drivers for data stores), and Puny_Parser (a base class for interfacing with text 
+parsers and template engines). Using the examples in the /classes/data and 
+/classes/parsers, it should be relatively easy to develop additional drivers.
+
+
+Installation
+------------
+
+Copy the Puny module (this directory) to the /modules directory of
+your Balance application. 
+
+
+Configuration
+-------------
+
+All configuration for Puny takes place in the module's 'config.ini' file. See
+the inline documentation in 'config.ini' for detailed information about each
+configuration option. 
+
+
+Developer Guide
+---------------
+
+### Including Puny in your application
+
+In general, Puny needs to be available on each application view. To avoid having to load 
+the module at the top of each view, it is possible to include the module once,in the 
+Balance index.php at the root of your application. Simply add the following lines to the 
+'index.php' file where it says 'Initialize any globally required modules here':
+
+// Puny initialization
+App::Get()->loadModule('puny');
+require_once(App::Get()->settings['puny_module_path'] . '/classes/Puny.class.php');
+
+
+### Installing your data store ###
+
+Look in the /schemas folder in the Puny module for a schema compatible with your datastore
+driver. Install the schema using whatever method is most appropriate for the technology. The
+default driver is the PDO driver implemented in ./classes/data/Puny_PdoDataStore.class.php.
+The MySQL schema compatible with this driver is in ./schemas/puny.pdo.mysql.sql. Copy this
+file and import it into the database you configured in the configuration step above.
+
+
+### Including Puny containers in your application views ### 
+
+The easiest way to include Puny containers in your application views is:
+
+<?php echo Puny::container()->load('resourceid');?>
+
+By default, container creates a '<div>' element and loads the content into it. To use
+something other than a '<div>' simply specify the html element to the container() function:
+
+<?php echo Puny::container('span')->load('resourceid');?>
+
+It is also possible to specify arbitrary attributes to attach to your container. Examples 
+include a DOM id, CSS class(es), style attribute, alt, rel, or anything else. This is 
+accomplished by passing an associative array as the second parameter to container() where
+the array keys are the attribute names, and the values are the attribute values. 
+
+<?php echo Puny::container('div',array('id'=>'mydiv','class'=>'foo bar'))->load('resourceid');?>
+
+
+### Allowing editors to log in and edit ###
+
+Somewhere in your application, there should be a login link that allows editors to log in
+and make edits to content. This is easily accomplished by adding the following line wherever
+you want the login link to appear:
+
+<?php echo Puny::status();?>
+
+This will display either a login or logout link, depending on whether or not an editor
+is currently logged in. 
+
+
+That's all there is to it, it lives up to its name.
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/classes/Puny.class.php b/0.8.1-rc1/balance/modules/puny/classes/Puny.class.php
new file mode 100644
index 0000000..67ed6bc
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/classes/Puny.class.php
@@ -0,0 +1,166 @@
+<?php
+/*
+ * 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.
+ */
+
+require_once( dirname(__FILE__) . '/Puny_Container.class.php');
+require_once( dirname(__FILE__) . '/Puny_Resource.class.php');
+
+/**
+ * Puny
+ * 
+ * Light-weight content editing for Balance applications. Puny makes it easy
+ * to add editable sections of content to your application views and supports
+ * real-time, in-place editing.
+ * 
+ * Puny has been designed so that it is easy to plug in custom back end data
+ * stores (MySql, MongoDB, SQLite, etc) and template engines (Markdown, Textile,
+ * bbcode, etc). Use what makes sense for your project, and if what you want
+ * is not yet supported, writing a Puny driver for a datastore or template 
+ * engine is a piece of cake. There are examples of each in the /classes/data and 
+ * /classes/parsers directories.
+ * 
+ * @author ahart
+ */
+
+class Puny {
+	
+	protected static $datastore = null;
+	
+	protected static $commonResourcesLoaded = false;
+
+	protected static $editorResourcesLoaded = false;
+	
+	protected static function init() {
+		
+		// Only if the datastore has not yet been initialized...
+		if (!self::$datastore) {
+			try {
+				// Obtain datastore configuration details
+				$datastoreClass = App::Get()->settings['puny_datastore_classname'];
+				require_once( App::Get()->settings['puny_datastore_classpath'] );
+		
+				// Create an instance of the datastore connector
+				self::$datastore = new $datastoreClass();
+		
+				// Connect to the datastore
+				self::$datastore->connect();
+			} catch ( Exception $e ) {
+				throw new Exception("Error instantiating Puny. "
+				. "The underlying cause was: " . $e->getMessage());
+			}
+		}
+		
+		self::injectCommonResources();
+		self::injectEditorResources();
+	}
+	
+	public static function load( $resourceId, $version = null, $parseContent = true ) {
+
+		self::init();
+		
+		// Load the raw data from the data store...
+		if (false !== ($resource = self::$datastore->load( $resourceId, $version ))) {
+			
+			// If a valid resource was found, return it
+			return ($parseContent) ? $resource->parse() : $resource;
+			
+		} else {
+			
+			// Otherwise, return an empty resource with the requested id
+			return new Puny_Resource( array("resourceId" => $resourceId, "content" => $resourceId) );
+		
+		}
+	}
+	
+	public static function store (Puny_Resource $resource ) {
+		
+		self::init();
+		
+		// Persist the resource to the datastore
+		self::$datastore->store( $resource );
+		
+	}
+	
+	public static function isEditing() {
+		return ( isset($_SESSION['puny']) && $_SESSION['puny']['editing'] === true );
+	}
+	
+	public function initializeEditorSession() {
+		$_SESSION['puny'] = array('editing' => true, 'sessionStart' => time());
+	}
+	
+	public static function destroyEditorSession() {
+		unset($_SESSION['puny']);
+	}
+	
+	public static function status() {
+		if (self::isEditing()) {
+			return "<a href='".App::Get()->settings['puny_module_root']."/logout'>Logout</a>";
+		} else {
+			return "<a href='".App::Get()->settings['puny_module_root']."/login'>Login</a>";
+		}
+	}
+	
+	protected static function injectCommonResources() {
+	  // Inject the environmental information needed for the javascript libraries
+	  // to function as expected...
+	  if ( !self::$commonResourcesLoaded ) {
+	    $js = "\r\n"
+	      . "var puny_module_root   = '" . trim(App::Get()->settings['puny_module_root']) . "'\r\n"
+	      . "    puny_module_static = '" . trim(App::Get()->settings['puny_module_static']) ."'\r\n"
+	      . "    puny_current_url = '" . $_SERVER['HTTP_REFERER'] ."';\r\n";
+	      App::Get()->response->addJavascript( $js, true ); // raw Javascript
+	    
+	    // Add puny default styles
+	    $staticPath = trim(App::Get()->settings['puny_module_static']);
+		App::Get()->response->addStylesheet($staticPath . '/css/defaults.css');
+		App::Get()->response->addJavascript($staticPath . '/js/jquery-1.7.2.min.js');
+		self::$commonResourcesLoaded = true;
+	  }
+	}
+
+	protected static function injectEditorResources() {
+		// Only inject resources if we are editing and they have not already been loaded...
+		$segments = App::Get()->request->uri;
+		$staticPath = trim(App::Get()->settings['puny_module_static']);
+		if ( self::isEditing() && strstr($segments,'edit') != false) {
+			
+			App::Get()->response->addJavascript($staticPath . '/js/gollum.js');
+			App::Get()->response->addJavascript($staticPath . '/js/gollum.dialog.js');
+			App::Get()->response->addJavascript($staticPath . '/js/gollum.placeholder.js');
+			App::Get()->response->addJavascript($staticPath . '/js/editor/gollum.editor.js');
+			
+			App::Get()->response->addStylesheet($staticPath . '/css/github.css');
+			App::Get()->response->addStylesheet($staticPath . '/css/editor.css');
+			App::Get()->response->addStylesheet($staticPath . '/css/dialog.css');
+		}
+		if ( self::isEditing() && !self::$editorResourcesLoaded ) {
+			
+			App::Get()->response->addJavascript($staticPath . '/js/puny.js');
+			App::Get()->response->addStylesheet($staticPath . '/css/puny.css');
+			self::$editorResourcesLoaded = true;
+		}
+	}
+	
+	public static function container( $htmlElmt = 'div' , $extra = array()) {
+		
+		self::init();
+		
+		// Create a new Puny_Container object according to the provided info
+		return new Puny_Container($htmlElmt, $extra);
+	}
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/classes/Puny_Container.class.php b/0.8.1-rc1/balance/modules/puny/classes/Puny_Container.class.php
new file mode 100644
index 0000000..97b786b
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/classes/Puny_Container.class.php
@@ -0,0 +1,85 @@
+<?php
+/*
+ * 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.
+ */
+
+require_once(dirname(__FILE__) . '/Puny.class.php');
+
+/**
+ * Puny_Container
+ * 
+ * This class provides convenience methods for creating an HTML container
+ * around a Puny_Resource. Puny_Container removes the need for developers
+ * to manually annotate HTML with the puny="..." attribute (so that the 
+ * Puny javascript in-place editor functions on the resource).
+ * 
+ * @author ahart
+ */
+class Puny_Container {
+	
+	protected $htmlElement;
+	protected $attributes;
+	
+	/**
+	 * Constructor
+	 * 
+	 * @param string $elmt  The html element to use as a container (e.g.: 'div','span')
+	 * @param array  $attributes (optional) an associative array of attributes to 
+	 *                     attach to the html container element. e.g:
+	 *                     array("id" => 'foo', "class" => "bar baz");
+	 */
+	public function __construct( $elmt = 'div', $attributes = array() ) {
+		
+		$this->htmlElement = $elmt;
+		$this->attributes  = $attributes;
+	}
+	
+	/**
+	 * Load a resource into this container
+	 * 
+	 * This function simply calls the Puny::load function and returns
+	 * wraps the result in the container html
+	 * 
+	 * @param string $resourceId The unique id of the resource to load
+	 * @param int $version (optional) The version to load (default = latest)
+	 * @returns string
+	 */
+	public function load( $resourceId, $version = null ) {
+		return $this->render( Puny::load( $resourceId, $version, false ));
+	}
+	
+	
+	/**
+	 * Helper function for rendering a resource inside this container
+	 * 
+	 * @param unknown_type $resource
+	 * @access protected
+	 */
+	protected function render($resource) {
+		
+		$html = "<{$this->htmlElement}";
+		
+		foreach ($this->attributes as $k => $v) {
+			$html .= " {$k}=\"{$v}\"";
+		}
+		
+		$html .= " puny=\"{$resource->getId()}\">"
+			  .  "{$resource->parse()->getContent()}"
+			  .  "</{$this->htmlElement}>";
+		
+		return $html;
+	}
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/classes/Puny_Resource.class.php b/0.8.1-rc1/balance/modules/puny/classes/Puny_Resource.class.php
new file mode 100644
index 0000000..fe7c568
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/classes/Puny_Resource.class.php
@@ -0,0 +1,163 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * Puny_Resource
+ * 
+ * Represents a piece of content being managed by Puny. 
+ * 
+ * The Puny_Resource class is a wrapper around a piece of editable
+ * content (a resource). The class provides a number of convenience 
+ * functions for interacting with content.
+ * 
+ * @author ahart
+ */
+class Puny_Resource {
+
+	protected $id;						// The unique id for this resource
+	protected $version = 0;				// The version number for this resource
+	protected $content;					// The resource raw content
+	protected $parser  = 'markdown';	// The parser label for this resource
+	protected $parsedContent;			// The resource parsed content
+	
+	/**
+	 * Constructor
+	 * 
+	 * Optionally provide an associative array containing 
+	 * the data to use when initializing this object. 
+	 * 
+	 * @param array $data (optional) data to use when initializing the object
+	 */
+	public function __construct($data = array()) {
+		$this->id      = isset($data['resourceId']) ? $data['resourceId'] : false;
+		$this->version = isset($data['version'])    ? $data['version']    : 0;
+		$this->content = isset($data['content'])    ? $data['content']    : '';
+		$this->parser  = isset($data['parser'])     ? $data['parser']     : 'markdown';
+		$this->parsedContent = isset($data['parsedContent']) ? $data['parsedContent'] : '';
+	}
+	
+	/**
+	 * Get the unique id for this resource
+	 * @returns String
+	 */
+	public function getId() {
+		return $this->id;
+	}
+	
+	/**
+	 * Increment the version number for this resource
+	 * @returns Puny_Resource
+	 */
+	public function incrementVersion() {
+		$this->version += 1;
+		return $this;	// allow method chaining
+	}
+	
+	/**
+	 * Return the version number for this resource
+	 * @returns int
+	 */
+	public function getVersion() {
+		return $this->version;
+	}
+	
+	/**
+	 * Get the parser label for this resource. The parser
+	 * label is a text label which should correspond to 
+	 * one of the entries in the 'parsers' section of the
+	 * Puny module's config.ini file.
+	 */
+	public function getParser() {
+		return $this->parser;
+	}
+	
+	/**
+	 * Set the parser label for this resource. 
+	 * 
+	 * @param string $label The parser label to use
+	 */
+	public function setParser( $label ) {
+		$this->parser = $label;
+		return $this;	// allow method chaining
+	}
+	
+	/**
+	 * Get either the parsed or raw resource content. 
+	 * 
+	 * @param boolean $raw (default=false) return raw content?
+	 * @returns string
+	 */
+	public function getContent( $raw = false ) {
+		return ($raw) ? $this->content : $this->parsedContent;
+	}
+	
+	/**
+	 * set the raw content for this resource.
+	 * @param string $val The raw content for this resource
+	 * @returns Puny_Resource
+	 */
+	public function setContent( $val ) {
+		$this->content = $val;
+		return $this;	// allow method chaining
+	}
+	
+	/**
+	 * Parse the raw contents of this resourse
+	 * 
+	 * This function uses the parser label associated with this
+	 * resource to determine the parser to use, instantiates a
+	 * parser instance, and parses the raw content. The result
+	 * is stored in $this->parsedContent. 
+	 * 
+	 * @throws Exception
+	 * @returns Puny_Resource
+	 */
+	public function parse() {
+		// Determine the parser to use
+		$parserLabel = $this->getParser();
+			
+		// Ensure the appropriate parser has been required
+		$parsers = App::Get()->settings['puny_parser'];
+		if ( !in_array( $parserLabel, array_keys( $parsers ) ) ) {
+			throw new Exception("Error instantiating parser: "
+			. "label '{$parserLabel}' not configured. ");
+		} else {
+			require_once( $parsers[$parserLabel] );
+		}
+		
+		// Load the parser
+		$parserClassName = 'Puny_' . ucfirst($parserLabel) . 'Parser';
+		$parser = new $parserClassName();
+		
+		// Expand Balance constants:
+		// ([SITE_ROOT], [MODULE_ROOT], [MODULE_PATH], [MODULE_STATIC])
+		$content = str_replace('[SITE_ROOT]',SITE_ROOT, stripslashes($this->content));
+		$moduleInfo = App::Get()->loadModule();
+		if ($moduleInfo) {
+			$content = str_replace('[MODULE_ROOT]',$moduleInfo->moduleRoot, $content);
+			$content = str_replace('[MODULE_PATH]',$moduleInfo->modulePath, $content);
+			$content = str_replace('[MODULE_STATIC]',$moduleInfo->moduleStatic, $content);
+		}
+	
+		// Store the parsed contents
+		$this->parsedContent = $parser->parse( $content );
+		
+		// Allow method chaining
+		return $this;
+	}
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/classes/data/Puny_DataStore.class.php b/0.8.1-rc1/balance/modules/puny/classes/data/Puny_DataStore.class.php
new file mode 100644
index 0000000..d850dc6
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/classes/data/Puny_DataStore.class.php
@@ -0,0 +1,69 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * Puny_DataStore
+ * 
+ * Base class for Puny data store implementations
+ * 
+ * @abstract 
+ * 
+ * @author ahart
+ */
+abstract class Puny_DataStore {
+	
+	protected $host;
+	protected $username;
+	protected $password;
+	protected $dbname;
+	
+	protected $link;
+	
+	/**
+	 * Connect to the data store
+	 * 
+	 */	
+	public abstract function connect();
+	
+	/**
+	 * Disconnect from the data store
+	 */
+	public abstract function disconnect();
+	
+	/**
+	 * Request a resource from the data store. Optionally
+	 * specify a particular version of the resource to fetch.
+	 * 
+	 * @param string $resourceId The unique id of the resource
+	 * @param integer $version   (Optional) the version to retrieve. Default = latest.
+	 */
+	public abstract function load( $resourceId, $version = null );
+	
+	/**
+	 * Store a new version of a resource. For simplicity, versions are 
+	 * immutable. That is, every time a resource is stored, its version is
+	 * first incremented and a new record is created. Implemenations should
+	 * take care to automatically increment the version number of the
+	 * resource before persisting to the datastore.
+	 * 
+	 * @param string $resourceId The unique id of the resource
+	 * @param string $content The content to store 
+	 */
+	public abstract function store( Puny_Resource $resource );
+
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/classes/data/Puny_LocalFileDataStore.class.php b/0.8.1-rc1/balance/modules/puny/classes/data/Puny_LocalFileDataStore.class.php
new file mode 100644
index 0000000..df52079
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/classes/data/Puny_LocalFileDataStore.class.php
@@ -0,0 +1,79 @@
+<?php
+/*
+ * 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.
+ */
+
+// Require the abstract parent class definition
+require_once( dirname(__FILE__) . '/Puny_DataStore.class.php');
+
+/**
+ * An implementation of the Puny_DataStore class that persists
+ * content to ascii text files.
+ *
+ * @author ahart
+ */
+class Puny_LocalFileDataStore extends Puny_DataStore {
+
+  protected $dataDirectory;
+
+  public function connect() {
+    $this->dataDirectory = App::Get()->settings['puny_datastore_localfile_dir'];
+
+    // Ensure we can write to the directory
+    if (!is_writeable($this->dataDirectory)) {
+      throw new Exception("Puny can not write to the specified data directory");
+    }
+  }
+
+  public function disconnect() {
+    //noop
+  }
+
+  public function load( $resourceId, $version = null ) {
+
+    // The LocalFile data store does not currently support
+    // the concept of 'versions'. It could, but is the 
+    // added complexity really worth it? This is really 
+    // intended as a development tool, with the assumption
+    // that one of the more full-featured data store
+    // implementations (e.g.: PDO, Mongo) will ultimately
+    // be used. 
+
+    // Build the full path from the resourceId
+    $path = $this->dataDirectory . '/' . $resourceId . ".txt";
+
+    if (file_exists( $path ) ) {
+      $content  = file_get_contents($path);
+      $resource = array(
+			"resourceId" => $resourceId
+			, "content"  => $content
+			);
+      return new Puny_Resource($resource);
+    } else {
+      return false;
+    }
+  }
+
+  public function store ( Puny_Resource $resource ) {
+
+    // Build the full path from the resourceId
+    $path = $this->dataDirectory . '/' . $resource->getId() . ".txt";
+
+    // Store the latest content
+    file_put_contents($path, $resource->getContent(true)); // raw, unparsed content
+
+  }
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/classes/data/Puny_MongoDataStore.class.php b/0.8.1-rc1/balance/modules/puny/classes/data/Puny_MongoDataStore.class.php
new file mode 100644
index 0000000..a5482af
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/classes/data/Puny_MongoDataStore.class.php
@@ -0,0 +1,75 @@
+<?php
+/*
+ * 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.
+ */
+
+// Require the abstract parent class definition
+require_once( dirname(__FILE__) . '/Puny_DataStore.class.php');
+
+/**
+ * A MongoDB implementation of the Puny_DataStore class.
+ *
+ * @author ahart
+ */
+class Puny_MongoDataStore extends Puny_DataStore {
+
+  protected $collection;
+
+  public function connect() {
+    $dbname = App::Get()->settings['puny_datastore_mongo_db'];
+    $coll   = App::Get()->settings['puny_datastore_mongo_collection'];
+    $this->link = new Mongo();
+    $this->dbname = $this->link->selectDB($dbname);
+    $this->collection = $this->dbname->$coll;
+  }
+
+  public function disconnect() {
+    if ($this->link) {
+      $this->link->close();
+    }
+  }
+
+  public function load( $resourceId, $version = null ) {
+    // Build criteria for loading...
+    $criteria = array("resourceId" => $resourceId);
+    
+    // If a version is specified...
+    if ($version !== null) { 
+      $criteria['version'] = $version;
+      $doc = $this->collection->findOne( $criteria );
+    } 
+
+    // Otherwise...
+    else {
+      $cursor = $this->collection->find(array("resourceId" => $resourceId));
+      $cursor->sort(array('version' => -1));
+      $doc = $cursor->getNext();
+    }
+
+    // Return whatever was found...
+    return ($doc) ? new Puny_Resource( $doc ) : false;
+  }
+
+  public function store ( Puny_Resource $resource ) {
+    $doc = array(
+		 "resourceId" => $resource->getId()
+		 , "version"  => time()
+		 , "parser"   => $resource->getParser()
+		 , "content"  => $resource->getContent( true )); // raw, unparsed content
+
+    $this->collection->insert( $doc );
+  }
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/classes/data/Puny_PdoDataStore.class.php b/0.8.1-rc1/balance/modules/puny/classes/data/Puny_PdoDataStore.class.php
new file mode 100644
index 0000000..b630f30
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/classes/data/Puny_PdoDataStore.class.php
@@ -0,0 +1,111 @@
+<?php
+/*
+ * 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.
+ */
+
+// Require the abstract parent class definition
+require_once( dirname(__FILE__) . '/Puny_DataStore.class.php');
+
+
+/**
+ * A PDO implementation of the Puny_DataStore class.
+ * 
+ * @author ahart
+ */
+class Puny_PdoDataStore extends Puny_DataStore {
+	
+	protected $driver      = 'mysql';
+	protected $tablePrefix = 'puny_';
+	
+	/**
+	 * (non-PHPdoc)
+	 * @see Puny_DataStore::connect()
+	 * @throws PDOException
+	 */
+	public function connect() {
+		$this->host = App::Get()->settings['puny_datastore_pdo_host'];
+		$this->username = App::Get()->settings['puny_datastore_pdo_username'];
+		$this->password = App::Get()->settings['puny_datastore_pdo_password'];
+		$this->dbname   = App::Get()->settings['puny_datastore_pdo_dbname'];
+		$this->driver   = App::Get()->settings['puny_datastore_pdo_driver'];
+		$this->tablePrefix = App::Get()->settings['puny_datastore_pdo_tablePrefix'];
+		
+		$dsn = $this->driver . ':host=' . $this->host . ';dbname=' . $this->dbname;
+		$this->link = new PDO( $dsn, $this->username, $this->password );
+	}
+	
+	/**
+	 * (non-PHPdoc)
+	 * @see Puny_DataStore::disconnect()
+	 */
+	public function disconnect() {
+		if ($this->link)
+			$this->link = null;
+	}
+	
+	public function load( $resourceId, $version = null) {
+		
+		// Request the specified resource...
+		$sql  = "SELECT * FROM `{$this->tablePrefix}resource` WHERE `resourceId`=:resourceId ";
+		$data = array('resourceId' => $resourceId); 
+		
+		// If a version is specified, explicitly request that version...
+		if ($version != null) {
+			$sql .= " AND `version`=:version ";
+			$data['version'] = $version;
+		} 
+		
+		// Otherwise, simply get the latest version...
+		else {
+			$sql .= " ORDER BY `version` DESC ";
+		}
+		
+		// Limit our results to at most one result...
+		$sql .= " LIMIT 1 ";
+		
+		// Prepare and execute the query using the provided data...
+		$stmt = $this->link->prepare( $sql );
+		$stmt->execute( $data );
+
+		// Return the single result, or return false if no match...
+		if (false != ($resource = $stmt->fetch())) {
+			return new Puny_Resource($resource);
+		} else {
+			return false;
+		}
+	}
+	
+	public function store( Puny_Resource $resource ) {
+		
+		// Increment the resource version id... (see note in Puny_DataStore.class.php)
+		$resource->incrementVersion();
+		
+		// Create sql for storing this new resource version...
+		$sql = "INSERT INTO `{$this->tablePrefix}resource` (`resourceId`,`version`,`parser`,`content`) "
+			.  "VALUES (:resourceId, :version, :parser, :content) ";
+		
+		// Prepare and execute the statement using the provided data
+		$stmt = $this->link->prepare($sql);
+		$stmt->execute ( array (
+			'resourceId' => $resource->getId()
+			, 'version'  => $resource->getVersion()
+			, 'parser'   => $resource->getParser()
+			, 'content'  => $resource->getContent(true) // raw, unparsed content
+		));
+		
+	}
+	
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/classes/parsers/Puny_MarkdownParser.class.php b/0.8.1-rc1/balance/modules/puny/classes/parsers/Puny_MarkdownParser.class.php
new file mode 100644
index 0000000..4277d04
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/classes/parsers/Puny_MarkdownParser.class.php
@@ -0,0 +1,36 @@
+<?php
+/*
+ * 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.
+ */
+
+// Require the markdown php library (https://github.com/michelf/php-markdown/)
+require_once( App::Get()->settings['puny_module_path'] . '/libs/markdown.php');
+
+/**
+ * Markdown implementation of the Puny_Parser class
+ * 
+ * @author ahart
+ */
+
+class  Puny_MarkdownParser {
+	
+	public function parse ( $content ) {
+		
+		return Markdown( $content );
+		
+	}
+	
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/classes/parsers/Puny_Parser.class.php b/0.8.1-rc1/balance/modules/puny/classes/parsers/Puny_Parser.class.php
new file mode 100644
index 0000000..5701ff9
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/classes/parsers/Puny_Parser.class.php
@@ -0,0 +1,40 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * Puny_Parser
+ * 
+ * Base class for Puny parser implementations. 
+ * 
+ * @abstract
+ * 
+ * @author ahart
+ */
+abstract class Puny_Parser {
+	
+	/**
+	 * Implementations of this function should return the 
+	 * final (display-ready) version of the provided content.
+	 * 
+	 * @param string $content The content to parse
+	 * @returns string
+	 * @abstract
+	 */
+	public abstract function parse( $content );
+	
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/config.ini b/0.8.1-rc1/balance/modules/puny/config.ini
new file mode 100644
index 0000000..ed3b334
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/config.ini
@@ -0,0 +1,75 @@
+ # 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.
+
+#
+# Puny - Lightweight content editor for Balance applications
+#
+# ------------------------------------------------------------------------
+#
+
+[ADMINISTRATION CONFIGURATION]
+#
+# Editor login credentials
+# -------------------------------------
+# The editor is the user authorized to make content changes to the site
+#
+puny_editor_username = ''
+puny_editor_password = ''
+
+
+[DATASTORE CONFIGURATION]
+#
+# Which class will provide connection to the data store?
+puny_datastore_classname = Puny_LocalFileDataStore;
+
+# Where is this class in the filesystem?
+puny_datastore_classpath = [MODULE_PATH]/classes/data/Puny_LocalFileDataStore.class.php; 
+
+# Connection parameters specific to the Puny_LocalFileDataStore connector
+puny_datastore_localfile_dir   = '[MODULE_PATH]/data/resources';
+
+# Connection parameters specific to the Puny_PdoDataStore connector
+puny_datastore_pdo_host = 'localhost';
+puny_datastore_pdo_username    = '';
+puny_datastore_pdo_password    = '';
+puny_datastore_pdo_dbname      = '';
+puny_datastore_pdo_driver      = 'mysql';
+puny_datastore_pdo_tablePrefix = 'puny_';
+
+# Connection parameters specific to the Puny_MongoDataStore connector
+puny_datastore_mongo_db         = '';
+puny_datastore_mongo_collection = '';
+
+[PARSER CONFIGURATION]
+#
+# Puny supports an unlimited number of parsers. The only requirement is that
+# there be a driver that conforms to ./classes/parsers/Puny_Parser.class.php.
+# 
+# This array provides a mapping between parser labels and the corresponding
+# parser class that will do the work.
+#
+puny_parser[ 'markdown' ] = [MODULE_PATH]/classes/parsers/Puny_MarkdownParser.class.php
+
+
+
+[INTERNAL ROUTING]
+#
+# These variables are here to provide location independence (so that you can 
+# install Puny in ./modules/puny or ./modules/somethingelse without having 
+# to change any code. You should never have to edit these.
+#
+puny_module_path   = [MODULE_PATH]
+puny_module_root   = [MODULE_ROOT]
+puny_module_static = [MODULE_STATIC] 
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/hooks.php b/0.8.1-rc1/balance/modules/puny/hooks.php
new file mode 100644
index 0000000..e723f31
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/hooks.php
@@ -0,0 +1,17 @@
+<?php
+/*
+ * 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.
+ */
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/libs/markdown.php b/0.8.1-rc1/balance/modules/puny/libs/markdown.php
new file mode 100644
index 0000000..4fe0caa
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/libs/markdown.php
@@ -0,0 +1,2949 @@
+<?php
+/*
+ * 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.
+ */
+
+#
+# Markdown Extra  -  A text-to-HTML conversion tool for web writers
+#
+# PHP Markdown & Extra
+# Copyright (c) 2004-2012 Michel Fortin  
+# <http://michelf.com/projects/php-markdown/>
+#
+# Original Markdown
+# Copyright (c) 2004-2006 John Gruber  
+# <http://daringfireball.net/projects/markdown/>
+#
+
+
+define( 'MARKDOWN_VERSION',  "1.0.1o" ); # Sun 8 Jan 2012
+define( 'MARKDOWNEXTRA_VERSION',  "1.2.5" ); # Sun 8 Jan 2012
+
+
+#
+# Global default settings:
+#
+
+# Change to ">" for HTML output
+@define( 'MARKDOWN_EMPTY_ELEMENT_SUFFIX',  " />");
+
+# Define the width of a tab for code blocks.
+@define( 'MARKDOWN_TAB_WIDTH',     4 );
+
+# Optional title attribute for footnote links and backlinks.
+@define( 'MARKDOWN_FN_LINK_TITLE',         "" );
+@define( 'MARKDOWN_FN_BACKLINK_TITLE',     "" );
+
+# Optional class attribute for footnote links and backlinks.
+@define( 'MARKDOWN_FN_LINK_CLASS',         "" );
+@define( 'MARKDOWN_FN_BACKLINK_CLASS',     "" );
+
+
+#
+# WordPress settings:
+#
+
+# Change to false to remove Markdown from posts and/or comments.
+@define( 'MARKDOWN_WP_POSTS',      true );
+@define( 'MARKDOWN_WP_COMMENTS',   true );
+
+
+
+### Standard Function Interface ###
+
+@define( 'MARKDOWN_PARSER_CLASS',  'MarkdownExtra_Parser' );
+
+function Markdown($text) {
+#
+# Initialize the parser and return the result of its transform method.
+#
+	# Setup static parser variable.
+	static $parser;
+	if (!isset($parser)) {
+		$parser_class = MARKDOWN_PARSER_CLASS;
+		$parser = new $parser_class;
+	}
+
+	# Transform text using parser.
+	return $parser->transform($text);
+}
+
+
+### WordPress Plugin Interface ###
+
+/*
+Plugin Name: Markdown Extra
+Plugin URI: http://michelf.com/projects/php-markdown/
+Description: <a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://michelf.com/projects/php-markdown/">More...</a>
+Version: 1.2.5
+Author: Michel Fortin
+Author URI: http://michelf.com/
+*/
+
+if (isset($wp_version)) {
+	# More details about how it works here:
+	# <http://michelf.com/weblog/2005/wordpress-text-flow-vs-markdown/>
+	
+	# Post content and excerpts
+	# - Remove WordPress paragraph generator.
+	# - Run Markdown on excerpt, then remove all tags.
+	# - Add paragraph tag around the excerpt, but remove it for the excerpt rss.
+	if (MARKDOWN_WP_POSTS) {
+		remove_filter('the_content',     'wpautop');
+        remove_filter('the_content_rss', 'wpautop');
+		remove_filter('the_excerpt',     'wpautop');
+		add_filter('the_content',     'mdwp_MarkdownPost', 6);
+        add_filter('the_content_rss', 'mdwp_MarkdownPost', 6);
+		add_filter('get_the_excerpt', 'mdwp_MarkdownPost', 6);
+		add_filter('get_the_excerpt', 'trim', 7);
+		add_filter('the_excerpt',     'mdwp_add_p');
+		add_filter('the_excerpt_rss', 'mdwp_strip_p');
+		
+		remove_filter('content_save_pre',  'balanceTags', 50);
+		remove_filter('excerpt_save_pre',  'balanceTags', 50);
+		add_filter('the_content',  	  'balanceTags', 50);
+		add_filter('get_the_excerpt', 'balanceTags', 9);
+	}
+	
+	# Add a footnote id prefix to posts when inside a loop.
+	function mdwp_MarkdownPost($text) {
+		static $parser;
+		if (!$parser) {
+			$parser_class = MARKDOWN_PARSER_CLASS;
+			$parser = new $parser_class;
+		}
+		if (is_single() || is_page() || is_feed()) {
+			$parser->fn_id_prefix = "";
+		} else {
+			$parser->fn_id_prefix = get_the_ID() . ".";
+		}
+		return $parser->transform($text);
+	}
+	
+	# Comments
+	# - Remove WordPress paragraph generator.
+	# - Remove WordPress auto-link generator.
+	# - Scramble important tags before passing them to the kses filter.
+	# - Run Markdown on excerpt then remove paragraph tags.
+	if (MARKDOWN_WP_COMMENTS) {
+		remove_filter('comment_text', 'wpautop', 30);
+		remove_filter('comment_text', 'make_clickable');
+		add_filter('pre_comment_content', 'Markdown', 6);
+		add_filter('pre_comment_content', 'mdwp_hide_tags', 8);
+		add_filter('pre_comment_content', 'mdwp_show_tags', 12);
+		add_filter('get_comment_text',    'Markdown', 6);
+		add_filter('get_comment_excerpt', 'Markdown', 6);
+		add_filter('get_comment_excerpt', 'mdwp_strip_p', 7);
+	
+		global $mdwp_hidden_tags, $mdwp_placeholders;
+		$mdwp_hidden_tags = explode(' ',
+			'<p> </p> <pre> </pre> <ol> </ol> <ul> </ul> <li> </li>');
+		$mdwp_placeholders = explode(' ', str_rot13(
+			'pEj07ZbbBZ U1kqgh4w4p pre2zmeN6K QTi31t9pre ol0MP1jzJR '.
+			'ML5IjmbRol ulANi1NsGY J7zRLJqPul liA8ctl16T K9nhooUHli'));
+	}
+	
+	function mdwp_add_p($text) {
+		if (!preg_match('{^$|^<(p|ul|ol|dl|pre|blockquote)>}i', $text)) {
+			$text = '<p>'.$text.'</p>';
+			$text = preg_replace('{\n{2,}}', "</p>\n\n<p>", $text);
+		}
+		return $text;
+	}
+	
+	function mdwp_strip_p($t) { return preg_replace('{</?p>}i', '', $t); }
+
+	function mdwp_hide_tags($text) {
+		global $mdwp_hidden_tags, $mdwp_placeholders;
+		return str_replace($mdwp_hidden_tags, $mdwp_placeholders, $text);
+	}
+	function mdwp_show_tags($text) {
+		global $mdwp_hidden_tags, $mdwp_placeholders;
+		return str_replace($mdwp_placeholders, $mdwp_hidden_tags, $text);
+	}
+}
+
+
+### bBlog Plugin Info ###
+
+function identify_modifier_markdown() {
+	return array(
+		'name' => 'markdown',
+		'type' => 'modifier',
+		'nicename' => 'PHP Markdown Extra',
+		'description' => 'A text-to-HTML conversion tool for web writers',
+		'authors' => 'Michel Fortin and John Gruber',
+		'licence' => 'GPL',
+		'version' => MARKDOWNEXTRA_VERSION,
+		'help' => '<a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://michelf.com/projects/php-markdown/">More...</a>',
+		);
+}
+
+
+### Smarty Modifier Interface ###
+
+function smarty_modifier_markdown($text) {
+	return Markdown($text);
+}
+
+
+### Textile Compatibility Mode ###
+
+# Rename this file to "classTextile.php" and it can replace Textile everywhere.
+
+if (strcasecmp(substr(__FILE__, -16), "classTextile.php") == 0) {
+	# Try to include PHP SmartyPants. Should be in the same directory.
+	@include_once 'smartypants.php';
+	# Fake Textile class. It calls Markdown instead.
+	class Textile {
+		function TextileThis($text, $lite='', $encode='') {
+			if ($lite == '' && $encode == '')    $text = Markdown($text);
+			if (function_exists('SmartyPants'))  $text = SmartyPants($text);
+			return $text;
+		}
+		# Fake restricted version: restrictions are not supported for now.
+		function TextileRestricted($text, $lite='', $noimage='') {
+			return $this->TextileThis($text, $lite);
+		}
+		# Workaround to ensure compatibility with TextPattern 4.0.3.
+		function blockLite($text) { return $text; }
+	}
+}
+
+
+
+#
+# Markdown Parser Class
+#
+
+class Markdown_Parser {
+
+	# Regex to match balanced [brackets].
+	# Needed to insert a maximum bracked depth while converting to PHP.
+	var $nested_brackets_depth = 6;
+	var $nested_brackets_re;
+	
+	var $nested_url_parenthesis_depth = 4;
+	var $nested_url_parenthesis_re;
+
+	# Table of hash values for escaped characters:
+	var $escape_chars = '\`*_{}[]()>#+-.!';
+	var $escape_chars_re;
+
+	# Change to ">" for HTML output.
+	var $empty_element_suffix = MARKDOWN_EMPTY_ELEMENT_SUFFIX;
+	var $tab_width = MARKDOWN_TAB_WIDTH;
+	
+	# Change to `true` to disallow markup or entities.
+	var $no_markup = false;
+	var $no_entities = false;
+	
+	# Predefined urls and titles for reference links and images.
+	var $predef_urls = array();
+	var $predef_titles = array();
+
+
+	function Markdown_Parser() {
+	#
+	# Constructor function. Initialize appropriate member variables.
+	#
+		$this->_initDetab();
+		$this->prepareItalicsAndBold();
+	
+		$this->nested_brackets_re = 
+			str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
+			str_repeat('\])*', $this->nested_brackets_depth);
+	
+		$this->nested_url_parenthesis_re = 
+			str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
+			str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
+		
+		$this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
+		
+		# Sort document, block, and span gamut in ascendent priority order.
+		asort($this->document_gamut);
+		asort($this->block_gamut);
+		asort($this->span_gamut);
+	}
+
+
+	# Internal hashes used during transformation.
+	var $urls = array();
+	var $titles = array();
+	var $html_hashes = array();
+	
+	# Status flag to avoid invalid nesting.
+	var $in_anchor = false;
+	
+	
+	function setup() {
+	#
+	# Called before the transformation process starts to setup parser 
+	# states.
+	#
+		# Clear global hashes.
+		$this->urls = $this->predef_urls;
+		$this->titles = $this->predef_titles;
+		$this->html_hashes = array();
+		
+		$in_anchor = false;
+	}
+	
+	function teardown() {
+	#
+	# Called after the transformation process to clear any variable 
+	# which may be taking up memory unnecessarly.
+	#
+		$this->urls = array();
+		$this->titles = array();
+		$this->html_hashes = array();
+	}
+
+
+	function transform($text) {
+	#
+	# Main function. Performs some preprocessing on the input text
+	# and pass it through the document gamut.
+	#
+		$this->setup();
+	
+		# Remove UTF-8 BOM and marker character in input, if present.
+		$text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
+
+		# Standardize line endings:
+		#   DOS to Unix and Mac to Unix
+		$text = preg_replace('{\r\n?}', "\n", $text);
+
+		# Make sure $text ends with a couple of newlines:
+		$text .= "\n\n";
+
+		# Convert all tabs to spaces.
+		$text = $this->detab($text);
+
+		# Turn block-level HTML blocks into hash entries
+		$text = $this->hashHTMLBlocks($text);
+
+		# Strip any lines consisting only of spaces and tabs.
+		# This makes subsequent regexen easier to write, because we can
+		# match consecutive blank lines with /\n+/ instead of something
+		# contorted like /[ ]*\n+/ .
+		$text = preg_replace('/^[ ]+$/m', '', $text);
+
+		# Run document gamut methods.
+		foreach ($this->document_gamut as $method => $priority) {
+			$text = $this->$method($text);
+		}
+		
+		$this->teardown();
+
+		return $text . "\n";
+	}
+	
+	var $document_gamut = array(
+		# Strip link definitions, store in hashes.
+		"stripLinkDefinitions" => 20,
+		
+		"runBasicBlockGamut"   => 30,
+		);
+
+
+	function stripLinkDefinitions($text) {
+	#
+	# Strips link definitions from text, stores the URLs and titles in
+	# hash references.
+	#
+		$less_than_tab = $this->tab_width - 1;
+
+		# Link defs are in the form: ^[id]: url "optional title"
+		$text = preg_replace_callback('{
+							^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?:	# id = $1
+							  [ ]*
+							  \n?				# maybe *one* newline
+							  [ ]*
+							(?:
+							  <(.+?)>			# url = $2
+							|
+							  (\S+?)			# url = $3
+							)
+							  [ ]*
+							  \n?				# maybe one newline
+							  [ ]*
+							(?:
+								(?<=\s)			# lookbehind for whitespace
+								["(]
+								(.*?)			# title = $4
+								[")]
+								[ ]*
+							)?	# title is optional
+							(?:\n+|\Z)
+			}xm',
+			array(&$this, '_stripLinkDefinitions_callback'),
+			$text);
+		return $text;
+	}
+	function _stripLinkDefinitions_callback($matches) {
+		$link_id = strtolower($matches[1]);
+		$url = $matches[2] == '' ? $matches[3] : $matches[2];
+		$this->urls[$link_id] = $url;
+		$this->titles[$link_id] =& $matches[4];
+		return ''; # String that will replace the block
+	}
+
+
+	function hashHTMLBlocks($text) {
+		if ($this->no_markup)  return $text;
+
+		$less_than_tab = $this->tab_width - 1;
+
+		# Hashify HTML blocks:
+		# We only want to do this for block-level HTML tags, such as headers,
+		# lists, and tables. That's because we still want to wrap <p>s around
+		# "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+		# phrase emphasis, and spans. The list of tags we're looking for is
+		# hard-coded:
+		#
+		# *  List "a" is made of tags which can be both inline or block-level.
+		#    These will be treated block-level when the start tag is alone on 
+		#    its line, otherwise they're not matched here and will be taken as 
+		#    inline later.
+		# *  List "b" is made of tags which are always block-level;
+		#
+		$block_tags_a_re = 'ins|del';
+		$block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
+						   'script|noscript|form|fieldset|iframe|math';
+
+		# Regular expression for the content of a block tag.
+		$nested_tags_level = 4;
+		$attr = '
+			(?>				# optional tag attributes
+			  \s			# starts with whitespace
+			  (?>
+				[^>"/]+		# text outside quotes
+			  |
+				/+(?!>)		# slash not followed by ">"
+			  |
+				"[^"]*"		# text inside double quotes (tolerate ">")
+			  |
+				\'[^\']*\'	# text inside single quotes (tolerate ">")
+			  )*
+			)?	
+			';
+		$content =
+			str_repeat('
+				(?>
+				  [^<]+			# content without tag
+				|
+				  <\2			# nested opening tag
+					'.$attr.'	# attributes
+					(?>
+					  />
+					|
+					  >', $nested_tags_level).	# end of opening tag
+					  '.*?'.					# last level nested tag content
+			str_repeat('
+					  </\2\s*>	# closing nested tag
+					)
+				  |				
+					<(?!/\2\s*>	# other tags with a different name
+				  )
+				)*',
+				$nested_tags_level);
+		$content2 = str_replace('\2', '\3', $content);
+
+		# First, look for nested blocks, e.g.:
+		# 	<div>
+		# 		<div>
+		# 		tags for inner block must be indented.
+		# 		</div>
+		# 	</div>
+		#
+		# The outermost tags must start at the left margin for this to match, and
+		# the inner nested divs must be indented.
+		# We need to do this before the next, more liberal match, because the next
+		# match will start at the first `<div>` and stop at the first `</div>`.
+		$text = preg_replace_callback('{(?>
+			(?>
+				(?<=\n\n)		# Starting after a blank line
+				|				# or
+				\A\n?			# the beginning of the doc
+			)
+			(						# save in $1
+
+			  # Match from `\n<tag>` to `</tag>\n`, handling nested tags 
+			  # in between.
+					
+						[ ]{0,'.$less_than_tab.'}
+						<('.$block_tags_b_re.')# start tag = $2
+						'.$attr.'>			# attributes followed by > and \n
+						'.$content.'		# content, support nesting
+						</\2>				# the matching end tag
+						[ ]*				# trailing spaces/tabs
+						(?=\n+|\Z)	# followed by a newline or end of document
+
+			| # Special version for tags of group a.
+
+						[ ]{0,'.$less_than_tab.'}
+						<('.$block_tags_a_re.')# start tag = $3
+						'.$attr.'>[ ]*\n	# attributes followed by >
+						'.$content2.'		# content, support nesting
+						</\3>				# the matching end tag
+						[ ]*				# trailing spaces/tabs
+						(?=\n+|\Z)	# followed by a newline or end of document
+					
+			| # Special case just for <hr />. It was easier to make a special 
+			  # case than to make the other regex more complicated.
+			
+						[ ]{0,'.$less_than_tab.'}
+						<(hr)				# start tag = $2
+						'.$attr.'			# attributes
+						/?>					# the matching end tag
+						[ ]*
+						(?=\n{2,}|\Z)		# followed by a blank line or end of document
+			
+			| # Special case for standalone HTML comments:
+			
+					[ ]{0,'.$less_than_tab.'}
+					(?s:
+						<!-- .*? -->
+					)
+					[ ]*
+					(?=\n{2,}|\Z)		# followed by a blank line or end of document
+			
+			| # PHP and ASP-style processor instructions (<? and <%)
+			
+					[ ]{0,'.$less_than_tab.'}
+					(?s:
+						<([?%])			# $2
+						.*?
+						\2>
+					)
+					[ ]*
+					(?=\n{2,}|\Z)		# followed by a blank line or end of document
+					
+			)
+			)}Sxmi',
+			array(&$this, '_hashHTMLBlocks_callback'),
+			$text);
+
+		return $text;
+	}
+	function _hashHTMLBlocks_callback($matches) {
+		$text = $matches[1];
+		$key  = $this->hashBlock($text);
+		return "\n\n$key\n\n";
+	}
+	
+	
+	function hashPart($text, $boundary = 'X') {
+	#
+	# Called whenever a tag must be hashed when a function insert an atomic 
+	# element in the text stream. Passing $text to through this function gives
+	# a unique text-token which will be reverted back when calling unhash.
+	#
+	# The $boundary argument specify what character should be used to surround
+	# the token. By convension, "B" is used for block elements that needs not
+	# to be wrapped into paragraph tags at the end, ":" is used for elements
+	# that are word separators and "X" is used in the general case.
+	#
+		# Swap back any tag hash found in $text so we do not have to `unhash`
+		# multiple times at the end.
+		$text = $this->unhash($text);
+		
+		# Then hash the block.
+		static $i = 0;
+		$key = "$boundary\x1A" . ++$i . $boundary;
+		$this->html_hashes[$key] = $text;
+		return $key; # String that will replace the tag.
+	}
+
+
+	function hashBlock($text) {
+	#
+	# Shortcut function for hashPart with block-level boundaries.
+	#
+		return $this->hashPart($text, 'B');
+	}
+
+
+	var $block_gamut = array(
+	#
+	# These are all the transformations that form block-level
+	# tags like paragraphs, headers, and list items.
+	#
+		"doHeaders"         => 10,
+		"doHorizontalRules" => 20,
+		
+		"doLists"           => 40,
+		"doCodeBlocks"      => 50,
+		"doBlockQuotes"     => 60,
+		);
+
+	function runBlockGamut($text) {
+	#
+	# Run block gamut tranformations.
+	#
+		# We need to escape raw HTML in Markdown source before doing anything 
+		# else. This need to be done for each block, and not only at the 
+		# begining in the Markdown function since hashed blocks can be part of
+		# list items and could have been indented. Indented blocks would have 
+		# been seen as a code block in a previous pass of hashHTMLBlocks.
+		$text = $this->hashHTMLBlocks($text);
+		
+		return $this->runBasicBlockGamut($text);
+	}
+	
+	function runBasicBlockGamut($text) {
+	#
+	# Run block gamut tranformations, without hashing HTML blocks. This is 
+	# useful when HTML blocks are known to be already hashed, like in the first
+	# whole-document pass.
+	#
+		foreach ($this->block_gamut as $method => $priority) {
+			$text = $this->$method($text);
+		}
+		
+		# Finally form paragraph and restore hashed blocks.
+		$text = $this->formParagraphs($text);
+
+		return $text;
+	}
+	
+	
+	function doHorizontalRules($text) {
+		# Do Horizontal Rules:
+		return preg_replace(
+			'{
+				^[ ]{0,3}	# Leading space
+				([-*_])		# $1: First marker
+				(?>			# Repeated marker group
+					[ ]{0,2}	# Zero, one, or two spaces.
+					\1			# Marker character
+				){2,}		# Group repeated at least twice
+				[ ]*		# Tailing spaces
+				$			# End of line.
+			}mx',
+			"\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n", 
+			$text);
+	}
+
+
+	var $span_gamut = array(
+	#
+	# These are all the transformations that occur *within* block-level
+	# tags like paragraphs, headers, and list items.
+	#
+		# Process character escapes, code spans, and inline HTML
+		# in one shot.
+		"parseSpan"           => -30,
+
+		# Process anchor and image tags. Images must come first,
+		# because ![foo][f] looks like an anchor.
+		"doImages"            =>  10,
+		"doAnchors"           =>  20,
+		
+		# Make links out of things like `<http://example.com/>`
+		# Must come after doAnchors, because you can use < and >
+		# delimiters in inline links like [this](<url>).
+		"doAutoLinks"         =>  30,
+		"encodeAmpsAndAngles" =>  40,
+
+		"doItalicsAndBold"    =>  50,
+		"doHardBreaks"        =>  60,
+		);
+
+	function runSpanGamut($text) {
+	#
+	# Run span gamut tranformations.
+	#
+		foreach ($this->span_gamut as $method => $priority) {
+			$text = $this->$method($text);
+		}
+
+		return $text;
+	}
+	
+	
+	function doHardBreaks($text) {
+		# Do hard breaks:
+		return preg_replace_callback('/ {2,}\n/', 
+			array(&$this, '_doHardBreaks_callback'), $text);
+	}
+	function _doHardBreaks_callback($matches) {
+		return $this->hashPart("<br$this->empty_element_suffix\n");
+	}
+
+
+	function doAnchors($text) {
+	#
+	# Turn Markdown link shortcuts into XHTML <a> tags.
+	#
+		if ($this->in_anchor) return $text;
+		$this->in_anchor = true;
+		
+		#
+		# First, handle reference-style links: [link text] [id]
+		#
+		$text = preg_replace_callback('{
+			(					# wrap whole match in $1
+			  \[
+				('.$this->nested_brackets_re.')	# link text = $2
+			  \]
+
+			  [ ]?				# one optional space
+			  (?:\n[ ]*)?		# one optional newline followed by spaces
+
+			  \[
+				(.*?)		# id = $3
+			  \]
+			)
+			}xs',
+			array(&$this, '_doAnchors_reference_callback'), $text);
+
+		#
+		# Next, inline-style links: [link text](url "optional title")
+		#
+		$text = preg_replace_callback('{
+			(				# wrap whole match in $1
+			  \[
+				('.$this->nested_brackets_re.')	# link text = $2
+			  \]
+			  \(			# literal paren
+				[ \n]*
+				(?:
+					<(.+?)>	# href = $3
+				|
+					('.$this->nested_url_parenthesis_re.')	# href = $4
+				)
+				[ \n]*
+				(			# $5
+				  ([\'"])	# quote char = $6
+				  (.*?)		# Title = $7
+				  \6		# matching quote
+				  [ \n]*	# ignore any spaces/tabs between closing quote and )
+				)?			# title is optional
+			  \)
+			)
+			}xs',
+			array(&$this, '_doAnchors_inline_callback'), $text);
+
+		#
+		# Last, handle reference-style shortcuts: [link text]
+		# These must come last in case you've also got [link text][1]
+		# or [link text](/foo)
+		#
+		$text = preg_replace_callback('{
+			(					# wrap whole match in $1
+			  \[
+				([^\[\]]+)		# link text = $2; can\'t contain [ or ]
+			  \]
+			)
+			}xs',
+			array(&$this, '_doAnchors_reference_callback'), $text);
+
+		$this->in_anchor = false;
+		return $text;
+	}
+	function _doAnchors_reference_callback($matches) {
+		$whole_match =  $matches[1];
+		$link_text   =  $matches[2];
+		$link_id     =& $matches[3];
+
+		if ($link_id == "") {
+			# for shortcut links like [this][] or [this].
+			$link_id = $link_text;
+		}
+		
+		# lower-case and turn embedded newlines into spaces
+		$link_id = strtolower($link_id);
+		$link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
+
+		if (isset($this->urls[$link_id])) {
+			$url = $this->urls[$link_id];
+			$url = $this->encodeAttribute($url);
+			
+			$result = "<a href=\"$url\"";
+			if ( isset( $this->titles[$link_id] ) ) {
+				$title = $this->titles[$link_id];
+				$title = $this->encodeAttribute($title);
+				$result .=  " title=\"$title\"";
+			}
+		
+			$link_text = $this->runSpanGamut($link_text);
+			$result .= ">$link_text</a>";
+			$result = $this->hashPart($result);
+		}
+		else {
+			$result = $whole_match;
+		}
+		return $result;
+	}
+	function _doAnchors_inline_callback($matches) {
+		$whole_match	=  $matches[1];
+		$link_text		=  $this->runSpanGamut($matches[2]);
+		$url			=  $matches[3] == '' ? $matches[4] : $matches[3];
+		$title			=& $matches[7];
+
+		$url = $this->encodeAttribute($url);
+
+		$result = "<a href=\"$url\"";
+		if (isset($title)) {
+			$title = $this->encodeAttribute($title);
+			$result .=  " title=\"$title\"";
+		}
+		
+		$link_text = $this->runSpanGamut($link_text);
+		$result .= ">$link_text</a>";
+
+		return $this->hashPart($result);
+	}
+
+
+	function doImages($text) {
+	#
+	# Turn Markdown image shortcuts into <img> tags.
+	#
+		#
+		# First, handle reference-style labeled images: ![alt text][id]
+		#
+		$text = preg_replace_callback('{
+			(				# wrap whole match in $1
+			  !\[
+				('.$this->nested_brackets_re.')		# alt text = $2
+			  \]
+
+			  [ ]?				# one optional space
+			  (?:\n[ ]*)?		# one optional newline followed by spaces
+
+			  \[
+				(.*?)		# id = $3
+			  \]
+
+			)
+			}xs', 
+			array(&$this, '_doImages_reference_callback'), $text);
+
+		#
+		# Next, handle inline images:  ![alt text](url "optional title")
+		# Don't forget: encode * and _
+		#
+		$text = preg_replace_callback('{
+			(				# wrap whole match in $1
+			  !\[
+				('.$this->nested_brackets_re.')		# alt text = $2
+			  \]
+			  \s?			# One optional whitespace character
+			  \(			# literal paren
+				[ \n]*
+				(?:
+					<(\S*)>	# src url = $3
+				|
+					('.$this->nested_url_parenthesis_re.')	# src url = $4
+				)
+				[ \n]*
+				(			# $5
+				  ([\'"])	# quote char = $6
+				  (.*?)		# title = $7
+				  \6		# matching quote
+				  [ \n]*
+				)?			# title is optional
+			  \)
+			)
+			}xs',
+			array(&$this, '_doImages_inline_callback'), $text);
+
+		return $text;
+	}
+	function _doImages_reference_callback($matches) {
+		$whole_match = $matches[1];
+		$alt_text    = $matches[2];
+		$link_id     = strtolower($matches[3]);
+
+		if ($link_id == "") {
+			$link_id = strtolower($alt_text); # for shortcut links like ![this][].
+		}
+
+		$alt_text = $this->encodeAttribute($alt_text);
+		if (isset($this->urls[$link_id])) {
+			$url = $this->encodeAttribute($this->urls[$link_id]);
+			$result = "<img src=\"$url\" alt=\"$alt_text\"";
+			if (isset($this->titles[$link_id])) {
+				$title = $this->titles[$link_id];
+				$title = $this->encodeAttribute($title);
+				$result .=  " title=\"$title\"";
+			}
+			$result .= $this->empty_element_suffix;
+			$result = $this->hashPart($result);
+		}
+		else {
+			# If there's no such link ID, leave intact:
+			$result = $whole_match;
+		}
+
+		return $result;
+	}
+	function _doImages_inline_callback($matches) {
+		$whole_match	= $matches[1];
+		$alt_text		= $matches[2];
+		$url			= $matches[3] == '' ? $matches[4] : $matches[3];
+		$title			=& $matches[7];
+
+		$alt_text = $this->encodeAttribute($alt_text);
+		$url = $this->encodeAttribute($url);
+		$result = "<img src=\"$url\" alt=\"$alt_text\"";
+		if (isset($title)) {
+			$title = $this->encodeAttribute($title);
+			$result .=  " title=\"$title\""; # $title already quoted
+		}
+		$result .= $this->empty_element_suffix;
+
+		return $this->hashPart($result);
+	}
+
+
+	function doHeaders($text) {
+		# Setext-style headers:
+		#	  Header 1
+		#	  ========
+		#  
+		#	  Header 2
+		#	  --------
+		#
+		$text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
+			array(&$this, '_doHeaders_callback_setext'), $text);
+
+		# atx-style headers:
+		#	# Header 1
+		#	## Header 2
+		#	## Header 2 with closing hashes ##
+		#	...
+		#	###### Header 6
+		#
+		$text = preg_replace_callback('{
+				^(\#{1,6})	# $1 = string of #\'s
+				[ ]*
+				(.+?)		# $2 = Header text
+				[ ]*
+				\#*			# optional closing #\'s (not counted)
+				\n+
+			}xm',
+			array(&$this, '_doHeaders_callback_atx'), $text);
+
+		return $text;
+	}
+	function _doHeaders_callback_setext($matches) {
+		# Terrible hack to check we haven't found an empty list item.
+		if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1]))
+			return $matches[0];
+		
+		$level = $matches[2]{0} == '=' ? 1 : 2;
+		$block = "<h$level>".$this->runSpanGamut($matches[1])."</h$level>";
+		return "\n" . $this->hashBlock($block) . "\n\n";
+	}
+	function _doHeaders_callback_atx($matches) {
+		$level = strlen($matches[1]);
+		$block = "<h$level>".$this->runSpanGamut($matches[2])."</h$level>";
+		return "\n" . $this->hashBlock($block) . "\n\n";
+	}
+
+
+	function doLists($text) {
+	#
+	# Form HTML ordered (numbered) and unordered (bulleted) lists.
+	#
+		$less_than_tab = $this->tab_width - 1;
+
+		# Re-usable patterns to match list item bullets and number markers:
+		$marker_ul_re  = '[*+-]';
+		$marker_ol_re  = '\d+[\.]';
+		$marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
+
+		$markers_relist = array(
+			$marker_ul_re => $marker_ol_re,
+			$marker_ol_re => $marker_ul_re,
+			);
+
+		foreach ($markers_relist as $marker_re => $other_marker_re) {
+			# Re-usable pattern to match any entirel ul or ol list:
+			$whole_list_re = '
+				(								# $1 = whole list
+				  (								# $2
+					([ ]{0,'.$less_than_tab.'})	# $3 = number of spaces
+					('.$marker_re.')			# $4 = first list item marker
+					[ ]+
+				  )
+				  (?s:.+?)
+				  (								# $5
+					  \z
+					|
+					  \n{2,}
+					  (?=\S)
+					  (?!						# Negative lookahead for another list item marker
+						[ ]*
+						'.$marker_re.'[ ]+
+					  )
+					|
+					  (?=						# Lookahead for another kind of list
+					    \n
+						\3						# Must have the same indentation
+						'.$other_marker_re.'[ ]+
+					  )
+				  )
+				)
+			'; // mx
+			
+			# We use a different prefix before nested lists than top-level lists.
+			# See extended comment in _ProcessListItems().
+		
+			if ($this->list_level) {
+				$text = preg_replace_callback('{
+						^
+						'.$whole_list_re.'
+					}mx',
+					array(&$this, '_doLists_callback'), $text);
+			}
+			else {
+				$text = preg_replace_callback('{
+						(?:(?<=\n)\n|\A\n?) # Must eat the newline
+						'.$whole_list_re.'
+					}mx',
+					array(&$this, '_doLists_callback'), $text);
+			}
+		}
+
+		return $text;
+	}
+	function _doLists_callback($matches) {
+		# Re-usable patterns to match list item bullets and number markers:
+		$marker_ul_re  = '[*+-]';
+		$marker_ol_re  = '\d+[\.]';
+		$marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
+		
+		$list = $matches[1];
+		$list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol";
+		
+		$marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
+		
+		$list .= "\n";
+		$result = $this->processListItems($list, $marker_any_re);
+		
+		$result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
+		return "\n". $result ."\n\n";
+	}
+
+	var $list_level = 0;
+
+	function processListItems($list_str, $marker_any_re) {
+	#
+	#	Process the contents of a single ordered or unordered list, splitting it
+	#	into individual list items.
+	#
+		# The $this->list_level global keeps track of when we're inside a list.
+		# Each time we enter a list, we increment it; when we leave a list,
+		# we decrement. If it's zero, we're not in a list anymore.
+		#
+		# We do this because when we're not inside a list, we want to treat
+		# something like this:
+		#
+		#		I recommend upgrading to version
+		#		8. Oops, now this line is treated
+		#		as a sub-list.
+		#
+		# As a single paragraph, despite the fact that the second line starts
+		# with a digit-period-space sequence.
+		#
+		# Whereas when we're inside a list (or sub-list), that line will be
+		# treated as the start of a sub-list. What a kludge, huh? This is
+		# an aspect of Markdown's syntax that's hard to parse perfectly
+		# without resorting to mind-reading. Perhaps the solution is to
+		# change the syntax rules such that sub-lists must start with a
+		# starting cardinal number; e.g. "1." or "a.".
+		
+		$this->list_level++;
+
+		# trim trailing blank lines:
+		$list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
+
+		$list_str = preg_replace_callback('{
+			(\n)?							# leading line = $1
+			(^[ ]*)							# leading whitespace = $2
+			('.$marker_any_re.'				# list marker and space = $3
+				(?:[ ]+|(?=\n))	# space only required if item is not empty
+			)
+			((?s:.*?))						# list item text   = $4
+			(?:(\n+(?=\n))|\n)				# tailing blank line = $5
+			(?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n))))
+			}xm',
+			array(&$this, '_processListItems_callback'), $list_str);
+
+		$this->list_level--;
+		return $list_str;
+	}
+	function _processListItems_callback($matches) {
+		$item = $matches[4];
+		$leading_line =& $matches[1];
+		$leading_space =& $matches[2];
+		$marker_space = $matches[3];
+		$tailing_blank_line =& $matches[5];
+
+		if ($leading_line || $tailing_blank_line || 
+			preg_match('/\n{2,}/', $item))
+		{
+			# Replace marker with the appropriate whitespace indentation
+			$item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
+			$item = $this->runBlockGamut($this->outdent($item)."\n");
+		}
+		else {
+			# Recursion for sub-lists:
+			$item = $this->doLists($this->outdent($item));
+			$item = preg_replace('/\n+$/', '', $item);
+			$item = $this->runSpanGamut($item);
+		}
+
+		return "<li>" . $item . "</li>\n";
+	}
+
+
+	function doCodeBlocks($text) {
+	#
+	#	Process Markdown `<pre><code>` blocks.
+	#
+		$text = preg_replace_callback('{
+				(?:\n\n|\A\n?)
+				(	            # $1 = the code block -- one or more lines, starting with a space/tab
+				  (?>
+					[ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
+					.*\n+
+				  )+
+				)
+				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
+			}xm',
+			array(&$this, '_doCodeBlocks_callback'), $text);
+
+		return $text;
+	}
+	function _doCodeBlocks_callback($matches) {
+		$codeblock = $matches[1];
+
+		$codeblock = $this->outdent($codeblock);
+		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+
+		# trim leading newlines and trailing newlines
+		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
+
+		$codeblock = "<pre><code>$codeblock\n</code></pre>";
+		return "\n\n".$this->hashBlock($codeblock)."\n\n";
+	}
+
+
+	function makeCodeSpan($code) {
+	#
+	# Create a code span markup for $code. Called from handleSpanToken.
+	#
+		$code = htmlspecialchars(trim($code), ENT_NOQUOTES);
+		return $this->hashPart("<code>$code</code>");
+	}
+
+
+	var $em_relist = array(
+		''  => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?=\S|$)(?![\.,:;]\s)',
+		'*' => '(?<=\S|^)(?<!\*)\*(?!\*)',
+		'_' => '(?<=\S|^)(?<!_)_(?!_)',
+		);
+	var $strong_relist = array(
+		''   => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?=\S|$)(?![\.,:;]\s)',
+		'**' => '(?<=\S|^)(?<!\*)\*\*(?!\*)',
+		'__' => '(?<=\S|^)(?<!_)__(?!_)',
+		);
+	var $em_strong_relist = array(
+		''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?=\S|$)(?![\.,:;]\s)',
+		'***' => '(?<=\S|^)(?<!\*)\*\*\*(?!\*)',
+		'___' => '(?<=\S|^)(?<!_)___(?!_)',
+		);
+	var $em_strong_prepared_relist;
+	
+	function prepareItalicsAndBold() {
+	#
+	# Prepare regular expressions for searching emphasis tokens in any
+	# context.
+	#
+		foreach ($this->em_relist as $em => $em_re) {
+			foreach ($this->strong_relist as $strong => $strong_re) {
+				# Construct list of allowed token expressions.
+				$token_relist = array();
+				if (isset($this->em_strong_relist["$em$strong"])) {
+					$token_relist[] = $this->em_strong_relist["$em$strong"];
+				}
+				$token_relist[] = $em_re;
+				$token_relist[] = $strong_re;
+				
+				# Construct master expression from list.
+				$token_re = '{('. implode('|', $token_relist) .')}';
+				$this->em_strong_prepared_relist["$em$strong"] = $token_re;
+			}
+		}
+	}
+	
+	function doItalicsAndBold($text) {
+		$token_stack = array('');
+		$text_stack = array('');
+		$em = '';
+		$strong = '';
+		$tree_char_em = false;
+		
+		while (1) {
+			#
+			# Get prepared regular expression for seraching emphasis tokens
+			# in current context.
+			#
+			$token_re = $this->em_strong_prepared_relist["$em$strong"];
+			
+			#
+			# Each loop iteration search for the next emphasis token. 
+			# Each token is then passed to handleSpanToken.
+			#
+			$parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+			$text_stack[0] .= $parts[0];
+			$token =& $parts[1];
+			$text =& $parts[2];
+			
+			if (empty($token)) {
+				# Reached end of text span: empty stack without emitting.
+				# any more emphasis.
+				while ($token_stack[0]) {
+					$text_stack[1] .= array_shift($token_stack);
+					$text_stack[0] .= array_shift($text_stack);
+				}
+				break;
+			}
+			
+			$token_len = strlen($token);
+			if ($tree_char_em) {
+				# Reached closing marker while inside a three-char emphasis.
+				if ($token_len == 3) {
+					# Three-char closing marker, close em and strong.
+					array_shift($token_stack);
+					$span = array_shift($text_stack);
+					$span = $this->runSpanGamut($span);
+					$span = "<strong><em>$span</em></strong>";
+					$text_stack[0] .= $this->hashPart($span);
+					$em = '';
+					$strong = '';
+				} else {
+					# Other closing marker: close one em or strong and
+					# change current token state to match the other
+					$token_stack[0] = str_repeat($token{0}, 3-$token_len);
+					$tag = $token_len == 2 ? "strong" : "em";
+					$span = $text_stack[0];
+					$span = $this->runSpanGamut($span);
+					$span = "<$tag>$span</$tag>";
+					$text_stack[0] = $this->hashPart($span);
+					$$tag = ''; # $$tag stands for $em or $strong
+				}
+				$tree_char_em = false;
+			} else if ($token_len == 3) {
+				if ($em) {
+					# Reached closing marker for both em and strong.
+					# Closing strong marker:
+					for ($i = 0; $i < 2; ++$i) {
+						$shifted_token = array_shift($token_stack);
+						$tag = strlen($shifted_token) == 2 ? "strong" : "em";
+						$span = array_shift($text_stack);
+						$span = $this->runSpanGamut($span);
+						$span = "<$tag>$span</$tag>";
+						$text_stack[0] .= $this->hashPart($span);
+						$$tag = ''; # $$tag stands for $em or $strong
+					}
+				} else {
+					# Reached opening three-char emphasis marker. Push on token 
+					# stack; will be handled by the special condition above.
+					$em = $token{0};
+					$strong = "$em$em";
+					array_unshift($token_stack, $token);
+					array_unshift($text_stack, '');
+					$tree_char_em = true;
+				}
+			} else if ($token_len == 2) {
+				if ($strong) {
+					# Unwind any dangling emphasis marker:
+					if (strlen($token_stack[0]) == 1) {
+						$text_stack[1] .= array_shift($token_stack);
+						$text_stack[0] .= array_shift($text_stack);
+					}
+					# Closing strong marker:
+					array_shift($token_stack);
+					$span = array_shift($text_stack);
+					$span = $this->runSpanGamut($span);
+					$span = "<strong>$span</strong>";
+					$text_stack[0] .= $this->hashPart($span);
+					$strong = '';
+				} else {
+					array_unshift($token_stack, $token);
+					array_unshift($text_stack, '');
+					$strong = $token;
+				}
+			} else {
+				# Here $token_len == 1
+				if ($em) {
+					if (strlen($token_stack[0]) == 1) {
+						# Closing emphasis marker:
+						array_shift($token_stack);
+						$span = array_shift($text_stack);
+						$span = $this->runSpanGamut($span);
+						$span = "<em>$span</em>";
+						$text_stack[0] .= $this->hashPart($span);
+						$em = '';
+					} else {
+						$text_stack[0] .= $token;
+					}
+				} else {
+					array_unshift($token_stack, $token);
+					array_unshift($text_stack, '');
+					$em = $token;
+				}
+			}
+		}
+		return $text_stack[0];
+	}
+
+
+	function doBlockQuotes($text) {
+		$text = preg_replace_callback('/
+			  (								# Wrap whole match in $1
+				(?>
+				  ^[ ]*>[ ]?			# ">" at the start of a line
+					.+\n					# rest of the first line
+				  (.+\n)*					# subsequent consecutive lines
+				  \n*						# blanks
+				)+
+			  )
+			/xm',
+			array(&$this, '_doBlockQuotes_callback'), $text);
+
+		return $text;
+	}
+	function _doBlockQuotes_callback($matches) {
+		$bq = $matches[1];
+		# trim one level of quoting - trim whitespace-only lines
+		$bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
+		$bq = $this->runBlockGamut($bq);		# recurse
+
+		$bq = preg_replace('/^/m', "  ", $bq);
+		# These leading spaces cause problem with <pre> content, 
+		# so we need to fix that:
+		$bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx', 
+			array(&$this, '_doBlockQuotes_callback2'), $bq);
+
+		return "\n". $this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n";
+	}
+	function _doBlockQuotes_callback2($matches) {
+		$pre = $matches[1];
+		$pre = preg_replace('/^  /m', '', $pre);
+		return $pre;
+	}
+
+
+	function formParagraphs($text) {
+	#
+	#	Params:
+	#		$text - string to process with html <p> tags
+	#
+		# Strip leading and trailing lines:
+		$text = preg_replace('/\A\n+|\n+\z/', '', $text);
+
+		$grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+
+		#
+		# Wrap <p> tags and unhashify HTML blocks
+		#
+		foreach ($grafs as $key => $value) {
+			if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
+				# Is a paragraph.
+				$value = $this->runSpanGamut($value);
+				$value = preg_replace('/^([ ]*)/', "<p>", $value);
+				$value .= "</p>";
+				$grafs[$key] = $this->unhash($value);
+			}
+			else {
+				# Is a block.
+				# Modify elements of @grafs in-place...
+				$graf = $value;
+				$block = $this->html_hashes[$graf];
+				$graf = $block;
+//				if (preg_match('{
+//					\A
+//					(							# $1 = <div> tag
+//					  <div  \s+
+//					  [^>]*
+//					  \b
+//					  markdown\s*=\s*  ([\'"])	#	$2 = attr quote char
+//					  1
+//					  \2
+//					  [^>]*
+//					  >
+//					)
+//					(							# $3 = contents
+//					.*
+//					)
+//					(</div>)					# $4 = closing tag
+//					\z
+//					}xs', $block, $matches))
+//				{
+//					list(, $div_open, , $div_content, $div_close) = $matches;
+//
+//					# We can't call Markdown(), because that resets the hash;
+//					# that initialization code should be pulled into its own sub, though.
+//					$div_content = $this->hashHTMLBlocks($div_content);
+//					
+//					# Run document gamut methods on the content.
+//					foreach ($this->document_gamut as $method => $priority) {
+//						$div_content = $this->$method($div_content);
+//					}
+//
+//					$div_open = preg_replace(
+//						'{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open);
+//
+//					$graf = $div_open . "\n" . $div_content . "\n" . $div_close;
+//				}
+				$grafs[$key] = $graf;
+			}
+		}
+
+		return implode("\n\n", $grafs);
+	}
+
+
+	function encodeAttribute($text) {
+	#
+	# Encode text for a double-quoted HTML attribute. This function
+	# is *not* suitable for attributes enclosed in single quotes.
+	#
+		$text = $this->encodeAmpsAndAngles($text);
+		$text = str_replace('"', '&quot;', $text);
+		return $text;
+	}
+	
+	
+	function encodeAmpsAndAngles($text) {
+	#
+	# Smart processing for ampersands and angle brackets that need to 
+	# be encoded. Valid character entities are left alone unless the
+	# no-entities mode is set.
+	#
+		if ($this->no_entities) {
+			$text = str_replace('&', '&amp;', $text);
+		} else {
+			# Ampersand-encoding based entirely on Nat Irons's Amputator
+			# MT plugin: <http://bumppo.net/projects/amputator/>
+			$text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', 
+								'&amp;', $text);;
+		}
+		# Encode remaining <'s
+		$text = str_replace('<', '&lt;', $text);
+
+		return $text;
+	}
+
+
+	function doAutoLinks($text) {
+		$text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i', 
+			array(&$this, '_doAutoLinks_url_callback'), $text);
+
+		# Email addresses: <address@domain.foo>
+		$text = preg_replace_callback('{
+			<
+			(?:mailto:)?
+			(
+				(?:
+					[-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+
+				|
+					".*?"
+				)
+				\@
+				(?:
+					[-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+
+				|
+					\[[\d.a-fA-F:]+\]	# IPv4 & IPv6
+				)
+			)
+			>
+			}xi',
+			array(&$this, '_doAutoLinks_email_callback'), $text);
+
+		return $text;
+	}
+	function _doAutoLinks_url_callback($matches) {
+		$url = $this->encodeAttribute($matches[1]);
+		$link = "<a href=\"$url\">$url</a>";
+		return $this->hashPart($link);
+	}
+	function _doAutoLinks_email_callback($matches) {
+		$address = $matches[1];
+		$link = $this->encodeEmailAddress($address);
+		return $this->hashPart($link);
+	}
+
+
+	function encodeEmailAddress($addr) {
+	#
+	#	Input: an email address, e.g. "foo@example.com"
+	#
+	#	Output: the email address as a mailto link, with each character
+	#		of the address encoded as either a decimal or hex entity, in
+	#		the hopes of foiling most address harvesting spam bots. E.g.:
+	#
+	#	  <p><a href="&#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x66;o&#111;
+	#        &#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#111;
+	#        &#x6d;">&#x66;o&#111;&#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;
+	#        &#101;&#46;&#x63;&#111;&#x6d;</a></p>
+	#
+	#	Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
+	#   With some optimizations by Milian Wolff.
+	#
+		$addr = "mailto:" . $addr;
+		$chars = preg_split('/(?<!^)(?!$)/', $addr);
+		$seed = (int)abs(crc32($addr) / strlen($addr)); # Deterministic seed.
+		
+		foreach ($chars as $key => $char) {
+			$ord = ord($char);
+			# Ignore non-ascii chars.
+			if ($ord < 128) {
+				$r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
+				# roughly 10% raw, 45% hex, 45% dec
+				# '@' *must* be encoded. I insist.
+				if ($r > 90 && $char != '@') /* do nothing */;
+				else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';';
+				else              $chars[$key] = '&#'.$ord.';';
+			}
+		}
+		
+		$addr = implode('', $chars);
+		$text = implode('', array_slice($chars, 7)); # text without `mailto:`
+		$addr = "<a href=\"$addr\">$text</a>";
+
+		return $addr;
+	}
+
+
+	function parseSpan($str) {
+	#
+	# Take the string $str and parse it into tokens, hashing embeded HTML,
+	# escaped characters and handling code spans.
+	#
+		$output = '';
+		
+		$span_re = '{
+				(
+					\\\\'.$this->escape_chars_re.'
+				|
+					(?<![`\\\\])
+					`+						# code span marker
+			'.( $this->no_markup ? '' : '
+				|
+					<!--    .*?     -->		# comment
+				|
+					<\?.*?\?> | <%.*?%>		# processing instruction
+				|
+					<[/!$]?[-a-zA-Z0-9:_]+	# regular tags
+					(?>
+						\s
+						(?>[^"\'>]+|"[^"]*"|\'[^\']*\')*
+					)?
+					>
+			').'
+				)
+				}xs';
+
+		while (1) {
+			#
+			# Each loop iteration seach for either the next tag, the next 
+			# openning code span marker, or the next escaped character. 
+			# Each token is then passed to handleSpanToken.
+			#
+			$parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
+			
+			# Create token from text preceding tag.
+			if ($parts[0] != "") {
+				$output .= $parts[0];
+			}
+			
+			# Check if we reach the end.
+			if (isset($parts[1])) {
+				$output .= $this->handleSpanToken($parts[1], $parts[2]);
+				$str = $parts[2];
+			}
+			else {
+				break;
+			}
+		}
+		
+		return $output;
+	}
+	
+	
+	function handleSpanToken($token, &$str) {
+	#
+	# Handle $token provided by parseSpan by determining its nature and 
+	# returning the corresponding value that should replace it.
+	#
+		switch ($token{0}) {
+			case "\\":
+				return $this->hashPart("&#". ord($token{1}). ";");
+			case "`":
+				# Search for end marker in remaining text.
+				if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', 
+					$str, $matches))
+				{
+					$str = $matches[2];
+					$codespan = $this->makeCodeSpan($matches[1]);
+					return $this->hashPart($codespan);
+				}
+				return $token; // return as text since no ending marker found.
+			default:
+				return $this->hashPart($token);
+		}
+	}
+
+
+	function outdent($text) {
+	#
+	# Remove one level of line-leading tabs or spaces
+	#
+		return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text);
+	}
+
+
+	# String length function for detab. `_initDetab` will create a function to 
+	# hanlde UTF-8 if the default function does not exist.
+	var $utf8_strlen = 'mb_strlen';
+	
+	function detab($text) {
+	#
+	# Replace tabs with the appropriate amount of space.
+	#
+		# For each line we separate the line in blocks delemited by
+		# tab characters. Then we reconstruct every line by adding the 
+		# appropriate number of space between each blocks.
+		
+		$text = preg_replace_callback('/^.*\t.*$/m',
+			array(&$this, '_detab_callback'), $text);
+
+		return $text;
+	}
+	function _detab_callback($matches) {
+		$line = $matches[0];
+		$strlen = $this->utf8_strlen; # strlen function for UTF-8.
+		
+		# Split in blocks.
+		$blocks = explode("\t", $line);
+		# Add each blocks to the line.
+		$line = $blocks[0];
+		unset($blocks[0]); # Do not add first block twice.
+		foreach ($blocks as $block) {
+			# Calculate amount of space, insert spaces, insert block.
+			$amount = $this->tab_width - 
+				$strlen($line, 'UTF-8') % $this->tab_width;
+			$line .= str_repeat(" ", $amount) . $block;
+		}
+		return $line;
+	}
+	function _initDetab() {
+	#
+	# Check for the availability of the function in the `utf8_strlen` property
+	# (initially `mb_strlen`). If the function is not available, create a 
+	# function that will loosely count the number of UTF-8 characters with a
+	# regular expression.
+	#
+		if (function_exists($this->utf8_strlen)) return;
+		$this->utf8_strlen = create_function('$text', 'return preg_match_all(
+			"/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/", 
+			$text, $m);');
+	}
+
+
+	function unhash($text) {
+	#
+	# Swap back in all the tags hashed by _HashHTMLBlocks.
+	#
+		return preg_replace_callback('/(.)\x1A[0-9]+\1/', 
+			array(&$this, '_unhash_callback'), $text);
+	}
+	function _unhash_callback($matches) {
+		return $this->html_hashes[$matches[0]];
+	}
+
+}
+
+
+#
+# Markdown Extra Parser Class
+#
+
+class MarkdownExtra_Parser extends Markdown_Parser {
+
+	# Prefix for footnote ids.
+	var $fn_id_prefix = "";
+	
+	# Optional title attribute for footnote links and backlinks.
+	var $fn_link_title = MARKDOWN_FN_LINK_TITLE;
+	var $fn_backlink_title = MARKDOWN_FN_BACKLINK_TITLE;
+	
+	# Optional class attribute for footnote links and backlinks.
+	var $fn_link_class = MARKDOWN_FN_LINK_CLASS;
+	var $fn_backlink_class = MARKDOWN_FN_BACKLINK_CLASS;
+	
+	# Predefined abbreviations.
+	var $predef_abbr = array();
+
+
+	function MarkdownExtra_Parser() {
+	#
+	# Constructor function. Initialize the parser object.
+	#
+		# Add extra escapable characters before parent constructor 
+		# initialize the table.
+		$this->escape_chars .= ':|';
+		
+		# Insert extra document, block, and span transformations. 
+		# Parent constructor will do the sorting.
+		$this->document_gamut += array(
+			"doFencedCodeBlocks" => 5,
+			"stripFootnotes"     => 15,
+			"stripAbbreviations" => 25,
+			"appendFootnotes"    => 50,
+			);
+		$this->block_gamut += array(
+			"doFencedCodeBlocks" => 5,
+			"doTables"           => 15,
+			"doDefLists"         => 45,
+			);
+		$this->span_gamut += array(
+			"doFootnotes"        => 5,
+			"doAbbreviations"    => 70,
+			);
+		
+		parent::Markdown_Parser();
+	}
+	
+	
+	# Extra variables used during extra transformations.
+	var $footnotes = array();
+	var $footnotes_ordered = array();
+	var $abbr_desciptions = array();
+	var $abbr_word_re = '';
+	
+	# Give the current footnote number.
+	var $footnote_counter = 1;
+	
+	
+	function setup() {
+	#
+	# Setting up Extra-specific variables.
+	#
+		parent::setup();
+		
+		$this->footnotes = array();
+		$this->footnotes_ordered = array();
+		$this->abbr_desciptions = array();
+		$this->abbr_word_re = '';
+		$this->footnote_counter = 1;
+		
+		foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
+			if ($this->abbr_word_re)
+				$this->abbr_word_re .= '|';
+			$this->abbr_word_re .= preg_quote($abbr_word);
+			$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+		}
+	}
+	
+	function teardown() {
+	#
+	# Clearing Extra-specific variables.
+	#
+		$this->footnotes = array();
+		$this->footnotes_ordered = array();
+		$this->abbr_desciptions = array();
+		$this->abbr_word_re = '';
+		
+		parent::teardown();
+	}
+	
+	
+	### HTML Block Parser ###
+	
+	# Tags that are always treated as block tags:
+	var $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend';
+	
+	# Tags treated as block tags only if the opening tag is alone on it's line:
+	var $context_block_tags_re = 'script|noscript|math|ins|del';
+	
+	# Tags where markdown="1" default to span mode:
+	var $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
+	
+	# Tags which must not have their contents modified, no matter where 
+	# they appear:
+	var $clean_tags_re = 'script|math';
+	
+	# Tags that do not need to be closed.
+	var $auto_close_tags_re = 'hr|img';
+	
+
+	function hashHTMLBlocks($text) {
+	#
+	# Hashify HTML Blocks and "clean tags".
+	#
+	# We only want to do this for block-level HTML tags, such as headers,
+	# lists, and tables. That's because we still want to wrap <p>s around
+	# "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+	# phrase emphasis, and spans. The list of tags we're looking for is
+	# hard-coded.
+	#
+	# This works by calling _HashHTMLBlocks_InMarkdown, which then calls
+	# _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1" 
+	# attribute is found whitin a tag, _HashHTMLBlocks_InHTML calls back
+	#  _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
+	# These two functions are calling each other. It's recursive!
+	#
+		#
+		# Call the HTML-in-Markdown hasher.
+		#
+		list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
+		
+		return $text;
+	}
+	function _hashHTMLBlocks_inMarkdown($text, $indent = 0, 
+										$enclosing_tag_re = '', $span = false)
+	{
+	#
+	# Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
+	#
+	# *   $indent is the number of space to be ignored when checking for code 
+	#     blocks. This is important because if we don't take the indent into 
+	#     account, something like this (which looks right) won't work as expected:
+	#
+	#     <div>
+	#         <div markdown="1">
+	#         Hello World.  <-- Is this a Markdown code block or text?
+	#         </div>  <-- Is this a Markdown code block or a real tag?
+	#     <div>
+	#
+	#     If you don't like this, just don't indent the tag on which
+	#     you apply the markdown="1" attribute.
+	#
+	# *   If $enclosing_tag_re is not empty, stops at the first unmatched closing 
+	#     tag with that name. Nested tags supported.
+	#
+	# *   If $span is true, text inside must treated as span. So any double 
+	#     newline will be replaced by a single newline so that it does not create 
+	#     paragraphs.
+	#
+	# Returns an array of that form: ( processed text , remaining text )
+	#
+		if ($text === '') return array('', '');
+
+		# Regex to check for the presense of newlines around a block tag.
+		$newline_before_re = '/(?:^\n?|\n\n)*$/';
+		$newline_after_re = 
+			'{
+				^						# Start of text following the tag.
+				(?>[ ]*<!--.*?-->)?		# Optional comment.
+				[ ]*\n					# Must be followed by newline.
+			}xs';
+		
+		# Regex to match any tag.
+		$block_tag_re =
+			'{
+				(					# $2: Capture hole tag.
+					</?					# Any opening or closing tag.
+						(?>				# Tag name.
+							'.$this->block_tags_re.'			|
+							'.$this->context_block_tags_re.'	|
+							'.$this->clean_tags_re.'        	|
+							(?!\s)'.$enclosing_tag_re.'
+						)
+						(?:
+							(?=[\s"\'/a-zA-Z0-9])	# Allowed characters after tag name.
+							(?>
+								".*?"		|	# Double quotes (can contain `>`)
+								\'.*?\'   	|	# Single quotes (can contain `>`)
+								.+?				# Anything but quotes and `>`.
+							)*?
+						)?
+					>					# End of tag.
+				|
+					<!--    .*?     -->	# HTML Comment
+				|
+					<\?.*?\?> | <%.*?%>	# Processing instruction
+				|
+					<!\[CDATA\[.*?\]\]>	# CData Block
+				|
+					# Code span marker
+					`+
+				'. ( !$span ? ' # If not in span.
+				|
+					# Indented code block
+					(?: ^[ ]*\n | ^ | \n[ ]*\n )
+					[ ]{'.($indent+4).'}[^\n]* \n
+					(?>
+						(?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n
+					)*
+				|
+					# Fenced code block marker
+					(?> ^ | \n )
+					[ ]{0,'.($indent).'}~~~+[ ]*\n
+				' : '' ). ' # End (if not is span).
+				)
+			}xs';
+
+		
+		$depth = 0;		# Current depth inside the tag tree.
+		$parsed = "";	# Parsed text that will be returned.
+
+		#
+		# Loop through every tag until we find the closing tag of the parent
+		# or loop until reaching the end of text if no parent tag specified.
+		#
+		do {
+			#
+			# Split the text using the first $tag_match pattern found.
+			# Text before  pattern will be first in the array, text after
+			# pattern will be at the end, and between will be any catches made 
+			# by the pattern.
+			#
+			$parts = preg_split($block_tag_re, $text, 2, 
+								PREG_SPLIT_DELIM_CAPTURE);
+			
+			# If in Markdown span mode, add a empty-string span-level hash 
+			# after each newline to prevent triggering any block element.
+			if ($span) {
+				$void = $this->hashPart("", ':');
+				$newline = "$void\n";
+				$parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
+			}
+			
+			$parsed .= $parts[0]; # Text before current tag.
+			
+			# If end of $text has been reached. Stop loop.
+			if (count($parts) < 3) {
+				$text = "";
+				break;
+			}
+			
+			$tag  = $parts[1]; # Tag to handle.
+			$text = $parts[2]; # Remaining text after current tag.
+			$tag_re = preg_quote($tag); # For use in a regular expression.
+			
+			#
+			# Check for: Code span marker
+			#
+			if ($tag{0} == "`") {
+				# Find corresponding end marker.
+				$tag_re = preg_quote($tag);
+				if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)'.$tag_re.'(?!`)}',
+					$text, $matches))
+				{
+					# End marker found: pass text unchanged until marker.
+					$parsed .= $tag . $matches[0];
+					$text = substr($text, strlen($matches[0]));
+				}
+				else {
+					# Unmatched marker: just skip it.
+					$parsed .= $tag;
+				}
+			}
+			#
+			# Check for: Fenced code block marker.
+			#
+			else if (preg_match('{^\n?[ ]{0,'.($indent+3).'}~}', $tag)) {
+				# Fenced code block marker: find matching end marker.
+				$tag_re = preg_quote(trim($tag));
+				if (preg_match('{^(?>.*\n)+?[ ]{0,'.($indent).'}'.$tag_re.'[ ]*\n}', $text, 
+					$matches)) 
+				{
+					# End marker found: pass text unchanged until marker.
+					$parsed .= $tag . $matches[0];
+					$text = substr($text, strlen($matches[0]));
+				}
+				else {
+					# No end marker: just skip it.
+					$parsed .= $tag;
+				}
+			}
+			#
+			# Check for: Indented code block.
+			#
+			else if ($tag{0} == "\n" || $tag{0} == " ") {
+				# Indented code block: pass it unchanged, will be handled 
+				# later.
+				$parsed .= $tag;
+			}
+			#
+			# Check for: Opening Block level tag or
+			#            Opening Context Block tag (like ins and del) 
+			#               used as a block tag (tag is alone on it's line).
+			#
+			else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) ||
+				(	preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) &&
+					preg_match($newline_before_re, $parsed) &&
+					preg_match($newline_after_re, $text)	)
+				)
+			{
+				# Need to parse tag and following text using the HTML parser.
+				list($block_text, $text) = 
+					$this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
+				
+				# Make sure it stays outside of any paragraph by adding newlines.
+				$parsed .= "\n\n$block_text\n\n";
+			}
+			#
+			# Check for: Clean tag (like script, math)
+			#            HTML Comments, processing instructions.
+			#
+			else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) ||
+				$tag{1} == '!' || $tag{1} == '?')
+			{
+				# Need to parse tag and following text using the HTML parser.
+				# (don't check for markdown attribute)
+				list($block_text, $text) = 
+					$this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
+				
+				$parsed .= $block_text;
+			}
+			#
+			# Check for: Tag with same name as enclosing tag.
+			#
+			else if ($enclosing_tag_re !== '' &&
+				# Same name as enclosing tag.
+				preg_match('{^</?(?:'.$enclosing_tag_re.')\b}', $tag))
+			{
+				#
+				# Increase/decrease nested tag count.
+				#
+				if ($tag{1} == '/')						$depth--;
+				else if ($tag{strlen($tag)-2} != '/')	$depth++;
+
+				if ($depth < 0) {
+					#
+					# Going out of parent element. Clean up and break so we
+					# return to the calling function.
+					#
+					$text = $tag . $text;
+					break;
+				}
+				
+				$parsed .= $tag;
+			}
+			else {
+				$parsed .= $tag;
+			}
+		} while ($depth >= 0);
+		
+		return array($parsed, $text);
+	}
+	function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
+	#
+	# Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
+	#
+	# *   Calls $hash_method to convert any blocks.
+	# *   Stops when the first opening tag closes.
+	# *   $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
+	#     (it is not inside clean tags)
+	#
+	# Returns an array of that form: ( processed text , remaining text )
+	#
+		if ($text === '') return array('', '');
+		
+		# Regex to match `markdown` attribute inside of a tag.
+		$markdown_attr_re = '
+			{
+				\s*			# Eat whitespace before the `markdown` attribute
+				markdown
+				\s*=\s*
+				(?>
+					(["\'])		# $1: quote delimiter		
+					(.*?)		# $2: attribute value
+					\1			# matching delimiter	
+				|
+					([^\s>]*)	# $3: unquoted attribute value
+				)
+				()				# $4: make $3 always defined (avoid warnings)
+			}xs';
+		
+		# Regex to match any tag.
+		$tag_re = '{
+				(					# $2: Capture hole tag.
+					</?					# Any opening or closing tag.
+						[\w:$]+			# Tag name.
+						(?:
+							(?=[\s"\'/a-zA-Z0-9])	# Allowed characters after tag name.
+							(?>
+								".*?"		|	# Double quotes (can contain `>`)
+								\'.*?\'   	|	# Single quotes (can contain `>`)
+								.+?				# Anything but quotes and `>`.
+							)*?
+						)?
+					>					# End of tag.
+				|
+					<!--    .*?     -->	# HTML Comment
+				|
+					<\?.*?\?> | <%.*?%>	# Processing instruction
+				|
+					<!\[CDATA\[.*?\]\]>	# CData Block
+				)
+			}xs';
+		
+		$original_text = $text;		# Save original text in case of faliure.
+		
+		$depth		= 0;	# Current depth inside the tag tree.
+		$block_text	= "";	# Temporary text holder for current text.
+		$parsed		= "";	# Parsed text that will be returned.
+
+		#
+		# Get the name of the starting tag.
+		# (This pattern makes $base_tag_name_re safe without quoting.)
+		#
+		if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
+			$base_tag_name_re = $matches[1];
+
+		#
+		# Loop through every tag until we find the corresponding closing tag.
+		#
+		do {
+			#
+			# Split the text using the first $tag_match pattern found.
+			# Text before  pattern will be first in the array, text after
+			# pattern will be at the end, and between will be any catches made 
+			# by the pattern.
+			#
+			$parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+			
+			if (count($parts) < 3) {
+				#
+				# End of $text reached with unbalenced tag(s).
+				# In that case, we return original text unchanged and pass the
+				# first character as filtered to prevent an infinite loop in the 
+				# parent function.
+				#
+				return array($original_text{0}, substr($original_text, 1));
+			}
+			
+			$block_text .= $parts[0]; # Text before current tag.
+			$tag         = $parts[1]; # Tag to handle.
+			$text        = $parts[2]; # Remaining text after current tag.
+			
+			#
+			# Check for: Auto-close tag (like <hr/>)
+			#			 Comments and Processing Instructions.
+			#
+			if (preg_match('{^</?(?:'.$this->auto_close_tags_re.')\b}', $tag) ||
+				$tag{1} == '!' || $tag{1} == '?')
+			{
+				# Just add the tag to the block as if it was text.
+				$block_text .= $tag;
+			}
+			else {
+				#
+				# Increase/decrease nested tag count. Only do so if
+				# the tag's name match base tag's.
+				#
+				if (preg_match('{^</?'.$base_tag_name_re.'\b}', $tag)) {
+					if ($tag{1} == '/')						$depth--;
+					else if ($tag{strlen($tag)-2} != '/')	$depth++;
+				}
+				
+				#
+				# Check for `markdown="1"` attribute and handle it.
+				#
+				if ($md_attr && 
+					preg_match($markdown_attr_re, $tag, $attr_m) &&
+					preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
+				{
+					# Remove `markdown` attribute from opening tag.
+					$tag = preg_replace($markdown_attr_re, '', $tag);
+					
+					# Check if text inside this tag must be parsed in span mode.
+					$this->mode = $attr_m[2] . $attr_m[3];
+					$span_mode = $this->mode == 'span' || $this->mode != 'block' &&
+						preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag);
+					
+					# Calculate indent before tag.
+					if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
+						$strlen = $this->utf8_strlen;
+						$indent = $strlen($matches[1], 'UTF-8');
+					} else {
+						$indent = 0;
+					}
+					
+					# End preceding block with this tag.
+					$block_text .= $tag;
+					$parsed .= $this->$hash_method($block_text);
+					
+					# Get enclosing tag name for the ParseMarkdown function.
+					# (This pattern makes $tag_name_re safe without quoting.)
+					preg_match('/^<([\w:$]*)\b/', $tag, $matches);
+					$tag_name_re = $matches[1];
+					
+					# Parse the content using the HTML-in-Markdown parser.
+					list ($block_text, $text)
+						= $this->_hashHTMLBlocks_inMarkdown($text, $indent, 
+							$tag_name_re, $span_mode);
+					
+					# Outdent markdown text.
+					if ($indent > 0) {
+						$block_text = preg_replace("/^[ ]{1,$indent}/m", "", 
+													$block_text);
+					}
+					
+					# Append tag content to parsed text.
+					if (!$span_mode)	$parsed .= "\n\n$block_text\n\n";
+					else				$parsed .= "$block_text";
+					
+					# Start over a new block.
+					$block_text = "";
+				}
+				else $block_text .= $tag;
+			}
+			
+		} while ($depth > 0);
+		
+		#
+		# Hash last block text that wasn't processed inside the loop.
+		#
+		$parsed .= $this->$hash_method($block_text);
+		
+		return array($parsed, $text);
+	}
+
+
+	function hashClean($text) {
+	#
+	# Called whenever a tag must be hashed when a function insert a "clean" tag
+	# in $text, it pass through this function and is automaticaly escaped, 
+	# blocking invalid nested overlap.
+	#
+		return $this->hashPart($text, 'C');
+	}
+
+
+	function doHeaders($text) {
+	#
+	# Redefined to add id attribute support.
+	#
+		# Setext-style headers:
+		#	  Header 1  {#header1}
+		#	  ========
+		#  
+		#	  Header 2  {#header2}
+		#	  --------
+		#
+		$text = preg_replace_callback(
+			'{
+				(^.+?)								# $1: Header text
+				(?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})?	# $2: Id attribute
+				[ ]*\n(=+|-+)[ ]*\n+				# $3: Header footer
+			}mx',
+			array(&$this, '_doHeaders_callback_setext'), $text);
+
+		# atx-style headers:
+		#	# Header 1        {#header1}
+		#	## Header 2       {#header2}
+		#	## Header 2 with closing hashes ##  {#header3}
+		#	...
+		#	###### Header 6   {#header2}
+		#
+		$text = preg_replace_callback('{
+				^(\#{1,6})	# $1 = string of #\'s
+				[ ]*
+				(.+?)		# $2 = Header text
+				[ ]*
+				\#*			# optional closing #\'s (not counted)
+				(?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # id attribute
+				[ ]*
+				\n+
+			}xm',
+			array(&$this, '_doHeaders_callback_atx'), $text);
+
+		return $text;
+	}
+	function _doHeaders_attr($attr) {
+		if (empty($attr))  return "";
+		return " id=\"$attr\"";
+	}
+	function _doHeaders_callback_setext($matches) {
+		if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
+			return $matches[0];
+		$level = $matches[3]{0} == '=' ? 1 : 2;
+		$attr  = $this->_doHeaders_attr($id =& $matches[2]);
+		$block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";
+		return "\n" . $this->hashBlock($block) . "\n\n";
+	}
+	function _doHeaders_callback_atx($matches) {
+		$level = strlen($matches[1]);
+		$attr  = $this->_doHeaders_attr($id =& $matches[3]);
+		$block = "<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";
+		return "\n" . $this->hashBlock($block) . "\n\n";
+	}
+
+
+	function doTables($text) {
+	#
+	# Form HTML tables.
+	#
+		$less_than_tab = $this->tab_width - 1;
+		#
+		# Find tables with leading pipe.
+		#
+		#	| Header 1 | Header 2
+		#	| -------- | --------
+		#	| Cell 1   | Cell 2
+		#	| Cell 3   | Cell 4
+		#
+		$text = preg_replace_callback('
+			{
+				^							# Start of a line
+				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
+				[|]							# Optional leading pipe (present)
+				(.+) \n						# $1: Header row (at least one pipe)
+				
+				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
+				[|] ([ ]*[-:]+[-| :]*) \n	# $2: Header underline
+				
+				(							# $3: Cells
+					(?>
+						[ ]*				# Allowed whitespace.
+						[|] .* \n			# Row content.
+					)*
+				)
+				(?=\n|\Z)					# Stop at final double newline.
+			}xm',
+			array(&$this, '_doTable_leadingPipe_callback'), $text);
+		
+		#
+		# Find tables without leading pipe.
+		#
+		#	Header 1 | Header 2
+		#	-------- | --------
+		#	Cell 1   | Cell 2
+		#	Cell 3   | Cell 4
+		#
+		$text = preg_replace_callback('
+			{
+				^							# Start of a line
+				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
+				(\S.*[|].*) \n				# $1: Header row (at least one pipe)
+				
+				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
+				([-:]+[ ]*[|][-| :]*) \n	# $2: Header underline
+				
+				(							# $3: Cells
+					(?>
+						.* [|] .* \n		# Row content
+					)*
+				)
+				(?=\n|\Z)					# Stop at final double newline.
+			}xm',
+			array(&$this, '_DoTable_callback'), $text);
+
+		return $text;
+	}
+	function _doTable_leadingPipe_callback($matches) {
+		$head		= $matches[1];
+		$underline	= $matches[2];
+		$content	= $matches[3];
+		
+		# Remove leading pipe for each row.
+		$content	= preg_replace('/^ *[|]/m', '', $content);
+		
+		return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
+	}
+	function _doTable_callback($matches) {
+		$head		= $matches[1];
+		$underline	= $matches[2];
+		$content	= $matches[3];
+
+		# Remove any tailing pipes for each line.
+		$head		= preg_replace('/[|] *$/m', '', $head);
+		$underline	= preg_replace('/[|] *$/m', '', $underline);
+		$content	= preg_replace('/[|] *$/m', '', $content);
+		
+		# Reading alignement from header underline.
+		$separators	= preg_split('/ *[|] */', $underline);
+		foreach ($separators as $n => $s) {
+			if (preg_match('/^ *-+: *$/', $s))		$attr[$n] = ' align="right"';
+			else if (preg_match('/^ *:-+: *$/', $s))$attr[$n] = ' align="center"';
+			else if (preg_match('/^ *:-+ *$/', $s))	$attr[$n] = ' align="left"';
+			else									$attr[$n] = '';
+		}
+		
+		# Parsing span elements, including code spans, character escapes, 
+		# and inline HTML tags, so that pipes inside those gets ignored.
+		$head		= $this->parseSpan($head);
+		$headers	= preg_split('/ *[|] */', $head);
+		$col_count	= count($headers);
+		
+		# Write column headers.
+		$text = "<table>\n";
+		$text .= "<thead>\n";
+		$text .= "<tr>\n";
+		foreach ($headers as $n => $header)
+			$text .= "  <th$attr[$n]>".$this->runSpanGamut(trim($header))."</th>\n";
+		$text .= "</tr>\n";
+		$text .= "</thead>\n";
+		
+		# Split content by row.
+		$rows = explode("\n", trim($content, "\n"));
+		
+		$text .= "<tbody>\n";
+		foreach ($rows as $row) {
+			# Parsing span elements, including code spans, character escapes, 
+			# and inline HTML tags, so that pipes inside those gets ignored.
+			$row = $this->parseSpan($row);
+			
+			# Split row by cell.
+			$row_cells = preg_split('/ *[|] */', $row, $col_count);
+			$row_cells = array_pad($row_cells, $col_count, '');
+			
+			$text .= "<tr>\n";
+			foreach ($row_cells as $n => $cell)
+				$text .= "  <td$attr[$n]>".$this->runSpanGamut(trim($cell))."</td>\n";
+			$text .= "</tr>\n";
+		}
+		$text .= "</tbody>\n";
+		$text .= "</table>";
+		
+		return $this->hashBlock($text) . "\n";
+	}
+
+	
+	function doDefLists($text) {
+	#
+	# Form HTML definition lists.
+	#
+		$less_than_tab = $this->tab_width - 1;
+
+		# Re-usable pattern to match any entire dl list:
+		$whole_list_re = '(?>
+			(								# $1 = whole list
+			  (								# $2
+				[ ]{0,'.$less_than_tab.'}
+				((?>.*\S.*\n)+)				# $3 = defined term
+				\n?
+				[ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+			  )
+			  (?s:.+?)
+			  (								# $4
+				  \z
+				|
+				  \n{2,}
+				  (?=\S)
+				  (?!						# Negative lookahead for another term
+					[ ]{0,'.$less_than_tab.'}
+					(?: \S.*\n )+?			# defined term
+					\n?
+					[ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+				  )
+				  (?!						# Negative lookahead for another definition
+					[ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+				  )
+			  )
+			)
+		)'; // mx
+
+		$text = preg_replace_callback('{
+				(?>\A\n?|(?<=\n\n))
+				'.$whole_list_re.'
+			}mx',
+			array(&$this, '_doDefLists_callback'), $text);
+
+		return $text;
+	}
+	function _doDefLists_callback($matches) {
+		# Re-usable patterns to match list item bullets and number markers:
+		$list = $matches[1];
+		
+		# Turn double returns into triple returns, so that we can make a
+		# paragraph for the last item in a list, if necessary:
+		$result = trim($this->processDefListItems($list));
+		$result = "<dl>\n" . $result . "\n</dl>";
+		return $this->hashBlock($result) . "\n\n";
+	}
+
+
+	function processDefListItems($list_str) {
+	#
+	#	Process the contents of a single definition list, splitting it
+	#	into individual term and definition list items.
+	#
+		$less_than_tab = $this->tab_width - 1;
+		
+		# trim trailing blank lines:
+		$list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
+
+		# Process definition terms.
+		$list_str = preg_replace_callback('{
+			(?>\A\n?|\n\n+)					# leading line
+			(								# definition terms = $1
+				[ ]{0,'.$less_than_tab.'}	# leading whitespace
+				(?![:][ ]|[ ])				# negative lookahead for a definition 
+											#   mark (colon) or more whitespace.
+				(?> \S.* \n)+?				# actual term (not whitespace).	
+			)			
+			(?=\n?[ ]{0,3}:[ ])				# lookahead for following line feed 
+											#   with a definition mark.
+			}xm',
+			array(&$this, '_processDefListItems_callback_dt'), $list_str);
+
+		# Process actual definitions.
+		$list_str = preg_replace_callback('{
+			\n(\n+)?						# leading line = $1
+			(								# marker space = $2
+				[ ]{0,'.$less_than_tab.'}	# whitespace before colon
+				[:][ ]+						# definition mark (colon)
+			)
+			((?s:.+?))						# definition text = $3
+			(?= \n+ 						# stop at next definition mark,
+				(?:							# next term or end of text
+					[ ]{0,'.$less_than_tab.'} [:][ ]	|
+					<dt> | \z
+				)						
+			)					
+			}xm',
+			array(&$this, '_processDefListItems_callback_dd'), $list_str);
+
+		return $list_str;
+	}
+	function _processDefListItems_callback_dt($matches) {
+		$terms = explode("\n", trim($matches[1]));
+		$text = '';
+		foreach ($terms as $term) {
+			$term = $this->runSpanGamut(trim($term));
+			$text .= "\n<dt>" . $term . "</dt>";
+		}
+		return $text . "\n";
+	}
+	function _processDefListItems_callback_dd($matches) {
+		$leading_line	= $matches[1];
+		$marker_space	= $matches[2];
+		$def			= $matches[3];
+
+		if ($leading_line || preg_match('/\n{2,}/', $def)) {
+			# Replace marker with the appropriate whitespace indentation
+			$def = str_repeat(' ', strlen($marker_space)) . $def;
+			$def = $this->runBlockGamut($this->outdent($def . "\n\n"));
+			$def = "\n". $def ."\n";
+		}
+		else {
+			$def = rtrim($def);
+			$def = $this->runSpanGamut($this->outdent($def));
+		}
+
+		return "\n<dd>" . $def . "</dd>\n";
+	}
+
+
+	function doFencedCodeBlocks($text) {
+	#
+	# Adding the fenced code block syntax to regular Markdown:
+	#
+	# ~~~
+	# Code block
+	# ~~~
+	#
+		$less_than_tab = $this->tab_width;
+		
+		$text = preg_replace_callback('{
+				(?:\n|\A)
+				# 1: Opening marker
+				(
+					~{3,} # Marker: three tilde or more.
+				)
+				[ ]* \n # Whitespace and newline following marker.
+				
+				# 2: Content
+				(
+					(?>
+						(?!\1 [ ]* \n)	# Not a closing marker.
+						.*\n+
+					)+
+				)
+				
+				# Closing marker.
+				\1 [ ]* \n
+			}xm',
+			array(&$this, '_doFencedCodeBlocks_callback'), $text);
+
+		return $text;
+	}
+	function _doFencedCodeBlocks_callback($matches) {
+		$codeblock = $matches[2];
+		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+		$codeblock = preg_replace_callback('/^\n+/',
+			array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock);
+		$codeblock = "<pre><code>$codeblock</code></pre>";
+		return "\n\n".$this->hashBlock($codeblock)."\n\n";
+	}
+	function _doFencedCodeBlocks_newlines($matches) {
+		return str_repeat("<br$this->empty_element_suffix", 
+			strlen($matches[0]));
+	}
+
+
+	#
+	# Redefining emphasis markers so that emphasis by underscore does not
+	# work in the middle of a word.
+	#
+	var $em_relist = array(
+		''  => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?=\S|$)(?![\.,:;]\s)',
+		'*' => '(?<=\S|^)(?<!\*)\*(?!\*)',
+		'_' => '(?<=\S|^)(?<!_)_(?![a-zA-Z0-9_])',
+		);
+	var $strong_relist = array(
+		''   => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?=\S|$)(?![\.,:;]\s)',
+		'**' => '(?<=\S|^)(?<!\*)\*\*(?!\*)',
+		'__' => '(?<=\S|^)(?<!_)__(?![a-zA-Z0-9_])',
+		);
+	var $em_strong_relist = array(
+		''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?=\S|$)(?![\.,:;]\s)',
+		'***' => '(?<=\S|^)(?<!\*)\*\*\*(?!\*)',
+		'___' => '(?<=\S|^)(?<!_)___(?![a-zA-Z0-9_])',
+		);
+
+
+	function formParagraphs($text) {
+	#
+	#	Params:
+	#		$text - string to process with html <p> tags
+	#
+		# Strip leading and trailing lines:
+		$text = preg_replace('/\A\n+|\n+\z/', '', $text);
+		
+		$grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+
+		#
+		# Wrap <p> tags and unhashify HTML blocks
+		#
+		foreach ($grafs as $key => $value) {
+			$value = trim($this->runSpanGamut($value));
+			
+			# Check if this should be enclosed in a paragraph.
+			# Clean tag hashes & block tag hashes are left alone.
+			$is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
+			
+			if ($is_p) {
+				$value = "<p>$value</p>";
+			}
+			$grafs[$key] = $value;
+		}
+		
+		# Join grafs in one text, then unhash HTML tags. 
+		$text = implode("\n\n", $grafs);
+		
+		# Finish by removing any tag hashes still present in $text.
+		$text = $this->unhash($text);
+		
+		return $text;
+	}
+	
+	
+	### Footnotes
+	
+	function stripFootnotes($text) {
+	#
+	# Strips link definitions from text, stores the URLs and titles in
+	# hash references.
+	#
+		$less_than_tab = $this->tab_width - 1;
+
+		# Link defs are in the form: [^id]: url "optional title"
+		$text = preg_replace_callback('{
+			^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?:	# note_id = $1
+			  [ ]*
+			  \n?					# maybe *one* newline
+			(						# text = $2 (no blank lines allowed)
+				(?:					
+					.+				# actual text
+				|
+					\n				# newlines but 
+					(?!\[\^.+?\]:\s)# negative lookahead for footnote marker.
+					(?!\n+[ ]{0,3}\S)# ensure line is not blank and followed 
+									# by non-indented content
+				)*
+			)		
+			}xm',
+			array(&$this, '_stripFootnotes_callback'),
+			$text);
+		return $text;
+	}
+	function _stripFootnotes_callback($matches) {
+		$note_id = $this->fn_id_prefix . $matches[1];
+		$this->footnotes[$note_id] = $this->outdent($matches[2]);
+		return ''; # String that will replace the block
+	}
+
+
+	function doFootnotes($text) {
+	#
+	# Replace footnote references in $text [^id] with a special text-token 
+	# which will be replaced by the actual footnote marker in appendFootnotes.
+	#
+		if (!$this->in_anchor) {
+			$text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
+		}
+		return $text;
+	}
+
+	
+	function appendFootnotes($text) {
+	#
+	# Append footnote list to text.
+	#
+		$text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', 
+			array(&$this, '_appendFootnotes_callback'), $text);
+	
+		if (!empty($this->footnotes_ordered)) {
+			$text .= "\n\n";
+			$text .= "<div class=\"footnotes\">\n";
+			$text .= "<hr". $this->empty_element_suffix ."\n";
+			$text .= "<ol>\n\n";
+			
+			$attr = " rev=\"footnote\"";
+			if ($this->fn_backlink_class != "") {
+				$class = $this->fn_backlink_class;
+				$class = $this->encodeAttribute($class);
+				$attr .= " class=\"$class\"";
+			}
+			if ($this->fn_backlink_title != "") {
+				$title = $this->fn_backlink_title;
+				$title = $this->encodeAttribute($title);
+				$attr .= " title=\"$title\"";
+			}
+			$num = 0;
+			
+			while (!empty($this->footnotes_ordered)) {
+				$footnote = reset($this->footnotes_ordered);
+				$note_id = key($this->footnotes_ordered);
+				unset($this->footnotes_ordered[$note_id]);
+				
+				$footnote .= "\n"; # Need to append newline before parsing.
+				$footnote = $this->runBlockGamut("$footnote\n");				
+				$footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', 
+					array(&$this, '_appendFootnotes_callback'), $footnote);
+				
+				$attr = str_replace("%%", ++$num, $attr);
+				$note_id = $this->encodeAttribute($note_id);
+				
+				# Add backlink to last paragraph; create new paragraph if needed.
+				$backlink = "<a href=\"#fnref:$note_id\"$attr>&#8617;</a>";
+				if (preg_match('{</p>$}', $footnote)) {
+					$footnote = substr($footnote, 0, -4) . "&#160;$backlink</p>";
+				} else {
+					$footnote .= "\n\n<p>$backlink</p>";
+				}
+				
+				$text .= "<li id=\"fn:$note_id\">\n";
+				$text .= $footnote . "\n";
+				$text .= "</li>\n\n";
+			}
+			
+			$text .= "</ol>\n";
+			$text .= "</div>";
+		}
+		return $text;
+	}
+	function _appendFootnotes_callback($matches) {
+		$node_id = $this->fn_id_prefix . $matches[1];
+		
+		# Create footnote marker only if it has a corresponding footnote *and*
+		# the footnote hasn't been used by another marker.
+		if (isset($this->footnotes[$node_id])) {
+			# Transfert footnote content to the ordered list.
+			$this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
+			unset($this->footnotes[$node_id]);
+			
+			$num = $this->footnote_counter++;
+			$attr = " rel=\"footnote\"";
+			if ($this->fn_link_class != "") {
+				$class = $this->fn_link_class;
+				$class = $this->encodeAttribute($class);
+				$attr .= " class=\"$class\"";
+			}
+			if ($this->fn_link_title != "") {
+				$title = $this->fn_link_title;
+				$title = $this->encodeAttribute($title);
+				$attr .= " title=\"$title\"";
+			}
+			
+			$attr = str_replace("%%", $num, $attr);
+			$node_id = $this->encodeAttribute($node_id);
+			
+			return
+				"<sup id=\"fnref:$node_id\">".
+				"<a href=\"#fn:$node_id\"$attr>$num</a>".
+				"</sup>";
+		}
+		
+		return "[^".$matches[1]."]";
+	}
+		
+	
+	### Abbreviations ###
+	
+	function stripAbbreviations($text) {
+	#
+	# Strips abbreviations from text, stores titles in hash references.
+	#
+		$less_than_tab = $this->tab_width - 1;
+
+		# Link defs are in the form: [id]*: url "optional title"
+		$text = preg_replace_callback('{
+			^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?:	# abbr_id = $1
+			(.*)					# text = $2 (no blank lines allowed)	
+			}xm',
+			array(&$this, '_stripAbbreviations_callback'),
+			$text);
+		return $text;
+	}
+	function _stripAbbreviations_callback($matches) {
+		$abbr_word = $matches[1];
+		$abbr_desc = $matches[2];
+		if ($this->abbr_word_re)
+			$this->abbr_word_re .= '|';
+		$this->abbr_word_re .= preg_quote($abbr_word);
+		$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+		return ''; # String that will replace the block
+	}
+	
+	
+	function doAbbreviations($text) {
+	#
+	# Find defined abbreviations in text and wrap them in <abbr> elements.
+	#
+		if ($this->abbr_word_re) {
+			// cannot use the /x modifier because abbr_word_re may 
+			// contain significant spaces:
+			$text = preg_replace_callback('{'.
+				'(?<![\w\x1A])'.
+				'(?:'.$this->abbr_word_re.')'.
+				'(?![\w\x1A])'.
+				'}', 
+				array(&$this, '_doAbbreviations_callback'), $text);
+		}
+		return $text;
+	}
+	function _doAbbreviations_callback($matches) {
+		$abbr = $matches[0];
+		if (isset($this->abbr_desciptions[$abbr])) {
+			$desc = $this->abbr_desciptions[$abbr];
+			if (empty($desc)) {
+				return $this->hashPart("<abbr>$abbr</abbr>");
+			} else {
+				$desc = $this->encodeAttribute($desc);
+				return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");
+			}
+		} else {
+			return $matches[0];
+		}
+	}
+
+}
+
+
+/*
+
+PHP Markdown Extra
+==================
+
+Description
+-----------
+
+This is a PHP port of the original Markdown formatter written in Perl 
+by John Gruber. This special "Extra" version of PHP Markdown features 
+further enhancements to the syntax for making additional constructs 
+such as tables and definition list.
+
+Markdown is a text-to-HTML filter; it translates an easy-to-read /
+easy-to-write structured text format into HTML. Markdown's text format
+is most similar to that of plain text email, and supports features such
+as headers, *emphasis*, code blocks, blockquotes, and links.
+
+Markdown's syntax is designed not as a generic markup language, but
+specifically to serve as a front-end to (X)HTML. You can use span-level
+HTML tags anywhere in a Markdown document, and you can use block level
+HTML tags (like <div> and <table> as well).
+
+For more information about Markdown's syntax, see:
+
+<http://daringfireball.net/projects/markdown/>
+
+
+Bugs
+----
+
+To file bug reports please send email to:
+
+<michel.fortin@michelf.com>
+
+Please include with your report: (1) the example input; (2) the output you
+expected; (3) the output Markdown actually produced.
+
+
+Version History
+--------------- 
+
+See the readme file for detailed release notes for this version.
+
+
+Copyright and License
+---------------------
+
+PHP Markdown & Extra  
+Copyright (c) 2004-2009 Michel Fortin  
+<http://michelf.com/>  
+All rights reserved.
+
+Based on Markdown  
+Copyright (c) 2003-2006 John Gruber   
+<http://daringfireball.net/>   
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+*	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+*	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+*	Neither the name "Markdown" nor the names of its contributors may
+	be used to endorse or promote products derived from this software
+	without specific prior written permission.
+
+This software is provided by the copyright holders and contributors "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 copyright owner
+or contributors 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.
+
+*/
+?>
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/schemas/schema.pdo.mysql b/0.8.1-rc1/balance/modules/puny/schemas/schema.pdo.mysql
new file mode 100644
index 0000000..e53d30d
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/schemas/schema.pdo.mysql
@@ -0,0 +1,26 @@
+-- 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.
+
+--
+-- Table structure for table `puny_resource`
+--
+
+CREATE TABLE IF NOT EXISTS `puny_resource` (
+  `resourceId` varchar(60) NOT NULL,
+  `version` int(10) unsigned NOT NULL,
+  `parser` varchar(60) NOT NULL,
+  `content` text NOT NULL,
+  PRIMARY KEY  (`resourceId`,`version`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Puny content resources';
diff --git a/0.8.1-rc1/balance/modules/puny/scripts/login.php b/0.8.1-rc1/balance/modules/puny/scripts/login.php
new file mode 100644
index 0000000..b638fe4
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/scripts/login.php
@@ -0,0 +1,52 @@
+<?php
+/*
+ * 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.
+ */
+
+// Include the main Puny class
+require_once(App::Get()->settings['puny_module_path'] . '/classes/Puny.class.php');
+
+// Get the configured editor username / password
+$punyUsername = App::Get()->settings['puny_editor_username'];
+$punyPassword = App::Get()->settings['puny_editor_password'];
+
+// Get the provided credentials from the POST request
+$username = $_POST['username'];
+$password = $_POST['password'];
+
+// Ensure that the editor credentials are properly configured in config.ini
+if ( !($punyUsername && $punyPassword) ) {
+	$_SESSION['puny_error'] = "Unable to launch Puny because the Puny "
+		. "admin credentials are not configured properly.";
+	App::Get()->redirect(App::Get()->settings['puny_module_root'] . '/error');
+}
+
+// Test the provided values against the configured values
+if ( $username == $punyUsername && $password == $punyPassword ) {
+	// Login success
+	Puny::initializeEditorSession();
+	App::get()->redirect(SITE_ROOT . '/');
+} else {
+	// Login Failure...
+	$_SESSION['puny_error'] = "Invalid editor credentials provided...";
+	App::Get()->redirect(App::Get()->settings['puny_module_root'] . '/error');
+}
+
+exit();
+
+
+
+
diff --git a/0.8.1-rc1/balance/modules/puny/scripts/logout.php b/0.8.1-rc1/balance/modules/puny/scripts/logout.php
new file mode 100644
index 0000000..b223fea
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/scripts/logout.php
@@ -0,0 +1,32 @@
+<?php
+/*
+ * 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.
+ */
+
+// Parse the Puny config file
+$module = App::Get()->loadModule();
+
+// Include the main Puny class
+require_once(App::Get()->settings['puny_module_path'] . '/classes/Puny.class.php');
+
+// Destroy the editor session
+Puny::destroyEditorSession();
+
+// Redirect home
+App::Get()->redirect(SITE_ROOT . '/');
+
+exit();
+
diff --git a/0.8.1-rc1/balance/modules/puny/scripts/store.php b/0.8.1-rc1/balance/modules/puny/scripts/store.php
new file mode 100644
index 0000000..3d3665a
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/scripts/store.php
@@ -0,0 +1,40 @@
+<?php
+/*
+ * 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.
+ */
+
+// Parse the Puny config file
+$module = App::Get()->loadModule();
+
+// Include the main Puny class
+require_once(App::Get()->settings['puny_module_path'] . '/classes/Puny.class.php');
+
+// Get the resource id from the request parameters
+$resourceId = $_POST['resourceId'];
+$content    = $_POST['content'];
+
+// Load the requested resource and update the content
+$resource = Puny::load($resourceId)->setContent($content);
+
+// Store the updated content as a new version
+Puny::store($resource);
+
+// we're done :)
+echo json_encode(array(
+	"status"     => "ok"
+	, "resourceId" => $resourceId
+	, "version"    => $resource->getVersion()
+	, "parsedContent" => $resource->parse()->getContent()));
diff --git a/0.8.1-rc1/balance/modules/puny/static/css/defaults.css b/0.8.1-rc1/balance/modules/puny/static/css/defaults.css
new file mode 100644
index 0000000..41f89c0
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/css/defaults.css
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+@CHARSET "UTF-8";
+
+/* Puny Module Default Style */
+
+[puny] blockquote {
+	margin:20px 40px;
+}
+[puny] code {
+	font-family: monospace;
+}
+[puny] em {
+	font-style: italic;
+}
+[puny] ol {
+	list-style: decimal;
+}
+[puny] ul {
+	list-style: disc;
+}
+[puny] strong {
+	font-weight: bold;
+}
diff --git a/0.8.1-rc1/balance/modules/puny/static/css/dialog.css b/0.8.1-rc1/balance/modules/puny/static/css/dialog.css
new file mode 100644
index 0000000..da0b083
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/css/dialog.css
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+ 
+/* @control dialog */
+
+#gollum-dialog-dialog {
+  display: block;
+  overflow: visible;
+  position: absolute;
+  left: 50%;
+}
+
+#gollum-dialog-dialog.active {
+  display: block;
+}
+
+#gollum-dialog-dialog-inner {
+  margin: 0 0 0 -225px;
+  position: relative;
+  width: 450px;
+
+  border: 7px solid #999;
+  border: 7px solid rgba(0, 0, 0, 0.3); 
+  border-radius: 5px;
+  -moz-border-radius: 5px;
+  -webkit-border-radius: 5px;
+}
+
+#gollum-dialog-dialog-bg {
+  background-color: #fff;
+  overflow: hidden;
+  padding: 1em;
+  
+  background: -webkit-gradient(linear, left top, left bottom, from(#f7f7f7), to(#ffffff));
+  background: -moz-linear-gradient(top, #f7f7f7, #ffffff);
+}
+
+#gollum-dialog-dialog-inner h4 {
+  border-bottom: 1px solid #ddd;
+  color: #000;
+  font-size: 1.8em;
+  line-height: normal;
+  font-weight: bold;
+  margin: 0 0 0.75em 0;
+  padding: 0 0 0.3em 0;
+}
+
+#gollum-dialog-dialog-body {
+  font-size: 1.2em;
+  line-height: 1.6em;
+}
+
+#gollum-dialog-dialog-body fieldset {
+  display: block;
+  border: 0;
+  margin: 0;
+  overflow: hidden;
+  padding: 0;
+}
+
+#gollum-dialog-dialog-body fieldset .field {
+  margin: 0 0 1.5em 0;
+  padding: 0;
+}
+
+  #gollum-dialog-dialog-body fieldset .field label {
+    color: #000;
+    display: block;
+    font-size: 1.2em;
+    font-weight: bold;
+    line-height: 1.6em;
+    margin: 0;
+    padding: 0;
+    min-width: 80px;
+  }
+  
+  #gollum-dialog-dialog-body fieldset .field input[type="text"] {
+    border: 1px solid #ddd;
+    display: block;
+    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+    font-size: 1.2em;
+    line-height: 1.6em;
+    margin: 0.3em 0 0 0;
+    padding: 0.3em 0.5em;
+    width: 96.5%;
+  }
+  
+  #gollum-dialog-dialog-body fieldset .field input.code {
+    font-family: 'Monaco', 'Courier New', Courier, monospace;
+  }
+  
+#gollum-dialog-dialog-body fieldset .field:last-child {
+  margin: 0 0 1em 0;
+}
+
+#gollum-dialog-dialog-buttons {
+  border-top: 1px solid #ddd;
+  overflow: hidden;
+  margin: 1.5em 0 0 0;
+  padding: 1em 0 0 0;
+}
+
+#gollum-dialog-dialog a.minibutton {
+  float: right;
+  margin-right: 0.5em;
+  width: auto;
+}
+
+#gollum-dialog-dialog a.minibutton,
+#gollum-dialog-dialog a.minibutton:visited {
+  background-color: #f7f7f7;
+  border: 1px solid #d4d4d4;
+  color: #333;
+  cursor: pointer;
+  display: block;
+  font-size: 1.2em;
+  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+  font-weight: bold;
+  margin: 0 0 0 0.8em;
+  padding: 0.4em 1em;
+
+  text-shadow: 0 1px 0 #fff;
+
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f4f4f4', endColorstr='#ececec');
+  background: -webkit-gradient(linear, left top, left bottom, from(#f4f4f4), to(#ececec));
+  background: -moz-linear-gradient(top, #f4f4f4, #ececec);
+
+  border-radius: 3px;
+  -moz-border-radius: 3px;
+  -webkit-border-radius: 3px;
+}
+
+#gollum-dialog-dialog a.minibutton:hover {
+  background: #3072b3;
+  border-color: #518cc6 #518cc6 #2a65a0;
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
+  text-decoration: none;
+
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#599bdc', endColorstr='#3072b3');
+  background: -webkit-gradient(linear, left top, left bottom, from(#599bdc), to(#3072b3));
+  background: -moz-linear-gradient(top, #599bdc, #3072b3);
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/static/css/editor.css b/0.8.1-rc1/balance/modules/puny/static/css/editor.css
new file mode 100644
index 0000000..f6175fa
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/css/editor.css
@@ -0,0 +1,567 @@
+/*
+ * 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.
+ */
+
+/*
+  editor.css
+  Wiki editor formatting
+*/
+
+a {
+  -moz-outline: none !important;
+}
+
+.jaws {
+  /* JAWS should see it, but you can't */
+  display: block;
+  height: 1px;
+  left: -5000px;
+  overflow: hidden;
+  position: absolute;
+  top: -5000px;
+  width: 1px;
+}
+
+#gollum-editor {
+  border: 1px solid #e4e4e4;
+  background: #f9f9f9;
+  margin: 1em 0 5em;
+  overflow: hidden;
+  padding: 1em 1em 0.4em;
+
+  border-radius: 1em;
+  -moz-border-radius: 1em;
+  -webkit-border-radius: 1em;
+}
+
+.ie #gollum-editor {
+  padding-bottom: 1em;  
+}
+
+#gollum-editor form fieldset {
+  border: 0;
+  margin: 0;
+  padding: 0;
+  width: 100%;
+}
+
+#gollum-editor .singleline {
+  display: block;
+  margin: 0 0 0.7em 0;
+  overflow: hidden;
+}
+
+#gollum-editor .singleline input {
+  background: #fff;
+  border: 1px solid #ddd;
+  color: #000;
+  font-size: 1.3em;
+  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+  line-height: 1.8em;
+  margin: 1em 0 0.4em;
+  padding: 0.5em;
+  width: 98%;
+}
+
+#gollum-editor .singleline input.ph {
+  color: #999;
+}
+
+#gollum-editor-title-field input#gollum-editor-page-title {
+  font-weight: bold;
+  margin-top: 0;
+}
+
+#gollum-editor-title-field.active {
+  border-bottom: 1px solid #ddd;
+  display: block;
+  margin: 0 0 0.3em 0;
+  padding: 0 0 0.5em 0;
+}
+
+#gollum-editor-title-field input#gollum-editor-page-title.ph {
+  color: #000;
+}
+
+/* @control editor-view-tab */
+#gollum-editor #gollum-editor-type-switcher {
+  display: none;
+}
+
+/* @control function-bar */
+#gollum-editor #gollum-editor-function-bar  {
+  border-bottom: 1px solid #ddd;
+  overflow: hidden;
+  padding: 0;
+}
+
+
+#gollum-editor-title-field + #gollum-editor-function-bar {
+  margin-top: 0.6em;
+}
+
+#gollum-editor #gollum-editor-function-bar #gollum-editor-function-buttons {
+  /* display: none; */
+}
+
+#gollum-editor #gollum-editor-function-bar.active #gollum-editor-function-buttons {
+  display: block;
+  float: left;
+  overflow: hidden;
+  padding: 0 0 1.1em 0;
+}
+
+#gollum-editor #gollum-editor-function-bar a.function-button {
+  background: #f7f7f7;
+  border: 1px solid #ddd;
+  color: #333;
+  display: block;
+  float: left;
+  height: 25px;
+  overflow: hidden;
+  margin: 0.2em 0.5em 0 0;
+  /* text-indent: -5000px; */
+  text-shadow: 0 1px 0 #fff;
+  width: 25px;
+  
+  border-radius: 0.3em;
+  -moz-border-radius: 0.3em;
+  -webkit-border-radius: 0.3em;
+  
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f4f4f4', endColorstr='#ececec');
+  background: -webkit-gradient(linear, left top, left bottom, from(#f4f4f4), to(#ececec));
+  background: -moz-linear-gradient(top, #f4f4f4, #ececec);
+}
+
+#gollum-editor #gollum-editor-function-bar a.function-button:hover {
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
+  text-decoration: none;
+  
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#599bdc', endColorstr='#3072b3');
+  background: -webkit-gradient(linear, left top, left bottom, from(#599bdc), to(#3072b3));
+  background: -moz-linear-gradient(top, #599bdc, #3072b3);
+}
+
+#gollum-editor #gollum-editor-function-bar a span {
+  background-image: url(../img/icon-sprite.png);
+  background-repeat: no-repeat;
+  display: block;
+  height: 25px;
+  overflow: hidden;
+  text-indent: -5000px;
+  width: 25px;
+}
+
+a#function-bold span { background-position: 0 0; }
+a#function-italic span { background-position: -27px 0; }
+a#function-underline span { background-position: -54px 0; }
+a#function-code span { background-position: -82px 0; }
+a#function-ul span { background-position: -109px 0; }
+a#function-ol span { background-position: -136px 0; }
+a#function-blockquote span { background-position: -163px 0; }
+a#function-hr span { background-position: -190px 0; }
+a#function-h1 span { background-position: -217px 0; }
+a#function-h2 span { background-position: -244px 0; }
+a#function-h3 span { background-position: -271px 0; }
+a#function-link span { background-position: -298px 0; }
+a#function-image span { background-position: -324px 0; }
+a#function-help span { background-position: -405px 0; } 
+
+a#function-bold:hover span { background-position: 0 -28px; }
+a#function-italic:hover span { background-position: -27px -28px; }
+a#function-underline:hover span { background-position: -54px -28px; }
+a#function-code:hover span { background-position: -82px -28px; }
+a#function-ul:hover span { background-position: -109px -28px; }
+a#function-ol:hover span { background-position: -136px -28px; }
+a#function-blockquote:hover span { background-position: -163px -28px; }
+a#function-hr:hover span { background-position: -190px -28px; }
+a#function-h1:hover span { background-position: -217px -28px; }
+a#function-h2:hover span { background-position: -244px -28px; }
+a#function-h3:hover span { background-position: -271px -28px; }
+a#function-link:hover span { background-position: -298px -28px; }
+a#function-image:hover span { background-position: -324px -28px; }
+a#function-help:hover span { background-position: -405px -28px; } 
+
+
+#gollum-editor #gollum-editor-function-bar a.disabled {
+  display: none;
+}
+
+#gollum-editor #gollum-editor-function-bar span.function-divider {
+  display: block;
+  float: left;
+  width: 0.5em;
+}
+
+#gollum-editor #gollum-editor-function-bar #gollum-editor-format-selector {
+  overflow: hidden;
+  padding: 0 0 1.1em 0;
+}
+
+#gollum-editor #gollum-editor-function-bar 
+  #gollum-editor-format-selector select {  
+  background-color: #f9f9f9;
+  border: 1px solid transparent;
+  
+  float: right;
+  font-size: 1.1em;
+  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+  font-weight: bold;
+  line-height: 1.6em;
+  padding: 0.5em 0.7em;
+  margin-bottom: 0;
+ 
+ 
+  border-radius: 0.5em;
+  -moz-border-radius: 0.5em;
+  -webkit-border-radius: 0.5em; 
+  -moz-outline: none;
+}
+
+#gollum-editor #gollum-editor-function-bar 
+  #gollum-editor-format-selector select:hover {
+  background-color: #fff;
+  border: 1px solid #ddd;
+  -moz-outline: none;
+}
+
+#gollum-editor #gollum-editor-function-bar
+  #gollum-editor-format-selector label {
+  color: #999;
+  float: right;
+  font-size: 1.1em;
+  font-weight: bold;
+  line-height: 1.6em;
+  padding: 0.6em 0.5em 0 0;
+}
+  
+#gollum-editor #gollum-editor-function-bar
+  #gollum-editor-format-selector label:after {
+  content: ':';
+}
+  
+  
+/* @section form-fields */
+
+body {
+font: 13px Helvetica,arial,freesans,clean,sans-serif;
+line-height: 1.4;
+color: #333;
+position: relative;
+padding: 0;
+width: 100%;
+z-index: 9;
+display: block;
+margin: 0 auto;
+}
+
+#gollum-editor textarea#gollum-editor-body {
+  background: #fff;
+  border: 1px solid #ddd;
+  font-size: 1.3em;
+  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+  line-height: 1.8em;
+  margin: 1em 0 0.4em;
+  padding: 0.5em; /* I don't really like mixing pct & em hereÉ */
+  width: 100%;
+  height: 20em;
+}
+
+#gollum-editor input.gollum-editor-input {
+  background-color: #f7f7f7;
+  border: 1px solid #d4d4d4;
+  color: #333;
+  cursor: pointer;
+  display: block;
+  float: left;
+  font-size: 1.2em;
+  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+  font-weight: bold;
+  height: 35px;
+  margin: 0px 5px;
+  padding: 0.4em 1em;
+
+  text-shadow: 0 1px 0 #fff;
+
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f4f4f4', endColorstr='#ececec');
+  background: -webkit-gradient(linear, left top, left bottom, from(#f4f4f4), to(#ececec));
+  background: -moz-linear-gradient(top, #f4f4f4, #ececec);
+
+  border-radius: 3px;
+  -moz-border-radius: 3px;
+  -webkit-border-radius: 3px;
+}
+
+.webkit #gollum-editor input#gollum-editor-submit {
+  padding: 0.5em 1em 0.45em;
+}
+
+.ie #gollum-editor input#gollum-editor-submit {
+  padding: 0.4em 1em 0.5em;
+}
+
+#gollum-editor input#gollum-editor-submit:hover {
+  background: #3072b3;
+  border-color: #518cc6 #518cc6 #2a65a0;
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
+  text-decoration: none;
+
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#599bdc', endColorstr='#3072b3');
+  background: -webkit-gradient(linear, left top, left bottom, from(#599bdc), to(#3072b3));
+  background: -moz-linear-gradient(top, #599bdc, #3072b3);
+}
+
+#gollum-editor .collapsed,
+#gollum-editor .expanded {
+  border-bottom: 1px solid #ddd;
+  display: block;
+  overflow: hidden;
+  padding: 1em 0 0.5em;
+}
+
+#gollum-editor #gollum-editor-body + .collapsed,
+#gollum-editor #gollum-editor-body + .expanded {
+  border-top: 1px solid #ddd;
+  margin-top: 0.7em;
+}
+
+#gollum-editor .collapsed a.button,
+#gollum-editor .expanded a.button {
+  background: #f7f7f7;
+  border: 1px solid #ddd;
+  color: #333;
+  display: block;
+  float: left;
+  height: 25px;
+  overflow: hidden;
+  margin: 0.2em 0.5em 0.75em 0;
+  text-shadow: 0 1px 0 #fff;
+  width: 25px;
+  
+  border-radius: 0.3em;
+  -moz-border-radius: 0.3em;
+  -webkit-border-radius: 0.3em;
+  
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f4f4f4', endColorstr='#ececec');
+  background: -webkit-gradient(linear, left top, left bottom, from(#f4f4f4), to(#ececec));
+  background: -moz-linear-gradient(top, #f4f4f4, #ececec);
+}
+
+#gollum-editor .collapsed h4,
+#gollum-editor .expanded h4 {
+  font-size: 1.6em;
+  float: left;
+  margin: 0;
+  padding: 0.4em 0 0 0.3em;
+  text-shadow: 0 -1px 0 #fff;
+}
+
+#gollum-editor .collapsed a.button:hover,
+#gollum-editor .expanded h4 a.button:hover {
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
+  text-decoration: none;
+  
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#599bdc', endColorstr='#3072b3');
+  background: -webkit-gradient(linear, left top, left bottom, from(#599bdc), to(#3072b3));
+  background: -moz-linear-gradient(top, #599bdc, #3072b3);
+}
+
+#gollum-editor .collapsed a span,
+#gollum-editor .expanded a span {
+  background-image: url(../img/icon-sprite.png);
+  background-position: -351px -1px;
+  background-repeat: no-repeat;
+  display: block;
+  height: 25px;
+  overflow: hidden;
+  text-indent: -5000px;
+  width: 25px;
+}
+
+#gollum-editor .collapsed a:hover span {
+  background-position: -351px -28px;
+}
+
+#gollum-editor .expanded a span {
+  background-position: -378px 0;
+}
+
+#gollum-editor .expanded a:hover span {
+  background-position: -378px -28px;
+}
+
+#gollum-editor .collapsed textarea {
+  display: none;
+}
+
+#gollum-editor .expanded textarea {
+  background-color: #fff;
+  border: 1px solid #ddd;
+  clear: both;
+  display: block;
+  font-size: 1.3em;
+  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+  height: 7em;
+  line-height: 1.8em;
+  margin: 0.7em 0;
+  padding: 0.5em;
+  width: 98%;
+}
+
+/* @control minibutton */
+
+#gollum-editor a.minibutton,
+#gollum-editor a.minibutton:visited {
+  background-color: #f7f7f7;
+  border: 1px solid #d4d4d4;
+  color: #333;
+  cursor: pointer;
+  display: block;
+  font-size: 1.2em;
+  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+  font-weight: bold;
+  line-height: 1.2em;
+  margin: 0 0 0 0.8em;
+  padding: 0.5em 1em;
+
+  text-shadow: 0 1px 0 #fff;
+
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f4f4f4', endColorstr='#ececec');
+  background: -webkit-gradient(linear, left top, left bottom, from(#f4f4f4), to(#ececec));
+  background: -moz-linear-gradient(top, #f4f4f4, #ececec);
+
+  border-radius: 3px;
+  -moz-border-radius: 3px;
+  -webkit-border-radius: 3px;
+}
+
+#gollum-editor a.minibutton:hover {
+  background: #3072b3;
+  border-color: #518cc6 #518cc6 #2a65a0;
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
+  text-decoration: none;
+
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#599bdc', endColorstr='#3072b3');
+  background: -webkit-gradient(linear, left top, left bottom, from(#599bdc), to(#3072b3));
+  background: -moz-linear-gradient(top, #599bdc, #3072b3);
+}
+
+
+#gollum-editor #gollum-editor-preview {
+  float: left;
+  font-weight: normal;
+  padding: left;
+}
+
+
+/* @section help */
+#gollum-editor-help {
+  margin: 0;
+  overflow: hidden;
+  padding: 0;
+  border: 1px solid #ddd;
+  border-width: 0 1px 1px 1px;
+}
+
+  #gollum-editor-help-parent,
+  #gollum-editor-help-list {
+    display: block;
+    float: left;
+    height: 17em;
+    list-style-type: none;
+    overflow: auto;
+    margin: 0;
+    padding: 1em 0;
+    width: 18%;
+  }
+  
+  #gollum-editor-help-parent {
+    border-right: 1px solid #eee;
+  }
+  
+  #gollum-editor-help-list {
+    background: #fafafa;
+    border-right: 1px solid #eee;
+  }
+  
+  #gollum-editor-help-parent li,
+  #gollum-editor-help-list li {
+    font-size: 1.2em;
+    line-height: 1.6em;
+    margin: 0;
+    padding: 0;
+  }
+    
+    #gollum-editor-help-parent li a,
+    #gollum-editor-help-list li a {
+      border: 1px solid transparent;
+      border-width: 1px 0;
+      display: block;
+      font-weight: bold;
+      height: 10%;
+      width: auto;
+      padding: 0.2em 1em;
+      text-shadow: 0 -1px 0 #fff;
+    }
+    
+    #gollum-editor-help-parent li a:hover,
+    #gollum-editor-help-list li a:hover {
+      background: #fff;
+      border-color: #f0f0f0;
+      text-decoration: none;
+      
+      box-shadow: none;
+    }
+    
+    #gollum-editor-help-parent li a.selected,
+    #gollum-editor-help-list li a.selected {
+      border: 1px solid #eee;
+      border-bottom-color: #e7e7e7;
+      border-width: 1px 0;
+      background: #fff;
+      color: #000;
+      
+      box-shadow: 0 1px 2px #f0f0f0;
+    }
+    
+  #gollum-editor-help-wrapper {
+    background: #fff;
+    overflow: auto;
+    height: 17em;
+    padding: 1em;
+  }
+  
+    #gollum-editor-help-content {
+      font-size: 1.2em;
+      margin: 0 1em 0 0.5em;
+      padding: 0;
+      line-height: 1.8em;
+    }
+    
+    #gollum-editor-help-content p {
+      margin: 0 0 1em 0;
+      padding: 0;
+    }
+    
+/* IE */
+.ie #gollum-editor .singleline input {
+  padding-top: 0.25em;
+  padding-bottom: 0.75em;
+}
diff --git a/0.8.1-rc1/balance/modules/puny/static/css/github.css b/0.8.1-rc1/balance/modules/puny/static/css/github.css
new file mode 100644
index 0000000..96d19c1
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/css/github.css
@@ -0,0 +1,677 @@
+/*
+ * 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.
+ */
+
+#wiki-wrapper #template blockquote {
+  margin: 1em 0;
+  border-left: 4px solid #ddd;
+  padding-left: .8em;
+  color: #555;
+}
+
+/*
+  gollum.css
+  A basic stylesheet for Gollum
+*/
+
+/* @section core */
+body, html {
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 10px;
+  margin: 0;
+  padding: 0;
+}
+
+#wiki-wrapper {
+  margin: 0 auto;
+  overflow: visible;
+  width: 90%;
+}
+
+a:link {
+  color: #4183c4;
+  text-decoration: none;
+}
+
+a:hover, a:visited {
+  color: #4183c4;
+  text-decoration: underline;
+}
+
+
+/* @section head */
+#head {
+  margin: 4.5em 0 0.5em;
+  padding: 0.5em 0;
+  overflow: hidden;
+}
+
+  #head h1 {
+     /* display: none; */
+  }
+  
+  #head ul.actions {
+    float: right;
+  }
+  
+/* @section content */
+#wiki-content {
+  height: 1%;
+  overflow: visible;
+}
+
+  #wiki-content .wrap {
+    height: 1%;
+    overflow: auto;
+  }
+
+  /* @section comments */
+  #wiki-body #inline-comment {
+    display: none; /* todo */
+  }
+
+  /* @section body */
+  #wiki-body {
+    display: block;
+    float: left;
+    margin-right: 3%;
+    width: 100%;
+  }
+
+  .has-rightbar #wiki-body {
+    width: 68%;
+  }
+  
+  /* @section rightbar */
+  #wiki-rightbar {
+    background-color: #f7f7f7;
+    border: 1px solid #ddd;
+    font-size: 13px;
+    float: right;
+    padding: 7px;
+    width: 25%;
+    
+    border-radius: 0.5em;
+    -moz-border-radius: 0.5em;
+    -webkit-border-radius: 0.5em;
+  }
+  
+    #wiki-rightbar p {
+      margin: 13px 0 0;
+    }
+
+      #wiki-rightbar > p:first-child {
+        margin-top: 0;
+      }
+
+    #wiki-rightbar p.parent {
+      border-bottom: 1px solid #bbb;
+      font-weight: bold;
+      margin: 0 0 0.5em 0;
+      padding: 0 0 0.5em 0;
+      text-shadow: 0 1px 0 #fff;
+    }
+    
+    /* Back arrow */
+    #wiki-rightbar p.parent:before {
+      color: #666;
+      content: "<-- ";
+    }
+    
+    #wiki-rightbar h3 {
+      font-size: 1.2em;
+      color: #333;
+      margin: 1.2em 0 0;
+      padding: 0;
+      text-shadow: 0 1px 0 #fff;
+    }
+    
+    #wiki-rightbar ul {
+      margin: 0.5em 0 1em;
+      padding: 0;
+    }
+    
+    #wiki-rightbar ul li {
+      color: #bbb;
+      margin: 0 0 0 1em;
+      padding: 0;
+      line-height: 1.75em;
+      list-style-position: inside;
+      list-style-type: round;
+    } 
+    
+    #wiki-rightbar #nav ul li a {
+      font-weight: bold;
+      text-shadow: 0 1px 0 #fff;
+    }
+    
+  /* @section footer */
+  #wiki-footer {
+    clear: both;
+    margin: 2em 0 5em;
+  }
+  
+    .has-rightbar #wiki-footer {
+      width: 70%;
+    }
+    
+    #wiki-footer #footer-content {
+      background-color: #f7f7f7;
+      border: 1px solid #ddd;
+      font-size: 1.2em;
+      line-height: 1.5em;
+      margin-top: 1.5em;
+      padding: 1em;
+      
+      border-radius: 0.5em;
+      -moz-border-radius: 0.5em;
+      -webkit-border-radius: 0.5em;
+    }
+    
+    #wiki-footer #footer-content h3 {
+      font-size: 1.2em;
+      color: #333;
+      margin: 0;
+      padding: 0 0 0.2em;
+      text-shadow: 0 1px 0 #fff;
+    }
+    
+    #wiki-footer #footer-content p {
+      margin: 0.5em 0 0;
+      padding: 0;
+    }
+    
+    #wiki-footer #footer-content ul.links {
+      margin: 0.5em 0 0;
+      overflow: hidden;
+      padding: 0;
+    }
+    
+    #wiki-footer #footer-content ul.links li {
+      color: #999;
+      float: left;
+      list-style-position: inside;
+      list-style-type: square;
+      padding: 0;
+      margin-left: 0.75em;
+    }
+    
+    #wiki-footer #footer-content ul.links li a {
+      font-weight: bold;
+      text-shadow: 0 1px 0 #fff;
+    }
+    
+    #wiki-footer #footer-content ul.links li:first-child {
+      list-style-type: none;
+      margin: 0;
+    }  
+    
+    .ff #wiki-footer #footer-content ul.links li:first-child {
+      margin: 0 -0.75em 0 0;
+    }
+  
+  /* @section page-footer */
+  .page #footer {
+    margin: 1em 0 7em;
+  }
+  
+  #footer p#last-edit {
+    font-size: .9em;
+    line-height: 1.6em;
+    color: #999;
+    margin: 0.9em 0;
+  }
+  
+    #footer p#last-edit span.username {
+      font-weight: bold;
+    }
+
+
+/* @section history */
+.history h1 {
+  color: #999;
+  font-weight: normal;
+}
+
+  .history h1 strong {
+    color: #000;
+    font-weight: bold;
+  }
+
+#wiki-history {
+  margin-top: 3em;
+}
+
+  #wiki-history fieldset {
+    border: 0;
+    margin: 2em 0;
+    padding: 0;
+  }
+  
+  #wiki-history table, #wiki-history tbody {
+    border-collapse: collapse;
+    padding: 0;
+    margin: 0;
+    width: 100%;
+  }
+  
+  #wiki-history table tr {
+    padding: 0;
+    margin: 0;
+  }
+  
+  #wiki-history table tr {
+    background-color: #ebf2f6;
+  }
+  
+  #wiki-history table tr td {
+    border: 1px solid #c0dce9;
+    font-size: 1.2em;
+    line-height: 1.6em;
+    margin: 0;
+    padding: 0.3em 0.7em;
+  }
+  
+  #wiki-history table tr td.checkbox {
+    min-width: 2em;
+    padding: 0.3em;
+  }
+  
+  #wiki-history table tr td.checkbox input {
+    cursor: pointer;
+    display: block;
+    padding-right: 0;
+    padding-top: 0.4em;
+    margin-right: -0.2em;
+  }
+  
+  #wiki-history table tr:nth-child(2n),
+  #wiki-history table tr.alt-row {
+    background-color: #f3f7fa;
+  }
+  
+  #wiki-history table tr.selected {
+    background-color: #ffffea !important;
+    z-index: 100;
+  }
+  
+  #wiki-history table tr td.commit-name {
+    border-left: 0;
+  }
+  
+  #wiki-history table tr td.commit-name span.time-elapsed {
+    color: #999;
+  }
+  
+  #wiki-history table tr td.author {
+    width: 20%;
+  }
+  
+  #wiki-history table tr td.author a {
+    color: #000;
+    font-weight: bold;
+  }
+  
+  #wiki-history table tr td.author a span.username {
+    display: block;
+    padding-top: 3px;
+  }
+  
+  #wiki-history table tr td img {
+    background-color: #fff;
+    border: 1px solid #999;
+    display: block;
+    float: left;
+    height: 18px;
+    overflow: hidden;
+    margin: 0 0.5em 0 0;
+    width: 18px;
+    padding: 2px;
+  }
+  
+  #wiki-history table tr td.commit-name a {
+    font-size: 0.9em;
+    font-family: 'Monaco', 'Andale Mono', Consolas, 'Courier New', monospace;
+    padding: 0 0.2em;
+  }
+
+.history #wiki-history ul.actions li,
+.history #footer ul.actions li {
+  margin: 0 0.6em 0 0;
+}
+
+
+/* @section edit */
+.edit h1 {
+  color: #999;
+  font-weight: normal;
+}
+
+  .edit h1 strong {
+    color: #000;
+    font-weight: bold;
+  }
+
+
+/* @section search */
+.results h1 {
+  color: #999;
+  font-weight: normal;
+}
+
+  .results h1 strong {
+    color: #000;
+    font-weight: bold;
+  }
+  
+  .results #results {
+    border-bottom: 1px solid #ccc;
+    margin-bottom: 2em;
+    padding-bottom: 2em;
+  }
+  
+  .results #results ul {
+    margin: 2em 0 0 0;
+    padding: 0;
+  }
+  
+    .results #results ul li {
+      font-size: 1.2em;
+      line-height: 1.6em;
+      list-style-position: outside;
+      padding: 0.2em 0;
+    }
+    
+    .results #results ul li span.count {
+      color: #999;
+    }
+
+  .results p#no-results {
+    font-size: 1.2em;
+    line-height: 1.6em;
+    margin-top: 2em;
+  }
+  
+  .results #footer ul.actions li {
+    margin: 0 1em 0 0;
+  }
+  
+
+/* @section compare */
+.compare h1 {
+  color: #999;
+  font-weight: normal;
+}
+
+  .compare h1 strong {
+    color: #000;
+    font-weight: bold;
+  }
+  
+  .compare #compare-content {
+    margin-top: 3em;
+  }
+  
+  .compare .data {
+    border: 1px solid #ddd;
+    margin-top: 1em;
+    overflow: auto;
+  }
+  
+  .compare .data pre {
+    margin: 0;
+    padding: 0;
+  }
+  
+  .compare .data pre div {
+    padding: 0 0 0 1em;
+  }
+  
+  .compare .data tr td {
+    font-family: "Consolas", "Monaco", "Andale Mono", "Courier New", monospace;
+    font-size: 1.2em;
+    line-height: 1.8em;
+    margin: 0;
+    padding: 0;
+  }
+  
+  .compare .data td.line_numbers {
+    background: #f7f7f7;
+    border-right: 1px solid #999;
+    color: #999; 
+    padding: 0 0 0 0.5em;
+  }
+
+.compare #compare-content ul.actions li,
+.compare #footer ul.actions li {
+  margin-left: 0;
+  margin-right: 0.6em;
+}
+  
+  
+  
+/* @control syntax */
+.highlight  { background: #ffffff; }
+.highlight .c { color: #999988; font-style: italic } 
+.highlight .err { color: #a61717; background-color: #e3d2d2 } 
+.highlight .k { font-weight: bold } 
+.highlight .o { font-weight: bold } 
+.highlight .cm { color: #999988; font-style: italic } 
+.highlight .cp { color: #999999; font-weight: bold } 
+.highlight .c1 { color: #999988; font-style: italic } 
+.highlight .cs { color: #999999; font-weight: bold; font-style: italic } 
+.highlight .gd { color: #000000; background-color: #ffdddd } 
+.highlight .gd .x { color: #000000; background-color: #ffaaaa } 
+.highlight .ge { font-style: italic } 
+.highlight .gr { color: #aa0000 } 
+.highlight .gh { color: #999999 } 
+.highlight .gi { color: #000000; background-color: #ddffdd } 
+.highlight .gi .x { color: #000000; background-color: #aaffaa } 
+.highlight .gc { color: #999; background-color: #EAF2F5 }
+.highlight .go { color: #888888 } 
+.highlight .gp { color: #555555 } 
+.highlight .gs { font-weight: bold } 
+.highlight .gu { color: #aaaaaa } 
+.highlight .gt { color: #aa0000 } 
+
+
+/* @control minibutton */
+ul.actions {
+   display: block;
+   list-style-type: none;
+   overflow: hidden;
+   padding: 0;
+}
+
+ ul.actions li {
+   float: left;
+   font-size: 1.2em;
+   margin-left: 0.6em;
+ }
+
+.minibutton a {
+  background-color: #f7f7f7;
+  border: 1px solid #d4d4d4;
+  color: #333;
+  display: block;
+  font-weight: bold;
+  margin: 0;
+  padding: 0.4em 1em;
+  height: 1.4em;
+
+  text-shadow: 0 1px 0 #fff;
+
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f4f4f4', endColorstr='#ececec');
+  background: -webkit-gradient(linear, left top, left bottom, from(#f4f4f4), to(#ececec));
+  background: -moz-linear-gradient(top, #f4f4f4, #ececec);
+
+  border-radius: 3px;
+  -moz-border-radius: 3px;
+  -webkit-border-radius: 3px;
+}
+
+#search-submit {
+  background-color: #f7f7f7;
+  border: 1px solid #d4d4d4;
+  color: #333;
+  display: block;
+  font-weight: bold;
+  margin: 0;
+  padding: 0.4em 1em;
+
+  text-shadow: 0 1px 0 #fff;
+
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f4f4f4', endColorstr='#ececec');
+  background: -webkit-gradient(linear, left top, left bottom, from(#f4f4f4), to(#ececec));
+  background: -moz-linear-gradient(top, #f4f4f4, #ececec);
+
+  border-radius: 3px;
+  -moz-border-radius: 3px;
+  -webkit-border-radius: 3px;
+}
+
+.minibutton a:hover,
+#search-submit:hover {
+  background: #3072b3;
+  border-color: #518cc6 #518cc6 #2a65a0;
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
+  text-decoration: none;
+
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#599bdc', endColorstr='#3072b3');
+  background: -webkit-gradient(linear, left top, left bottom, from(#599bdc), to(#3072b3));
+  background: -moz-linear-gradient(top, #599bdc, #3072b3);
+}
+
+.minibutton a:visited {
+  text-decoration: none;
+}
+
+
+/* @special error */
+#wiki-wrapper.error {
+  height: 1px;
+  position: absolute;
+  overflow: visible;
+  top: 50%;
+  width: 100%;
+}
+
+#error {
+  background-color: #f9f9f9;
+  border: 1px solid #e4e4e4;
+  left: 50%;
+  overflow: hidden;
+  padding: 2%;
+  margin: -10% 0 0 -35%;
+  position: absolute;
+  width: 70%;
+  
+  border-radius: 0.5em;
+  -moz-border-radius: 0.5em;
+  -webkit-border-radius: 0.5em;
+}
+
+#error h1 {
+  font-size: 3em;
+  line-height: normal;
+  margin: 0;
+  padding: 0;
+}
+
+#error p {
+  font-size: 1.2em;
+  line-height: 1.6em;
+  margin: 1em 0 0.5em;
+  padding: 0;
+}
+
+
+/* @control searchbar */
+#head #searchbar {
+  float: right;
+  margin: 1em 0 0 0;
+  padding: 0;
+  overflow: hidden;
+}
+
+  #head #searchbar #searchbar-fauxtext {
+    background: #fff;
+    border: 1px solid #d4d4d4;
+    overflow: hidden;
+    
+    border-radius: 0.3em;
+    -moz-border-radius: 0.3em;
+    -webkit-border-radius: 0.3em;
+  }
+
+  #head #searchbar #searchbar-fauxtext input#search-query {
+    border: none;
+    color: #000;
+    float: left;
+    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+    font-size: 1.2em;
+    height: 1.8em;
+    
+    -webkit-focus-ring: none;
+  }
+
+  .ff #head #searchbar #searchbar-fauxtext input#search-query {
+    padding: 0.2em 0 0.2em 0.5em;
+  }
+  
+  .ie #head #searchbar #searchbar-fauxtext input#search-query {
+    padding: 0.4em 0 0 0.5em;
+  }
+  
+  #head #searchbar #searchbar-fauxtext input#search-query.ph {
+    color: #999;
+  }
+  
+  #head #searchbar #searchbar-fauxtext #search-submit {
+    border: 0;
+    border-left: 1px solid #d4d4d4;
+    cursor: pointer;
+    margin: 0 !important;
+    padding: 0;
+    float: right;
+    font-size: 1.2em;
+    
+    border-radius: 0 3px 3px 0;
+    -moz-border-radius: 0 3px 3px 0;
+    -webkit-border-radius: 0 3px 3px 0;
+  }
+  
+  #head #searchbar #searchbar-fauxtext #search-submit span {
+    background-image: url(/images/icon-sprite.png);
+    background-position: -431px -1px;
+    background-repeat: no-repeat;
+    display: block;
+    height: 2em;
+    overflow: hidden;
+    text-indent: -5000px;
+    width: 28px;
+  }
+
+  .ff #head #searchbar #searchbar-fauxtext #search-submit span,
+  .ie #head #searchbar #searchbar-fauxtext #search-submit span {
+    height: 2.2em;
+  }
+
+  #head #searchbar #searchbar-fauxtext #search-submit:hover span {
+    background-position: -431px -28px;
+    padding: 0;
+  }
diff --git a/0.8.1-rc1/balance/modules/puny/static/css/puny.css b/0.8.1-rc1/balance/modules/puny/static/css/puny.css
new file mode 100644
index 0000000..68b3448
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/css/puny.css
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+@CHARSET "UTF-8";
+
+[puny] {
+	
+	background-color:#fcfae6 !important;
+	color:#222 !important;
+	
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	border-radius: 5px;
+}
+
+[puny] a {
+	color:#225 !important;
+}
diff --git a/0.8.1-rc1/balance/modules/puny/static/img/icon-sprite.png b/0.8.1-rc1/balance/modules/puny/static/img/icon-sprite.png
new file mode 100644
index 0000000..83e8c6f
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/img/icon-sprite.png
Binary files differ
diff --git a/0.8.1-rc1/balance/modules/puny/static/js/editable.js b/0.8.1-rc1/balance/modules/puny/static/js/editable.js
new file mode 100644
index 0000000..5d82c03
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/js/editable.js
@@ -0,0 +1,1090 @@
+/*
+ * 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.
+ */
+
+/**
+ *  gollum.editor.js
+ *  A jQuery plugin that creates the Gollum Editor.
+ *
+ *  Usage:
+ *  $.GollumEditor(); on DOM ready.
+ */
+(function($) {
+
+  // Editor options
+  var DefaultOptions = {
+    MarkupType: 'markdown',
+    EditorMode: 'code',
+    NewFile: false,
+    HasFunctionBar: true,
+    Debug: false,
+    NoDefinitionsFor: []
+  };
+  var ActiveOptions = {};
+
+  /**
+   *  $.GollumEditor
+   *
+   *  You don't need to do anything. Just run this on DOM ready.
+   */
+  $.GollumEditor = function( IncomingOptions ) {
+
+    ActiveOptions = $.extend( DefaultOptions, IncomingOptions );
+
+    debug('GollumEditor loading');
+
+    if ( EditorHas.baseEditorMarkup() ) {
+
+      if ( EditorHas.titleDisplayed() ) {
+        $('#gollum-editor-title-field').addClass('active');
+      }
+
+      if ( EditorHas.editSummaryMarkup() ) {
+        $.GollumEditor.Placeholder.add($('#gollum-editor-edit-summary input'));
+        $('#gollum-editor form[name="gollum-editor"]').submit(function( e ) {
+          e.preventDefault();
+          $.GollumEditor.Placeholder.clearAll();
+          debug('submitting');
+          $(this).unbind('submit');
+          $(this).submit();
+        });
+      }
+
+      if ( EditorHas.collapsibleInputs() ) {
+        $('#gollum-editor .collapsed a.button, ' +
+          '#gollum-editor .expanded a.button').click(function( e ) {
+          e.preventDefault();
+          $(this).parent().toggleClass('expanded');
+          $(this).parent().toggleClass('collapsed');
+        });
+      }
+
+      if ( EditorHas.previewButton() ) {
+        var formAction =
+        $('#gollum-editor #gollum-editor-preview').click(function() {
+          // make a dummy form, submit to new target window
+          // get form fields
+          var oldAction = $('#gollum-editor form').attr('action');
+          var $form = $($('#gollum-editor form').get(0));
+          $form.attr('action', this.href || '/preview');
+          $form.attr('target', '_blank');
+          $form.submit();
+
+
+          $form.attr('action', oldAction);
+          $form.removeAttr('target');
+          return false;
+        });
+      }
+
+      // Initialize the function bar by loading proper definitions
+      if ( EditorHas.functionBar() ) {
+
+        var htmlSetMarkupLang =
+          $('#gollum-editor-body').attr('data-markup-lang');
+
+        if ( htmlSetMarkupLang ) {
+          ActiveOptions.MarkupType = htmlSetMarkupLang;
+        }
+
+        // load language definition
+        LanguageDefinition.setActiveLanguage( ActiveOptions.MarkupType );
+        if ( EditorHas.formatSelector() ) {
+          FormatSelector.init(
+            $('#gollum-editor-format-selector select') );
+        }
+
+        if ( EditorHas.help() ) {
+          $('#gollum-editor-help').hide();
+          $('#gollum-editor-help').removeClass('jaws');
+        }
+
+      }
+      // EditorHas.functionBar
+    }
+    // EditorHas.baseEditorMarkup
+  };
+
+
+
+  /**
+   *  $.GollumEditor.defineLanguage
+   *  Defines a set of language actions that Gollum can use.
+   *  Used by the definitions in langs/ to register language definitions.
+   */
+  $.GollumEditor.defineLanguage = function( language_name, languageObject ) {
+    if ( typeof languageObject == 'object' ) {
+      LanguageDefinition.define( language_name, languageObject );
+    } else {
+      debug('GollumEditor.defineLanguage: definition for ' + language_name +
+            ' is not an object');
+    }
+  };
+
+
+  /**
+   *  debug
+   *  Prints debug information to console.log if debug output is enabled.
+   *
+   *  @param  mixed  Whatever you want to dump to console.log
+   *  @return void
+   */
+  var debug = function(m) {
+    if ( ActiveOptions.Debug &&
+         typeof console != 'undefined' ) {
+      console.log( m );
+    }
+  };
+
+
+
+  /**
+   *  LanguageDefinition
+   *  Language definition file handler
+   *  Loads language definition files as necessary.
+   */
+  var LanguageDefinition = {
+
+    _ACTIVE_LANG: '',
+    _LOADED_LANGS: [],
+    _LANG: {},
+
+    /**
+     *  Defines a language
+     *
+     *  @param name string  The name of the language
+     *  @param name object  The definition object
+     */
+    define: function( name, definitionObject ) {
+      LanguageDefinition._ACTIVE_LANG = name;
+      LanguageDefinition._LOADED_LANGS.push( name );
+      if ( typeof $.GollumEditor.WikiLanguage == 'object' ) {
+        var definition = {};
+        $.extend(definition, $.GollumEditor.WikiLanguage, definitionObject);
+        LanguageDefinition._LANG[name] = definition;
+      } else {
+        LanguageDefinition._LANG[name] = definitionObject;
+      }
+    },
+
+    getActiveLanguage: function() {
+      return LanguageDefinition._ACTIVE_LANG;
+    },
+
+    setActiveLanguage: function( name ) {
+      if ( !LanguageDefinition.isLoadedFor(name) ) {
+        LanguageDefinition._ACTIVE_LANG = null;
+        LanguageDefinition.loadFor( name, function(x, t) {
+          if ( t != 'success' ) {
+            debug('Failed to load language definition for ' + name);
+            // well, fake it and turn everything off for this one
+            LanguageDefinition.define( name, {} );
+          }
+
+          // update features that rely on the language definition
+          if ( EditorHas.functionBar() ) {
+            FunctionBar.refresh();
+          }
+
+          if ( LanguageDefinition.isValid() && EditorHas.formatSelector() ) {
+            FormatSelector.updateSelected();
+          }
+
+        } );
+      } else {
+        LanguageDefinition._ACTIVE_LANG = name;
+        FunctionBar.refresh();
+      }
+    },
+
+
+    /**
+     *  gets a definition object for a specified attribute
+     *
+     *  @param  string  attr    The specified attribute.
+     *  @param  string  specified_lang  The language to pull a definition for.
+     *  @return object if exists, null otherwise
+     */
+    getDefinitionFor: function( attr, specified_lang ) {
+      if ( !specified_lang ) {
+        specified_lang = LanguageDefinition._ACTIVE_LANG;
+      }
+
+      if ( LanguageDefinition.isLoadedFor(specified_lang) &&
+           LanguageDefinition._LANG[specified_lang][attr] &&
+           typeof LanguageDefinition._LANG[specified_lang][attr] == 'object' ) {
+        return LanguageDefinition._LANG[specified_lang][attr];
+      }
+
+      return null;
+    },
+
+
+    /**
+     *  loadFor
+     *  Asynchronously loads a definition file for the current markup.
+     *  Definition files are necessary to use the code editor.
+     *
+     *  @param  string  markup_name  The markup name you want to load
+     *  @return void
+     */
+    loadFor: function( markup_name, on_complete ) {
+      // Keep us from hitting 404s on our site, check the definition blacklist
+      if ( ActiveOptions.NoDefinitionsFor.length ) {
+        for ( var i=0; i < ActiveOptions.NoDefinitionsFor.length; i++ ) {
+          if ( markup_name == ActiveOptions.NoDefinitionsFor[i] ) {
+            // we don't have this. get out.
+            if ( typeof on_complete == 'function' ) {
+              on_complete( null, 'error' );
+              return;
+            }
+          }
+        }
+      }
+
+      // attempt to load the definition for this language
+      var script_uri = '/javascript/editor/langs/' + markup_name + '.js';
+      $.ajax({
+                url: script_uri,
+                dataType: 'script',
+                complete: function( xhr, textStatus ) {
+                  if ( typeof on_complete == 'function' ) {
+                    on_complete( xhr, textStatus );
+                  }
+                }
+            });
+    },
+
+
+    /**
+     *  isLoadedFor
+     *  Checks to see if a definition file has been loaded for the
+     *  specified markup language.
+     *
+     *  @param  string  markup_name   The name of the markup.
+     *  @return boolean
+     */
+    isLoadedFor: function( markup_name ) {
+      if ( LanguageDefinition._LOADED_LANGS.length === 0 ) {
+        return false;
+      }
+
+      for ( var i=0; i < LanguageDefinition._LOADED_LANGS.length; i++ ) {
+        if ( LanguageDefinition._LOADED_LANGS[i] == markup_name ) {
+          return true;
+        }
+      }
+      return false;
+    },
+
+    isValid: function() {
+      return ( LanguageDefinition._ACTIVE_LANG &&
+               typeof LanguageDefinition._LANG[LanguageDefinition._ACTIVE_LANG] ==
+               'object' );
+    }
+
+  };
+
+
+  /**
+   *  EditorHas
+   *  Various conditionals to check what features of the Gollum Editor are
+   *  active/operational.
+   */
+  var EditorHas = {
+
+
+    /**
+     *  EditorHas.baseEditorMarkup
+     *  True if the basic editor form is in place.
+     *
+     *  @return boolean
+     */
+    baseEditorMarkup: function() {
+      return ( $('#gollum-editor').length &&
+               $('#gollum-editor-body').length );
+    },
+
+
+    /**
+     *  EditorHas.collapsibleInputs
+     *  True if the editor contains collapsible inputs for things like the
+     *  sidebar or footer, false otherwise.
+     *
+     *  @return boolean
+     */
+    collapsibleInputs: function() {
+      return $('#gollum-editor .collapsed, #gollum-editor .expanded').length;
+    },
+
+
+    /**
+     *  EditorHas.formatSelector
+     *  True if the editor has a format selector (for switching between
+     *  language types), false otherwise.
+     *
+     *  @return boolean
+     */
+    formatSelector: function() {
+      return $('#gollum-editor-format-selector select').length;
+    },
+
+
+    /**
+     *  EditorHas.functionBar
+     *  True if the Function Bar markup exists.
+     *
+     *  @return boolean
+     */
+    functionBar: function() {
+      return ( ActiveOptions.HasFunctionBar &&
+               $('#gollum-editor-function-bar').length );
+    },
+
+
+    /**
+     *  EditorHas.ff4Environment
+     *  True if in a Firefox 4.0 Beta environment.
+     *
+     *  @return boolean
+     */
+    ff4Environment: function() {
+      var ua = new RegExp(/Firefox\/4.0b/);
+      return ( ua.test( navigator.userAgent ) );
+    },
+
+
+    /**
+     *  EditorHas.editSummaryMarkup
+     *  True if the editor has a summary field (Gollum's commit message),
+     *  false otherwise.
+     *
+     *  @return boolean
+     */
+    editSummaryMarkup: function() {
+      return ( $('input#gollum-editor-message-field').length > 0 );
+    },
+
+
+    /**
+     *  EditorHas.help
+     *  True if the editor contains the inline help sector, false otherwise.
+     *
+     *  @return boolean
+     */
+    help: function() {
+      return ( $('#gollum-editor #gollum-editor-help').length &&
+               $('#gollum-editor #function-help').length );
+    },
+
+
+    /**
+     *  EditorHas.previewButton
+     *  True if the editor has a preview button, false otherwise.
+     *
+     *  @return boolean
+     */
+    previewButton: function() {
+      return ( $('#gollum-editor #gollum-editor-preview').length );
+    },
+
+
+    /**
+     *  EditorHas.titleDisplayed
+     *  True if the editor is displaying a title field, false otherwise.
+     *
+     *  @return boolean
+     */
+    titleDisplayed: function() {
+      return ( ActiveOptions.NewFile );
+    }
+
+  };
+
+
+  /**
+   *  FunctionBar
+   *
+   *  Things the function bar does.
+   */
+   var FunctionBar = {
+
+      isActive: false,
+
+
+      /**
+       *  FunctionBar.activate
+       *  Activates the function bar, attaching all click events
+       *  and displaying the bar.
+       *
+       */
+      activate: function() {
+        debug('Activating function bar');
+
+        // check these out
+        $('#gollum-editor-function-bar a.function-button').each(function() {
+          if ( LanguageDefinition.getDefinitionFor( $(this).attr('id') ) ) {
+            $(this).click( FunctionBar.evtFunctionButtonClick );
+            $(this).removeClass('disabled');
+          }
+          else if ( $(this).attr('id') != 'function-help' ) {
+            $(this).addClass('disabled');
+          }
+        });
+
+        // show bar as active
+        $('#gollum-editor-function-bar').addClass( 'active' );
+        FunctionBar.isActive = true;
+      },
+
+
+      deactivate: function() {
+        $('#gollum-editor-function-bar a.function-button').unbind('click');
+        $('#gollum-editor-function-bar').removeClass( 'active' );
+        FunctionBar.isActive = false;
+      },
+
+
+      /**
+       *  FunctionBar.evtFunctionButtonClick
+       *  Event handler for the function buttons. Traps the click and
+       *  executes the proper language action.
+       *
+       *  @param jQuery.Event jQuery event object.
+       */
+      evtFunctionButtonClick: function(e) {
+        e.preventDefault();
+        var def = LanguageDefinition.getDefinitionFor( $(this).attr('id') );
+        if ( typeof def == 'object' ) {
+          FunctionBar.executeAction( def );
+        }
+      },
+
+
+      /**
+       *  FunctionBar.executeAction
+       *  Executes a language-specific defined action for a function button.
+       *
+       */
+      executeAction: function( definitionObject ) {
+        // get the selected text from the textarea
+        var txt = $('#gollum-editor-body').val();
+        // hmm, I'm not sure this will work in a textarea
+        var selPos = FunctionBar
+                      .getFieldSelectionPosition( $('#gollum-editor-body') );
+        var selText = FunctionBar.getFieldSelection( $('#gollum-editor-body') );
+        var repText = selText;
+        var reselect = true;
+        var cursor = null;
+
+        // execute a replacement function if one exists
+        if ( definitionObject.exec &&
+             typeof definitionObject.exec == 'function' ) {
+          definitionObject.exec( txt, selText, $('#gollum-editor-body') );
+          return;
+        }
+
+        // execute a search/replace if they exist
+        var searchExp = /([^\n]+)/gi;
+        if ( definitionObject.search &&
+             typeof definitionObject.search == 'object' ) {
+          debug('Replacing search Regex');
+          searchExp = null;
+          searchExp = new RegExp ( definitionObject.search );
+          debug( searchExp );
+        }
+        debug('repText is ' + '"' + repText + '"');
+        // replace text
+        if ( definitionObject.replace &&
+             typeof definitionObject.replace == 'string' ) {
+          debug('Running replacement - using ' + definitionObject.replace);
+          var rt = definitionObject.replace;
+          repText = repText.replace( searchExp, rt );
+          // remove backreferences
+          repText = repText.replace( /\$[\d]/g, '' );
+
+          if ( repText === '' ) {
+            debug('Search string is empty');
+
+            // find position of $1 - this is where we will place the cursor
+            cursor = rt.indexOf('$1');
+
+            // we have an empty string, so just remove backreferences
+            repText = rt.replace( /\$[\d]/g, '' );
+
+            // if the position of $1 doesn't exist, stick the cursor in
+            // the middle
+            if ( cursor == -1 ) {
+              cursor = Math.floor( rt.length / 2 );
+            }
+          }
+        }
+
+        // append if necessary
+        if ( definitionObject.append &&
+             typeof definitionObject.append == 'string' ) {
+          if ( repText == selText ) {
+            reselect = false;
+          }
+          repText += definitionObject.append;
+        }
+
+        if ( repText ) {
+          FunctionBar.replaceFieldSelection( $('#gollum-editor-body'),
+                                             repText, reselect, cursor );
+        }
+
+      },
+
+
+      /**
+       *  getFieldSelectionPosition
+       *  Retrieves the selection range for the textarea.
+       *
+       *  @return object the .start and .end offsets in the string
+       */
+      getFieldSelectionPosition: function( $field ) {
+        if ($field.length) {
+          var start = 0, end = 0;
+          var el = $field.get(0);
+
+          if (typeof el.selectionStart == "number" &&
+              typeof el.selectionEnd == "number") {
+            start = el.selectionStart;
+            end = el.selectionEnd;
+          } else {
+            var range = document.selection.createRange();
+            var stored_range = range.duplicate();
+            stored_range.moveToElementText( el );
+            stored_range.setEndPoint( 'EndToEnd', range );
+            start = stored_range.text.length - range.text.length;
+            end = start + range.text.length;
+
+            // so, uh, we're close, but we need to search for line breaks and
+            // adjust the start/end points accordingly since IE counts them as
+            // 2 characters in TextRange.
+            var s = start;
+            var lb = 0;
+            var i;
+            debug('IE: start position is currently ' + s);
+            for ( i=0; i < s; i++ ) {
+              if ( el.value.charAt(i).match(/\r/) ) {
+                ++lb;
+              }
+            }
+
+            if ( lb ) {
+              debug('IE start: compensating for ' + lb + ' line breaks');
+              start = start - lb;
+              lb = 0;
+            }
+
+            var e = end;
+            for ( i=0; i < e; i++ ) {
+              if ( el.value.charAt(i).match(/\r/) ) {
+                ++lb;
+              }
+            }
+
+            if ( lb ) {
+              debug('IE end: compensating for ' + lb + ' line breaks');
+              end = end - lb;
+            }
+          }
+
+          return {
+              start: start,
+              end: end
+          };
+        } // end if ($field.length)
+      },
+
+
+      /**
+       *  getFieldSelection
+       *  Returns the currently selected substring of the textarea.
+       *
+       *  @param  jQuery  A jQuery object for the textarea.
+       *  @return string  Selected string.
+       */
+      getFieldSelection: function( $field ) {
+        var selStr = '';
+        var selPos;
+
+        if ( $field.length ) {
+          selPos = FunctionBar.getFieldSelectionPosition( $field );
+          selStr = $field.val().substring( selPos.start, selPos.end );
+          debug('Selected: ' + selStr + ' (' + selPos.start + ', ' +
+                selPos.end + ')');
+          return selStr;
+        }
+        return false;
+      },
+
+
+      isShown: function() {
+        return ($('#gollum-editor-function-bar').is(':visible'));
+      },
+
+      refresh: function() {
+        if ( EditorHas.functionBar() ) {
+          debug('Refreshing function bar');
+          if ( LanguageDefinition.isValid() ) {
+            $('#gollum-editor-function-bar a.function-button').unbind('click');
+            FunctionBar.activate();
+            if ( Help ) {
+              Help.setActiveHelp( LanguageDefinition.getActiveLanguage() );
+            }
+          } else {
+            debug('Language definition is invalid.');
+            if ( FunctionBar.isShown() ) {
+              // deactivate the function bar; it's not gonna work now
+              FunctionBar.deactivate();
+            }
+            if ( Help.isShown() ) {
+              Help.hide();
+            }
+          }
+        }
+      },
+
+
+      /**
+       *  replaceFieldSelection
+       *  Replaces the currently selected substring of the textarea with
+       *  a new string.
+       *
+       *  @param  jQuery  A jQuery object for the textarea.
+       *  @param  string  The string to replace the current selection with.
+       *  @param  boolean Reselect the new text range.
+       */
+      replaceFieldSelection: function( $field, replaceText, reselect, cursorOffset ) {
+        var selPos = FunctionBar.getFieldSelectionPosition( $field );
+        var fullStr = $field.val();
+        var selectNew = true;
+        if ( reselect === false) {
+          selectNew = false;
+        }
+
+        var scrollTop = null;
+        if ( $field[0].scrollTop ) {
+          scrollTop = $field[0].scrollTop;
+        }
+
+        $field.val( fullStr.substring(0, selPos.start) + replaceText +
+                    fullStr.substring(selPos.end) );
+        $field[0].focus();
+
+        if ( selectNew ) {
+          if ( $field[0].setSelectionRange ) {
+            if ( cursorOffset ) {
+              $field[0].setSelectionRange(
+                                            selPos.start + cursorOffset,
+                                            selPos.start + cursorOffset
+               );
+            } else {
+              $field[0].setSelectionRange( selPos.start,
+                                           selPos.start + replaceText.length );
+            }
+          } else if ( $field[0].createTextRange ) {
+            var range = $field[0].createTextRange();
+            range.collapse( true );
+            if ( cursorOffset ) {
+              range.moveEnd( selPos.start + cursorOffset );
+              range.moveStart( selPos.start + cursorOffset );
+            } else {
+              range.moveEnd( 'character', selPos.start + replaceText.length );
+              range.moveStart( 'character', selPos.start );
+            }
+            range.select();
+          }
+        }
+
+        if ( scrollTop ) {
+          // this jumps sometimes in FF
+          $field[0].scrollTop = scrollTop;
+        }
+      }
+   };
+
+
+
+   /**
+    *  FormatSelector
+    *
+    *  Functions relating to the format selector (if it exists)
+    */
+   var FormatSelector = {
+
+     $_SELECTOR: null,
+
+     /**
+      *  FormatSelector.evtChangeFormat
+      *  Event handler for when a format has been changed by the format
+      *  selector. Will automatically load a new language definition
+      *  via JS if necessary.
+      *
+      *  @return void
+      */
+     evtChangeFormat: function( e ) {
+       var newMarkup = $(this).val();
+       LanguageDefinition.setActiveLanguage( newMarkup );
+     },
+
+
+     /**
+      *  FormatSelector.init
+      *  Initializes the format selector.
+      *
+      *  @return void
+      */
+     init: function( $sel ) {
+       debug('Initializing format selector');
+
+       // unbind events if init is being called twice for some reason
+       if ( FormatSelector.$_SELECTOR &&
+            typeof FormatSelector.$_SELECTOR == 'object' ) {
+         FormatSelector.$_SELECTOR.unbind( 'change' );
+       }
+
+       FormatSelector.$_SELECTOR = $sel;
+
+       // set format selector to the current language
+       FormatSelector.updateSelected();
+       FormatSelector.$_SELECTOR.change( FormatSelector.evtChangeFormat );
+     },
+
+
+     /**
+      * FormatSelector.update
+      */
+    updateSelected: function() {
+       var currentLang = LanguageDefinition.getActiveLanguage();
+       FormatSelector.$_SELECTOR.val( currentLang );
+    }
+
+   };
+
+
+
+   /**
+    *  Help
+    *
+    *  Functions that manage the display and loading of inline help files.
+    */
+  var Help = {
+
+    _ACTIVE_HELP: '',
+    _LOADED_HELP_LANGS: [],
+    _HELP: {},
+
+    /**
+     *  Help.define
+     *
+     *  Defines a new help context and enables the help function if it
+     *  exists in the Gollum Function Bar.
+     *
+     *  @param string name   The name you're giving to this help context.
+     *                       Generally, this should match the language name.
+     *  @param object definitionObject The definition object being loaded from a
+     *                                 language / help definition file.
+     *  @return void
+     */
+    define: function( name, definitionObject ) {
+      if ( Help.isValidHelpFormat( definitionObject ) ) {
+        debug('help is a valid format');
+
+        Help._ACTIVE_HELP_LANG = name;
+        Help._LOADED_HELP_LANGS.push( name );
+        Help._HELP[name] = definitionObject;
+
+        if ( $("#function-help").length ) {
+          if ( $('#function-help').hasClass('disabled') ) {
+            $('#function-help').removeClass('disabled');
+          }
+          $('#function-help').unbind('click');
+          $('#function-help').click( Help.evtHelpButtonClick );
+
+          // generate help menus
+          Help.generateHelpMenuFor( name );
+
+          if ( $('#gollum-editor-help').length &&
+               typeof $('#gollum-editor-help').attr('data-autodisplay') !== 'undefined' &&
+               $('#gollum-editor-help').attr('data-autodisplay') === 'true' ) {
+            Help.show();
+          }
+        }
+      } else {
+        if ( $('#function-help').length ) {
+          $('#function-help').addClass('disabled');
+        }
+      }
+    },
+
+    /**
+     *  Help.generateHelpMenuFor
+     *  Generates the markup for the main help menu given a context name.
+     *
+     *  @param string  name  The context name.
+     *  @return void
+     */
+    generateHelpMenuFor: function( name ) {
+      if ( !Help._HELP[name] ) {
+        debug('Help is not defined for ' + name.toString());
+        return false;
+      }
+      var helpData = Help._HELP[name];
+
+      // clear this shiz out
+      $('#gollum-editor-help-parent').html('');
+      $('#gollum-editor-help-list').html('');
+      $('#gollum-editor-help-content').html('');
+
+      // go go inefficient algorithm
+      for ( var i=0; i < helpData.length; i++ ) {
+        if ( typeof helpData[i] != 'object' ) {
+          break;
+        }
+
+        var $newLi = $('<li><a href="#" rel="' + i + '">' +
+                       helpData[i].menuName + '</a></li>');
+        $('#gollum-editor-help-parent').append( $newLi );
+        if ( i === 0 ) {
+          // select on first run
+          $newLi.children('a').addClass('selected');
+        }
+        $newLi.children('a').click( Help.evtParentMenuClick );
+      }
+
+      // generate parent submenu on first run
+      Help.generateSubMenu( helpData[0], 0 );
+      $($('#gollum-editor-help-list li a').get(0)).click();
+
+    },
+
+    /**
+     *  Help.generateSubMenu
+     *  Generates the markup for the inline help sub-menu given the data
+     *  object for the submenu and the array index to start at.
+     *
+     *  @param object subData The data for the sub-menu.
+     *  @param integer index  The index clicked on (parent menu index).
+     *  @return void
+     */
+    generateSubMenu: function( subData, index ) {
+      $('#gollum-editor-help-list').html('');
+      $('#gollum-editor-help-content').html('');
+      for ( var i=0; i < subData.content.length; i++ ) {
+        if ( typeof subData.content[i] != 'object' ) {
+          break;
+        }
+
+        var $subLi = $('<li><a href="#" rel="' + index + ':' + i + '">' +
+                       subData.content[i].menuName + '</a></li>');
+
+
+        $('#gollum-editor-help-list').append( $subLi );
+        $subLi.children('a').click( Help.evtSubMenuClick );
+      }
+    },
+
+    hide: function() {
+      if ( $.browser.msie ) {
+        $('#gollum-editor-help').css('display', 'none');
+      } else {
+        $('#gollum-editor-help').animate({
+          opacity: 0
+        }, 200, function() {
+          $('#gollum-editor-help')
+            .animate({ height: 'hide' }, 200);
+        });
+      }
+    },
+
+    show: function() {
+      if ( $.browser.msie ) {
+        // bypass effects for internet explorer, since it does weird crap
+        // to text antialiasing with opacity animations
+        $('#gollum-editor-help').css('display', 'block');
+      } else {
+        $('#gollum-editor-help').animate({
+          height: 'show'
+        }, 200, function() {
+          $('#gollum-editor-help')
+            .animate({ opacity: 1 }, 300);
+        });
+      }
+    },
+
+    /**
+     *  Help.showHelpFor
+     *  Displays the actual help content given the two menu indexes, which are
+     *  rendered in the rel="" attributes of the help menus
+     *
+     *  @param integer index1  parent index
+     *  @param integer index2  submenu index
+     *  @return void
+     */
+    showHelpFor: function( index1, index2 ) {
+      var html =
+        Help._HELP[Help._ACTIVE_HELP_LANG][index1].content[index2].data;
+      $('#gollum-editor-help-content').html(html);
+    },
+
+    /**
+     *  Help.isLoadedFor
+     *  Returns true if help is loaded for a specific markup language,
+     *  false otherwise.
+     *
+     *  @param string name   The name of the markup language.
+     *  @return boolean
+     */
+    isLoadedFor: function( name ) {
+      for ( var i=0; i < Help._LOADED_HELP_LANGS.length; i++ ) {
+        if ( name == Help._LOADED_HELP_LANGS[i] ) {
+          return true;
+        }
+      }
+      return false;
+    },
+
+    isShown: function() {
+      return ($('#gollum-editor-help').is(':visible'));
+    },
+
+    /**
+     *  Help.isValidHelpFormat
+     *  Does a quick check to make sure that the help definition isn't in a
+     *  completely messed-up format.
+     *
+     *  @param object (Array) helpArr  The help definition array.
+     *  @return boolean
+     */
+    isValidHelpFormat: function( helpArr ) {
+      return ( typeof helpArr == 'object' &&
+               helpArr.length &&
+               typeof helpArr[0].menuName == 'string' &&
+               typeof helpArr[0].content == 'object' &&
+               helpArr[0].content.length );
+    },
+
+    /**
+     *  Help.setActiveHelp
+     *  Sets the active help definition to the one defined in the argument,
+     *  re-rendering the help menu to match the new definition.
+     *
+     *  @param string  name  The name of the help definition.
+     *  @return void
+     */
+    setActiveHelp: function( name ) {
+      if ( !Help.isLoadedFor( name ) ) {
+        if ( $('#function-help').length ) {
+          $('#function-help').addClass('disabled');
+        }
+        if ( Help.isShown() ) {
+          Help.hide();
+        }
+      } else {
+        Help._ACTIVE_HELP_LANG = name;
+        if ( $("#function-help").length ) {
+          if ( $('#function-help').hasClass('disabled') ) {
+            $('#function-help').removeClass('disabled');
+          }
+          $('#function-help').unbind('click');
+          $('#function-help').click( Help.evtHelpButtonClick );
+          Help.generateHelpMenuFor( name );
+        }
+      }
+    },
+
+    /**
+     *  Help.evtHelpButtonClick
+     *  Event handler for clicking the help button in the function bar.
+     *
+     *  @param jQuery.Event e  The jQuery event object.
+     *  @return void
+     */
+    evtHelpButtonClick: function( e ) {
+      e.preventDefault();
+      if ( Help.isShown() ) {
+        // turn off autodisplay if it's on
+        if ( $('#gollum-editor-help').length &&
+             $('#gollum-editor-help').attr('data-autodisplay') !== 'undefined' &&
+             $('#gollum-editor-help').attr('data-autodisplay') === 'true' ) {
+          $.post('/wiki/help?_method=delete');
+          $('#gollum-editor-help').attr('data-autodisplay', '');
+        }
+        Help.hide(); }
+      else { Help.show(); }
+    },
+
+    /**
+     *  Help.evtParentMenuClick
+     *  Event handler for clicking on an item in the parent menu. Automatically
+     *  renders the submenu for the parent menu as well as the first result for
+     *  the actual plain text.
+     *
+     *  @param jQuery.Event e  The jQuery event object.
+     *  @return void
+     */
+    evtParentMenuClick: function( e ) {
+      e.preventDefault();
+      // short circuit if we've selected this already
+      if ( $(this).hasClass('selected') ) { return; }
+
+      // populate from help data for this
+      var helpIndex = $(this).attr('rel');
+      var subData = Help._HELP[Help._ACTIVE_HELP_LANG][helpIndex];
+
+      $('#gollum-editor-help-parent li a').removeClass('selected');
+      $(this).addClass('selected');
+      Help.generateSubMenu( subData, helpIndex );
+      $($('#gollum-editor-help-list li a').get(0)).click();
+    },
+
+    /**
+     *  Help.evtSubMenuClick
+     *  Event handler for clicking an item in a help submenu. Renders the
+     *  appropriate text for the submenu link.
+     *
+     *  @param jQuery.Event e  The jQuery event object.
+     *  @return void
+     */
+    evtSubMenuClick: function( e ) {
+      e.preventDefault();
+      if ( $(this).hasClass('selected') ) { return; }
+
+      // split index rel data
+      var rawIndex = $(this).attr('rel').split(':');
+      $('#gollum-editor-help-list li a').removeClass('selected');
+      $(this).addClass('selected');
+      Help.showHelpFor( rawIndex[0], rawIndex[1] );
+    }
+  };
+
+  // Publicly-accessible function to Help.define
+  $.GollumEditor.defineHelp = Help.define;
+
+  // Dialog exists as its own thing now
+  $.GollumEditor.Dialog = $.GollumDialog;
+  $.GollumEditor.replaceSelection = function( repText ) {
+    FunctionBar.replaceFieldSelection( $('#gollum-editor-body'), repText );
+  };
+
+  // Placeholder exists as its own thing now
+  $.GollumEditor.Placeholder = $.GollumPlaceholder;
+
+})(jQuery);
diff --git a/0.8.1-rc1/balance/modules/puny/static/js/editor/gollum.editor.js b/0.8.1-rc1/balance/modules/puny/static/js/editor/gollum.editor.js
new file mode 100644
index 0000000..de09357
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/js/editor/gollum.editor.js
@@ -0,0 +1,1090 @@
+/*
+ * 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.
+ */
+
+/**
+ *  gollum.editor.js
+ *  A jQuery plugin that creates the Gollum Editor.
+ *
+ *  Usage:
+ *  $.GollumEditor(); on DOM ready.
+ */
+(function($) {
+
+  // Editor options
+  var DefaultOptions = {
+    MarkupType: 'markdown',
+    EditorMode: 'code',
+    NewFile: false,
+    HasFunctionBar: true,
+    Debug: false,
+    NoDefinitionsFor: []
+  };
+  var ActiveOptions = {};
+
+  /**
+   *  $.GollumEditor
+   *
+   *  You don't need to do anything. Just run this on DOM ready.
+   */
+  $.GollumEditor = function( IncomingOptions ) {
+
+    ActiveOptions = $.extend( DefaultOptions );
+
+    debug('GollumEditor loading');
+
+    if ( EditorHas.baseEditorMarkup() ) {
+
+      if ( EditorHas.titleDisplayed() ) {
+        $('#gollum-editor-title-field').addClass('active');
+      }
+
+      if ( EditorHas.editSummaryMarkup() ) {
+        $.GollumEditor.Placeholder.add($('#gollum-editor-edit-summary input'));
+        $('#gollum-editor form[name="gollum-editor"]').submit(function( e ) {
+          e.preventDefault();
+          $.GollumEditor.Placeholder.clearAll();
+          debug('submitting');
+          $(this).unbind('submit');
+          $(this).submit();
+        });
+      }
+
+      if ( EditorHas.collapsibleInputs() ) {
+        $('#gollum-editor .collapsed a.button, ' +
+          '#gollum-editor .expanded a.button').click(function( e ) {
+          e.preventDefault();
+          $(this).parent().toggleClass('expanded');
+          $(this).parent().toggleClass('collapsed');
+        });
+      }
+
+      if ( EditorHas.previewButton() ) {
+        var formAction =
+        $('#gollum-editor #gollum-editor-preview').click(function() {
+          // make a dummy form, submit to new target window
+          // get form fields
+          var oldAction = $('#gollum-editor form').attr('action');
+          var $form = $($('#gollum-editor form').get(0));
+          $form.attr('action', this.href || '/preview');
+          $form.attr('target', '_blank');
+          $form.submit();
+
+
+          $form.attr('action', oldAction);
+          $form.removeAttr('target');
+          return false;
+        });
+      }
+
+      // Initialize the function bar by loading proper definitions
+      if ( EditorHas.functionBar() ) {
+
+        var htmlSetMarkupLang =
+          $('#gollum-editor-body').attr('data-markup-lang');
+
+        if ( htmlSetMarkupLang ) {
+          ActiveOptions.MarkupType = htmlSetMarkupLang;
+        }
+
+        // load language definition
+        LanguageDefinition.setActiveLanguage( ActiveOptions.MarkupType );
+        if ( EditorHas.formatSelector() ) {
+          FormatSelector.init(
+            $('#gollum-editor-format-selector select') );
+        }
+
+        if ( EditorHas.help() ) {
+          $('#gollum-editor-help').hide();
+          $('#gollum-editor-help').removeClass('jaws');
+        }
+
+      }
+      // EditorHas.functionBar
+    }
+    // EditorHas.baseEditorMarkup
+  };
+
+
+
+  /**
+   *  $.GollumEditor.defineLanguage
+   *  Defines a set of language actions that Gollum can use.
+   *  Used by the definitions in langs/ to register language definitions.
+   */
+  $.GollumEditor.defineLanguage = function( language_name, languageObject ) {
+    if ( typeof languageObject == 'object' ) {
+      LanguageDefinition.define( language_name, languageObject );
+    } else {
+      debug('GollumEditor.defineLanguage: definition for ' + language_name +
+            ' is not an object');
+    }
+  };
+
+
+  /**
+   *  debug
+   *  Prints debug information to console.log if debug output is enabled.
+   *
+   *  @param  mixed  Whatever you want to dump to console.log
+   *  @return void
+   */
+  var debug = function(m) {
+    if ( ActiveOptions.Debug &&
+         typeof console != 'undefined' ) {
+      console.log( m );
+    }
+  };
+
+
+
+  /**
+   *  LanguageDefinition
+   *  Language definition file handler
+   *  Loads language definition files as necessary.
+   */
+  var LanguageDefinition = {
+
+    _ACTIVE_LANG: '',
+    _LOADED_LANGS: [],
+    _LANG: {},
+
+    /**
+     *  Defines a language
+     *
+     *  @param name string  The name of the language
+     *  @param name object  The definition object
+     */
+    define: function( name, definitionObject ) {
+      LanguageDefinition._ACTIVE_LANG = name;
+      LanguageDefinition._LOADED_LANGS.push( name );
+      if ( typeof $.GollumEditor.WikiLanguage == 'object' ) {
+        var definition = {};
+        $.extend(definition, $.GollumEditor.WikiLanguage, definitionObject);
+        LanguageDefinition._LANG[name] = definition;
+      } else {
+        LanguageDefinition._LANG[name] = definitionObject;
+      }
+    },
+
+    getActiveLanguage: function() {
+      return LanguageDefinition._ACTIVE_LANG;
+    },
+
+    setActiveLanguage: function( name ) {
+      if ( !LanguageDefinition.isLoadedFor(name) ) {
+        LanguageDefinition._ACTIVE_LANG = null;
+        LanguageDefinition.loadFor( name, function(x, t) {
+          if ( t != 'success' ) {
+            debug('Failed to load language definition for ' + name);
+            // well, fake it and turn everything off for this one
+            LanguageDefinition.define( name, {} );
+          }
+
+          // update features that rely on the language definition
+          if ( EditorHas.functionBar() ) {
+            FunctionBar.refresh();
+          }
+
+          if ( LanguageDefinition.isValid() && EditorHas.formatSelector() ) {
+            FormatSelector.updateSelected();
+          }
+
+        } );
+      } else {
+        LanguageDefinition._ACTIVE_LANG = name;
+        FunctionBar.refresh();
+      }
+    },
+
+
+    /**
+     *  gets a definition object for a specified attribute
+     *
+     *  @param  string  attr    The specified attribute.
+     *  @param  string  specified_lang  The language to pull a definition for.
+     *  @return object if exists, null otherwise
+     */
+    getDefinitionFor: function( attr, specified_lang ) {
+      if ( !specified_lang ) {
+        specified_lang = LanguageDefinition._ACTIVE_LANG;
+      }
+
+      if ( LanguageDefinition.isLoadedFor(specified_lang) &&
+           LanguageDefinition._LANG[specified_lang][attr] &&
+           typeof LanguageDefinition._LANG[specified_lang][attr] == 'object' ) {
+        return LanguageDefinition._LANG[specified_lang][attr];
+      }
+
+      return null;
+    },
+
+
+    /**
+     *  loadFor
+     *  Asynchronously loads a definition file for the current markup.
+     *  Definition files are necessary to use the code editor.
+     *
+     *  @param  string  markup_name  The markup name you want to load
+     *  @return void
+     */
+    loadFor: function( markup_name, on_complete ) {
+      // Keep us from hitting 404s on our site, check the definition blacklist
+      if ( ActiveOptions.NoDefinitionsFor.length ) {
+        for ( var i=0; i < ActiveOptions.NoDefinitionsFor.length; i++ ) {
+          if ( markup_name == ActiveOptions.NoDefinitionsFor[i] ) {
+            // we don't have this. get out.
+            if ( typeof on_complete == 'function' ) {
+              on_complete( null, 'error' );
+              return;
+            }
+          }
+        }
+      }
+
+      // attempt to load the definition for this language
+      var script_uri =  puny_module_static + '/js/editor/langs/' + markup_name + '.js';
+      $.ajax({
+                url: script_uri,
+                dataType: 'script',
+                complete: function( xhr, textStatus ) {
+                  if ( typeof on_complete == 'function' ) {
+                    on_complete( xhr, textStatus );
+                  }
+                }
+            });
+    },
+
+
+    /**
+     *  isLoadedFor
+     *  Checks to see if a definition file has been loaded for the
+     *  specified markup language.
+     *
+     *  @param  string  markup_name   The name of the markup.
+     *  @return boolean
+     */
+    isLoadedFor: function( markup_name ) {
+      if ( LanguageDefinition._LOADED_LANGS.length === 0 ) {
+        return false;
+      }
+
+      for ( var i=0; i < LanguageDefinition._LOADED_LANGS.length; i++ ) {
+        if ( LanguageDefinition._LOADED_LANGS[i] == markup_name ) {
+          return true;
+        }
+      }
+      return false;
+    },
+
+    isValid: function() {
+      return ( LanguageDefinition._ACTIVE_LANG &&
+               typeof LanguageDefinition._LANG[LanguageDefinition._ACTIVE_LANG] ==
+               'object' );
+    }
+
+  };
+
+
+  /**
+   *  EditorHas
+   *  Various conditionals to check what features of the Gollum Editor are
+   *  active/operational.
+   */
+  var EditorHas = {
+
+
+    /**
+     *  EditorHas.baseEditorMarkup
+     *  True if the basic editor form is in place.
+     *
+     *  @return boolean
+     */
+    baseEditorMarkup: function() {
+      return ( $('#gollum-editor').length &&
+               $('#gollum-editor-body').length );
+    },
+
+
+    /**
+     *  EditorHas.collapsibleInputs
+     *  True if the editor contains collapsible inputs for things like the
+     *  sidebar or footer, false otherwise.
+     *
+     *  @return boolean
+     */
+    collapsibleInputs: function() {
+      return $('#gollum-editor .collapsed, #gollum-editor .expanded').length;
+    },
+
+
+    /**
+     *  EditorHas.formatSelector
+     *  True if the editor has a format selector (for switching between
+     *  language types), false otherwise.
+     *
+     *  @return boolean
+     */
+    formatSelector: function() {
+      return $('#gollum-editor-format-selector select').length;
+    },
+
+
+    /**
+     *  EditorHas.functionBar
+     *  True if the Function Bar markup exists.
+     *
+     *  @return boolean
+     */
+    functionBar: function() {
+      return ( ActiveOptions.HasFunctionBar &&
+               $('#gollum-editor-function-bar').length );
+    },
+
+
+    /**
+     *  EditorHas.ff4Environment
+     *  True if in a Firefox 4.0 Beta environment.
+     *
+     *  @return boolean
+     */
+    ff4Environment: function() {
+      var ua = new RegExp(/Firefox\/4.0b/);
+      return ( ua.test( navigator.userAgent ) );
+    },
+
+
+    /**
+     *  EditorHas.editSummaryMarkup
+     *  True if the editor has a summary field (Gollum's commit message),
+     *  false otherwise.
+     *
+     *  @return boolean
+     */
+    editSummaryMarkup: function() {
+      return ( $('input#gollum-editor-message-field').length > 0 );
+    },
+
+
+    /**
+     *  EditorHas.help
+     *  True if the editor contains the inline help sector, false otherwise.
+     *
+     *  @return boolean
+     */
+    help: function() {
+      return ( $('#gollum-editor #gollum-editor-help').length &&
+               $('#gollum-editor #function-help').length );
+    },
+
+
+    /**
+     *  EditorHas.previewButton
+     *  True if the editor has a preview button, false otherwise.
+     *
+     *  @return boolean
+     */
+    previewButton: function() {
+      return ( $('#gollum-editor #gollum-editor-preview').length );
+    },
+
+
+    /**
+     *  EditorHas.titleDisplayed
+     *  True if the editor is displaying a title field, false otherwise.
+     *
+     *  @return boolean
+     */
+    titleDisplayed: function() {
+      return ( ActiveOptions.NewFile );
+    }
+
+  };
+
+
+  /**
+   *  FunctionBar
+   *
+   *  Things the function bar does.
+   */
+   var FunctionBar = {
+
+      isActive: false,
+
+
+      /**
+       *  FunctionBar.activate
+       *  Activates the function bar, attaching all click events
+       *  and displaying the bar.
+       *
+       */
+      activate: function() {
+        debug('Activating function bar');
+
+        // check these out
+        $('#gollum-editor-function-bar a.function-button').each(function() {
+          if ( LanguageDefinition.getDefinitionFor( $(this).attr('id') ) ) {
+            $(this).click( FunctionBar.evtFunctionButtonClick );
+            $(this).removeClass('disabled');
+          }
+          else if ( $(this).attr('id') != 'function-help' ) {
+            $(this).addClass('disabled');
+          }
+        });
+
+        // show bar as active
+        $('#gollum-editor-function-bar').addClass( 'active' );
+        FunctionBar.isActive = true;
+      },
+
+
+      deactivate: function() {
+        $('#gollum-editor-function-bar a.function-button').unbind('click');
+        $('#gollum-editor-function-bar').removeClass( 'active' );
+        FunctionBar.isActive = false;
+      },
+
+
+      /**
+       *  FunctionBar.evtFunctionButtonClick
+       *  Event handler for the function buttons. Traps the click and
+       *  executes the proper language action.
+       *
+       *  @param jQuery.Event jQuery event object.
+       */
+      evtFunctionButtonClick: function(e) {
+        e.preventDefault();
+        var def = LanguageDefinition.getDefinitionFor( $(this).attr('id') );
+        if ( typeof def == 'object' ) {
+          FunctionBar.executeAction( def );
+        }
+      },
+
+
+      /**
+       *  FunctionBar.executeAction
+       *  Executes a language-specific defined action for a function button.
+       *
+       */
+      executeAction: function( definitionObject ) {
+        // get the selected text from the textarea
+        var txt = $('#gollum-editor-body').val();
+        // hmm, I'm not sure this will work in a textarea
+        var selPos = FunctionBar
+                      .getFieldSelectionPosition( $('#gollum-editor-body') );
+        var selText = FunctionBar.getFieldSelection( $('#gollum-editor-body') );
+        var repText = selText;
+        var reselect = true;
+        var cursor = null;
+
+        // execute a replacement function if one exists
+        if ( definitionObject.exec &&
+             typeof definitionObject.exec == 'function' ) {
+          definitionObject.exec( txt, selText, $('#gollum-editor-body') );
+          return;
+        }
+
+        // execute a search/replace if they exist
+        var searchExp = /([^\n]+)/gi;
+        if ( definitionObject.search &&
+             typeof definitionObject.search == 'object' ) {
+          debug('Replacing search Regex');
+          searchExp = null;
+          searchExp = new RegExp ( definitionObject.search );
+          debug( searchExp );
+        }
+        debug('repText is ' + '"' + repText + '"');
+        // replace text
+        if ( definitionObject.replace &&
+             typeof definitionObject.replace == 'string' ) {
+          debug('Running replacement - using ' + definitionObject.replace);
+          var rt = definitionObject.replace;
+          repText = repText.replace( searchExp, rt );
+          // remove backreferences
+          repText = repText.replace( /\$[\d]/g, '' );
+
+          if ( repText === '' ) {
+            debug('Search string is empty');
+
+            // find position of $1 - this is where we will place the cursor
+            cursor = rt.indexOf('$1');
+
+            // we have an empty string, so just remove backreferences
+            repText = rt.replace( /\$[\d]/g, '' );
+
+            // if the position of $1 doesn't exist, stick the cursor in
+            // the middle
+            if ( cursor == -1 ) {
+              cursor = Math.floor( rt.length / 2 );
+            }
+          }
+        }
+
+        // append if necessary
+        if ( definitionObject.append &&
+             typeof definitionObject.append == 'string' ) {
+          if ( repText == selText ) {
+            reselect = false;
+          }
+          repText += definitionObject.append;
+        }
+
+        if ( repText ) {
+          FunctionBar.replaceFieldSelection( $('#gollum-editor-body'),
+                                             repText, reselect, cursor );
+        }
+
+      },
+
+
+      /**
+       *  getFieldSelectionPosition
+       *  Retrieves the selection range for the textarea.
+       *
+       *  @return object the .start and .end offsets in the string
+       */
+      getFieldSelectionPosition: function( $field ) {
+        if ($field.length) {
+          var start = 0, end = 0;
+          var el = $field.get(0);
+
+          if (typeof el.selectionStart == "number" &&
+              typeof el.selectionEnd == "number") {
+            start = el.selectionStart;
+            end = el.selectionEnd;
+          } else {
+            var range = document.selection.createRange();
+            var stored_range = range.duplicate();
+            stored_range.moveToElementText( el );
+            stored_range.setEndPoint( 'EndToEnd', range );
+            start = stored_range.text.length - range.text.length;
+            end = start + range.text.length;
+
+            // so, uh, we're close, but we need to search for line breaks and
+            // adjust the start/end points accordingly since IE counts them as
+            // 2 characters in TextRange.
+            var s = start;
+            var lb = 0;
+            var i;
+            debug('IE: start position is currently ' + s);
+            for ( i=0; i < s; i++ ) {
+              if ( el.value.charAt(i).match(/\r/) ) {
+                ++lb;
+              }
+            }
+
+            if ( lb ) {
+              debug('IE start: compensating for ' + lb + ' line breaks');
+              start = start - lb;
+              lb = 0;
+            }
+
+            var e = end;
+            for ( i=0; i < e; i++ ) {
+              if ( el.value.charAt(i).match(/\r/) ) {
+                ++lb;
+              }
+            }
+
+            if ( lb ) {
+              debug('IE end: compensating for ' + lb + ' line breaks');
+              end = end - lb;
+            }
+          }
+
+          return {
+              start: start,
+              end: end
+          };
+        } // end if ($field.length)
+      },
+
+
+      /**
+       *  getFieldSelection
+       *  Returns the currently selected substring of the textarea.
+       *
+       *  @param  jQuery  A jQuery object for the textarea.
+       *  @return string  Selected string.
+       */
+      getFieldSelection: function( $field ) {
+        var selStr = '';
+        var selPos;
+
+        if ( $field.length ) {
+          selPos = FunctionBar.getFieldSelectionPosition( $field );
+          selStr = $field.val().substring( selPos.start, selPos.end );
+          debug('Selected: ' + selStr + ' (' + selPos.start + ', ' +
+                selPos.end + ')');
+          return selStr;
+        }
+        return false;
+      },
+
+
+      isShown: function() {
+        return ($('#gollum-editor-function-bar').is(':visible'));
+      },
+
+      refresh: function() {
+        if ( EditorHas.functionBar() ) {
+          debug('Refreshing function bar');
+          if ( LanguageDefinition.isValid() ) {
+            $('#gollum-editor-function-bar a.function-button').unbind('click');
+            FunctionBar.activate();
+            if ( Help ) {
+              Help.setActiveHelp( LanguageDefinition.getActiveLanguage() );
+            }
+          } else {
+            debug('Language definition is invalid.');
+            if ( FunctionBar.isShown() ) {
+              // deactivate the function bar; it's not gonna work now
+              FunctionBar.deactivate();
+            }
+            if ( Help.isShown() ) {
+              Help.hide();
+            }
+          }
+        }
+      },
+
+
+      /**
+       *  replaceFieldSelection
+       *  Replaces the currently selected substring of the textarea with
+       *  a new string.
+       *
+       *  @param  jQuery  A jQuery object for the textarea.
+       *  @param  string  The string to replace the current selection with.
+       *  @param  boolean Reselect the new text range.
+       */
+      replaceFieldSelection: function( $field, replaceText, reselect, cursorOffset ) {
+        var selPos = FunctionBar.getFieldSelectionPosition( $field );
+        var fullStr = $field.val();
+        var selectNew = true;
+        if ( reselect === false) {
+          selectNew = false;
+        }
+
+        var scrollTop = null;
+        if ( $field[0].scrollTop ) {
+          scrollTop = $field[0].scrollTop;
+        }
+
+        $field.val( fullStr.substring(0, selPos.start) + replaceText +
+                    fullStr.substring(selPos.end) );
+        $field[0].focus();
+
+        if ( selectNew ) {
+          if ( $field[0].setSelectionRange ) {
+            if ( cursorOffset ) {
+              $field[0].setSelectionRange(
+                                            selPos.start + cursorOffset,
+                                            selPos.start + cursorOffset
+               );
+            } else {
+              $field[0].setSelectionRange( selPos.start,
+                                           selPos.start + replaceText.length );
+            }
+          } else if ( $field[0].createTextRange ) {
+            var range = $field[0].createTextRange();
+            range.collapse( true );
+            if ( cursorOffset ) {
+              range.moveEnd( selPos.start + cursorOffset );
+              range.moveStart( selPos.start + cursorOffset );
+            } else {
+              range.moveEnd( 'character', selPos.start + replaceText.length );
+              range.moveStart( 'character', selPos.start );
+            }
+            range.select();
+          }
+        }
+
+        if ( scrollTop ) {
+          // this jumps sometimes in FF
+          $field[0].scrollTop = scrollTop;
+        }
+      }
+   };
+
+
+
+   /**
+    *  FormatSelector
+    *
+    *  Functions relating to the format selector (if it exists)
+    */
+   var FormatSelector = {
+
+     $_SELECTOR: null,
+
+     /**
+      *  FormatSelector.evtChangeFormat
+      *  Event handler for when a format has been changed by the format
+      *  selector. Will automatically load a new language definition
+      *  via JS if necessary.
+      *
+      *  @return void
+      */
+     evtChangeFormat: function( e ) {
+       var newMarkup = $(this).val();
+       LanguageDefinition.setActiveLanguage( newMarkup );
+     },
+
+
+     /**
+      *  FormatSelector.init
+      *  Initializes the format selector.
+      *
+      *  @return void
+      */
+     init: function( $sel ) {
+       debug('Initializing format selector');
+
+       // unbind events if init is being called twice for some reason
+       if ( FormatSelector.$_SELECTOR &&
+            typeof FormatSelector.$_SELECTOR == 'object' ) {
+         FormatSelector.$_SELECTOR.unbind( 'change' );
+       }
+
+       FormatSelector.$_SELECTOR = $sel;
+
+       // set format selector to the current language
+       FormatSelector.updateSelected();
+       FormatSelector.$_SELECTOR.change( FormatSelector.evtChangeFormat );
+     },
+
+
+     /**
+      * FormatSelector.update
+      */
+    updateSelected: function() {
+       var currentLang = LanguageDefinition.getActiveLanguage();
+       FormatSelector.$_SELECTOR.val( currentLang );
+    }
+
+   };
+
+
+
+   /**
+    *  Help
+    *
+    *  Functions that manage the display and loading of inline help files.
+    */
+  var Help = {
+
+    _ACTIVE_HELP: '',
+    _LOADED_HELP_LANGS: [],
+    _HELP: {},
+
+    /**
+     *  Help.define
+     *
+     *  Defines a new help context and enables the help function if it
+     *  exists in the Gollum Function Bar.
+     *
+     *  @param string name   The name you're giving to this help context.
+     *                       Generally, this should match the language name.
+     *  @param object definitionObject The definition object being loaded from a
+     *                                 language / help definition file.
+     *  @return void
+     */
+    define: function( name, definitionObject ) {
+      if ( Help.isValidHelpFormat( definitionObject ) ) {
+        debug('help is a valid format');
+
+        Help._ACTIVE_HELP_LANG = name;
+        Help._LOADED_HELP_LANGS.push( name );
+        Help._HELP[name] = definitionObject;
+
+        if ( $("#function-help").length ) {
+          if ( $('#function-help').hasClass('disabled') ) {
+            $('#function-help').removeClass('disabled');
+          }
+          $('#function-help').unbind('click');
+          $('#function-help').click( Help.evtHelpButtonClick );
+
+          // generate help menus
+          Help.generateHelpMenuFor( name );
+
+          if ( $('#gollum-editor-help').length &&
+               typeof $('#gollum-editor-help').attr('data-autodisplay') !== 'undefined' &&
+               $('#gollum-editor-help').attr('data-autodisplay') === 'true' ) {
+            Help.show();
+          }
+        }
+      } else {
+        if ( $('#function-help').length ) {
+          $('#function-help').addClass('disabled');
+        }
+      }
+    },
+
+    /**
+     *  Help.generateHelpMenuFor
+     *  Generates the markup for the main help menu given a context name.
+     *
+     *  @param string  name  The context name.
+     *  @return void
+     */
+    generateHelpMenuFor: function( name ) {
+      if ( !Help._HELP[name] ) {
+        debug('Help is not defined for ' + name.toString());
+        return false;
+      }
+      var helpData = Help._HELP[name];
+
+      // clear this shiz out
+      $('#gollum-editor-help-parent').html('');
+      $('#gollum-editor-help-list').html('');
+      $('#gollum-editor-help-content').html('');
+
+      // go go inefficient algorithm
+      for ( var i=0; i < helpData.length; i++ ) {
+        if ( typeof helpData[i] != 'object' ) {
+          break;
+        }
+
+        var $newLi = $('<li><a href="#" rel="' + i + '">' +
+                       helpData[i].menuName + '</a></li>');
+        $('#gollum-editor-help-parent').append( $newLi );
+        if ( i === 0 ) {
+          // select on first run
+          $newLi.children('a').addClass('selected');
+        }
+        $newLi.children('a').click( Help.evtParentMenuClick );
+      }
+
+      // generate parent submenu on first run
+      Help.generateSubMenu( helpData[0], 0 );
+      $($('#gollum-editor-help-list li a').get(0)).click();
+
+    },
+
+    /**
+     *  Help.generateSubMenu
+     *  Generates the markup for the inline help sub-menu given the data
+     *  object for the submenu and the array index to start at.
+     *
+     *  @param object subData The data for the sub-menu.
+     *  @param integer index  The index clicked on (parent menu index).
+     *  @return void
+     */
+    generateSubMenu: function( subData, index ) {
+      $('#gollum-editor-help-list').html('');
+      $('#gollum-editor-help-content').html('');
+      for ( var i=0; i < subData.content.length; i++ ) {
+        if ( typeof subData.content[i] != 'object' ) {
+          break;
+        }
+
+        var $subLi = $('<li><a href="#" rel="' + index + ':' + i + '">' +
+                       subData.content[i].menuName + '</a></li>');
+
+
+        $('#gollum-editor-help-list').append( $subLi );
+        $subLi.children('a').click( Help.evtSubMenuClick );
+      }
+    },
+
+    hide: function() {
+      if ( $.browser.msie ) {
+        $('#gollum-editor-help').css('display', 'none');
+      } else {
+        $('#gollum-editor-help').animate({
+          opacity: 0
+        }, 200, function() {
+          $('#gollum-editor-help')
+            .animate({ height: 'hide' }, 200);
+        });
+      }
+    },
+
+    show: function() {
+      if ( $.browser.msie ) {
+        // bypass effects for internet explorer, since it does weird crap
+        // to text antialiasing with opacity animations
+        $('#gollum-editor-help').css('display', 'block');
+      } else {
+        $('#gollum-editor-help').animate({
+          height: 'show'
+        }, 200, function() {
+          $('#gollum-editor-help')
+            .animate({ opacity: 1 }, 300);
+        });
+      }
+    },
+
+    /**
+     *  Help.showHelpFor
+     *  Displays the actual help content given the two menu indexes, which are
+     *  rendered in the rel="" attributes of the help menus
+     *
+     *  @param integer index1  parent index
+     *  @param integer index2  submenu index
+     *  @return void
+     */
+    showHelpFor: function( index1, index2 ) {
+      var html =
+        Help._HELP[Help._ACTIVE_HELP_LANG][index1].content[index2].data;
+      $('#gollum-editor-help-content').html(html);
+    },
+
+    /**
+     *  Help.isLoadedFor
+     *  Returns true if help is loaded for a specific markup language,
+     *  false otherwise.
+     *
+     *  @param string name   The name of the markup language.
+     *  @return boolean
+     */
+    isLoadedFor: function( name ) {
+      for ( var i=0; i < Help._LOADED_HELP_LANGS.length; i++ ) {
+        if ( name == Help._LOADED_HELP_LANGS[i] ) {
+          return true;
+        }
+      }
+      return false;
+    },
+
+    isShown: function() {
+      return ($('#gollum-editor-help').is(':visible'));
+    },
+
+    /**
+     *  Help.isValidHelpFormat
+     *  Does a quick check to make sure that the help definition isn't in a
+     *  completely messed-up format.
+     *
+     *  @param object (Array) helpArr  The help definition array.
+     *  @return boolean
+     */
+    isValidHelpFormat: function( helpArr ) {
+      return ( typeof helpArr == 'object' &&
+               helpArr.length &&
+               typeof helpArr[0].menuName == 'string' &&
+               typeof helpArr[0].content == 'object' &&
+               helpArr[0].content.length );
+    },
+
+    /**
+     *  Help.setActiveHelp
+     *  Sets the active help definition to the one defined in the argument,
+     *  re-rendering the help menu to match the new definition.
+     *
+     *  @param string  name  The name of the help definition.
+     *  @return void
+     */
+    setActiveHelp: function( name ) {
+      if ( !Help.isLoadedFor( name ) ) {
+        if ( $('#function-help').length ) {
+          $('#function-help').addClass('disabled');
+        }
+        if ( Help.isShown() ) {
+          Help.hide();
+        }
+      } else {
+        Help._ACTIVE_HELP_LANG = name;
+        if ( $("#function-help").length ) {
+          if ( $('#function-help').hasClass('disabled') ) {
+            $('#function-help').removeClass('disabled');
+          }
+          $('#function-help').unbind('click');
+          $('#function-help').click( Help.evtHelpButtonClick );
+          Help.generateHelpMenuFor( name );
+        }
+      }
+    },
+
+    /**
+     *  Help.evtHelpButtonClick
+     *  Event handler for clicking the help button in the function bar.
+     *
+     *  @param jQuery.Event e  The jQuery event object.
+     *  @return void
+     */
+    evtHelpButtonClick: function( e ) {
+      e.preventDefault();
+      if ( Help.isShown() ) {
+        // turn off autodisplay if it's on
+        if ( $('#gollum-editor-help').length &&
+             $('#gollum-editor-help').attr('data-autodisplay') !== 'undefined' &&
+             $('#gollum-editor-help').attr('data-autodisplay') === 'true' ) {
+          $.post('/wiki/help?_method=delete');
+          $('#gollum-editor-help').attr('data-autodisplay', '');
+        }
+        Help.hide(); }
+      else { Help.show(); }
+    },
+
+    /**
+     *  Help.evtParentMenuClick
+     *  Event handler for clicking on an item in the parent menu. Automatically
+     *  renders the submenu for the parent menu as well as the first result for
+     *  the actual plain text.
+     *
+     *  @param jQuery.Event e  The jQuery event object.
+     *  @return void
+     */
+    evtParentMenuClick: function( e ) {
+      e.preventDefault();
+      // short circuit if we've selected this already
+      if ( $(this).hasClass('selected') ) { return; }
+
+      // populate from help data for this
+      var helpIndex = $(this).attr('rel');
+      var subData = Help._HELP[Help._ACTIVE_HELP_LANG][helpIndex];
+
+      $('#gollum-editor-help-parent li a').removeClass('selected');
+      $(this).addClass('selected');
+      Help.generateSubMenu( subData, helpIndex );
+      $($('#gollum-editor-help-list li a').get(0)).click();
+    },
+
+    /**
+     *  Help.evtSubMenuClick
+     *  Event handler for clicking an item in a help submenu. Renders the
+     *  appropriate text for the submenu link.
+     *
+     *  @param jQuery.Event e  The jQuery event object.
+     *  @return void
+     */
+    evtSubMenuClick: function( e ) {
+      e.preventDefault();
+      if ( $(this).hasClass('selected') ) { return; }
+
+      // split index rel data
+      var rawIndex = $(this).attr('rel').split(':');
+      $('#gollum-editor-help-list li a').removeClass('selected');
+      $(this).addClass('selected');
+      Help.showHelpFor( rawIndex[0], rawIndex[1] );
+    }
+  };
+
+  // Publicly-accessible function to Help.define
+  $.GollumEditor.defineHelp = Help.define;
+
+  // Dialog exists as its own thing now
+  $.GollumEditor.Dialog = $.GollumDialog;
+  $.GollumEditor.replaceSelection = function( repText ) {
+    FunctionBar.replaceFieldSelection( $('#gollum-editor-body'), repText );
+  };
+
+  // Placeholder exists as its own thing now
+  $.GollumEditor.Placeholder = $.GollumPlaceholder;
+
+})(jQuery);
diff --git a/0.8.1-rc1/balance/modules/puny/static/js/editor/langs/markdown.js b/0.8.1-rc1/balance/modules/puny/static/js/editor/langs/markdown.js
new file mode 100644
index 0000000..1ac8e3b
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/js/editor/langs/markdown.js
@@ -0,0 +1,228 @@
+/*
+ * 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.
+ */
+
+/**
+ *  Markdown Language Definition
+ *
+ *  A language definition for string manipulation operations, in this case
+ *  for the Markdown, uh, markup language. Uses regexes for various functions
+ *  by default. If regexes won't do and you need to do some serious
+ *  manipulation, you can declare a function in the object instead.
+ *
+ *  Code example:
+ *  'functionbar-id'  :   {
+ *                          exec: function(text, selectedText) {
+ *                                   functionStuffHere();
+ *                                },
+ *                          search: /somesearchregex/gi,
+ *                          replace: 'replace text for RegExp.replace',
+ *                          append: "just add this where the cursor is"
+ *                         }
+ *
+**/
+(function($) {
+
+var MarkDown = {
+
+  'function-bold' :         {
+                              search: /([^\n]+)([\n\s]*)/g,
+                              replace: "**$1**$2"
+                            },
+
+  'function-italic' :       {
+                              search: /([^\n]+)([\n\s]*)/g,
+                              replace: "_$1_$2"
+                            },
+
+  'function-code'   :       {
+                              search: /(^[\n]+)([\n\s]*)/g,
+                              replace: "`$1`$2"
+                            },
+
+  'function-hr'     :       {
+                              append: "\n***\n"
+                            },
+
+  'function-ul'     :       {
+                              search: /(.+)([\n]?)/g,
+                              replace: "* $1$2"
+                            },
+
+  /* This looks silly but is completely valid Markdown */
+  'function-ol'   :         {
+                              search: /(.+)([\n]?)/g,
+                              replace: "1. $1$2"
+                            },
+
+  'function-blockquote' :   {
+                              search: /(.+)([\n]?)/g,
+                              replace: "> $1$2"
+                            },
+
+  'function-h1'         :   {
+                              search: /(.+)([\n]?)/g,
+                              replace: "# $1$2"
+                            },
+
+  'function-h2'         :   {
+                              search: /(.+)([\n]?)/g,
+                              replace: "## $1$2"
+                            },
+
+  'function-h3'         :   {
+                              search: /(.+)([\n]?)/g,
+                              replace: "### $1$2"
+                            },
+
+  'function-link'       :   {
+                              exec: function( txt, selText, $field ) {
+                                var results = null;
+                                $.GollumEditor.Dialog.init({
+                                  title: 'Insert Link',
+                                  fields: [
+                                    {
+                                      id:   'text',
+                                      name: 'Link Text',
+                                      type: 'text'
+                                    },
+                                    {
+                                      id:   'href',
+                                      name: 'URL',
+                                      type: 'text'
+                                    }
+                                  ],
+                                  OK: function( res ) {
+                                   var rep = '';
+                                   if ( res['text'] && res['href'] ) {
+                                      rep = '[' + res['text'] + '](' +
+                                             res['href'] + ')';
+                                    }
+                                    $.GollumEditor.replaceSelection( rep );
+                                  }
+                                });
+                              }
+                            },
+
+  'function-image'      :   {
+                              exec: function( txt, selText, $field ) {
+                                var results = null;
+                                $.GollumEditor.Dialog.init({
+                                  title: 'Insert Image',
+                                  fields: [
+                                    {
+                                      id: 'url',
+                                      name: 'Image URL',
+                                      type: 'text'
+                                    },
+                                    {
+                                      id: 'alt',
+                                      name: 'Alt Text',
+                                      type: 'text'
+                                    }
+                                  ],
+                                  OK: function( res ) {
+                                    var rep = '';
+                                    if ( res['url'] && res['alt'] ) {
+                                      rep = '![' + res['alt'] + ']' +
+                                            '(' + res['url'] + ')';
+                                    }
+                                    $.GollumEditor.replaceSelection( rep );
+                                  }
+                                });
+                              }
+                            }
+
+};
+
+var MarkDownHelp = [
+
+  {
+    menuName: 'Block Elements',
+    content: [
+                {
+                  menuName: 'Paragraphs &amp; Breaks',
+                  data: '<p>To create a paragraph, simply create a block of text that is not separated by one or more blank lines. Blocks of text separated by one or more blank lines will be parsed as paragraphs.</p><p>If you want to create a line break, end a line with two or more spaces, then hit Return/Enter.</p>'
+                },
+                {
+                  menuName: 'Headers',
+                  data: '<p>Markdown supports two header formats. The wiki editor uses the &ldquo;atx&rsquo;-style headers. Simply prefix your header text with the number of <code>#</code> characters to specify heading depth. For example: <code># Header 1</code>, <code>## Header 2</code> and <code>### Header 3</code> will be progressively smaller headers. You may end your headers with any number of hashes.</p>'
+                },
+                {
+                  menuName: 'Blockquotes',
+                  data: '<p>Markdown creates blockquotes email-style by prefixing each line with the <code>&gt;</code>. This looks best if you decide to hard-wrap text and prefix each line with a <code>&gt;</code> character, but Markdown supports just putting <code>&gt;</code> before your paragraph.</p>'
+                },
+                {
+                  menuName: 'Lists',
+                  data: '<p>Markdown supports both ordered and unordered lists. To create an ordered list, simply prefix each line with a number (any number will do &mdash; this is why the editor only uses one number.) To create an unordered list, you can prefix each line with <code>*</code>, <code>+</code> or <code>-</code>.</p> List items can contain multiple paragraphs, however each paragraph must be indented by at least 4 spaces or a tab.'
+                },
+                {
+                  menuName: 'Code Blocks',
+                  data: '<p>Markdown wraps code blocks in pre-formatted tags to preserve indentation in your code blocks. To create a code block, indent the entire block by at least 4 spaces or one tab. Markdown will strip the extra indentation you&rsquo;ve added to the code block.</p>'
+                },
+                {
+                  menuName: 'Horizontal Rules',
+                  data: 'Horizontal rules are created by placing three or more hyphens, asterisks or underscores on a line by themselves. Spaces are allowed between the hyphens, asterisks or underscores.'
+                }
+              ]
+  },
+
+  {
+    menuName: 'Span Elements',
+    content: [
+                {
+                  menuName: 'Links',
+                  data: '<p>Markdown has two types of links: <strong>inline</strong> and <strong>reference</strong>. For both types of links, the text you want to display to the user is placed in square brackets. For example, if you want your link to display the text &ldquo;GitHub&rdquo;, you write <code>[GitHub]</code>.</p><p>To create an inline link, create a set of parentheses immediately after the brackets and write your URL within the parentheses. (e.g., <code>[GitHub](http://github.com/)</code>). Relative paths are allowed in inline links.</p><p>To create a reference link, use two sets of square brackets. <code>[my internal link][internal-ref]</code> will link to the internal reference <code>internal-ref</code>.</p>'
+                },
+
+                {
+                  menuName: 'Emphasis',
+                  data: '<p>Asterisks (<code>*</code>) and underscores (<code>_</code>) are treated as emphasis and are wrapped with an <code>&lt;em&gt;</code> tag, which usually displays as italics in most browsers. Double asterisks (<code>**</code>) or double underscores (<code>__</code>) are treated as bold using the <code>&lt;strong&gt;</code> tag. To create italic or bold text, simply wrap your words in single/double asterisks/underscores. For example, <code>**My double emphasis text**</code> becomes <strong>My double emphasis text</strong>, and <code>*My single emphasis text*</code> becomes <em>My single emphasis text</em>.</p>'
+                },
+
+                {
+                  menuName: 'Code',
+                  data: '<p>To create inline spans of code, simply wrap the code in backticks (<code>`</code>). Markdown will turn <code>`myFunction`</code> into <code>myFunction</code>.</p>'
+                },
+
+                {
+                  menuName: 'Images',
+                  data: '<p>Markdown image syntax looks a lot like the syntax for links; it is essentially the same syntax preceded by an exclamation point (<code>!</code>). For example, if you want to link to an image at <code>http://github.com/unicorn.png</code> with the alternate text <code>My Unicorn</code>, you would write <code>![My Unicorn](http://github.com/unicorn.png)</code>.</p>'
+                }
+              ]
+  },
+
+  {
+    menuName: 'Miscellaneous',
+    content: [
+                {
+                  menuName: 'Automatic Links',
+                  data: '<p>If you want to create a link that displays the actual URL, markdown allows you to quickly wrap the URL in <code>&lt;</code> and <code>&gt;</code> to do so. For example, the link <a href="javascript:void(0);">http://github.com/</a> is easily produced by writing <code>&lt;http://github.com/&gt;</code>.</p>'
+                },
+
+                {
+                  menuName: 'Escaping',
+                  data: '<p>If you want to use a special Markdown character in your document (such as displaying literal asterisks), you can escape the character with the backslash (<code>\\</code>). Markdown will ignore the character directly after a backslash.'
+                }
+              ]
+  }
+];
+
+
+$.GollumEditor.defineLanguage('markdown', MarkDown);
+$.GollumEditor.defineHelp('markdown', MarkDownHelp);
+
+})(jQuery);
diff --git a/0.8.1-rc1/balance/modules/puny/static/js/gollum.dialog.js b/0.8.1-rc1/balance/modules/puny/static/js/gollum.dialog.js
new file mode 100644
index 0000000..6aecc7c
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/js/gollum.dialog.js
@@ -0,0 +1,279 @@
+/*
+ * 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.
+ */
+
+/**
+  *  gollum.dialog.js
+  *
+  *  Used for dialogs. Duh.
+  *
+  */
+
+(function($) {
+
+  var Dialog = {
+
+    debugOn: false,
+    markupCreated: false,
+    markup: '',
+
+    attachEvents: function( evtOK ) {
+      $('#gollum-dialog-action-ok').click(function( e ) {
+        Dialog.eventOK( e, evtOK );
+      });
+      $('#gollum-dialog-action-cancel').click( Dialog.eventCancel );
+      $('#gollum-dialog-dialog input[type="text"]').keydown(function( e ) {
+        if ( e.keyCode == 13 ) {
+          Dialog.eventOK( e, evtOK );
+        }
+      });
+    },
+
+    detachEvents: function() {
+      $('#gollum-dialog-action-ok').unbind('click');
+      $('#gollum-dialog-action-cancel').unbind('click');
+    },
+
+    createFieldMarkup: function( fieldArray ) {
+      var fieldMarkup = '<fieldset>';
+      for ( var i=0; i < fieldArray.length; i++ ) {
+        if ( typeof fieldArray[i] == 'object' ) {
+          fieldMarkup += '<div class="field">';
+          switch ( fieldArray[i].type ) {
+
+          // only text is supported for now
+          case 'text':
+            fieldMarkup += Dialog.createFieldText( fieldArray[i] );
+            break;
+
+          default:
+            break;
+
+          }
+          fieldMarkup += '</div>';
+        }
+
+      }
+      fieldMarkup += '</fieldset>';
+      return fieldMarkup;
+    },
+
+    createFieldText: function( fieldAttributes ) {
+      var html = '';
+
+      if ( fieldAttributes.name ) {
+        html += '<label';
+        if ( fieldAttributes.id ) {
+          html += ' for="' + fieldAttributes.name + '"';
+        }
+        html += '>' + fieldAttributes.name + '</label>';
+      }
+
+      html += '<input type="text"';
+
+      if ( fieldAttributes.id ) {
+        html += ' name="' + fieldAttributes.id + '"'
+        if ( fieldAttributes.type == 'code' ) {
+          html+= ' class="code"';
+        }
+        html += ' id="gollum-dialog-dialog-generated-field-' +
+          fieldAttributes.id + '">';
+      }
+
+      return html;
+    },
+
+    createMarkup: function( title, body ) {
+      Dialog.markupCreated = true;
+      if ($.facebox) {
+        return '<div id="gollum-dialog-dialog">' +
+               '<div id="gollum-dialog-dialog-title"><h4>' +
+               title +'</h4></div>' +
+               '<div id="gollum-dialog-dialog-body">' + body + '</div>' +
+               '<div id="gollum-dialog-dialog-buttons">' +
+               '<a href="#" title="Cancel" id="gollum-dialog-action-cancel" ' +
+               'class="gollum-minibutton">Cancel</a>' +
+               '<a href="#" title="OK" id="gollum-dialog-action-ok" '+
+               'class="gollum-minibutton">OK</a>' +
+               '</div>' +
+               '</div>';
+      } else {
+        return '<div id="gollum-dialog-dialog">' +
+               '<div id="gollum-dialog-dialog-inner">' +
+               '<div id="gollum-dialog-dialog-bg">' +
+               '<div id="gollum-dialog-dialog-title"><h4>' +
+               title +'</h4></div>' +
+               '<div id="gollum-dialog-dialog-body">' + body + '</div>' +
+               '<div id="gollum-dialog-dialog-buttons">' +
+               '<a href="#" title="Cancel" id="gollum-dialog-action-cancel" ' +
+               'class="minibutton">Cancel</a>' +
+               '<a href="#" title="OK" id="gollum-dialog-action-ok" '+
+               'class="minibutton">OK</a>' +
+               '</div>' +
+               '</div>' +
+               '</div>' +
+               '</div>';
+      }
+    },
+
+    eventCancel: function( e ) {
+      e.preventDefault();
+      debug('Cancelled dialog.');
+      Dialog.hide();
+    },
+
+    eventOK: function( e, evtOK ) {
+      e.preventDefault();
+
+      var results = [];
+      // get the results from each field and build them into the object
+      $('#gollum-dialog-dialog-body input').each(function() {
+        results[$(this).attr('name')] = $(this).val();
+      });
+
+      // pass them to evtOK if it exists (which it should)
+      if ( evtOK &&
+           typeof evtOK == 'function' ) {
+        evtOK( results );
+      }
+      Dialog.hide();
+    },
+
+    hide: function() {
+      if ( $.facebox ) {
+        Dialog.markupCreated = false;
+        $(document).trigger('close.facebox');
+        Dialog.detachEvents();
+      } else {
+        if ( $.browser.msie ) {
+          $('#gollum-dialog-dialog').hide().removeClass('active');
+          $('select').css('visibility', 'visible');
+        } else {
+          $('#gollum-dialog-dialog').animate({ opacity: 0 }, {
+            duration: 200,
+            complete: function() {
+              $('#gollum-dialog-dialog').removeClass('active');
+            }
+          });
+        }
+      }
+    },
+
+    init: function( argObject ) {
+      var title = '';
+      var body = '';
+
+      // bail out if necessary
+      if ( !argObject ||
+           typeof argObject != 'object' ) {
+        debug('Editor Dialog: Cannot init; invalid init object');
+        return;
+      }
+
+      if ( argObject.body && typeof argObject.body == 'string' ) {
+        body = '<p>' + argObject.body + '</p>';
+      }
+
+      // alright, build out fields
+      if ( argObject.fields && typeof argObject.fields == 'object' ) {
+        body += Dialog.createFieldMarkup( argObject.fields );
+      }
+
+      if ( argObject.title && typeof argObject.title == 'string' ) {
+        title = argObject.title;
+      }
+
+      if ( Dialog.markupCreated ) {
+        if ($.facebox) {
+          $(document).trigger('close.facebox');
+        } else {
+          $('#gollum-dialog-dialog').remove();
+        }
+      }
+
+      Dialog.markup = Dialog.createMarkup( title, body );
+
+      if ($.facebox) {
+        $(document).bind('reveal.facebox', function() {
+          if ( argObject.OK &&
+               typeof argObject.OK == 'function' ) {
+            Dialog.attachEvents( argObject.OK );
+            $($('#facebox input[type="text"]').get(0)).focus();
+          }
+        });
+      } else {
+        $('body').append( Dialog.markup );
+        if ( argObject.OK &&
+             typeof argObject.OK == 'function' ) {
+          Dialog.attachEvents( argObject.OK );
+        }
+      }
+
+      Dialog.show();
+    },
+
+    show: function() {
+      if ( !Dialog.markupCreated ) {
+        debug('Dialog: No markup to show. Please use init first.');
+      } else {
+        debug('Showing dialog');
+        if ($.facebox) {
+          $.facebox( Dialog.markup );
+        } else {
+          if ( $.browser.msie ) {
+            $('#gollum-dialog.dialog').addClass('active');
+            Dialog.position();
+            $('select').css('visibility', 'hidden');
+          } else {
+            $('#gollum-dialog.dialog').css('display', 'none');
+            $('#gollum-dialog-dialog').animate({ opacity: 0 }, {
+              duration: 0,
+              complete: function() {
+                $('#gollum-dialog-dialog').css('display', 'block');
+                Dialog.position(); // position this thing
+                $('#gollum-dialog-dialog').animate({ opacity: 1 }, {
+                duration: 500
+                });
+              }
+            });
+          }
+        }
+      }
+    },
+
+    position: function() {
+      var dialogHeight = $('#gollum-dialog-dialog-inner').height();
+      $('#gollum-dialog-dialog-inner')
+        .css('height', dialogHeight + 'px');
+    }
+  };
+
+  if ($.facebox) {
+    $(document).bind('reveal.facebox', function() {
+      $('#facebox img.close_image').remove();
+    });
+  }
+
+  var debug = function(m) {
+    if ( Dialog.debugOn
+         && typeof console != 'undefined' ) {
+      console.log( m );
+    }
+  };
+
+  $.GollumDialog = Dialog;
+
+})(jQuery);
diff --git a/0.8.1-rc1/balance/modules/puny/static/js/gollum.js b/0.8.1-rc1/balance/modules/puny/static/js/gollum.js
new file mode 100644
index 0000000..5acca0c
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/js/gollum.js
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+// ua
+$(document).ready(function() {
+  var nodeSelector = {
+    node1: null,
+    node2: null,
+
+    selectNodeRange: function( n1, n2 ) {
+      if ( nodeSelector.node1 && nodeSelector.node2 ) {
+        $('#wiki-history td.selected').removeClass('selected');
+        nodeSelector.node1.addClass('selected');
+        nodeSelector.node2.addClass('selected');
+
+        // swap the nodes around if they went in reverse
+        if ( nodeSelector.nodeComesAfter( nodeSelector.node1,
+                                          nodeSelector.node2 ) ) {
+          var n = nodeSelector.node1;
+          nodeSelector.node1 = nodeSelector.node2;
+          nodeSelector.node2 = n;
+        }
+
+        var s = true;
+        var $nextNode = nodeSelector.node1.next();
+        while ( $nextNode ) {
+          $nextNode.addClass('selected');
+          if ( $nextNode[0] == nodeSelector.node2[0] ) {
+            break;
+          }
+          $nextNode = $nextNode.next();
+        }
+      }
+    },
+
+    nodeComesAfter: function ( n1, n2 ) {
+      var s = false;
+      $(n1).prevAll().each(function() {
+        if ( $(this)[0] == $(n2)[0] ) {
+          s = true;
+        }
+      });
+      return s;
+    },
+
+    checkNode: function( nodeCheckbox ) {
+      var $nodeCheckbox = nodeCheckbox;
+      var $node = $(nodeCheckbox).parent().parent();
+      // if we're unchecking
+      if ( !$nodeCheckbox.is(':checked') ) {
+
+        // remove the range, since we're breaking it
+        $('#wiki-history tr.selected').each(function() {
+          if ( $(this).find('td.checkbox input').is(':checked') ) {
+            return;
+          }
+          $(this).removeClass('selected');
+        });
+
+        // no longer track this
+        if ( $node[0] == nodeSelector.node1[0] ) {
+          nodeSelector.node1 = null;
+          if ( nodeSelector.node2 ) {
+            nodeSelector.node1 = nodeSelector.node2;
+            nodeSelector.node2 = null;
+          }
+        } else if ( $node[0] == nodeSelector.node2[0] ) {
+          nodeSelector.node2 = null;
+        }
+
+      } else {
+        if ( !nodeSelector.node1 ) {
+          nodeSelector.node1 = $node;
+          nodeSelector.node1.addClass('selected');
+        } else if ( !nodeSelector.node2 ) {
+          // okay, we don't have a node 2 but have a node1
+          nodeSelector.node2 = $node;
+          nodeSelector.node2.addClass('selected');
+          nodeSelector.selectNodeRange( nodeSelector.node1,
+                                        nodeSelector.node2 );
+        } else {
+          // we have two selected already
+          $nodeCheckbox[0].checked = false;
+        }
+      }
+    }
+  };
+
+  // ua detection
+  if ($.browser.mozilla) {
+    $('body').addClass('ff');
+  } else if ($.browser.webkit) {
+    $('body').addClass('webkit');
+  } else if ($.browser.msie) {
+    $('body').addClass('ie');
+    if ($.browser.version == "7.0") {
+      $('body').addClass('ie7');
+    } else if ($.browser.version == "8.0") {
+      $('body').addClass('ie8');
+    }
+  }
+
+  if ($('#minibutton-new-page').length) {
+    $('#minibutton-new-page').removeClass('jaws');
+    $('#minibutton-new-page').click(function(e) {
+      e.preventDefault();
+      $.GollumDialog.init({
+                            title: 'Create New Page',
+                            fields: [
+                              {
+                                id:   'name',
+                                name: 'Page Name',
+                                type: 'text'
+                              }
+                            ],
+                            OK: function( res ) {
+                              var n = 'New Page';
+                              if ( res['name'] )
+                                var n = res['name'];
+                              n = encodeURIComponent( n );
+                              window.location = '/' + n;
+                            }
+                          });
+    });
+  }
+
+  if ($('#wiki-wrapper').hasClass('history')) {
+    $('#wiki-history td.checkbox input').each(function() {
+      $(this).click(function() {
+        nodeSelector.checkNode($(this));
+      });
+      if ( $(this).is(':checked') ) {
+        nodeSelector.checkNode($(this));
+      }
+    });
+
+    if ($('.history a.action-compare-revision').length) {
+      $('.history a.action-compare-revision').click(function() {
+        $("#version-form").submit();
+      });
+    }
+  }
+
+  if ($('#searchbar a#search-submit').length) {
+    $.GollumPlaceholder.add($('#searchbar #search-query'));
+    $('#searchbar a#search-submit').click(function(e) {
+      e.preventDefault();
+      $('#searchbar #search-form')[0].submit();
+    });
+    $('#searchbar #search-form').submit(function(e) {
+      $.GollumPlaceholder.clearAll();
+      $(this).unbind('submit');
+      $(this).submit();
+    });
+  }
+
+  if ($('#gollum-revert-form').length &&
+      $('.gollum-revert-button').length ) {
+    $('a.gollum-revert-button').click(function(e) {
+      e.preventDefault();
+      $('#gollum-revert-form').submit();
+    });
+  }
+});
diff --git a/0.8.1-rc1/balance/modules/puny/static/js/gollum.placeholder.js b/0.8.1-rc1/balance/modules/puny/static/js/gollum.placeholder.js
new file mode 100644
index 0000000..882f1bb
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/js/gollum.placeholder.js
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+(function($) {
+
+  var Placeholder = {
+   
+     _PLACEHOLDERS : [],
+   
+    _p : function( $field ) {
+    
+       this.fieldObject = $field; 
+       this.placeholderText = $field.val();
+       var placeholderText = $field.val();
+     
+       $field.addClass('ph');
+     
+       $field.blur(function() {
+         if ( $(this).val() == '' ) {
+           $(this).val( placeholderText );
+           $(this).addClass('ph');
+         }
+       });
+     
+       $field.focus(function() {
+         $(this).removeClass('ph');
+         if ( $(this).val() == placeholderText ) {
+           $(this).val('');
+         } else {
+           $(this)[0].select();
+         }
+       });
+     
+     },
+   
+     add : function( $field ) {
+       Placeholder._PLACEHOLDERS.push( new Placeholder._p( $field ) );
+     },
+   
+     clearAll: function() {
+       for ( var i=0; i < Placeholder._PLACEHOLDERS.length; i++ ) {
+         if ( Placeholder._PLACEHOLDERS[i].fieldObject.val() == 
+              Placeholder._PLACEHOLDERS[i].placeholderText ) {
+           Placeholder._PLACEHOLDERS[i].fieldObject.val('');
+         }
+       }
+     },
+   
+     exists : function() {
+       return ( _PLACEHOLDERS.length );
+     }
+   
+ };
+ 
+ $.GollumPlaceholder = Placeholder;
+ 
+})(jQuery);
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/static/js/jquery-1.7.2.min.js b/0.8.1-rc1/balance/modules/puny/static/js/jquery-1.7.2.min.js
new file mode 100644
index 0000000..93adea1
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/js/jquery-1.7.2.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.7.2 jquery.com | jquery.org/license */
+(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(
+a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f
+.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/static/js/puny.js b/0.8.1-rc1/balance/modules/puny/static/js/puny.js
new file mode 100644
index 0000000..a49888a
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/static/js/puny.js
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+/**
+ * Puny - A light-weight content editor for Balance applications
+ * 
+ * This library depends on JQuery v 1.4.1 or higher (http://www.jquery.com)
+ */
+$(document).ready(function() {
+	
+	// Support click-to-edit on puny elements
+	$('[puny]').live('click',function(event) {
+		punyInitEditor($(this));
+	});
+	// Enable the editor save button
+	$('#gollum-editor-submit').live('click', punyPersistChanges);
+	// Enable the editor cancel button
+	$('#gollum-editor-cancel').live('click', punyCancel);
+	
+});
+
+var editingResourceId = false;
+
+
+function punyInitEditor ( elmt ) {
+	editingResourceId = elmt.attr('puny');
+	window.location = puny_module_root + '/edit/' + editingResourceId;
+};
+
+function punyCancel() {
+	window.location = puny_current_url;
+}
+
+function punyPersistChanges(event) {
+	editingResourceId = $('#punyResourceId').val();
+	$.post( puny_module_root + '/store.do',{
+		'resourceId' : editingResourceId
+		, 'content'  : $('#gollum-editor-body').val()
+	},function( data ) {
+		window.location = puny_current_url;
+	}, 'json');
+}
diff --git a/0.8.1-rc1/balance/modules/puny/views/edit.php b/0.8.1-rc1/balance/modules/puny/views/edit.php
new file mode 100644
index 0000000..0c4ed32
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/views/edit.php
@@ -0,0 +1,141 @@
+<?php
+/*
+ * 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.
+ */
+
+$module = App::Get()->loadModule();
+
+// Pass the installed site root to javascript                                                                   
+App::Get()->response->addJavascript("var site_root = '" . SITE_ROOT . "';",true);
+				
+// Don't show a header or footer on this view
+App::Get()->response->useHeaderFile(false);
+App::Get()->response->useFooterFile(false);
+
+// Include the main Puny class
+require_once(App::Get()->settings['puny_module_path'] . '/classes/Puny.class.php');
+
+// Load the requested resource
+$resource = Puny::load(App::Get()->request->segments[0]);
+
+// Get the raw contents
+$content = $resource->getContent(true);
+?>
+
+<!-- JAVASCRIPTS -->
+<!-- STYLESHEETS -->
+<script type="text/javascript">
+	$(document).ready(function() {
+		$.GollumEditor();
+	});
+</script>
+
+
+<div id="wiki-wrapper" class="edit outer">
+  <div id="head">
+    <h1>Editing <strong><?php echo $resource->getId();?></strong></h1>
+    <p>(latest version: <?php echo $resource->getVersion();?>)</p>
+  </div>
+  <div id="wiki-content">
+		<div id="gollum-editor" data-escaped-name="Home" class="edit">
+				<input type="hidden" id="punyResourceId" name="punyResourceId" value="<?php echo $resource->getId()?>"/>
+
+					<div id="gollum-editor-function-bar">
+						<div id="gollum-editor-function-buttons">
+							<a href="#" id="function-h1" class="function-button" title="Header 1" tabindex="-1"> 
+								<span>Header 1</span> </a>
+							<a href="#" id="function-h2" class="function-button" title="Header 2" tabindex="-1">
+								<span>Header 2</span> </a> 
+							<a href="#" id="function-h3" class="function-button" title="Header 3" tabindex="-1">
+								<span>Header 3</span> </a> 
+							<span class="function-divider">&nbsp;</span> 
+							<a href="#" id="function-internal-link" class="function-button" title="Wiki Link" tabindex="-1">
+								<span>Wiki Link</span> </a> 
+							<a href="#" id="function-link" class="function-button" title="Link" tabindex="-1">
+								<span>Link</span> </a>
+							<a href="#" id="function-image" class="function-button" title="Image" tabindex="-1">
+								<span>Image</span> </a> 
+							<span class="function-divider">&nbsp;</span>
+							<a href="#" id="function-bold" class="function-button" title="Bold" tabindex="-1">
+								<span>Bold</span> </a>
+							<a href="#" id="function-italic" class="function-button" title="Italic" tabindex="-1">
+								<span>Italic</span> </a>
+							<a href="#" id="function-code" class="function-button" title="Code" tabindex="-1">
+								<span>Code</span> </a> 
+							<span class="function-divider">&nbsp;</span>
+							<a href="#" id="function-ul" class="function-button" title="Unordered List" tabindex="-1">
+								<span>Unordered List</span> </a> 
+							<a href="#" id="function-ol" class="function-button" title="Ordered List" tabindex="-1">
+								<span>Ordered List</span> </a>
+							<a href="#" id="function-blockquote" class="function-button" title="Blockquote" tabindex="-1">
+								<span>Blockquote</span> </a>
+							<a href="#" id="function-hr" class="function-button" title="Horizontal Rule" tabindex="-1">
+								<span>Horizontal Rule</span> </a> 
+							<span class="function-divider">&nbsp;</span>
+							<a href="#" id="function-help" class="function-button" title="Help" tabindex="-1">
+								<span>Help</span> </a>
+						</div>
+
+						<div id="gollum-editor-format-selector">
+							<!--  <select id="wiki_format" name="wiki[format]">
+								<option value="asciidoc">AsciiDoc</option>
+								<option value="creole">Creole</option>
+								<option value="markdown" selected="selected">Markdown</option>
+								<option value="mediawiki">MediaWiki</option>
+								<option value="org">Org-mode</option>
+								<option value="pod">Pod</option>
+								<option value="rdoc">RDoc</option>
+								<option value="textile">Textile</option>
+								<option value="rest">reStructuredText</option>
+							</select> -->
+							<label id="wiki_format" name="wiki[format]">Markdown</label>
+							<label for="wiki_format">Edit Mode</label>
+						</div>
+					</div>
+
+					<div id="gollum-editor-help" class="jaws" data-autodisplay=&quot;true&quot;>
+						<ul id="gollum-editor-help-parent">
+							<li></li>
+						</ul>
+						<ul id="gollum-editor-help-list">
+							<li></li>
+						</ul>
+						<div id="gollum-editor-help-wrapper">
+							<div id="gollum-editor-help-content">
+								<p></p>
+							</div>
+						</div>
+					</div>
+ 
+					<div id="gollum-error-message"></div>
+					<textarea data-markup-lang="markdown" format="markdown"
+						id="gollum-editor-body" name="punyContent"><?php echo stripslashes($content)?></textarea>
+<!-- Edit Message -->
+					<!--<div id="gollum-editor-edit-summary" class="singleline">
+						<label class="jaws" for="wiki_commit">Edit Message</label> 
+						<input id="gollum-editor-message-field" name="wiki[commit]"
+							placeholder="Write a small message here explaining this change. (Optional)"
+							type="text" />
+					</div> -->
+
+					<span class="jaws"><br> </span> 
+					<input id="gollum-editor-submit" class="gollum-editor-input" name="commit"
+						title="Save current changes" type="submit" value="Save" />
+					<input id="gollum-editor-cancel" class="gollum-editor-input" name="cancel"
+						title="Cancel changes" type="submit" value="Cancel" />
+		</div>
+	</div>
+</div>
diff --git a/0.8.1-rc1/balance/modules/puny/views/error.php b/0.8.1-rc1/balance/modules/puny/views/error.php
new file mode 100644
index 0000000..4576634
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/views/error.php
@@ -0,0 +1,31 @@
+<?php
+/*
+ * 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.
+ */
+
+	// Grab the most recent error from the session
+	$errorText = $_SESSION['puny_error'];
+	unset($_SESSION['puny_error']);
+	
+	// Don't show a header or footer for this view
+	App::Get()->response->useHeaderFile(false);
+	App::Get()->response->useFooterFile(false);
+
+?>
+
+<h1>Puny</h1>
+<h2>An error has occurred:</h2>
+<p><?php echo $errorText;?></p>
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/views/login.php b/0.8.1-rc1/balance/modules/puny/views/login.php
new file mode 100644
index 0000000..66f9ee8
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/views/login.php
@@ -0,0 +1,61 @@
+<?php
+/*
+ * 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.
+ */
+
+// Parse the Puny config file
+$module = App::Get()->loadModule();
+
+App::Get()->response->useHeaderFile(false);
+App::Get()->response->useFooterFile(false);
+
+?>
+<style type="text/css">
+div#login {
+	padding:15px;
+	width:800px;
+	background-color:#dfdfdf;
+	margin-bottom:none;
+	border:solid 5px #888;
+	font-size:1.2em;
+	color:#333;
+	-webkit-border-radius: 8px;
+	-moz-border-radius: 8px;
+	border-radius: 8px;
+}
+form {
+	margin:30px;
+}
+input {
+	padding:5px;
+	margin-right:5px;
+}
+label {
+	padding-right:5px;
+}
+</style>
+<center>
+<p>&nbsp;</p>
+<div id="login">
+<form method="POST" action="<?php echo $module->moduleRoot?>/login.do">
+<label>Username:</label>
+<input type="text" alt="username input" name="username"/>
+<label>Password:</label>
+<input type="password" alt="password input" name="password"/>
+<input type="submit" value="Login"/>
+</form>
+</div>
+</center>
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/views/logout.php b/0.8.1-rc1/balance/modules/puny/views/logout.php
new file mode 100644
index 0000000..fc2459c
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/views/logout.php
@@ -0,0 +1,32 @@
+<?php
+/*
+ * 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.
+ */
+
+// Parse the Puny config file
+$module = App::Get()->loadModule();
+
+// Include the main Puny class
+require_once($module->modulePath . '/classes/Puny.class.php');
+
+// Instantiate Puny
+$puny = new Puny();
+
+// Destroy the editor session
+$puny->destroyEditorSession();
+
+// Redirect home
+App::Get()->redirect(SITE_ROOT . '/');
\ No newline at end of file
diff --git a/0.8.1-rc1/balance/modules/puny/views/preview.php b/0.8.1-rc1/balance/modules/puny/views/preview.php
new file mode 100644
index 0000000..f14c92c
--- /dev/null
+++ b/0.8.1-rc1/balance/modules/puny/views/preview.php
@@ -0,0 +1,36 @@
+<?php
+/*
+ * 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.
+ */
+
+// Parse the Puny config file
+$module = App::Get()->loadModule();
+
+// Include the main Puny class
+require_once($module->modulePath . '/classes/Puny.class.php');
+
+// Instantiate Puny
+$puny = new Puny();
+
+// Obtain the parameters from the request
+$resourceId = App::Get()->request->segments[0];
+$versionId  = isset(App::Get()->request->segments[1]) ? App::Get()->request->segments[1] : null;
+
+// Load, parse, and display the requested resource
+echo $puny->load($resourceId, $versionId)->getContent();
+
+// we're done :)
+?>
\ No newline at end of file
diff --git a/0.8.1-rc1/catalog/pom.xml b/0.8.1-rc1/catalog/pom.xml
new file mode 100644
index 0000000..239f4db
--- /dev/null
+++ b/0.8.1-rc1/catalog/pom.xml
@@ -0,0 +1,211 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>cas-catalog</artifactId>
+  <name>OODT CAS Virtual Catalog and Integration Service.</name>
+  <description>CAS Catalog is an effort to virtualize underlying 
+  catalogs for use in the CAS system. Heterogeneous catalog models 
+  are mapped to a common dictionary, and then integrated locally so that
+  they may be queried across and ingested into.
+  </description>
+  <scm>
+   	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/catalog</connection>
+   	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/catalog</developerConnection>
+   	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/catalog</url>
+  </scm>
+  <profiles>
+    <profile>
+      <id>audit</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>rat-maven-plugin</artifactId>
+            <configuration>
+              <excludes>
+                <exclude>**/src/main/java/org/apache/oodt/cas/catalog/query/parser/*.java</exclude>
+              </excludes>
+            </configuration>
+            <executions>
+              <execution>
+                <phase>verify</phase>
+                <goals>
+                  <goal>check</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>tmpdir</id>
+      <activation>
+        <property>
+           <name>test.tmpdir</name>
+        </property>
+      </activation>
+       <build>
+        <plugins>
+         <plugin>
+          <artifactId>maven-surefire-plugin</artifactId>
+          <version>2.4.3</version>
+          <configuration>
+          <systemProperties>
+             <property>
+               <name>java.io.tmpdir</name>
+               <value>${test.tmpdir}</value>
+              </property>
+           </systemProperties>
+           </configuration>
+         </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-2</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/assembly/assembly.xml</descriptor>
+          </descriptors>
+          <archive />
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+    <resources>
+      <resource>
+        <targetPath>org/apache/oodt/cas/catalog/config</targetPath>
+        <directory>${basedir}/src/main/resources/policy</directory>
+        <includes>
+          <include>catserv-properties.xml</include>          
+          <include>catserv-beans.xml</include>    
+          <include>catserv-server-config.xml</include>
+          <include>catserv-server-cmd-line-beans.xml</include>          
+          <include>catserv-client-config.xml</include>                          
+          <include>catserv-client-action-beans.xml</include>          
+          <include>catserv-client-cmd-line-beans.xml</include>          
+        </includes>
+      </resource>
+    </resources>
+  </build>
+  <ciManagement>
+    <notifiers>
+      <notifier>
+        <configuration>
+          <address>chris.mattmann@jpl.nasa.gov</address>
+        </configuration>
+      </notifier>
+    </notifiers>
+  </ciManagement>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-commons</artifactId>
+      <version>${project.parent.version}</version>    
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-metadata</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-cli</artifactId>
+      <version>${project.parent.version}</version>    
+    </dependency>  
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+      <version>3.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.lucene</groupId>
+      <artifactId>lucene-core</artifactId>
+      <version>2.0.0</version>
+    </dependency>
+    <dependency>
+      <groupId>xmlrpc</groupId>
+      <artifactId>xmlrpc</artifactId>
+      <version>2.0.1</version>
+    </dependency>
+    <dependency>
+      <groupId>com.thoughtworks.xstream</groupId>
+      <artifactId>xstream</artifactId>
+      <version>1.3.1</version>
+      <exclusions>
+        <exclusion>
+          <!-- xom is an optional dependency of xstream. Its also an Apache incompatible license -->
+          <groupId>xom</groupId>
+          <artifactId>xom</artifactId>
+        </exclusion> 
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>hsqldb</groupId>
+      <artifactId>hsqldb</artifactId>
+      <version>1.8.0.7</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.12</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+<!-- 
+  <reporting>
+  	<plugins>
+  		<plugin>
+  			<groupId>org.apache.maven.plugins</groupId>
+  			<artifactId>maven-project-info-reports-plugin</artifactId>
+  			<version>2.4</version>
+  			<configuration>
+  				<checkoutDirectoryName>catalog</checkoutDirectoryName>
+  			</configuration>
+  		</plugin>
+  	</plugins>
+  </reporting>
+-->
+</project>
diff --git a/0.8.1-rc1/catalog/src/main/assembly/assembly.xml b/0.8.1-rc1/catalog/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..28e832f
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/assembly/assembly.xml
@@ -0,0 +1,77 @@
+<!-- 
+  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.
+-->

+<assembly>

+  <id>dist</id>

+  <formats>

+    <format>tar.gz</format>
+    <format>zip</format>

+  </formats>

+  <includeBaseDirectory>true</includeBaseDirectory>
+  <baseDirectory>${project.artifactId}-${project.version}</baseDirectory>  
+  <includeSiteDirectory>false</includeSiteDirectory>

+  <fileSets>

+    <fileSet>

+      <directory>${basedir}</directory>

+      <outputDirectory>.</outputDirectory>

+      <includes>

+        <include>LICENSE.txt</include>

+        <include>CHANGES.txt</include>

+      </includes>

+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/bin</directory>
+      <outputDirectory>bin</outputDirectory>
+      <includes/>
+      <fileMode>755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>etc</outputDirectory>
+      <includes>
+        <include>**.properties</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>logs</outputDirectory>
+      <includes>
+        <include>REMOVE.log</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>etc</outputDirectory>
+      <includes>
+        <include>**.properties</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/policy</directory>
+      <outputDirectory>policy</outputDirectory>
+      <includes/>
+    </fileSet>

+  </fileSets>

+  <dependencySets>

+    <dependencySet>

+      <outputDirectory>lib</outputDirectory>

+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>

+      <unpackOptions/>

+    </dependencySet>

+  </dependencySets>

+</assembly>

diff --git a/0.8.1-rc1/catalog/src/main/bin/catserv-client b/0.8.1-rc1/catalog/src/main/bin/catserv-client
new file mode 100644
index 0000000..babfd25
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/bin/catserv-client
@@ -0,0 +1,33 @@
+#!/bin/csh
+
+###########################################################################
+# 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.
+###########################################################################
+
+set args
+
+if ( $#args > 0 ) then
+        set args = "$*"
+endif
+
+setenv CATALOG_HOME `pwd`/..
+
+${JAVA_HOME}/bin/java \
+        -Djava.ext.dirs=../lib \
+        -Djava.util.logging.config.file=../etc/logging.properties \
+        -Dorg.apache.oodt.cas.cli.action.spring.config=../policy/cmd-line-actions.xml \
+        -Dorg.apache.oodt.cas.cli.option.spring.config=../policy/cmd-line-options.xml \
+        org.apache.oodt.cas.catalog.server.CatalogServiceCommandLineClient ${args}
diff --git a/0.8.1-rc1/catalog/src/main/bin/catserv-server b/0.8.1-rc1/catalog/src/main/bin/catserv-server
new file mode 100644
index 0000000..bd21233
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/bin/catserv-server
@@ -0,0 +1,33 @@
+#!/bin/csh
+
+###########################################################################
+# 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.
+###########################################################################
+
+set args
+
+if ( $#args > 0 ) then
+        set args = "$*"
+endif
+
+setenv CATALOG_HOME `pwd`/..
+
+${JAVA_HOME}/bin/java \
+        -Djava.ext.dirs=../lib \
+        -Djava.util.logging.config.file=../etc/logging.properties \
+        -Dorg.apache.oodt.cas.cli.action.spring.config=../policy/cmd-line-server-actions.xml \
+        -Dorg.apache.oodt.cas.cli.option.spring.config=../policy/cmd-line-server-options.xml \
+        org.apache.oodt.cas.catalog.server.CatalogServiceServerLauncher ${args}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/CatalogServiceCliAction.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/CatalogServiceCliAction.java
new file mode 100644
index 0000000..0cd80ff
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/CatalogServiceCliAction.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.server.channel.CommunicationChannelClientFactory;
+import org.apache.oodt.cas.catalog.server.channel.xmlrpc.XmlRpcCommunicationChannelClientFactory;
+import org.apache.oodt.cas.catalog.system.impl.CatalogServiceClient;
+import org.apache.oodt.cas.catalog.system.impl.CatalogServiceClientFactory;
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+
+/**
+ * Base Catalog Service {@link CmdLineAction}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public abstract class CatalogServiceCliAction extends CmdLineAction {
+
+   private CatalogServiceClient client;
+
+   private String getUrl() {
+      return System.getProperty("org.apache.oodt.cas.catalog.url");
+   }
+
+   private int getChunkSize() {
+      return Integer.getInteger("org.apache.oodt.cas.catalog.chunkSize", 1024);
+   }
+
+   private int getRequestTimeout() {
+      return Integer.getInteger("org.apache.oodt.cas.catalog.requestTimeout", 20);
+   }
+
+   private int getConnectionTimeout() {
+      return Integer.getInteger("org.apache.oodt.cas.catalog.connectionTimeout", 60);
+   }
+
+   private int getAutoPagerSize() {
+      return Integer.getInteger("org.apache.oodt.cas.catalog.autoPagerSize", 1000);
+   }
+
+   public CatalogServiceClient getClient() {
+      if (client == null) {
+         CatalogServiceClientFactory factory = new CatalogServiceClientFactory();
+         factory.setCommunicationChannelClientFactory(getCommunicationChannelFactory());
+         factory.setAutoPagerSize(getAutoPagerSize());
+         return client = factory.createCatalogService();
+      } else {
+         return client;
+      }
+   }
+
+   private CommunicationChannelClientFactory getCommunicationChannelFactory() {
+      XmlRpcCommunicationChannelClientFactory factory = new XmlRpcCommunicationChannelClientFactory();
+      factory.setServerUrl(getUrl());
+      factory.setChunkSize(getChunkSize());
+      factory.setRequestTimeout(getRequestTimeout());
+      factory.setConnectionTimeout(getConnectionTimeout());
+      return factory;
+   }
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/GetSupportedCatalogIdsCliAction.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/GetSupportedCatalogIdsCliAction.java
new file mode 100644
index 0000000..450e657
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/GetSupportedCatalogIdsCliAction.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.system.impl.CatalogServiceClient;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which get a list of supported {@link Catalog}
+ * IDs for given {@link CatalogServiceClient}.
+ *
+ * @author bfoster (Brian Foster) 
+ */
+public class GetSupportedCatalogIdsCliAction extends CatalogServiceCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         printer.println("CatalogIDs: " + getClient().getCurrentCatalogIds());
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get supported Catalog IDs : " + e.getMessage(), e);
+      }
+   }
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/LoadCatalogRepositoryCliAction.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/LoadCatalogRepositoryCliAction.java
new file mode 100644
index 0000000..82cdddb
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/LoadCatalogRepositoryCliAction.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.cli.action;
+
+//JDK imports
+import java.util.Set;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.repository.CatalogRepository;
+import org.apache.oodt.cas.catalog.repository.CatalogRepositoryFactory;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.util.Serializer;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+//Spring imports
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+/**
+ * A {@link CmdLineAction} which allows {@link Catalog}s to be loaded from
+ * an existing {@link CatalogRepositoryFactory} and to be add to a running
+ * Catalog Service from an existing Spring bean XML file.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class LoadCatalogRepositoryCliAction extends CatalogServiceCliAction {
+
+   protected String catalogRepositoryId;
+   protected String beanRepo;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(catalogRepositoryId, "Must specify catalogRepositoryId");
+         Validate.notNull(beanRepo, "Must specify beanRepo");
+
+         FileSystemXmlApplicationContext appContext = new FileSystemXmlApplicationContext(
+               new String[] { this.beanRepo }, false);
+         appContext.setClassLoader(new Serializer().getClassLoader());
+         appContext.refresh();
+         CatalogRepositoryFactory factory = (CatalogRepositoryFactory) appContext
+               .getBean(this.catalogRepositoryId, CatalogRepositoryFactory.class);
+         CatalogRepository catalogRepository = factory.createRepository();
+         Set<Catalog> catalogs = catalogRepository.deserializeAllCatalogs();
+         printer.println("Deserialized Catalogs: " + catalogs.toString());
+         for (Catalog catalog : catalogs) {
+            printer.println("Adding Catalog: " + catalog);
+            getClient().addCatalog(catalog);
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to load catalogs from bean repo : " + e.getMessage(), e);
+      }
+   }
+
+   public void setCatalogRepositoryId(String catalogRepositoryId) {
+      this.catalogRepositoryId = catalogRepositoryId;
+   }
+
+   public void setBeanRepo(String beanRepo) {
+      this.beanRepo = beanRepo;
+   }
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/LoadCatalogsCliAction.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/LoadCatalogsCliAction.java
new file mode 100644
index 0000000..72637b2
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/LoadCatalogsCliAction.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.cli.action;
+
+//JDK imports
+import java.util.Map;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.util.Serializer;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+//Spring imports
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+/**
+ * A {@link CmdLineAction} which loads {@link Catalog}s from a Spring XML file
+ * and adds them to the running Catalog Service.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class LoadCatalogsCliAction extends CatalogServiceCliAction {
+
+   protected String beanRepo;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(beanRepo, "Must specify beanRepo");
+
+         FileSystemXmlApplicationContext repoAppContext =
+            new FileSystemXmlApplicationContext(
+               new String[] { this.beanRepo }, false);
+         repoAppContext.setClassLoader(new Serializer().getClassLoader());
+         repoAppContext.refresh();
+         @SuppressWarnings("unchecked")
+         Map<String, Catalog> catalogs = repoAppContext
+               .getBeansOfType(Catalog.class);
+         for (Catalog catalog : catalogs.values()) {
+            printer.println("Adding catalog: " + catalog.getId());
+            getClient().addCatalog(catalog);
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to load catalogs : "
+               + e.getMessage(), e);
+      }
+   }
+
+   public void setBeanRepo(String beanRepo) {
+      this.beanRepo = beanRepo;
+   }
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/PagedQueryCliAction.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/PagedQueryCliAction.java
new file mode 100644
index 0000000..0fef91a
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/PagedQueryCliAction.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.cli.action;
+
+//JDK imports
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.Page;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.query.parser.QueryParser;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+
+/**
+ * @author bfoster (Brian Foster)
+ */
+public class PagedQueryCliAction extends CatalogServiceCliAction {
+
+   protected int pageNum = -1;
+   protected int pageSize = -1;
+   protected String query;
+   protected Set<String> catalogIds;
+
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.isTrue(pageNum != -1, "Must specify pageNum");
+         Validate.isTrue(pageSize != -1, "Must specify pageSize");
+         Validate.notNull(query, "Must specify query");
+
+         QueryExpression queryExpression = QueryParser
+               .parseQueryExpression(query);
+         Page page = null;
+         if (catalogIds == null) {
+            page = getClient().getPage(new PageInfo(pageSize, pageNum),
+                  queryExpression);
+         } else {
+            page = getClient().getPage(new PageInfo(pageSize, pageNum),
+                  queryExpression, catalogIds);
+         }
+         List<TransactionalMetadata> transactionMetadatas = getClient()
+               .getMetadata(page);
+         for (TransactionalMetadata tMet : transactionMetadatas) {
+            printer.print("ID: " + tMet.getTransactionId() + " ; CatalogIDs: "
+                  + tMet.getCatalogIds() + " ; Metadata: (");
+            StringBuffer sb = new StringBuffer("");
+            for (Object metKey : tMet.getMetadata().getHashtable().keySet()) {
+               sb.append(metKey
+                     + "="
+                     + tMet.getMetadata().getAllMetadata((String) metKey)
+                           .toString().replaceAll("[\\[\\]]", "'") + ", ");
+            }
+            printer.println(sb.substring(0, sb.length() - 2) + ")");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to perform query '" + query
+               + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setPageSize(int pageSize) {
+      this.pageSize = pageSize;
+   }
+
+   public void setPageNum(int pageNum) {
+      this.pageNum = pageNum;
+   }
+
+   public void setQuery(String query) {
+      this.query = query;
+   }
+
+   public void setCatalogIds(List<String> catalogIds) {
+      this.catalogIds = new HashSet<String>(catalogIds);
+   }
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/QueryCliAction.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/QueryCliAction.java
new file mode 100644
index 0000000..a896e13
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/QueryCliAction.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.cli.action;
+
+//JDK imports
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.query.parser.QueryParser;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which queries Catalog Service.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class QueryCliAction  extends CatalogServiceCliAction {
+
+   protected String query;
+   protected Set<String> catalogIds;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(query, "Must specify query");
+
+         QueryExpression queryExpression = QueryParser
+               .parseQueryExpression(query);
+         QueryPager queryPager = null;
+         if (catalogIds == null) {
+            queryPager = getClient().query(queryExpression);
+         } else {
+            queryPager = getClient().query(queryExpression, catalogIds);
+         }
+         List<TransactionalMetadata> transactionMetadatas = getClient()
+               .getAllPages(queryPager);
+         for (TransactionalMetadata tMet : transactionMetadatas) {
+            printer.print("ID: " + tMet.getTransactionId() + " ; CatalogIDs: "
+                  + tMet.getCatalogIds() + " ; Metadata: (");
+            StringBuffer sb = new StringBuffer("");
+            for (Object metKey : tMet.getMetadata().getHashtable().keySet()) {
+               sb.append(metKey
+                     + "="
+                     + tMet.getMetadata().getAllMetadata((String) metKey)
+                           .toString().replaceAll("[\\[\\]]", "'") + ", ");
+            }
+            printer.println(sb.substring(0, sb.length() - 2) + ")");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to perform query '" + query
+               + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setQuery(String query) {
+      this.query = query;
+   }
+
+   public void setCatalogIds(List<String> catalogIds) {
+      this.catalogIds = new HashSet<String>(catalogIds);
+   }
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/ReducedPagedQueryCliAction.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/ReducedPagedQueryCliAction.java
new file mode 100644
index 0000000..a6a0574
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/ReducedPagedQueryCliAction.java
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.cli.action;
+
+//JDK imports
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+//Apache imports
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.Page;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.query.parser.QueryParser;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which queries Catalog Service.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class ReducedPagedQueryCliAction extends CatalogServiceCliAction {
+
+   protected int pageNum = -1;
+   protected int pageSize = -1;
+   protected String query;
+   protected Set<String> catalogIds;
+   protected List<String> termNames;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.isTrue(pageNum != -1, "Must specify pageNum");
+         Validate.isTrue(pageSize != -1, "Must specify pageSize");
+         Validate.notNull(query, "Must specify query");
+         Validate.notNull(termNames, "Must specify termNames");
+
+         QueryExpression queryExpression = QueryParser
+               .parseQueryExpression(query);
+         Page page = null;
+         if (catalogIds == null) {
+            page = getClient().getPage(new PageInfo(pageSize, pageNum),
+                  queryExpression);
+         } else {
+            page = getClient().getPage(new PageInfo(pageSize, pageNum),
+                  queryExpression, catalogIds);
+         }
+         List<TransactionalMetadata> transactionMetadatas = getClient()
+               .getMetadata(page);
+         for (TransactionalMetadata tMet : transactionMetadatas) {
+            StringBuffer sb = new StringBuffer("");
+            for (String termName : this.termNames) {
+               List<String> values = tMet.getMetadata().getAllMetadata(
+                     (String) termName);
+               sb.append(termName
+                     + " = '"
+                     + (values == null ? "null" : StringUtils.join(
+                           values.iterator(), ",")) + "', ");
+            }
+            printer.println(sb.substring(0, sb.length() - 2));
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to perform query '" + query
+               + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setPageSize(int pageSize) {
+      this.pageSize = pageSize;
+   }
+
+   public void setPageNum(int pageNum) {
+      this.pageNum = pageNum;
+   }
+
+   public void setQuery(String query) {
+      this.query = query;
+   }
+
+   public void setCatalogIds(List<String> catalogIds) {
+      this.catalogIds = new HashSet<String>(catalogIds);
+   }
+
+   public void setReducedTerms(List<String> termNames) {
+      this.termNames = termNames;
+   }
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/ReducedQueryCliAction.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/ReducedQueryCliAction.java
new file mode 100644
index 0000000..8753db7
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/ReducedQueryCliAction.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.cli.action;
+
+//JDK imports
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+//Apache imports
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.query.parser.QueryParser;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which queries the Catalog Service and limits the
+ * results to a subset of given terms.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class ReducedQueryCliAction extends CatalogServiceCliAction {
+
+   protected String query;
+   protected Set<String> catalogIds;
+   protected List<String> termNames;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(query, "Must specify query");
+         Validate.notNull(termNames, "Must specify termNames");
+
+         QueryExpression queryExpression = QueryParser
+               .parseQueryExpression(query);
+         QueryPager queryPager = null;
+         if (catalogIds == null) {
+            queryPager = getClient().query(queryExpression);
+         } else {
+            queryPager = getClient().query(queryExpression, catalogIds);
+         }
+         List<TransactionalMetadata> transactionMetadatas = getClient()
+               .getAllPages(queryPager);
+         for (TransactionalMetadata tMet : transactionMetadatas) {
+            StringBuffer sb = new StringBuffer("");
+            for (String termName : this.termNames) {
+               List<String> values = tMet.getMetadata().getAllMetadata(
+                     (String) termName);
+               sb.append(termName
+                     + " = '"
+                     + (values == null ? "null" : StringUtils.join(
+                           values.iterator(), ",")) + "', ");
+            }
+            printer.println(sb.substring(0, sb.length() - 2));
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("", e);
+      }
+   }
+
+   public void setQuery(String query) {
+      this.query = query;
+   }
+
+   public void setCatalogIds(List<String> catalogIds) {
+      this.catalogIds = new HashSet<String>(catalogIds);
+   }
+
+   public void setReducedTerms(List<String> termNames) {
+      this.termNames = termNames;
+   }
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/ShutdownCliAction.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/ShutdownCliAction.java
new file mode 100644
index 0000000..384492f
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/cli/action/ShutdownCliAction.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which shuts down Catalog Service server.
+ * @author bfoster (Brian Foster)
+ */
+public class ShutdownCliAction extends CatalogServiceCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         getClient().shutdown();
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to shutdown server : "
+               + e.getMessage(), e);
+      }
+   }
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogDictionaryException.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogDictionaryException.java
new file mode 100644
index 0000000..899bedb
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogDictionaryException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.catalog.exception;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class CatalogDictionaryException extends Exception {
+
+	private static final long serialVersionUID = 7734987410778199955L;
+
+	public CatalogDictionaryException() {
+		super();
+	}
+	
+	public CatalogDictionaryException(String msg) {
+		super(msg);
+	}
+	
+	public CatalogDictionaryException(String msg, Throwable throwable) {
+		super(msg, throwable);
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogException.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogException.java
new file mode 100644
index 0000000..3225559
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.exception;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class CatalogException extends Exception {
+
+	private static final long serialVersionUID = 7734987410778199955L;
+
+	public CatalogException() {
+		super();
+	}
+	
+	public CatalogException(String msg) {
+		super(msg);
+	}
+	
+	public CatalogException(String msg, Throwable throwable) {
+		super(msg, throwable);
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogIndexException.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogIndexException.java
new file mode 100644
index 0000000..37529d8
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogIndexException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.exception;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class CatalogIndexException extends Exception {
+
+	private static final long serialVersionUID = 7734987410778199955L;
+
+	public CatalogIndexException() {
+		super();
+	}
+	
+	public CatalogIndexException(String msg) {
+		super(msg);
+	}
+	
+	public CatalogIndexException(String msg, Throwable throwable) {
+		super(msg, throwable);
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogRepositoryException.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogRepositoryException.java
new file mode 100644
index 0000000..ee9042f
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogRepositoryException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.exception;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class CatalogRepositoryException extends Exception {
+
+	private static final long serialVersionUID = 7734987410778199955L;
+
+	public CatalogRepositoryException() {
+		super();
+	}
+	
+	public CatalogRepositoryException(String msg) {
+		super(msg);
+	}
+	
+	public CatalogRepositoryException(String msg, Throwable throwable) {
+		super(msg, throwable);
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogServiceException.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogServiceException.java
new file mode 100644
index 0000000..880ffba
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/CatalogServiceException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.exception;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class CatalogServiceException extends Exception {
+
+	private static final long serialVersionUID = 7734987410778199955L;
+
+	public CatalogServiceException() {
+		super();
+	}
+	
+	public CatalogServiceException(String msg) {
+		super(msg);
+	}
+	
+	public CatalogServiceException(String msg, Throwable throwable) {
+		super(msg, throwable);
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/IngestServiceException.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/IngestServiceException.java
new file mode 100644
index 0000000..e61001b
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/IngestServiceException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.exception;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class IngestServiceException extends Exception {
+
+	private static final long serialVersionUID = 7734987410778199955L;
+
+	public IngestServiceException() {
+		super();
+	}
+	
+	public IngestServiceException(String msg) {
+		super(msg);
+	}
+	
+	public IngestServiceException(String msg, Throwable throwable) {
+		super(msg, throwable);
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/QueryServiceException.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/QueryServiceException.java
new file mode 100644
index 0000000..5e25883
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/exception/QueryServiceException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.exception;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class QueryServiceException extends Exception {
+
+	private static final long serialVersionUID = 7734987410778199955L;
+
+	public QueryServiceException() {
+		super();
+	}
+	
+	public QueryServiceException(String msg) {
+		super(msg);
+	}
+	
+	public QueryServiceException(String msg, Throwable throwable) {
+		super(msg, throwable);
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/DataSourceIngestMapper.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/DataSourceIngestMapper.java
new file mode 100644
index 0000000..2f77735
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/DataSourceIngestMapper.java
@@ -0,0 +1,342 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.mapping;
+
+//JDK imports
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+//SQL imports
+import javax.sql.DataSource;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogRepositoryException;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.IndexPager;
+import org.apache.oodt.cas.catalog.page.IngestReceipt;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.struct.TransactionIdFactory;
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+import org.apache.oodt.commons.date.DateUtils;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Ingest Mapper that indexes to an DataSource Database
+ * <p>
+ */
+public class DataSourceIngestMapper implements IngestMapper {
+
+	protected DataSource dataSource;
+	
+	public DataSourceIngestMapper(String user, String pass, String driver,
+			String jdbcUrl) throws InstantiationException {
+		this.dataSource = DatabaseConnectionBuilder.buildDataSource(user, pass,
+                driver, jdbcUrl);
+	}
+	
+	public synchronized void deleteAllMappingsForCatalog(String catalogId)
+			throws CatalogRepositoryException {
+		Connection conn = null;
+		Statement stmt = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			stmt.execute("DELETE FROM CatalogServiceMapper WHERE CATALOG_ID = '" + catalogId + "'");
+		}catch (Exception e) {
+			throw new CatalogRepositoryException(e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	public synchronized void deleteAllMappingsForCatalogServiceTransactionId(
+			TransactionId<?> catalogServiceTransactionId)
+			throws CatalogRepositoryException {
+		Connection conn = null;
+		Statement stmt = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			stmt.execute("DELETE FROM CatalogServiceMapper WHERE CAT_SERV_TRANS_ID = '" + catalogServiceTransactionId + "'");
+			conn.commit();
+		}catch (Exception e) {
+			throw new CatalogRepositoryException(e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	public synchronized void deleteTransactionIdMapping(
+			TransactionId<?> catalogTransactionId, String catalogId)
+			throws CatalogRepositoryException {
+		Connection conn = null;
+		Statement stmt = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			stmt.execute("DELETE FROM CatalogServiceMapper WHERE CAT_TRANS_ID = '" + catalogTransactionId + "' AND CATALOG_ID = '" + catalogId + "'");
+			conn.commit();
+		}catch (Exception e) {
+			throw new CatalogRepositoryException(e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	public synchronized TransactionId<?> getCatalogServiceTransactionId(
+			TransactionId<?> catalogTransactionId, String catalogId)
+			throws CatalogRepositoryException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			rs = stmt.executeQuery("SELECT CAT_SERV_TRANS_ID,CAT_SERV_TRANS_FACTORY FROM CatalogServiceMapper WHERE CAT_TRANS_ID = '"+ catalogTransactionId + "' AND CATALOG_ID = '" + catalogId + "'");
+			
+			while(rs.next())
+				return ((TransactionIdFactory) Class.forName(rs.getString("CAT_SERV_TRANS_FACTORY")).newInstance()).createTransactionId(rs.getString("CAT_SERV_TRANS_ID"));
+
+			return null;
+		}catch (Exception e) {
+			throw new CatalogRepositoryException(e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	public synchronized TransactionId<?> getCatalogTransactionId(
+			TransactionId<?> catalogServiceTransactionId, String catalogId)
+			throws CatalogRepositoryException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			rs = stmt.executeQuery("SELECT CAT_TRANS_ID,CAT_TRANS_FACTORY FROM CatalogServiceMapper WHERE CAT_SERV_TRANS_ID = '"+ catalogServiceTransactionId + "' AND CATALOG_ID = '" + catalogId + "'");
+			
+			while(rs.next())
+				return ((TransactionIdFactory) Class.forName(rs.getString("CAT_TRANS_FACTORY")).newInstance()).createTransactionId(rs.getString("CAT_TRANS_ID"));
+
+			return null;
+		}catch (Exception e) {
+			throw new CatalogRepositoryException(e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	public synchronized Set<String> getCatalogIds(
+			TransactionId<?> catalogServiceTransactionId)
+			throws CatalogRepositoryException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			rs = stmt.executeQuery("SELECT CATALOG_ID FROM CatalogServiceMapper WHERE CAT_SERV_TRANS_ID = '"+ catalogServiceTransactionId + "'");
+			
+			Set<String> catalogIds = new HashSet<String>();
+			while(rs.next())
+				catalogIds.add(rs.getString("CATALOG_ID"));
+
+			return catalogIds;
+		}catch (Exception e) {
+			throw new CatalogRepositoryException(e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}	
+	}
+
+	public synchronized Set<TransactionId<?>> getPageOfCatalogTransactionIds(
+			IndexPager indexPager, String catalogId)
+			throws CatalogRepositoryException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			rs = stmt.executeQuery(
+				"SELECT * FROM "
+					+"( SELECT a.*, ROWNUM r FROM " 
+						+ "( SELECT CAT_TRANS_FACTORY,CAT_TRANS_ID FROM CatalogServiceMapper WHERE CatalogServiceMapper.CATALOG_ID = '" + catalogId + "' ORDER BY CatalogServiceMapper.CAT_SERV_TRANS_ID DESC ) a "
+					+ "WHERE ROWNUM <= " + (indexPager.getPageSize() * (indexPager.getPageNum() + 1)) + " ) "
+				+ "WHERE r >= " + ((indexPager.getPageSize() * indexPager.getPageNum()) + 1));
+			
+			Set<TransactionId<?>> transactionIds = new HashSet<TransactionId<?>>();
+			while(rs.next())
+				transactionIds.add(((TransactionIdFactory) Class.forName(rs.getString("CAT_TRANS_FACTORY")).newInstance()).createTransactionId(rs.getString("CAT_TRANS_ID")));
+				
+			return transactionIds;
+		}catch (Exception e) {
+			throw new CatalogRepositoryException(e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	public synchronized boolean hasCatalogServiceTransactionId(
+			TransactionId<?> catalogServiceTransactionId)
+			throws CatalogRepositoryException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			rs = stmt.executeQuery("SELECT CAT_SERV_TRANS_ID FROM CatalogServiceMapper WHERE CAT_SERV_TRANS_ID = '"+ catalogServiceTransactionId + "'");
+			return rs.next();
+		}catch (Exception e) {
+			throw new CatalogRepositoryException(e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	public synchronized void storeTransactionIdMapping(
+			TransactionId<?> catalogServiceTransactionId,
+			TransactionIdFactory catalogServiceTransactionIdFactory,
+			CatalogReceipt catalogReceipt,
+			TransactionIdFactory catalogTransactionIdFactory)
+			throws CatalogRepositoryException { 
+		Connection conn = null;
+		Statement stmt = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			Calendar calTime = DateUtils.getCurrentUtcTime();
+			calTime.setTime(catalogReceipt.getTransactionDate());
+			stmt.execute("INSERT INTO CatalogServiceMapper (CAT_SERV_TRANS_ID, CAT_SERV_TRANS_FACTORY, CAT_TRANS_ID, CAT_TRANS_FACTORY, CAT_TRANS_DATE, CATALOG_ID) VALUES ('" 
+					+ catalogServiceTransactionId + "', '" 
+					+ catalogServiceTransactionIdFactory.getClass().getName() + "', '" 
+					+ catalogReceipt.getTransactionId() + "', '" 
+					+ catalogTransactionIdFactory.getClass().getName() + "', '" 
+					+ DateUtils.toString(calTime) + "', '"
+					+ catalogReceipt.getCatalogId() + "')");
+			conn.commit();
+		}catch (Exception e) {
+			throw new CatalogRepositoryException(e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	public CatalogReceipt getCatalogReceipt(
+			TransactionId<?> catalogServiceTransactionId, String catalogId)
+			throws CatalogRepositoryException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			rs = stmt.executeQuery("SELECT CAT_TRANS_ID, CAT_TRANS_FACTORY, CAT_TRANS_DATE FROM CatalogServiceMapper WHERE CAT_SERV_TRANS_ID = '"+ catalogServiceTransactionId + "' AND CATALOG_ID = '" + catalogId + "'");
+			
+			if(rs.next()) {
+				TransactionId<?> catalogTransactionId =  ((TransactionIdFactory) Class.forName(rs.getString("CAT_TRANS_FACTORY")).newInstance()).createTransactionId(rs.getString("CAT_TRANS_ID"));
+				Date transactionDate = DateUtils.toCalendar(rs.getString("CAT_TRANS_DATE"), DateUtils.FormatType.UTC_FORMAT).getTime();
+				return new CatalogReceipt(new IngestReceipt(catalogTransactionId, transactionDate), catalogId);
+			}else {
+				return null;
+			}
+		}catch (Exception e) {
+			throw new CatalogRepositoryException(e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/DataSourceIngestMapperFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/DataSourceIngestMapperFactory.java
new file mode 100644
index 0000000..056e035
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/DataSourceIngestMapperFactory.java
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.mapping;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+//OODT imports
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory for creating DataSourceIngestMapper
+ * <p>
+ */
+public class DataSourceIngestMapperFactory implements IngestMapperFactory {
+
+    protected String jdbcUrl;
+    protected String user;
+    protected String pass;
+    protected String driver;
+	
+	public DataSourceIngestMapperFactory() {}
+
+	public String getJdbcUrl() {
+		return jdbcUrl;
+	}
+
+	@Required
+	public void setJdbcUrl(String jdbcUrl) {
+		this.jdbcUrl = jdbcUrl;
+	}
+
+	public String getUser() {
+		return user;
+	}
+	
+	@Required
+	public void setUser(String user) {
+		this.user = user;
+	}
+
+	public String getPass() {
+		return pass;
+	}
+
+	@Required
+	public void setPass(String pass) {
+		this.pass = pass;
+	}
+
+	public String getDriver() {
+		return driver;
+	}
+
+	@Required
+	public void setDriver(String driver) {
+		this.driver = driver;
+	}
+	
+	public IngestMapper createMapper() {
+		try {
+			return new DataSourceIngestMapper(user, pass,
+	                driver, jdbcUrl);
+		}catch (Exception e) {
+			e.printStackTrace();
+			return null;
+		}
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/InMemoryIngestMapper.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/InMemoryIngestMapper.java
new file mode 100644
index 0000000..dc04816
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/InMemoryIngestMapper.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.mapping;
+
+//OODT imports
+import org.apache.oodt.commons.database.SqlScript;
+
+//JDK imports
+import java.io.File;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class InMemoryIngestMapper extends DataSourceIngestMapper {
+
+	public InMemoryIngestMapper(String user, String pass, String driver,
+			String jdbcUrl, String tablesFile) throws Exception {
+		super(user, pass, driver, jdbcUrl);
+        SqlScript coreSchemaScript = new SqlScript(new File(tablesFile).getAbsolutePath(), this.dataSource);
+        coreSchemaScript.loadScript();
+        coreSchemaScript.execute();
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/InMemoryIngestMapperFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/InMemoryIngestMapperFactory.java
new file mode 100644
index 0000000..8d79e41
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/InMemoryIngestMapperFactory.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.mapping;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.struct.impl.index.InMemoryIndexFactory;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class InMemoryIngestMapperFactory extends DataSourceIngestMapperFactory {
+
+	private static final Logger LOG = Logger.getLogger(InMemoryIndexFactory.class.getName());
+	
+	protected String tablesFile;
+	
+	@Override
+	public InMemoryIngestMapper createMapper() {
+		try {
+			return new InMemoryIngestMapper(user, pass,
+	                driver, jdbcUrl, this.tablesFile);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed to create InMemoryIndex : " + e.getMessage(), e);
+			return null;
+		}
+	}
+	
+	public void setTablesFile(String tablesFile) {
+		this.tablesFile = tablesFile;
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/IngestMapper.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/IngestMapper.java
new file mode 100644
index 0000000..556c161
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/IngestMapper.java
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.mapping;
+
+//JDK imports
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogRepositoryException;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.IndexPager;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.struct.TransactionIdFactory;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * An Interface Ingest Mapper that indexes transaction ids to catalog transaction ids and catlaog ids
+ * <p>
+ */
+public interface IngestMapper {
+
+	/**
+	 * Maps the three arguments to each other so any of the others can be
+	 * retrieved via one of the other arguments
+	 * 
+	 * @param catalogId
+	 *            The ID that uniquely represents a catalog
+	 * @param catalogServiceTransactionId
+	 *            TransactionId generated by the CatalogService
+	 * @param catalogTransactionId
+	 *            The TransactionId used by the Catalog given (maybe the same as
+	 *            catalogServiceTransactionId, maybe different)
+	 * @throws CatalogRepositoryException
+	 *             Any error
+	 */
+	public void storeTransactionIdMapping(
+			TransactionId<?> catalogServiceTransactionId, TransactionIdFactory catalogServiceTransactionIdFactory,
+			CatalogReceipt catalogReceipt, TransactionIdFactory catalogTransactionIdFactory)
+			throws CatalogRepositoryException;
+
+	public Set<TransactionId<?>> getPageOfCatalogTransactionIds(IndexPager indexPager,
+			String catalogId) throws CatalogRepositoryException;
+	
+	public void deleteTransactionIdMapping(TransactionId<?> catalogTransactionId, 
+			String catalogId) throws CatalogRepositoryException;
+	
+	public void deleteAllMappingsForCatalogServiceTransactionId(
+			TransactionId<?> catalogServiceTransactionId)
+			throws CatalogRepositoryException;
+	
+	public void deleteAllMappingsForCatalog(String catalogId)
+			throws CatalogRepositoryException;
+	
+	/**
+	 * Verify if the given CatalogService TransactionId has been stored in a
+	 * mapping {@link storeTransactionIdMapping(String, TransactionId<?>,
+	 * TransactionId<?>)}
+	 * 
+	 * @param catalogServiceTransactionId
+	 *            The CatalogService TransactionId in question
+	 * @return True is the catalogServiceTransactionId has been used in a used in a mapping
+	 * @throws CatalogRepositoryException
+	 *             Any error
+	 */
+	public boolean hasCatalogServiceTransactionId(
+			TransactionId<?> catalogServiceTransactionId)
+			throws CatalogRepositoryException;
+
+	/**
+	 * Get the CatalogService TransactionId that was mapped to the given Catalog
+	 * URN and Catalog TransactionId
+	 * 
+	 * @param catalogTransactionId
+	 *            A Catalog TransactionId
+	 * @param catalogId
+	 *            A unique Catalog ID when the Catalog TransactionId was used
+	 * @return The CatalogService TransactionId which was mapped to the given
+	 *         Catalog TransactionId and Catalog ID
+	 * @throws CatalogRepositoryException
+	 *             Any Error
+	 */
+	public TransactionId<?> getCatalogServiceTransactionId(
+			TransactionId<?> catalogTransactionId, String catalogId)
+			throws CatalogRepositoryException;
+
+	/**
+	 * Get the Catalog TransactionId that was mapped to the given Catalog ID
+	 * and CatalogService TransactionId
+	 * 
+	 * @param catalogServiceTransactionId
+	 *            A Catalog TransactionId
+	 * @param catalogId
+	 *            A unique Catalog ID when the Catalog TransactionId was used
+	 * @return The CatalogService TransactionId which was mapped to the given
+	 *         Catalog TransactionId and Catalog ID
+	 * @throws CatalogRepositoryException
+	 *             Any Error
+	 */
+	public TransactionId<?> getCatalogTransactionId(
+			TransactionId<?> catalogServiceTransactionId, String catalogId)
+			throws CatalogRepositoryException;
+
+	/**
+	 * Get all the Catalog URNs for which the given TransactionId was mapped
+	 * 
+	 * @param catalogServiceTransactionId
+	 *            A CatalogService TransactionId
+	 * @return Catalog IDs for which the given TransactionId was mapped
+	 * @throws CatalogRepositoryException
+	 *             Any Error
+	 */
+	public Set<String> getCatalogIds(
+			TransactionId<?> catalogServiceTransactionId)
+			throws CatalogRepositoryException;
+	
+	/**
+	 * 
+	 * @param catalogServiceTransactionId
+	 * @param catalogId
+	 * @return
+	 * @throws CatalogRepositoryException
+	 */
+	public CatalogReceipt getCatalogReceipt(
+			TransactionId<?> catalogServiceTransactionId, String catalogId)
+			throws CatalogRepositoryException;
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/IngestMapperFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/IngestMapperFactory.java
new file mode 100644
index 0000000..1127a01
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/IngestMapperFactory.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.mapping;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory for creating IngestMapper
+ * <p>
+ */
+public interface IngestMapperFactory {
+
+	public IngestMapper createMapper();
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/LuceneIngestMapper.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/LuceneIngestMapper.java
new file mode 100644
index 0000000..231480c
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/LuceneIngestMapper.java
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.mapping;
+
+//JDK imports
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogRepositoryException;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.IndexPager;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.struct.TransactionIdFactory;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Ingest Mapper that indexes to a Lucene index
+ * <p>
+ */
+public class LuceneIngestMapper implements IngestMapper {
+
+	public void deleteAllMappingsForCatalog(String catalogId)
+			throws CatalogRepositoryException {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void deleteAllMappingsForCatalogServiceTransactionId(
+			TransactionId<?> catalogServiceTransactionId)
+			throws CatalogRepositoryException {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void deleteTransactionIdMapping(
+			TransactionId<?> catalogTransactionId, String catalogId)
+			throws CatalogRepositoryException {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public CatalogReceipt getCatalogReceipt(
+			TransactionId<?> catalogServiceTransactionId, String catalogId)
+			throws CatalogRepositoryException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public TransactionId<?> getCatalogServiceTransactionId(
+			TransactionId<?> catalogTransactionId, String catalogId)
+			throws CatalogRepositoryException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public TransactionId<?> getCatalogTransactionId(
+			TransactionId<?> catalogServiceTransactionId, String catalogId)
+			throws CatalogRepositoryException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Set<String> getCatalogIds(
+			TransactionId<?> catalogServiceTransactionId)
+			throws CatalogRepositoryException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Set<TransactionId<?>> getPageOfCatalogTransactionIds(
+			IndexPager indexPager, String catalogId)
+			throws CatalogRepositoryException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public boolean hasCatalogServiceTransactionId(
+			TransactionId<?> catalogServiceTransactionId)
+			throws CatalogRepositoryException {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	public void storeTransactionIdMapping(
+			TransactionId<?> catalogServiceTransactionId,
+			TransactionIdFactory catalogServiceTransactionIdFactory,
+			CatalogReceipt catalogReceipt,
+			TransactionIdFactory catalogTransactionIdFactory)
+			throws CatalogRepositoryException {
+		// TODO Auto-generated method stub
+		
+	}
+
+
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/LuceneIngestMapperFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/LuceneIngestMapperFactory.java
new file mode 100644
index 0000000..dee45ce
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/LuceneIngestMapperFactory.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.mapping;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory for creating LuceneIngestMapper
+ * <p>
+ */
+public class LuceneIngestMapperFactory implements
+		IngestMapperFactory {
+
+	public IngestMapper createMapper() {
+		return new LuceneIngestMapper();
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/MemoryBasedIngestMapper.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/MemoryBasedIngestMapper.java
new file mode 100644
index 0000000..872b7d7
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/MemoryBasedIngestMapper.java
@@ -0,0 +1,291 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.mapping;
+
+//JDK imports
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogRepositoryException;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.IndexPager;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.struct.TransactionIdFactory;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Ingest Mapper that indexes to local memory
+ * <p>
+ */
+public class MemoryBasedIngestMapper implements IngestMapper {
+
+	private static Logger LOG = Logger.getLogger(MemoryBasedIngestMapper.class.getName());
+	
+	protected HashMap<String, TransactionIdMapping> catalogServiceTransactionIdKeyMapping;
+	protected HashMap<String, TransactionIdMapping> catalogInfoKeyMapping;
+	protected HashMap<String, List<CatalogReceipt>> catalogIdToCatalogReceiptMapping;
+	
+	public MemoryBasedIngestMapper() {
+		this.catalogServiceTransactionIdKeyMapping = new HashMap<String, TransactionIdMapping>();
+		this.catalogInfoKeyMapping = new HashMap<String, TransactionIdMapping>();
+		this.catalogIdToCatalogReceiptMapping = new HashMap<String, List<CatalogReceipt>>();
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @seeorg.apache.oodt.cas.catalog.repository.CatalogRepository#
+	 * getCatalogServiceTransactionId
+	 * (org.apache.oodt.cas.catalog.struct.TransactionId, java.lang.String)
+	 */
+	public synchronized TransactionId<?> getCatalogServiceTransactionId(
+			TransactionId<?> catalogTransactionId, String catalogId)
+			throws CatalogRepositoryException {
+		LOG.log(Level.INFO, "Looking up CatalogService TransactionId for Catalog TransactionId '" + catalogTransactionId + "' and catalog '" + catalogId + "'");
+		String key = generateKey(catalogTransactionId.toString(), catalogId);
+//		System.out.println("LOOKING UP: " + key);
+		TransactionIdMapping mapping = this.catalogInfoKeyMapping.get(key);
+		if (mapping != null) {
+			return mapping.catalogServiceTransactionId;
+		}else {
+			return null;
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @seeorg.apache.oodt.cas.catalog.repository.CatalogRepository#
+	 * getCatalogTransactionId
+	 * (org.apache.oodt.cas.catalog.struct.TransactionId, java.lang.String)
+	 */
+	public synchronized TransactionId<?> getCatalogTransactionId(
+			TransactionId<?> catalogServiceTransactionId, String catalogId)
+			throws CatalogRepositoryException {
+		TransactionIdMapping mapping = this.catalogServiceTransactionIdKeyMapping
+				.get(catalogServiceTransactionId.toString());
+		if (mapping != null)
+			for (CatalogReceipt receipt : mapping.getCatalogReceipts())
+				if (receipt.getCatalogId().equals(catalogId))
+					return receipt.getTransactionId();
+		return null;
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.apache.oodt.cas.catalog.mapping.IngestMapper#getPage(org.apache
+	 * .oodt.cas.catalog.page.IndexPager, java.lang.String)
+	 */
+	public synchronized Set<TransactionId<?>> getPageOfCatalogTransactionIds(IndexPager indexPager,
+			String catalogId) throws CatalogRepositoryException {
+		Set<TransactionId<?>> catalogTransactionIds = new HashSet<TransactionId<?>>();
+		List<CatalogReceipt> catalogReceipts = this.catalogIdToCatalogReceiptMapping.get(catalogId);
+		if (catalogReceipts != null) 
+			for (int i = indexPager.getPageNum() * indexPager.getPageSize(); i < catalogReceipts.size() && i < (indexPager.getPageNum() + 1) * indexPager.getPageSize(); i++) 
+				catalogTransactionIds.add(catalogReceipts.get(i).getTransactionId());
+		return catalogTransactionIds;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.apache.oodt.cas.catalog.mapping.IngestMapper#deleteAllMappingsForCatalog(java.lang.String)
+	 */
+	public synchronized void deleteAllMappingsForCatalog(String catalogId)
+			throws CatalogRepositoryException {
+		List<CatalogReceipt> catalogReceipts = this.catalogIdToCatalogReceiptMapping.remove(catalogId);
+		if (catalogReceipts != null) {
+			for (CatalogReceipt catalogReceipt : catalogReceipts) {
+				TransactionIdMapping mapping = this.catalogInfoKeyMapping.remove(generateKey(catalogReceipt.getTransactionId().toString(), catalogReceipt.getCatalogId()));
+				if (mapping != null)
+					mapping.getCatalogReceipts().remove(catalogReceipt);
+			}
+		}		
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.apache.oodt.cas.catalog.repository.CatalogRepository#deleteAllMappingsForCatalogServiceTransactionId(org.apache.oodt.cas.catalog.struct.TransactionId)
+	 */
+	public synchronized void deleteAllMappingsForCatalogServiceTransactionId(
+			TransactionId<?> catalogServiceTransactionId)
+			throws CatalogRepositoryException {
+		TransactionIdMapping mapping = this.catalogServiceTransactionIdKeyMapping.remove(catalogServiceTransactionId.toString());
+		if (mapping != null)
+			for (CatalogReceipt catalogReceipt : mapping.getCatalogReceipts()) {
+				this.catalogIdToCatalogReceiptMapping.get(catalogReceipt.getCatalogId()).remove(catalogReceipt);
+				this.catalogInfoKeyMapping.remove(generateKey(catalogReceipt.getTransactionId().toString(), catalogReceipt.getCatalogId()));
+			}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.apache.oodt.cas.catalog.repository.CatalogRepository#deleteTransactionIdMapping(org.apache.oodt.cas.catalog.struct.TransactionId, org.apache.oodt.cas.catalog.struct.TransactionId, java.lang.String)
+	 */
+	public synchronized void deleteTransactionIdMapping(
+			TransactionId<?> catalogTransactionId, String catalogId)
+			throws CatalogRepositoryException {
+		List<CatalogReceipt> catalogReceipts = this.catalogIdToCatalogReceiptMapping.get(catalogId);
+		for (int i = 0; i < catalogReceipts.size(); i++) {
+			if (catalogReceipts.get(i).getCatalogId().equals(catalogId) && catalogReceipts.get(i).getTransactionId().equals(catalogTransactionId)) {
+				catalogReceipts.remove(i);
+				break;
+			}
+		}
+		TransactionIdMapping mapping = this.catalogInfoKeyMapping.remove(generateKey(catalogTransactionId.toString(), catalogId));
+		this.catalogServiceTransactionIdKeyMapping.remove(mapping.getCatalogServiceTransactionId().toString());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.apache.oodt.cas.catalog.repository.CatalogRepository#hasCatalogServiceTransactionId(org.apache.oodt.cas.catalog.struct.TransactionId)
+	 */
+	public synchronized boolean hasCatalogServiceTransactionId(
+			TransactionId<?> catalogServiceTransactionId)
+			throws CatalogRepositoryException {
+		return this.catalogServiceTransactionIdKeyMapping.containsKey(catalogServiceTransactionId.toString());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @seeorg.apache.oodt.cas.catalog.repository.CatalogRepository#
+	 * storeTransactionIdMapping(java.lang.String,
+	 * org.apache.oodt.cas.catalog.struct.TransactionId,
+	 * org.apache.oodt.cas.catalog.struct.TransactionId)
+	 */
+	public synchronized void storeTransactionIdMapping(
+			TransactionId<?> catalogServiceTransactionId,
+			TransactionIdFactory catalogServiceTransactionIdFactory,
+			CatalogReceipt catalogReceipt,
+			TransactionIdFactory catalogTransactionIdFactory)
+			throws CatalogRepositoryException { 
+		TransactionIdMapping mapping = this.catalogServiceTransactionIdKeyMapping
+				.get(catalogServiceTransactionId.toString());
+		if (mapping == null)
+			mapping = new TransactionIdMapping(catalogServiceTransactionId);
+		mapping.addCatalogReceipt(catalogReceipt);
+		this.catalogServiceTransactionIdKeyMapping.put(
+				catalogServiceTransactionId.toString(), mapping);
+		this.catalogInfoKeyMapping.put(generateKey(catalogReceipt.getTransactionId().toString(), catalogReceipt.getCatalogId()), mapping);
+		List<CatalogReceipt> catalogReceipts = this.catalogIdToCatalogReceiptMapping.get(catalogReceipt.getCatalogId());
+		if (catalogReceipts == null)
+			catalogReceipts = new Vector<CatalogReceipt>();
+		catalogReceipts.add(catalogReceipt);
+		this.catalogIdToCatalogReceiptMapping.put(catalogReceipt.getCatalogId(), catalogReceipts);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.apache.oodt.cas.catalog.repository.CatalogRepository#getCatalogs
+	 * (org.apache.oodt.cas.catalog.struct.TransactionId)
+	 */
+	public synchronized Set<String> getCatalogIds(
+			TransactionId<?> catalogServiceTransactionId)
+			throws CatalogRepositoryException {
+		HashSet<String> catalogs = new HashSet<String>();
+		TransactionIdMapping mapping = this.catalogServiceTransactionIdKeyMapping
+				.get(catalogServiceTransactionId.toString());
+		for (CatalogReceipt catalogReceipt : mapping.getCatalogReceipts())
+			catalogs.add(catalogReceipt.getCatalogId());
+		return catalogs;
+	}
+
+	public CatalogReceipt getCatalogReceipt(
+			TransactionId<?> catalogServiceTransactionId, String catalogId)
+			throws CatalogRepositoryException {
+		TransactionIdMapping mapping = this.catalogServiceTransactionIdKeyMapping.get(catalogServiceTransactionId);
+		for (CatalogReceipt catalogReceipt : mapping.getCatalogReceipts())
+			if (catalogReceipt.getCatalogId().equals(catalogId))
+				return catalogReceipt;
+		return null;
+	}
+
+	private static String generateKey(String catalogTransactionId, String catalogId) {
+		return catalogTransactionId + ":" + catalogId;
+	}
+	
+	private class TransactionIdMapping {
+
+		private TransactionId<?> catalogServiceTransactionId;
+		List<CatalogReceipt> catalogReceipts;
+
+		public TransactionIdMapping(TransactionId<?> catalogServiceTransactionId) {
+			this.catalogServiceTransactionId = catalogServiceTransactionId;
+			this.catalogReceipts = new Vector<CatalogReceipt>();
+		}
+
+		public void addCatalogReceipt(CatalogReceipt catalogReceipt) {
+			this.catalogReceipts.add(catalogReceipt);
+		}
+
+		public List<CatalogReceipt> getCatalogReceipts() {
+			return this.catalogReceipts;
+		}
+
+		public TransactionId<?> getCatalogServiceTransactionId() {
+			return catalogServiceTransactionId;
+		}
+
+	}
+
+//	private class CatalogInfo {
+//
+//		private String catalogId;
+//		private TransactionId<?> catalogTransactionId;
+//
+//		public CatalogInfo(String catalogId,
+//				TransactionId<?> catalogTransactionId) {
+//			this.catalogId = catalogId;
+//			this.catalogTransactionId = catalogTransactionId;
+//		}
+//
+//		public String getCatalogUrn() {
+//			return this.catalogId;
+//		}
+//
+//		public TransactionId<?> getCatalogTransactionId() {
+//			return this.catalogTransactionId;
+//		}
+//		
+//		public boolean equals(Object obj) {
+//			if (obj instanceof CatalogInfo) {
+//				return this.toString().equals(obj.toString());
+//			}else {
+//				return false;
+//			}
+//		}
+//		
+//		public String toString() {
+//			return this.catalogId + ":" + this.catalogTransactionId;
+//		}
+//
+//	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/MemoryBasedIngestMapperFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/MemoryBasedIngestMapperFactory.java
new file mode 100644
index 0000000..d7fe89b
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/mapping/MemoryBasedIngestMapperFactory.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.mapping;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory for creating MemoryBasedIngestMapper
+ * <p>
+ */
+public class MemoryBasedIngestMapperFactory implements IngestMapperFactory {
+
+	public IngestMapper createMapper() {
+		return new MemoryBasedIngestMapper();
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/metadata/TransactionalMetadata.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/metadata/TransactionalMetadata.java
new file mode 100644
index 0000000..7474581
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/metadata/TransactionalMetadata.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.metadata;
+
+//JDK imports
+import java.util.Date;
+import java.util.Set;
+
+//APACHE imports
+import org.apache.commons.lang.StringUtils;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.page.TransactionReceipt;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.system.CatalogService;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * Metadata tied to a Transaction
+ * <p>
+ */
+public class TransactionalMetadata {
+
+	protected TransactionReceipt receipt;
+	protected Metadata metadata;
+	
+	public TransactionalMetadata(TransactionReceipt receipt, Metadata metadata) {
+		this.receipt = receipt;
+		this.metadata = metadata;
+		this.metadata.replaceMetadata(CatalogService.CATALOG_SERVICE_TRANSACTION_ID_MET_KEY, this.receipt.getTransactionId().toString());
+		this.metadata.replaceMetadata(CatalogService.CATALOG_IDS_MET_KEY, StringUtils.join(this.receipt.getCatalogIds().iterator(), ","));
+	}
+
+	public TransactionId<?> getTransactionId() {
+		return receipt.getTransactionId();
+	}
+
+	public Set<String> getCatalogIds() {
+		return receipt.getCatalogIds();
+	}
+	
+	public Date getTransactionDate() {
+		return receipt.getTransactionDate();
+	}
+	
+	public Metadata getMetadata() {
+		return metadata;
+	}
+	
+	@Override
+	public int hashCode() {
+		return this.getTransactionId().hashCode();
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/CatalogReceipt.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/CatalogReceipt.java
new file mode 100644
index 0000000..417390a
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/CatalogReceipt.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.page;
+
+//JDK imports
+import java.util.Date;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class CatalogReceipt {
+
+	protected TransactionId<?> transactionId;
+	protected Date transactionDate;
+	protected String catalogId;
+	
+	public CatalogReceipt(IngestReceipt ingestReceipt, String catalogId) {
+		this.transactionId = ingestReceipt.getCatalogTransactionId();
+		this.transactionDate = ingestReceipt.getTransactionDate();
+		this.catalogId = catalogId;
+	}
+	
+	public TransactionId<?> getTransactionId() {
+		return this.transactionId;
+	}
+
+	public Date getTransactionDate() {
+		return this.transactionDate;
+	}
+
+	public String getCatalogId() {
+		return this.catalogId;
+	}
+	
+	public boolean equals(Object obj) {
+		if (obj instanceof CatalogReceipt) {
+			CatalogReceipt compareTo = (CatalogReceipt) obj;
+			return this.transactionId.equals(compareTo.transactionId) && this.transactionDate.equals(compareTo.transactionDate) && this.catalogId.equals(compareTo.catalogId);
+		}else {
+			return false;
+		}
+	}
+	
+	public int hashCode() {
+		return this.toString().hashCode();
+	}
+	
+	public String toString() {
+		return ("{CatalogReceipt(tID=" + this.transactionId + ",tDate=" + this.transactionDate + ",catID=" + this.catalogId + ")}");
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/IndexPager.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/IndexPager.java
new file mode 100644
index 0000000..4ba61a3
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/IndexPager.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.page;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A pager for paging through a index
+ * <p>
+ */
+public class IndexPager {
+
+	protected int pageSize;
+	protected int pageNum;
+	protected int totalPages;
+	protected int numOfHits;
+	
+	public IndexPager() {
+		this.pageSize = 20;
+		this.pageNum = 1;
+		this.totalPages = 0;
+	}
+	
+	public IndexPager(ProcessedPageInfo processedPageInfo) {
+		this.pageSize = processedPageInfo.getPageSize();
+		this.pageNum = processedPageInfo.getPageNum();
+		this.totalPages = processedPageInfo.getTotalPages();
+		this.numOfHits = processedPageInfo.getNumOfHits();
+	}
+	
+	public ProcessedPageInfo getProcessedPageInfo() {
+		return new ProcessedPageInfo(this.pageSize, this.pageNum, this.numOfHits);
+	}
+	
+	public int getPageSize() {
+		return this.pageSize;
+	}
+	
+	public int getPageNum() {
+		return this.pageNum;
+	}
+	
+	public int getTotalPages() {
+		return this.totalPages;
+	}
+	
+	public int getNumOfHits() {
+		return this.numOfHits;
+	}
+
+	public void incrementPageNumber() {
+		if (this.pageNum + 1 <= this.totalPages)
+			this.pageNum++;
+	}
+	
+	public boolean isLastPage() {
+		return this.getProcessedPageInfo().isLastPage();
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/IngestReceipt.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/IngestReceipt.java
new file mode 100644
index 0000000..f6e0b38
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/IngestReceipt.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.page;
+
+//JDK imports
+import java.util.Date;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class IngestReceipt {
+
+	protected TransactionId<?> catalogTransactionId;
+	protected Date transactionDate;
+	
+	public IngestReceipt(TransactionId<?> catalogTransactionId, Date transactionDate) {
+		this.catalogTransactionId = catalogTransactionId;
+		this.transactionDate = transactionDate;
+	}
+	
+	public TransactionId<?> getCatalogTransactionId() {
+		return this.catalogTransactionId;
+	}
+	
+	public Date getTransactionDate() {
+		return this.transactionDate;
+	}
+	
+	public int hashCode() {
+		return this.catalogTransactionId.hashCode();
+	}
+	
+	public String toString() {
+		return this.catalogTransactionId.toString() + " : " + this.transactionDate.toString();
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/Page.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/Page.java
new file mode 100644
index 0000000..be5dce3
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/Page.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.page;
+
+//JDK imports
+import java.util.List;
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class Page {
+
+	protected List<TransactionReceipt> receipts;
+	protected ProcessedPageInfo processedPageInfo;
+	protected QueryExpression queryExpression;
+	protected Set<String> restrictToCatalogIds;
+	
+	public Page(ProcessedPageInfo pageInfo, QueryExpression queryExpression, Set<String> restrictToCatalogIds, List<TransactionReceipt> receipts) {
+		this.processedPageInfo = pageInfo;
+		this.queryExpression = queryExpression;
+		this.restrictToCatalogIds = restrictToCatalogIds;
+		this.receipts = receipts;
+	}
+	
+	public List<TransactionReceipt> getReceipts() {
+		return this.receipts;
+	}
+	
+	public int getPageSize() {
+		return this.processedPageInfo.getPageSize();
+	}
+	
+	public int getPageNum() {
+		return this.processedPageInfo.getPageNum();
+	}
+	
+	public int getTotalPages() {
+		return this.processedPageInfo.getTotalPages();
+	}
+	
+	public int getNumOfHits() {
+		return this.processedPageInfo.getNumOfHits();
+	}
+	
+	public QueryExpression getQueryExpression() {
+		return queryExpression;
+	}
+
+	public Set<String> getRestrictToCatalogIds() {
+		return restrictToCatalogIds;
+	}
+	
+	public boolean isLastPage() {
+		return this.processedPageInfo.isLastPage();
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/PageInfo.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/PageInfo.java
new file mode 100644
index 0000000..ddfffd3
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/PageInfo.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.page;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class PageInfo {
+
+	protected int pageSize;
+	protected int pageNum;
+	
+	public static final int LAST_PAGE = Integer.MAX_VALUE;
+	public static final int FIRST_PAGE = 1;
+
+	public PageInfo(int pageSize, int pageNum) {
+		this.pageSize = pageSize;
+		if (pageNum < 1)
+			this.pageNum = 1;
+		else
+			this.pageNum = pageNum;
+	}
+
+	public int getPageSize() {
+		return pageSize;
+	}
+
+	public int getPageNum() {
+		return pageNum;
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/ProcessedPageInfo.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/ProcessedPageInfo.java
new file mode 100644
index 0000000..d454e69
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/ProcessedPageInfo.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.page;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class ProcessedPageInfo extends PageInfo {
+
+	protected int totalPages;
+	protected int numOfHits;
+	
+	public ProcessedPageInfo(int pageSize, int pageNum, int numOfHits) {
+		super(pageSize, pageNum > ((int) Math.ceil((double) numOfHits / (double) pageSize)) ? ((int) Math.ceil((double) numOfHits / (double) pageSize)) : pageNum);
+		this.totalPages = ((int) Math.ceil((double) numOfHits / (double) pageSize));
+		this.numOfHits = numOfHits;
+	}
+	
+	public int getTotalPages() {
+		return this.totalPages;
+	}
+	
+	public int getNumOfHits() {
+		return this.numOfHits;
+	}
+	
+	public boolean isLastPage() {
+		return this.pageNum >= this.totalPages;
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/QueryPager.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/QueryPager.java
new file mode 100644
index 0000000..d7f65da
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/QueryPager.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.page;
+
+//JDK imports
+import java.util.Collections;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A pager for paging through query results
+ * <p>
+ */
+public class QueryPager extends IndexPager {
+
+	protected List<TransactionReceipt> receipts;
+	
+	public QueryPager(List<TransactionReceipt> receipts) {
+		super();
+		this.receipts = new Vector<TransactionReceipt>(receipts);
+		this.totalPages = this.caculateTotalPages();
+		this.numOfHits = receipts.size();
+	}
+
+	protected int caculateTotalPages() {
+		return (int) Math.ceil((double) receipts.size() / (double) this.getPageSize());
+	}
+	
+	public void setPageInfo(PageInfo pageInfo) {
+		this.pageSize = Math.max(pageInfo.getPageSize(), 0);
+		this.totalPages = this.caculateTotalPages();
+		if (this.totalPages == 0)
+			this.pageNum = 0;
+		else
+			this.pageNum = (pageInfo.getPageNum() == PageInfo.LAST_PAGE || pageInfo.getPageNum() >= this.totalPages) ? this.totalPages : pageInfo.getPageNum();
+	}
+		
+	public List<TransactionReceipt> getTransactionReceipts() {
+		return Collections.unmodifiableList(this.receipts);
+	}
+	
+	public List<TransactionReceipt> getCurrentPage() {
+		List<TransactionReceipt> currentPage = new Vector<TransactionReceipt>();
+		if (this.pageNum > 0)
+			for (int i = (this.getPageNum() - 1) * this.getPageSize(); i < receipts.size() && i < this.getPageNum() * this.getPageSize(); i++)
+				currentPage.add(receipts.get(i));
+		return currentPage;
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/TransactionReceipt.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/TransactionReceipt.java
new file mode 100644
index 0000000..f8e4848
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/page/TransactionReceipt.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.page;
+
+//JDK imports
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Reciept created by performing a transaction with a CatalogService
+ * <p>
+ */
+public class TransactionReceipt {
+
+	protected TransactionId<?> transactionId;
+	protected Set<String> catalogIds;
+	protected Date transactionDate;
+	protected Vector<CatalogReceipt> catalogReceipts;
+	
+	public TransactionReceipt(TransactionId<?> transactionId, List<CatalogReceipt> catalogReceipts) {
+		this.transactionId = transactionId;
+		this.catalogIds = new HashSet<String>();
+		this.catalogReceipts = new Vector<CatalogReceipt>(catalogReceipts);
+		for (CatalogReceipt catalogReceipt : catalogReceipts) {
+			this.catalogIds.add(catalogReceipt.getCatalogId());
+			if (this.transactionDate == null)
+				this.transactionDate = catalogReceipt.getTransactionDate();
+			else if (this.transactionDate.before(catalogReceipt.getTransactionDate()))
+				this.transactionDate = catalogReceipt.getTransactionDate();
+		}
+	}
+
+	public TransactionId<?> getTransactionId() {
+		return this.transactionId;
+	}
+	
+	public Set<String> getCatalogIds() {
+		return this.catalogIds;
+	}
+	
+	public Date getTransactionDate() {
+		return this.transactionDate;
+	}
+	
+	public List<CatalogReceipt> getCatalogReceipts() {
+		return Collections.unmodifiableList(this.catalogReceipts);
+	}
+	
+	public int hashCode() {
+		return this.transactionId.hashCode();
+	}
+	
+	public boolean equals(Object obj) {
+		if (obj instanceof TransactionReceipt) {
+			return this.transactionId.equals(((TransactionReceipt) obj).transactionId);
+		}else {
+			return false;
+		}
+	}
+	
+	public String toString() {
+		return this.transactionId + ":" + this.catalogIds;
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/ComparisonQueryExpression.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/ComparisonQueryExpression.java
new file mode 100644
index 0000000..fc04920
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/ComparisonQueryExpression.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A TermQueryExpression which allows Term comparison
+ * <p>
+ */
+public class ComparisonQueryExpression extends TermQueryExpression {
+
+	public static enum Operator { EQUAL_TO("=="), LESS_THAN_EQUAL_TO("<="), GREATER_THAN_EQUAL_TO(">="), LESS_THAN("<"), GREATER_THAN(">"), LIKE("LIKE"); 
+	
+		private String value;
+		
+		Operator(String value) {
+			this.value = value;
+		}
+		
+		public static Operator getOperatorBySign(String sign) {
+			if (EQUAL_TO.value.equals(sign))
+				return EQUAL_TO;
+			else if (LESS_THAN_EQUAL_TO.value.equals(sign))
+				return LESS_THAN_EQUAL_TO;
+			else if (GREATER_THAN_EQUAL_TO.value.equals(sign))
+				return GREATER_THAN_EQUAL_TO;
+			else if (LESS_THAN.value.equals(sign))
+				return LESS_THAN;
+			else if (GREATER_THAN.value.equals(sign))
+				return GREATER_THAN;
+			else if (LIKE.value.equals(sign))
+				return LIKE;
+			else
+				throw new IllegalArgumentException("Not matching operator for '" + sign + "'");
+		}
+		
+		public String toString() {
+			return this.value;
+		}
+	
+	}
+	protected Operator operator;
+	
+	public void setOperator(Operator operator) {
+		this.operator = operator;
+	}
+	
+	public Operator getOperator() {
+		return this.operator;
+	}
+
+	@Override
+	public String toString() {
+		return "({" + this.bucketNames + "} " + this.getTerm().getName() + " " + this.operator + " " + this.getTerm().getValues() + ")";
+	}
+
+	@Override
+	public ComparisonQueryExpression clone() {
+		ComparisonQueryExpression newQE = new ComparisonQueryExpression();
+		newQE.operator = this.operator;
+		newQE.setTerm(this.term.clone());
+		newQE.setBucketNames(this.getBucketNames());
+		return newQE;
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/CustomQueryExpression.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/CustomQueryExpression.java
new file mode 100644
index 0000000..a39f263
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/CustomQueryExpression.java
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query;
+
+//JDK imports
+import java.util.Properties;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Configurable QueryExpression
+ * <p>
+ */
+public class CustomQueryExpression extends QueryExpression {
+
+	protected Properties properties;
+	protected String name;
+	
+	public CustomQueryExpression(String name) {
+		this(name, new Properties());
+	}
+	
+	public CustomQueryExpression(String name, Properties properties) {
+		super();
+		this.name = name;
+		if (properties != null)
+			this.properties = properties;
+		else 
+			this.properties = new Properties();
+	}
+	
+	public String getName() {
+		return this.name;
+	}
+	
+	public void setProperty(String key, String value) {
+		this.properties.put(key, value);
+	}
+	
+	public String getProperty(String key) {
+		return this.properties.getProperty(key);
+	}
+	
+	@Override
+	public CustomQueryExpression clone() {
+		CustomQueryExpression cqe = new CustomQueryExpression(this.name, (Properties) this.properties.clone());
+		cqe.setBucketNames(this.getBucketNames());
+		return cqe;
+	}
+
+	@Override
+	public String toString() {
+		return "({" + this.bucketNames + "} " + this.name + " : " + this.properties.toString() + ")";
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/CustomWrapperQueryExpression.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/CustomWrapperQueryExpression.java
new file mode 100644
index 0000000..8a621fd
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/CustomWrapperQueryExpression.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class CustomWrapperQueryExpression extends WrapperQueryExpression {
+
+	protected String meaning;
+	
+	public CustomWrapperQueryExpression(String meaning) {
+		this.meaning = meaning;
+	}
+	
+	public CustomWrapperQueryExpression(String meaning, QueryExpression queryExpression) {
+		super(queryExpression);
+		this.meaning = meaning;
+	}
+	
+	public String getMeaning() {
+		return this.meaning;
+	}
+	
+	@Override
+	public CustomWrapperQueryExpression clone() {
+		CustomWrapperQueryExpression cwqe = new CustomWrapperQueryExpression(this.meaning, this.queryExpression.clone());
+		cwqe.setBucketNames(this.bucketNames);
+		return cwqe;
+	}
+
+	@Override
+	public String toString() {
+		return "({" + this.bucketNames + "} " + this.meaning + "(" + this.queryExpression + "))";
+	}
+
+	@Override
+	public boolean isValidWithNoSubExpression() {
+		return false;
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/FreeTextQueryExpression.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/FreeTextQueryExpression.java
new file mode 100644
index 0000000..88278fc
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/FreeTextQueryExpression.java
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query;
+
+//JDK imports
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/**
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Free Text TermQueryExpression
+ * </p>
+ * 
+ */
+public class FreeTextQueryExpression extends TermQueryExpression {
+	
+	private HashSet<String> noiseWordHash = new HashSet<String>(
+		Arrays.asList(new String[] { "a", "all", "am", "an", "and",
+        "any", "are", "as", "at", "be", "but", "can", "did", "do", "does",
+        "for", "from", "had", "has", "have", "here", "how", "i", "if",
+        "in", "is", "it", "no", "not", "of", "on", "or", "so", "that",
+        "the", "then", "there", "this", "to", "too", "up", "use", "what",
+        "when", "where", "who", "why", "you" }));
+
+    /**
+     * A method for adding unparsed free text to the FreeTextCriteria. Free text
+     * entered as a string is tokenized and punctuation and common words are
+     * dropped before the values are added to the query. In order to query for
+     * pre-parsed keywords, see the setValues method of this class.
+     * 
+     * @param text
+     *            The free text to be parsed and searched on.
+     */
+    public void addFreeText(String text) {
+        // remove punctuation from the text
+        text = text.replaceAll("\\p{Punct}+", "");
+
+        // tokenize string using default delimiters
+        StringTokenizer tok = new StringTokenizer(text);
+        String token = null;
+
+        // filter noise words and add to values vector
+        List<String> values = new Vector<String>();
+        while (tok.hasMoreElements()) {
+            token = tok.nextToken();
+            if (!noiseWordHash.contains(token))
+                values.add(token);
+        }
+        if (values.size() > 0) {
+        	values.addAll(this.term.getValues());
+        	this.term.setValues(values);
+        }
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * generating a human-parsable string version of the query criteria. Note
+     * that the returned String follows the Lucene query language.
+     * 
+     * @return The query as a String.
+     */
+    public String toString() {
+        String serial = "({" + this.bucketNames + "} " + this.term.getName() + " :|";
+        for (String value : this.term.getValues())
+            serial += "+" + value;
+        serial += "|: )";
+        return serial;
+    }
+    
+	@Override
+	public FreeTextQueryExpression clone() {
+		FreeTextQueryExpression ftQE = new FreeTextQueryExpression();
+		ftQE.noiseWordHash = new HashSet<String>(this.noiseWordHash);
+		ftQE.setTerm(this.term.clone());
+		ftQE.setBucketNames(this.bucketNames);
+		return ftQE;
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/NotQueryExpression.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/NotQueryExpression.java
new file mode 100644
index 0000000..3609dfc
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/NotQueryExpression.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A WrapperQueryExpression which signifies negation of wrapped QueryExpression
+ * <p>
+ */
+public class NotQueryExpression extends WrapperQueryExpression {
+	
+	public NotQueryExpression() {
+		super();
+	}
+	
+	public NotQueryExpression(QueryExpression queryExpression) {
+		super(queryExpression);
+	}
+
+	@Override
+	public NotQueryExpression clone() {
+		NotQueryExpression nqe = new NotQueryExpression(this.queryExpression.clone());
+		nqe.setBucketNames(this.getBucketNames());
+		return nqe;
+	}
+	
+	@Override
+	public String toString() {
+		return "(NOT (" + this.queryExpression + "))";
+	}
+
+	@Override
+	public boolean isValidWithNoSubExpression() {
+		return false;
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/QueryExpression.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/QueryExpression.java
new file mode 100644
index 0000000..c8ef02a
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/QueryExpression.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query;
+
+//JDK imports
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Expression for querying against a CatalogServices Metadata
+ * <p>
+ */
+public abstract class QueryExpression implements Cloneable {
+    
+    protected Set<String> bucketNames;
+    
+    public QueryExpression() {}
+    
+    public QueryExpression(Set<String> bucketNames) { 
+    	this.bucketNames = new HashSet<String>(bucketNames);
+    }
+    
+	public Set<String> getBucketNames() {
+		return (this.bucketNames != null) ? new HashSet<String>(this.bucketNames) : null;
+	}
+
+	public void setBucketNames(Set<String> bucketNames) {
+		this.bucketNames = bucketNames;
+	}
+
+	public abstract String toString();
+
+    public abstract QueryExpression clone();
+    
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/QueryLogicalGroup.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/QueryLogicalGroup.java
new file mode 100644
index 0000000..60be735
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/QueryLogicalGroup.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query;
+
+//JDK imports
+import java.util.Collections;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A QueryExpression which groups other QueryExpressions
+ * <p>
+ */
+public class QueryLogicalGroup extends QueryExpression {
+
+	public enum Operator { AND, OR }
+	
+    protected Operator operator;
+
+    protected List<QueryExpression> queryExpressions;
+
+    public QueryLogicalGroup() {
+    	this(new Vector<QueryExpression>(), Operator.AND);
+    }
+    
+    public QueryLogicalGroup(List<QueryExpression> queryExpressions) {
+    	this(queryExpressions, Operator.AND);
+    }
+
+    public QueryLogicalGroup(List<QueryExpression> queryExpressions, Operator operator) {
+    	this.setExpressions(queryExpressions);
+    	this.setOperator(operator);
+    }
+    
+    public void setExpressions(List<QueryExpression> queryExpressions) {
+        this.queryExpressions = new Vector<QueryExpression>(queryExpressions);
+    }
+
+    /**
+     * 
+     * @param queryCriteria
+     */
+    public void addExpression(QueryExpression queryExpression) {
+    	this.queryExpressions.add(queryExpression);
+    }
+    
+    /**
+     * 
+     * @param queryCriterias
+     */
+    public void addExpressions(List<QueryExpression> queryExpressions) {
+    	this.queryExpressions.addAll(queryExpressions);
+    }
+
+    /**
+     * 
+     * @return
+     */
+    public List<QueryExpression> getExpressions() {
+        return Collections.unmodifiableList(this.queryExpressions);
+    }
+
+    /**
+     * 
+     * @param operator
+     */
+    public void setOperator(Operator operator) {
+        this.operator = operator;
+    }
+
+    /**
+     * 
+     * @return
+     */
+    public Operator getOperator() {
+        return this.operator;
+    }
+
+    @Override
+    public String toString() {
+        String query = "({" + this.bucketNames + "} " + this.operator + " : ";
+        for (QueryExpression queryExpression : this.queryExpressions)
+            query += queryExpression.toString() + ",";
+        return query.substring(0, query.length() - 1) + ")";
+    }
+    
+    public QueryLogicalGroup clone() {
+    	QueryLogicalGroup qlGroup = new QueryLogicalGroup();
+    	qlGroup.setBucketNames(this.getBucketNames());
+    	qlGroup.setOperator(this.operator);
+    	for (QueryExpression qe : this.queryExpressions)
+    		qlGroup.addExpression(qe.clone());
+    	return qlGroup;
+    }
+    
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/StdQueryExpression.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/StdQueryExpression.java
new file mode 100644
index 0000000..4353d4c
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/StdQueryExpression.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query;
+
+//JDK imports
+import java.util.Set;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Standard QueryExpression
+ * <p>
+ */
+public class StdQueryExpression extends QueryExpression {
+
+	public StdQueryExpression() {
+		super();
+	}
+	
+	public StdQueryExpression(Set<String> bucketNames) {
+		super(bucketNames);
+	}
+	
+	@Override
+	public StdQueryExpression clone() {
+		return new StdQueryExpression(this.getBucketNames());
+	}
+
+	@Override
+	public String toString() {
+		return "({" + this.bucketNames + "})";
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/TermQueryExpression.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/TermQueryExpression.java
new file mode 100644
index 0000000..b551126
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/TermQueryExpression.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.term.Term;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A QueryExpression which wrappers a Term
+ * <p>
+ */
+public abstract class TermQueryExpression extends QueryExpression implements Cloneable {
+
+	protected Term term;
+
+    public Term getTerm() {
+		return this.term;
+	}
+
+    public void setTerm(Term term) {
+    	this.term = term;
+    }
+    	
+    public abstract TermQueryExpression clone();
+    
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/WrapperQueryExpression.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/WrapperQueryExpression.java
new file mode 100644
index 0000000..a11c627
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/WrapperQueryExpression.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A QueryExpression which wrappers another QueryExpression
+ * <p>
+ */
+public abstract class WrapperQueryExpression extends QueryExpression {
+
+	protected QueryExpression queryExpression;
+
+	public WrapperQueryExpression() {
+		super();
+	}
+	
+	public WrapperQueryExpression(QueryExpression queryExpression) {
+		this();
+		this.queryExpression = queryExpression;
+	}
+	
+	public QueryExpression getQueryExpression() {
+		return queryExpression;
+	}
+
+	public void setQueryExpression(QueryExpression queryExpression) {
+		this.queryExpression = queryExpression;
+	}
+
+	@Override
+	public String toString() {
+		return "(" + this.queryExpression + ")";
+	}
+	
+	public abstract boolean isValidWithNoSubExpression();
+
+	public abstract WrapperQueryExpression clone();
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/FilterAlgorithm.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/FilterAlgorithm.java
new file mode 100644
index 0000000..c3b99e1
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/FilterAlgorithm.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query.filter;
+
+//JDK imports
+import java.util.List;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * An algorithm interface for defining how QueryFilter filters query results
+ * <p>
+ */
+public abstract class FilterAlgorithm<FilterType> {
+    
+    public abstract List<FilterType> filter(List<FilterType> events); 
+    
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/QueryFilter.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/QueryFilter.java
new file mode 100644
index 0000000..bbfdf14
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/QueryFilter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query.filter;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Filter interface for filtering queries
+ * <p>
+ */
+public abstract class QueryFilter<FilterType> {
+
+	protected FilterAlgorithm<FilterType> filterAlgorithm;
+	
+	public QueryFilter() {}
+	
+	public QueryFilter(FilterAlgorithm<FilterType> filterAlgorithm) {
+		super();
+		this.filterAlgorithm = filterAlgorithm;
+	}
+	
+	public void setFilterAlgorithm(FilterAlgorithm<FilterType> filterAlgorithm) {
+		this.filterAlgorithm = filterAlgorithm;
+	}
+	
+	public FilterAlgorithm<FilterType> getFilterAlgorithm() {
+		return this.filterAlgorithm;
+	}
+	
+	public List<TransactionalMetadata> filterMetadataList(List<TransactionalMetadata> metadataToFilter) {
+		return this.filterTypeToMetadata(this.filterAlgorithm.filter(this.metadataToFilterType(metadataToFilter)));
+	}
+	
+	protected abstract List<FilterType> metadataToFilterType(List<TransactionalMetadata> metadataList);
+	
+	protected abstract List<TransactionalMetadata> filterTypeToMetadata(List<FilterType> filterObjects);
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/MetadataTimeEvent.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/MetadataTimeEvent.java
new file mode 100644
index 0000000..aa8eaaf
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/MetadataTimeEvent.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query.filter.time;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.commons.filter.ObjectTimeEvent;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A ObjectTimeEvent that holds TermBuckets
+ * <p>
+ */
+public class MetadataTimeEvent extends ObjectTimeEvent<TransactionalMetadata> {
+
+    public MetadataTimeEvent(long startTime, long endTime, TransactionalMetadata timeObj) {
+		super(startTime, endTime, timeObj);
+    }
+	
+	public MetadataTimeEvent(long startTime, long endTime, double priority, TransactionalMetadata timeObj) {
+		super(startTime, endTime, priority, timeObj);
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/MetadataTimeEventFilterAlgorithm.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/MetadataTimeEventFilterAlgorithm.java
new file mode 100644
index 0000000..114a4d5
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/MetadataTimeEventFilterAlgorithm.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query.filter.time;
+
+//JDK imports
+import java.util.Collections;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.query.filter.FilterAlgorithm;
+import org.apache.oodt.commons.filter.TimeEventWeightedHash;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ */
+public class MetadataTimeEventFilterAlgorithm extends FilterAlgorithm<MetadataTimeEvent> {
+	
+    protected long epsilon;
+    
+    public MetadataTimeEventFilterAlgorithm() {
+        this.epsilon = 0;
+    }
+    
+    public MetadataTimeEventFilterAlgorithm(long epsilon) {
+        this.epsilon = epsilon;
+    }
+    
+    public void setEpsilon(long epsilon) {
+        this.epsilon = epsilon;
+    }
+    
+    public long getEpsilon() {
+        return this.epsilon;
+    }
+
+	@Override
+	public List<MetadataTimeEvent> filter(List<MetadataTimeEvent> events) {
+		TimeEventWeightedHash timeEventHash = TimeEventWeightedHash.buildHash(events, this.epsilon);
+		return Collections.unmodifiableList((List<MetadataTimeEvent>) timeEventHash.getGreatestWeightedPathAsOrderedList());
+	}
+    
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/MetadataTimeEventQueryFilter.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/MetadataTimeEventQueryFilter.java
new file mode 100644
index 0000000..29caf00
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/MetadataTimeEventQueryFilter.java
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query.filter.time;
+
+//JDK imports
+import java.util.Collections;
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.query.filter.QueryFilter;
+import org.apache.oodt.cas.catalog.query.filter.time.conv.AsciiSortableVersionConverter;
+import org.apache.oodt.cas.catalog.query.filter.time.conv.VersionConverter;
+
+//OODT imports
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A query filter that allows user to filter results in a complex query
+ * <p>
+ */
+public class MetadataTimeEventQueryFilter extends QueryFilter<MetadataTimeEvent> {
+
+    private String startDateTimeMetKey, endDateTimeMetKey, priorityMetKey;
+    private VersionConverter converter;
+
+    public MetadataTimeEventQueryFilter() {
+    	super();
+        this.converter = new AsciiSortableVersionConverter();
+    }
+
+    public String getStartDateTimeMetKey() {
+        return startDateTimeMetKey;
+    }
+
+    public void setStartDateTimeMetKey(String startDateTimeMetKey) {
+        this.startDateTimeMetKey = startDateTimeMetKey;
+    }
+
+    public String getEndDateTimeMetKey() {
+        return endDateTimeMetKey;
+    }
+
+    public void setEndDateTimeMetKey(String endDateTimeMetKey) {
+        this.endDateTimeMetKey = endDateTimeMetKey;
+    }
+
+    public String getPriorityMetKey() {
+        return priorityMetKey;
+    }
+
+    public void setPriorityMetKey(String priorityMetKey) {
+        this.priorityMetKey = priorityMetKey;
+    }
+
+    public VersionConverter getConverter() {
+        return converter;
+    }
+
+    public void setConverter(VersionConverter converter) {
+        if (converter != null)
+            this.converter = converter;
+    }
+
+	@Override
+	protected List<MetadataTimeEvent> metadataToFilterType(List<TransactionalMetadata> metadataList) {
+		List<MetadataTimeEvent> timeEvents = new Vector<MetadataTimeEvent>();
+		for (TransactionalMetadata transactionalMetadata : metadataList) {
+			double priority = 0;
+			if (this.getPriorityMetKey() != null)
+				priority = Double.parseDouble(transactionalMetadata.getMetadata().getMetadata(this.priorityMetKey));
+			long startTime = Long.parseLong(transactionalMetadata.getMetadata().getMetadata(this.startDateTimeMetKey));
+			String endTimeString = transactionalMetadata.getMetadata().getMetadata(this.endDateTimeMetKey);
+			long endTime = startTime;
+			if (endTimeString != null)
+				endTime = Long.parseLong(endTimeString);
+			timeEvents.add(new MetadataTimeEvent(startTime, endTime, priority, transactionalMetadata));
+		}
+		return Collections.unmodifiableList(timeEvents);
+	}
+
+	@Override
+	protected List<TransactionalMetadata> filterTypeToMetadata(List<MetadataTimeEvent> filterObjects) {
+		List<TransactionalMetadata> metadataList = new Vector<TransactionalMetadata>();
+		for (MetadataTimeEvent timeEvent : filterObjects)
+			metadataList.add(timeEvent.getTimeObject());
+		return Collections.unmodifiableList(metadataList);
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/conv/AsciiSortableVersionConverter.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/conv/AsciiSortableVersionConverter.java
new file mode 100644
index 0000000..0268930
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/conv/AsciiSortableVersionConverter.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query.filter.time.conv;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * Converts a ascii sortable String version into a priority number
+ * <p>
+ */
+public class AsciiSortableVersionConverter implements VersionConverter {
+
+    public double convertToPriority(String version) throws Exception {
+        double priority = 0;
+        char[] versionCharArray = version.toCharArray();
+        for (int i = 0, j = versionCharArray.length - 1; i < versionCharArray.length; i++, j--)
+            priority += (((int) versionCharArray[i]) * Math.pow(10, j));
+        return priority;
+    }
+    
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/conv/VersionConverter.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/conv/VersionConverter.java
new file mode 100644
index 0000000..29f2314
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/filter/time/conv/VersionConverter.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.query.filter.time.conv;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * An interface for converting a String version into a priority number
+ * <p>
+ */
+public interface VersionConverter {
+
+    public double convertToPriority(String version) throws Exception;
+    
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/JJTQueryParserState.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/JJTQueryParserState.java
new file mode 100644
index 0000000..7e9b0a0
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/JJTQueryParserState.java
@@ -0,0 +1,123 @@
+/* Generated By:JavaCC: Do not edit this line. JJTQueryParserState.java Version 5.0 */
+package org.apache.oodt.cas.catalog.query.parser;
+
+public class JJTQueryParserState {
+  private java.util.List<Node> nodes;
+  private java.util.List<Integer> marks;
+
+  private int sp;        // number of nodes on stack
+  private int mk;        // current mark
+  private boolean node_created;
+
+  public JJTQueryParserState() {
+    nodes = new java.util.ArrayList<Node>();
+    marks = new java.util.ArrayList<Integer>();
+    sp = 0;
+    mk = 0;
+  }
+
+  /* Determines whether the current node was actually closed and
+     pushed.  This should only be called in the final user action of a
+     node scope.  */
+  public boolean nodeCreated() {
+    return node_created;
+  }
+
+  /* Call this to reinitialize the node stack.  It is called
+     automatically by the parser's ReInit() method. */
+  public void reset() {
+    nodes.clear();
+    marks.clear();
+    sp = 0;
+    mk = 0;
+  }
+
+  /* Returns the root node of the AST.  It only makes sense to call
+     this after a successful parse. */
+  public Node rootNode() {
+    return nodes.get(0);
+  }
+
+  /* Pushes a node on to the stack. */
+  public void pushNode(Node n) {
+    nodes.add(n);
+    ++sp;
+  }
+
+  /* Returns the node on the top of the stack, and remove it from the
+     stack.  */
+  public Node popNode() {
+    if (--sp < mk) {
+      mk = marks.remove(marks.size()-1);
+    }
+    return nodes.remove(nodes.size()-1);
+  }
+
+  /* Returns the node currently on the top of the stack. */
+  public Node peekNode() {
+    return nodes.get(nodes.size()-1);
+  }
+
+  /* Returns the number of children on the stack in the current node
+     scope. */
+  public int nodeArity() {
+    return sp - mk;
+  }
+
+
+  public void clearNodeScope(Node n) {
+    while (sp > mk) {
+      popNode();
+    }
+    mk = marks.remove(marks.size()-1);
+  }
+
+
+  public void openNodeScope(Node n) {
+    marks.add(mk);
+    mk = sp;
+    n.jjtOpen();
+  }
+
+
+  /* A definite node is constructed from a specified number of
+     children.  That number of nodes are popped from the stack and
+     made the children of the definite node.  Then the definite node
+     is pushed on to the stack. */
+  public void closeNodeScope(Node n, int num) {
+    mk = marks.remove(marks.size()-1);
+    while (num-- > 0) {
+      Node c = popNode();
+      c.jjtSetParent(n);
+      n.jjtAddChild(c, num);
+    }
+    n.jjtClose();
+    pushNode(n);
+    node_created = true;
+  }
+
+
+  /* A conditional node is constructed if its condition is true.  All
+     the nodes that have been pushed since the node was opened are
+     made children of the conditional node, which is then pushed
+     on to the stack.  If the condition is false the node is not
+     constructed and they are left on the stack. */
+  public void closeNodeScope(Node n, boolean condition) {
+    if (condition) {
+      int a = nodeArity();
+      mk = marks.remove(marks.size()-1);
+      while (a-- > 0) {
+        Node c = popNode();
+        c.jjtSetParent(n);
+        n.jjtAddChild(c, a);
+      }
+      n.jjtClose();
+      pushNode(n);
+      node_created = true;
+    } else {
+      mk = marks.remove(marks.size()-1);
+      node_created = false;
+    }
+  }
+}
+/* JavaCC - OriginalChecksum=a225ad3a5c4857e9f64392e47d6acfb8 (do not edit this line) */
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/Node.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/Node.java
new file mode 100644
index 0000000..09710a8
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/Node.java
@@ -0,0 +1,36 @@
+/* Generated By:JJTree: Do not edit this line. Node.java Version 4.3 */
+/* JavaCCOptions:MULTI=false,NODE_USES_PARSER=false,VISITOR=false,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package org.apache.oodt.cas.catalog.query.parser;
+
+/* All AST nodes must implement this interface.  It provides basic
+   machinery for constructing the parent and child relationships
+   between nodes. */
+
+public
+interface Node {
+
+  /** This method is called after the node has been made the current
+    node.  It indicates that child nodes can now be added to it. */
+  public void jjtOpen();
+
+  /** This method is called after all the child nodes have been
+    added. */
+  public void jjtClose();
+
+  /** This pair of methods are used to inform the node of its
+    parent. */
+  public void jjtSetParent(Node n);
+  public Node jjtGetParent();
+
+  /** This method tells the node to add its argument to the node's
+    list of children.  */
+  public void jjtAddChild(Node n, int i);
+
+  /** This method returns a child node.  The children are numbered
+     from zero, left to right. */
+  public Node jjtGetChild(int i);
+
+  /** Return the number of children the node has. */
+  public int jjtGetNumChildren();
+}
+/* JavaCC - OriginalChecksum=d803b99b9dbe9f48568711ddba598d1d (do not edit this line) */
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/ParseException.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/ParseException.java
new file mode 100644
index 0000000..983b30e
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/ParseException.java
@@ -0,0 +1,187 @@
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 5.0 */
+/* JavaCCOptions:KEEP_LINE_COL=null */
+package org.apache.oodt.cas.catalog.query.parser;
+
+/**
+ * This exception is thrown when parse errors are encountered.
+ * You can explicitly create objects of this exception type by
+ * calling the method generateParseException in the generated
+ * parser.
+ *
+ * You can modify this class to customize your error reporting
+ * mechanisms so long as you retain the public fields.
+ */
+public class ParseException extends Exception {
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * This constructor is used by the method "generateParseException"
+   * in the generated parser.  Calling this constructor generates
+   * a new object of this type with the fields "currentToken",
+   * "expectedTokenSequences", and "tokenImage" set.
+   */
+  public ParseException(Token currentTokenVal,
+                        int[][] expectedTokenSequencesVal,
+                        String[] tokenImageVal
+                       )
+  {
+    super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
+    currentToken = currentTokenVal;
+    expectedTokenSequences = expectedTokenSequencesVal;
+    tokenImage = tokenImageVal;
+  }
+
+  /**
+   * The following constructors are for use by you for whatever
+   * purpose you can think of.  Constructing the exception in this
+   * manner makes the exception behave in the normal way - i.e., as
+   * documented in the class "Throwable".  The fields "errorToken",
+   * "expectedTokenSequences", and "tokenImage" do not contain
+   * relevant information.  The JavaCC generated code does not use
+   * these constructors.
+   */
+
+  public ParseException() {
+    super();
+  }
+
+  /** Constructor with message. */
+  public ParseException(String message) {
+    super(message);
+  }
+
+
+  /**
+   * This is the last token that has been consumed successfully.  If
+   * this object has been created due to a parse error, the token
+   * followng this token will (therefore) be the first error token.
+   */
+  public Token currentToken;
+
+  /**
+   * Each entry in this array is an array of integers.  Each array
+   * of integers represents a sequence of tokens (by their ordinal
+   * values) that is expected at this point of the parse.
+   */
+  public int[][] expectedTokenSequences;
+
+  /**
+   * This is a reference to the "tokenImage" array of the generated
+   * parser within which the parse error occurred.  This array is
+   * defined in the generated ...Constants interface.
+   */
+  public String[] tokenImage;
+
+  /**
+   * It uses "currentToken" and "expectedTokenSequences" to generate a parse
+   * error message and returns it.  If this object has been created
+   * due to a parse error, and you do not catch it (it gets thrown
+   * from the parser) the correct error message
+   * gets displayed.
+   */
+  private static String initialise(Token currentToken,
+                           int[][] expectedTokenSequences,
+                           String[] tokenImage) {
+    String eol = System.getProperty("line.separator", "\n");
+    StringBuffer expected = new StringBuffer();
+    int maxSize = 0;
+    for (int i = 0; i < expectedTokenSequences.length; i++) {
+      if (maxSize < expectedTokenSequences[i].length) {
+        maxSize = expectedTokenSequences[i].length;
+      }
+      for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+        expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
+      }
+      if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+        expected.append("...");
+      }
+      expected.append(eol).append("    ");
+    }
+    String retval = "Encountered \"";
+    Token tok = currentToken.next;
+    for (int i = 0; i < maxSize; i++) {
+      if (i != 0) retval += " ";
+      if (tok.kind == 0) {
+        retval += tokenImage[0];
+        break;
+      }
+      retval += " " + tokenImage[tok.kind];
+      retval += " \"";
+      retval += add_escapes(tok.image);
+      retval += " \"";
+      tok = tok.next;
+    }
+    retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+    retval += "." + eol;
+    if (expectedTokenSequences.length == 1) {
+      retval += "Was expecting:" + eol + "    ";
+    } else {
+      retval += "Was expecting one of:" + eol + "    ";
+    }
+    retval += expected.toString();
+    return retval;
+  }
+
+  /**
+   * The end of line string for this machine.
+   */
+  protected String eol = System.getProperty("line.separator", "\n");
+
+  /**
+   * Used to convert raw characters to their escaped version
+   * when these raw version cannot be used as part of an ASCII
+   * string literal.
+   */
+  static String add_escapes(String str) {
+      StringBuffer retval = new StringBuffer();
+      char ch;
+      for (int i = 0; i < str.length(); i++) {
+        switch (str.charAt(i))
+        {
+           case 0 :
+              continue;
+           case '\b':
+              retval.append("\\b");
+              continue;
+           case '\t':
+              retval.append("\\t");
+              continue;
+           case '\n':
+              retval.append("\\n");
+              continue;
+           case '\f':
+              retval.append("\\f");
+              continue;
+           case '\r':
+              retval.append("\\r");
+              continue;
+           case '\"':
+              retval.append("\\\"");
+              continue;
+           case '\'':
+              retval.append("\\\'");
+              continue;
+           case '\\':
+              retval.append("\\\\");
+              continue;
+           default:
+              if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+                 String s = "0000" + Integer.toString(ch, 16);
+                 retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+              } else {
+                 retval.append(ch);
+              }
+              continue;
+        }
+      }
+      return retval.toString();
+   }
+
+}
+/* JavaCC - OriginalChecksum=2dc94ec6e6c4be52e333891b220b8ef1 (do not edit this line) */
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParser.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParser.java
new file mode 100644
index 0000000..e9c0818
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParser.java
@@ -0,0 +1,1022 @@
+/* Generated By:JJTree&JavaCC: Do not edit this line. QueryParser.java */
+        package org.apache.oodt.cas.catalog.query.parser;
+
+        import java.io.ByteArrayInputStream;
+        import java.util.Arrays;
+        import java.util.HashSet;
+        import java.util.Vector;
+        import java.util.Properties;
+        import org.apache.oodt.cas.catalog.query.QueryExpression;
+        import org.apache.oodt.cas.catalog.query.QueryLogicalGroup;
+        import org.apache.oodt.cas.catalog.query.StdQueryExpression;
+        import org.apache.oodt.cas.catalog.query.ComparisonQueryExpression;
+        import org.apache.oodt.cas.catalog.query.CustomQueryExpression;
+        import org.apache.oodt.cas.catalog.term.Term;
+
+    public class QueryParser/*@bgen(jjtree)*/implements QueryParserTreeConstants, QueryParserConstants {/*@bgen(jjtree)*/
+  protected JJTQueryParserState jjtree = new JJTQueryParserState();
+        public static QueryExpression parseQueryExpression(String queryExpressionString) throws ParseException, TokenMgrError {
+                return new QueryParser(new ByteArrayInputStream(queryExpressionString.getBytes())).parseInput();
+        }
+
+        public static void main( String[] args ) throws ParseException, TokenMgrError {
+                System.out.println(new QueryParser( System.in ).parseInput());
+        }
+
+  final public QueryExpression parseInput() throws ParseException {
+ /*@bgen(jjtree) parseInput */
+        SimpleNode jjtn000 = new SimpleNode(JJTPARSEINPUT);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);QueryExpression qe = null;
+    try {
+      qe = Query(null);
+      jj_consume_token(0);
+          jjtree.closeNodeScope(jjtn000, true);
+          jjtc000 = false;
+          {if (true) return qe;}
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+          }
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final public QueryExpression Query(Vector<String> bucketNames) throws ParseException {
+ /*@bgen(jjtree) Query */
+        SimpleNode jjtn000 = new SimpleNode(JJTQUERY);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);QueryExpression qe1 = null;
+        QueryExpression qe2 = null;
+        Token operator = null;
+    try {
+      qe1 = QueryExpression(bucketNames);
+      label_1:
+      while (true) {
+        if (jj_2_1(2147483647)) {
+          ;
+        } else {
+          break label_1;
+        }
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case AND:
+          operator = jj_consume_token(AND);
+          break;
+        case OR:
+          operator = jj_consume_token(OR);
+          break;
+        default:
+          jj_la1[0] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+        qe2 = Query(bucketNames);
+      }
+      jjtree.closeNodeScope(jjtn000, true);
+      jjtc000 = false;
+        if (qe2 == null) {
+                {if (true) return qe1;}
+        }else {
+                QueryLogicalGroup queryLogicalGroup = new QueryLogicalGroup();
+                if (bucketNames != null)
+                        queryLogicalGroup.setBucketNames(new HashSet<String>(bucketNames));
+                queryLogicalGroup.setOperator(QueryLogicalGroup.Operator.valueOf(operator.image.trim().toUpperCase()));
+                queryLogicalGroup.addExpression(qe1);
+                queryLogicalGroup.addExpression(qe2);
+                {if (true) return queryLogicalGroup;}
+        }
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        {if (true) throw (RuntimeException)jjte000;}
+      }
+      if (jjte000 instanceof ParseException) {
+        {if (true) throw (ParseException)jjte000;}
+      }
+      {if (true) throw (Error)jjte000;}
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final public QueryExpression QueryExpression(Vector<String> bucketNames) throws ParseException {
+ /*@bgen(jjtree) QueryExpression */
+        SimpleNode jjtn000 = new SimpleNode(JJTQUERYEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);QueryExpression qe = null;
+    try {
+      if (jj_2_2(2147483647)) {
+        qe = PriorityQueryExpression(bucketNames);
+      } else if (jj_2_3(2147483647)) {
+        qe = StdQueryExpression();
+      } else if (jj_2_4(2147483647)) {
+        qe = CustomQueryExpression(bucketNames);
+      } else if (jj_2_5(2147483647)) {
+        qe = ComparisonQueryExpression(bucketNames);
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+      jjtree.closeNodeScope(jjtn000, true);
+      jjtc000 = false;
+      {if (true) return qe;}
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        {if (true) throw (RuntimeException)jjte000;}
+      }
+      if (jjte000 instanceof ParseException) {
+        {if (true) throw (ParseException)jjte000;}
+      }
+      {if (true) throw (Error)jjte000;}
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final public QueryExpression StdQueryExpression() throws ParseException {
+ /*@bgen(jjtree) StdQueryExpression */
+        SimpleNode jjtn000 = new SimpleNode(JJTSTDQUERYEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);QueryExpression qe = null;
+        Vector<String> bucketNames = new Vector<String>();
+    try {
+      jj_consume_token(OPEN_BRACES);
+      label_2:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case SPACE:
+          ;
+          break;
+        default:
+          jj_la1[1] = jj_gen;
+          break label_2;
+        }
+        jj_consume_token(SPACE);
+      }
+      jj_consume_token(BUCKET_NAME_KEY);
+      label_3:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case SPACE:
+          ;
+          break;
+        default:
+          jj_la1[2] = jj_gen;
+          break label_3;
+        }
+        jj_consume_token(SPACE);
+      }
+      jj_consume_token(EQUALS);
+      label_4:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case SPACE:
+          ;
+          break;
+        default:
+          jj_la1[3] = jj_gen;
+          break label_4;
+        }
+        jj_consume_token(SPACE);
+      }
+      getValues(bucketNames);
+      label_5:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case SPACE:
+          ;
+          break;
+        default:
+          jj_la1[4] = jj_gen;
+          break label_5;
+        }
+        jj_consume_token(SPACE);
+      }
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case SEMI_COLON:
+        jj_consume_token(SEMI_COLON);
+        label_6:
+        while (true) {
+          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+          case SPACE:
+            ;
+            break;
+          default:
+            jj_la1[5] = jj_gen;
+            break label_6;
+          }
+          jj_consume_token(SPACE);
+        }
+        qe = Query(bucketNames);
+        break;
+      default:
+        jj_la1[6] = jj_gen;
+        ;
+      }
+      label_7:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case SPACE:
+          ;
+          break;
+        default:
+          jj_la1[7] = jj_gen;
+          break label_7;
+        }
+        jj_consume_token(SPACE);
+      }
+      jj_consume_token(CLOSE_BRACES);
+      jjtree.closeNodeScope(jjtn000, true);
+      jjtc000 = false;
+        if (qe == null) {
+                {if (true) return new StdQueryExpression(new HashSet<String>(bucketNames));}
+        }else {
+                {if (true) return qe;}
+        }
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        {if (true) throw (RuntimeException)jjte000;}
+      }
+      if (jjte000 instanceof ParseException) {
+        {if (true) throw (ParseException)jjte000;}
+      }
+      {if (true) throw (Error)jjte000;}
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final public QueryExpression ComparisonQueryExpression(Vector<String> bucketNames) throws ParseException {
+ /*@bgen(jjtree) ComparisonQueryExpression */
+        SimpleNode jjtn000 = new SimpleNode(JJTCOMPARISONQUERYEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);Token termName = null;
+        Token operator = null;
+        Vector<String> values = new Vector<String>();
+    try {
+      termName = jj_consume_token(TERM);
+      label_8:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case SPACE:
+          ;
+          break;
+        default:
+          jj_la1[8] = jj_gen;
+          break label_8;
+        }
+        jj_consume_token(SPACE);
+      }
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case EQ:
+        operator = jj_consume_token(EQ);
+        break;
+      case GT:
+        operator = jj_consume_token(GT);
+        break;
+      case GE:
+        operator = jj_consume_token(GE);
+        break;
+      case LT:
+        operator = jj_consume_token(LT);
+        break;
+      case LE:
+        operator = jj_consume_token(LE);
+        break;
+      default:
+        jj_la1[9] = jj_gen;
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+      label_9:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case SPACE:
+          ;
+          break;
+        default:
+          jj_la1[10] = jj_gen;
+          break label_9;
+        }
+        jj_consume_token(SPACE);
+      }
+      getValues(values);
+      jjtree.closeNodeScope(jjtn000, true);
+      jjtc000 = false;
+        Term term = new Term(termName.image);
+        term.setValues(values); //Arrays.asList(termValues.image.split(",")));
+        ComparisonQueryExpression comparisonQueryExpression = new ComparisonQueryExpression();
+        if (bucketNames != null)
+                comparisonQueryExpression.setBucketNames(new HashSet<String>(bucketNames));
+        comparisonQueryExpression.setTerm(term);
+        comparisonQueryExpression.setOperator(ComparisonQueryExpression.Operator.getOperatorBySign(operator.image));
+        {if (true) return comparisonQueryExpression;}
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        {if (true) throw (RuntimeException)jjte000;}
+      }
+      if (jjte000 instanceof ParseException) {
+        {if (true) throw (ParseException)jjte000;}
+      }
+      {if (true) throw (Error)jjte000;}
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final public QueryExpression PriorityQueryExpression(Vector<String> bucketNames) throws ParseException {
+ /*@bgen(jjtree) PriorityQueryExpression */
+        SimpleNode jjtn000 = new SimpleNode(JJTPRIORITYQUERYEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);QueryExpression qe = null;
+    try {
+      jj_consume_token(OPEN_PARENS);
+      qe = Query(bucketNames);
+      jj_consume_token(CLOSE_PARENS);
+      jjtree.closeNodeScope(jjtn000, true);
+      jjtc000 = false;
+      {if (true) return qe;}
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        {if (true) throw (RuntimeException)jjte000;}
+      }
+      if (jjte000 instanceof ParseException) {
+        {if (true) throw (ParseException)jjte000;}
+      }
+      {if (true) throw (Error)jjte000;}
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final public QueryExpression CustomQueryExpression(Vector<String> bucketNames) throws ParseException {
+ /*@bgen(jjtree) CustomQueryExpression */
+        SimpleNode jjtn000 = new SimpleNode(JJTCUSTOMQUERYEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);Token customNameToken = null;
+        Properties p = new Properties();
+    try {
+      jj_consume_token(OPEN_BRACES);
+      label_10:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case SPACE:
+          ;
+          break;
+        default:
+          jj_la1[11] = jj_gen;
+          break label_10;
+        }
+        jj_consume_token(SPACE);
+      }
+      jj_consume_token(CUSTOM_NAME_KEY);
+      label_11:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case SPACE:
+          ;
+          break;
+        default:
+          jj_la1[12] = jj_gen;
+          break label_11;
+        }
+        jj_consume_token(SPACE);
+      }
+      jj_consume_token(EQUALS);
+      label_12:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case SPACE:
+          ;
+          break;
+        default:
+          jj_la1[13] = jj_gen;
+          break label_12;
+        }
+        jj_consume_token(SPACE);
+      }
+      jj_consume_token(QUOTE);
+      customNameToken = jj_consume_token(TERM);
+      jj_consume_token(QUOTE);
+      if (jj_2_6(2147483647)) {
+        label_13:
+        while (true) {
+          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+          case SPACE:
+            ;
+            break;
+          default:
+            jj_la1[14] = jj_gen;
+            break label_13;
+          }
+          jj_consume_token(SPACE);
+        }
+        jj_consume_token(SEMI_COLON);
+        getProperties(p);
+      } else {
+        ;
+      }
+      label_14:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case SPACE:
+          ;
+          break;
+        default:
+          jj_la1[15] = jj_gen;
+          break label_14;
+        }
+        jj_consume_token(SPACE);
+      }
+      jj_consume_token(CLOSE_BRACES);
+          jjtree.closeNodeScope(jjtn000, true);
+          jjtc000 = false;
+                CustomQueryExpression cqe = new CustomQueryExpression(customNameToken.image, p);
+        if (bucketNames != null)
+                cqe.setBucketNames(new HashSet<String>(bucketNames));
+        {if (true) return cqe;}
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+          }
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final public void getValues(Vector<String> values) throws ParseException {
+ /*@bgen(jjtree) getValues */
+        SimpleNode jjtn000 = new SimpleNode(JJTGETVALUES);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);Token value = null;
+    try {
+      value = jj_consume_token(VALUE);
+      label_15:
+      while (true) {
+        if (jj_2_7(2147483647)) {
+          ;
+        } else {
+          break label_15;
+        }
+        jj_consume_token(COMMA);
+        getValues(values);
+      }
+          jjtree.closeNodeScope(jjtn000, true);
+          jjtc000 = false;
+                values.add(0, value.image.replaceAll("'", ""));
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+          }
+    }
+  }
+
+  final public void getProperties(Properties p) throws ParseException {
+ /*@bgen(jjtree) getProperties */
+        SimpleNode jjtn000 = new SimpleNode(JJTGETPROPERTIES);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);Token propertyKey = null;
+        Token propertyVal = null;
+    try {
+      propertyKey = jj_consume_token(P_KEY);
+      label_16:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case SPACE:
+          ;
+          break;
+        default:
+          jj_la1[16] = jj_gen;
+          break label_16;
+        }
+        jj_consume_token(SPACE);
+      }
+      jj_consume_token(EQUALS);
+      label_17:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case SPACE:
+          ;
+          break;
+        default:
+          jj_la1[17] = jj_gen;
+          break label_17;
+        }
+        jj_consume_token(SPACE);
+      }
+      propertyVal = jj_consume_token(VALUE);
+      label_18:
+      while (true) {
+        if (jj_2_8(2147483647)) {
+          ;
+        } else {
+          break label_18;
+        }
+        jj_consume_token(COMMA);
+        getProperties(p);
+      }
+          jjtree.closeNodeScope(jjtn000, true);
+          jjtc000 = false;
+                p.put(propertyKey.image.substring(2), propertyVal.image.replaceAll("'", ""));
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+          }
+    }
+  }
+
+  final private boolean jj_2_1(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_1(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(0, xla); }
+  }
+
+  final private boolean jj_2_2(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_2(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(1, xla); }
+  }
+
+  final private boolean jj_2_3(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_3(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(2, xla); }
+  }
+
+  final private boolean jj_2_4(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_4(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(3, xla); }
+  }
+
+  final private boolean jj_2_5(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_5(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(4, xla); }
+  }
+
+  final private boolean jj_2_6(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_6(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(5, xla); }
+  }
+
+  final private boolean jj_2_7(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_7(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(6, xla); }
+  }
+
+  final private boolean jj_2_8(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_8(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(7, xla); }
+  }
+
+  final private boolean jj_3_8() {
+    if (jj_scan_token(COMMA)) return true;
+    return false;
+  }
+
+  final private boolean jj_3_3() {
+    if (jj_scan_token(OPEN_BRACES)) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_scan_token(4)) { jj_scanpos = xsp; break; }
+    }
+    if (jj_scan_token(BUCKET_NAME_KEY)) return true;
+    return false;
+  }
+
+  final private boolean jj_3_2() {
+    if (jj_scan_token(OPEN_PARENS)) return true;
+    return false;
+  }
+
+  final private boolean jj_3_7() {
+    if (jj_scan_token(COMMA)) return true;
+    return false;
+  }
+
+  final private boolean jj_3_1() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(5)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(6)) return true;
+    }
+    return false;
+  }
+
+  final private boolean jj_3_5() {
+    if (jj_scan_token(TERM)) return true;
+    return false;
+  }
+
+  final private boolean jj_3_6() {
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_scan_token(4)) { jj_scanpos = xsp; break; }
+    }
+    if (jj_scan_token(SEMI_COLON)) return true;
+    return false;
+  }
+
+  final private boolean jj_3_4() {
+    if (jj_scan_token(OPEN_BRACES)) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_scan_token(4)) { jj_scanpos = xsp; break; }
+    }
+    if (jj_scan_token(CUSTOM_NAME_KEY)) return true;
+    return false;
+  }
+
+  public QueryParserTokenManager token_source;
+  SimpleCharStream jj_input_stream;
+  public Token token, jj_nt;
+  private int jj_ntk;
+  private Token jj_scanpos, jj_lastpos;
+  private int jj_la;
+  public boolean lookingAhead = false;
+  private boolean jj_semLA;
+  private int jj_gen;
+  final private int[] jj_la1 = new int[18];
+  static private int[] jj_la1_0;
+  static {
+      jj_la1_0();
+   }
+   private static void jj_la1_0() {
+      jj_la1_0 = new int[] {0x60,0x10,0x10,0x10,0x10,0x10,0x200,0x10,0x10,0x7c0000,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,};
+   }
+  final private JJCalls[] jj_2_rtns = new JJCalls[8];
+  private boolean jj_rescan = false;
+  private int jj_gc = 0;
+
+  public QueryParser(java.io.InputStream stream) {
+     this(stream, null);
+  }
+  public QueryParser(java.io.InputStream stream, String encoding) {
+    try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+    token_source = new QueryParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 18; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  public void ReInit(java.io.InputStream stream) {
+     ReInit(stream, null);
+  }
+  public void ReInit(java.io.InputStream stream, String encoding) {
+    try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+    token_source.ReInit(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jjtree.reset();
+    jj_gen = 0;
+    for (int i = 0; i < 18; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  public QueryParser(java.io.Reader stream) {
+    jj_input_stream = new SimpleCharStream(stream, 1, 1);
+    token_source = new QueryParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 18; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  public void ReInit(java.io.Reader stream) {
+    jj_input_stream.ReInit(stream, 1, 1);
+    token_source.ReInit(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jjtree.reset();
+    jj_gen = 0;
+    for (int i = 0; i < 18; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  public QueryParser(QueryParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 18; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  public void ReInit(QueryParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jjtree.reset();
+    jj_gen = 0;
+    for (int i = 0; i < 18; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  final private Token jj_consume_token(int kind) throws ParseException {
+    Token oldToken;
+    if ((oldToken = token).next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    if (token.kind == kind) {
+      jj_gen++;
+      if (++jj_gc > 100) {
+        jj_gc = 0;
+        for (int i = 0; i < jj_2_rtns.length; i++) {
+          JJCalls c = jj_2_rtns[i];
+          while (c != null) {
+            if (c.gen < jj_gen) c.first = null;
+            c = c.next;
+          }
+        }
+      }
+      return token;
+    }
+    token = oldToken;
+    jj_kind = kind;
+    throw generateParseException();
+  }
+
+  static private final class LookaheadSuccess extends java.lang.Error { }
+  final private LookaheadSuccess jj_ls = new LookaheadSuccess();
+  final private boolean jj_scan_token(int kind) {
+    if (jj_scanpos == jj_lastpos) {
+      jj_la--;
+      if (jj_scanpos.next == null) {
+        jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
+      } else {
+        jj_lastpos = jj_scanpos = jj_scanpos.next;
+      }
+    } else {
+      jj_scanpos = jj_scanpos.next;
+    }
+    if (jj_rescan) {
+      int i = 0; Token tok = token;
+      while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
+      if (tok != null) jj_add_error_token(kind, i);
+    }
+    if (jj_scanpos.kind != kind) return true;
+    if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
+    return false;
+  }
+
+  final public Token getNextToken() {
+    if (token.next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    jj_gen++;
+    return token;
+  }
+
+  final public Token getToken(int index) {
+    Token t = lookingAhead ? jj_scanpos : token;
+    for (int i = 0; i < index; i++) {
+      if (t.next != null) t = t.next;
+      else t = t.next = token_source.getNextToken();
+    }
+    return t;
+  }
+
+  final private int jj_ntk() {
+    if ((jj_nt=token.next) == null)
+      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
+    else
+      return (jj_ntk = jj_nt.kind);
+  }
+
+  private java.util.Vector<int[]> jj_expentries = new java.util.Vector<int[]>();
+  private int[] jj_expentry;
+  private int jj_kind = -1;
+  private int[] jj_lasttokens = new int[100];
+  private int jj_endpos;
+
+  private void jj_add_error_token(int kind, int pos) {
+    if (pos >= 100) return;
+    if (pos == jj_endpos + 1) {
+      jj_lasttokens[jj_endpos++] = kind;
+    } else if (jj_endpos != 0) {
+      jj_expentry = new int[jj_endpos];
+      for (int i = 0; i < jj_endpos; i++) {
+        jj_expentry[i] = jj_lasttokens[i];
+      }
+      boolean exists = false;
+      for (java.util.Enumeration e = jj_expentries.elements(); e.hasMoreElements();) {
+        int[] oldentry = (int[])(e.nextElement());
+        if (oldentry.length == jj_expentry.length) {
+          exists = true;
+          for (int i = 0; i < jj_expentry.length; i++) {
+            if (oldentry[i] != jj_expentry[i]) {
+              exists = false;
+              break;
+            }
+          }
+          if (exists) break;
+        }
+      }
+      if (!exists) jj_expentries.addElement(jj_expentry);
+      if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
+    }
+  }
+
+  public ParseException generateParseException() {
+    jj_expentries.removeAllElements();
+    boolean[] la1tokens = new boolean[28];
+    for (int i = 0; i < 28; i++) {
+      la1tokens[i] = false;
+    }
+    if (jj_kind >= 0) {
+      la1tokens[jj_kind] = true;
+      jj_kind = -1;
+    }
+    for (int i = 0; i < 18; i++) {
+      if (jj_la1[i] == jj_gen) {
+        for (int j = 0; j < 32; j++) {
+          if ((jj_la1_0[i] & (1<<j)) != 0) {
+            la1tokens[j] = true;
+          }
+        }
+      }
+    }
+    for (int i = 0; i < 28; i++) {
+      if (la1tokens[i]) {
+        jj_expentry = new int[1];
+        jj_expentry[0] = i;
+        jj_expentries.addElement(jj_expentry);
+      }
+    }
+    jj_endpos = 0;
+    jj_rescan_token();
+    jj_add_error_token(0, 0);
+    int[][] exptokseq = new int[jj_expentries.size()][];
+    for (int i = 0; i < jj_expentries.size(); i++) {
+      exptokseq[i] = jj_expentries.elementAt(i);
+    }
+    return new ParseException(token, exptokseq, tokenImage);
+  }
+
+  final public void enable_tracing() {
+  }
+
+  final public void disable_tracing() {
+  }
+
+  final private void jj_rescan_token() {
+    jj_rescan = true;
+    for (int i = 0; i < 8; i++) {
+    try {
+      JJCalls p = jj_2_rtns[i];
+      do {
+        if (p.gen > jj_gen) {
+          jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
+          switch (i) {
+            case 0: jj_3_1(); break;
+            case 1: jj_3_2(); break;
+            case 2: jj_3_3(); break;
+            case 3: jj_3_4(); break;
+            case 4: jj_3_5(); break;
+            case 5: jj_3_6(); break;
+            case 6: jj_3_7(); break;
+            case 7: jj_3_8(); break;
+          }
+        }
+        p = p.next;
+      } while (p != null);
+      } catch(LookaheadSuccess ls) { }
+    }
+    jj_rescan = false;
+  }
+
+  final private void jj_save(int index, int xla) {
+    JJCalls p = jj_2_rtns[index];
+    while (p.gen > jj_gen) {
+      if (p.next == null) { p = p.next = new JJCalls(); break; }
+      p = p.next;
+    }
+    p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
+  }
+
+  static final class JJCalls {
+    int gen;
+    Token first;
+    int arg;
+    JJCalls next;
+  }
+
+    }
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParser.jj b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParser.jj
new file mode 100644
index 0000000..2537616
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParser.jj
@@ -0,0 +1,497 @@
+/*@bgen(jjtree) Generated By:JJTree: Do not edit this line. ./QueryParser.jj */
+/*@egen*//*
+ * 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.
+ */
+
+options {
+  JDK_VERSION = "1.5";
+  STATIC = false;
+}
+
+PARSER_BEGIN(QueryParser)
+	package org.apache.oodt.cas.catalog.query.parser;
+
+	import java.io.ByteArrayInputStream;
+	import java.util.Arrays;
+	import java.util.HashSet;
+	import java.util.Vector;
+	import java.util.Properties;
+	import org.apache.oodt.cas.catalog.query.QueryExpression;
+	import org.apache.oodt.cas.catalog.query.QueryLogicalGroup;
+	import org.apache.oodt.cas.catalog.query.StdQueryExpression;
+	import org.apache.oodt.cas.catalog.query.ComparisonQueryExpression;
+	import org.apache.oodt.cas.catalog.query.CustomQueryExpression;
+	import org.apache.oodt.cas.catalog.term.Term;
+	
+    public class QueryParser/*@bgen(jjtree)*/implements QueryParserTreeConstants/*@egen*/ {/*@bgen(jjtree)*/
+  protected JJTQueryParserState jjtree = new JJTQueryParserState();
+
+/*@egen*/
+    	
+    	public static QueryExpression parseQueryExpression(String queryExpressionString) throws ParseException, TokenMgrError {
+    		return new QueryParser(new ByteArrayInputStream(queryExpressionString.getBytes())).parseInput();
+    	}
+    	
+       	public static void main( String[] args ) throws ParseException, TokenMgrError {
+          	System.out.println(new QueryParser( System.in ).parseInput());
+       	} 
+       	
+    }
+PARSER_END(QueryParser)
+
+SKIP : { "\r" | "\n" | "\r\n" }
+TOKEN: { < SPACE : " " > }
+TOKEN: { < AND : " AND " > }
+TOKEN: { < OR : " OR " > }
+TOKEN: { < QUOTE : "'" > }
+TOKEN: { < EQUALS : "=" > }
+TOKEN: { < SEMI_COLON : ";" > }
+TOKEN: { < COMMA : "," > }
+TOKEN: { < OPEN_BRACES : "{" > }
+TOKEN: { < CLOSE_BRACES : "}" > }
+TOKEN: { < OPEN_PARENS : "(" > }
+TOKEN: { < CLOSE_PARENS : ")" > }
+TOKEN: { < BUCKET_NAME_KEY : "bucketNames" > }
+TOKEN: { < CUSTOM_NAME_KEY : "name" > }
+TOKEN: { < P_KEY : "p:" <TERM> > }
+TOKEN: {
+      < EQ : "==" >
+    | < GE : ">=" >
+    | < GT : ">" >
+    | < LE : "<=" >
+    | < LT : "<" >
+}
+TOKEN: { < TERM: (["a"-"z","A"-"Z"])+ (<STRING_LITERAL>)* > }
+TOKEN: { < VALUE : "'" ( <TERM> | <NON_TERM> ) "'" > }
+TOKEN: { < #NON_TERM: (<STRING_LITERAL> | <SPECIAL_CHARS>)+ (<STRING_LITERAL> | " "<STRING_LITERAL> | " "<SPECIAL_CHARS> | <SPECIAL_CHARS>)* > }
+TOKEN: { < #STRING_LITERAL: (["0"-"9","a"-"z","A"-"Z","-","_",".",":","/"]) > }
+TOKEN: { < #SPECIAL_CHARS: (["/","\\","?","<",">","~","`","*","#","&","!","@","$","%","^","(",")","{","}","[","]"]) > }
+
+QueryExpression parseInput() : 
+{/*@bgen(jjtree) parseInput */
+        SimpleNode jjtn000 = new SimpleNode(JJTPARSEINPUT);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+/*@egen*/
+	QueryExpression qe = null;
+}
+{/*@bgen(jjtree) parseInput */
+        try {
+/*@egen*/
+   	qe = Query(null) <EOF>/*@bgen(jjtree)*/
+        {
+          jjtree.closeNodeScope(jjtn000, true);
+          jjtc000 = false;
+        }
+/*@egen*/
+   	{ return qe; }/*@bgen(jjtree)*/
+        } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            throw (RuntimeException)jjte000;
+          }
+          if (jjte000 instanceof ParseException) {
+            throw (ParseException)jjte000;
+          }
+          throw (Error)jjte000;
+        } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+          }
+        }
+/*@egen*/
+}
+
+QueryExpression Query(Vector<String> bucketNames) : 
+{/*@bgen(jjtree) Query */
+        SimpleNode jjtn000 = new SimpleNode(JJTQUERY);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+/*@egen*/
+	QueryExpression qe1 = null;
+	QueryExpression qe2 = null;
+	Token operator = null;
+}
+{/*@bgen(jjtree) Query */
+    try {
+/*@egen*/
+    qe1 = QueryExpression(bucketNames) ( LOOKAHEAD( <AND> | <OR> ) ( operator = <AND> | operator = <OR> ) qe2 = Query(bucketNames) )*/*@bgen(jjtree)*/
+    {
+      jjtree.closeNodeScope(jjtn000, true);
+      jjtc000 = false;
+    }
+/*@egen*/
+    { 
+    	if (qe2 == null) {
+    		return qe1;
+    	}else {
+    		QueryLogicalGroup queryLogicalGroup = new QueryLogicalGroup();
+    		if (bucketNames != null)
+    			queryLogicalGroup.setBucketNames(new HashSet<String>(bucketNames));
+    		queryLogicalGroup.setOperator(QueryLogicalGroup.Operator.valueOf(operator.image.trim().toUpperCase()));
+    		queryLogicalGroup.addExpression(qe1);
+    		queryLogicalGroup.addExpression(qe2);
+    		return queryLogicalGroup;
+    	}
+    }/*@bgen(jjtree)*/
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        throw (RuntimeException)jjte000;
+      }
+      if (jjte000 instanceof ParseException) {
+        throw (ParseException)jjte000;
+      }
+      throw (Error)jjte000;
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+/*@egen*/
+}
+
+QueryExpression QueryExpression(Vector<String> bucketNames) :
+{/*@bgen(jjtree) QueryExpression */
+        SimpleNode jjtn000 = new SimpleNode(JJTQUERYEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+/*@egen*/
+	QueryExpression qe = null;
+}
+{/*@bgen(jjtree) QueryExpression */
+    try {
+/*@egen*/
+    ( 
+    	LOOKAHEAD ( <OPEN_PARENS> ) 
+    	qe = PriorityQueryExpression(bucketNames)
+    | 
+    	LOOKAHEAD ( <OPEN_BRACES> (<SPACE>)* <BUCKET_NAME_KEY> ) 
+    	qe = StdQueryExpression()
+    | 
+    	LOOKAHEAD ( <OPEN_BRACES> (<SPACE>)* <CUSTOM_NAME_KEY> ) 
+    	qe = CustomQueryExpression(bucketNames)
+    | 
+        LOOKAHEAD ( <TERM> ) 
+    	qe = ComparisonQueryExpression(bucketNames) 
+    )/*@bgen(jjtree)*/
+    {
+      jjtree.closeNodeScope(jjtn000, true);
+      jjtc000 = false;
+    }
+/*@egen*/
+    
+    { return qe; }/*@bgen(jjtree)*/
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        throw (RuntimeException)jjte000;
+      }
+      if (jjte000 instanceof ParseException) {
+        throw (ParseException)jjte000;
+      }
+      throw (Error)jjte000;
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+/*@egen*/
+}
+
+QueryExpression StdQueryExpression() : 
+{/*@bgen(jjtree) StdQueryExpression */
+        SimpleNode jjtn000 = new SimpleNode(JJTSTDQUERYEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+/*@egen*/
+	QueryExpression qe = null;
+	Vector<String> bucketNames = new Vector<String>();
+}
+{/*@bgen(jjtree) StdQueryExpression */
+    try {
+/*@egen*/
+    <OPEN_BRACES> (<SPACE>)* <BUCKET_NAME_KEY> (<SPACE>)* <EQUALS> (<SPACE>)* getValues(bucketNames) (<SPACE>)* [<SEMI_COLON> (<SPACE>)* qe = Query(bucketNames)] (<SPACE>)* <CLOSE_BRACES>/*@bgen(jjtree)*/
+    {
+      jjtree.closeNodeScope(jjtn000, true);
+      jjtc000 = false;
+    }
+/*@egen*/
+    { 
+    	if (qe == null) {
+    		return new StdQueryExpression(new HashSet<String>(bucketNames));
+    	}else {
+    		return qe; 
+    	}
+    }/*@bgen(jjtree)*/
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        throw (RuntimeException)jjte000;
+      }
+      if (jjte000 instanceof ParseException) {
+        throw (ParseException)jjte000;
+      }
+      throw (Error)jjte000;
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+/*@egen*/
+}
+
+QueryExpression ComparisonQueryExpression(Vector<String> bucketNames) : 
+{/*@bgen(jjtree) ComparisonQueryExpression */
+        SimpleNode jjtn000 = new SimpleNode(JJTCOMPARISONQUERYEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+/*@egen*/
+	Token termName = null;
+	Token operator = null;
+	Vector<String> values = new Vector<String>();
+}
+{/*@bgen(jjtree) ComparisonQueryExpression */
+    try {
+/*@egen*/
+    termName = <TERM> (<SPACE>)* ( operator = <EQ> | operator = <GT> | operator = <GE> | operator = <LT> | operator = <LE> ) (<SPACE>)* getValues(values)/*@bgen(jjtree)*/
+    {
+      jjtree.closeNodeScope(jjtn000, true);
+      jjtc000 = false;
+    }
+/*@egen*/
+    { 
+    	Term term = new Term(termName.image);
+    	term.setValues(values); //Arrays.asList(termValues.image.split(",")));
+    	ComparisonQueryExpression comparisonQueryExpression = new ComparisonQueryExpression();
+    	if (bucketNames != null)
+    		comparisonQueryExpression.setBucketNames(new HashSet<String>(bucketNames));
+    	comparisonQueryExpression.setTerm(term);
+    	comparisonQueryExpression.setOperator(ComparisonQueryExpression.Operator.getOperatorBySign(operator.image));
+    	return comparisonQueryExpression; 
+    }/*@bgen(jjtree)*/
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        throw (RuntimeException)jjte000;
+      }
+      if (jjte000 instanceof ParseException) {
+        throw (ParseException)jjte000;
+      }
+      throw (Error)jjte000;
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+/*@egen*/
+}
+
+QueryExpression PriorityQueryExpression(Vector<String> bucketNames) :
+{/*@bgen(jjtree) PriorityQueryExpression */
+        SimpleNode jjtn000 = new SimpleNode(JJTPRIORITYQUERYEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+/*@egen*/
+	QueryExpression qe = null;
+}
+{/*@bgen(jjtree) PriorityQueryExpression */
+    try {
+/*@egen*/
+    <OPEN_PARENS> qe = Query(bucketNames) <CLOSE_PARENS>/*@bgen(jjtree)*/
+    {
+      jjtree.closeNodeScope(jjtn000, true);
+      jjtc000 = false;
+    }
+/*@egen*/
+    { return qe; }/*@bgen(jjtree)*/
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        throw (RuntimeException)jjte000;
+      }
+      if (jjte000 instanceof ParseException) {
+        throw (ParseException)jjte000;
+      }
+      throw (Error)jjte000;
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+/*@egen*/
+}
+
+QueryExpression CustomQueryExpression(Vector<String> bucketNames) :
+{/*@bgen(jjtree) CustomQueryExpression */
+        SimpleNode jjtn000 = new SimpleNode(JJTCUSTOMQUERYEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+/*@egen*/
+	Token customNameToken = null;
+	Properties p = new Properties();
+}
+{/*@bgen(jjtree) CustomQueryExpression */
+        try {
+/*@egen*/
+	<OPEN_BRACES> (<SPACE>)* <CUSTOM_NAME_KEY> (<SPACE>)* <EQUALS> (<SPACE>)* <QUOTE> customNameToken = <TERM> <QUOTE> [ LOOKAHEAD ((<SPACE>)* <SEMI_COLON>) (<SPACE>)* <SEMI_COLON> getProperties(p) ] (<SPACE>)* <CLOSE_BRACES>/*@bgen(jjtree)*/
+        {
+          jjtree.closeNodeScope(jjtn000, true);
+          jjtc000 = false;
+        }
+/*@egen*/
+	{ 
+		CustomQueryExpression cqe = new CustomQueryExpression(customNameToken.image, p);
+    	if (bucketNames != null)
+    		cqe.setBucketNames(new HashSet<String>(bucketNames));
+    	return cqe;
+	}/*@bgen(jjtree)*/
+        } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            throw (RuntimeException)jjte000;
+          }
+          if (jjte000 instanceof ParseException) {
+            throw (ParseException)jjte000;
+          }
+          throw (Error)jjte000;
+        } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+          }
+        }
+/*@egen*/
+}
+
+void getValues(Vector<String> values) : 
+{/*@bgen(jjtree) getValues */
+        SimpleNode jjtn000 = new SimpleNode(JJTGETVALUES);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+/*@egen*/
+	Token value = null;
+}
+{/*@bgen(jjtree) getValues */
+        try {
+/*@egen*/
+	value = <VALUE> ( LOOKAHEAD (<COMMA>) <COMMA> getValues(values) ) */*@bgen(jjtree)*/
+        {
+          jjtree.closeNodeScope(jjtn000, true);
+          jjtc000 = false;
+        }
+/*@egen*/
+	{ 
+		values.add(0, value.image.replaceAll("'", ""));
+	}/*@bgen(jjtree)*/
+        } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            throw (RuntimeException)jjte000;
+          }
+          if (jjte000 instanceof ParseException) {
+            throw (ParseException)jjte000;
+          }
+          throw (Error)jjte000;
+        } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+          }
+        }
+/*@egen*/
+}
+
+void getProperties(Properties p) : 
+{/*@bgen(jjtree) getProperties */
+        SimpleNode jjtn000 = new SimpleNode(JJTGETPROPERTIES);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+/*@egen*/
+	Token propertyKey = null;
+	Token propertyVal = null;
+}
+{/*@bgen(jjtree) getProperties */
+        try {
+/*@egen*/
+	propertyKey = <P_KEY> (<SPACE>)* <EQUALS> (<SPACE>)* propertyVal = <VALUE> ( LOOKAHEAD (<COMMA>) <COMMA> getProperties(p) ) */*@bgen(jjtree)*/
+        {
+          jjtree.closeNodeScope(jjtn000, true);
+          jjtc000 = false;
+        }
+/*@egen*/
+	{ 
+		p.put(propertyKey.image.substring(2), propertyVal.image.replaceAll("'", ""));
+	}/*@bgen(jjtree)*/
+        } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            throw (RuntimeException)jjte000;
+          }
+          if (jjte000 instanceof ParseException) {
+            throw (ParseException)jjte000;
+          }
+          throw (Error)jjte000;
+        } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+          }
+        }
+/*@egen*/
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParser.jjt b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParser.jjt
new file mode 100644
index 0000000..60697fb
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParser.jjt
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ */
+
+options {
+  JDK_VERSION = "1.5";
+  STATIC = false;
+}
+
+PARSER_BEGIN(QueryParser)
+	package org.apache.oodt.cas.catalog.query.parser;
+
+	import java.io.ByteArrayInputStream;
+	import java.util.Arrays;
+	import java.util.HashSet;
+	import java.util.Vector;
+	import java.util.Properties;
+	import org.apache.oodt.cas.catalog.query.QueryExpression;
+	import org.apache.oodt.cas.catalog.query.QueryLogicalGroup;
+	import org.apache.oodt.cas.catalog.query.StdQueryExpression;
+	import org.apache.oodt.cas.catalog.query.ComparisonQueryExpression;
+	import org.apache.oodt.cas.catalog.query.CustomQueryExpression;
+	import org.apache.oodt.cas.catalog.term.Term;
+	
+    public class QueryParser {
+    	
+    	public static QueryExpression parseQueryExpression(String queryExpressionString) throws ParseException, TokenMgrError {
+    		return new QueryParser(new ByteArrayInputStream(queryExpressionString.getBytes())).parseInput();
+    	}
+    	
+       	public static void main( String[] args ) throws ParseException, TokenMgrError {
+          	System.out.println(new QueryParser( System.in ).parseInput());
+       	} 
+       	
+    }
+PARSER_END(QueryParser)
+
+SKIP : { "\r" | "\n" | "\r\n" }
+TOKEN: { < SPACE : " " > }
+TOKEN: { < AND : " AND " > }
+TOKEN: { < OR : " OR " > }
+TOKEN: { < QUOTE : "'" > }
+TOKEN: { < EQUALS : "=" > }
+TOKEN: { < SEMI_COLON : ";" > }
+TOKEN: { < COMMA : "," > }
+TOKEN: { < OPEN_BRACES : "{" > }
+TOKEN: { < CLOSE_BRACES : "}" > }
+TOKEN: { < OPEN_PARENS : "(" > }
+TOKEN: { < CLOSE_PARENS : ")" > }
+TOKEN: { < BUCKET_NAME_KEY : "bucketNames" > }
+TOKEN: { < CUSTOM_NAME_KEY : "name" > }
+TOKEN: { < P_KEY : "p:" <TERM> > }
+TOKEN: {
+      < EQ : "==" >
+    | < GE : ">=" >
+    | < GT : ">" >
+    | < LE : "<=" >
+    | < LT : "<" >
+}
+TOKEN: { < TERM: (["a"-"z","A"-"Z"])+ (<STRING_LITERAL>)* > }
+TOKEN: { < VALUE : "'" ( <TERM> | <NON_TERM> ) "'" > }
+TOKEN: { < #NON_TERM: (<STRING_LITERAL> | <SPECIAL_CHARS>)+ (<STRING_LITERAL> | " "<STRING_LITERAL> | " "<SPECIAL_CHARS> | <SPECIAL_CHARS>)* > }
+TOKEN: { < #STRING_LITERAL: (["0"-"9","a"-"z","A"-"Z","-","_",".",":","/"]) > }
+TOKEN: { < #SPECIAL_CHARS: (["/","\\","?","<",">","~","`","*","#","&","!","@","$","%","^","(",")","{","}","[","]"]) > }
+
+QueryExpression parseInput() : 
+{
+	QueryExpression qe = null;
+}
+{
+   	qe = Query(null) <EOF>
+   	{ return qe; }
+}
+
+QueryExpression Query(Vector<String> bucketNames) : 
+{
+	QueryExpression qe1 = null;
+	QueryExpression qe2 = null;
+	Token operator = null;
+}
+{
+    qe1 = QueryExpression(bucketNames) ( LOOKAHEAD( <AND> | <OR> ) ( operator = <AND> | operator = <OR> ) qe2 = Query(bucketNames) )*
+    { 
+    	if (qe2 == null) {
+    		return qe1;
+    	}else {
+    		QueryLogicalGroup queryLogicalGroup = new QueryLogicalGroup();
+    		if (bucketNames != null)
+    			queryLogicalGroup.setBucketNames(new HashSet<String>(bucketNames));
+    		queryLogicalGroup.setOperator(QueryLogicalGroup.Operator.valueOf(operator.image.trim().toUpperCase()));
+    		queryLogicalGroup.addExpression(qe1);
+    		queryLogicalGroup.addExpression(qe2);
+    		return queryLogicalGroup;
+    	}
+    }
+}
+
+QueryExpression QueryExpression(Vector<String> bucketNames) :
+{
+	QueryExpression qe = null;
+}
+{
+    ( 
+    	LOOKAHEAD ( <OPEN_PARENS> ) 
+    	qe = PriorityQueryExpression(bucketNames)
+    | 
+    	LOOKAHEAD ( <OPEN_BRACES> (<SPACE>)* <BUCKET_NAME_KEY> ) 
+    	qe = StdQueryExpression()
+    | 
+    	LOOKAHEAD ( <OPEN_BRACES> (<SPACE>)* <CUSTOM_NAME_KEY> ) 
+    	qe = CustomQueryExpression(bucketNames)
+    | 
+        LOOKAHEAD ( <TERM> ) 
+    	qe = ComparisonQueryExpression(bucketNames) 
+    )
+    
+    { return qe; }
+}
+
+QueryExpression StdQueryExpression() : 
+{
+	QueryExpression qe = null;
+	Vector<String> bucketNames = new Vector<String>();
+}
+{
+    <OPEN_BRACES> (<SPACE>)* <BUCKET_NAME_KEY> (<SPACE>)* <EQUALS> (<SPACE>)* getValues(bucketNames) (<SPACE>)* [<SEMI_COLON> (<SPACE>)* qe = Query(bucketNames)] (<SPACE>)* <CLOSE_BRACES>
+    { 
+    	if (qe == null) {
+    		return new StdQueryExpression(new HashSet<String>(bucketNames));
+    	}else {
+    		return qe; 
+    	}
+    }
+}
+
+QueryExpression ComparisonQueryExpression(Vector<String> bucketNames) : 
+{
+	Token termName = null;
+	Token operator = null;
+	Vector<String> values = new Vector<String>();
+}
+{
+    termName = <TERM> (<SPACE>)* ( operator = <EQ> | operator = <GT> | operator = <GE> | operator = <LT> | operator = <LE> ) (<SPACE>)* getValues(values)
+    { 
+    	Term term = new Term(termName.image);
+    	term.setValues(values); //Arrays.asList(termValues.image.split(",")));
+    	ComparisonQueryExpression comparisonQueryExpression = new ComparisonQueryExpression();
+    	if (bucketNames != null)
+    		comparisonQueryExpression.setBucketNames(new HashSet<String>(bucketNames));
+    	comparisonQueryExpression.setTerm(term);
+    	comparisonQueryExpression.setOperator(ComparisonQueryExpression.Operator.getOperatorBySign(operator.image));
+    	return comparisonQueryExpression; 
+    }
+}
+
+QueryExpression PriorityQueryExpression(Vector<String> bucketNames) :
+{
+	QueryExpression qe = null;
+}
+{
+    <OPEN_PARENS> qe = Query(bucketNames) <CLOSE_PARENS>
+    { return qe; }
+}
+
+QueryExpression CustomQueryExpression(Vector<String> bucketNames) :
+{
+	Token customNameToken = null;
+	Properties p = new Properties();
+}
+{
+	<OPEN_BRACES> (<SPACE>)* <CUSTOM_NAME_KEY> (<SPACE>)* <EQUALS> (<SPACE>)* <QUOTE> customNameToken = <TERM> <QUOTE> [ LOOKAHEAD ((<SPACE>)* <SEMI_COLON>) (<SPACE>)* <SEMI_COLON> getProperties(p) ] (<SPACE>)* <CLOSE_BRACES>
+	{ 
+		CustomQueryExpression cqe = new CustomQueryExpression(customNameToken.image, p);
+    	if (bucketNames != null)
+    		cqe.setBucketNames(new HashSet<String>(bucketNames));
+    	return cqe;
+	}
+}
+
+void getValues(Vector<String> values) : 
+{
+	Token value = null;
+}
+{
+	value = <VALUE> ( LOOKAHEAD (<COMMA>) <COMMA> getValues(values) ) *
+	{ 
+		values.add(0, value.image.replaceAll("'", ""));
+	}
+}
+
+void getProperties(Properties p) : 
+{
+	Token propertyKey = null;
+	Token propertyVal = null;
+}
+{
+	propertyKey = <P_KEY> (<SPACE>)* <EQUALS> (<SPACE>)* propertyVal = <VALUE> ( LOOKAHEAD (<COMMA>) <COMMA> getProperties(p) ) *
+	{ 
+		p.put(propertyKey.image.substring(2), propertyVal.image.replaceAll("'", ""));
+	}
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParserConstants.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParserConstants.java
new file mode 100644
index 0000000..ac3ded6
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParserConstants.java
@@ -0,0 +1,65 @@
+/* Generated By:JJTree&JavaCC: Do not edit this line. QueryParserConstants.java */
+package org.apache.oodt.cas.catalog.query.parser;
+
+public interface QueryParserConstants {
+
+  int EOF = 0;
+  int SPACE = 4;
+  int AND = 5;
+  int OR = 6;
+  int QUOTE = 7;
+  int EQUALS = 8;
+  int SEMI_COLON = 9;
+  int COMMA = 10;
+  int OPEN_BRACES = 11;
+  int CLOSE_BRACES = 12;
+  int OPEN_PARENS = 13;
+  int CLOSE_PARENS = 14;
+  int BUCKET_NAME_KEY = 15;
+  int CUSTOM_NAME_KEY = 16;
+  int P_KEY = 17;
+  int EQ = 18;
+  int GE = 19;
+  int GT = 20;
+  int LE = 21;
+  int LT = 22;
+  int TERM = 23;
+  int VALUE = 24;
+  int NON_TERM = 25;
+  int STRING_LITERAL = 26;
+  int SPECIAL_CHARS = 27;
+
+  int DEFAULT = 0;
+
+  String[] tokenImage = {
+    "<EOF>",
+    "\"\\r\"",
+    "\"\\n\"",
+    "\"\\r\\n\"",
+    "\" \"",
+    "\" AND \"",
+    "\" OR \"",
+    "\"\\\'\"",
+    "\"=\"",
+    "\";\"",
+    "\",\"",
+    "\"{\"",
+    "\"}\"",
+    "\"(\"",
+    "\")\"",
+    "\"bucketNames\"",
+    "\"name\"",
+    "<P_KEY>",
+    "\"==\"",
+    "\">=\"",
+    "\">\"",
+    "\"<=\"",
+    "\"<\"",
+    "<TERM>",
+    "<VALUE>",
+    "<NON_TERM>",
+    "<STRING_LITERAL>",
+    "<SPECIAL_CHARS>",
+  };
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParserTokenManager.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParserTokenManager.java
new file mode 100644
index 0000000..52abf3c
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParserTokenManager.java
@@ -0,0 +1,757 @@
+/* Generated By:JJTree&JavaCC: Do not edit this line. QueryParserTokenManager.java */
+package org.apache.oodt.cas.catalog.query.parser;
+import java.io.ByteArrayInputStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Vector;
+import java.util.Properties;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.query.QueryLogicalGroup;
+import org.apache.oodt.cas.catalog.query.StdQueryExpression;
+import org.apache.oodt.cas.catalog.query.ComparisonQueryExpression;
+import org.apache.oodt.cas.catalog.query.CustomQueryExpression;
+import org.apache.oodt.cas.catalog.term.Term;
+
+public class QueryParserTokenManager implements QueryParserConstants
+{
+  public  java.io.PrintStream debugStream = System.out;
+  public  void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
+private final int jjStopStringLiteralDfa_0(int pos, long active0)
+{
+   switch (pos)
+   {
+      case 0:
+         if ((active0 & 0x18000L) != 0L)
+         {
+            jjmatchedKind = 23;
+            return 16;
+         }
+         if ((active0 & 0x80L) != 0L)
+            return 10;
+         return -1;
+      case 1:
+         if ((active0 & 0x18000L) != 0L)
+         {
+            jjmatchedKind = 23;
+            jjmatchedPos = 1;
+            return 16;
+         }
+         return -1;
+      case 2:
+         if ((active0 & 0x18000L) != 0L)
+         {
+            jjmatchedKind = 23;
+            jjmatchedPos = 2;
+            return 16;
+         }
+         return -1;
+      case 3:
+         if ((active0 & 0x8000L) != 0L)
+         {
+            jjmatchedKind = 23;
+            jjmatchedPos = 3;
+            return 16;
+         }
+         if ((active0 & 0x10000L) != 0L)
+            return 16;
+         return -1;
+      case 4:
+         if ((active0 & 0x8000L) != 0L)
+         {
+            jjmatchedKind = 23;
+            jjmatchedPos = 4;
+            return 16;
+         }
+         return -1;
+      case 5:
+         if ((active0 & 0x8000L) != 0L)
+         {
+            jjmatchedKind = 23;
+            jjmatchedPos = 5;
+            return 16;
+         }
+         return -1;
+      case 6:
+         if ((active0 & 0x8000L) != 0L)
+         {
+            jjmatchedKind = 23;
+            jjmatchedPos = 6;
+            return 16;
+         }
+         return -1;
+      case 7:
+         if ((active0 & 0x8000L) != 0L)
+         {
+            jjmatchedKind = 23;
+            jjmatchedPos = 7;
+            return 16;
+         }
+         return -1;
+      case 8:
+         if ((active0 & 0x8000L) != 0L)
+         {
+            jjmatchedKind = 23;
+            jjmatchedPos = 8;
+            return 16;
+         }
+         return -1;
+      case 9:
+         if ((active0 & 0x8000L) != 0L)
+         {
+            jjmatchedKind = 23;
+            jjmatchedPos = 9;
+            return 16;
+         }
+         return -1;
+      default :
+         return -1;
+   }
+}
+private final int jjStartNfa_0(int pos, long active0)
+{
+   return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
+}
+private final int jjStopAtPos(int pos, int kind)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   return pos + 1;
+}
+private final int jjStartNfaWithStates_0(int pos, int kind, int state)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) { return pos + 1; }
+   return jjMoveNfa_0(state, pos + 1);
+}
+private final int jjMoveStringLiteralDfa0_0()
+{
+   switch(curChar)
+   {
+      case 13:
+         jjmatchedKind = 1;
+         return jjMoveStringLiteralDfa1_0(0x8L);
+      case 32:
+         jjmatchedKind = 4;
+         return jjMoveStringLiteralDfa1_0(0x60L);
+      case 39:
+         return jjStartNfaWithStates_0(0, 7, 10);
+      case 40:
+         return jjStopAtPos(0, 13);
+      case 41:
+         return jjStopAtPos(0, 14);
+      case 44:
+         return jjStopAtPos(0, 10);
+      case 59:
+         return jjStopAtPos(0, 9);
+      case 60:
+         jjmatchedKind = 22;
+         return jjMoveStringLiteralDfa1_0(0x200000L);
+      case 61:
+         jjmatchedKind = 8;
+         return jjMoveStringLiteralDfa1_0(0x40000L);
+      case 62:
+         jjmatchedKind = 20;
+         return jjMoveStringLiteralDfa1_0(0x80000L);
+      case 98:
+         return jjMoveStringLiteralDfa1_0(0x8000L);
+      case 110:
+         return jjMoveStringLiteralDfa1_0(0x10000L);
+      case 123:
+         return jjStopAtPos(0, 11);
+      case 125:
+         return jjStopAtPos(0, 12);
+      default :
+         return jjMoveNfa_0(3, 0);
+   }
+}
+private final int jjMoveStringLiteralDfa1_0(long active0)
+{
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(0, active0);
+      return 1;
+   }
+   switch(curChar)
+   {
+      case 10:
+         if ((active0 & 0x8L) != 0L)
+            return jjStopAtPos(1, 3);
+         break;
+      case 61:
+         if ((active0 & 0x40000L) != 0L)
+            return jjStopAtPos(1, 18);
+         else if ((active0 & 0x80000L) != 0L)
+            return jjStopAtPos(1, 19);
+         else if ((active0 & 0x200000L) != 0L)
+            return jjStopAtPos(1, 21);
+         break;
+      case 65:
+         return jjMoveStringLiteralDfa2_0(active0, 0x20L);
+      case 79:
+         return jjMoveStringLiteralDfa2_0(active0, 0x40L);
+      case 97:
+         return jjMoveStringLiteralDfa2_0(active0, 0x10000L);
+      case 117:
+         return jjMoveStringLiteralDfa2_0(active0, 0x8000L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(0, active0);
+}
+private final int jjMoveStringLiteralDfa2_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(0, old0); 
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(1, active0);
+      return 2;
+   }
+   switch(curChar)
+   {
+      case 78:
+         return jjMoveStringLiteralDfa3_0(active0, 0x20L);
+      case 82:
+         return jjMoveStringLiteralDfa3_0(active0, 0x40L);
+      case 99:
+         return jjMoveStringLiteralDfa3_0(active0, 0x8000L);
+      case 109:
+         return jjMoveStringLiteralDfa3_0(active0, 0x10000L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(1, active0);
+}
+private final int jjMoveStringLiteralDfa3_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(1, old0); 
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(2, active0);
+      return 3;
+   }
+   switch(curChar)
+   {
+      case 32:
+         if ((active0 & 0x40L) != 0L)
+            return jjStopAtPos(3, 6);
+         break;
+      case 68:
+         return jjMoveStringLiteralDfa4_0(active0, 0x20L);
+      case 101:
+         if ((active0 & 0x10000L) != 0L)
+            return jjStartNfaWithStates_0(3, 16, 16);
+         break;
+      case 107:
+         return jjMoveStringLiteralDfa4_0(active0, 0x8000L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(2, active0);
+}
+private final int jjMoveStringLiteralDfa4_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(2, old0); 
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(3, active0);
+      return 4;
+   }
+   switch(curChar)
+   {
+      case 32:
+         if ((active0 & 0x20L) != 0L)
+            return jjStopAtPos(4, 5);
+         break;
+      case 101:
+         return jjMoveStringLiteralDfa5_0(active0, 0x8000L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(3, active0);
+}
+private final int jjMoveStringLiteralDfa5_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(3, old0); 
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(4, active0);
+      return 5;
+   }
+   switch(curChar)
+   {
+      case 116:
+         return jjMoveStringLiteralDfa6_0(active0, 0x8000L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(4, active0);
+}
+private final int jjMoveStringLiteralDfa6_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(4, old0); 
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(5, active0);
+      return 6;
+   }
+   switch(curChar)
+   {
+      case 78:
+         return jjMoveStringLiteralDfa7_0(active0, 0x8000L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(5, active0);
+}
+private final int jjMoveStringLiteralDfa7_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(5, old0); 
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(6, active0);
+      return 7;
+   }
+   switch(curChar)
+   {
+      case 97:
+         return jjMoveStringLiteralDfa8_0(active0, 0x8000L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(6, active0);
+}
+private final int jjMoveStringLiteralDfa8_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(6, old0); 
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(7, active0);
+      return 8;
+   }
+   switch(curChar)
+   {
+      case 109:
+         return jjMoveStringLiteralDfa9_0(active0, 0x8000L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(7, active0);
+}
+private final int jjMoveStringLiteralDfa9_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(7, old0); 
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(8, active0);
+      return 9;
+   }
+   switch(curChar)
+   {
+      case 101:
+         return jjMoveStringLiteralDfa10_0(active0, 0x8000L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(8, active0);
+}
+private final int jjMoveStringLiteralDfa10_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(8, old0); 
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(9, active0);
+      return 10;
+   }
+   switch(curChar)
+   {
+      case 115:
+         if ((active0 & 0x8000L) != 0L)
+            return jjStartNfaWithStates_0(10, 15, 16);
+         break;
+      default :
+         break;
+   }
+   return jjStartNfa_0(9, active0);
+}
+private final void jjCheckNAdd(int state)
+{
+   if (jjrounds[state] != jjround)
+   {
+      jjstateSet[jjnewStateCnt++] = state;
+      jjrounds[state] = jjround;
+   }
+}
+private final void jjAddStates(int start, int end)
+{
+   do {
+      jjstateSet[jjnewStateCnt++] = jjnextStates[start];
+   } while (start++ != end);
+}
+private final void jjCheckNAddTwoStates(int state1, int state2)
+{
+   jjCheckNAdd(state1);
+   jjCheckNAdd(state2);
+}
+private final void jjCheckNAddStates(int start, int end)
+{
+   do {
+      jjCheckNAdd(jjnextStates[start]);
+   } while (start++ != end);
+}
+private final void jjCheckNAddStates(int start)
+{
+   jjCheckNAdd(jjnextStates[start]);
+   jjCheckNAdd(jjnextStates[start + 1]);
+}
+private final int jjMoveNfa_0(int startState, int curPos)
+{
+   int[] nextStates;
+   int startsAt = 0;
+   jjnewStateCnt = 16;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int j, kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         MatchLoop: do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 10:
+                  if ((0xd7ffe77a00000000L & l) != 0L)
+                     jjCheckNAddStates(0, 2);
+                  break;
+               case 16:
+               case 5:
+                  if ((0x7ffe00000000000L & l) == 0L)
+                     break;
+                  if (kind > 23)
+                     kind = 23;
+                  jjCheckNAdd(5);
+                  break;
+               case 3:
+                  if (curChar == 39)
+                     jjAddStates(3, 4);
+                  break;
+               case 0:
+                  if (curChar == 58)
+                     jjstateSet[jjnewStateCnt++] = 1;
+                  break;
+               case 2:
+                  if ((0x7ffe00000000000L & l) == 0L)
+                     break;
+                  if (kind > 17)
+                     kind = 17;
+                  jjstateSet[jjnewStateCnt++] = 2;
+                  break;
+               case 8:
+                  if ((0x7ffe00000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(8, 9);
+                  break;
+               case 9:
+                  if (curChar == 39 && kind > 24)
+                     kind = 24;
+                  break;
+               case 11:
+                  if (curChar == 32)
+                     jjAddStates(5, 6);
+                  break;
+               case 12:
+                  if ((0x7ffe00000000000L & l) != 0L)
+                     jjCheckNAddStates(7, 9);
+                  break;
+               case 13:
+                  if ((0xd7ffe77a00000000L & l) != 0L)
+                     jjCheckNAddStates(7, 9);
+                  break;
+               case 14:
+                  if ((0xd000877a00000000L & l) != 0L)
+                     jjCheckNAddStates(7, 9);
+                  break;
+               case 15:
+                  if ((0xd7ffe77a00000000L & l) != 0L)
+                     jjCheckNAddStates(10, 13);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         MatchLoop: do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 10:
+                  if ((0x6fffffffffffffffL & l) != 0L)
+                     jjCheckNAddStates(0, 2);
+                  if ((0x7fffffe07fffffeL & l) != 0L)
+                     jjCheckNAddStates(14, 16);
+                  break;
+               case 16:
+                  if ((0x7fffffe87fffffeL & l) != 0L)
+                  {
+                     if (kind > 23)
+                        kind = 23;
+                     jjCheckNAdd(5);
+                  }
+                  if ((0x7fffffe07fffffeL & l) != 0L)
+                  {
+                     if (kind > 23)
+                        kind = 23;
+                     jjCheckNAddTwoStates(4, 5);
+                  }
+                  break;
+               case 3:
+                  if ((0x7fffffe07fffffeL & l) != 0L)
+                  {
+                     if (kind > 23)
+                        kind = 23;
+                     jjCheckNAddTwoStates(4, 5);
+                  }
+                  if (curChar == 112)
+                     jjstateSet[jjnewStateCnt++] = 0;
+                  break;
+               case 1:
+                  if ((0x7fffffe07fffffeL & l) == 0L)
+                     break;
+                  if (kind > 17)
+                     kind = 17;
+                  jjCheckNAddTwoStates(1, 2);
+                  break;
+               case 2:
+                  if ((0x7fffffe87fffffeL & l) == 0L)
+                     break;
+                  if (kind > 17)
+                     kind = 17;
+                  jjCheckNAdd(2);
+                  break;
+               case 4:
+                  if ((0x7fffffe07fffffeL & l) == 0L)
+                     break;
+                  if (kind > 23)
+                     kind = 23;
+                  jjCheckNAddTwoStates(4, 5);
+                  break;
+               case 5:
+                  if ((0x7fffffe87fffffeL & l) == 0L)
+                     break;
+                  if (kind > 23)
+                     kind = 23;
+                  jjCheckNAdd(5);
+                  break;
+               case 7:
+                  if ((0x7fffffe07fffffeL & l) != 0L)
+                     jjCheckNAddStates(14, 16);
+                  break;
+               case 8:
+                  if ((0x7fffffe87fffffeL & l) != 0L)
+                     jjCheckNAddTwoStates(8, 9);
+                  break;
+               case 12:
+                  if ((0x7fffffe87fffffeL & l) != 0L)
+                     jjCheckNAddStates(7, 9);
+                  break;
+               case 13:
+                  if ((0x6fffffffffffffffL & l) != 0L)
+                     jjCheckNAddStates(7, 9);
+                  break;
+               case 14:
+                  if ((0x6800000178000001L & l) != 0L)
+                     jjCheckNAddStates(7, 9);
+                  break;
+               case 15:
+                  if ((0x6fffffffffffffffL & l) != 0L)
+                     jjCheckNAddStates(10, 13);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         MatchLoop: do
+         {
+            switch(jjstateSet[--i])
+            {
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 16 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+static final int[] jjnextStates = {
+   9, 11, 15, 7, 10, 12, 14, 13, 9, 11, 13, 9, 11, 15, 7, 8, 
+   9, 
+};
+public static final String[] jjstrLiteralImages = {
+"", null, null, null, "\40", "\40\101\116\104\40", "\40\117\122\40", "\47", 
+"\75", "\73", "\54", "\173", "\175", "\50", "\51", 
+"\142\165\143\153\145\164\116\141\155\145\163", "\156\141\155\145", null, "\75\75", "\76\75", "\76", "\74\75", "\74", null, 
+null, null, null, null, };
+public static final String[] lexStateNames = {
+   "DEFAULT", 
+};
+static final long[] jjtoToken = {
+   0x1fffff1L, 
+};
+static final long[] jjtoSkip = {
+   0xeL, 
+};
+protected SimpleCharStream input_stream;
+private final int[] jjrounds = new int[16];
+private final int[] jjstateSet = new int[32];
+protected char curChar;
+public QueryParserTokenManager(SimpleCharStream stream){
+   if (SimpleCharStream.staticFlag)
+      throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+   input_stream = stream;
+}
+public QueryParserTokenManager(SimpleCharStream stream, int lexState){
+   this(stream);
+   SwitchTo(lexState);
+}
+public void ReInit(SimpleCharStream stream)
+{
+   jjmatchedPos = jjnewStateCnt = 0;
+   curLexState = defaultLexState;
+   input_stream = stream;
+   ReInitRounds();
+}
+private final void ReInitRounds()
+{
+   int i;
+   jjround = 0x80000001;
+   for (i = 16; i-- > 0;)
+      jjrounds[i] = 0x80000000;
+}
+public void ReInit(SimpleCharStream stream, int lexState)
+{
+   ReInit(stream);
+   SwitchTo(lexState);
+}
+public void SwitchTo(int lexState)
+{
+   if (lexState >= 1 || lexState < 0)
+      throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+   else
+      curLexState = lexState;
+}
+
+protected Token jjFillToken()
+{
+   Token t = Token.newToken(jjmatchedKind);
+   t.kind = jjmatchedKind;
+   String im = jjstrLiteralImages[jjmatchedKind];
+   t.image = (im == null) ? input_stream.GetImage() : im;
+   t.beginLine = input_stream.getBeginLine();
+   t.beginColumn = input_stream.getBeginColumn();
+   t.endLine = input_stream.getEndLine();
+   t.endColumn = input_stream.getEndColumn();
+   return t;
+}
+
+int curLexState = 0;
+int defaultLexState = 0;
+int jjnewStateCnt;
+int jjround;
+int jjmatchedPos;
+int jjmatchedKind;
+
+public Token getNextToken() 
+{
+  int kind;
+  Token specialToken = null;
+  Token matchedToken;
+  int curPos = 0;
+
+  EOFLoop :
+  for (;;)
+  {   
+   try   
+   {     
+      curChar = input_stream.BeginToken();
+   }     
+   catch(java.io.IOException e)
+   {        
+      jjmatchedKind = 0;
+      matchedToken = jjFillToken();
+      return matchedToken;
+   }
+
+   try { input_stream.backup(0);
+      while (curChar <= 10 && (0x400L & (1L << curChar)) != 0L)
+         curChar = input_stream.BeginToken();
+   }
+   catch (java.io.IOException e1) { continue EOFLoop; }
+   jjmatchedKind = 0x7fffffff;
+   jjmatchedPos = 0;
+   curPos = jjMoveStringLiteralDfa0_0();
+   if (jjmatchedKind != 0x7fffffff)
+   {
+      if (jjmatchedPos + 1 < curPos)
+         input_stream.backup(curPos - jjmatchedPos - 1);
+      if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+      {
+         matchedToken = jjFillToken();
+         return matchedToken;
+      }
+      else
+      {
+         continue EOFLoop;
+      }
+   }
+   int error_line = input_stream.getEndLine();
+   int error_column = input_stream.getEndColumn();
+   String error_after = null;
+   boolean EOFSeen = false;
+   try { input_stream.readChar(); input_stream.backup(1); }
+   catch (java.io.IOException e1) {
+      EOFSeen = true;
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+      if (curChar == '\n' || curChar == '\r') {
+         error_line++;
+         error_column = 0;
+      }
+      else
+         error_column++;
+   }
+   if (!EOFSeen) {
+      input_stream.backup(1);
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+   }
+   throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
+  }
+}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParserTreeConstants.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParserTreeConstants.java
new file mode 100644
index 0000000..cf3628b
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/QueryParserTreeConstants.java
@@ -0,0 +1,29 @@
+/* Generated By:JJTree: Do not edit this line. ./QueryParserTreeConstants.java */
+
+package org.apache.oodt.cas.catalog.query.parser;
+
+public interface QueryParserTreeConstants
+{
+  public int JJTPARSEINPUT = 0;
+  public int JJTQUERY = 1;
+  public int JJTQUERYEXPRESSION = 2;
+  public int JJTSTDQUERYEXPRESSION = 3;
+  public int JJTCOMPARISONQUERYEXPRESSION = 4;
+  public int JJTPRIORITYQUERYEXPRESSION = 5;
+  public int JJTCUSTOMQUERYEXPRESSION = 6;
+  public int JJTGETVALUES = 7;
+  public int JJTGETPROPERTIES = 8;
+
+
+  public String[] jjtNodeName = {
+    "parseInput",
+    "Query",
+    "QueryExpression",
+    "StdQueryExpression",
+    "ComparisonQueryExpression",
+    "PriorityQueryExpression",
+    "CustomQueryExpression",
+    "getValues",
+    "getProperties",
+  };
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/SimpleCharStream.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/SimpleCharStream.java
new file mode 100644
index 0000000..eca5b5a
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/SimpleCharStream.java
@@ -0,0 +1,471 @@
+/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */
+/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package org.apache.oodt.cas.catalog.query.parser;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (without unicode processing).
+ */
+
+public class SimpleCharStream
+{
+/** Whether parser is static. */
+  public static final boolean staticFlag = false;
+  int bufsize;
+  int available;
+  int tokenBegin;
+/** Position in buffer. */
+  public int bufpos = -1;
+  protected int bufline[];
+  protected int bufcolumn[];
+
+  protected int column = 0;
+  protected int line = 1;
+
+  protected boolean prevCharIsCR = false;
+  protected boolean prevCharIsLF = false;
+
+  protected java.io.Reader inputStream;
+
+  protected char[] buffer;
+  protected int maxNextCharInd = 0;
+  protected int inBuf = 0;
+  protected int tabSize = 8;
+
+  protected void setTabSize(int i) { tabSize = i; }
+  protected int getTabSize(int i) { return tabSize; }
+
+
+  protected void ExpandBuff(boolean wrapAround)
+  {
+    char[] newbuffer = new char[bufsize + 2048];
+    int newbufline[] = new int[bufsize + 2048];
+    int newbufcolumn[] = new int[bufsize + 2048];
+
+    try
+    {
+      if (wrapAround)
+      {
+        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+        System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
+        buffer = newbuffer;
+
+        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+        System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+        bufline = newbufline;
+
+        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+        System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+        bufcolumn = newbufcolumn;
+
+        maxNextCharInd = (bufpos += (bufsize - tokenBegin));
+      }
+      else
+      {
+        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+        buffer = newbuffer;
+
+        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+        bufline = newbufline;
+
+        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+        bufcolumn = newbufcolumn;
+
+        maxNextCharInd = (bufpos -= tokenBegin);
+      }
+    }
+    catch (Throwable t)
+    {
+      throw new Error(t.getMessage());
+    }
+
+
+    bufsize += 2048;
+    available = bufsize;
+    tokenBegin = 0;
+  }
+
+  protected void FillBuff() throws java.io.IOException
+  {
+    if (maxNextCharInd == available)
+    {
+      if (available == bufsize)
+      {
+        if (tokenBegin > 2048)
+        {
+          bufpos = maxNextCharInd = 0;
+          available = tokenBegin;
+        }
+        else if (tokenBegin < 0)
+          bufpos = maxNextCharInd = 0;
+        else
+          ExpandBuff(false);
+      }
+      else if (available > tokenBegin)
+        available = bufsize;
+      else if ((tokenBegin - available) < 2048)
+        ExpandBuff(true);
+      else
+        available = tokenBegin;
+    }
+
+    int i;
+    try {
+      if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
+      {
+        inputStream.close();
+        throw new java.io.IOException();
+      }
+      else
+        maxNextCharInd += i;
+      return;
+    }
+    catch(java.io.IOException e) {
+      --bufpos;
+      backup(0);
+      if (tokenBegin == -1)
+        tokenBegin = bufpos;
+      throw e;
+    }
+  }
+
+/** Start. */
+  public char BeginToken() throws java.io.IOException
+  {
+    tokenBegin = -1;
+    char c = readChar();
+    tokenBegin = bufpos;
+
+    return c;
+  }
+
+  protected void UpdateLineColumn(char c)
+  {
+    column++;
+
+    if (prevCharIsLF)
+    {
+      prevCharIsLF = false;
+      line += (column = 1);
+    }
+    else if (prevCharIsCR)
+    {
+      prevCharIsCR = false;
+      if (c == '\n')
+      {
+        prevCharIsLF = true;
+      }
+      else
+        line += (column = 1);
+    }
+
+    switch (c)
+    {
+      case '\r' :
+        prevCharIsCR = true;
+        break;
+      case '\n' :
+        prevCharIsLF = true;
+        break;
+      case '\t' :
+        column--;
+        column += (tabSize - (column % tabSize));
+        break;
+      default :
+        break;
+    }
+
+    bufline[bufpos] = line;
+    bufcolumn[bufpos] = column;
+  }
+
+/** Read a character. */
+  public char readChar() throws java.io.IOException
+  {
+    if (inBuf > 0)
+    {
+      --inBuf;
+
+      if (++bufpos == bufsize)
+        bufpos = 0;
+
+      return buffer[bufpos];
+    }
+
+    if (++bufpos >= maxNextCharInd)
+      FillBuff();
+
+    char c = buffer[bufpos];
+
+    UpdateLineColumn(c);
+    return c;
+  }
+
+  @Deprecated
+  /**
+   * @deprecated
+   * @see #getEndColumn
+   */
+
+  public int getColumn() {
+    return bufcolumn[bufpos];
+  }
+
+  @Deprecated
+  /**
+   * @deprecated
+   * @see #getEndLine
+   */
+
+  public int getLine() {
+    return bufline[bufpos];
+  }
+
+  /** Get token end column number. */
+  public int getEndColumn() {
+    return bufcolumn[bufpos];
+  }
+
+  /** Get token end line number. */
+  public int getEndLine() {
+     return bufline[bufpos];
+  }
+
+  /** Get token beginning column number. */
+  public int getBeginColumn() {
+    return bufcolumn[tokenBegin];
+  }
+
+  /** Get token beginning line number. */
+  public int getBeginLine() {
+    return bufline[tokenBegin];
+  }
+
+/** Backup a number of characters. */
+  public void backup(int amount) {
+
+    inBuf += amount;
+    if ((bufpos -= amount) < 0)
+      bufpos += bufsize;
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    available = bufsize = buffersize;
+    buffer = new char[buffersize];
+    bufline = new int[buffersize];
+    bufcolumn = new int[buffersize];
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream, int startline,
+                          int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream)
+  {
+    this(dstream, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    if (buffer == null || buffersize != buffer.length)
+    {
+      available = bufsize = buffersize;
+      buffer = new char[buffersize];
+      bufline = new int[buffersize];
+      bufcolumn = new int[buffersize];
+    }
+    prevCharIsLF = prevCharIsCR = false;
+    tokenBegin = inBuf = maxNextCharInd = 0;
+    bufpos = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream, int startline,
+                     int startcolumn)
+  {
+    ReInit(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+  int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+  {
+    this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+                          int startcolumn) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, int startline,
+                          int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, 1, 1, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream)
+  {
+    this(dstream, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+                          int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, int startline,
+                          int startcolumn, int buffersize)
+  {
+    ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(dstream, encoding, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+                     int startcolumn) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(dstream, encoding, startline, startcolumn, 4096);
+  }
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, int startline,
+                     int startcolumn)
+  {
+    ReInit(dstream, startline, startcolumn, 4096);
+  }
+  /** Get token literal value. */
+  public String GetImage()
+  {
+    if (bufpos >= tokenBegin)
+      return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+    else
+      return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+                            new String(buffer, 0, bufpos + 1);
+  }
+
+  /** Get the suffix. */
+  public char[] GetSuffix(int len)
+  {
+    char[] ret = new char[len];
+
+    if ((bufpos + 1) >= len)
+      System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+    else
+    {
+      System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+                                                        len - bufpos - 1);
+      System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+    }
+
+    return ret;
+  }
+
+  /** Reset buffer when finished. */
+  public void Done()
+  {
+    buffer = null;
+    bufline = null;
+    bufcolumn = null;
+  }
+
+  /**
+   * Method to adjust line and column numbers for the start of a token.
+   */
+  public void adjustBeginLineColumn(int newLine, int newCol)
+  {
+    int start = tokenBegin;
+    int len;
+
+    if (bufpos >= tokenBegin)
+    {
+      len = bufpos - tokenBegin + inBuf + 1;
+    }
+    else
+    {
+      len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+    }
+
+    int i = 0, j = 0, k = 0;
+    int nextColDiff = 0, columnDiff = 0;
+
+    while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
+    {
+      bufline[j] = newLine;
+      nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+      bufcolumn[j] = newCol + columnDiff;
+      columnDiff = nextColDiff;
+      i++;
+    }
+
+    if (i < len)
+    {
+      bufline[j] = newLine++;
+      bufcolumn[j] = newCol + columnDiff;
+
+      while (i++ < len)
+      {
+        if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+          bufline[j] = newLine++;
+        else
+          bufline[j] = newLine;
+      }
+    }
+
+    line = bufline[j];
+    column = bufcolumn[j];
+  }
+
+}
+/* JavaCC - OriginalChecksum=121bf419e6c52d5335ce44acb0bd27aa (do not edit this line) */
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/SimpleNode.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/SimpleNode.java
new file mode 100644
index 0000000..7af2bcf
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/SimpleNode.java
@@ -0,0 +1,79 @@
+/* Generated By:JJTree: Do not edit this line. SimpleNode.java Version 4.3 */
+/* JavaCCOptions:MULTI=false,NODE_USES_PARSER=false,VISITOR=false,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package org.apache.oodt.cas.catalog.query.parser;
+
+public
+class SimpleNode implements Node {
+
+  protected Node parent;
+  protected Node[] children;
+  protected int id;
+  protected Object value;
+  protected QueryParser parser;
+
+  public SimpleNode(int i) {
+    id = i;
+  }
+
+  public SimpleNode(QueryParser p, int i) {
+    this(i);
+    parser = p;
+  }
+
+  public void jjtOpen() {
+  }
+
+  public void jjtClose() {
+  }
+
+  public void jjtSetParent(Node n) { parent = n; }
+  public Node jjtGetParent() { return parent; }
+
+  public void jjtAddChild(Node n, int i) {
+    if (children == null) {
+      children = new Node[i + 1];
+    } else if (i >= children.length) {
+      Node c[] = new Node[i + 1];
+      System.arraycopy(children, 0, c, 0, children.length);
+      children = c;
+    }
+    children[i] = n;
+  }
+
+  public Node jjtGetChild(int i) {
+    return children[i];
+  }
+
+  public int jjtGetNumChildren() {
+    return (children == null) ? 0 : children.length;
+  }
+
+  public void jjtSetValue(Object value) { this.value = value; }
+  public Object jjtGetValue() { return value; }
+
+  /* You can override these two methods in subclasses of SimpleNode to
+     customize the way the node appears when the tree is dumped.  If
+     your output uses more than one line you should override
+     toString(String), otherwise overriding toString() is probably all
+     you need to do. */
+
+  public String toString() { return QueryParserTreeConstants.jjtNodeName[id]; }
+  public String toString(String prefix) { return prefix + toString(); }
+
+  /* Override this method if you want to customize how the node dumps
+     out its children. */
+
+  public void dump(String prefix) {
+    System.out.println(toString(prefix));
+    if (children != null) {
+      for (int i = 0; i < children.length; ++i) {
+        SimpleNode n = (SimpleNode)children[i];
+        if (n != null) {
+          n.dump(prefix + " ");
+        }
+      }
+    }
+  }
+}
+
+/* JavaCC - OriginalChecksum=040e6dcfc83a8e9d2049166ee31054f3 (do not edit this line) */
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/Token.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/Token.java
new file mode 100644
index 0000000..2c18bd4
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/Token.java
@@ -0,0 +1,131 @@
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */
+/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package org.apache.oodt.cas.catalog.query.parser;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token implements java.io.Serializable {
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * An integer that describes the kind of this token.  This numbering
+   * system is determined by JavaCCParser, and a table of these numbers is
+   * stored in the file ...Constants.java.
+   */
+  public int kind;
+
+  /** The line number of the first character of this Token. */
+  public int beginLine;
+  /** The column number of the first character of this Token. */
+  public int beginColumn;
+  /** The line number of the last character of this Token. */
+  public int endLine;
+  /** The column number of the last character of this Token. */
+  public int endColumn;
+
+  /**
+   * The string image of the token.
+   */
+  public String image;
+
+  /**
+   * A reference to the next regular (non-special) token from the input
+   * stream.  If this is the last token from the input stream, or if the
+   * token manager has not read tokens beyond this one, this field is
+   * set to null.  This is true only if this token is also a regular
+   * token.  Otherwise, see below for a description of the contents of
+   * this field.
+   */
+  public Token next;
+
+  /**
+   * This field is used to access special tokens that occur prior to this
+   * token, but after the immediately preceding regular (non-special) token.
+   * If there are no such special tokens, this field is set to null.
+   * When there are more than one such special token, this field refers
+   * to the last of these special tokens, which in turn refers to the next
+   * previous special token through its specialToken field, and so on
+   * until the first special token (whose specialToken field is null).
+   * The next fields of special tokens refer to other special tokens that
+   * immediately follow it (without an intervening regular token).  If there
+   * is no such token, this field is null.
+   */
+  public Token specialToken;
+
+  /**
+   * An optional attribute value of the Token.
+   * Tokens which are not used as syntactic sugar will often contain
+   * meaningful values that will be used later on by the compiler or
+   * interpreter. This attribute value is often different from the image.
+   * Any subclass of Token that actually wants to return a non-null value can
+   * override this method as appropriate.
+   */
+  public Object getValue() {
+    return null;
+  }
+
+  /**
+   * No-argument constructor
+   */
+  public Token() {}
+
+  /**
+   * Constructs a new token for the specified Image.
+   */
+  public Token(int kind)
+  {
+    this(kind, null);
+  }
+
+  /**
+   * Constructs a new token for the specified Image and Kind.
+   */
+  public Token(int kind, String image)
+  {
+    this.kind = kind;
+    this.image = image;
+  }
+
+  /**
+   * Returns the image.
+   */
+  public String toString()
+  {
+    return image;
+  }
+
+  /**
+   * Returns a new Token object, by default. However, if you want, you
+   * can create and return subclass objects based on the value of ofKind.
+   * Simply add the cases to the switch for all those special cases.
+   * For example, if you have a subclass of Token called IDToken that
+   * you want to create if ofKind is ID, simply add something like :
+   *
+   *    case MyParserConstants.ID : return new IDToken(ofKind, image);
+   *
+   * to the following switch statement. Then you can cast matchedToken
+   * variable to the appropriate type and use sit in your lexical actions.
+   */
+  public static Token newToken(int ofKind, String image)
+  {
+    switch(ofKind)
+    {
+      default : return new Token(ofKind, image);
+    }
+  }
+
+  public static Token newToken(int ofKind)
+  {
+    return newToken(ofKind, null);
+  }
+
+}
+/* JavaCC - OriginalChecksum=a71b830768b8b7df481722ce93775dc3 (do not edit this line) */
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/TokenMgrError.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/TokenMgrError.java
new file mode 100644
index 0000000..27df15c
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/query/parser/TokenMgrError.java
@@ -0,0 +1,147 @@
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */
+/* JavaCCOptions: */
+package org.apache.oodt.cas.catalog.query.parser;
+
+/** Token Manager Error. */
+public class TokenMgrError extends Error
+{
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /*
+   * Ordinals for various reasons why an Error of this type can be thrown.
+   */
+
+  /**
+   * Lexical error occurred.
+   */
+  static final int LEXICAL_ERROR = 0;
+
+  /**
+   * An attempt was made to create a second instance of a static token manager.
+   */
+  static final int STATIC_LEXER_ERROR = 1;
+
+  /**
+   * Tried to change to an invalid lexical state.
+   */
+  static final int INVALID_LEXICAL_STATE = 2;
+
+  /**
+   * Detected (and bailed out of) an infinite loop in the token manager.
+   */
+  static final int LOOP_DETECTED = 3;
+
+  /**
+   * Indicates the reason why the exception is thrown. It will have
+   * one of the above 4 values.
+   */
+  int errorCode;
+
+  /**
+   * Replaces unprintable characters by their escaped (or unicode escaped)
+   * equivalents in the given string
+   */
+  protected static final String addEscapes(String str) {
+    StringBuffer retval = new StringBuffer();
+    char ch;
+    for (int i = 0; i < str.length(); i++) {
+      switch (str.charAt(i))
+      {
+        case 0 :
+          continue;
+        case '\b':
+          retval.append("\\b");
+          continue;
+        case '\t':
+          retval.append("\\t");
+          continue;
+        case '\n':
+          retval.append("\\n");
+          continue;
+        case '\f':
+          retval.append("\\f");
+          continue;
+        case '\r':
+          retval.append("\\r");
+          continue;
+        case '\"':
+          retval.append("\\\"");
+          continue;
+        case '\'':
+          retval.append("\\\'");
+          continue;
+        case '\\':
+          retval.append("\\\\");
+          continue;
+        default:
+          if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+            String s = "0000" + Integer.toString(ch, 16);
+            retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+          } else {
+            retval.append(ch);
+          }
+          continue;
+      }
+    }
+    return retval.toString();
+  }
+
+  /**
+   * Returns a detailed message for the Error when it is thrown by the
+   * token manager to indicate a lexical error.
+   * Parameters :
+   *    EOFSeen     : indicates if EOF caused the lexical error
+   *    curLexState : lexical state in which this error occurred
+   *    errorLine   : line number when the error occurred
+   *    errorColumn : column number when the error occurred
+   *    errorAfter  : prefix that was seen before this error occurred
+   *    curchar     : the offending character
+   * Note: You can customize the lexical error message by modifying this method.
+   */
+  protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
+    return("Lexical error at line " +
+          errorLine + ", column " +
+          errorColumn + ".  Encountered: " +
+          (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+          "after : \"" + addEscapes(errorAfter) + "\"");
+  }
+
+  /**
+   * You can also modify the body of this method to customize your error messages.
+   * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+   * of end-users concern, so you can return something like :
+   *
+   *     "Internal Error : Please file a bug report .... "
+   *
+   * from this method for such cases in the release version of your parser.
+   */
+  public String getMessage() {
+    return super.getMessage();
+  }
+
+  /*
+   * Constructors of various flavors follow.
+   */
+
+  /** No arg constructor. */
+  public TokenMgrError() {
+  }
+
+  /** Constructor with message and reason. */
+  public TokenMgrError(String message, int reason) {
+    super(message);
+    errorCode = reason;
+  }
+
+  /** Full Constructor. */
+  public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
+    this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+  }
+}
+/* JavaCC - OriginalChecksum=aa4a499114e90d0d55997529e48f5ebe (do not edit this line) */
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/CatalogRepository.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/CatalogRepository.java
new file mode 100644
index 0000000..12b90e0
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/CatalogRepository.java
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.repository;
+
+//JDK imports
+import java.util.List;
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogRepositoryException;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.util.PluginURL;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ *          <p>
+ *          Repository where the CatalogService stores its TransactionId Mapping
+ *          and serializes its Catalogs
+ *          <p>
+ */
+public interface CatalogRepository {
+//
+//	/**
+//	 * Verifies if the given Catalog URN has been serialized via {@link
+//	 * serializeCatalog(Catalog)}
+//	 * 
+//	 * @param catalogUrn
+//	 *            The URN that unique represents the Catalog
+//	 * @return True if the Catalog has been serialized, false otherwise
+//	 * @throws CatalogRepositoryException
+//	 *             Any Error
+//	 */
+//	public boolean isCatalogSerialized(String catalogUrn)
+//			throws CatalogRepositoryException;
+//
+	/**
+	 * Serializes a given Catalog to the Repository
+	 * 
+	 * @param catalog
+	 *            The Catalog to be serialized
+	 * @throws CatalogRepositoryException
+	 *             Any Error
+	 */
+	public void serializeCatalog(Catalog catalog)
+			throws CatalogRepositoryException;
+//
+//	/**
+//	 * Loads a Catalog from the Repository
+//	 * 
+//	 * @param catalogUrn
+//	 *            The URN that unique represents a Catalog
+//	 * @return The Catalog represented by the given URN
+//	 * @throws CatalogRepositoryException
+//	 *             Any Error
+//	 */
+//	public Catalog deserializeCatalog(String catalogUrn)
+//			throws CatalogRepositoryException;
+//
+	/**
+	 * Removes a Catalog from the Repository
+	 * 
+	 * @param catalogUrn
+	 *            The URN that unique represents the Catalog to be removed
+	 * @param preserveMapping
+	 *            If true, don't erase TransactionId mapping for this catalog
+	 * @throws CatalogRepositoryException
+	 *             Any Error
+	 */
+	public void deleteSerializedCatalog(String catalogUrn)
+			throws CatalogRepositoryException;
+
+	/**
+	 * Loads all Catalogs serialized in this Repository
+	 * 
+	 * @return All the Catalogs serialized in this Repository
+	 * @throws CatalogRepositoryException
+	 *             Any Error
+	 */
+	public Set<Catalog> deserializeAllCatalogs()
+			throws CatalogRepositoryException;
+
+	public void serializePluginURLs(List<PluginURL> urls) 
+			throws CatalogRepositoryException;
+	
+	public List<PluginURL> deserializePluginURLs() 
+			throws CatalogRepositoryException;
+	
+	public boolean isModifiable() throws CatalogRepositoryException;
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/CatalogRepositoryFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/CatalogRepositoryFactory.java
new file mode 100644
index 0000000..e171154
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/CatalogRepositoryFactory.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.repository;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogRepositoryException;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory for creating CatalogRepository
+ * <p>
+ */
+public interface CatalogRepositoryFactory {
+
+	public CatalogRepository createRepository() throws CatalogRepositoryException;
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/MemoryBasedCatalogRepository.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/MemoryBasedCatalogRepository.java
new file mode 100644
index 0000000..4a82e98
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/MemoryBasedCatalogRepository.java
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.repository;
+
+//JDK imports
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogRepositoryException;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.util.PluginURL;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ *          <p>
+ *          Memory based Repository where the CatalogService stores its
+ *          TransactionId Mapping and serializes its Catalogs
+ *          <p>
+ */
+public class MemoryBasedCatalogRepository implements CatalogRepository {
+	
+	protected HashMap<String, Catalog> catalogMap;
+	protected List<PluginURL> classLoaderUrls;
+
+	public MemoryBasedCatalogRepository() {
+		this.catalogMap = new HashMap<String, Catalog>();
+		this.classLoaderUrls = new Vector<PluginURL>();
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @seeorg.apache.oodt.cas.catalog.repository.CatalogRepository#
+	 * deleteSerializedCatalog(java.lang.String)
+	 */
+	public void deleteSerializedCatalog(String catalogUrn)
+			throws CatalogRepositoryException {
+		this.catalogMap.remove(catalogUrn);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @seeorg.apache.oodt.cas.catalog.repository.CatalogRepository#
+	 * deserializeAllCatalogs()
+	 */
+	public Set<Catalog> deserializeAllCatalogs()
+			throws CatalogRepositoryException {
+		return new HashSet<Catalog>(this.catalogMap.values());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.apache.oodt.cas.catalog.repository.CatalogRepository#deserializeCatalog
+	 * (java.lang.String)
+	 */
+	public Catalog deserializeCatalog(String catalogUrn)
+			throws CatalogRepositoryException {
+		return this.catalogMap.get(catalogUrn);
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @seeorg.apache.oodt.cas.catalog.repository.CatalogRepository#
+	 * isCatalogSerialized(java.lang.String)
+	 */
+	public boolean isCatalogSerialized(String catalogUrn)
+			throws CatalogRepositoryException {
+		return this.catalogMap.containsKey(catalogUrn);
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.apache.oodt.cas.catalog.repository.CatalogRepository#serializeCatalog
+	 * (org.apache.oodt.cas.catalog.Catalog)
+	 */
+	public void serializeCatalog(Catalog catalog)
+			throws CatalogRepositoryException {
+		this.catalogMap.put(catalog.getId(), catalog);
+	}
+	
+	public void serializePluginURLs(List<PluginURL> urls) 
+			throws CatalogRepositoryException {
+		this.classLoaderUrls.addAll(urls);
+	}
+
+	public List<PluginURL> deserializePluginURLs() 
+			throws CatalogRepositoryException {
+		return new Vector<PluginURL>(this.classLoaderUrls);
+	}
+	
+	public boolean isModifiable() 
+			throws CatalogRepositoryException {
+		return true;
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/MemoryBasedCatalogRepositoryFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/MemoryBasedCatalogRepositoryFactory.java
new file mode 100644
index 0000000..9d25064
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/MemoryBasedCatalogRepositoryFactory.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.repository;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogRepositoryException;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory for creating MemoryBasedCatalogRepository
+ * <p>
+ */
+public class MemoryBasedCatalogRepositoryFactory implements
+		CatalogRepositoryFactory {
+
+	public MemoryBasedCatalogRepository createRepository()
+			throws CatalogRepositoryException {
+		return new MemoryBasedCatalogRepository();
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/SerializedCatalogRepository.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/SerializedCatalogRepository.java
new file mode 100644
index 0000000..b130280
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/SerializedCatalogRepository.java
@@ -0,0 +1,209 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.repository;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//APACHE imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogRepositoryException;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.util.PluginURL;
+import org.apache.oodt.cas.catalog.util.Serializer;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * Catalog Repository that serializes Catalogs via XStream utility
+ * <p>
+ */
+public class SerializedCatalogRepository implements CatalogRepository {
+
+	private static Logger LOG = Logger.getLogger(SerializedCatalogRepository.class.getName());
+	protected String storageDir;
+	
+	public SerializedCatalogRepository(String storageDir) throws InstantiationException {
+		try {
+			this.storageDir = storageDir;
+			new File(this.storageDir + "/catalogs").mkdirs();
+			new File(this.storageDir + "/classloaders").mkdirs();
+		}catch(Exception e) {
+			e.printStackTrace();
+			throw new InstantiationException("Failed to instantiate SerializedCatalogRepository : " + e.getMessage());
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.apache.oodt.cas.catalog.repository.MemoryBasedCatalogRepository#deleteSerializedCatalog(java.lang.String)
+	 */
+	public void deleteSerializedCatalog(String catalogUrn)
+			throws CatalogRepositoryException {
+		LOG.log(Level.INFO, "Deleting Catalog: '" + catalogUrn + "' . . . ");
+		boolean catalogFileDelete = this.getCatalogFile(catalogUrn).delete();
+		if (!catalogFileDelete)
+			throw new CatalogRepositoryException("Failed to deserialize catalog '" + catalogUrn + "', delete files returned false");
+		else 
+			LOG.log(Level.INFO, "Successfully deleting Catalog: '" + catalogUrn + "'");
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.apache.oodt.cas.catalog.repository.MemoryBasedCatalogRepository#deserializeCatalog(java.lang.String)
+	 */
+	public Catalog deserializeCatalog(String catalogUrn)
+			throws CatalogRepositoryException {
+		LOG.log(Level.INFO, "Deserializing Catalog: " + catalogUrn);
+		FileInputStream catalogIn = null;
+		try {
+			return new Serializer().deserializeObject(Catalog.class, catalogIn = new FileInputStream(this.getCatalogFile(catalogUrn)));
+		}catch (Exception e) {
+			throw new CatalogRepositoryException("Failed to Deserialized Catalogs from '" + this.storageDir + "' : " + e.getMessage(), e);
+		}finally {
+			try {
+				catalogIn.close();
+			}catch (Exception e) {}
+		}
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.apache.oodt.cas.catalog.repository.MemoryBasedCatalogRepository#deserializeAllCatalogs()
+	 */
+	public Set<Catalog> deserializeAllCatalogs()
+			throws CatalogRepositoryException {
+		HashSet<Catalog> catalogs = new HashSet<Catalog>();
+		for (String catalogFile : new File(this.storageDir + "/catalogs").list()) {
+			Catalog catalog = this.deserializeCatalog(catalogFile.split("\\.ser")[0]);
+			catalogs.add(catalog);
+		}
+		return catalogs;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.apache.oodt.cas.catalog.repository.MemoryBasedCatalogRepository#isCatalogSerialized(java.lang.String)
+	 */
+	public boolean isCatalogSerialized(String catalogUrn)
+			throws CatalogRepositoryException {
+		return this.getCatalogFile(catalogUrn).exists();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.apache.oodt.cas.catalog.repository.MemoryBasedCatalogRepository#serializeCatalog(org.apache.oodt.cas.catalog.Catalog)
+	 */
+	public void serializeCatalog(Catalog catalog)
+			throws CatalogRepositoryException {
+		LOG.log(Level.INFO, "Serializing Catalog: " + catalog.getId());
+		FileOutputStream catalogOut = null;
+		try {
+			//serialize Catalog
+			new Serializer().serializeObject(catalog, (catalogOut = new FileOutputStream(this.getCatalogFileWorker(catalog.getId()))));
+			if (this.getCatalogFile(catalog.getId()).exists())
+				FileUtils.copyFile(this.getCatalogFile(catalog.getId()), this.getCatalogFileBkup(catalog.getId()), true);
+			FileUtils.copyFile(this.getCatalogFileWorker(catalog.getId()), this.getCatalogFile(catalog.getId()), true);
+			this.getCatalogFileWorker(catalog.getId()).delete();
+			this.getCatalogFileBkup(catalog.getId()).delete();
+		}catch (Exception e) {
+			throw new CatalogRepositoryException("Failed to Serialized Catalogs to '" + this.storageDir + "' : " + e.getMessage(), e);
+		}finally {
+			try {
+				catalogOut.close();
+			}catch (Exception e) {}
+		}	
+	}
+	
+	public void serializePluginURLs(List<PluginURL> urls) 
+			throws CatalogRepositoryException {
+		FileOutputStream urlsOut = null;
+		try {
+			//serialize URLs
+			new Serializer().serializeObject(urls, (urlsOut = new FileOutputStream(this.getClassLoaderUrlsFileWorker())));
+			if (this.getClassLoaderUrlsFile().exists())
+				FileUtils.copyFile(this.getClassLoaderUrlsFile(), this.getClassLoaderUrlsFileBkup(), true);
+			FileUtils.copyFile(this.getClassLoaderUrlsFileWorker(), this.getClassLoaderUrlsFile(), true);
+			this.getClassLoaderUrlsFileWorker().delete();
+			this.getClassLoaderUrlsFileBkup().delete();
+		}catch (Exception e) {
+			throw new CatalogRepositoryException("Failed to Serialized ClassLoader URLs to '" + this.storageDir + "' : " + e.getMessage(), e);
+		}finally {
+			try {
+				urlsOut.close();
+			}catch (Exception e) {}
+		}	
+	}
+
+	public List<PluginURL> deserializePluginURLs() throws CatalogRepositoryException {
+		FileInputStream urlsIn = null;
+		try {
+			if (this.getClassLoaderUrlsFile().exists())
+				return new Serializer().deserializeObject(List.class, (urlsIn = new FileInputStream(this.getClassLoaderUrlsFile())));
+			else
+				return Collections.emptyList();
+		}catch (Exception e) {
+			throw new CatalogRepositoryException("Failed to Deserialized All ClassLoader URLs from '" + this.storageDir + "' : " + e.getMessage(), e);
+		}finally {
+			try {
+				urlsIn.close();
+			}catch (Exception e) {}
+		}
+	}
+
+	public boolean isModifiable() 
+			throws CatalogRepositoryException {
+		return true;
+	}
+
+	protected File getCatalogFile(String catalogUrn) {
+		return new File(this.storageDir + "/catalogs/" + catalogUrn + ".ser");
+	}
+
+	protected File getCatalogFileBkup(String catalogUrn) {
+		return new File(this.storageDir + "/catalogs/" + catalogUrn + ".ser-bkup");
+	}
+	
+	protected File getCatalogFileWorker(String catalogUrn) {
+		return new File(this.storageDir + "/catalogs/" + catalogUrn + ".ser-worker");
+	}
+	
+	protected File getClassLoaderUrlsFile() {
+		return new File(this.storageDir + "/classloaders/urls.ser");
+	}
+	
+	protected File getClassLoaderUrlsFileBkup() {
+		return new File(this.storageDir + "/classloaders/urls.ser-bkup");
+	}
+	
+	protected File getClassLoaderUrlsFileWorker() {
+		return new File(this.storageDir + "/classloaders/urls.ser-worker");
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/SerializedCatalogRepositoryFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/SerializedCatalogRepositoryFactory.java
new file mode 100644
index 0000000..7e07b40
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/SerializedCatalogRepositoryFactory.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.repository;
+
+//Spring imports
+import org.apache.oodt.cas.catalog.exception.CatalogRepositoryException;
+import org.springframework.beans.factory.annotation.Required;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory for creating SerializedMemoryBasedCatalogRepository
+ * <p>
+ */
+public class SerializedCatalogRepositoryFactory implements CatalogRepositoryFactory {
+
+	protected String storageDir;
+
+	public SerializedCatalogRepositoryFactory() {}
+	
+	@Required
+	public void setStorageDir(String storageDir) {
+		this.storageDir = storageDir;
+	}
+
+	public SerializedCatalogRepository createRepository()
+			throws CatalogRepositoryException {
+		try {
+			return new SerializedCatalogRepository(PathUtils.doDynamicReplacement(this.storageDir));
+		}catch (Exception e) {
+			throw new CatalogRepositoryException("Failed to create Serialized Catalog Repository : " + e.getMessage(), e);
+		}
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/SpringCatalogRepository.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/SpringCatalogRepository.java
new file mode 100644
index 0000000..c78f7fb
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/SpringCatalogRepository.java
@@ -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.
+ */
+package org.apache.oodt.cas.catalog.repository;
+
+//JDK imports
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogRepositoryException;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.util.PluginURL;
+import org.apache.oodt.cas.catalog.util.Serializer;
+
+//Spring imports
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Spring Framework based CatalogRepository
+ * <p>
+ */
+public class SpringCatalogRepository implements CatalogRepository {
+
+	protected String beanRepo;
+	
+	public SpringCatalogRepository(String beanRepo) {
+		this.beanRepo = beanRepo;
+	}
+	
+	public Set<Catalog> deserializeAllCatalogs()
+			throws CatalogRepositoryException {
+		try {
+	        FileSystemXmlApplicationContext appContext = new FileSystemXmlApplicationContext(new String[] { this.beanRepo }, false);
+	        appContext.setClassLoader(new Serializer().getClassLoader());
+	        appContext.refresh();
+	        return new HashSet<Catalog>(appContext.getBeansOfType(Catalog.class).values());
+		} catch (Exception e) {
+			throw new CatalogRepositoryException(e.getMessage(), e);
+		}
+	}
+
+	public void deleteSerializedCatalog(String catalogUrn)
+			throws CatalogRepositoryException {
+		throw new CatalogRepositoryException("Modification not allowed during runtime");
+	}
+
+	public boolean isModifiable() throws CatalogRepositoryException {
+		return false;
+	}
+
+	public void serializeCatalog(Catalog catalog)
+			throws CatalogRepositoryException {
+		throw new CatalogRepositoryException("Modification not allowed during runtime");		
+	}
+
+	public List<PluginURL> deserializePluginURLs()
+			throws CatalogRepositoryException {
+		// TODO Auto-generated method stub
+		return Collections.emptyList();
+	}
+
+	public void serializePluginURLs(List<PluginURL> urls)
+			throws CatalogRepositoryException {
+		throw new CatalogRepositoryException("Modification not allowed during runtime");		
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/SpringCatalogRepositoryFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/SpringCatalogRepositoryFactory.java
new file mode 100644
index 0000000..4a7a71b
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/repository/SpringCatalogRepositoryFactory.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.repository;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogRepositoryException;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A factory for creating SpringCatalogRepository
+ * <p>
+ */
+public class SpringCatalogRepositoryFactory implements CatalogRepositoryFactory {
+
+	protected String catalogBeanRepo;
+	
+	public CatalogRepository createRepository()
+			throws CatalogRepositoryException {
+		return new SpringCatalogRepository(this.catalogBeanRepo);
+	}
+	
+	public void setCatalogBeanRepo(String catalogBeanRepo) {
+		this.catalogBeanRepo = catalogBeanRepo;
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/CatalogServiceCommandLineClient.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/CatalogServiceCommandLineClient.java
new file mode 100644
index 0000000..89135ed
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/CatalogServiceCommandLineClient.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server;
+
+//JDK imports
+import java.io.FileInputStream;
+
+//OODT imports
+import org.apache.oodt.cas.cli.CmdLineUtility;
+
+/**
+ * Client Utility for sending commands to servers.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class CatalogServiceCommandLineClient {
+
+   public static void main(String[] args) throws Exception {
+      // Load Catalog Service properties.
+      String propertiesFile = System
+            .getProperty("org.apache.oodt.cas.catalog.properties.file");
+      if (propertiesFile != null) {
+         System.getProperties().load(new FileInputStream(propertiesFile));
+      }
+
+      // Run Command line.
+      CmdLineUtility cmdLineUtility = new CmdLineUtility();
+      cmdLineUtility.run(args);
+   }
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/CatalogServiceServerLauncher.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/CatalogServiceServerLauncher.java
new file mode 100644
index 0000000..4b911af
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/CatalogServiceServerLauncher.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server;
+
+//JDK imports
+import java.io.FileInputStream;
+
+//OODT imports
+import org.apache.oodt.cas.cli.CmdLineUtility;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * Utility for launching CommunicationChannelServers
+ * <p>
+ */
+public class CatalogServiceServerLauncher {
+		
+	private CatalogServiceServerLauncher() throws InstantiationException {}
+	
+	public static void main(String[] args) throws Exception {
+      // Load Catalog Service properties.
+      String propertiesFile = System
+            .getProperty("org.apache.oodt.cas.catalog.properties.file");
+      if (propertiesFile != null) {
+         System.getProperties().load(new FileInputStream(propertiesFile));
+      }
+
+      // Run Command line.
+      CmdLineUtility cmdLineUtility = new CmdLineUtility();
+      cmdLineUtility.run(args);
+	}
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/AbstractCommunicationChannelClient.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/AbstractCommunicationChannelClient.java
new file mode 100644
index 0000000..0d0ae6f
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/AbstractCommunicationChannelClient.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel;
+
+//JDK imports
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.util.Serializer;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * An Abstract Communication Channel Client Interface that automatically handles throw execeptions
+ * <p>
+ */
+public abstract class AbstractCommunicationChannelClient implements CommunicationChannelClient {
+	
+	private static Logger LOG = Logger.getLogger(AbstractCommunicationChannelClient.class.getName());
+	protected Serializer serializer;
+
+	public AbstractCommunicationChannelClient() {
+		this.serializer = new Serializer(false);
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/AbstractCommunicationChannelServer.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/AbstractCommunicationChannelServer.java
new file mode 100644
index 0000000..3549d86
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/AbstractCommunicationChannelServer.java
@@ -0,0 +1,455 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel;
+
+//JDK imports
+import java.net.URL;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.Page;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.page.TransactionReceipt;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.struct.Dictionary;
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.system.CatalogService;
+import org.apache.oodt.cas.catalog.util.PluginURL;
+import org.apache.oodt.cas.catalog.util.Serializer;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * An Abstract Communication Channel Server Interface that automatically handles throw exceptions
+ * <p>
+ */
+public abstract class AbstractCommunicationChannelServer implements CommunicationChannelServer {
+	
+	private static Logger LOG = Logger.getLogger(AbstractCommunicationChannelServer.class.getName());
+	
+	protected CatalogService catalogService;
+	protected int port;
+	protected Serializer serializer;
+	
+	public AbstractCommunicationChannelServer() {
+		this.serializer = new Serializer();
+	}
+	
+	public void setCatalogService(CatalogService catalogService) {
+		this.catalogService = catalogService;
+	}
+	
+	public void setPort(int port) { 
+		this.port = port;
+	}
+	
+	public int getPort() {
+		return this.port;
+	}
+
+	public void shutdown() throws Exception {
+		try {
+			this.catalogService.shutdown();
+			this.catalogService = null;
+			System.gc(); // used to speed up shutdown process (gives java a boost-start at cleaning up everything so server will die)
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed to shutdown server : " + e.getMessage(), e);
+			throw new Exception("Failed to shutdown server : " + e.getMessage(), e);
+		}
+	}
+	
+	public boolean isRestrictQueryPermissions() throws Exception {
+		try {
+			return this.catalogService.isRestrictQueryPermissions();
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while checking server query permissions : " + e.getMessage(), e);
+			throw new Exception("Failed while checking server query permissions : " + e.getMessage(), e);
+		}
+	}
+//
+//	public void setRestrictQueryPermissions(boolean restrictQueryPermissions) throws CatalogServiceException {
+//		this.catalogService.setRestrictQueryPermissions(restrictQueryPermissions);
+//	}
+//
+	public boolean isRestrictIngestPermissions() throws Exception {
+		try {
+			return this.catalogService.isRestrictIngestPermissions();
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while checking server ingest permissions : " + e.getMessage(), e);
+			throw new Exception("Failed while checking server ingest permissions : " + e.getMessage(), e);
+		}
+	}
+//
+//	public void setHasIngestPermissions(boolean restrictIngestPermissions) throws CatalogServiceException {
+//		this.catalogService.setHasIngestPermissions(restrictIngestPermissions);
+//	}
+
+//	public Class<? extends TransactionId<?>> getTransactionIdClass() throws CatalogServiceException {
+//		return this.catalogService.getTransactionIdClass();
+//	}
+//
+//	public void setTransactionIdClass(Class<? extends TransactionId<?>> transactionIdClass) throws CatalogServiceException {
+//		this.catalogService.setTransactionIdClass(transactionIdClass);
+//	}
+//
+	public void addCatalog(Catalog catalog) throws Exception {
+		try {
+			this.catalogService.addCatalog(catalog);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while adding catalog '" + catalog + "' to server : " + e.getMessage(), e);
+			throw new Exception("Failed while adding catalog '" + catalog + "' to server : " + e.getMessage(), e);
+		}
+	}
+	
+	public void replaceCatalog(Catalog catalog) throws Exception {
+		try {
+			this.catalogService.replaceCatalog(catalog);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while replacing catalog '" + catalog + "' to server : " + e.getMessage(), e);
+			throw new Exception("Failed while replacing catalog '" + catalog + "' to server : " + e.getMessage(), e);
+		}
+	}
+	
+	public void addCatalog(String catalogId, Index index) throws Exception {
+		try {
+			this.catalogService.addCatalog(catalogId, index);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while adding catalog '" + catalogId + "' with index '" + index + "' to server : " + e.getMessage(), e);
+			throw new Exception("Failed while adding catalog '" + catalogId + "' with index '" + index + "' to server : " + e.getMessage(), e);
+		}
+	}
+	
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries) throws Exception {
+		try {
+			this.catalogService.addCatalog(catalogId, index, dictionaries);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while adding catalog '" + catalogId + "' with index '" + index + "' and dictionaries '" + dictionaries + "' to server : " + e.getMessage(), e);
+			throw new Exception("Failed while adding catalog '" + catalogId + "' with index '" + index + "' and dictionaries '" + dictionaries + "' to server : " + e.getMessage(), e);
+		}
+	}
+
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries, boolean restrictQueryPermission, boolean restrictIngestPermission) throws Exception {
+		try {
+			this.catalogService.addCatalog(catalogId, index, dictionaries, restrictQueryPermission, restrictIngestPermission);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while adding catalog '" + catalogId + "' with index '" + index + "' and dictionaries '" + dictionaries + "' and restrictQueryPermission '" + restrictQueryPermission + "' and restrictIngestPermission '" + restrictIngestPermission + "' to server : " + e.getMessage(), e);
+			throw new Exception("Failed while adding catalog '" + catalogId + "' with index '" + index + "' and dictionaries '" + dictionaries + "' and restrictQueryPermission '" + restrictQueryPermission + "' and restrictIngestPermission '" + restrictIngestPermission + "' to server : " + e.getMessage(), e);
+		}
+	}
+
+	public void addDictionary(String catalogId, Dictionary dictionary) throws Exception {
+		try {
+			this.catalogService.addDictionary(catalogId, dictionary);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while adding dictionary '" + dictionary + "' to catalog '" + catalogId + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while adding dictionary '" + dictionary + "' to catalog '" + catalogId + "' : " + e.getMessage(), e);
+		}
+	}
+	
+	public void replaceDictionaries(String catalogId, List<Dictionary> dictionaries) throws Exception {
+		try {
+			this.catalogService.replaceDictionaries(catalogId, dictionaries);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while replacing dictionaries '" + dictionaries + "' in catalog '" + catalogId + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while replacing dictionaries '" + dictionaries + "' in catalog '" + catalogId + "' : " + e.getMessage(), e);
+		}
+	}
+
+	public void replaceIndex(String catalogId, Index index) throws Exception {
+		try {
+			this.catalogService.replaceIndex(catalogId, index);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while replacing index '" + index + "' in catalog '" + catalogId + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while replacing index '" + index + "' in catalog '" + catalogId + "' : " + e.getMessage(), e);
+		}
+	}
+
+	public void modifyIngestPermission(String catalogId, boolean restrictIngestPermission) throws Exception {
+		try {
+			this.catalogService.modifyIngestPermission(catalogId, restrictIngestPermission);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while changing ingest permissions for catalog '" + catalogId + "' to '" + restrictIngestPermission + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while changing ingest permissions for catalog '" + catalogId + "' to '" + restrictIngestPermission + "' : " + e.getMessage(), e);
+		}
+	}
+	
+	public void modifyQueryPermission(String catalogId, boolean restrictQueryPermission) throws Exception {
+		try {
+			this.catalogService.modifyQueryPermission(catalogId, restrictQueryPermission);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while changing query permissions for catalog '" + catalogId + "' to '" + restrictQueryPermission + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while changing query permissions for catalog '" + catalogId + "' to '" + restrictQueryPermission + "' : " + e.getMessage(), e);
+		}
+	}
+	
+	public void removeCatalog(String catalogId) throws Exception {
+		try {
+			this.catalogService.removeCatalog(catalogId);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while removing catalog '" + catalogId + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while removing catalog '" + catalogId + "' : " + e.getMessage(), e);
+		}
+	}
+
+//	public void removeCatalog(String catalogUrn, boolean preserveMapping) throws CatalogServiceException {
+//		this.catalogService.removeCatalog(catalogUrn, preserveMapping);
+//	}
+
+	public List<PluginURL> getPluginUrls() throws Exception {
+		try {
+			return this.catalogService.getPluginUrls();
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting plugin URLs : " + e.getMessage(), e);
+			throw new Exception("Failed while getting plugin URLs : " + e.getMessage(), e);
+		}
+	}
+	
+	public void addPluginUrls(List<PluginURL> pluginURLs) throws Exception {
+		try {
+			this.catalogService.addPluginUrls(pluginURLs);
+			this.serializer.refreshClassLoader();
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while adding plugin URLs '" + pluginURLs + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while adding plugin URLs '" + pluginURLs + "' : " + e.getMessage(), e);
+		}
+	}
+	
+	public URL getPluginStorageDir() throws Exception {
+		try {
+			return this.catalogService.getPluginStorageDir();
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting plugin storage directory : " + e.getMessage(), e);
+			throw new Exception("Failed while getting plugin storage directory : " + e.getMessage(), e);
+		}
+	}
+	
+//	public Set<Catalog> getCurrentCatalogList() throws CatalogServiceException {
+//		return this.catalogService.getCurrentCatalogList();
+//	}
+//	
+//	public Catalog getCatalog(String catalogUrn) throws CatalogServiceException {
+//		return this.catalogService.getCatalog(catalogUrn);
+//	}
+
+	public Set<String> getCurrentCatalogIds() throws Exception {
+		try {
+			return this.catalogService.getCurrentCatalogIds();
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting current catalog ids : " + e.getMessage(), e);
+			throw new Exception("Failed while getting current catalog ids : " + e.getMessage(), e);
+		}	
+	}
+		
+	public TransactionReceipt ingest(Metadata metadata) throws Exception {
+		try {
+			return this.catalogService.ingest(metadata);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while performing ingest : " + e.getMessage(), e);
+			throw new Exception("Failed while performing ingest : " + e.getMessage(), e);
+		}
+	}
+	
+	public void delete(Metadata metadata) throws Exception {
+		try {
+			this.catalogService.delete(metadata);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while performing deletion : " + e.getMessage(), e);
+			throw new Exception("Failed while performing deletion : " + e.getMessage(), e);
+		}	
+	}
+	
+	public List<String> getProperty(String key) throws Exception {
+		try {
+			return this.catalogService.getProperty(key);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting property '" + key + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while getting property '" + key + "' : " + e.getMessage(), e);
+		}	
+	}
+
+	public Properties getCalalogProperties() throws Exception {
+		try {
+			return this.catalogService.getCalalogProperties();
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting catalog properties : " + e.getMessage(), e);
+			throw new Exception("Failed while getting catalog properties : " + e.getMessage(), e);
+		}		
+	}
+	
+	public Properties getCalalogProperties(String catalogId) throws Exception {
+		try {
+			return this.catalogService.getCalalogProperties(catalogId);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting catalog properties for catalog '" + catalogId + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while getting catalog properties for catalog '" + catalogId + "' : " + e.getMessage(), e);
+		}	
+	}
+
+//	public Page getFirstPage(QueryExpression queryExpression) throws Exception {
+//		return this.catalogService.getFirstPage(queryExpression);
+//	}
+//
+//	public Page getFirstPage(QueryExpression queryExpression, Set<String> catalogIds) throws Exception {
+//		return this.catalogService.getFirstPage(queryExpression, catalogIds);
+//	}
+	
+	public Page getNextPage(Page page) throws Exception {
+		try {
+			return this.catalogService.getNextPage(page);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting next page : " + e.getMessage(), e);
+			throw new Exception("Failed while getting next page : " + e.getMessage(), e);
+		}	
+	}
+	
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression) throws Exception {
+		try {
+			return this.catalogService.getPage(pageInfo, queryExpression);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting next page [pageInfo='" + pageInfo + "',query='" + queryExpression + "'] : " + e.getMessage(), e);
+			throw new Exception("Failed while getting next page [pageInfo='" + pageInfo + "',query='" + queryExpression + "'] : " + e.getMessage(), e);
+		}
+	}
+	
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression, Set<String> catalogIds) throws Exception {
+		try {
+			return this.catalogService.getPage(pageInfo, queryExpression, catalogIds);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting next page [pageInfo='" + pageInfo + "',query='" + queryExpression + "',catalogIds='" + catalogIds + "'] : " + e.getMessage(), e);
+			throw new Exception("Failed while getting next page [pageInfo='" + pageInfo + "',query='" + queryExpression + "',catalogIds='" + catalogIds + "'] : " + e.getMessage(), e);
+		}
+	}
+	
+//	public Page getLastPage(QueryExpression queryExpression) throws Exception {
+//		return this.catalogService.getLastPage(queryExpression);
+//	}
+//	
+//	public Page getLastPage(QueryExpression queryExpression, Set<String> catalogIds) throws Exception {
+//		return this.catalogService.getLastPage(queryExpression, catalogIds);
+//	}
+	
+	public List<TransactionalMetadata> getMetadata(Page page) throws Exception {
+		try {
+			return this.catalogService.getMetadata(page);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting metadata for page : " + e.getMessage(), e);
+			throw new Exception("Failed while getting metadata for page : " + e.getMessage(), e);
+		}
+	}
+	
+	public QueryPager query(QueryExpression queryExpression) throws Exception {
+		try {
+			return this.catalogService.query(queryExpression);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while performing query '" + queryExpression + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while performing query '" + queryExpression + "' : " + e.getMessage(), e);
+		}
+	}
+	
+	public QueryPager query(QueryExpression queryExpression, Set<String> catalogIds) throws Exception {
+		try {
+			return this.catalogService.query(queryExpression, catalogIds);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while performing query '" + queryExpression + "' to catalogs '" + catalogIds + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while performing query '" + queryExpression + "' to catalogs '" + catalogIds + "' : " + e.getMessage(), e);
+		}
+	}
+	
+//	public QueryPager query(QueryExpression queryExpression, boolean sortResults) throws CatalogServiceException {
+//		return this.catalogService.query(queryExpression, sortResults);
+//	}
+ 
+	public List<TransactionalMetadata> getNextPage(QueryPager queryPager) throws Exception {
+		try {
+			return this.catalogService.getNextPage(queryPager);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while get next page from query pager : " + e.getMessage(), e);
+			throw new Exception("Failed while get next page from query pager : " + e.getMessage(), e);
+		}	
+	}
+
+//	public List<TransactionId<?>> getTransactionIdsForAllPages(QueryPager queryPager) throws CatalogServiceException {
+//		return this.catalogService.getTransactionIdsForAllPages(queryPager);
+//	}
+	
+	public List<TransactionalMetadata> getAllPages(QueryPager queryPager) throws Exception {
+		try {
+			return this.catalogService.getAllPages(queryPager);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while get all pages from query pager : " + e.getMessage(), e);
+			throw new Exception("Failed while get all pages from query pager : " + e.getMessage(), e);
+		}	
+	}
+	
+	public List<TransactionalMetadata> getMetadataFromTransactionIdStrings(List<String> catalogServiceTransactionIdStrings) throws Exception {
+		try {
+			return this.catalogService.getMetadataFromTransactionIdStrings(catalogServiceTransactionIdStrings);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting metadata for catalog service transaction ids '" + catalogServiceTransactionIdStrings + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while getting metadata for catalog service transaction ids '" + catalogServiceTransactionIdStrings + "' : " + e.getMessage(), e);
+		}	
+	}
+	
+	public List<TransactionalMetadata> getMetadataFromTransactionIds(List<TransactionId<?>> catalogServiceTransactionIds) throws Exception {
+		try {
+			return this.catalogService.getMetadataFromTransactionIds(catalogServiceTransactionIds);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting metadata for catalog service transaction ids '" + catalogServiceTransactionIds + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while getting metadata for catalog service transaction ids '" + catalogServiceTransactionIds + "' : " + e.getMessage(), e);
+		}	
+	}
+	
+	public List<TransactionId<?>> getCatalogServiceTransactionIds(List<TransactionId<?>> catalogTransactionIds, String catalogId) throws Exception {
+		try {
+			return this.catalogService.getCatalogServiceTransactionIds(catalogTransactionIds, catalogId);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting catalog service transaction ids for catalog transaction ids '" + catalogTransactionIds + "' from catalog '" + catalogId + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while getting catalog service transaction ids for catalog transaction ids '" + catalogTransactionIds + "' from catalog '" + catalogId + "' : " + e.getMessage(), e);
+		}	
+	}
+	
+	public TransactionId<?> getCatalogServiceTransactionId(TransactionId<?> catalogTransactionId, String catalogId) throws Exception {
+		try {
+			return this.catalogService.getCatalogServiceTransactionId(catalogTransactionId, catalogId);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting catalog service transaction id for catalog transaction id '" + catalogTransactionId + "' from catalog '" + catalogId + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while getting catalog service transaction id for catalog transaction id '" + catalogTransactionId + "' from catalog '" + catalogId + "' : " + e.getMessage(), e);
+		}		
+	}
+	
+	public TransactionId<?> getCatalogServiceTransactionId(CatalogReceipt catalogReceipt, boolean generateNew) throws Exception {
+		try {
+			return this.catalogService.getCatalogServiceTransactionId(catalogReceipt, generateNew);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed while getting metadata for catalog service transaction id for catalog receipt '" + catalogReceipt + "' with generate new equal '" + generateNew + "' : " + e.getMessage(), e);
+			throw new Exception("Failed while getting metadata for catalog service transaction id for catalog receipt '" + catalogReceipt + "' with generate new equal '" + generateNew + "' : " + e.getMessage(), e);
+		}		
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/CommunicationChannelClient.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/CommunicationChannelClient.java
new file mode 100644
index 0000000..cfd9b3b
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/CommunicationChannelClient.java
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel;
+
+//JDK imports
+import java.net.URL;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.Page;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.page.TransactionReceipt;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.struct.Dictionary;
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.util.PluginURL;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Communication Channel Interface
+ * <p>
+ */
+public interface CommunicationChannelClient {
+
+	public void shutdown() throws Exception;
+	
+	public boolean isRestrictQueryPermissions() throws Exception;
+
+//	public void setRestrictQueryPermissions(boolean restrictQueryPermissions) throws Exception;
+
+	public boolean isRestrictIngestPermissions() throws Exception;
+
+//	public void setHasIngestPermissions(boolean restrictIngestPermissions) throws Exception;
+
+//	public Class<? extends TransactionId<?>> getTransactionIdClass() throws Exception;
+//
+//	public void setTransactionIdClass(Class<? extends TransactionId<?>> transactionIdClass) throws Exception;
+//
+
+	public void addCatalog(Catalog catalog) throws Exception;
+
+	public void replaceCatalog(Catalog catalog) throws Exception;
+
+	public void addCatalog(String catalogId, Index index) throws Exception;
+	
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries) throws Exception;
+
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries, boolean restrictQueryPermission, boolean restrictIngestPermission) throws Exception;
+
+	public void addDictionary(String catalogId, Dictionary dictionary) throws Exception;
+
+	public void replaceDictionaries(String catalogId, List<Dictionary> dictionaries) throws Exception;
+
+	public void replaceIndex(String catalogId, Index index) throws Exception;
+
+	public void modifyIngestPermission(String catalogId, boolean restrictIngestPermission) throws Exception;
+	
+	public void modifyQueryPermission(String catalogId, boolean restrictQueryPermission) throws Exception;
+	
+	public void removeCatalog(String catalogUrn) throws Exception;
+
+//	public void removeCatalog(String catalogUrn, boolean preserveMapping) throws Exception;
+
+	public List<PluginURL> getPluginUrls() throws Exception;
+
+	public void addPluginUrls(List<PluginURL> pluginUrls) throws Exception;
+
+	public URL getPluginStorageDir() throws Exception;
+	
+	public void transferUrl(URL fromUrl, URL toUrl) throws Exception;
+	
+//	public Set<Catalog> getCurrentCatalogList() throws Exception;
+//	
+//	public Catalog getCatalog(String catalogUrn) throws Exception;
+
+	public Set<String> getCurrentCatalogIds() throws Exception;
+		
+	public TransactionReceipt ingest(Metadata metadata) throws Exception;
+	
+	public void delete(Metadata metadata) throws Exception;
+	
+	public List<String> getProperty(String key) throws Exception;
+
+	public Properties getCalalogProperties() throws Exception;
+	
+	public Properties getCalalogProperties(String catalogUrn) throws Exception;
+	
+//	public Page getFirstPage(QueryExpression queryExpression) throws Exception;
+//
+//	public Page getFirstPage(QueryExpression queryExpression, Set<String> catalogIds) throws Exception;
+	
+	public Page getNextPage(Page page) throws Exception;
+	
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression) throws Exception;
+	
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression, Set<String> catalogIds) throws Exception;
+	
+//	public Page getLastPage(QueryExpression queryExpression) throws Exception;
+//
+//	public Page getLastPage(QueryExpression queryExpression, Set<String> catalogIds) throws Exception;
+	
+	public List<TransactionalMetadata> getMetadata(Page page) throws Exception;
+
+	public QueryPager query(QueryExpression queryExpression) throws Exception;
+
+	public QueryPager query(QueryExpression queryExpression, Set<String> catalogIds) throws Exception;
+	
+//	public QueryPager query(QueryExpression queryExpression, boolean sortResults) throws Exception;
+ 
+	public List<TransactionalMetadata> getNextPage(QueryPager queryPager) throws Exception;
+
+	public List<TransactionId<?>> getTransactionIdsForAllPages(QueryPager queryPager) throws Exception;
+	
+	public List<TransactionalMetadata> getAllPages(QueryPager queryPager) throws Exception;
+	
+	public List<TransactionalMetadata> getMetadataFromTransactionIdStrings(List<String> catalogServiceTransactionIdStrings) throws Exception;
+	
+	public List<TransactionalMetadata> getMetadataFromTransactionIds(List<TransactionId<?>> catalogServiceTransactionIds) throws Exception;
+	
+	public List<TransactionId<?>> getCatalogServiceTransactionIds(List<TransactionId<?>> catalogTransactionIds, String catalogUrn) throws Exception;
+	
+	public TransactionId<?> getCatalogServiceTransactionId(TransactionId<?> catalogTransactionId, String catalogUrn) throws Exception;
+	
+	public TransactionId<?> getCatalogServiceTransactionId(CatalogReceipt catalogReceipt, boolean generateNew) throws Exception;
+	
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/CommunicationChannelClientFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/CommunicationChannelClientFactory.java
new file mode 100644
index 0000000..2bc3c58
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/CommunicationChannelClientFactory.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory for creating CommunicationChannelClient
+ * <p>
+ */
+public interface CommunicationChannelClientFactory {
+
+	public CommunicationChannelClient createCommunicationChannelClient();
+	
+	public void setServerUrl(String url);
+	
+	public String getServerUrl();
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/CommunicationChannelServer.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/CommunicationChannelServer.java
new file mode 100644
index 0000000..a486a58
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/CommunicationChannelServer.java
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel;
+
+//JDK imports
+import java.net.URL;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogServiceException;
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.Page;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.page.TransactionReceipt;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.struct.Dictionary;
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.system.CatalogService;
+import org.apache.oodt.cas.catalog.util.PluginURL;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Communication Channel Server
+ * <p>
+ */
+public interface CommunicationChannelServer {
+
+	public void setCatalogService(CatalogService catalogService) throws Exception;
+	
+	public void setPort(int port) throws Exception;
+
+	public int getPort();
+	
+	public void startup() throws Exception;
+
+	public void shutdown() throws Exception;
+
+	public boolean isRestrictQueryPermissions() throws Exception;
+//
+//	public void setRestrictQueryPermissions(boolean restrictQueryPermissions) throws Exception;
+//
+	public boolean isRestrictIngestPermissions() throws Exception;
+//
+//	public void setHasIngestPermissions(boolean restrictIngestPermissions) throws Exception;
+
+//	public Class<? extends TransactionId<?>> getTransactionIdClass() throws Exception;
+//
+//	public void setTransactionIdClass(Class<? extends TransactionId<?>> transactionIdClass) throws Exception;
+//	
+	public void addCatalog(Catalog catalog) throws Exception;
+
+	public void replaceCatalog(Catalog catalog) throws Exception;
+	
+	public void addCatalog(String catalogId, Index index) throws Exception;
+	
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries) throws Exception;
+
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries, boolean restrictQueryPermission, boolean restrictIngestPermission) throws Exception;
+
+	public void addDictionary(String catalogId, Dictionary dictionary) throws Exception;
+
+	public void replaceDictionaries(String catalogId, List<Dictionary> dictionaries) throws Exception;
+	
+	public void replaceIndex(String catalogId, Index index) throws Exception;
+
+	public void modifyIngestPermission(String catalogId, boolean restrictIngestPermission) throws Exception;
+	
+	public void modifyQueryPermission(String catalogId, boolean restrictQueryPermission) throws Exception;
+		
+	public void removeCatalog(String catalogUrn) throws Exception;
+	
+//	public void removeCatalog(String catalogUrn, boolean preserveMapping) throws Exception;
+
+	public List<PluginURL> getPluginUrls() throws Exception;
+	
+	public void addPluginUrls(List<PluginURL> pluginURLs) throws Exception;
+	
+	public URL getPluginStorageDir() throws Exception;
+	
+//	public Set<Catalog> getCurrentCatalogList() throws Exception;
+//	
+//	public Catalog getCatalog(String catalogUrn) throws Exception;
+
+	public Set<String> getCurrentCatalogIds() throws Exception;
+		
+	public TransactionReceipt ingest(Metadata metadata) throws Exception;
+	
+	public void delete(Metadata metadata) throws Exception;
+	
+	public List<String> getProperty(String key) throws Exception;
+
+	public Properties getCalalogProperties() throws Exception;
+	
+	public Properties getCalalogProperties(String catalogUrn) throws Exception;
+	
+//	public Page getFirstPage(QueryExpression queryExpression) throws Exception;
+//
+//	public Page getFirstPage(QueryExpression queryExpression, Set<String> catalogIds) throws Exception;
+	
+	public Page getNextPage(Page page) throws Exception;
+	
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression) throws Exception;
+	
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression, Set<String> catalogIds) throws Exception;
+	
+//	public Page getLastPage(QueryExpression queryExpression) throws Exception;
+//
+//	public Page getLastPage(QueryExpression queryExpression, Set<String> catalogIds) throws Exception;
+	
+	public List<TransactionalMetadata> getMetadata(Page page) throws Exception;
+	
+	public QueryPager query(QueryExpression queryExpression) throws Exception;
+
+	public QueryPager query(QueryExpression queryExpression, Set<String> catalogIds) throws Exception;
+
+//	public QueryPager query(QueryExpression queryExpression, boolean sortResults) throws Exception;
+ 
+	public List<TransactionalMetadata> getNextPage(QueryPager queryPager) throws Exception;
+
+//	public List<TransactionId<?>> getTransactionIdsForAllPages(QueryPager queryPager) throws Exception;
+	
+	public List<TransactionalMetadata> getAllPages(QueryPager queryPager) throws Exception;
+	
+	public List<TransactionalMetadata> getMetadataFromTransactionIdStrings(List<String> catalogServiceTransactionIdStrings) throws Exception;
+	
+	public List<TransactionalMetadata> getMetadataFromTransactionIds(List<TransactionId<?>> catalogServiceTransactionIds) throws Exception;
+	
+	public List<TransactionId<?>> getCatalogServiceTransactionIds(List<TransactionId<?>> catalogTransactionIds, String catalogUrn) throws Exception;
+	
+	public TransactionId<?> getCatalogServiceTransactionId(TransactionId<?> catalogTransactionId, String catalogUrn) throws Exception;
+	
+	public TransactionId<?> getCatalogServiceTransactionId(CatalogReceipt catalogReceipt, boolean generateNew) throws Exception;
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/CommunicationChannelServerFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/CommunicationChannelServerFactory.java
new file mode 100644
index 0000000..8f74fe9
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/CommunicationChannelServerFactory.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.system.CatalogServiceFactory;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory for creating CommunicationChannelServer
+ * <p>
+ */
+public interface CommunicationChannelServerFactory {
+	
+	public CommunicationChannelServer createCommunicationChannelServer();
+	
+	public void setPort(int port);
+	
+	public int getPort();
+	
+	public void setCatalogServiceFactory(CatalogServiceFactory catalogServiceFactory);
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/rmi/RmiCommunicationChannelClient.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/rmi/RmiCommunicationChannelClient.java
new file mode 100644
index 0000000..43c1b90
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/rmi/RmiCommunicationChannelClient.java
@@ -0,0 +1,269 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel.rmi;
+
+//JDK imports
+import java.net.URL;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.Page;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.page.TransactionReceipt;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.server.channel.CommunicationChannelClient;
+import org.apache.oodt.cas.catalog.struct.Dictionary;
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.util.PluginURL;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class RmiCommunicationChannelClient extends UnicastRemoteObject implements CommunicationChannelClient{
+
+	private static final long serialVersionUID = 4618051069367331679L;
+
+	protected RmiCommunicationChannelClient() throws RemoteException {
+		super();
+	}
+
+	public void addCatalog(Catalog catalog) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void addCatalog(String catalogId, Index index) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void addCatalog(String catalogId, Index index,
+			List<Dictionary> dictionaries) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void addCatalog(String catalogId, Index index,
+			List<Dictionary> dictionaries, boolean restrictQueryPermission,
+			boolean restrictIngestPermission) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void addDictionary(String catalogId, Dictionary dictionary)
+			throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void addPluginUrls(List<PluginURL> pluginUrls) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void delete(Metadata metadata) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public List<TransactionalMetadata> getAllPages(QueryPager queryPager)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Properties getCalalogProperties() throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Properties getCalalogProperties(String catalogUrn) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public TransactionId<?> getCatalogServiceTransactionId(
+			TransactionId<?> catalogTransactionId, String catalogUrn)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public TransactionId<?> getCatalogServiceTransactionId(
+			CatalogReceipt catalogReceipt, boolean generateNew)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<TransactionId<?>> getCatalogServiceTransactionIds(
+			List<TransactionId<?>> catalogTransactionIds, String catalogUrn)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Set<String> getCurrentCatalogIds() throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<TransactionalMetadata> getMetadata(Page page) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<TransactionalMetadata> getMetadataFromTransactionIdStrings(
+			List<String> catalogServiceTransactionIdStrings) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<TransactionalMetadata> getMetadataFromTransactionIds(
+			List<TransactionId<?>> catalogServiceTransactionIds)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Page getNextPage(Page page) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<TransactionalMetadata> getNextPage(QueryPager queryPager)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression,
+			Set<String> catalogIds) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public URL getPluginStorageDir() throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<PluginURL> getPluginUrls() throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<String> getProperty(String key) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<TransactionId<?>> getTransactionIdsForAllPages(
+			QueryPager queryPager) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public TransactionReceipt ingest(Metadata metadata) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public boolean isRestrictIngestPermissions() throws Exception {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	public boolean isRestrictQueryPermissions() throws Exception {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	public void modifyIngestPermission(String catalogId,
+			boolean restrictIngestPermission) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void modifyQueryPermission(String catalogId,
+			boolean restrictQueryPermission) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public QueryPager query(QueryExpression queryExpression) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public QueryPager query(QueryExpression queryExpression,
+			Set<String> catalogIds) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public void removeCatalog(String catalogUrn) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void replaceCatalog(Catalog catalog) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void replaceDictionaries(String catalogId,
+			List<Dictionary> dictionaries) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void replaceIndex(String catalogId, Index index) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void shutdown() throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void transferUrl(URL fromUrl, URL toUrl) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/rmi/RmiCommunicationChannelClientInterface.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/rmi/RmiCommunicationChannelClientInterface.java
new file mode 100644
index 0000000..1bd14ed
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/rmi/RmiCommunicationChannelClientInterface.java
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel.rmi;
+
+//JDK imports
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.mapping.IngestMapper;
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.repository.CatalogRepository;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public interface RmiCommunicationChannelClientInterface extends Remote {
+	
+	public void setCatalogRepository(CatalogRepository catalogRepository);
+	
+	public CatalogRepository getCatalogRepository() throws Exception;
+	
+	public IngestMapper getIngestMapper() throws RemoteException;
+
+	public void setIngestMapper(IngestMapper ingestMapper) throws RemoteException;
+
+	public boolean isRestrictQueryPermissions() throws RemoteException;
+
+	public void setRestrictQueryPermissions(boolean restrictQueryPermissions) throws RemoteException;
+
+	public boolean isHasIngestPermissions() throws RemoteException;
+
+	public void setHasIngestPermissions(boolean restrictIngestPermissions) throws RemoteException;
+
+	public Class<? extends TransactionId<?>> getTransactionIdClass() throws RemoteException;
+
+	public void setTransactionIdClass(Class<? extends TransactionId<?>> transactionIdClass) throws RemoteException;
+
+	public void addCatalog(Catalog catalog) throws RemoteException;
+	
+	public void addCatalog(Catalog catalog, boolean allowOverride) throws RemoteException;
+	
+	public void removeCatalog(String catalogUrn) throws RemoteException;
+
+	public void removeCatalog(String catalogUrn, boolean preserveMapping) throws RemoteException;
+
+	public Set<Catalog> getCurrentCatalogList() throws RemoteException;
+	
+	public Catalog getCatalog(String catalogUrn) throws RemoteException;
+
+	public Set<String> getCurrentCatalogIds() throws RemoteException;
+		
+	public TransactionId<?> ingest(Metadata metadata) throws RemoteException;
+	
+	public void delete(Metadata metadata) throws RemoteException;
+	
+	public List<String> getProperty(String key) throws RemoteException;
+
+	public Properties getCalalogProperties() throws RemoteException;
+	
+	public Properties getCalalogProperties(String catalogUrn) throws RemoteException;
+	
+	public QueryPager query(QueryExpression queryExpression) throws RemoteException;
+	
+	public QueryPager query(QueryExpression queryExpression, boolean sortResults) throws RemoteException;
+ 
+	public Set<TransactionalMetadata> getNextPage(QueryPager queryPager) throws RemoteException;
+
+	public Set<TransactionId<?>> getTransactionIdsForAllPages(QueryPager queryPager) throws RemoteException;
+	
+	public Set<TransactionalMetadata> getAllPages(QueryPager queryPager) throws RemoteException;
+	
+	public Set<TransactionalMetadata> getMetadataFromTransactionIdStrings(List<String> catalogServiceTransactionIdStrings) throws RemoteException;
+	
+	public Set<TransactionalMetadata> getMetadataFromTransactionIds(List<TransactionId<?>> catalogServiceTransactionIds) throws RemoteException;
+	
+	public Set<TransactionId<?>> getCatalogServiceTransactionIds(List<TransactionId<?>> catalogTransactionIds, String catalogUrn) throws RemoteException;
+	
+	public TransactionId<?> getCatalogServiceTransactionId(TransactionId<?> catalogTransactionId, String catalogUrn) throws RemoteException;
+	
+	public TransactionId<?> getCatalogServiceTransactionId(TransactionId<?> catalogTransactionId, String catalogUrn, boolean generateNew) throws RemoteException;
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/rmi/RmiCommunicationChannelClientMBean.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/rmi/RmiCommunicationChannelClientMBean.java
new file mode 100644
index 0000000..9c25ab7
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/rmi/RmiCommunicationChannelClientMBean.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel.rmi;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public interface RmiCommunicationChannelClientMBean {
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/rmi/RmiCommunicationChannelServer.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/rmi/RmiCommunicationChannelServer.java
new file mode 100644
index 0000000..32a0610
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/rmi/RmiCommunicationChannelServer.java
@@ -0,0 +1,277 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel.rmi;
+
+//JDK imports
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.Page;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.page.TransactionReceipt;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.server.channel.CommunicationChannelServer;
+import org.apache.oodt.cas.catalog.struct.Dictionary;
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.system.CatalogService;
+import org.apache.oodt.cas.catalog.util.PluginURL;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class RmiCommunicationChannelServer implements
+		CommunicationChannelServer {
+
+	public void shutdown() throws IOException {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void startup()
+			throws IOException {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void addCatalog(Catalog catalog) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void addCatalog(String catalogId, Index index) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void addCatalog(String catalogId, Index index,
+			List<Dictionary> dictionaries) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void addCatalog(String catalogId, Index index,
+			List<Dictionary> dictionaries, boolean restrictQueryPermission,
+			boolean restrictIngestPermission) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void addDictionary(String catalogId, Dictionary dictionary)
+			throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void addPluginUrls(List<PluginURL> pluginURLs) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void delete(Metadata metadata) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public List<TransactionalMetadata> getAllPages(QueryPager queryPager)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Properties getCalalogProperties() throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Properties getCalalogProperties(String catalogUrn) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public TransactionId<?> getCatalogServiceTransactionId(
+			TransactionId<?> catalogTransactionId, String catalogUrn)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public TransactionId<?> getCatalogServiceTransactionId(
+			CatalogReceipt catalogReceipt, boolean generateNew)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<TransactionId<?>> getCatalogServiceTransactionIds(
+			List<TransactionId<?>> catalogTransactionIds, String catalogUrn)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Set<String> getCurrentCatalogIds() throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<TransactionalMetadata> getMetadata(Page page) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<TransactionalMetadata> getMetadataFromTransactionIdStrings(
+			List<String> catalogServiceTransactionIdStrings) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<TransactionalMetadata> getMetadataFromTransactionIds(
+			List<TransactionId<?>> catalogServiceTransactionIds)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Page getNextPage(Page page) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<TransactionalMetadata> getNextPage(QueryPager queryPager)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression,
+			Set<String> catalogIds) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public URL getPluginStorageDir() throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<PluginURL> getPluginUrls() throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public int getPort() {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	public List<String> getProperty(String key) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public TransactionReceipt ingest(Metadata metadata) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public boolean isRestrictIngestPermissions() throws Exception {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	public boolean isRestrictQueryPermissions() throws Exception {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	public void modifyIngestPermission(String catalogId,
+			boolean restrictIngestPermission) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void modifyQueryPermission(String catalogId,
+			boolean restrictQueryPermission) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public QueryPager query(QueryExpression queryExpression) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public QueryPager query(QueryExpression queryExpression,
+			Set<String> catalogIds) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public void removeCatalog(String catalogUrn) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void replaceCatalog(Catalog catalog) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void replaceDictionaries(String catalogId,
+			List<Dictionary> dictionaries) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void replaceIndex(String catalogId, Index index) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void setCatalogService(CatalogService catalogService)
+			throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void setPort(int port) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/xmlrpc/XmlRpcCommunicationChannelClient.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/xmlrpc/XmlRpcCommunicationChannelClient.java
new file mode 100644
index 0000000..466ee60
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/xmlrpc/XmlRpcCommunicationChannelClient.java
@@ -0,0 +1,442 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel.xmlrpc;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.Page;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.page.TransactionReceipt;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.server.channel.AbstractCommunicationChannelClient;
+import org.apache.oodt.cas.catalog.struct.Dictionary;
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.util.PluginURL;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//APACHE imports
+import org.apache.xmlrpc.CommonsXmlRpcTransportFactory;
+import org.apache.xmlrpc.XmlRpcClient;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Communication Channel Client over XML-RPC
+ * <p>
+ */
+public class XmlRpcCommunicationChannelClient extends AbstractCommunicationChannelClient {
+
+	protected XmlRpcClient client;
+	protected int chunkSize;
+	
+	public XmlRpcCommunicationChannelClient(URL serverUrl, int connectionTimeout, int requestTimeout, int chunkSize) {
+		super();
+        CommonsXmlRpcTransportFactory transportFactory = new CommonsXmlRpcTransportFactory(serverUrl);
+        transportFactory.setConnectionTimeout(connectionTimeout * 60 * 1000);
+        transportFactory.setTimeout(requestTimeout * 60 * 1000);        
+		this.client = new XmlRpcClient(serverUrl, transportFactory);
+		this.chunkSize = chunkSize;
+	}
+	
+	public void shutdown() throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_shutdown", args);
+	}
+
+	public void addCatalog(Catalog catalog) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(catalog));
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_addCatalog", args);
+	}
+	
+	public void replaceCatalog(Catalog catalog) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(catalog));
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_replaceCatalog", args);	
+	}
+	
+	public void addCatalog(String catalogId, Index index) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(catalogId);
+		args.add(this.serializer.serializeObject(index));
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_addCatalog", args);
+	}
+	
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(catalogId);
+		args.add(this.serializer.serializeObject(index));
+		args.add(this.serializer.serializeObject(dictionaries));
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_addCatalog", args);
+	}
+
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries, boolean restrictQueryPermission, boolean restrictIngestPermission) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(catalogId);
+		args.add(this.serializer.serializeObject(index));
+		args.add(this.serializer.serializeObject(dictionaries));
+		args.add(restrictQueryPermission);
+		args.add(restrictIngestPermission);
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_addCatalog", args);
+	}
+
+	public void addDictionary(String catalogId, Dictionary dictionary) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(catalogId);
+		args.add(this.serializer.serializeObject(dictionary));
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_addDictionary", args);
+	}
+	
+	public void replaceDictionaries(String catalogId, List<Dictionary> dictionaries) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(catalogId);
+		args.add(this.serializer.serializeObject(dictionaries));
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_addDictionary", args);
+	}
+
+	public void replaceIndex(String catalogId, Index index) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(catalogId);
+		args.add(this.serializer.serializeObject(index));
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_replaceIndex", args);
+	}
+
+	public void modifyIngestPermission(String catalogId, boolean restrictIngestPermission) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(catalogId);
+		args.add(this.serializer.serializeObject(restrictIngestPermission));
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_modifyIngestPermission", args);
+	}
+	
+	public void modifyQueryPermission(String catalogId, boolean restrictQueryPermission) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(catalogId);
+		args.add(this.serializer.serializeObject(restrictQueryPermission));
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_modifyQueryPermission", args);
+	}
+	
+	public List<PluginURL> getPluginUrls() throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		return this.serializer.deserializeObject(List.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getPluginUrls", args));
+	}
+	
+	public void addPluginUrls(List<PluginURL> pluginURLs) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(pluginURLs));
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_addPluginUrls", args);
+	}
+	
+	public URL getPluginStorageDir() throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		return this.serializer.deserializeObject(URL.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getPluginStorageDir", args));	
+	}
+	
+	public void transferUrl(URL fromUrl, URL toURL) throws Exception {
+		System.out.println("Transfering '" + fromUrl + "' to '" + toURL + "'");
+        FileInputStream is = null;
+        try {
+            byte[] buf = new byte[this.chunkSize];
+	        is = new FileInputStream(new File(fromUrl.getPath()));
+            int offset = 0;
+            int numBytes = 0;
+	        while ((numBytes = is.read(buf, offset, chunkSize)) != -1)
+	            this.transferFile(new File(toURL.getPath()).getAbsolutePath(), buf, offset, numBytes);
+        }catch (Exception e) {
+        	throw e;
+        }finally {
+        	try {
+        		is.close();
+        	}catch(Exception e) {}
+        }
+	}
+	
+    protected void transferFile(String filePath, byte[] fileData, int offset,
+            int numBytes) throws Exception {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(filePath);
+        argList.add(fileData);
+        argList.add(new Integer(offset));
+        argList.add(new Integer(numBytes));
+        client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_transferFile", argList);
+    }
+
+	public void delete(Metadata metadata) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(metadata));
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_delete", args);		
+	}
+
+	public List<TransactionalMetadata> getAllPages(QueryPager queryPager) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(queryPager));
+		return this.serializer.deserializeObject(List.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getAllPages", args));
+	}
+
+	public Properties getCalalogProperties() throws Exception {
+		return this.serializer.deserializeObject(Properties.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getCalalogProperties", new Vector<Object>()));
+	}
+
+	public Properties getCalalogProperties(String catalogUrn)
+			throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(catalogUrn);
+		return this.serializer.deserializeObject(Properties.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getCalalogProperties", args));
+	}
+
+//	public Catalog getCatalog(String catalogUrn) throws Exception {
+//		Vector<Object> args = new Vector<Object>();
+//		args.add(catalogUrn);
+//		return this.serializer.deserializeObject(Catalog.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getCatalog", args));
+//	}
+
+//	public CatalogRepository getCatalogRepository()
+//			throws Exception {
+//		return this.serializer.deserializeObject(CatalogRepository.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getCatalogRepository", new Vector<Object>()));
+//	}
+
+	public TransactionId<?> getCatalogServiceTransactionId(
+			TransactionId<?> catalogTransactionId, String catalogUrn)
+			throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(catalogTransactionId));
+		args.add(catalogUrn);
+		return this.serializer.deserializeObject(TransactionId.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getCatalogServiceTransactionId", args));
+	}
+
+	public TransactionId<?> getCatalogServiceTransactionId(
+			CatalogReceipt catalogReceipt,
+			boolean generateNew) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(catalogReceipt));
+		args.add(this.serializer.serializeObject(new Boolean(generateNew)));
+		return this.serializer.deserializeObject(TransactionId.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getCatalogServiceTransactionId2", args));
+	}
+
+	public List<TransactionId<?>> getCatalogServiceTransactionIds(
+			List<TransactionId<?>> catalogTransactionIds, String catalogUrn)
+			throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(catalogTransactionIds));
+		args.add(catalogUrn);
+		return this.serializer.deserializeObject(List.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getCatalogServiceTransactionId", args));
+	}
+
+	public Set<String> getCurrentCatalogIds() throws Exception {
+		return this.serializer.deserializeObject(Set.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getCurrentCatalogIds", new Vector<Object>()));
+	}
+
+//	public Set<Catalog> getCurrentCatalogList() throws Exception {
+//		return this.serializer.deserializeObject(Set.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getCurrentCatalogList", new Vector<Object>()));
+//	}
+//
+//	public IngestMapper getIngestMapper() throws Exception { 
+//		return this.serializer.deserializeObject(IngestMapper.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getIngestMapper", new Vector<Object>()));
+//	}
+
+	public List<TransactionalMetadata> getMetadataFromTransactionIdStrings(
+			List<String> catalogServiceTransactionIdStrings)
+			throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(catalogServiceTransactionIdStrings));
+		return this.serializer.deserializeObject(List.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getMetadataFromTransactionIdStrings", args));
+	}
+
+	public List<TransactionalMetadata> getMetadataFromTransactionIds(
+			List<TransactionId<?>> catalogServiceTransactionIds)
+			throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(catalogServiceTransactionIds));
+		return this.serializer.deserializeObject(List.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getMetadataFromTransactionIds", args));
+	}
+
+	public List<TransactionalMetadata> getNextPage(QueryPager queryPager)
+			throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(queryPager));
+		return this.serializer.deserializeObject(List.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getNextPage", args));
+	}
+
+	public List<String> getProperty(String key) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(key);
+		return this.serializer.deserializeObject(List.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getProperty", args));
+	}
+
+	public Class<? extends TransactionId<?>> getTransactionIdClass() throws Exception {
+		return this.serializer.deserializeObject(Class.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getTransactionIdClass", new Vector<Object>()));
+	}
+
+	public List<TransactionId<?>> getTransactionIdsForAllPages(
+			QueryPager queryPager) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(queryPager));
+		return this.serializer.deserializeObject(List.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getTransactionIdsForAllPages", args));
+	}
+
+	public TransactionReceipt ingest(Metadata metadata)
+			throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(metadata));
+		return this.serializer.deserializeObject(TransactionReceipt.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_ingest", args));
+	}
+
+	public boolean isRestrictIngestPermissions() throws Exception {
+		return this.serializer.deserializeObject(Boolean.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_isRestrictIngestPermissions", new Vector<Object>()));
+	}
+
+	public boolean isRestrictQueryPermissions() throws Exception {
+		return this.serializer.deserializeObject(Boolean.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_isRestrictQueryPermissions", new Vector<Object>()));
+	}
+
+	public Page getFirstPage(QueryExpression queryExpression) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(queryExpression));
+		return this.serializer.deserializeObject(Page.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getFirstPage", args));
+	}
+
+	public Page getFirstPage(QueryExpression queryExpression, Set<String> catalogIds) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(queryExpression));
+		args.add(this.serializer.serializeObject(catalogIds));
+		return this.serializer.deserializeObject(Page.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getFirstPage", args));
+	}
+	
+	public Page getNextPage(Page page) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(page));
+		return this.serializer.deserializeObject(Page.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getNextPage2", args));
+	}
+	
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(pageInfo));
+		args.add(this.serializer.serializeObject(queryExpression));
+		return this.serializer.deserializeObject(Page.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getPage", args));
+	}
+	
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression, Set<String> catalogIds) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(pageInfo));
+		args.add(this.serializer.serializeObject(queryExpression));
+		args.add(this.serializer.serializeObject(catalogIds));
+		return this.serializer.deserializeObject(Page.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getPage", args));
+	}
+	
+	public Page getLastPage(QueryExpression queryExpression) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(queryExpression));
+		return this.serializer.deserializeObject(Page.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getLastPage", args));
+	}
+
+	public Page getLastPage(QueryExpression queryExpression, Set<String> catalogIds) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(queryExpression));
+		args.add(this.serializer.serializeObject(catalogIds));
+		return this.serializer.deserializeObject(Page.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getLastPage", args));
+	}
+	
+	public List<TransactionalMetadata> getMetadata(Page page) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(page));
+		return this.serializer.deserializeObject(List.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_getMetadata", args));
+	}
+	
+	public QueryPager query(QueryExpression queryExpression)
+			throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(queryExpression));
+		return this.serializer.deserializeObject(QueryPager.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_query", args));
+	}
+
+	public QueryPager query(QueryExpression queryExpression, Set<String> catalogIds) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(this.serializer.serializeObject(queryExpression));
+		args.add(this.serializer.serializeObject(catalogIds));
+		return this.serializer.deserializeObject(QueryPager.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_query", args));
+	}
+	
+//	public QueryPager query(QueryExpression queryExpression, boolean sortResults)
+//			throws Exception {
+//		Vector<Object> args = new Vector<Object>();
+//		args.add(this.serializer.serializeObject(queryExpression));
+//		args.add(this.serializer.serializeObject(new Boolean(sortResults)));
+//		return this.serializer.deserializeObject(QueryPager.class, (String) this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_query", args));
+//	}
+
+	public void removeCatalog(String catalogUrn) throws Exception {
+		Vector<Object> args = new Vector<Object>();
+		args.add(catalogUrn);
+		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_removeCatalog", args);		
+	}
+
+//	public void removeCatalog(String catalogUrn, boolean preserveMapping)
+//			throws Exception {
+//		Vector<Object> args = new Vector<Object>();
+//		args.add(catalogUrn);
+//		args.add(this.serializer.serializeObject(new Boolean(preserveMapping)));
+//		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_removeCatalog", args);		
+//	}
+
+//	public void setCatalogRepository(CatalogRepository catalogRepository)
+//			throws Exception {
+//		Vector<Object> args = new Vector<Object>();
+//		args.add(this.serializer.serializeObject(catalogRepository));
+//		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_setCatalogRepository", args);
+//	}
+
+//	public void setHasIngestPermissions(boolean restrictIngestPermissions) throws Exception {
+//		Vector<Object> args = new Vector<Object>();
+//		args.add(this.serializer.serializeObject(new Boolean(restrictIngestPermissions)));
+//		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_setHasIngestPermissions", args);		
+//	}
+
+//	public void setIngestMapper(IngestMapper ingestMapper) throws Exception {
+//		Vector<Object> args = new Vector<Object>();
+//		args.add(this.serializer.serializeObject(ingestMapper));
+//		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_setIngestMapper", args);		
+//	}
+
+//	public void setRestrictQueryPermissions(boolean restrictQueryPermissions) throws Exception {
+//		Vector<Object> args = new Vector<Object>();
+//		args.add(this.serializer.serializeObject(new Boolean(restrictQueryPermissions)));
+//		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_setRestrictQueryPermissions", args);			
+//	}
+
+//	public void setTransactionIdClass(
+//			Class<? extends TransactionId<?>> transactionIdClass) throws Exception {
+//		Vector<Object> args = new Vector<Object>();
+//		args.add(this.serializer.serializeObject(transactionIdClass));
+//		this.client.execute(XmlRpcCommunicationChannelServer.class.getSimpleName() + ".xmlrpc_setTransactionIdClass", args);		
+//	}
+
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/xmlrpc/XmlRpcCommunicationChannelClientFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/xmlrpc/XmlRpcCommunicationChannelClientFactory.java
new file mode 100644
index 0000000..fb01ac0
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/xmlrpc/XmlRpcCommunicationChannelClientFactory.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel.xmlrpc;
+
+//JDK imports
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.server.channel.CommunicationChannelClient;
+import org.apache.oodt.cas.catalog.server.channel.CommunicationChannelClientFactory;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+//OODT imports
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory for creating XmlRpcCommunicationChannelServer
+ * <p>
+ */
+public class XmlRpcCommunicationChannelClientFactory implements
+		CommunicationChannelClientFactory {
+	
+	private static Logger LOG = Logger.getLogger(XmlRpcCommunicationChannelClientFactory.class.getName());
+	
+	protected String serverUrl;
+	protected int connectionTimeout;
+	protected int requestTimeout;
+	protected int chunkSize;
+	
+	public XmlRpcCommunicationChannelClientFactory() {}
+	
+	public CommunicationChannelClient createCommunicationChannelClient() {
+		try {
+			return new XmlRpcCommunicationChannelClient(new URL(this.serverUrl), this.connectionTimeout, this.requestTimeout, this.chunkSize);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed to create XmlRpcCommunicationChannelClient : " + e.getMessage(), e);
+			return null;
+		}
+	}
+	
+	@Required
+	public void setServerUrl(String serverUrl) {
+		this.serverUrl = serverUrl;
+	}
+	
+	public String getServerUrl() {
+		return this.serverUrl;
+	}
+	
+	/**
+	 * @param connectionTimeout timeout for client in minutes
+	 */
+	@Required
+	public void setConnectionTimeout(int connectionTimeout) {
+		this.connectionTimeout = connectionTimeout;
+	}
+	
+	/**
+	 * 
+	 * @param requestTimeout timout for client in minutes
+	 */
+	@Required
+	public void setRequestTimeout(int requestTimeout) {
+		this.requestTimeout = requestTimeout;
+	}
+	
+	@Required
+	public void setChunkSize(int chunkSize) {
+		this.chunkSize = chunkSize;
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/xmlrpc/XmlRpcCommunicationChannelServer.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/xmlrpc/XmlRpcCommunicationChannelServer.java
new file mode 100644
index 0000000..07b2ca2
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/xmlrpc/XmlRpcCommunicationChannelServer.java
@@ -0,0 +1,316 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel.xmlrpc;
+
+//JDK imports
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.List;
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.Page;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.server.channel.AbstractCommunicationChannelServer;
+import org.apache.oodt.cas.catalog.struct.Dictionary;
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//APACHE imports
+import org.apache.xmlrpc.WebServer;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Communication Channel Server over XML-RPC
+ * <p>
+ */
+public class XmlRpcCommunicationChannelServer extends
+		AbstractCommunicationChannelServer {
+
+	private WebServer webServer;
+	
+	public XmlRpcCommunicationChannelServer() {
+		super();
+	}
+	
+	public void startup() throws Exception {
+		this.webServer = new WebServer(this.port);
+		this.webServer.addHandler(this.getClass().getSimpleName(), this);
+		this.webServer.start();
+	}
+	
+	public boolean xmlrpc_shutdown() throws Exception {
+		this.shutdown();
+		this.webServer.shutdown();
+		this.webServer = null;
+		return true;
+	}
+	
+	public boolean xmlrpc_addCatalog(String catalogObject) throws Exception {
+		this.addCatalog(this.serializer.deserializeObject(Catalog.class, catalogObject));
+		return true;
+	}
+	
+	public boolean xmlrpc_replaceCatalog(String catalogObject) throws Exception {
+		this.replaceCatalog(this.serializer.deserializeObject(Catalog.class, catalogObject));
+		return true;
+	}
+	
+	public boolean xmlrpc_addCatalog(String catalogId, String indexObject) throws Exception {
+		this.addCatalog(catalogId, this.serializer.deserializeObject(Index.class, indexObject));
+		return true;
+	}
+	
+	public boolean xmlrpc_addCatalog(String catalogId, String indexObject, String dictionariesObject) throws Exception {
+		this.addCatalog(catalogId, this.serializer.deserializeObject(Index.class, indexObject), this.serializer.deserializeObject(List.class, dictionariesObject));
+		return true;
+	}
+
+	public boolean xmlrpc_addCatalog(String catalogId, String indexObject, String dictionariesObject, String restrictQueryPermissionObject, String restrictIngestPermissionObject) throws Exception {
+		this.addCatalog(catalogId, this.serializer.deserializeObject(Index.class, indexObject), this.serializer.deserializeObject(List.class, dictionariesObject), this.serializer.deserializeObject(Boolean.class, restrictQueryPermissionObject), this.serializer.deserializeObject(Boolean.class, restrictIngestPermissionObject));
+		return true;
+	}
+
+	public boolean xmlrpc_addDictionary(String catalogId, String dictionaryObject) throws Exception {
+		this.addDictionary(catalogId, this.serializer.deserializeObject(Dictionary.class, dictionaryObject));
+		return true;
+	}
+	
+	public boolean xmlrpc_replaceDictionaries(String catalogId, String dictionariesObject) throws Exception {
+		this.replaceDictionaries(catalogId, this.serializer.deserializeObject(List.class, dictionariesObject));
+		return true;
+	}
+
+	public boolean xmlrpc_replaceIndex(String catalogId, String indexObject) throws Exception {
+		this.replaceIndex(catalogId, this.serializer.deserializeObject(Index.class, indexObject));
+		return true;
+	}
+
+	public boolean xmlrpc_modifyIngestPermission(String catalogId, String restrictIngestPermissionObject) throws Exception {
+		this.modifyIngestPermission(catalogId, this.serializer.deserializeObject(Boolean.class, restrictIngestPermissionObject));
+		return true;
+	}
+	
+	public boolean xmlrpc_modifyQueryPermission(String catalogId, String restrictQueryPermissionObject) throws Exception {
+		this.modifyIngestPermission(catalogId, this.serializer.deserializeObject(Boolean.class, restrictQueryPermissionObject));
+		return true;
+	}
+	
+	public boolean xmlrpc_delete(String metadataObject) throws Exception {
+		this.delete(this.serializer.deserializeObject(Metadata.class, metadataObject));	
+		return true;
+	}
+	
+	public String xmlrpc_getPluginUrls() throws Exception {
+		return this.serializer.serializeObject(this.getPluginUrls());
+	}
+	
+	public boolean xmlrpc_addPluginUrls(String pluginUrlsObject) throws Exception {
+		this.addPluginUrls(this.serializer.deserializeObject(List.class, pluginUrlsObject));
+		return true;
+	}
+	
+	public String xmlrpc_getPluginStorageDir() throws Exception {
+		return this.serializer.serializeObject(this.getPluginStorageDir());
+	}
+	
+    public boolean xmlrpc_transferFile(String filePath, byte[] fileData, int offset, int numBytes) throws Exception {
+        FileOutputStream fOut = null;
+        try {
+            File outFile = new File(filePath);
+	        if (outFile.exists()) 
+	        	fOut = new FileOutputStream(outFile, true);
+	        else 
+	        	fOut = new FileOutputStream(outFile, false);
+	
+	        fOut.write(fileData, (int) offset, (int) numBytes);
+        }catch (Exception e) {
+        	throw e;
+        }finally {
+        	try {
+        		fOut.close();
+        	}catch(Exception e) {}
+        }
+        return true;
+    }
+
+	public String xmlrpc_getAllPages(String queryPagerObject) throws Exception {
+		return this.serializer.serializeObject(this.getAllPages(this.serializer.deserializeObject(QueryPager.class, queryPagerObject)));	
+	}
+
+	public String xmlrpc_getCalalogProperties() throws Exception {
+		return this.serializer.serializeObject(this.getCalalogProperties());	
+	}
+
+	public String xmlrpc_getCalalogProperties(String catalogUrn)
+			throws Exception {
+		return this.serializer.serializeObject(this.getCalalogProperties(catalogUrn));	
+	}
+
+//	public String xmlrpc_getCatalog(String catalogUrn) throws Exception {
+//		return this.serializer.serializeObject(this.getCatalog(catalogUrn));	
+//	}
+
+	public String xmlrpc_getCatalogServiceTransactionId(
+			String catalogTransactionIdObject, String catalogUrn)
+			throws Exception {
+		return this.serializer.serializeObject(this.getCatalogServiceTransactionId(this.serializer.deserializeObject(TransactionId.class, catalogTransactionIdObject), catalogUrn));	
+	}
+
+	public String xmlrpc_getCatalogServiceTransactionId2(
+			String catalogReceiptObject,
+			String generateNewObject) throws Exception {
+		return this.serializer.serializeObject(this.getCatalogServiceTransactionId(this.serializer.deserializeObject(CatalogReceipt.class, catalogReceiptObject), this.serializer.deserializeObject(Boolean.class, generateNewObject)));	
+	}
+
+	public String xmlrpc_getCatalogServiceTransactionIds(
+			String catalogTransactionIdsObject, String catalogUrn)
+			throws Exception {
+		return this.serializer.serializeObject(this.getCatalogServiceTransactionIds(this.serializer.deserializeObject(List.class, catalogTransactionIdsObject), catalogUrn));	
+	}
+
+	public String xmlrpc_getCurrentCatalogIds() throws Exception {
+		return this.serializer.serializeObject(this.getCurrentCatalogIds());	
+	}
+
+//	public String xmlrpc_getCurrentCatalogList() throws Exception {
+//		return this.serializer.serializeObject(this.getCurrentCatalogList());	
+//	}
+
+	public String xmlrpc_getMetadataFromTransactionIdStrings(
+			String catalogServiceTransactionIdStringsObject)
+			throws Exception {
+		return this.serializer.serializeObject(this.getMetadataFromTransactionIdStrings(this.serializer.deserializeObject(List.class, catalogServiceTransactionIdStringsObject)));	
+	}
+
+	public String xmlrpc_getMetadataFromTransactionIds(
+			String catalogServiceTransactionIdsObject)
+			throws Exception {
+		return this.serializer.serializeObject(this.getMetadataFromTransactionIds(this.serializer.deserializeObject(List.class, catalogServiceTransactionIdsObject)));	
+	}
+
+	public String xmlrpc_getNextPage(String queryPagerObject)
+			throws Exception {
+		return this.serializer.serializeObject(this.getNextPage(this.serializer.deserializeObject(QueryPager.class, queryPagerObject)));	
+	}
+
+	public String xmlrpc_getProperty(String key) throws Exception {
+		return this.serializer.serializeObject(this.getProperty(key));	
+	}
+//
+//	public String xmlrpc_getTransactionIdClass() throws Exception {
+//		return this.serializer.serializeObject(this.getTransactionIdClass());	
+//	}
+
+//	public String xmlrpc_getTransactionIdsForAllPages(
+//			String queryPagerObject) throws Exception {
+//		return this.serializer.serializeObject(this.getTransactionIdsForAllPages(this.serializer.deserializeObject(QueryPager.class, queryPagerObject)));	
+//	}
+
+	public String xmlrpc_ingest(String metadataObject)
+			throws Exception {
+		return this.serializer.serializeObject(this.ingest(this.serializer.deserializeObject(Metadata.class, metadataObject)));	
+	}
+
+	public String xmlrpc_isRestrictIngestPermissions() throws Exception {
+		return this.serializer.serializeObject(new Boolean(this.isRestrictIngestPermissions()));	
+	}
+
+	public String xmlrpc_isRestrictQueryPermissions() throws Exception {
+		return this.serializer.serializeObject(new Boolean(this.isRestrictQueryPermissions()));
+	}
+
+	public String xmlrpc_query(String queryExpressionObject) throws Exception {
+		return this.serializer.serializeObject(this.query(this.serializer.deserializeObject(QueryExpression.class, queryExpressionObject)));	
+	}
+
+	public String xmlrpc_query(String queryExpressionObject, String catalogIdsObject) throws Exception {
+		return this.serializer.serializeObject(this.query(this.serializer.deserializeObject(QueryExpression.class, queryExpressionObject), this.serializer.deserializeObject(Set.class, catalogIdsObject)));	
+	}
+	
+//	public String xmlrpc_getFirstPage(String queryExpressionObject) throws Exception {
+//		return this.serializer.serializeObject(this.getFirstPage(this.serializer.deserializeObject(QueryExpression.class, queryExpressionObject)));	
+//	}
+//
+//	public String xmlrpc_getFirstPage(String queryExpressionObject, String catalogIdsObject) throws Exception {
+//		return this.serializer.serializeObject(this.getFirstPage(this.serializer.deserializeObject(QueryExpression.class, queryExpressionObject), this.serializer.deserializeObject(Set.class, catalogIdsObject)));	
+//	}
+	
+	public String xmlrpc_getNextPage2(String pageObject) throws Exception {
+		return this.serializer.serializeObject(this.getNextPage(this.serializer.deserializeObject(Page.class, pageObject)));	
+	}
+	
+	public String xmlrpc_getPage(String pageInfoObject, String queryExpressionObject) throws Exception {
+		return this.serializer.serializeObject(this.getPage(this.serializer.deserializeObject(PageInfo.class, pageInfoObject), this.serializer.deserializeObject(QueryExpression.class, queryExpressionObject)));
+	}
+	
+	public String xmlrpc_getPage(String pageInfoObject, String queryExpressionObject, String catalogIdsObject) throws Exception {
+		return this.serializer.serializeObject(this.getPage(this.serializer.deserializeObject(PageInfo.class, pageInfoObject), this.serializer.deserializeObject(QueryExpression.class, queryExpressionObject), this.serializer.deserializeObject(Set.class, catalogIdsObject)));
+	}
+	
+//	public String xmlrpc_getLastPage(String queryExpressionObject) throws Exception {
+//		return this.serializer.serializeObject(this.getLastPage(this.serializer.deserializeObject(QueryExpression.class, queryExpressionObject)));	
+//	}
+//
+//	public String xmlrpc_getLastPage(String queryExpressionObject, String catalogIdsObject) throws Exception {
+//		return this.serializer.serializeObject(this.getLastPage(this.serializer.deserializeObject(QueryExpression.class, queryExpressionObject), this.serializer.deserializeObject(Set.class, catalogIdsObject)));	
+//	}
+	
+	public String xmlrpc_getMetadata(String pageObject) throws Exception {
+		return this.serializer.serializeObject(this.getMetadata(this.serializer.deserializeObject(Page.class, pageObject)));
+	}
+	
+//	public String xmlrpc_query(String queryExpressionObject, String sortResultsObject) throws Exception {
+//		System.out.println(this.getClass().getClassLoader());
+//		return this.serializer.serializeObject(this.query(this.serializer.deserializeObject(QueryExpression.class, queryExpressionObject), this.serializer.deserializeObject(Boolean.class, sortResultsObject)));	
+//	}
+
+	public boolean xmlrpc_removeCatalog(String catalogUrn) throws Exception {
+		this.removeCatalog(catalogUrn);
+		return true;
+	}
+//
+//	public boolean xmlrpc_removeCatalog(String catalogUrn, String preserveMappingObject) throws Exception {
+//		this.removeCatalog(catalogUrn, this.serializer.deserializeObject(Boolean.class, preserveMappingObject));	
+//		return true;
+//	}
+//	
+//	public boolean xmlrpc_setHasIngestPermissions(String restrictIngestPermissionsObject) throws Exception {
+//		this.setHasIngestPermissions(this.serializer.deserializeObject(Boolean.class, restrictIngestPermissionsObject));	
+//		return true;
+//	}
+//
+//	public boolean xmlrpc_setRestrictQueryPermissions(String restrictQueryPermissionsObject) throws Exception {
+//		this.setRestrictQueryPermissions(this.serializer.deserializeObject(Boolean.class, restrictQueryPermissionsObject));		
+//		return true;
+//	}
+
+//	public boolean setTransactionIdClass(String transactionIdClassObject) throws Exception {
+//		this.setTransactionIdClass(this.serializer.deserializeObject(Class.class, transactionIdClassObject));	
+//		return true;
+//	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/xmlrpc/XmlRpcCommunicationChannelServerFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/xmlrpc/XmlRpcCommunicationChannelServerFactory.java
new file mode 100644
index 0000000..565d4d3
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/channel/xmlrpc/XmlRpcCommunicationChannelServerFactory.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.channel.xmlrpc;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.server.channel.CommunicationChannelServer;
+import org.apache.oodt.cas.catalog.server.channel.CommunicationChannelServerFactory;
+import org.apache.oodt.cas.catalog.system.CatalogServiceFactory;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+//OODT imports
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory for creating XmlRpcCommunicationChannelServer
+ * <p>
+ */
+public class XmlRpcCommunicationChannelServerFactory implements
+		CommunicationChannelServerFactory {
+	
+	private static Logger LOG = Logger.getLogger(XmlRpcCommunicationChannelServerFactory.class.getName());
+	
+	protected int port;
+	protected CatalogServiceFactory catalogServiceFactory;
+	
+	public XmlRpcCommunicationChannelServerFactory() {}
+	
+	public CommunicationChannelServer createCommunicationChannelServer() {
+		try {
+			XmlRpcCommunicationChannelServer server = new XmlRpcCommunicationChannelServer();
+			server.setCatalogService(this.catalogServiceFactory.createCatalogService());
+			server.setPort(this.port);
+			return server;
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed to create XML-RPC server : " + e.getMessage(), e);
+			return null;
+		}
+	}
+	
+	@Required
+	public void setPort(int port) {
+		this.port = port;
+	}
+	
+	public int getPort() {
+		return this.port;
+	}
+	
+	@Required
+	public void setCatalogServiceFactory(CatalogServiceFactory catalogServiceFactory) {
+		this.catalogServiceFactory = catalogServiceFactory;
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/cli/action/CatalogServiceServerCliAction.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/cli/action/CatalogServiceServerCliAction.java
new file mode 100644
index 0000000..e8cbb3e
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/cli/action/CatalogServiceServerCliAction.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.mapping.IngestMapperFactory;
+import org.apache.oodt.cas.catalog.repository.CatalogRepositoryFactory;
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+
+/**
+ * Base Catalog Service Server {@link CmdLineAction}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public abstract class CatalogServiceServerCliAction extends CmdLineAction {
+
+   public int getPort() {
+      return Integer.getInteger("org.apache.oodt.cas.catalog.port");
+   }
+
+   public String getTransactionId() {
+      return System.getProperty("org.apache.oodt.cas.catalog.transactionid");
+   }
+
+   public CatalogRepositoryFactory getRepository()
+         throws InstantiationException, IllegalAccessException,
+         ClassNotFoundException {
+      return (CatalogRepositoryFactory) Class.forName(
+            System.getProperty("org.apache.oodt.cas.catalog.repository"))
+            .newInstance();
+   }
+
+   public IngestMapperFactory getIngestMapper() throws InstantiationException,
+         IllegalAccessException, ClassNotFoundException {
+      return (IngestMapperFactory) Class.forName(
+            System.getProperty("org.apache.oodt.cas.catalog.ingestmapper"))
+            .newInstance();
+   }
+
+   public boolean getRestrictQueryPermissions() {
+      return Boolean
+            .getBoolean("org.apache.oodt.cas.catalog.restrict.query.permissions");
+   }
+
+   public boolean getRestrictIngestPermissions() {
+      return Boolean
+            .getBoolean("org.apache.oodt.cas.catalog.restrict.ingest.permissions");
+   }
+
+   public boolean getOneCatalogFailsAllFail() {
+      return Boolean
+            .getBoolean("org.apache.oodt.cas.catalog.oneCatalogFailsAllFail");
+   }
+
+   public boolean getSimplifyQueries() {
+      return Boolean.getBoolean("org.apache.oodt.cas.catalog.simplifyQueries");
+   }
+
+   public boolean getDisableIntersectingCrossCatalogQueries() {
+      return Boolean
+            .getBoolean("org.apache.oodt.cas.catalog.disableIntersectingCrossCatalogQueries");
+   }
+
+   public int getCrossCatalogResultSortingThreshold() {
+      return Integer
+            .getInteger("org.apache.oodt.cas.catalog.crossCatalogResultSortingThreshold");
+   }
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/cli/action/LaunchXmlRpcServerCliAction.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/cli/action/LaunchXmlRpcServerCliAction.java
new file mode 100644
index 0000000..1ef4747
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/server/cli/action/LaunchXmlRpcServerCliAction.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.server.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.server.channel.xmlrpc.XmlRpcCommunicationChannelServerFactory;
+import org.apache.oodt.cas.catalog.system.impl.CatalogServiceLocalFactory;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class LaunchXmlRpcServerCliAction extends CatalogServiceServerCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         printer.println("Starting XML-RPC server on port " + getPort());
+         getXmlRpcFactory().createCommunicationChannelServer().startup();
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to startup server : "
+               + e.getMessage(), e);
+      }
+   }
+
+   protected XmlRpcCommunicationChannelServerFactory getXmlRpcFactory()
+         throws InstantiationException, IllegalAccessException,
+         ClassNotFoundException {
+      XmlRpcCommunicationChannelServerFactory factory = new XmlRpcCommunicationChannelServerFactory();
+      factory.setPort(getPort());
+      factory.setCatalogServiceFactory(getCatalogServiceFactory());
+      return factory;
+   }
+
+   protected CatalogServiceLocalFactory getCatalogServiceFactory()
+         throws InstantiationException, IllegalAccessException,
+         ClassNotFoundException {
+      CatalogServiceLocalFactory factory = new CatalogServiceLocalFactory();
+      factory.setTransactionIdFactory(getTransactionId());
+      factory.setCatalogRepositoryFactory(getRepository());
+      factory.setIngestMapperFactory(getIngestMapper());
+      factory.setRestrictQueryPermissions(getRestrictQueryPermissions());
+      factory.setRestrictIngestPermissions(getRestrictIngestPermissions());
+      factory.setOneCatalogFailsAllFail(getOneCatalogFailsAllFail());
+      factory.setSimplifyQueries(getSimplifyQueries());
+      factory.setDisableIntersectingCrossCatalogQueries(
+            getDisableIntersectingCrossCatalogQueries());
+      factory.setCrossCatalogResultSortingThreshold(
+            getCrossCatalogResultSortingThreshold());
+      return factory;
+   }
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/Dictionary.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/Dictionary.java
new file mode 100644
index 0000000..4d9d512
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/Dictionary.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogDictionaryException;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.term.TermBucket;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Dictionary for create Catalog understandable Terms from Metadata
+ * <p>
+ */
+public interface Dictionary {
+
+	/**
+	 * Given a Metadata object a lookup call to a given dictionary will
+	 * always return the same TermBucket.  However, calls to several
+	 * Dictionary's lookup method may return different TermBuckets for
+	 * a given Metadata object.
+	 * @param metadata The Metadata for which a TermBucket will be created
+	 * @return TermBucket representing the given Metadata for this Dictionary or
+	 * null if Metadata is not recognized by this Dictionary
+	 */
+	public TermBucket lookup(Metadata metadata) throws CatalogDictionaryException;
+
+	/**
+	 * Generates Metadata for the given TermBucket.  A call to lookup(Metadata) and
+	 * then reverseLookup(TermBucket) may not give you back the original Metadata
+	 * because lookup may ignore key/values in Metadata for which it does not
+	 * understand.
+	 * @param termBucket The TermBucket for which Metadata will be created
+	 * @return Metadata for the given TermBucket.  If the TermBucket is not understood,
+	 * then an empty Metadata object should be returned.
+	 */
+	public Metadata reverseLookup(TermBucket termBucket) throws CatalogDictionaryException;
+			
+	/**
+	 * 
+	 * @param queryExpression
+	 * @return
+	 * @throws CatalogDictionaryException
+	 */
+	public boolean understands(QueryExpression queryExpression) throws CatalogDictionaryException;
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/DictionaryFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/DictionaryFactory.java
new file mode 100644
index 0000000..ed89e41
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/DictionaryFactory.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public interface DictionaryFactory {
+
+	public Dictionary createDictionary();
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/Index.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/Index.java
new file mode 100644
index 0000000..ed33efc
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/Index.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct;
+
+//JDK imports
+import java.util.List;
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogIndexException;
+import org.apache.oodt.cas.catalog.page.IndexPager;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Interface for Communicating with an Term Index.  Should also implement
+ * IngestService to allow Term ingest to this Index and/or implement 
+ * QueryService to allow Term query on this Index.
+ * <p>
+ */
+public interface Index {
+	
+	public Properties getProperties() throws CatalogIndexException;
+	
+	public String getProperty(String key) throws CatalogIndexException;
+	
+	/**
+	 * Returns a list of TransactionIds associated with the 
+	 * given Index page.
+	 * @param indexPage The page for which TransactionIds will be returned
+	 * @return A page of TransactionIds, if page does not exist,
+	 * then returns null.
+	 */
+	public List<TransactionId<?>> getPage(IndexPager indexPage) throws CatalogIndexException;
+	
+	/**
+	 * 
+	 * @return
+	 */
+	public TransactionIdFactory getTransactionIdFactory() throws CatalogIndexException;
+	
+	/**
+	 * 
+	 * @param catalogTransactionid
+	 * @return
+	 * @throws CatalogIndexException
+	 */
+	public boolean hasTransactionId(TransactionId<?> transactionid)  throws CatalogIndexException;
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/IndexFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/IndexFactory.java
new file mode 100644
index 0000000..184eed5
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/IndexFactory.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public interface IndexFactory {
+
+	public Index createIndex();
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/IngestService.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/IngestService.java
new file mode 100644
index 0000000..7704edb
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/IngestService.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.IngestServiceException;
+import org.apache.oodt.cas.catalog.page.IngestReceipt;
+import org.apache.oodt.cas.catalog.term.TermBucket;
+
+//OODT imports
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Interface for performing ingests to an Index
+ * <p>
+ */
+public interface IngestService {
+	
+	/**
+	 * Indexes the given TermBucket to a TransactionId, and returns a IngestReceipt
+	 * @param termBuckets The List of TermBucket to be ingested
+	 * @return IngestReceipt Receipt of ingest
+	 * @throws IngestServiceException Any error 
+	 */
+	public IngestReceipt ingest(List<TermBucket> termBuckets) throws IngestServiceException;
+	
+	/**
+	 * TermBucket updates to given TransactionId.  A new TransactionId can be returned in IngestReceipt
+	 * if so desired and it will automatically get remapped by CatalogService.  Existing metadata 
+	 * for given TransactionId should not be deleted, just the terms in the given term buckets should
+	 * be modified.  For a complete re-ingest, one should instead delete() then ingest().
+	 * @param transactionId
+	 * @param termBuckets
+	 * @throws IngestServiceException
+	 */
+	public IngestReceipt update(TransactionId<?> transactionId, List<TermBucket> termBuckets) throws IngestServiceException;
+	
+	/**
+	 * Deletes all TermBuckets attached to given TransactionId -- there should be no trace of 
+	 * given transaction after this method is called.
+	 * @param transactionId The ID for given transaction which should be erased
+	 * @throws IngestServiceException Any error 
+	 */
+	public boolean delete(TransactionId<?> transactionId) throws IngestServiceException;
+	
+	/**
+	 * Deletes only the Terms in the given TermBuckets from the given TransactionId
+	 * @param transactionId The TransactionId for which Terms will be deleted
+	 * @param termBuckets The reduction set of Terms for each TermBucket
+	 * @throws IngestServiceException Any error
+	 */
+	public boolean reduce(TransactionId<?> transactionId, List<TermBucket> termBuckets) throws IngestServiceException;
+		
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/QueryService.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/QueryService.java
new file mode 100644
index 0000000..31b729c
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/QueryService.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct;
+
+//JDK imports
+import java.util.List;
+import java.util.Map;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.QueryServiceException;
+import org.apache.oodt.cas.catalog.page.IngestReceipt;
+import org.apache.oodt.cas.catalog.page.TransactionReceipt;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.term.TermBucket;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Interface for performing queries to a Catalog
+ * <p>
+ */
+public interface QueryService {
+
+	/**
+	 * Returns all the TransactionIds that fall under the given query
+	 * @param query The query for TransactionIds
+	 * @return Returns a List of TransactionIds that meet the query, otherwise
+	 * an empty List is no TransactionIds are found for the given query
+	 */
+	public List<IngestReceipt> query(QueryExpression queryExpression) throws QueryServiceException;
+	
+	/**
+	 * Returns the results of the given query such that: [startIndex, endIndex)
+	 * @param queryExpression The query for which results will be returned
+	 * @param startIndex The start index of subset of results to be returned
+	 * @param endIndex The end index of the subset of results to be returned
+	 * @return The results of the given query such that: [startIndex, endIndex)
+	 * @throws QueryServiceException on an error
+	 */
+	public List<IngestReceipt> query(QueryExpression queryExpression, int startIndex, int endIndex) throws QueryServiceException;
+
+	/**
+	 * Returns the number of results found for the given query
+	 * @param queryExpression The query whose size in question
+	 * @return The number of results found for the given query
+	 * @throws QueryServiceException on an error
+	 */
+	public int sizeOf(QueryExpression queryExpression) throws QueryServiceException;
+	
+	/**
+	 * Returns a List of TermBuckets ingested for a given TransactionId
+	 * @param transactionId The TransactionId in question
+	 * @return A List of TermBuckets for the given TransactionId or empty list
+	 * if no record of the give TranactionId exists
+	 */
+	public List<TermBucket> getBuckets(TransactionId<?> transactionId) throws QueryServiceException;
+	
+	/**
+	 * Does the same as getBuckets(TransactionId), except is performed over a list
+	 * of TransactionIds
+	 * @param transactionIds A List of TransactionIds for which TermBuckets are wanted
+	 * @return A Map of TransactionIds to TermBuckets
+	 */
+	public Map<TransactionId<?>, List<TermBucket>> getBuckets(List<TransactionId<?>> transactionIds) throws QueryServiceException;
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/TransactionId.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/TransactionId.java
new file mode 100644
index 0000000..f3f1835
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/TransactionId.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Interface for storing TransactionIds
+ * <p>
+ */
+public abstract class TransactionId<NativeType> {
+
+	protected NativeType nativeId;
+	
+	public TransactionId() {}
+
+	public TransactionId(NativeType nativeId) {
+		this.nativeId = nativeId;
+	}
+	
+	public TransactionId(String stringId) {
+		this.nativeId = this.fromString(stringId);
+	}
+	
+	@Override
+	public int hashCode() {
+		return this.toString().hashCode();
+	}
+	
+	public NativeType getNativeId() {
+		return this.nativeId;
+	}
+		
+	/**
+	 * Should override this method if NativeType.toString()
+	 * does not properly represent the String value of the
+	 * native type.  The string value of the NativeType should
+	 * be as unique as in its native form.
+	 */
+	public String toString() {
+		return this.nativeId.toString();
+	}
+	
+	public boolean equals(Object obj) {
+		if (obj instanceof TransactionId<?>)
+			return this.toString().equals(obj.toString());
+		else if (obj instanceof String)
+			return this.toString().equals((String) obj);
+		else
+			return false;
+	}
+	
+	protected abstract NativeType fromString(String stringId);
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/TransactionIdFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/TransactionIdFactory.java
new file mode 100644
index 0000000..587383d
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/TransactionIdFactory.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public interface TransactionIdFactory {
+
+	public TransactionId<?> createNewTransactionId();
+	
+	public TransactionId<?> createTransactionId(String transactionIdString);
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/dictionary/WorkflowManagerDictionary.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/dictionary/WorkflowManagerDictionary.java
new file mode 100644
index 0000000..48649b3
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/dictionary/WorkflowManagerDictionary.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct.impl.dictionary;
+
+//JDK imports
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogDictionaryException;
+import org.apache.oodt.cas.catalog.query.ComparisonQueryExpression;
+import org.apache.oodt.cas.catalog.query.NotQueryExpression;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.query.QueryLogicalGroup;
+import org.apache.oodt.cas.catalog.query.StdQueryExpression;
+import org.apache.oodt.cas.catalog.query.TermQueryExpression;
+import org.apache.oodt.cas.catalog.struct.Dictionary;
+import org.apache.oodt.cas.catalog.term.Term;
+import org.apache.oodt.cas.catalog.term.TermBucket;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class WorkflowManagerDictionary implements Dictionary {
+
+	public TermBucket lookup(Metadata metadata)
+			throws CatalogDictionaryException {
+		if (metadata.getMetadata("ProductType") != null && metadata.getAllMetadata("ProductType").contains("Workflows")) {
+			TermBucket workflowBucket = new TermBucket("Workflows");
+			for (Object key : metadata.getHashtable().keySet()) 
+				workflowBucket.addTerm(new Term((String) key, metadata.getAllMetadata((String) key)));
+			return workflowBucket;
+		}else {
+			return null;
+		}
+	}
+
+	public Metadata reverseLookup(TermBucket termBucket)
+			throws CatalogDictionaryException {
+		Metadata metadata = new Metadata();
+		if (termBucket.getName().equals("Workflows")) {
+			for (Term term : termBucket.getTerms())
+				metadata.addMetadata(term.getName(), term.getValues());
+		}
+		return metadata;
+	}
+
+	public boolean understands(QueryExpression queryExpression)
+			throws CatalogDictionaryException {
+		Set<String> bucketNames = queryExpression.getBucketNames();
+		if (bucketNames == null || bucketNames.contains("Workflows")) {
+			if (queryExpression instanceof NotQueryExpression 
+					|| queryExpression instanceof ComparisonQueryExpression 
+					|| queryExpression instanceof StdQueryExpression 
+					|| queryExpression instanceof QueryLogicalGroup) {
+				return true;
+			} else
+				return false;	
+		}
+		return false;
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/dictionary/WorkflowManagerDictionaryFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/dictionary/WorkflowManagerDictionaryFactory.java
new file mode 100644
index 0000000..e629667
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/dictionary/WorkflowManagerDictionaryFactory.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct.impl.dictionary;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.struct.DictionaryFactory;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class WorkflowManagerDictionaryFactory implements DictionaryFactory {
+
+	public WorkflowManagerDictionary createDictionary() {
+		return new WorkflowManagerDictionary();
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/DataSourceIndex.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/DataSourceIndex.java
new file mode 100644
index 0000000..a046263
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/DataSourceIndex.java
@@ -0,0 +1,532 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct.impl.index;
+
+//JDK imports
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//SQL imports
+import javax.sql.DataSource;
+
+//OODT imports
+import org.apache.commons.lang.StringUtils;
+import org.apache.oodt.cas.catalog.exception.CatalogIndexException;
+import org.apache.oodt.cas.catalog.exception.IngestServiceException;
+import org.apache.oodt.cas.catalog.exception.QueryServiceException;
+import org.apache.oodt.cas.catalog.page.IndexPager;
+import org.apache.oodt.cas.catalog.page.IngestReceipt;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.page.ProcessedPageInfo;
+import org.apache.oodt.cas.catalog.query.ComparisonQueryExpression;
+import org.apache.oodt.cas.catalog.query.NotQueryExpression;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.query.QueryLogicalGroup;
+import org.apache.oodt.cas.catalog.query.StdQueryExpression;
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.IngestService;
+import org.apache.oodt.cas.catalog.struct.QueryService;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.struct.TransactionIdFactory;
+import org.apache.oodt.cas.catalog.struct.impl.transaction.UuidTransactionIdFactory;
+import org.apache.oodt.cas.catalog.term.Term;
+import org.apache.oodt.cas.catalog.term.TermBucket;
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+import org.apache.oodt.commons.date.DateUtils;
+
+/**
+ * 
+ * DataSource Indexer which supports both ingest and query
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class DataSourceIndex implements Index, IngestService, QueryService {
+
+	private static final Logger LOG = Logger.getLogger(DataSourceIndex.class.getName());
+	
+	protected DataSource dataSource;
+	protected boolean useUTF8;
+	
+	public DataSourceIndex(String user, String pass, String driver, String jdbcUrl, boolean useUTF8) {
+		this.dataSource = DatabaseConnectionBuilder.buildDataSource(user, pass, driver, jdbcUrl);
+		this.useUTF8 = useUTF8;
+	}
+	
+	public IndexPager getPager(PageInfo pageInfo) throws CatalogIndexException {
+		return new IndexPager(new ProcessedPageInfo(pageInfo.getPageSize(), pageInfo.getPageNum(), this.getNumOfTransactions()));
+	}
+	
+	protected int getNumOfTransactions() throws CatalogIndexException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			rs = stmt.executeQuery("SELECT COUNT(transaction_id) AS numTransIds FROM transactions");
+			if (rs.next())
+				return rs.getInt("numTransIds");
+			else
+				throw new Exception("Failed to query for number of transactions");
+		}catch (Exception e) {
+			throw new CatalogIndexException("Failed to get number of transactions : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public List<TransactionId<?>> getPage(IndexPager indexPage) throws CatalogIndexException {
+//		Connection conn = null;
+//		Statement stmt = null;
+//		ResultSet rs = null;
+//		try {
+//			conn = this.dataSource.getConnection();
+//			stmt = conn.createStatement();
+//			rs = stmt.executeQuery("SELECT transaction_id,transaction_class,transaction_date FROM transactions");
+//			int startLoc = pager.getPageNum() * pager.getPageSize();
+//			int endLoc = startLoc + pager.getPageSize();
+//			List<IngestReceipt> receipts = new Vector<IngestReceipt>();
+//			for (int i = startLoc; i < endLoc && rs.next(); i++) {
+//				receipts.add(new IngestReceipt(((TransactionId<?>) Class.forName(rs.getString("transaction_class")).getConstructor(String.class).newInstance(rs.getString("transaction_id"))), DateUtils.toCalendar(rs.getString("transaction_date"), DateUtils.FormatType.LOCAL_FORMAT).getTime()));
+//			}
+//			return rs.next();
+//		}catch (Exception e) {
+//			throw new CatalogIndexException("Failed to check for transaction id '" + transactionId + "' : " + e.getMessage(), e);
+//		}finally {
+//			try {
+//				conn.close();
+//			}catch(Exception e) {}
+//			try {
+//				stmt.close();
+//			}catch(Exception e) {}
+//			try {
+//				rs.close();
+//			}catch(Exception e) {}
+//		}
+		return null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Properties getProperties() throws CatalogIndexException {
+		return new Properties();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getProperty(String key) throws CatalogIndexException {
+		return null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public TransactionIdFactory getTransactionIdFactory()
+			throws CatalogIndexException {
+		return new UuidTransactionIdFactory();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean hasTransactionId(TransactionId<?> transactionId)
+			throws CatalogIndexException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			rs = stmt.executeQuery("SELECT DISTINCT transaction_id FROM transactions WHERE transaction_id = '" + transactionId + "'");
+			return rs.next();
+		}catch (Exception e) {
+			throw new CatalogIndexException("Failed to check for transaction id '" + transactionId + "' : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean delete(TransactionId<?> transactionId)
+			throws IngestServiceException {
+		Connection conn = null;
+		Statement stmt = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			stmt.execute("DELETE FROM transactions WHERE transaction_id = '" + transactionId + "'");
+			stmt.execute("DELETE FROM transaction_terms WHERE transaction_id = '" + transactionId + "'");
+			conn.commit();
+			return true;
+		}catch (Exception e) {
+			throw new IngestServiceException("Failed to delete transaction id '" + transactionId + "' : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IngestReceipt ingest(List<TermBucket> termBuckets) throws IngestServiceException {
+		Connection conn = null;
+		Statement stmt = null;
+		TransactionId<?> catalogTransactionId = null;
+		try {
+			catalogTransactionId = this.getTransactionIdFactory().createNewTransactionId();
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			Calendar calendar = DateUtils.getCurrentLocalTime();
+			stmt.execute("INSERT INTO transactions VALUES ('" + catalogTransactionId + "','" + DateUtils.toString(calendar) + "')");
+			for (TermBucket termBucket : termBuckets) {
+				for (Term term : termBucket.getTerms()) {
+					for (String value : term.getValues()) {
+						try {
+							stmt.execute("INSERT INTO transaction_terms VALUES ('" + catalogTransactionId + "','" + termBucket.getName() + "','" + term.getName() + "','" + (this.useUTF8 ? URLEncoder.encode(value, "UTF8") : value) + "')");
+						}catch (Exception e) {
+							LOG.log(Level.WARNING, "Failed to ingest term: '" + catalogTransactionId + "','" + termBucket.getName() + "','" + term.getName() + "','" + value + "'");
+						}
+					}
+				}
+			}
+			conn.commit();
+			return new IngestReceipt(catalogTransactionId, calendar.getTime());
+		}catch (Exception e) {
+			throw new IngestServiceException("Failed to ingest metadata for transaction id '" + catalogTransactionId + "' : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean reduce(TransactionId<?> transactionId,
+			List<TermBucket> termBuckets) throws IngestServiceException {
+		Connection conn = null;
+		Statement stmt = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			for (TermBucket termBucket : termBuckets) 
+				for (Term term : termBucket.getTerms()) 
+					for (String value : term.getValues()) 
+						try {
+							stmt.execute("DELETE FROM transaction_terms WHERE transaction_id = '" + transactionId + "' AND bucket_name = '" + termBucket.getName() + "' AND term_name = '" + term.getName() + "' AND term_value = '" + (this.useUTF8 ? URLEncoder.encode(value, "UTF8") : value) + "'");
+						}catch (Exception e) {
+							LOG.log(Level.WARNING, "Failed to delete term: '" + transactionId + "','" + termBucket.getName() + "','" + term.getName() + "','" + value + "'");
+						}
+			conn.commit();
+			return true;
+		}catch (Exception e) {
+			throw new IngestServiceException("Failed to delete transaction id '" + transactionId + "' : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IngestReceipt update(TransactionId<?> transactionId,
+			List<TermBucket> termBuckets) throws IngestServiceException {
+		Connection conn = null;
+		Statement stmt = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			for (TermBucket termBucket : termBuckets) 
+				for (Term term : termBucket.getTerms()) 
+					for (String value : term.getValues())
+						try {
+							stmt.execute("DELETE FROM transaction_terms WHERE transaction_id = '" + transactionId + "' AND bucket_name = '" + termBucket.getName() + "' AND term_name = '" + term.getName() + "'");
+							stmt.execute("INSERT INTO transaction_terms VALUES ('" + transactionId + "','" + termBucket.getName() + "','" + term.getName() + "','" + (this.useUTF8 ? URLEncoder.encode(value, "UTF8") : value) + "')");
+						}catch (Exception e) {
+							LOG.log(Level.WARNING, "Failed to ingest term: '" + transactionId + "','" + termBucket.getName() + "','" + term.getName() + "','" + value + "'");
+						}
+			Calendar calendar = DateUtils.getCurrentLocalTime();
+			stmt.execute("UPDATE transactions SET transaction_date = '" + DateUtils.toString(calendar) + "' WHERE transaction_id = '" + transactionId + "'");
+			return new IngestReceipt(transactionId, calendar.getTime());
+		}catch (Exception e) {
+			throw new IngestServiceException("Failed to ingest metadata for transaction id '" + transactionId + "' : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public List<TermBucket> getBuckets(TransactionId<?> transactionId)
+			throws QueryServiceException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			HashMap<String, TermBucket> termBuckets = new HashMap<String, TermBucket>();
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			rs = stmt.executeQuery("SELECT bucket_name,term_name,term_value FROM transaction_terms WHERE transaction_id = '" + transactionId + "'");
+			while (rs.next()) {
+                String bucketName = rs.getString("bucket_name");
+                String termName = rs.getString("term_name");
+                String termValue = rs.getString("term_value");
+                TermBucket bucket = termBuckets.get(bucketName);
+                if (bucket == null)
+                	bucket = new TermBucket(bucketName);
+                Term term = new Term(termName, Collections.singletonList((this.useUTF8 ? URLDecoder.decode(termValue, "UTF8") : termValue)));
+                bucket.addTerm(term);
+                termBuckets.put(bucketName, bucket);
+			}
+			return new Vector<TermBucket>(termBuckets.values());
+		}catch (Exception e) {
+			throw new QueryServiceException("Failed to get term buckets for transaction id '" + transactionId + "' : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Map<TransactionId<?>, List<TermBucket>> getBuckets(
+			List<TransactionId<?>> transactionIds) throws QueryServiceException {
+		HashMap<TransactionId<?>, List<TermBucket>> map = new HashMap<TransactionId<?>, List<TermBucket>>();
+		for (TransactionId<?> transactionId : transactionIds) 
+			map.put(transactionId, this.getBuckets(transactionId));
+		return map;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public List<IngestReceipt> query(QueryExpression queryExpression)
+			throws QueryServiceException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			String sqlQuery = "SELECT DISTINCT transaction_id,transaction_date FROM transactions WHERE transaction_id IN (" + this.getSqlQuery(queryExpression) + ")";
+	        LOG.log(Level.INFO, "Performing Query: " + sqlQuery);
+			rs = stmt.executeQuery(sqlQuery);	
+
+			List<IngestReceipt> receipts = new Vector<IngestReceipt>();
+			while (rs.next()) 
+				receipts.add(new IngestReceipt(this.getTransactionIdFactory().createTransactionId(rs.getString("transaction_id")), DateUtils.toCalendar(rs.getString("transaction_date"), DateUtils.FormatType.LOCAL_FORMAT).getTime()));
+			return receipts;
+		}catch (Exception e) {
+			throw new QueryServiceException("Failed to query Workflow Instances Database : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+	
+	public List<IngestReceipt> query(QueryExpression queryExpression, int startIndex, int endIndex) throws QueryServiceException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			String sqlQuery = "SELECT DISTINCT transaction_id,transaction_date FROM transactions WHERE transaction_id IN (" + this.getSqlQuery(queryExpression) + ")";
+	        LOG.log(Level.INFO, "Performing Query: " + sqlQuery);
+			rs = stmt.executeQuery(sqlQuery);	
+
+			List<IngestReceipt> receipts = new Vector<IngestReceipt>();
+			int index = 0;
+			while (startIndex > index && rs.next()) index++;
+			while (rs.next() && index++ <= endIndex) 
+				receipts.add(new IngestReceipt(this.getTransactionIdFactory().createTransactionId(rs.getString("transaction_id")), DateUtils.toCalendar(rs.getString("transaction_date"), DateUtils.FormatType.LOCAL_FORMAT).getTime()));
+			return receipts;
+		}catch (Exception e) {
+			throw new QueryServiceException("Failed to query Workflow Instances Database : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	public int sizeOf(QueryExpression queryExpression)
+			throws QueryServiceException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			String sqlQuery = "SELECT COUNT(transaction_id) AS numTransactions FROM transactions WHERE transaction_id IN (" + this.getSqlQuery(queryExpression) + ")";
+	        LOG.log(Level.INFO, "Performing Query: " + sqlQuery);
+			rs = stmt.executeQuery(sqlQuery);	
+
+			int numTransactions = 0;
+            while (rs.next())
+            	numTransactions = rs.getInt("numTransactions");
+            
+			return numTransactions;
+		}catch (Exception e) {
+			throw new QueryServiceException("Failed to get size of query : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+	
+	
+    private String getSqlQuery(QueryExpression queryExpression) throws QueryServiceException, UnsupportedEncodingException {
+        String sqlQuery = null;
+		String bucketNameFilter = "";
+		if (queryExpression.getBucketNames() != null) {
+			if (queryExpression.getBucketNames().size() == 1)
+				bucketNameFilter += "bucket_name = '" + queryExpression.getBucketNames().iterator().next() + "' AND ";
+			else if (queryExpression.getBucketNames().size() > 1)
+				bucketNameFilter += "(bucket_name = '" + StringUtils.join(queryExpression.getBucketNames().iterator(), "' OR bucket_name = '") + "') AND ";
+		}
+        if (queryExpression instanceof QueryLogicalGroup) {
+        	QueryLogicalGroup qlg = (QueryLogicalGroup) queryExpression;
+            sqlQuery = "(" + this.getSqlQuery(qlg.getExpressions().get(0));
+            String op = qlg.getOperator() == QueryLogicalGroup.Operator.AND ? "INTERSECT" : "UNION";
+            for (int i = 1; i < qlg.getExpressions().size(); i++) 
+                sqlQuery += ") " + op + " (" + this.getSqlQuery(qlg.getExpressions().get(i));
+            sqlQuery += ")";
+        }else if (queryExpression instanceof ComparisonQueryExpression){
+        	ComparisonQueryExpression cqe = (ComparisonQueryExpression) queryExpression;
+        	String operator = null;
+            if (cqe.getOperator().equals(ComparisonQueryExpression.Operator.EQUAL_TO)) {
+            	operator = "=";
+            } else if (cqe.getOperator().equals(ComparisonQueryExpression.Operator.GREATER_THAN)) {
+            	operator = ">";
+            } else if (cqe.getOperator().equals(ComparisonQueryExpression.Operator.GREATER_THAN_EQUAL_TO)) {
+            	operator = ">=";
+            } else if (cqe.getOperator().equals(ComparisonQueryExpression.Operator.LESS_THAN)) {
+            	operator = "<";
+            } else if (cqe.getOperator().equals(ComparisonQueryExpression.Operator.LESS_THAN_EQUAL_TO)) {
+            	operator = "<=";
+            } else {
+                throw new QueryServiceException("Invalid ComparisonQueryExpression Operator '" + cqe.getOperator() + "'");
+            }
+            
+            sqlQuery = "SELECT DISTINCT transaction_id FROM transaction_terms WHERE " + bucketNameFilter + " term_name = '" + cqe.getTerm().getName() + "' AND (";
+        	for (int i = 0; i < cqe.getTerm().getValues().size(); i++) {
+        		String value = cqe.getTerm().getValues().get(i);
+                sqlQuery += "term_value " + operator + " '" + (this.useUTF8 ? URLEncoder.encode(value, "UTF-8") : value) + "'";
+	            if ((i + 1) < cqe.getTerm().getValues().size())
+	            	sqlQuery += " OR ";
+        	}
+        	sqlQuery += ")";
+        }else if (queryExpression instanceof NotQueryExpression) {
+        	NotQueryExpression nqe = (NotQueryExpression) queryExpression;
+            sqlQuery = "SELECT DISTINCT transaction_id FROM transaction_terms WHERE " + bucketNameFilter + " NOT (" + this.getSqlQuery(nqe.getQueryExpression()) + ")";
+        }else if (queryExpression instanceof StdQueryExpression) {
+            sqlQuery = "SELECT DISTINCT transaction_id FROM transaction_terms " + bucketNameFilter;
+        }else {
+            throw new QueryServiceException("Invalid QueryExpression '" + queryExpression.getClass().getCanonicalName() + "'");
+        }
+        return sqlQuery;
+    }
+
+}
+	
\ No newline at end of file
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/DataSourceIndexFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/DataSourceIndexFactory.java
new file mode 100644
index 0000000..cf6d1ba
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/DataSourceIndexFactory.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct.impl.index;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.IndexFactory;
+
+/**
+ * 
+ * Factory for creating DataSourceIndex(s).
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class DataSourceIndexFactory implements IndexFactory {
+
+    protected String jdbcUrl;
+    protected String user;
+    protected String pass;
+    protected String driver;
+    protected boolean useUTF8;
+	
+    public DataSourceIndexFactory() {
+    	this.useUTF8 = false;
+    }
+    
+	public Index createIndex() {
+		return new DataSourceIndex(this.user, this.pass, this.driver, this.jdbcUrl, this.useUTF8);
+	}
+	
+	public void setJdbcUrl(String jdbcUrl) {
+		this.jdbcUrl = jdbcUrl;
+	}
+
+	public void setUser(String user) {
+		this.user = user;
+	}
+
+	public void setPass(String pass) {
+		this.pass = pass;
+	}
+
+	public void setDriver(String driver) {
+		this.driver = driver;
+	}
+	
+	public void setUseUTF8(boolean useUTF8) {
+		this.useUTF8 = useUTF8;
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/InMemoryIndex.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/InMemoryIndex.java
new file mode 100644
index 0000000..087b1b2
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/InMemoryIndex.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct.impl.index;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.sql.SQLException;
+
+//OODT imports
+import org.apache.oodt.commons.database.SqlScript;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A in memory Index which is ingestable
+ * <p>
+ */
+public class InMemoryIndex extends DataSourceIndex {
+
+	public InMemoryIndex(String user, String pass, String driver,
+			String jdbcUrl, boolean useUTF8, String tablesFile) throws SQLException, IOException {
+		super(user, pass, driver, jdbcUrl, useUTF8);
+        SqlScript coreSchemaScript = new SqlScript(new File(tablesFile).getAbsolutePath(), this.dataSource);
+        coreSchemaScript.loadScript();
+        coreSchemaScript.execute();
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/InMemoryIndexFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/InMemoryIndexFactory.java
new file mode 100644
index 0000000..542cae6
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/InMemoryIndexFactory.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct.impl.index;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class InMemoryIndexFactory extends DataSourceIndexFactory {
+
+	private static final Logger LOG = Logger.getLogger(InMemoryIndexFactory.class.getName());
+	
+	protected String tablesFile;
+	
+	public InMemoryIndex createIndex() {
+		try {
+			return new InMemoryIndex(this.user, this.pass, this.driver, this.jdbcUrl, this.useUTF8, this.tablesFile);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed to create InMemoryIndex : " + e.getMessage(), e);
+			return null;
+		}
+	}
+	
+	public void setTablesFile(String tablesFile) {
+		this.tablesFile = tablesFile;
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/WorkflowManagerDataSourceIndex.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/WorkflowManagerDataSourceIndex.java
new file mode 100644
index 0000000..8c619be
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/WorkflowManagerDataSourceIndex.java
@@ -0,0 +1,306 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct.impl.index;
+
+//JDK imports
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//SQL imports
+import javax.sql.DataSource;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogIndexException;
+import org.apache.oodt.cas.catalog.exception.QueryServiceException;
+import org.apache.oodt.cas.catalog.page.IndexPager;
+import org.apache.oodt.cas.catalog.page.IngestReceipt;
+import org.apache.oodt.cas.catalog.query.ComparisonQueryExpression;
+import org.apache.oodt.cas.catalog.query.NotQueryExpression;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.query.QueryLogicalGroup;
+import org.apache.oodt.cas.catalog.query.StdQueryExpression;
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.QueryService;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.struct.TransactionIdFactory;
+import org.apache.oodt.cas.catalog.struct.impl.transaction.LongTransactionIdFactory;
+import org.apache.oodt.cas.catalog.term.Term;
+import org.apache.oodt.cas.catalog.term.TermBucket;
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+
+//EDA imports
+import org.apache.oodt.commons.util.DateConvert;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A queriable index for querying for original cas-workflow instance metadata (not for cas-workflow2)
+ * <p>
+ */
+public class WorkflowManagerDataSourceIndex implements Index, QueryService {
+
+	private static final Logger LOG = Logger.getLogger(WorkflowManagerDataSourceIndex.class.getName());
+	
+	protected DataSource dataSource;
+	
+	public WorkflowManagerDataSourceIndex(String user, String pass, String driver, String jdbcUrl) throws InstantiationException {
+		this.dataSource = DatabaseConnectionBuilder.buildDataSource(user, pass, driver, jdbcUrl);
+	}
+	
+	public List<TransactionId<?>> getPage(IndexPager indexPage)
+			throws CatalogIndexException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Properties getProperties() throws CatalogIndexException {
+		return new Properties();
+	}
+
+	public String getProperty(String key) throws CatalogIndexException {
+		return null;
+	}
+
+	public TransactionIdFactory getTransactionIdFactory() throws CatalogIndexException {
+		return new LongTransactionIdFactory();
+	}
+
+	public boolean hasTransactionId(TransactionId<?> transactionId)
+			throws CatalogIndexException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			rs = stmt.executeQuery("SELECT DISTINCT workflow_instance_id FROM workflow_instance_metadata WHERE workflow_instance_id = '" + transactionId + "'");	
+			return rs.next();
+		}catch (Exception e) {
+			throw new CatalogIndexException("Failed to check for workflow id '" + transactionId + "' : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	public List<TermBucket> getBuckets(TransactionId<?> transactionId)
+			throws QueryServiceException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			rs = stmt.executeQuery("SELECT * FROM workflow_instance_metadata WHERE workflow_instance_id = '" + transactionId + "'");	
+			
+			TermBucket tb = new TermBucket("Workflows");
+			while (rs.next()) {
+                String key = rs.getString("workflow_met_key");
+                String value = URLDecoder.decode(rs.getString("workflow_met_val"), "UTF-8");
+                tb.addTerm(new Term(key, Collections.singletonList(value)));
+            }
+			return Collections.singletonList(tb);
+		}catch (Exception e) {
+			throw new QueryServiceException("Failed to get Workflow Instance Metadata for workflow id '" + transactionId + "' : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+
+	public Map<TransactionId<?>, List<TermBucket>> getBuckets(
+			List<TransactionId<?>> transactionIds) throws QueryServiceException {
+		Map<TransactionId<?>, List<TermBucket>> returnMap = new HashMap<TransactionId<?>, List<TermBucket>>();
+		for (TransactionId<?> transactionId : transactionIds) 
+			returnMap.put(transactionId, this.getBuckets(transactionId));
+		return returnMap;
+	}
+
+	public List<IngestReceipt> query(QueryExpression queryExpression)
+			throws QueryServiceException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			String sqlQuery = "SELECT workflow_instance_id,start_date_time FROM workflow_instances WHERE workflow_instance_id IN (" + this.getSqlQuery(queryExpression) + ")";
+	        LOG.log(Level.INFO, "Performing Query: " + sqlQuery);
+			rs = stmt.executeQuery(sqlQuery);
+			
+			List<IngestReceipt> receipts = new Vector<IngestReceipt>();
+			while (rs.next()) 
+                receipts.add(new IngestReceipt(new LongTransactionIdFactory().createTransactionId(rs.getString("workflow_instance_id")), DateConvert.isoParse(rs.getString("start_date_time"))));
+			return receipts;
+		}catch (Exception e) {
+			throw new QueryServiceException("Failed to query Workflow Instances Database : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+	
+	public List<IngestReceipt> query(QueryExpression queryExpression, int startIndex, int endIndex) throws QueryServiceException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			String sqlQuery = "SELECT workflow_instance_id,start_date_time FROM workflow_instances WHERE workflow_instance_id IN (" + this.getSqlQuery(queryExpression) + ")";
+	        LOG.log(Level.INFO, "Performing Query: " + sqlQuery);
+			rs = stmt.executeQuery(sqlQuery);
+			
+			List<IngestReceipt> receipts = new Vector<IngestReceipt>();
+			int index = 0;
+			while (startIndex > index && rs.next()) index++;
+			while (rs.next() && index++ <= endIndex) 
+				receipts.add(new IngestReceipt(new LongTransactionIdFactory().createTransactionId(rs.getString("workflow_instance_id")), DateConvert.isoParse(rs.getString("start_date_time"))));
+			return receipts;
+		}catch (Exception e) {
+			throw new QueryServiceException("Failed to query Workflow Instances Database : " + e.getMessage(), e);
+		}finally {
+			try {
+				conn.close();
+			}catch(Exception e) {}
+			try {
+				stmt.close();
+			}catch(Exception e) {}
+			try {
+				rs.close();
+			}catch(Exception e) {}
+		}
+	}
+	
+	public int sizeOf(QueryExpression queryExpression)
+			throws QueryServiceException {
+		Connection conn = null;
+		Statement stmt = null;
+		ResultSet rs = null;
+		try {
+			conn = this.dataSource.getConnection();
+			stmt = conn.createStatement();
+			String sqlQuery = "SELECT COUNT(workflow_instance_id) AS numInstances FROM workflow_instances WHERE workflow_instance_id IN (" + this.getSqlQuery(queryExpression) + ")";
+			LOG.log(Level.INFO, "Performing Query: " + sqlQuery);
+			rs = stmt.executeQuery(sqlQuery);
+
+			int numInstances = 0;
+			while (rs.next())
+				numInstances = rs.getInt("numInstances");
+
+			return numInstances;
+		} catch (Exception e) {
+			throw new QueryServiceException(
+					"Failed to get size of query in Workflow Instances Database : "
+							+ e.getMessage(), e);
+		} finally {
+			try {
+				conn.close();
+			} catch (Exception e) {
+			}
+			try {
+				stmt.close();
+			} catch (Exception e) {
+			}
+			try {
+				rs.close();
+			} catch (Exception e) {
+			}
+		}
+	}
+	
+    private String getSqlQuery(QueryExpression queryExpression) throws QueryServiceException, UnsupportedEncodingException {
+        String sqlQuery = null;
+        if (queryExpression instanceof QueryLogicalGroup) {
+        	QueryLogicalGroup qlg = (QueryLogicalGroup) queryExpression;
+            sqlQuery = "(" + this.getSqlQuery(qlg.getExpressions().get(0));
+            String op = qlg.getOperator() == QueryLogicalGroup.Operator.AND ? "INTERSECT" : "UNION";
+            for (int i = 1; i < qlg.getExpressions().size(); i++) 
+                sqlQuery += ") " + op + " (" + this.getSqlQuery(qlg.getExpressions().get(i));
+            sqlQuery += ")";
+        }else if (queryExpression instanceof ComparisonQueryExpression){
+        	ComparisonQueryExpression cqe = (ComparisonQueryExpression) queryExpression;
+        	String operator = null;
+            if (cqe.getOperator().equals(ComparisonQueryExpression.Operator.EQUAL_TO)) {
+            	operator = "=";
+            } else if (cqe.getOperator().equals(ComparisonQueryExpression.Operator.GREATER_THAN)) {
+            	operator = ">";
+            } else if (cqe.getOperator().equals(ComparisonQueryExpression.Operator.GREATER_THAN_EQUAL_TO)) {
+            	operator = ">=";
+            } else if (cqe.getOperator().equals(ComparisonQueryExpression.Operator.LESS_THAN)) {
+            	operator = "<";
+            } else if (cqe.getOperator().equals(ComparisonQueryExpression.Operator.LESS_THAN_EQUAL_TO)) {
+            	operator = "<=";
+            } else {
+                throw new QueryServiceException("Invalid ComparisonQueryExpression Operator '" + cqe.getOperator() + "'");
+            }
+            
+            sqlQuery = "SELECT DISTINCT workflow_instance_id FROM workflow_instance_metadata WHERE workflow_met_key = '" + cqe.getTerm().getName() + "' AND (";
+        	for (int i = 0; i < cqe.getTerm().getValues().size(); i++) {
+        		String value = cqe.getTerm().getValues().get(i);
+                sqlQuery += "workflow_met_val " + operator + " '" + URLEncoder.encode(value, "UTF-8") + "'";
+	            if ((i + 1) < cqe.getTerm().getValues().size())
+	            	sqlQuery += "OR";
+        	}
+        	sqlQuery += ")";
+        }else if (queryExpression instanceof NotQueryExpression) {
+        	NotQueryExpression nqe = (NotQueryExpression) queryExpression;
+            sqlQuery = "SELECT DISTINCT workflow_instance_id FROM workflow_instance_metadata WHERE NOT (" + this.getSqlQuery(nqe.getQueryExpression()) + ")";
+        }else if (queryExpression instanceof StdQueryExpression) {
+            sqlQuery = "SELECT DISTINCT workflow_instance_id FROM workflow_instance_metadata";
+        }else {
+            throw new QueryServiceException("Invalid QueryExpression '" + queryExpression.getClass().getCanonicalName() + "'");
+        }
+        return sqlQuery;
+    }
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/WorkflowManagerDataSourceIndexFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/WorkflowManagerDataSourceIndexFactory.java
new file mode 100644
index 0000000..b7abe3c
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/index/WorkflowManagerDataSourceIndexFactory.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct.impl.index;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.struct.IndexFactory;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class WorkflowManagerDataSourceIndexFactory implements IndexFactory {
+
+    protected String jdbcUrl;
+    protected String user;
+    protected String pass;
+    protected String driver;
+	
+	public WorkflowManagerDataSourceIndex createIndex() {
+		try {
+			return new WorkflowManagerDataSourceIndex(this.user, this.pass, this.driver, this.jdbcUrl);
+		}catch (Exception e) {
+			//log
+			return null;
+		}
+	}
+
+	public void setJdbcUrl(String jdbcUrl) {
+		this.jdbcUrl = jdbcUrl;
+	}
+
+	public void setUser(String user) {
+		this.user = user;
+	}
+
+	public void setPass(String pass) {
+		this.pass = pass;
+	}
+
+	public void setDriver(String driver) {
+		this.driver = driver;
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/transaction/LongTransactionIdFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/transaction/LongTransactionIdFactory.java
new file mode 100644
index 0000000..1d8a573
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/transaction/LongTransactionIdFactory.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct.impl.transaction;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.struct.TransactionIdFactory;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class LongTransactionIdFactory implements TransactionIdFactory {
+
+	public TransactionId<?> createNewTransactionId() {
+		return new TransactionId<Long>(System.currentTimeMillis()) {
+
+			@Override
+			protected Long fromString(String stringId) {
+				return Long.parseLong(stringId);
+			}
+			
+		};
+	}
+
+	public TransactionId<?> createTransactionId(String transactionIdString) {
+		return new TransactionId<Long>(transactionIdString) {
+
+			@Override
+			protected Long fromString(String stringId) {
+				return Long.parseLong(stringId);
+			}
+			
+		};
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/transaction/StringTransactionIdFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/transaction/StringTransactionIdFactory.java
new file mode 100644
index 0000000..8e1bc18
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/transaction/StringTransactionIdFactory.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct.impl.transaction;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.struct.TransactionIdFactory;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class StringTransactionIdFactory implements TransactionIdFactory {
+
+	public TransactionId<String> createNewTransactionId() {
+		return new StringTransactionId(Long.toString(System.currentTimeMillis()));
+	}
+
+	public TransactionId<?> createTransactionId(String transactionIdString) {
+		return new StringTransactionId(transactionIdString);
+	}
+	
+	private class StringTransactionId extends TransactionId<String> {
+
+		public StringTransactionId(String stringValue) {
+			this.nativeId = stringValue;
+		}
+		
+		@Override
+		protected String fromString(String stringId) {
+			return stringId;
+		}
+		
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/transaction/UuidTransactionIdFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/transaction/UuidTransactionIdFactory.java
new file mode 100644
index 0000000..96aeda8
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/struct/impl/transaction/UuidTransactionIdFactory.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.struct.impl.transaction;
+
+//JDK imports
+import java.util.UUID;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.struct.TransactionIdFactory;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class UuidTransactionIdFactory implements TransactionIdFactory {
+
+	public TransactionId<?> createNewTransactionId() {
+		return new TransactionId<UUID>(UUID.randomUUID()) {
+
+			@Override
+			protected UUID fromString(String stringId) {
+				return UUID.fromString(stringId);
+			}
+			
+		};
+	}
+
+	public TransactionId<?> createTransactionId(String transactionIdString) {
+		return new TransactionId<UUID>(transactionIdString) {
+
+			@Override
+			protected UUID fromString(String stringId) {
+				return UUID.fromString(stringId);
+			}
+			
+		};
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/Catalog.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/Catalog.java
new file mode 100644
index 0000000..4f5fc93
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/Catalog.java
@@ -0,0 +1,385 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.system;
+
+//JDK imports
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogDictionaryException;
+import org.apache.oodt.cas.catalog.exception.CatalogException;
+import org.apache.oodt.cas.catalog.exception.CatalogIndexException;
+import org.apache.oodt.cas.catalog.exception.IngestServiceException;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.IndexPager;
+import org.apache.oodt.cas.catalog.page.IngestReceipt;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.struct.Dictionary;
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.IngestService;
+import org.apache.oodt.cas.catalog.struct.QueryService;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.struct.TransactionIdFactory;
+import org.apache.oodt.cas.catalog.term.Term;
+import org.apache.oodt.cas.catalog.term.TermBucket;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Calatog is a communication interface between the CatalogService and an underlying
+ * database or index service
+ * <p>
+ */
+public class Catalog {
+
+	private static Logger LOG = Logger.getLogger(Catalog.class.getName());
+		
+	protected Vector<Dictionary> dictionaries;
+	protected Index index;
+	protected String id;
+	protected boolean restrictQueryPermissions = true;
+	protected boolean restrictIngestPermissions = true;
+	
+	public Catalog(String id, Index index, List<Dictionary> dictionaries, boolean restrictQueryPermissions, boolean restrictIngestPermissions) {
+		this.id = id;
+		this.index = index;
+		if (dictionaries != null)
+			this.dictionaries = new Vector<Dictionary>(dictionaries);
+		this.restrictQueryPermissions = restrictQueryPermissions;
+		this.restrictIngestPermissions = restrictIngestPermissions;
+	}
+	
+	public String getId() {
+		return this.id;
+	}
+
+	public TransactionIdFactory getTransactionIdFactory() throws CatalogIndexException {
+		return this.index.getTransactionIdFactory();
+	}
+	
+	public void setIndex(Index index) {
+		this.index = index;
+	}
+	
+	public void setDictionaries(List<Dictionary> dictionaries) {
+		this.dictionaries = new Vector<Dictionary>(dictionaries);
+	}
+	
+	public List<Dictionary> getDictionaries() {
+		return Collections.unmodifiableList(this.dictionaries);
+	}
+	
+	public void addDictionary(Dictionary dictionary) {
+		if (this.dictionaries == null)
+			this.dictionaries = new Vector<Dictionary>();
+		this.dictionaries.add(dictionary);
+	}
+
+	public void setRestrictQueryPermissions(boolean restrictQueryPermissions) {
+		this.restrictQueryPermissions = restrictQueryPermissions;
+	}
+
+	public void setRestrictIngestPermissions(boolean restrictIngestPermissions) {
+		this.restrictIngestPermissions = restrictIngestPermissions;
+	}
+
+	public boolean isQueriable() {
+		return this.index instanceof QueryService && !this.restrictQueryPermissions;
+	}
+	
+	public boolean isIngestable() {
+		return this.index instanceof IngestService && !this.restrictIngestPermissions;
+	}
+	
+	public List<TransactionId<?>> getPage(IndexPager indexPage) throws CatalogIndexException {
+		return this.index.getPage(indexPage);
+	}
+	
+	public TransactionId<?> getTransactionIdFromString(String catalogTransactionId) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, CatalogIndexException {
+		return this.getTransactionIdFactory().createTransactionId(catalogTransactionId);
+	}
+	
+	public boolean hasTransactionId(TransactionId<?> catalogTransactionid)  throws CatalogIndexException {
+		return this.index.hasTransactionId(catalogTransactionid);
+	}
+	
+	public String getProperty(String key)  throws CatalogException {
+		try {
+			return this.index.getProperty(key);
+		}catch (Exception e) {
+			throw new CatalogException("Failed to get property '" + key + "' : " + e.getMessage(), e);
+		}
+	}
+	
+	public Properties getProperties() throws CatalogException {
+		try {
+			return this.index.getProperties();
+		}catch (Exception e) {
+			throw new CatalogException("Failed to get properties : " + e.getMessage(), e);
+		}
+	}
+	
+	/**
+	 * 
+	 * @param transactionId
+	 * @param metadata
+	 * @return TransactionId param if used by underlying catalog, otherwise
+	 * the TransactionId generated and used by underlying catalog.  if no
+	 * TermBuckets where created from the Metadata then null is returned
+	 * @throws IngestServiceException
+	 */
+	public CatalogReceipt ingest(Metadata metadata) throws CatalogException {
+		try {
+			if (this.isIngestable()) {
+				List<TermBucket> termBuckets = this.getTermBuckets(metadata);
+				if (termBuckets.size() > 0) {
+					LOG.log(Level.INFO, "Catalog '" + this + "' attemping ingest metadata");
+					return new CatalogReceipt(((IngestService) this.index).ingest(termBuckets), this.getId());
+				}else {
+					LOG.log(Level.WARNING, "Catalog '" + this + "' dictionaries did not generate any TermBuckets from Metadata");
+					return null;
+				}
+			}else {
+				LOG.log(Level.WARNING, "Catalog '" + this + "' is not ingestable");
+				return null;
+			}
+		}catch (Exception e) {
+			throw new CatalogException(e.getMessage(), e);
+		}
+	}
+	
+	public CatalogReceipt update(TransactionId<?> transactionId, Metadata metadata) throws CatalogException {
+		try {
+			if (this.isIngestable()) {
+				List<TermBucket> termBuckets = this.getTermBuckets(metadata);
+				if (termBuckets.size() > 0) {
+					LOG.log(Level.INFO, "Catalog '" + this + "' attemping update metadata for catalog TransactionId [id = '" + transactionId + "']");
+					IngestReceipt ingestReceipt = ((IngestService) this.index).update(transactionId, termBuckets);
+					if (ingestReceipt != null)
+						return new CatalogReceipt(ingestReceipt, this.getId());
+					else
+						return null;
+				}else {
+					LOG.log(Level.WARNING, "Catalog '" + this + "' did not generate any TermBuckets from Metadata for catalog TransactionId [id = '" + transactionId + "']");
+					return null;
+				}
+			}else {
+				LOG.log(Level.WARNING, "Catalog '" + this + "' is not ingestable");
+				return null;
+			}
+		}catch (Exception e) {
+			throw new CatalogException(e.getMessage(), e);
+		}
+	}
+	
+	public boolean delete(TransactionId<?> transactionId) throws CatalogException {
+		try {
+			if (this.isIngestable()) {
+				LOG.log(Level.INFO, "Catalog '" + this + "' attemping to delete all TermBuckets associated with catalog TransactionId [id = '" + transactionId + "']");
+				return ((IngestService) this.index).delete(transactionId);
+			}else {
+				LOG.log(Level.WARNING, "Catalog '" + this + "' is not ingestable");
+				return false;
+			}
+		}catch (Exception e) {
+			throw new CatalogException(e.getMessage(), e);
+		}
+	}
+	
+	public boolean reduce(TransactionId<?> transactionId, Metadata metadata) throws CatalogException {
+		try {
+			if (this.isIngestable()) {
+				List<TermBucket> termBuckets = this.getTermBuckets(metadata);
+				if (termBuckets.size() > 0) {
+					LOG.log(Level.INFO, "Catalog '" + this + "' attemping reduce metadata for catalog TransactionId [id = '" + transactionId + "']");
+					return ((IngestService) this.index).reduce(transactionId, termBuckets);
+				}else {
+					LOG.log(Level.WARNING, "Catalog '" + this + "' did not generate any TermBuckets from Metadata for catalog TransactionId [id = '" + transactionId + "'] -- no metadata reduction took place");
+					return false;
+				}
+			}else {
+				LOG.log(Level.WARNING, "Catalog '" + this + "' is not ingestable");
+				return false;
+			}
+		}catch(Exception e) {
+			throw new CatalogException(e.getMessage(), e);
+		}
+	}
+		
+	public List<CatalogReceipt> query(QueryExpression queryExpression) throws CatalogException {
+		try {
+			if (this.isQueriable()) {
+				QueryService queryService = (QueryService) this.index;
+				List<CatalogReceipt> catalogReceipts = new Vector<CatalogReceipt>();
+				for (IngestReceipt ingestReceipt : queryService.query(queryExpression)) 
+					catalogReceipts.add(new CatalogReceipt(ingestReceipt, this.getId()));
+				return Collections.unmodifiableList(catalogReceipts);
+			}else {
+				LOG.log(Level.WARNING, "Catalog '" + this + "' is not queriable");
+				return Collections.emptyList();
+			}
+		}catch (Exception e) {
+			throw new CatalogException(e.getMessage(), e);
+		}
+	}
+	
+
+	public List<CatalogReceipt> query(QueryExpression queryExpression, int startIndex, int endIndex) throws CatalogException {
+		try {
+			if (this.isQueriable()) {
+				QueryService queryService = (QueryService) this.index;
+				List<CatalogReceipt> catalogReceipts = new Vector<CatalogReceipt>();
+				for (IngestReceipt ingestReceipt : queryService.query(queryExpression, startIndex, endIndex)) 
+					catalogReceipts.add(new CatalogReceipt(ingestReceipt, this.getId()));
+				return Collections.unmodifiableList(catalogReceipts);
+			}else {
+				LOG.log(Level.WARNING, "Catalog '" + this + "' is not queriable");
+				return Collections.emptyList();
+			}
+		}catch (Exception e) {
+			throw new CatalogException(e.getMessage(), e);
+		}
+	}
+	
+	public int sizeOf(QueryExpression queryExpression) throws CatalogException {
+		try {
+			if (this.isQueriable()) {
+				QueryService queryService = (QueryService) this.index;
+				return queryService.sizeOf(queryExpression);
+			}else {
+				LOG.log(Level.WARNING, "Catalog '" + this + "' is not queriable");
+				return 0;
+			}
+		}catch (Exception e) {
+			throw new CatalogException(e.getMessage(), e);
+		}
+	}
+	
+	public Metadata getMetadata(TransactionId<?> transactionId) throws CatalogException {
+		try {
+			if (this.isQueriable()) {
+				QueryService queryService = (QueryService) this.index;
+				return this.getMetadataFromBuckets(queryService.getBuckets(transactionId));
+			}else { 
+				LOG.log(Level.WARNING, "Catalog '" + this + "' is not queriable");
+				return new Metadata();
+			}
+		}catch(Exception e) {
+			throw new CatalogException(e.getMessage(), e);
+		}
+	}
+	
+	public Map<TransactionId<?>, Metadata> getMetadata(List<TransactionId<?>> transactionIds) throws CatalogException {
+		try {
+			Map<TransactionId<?>, Metadata> metadataMap = new HashMap<TransactionId<?>, Metadata>();
+			if (this.isQueriable()) {
+				QueryService queryService = (QueryService) this.index;
+				Map<TransactionId<?>, List<TermBucket>> termBucketMap = queryService.getBuckets(transactionIds);
+				for (TransactionId<?> transactionId : termBucketMap.keySet())
+					metadataMap.put(transactionId, this.getMetadataFromBuckets(termBucketMap.get(transactionId)));
+			}else {
+				LOG.log(Level.WARNING, "Catalog '" + this + "' is not queriable");
+			}
+			return metadataMap;
+		}catch(Exception e) {
+			throw new CatalogException(e.getMessage(), e);
+		}
+	}
+	
+	public boolean isInterested(QueryExpression queryExpression) throws CatalogException {
+		try {
+			if (this.dictionaries != null) {
+				for (Dictionary dictionary : this.dictionaries)
+					if (dictionary.understands(queryExpression))
+						return true;
+				return false;
+			}else {
+				return true;
+			}
+		}catch(Exception e) {
+			throw new CatalogException(e.getMessage(), e);
+		}
+	}
+	
+	protected Metadata getMetadataFromBuckets(List<TermBucket> termBuckets) throws CatalogDictionaryException {
+		Metadata metadata = new Metadata();
+		for (TermBucket termBucket : termBuckets) {
+			if (this.dictionaries != null) {
+				for (Dictionary dictionary : this.dictionaries) 
+					metadata.addMetadata(dictionary.reverseLookup(termBucket));
+			}else {
+				metadata.addMetadata(this.asMetadata(termBuckets));
+			}
+		}
+		return metadata;
+	}
+	
+	protected Metadata asMetadata(List<TermBucket> termBuckets) {
+		Metadata m = new Metadata();
+		for (TermBucket bucket : termBuckets)
+			for (Term term : bucket.getTerms())
+				m.addMetadata(term.getName(), term.getValues());
+		return m;
+	}
+    
+	protected List<TermBucket> getTermBuckets(Metadata metadata) throws CatalogDictionaryException {
+		List<TermBucket> termBuckets = new Vector<TermBucket>();
+		if (this.dictionaries != null) {
+			for (Dictionary dictionary : this.dictionaries) {
+				TermBucket termBucket = dictionary.lookup(metadata);
+				if (termBucket != null)
+					termBuckets.add(termBucket);
+			}
+		}else {
+			LOG.log(Level.WARNING, "Catalog '" + this + "' has no dictionaries defined, attempting to send all Metadata in a default TermBucket");
+			TermBucket bucket = new TermBucket();
+			for (String key : metadata.getAllKeys())
+				bucket.addTerm(new Term(key, metadata.getAllMetadata(key)));
+			termBuckets.add(bucket);
+		}
+		return termBuckets;
+	}
+	
+	public int hashCode() {
+		return this.toString().hashCode();
+	}
+	
+	public boolean equals(Object obj) {
+		if (obj instanceof Catalog) 
+			return ((Catalog) obj).getId().equals(this.getId());
+		else if (obj instanceof String) 
+			return this.getId().equals((String) obj);
+		else
+			return false;
+	}
+	
+    public String toString() {
+    	return this.getId();
+    }
+		
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/CatalogFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/CatalogFactory.java
new file mode 100644
index 0000000..d01b945
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/CatalogFactory.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.system;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+//OOD imports
+import org.apache.oodt.cas.catalog.struct.Dictionary;
+import org.apache.oodt.cas.catalog.struct.DictionaryFactory;
+import org.apache.oodt.cas.catalog.struct.IndexFactory;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class CatalogFactory {
+
+	protected String catalogId;
+	protected IndexFactory indexFactory;
+	protected List<DictionaryFactory> dictionaryFactories;
+	protected boolean restrictQueryPermissions;
+	protected boolean restrictIngestPermissions;
+	
+	public Catalog createCatalog() {
+		Vector<Dictionary> dictionaries = null;
+		if (this.dictionaryFactories != null) {
+			dictionaries = new Vector<Dictionary>();
+			for (DictionaryFactory dictionaryFactory : this.dictionaryFactories)
+				dictionaries.add(dictionaryFactory.createDictionary());
+		}
+		return new Catalog(this.catalogId, this.indexFactory.createIndex(), dictionaries, this.restrictQueryPermissions, this.restrictIngestPermissions);
+	}
+
+	@Required
+	public void setCatalogId(String catalogId) {
+		this.catalogId = catalogId;
+	}
+
+	@Required
+	public void setIndexFactory(IndexFactory indexFactory) {
+		this.indexFactory = indexFactory;
+	}
+
+	@Required
+	public void setDictionaryFactories(List<DictionaryFactory> dictionaryFactories) {
+		this.dictionaryFactories = dictionaryFactories;
+	}
+
+	@Required
+	public void setRestrictQueryPermissions(boolean restrictQueryPermissions) {
+		this.restrictQueryPermissions = restrictQueryPermissions;
+	}
+
+	@Required
+	public void setRestrictIngestPermissions(boolean restrictIngestPermissions) {
+		this.restrictIngestPermissions = restrictIngestPermissions;
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/CatalogService.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/CatalogService.java
new file mode 100644
index 0000000..05374d4
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/CatalogService.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.system;
+
+//JDK imports
+import java.net.URL;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogServiceException;
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.Page;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.page.TransactionReceipt;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.struct.Dictionary;
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.util.PluginURL;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * An interface for a Metadata Catalog Manager Service
+ * <p>
+ */
+public interface CatalogService {
+		
+	public static final String CATALOG_SERVICE_TRANSACTION_ID_MET_KEY = "urn:CatalogService:TransactionId";
+	public static final String CATALOG_IDS_MET_KEY = "urn:CatalogService:CatalogIds";
+	public static final String ENABLE_UPDATE_MET_KEY = "urn:CatalogService:EnableUpdate";
+	public static final String CATALOG_TRANSACTION_ID_MET_KEY = "urn:Catalog:TransactionId";
+	public static final String CATALOG_ID_MET_KEY = "urn:Catalog:Id";
+
+	public void shutdown() throws CatalogServiceException;
+	
+	public boolean isRestrictQueryPermissions() throws CatalogServiceException;
+
+	public boolean isRestrictIngestPermissions() throws CatalogServiceException;
+
+	public void addCatalog(Catalog catalog) throws CatalogServiceException;
+	
+	public void replaceCatalog(Catalog catalog) throws CatalogServiceException;
+	
+	public void addCatalog(String catalogId, Index index) throws CatalogServiceException;
+	
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries) throws CatalogServiceException;
+
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries, boolean restrictQueryPermission, boolean restrictIngestPermission) throws CatalogServiceException;
+
+	public void addDictionary(String catalogId, Dictionary dictionary) throws CatalogServiceException;
+
+	public void replaceDictionaries(String catalogId, List<Dictionary> dictionaries) throws CatalogServiceException;
+	
+	public void replaceIndex(String catalogId, Index index) throws CatalogServiceException;
+
+	public void modifyIngestPermission(String catalogId, boolean restrictIngestPermission) throws CatalogServiceException;
+	
+	public void modifyQueryPermission(String catalogId, boolean restrictQueryPermission) throws CatalogServiceException;
+		
+	public void removeCatalog(String catalogId) throws CatalogServiceException;
+
+	public URL getPluginStorageDir() throws CatalogServiceException;
+	
+	public List<PluginURL> getPluginUrls() throws CatalogServiceException;
+
+	public void addPluginUrls(List<PluginURL> pluginURLs) throws CatalogServiceException;
+
+	public Set<String> getCurrentCatalogIds() throws CatalogServiceException;
+		
+	public TransactionReceipt ingest(Metadata metadata) throws CatalogServiceException;
+	
+	public void delete(Metadata metadata) throws CatalogServiceException;
+	
+	public List<String> getProperty(String key) throws CatalogServiceException;
+
+	public Properties getCalalogProperties() throws CatalogServiceException;
+	
+	public Properties getCalalogProperties(String catalogUrn) throws CatalogServiceException;
+	
+	public Page getNextPage(Page page) throws CatalogServiceException;
+		
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression) throws CatalogServiceException;
+	
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression, Set<String> catalogIds) throws CatalogServiceException;
+
+	public List<TransactionalMetadata> getMetadata(Page page) throws CatalogServiceException;
+	
+	public QueryPager query(QueryExpression queryExpression) throws CatalogServiceException;
+
+	public QueryPager query(QueryExpression queryExpression, Set<String> catalogIds) throws CatalogServiceException;
+	 
+	public List<TransactionalMetadata> getNextPage(QueryPager queryPager) throws CatalogServiceException;
+	
+	public List<TransactionalMetadata> getAllPages(QueryPager queryPager) throws CatalogServiceException;
+	
+	public List<TransactionalMetadata> getMetadataFromTransactionIdStrings(List<String> catalogServiceTransactionIdStrings) throws CatalogServiceException;
+	
+	public List<TransactionalMetadata> getMetadataFromTransactionIds(List<TransactionId<?>> catalogServiceTransactionIds) throws CatalogServiceException;
+	
+	public List<TransactionId<?>> getCatalogServiceTransactionIds(List<TransactionId<?>> catalogTransactionIds, String catalogUrn) throws CatalogServiceException;
+	
+	public TransactionId<?> getCatalogServiceTransactionId(TransactionId<?> catalogTransactionId, String catalogUrn) throws CatalogServiceException;
+	
+	public TransactionId<?> getCatalogServiceTransactionId(CatalogReceipt catalogReceipt, boolean generateNew) throws CatalogServiceException;
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/CatalogServiceFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/CatalogServiceFactory.java
new file mode 100644
index 0000000..7ced6ce
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/CatalogServiceFactory.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.system;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory for CatalogService
+ * <p>
+ */
+public interface CatalogServiceFactory {
+
+	public CatalogService createCatalogService();
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/impl/CatalogServiceClient.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/impl/CatalogServiceClient.java
new file mode 100644
index 0000000..623d8b0
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/impl/CatalogServiceClient.java
@@ -0,0 +1,407 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.system.impl;
+
+//JDK imports
+import java.io.File;
+import java.net.URL;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogServiceException;
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.Page;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.page.TransactionReceipt;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.server.channel.CommunicationChannelClient;
+import org.apache.oodt.cas.catalog.struct.Dictionary;
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.system.CatalogService;
+import org.apache.oodt.cas.catalog.util.PluginURL;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Client that appears to be a CatalogService, but communicates with a CatalogService Server
+ * <p>
+ */
+public class CatalogServiceClient implements CatalogService {
+
+	protected CommunicationChannelClient communicationChannelClient;
+	protected int autoPagerSize;
+	
+	public CatalogServiceClient(CommunicationChannelClient communicationChannelClient, int autoPagerSize) {
+		this.communicationChannelClient = communicationChannelClient;
+		this.autoPagerSize = autoPagerSize;
+	}
+	
+	public void shutdown() throws CatalogServiceException  {
+		try {
+			this.communicationChannelClient.shutdown();
+		}catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	protected List<PluginURL> transferToServerSide(List<PluginURL> clientSideUrls) throws CatalogServiceException {
+		try {
+			URL customUrlStorageDir = this.communicationChannelClient.getPluginStorageDir();
+			System.out.println("Got Tmp dir : " + customUrlStorageDir);
+			Vector<PluginURL> serverSideUrls = new Vector<PluginURL>();
+			for (PluginURL pluginURL : clientSideUrls) {
+				PluginURL serverSideURL = new PluginURL(pluginURL.getCatalogId(), new URL(customUrlStorageDir, new File(pluginURL.getURL().getFile()).getName()));
+				System.out.println("generated server side url : " + customUrlStorageDir);
+				this.communicationChannelClient.transferUrl(pluginURL.getURL(), serverSideURL.getURL());
+				serverSideUrls.add(serverSideURL);
+			}
+			return serverSideUrls;
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+		
+	public void addCatalog(Catalog catalog) throws CatalogServiceException {
+		try {
+			this.communicationChannelClient.addCatalog(catalog);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public void replaceCatalog(Catalog catalog)
+			throws CatalogServiceException {
+		try {
+			this.communicationChannelClient.replaceCatalog(catalog);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	public void addCatalog(String catalogId, Index index)
+			throws CatalogServiceException {
+		try {
+			this.communicationChannelClient.addCatalog(catalogId, index);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries) throws CatalogServiceException {
+		try {
+			this.communicationChannelClient.addCatalog(catalogId, index, dictionaries);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries, boolean restrictQueryPermission,
+			boolean restrictIngestPermission) throws CatalogServiceException {
+		try {
+			this.communicationChannelClient.addCatalog(catalogId, index, dictionaries, restrictQueryPermission, restrictIngestPermission);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public void addDictionary(String catalogId, Dictionary dictionary)
+			throws CatalogServiceException {
+		try {
+			this.communicationChannelClient.addDictionary(catalogId, dictionary);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public void replaceDictionaries(String catalogId, List<Dictionary> dictionaries) throws CatalogServiceException {
+		try {
+			this.communicationChannelClient.replaceDictionaries(catalogId, dictionaries);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	public void modifyIngestPermission(String catalogId,
+			boolean restrictIngestPermission) throws CatalogServiceException {
+		try {
+			this.communicationChannelClient.modifyIngestPermission(catalogId, restrictIngestPermission);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public void modifyQueryPermission(String catalogId,
+			boolean restrictQueryPermission) throws CatalogServiceException {
+		try {
+			this.communicationChannelClient.modifyQueryPermission(catalogId, restrictQueryPermission);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public void replaceIndex(String catalogId, Index index)
+			throws CatalogServiceException {
+		try {
+			this.communicationChannelClient.replaceIndex(catalogId, index);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	public void removeCatalog(String catalogId) throws CatalogServiceException {
+		try {
+			this.communicationChannelClient.removeCatalog(catalogId);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	public URL getPluginStorageDir() throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getPluginStorageDir();
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	public List<PluginURL> getPluginUrls() throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getPluginUrls();
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public void addPluginUrls(List<PluginURL> urls) throws CatalogServiceException {
+		try {
+			this.communicationChannelClient.addPluginUrls(this.transferToServerSide(urls));
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	public void delete(Metadata metadata) throws CatalogServiceException {
+		try {
+			this.communicationChannelClient.delete(metadata);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public List<TransactionalMetadata> getAllPages(QueryPager queryPager)
+			throws CatalogServiceException {
+		try {
+			List<TransactionalMetadata> metadata = new Vector<TransactionalMetadata>();
+			if (queryPager.getTotalPages() > 0) {
+				queryPager.setPageInfo(new PageInfo(this.autoPagerSize, PageInfo.FIRST_PAGE));
+				while (!queryPager.isLastPage()) {
+					metadata.addAll(this.communicationChannelClient.getNextPage(queryPager));
+					queryPager.incrementPageNumber();
+				}
+				metadata.addAll(this.communicationChannelClient.getNextPage(queryPager));
+			}
+			return metadata;
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public Properties getCalalogProperties() throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getCalalogProperties();
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public Properties getCalalogProperties(String catalogUrn)
+			throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getCalalogProperties(catalogUrn);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public TransactionId<?> getCatalogServiceTransactionId(
+			TransactionId<?> catalogTransactionId, String catalogUrn)
+			throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getCatalogServiceTransactionId(catalogTransactionId, catalogUrn);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public TransactionId<?> getCatalogServiceTransactionId(
+			CatalogReceipt catalogReceipt, boolean generateNew) throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getCatalogServiceTransactionId(catalogReceipt, generateNew);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public List<TransactionId<?>> getCatalogServiceTransactionIds(
+			List<TransactionId<?>> catalogTransactionIds, String catalogUrn)
+			throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getCatalogServiceTransactionIds(catalogTransactionIds, catalogUrn);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public Set<String> getCurrentCatalogIds() throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getCurrentCatalogIds();
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public List<TransactionalMetadata> getMetadataFromTransactionIdStrings(
+			List<String> catalogServiceTransactionIdStrings)
+			throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getMetadataFromTransactionIdStrings(catalogServiceTransactionIdStrings);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public List<TransactionalMetadata> getMetadataFromTransactionIds(
+			List<TransactionId<?>> catalogServiceTransactionIds)
+			throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getMetadataFromTransactionIds(catalogServiceTransactionIds);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public List<TransactionalMetadata> getNextPage(QueryPager queryPager)
+			throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getNextPage(queryPager);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public List<String> getProperty(String key) throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getProperty(key);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public List<TransactionId<?>> getTransactionIdsForAllPages(
+			QueryPager queryPager) throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getTransactionIdsForAllPages(queryPager);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public TransactionReceipt ingest(Metadata metadata)
+			throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.ingest(metadata);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public boolean isRestrictIngestPermissions() throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.isRestrictIngestPermissions();
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+	public boolean isRestrictQueryPermissions() throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.isRestrictQueryPermissions();
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	public Page getNextPage(Page page) throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getNextPage(page);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression) throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getPage(pageInfo, queryExpression);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression, Set<String> catalogIds) throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getPage(pageInfo, queryExpression, catalogIds);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	public List<TransactionalMetadata> getMetadata(Page page) throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.getMetadata(page);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	public QueryPager query(QueryExpression queryExpression)
+			throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.query(queryExpression);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	public QueryPager query(QueryExpression queryExpression, Set<String> catalogIds) throws CatalogServiceException {
+		try {
+			return this.communicationChannelClient.query(queryExpression, catalogIds);
+		} catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/impl/CatalogServiceClientFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/impl/CatalogServiceClientFactory.java
new file mode 100644
index 0000000..26a5fe6
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/impl/CatalogServiceClientFactory.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.system.impl;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.server.channel.CommunicationChannelClientFactory;
+import org.apache.oodt.cas.catalog.system.CatalogServiceFactory;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+//OODT imports
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory for CatalogServiceClient
+ * <p>
+ */
+public class CatalogServiceClientFactory implements CatalogServiceFactory {
+	
+	protected CommunicationChannelClientFactory communicationChannelClientFactory;
+	protected int autoPagerSize;
+	
+	public CatalogServiceClientFactory() {
+		this.autoPagerSize = 500;
+	}
+	
+	public CatalogServiceClient createCatalogService() {
+		return new CatalogServiceClient(this.communicationChannelClientFactory.createCommunicationChannelClient(), this.autoPagerSize);
+	}
+	
+	@Required
+	public void setCommunicationChannelClientFactory(CommunicationChannelClientFactory communicationChannelClientFactory) {
+		this.communicationChannelClientFactory = communicationChannelClientFactory;
+	}
+	
+	@Required
+	public void setAutoPagerSize(int autoPagerSize) {
+		if (autoPagerSize > 0)
+			this.autoPagerSize = autoPagerSize;
+	}
+	
+	public String getServerUrl() {
+		return this.communicationChannelClientFactory.getServerUrl();
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/impl/CatalogServiceLocal.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/impl/CatalogServiceLocal.java
new file mode 100644
index 0000000..dddb9b9
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/impl/CatalogServiceLocal.java
@@ -0,0 +1,1269 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.system.impl;
+
+//JDK imports
+import java.io.File;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+import java.util.Map.Entry;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.exception.CatalogDictionaryException;
+import org.apache.oodt.cas.catalog.exception.CatalogException;
+import org.apache.oodt.cas.catalog.exception.CatalogIndexException;
+import org.apache.oodt.cas.catalog.exception.CatalogServiceException;
+import org.apache.oodt.cas.catalog.mapping.IngestMapper;
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.CatalogReceipt;
+import org.apache.oodt.cas.catalog.page.Page;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.page.ProcessedPageInfo;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.page.TransactionReceipt;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.query.QueryLogicalGroup;
+import org.apache.oodt.cas.catalog.query.WrapperQueryExpression;
+import org.apache.oodt.cas.catalog.repository.CatalogRepository;
+import org.apache.oodt.cas.catalog.struct.Dictionary;
+import org.apache.oodt.cas.catalog.struct.Index;
+import org.apache.oodt.cas.catalog.struct.TransactionId;
+import org.apache.oodt.cas.catalog.struct.TransactionIdFactory;
+import org.apache.oodt.cas.catalog.system.Catalog;
+import org.apache.oodt.cas.catalog.system.CatalogService;
+import org.apache.oodt.cas.catalog.util.PluginURL;
+import org.apache.oodt.cas.catalog.util.QueryUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Calatog Service that manages Metadata via one or more underlying Catalogs
+ * <p>
+ */
+public class CatalogServiceLocal implements CatalogService {
+	
+	private static Logger LOG = Logger.getLogger(CatalogServiceLocal.class.getName());
+	
+	protected Set<Catalog> catalogs;
+	protected ReadWriteLock catalogsLock;
+	protected CatalogRepository catalogRepository;
+	protected IngestMapper ingestMapper;
+	protected ReadWriteLock ingestMapperLock;
+	protected boolean restrictQueryPermissions;
+	protected boolean restrictIngestPermissions;
+	protected TransactionIdFactory transactionIdFactory;
+	protected File pluginStorageDir;
+	protected boolean oneCatalogFailsAllFail;
+	protected boolean simplifyQueries;
+	protected boolean disableIntersectingCrossCatalogQueries;
+	protected int crossCatalogResultSortingThreshold;
+	
+	public CatalogServiceLocal(CatalogRepository catalogRepository, IngestMapper ingestMapper, File pluginStorageDir, TransactionIdFactory transactionIdFactory, boolean restrictQueryPermissions, boolean restrictIngestPermissions, boolean oneCatalogFailsAllFail, boolean simplifyQueries, boolean disableIntersectingCrossCatalogQueries, int crossCatalogResultSortingThreshold) throws InstantiationException {
+		try {
+			this.catalogs = new HashSet<Catalog>();
+			this.catalogsLock = new ReentrantReadWriteLock();
+			this.ingestMapperLock = new ReentrantReadWriteLock();
+			this.setPluginStorageDir(pluginStorageDir);
+			this.setRestrictQueryPermissions(restrictQueryPermissions);
+			this.setRestrictIngestPermissions(restrictIngestPermissions);
+			this.setTransactionIdFactory(transactionIdFactory);
+			this.setIngestMapper(ingestMapper);
+			this.setCatalogRepository(catalogRepository);	
+			this.oneCatalogFailsAllFail = oneCatalogFailsAllFail;
+			this.simplifyQueries = simplifyQueries;
+			this.disableIntersectingCrossCatalogQueries = disableIntersectingCrossCatalogQueries;
+			this.crossCatalogResultSortingThreshold = crossCatalogResultSortingThreshold;
+		}catch (Exception e) {
+			e.printStackTrace();
+			throw new InstantiationException(e.getMessage());
+		}
+	}
+	
+	/**
+	 * Set the CatalogRepository for this CatalogService, with replace existing CatalogRepository
+	 * and immediately load all Catalogs from it.
+	 * @param repository The CatalogRepository to be used by this CatalogService
+	 * @throws CatalogServiceException On Error loading given CatalogRepository
+	 */
+	protected void setCatalogRepository(CatalogRepository catalogRepository) throws CatalogServiceException {
+		if (catalogRepository != null) {
+			this.catalogsLock.writeLock().lock();
+			CatalogRepository backupRepository = null;
+			Set<Catalog> backupCatalogs = null;
+			try {
+				LOG.log(Level.INFO, "Using CatalogRepository '" + catalogRepository.getClass().getName() + "'");
+				backupRepository = this.catalogRepository;
+				backupCatalogs = new HashSet<Catalog>(this.catalogs);
+				LOG.log(Level.INFO, "Loading Catalogs from CatalogRepository . . .");
+				this.catalogs = catalogRepository.deserializeAllCatalogs();
+				LOG.log(Level.INFO, "Loaded Catalogs: '" + this.catalogs + "'");
+				this.catalogRepository = catalogRepository;
+			}catch (Exception e) {
+				this.catalogs = backupCatalogs;
+				this.catalogRepository = backupRepository;
+				throw new CatalogServiceException("Failed to set CatalogRepository '" + catalogRepository + "', reverting back to original settings : " + e.getMessage(), e);
+			}finally {
+				this.catalogsLock.writeLock().unlock();
+			}
+		}else {
+			throw new CatalogServiceException("Cannot add NULL CatalogRepository to CatalogService, reverting back to original settings");
+		}
+	}
+
+	protected void setIngestMapper(IngestMapper ingestMapper) {
+		this.ingestMapperLock.writeLock().lock();
+		try {
+			LOG.log(Level.INFO, "Using IngestMapper '" + ingestMapper.getClass().getName() + "'");
+			this.ingestMapper = ingestMapper;
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed to set ingest mapper : " + e.getMessage(), e);
+		}finally {
+			this.ingestMapperLock.writeLock().unlock();
+		}
+	}
+
+	public void shutdown() throws CatalogServiceException {
+		this.catalogsLock.writeLock().lock();
+		this.ingestMapperLock.writeLock().lock();
+	}
+	
+	/**
+	 * Returns true if this CatalogService is restricting any queries
+	 * from being made to the Catalogs it is managing
+	 * @return True is restricting queries, false if restriction is
+	 * on a per Catalog bases.
+	 */
+	public boolean isRestrictQueryPermissions() {
+		return this.restrictIngestPermissions;
+	}
+
+	/**
+	 * Modify this CatalogServices query restriction, default is false.
+	 * @param restrictQueryPermissions True to block all querys to managing
+	 * Catalogs or false to leave it at a per Catalog bases.
+	 */
+	protected void setRestrictQueryPermissions(boolean restrictQueryPermissions) {
+		this.restrictQueryPermissions = restrictQueryPermissions;
+	}
+
+	/**
+	 * Returns true if this CatalogService is restricting any ingestions
+	 * from being made to the Catalogs it is managing
+	 * @return True is restricting ingestions, false if restriction is
+	 * on a per Catalog bases.
+	 */
+	public boolean isRestrictIngestPermissions() {
+		return this.restrictIngestPermissions;
+	}
+
+	/**
+	 * Modify this CatalogServices ingest restriction, default is false.
+	 * @param restrictIngestPermissions True to block all ingestions to managing
+	 * Catalogs or false to leave it at a per Catalog bases.
+	 */
+	protected void setRestrictIngestPermissions(boolean restrictIngestPermissions) {
+		this.restrictIngestPermissions = restrictIngestPermissions;
+	}
+
+	/**
+	 * 
+	 * @param transactionIdClass
+	 */
+	protected void setTransactionIdFactory(
+			TransactionIdFactory transactionIdFactory) {
+		this.transactionIdFactory = transactionIdFactory;
+	}
+	
+	public void addCatalog(String catalogId, Index index) throws CatalogServiceException {
+		if (!this.containsCatalog(catalogId)) {
+			try {
+				this.replaceCatalog(new Catalog(catalogId, index, null, false, false));
+			}catch (Exception e) {
+				
+			}
+		} else {
+			LOG.log(Level.WARNING, "Attempt to override an existing catalog '" + catalogId + "' already used in CatalogService, remedy and retry add -- no changes took place!");
+		}
+	}
+	
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries) throws CatalogServiceException {
+		if (!this.containsCatalog(catalogId)) {
+			try {
+				this.replaceCatalog(new Catalog(catalogId, index, dictionaries, false, false));
+			}catch (Exception e) {
+				
+			}
+		} else {
+			LOG.log(Level.WARNING, "Attempt to override an existing catalog '" + catalogId + "' already used in CatalogService, remedy and retry add -- no changes took place!");
+		}
+	}
+
+	public void addCatalog(String catalogId, Index index, List<Dictionary> dictionaries, boolean restrictQueryPermission, boolean restrictIngestPermission) throws CatalogServiceException {
+		if (!this.containsCatalog(catalogId)) {
+			try {
+				this.replaceCatalog(new Catalog(catalogId, index, dictionaries, restrictQueryPermission, restrictIngestPermission));
+			}catch (Exception e) {
+				
+			}
+		} else {
+			LOG.log(Level.WARNING, "Attempt to override an existing catalog '" + catalogId + "' already used in CatalogService, remedy and retry add -- no changes took place!");
+		}
+	}
+
+	public void addDictionary(String catalogId, Dictionary dictionary) throws CatalogServiceException {
+		if (this.containsCatalog(catalogId)) {
+			Set<Catalog> backupCatalogs = null;
+			this.catalogsLock.writeLock().lock();
+			try {
+				backupCatalogs = new HashSet<Catalog>(this.catalogs);
+				for (Catalog catalog : this.catalogs) {
+					if (catalog.getId().equals(catalogId)) {
+						catalog.addDictionary(dictionary);
+						this.catalogRepository.serializeCatalog(catalog);
+						break;
+					}
+				}
+			}catch (Exception e) {
+				this.catalogs = backupCatalogs;
+				throw new CatalogServiceException("Failed to serialize Catalog '" + catalogId + "' -- if CatalogService goes down, Catalog will have to be readded : " + e.getMessage(), e);
+			}finally {
+				this.catalogsLock.writeLock().unlock();
+			}
+		} else {
+			LOG.log(Level.WARNING, "Attempt to change an existing catalog '" + catalogId + "' already used in CatalogService, remedy and retry add -- no changes took place!");
+		}
+	}
+	
+	public void replaceDictionaries(String catalogId, List<Dictionary> dictionaries) throws CatalogServiceException {
+		this.modifyCatalog(catalogId, dictionaries, null, null, null);
+	}
+
+	public void replaceIndex(String catalogId, Index index) throws CatalogServiceException {
+		this.modifyCatalog(catalogId, null, index, null, null);
+	}
+
+	public void modifyIngestPermission(String catalogId, boolean restrictIngestPermission) throws CatalogServiceException {
+		this.modifyCatalog(catalogId, null, null, null, restrictIngestPermission);
+	}
+	
+	public void modifyQueryPermission(String catalogId, boolean restrictQueryPermission) throws CatalogServiceException {
+		this.modifyCatalog(catalogId, null, null, restrictQueryPermission, null);
+	}
+	
+	protected void modifyCatalog(String catalogId, List<Dictionary> dictionaries, Index index, Boolean restrictQueryPermission, Boolean restrictIngestPermission) throws CatalogServiceException {
+		if (this.containsCatalog(catalogId)) {
+			Set<Catalog> backupCatalogs = null;
+			this.catalogsLock.writeLock().lock();
+			try {
+				backupCatalogs = new HashSet<Catalog>(this.catalogs);
+				for (Catalog catalog : this.catalogs) {
+					if (catalog.getId().equals(catalogId)) {
+						if (dictionaries != null)
+							catalog.setDictionaries(dictionaries);
+						if (index != null)
+							catalog.setIndex(index);
+						if (restrictQueryPermission != null)
+							catalog.setRestrictQueryPermissions(restrictQueryPermissions);
+						if (restrictIngestPermission != null)
+							catalog.setRestrictIngestPermissions(restrictIngestPermissions);
+						this.catalogRepository.serializeCatalog(catalog);
+						break;
+					}
+				}
+			}catch (Exception e) {
+				this.catalogs = backupCatalogs;
+				throw new CatalogServiceException("Failed to serialize Catalog '" + catalogId + "' -- if CatalogService goes down, Catalog will have to be readded : " + e.getMessage(), e);
+			}finally {
+				this.catalogsLock.writeLock().unlock();
+			}
+		}
+	}
+
+	protected boolean containsCatalog(String catalogId) throws CatalogServiceException {
+		this.catalogsLock.readLock().lock();
+		try {
+			return this.catalogs.contains(catalogId);
+		}catch (Exception e) {
+			throw new CatalogServiceException("Failed to check if catalog '" + catalogId + "' has already been added to this CatalogService : " + e.getMessage(), e);
+		}finally {
+			this.catalogsLock.readLock().unlock();
+		}
+	}
+	
+	/**
+	 * Ability to dynamically add a Catalog to this CatalogService for managing
+	 * @param catalog Catalog for this CatalogService to manage
+	 * @return True if catalogs where added to list
+	 * @throws CatalogServiceException If one of the adding Catalog
+	 * URNs equals that of an existing Catalog. 
+	 */	
+	public void addCatalog(Catalog catalog) throws CatalogServiceException {
+		if (!this.containsCatalog(catalog.getId()))
+			this.replaceCatalog(catalog);
+		else
+			LOG.log(Level.WARNING, "Attempt to override an existing catalog '" + catalog + "' already used in CatalogService, remedy and retry add -- no changes took place!");
+	}
+	
+	/**
+	 * Ability to dynamically add a Catalog to this CatalogService for managing
+	 * @param catalog Catalog for this CatalogService to manage
+	 * @param allowOverride True to allow adding Catalog to override existing Catalog with same URN
+	 * @throws CatalogServiceException When allowOverride=false and one of the adding Catalog
+	 * URNs equals that of an existing Catalog. 
+	 */
+	public void replaceCatalog(Catalog catalog) throws CatalogServiceException {
+		Set<Catalog> backupCatalogs = null;
+		this.catalogsLock.writeLock().lock();
+		try {
+			backupCatalogs = new HashSet<Catalog>(this.catalogs);
+			this.catalogs.remove(catalog);
+			this.catalogs.add(catalog);
+			this.catalogRepository.serializeCatalog(catalog);
+		}catch (Exception e) {
+			this.catalogs = backupCatalogs;
+			throw new CatalogServiceException("Failed to serialize Catalog '" + catalog + "' -- if CatalogService goes down, Catalog will have to be readded : " + e.getMessage(), e);
+		}finally {
+			this.catalogsLock.writeLock().unlock();
+		}
+	}
+	
+	public void removeCatalog(String catalogUrn) throws CatalogServiceException {
+		this.removeCatalog(catalogUrn, false);
+	}
+	
+	/**
+	 * 
+	 * @param catalogUrn
+	 * @throws CatalogServiceException
+	 */
+	public void removeCatalog(String catalogId, boolean preserveMapping) throws CatalogServiceException {
+			this.catalogsLock.readLock().lock();
+			Catalog rmCatalog = null;
+			try {
+				for (Catalog catalog : this.catalogs) {
+					if (catalog.getId().equals(catalogId)) {
+						rmCatalog = catalog;
+						break;
+					}
+				}
+			}catch (Exception e) {
+				throw new CatalogServiceException("Failed to find catalog object for catalog URN '" + catalogId + "' : " + e.getMessage(), e);
+			}finally {
+				this.catalogsLock.readLock().unlock();
+			}
+			
+			if (rmCatalog != null) {
+				this.catalogsLock.writeLock().lock();
+				try {
+					LOG.log(Level.INFO, "Removing catalog '" + rmCatalog + "'");
+					this.catalogs.remove(rmCatalog);
+					this.catalogRepository.deleteSerializedCatalog(catalogId);
+					if (!preserveMapping) {
+						this.ingestMapperLock.writeLock().lock();
+						try {
+							LOG.log(Level.INFO, "Deleting all index mappings for catalog '" + rmCatalog + "'");
+							this.ingestMapper.deleteAllMappingsForCatalog(catalogId);
+						}catch (Exception e) {
+							throw e;
+						}finally {
+							this.ingestMapperLock.writeLock().unlock();
+						}
+					}
+				}catch (Exception e) {
+					throw new CatalogServiceException("Failed to remove Catalog '" + catalogId + "' from this CatalogService");
+				}finally {
+					this.catalogsLock.writeLock().unlock();
+				}
+			}else {
+				LOG.log(Level.WARNING, "Catalog '" + catalogId + "' is not currently managed by this CatalogService");
+			}
+	}
+	
+	public void setPluginStorageDir(File pluginStorageDir) {
+		this.pluginStorageDir = pluginStorageDir;
+		this.pluginStorageDir.mkdirs();
+	}
+	
+	public URL getPluginStorageDir() throws CatalogServiceException {
+		try {
+			return new URL("file://" + this.pluginStorageDir.getAbsolutePath());
+		}catch (Exception e) {
+			throw new CatalogServiceException("Failed to get plugin storage dir directory : " + e.getMessage(), e);
+		}
+	}
+	
+	public List<PluginURL> getPluginUrls() throws CatalogServiceException {
+		try {
+			return this.catalogRepository.deserializePluginURLs();
+		}catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	public void addPluginUrls(List<PluginURL> urls) throws CatalogServiceException {
+		try {
+			List<PluginURL> currentUrls = new Vector<PluginURL>(this.catalogRepository.deserializePluginURLs());
+			currentUrls.addAll(urls);
+			this.catalogRepository.serializePluginURLs(currentUrls);
+		}catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	/**
+	 * 
+	 * @return
+	 * @throws CatalogServiceException
+	 */
+	public Set<Catalog> getCurrentCatalogList() throws CatalogServiceException {
+		this.catalogsLock.readLock().lock();
+		try {
+			return new HashSet<Catalog>(this.catalogs);
+		}catch (Exception e) {
+			throw new CatalogServiceException("Failed to get current catalog list : " + e.getMessage(), e);
+		}finally {
+			this.catalogsLock.readLock().unlock();
+		}
+	}
+	
+	protected Catalog getCatalog(String catalogUrn) throws CatalogServiceException {
+		this.catalogsLock.readLock().lock();
+		try {
+			for (Catalog catalog : this.catalogs)
+				if (catalog.getId().equals(catalogUrn))
+					return catalog;
+			return null;
+		}catch (Exception e) {
+			throw new CatalogServiceException("Failed to get catalog catalog '" +  catalogUrn + "' : " + e.getMessage(), e);
+		}finally {
+			this.catalogsLock.readLock().unlock();
+		}
+	}
+	
+	/**
+	 * 
+	 * @return
+	 * @throws CatalogServiceException
+	 */
+	public Set<String> getCurrentCatalogIds() throws CatalogServiceException {
+		this.catalogsLock.readLock().lock();
+		try {
+			Set<String> catalogIds = new HashSet<String>();
+			for (Catalog catalog : this.catalogs) 
+				catalogIds.add(catalog.getId());
+			return catalogIds;
+		}catch (Exception e) {
+			throw new CatalogServiceException("Failed to get current catalog ids list : " + e.getMessage(), e);
+		}finally {
+			this.catalogsLock.readLock().unlock();
+		}
+	}
+		
+	public TransactionReceipt ingest(Metadata metadata) throws CatalogServiceException {
+		if (this.restrictIngestPermissions) 
+			throw new CatalogServiceException("Ingest permissions are restricted for this CatalogService -- request denied");
+		try {	
+			boolean performUpdate = false;
+			TransactionId<?> catalogServiceTransactionId = this.getCatalogServiceTransactionId(metadata);
+			if (performUpdate = this.ingestMapper.hasCatalogServiceTransactionId(catalogServiceTransactionId)) 
+				LOG.log(Level.INFO, "TransactionId '" + catalogServiceTransactionId + "' is an existing TransactionId, switching to update mode");
+			List<CatalogReceipt> catalogReceipts = new Vector<CatalogReceipt>();
+			for (Catalog catalog : this.getFilteredCatalogList(metadata)) {			
+				if (catalog.isIngestable()) {
+					this.ingestMapperLock.writeLock().lock();
+					try {
+						// perform update
+						if (performUpdate) {
+							if (!Boolean.parseBoolean(metadata.getMetadata(ENABLE_UPDATE_MET_KEY)))
+								throw new CatalogServiceException("TransactionId '" + catalogServiceTransactionId + "' already exists -- enable update by setting metadata key '" + ENABLE_UPDATE_MET_KEY + "'=true");
+							TransactionId<?> catalogTransactionId = this.ingestMapper.getCatalogTransactionId(catalogServiceTransactionId, catalog.getId());
+							if (catalogTransactionId != null) {
+								CatalogReceipt catalogReceipt = catalog.update(catalogTransactionId, metadata);
+								if (catalogReceipt != null) {
+									if (!catalogReceipt.getTransactionId().equals(catalogTransactionId)) {
+										this.ingestMapper.deleteTransactionIdMapping(catalogTransactionId, catalog.getId());
+										this.ingestMapper.storeTransactionIdMapping(catalogServiceTransactionId, this.transactionIdFactory, catalogReceipt, catalog.getTransactionIdFactory());
+									}
+									catalogReceipts.add(catalogReceipt);
+									LOG.log(Level.INFO, "Successfully updated metadata to catalog '" + catalog + "' for TransactionId '" + catalogServiceTransactionId + "'");
+								}else {
+									LOG.log(Level.SEVERE, "Update attempt to catalog '" + catalog + "' failed for TransactionId '" + catalogServiceTransactionId + "' -- update returned false");
+								}
+							}else {
+								LOG.log(Level.INFO, "Catalog '" + catalog + "' was not on ingest list for TransactionId '" + catalogServiceTransactionId + "' -- skipping");
+							}
+						// perform ingest	
+						}else {
+							LOG.log(Level.INFO, "Performing ingest for TransactionId '" + catalogServiceTransactionId + "' to catalog '" + catalog + "'");
+							CatalogReceipt catalogReceipt = catalog.ingest(metadata);
+							if (catalogReceipt != null) {
+								LOG.log(Level.INFO, "Successfully ingested metadata -- Indexing TransactionId information for ingest (CatalogService TransactionId = '" + catalogServiceTransactionId + "', Catalog TransactionId = '" + catalogReceipt.getTransactionId() + "', catalog = '" + catalogReceipt.getCatalogId() + "')");
+								this.ingestMapper.storeTransactionIdMapping(catalogServiceTransactionId, this.transactionIdFactory, catalogReceipt, catalog.getTransactionIdFactory());
+								catalogReceipts.add(catalogReceipt);
+							}else {
+								LOG.log(Level.WARNING, "Catalog '" + catalog + "' not interested in any Metadata for TransactionId '" + catalogServiceTransactionId + "'");
+							}
+						}
+					}catch (Exception e) {
+						LOG.log(Level.WARNING, "Failed to add metadata to catalog '" + catalog.getId() + "' : " + e.getMessage(), e);
+						if (this.oneCatalogFailsAllFail)
+							throw new CatalogServiceException("Failed to add metadata to catalog '" + catalog.getId() + "' : " + e.getMessage(), e);
+					}finally {
+						this.ingestMapperLock.writeLock().unlock();
+					}
+				}else {
+					LOG.log(Level.WARNING, "Ingest not permitted to catalog '" + catalog + "' -- skipping over catalog");
+				}
+			}
+			return (catalogReceipts.size() > 0) ? new TransactionReceipt(catalogServiceTransactionId, catalogReceipts) : null;
+		}catch (Exception e) {
+			throw new CatalogServiceException("Error occured during Metadata ingest attempt : " + e.getMessage(), e);
+		}
+	}
+	
+	/**
+	 * 
+	 * @param metadata
+	 * @throws CatalogServiceException
+	 */
+	public void delete(Metadata metadata) throws CatalogServiceException {
+		if (this.restrictIngestPermissions)
+			throw new CatalogServiceException("Delete permissions are restricted for this CatalogService -- request denied");
+		TransactionId<?> catalogServiceTransactionId = this.getCatalogServiceTransactionId(metadata, false);
+		if (catalogServiceTransactionId != null) {
+			for (Catalog catalog : this.getFilteredCatalogList(metadata)) {
+				if (catalog.isIngestable()) {
+					this.ingestMapperLock.writeLock().lock();
+					try {
+						TransactionId<?> catalogTransactionId = this.ingestMapper.getCatalogTransactionId(catalogServiceTransactionId, catalog.getId());
+						if (catalogTransactionId != null) {
+							if (this.doReduce(metadata)) {
+								LOG.log(Level.INFO, "Deleting metadata from TransactionId '" + catalogServiceTransactionId + "' for catalog '" + catalog + "'");
+								if (catalog.reduce(catalogTransactionId, metadata)) {
+									LOG.log(Level.INFO, "Successfully deleted metadata from catalog '" + catalog + "' for TransactionId [id = " + catalogServiceTransactionId + "]");
+								}else {
+									LOG.log(Level.INFO, "Failed to deleted metadata from catalog '" + catalog + "' for TransactionId [id = " + catalogServiceTransactionId + "] -- delete returned false");
+								}
+							}else {
+								LOG.log(Level.INFO, "Deleting all records of TransactionId from catalog '" + catalog + "'");
+								if (catalog.delete(catalogTransactionId)) {
+									this.ingestMapper.deleteTransactionIdMapping(catalogTransactionId, catalog.getId());
+									LOG.log(Level.INFO, "Successfully deleted metadata from catalog '" + catalog + "' for TransactionId [id = " + catalogServiceTransactionId + "]");
+								}else {
+									LOG.log(Level.INFO, "Failed to deleted metadata from catalog '" + catalog + "' for TransactionId [id = " + catalogServiceTransactionId + "] -- delete returned false");
+								}
+							}
+						}else {
+							LOG.log(Level.INFO, "Catalog '" + catalog + "' was not on delete list for TransactionId '" + catalogServiceTransactionId + "' -- skipping");
+						}
+					}catch (Exception e) {
+						LOG.log(Level.WARNING, "Error occured while deleting metadata for TransactionId [id = " + catalogServiceTransactionId + "] : " + e.getMessage(), e);
+						if (this.oneCatalogFailsAllFail)
+							throw new CatalogServiceException("Error occured while deleting metadata for TransactionId [id = " + catalogServiceTransactionId + "] : " + e.getMessage(), e);
+					}finally {
+						this.ingestMapperLock.writeLock().unlock();
+					}
+				}else {
+					LOG.log(Level.WARNING, "Deletion is not permitted to catalog '" + catalog + "' -- skipping over catalog");
+				}	
+			}
+		}else {
+			throw new CatalogServiceException("Must specify a TransactionId to delete");
+		}
+	}
+	
+	protected boolean doReduce(Metadata metadata) {
+		for (String key : metadata.getAllKeys())
+			if (!(key.equals(CATALOG_SERVICE_TRANSACTION_ID_MET_KEY) || key.equals(CATALOG_IDS_MET_KEY) || key.equals(CATALOG_TRANSACTION_ID_MET_KEY) || key.equals(CATALOG_ID_MET_KEY)))
+				return true;
+		return false;
+	}
+	
+	public List<String> getProperty(String key) throws CatalogServiceException {
+		List<String> vals = new Vector<String>();
+		for (Catalog catalog : this.getCurrentCatalogList()) {
+			try {
+				String val = catalog.getProperty(key);
+				if (val != null)
+					vals.add(val);
+			}catch (Exception e) {
+				if (this.oneCatalogFailsAllFail)
+					throw new CatalogServiceException("Failed to get catalog property '" + key + "' from catalog '" + catalog.getId() + "' : " + e.getMessage(), e);
+				else
+					LOG.log(Level.WARNING, "Failed to get catalog property '" + key + "' from catalog '" + catalog.getId() + "' : " + e.getMessage(), e);
+			}
+		}
+		return vals;
+	}
+
+	public Properties getCalalogProperties() throws CatalogServiceException {
+		Properties properties = new Properties();
+		for (Catalog catalog : this.getCurrentCatalogList()) {
+			try {
+				Properties catalogProperties = catalog.getProperties();
+				for (Object key : catalogProperties.keySet()) {
+					String value = properties.getProperty((String) key);
+					if (value != null)
+						value += "," + catalogProperties.getProperty((String) key);
+					else 
+						value = catalogProperties.getProperty((String) key);
+					properties.setProperty((String) key, value);
+				}
+			}catch (Exception e) {
+				if (this.oneCatalogFailsAllFail)
+					throw new CatalogServiceException("Failed to get catalog properties from catalog '" + catalog.getId() + "' : " + e.getMessage(), e);
+				else
+					LOG.log(Level.WARNING, "Failed to get catalog properties from catalog '" + catalog.getId() + "' : " + e.getMessage(), e);
+			}
+		}
+		return properties;
+	}
+	
+	public Properties getCalalogProperties(String catalogUrn) throws CatalogServiceException {
+		try {
+			Catalog catalog = this.getCatalog(catalogUrn);
+			if (catalog != null)
+				return catalog.getProperties();
+			else 
+				return null;
+		}catch (Exception e) {
+			throw new CatalogServiceException("Failed to get catalog properties from catalog '" + catalogUrn + "' : " + e.getMessage(), e);
+		}
+	}
+	
+	public Page getNextPage(Page page) throws CatalogServiceException {
+		QueryPager queryPager = new QueryPager(this._query(page.getQueryExpression(), page.getRestrictToCatalogIds()));
+		queryPager.setPageInfo(new PageInfo(page.getPageSize(), page.getPageNum() + 1));
+		return this.getPage(page.getQueryExpression(), page.getRestrictToCatalogIds(), queryPager);
+	}
+	
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression) throws CatalogServiceException {
+		return this.getPage(pageInfo, queryExpression, this.getCurrentCatalogIds());
+	}
+	
+	public Page getPage(PageInfo pageInfo, QueryExpression queryExpression, Set<String> catalogIds) throws CatalogServiceException {
+		if (this.disableIntersectingCrossCatalogQueries) {
+			try {
+				int totalResults = 0;
+				LinkedHashMap<String, Integer> catalogToSizeOfMap = new LinkedHashMap<String, Integer>();
+				for (String catalogId : catalogIds) {
+					Catalog catalog = this.getCatalog(catalogId);
+					QueryExpression qe = this.reduceToUnderstoodExpressions(catalog, queryExpression);
+					if (qe != null) {
+						int catalogResultSize = catalog.sizeOf(qe);
+						totalResults += catalogResultSize;
+						catalogToSizeOfMap.put(catalogId, catalogResultSize);
+					}
+				}
+				
+				LOG.log(Level.INFO, "Routing query to catalogs as non-cross catalog intersecting queries . . .");
+				if (totalResults <= this.crossCatalogResultSortingThreshold) {
+					List<CatalogReceipt> catalogReceipts = new Vector<CatalogReceipt>();
+					for (String catalogId : catalogToSizeOfMap.keySet()) {
+						Catalog catalog = this.getCatalog(catalogId);
+						QueryExpression qe = this.reduceToUnderstoodExpressions(catalog, queryExpression);
+						if (qe != null)
+							catalogReceipts.addAll(catalog.query(qe));
+					}
+					List<TransactionReceipt> transactionReceipts = this.getPossiblyUnindexedTransactionReceipts(catalogReceipts);
+					LOG.log(Level.INFO, "Sorting Query Results . . . ");
+					Collections.sort(transactionReceipts, new Comparator<TransactionReceipt>() {
+						public int compare(TransactionReceipt o1,
+								TransactionReceipt o2) {
+							return o2.getTransactionDate().compareTo(o1.getTransactionDate());
+						}
+					});
+					QueryPager queryPager = new QueryPager(transactionReceipts);
+					queryPager.setPageInfo(pageInfo);
+					return this.getPage(queryExpression, catalogIds, queryPager);
+				}else {
+					int currentIndex = 0;
+					int desiredStartingIndex = pageInfo.getPageNum() * pageInfo.getPageSize();
+					List<CatalogReceipt> pageOfReceipts = new Vector<CatalogReceipt>();
+					for (Entry<String, Integer> entry : catalogToSizeOfMap.entrySet()) {
+						if (desiredStartingIndex - currentIndex <= entry.getValue()) {
+							Catalog catalog = this.getCatalog(entry.getKey());
+							QueryExpression qe = this.reduceToUnderstoodExpressions(catalog, queryExpression);
+							if (qe != null) {
+								List<CatalogReceipt> receipts = catalog.query(qe, desiredStartingIndex - currentIndex, Math.min((desiredStartingIndex - currentIndex) + pageInfo.getPageSize(), entry.getValue()));
+								pageOfReceipts.addAll(receipts);
+								if (pageOfReceipts.size() >= pageInfo.getPageSize())
+									break;
+							}
+						}else {
+							currentIndex += entry.getValue();
+						}
+					}
+					return new Page(new ProcessedPageInfo(pageInfo.getPageSize(), pageInfo.getPageNum(), totalResults), queryExpression, catalogIds, this.indexReceipts(this.getPossiblyUnindexedTransactionReceipts(pageOfReceipts)));
+				}
+			}catch (Exception e) {
+				throw new CatalogServiceException(e.getMessage(), e);
+			}
+		}else {
+			QueryPager queryPager = new QueryPager(this._query(queryExpression, catalogIds)); 
+			queryPager.setPageInfo(pageInfo);
+			return this.getPage(queryExpression, catalogIds, queryPager);
+		}
+	}
+	
+	public QueryPager query(QueryExpression queryExpression) throws CatalogServiceException {
+		return this.query(queryExpression, this.getCurrentCatalogIds());
+	}
+
+	public List<TransactionalMetadata> getMetadata(Page page) throws CatalogServiceException {
+		return this.getMetadata(page.getReceipts());
+	}
+	
+	protected Page getPage(QueryExpression queryExpression, Set<String> restrictToCatalogIds, QueryPager queryPager) throws CatalogServiceException {
+		return new Page(new ProcessedPageInfo(queryPager.getPageSize(), queryPager.getPageNum(), queryPager.getNumOfHits()), queryExpression, restrictToCatalogIds, this.indexReceipts(queryPager.getCurrentPage()));
+	}
+	
+	public QueryPager query(QueryExpression queryExpression, Set<String> catalogIds) throws CatalogServiceException {
+		return new QueryPager(this.indexReceipts(this._query(queryExpression, catalogIds)));
+	}
+	
+	/**
+	 * 
+	 * @param queryExpression
+	 * @param indexPage
+	 * @return
+	 * @throws CatalogServiceException
+	 */
+	public List<TransactionReceipt> _query(QueryExpression queryExpression, Set<String> catalogIds) throws CatalogServiceException {
+		if (this.restrictQueryPermissions)
+			throw new CatalogServiceException("Query permissions are restricted for this CatalogService -- request denied");
+		try {
+			LOG.log(Level.INFO, "Recieved query '" + queryExpression + "'");
+			if (this.simplifyQueries) {
+				queryExpression = QueryUtils.simplifyQuery(queryExpression);
+				LOG.log(Level.INFO, "Simplified query to '" + queryExpression + "' -- routing query to catalogs");
+			}
+			QueryResult queryResult = this.queryRecur(queryExpression, catalogIds);
+			List<CatalogReceipt> catalogReceipts = new Vector<CatalogReceipt>();
+			if (queryResult.getCatalogReceipts() == null && queryResult.getInterestedCatalogs() != null) {
+				for (Catalog catalog : this.getCurrentCatalogList()) {
+					try {
+						if (queryResult.getInterestedCatalogs().contains(catalog.getId())) {
+							LOG.log(Level.INFO, "Restricting query to understood terms for Catalog '" + catalog + "'");
+							QueryExpression reducedExpression = this.reduceToUnderstoodExpressions(catalog, queryExpression);
+							LOG.log(Level.INFO, "Querying Catalog '" + catalog + "' with query '" + reducedExpression + "'");
+							catalogReceipts.addAll(catalog.query(reducedExpression));
+						}
+					}catch (Exception e) {
+						if (this.oneCatalogFailsAllFail)
+							throw new CatalogServiceException("Failed to query catalog '" + catalog.getId() + "' for query '" + queryExpression + "' : " + e.getMessage(), e);
+						else
+							LOG.log(Level.WARNING, "Failed to query catalog '" + catalog.getId() + "' for query '" + queryExpression + "' : " + e.getMessage(), e);
+					}	
+				}
+			}
+			List<TransactionReceipt> transactionReceipts = this.getPossiblyUnindexedTransactionReceipts(catalogReceipts);
+			LOG.log(Level.INFO, "Sorting Query Results . . . ");
+			Collections.sort(transactionReceipts, new Comparator<TransactionReceipt>() {
+				public int compare(TransactionReceipt o1,
+						TransactionReceipt o2) {
+					return o2.getTransactionDate().compareTo(o1.getTransactionDate());
+				}
+			});
+
+			LOG.log(Level.INFO, "Query returned " + transactionReceipts.size() + " results");
+			return transactionReceipts;
+		}catch (Exception e) {
+			e.printStackTrace();
+			throw new CatalogServiceException("Failed to get TransactionId to Metadata map for query '" + queryExpression + "' : " + e.getMessage(), e);
+		}
+	}
+	
+	protected List<TransactionReceipt> getPossiblyUnindexedTransactionReceipts(List<CatalogReceipt> catalogReceipts) throws CatalogServiceException {
+		try {
+			List<TransactionReceipt> returnList = new Vector<TransactionReceipt>();
+			LinkedHashMap<TransactionId<?>, List<CatalogReceipt>> existing = new LinkedHashMap<TransactionId<?>, List<CatalogReceipt>>();
+ 			for (CatalogReceipt catalogReceipt : catalogReceipts) {
+ 				TransactionId<?> catalogServiceTransactionId = this.getCatalogServiceTransactionId(catalogReceipt.getTransactionId(), catalogReceipt.getCatalogId());
+ 				if (catalogServiceTransactionId != null) {
+ 					List<CatalogReceipt> found = existing.get(catalogServiceTransactionId);
+ 					if (found == null) 
+ 						found = new Vector<CatalogReceipt>();
+ 					found.add(catalogReceipt);	
+ 					existing.put(catalogServiceTransactionId, found);
+ 				}else {
+ 					returnList.add(new TransactionReceipt(null, Collections.singletonList(catalogReceipt)));
+ 				}
+ 			}
+ 			for (TransactionId<?> transactionId : existing.keySet())
+ 				returnList.add(new TransactionReceipt(transactionId, existing.get(transactionId)));
+ 			return returnList;
+		}catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}
+	}
+	
+	protected List<TransactionReceipt> indexReceipts(List<TransactionReceipt> transactionReceipts) throws CatalogServiceException {
+		List<TransactionReceipt> indexedReceipts = new Vector<TransactionReceipt>();
+		for (TransactionReceipt transactionReceipt : transactionReceipts) {
+			try {
+//				for (CatalogReceipt catalogReceipt : transactionReceipt.getCatalogReceipts()) {
+					if (transactionReceipt.getTransactionId() == null)
+						transactionReceipt = new TransactionReceipt(this.getCatalogServiceTransactionId(transactionReceipt.getCatalogReceipts().get(0), true), transactionReceipt.getCatalogReceipts());
+//				}
+				indexedReceipts.add(transactionReceipt);
+			}catch(Exception e) {
+				throw new CatalogServiceException(e.getMessage(), e);
+			}
+		}
+		return indexedReceipts;
+	}
+ 
+	public List<TransactionalMetadata> getNextPage(QueryPager queryPager) throws CatalogServiceException {
+		try {
+			return this.getMetadata(queryPager.getCurrentPage());
+		}catch (Exception e) {
+			throw new CatalogServiceException("Failed to get next page of Metadata : " + e.getMessage(), e);
+		}
+	}
+	
+	public List<TransactionalMetadata> getAllPages(QueryPager queryPager) throws CatalogServiceException {
+		try {
+			return this.getMetadata(queryPager.getTransactionReceipts());
+		}catch (Exception e) {
+			throw new CatalogServiceException("Failed to get all page of Metadata : " + e.getMessage(), e);
+		}	
+	}
+	
+	public List<TransactionalMetadata> getMetadataFromTransactionIdStrings(List<String> catalogServiceTransactionIdStrings) throws CatalogServiceException {
+		List<TransactionId<?>> catalogServiceTransactionIds = new Vector<TransactionId<?>>();
+		for (String catalogServiceTransactionIdString : catalogServiceTransactionIdStrings) 
+			catalogServiceTransactionIds.add(this.generateTransactionId(catalogServiceTransactionIdString));
+		return this.getMetadataFromTransactionIds(catalogServiceTransactionIds);
+	}
+	
+	public List<TransactionalMetadata> getMetadata(List<TransactionReceipt> transactionReceipts) throws CatalogServiceException {
+		LinkedHashSet<TransactionalMetadata> metadataSet = new LinkedHashSet<TransactionalMetadata>();
+		for (TransactionReceipt transactionReceipt : transactionReceipts) {
+			Metadata metadata = new Metadata();
+			Vector<CatalogReceipt> successfulCatalogReceipts = new Vector<CatalogReceipt>();
+			for (CatalogReceipt catalogReceipt : transactionReceipt.getCatalogReceipts()) {
+				try {
+					Catalog catalog = this.getCatalog(catalogReceipt.getCatalogId());
+					metadata.addMetadata(catalog.getMetadata(catalogReceipt.getTransactionId()));
+					successfulCatalogReceipts.add(catalogReceipt);
+				}catch (Exception e) {
+					if (this.oneCatalogFailsAllFail)
+						throw new CatalogServiceException("Failed to get metadata for transaction ids for catalog '" + catalogReceipt.getCatalogId() + "' : " + e.getMessage(), e);
+					else
+						LOG.log(Level.WARNING, "Failed to get metadata for transaction ids for catalog '" + catalogReceipt.getCatalogId() + "' : " + e.getMessage(), e);
+				}
+			}
+			if (metadata.getHashtable().keySet().size() > 0)
+				metadataSet.add(new TransactionalMetadata(new TransactionReceipt(transactionReceipt.getTransactionId(), successfulCatalogReceipts), metadata));
+		}
+		return new Vector<TransactionalMetadata>(metadataSet);
+	}
+	
+	public List<TransactionalMetadata> getMetadataFromTransactionIds(List<TransactionId<?>> catalogServiceTransactionIds) throws CatalogServiceException {
+		LinkedHashSet<TransactionalMetadata> metadataSet = new LinkedHashSet<TransactionalMetadata>();
+		for (TransactionId<?> catalogServiceTransactionId : catalogServiceTransactionIds) {
+			Metadata metadata = new Metadata();
+			Vector<CatalogReceipt> catalogReceipts = new Vector<CatalogReceipt>();
+			for (Catalog catalog : this.getCurrentCatalogList()) {
+				try {
+					CatalogReceipt catalogReceipt = this.ingestMapper.getCatalogReceipt(catalogServiceTransactionId, catalog.getId());
+					if (catalogReceipt != null) {
+						metadata.addMetadata(catalog.getMetadata(catalogReceipt.getTransactionId()).getHashtable());
+						catalogReceipts.add(catalogReceipt);
+					}
+				}catch (Exception e) {
+					if (this.oneCatalogFailsAllFail)
+						throw new CatalogServiceException("Failed to get metadata for transaction ids for catalog '" + catalog.getId() + "' : " + e.getMessage(), e);
+					else
+						LOG.log(Level.WARNING, "Failed to get metadata for transaction ids for catalog '" + catalog.getId() + "' : " + e.getMessage(), e);
+				}
+			}
+			if (metadata.getHashtable().keySet().size() > 0)
+				metadataSet.add(new TransactionalMetadata(new TransactionReceipt(catalogServiceTransactionId, catalogReceipts), metadata));
+		}
+		return new Vector<TransactionalMetadata>(metadataSet);
+	}
+	
+	public List<TransactionId<?>> getCatalogServiceTransactionIds(List<TransactionId<?>> catalogTransactionIds, String catalogUrn) throws CatalogServiceException {
+		LinkedHashSet<TransactionId<?>> catalogServiceTransactionIds = new LinkedHashSet<TransactionId<?>>();
+		for (TransactionId<?> catalogTransactionId : catalogTransactionIds) {
+			TransactionId<?> catalogServiceTransactionId = this.getCatalogServiceTransactionId(catalogTransactionId, catalogUrn);
+			catalogServiceTransactionIds.add(catalogServiceTransactionId);
+		}
+		return new Vector<TransactionId<?>>(catalogServiceTransactionIds); 
+	}
+	
+	public TransactionId<?> getCatalogServiceTransactionId(TransactionId<?> catalogTransactionId, String catalogUrn) throws CatalogServiceException {
+		this.ingestMapperLock.readLock().lock();
+		try {
+			return this.ingestMapper.getCatalogServiceTransactionId(catalogTransactionId, catalogUrn);
+		}catch (Exception e) {
+			throw new CatalogServiceException(e.getMessage(), e);
+		}finally {
+			this.ingestMapperLock.readLock().unlock();
+		}
+	}
+	
+	public TransactionId<?> getCatalogServiceTransactionId(CatalogReceipt catalogReceipt, boolean generateNew) throws CatalogServiceException {
+		try {
+			TransactionId<?> catalogServiceTransactionId = this.getCatalogServiceTransactionId(catalogReceipt.getTransactionId(), catalogReceipt.getCatalogId());
+			if (catalogServiceTransactionId == null && generateNew) {
+				catalogServiceTransactionId = this.generateNewUniqueTransactionId();
+				LOG.log(Level.INFO, "CatalogServer mapping transaction: " + catalogServiceTransactionId + "," + catalogReceipt.getTransactionId() + "," + catalogReceipt.getCatalogId());
+				this.ingestMapperLock.writeLock().lock();
+				try {
+					this.ingestMapper.storeTransactionIdMapping(catalogServiceTransactionId, this.transactionIdFactory, catalogReceipt, this.getCatalog(catalogReceipt.getCatalogId()).getTransactionIdFactory());
+				}catch (Exception e) {
+					throw new CatalogServiceException("Failed to write TransactionId '" + catalogServiceTransactionId + "' : " + e.getMessage(), e);
+				}finally {
+					this.ingestMapperLock.writeLock().unlock();
+				}
+			}
+			return catalogServiceTransactionId;
+		}catch (Exception e) {
+			throw new CatalogServiceException("Failed to get CatalogServiceTransactionId : " + e.getMessage(), e);
+		}
+	}
+
+	protected TransactionId<?> generateNewUniqueTransactionId() {
+		try {
+			return this.transactionIdFactory.createNewTransactionId();
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed to generate a new TransactionId from factory '" + this.transactionIdFactory.getClass().getCanonicalName() + "' : " + e.getMessage(), e);
+			return null;
+		}
+	}
+	
+	protected TransactionId<?> generateTransactionId(String stringTransactionId) {
+		try {
+			return this.transactionIdFactory.createTransactionId(stringTransactionId);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed to generate a new TransactionId from factory '" + this.transactionIdFactory.getClass().getCanonicalName() + "' for string value '" + stringTransactionId + ": " + e.getMessage(), e);
+			return null;
+		}
+	}
+	
+	// check if transaction id was specified by user, otherwise generate a new one
+	protected TransactionId<?> getCatalogServiceTransactionId(Metadata metadata) throws Exception {
+		return this.getCatalogServiceTransactionId(metadata, true);
+	}
+	
+	protected TransactionId<?> getCatalogServiceTransactionId(Metadata metadata, boolean generateNew) throws CatalogServiceException {
+		try {
+			if (metadata.getMetadata(CatalogServiceLocal.CATALOG_SERVICE_TRANSACTION_ID_MET_KEY) != null) {
+				return this.generateTransactionId(metadata.getMetadata(CatalogServiceLocal.CATALOG_SERVICE_TRANSACTION_ID_MET_KEY));
+			}else if (metadata.getMetadata(CatalogServiceLocal.CATALOG_TRANSACTION_ID_MET_KEY) != null && metadata.getMetadata(CatalogServiceLocal.CATALOG_ID_MET_KEY) != null) {
+				String catalogId = metadata.getMetadata(CatalogServiceLocal.CATALOG_ID_MET_KEY);
+				Catalog catalog = this.getCatalog(catalogId);
+				if (catalog != null) {
+					TransactionId<?> catalogTransactionId = catalog.getTransactionIdFromString(metadata.getMetadata(CatalogServiceLocal.CATALOG_TRANSACTION_ID_MET_KEY));
+					TransactionId<?> catalogServiceTransactionId = this.ingestMapper.getCatalogServiceTransactionId(catalogTransactionId, catalogId);
+					if (catalogServiceTransactionId == null)
+						throw new CatalogServiceException("CatalogService's Catalog '" + catalog.getId() + "' is not aware of TransactionId '" + catalogTransactionId + "'s");
+					return catalogServiceTransactionId;
+				}else {
+					throw new CatalogServiceException("This CatalogService has no Catalog with ID = '" + catalogId + "'");
+				}
+			}else if (generateNew) {
+				return this.generateNewUniqueTransactionId();
+			}else {
+				throw new CatalogServiceException("Metadata fields not present to determine a TransactionId");
+			}
+		}catch (Exception e) {
+			throw new CatalogServiceException("Failed determine TransactionId : " + e.getMessage(), e);
+		}
+	}
+	
+	protected Set<Catalog> getFilteredCatalogList(Metadata metadata) throws CatalogServiceException {
+		try {
+			if (metadata.containsKey(CATALOG_ID_MET_KEY)) {
+				Catalog catalog = this.getCatalog(metadata.getMetadata(CATALOG_ID_MET_KEY));
+				if (catalog == null)
+					throw new CatalogServiceException("Catalog '" + metadata.getMetadata(CATALOG_ID_MET_KEY) + "' is not managed by this CatalogService");
+				else
+					return Collections.singleton(catalog);
+			}else if (metadata.containsKey(CATALOG_IDS_MET_KEY)) {
+				HashSet<Catalog> filteredCatalogList = new HashSet<Catalog>();
+				for (Object catalogUrn : metadata.getAllMetadata(CATALOG_IDS_MET_KEY)) {
+					Catalog catalog = this.getCatalog((String) catalogUrn);
+					if (catalog == null)
+						throw new CatalogServiceException("Catalog '" + metadata.getMetadata(CATALOG_ID_MET_KEY) + "' is not managed by this CatalogService");
+					else
+						filteredCatalogList.add(catalog);
+				}
+				return filteredCatalogList;
+			}else {
+				return new HashSet<Catalog>(this.catalogs);
+			}
+		}catch (Exception e) {
+			throw new CatalogServiceException("Failed to get filtered catalog list : " + e.getMessage(), e);
+		}
+	}
+	
+	protected QueryResult queryRecur(QueryExpression queryExpression, Set<String> restrictToCatalogIds) throws CatalogServiceException, CatalogException {
+		// get QueryResults for sub queries
+		if (queryExpression instanceof QueryLogicalGroup) {
+			
+			// get children query results
+			List<QueryResult> childrenQueryResults = new Vector<QueryResult>();
+			for (QueryExpression subQueryExpression : ((QueryLogicalGroup) queryExpression).getExpressions()) 
+				childrenQueryResults.add(queryRecur(subQueryExpression, restrictToCatalogIds));
+			
+			// if (QueryLogicalGroup's operator is AND and is unbalanced or a child contains query results)
+			if ((((QueryLogicalGroup) queryExpression).getOperator().equals(QueryLogicalGroup.Operator.AND) && containsUnbalancedCatalogInterest(childrenQueryResults)) || containsTranactionReceipts(childrenQueryResults)) {
+				
+				for (int i = 0; i < childrenQueryResults.size(); i++) {
+					QueryResult childQueryResult = childrenQueryResults.get(i);
+					
+					// if childQueryResult has not been used, use it
+					if (childQueryResult.getCatalogReceipts() == null) { 
+						List<CatalogReceipt> catalogReceipts = new Vector<CatalogReceipt>();
+						for (Catalog catalog : this.getCurrentCatalogList()) {
+							try {
+								if (childQueryResult.getInterestedCatalogs().contains(catalog.getId())) 
+									catalogReceipts.addAll(catalog.query(this.reduceToUnderstoodExpressions(catalog, childQueryResult.getQueryExpression())));
+							}catch (Exception e) {
+								if (this.oneCatalogFailsAllFail)
+									throw new CatalogServiceException("Failed to query catalog '" + catalog.getId() + "' for query '" + queryExpression + "' : " + e.getMessage(), e);
+								else
+									LOG.log(Level.WARNING, "Failed to query catalog '" + catalog.getId() + "' for query '" + queryExpression + "' : " + e.getMessage(), e);
+							}
+						}
+						childQueryResult.setCatalogReceipts(catalogReceipts);
+					}
+					
+				}
+				
+				// get intersection of results
+	   			QueryResult queryResult = new QueryResult(queryExpression);
+	   			queryResult.setCatalogReceipts(this.getIntersection(childrenQueryResults));
+				return queryResult;
+			}else {
+				// get merge of results
+				QueryResult queryResult = new QueryResult(queryExpression);
+				HashSet<String> interestedCatalogs = new HashSet<String>();
+				for (QueryResult childQueryResult : childrenQueryResults)
+					interestedCatalogs.addAll(childQueryResult.getInterestedCatalogs());
+				queryResult.setInterestedCatalogs(interestedCatalogs);
+				return queryResult;
+			}
+		}else if (queryExpression instanceof WrapperQueryExpression) {
+
+			// check for catalogs interested in wrapper query expression
+			restrictToCatalogIds.retainAll(getInterestedCatalogs(queryExpression, restrictToCatalogIds));
+			
+			// check for catalogs interested in wrapped query expression
+			QueryResult wrapperExprQueryResult = null;
+			QueryExpression wrapperQE = ((WrapperQueryExpression) queryExpression).getQueryExpression();
+			if (wrapperQE instanceof QueryLogicalGroup) {
+				wrapperExprQueryResult = this.queryRecur((QueryLogicalGroup) wrapperQE, restrictToCatalogIds);
+			}else {
+				wrapperExprQueryResult = new QueryResult(wrapperQE);
+				wrapperExprQueryResult.interestedCatalogs = getInterestedCatalogs(wrapperQE, restrictToCatalogIds);
+				wrapperExprQueryResult.interestedCatalogs.retainAll(restrictToCatalogIds);
+			}				
+			return wrapperExprQueryResult;
+		}else {
+			// determine catalogs interested in this query expression
+			QueryResult queryResult = new QueryResult(queryExpression);
+			Set<String> interestedCatalogs = getInterestedCatalogs(queryExpression, restrictToCatalogIds);
+			interestedCatalogs.retainAll(restrictToCatalogIds);
+			queryResult.setInterestedCatalogs(interestedCatalogs);
+			return queryResult;
+		}
+	}
+	
+	protected List<CatalogReceipt> getIntersection(List<QueryResult> queryResults) {
+		List<CatalogReceipt> catalogReceipts = new Vector<CatalogReceipt>();
+		if (queryResults.size() > 0) {
+			catalogReceipts.addAll(queryResults.get(0).getCatalogReceipts());
+			for (int i = 1; i < queryResults.size(); i++) {
+				QueryResult qr = queryResults.get(i);
+TR:				for (CatalogReceipt catalogReceipt : qr.getCatalogReceipts()) {
+					for (CatalogReceipt compCatalogReceipt : catalogReceipts) {
+						if (catalogReceipt.getTransactionId().equals(compCatalogReceipt.getTransactionId()))
+							continue TR;
+					}
+					catalogReceipts.remove(catalogReceipt);
+				}
+			}
+		}
+		return catalogReceipts;
+	}
+
+	protected QueryExpression reduceToUnderstoodExpressions(Catalog catalog, QueryExpression queryExpression) throws CatalogDictionaryException, CatalogException {
+		if (queryExpression instanceof QueryLogicalGroup) {
+        	QueryLogicalGroup queryLogicalGroup = (QueryLogicalGroup) queryExpression;
+        	List<QueryExpression> restrictedExpressions = new Vector<QueryExpression>();
+        	for (QueryExpression qe : queryLogicalGroup.getExpressions()) {
+        		QueryExpression restrictedQE = this.reduceToUnderstoodExpressions(catalog, qe);
+        		if (restrictedQE == null && queryLogicalGroup.getOperator().equals(QueryLogicalGroup.Operator.AND) && this.disableIntersectingCrossCatalogQueries) {
+        			restrictedExpressions.clear();
+        			break;
+        		}
+        		if (restrictedQE != null)
+        			restrictedExpressions.add(restrictedQE);
+        	}
+        	if (restrictedExpressions.size() > 0) {
+        		if (restrictedExpressions.size() == 1) {
+        			return restrictedExpressions.get(0);
+        		}else {
+		        	QueryLogicalGroup restrictedQueryLogicalGroup = queryLogicalGroup.clone();
+		        	restrictedQueryLogicalGroup.setExpressions(restrictedExpressions);
+		        	return restrictedQueryLogicalGroup;
+        		}
+        	}else {
+        		return null;
+        	}
+		}else if (queryExpression instanceof WrapperQueryExpression) {
+			WrapperQueryExpression wrapperQueryExpresssion = (WrapperQueryExpression) queryExpression;
+        	if (catalog.isInterested(queryExpression)) {
+	        	QueryExpression qe = this.reduceToUnderstoodExpressions(catalog, wrapperQueryExpresssion.getQueryExpression());
+				if (qe != null) {
+					WrapperQueryExpression wqe = wrapperQueryExpresssion.clone();
+					wqe.setQueryExpression(qe);
+					return wqe;
+				}else if (wrapperQueryExpresssion.isValidWithNoSubExpression()){
+					WrapperQueryExpression wqe = wrapperQueryExpresssion.clone();
+					wqe.setQueryExpression(null);
+					return wqe;
+				}else {
+					return null;
+				}
+        	}else {
+        		return null;
+        	}
+        	
+        }else if (catalog.isInterested(queryExpression)) {
+        	return queryExpression;
+    	}else {
+    		return null;
+    	}
+	}
+	
+	protected boolean containsTranactionReceipts(List<QueryResult> queryResults) {
+		for (QueryResult queryResult : queryResults)
+			if (queryResult.getCatalogReceipts() != null)
+				return true;
+		return false;
+	}
+
+	protected boolean containsUnbalancedCatalogInterest(List<QueryResult> queryResults) {
+		if (queryResults.size() > 0) {
+			QueryResult firstQueryResult = queryResults.get(0);
+			for (int i = 1; i < queryResults.size(); i++) {
+				QueryResult queryResult = queryResults.get(i);
+				if (!(queryResult.interestedCatalogs.containsAll(firstQueryResult.interestedCatalogs) && firstQueryResult.interestedCatalogs.containsAll(queryResult.interestedCatalogs)))
+					return true;
+			}
+			return false;
+		}else {
+			return false;
+		}
+	}
+
+	protected HashSet<String> getInterestedCatalogs(QueryExpression queryExpression, Set<String> restrictToCatalogIds) throws CatalogException, CatalogServiceException {
+		HashSet<String> interestedCatalogs = new HashSet<String>();
+		for (Catalog catalog : this.getCurrentCatalogList()) {
+			try {
+				if (restrictToCatalogIds.contains(catalog.getId())) {
+					if (catalog.isInterested(queryExpression))
+						interestedCatalogs.add(catalog.getId());
+				}
+			}catch (Exception e) {
+				if (this.oneCatalogFailsAllFail)
+					throw new CatalogException("Failed to determine if Catalog '" + catalog.getId() + "' is interested in query expression '" + queryExpression + "' : " + e.getMessage(), e);
+				else
+					LOG.log(Level.WARNING, "Failed to determine if Catalog '" + catalog.getId() + "' is interested in query expression '" + queryExpression + "' : " + e.getMessage(), e);
+			}
+		}
+		return interestedCatalogs;
+	}
+
+	protected class QueryResult {
+		
+		private QueryExpression queryExpression;
+		private List<CatalogReceipt> catalogReceipts;
+		private Set<String> interestedCatalogs;
+		
+		public QueryResult(QueryExpression queryExpression) {
+			this.queryExpression = queryExpression;
+		}
+
+		public QueryExpression getQueryExpression() {
+			return queryExpression;
+		}
+
+		public void setQueryExpression(QueryExpression queryExpression) {
+			this.queryExpression = queryExpression;
+		}
+
+		public List<CatalogReceipt> getCatalogReceipts() {
+			return catalogReceipts;
+		}
+
+		public void setCatalogReceipts(
+				List<CatalogReceipt> catalogReceipts) {
+			this.catalogReceipts = catalogReceipts;
+		}
+
+		public Set<String> getInterestedCatalogs() {
+			return interestedCatalogs;
+		}
+
+		public void setInterestedCatalogs(Set<String> interestedCatalogs) {
+			this.interestedCatalogs = interestedCatalogs;
+		}
+	
+	}
+	
+	protected class QueryResultGroup {
+		HashSet<TransactionReceipt> transactionReceipts;
+		String id;
+		
+		public QueryResultGroup(String id) {
+			this.id = id;
+			transactionReceipts = new HashSet<TransactionReceipt>();
+		}
+		
+		public HashSet<TransactionReceipt> getResults() {
+			return this.transactionReceipts;
+		}
+		
+		public void addTransactionReceipt(TransactionReceipt transactionReceipt) {
+			this.transactionReceipts.add(transactionReceipt);
+		}
+	}
+		
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/impl/CatalogServiceLocalFactory.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/impl/CatalogServiceLocalFactory.java
new file mode 100644
index 0000000..5ef8204
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/system/impl/CatalogServiceLocalFactory.java
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.system.impl;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.mapping.IngestMapperFactory;
+import org.apache.oodt.cas.catalog.repository.CatalogRepositoryFactory;
+import org.apache.oodt.cas.catalog.struct.TransactionIdFactory;
+import org.apache.oodt.cas.catalog.system.CatalogServiceFactory;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+//OODT imports
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Factory class for CatalogServiceLocal
+ * <p>
+ */
+public class CatalogServiceLocalFactory implements CatalogServiceFactory {
+
+	private static Logger LOG = Logger.getLogger(CatalogServiceLocalFactory.class.getName());
+	
+	protected CatalogRepositoryFactory catalogRepositoryFactory = null;
+	protected IngestMapperFactory ingestMapperFactory  = null;
+	protected boolean restrictQueryPermissions = false;
+	protected boolean restrictIngestPermissions = false;
+	protected TransactionIdFactory transactionIdFactory = null;
+	protected String pluginStorageDir = null;
+	protected boolean oneCatalogFailsAllFail = false;
+	protected boolean simplifyQueries = false;
+	protected boolean disableIntersectingCrossCatalogQueries = false;
+	protected int crossCatalogResultSortingThreshold = 200;
+	
+	public CatalogServiceLocalFactory() {} 
+	
+	public CatalogServiceLocal createCatalogService() {
+		try {
+			return new CatalogServiceLocal(this.catalogRepositoryFactory.createRepository(), this.ingestMapperFactory.createMapper(), new File(this.pluginStorageDir), this.transactionIdFactory, this.restrictQueryPermissions, this.restrictIngestPermissions, this.oneCatalogFailsAllFail, this.simplifyQueries, this.disableIntersectingCrossCatalogQueries, this.crossCatalogResultSortingThreshold);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed to create CatalogServiceLocal : " + e.getMessage(), e);
+			return null;
+		}
+	}
+
+	@Required
+	public void setCatalogRepositoryFactory(CatalogRepositoryFactory catalogRepositoryFactory) {
+		this.catalogRepositoryFactory = catalogRepositoryFactory;
+	}
+
+	@Required
+	public void setIngestMapperFactory(IngestMapperFactory ingestMapperFactory) {
+		this.ingestMapperFactory = ingestMapperFactory;
+	}
+
+	@Required
+	public void setRestrictQueryPermissions(boolean restrictQueryPermissions) {
+		this.restrictQueryPermissions = restrictQueryPermissions;
+	}
+
+	@Required
+	public void setRestrictIngestPermissions(boolean restrictIngestPermissions) {
+		this.restrictIngestPermissions = restrictIngestPermissions;
+	}
+
+	@Required
+	public void setTransactionIdFactory(String transactionIdFactory) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+		this.transactionIdFactory = (TransactionIdFactory) Class.forName(transactionIdFactory).newInstance();
+	}
+	
+	@Required
+	public void setPluginStorageDir(String pluginStorageDir) {
+		this.pluginStorageDir = pluginStorageDir;
+	}
+	
+	@Required
+	public void setOneCatalogFailsAllFail(boolean oneCatalogFailsAllFail) {
+		this.oneCatalogFailsAllFail = oneCatalogFailsAllFail;
+	}
+
+	@Required
+	public void setSimplifyQueries(boolean simplifyQueries) {
+		this.simplifyQueries = simplifyQueries;
+	}
+	
+	@Required
+	public void setDisableIntersectingCrossCatalogQueries(boolean disableIntersectingCrossCatalogQueries) {
+		this.disableIntersectingCrossCatalogQueries = disableIntersectingCrossCatalogQueries;
+	}
+
+	@Required
+	public void setCrossCatalogResultSortingThreshold(
+			int crossCatalogResultSortingThreshold) {
+		this.crossCatalogResultSortingThreshold = crossCatalogResultSortingThreshold;
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/term/Bucket.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/term/Bucket.java
new file mode 100644
index 0000000..8f9b9af
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/term/Bucket.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.term;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Bucket represents an ingestable or queriable group
+ * <p>
+ */
+public class Bucket {
+
+	private String name;
+	
+	public Bucket() {
+		this.name = "Default";
+	}
+	
+	public Bucket(String name) {
+		this.name = name;
+	}
+	
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+	public String getName() {
+		return this.name;
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/term/Term.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/term/Term.java
new file mode 100644
index 0000000..653a9ca
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/term/Term.java
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.term;
+
+//JDK imports
+import java.util.Collections;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A ingestable or queriable item
+ * <p>
+ */
+public class Term implements Cloneable {
+
+	protected String name;
+	protected List<String> values;
+	protected Type type;
+	public enum Type { 
+		xml_boolean,
+		xml_base64Binary,
+		xml_hexBinary,
+		xml_anyURI,
+		xml_language,
+		xml_normalizedString,
+		xml_string,
+		xml_token,
+		xml_byte,
+		xml_decimal,
+		xml_double,
+		xml_float,
+		xml_int,
+		xml_integer,
+		xml_long,
+		xml_negativeInteger,
+		xml_nonNegativeInteger,
+		xml_nonPositiveInteger,
+		xml_positiveInteger,
+		xml_short,
+		xml_unsignedByte,
+		xml_unsignedInt,
+		xml_unsignedLong,
+		xml_unsignedShort,
+		xml_date,
+		xml_dateTime,
+		xml_duration,
+		xml_gDay,
+		xml_gMonth,
+		xml_gMonthDay,
+		xml_gYear,
+		xml_gYearMonth,
+		xml_time,
+		xml_Name,
+		xml_NCName,
+		xml_NOTATION,
+		xml_QName,
+		xml_ENTITY,
+		xml_ENTITIES,
+		xml_ID,
+		xml_IDREF,
+		xml_IDREFS,
+		xml_NMTOKEN,
+		xml_NMTOKENS,
+		xml_anyType,
+		xml_anySimpleType
+	};
+	
+	public Term() {
+		this.type = Type.xml_string;
+		this.values = Collections.emptyList();
+	}
+	
+	public Term(String name) {
+		this();
+		this.name = name;
+	}
+	
+	public Term(String name, List<String> values) {
+		this(name);
+		this.setValues(values);
+	}
+	
+	public Term(String name, List<String> values, Type type) {
+		this(name, values);
+		if (type != null)
+			this.type = type;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public List<String> getValues() {
+		return values;
+	}
+
+	public void setValues(List<String> values) {
+		this.values = new Vector<String>(values);
+	}
+	
+	public String getFirstValue() {
+		String firstValue = null;
+		if (this.values.size() > 0)
+			firstValue = this.values.get(0);
+		return firstValue; 
+	}
+
+	public Type getType() {
+		return type;
+	}
+
+	public void setType(Type type) {
+		this.type = type;
+	}
+	
+	@Override
+	public int hashCode() {
+		return this.name.hashCode();
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+		if (obj instanceof Term) {
+			Term compareToTerm = (Term) obj;
+			return (this.name.equals(compareToTerm.name)
+					&& this.type.equals(compareToTerm.type)
+					&& this.values.containsAll(compareToTerm.values) && compareToTerm.values
+					.containsAll(this.values));
+		}else {
+			return false;
+		}
+	}
+	
+	@Override
+	public Term clone() {
+		return new Term(this.name, this.values, this.type);
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/term/TermBucket.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/term/TermBucket.java
new file mode 100644
index 0000000..4d3ed78
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/term/TermBucket.java
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.term;
+
+//JDK imports
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Bucket which has Terms attached to it
+ * <p>
+ */
+public class TermBucket extends Bucket {
+
+	private HashMap<String, Term> terms;
+	
+	public TermBucket() {
+		super();
+		this.terms = new HashMap<String, Term>();
+	}
+	
+	public TermBucket(String name) {
+		super(name);
+		this.terms = new HashMap<String, Term>();
+	}
+	
+	public TermBucket(String name, Set<Term> terms) {
+		this(name);
+		this.setTerms(terms);
+	}
+	
+	public void setTerms(Set<Term> terms) {
+		if (terms != null) {
+			this.terms = new HashMap<String, Term>();
+			for (Term term : terms)
+				this.terms.put(term.name, term);
+		}
+	}
+	
+	public void addTerms(Set<Term> terms) {
+		this.addTerms(terms, false);
+	}
+	
+	public void addTerms(Set<Term> terms, boolean replace) {
+		if (replace) {
+			for (Term term : terms)
+				this.terms.put(term.name, term);
+		}else {
+			for (Term term : terms) {
+				Term found = this.terms.get(term.name);
+				if (found != null) {
+					List<String> newTermValues = new Vector<String>();
+					newTermValues.addAll(found.getValues());
+					newTermValues.addAll(term.getValues());
+					found.setValues(newTermValues);
+				}else {
+					this.terms.put(term.name, term);
+				}
+			}
+		}
+	}
+	
+	public void addTerm(Term term) {
+		this.addTerms(Collections.singleton(term));
+	}
+	
+	public void addTerm(Term term, boolean replace) {
+		this.addTerms(Collections.singleton(term), replace);
+	}
+	
+	public Set<Term> getTerms() {
+		return Collections.unmodifiableSet(new HashSet<Term>(this.terms.values()));
+	}
+	
+	public Term getTermByName(String termName) {
+		return this.terms.get(termName);
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/CasPropertyPlaceholderConfigurer.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/CasPropertyPlaceholderConfigurer.java
new file mode 100644
index 0000000..541cdc5
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/CasPropertyPlaceholderConfigurer.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.util;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//Spring imports
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class CasPropertyPlaceholderConfigurer extends
+        PropertyPlaceholderConfigurer {
+
+    @Override
+    protected String convertPropertyValue(String value) {
+        try {
+        	String defaultValue = null;
+        	String[] splitValue = value.split(";");
+        	if (splitValue.length == 2) {
+        		value = splitValue[0];
+        		defaultValue = splitValue[1];
+        	}
+            String result = PathUtils.doDynamicReplacement(value);
+            if (result.equals("null"))
+            	return defaultValue;
+            else
+            	return result;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return value;
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/PluginClassLoader.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/PluginClassLoader.java
new file mode 100644
index 0000000..d1c7d7d
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/PluginClassLoader.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.util;
+
+//JDK imports
+import java.io.File;
+import java.io.FileFilter;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Java ClassLoader for loading plugin classes in Catalogs and QueryExpressions</p>.
+ */
+public class PluginClassLoader extends URLClassLoader {
+
+	private static final Logger LOG = Logger.getLogger(PluginClassLoader.class.getName());
+	
+	public PluginClassLoader() {
+		super(getPluginURLs());
+	}
+	
+	public PluginClassLoader(ClassLoader parent) {
+		super(new URL[0], parent);
+	}
+
+	protected void addURL(PluginURL pluginURL) {
+		super.addURL(pluginURL.getURL());
+	}
+	
+	protected void addURLs(List<URL> urls) {
+		for (URL url : urls)
+			this.addURL(url);
+	}
+	
+	public static URL[] getPluginURLs() {
+		List<URL> urls = new Vector<URL>();
+		try {
+			String pluginDirs = System.getProperty("org.apache.oodt.cas.catalog.plugin.dirs");
+			if (pluginDirs != null) {
+				for (String pluginDir : PathUtils.doDynamicReplacement(pluginDirs).split(",")) {
+					File[] jarFiles = new File(pluginDir).listFiles(new FileFilter() {
+						public boolean accept(File pathname) {
+							return pathname.getName().endsWith(".jar");
+						}					
+					});
+					for (File jarFile : jarFiles) {
+						try {
+							urls.add(jarFile.toURL());
+						}catch (Exception e) {
+							LOG.log(Level.SEVERE, "Failed to load jar file '" + jarFile + "' : " + e.getMessage(), e);
+						}
+					
+					}
+				}
+			}
+		}catch (Exception e) {}
+		return urls.toArray(new URL[urls.size()]);
+	}
+	
+	public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+		try {
+			Class<?> clazz = this.findLoadedClass(name);
+			if (clazz == null)
+				clazz = this.findClass(name);
+			return clazz;
+		}catch (Exception e) {}
+		return super.loadClass(name, resolve);
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/PluginURL.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/PluginURL.java
new file mode 100644
index 0000000..9f4d254
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/PluginURL.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.util;
+
+//JDK imports
+import java.net.URL;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Plugin URL for transfering Jars to server side</p>.
+ */
+public class PluginURL{
+
+	protected String catalogId;
+	protected URL url;
+	
+	public PluginURL(String catalogId, URL url) {
+		this.catalogId = catalogId;
+		this.url = url;
+	}
+	
+	public String getCatalogId() {
+		return this.catalogId;
+	}
+	
+	public URL getURL() {
+		return this.url;
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/QueryUtils.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/QueryUtils.java
new file mode 100644
index 0000000..b38caaa
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/QueryUtils.java
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.util;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.query.QueryLogicalGroup;
+import org.apache.oodt.cas.catalog.query.WrapperQueryExpression;
+import org.apache.oodt.cas.catalog.query.filter.QueryFilter;
+import org.apache.oodt.cas.catalog.query.parser.ParseException;
+import org.apache.oodt.cas.catalog.query.parser.QueryParser;
+import org.apache.oodt.cas.catalog.query.parser.TokenMgrError;
+
+//OODT imports
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * Utilities for helping filter query results
+ * <p>
+ */
+public class QueryUtils {
+
+	public static List<TransactionalMetadata> filterMetadata(QueryFilter<?> queryFilter, List<TransactionalMetadata> metadataList) {
+		return queryFilter.filterMetadataList(metadataList);
+	}
+	
+	public static List<TransactionalMetadata> sort(List<TransactionalMetadata> metadataList, String sortByMetadataKey) {
+		return null;
+	}
+	
+	public static QueryExpression simplifyQuery(QueryExpression queryExpression) {
+		return _simplifyQuery(queryExpression.clone());
+	}
+	
+	/**
+	 * Might later be factored out into a Query Normalizer Interface . . . this method currently compacts AND(s).
+	 * @param queryExpression Query to be simplified
+	 * @return simplified query
+	 */
+	private static QueryExpression _simplifyQuery(QueryExpression queryExpression) {
+		if (queryExpression instanceof QueryLogicalGroup) {
+			QueryLogicalGroup.Operator operator = ((QueryLogicalGroup) queryExpression).getOperator();
+			boolean changed;
+			do {
+				changed = false;
+				Vector<QueryExpression> children = new Vector<QueryExpression>();
+				for (QueryExpression qe : ((QueryLogicalGroup) queryExpression).getExpressions()) {
+					if (qe instanceof QueryLogicalGroup && ((QueryLogicalGroup) qe).getOperator().equals(operator)) {
+						children.addAll(((QueryLogicalGroup) qe).getExpressions());
+						changed = true;
+					}else {
+						children.add(qe);
+					}
+				}
+				((QueryLogicalGroup) queryExpression).setExpressions(children);
+			}while(changed);
+		}else if (queryExpression instanceof WrapperQueryExpression) {
+			((WrapperQueryExpression) queryExpression).setQueryExpression(((WrapperQueryExpression) queryExpression).getQueryExpression());
+		}
+		return queryExpression;
+	}
+	
+	public static void main(String[] args) throws ParseException, TokenMgrError {
+		QueryExpression qe = QueryParser.parseQueryExpression("{bucketNames = 'joe,tim' ; Name == 'Tim,Joe' AND City == 'Upland' AND State == 'CA'}");
+		System.out.println(qe.toString());
+		System.out.println(simplifyQuery(qe).toString());
+		System.out.println("");
+		qe = QueryParser.parseQueryExpression("Name == 'Tim,Joe' AND (City == 'Upland' AND State == 'CA')");
+		System.out.println(qe.toString());
+		System.out.println(simplifyQuery(qe).toString());
+	}
+	
+//	public static QueryExpression convertAndsToOrs(QueryExpression queryExpression) {
+//		if (queryExpression instanceof QueryLogicalGroup) {
+//			if (((QueryLogicalGroup) queryExpression).getOperator().equals(QueryLogicalGroup.Operator.AND)) {
+//				QueryLogicalGroup convertedQueryExpression = new QueryLogicalGroup();
+//				convertedQueryExpression.setOperator(QueryLogicalGroup.Operator.OR);
+//				for (QueryExpression subQueryExpression : ((QueryLogicalGroup) queryExpression).getExpressions())
+//					convertedQueryExpression.addExpression(new NotQueryExpression(convertAndsToOrs(subQueryExpression)));
+//				return new NotQueryExpression(convertedQueryExpression);
+//			}else {
+//				QueryLogicalGroup convertedQueryExpression = new QueryLogicalGroup();
+//				convertedQueryExpression.setOperator(QueryLogicalGroup.Operator.OR);
+//				for (QueryExpression subQueryExpression : ((QueryLogicalGroup) queryExpression).getExpressions()) 
+//					convertedQueryExpression.addExpression(convertAndsToOrs(subQueryExpression));
+//				return convertedQueryExpression;
+//			}
+//		}else if (queryExpression instanceof NotQueryExpression) {
+//			return new NotQueryExpression(convertAndsToOrs(((NotQueryExpression) queryExpression).getQueryExpression()));
+//		}else {
+//			return queryExpression;
+//		}
+//	}
+//	
+//	public static QueryExpression reduceNots(QueryExpression queryExpression) {
+//		if (queryExpression instanceof NotQueryExpression) {
+//			NotQueryExpression notQueryExpression = (NotQueryExpression) queryExpression;
+//			if (notQueryExpression.getQueryExpression() instanceof QueryLogicalGroup && ((QueryLogicalGroup) notQueryExpression.getQueryExpression()).getOperator().equals(QueryLogicalGroup.Operator.OR)) {
+//				QueryLogicalGroup queryLogicalGroup = (QueryLogicalGroup) notQueryExpression.getQueryExpression();
+//				QueryLogicalGroup newQueryLogicalGroup = new QueryLogicalGroup();
+//				newQueryLogicalGroup.setOperator(QueryLogicalGroup.Operator.AND);
+//				for (QueryExpression subQueryExpression : queryLogicalGroup.getExpressions()) {
+//					if (subQueryExpression instanceof NotQueryExpression) {
+//						newQueryLogicalGroup.addExpression(reduceNots(((NotQueryExpression) subQueryExpression).getQueryExpression()));
+//					}else {
+//						newQueryLogicalGroup.addExpression(new NotQueryExpression(reduceNots(subQueryExpression)));
+//					}
+//				}
+//				return newQueryLogicalGroup;
+//			}else {
+//				return new NotQueryExpression(reduceNots(notQueryExpression.getQueryExpression()));
+//			}
+//		}else if (queryExpression instanceof QueryLogicalGroup){
+//			QueryLogicalGroup queryLogicalGroup = (QueryLogicalGroup) queryExpression;
+//			QueryLogicalGroup newQueryLogicalGroup = new QueryLogicalGroup();
+//			newQueryLogicalGroup.setOperator(queryLogicalGroup.getOperator());
+//			for (QueryExpression subQueryExpression : queryLogicalGroup.getExpressions())
+//				newQueryLogicalGroup.addExpression(reduceNots(subQueryExpression));
+//			return newQueryLogicalGroup;
+//		}else {
+//			return queryExpression;
+//		}
+//	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/Serializer.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/Serializer.java
new file mode 100644
index 0000000..c807b08
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/Serializer.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.util;
+
+//JDK imports
+import java.io.InputStream;
+import java.io.OutputStream;
+
+//XStream imports
+import com.thoughtworks.xstream.XStream;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class Serializer {
+
+	protected ClassLoader classLoader;
+	protected boolean usePluginUrls;
+	
+	public Serializer() {
+		this(true);
+	}
+
+	public Serializer(boolean usePluginUrls) {
+		this.usePluginUrls = usePluginUrls;
+		this.refreshClassLoader();
+	}
+	
+	public void refreshClassLoader() {
+		if (usePluginUrls)
+			this.classLoader = new PluginClassLoader();
+		else
+			this.classLoader = Serializer.class.getClassLoader();
+	}
+	
+	public void setUsePluginUrls(boolean usePluginUrls) {
+		this.usePluginUrls = usePluginUrls;
+	}
+
+	public ClassLoader getClassLoader() {
+		return classLoader;
+	}
+	
+	/**
+	 * Serializes any java object into a java Serializable String
+	 * @param <T> Object type to be serialized
+	 * @param object The Object of type <T> to be serialized
+	 * @return A String for of the object arg
+	 */
+	public <T> String serializeObject(T object) {
+		XStream xStream = new XStream();
+		return xStream.toXML(object);
+	}
+	
+	public <T> void serializeObject(T object, OutputStream outStream) {
+		XStream xStream = new XStream();
+		xStream.toXML(object, outStream);
+	}
+	
+	/**
+	 * Deserializes any object that has been serialized by the serializedObject(T) method
+	 * @param <T> Type of Object that was originally serialized
+	 * @param clazz The class object representation of the object type
+	 * @param xmlObject The String for of the object to be deserialized
+	 * @return The deserialized object
+	 * @throws ClassNotFoundException
+	 * @throws InstantiationException
+	 * @throws IllegalAccessException
+	 */
+	public <T> T deserializeObject(Class<T> clazz, String xmlObject) {
+		XStream xStream = new XStream();
+		xStream.setClassLoader(getClassLoader());
+		return (T) xStream.fromXML(xmlObject);
+	}
+	
+	public <T> T deserializeObject(Class<T> clazz, InputStream inStream) {
+		XStream xStream = new XStream();
+		xStream.setClassLoader(getClassLoader());
+		return (T) xStream.fromXML(inStream);
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/SpringUtils.java b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/SpringUtils.java
new file mode 100644
index 0000000..f9bbd55
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/java/org/apache/oodt/cas/catalog/util/SpringUtils.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.util;
+
+//JDK imports
+import java.util.HashSet;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.catalog.system.Catalog;
+
+//Spring imports
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class SpringUtils {
+
+	private static Logger LOG = Logger.getLogger(SpringUtils.class.getName());
+	
+	public static HashSet<Catalog> loadCatalogs(String catalogBeanRepo) throws Exception {
+        FileSystemXmlApplicationContext appContext = new FileSystemXmlApplicationContext(catalogBeanRepo);
+        Map<String, Catalog> catalogsMap = appContext.getBeansOfType(Catalog.class);
+        HashSet<Catalog> catalogs = new HashSet<Catalog>();
+        for (String key : catalogsMap.keySet()) {
+        	Catalog curCatalog = catalogsMap.get(key);
+        	LOG.log(Level.INFO, "Loading catalog configuration for Catalog: '" + curCatalog + "'");
+        	if (catalogs.contains(curCatalog))
+        		throw new Exception("Catalog URN : '" + curCatalog + "' conflicts with another Catalog's URN.  **NOTE: URNs are created based on the following rule: urn:<namespace>:<id or name (if set)>");
+        	catalogs.add(curCatalog);
+        }
+        return catalogs;
+	}
+	
+}
diff --git a/0.8.1-rc1/catalog/src/main/resources/REMOVE.log b/0.8.1-rc1/catalog/src/main/resources/REMOVE.log
new file mode 100644
index 0000000..4f706a1
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/REMOVE.log
@@ -0,0 +1,19 @@
+###########################################################################
+# 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.
+###########################################################################
+
+You can remove this file. It was only included to ensure that the log directory for this
+distribution was created on assembly.
diff --git a/0.8.1-rc1/catalog/src/main/resources/logging.properties b/0.8.1-rc1/catalog/src/main/resources/logging.properties
new file mode 100644
index 0000000..678a422
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/logging.properties
@@ -0,0 +1,56 @@
+###########################################################################
+# 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.
+###########################################################################
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.FileHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = ../logs/cas_catalog%g.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 5
+java.util.logging.FileHandler.append = true
+java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = INFO
+httpclient.wire.header.level = INFO
+httpclient.wire.level = INFO
+
+# airs dom loggin
+sun.rmi.level = INFO
+
+# spring framework logging
+org.springframework.beans.level = SEVERE
+org.springframework.core.level = SEVERE
+org.springframework.level = SEVERE
+org.springframework.beans.factory.level = SEVERE
+org.springframework.beans.factory.config.level = SEVERE
+org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.level = SEVERE
+org.apache.oodt.cas.crawl.util.CasPropertyPlaceholderConfigurer.level = SEVERE
+sun.net.level = SEVERE
diff --git a/0.8.1-rc1/catalog/src/main/resources/oracle/create-transaction-id-map-table.sql b/0.8.1-rc1/catalog/src/main/resources/oracle/create-transaction-id-map-table.sql
new file mode 100644
index 0000000..b5f0181
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/oracle/create-transaction-id-map-table.sql
@@ -0,0 +1,29 @@
+ -- 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.
+ 
+CREATE TABLE CatalogServiceMapper (
+  CAT_SERV_TRANS_ID VARCHAR2(255) NOT NULL ,
+  CAT_SERV_TRANS_FACTORY VARCHAR2(255) NOT NULL ,
+  CAT_TRANS_ID VARCHAR2(255) NOT NULL ,
+  CAT_TRANS_FACTORY VARCHAR2(255) NOT NULL ,
+  CAT_TRANS_DATE VARCHAR2(255) NOT NULL ,
+  CATALOG_ID VARCHAR2(255) NOT NULL
+);
+
+CREATE INDEX CatalogServiceMapper_CSTId_idx ON CatalogServiceMapper(CAT_SERV_TRANS_ID);  
+CREATE INDEX CatalogServiceMapper_CTId_idx ON CatalogServiceMapper(CAT_TRANS_ID);  
+CREATE INDEX CatalogServiceMapper_CatId_idx ON CatalogServiceMapper(CATALOG_ID);  
+
+EXIT;
diff --git a/0.8.1-rc1/catalog/src/main/resources/oracle/create-transaction-index-table.sql b/0.8.1-rc1/catalog/src/main/resources/oracle/create-transaction-index-table.sql
new file mode 100644
index 0000000..d89271d
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/oracle/create-transaction-index-table.sql
@@ -0,0 +1,31 @@
+ -- 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.
+ 
+CREATE TABLE transactions
+(
+  transaction_id varchar2(256) NOT NULL,
+  transaction_date varchar2(256) NOT NULL
+);
+
+CREATE TABLE transaction_terms
+(
+  transaction_id varchar2(256) NOT NULL,
+  bucket_name varchar2(256) NOT NULL,
+  term_name varchar2(256) NOT NULL,
+  term_value varchar2(1000) NOT NULL
+);
+
+CREATE INDEX transactions_transid_idx ON transactions(transaction_id);  
+CREATE INDEX transaction_terms_transid_idx ON transaction_terms(transaction_id);  
\ No newline at end of file
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/catserv-beans.xml b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-beans.xml
new file mode 100644
index 0000000..da9a6e0
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-beans.xml
@@ -0,0 +1,71 @@
+<?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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor" />
+
+	<!-- Catalog Services -->
+	<bean id="CatalogServiceLocalFactory" lazy-init="true" class="org.apache.oodt.cas.catalog.system.impl.CatalogServiceLocalFactory">
+		<property name="transactionIdFactory" value="org.apache.oodt.cas.catalog.struct.impl.transaction.UuidTransactionIdFactory" />
+		<property name="catalogRepositoryFactory" ref="SerializedCatalogRepositoryFactory" />
+		<property name="ingestMapperFactory" ref="InMemoryIngestMapperFactory" />
+		<property name="pluginStorageDir" value="${pcs.support.home}/cas-catalog/plugin-jars/" />
+		<property name="restrictQueryPermissions" value="false" />
+		<property name="restrictIngestPermissions" value="false" />
+		<property name="oneCatalogFailsAllFail" value="true" />
+		<property name="simplifyQueries" value="true" />
+		<property name="disableIntersectingCrossCatalogQueries" value="false" />
+		<property name="crossCatalogResultSortingThreshold" value="200" />
+	</bean>
+
+	<!-- Communication Channels -->
+	<bean id="XmlRpcServerFactory" lazy-init="true" class="org.apache.oodt.cas.catalog.server.channel.xmlrpc.XmlRpcCommunicationChannelServerFactory">
+		<property name="port" value="${catalog.port}" />
+		<property name="catalogServiceFactory" ref="CatalogServiceLocalFactory" />
+	</bean>
+
+	<!-- Catalog Repositories -->
+	<bean id="SpringCatalogRepositoryFactory" lazy-init="true" class="org.apache.oodt.cas.catalog.repository.SpringCatalogRepositoryFactory">
+		<property name="catalogBeanRepo" value="${catalog.home}/policy/filemgr-catalog-beans.xml" />
+	</bean>
+	<bean id="WorkflowManagerRepositoryFactory" lazy-init="true" class="org.apache.oodt.cas.catalog.repository.SpringCatalogRepositoryFactory">
+		<property name="catalogBeanRepo" value="${catalog.home}/policy/workflow-manager-beans.xml" />
+	</bean>
+	<bean id="SerializedCatalogRepositoryFactory" lazy-init="true" class="org.apache.oodt.cas.catalog.repository.SerializedCatalogRepositoryFactory">
+		<property name="storageDir" value="${pcs.support.home}/cas-catalog/catalog-repo" />
+	</bean>
+
+	<!-- Mapper Indexes -->
+	<bean id="DataSourceIngestMapperFactory" lazy-init="true" class="org.apache.oodt.cas.catalog.mapping.DataSourceIngestMapperFactory">
+		<property name="jdbcUrl" value="jdbc:oracle:thin:@dew.jpl.nasa.gov:1521:npptest" />
+		<property name="user" value="sa" />
+		<property name="pass" value="" />
+		<property name="driver" value="oracle.jdbc.driver.OracleDriver" />
+	</bean>
+	<bean id="InMemoryIngestMapperFactory" lazy-init="true" class="org.apache.oodt.cas.catalog.mapping.InMemoryIngestMapperFactory">
+		<property name="jdbcUrl" value="jdbc:hsqldb:file:${pcs.support.home}/hsqldb;shutdown=true" />
+		<property name="user" value="sa" />
+		<property name="pass" value="" />
+		<property name="driver" value="org.hsqldb.jdbcDriver" />
+		<property name="tablesFile" value="${catalog.home}/policy/in-memory-ingest-mapper.sql" />
+	</bean>
+	<bean id="MemoryBasedIngestMapperFactory" lazy-init="true" class="org.apache.oodt.cas.catalog.mapping.MemoryBasedIngestMapperFactory" />
+
+</beans>
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/catserv-client-action-beans.xml b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-client-action-beans.xml
new file mode 100644
index 0000000..bd767d5
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-client-action-beans.xml
@@ -0,0 +1,51 @@
+<?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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+    
+    <bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor"/>    
+    
+    <bean id="shutdown" class="org.apache.oodt.cas.catalog.server.action.ShutdownServerAction">
+        <property name="description" value="Shuts down the server for which the given client connects"/>
+    </bean>
+    <bean id="query_all" class="org.apache.oodt.cas.catalog.server.action.QueryServerAction">
+        <property name="description" value="Performs a un-paged query to the server which the given client connects"/>        
+    </bean>
+    <bean id="reduced_query_all" class="org.apache.oodt.cas.catalog.server.action.ReducedQueryServerAction">
+        <property name="description" value="Performs a un-paged query to the server which the given client connects"/>        
+    </bean>
+    <bean id="query_paged" class="org.apache.oodt.cas.catalog.server.action.PagedQueryServerAction">
+        <property name="description" value="Performs a paged query to the server which the given client connects"/>        
+    </bean>
+    <bean id="reduced_query_paged" class="org.apache.oodt.cas.catalog.server.action.ReducedPagedQueryServerAction">
+        <property name="description" value="Performs a paged query to the server which the given client connects"/>        
+    </bean>
+    <bean id="load_catalogs" class="org.apache.oodt.cas.catalog.server.action.LoadCatalogsServerAction">
+        <property name="description" value="Loads the catalogs from the given spring xml file into the server for which the given client connects"/>        
+    </bean>
+    <bean id="load_catalog_repo" class="org.apache.oodt.cas.catalog.server.action.LoadCatalogRepositoryServerAction">
+        <property name="description" value="Loads the catalogs from the given repository from the given spring xml file into the server for which the given client connects"/>        
+    </bean>
+    <bean id="get_catalog_ids" class="org.apache.oodt.cas.catalog.server.action.GetSupportedCatalogIds">
+        <property name="description" value="Gets a list of supported catalog ids from the server which the given client connects"/>        
+    </bean>
+    
+</beans>
+
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/catserv-client-cmd-line-beans.xml b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-client-cmd-line-beans.xml
new file mode 100644
index 0000000..a07f191
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-client-cmd-line-beans.xml
@@ -0,0 +1,302 @@
+<?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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+    
+    <bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor"/>
+    
+    <!-- CAS-Catalog Cmd-Line-Options -->
+    <bean id="action" class="org.apache.oodt.commons.option.CmdLineOption">
+        <property name="shortOption" value="a"/>
+        <property name="longOption" value="action"/>
+        <property name="description" value="The CatalogService Action Bean to run"/>
+        <property name="hasArgs" value="true"/>
+        <property name="optionArgName" value="bean id"/>
+        <property name="required" value="true"/>
+    </bean>
+    
+    <bean id="clientFactoryBeanId" class="org.apache.oodt.commons.option.CmdLineOption">
+        <property name="shortOption" value="cfb"/>
+        <property name="longOption" value="clientFactoryBeanId"/>
+        <property name="description" value="CatalogServiceClientFactory Bean Id"/>
+        <property name="hasArgs" value="true"/>
+        <property name="optionArgName" value="bean id"/>
+        <property name="required" value="true"/>
+    </bean>
+    
+    <bean id="query" class="org.apache.oodt.commons.option.CmdLineOption">
+        <property name="shortOption" value="q"/>
+        <property name="longOption" value="query"/>
+        <property name="description" value="CatalogService String Query"/>
+        <property name="hasArgs" value="true"/>
+        <property name="optionArgName" value="query"/>
+        <property name="requiredOptions">
+            <list>
+                <bean class="org.apache.oodt.commons.option.required.RequiredOption">
+                    <property name="optionLongName" value="action"/>
+                    <property name="requireAllValues" value="false"/>
+                    <property name="optionValues">
+                        <list>
+                            <value>query_all</value>
+                            <value>reduced_query_all</value>
+                            <value>query_paged</value>
+                            <value>reduced_query_paged</value>                            
+                        </list>
+                    </property>
+                </bean>
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.commons.option.handler.CmdLineOptionBeanHandler">
+                <property name="applyToBeans">
+                    <list>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo"
+                            p:bean-ref="query_all"/>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo"
+                            p:bean-ref="reduced_query_all"/>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo"
+                            p:bean-ref="query_paged"/>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo"
+                            p:bean-ref="reduced_query_paged"/>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+    
+    <bean id="pageSize" class="org.apache.oodt.commons.option.CmdLineOption">
+        <property name="shortOption" value="ps"/>
+        <property name="longOption" value="pageSize"/>
+        <property name="description" value="Paged Query PageSize"/>
+        <property name="hasArgs" value="true"/>
+        <property name="optionArgName" value="integer"/>
+        <property name="type" value="int"/>
+        <property name="requiredOptions">
+            <list>
+                <bean class="org.apache.oodt.commons.option.required.RequiredOption">
+                    <property name="optionLongName" value="action"/>
+                    <property name="requireAllValues" value="false"/>
+                    <property name="optionValues">
+                        <list>
+                            <value>query_paged</value>
+                            <value>reduced_query_paged</value>
+                        </list>
+                    </property>
+                </bean>
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.commons.option.handler.CmdLineOptionBeanHandler">
+                <property name="applyToBeans">
+                    <list>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo"
+                            p:bean-ref="query_paged"/>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo"
+                            p:bean-ref="reduced_query_paged"/>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+    
+    <bean id="pageNum" class="org.apache.oodt.commons.option.CmdLineOption">
+        <property name="shortOption" value="pn"/>
+        <property name="longOption" value="pageNum"/>
+        <property name="description" value="Paged Query PageNum"/>
+        <property name="hasArgs" value="true"/>
+        <property name="optionArgName" value="integer"/>
+        <property name="type" value="int"/>
+        <property name="requiredOptions">
+            <list>
+                <bean class="org.apache.oodt.commons.option.required.RequiredOption">
+                    <property name="optionLongName" value="action"/>
+                    <property name="requireAllValues" value="false"/>
+                    <property name="optionValues">
+                        <list>
+                            <value>query_paged</value>
+                            <value>reduced_query_paged</value>                            
+                        </list>
+                    </property>
+                </bean>
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.commons.option.handler.CmdLineOptionBeanHandler">
+                <property name="applyToBeans">
+                    <list>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo"
+                            p:bean-ref="query_paged"/>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo"
+                            p:bean-ref="reduced_query_paged"/>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+    
+    <bean id="reducedTerms" class="org.apache.oodt.commons.option.CmdLineOption">
+        <property name="shortOption" value="rt"/>
+        <property name="longOption" value="reducedTerms"/>
+        <property name="description" value="Term filter for query results"/>
+        <property name="hasArgs" value="true"/>
+        <property name="optionArgName" value="list"/>
+        <property name="type" value="java.util.List"/>        
+        <property name="requiredOptions">
+            <list>
+                <bean class="org.apache.oodt.commons.option.required.RequiredOption">
+                    <property name="optionLongName" value="action"/>
+                    <property name="requireAllValues" value="false"/>
+                    <property name="optionValues">
+                        <list>
+                            <value>reduced_query_all</value>
+                            <value>reduced_query_paged</value>                            
+                        </list>
+                    </property>
+                </bean>
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.commons.option.handler.CmdLineOptionBeanHandler">
+                <property name="applyToBeans">
+                    <list>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo"
+                            p:bean-ref="reduced_query_all"/>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo"
+                            p:bean-ref="reduced_query_paged"/>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+    
+    <bean id="beanId" class="org.apache.oodt.commons.option.CmdLineOption">
+        <property name="shortOption" value="bid"/>
+        <property name="longOption" value="beanId"/>
+        <property name="description" value="Spring Bean Id"/>
+        <property name="hasArgs" value="true"/>
+        <property name="optionArgName" value="bean id"/>
+        <property name="requiredOptions">
+            <list>
+                <bean class="org.apache.oodt.commons.option.required.RequiredOption">
+                    <property name="optionLongName" value="action"/>
+                    <property name="requireAllValues" value="false"/>
+                    <property name="optionValues">
+                        <list>
+                            <value>load_catalog_repo</value>
+                        </list>
+                    </property>
+                </bean>
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.commons.option.handler.CmdLineOptionBeanHandler">
+                <property name="applyToBeans">
+                    <list>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo" p:bean-ref="load_catalog_repo"/>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+    
+    <bean id="catalogIds" class="org.apache.oodt.commons.option.CmdLineOption">
+        <property name="shortOption" value="cid"/>
+        <property name="longOption" value="catalogIds"/>
+        <property name="description" value="List of Catalog IDs to query"/>
+        <property name="hasArgs" value="true"/>
+        <property name="optionArgName" value="catalog ids"/>
+        <property name="type" value="java.util.List"/>
+        <property name="handler">
+            <bean class="org.apache.oodt.commons.option.handler.CmdLineOptionBeanHandler">
+                <property name="applyToBeans">
+                    <list>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo" p:bean-ref="query_all"/>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo" p:bean-ref="reduced_query_all"/>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo" p:bean-ref="query_paged"/>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo" p:bean-ref="reduced_query_paged"/>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+    
+    <bean id="beanRepo" class="org.apache.oodt.commons.option.CmdLineOption">
+        <property name="shortOption" value="br"/>
+        <property name="longOption" value="beanRepo"/>
+        <property name="description" value="Spring Bean XML File"/>
+        <property name="hasArgs" value="true"/>
+        <property name="optionArgName" value="file path"/>
+        <property name="requiredOptions">
+            <list>
+                <bean class="org.apache.oodt.commons.option.required.RequiredOption">
+                    <property name="optionLongName" value="action"/>
+                    <property name="requireAllValues" value="false"/>
+                    <property name="optionValues">
+                        <list>
+                            <value>load_catalogs</value>
+                            <value>load_catalog_repo</value>                            
+                        </list>
+                    </property>
+                </bean>
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.commons.option.handler.CmdLineOptionBeanHandler">
+                <property name="applyToBeans">
+                    <list>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo" p:bean-ref="load_catalogs"/>
+                        <bean class="org.apache.oodt.commons.option.handler.BeanInfo" p:bean-ref="load_catalog_repo"/>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+    
+    <bean id="printSupportedActions" class="org.apache.oodt.commons.option.CmdLineOption">
+        <property name="shortOption" value="psa"/>
+        <property name="longOption" value="printSupportedActions"/>
+        <property name="description" value="Prints a list and description of all supported CatalogServiceServerActions"/>
+        <property name="hasArgs" value="false"/>
+        <property name="required" value="false"/>
+        <property name="performAndQuit" value="true"/>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.catalog.server.option.PrintSupportedActionsHandler">
+                <property name="beanRepo" value="/${catalog.home}/policy/catserv-client-config.xml"/>
+            </bean>
+        </property>
+    </bean>
+    
+    <bean id="printSupportedClients" class="org.apache.oodt.commons.option.CmdLineOption">
+        <property name="shortOption" value="psc"/>
+        <property name="longOption" value="printSupportedClients"/>
+        <property name="description" value="Prints a list and description of all supported CatalogServiceClientFactories"/>
+        <property name="hasArgs" value="false"/>
+        <property name="required" value="false"/>
+        <property name="performAndQuit" value="true"/>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.catalog.server.option.PrintSupportedClientsHandler">
+                <property name="beanRepo" value="/${catalog.home}/policy/catserv-client-config.xml"/>
+            </bean>
+        </property>
+    </bean>
+    
+</beans>
+
+
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/catserv-client-config.xml b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-client-config.xml
new file mode 100644
index 0000000..af0281a
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-client-config.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+    
+    <import resource="catserv-properties.xml"/>
+    <import resource="catserv-beans.xml"/>
+    <import resource="catserv-client-action-beans.xml"/>
+    <import resource="catserv-client-cmd-line-beans.xml"/>
+    
+</beans>
+
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/catserv-properties.xml b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-properties.xml
new file mode 100644
index 0000000..a6b625c
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-properties.xml
@@ -0,0 +1,43 @@
+<?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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+    
+    <bean class="org.apache.oodt.cas.catalog.util.CasPropertyPlaceholderConfigurer">
+        
+        <!-- Allow for system-level properties to override all properties below -->
+        <property name="systemPropertiesMode" value="2"/>
+        
+        <!-- Properties -->
+        <property name="properties">
+            <props>
+                <prop key="catalog.url">[CATALOG_URL];http://localhost:10000</prop>           
+                <prop key="catalog.port">[CATALOG_PORT];10000</prop>           
+                <prop key="pcs.support.home">[PCS_SUPPORT_HOME];/tmp</prop>       
+                <!--prop key="filemgr.home">[FILEMGR_HOME];/tmp</prop-->           
+                <prop key="workflowmgr.home">[WORKFLOWMGR_HOME];/tmp</prop>           
+                <prop key="catalog.home">[CATALOG_HOME];/tmp</prop>           
+            </props>
+        </property>
+        
+    </bean>
+    
+</beans>
+
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/catserv-server-cmd-line-beans.xml b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-server-cmd-line-beans.xml
new file mode 100644
index 0000000..dd27395
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-server-cmd-line-beans.xml
@@ -0,0 +1,51 @@
+<?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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+    <bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor"/>
+
+    <!-- CAS-Catalog Cmd-Line-Options -->
+    <bean id="serverFactoryBeanId" class="org.apache.oodt.commons.option.CmdLineOption">
+        <property name="shortOption" value="sfb"/>
+        <property name="longOption" value="serverFactoryBeanId"/>
+        <property name="description" value="CommunicationChannelServerFactory Bean Id"/>
+        <property name="hasArgs" value="true"/>
+        <property name="optionArgName" value="bean id"/>
+        <property name="required" value="true"/>
+    </bean>
+
+    <bean id="printSupportedServers" class="org.apache.oodt.commons.option.CmdLineOption">
+        <property name="shortOption" value="pss"/>
+        <property name="longOption" value="printSupportedServers"/>
+        <property name="description" value="Prints a list and description of all supported CommunicationChannelServerFactories"/>
+        <property name="hasArgs" value="false"/>
+        <property name="required" value="false"/>
+        <property name="performAndQuit" value="true"/>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.catalog.server.option.PrintSupportedServersHandler">
+                <property name="beanRepo" value="/${catalog.home}/policy/catserv-server-config.xml"/>
+            </bean>
+        </property>
+    </bean>
+
+</beans>
+
+
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/catserv-server-config.xml b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-server-config.xml
new file mode 100644
index 0000000..c7f9292
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/catserv-server-config.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+    
+    <import resource="catserv-properties.xml"/>
+    <import resource="catserv-beans.xml"/>
+    <import resource="catserv-server-cmd-line-beans.xml"/>
+    
+</beans>
+
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/cmd-line-actions.xml b/0.8.1-rc1/catalog/src/main/resources/policy/cmd-line-actions.xml
new file mode 100644
index 0000000..0316f88
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/cmd-line-actions.xml
@@ -0,0 +1,51 @@
+<?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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor" />
+
+  <!-- Command Line Actions -->
+	<bean id="shutdown" class="org.apache.oodt.cas.catalog.cli.action.ShutdownCliAction">
+		<property name="description" value="Shuts down the server for which the given client connects" />
+	</bean>
+	<bean id="query_all" class="org.apache.oodt.cas.catalog.cli.action.QueryCliAction">
+		<property name="description" value="Performs a un-paged query to the server which the given client connects" />
+	</bean>
+	<bean id="reduced_query_all" class="org.apache.oodt.cas.catalog.cli.action.ReducedQueryCliAction">
+		<property name="description" value="Performs a un-paged query to the server which the given client connects" />
+	</bean>
+	<bean id="query_paged" class="org.apache.oodt.cas.catalog.cli.action.PagedQueryCliAction">
+		<property name="description" value="Performs a paged query to the server which the given client connects" />
+	</bean>
+	<bean id="reduced_query_paged" class="org.apache.oodt.cas.catalog.cli.action.ReducedPagedQueryCliAction">
+		<property name="description" value="Performs a paged query to the server which the given client connects" />
+	</bean>
+	<bean id="load_catalogs" class="org.apache.oodt.cas.catalog.cli.action.LoadCatalogsCliAction">
+		<property name="description" value="Loads the catalogs from the given spring xml file into the server for which the given client connects" />
+	</bean>
+	<bean id="load_catalog_repo" class="org.apache.oodt.cas.catalog.cli.action.LoadCatalogRepositoryCliAction">
+		<property name="description" value="Loads the catalogs from the given repository from the given spring xml file into the server for which the given client connects" />
+	</bean>
+	<bean id="get_catalog_ids" class="org.apache.oodt.cas.catalog.cli.action.GetSupportedCatalogIdsCliAction">
+		<property name="description" value="Gets a list of supported catalog ids from the server which the given client connects" />
+	</bean>
+
+</beans>
\ No newline at end of file
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/cmd-line-options.xml b/0.8.1-rc1/catalog/src/main/resources/policy/cmd-line-options.xml
new file mode 100644
index 0000000..28253ee
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/cmd-line-options.xml
@@ -0,0 +1,317 @@
+<?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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean id="url" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="u" />
+    <property name="longOption" value="url" />
+    <property name="description" value="Server URL" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="url" />
+    <property name="required" value="true" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.url</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+    <property name="validators">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+          <property name="allowedArgs">
+            <list>
+              <value>http://.*:\d*</value>
+            </list>
+          </property>
+        </bean>
+      </list>
+    </property>
+  </bean>
+
+  <bean id="chunkSize" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="cs" />
+    <property name="longOption" value="chunkSize" />
+    <property name="description" value="XML-RPC data chunk size in bytes" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="int" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.chunkSize</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="requestTimeout" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="rqt" />
+    <property name="longOption" value="requestTimeout" />
+    <property name="description" value="XML-RPC request timeout in seconds" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="int" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.requestTimeout</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="connectionTimeout" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="ct" />
+    <property name="longOption" value="connectionTimeout" />
+    <property name="description" value="XML-RPC connection timeout in seconds" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="int" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.connectionTimeout</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+	<bean id="query" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="q" />
+		<property name="longOption" value="query" />
+		<property name="description" value="CatalogService String Query" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="query" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="query_all" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="reduced_query_all" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="query_paged" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="reduced_query_paged" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="query_all" />
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="reduced_query_all" />
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="query_paged" />
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="reduced_query_paged" />
+          </list>
+        </property>
+      </bean>
+    </property>
+	</bean>
+
+	<bean id="pageSize" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="ps" />
+		<property name="longOption" value="pageSize" />
+		<property name="description" value="Paged Query PageSize" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="integer" />
+		<property name="type" value="int" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="query_paged" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="reduced_query_paged" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="query_paged" />
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="reduced_query_paged" />
+          </list>
+        </property>
+      </bean>
+    </property>
+	</bean>
+
+	<bean id="pageNum" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="pn" />
+		<property name="longOption" value="pageNum" />
+		<property name="description" value="Paged Query PageNum" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="integer" />
+		<property name="type" value="int" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="query_paged" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="reduced_query_paged" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="query_paged" />
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="reduced_query_paged" />
+          </list>
+        </property>
+      </bean>
+    </property>
+	</bean>
+
+	<bean id="reducedTerms" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="rt" />
+		<property name="longOption" value="reducedTerms" />
+		<property name="description" value="Term filter for query results" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="list" />
+		<property name="type" value="java.util.List" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="reduced_query_all" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="reduced_query_paged" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="reduced_query_all" />
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="reduced_query_paged" />
+          </list>
+        </property>
+      </bean>
+    </property>
+	</bean>
+
+	<bean id="catalogRepositoryId" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="crid" />
+		<property name="longOption" value="catalogRepositoryId" />
+		<property name="description" value="CatalogRepository Spring Bean Id" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="bean id" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="load_catalog_repo" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="load_catalog_repo" />
+          </list>
+        </property>
+      </bean>
+    </property>
+	</bean>
+
+	<bean id="catalogIds" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="cid" />
+		<property name="longOption" value="catalogIds" />
+		<property name="description" value="List of Catalog IDs to query" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="catalog ids" />
+		<property name="type" value="java.util.List" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="query_all" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="reduced_query_all" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="query_paged" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="reduced_query_paged" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="query_all" />
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="reduced_query_all" />
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="query_paged" />
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="reduced_query_paged" />
+          </list>
+        </property>
+      </bean>
+    </property>
+	</bean>
+
+	<bean id="beanRepo" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="br" />
+		<property name="longOption" value="beanRepo" />
+		<property name="description" value="Spring Bean XML File" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="file path" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="load_catalogs" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="load_catalog_repo" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="load_catalogs" />
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="load_catalog_repo" />
+          </list>
+        </property>
+      </bean>
+    </property>
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/cmd-line-server-actions.xml b/0.8.1-rc1/catalog/src/main/resources/policy/cmd-line-server-actions.xml
new file mode 100644
index 0000000..3c835ea
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/cmd-line-server-actions.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor" />
+
+  <!-- Command Line Actions -->
+	<bean id="launchXmlRpcServer" class="org.apache.oodt.cas.catalog.server.cli.action.LaunchXmlRpcServerCliAction">
+		<property name="description" value="Brings up a Catalog Service behind an XML-RPC server" />
+	</bean>
+
+</beans>
\ No newline at end of file
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/cmd-line-server-options.xml b/0.8.1-rc1/catalog/src/main/resources/policy/cmd-line-server-options.xml
new file mode 100644
index 0000000..0f8b139
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/cmd-line-server-options.xml
@@ -0,0 +1,207 @@
+<?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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean id="port" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="p" />
+    <property name="longOption" value="port" />
+    <property name="description" value="Port number to bring up server on" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="int" />
+    <property name="required" value="true" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.port</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+    <property name="validators">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+          <property name="allowedArgs">
+            <list>
+              <value>\d+</value>
+            </list>
+          </property>
+        </bean>
+      </list>
+    </property>
+  </bean>
+
+  <bean id="transactionIdFactory" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="tidf" />
+    <property name="longOption" value="transactionIdFactory" />
+    <property name="description" value="TransactionIdFactory classpath" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.transactionid</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="repositoryFactory" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="rf" />
+    <property name="longOption" value="repositoryFactory" />
+    <property name="description" value="CatalogRepositoryFactory classpath" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.repository</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="ingestMapperFactory" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="imf" />
+    <property name="longOption" value="ingestMapperFactory" />
+    <property name="description" value="IngestMapperFactory classpath" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="int" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.ingestmapper</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="restrictQueries" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="rq" />
+    <property name="longOption" value="restrictQueries" />
+    <property name="description" value="Restrict query permissions" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.restrict.query.permissions</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="restrictIngest" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="ri" />
+    <property name="longOption" value="restrictIngest" />
+    <property name="description" value="Restrict ingest permissions" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.restrict.ingest.permissions</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="oneCatalogFailsAllFail" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="ofaf" />
+    <property name="longOption" value="oneCatalogFailsAllFail" />
+    <property name="description" value="" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.oneCatalogFailsAllFail</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="simplifyQuery" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="sq" />
+    <property name="longOption" value="simplifyQuery" />
+    <property name="description" value="Will optimize your query if true" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.simplifyQueries</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="disableCrossCatalogJoins" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="dccj" />
+    <property name="longOption" value="disableCrossCatalogJoins" />
+    <property name="description" value="Will disable queries from joining metadata that has been split across multiple catalogs" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.disableIntersectingCrossCatalogQueries</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="sortingThreshold" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="st" />
+    <property name="longOption" value="sortingThreshold" />
+    <property name="description" value="Threshold of query results at which sorting is turned off so query return time can be optimized" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+        <property name="propertyNames">
+          <list>
+            <value>org.apache.oodt.cas.catalog.crossCatalogResultSortingThreshold</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+</beans>
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/in-memory-index-cat.sql b/0.8.1-rc1/catalog/src/main/resources/policy/in-memory-index-cat.sql
new file mode 100644
index 0000000..fbbd46e
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/in-memory-index-cat.sql
@@ -0,0 +1,32 @@
+ -- 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.
+ 
+DROP TABLE transactions IF EXISTS;
+DROP TABLE transaction_terms IF EXISTS;
+
+CREATE TABLE transactions
+(
+  transaction_id varchar(256) NOT NULL,
+  transaction_date varchar(256) NOT NULL
+);
+
+CREATE TABLE transaction_terms
+(
+  transaction_id varchar(256) NOT NULL,
+  bucket_name varchar(256) NOT NULL,
+  term_name varchar(256) NOT NULL,
+  term_value varchar(1000) NOT NULL
+);
+
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/in-memory-ingest-mapper.sql b/0.8.1-rc1/catalog/src/main/resources/policy/in-memory-ingest-mapper.sql
new file mode 100644
index 0000000..571a36e
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/in-memory-ingest-mapper.sql
@@ -0,0 +1,26 @@
+ -- 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.
+ 
+DROP TABLE CatalogServiceMapper IF EXISTS;
+
+CREATE TABLE CatalogServiceMapper (
+  CAT_SERV_TRANS_ID VARCHAR(255) NOT NULL ,
+  CAT_SERV_TRANS_FACTORY VARCHAR(255) NOT NULL ,
+  CAT_TRANS_ID VARCHAR(255) NOT NULL ,
+  CAT_TRANS_FACTORY VARCHAR(255) NOT NULL ,
+  CAT_TRANS_DATE VARCHAR(255) NOT NULL ,
+  CATALOG_ID VARCHAR(255) NOT NULL
+);
+
diff --git a/0.8.1-rc1/catalog/src/main/resources/policy/workflow-catalog-beans.xml b/0.8.1-rc1/catalog/src/main/resources/policy/workflow-catalog-beans.xml
new file mode 100644
index 0000000..b641b8d
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/main/resources/policy/workflow-catalog-beans.xml
@@ -0,0 +1,56 @@
+<?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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+    
+    <bean id="WorkflowManagerCatalog" factory-bean="WorkflowManagerCatalogFactory" factory-method="createCatalog"/>
+    <bean id="WorkflowManagerCatalogFactory" class="org.apache.oodt.cas.catalog.system.CatalogFactory">
+        <property name="catalogId" value="urn:PEATE:WorkflowInstancesCatalog"/>
+        <property name="indexFactory" ref="WorkflowManagerDataSourceIndexFactory"/>
+        <property name="dictionaryFactories">
+            <list>
+                <ref bean="WorkflowManagerDictionaryFactory"/>
+            </list>
+        </property>
+        <property name="restrictQueryPermissions" value="false"/>
+        <property name="restrictIngestPermissions" value="false"/>
+    </bean>
+    
+    <!-- WorkflowManager Indexes -->
+    <bean id="WorkflowManagerDataSourceIndexFactory" class="org.apache.oodt.cas.catalog.struct.impl.index.WorkflowManagerDataSourceIndexFactory">
+        <property name="jdbcUrl" value="jdbc:oracle:thin:@dew.jpl.nasa.gov:1521:npptest"/>        
+        <property name="user" value="nppint"/>
+        <property name="pass" value="Peate"/>
+        <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
+    </bean>
+    <bean id="InMemoryIndexFactory" class="org.apache.oodt.cas.catalog.struct.impl.index.InMemoryIndexFactory">
+        <property name="jdbcUrl" value="jdbc:hsqldb:file:${pcs.support.home}/hsqldb;shutdown=true"/>        
+        <property name="user" value="sa"/>
+        <property name="pass" value=""/>
+        <property name="driver" value="org.hsqldb.jdbcDriver"/>
+        <property name="tablesFile" value="${workflowmgr.home}/policy/in-memory-index-cat.sql"/>
+    </bean>
+    
+    <!-- WorkflowManager Dictionary -->
+    <bean id="WorkflowManagerDictionaryFactory" class="org.apache.oodt.cas.catalog.struct.impl.dictionary.WorkflowManagerDictionaryFactory"/>
+    
+</beans>
+
+
diff --git a/0.8.1-rc1/catalog/src/test/java/org/apache/oodt/cas/catalog/system/impl/TestCatalogServiceLocal.java b/0.8.1-rc1/catalog/src/test/java/org/apache/oodt/cas/catalog/system/impl/TestCatalogServiceLocal.java
new file mode 100644
index 0000000..a6aff3a
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/test/java/org/apache/oodt/cas/catalog/system/impl/TestCatalogServiceLocal.java
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.catalog.system.impl;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Vector;
+
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.cas.catalog.exception.CatalogServiceException;
+import org.apache.oodt.cas.catalog.mapping.InMemoryIngestMapperFactory;
+import org.apache.oodt.cas.catalog.metadata.TransactionalMetadata;
+import org.apache.oodt.cas.catalog.page.Page;
+import org.apache.oodt.cas.catalog.page.PageInfo;
+import org.apache.oodt.cas.catalog.page.QueryPager;
+import org.apache.oodt.cas.catalog.page.TransactionReceipt;
+import org.apache.oodt.cas.catalog.query.QueryExpression;
+import org.apache.oodt.cas.catalog.query.parser.ParseException;
+import org.apache.oodt.cas.catalog.query.parser.QueryParser;
+import org.apache.oodt.cas.catalog.query.parser.TokenMgrError;
+import org.apache.oodt.cas.catalog.repository.MemoryBasedCatalogRepositoryFactory;
+import org.apache.oodt.cas.catalog.struct.impl.index.DataSourceIndexFactory;
+import org.apache.oodt.cas.catalog.struct.impl.index.InMemoryIndexFactory;
+import org.apache.oodt.cas.catalog.struct.impl.transaction.UuidTransactionIdFactory;
+import org.apache.oodt.cas.catalog.system.CatalogFactory;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class TestCatalogServiceLocal extends TestCase {
+
+	private CatalogServiceLocal cs;
+	private File testDir;
+	
+	public void setUp() {
+		try {
+			File tempFile = File.createTempFile("foo", "bar");
+			tempFile.deleteOnExit();
+			testDir = new File(tempFile.getParentFile(), "cas-catalog");
+	
+			CatalogServiceLocalFactory factory = new CatalogServiceLocalFactory();
+			factory
+					.setCatalogRepositoryFactory(new MemoryBasedCatalogRepositoryFactory());
+			factory.setIngestMapperFactory(this
+					.getOracleIngestMapperFactory(testDir.getAbsolutePath() + "/mapper"));
+			factory.setOneCatalogFailsAllFail(true);
+			factory.setSimplifyQueries(true);
+			factory.setPluginStorageDir("/dev/null");
+			factory.setRestrictIngestPermissions(false);
+			factory.setRestrictQueryPermissions(false);
+			factory.setTransactionIdFactory(UuidTransactionIdFactory.class
+					.getCanonicalName());
+			cs = factory.createCatalogService();
+	
+			CatalogFactory catalogFactory = new CatalogFactory();
+			catalogFactory.setCatalogId("TestCatalog1");
+			catalogFactory.setDictionaryFactories(null);
+			catalogFactory
+					.setIndexFactory(getInMemoryDSFactory(testDir.getAbsolutePath() + "/index/1/"));
+			catalogFactory.setRestrictIngestPermissions(false);
+			catalogFactory.setRestrictQueryPermissions(false);
+			cs.addCatalog(catalogFactory.createCatalog());
+			catalogFactory.setCatalogId("TestCatalog2");
+			catalogFactory
+					.setIndexFactory(getInMemoryDSFactory(testDir.getAbsolutePath() + "/index/2/"));
+			cs.addCatalog(catalogFactory.createCatalog());
+		}catch (Exception e) {
+			e.printStackTrace();
+			TestCase.fail(e.getMessage());
+		}
+	}
+	
+	public void tearDown() {
+		try {
+			FileUtils.forceDelete(this.testDir);
+		} catch (IOException e) {
+			e.printStackTrace();
+			TestCase.fail(e.getMessage());
+		}
+	}
+
+	public void testDataSourceCatalogIngestQueryAndDelete()
+			throws CatalogServiceException, ParseException, TokenMgrError {
+		// test ingest
+		Metadata m = new Metadata();
+		m.addMetadata("testkey1", "testval1");
+		TransactionReceipt tr = cs.ingest(m);
+		Vector<TransactionReceipt> receipts = new Vector<TransactionReceipt>();
+		receipts.add(tr);
+		List<TransactionalMetadata> metadatas = cs.getMetadata(receipts);
+		assertEquals(metadatas.size(), 1);
+		Metadata ingestedMetadata = metadatas.get(0).getMetadata();
+		assertEquals(ingestedMetadata.getMetadata("testkey1"), "testval1");
+		assertEquals(ingestedMetadata.getAllMetadata("testkey1").size(), 2);
+
+		// test ingest update
+		m.replaceMetadata(
+				CatalogServiceLocal.CATALOG_SERVICE_TRANSACTION_ID_MET_KEY, tr.getTransactionId().toString());
+		m.replaceMetadata(CatalogServiceLocal.ENABLE_UPDATE_MET_KEY, "true");
+		tr = cs.ingest(m);
+		receipts = new Vector<TransactionReceipt>();
+		receipts.add(tr);
+		metadatas = cs.getMetadata(receipts);
+		assertEquals(metadatas.size(), 1);
+		ingestedMetadata = metadatas.get(0).getMetadata();
+		assertEquals(ingestedMetadata.getMetadata("testkey1"), "testval1");
+		assertEquals(ingestedMetadata.getAllMetadata("testkey1").size(), 2);
+
+		// test query using querypager
+		QueryExpression qe = QueryParser
+				.parseQueryExpression("testkey1 == 'testval1'");
+		QueryPager pager = cs.query(qe);
+		metadatas = cs.getNextPage(pager);
+		assertEquals(metadatas.size(), 1);
+		ingestedMetadata = metadatas.get(0).getMetadata();
+		assertEquals(ingestedMetadata.getMetadata("testkey1"), "testval1");
+		assertEquals(ingestedMetadata.getAllMetadata("testkey1").size(), 2);
+
+		// test query using std paging
+		qe = QueryParser.parseQueryExpression("testkey1 == 'testval1'");
+		Page page = cs.getPage(new PageInfo(20, PageInfo.FIRST_PAGE), qe);
+		metadatas = cs.getMetadata(page);
+		assertEquals(metadatas.size(), 1);
+		ingestedMetadata = metadatas.get(0).getMetadata();
+		assertEquals(ingestedMetadata.getMetadata("testkey1"), "testval1");
+		assertEquals(ingestedMetadata.getAllMetadata("testkey1").size(), 2);
+
+		// test query using std paging with catalog restriction
+		qe = QueryParser.parseQueryExpression("testkey1 == 'testval1'");
+		page = cs.getPage(new PageInfo(20, PageInfo.FIRST_PAGE), qe,
+				Collections.singleton("TestCatalog1"));
+		metadatas = cs.getMetadata(page);
+		assertEquals(metadatas.size(), 1);
+		ingestedMetadata = metadatas.get(0).getMetadata();
+		assertEquals(ingestedMetadata.getMetadata("testkey1"), "testval1");
+		assertEquals(ingestedMetadata.getAllMetadata("testkey1").size(), 1);
+
+		// test delete
+		m = new Metadata();
+		m.addMetadata(CatalogServiceLocal.CATALOG_SERVICE_TRANSACTION_ID_MET_KEY, tr.getTransactionId().toString());
+		cs.delete(m);
+		assertEquals(cs.getMetadata(Collections.singletonList(tr)).size(), 0);
+	}
+
+	private InMemoryIngestMapperFactory getOracleIngestMapperFactory(
+			String tmpDirPath) throws SQLException, IOException {
+		String user = "sa";
+		String pass = "";
+		String driver = "org.hsqldb.jdbcDriver";
+		String url = "jdbc:hsqldb:file:" + tmpDirPath + ";shutdown=true";
+
+		InMemoryIngestMapperFactory factory = new InMemoryIngestMapperFactory();
+		factory.setDriver(driver);
+		factory.setJdbcUrl(url);
+		factory.setPass(pass);
+		factory.setUser(user);
+		factory.setTablesFile("src/test/resources/test-mapper-cat.sql");
+		return factory;
+	}
+
+	private DataSourceIndexFactory getInMemoryDSFactory(String tmpDirPath)
+			throws IOException, SQLException {
+		String user = "sa";
+		String pass = "";
+		String driver = "org.hsqldb.jdbcDriver";
+		String url = "jdbc:hsqldb:file:" + tmpDirPath + ";shutdown=true";
+
+		InMemoryIndexFactory indexFactory = new InMemoryIndexFactory();
+		indexFactory.setDriver(driver);
+		indexFactory.setJdbcUrl(url);
+		indexFactory.setPass(pass);
+		indexFactory.setUser(user);
+		indexFactory.setTablesFile("src/test/resources/test-index-cat.sql");
+		return indexFactory;
+	}
+
+}
diff --git a/0.8.1-rc1/catalog/src/test/resources/test-index-cat.sql b/0.8.1-rc1/catalog/src/test/resources/test-index-cat.sql
new file mode 100644
index 0000000..fbbd46e
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/test/resources/test-index-cat.sql
@@ -0,0 +1,32 @@
+ -- 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.
+ 
+DROP TABLE transactions IF EXISTS;
+DROP TABLE transaction_terms IF EXISTS;
+
+CREATE TABLE transactions
+(
+  transaction_id varchar(256) NOT NULL,
+  transaction_date varchar(256) NOT NULL
+);
+
+CREATE TABLE transaction_terms
+(
+  transaction_id varchar(256) NOT NULL,
+  bucket_name varchar(256) NOT NULL,
+  term_name varchar(256) NOT NULL,
+  term_value varchar(1000) NOT NULL
+);
+
diff --git a/0.8.1-rc1/catalog/src/test/resources/test-mapper-cat.sql b/0.8.1-rc1/catalog/src/test/resources/test-mapper-cat.sql
new file mode 100644
index 0000000..571a36e
--- /dev/null
+++ b/0.8.1-rc1/catalog/src/test/resources/test-mapper-cat.sql
@@ -0,0 +1,26 @@
+ -- 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.
+ 
+DROP TABLE CatalogServiceMapper IF EXISTS;
+
+CREATE TABLE CatalogServiceMapper (
+  CAT_SERV_TRANS_ID VARCHAR(255) NOT NULL ,
+  CAT_SERV_TRANS_FACTORY VARCHAR(255) NOT NULL ,
+  CAT_TRANS_ID VARCHAR(255) NOT NULL ,
+  CAT_TRANS_FACTORY VARCHAR(255) NOT NULL ,
+  CAT_TRANS_DATE VARCHAR(255) NOT NULL ,
+  CATALOG_ID VARCHAR(255) NOT NULL
+);
+
diff --git a/0.8.1-rc1/cli/README.txt b/0.8.1-rc1/cli/README.txt
new file mode 100644
index 0000000..7a05005
--- /dev/null
+++ b/0.8.1-rc1/cli/README.txt
@@ -0,0 +1,1125 @@
+CAS-CLI In a Nutshell
+
+There are 2 type of Command Line Option:
+- SimpleCmdLineOption
+- AdvancedCmdLineOption
+
+An AdvancedCmdLineOption is a SimpleCmdLineOption which is also a ValidatableCmdLineOption and HandleableCmdLineOption, which means that you would like to plug in validator and handlers to your option and let CAS-CLI run them against the argument values given to your options.  If you would like to just have CAS-CLI parse out your arguments and you want to handle and valid them yourself in your code then just use SimpleCmdLineOption.  However, I of course recommend using AdvancedCmdLineOption for reasons which this README was written :).
+
+How do i use CAS-CLI?
+First off, start by creating a directory to work in: cli-test. In it create your main class MyMain.java:
+
+import org.apache.oodt.cas.cli.CmdLineUtility;
+
+public class MyMain {
+
+   public static void main(String[] args) {
+      CmdLineUtility cmdLineUtility = new CmdLineUtility();
+      cmdLineUtility.run(args);
+   }
+}
+
+Nexted create 2 XML files (put them in the same directory as your MyMain.java): cmd-line-options.xml and cmd-line-actions.xml.  cmd-line-options.xml will contain the declaration of your supported AdvancedCmdLineOption and cmd-line-actions.xml will contain your supported CmdLineActions.  For now though, in order to show you what you get for free, create an cmd-line-options.xml file which defines now AdvancedCmdLineOption:
+
+<?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:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+</beans>
+
+Next create an cmd-line-actions.xml file with the following CmdLineAction that prints out "Hello World" when it is executed:
+
+<?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:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+  <bean id="PrintHelloWorldAction" class="org.apache.oodt.cas.cli.action.PrintMessageAction">
+    <property name="description" value="Prints out 'Hello World'" />
+    <property name="message" value="Hello World" />
+  </bean>
+</beans>
+
+Now create a logging.properties file in your cli-test directory with the following contents:
+
+org.springframework.beans.level = WARNING
+org.springframework.core.level = WARNING
+org.springframework.level = WARNING
+org.springframework.beans.factory.level = WARNING
+org.springframework.beans.factory.config.level = WARNING
+org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.level = WARNING
+
+
+Next create a script: cli-test.sh.  This should go in the cli-test directory and should look like:
+
+#!/bin/sh
+
+java \
+  -Djava.ext.dirs=. \
+  -Djava.util.logging.config.file=./logging.properties \
+        -Dorg.apache.oodt.cas.cli.action.spring.config=./cmd-line-actions.xml \
+        -Dorg.apache.oodt.cas.cli.option.spring.config=./cmd-line-options.xml \
+  MyMain "$@"
+
+Then checkout cas-cli and in the same directory as its pom.xml file run (you will need to install maven 2 if you do not have it):
+
+$ mvn package
+
+untar the *-dist.tar file in the target directory and copy all the *.jar files from the lib directory to your cli-test directory
+
+Now compile your MyMain.java:
+javac -Djava.ext.dirs=. MyMain.java
+
+Then (in your cli-test directory) execute cli-test.sh:
+
+$ ./cli-test.sh
+
+You should see:
+-----------------------------------------------------------------------------------------------------------------
+| Short | Long                                             | Description
+-----------------------------------------------------------------------------------------------------------------
+
+ -a,     --action <action-name>                             This is the name of the action to trigger
+ -h,     --help                                             Prints help menu
+ -psa,   --printSupportedActions                            Print Supported Actions
+-----------------------------------------------------------------------------------------------------------------
+
+Running cli-test.sh without any arguments is the same as running:
+
+$ ./cli-test.sh -h
+
+or
+
+$ ./cli-test.sh --help
+
+Now to see the list of supported CmdLineAction which you can run, execute:
+
+$ ./cli-test.sh -psa
+
+You should see:
+-----------------------------------------------------------------------------------------------------------------
+| Action                            | Description
+-----------------------------------------------------------------------------------------------------------------
+  PrintHelloWorldAction               Prints out 'Hello World'
+
+-----------------------------------------------------------------------------------------------------------------
+
+To see help for a specific action use the help option with the action id given as its argument value:
+
+$ ./cli-test.sh -h PrintHelloWorldAction
+
+You should see:
+** Action Help for 'PrintHelloWorldAction' **
+> DESCRIPTION:
+ Prints out 'Hello World'
+
+> USAGE:
+ Required:
+   -a [--action] PrintHelloWorldAction
+ Optional:
+
+> EXAMPLES:
+ - N/A
+
+Now to run PrintHelloWorldAction:
+
+$ ./cli-test.sh -a PrintHelloWorldAction
+
+You should see:
+Hello World
+
+So far so easy right?  Now lets take a look at the class for the action (i.e. org.apache.oodt.cas.cli.action.PrintMessageAction) we just ran and see how easy the code for it is:
+
+public class PrintMessageAction extends CmdLineAction {
+
+   private String message;
+
+   @Override
+   public void execute(ActionMessagePrinter printer) {
+      Validate.notNull(message);
+
+      printer.print(message);
+   }
+
+   @Required
+   public void setMessage(String message) {
+      this.message = message;
+   }
+
+   public String getMessage() {
+      return message;
+   }
+}
+
+As your can see it has a setter method for its variable 'message'.  The reason the PrintHelloWorldAction prints out hello is because we set the message property in the cmd-line-actions.xml file for bean id PrintMessageAction to "Hello World":
+
+    <property name="message" value="Hello World" />
+
+If we where to change that to something else, say "Bye World", it would instead print "Bye World" when PrintHelloWorldAction was run (of course then you would probably want to change its id to "ByeHelloWorldAction".  No lets see how easy it is to add our own options.  Let's make another action in cmd-line-actions.xml called "PrintMessageAction" so that cmd-line-actions.xml now looks like this:
+
+<?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:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+  <bean id="PrintHelloWorldAction" class="org.apache.oodt.cas.cli.action.PrintMessageAction">
+    <property name="description" value="Prints out 'Hello World'" />
+    <property name="message" value="Hello World" />
+  </bean>
+  <bean id="PrintMessageAction" class="org.apache.oodt.cas.cli.action.PrintMessageAction">
+    <property name="description" value="Prints out specified message" />
+  </bean>
+</beans>
+
+Notice we used the same java class and we didn't set the message property.  This is because we are going to now set this property via the command line.  Now in cmd-line-options.xml let's create add an option:
+
+<?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:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+  <bean id="printMessage" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="pm" />
+    <property name="longOption" value="printMessage" />
+    <property name="description" value="Message to print out" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="message" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+</beans>
+
+Now run:
+
+$ ./cli-test.sh -h
+
+You should see:
+-----------------------------------------------------------------------------------------------------------------
+| Short | Long                                             | Description
+-----------------------------------------------------------------------------------------------------------------
+
+ -a,     --action <action-name>                             This is the name of the action to trigger
+ -pm,    --printMessage <message>                           Message to print out
+                                                              Requirement Rules: 
+                                                               [PrintMessageAction : REQUIRED] 
+
+                                                              Handler: 
+                                                               Will invoke 'setPrintMessage' on action selected, 
+                                                               except for the following actions: 
+                                                               [PrintMessageAction : setMessage] 
+
+ -h,     --help                                             Prints help menu
+ -psa,   --printSupportedActions                            Print Supported Actions
+-----------------------------------------------------------------------------------------------------------------
+
+Notice now that we have an option --printMessage.  The description we put the for option printMessage in cmd-line-options.xml is now under description in your command line help.  Also notice the requirement rules.  The requirement rules setup for this option is: if PrintMessageAction is executed then printMessage option becomes required.  You can also see this requirement rule when running:
+
+$ ./cli-test.sh -h PrintMessageAction
+
+You should see:
+** Action Help for 'PrintMessageAction' **
+> DESCRIPTION:
+ Prints out 'Hello World'
+
+> USAGE:
+ Required:
+   -a [--action] PrintMessageAction
+   -pm [--printMessage] <message>
+ Optional:
+
+> EXAMPLES:
+ - N/A
+
+Notice that printMessage is now under the required options.  Now here is the really cool magic.  Run:
+
+$ ./cli-test.sh -a PrintMessageAction -pm "Hocus Pocus"
+
+You should see:
+Hocus Pocus
+
+We can now dynamically tell it what we want it to print out.  How does this work?  This works because we assigned a handler to the printMessage option.  The handler assigned was: org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler.  This handler takes a list of org.apache.oodt.cas.cli.option.handler.ApplyToAction beans which tell it the actionName and (optionally) the method name to invoke on that action.  So when this option is specified, the value given to the option (in this case was "Hocus Pocus") was then passed as the argument to the method setMessage(String) on the action PrintMessageAction.
+
+Options can also have static argument values, which can be used as a default argument value or as a permanent argument for an option.  Let's modify the current example to show what i mean.  Here is how you would use static argument values to make "Hello World" the default:
+
+<?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:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+  <bean id="printMessage" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="pm" />
+    <property name="longOption" value="printMessage" />
+    <property name="description" value="Message to print out" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="message" />
+    <property name="staticArgs">
+      <list>
+        <value>Hello World</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+</beans>
+
+Now execute the following:
+
+$ ./cli-test.sh -a PrintMessageAction -pm
+
+You should see:
+Hello World
+
+Then execute:
+
+./cli-test.sh -a PrintMessageAction -pm "Hocus Pocus"
+
+You should see:
+Hocus Pocus
+
+So the static argument value made printMessage option value optional.  Now the other way to use static arguments is to make an option not support argument values and use the static argument value as its permanent value.  Modify your cmd-line-options.xml to look like the following:
+
+<?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:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+  <bean id="printMessage" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="pm" />
+    <property name="longOption" value="printMessage" />
+    <property name="description" value="Message to print out" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>Hello World</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+</beans>
+
+Now execute the following:
+
+$ ./cli-test.sh -h PrintMessageAction
+
+You should see:
+
+** Action Help for 'PrintMessageAction' **
+> DESCRIPTION:
+ Prints out 'Hello World'
+
+> USAGE:
+ Required:
+   -a [--action] PrintMessageAction
+   -pm [--printMessage]
+ Optional:
+
+> EXAMPLES:
+ - N/A
+
+Notice that -pm does have <message> anymore, this means it doesn't support arguments.  Now execute:
+
+$ ./cli-test.sh -a PrintMessageAction -pm
+
+You should see:
+Hello World
+
+Now how is this useful, less change the the cmd-line-options.xml file, renaming printMessage option to printHelloWorld and add another action printByeWorld:
+
+<?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:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+  <bean id="printHelloWorld" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="phw" />
+    <property name="longOption" value="printHelloWorld" />
+    <property name="description" value="Print out 'Hello World'" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>Hello World</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="printByeWorld" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="pbw" />
+    <property name="longOption" value="printByeWorld" />
+    <property name="description" value="Print out 'Bye World'" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>Bye World</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+</beans>
+
+There are now 2 options, but i've set them both to optional because only one should be specified.  However, this is a problem because we want at least 1 specified (this will be addressed next).  For now let's see how these two options with static argument values work.  Execute the following:
+
+$ ./cli-test.sh -h PrintMessageAction
+
+You should see:
+** Action Help for 'PrintMessageAction' **
+> DESCRIPTION:
+ Prints out 'Hello World'
+
+> USAGE:
+ Required:
+   -a [--action] PrintMessageAction
+ Optional:
+   -pbw [--printByeWorld]
+   -phw [--printHelloWorld]
+
+> EXAMPLES:
+ - N/A
+
+Our two options now appear under the optional section.  Now execute:
+
+$ ./cli-test.sh -a PrintMessageAction -pbw
+
+You should see:
+Bye World
+
+Then execute:
+
+$ ./cli-test.sh -a PrintMessageAction -phw
+
+You should see:
+Hello World
+
+Now this works nice, except cas-cli is able to enforce one of the options (i.e. -pbw and -phw) to be specific so if you run the following it causes the action to print out an ERROR:
+
+$ ./cli-test.sh -a PrintMessageAction
+
+You should see:
+ERROR: Must specify message
+
+We can prevent the PrintMessageAction from having to throw this exception by, creating a group option and adding both -pbw and -phw to it.  Modify your cmd-line-options.xml to the following:
+
+<?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:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+  <bean id="print" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="p" />
+    <property name="longOption" value="print" />
+    <property name="description" value="Declare that you wish to print a message" />
+    <property name="hasArgs" value="false" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="helloWorld" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="byeWorld" p:required="false" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="helloWorld" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption" p:isSubOption="true">
+    <property name="shortOption" value="hw" />
+    <property name="longOption" value="helloWorld" />
+    <property name="description" value="Print out 'Hello World'" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>Hello World</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="byeWorld" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption" p:isSubOption="true">
+    <property name="shortOption" value="bw" />
+    <property name="longOption" value="byeWorld" />
+    <property name="description" value="Print out 'Bye World'" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>Bye World</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+</beans>
+
+So what was changed here is 'printHelloWorld' was renamed to 'helloWorld' and p:isSubOption="true" was added to it (similar was done with 'printByeWorld').  Also a group option was created and 'helloWorld' and 'byeWorld' where added as optional sub-options.  When all sub-options of a group option are option, then one of the sub-options will be required.  Now execute:
+
+$ ./cli-test.sh -h
+
+You should see:
+-----------------------------------------------------------------------------------------------------------------
+| Short | Long                                             | Description
+-----------------------------------------------------------------------------------------------------------------
+
+ -a,     --action <action-name>                             This is the name of the action to trigger
+ -p,     --print                                            Declare that you wish to print a message
+                                                              Requirement Rules: 
+                                                               [PrintMessageAction : REQUIRED] 
+
+   SubOptions:
+   > Required:
+   > Optional:
+      -hw,    --helloWorld                                  Print out 'Hello World'
+                                                              Requirement Rules: 
+                                                               [PrintMessageAction : OPTIONAL] 
+
+                                                              Handler: 
+                                                               Will invoke 'setHelloWorld' on action selected, 
+                                                               except for the following actions: 
+                                                               [PrintMessageAction : setMessage] 
+      -bw,    --byeWorld                                    Print out 'Bye World'
+                                                              Requirement Rules: 
+                                                               [PrintMessageAction : OPTIONAL] 
+
+                                                              Handler: 
+                                                               Will invoke 'setByeWorld' on action selected, 
+                                                               except for the following actions: 
+                                                               [PrintMessageAction : setMessage] 
+
+ -h,     --help                                             Prints help menu
+ -psa,   --printSupportedActions                            Print Supported Actions
+-----------------------------------------------------------------------------------------------------------------
+
+Then execute:
+
+$ ./cli-test.sh -h PrintMessageAction
+
+You should see:
+** Action Help for 'PrintMessageAction' **
+> DESCRIPTION:
+ Prints out 'Hello World'
+
+> USAGE:
+ Required:
+   -a [--action] PrintMessageAction
+   -p [--print]
+     One of:
+      -hw [--helloWorld]
+      -bw [--byeWorld]
+ Optional:
+
+> EXAMPLES:
+ - N/A
+
+Notice how "One of:" is listed under -p option, that means the on of the optional sub-options must be specified.  Now let's rerun the command which caused PrintMessageAction to throw the ERROR:
+
+$ ./cli-test.sh -a PrintMessageAction
+
+You should see:
+ERROR: Missing required options:
+ - [longOption='print',shortOption='p',description='Declare that you wish to print a message']
+
+This time cas-cli was able to realize that you are missing an option and tell you to set it.  Now let's add the -p option to the previous command:
+
+$ ./cli-test.sh -a PrintMessageAction -p
+
+You should see:
+ERROR: Must specify a subOption for group option '[longOption='print',shortOption='p',description='Declare that you wish to print a message']'
+
+You are now told by cas-cli that you need to specify a sup-option for print (thus solving the problem we had before with two optional options).  Now execute the following:
+
+$ ./cli-test.sh -a PrintMessageAction -p -hw
+
+You should see:
+Hello World
+
+Then execute:
+
+/cli-test.sh -a PrintMessageAction -p -bw
+
+You should see:
+Bye World
+
+As you can see, still the same output as before without the grouping, but have we now added the ability to have list of optional options where at least one is required.
+
+Up til now, we have just accepted that -a, -h, and -psa magically appear.  However, these are defaults that a given to you for free if you don't specify replacements.  Say for example we don't like -a or --action for the action option and instead would like -e and --execute.  We can change our cmd-line-options.xml to the following:
+
+<?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:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+  <bean id="execute" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption">
+    <property name="shortOption" value="e" />
+    <property name="longOption" value="execute" />
+    <property name="description" value="Executes the specified action" />
+    <property name="hasArgs" value="true" />
+    <property name="required" value="true" />
+  </bean>
+
+  <bean id="print" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="p" />
+    <property name="longOption" value="print" />
+    <property name="description" value="Declare that you wish to print a message" />
+    <property name="hasArgs" value="false" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="helloWorld" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="byeWorld" p:required="false" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="helloWorld" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption" p:isSubOption="true">
+    <property name="shortOption" value="hw" />
+    <property name="longOption" value="helloWorld" />
+    <property name="description" value="Print out 'Hello World'" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>Hello World</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="byeWorld" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption" p:isSubOption="true">
+    <property name="shortOption" value="bw" />
+    <property name="longOption" value="byeWorld" />
+    <property name="description" value="Print out 'Bye World'" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>Bye World</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+</beans>
+
+Now execute the following and notice that -a and --action are no longer and -e and --execute are there instead:
+
+$ ./cli-test.sh -h
+
+You should see:
+-----------------------------------------------------------------------------------------------------------------
+| Short | Long                                             | Description
+-----------------------------------------------------------------------------------------------------------------
+
+ -e,     --execute <action-name>                            Executes the specified action
+ -p,     --print                                            Declare that you wish to print a message
+                                                              Requirement Rules: 
+                                                               [PrintMessageAction : REQUIRED] 
+
+   SubOptions:
+   > Required:
+   > Optional:
+      -hw,    --helloWorld                                  Print out 'Hello World'
+                                                              Requirement Rules: 
+                                                               [PrintMessageAction : OPTIONAL] 
+
+                                                              Handler: 
+                                                               Will invoke 'setHelloWorld' on action selected, 
+                                                               except for the following actions: 
+                                                               [PrintMessageAction : setMessage] 
+      -bw,    --byeWorld                                    Print out 'Bye World'
+                                                              Requirement Rules: 
+                                                               [PrintMessageAction : OPTIONAL] 
+
+                                                              Handler: 
+                                                               Will invoke 'setByeWorld' on action selected, 
+                                                               except for the following actions: 
+                                                               [PrintMessageAction : setMessage] 
+
+ -h,     --help                                             Prints help menu
+ -psa,   --printSupportedActions                            Print Supported Actions
+-----------------------------------------------------------------------------------------------------------------
+
+Now try executing a command we ran before:
+
+$ ./cli-test.sh -a PrintMessageAction -p -bw
+
+You should see:
+ERROR: Invalid option: 'a'
+
+This is because you now have to use your new action (i.e. -e):
+
+$ ./cli-test.sh -e PrintMessageAction -p -bw
+
+You should see:
+Bye World
+
+Similarly the same can be done for help and print supported actions:
+
+<?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:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+  <bean id="execute" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption">
+    <property name="shortOption" value="e" />
+    <property name="longOption" value="execute" />
+    <property name="description" value="Executes the specified action" />
+    <property name="hasArgs" value="true" />
+    <property name="required" value="true" />
+  </bean>
+
+  <bean id="manual" class="org.apache.oodt.cas.cli.option.HelpCmdLineOption">
+    <property name="shortOption" value="man" />
+    <property name="longOption" value="manual" />
+    <property name="description" value="Print out option help" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="false" />
+  </bean>
+
+  <bean id="listActions" class="org.apache.oodt.cas.cli.option.PrintSupportedActionsCmdLineOption">
+    <property name="shortOption" value="la" />
+    <property name="longOption" value="listActions" />
+    <property name="description" value="Print out supported actions" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="false" />
+  </bean>
+
+  <bean id="print" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="p" />
+    <property name="longOption" value="print" />
+    <property name="description" value="Declare that you wish to print a message" />
+    <property name="hasArgs" value="false" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="helloWorld" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="byeWorld" p:required="false" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="helloWorld" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption" p:isSubOption="true">
+    <property name="shortOption" value="hw" />
+    <property name="longOption" value="helloWorld" />
+    <property name="description" value="Print out 'Hello World'" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>Hello World</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="byeWorld" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption" p:isSubOption="true">
+    <property name="shortOption" value="bw" />
+    <property name="longOption" value="byeWorld" />
+    <property name="description" value="Print out 'Bye World'" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>Bye World</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+</beans>
+
+Now try running:
+
+$ ./cli-test.sh -h
+
+You should see:
+ERROR: Invalid option: 'h'
+
+This is because you have replace -h and --help with -man and --manual so instead run:
+
+$ ./cli-test.sh -man
+
+You should see:
+-----------------------------------------------------------------------------------------------------------------
+| Short | Long                                             | Description
+-----------------------------------------------------------------------------------------------------------------
+
+ -e,     --execute <action-name>                            Executes the specified action
+ -p,     --print                                            Declare that you wish to print a message
+                                                              Requirement Rules: 
+                                                               [PrintMessageAction : REQUIRED] 
+
+   SubOptions:
+   > Required:
+   > Optional:
+      -hw,    --helloWorld                                  Print out 'Hello World'
+                                                              Requirement Rules: 
+                                                               [PrintMessageAction : OPTIONAL] 
+
+                                                              Handler: 
+                                                               Will invoke 'setHelloWorld' on action selected, 
+                                                               except for the following actions: 
+                                                               [PrintMessageAction : setMessage] 
+      -bw,    --byeWorld                                    Print out 'Bye World'
+                                                              Requirement Rules: 
+                                                               [PrintMessageAction : OPTIONAL] 
+
+                                                              Handler: 
+                                                               Will invoke 'setByeWorld' on action selected, 
+                                                               except for the following actions: 
+                                                               [PrintMessageAction : setMessage] 
+
+ -la,    --listActions                                      Print out supported actions
+ -man,   --manual                                           Print out option help
+-----------------------------------------------------------------------------------------------------------------
+
+Now execute:
+
+$ ./cli-test.sh -la
+
+You should see:
+-----------------------------------------------------------------------------------------------------------------
+| Action                            | Description
+-----------------------------------------------------------------------------------------------------------------
+  PrintHelloWorldAction               Prints out 'Hello World'
+
+  PrintMessageAction                  Prints out specified message
+
+-----------------------------------------------------------------------------------------------------------------
+
+At the begin of this guide it was stated that AdvancedCmdLineOption is a ValidatableCmdLineOption and HandleableCmdLineOption.  It has already been should how they are HandleableCmdLineOption by examples using handlers.  Now let's look at how they are ValidatableCmdLineOption.  Lets added another sub-option to --print which allows use to specify whatever message we want, so long as the argument value is "<someword> World":
+
+<?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:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+  <bean id="execute" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption">
+    <property name="shortOption" value="e" />
+    <property name="longOption" value="execute" />
+    <property name="description" value="Executes the specified action" />
+    <property name="hasArgs" value="true" />
+    <property name="required" value="true" />
+  </bean>
+
+  <bean id="manual" class="org.apache.oodt.cas.cli.option.HelpCmdLineOption">
+    <property name="shortOption" value="man" />
+    <property name="longOption" value="manual" />
+    <property name="description" value="Print out option help" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="false" />
+  </bean>
+
+  <bean id="listActions" class="org.apache.oodt.cas.cli.option.PrintSupportedActionsCmdLineOption">
+    <property name="shortOption" value="la" />
+    <property name="longOption" value="listActions" />
+    <property name="description" value="Print out supported actions" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="false" />
+  </bean>
+
+  <bean id="print" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="p" />
+    <property name="longOption" value="print" />
+    <property name="description" value="Declare that you wish to print a message" />
+    <property name="hasArgs" value="false" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="helloWorld" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="byeWorld" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="custom" p:required="false" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="helloWorld" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption" p:isSubOption="true">
+    <property name="shortOption" value="hw" />
+    <property name="longOption" value="helloWorld" />
+    <property name="description" value="Print out 'Hello World'" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>Hello World</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="byeWorld" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption" p:isSubOption="true">
+    <property name="shortOption" value="bw" />
+    <property name="longOption" value="byeWorld" />
+    <property name="description" value="Print out 'Bye World'" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>Bye World</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="custom" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption" p:isSubOption="true">
+    <property name="shortOption" value="c" />
+    <property name="longOption" value="custom" />
+    <property name="description" value="Print out custom message" />
+    <property name="hasArgs" value="true" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="PrintMessageAction" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="PrintMessageAction" p:methodName="setMessage" />
+          </list>
+        </property>
+      </bean>
+    </property>
+    <property name="validators">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+          <property name="allowedArgs">
+            <list>
+              <value>[^\s]+\sWorld</value>
+            </list>
+          </property>
+        </bean>
+      </list>
+    </property>
+  </bean>
+</beans>
+
+Now try executing:
+
+$ ./cli-test.sh -e PrintMessageAction -p -c "Hey World"
+
+You should see:
+Hey World
+
+Let's change it a bit:
+
+$ ./cli-test.sh -e PrintMessageAction -p -c "Hey There World"
+
+You should see:
+ERROR: Validation Failures: - Value 'Hey There World' is not allowed for option [longOption='custom',shortOption='c',description='Print out custom message'] - Allowed values = [[^\s]+\sWorld]
+
+The validator used was: org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator.  This validator takes a java Pattern supported regular expression which is enforced against the options argument values.  Other supplied validators are:
+
+AllowedArgsCmdLineOptionValidator - Argument value must be one of the supplied values
+ClassExistsCmdLineOptionValidator - Expects the argument value to be an existing java class
+FileExistCmdLineOptionValidator - Expects the argument value to be an existing file
+
diff --git a/0.8.1-rc1/cli/pom.xml b/0.8.1-rc1/cli/pom.xml
new file mode 100644
index 0000000..9a9f8f3
--- /dev/null
+++ b/0.8.1-rc1/cli/pom.xml
@@ -0,0 +1,116 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<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>
+	<parent>
+		<groupId>org.apache.oodt</groupId>
+		<artifactId>oodt-core</artifactId>
+		<version>0.8.1</version>
+		<relativePath>../core/pom.xml</relativePath>
+	</parent>
+	<artifactId>cas-cli</artifactId>
+	<name>CAS Command Line Interface</name>
+	<profiles>
+		<profile>
+			<id>audit</id>
+			<activation>
+				<activeByDefault>false</activeByDefault>
+			</activation>
+			<build>
+				<plugins>
+					<plugin>
+						<groupId>org.codehaus.mojo</groupId>
+						<artifactId>rat-maven-plugin</artifactId>
+						<configuration>
+							<excludes>
+								<exclude>**/resources/examples/**/*</exclude>
+							</excludes>
+						</configuration>
+						<executions>
+							<execution>
+								<phase>verify</phase>
+								<goals>
+									<goal>check</goal>
+								</goals>
+							</execution>
+						</executions>
+					</plugin>
+				</plugins>
+			</build>
+		</profile>
+	</profiles>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<version>2.2-beta-2</version>
+				<configuration>
+					<descriptors>
+						<descriptor>src/main/assembly/assembly.xml</descriptor>
+					</descriptors>
+				</configuration>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>single</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+	<dependencies>
+		<dependency>
+			<groupId>commons-lang</groupId>
+			<artifactId>commons-lang</artifactId>
+			<version>2.3</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-core</artifactId>
+			<version>2.5.4</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-hibernate3</artifactId>
+			<version>2.0.8</version>
+			<exclusions>
+				<exclusion>
+					<groupId>javax.transaction</groupId>
+					<artifactId>jta</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<dependency>
+			<groupId>com.google.guava</groupId>
+			<artifactId>guava</artifactId>
+			<version>10.0.1</version>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.2</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+</project>
diff --git a/0.8.1-rc1/cli/src/main/assembly/assembly.xml b/0.8.1-rc1/cli/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..be96b1a
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/assembly/assembly.xml
@@ -0,0 +1,36 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<assembly>
+	<id>dist</id>
+	<formats>
+		<format>tar.gz</format>
+		<format>zip</format>
+	</formats>
+	<includeBaseDirectory>true</includeBaseDirectory>
+	<baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
+	<includeSiteDirectory>false</includeSiteDirectory>
+	<dependencySets>
+		<dependencySet>
+			<outputDirectory>lib</outputDirectory>
+			<unpack>false</unpack>
+			<useProjectArtifact>true</useProjectArtifact>
+			<useTransitiveDependencies>true</useTransitiveDependencies>
+			<unpackOptions />
+		</dependencySet>
+	</dependencySets>
+</assembly>
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/CmdLineArgs.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/CmdLineArgs.java
new file mode 100644
index 0000000..999424f
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/CmdLineArgs.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findAction;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findSpecifiedHelpOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findSpecifiedPrintSupportedActionsOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findSpecifiedActionOption;
+
+//JDK imports
+import java.util.Set;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.option.ActionCmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.HelpCmdLineOption;
+import org.apache.oodt.cas.cli.option.PrintSupportedActionsCmdLineOption;
+
+/**
+ * A convenience class for {@link CmdLineUtility} for helping use already parsed
+ * Command-Line arguments.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class CmdLineArgs {
+
+   private CmdLineAction specifiedAction;
+   private Set<CmdLineAction> supportedActions;
+
+   private CmdLineOptionInstance helpOptionInst;
+   private CmdLineOptionInstance actionOptionInst;
+   private CmdLineOptionInstance psaOptionInst;
+   private Set<CmdLineOption> supportedOptions;
+   private Set<CmdLineOptionInstance> specifiedOptions;
+
+   /* package */CmdLineArgs(Set<CmdLineAction> supportedActions,
+         Set<CmdLineOption> supportedOptions,
+         Set<CmdLineOptionInstance> specifiedOptions) {
+      Validate.notNull(supportedActions);
+      Validate.notNull(supportedOptions);
+      Validate.notNull(specifiedOptions);
+
+      helpOptionInst = findSpecifiedHelpOption(specifiedOptions);
+      psaOptionInst = findSpecifiedPrintSupportedActionsOption(specifiedOptions);
+      actionOptionInst = findSpecifiedActionOption(specifiedOptions);
+
+      this.supportedOptions = supportedOptions;
+      this.specifiedOptions = specifiedOptions;
+      this.supportedActions = supportedActions;
+
+      if (actionOptionInst != null) {
+         specifiedAction = findAction(actionOptionInst, supportedActions);
+      }
+   }
+
+   /**
+    * @return The {@link CmdLineOptionInstance} which is the specified
+    *         {@link HelpCmdLineOption}, or null if it was not specified
+    */
+   public CmdLineOptionInstance getHelpOptionInst() {
+      return helpOptionInst;
+   }
+
+   /**
+    * @return The {@link CmdLineOptionInstance} which is the specified
+    *         {@link ActionCmdLineOption}, or null if it was not specified
+    */
+   public CmdLineOptionInstance getActionOptionInst() {
+      return actionOptionInst;
+   }
+
+   /**
+    * @return The {@link CmdLineOptionInstance} which is the specified
+    *         {@link PrintSupportedActionsCmdLineOption}, or null if it was not
+    *         specified
+    */
+   public CmdLineOptionInstance getPrintSupportedActionsOptionInst() {
+      return psaOptionInst;
+   }
+
+   /**
+    * @return All supported {@link CmdLineOption}s
+    */
+   public Set<CmdLineOption> getSupportedOptions() {
+      return supportedOptions;
+   }
+
+   /**
+    * @return All specified {@link CmdLineOptionInstance}s
+    */
+   public Set<CmdLineOptionInstance> getSpecifiedOptions() {
+      return specifiedOptions;
+   }
+
+   /**
+    * @return All supported {@link CmdLineAction}s
+    */
+   public Set<CmdLineAction> getSupportedActions() {
+      return supportedActions;
+   }
+
+   /**
+    * @return The {@link CmdLineAction} which was specified
+    */
+   public CmdLineAction getSpecifiedAction() {
+      return specifiedAction;
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/CmdLineUtility.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/CmdLineUtility.java
new file mode 100644
index 0000000..3ae4e9d
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/CmdLineUtility.java
@@ -0,0 +1,386 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.asAdvancedOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.determineFailedValidation;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.determineRequired;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findFirstActionOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findHelpOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findPerformAndQuitOptions;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findPrintSupportedActionsOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.handlePerformAndQuitOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.isAdvancedOption;
+
+//JDK imports
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.action.store.CmdLineActionStore;
+import org.apache.oodt.cas.cli.action.store.spring.SpringCmdLineActionStoreFactory;
+import org.apache.oodt.cas.cli.construct.CmdLineConstructor;
+import org.apache.oodt.cas.cli.construct.StdCmdLineConstructor;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.cli.exception.CmdLineActionExecutionException;
+import org.apache.oodt.cas.cli.exception.CmdLineActionStoreException;
+import org.apache.oodt.cas.cli.exception.CmdLineConstructionException;
+import org.apache.oodt.cas.cli.exception.CmdLineOptionStoreException;
+import org.apache.oodt.cas.cli.exception.CmdLineParserException;
+import org.apache.oodt.cas.cli.option.ActionCmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.HelpCmdLineOption;
+import org.apache.oodt.cas.cli.option.PrintSupportedActionsCmdLineOption;
+import org.apache.oodt.cas.cli.option.store.CmdLineOptionStore;
+import org.apache.oodt.cas.cli.option.store.spring.SpringCmdLineOptionStoreFactory;
+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator;
+import org.apache.oodt.cas.cli.parser.CmdLineParser;
+import org.apache.oodt.cas.cli.parser.StdCmdLineParser;
+import org.apache.oodt.cas.cli.presenter.CmdLinePresenter;
+import org.apache.oodt.cas.cli.presenter.StdCmdLinePresenter;
+import org.apache.oodt.cas.cli.printer.CmdLinePrinter;
+import org.apache.oodt.cas.cli.printer.StdCmdLinePrinter;
+import org.apache.oodt.cas.cli.util.CmdLineIterable;
+import org.apache.oodt.cas.cli.util.CmdLineUtils;
+import org.apache.oodt.cas.cli.util.ParsedArg;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * A highly configurable utility class which supports parsing and handling of
+ * command line arguments via its action driven design. After parsing the
+ * command line arguments it will check for required arguments not specified,
+ * validate the arguments, run the arguments handlers and then invoke the
+ * specified action. It also supports print out help messages and printing
+ * supported actions.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class CmdLineUtility {
+
+   private boolean debugMode;
+   private CmdLineParser parser;
+   private CmdLineConstructor constructor;
+   private CmdLineOptionStore optionStore;
+   private CmdLineActionStore actionStore;
+   private CmdLinePrinter printer;
+   private CmdLinePresenter presenter;
+
+   public CmdLineUtility() {
+      parser = new StdCmdLineParser();
+      constructor = new StdCmdLineConstructor();
+      optionStore = new SpringCmdLineOptionStoreFactory().createStore();
+      actionStore = new SpringCmdLineActionStoreFactory().createStore();
+      printer = new StdCmdLinePrinter();
+      presenter = new StdCmdLinePresenter();
+
+      debugMode = Boolean.getBoolean("org.apache.oodt.cas.cli.debug");
+   }
+
+   public CmdLineOptionStore getOptionStore() {
+      return optionStore;
+   }
+
+   public void setOptionStore(CmdLineOptionStore optionStore) {
+      this.optionStore = optionStore;
+   }
+
+   public CmdLineActionStore getActionStore() {
+      return actionStore;
+   }
+
+   public void setActionStore(CmdLineActionStore actionStore) {
+      this.actionStore = actionStore;
+   }
+
+   public CmdLinePrinter getPrinter() {
+      return printer;
+   }
+
+   public void setPrinter(CmdLinePrinter printer) {
+      this.printer = printer;
+   }
+
+   public CmdLinePresenter getPresenter() {
+      return presenter;
+   }
+
+   public void setPresenter(CmdLinePresenter presenter) {
+      this.presenter = presenter;
+   }
+
+   public void printOptionHelp(CmdLineArgs cmdLineArgs) {
+      presenter.presentOptionHelp(printer.printOptionsHelp(cmdLineArgs
+            .getSupportedOptions()));
+   }
+
+   public void printActionHelp(CmdLineArgs cmdLineArgs) {
+      Validate.notEmpty(cmdLineArgs.getHelpOptionInst().getValues());
+
+      presenter.presentActionHelp(printer.printActionHelp(
+            CmdLineUtils.findAction(cmdLineArgs.getHelpOptionInst().getValues()
+                  .get(0), cmdLineArgs.getSupportedActions()),
+            cmdLineArgs.getSupportedOptions()));
+   }
+
+   public void printActionsHelp(CmdLineArgs cmdLineArgs) {
+      presenter.presentActionsHelp(printer.printActionsHelp(cmdLineArgs
+            .getSupportedActions()));
+   }
+
+   public void printActionMessages(List<String> messages) {
+      presenter.presentActionMessage(printer.printActionMessages(messages));
+   }
+
+   public void printValidationErrors(List<CmdLineOptionValidator.Result> results) {
+      presenter.presentErrorMessage(printer
+            .printOptionValidationErrors(results));
+   }
+
+   public void printMissingRequiredOptionsError(
+         Set<CmdLineOption> missingOptions) {
+      presenter.presentErrorMessage(printer
+            .printRequiredOptionsMissingError(missingOptions));
+   }
+
+   public void printErrorMessage(String errorMessage) {
+      presenter.presentErrorMessage(errorMessage);
+   }
+
+   /**
+    * Parses given command line arguments, then checks for help and print
+    * supported actions options, prints them out if found, otherwise performs
+    * execution on the arguments - see execute(CmdLineArgs).
+    * 
+    * @param args
+    *           The who will be parsed and executed.
+    */
+   public void run(String[] args) {
+      try {
+         CmdLineArgs cmdLineArgs = parse(args);
+         if (cmdLineArgs.getSpecifiedOptions().isEmpty()) {
+            printOptionHelp(cmdLineArgs);
+         } else if (!handleHelp(cmdLineArgs)
+               && !handlePrintSupportedActions(cmdLineArgs)) {
+            execute(cmdLineArgs);
+         }
+      } catch (Exception e) {
+         if (debugMode) {
+            throw new RuntimeException(e);
+         }
+         printErrorMessage(e.getMessage());
+      }
+   }
+
+   /**
+    * Parses the given command line arguments and converts it to
+    * {@link CmdLineArgs}.
+    * 
+    * @param args
+    *           The command line arguments to parse.
+    * @return The parsed command line arguments in {@link CmdLineArgs} form.
+    * @throws IOException
+    *            On error parsing command line arguments.
+    * @throws CmdLineConstructionException
+    *            On error constructing command line arguments.
+    * @throws CmdLineOptionStoreException
+    */
+   public CmdLineArgs parse(String[] args) throws CmdLineParserException,
+         CmdLineActionStoreException, CmdLineConstructionException,
+         CmdLineOptionStoreException {
+      Validate.notNull(parser);
+      Validate.notNull(optionStore);
+
+      // Load supported options.
+      Set<CmdLineOption> validOptions = optionStore.loadSupportedOptions();
+      initializeHandlers(validOptions);
+
+      // Insure help options is present if required.
+      if (findHelpOption(validOptions) == null) {
+         validOptions.add(new HelpCmdLineOption());
+      }
+
+      // Insure action options are present if required.
+      if (findFirstActionOption(validOptions) == null) {
+         validOptions.add(new ActionCmdLineOption());
+      }
+
+      // Insure print supported actions option is present if required.
+      if (findPrintSupportedActionsOption(validOptions) == null) {
+         validOptions.add(new PrintSupportedActionsCmdLineOption());
+      }
+
+      // Parse command line arguments.
+      return new CmdLineArgs(actionStore.loadSupportedActions(), validOptions,
+            constructor.construct(
+                  new CmdLineIterable<ParsedArg>(parser.parse(args)),
+                  validOptions));
+   }
+
+   /**
+    * Initializes each {@link CmdLineOptionHandler} with their assigned
+    * {@link CmdLineOption}.
+    * 
+    * @param options
+    */
+   public void initializeHandlers(Set<CmdLineOption> options) {
+      for (CmdLineOption option : options) {
+         if (isAdvancedOption(option)
+               && asAdvancedOption(option).getHandler() != null) {
+            asAdvancedOption(option).getHandler().initialize(option);
+         }
+      }
+   }
+
+   /**
+    * Checks if help option was specified and if so prints out help.
+    * 
+    * @param cmdLineArgs
+    *           The {@link CmdLineArgs} which will be checked for help option
+    * @return True if help was printed, false otherwise
+    */
+   public boolean handleHelp(CmdLineArgs cmdLineArgs) {
+      if (cmdLineArgs.getHelpOptionInst() != null) {
+         if (cmdLineArgs.getHelpOptionInst().getValues().isEmpty()) {
+            printOptionHelp(cmdLineArgs);
+         } else {
+            printActionHelp(cmdLineArgs);
+         }
+         return true;
+      }
+      return false;
+   }
+
+   /**
+    * Checks if print supported actions option was specified and if so prints
+    * out supported actions.
+    * 
+    * @param cmdLineArgs
+    *           The {@link CmdLineArgs} which will be checked for print
+    *           supported action options
+    * @return True if supported actions was printed, false otherwise
+    */
+   public boolean handlePrintSupportedActions(CmdLineArgs cmdLineArgs) {
+      if (cmdLineArgs.getPrintSupportedActionsOptionInst() != null) {
+         printActionsHelp(cmdLineArgs);
+         return true;
+      }
+      return false;
+   }
+
+   /**
+    * Checks if required options are set and validation passes, then runs
+    * handlers and executes its action.
+    * 
+    * @param cmdLineArgs
+    *           The {@link CmdLineArgs} for which execution processing will be
+    *           run.
+    */
+   public void execute(CmdLineArgs cmdLineArgs)
+         throws CmdLineActionExecutionException, CmdLineActionException {
+      Set<CmdLineOptionInstance> performAndQuitOptions = findPerformAndQuitOptions(cmdLineArgs
+            .getSpecifiedOptions());
+      if (!performAndQuitOptions.isEmpty()) {
+         for (CmdLineOptionInstance option : performAndQuitOptions) {
+            handlePerformAndQuitOption(option);
+         }
+         return;
+      }
+
+      if (cmdLineArgs.getActionOptionInst() == null) {
+         throw new CmdLineActionExecutionException(
+               "Must specify an action option!");
+      }
+      Set<CmdLineOption> requiredOptionsNotSet = check(cmdLineArgs);
+      if (!requiredOptionsNotSet.isEmpty()) {
+         printMissingRequiredOptionsError(requiredOptionsNotSet);
+         return;
+      }
+
+      List<CmdLineOptionValidator.Result> failedValidationResults = determineFailedValidation(validate(cmdLineArgs));
+      if (!failedValidationResults.isEmpty()) {
+         printValidationErrors(failedValidationResults);
+         return;
+      }
+
+      handle(cmdLineArgs);
+
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      cmdLineArgs.getSpecifiedAction().execute(printer);
+      printActionMessages(printer.getPrintedMessages());
+   }
+
+   /**
+    * Checks for required options which are not set and returns the ones it
+    * finds.
+    * 
+    * @param cmdLineArgs
+    *           The {@link CmdLineArgs} which will be check for required
+    *           options.
+    * @return The required {@link CmdLineOption}s not specified.
+    */
+   public static Set<CmdLineOption> check(CmdLineArgs cmdLineArgs) {
+      Set<CmdLineOption> requiredOptions = determineRequired(
+            cmdLineArgs.getSpecifiedAction(), cmdLineArgs.getSupportedOptions());
+      HashSet<CmdLineOption> requiredOptionsNotSet = new HashSet<CmdLineOption>(
+            requiredOptions);
+      for (CmdLineOptionInstance specifiedOption : cmdLineArgs
+            .getSpecifiedOptions()) {
+         requiredOptionsNotSet.remove(specifiedOption.getOption());
+      }
+      return requiredOptionsNotSet;
+   }
+
+   /**
+    * Runs validation on {@link CmdLineArgs} and returns the validation results.
+    * 
+    * @param cmdLineArgs
+    *           The {@link CmdLineArgs} which will be validated.
+    * @return The {@link CmdLineOptionValidator.Result}s generated when running
+    *         {@link CmdLineOptionValidator}s.
+    */
+   public static List<CmdLineOptionValidator.Result> validate(
+         CmdLineArgs cmdLineArgs) {
+      Validate.notNull(cmdLineArgs);
+
+      List<CmdLineOptionValidator.Result> results = Lists.newArrayList();
+      for (CmdLineOptionInstance optionInst : cmdLineArgs.getSpecifiedOptions()) {
+         results.addAll(CmdLineUtils.validate(optionInst));
+      }
+      return results;
+   }
+
+   /**
+    * Runs the {@link CmdLineOptionHandler}s for {@link CmdLineArgs} given.
+    * 
+    * @param cmdLineArgs
+    *           The {@link CmdLineArgs} whose option handlers will be run.
+    */
+   public static void handle(CmdLineArgs cmdLineArgs) {
+      for (CmdLineOptionInstance option : cmdLineArgs.getSpecifiedOptions()) {
+         CmdLineUtils.handle(cmdLineArgs.getSpecifiedAction(), option);
+      }
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/CmdLineAction.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/CmdLineAction.java
new file mode 100644
index 0000000..186954a
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/CmdLineAction.java
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * Action which is specified and configured via {@link CmdLineOption}s and
+ * then executed.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public abstract class CmdLineAction {
+
+   private String name;
+   private String description;
+   private String detailedDescription;
+   private String examples;
+
+   public CmdLineAction() {
+   }
+
+   public CmdLineAction(String name, String description) {
+      this.name = name;
+      this.description = description;
+   }
+
+   public void setName(String name) {
+      this.name = name;
+   }
+
+   public String getName() {
+      return name;
+   }
+
+   public void setDescription(String description) {
+      this.description = description;
+   }
+
+   public String getDescription() {
+      return description;
+   }
+
+   public void setDetailedDescription(String detailedDescription) {
+      this.detailedDescription = detailedDescription;
+   }
+
+   public String getDetailedDescription() {
+      return detailedDescription;
+   }
+
+   public void setExamples(String examples) {
+      this.examples = examples;
+   }
+
+   public String getExamples() {
+      return examples;
+   }
+
+   public abstract void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException;
+
+   public static class ActionMessagePrinter {
+      private List<String> messages;
+
+      public ActionMessagePrinter() {
+         messages = Lists.newArrayList();
+      }
+
+      public void print(String message) {
+         messages.add(message);
+      }
+
+      public void println(String message) {
+         print(message);
+         println();
+      }
+
+      public void println() {
+         messages.add("\n");
+      }
+
+      public List<String> getPrintedMessages() {
+         return messages;
+      }
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/PrintMessageAction.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/PrintMessageAction.java
new file mode 100644
index 0000000..68aabeb
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/PrintMessageAction.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * A {@link CmdLineAction} which prints out a given message.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class PrintMessageAction extends CmdLineAction {
+
+   private String message;
+
+   @Override
+   public void execute(ActionMessagePrinter printer) {
+      Validate.notNull(message, "Must specify message");
+
+      printer.print(message);
+   }
+
+   @Required
+   public void setMessage(String message) {
+      this.message = message;
+   }
+
+   public String getMessage() {
+      return message;
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/CmdLineActionStore.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/CmdLineActionStore.java
new file mode 100644
index 0000000..a92b4f1
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/CmdLineActionStore.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.action.store;
+
+//JDK imports
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.exception.CmdLineActionStoreException;
+
+/**
+ * Storage for loading supported {@link CmdLineAction}s.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public interface CmdLineActionStore {
+
+   public Set<CmdLineAction> loadSupportedActions()
+         throws CmdLineActionStoreException;
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/CmdLineActionStoreFactory.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/CmdLineActionStoreFactory.java
new file mode 100644
index 0000000..2b90387
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/CmdLineActionStoreFactory.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.action.store;
+
+/**
+ * Factory for creating {@link CmdLineActionStore}s.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public interface CmdLineActionStoreFactory {
+
+   public CmdLineActionStore createStore();
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/spring/SpringCmdLineActionStore.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/spring/SpringCmdLineActionStore.java
new file mode 100644
index 0000000..2467105
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/spring/SpringCmdLineActionStore.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.action.store.spring;
+
+//JDK imports
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.action.store.CmdLineActionStore;
+import org.apache.oodt.cas.cli.exception.CmdLineActionStoreException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+/**
+ * A Spring Framework based {@link CmdLineActionStore}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class SpringCmdLineActionStore implements CmdLineActionStore {
+
+   private ApplicationContext appContext;
+
+   public SpringCmdLineActionStore(String springConfig) {
+      appContext = new FileSystemXmlApplicationContext(springConfig);
+      handleSpringSetContextInjectionType();
+      handleSettingNameForCmdLineActions();
+   }
+
+   @Override
+   public Set<CmdLineAction> loadSupportedActions()
+         throws CmdLineActionStoreException {
+      @SuppressWarnings("unchecked")
+      Map<String, CmdLineAction> actionsMap = appContext
+            .getBeansOfType(CmdLineAction.class);
+      return new HashSet<CmdLineAction>(actionsMap.values());
+   }
+
+   protected ApplicationContext getApplicationContext() {
+      return appContext;
+   }
+
+   private void handleSpringSetContextInjectionType() {
+      @SuppressWarnings("unchecked")
+      Map<String, SpringSetContextInjectionType> beans = appContext
+            .getBeansOfType(SpringSetContextInjectionType.class);
+      for (SpringSetContextInjectionType bean : beans.values()) {
+         bean.setContext(appContext);
+      }
+   }
+
+   private void handleSettingNameForCmdLineActions() {
+      @SuppressWarnings("unchecked")
+      Map<String, CmdLineAction> beans = appContext
+            .getBeansOfType(CmdLineAction.class);
+      for (Entry<String, CmdLineAction> entry : beans.entrySet()) {
+         entry.getValue().setName(entry.getKey());
+      }
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/spring/SpringCmdLineActionStoreFactory.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/spring/SpringCmdLineActionStoreFactory.java
new file mode 100644
index 0000000..90399d3
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/spring/SpringCmdLineActionStoreFactory.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.action.store.spring;
+
+//OODT imports
+import org.apache.commons.lang.Validate;
+import org.apache.oodt.cas.cli.action.store.CmdLineActionStoreFactory;
+
+/**
+ * Factory for creating {@link SpringCmdLineActionStore}s.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class SpringCmdLineActionStoreFactory implements
+      CmdLineActionStoreFactory {
+
+   private String config;
+
+   public SpringCmdLineActionStoreFactory() {
+      config = System.getProperty(
+            "org.apache.oodt.cas.cli.action.spring.config", null);
+   }
+
+   public SpringCmdLineActionStore createStore() {
+      Validate.notNull(config);
+
+      return new SpringCmdLineActionStore(config);
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/spring/SpringSetContextInjectionType.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/spring/SpringSetContextInjectionType.java
new file mode 100644
index 0000000..e251b70
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/action/store/spring/SpringSetContextInjectionType.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.action.store.spring;
+
+//Spring imports
+import org.springframework.context.ApplicationContext;
+
+/**
+ * Interface which if implemented will have the Spring Framework
+ * {@link ApplicationContext} injected via the setter method after loading from
+ * Spring XML configuration.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public interface SpringSetContextInjectionType {
+
+   public void setContext(ApplicationContext appContext);
+
+   public ApplicationContext getContext();
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/construct/CmdLineConstructor.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/construct/CmdLineConstructor.java
new file mode 100644
index 0000000..50c4612
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/construct/CmdLineConstructor.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.construct;
+
+//JDK imports
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineConstructionException;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.util.CmdLineIterable;
+import org.apache.oodt.cas.cli.util.ParsedArg;
+
+/**
+ * Responsible for constructing {@link CmdLineOptionInstance}s from parsed
+ * command line arguments.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public interface CmdLineConstructor {
+
+   public Set<CmdLineOptionInstance> construct(CmdLineIterable<ParsedArg> parsedArgs,
+         Set<CmdLineOption> validOptions) throws CmdLineConstructionException;
+
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/construct/StdCmdLineConstructor.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/construct/StdCmdLineConstructor.java
new file mode 100644
index 0000000..888db6e
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/construct/StdCmdLineConstructor.java
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.construct;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.getOptionByName;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.isHelpOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.isSubOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.sortOptionsByRequiredStatus;
+
+//JDK imports
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Stack;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineConstructionException;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.GroupCmdLineOption;
+import org.apache.oodt.cas.cli.option.GroupSubOption;
+import org.apache.oodt.cas.cli.util.CmdLineIterable;
+import org.apache.oodt.cas.cli.util.ParsedArg;
+
+//Google imports
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Standard {@link CmdLineConstructor} which support options and option
+ * groups.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class StdCmdLineConstructor implements CmdLineConstructor {
+
+   public Set<CmdLineOptionInstance> construct(CmdLineIterable<ParsedArg> parsedArgs,
+         Set<CmdLineOption> validOptions) throws CmdLineConstructionException {
+      HashSet<CmdLineOptionInstance> optionInstances = new HashSet<CmdLineOptionInstance>();
+
+      Stack<CmdLineOptionInstance> groupOptions = new Stack<CmdLineOptionInstance>();
+      for (ParsedArg arg : parsedArgs) {
+
+         if (arg.getType().equals(ParsedArg.Type.OPTION)) {
+
+            // check if option is a valid one
+            CmdLineOption option = getOptionByName(arg.getName(),
+                  validOptions);
+            if (option == null) {
+               throw new CmdLineConstructionException("Invalid option: '" + arg.getName() + "'");
+            }
+
+            // read found option
+            CmdLineOptionInstance specifiedOption = getOption(parsedArgs, option);
+
+            // Check if we are currently loading subOptions.
+            if (!groupOptions.isEmpty()) {
+
+               CmdLineOptionInstance currentGroup = groupOptions.peek();
+
+               // Check if option is NOT a subOption for current group.
+               if (!isSubOption(currentGroup.getOption(), option)) {
+
+                  // Check if current group was expecting more subOptions.
+                  Set<CmdLineOption> requiredSubOptions = verifyGroupHasRequiredSubOptions(currentGroup);
+                  if (!requiredSubOptions.isEmpty()) {
+                     throw new CmdLineConstructionException(
+                           "Missing the following required subOptions for '"
+                                 + currentGroup.getOption()
+                                 + "': "
+                                 + sortOptionsByRequiredStatus(requiredSubOptions));
+
+                  } else if (currentGroup.getSubOptions().isEmpty()) {
+                     throw new CmdLineConstructionException(
+                           "Must specify a subOption for group option '"
+                                 + currentGroup.getOption() + "'");
+
+                  } else {
+
+                     // pop group and add to list of specified options.
+                     optionInstances.add(groupOptions.pop());
+                  }
+               // It is a sub-option...
+               } else {
+
+                  // Add option to current group subOptions.
+                  currentGroup.addSubOption(specifiedOption);
+                  continue;
+
+               }
+            }
+
+            if (option instanceof GroupCmdLineOption) {
+
+               // Push group as current group.
+               groupOptions.push(specifiedOption);
+               
+               if (!parsedArgs.hasNext()) {
+                  throw new CmdLineConstructionException(
+                        "Must specify a subOption for group option '"
+                              + specifiedOption.getOption() + "'");
+               }
+            } else if (option.isSubOption()) {
+               throw new CmdLineConstructionException("Option '" + option
+                     + "' is a subOption, but was used at top level Option");
+
+            } else {
+
+               // Option good to go.
+               optionInstances.add(specifiedOption);
+            }
+         } else {
+            throw new CmdLineConstructionException("Invalid argument: '" + arg + "'");
+         }
+      }
+      while (!groupOptions.isEmpty()) {
+         CmdLineOptionInstance currentGroup = groupOptions.pop();
+         Set<CmdLineOption> requiredSubOptions = verifyGroupHasRequiredSubOptions(currentGroup);
+         if (!requiredSubOptions.isEmpty()) {
+            throw new CmdLineConstructionException(
+                  "Missing the following required subOptions for '"
+                        + currentGroup.getOption() + "': "
+                        + sortOptionsByRequiredStatus(requiredSubOptions));
+
+         } else {
+            optionInstances.add(currentGroup);
+         }
+      }
+      return optionInstances;
+   }
+
+   @VisibleForTesting
+   /* package */static CmdLineOptionInstance getOption(CmdLineIterable<ParsedArg> args,
+         CmdLineOption option) throws CmdLineConstructionException {
+      CmdLineOptionInstance specifiedOption = new CmdLineOptionInstance();
+      specifiedOption.setOption(option);
+      List<String> values = getValues(args);
+      if (isHelpOption(option)) {
+         specifiedOption.setValues(values);         
+      } else if (option.hasArgs()) {
+         if (!values.isEmpty()) {
+            specifiedOption.setValues(values);
+         } else if (!option.hasStaticArgs()) {
+            throw new CmdLineConstructionException("Option " + option + " requires args");
+         }
+      } else if (!option.hasArgs() && !values.isEmpty()) {
+         throw new CmdLineConstructionException("Option " + option + " does not support args");
+      }
+      return specifiedOption;
+   }
+
+
+   @VisibleForTesting
+   /* package */static Set<CmdLineOption> verifyGroupHasRequiredSubOptions(
+         CmdLineOptionInstance group) {
+      Validate.isTrue(group.isGroup());
+
+      Set<CmdLineOption> missingSubOptions = new HashSet<CmdLineOption>();
+      TOP: for (GroupSubOption subOption : ((GroupCmdLineOption) group.getOption())
+            .getSubOptions()) {
+         if (subOption.isRequired()) {
+            for (CmdLineOptionInstance specifiedSubOption : group
+                  .getSubOptions()) {
+               if (specifiedSubOption.getOption().equals(subOption.getOption())) {
+                  continue TOP;
+               }
+            }
+            missingSubOptions.add(subOption.getOption());
+         }
+      }
+      return missingSubOptions;
+   }
+
+   @VisibleForTesting
+   /* package */static List<String> getValues(CmdLineIterable<ParsedArg> args) {
+      List<String> values = new ArrayList<String>();
+      ParsedArg nextValue = args.incrementAndGet();
+      while (nextValue != null && nextValue.getType().equals(ParsedArg.Type.VALUE)) {
+         values.add(nextValue.getName());
+         nextValue = args.incrementAndGet();
+      }
+      args.descrementIndex();
+      return values;
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineActionException.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineActionException.java
new file mode 100644
index 0000000..76d56ec
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineActionException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.exception;
+
+/**
+ * An {@link Exception} thrown when failure to execute a {@link CmdLineAction}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class CmdLineActionException extends Exception {
+
+   private static final long serialVersionUID = 6416302963047726032L;
+
+   public CmdLineActionException(String msg) {
+      super(msg);
+   }
+
+   public CmdLineActionException(String msg, Throwable t) {
+      super(msg, t);
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineActionExecutionException.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineActionExecutionException.java
new file mode 100644
index 0000000..85709d9
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineActionExecutionException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.exception;
+
+/**
+ * An {@link Exception} thrown when failure to execute a {@link CmdLineAction}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class CmdLineActionExecutionException extends Exception {
+
+   private static final long serialVersionUID = 4784139793086538249L;
+
+   public CmdLineActionExecutionException(String msg) {
+      super(msg);
+   }
+
+   public CmdLineActionExecutionException(String msg, Throwable t) {
+      super(msg, t);
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineActionStoreException.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineActionStoreException.java
new file mode 100644
index 0000000..dbeefed
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineActionStoreException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.exception;
+
+/**
+ * An {@link Exception} thrown by {@link CmdLineActionStore}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class CmdLineActionStoreException extends Exception {
+
+   private static final long serialVersionUID = 4303378887098186113L;
+
+   public CmdLineActionStoreException(String msg) {
+      super(msg);
+   }
+
+   public CmdLineActionStoreException(String msg, Throwable t) {
+      super(msg, t);
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineConstructionException.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineConstructionException.java
new file mode 100644
index 0000000..d562120
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineConstructionException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.exception;
+
+/**
+ * {@link Exception} thrown if there is an error during command line
+ * construction.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class CmdLineConstructionException extends Exception {
+
+   private static final long serialVersionUID = 223647396006947261L;
+
+   public CmdLineConstructionException(String msg) {
+      super(msg);
+   }
+
+   public CmdLineConstructionException(String msg, Throwable t) {
+      super(msg, t);
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineOptionStoreException.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineOptionStoreException.java
new file mode 100644
index 0000000..3381cc5
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineOptionStoreException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.exception;
+
+/**
+ * An {@link Exception} thrown by {@link CmdLineOptionStore}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class CmdLineOptionStoreException extends Exception {
+
+   private static final long serialVersionUID = -5223714380324479058L;
+
+   public CmdLineOptionStoreException(String msg) {
+      super(msg);
+   }
+
+   public CmdLineOptionStoreException(String msg, Throwable t) {
+      super(msg, t);
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineParserException.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineParserException.java
new file mode 100644
index 0000000..af241a4
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineParserException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.exception;
+
+/**
+ * A {@link Exception} throw when there is an error parsing command line args.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class CmdLineParserException extends Exception {
+
+   private static final long serialVersionUID = 926637321837303042L;
+
+   public CmdLineParserException(String msg) {
+      super(msg);
+   }
+
+   public CmdLineParserException(String msg, Throwable t) {
+      super(msg, t);
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineUtilityException.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineUtilityException.java
new file mode 100644
index 0000000..f609ff4
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/CmdLineUtilityException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.exception;
+
+/**
+ * An {@link Exception} thrown by {@link CmdLineUtility}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class CmdLineUtilityException extends Exception {
+
+   private static final long serialVersionUID = 2977147381764985598L;
+
+   public CmdLineUtilityException(String msg) {
+      super(msg);
+   }
+
+   public CmdLineUtilityException(String msg, Throwable t) {
+      super(msg, t);
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/OptionHelpException.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/OptionHelpException.java
new file mode 100644
index 0000000..cbc99f1
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/exception/OptionHelpException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.exception;
+
+//JDK imports
+import java.io.IOException;
+
+/**
+ * Exception thrown to express that {@link HelpCmdLineOption} should be given
+ * to see help message.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class OptionHelpException extends IOException {
+
+   private static final long serialVersionUID = -8198106641155733222L;
+
+   public OptionHelpException() {
+      super();
+   }
+
+   public OptionHelpException(String message) {
+      super(message);
+   }
+
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/ActionCmdLineOption.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/ActionCmdLineOption.java
new file mode 100644
index 0000000..023ad78
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/ActionCmdLineOption.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option;
+
+/**
+ * {@link CmdLineOption} for specifying {@link CmdLineAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class ActionCmdLineOption extends SimpleCmdLineOption {
+
+   public ActionCmdLineOption() {
+      this("a", "action", "This is the name of the action to trigger", true);
+   }
+
+   public ActionCmdLineOption(String shortOption, String longOption,
+         String description, boolean hasArgs) {
+      super(shortOption, longOption, description, hasArgs);
+      this.setArgsDescription("action-name");
+      this.setType(String.class);
+      this.setRequired(true);
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/AdvancedCmdLineOption.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/AdvancedCmdLineOption.java
new file mode 100644
index 0000000..3f1b0d7
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/AdvancedCmdLineOption.java
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option;
+
+//JDK imports
+import java.util.ArrayList;
+import java.util.List;
+
+//OODT imports
+import org.apache.commons.lang.Validate;
+import org.apache.oodt.cas.cli.option.handler.CmdLineOptionHandler;
+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator;
+
+/**
+ * Advanced version of a {@link CmdLineOption} which supports validation and
+ * option handling.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class AdvancedCmdLineOption extends SimpleCmdLineOption implements
+      ValidatableCmdLineOption, HandleableCmdLineOption {
+
+   private CmdLineOptionHandler handler;
+   private List<CmdLineOptionValidator> validators;
+   private boolean performAndQuit;
+
+   public AdvancedCmdLineOption() {
+      super();
+      validators = new ArrayList<CmdLineOptionValidator>();
+   }
+
+   public AdvancedCmdLineOption(String shortOption, String longOption,
+         String description, boolean hasArgs) {
+      super(shortOption, longOption, description, hasArgs);
+   }
+
+   public void setHandler(CmdLineOptionHandler handler) {
+      this.handler = handler;
+   }
+
+   public CmdLineOptionHandler getHandler() {
+      return handler;
+   }
+
+   public boolean hasHandler() {
+      return handler != null;
+   }
+   
+   public List<CmdLineOptionValidator> getValidators() {
+      return this.validators;
+   }
+
+   public void addValidator(CmdLineOptionValidator validator) {
+      Validate.notNull(validator);
+
+      validators.add(validator);
+   }
+
+   public void setValidators(List<CmdLineOptionValidator> validators) {
+      Validate.notNull(validators);
+
+      this.validators = validators;
+   }
+
+   public boolean isPerformAndQuit() {
+      return performAndQuit;
+   }
+
+   public void setPerformAndQuit(boolean performAndQuit) {
+      this.performAndQuit = performAndQuit;
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/CmdLineOption.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/CmdLineOption.java
new file mode 100755
index 0000000..8b60fb9
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/CmdLineOption.java
@@ -0,0 +1,81 @@
+/*

+ * 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.

+ */

+package org.apache.oodt.cas.cli.option;

+

+//JDK imports

+import java.util.List;

+

+//OODT imports

+import org.apache.oodt.cas.cli.option.require.RequirementRule;

+

+/**

+ * Command Line option interface spec.

+ * 

+ * @author bfoster (Brian Foster)

+ */

+public interface CmdLineOption {

+

+   public void setLongOption(String longOption);

+

+   public String getLongOption();

+

+   public void setShortOption(String shortOption);

+

+   public String getShortOption();

+

+   public void setDescription(String description);

+

+   public String getDescription();

+

+   public void setType(Class<?> type);

+

+   public Class<?> getType();

+

+   public void setRepeating(boolean repeating);

+

+   public boolean isRepeating();

+

+   public void setHasArgs(boolean hasArgs);

+

+   public boolean hasArgs();

+

+   public void setArgsDescription(String argDescription);

+

+   public String getArgsDescription();

+

+   public void setStaticArgs(List<String> values);

+

+   public List<String> getStaticArgs();

+

+   public boolean hasStaticArgs();

+

+   public void setRequired(boolean required);

+

+   public boolean isRequired();

+

+   public void setRequirementRules(List<RequirementRule> requirementRules);

+

+   public List<RequirementRule> getRequirementRules();

+

+   public void setIsSubOption(boolean isSubOption);

+

+   public boolean isSubOption();

+

+   public boolean equals(Object obj);

+

+   public int hashCode();

+}

diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/CmdLineOptionInstance.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/CmdLineOptionInstance.java
new file mode 100755
index 0000000..eefd697
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/CmdLineOptionInstance.java
@@ -0,0 +1,140 @@
+/*

+ * 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.

+ */

+package org.apache.oodt.cas.cli.option;

+

+//JDK imports

+import static org.apache.oodt.cas.cli.util.CmdLineUtils.isActionOption;

+import static org.apache.oodt.cas.cli.util.CmdLineUtils.isGroupOption;

+import static org.apache.oodt.cas.cli.util.CmdLineUtils.isHelpOption;

+import static org.apache.oodt.cas.cli.util.CmdLineUtils.isPrintSupportedActionsOption;

+

+import java.util.ArrayList;

+import java.util.HashSet;

+import java.util.List;

+import java.util.Set;

+

+//Apache imports

+import org.apache.commons.lang.Validate;

+

+/**

+ * A specified {@link CmdLineOption} with its specified argument values.

+ * 

+ * @author bfoster (Brian Foster)

+ */

+public class CmdLineOptionInstance {

+

+   private CmdLineOption option;

+   private List<String> values;

+   private Set<CmdLineOptionInstance> subOptions;

+

+   public CmdLineOptionInstance() {

+      values = new ArrayList<String>();

+      subOptions = new HashSet<CmdLineOptionInstance>();

+   }

+

+   public CmdLineOptionInstance(CmdLineOption option, List<String> values) {

+      Validate.notNull(option);

+      Validate.notNull(values);

+

+      this.option = option;

+      this.values = values;

+      subOptions = new HashSet<CmdLineOptionInstance>();

+   }

+

+   public void setOption(CmdLineOption option) {

+      this.option = option;

+   }

+

+   public CmdLineOption getOption() {

+      return option;

+   }

+

+   public boolean isGroup() {

+      return isGroupOption(option);

+   }

+

+   public boolean isAction() {

+      return isActionOption(option);

+   }

+

+   public boolean isHelp() {

+      return isHelpOption(option);

+   }

+

+   public boolean isPrintSupportedActions() {

+      return isPrintSupportedActionsOption(option);

+   }

+

+   public boolean isValidatable() {

+      return option instanceof ValidatableCmdLineOption;

+   }

+

+   public boolean isHandleable() {

+      return option instanceof HandleableCmdLineOption;

+   }

+

+   public void setValues(List<String> values) {

+      Validate.notNull(values);

+

+      this.values = new ArrayList<String>(values);

+   }

+

+   public void addValue(String value) {

+      values.add(value);

+   }

+

+   public List<String> getValues() {

+      if (values.isEmpty() && option.hasStaticArgs()) {

+         return option.getStaticArgs();

+      } else {

+         return values;

+      }

+   }

+

+   public void setSubOptions(List<CmdLineOptionInstance> subOptions) {

+      Validate.isTrue(isGroup(), "Must be group option to have subOptions");

+      Validate.notNull(subOptions, "Cannot set subOptions to NULL");

+

+      this.subOptions = new HashSet<CmdLineOptionInstance>(subOptions);

+   }

+

+   public void addSubOption(CmdLineOptionInstance subOption) {

+      Validate.isTrue(isGroup(), "Must be group option to have subOptions");

+      Validate.notNull(subOption, "Cannot add NULL subOption");

+

+      this.subOptions.add(subOption);

+   }

+

+   public Set<CmdLineOptionInstance> getSubOptions() {

+      return subOptions;

+   }

+

+   public boolean equals(Object obj) {

+      if (obj instanceof CmdLineOptionInstance) {

+         CmdLineOptionInstance compareObj = (CmdLineOptionInstance) obj;

+         return compareObj.option.equals(this.option)

+               && compareObj.values.equals(this.values);

+      } else {

+         return false;

+      }

+   }

+

+   public String toString() {

+      return "[option= " + option + ",values=" + values + ",subOptions="

+            + subOptions + "]";

+   }

+}

diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/GroupCmdLineOption.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/GroupCmdLineOption.java
new file mode 100644
index 0000000..69c1e4f
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/GroupCmdLineOption.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option;
+
+//JDK imports
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * {@link CmdLineOption} which is a group option (i.e. supports sub-
+ * {@link CmdLineOption}s.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GroupCmdLineOption extends SimpleCmdLineOption {
+
+   private List<GroupSubOption> subOptions;
+   private boolean allowAnySubOption;
+
+   public GroupCmdLineOption() {
+      super();
+      this.setHasArgs(false);
+      this.setAllowAnySubOptions(false);
+      subOptions = Lists.newArrayList();
+   }
+
+   public GroupCmdLineOption(String shortOption, String longOption,
+         String description, boolean hasArgs) {
+      super(shortOption, longOption, description, hasArgs);
+   }
+
+   public void setAllowAnySubOptions(boolean allowAnySubOption) {
+      this.allowAnySubOption = allowAnySubOption;
+   }
+
+   public boolean isAllowAnySubOptions() {
+      return subOptions.isEmpty() && allowAnySubOption;
+   }
+
+   public void setSubOptions(List<GroupSubOption> subOptions) {
+      Validate.notNull(subOptions, "Cannot set subOptions to NULL");
+
+      this.subOptions = Lists.newArrayList(subOptions);
+   }
+
+   public void addSubOption(GroupSubOption subOption) {
+      Validate.notNull(subOption, "Cannot add NULL subOption");
+
+      subOptions.add(subOption);
+   }
+
+   public List<GroupSubOption> getSubOptions() {
+      return subOptions;
+   }
+
+   public boolean hasSubOptions() {
+      return subOptions != null && !subOptions.isEmpty();
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/GroupSubOption.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/GroupSubOption.java
new file mode 100644
index 0000000..1066801
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/GroupSubOption.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option;
+
+/**
+ * A Group allowable sub-{@link CmdLineOption}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class GroupSubOption {
+
+   private CmdLineOption option;
+   private boolean required;
+
+   public GroupSubOption() {
+      required = false;
+   }
+
+   public GroupSubOption(CmdLineOption option, boolean required) {
+      this.option = option;
+      this.required = required;
+   }
+
+   public void setOption(CmdLineOption option) {
+      this.option = option;
+   }
+
+   public CmdLineOption getOption() {
+      return option;
+   }
+
+   public void setRequired(boolean required) {
+      this.required = required;
+   }
+
+   public boolean isRequired() {
+      return required;
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/HandleableCmdLineOption.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/HandleableCmdLineOption.java
new file mode 100644
index 0000000..79cd149
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/HandleableCmdLineOption.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option;
+
+//OODT imports
+import org.apache.oodt.cas.cli.option.handler.CmdLineOptionHandler;
+
+/**
+ * A {@link CmdLineOption} which has a {@link CmdLineOptionHandler} should
+ * implement this interface.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public interface HandleableCmdLineOption {
+
+   public void setHandler(CmdLineOptionHandler handler);
+
+   public CmdLineOptionHandler getHandler();
+
+   public boolean hasHandler();
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/HelpCmdLineOption.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/HelpCmdLineOption.java
new file mode 100644
index 0000000..85874e0
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/HelpCmdLineOption.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option;
+
+/**
+ * The Help {@link CmdLineOption}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class HelpCmdLineOption extends SimpleCmdLineOption {
+
+   public HelpCmdLineOption() {
+      this("h", "help", "Prints help menu", false);
+   }
+
+   public HelpCmdLineOption(String shortOption, String longOption,
+         String description, boolean hasArgs) {
+      super(shortOption, longOption, description, hasArgs);
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/PrintSupportedActionsCmdLineOption.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/PrintSupportedActionsCmdLineOption.java
new file mode 100644
index 0000000..2671879
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/PrintSupportedActionsCmdLineOption.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option;
+
+/**
+ * The Print Supported Actions {@link CmdLineOption}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class PrintSupportedActionsCmdLineOption extends SimpleCmdLineOption {
+
+   public PrintSupportedActionsCmdLineOption() {
+      super("psa", "printSupportedActions", "Print Supported Actions", false);
+   }
+
+   public PrintSupportedActionsCmdLineOption(String shortOption,
+         String longOption, String description, boolean hasArgs) {
+      super(shortOption, longOption, description, hasArgs);
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/SimpleCmdLineOption.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/SimpleCmdLineOption.java
new file mode 100755
index 0000000..23bf8b0
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/SimpleCmdLineOption.java
@@ -0,0 +1,187 @@
+/*

+ * 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.

+ */

+package org.apache.oodt.cas.cli.option;

+

+//JDK imports

+import java.util.ArrayList;

+import java.util.List;

+

+//OODT imports

+import org.apache.oodt.cas.cli.option.require.RequirementRule;

+

+/**

+ * {@link CmdLineOption} which implements the basic methods for any

+ * {@link CmdLineOption}. Can be used as-is or extends to add additional option

+ * features.

+ * 

+ * @author bfoster (Brian Foster)

+ */

+public class SimpleCmdLineOption implements CmdLineOption {

+

+   private String shortOption;

+

+   private String longOption;

+

+   private String description;

+

+   private boolean repeating;

+

+   private String argsDescription;

+

+   private boolean required;

+

+   private List<RequirementRule> requirementRules;

+

+   private boolean hasArgs;

+

+   private List<String> staticArgs;

+

+   private boolean isSubOption;

+

+   private Class<?> type;

+

+   public SimpleCmdLineOption() {

+      argsDescription = "arg";

+      repeating = false;

+      required = false;

+      hasArgs = false;

+      isSubOption = false;

+      type = String.class;

+      requirementRules = new ArrayList<RequirementRule>();

+   }

+

+   public SimpleCmdLineOption(String shortOption, String longOption,

+         String description, boolean hasArgs) {

+      this();

+      this.shortOption = shortOption;

+      this.longOption = longOption;

+      this.description = description;

+      this.hasArgs = hasArgs;

+   }

+

+   public Class<?> getType() {

+      return type;

+   }

+

+   public void setType(Class<?> type) {

+      this.type = type;

+   }

+

+   public String getShortOption() {

+      return shortOption;

+   }

+

+   public void setShortOption(String shortOption) {

+      this.shortOption = shortOption;

+   }

+

+   public String getLongOption() {

+      return longOption;

+   }

+

+   public void setLongOption(String longOption) {

+      this.longOption = longOption;

+   }

+

+   public String getDescription() {

+      return description;

+   }

+

+   public void setDescription(String description) {

+      this.description = description;

+   }

+

+   public boolean isRepeating() {

+      return repeating;

+   }

+

+   public void setRepeating(boolean repeating) {

+      this.repeating = repeating;

+   }

+

+   public boolean hasArgs() {

+      return hasArgs;

+   }

+

+   public void setHasArgs(boolean hasArgs) {

+      this.hasArgs = hasArgs;

+   }

+

+   public void setArgsDescription(String argDescription) {

+      this.argsDescription = argDescription;

+   }

+

+   public String getArgsDescription() {

+      return argsDescription;

+   }

+

+   public void setStaticArgs(List<String> staticArgs) {

+      this.staticArgs = staticArgs;

+   }

+

+   public List<String> getStaticArgs() {

+      return staticArgs;

+   }

+

+   public boolean hasStaticArgs() {

+      return staticArgs != null;

+   }

+

+   public void setRequired(boolean required) {

+      this.required = required;

+   }

+

+   public boolean isRequired() {

+      return required;

+   }

+

+   public List<RequirementRule> getRequirementRules() {

+      return this.requirementRules;

+   }

+

+   public void setRequirementRules(List<RequirementRule> requirementRules) {

+      this.requirementRules = requirementRules;

+   }

+

+   public void setIsSubOption(boolean isSubOption) {

+      this.isSubOption = isSubOption;

+   }

+

+   public boolean isSubOption() {

+      return isSubOption;

+   }

+

+   @Override

+   public boolean equals(Object obj) {

+      if (obj instanceof CmdLineOption) {

+         SimpleCmdLineOption compareObj = (SimpleCmdLineOption) obj;

+         return compareObj.shortOption.equals(this.shortOption)

+               || compareObj.longOption.equals(this.longOption);

+      } else

+         return false;

+   }

+

+   @Override

+   public int hashCode() {

+      return longOption.hashCode();

+   }

+

+   public String toString() {

+      return "[longOption='" + longOption + "',shortOption='"

+            + shortOption + "',description='" + description + "']";

+   }

+}

diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/ValidatableCmdLineOption.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/ValidatableCmdLineOption.java
new file mode 100644
index 0000000..f18c537
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/ValidatableCmdLineOption.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator;
+
+/**
+ * A {@link CmdLineOption} which has {@link CmdLineOptionValidator}s should
+ * implement this interface.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public interface ValidatableCmdLineOption {
+
+   public void setValidators(List<CmdLineOptionValidator> validators);
+
+   public List<CmdLineOptionValidator> getValidators();
+
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/handler/ApplyToAction.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/handler/ApplyToAction.java
new file mode 100644
index 0000000..490e336
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/handler/ApplyToAction.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.handler;
+
+/**
+ * Mapping of {@link CmdLineAction} name to its method which should be called by
+ * {@link ApplyToActionHandler} when injecting argument value.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class ApplyToAction {
+
+   private String actionName;
+   private String methodName;
+   private String description;
+   private String argDescription;
+
+   public ApplyToAction() {
+   }
+
+   public ApplyToAction(String actionName, String methodName) {
+      this.actionName = actionName;
+      this.methodName = methodName;
+   }
+
+   public String getActionName() {
+      return actionName;
+   }
+
+   public void setActionName(String actionName) {
+      this.actionName = actionName;
+   }
+
+   public String getMethodName() {
+      return methodName;
+   }
+
+   public void setMethodName(String methodName) {
+      this.methodName = methodName;
+   }
+
+   public String getDescription() {
+      return description;
+   }
+
+   public void setDescription(String description) {
+      this.description = description;
+   }
+
+   public String getArgDescription() {
+      return argDescription;
+   }
+
+   public void setArgDescription(String argDescription) {
+      this.argDescription = argDescription;
+   }
+
+   public String toString() {
+      return actionName + " : " + methodName;
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/handler/ApplyToActionHandler.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/handler/ApplyToActionHandler.java
new file mode 100644
index 0000000..2c26b6b
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/handler/ApplyToActionHandler.java
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.handler;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.convertToType;
+
+//JDK imports
+import java.util.Arrays;
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.StringUtils;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+
+//Google imports
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+
+/**
+ * {@link CmdLineOptionHandler} which applies {@link CmdLineOption} values to
+ * given {@link CmdLineAction}.  If {@link CmdLineOption} is a repeating option
+ * then "add<long-name>" is invoked on {@link CmdLineAction}, otherwise
+ * "set<long-name" is invoked, unless the method name was supplied, then that
+ * method will be invoked.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class ApplyToActionHandler implements CmdLineOptionHandler {
+
+   private List<ApplyToAction> applyToActions;
+
+   public void setApplyToActions(List<ApplyToAction> applyToActions) {
+      this.applyToActions = applyToActions;
+   }
+
+   public List<ApplyToAction> getApplyToActions() {
+      return applyToActions;
+   }
+
+   public void initialize(CmdLineOption option) {
+      // Do nothing.
+   }
+
+   public void handleOption(CmdLineAction action,
+         CmdLineOptionInstance optionInstance) {
+      try {
+         Class<?> type = optionInstance.getOption().getType();
+         List<?> vals = (optionInstance.getValues().isEmpty()) ? convertToType(
+               Arrays.asList(new String[] { "true" }), type = Boolean.TYPE)
+               : convertToType(optionInstance.getValues(), type);
+         String methodName = getMethodName(action.getName());
+         if (methodName != null) {
+            action.getClass().getMethod(methodName, type)
+                  .invoke(action, vals.toArray(new Object[vals.size()]));
+         } else {
+            action.getClass()
+                  .getMethod(
+                        (optionInstance.getOption().isRepeating() ? "add"
+                              : "set") + StringUtils.capitalize(optionInstance
+                                    .getOption().getLongOption()), type)
+                  .invoke(action, vals.toArray(new Object[vals.size()]));
+         }
+      } catch (Exception e) {
+         throw new RuntimeException(e);
+      }
+   }
+
+   @VisibleForTesting
+   protected String getMethodName(String actionName) {
+      if (applyToActions != null) {
+         for (ApplyToAction applyToAction : applyToActions) {
+            if (applyToAction.getActionName().equals(actionName)) {
+               return applyToAction.getMethodName();
+            }
+         }
+      }
+      return null;
+   }
+
+   @VisibleForTesting
+   protected String getDescription(String actionName) {
+      if (applyToActions != null) {
+         for (ApplyToAction applyToAction : applyToActions) {
+            if (applyToAction.getActionName().equals(actionName)) {
+               return applyToAction.getDescription();
+            }
+         }
+      }
+      return null;
+   }
+
+   @VisibleForTesting
+   protected String getArgDescription(String actionName) {
+      if (applyToActions != null) {
+         for (ApplyToAction applyToAction : applyToActions) {
+            if (applyToAction.getActionName().equals(actionName)) {
+               return applyToAction.getArgDescription();
+            }
+         }
+      }
+      return null;
+   }
+
+   public String getHelp(CmdLineOption option) {
+      return "Will invoke '" + (option.isRepeating() ? "add" : "set")
+         + StringUtils.capitalize(option.getLongOption())
+         + "' on action selected, except for the following actions: "
+         + (applyToActions != null ? applyToActions : Lists.newArrayList());
+   }
+
+   public String getDescription(CmdLineAction action, CmdLineOption option) {
+      return getDescription(action.getName());
+   }
+
+   public String getArgDescription(CmdLineAction action, CmdLineOption option) {
+      return getArgDescription(action.getName());
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/handler/CmdLineOptionHandler.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/handler/CmdLineOptionHandler.java
new file mode 100755
index 0000000..98f4aca
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/handler/CmdLineOptionHandler.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.handler;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+
+/**
+ * Handles a {@link CmdLineOption}'s values in relation to given
+ * {@link CmdLineAction}s.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public interface CmdLineOptionHandler {
+
+   /**
+    * Called after handler construction to allow handler to setup
+    * state before it is required to handle the option later. This
+    * is also called when help is run so allows registration to take
+    * place if necessary for help analysis.
+    */
+   public abstract void initialize(CmdLineOption option);
+
+   public abstract void handleOption(CmdLineAction selectedAction,
+         CmdLineOptionInstance optionInstance);
+
+   /**
+    * Gets the {@link CmdLineOptionHandler}s help message when associated with
+    * given {@link CmdLineOption}.
+    * 
+    * @param option
+    *           The {@link CmdLineOption} to which this
+    *           {@link CmdLineOptionHandler} was associated with
+    * @return The help message for this {@link CmdLineOptionHandler}
+    */
+   public abstract String getHelp(CmdLineOption option);
+
+   /**
+    * If this handler causes the argument descriptor to be different for
+    * certain {@link CmdLineAction}s, then should return the arg
+    * description here.
+    */
+   public abstract String getArgDescription(CmdLineAction action,
+         CmdLineOption option);
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/handler/SetJavaPropertiesHandler.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/handler/SetJavaPropertiesHandler.java
new file mode 100644
index 0000000..58745b7
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/handler/SetJavaPropertiesHandler.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.handler;
+
+//JDK imports
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.util.OptionPropertyRegister;
+
+/**
+ * {@link CmdLineOptionHandler} which sets Java Properties equals to the
+ * values specified by the {@link CmdLineOption} this handler is attached
+ * to.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class SetJavaPropertiesHandler implements CmdLineOptionHandler {
+
+   private List<String> propertyNames;
+
+   public void initialize(CmdLineOption option) {
+      for (String property : propertyNames) {
+         OptionPropertyRegister.registerOption(property, option);
+      }
+   }
+
+   public void handleOption(CmdLineAction selectedAction,
+         CmdLineOptionInstance optionInstance) {
+      Validate.notNull(propertyNames);
+
+      for (String propertyName : propertyNames) {
+         System.setProperty(propertyName,
+               StringUtils.join(optionInstance.getValues(),
+                     optionInstance.getOption().getType().equals(List.class) ?
+                           "," :  " "));
+      }
+   }
+
+   public void setPropertyNames(List<String> propertyNames) {
+      this.propertyNames = propertyNames;
+   }
+
+   public List<String> getPropertyNames() {
+      return propertyNames;
+   }
+
+   public String getHelp(CmdLineOption option) {
+      return "Sets the following Java Properties: " + this.propertyNames;
+   }
+
+   public String getArgDescription(CmdLineAction action, CmdLineOption option) {
+      return null;
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/require/ActionDependencyRule.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/require/ActionDependencyRule.java
new file mode 100644
index 0000000..96b650a
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/require/ActionDependencyRule.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.require;
+
+//OODT imports
+import org.apache.commons.lang.Validate;
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+
+/**
+ * A {@link RequirementRule} which links the {@link CmdLineOption} to the
+ * {@link CmdLineAction} via the {@link CmdLineAction}'s name and also specifies
+ * its relationship to the {@link CmdLineAction} (i.e. Required, Optional,
+ * etc...).
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class ActionDependencyRule implements RequirementRule {
+   String actionName;
+   Relation relation;
+
+   public ActionDependencyRule() {
+   }
+
+   public ActionDependencyRule(String actionName, Relation relation) {
+      this.actionName = actionName;
+      this.relation = relation;
+   }
+
+   public String getActionName() {
+      return actionName;
+   }
+
+   public void setActionName(String actionName) {
+      this.actionName = actionName;
+   }
+
+   public Relation getRelation() {
+      return relation;
+   }
+
+   public void setRelation(Relation relation) {
+      this.relation = relation;
+   }
+
+   public Relation getRelation(CmdLineAction action) {
+      Validate.notNull(actionName);
+      Validate.notNull(relation);
+      Validate.notNull(action);
+
+      if (action.getName().equals(actionName)) {
+         return relation;
+      }
+      return Relation.NONE;
+   }
+
+   public String toString() {
+      return actionName + " : " + relation;
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/require/RequirementRule.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/require/RequirementRule.java
new file mode 100755
index 0000000..438c02b
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/require/RequirementRule.java
@@ -0,0 +1,36 @@
+/*

+ * 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.

+ */

+package org.apache.oodt.cas.cli.option.require;

+

+//OODT imports

+import org.apache.oodt.cas.cli.action.CmdLineAction;

+

+/**

+ * A {@link CmdLineOption} requirement rule which specifies if it is required,

+ * optional, or not required at all.

+ * 

+ * @author bfoster (Brian Foster)

+ */

+public interface RequirementRule {

+

+   public enum Relation {

+      REQUIRED, OPTIONAL, NONE

+   }

+

+   public Relation getRelation(CmdLineAction action);

+

+}

diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/store/CmdLineOptionStore.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/store/CmdLineOptionStore.java
new file mode 100644
index 0000000..7df83de
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/store/CmdLineOptionStore.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.store;
+
+//JDK imports
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineOptionStoreException;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+
+/**
+ * Storage for loading supported {@link CmdLineOption}s.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public interface CmdLineOptionStore {
+
+   public Set<CmdLineOption> loadSupportedOptions()
+      throws CmdLineOptionStoreException;
+
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/store/CmdLineOptionStoreFactory.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/store/CmdLineOptionStoreFactory.java
new file mode 100644
index 0000000..8dec068
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/store/CmdLineOptionStoreFactory.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.store;
+
+/**
+ * Factory for creating {@link CmdLineOptionStore}s.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public interface CmdLineOptionStoreFactory {
+
+   public CmdLineOptionStore createStore();
+
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/store/spring/SpringCmdLineOptionStore.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/store/spring/SpringCmdLineOptionStore.java
new file mode 100644
index 0000000..f0b1b15
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/store/spring/SpringCmdLineOptionStore.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.store.spring;
+
+//JDK imports
+import java.util.Map;
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineOptionStoreException;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.store.CmdLineOptionStore;
+
+//Spring imports
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+//Google imports
+import com.google.common.collect.Sets;
+
+/**
+ * Spring Framework based {@link CmdLineOptionStore}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class SpringCmdLineOptionStore implements CmdLineOptionStore {
+
+   private ApplicationContext appContext;
+
+   public SpringCmdLineOptionStore(String springConfig) {
+      appContext = new FileSystemXmlApplicationContext(springConfig);
+   }
+
+   @Override
+   public Set<CmdLineOption> loadSupportedOptions()
+         throws CmdLineOptionStoreException {
+      @SuppressWarnings("unchecked")
+      Map<String, CmdLineOption> optionsMap = appContext
+            .getBeansOfType(CmdLineOption.class);
+      Set<CmdLineOption> supportedOptions = Sets.newHashSet();
+      for (CmdLineOption option : optionsMap.values()) {
+         if (!option.isSubOption()) {
+            supportedOptions.add(option);
+         }
+      }
+      return supportedOptions;
+   }
+
+   protected ApplicationContext getApplicationContext() {
+      return appContext;
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/store/spring/SpringCmdLineOptionStoreFactory.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/store/spring/SpringCmdLineOptionStoreFactory.java
new file mode 100644
index 0000000..ae7fc60
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/store/spring/SpringCmdLineOptionStoreFactory.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.store.spring;
+
+//OODT imports
+import org.apache.commons.lang.Validate;
+import org.apache.oodt.cas.cli.option.store.CmdLineOptionStoreFactory;
+
+/**
+ * Factory for creating {@link SpringCmdLineOptionStore}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class SpringCmdLineOptionStoreFactory implements
+      CmdLineOptionStoreFactory {
+
+   private String config;
+
+   public SpringCmdLineOptionStoreFactory() {
+      config = System.getProperty(
+            "org.apache.oodt.cas.cli.option.spring.config", null);
+   }
+
+   @Override
+   public SpringCmdLineOptionStore createStore() {
+      Validate.notNull(config);
+
+      return new SpringCmdLineOptionStore(config);
+   }
+
+   public void setConfig(String config) {
+      this.config = config;
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/AllowedArgsCmdLineOptionValidator.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/AllowedArgsCmdLineOptionValidator.java
new file mode 100755
index 0000000..838cab9
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/AllowedArgsCmdLineOptionValidator.java
@@ -0,0 +1,66 @@
+/*

+ * 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.

+ */

+package org.apache.oodt.cas.cli.option.validator;

+

+//JDK imports

+import java.util.LinkedList;

+import java.util.List;

+

+//OODT imports

+import org.apache.commons.lang.Validate;

+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;

+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator.Result.Grade;

+

+/**

+ * A {@link CmdLineOptionValidator} which check args against a supplied list of

+ * valid allowed arguments.

+ * 

+ * @author bfoster (Brian Foster)

+ */

+public class AllowedArgsCmdLineOptionValidator implements

+      CmdLineOptionValidator {

+

+   private List<String> allowedArgs;

+

+   public AllowedArgsCmdLineOptionValidator() {

+      this.allowedArgs = new LinkedList<String>();

+   }

+

+   @Override

+   public Result validate(CmdLineOptionInstance optionInst) {

+      Validate.notNull(optionInst);

+

+      for (String value : optionInst.getValues()) {

+         if (!allowedArgs.contains(value)) {

+            return new Result(Grade.FAIL, "Value '" + value

+                  + "' is not allowed for option "

+                  + optionInst.getOption().getLongOption()

+                  + " - Allowed values = " + this.getAllowedArgs());

+         }

+      }

+      return new Result(Grade.PASS, "Success");

+   }

+

+   public List<String> getAllowedArgs() {

+      return allowedArgs;

+   }

+

+   public void setAllowedArgs(List<String> allowedArgs) {

+      this.allowedArgs = allowedArgs;

+   }

+

+}

diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/ArgRegExpCmdLineOptionValidator.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/ArgRegExpCmdLineOptionValidator.java
new file mode 100755
index 0000000..7cbd850
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/ArgRegExpCmdLineOptionValidator.java
@@ -0,0 +1,52 @@
+/*

+ * 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.

+ */

+package org.apache.oodt.cas.cli.option.validator;

+

+//JDK imports

+import java.util.regex.Pattern;

+

+//OODT imports

+import org.apache.commons.lang.Validate;

+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;

+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator.Result.Grade;

+

+/**

+ * Performs validation on option instances via allowed args which are regular

+ * expressions for allowed argument values.

+ * 

+ * @author bfoster (Brian Foster)

+ */

+public class ArgRegExpCmdLineOptionValidator extends

+      AllowedArgsCmdLineOptionValidator {

+

+   @Override

+   public Result validate(CmdLineOptionInstance optionInst) {

+      Validate.notNull(optionInst);

+

+      TOP: for (String value : optionInst.getValues()) {

+         for (String regex : getAllowedArgs()) {

+            if (Pattern.matches(regex, value)) {

+               continue TOP;

+            }

+         }

+         return new Result(Grade.FAIL, "Value '" + value

+               + "' is not allowed for option " + optionInst.getOption()

+               + " - Allowed values = " + getAllowedArgs());

+      }

+      return new Result(Grade.PASS, "Success");

+   }

+}

diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/ClassExistsCmdLineOptionValidator.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/ClassExistsCmdLineOptionValidator.java
new file mode 100755
index 0000000..a698e99
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/ClassExistsCmdLineOptionValidator.java
@@ -0,0 +1,47 @@
+/*

+ * 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.

+ */

+package org.apache.oodt.cas.cli.option.validator;

+

+//OODT imports

+import org.apache.commons.lang.Validate;

+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;

+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator.Result.Grade;

+

+/**

+ * Validates arguments which are checked to see if they are valid classpaths.

+ * 

+ * @author bfoster (Brian Foster)

+ */

+public class ClassExistsCmdLineOptionValidator implements

+      CmdLineOptionValidator {

+

+   @Override

+   public Result validate(CmdLineOptionInstance optionInst) {

+      Validate.notNull(optionInst);

+

+      for (String value : optionInst.getValues()) {

+         try {

+            Class.forName(value);

+         } catch (Exception e) {

+            return new Result(Grade.FAIL, "Value '" + value

+                  + "' for option " + optionInst.getOption().getLongOption()

+                  + " is not a valid class");

+         }

+      }

+      return new Result(Grade.PASS, "Success");

+   }

+}

diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/CmdLineOptionValidator.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/CmdLineOptionValidator.java
new file mode 100755
index 0000000..16ed176
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/CmdLineOptionValidator.java
@@ -0,0 +1,56 @@
+/*

+ * 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.

+ */

+package org.apache.oodt.cas.cli.option.validator;

+

+//OODT imports

+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;

+

+/**

+ * Validator for specified values of {@link CmdLineOption}s.

+ * 

+ * @author bfoster (Brian Foster)

+ */

+public interface CmdLineOptionValidator {

+

+   public class Result {

+      public enum Grade {

+         PASS, FAIL;

+      }

+

+      private String message;

+      private Grade grade;

+

+      public Result(Grade grade, String message) {

+         this.message = message;

+         this.grade = grade;

+      }

+

+      public String getMessage() {

+         return message;

+      }

+

+      public Grade getGrade() {

+         return grade;

+      }

+   }

+

+   /**

+    * Throws {@link CmdLineValidationException} if validation fails, otherwise

+    * method just returns.

+    */

+   public Result validate(CmdLineOptionInstance optionInst);

+}

diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/FileExistCmdLineOptionValidator.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/FileExistCmdLineOptionValidator.java
new file mode 100755
index 0000000..5e7d0dc
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/FileExistCmdLineOptionValidator.java
@@ -0,0 +1,48 @@
+/*

+ * 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.

+ */

+package org.apache.oodt.cas.cli.option.validator;

+

+//JDK imports

+import java.io.File;

+

+//OODT imports

+import org.apache.commons.lang.Validate;

+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;

+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator.Result.Grade;

+

+/**

+ * A {@link CmdLineOptionValidator} which checks args if they are existing

+ * files.

+ * 

+ * @author bfoster (Brian Foster)

+ */

+public class FileExistCmdLineOptionValidator implements CmdLineOptionValidator {

+

+   @Override

+   public Result validate(CmdLineOptionInstance optionInst) {

+      Validate.notNull(optionInst);

+

+      for (String value : optionInst.getValues()) {

+         if (!new File(value).exists()) {

+            return new Result(Grade.FAIL, "Value '" + value

+                  + "' for option " + optionInst.getOption().getLongOption()

+                  + " is not an existing file");

+         }

+      }

+      return new Result(Grade.PASS, "Success");

+   }

+}

diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/NoRestrictionsCmdLineOptionValidator.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/NoRestrictionsCmdLineOptionValidator.java
new file mode 100755
index 0000000..85ca2dd
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/option/validator/NoRestrictionsCmdLineOptionValidator.java
@@ -0,0 +1,34 @@
+/*

+ * 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.

+ */

+package org.apache.oodt.cas.cli.option.validator;

+

+//OODT imports

+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;

+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator.Result.Grade;

+

+/**

+ * A {@link CmdLineOptionValidator} which always returns true.

+ * 

+ * @author bfoster (Brian Foster)

+ */

+public class NoRestrictionsCmdLineOptionValidator implements

+      CmdLineOptionValidator {

+

+   public Result validate(CmdLineOptionInstance optionInst) {

+      return new Result(Grade.PASS, "Success");

+   }

+}

diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/parser/CmdLineParser.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/parser/CmdLineParser.java
new file mode 100644
index 0000000..9e65191
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/parser/CmdLineParser.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.parser;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineParserException;
+import org.apache.oodt.cas.cli.util.ParsedArg;
+
+/**
+ * Command Line parser which parse command line arguments into a {@link Set} of
+ * {@link CmdLineOptionInstance}s.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public interface CmdLineParser {
+
+   public List<ParsedArg> parse(String[] args) throws CmdLineParserException;
+
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/parser/StdCmdLineParser.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/parser/StdCmdLineParser.java
new file mode 100755
index 0000000..abb028e
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/parser/StdCmdLineParser.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.parser;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineParserException;
+import org.apache.oodt.cas.cli.util.ParsedArg;
+
+//Google imports
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+
+/**
+ * Standard Command-line parser which parser command line options of the form
+ * --longOption or -shortOption followed by 0 or more values.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class StdCmdLineParser implements CmdLineParser {
+
+   public List<ParsedArg> parse(String[] args) throws CmdLineParserException {
+      List<ParsedArg> parsedArgs = Lists.newArrayList();
+
+      for (String arg : args) {
+         if (isOption(arg)) {
+            parsedArgs.add(new ParsedArg(getOptionName(arg),
+                  ParsedArg.Type.OPTION));
+         } else {
+            parsedArgs.add(new ParsedArg(arg, ParsedArg.Type.VALUE));
+         }
+      }
+      return parsedArgs;
+   }
+
+   @VisibleForTesting
+   /* package */static boolean isOption(String arg) {
+      return (arg.startsWith("-"));
+   }
+
+   @VisibleForTesting
+   /* package */static String getOptionName(String arg) {
+      if (arg.startsWith("--")) {
+         return arg.substring(2);
+      } else if (arg.startsWith("-")) {
+         return arg.substring(1);
+      } else {
+         return null;
+      }
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/presenter/CmdLinePresenter.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/presenter/CmdLinePresenter.java
new file mode 100644
index 0000000..5cafd3a
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/presenter/CmdLinePresenter.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.presenter;
+
+/**
+ * Presenter to displaying help messages generated by help printers.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public interface CmdLinePresenter {
+
+   public void presentOptionHelp(String optionHelpMessage);
+
+   public void presentActionHelp(String actionHelpMessage);
+
+   public void presentActionsHelp(String actionsHelpMessage);
+
+   public void presentErrorMessage(String errorMessage);
+
+   public void presentActionMessage(String actionMessage);
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/presenter/StdCmdLinePresenter.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/presenter/StdCmdLinePresenter.java
new file mode 100644
index 0000000..4b8767b
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/presenter/StdCmdLinePresenter.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.presenter;
+
+//JDK imports
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+/**
+ * Standard help presenter which sends help messages to {@link System.out}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class StdCmdLinePresenter implements
+      CmdLinePresenter {
+
+   private PrintStream ps;
+
+   public StdCmdLinePresenter() {
+      this(System.out);
+   }
+
+   public StdCmdLinePresenter(OutputStream os) {
+      Validate.notNull(os);
+
+      ps = new PrintStream(os);
+   }
+
+   @Override
+   public void presentOptionHelp(String optionHelpMessage) {
+      ps.println(optionHelpMessage);
+   }
+
+   @Override
+   public void presentActionHelp(String actionHelpMessage) {
+      ps.println(actionHelpMessage);
+   }
+
+   @Override
+   public void presentActionsHelp(String actionsHelpMessage) {
+      ps.println(actionsHelpMessage);
+   }
+
+   @Override
+   public void presentErrorMessage(String errorMessage) {
+      ps.println("ERROR: " + errorMessage);
+   }
+
+   @Override
+   public void presentActionMessage(String actionMessage) {
+      ps.println(actionMessage);
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/printer/CmdLinePrinter.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/printer/CmdLinePrinter.java
new file mode 100644
index 0000000..709beef
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/printer/CmdLinePrinter.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.printer;
+
+//JDK imports
+import java.util.List;
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator.Result;
+
+/**
+ * Printer which is responsible for generating a {@link String} representation
+ * of help, validation errors, and missing required options errors.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public interface CmdLinePrinter {
+
+   /**
+    * Should generate help message for action specified by
+    * {@link #CmdLineArgs.getSpecifiedAction()}.
+    * 
+    * @param action
+    *           {@link CmdLineAction} for which help will be generate
+    * @param options
+    *           Supported {@link CmdLineOption}s
+    * @return Help message for specified action
+    */
+   public String printActionHelp(CmdLineAction action, Set<CmdLineOption> options);
+
+   /**
+    * Generates help messages given {@link CmdLineAction}s.
+    * 
+    * @param actions
+    *           {@link CmdLineAction}s to print help for
+    * @return Help message for given {@link CmdLineAction}s
+    */
+   public String printActionsHelp(Set<CmdLineAction> actions);
+
+   /**
+    * Generates help message for given {@link CmdLineOption}s.
+    * 
+    * @param options
+    *           {@link CmdLineOption}s for which help message will be generated
+    * @return Help message for given {@link CmdLineOption}s
+    */
+   public String printOptionsHelp(Set<CmdLineOption> options);
+
+   /**
+    * Generate validation error message for results of failed validations.
+    * 
+    * @param results
+    *           {@link List} of FAILed validations
+    * @return Generated validation error message
+    */
+   public String printOptionValidationErrors(List<Result> results);
+
+   /**
+    * Generates missing required options error message from given
+    * {@link CmdLineOption}s which where required and not specified.
+    * 
+    * @param missingOptions
+    *           {@link Set} of {@link CmdLineOption}s which where required and
+    *           not set.
+    * @return Generated missing required options error message.
+    */
+   public String printRequiredOptionsMissingError(
+         Set<CmdLineOption> missingOptions);
+
+   /**
+    * Generates {@link CmdLineAction} message from list of messages.
+    *
+    * @param messages The messages from a {@link CmdLineAction}
+    * @return printed message from list of messages.
+    */
+   public String printActionMessages(List<String> messages);
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/printer/StdCmdLinePrinter.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/printer/StdCmdLinePrinter.java
new file mode 100644
index 0000000..36c3fa1
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/printer/StdCmdLinePrinter.java
@@ -0,0 +1,318 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.printer;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.asGroupOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.determineOptional;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.determineRelevantSubOptions;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.determineRequired;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.determineRequiredSubOptions;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.getFormattedString;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.isGroupOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.sortActions;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.sortOptions;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.sortOptionsByRequiredStatus;
+
+//JDK imports
+import java.util.List;
+import java.util.Set;
+
+//Apache imports
+import org.apache.commons.lang.StringUtils;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.option.ActionCmdLineOption;
+import org.apache.oodt.cas.cli.option.AdvancedCmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.GroupCmdLineOption;
+import org.apache.oodt.cas.cli.option.GroupSubOption;
+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator.Result;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * Standard {@link CmdLinePrinter}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class StdCmdLinePrinter implements CmdLinePrinter {
+
+   @Override
+   public String printActionHelp(CmdLineAction action,
+         Set<CmdLineOption> options) {
+      StringBuffer sb = new StringBuffer("");
+      sb.append(getHeader(action)).append("\n");
+      sb.append(getDescription(action)).append("\n");
+      sb.append(getUsage(action, options)).append("\n");
+      sb.append(getExamples(action)).append("\n");
+      sb.append(getFooter(action)).append("\n");
+      return sb.toString();
+   }
+
+   protected String getHeader(CmdLineAction action) {
+      return "** Action Help for '" + action.getName() + "' **";
+   }
+
+   protected String getDescription(CmdLineAction action) {
+      StringBuffer sb = new StringBuffer("> DESCRIPTION:\n");
+      if (action.getDetailedDescription() != null) {
+         sb.append(" ").append(action.getDetailedDescription()
+               .replaceAll("^\\s*", "").replaceAll("\\s*$", ""));
+      } else if (action.getDescription() != null) {
+         sb.append(" ").append(
+               action.getDescription().replaceAll("^\\s*", "")
+                     .replaceAll("\\s*$", ""));
+      } else {
+         sb.append(" - N/A");
+      }
+      return sb.append("\n").toString();
+   }
+
+   protected String getUsage(CmdLineAction action, Set<CmdLineOption> options) {
+      StringBuffer sb = new StringBuffer("> USAGE:\n");
+      sb.append(getRequiredSubHeader()).append("\n");
+      Set<CmdLineOption> requiredOptions = determineRequired(action, options);
+      List<CmdLineOption> sortedRequiredOptions = sortOptions(requiredOptions);
+      for (CmdLineOption option : sortedRequiredOptions) {
+         sb.append(getRequiredOptionHelp(action, option)).append("\n");
+      }
+
+      sb.append(getOptionalSubHeader()).append("\n");
+      Set<CmdLineOption> optionalOptions = determineOptional(action, options);
+      List<CmdLineOption> sortedOptionalOptions = sortOptions(optionalOptions);
+      for (CmdLineOption option : sortedOptionalOptions) {
+         sb.append(getOptionalOptionHelp(action, option)).append("\n");
+      }
+      return sb.toString();
+   }
+
+   protected String getRequiredSubHeader() {
+      return " Required:";
+   }
+
+   protected String getRequiredOptionHelp(CmdLineAction action,
+         CmdLineOption option) {
+      if (option instanceof GroupCmdLineOption) {
+         return getGroupHelp(action, (GroupCmdLineOption) option, "   ");
+      } else {
+         return getOptionHelp(action, option, "   ");
+      }
+   }
+
+   protected String getOptionalSubHeader() {
+      return " Optional:";
+   }
+
+   protected String getOptionalOptionHelp(CmdLineAction action,
+         CmdLineOption option) {
+      if (option instanceof GroupCmdLineOption) {
+         return getGroupHelp(action, (GroupCmdLineOption) option, "   ");
+      } else {
+         return getOptionHelp(action, option, "   ");
+      }
+   }
+
+   protected String getExamples(CmdLineAction action) {
+      StringBuffer sb = new StringBuffer("> EXAMPLES:\n");
+      if (action.getExamples() != null) {
+         sb.append(" ").append(action.getExamples().replaceAll("^\\s*", "")
+               .replaceAll("\\s*$", ""));
+      } else {
+         sb.append(" - N/A");
+      }
+      return sb.toString();
+   }
+
+   protected String getFooter(CmdLineAction action) {
+      return "";
+   }
+
+   protected String getOptionHelp(CmdLineAction action, CmdLineOption option,
+         String indent) {
+      String argDescription = null;
+      if (option instanceof AdvancedCmdLineOption) {
+         argDescription = ((AdvancedCmdLineOption) option).getHandler()
+               .getArgDescription(action, option);
+      }
+
+      String argHelp = null;
+      if (option instanceof ActionCmdLineOption && option.hasArgs()) {
+         argHelp = " " + action.getName();
+      } else {
+         argHelp = (option.hasArgs() ? " <"
+               + (argDescription != null ? argDescription : option
+                     .getArgsDescription()) + ">" : "");
+      }
+      return indent + "-" + option.getShortOption() + " [--"
+            + option.getLongOption() + "]" + argHelp;
+   }
+
+   protected String getGroupHelp(CmdLineAction action,
+         GroupCmdLineOption option, String indent) {
+      String helpString = getOptionHelp(action, option, indent);
+      Set<CmdLineOption> subOptions = determineRequiredSubOptions(action,
+            (GroupCmdLineOption) option);
+      if (subOptions.isEmpty()) {
+         if (!option.getSubOptions().isEmpty()) {
+            helpString += "\n" + indent + "  One of:";
+            for (GroupSubOption subOption : option.getSubOptions()) {
+               helpString += "\n"
+                     + getOptionHelp(action, subOption.getOption(), "   "
+                           + indent);
+            }
+         }
+      } else {
+         for (CmdLineOption subOption : determineRelevantSubOptions(action,
+               option)) {
+            helpString += "\n";
+            if (subOption instanceof GroupCmdLineOption) {
+               helpString += getGroupHelp(action,
+                     (GroupCmdLineOption) subOption, "  " + indent);
+            } else {
+               helpString += getOptionHelp(action, subOption, "  " + indent);
+            }
+            helpString += " "
+                  + (subOptions.contains(subOption) ? "(required)"
+                        : "(optional)");
+         }
+      }
+      return helpString;
+   }
+
+   @Override
+   public String printActionsHelp(Set<CmdLineAction> actions) {
+      StringBuffer sb = new StringBuffer("");
+      sb.append("-----------------------------------------------------------------------------------------------------------------\n");
+      sb.append("|" + StringUtils.rightPad(" Action", 35) + "|"
+            + " Description\n");
+      sb.append("-----------------------------------------------------------------------------------------------------------------\n");
+      for (CmdLineAction action : sortActions(actions)) {
+         sb.append("  ").append(StringUtils.rightPad(action.getName(), 35));
+         sb.append(" ").append(action.getDescription()).append("\n\n");
+      }
+      sb.append("-----------------------------------------------------------------------------------------------------------------\n");
+      return sb.toString();
+   }
+
+   @Override
+   public String printOptionsHelp(Set<CmdLineOption> options) {
+      StringBuffer sb = new StringBuffer("");
+      List<CmdLineOption> sortedOptions = sortOptionsByRequiredStatus(options);
+      sb.append(getHeader()).append("\n");
+      for (CmdLineOption option : sortedOptions) {
+         sb.append(getOptionHelp(option, "")).append("\n");
+      }
+      sb.append(getFooter()).append("\n");
+      return sb.toString();
+   }
+
+   protected String getHeader() {
+      StringBuffer sb = new StringBuffer("");
+      sb.append("-----------------------------------------------------------------------------------------------------------------\n");
+      sb.append("|" + StringUtils.rightPad(" Short", 7) + "|"
+            + StringUtils.rightPad(" Long", 50) + "| Description\n");
+      sb.append("-----------------------------------------------------------------------------------------------------------------\n");
+      return sb.toString();
+   }
+
+   protected String getOptionHelp(CmdLineOption option, String indent) {
+      String argName = option.hasArgs() ? " <" + option.getArgsDescription()
+            + ">" : "";
+      String optionUsage = indent
+            + "-"
+            + StringUtils.rightPad(option.getShortOption() + ",", 7)
+            + "--"
+            + StringUtils.rightPad((option.getLongOption() + argName),
+                  49 - indent.length()) + option.getDescription();
+
+      optionUsage = " " + optionUsage;
+
+      if (!option.getRequirementRules().isEmpty()) {
+         optionUsage += "\n"
+               + getFormattedString("Requirement Rules:", 62, 113)
+               + getFormattedString(option.getRequirementRules().toString(),
+                     63, 113);
+      }
+
+      if (option instanceof AdvancedCmdLineOption) {
+         if (((AdvancedCmdLineOption) option).hasHandler()) {
+            String handlerHelp = ((AdvancedCmdLineOption) option).getHandler()
+                  .getHelp(option);
+            if (handlerHelp != null) {
+               optionUsage += "\n"
+                     + getFormattedString("Handler:", 62, 113)
+                     + getFormattedString(handlerHelp, 63, 113);
+            }
+         }
+      } else if (isGroupOption(option)) {
+         GroupCmdLineOption groupOption = asGroupOption(option);
+         optionUsage += "\n";
+         optionUsage += "   SubOptions:\n";
+         optionUsage += "   > Required:\n";
+
+         List<CmdLineOption> optionalOptions = Lists.newArrayList();
+         for (GroupSubOption subOption : groupOption.getSubOptions()) {
+            if (subOption.isRequired()) {
+               optionUsage += getOptionHelp(subOption.getOption(), "     ");
+            } else {
+               optionalOptions.add(subOption.getOption());
+            }
+         }
+         optionUsage += "   > Optional:\n";
+         for (CmdLineOption optionalOption : optionalOptions) {
+            optionUsage += getOptionHelp(optionalOption, "     ");
+         }
+      }
+
+      return optionUsage;
+   }
+
+   protected String getFooter() {
+      return "-----------------------------------------------------------------------------------------------------------------";
+   }
+
+   @Override
+   public String printOptionValidationErrors(List<Result> results) {
+      StringBuffer sb = new StringBuffer("Validation Failures:");
+      for (Result result : results) {
+         sb.append(" - ").append(result.getMessage()).append("\n");
+      }
+      return sb.toString();
+   }
+
+   @Override
+   public String printRequiredOptionsMissingError(
+         Set<CmdLineOption> missingOptions) {
+      StringBuffer sb = new StringBuffer("Missing required options:\n");
+      for (CmdLineOption option : missingOptions) {
+         sb.append(" - ").append(option.toString()).append("\n");
+      }
+      return sb.toString();
+   }
+
+   @Override
+   public String printActionMessages(List<String> messages) {
+      StringBuffer sb = new StringBuffer("");
+      for (String message : messages) {
+         sb.append(message);
+      }
+      return sb.toString();
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/util/CmdLineIterable.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/util/CmdLineIterable.java
new file mode 100644
index 0000000..f110e07
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/util/CmdLineIterable.java
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.util;
+
+//JDK imports
+import java.util.Iterator;
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+/**
+ * An {@link Iterable} which allows multiple concurrent iterators which affect
+ * each other, also allows you to increment iterators index manually. All
+ * iterators handle termination safely. However, the catch being that you can
+ * only iterate through this {@link Iterable} once, then you must create a new
+ * object of it to iterate over it again.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class CmdLineIterable<T> implements Iterable<T> {
+   private int curIndex;
+   private List<T> args;
+
+   public CmdLineIterable(List<T> args) {
+      Validate.notNull(args);
+
+      curIndex = -1;
+      this.args = args;
+   }
+
+   public List<T> getArgs() {
+      return args;
+   }
+
+   public List<T> getArgsLeft() {
+      return args.subList(curIndex, args.size());
+   }
+
+   public int getCurrentIndex() {
+      return curIndex;
+   }
+
+   public void incrementIndex() {
+      if (curIndex < args.size()) {
+         curIndex++;
+      }
+   }
+
+   public void descrementIndex() {
+      if (curIndex > 0) {
+         curIndex--;
+      }
+   }
+
+   public T incrementAndGet() {
+      incrementIndex();
+      return getCurrentArg();
+   }
+
+   public T getAndIncrement() {
+      T next = getCurrentArg();
+      incrementIndex();
+      return next;
+   }
+
+   public int numArgs() {
+      return args.size();
+   }
+
+   public T getArg(int index) {
+      return args.get(index);
+   }
+
+   public boolean hasNext() {
+      return curIndex + 1 < args.size();
+   }
+
+   public T getCurrentArg() {
+      if (curIndex == -1) {
+         return incrementAndGet();
+      } else if (curIndex > -1 && curIndex < args.size()) {
+         return args.get(curIndex);
+      } else {
+         return null;
+      }
+   }
+
+   public Iterator<T> iterator() {
+      return new Iterator<T>() {
+
+         public boolean hasNext() {
+            return CmdLineIterable.this.hasNext();
+         }
+
+         public T next() {
+            if (!hasNext()) {
+               throw new IndexOutOfBoundsException((curIndex + 1) + "");
+            }
+            return incrementAndGet();
+         }
+
+         public void remove() {
+            // do nothing
+         }
+
+      };
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/util/CmdLineUtils.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/util/CmdLineUtils.java
new file mode 100755
index 0000000..06df1d2
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/util/CmdLineUtils.java
@@ -0,0 +1,1128 @@
+/*

+ * 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.

+ */

+package org.apache.oodt.cas.cli.util;

+

+//JDK imports

+import java.io.File;

+import java.net.MalformedURLException;

+import java.net.URL;

+import java.util.Collections;

+import java.util.Comparator;

+import java.util.LinkedList;

+import java.util.List;

+import java.util.Set;

+

+//OODT imports

+import org.apache.commons.lang.StringUtils;

+import org.apache.commons.lang.Validate;

+import org.apache.oodt.cas.cli.action.CmdLineAction;

+import org.apache.oodt.cas.cli.option.ActionCmdLineOption;

+import org.apache.oodt.cas.cli.option.AdvancedCmdLineOption;

+import org.apache.oodt.cas.cli.option.CmdLineOption;

+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;

+import org.apache.oodt.cas.cli.option.GroupCmdLineOption;

+import org.apache.oodt.cas.cli.option.GroupSubOption;

+import org.apache.oodt.cas.cli.option.HandleableCmdLineOption;

+import org.apache.oodt.cas.cli.option.HelpCmdLineOption;

+import org.apache.oodt.cas.cli.option.PrintSupportedActionsCmdLineOption;

+import org.apache.oodt.cas.cli.option.SimpleCmdLineOption;

+import org.apache.oodt.cas.cli.option.ValidatableCmdLineOption;

+import org.apache.oodt.cas.cli.option.require.RequirementRule;

+import org.apache.oodt.cas.cli.option.require.RequirementRule.Relation;

+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator;

+

+//Google imports

+import com.google.common.collect.Lists;

+import com.google.common.collect.Sets;

+

+/**

+ * Collection of common helper methods.

+ * 

+ * @author bfoster (Brian Foster)

+ */

+public class CmdLineUtils {

+

+   private CmdLineUtils() {

+   }

+

+   /**

+    * Determines which of the given {@link CmdLineOption}s are either always

+    * required and are required because the given {@link CmdLineAction} was

+    * specified.

+    * 

+    * @param action

+    *           The {@link CmdLineAction} which was specified.

+    * @param options

+    *           The {@link CmdLineOption}s in question of being required or not.

+    * @return The {@link Set} of {@link CmdLineOption}s which are either always

+    *         required or are required because the given {@link CmdLineAction}

+    *         was specified.

+    */

+   public static Set<CmdLineOption> determineRequired(CmdLineAction action,

+         Set<CmdLineOption> options) {

+      return determineRequired(action, options, false);

+   }

+

+   /**

+    * Same as method above but optionally allows action options to be ignored.

+    */

+   public static Set<CmdLineOption> determineRequired(CmdLineAction action,

+         Set<CmdLineOption> options, boolean ignoreActionOption) {

+      Validate.notNull(action);

+      Validate.notNull(options);

+

+      Set<CmdLineOption> requiredOptions = Sets.newHashSet();

+      for (CmdLineOption option : options) {

+         if (!(ignoreActionOption && isActionOption(option))

+               && isRequired(action, option)) {

+            requiredOptions.add(option);

+         }

+      }

+      return requiredOptions;

+   }

+

+   /**

+    * Determines the given {@link GroupCmdLineOption}'s sub-options which

+    * affect the given {@link CmdLineAction}.

+    * 

+    * @param action

+    *           The {@link CmdLineAction} for which given

+    *           {@link GroupCmdLineOption}'s sub-options will be determined

+    *           relevant or not

+    * @param option

+    *           The {@link GroupCmdLineOption} whose sub-options are in question

+    *           of being relevant to the given {@link CmdLineAction}

+    * @return The {@link GroupCmdLineOption}'s sub-options who are relevant to

+    *         given {@link CmdLineAction}

+    */

+   public static Set<CmdLineOption> determineRelevantSubOptions(

+         CmdLineAction action, GroupCmdLineOption option) {

+      Set<CmdLineOption> relevantOptions = Sets.newHashSet();

+      for (GroupSubOption subOption : option.getSubOptions()) {

+         if (subOption.getOption().getRequirementRules().isEmpty()

+               || isRequired(action, subOption.getOption())

+               || isStrictlyOptional(action, subOption.getOption())) {

+            relevantOptions.add(subOption.getOption());

+         }

+      }

+      return relevantOptions;

+   }

+

+   /**

+    * Determines the sub-options of given {@link GroupCmdLineOption} who are

+    * always required.

+    * 

+    * @param option

+    *           The {@link GroupCmdLineOption} whose sub-options are check where

+    *           they are required

+    * @return The required sub-options of given {@link GroupCmdLineOption}

+    */

+   public static Set<CmdLineOption> determineRequiredSubOptions(

+         GroupCmdLineOption option) {

+      Validate.notNull(option);

+

+      Set<CmdLineOption> requiredOptions = Sets.newHashSet();

+      for (GroupSubOption subOption : option.getSubOptions()) {

+         if (subOption.isRequired()) {

+            requiredOptions.add(subOption.getOption());

+         }

+      }

+      return requiredOptions;

+   }

+

+   /**

+    * Determines the sub-options of given {@link GroupCmdLineOption} who are

+    * either always required for become requried when given

+    * {@link CmdLineAction} is specified.

+    * 

+    * @param action

+    *           The specified {@link CmdLineAction}

+    * @param option

+    *           The {@link GroupCmdLineOption} whose sub-options are checked if

+    *           they are required

+    * @return The given {@link GroupCmdLineOption}'s required sub-options

+    */

+   public static Set<CmdLineOption> determineRequiredSubOptions(

+         CmdLineAction action, GroupCmdLineOption option) {

+      Validate.notNull(action);

+      Validate.notNull(option);

+

+      Set<CmdLineOption> requiredOptions = Sets.newHashSet();

+      for (GroupSubOption subOption : option.getSubOptions()) {

+         if (subOption.isRequired()

+               || isRequired(action, subOption.getOption())) {

+            requiredOptions.add(subOption.getOption());

+         }

+      }

+      return requiredOptions;

+   }

+

+   /**

+    * Determines if the given {@link CmdLineOption} is required because the

+    * given {@link CmdLineAction} was specified or because it is always required.

+    * 

+    * @param action

+    *           The {@link CmdLineAction} which was specified.

+    * @param option

+    *           The {@link CmdLineOption} in question of being required or not.

+    * @return True is option is required, false otherwise.

+    */

+   public static boolean isRequired(CmdLineAction action, CmdLineOption option) {

+      Validate.notNull(option);

+      Validate.notNull(action);

+

+      for (RequirementRule requirementRule : option.getRequirementRules()) {

+         if (requirementRule.getRelation(action) == Relation.REQUIRED) {

+            return true;

+         }

+      }

+      return option.getRequirementRules().isEmpty() && option.isRequired();

+   }

+

+   /**

+    * Determines which of the given {@link CmdLineOption}s are optional because

+    * the given {@link CmdLineAction} was specified.

+    * 

+    * @param action

+    *           The {@link CmdLineAction} which was specified.

+    * @param options

+    *           The {@link CmdLineOption} in question of being optional or not.

+    * @return The {@link Set} of {@link CmdLineOption}s where are optional

+    *         because the given {@link CmdLineAction} was specified.

+    */

+   public static Set<CmdLineOption> determineOptional(CmdLineAction action,

+         Set<CmdLineOption> options) {

+      Validate.notNull(action);

+      Validate.notNull(options);

+

+      Set<CmdLineOption> optionalOptions = Sets.newHashSet();

+      for (CmdLineOption option : options) {

+         if (isOptional(action, option)) {

+            optionalOptions.add(option);

+         }

+      }

+      return optionalOptions;

+   }

+

+   /**

+    * Determines if the given {@link CmdLineOption} is optional either because

+    * it is always optional or because the given {@link CmdLineAction} was

+    * specified.

+    * 

+    * @param action

+    *           The {@link CmdLineAction} which was specified.

+    * @param option

+    *           The {@link CmdLineOption} in question of being optional or not.

+    * @return True is option is optional, false otherwise.

+    */

+   public static boolean isOptional(CmdLineAction action, CmdLineOption option) {

+      Validate.notNull(action);

+      Validate.notNull(option);

+

+      if (isPerformAndQuitOption(option)) {

+         return false;

+      }

+

+      for (RequirementRule requirementRule : option.getRequirementRules()) {

+         if (requirementRule.getRelation(action) == Relation.OPTIONAL) {

+            return true;

+         }

+      }

+      return option.getRequirementRules().isEmpty() && !option.isRequired();

+   }

+

+   /**

+    * Determines if the given {@link CmdLineOption} is optional ONLY because the

+    * given {@link CmdLineAction} was specified.

+    * 

+    * @param action

+    *           The {@link CmdLineAction} which was specified.

+    * @param option

+    *           The {@link CmdLineOption} in question of being optional or not.

+    * @return True is option is optional, false otherwise.

+    */   

+   public static boolean isStrictlyOptional(CmdLineAction action, CmdLineOption option) {

+      Validate.notNull(action);

+      Validate.notNull(option);

+

+      if (isPerformAndQuitOption(option)) {

+         return false;

+      }

+

+      for (RequirementRule requirementRule : option.getRequirementRules()) {

+         if (requirementRule.getRelation(action) == Relation.OPTIONAL) {

+            return true;

+         }

+      }

+      return false;

+   }

+

+   /**

+    * Get {@link CmdLineOption}s which are always required regardless of

+    * {@link CmdLineAction} specified. NOTE: Ignores {@link CmdLineOption}s of

+    * type {@link ActionCmdLineOption}.

+    * 

+    * @param options

+    *           The {@link CmdLineOption}S to check for required

+    *           {@link CmdLineOption}s

+    * @return The {@link CmdLineOption}s which will be check for always required

+    *         {@link CmdLineOption}s

+    */

+   public static Set<CmdLineOption> getRequiredOptions(

+         Set<CmdLineOption> options) {

+      Validate.notNull(options);

+

+      return getRequiredOptions(options, true);

+   }

+

+   /**

+    * Get {@link CmdLineOption}s which are always required regardless of

+    * {@link CmdLineAction} specified.

+    * 

+    * @param options

+    *           The {@link CmdLineOption}S to check for required

+    *           {@link CmdLineOption}s

+    * @param ignoreActionOption

+    *           Where or not to ignore {@link CmdLineOption}s of type

+    *           {@link ActionCmdLineOption}

+    * @return The {@link CmdLineOption}s which will be check for always required

+    *         {@link CmdLineOption}s

+    */

+   public static Set<CmdLineOption> getRequiredOptions(

+         Set<CmdLineOption> options, boolean ignoreActionOption) {

+      Validate.notNull(options);

+

+      Set<CmdLineOption> requiredOptions = Sets.newHashSet();

+      for (CmdLineOption option : options) {

+         if (option.isRequired()

+               && !(isActionOption(option) && ignoreActionOption)) {

+            requiredOptions.add(option);

+         }

+      }

+      return requiredOptions;

+   }

+

+   /**

+    * Sorts {@link CmdLineOption}s by requirement levels. {@link CmdLineOption}s

+    * which are always required have highest sort score, followed by

+    * {@link CmdLineOption}s which have {@link RequirementRule}s, followed by

+    * all others.

+    * 

+    * @param options

+    *           The {@link Set} of {@link CmdLineOption}s to sort.

+    * @return The {@link CmdLineOption}s sorted by requirement.

+    */

+   public static List<CmdLineOption> sortOptionsByRequiredStatus(

+         Set<CmdLineOption> options) {

+      Validate.notNull(options);

+

+      List<CmdLineOption> optionsList = Lists.newArrayList(options);

+      Collections.sort(optionsList, new Comparator<CmdLineOption>() {

+         public int compare(CmdLineOption option1, CmdLineOption option2) {

+            int thisScore = (option1.isRequired() ? 2 : 0)

+                  + (!option1.getRequirementRules().isEmpty() ? 1 : 0);

+            int compareScore = (option2.isRequired() ? 2 : 0)

+                  + (!option2.getRequirementRules().isEmpty() ? 1 : 0);

+            if (thisScore == compareScore) {

+               return option2.getLongOption()

+                     .compareTo(option1.getLongOption());

+            } else {

+               return new Integer(thisScore).compareTo(compareScore);

+            }

+         }

+      });

+      Collections.reverse(optionsList);

+      return optionsList;

+   }

+

+   /**

+    * Sorts {@link CmdLineOption}s by there long name.

+    *

+    * @param options The {@link CmdLineOption}s to be sorted

+    * @return Sorted {@link List} of {@link CmdLineOption}s

+    */

+   public static List<CmdLineOption> sortOptions(Set<CmdLineOption> options) {

+      List<CmdLineOption> optionList = Lists.newArrayList(options);

+      Collections.sort(optionList, new Comparator<CmdLineOption>() {

+         @Override

+         public int compare(CmdLineOption o1, CmdLineOption o2) {

+            return o1.getLongOption().compareTo(o2.getLongOption());

+         }

+      });

+      return optionList;

+   }

+   

+   /**

+    * Sorts {@link CmdLineAction}s by there name.

+    *

+    * @param actions The {@link CmdLineAction}s to be sorted

+    * @return Sorted {@link List} of {@link CmdLineAction}s

+    */

+   public static List<CmdLineAction> sortActions(Set<CmdLineAction> actions) {

+      List<CmdLineAction> actionsList = Lists.newArrayList(actions);

+      Collections.sort(actionsList, new Comparator<CmdLineAction>() {

+         @Override

+         public int compare(CmdLineAction a1, CmdLineAction a2) {

+            return a1.getName().compareTo(a2.getName());

+         }

+      });

+      return actionsList;

+   }

+

+   /**

+    * Finds {@link CmdLineOption} whose short name or long name equals given

+    * option name.

+    * 

+    * @param optionName

+    *           The short or long name of the {@link CmdLineOption} to find

+    * @param options

+    *           The {@link CmdLineOption}s to search in

+    * @return The {@link CmdLineOption} found or null if not found.

+    */

+   public static CmdLineOption getOptionByName(String optionName,

+         Set<CmdLineOption> options) {

+      Validate.notNull(optionName);

+      Validate.notNull(options);

+

+      for (CmdLineOption option : options) {

+         if (option.getLongOption().equals(optionName)

+               || option.getShortOption().equals(optionName)) {

+            return option;

+         } else if (isGroupOption(option)) {

+            Set<CmdLineOption> subOptions = Sets.newHashSet(); 

+            for (GroupSubOption subOption : asGroupOption(option).getSubOptions()) {

+               subOptions.add(subOption.getOption());

+            }

+            CmdLineOption foundOption = getOptionByName(optionName, subOptions);

+            if (foundOption != null) {

+               return foundOption;

+            }

+         }

+      }

+      return null;

+   }

+

+   /**

+    * Finds {@link CmdLineOptionInstance} whose {@link CmdLineOption}'s short

+    * name or long name equals given option name.

+    * 

+    * @param optionName

+    *           The short or long name of the {@link CmdLineOptionInstance}'s

+    *           {@link CmdLineOption} to find

+    * @param optionInsts

+    *           The {@link CmdLineOptionIntance}s to search in

+    * @return The {@link CmdLineOptionInstance} found or null if not found.

+    */

+   public static CmdLineOptionInstance getOptionInstanceByName(

+         String optionName, Set<CmdLineOptionInstance> optionInsts) {

+      Validate.notNull(optionName);

+      Validate.notNull(optionInsts);

+

+      for (CmdLineOptionInstance optionInst : optionInsts)

+         if (optionInst.getOption().getLongOption().equals(optionName)

+               || optionInst.getOption().getShortOption().equals(optionName))

+            return optionInst;

+      return null;

+   }

+

+   /**

+    * Checks if given {@link CmdLineOption} is a sub-option of other given

+    * {@link CmdLineOption}.

+    * 

+    * @param option

+    *           {@link CmdLineOption} which is being checked if the other given

+    *           {@link CmdLineOption} is one of its sub-options

+    * @param subOption

+    *           The {@link CmdLineOption} which is being check if it is a

+    *           sub-option of the other given {@link CmdLineOption}

+    * @return True if subOption is a sub-option of option

+    */

+   public static boolean isSubOption(CmdLineOption option,

+         CmdLineOption subOption) {

+      Validate.notNull(option);

+      Validate.notNull(subOption);

+

+      if (isGroupOption(option)) {

+         for (GroupSubOption curSubOption : asGroupOption(option)

+               .getSubOptions()) {

+            if (curSubOption.getOption().equals(subOption)) {

+               return true;

+            }

+         }

+      }

+      return false;

+   }

+

+   /**

+    * Finds all the perform-and-quit type {@link CmdLineOptionInstance}s from

+    * the given {@link Set} of {@link CmdLineOptionInstance}s.

+    * 

+    * @param options

+    *           The {@link Set} of {@link CmdLineOptionInstance} who will be

+    *           check for perform-and-quit {@link CmdLineOptionInstance}s

+    * @return The perform-and-quit {@link CmdLineOptionInstance}s found

+    */

+   public static Set<CmdLineOptionInstance> findPerformAndQuitOptions(

+         Set<CmdLineOptionInstance> options) {

+      Validate.notNull(options);

+

+      Set<CmdLineOptionInstance> performAndQuitOptions = Sets.newHashSet();

+      for (CmdLineOptionInstance option : options) {

+         if (isPerformAndQuitOption(option.getOption())) {

+            performAndQuitOptions.add(option);

+         }

+      }

+      return performAndQuitOptions;

+   }

+

+   /**

+    * Checks if the given {@link CmdLineOption} is a perform-and-quit type

+    * {@link CmdLineOption}.

+    * 

+    * @param option

+    *           The {@link CmdLineOption} being checked if it is

+    *           perform-and-quit type.

+    * @return True if {@link CmdLineOption} is a perform-and-quit type, false

+    *         otherwise.

+    */

+   public static boolean isPerformAndQuitOption(CmdLineOption option) {

+      Validate.notNull(option);

+

+      if (isHelpOption(option) || isPrintSupportedActionsOption(option)) {

+         return true;

+      } else if (isAdvancedOption(option)) {

+         return asAdvancedOption(option).isPerformAndQuit();

+      } else {

+         return false;

+      }

+   }

+

+   /**

+    * Finds the first {@link CmdLineOptionInstance} whose {@link CmdLineOption}

+    * is the given {@link CmdLineOption}.

+    * 

+    * @param option

+    *           The {@link CmdLineOption} to find.

+    * @param specifiedOptions

+    *           The {@link CmdLineOptionInstance} whose {@link CmdLineOption} is

+    *           the given {@link CmdLineOption}

+    * @return The first {@link CmdLineOptionInstance} whose

+    *         {@link CmdLineOption} is the given {@link CmdLineOption}, or null

+    *         if not found

+    */

+   public static CmdLineOptionInstance findSpecifiedOption(

+         CmdLineOption option, Set<CmdLineOptionInstance> specifiedOptions) {

+      Validate.notNull(option);

+      Validate.notNull(specifiedOptions);

+

+      for (CmdLineOptionInstance specifiedOption : specifiedOptions) {

+         if (specifiedOption.getOption().equals(option)) {

+            return specifiedOption;

+         }

+      }

+      return null;

+   }

+

+   /**

+    * Finds the {@link CmdLineOptionInstance}s whose {@link CmdLineOption} is

+    * the given {@link CmdLineOption}.

+    * 

+    * @param option

+    *           The {@link CmdLineOption} to find.

+    * @param specifiedOptions

+    *           The {@link CmdLineOptionInstance} whose {@link CmdLineOption} is

+    *           the given {@link CmdLineOption}

+    * @return The {@link CmdLineOptionInstance}s whose {@link CmdLineOption} is

+    *         the given {@link CmdLineOption}

+    */

+   public static Set<CmdLineOptionInstance> findAllOfSpecifiedOption(

+         CmdLineOption option, Set<CmdLineOptionInstance> specifiedOptions) {

+      Validate.notNull(option);

+      Validate.notNull(specifiedOptions);

+

+      Set<CmdLineOptionInstance> options = Sets.newHashSet();

+      for (CmdLineOptionInstance specifiedOption : specifiedOptions) {

+         if (specifiedOption.getOption().equals(option)) {

+            options.add(specifiedOption);

+         }

+      }

+      return options;

+   }

+

+   /**

+    * Checks if {@link CmdLineOption} is a {@link PrintSupportedActionsOption}.

+    * 

+    * @param option

+    *           The {@link CmdLineOption} in question

+    * @return True is {@link CmdLineOption} is a

+    *         {@link PrintSupportedActionsOption}, false otherwise

+    */

+   public static boolean isPrintSupportedActionsOption(CmdLineOption option) {

+      Validate.notNull(option);

+

+      return option instanceof PrintSupportedActionsCmdLineOption;

+   }

+

+   /**

+    * Finds {@link CmdLineOption} of type

+    * {@link PrintSupportedActionsCmdLineOption}.

+    * 

+    * @param options

+    *           The {@link Set} of {@link CmdLineOption} to find a

+    *           {@link PrintSupportedActionsCmdLineOption} in

+    * @return The found {@link PrintSupportedActionsCmdLineOption}, or null if

+    *         not found.

+    */

+   public static PrintSupportedActionsCmdLineOption findPrintSupportedActionsOption(

+         Set<CmdLineOption> options) {

+      Validate.notNull(options);

+

+      for (CmdLineOption option : options) {

+         if (isPrintSupportedActionsOption(option)) {

+            return (PrintSupportedActionsCmdLineOption) option;

+         }

+      }

+      return null;

+   }

+

+   /**

+    * Finds {@link CmdLineOptionInstance} whose {@link CmdLineOption} of type

+    * {@link PrintSupportedActionsCmdLineOption}.

+    * 

+    * @param options

+    *           The {@link Set} of {@link CmdLineOptionInstance} to find the

+    *           {@link CmdLineOptionInstance} whose {@link CmdLineOption} is of

+    *           type {@link PrintSupportedActionsCmdLineOption} in

+    * @throws IllegalArgumentException

+    *            If more than one print supported actions option is specified

+    * @return The found {@link CmdLineOptionInstance} whose

+    *         {@link CmdLineOption} is of type

+    *         {@link PrintSupportedActionsCmdLineOption}, or null if not found.

+    */

+   public static CmdLineOptionInstance findSpecifiedPrintSupportedActionsOption(

+         Set<CmdLineOptionInstance> options) {

+      Validate.notNull(options);

+

+      CmdLineOptionInstance specifiedPsa = null;

+      for (CmdLineOptionInstance option : options) {

+         if (isPrintSupportedActionsOption(option.getOption())) {

+            if (specifiedPsa != null) {

+               throw new IllegalArgumentException(

+                     "Only on print supported actions option can be specified!");

+            }

+            specifiedPsa = option;

+         }

+      }

+      return specifiedPsa;

+   }

+

+   /**

+    * Checks if {@link CmdLineOption} is a {@link AdvancedCmdLineOption}.

+    * 

+    * @param option

+    *           The {@link CmdLineOption} checked if it is a

+    *           {@link AdvancedCmdLineOption}

+    * @return True if {@link CmdLineOption} is a {@link AdvancedCmdLineOption},

+    *         false otherwise

+    */

+   public static boolean isAdvancedOption(CmdLineOption option) {

+      Validate.notNull(option);

+

+      return option instanceof AdvancedCmdLineOption;

+   }

+

+   /**

+    * Casts the {@link CmdLineOption} to a {@link AdvancedCmdLineOption}.

+    * 

+    * @param option

+    *           The {@link CmdLineOption} to cast as a

+    *           {@link AdvancedCmdLineOption}

+    * @return The casted {@link CmdLineOption}

+    */

+   public static AdvancedCmdLineOption asAdvancedOption(CmdLineOption option) {

+      Validate.isTrue(isAdvancedOption(option));

+

+      return (AdvancedCmdLineOption) option;

+   }

+

+   /**

+    * Checks if {@link CmdLineOption} is a {@link SimpleCmdLineOption}.

+    * 

+    * @param option

+    *           The {@link CmdLineOption} checked if it is a

+    *           {@link SimpleCmdLineOption}

+    * @return True if {@link CmdLineOption} is a {@link SimpleCmdLineOption},

+    *         false otherwise

+    */

+   public static boolean isSimpleOption(CmdLineOption option) {

+      Validate.notNull(option);

+

+      return option instanceof SimpleCmdLineOption;

+   }

+

+   /**

+    * Casts the {@link CmdLineOption} to a {@link SimpleCmdLineOption}.

+    * 

+    * @param option

+    *           The {@link CmdLineOption} to cast as a

+    *           {@link SimpleCmdLineOption}

+    * @return The casted {@link CmdLineOption}

+    */

+   public static SimpleCmdLineOption asSimpleOption(CmdLineOption option) {

+      Validate.isTrue(isSimpleOption(option));

+

+      return (SimpleCmdLineOption) option;

+   }

+

+   /**

+    * Checks if {@link CmdLineOption} is a {@link ActionCmdLineOption}.

+    * 

+    * @param option

+    *           {@link CmdLineOption} check if a {@link ActionCmdLineOption}

+    * @return True if {@link CmdLineOption} is a {@link ActionCmdLineOption},

+    *         false otherwise

+    */

+   public static boolean isActionOption(CmdLineOption option) {

+      Validate.notNull(option);

+

+      return option instanceof ActionCmdLineOption;

+   }

+

+   /**

+    * Find {@link ActionCmdLineOption} in {@link Set} of {@link CmdLineOption}s.

+    * 

+    * @param options

+    *           The {@link Set} of {@link CmdLineOption} to search through for a

+    *           {@link ActionCmdLineOption}

+    * @return The found {@link ActionCmdLineOption}, or null if not found

+    */

+   public static ActionCmdLineOption findFirstActionOption(

+         Set<CmdLineOption> options) {

+      Validate.notNull(options);

+

+      for (CmdLineOption option : options) {

+         if (isActionOption(option)) {

+            return (ActionCmdLineOption) option;

+         } else if (isGroupOption(option)) {

+            GroupCmdLineOption groupOption = (GroupCmdLineOption) option;

+            Set<CmdLineOption> subOptions = Sets.newHashSet();

+            for (GroupSubOption subOption : groupOption.getSubOptions()) {

+               subOptions.add(subOption.getOption());

+            }

+            ActionCmdLineOption foundOption = findFirstActionOption(subOptions);

+            if (foundOption != null) {

+               return foundOption;

+            }

+         }

+      }

+      return null;

+   }

+

+   /**

+    * Finds all {@link CmdLineOption}s that are {@link ActionCmdLineOption}s.

+    * 

+    * @param options

+    *           The {@link CmdLineOption}s to look through for

+    *           {@link ActionCmdLineOption}s

+    * @return All {@link ActionCmdLineOption}s found

+    */

+   public static List<ActionCmdLineOption> findActionOptions(

+         Set<CmdLineOption> options) {

+      Validate.notNull(options);

+

+      List<ActionCmdLineOption> actionOptions = Lists.newArrayList();

+      for (CmdLineOption option : options) {

+         if (isActionOption(option)) {

+            actionOptions.add((ActionCmdLineOption) option);

+         } else if (isGroupOption(option)) {

+            GroupCmdLineOption groupOption = (GroupCmdLineOption) option;

+            Set<CmdLineOption> subOptions = Sets.newHashSet();

+            for (GroupSubOption subOption : groupOption.getSubOptions()) {

+               subOptions.add(subOption.getOption());

+            }

+            actionOptions.addAll(findActionOptions(subOptions));

+         }

+      }

+      return actionOptions;

+   }

+

+   /**

+    * Find {@link ActionCmdLineOption} in {@link Set} of {@link CmdLineOption}s.

+    * 

+    * @param options

+    *           The {@link Set} of {@link CmdLineOption} to search through for a

+    *           {@link ActionCmdLineOption}

+    * @throws IllegalArgumentException

+    *            If more than one action option has be specified

+    * @return The found {@link ActionCmdLineOption}, or null if not found

+    */

+   public static CmdLineOptionInstance findSpecifiedActionOption(

+         Set<CmdLineOptionInstance> options) {

+      Validate.notNull(options);

+

+      CmdLineOptionInstance specifiedAction = null;

+      for (CmdLineOptionInstance option : options) {

+         if (option.isAction()) {

+            if (specifiedAction != null) {

+               throw new IllegalArgumentException(

+                     "Only one action may be specified!");

+            }

+            specifiedAction = option;

+         } else if (option.isGroup()) {

+            CmdLineOptionInstance foundAction = findSpecifiedActionOption(option

+                  .getSubOptions());

+            if (specifiedAction != null && foundAction != null) {

+               throw new IllegalArgumentException(

+                  "Only one action may be specified!");

+            } else if (foundAction != null) {

+               specifiedAction = foundAction;

+            }

+         }

+      }

+      return specifiedAction;

+   }

+

+   /**

+    * Checks if {@link CmdLineOption} is a {@link GroupCmdLineOption}.

+    * 

+    * @param option

+    *           {@link CmdLineOption} in question

+    * @return True if {@link CmdLineOption} is a {@link GroupCmdLineOption},

+    *         false otherwise

+    */

+   public static boolean isGroupOption(CmdLineOption option) {

+      Validate.notNull(option);

+

+      return option instanceof GroupCmdLineOption;

+   }

+

+   /**

+    * Cast {@link CmdLineOption} to a {@link GroupCmdLineOption}.

+    * 

+    * @param option

+    *           The {@link CmdLineOption} to be cast as a

+    *           {@link GroupCmdLineOption}

+    * @return A {@link GroupCmdLineOption}

+    */

+   public static GroupCmdLineOption asGroupOption(CmdLineOption option) {

+      Validate.isTrue(isGroupOption(option));

+

+      return (GroupCmdLineOption) option;

+   }

+

+   /**

+    * Checks if {@link CmdLineOption} is a {@link HelpCmdLineOption}.

+    * 

+    * @param option

+    *           The {@link CmdLineOption} that is checked if it is a

+    *           {@link HelpCmdLineOption}

+    * @return True if {@link CmdLineOption} is a {@link HelpCmdLineOption},

+    *         otherwise false

+    */

+   public static boolean isHelpOption(CmdLineOption option) {

+      Validate.notNull(option);

+

+      return option instanceof HelpCmdLineOption;

+   }

+

+   /**

+    * Casts {@link CmdLineOption} to a {@link HelpCmdLineOption}.

+    * 

+    * @param option

+    *           The {@link CmdLineOption} to be cast as a

+    *           {@link HelpCmdLineOption}

+    * @return A {@link HelpCmdLineOption}

+    */

+   public static HelpCmdLineOption asHelpOption(CmdLineOption option) {

+      Validate.isTrue(isHelpOption(option));

+

+      return (HelpCmdLineOption) option;

+   }

+

+   /**

+    * Finds the {@link HelpCmdLineOption} in the {@link Set} of

+    * {@link CmdLineOption}s.

+    * 

+    * @param options

+    *           The {@link Set} of {@link CmdLineOption}s to search through for

+    *           {@link HelpCmdLineOption}

+    * @return The found {@link HelpCmdLineOption}, null if not found

+    */

+   public static HelpCmdLineOption findHelpOption(Set<CmdLineOption> options) {

+      Validate.notNull(options);

+

+      for (CmdLineOption option : options) {

+         if (isHelpOption(option)) {

+            return (HelpCmdLineOption) option;

+         }

+      }

+      return null;

+   }

+

+   /**

+    * Finds the {@link CmdLineOptionInstance} whose {@link CmdLineOption} is of

+    * type {@link HelpCmdLineOption}

+    * 

+    * @param options

+    *           The {@link Set} of {@link CmdLineOptionInstance}s to search

+    *           through for the {@link CmdLineOptionInstance} whose

+    *           {@link CmdLineOption} is of type {@link HelpCmdLineOption}

+    * @throws IllegalArgumentException

+    *            If more than one help option is specified

+    * @return The found {@link CmdLineOptionInstance}, null if not found

+    */

+   public static CmdLineOptionInstance findSpecifiedHelpOption(

+         Set<CmdLineOptionInstance> options) {

+      Validate.notNull(options);

+

+      CmdLineOptionInstance specifiedHelp = null;

+      for (CmdLineOptionInstance option : options) {

+         if (isHelpOption(option.getOption())) {

+            if (specifiedHelp != null) {

+               throw new IllegalArgumentException(

+                     "Help can only be specified once!");

+            }

+            specifiedHelp = option;

+         }

+      }

+      return specifiedHelp;

+   }

+

+   /**

+    * Finds the {@link CmdLineAction} specified by the given

+    * {@link CmdLineOptionInstance}.

+    * 

+    * @param actionOption

+    *           The {@link CmdLineOptionInstance} which specifies an

+    *           {@link ActionCmdLineOption}

+    * @param supportedActions

+    *           {@link Set} of supported {@link CmdLineAction}s

+    * @return The found {@link CmdLineAction}, null if not found

+    */

+   public static CmdLineAction findAction(CmdLineOptionInstance actionOption,

+         Set<CmdLineAction> supportedActions) {

+      Validate.isTrue(actionOption.isAction());

+      Validate.notEmpty(actionOption.getValues());

+      Validate.notNull(supportedActions);

+

+      return findAction(actionOption.getValues().get(0), supportedActions);

+   }

+

+   /**

+    * Finds a {@link CmdLineAction} by its name.

+    * 

+    * @param actionName

+    *           Name of {@link CmdLineAction} to find

+    * @param supportedActions

+    *           {@link Set} of supported {@link CmdLineAction}s

+    * @return Found {@link CmdLineAction} or null if not found

+    */

+   public static CmdLineAction findAction(String actionName,

+         Set<CmdLineAction> supportedActions) {

+      Validate.notNull(actionName);

+      Validate.notNull(supportedActions);

+

+      for (CmdLineAction action : supportedActions) {

+         if (action.getName().equals(actionName)) {

+            return action;

+         }

+      }

+      return null;

+   }

+

+   /**

+    * Validates the given {@link CmdLineOptionInstance}.

+    * 

+    * @param option

+    *           The {@link CmdLineOptionInstance} to be validated

+    * @return {@link CmdLineOptionValidator.Result}s from running

+    *         {@link CmdLineOptionValidator}s.

+    */

+   public static List<CmdLineOptionValidator.Result> validate(

+         CmdLineOptionInstance option) {

+      Validate.notNull(option);

+

+      List<CmdLineOptionValidator.Result> results = Lists.newArrayList();

+      if (option.isValidatable()) {

+         for (CmdLineOptionValidator validator : ((ValidatableCmdLineOption) option

+               .getOption()).getValidators()) {

+            results.add(validator.validate(option));

+         }

+      }

+

+      if (option.isGroup()) {

+         for (CmdLineOptionInstance subOption : option.getSubOptions()) {

+            results.addAll(validate(subOption));

+         }

+      }

+      return results;

+   }

+

+   /**

+    * Finds the {@link CmdLineOptionValidator.Result}s with grade of FAIL.

+    * 

+    * @param results

+    *           The {@link CmdLineOptionValidator.Result}s which are checked if

+    *           they have a failing grade.

+    * @return {@link CmdLineOptionValidator.Result}s with grade of FAIL.

+    */

+   public static List<CmdLineOptionValidator.Result> determineFailedValidation(

+         List<CmdLineOptionValidator.Result> results) {

+      List<CmdLineOptionValidator.Result> failedResults = Lists.newArrayList();

+      for (CmdLineOptionValidator.Result result : results) {

+         if (result.getGrade().equals(CmdLineOptionValidator.Result.Grade.FAIL)) {

+            failedResults.add(result);

+         }

+      }

+      return failedResults;

+   }

+

+   /**

+    * Runs the {@link CmdLineOptionInstance}'s handler if it a perform and

+    * quit option.

+    * 

+    * @param option

+    *           The {@link CmdLineOptionInstance} whose handler will be run

+    */

+   public static void handlePerformAndQuitOption(CmdLineOptionInstance option) {

+      Validate.notNull(option);

+

+      if (option.isHandleable()

+            && ((HandleableCmdLineOption) option.getOption()).getHandler() != null) {

+         ((HandleableCmdLineOption) option.getOption()).getHandler()

+               .handleOption(null, option);

+      }

+

+      if (option.isGroup()) {

+         for (CmdLineOptionInstance subOption : option.getSubOptions()) {

+            handlePerformAndQuitOption(subOption);

+         }

+      }     

+   }

+

+   /**

+    * Runs the {@link CmdLineOptionInstance}'s handler against the given

+    * {@link CmdLineAction}.

+    * 

+    * @param action

+    *           The {@link CmdLineAction} which the given

+    *           {@link CmdLineOptionInstance}'s handler will be run against

+    * @param option

+    *           The {@link CmdLineOptionInstance} whose handler will be run

+    *           against the given {@link CmdLineAction}

+    */

+   public static void handle(CmdLineAction action, CmdLineOptionInstance option) {

+      Validate.notNull(action);

+      Validate.notNull(option);

+

+      if (option.isHandleable()

+            && ((HandleableCmdLineOption) option.getOption()).getHandler() != null) {

+         ((HandleableCmdLineOption) option.getOption()).getHandler()

+               .handleOption(action, option);

+      }

+

+      if (option.isGroup()) {

+         for (CmdLineOptionInstance subOption : option.getSubOptions()) {

+            handle(action, subOption);

+         }

+      }     

+   }

+

+   /**

+    * Formats given string to a string where txt starts at startIndex and wraps

+    * around at endIndex, all other indexes are filled with empty space.

+    */

+   public static String getFormattedString(String string, int startIndex,

+         int endIndex) {

+      StringBuffer outputString = new StringBuffer("");

+      String[] splitStrings = StringUtils.split(string, " ");

+      StringBuffer curLine = null;

+      for (int i = 0; i < splitStrings.length; i++) {

+         curLine = new StringBuffer("");

+         curLine.append(splitStrings[i] + " ");

+

+         for (; i + 1 < splitStrings.length

+               && curLine.length() + splitStrings[i + 1].length() <= (endIndex - startIndex); i++)

+            curLine.append(splitStrings[i + 1] + " ");

+

+         outputString.append(StringUtils.repeat(" ", startIndex)

+               + curLine.toString() + "\n");

+      }

+      return outputString.toString();

+   }

+

+   public static List<?> convertToType(List<String> values, Class<?> type)

+         throws MalformedURLException, ClassNotFoundException,

+         InstantiationException, IllegalAccessException {

+      if (type.equals(File.class)) {

+         List<Object> files = new LinkedList<Object>();

+         for (String value : values)

+            files.add(new File(value));

+         return files;

+      } else if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)) {

+         List<Object> booleans = new LinkedList<Object>();

+         for (String value : values)

+            booleans.add(value.toLowerCase().trim().equals("true"));

+         return booleans;

+      } else if (type.equals(URL.class)) {

+         List<Object> urls = new LinkedList<Object>();

+         for (String value : values)

+            urls.add(new URL(value));

+         return urls;

+      } else if (type.equals(Class.class)) {

+         List<Object> classes = new LinkedList<Object>();

+         for (String value : values)

+            classes.add(Class.forName(value));

+         return classes;

+      } else if (type.equals(List.class)) {

+         List<Object> lists = new LinkedList<Object>();

+         lists.add(values);

+         return lists;

+      } else if (type.equals(Integer.class) || type.equals(Integer.TYPE)) {

+         List<Object> ints = new LinkedList<Object>();

+         for (String value : values)

+            ints.add(new Integer(value));

+         return ints;

+      } else if (type.equals(Long.class) || type.equals(Long.TYPE)) {

+         List<Object> longs = new LinkedList<Object>();

+         for (String value : values)

+            longs.add(new Long(value));

+         return longs;

+      } else if (type.equals(Double.class) || type.equals(Double.TYPE)) {

+         List<Object> doubles = new LinkedList<Object>();

+         for (String value : values)

+            doubles.add(new Double(value));

+         return doubles;

+      } else if (type.equals(String.class)) {

+         StringBuffer combinedString = new StringBuffer("");

+         for (String value : values)

+            combinedString.append(value + " ");

+         return Lists.newArrayList(combinedString.toString().trim());

+      } else {

+         List<Object> objects = new LinkedList<Object>();

+         for (String value : values) {

+            Object object = Class.forName(value).newInstance();

+            if (!type.isAssignableFrom(object.getClass())) {

+               throw new RuntimeException(object.getClass() + " is not a valid"

+                     + " type or sub-type of " + type);

+            }

+            objects.add(object);

+         }

+         return objects;

+      }

+   }

+}

diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/util/OptionPropertyRegister.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/util/OptionPropertyRegister.java
new file mode 100644
index 0000000..41f6ff5
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/util/OptionPropertyRegister.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.util;
+
+//JDK imports
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+
+//Google imports
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+/**
+ * Register for determining if a Java Property is required or optional and
+ * thus determining which options become required or optional because
+ * said property has been registered.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class OptionPropertyRegister {
+
+   private static Map<String, CmdLineOption> optionRegistrations = Maps.newHashMap();
+
+   private OptionPropertyRegister() {
+      throw new RuntimeException("Do not instantiate OptionPropertyRegister");
+   }
+
+   public static void registerOption(String property, CmdLineOption option) {
+      Validate.isTrue(!optionRegistrations.containsKey(property),
+            "Property '" + property + "' is already registered to: "
+            + optionRegistrations.get(property));
+
+      optionRegistrations.put(property, option);
+   }
+
+   public static CmdLineOption getRegisteredOption(String property) {
+      for (Entry<String, CmdLineOption> optionRegistration : optionRegistrations.entrySet()) {
+         if (optionRegistration.getKey().equals(property)) {
+            return optionRegistration.getValue();
+         }
+      }
+      return null;
+   }
+   
+   public static Set<String> getProperties(CmdLineOption specifiedOption) {
+      Set<String> properties = Sets.newHashSet();
+      for (Entry<String, CmdLineOption> optionRegistration : optionRegistrations.entrySet()) {
+         if (optionRegistration.getValue().equals(specifiedOption)) {
+            properties.add(optionRegistration.getKey());
+         }
+      }
+      return properties;
+   }
+
+   public static void clearRegister() {
+      optionRegistrations.clear();
+   }
+}
diff --git a/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/util/ParsedArg.java b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/util/ParsedArg.java
new file mode 100644
index 0000000..03f9acd
--- /dev/null
+++ b/0.8.1-rc1/cli/src/main/java/org/apache/oodt/cas/cli/util/ParsedArg.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.util;
+
+/**
+ * 
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class ParsedArg {
+
+   public enum Type {
+      OPTION, VALUE;
+   }
+
+   private String name;
+   private Type type;
+
+   public ParsedArg(String name, Type type) {
+      this.name = name;
+      this.type = type;
+   }
+
+   public String getName() {
+      return name;
+   }
+
+   public Type getType() {
+      return type;
+   }
+
+   public String toString() {
+      return name + " : " + type;
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/TestCmdLineArgs.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/TestCmdLineArgs.java
new file mode 100644
index 0000000..b6a5963
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/TestCmdLineArgs.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli;
+
+//Google static imports
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Sets.newHashSet;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createAction;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createActionOption;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createOptionInstance;
+
+//JDK imports
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.cli.CmdLineArgs;
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.option.ActionCmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.HelpCmdLineOption;
+import org.apache.oodt.cas.cli.option.PrintSupportedActionsCmdLineOption;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link CmdLineArgs}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestCmdLineArgs extends TestCase {
+
+   private final static CmdLineAction TEST_ACTION_1 = createAction("TestAction1");
+   private final static CmdLineAction TEST_ACTION_2 = createAction("TestAction2");
+   private final static CmdLineAction TEST_ACTION_3 = createAction("TestAction3");
+
+   private final static ActionCmdLineOption ACTION_OPTION = createActionOption("operation");
+   private final static HelpCmdLineOption HELP_OPTION = new HelpCmdLineOption();
+   private final static PrintSupportedActionsCmdLineOption PSA_ACTION = new PrintSupportedActionsCmdLineOption();
+
+   private final static Set<CmdLineAction> SUPPORTED_ACTIONS = newHashSet(
+         TEST_ACTION_1, TEST_ACTION_2, TEST_ACTION_3);
+   private final static Set<CmdLineOption> SUPPORTED_OPTIONS = newHashSet(
+         (CmdLineOption) ACTION_OPTION, (CmdLineOption) HELP_OPTION,
+         (CmdLineOption) PSA_ACTION);
+
+   public void testBaseCase() {
+      CmdLineOptionInstance specifiedAction = createOptionInstance(
+            ACTION_OPTION, TEST_ACTION_1.getName());
+      Set<CmdLineOptionInstance> specifiedOptions = newHashSet(specifiedAction);
+      CmdLineArgs args = new CmdLineArgs(SUPPORTED_ACTIONS, SUPPORTED_OPTIONS,
+            specifiedOptions);
+      assertEquals(TEST_ACTION_1, args.getSpecifiedAction());
+      assertEquals(args.getActionOptionInst(), specifiedAction);
+      assertEquals(ACTION_OPTION, args.getActionOptionInst().getOption());
+      assertNull(args.getHelpOptionInst());
+      assertNull(args.getPrintSupportedActionsOptionInst());
+   }
+
+   public void testCaseActionNotSupported() {
+      CmdLineOptionInstance specifiedAction = createOptionInstance(
+            ACTION_OPTION, "NotSupportedActionName");
+      Set<CmdLineOptionInstance> specifiedOptions = newHashSet(specifiedAction);
+      CmdLineArgs args = new CmdLineArgs(SUPPORTED_ACTIONS, SUPPORTED_OPTIONS,
+            specifiedOptions);
+
+      // Verify that CmdLineAction is null since it was not able to be located
+      // in set of supported actions.
+      assertNull(args.getSpecifiedAction());
+      // Verify that if did find the action option.
+      assertEquals(specifiedAction.getOption(), args.getActionOptionInst()
+            .getOption());
+      // Verify that if found the specified action even though it is not
+      // supported.
+      assertEquals(newArrayList("NotSupportedActionName"), args
+            .getActionOptionInst().getValues());
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/TestCmdLineUtility.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/TestCmdLineUtility.java
new file mode 100644
index 0000000..561140b
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/TestCmdLineUtility.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.CmdLineUtility.validate;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createActionOption;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createAdvancedOption;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createApplyToActionHandler;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createOptionInstance;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.determineFailedValidation;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.getOptionByName;
+
+//JDK imports
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.cli.CmdLineArgs;
+import org.apache.oodt.cas.cli.CmdLineUtility;
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.action.PrintMessageAction;
+import org.apache.oodt.cas.cli.option.AdvancedCmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.HelpCmdLineOption;
+import org.apache.oodt.cas.cli.option.PrintSupportedActionsCmdLineOption;
+import org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator;
+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator.Result;
+import org.apache.oodt.cas.cli.test.util.TestUtils;
+
+//Google imports
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link CmdLineUtility}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestCmdLineUtility extends TestCase {
+
+   public void testCheck() {
+      CmdLineArgs args = getArgs();
+
+      // Expect pass.
+      assertEquals(0, CmdLineUtility.check(args).size());
+
+      // Expect fail.
+      args.getSupportedOptions().add(
+            TestUtils.createSimpleOption("ReqTestAction", true));
+      assertEquals(1, CmdLineUtility.check(args).size());
+   }
+
+   public void testValidate() {
+      CmdLineArgs args = getArgs();
+
+      // Expect pass.
+      assertEquals(1, CmdLineUtility.validate(args).size());
+      assertEquals(Result.Grade.PASS, CmdLineUtility.validate(args).get(0)
+            .getGrade());
+
+      // Add validator which will cause fail.
+      AdvancedCmdLineOption option = (AdvancedCmdLineOption) getOptionByName("message", args.getSupportedOptions());
+      ArgRegExpCmdLineOptionValidator validator = new ArgRegExpCmdLineOptionValidator();
+      validator.setAllowedArgs(Lists.newArrayList("\\d{1,2}"));
+      option.addValidator(validator);
+
+      // Expect fail.
+      assertFalse(determineFailedValidation(validate(args)).isEmpty());
+   }
+
+   public void testHandle() {
+      CmdLineArgs args = getArgs();
+
+      // Verify handling works.
+      PrintMessageAction action = (PrintMessageAction) args
+            .getSpecifiedAction();
+      assertNull(action.getMessage());
+      CmdLineUtility.handle(args);
+      assertEquals("Test Message", action.getMessage());
+   }
+
+   private CmdLineArgs getArgs() {
+      // Setup Supported Actions.
+      String actionName = "TestAction";
+      PrintMessageAction action = new PrintMessageAction();
+      action.setName(actionName);
+      Set<CmdLineAction> actions = Sets.newHashSet((CmdLineAction) action);
+
+      // Setup Supported Options.
+      Set<CmdLineOption> options = Sets.newHashSet();
+      options.add(new HelpCmdLineOption());
+      options.add(new PrintSupportedActionsCmdLineOption());
+      options.add(createActionOption("action"));
+      AdvancedCmdLineOption option = createAdvancedOption("message",
+            createApplyToActionHandler(actionName, "setMessage"));
+      ArgRegExpCmdLineOptionValidator validator = new ArgRegExpCmdLineOptionValidator();
+      validator.setAllowedArgs(Lists.newArrayList(".*"));
+      option.addValidator(validator);
+      options.add(option);
+
+      // Setup Specified Options.
+      Set<CmdLineOptionInstance> specifiedOptions = Sets.newHashSet();
+      specifiedOptions.add(createOptionInstance(option, "Test Message"));
+      specifiedOptions.add(createOptionInstance(createActionOption("action"),
+            "TestAction"));
+
+      // Setup CmdLineArgs.
+      return new CmdLineArgs(actions, options, specifiedOptions);
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/action/store/spring/TestSpringCmdLineActionStore.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/action/store/spring/TestSpringCmdLineActionStore.java
new file mode 100644
index 0000000..a629679
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/action/store/spring/TestSpringCmdLineActionStore.java
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.action.store.spring;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findAction;
+
+//JDK imports
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+//Apache imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.action.PrintMessageAction;
+import org.apache.oodt.cas.cli.action.store.spring.SpringCmdLineActionStore;
+import org.apache.oodt.cas.cli.exception.CmdLineActionStoreException;
+import org.apache.oodt.cas.cli.test.util.TestSetContextInjectTypeAction;
+
+//Spring imports
+import org.springframework.context.ApplicationContext;
+
+/**
+ * Test case for {@link SpringCmdLineActionStore}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestSpringCmdLineActionStore extends TestCase {
+
+   private static final String SPRING_CONFIG = "src/test/resources/cmd-line-actions.xml";
+
+   public void testActionNamesAutoSet() {
+      SpringCmdLineActionStore store = new SpringCmdLineActionStore(
+            SPRING_CONFIG);
+      ApplicationContext appContext = store.getApplicationContext();
+      @SuppressWarnings("unchecked")
+      Map<String, CmdLineAction> actionsMap = appContext
+            .getBeansOfType(CmdLineAction.class);
+      for (Entry<String, CmdLineAction> entry : actionsMap.entrySet()) {
+         assertEquals(entry.getKey(), entry.getValue().getName());
+      }
+   }
+
+   public void testApplicationContextAutoSet() throws CmdLineActionStoreException {
+      SpringCmdLineActionStore store = new SpringCmdLineActionStore(
+            SPRING_CONFIG);
+      TestSetContextInjectTypeAction action = (TestSetContextInjectTypeAction) findAction(
+            "TestSetContextInjectAction", store.loadSupportedActions());
+      assertEquals(action.getContext(), store.getApplicationContext());
+   }
+
+   public void testLoadSupportedActions() throws CmdLineActionStoreException {
+      SpringCmdLineActionStore store = new SpringCmdLineActionStore(
+            SPRING_CONFIG);
+      Set<CmdLineAction> actions = store.loadSupportedActions();
+
+      // Check that all actions were loaded.
+      assertEquals(3, actions.size());
+
+      // Load and verify PrintMessageAction was loaded correctly.
+      CmdLineAction action = findAction("PrintMessageAction", actions);
+      assertTrue(action instanceof PrintMessageAction);
+      PrintMessageAction pma = (PrintMessageAction) action;
+      assertEquals("Prints out a given message", pma.getDescription());
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      try {
+         pma.execute(printer);
+         fail("Should have thrown IllegalArgumentException");
+      } catch (IllegalArgumentException e) { /* do nothing */ }
+      assertEquals(0, printer.getPrintedMessages().size());
+
+      // Load and verify PrintHelloWorldAction was loaded correctly.
+      action = findAction("PrintHelloWorldAction", actions);
+      assertTrue(action instanceof PrintMessageAction);
+      pma = (PrintMessageAction) action;
+      assertEquals("Prints out 'Hello World'", pma.getDescription());
+      assertEquals("Hello World", pma.getMessage());
+      pma.execute(printer);
+      assertEquals(1, printer.getPrintedMessages().size());
+      assertEquals(pma.getMessage(), printer.getPrintedMessages().get(0));
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/handler/TestApplyToAction.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/handler/TestApplyToAction.java
new file mode 100644
index 0000000..06a5a4c
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/handler/TestApplyToAction.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.handler;
+
+//JUnit imports
+import org.apache.oodt.cas.cli.option.handler.ApplyToAction;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link ApplyToAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestApplyToAction extends TestCase {
+
+   public void testVariableSetters() {
+      ApplyToAction applyToAction = new ApplyToAction();
+      assertNull(applyToAction.getActionName());
+      assertNull(applyToAction.getMethodName());
+
+      String actionName = "message";
+      applyToAction.setActionName(actionName);
+      assertEquals(actionName, applyToAction.getActionName());
+
+      String methodName = "setMessage";
+      applyToAction.setMethodName(methodName);
+      assertEquals(methodName, applyToAction.getMethodName());
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/handler/TestApplyToActionHandler.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/handler/TestApplyToActionHandler.java
new file mode 100644
index 0000000..1b8a0a3
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/handler/TestApplyToActionHandler.java
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.handler;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createAdvancedOption;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createApplyToActionHandler;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createOptionInstance;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.action.PrintMessageAction;
+import org.apache.oodt.cas.cli.option.AdvancedCmdLineOption;
+import org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link ApplyToActionHandler}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestApplyToActionHandler extends TestCase {
+
+   public void testWithoutApplyToActionMappingSet() {
+      ApplyToActionHandler handler = new ApplyToActionHandler();
+      assertNull(handler.getApplyToActions());
+      PrintMessageAction action = new PrintMessageAction();
+      action.setName("PrintMessageAction");
+
+      assertNull(action.getMessage());
+
+      AdvancedCmdLineOption option = new AdvancedCmdLineOption();
+      option.setLongOption("message");
+      option.setHandler(handler);
+      option.getHandler().handleOption(action,
+            createOptionInstance(option, "Howdy"));
+
+      assertEquals("Howdy", action.getMessage());
+   }
+
+   public void testApplyToActionsMapping() {
+      PrintMessageAction action = new PrintMessageAction();
+      action.setName("PrintMessageAction");
+      AdvancedCmdLineOption option = createAdvancedOption("printMessage",
+            createApplyToActionHandler(action.getName(), "setMessage"));
+      option.getHandler().handleOption(action,
+            createOptionInstance(option, "Howdy"));
+
+      assertEquals("Howdy", action.getMessage());
+   }
+
+   public void testSetOrAddInvoke() {
+      TestCmdLineAction action = new TestCmdLineAction();
+      action.setName("TestAction");
+      AdvancedCmdLineOption option = createAdvancedOption("message",
+            createApplyToActionHandler(action.getName(), null));
+
+      // Test that default isRepeating() is false.
+      option.getHandler().handleOption(action,
+            createOptionInstance(option, "Howdy"));
+      assertEquals(TestCmdLineAction.CallType.SET, action.getCallType());
+
+      // Test when isRepeating() is set to false.
+      option.setRepeating(false);
+      option.getHandler().handleOption(action,
+            createOptionInstance(option, "Howdy"));
+      assertEquals(TestCmdLineAction.CallType.SET, action.getCallType());
+
+      // Test when isRepeating() is set to true.
+      option.setRepeating(true);
+      option.getHandler().handleOption(action,
+            createOptionInstance(option, "Howdy"));
+      assertEquals(TestCmdLineAction.CallType.ADD, action.getCallType());
+   }
+
+   public static class TestCmdLineAction extends CmdLineAction {
+      public enum CallType { ADD, SET };
+      private CallType callType;
+
+      @Override
+      public void execute(ActionMessagePrinter printer) {
+      }
+
+      public void addMessage(String message) {
+         callType = CallType.ADD;
+      }
+
+      public void setMessage(String message) {
+         callType = CallType.SET;
+      }
+
+      public CallType getCallType () {
+         return callType;
+      }
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/handler/TestSetJavaPropertiesHandler.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/handler/TestSetJavaPropertiesHandler.java
new file mode 100644
index 0000000..442ce50
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/handler/TestSetJavaPropertiesHandler.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.handler;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createAdvancedOption;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createOptionInstance;
+
+//JDK imports
+import java.util.List;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * Test class for {@link SetJavaPropertiesHandler}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestSetJavaPropertiesHandler extends TestCase {
+
+   public void testSettingOfProperties() {
+      String property = "test.property";
+      SetJavaPropertiesHandler handler = new SetJavaPropertiesHandler();
+      handler.setPropertyNames(Lists.newArrayList(property));
+      CmdLineOption option = createAdvancedOption("testOption", handler);
+      CmdLineOptionInstance optionInstance = createOptionInstance(option, "Hello", "World");
+
+      assertNull(System.getProperty(property));
+      
+      handler.handleOption(null, optionInstance);
+      assertEquals("Hello World", System.getProperty(property));
+
+      option.setType(List.class);
+      handler.handleOption(null, optionInstance);
+      assertEquals("Hello,World", System.getProperty(property));
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/require/TestActionDependencyRule.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/require/TestActionDependencyRule.java
new file mode 100644
index 0000000..35f3a34
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/require/TestActionDependencyRule.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.require;
+
+//OODT imports
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createAction;
+
+//OODT imports
+import org.apache.oodt.cas.cli.option.require.ActionDependencyRule;
+import org.apache.oodt.cas.cli.option.require.RequirementRule.Relation;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link ActionDependencyRule}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestActionDependencyRule extends TestCase {
+
+   public void testInitialCase() {
+      ActionDependencyRule actionDependency = new ActionDependencyRule();
+      assertNull(actionDependency.getActionName());
+      assertNull(actionDependency.getRelation());
+   }
+
+   public void testVariableSetting() {
+      String actionName = "operation";
+      Relation relation = Relation.OPTIONAL;
+      ActionDependencyRule actionDependency = new ActionDependencyRule(
+            actionName, relation);
+      assertEquals(actionName, actionDependency.getActionName());
+      assertEquals(relation, actionDependency.getRelation());
+
+      actionName = "action";
+      relation = Relation.REQUIRED;
+      actionDependency.setActionName(actionName);
+      actionDependency.setRelation(relation);
+      assertEquals(actionName, actionDependency.getActionName());
+      assertEquals(relation, actionDependency.getRelation());
+   }
+
+   public void testGetRelation() {
+      String actionName = "operation";
+      Relation relation = Relation.OPTIONAL;
+      ActionDependencyRule actionDependency = new ActionDependencyRule(
+            actionName, relation);
+      assertEquals(relation,
+            actionDependency.getRelation(createAction(actionName)));
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/store/spring/TestSpringCmdLineOptionStore.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/store/spring/TestSpringCmdLineOptionStore.java
new file mode 100644
index 0000000..419b7ef
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/store/spring/TestSpringCmdLineOptionStore.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.store.spring;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createOptionInstance;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findAction;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.getOptionByName;
+
+//JDK imports
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.action.PrintMessageAction;
+import org.apache.oodt.cas.cli.action.store.spring.SpringCmdLineActionStore;
+import org.apache.oodt.cas.cli.exception.CmdLineActionStoreException;
+import org.apache.oodt.cas.cli.exception.CmdLineOptionStoreException;
+import org.apache.oodt.cas.cli.option.AdvancedCmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler;
+import org.apache.oodt.cas.cli.option.require.ActionDependencyRule;
+import org.apache.oodt.cas.cli.option.require.RequirementRule.Relation;
+import org.apache.oodt.cas.cli.option.store.spring.SpringCmdLineOptionStore;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link SpringCmdLineOptionStore}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestSpringCmdLineOptionStore extends TestCase {
+
+   private static final String SPRING_OPTION_CONFIG = "src/test/resources/cmd-line-options.xml";
+   private static final String SPRING_ACTION_CONFIG = "src/test/resources/cmd-line-actions.xml";
+
+   public void testLoadSupportedOptions() throws CmdLineActionStoreException,
+         CmdLineOptionStoreException {
+      SpringCmdLineOptionStore optionStore = new SpringCmdLineOptionStore(
+            SPRING_OPTION_CONFIG);
+      Set<CmdLineOption> options = optionStore.loadSupportedOptions();
+      SpringCmdLineActionStore actionStore = new SpringCmdLineActionStore(
+            SPRING_ACTION_CONFIG);
+      Set<CmdLineAction> actions = actionStore.loadSupportedActions();
+
+      // Check that all options were loaded.
+      assertEquals(2, options.size());
+
+      // Load and verify printHelloWorld was loaded correctly.
+      CmdLineOption option = getOptionByName("printHelloWorld", options);
+      assertTrue(option instanceof AdvancedCmdLineOption);
+      AdvancedCmdLineOption advancedOption = (AdvancedCmdLineOption) option;
+      assertEquals("phw", advancedOption.getShortOption());
+      assertEquals("printHelloWorld", advancedOption.getLongOption());
+      assertEquals("Print Hello World", advancedOption.getDescription());
+      assertFalse(advancedOption.hasArgs());
+      assertEquals(1, advancedOption.getStaticArgs().size());
+      assertEquals("Hello World!", advancedOption.getStaticArgs().get(0));
+      assertEquals(1, advancedOption.getRequirementRules().size());
+      assertEquals("PrintMessageAction", ((ActionDependencyRule) advancedOption
+            .getRequirementRules().get(0)).getActionName());
+      assertEquals(Relation.OPTIONAL, ((ActionDependencyRule) advancedOption
+            .getRequirementRules().get(0)).getRelation());
+
+      // Load and verify printMessage was loaded correctly.
+      option = getOptionByName("printMessage", options);
+      assertTrue(option instanceof AdvancedCmdLineOption);
+      advancedOption = (AdvancedCmdLineOption) option;
+      assertEquals("pm", advancedOption.getShortOption());
+      assertEquals("printMessage", advancedOption.getLongOption());
+      assertEquals("Message to print out", advancedOption.getDescription());
+      assertEquals(true, advancedOption.hasArgs());
+      assertEquals("message", advancedOption.getArgsDescription());
+      assertEquals(1, advancedOption.getRequirementRules().size());
+      assertEquals("PrintMessageAction", ((ActionDependencyRule) advancedOption
+            .getRequirementRules().get(0)).getActionName());
+      assertEquals(Relation.REQUIRED, ((ActionDependencyRule) advancedOption
+            .getRequirementRules().get(0)).getRelation());
+      assertNotNull(advancedOption.getHandler());
+      assertTrue(advancedOption.getHandler() instanceof ApplyToActionHandler);
+      assertEquals(1, ((ApplyToActionHandler) advancedOption.getHandler())
+            .getApplyToActions().size());
+      assertEquals(findAction("PrintMessageAction", actions).getName(),
+            ((ApplyToActionHandler) advancedOption.getHandler())
+                  .getApplyToActions().get(0).getActionName());
+      assertEquals("setMessage",
+            ((ApplyToActionHandler) advancedOption.getHandler())
+                  .getApplyToActions().get(0).getMethodName());
+   }
+
+   public void testHandlers() throws CmdLineActionStoreException,
+         CmdLineOptionStoreException {
+      SpringCmdLineOptionStore store = new SpringCmdLineOptionStore(
+            SPRING_OPTION_CONFIG);
+      Set<CmdLineOption> options = store.loadSupportedOptions();
+      SpringCmdLineActionStore actionStore = new SpringCmdLineActionStore(
+            SPRING_ACTION_CONFIG);
+      Set<CmdLineAction> actions = actionStore.loadSupportedActions();
+
+      // Load PrintHelloWorldAction
+      PrintMessageAction printHelloWorldAction = (PrintMessageAction) findAction(
+            "PrintMessageAction", actions);
+      AdvancedCmdLineOption printHelloWorldOption = (AdvancedCmdLineOption) getOptionByName(
+            "printHelloWorld", options);
+      printHelloWorldOption.getHandler().handleOption(printHelloWorldAction,
+            createOptionInstance(printHelloWorldOption));
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      printHelloWorldAction.execute(printer);
+      assertEquals(1, printer.getPrintedMessages().size());
+      assertEquals("Hello World!", printer.getPrintedMessages().get(0));
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestAllowedArgsCmdLineOptionValidator.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestAllowedArgsCmdLineOptionValidator.java
new file mode 100644
index 0000000..eb54ddf
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestAllowedArgsCmdLineOptionValidator.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.validator;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createOptionInstance;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createSimpleOption;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.validator.AllowedArgsCmdLineOptionValidator;
+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator.Result;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * Test class for {@link AllowedArgsCmdLineOptionValidator}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestAllowedArgsCmdLineOptionValidator extends TestCase {
+
+   public void testIntialState() {
+      // Test no null option instance allowed.
+      try {
+         new AllowedArgsCmdLineOptionValidator().validate(null);
+         fail("Should have thrown IllegalArgumentException");
+      } catch (IllegalArgumentException ignore) { /* expect throw */
+      }
+
+      // Test no allowed args set and valid option instance
+      CmdLineOptionInstance instance = createOptionInstance(
+            createSimpleOption("test", false), "value");
+      assertEquals(Result.Grade.FAIL, new AllowedArgsCmdLineOptionValidator()
+            .validate(instance).getGrade());
+   }
+
+   public void testValidate() {
+      AllowedArgsCmdLineOptionValidator validator = new AllowedArgsCmdLineOptionValidator();
+      validator.setAllowedArgs(Lists.newArrayList("value1", "value2"));
+
+      // Test no null option instance allowed.
+      try {
+         validator.validate(null);
+         fail("Should have thrown IllegalArgumentException");
+      } catch (IllegalArgumentException ignore) { /* expect throw */
+      }
+
+      // Test should fail case.
+      CmdLineOptionInstance instance = createOptionInstance(
+            createSimpleOption("test", false), "value");
+      assertEquals(Result.Grade.FAIL, validator.validate(instance).getGrade());
+
+      // Test should pass case.
+      instance = createOptionInstance(createSimpleOption("test", false),
+            "value1");
+      assertEquals(Result.Grade.PASS, validator.validate(instance).getGrade());
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestArgRegExpCmdLineOptionValidator.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestArgRegExpCmdLineOptionValidator.java
new file mode 100644
index 0000000..55cb66b
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestArgRegExpCmdLineOptionValidator.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.validator;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createOptionInstance;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createSimpleOption;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.validator.AllowedArgsCmdLineOptionValidator;
+import org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator;
+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator.Result;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * Test class for {@link ArgRegExpCmdLineOptionValidator}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestArgRegExpCmdLineOptionValidator extends TestCase {
+
+   public void testInitialCase() {
+      // Test null option instancd not allowed.
+      try {
+         new ArgRegExpCmdLineOptionValidator().validate(null);
+         fail("Should have thrown IllegalArgumentException");
+      } catch (IllegalArgumentException ignore) { /* expect throw */
+      }
+
+      // Test no allowed args set and valid option instance
+      CmdLineOptionInstance instance = createOptionInstance(
+            createSimpleOption("test", false), "value");
+      assertEquals(Result.Grade.FAIL, new AllowedArgsCmdLineOptionValidator()
+            .validate(instance).getGrade());
+   }
+
+   public void testValidate() {
+      ArgRegExpCmdLineOptionValidator validator = new ArgRegExpCmdLineOptionValidator();
+      validator.setAllowedArgs(Lists.newArrayList("v.*?1", "v.*?2"));
+
+      // Test no null option instance allowed.
+      try {
+         validator.validate(null);
+         fail("Should have thrown IllegalArgumentException");
+      } catch (IllegalArgumentException ignore) { /* expect throw */
+      }
+
+      // Test should fail case.
+      CmdLineOptionInstance instance = createOptionInstance(
+            createSimpleOption("test", false), "value");
+      assertEquals(Result.Grade.FAIL, validator.validate(instance).getGrade());
+
+      // Test should pass case.
+      instance = createOptionInstance(createSimpleOption("test", false),
+            "value1");
+      assertEquals(Result.Grade.PASS, validator.validate(instance).getGrade());
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestClassExistsCmdLineOptionValidator.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestClassExistsCmdLineOptionValidator.java
new file mode 100644
index 0000000..72abf9f
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestClassExistsCmdLineOptionValidator.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.validator;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createOptionInstance;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createSimpleOption;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.validator.ClassExistsCmdLineOptionValidator;
+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator.Result;
+
+/**
+ * Test class for {@link ClassExistsCmdLineOptionValidator}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestClassExistsCmdLineOptionValidator extends TestCase {
+
+   public void testValidate() {
+      // Check null option instance not allowed.
+      try {
+         new ClassExistsCmdLineOptionValidator().validate(null);
+      } catch (IllegalArgumentException ignore) { /* expect throw */
+      }
+
+      // Check fail case.
+      CmdLineOptionInstance instance = createOptionInstance(
+            createSimpleOption("test", false), "bogus");
+      assertEquals(Result.Grade.FAIL, new ClassExistsCmdLineOptionValidator()
+            .validate(instance).getGrade());
+
+      // Check pass case.
+      instance = createOptionInstance(createSimpleOption("test", false),
+            "java.lang.String");
+      assertEquals(Result.Grade.PASS, new ClassExistsCmdLineOptionValidator()
+            .validate(instance).getGrade());
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestFileExistCmdLineOptionValidator.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestFileExistCmdLineOptionValidator.java
new file mode 100644
index 0000000..7a85f44
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestFileExistCmdLineOptionValidator.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.validator;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createOptionInstance;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createSimpleOption;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator;
+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator.Result;
+
+/**
+ * Test class for {@link FileExistCmdLineOptionValidator}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestFileExistCmdLineOptionValidator extends TestCase {
+
+   public void testValidate() throws IOException {
+      // Test null option instance not allowed.
+      try {
+         new FileExistCmdLineOptionValidator().validate(null);
+         fail("Should have thrown IllegalArgumentException");
+      } catch (IllegalArgumentException ignore) { /* expect throw */
+      }
+
+      // Test fail case.
+      CmdLineOptionInstance instance = createOptionInstance(
+            createSimpleOption("test", false), "bogus");
+      assertEquals(Result.Grade.FAIL, new FileExistCmdLineOptionValidator()
+            .validate(instance).getGrade());
+
+      // Test pass case.
+      File tempFile = File.createTempFile("bogus", "bogus");
+      tempFile.deleteOnExit();
+      instance = createOptionInstance(createSimpleOption("test", false),
+            tempFile.getAbsolutePath());
+      assertEquals(Result.Grade.PASS, new FileExistCmdLineOptionValidator()
+            .validate(instance).getGrade());
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestNoRestrictionsCmdLineOptionValidator.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestNoRestrictionsCmdLineOptionValidator.java
new file mode 100644
index 0000000..aa5ef9c
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/option/validator/TestNoRestrictionsCmdLineOptionValidator.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.option.validator;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createOptionInstance;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createSimpleOption;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.validator.NoRestrictionsCmdLineOptionValidator;
+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator.Result;
+
+/**
+ * Test class for {@link NoRestrictionsCmdLineOptionValidator}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestNoRestrictionsCmdLineOptionValidator extends TestCase {
+
+   public void testValidate() {
+      // Test pass for null option instance.
+      assertEquals(Result.Grade.PASS,
+            new NoRestrictionsCmdLineOptionValidator().validate(null)
+                  .getGrade());
+
+      // Test pass for not null option instance.
+      CmdLineOptionInstance instance = createOptionInstance(
+            createSimpleOption("test", false), "bogus");
+      assertEquals(Result.Grade.PASS,
+            new NoRestrictionsCmdLineOptionValidator().validate(instance)
+                  .getGrade());
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/parser/TestStdCmdLineOptionParser.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/parser/TestStdCmdLineOptionParser.java
new file mode 100644
index 0000000..8786834
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/parser/TestStdCmdLineOptionParser.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.parser;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineParserException;
+import org.apache.oodt.cas.cli.util.ParsedArg;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link StdCmdLineOptionParser}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestStdCmdLineOptionParser extends TestCase {
+
+   public void testParser() throws CmdLineParserException {
+      String[] args =
+            "--group --list one two three four --scalar one --none --group --list one --scalar one"
+                  .split(" ");
+
+      // Parse args.
+      StdCmdLineParser parser = new StdCmdLineParser();
+      List<ParsedArg> parsedArgs = parser.parse(args);
+
+      // Check that 14 option instances where returned.
+      assertEquals(14, parsedArgs.size());
+
+      // Check that all args where found and assigned the appropriate type.
+      assertEquals("group", parsedArgs.get(0).getName());
+      assertEquals(ParsedArg.Type.OPTION, parsedArgs.get(0).getType());
+      assertEquals("list", parsedArgs.get(1).getName());
+      assertEquals(ParsedArg.Type.OPTION, parsedArgs.get(1).getType());
+      assertEquals("one", parsedArgs.get(2).getName());
+      assertEquals(ParsedArg.Type.VALUE, parsedArgs.get(2).getType());
+      assertEquals("two", parsedArgs.get(3).getName());
+      assertEquals(ParsedArg.Type.VALUE, parsedArgs.get(3).getType());      
+      assertEquals("three", parsedArgs.get(4).getName());
+      assertEquals(ParsedArg.Type.VALUE, parsedArgs.get(4).getType());
+      assertEquals("four", parsedArgs.get(5).getName());
+      assertEquals(ParsedArg.Type.VALUE, parsedArgs.get(5).getType());
+      assertEquals("scalar", parsedArgs.get(6).getName());
+      assertEquals(ParsedArg.Type.OPTION, parsedArgs.get(6).getType());
+      assertEquals("one", parsedArgs.get(7).getName());
+      assertEquals(ParsedArg.Type.VALUE, parsedArgs.get(7).getType());
+      assertEquals("none", parsedArgs.get(8).getName());
+      assertEquals(ParsedArg.Type.OPTION, parsedArgs.get(8).getType());
+      assertEquals("group", parsedArgs.get(9).getName());
+      assertEquals(ParsedArg.Type.OPTION, parsedArgs.get(9).getType());
+      assertEquals("list", parsedArgs.get(10).getName());
+      assertEquals(ParsedArg.Type.OPTION, parsedArgs.get(10).getType());
+      assertEquals("one", parsedArgs.get(11).getName());
+      assertEquals(ParsedArg.Type.VALUE, parsedArgs.get(11).getType());
+      assertEquals("scalar", parsedArgs.get(12).getName());
+      assertEquals(ParsedArg.Type.OPTION, parsedArgs.get(12).getType());
+      assertEquals("one", parsedArgs.get(13).getName());
+      assertEquals(ParsedArg.Type.VALUE, parsedArgs.get(13).getType());
+   }
+
+   public void testIsOption() {
+      assertTrue(StdCmdLineParser.isOption("--arg"));
+      assertTrue(StdCmdLineParser.isOption("-arg"));
+      assertFalse(StdCmdLineParser.isOption("arg"));
+   }
+
+   public void testGetOptionName() {
+      assertEquals("arg", StdCmdLineParser.getOptionName("--arg"));
+      assertEquals("arg", StdCmdLineParser.getOptionName("-arg"));
+      assertNull(StdCmdLineParser.getOptionName("arg"));
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/test/util/TestOutputStream.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/test/util/TestOutputStream.java
new file mode 100644
index 0000000..c0d3998
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/test/util/TestOutputStream.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.test.util;
+
+//JDK imports
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Test {@link OutputStream} which writes everything to a {@link StringBuffer}
+ * which can be retrieved to see what was written.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestOutputStream extends OutputStream {
+
+   private StringBuffer sb = new StringBuffer("");
+
+   @Override
+   public void write(int character) throws IOException {
+      sb.append((char) character);
+   }
+
+   public String getText() {
+      return sb.toString();
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/test/util/TestSetContextInjectTypeAction.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/test/util/TestSetContextInjectTypeAction.java
new file mode 100644
index 0000000..f1e934e
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/test/util/TestSetContextInjectTypeAction.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.test.util;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.action.store.spring.SpringSetContextInjectionType;
+
+//Spring imports
+import org.springframework.context.ApplicationContext;
+
+/**
+ * Test {@link CmdLineAction} for testing {@link SpringSetContextInjectionType}
+ * are injected with the {@link ApplicationContext} correctly.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestSetContextInjectTypeAction extends CmdLineAction implements
+      SpringSetContextInjectionType {
+
+   private ApplicationContext appContext;
+
+   @Override
+   public void execute(ActionMessagePrinter printer) {
+   }
+
+   public void setContext(ApplicationContext appContext) {
+      this.appContext = appContext;
+   }
+
+   public ApplicationContext getContext() {
+      return appContext;
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/test/util/TestUtils.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/test/util/TestUtils.java
new file mode 100644
index 0000000..8353bb7
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/test/util/TestUtils.java
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.test.util;
+
+//JDK imports
+import java.util.Collections;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.option.ActionCmdLineOption;
+import org.apache.oodt.cas.cli.option.AdvancedCmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.GroupCmdLineOption;
+import org.apache.oodt.cas.cli.option.SimpleCmdLineOption;
+import org.apache.oodt.cas.cli.option.handler.ApplyToAction;
+import org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler;
+import org.apache.oodt.cas.cli.option.handler.CmdLineOptionHandler;
+import org.apache.oodt.cas.cli.option.require.ActionDependencyRule;
+import org.apache.oodt.cas.cli.option.require.RequirementRule;
+import org.apache.oodt.cas.cli.option.require.RequirementRule.Relation;
+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * Base Test case for CAS-CL unit tests.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestUtils {
+
+   public static CmdLineAction createAction(String name) {
+      return new CmdLineAction(name, "This is an action description") {
+
+         @Override
+         public void execute(ActionMessagePrinter printer) {
+            // do nothing
+         }
+
+      };
+   }
+
+   public static GroupCmdLineOption createGroupOption(String longName,
+         boolean required) {
+      GroupCmdLineOption option = new GroupCmdLineOption();
+      option.setLongOption(longName);
+      option.setShortOption(longName);
+      option.setRequired(required);
+      return option;
+   }
+
+   public static SimpleCmdLineOption createSimpleOption(String longName,
+         boolean required) {
+      return createSimpleOption(longName, longName, required);
+   }
+
+   public static SimpleCmdLineOption createSimpleOption(String shortName,
+         String longName, boolean required) {
+      SimpleCmdLineOption option = new SimpleCmdLineOption();
+      option.setShortOption(shortName);
+      option.setLongOption(longName);
+      option.setRequired(required);
+      return option;
+   }
+
+   public static SimpleCmdLineOption createSimpleOption(String longName,
+         RequirementRule rule) {
+      return createSimpleOption(longName, longName, rule);
+   }
+
+   public static SimpleCmdLineOption createSimpleOption(String shortName,
+         String longName, RequirementRule rule) {
+      SimpleCmdLineOption option = new SimpleCmdLineOption();
+      option.setShortOption(shortName);
+      option.setLongOption(longName);
+      option.setRequirementRules(Collections.singletonList(rule));
+      return option;
+   }
+
+   public static AdvancedCmdLineOption createAdvancedOption(String longName,
+         CmdLineOptionHandler handler) {
+      return createAdvancedOption(longName, longName, handler);
+   }
+
+   public static AdvancedCmdLineOption createAdvancedOption(String shortName,
+         String longName, CmdLineOptionHandler handler) {
+      AdvancedCmdLineOption option = new AdvancedCmdLineOption();
+      option.setShortOption(shortName);
+      option.setLongOption(longName);
+      option.setHandler(handler);
+      return option;
+   }
+
+   public static AdvancedCmdLineOption createValidationOption(String longName,
+         CmdLineOptionValidator... validators) {
+      AdvancedCmdLineOption option = new AdvancedCmdLineOption();
+      option.setLongOption(longName);
+      option.setShortOption(longName);
+      option.setValidators(Lists.newArrayList(validators));
+      return option;
+   }
+
+   public static ActionCmdLineOption createActionOption(String longName) {
+      ActionCmdLineOption option = new ActionCmdLineOption();
+      option.setLongOption(longName);
+      option.setShortOption(longName);
+      return option;
+   }
+
+   public static CmdLineOptionInstance createOptionInstance(
+         CmdLineOption option, String... values) {
+      return new CmdLineOptionInstance(option, Lists.newArrayList(values));
+   }
+
+   public static RequirementRule createRequiredRequirementRule(
+         CmdLineAction action) {
+      ActionDependencyRule rule = new ActionDependencyRule();
+      rule.setActionName(action.getName());
+      rule.setRelation(Relation.REQUIRED);
+      return rule;
+   }
+
+   public static RequirementRule createOptionalRequirementRule(
+         CmdLineAction action) {
+      ActionDependencyRule rule = new ActionDependencyRule();
+      rule.setActionName(action.getName());
+      rule.setRelation(Relation.OPTIONAL);
+      return rule;
+   }
+
+   public static ApplyToActionHandler createApplyToActionHandler(
+         String actionName, String methodName) {
+      ApplyToActionHandler handler = new ApplyToActionHandler();
+      handler.setApplyToActions(Lists.newArrayList(new ApplyToAction(
+            actionName, methodName)));
+      return handler;
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/util/TestCmdLineIterable.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/util/TestCmdLineIterable.java
new file mode 100644
index 0000000..3ba75e3
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/util/TestCmdLineIterable.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.util;
+
+//JDK imports
+import java.util.Arrays;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineParserException;
+import org.apache.oodt.cas.cli.parser.StdCmdLineParser;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link Args}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestCmdLineIterable extends TestCase {
+
+   private static final String ARGS_STRING = "--operation download --url http://somewhere.com --user foo --pass bar --toDir /tmp";
+
+   public void testIteration() throws CmdLineParserException {
+      StringBuffer argsString = new StringBuffer("");
+      CmdLineIterable<ParsedArg> args = createArgs();
+      for (ParsedArg arg : args) {
+         if (arg.getType().equals(ParsedArg.Type.OPTION)) {
+            argsString.append("--");
+         }
+         argsString.append(arg.getName()).append(" ");
+         int i = 0;
+         for (ParsedArg argInner : args) {
+            if (argInner.getType().equals(ParsedArg.Type.OPTION)) {
+               argsString.append("--");
+            }
+            argsString.append(argInner.getName()).append(" ");
+            if (i++ > 1) {
+               break;
+            }
+         }
+         arg = args.incrementAndGet();
+         if (arg.getType().equals(ParsedArg.Type.OPTION)) {
+            argsString.append("--");
+         }
+         argsString.append(arg.getName()).append(" ");
+      }
+
+      assertEquals(Arrays.asList(ARGS_STRING.split(" ")),
+            Arrays.asList(argsString.toString().split(" ")));
+   }
+
+   public void testIndexOutOfBoundsException() throws CmdLineParserException {
+      CmdLineIterable<ParsedArg> args = new CmdLineIterable<ParsedArg>(
+            new StdCmdLineParser().parse(new String[] {}));
+      try {
+         args.iterator().next();
+         fail("Should have thrown IndexOutOfBoundsException");
+      } catch (IndexOutOfBoundsException ignore) { /* expect throw */
+      }
+   }
+
+   private CmdLineIterable<ParsedArg> createArgs() throws CmdLineParserException {
+      return new CmdLineIterable<ParsedArg>(
+            new StdCmdLineParser().parse(ARGS_STRING.split(" ")));
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/util/TestCmdLineUtils.java b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/util/TestCmdLineUtils.java
new file mode 100644
index 0000000..c4ce9cc
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/java/org/apache/oodt/cas/cli/util/TestCmdLineUtils.java
@@ -0,0 +1,527 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.cli.util;
+
+//OODT static imports
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createAction;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createActionOption;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createAdvancedOption;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createGroupOption;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createOptionInstance;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createOptionalRequirementRule;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createRequiredRequirementRule;
+import static org.apache.oodt.cas.cli.test.util.TestUtils.createSimpleOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.determineFailedValidation;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findFirstActionOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findSpecifiedActionOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findSpecifiedHelpOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.findSpecifiedPrintSupportedActionsOption;
+import static org.apache.oodt.cas.cli.util.CmdLineUtils.validate;
+
+//JDK imports
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.option.ActionCmdLineOption;
+import org.apache.oodt.cas.cli.option.AdvancedCmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.GroupCmdLineOption;
+import org.apache.oodt.cas.cli.option.GroupSubOption;
+import org.apache.oodt.cas.cli.option.HelpCmdLineOption;
+import org.apache.oodt.cas.cli.option.PrintSupportedActionsCmdLineOption;
+import org.apache.oodt.cas.cli.option.SimpleCmdLineOption;
+import org.apache.oodt.cas.cli.option.handler.CmdLineOptionHandler;
+import org.apache.oodt.cas.cli.option.validator.AllowedArgsCmdLineOptionValidator;
+import org.apache.oodt.cas.cli.option.validator.CmdLineOptionValidator;
+import org.apache.oodt.cas.cli.test.util.TestUtils;
+import org.apache.oodt.cas.cli.util.CmdLineUtils;
+
+//Google imports
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * Test class for {@link CmdLineUtils}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestCmdLineUtils extends TestCase {
+
+   public void testDetermineRequired() {
+      CmdLineAction action = createAction("TestAction");
+      CmdLineOption urlOption, passOption, actionOption;
+
+      HashSet<CmdLineOption> options = Sets.newHashSet(
+            urlOption = createSimpleOption("url",
+                  createRequiredRequirementRule(action)),
+            passOption = createSimpleOption("pass", false),
+            createSimpleOption("user", false),
+            actionOption = createActionOption("operation"));
+
+      Set<CmdLineOption> requiredOptions = CmdLineUtils.determineRequired(
+            action, options);
+      assertEquals(Sets.newHashSet(urlOption, actionOption), requiredOptions);
+
+      options = Sets.newHashSet(
+            urlOption = createSimpleOption("url",
+                  createRequiredRequirementRule(action)),
+            passOption = createSimpleOption("pass", true),
+            createSimpleOption("user", false),
+            actionOption = createActionOption("operation"));
+
+      requiredOptions = CmdLineUtils.determineRequired(action, options);
+      assertEquals(Sets.newHashSet(urlOption, passOption, actionOption),
+            requiredOptions);
+   }
+
+   public void testIsRequired() {
+      CmdLineAction action = createAction("TestAction");
+      assertTrue(CmdLineUtils.isRequired(action,
+            createSimpleOption("url", createRequiredRequirementRule(action))));
+      assertTrue(CmdLineUtils.isRequired(action,
+            createSimpleOption("url", true)));
+      assertFalse(CmdLineUtils.isRequired(action,
+            createSimpleOption("url", false)));
+   }
+
+   public void testDetermineOptional() {
+      CmdLineAction action = createAction("TestAction");
+      CmdLineOption actionOption = new ActionCmdLineOption();
+      CmdLineOption passOption, userOption;
+
+      HashSet<CmdLineOption> options = Sets.newHashSet(
+            createSimpleOption("url", createRequiredRequirementRule(action)),
+            passOption = createSimpleOption("pass", false),
+            userOption = createSimpleOption("user", false), actionOption);
+
+      Set<CmdLineOption> optionalOptions = CmdLineUtils.determineOptional(
+            action, options);
+      assertEquals(2, optionalOptions.size());
+      assertEquals(Sets.newHashSet(passOption, userOption), optionalOptions);
+
+      options = Sets.newHashSet(createSimpleOption("pass", true),
+            createSimpleOption("user", true), actionOption);
+
+      optionalOptions = CmdLineUtils.determineOptional(action, options);
+      assertTrue(optionalOptions.isEmpty());
+
+      options = Sets.newHashSet(
+            passOption = createSimpleOption("pass",
+                  createOptionalRequirementRule(action)),
+            userOption = createSimpleOption("user",
+                  createOptionalRequirementRule(action)), actionOption);
+
+      optionalOptions = CmdLineUtils.determineOptional(action, options);
+      assertEquals(Sets.newHashSet(passOption, userOption), optionalOptions);
+   }
+
+   public void testIsOptional() {
+      CmdLineAction action = createAction("TestAction");
+      assertTrue(CmdLineUtils.isOptional(action,
+            createSimpleOption("url", createOptionalRequirementRule(action))));
+      assertFalse(CmdLineUtils.isOptional(action,
+            createSimpleOption("url", true)));
+      assertTrue(CmdLineUtils.isOptional(action,
+            createSimpleOption("url", false)));
+   }
+
+   public void testGetRequiredOptions() {
+      CmdLineOption urlOption = createSimpleOption("url", true);
+      HashSet<CmdLineOption> options = Sets.newHashSet(urlOption,
+            createActionOption("action"), createSimpleOption("user", false),
+            createSimpleOption("pass", false));
+
+      assertEquals(Sets.newHashSet(urlOption),
+            CmdLineUtils.getRequiredOptions(options));
+   }
+
+   public void testGetRequiredOptionsDoNotIgnoreActionOptions() {
+      CmdLineOption actionOption, urlOption;
+      HashSet<CmdLineOption> options = Sets.newHashSet(
+            actionOption = createActionOption("action"),
+            urlOption = createSimpleOption("url", true),
+            createSimpleOption("user", false),
+            createSimpleOption("pass", false));
+
+      actionOption.setRequired(true);
+      assertEquals(Sets.newHashSet(actionOption, urlOption),
+            CmdLineUtils.getRequiredOptions(options, false));
+   }
+
+   public void testSortOptionsByRequiredStatus() {
+      CmdLineAction action = createAction("action");
+      CmdLineOption userOption, urlOption, passOption, actionOption;
+      HashSet<CmdLineOption> options = Sets.newHashSet(
+            userOption = createSimpleOption("user", false),
+            urlOption = createSimpleOption("url",
+                  createRequiredRequirementRule(action)),
+            passOption = createSimpleOption("pass", false),
+            actionOption = createActionOption("action"));
+
+      actionOption.setRequired(true);
+      List<CmdLineOption> sortedOptions = CmdLineUtils
+            .sortOptionsByRequiredStatus(options);
+      assertEquals(options.size(), sortedOptions.size());
+      assertEquals(actionOption, sortedOptions.get(0));
+      assertEquals(urlOption, sortedOptions.get(1));
+      assertEquals(Sets.newHashSet(userOption, passOption),
+            Sets.newHashSet(sortedOptions.get(2), sortedOptions.get(3)));
+   }
+
+   public void testSortActions() {
+      Set<CmdLineAction> actions = Sets.newHashSet(
+            createAction("Tom"),
+            createAction("Bill"),
+            createAction("Young"),
+            createAction("Andy"));
+      List<CmdLineAction> sortedActions = CmdLineUtils.sortActions(actions);
+      assertEquals("Andy", sortedActions.get(0).getName());
+      assertEquals("Bill", sortedActions.get(1).getName());
+      assertEquals("Tom", sortedActions.get(2).getName());
+      assertEquals("Young", sortedActions.get(3).getName());
+   }
+
+   public void testGetOptionByName() {
+      CmdLineAction action = createAction("action");
+      CmdLineOption userOption, urlOption, passOption, actionOption;
+      HashSet<CmdLineOption> options = Sets.newHashSet(
+            userOption = createSimpleOption("user", "username", false),
+            urlOption = createSimpleOption("u", "url",
+                  createRequiredRequirementRule(action)),
+            passOption = createSimpleOption("pass", "password", false),
+            actionOption = createActionOption("action"));
+
+      assertEquals(userOption,
+            CmdLineUtils.getOptionByName(userOption.getShortOption(), options));
+      assertEquals(userOption,
+            CmdLineUtils.getOptionByName(userOption.getLongOption(), options));
+      assertEquals(urlOption,
+            CmdLineUtils.getOptionByName(urlOption.getShortOption(), options));
+      assertEquals(urlOption,
+            CmdLineUtils.getOptionByName(urlOption.getLongOption(), options));
+      assertEquals(passOption,
+            CmdLineUtils.getOptionByName(passOption.getShortOption(), options));
+      assertEquals(passOption,
+            CmdLineUtils.getOptionByName(passOption.getLongOption(), options));
+      assertEquals(actionOption, CmdLineUtils.getOptionByName(
+            actionOption.getShortOption(), options));
+      assertEquals(actionOption,
+            CmdLineUtils.getOptionByName(actionOption.getLongOption(), options));
+   }
+
+   public void testGetOptionInstanceByName() {
+      CmdLineAction action = createAction("action");
+      CmdLineOptionInstance userOptionInst, urlOptionInst, passOptionInst, actionOptionInst;
+      HashSet<CmdLineOptionInstance> optionInsts = Sets.newHashSet(
+            userOptionInst = new CmdLineOptionInstance(createSimpleOption(
+                  "user", "username", false), new ArrayList<String>()),
+            urlOptionInst = new CmdLineOptionInstance(createSimpleOption("u",
+                  "url", createRequiredRequirementRule(action)),
+                  new ArrayList<String>()),
+            passOptionInst = new CmdLineOptionInstance(createSimpleOption(
+                  "pass", "password", false), new ArrayList<String>()),
+            actionOptionInst = new CmdLineOptionInstance(
+                  createActionOption("action"), new ArrayList<String>()));
+
+      assertEquals(userOptionInst, CmdLineUtils.getOptionInstanceByName(
+            userOptionInst.getOption().getShortOption(), optionInsts));
+      assertEquals(userOptionInst, CmdLineUtils.getOptionInstanceByName(
+            userOptionInst.getOption().getLongOption(), optionInsts));
+      assertEquals(urlOptionInst, CmdLineUtils.getOptionInstanceByName(
+            urlOptionInst.getOption().getShortOption(), optionInsts));
+      assertEquals(urlOptionInst, CmdLineUtils.getOptionInstanceByName(
+            urlOptionInst.getOption().getLongOption(), optionInsts));
+      assertEquals(passOptionInst, CmdLineUtils.getOptionInstanceByName(
+            passOptionInst.getOption().getShortOption(), optionInsts));
+      assertEquals(passOptionInst, CmdLineUtils.getOptionInstanceByName(
+            passOptionInst.getOption().getLongOption(), optionInsts));
+      assertEquals(actionOptionInst, CmdLineUtils.getOptionInstanceByName(
+            actionOptionInst.getOption().getShortOption(), optionInsts));
+      assertEquals(actionOptionInst, CmdLineUtils.getOptionInstanceByName(
+            actionOptionInst.getOption().getLongOption(), optionInsts));
+   }
+
+   public void testIsSubOption() {
+      CmdLineOption subOption = createSimpleOption("test", false);
+      GroupCmdLineOption groupOption = createGroupOption("group", false);
+      assertFalse(CmdLineUtils.isSubOption(groupOption, subOption));
+
+      groupOption.addSubOption(new GroupSubOption(subOption, false));
+      assertTrue(CmdLineUtils.isSubOption(groupOption, subOption));
+   }
+
+   public void testFindPerformAndQuitOptions() {
+      AdvancedCmdLineOption performAndQuitOption = createAdvancedOption("help",
+            null);
+      performAndQuitOption.setPerformAndQuit(true);
+      AdvancedCmdLineOption otherOption = createAdvancedOption("help", null);
+      otherOption.setPerformAndQuit(false);
+
+      CmdLineOptionInstance performAndQuitOptionInstance = new CmdLineOptionInstance(
+            performAndQuitOption, new ArrayList<String>());
+      CmdLineOptionInstance otherInstance = new CmdLineOptionInstance(
+            otherOption, new ArrayList<String>());
+
+      assertEquals(Sets.newHashSet(performAndQuitOptionInstance),
+            CmdLineUtils.findPerformAndQuitOptions(Sets.newHashSet(
+                  performAndQuitOptionInstance, otherInstance)));
+   }
+
+   public void testIsPerformAndQuitOption() {
+      AdvancedCmdLineOption performAndQuitOption = createAdvancedOption("help",
+            null);
+      performAndQuitOption.setPerformAndQuit(true);
+      AdvancedCmdLineOption otherOption = createAdvancedOption("help", null);
+      otherOption.setPerformAndQuit(false);
+
+      assertTrue(CmdLineUtils.isPerformAndQuitOption(performAndQuitOption));
+      assertFalse(CmdLineUtils.isPerformAndQuitOption(otherOption));
+   }
+
+   public void testFindSpecifiedOption() {
+      CmdLineOption findOption = createSimpleOption("test", false);
+      Set<CmdLineOptionInstance> options = Sets.newHashSet(
+            createOptionInstance(createSimpleOption("test1", false)),
+            createOptionInstance(createSimpleOption("test2", false)));
+
+      assertNull(CmdLineUtils.findSpecifiedOption(findOption, options));
+      options.add(createOptionInstance(findOption));
+      assertEquals(createOptionInstance(findOption),
+            CmdLineUtils.findSpecifiedOption(findOption, options));
+   }
+
+   public void testFindAllOfSpecifiedOption() {
+      CmdLineOption findOption = createSimpleOption("test", false);
+      Set<CmdLineOptionInstance> options = Sets.newHashSet(
+            createOptionInstance(createSimpleOption("test1", false)),
+            createOptionInstance(createSimpleOption("test2", false)));
+
+      assertTrue(CmdLineUtils.findAllOfSpecifiedOption(findOption, options)
+            .isEmpty());
+      CmdLineOptionInstance firstOption = createOptionInstance(findOption,
+            "first");
+      CmdLineOptionInstance secondOption = createOptionInstance(findOption,
+            "second");
+      options.add(firstOption);
+      assertEquals(Sets.newHashSet(firstOption),
+            CmdLineUtils.findAllOfSpecifiedOption(findOption, options));
+      options.add(secondOption);
+      assertEquals(Sets.newHashSet(firstOption, secondOption),
+            CmdLineUtils.findAllOfSpecifiedOption(findOption, options));
+   }
+
+   public void testIsPrintSupportedActionsOption() {
+      assertFalse(CmdLineUtils
+            .isPrintSupportedActionsOption(createSimpleOption("test", false)));
+      assertTrue(CmdLineUtils
+            .isPrintSupportedActionsOption(new PrintSupportedActionsCmdLineOption()));
+   }
+
+   public void testFindPrintSupportedActionsOption() {
+      CmdLineOption psaAction = new PrintSupportedActionsCmdLineOption();
+      Set<CmdLineOption> options = Sets.newHashSet(
+            (CmdLineOption) createSimpleOption("test", false),
+            createSimpleOption("test2", false));
+
+      assertNull(CmdLineUtils.findPrintSupportedActionsOption(options));
+      options.add(psaAction);
+      assertEquals(psaAction,
+            CmdLineUtils.findPrintSupportedActionsOption(options));
+   }
+
+   public void testFindSpecifiedPrintSupportedActionsOption() {
+      CmdLineOptionInstance psaAction = createOptionInstance(
+            new PrintSupportedActionsCmdLineOption());
+      Set<CmdLineOptionInstance> options = Sets.newHashSet(
+            createOptionInstance(createSimpleOption("test", false)),
+            createOptionInstance(createSimpleOption("test2", false)));
+
+      assertNull(findSpecifiedPrintSupportedActionsOption(options));
+      options.add(psaAction);
+      assertEquals(psaAction,
+            findSpecifiedPrintSupportedActionsOption(options));
+      options.add(createOptionInstance(new PrintSupportedActionsCmdLineOption(
+            "psa2", "PrintSupportedActions2", "Print Actions 2", false)));
+      try {
+         findSpecifiedPrintSupportedActionsOption(options);
+         fail("Should have thrown IllegalArgumentException");
+      } catch (IllegalArgumentException ignore) { /* expect throw */ }
+   }
+
+   public void testIsSimpleOption() {
+      assertTrue(CmdLineUtils
+            .isSimpleOption(new PrintSupportedActionsCmdLineOption()));
+      assertTrue(CmdLineUtils.isSimpleOption(new HelpCmdLineOption()));
+      assertTrue(CmdLineUtils.isSimpleOption(createSimpleOption("Test", true)));
+   }
+
+   public void testIsActionOption() {
+      assertFalse(CmdLineUtils.isActionOption(new HelpCmdLineOption()));
+      assertTrue(CmdLineUtils.isActionOption(createActionOption("action")));
+   }
+
+   public void testFindActionOption() {
+      ActionCmdLineOption actionOption = createActionOption("action");
+      Set<CmdLineOption> options = Sets.newHashSet(
+            (CmdLineOption) createSimpleOption("test", false),
+            createSimpleOption("test", false));
+
+      assertNull(findFirstActionOption(options));
+      options.add(actionOption);
+      assertEquals(actionOption, findFirstActionOption(options));
+   }
+
+   public void testFindSpecifiedActionOption() {
+      CmdLineOptionInstance actionOption = createOptionInstance(createActionOption("action"));
+      Set<CmdLineOptionInstance> options = Sets.newHashSet(
+            createOptionInstance(createSimpleOption("test", false)),
+            createOptionInstance(createSimpleOption("test", false)));
+
+      assertNull(findSpecifiedActionOption(options));
+      options.add(actionOption);
+      assertEquals(actionOption,
+            findSpecifiedActionOption(options));
+      options.add(createOptionInstance(createActionOption("action2")));
+      try {
+         findSpecifiedActionOption(options);
+         fail("Should have thrown IllegalArgumentException");
+      } catch (IllegalArgumentException ignore) { /* expect throw */ }
+      
+   }
+
+   public void testIsGroupOption() {
+      assertFalse(CmdLineUtils.isGroupOption(new HelpCmdLineOption()));
+      assertTrue(CmdLineUtils.isGroupOption(createGroupOption("test", false)));
+   }
+
+   public void testAsGroupOption() {
+      try {
+         CmdLineUtils.asGroupOption(createSimpleOption("test", false));
+         fail("Should have thrown IllegalArgumentException");
+      } catch (IllegalArgumentException ignore) { /* expect throw */
+      }
+      CmdLineUtils.asGroupOption(createGroupOption("test", false));
+   }
+
+   public void testIsHelpOption() {
+      assertFalse(CmdLineUtils.isHelpOption(createSimpleOption("test", false)));
+      assertTrue(CmdLineUtils.isHelpOption(new HelpCmdLineOption()));
+   }
+
+   public void testAsHelpOption() {
+      try {
+         CmdLineUtils.asHelpOption(createSimpleOption("test", false));
+         fail("Should have thrown IllegalArgumentException");
+      } catch (IllegalArgumentException ignore) { /* expect throw */ }
+      CmdLineUtils.asHelpOption(new HelpCmdLineOption());
+   }
+
+   public void testFindHelpOption() {
+      HelpCmdLineOption helpOption = new HelpCmdLineOption();
+      Set<CmdLineOption> options = Sets.newHashSet(
+            (CmdLineOption) createSimpleOption("test", false),
+            createSimpleOption("test", false));
+
+      assertNull(CmdLineUtils.findHelpOption(options));
+      options.add(helpOption);
+      assertEquals(helpOption, CmdLineUtils.findHelpOption(options));
+   }
+
+   public void testFindSpecifiedHelpOption() {
+      CmdLineOptionInstance helpOption = createOptionInstance(new HelpCmdLineOption());
+      Set<CmdLineOptionInstance> options = Sets.newHashSet(
+            createOptionInstance(createSimpleOption("test", false)),
+            createOptionInstance(createSimpleOption("test", false)));
+
+      assertNull(findSpecifiedHelpOption(options));
+      options.add(helpOption);
+      assertEquals(helpOption, findSpecifiedHelpOption(options));
+      options.add(createOptionInstance(new HelpCmdLineOption("h2", "help2", "Second Help Option", true)));
+      try {
+         findSpecifiedHelpOption(options);
+         fail("Should have thrown IllegalArgumentException");
+      } catch (IllegalArgumentException ignore) { /* expect throw */ }
+   }
+
+   public void testValidate() {
+      AdvancedCmdLineOption option = new AdvancedCmdLineOption("t", "test", "",
+            true);
+      AllowedArgsCmdLineOptionValidator validator = new AllowedArgsCmdLineOptionValidator();
+      validator.setAllowedArgs(Lists.newArrayList("value"));
+      option.setValidators(Lists
+            .newArrayList((CmdLineOptionValidator) validator));
+
+      // Test case fail.
+      assertFalse(determineFailedValidation(validate(createOptionInstance(option, "value1"))).isEmpty());
+      // Test case pass.
+      assertTrue(determineFailedValidation(validate(createOptionInstance(option, "value"))).isEmpty());
+   }
+
+   public void testHandle() {
+      CmdLineAction action = createAction("testAction");
+      action.setDescription("test description");
+      AdvancedCmdLineOption option = new AdvancedCmdLineOption("t", "test", "",
+            true);
+      // Insure runs with no errors when action doesn't have a handler.
+      CmdLineUtils.handle(action, createOptionInstance(option));
+
+      // Test case when option has a handler.
+      option.setHandler(new CmdLineOptionHandler() {
+         @Override
+         public void initialize(CmdLineOption option) {}
+
+         @Override
+         public void handleOption(CmdLineAction selectedAction,
+               CmdLineOptionInstance optionInstance) {
+            selectedAction.setDescription("handler modified description");
+         }
+
+         @Override
+         public String getHelp(CmdLineOption option) {
+            return null;
+         }
+
+         @Override
+         public String getArgDescription(CmdLineAction action,
+               CmdLineOption option) {
+            return null;
+         }
+      });
+      CmdLineUtils.handle(action, createOptionInstance(option));
+      assertEquals("handler modified description", action.getDescription());
+   }
+
+   public void testFindAction() {
+      CmdLineAction action = createAction("TestAction1");
+      Set<CmdLineAction> actions = Sets.newHashSet(action,
+            createAction("TestAction2"), createAction("TestAction3"));
+      assertNull(CmdLineUtils.findAction(
+            createOptionInstance(createActionOption("action"), "TestAction"),
+            actions));
+      assertEquals(action, CmdLineUtils.findAction(
+            createOptionInstance(createActionOption("action"), "TestAction1"),
+            actions));
+   }
+}
diff --git a/0.8.1-rc1/cli/src/test/resources/cmd-line-actions.xml b/0.8.1-rc1/cli/src/test/resources/cmd-line-actions.xml
new file mode 100644
index 0000000..ca3fa77
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/resources/cmd-line-actions.xml
@@ -0,0 +1,36 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+	<bean id="PrintMessageAction" class="org.apache.oodt.cas.cli.action.PrintMessageAction">
+		<property name="description" value="Prints out a given message" />
+	</bean>
+	<bean id="PrintHelloWorldAction" class="org.apache.oodt.cas.cli.action.PrintMessageAction">
+		<property name="description" value="Prints out 'Hello World'" />
+		<property name="message" value="Hello World" />
+	</bean>
+	<bean id="TestSetContextInjectAction"
+		class="org.apache.oodt.cas.cli.test.util.TestSetContextInjectTypeAction">
+		<property name="description"
+			value="Test action for testing application context injection" />
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/cli/src/test/resources/cmd-line-options.xml b/0.8.1-rc1/cli/src/test/resources/cmd-line-options.xml
new file mode 100644
index 0000000..3418698
--- /dev/null
+++ b/0.8.1-rc1/cli/src/test/resources/cmd-line-options.xml
@@ -0,0 +1,75 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+	<bean id="printHelloWorld" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="phw" />
+		<property name="longOption" value="printHelloWorld" />
+		<property name="description" value="Print Hello World" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>Hello World!</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="PrintMessageAction" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+				<property name="applyToActions">
+					<list>
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="PrintMessageAction" p:methodName="setMessage" />
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="printMessage" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="pm" />
+		<property name="longOption" value="printMessage" />
+		<property name="description" value="Message to print out" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="message" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="PrintMessageAction" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+				<property name="applyToActions">
+					<list>
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="PrintMessageAction" p:methodName="setMessage" />
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/cluster-tools/scripts/shutdown.sh b/0.8.1-rc1/cluster-tools/scripts/shutdown.sh
new file mode 100755
index 0000000..5f866cf
--- /dev/null
+++ b/0.8.1-rc1/cluster-tools/scripts/shutdown.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+#
+# 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.
+#
+#Source environment and utilites
+ENVS=$(dirname $(readlink -f ${BASH_SOURCE[0]}))/../setup/env-vars.sh
+. ${ENVS}
+if ! isScript
+then
+    printError "Cannot source this file."
+    return 255
+fi
+#Now run commands
+echo "Attempting to kill Mesos master on: ${MESOS_MASTER_IP}"
+sshc ${MESOS_MASTER_IP} "pkill -u $(whoami) mesos-master" false \
+                             || printError "Could not terminate mesos master"
+#Loop through hosts and start slaves (except the first, which is master)
+for host in $(cat ${HOSTS_FILE} | grep -v "^#" | tail -n +2 )
+do
+    echo "Attempting to kill Mesos slave on: ${host}"
+    sshc ${host} "pkill -u $(whoami) mesos-slave" false \
+                      || printError "Could not terminate mesos slave on ${host}"
+done
+sshc ${RESOURCE_HOST} \
+    "pkill -u $(whoami) -f org.apache.oodt.cas.resource.system.XmlRpcResourceManager" false \
+    || printError "Could not terminate resource manager on host: ${RESOURCE_HOST}"
+#Shut down screen if using screen
+if [[ "${SCREEN}" != "" ]]
+then
+    screen -X -S ${SCREEN} quit
+fi
+#Shutdown Hadoop HDFS
+${HADOOP_HOME}/sbin/stop-dfs.sh
diff --git a/0.8.1-rc1/cluster-tools/scripts/start-up.sh b/0.8.1-rc1/cluster-tools/scripts/start-up.sh
new file mode 100755
index 0000000..0cf736b
--- /dev/null
+++ b/0.8.1-rc1/cluster-tools/scripts/start-up.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+#
+# 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.
+#
+#Source environment and utilites
+ENVS=$(dirname $(readlink -f ${BASH_SOURCE[0]}))/../setup/env-vars.sh
+. ${ENVS}
+if ! isScript
+then
+    printError "Cannot source this file."
+    return 255
+fi
+
+#Setup host to command map
+starts=()
+starts+=("mm ${MESOS_MASTER_IP} '$(printScriptLocation)/start-up/mesos-master.bash'")
+starts+=("rm ${RESOURCE_HOST}   '$(printScriptLocation)/start-up/resource.bash'")
+#Slaves
+let n=0
+for host in $(cat ${HOSTS_FILE} | grep -v "^#" | tail -n +2 )
+do
+    starts+=("s${n} ${host} '$(printScriptLocation)/start-up/mesos-slave.bash'")
+    let n=n+1
+done
+
+#Setup screen if existing
+if [[ "${SCREEN}" != "" ]]
+then
+    initScreen "${SCREEN}"
+fi
+#Start Hadoop HDFS 
+${HADOOP_HOME}/sbin/start-dfs.sh
+
+#Run all start-up commands
+for elem in "${starts[@]}"
+do
+    set -- ${elem}
+    tab=${1}
+    host=${2}
+    cmd=${3}
+    echo "Running: ${cmd} on ${host} via ${SCREEN:-ssh} (${tab})"
+    #Run in screen if set, or ssh if not set
+    if [[ "${SCREEN}" != "" ]]
+    then
+        screenr ${tab} ${host} "${cmd}" || errorAndExit "Could not run ${cmd} on ${host} via ${SCREEN}"
+    else
+        sshc ${host} "${cmd}" true || errorAndExit "Could not run ${cmd} on ${host} via ssh"
+    fi
+    sleep 1
+done
+
+
diff --git a/0.8.1-rc1/cluster-tools/scripts/start-up/mesos-master.bash b/0.8.1-rc1/cluster-tools/scripts/start-up/mesos-master.bash
new file mode 100755
index 0000000..7abe3cf
--- /dev/null
+++ b/0.8.1-rc1/cluster-tools/scripts/start-up/mesos-master.bash
@@ -0,0 +1,28 @@
+#!/bin/bash
+#
+# 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.
+#
+#Wrapper to start-up mesos-master.
+ENVS=$(dirname $(readlink -f ${BASH_SOURCE[0]}))/../../setup/env-vars.sh
+. ${ENVS}
+#Don't source this
+if ! isScript
+then
+    printError "Cannot source this file."
+    return 255
+fi
+mkdir -p ${RUN_DIR}/work/mesos
+${MESOS_BUILD}/bin/mesos-master.sh --ip=${MESOS_MASTER_IP}
diff --git a/0.8.1-rc1/cluster-tools/scripts/start-up/mesos-slave.bash b/0.8.1-rc1/cluster-tools/scripts/start-up/mesos-slave.bash
new file mode 100755
index 0000000..6036e81
--- /dev/null
+++ b/0.8.1-rc1/cluster-tools/scripts/start-up/mesos-slave.bash
@@ -0,0 +1,27 @@
+#!/bin/bash
+#
+# 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.
+#
+#Wrapper to start-up mesos-slave.
+ENVS=$(dirname $(readlink -f ${BASH_SOURCE[0]}))/../../setup/env-vars.sh
+. ${ENVS}
+#Don't source this
+if ! isScript
+then
+    printError "Cannot source this file."
+    return 255
+fi
+${MESOS_BUILD}/bin/mesos-slave.sh --master=${MESOS_MASTER_IP}:5050 --no-switch_user
diff --git a/0.8.1-rc1/cluster-tools/scripts/start-up/resource.bash b/0.8.1-rc1/cluster-tools/scripts/start-up/resource.bash
new file mode 100755
index 0000000..d3e9c40
--- /dev/null
+++ b/0.8.1-rc1/cluster-tools/scripts/start-up/resource.bash
@@ -0,0 +1,33 @@
+#!/bin/bash
+#
+# 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.
+#
+#Wrapper to start-up resource.
+ENVS=$(dirname $(readlink -f ${BASH_SOURCE[0]}))/../../setup/env-vars.sh
+. ${ENVS}
+#Start-up script
+if ! isScript
+then
+    printError "Cannot source this file."
+    return 255
+fi
+loc=${RESOURCE_HOME}/bin/
+(
+    cd ${loc}
+    ./resmgr start
+    #Wait required for catching output
+    wait
+)
diff --git a/0.8.1-rc1/cluster-tools/scripts/utilites.sh b/0.8.1-rc1/cluster-tools/scripts/utilites.sh
new file mode 100755
index 0000000..bea233b
--- /dev/null
+++ b/0.8.1-rc1/cluster-tools/scripts/utilites.sh
Binary files differ
diff --git a/0.8.1-rc1/cluster-tools/setup/deploy.sh b/0.8.1-rc1/cluster-tools/setup/deploy.sh
new file mode 100755
index 0000000..b4b151f
--- /dev/null
+++ b/0.8.1-rc1/cluster-tools/setup/deploy.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+#
+# 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.
+#
+#Variables are in the env_vars.sh file
+ENVS=$(dirname $(readlink -f ${BASH_SOURCE[0]}))/env-vars.sh
+if [ ! -f ./env-vars.sh ]
+then
+    echo "${ENVS} not found. Please use ${ENVS}.tmpl as a template to create it."
+    exit 1
+fi
+. ${ENVS}
+
+#Tell us what ya going to do
+echo "Deploying the cluster components:"
+echo "  Host file: ${HOSTS_FILE:-ERROR: Host file not set}"
+echo "  Temporary directory: ${TMP_DIR:-ERROR: Temp dir not set}"
+echo "  Install directory:   ${INSTALL_DIR:-ERROR: Install dir not set}"
+
+#Checking versions
+if [ -z ${INSTALL_DIR} ] || [ -z ${TMP_DIR} ] || [ -z ${HOSTS_FILE} ]
+then
+    echo "ERROR: Needed variables not set. Did you set the environment files?"
+    exit 1
+fi
+#Check directories exit
+if [ ! -d ${INSTALL_DIR} ] || [ ! -d ${TMP_DIR} ] || [ ! -f ${HOSTS_FILE} ]
+then
+    echo "ERROR: Needed directories or files don't exist"
+    exit 1
+fi
+#Cannot find scripts
+if [ ! -d ../scripts ]
+then
+    echo "ERROR: Cannot find scripts directory: ../scripts"
+    exit 1
+fi
+#Check space
+if [ -e ${INSTALL_DIR} ] && (( $(df -k ${INSTALL_DIR} | awk 'NR==3 {print $3}') < 5000000 ))
+then
+    echo "ERROR: Not enough space (5GB) to install in: ${INSTALL_DIR}."
+    exit 1 
+fi
+#Check space
+if (( $(df -k ${TMP_DIR} | awk 'NR==3 {print $3}') < 3000000 ))
+then
+    echo "ERROR: Not enough tmp space (3GB): ${TMP_DIR}."
+    exit 1
+fi
+
+while true; do
+    read -p "Continue installing(y/n)? " yn
+    case $yn in
+        [Yy]* ) break;;
+        [Nn]* ) exit;;
+        * ) echo "Please answer y or n.";;
+    esac
+done
+#Put on all hosts
+for host in $(cat ${HOSTS_FILE} | grep -v "^#" | tail -n +2 )
+do
+    echo "Deploying to: ${host}"
+    ssh ${host} "mkdir -p ${INSTALL_DIR};" \
+    ||{ \
+         echo "WARNING: Cannot create ${INSTALL_DIR} on ${host} Deploy manually."; \
+         continue;\
+      }
+    rsync -avz ${INSTALL_DIR}/* "${host}:${INSTALL_DIR}"
+done
diff --git a/0.8.1-rc1/cluster-tools/setup/env-vars.sh.tmpl b/0.8.1-rc1/cluster-tools/setup/env-vars.sh.tmpl
new file mode 100755
index 0000000..f78fd0a
--- /dev/null
+++ b/0.8.1-rc1/cluster-tools/setup/env-vars.sh.tmpl
@@ -0,0 +1,109 @@
+#!/bin/bash
+#
+# 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.
+#
+#****************************
+# Instructions:
+#   1. Copy this file to ./env-vars.sh
+#   2. Add execute permissions to ./env-vars.sh
+#   3. Change next three sections to configure installation
+#****************************
+
+#****************************
+# Set these directories:
+#  INSTALL_DIR - Directory used to install and run software.
+#  TMP_DIR - Temporary directory used as scratch space.
+#  RUN_DIR - Directory that will hold run-time artifacts from software.
+#****************************
+export RUN_DIR=/your/runtime/dir/goes/here
+export INSTALL_DIR=/your/install/dir/goes/here
+export TMP_DIR=/your/tmp/dir/goes/here
+
+#****************************
+# Set SCREEN if use of GNU Screen is desired
+#****************************
+#export SCREEN="soodt-screen"
+
+#****************************
+# Set Ports
+#****************************
+export HADOOP_NAMENODE_PORT=8090
+export MESOS_MASTER_PORT=5050
+
+#****************************
+# Set these versions of software 
+#****************************
+export APACHE_MESOS_VERSION=0.19.0
+export SCALA_VERSION=2.10.4
+export KAFKA_VERSION=2.10-0.8.1.1
+export SPARK_VERSION=1.1.0
+export TACHYON_VERSION=0.5.0
+export HADOOP_VERSION=2.4.0
+export CLUSTER_TOOLS_VERSION=trunk
+
+#****************************
+# Set JAVA_HOME (will use from environment if set)
+#****************************
+export JAVA_HOME=${JAVA_HOME:-/path/to/java/home/}
+
+###
+#Beyond This Line: Advanced Users Only
+#(Following lines should be setup properly)
+###
+# Hosts file
+export HOSTS_FILE="${INSTALL_DIR}/cluster-tools/setup/hosts"
+export ENV_VARS="${INSTALL_DIR}/cluster-tools/setup/env-vars.sh" 
+# Hosts
+if [ -f ${HOSTS_FILE} ]
+then
+    export MESOS_HOST="$(cat ${HOSTS_FILE} | grep -v "^#" | head -1)"
+    export HADOOP_NAMENODE="${MESOS_HOST}"
+fi
+export RESOURCEMGR_HOST=${MESOS_HOST}
+# HADOOP envs
+export HADOOP_HOME="${INSTALL_DIR}/hadoop-${HADOOP_VERSION}"
+export HADOOP_OPTS="-XX:-PrintWarnings"
+
+# Source utility function
+if [ -f $(dirname ${ENV_VARS})/../scripts/utilites.sh ]
+then
+    . $(dirname ${ENV_VARS})/../scripts/utilites.sh
+fi
+
+# Mesos variables
+export MESOS_BUILD="${INSTALL_DIR}/mesos-${APACHE_MESOS_VERSION}/build/"
+export MESOS_HOME="${MESOS_BUILD}"
+export MESOS_LOG_DIR="${RUN_DIR}/log/mesos/"
+export MESOS_WORK_DIR="${RUN_DIR}/work/mesos/"
+export MESOS_NATIVE_LIBRARY="${MESOS_BUILD}/src/.libs/libmesos.so"
+# Get mesos master ip
+if [ -n "${MESOS_HOST}" ]
+then
+    export MESOS_MASTER_IP="$(host ${MESOS_HOST} | awk '{print $NF}')"
+fi
+# For Spark
+export MASTER="mesos://${MESOS_MASTER_IP}:${MESOS_MASTER_PORT}"
+export SPARK_HOME="${INSTALL_DIR}/spark-${SPARK_VERSION}-bin-hadoop2.4"
+for lib in "${SPARK_HOME}/python/" "${SPARK_HOME}/python/build/"
+do
+    if [[ ${PYTHONPATH} != *${lib}* ]]
+    then
+        export PYTHONPATH=${PYTHONPATH}:${lib}
+    fi
+done
+# Resource manager
+export RESOURCE_HOST="${RESOURCEMGR_HOST}"
+export RESOURCE_HOME="${INSTALL_DIR}/oodt/resource" 
diff --git a/0.8.1-rc1/cluster-tools/setup/hdfs-config/core-site.xml b/0.8.1-rc1/cluster-tools/setup/hdfs-config/core-site.xml
new file mode 100644
index 0000000..9c7517e
--- /dev/null
+++ b/0.8.1-rc1/cluster-tools/setup/hdfs-config/core-site.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<!--
+  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. See accompanying LICENSE file.
+-->
+
+<!-- Put site-specific property overrides in this file. -->
+
+<configuration>
+  <property>
+    <name>fs.defaultFS</name>
+    <value>hdfs://[HDFS_HOST]:[HDFS_PORT]</value>
+    <description>Filesystem name node setup</description>
+  </property>
+</configuration>
diff --git a/0.8.1-rc1/cluster-tools/setup/hdfs-config/hdfs-site.xml b/0.8.1-rc1/cluster-tools/setup/hdfs-config/hdfs-site.xml
new file mode 100644
index 0000000..868f850
--- /dev/null
+++ b/0.8.1-rc1/cluster-tools/setup/hdfs-config/hdfs-site.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<!--
+  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. See accompanying LICENSE file.
+-->
+
+<!-- Put site-specific property overrides in this file. -->
+
+<configuration>
+  <property>
+    <name>dfs.namenode.name.dir</name>
+    <value>file://[INSTALL_DIR]/hadoop/name-node/</value>
+    <description>Filesystem name node logging dir</description>
+  </property>
+  <property>
+    <name>dfs.datanode.data.dir</name>
+    <value>file://[INSTALL_DIR]/hadoop/data-node/</value>
+    <description>Filesystem data node setup</description>
+  </property>
+
+</configuration>
diff --git a/0.8.1-rc1/cluster-tools/setup/hosts b/0.8.1-rc1/cluster-tools/setup/hosts
new file mode 100644
index 0000000..3fc2031
--- /dev/null
+++ b/0.8.1-rc1/cluster-tools/setup/hosts
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+#Hosts file:
+# List of hosts, lines starting with '#' are ignored.
+# First listed host is used as the MESOS master.
+host0.example.com
+host1.example.com
+host2.example.com
+host3.example.com
+host4.example.com
+host5.example.com
diff --git a/0.8.1-rc1/cluster-tools/setup/install.sh b/0.8.1-rc1/cluster-tools/setup/install.sh
new file mode 100755
index 0000000..e174b49
--- /dev/null
+++ b/0.8.1-rc1/cluster-tools/setup/install.sh
@@ -0,0 +1,197 @@
+#!/bin/bash
+# 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.
+
+#Variables are in the env_vars.sh file
+ENVS=$(dirname $(readlink -f ${BASH_SOURCE[0]}))/env-vars.sh
+HOSTS=$(dirname $(readlink -f ${BASH_SOURCE[0]}))/hosts
+if [ ! -f ${ENVS} ]
+then
+    echo "${ENVS} not found. Please use ${ENVS}.tmpl as a template to create it."
+    exit 1
+elif [ ! -f ${HOSTS} ]
+then
+    echo "${HOSTS} not found. Please use create a hosts file."
+    exit 1
+fi
+. ${ENVS}
+#Setup hosts from bootstraped host file
+MESOS_HOST="$(cat ${HOSTS} | grep -v "^#" | head -1)"
+HADOOP_NAMENODE="${MESOS_HOST}"
+
+#Tell us what ya going to do
+echo "Installing the BDAS components:"
+echo " ----------- Software Versions -----------"
+echo "  Mesos version:   ${APACHE_MESOS_VERSION:-ERROR: Version not set}"
+echo "  Scala version:   ${SCALA_VERSION:-ERROR: Version not set}"
+echo "  Kafka version:   ${KAFKA_VERSION:-ERROR: Version not set}"
+echo "  Spark version:   ${SPARK_VERSION:-ERROR: Version not set}"
+echo "  Tachyon version: ${TACHYON_VERSION:-ERROR: Version not set}"
+echo "  Hadoop version:  ${HADOOP_VERSION:-ERROR: Version not set}"
+echo "  Cluster Tools version:  ${CLUSTER_TOOLS_VERSION:-ERROR: Version not set}"
+echo " --------- Environment Variables ---------"
+echo "  Hosts file install:   ${HOSTS_FILE:-ERROR: No hosts file install location set}" 
+echo "  Environment install:  ${ENV_VARS:-ERROR: No environment variables file install location set}" 
+echo "  Hadoop namenode:      ${HADOOP_NAMENODE:-ERROR: No Hadoop namenode set}" 
+echo "  Hadoop namenode port: ${HADOOP_NAMENODE_PORT:-ERROR: No Hadoop namenode port set}" 
+echo " ------------ Support Software -----------"
+echo "  Maven home: ${M2_HOME:-ERROR: No maven home set}" 
+echo "  Java home:  ${JAVA_HOME:-ERROR: No maven home set}" 
+echo " ---------- Support Directories ----------"
+echo "  Temporary directory: ${TMP_DIR:-ERROR: Temp dir not set}"
+echo "  Running directory:   ${RUN_DIR:-ERROR: Running dir not set}"
+echo " ----------- Install Directory -----------"
+echo "  Install directory:   ${INSTALL_DIR:-ERROR: Install dir not set}"
+#Checking installed software
+if [ -z ${M2_HOME} ] || [ -z ${JAVA_HOME} ] || [ ! -f ${M2_HOME}/bin/mvn ] || \
+   [ ! -f ${JAVA_HOME}/bin/java ]
+then
+    echo "ERROR: Needed software not found."
+    exit 1
+fi
+
+#Checking versions
+if [ -z ${APACHE_MESOS_VERSION} ] || [ -z ${SCALA_VERSION} ] || [ -z ${KAFKA_VERSION} ] || \
+   [ -z ${SPARK_VERSION} ] || [ -z ${TACHYON_VERSION} ] || [ -z ${HADOOP_VERSION} ] || \
+   [ -z ${CLUSTER_TOOLS_VERSION} ] || [ -z ${INSTALL_DIR} ] || [ -z ${TMP_DIR} ] || \
+   [ -z ${HADOOP_NAMENODE} ] || [ -z ${HADOOP_NAMENODE_PORT} ] || [ -z ${ENV_VARS} ] || [ -z ${HOSTS_FILE} ]
+then
+    echo "ERROR: Needed variables not set. Did you source the environment files?"
+    exit 1
+fi
+#Check directories exit
+if [ ! -d ${INSTALL_DIR} ] || [ ! -d ${RUN_DIR} ] || [ ! -d ${TMP_DIR} ]
+then
+    echo "ERROR: Needed directories don't exist"
+    exit 1
+fi
+#Check space
+if [ -e ${INSTALL_DIR} ] && (( $(df -k ${INSTALL_DIR} | awk 'NR==3 {print $3}') < 5000000 ))
+then
+    echo "ERROR: Not enough space (5GB) to install in: ${INSTALL_DIR}."
+    exit 1 
+fi
+#Check space
+if (( $(df -k ${TMP_DIR} | awk 'NR==3 {print $3}') < 3000000 ))
+then
+    echo "ERROR: Not enough tmp space (3GB): ${TMP_DIR}."
+    exit 1
+fi
+
+while true; do
+    read -p "Continue installing(y/n)? " yn
+    case $yn in
+        [Yy]* ) break;;
+        [Nn]* ) exit;;
+        * ) echo "Please answer y or n.";;
+    esac
+done
+
+#Start of installation
+INSTALL_LOG=dependancy-installation-$(date +"%Y-%m-%dT%H:%M:%S").log
+echo "Installing dependancies at $(date +"%Y-%m-%dT%H:%M:%S")" | tee ${INSTALL_LOG} 
+
+#Downloads: wget and untar these 
+APACHE_MIRROR=http://archive.apache.org/dist/
+_KAFKA_VR=$(echo ${KAFKA_VERSION} | sed 's/^[^-]*-//')
+DOWNLOADS[0]=http://www.scala-lang.org/files/archive/scala-${SCALA_VERSION}.tgz
+DOWNLOADS[1]=${APACHE_MIRROR}/hadoop/common/hadoop-${HADOOP_VERSION}/hadoop-${HADOOP_VERSION}.tar.gz
+DOWNLOADS[2]=${APACHE_MIRROR}/mesos/${APACHE_MESOS_VERSION}/mesos-${APACHE_MESOS_VERSION}.tar.gz
+DOWNLOADS[3]=${APACHE_MIRROR}/spark/spark-${SPARK_VERSION}/spark-${SPARK_VERSION}-bin-hadoop2.4.tgz
+DOWNLOADS[4]=${APACHE_MIRROR}/kafka/${_KAFKA_VR}/kafka_${KAFKA_VERSION}.tgz
+DOWNLOADS[5]=https://github.com/amplab/tachyon/releases/download/v${TACHYON_VERSION}/tachyon-${TACHYON_VERSION}-bin.tar.gz
+
+mkdir -p ${TMP_DIR}/download
+mkdir -p ${INSTALL_DIR}
+#Grab all the downloads
+for url in "${DOWNLOADS[@]}"
+do
+    tarball=$(basename ${url})
+    #Get directory name without .tar.gz and .tgz 
+    dir=${tarball%%.tar.gz}
+    dir=${dir%%.tgz}
+    #Remove -bin for Tachyeon
+    dir=${dir%%-bin}
+    echo "Attempting to install: ${dir}" | tee -a ${INSTALL_LOG} 
+    #If something
+    if [ -e ${INSTALL_DIR}/${dir} ]
+    then
+        echo "${dir} installation detected."
+    else
+        rm -f ${TMP_DIR}/download/${tarball}
+        #wget or fail and continue
+        wget -nc -P ${TMP_DIR}/download ${url} &>> ${INSTALL_LOG} \
+        ||{ \
+            echo "WARNING: Failed to wget: ${url} Install manually." | tee -a ${INSTALL_LOG};\
+            continue;\
+          }
+        #untar or fail and continue
+        tar -xzf ${TMP_DIR}/download/${tarball} -C ${TMP_DIR}/download \
+        ||{ \
+            echo "WARNING: Failed to untar: ${tarball} Install manually." | tee -a ${INSTALL_LOG};\
+            continue;\
+          }
+        #Move to installation directory or fail and continue
+        mv ${TMP_DIR}/download/${dir} ${INSTALL_DIR} \
+        ||{ \
+            echo "WARNING: Failed to move: ${dir} to ${INSTALL_DIR} Install manually." | tee -a ${INSTALL_LOG};\
+            continue;\
+          }
+        #Move to installation directory or fail and continue
+        mv ${TMP_DIR}/download/${tarball} ${INSTALL_DIR}/${dir} \
+        ||{ \
+            echo "WARNING: Failed to move: ${tarball} to ${INSTALL_DIR} Install manually." | tee -a ${INSTALL_LOG};\
+            continue;\
+          }
+    fi
+done
+#Install scripts
+if [ -e ${INSTALL_DIR}/cluster-tools/scripts ]
+then
+    echo "Cluster tools already installed"
+else
+    echo "Exporting OODT-cluster tools" | tee -a ${INSTALL_LOG}
+    svn export https://svn.apache.org/repos/asf/oodt/${CLUSTER_TOOLS_VERSION}/cluster-tools/ ${INSTALL_DIR}/cluster-tools/ \
+    ||{ \
+         echo "WARNING: Failed to export cluster-tools: ${CLUSTER_TOOLS_VERSION} Install manually." | tee -a ${INSTALL_LOG};\
+      }
+    cp ${ENVS} ${ENV_VARS} 
+    cp ${HOSTS} ${HOSTS_FILE}
+fi
+echo "Building messos. This may take awhile" | tee -a ${INSTALL_LOG}
+#Mesos post processing
+if [ -e ${INSTALL_DIR}/mesos-${APACHE_MESOS_VERSION}/build ]
+then
+    echo "Mesos already built at: ${INSTALL_DIR}/mesos-${APACHE_MESOS_VERSION}/build"
+else
+    _MESOS_BUILD=${INSTALL_DIR}/mesos-${APACHE_MESOS_VERSION}/build
+    mkdir ${_MESOS_BUILD}
+    cd ${_MESOS_BUILD}
+    ../configure &>> ${INSTALL_LOG}
+    make &>> ${INSTALL_LOG} 
+fi
+
+#Hadoop namenode and configuration
+echo "Replacing host and port information in Hadoop Information" | tee -a ${INSTALL_LOG}
+sed -i -e "s/[INSTALL_DIR]/${INSTALL_DIR}/g" ${INSTALL_DIR}/cluster-tools/setup/hdfs-config/*.xml
+sed -i -e "s/[HDFS_HOST]/${HADOOP_NAMENODE}/g" ${INSTALL_DIR}/cluster-tools/setup/hdfs-config/*.xml
+sed -i -e "s/[HDFS_PORT]/${HADOOP_NAMENODE_PORT}/g" ${INSTALL_DIR}/cluster-tools/setup/hdfs-config/*.xml
+tail -n +2 ${HOSTS} > ${INSTALL_DIR}/cluster-tools/setup/hdfs-config/slaves
+echo "Moving ${INSTALL_DIR}/cluster-tools/setup/hdfs-config/ to ${HADOOP_HOME}/etc/hadoop/" | tee -a ${INSTALL_LOG}
+mv --backup=numbered --suffix=.bak ${INSTALL_DIR}/cluster-tools/setup/hdfs-config/* ${HADOOP_HOME}/etc/hadoop
+echo "Formating HDFS namenode" | tee -a ${INSTALL_LOG}
+${HADOOP_HOME}/bin/hdfs namenode -format
+
+echo "All done at $(date +"%Y-%m-%dT%H:%M:%S")" | tee -a ${INSTALL_LOG}
diff --git a/0.8.1-rc1/commons/pom.xml b/0.8.1-rc1/commons/pom.xml
new file mode 100644
index 0000000..820c7be
--- /dev/null
+++ b/0.8.1-rc1/commons/pom.xml
@@ -0,0 +1,165 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>oodt-commons</artifactId>
+  <name>Common Utilities</name>
+  <packaging>jar</packaging>
+  <description>Apache OODT Common Utilities Project</description>
+  <scm>
+   	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/commons</connection>
+   	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/commons</developerConnection>
+   	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/commons</url>
+  </scm>
+  <build>
+    <resources>
+        <resource>
+            <targetPath>org/apache/oodt/commons</targetPath>
+            <directory>${basedir}/src/main/resources/dtd</directory>
+            <includes>
+                <include>Configuration.dtd</include>
+            </includes>
+        </resource>
+        <resource>
+            <targetPath>org/apache/oodt/commons/util</targetPath>
+            <directory>${basedir}/src/main/resources/conf</directory>
+            <includes>
+                <include>entities.xml</include>
+            </includes>
+        </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>2.4</version>
+        <configuration>
+          <forkMode>pertest</forkMode>
+          <useSystemClassLoader>false</useSystemClassLoader>
+          <systemProperties>
+             <property>
+               <name>java.util.logging.config.file</name>
+               <value>${basedir}/src/test/resources/test.logging.properties</value>
+              </property>
+           </systemProperties>
+           <forkedProcessTimeoutInSeconds>0</forkedProcessTimeoutInSeconds>
+           <redirectTestOutputToFile>true</redirectTestOutputToFile>
+            <includes>
+              <include>**/*Test*.java</include>
+            </includes>
+          <redirectTestOutputToFile>true</redirectTestOutputToFile>
+        </configuration>
+      </plugin>
+    </plugins> 
+  </build>
+  <profiles>
+    <profile>
+      <id>audit</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>rat-maven-plugin</artifactId>
+            <configuration>
+              <excludes>
+                <exclude>**/test/resources/*</exclude>
+                <exclude>**/package.html</exclude>
+              </excludes>
+              <numUnapprovedLicenses>1</numUnapprovedLicenses>
+            </configuration>
+            <executions>
+              <execution>
+                <phase>verify</phase>
+                <goals>
+                  <goal>check</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+  <dependencies>
+    <dependency>
+      <groupId>commons-dbcp</groupId>
+      <artifactId>commons-dbcp</artifactId>
+      <version>1.2.1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+      <version>2.1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-pool</groupId>
+      <artifactId>commons-pool</artifactId>
+      <version>1.2</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <version>2.3</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.0.3</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-core</artifactId>
+      <version>2.5.4</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-hibernate3</artifactId>
+      <version>2.0.8</version>
+      <exclusions>
+        <exclusion>
+          <groupId>javax.transaction</groupId>
+          <artifactId>jta</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+        <groupId>xmlrpc</groupId>
+        <artifactId>xmlrpc</artifactId>
+        <version>2.0.1</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+    </dependency>
+    <dependency>
+        <groupId>xerces</groupId>
+        <artifactId>xercesImpl</artifactId>
+        <version>2.9.1</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/Configuration.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/Configuration.java
new file mode 100644
index 0000000..47da91e
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/Configuration.java
@@ -0,0 +1,735 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons;
+
+import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.*;
+import org.apache.oodt.commons.util.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.naming.NoInitialContextException;
+import java.rmi.registry.Registry;
+import java.util.StringTokenizer;
+
+/** EDA Configuration.
+ *
+ * An object of this class represents the configuration information for the EDA software.
+ *
+ * @author Kelly
+ */
+public class Configuration {
+	/** The singleton configuration. */
+	static Configuration configuration = null;
+
+	/** Name of property that specifies the direcotries that contains XML entities. */
+	public static final String ENTITY_DIRS_PROP = "entity.dirs";
+
+	/** Name of the default config file. */
+	public static final String DEFAULT_CONFIG_FILE = ".edarc.xml";
+
+	/** Alternate config file. */
+	public static final String ALT_CONFIG_FILE = ".oodtrc.xml";
+
+	/** Library-location config file. */
+	public static final File LIB_CONFIG_FILE = new File(System.getProperty("java.home", "/") + File.separator + "lib"
+		+ File.separator + "edarc.xml");
+
+	/** Non-JRE library location of config file. */
+	public static final File ALT_LIB_CONFIG_FILE = new File(System.getProperty("java.home", "/") + File.separator + ".."
+		+ File.separator + "lib" + File.separator + "edarc.xml");
+
+	 /** Get the singleton configuration.
+	  *
+	  * This method returns the singleton configuration object, or creates it if it
+	  * doesn't yet exist.  To create it, it reads the configuration file specified by
+	  * the system property <code>org.apache.oodt.commons.Configuration.url</code> or the file in the
+	  * user's home directory called .edarc.xml if the system property isn't
+	  * specified.  It parses the file and returns a <code>Configuration</code> object
+	  * initialized with the data specified therein.
+	  *
+	  * @throws IOException If reading the configuration file fails.
+	  * @throws SAXException If parsing the configuration file fails.
+	  * @throws MalformedURLException If the URL specification is invalid.
+	  * @return An initialized configuration object.
+	  */
+	 public static Configuration getConfiguration() throws IOException, SAXException, MalformedURLException {
+		 // Got one?  Use it.
+		 if (configuration != null) return configuration;
+
+		 URL url;
+
+		 // First preference: URL via the org.apache.oodt.commons.Configuration.url prop.
+		 String urlString = System.getProperty("org.apache.oodt.commons.Configuration.url");
+		 if (urlString != null) {
+			 url = new URL(urlString);
+		 } else {
+			 File file = null;
+
+			 // Second preference: file via the org.apache.oodt.commons.Configuration.file prop.
+			 String filename = System.getProperty("org.apache.oodt.commons.Configuration.file");
+			 if (filename != null) {
+				 file = new File(filename);
+				 if (!file.exists()) throw new IOException("File " + file + " not found");
+			 } else {
+				 List candidates = new ArrayList();
+
+				 // Third preference: ~/.edarc.xml
+				 File homedir = new File(System.getProperty("user.home", "/"));
+				 File homedirfile = new File(homedir, DEFAULT_CONFIG_FILE);
+				 candidates.add(homedirfile);
+
+				 // Fourth preference: ~/.oodtrc.xml
+				 File alt = new File(homedir, ALT_CONFIG_FILE);
+				 candidates.add(alt);
+
+				 // Fifth and sixth preferences: $EDA_HOME/conf/edarc.xml and $EDA_HOME/etc/edarc.xml
+				 String edaHome = System.getProperty("eda.home");
+				 if (edaHome != null) {
+					 File edaHomeDir = new File(edaHome);
+					 candidates.add(new File(new File(edaHomeDir, "conf"), "edarc.xml"));
+					 candidates.add(new File(new File(edaHomeDir, "etc"), "edarc.xml"));
+				 }
+
+				 // Seventh preference: JAVA_HOME/lib/edarc.xml
+				 candidates.add(LIB_CONFIG_FILE);
+
+				 // Final preference: JAVA_HOME/../lib/edarc.xml (to get out of JRE)
+				 candidates.add(ALT_LIB_CONFIG_FILE);
+
+				 // Now find one.
+				 boolean found = false;
+				 for (Iterator i = candidates.iterator(); i.hasNext();) {
+					 file = (File) i.next();
+					 if (file.exists()) {
+						 found = true;
+						 break;
+					 }
+				 }
+				 if (found && file == alt)
+					 System.err.println("WARNING: Using older config file " + alt + "; rename to "
+						 + homedirfile + " as soon as possible.");
+				 if (!found) {
+					 return getEmptyConfiguration();
+				 }
+			 }
+			 url = file.toURL();
+		 }
+
+		 return getConfiguration(url);
+
+	 }
+
+	/** Get the singleton configuration.
+	 *
+	 * This method returns the singleton configuration object from a 
+	 * specified file url.  It parses the file and returns a <code>Configuration</code> object
+	 * initialized with the data specified therein.  Added by Chris Mattmann 12/05/03.
+	 *
+	 * @throws IOException If an I/O error occurs.
+	 * @return An initialized configuration object.
+	 */
+	public static Configuration getConfiguration(URL configFileUrl) throws SAXException, IOException {
+		synchronized (Configuration.class) {
+			if (configuration == null)
+				configuration = new Configuration(configFileUrl);
+		}
+		return configuration;
+	}
+
+	private static Configuration getEmptyConfiguration() {
+		synchronized (Configuration.class) {
+			if (configuration == null)
+				configuration = new Configuration();
+		}
+		return configuration;
+	}
+
+
+	/** Get the singleton configuration without exception.
+	 *
+	 * This method is identical to {@link #getConfiguration} but traps all checked
+	 * exceptions.  If the configuration can't be read, it returns null.
+	 *
+	 * @return An initialized configuration object, or null if an error occurred.
+	 */
+	public static Configuration getConfigurationWithoutException() {
+		// Got one?  Use it.  Do this out of a try block for performance.
+		if (configuration != null) return configuration;
+
+		// Try to get it.
+		try {
+			return getConfiguration();
+		} catch (RuntimeException ex) {
+			throw ex;
+		} catch (Exception ex) {
+			System.err.println("Exception " + ex.getClass().getName() + " while getting configuration: "
+				+ ex.getMessage());
+			ex.printStackTrace();
+			return null;
+		}
+	}
+
+	Configuration() {
+		serverMgrPort = 7577;
+		nameServerStateFrequency = 6000000;
+		nameServerObjectKey = "StandardNS%20POA";
+		nameServerPort = "10000";
+		nameServerHost = "localhost";
+		nameServerVersion = "1.0";
+		nameServerUsingRIRProtocol = false;
+		webServerDocumentDirectory = new File(System.getProperty("user.home", "/") + "tomcat/webapps/ROOT");
+		webPort = "8080";
+		webHost = "localhost";
+		System.setProperty(WEB_PROTOCOL_PROPERTY, "http");
+		initializeContext();
+	}
+
+	/** Construct a configuration.
+	 *
+	 * @param url The location of the configuration.
+	 * @throws IOException If reading the configuration file fails.
+	 * @throws SAXParseException If parsing the configuration file fails.
+	 */
+	Configuration(URL url) throws IOException, SAXException {
+		this(new InputSource(url.toString()));
+	}
+
+	Configuration(InputSource inputSource) throws IOException, SAXException {
+		String systemID = inputSource.getSystemId();
+		if (systemID == null) inputSource.setSystemId("file:/unknown");
+
+		// Get the document
+		DOMParser parser = XML.createDOMParser();
+		parser.setEntityResolver(new ConfigurationEntityResolver());
+		parser.setErrorHandler(new ErrorHandler() {
+			public void error(SAXParseException ex) throws SAXException {
+				throw ex;
+			}
+			public void warning(SAXParseException ex) {
+				System.err.println("Warning: " + ex.getMessage());
+			}
+			public void fatalError(SAXParseException ex) throws SAXException {
+				System.err.println("Fatal parse error: " + ex.getMessage());
+				throw ex;
+			}
+		});
+		parser.parse(inputSource);
+		Document document = parser.getDocument();
+		XML.removeComments(document);
+		document.normalize();
+		
+		// See if this really is a <configuration> document.
+		if (!document.getDocumentElement().getNodeName().equals("configuration"))
+			throw new SAXException("Configuration " + inputSource.getSystemId() + " is not a <configuration> document");
+
+		NodeList list = document.getDocumentElement().getChildNodes();
+		for (int eachChild = 0; eachChild < list.getLength(); ++eachChild) {
+			Node childNode = list.item(eachChild);
+			if (childNode.getNodeName().equals("webServer")) {
+				NodeList children = childNode.getChildNodes();
+				for (int i = 0; i < children.getLength(); ++i) {
+					Node node = children.item(i);
+					if ("host".equals(node.getNodeName()))
+						webHost = XML.unwrappedText(node);
+					else if ("port".equals(node.getNodeName()))
+						webPort = XML.unwrappedText(node);
+					else if ("dir".equals(node.getNodeName()))
+						webServerDocumentDirectory = new File(XML.unwrappedText(node));
+				}					
+				properties.setProperty("org.apache.oodt.commons.Configuration.webServer.baseURL", getWebServerBaseURL());
+				if (webServerDocumentDirectory == null)
+					webServerDocumentDirectory = new File(System.getProperty("user.home", "/")
+						+ "/dev/htdocs");
+			} else if (childNode.getNodeName().equals("nameServer")) {
+				Element nameServerNode = (Element) childNode;
+				String nameServerStateFrequencyString = nameServerNode.getAttribute("stateFrequency");
+				if (nameServerStateFrequencyString == null || nameServerStateFrequencyString.length() == 0)
+					nameServerStateFrequency = 0;
+				else try {
+					nameServerStateFrequency = Integer.parseInt(nameServerStateFrequencyString);
+				} catch (NumberFormatException ex) {
+					throw new SAXException("Illegal nun-numeric value \"" + nameServerStateFrequencyString
+						+ "\" for stateFrequency attribute");
+				}
+				if (childNode.getFirstChild().getNodeName().equals("rir")) {
+					nameServerUsingRIRProtocol = true;
+					NodeList children = childNode.getFirstChild().getChildNodes();
+					nameServerObjectKey = children.getLength() == 1? XML.unwrappedText(children.item(0)):null;
+				} else {
+					nameServerUsingRIRProtocol = false;
+					nameServerVersion = null;
+					nameServerPort = null;
+					// Must be same as CORBAMgr.NS_OBJECT_KEY:
+					nameServerObjectKey = "StandardNS/NameServer%2DPOA/_root";
+					NodeList children = childNode.getFirstChild().getChildNodes();
+					for (int i = 0; i < children.getLength(); ++i) {
+						Node node = children.item(i);
+						if (node.getNodeName().equals("version"))
+							nameServerVersion = XML.unwrappedText(node);
+						else if (node.getNodeName().equals("host"))
+							nameServerHost = XML.unwrappedText(node);
+						else if (node.getNodeName().equals("port"))
+							nameServerPort = XML.unwrappedText(node);
+						else if (node.getNodeName().equals("objectKey"))
+							nameServerObjectKey = XML.unwrappedText(node);
+					}
+				}
+			} else if (childNode.getNodeName().equals("xml")) {
+				NodeList children = childNode.getChildNodes();
+				for (int i = 0; i < children.getLength(); ++i) {
+					Node xmlNode = children.item(i);
+					if ("entityRef".equals(xmlNode.getNodeName())) {
+						NodeList dirNodes = xmlNode.getChildNodes();
+						StringBuffer refDirs = new StringBuffer(System.getProperty(ENTITY_DIRS_PROP, ""));
+						for (int j = 0; j < dirNodes.getLength(); ++j)
+							refDirs.append(',').append(XML.unwrappedText(dirNodes.item(j)));
+						if (refDirs.length() > 0)
+							System.setProperty(ENTITY_DIRS_PROP, refDirs.charAt(0) == ','?
+								refDirs.substring(1) : refDirs.toString());
+					}
+				}
+			} else if ("serverMgr".equals(childNode.getNodeName())) {
+				serverMgrPort = Integer.parseInt(XML.unwrappedText(childNode.getFirstChild()));
+			} else if (childNode.getNodeName().equals("properties")) {
+				loadProperties(childNode, properties);
+			} else if (childNode.getNodeName().equals("programs")) {
+				NodeList children = childNode.getChildNodes();
+				for (int i = 0; i < children.getLength(); ++i) {
+					// They're all of type execServer---for now.
+					ExecServerConfig esc = new ExecServerConfig(children.item(i));
+					esc.getProperties().setProperty("org.apache.oodt.commons.Configuration.url", inputSource.getSystemId());
+					execServers.add(esc);
+				}
+			}
+		}
+
+		initializeContext();
+	}
+
+	private void initializeContext() {
+		contextEnvironment.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.oodt.commons.object.jndi.ObjectCtxFactory");
+		String registryList = System.getProperty("org.apache.oodt.commons.rmiregistries", System.getProperty("rmiregistries"));
+		if (registryList == null) {
+			String host = System.getProperty("rmiregistry.host", "localhost");
+			int port = Integer.getInteger("rmiregistry.port", Registry.REGISTRY_PORT).intValue();
+			registryList = "rmi://" + host + ":" + port;
+		}
+		contextEnvironment.put("rmiregistries", registryList);
+	}
+
+	/** Serialize this configuration into a serialized XML document.
+	 *
+	 * @return Serialized XML version of this configuration.
+	 * @throws DOMException If an error occurs constructing the XML structure.
+	 */
+	public String toXML() throws DOMException {
+		Document doc = createDocument("configuration");
+		doc.replaceChild(toXML(doc), doc.getDocumentElement());
+		return XML.serialize(doc);
+	}
+
+	/** 
+	 *
+	 * @param document The document to which the XML structure will belong.
+	 * @return The root node representing this configuration.
+	 * @throws DOMException If an error occurs constructing the XML structure.
+	 */
+	public Node toXML(Document document) throws DOMException {
+		// <configuration>
+		Element configurationNode = document.createElement("configuration");
+
+		// <webServer>
+		Element webServerNode = document.createElement("webServer");
+		configurationNode.appendChild(webServerNode);
+
+		// <webServer>
+		//   <host>...</host><port>...</port><dir>...</dir>
+		XML.add(webServerNode, "host", webHost);
+		XML.add(webServerNode, "port", webPort);
+		XML.add(webServerNode, "dir", webServerDocumentDirectory.toString());
+
+		// <nameServer>
+		Element nameServerNode = document.createElement("nameServer");
+		nameServerNode.setAttribute("stateFrequency", String.valueOf(nameServerStateFrequency));
+		configurationNode.appendChild(nameServerNode);
+
+		// <nameServer>
+		//   <rir> or <iiop>
+		if (nameServerUsingRIRProtocol) {
+			Element rirNode = document.createElement("rir");
+			nameServerNode.appendChild(rirNode);
+			if (nameServerObjectKey != null)
+				XML.add(rirNode, "objectKey", nameServerObjectKey);
+		} else {
+			Element iiopNode = document.createElement("iiop");
+			nameServerNode.appendChild(iiopNode);
+			if (nameServerVersion != null)
+				XML.add(iiopNode, "version", nameServerVersion);
+			XML.add(iiopNode, "host", nameServerHost);
+			if (nameServerPort != null)
+				XML.add(iiopNode, "port", nameServerPort);
+			if (nameServerObjectKey != null)
+				XML.add(iiopNode, "objectKey", nameServerObjectKey);
+		}
+
+		// <xml><entityRef><dir>...
+		if (!getEntityRefDirs().isEmpty()) {
+			Element xmlNode = document.createElement("xml");
+			configurationNode.appendChild(xmlNode);
+			Element entityRefNode = document.createElement("entityRef");
+			xmlNode.appendChild(entityRefNode);
+			XML.add(entityRefNode, "dir", getEntityRefDirs());
+		}
+
+		// <serverMgr><port>...
+		if (getServerMgrPort() != 0) {
+			Element serverMgrNode = document.createElement("serverMgr");
+			configurationNode.appendChild(serverMgrNode);
+			XML.add(serverMgrNode, "port", String.valueOf(getServerMgrPort()));
+		}
+
+		// Global <properties>...</properties>
+		if (properties.size() > 0)
+			dumpProperties(properties, configurationNode);
+
+		// <programs>...
+		if (execServers.size() > 0) {
+			Element programsNode = document.createElement("programs");
+			configurationNode.appendChild(programsNode);
+
+			for (Iterator i = execServers.iterator(); i.hasNext();) {
+				ExecServerConfig esc = (ExecServerConfig) i.next();
+				Element execServerNode = document.createElement("execServer");
+				programsNode.appendChild(execServerNode);
+				XML.add(execServerNode, "class", esc.getClassName());
+				XML.add(execServerNode, "objectKey", esc.getObjectKey());
+				XML.add(execServerNode, "host", esc.getPreferredHost().toString());
+				if (esc.getProperties().size() > 0)
+					dumpProperties(esc.getProperties(), execServerNode);
+			}
+		}
+
+		return configurationNode;
+	}
+
+	/** Merge the properties in the configuration into the given properties.
+	 *
+	 * Properties that already exist in the <var>targetProps</var> won't be
+	 * overwritten.
+	 *
+	 * @param targetProps The target properties.
+	 */
+	public void mergeProperties(Properties targetProps) {
+		for (Iterator i = properties.entrySet().iterator(); i.hasNext();) {
+			Map.Entry entry = (Map.Entry) i.next();
+			if (!targetProps.containsKey(entry.getKey()))
+				targetProps.put(entry.getKey(), entry.getValue());
+		}
+	}
+
+	/** Get the exec-server configurations.
+	 *
+	 * @return A collection of exec server configurations, each of class {@link ExecServerConfig}.
+	 */
+	public Collection getExecServerConfigs() {
+		return execServers;
+	}
+
+        /** Get the exec-server configurations.
+         *
+         * @param clazz The class of exec servers that will be returned.
+         * @return A collection of exec server configurations, each of class {@link ExecServerConfig}.
+         */
+        public Collection getExecServerConfigs(Class clazz) {
+                String className = clazz.getName();
+                Collection execServerConfigs = new ArrayList();
+                for (Iterator i = execServers.iterator(); i.hasNext();) {
+                        ExecServerConfig exec = (ExecServerConfig) i.next();
+                        if (className.equals(exec.getClassName()))
+                                execServerConfigs.add(exec);
+                }
+                return execServerConfigs;
+        }
+
+        /** Get an exec-server configuration.
+         *
+         * @param objectKey The object key of the Exec Server to retrieve.
+         * @return An {@link ExecServerConfig} or null if object key not found.
+         */
+        public ExecServerConfig getExecServerConfig(String objectKey) {
+                ExecServerConfig execServerConfig = null;
+                for (Iterator i = execServers.iterator(); i.hasNext() && execServerConfig == null;) {
+                        ExecServerConfig exec = (ExecServerConfig) i.next();
+                        if (objectKey.equals(exec.getObjectKey()))
+                                execServerConfig = exec;
+                }
+                return execServerConfig;
+        }
+
+	/** Get the web server base URL.
+	 *
+	 * @return The base web server URL.
+	 */
+	public String getWebServerBaseURL() {
+		String proto = System.getProperty(WEB_PROTOCOL_PROPERTY);
+		if (proto == null) {
+			if ("443".equals(webPort)) proto = "https";
+			else proto = "http";
+		}
+		return proto + "://" + webHost + ":" + webPort;
+	}
+
+	/** Get the web server document directory.
+	 *
+	 * @return The document directory.
+	 */
+	public File getWebServerDocumentDirectory() {
+		return webServerDocumentDirectory;
+	}
+
+	/** Get the name server URL.
+	 *
+	 * @return The name server URL.
+	 */
+	public String getNameServerURL() {
+		return getWebServerBaseURL() + "/ns.ior";
+	}
+
+	/** Get the name server port, if any.
+	 *
+	 * @return The port.
+	 */
+	public String getNameServerPort() {
+		return nameServerPort;
+	}
+
+	/** Get the frequency with which the name server saves its state.
+	 *
+	 * @return The state-save frequency in milliseconds; <= 0 means never save state.
+	 */
+	public int getNameServerStateFrequency() {
+		return nameServerStateFrequency;
+	}
+
+	/** Get the object context.
+	 *
+	 * @return The object context based on this configuration.
+	 * @throws NamingException If the context can't be created.
+	 */
+	public Context getObjectContext() throws NamingException {
+		Context c = null;
+		final String className = (String) contextEnvironment.get(javax.naming.Context.INITIAL_CONTEXT_FACTORY);
+		if (className == null)
+			c = new InitialContext(contextEnvironment);
+		else try {
+			// Work around iPlanet bug.  JNDI uses the thread's context class
+			// loader to load the initial context factory class.  For some
+			// reason, that loader fails to find things in iPlanet's
+			// classpath, such as the EDA initial context factory.  Here, we
+			// cut a new thread and explicitly set its context class loader to
+			// the application class loader.  When JNDI looks up the initial
+			// context factory, the thread's context class loader is the app
+			// class loader, which succeeds.
+			Class clazz = Class.forName(className);
+			final ClassLoader loader = clazz.getClassLoader();
+			InitialContextThread thread = new InitialContextThread(loader);
+			thread.start();
+			try {
+				thread.join();
+			} catch (InterruptedException ex) {
+				throw new NoInitialContextException("Initial context thread interrupted: " + ex.getMessage());
+			}
+			c = thread.getContext();
+			if (c == null)
+				throw thread.getException();
+		} catch (ClassNotFoundException ex) {
+			throw new NoInitialContextException("Class " + className + " not found");
+		}
+		return c;
+	}
+
+	/** Get the entity reference directories.
+	 *
+	 * @return A list of {@link java.lang.String}s naming directories for entity references.
+	 */
+	public List getEntityRefDirs() {
+		List dirs = new ArrayList();
+		for (StringTokenizer t = new StringTokenizer(System.getProperty(ENTITY_DIRS_PROP, ""), ",;|"); t.hasMoreTokens();)
+			dirs.add(t.nextToken());
+		return dirs;
+	}
+
+	/** Get the port number on which the server manager is listening.
+	 *
+	 * @return The port number, or 0 if there is no server manager.
+	 */
+	public int getServerMgrPort() {
+		return serverMgrPort;
+	}
+
+	/** Load the properties described in an XML properties element into the
+	 * given properties object.
+	 *
+	 * @param propertiesNode The XML node which is a <code>&lt;properties&gt;</code> element.
+	 * @param props The properties object to load with properties from <var>propertiesNode</var>.
+	 */
+	static void loadProperties(Node propertiesNode, Properties props) {
+		NodeList children = propertiesNode.getChildNodes();
+		for (int i = 0; i < children.getLength(); i += 2) {
+			String key = XML.unwrappedText(children.item(i));
+			String value = XML.unwrappedText(children.item(i+1));
+			props.setProperty(key, value);
+		}
+	}
+
+	/** Dump the properties from the given properties object in XML form, appending
+	 * them to the given node under a &lt;properties&gt; element.
+	 *
+	 * @param props The properties to dump in XML form.
+	 * @param node The node to which to append the &lt;properties&gt; element.
+	 * @throws DOMException If a DOM error occurs.
+	 */
+	static void dumpProperties(Properties props, Node node) {
+		Element propertiesElement = node.getOwnerDocument().createElement("properties");
+		node.appendChild(propertiesElement);
+		for (Iterator i = props.entrySet().iterator(); i.hasNext();) {
+			Map.Entry entry = (Map.Entry) i.next();
+			XML.add(propertiesElement, "key", (String) entry.getKey());
+			XML.add(propertiesElement, "value", (String) entry.getValue());
+		}
+	}
+
+	/** Create a new XML document with the configuration DTD.
+	 *
+	 * @param name Name to give to the document element.
+	 * @returns An XML DOM document with the doctype and the root document empty element in place.
+	 * @throws DOMException If we can't create the document.
+	 */
+	static Document createDocument(String documentElementName) throws DOMException {
+		DocumentType docType = XML.getDOMImplementation().createDocumentType(documentElementName, DTD_FPI, DTD_URL);
+		Document doc = XML.getDOMImplementation().createDocument(/*namespaceURI*/null, documentElementName, docType);
+		return doc;
+	}
+
+	/** The formal public identifier (FPI) of the configuration document type definition (DTD). */
+	public static final String DTD_FPI = "-//JPL//DTD EDA Configuration 1.0//EN";
+	
+	/** The old formal public identifier (FPI) of the configuration document type definition (DTD). */
+	public static final String DTD_OLD_FPI = "-//JPL//DTD OODT Configuration 1.0//EN";
+
+	/** The system identifier of the configuration document type definition (DTD). */
+	public static final String DTD_URL = "http://oodt.jpl.nasa.gov/edm-commons/Configuration.dtd";
+
+	/** Name of the system property that names the web protocol to use. */
+	public static final String WEB_PROTOCOL_PROPERTY = "org.apache.oodt.commons.Configuration.webProtocol";
+
+	/** Global properties. */
+	private Properties properties = new Properties();
+
+	/** Object context environment. */
+	Hashtable contextEnvironment = new Hashtable();
+
+	/** Exec-servers. */
+	private List execServers = new ArrayList();
+
+	/** Web server host. */
+	private String webHost;
+
+	/** Web server port. */
+	private String webPort;
+
+	/** Web server doc dir. */
+	private File webServerDocumentDirectory;
+
+	/** Name server using rir protocol.
+	 *
+	 * If false, then it's using iiop.
+	 */
+	private boolean nameServerUsingRIRProtocol;
+
+	/** Name server version. */
+	private String nameServerVersion;
+
+	/** Name server host. */
+	private String nameServerHost;
+
+	/** Name server port. */
+	private String nameServerPort;
+
+	/** Name server object key. */
+	private String nameServerObjectKey;
+
+	/** How often the name server saves its state. */
+	private int nameServerStateFrequency;
+
+	/** On what port the server manager will listen. */
+	private int serverMgrPort;
+
+	/** Thread to set a context class loader and get a JNDI initial context. */
+	private class InitialContextThread extends Thread {
+		/** Ctor
+		 *
+		 * @param loader What class loader to use as thread's context class loader.
+		 */
+		public InitialContextThread(ClassLoader loader) {
+			setContextClassLoader(loader);
+		}
+
+		public void run() {
+			try {
+				context = new InitialContext(contextEnvironment);
+			} catch (NamingException ex) {
+				exception = ex;
+			} catch (Throwable t) {
+				System.err.println("Unexpected throwable " + t.getClass().getName() + " getting initial context: "
+					+ t.getMessage());
+				t.printStackTrace();
+			}
+		}
+
+		/** Get the context.
+		 *
+		 * <strong>Warning!</strong> Do not call this method until the thread terminates.
+		 *
+		 * @return The context, or null if the context could not be retrieved.
+		 */
+		public Context getContext() {
+			return context;
+		}
+
+		/** Get any exception.
+		 *
+		 * @return Any exception that occurred while retrieving the context.
+		 */
+		public NamingException getException() {
+			return exception;
+		}
+
+		/** JNDI context. */
+		private Context context;
+
+		/** Any exception. */
+		private NamingException exception;
+	}
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/ConfigurationEntityResolver.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/ConfigurationEntityResolver.java
new file mode 100644
index 0000000..cc784dc
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/ConfigurationEntityResolver.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons;
+
+import java.io.IOException;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/** XML entity resolver for the configuration file.
+ *
+ * This resolver attempts to use a locally accessible configuration.dtd so that we can
+ * bootstrap enterprise applications without http access.  You see, The config file
+ * specifies the list of entity directories, but the config file itself is an XML document
+ * that refers to its doctype entity.  We therefore resolve the config DTD to a
+ * classpath-acessible copy.
+ *
+ * @author Kelly
+ */
+class ConfigurationEntityResolver implements EntityResolver {
+	public InputSource resolveEntity(String publicID, String systemID) throws SAXException, IOException {
+		if (Configuration.DTD_FPI.equals(publicID) || Configuration.DTD_OLD_FPI.equals(publicID))
+			return new InputSource(Configuration.class.getResourceAsStream("Configuration.dtd"));
+		return null;
+	}
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/ConfiguredTestCase.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/ConfiguredTestCase.java
new file mode 100644
index 0000000..3c7530a
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/ConfiguredTestCase.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons;

+

+import java.io.BufferedInputStream;

+import junit.framework.TestCase;

+import org.xml.sax.InputSource;

+import java.io.InputStream;

+import java.io.IOException;

+import java.io.StringReader;

+

+/**

+ * Base test case for tests that need the Configuration object.

+ *

+ * @author Kelly

+ */ 

+public abstract class ConfiguredTestCase extends TestCase {

+	/**

+	 * Creates a new {@link ConfiguredTestCase} instance.

+	 *

+	 * @param caseName Case name.

+	 */

+	protected ConfiguredTestCase(String caseName) {

+		super(caseName);

+	}

+	

+	/**

+	 * Set up a test Configuration object.

+	 *

+	 * @throws Exception if an error occurs.

+	 */

+	protected void setUp() throws Exception {

+		super.setUp();

+		if (Configuration.configuration == null) {

+			try {

+				StringReader reader = new StringReader(TSTDOC);

+				InputSource is = new InputSource(reader);

+				is.setEncoding("UTF-8");

+				is.setPublicId("-//JPL//XML EDM Test Configuration 0.0.0//EN");

+				is.setSystemId("internal:test-edarc.xml");

+				Configuration.configuration = new Configuration(is);

+				reader.close();

+			} catch (IOException ex) {

+				ex.printStackTrace();

+				throw new IllegalStateException("Unexpected IOException: " + ex.getMessage());

+			}

+		}

+	}

+

+	/** Test configuration, as a document. */

+	private static final String TSTDOC = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE configuration PUBLIC"

+		+ " \"-//JPL//DTD EDA Configuration 1.0//EN\" \"http://oodt.jpl.nasa.gov/edm-commons/Configuration.dtd\">\n"

+		+ "<configuration><webServer><host>www.jpl.nasa.gov</host><port>81</port><dir>/non/existent/htdocs</dir>"

+		+ "</webServer><nameServer><iiop><version>1</version><host>oodt.jpl.nasa.gov</host><port>82</port>"

+		+ "<objectKey>StandardNS/NameServer%2DPOA/_test</objectKey></iiop></nameServer><ldapServer>"

+		+ "<host>ldap.jpl.nasa.gov</host><port>83</port><managerDN>cn=GeorgeTestostoles,dc=test,dc=zone</managerDN>"

+		+ "<password>h1ghly;s3cr3t</password></ldapServer><xml><parser>crimson</parser><entityRef>"

+		+ "<dir>/non/existent/htdocs/xml</dir><dir>/non/existent/htdocs/dtd</dir></entityRef></xml><serverMgr>"

+		+ "<port>84</port></serverMgr><properties><key>global</key><value>1</value><key>override</key><value>2</value>"

+		+ "</properties><programs><execServer><class>TestServer</class><objectKey>urn:eda:rmi:TestObject</objectKey>"

+		+ "<host>oodt.jpl.nasa.gov</host><properties><key>local</key><value>3</value><key>override</key><value>4</value>"

+		+ "</properties></execServer><client><class>TestClient</class><properties><key>local</key><value>5</value>"

+		+ "<key>override</key><value>6</value></properties></client></programs></configuration>";

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/EDAException.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/EDAException.java
new file mode 100644
index 0000000..429fe89
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/EDAException.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons;
+
+public class EDAException extends Exception {
+	public EDAException(String msg) {
+		super(msg);
+	}
+
+	public EDAException(Throwable cause) {
+		super(cause);
+	}
+
+	public EDAException(String msg, Throwable cause) {
+		super(msg, cause);
+	}
+}
+
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/ExecServer.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/ExecServer.java
new file mode 100644
index 0000000..9e8293d
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/ExecServer.java
@@ -0,0 +1,474 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons;
+
+import java.io.*;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.net.*;
+import java.rmi.RMISecurityManager;
+import java.util.*;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import org.apache.oodt.commons.io.Log;
+import org.apache.oodt.commons.util.*;
+import org.apache.xmlrpc.XmlRpcClientLite;
+import org.apache.xmlrpc.XmlRpcServer;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+import java.rmi.Remote;
+import java.rmi.server.RemoteStub;
+import java.rmi.server.UnicastRemoteObject;
+import java.rmi.server.RemoteObject;
+import java.rmi.server.RemoteRef;
+import java.io.ObjectOutputStream;
+import java.io.ByteArrayOutputStream;
+import org.apache.oodt.commons.io.Base64EncodingOutputStream;
+
+/** Server execution program.
+ *
+ * This is an executable class that starts a JPL EDA server.
+ *
+ * @author Kelly
+ */
+public class ExecServer {
+	/** Start a server.
+	 *
+	 * The command-line should have two arguments:
+	 *
+	 * <ol>
+	 *   <li>The fully-qualified class name of the server to execute.</li>
+	 *   <li>The object name of the server to register with the naming service.</li>
+	 * </ol>
+	 *
+	 * @param argv The command-line arguments
+	 */
+	public static void main(String[] argv) {
+		if (argv.length < 2) {
+			System.err.println("Usage: class-name-of-server object-name");
+			System.exit(1);
+		}
+
+		String className = argv[0];
+		String name = argv[1];
+
+		// Enable support of our special URLs, like stdin:
+		System.setProperty("java.protocol.handler.pkgs", "org.apache.oodt.commons.net.protocol");
+
+		try {
+			// Get the configuration.
+			configuration = Configuration.getConfiguration();
+			configuration.mergeProperties(System.getProperties());
+
+			// Set up the logger.
+			LogInit.init(System.getProperties(), name);
+
+			// Run initializers
+			try {
+				runInitializers();
+			} catch (EDAException ex) {
+				ex.printStackTrace();
+				System.exit(1);
+			}
+
+			// Create it.
+			final ExecServer server = new ExecServer(name, className);
+
+			// Print it.
+			if (Boolean.getBoolean(PRINT_IOR_PROPERTY)) {
+				if (server.getServant() instanceof RemoteObject) {
+					RemoteObject remoteObject = (RemoteObject) server.getServant();
+					RemoteStub remoteStub = (RemoteStub) RemoteObject.toStub(remoteObject);
+					RemoteRef ref = remoteStub.getRef();
+					System.out.print("RMI:");
+					System.out.flush();
+					ObjectOutputStream objOut
+						= new ObjectOutputStream(new Base64EncodingOutputStream(System.out));
+					objOut.writeObject(ref);
+					objOut.flush();
+					System.out.println();
+				} else {
+					org.omg.PortableServer.Servant servant=(org.omg.PortableServer.Servant)server.getServant();
+					org.omg.CORBA.ORB orb = servant._orb();
+					System.out.println(orb.object_to_string(servant._this_object(orb)));
+				}
+				System.out.flush();
+			}
+
+			// Bind it.
+			if (!Boolean.getBoolean(DISABLE_BINDING)) {
+				binder = new Binder(name, server);
+				binder.start();
+			}
+
+			// Prepare for the inevitable
+			Runtime.getRuntime().addShutdownHook(new Thread() {
+				public void run() {
+					server.shutdown0();
+				}
+			});
+
+			// We're done here.
+			for (;;) try {
+				Thread.currentThread().join();
+			} catch (InterruptedException ignore) {}
+		} catch (IOException ex) {
+			System.err.println("I/O error during initialization: " + ex.getMessage());
+			ex.printStackTrace();
+		} catch (SAXParseException ex) {
+			System.err.println("Error in the configuration file at line " + ex.getLineNumber() + ", column "
+				+ ex.getColumnNumber() + ": " + ex.getMessage());
+		} catch (SAXException ex) {
+			System.err.println("Error " + ex.getClass().getName() + " while attempting to parse the configuration"
+				+ " file: " + ex.getMessage());
+		} catch (javax.naming.NamingException ex) {
+			System.err.println("Naming/directory error: " + ex.getClass().getName() + ": " + ex.getMessage());
+		} catch (java.lang.reflect.InvocationTargetException ex) {
+			Throwable target = ex.getTargetException();
+			System.err.println("Constructor for \"" + className + "\" threw " + target.getClass().getName() + ": "
+				+ ex.getMessage());
+			target.printStackTrace();
+		} catch (RuntimeException ex) {
+			throw ex;
+		} catch (Exception ex) {
+			System.err.println("Exception " + ex.getClass().getName() + " initializing server \"" + name
+				+ "\" with class \"" + className + "\": " + ex.getMessage());
+			ex.printStackTrace();
+		} 
+		System.exit(1);
+	}
+
+	protected ExecServer(String name) {
+		this.name = name;
+	}
+
+	/** Create a new executable server.
+	 *
+	 * @param name Name of the server
+	 * @param className Name of class that implements the server.
+	 * @throws ClassNotFoundException If the class for <var>className</var> can't be found.
+	 * @throws NoSuchMethodException If the constructor for <var>className</var> taking a single <code>ExecServer</code>
+	 *         can't be found.
+	 * @throws InstantiationException If the class for <var>className</var> is abstract or is an interface.
+	 * @throws IllegalAccessException If the class for <var>className</var> isn't public.
+	 * @throws InvocationTargetException If an exception occurs in the constructor for <var>className</var>.
+	 * @throws DOMException If the server's status document can't be created.
+	 * @throws UnknownHostException If the local host name can't be determined.
+	 */
+	public ExecServer(String name, String className) throws ClassNotFoundException, NoSuchMethodException,
+		InstantiationException, IllegalAccessException, InvocationTargetException, DOMException, UnknownHostException {
+		this.name = name;
+
+		// Find the class and the required constructor.
+		Class clazz = Class.forName(className);
+		Constructor ctor = clazz.getConstructor(new Class[]{ExecServer.class});
+
+		// Invoke the constructor to create the servant.
+		servant = ctor.newInstance(new Object[]{this});
+		Date startDate = new Date();
+
+		// Create the XML-RPC interface to this server.
+		xmlrpcServer = new XmlRpcServer();
+		xmlrpcServer.addHandler("server", this);
+
+		// Create the server status document.
+		DocumentType docType = XML.getDOMImplementation().createDocumentType("server", STATUS_FPI, STATUS_URL);
+		statusDocument = XML.getDOMImplementation().createDocument(/*namespaceURI*/null, "server", docType);
+		Element serverElement = statusDocument.getDocumentElement();
+		XML.add(serverElement, "name", name);
+		XML.add(serverElement, "class", className);
+		XML.add(serverElement, "state", "up");
+		Element startElement = statusDocument.createElement("start");
+		serverElement.appendChild(startElement);
+		Element userElement = statusDocument.createElement("user");
+		startElement.appendChild(userElement);
+		XML.add(userElement, "name", System.getProperty("user.name", "UNKNOWN"));
+		XML.add(userElement, "cwd", System.getProperty("user.dir", "UNKNOWN"));
+		XML.add(userElement, "home", System.getProperty("user.home", "UNKNOWN"));
+		Element dateElement = statusDocument.createElement("date");
+		startElement.appendChild(dateElement);
+		dateElement.setAttribute("ms", String.valueOf(startDate.getTime()));
+		dateElement.appendChild(statusDocument.createTextNode(startDate.toString()));
+		XML.add(startElement, "config", System.getProperty("org.apache.oodt.commons.Configuration.url", "UNKNOWN"));
+		Element hostElement = statusDocument.createElement("host");
+		serverElement.appendChild(hostElement);
+		XML.add(hostElement, "name", InetAddress.getLocalHost().getHostName());
+		Element osElement = statusDocument.createElement("os");
+		hostElement.appendChild(osElement);
+		XML.add(osElement, "name", System.getProperty("os.name", "UNKNOWN"));
+		XML.add(osElement, "version", System.getProperty("os.version", "UNKNOWN"));
+		XML.add(osElement, "arch", System.getProperty("os.arch", "UNKNOWN"));
+		Element vmElement = statusDocument.createElement("vm");
+		serverElement.appendChild(vmElement);
+		XML.add(vmElement, "name", System.getProperty("java.vm.name", "UNKNOWN"));
+		XML.add(vmElement, "version", System.getProperty("java.version", "UNKNOWN"));
+		XML.add(vmElement, "classpath", System.getProperty("java.class.path", "UNKNOWN"));
+		XML.add(vmElement, "extdirs", System.getProperty("java.ext.dirs", "UNKNOWN"));
+		logElement = statusDocument.createElement("log");
+		serverElement.appendChild(logElement);
+	}
+
+	/** Get my name.
+	 *
+	 * @return The name under which I'm registered in teh naming context.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/** Return the servant for this executable server.
+	 *
+	 * @return The servant.
+	 */
+	public Object getServant() {
+		return servant;
+	}
+
+	/** Control this server.
+	 *
+	 * @param command Command to send to the server.
+	 * @return Results of <var>command</var>.
+	 */
+	public byte[] control(byte[] command) {
+		return xmlrpcServer.execute(new ByteArrayInputStream(command));
+	}
+
+	/** Return the server's class name.
+	 *
+	 * @return Its class name.
+	 */
+	public String getServerClassName() {
+		return className;
+	}
+
+	/** Return status of this server.
+	 *
+	 * @return Its status.
+	 */
+	public String getServerStatus() {
+		// Update the status document with the current log.
+		for (Iterator i = LogInit.MEMORY_LOGGER.getMessages().iterator(); i.hasNext();) {
+			String message = (String) i.next();
+			Element messageElement = statusDocument.createElement("message");
+			messageElement.setAttribute("xml:space", "preserve");
+			messageElement.appendChild(statusDocument.createTextNode(message));
+			logElement.appendChild(messageElement);
+		}
+
+		// Serialize the document.
+		String rc = XML.serialize(statusDocument);
+
+		// Remove all the log messages from the document.
+		NodeList children = logElement.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i)
+			logElement.removeChild(children.item(i));
+
+		// Return the serialized form, which included the log messages.
+		System.err.println(rc);
+		return rc;
+	}
+
+	/** Set a system property.
+	 *
+	 * This uses the property manager to notify property change listeners.
+	 *
+	 * @param key Property's name.
+	 * @param value New value.
+	 * @return Zero (return required for XML-RPC access).
+	 */
+	public int setSystemProperty(String key, String value) {
+		System.err.println("Setting system property \"" + key + "\" to \"" + value + "\"");
+		PropertyMgr.setProperty(key, value);
+		return 0;
+	}
+
+	/**
+	 * Call the server manager on the local system.
+	 *
+	 * @param port What port on the local system the server manager is listening.
+	 * @param user User name to use for authentication.
+	 * @param password Authenticator for <var>user</var>.
+	 * @param method What method in the server manager to call.
+	 * @param params Parameters to pass to the method named by <var>method</var>.
+	 * @return The return value from the method named by <var>method</var>.
+	 * @throws Exception If any error occurs.
+	 */
+	public Object callLocalServerManager(int port, String user, String password, String method, List params) throws Exception {
+		XmlRpcClientLite local = new XmlRpcClientLite("localhost", port);
+		local.setBasicAuthentication(user, password);
+		return local.execute(method, new Vector(params));
+	}
+
+	/** Shut down and exit.
+	 *
+	 * @return Zero.
+	 */
+	public int shutdown() {
+		// Log it.
+		System.err.println("Received shutdown command");
+
+		// Make sure we actually exit sometime soon.
+		new Thread() {
+			public void run() {
+				try {
+					Thread.sleep(15000);
+				} catch (InterruptedException ignore) {}
+				System.exit(1);
+			}
+		}.start();
+
+		// Clean up.
+		shutdown0();
+
+		// And exit.
+		System.err.println("Calling System.exit with status code 0");
+		System.exit(0);
+		return 0;
+	}
+
+	private void shutdown0() {
+		// Unbind.
+		if (!Boolean.getBoolean(DISABLE_BINDING)) try {
+			binder.stopBinding();
+			Context objectContext = configuration.getObjectContext();
+			objectContext.unbind(getName());
+			objectContext.close();
+		} catch (NamingException ignore) {}
+
+		// Kill the ORB.  YEAH!  KILL IT, KILL IT, KIIIIIIIIIIIIIIL IIIIIIIIT!!!!!!!1
+		try {
+			if (servant instanceof org.omg.PortableServer.Servant) {
+				org.omg.PortableServer.Servant s = (org.omg.PortableServer.Servant) servant;
+				org.omg.CORBA.ORB orb = s._orb();
+				orb.shutdown(false/*=>terminate without waiting for reqs to complete*/);
+			}
+		} catch (Throwable ignore) {}
+	}
+
+	/**
+	 * Binding thread.
+	 */
+	private static class Binder extends Thread {
+		public Binder(String name, ExecServer server) {
+			super("Binder for " + name);
+			setDaemon(true);
+			this.name = name;
+			this.server = server;
+			keepBinding = true;
+		}
+		public void run() {
+			while (shouldKeepBinding()) try {
+				Context objectContext = configuration.getObjectContext();
+				objectContext.rebind(name, server.getServant());
+				objectContext.close();
+			} catch (Throwable ex) {
+				System.err.println("Exception binding at " + new Date() + "; will keep trying...");
+				ex.printStackTrace();
+		        } finally {
+				try {
+					Thread.sleep(REBIND_PERIOD);
+				} catch (InterruptedException ignore) {}
+			}
+		}
+		public synchronized void stopBinding() {
+			keepBinding = false;
+		}
+		private synchronized boolean shouldKeepBinding() {
+			return keepBinding;
+		}
+		private boolean keepBinding;
+		private String name;
+		private ExecServer server;
+	}
+
+	/**
+	 * Run all initializers.
+	 *
+	 * This instantiates and calls the {@link Initializer#initialize} method of each
+	 * initializer specified by class name in a comma separated list of classes in the
+	 * system properties.  The property name is <code>org.apache.oodt.commons.initializers</code>, or
+	 * if not defined, <code>org.apache.oodt.commons.ExecServer.initializers</code>, or if not
+	 * defined, <code>initializers</code>.  And if that one's not defined, then none
+	 * are run.
+	 *
+	 * @throws EDAException if an error occurs.
+	 */
+	public static void runInitializers() throws EDAException {
+		String initList = System.getProperty("org.apache.oodt.commons.initializers",
+			System.getProperty("org.apache.oodt.commons.ExecServer.initializers", System.getProperty("initializers", "")));
+		for (Iterator i = org.apache.oodt.commons.util.Utility.parseCommaList(initList); i.hasNext();) {
+			String iname = (String) i.next();
+			try {
+				Class initClass = Class.forName(iname);
+				Initializer init = (Initializer) initClass.newInstance();
+				init.initialize();
+			} catch (ClassNotFoundException ex) {
+				System.err.println("Initializer \"" + iname + "\" not found; aborting");
+				throw new EDAException(ex);
+			} catch (InstantiationException ex) {
+				System.err.println("Initializer \"" + iname + "\" is abstract; aborting");
+				throw new EDAException(ex);
+			} catch (IllegalAccessException ex) {
+				System.err.println("Initializer \"" + iname + "\" isn't public; aborting");
+				throw new EDAException(ex);
+			} catch (EDAException ex) {
+				System.err.println("Initializer \"" + iname + "\" failed: " + ex.getMessage());
+				throw new EDAException(ex);
+			}
+		}
+	}
+
+	/** The configuration. */
+	private static Configuration configuration;
+
+	/** Object key name. */
+	protected String name;
+
+	/** The servant. */
+	private Object servant;
+
+	/** The server class name. */
+	private String className;
+
+	/** Current binder, if any. */
+	private static Binder binder;
+
+	/** Server's status document. */
+	private Document statusDocument;
+
+	/** The &lt;log&gt; element within the status document. */
+	private Element logElement;
+
+	/** The XML-RPC interface to this server. */
+	private XmlRpcServer xmlrpcServer;
+
+	/** Status DTD formal public identifier. */
+	public static final String STATUS_FPI = "-//JPL//DTD EDA Server Status 1.0";
+	
+	/** Status DTD system identifier. */
+	public static final String STATUS_URL = "http://oodt.jpl.nasa.gov/edm-commons/xml/serverStatus.dtd";
+
+	/** Name of the property that prints the server's IOR or RMI handle. */
+	public static final String PRINT_IOR_PROPERTY = "org.apache.oodt.commons.ExecServer.printIOR";
+
+	/** Name of the property that prevents binding of this object with the naming service. */
+	public static final String DISABLE_BINDING = "org.apache.oodt.commons.ExecServer.disableBinding";
+
+	/** How long to wait before bind attempts, in ms. */
+	private static final long REBIND_PERIOD = Long.getLong("org.apache.oodt.commons.ExecServer.rebindPeriod", 30*60*1000).longValue();
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/ExecServerConfig.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/ExecServerConfig.java
new file mode 100644
index 0000000..ebea28f
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/ExecServerConfig.java
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons;
+
+import java.io.*;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.*;
+import org.apache.oodt.commons.util.Documentable;
+import org.apache.oodt.commons.util.XML;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+/** Configuration for an EDA exec-server.
+ *
+ * @author Kelly
+ */
+public class ExecServerConfig extends Executable implements Documentable {
+	/** Create an exec-server configuration.
+	 *
+	 * @param className Name of the class to execute.
+	 * @param objectKey Object key under which class will register.
+	 * @param properties Properties for the server.
+	 */
+	public ExecServerConfig(String className, String objectKey, InetAddress preferredHost, Properties properties) {
+		this.className = className;
+		this.objectKey = objectKey;
+		this.preferredHost = preferredHost;
+		this.properties = properties;
+	}
+
+	/** Create an exec-server configuration.
+	 *
+	 * @param xml XML DOM description, must be an &lt;execServer&gt; element.
+	 * @throws SAXException If <var>xml</var> is invalid.
+	 * @throws UnknownHostException If the <var>xml</var> refers to an unknown host name.
+	 */
+	public ExecServerConfig(Node xml) throws SAXException, UnknownHostException {
+		properties = new Properties();
+		preferredHost = org.apache.oodt.commons.net.Net.getLoopbackAddress();
+		NodeList children = xml.getChildNodes();
+		className = XML.unwrappedText(children.item(0));
+		objectKey = XML.unwrappedText(children.item(1));
+		for (int i = 2; i < children.getLength(); ++i) {
+			Node child = children.item(i);
+			String name = child.getNodeName();
+			if ("host".equals(name))
+				preferredHost = InetAddress.getByName(XML.unwrappedText(children.item(2)));
+			else if ("properties".equals(name))
+				Configuration.loadProperties(child, properties);
+			else throw new SAXException("Unknown node " + name + " in exec server XML");
+		}
+	}		
+
+	/** Create an exec-server configuration.
+	 *
+	 * @param xml Serialized XML description.
+	 * @throws SAXException If we can't parse <var>xml</var>.
+	 * @throws UnknownHostException If the <var>xml</var> refers to an unknown host name.
+	 */
+	public ExecServerConfig(String xml) throws SAXException, UnknownHostException {
+		this(XML.parse(xml).getDocumentElement());
+	}
+
+	protected String[] getCommandLine() {
+		String[] commandLine = new String[6 + properties.size()];
+		commandLine[0] = "java";
+		commandLine[1] = "-Xms" + initialHeap;
+		commandLine[2] = "-Xmx" + maxHeap;
+		int index = 3;
+		for (Iterator i = properties.entrySet().iterator(); i.hasNext();) {
+			Map.Entry entry = (Map.Entry) i.next();
+			commandLine[index++] = "-D" + entry.getKey() + "=" + entry.getValue();
+		}
+		commandLine[index++] = "org.apache.oodt.commons.ExecServer";
+		commandLine[index++] = className;
+		commandLine[index++] = objectKey;
+		return commandLine;
+	}
+
+	/** Get the class name I'm going to execute.
+	 *
+	 * @return The class name.
+	 */
+	public String getClassName() {
+		return className;
+	}
+
+	/** Get the object key I'm going to use.
+	 *
+	 * @return The object key.
+	 */
+	public String getObjectKey() {
+		return objectKey;
+	}
+
+	/** Get the properties for my process.
+	 *
+	 * @return The properties.
+	 */
+	public Properties getProperties() {
+		return properties;
+	}
+
+	/** Get the preferred host.
+	 *
+	 * @return The host on which this server prefers to run.
+	 */
+	public InetAddress getPreferredHost() {
+		return preferredHost;
+	}
+
+	public int hashCode() {
+		return className.hashCode() ^ objectKey.hashCode() ^ properties.hashCode();
+	}
+
+	public boolean equals(Object rhs) {
+		if (rhs == this) return true;
+		if (rhs == null || !(rhs instanceof ExecServerConfig)) return false;
+		ExecServerConfig obj = (ExecServerConfig) rhs;
+		return className.equals(obj.className) && objectKey.equals(obj.objectKey) && properties.equals(obj.properties);
+	}
+
+	public String toString() {
+		return className + " " + objectKey;
+	}
+
+	public Node toXML(Document doc) throws DOMException {
+		Element execServerElement = doc.createElement("execServer");
+		XML.add(execServerElement, "class", getClassName());
+		XML.add(execServerElement, "objectKey", getObjectKey());
+		XML.add(execServerElement, "preferredHost", getPreferredHost().toString());
+		Configuration.dumpProperties(getProperties(), execServerElement);
+		return execServerElement;
+	}
+
+	/** Yield this exce-server configuration as serialized XML.
+	 *
+	 * @return This object as a string serialized XML document.
+	 * @throws DOMException If we can't create the XML document.
+	 */
+	public String toXML() throws DOMException {
+		Document doc = Configuration.createDocument("execServer");
+		doc.replaceChild(toXML(doc), doc.getDocumentElement());
+		return XML.serialize(doc);
+	}
+
+	/** Class name for the ExecServer to execute. */
+	private String className;
+
+	/** Instance name. */
+	private String objectKey;
+
+	/** Properties for the server. */
+	private Properties properties;
+
+	/** Preferred host. */
+	private InetAddress preferredHost;
+
+	/** Initial heap size. */
+	private static String initialHeap;
+
+	/** Max heap size. */
+	private static String maxHeap;
+
+	/** Initialize the heap sizes. */
+	static {
+		Properties props = new Properties();
+		org.apache.oodt.commons.util.Utility.loadProperties(props, ExecServerConfig.class, "ExecServerConfig.properties");
+		initialHeap = props.getProperty("initialHeap", "32m");
+		maxHeap = props.getProperty("maxHeap", "128m");
+	}
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/Executable.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/Executable.java
new file mode 100644
index 0000000..dc3940a
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/Executable.java
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons;
+
+import java.io.*;
+import java.util.*;
+
+/** An executable object.
+ *
+ * Objects of this class are programs that can be executed asynchronously.  Their standard
+ * output and standard error streams are shared with the parent process' standard output
+ * and error streams.
+ *
+ * @author Kelly
+ */
+public abstract class Executable {
+	/** Construct an executable.
+	 */
+	public Executable() {}
+
+	/** Get the command-line.
+	 *
+	 * @return Command-line.
+	 */
+	protected abstract String[] getCommandLine();
+
+	/** Start executing this program.
+	 *
+	 * If any error occurs while launching the program, this method notes a message to
+	 * stderr, but otherwise takes no further action.
+	 */
+	public void execute() {
+		// We force program execution to be asynchronous by cutting a new thread.
+		new Thread() {
+			public void run() {
+				try {
+					process = Runtime.getRuntime().exec(getCommandLine());
+					
+					// Read all output (standard and error output)
+					// from the process and pass it to the user.
+					redirect(process.getErrorStream(), System.err);
+					redirect(process.getInputStream(), System.out);
+				} catch (IOException ex) {
+					System.err.println("Can't execute command \"" + getCommandLine()[0] + "\": "
+						+ ex.getMessage());
+				}
+			}
+
+			/** Redirect the given input onto the given output.
+			 *
+			 * @param in The stream to read.
+			 * @param out Where to write it.
+			 */
+			private void redirect(final InputStream in, final OutputStream out) {
+				// Do this in the background, too.
+				new Thread() {
+					public void run() {
+						try {
+							byte[] buf = new byte[1024];
+							for (;;) {
+								int numRead = in.read(buf);
+								if (numRead == -1) {
+									in.close();
+									break;
+								}
+								out.write(buf, 0, numRead);
+							}
+						} catch (IOException ex) {
+							try {
+								in.close();
+							} catch (IOException ignore) {}
+						}
+					}
+				}.start();
+			}
+		}.start();
+
+		// Spin until the process field is set.
+		while (process == null)
+			Thread.yield();
+	}
+
+	/** Wait for the process to terminate.
+	 *
+	 * @throws InterruptedException If the thread waiting for the termination is interrupted.
+	 * @return The exit value of the process.
+	 */
+	public int waitFor() throws InterruptedException {
+		return process.waitFor();
+	}
+
+	/** Terminate this process.
+	 */
+	public void terminate() {
+		process.destroy();
+	}
+
+	/** The process backing this executable. */
+	protected Process process;
+
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/Initializer.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/Initializer.java
new file mode 100644
index 0000000..1bb0301
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/Initializer.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons;
+
+/**
+ * Initializer for an enterprise application.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+public interface Initializer {
+	/**
+	 * Initialize the appliction.
+	 *
+	 * @throws EDAException if an error occurs.
+	 */
+	void initialize() throws EDAException;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/MultiServer.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/MultiServer.java
new file mode 100644
index 0000000..db89f91
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/MultiServer.java
@@ -0,0 +1,576 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons;

+

+import java.io.IOException;

+import java.io.StringReader;

+import java.lang.reflect.Constructor;

+import java.lang.reflect.InvocationTargetException;

+import java.rmi.registry.Registry;

+import java.rmi.server.RemoteObject;

+import java.util.HashMap;

+import java.util.Hashtable;

+import java.util.Iterator;

+import java.util.Map;

+import java.util.Timer;

+import java.util.TimerTask;

+import javax.naming.Context;

+import javax.naming.NamingException;

+import javax.naming.spi.NamingManager;

+import javax.xml.parsers.DocumentBuilder;

+import javax.xml.parsers.DocumentBuilderFactory;

+import javax.xml.parsers.ParserConfigurationException;

+import org.apache.oodt.commons.util.LogInit;

+import org.apache.oodt.commons.util.XML;

+import org.w3c.dom.Document;

+import org.w3c.dom.Element;

+import org.w3c.dom.Node;

+import org.w3c.dom.NodeList;

+import org.xml.sax.InputSource;

+import org.xml.sax.SAXException;

+

+/**

+ * The MultiServer runs multiple server objects in a single JVM.  Instead of running a

+ * separate product server, profile server, query server, and so forth, in their own JVMs,

+ * which are extremely heavy-weight operating system processes, we can put them into one

+ * JVM which reduces the memory footprint on a single computer enormously.

+ *

+ * <h3>Specifying the Configuration</h3>

+ *

+ * The MultiServer configuration is an XML document.  Here's

+ * a sample:

+ * <pre>&lt;multiserver

+ *   xmlns="http://oodt.jpl.nasa.gov/edm-commons/xml/multiserver"

+ *   id="My Multi Server"&gt;

+ *   &lt;server

+ *     class="org.apache.oodt.commons.product.rmi.ProductServiceImpl"

+ *     id="urn:eda:rmi:BioServer"

+ *     bind="rebind" /&gt;

+ *   &lt;server

+ *     class="org.apache.oodt.commons.product.rmi.ProductServiceImpl"

+ *     id="urn:eda:rmi:SpaceServer"

+ *     bind="1800000" /&gt;

+ *   &lt;server

+ *     class="org.apache.oodt.commons.profile.rmi.ProfileServiceImpl"

+ *     id="urn:eda:rmi:Resource"

+ *     bind="bind" /&gt;

+ *   &lt;properties&gt;

+ *     &lt;property name="urn:eda:rmi:BioServer.handlers"&gt;

+ *       edrn.MedHandler,edrn.SpecimenHandler

+ *     &lt;/property&gt;

+ *     &lt;property name="urn:eda:rmi:SpaceServer.handlers"&gt;

+ *       pds.PlanetoidHandler

+ *     &lt;/property&gt;

+ *     &lt;property name="org.apache.oodt.commons.profile.Handlers"&gt;

+ *       com.sun.ResourceHandler

+ *     &lt;/property&gt;

+ *   &lt;/properties&gt;

+ * &lt;/multiserver&gt;</pre>

+ *

+ * <p>This would start three servers (two products, one profile) with the various property

+ * settings indicated.  The MultiServer expects the property

+ * <code>org.apache.oodt.commons.MultiServer.config</code> to identify the URL of the configuration.  You

+ * can shorten that to <code>MultiServer.config</code> or <code>multiserver.config</code>

+ * or even just <code>config</code>, in that order.  If none of those properties are

+ * specified then the MultiServer will expect the URL to be the first (and only) command

+ * line argument.

+ *

+ * <p>The <code>id</code> attribute on the <code>multiserver</code> element tells the name

+ * of the whole application; it's used to prefix log messages.

+ *

+ * <h3>Server Specification</h3>

+ *

+ * <p>Each <code>&lt;server&gt;</code> entry names a server to start.  The

+ * <code>class</code> attribute is the name of the RMI-compatible Java class that the

+ * server will run.  (Note that currently only RMI servers are supported.)  The

+ * <code>id</code> attribute tells the name the server should use to register with the

+ * naming context.  And the <code>bind</code> attribute tells how the registration should

+ * proceed.  It can take on the following values:

+ *

+ * <ul>

+ *   <li><code>true</code> meaning the object will attempt a bind.  If the ID is already

+ *   bound in the context, the MultiServer fails.</li>

+ *

+ *   <li><code>false</code> meaning the object won't be bound.</li>

+ *

+ *   <li><code>rebind</code> meaning the object will rebind its ID in the context,

+ *   overwriting any previous binding.

+ *

+ *   <li><var>number</var> meaining the object will rebind its ID once at starup, and

+ *   every <var>number</var> milliseconds thereafter.  This is, in OODT's experience, the

+ *   most useful option as it helps an entire dpeloyed network of servers self-heal after

+ *   a naming context restart.

+ * </ul>

+ *

+ * <h3>Propery Specification</h3>

+ *

+ * <p>For convenience, System Properties may be specified in the configirutaion as well.

+ * However, any properties already defined (such as using the <code>-D</code> command-line

+ * argument) get priority and their values won't be overridden.  To specify properties,

+ * list any number of <code>&lt;property&gt;</code> elements under the

+ * <code>&lt;properties&gt;</code> element with a <code>name</code> attribute naming the

+ * System Property key and the text of the element naming its value.  Note that the text

+ * will be unwrapped.

+ *

+ * @author Kelly

+ * @version $Revision: 1.3 $

+ */

+public class MultiServer {

+	/**

+	 * Start the multi server.

+	 *

+	 * @param argv Command-line arguments.

+	 * @throws Throwable if an error occurs.

+	 */

+	public static void main(String[] argv) throws Throwable {

+		String config = System.getProperty("org.apache.oodt.commons.MultiServer.config", System.getProperty("MultiServer.config",

+			System.getProperty("multiserver.config", System.getProperty("config"))));

+		if (config == null) {

+			if (argv.length != 1)

+				throw new IllegalStateException("No org.apache.oodt.commons.MultiServer.config property or config URL argument");

+			else

+				config = argv[0];

+		}

+

+		StringReader reader = new StringReader(CONFIG);

+		Configuration.configuration = new Configuration(new InputSource(reader));

+		reader.close();

+		parseConfig(new InputSource(config));

+

+		Hashtable t = new Hashtable();

+		t.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.oodt.commons.object.jndi.ObjectCtxFactory");

+		String registryList = System.getProperty("org.apache.oodt.commons.rmiregistries", System.getProperty("rmiregistries"));

+		if (registryList == null) {

+			String host = System.getProperty("rmiregistry.host", "localhost");

+			int port = Integer.getInteger("rmiregistry.port", Registry.REGISTRY_PORT).intValue();

+			registryList = "rmi://" + host + ":" + port;

+		}

+		t.put("rmiregistries", registryList);

+		context = NamingManager.getInitialContext(t);

+		ExecServer.runInitializers();

+		try {

+			LogInit.init(System.getProperties(), getAppName());

+			if (servers.isEmpty()) throw new IllegalStateException("No servers defined in config");

+

+			Runtime.getRuntime().addShutdownHook(new Thread() {

+				public void run() {

+					shutdown();

+				}

+			});

+			startup();

+		} catch (Throwable ex) {

+			ex.printStackTrace();

+			try {

+				shutdown();

+			} catch (Throwable ignore) {}

+			System.exit(1);

+		}

+		for (;;) try {

+			Thread.currentThread().join();

+		} catch (InterruptedException ignore) {}

+	}

+

+	/**

+	 * Parse the MultiServer configuration.

+	 *

+	 * @param is Source of the configuration.

+	 * @throws ParserConfigurationException If we can't create a parser.

+	 * @throws SAXException If there's a parse error.

+	 * @throws IOException If there's a problem reading the configuration.

+	 * @throws ClassNotFoundException If we can't find a server class.

+	 * @throws NoSuchMethodException If the server class doesn't have the right constructor.

+	 * @throws InstantiationException If we can create a server object.

+	 * @throws IllegalAccessException If the server constructor isn't accessible.

+	 * @throws InvocationTargetException If the server constructor throws an exception.

+	 */

+	static void parseConfig(InputSource is) throws ParserConfigurationException, SAXException, IOException,

+		ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException,

+		InvocationTargetException {

+		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

+		factory.setIgnoringComments(true);

+		factory.setIgnoringElementContentWhitespace(true);

+		factory.setNamespaceAware(true);

+		factory.setValidating(false);

+		DocumentBuilder builder = factory.newDocumentBuilder();

+		Document doc = builder.parse(is);

+		Element root = doc.getDocumentElement();

+		appName = root.getAttribute("id");

+		if (appName == null) throw new SAXException("id attribute missing from multiserver element");

+

+		// Set properties

+		NodeList children = root.getChildNodes();

+		for (int i = 0; i < children.getLength(); ++i) {

+			Node node = (Node) children.item(i);

+			if ("properties".equals(node.getNodeName())) {

+				NodeList props = ((Element) node).getElementsByTagName("property");

+				for (int j = 0; j < props.getLength(); ++j) {

+					Element property = (Element) props.item(j);

+					String name = property.getAttribute("name");

+					if (!System.getProperties().containsKey(name)) {

+						String value = XML.unwrappedText(property);

+						System.setProperty(name, value);

+					}

+				}

+			}

+		}		

+

+		// Create servers

+		NodeList serverNodes = root.getElementsByTagName("server");

+		servers = new HashMap();

+		for (int i = 0; i < serverNodes.getLength(); ++i) {

+			Element serverElem = (Element) serverNodes.item(i);

+			String name = serverElem.getAttribute("id");

+			if (name == null) throw new SAXException("id attribute missing from server element");

+			String className = serverElem.getAttribute("class");

+			if (className == null) throw new SAXException("class attribute missing from server element");

+			String bindKind = serverElem.getAttribute("bind");

+			if (bindKind == null) throw new SAXException("bind attribute missing from server element");

+			Server server;

+			if ("true".equals(bindKind))

+				server = new BindingServer(name, className);

+			else if ("false".equals(bindKind))

+				server = new NonbindingServer(name, className);

+			else if ("rebind".equals(bindKind))

+				server = new RebindingServer(name, className);

+			else try {

+				long period = Long.parseLong(bindKind);

+				server = new AutobindingServer(name, className, period);

+			} catch (NumberFormatException ex) {

+				throw new SAXException("Expected true, false, rebind, or auto for bind attribute but got `"

+					+ bindKind + "'");

+			}

+			servers.put(name, server);

+		}

+

+	}

+

+	/**

+	 * Start each server.

+	 *

+	 * @throws NamingException if an error occurs.

+	 */

+	static void startup() throws NamingException {

+		for (Iterator i = servers.values().iterator(); i.hasNext();) {

+			Server s = (Server) i.next();

+			s.start();

+		}

+	}

+

+	/**

+	 * Stop each server.

+	 */

+	static void shutdown() {

+		for (Iterator i = servers.values().iterator(); i.hasNext();) try {

+			Server s = (Server) i.next();

+			s.stop();

+		} catch (NamingException ignore) {}

+		TIMER.cancel();

+	}

+

+	/**

+	 * Get the name of the application.

+	 *

+	 * @return a {@link String} value.

+	 */

+	static String getAppName() {

+		return appName;

+	}

+

+	/**

+	 * Get the servers.  Keys are {@String} names and values are {@link #Server}s.

+	 *

+	 * @return a {@link Map} of the defined servers.

+	 */

+	static Map getServers() {

+		return servers;

+	}

+

+	/**

+	 * A server.

+	 */

+	static abstract class Server extends ExecServer {

+		/**

+		 * Creates a new {@link Server} instance.

+		 *

+		 * @param name ID under which to register.

+		 * @param className Class of server to instantiate.

+		 * @throws ClassNotFoundException If we can't find the server class.

+		 * @throws NoSuchMethodException If the server class doesn't have the right constructor.

+		 * @throws InstantiationException If we can create the server object.

+		 * @throws IllegalAccessException If the server constructor isn't accessible.

+		 * @throws InvocationTargetException If the server constructor throws an exception.

+		 */

+		protected Server(String name, String className) throws ClassNotFoundException, NoSuchMethodException,

+			InstantiationException, IllegalAccessException, InvocationTargetException {

+			super(name);

+			this.className = className;

+			Class clazz = Class.forName(className);

+			Constructor ctor = clazz.getConstructor(new Class[]{ ExecServer.class });

+			servant = (RemoteObject) ctor.newInstance(new Object[]{ this });

+		}

+

+		/**

+		 * Get the name of the server class to instantiate.

+		 *

+		 * @return a {@link String} value.

+		 */

+		public String getClassName() {

+			return className;

+		}

+

+		/**

+		 * Get the type of binding this server will perform.  Possible values are

+		 * {@link #BINDING}, {@link #NONBINDING}, {@link #REBINDING}, or {@link

+		 * #AUTO}.

+		 *

+		 * @return An integer identifiying the binding behavior.

+		 */

+		public abstract int getBindingBehavior();

+

+		/**

+		 * Start this server.

+		 *

+		 * @throws NamingException if an error occurs during the binding.

+		 */

+		public abstract void start() throws NamingException;

+

+		/**

+		 * Stop this server.

+		 *

+		 * @throws NamingException if an error occurs during unbinding.

+		 */

+		public abstract void stop() throws NamingException;

+

+		/** Name of server class. */

+		protected String className;

+

+		/** Server object. */

+		protected RemoteObject servant;

+	}

+

+	/** Inidcates server will try a bind. */

+	public static final int BINDING = 1;

+

+	/** Indicates server won't be bound. */

+	public static final int NONBINDING = 2;

+

+	/** Indicates server will try a rebind. */

+	public static final int REBINDING = 3;

+

+	/** Indicates server will try periodic rebinding. */

+	public static final int AUTO = 4;

+

+	/** Timer to schedule periodic rebinind. */

+	private static final Timer TIMER = new Timer(/*isDaemon*/true);

+

+	/** Name of this application. */

+	private static String appName;

+

+	/** Known servers.  Keys are {@String} names and values are {@link #Server}s. */

+	private static Map servers;

+

+	/** The naming context. */

+	private static Context context;

+

+	/** The edarc.xml file to satisfy the MultiServer's servers. */

+	private static final String CONFIG = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE configuration PUBLIC"

+		+ " \"-//JPL//DTD EDA Configuration 1.0//EN\" \"http://enterprise.jpl.nasa.gov/dtd/configuration.dtd\">\n"

+		+ "<configuration><webServer><host>localhost</host><port>80</port></webServer>"

+		+ "<nameServer><iiop><host>localhost</host><port>10000</port></iiop></nameServer></configuration>";

+

+	/**

+	 * A server that tries a single bind.

+	 */

+	static class BindingServer extends Server {

+		/**

+		 * Creates a new {@link BindingServer} instance.

+		 *

+		 * @param name ID under which to register.

+		 * @param className Class of server to instantiate.

+		 * @throws ClassNotFoundException If we can't find the server class.

+		 * @throws NoSuchMethodException If the server class doesn't have the right constructor.

+		 * @throws InstantiationException If we can create the server object.

+		 * @throws IllegalAccessException If the server constructor isn't accessible.

+		 * @throws InvocationTargetException If the server constructor throws an exception.

+		 */

+		BindingServer(String name, String className) throws ClassNotFoundException, NoSuchMethodException,

+			InstantiationException, IllegalAccessException, InvocationTargetException {

+			super(name, className);

+		}

+

+		public int getBindingBehavior() {

+			return BINDING;

+		}

+

+		/**

+		 * Start by binding.

+		 *

+		 * @throws NamingException if an error occurs.

+		 */

+		public void start() throws NamingException {

+			context.bind(name, servant);

+		}

+

+		/**

+		 * Stop by unbinding.

+		 *

+		 * @throws NamingException if an error occurs.

+		 */

+		public void stop() throws NamingException {

+			context.unbind(name);

+		}

+	}

+

+	/**

+	 * A (named, but anonymous) server that isn't bound to a naming context.

+	 */

+	static class NonbindingServer extends Server {

+		/**

+		 * Creates a new {@link NonbindingServer} instance.

+		 *

+		 * @param name ID under which to register.

+		 * @param className Class of server to instantiate.

+		 * @throws ClassNotFoundException If we can't find the server class.

+		 * @throws NoSuchMethodException If the server class doesn't have the right constructor.

+		 * @throws InstantiationException If we can create the server object.

+		 * @throws IllegalAccessException If the server constructor isn't accessible.

+		 * @throws InvocationTargetException If the server constructor throws an exception.

+		 */

+		NonbindingServer(String name, String className) throws ClassNotFoundException, NoSuchMethodException,

+			InstantiationException, IllegalAccessException, InvocationTargetException {

+			super(name, className);

+		}

+

+		public int getBindingBehavior() {

+			return NONBINDING;

+		}

+

+		/**

+		 * Start by taking no action.

+		 */

+		public void start() {}

+

+		/**

+		 * Stop by taking no action.

+		 */

+		public void stop() {}

+	}

+

+	/**

+	 * A server that rebinds its ID in the naming context.

+	 */

+	static class RebindingServer extends BindingServer {

+		/**

+		 * Creates a new {@link RebindingServer} instance.

+		 *

+		 * @param name ID under which to register.

+		 * @param className Class of server to instantiate.

+		 * @throws ClassNotFoundException If we can't find the server class.

+		 * @throws NoSuchMethodException If the server class doesn't have the right constructor.

+		 * @throws InstantiationException If we can create the server object.

+		 * @throws IllegalAccessException If the server constructor isn't accessible.

+		 * @throws InvocationTargetException If the server constructor throws an exception.

+		 */

+		RebindingServer(String name, String className) throws ClassNotFoundException, NoSuchMethodException,

+			InstantiationException, IllegalAccessException, InvocationTargetException {

+			super(name, className);

+		}

+

+		public int getBindingBehavior() {

+			return REBINDING;

+		}

+

+		/**

+		 * Start by rebinding in naming context.

+		 *

+		 * @throws NamingException if an error occurs.

+		 */

+		public void start() throws NamingException {

+			context.rebind(name, servant);

+		}

+	}

+

+	/**

+	 * A server that periodically rebinds its ID in the naming context.

+	 */

+	static class AutobindingServer extends Server {

+		/**

+		 * Creates a new {@link AutobindingServer} instance.

+		 *

+		 * @param name ID under which to register.

+		 * @param className Class of server to instantiate.

+		 * @throws ClassNotFoundException If we can't find the server class.

+		 * @throws NoSuchMethodException If the server class doesn't have the right constructor.

+		 * @throws InstantiationException If we can create the server object.

+		 * @throws IllegalAccessException If the server constructor isn't accessible.

+		 * @throws InvocationTargetException If the server constructor throws an exception.

+		 */

+		AutobindingServer(String name, String className, long period) throws ClassNotFoundException, NoSuchMethodException,

+			InstantiationException, IllegalAccessException, InvocationTargetException {

+			super(name, className);

+			this.period = period;

+		}

+

+		public int getBindingBehavior() {

+			return AUTO;

+		}

+

+		/**

+		 * Start by scheduling the timer task that rebinds this server.

+		 */

+		public void start() {

+			TIMER.schedule(binder = new Binder(), /*delay*/0L, /*period*/period);

+		}

+

+		/**

+		 * Stop by canceling the timer task and unbinding from the server.

+		 *

+		 * @throws NamingException if an error occurs.

+		 */

+		public void stop() throws NamingException {

+			if (binder != null) binder.cancel();

+			context.unbind(name);

+		}

+

+		/**

+		 * Get how often this server process will be rebound.

+		 *

+		 * @return Period in milliseconds.

+		 */

+		public long getPeriod() {

+			return period;

+		}

+

+		/** How often to rebind in milliseconds. */

+		private long period;

+

+		/** Timer task that rebinds. */

+		private Binder binder;

+

+		/**

+		 * Timer task that rebinds this server to the naming context.

+		 */

+		private class Binder extends TimerTask {

+			public void run() {

+				try {

+					context.rebind(name, servant);

+				} catch (NamingException ex) {}

+			}

+		}

+	}

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/Service.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/Service.java
new file mode 100644
index 0000000..9854bfc
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/Service.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * An enterprise service.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1 $
+ */
+public interface Service extends Remote {
+	/**
+	 * Get the interface name of the service.
+	 *
+	 * Nominally, this should return the fully qualified class name of the
+	 * implementation class, not the interface name.  No idea how that "standard" got
+	 * started.  So, a good return value might be
+	 * <code>jpl.oodt.product.rmi.ProductServiceImpl</code> and <strong>not</strong>
+	 * <code>jpl.oodt.product.ProductService</code>.
+	 *
+	 * @return a <code>String</code> value.
+	 * @throws RemoteException if an error occurs.
+	 */
+	String getServerInterfaceName() throws RemoteException;
+
+	/**
+	 * Control the server.
+	 *
+	 * @param command a <code>byte[]</code> value.
+	 * @return Response.
+	 * @throws RemoteException if an error occurs.
+	 */
+	byte[] control(byte[] command) throws RemoteException;
+
+	
+	/**
+	 * Control the server asynchronously.
+	 *
+	 * @param command a <code>byte[]</code> value.
+	 * @throws RemoteException if an error occurs.
+	 */
+	void controlAsync(byte[] command) throws RemoteException;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/Activity.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/Activity.java
new file mode 100644
index 0000000..5941573
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/Activity.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons.activity;
+
+import java.net.InetAddress;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Date;
+import java.util.Random;
+import org.apache.oodt.commons.net.Net;
+
+/**
+ * An activity is an occurrence of some active action.  It has a unique ID in the
+ * universe, a way to log incidents that occur during the course of the activity, and a
+ * way to indicate that the activity has stopped.
+ *
+ * @author Kelly
+ * @version $Revision: 1.2 $
+ */
+public abstract class Activity {
+	/**
+	 * Creates a new {@link Activity} instance.
+	 *
+	 */
+	protected Activity() {
+		setID(generateID());
+	}
+
+	/**
+	 * Change the activity's ID to the given value.
+	 *
+	 * @param id New ID.
+	 */
+	public void setID(String id) {
+		if (id == null) throw new IllegalArgumentException("ID required");
+		this.id = id;
+	}
+
+	/**
+	 * Get the activity's ID.
+	 *
+	 * @return a {@link String} ID.
+	 */
+	public String getID() {
+		return id;
+	}
+
+	/**
+	 * Stop this activity.  This method logs a <code>ActivityStopped</code> incident.  No
+	 * further incidents may be logged after calling this method.
+	 */
+	public synchronized void stop() {
+		if (!started) return;
+		this.started = false;
+		log(new ActivityStopped());
+	}
+
+	/**
+	 * Log the given incident.
+	 *
+	 * @param incident The incident to log.
+	 */
+	public final synchronized void log(Incident incident) {
+		incident.setActivityID(id);
+		recordIncident(incident);
+	}
+
+	/**
+	 * Record the given incident.
+	 *
+	 * @param incident an {@link Incident} value.
+	 */
+	protected abstract void recordIncident(Incident incident);
+
+	/**
+	 * Generate a unique ID for the activity based on Internet address, a unique
+	 * counter, the time, and some random bytes.
+	 *
+	 * @return a {@link String} value.
+	 */
+	private String generateID() {
+		try {
+			InetAddress addr = Net.getLocalHost();	                       // Get the local host's IP address
+			long nextNum = ++counter;				       // Get the next 64 bit number
+			Date date = new Date();					       // Get the current time
+			byte[] bytes = new byte[32];				       // Make space for 32 random bytes
+			RANDOM.nextBytes(bytes);				       // Fill in 32 random bytes
+			StringBuffer input = new StringBuffer();		       // Make space to put the 1st 3 components...
+			input.append(addr).append(nextNum).append(date);	       // ...together and put 'em together
+			MessageDigest messageDigest = MessageDigest.getInstance("MD5");// Prepare to take a hash
+			messageDigest.update(input.toString().getBytes());	       // Add the 1st 3 components
+			byte[] sig = messageDigest.digest(bytes);		       // And add the random bytes
+			StringBuffer output = new StringBuffer();		       // Make space to store the hash as a string
+			for (int i = 0; i < sig.length; ++i)			       // For each byte in the hash
+				output.append(Integer.toHexString(((int)sig[i])&0xff));// Store it as a hex value
+			return output.toString();				       // And return the string
+		} catch (NoSuchAlgorithmException ex) {
+			throw new IllegalStateException("MD5 algorithm not available");
+		}
+	}
+
+	/** Unique ID of the activity. */
+	protected String id;
+
+	/** Flag that tells if this activity is active. */
+	private boolean started = true;
+
+	/** Random number generator for unique IDs. */
+	private static final Random RANDOM = new Random();
+
+	/** Counter for unique IDs. */
+	private static long counter = 0;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/ActivityException.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/ActivityException.java
new file mode 100644
index 0000000..cb2e3d1
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/ActivityException.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons.activity;
+
+/**
+   This class is intended to be thrown as an exception in the org.apache.oodt.commons.activity package.
+
+   @author S. Hardman
+   @version $Revision: 1.1 $
+*/
+public class ActivityException extends Exception {
+
+   /**
+      This constructor calls the {@link Exception} constructor with the same signature.
+   */
+   public ActivityException() {
+      super();
+   }
+
+
+   /**
+      This constructor calls the {@link Exception} constructor with the same signature.
+
+      @param message The message associated with the exception.
+   */
+   public ActivityException(String message) {
+      super(message);
+   }
+
+
+   /**
+      This constructor calls the {@link Exception} constructor with the same signature.
+
+      @param cause The exception that caused this exception.
+   */
+   public ActivityException(Throwable cause) {
+      super(cause);
+   }
+
+
+   /**
+      This constructor calls the {@link Exception} constructor with the same signature.
+
+      @param message The message associated with the exception.
+      @param cause The exception that caused this exception.
+   */
+   public ActivityException(String message, Throwable cause) {
+      super(message, cause);
+   }
+}
+
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/ActivityFactory.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/ActivityFactory.java
new file mode 100644
index 0000000..2bf073f
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/ActivityFactory.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+/**

+ * Factory for activities.  Classes that implement this interface are responsible for

+ * generating application-specific Activities on demand.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public interface ActivityFactory {

+	/**

+	 * Create an activity.

+	 *

+	 * @return an new {@link Activity} instance.

+	 */

+	Activity createActivity();

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/ActivityStopped.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/ActivityStopped.java
new file mode 100644
index 0000000..94a5ff2
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/ActivityStopped.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+/**

+ * An incident that indicates that an activity has stopped.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+class ActivityStopped extends Incident {

+	/**

+	 * Creates a new {@link ActivityStopped} instance.

+	 */

+	ActivityStopped() {}

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/ActivityTracker.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/ActivityTracker.java
new file mode 100644
index 0000000..70e52b0
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/ActivityTracker.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.util.ArrayList;

+import java.util.Collection;

+import java.util.Iterator;

+import java.util.List;

+import java.util.StringTokenizer;

+

+/**

+ * Tracker of activities.  This is the main class applications use to keep track

+ * activities.  To track an activity, call the {@link #createActivity} method to generate

+ * a new {@link Activity}, then log {@link Incident}s against it with the {@link

+ * Activity#log} method.  Finally, top the activity with {@link Activity#stop}.

+ *

+ * <p>The <code>ActivityTracker</code> generates activities using an {@link

+ * ActivityFactory}.  It configures the factory by examining the system properties.  The

+ * property <code>org.apache.oodt.commons.activity.factories</code> (or the

+ * <code>activity.factories</code> property for those that prefer an abbreviated name and

+ * the prior one isn't defined) is a comma- (or vertical bar-) seperated list of class

+ * names.  Each class is expected to implement the {@link ActivityFactory} interface.  If

+ * there are none (or neither property is defined), then a special null factory is used

+ * that throws away all incidents.  If more than one's defined, then a special factory is

+ * used that multiplexes all incidents to each one.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public class ActivityTracker {

+	/**

+	 * Generate an activity.

+	 *

+	 * @return an new {@link Activity} instance.

+	 */

+	public static Activity createActivity() {

+		return factory.createActivity();

+	}

+

+	/** What actually makes Activities. */

+	static ActivityFactory factory;

+

+	/**

+	 * Examine the prope

+	 *

+	 * @throws Exception if an error occurs.

+	 */

+	static void initializeFactories() throws Exception {

+		String facNames = System.getProperty("org.apache.oodt.commons.activity.factories", System.getProperty("activity.factories", ""));

+		List factories = new ArrayList();

+		for (StringTokenizer tokens = new StringTokenizer(facNames, ",|"); tokens.hasMoreTokens();) {

+			String factoryName = tokens.nextToken();

+			Class factoryClass = Class.forName(factoryName);

+			factories.add(factoryClass.newInstance());

+		}

+		if (factories.isEmpty())

+			factory = new NullActivityFactory();

+		else if (factories.size() == 1)

+			factory = (ActivityFactory) factories.get(0);

+		else

+			factory = new CompositeActivityFactory(factories);

+	}

+

+	/**

+	 * Initialize the <code>factory</code>.

+	 */

+	static {

+		try {

+			initializeFactories();

+		} catch (RuntimeException ex) {

+			throw ex;

+		} catch (Exception ex) {

+			throw new IllegalStateException("Cannot initialize activity factories: " + ex.getMessage());

+		}

+	}

+

+	/**

+	 * Special factory that creates only null activities.  Null activities toss out every incident.

+	 */

+	private static class NullActivityFactory implements ActivityFactory {

+		/**

+		 * Create null activities.

+		 *

+		 * @return Null activity.

+		 */

+		public Activity createActivity() {

+			return new NullActivity();

+		}

+	}

+

+	/**

+	 * Special factory that multiplexes activites.  This factory takes a collection of

+	 * other factories.  It generates activities that then fantail incidents to other

+	 * factories' activities.

+	 */

+	private static class CompositeActivityFactory implements ActivityFactory {

+		/**

+		 * Creates a new {@link CompositeActivityFactory} instance.

+		 *

+		 * @param factories a {@link Collection} of ActivityFactories.

+		 */

+		private CompositeActivityFactory(Collection factories) {

+			this.factories = factories;

+		}

+

+		/**

+		 * Create an activity that fantails to other factories' activities.

+		 *

+		 * @return an {@link Activity} value.

+		 */

+		public Activity createActivity() {

+			List activities = new ArrayList();

+			for (Iterator i = factories.iterator(); i.hasNext();) {

+				ActivityFactory factory = (ActivityFactory) i.next();

+				activities.add(factory.createActivity());

+			}

+			return new CompositeActivity(activities);

+		}

+

+		/** Collection of {@link ActivityFactory} instances. */

+		private Collection factories;

+	}

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/CompositeActivity.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/CompositeActivity.java
new file mode 100644
index 0000000..56fb788
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/CompositeActivity.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.util.Collection;

+import java.util.Iterator;

+

+/**

+ * A composite activity multiplexes incidents to multiple other activities.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public class CompositeActivity extends Activity {

+	/**

+	 * Creates a new {@link CompositeActivity} instance.

+	 *

+	 * @param activities a {@link Collection} of {@link Activity} instances.

+	 */

+	public CompositeActivity(Collection activities) {

+		if (activities == null)

+			throw new IllegalArgumentException("Activities collection required");

+		for (Iterator i = activities.iterator(); i.hasNext();)

+			if (!(i.next() instanceof Activity))

+				throw new IllegalArgumentException("Non-Activity in activities collection");

+		this.activities = activities;

+	}

+

+	/**

+	 * Record the given incident in each of our delegate activities.

+	 *

+	 * @param incident The {@link Incident} to record.

+	 */

+	public void recordIncident(Incident incident) {

+		for (Iterator i = activities.iterator(); i.hasNext();)

+			((Activity) i.next()).recordIncident(incident);

+	}

+

+	/**

+	 * A collection of {@link Activity} instances.

+	 */

+	private Collection activities;

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/DatagramLogger.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/DatagramLogger.java
new file mode 100644
index 0000000..4cdc3dd
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/DatagramLogger.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.io.ByteArrayInputStream;

+import java.io.IOException;

+import java.io.InvalidClassException;

+import java.io.ObjectInputStream;

+import java.io.OptionalDataException;

+import java.io.StreamCorruptedException;

+import java.net.DatagramPacket;

+import java.net.DatagramSocket;

+import java.util.HashMap;

+import java.util.Map;

+

+/**

+ * The datagram logger accepts incidents in UDP datagrams and saves them in a {@link

+ * Storage}.  The datagrams contain serialized {@link Incident}s, and are probably sent by

+ * a {@link DatagramLoggingActivityFactory}.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+class DatagramLogger {

+	public static void main(String[] argv) throws Throwable {

+		if (argv.length > 0) {

+			System.err.println("This program takes NO command line arguments.");

+			System.err.println("Set the activity.port property to adjust the port number.");

+			System.err.println("Set the activity.storage property to set the Storage class to use.");

+			System.exit(1);

+		}

+		int port = Integer.getInteger("activity.port", 4556).intValue();

+		String className = System.getProperty("activity.storage");

+		if (className == null) {

+			System.err.println("No Storage class defined via the `activity.storage' property; exiting...");

+			System.exit(1);

+		}

+		Class storageClass = Class.forName(className);

+		storage = (Storage) storageClass.newInstance();

+		DatagramSocket socket = new DatagramSocket(port);

+		byte[] buf = new byte[2048];

+		DatagramPacket packet = new DatagramPacket(buf, buf.length);

+		for (;;) {

+			socket.receive(packet);

+			byte[] received = new byte[packet.getLength()];

+			System.arraycopy(packet.getData(), packet.getOffset(), received, 0, packet.getLength());

+			new ReceiverThread(received).start();

+		} 

+	}

+

+	/** Long term storage for incidents. */

+	private static Storage storage;

+

+	/** History awaiting long-term storage.  Keys are {@link String} activity IDs, and values are {@link History} objects. */

+	private static Map histories = new HashMap();

+

+	/**

+	 * Thread that saves off an incident into a history so the main thread can go back

+	 * to receiving more datagrams.

+	 */

+	private static class ReceiverThread extends Thread {

+		/**

+		 * Creates a new {@link ReceiverThread} instance.

+		 *

+		 * @param data Copy of bytes received in a datagram.

+		 */

+		private ReceiverThread(byte[] data) {

+			this.data = data;

+		}

+

+		/**

+		 * Reconstitute the incident in the received byte array and store it into

+		 * a {@link History}.

+		 */

+		public void run() {

+			try {

+				ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data));

+				Incident incident = (Incident) in.readObject();

+				String id = incident.getActivityID();

+				in.close();

+				History history;

+				synchronized (histories) {

+					history = (History) histories.get(id);

+					if (history == null) {

+						histories.put(id, new History(incident, storage));

+						return;

+					}

+				}

+				history.addIncident(incident);

+			} catch (ClassNotFoundException ex) {

+				System.err.println("Dropping Incident of unknown class: " + ex.getMessage());

+			} catch (InvalidClassException ex) {

+				System.err.println("Dropping Incident of invalid class: " + ex.getMessage());

+			} catch (StreamCorruptedException ex) {

+				System.err.println("Unable to read Incident from packet: " + ex.getMessage());

+			} catch (OptionalDataException ex) {

+				System.err.println("Primitive data instead of Incident in packet: " + ex.getMessage());

+			} catch (IOException ex) {

+				throw new IllegalStateException("Unexpected IOException: " + ex.getMessage());

+			}

+		}

+

+		/** Bytes received in a datagram. */

+		private byte[] data;

+	}

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/DatagramLoggingActivityFactory.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/DatagramLoggingActivityFactory.java
new file mode 100644
index 0000000..fabdae7
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/DatagramLoggingActivityFactory.java
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.io.ByteArrayOutputStream;

+import java.io.IOException;

+import java.io.ObjectOutputStream;

+import java.net.DatagramPacket;

+import java.net.DatagramSocket;

+import java.net.InetAddress;

+import java.net.SocketException;

+import java.net.UnknownHostException;

+

+/**

+ * This activity factory produces activities that log their incidents using datagrams.  It

+ * examines the system properties to determine where to send the incidents.  The property

+ * <code>org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.host</code> (or

+ * <code>activity.host</code> if not defined) teslls to what host to send the datagrams.

+ * There's no default value, and it's an runtime exception if neither property's defined.

+ *

+ * <p>The property <code>org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.port</code> (or

+ * <code>activity.port</code> if not defined) tells to what port to send the datagrams.

+ * It defaults to 4556.

+ *

+ * <p>Once created, it records incidents by serializing them into a byte buffer and

+ * sending that buffer as a datagram to the activity host/port.  This does limit the size

+ * of incidents that can go over, but most incidents are pretty small.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public class DatagramLoggingActivityFactory implements ActivityFactory {

+	/**

+	 * Creates a new {@link DatagramLoggingActivityFactory} instance.

+	 */

+	public DatagramLoggingActivityFactory() {

+		String hostname = System.getProperty("org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.host",

+			System.getProperty("activity.host", ""));

+		port = Integer.getInteger("org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.port",

+			Integer.getInteger("activity.port", 4556)).intValue();

+		if (hostname.length() == 0)

+			throw new IllegalStateException("System property `org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.host'"

+				+ " (or simply `activity.host') not defined or is empty");

+		try {

+			host = InetAddress.getByName(hostname);

+			socket = new DatagramSocket();

+		} catch (UnknownHostException ex) {

+			throw new IllegalStateException("Activity host `" + host + "' unknown");

+		} catch (SocketException ex) {

+			throw new IllegalStateException("Cannot create anonymous datagram socket");

+		}

+	}

+

+	/**

+	 * Create an activity that records incidents in a UDP datagram.

+	 *

+	 * @return an {@link Activity} value.

+	 */

+	public Activity createActivity() {

+		return new Activity() {

+			public void recordIncident(Incident incident) {

+				try {

+					ByteArrayOutputStream baos = new ByteArrayOutputStream();

+					ObjectOutputStream oos = new ObjectOutputStream(baos);

+					oos.writeObject(incident);

+					oos.close();

+					baos.close();

+					byte[] buf = baos.toByteArray();

+					DatagramPacket packet = new DatagramPacket(buf, buf.length, host, port);

+					socket.send(packet);

+				} catch (IOException ignore) {}

+			}

+		};

+	}

+

+	/** To what host to send datagrams. */

+	InetAddress host;

+

+	/** To what port on {@link #host}. */

+	int port;

+

+	/** Transmission socket for datagrams. */

+	DatagramSocket socket;

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/History.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/History.java
new file mode 100644
index 0000000..ae9a507
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/History.java
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.List;

+import java.util.Timer;

+import java.util.TimerTask;

+

+/**

+ * A history of incidents to be stored in long-term storage.

+ *

+ * The <code>History</code> tracks Incidents that occurred during the course of an

+ * activity.  It's a temporary container for incidents before the activity is deemed

+ * complete and stored into whatever the long-term {@link Storage} is.  A

+ * <code>History</code> starts out with at least one {@link Incident} received from

+ * (usually remote) processing.  Other incidents arrive through {@link #addIncident} and

+ * must have the same ID.  Eventually, one of those incidents will be an

+ * <code>ActivityStopped</code> incident, which then schedules the History to commit

+ * itself.

+ *

+ * <p>It doesn't commit itself right away though; other incidents may arrive that are part

+ * of the activity out of order, so there's a delay of {@link #closeTime} milliseconds

+ * before it's sent to {@link Storage}.  Other incidents will be recorded during this delay.

+ *

+ * <p>It's also possible that the <code>ActivityStopped</code> incident never arrives from

+ * the process that deems the activity stopped.  In that case, the idle timer (which is

+ * reset whenever an incident arrives) determines when to put the <code>History</code>

+ * into its commital state.  The stop can arrive after this point (and will be recorded),

+ * but it otherwise doesn't affect the commit-to-close time.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+final class History {

+	/**

+	 * Creates a new {@link History} instance.

+	 *

+	 * @param initialIncident Incident which gives the history its ID.

+	 * @param storage Where to store the incidents when the history's done.

+	 */

+	History(Incident initialIncident, Storage storage) {

+		id = initialIncident.getActivityID();

+		this.storage = storage;

+		incidents.add(initialIncident);

+		scheduleExpiration();

+	}

+

+	/**

+	 * Add an incident to this history.

+	 *

+	 * @param incident an {@link Incident} value.

+	 */

+	synchronized void addIncident(Incident incident) {

+		if (!incident.getActivityID().equals(id))

+			throw new IllegalArgumentException("Incident's activity ID " + incident.getActivityID()

+				+ " doesn't match History's ID " + id);

+		if (incidents == null) return;

+		incidents.add(incident);

+		if (expireHistoryTask != null)

+			expireHistoryTask.cancel();

+		if (incident instanceof ActivityStopped)

+			commit();

+		else if (closeHistoryTask == null)

+			scheduleExpiration();

+	}

+

+	/**

+	 * Commit this history by starting the commit-to-close timer.

+	 */

+	private void commit() {

+		if (closeHistoryTask != null) return;

+		TIMER.schedule(closeHistoryTask = new CloseHistoryTask(), closeTime);

+	}

+

+	/**

+	 * Schedule expiration of this history due to idleness.

+	 */

+	private void scheduleExpiration() {

+		TIMER.schedule(expireHistoryTask = new ExpireHistoryTask(), idleTime);

+	}

+

+	/**

+	 * Close this history out by storing the incidents to long-term storage.

+	 */

+	private synchronized void close() {

+ 		Collections.sort(incidents);

+		storage.store(id, incidents);

+		incidents = null;

+	}

+

+	/** History's ID. */

+	private String id;

+

+	/** In what long-term storage to store incidents. */

+	private Storage storage;

+

+	/** Timer task that expires an idle history.  If null, this history is in commit-to-close state. */

+	private ExpireHistoryTask expireHistoryTask;

+

+	/** Timer task to close a history.  If nonnull, this history is in commit-to-close state. */ 

+	private CloseHistoryTask closeHistoryTask;

+

+	/** Incidents to store. */

+	private List incidents = new ArrayList();

+

+	/**

+	 * Timer task that expires (commits and closes) an idle history.

+	 */

+	private class ExpireHistoryTask extends TimerTask {

+		public void run() {

+			synchronized (History.this) {

+				// Check to see if a new expireHistoryTask got generated.

+				// If it did, it means a new incident got logged while we

+				// were about to expire the history.  But if the history's

+				// current expiration task is this task, then we're clear

+				// to commit the history, and any incidents that arrive

+				// won't reset it.

+				if (expireHistoryTask == this) commit();

+			}

+		}

+	}

+

+	/**

+	 * Timer task that gives time for more incidents to arrive before closing forever a history.

+	 */

+	private class CloseHistoryTask extends TimerTask {

+		public void run() {

+			close();

+		}

+	}

+

+	/** Only timer we'll ever need. */

+ 	private static final Timer TIMER = new Timer(/*isDaemon*/true);

+

+	/** How many milliseconds to wait before giving up on an idle history. */

+	static long idleTime = Long.getLong("org.apache.oodt.commons.activity.History.idle", 5*60*1000).longValue();

+

+	/** How many milliseconds to wait to give a history extra time to receive incidents before saving it to storage. */

+	static long closeTime = Long.getLong("org.apache.oodt.commons.activity.History.close", 5*60*1000).longValue();

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/Incident.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/Incident.java
new file mode 100644
index 0000000..e95293f
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/Incident.java
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.io.Serializable;

+import java.util.Date;

+

+/**

+ * An incident signifies some occurrence within an activity.

+ *

+ * @author Kelly

+ * @version $Revision: 1.3 $

+ */

+public class Incident implements Serializable, Comparable {

+	/**

+	 * Creates a new {@link Incident} instance, timestamping it.

+	 */

+	public Incident() {

+		time = new Date();

+	}

+

+	/**

+	 * Get the timestamp of this incident.

+	 *

+	 * @return a {@link Date} value.

+	 */

+	public Date getTime() {

+		return time;

+	}

+

+	/**

+	 * Get the ID of the activity to which the incident belongs.

+	 *

+	 * @return a {@link String} value.

+	 */

+	public String getActivityID() {

+		return id;

+	}

+

+	/**

+	 * Set the ID of the activity to which this incident belongs.

+	 *

+	 * @param id a {@link String} value.

+	 */

+	void setActivityID(String id) {

+		this.id = id;

+	}

+

+	/**

+	 * Two incidents are equal if they're the same object, or if they both have the

+	 * equal timestamps and either both their IDs are null or are equal.

+	 *

+	 * @param obj an {@link Object} value.

+	 * @return True if incidents are equal.

+	 */

+	public boolean equals(Object obj) {

+		if (obj == this) return true;

+		if (!(obj instanceof Incident)) return false;

+		Incident rhs = (Incident) obj;

+		return ((id == null && rhs.id == null) || id.equals(rhs.id)) && time.equals(rhs.time);

+	}

+

+	/**

+	 * Two incidents compare with each other mostly by their timestamps

+	 *

+	 * @param obj an {@link Object} value.

+	 * @return -1 if this object is less than <var>obj</var>, 0 if they're equal,

+	 * or 1 if this object is greater than <var>obj</var>

+	 */

+	public int compareTo(Object obj) {

+		Incident rhs = (Incident) obj;

+		int idComp = id == null && rhs.id != null? -1 : id == null && rhs.id == null? 0 : id != null && rhs.id == null? 1

+			: id.compareTo(rhs.id);

+		if (idComp == 0)

+			return time.compareTo(rhs.time);

+		else

+			return idComp;

+	}

+

+	public String toString() {

+		return getClass().getName();

+	}

+

+	public int hashCode() {

+		return time.hashCode() ^ (id == null? 0xaaaaaaaa : id.hashCode());

+	}

+

+	/** Timestamp of this incident. */

+	protected Date time;

+

+	/** ID of the activity to which this incident belongs. */

+	private String id;

+

+       /** Serial version unique ID. */

+       static final long serialVersionUID = -8119061795944984581L;

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/NullActivity.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/NullActivity.java
new file mode 100644
index 0000000..c6a1863
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/NullActivity.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+/**

+ * A null activity doesn't record any incidents.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public class NullActivity extends Activity {

+	/**

+	 * Ignore the incident.

+	 *

+	 * @param incident Ignored.

+	 */

+	public void recordIncident(Incident incident) {}

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/NullStorage.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/NullStorage.java
new file mode 100644
index 0000000..b4612fc
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/NullStorage.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.util.List;

+

+/**

+ * Null storage doesn't store any {@link Incident}s.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+class NullStorage implements Storage {

+	/**

+	 * Ignore the activity ID and the list of {@link Incident}s.

+	 *

+	 * @param id Ignored activity ID.

+	 * @param incidents Ignored incidents.

+	 */

+	public void store(String id, List incidents) {}

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/Retrieval.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/Retrieval.java
new file mode 100644
index 0000000..13e9024
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/Retrieval.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.sql.SQLException;

+import java.util.List;

+

+/**

+   Retrieval is a vehicle for getting activities and their associated incidents from {@link Storage}.

+

+   @author S. Hardman

+   @version $Revision: 1.1 $

+*/

+public interface Retrieval {

+

+   /**

+      Retrieve the list of activities.

+

+      @return A list of {@link StoredActivity} classes.

+      @throws ActivityException If an error occurs accessing the Storage.

+   */

+   List retrieve() throws ActivityException;

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/SQLDatabaseRetrieval.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/SQLDatabaseRetrieval.java
new file mode 100644
index 0000000..005cb40
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/SQLDatabaseRetrieval.java
@@ -0,0 +1,218 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons.activity;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+   <p>This class enables retrieval of activity incidents from just about
+   any database management system. It should support MySQL, PostgreSQL,
+   Oracle and Sybase.
+   </p>
+
+   <p>This class uses the following properties:
+   <ul>
+      <li><code>org.apache.oodt.commons.activity.SQLDatabaseRetrieval.driver</code><br>
+      Must contain the name of the JDBC driver class. See the following
+      examples:
+      <ul>
+         <li>com.mysql.jdbc.Driver</li>
+         <li>org.postgresql.Driver</li>
+         <li>oracle.jdbc.driver.OracleDriver</li>
+         <li>com.sybase.jdbc2.jdbc.SybDriver</li>
+      </ul>
+      </li>
+
+      <li><code>org.apache.oodt.commons.activity.SQLDatabaseRetrieval.url</code><br>
+      Must contain the URL specification for the target database. See the
+      following examples:
+      <ul>
+         <li>jdbc:mysql://host:port/database</li>
+         <li>jdbc:postgresql://host:port/database</li>
+         <li>jdbc:oracle:thin:@host:port:database</li>
+         <li>jdbc:sybase::Tds:host:port/database</li>
+      </ul>
+      </li>
+
+      <li><code>org.apache.oodt.commons.activity.SQLDatabaseRetrieval.user</code><br>
+      Must contain the user name for the target database.</li>
+
+      <li><code>org.apache.oodt.commons.activity.SQLDatabaseRetrieval.password</code><br>
+      Must contain the password for the target database.</li>
+
+   </ul>
+   </p>
+
+   <p>This class expects the following table to exist in the target
+   database (data types will vary depending on the vendor):<br>
+      <pre>
+      create table incidents (
+         activityID varchar(32) not null,
+         className varchar(255) not null,
+         occurTime bigint not null default 0,
+         detail text null,
+         primary key (activityID, className, occurTime))
+      </pre>
+   </p>
+
+   @author S. Hardman
+   @version $Revision: 1.1 $
+*/
+public class SQLDatabaseRetrieval implements Retrieval {
+
+   /** The database driver.
+   */
+   private String driver;
+
+   /** The URL for the database.
+   */
+   private String url;
+
+   /** The user name for the database.
+   */
+   private String user;
+
+   /** The password associated with the user name.
+   */
+   private String password;
+
+   /** The database connection.
+   */
+   private Connection connection;
+
+
+   /**
+      This constructor grabs the necessary system properties for the database connection.
+   */
+   public SQLDatabaseRetrieval() {
+
+      // Grab the properties and make sure they are all there.
+      driver = System.getProperty("org.apache.oodt.commons.activity.SQLDatabaseRetrieval.driver");
+      url = System.getProperty("org.apache.oodt.commons.activity.SQLDatabaseRetrieval.url");
+      user = System.getProperty("org.apache.oodt.commons.activity.SQLDatabaseRetrieval.user");
+      password = System.getProperty("org.apache.oodt.commons.activity.SQLDatabaseRetrieval.password");
+
+      if ((driver == null) || (url == null) || (user == null) || (password == null)) {
+         throw new IllegalStateException("SQLDatabaseRetrieval(): Required system properties `org.apache.oodt.commons.activity.SQLDatabaseRetrieval.[driver,url,user,password]' are not completely defined.");
+      }
+   }
+
+
+   /**
+      Retrieve the list of activities.
+
+      @return A list of {@link StoredActivity} classes.
+      @throws ActivityException If an error occurs opening or accessing the database.
+   */
+   public List retrieve() throws ActivityException {
+
+      Connection conn = null;
+      Statement stmt = null;
+      List activities = new ArrayList();
+
+      try {
+         conn = openConnection();
+         stmt = conn.createStatement();
+         String sqlCmd = "SELECT activityID, className, occurTime, detail FROM incidents ORDER BY activityID, occurTime";
+         String activityID = "";
+         StoredActivity activity = null;
+         ResultSet rs = stmt.executeQuery(sqlCmd);
+         while (rs.next()) {
+             String currActivityID = rs.getString(1);
+             if (!activityID.equals(currActivityID)) {
+                activity = new StoredActivity(currActivityID);
+                activities.add(activity);
+                activityID = currActivityID;
+             }
+             activity.addIncident(new StoredIncident(rs.getString(2), rs.getLong(3), rs.getString(4)));
+         }
+
+         return (activities);
+      }
+      catch (ClassNotFoundException e) {
+         throw new ActivityException("SQLDatabaseRetrieval.retrieve(): An exception occurred locating the JDBC driver class.", e);
+      }
+      catch (SQLException e) {
+         throw new ActivityException("SQLDatabaseRetrieval.retrieve(): An exception occurred opening or accessing the database.", e);
+      }
+      finally {
+         try {
+            if (stmt != null) stmt.close();
+            if (conn != null) conn.close();
+         }
+         catch (SQLException e) {}
+      }
+   }
+
+
+   /**
+      This method opens the database connection.
+
+      @returns The Connection object.
+      @throws ClassNotFoundException If the JDBC driver class can't be located.
+      @throws SQLException If an error occurs opening the database connection.
+   */
+	private Connection openConnection() throws ClassNotFoundException, SQLException {
+      Class.forName(driver);
+      return (DriverManager.getConnection(url, user, password));
+   }
+
+
+   /**
+      Execute the SQLDatabaseRetrieval class via the command-line.
+
+      The program exits with status 0 on success, 1 on failure.
+
+      @param argv The command-line arguments.
+   */
+   public static void main(String[] argv) {
+
+      try {
+         SQLDatabaseRetrieval retrieval = new SQLDatabaseRetrieval();
+         List activities = retrieval.retrieve();
+         for (Iterator i = activities.iterator(); i.hasNext();) {
+            StoredActivity activity = (StoredActivity) i.next();
+            System.out.println("Activity: " + activity.getActivityID());
+            List incidents = activity.getIncidents();
+            for (Iterator j = incidents.iterator(); j.hasNext();) {
+               StoredIncident incident = (StoredIncident) j.next();
+               System.out.println("   Incident: " + incident.getClassName() + ", " + incident.getOccurTime() + ", " + incident.getDetail());
+            }
+         }
+         System.exit(0);
+      }
+      catch (Exception e) {
+         Throwable cause = e.getCause();
+         String message = "";
+         if (cause != null) {
+            System.err.println(e.getMessage() + " Additional information: " + cause.getMessage());
+         }
+         else {
+            System.err.println(e.getMessage());
+         }
+         System.exit(1);
+      }
+   }
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/SQLDatabaseStorage.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/SQLDatabaseStorage.java
new file mode 100644
index 0000000..0aa6f2a
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/SQLDatabaseStorage.java
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons.activity;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+import java.util.List;
+import javax.sql.DataSource;
+
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+
+/**
+ * <p>
+ * This class enables storage of activity incidents in just about any database
+ * management system. It should support MySQL, PostgreSQL, Oracle and Sybase.
+ * </p>
+ * 
+ * <p>
+ * This class uses the following properties:
+ * <ul>
+ * <li><code>org.apache.oodt.commons.activity.SQLDatabaseStorage.driver</code><br>
+ * Must contain the name of the JDBC driver class. See the following examples:
+ * <ul>
+ * <li>com.mysql.jdbc.Driver</li>
+ * <li>org.postgresql.Driver</li>
+ * <li>oracle.jdbc.driver.OracleDriver</li>
+ * <li>com.sybase.jdbc2.jdbc.SybDriver</li>
+ * </ul>
+ * </li>
+ * 
+ * <li><code>org.apache.oodt.commons.activity.SQLDatabaseStorage.url</code><br>
+ * Must contain the URL specification for the target database. See the following
+ * examples:
+ * <ul>
+ * <li>jdbc:mysql://host:port/database</li>
+ * <li>jdbc:postgresql://host:port/database</li>
+ * <li>jdbc:oracle:thin:@host:port:database</li>
+ * <li>jdbc:sybase::Tds:host:port/database</li>
+ * </ul>
+ * </li>
+ * 
+ * <li><code>org.apache.oodt.commons.activity.SQLDatabaseStorage.user</code><br>
+ * Must contain the user name for the target database.</li>
+ * 
+ * <li><code>org.apache.oodt.commons.activity.SQLDatabaseStorage.password</code>
+ * <br>
+ * Must contain the password for the target database.</li>
+ * 
+ * </ul>
+ * </p>
+ * 
+ * <p>
+ * This class expects the following table to exist in the target database (data
+ * types will vary depending on the vendor):<br>
+ * 
+ * <pre>
+ * create table incidents (
+ *          activityID varchar(32) not null,
+ *          className varchar(255) not null,
+ *          occurTime bigint not null default 0,
+ *          detail text null,
+ *          primary key (activityID, className, occurTime))
+ * </pre>
+ * 
+ * </p>
+ * 
+ * @author S. Hardman
+ * @version $Revision: 1.2 $
+ */
+public class SQLDatabaseStorage implements Storage {
+
+  /**
+   * The data source;
+   */
+  private DataSource ds;
+
+  /**
+   * Constructor given no arguments.
+   * 
+   * This constructor grabs the necessary system properties and opens the
+   * database connection based on the property values.
+   */
+  public SQLDatabaseStorage() {
+
+    // Grab the properties and make sure they are all there.
+    String driver = System
+        .getProperty("org.apache.oodt.commons.activity.SQLDatabaseStorage.driver");
+    String url = System
+        .getProperty("org.apache.oodt.commons.activity.SQLDatabaseStorage.url");
+    String user = System
+        .getProperty("org.apache.oodt.commons.activity.SQLDatabaseStorage.user");
+    String password = System
+        .getProperty("org.apache.oodt.commons.activity.SQLDatabaseStorage.password");
+
+    if ((driver == null) || (url == null) || (user == null)
+        || (password == null)) {
+      throw new IllegalStateException(
+          "SQLDatabaseStorage(): Required system properties `org.apache.oodt.commons.activity.SQLDatabaseStorage.[driver,url,user,password]' are not completely defined.");
+    }
+
+    this.ds = DatabaseConnectionBuilder.buildDataSource(user, password, driver,
+        url);
+  }
+
+  /**
+   * This method stores the list of incidents for the activity in the database
+   * table named "incidents".
+   * 
+   * @param id
+   *          The activity identifier.
+   * @param incidents
+   *          A list of {@link Incident}.
+   */
+  public void store(String id, List incidents) {
+    Statement statement = null;
+    Connection conn = null;
+
+    try {
+      conn = this.ds.getConnection();
+      statement = conn.createStatement();
+      for (Iterator i = incidents.iterator(); i.hasNext();) {
+        Incident incident = (Incident) i.next();
+        statement
+            .executeUpdate("insert into incidents (activityID, className, occurTime, detail) values ('"
+                + id
+                + "', '"
+                + incident.getClass().getName()
+                + "', "
+                + incident.getTime().getTime()
+                + ", '"
+                + escapeSingleQuote(incident.toString()) + "')");
+      }
+    } catch (SQLException e) {
+      System.err
+          .println("SQLDatabaseStorage.store(): Ignoring an exception that occurred while inserting a row into the database. Specifically, exception '"
+              + e.getClass().getName()
+              + "' occurred with message '"
+              + e.getMessage() + "'");
+    } finally {
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (SQLException ignore) {
+        }
+        conn = null;
+        conn = null;
+      }
+    }
+  }
+
+  /**
+   * This method closes the database connection.
+   * 
+   * @throws Throwable
+   *           If something goes wrong.
+   */
+  public void finalize() throws Throwable {
+    this.ds = null;
+    super.finalize();
+  }
+
+  /**
+   * This method will escape any single quotes found in the input string and
+   * return the escaped string. This will ready the string for insertion into a
+   * database. The single quote is escaped by inserting an additional single
+   * quote in front of it in the string. If some considerate developer has
+   * already escaped the single quotes in the input string, this method will
+   * essentially do nothing.
+   * 
+   * @param inputString
+   *          The string to be escaped.
+   * @return The escaped string.
+   */
+  public static String escapeSingleQuote(String inputString) {
+    int index = inputString.indexOf('\'');
+    if (index == -1) {
+      return (inputString);
+    }
+
+    String outputString = inputString;
+    while (index != -1) {
+
+      // If the single quote is the last character in the string or
+      // the next character is not another single quote, insert a
+      // single quote in front of the current single quote.
+      if ((index == (outputString.length() - 1))
+          || (outputString.charAt(index + 1) != '\'')) {
+        outputString = outputString.substring(0, index) + "'"
+            + outputString.substring(index);
+      }
+
+      // If we are not at the end of the string, check for another
+      // single quote.
+      if ((index + 2) <= (outputString.length() - 1)) {
+        index = outputString.indexOf('\'', index + 2);
+      } else {
+        index = -1;
+      }
+    }
+    return (outputString);
+  }
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/StandardOutputStorage.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/StandardOutputStorage.java
new file mode 100644
index 0000000..997cab3
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/StandardOutputStorage.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.io.OutputStreamWriter;

+

+/**

+ * Storage that sends activity reports to the standard output as plain text.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public class StandardOutputStorage extends WriterStorage {

+	/**

+	 * Creates a new {@link StandardOutputStorage} instance.

+	 */

+	public StandardOutputStorage() {

+		super(new OutputStreamWriter(System.out));

+	}

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/Storage.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/Storage.java
new file mode 100644
index 0000000..4e73384
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/Storage.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.util.List;

+

+/**

+ * A Storage is a place to store for the long term record an activity and the incidents

+ * that define it.

+ *

+ * @author Kelly

+ * @version $Revision: 1.2 $

+ */

+public interface Storage {

+	/**

+	 * Store the activity.

+	 *

+	 * @param id Activity ID.

+	 * @param incidents a {@link List} of {@link Incident}s that defined it.

+	 */

+	void store(String id, List incidents);

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/StoredActivity.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/StoredActivity.java
new file mode 100644
index 0000000..bce4b34
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/StoredActivity.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons.activity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+   This class holds an activity retrieved from storage.
+
+   @author S. Hardman
+   @version $Revision: 1.1 $
+   @see StoredIncident
+*/
+public class StoredActivity {
+
+   /** The identifier for the activity.
+   */
+   private String activityID;
+
+   /** The list of incidents associated with the activity.
+   */
+   private List incidents;
+
+
+   /**
+      This contructor initializes the activity.
+
+      @param activityID The identifier for the activity.
+   */
+   public StoredActivity(String activityID) {
+      this.activityID = activityID;
+      incidents = new ArrayList();
+   }
+
+
+   /**
+      Add an incident to the list of incidents.
+
+      @param incident The StoredIncident class to add to the list.
+   */
+   public void addIncident(StoredIncident incident) {
+      incidents.add(incident);
+   }
+
+   /**
+      Return the activity identifier.
+
+      @return The activity identifier.
+   */
+   public final String getActivityID() {
+      return (activityID);
+   }
+
+
+   /**
+      Return the list of associated incidents.
+
+      @return The list of associated incidents.
+   */
+   public final List getIncidents() {
+      return (incidents);
+   }
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/StoredIncident.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/StoredIncident.java
new file mode 100644
index 0000000..fd72552
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/StoredIncident.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons.activity;
+
+
+/**
+   This class holds an incident retrieved from storage.
+
+   @author S. Hardman
+   @version $Revision: 1.1 $
+   @see StoredActivity
+*/
+public class StoredIncident {
+
+   /** The name of the incident class.
+   */
+   private String className;
+
+   /** The time the incident occurred.
+   */
+   private long occurTime;
+
+   /** Detailed information regarding the incident.
+   */
+   private String detail;
+
+
+   /**
+      This contructor initializes the incident.
+
+      @param className The name of the incident class.
+      @param occurTime The time the incident occurred.
+      @param detail Detailed information regarding the incident.
+   */
+   public StoredIncident(String className, long occurTime, String detail) {
+      this.className = className;
+      this.occurTime = occurTime;
+      this.detail = detail;
+   }
+
+
+   /**
+      Return the name of the incident class.
+
+      @return The name of the incident class.
+   */
+   public final String getClassName() {
+      return (className);
+   }
+
+
+   /**
+      Return the time the incident occurred.
+
+      @return The time the incident occurred.
+   */
+   public final long getOccurTime() {
+      return (occurTime);
+   }
+
+
+   /**
+      Return the detailed information regarding the incident.
+
+      @return The detailed information regarding the incident.
+   */
+   public final String getDetail() {
+      return (detail);
+   }
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/WriterStorage.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/WriterStorage.java
new file mode 100644
index 0000000..25cff9a
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/WriterStorage.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.util.List;

+import java.io.Writer;

+import java.io.PrintWriter;

+

+/**

+ * Storage that sends activity reports to a {@link Writer} as plain text.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public abstract class WriterStorage implements Storage {

+	/**

+	 * Creates a new {@link WriterStorage} instance.

+	 *

+	 * @param writer Where to write activity reports.

+	 */

+	protected WriterStorage(Writer writer) {

+		this.writer = new PrintWriter(writer, /*autoflush*/true);

+	}

+

+	/**

+	 * Write a line of text for a stored activity.

+	 *

+	 * The format is <code><var>activityID</var>[<var>incident</var>,<var>incident</var>...]</code>.

+	 *

+	 * @param id a {@link String} value.

+	 * @param incidents a {@link List} value.

+	 */

+	public void store(String id, List incidents) {

+		writer.println(id + incidents);

+	}

+

+	/** Where to send the text. */

+	protected PrintWriter writer;

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/XMLStandardOutputStorage.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/XMLStandardOutputStorage.java
new file mode 100644
index 0000000..4449877
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/XMLStandardOutputStorage.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.io.IOException;

+import javax.xml.transform.Transformer;

+import javax.xml.transform.TransformerException;

+import javax.xml.transform.TransformerFactory;

+import javax.xml.transform.dom.DOMSource;

+import javax.xml.transform.stream.StreamResult;

+import org.w3c.dom.Document;

+

+/**

+ * Simple storage that writes XML documents describing activities to the standard output.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public class XMLStandardOutputStorage extends XMLStorage {

+	/**

+	 * Creates a new {@link XMLStandardOutputStorage} instance.

+	 */

+	public XMLStandardOutputStorage() {

+		super();

+		factory = TransformerFactory.newInstance();

+	}

+

+	protected void saveDocument(Document doc) throws IOException {

+		try {

+			Transformer transformer = factory.newTransformer();

+			DOMSource source = new DOMSource(doc);

+			StreamResult result = new StreamResult(System.out);

+			transformer.transform(source, result);

+			System.out.println();

+		} catch (TransformerException ex) {

+			throw new IllegalStateException("Unexpected TransformerException: " + ex.getMessage());

+		}

+	}

+

+	/** Factory for transformers that serialize XML documents into plain text. */ 

+	private TransformerFactory factory;

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/XMLStorage.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/XMLStorage.java
new file mode 100644
index 0000000..d171ac1
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/activity/XMLStorage.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.io.IOException;

+import java.util.Iterator;

+import java.util.List;

+import javax.xml.parsers.DocumentBuilder;

+import javax.xml.parsers.DocumentBuilderFactory;

+import javax.xml.parsers.ParserConfigurationException;

+import org.w3c.dom.Document;

+import org.w3c.dom.Element;

+

+/**

+ * Storage that saves activities as XML documents.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public abstract class XMLStorage implements Storage {

+	/**

+	 * Creates a new {@link XMLStorage} instance.

+	 */

+	protected XMLStorage() {

+		factory = DocumentBuilderFactory.newInstance();

+	}

+

+	public void store(String id, List incidents) {

+		try {

+			DocumentBuilder builder = factory.newDocumentBuilder();

+			Document doc = builder.newDocument();

+			Element root = doc.createElement("activity");

+			root.setAttribute("id", id);

+			doc.appendChild(root);

+

+			for (Iterator i = incidents.iterator(); i.hasNext();) {

+				Incident incident = (Incident) i.next();

+				Element e = doc.createElement(incident.getClass().getName());

+				e.setAttribute("time", String.valueOf(incident.getTime().getTime()));

+				e.appendChild(doc.createTextNode(incident.toString()));

+				root.appendChild(e);

+			}

+			saveDocument(doc);

+		} catch (ParserConfigurationException ex) {

+			throw new IllegalStateException("Unexpected ParserConfigurationException: " + ex.getMessage());

+		} catch (IOException ex) {

+			System.err.println("Unable to save activity " + id + " due to " + ex.getClass().getName() + ": "

+				+ ex.getMessage());

+			ex.printStackTrace();

+		}

+	}

+

+	/**

+	 * Save a completed activity record.

+	 *

+	 * @param doc XML document containing the activity's incidents.

+	 * @throws IOException if an error occurs.

+	 */

+	protected abstract void saveDocument(Document doc) throws IOException;

+

+	/** Factory for document builders which we use to create XML documents. */

+	protected DocumentBuilderFactory factory;

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/database/DatabaseConnectionBuilder.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/database/DatabaseConnectionBuilder.java
new file mode 100644
index 0000000..b3c0f77
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/database/DatabaseConnectionBuilder.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.commons.database;
+
+//JDK imports
+import javax.sql.DataSource;
+
+//APACHE imports
+import org.apache.commons.dbcp.ConnectionFactory;
+import org.apache.commons.dbcp.DriverManagerConnectionFactory;
+import org.apache.commons.dbcp.PoolableConnectionFactory;
+import org.apache.commons.dbcp.PoolingDataSource;
+import org.apache.commons.pool.impl.GenericObjectPool;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A class to build database connections from JDBC information.
+ * </p>.
+ */
+public final class DatabaseConnectionBuilder {
+
+    public static final DataSource buildDataSource(String user, String pass,
+            String driver, String url) {
+
+        DataSource ds = null;
+
+        try {
+            Class.forName(driver);
+        } catch (ClassNotFoundException ignore) {
+        }
+
+        GenericObjectPool connectionPool = new GenericObjectPool(null);
+        ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
+                url, user, pass);
+        PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(
+                connectionFactory, connectionPool, null, null, false, true);
+
+        ds = new PoolingDataSource(connectionPool);
+
+        return ds;
+    }
+
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/database/SqlScript.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/database/SqlScript.java
new file mode 100644
index 0000000..1127293
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/database/SqlScript.java
@@ -0,0 +1,257 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.commons.database;
+
+//JDK imports
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import javax.sql.DataSource;
+
+/**
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Abstract layer around a SQL script
+ * </p>.
+ */
+public class SqlScript {
+
+    public final static char QUERY_ENDS = ';';
+
+    private File script;
+
+    private DataSource ds;
+
+    private boolean useBatch = true;
+
+    private List statementList = null;
+
+    /**
+     * @param args
+     * @throws SQLException
+     */
+
+    public SqlScript(String scriptFileName, DataSource ds) throws SQLException {
+        script = new File(scriptFileName);
+        statementList = new Vector();
+        this.ds = ds;
+    }
+
+    public static void main(String[] args) {
+        String usage = "SqlScript [options] </path/to/sql/file>\n"
+                + "--user <user>\n" + "--pass <pass>\n" + "--url <jdbc url>\n"
+                + "--driver <java class spec>\n";
+
+        String user = null, pass = null, url = null, driver = null;
+        String sqlScriptFilePath = null;
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--user")) {
+                user = args[++i];
+            } else if (args[i].equals("--pass")) {
+                pass = args[++i];
+            } else if (args[i].equals("--driver")) {
+                driver = args[++i];
+            } else if (args[i].equals("--url")) {
+                url = args[++i];
+            } else if (!args[i].startsWith("--")) {
+                sqlScriptFilePath = args[i];
+            }
+        }
+
+        if (user == null || pass == null || url == null || driver == null
+                || sqlScriptFilePath == null) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        DataSource ds = DatabaseConnectionBuilder.buildDataSource(user, pass,
+                driver, url);
+
+        try {
+            SqlScript sqlScript = new SqlScript(sqlScriptFilePath, ds);
+            sqlScript.loadScript();
+            sqlScript.execute();
+
+        } catch (SQLException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+    }
+
+    public void loadScript() throws IOException {
+        BufferedReader reader = new BufferedReader(new FileReader(script));
+
+        try {
+            String line = null;
+            StringBuffer query = new StringBuffer();
+            boolean queryEnds = false;
+
+            while ((line = reader.readLine()) != null) {
+                if (isComment(line))
+                    continue;
+                queryEnds = checkStatementEnds(line);
+                query.append(line);
+                if (queryEnds) {
+                    statementList.add(query.toString());
+                    query.setLength(0);
+                }
+            }
+        }
+        finally {
+            reader.close();
+        }
+    }
+
+    public void execute() throws SQLException {
+        if (useBatch) {
+            doExecuteBatch();
+        } else {
+            if (statementList != null && statementList.size() > 0) {
+                for (Iterator i = statementList.iterator(); i.hasNext();) {
+                    String sqlStatement = (String) i.next();
+                    doExecuteIndividual(sqlStatement);
+
+                }
+
+            }
+
+        }
+    }
+
+    /**
+     * @return the useBatch
+     */
+    public boolean isUseBatch() {
+        return useBatch;
+    }
+
+    /**
+     * @param useBatch
+     *            the useBatch to set
+     */
+    public void setUseBatch(boolean useBatch) {
+        this.useBatch = useBatch;
+    }
+
+    private boolean isComment(String line) {
+        if ((line != null) && (line.length() > 0))
+            return (line.charAt(0) == '#');
+        return false;
+    }
+
+    private boolean checkStatementEnds(String s) {
+        return (s.indexOf(QUERY_ENDS) != -1);
+    }
+
+    private void doExecuteIndividual(String sql) {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = ds.getConnection();
+            statement = conn.createStatement();
+
+            statement.execute(sql);
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+            System.out.println("Exception executing SQL: [" + sql
+                    + "]: message: " + e.getMessage());
+
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (Exception ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+                } catch (Exception ignore) {
+                }
+
+                conn = null;
+            }
+        }
+    }
+
+    private void doExecuteBatch() {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            if (statementList != null && statementList.size() > 0) {
+                conn = ds.getConnection();
+                statement = conn.createStatement();
+
+                for (Iterator i = statementList.iterator(); i.hasNext();) {
+                    String sqlStatement = (String) i.next();
+                    statement.addBatch(sqlStatement);
+                }
+
+                statement.executeBatch();
+            }
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+            System.out
+                    .println("Exception executing SQL batch statement: message: "
+                            + e.getMessage());
+
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (Exception ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+                } catch (Exception ignore) {
+                }
+
+                conn = null;
+            }
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/date/DateUtils.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/date/DateUtils.java
new file mode 100644
index 0000000..188a5eb
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/date/DateUtils.java
@@ -0,0 +1,240 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.commons.date;
+
+//JDK imports
+import java.text.DecimalFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class DateUtils {
+
+    public static enum FormatType { UTC_FORMAT, LOCAL_FORMAT, TAI_FORMAT };
+    
+    public static Calendar tai93epoch = new GregorianCalendar(1993, GregorianCalendar.JANUARY, 1);
+    
+    public static Calendar julianEpoch = new GregorianCalendar(1970, GregorianCalendar.JANUARY, 1);
+    
+    private static SimpleDateFormat utcFormat = new SimpleDateFormat(
+            "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+    private static SimpleDateFormat taiFormat = new SimpleDateFormat(
+            "yyyy-MM-dd'T'HH:mm:ss.SSS");
+    private static SimpleDateFormat localFormat = new SimpleDateFormat(
+            "yyyy-MM-dd'T'HH:mm:ss.SSSZ");    
+    
+    static {
+        utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+        taiFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+    }
+    
+    static enum IndexType {
+        DATE(0),
+        LEAP_SECS(1);
+        
+        public int index;
+        
+        IndexType(int index) {
+            this.index = index;
+        }
+    }
+    
+    //Info taken from ftp://oceans.gsfc.nasa.gov/COMMON/leapsec.dat
+    static long[][] dateAndLeapSecs = {
+        { 0 , 10 },
+        { new GregorianCalendar(1972, GregorianCalendar.JULY,    1).getTimeInMillis() , 11 },
+        { new GregorianCalendar(1973, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 12 },
+        { new GregorianCalendar(1974, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 13 },
+        { new GregorianCalendar(1975, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 14 },
+        { new GregorianCalendar(1976, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 15 },
+        { new GregorianCalendar(1977, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 16 },
+        { new GregorianCalendar(1978, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 17 },
+        { new GregorianCalendar(1979, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 18 },
+        { new GregorianCalendar(1980, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 19 },
+        { new GregorianCalendar(1981, GregorianCalendar.JULY,    1).getTimeInMillis() , 20 },
+        { new GregorianCalendar(1982, GregorianCalendar.JULY,    1).getTimeInMillis() , 21 },
+        { new GregorianCalendar(1983, GregorianCalendar.JULY,    1).getTimeInMillis() , 22 },
+        { new GregorianCalendar(1985, GregorianCalendar.JULY,    1).getTimeInMillis() , 23 },
+        { new GregorianCalendar(1988, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 24 },
+        { new GregorianCalendar(1990, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 25 },
+        { new GregorianCalendar(1991, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 26 },
+        { new GregorianCalendar(1992, GregorianCalendar.JULY,    1).getTimeInMillis() , 27 },
+        { new GregorianCalendar(1993, GregorianCalendar.JULY,    1).getTimeInMillis() , 28 },
+        { new GregorianCalendar(1994, GregorianCalendar.JULY,    1).getTimeInMillis() , 29 },
+        { new GregorianCalendar(1996, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 30 },
+        { new GregorianCalendar(1997, GregorianCalendar.JULY,    1).getTimeInMillis() , 31 },
+        { new GregorianCalendar(1999, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 32 },
+        { new GregorianCalendar(2006, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 33 },
+        { new GregorianCalendar(2009, GregorianCalendar.JANUARY, 1).getTimeInMillis() , 34 },
+    };
+    
+    private DateUtils() {}
+    
+    public static int getLeapSecsForDate(Calendar utcCal) throws Exception {
+        long timeInMillis = utcCal.getTimeInMillis();
+        for (int i = dateAndLeapSecs.length - 1; i >= 0; i--) {
+            if (dateAndLeapSecs[i][IndexType.DATE.index] < timeInMillis)
+                return (int) dateAndLeapSecs[i][IndexType.LEAP_SECS.index];
+        }
+        throw new Exception("No Leap Second found for given date!");
+    }
+    
+    public static synchronized Calendar toTai(Calendar cal) throws Exception {
+        Calendar taiCal = Calendar.getInstance(createTaiTimeZone(getLeapSecsForDate(cal)));
+        taiCal.setTimeInMillis(cal.getTimeInMillis() + getLeapSecsForDate(cal) * 1000);
+        return taiCal;
+    }
+    
+    private static synchronized Calendar taiToUtc(Calendar taiCal) throws Exception {
+        Calendar calUtc = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+        calUtc.setTimeInMillis(taiCal.getTimeInMillis() - taiCal.getTimeZone().getRawOffset());
+        return calUtc;
+    }
+    
+    private static Calendar taiToLocal(Calendar taiCal) throws Exception {
+        return toLocal(taiToUtc(taiCal));
+    }
+
+    public static synchronized Calendar toLocal(Calendar cal) throws Exception {
+        if (cal.getTimeZone().getID().equals("TAI")) {
+            return taiToLocal(cal);
+        } else {
+            Calendar calLocal = Calendar.getInstance();
+            calLocal.setTimeInMillis(cal.getTimeInMillis());
+            return calLocal;
+        }
+    }
+
+    public static synchronized Calendar toUtc(Calendar cal) throws Exception {
+        if (cal.getTimeZone().getID().equals("TAI")) {
+            return taiToUtc(cal);
+        } else {
+            Calendar calUtc = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+            calUtc.setTimeInMillis(cal.getTimeInMillis());
+            return calUtc;   
+        }
+    }
+    
+    public static Calendar getCurrentUtcTime() throws Exception {
+        return toUtc(getCurrentLocalTime());
+    }
+    
+    public static Calendar getCurrentLocalTime() throws Exception {
+        return Calendar.getInstance();
+    }
+    
+    public static Calendar getCurrentTaiTime() throws Exception {
+        return toTai(getCurrentUtcTime());
+    }
+    
+    public static String toCustomLocalFormat(Calendar cal, String format) {
+        return new SimpleDateFormat(format).format(cal.getTime());
+    }
+    
+    public static String toString(Calendar cal) {
+        String timeZoneId = cal.getTimeZone().getID();
+        if (timeZoneId.equals("UTC")) {
+            return utcFormat.format(cal.getTime());
+        }else if (timeZoneId.equals("TAI")) {
+            return taiFormat.format(cal.getTime()) + "-0000" 
+                + (cal.getTimeZone().getRawOffset() / 1000);
+        }else {
+            return localFormat.format(cal.getTime());
+        }
+    }
+    
+    public static synchronized Calendar toLocalCustomFormatCalendar(String calString, String format) throws ParseException {
+        Calendar localCal = Calendar.getInstance();
+        localCal.setTime(new SimpleDateFormat(format).parse(calString));
+        return localCal;
+    }
+    
+    public static synchronized Calendar toCalendar(String calString, FormatType formatType)
+            throws ParseException {
+        Calendar cal = Calendar.getInstance();
+        switch (formatType) {
+            case LOCAL_FORMAT:
+                cal.setTimeInMillis(localFormat.parse(calString).getTime());
+                break;
+            case TAI_FORMAT:
+                cal.setTimeZone(createTaiTimeZone(Integer.parseInt(calString
+                    .substring(calString.length() - 2))));
+                calString = calString.substring(0, calString.length() - 5);
+                cal.setTimeInMillis(taiFormat.parse(calString).getTime());
+                break;
+            case UTC_FORMAT:
+                cal.setTimeZone(TimeZone.getTimeZone("UTC"));
+                cal.setTimeInMillis(utcFormat.parse(calString).getTime());
+                break;
+            default:
+                cal.setTimeInMillis(localFormat.parse(calString).getTime());
+        }
+        return cal;
+    }
+    
+    public static double getTimeInSecs(Calendar cal, Calendar epoch) throws Exception {
+        return getTimeInMillis(cal, epoch) / 1000.0;
+    }
+    
+    public static String toString(double seconds) {
+        return new DecimalFormat("#.000").format(seconds);
+    }
+    
+    public static long getTimeInMillis(Calendar cal, Calendar epoch) throws Exception {
+        long epochDiffInMilli;
+        /**
+         * Fixes date conversion issues preventing tests passing in the UK but working elsewhere in the world.
+         */
+        if(julianEpoch.getTimeZone().getID().equals("Europe/London")){
+            epochDiffInMilli = epoch.getTimeInMillis() - (julianEpoch.getTimeInMillis()+julianEpoch.getTimeZone().getOffset(julianEpoch.getTimeInMillis())) ;
+        }else {
+            epochDiffInMilli = epoch.getTimeInMillis() - julianEpoch.getTimeInMillis() ;
+        }
+        if (cal.getTimeZone().getID().equals("TAI"))
+            epochDiffInMilli += getLeapSecsForDate(epoch) * 1000;
+        long milliseconds = cal.getTimeInMillis();
+        return milliseconds - epochDiffInMilli;
+    }
+    
+    private static TimeZone createTaiTimeZone(int leapSecs) {
+        return new SimpleTimeZone(leapSecs * 1000, "TAI");
+    }
+    
+    public static void main(String[] args) throws Exception {
+        Calendar curTime = getCurrentLocalTime();
+        System.out.println("Test Time: " + toString(toCalendar(toString(toTai(toCalendar("2008-01-20T16:29:55.000Z", 
+                FormatType.UTC_FORMAT))), FormatType.TAI_FORMAT)));
+        System.out.println("Current Local Time: " + toString(curTime) + " " + curTime.getTimeInMillis());
+        System.out.println("Current UTC Time: " + toString((curTime = toCalendar("2008-01-20T16:29:55.000Z", 
+                FormatType.UTC_FORMAT))) + " " + toString(getTimeInSecs(curTime, tai93epoch)));
+        System.out.println("Current TAI Time: " + toString((curTime = toTai(toCalendar("2008-01-20T16:29:55.000Z", 
+                FormatType.UTC_FORMAT)))) + " " + toString(getTimeInSecs(curTime, tai93epoch)));
+        System.out.println("Current UTC Time: " + toString(taiToUtc(curTime)));
+    }
+    
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/exec/EnvUtilities.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/exec/EnvUtilities.java
new file mode 100644
index 0000000..ae06eac
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/exec/EnvUtilities.java
@@ -0,0 +1,174 @@
+/*

+ * 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.

+ */

+

+

+package org.apache.oodt.commons.exec;

+

+//JDK imports

+import java.io.BufferedReader;

+import java.io.ByteArrayInputStream;

+import java.io.IOException;

+import java.io.InputStream;

+import java.io.InputStreamReader;

+import java.util.Map;

+import java.util.Properties;

+import java.util.logging.Level;

+import java.util.logging.Logger;

+

+/**

+ * @author mattmann

+ * @author bfoster

+ * @author mstarch

+ * @version $Revision$

+ * 

+ * <p>

+ * Environment Utilities for reading variables and setting them and such.

+ * </p>.

+ */

+public final class EnvUtilities {

+

+    private static final Logger LOG = Logger.getLogger(EnvUtilities.class

+            .getName());

+

+    private EnvUtilities() throws InstantiationException {

+        throw new InstantiationException("Don't construct utility classes!");

+    }

+

+    /**

+     * This method returns a particular named environment variable from the user's

+     * working environment using the {@link #getEnv()} method to grab that environment.

+     * 

+     * @param envVarName The named environment variable to return.

+     * @return The environment variable value, as a String.

+     */

+    public static String getEnv(String envVarName) {

+        return System.getenv(envVarName);

+    }

+

+    /**

+     * This method does exactly the same thing as {@link #getEnvUsingWaitFor()},

+     * except it uses System.getenv()

+     * 

+     * @return The user's current environment, in a {@link Properties} object.

+     */

+    public static Properties getEnv() {

+        Properties envProps = new Properties();

+        for (Map.Entry<String, String> entry : System.getenv().entrySet())

+            envProps.setProperty(entry.getKey(), entry.getValue());

+        return envProps;

+    }

+

+    /**

+     * This method grabs the current environment using the Linux shell program

+     * called <code>env</code>. Unfortunately, this method also uses

+     * {@link Process#waitFor()}, which seems to hang when folks have weird

+     * environment variables and such.

+     * 

+     * A more appropriate method to call is {@link #getEnv()} because it uses

+     * the {@link ExecHelper} class, which seems to handle process termination a

+     * bit more elegantly.

+     * 

+     * @deprecated

+     * @return A {@link Properites} object containing the user's current

+     *         environment variables.

+     */

+    public static Properties getEnvUsingWaitFor() {

+        String commandLine = "env";

+

+        Process p = null;

+        Properties envProps = null;

+

+        try {

+            p = Runtime.getRuntime().exec(commandLine);

+            int retVal = p.waitFor();

+            envProps = new Properties();

+            envProps.load(preProcessInputStream(p.getInputStream()));

+        } catch (Exception e) {

+            e.printStackTrace();

+            LOG.log(Level.WARNING, "Error executing env command: Message: "

+                    + e.getMessage());

+        } finally {

+            try {

+                if (p.getErrorStream() != null)

+                    p.getErrorStream().close();

+            } catch (Exception e) {

+            }

+            try {

+                if (p.getInputStream() != null)

+                    p.getInputStream().close();

+            } catch (Exception e) {

+            }

+            try {

+                if (p.getOutputStream() != null)

+                    p.getOutputStream().close();

+            } catch (Exception e) {

+            }

+        }

+

+        return envProps;

+    }

+

+    /**

+     * This method turns an {@link InputStream} into a String. Method taken

+     * from:<br>

+     * 

+     * <a

+     * href="http://snippets.dzone.com/posts/show/555">http://snippets.dzone.com/posts/show/555</a>.

+     * 

+     * @param in

+     *            The {@link InputStream} to Stringify.

+     * @return A String constructed from the given {@link InputStream}.

+     * @throws IOException

+     *             If any error occurs.

+     */

+    public static String slurp(InputStream in) throws IOException {

+        StringBuffer out = new StringBuffer();

+        byte[] b = new byte[4096];

+        for (int n; (n = in.read(b)) != -1;) {

+            out.append(new String(b, 0, n));

+        }

+        return out.toString();

+    }

+

+    protected static InputStream preProcessInputStream(InputStream is)

+            throws Exception {

+        // basically read this sucker into a BufferedReader

+        // line by line, and replaceAll on \ with \\

+        // so \\\\ with \\\\\\\\

+        BufferedReader reader = new BufferedReader(new InputStreamReader(is));

+        String line = null;

+        StringBuffer buf = new StringBuffer();

+

+        while ((line = reader.readLine()) != null) {

+            // fix the line

+            line = line.replaceAll("\\\\", "\\\\\\\\");

+            buf.append(line + "\n");

+        }

+

+        if (reader != null) {

+            try {

+                reader.close();

+            } catch (Exception ignore) {

+            }

+

+            reader = null;

+        }

+

+        return new ByteArrayInputStream(buf.toString().getBytes());

+    }

+

+}

diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/exec/ExecHelper.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/exec/ExecHelper.java
new file mode 100644
index 0000000..e5e89b4
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/exec/ExecHelper.java
@@ -0,0 +1,471 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.commons.exec;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+/**
+ * <p>
+ * This class is taken from Stephen Ostermiller's example at:
+ * http://ostermiller.org/utils/ExecHelper.java.html
+ * 
+ * It provides some useful methods for manipulating and reading in the output of
+ * a {@link Process} resultant from a call to {@link Runtime#getRuntime()}
+ * without using the {@link Process#waitFor()} method, which apparently can hang
+ * on certain underlying systems.
+ * </p>
+ * 
+ * @author mattmann
+ * 
+ */
+public final class ExecHelper {
+
+    /**
+     * Executes the specified command and arguments in a separate process, and
+     * waits for the process to finish.
+     * <p>
+     * Output from the process is expected to be text in the system's default
+     * character set.
+     * <p>
+     * No input is passed to the process on STDIN.
+     * 
+     * @param cmdarray
+     *            array containing the command to call and its arguments.
+     * @return The results of the execution in an ExecHelper object.
+     * @throws SecurityException
+     *             if a security manager exists and its checkExec method doesn't
+     *             allow creation of a subprocess.
+     * @throws IOException -
+     *             if an I/O error occurs
+     * @throws NullPointerException -
+     *             if cmdarray is null
+     * @throws IndexOutOfBoundsException -
+     *             if cmdarray is an empty array (has length 0).
+     * 
+     * 
+     */
+    public static ExecHelper exec(String[] cmdarray) throws IOException {
+        return new ExecHelper(Runtime.getRuntime().exec(cmdarray), null);
+    }
+
+    /**
+     * Executes the specified command and arguments in a separate process, and
+     * waits for the process to finish.
+     * <p>
+     * Output from the process is expected to be text in the system's default
+     * character set.
+     * <p>
+     * No input is passed to the process on STDIN.
+     * 
+     * @param cmdarray
+     *            array containing the command to call and its arguments.
+     * @param envp
+     *            array of strings, each element of which has environment
+     *            variable settings in format name=value.
+     * @return The results of the execution in an ExecHelper object.
+     * @throws SecurityException
+     *             if a security manager exists and its checkExec method doesn't
+     *             allow creation of a subprocess.
+     * @throws IOException -
+     *             if an I/O error occurs
+     * @throws NullPointerException -
+     *             if cmdarray is null
+     * @throws IndexOutOfBoundsException -
+     *             if cmdarray is an empty array (has length 0).
+     * 
+     * 
+     */
+    public static ExecHelper exec(String[] cmdarray, String[] envp)
+            throws IOException {
+        return new ExecHelper(Runtime.getRuntime().exec(cmdarray, envp), null);
+    }
+
+    /**
+     * Executes the specified command and arguments in a separate process, and
+     * waits for the process to finish.
+     * <p>
+     * Output from the process is expected to be text in the system's default
+     * character set.
+     * <p>
+     * No input is passed to the process on STDIN.
+     * 
+     * @param cmdarray
+     *            array containing the command to call and its arguments.
+     * @param envp
+     *            array of strings, each element of which has environment
+     *            variable settings in format name=value.
+     * @param dir
+     *            the working directory of the subprocess, or null if the
+     *            subprocess should inherit the working directory of the current
+     *            process.
+     * @return The results of the execution in an ExecHelper object.
+     * @throws SecurityException
+     *             if a security manager exists and its checkExec method doesn't
+     *             allow creation of a subprocess.
+     * @throws IOException -
+     *             if an I/O error occurs
+     * @throws NullPointerException -
+     *             if cmdarray is null
+     * @throws IndexOutOfBoundsException -
+     *             if cmdarray is an empty array (has length 0).
+     * 
+     * 
+     */
+    public static ExecHelper exec(String[] cmdarray, String[] envp, File dir)
+            throws IOException {
+        return new ExecHelper(Runtime.getRuntime().exec(cmdarray, envp, dir),
+                null);
+    }
+
+    /**
+     * Executes the specified command and arguments in a separate process, and
+     * waits for the process to finish.
+     * <p>
+     * No input is passed to the process on STDIN.
+     * 
+     * @param cmdarray
+     *            array containing the command to call and its arguments.
+     * @param charset
+     *            Output from the executed command is expected to be in this
+     *            character set.
+     * @return The results of the execution in an ExecHelper object.
+     * @throws SecurityException
+     *             if a security manager exists and its checkExec method doesn't
+     *             allow creation of a subprocess.
+     * @throws IOException -
+     *             if an I/O error occurs
+     * @throws NullPointerException -
+     *             if cmdarray is null
+     * @throws IndexOutOfBoundsException -
+     *             if cmdarray is an empty array (has length 0).
+     * 
+     * 
+     */
+    public static ExecHelper exec(String[] cmdarray, String charset)
+            throws IOException {
+        return new ExecHelper(Runtime.getRuntime().exec(cmdarray), charset);
+    }
+
+    /**
+     * Executes the specified command and arguments in a separate process, and
+     * waits for the process to finish.
+     * <p>
+     * No input is passed to the process on STDIN.
+     * 
+     * @param cmdarray
+     *            array containing the command to call and its arguments.
+     * @param envp
+     *            array of strings, each element of which has environment
+     *            variable settings in format name=value.
+     * @param charset
+     *            Output from the executed command is expected to be in this
+     *            character set.
+     * @return The results of the execution in an ExecHelper object.
+     * @throws SecurityException
+     *             if a security manager exists and its checkExec method doesn't
+     *             allow creation of a subprocess.
+     * @throws IOException -
+     *             if an I/O error occurs
+     * @throws NullPointerException -
+     *             if cmdarray is null
+     * @throws IndexOutOfBoundsException -
+     *             if cmdarray is an empty array (has length 0).
+     * 
+     * 
+     */
+    public static ExecHelper exec(String[] cmdarray, String[] envp,
+            String charset) throws IOException {
+        return new ExecHelper(Runtime.getRuntime().exec(cmdarray, envp),
+                charset);
+    }
+
+    /**
+     * Executes the specified command and arguments in a separate process, and
+     * waits for the process to finish.
+     * <p>
+     * No input is passed to the process on STDIN.
+     * 
+     * @param cmdarray
+     *            array containing the command to call and its arguments.
+     * @param envp
+     *            array of strings, each element of which has environment
+     *            variable settings in format name=value.
+     * @param dir
+     *            the working directory of the subprocess, or null if the
+     *            subprocess should inherit the working directory of the current
+     *            process.
+     * @param charset
+     *            Output from the executed command is expected to be in this
+     *            character set.
+     * @return The results of the execution in an ExecHelper object.
+     * @throws SecurityException
+     *             if a security manager exists and its checkExec method doesn't
+     *             allow creation of a subprocess.
+     * @throws IOException -
+     *             if an I/O error occurs
+     * @throws NullPointerException -
+     *             if cmdarray is null
+     * @throws IndexOutOfBoundsException -
+     *             if cmdarray is an empty array (has length 0).
+     * 
+     * 
+     */
+    public static ExecHelper exec(String[] cmdarray, String[] envp, File dir,
+            String charset) throws IOException {
+        return new ExecHelper(Runtime.getRuntime().exec(cmdarray, envp, dir),
+                charset);
+    }
+
+    /**
+     * Executes the specified command using a shell. On windows uses cmd.exe or
+     * command.exe. On other platforms it uses /bin/sh.
+     * <p>
+     * A shell should be used to execute commands when features such as file
+     * redirection, pipes, argument parsing are desired.
+     * <p>
+     * Output from the process is expected to be text in the system's default
+     * character set.
+     * <p>
+     * No input is passed to the process on STDIN.
+     * 
+     * @param command
+     *            String containing a command to be parsed by the shell and
+     *            executed.
+     * @return The results of the execution in an ExecHelper object.
+     * @throws SecurityException
+     *             if a security manager exists and its checkExec method doesn't
+     *             allow creation of a subprocess.
+     * @throws IOException -
+     *             if an I/O error occurs
+     * @throws NullPointerException -
+     *             if command is null
+     * 
+     * 
+     */
+    public static ExecHelper execUsingShell(String command) throws IOException {
+        return execUsingShell(command, null);
+    }
+
+    /**
+     * Executes the specified command using a shell. On windows uses cmd.exe or
+     * command.exe. On other platforms it uses /bin/sh.
+     * <p>
+     * A shell should be used to execute commands when features such as file
+     * redirection, pipes, argument parsing are desired.
+     * <p>
+     * No input is passed to the process on STDIN.
+     * 
+     * @param command
+     *            String containing a command to be parsed by the shell and
+     *            executed.
+     * @param charset
+     *            Output from the executed command is expected to be in this
+     *            character set.
+     * @return The results of the execution in an ExecHelper object.
+     * @throws SecurityException
+     *             if a security manager exists and its checkExec method doesn't
+     *             allow creation of a subprocess.
+     * @throws IOException -
+     *             if an I/O error occurs
+     * @throws NullPointerException -
+     *             if command is null
+     * 
+     * 
+     */
+    public static ExecHelper execUsingShell(String command, String charset)
+            throws IOException {
+        if (command == null)
+            throw new NullPointerException();
+        String[] cmdarray;
+        String os = System.getProperty("os.name");
+        if (os.equals("Windows 95") || os.equals("Windows 98")
+                || os.equals("Windows ME")) {
+            cmdarray = new String[] { "command.exe", "/C", command };
+        } else if (os.startsWith("Windows")) {
+            cmdarray = new String[] { "cmd.exe", "/C", command };
+        } else {
+            cmdarray = new String[] { "/bin/sh", "-c", command };
+        }
+        return new ExecHelper(Runtime.getRuntime().exec(cmdarray), charset);
+    }
+
+    /**
+     * Take a process, record its standard error and standard out streams, wait
+     * for it to finish
+     * 
+     * @param process
+     *            process to watch
+     * @throws SecurityException
+     *             if a security manager exists and its checkExec method doesn't
+     *             allow creation of a subprocess.
+     * @throws IOException -
+     *             if an I/O error occurs
+     * @throws NullPointerException -
+     *             if cmdarray is null
+     * @throws IndexOutOfBoundsException -
+     *             if cmdarray is an empty array (has length 0).
+     * 
+     * 
+     */
+    private ExecHelper(Process process, String charset) throws IOException {
+    	try {
+	        StringBuffer output = new StringBuffer();
+	        StringBuffer error = new StringBuffer();
+	
+	        Reader stdout;
+	        Reader stderr;
+	
+	        if (charset == null) {
+	            // This is one time that the system charset is appropriate,
+	            // don't specify a character set.
+	            stdout = new InputStreamReader(process.getInputStream());
+	            stderr = new InputStreamReader(process.getErrorStream());
+	        } else {
+	            stdout = new InputStreamReader(process.getInputStream(), charset);
+	            stderr = new InputStreamReader(process.getErrorStream(), charset);
+	        }
+	        char[] buffer = new char[1024];
+	
+	        boolean done = false;
+	        boolean stdoutclosed = false;
+	        boolean stderrclosed = false;
+	        while (!done) {
+	            boolean readSomething = false;
+	            // read from the process's standard output
+	            if (!stdoutclosed && stdout.ready()) {
+	                readSomething = true;
+	                int read = stdout.read(buffer, 0, buffer.length);
+	                if (read < 0) {
+	                    readSomething = true;
+	                    stdoutclosed = true;
+	                } else if (read > 0) {
+	                    readSomething = true;
+		                    output.append(buffer, 0, read);
+	                }
+	            }
+	            // read from the process's standard error
+	            if (!stderrclosed && stderr.ready()) {
+	                int read = stderr.read(buffer, 0, buffer.length);
+	                if (read < 0) {
+	                    readSomething = true;
+	                    stderrclosed = true;
+	                } else if (read > 0) {
+	                    readSomething = true;
+	                    error.append(buffer, 0, read);
+	                }
+	            }
+	            // Check the exit status only we haven't read anything,
+	            // if something has been read, the process is obviously not dead
+	            // yet.
+	            if (!readSomething) {
+	                try {
+	                    this.status = process.exitValue();
+	                    done = true;
+	                } catch (IllegalThreadStateException itx) {
+	                    // Exit status not ready yet.
+	                    // Give the process a little breathing room.
+	                    try {
+	                        Thread.sleep(100);
+	                    } catch (InterruptedException ix) {
+	                        process.destroy();
+	                        throw new IOException("Interrupted - processes killed");
+	                    }
+	                }
+	            }
+	        }
+	
+	        this.output = output.toString();
+	        this.error = error.toString();
+    	}catch (Exception e) {
+    		e.printStackTrace();
+    		throw new IOException("Process exec failed : " + e.getMessage());
+    	}finally {
+            try {
+            	process.getErrorStream().close();
+            } catch (Exception e) {}
+            try {
+               	process.getInputStream().close();
+            } catch (Exception e) {}
+            try {
+            	process.getOutputStream().close();
+            } catch (Exception e) {}
+    	}
+    }
+
+    /**
+     * The output of the job that ran.
+     * 
+     * 
+     */
+    private String output;
+
+    /**
+     * Get the output of the job that ran.
+     * 
+     * @return Everything the executed process wrote to its standard output as a
+     *         String.
+     * 
+     * 
+     */
+    public String getOutput() {
+        return output;
+    }
+
+    /**
+     * The error output of the job that ran.
+     * 
+     * 
+     */
+    private String error;
+
+    /**
+     * Get the error output of the job that ran.
+     * 
+     * @return Everything the executed process wrote to its standard error as a
+     *         String.
+     * 
+     * 
+     */
+    public String getError() {
+        return error;
+    }
+
+    /**
+     * The status of the job that ran.
+     * 
+     * 
+     */
+    private int status;
+
+    /**
+     * Get the status of the job that ran.
+     * 
+     * @return exit status of the executed process, by convention, the value 0
+     *         indicates normal termination.
+     * 
+     * 
+     */
+    public int getStatus() {
+        return status;
+    }
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/exec/ExecUtils.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/exec/ExecUtils.java
new file mode 100644
index 0000000..bb4b9e5
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/exec/ExecUtils.java
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.commons.exec;
+
+//OODT imports
+import org.apache.oodt.commons.io.LoggerOutputStream;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Utilities for executing programs.
+ * 
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public final class ExecUtils {
+
+   private ExecUtils() throws InstantiationException {
+      throw new InstantiationException("Don't construct utility classes!");
+   }
+
+   public static String printCommandLine(String[] args) {
+      StringBuffer cmdLine = new StringBuffer();
+
+      if (args != null && args.length > 0) {
+         for (int i = 0; i < args.length; i++) {
+            cmdLine.append(args[i]);
+            cmdLine.append(" ");
+         }
+      }
+
+      return cmdLine.toString();
+   }
+
+   public static int callProgram(String commandLine, Logger logger)
+         throws IOException {
+      return callProgram(commandLine, logger, null);
+   }
+
+   public static int callProgram(String commandLine, OutputStream stdOutStream,
+         OutputStream stdErrStream) throws IOException {
+      return callProgram(commandLine, stdOutStream, stdErrStream, null);
+   }
+
+   public static int callProgram(String commandLine, Logger logger, File workDir)
+         throws IOException {
+      LoggerOutputStream loggerInfoStream = null;
+      LoggerOutputStream loggerSevereStream = null;
+      try {
+         return callProgram(
+               commandLine,
+               loggerInfoStream = new LoggerOutputStream(logger, Level.INFO),
+               loggerSevereStream = new LoggerOutputStream(logger, Level.SEVERE),
+               workDir);
+      } catch (Exception e) {
+         throw new IOException(e);
+      } finally {
+         try { loggerInfoStream.close(); } catch (Exception e) {}
+         try { loggerSevereStream.close(); } catch (Exception e) {}
+      }
+   }
+
+   public static int callProgram(String commandLine, OutputStream stdOutStream,
+         OutputStream stdErrStream, File workDir) throws IOException {
+      Process progProcess = null;
+      StreamGobbler errorGobbler = null, outputGobbler = null;
+      int returnVal = -1;
+      try {
+         progProcess = (workDir == null) ? Runtime.getRuntime().exec(
+               commandLine) : Runtime.getRuntime().exec(commandLine, null,
+               workDir);
+         errorGobbler = new StreamGobbler(progProcess.getErrorStream(),
+               "ERROR", stdErrStream);
+         outputGobbler = new StreamGobbler(progProcess.getInputStream(),
+               "OUTPUT", stdOutStream);
+         errorGobbler.start();
+         outputGobbler.start();
+         returnVal = progProcess.waitFor();
+         return returnVal;
+      } catch (Exception e) {
+         e.printStackTrace();
+         throw new IOException("Failed to run '" + commandLine
+               + "' -- return val = " + returnVal + " : " + e.getMessage());
+      } finally {
+         if (errorGobbler != null) {
+            errorGobbler.stopGobblingAndDie();
+         }
+         if (outputGobbler != null) {
+            outputGobbler.stopGobblingAndDie();
+         }
+         try { progProcess.getErrorStream().close(); } catch (Exception e) {}
+         try { progProcess.getInputStream().close(); } catch (Exception e) {}
+         try { progProcess.getOutputStream().close(); } catch (Exception e) {}
+      }
+   }
+
+   public static int callProgram(String commandLine, File workDir)
+         throws IOException {
+      Process p = Runtime.getRuntime().exec(commandLine, null, workDir);
+      return processProgram(p);
+   }
+
+   public static int callProgram(String[] args, File workDir)
+         throws IOException {
+      Process p = Runtime.getRuntime().exec(args, null, workDir);
+      return processProgram(p);
+   }
+
+   private static int processProgram(Process p) {
+
+      StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(),
+            "ERROR", System.err);
+
+      // any output?
+      StreamGobbler outputGobbler = new StreamGobbler(p.getInputStream(),
+            "OUTPUT", System.out);
+
+      errorGobbler.start();
+      outputGobbler.start();
+      int retVal = -1;
+      try {
+         retVal = p.waitFor();
+      } catch (InterruptedException ignore) {
+      } finally {
+         // first stop the threads
+         if (outputGobbler != null && outputGobbler.isAlive()) {
+            outputGobbler.stopGobblingAndDie();
+            outputGobbler = null;
+         }
+
+         if (errorGobbler != null && errorGobbler.isAlive()) {
+            errorGobbler.stopGobblingAndDie();
+            errorGobbler = null;
+         }
+
+         try { p.getErrorStream().close(); } catch (Exception ignore) {}
+         try { p.getOutputStream().close(); } catch (Exception ignore) {}
+         try { p.getInputStream().close(); } catch (Exception ignore) {}
+      }
+      return retVal;
+   }
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/exec/StreamGobbler.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/exec/StreamGobbler.java
new file mode 100644
index 0000000..e17c829
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/exec/StreamGobbler.java
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.commons.exec;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>This class is a Utility class for dealing with java <code>Process</code> streams. It was
+ * taken from the site: 
+ * <a href="http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html">http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html</a>, 
+ * and was written by Michael Daconta.</p>
+ *
+ */
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class StreamGobbler extends Thread {
+	
+	private static final Logger LOG = Logger.getLogger(StreamGobbler.class.getName());
+	
+    InputStream is;
+
+    String type;
+
+    OutputStream os;
+
+    private boolean running = true;
+
+    public StreamGobbler(InputStream is, String type) {
+        this(is, type, null);
+    }
+
+    public StreamGobbler(InputStream is, String type, OutputStream redirect) {
+        this.is = is;
+        this.type = type;
+        this.os = redirect;
+    }
+
+    public void run() {
+        try {
+            PrintWriter pw = null;
+            if (os != null)
+                pw = new PrintWriter(os);
+
+            InputStreamReader isr = new InputStreamReader(is);
+            BufferedReader br = new BufferedReader(isr);
+            String line = null;
+            while ((line = br.readLine()) != null && this.running) {
+                if (pw != null)
+                    pw.println(this.type + ": " + line);
+            }
+            if (pw != null)
+                pw.flush();
+        } catch (IOException ioe) {
+        	LOG.log(Level.FINEST, "StreamGobbler failed while gobbling : " + ioe.getMessage(), ioe);
+        }
+    }
+
+    public void stopGobblingAndDie() {
+        this.running = false;
+    }
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/filter/ObjectTimeEvent.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/filter/ObjectTimeEvent.java
new file mode 100644
index 0000000..a2a9822
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/filter/ObjectTimeEvent.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.commons.filter;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>A {@link TimeEvent} associated with a particular {@link Object}</p>.
+ */
+public class ObjectTimeEvent<objType> extends TimeEvent {
+
+    private objType timeObj;
+
+    public ObjectTimeEvent(long startTime, long endTime, objType timeObj) {
+        super(startTime, endTime);
+        this.timeObj = timeObj;
+    }
+
+    public ObjectTimeEvent(long startTime, long endTime, double priority,
+            objType timeObj) {
+        super(startTime, endTime, priority);
+        this.timeObj = timeObj;
+    }
+
+    public objType getTimeObject() {
+        return this.timeObj;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof ObjectTimeEvent) {
+            ObjectTimeEvent<?> ote = (ObjectTimeEvent<?>) obj;
+            return super.equals(obj) && this.timeObj.equals(ote.timeObj);
+        } else
+            return false;
+    }
+    
+    @Override
+    public String toString() {
+        return super.toString() + " - " + timeObj;
+    }
+
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/filter/TimeEvent.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/filter/TimeEvent.java
new file mode 100644
index 0000000..386344e
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/filter/TimeEvent.java
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.commons.filter;
+
+//JDK imports
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A basis for time-based queries results over a start/end datetime with
+ * a duration
+ * </p>.
+ */
+public class TimeEvent implements Comparable<TimeEvent> {
+
+    protected long startTime, endTime, dur;
+
+    protected double priority;
+
+    public TimeEvent(long startTime, long endTime) {
+        this(startTime, endTime, 0);
+    }
+
+    public TimeEvent(long startTime, long endTime, double priority) {
+        this.startTime = startTime;
+        this.endTime = endTime;
+        this.dur = this.endTime - this.startTime;
+        this.priority = priority;
+    }
+
+    public void setPriority(double priority) {
+        this.priority = priority;
+    }
+
+    public double getPriority() {
+        return this.priority;
+    }
+
+    public long getStartTime() {
+        return this.startTime;
+    }
+
+    public long getEndTime() {
+        return this.endTime;
+    }
+
+    public long getDuration() {
+        return this.dur;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof TimeEvent) {
+            TimeEvent te = (TimeEvent) obj;
+            return te.startTime == this.startTime && te.endTime == this.endTime;
+        } else
+            return false;
+    }
+
+    @Override
+    public String toString() {
+        return "[" + this.startTime + "," + this.endTime + "] - "
+                + this.priority;
+    }
+    
+    public static boolean happenAtSameTime(TimeEvent te1, TimeEvent te2) {
+        return te1.getStartTime() == te2.getStartTime() && te1.getEndTime() == te2.getEndTime();
+    }
+
+    public int compareTo(TimeEvent te) {
+        return new Long(this.startTime).compareTo(te.startTime);
+    }
+ 
+    public static List<? extends TimeEvent> getTimeOrderedEvents(List<? extends TimeEvent> events) {
+        TimeEvent[] eventsArray = events
+                .toArray(new TimeEvent[events.size()]);
+        Arrays.sort(eventsArray);
+        return Arrays.asList(eventsArray);
+    }
+    
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/filter/TimeEventWeightedHash.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/filter/TimeEventWeightedHash.java
new file mode 100644
index 0000000..38aa8fd
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/filter/TimeEventWeightedHash.java
@@ -0,0 +1,389 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.commons.filter;
+
+//JDK imports
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+* 
+* @author bfoster
+* @version $Revision$
+*
+* <p>
+* Builds a time sorted hash where the top value has the earliest time.  This hash
+* is a directional graph.  It builds all possible paths from top node to leaf
+* nodes.  At any time you can ask for the greatest weighted path in the hash -- that
+* is, the path from root node to a leaf node which fills the most time. Epsilon is 
+* TimeEvent objects allowed time overlap (it is of the same unit of measurement that 
+* is used in you TimeEvent objects added to this hash).
+* </p>.
+*/
+public class TimeEventWeightedHash {
+
+  private TimeEventNode root;
+  
+  protected long epsilon;
+  
+  private MyLinkedHashSet<TimeEventNode> leafNodes;
+      
+  private TimeEventWeightedHash() {
+      root = new TimeEventNode(new TimeEvent(-1, -1));
+      leafNodes = new MyLinkedHashSet<TimeEventNode>();
+      leafNodes.add(this.root);
+  }
+  
+  public static TimeEventWeightedHash buildHash(List<? extends TimeEvent> events) {
+	  return buildHash(events, 0);
+  }
+  
+  /**
+   * Returns the Greatest Weighted Path of TimeEvents
+   */
+  public static TimeEventWeightedHash buildHash(List<? extends TimeEvent> events, long epsilon) {
+	  TimeEventWeightedHash hash = new TimeEventWeightedHash();
+	  hash.epsilon = epsilon;
+      events = TimeEvent.getTimeOrderedEvents(events);
+      for (TimeEvent event : events)
+    	  hash.addEvent(event);
+      return hash;
+  }
+  
+  public List<? extends TimeEvent> getGreatestWeightedPathAsOrderedList() {
+      WeightedNode wn = this.getGreatestWeightedPath();
+      List<TimeEvent> gwpEvents = new LinkedList<TimeEvent>();
+      while(wn != null) {
+          gwpEvents.add(wn.getTimeEvent());
+          wn = wn.getChild();
+      }
+      
+      return gwpEvents;
+  }
+ 
+  private void addEvent(TimeEvent newEvent) {
+      TimeEventNode newEventNode = new TimeEventNode(newEvent);
+      MyLinkedHashSet<TimeEventNode> parentNodes = this.findParents(newEvent);
+      MyLinkedHashSet<TimeEventNode> childrenNodes = this.findChildren(newEvent, parentNodes);
+      
+      if (childrenNodes.size() == 0)
+          leafNodes.add(newEventNode);
+      
+      newEventNode.addParents(parentNodes);
+      newEventNode.addChildren(childrenNodes);
+      
+  }
+  
+  private MyLinkedHashSet<TimeEventNode> findParents(TimeEvent newEvent) {
+      MyLinkedHashSet<TimeEventNode> parentNodes = new MyLinkedHashSet<TimeEventNode>();
+      MyLinkedHashSet<TimeEventNode> possibleParentNodes = new MyLinkedHashSet<TimeEventNode>();
+      MyLinkedHashSet<TimeEventNode> possibleParentNodesAlreadyChecked = new MyLinkedHashSet<TimeEventNode>();
+      
+      //iterate through possible parent nodes add possible parent child as
+      // possible parents if they do not conflict
+      TimeEventNode curPPN = this.root;
+      while (curPPN != null) {
+          boolean ppnListChanged = false;
+          for (TimeEventNode curChild : curPPN.getChildren()) {
+              //if curChild does not conficts with te, then it is a possible parent
+              if (happensBefore(curChild.getTimeEvent(), newEvent) 
+                      && !possibleParentNodesAlreadyChecked.contains(curChild)) {
+                  possibleParentNodes.add(curChild);
+                  ppnListChanged = true;
+              }
+          }
+          //if all children where not possible parents, then curPPN must be parent
+          if (!ppnListChanged)
+              parentNodes.add(curPPN);
+          
+          //get next curPPN
+          possibleParentNodes.remove(curPPN);
+          possibleParentNodesAlreadyChecked.add(curPPN);
+          while((curPPN = possibleParentNodes.get(0)) != null 
+                  && possibleParentNodesAlreadyChecked.contains(curPPN)) {
+              possibleParentNodes.remove(curPPN);
+          }
+      }
+      
+      return parentNodes;
+  }
+  
+  private MyLinkedHashSet<TimeEventNode> findChildren(TimeEvent newEvent, MyLinkedHashSet<TimeEventNode> parentNodes) {
+      MyLinkedHashSet<TimeEventNode> childrenNodes = new MyLinkedHashSet<TimeEventNode>();
+      MyLinkedHashSet<TimeEventNode> possibleChildrenNodes = new MyLinkedHashSet<TimeEventNode>();
+      for (TimeEventNode parent : parentNodes) {
+          possibleChildrenNodes.addAll(parent.getChildren());
+          TimeEventNode curPCN = possibleChildrenNodes.get(0);
+          while (curPCN != null && !parentNodes.contains(curPCN)) {
+              if (happensBefore(newEvent, curPCN.getTimeEvent())) {
+                  childrenNodes.add(curPCN);
+              }else {
+                  possibleChildrenNodes.addAll(curPCN.getChildren());
+              }
+              possibleChildrenNodes.remove(curPCN);
+              curPCN = possibleChildrenNodes.get(0);
+          }
+      }
+      return childrenNodes;
+  }
+  
+  private boolean happensBefore(TimeEvent t1, TimeEvent t2) {
+      long boundaryCheck = t2.getStartTime() - t1.getEndTime();
+      return t1.getStartTime() < t2.getStartTime() && (boundaryCheck + epsilon) > 0;
+  }
+  
+  private WeightedNode getGreatestWeightedPath() {
+      TimeEventNode max = this.leafNodes.get(0);
+      for (TimeEventNode ten : this.leafNodes) {
+         if (ten.getPathWeight() > max.getPathWeight() 
+                 || (ten.getPathWeight() == max.getPathWeight() 
+                         && ten.getPathPriorityWeight() > max.getPathPriorityWeight()))
+             max = ten;
+      }
+      WeightedNode root = new WeightedNode(max.getTimeEvent());
+      TimeEventNode curTEN = max.greatestWieghtedParent;
+      while (curTEN != null) {
+          WeightedNode temp = new WeightedNode(curTEN.getTimeEvent());
+          temp.setChild(root);
+          root = temp;
+          curTEN = curTEN.greatestWieghtedParent;
+      }
+      return root.getChild();
+  }
+  
+  private class MyLinkedHashSet<E> extends HashSet<E> {
+
+      private static final long serialVersionUID = -7319154087430025841L;
+      
+      private LinkedList<E> listSet;
+      
+      public MyLinkedHashSet() {
+          this.listSet = new LinkedList<E>();
+      }
+      
+      @Override
+      public boolean add(E ten) {
+          boolean wasAdded = false;
+          if (wasAdded = super.add(ten))
+              listSet.add(ten);
+          return wasAdded;
+      }
+      
+      @Override
+      public boolean addAll(Collection<? extends E> collection) {
+          boolean setChanged = false;
+          for (E ten : collection) {
+              if (this.add(ten))
+                  setChanged = true;
+          }
+          return setChanged;
+      }
+      
+      @Override
+      public boolean remove(Object ten) {
+          if (super.remove(ten)) {
+              this.listSet.remove(ten);
+              return true;
+          }else 
+              return false;
+      }
+      
+      @Override
+      public boolean removeAll(Collection<?> collection) {
+          boolean setChanged = false;
+          for (Object obj : collection) {
+              if (this.remove(obj))
+                  setChanged = true;
+          }
+          return setChanged;  
+      }
+      
+      public E get(int index) {
+          if (this.listSet.size() > index)
+              return this.listSet.get(index);
+          else 
+              return null;
+      }
+      
+      public List<E> getList() {
+          return this.listSet;
+      }
+      
+  }
+
+  private class TimeEventNode {
+
+      private TimeEvent te;
+      
+      private MyLinkedHashSet<TimeEventNode> children;
+
+      private MyLinkedHashSet<TimeEventNode> parents;
+      
+      private TimeEventNode greatestWieghtedParent;
+              
+      public TimeEventNode(TimeEvent te) {
+          this.te = te;
+          children = new MyLinkedHashSet<TimeEventNode>();
+          parents = new MyLinkedHashSet<TimeEventNode>();
+      }
+      
+      public long getPathWeight() {
+          if (this.greatestWieghtedParent != null)
+              return te.getDuration()
+                      + this.greatestWieghtedParent.getPathWeight();
+          else
+              return te.getDuration();
+      }
+
+      public double getPathPriorityWeight() {
+          if (this.greatestWieghtedParent != null)
+              return te.getPriority()
+                      + this.greatestWieghtedParent.getPathPriorityWeight();
+          else
+              return te.getPriority();
+      }
+
+      public TimeEvent getTimeEvent() {
+          return this.te;
+      }
+
+      public void setTimeEvent(TimeEvent te) {
+          this.te = te;
+      }
+      
+      public void addChild(TimeEventNode child) {            
+          //remove parent to grandchild links
+          for (TimeEventNode parent : this.parents) {
+              parent.children.remove(child);
+              child.parents.remove(parent);
+          }
+          
+          //link to child
+          this.children.add(child);
+          child.parents.add(this);
+          leafNodes.remove(this);
+          
+          //determine child's greatest weighted parent
+          child.greatestWieghtedParent = this;
+          for (TimeEventNode parent : child.parents) {
+              long gwpPaW = child.greatestWieghtedParent.getPathWeight();
+              long pPaW = parent.getPathWeight();
+              double gwpPiW = child.greatestWieghtedParent.getPathPriorityWeight();
+              double pPiW = parent.getPathPriorityWeight();
+              if (pPaW > gwpPaW || (pPaW == gwpPaW && pPiW > gwpPiW))                    
+                  child.greatestWieghtedParent = parent;
+          }
+      }
+      
+      public void addParent(TimeEventNode parent) {
+          parent.addChild(this);
+      }
+
+      public void addChildren(Collection<TimeEventNode> children) {
+          for (TimeEventNode child : children)
+              this.addChild(child);
+      }
+      
+      public void addParents(Collection<TimeEventNode> parents) {
+          for (TimeEventNode parent : parents)
+              this.addParent(parent);
+      }
+
+      public MyLinkedHashSet<TimeEventNode> getChildren() {
+          return this.children;
+      }
+      
+      public MyLinkedHashSet<TimeEventNode> getParents() {
+          return this.parents;
+      }
+
+      public boolean equals(Object obj) {
+          if (obj instanceof TimeEventNode) {
+              TimeEventNode ten = (TimeEventNode) obj;
+              return this.te.equals(ten.te);
+          } else
+              return false;
+      }
+
+      public String toString() {
+          return this.te.toString() + " -- " + this.getPathWeight();
+      }
+      
+  }
+
+  private class WeightedNode {
+
+      private long pathWeight;
+
+      private WeightedNode child;
+
+      private TimeEvent te;
+
+      private WeightedNode(TimeEvent te) {
+          this.te = te;
+          pathWeight = te.getDuration();
+      }
+
+      private void setChild(WeightedNode child) {
+          this.child = child;
+          if (child != null)
+              this.pathWeight = this.te.getDuration() + child.getPathWeight();
+      }
+
+      public TimeEvent getTimeEvent() {
+          return this.te;
+      }
+
+      public WeightedNode getChild() {
+          return this.child;
+      }
+
+      public long getPathWeight() {
+          return this.pathWeight;
+      }
+
+      public String toString() {
+          return te.toString() + "\n" 
+              + (child != null ? child.toString() : "");
+      }
+
+  }
+
+  public String toString() {
+      StringBuffer sb = new StringBuffer("");
+      LinkedList<TimeEventNode> printNodes = new LinkedList<TimeEventNode>();
+      printNodes.add(this.root);
+      sb.append(printNodes(printNodes, "-", 0));
+      return sb.toString();
+  }
+
+  private StringBuffer printNodes(List<TimeEventNode> list,
+          String spacer, long curPathWeight) {
+      StringBuffer output = new StringBuffer("");
+      for (TimeEventNode node : list) {
+          output.append(spacer);
+          output.append(node.te + " -- " + (curPathWeight + node.te.getDuration()) + "\n");
+          output.append(printNodes(node.getChildren().getList(), " " + spacer, curPathWeight + node.te.getDuration()));
+      }
+      return output;
+  }
+
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/Base64DecodingInputStream.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/Base64DecodingInputStream.java
new file mode 100644
index 0000000..4cd3c3d
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/Base64DecodingInputStream.java
@@ -0,0 +1,164 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import org.apache.oodt.commons.util.Base64;
+
+/** An input stream that decodes its data from the RFC-1512 base 64 format.
+ *
+ * Wrap this input stream around another input stream, and all the bytes will be converted
+ * from their base-64 format when you read from it.
+ *
+ * @author Kelly
+ */
+public class Base64DecodingInputStream extends FilterInputStream {
+	/** Construct a base-64 decoding input stream.
+	 *
+	 * @param inputStream The input stream to decode.
+	 */
+	public Base64DecodingInputStream(InputStream inputStream) {
+		super(inputStream);
+	}
+
+	/** Read the next byte.
+	 *
+	 * Decode more base-64 data and return the next decoded byte.
+	 *
+	 * @return The byte, or -1 on end of stream.
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public int read() throws IOException {
+		if (in == null) throw new IOException("Can't read from a closed stream");
+
+		// If we've used up the decoded data buffer, read 4 more bytes and decode 'em.
+		if (buffer == null || index == buffer.length) {
+			byte[] streamBuf = new byte[4];
+			int toRead = 4;
+			int atIndex = 0;
+			int actuallyGot;
+			boolean firstRead = true;
+			while (toRead > 0) {
+				actuallyGot = in.read(streamBuf, atIndex, toRead);
+				if (actuallyGot == -1) {
+					if (firstRead) return -1;
+					else break;
+				}
+				firstRead = false;
+				atIndex += actuallyGot;
+				toRead -= actuallyGot;
+			}
+			buffer = Base64.decode(streamBuf);
+			if (buffer.length == 0) {
+				buffer = null;
+				return -1;
+			}
+			index = 0;
+		}
+		return buffer[index++] & 0xff;
+	}
+
+	/** Read a bunch of bytes.
+	 *
+	 * This decodes base-64 data from the underlying stream and puts the result into
+	 * the given array.
+	 *
+	 * @param b The buffer to fill with decoded base-64 data.
+	 * @param offset Where in the buffer to start filling.
+	 * @param length How many bytes to fill.
+	 * @return The actual number of decoded bytes.
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public int read(byte[] b, int offset, int length) throws IOException {
+		if (b == null) throw new IllegalArgumentException("Can't read data into a null array");
+		if (offset < 0 || offset >= b.length)
+			throw new IndexOutOfBoundsException("Can't read data into an array with indexes 0.." + (b.length-1)
+				+ " at index " + offset);
+		if (length < 0) throw new IllegalArgumentException("Can't read a negative amount of data");
+		if (offset + length > b.length)
+			throw new IndexOutOfBoundsException("Can't read data past the right edge of an array");
+		if (in == null) throw new IOException("Can't read from a closed stream");
+
+		int c = read();
+		if (c == -1) return -1;
+		b[offset] = (byte) c;
+		int i = 1;
+		try {
+			for (; i < length; ++i) {
+				c = read();
+				if (c == -1) break;
+				b[offset + i] = (byte) c;
+			}
+		} catch (IOException ignore) {}
+		return i;
+	}
+
+	/** Skip bytes.
+	 *
+	 * This method skips and discards <var>n</var> decoded bytes on the input stream.
+	 *
+	 * @param n Number of bytes to skip.
+	 * @return Actual number of bytes skipped.
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public long skip(long n) throws IOException {
+		if (in == null) throw new IOException("Can't skip past data on a closed stream");
+		int actuallySkipped = 0;
+		while (n > 0) {
+			if (read() == -1) return actuallySkipped;
+			--n;
+			++actuallySkipped;
+		}
+		return actuallySkipped;
+	}
+
+	/** Return bytes available for reading or skipping without blocking.
+	 *
+	 * @return The number of bytes that can be read from this stream or skipped over
+	 * on the stream without blocking.
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public int available() throws IOException {
+		if (in == null) throw new IOException("Can't see how many bytes are available on a closed stream");
+		if (buffer != null && index < buffer.length)
+			return buffer.length - index;
+		return in.available() >= 4? 1 : 0;
+	}
+
+	/** Close this stream.
+	 *
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public void close() throws IOException {
+		if (in == null) throw new IOException("Can't close a closed stream");
+		in.close();
+		in = null;
+		buffer = null;
+	}
+
+	/** Buffer for decoded data.
+	 */
+	private byte[] buffer;
+
+	/** Where we'll next read out of the buffer.
+	 *
+	 * Since we always read 4 bytes at a time (a base-64 block), we can decode that
+	 * into as many as 3 bytes, so start out the index in an invalid location.
+	 */
+	private int index = 3;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/Base64EncodingOutputStream.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/Base64EncodingOutputStream.java
new file mode 100644
index 0000000..0841313
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/Base64EncodingOutputStream.java
@@ -0,0 +1,136 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import org.apache.oodt.commons.util.Base64;
+
+/** An output stream that encodes its data into RFC-1512 base 64 format.
+ *
+ * Wrap this input stream around another output stream, and all the bytes will be
+ * converted into their base-64 format when you write to it.
+ *
+ * @author Kelly
+ */
+public class Base64EncodingOutputStream extends FilterOutputStream {
+	/** Construct a base-64 encoding output stream.
+	 *
+	 * @param outputStream The output stream to which to write.
+	 */
+	public Base64EncodingOutputStream(OutputStream outputStream) {
+		super(outputStream);
+	}
+
+	/** Write a byte of data.
+	 *
+	 * The byte will be encoded into base-64 format on the output.
+	 *
+	 * @param b The byte.
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public void write(int b) throws IOException {
+		if (buffer == null)
+			throw new IOException("Can't write onto a closed stream");
+		buffer[index++] = (byte) b;
+		if (index == buffer.length) shipout();
+	}
+
+	/** Write a bunch of bytes.
+	 *
+	 * The given array of bytes will be encoded into base-64 on the output.
+	 *
+	 * @param b The array to write.
+	 * @param offset Where in the data to start writing.
+	 * @param length How many bytes to write.
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public void write(byte[] b, int offset, int length) throws IOException {
+		if (b == null) throw new IllegalArgumentException("Can't write a null array");
+		if (offset < 0 || offset >= b.length)
+			throw new IndexOutOfBoundsException("Can't get bytes at " + offset + " in array with indexes 0.."
+				+ (b.length - 1));
+		if (length < 0) throw new IllegalArgumentException("Can't write a negative amount of bytes");
+		if (offset + length > b.length)
+			throw new IndexOutOfBoundsException("Can't get bytes beyond edge of array");
+		if (buffer == null)
+			throw new IOException("Can't write onto a closed stream");
+		while (length > 0) {
+			int avail = buffer.length - index;
+			int amount = avail < length? avail : length;
+			System.arraycopy(b, offset, buffer, index, amount);
+			index += amount;
+			offset += amount;
+			length -= amount;
+			if (index == buffer.length) shipout();
+		}
+	}
+
+	/** Flush the stream.
+	 *
+	 * This causes any buffered bytes to be encoded and shipped out to the underlying
+	 * stream, which is also flushed.
+	 *
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public void flush() throws IOException {
+		if (buffer == null)
+			throw new IOException("Can't flush a closed stream");
+		shipout();
+		out.flush();
+	}
+
+	/** Close the stream.
+	 *
+	 * This writes out any unflushed data in base-64 format and closes the underlying
+	 * stream.
+	 *
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public void close() throws IOException {
+		if (buffer == null)
+			throw new IOException("Can't close an already closed stream");
+		flush();
+		out.close();
+		out = null;
+		buffer = null;
+	}
+
+	/** Ship out a bunch of buffered data in base-64 format.
+	 *
+	 * This resets the index of the next byte to insert back to zero.
+	 *
+	 * @throws IOException If an I/O error occurs.
+	 */
+	private void shipout() throws IOException {
+		byte[] encoded = Base64.encode(buffer, 0, index);
+		out.write(encoded);
+		index = 0;
+	}
+
+	/** Size of the output data buffer.  Must be a multiple of 3.
+	 */
+	private static final int BUFFER_SIZE = 300;
+
+	/** Buffer for output data.
+	 */
+	private byte[] buffer = new byte[BUFFER_SIZE];
+
+	/** Where we are in the buffer.
+	 */
+	private int index = 0;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/CountingOutputStream.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/CountingOutputStream.java
new file mode 100644
index 0000000..0afd3c2
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/CountingOutputStream.java
@@ -0,0 +1,64 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An output stream that counts the number bytes it passes on.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+public class CountingOutputStream extends FilterOutputStream {
+	/**
+	 * Creates a new <code>CountingOutputStream</code> instance.
+	 *
+	 * @param out Where to send bytes onto.
+	 */
+	public CountingOutputStream(OutputStream out) {
+		super(out);
+	}
+  
+	public void write(int b) throws IOException {
+		out.write(b);
+		++written;
+	}
+  
+	public void write(byte[] b) throws IOException {
+		out.write(b);
+		written += b.length;
+	}
+  
+	public void write(byte[] b, int offset, int length) throws IOException {
+		out.write(b, offset, length);
+		written += length;
+	}
+  
+	/**
+	 * Get the number of bytes written so far.
+	 *
+	 * @return a <code>long</code> value.
+	 */
+	public long getBytesWritten() {
+		return written;
+	}
+  
+	/** Number of bytes written so far. */
+	private long written = 0L;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/FixedBufferOutputStream.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/FixedBufferOutputStream.java
new file mode 100644
index 0000000..4c6217e
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/FixedBufferOutputStream.java
@@ -0,0 +1,119 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/** This stream writes its output into a byte buffer of fixed length.
+ *
+ * For a buffer of size <var>n</var>, only the last <var>n</var> bytes written are ever
+ * available.
+ *
+ * @author Kelly
+ */
+public class FixedBufferOutputStream extends OutputStream {
+	/** Construct a fixed buffer output stream.
+	 *
+	 * @param n Size of the buffer.
+	 */
+	public FixedBufferOutputStream(int n) {
+		if (n < 0) throw new IllegalArgumentException("Buffer size must be nonnegative");
+		buffer = new byte[n];
+		length = n;
+		size = 0;
+		start = 0;
+	}
+
+	public void write(int b) throws IOException {
+		checkIfClosed();
+		if (length == 0) return;
+		if (size < length)
+			buffer[size++] = (byte) b;
+		else {
+			buffer[start] = (byte) b;
+			start = (start + 1) % length;
+		}
+	}
+
+	public void write(byte[] a, int off, int len) throws IOException {
+		checkIfClosed();
+		if (a == null) throw new NullPointerException("Can't write from a null array");
+		else if ((off < 0) || (off > a.length) || (len < 0) || ((off + len) > a.length) || ((off + len) < 0)) {
+			throw new IndexOutOfBoundsException("Offset " + off + " and length " + len + " not within array bounds");
+		} else if (len == 0) {
+			return;
+		}
+		if (len > length) {
+			off += len - length;
+			len = length;
+		}
+		int capacity = length - size;
+		int insertionIndex = size < length? size : start;
+		int insertionLength = Math.min(length - insertionIndex, len);
+		int remaining = len - insertionLength;
+		System.arraycopy(a, off, buffer, insertionIndex, insertionLength);
+		if (remaining > 0) {
+			System.arraycopy(a, off + insertionLength, buffer, 0, remaining);
+			start = remaining;
+		} else if (capacity == 0)
+			start = insertionIndex + insertionLength;
+		size = Math.min(length, size + len);
+	}
+
+	public void flush() {
+		// Nothing need be done here
+	}
+
+	public void close() {
+		start = -1;
+	}
+
+	/** Get the buffer.
+	 *
+	 * This method constructs a new array whose contents is the data written.  Its
+	 * size is equal to the smaller of the number of bytes written or the size of the
+	 * fixed buffer passed to the constructor of this class.
+	 *
+	 * @return The buffer.
+	 */
+	public byte[] getBuffer() {
+		byte[] rc = new byte[Math.min(size, length)];
+		System.arraycopy(buffer, start, rc, 0, size - start);
+		System.arraycopy(buffer, 0, rc, size - start, start);
+		return rc;
+	}
+
+	/** Throw an exception if we've been closed.
+	 *
+	 * @throws IOException If this stream has been closed.
+	 */
+	private void checkIfClosed() throws IOException {
+		if (start == -1) throw new IOException("Can't write to closed stream");
+	}
+
+	/** Length of the buffer. */
+	private int length;
+
+	/** Current size of the data in the buffer. */
+	private int size;
+
+	/** Current start offset of the data in the buffer.  If negative, buffer is closed. */
+	private int start;
+
+	/** The buffer. */
+	private byte[] buffer;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/Log.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/Log.java
new file mode 100644
index 0000000..cb4ee3b
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/Log.java
@@ -0,0 +1,280 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/** The log.
+ *
+ * This class represents the application- or applet-wide logging facility.  If your
+ * application needs to log messages, here's your class.
+ *
+ * <p>To log a message, you call one of the <code>get</code> methods of this class to
+ * yield a {@link LogWriter} object.  You can then call methods like {@link
+ * LogWriter#println(String)} to log a line of text.  A typical invocation is
+ *
+ * <pre>Log.get().println("Buffer of length " + length + " allocated.");</pre>
+ *
+ * <p>This logs the given text using the default source string, and under the default
+ * category, and timestamped with the current time.  You can reuse the
+ * <code>LogWriter</code>, but the timestamp, source, and category won't change.  You
+ * should get a fresh <code>LogWriter</code>.
+ *
+ * <p><strong>Sources</strong> identify independent origins of log messages, such as
+ * independent threads in a program, or independent programs.  Sources are just strings.
+ * If you don't specify a source, you get a default source.  You can set the default
+ * source with {@link #setDefaultSource}.  You <em>always</em> get a source with every
+ * message, even if it's a default source.  If you don't otherwise set a default source
+ * string, the source is "app".
+ *
+ * <p><strong>Categories</strong> identify different classes or priorites of messages.
+ * Categories can be simple strings like "warning" or "debug", or they can be complex
+ * objects.  You get to define your categories.  Your group ought to agree on categories,
+ * though.  If you don't specify a category, you get a default category.  You can set the
+ * default category with {@link #setDefaultCategory}.  If you don't call that method, the
+ * default category is the String object "message".
+ *
+ * <p><strong>Streams</strong> identify independent activities within a program, which
+ * often have transient lifespans.  They're <em>not</em> separate output streams, but
+ * instead are separate, named entities representing separate activities (although a
+ * {@link LogListener} may put messages into separate output streams identified by each
+ * stream).  Activity streams are identified by strings.  To indicate the start and stop
+ * of streams, call {@link #startStream} and {@link #stopStream}.  These send
+ * stream-started and stream-stopped events to the log listeners, who may choose to pay
+ * attention to them or ignore them.  You can use streams to indicate to the log the start
+ * and the stop of activities such as an analyst examining the system, or a server
+ * handling a particular client.
+ *
+ * <p>All messages logged with this class go to one or more {@link LogListener} objects.
+ * A LogListener accepts logging events, such as a message being logged, and does
+ * something with it, such as writing the message to a file.  Call {@link #addLogListener}
+ * to add a log listener.  Logging of a message, starting a stream, and stopping a stream
+ * all get turned into {@link LogEvent}s and are multicasted to every registered listener.
+ *
+ * <p>The logging facility bootstraps itself with one or more log listeners specified by
+ * the system property <code>org.apache.oodt.commons.io.Log.loggers</code>.  This property must be a
+ * space-separated list of complete class names.  The logging facility will create an
+ * object of each class listed and add it as if you had called
+ * <code>addLogListener</code>.  (You can specify system properties on the command line or
+ * in the applet tag.)
+ *
+ * @see LogListener
+ * @see LogWriter
+ * @author Kelly
+ */
+public class Log {
+	/** Currently registered LogListeners.
+	 */
+	private static Vector listeners;
+
+	static {
+		listeners = new Vector();
+		String loggers = System.getProperty("org.apache.oodt.commons.io.Log.loggers", "");
+		StringTokenizer tokenizer = new StringTokenizer(loggers);
+		while (tokenizer.hasMoreTokens()) {
+			String className = tokenizer.nextToken();
+			try {
+				Class clazz = Class.forName(className);
+				LogListener listener = (LogListener) clazz.newInstance();
+				addLogListener(listener);
+			} catch (Exception e) {
+				System.err.println("Can't create log listener object from class " + className + ": " + e);
+				System.exit(1);
+			}
+		}
+	}
+
+	/** Get a writer to log messages.
+	 *
+	 * The writer will log messages with the current time, default category, and
+	 * default source.  Messages will go into the general log.
+	 *
+	 * @return A writer with which you can log messages.
+	 */
+	public static LogWriter get() {
+		if (lastWriter != null && !lastWriter.isFlushed())
+			return lastWriter;
+		else
+			return get(new Date(), getDefaultSource(), getDefaultCategory());
+	}
+
+	/** Get a writer to log messages.
+	 *
+	 * The writer will log messages with the current time, specified category, and
+	 * default source.  Messages will go into the general log.
+	 *
+	 * @param category The messages' category.
+	 * @return A writer with which you can log messages.
+	 */
+	public static LogWriter get(Object category) {
+		return get(new Date(), getDefaultSource(), category);
+	}
+
+	/** Get a writer to log messages.
+	 *
+	 * The writer will log messages with the specified time, specified category, and
+	 * specified source.
+	 *
+	 * @param timestamp The time for messages logged with the returned writer.
+	 * @param source The source of the log message.
+	 * @param category The messages' category.
+	 * @return A writer with which you can log messages.
+	 */
+	public static synchronized LogWriter get(Date timestamp, String source, Object category) {
+		lastWriter = new LogWriter(timestamp, source, category);
+		return lastWriter;
+	}
+
+	/** Start a new log stream.
+	 *
+	 * This method notifies the {@link LogListener}s that a new logging stream has
+	 * started.
+	 *
+	 * @param stream The name of the stream.
+	 * @param timestamp The time the stream started.  To use the current time, pass a new {@link Date} object.
+	 * @param source A string identifying who or what started the stream.
+	 */
+	public static void startStream(String stream, Date timestamp, String source) {
+		LogEvent event = null;
+		for (Enumeration e = listeners.elements(); e.hasMoreElements();) {
+			// Lazily create the event.
+			if (event == null)
+				event = new LogEvent(stream, timestamp, source);
+			((LogListener) e.nextElement()).streamStarted(event);
+		}
+	}
+
+	/** Stop a stream.
+	 *	    
+	 * This method notifies the {@link LogListener}s that a logging stream has stopped.
+	 *
+	 * @param stream The name of the stream that stopped.
+	 */
+	public static void stopStream(String stream) {
+		LogEvent event = null;
+		for (Enumeration e = listeners.elements(); e.hasMoreElements();) {
+			// Lazily create the event.
+			if (event == null)
+				event = new LogEvent(stream);
+			((LogListener) e.nextElement()).streamStopped(event);
+		}
+	}
+
+	/** Log a message.
+	 *
+	 * The {@link LogWriter}s call this when they've built up a complete message and
+	 * want it multicasted to the {@link LogListener}s.
+	 *
+	 * @param timestamp The message's timestamp.
+	 * @param source The source label of the message.
+	 * @param category The message's category.
+	 * @param message The message.
+	 */
+	static void logMessage(Date timestamp, String source, Object category, String message) {
+		LogEvent event = null;
+		for (Enumeration e = listeners.elements(); e.hasMoreElements();) {
+			// Lazily create the event.
+			if (event == null)
+				event = new LogEvent(timestamp, source, category, message);
+			((LogListener) e.nextElement()).messageLogged(event);
+		}
+	}
+
+	/** Set the default source.
+	 *
+	 * This sets the default source label used for logging.
+	 *
+	 * @param source The new default source label.
+	 */
+	public static void setDefaultSource(String source) {
+		if (source == null)
+			throw new IllegalArgumentException("Can't set a null default source");
+		defaultSource = source;
+	}
+
+	/** Get the default source.
+	 *
+	 * @return The default source label.
+	 */
+	public static String getDefaultSource() {
+		return defaultSource;
+	}
+
+	/** Set the default category.
+	 *
+	 * This sets the category object that's used by default for logging.
+	 *
+	 * @param category The new default category object.
+	 */
+	public static void setDefaultCategory(Object category) {
+		if (category == null)
+			throw new IllegalArgumentException("Can't set a null default category");
+		defaultCategory = category;
+	}
+
+	/** Get the default category.
+	 *
+	 * @return The default category object.
+	 */
+	public static Object getDefaultCategory() {
+		return defaultCategory;
+	}
+	
+	/** Add a log listener.
+	 *
+	 * The listener will be notified whenever a message is logged, a stream started,
+	 * or a stream stopped.
+	 *
+	 * @param listener The listener to add.
+	 */
+	public static void addLogListener(LogListener listener) {
+		if (listener == null)
+			throw new IllegalArgumentException("Can't add a null log listener");
+		listeners.addElement(listener);
+	}
+
+	/** Remove a log listener.
+	 *  
+	 * The listener won't receive anymore events unless it's added back.
+	 *
+	 * @param listener The listener to remove.
+	 */
+	public static void removeLogListener(LogListener listener) {
+		if (listener == null)
+			throw new IllegalArgumentException("Can't remove a null log listener");
+		listeners.removeElement(listener);
+	}
+
+	/** The default source label.
+	 */
+	private static String defaultSource = "app";
+
+	/** The default category object.
+	 */
+	private static Object defaultCategory = "message";
+
+	/** Last log writer created so it can be reused. */
+	private static LogWriter lastWriter;
+
+	/** Don't allow instantiation.
+	 *
+	 * When we convert to Java 2, this should throw UnsupportedOperationException.
+	 */
+	private Log() {}
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LogEvent.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LogEvent.java
new file mode 100644
index 0000000..9666880
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LogEvent.java
@@ -0,0 +1,172 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.util.Date;
+import java.util.EventObject;
+
+/** Logging event.
+ *
+ * A logging event is generated and delivered to all registered log listeners when a
+ * message was logged, a logging stream was started, or when a logging stream was stopped.
+ *
+ * <p>Use the various query methods to determine the details of the event.  The event
+ * source (from {@link EventObject#getSource}) is always a {@link String}.
+ *
+ * @see Log
+ * @see LogListener
+ * @author Kelly
+ */
+public class LogEvent extends EventObject {
+	/** Create a "message logged" event.
+	 *
+	 * @param timestamp The message's timestamp.
+	 * @param source The source label of the message.
+	 * @param category The message's category.
+	 * @param message The message.
+	 */
+	public LogEvent(Date timestamp, String source, Object category, String message) {
+		super(source);
+		type = MSG_LOGGED;
+		this.timestamp = timestamp;
+		this.category = category;
+		this.message = message;
+	}
+
+	/** Create a "stream started" event.
+	 *
+	 * @param stream The name of the stream.
+	 * @param timestamp The time the stream started.
+	 * @param source A string identifying who or what started the stream.
+	 */
+	public LogEvent(String stream, Date timestamp, String source) {
+		super(source);
+		type = STREAM_STARTED;
+		this.stream = stream;
+		this.timestamp = timestamp;
+	}
+
+	/** Create a "stream stopped" event.
+	 *
+	 * @param stream The name of the stream.
+	 */
+	public LogEvent(String stream) {
+		super(stream);
+		type = STREAM_STOPPED;
+		this.stream = stream;
+	}
+
+	/** Get the category.
+	 *
+	 * For message logged events, this is the category for the message. For all other
+	 * events, this returns null.
+	 *
+	 * @return The category, or null.
+	 */
+	public Object getCategory() {
+		return category;
+	}
+
+	/** Get the message.
+	 *  
+	 * For message logged events, this is the actual message text. For all other
+	 * events, this returns null.
+	 *
+	 *@return The message, or null.
+	 */
+	public String getMessage() {
+		return message;
+	}
+
+	/** Get the stream.
+	 *
+	 * For stream started and stopped events, this is the name of the stream that was
+	 * started or stopped.  For message logged events, this is null.
+	 *
+	 * @return The stream, or null.
+	 */
+	public String getStream() {
+		return stream;
+	}
+
+	/** Get the timestamp.
+	 *
+	 * For message logged and stream started events, this is the timestamp of the
+	 * event.  For stream stopped events, this is null.
+	 *
+	 * @return The timestamp, or null.
+	 */
+	public Date getTimestamp() {
+		return timestamp;
+	}
+
+	/** Return a string representation of this event.
+	 *
+	 * @return A string identifying the type of the event.
+	 */
+	public String toString() {
+		switch (type) {
+			case MSG_LOGGED:
+				return "Log Event (message logged)";
+			case STREAM_STARTED:
+				return "Log Event (stream started)";
+			case STREAM_STOPPED:
+				return "Log Event (stream stopped)";
+			default:
+				return "Unknown Log Event Type";
+		}
+	}
+
+	/** The timestamp: null if this is a "stream stopped" event.
+	 */
+	private Date timestamp;
+
+	/** The stream: null for logging.
+	 */
+	private String stream;
+
+	/** The category: null for stream started/stopped events.
+	 */
+	private Object category;
+
+	/** The message: nonnull only for "message logged" events.
+	 */
+	private String message;
+
+	/** The type of event this is.
+	 *
+	 * This gets one of the values <code>MSG_LOGGED</code>, <code>STREAM_STARTED</code>, or <code>STREAM_STOPPED</code>.
+	 */
+	private int type;
+
+	/** The "message logged" event type.
+	 *
+	 * @see #type
+	 */
+	private static final int MSG_LOGGED = 1;
+
+	/** The "stream started" event type.
+	 *
+	 * @see #type
+	 */
+	private static final int STREAM_STARTED = 2;
+
+	/** The "stream stopped" event type.
+	 *
+	 * @see #type
+	 */
+	private static final int STREAM_STOPPED = 3;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LogFilter.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LogFilter.java
new file mode 100644
index 0000000..714a186
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LogFilter.java
@@ -0,0 +1,144 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.util.Hashtable;
+
+/** A filter for log messages.
+ *
+ * This is a {@link LogListener} that filters out and passes through certain categories of
+ * log messages to another <code>LogListener</code>.  When you construct this listener,
+ * you pass a boolean flag that indicates its pass-through mode: if true, it passes log
+ * messages by default and filters out specified categories; if false, it filters out
+ * messages by default and passes through specified categories.
+ *
+ * <p>Note that this filter only affects events sent to {@link LogListener#messageLogged}.
+ * Events sent to {@link LogListener#streamStarted} and {@link LogListener#streamStopped}
+ * are passed through regardless.
+ *
+ * <p>Categories used by this filter should implement their {@link Object#hashCode} and
+ * {@link Object#equals} methods.
+ *
+ * @see Log
+ * @author Kelly
+ */
+public class LogFilter implements LogListener {
+	/** Create a log filter.
+	 *
+	 * The log filter passes through and filters out messages before sending them onto
+	 * the given log listener.
+	 *
+	 * @param listener What object will get filtered log messages.
+	 * @param passThrough If true, pass messages through by default and filter out the
+	 * specified <var>categories</var> of messages. If false, filter out messages by
+	 * default and pass through the specified <var>categories</var>.
+	 * @param categories Categories of messages to filter out (if
+	 * <var>passThrough</var> is true) or to pass through (if <var>passThrough</var>
+	 * is false).
+	 */
+	public LogFilter(LogListener listener, boolean passThrough, Object[] categories) {
+		if (listener == null)
+			throw new IllegalArgumentException("Can't filter messages to a null listener");
+		this.listener = listener;
+		this.passThrough = passThrough;
+		if (categories == null) return;
+		for (int i = 0; i < categories.length; ++i)
+			this.categories.put(categories[i], DUMMY);
+	}
+
+	/** Create a log filter.
+	 *  
+	 * The log filter passes through and filters out messages before sending them onto
+	 * the given log listener. The filter starts out empty (with no categories).
+	 *
+	 * @param listener What object will get filtered log messages.
+	 * @param passThrough If true, pass messages through by default. If false, filter out messages by default.
+	 */
+	public LogFilter(LogListener listener, boolean passThrough) {
+		this(listener, passThrough, /*categories*/null);
+	}
+
+	/** Add an additional category.
+	 *
+	 * If the filter is in pass-through mode, messages in this category will be
+	 * filtered out. If the filter is in filter mode, messages in this category will
+	 * be passed through.
+	 *
+	 * @param category The category to add.
+	 */
+	public void addCategory(Object category) {
+		categories.put(category, DUMMY);
+	}
+
+	/** Remove a category.
+	 *
+	 * If the category isn't in the filter, nothing happens.
+	 *
+	 * @param category The category to remove.
+	 */
+	public void removeCategory(Object category) {
+		categories.remove(category);
+	}
+
+	/** Pass on the event unmodified to the registered listener.
+	 *
+	 * @param event The event to pass.
+	 */
+	public void streamStarted(LogEvent event) {
+		listener.streamStarted(event);
+	}
+
+	/** Pass on the event unmodified to the registered listener.
+	 *
+	 * @param event The event to pass.
+	 */
+	public void streamStopped(LogEvent event) {
+		listener.streamStopped(event);
+	}
+
+	/** Filter the event, and possibly pass it onto the registered listener.
+	 *
+	 * @param event The event to filter.
+	 */
+	public void messageLogged(LogEvent event) {
+		boolean found = categories.containsKey(event.getCategory());
+		if ((passThrough && !found) || (!passThrough && found))
+			listener.messageLogged(event);
+	}
+
+	/** Ignore this event.
+	 */
+	public void propertyChange(java.beans.PropertyChangeEvent ignore) {}
+
+	/** If true, pass through by default, otherwise filter out by default.
+	 */
+	protected boolean passThrough;
+
+	/** Table of categories to filter/pass.
+	 *
+	 * This table maps all values to {@link #DUMMY}.  In Java2, we can get rid of
+	 * <code>DUMMY</code> and use a {@link java.util.HashSet} instead.
+	 */
+	protected Hashtable categories = new Hashtable();
+
+	/** The DUMMY value for all mappings in the {@link #categories} table.
+	 */
+	protected static final Object DUMMY = new Object();
+
+	/** The listener on whose behalf we filter.
+	 */
+	protected LogListener listener;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LogListener.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LogListener.java
new file mode 100644
index 0000000..49b18a7
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LogListener.java
@@ -0,0 +1,69 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.util.EventObject;
+
+/** Listener for logging events.
+ *
+ * Objects of classes that implement this interface are notified when messages are logged
+ * and when other logging events occur.
+ *
+ * @see Log
+ * @see LogEvent
+ * @author Kelly
+ */
+public interface LogListener extends java.beans.PropertyChangeListener {
+	/** A message got logged.
+	 *
+	 * The <var>event</var> contains the details of the message, including
+	 * 
+	 * <ul>
+	 *   <li>The timestamp of the message, from {@link LogEvent#getTimestamp}.</li>
+	 *   <li>The source of the message, from {@link EventObject#getSource}, which is always
+	 *     a {@link String}.</li>
+	 *   <li>The category of the message, from {@link LogEvent#getCategory}.</li>
+	 *   <li>The message text, from {@link LogEvent#getMessage}.</li>
+	 * </ul>
+	 *
+	 * @param event The logging event.
+	 */
+	void messageLogged(LogEvent event);
+
+	/** A stream got started.
+	 *
+	 * The <var>event</var> contains the details of stream start, including 
+	 *
+	 * <ul>
+	 *   <li>The name of the stream, from {@link LogEvent#getStream}.</li>
+	 *   <li>The time the stream got started, from {@link LogEvent#getTimestamp}</li>
+	 *   <li>The source of the new stream start, from {@link EventObject#getSource} (always a {@link String}).</li>
+	 * </ul>
+	 *
+	 * @param event The logging event.
+	 */
+	void streamStarted(LogEvent event);
+
+	/** A stream was stopped.
+	 *
+	 * The <var>event</var> contains the detail of the stream stop, which is the name
+	 * of the stream, from {@link LogEvent#getStream} or {@link EventObject#getSource}
+	 * (always a {@link String}).
+	 *
+	 * @param event The logging event.
+	 */
+	void streamStopped(LogEvent event);
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LogWriter.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LogWriter.java
new file mode 100644
index 0000000..2f8f37b
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LogWriter.java
@@ -0,0 +1,375 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.util.Date;
+
+/** A writer for log messages.
+ *
+ * Objects of this class let you write messages into the logging facility. You get these
+ * objects by calling one of the <code>get</code> methods of class {@link Log} and use it
+ * as you would use a {@link java.io.PrintWriter}. This class automatically flushes a message to
+ * the logging facility whenever you call one of the <code>println</code> methods, or
+ * {@link #flush}. It prints all values and objects using the platform's default character
+ * encoding.
+ *
+ * <p>Note that the <code>println</code> methods of this class don't actually write
+ * <em>any</em> line separation characters into the log.  Log listeners will want the
+ * messages without such characters anyway, so this is the correct behavior.
+ *
+ * @see Log
+ * @author Kelly
+ */
+public class LogWriter extends java.io.Writer {
+	/** Constructor.
+	 *
+	 * @param timestamp The time for messages logged with the returned writer.
+	 * @param source The source of the log message.
+	 * @param category The messages' category.
+	 */
+	LogWriter(Date timestamp, String source, Object category) {
+		buf = new StringBuffer(/*length*/ 80);
+		lock = buf;
+		this.timestamp = timestamp;
+		this.source = source;
+		this.category = category;
+		flushed = false;
+	}
+
+	/** Write a single character.
+	 *
+	 * This writes a single character (the low order 16 bits of c) to the log
+	 * writer. The character isn't flushed to the logging facility until you call one
+	 * of the <code>println</code> methods or {@link #flush}.
+	 *
+	 * @param c The character to write.
+	 */
+	public void write(int c) {
+		if (buf == null) return;
+		buf.append((char) c);
+	}
+
+	/** Write a portion of an array of characters.
+	 *
+	 * This writes the given character array starting at offset and going for length bytes.
+	 *
+	 * @param array The character array to write.
+	 * @param offset Where in the array to get characters to write.
+	 * @param length How many characters to write.
+	 */
+	public void write(char[] array, int offset, int length) {
+		if (buf == null || length == 0) return;
+		if (offset < 0 || offset > array.length || length < 0 || (offset+length) > array.length || (offset+length) < 0)
+			throw new IndexOutOfBoundsException("Can't write " + length + " characters at " + offset
+				+ " from array whose length is " + array.length);
+		buf.append(array, offset, length);
+	}
+
+	/** Write an array of characters.
+	 *
+	 * This writes the entire given array.
+	 *
+	 * @param array Array of characters to write.
+	 */
+	public void write(char[] array) {
+		write(array, 0, array.length);
+	}
+
+	/** Write a portion of a string.
+	 *
+	 * This writes length characters from the given string, starting offset characters
+	 * into it.
+	 *
+	 * @param string The string to write.
+	 * @param offset Where in the string to get characters to write.
+	 * @param length How many characters to write.
+	 */
+	public void write(String string, int offset, int length) {
+		if (buf == null || length == 0) return;
+		buf.append(string.substring(offset, offset + length));
+	}
+
+	/** Write a string.
+	 *
+	 * This writes the entire given string.
+	 *
+	 * @param string String to write.
+	 */
+	public void write(String string) {
+		write(string, 0, string.length());
+	}
+
+	/** Flush the log writer.
+	 *
+	 * This sends any text sent to the writer on its way to the logging facility, and beyond.
+	 */
+	public void flush() {
+		if (buf == null) return;
+		Log.logMessage(timestamp, source, category, buf.toString());
+		buf.setLength(0);
+		flushed = true;
+	}
+
+	/** Close the log writer.
+	 *
+	 * <p>This flushes any remaining text to the logging facility and then shuts down
+	 * the log writer. You can't use it again after that (but closing a previously
+	 * closed log writer is OK).
+	 */
+	public void close() {
+		flush();
+		buf = null;
+	}
+
+	/** Print a boolean value.
+	 *
+	 * This prints a boolean value ("true" or "false") into the log.
+	 *
+	 * @param b The <code>boolean</code> to print.
+	 */
+	public void print(boolean b) {
+		write(b? "true" : "false");
+	}
+
+	/** Print a character.
+	 *
+	 * The character is translated into one or more bytes according to the platform's
+	 * default character encoding.
+	 *
+	 * @param c The <code>char</code> to print.
+	 */
+	public void print(char c) {
+		write(String.valueOf(c));
+	}
+
+	/** Print an integer.
+	 *
+	 * @param i The <code>int</code> to print.
+	 */
+	public void print(int i) {
+		write(String.valueOf(i));
+	}
+
+	/** Print a long integer.
+	 *
+	 * @param l The <code>long</code> to print.
+	 */
+	public void print(long l) {
+		write(String.valueOf(l));
+	}
+
+	/** Print a floating-point number.
+	 *
+	 * @param f The <code>float</code> to print.
+	 */
+	public void print(float f) {
+		write(String.valueOf(f));
+	}
+
+	/** Print a double-precision floating-point number.
+	 *
+	 * @param d The <code>double</code> to print.
+	 */
+	public void print(double d) {
+		write(String.valueOf(d));
+	}
+
+	/** Print an array of characters.
+	 *
+	 * @param a The array of chars to print.
+	 */
+	public void print(char[] a) {
+		write(a);
+	}
+
+	/** Print a string.
+	 *
+	 * If the argument is <code>null</code> then the string
+	 * "null" is printed.
+	 *
+	 * @param s The <code>String</code> to print.
+	 */
+	public void print(String s) {
+		if (s == null) s = "null";
+		write(s);
+	}
+
+	/** Print an object.
+	 *
+	 * @param obj The <code>Object</code> to print.
+	 */
+	public void print(Object obj) {
+		write(String.valueOf(obj));
+	}
+
+	/** Print a boolean value and terminate the message.
+	 *
+	 * This prints a boolean into the log, and flushes the message to the logging
+	 * facility.
+	 *
+	 * @param b The <code>boolean</code> to print.
+	 */
+	public void println(boolean b) {
+		print(b);
+		println();
+	}
+
+	/** Print a character value and terminate the message.
+	 *
+	 * This prints a character into the log, and flushes the message to the logging
+	 * facility.
+	 *
+	 * @param c The <code>char</code> to print.
+	 */
+	public void println(char c) {
+		print(c);
+		println();
+	}
+
+	/** Print an integer value and terminate the message.
+	 *
+	 * This prints an integer into the log, and flushes the message to the logging
+	 * facility.
+	 *
+	 * @param i The <code>int</code> to print.
+	 */
+	public void println(int i) {
+		print(i);
+		println();
+	}
+
+	/** Print a long integer value and terminate the message.
+	 *
+	 * This prints a long integer into the log, and flushes the message to the logging
+	 * facility.
+	 *
+	 * @param l The <code>long</code> to print.
+	 */
+	public void println(long l) {
+		print(l);
+		println();
+	}
+
+	/** Print a floating-point value and terminate the message.
+	 *
+	 * This prints a floating-point value into the log, and flushes the message to the
+	 * logging facility.
+	 *
+	 * @param f The <code>float</code> to print.
+	 */
+	public void println(float f) {
+		print(f);
+		println();
+	}
+
+	/** Print a double-precision floating-point value and terminate the message.
+	 *
+	 * This prints a double-precision floating-point into the log, and flushes the
+	 * message to the logging facility.
+	 *
+	 * @param d The <code>double</code> to print.
+	 */
+	public void println(double d) {
+		print(d);
+		println();
+	}
+
+	/** Print a character array and terminate the message.
+	 *
+	 * This prints a character array into the log, and flushes the message to the
+	 * logging facility.
+	 *
+	 * @param a The array of chars to print.
+	 */
+	public void println(char[] a) {
+		print(a);
+		println();
+	}
+
+	/** Print a String and terminate the message.
+	 *
+	 * This prints a String into the log, and flushes the message to the logging
+	 * facility.
+	 *
+	 * @param s The <code>String</code> to print.
+	 */
+	public void println(String s) {
+		print(s);
+		println();
+	}
+
+	public void println(Throwable t) {
+		if (t == null) 
+			println("Null throwable");
+		else {
+			StackTraceElement[] frames = t.getStackTrace();
+			if (frames == null)
+				println("Null stack trace in " + t.getClass().getName());
+			else {
+				println(t.getClass().getName() + ":");
+				for (int i = 0; i < frames.length; ++i)
+					println(frames[i]);
+			}
+		}
+	}
+
+	/** Print an Object and terminate the message.
+	 *
+	 * This prints an Object into the log, and flushes the message to the logging
+	 * facility.
+	 *
+	 * @param obj The <code>Object</code> to print.
+	 */
+	public void println(Object obj) {
+		print(obj);
+		println();
+	}
+
+	/** Terminate the current message.
+	 *
+	 * This terminates any message text built up and sends it to the logging facility.
+	 */
+	public void println() {
+		flush();
+	}
+
+	/** Are we flushed yet?
+	 *
+	 * @return True if flushed, false otherwise.
+	 */
+	public boolean isFlushed() {
+		return flushed;
+	}
+
+	/** The buffer used to build up the message.  If this is null, then the writer is closed.
+	 */
+	private StringBuffer buf;
+
+	/** The timestamp this LogWriter will use for log messages.
+	 */
+	private Date timestamp;
+
+	/** The source label.
+	 */
+	private String source;
+
+	/** The category of messages generated by this writer.
+	 */
+	private Object category;
+
+	/** Flushed yet? */
+	private boolean flushed;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LoggerOutputStream.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LoggerOutputStream.java
new file mode 100644
index 0000000..fede09e
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/LoggerOutputStream.java
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.commons.io;
+
+//JDK imports
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.CharBuffer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * {@link OutputStream} wrapper around a java {@link Logger}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class LoggerOutputStream extends OutputStream {
+
+   public static final String NUM_BYTES_PER_WRITE_PROPERTY =
+         "org.apache.oodt.commons.io.logger.os.bytes.per.write";
+   private static final int NUM_BYTES_PER_WRITE = Integer.getInteger(
+         NUM_BYTES_PER_WRITE_PROPERTY, 512);
+
+   private Logger logger;
+   private CharBuffer buffer;
+   private Level logLevel;
+
+   public LoggerOutputStream(Logger logger) throws InstantiationException {
+      this(logger, Level.INFO);
+   }
+
+   public LoggerOutputStream(Logger logger, Level logLevel)
+         throws InstantiationException {
+      this(logger, NUM_BYTES_PER_WRITE, logLevel);
+   }
+
+   public LoggerOutputStream(Logger logger, int numOfBytesPerWrite)
+         throws InstantiationException {
+      this(logger, numOfBytesPerWrite, Level.INFO);
+   }
+
+   public LoggerOutputStream(Logger logger, int numOfBytesPerWrite,
+         Level logLevel) throws InstantiationException {
+      this.logger = logger;
+      this.buffer = CharBuffer.wrap(new char[numOfBytesPerWrite]);
+      this.logLevel = logLevel;
+   }
+
+   @Override
+   public void write(int b) throws IOException {
+      if (!buffer.hasRemaining()) {
+         flush();
+      }
+      buffer.put((char) b);
+   }
+
+   @Override
+   public void flush() {
+      if (buffer.position() > 0) {
+         char[] flushContext = new char[buffer.position()];
+         System.arraycopy(buffer.array(), 0, flushContext, 0, buffer.position());
+         logger.log(logLevel, new String(flushContext));
+         buffer.clear();
+      }
+   }
+
+   @Override
+   public void close() throws IOException {
+      flush();
+      super.close();
+   }
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/NullInputStream.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/NullInputStream.java
new file mode 100644
index 0000000..dae6dab
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/NullInputStream.java
@@ -0,0 +1,62 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An input stream that's always empty.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+public final class NullInputStream extends InputStream {
+        /**
+	 * Construct a null input stream.
+         */
+        public NullInputStream() {
+                open = true;
+        }
+
+        /**
+	 * Read a byte, which you can't do, so you always get -1 to indicate end-of-file.
+         *
+         * @return -1 to indicate end of file.
+         * @throws IOException If the stream is closed.
+         */
+        public int read() throws IOException {
+                checkOpen();
+                return -1;
+        }
+
+        public void close() throws IOException {
+                checkOpen();
+                open = false;
+        }
+
+        /**
+	 * Check if we're open.
+         *
+         * @throws IOException If we're not open.
+         */
+        private void checkOpen() throws IOException {
+                if (!open) throw new IOException("Stream closed");
+        }
+
+        /** Is the stream open? */
+        private boolean open;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/NullOutputStream.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/NullOutputStream.java
new file mode 100644
index 0000000..0190c03
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/NullOutputStream.java
@@ -0,0 +1,88 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.io.*;
+import java.util.*;
+
+/** A null output stream.
+ *
+ * This output stream throws away all data it gets.
+ *
+ * @author Kelly
+ */
+public class NullOutputStream extends OutputStream {
+	/** Construct a null output stream.
+	 */
+	public NullOutputStream() {
+		open = true;
+	}
+
+	/** Write a byte to the output stream, which is thrown away.
+	 *
+	 * @param b The byte to toss.
+	 * @throws IOException If the stream is closed.
+	 */
+	public void write(int b) throws IOException {
+		checkOpen();
+	}
+
+	/** Write a byte array to the output stream, which is thrown away.
+	 *
+	 * @param a The array to write.
+	 * @param offset Where in the array to ignore bytes to write.
+	 * @param length How many bytes to ignore.
+	 * @throws IOException If the stream is closed.
+	 */
+	public void write(byte[] a, int offset, int length) throws IOException {
+		if (a == null)
+			throw new NullPointerException("Can't write a null array");
+		else if ((offset < 0) || (offset > a.length) || (length < 0) || ((offset + length) > a.length)
+			|| ((offset + length) < 0))
+			throw new IndexOutOfBoundsException("Offset " + offset + " and length " + length
+				+ " not in array of length " + a.length);
+		checkOpen();
+	}
+
+	/** Flush an output stream, which does nothing.
+	 *
+	 * @throws IOException If the stream is closed.
+	 */
+	public void flush() throws IOException {
+		checkOpen();
+	}
+
+	/** Close an output stream.
+	 *
+	 * @throws IOException If the stream is already closed.
+	 */
+	public void close() throws IOException {
+		checkOpen();
+		open = false;
+	}
+
+	/** Check if we're open.
+	 *
+	 * @throws IOException If we're not open.
+	 */
+	private void checkOpen() throws IOException {
+		if (!open) throw new IOException("Stream closed");
+	}
+
+	/** Is the output stream open? */
+	private boolean open;
+}
+
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/WriterLogger.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/WriterLogger.java
new file mode 100644
index 0000000..7fbdaea
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/WriterLogger.java
@@ -0,0 +1,166 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.io.Writer;
+import java.io.IOException;
+import org.apache.oodt.commons.util.*;
+
+/** Log messages to a <code>Writer</code>.
+ *
+ * This class defines a {@link LogListener} that logs its messages to a character stream
+ * {@link Writer}.  This formats and writes to the output stream all log events passed to
+ * {@link LogListener#messageLogged}, one per line.  Each line is separated with the
+ * system's line separator characters, specified by the <code>line.separator</code> system
+ * property.
+ *
+ * <p>It ignores all events passed to {@link LogListener#streamStarted} and
+ * {@link LogListener#streamStopped}.
+ *
+ * <p>It quietly hides all IO errors that may occur during writing.
+ *
+ * @see Log
+ * @author Kelly
+ */
+public class WriterLogger implements LogListener {
+	/** Constructor given an output stream.
+	 *
+	 * Construct a writer logger that writes message events to the given output stream
+	 * and flushes the stream after every logged message.
+	 *
+	 * @param outputStream The output stream to which to write events.
+	 */
+	public WriterLogger(java.io.OutputStream outputStream) {
+		this(new java.io.BufferedWriter(new java.io.OutputStreamWriter(outputStream)), /*autoFlush*/ true);
+	}
+
+	/** Constructor given a writer.
+	 *
+	 * Construct a writer logger that writes message events to the given writer and
+	 * flushes the stream after every logged message.
+	 *
+	 * @param writer The writer to which to write events.
+	 */
+	public WriterLogger(Writer writer) {
+		this(writer, /*autoFlush*/ true);
+	}
+
+	/** General constructor.
+	 *
+	 * Construct a writer logger that writes message events to the given writer and
+	 * optionally flushes the stream after every logged message.
+	 *
+	 * @param writer The writer to which to write events.
+	 * @param autoFlush If true, call flush on the writer after every message
+	 * logged. If false, don't call flush.
+	 */
+	public WriterLogger(Writer writer, boolean autoFlush) {
+		if (writer == null)
+			throw new IllegalArgumentException("Can't write to a null writer");
+		this.writer = writer;
+		this.autoFlush = autoFlush;
+		this.lineSep = System.getProperty("line.separator", "\n");
+	}
+
+	/** Close the writer.
+	 *
+	 * This closes the writer to which this logger was logging.  Future message events
+	 * are ignored and not written.
+	 */
+	public final void close() {
+		if (writer == null) return;
+		try {
+			writer.close();
+		} catch (IOException ignore) {}
+		writer = null;
+	}
+
+	/** Log a message to the writer.
+	 *
+	 * This method first calls {@link #formatMessage} to format the message, and then
+	 * writes the message to the output stream.  
+	 * 
+	 * @param event The event describing the message that was logged.
+	 */
+	public final void messageLogged(LogEvent event) {
+		if (writer == null) return;
+		try {
+			writer.write(formatMessage(event.getTimestamp(), (String) event.getSource(), event.getCategory(),
+				event.getMessage()) + lineSep);
+			if (autoFlush) writer.flush();
+		} catch (IOException ignore) {}
+	}
+
+	/** Format a message for logging.
+	 *
+	 * This method formats a message as follows: 
+	 *
+	 * <p><code><var>epochTime</var> (<var>time</var>) <var>source</var> <var>category</var>:
+	 * <var>message</var> 
+	 *
+	 * <p>where <var>epochTime</var> is the time in milliseconds since midnight, 1st
+	 * January 1970 GMT, <var>time</var> is human-readable time, <var>source</var> is
+	 * the source of the message, <var>category</var> is the category under which the
+	 * message was logged, and <var>message</var> is the message.
+	 *
+	 * <p>You can override this method and provide your own formatting.
+	 *
+	 * @param timestamp Timestamp for the message.
+	 * @param source Source of the message.
+	 * @param category Category of the message.
+	 * @param message The message text.
+	 */
+	protected String formatMessage(java.util.Date timestamp, String source, Object category, String message) {
+		return ("\n" + DateConvert.isoFormat(timestamp) + " " + source + " " + category + ": " + message);
+	}
+
+	/** Ignore the stream started event.
+	 *
+	 * @param event The event to ignore.
+	 */
+	public void streamStarted(LogEvent event) {
+		return;
+	}
+
+	/** Ignore the stream stopped event.
+	 *
+	 * @param event The event to ignore.
+	 */
+	public void streamStopped(LogEvent event) {
+		return;
+	}
+
+	public void propertyChange(java.beans.PropertyChangeEvent ignore) {}
+
+	/** The writer to which we write log messages.
+	 *
+	 * If null, then we were closed.  This is protected so you can extend this class
+	 * and log other events normally ignored.
+	 */
+	protected Writer writer;
+	
+	/** If true, flush after every message logged.
+	 *
+	 * This is protected so you can extend this class and log other events normally ignored.
+	 */
+	protected boolean autoFlush;
+
+	/** What the line separator is.
+	 *
+	 * This is protected so you can extend this class and log other events normally ignored.
+	 */
+	protected String lineSep;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/package.html b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/package.html
new file mode 100644
index 0000000..c887802
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/io/package.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<!--
+ 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.
+-->
+<html>
+  <head>
+    <title>Apache OODT Commons: Input/Output
+    </title>
+  </head>
+  <body>
+    <p>Classes for handling input/output from various data sources and
+      sinks.
+    </p>
+  </body>
+</html>
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/net/Net.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/net/Net.java
new file mode 100644
index 0000000..87126fa
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/net/Net.java
@@ -0,0 +1,59 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.net;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/** Network utilities.
+ *
+ * @author Kelly.
+ */
+public class Net {
+	/** Return the IP address of the "localhost" loopback address.
+	 *
+	 * @return The loopback IP address, 127.0.0.1.
+	 */
+	public static InetAddress getLoopbackAddress() {
+		return loopback;
+	}
+
+	/**
+	 * Return the IP address of the local host's primary IP interface.
+	 *
+	 * @return an <code>InetAddress</code> value.
+	 */
+	public static InetAddress getLocalHost() {
+		return localHost;
+	}
+
+	/** The InetAddress of the loopback IP address, 127.0.0.1. */
+	private static InetAddress loopback = null;
+
+	/** The InetAddress of the local system's primary interface. */
+	private static InetAddress localHost = null;
+
+	/** Initialize this class. */
+	static {
+		try {
+			loopback = InetAddress.getByName(null);
+			localHost = InetAddress.getLocalHost();
+		} catch (UnknownHostException ex) {
+			System.err.println("FATAL ERROR: Cannot retrieve loopback or local address: " + ex.getMessage());
+			System.exit(1);
+		}
+	}
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/HTTPContext.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/HTTPContext.java
new file mode 100644
index 0000000..d164f99
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/HTTPContext.java
@@ -0,0 +1,236 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.object.jndi;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.NoSuchElementException;
+import javax.naming.CompositeName;
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.NotContextException;
+import javax.naming.OperationNotSupportedException;
+
+/**
+ * This is a pseudo context that yields any name passed in as a URL, if it can be parsed as an URL.
+ *
+ * @author Kelly
+ * @version $Revision: 1.2 $
+ */
+public class HTTPContext implements Context {
+	/**
+	 * Make the HTTPContext.
+	 *
+	 * @param environment Its environment, currently unused.
+	 */
+        public HTTPContext(Hashtable environment) {
+		if (environment == null)
+                        throw new IllegalArgumentException("Nonnull environment required; don't know why, but it is");
+                this.environment = (Hashtable) environment.clone();
+	}
+
+	public Object lookup(String name) throws NamingException {
+		checkName(name);
+		try {
+			return new URL(name);
+		} catch (MalformedURLException ex) {
+			throw new NamingException(ex.getMessage());
+		}
+	}
+
+	public Object lookup(Name name) throws NamingException {
+		return lookup(name.toString());
+	}
+
+	public void bind(String name, Object obj) throws NamingException {
+		checkName(name);
+		throw new OperationNotSupportedException("Not possible");
+	}
+
+	public void bind(Name name, Object obj) throws NamingException {
+		bind(name.toString(), obj);
+	}
+
+	public void rebind(String name, Object obj) throws NamingException {
+		checkName(name);
+		throw new OperationNotSupportedException("Not possible");
+	}
+
+	public void rebind(Name name, Object obj) throws NamingException {
+		rebind(name.toString(), obj);
+	}
+
+	public void unbind(String name) throws NamingException {
+		checkName(name);
+		throw new OperationNotSupportedException("Not possible");
+	}
+
+	public void unbind(Name name) throws NamingException {
+		unbind(name.toString());
+	}
+
+	public void rename(String oldName, String newName) throws NamingException {
+		checkName(newName);
+		throw new OperationNotSupportedException("Not possible");
+	}
+
+	public void rename(Name oldName, Name newName) throws NamingException {
+		rename(oldName.toString(), newName.toString());
+	}
+
+	public NamingEnumeration list(String name) throws NamingException {
+		if (name.length() > 0) 
+			throw new NotContextException("Subcontexts not supported");
+				
+		return new NamingEnumeration() {
+			public void close() {}
+			public boolean hasMore() {
+				return false;
+			}
+			public Object next() {
+				throw new NoSuchElementException();
+			}
+			public boolean hasMoreElements() {
+				return hasMore();
+			}
+			public Object nextElement() {
+				return next();
+			}
+		};
+	}
+		
+	public NamingEnumeration list(Name name) throws NamingException {
+		return list(name.toString());
+	}
+
+	public NamingEnumeration listBindings(String name) throws NamingException {
+		if (name.length() > 0) 
+			throw new NotContextException("Subcontexts not supported");
+		return new NamingEnumeration() {
+			public void close() {}
+			public boolean hasMore() {
+				return false;
+			}
+			public Object next() {
+				throw new NoSuchElementException();
+			}
+			public boolean hasMoreElements() {
+				return hasMore();
+			}
+			public Object nextElement() {
+				return next();
+			}
+		};
+	}
+
+	public NamingEnumeration listBindings(Name name) throws NamingException {
+		return listBindings(name.toString());
+	}
+
+	public void destroySubcontext(String name) throws NamingException {
+		throw new OperationNotSupportedException("Not yet implemented");
+	}
+
+	public void destroySubcontext(Name name) throws NamingException {
+		destroySubcontext(name.toString());
+	}
+
+	public Context createSubcontext(String name) throws NamingException {
+		throw new OperationNotSupportedException("Subcontexts not supported");
+	}
+
+	public Context createSubcontext(Name name) throws NamingException {
+		return createSubcontext(name.toString());
+	}
+
+	public Object lookupLink(String name) throws NamingException {
+		return lookup(name);
+	}
+
+	public Object lookupLink(Name name) throws NamingException {
+		return lookupLink(name.toString());
+	}
+
+	public NameParser getNameParser(String name) throws NamingException {
+		return nameParser;
+	}
+
+	public NameParser getNameParser(Name name) throws NamingException {
+		return getNameParser(name.toString());
+	}
+
+	public String composeName(String name, String prefix) throws NamingException {
+		Name result = composeName(new CompositeName(name), new CompositeName(prefix));
+		return result.toString();
+	}
+
+	public Name composeName(Name name, Name prefix) throws NamingException {
+		Name result = (Name) prefix.clone();
+		result.addAll(name);
+		return result;
+	}
+
+	public Object addToEnvironment(String propName, Object propVal) throws NamingException {
+		if (environment == null) environment = new Hashtable();
+		return environment.put(propName, propVal);
+	}
+
+	public Object removeFromEnvironment(String propName) throws NamingException {
+		if (environment == null) return null;
+		return environment.remove(propName);
+	}
+
+	public Hashtable getEnvironment() throws NamingException {
+		if (environment == null) return new Hashtable();
+		return (Hashtable) environment.clone();
+	}
+
+	public String getNameInNamespace() throws NamingException {
+		return "";
+	}
+
+	public void close() throws NamingException {
+		environment = null;
+	}
+
+	/**
+	 * Ensure the name is an HTTP product context name.
+	 *
+	 * @param name Name to check.
+	 * @throws InvalidNameException If <var>name</var>'s not an RMI object context name.
+	 */
+	protected void checkName(String name) throws InvalidNameException {
+		if (name == null)
+			throw new IllegalArgumentException("Can't check a null name");
+		if (name.length() == 0)
+			throw new InvalidNameException("Name's length is zero");
+		if (name.startsWith("http:") || name.startsWith("https:"))
+			return;
+		throw new InvalidNameException("Not an HTTP name; try http://some.host/some-context/...");
+	}
+
+	/** Context's environment; currently unused. */
+	private Hashtable environment;
+
+	/** Parser for object names. */
+	private static final NameParser nameParser = new ObjectNameParser();
+}
+
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/ObjectContext.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/ObjectContext.java
new file mode 100644
index 0000000..1bd38d2
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/ObjectContext.java
@@ -0,0 +1,461 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.object.jndi;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Properties;
+import javax.naming.CompositeName;
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameClassPair;
+import javax.naming.NameNotFoundException;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.OperationNotSupportedException;
+import org.apache.oodt.commons.util.Utility;
+
+/**
+ * Context for binding and looking up distributed objects.
+ *
+ * @author Kelly
+ * @version $Revision: 1.5 $
+ */
+class ObjectContext implements Context {
+	/**
+	 * Construct the object context.
+	 *
+	 * @param environment Its environment, currently unused.
+	 */
+	ObjectContext(Hashtable environment) {
+		this.environment = environment != null? (Hashtable) environment.clone() : new Hashtable();
+
+		// Add the CORBA context, but by name so we don't get a compile-time
+		// coupling with the edm-corba component, and only if CORBA's available.
+		try {
+			Class clazz = Class.forName("org.apache.oodt.commons.object.jndi.CORBAContext");
+			Constructor ctor = clazz.getConstructor(new Class[]{Hashtable.class});
+			Object corbaContext = ctor.newInstance(new Object[]{this.environment});
+			contexts.add(corbaContext);
+		} catch (Throwable ex) {}
+
+		String registryList = (String) environment.get("rmiregistries");
+		if (registryList != null) for (Iterator i = Utility.parseCommaList(registryList); i.hasNext();) {
+			Hashtable rmiEnv = (Hashtable) this.environment.clone();
+			URI uri = URI.create((String) i.next());
+			rmiEnv.put("host", uri.getHost());
+			rmiEnv.put("port", new Integer(uri.getPort()));
+			contexts.add(new RMIContext(rmiEnv));
+		}
+
+		Hashtable httpEnv = (Hashtable) this.environment.clone();
+		contexts.add(new HTTPContext(httpEnv));
+
+		String className = null;
+		for (Iterator i = org.apache.oodt.commons.util.Utility.parseCommaList(System.getProperty("org.apache.oodt.commons.object.contexts", ""));
+		        i.hasNext();) try {
+			className = (String) i.next();
+			Class clazz = Class.forName(className);
+			contexts.add(clazz.newInstance());
+		} catch (ClassNotFoundException ex) {
+			System.err.println("Ignoring not-found context class `" + className + "': " + ex.getMessage());
+		} catch (InstantiationException ex) {
+			System.err.println("Ignoring non-instantiable context class `" + className + "': " + ex.getMessage());
+		} catch (IllegalAccessException ex) {
+			System.err.println("Ignoring context class `" + className + "' with non-accessible no-args c'tor: "
+				+ ex.getMessage());
+		}
+
+		installAliases();
+		System.err.println("Object context ready; delegating to: " + contexts);
+	}
+
+	/**
+	 * Creates a new <code>ObjectContext</code> instance.  This constructor takes a
+	 * list of delegate contexts instead of building them from a passed-in
+	 * environment.  Currently, it's used solely for this class's {@link
+	 * ObjectContextTest unit test}.
+	 *
+	 * @param contexts a <code>List</code> of {@link Context}s.
+	 */
+	ObjectContext(List contexts) {
+		this.contexts = contexts;
+		installAliases();
+	}
+
+	/**
+	 * Returns the object to which the given name is bound.  Because this context
+	 * delegates to multiple other contexts, the lookup returns the first successful
+	 * match.
+	 *
+	 * @param name a <code>String</code> value.
+	 * @return an <code>Object</code> value.
+	 * @throws NamingException if an error occurs.
+	 */
+	public Object lookup(String name) throws NamingException {
+		if (name == null) throw new IllegalArgumentException("Name required");
+		if (name.length() == 0) return this;
+
+		// Let alias redirection do its magic
+		String alias = aliases.getProperty(name);
+		if (alias != null) name = alias;
+
+		for (Iterator i = contexts.iterator(); i.hasNext();) {
+			Context c = (Context) i.next();
+			try {
+				return c.lookup(name);
+			} catch (InvalidNameException ignore) {
+			} catch (NameNotFoundException ignore) {
+			} catch (NamingException ignore){}
+		}
+		throw new NameNotFoundException(name + " not found in any managed subcontext");
+	}
+
+	public Object lookup(Name name) throws NamingException {
+		return lookup(name.toString());
+	}
+
+	public synchronized void bind(String name, Object obj) throws NamingException {
+		if (name == null) throw new IllegalArgumentException("Name required");
+		if (name.length() == 0) throw new InvalidNameException("Cannot bind object named after context");
+
+		// If it's an alias name, stop here.
+		if (aliases.containsKey(name))
+			throw new NameAlreadyBoundException("Name \"" + name + "\" already bound as an aliased name");
+
+		// Make sure it isn't bound anywhere
+		for (NamingEnumeration e = list(""); e.hasMore();) {
+			NameClassPair nameClassPair = (NameClassPair) e.next();
+			if (name.equals(nameClassPair.getName()))
+				throw new NameAlreadyBoundException("Name \"" + name + "\" already bound by a managed subcontext");
+		}
+		doRebind(name, obj);
+	}
+
+	public void bind(Name name, Object obj) throws NamingException {
+		bind(name.toString(), obj);
+	}
+
+	/** {@inheritDoc} */
+	public synchronized void rebind(String name, Object obj) throws NamingException {
+		if (name == null) throw new IllegalArgumentException("Name required");
+		if (name.length() == 0) throw new InvalidNameException("Cannot rebind object named after context");
+
+		// If it's an alias name, remove the alias
+		if (aliases.containsKey(name))
+			aliases.remove(name);
+
+		doRebind(name, obj);
+	}
+
+	/**
+	 * Rebind the given name to the given object.
+	 *
+	 * @param name Name to rebind
+	 * @param obj Object to which it's bound
+	 * @throws NamingException if an error occurs.
+	 */
+	private void doRebind(String name, Object obj) throws NamingException {
+		boolean bound = false;
+		for (Iterator i = contexts.iterator(); i.hasNext();) {
+			Context c = (Context) i.next();
+			try {
+				c.rebind(name, obj);
+				bound = true;
+			} catch (NamingException ex) {}
+		}
+		if (!bound) throw new InvalidNameException("Name \"" + name + "\" not compatible with any managed subcontext");
+	}
+
+	public void rebind(Name name, Object obj) throws NamingException {
+		rebind(name.toString(), obj);
+	}
+
+	public void unbind(String name) throws NamingException {
+		if (name == null) throw new IllegalArgumentException("Name required");
+		if (name.length() == 0) throw new InvalidNameException("Cannot unbind object named after context");
+
+		// See if it's an aliased name
+		if (aliases.containsKey(name)) {
+			aliases.remove(name);
+			return;
+		}
+
+		boolean unbound = false;
+		for (Iterator i = contexts.iterator(); i.hasNext();) {
+			Context c = (Context) i.next();
+			try {
+				c.unbind(name);
+				unbound = true;
+			} catch (NamingException ignore) {}
+		}
+		if (!unbound) throw new InvalidNameException("Name \"" + name + "\" not compatible with any managed subcontext");
+	}
+
+	public void unbind(Name name) throws NamingException {
+		unbind(name.toString());
+	}
+
+	public void rename(String oldName, String newName) throws NamingException {
+		if (oldName == null || newName == null)
+			throw new IllegalArgumentException("Name required");
+		if (oldName.length() == 0 || newName.length() == 0)
+			throw new InvalidNameException("Cannot rename object named after context");
+
+		// See if it's an aliased name
+		String oldValue = (String) aliases.remove(oldName);
+		if (oldValue != null) {
+			aliases.setProperty(newName, oldName);
+			return;
+		}
+
+		boolean renamed = false;
+		for (Iterator i = contexts.iterator(); i.hasNext();) {
+			Context c = (Context) i.next();
+			try {
+				c.rename(oldName, newName);
+				renamed = true;
+			} catch (NamingException ignore) {}
+		}
+		if (!renamed) throw new InvalidNameException("Names not compatible with any managed subcontext");
+	}
+
+	public void rename(Name oldName, Name newName) throws NamingException {
+		rename(oldName.toString(), newName.toString());
+	}
+
+	public NamingEnumeration list(final String name) throws NamingException {
+		final Iterator eachContext = contexts.iterator();
+		return new NamingEnumeration() {
+			private NamingEnumeration enumeration
+				= eachContext.hasNext()? ((Context) eachContext.next()).list(name) : null;
+			private boolean open = true;
+			public Object next() throws NamingException {
+				if (!open) throw new NamingException("closed");
+				if (enumeration != null && enumeration.hasMore())
+					return enumeration.next();
+				else if (eachContext.hasNext()) {
+					enumeration = ((Context) eachContext.next()).list(name);
+					if (enumeration.hasMore())
+						return enumeration.next();
+				}
+				throw new NoSuchElementException("No more objects in context");
+			}
+			public Object nextElement() {
+				Object rc = null;
+				try {
+					rc = next();
+				} catch (NamingException ignore) {}
+				return rc;
+			}
+			public boolean hasMore() throws NamingException {
+				if (!open) return false;
+				if (enumeration == null)
+					return false;
+				else if (enumeration.hasMore())
+					return true;
+				else if (eachContext.hasNext()) {
+					enumeration = ((Context) eachContext.next()).list(name);
+					return hasMore();
+				}
+				return false;
+			}
+			public boolean hasMoreElements() {
+				boolean h = false;
+				try {
+					h = hasMore();
+				} catch (NamingException ignore) {}
+				return h;
+			}
+			public void close() throws NamingException {
+				open = false;
+				if (enumeration != null)
+					enumeration.close();
+			}
+		};
+	}
+		
+	public NamingEnumeration list(Name name) throws NamingException {
+		return list(name.toString());
+	}
+
+	public NamingEnumeration listBindings(final String name) throws NamingException {
+		final Iterator eachContext = contexts.iterator();
+		return new NamingEnumeration() {
+			private NamingEnumeration enumeration
+				= eachContext.hasNext()? ((Context) eachContext.next()).listBindings(name) : null;
+			private boolean open = true;
+			public Object next() throws NamingException {
+				if (!open) throw new NamingException("closed");
+				if (enumeration != null && enumeration.hasMore())
+					return enumeration.next();
+				else if (eachContext.hasNext()) {
+					enumeration = ((Context) eachContext.next()).listBindings(name);
+					if (enumeration.hasMore())
+						return enumeration.next();
+				}
+				throw new NoSuchElementException("No more objects in context");
+			}
+			public Object nextElement() {
+				Object rc = null;
+				try {
+					rc = next();
+				} catch (NamingException ignore) {}
+				return rc;
+			}
+			public boolean hasMore() throws NamingException {
+				if (!open) return false;
+				if (enumeration == null)
+					return false;
+				else if (enumeration.hasMore())
+					return true;
+				else if (eachContext.hasNext()) {
+					enumeration = ((Context) eachContext.next()).listBindings(name);
+					return hasMore();
+				}
+				return false;
+			}
+			public boolean hasMoreElements() {
+				boolean h = false;
+				try {
+					h = hasMore();
+				} catch (NamingException ignore) {}
+				return h;
+			}
+			public void close() throws NamingException {
+				open = false;
+				if (enumeration != null)
+					enumeration.close();
+			}
+		};
+	}
+
+	public NamingEnumeration listBindings(Name name) throws NamingException {
+		return listBindings(name.toString());
+	}
+
+	public void destroySubcontext(String name) throws NamingException {
+		throw new OperationNotSupportedException("Subcontexts not supported by ObjectContext");
+	}
+
+	public void destroySubcontext(Name name) throws NamingException {
+		destroySubcontext(name.toString());
+	}
+
+	public Context createSubcontext(String name) throws NamingException {
+		throw new OperationNotSupportedException("Subcontexts not supported by ObjectContext");
+	}
+
+	public Context createSubcontext(Name name) throws NamingException {
+		return createSubcontext(name.toString());
+	}
+
+	public Object lookupLink(String name) throws NamingException {
+		return lookup(name);
+	}
+
+	public Object lookupLink(Name name) throws NamingException {
+		return lookupLink(name.toString());
+	}
+
+	public NameParser getNameParser(String name) throws NamingException {
+		return nameParser;
+	}
+
+	public NameParser getNameParser(Name name) throws NamingException {
+		return getNameParser(name.toString());
+	}
+
+	public String composeName(String name, String prefix) throws NamingException {
+		Name result = composeName(new CompositeName(name), new CompositeName(prefix));
+		return result.toString();
+	}
+
+	public Name composeName(Name name, Name prefix) throws NamingException {
+		Name result = (Name) prefix.clone();
+		result.addAll(name);
+		return result;
+	}
+
+	public Object addToEnvironment(String propName, Object propVal) throws NamingException {
+		if (environment == null) environment = new Hashtable();
+		return environment.put(propName, propVal);
+	}
+
+	public Object removeFromEnvironment(String propName) throws NamingException {
+		if (environment == null) return null;
+		return environment.remove(propName);
+	}
+
+	public Hashtable getEnvironment() throws NamingException {
+		if (environment == null) return new Hashtable();
+		return (Hashtable) environment.clone();
+	}
+
+	public String getNameInNamespace() throws NamingException {
+		return "";
+	}
+
+	public void close() throws NamingException {
+		environment = null;
+	}
+
+	/**
+	 * Install aliases specified in the properties file.  The properties file simply
+	 * maps a string object name to a new object name.  Use the system property
+	 * <code>org.apache.oodt.commons.object.jndi.aliases</code> (preferred) or simply
+	 * <code>aliases</code> to tell the location of the properties file.
+	 */
+	private void installAliases() {
+		String aliasFileName = System.getProperty("org.apache.oodt.commons.object.jndi.aliases", System.getProperty("aliases"));
+		if (aliasFileName != null && aliasFileName.length() > 0) {
+			FileInputStream in = null;
+			try {
+				in = new FileInputStream(aliasFileName);
+				aliases.load(in);
+			} catch (IOException ex) {
+				throw new IllegalStateException("Cannot handle I/O exception reading alias file " + aliasFileName
+					+ ": " + ex.getMessage());
+			} finally {
+				if (in != null) try {
+					in.close();
+				} catch (IOException ignore) {}
+			}
+		}
+	}
+
+	/** Context's environment; currently unused. */
+	private Hashtable environment;
+
+	/** Parser for object names. */
+	private static final NameParser nameParser = new ObjectNameParser();
+
+	/** List of {@link Context}s to which we "multiplex". */
+	private List contexts = new ArrayList();
+
+	/** Aliased names. */
+	private Properties aliases = new Properties();
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/ObjectCtxFactory.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/ObjectCtxFactory.java
new file mode 100644
index 0000000..30cf715
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/ObjectCtxFactory.java
@@ -0,0 +1,30 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.object.jndi;
+
+import java.util.Hashtable;
+import javax.naming.Context;
+import javax.naming.spi.InitialContextFactory;
+
+/** JNDI context factory for object contexts.
+ *
+ * @author Kelly
+ */
+public class ObjectCtxFactory implements InitialContextFactory {
+	public Context getInitialContext(Hashtable environment) {
+		return new ObjectContext(environment);
+	}
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/ObjectNameParser.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/ObjectNameParser.java
new file mode 100644
index 0000000..3b9f06e
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/ObjectNameParser.java
@@ -0,0 +1,38 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.object.jndi;
+
+import java.util.Properties;
+import javax.naming.CompoundName;
+import javax.naming.Name;
+import javax.naming.NameParser;
+import javax.naming.NamingException;
+
+/** JNDI parser for object names.
+ *
+ * @author Kelly
+ */
+class ObjectNameParser implements NameParser {
+	private static Properties syntax = new Properties(); {
+		syntax.put("jndi.syntax.direction", "flat");
+		syntax.put("jndi.syntax.ignorecase", "false");
+	}
+	public Name parse(String name) throws NamingException {
+		return new CompoundName(name, syntax);
+	}
+}
+
+	
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/RMIContext.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/RMIContext.java
new file mode 100644
index 0000000..135a7f5
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/RMIContext.java
@@ -0,0 +1,374 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.object.jndi;
+
+import java.rmi.AlreadyBoundException;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import javax.naming.CommunicationException;
+import javax.naming.CompositeName;
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameClassPair;
+import javax.naming.NameNotFoundException;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.NotContextException;
+import javax.naming.OperationNotSupportedException;
+
+/**
+ * Context for binding and looking up distributed objects in RMI.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1 $
+ */
+
+
+
+public class RMIContext implements Context {
+	/*
+	* Construct the RMI object context.
+	* 
+	* @param host Host name.
+	* @param port Port number.
+	*/
+	public RMIContext(String host, int port) {
+        	Hashtable environment = new Hashtable();
+		environment.put("host", host);
+		environment.put("port", new Integer(port));
+		initEnv(environment);
+	}
+	
+	/**
+	 * Construct the RMI object context.
+	 *
+	 * @param environment Its environment, currently unused.
+	 */
+        public RMIContext(Hashtable environment) {
+                initEnv(environment);
+	}
+
+	/* Initializes environment
+	*
+	* @param environment Its environment, currently unused.
+	*/
+	private void initEnv(Hashtable environment) {
+		if (environment == null)
+                        throw new IllegalArgumentException("Nonnull environment required");
+                this.environment = (Hashtable) environment.clone();
+        }
+
+	public Object lookup(String name) throws NamingException {
+		checkName(name);
+		name = toRMIName(name);
+		if (name.length() == 0) return new RMIContext(environment);
+		Registry registry = getRegistry();
+		try {
+			return registry.lookup(name);
+		} catch (NotBoundException ex) {
+			throw new NameNotFoundException(name + " not found in RMI registry " + registry);
+		} catch (RemoteException ex) {
+			throw new NamingException("Remote exception: " + ex.getMessage());
+		}
+	}
+
+	public Object lookup(Name name) throws NamingException {
+		return lookup(name.toString());
+	}
+
+	public void bind(String name, Object obj) throws NamingException {
+		checkName(name);
+		Registry registry = getRegistry();
+		try {
+			registry.bind(toRMIName(name), (Remote) obj);
+		} catch (AlreadyBoundException ex) {
+			throw new NameAlreadyBoundException(name + " already bound in RMI registry " + registry);
+		} catch (RemoteException ex) {
+			throw new NamingException("Remote exception: " + ex.getMessage());
+		}
+	}
+
+	public void bind(Name name, Object obj) throws NamingException {
+		bind(name.toString(), obj);
+	}
+
+	public void rebind(String name, Object obj) throws NamingException {
+		checkName(name);
+		try {
+			Registry registry = getRegistry();
+			registry.rebind(toRMIName(name), (Remote) obj);
+		} catch (RemoteException ex) {
+			ex.printStackTrace();
+			throw new NamingException("Remote exception: " + ex.getMessage());
+		}
+	}
+
+	public void rebind(Name name, Object obj) throws NamingException {
+		rebind(name.toString(), obj);
+	}
+
+	public void unbind(String name) throws NamingException {
+		checkName(name);
+		Registry registry = getRegistry();
+		try {
+			registry.unbind(toRMIName(name));
+		} catch (NotBoundException ex) {
+			throw new NameNotFoundException(name + " not found in RMI registry " + registry);
+		} catch (RemoteException ex) {
+			throw new NamingException("Remote exception: " + ex.getMessage());
+		}
+	}
+
+	public void unbind(Name name) throws NamingException {
+		unbind(name.toString());
+	}
+
+	public void rename(String oldName, String newName) throws NamingException {
+		checkName(newName);
+		throw new OperationNotSupportedException("Not yet implemented");
+	}
+
+	public void rename(Name oldName, Name newName) throws NamingException {
+		rename(oldName.toString(), newName.toString());
+	}
+
+	public NamingEnumeration list(String name) throws NamingException {
+		if (name.length() > 0) 
+			throw new NotContextException("Subcontexts not supported");
+				
+		final Iterator i = getCurrentBindings().iterator();
+		return new NamingEnumeration() {
+			public void close() {}
+			public boolean hasMore() {
+				return i.hasNext();
+			}
+			public Object next() throws NamingException {
+				String n = "urn:eda:rmi:" + (String) i.next();
+				org.apache.oodt.commons.Service server = (org.apache.oodt.commons.Service) lookup(n);
+				try {
+					return new NameClassPair(n, server.getServerInterfaceName());
+				} catch (RemoteException ex) {
+					throw new CommunicationException(ex.getMessage());
+				}
+			}
+			public boolean hasMoreElements() {
+				return hasMore();
+			}
+			public Object nextElement() {
+				Object next = null;
+				try {
+					next = next();
+				} catch (RuntimeException ex) {
+					throw ex;
+				} catch (Exception ignore) {}
+				return next;
+			}
+		};
+	}
+		
+	public NamingEnumeration list(Name name) throws NamingException {
+		return list(name.toString());
+	}
+
+	public NamingEnumeration listBindings(String name) throws NamingException {
+		if (name.length() > 0) 
+			throw new NotContextException("Subcontexts not supported");
+		final Iterator i = getCurrentBindings().iterator();
+		return new NamingEnumeration() {
+			public void close() {}
+			public boolean hasMore() {
+				return i.hasNext();
+			}
+			public Object next() throws NamingException {
+				String n = "urn:eda:rmi:" + (String) i.next();
+				return new javax.naming.Binding(n, lookup(n));
+			}
+			public boolean hasMoreElements() {
+				return hasMore();
+			}
+			public Object nextElement() {
+				Object next = null;
+				try {
+					next = next();
+				} catch (RuntimeException ex) {
+					throw ex;
+				} catch (Exception ignore) {}
+				return next;
+			}
+		};
+	}
+
+	public NamingEnumeration listBindings(Name name) throws NamingException {
+		return listBindings(name.toString());
+	}
+
+	public void destroySubcontext(String name) throws NamingException {
+		throw new OperationNotSupportedException("Not yet implemented");
+	}
+
+	public void destroySubcontext(Name name) throws NamingException {
+		destroySubcontext(name.toString());
+	}
+
+	public Context createSubcontext(String name) throws NamingException {
+		throw new OperationNotSupportedException("Subcontexts not supported");
+	}
+
+	public Context createSubcontext(Name name) throws NamingException {
+		return createSubcontext(name.toString());
+	}
+
+	public Object lookupLink(String name) throws NamingException {
+		return lookup(name);
+	}
+
+	public Object lookupLink(Name name) throws NamingException {
+		return lookupLink(name.toString());
+	}
+
+	public NameParser getNameParser(String name) throws NamingException {
+		return nameParser;
+	}
+
+	public NameParser getNameParser(Name name) throws NamingException {
+		return getNameParser(name.toString());
+	}
+
+	public String composeName(String name, String prefix) throws NamingException {
+		Name result = composeName(new CompositeName(name), new CompositeName(prefix));
+		return result.toString();
+	}
+
+	public Name composeName(Name name, Name prefix) throws NamingException {
+		Name result = (Name) prefix.clone();
+		result.addAll(name);
+		return result;
+	}
+
+	public Object addToEnvironment(String propName, Object propVal) throws NamingException {
+		if (environment == null) environment = new Hashtable();
+		return environment.put(propName, propVal);
+	}
+
+	public Object removeFromEnvironment(String propName) throws NamingException {
+		if (environment == null) return null;
+		return environment.remove(propName);
+	}
+
+	public Hashtable getEnvironment() throws NamingException {
+		if (environment == null) return new Hashtable();
+		return (Hashtable) environment.clone();
+	}
+
+	public String getNameInNamespace() throws NamingException {
+		return "";
+	}
+
+	public void close() throws NamingException {
+		environment = null;
+	}
+
+	/**
+	 * Get the current bindings in the RMI registry.
+	 *
+	 * @return A list of the current bindings, as simple string names.
+	 */
+	private List getCurrentBindings() throws NamingException {
+		List names = null;
+		try {
+			Registry registry = getRegistry();
+			names = Arrays.asList(registry.list());
+		} catch (RemoteException ex) {
+			names = Collections.EMPTY_LIST;
+		}
+		return names;
+	}
+
+	/**
+	 * Convert the context object name into an rmiregistry name.
+	 *
+	 * @param name Context name.
+	 * @return rmiregistry name.
+	 */
+	private String toRMIName(String name) {
+		if (name == null) return "";
+		if (name.startsWith("urn:eda:rmi:"))
+			return name.substring(12);
+		if (name.startsWith("rmi:"))
+			return name.substring(4);
+		return name;
+	}
+
+	/**
+	 * Get the RMI registry.
+	 *
+	 * @return a <code>Registry</code> value.
+	 * @throws NamingException if an error occurs.
+	 */
+	private Registry getRegistry() throws NamingException {
+		if (registry != null) return registry;
+		try {
+			String host = environment.containsKey("host")? (String) environment.get("host") : "localhost";
+			int port = environment.containsKey("port")? ((Integer) environment.get("port")).intValue()
+				: Registry.REGISTRY_PORT;
+
+			
+			registry = LocateRegistry.getRegistry(host, port);
+		} catch (RemoteException ex) {
+			throw new NamingException("Remote exception locating registry: " + ex.getMessage());
+		}
+		return registry;
+	}
+
+	/**
+	 * Ensure the name is an RMI object context name.
+	 *
+	 * RMI object context names are URNs in the <code>eda</code> namespace, in the
+	 * <code>rmi</code> subnamespace.
+	 *
+	 * @param name Name to check.
+	 * @throws InvalidNameException If <var>name</var>'s not an RMI object context name.
+	 */
+	private void checkName(String name) throws InvalidNameException {
+		if (name == null)
+			throw new IllegalArgumentException("Can't check a null name");
+		if (name.length() == 0)
+			throw new InvalidNameException("Name's length is zero");
+		if (!name.startsWith("urn:eda:rmi:"))
+			throw new InvalidNameException("Not an RMI name; try urn:eda:rmi:yadda-yadda");
+	}
+
+	/** Context's environment; currently unused. */
+	private Hashtable environment;
+
+	/** RMI Registry. */
+	private Registry registry;
+
+	/** Parser for object names. */
+	private static final NameParser nameParser = new ObjectNameParser();
+}
+
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/package.html b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/package.html
new file mode 100644
index 0000000..36cd471
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/jndi/package.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<!--
+ 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.
+-->
+<html>
+  <head>
+    <title>Apache OODT Commons: Object Services for JNDI
+    </title>
+  </head>
+  <body>
+    <p>Java Naming and Directory Interface (JNDI) service provider for
+      commons object services.  This package defines a standard JNDI SPI
+      (service provider interface) that encapsulates the binding and
+      lookup of objects in a distributed network.
+    </p>
+  </body>
+</html>
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/package.html b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/package.html
new file mode 100644
index 0000000..79090f3
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/object/package.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<!--
+ 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.
+-->
+<html>
+  <head>
+    <title>Apache OODT Commons: Object Services
+    </title>
+  </head>
+  <body>
+    <p>The object services package includes interfaces, classes, and
+      utilities for the management of objects.  Object services
+      include locating, resolving, and manipulating objects, as well
+      as lifecycle management.
+    </p>
+  </body>
+</html>
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/package.html b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/package.html
new file mode 100644
index 0000000..8facd29
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/package.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<!--
+ 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.
+-->
+<html>
+  <head>
+    <title>Apache OODT Commons
+    </title>
+  </head>
+  <body>
+    <p>Common Java utilities for Apache OODT APIs and applications.</p>
+  </body>
+</html>
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/pagination/PaginationUtils.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/pagination/PaginationUtils.java
new file mode 100644
index 0000000..80e48cd
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/pagination/PaginationUtils.java
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.commons.pagination;
+
+import java.util.List;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A set of utility methods to do pagination.
+ * </p>
+ * 
+ */
+public final class PaginationUtils {
+
+    private PaginationUtils() throws InstantiationException {
+        throw new InstantiationException("Don't construct utility classes!");
+    }
+
+    public static int hasRemainder(int divisor, int quotient) {
+        if (divisor % quotient != 0) {
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+
+    public static int computeCurrentPage(int startIdx, int productsPerPage) {
+        return ((startIdx + 1) / productsPerPage)
+                + hasRemainder(startIdx + 1, productsPerPage);
+    }
+
+    public static int computeCurrentWindow(int currPage, int pagesPerPage) {
+        return (currPage / pagesPerPage) + hasRemainder(currPage, pagesPerPage);
+    }
+
+    public static int computeMinPage(int pagesPerPage, int currWindow) {
+        return (pagesPerPage * (currWindow - 1)) + 1;
+    }
+
+    public static int computeMaxPage(int minPage, int pagesPerPage,
+            int lastIdx, int productsPerPage) {
+        return Math.min(minPage + (pagesPerPage - 1), computeCurrentPage(
+                lastIdx, productsPerPage));
+    }
+
+    public static int computeEndIdx(int currPage, int productsPerPage,
+            int totalProducts) {
+        return Math.min((currPage * productsPerPage) - 1, totalProducts - 1);
+    }
+
+    public static int computePrevStartIdx(int minPage, int productsPerPage) {
+        int prevPage = Math.max(minPage - 2, 1);
+        return (prevPage * productsPerPage);
+    }
+
+    public static int computeNextStartIdx(int maxPage, int productsPerPage) {
+        int nextPage = maxPage;
+        return (nextPage * productsPerPage);
+
+    }
+
+    public static List iterateFrom(final int startIndex,
+            final List originalList, int pageSize) {
+        final int totalSize = originalList.size();
+
+        int endIndex = startIndex + pageSize;
+        if (endIndex > totalSize)
+            endIndex = totalSize;
+
+        return originalList.subList(startIndex, endIndex);
+    }
+
+    public static int getTotalPage(List originalList, int pageSize) {
+        if (originalList == null || originalList.size() <= 0)
+            return 0;
+        final int totalSize = originalList.size();
+        return ((totalSize - 1) / pageSize) + 1;
+    }
+
+    public static int getTotalPage(int numTotal, int pageSize) {
+        if (numTotal <= 0)
+            return 0;
+        return ((numTotal - 1) / pageSize) + 1;
+    }
+
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/spring/SpringSetIdInjectionType.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/spring/SpringSetIdInjectionType.java
new file mode 100755
index 0000000..1a0b146
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/spring/SpringSetIdInjectionType.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.commons.spring;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public interface SpringSetIdInjectionType {
+
+    /**
+     * Get a unique String id that represents this objects instance
+     * @return Unique String id
+     */
+    @Required
+    public String getId();
+
+    /**
+     * Set a unique id that represents this objects instance
+     * @param id Unique String id
+     */
+    @Required
+    public void setId(String id);
+
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/spring/postprocessor/SetIdBeanPostProcessor.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/spring/postprocessor/SetIdBeanPostProcessor.java
new file mode 100755
index 0000000..0a3189e
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/spring/postprocessor/SetIdBeanPostProcessor.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.commons.spring.postprocessor;
+
+//OODT imports
+import org.apache.oodt.commons.spring.SpringSetIdInjectionType;
+
+//Spring imports
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class SetIdBeanPostProcessor implements BeanPostProcessor {
+
+    public Object postProcessAfterInitialization(Object bean, String beanName)
+            throws BeansException {
+        if (bean instanceof SpringSetIdInjectionType)
+            ((SpringSetIdInjectionType) bean).setId(beanName);
+        return bean;
+    }
+
+    public Object postProcessBeforeInitialization(Object bean, String beanName)
+            throws BeansException {
+        return bean;
+    }
+
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/Base64.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/Base64.java
new file mode 100644
index 0000000..846c13c
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/Base64.java
@@ -0,0 +1,213 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import org.apache.oodt.commons.io.*;
+
+/** Base 64 encoding and decoding.
+ *
+ * This class provides methods for RFC-1521 specified "base 64" encoding and decoding of
+ * arbitrary data.  Pass a byte array into the {@link #encode} method and you'll get a
+ * byte array result where all of the bytes are printable ASCII values.  Pass that result
+ * into {@link #decode} and you'll get your original byte array.
+ *
+ * <p>Sincere thanks to Tom Daley for providing a sample encoder algorithm and a great
+ * explanation of how RFC-1521 is supposed to work.
+ *
+ * @author Kelly
+ */
+public class Base64 {
+	/** Encode into base 64.
+	 *
+	 * Encode the given data into RFC-1521 base 64.  Encoding a null array gives a
+	 * null result.
+	 *
+	 * @param data The data to encode.
+	 * @return Base-64 encoded <var>data</var>.
+	 */
+	public static byte[] encode(final byte[] data) {
+		return encode(data, 0, data.length);
+	}
+
+	/** Encode into base 64.
+	 *
+	 * Encode the given data into RFC-1521 base 64.  Encoding a null array gives a
+	 * null result.  Start encoding at the given offset and go for the given amount of
+	 * bytes.
+	 *
+	 * @param data The data to encode.
+	 * @param offset Where to start looking for data to encode.
+	 * @param length How much data to encode.
+	 * @return Base-64 encoded <var>data</var>
+	 */
+	public static byte[] encode(final byte[] data, int offset, int length) {
+		if (data == null) return null;
+		if (offset < 0 || offset > data.length)
+			throw new IndexOutOfBoundsException("Can't encode at index " + offset + " which is beyond array bounds 0.."
+				+ data.length);
+		if (length < 0) throw new IllegalArgumentException("Can't encode a negative amount of data");
+		if (offset + length > data.length)
+			throw new IndexOutOfBoundsException("Can't encode beyond right edge of array");
+		
+		int i, j;
+		byte dest[] = new byte[((length+2)/3)*4];
+
+		// Convert groups of 3 bytes into 4.
+		for (i = 0 + offset, j = 0; i < offset + length - 2; i += 3) {
+			dest[j++] = (byte) ((data[i] >>> 2) & 077);
+			dest[j++] = (byte) ((data[i+1] >>> 4) & 017 | (data[i] << 4) & 077);
+			dest[j++] = (byte) ((data[i+2] >>> 6) & 003 | (data[i+1] << 2) & 077);
+			dest[j++] = (byte) (data[i+2] & 077);
+		}
+
+		// Convert any leftover bytes.
+		if (i < offset + length) {
+			dest[j++] = (byte) ((data[i] >>> 2) & 077);
+			if (i < offset + length - 1) {
+				dest[j++] = (byte) ((data[i+1] >>> 4) & 017 | (data[i] << 4) & 077);
+				dest[j++] = (byte) ((data[i+1] << 2) & 077);
+			} else
+				dest[j++] = (byte) ((data[i] << 4) & 077);
+		}
+
+		// Now, map those onto base 64 printable ASCII.
+		for (i = 0; i <j; i++) {
+			if      (dest[i] < 26)  dest[i] = (byte)(dest[i] + 'A');
+			else if (dest[i] < 52)  dest[i] = (byte)(dest[i] + 'a'-26);
+			else if (dest[i] < 62)  dest[i] = (byte)(dest[i] + '0'-52);
+			else if (dest[i] < 63)  dest[i] = (byte) '+';
+			else                    dest[i] = (byte) '/';
+		}
+
+		// Pad the result with and we're done.
+		for (; i < dest.length; i++) dest[i] = (byte) '=';
+		return dest;
+	}
+
+	/** Decode from base 64.
+	 *
+	 * Decode the given RFC-1521 base 64 encoded bytes into the original data they
+	 * represent.  Decoding null data gives a null result.
+	 *
+	 * @param data Base-64 encoded data to decode.
+	 * @return Decoded <var>data</var>.
+	 */
+	public static byte[] decode(final byte[] data) {
+		return decode(data, 0, data.length);
+	}
+
+	/** Decode from base 64.
+	 *
+	 * Decode the given RFC-1521 base 64 encoded bytes into the original data they
+	 * represent.  Decoding null data gives a null result.
+	 *
+	 * @param data Base-64 encoded data to decode.
+	 * @param offset Where to start looking for data to decode.
+	 * @param length How much data to decode.
+	 * @return Decoded <var>data</var>.
+	 */
+	public static byte[] decode(final byte[] data, int offset, int length) {
+		if (data == null) return null;
+		if (offset < 0 || offset >= data.length)
+			throw new IndexOutOfBoundsException("Can't decode at index " + offset + " which is beyond array bounds 0.."
+				+ (data.length-1));
+		if (length < 0) throw new IllegalArgumentException("Can't decode a negative amount of data");
+		if (offset + length > data.length)
+			throw new IndexOutOfBoundsException("Can't decode beyond right edge of array");
+
+		// Ignore any padding at the end.
+		int tail = offset + length - 1;
+		while (tail >= offset && data[tail] == '=')
+			--tail;
+		byte dest[] = new byte[tail + offset + 1 - length/4];
+
+		// First, convert from base-64 ascii to 6 bit bytes.
+		for (int i = offset; i < offset+length; i++) {
+			if      (data[i] == '=') data[i] = 0;
+			else if (data[i] == '/') data[i] = 63;
+			else if (data[i] == '+') data[i] = 62;
+			else if (data[i] >= '0' && data[i] <= '9')
+				data[i] = (byte)(data[i] - ('0' - 52));
+			else if (data[i] >= 'a'  &&  data[i] <= 'z')
+				data[i] = (byte)(data[i] - ('a' - 26));
+			else if (data[i] >= 'A'  &&  data[i] <= 'Z')
+				data[i] = (byte)(data[i] - 'A');
+		}
+
+		// Map those from 4 6-bit byte groups onto 3 8-bit byte groups.
+		int i, j;
+		for (i = 0 + offset, j = 0; j < dest.length - 2; i += 4, j += 3) {
+			dest[j]   = (byte) (((data[i] << 2) & 255) | ((data[i+1] >>> 4) & 003));
+			dest[j+1] = (byte) (((data[i+1] << 4) & 255) | ((data[i+2] >>> 2) & 017));
+			dest[j+2] = (byte) (((data[i+2] << 6) & 255) | (data[i+3] & 077));
+		}
+
+		// And get the leftover ...
+		if (j < dest.length)
+			dest[j] = (byte) (((data[i] << 2) & 255) | ((data[i+1] >>> 4) & 003));
+		if (++j < dest.length)
+			dest[j] = (byte) (((data[i+1] << 4) & 255) | ((data[i+2] >>> 2) & 017));
+
+		// That's it.
+		return dest;
+	}
+
+	/** This class provides namespace for utility methods and shouldn't be instantiated.
+	 */
+	private Base64() {
+		throw new IllegalStateException(getClass().getName() + " should not be instantiated");
+	}
+
+	/** Command-line runner that encodes or decodes.
+	 *
+	 * @param argv Command-line arguments.
+	 */
+	public static void main(String[] argv) throws Exception {
+		if (argv.length < 1 || argv.length > 2) {
+			System.err.println("Usage: encode|decode [file]");
+			System.exit(1);
+		}
+		boolean encode = true;
+		if ("encode".equals(argv[0]))
+			encode = true;
+		else if ("decode".equals(argv[0]))
+			encode = false;
+		else {
+			System.err.println("Specify either \"encode\" or \"decode\"");
+			System.exit(1);
+		}
+		InputStream source = argv.length == 2? new BufferedInputStream(new FileInputStream(argv[1])) : System.in;
+		InputStream in;
+		OutputStream out;
+		if (encode) {
+			in = source;
+			out = new Base64EncodingOutputStream(System.out);
+		} else {
+			in = new Base64DecodingInputStream(source);
+			out = System.out;
+		}
+		byte[] buf = new byte[512];
+		int numRead;
+		while ((numRead = in.read(buf)) != -1)
+			out.write(buf, 0, numRead);
+		in.close();
+		out.close();
+		System.exit(0);
+	}
+}
+
+			
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/CacheMap.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/CacheMap.java
new file mode 100644
index 0000000..523d92f
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/CacheMap.java
@@ -0,0 +1,228 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.util.*;
+
+// Definitions for intended functions:
+//
+// DEFN size(x) = The size of an object x, usually by the size(), length(), or getLength()
+//                methods defined for x.
+// NFED
+//
+// DEFN keys(x) = Set of keys from map x.
+// NFED
+//
+// DEFN dup(x) = Duplicate of object x.
+// NFED
+//
+// DEFN presence(x, y) = True if (x, z) or (z, x) exists in map y for any z.
+// NFED
+//
+// DEFN advance(x, y) = sequence y such that object x in y is moved to the front of the
+//                      sequence, or y if x is not an element of x.
+// NFED
+//
+// DEFN value(v, y) = value v of (k, v) mapping in y.
+// NFED
+//
+// A cache-map Z is a triple (c, C, M) such that c is the capacity, C is an ordered
+// sequence of n keys = {k_0, k_1, ..., k_(n-1)}, and M is a set of mappings (k, v) such
+// that k is the for value v, and all k's are unique.  For all k_i in C, there exists
+// (k_i, v_i) in M.  size(Z) = size(C) = size(M) <= c.  The most recently used v is at the
+// head of C, and the least recently used is at the tail.  When a new (k_new, v_new) is
+// added to Z, C = {k_new, k_0, ..., k_(n-1)} and if size(C) >= c, the previous k_(n-1) is
+// removed from C and M; and M = M U (k_new, v_new).
+
+
+/** A cache map is a map with a built-in cache.
+ *
+ * It operates in all ways like a regular {@link java.util.Map}, except that you can store
+ * only a limited number of entries.  After adding an entry that exceeds the size of the
+ * cache, the map ejects the least recently used entry.
+ *
+ * @author Kelly
+ */
+public class CacheMap implements Map {
+	/** Create a cache map with a default capacity of 5 entries.
+	 */
+	public CacheMap() {
+		// FXN: [ c, C, M := 5, {}, {} ]
+		this(DEFAULT_CAPACITY);
+	}
+
+	/** Create a cache map with the given capacity.
+	 *
+	 * @param capacity How big the cache is.
+	 */
+	public CacheMap(int capacity) {
+		// FXN: [ c, C, M := capacity, {}, {} ]
+
+		if (capacity < 0)
+			throw new IllegalArgumentException("Can't have a negative size " + capacity + " cache map");
+		this.capacity = capacity;
+	}
+
+	/** Get the cache map's capacity.
+	 *
+	 * @return Its capacity.
+	 */
+	public int getCapacity() {
+		return capacity;
+	}
+
+	/** Create a cache map from the given map, having the capacity of the given map.
+	 *
+	 * @param map The map to copy.
+	 */
+	public CacheMap(Map map) {
+		// FXN: [ c, C, M := size(map), keys(map), dup(map) ]
+
+		this.capacity = map.size();
+		putAll(map);
+	}
+
+	public int size() {
+		// FXN: [ return value := size(M) ]
+		return map.size();
+	}
+
+	public boolean isEmpty() {
+		// FXN: [ return value := size(M) = 0? ]
+		return map.size() == 0;
+	}
+
+	/** Returns true if there's a mapping for the specified key in the cache map.
+	 *
+	 * This method does not otherwise affect the cache.
+	 *
+	 * @param key Key to check.
+	 * @return True if the cache map contains a mapping for the <var>key</var>.
+	 */
+	public boolean containsKey(Object key) {
+		// FXN: [ return value := presence(key, M) ]
+		return (map.containsKey(key));
+	}
+
+	/** Returns true if there's a mapping for the specified value in the cache map.
+	 *
+	 * This method does not otherwise affect the cache.
+	 *
+	 * @param value Value to check.
+	 * @return True if the cache map contains a mapping for the <var>value</var>.
+	 */
+	public boolean containsValue(Object value) {
+		// FXN: [ return value := presence(value, M) ]
+		return map.containsValue(value);
+	}
+
+	public Object get(Object key) {
+		// FXN: [ key in M -> C, return value := advance(key, C), value(key, M)
+		//      | true     -> C, return value := C, null ]
+
+		advance(key);
+		return map.get(key);
+	}
+
+	public Object put(Object key, Object value) {
+		// FXN: [ key in M -> C, M, return value := advance(key, C), M U (key, value), value(key, M)
+		//      | size(C) < c -> C, M, return value := key || C, M U (key, value), null
+		//      | true -> C, M, return value := key || {k_i | k elem C, 0 <= i <= c - 2},
+		//                                      (M U (key, value)) - (k_(c-1), v), null ]
+
+		Object old = map.put(key, value);
+		if (old != null) {
+			advance(key);
+			return old;
+		}
+
+		cache.addFirst(key);
+		if (cache.size() > capacity)
+			map.remove(cache.removeLast());
+		return null;
+	}
+	
+	public Object remove(Object key) {
+		// FXN: [ key in M -> C, M, return value := C - key, M - (key, v), v
+		//      | true -> return value := null ]
+
+		if (!map.containsKey(key))
+			return null;
+		cache.remove(key);
+		return map.remove(key);
+	}
+
+	public void putAll(Map t) {
+		// FXN: [ C, M := (keys(t) || C)[0..(c-1)], { (k_i, v_i) | k_i elem of (keys(t) || C)[0..(c-1)]} ]
+		for (Iterator i = t.entrySet().iterator(); i.hasNext();) {
+			Map.Entry entry = (Map.Entry) i.next();
+			put(entry.getKey(), entry.getValue());
+		}
+	}
+
+	public void clear() {
+		cache.clear();
+		map.clear();
+	}
+
+	public Set keySet() {
+		throw new UnsupportedOperationException("Not implemented for CacheMap");
+	}
+	public Collection values() {
+		throw new UnsupportedOperationException("Not implemented for CacheMap");
+	}
+	public Set entrySet() {
+		throw new UnsupportedOperationException("Not implemented for CacheMap");
+	}
+
+	public boolean equals(Object rhs) {
+		if (rhs == this) return true;
+		if (rhs == null || !(rhs instanceof CacheMap)) return false;
+		CacheMap obj = (CacheMap) rhs;
+		return obj.cache.equals(cache);
+	}
+
+	public int hashCode() {
+		return cache.hashCode();
+	}
+
+	/** Advance the given key to the front of the cache.
+	 *
+	 * If the key isn't in the cache, leave the cache alone.
+	 *
+	 * @param key The key to advance.
+	 */
+	private void advance(Object key) {
+		// FXN: [ C = advance(key, C) ]
+
+		boolean present = cache.remove(key);
+		if (!present) return;
+		cache.addFirst(key);
+	}
+
+	/** What the default capacity of a cache map is. */
+	private static final int DEFAULT_CAPACITY = 5;
+
+	/** The cache (C). */
+	private LinkedList cache = new LinkedList();
+
+	/** The map (M). */
+	private Map map = new HashMap();
+
+	/** The capacity of this cache map (c). */
+	private int capacity;
+}
+
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/DOMParser.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/DOMParser.java
new file mode 100644
index 0000000..8f12bfb
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/DOMParser.java
@@ -0,0 +1,263 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+
+package org.apache.oodt.commons.util;
+
+import java.io.IOException;
+import java.util.*;
+import org.xml.sax.*;
+import org.w3c.dom.*;
+import javax.xml.parsers.DocumentBuilder;
+
+/** An XML Document Object Model parser.
+ *
+ * Objects of this class are DOM parsers.
+ *
+ * @author Kelly
+ */
+public class DOMParser {
+	/** Construct the DOM Parser.
+	 */
+	DOMParser(DocumentBuilder builder) {
+		this.builder = builder;
+	}
+
+	/** Get the document.
+	 *
+	 * @return The document.
+	 */
+	public Document getDocument() {
+		if (document == null)
+			throw new IllegalStateException("Must parse something first");
+		return document;
+	}
+
+	/** Returns a list of features that this parser recognizes.
+	 *
+	 * This method will never return null; if no features are recognized, this
+	 * method will return a zero length array.
+	 *
+	 * @return Recognized features.
+	 */
+	public String[] getFeaturesRecognized() {
+		return EMPTY_STRING_ARRAY;
+	}
+
+	/**
+	 * Returns a list of properties that this parser recognizes.
+	 * This method will never return null; if no properties are
+	 * recognized, this method will return a zero length array.
+	 *
+	 * @return Recognized properties.
+	 */
+	public String[] getPropertiesRecognized() {
+		return EMPTY_STRING_ARRAY;
+	}
+
+	/** Resets the parser. */
+	public void reset() throws Exception {
+		document = null;
+	}
+
+	/** Resets or copies the parser. */
+	public void resetOrCopy() throws Exception {
+		reset();
+	}
+
+	/**
+	 * Set the state of any feature in a SAX2 parser.  The parser
+	 * might not recognize the feature, and if it does recognize
+	 * it, it might not be able to fulfill the request.
+	 *
+	 * @param featureId The unique identifier (URI) of the feature.
+	 * @param state The requested state of the feature (true or false).
+	 *
+	 * @exception SAXNotRecognizedException If the requested feature is
+	 *                                      not known.
+	 * @exception SAXNotSupportedException If the requested feature is
+	 *                                     known, but the requested state
+	 *                                     is not supported.
+	 */
+	public void setFeature(String featureId, boolean state) throws SAXNotRecognizedException, SAXNotSupportedException {
+		throw new SAXNotSupportedException("This parser supports no features");
+	}
+
+	/**
+	 * Query the current state of any feature in a SAX2 parser.  The
+	 * parser might not recognize the feature.
+	 *
+	 * @param featureId The unique identifier (URI) of the feature
+	 *                  being set.
+	 *
+	 * @return The current state of the feature.
+	 *
+	 * @exception SAXNotRecognizedException If the requested feature is
+	 *                                      not known.
+	 */
+	public boolean getFeature(String featureId) throws SAXNotRecognizedException, SAXNotSupportedException {
+		throw new SAXNotSupportedException("This parser supports no features");
+	}
+
+	/**
+	 * Set the value of any property in a SAX2 parser.  The parser
+	 * might not recognize the property, and if it does recognize
+	 * it, it might not support the requested value.
+	 *
+	 * @param propertyId The unique identifier (URI) of the property
+	 *                   being set.
+	 * @param value The value to which the property is being set.
+	 *
+	 * @exception SAXNotRecognizedException If the requested property is
+	 *                                      not known.
+	 * @exception SAXNotSupportedException If the requested property is
+	 *                                     known, but the requested
+	 *                                     value is not supported.
+	 */
+	public void setProperty(String propertyId, Object value) throws SAXNotRecognizedException, SAXNotSupportedException {
+		throw new SAXNotSupportedException("This parser supports no properties");
+	}
+
+	/**
+	 * Return the current value of a property in a SAX2 parser.
+	 * The parser might not recognize the property.
+	 *
+	 * @param propertyId The unique identifier (URI) of the property
+	 *                   being set.
+	 *
+	 * @return The current value of the property.
+	 *
+	 * @exception SAXNotRecognizedException If the requested property is
+	 *                                      not known.
+	 *
+	 */
+	public Object getProperty(String propertyId) throws SAXNotRecognizedException, SAXNotSupportedException {
+		throw new SAXNotSupportedException("This parser supports no properties");
+	}
+
+	/**
+	 * Returns true if the specified feature is recognized.
+	 *
+	 */
+	public boolean isFeatureRecognized(String featureId) {
+		return false;
+	}
+
+
+	/**
+	 * Returns true if the specified property is recognized.
+	 *
+	 */
+	public boolean isPropertyRecognized(String propertyId) {
+		return false;
+	}
+
+	/**
+	 * return the locator being used by the parser
+	 *
+	 * @return the parser's active locator
+	 */
+	public final Locator getLocator() {
+		throw new IllegalStateException("Locators ar enot supported");
+	}
+
+	/**
+	 * Sets the resolver used to resolve external entities. The EntityResolver
+	 * interface supports resolution of public and system identifiers.
+	 *
+	 * @param resolver The new entity resolver. Passing a null value will
+	 *                 uninstall the currently installed resolver.
+	 */
+	public void setEntityResolver(EntityResolver resolver) {
+		builder.setEntityResolver(resolver);
+	}
+
+	/**
+	 * Return the current entity resolver.
+	 *
+	 * @return The current entity resolver, or null if none
+	 *         has been registered.
+	 * @see #setEntityResolver
+	 */
+	public EntityResolver getEntityResolver() {
+		throw new IllegalStateException("The resolver can only be set, not queried");
+	}
+
+	/**
+	 * Sets the error handler.
+	 *
+	 * @param handler The new error handler.
+	 */
+	public void setErrorHandler(ErrorHandler handler) {
+		builder.setErrorHandler(handler);
+	}
+
+	/**
+	 * Return the current error handler.
+	 *
+	 * @return The current error handler, or null if none
+	 *         has been registered.
+	 * @see #setErrorHandler
+	 */
+	public ErrorHandler getErrorHandler() {
+		throw new IllegalStateException("The error handler can only be set, not queried");
+	}
+
+	/**
+	 * Parses the specified input source.
+	 *
+	 * @param source The input source.
+	 *
+	 * @exception org.xml.sax.SAXException Throws exception on SAX error.
+	 * @exception java.io.IOException Throws exception on i/o error.
+	 */
+	public void parse(InputSource source) throws SAXException, IOException {
+		document = builder.parse(source);
+	}
+
+	/**
+	 * Parses the input source specified by the given system identifier.
+	 * <p>
+	 * This method is equivalent to the following:
+	 * <pre>
+	 *     parse(new InputSource(systemId));
+	 * </pre>
+	 *
+	 * @param systemID The input source.
+	 *
+	 * @exception org.xml.sax.SAXException Throws exception on SAX error.
+	 * @exception java.io.IOException Throws exception on i/o error.
+	 */
+	public void parse(String systemID) throws SAXException, IOException {
+		document = builder.parse(systemID);
+	}
+
+
+	/**
+	 * Set the locale to use for messages.
+	 *
+	 * @param locale The locale object to use for localization of messages.
+	 *
+	 * @exception SAXException An exception thrown if the parser does not
+	 *                         support the specified locale.
+	 */
+	public void setLocale(Locale locale) throws SAXException {
+		throw new IllegalStateException("This parser does not support localized error messages");
+	}
+
+	private static final String[] EMPTY_STRING_ARRAY = new String[0];
+	private Document document;
+	private DocumentBuilder builder;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/DateConvert.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/DateConvert.java
new file mode 100644
index 0000000..9f6cc5a
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/DateConvert.java
@@ -0,0 +1,396 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+	The <code>DateConvert</code> class is intended to provide date/time
+	conversion and parse routines. For a description of the syntax of the
+	format strings see {@link SimpleDateFormat}.
+
+	@author S. Hardman
+	@version $Revision: 1.1.1.1 $
+ */
+public class DateConvert {
+
+	/**
+		The number of milliseconds in a minute.
+	*/
+	private final static long MS_IN_MINUTE = 60000;
+
+	/**
+		The number of milliseconds in an hour.
+	*/
+	private final static long MS_IN_HOUR = 3600000;
+
+	/**
+		The number of milliseconds in a day.
+	*/
+	private final static long MS_IN_DAY = 86400000;
+
+	/**
+		The format string representing the ISO 8601 format. The format
+		is close to CCSDS ASCII Time Code A. 
+	*/
+	private final static String ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS";
+
+	/**
+		The format string representing the CCSDS ASCII Time Code B format
+		excluding the trailing "Z".
+	*/
+	private final static String DOY_FORMAT = "yyyy-DDD'T'HH:mm:ss.SSS";
+
+	/**
+		The format string representing the EDA time stamp format.
+	*/
+	private final static String TS_FORMAT = "yyyyMMddHHmmssSSS";
+
+	/**
+		The format string representing the DBMS format.
+	*/
+	private final static String DBMS_FORMAT = "dd-MMM-yyyy HH:mm:ss";
+
+	/**
+		The format string representing the Year-Month-Day format.
+	*/
+	private final static String YMD_FORMAT = "yyyy-MM-dd";
+
+
+	/**
+		Constructor given no arguments.
+
+		This is a static-only class that may not be instantiated.
+
+		@throws IllegalStateException If the class is instantiated.
+	*/
+	public DateConvert() throws IllegalStateException {
+		throw new IllegalStateException("Instantiation of this class is not allowed.");
+	}
+
+
+	/**
+		Format the given date and return the resulting string in ISO 8601 format.
+
+		The format is as follows: "yyyy-MM-dd'T'HH:mm:ss.SSS[Z|[+|-]HH:mm]".
+
+		@param inputDate The date to be converted into string format.
+		@return The formatted date/time string.
+	*/
+	public static String isoFormat(Date inputDate) {
+
+		// Setup the date format and convert the given date.
+		SimpleDateFormat dateFormat = new SimpleDateFormat(ISO_FORMAT);
+		String dateString = dateFormat.format(inputDate);
+
+		// Determine the time zone and concatenate the time zone designator
+		// onto the formatted date/time string.
+		TimeZone tz = dateFormat.getTimeZone();
+		String tzName = tz.getDisplayName();
+		if (tzName.equals("Greenwich Mean Time")) {
+			dateString = dateString.concat("Z");
+		}
+		else {
+			// Determine the hour offset. Add an hour if daylight savings
+			// is in effect.
+			long tzOffsetMS = tz.getRawOffset();
+			long tzOffsetHH = tzOffsetMS / MS_IN_HOUR;
+			if (tz.inDaylightTime(inputDate)) {
+				tzOffsetHH = tzOffsetHH + 1;
+			}
+			String hourString = String.valueOf(Math.abs(tzOffsetHH));
+			if (hourString.length() == 1) {
+				hourString = "0" + hourString;
+			}
+
+			// Determine the minute offset.
+			long tzOffsetMMMS = tzOffsetMS % MS_IN_HOUR;
+			long tzOffsetMM = 0;
+			if (tzOffsetMMMS != 0) {
+				tzOffsetMM = tzOffsetMMMS / MS_IN_MINUTE;
+			}
+			String minuteString = String.valueOf(tzOffsetMM);
+			if (minuteString.length() == 1) {
+				minuteString = "0" + minuteString;
+			}
+
+			// Determine the sign of the offset.
+			String sign = "+";
+			if (String.valueOf(tzOffsetMS).indexOf("-") != -1) {
+				sign = "-";
+			}
+
+			dateString = dateString.concat(sign + hourString + ":" + minuteString);
+		}
+
+		return(dateString);
+	}
+
+
+	/**
+		Parse the given date/time string in ISO 8601 format and return the
+		resulting <code>Date</code> object.
+
+		The format is as follows: "yyyy-MM-dd'T'HH:mm:ss.SSS[Z|[+|-]HH:mm]".
+
+		@param inputString The string to be parsed.
+		@return The resulting Date object.
+		@throws ParseException If the string is null or does not match the date/time
+		format.
+	*/
+	public static Date isoParse(String inputString) throws ParseException {
+
+		// Setup the date format.
+		SimpleDateFormat dateFormat = new SimpleDateFormat(ISO_FORMAT);
+		dateFormat.setLenient(false);
+
+		// The length of the input string should be at least 24 characters.
+		if (inputString == null || inputString.length() < 24) {
+			throw new ParseException("An exception occurred because the input date/time string was null or under 24 characters in length.", inputString.length());
+		}
+
+		// Evaluate the the specified offset and set the time zone.
+		String offsetString = inputString.substring(23);
+		if (offsetString.equals("Z")) {
+			dateFormat.setTimeZone(TimeZone.getTimeZone("Greenwich Mean Time"));
+		}
+		else if (offsetString.startsWith("-") || offsetString.startsWith("+")) {
+			SimpleDateFormat offsetFormat = new SimpleDateFormat();
+			if (offsetString.length() == 3) {
+				offsetFormat.applyPattern("HH");
+			}
+			else if (offsetString.length() == 6) {
+				offsetFormat.applyPattern("HH:mm");
+			}
+			else {
+				throw new ParseException("An exception occurred because the offset portion was not the valid length of 3 or 6 characters.", 25);
+			}
+
+			// Validate the given offset.
+			offsetFormat.setLenient(false);
+			Date offsetDate = offsetFormat.parse(offsetString.substring(1));
+
+			// Set the time zone with the validated offset.
+			dateFormat.setTimeZone(TimeZone.getTimeZone("GMT" + offsetString));
+		}
+		else {
+			throw new ParseException("An exception occurred because the offset portion of the input date/time string was not 'Z' or did not start with '+' or '-'.", 24);
+		}
+
+		// Parse the given string.
+		Date parseDate = dateFormat.parse(inputString);
+
+		return(parseDate);
+	}
+
+
+	/**
+		Format the given date and return the resulting string in CCSDS
+		ASCII Time Code B format.
+
+		The format is as follows: "yyyy-DDD'T'HH:mm:ss.SSS".
+
+		@param inputDate The date to be converted into string format.
+		@return The formatted date/time string.
+	*/
+	public static String doyFormat(Date inputDate) {
+
+		// Setup the date format and convert the given date.
+		SimpleDateFormat dateFormat = new SimpleDateFormat(DOY_FORMAT);
+		String dateString = dateFormat.format(inputDate);
+
+		return(dateString);
+	}
+
+
+	/**
+		Parse the given date/time string in CCSDS ASCII Time Code B format
+		and return the resulting <code>Date</code> object.
+
+		The format is as follows: "yyyy-DDD'T'HH:mm:ss.SSS".
+
+		@param inputString The string to be parsed.
+		@return The resulting Date object.
+		@throws ParseException If the string does not match the date/time
+		format.
+	*/
+	public static Date doyParse(String inputString) throws ParseException {
+
+		// Setup the date format and parse the given string.
+		SimpleDateFormat dateFormat = new SimpleDateFormat(DOY_FORMAT);
+		dateFormat.setLenient(false);
+		Date parseDate = dateFormat.parse(inputString);
+
+		return(parseDate);
+	}
+
+
+	/**
+		Format the given date and return the resulting string in a timestamp
+		format.
+
+		The format is as follows: "yyyyMMddHHmmssSSS".
+
+		@param inputDate The date to be converted into string format.
+		@return The formatted date/time string.
+	*/
+	public static String tsFormat(Date inputDate) {
+
+		// Setup the date format and convert the given date.
+		SimpleDateFormat dateFormat = new SimpleDateFormat(TS_FORMAT);
+		String dateString = dateFormat.format(inputDate);
+
+		return(dateString);
+	}
+
+
+	/**
+		Parse the given date/time string in timestamp format
+		and return the resulting <code>Date</code> object.
+
+		The format is as follows: "yyyyMMddHHmmssSSS".
+
+		@param inputString The string to be parsed.
+		@return The resulting Date object.
+		@throws ParseException If the string does not match the date/time
+		format.
+	*/
+	public static Date tsParse(String inputString) throws ParseException {
+
+		// Setup the date format and parse the given string.
+		SimpleDateFormat dateFormat = new SimpleDateFormat(TS_FORMAT);
+		dateFormat.setLenient(false);
+		Date parseDate = dateFormat.parse(inputString);
+
+		return(parseDate);
+	}
+
+
+	/**
+		Format the given date and return the resulting string in a DBMS
+		format.
+
+		The format is as follows: "dd-MMM-yyyy HH:mm:ss".
+
+		@param inputDate The date to be converted into string format.
+		@return The formatted date/time string.
+	*/
+	public static String dbmsFormat(Date inputDate) {
+
+		// Setup the date format and convert the given date.
+		SimpleDateFormat dateFormat = new SimpleDateFormat(DBMS_FORMAT);
+		String dateString = dateFormat.format(inputDate);
+
+		return(dateString);
+	}
+
+
+	/**
+		Parse the given date/time string in DBMS format
+		and return the resulting <code>Date</code> object.
+
+		The format is as follows: "dd-MMM-yyyy HH:mm:ss".
+
+		@param inputString The string to be parsed.
+		@return The resulting Date object.
+		@throws ParseException If the string does not match the date/time
+		format.
+	*/
+	public static Date dbmsParse(String inputString) throws ParseException {
+
+		// Setup the date format and parse the given string.
+		SimpleDateFormat dateFormat = new SimpleDateFormat(DBMS_FORMAT);
+		dateFormat.setLenient(false);
+		Date parseDate = dateFormat.parse(inputString);
+
+		return(parseDate);
+	}
+
+
+	/**
+		Format the given date and return the resulting string in a
+		year-month-day format.
+
+		The format is as follows: "yyyy-MM-dd".
+
+		@param inputDate The date to be converted into string format.
+		@return The formatted date/time string.
+	*/
+	public static String ymdFormat(Date inputDate) {
+
+		// Setup the date format and convert the given date.
+		SimpleDateFormat dateFormat = new SimpleDateFormat(YMD_FORMAT);
+		String dateString = dateFormat.format(inputDate);
+
+		return(dateString);
+	}
+
+
+	/**
+		Parse the given date/time string in year-month-day format
+		and return the resulting <code>Date</code> object.
+
+		The format is as follows: "yyyy-MM-dd".
+
+		@param inputString The string to be parsed.
+		@return The resulting Date object.
+		@throws ParseException If the string does not match the date/time
+		format.
+	*/
+	public static Date ymdParse(String inputString) throws ParseException {
+
+		// Setup the date format and parse the given string.
+		SimpleDateFormat dateFormat = new SimpleDateFormat(YMD_FORMAT);
+		dateFormat.setLenient(false);
+		Date parseDate = dateFormat.parse(inputString);
+
+		return(parseDate);
+	}
+
+
+	/**
+		Get the number of milliseconds in a minute.
+
+		@return The number of milliseconds in a minute.
+	*/
+	public static long getMsecsInMinute() {
+		return(MS_IN_MINUTE);
+	}
+
+
+	/**
+		Get the number of milliseconds in an hour.
+
+		@return The number of milliseconds in an hour.
+	*/
+	public static long getMsecsInHour() {
+		return(MS_IN_HOUR);
+	}
+
+
+	/**
+		Get the number of milliseconds in a day.
+
+		@return The number of milliseconds in a day.
+	*/
+	public static long getMsecsInDay() {
+		return(MS_IN_DAY);
+	}
+}
+
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/Documentable.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/Documentable.java
new file mode 100644
index 0000000..90c9ce9
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/Documentable.java
@@ -0,0 +1,36 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import java.util.*;
+import org.w3c.dom.*;
+
+/** A documentable object.
+ *
+ * An object that exhibits this interface can be documented, in XML, as a DOM node.
+ *
+ * @author Kelly.
+ */
+public interface Documentable {
+	/** Document (aka serialize) this object into an XML DOM node.
+	 *
+	 * @param doc What document will own the node.
+	 * @return This object as an XML DOM node.
+	 * @throws DOMException If an error occurs while creating the DOM structure.
+	 */
+	Node toXML(Document doc) throws DOMException;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/EnterpriseEntityResolver.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/EnterpriseEntityResolver.java
new file mode 100644
index 0000000..af01b8a
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/EnterpriseEntityResolver.java
@@ -0,0 +1,159 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+import java.io.InputStreamReader;
+
+/** XML entity resolver for enterprise applications.
+ *
+ * This resolver attempts to retrieves entities from local sources before deferring to the
+ * default parser's entity resolver.
+ *
+ * @author Kelly
+ */
+public class EnterpriseEntityResolver implements EntityResolver {
+	/** Mapping of public identifiers to known file names. */
+	static Map entities;
+
+	/** Initialize the class by reading the entites.xml file. */
+	static {
+		entities = new HashMap();
+		try {
+			SAXParserFactory factory = SAXParserFactory.newInstance();
+			factory.setNamespaceAware(false);
+			factory.setValidating(true);
+			javax.xml.parsers.SAXParser p = factory.newSAXParser();
+			p.parse(new InputSource(EnterpriseEntityResolver.class.getResourceAsStream("entities.xml")),
+				new DefaultHandler() {
+					private StringBuffer token = new StringBuffer();
+					private String pi;
+					public void characters(char[] ch, int start, int length) {
+						token.append(ch, start, length);
+					}
+					public void endElement(String ns, String name, String qual) {
+						if ("pi".equals(qual))
+							pi = token.toString().trim();
+						else if ("filename".equals(qual)) {
+							entities.put(pi, token.toString().trim());
+						}
+						token.delete(0, token.length());
+					}
+				});
+		} catch (ParserConfigurationException ex) {
+			throw new IllegalStateException("Unexpected ParserConfigurationException: " + ex.getMessage());
+		} catch (SAXParseException ex) {
+			System.err.println("Error parsing entities.xml at line " + ex.getLineNumber() + ", column "
+				+ ex.getColumnNumber() + "; ignoring entity lookup");
+		} catch (SAXException ex) {
+			System.err.println("Exception parsing entities.xml: " + ex.getMessage() + "; ignoring entity lookup");
+		} catch (IOException ex) {
+			System.err.println("I/O error reading entities.xml: " + ex.getMessage() + "; ignoring entity lookup");
+		}
+	}
+
+	public InputSource resolveEntity(String publicID, String systemID) throws SAXException, IOException {
+		String filename = computeFilename(publicID, systemID);
+		if (filename == null) return null;
+
+		// Resolve it using class loader first.  Any DTD in the toplevel directory
+		// of any jar present to the application is a potential source.
+		InputStream in = getClass().getResourceAsStream("/" + filename);
+		if (in != null)
+			return new InputSource(new BufferedReader(new InputStreamReader(in)));
+
+		// OK, try the filesystem next.  You can control what directories get
+		// searched by setting the entity.dirs property.
+		File file = findFile(getEntityRefDirs(System.getProperty("entity.dirs", "")), filename);
+		if (file != null) try {
+			return new InputSource(new BufferedReader(new FileReader(file)));
+		} catch (IOException ignore) {}
+
+		// No luck either way.
+		return null;
+	}
+
+	/** Compute the possible filename from public and system identifiers.
+	 *
+	 * This attempts to map the public ID to a known file based on a table (see
+	 * <code>entity.xml</code>).  If that doesn't work, then it will use the
+	 * file part of the system ID.  If there's no file part, it returns null.
+	 *
+	 * @param publicID The public identifier.
+	 * @param systemID The system identifier.
+	 * @return A file computed from <var>publicID</var> and <var>systemID</var>.
+	 */
+	static String computeFilename(String publicID, String systemID) {
+		String name = (String) entities.get(publicID);
+		if (name == null) try {
+			URL url = new URL(systemID);
+			File file = new File(url.getFile());
+			name = file.getName();
+		} catch (MalformedURLException ignore) {}
+		return name;
+	}
+
+	/**
+	 * Get a list of entity directories from the given string specification.
+	 *
+	 * @param spec Directory names separated by commas.
+	 * @return a {@link List} of those directory names.
+	 */
+	static List getEntityRefDirs(String spec) {
+		List dirs = new ArrayList();
+		for (StringTokenizer t = new StringTokenizer(spec, ",;|"); t.hasMoreTokens();)
+			dirs.add(t.nextToken());
+		return dirs;
+	}
+
+	/** Find a file under a list of directories.
+	 * 
+	 * @param dirs List of {@link java.lang.String} directory names.
+	 * @param filename Name of the file to find under one of the directories named in <var>dirs</var>.
+	 * @return The first path to the file named by <var>filename</var> under a directory in <var>dirs</var>,
+	 * or null if no directory in <var>dirs</var> contains a file named <var>filename</var>.
+	 */
+	static File findFile(List dirs, String filename) {
+		for (Iterator i = dirs.iterator(); i.hasNext();) {
+			File potentialFile = new File((String) i.next(), filename);
+			if (potentialFile.isFile()) return potentialFile;
+		}
+		return null;
+	}
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/FileLogger.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/FileLogger.java
new file mode 100644
index 0000000..a4fafa9
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/FileLogger.java
@@ -0,0 +1,68 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import java.util.*;
+import org.apache.oodt.commons.io.*;
+import org.apache.oodt.commons.util.*;
+
+/**
+	The <code>FileLogger</code> class is intended to be used with the
+	{@link Log} class in order to setup a log file as a {@link LogListener}.
+
+	@author S. Hardman
+	@version $Revision: 1.1 $
+*/
+public class FileLogger extends WriterLogger {
+
+	/**
+		Constructor given no arguments.
+
+		This constructor will create a new log file or append to an existing
+		log file if the specified file exists. The constructor will then call
+		the other constructor with the output stream argument. This constructor
+		utilizes two system properties for specifying the path and name of the
+		log file. They are as follows:
+
+		<p>org.apache.oodt.commons.util.FileLogger.path - If specified, this is the directory where
+			the log file will be found or created, otherwise the local directory
+			will be utilized.
+
+		<p>org.apache.oodt.commons.util.FileLogger.name - If specified, this is the name of the log
+			file to be found or created, otherwise the name will be as follows:
+			"eda_yyyymmddhhmmssSSS.log".
+
+		@throws FileNotFoundException If the file cannot be opened for any
+			reason.
+	*/
+	public FileLogger () throws FileNotFoundException {
+		this(new FileOutputStream(System.getProperty("org.apache.oodt.commons.util.FileLogger.path", ".") + "/" + System.getProperty("org.apache.oodt.commons.util.FileLogger.name", "eda_" + DateConvert.tsFormat(new Date()) + ".log"), true));
+	}
+
+
+	/**
+		Constructor given an output stream.
+
+		This constructor calls the {@link WriterLogger} constructor with the
+		same signature.
+
+		@param outputStream The output stream representing the log destination.
+	*/
+	public FileLogger (OutputStream outputStream) {
+		super(outputStream);
+	}
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/JDBC_DB.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/JDBC_DB.java
new file mode 100644
index 0000000..5d41776
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/JDBC_DB.java
@@ -0,0 +1,441 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.text.SimpleDateFormat;
+import java.util.Properties;
+
+/**
+	This class is a wrapper for JDBC.
+
+	@author D. Crichton
+	@version $Revision: 1.3 $
+*/
+public class JDBC_DB
+{
+	Properties serverProps;
+	Connection connect;
+	String sql_command;
+	Statement stmt;
+	ResultSet rs;
+	ResultSetMetaData rs_meta;
+	int affected;
+	boolean more_rows;
+	boolean keep_connect_open;
+	private boolean autoCommitMode = false;
+	public final String TO_DATE_FORMAT = "DD-MM-YYYY HH24:MI:SS";
+
+	/******************************************************************
+	**
+	** JDBC_DB
+	**
+	** Constructor method will create class instance and load the
+	** Oracle DB driver
+	**
+	*******************************************************************/
+
+	public  JDBC_DB(
+			java.util.Properties sys_props) throws SQLException
+	{
+			String  classname;
+
+			serverProps = sys_props;
+			keep_connect_open = true;
+
+	}
+
+	public  JDBC_DB(
+			java.util.Properties sys_props,
+			Connection srv_connect) throws SQLException
+	{
+			String  classname;
+
+			serverProps = sys_props;
+			connect = srv_connect;
+
+			if (srv_connect == null) {
+				keep_connect_open  = false;
+			} else {
+				keep_connect_open = true;
+			}
+	}
+
+	public void setAutoCommitMode(boolean autoCommitMode) {
+		this.autoCommitMode = autoCommitMode;
+	}
+
+	/******************************************************************
+	**
+	** openConnection
+	**
+	** Open a connection to the database.
+	**
+	*******************************************************************/
+	public void openConnection() throws SQLException
+
+	{
+		openConnection(serverProps.getProperty("org.apache.oodt.commons.util.JDBC_DB.user", "unknown"),
+			serverProps.getProperty("org.apache.oodt.commons.util.JDBC_DB.password"),
+			serverProps.getProperty("org.apache.oodt.commons.util.JDBC_DB.database"));
+	}
+
+
+	public void openConnection(
+		String username,
+		String password,
+		String database) throws SQLException
+	{
+		String url, classname;
+
+		if (stmt != null)
+			stmt.close();
+
+		if (rs != null)
+			rs.close();
+
+		if (keep_connect_open)
+			return;
+
+		if (connect != null)
+			connect.close();
+
+
+		rs_meta = null;
+		connect = null;
+		stmt = null;
+		rs = null;
+
+		Properties props = new Properties();
+		props.put("user", username);
+
+		if (password != null)
+			props.put("password", password);
+
+
+		classname = serverProps.getProperty("org.apache.oodt.commons.util.JDBC_DB.driver", "oracle.jdbc.driver.OracleDriver");
+		try {
+			System.err.println("Attempting to load class " + classname);
+			Class.forName(classname);
+			System.err.println("Loaded " + classname);
+		} catch (ClassNotFoundException e) {
+			System.err.println("Can't load JDBC driver \"" + classname + "\": " + e.getMessage());
+			e.printStackTrace();
+		}
+		url = serverProps.getProperty("org.apache.oodt.commons.util.JDBC_DB.url", "jdbc:oracle:@");
+		try {
+			if (database != null) {
+				System.err.println("Connecting to url+database combo: " + url + database);
+				connect = DriverManager.getConnection(url+database, props);
+			} else {
+				System.err.println("Connecting to full url: " + url);
+				connect = DriverManager.getConnection(url, props);
+			}
+		} catch (SQLException e) {
+			System.err.println("SQL Exception during connection creation: " + e.getMessage());
+			e.printStackTrace();
+			while (e != null) {
+				System.err.println(e.getMessage());
+				e = e.getNextException();
+			}
+		}
+
+		connect.setAutoCommit(autoCommitMode);
+
+	}
+
+
+	/******************************************************************
+	**
+	** closeConnection
+	**
+	** Close a connection to the database.
+	**
+	*******************************************************************/
+
+	public void closeConnection() {
+		try {
+			if (rs != null) {
+				rs.close();
+			}
+			if (stmt != null) {
+				stmt.close();
+			}
+			if (keep_connect_open) {
+				return;
+			}
+			if (connect != null) {
+				connect.close();
+			}
+			connect = null;
+			rs = null;
+			stmt = null;
+		} catch (SQLException e) {
+			System.err.println("Ignoring database close connection exception");
+			//System.err.println("Ignoring exception " + e.getClass().getName() + ": " + e.getMessage());
+			//e.printStackTrace();
+		}
+	}
+
+	/******************************************************************
+	**
+	** executeSQLCommand
+	**
+	** Send an SQL command to the DBMS to be executed.
+	**
+	*******************************************************************/
+
+	public void executeSQLCommand(String cmd) throws SQLException
+	{
+
+
+		/*
+		** Get the string, and create the statement
+		*/
+		sql_command = cmd;
+
+		if (stmt!=null)
+			stmt.close();
+
+		if (connect == null) openConnection();
+		if (connect == null) {
+			keep_connect_open = false;
+			openConnection();
+		}
+		if (connect == null)
+			throw new IllegalStateException("Connection is null!!!");
+		
+		if (connect.isClosed()) {
+			connect = null;
+			keep_connect_open = false;
+			openConnection();
+		}
+		if (connect == null)
+			throw new IllegalStateException("Connection is still null!!!");
+		if (connect.isClosed())
+			throw new IllegalStateException("Connection got closed!");
+
+		stmt = connect.createStatement();
+		affected = stmt.executeUpdate(sql_command);
+	}
+
+	/******************************************************************
+	**
+	** executeQuery
+	**
+	** Send an SQL query to the DBMS to be executed.
+	**
+	*******************************************************************/
+	public ResultSet executeQuery(String cmd) throws SQLException
+	{
+		sql_command = cmd;
+
+
+		if (stmt!=null)
+			stmt.close();
+
+		if (connect == null) openConnection();
+		if (connect == null) {
+			keep_connect_open = false;
+			openConnection();
+		}
+		if (connect == null)
+			throw new IllegalStateException("Connection is null!!!");
+		
+		if (connect.isClosed()) {
+			connect = null;
+			keep_connect_open = false;
+			openConnection();
+		}
+		if (connect == null)
+			throw new IllegalStateException("Connection is still null!!!");
+		if (connect.isClosed())
+			throw new IllegalStateException("Connection got closed!");
+
+
+		//long time0 = System.currentTimeMillis();
+		stmt = connect.createStatement();
+		//long time = System.currentTimeMillis();
+		//System.err.println("###### Creating a new statement: " + (time - time0));
+		//time0 = time;
+
+		if (rs!=null)
+			rs.close();
+
+		rs = stmt.executeQuery(sql_command);
+		//time = System.currentTimeMillis();
+		//System.err.println("###### Executing the query: " + (time - time0));
+
+		if (rs == null)
+		{
+			return(null);
+		}
+
+		return(rs);
+
+
+	}
+
+	/******************************************************************
+	**
+	** getCount
+	**
+	** Will return a count when user passes sting select count(*) from ...
+	**
+	*******************************************************************/
+	public int getCount(String cmd) throws SQLException
+	{
+		sql_command = cmd;
+		int count;
+
+
+		if (stmt!=null)
+			stmt.close();
+
+		stmt = connect.createStatement();
+
+		if (rs!=null)
+			rs.close();
+
+		rs = stmt.executeQuery(sql_command);
+
+		if (rs == null)
+		{
+			return(0);
+		}
+
+		count = 0;
+
+		while (rs.next())
+		{
+			count = rs.getInt(1);
+		}
+
+		stmt.close();
+		rs.close();
+
+
+		return(count);
+
+
+	}
+	/******************************************************************
+	**
+	** commit
+	**
+	**
+	**
+	*******************************************************************/
+	public void commit() throws SQLException
+	{
+		connect.commit();
+	}
+
+	/******************************************************************
+	**
+	** rollback
+	**
+	**
+	**
+	*******************************************************************/
+	public void rollback()
+	{
+		try
+		{
+			if (connect != null)
+				connect.rollback();
+		}
+
+		catch (SQLException e)
+		{
+
+		}
+	}
+
+	 protected void finalize() throws Throwable
+	{
+		try
+		{
+			if ((connect != null) && (!keep_connect_open))
+			{
+				connect.close();
+
+			}
+
+			if (rs != null)
+			{
+				rs.close();
+			}
+
+			if (stmt != null)
+			{
+				stmt.close();
+			}
+
+		}
+		catch (SQLException e)
+		{
+		}
+	}
+
+	/******************************************************************
+	**
+	** Convert Date to string in format for
+	** Oracle TO_DATE processing - DD-MM-YY HH24:MI:SS
+	**
+	**
+	*******************************************************************/
+
+
+	public String toDateStr(java.util.Date inDate)
+	{
+
+		String outDate;
+/*
+		outDate = Integer.toString(inDate.getDate()) + "-" +
+			   Integer.toString(inDate.getMonth() + 1) + "-" +
+			   Integer.toString(inDate.getYear()) + " " +
+			   Integer.toString(inDate.getHours()) + ":" +
+			   Integer.toString(inDate.getMinutes()) + ":" +
+			   Integer.toString(inDate.getSeconds());
+		return(outDate);
+*/
+
+		SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
+		String dateStr = fmt.format(inDate);
+
+		return dateStr;
+
+
+	}
+
+	public Connection getConnection() throws SQLException
+	{
+		if (connect == null) openConnection();
+		if (connect == null) {
+			keep_connect_open = false;
+			openConnection();
+		}
+		if (connect == null)
+			throw new IllegalStateException("getConnection can't get a connection pointer");
+		return(connect);
+	}
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/LDAP.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/LDAP.java
new file mode 100644
index 0000000..81a0c70
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/LDAP.java
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import java.util.*;
+
+/** LDAP services.
+ *
+ * This class provides LDAP convenience services.
+ *
+ * @author Kelly
+ */
+public class LDAP {
+	/** Convert the given string into an LDAP-safe query string.
+	 *
+	 * This method escapes certain characters that are special in LDAP query strings.
+	 *
+	 * @return An escaped, LDAP-safe string.
+	 */
+	public static String toLDAPString(String str) {
+		StringBuffer result = new StringBuffer();
+		for (int i = 0; i < str.length(); ++i) {
+			char ch = str.charAt(i);
+			switch (ch) {
+				case '*':
+					result.append("\\2a");
+					break;
+				case '(':
+					result.append("\\28");
+					break;
+				case ')':
+					result.append("\\29");
+					break;
+				case '\\':
+					result.append("\\5c");
+					break;
+				default:
+					result.append(ch);
+					break;
+			}
+		}
+		return result.toString();
+	}
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/LogEventMultiplexer.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/LogEventMultiplexer.java
new file mode 100644
index 0000000..af83375
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/LogEventMultiplexer.java
@@ -0,0 +1,76 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.beans.PropertyChangeEvent;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.oodt.commons.io.LogEvent;
+import org.apache.oodt.commons.io.LogListener;
+
+/** Multiplexer for logging events.
+ *
+ * @author Kelly
+ */
+public class LogEventMultiplexer implements LogListener {
+	/** Add an event listener.
+	 *
+	 * @param listener Listener to add.
+	 */
+	public void addListener(LogListener listener) {
+		listeners.add(listener);
+	}
+
+	/** Remove an event listener.
+	 *
+	 * @param listener Listener to remove.
+	 */
+	public void removeListener(LogListener listener) {
+		listeners.remove(listener);
+	}
+
+	public void messageLogged(LogEvent event) {
+		for (Iterator i = listeners.iterator(); i.hasNext();) {
+			LogListener listener = (LogListener) i.next();
+			listener.messageLogged(event);
+		}
+	}
+
+	public void streamStarted(LogEvent event) {
+		for (Iterator i = listeners.iterator(); i.hasNext();) {
+			LogListener listener = (LogListener) i.next();
+			listener.streamStarted(event);
+		}
+	}
+
+	public void streamStopped(LogEvent event) {
+		for (Iterator i = listeners.iterator(); i.hasNext();) {
+			LogListener listener = (LogListener) i.next();
+			listener.streamStopped(event);
+		}
+	}
+
+	public void propertyChange(PropertyChangeEvent event) {
+		for (Iterator i = listeners.iterator(); i.hasNext();) {
+			LogListener listener = (LogListener) i.next();
+			listener.propertyChange(event);
+		}
+	}
+
+	/** List of listeners to which I multiplex events. */
+	private List listeners = new ArrayList();
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/LogInit.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/LogInit.java
new file mode 100644
index 0000000..9c43f03
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/LogInit.java
@@ -0,0 +1,120 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.util.*;
+import org.apache.oodt.commons.io.*;
+import java.beans.PropertyChangeEvent;
+
+/**
+	The <code>LogInit</code> class is intended to be used to initialize
+	the logging capability implemented by the {@link Log} class.
+
+	Maybe someday the <code>init</code> method will become part of the 
+	{@link Log} class.
+
+	@author S. Hardman
+	@version $Revision: 1.1.1.1 $
+	@see Log
+*/
+public class LogInit {
+
+	/**
+		Constructor given no arguments.
+
+		This is a static-only class that may not be instantiated.
+
+		@throws IllegalStateException If the class is instantiated.
+	*/
+	public LogInit() throws IllegalStateException {
+		throw new IllegalStateException("LogInit(): Instantiation of this class is not allowed.");
+	}
+
+
+	/**
+		Initialize the logging capability as specified in the configuration.
+
+		@param props The system properties.
+		@param source The default source to be included in messages.
+		@throws Exception If the logging capability cannot be initialized.
+	*/
+	public static void init(Properties props, String source) throws Exception {
+		// Set up the log event pipeline: filter -> multiplexer -> memory
+		// log/user-specified log.  First the multiplexer.
+		LogEventMultiplexer mux = new LogEventMultiplexer();
+
+		// One destination out of the multiplexer is the in-memory round-robin logger.
+		mux.addListener(MEMORY_LOGGER);
+
+		// Another destination is any user-specified logger.
+		String userSpecifiedListener = props.getProperty("org.apache.oodt.commons.util.LogInit.listener");
+		if (userSpecifiedListener != null)
+			mux.addListener((LogListener) Class.forName(userSpecifiedListener).newInstance());
+
+		// Ahead of the multiplexer is the filter.
+		String categoryList = props.getProperty("org.apache.oodt.commons.util.LogInit.categories", "");
+		StringTokenizer tokens = new StringTokenizer(categoryList);
+		Object[] categories = new Object[tokens.countTokens()];
+		for (int i = 0; i < categories.length; ++i)
+			categories[i] = tokens.nextToken();
+		EnterpriseLogFilter filter = new EnterpriseLogFilter(mux, true, categories);
+		Log.addLogListener(filter);
+
+		// And set the source label.
+		Log.setDefaultSource(source);
+	}
+
+	/** Log filter that uses strings as category objects.
+	 */
+	public static class EnterpriseLogFilter extends LogFilter {
+		/** Construct an EnterpriseLogFilter.
+		 *
+		 * @param listener What object will get filtered log messages.
+		 * @param passThrough If true, pass messages through by default and filter out the
+		 * specified <var>categories</var> of messages. If false, filter out messages by
+		 * default and pass through the specified <var>categories</var>.
+		 * @param categories Categories of messages to filter out (if
+		 * <var>passThrough</var> is true) or to pass through (if <var>passThrough</var>
+		 * is false).
+		 */
+		public EnterpriseLogFilter(LogListener listener, boolean passThrough, Object[] categories) {
+			super(listener, passThrough, categories);
+			PropertyMgr.addPropertyChangeListener(this);
+		}
+
+		/** Update the list of categories to either pass-through or filter out.
+		 *
+		 * @param event Property change event.
+		 */
+		public void propertyChange(PropertyChangeEvent event) {
+			String key = event.getPropertyName();
+			if ("org.apache.oodt.commons.util.LogInit.categories".equals(key)) {
+				String categoriesList = (String) event.getNewValue();
+				categories.clear();
+				if (categoriesList != null) {
+					StringTokenizer tokens = new StringTokenizer(categoriesList);
+					categories.put(tokens.nextToken(), DUMMY);
+				}
+				Log.get("Info").println("Enterprise log now filtering out " + (categoriesList == null?
+					"all categories of messages" : "messages in categories " + categoriesList));
+			}
+		}
+	}
+
+	/** The single memory logger for an application. */
+	public static final MemoryLogger MEMORY_LOGGER = new MemoryLogger();
+}
+
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/MemoryLogger.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/MemoryLogger.java
new file mode 100644
index 0000000..117d265
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/MemoryLogger.java
@@ -0,0 +1,100 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.beans.PropertyChangeEvent;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Iterator;
+import org.apache.oodt.commons.io.LogListener;
+import org.apache.oodt.commons.io.LogEvent;
+
+/** In-memory logger.
+ *
+ * This logger maintains log messages in memory.
+ *
+ * @author Kelly
+ */
+public class MemoryLogger implements LogListener {
+	/** Create a memory logger.
+	 *
+	 * The size of the message cache comes from the system property <code>org.apache.oodt.commons.util.MemoryLogger.size</code>,
+	 * or {@link #DEF_SIZE} if that property isn't specified.
+	 */
+	public MemoryLogger() {
+		this(Integer.getInteger("org.apache.oodt.commons.util.MemoryLogger.size", DEF_SIZE).intValue());
+	}
+
+	/** Create a memory logger.
+	 *
+	 * @param size Size of the message cache.
+	 */
+	public MemoryLogger(int size) {
+		this.size = size;
+	}
+
+	/** Get the list of messages logged so far.
+	 *
+	 * This returns a list of {@link String}s in time order.
+	 *
+	 * @return A list of message strings.
+	 */
+	public List getMessages() {
+		return (List) messages.clone();
+	}
+
+	/** Get the maximum size of the cache.
+	 *
+	 * @return The maximum size of the cache.
+	 */
+	public int getSize() {
+		return size;
+	}
+
+	/** Set the maximum size of the cache.
+	 *
+	 * @param size The new maximum cache size.
+	 */
+	public void setSize(int size) {
+		if (size < 0) throw new IllegalArgumentException("Log cache size can't be negative");
+		int delta = this.size - size;
+		this.size = size;
+		if (delta <= 0) return;
+		if (messages.size() < size) return;
+		while (delta-- > 0)
+			messages.removeFirst();
+	}
+
+	public void streamStarted(LogEvent ignore) {}
+	public void streamStopped(LogEvent ignore) {}
+	public void propertyChange(PropertyChangeEvent ignore) {}
+
+	public void messageLogged(LogEvent event) {
+		messages.add(DateConvert.isoFormat(event.getTimestamp()) + " " + event.getSource() + " " + event.getCategory()
+			+ ": " + event.getMessage());
+		if (messages.size() > size)
+			messages.removeFirst();
+	}
+
+	/** The list of messages. */
+	private LinkedList messages = new LinkedList();
+
+	/** Maximum size of message cache. */
+	private int size;
+
+	/** The default size of the message cache, 32. */
+	public static final int DEF_SIZE = 32;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/PropertyMgr.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/PropertyMgr.java
new file mode 100644
index 0000000..55b6ab7
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/PropertyMgr.java
@@ -0,0 +1,61 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.util.*;
+import java.beans.*;
+
+/** Property manager manages updates to properties.
+ *
+ * @author Kelly
+ */
+public class PropertyMgr {
+	/** Add a listener for property changes.
+	 *
+	 * @param listener Listener to add.
+	 */
+	public static void addPropertyChangeListener(PropertyChangeListener listener) {
+		listeners.add(listener);
+	}
+
+	/** Remove a listener's interest in property changes.
+	 *
+	 * @param listener Listener to remove.
+	 */
+	public static void removePropertyChangeListener(PropertyChangeListener listener) {
+		listeners.remove(listener);
+	}
+
+	/** Set a property and notify listeners.
+	 *
+	 * @param key Property's name.
+	 * @param value New property's value.
+	 */
+	public static void setProperty(String key, String value) {
+		String oldValue = System.getProperty(key);
+		System.setProperty(key, value);
+		if (!listeners.isEmpty()) {
+			PropertyChangeEvent event = new PropertyChangeEvent(System.getProperties(), key, oldValue, value);
+			for (Iterator i = listeners.iterator(); i.hasNext();) {
+				PropertyChangeListener listener = (PropertyChangeListener) i.next();
+				listener.propertyChange(event);
+			}
+		}
+	}
+
+	/** Property change listeners. */
+	private static List listeners = new ArrayList();
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/SAXParser.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/SAXParser.java
new file mode 100644
index 0000000..949dc08
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/SAXParser.java
@@ -0,0 +1,321 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.IOException;
+import java.util.*;
+import org.xml.sax.*;
+
+/** An XML Simple API for XML (SAX) parser.
+ *
+ * Objects of this class are SAX parsers.
+ *
+ * @author Kelly
+ */
+public class SAXParser {
+	/** Construct a SAX Parser.
+	 */
+	SAXParser(javax.xml.parsers.SAXParser parser) {
+		this.parser = parser;
+	}
+
+	/** Returns a list of features that this parser recognizes.
+	 *
+	 * This method will never return null; if no features are recognized, this
+	 * method will return a zero length array.
+	 *
+	 * @return Recognized features.
+	 */
+	public String[] getFeaturesRecognized() {
+		return EMPTY_STRING_ARRAY;
+	}
+
+	/**
+	 * Returns a list of properties that this parser recognizes.
+	 * This method will never return null; if no properties are
+	 * recognized, this method will return a zero length array.
+	 *
+	 * @return Recognized properties.
+	 */
+	public String[] getPropertiesRecognized() {
+		return EMPTY_STRING_ARRAY;
+	}
+
+	/** Resets the parser. */
+	public void reset() {}
+
+
+	/**
+	 * Set the state of any feature in a SAX2 parser.  The parser
+	 * might not recognize the feature, and if it does recognize
+	 * it, it might not be able to fulfill the request.
+	 *
+	 * @param featureId The unique identifier (URI) of the feature.
+	 * @param state The requested state of the feature (true or false).
+	 *
+	 * @exception SAXNotRecognizedException If the requested feature is
+	 *                                      not known.
+	 * @exception SAXNotSupportedException If the requested feature is
+	 *                                     known, but the requested state
+	 *                                     is not supported.
+	 */
+	public void setFeature(String featureId, boolean state) throws SAXNotRecognizedException, SAXNotSupportedException {
+		throw new SAXNotSupportedException("This parser supports no features");
+	}
+
+	/**
+	 * Query the current state of any feature in a SAX2 parser.  The
+	 * parser might not recognize the feature.
+	 *
+	 * @param featureId The unique identifier (URI) of the feature
+	 *                  being set.
+	 *
+	 * @return The current state of the feature.
+	 *
+	 * @exception SAXNotRecognizedException If the requested feature is
+	 *                                      not known.
+	 */
+	public boolean getFeature(String featureId) throws SAXNotRecognizedException, SAXNotSupportedException {
+		throw new SAXNotSupportedException("This parser supports no features");
+	}
+
+	/**
+	 * Set the value of any property in a SAX2 parser.  The parser
+	 * might not recognize the property, and if it does recognize
+	 * it, it might not support the requested value.
+	 *
+	 * @param propertyId The unique identifier (URI) of the property
+	 *                   being set.
+	 * @param value The value to which the property is being set.
+	 *
+	 * @exception SAXNotRecognizedException If the requested property is
+	 *                                      not known.
+	 * @exception SAXNotSupportedException If the requested property is
+	 *                                     known, but the requested
+	 *                                     value is not supported.
+	 */
+	public void setProperty(String propertyId, Object value) throws SAXNotRecognizedException, SAXNotSupportedException {
+		throw new SAXNotSupportedException("This parser supports no properties");
+	}
+
+	/**
+	 * Return the current value of a property in a SAX2 parser.
+	 * The parser might not recognize the property.
+	 *
+	 * @param propertyId The unique identifier (URI) of the property
+	 *                   being set.
+	 *
+	 * @return The current value of the property.
+	 *
+	 * @exception SAXNotRecognizedException If the requested property is
+	 *                                      not known.
+	 *
+	 */
+	public Object getProperty(String propertyId) throws SAXNotRecognizedException, SAXNotSupportedException {
+		throw new SAXNotSupportedException("This parser supports no properties");
+	}
+
+	/**
+	 * Returns true if the specified feature is recognized.
+	 *
+	 */
+	public boolean isFeatureRecognized(String featureId) {
+		return false;
+	}
+
+
+	/**
+	 * Returns true if the specified property is recognized.
+	 *
+	 */
+	public boolean isPropertyRecognized(String propertyId) {
+		return false;
+	}
+
+	/**
+	 * return the locator being used by the parser
+	 *
+	 * @return the parser's active locator
+	 */
+	public final Locator getLocator() {
+		throw new IllegalStateException("This parser doesn't support locators");
+	}
+
+	/**
+	 * Sets the resolver used to resolve external entities. The EntityResolver
+	 * interface supports resolution of public and system identifiers.
+	 *
+	 * @param resolver The new entity resolver. Passing a null value will
+	 *                 uninstall the currently installed resolver.
+	 */
+	public void setEntityResolver(EntityResolver resolver) {
+		try {
+			parser.getXMLReader().setEntityResolver(resolver);
+		} catch (SAXException ignore) {}
+	}
+
+	/**
+	 * Return the current entity resolver.
+	 *
+	 * @return The current entity resolver, or null if none
+	 *         has been registered.
+	 * @see #setEntityResolver
+	 */
+	public EntityResolver getEntityResolver() {
+		throw new IllegalStateException("This parser supports only setting of the entity resolver, not querying");
+	}
+
+	/**
+	 * Sets the error handler.
+	 *
+	 * @param handler The new error handler.
+	 */
+	public void setErrorHandler(ErrorHandler handler) {
+		try {
+			parser.getXMLReader().setErrorHandler(handler);
+		} catch (SAXException ignore) {}
+	}
+
+	/**
+	 * Return the current error handler.
+	 *
+	 * @return The current error handler, or null if none
+	 *         has been registered.
+	 * @see #setErrorHandler
+	 */
+	public ErrorHandler getErrorHandler() {
+		throw new IllegalStateException("This parser supports only setting of the error handler, not querying");
+	}
+
+	/**
+	 * Parses the specified input source.
+	 *
+	 * @param source The input source.
+	 *
+	 * @exception org.xml.sax.SAXException Throws exception on SAX error.
+	 * @exception java.io.IOException Throws exception on i/o error.
+	 */
+	public void parse(InputSource source) throws SAXException, IOException {
+		parser.getXMLReader().parse(source);
+	}
+
+	/**
+	 * Parses the input source specified by the given system identifier.
+	 * <p>
+	 * This method is equivalent to the following:
+	 * <pre>
+	 *     parse(new InputSource(systemId));
+	 * </pre>
+	 *
+	 * @param systemID The input source.
+	 *
+	 * @exception org.xml.sax.SAXException Throws exception on SAX error.
+	 * @exception java.io.IOException Throws exception on i/o error.
+	 */
+	public void parse(String systemID) throws SAXException, IOException {
+		parser.getXMLReader().parse(systemID);
+	}
+
+
+	/**
+	 * Set the locale to use for messages.
+	 *
+	 * @param locale The locale object to use for localization of messages.
+	 *
+	 * @exception SAXException An exception thrown if the parser does not
+	 *                         support the specified locale.
+	 */
+	public void setLocale(Locale locale) throws SAXException {
+		throw new IllegalStateException("This parser doesn't support localized error messages");
+	}
+
+	/**
+	 * Allow an application to register a DTD event handler.
+	 *
+	 * <p>If the application does not register a DTD handler, all DTD
+	 * events reported by the SAX parser will be silently ignored.</p>
+	 *
+	 * <p>Applications may register a new or different handler in the
+	 * middle of a parse, and the SAX parser must begin using the new
+	 * handler immediately.</p>
+	 *
+	 * @param handler The DTD handler.
+	 * @exception java.lang.NullPointerException If the handler 
+	 *            argument is null.
+	 * @see #getDTDHandler
+	 */
+	public void setDTDHandler(DTDHandler handler) {
+		try {
+			parser.getXMLReader().setDTDHandler(handler);
+		} catch (SAXException ignore) {}
+	}
+
+	/**
+	 * Return the current DTD handler.
+	 *
+	 * @return The current DTD handler, or null if none
+	 *         has been registered.
+	 * @see #setDTDHandler
+	 */
+	public DTDHandler getDTDHandler() {
+		try {
+			return parser.getXMLReader().getDTDHandler();
+		} catch (SAXException ex) {
+			throw new IllegalStateException("Unexpected SAXException: " + ex.getMessage());
+		}
+	}
+
+	/**
+	 * Allow an application to register a content event handler.
+	 *
+	 * <p>If the application does not register a content handler, all
+	 * content events reported by the SAX parser will be silently
+	 * ignored.</p>
+	 *
+	 * <p>Applications may register a new or different handler in the
+	 * middle of a parse, and the SAX parser must begin using the new
+	 * handler immediately.</p>
+	 *
+	 * @param handler The content handler.
+	 * @exception java.lang.NullPointerException If the handler 
+	 *            argument is null.
+	 * @see #getContentHandler
+	 */
+	public void setContentHandler(ContentHandler handler) {
+		try {
+			parser.getXMLReader().setContentHandler(handler);
+		} catch (SAXException ignore) {}
+	}
+
+	/**
+	 * Return the current content handler.
+	 *
+	 * @return The current content handler, or null if none
+	 *         has been registered.
+	 * @see #setContentHandler
+	 */
+	public ContentHandler getContentHandler() {
+		try {
+			return parser.getXMLReader().getContentHandler();
+		} catch (SAXException ex) {
+			throw new IllegalStateException("Unexpected SAXException: " + ex.getMessage());
+		}
+
+	}
+
+	private static final String[] EMPTY_STRING_ARRAY = new String[0];
+	private javax.xml.parsers.SAXParser parser;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/ScreenLogger.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/ScreenLogger.java
new file mode 100644
index 0000000..8db00a9
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/ScreenLogger.java
@@ -0,0 +1,52 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import org.apache.oodt.commons.io.*;
+
+/**
+	The <code>ScreenLogger</code> class is intended to be used with the
+	{@link Log} class in order to setup the System.err as a {@link LogListener}.
+
+	@author S. Hardman
+	@version $Revision: 1.1 $
+*/
+public class ScreenLogger extends WriterLogger {
+
+	/**
+		Constructor given no arguments.
+
+		This constructor will specify System.err as the output stream
+		and then call the other constructor with the output stream argument.
+	*/
+	public ScreenLogger () {
+		this(System.err);
+	}
+
+
+	/**
+		Constructor given an output stream.
+
+		This constructor calls the {@link WriterLogger} constructor with the
+		same signature.
+
+		@param outputStream The output stream representing the log destination.
+	*/
+	public ScreenLogger (OutputStream outputStream) {
+		super(outputStream);
+	}
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/Utility.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/Utility.java
new file mode 100644
index 0000000..12b257f
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/Utility.java
@@ -0,0 +1,211 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+/** Miscellaneous utilities.
+ *
+ * This class contains various miscellaneous functions as static methods.
+ *
+ * @author Kelly
+ */
+public class Utility {
+	/** Load properties from a resource.
+	 *
+	 * This loads properties from the given resource (relative to the given class)
+	 * into the given properties object.  If any error occurs, this method prints a
+	 * message to stderr but otherwise takes no special action.
+	 *
+	 * <p>You typically use this to merge properties for your application into the
+	 * System properties by calling this method as follows:
+	 * <pre>Utility.loadProperties(System.getProperties(), MyClass.class,
+	 * "MyClass.properties");</pre> This adds the properties from the file
+	 * <code>MyClass.properties</code> (which must exist in the same directory as the
+	 * file <code>MyClass.class</code>, whether in the filesystem or in a jar) into
+	 * the system properties.  You can then fetch these properties from anywhere in
+	 * your program with <code>System.getProperty(String)</code>,
+	 * <code>Integer.getInteger</code>, etc.
+	 *
+	 * <p>You can also use the method to load properties into a newly created
+	 * properties object that you provide.  This keeps your properties separate, but
+	 * then you have to pass a properties object all over the place, and you can't
+	 * take advantage of non-String properties through methods like
+	 * <code>Long#getLong(String)</code>, etc.
+	 *
+	 * @param props The properties object to load.
+	 * @param clazz The class used to locate the resource.
+	 * @param resourceName The name of the resource.
+	 */
+	public static void loadProperties(Properties props, final Class clazz, final String resourceName) {
+		BufferedInputStream in = null;
+		try {
+			in = new BufferedInputStream(clazz.getResourceAsStream(resourceName));
+			props.load(in);
+		} catch (IOException ex) {
+			System.err.println("I/O exception while loading \"" + resourceName + "\": " + ex.getMessage());
+		} finally {
+			if (in != null) try {
+				in.close();
+			} catch (IOException ignore) {}
+		}
+	}
+
+	/** Parse a list.
+	 *
+	 * This yields an iterator created from a list where commas (and optional leading
+	 * and trailing whitespace) separate each element.  Each element will occur only
+	 * once in the iterator regardless of how many times it appeared in the string.
+	 *
+	 * @param list The list to parse.
+	 * @return The iterator over unique elements in the <var>list</var>.
+	 */
+	public static Iterator parseCommaList(final String list) {
+		if (list == null) return new Iterator() {
+			public boolean hasNext() {
+				return false;
+			}
+			public Object next() {
+				throw new java.util.NoSuchElementException("There weren't ANY elements in this iterator, ever");
+			}
+			public void remove() {
+				throw new UnsupportedOperationException("Can't remove elements from this iterator");
+			}
+		};
+		HashSet set = new HashSet();
+		StringTokenizer tokens = new StringTokenizer(list, ",");
+		while (tokens.hasMoreTokens())
+			set.add(tokens.nextToken().trim());
+		return set.iterator();
+	}
+
+	/** Asynchronously redirect an input stream onto an output stream.
+	 *
+	 * The output stream is never closed.
+	 *
+	 * @param in Input stream to redirect.
+	 * @param out Where to redirect <var>in</var>.
+	 */
+	public static void redirect(final InputStream in, final OutputStream out) {
+		new Thread() {
+			public void run() {
+				try {
+					byte[] buf = new byte[1024];
+					for (;;) {
+						int numRead = in.read(buf);
+						if (numRead == -1) {
+							in.close();
+							break;
+						}
+						out.write(buf, 0, numRead);
+					}
+				} catch (IOException ex) {
+					try {
+						in.close();
+					} catch (IOException ignore) {}
+				}
+			}
+		}.start();
+	}
+
+	/** Log statistics on memory to stderr.
+	 *
+	 * @param msg Text to include in log.
+	 */
+	public static void logMemoryStats(String msg) {
+		Runtime rt = Runtime.getRuntime();
+		System.err.println(msg + ": total=" + (rt.totalMemory() / 1024) + "KB, free=" + (rt.freeMemory() / 1024) + "KB");
+	}
+
+	/** Check string s is numeric.  Numeric strings include 5.7, -3.9, 14.981E16, etc.
+         *
+         * @param s Text to be checked.
+	 * @return True is <var>s</var> is a numeric string.
+         */
+	public static boolean isNumeric(String s) {
+                try {
+                        Double.parseDouble(s);
+                } catch (NumberFormatException ex) {
+                         return false;
+                }
+                return true;
+        }
+
+	/**
+	 * Delete a file or directory.  If <var>file</var> references a directory, it
+	 * recursively deletes all the directory tree.
+	 *
+	 * @param file File, directory, or other filesystem artifact to delete.
+	 * @return True if <var>file</var> was deleted, false otherwise.
+	 */
+	public static boolean delete(File file) {
+		if (file.isDirectory()) {
+			File[] entries = file.listFiles();
+			for (int i = 0; i < entries.length; ++i)
+				if (!delete(entries[i]))
+					return false;
+		}
+		return file.delete();
+	}
+
+   /**
+    * This method will escape any single quotes found in the input string
+    * and return the escaped string. This will ready the string for
+    * insertion into a database. The single quote is escaped by inserting
+    * an additional single quote in front of it in the string. If some
+    * considerate developer has already escaped the single quotes in the
+    * input string, this method will essentially do nothing.
+    *
+    * @param inputString The string to be escaped.
+    * @return The escaped string.
+    */
+   public static String escapeSingleQuote(String inputString) {
+
+      int index = inputString.indexOf('\'');
+      if (index == -1) {
+         return (inputString);
+      }
+
+      String outputString = inputString;
+      while (index != -1) {
+
+         // If the single quote is the last character in the string or 
+         // the next character is not another single quote, insert a
+         // single quote in front of the current single quote.
+         if ((index == (outputString.length() - 1)) || (outputString.charAt(index + 1) != '\'')) {
+            outputString = outputString.substring(0, index) + "'" + outputString.substring(index);
+         }
+
+         // If we are not at the end of the string, check for another
+         // single quote.
+         if ((index + 2) <= (outputString.length() - 1)) {
+            index = outputString.indexOf('\'', index + 2);
+         }
+         else {
+            index = -1;
+         }
+      }
+      return (outputString);
+   }
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/XML.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/XML.java
new file mode 100644
index 0000000..8b4551a
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/XML.java
@@ -0,0 +1,651 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+//
+// Portions of this code come from the Apache XML Project's Xerces 1.0.3 XML Parser
+// (specifically, the functions escape and getEntityRef).  Apache license applies:
+//
+// The Apache Software License, Version 1.1
+//
+// Copyright (c) 1999 The Apache Software Foundation.  All rights reserved.
+//
+// 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. Redistributions in binary form must reproduce the above copyright notice, this list
+//    of conditions and the following disclaimer in the documentation and/or other materials
+//    provided with the distribution.
+//
+// 3. The end-user documentation included with the redistribution, if any, must include
+//    the following acknowledgment:
+//
+//    "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)."
+//
+//    Alternately, this acknowledgment may appear in the software itself,
+//    if and wherever such third-party acknowledgments normally appear.
+//
+// 4. The names "Xerces" and "Apache Software Foundation" must not be used to endorse or
+//    promote products derived from this software without prior written permission. For
+//    written permission, please contact apache@apache.org.
+//
+// 5. Products derived from this software may not be called "Apache", nor may "Apache"
+//    appear in their name, without prior written permission of the Apache Software
+//    Foundation.
+//
+// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
+// ITS CONTRIBUTORS 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.
+//
+// $Id: XML.java,v 1.2 2005-05-01 22:49:55 cmattmann Exp $
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import java.util.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.OutputKeys;
+
+/** XML services.
+ *
+ * This class provides several XML convenience services and encapsulates the underlying
+ * XML implementation, allowing it to vary without impacting developers.
+ *
+ * @author Kelly
+ */
+public class XML {
+	private static DocumentBuilder getStandardDocumentBuilder() {
+		try {
+			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+			factory.setCoalescing(false);
+			factory.setExpandEntityReferences(false);
+			factory.setIgnoringComments(false);
+			factory.setIgnoringElementContentWhitespace(true);
+			factory.setNamespaceAware(true);
+			factory.setValidating(true);
+			return factory.newDocumentBuilder();
+		} catch (ParserConfigurationException ex) {
+			throw new IllegalStateException("Unexpected ParserConfigurationException: " + ex.getMessage());
+		}
+	}
+
+	/** Get the DOM implementation.
+	 *
+	 * @return The DOM implementation.
+	 */
+	public static DOMImplementation getDOMImplementation() {
+		return getStandardDocumentBuilder().getDOMImplementation();
+	}
+
+	/** Create a DOM document.
+	 *
+	 * @return A new DOM document.
+	 */
+	public static Document createDocument() {
+		return getStandardDocumentBuilder().newDocument();
+	}
+
+	/** Create a DOM parser.
+	 *
+	 * This method creates a new DOM parser that has validation turned on and
+	 * ignorable whitespace not included, and has a default error handler that prints
+	 * error messages and warnings to the standard error stream.
+	 *
+	 * @return A new DOM parser.
+	 */
+	public static DOMParser createDOMParser() {
+		DocumentBuilder builder = getStandardDocumentBuilder();
+		builder.setEntityResolver(ENTERPRISE_ENTITY_RESOLVER);
+		builder.setErrorHandler(new ErrorHandler() {
+			public void error(SAXParseException ex) {
+				System.err.println("Parse error: " + ex.getMessage());
+				ex.printStackTrace();
+			}
+			public void warning(SAXParseException ex) {
+				System.err.println("Parse warning: " + ex.getMessage());
+			}
+			public void fatalError(SAXParseException ex) {
+				System.err.println("Fatal parse error: " + ex.getMessage());
+				ex.printStackTrace();
+			}
+		});
+		return new DOMParser(builder);
+	}
+
+	/** Create a SAX parser.
+	 *
+	 * This method creates a new, default SAX parser.  It's set up with a default
+	 * error handler that just prints messages to the standard error stream.
+	 *
+	 * @return A new SAX parser.
+	 */
+	public static SAXParser createSAXParser() {
+		try {
+			SAXParserFactory factory = SAXParserFactory.newInstance();
+			factory.setNamespaceAware(false);
+			factory.setValidating(false);
+			javax.xml.parsers.SAXParser saxParser = factory.newSAXParser();
+			saxParser.getXMLReader().setEntityResolver(ENTERPRISE_ENTITY_RESOLVER);
+			saxParser.getXMLReader().setErrorHandler(new ErrorHandler() {
+				public void error(SAXParseException ex) {
+					System.err.println("Parse error: " + ex.getMessage());
+				}
+				public void warning(SAXParseException ex) {
+					System.err.println("Parse warning: " + ex.getMessage());
+				}
+				public void fatalError(SAXParseException ex) {
+					System.err.println("Fatal parse error: " + ex.getMessage());
+				}
+			});
+			SAXParser p = new SAXParser(saxParser);
+			return p;
+		} catch (ParserConfigurationException ex) {
+			throw new IllegalStateException("Unexpected ParserConfigurationException: " + ex.getMessage());
+		} catch (SAXException ex) {
+			throw new IllegalStateException("Unexpected SAXException: " + ex.getMessage());
+		}
+	}
+
+	/** Serialize an XML DOM document into a String.
+	 *
+	 * This method takes a DOM document and pretty-prints (or pretty-serializes, in
+	 * XML parlance) it into a string.
+	 *
+	 * @param doc The document.
+	 * @param omitXMLDeclaration True if we should omit the XML declaration, false to keep the XML declaration.
+	 * @return The pretty-serialized, stringified, document.
+	 */
+	public static String serialize(Document doc, boolean omitXMLDeclaration) {
+		StringWriter writer = new StringWriter();
+		try {
+			serialize(doc, writer, omitXMLDeclaration);
+		} catch (IOException cantHappen) {}
+		return writer.getBuffer().toString();
+	}
+
+	/** Serialize an XML DOM document into a String.
+	 *
+	 * This method takes a DOM document and pretty-prints (or pretty-serializes, in
+	 * XML parlance) it into a string.
+	 *
+	 * @param doc The document.
+	 * @return The pretty-serialized, stringified, document.
+	 */
+	public static String serialize(Document doc) {
+		return serialize(doc, /*omitXMLDeclaration*/false);
+	}
+
+	/** Serialize an XML DOM document into a writer.
+	 *
+	 * This method takes a DOM document and pretty-prints (or pretty-serializes, in
+	 * XML parlance) it into a writer.
+	 *
+	 * @param doc The document.
+	 * @param writer Where to write it.
+	 * @param omitXMLDeclaration True if we should omit the XML declaration, false to keep the XML declaration.
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public static void serialize(Document doc, Writer writer, boolean omitXMLDeclaration) throws IOException {
+		try {
+			TransformerFactory factory = TransformerFactory.newInstance();
+			Transformer transformer = factory.newTransformer();
+			
+			//update 05/01/2005
+			//author: Chris Mattmann
+			//set properties to pretty print
+			//and also to include the DOCTYPE when serializing the XML
+			
+			//only set this if it's not null else we get a nice NullPointerException
+			if(doc.getDoctype().getPublicId() != null){
+				transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, doc.getDoctype().getPublicId());			    
+			}
+
+			//only set this if it's not null else we get a nice NullPointerException
+			if(doc.getDoctype().getSystemId() != null){
+				transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());			    
+			}
+
+			transformer.setOutputProperty(OutputKeys.INDENT,"yes");
+			
+			DOMSource source = new DOMSource(doc);
+			StreamResult result = new StreamResult(writer);
+			transformer.transform(source, result);
+		} catch (TransformerConfigurationException ex) {
+			throw new IllegalStateException("Unexpected TransformerConfigurationException: " + ex.getMessage());
+		} catch (TransformerException ex) {
+			throw new IllegalStateException("Unexpected TransformerException: " + ex.getMessage());
+		}
+	}
+
+	/** Serialize an XML DOM document into a writer.
+	 *
+	 * This method takes a DOM document and pretty-prints (or pretty-serializes, in
+	 * XML parlance) it into a writer.
+	 *
+	 * @param doc The document.
+	 * @param writer Where to write it.
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public static void serialize(Document doc, Writer writer) throws IOException {
+		serialize(doc, writer, /*omitXMLDeclaration*/false);
+	}
+
+	/** Parse the given XML document into a DOM tree.
+	 *
+	 * @param inputSource The XML document to parse.
+	 * @return A DOM tree for the given XML document.
+	 * @throws SAXException If a parse error occurs.
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public static Document parse(InputSource inputSource) throws SAXException, IOException {
+		DOMParser parser = XML.createDOMParser();
+		parser.parse(inputSource);
+		return parser.getDocument();
+	}
+
+	/** Parse the given XML document into a DOM tree.
+	 *
+	 * @param string The XML document to parse.
+	 * @return A DOM tree for the given XML document.
+	 * @throws SAXException If a parse error occurs.
+	 */
+	public static Document parse(String string) throws SAXException {
+		Document doc = null;
+		try {
+			DOMParser parser = XML.createDOMParser();
+			StringReader reader = new StringReader(string);
+			InputSource inputSource = new InputSource(reader);
+			doc = parse(inputSource);
+			reader.close();
+		} catch (IOException cantHappen) {
+			cantHappen.printStackTrace();
+			throw new RuntimeException("I/O exception " + cantHappen.getClass().getName()
+				+ " can NOT have happened, yet it did!  Message: " + cantHappen.getMessage());
+		}
+		return doc;
+	}
+
+	/** Parse the given XML document into a DOM tree.
+	 *
+	 * @param reader The XML document to parse.
+	 * @return A DOM tree for the given XML document.
+	 * @throws SAXException If a parse error occurs.
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public static Document parse(Reader reader) throws SAXException, IOException {
+		return parse(new InputSource(reader));
+	}
+
+	/** Parse the given XML document into a DOM tree.
+	 *
+	 * @param inputStream The XML document to parse.
+	 * @return A DOM tree for the given XML document.
+	 * @throws SAXException If a parse error occurs.
+	 * @throws IOException If an I/O error occurs.
+	 */
+	public static Document parse(InputStream inputStream) throws SAXException, IOException {
+		return parse(new InputStreamReader(inputStream));
+	}
+
+	/** Add a repeating child element with text from the given collection to the given node.
+	 *
+	 * For example, if <var>values</var> is a {@link java.util.List} with strings items
+	 * "a", "b", and "c", and <var>name</var> is "value", then the XML document will
+	 * have
+	 * <pre>&lt;value&gt;a&lt;/value&gt;
+	 * &lt;value&gt;b&lt;/value&gt;
+	 * &lt;value&gt;c&lt;/value&gt;</pre>
+	 * appended to <var>node</var>.
+	 *
+	 * @param node Node to which to add child elements.
+	 * @param name Name to give each child element.
+	 * @param values Collection of values to assign to each child element, in iterator order.
+	 * @throws DOMException If a DOM error occurs.
+	 */
+	public static void add(Node node, String name, Collection values) throws DOMException {
+		for (Iterator i = values.iterator(); i.hasNext();)
+			add(node, name, i.next());
+	}
+
+	/** Add a child element with the given text to the given element.
+	 *
+	 * This method modifies your DOM tree so that
+	 * <pre>&lt;node&gt;
+	 *   ...
+	 * &lt;/node&gt;</pre>
+	 * becomes
+	 * <pre>&lt;node&gt;
+	 *   ...
+	 *   &lt;name&gt;text&gt;/name&gt;
+	 * &lt;/node&gt;</pre>
+	 *
+	 * Adding a null <var>name</var> does nothing.  Adding null <var>text</var>
+	 * won't add the element.
+	 *
+	 * @param node Node to which to add a child element.
+	 * @param name Name of the child element to add to <var>node</var>.
+	 * @param text What text the text-node child the child element named <var>name</var> should have.  If null,
+	 * nothing happens.
+	 * @throws DOMException If a DOM error occurs.
+	 */
+	public static void addNonNull(Node node, String name, String text) throws DOMException {
+		if (text == null) return;
+		add(node, name, text);
+	}
+
+	/** Add a child element with the given text to the given element.
+	 *
+	 * This method modifies your DOM tree so that
+	 * <pre>&lt;node&gt;
+	 *   ...
+	 * &lt;/node&gt;</pre>
+	 * becomes
+	 * <pre>&lt;node&gt;
+	 *   ...
+	 *   &lt;name&gt;text&gt;/name&gt;
+	 * &lt;/node&gt;</pre>
+	 *
+	 * Adding a null <var>name</var> does nothing.  Adding null <var>text</var>
+	 * results in an empty <var>name</var> tag.
+	 *
+	 * @param node Node to which to add a child element.
+	 * @param name Name of the child element to add to <var>node</var>.
+	 * @param text What text the text-node child the child element named <var>name</var> should have.
+	 * @throws DOMException If a DOM error occurs.
+	 */
+	public static void add(Node node, String name, String text) throws DOMException {
+		if (name == null) return;
+		if (node == null) throw new IllegalArgumentException("Can't add to a null node");
+		Document doc = node.getOwnerDocument();
+		Element element = doc.createElement(name);
+		if (text != null) element.appendChild(doc.createTextNode(text));
+		node.appendChild(element);
+	}
+
+	/** Add a child element with the string representation of the given
+	 * <var>object</var> to the given <var>node</var>.
+	 *
+	 * This method modifies your DOM tree so that
+	 * <pre>&lt;node&gt;
+	 *   ...
+	 * &lt;/node&gt;</pre>
+	 * becomes
+	 * <pre>&lt;node&gt;
+	 *   ...
+	 *   &lt;name&gt;string-rep&gt;/name&gt;
+	 * &lt;/node&gt;</pre>
+	 *
+	 * Adding a null <var>name</var> does nothing.  Adding null <var>object</var>
+	 * results in an empty <var>name</var> tag.
+	 *
+	 * @param node Node to which to add a child element.
+	 * @param name Name of the child element to add to <var>node</var>.
+	 * @param object The string representation of the object to have as the text-node
+	 * child the child element named <var>name</var>.
+	 * @throws DOMException If a DOM error occurs.
+	 */
+	public static void add(Node node, String name, Object object) throws DOMException {
+		add(node, name, object == null? null : object.toString());
+	}
+
+	/** Get unwrapped text from the given DOM node
+	 *
+	 * This method unwraps any wrapped text.  For example, if the document contains
+	 * <pre>&lt;node&gt;Hello, world.  This is
+	 *    my first document.
+         * &lt;/node&gt;</pre>
+	 * then the node's unwrapped text is
+	 * <pre>Hello, world.  This is my first document.</pre>
+	 * while the {@link #text} method would return the wrapped value
+	 * <pre>Hello, world.  This is
+	 *    my first document.</pre>
+	 *
+	 * <p>In other words, it collects the text nodes under the given node and replaces
+	 * strings of newlines and spaces with a single space.  Unwrapping a null node
+	 * returns a null string.
+	 *
+	 * @param node The node.
+	 * @return The text in its children, unwrapped.
+	 */
+	public static String unwrappedText(Node node) {
+		if (node == null) return null;
+		StringBuffer buffer = new StringBuffer();
+		StringBuffer wrapped = new StringBuffer(text1(node, buffer));
+		boolean newline = false;
+		for (int i = 0; i < wrapped.length(); ++i) {
+			if (newline == false) {
+				if (wrapped.charAt(i) == '\n') {
+					newline = true;
+					wrapped.setCharAt(i, ' ');
+				}
+			} else {
+				if (Character.isWhitespace(wrapped.charAt(i))) {
+					wrapped.deleteCharAt(i);
+					--i;
+				} else
+					newline = false;
+			}
+		}
+		return wrapped.toString().trim();
+	}
+
+	/** Get the text from the given DOM node.
+	 *
+	 * Getting text from a null node gives you a null string.
+	 *
+	 * @param node The node.
+	 * @return The text in its children.
+	 */
+	public static String text(Node node) {
+		// [ return text(node) ]
+		StringBuffer buffer = new StringBuffer();
+		return text1(node, buffer);
+	}
+
+	/** Dump the structure of the DOM tree rooted at the given node to the given writer.
+	 *
+	 * This outputs the tree structure including the type of each node, its name, and
+	 * its value.  Note that for many nodes, the name isn't useful (the name of text
+	 * nodes, for example, is <code>#text</code>), and for many nodes, the value is
+	 * null.
+	 *
+	 * @param writer The writer to which write the tree structure.
+	 * @param node The tree to output.
+	 */
+	public static void dump(PrintWriter writer, Node node) {
+		dump(writer, node, 0);
+	}
+
+	/** Remove all comments from the given document node's subtree.
+	 *
+	 * @param node Node from which to search for comments to nuke.
+	 */
+	public static void removeComments(Node node) {
+		List commentNodes = new ArrayList();
+		findCommentNodes(commentNodes, node);
+		for (Iterator i = commentNodes.iterator(); i.hasNext();) {
+			Node commentNode = (Node) i.next();
+			commentNode.getParentNode().removeChild(commentNode);
+		}
+	}
+
+	/** The resolver for entities for the JPL enterprise. */
+	public static final EntityResolver ENTERPRISE_ENTITY_RESOLVER = new EnterpriseEntityResolver();
+
+	/** An empty XML DOM document.  This is handy for some basic operations, and for
+	 * fetching the DOM implementation.
+	 */
+	public static final Document EMPTY_DOCUMENT = org.apache.oodt.commons.util.XML.createDocument();
+
+	/** Identifies the last printable character in the Unicode range that is supported
+	 * by the encoding used with this serializer.  For 8-bit encodings this will be either
+	 * 0x7E or 0xFF.  For 16-bit encodings this will be 0xFFFF. Characters that are not
+	 * printable will be escaped using character references.
+	 *
+	 * <p>Taken from Xerces 1.0.3.  Apache license applies; see source code for
+	 * license.
+	 *
+	 */
+	private static int LAST_PRINTABLE = 0x7E;
+
+	/** Escapes a string so it may be printed as text content or attribute value. Non
+	 * printable characters are escaped using character references.  Where the format
+	 * specifies a deault entity reference, that reference is used
+	 * (e.g. <code>&amp;lt;</code>).
+	 *
+	 * <p>Taken from Xerces 1.0.3.  Apache license applies; see source code for
+	 * license.
+	 *
+	 * @param source The string to escape
+	 * @return The escaped string
+	 */
+	public static String escape(String source) {
+		StringBuffer    result;
+		int             i;
+		char            ch;
+		String          charRef;
+        
+		result = new StringBuffer(source.length());
+		for (i = 0; i < source.length(); ++i) {
+			ch = source.charAt(i);
+			// If the character is not printable, print as character
+			// reference.  Non printables are below ASCII space but not tab or
+			// line terminator, ASCII delete, or above a certain Unicode
+			// threshold.
+			if ((ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r') || ch > LAST_PRINTABLE || ch == 0xF7)
+				result.append("&#").append(Integer.toString(ch)).append(';');
+			else {
+				// If there is a suitable entity reference for this
+				// character, print it. The list of available entity
+				// references is almost but not identical between XML and
+				// HTML.
+				charRef = getEntityRef(ch);
+				if (charRef == null) result.append(ch);
+				else                 result.append('&').append(charRef).append(';');
+			}
+		}
+		return result.toString();
+	}
+
+	/** Find all comment nodes under the given node and add them to the given list.
+	 *
+	 * @param list List to add to.
+	 * @param node Node to search.
+	 */
+	private static void findCommentNodes(List list, Node node) {
+		if (node.getNodeType() == Node.COMMENT_NODE)
+			list.add(node);
+		else {
+			NodeList children = node.getChildNodes();
+			for (int i = 0; i < children.getLength(); ++i) {
+				findCommentNodes(list, children.item(i));
+			}
+		}
+	}
+
+	/** Get the entity reference for the given character.
+	 *
+	 * Taken from Xerces 1.0.3; see source code for license.
+	 */
+	private static String getEntityRef(char ch) {
+		// Encode special XML characters into the equivalent character references.
+		// These five are defined by default for all XML documents.
+		switch (ch) {
+			case '<':  return "lt";
+			case '>':  return "gt";
+			case '"':  return "quot";
+			case '\'': return "apos";
+			case '&':  return "amp";
+		}
+		return null;
+	}
+
+	/** Get the text from the child node using the given buffer.
+	 *
+	 * @param node The node.
+	 * @param buffer The buffer to use.
+	 * @return The text.
+	 */
+	private static String text1(Node node, StringBuffer buffer) {
+		for (Node ch = node.getFirstChild(); ch != null; ch = ch.getNextSibling()) {
+			if (ch.getNodeType() == Node.ELEMENT_NODE || ch.getNodeType() == Node.ENTITY_REFERENCE_NODE)
+				buffer.append(text(ch));
+			else if (ch.getNodeType() == Node.TEXT_NODE)
+				buffer.append(ch.getNodeValue());
+		}
+		return buffer.toString();
+	}
+
+	/** Dump the structure of the DOM tree rooted at the given node to the given writer,
+	 * indenting the contents.
+	 *
+	 * @param indentAmt The number of spaces to indent the output of this node;
+	 * children are indented two more than this amount.
+	 * @param writer The writer to which write the tree structure.
+	 * @param node The tree to output.
+	 */
+	private static void dump(PrintWriter writer, Node node, int indentAmt) {
+		for (int i = 0; i < indentAmt; ++i)
+			writer.print(' ');
+		writer.println(typeOf(node) + "(" + node.getNodeName() + ", " + node.getNodeValue() + ")");
+		NodeList children = node.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i)
+			dump(writer, children.item(i), indentAmt + 2);
+	}
+
+	/** Return a human-readable representation of the type of the given node.
+	 *
+	 * For example, an attribute node returns <code>Attribute</code>, while an element
+	 * node returns <code>Element</code>.
+	 *
+	 * @param node The node.
+	 * @return The name of the node's type.
+	 */
+	private static String typeOf(Node node) {
+		switch (node.getNodeType()) {
+			case Node.ATTRIBUTE_NODE:              return "Attribute";
+			case Node.CDATA_SECTION_NODE:          return "CDATA-Section";
+			case Node.COMMENT_NODE:                return "Comment";
+			case Node.DOCUMENT_FRAGMENT_NODE:      return "Document-Fragment";
+			case Node.DOCUMENT_NODE:               return "Document";
+			case Node.DOCUMENT_TYPE_NODE:          return "Document-Type";
+			case Node.ELEMENT_NODE:                return "Element";
+			case Node.ENTITY_NODE:                 return "Entity";
+			case Node.ENTITY_REFERENCE_NODE:       return "Entity-Ref";
+			case Node.NOTATION_NODE:               return "Notation";
+			case Node.PROCESSING_INSTRUCTION_NODE: return "Proc-Instr";
+			case Node.TEXT_NODE:                   return "Text";
+			default:                               return "Unknown!";
+		}
+	}
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/XMLRPC.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/XMLRPC.java
new file mode 100644
index 0000000..11192c7
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/XMLRPC.java
@@ -0,0 +1,220 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import java.util.*;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** XML-RPC utilities.
+ *
+ * This class provides several XML-RPC utilities.
+ *
+ * @author Kelly
+ */
+public class XMLRPC {
+	/** Build an XML-RPC method call.
+	 *
+	 * This may throw {@link IllegalArgumentException} if the <var>params</var>
+	 * contains an object that's incompatible with XML-RPC.
+	 *
+	 * @param name Name of the method to call.
+	 * @param params Parameters to pass to the call.
+	 * @return An XML string encapsulationg the call.
+	 * @throws DOMException If we can't construct the call.
+	 */
+	public static byte[] createMethodCall(String name, Collection params) throws DOMException {
+		Document doc = XML.createDocument();
+		Element methodCallElement = doc.createElement("methodCall");
+		doc.appendChild(methodCallElement);
+		XML.add(methodCallElement, "methodName", name);
+		if (params != null && !params.isEmpty()) {
+			Element paramsElement = doc.createElement("params");
+			methodCallElement.appendChild(paramsElement);
+			for (Iterator i = params.iterator(); i.hasNext();)
+				paramsElement.appendChild(createValueElement(doc, i.next()));
+		}
+		return XML.serialize(doc).getBytes();
+	}
+
+	/** Create a &lt;value&gt; element for an XML-RPC method.
+	 *
+	 * This may throw {@link IllegalArgumentException} if the <var>value</var> is
+	 * incompatible with XML-RPC.
+	 *
+	 * @param doc Owning document.
+	 * @param value The value.
+	 * @throws DOMException If we can't construct the &lt;value&gt;.
+	 */
+	private static Element createValueElement(Document doc, Object value) throws DOMException {
+		if (value == null)
+			throw new IllegalArgumentException("Nulls not supported in XML-RPC");
+		Element valueElement = doc.createElement("value");
+		if (value instanceof Integer || value instanceof Short) {
+			XML.add(valueElement, "int", value.toString());
+		} else if (value instanceof Boolean) {
+			XML.add(valueElement, "boolean", ((Boolean) value).booleanValue()? "1" : "0");
+		} else if (value instanceof String) {
+			Element stringElement = doc.createElement("string");
+			valueElement.appendChild(stringElement);
+			stringElement.appendChild(doc.createCDATASection(value.toString()));
+		} else if (value instanceof Float || value instanceof Double) {
+			XML.add(valueElement, "double", value.toString());
+		} else if (value instanceof Date) {
+			XML.add(valueElement, "dateTime.iso8601", ISO8601_FORMAT.format((Date) value));
+		} else if (value instanceof byte[]) {
+			Element base64Element = doc.createElement("base64");
+			valueElement.appendChild(base64Element);
+			base64Element.appendChild(doc.createCDATASection(new String(Base64.encode((byte[])value))));
+		} else if (value instanceof Map) {
+			Element structElement = doc.createElement("struct");
+			valueElement.appendChild(structElement);
+			Map map = (Map) value;
+			for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
+				Element memberElement = doc.createElement("member");
+				valueElement.appendChild(memberElement);
+				Map.Entry entry = (Map.Entry) i.next();
+				if (!(entry.getKey() instanceof String))
+					throw new IllegalArgumentException("Keys in maps for XML-RPC structs must be Strings");
+				XML.add(memberElement, "name", entry.getKey().toString());
+				memberElement.appendChild(createValueElement(doc, entry.getValue()));
+			}
+		} else if (value instanceof Collection) {
+			Element arrayElement = doc.createElement("array");
+			valueElement.appendChild(arrayElement);
+			Element dataElement = doc.createElement("data");
+			arrayElement.appendChild(dataElement);
+			Collection collection = (Collection) value;
+			for (Iterator i = collection.iterator(); i.hasNext();)
+				dataElement.appendChild(createValueElement(doc, i.next()));
+		} else throw new IllegalArgumentException(value.getClass().getName() + " not supported in XML-RPC");
+		return valueElement;
+	}
+
+	/** Parse an XML-RPC method response.
+	 *
+	 * @param response The response data.
+	 * @return The value contained in the <var>response</var>.
+	 * @throws XMLRPCFault If the <var>response</var> contained a fault.
+	 */
+	public static Object parseResponse(byte[] response) throws XMLRPCFault {
+		try {
+			DOMParser parser = XML.createDOMParser();
+			parser.setFeature("http://xml.org/sax/features/validation", false);
+			parser.parse(new InputSource(new ByteArrayInputStream(response)));
+			Document doc = parser.getDocument();
+			doc.normalize();
+			XML.removeComments(doc);
+			Element methodResponseElement = doc.getDocumentElement();
+			if (!"methodResponse".equals(methodResponseElement.getNodeName()))
+				throw new SAXException("Not a <methodResponse> document");
+			Node child = methodResponseElement.getFirstChild();
+			if ("params".equals(child.getNodeName())) {
+				return parseValue(child.getFirstChild().getFirstChild());
+			} else if ("fault".equals(child.getNodeName())) {
+				try {
+					Map map = (Map) parseValue(child.getFirstChild());
+					throw new XMLRPCFault(((Integer) map.get("faultCode")).intValue(),
+						(String) map.get("faultString"));
+				} catch (ClassCastException ex) {
+					throw new SAXException("XML-RPC <fault> invalid");
+				}
+			} else throw new SAXException("XML-RPC response does not contain <params> or <fault>");
+		} catch (SAXException ex) {
+			throw new IllegalArgumentException(ex.getMessage());
+		} catch (IOException ex) {
+			throw new RuntimeException("Unexpected I/O exception that shouldn't happen, but did: " + ex.getMessage());
+		}
+	}
+
+	/** Parse an XML-RPC &lt;value&gt;.
+	 *
+	 * @param node The &lt;value&gt; node.
+	 * @return The Java value of <var>node</var>.
+	 */
+	private static Object parseValue(Node node) {
+		String n = node.getNodeName();
+		if (!"value".equals(n)) throw new IllegalArgumentException("Expecting a <value>, not a <" + n + ">");
+		Node t = node.getFirstChild();
+		n = t.getNodeName();
+
+		// Default if there's no nested element is a String.
+		if (t.getNodeType() == Node.TEXT_NODE || t.getNodeType() == Node.CDATA_SECTION_NODE) {
+			return t.getNodeValue();
+		}
+
+		// Figure out what the type is from the nested element.
+		String txt = XML.unwrappedText(t);
+		if ("i4".equals(n) || "int".equals(n)) {
+			return new Integer(txt);
+		} else if ("boolean".equals(n)) {
+			if ("1".equals(txt))      return new Boolean(true);
+			else if ("0".equals(txt)) return new Boolean(false);
+			else throw new IllegalArgumentException(n + " does not contain a 0 or 1");
+		} else if ("string".equals(n)) {
+			return txt;
+		} else if ("double".equals(n)) {
+			return new Double(txt);
+		} else if ("dateTime.iso8601".equals(n)) {
+			try {
+				return ISO8601_FORMAT.parse(txt);
+			} catch (ParseException ex) {
+				throw new IllegalArgumentException(n + " does not contain an ISO8601 format date/time");
+			}
+		} else if ("base64".equals(n)) {
+			return Base64.decode(txt.getBytes());
+		} else if ("struct".equals(n)) {
+			Map m = new HashMap();
+			NodeList memberNodes = t.getChildNodes();
+			for (int i = 0; i < memberNodes.getLength(); ++i) {
+				Node memberNode = memberNodes.item(i);
+				if (!"member".equals(memberNode.getNodeName()))
+					throw new IllegalArgumentException(n + " contains <" + memberNode.getNodeName()
+						+ ">, not <member>");
+				Node nameNode = memberNode.getFirstChild();
+				if (nameNode == null || !"name".equals(nameNode.getNodeName()))
+					throw new IllegalArgumentException("<member> missing <name> element");
+				Node valueNode = nameNode.getNextSibling();
+				if (valueNode == null || !"value".equals(valueNode.getNodeName()))
+					throw new IllegalArgumentException("<member> missing <value> element");
+				m.put(XML.unwrappedText(nameNode), parseValue(valueNode));
+			}
+			return m;
+		} else if ("array".equals(n)) {
+			Node dataNode = t.getFirstChild();
+			if (dataNode == null || !"data".equals(dataNode.getNodeName()))
+				throw new IllegalArgumentException("<array> missing <data> element");
+			NodeList children = dataNode.getChildNodes();
+			List x = new ArrayList(children.getLength());
+			for (int i = 0; i < children.getLength(); ++i)
+				x.add(parseValue(children.item(i)));
+			return x;
+		} else throw new IllegalArgumentException("Illegal type " + n + " in <value>");
+	}
+
+	/** Constructor that causes a runtime exception since this is a utility class.
+	 */
+	private XMLRPC() {
+		throw new IllegalStateException("Do not construct XMLRPC objects");
+	}
+
+	/** ISO8601 date format for XML-RPC dates. */
+	private static DateFormat ISO8601_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/XMLRPCFault.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/XMLRPCFault.java
new file mode 100644
index 0000000..6159b14
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/XMLRPCFault.java
@@ -0,0 +1,63 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import java.util.*;
+import java.text.ParseException;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** XML-RPC fault.
+ *
+ * This exception is thrown when a fault is returned from an XML-RPC call.
+ *
+ * @author Kelly
+ */
+public class XMLRPCFault extends Exception {
+	/** Constructor.
+	 *
+	 * @param code Fault code.
+	 * @param string Fault string.
+	 */
+	public XMLRPCFault(int code, String string) {
+		super(code + ": " + string);
+		this.code = code;
+		this.string = string;
+	}
+
+	/** Get the fault code.
+	 *
+	 * @return The fault code.
+	 */
+	public int getCode() {
+		return code;
+	}
+
+	/** Get the fault string.
+	 *
+	 * @return The fault string.
+	 */
+	public String getString() {
+		return string;
+	}
+
+	/** Fault code. */
+	private int code;
+
+	/** Fault string. */
+	private String string;
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/package.html b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/package.html
new file mode 100644
index 0000000..314ef21
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/util/package.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<!--
+ 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.
+-->
+<html>
+  <head>
+    <title>Apache OODT Common Utilities
+    </title>
+  </head>
+  <body>
+    <p>Utility classes for Apache OODT.
+    </p>
+  </body>
+</html>
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/xml/DOMUtil.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/xml/DOMUtil.java
new file mode 100644
index 0000000..c780323
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/xml/DOMUtil.java
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.commons.xml;
+
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+/**
+ * 
+ * <p>
+ * This class was adapted from an O'Reilly site on DOM utilities. It contains a
+ * few helper methods to make extracting out XML text from DOM representations a
+ * little easier.
+ * </p>
+ * 
+ * @author mattmann
+ * @version 1.0
+ */
+public class DOMUtil {
+
+    /**
+     * 
+     * <p>
+     * Method returns the First occurence of Element 'name' in the DOM Node
+     * 'element'.
+     * </p>
+     * 
+     * @param element
+     *            The DOM Element node to traverse.
+     * @param name
+     *            The XML name of the Element to return.
+     * @return Element "element" with Name "name"'s first occurence.
+     */
+    public static Element getFirstElement(Element element, String name)
+            throws Exception {
+        NodeList n1 = element.getElementsByTagName(name);
+
+        if (n1.getLength() < 1) {
+            throw new Exception("Element: " + element + " does not contain: "
+                    + name);
+        }
+
+        return (Element) n1.item(0);
+    }
+
+    /**
+     * *
+     * <p>
+     * This function is intended when you have a DOM element with no other DOM
+     * elements inside (i.e. <Tag><Tag2>here is text</Tag2></Tag>)
+     * </p> *
+     * 
+     * @param node
+     *            The DOM 'SimpleElement' as defined in the Function definition.
+     * @param name
+     *            The name of the Text to retreive.
+     * @return the Text inbetween the simple element tags.
+     */
+    public static String getSimpleElementText(Element node, String name)
+            throws Exception {
+        Element namedElement = getFirstElement(node, name);
+        return getSimpleElementText(namedElement);
+    }
+
+    /**
+     * *
+     * <p>
+     * This function is intended for use when you have merely text between an
+     * XML Element (i.e. <Tag>text here</Tag>).
+     * </p>
+     * 
+     * @param node
+     *            The DOM XML Tag, with text inbetween.
+     * @return String text inbetween the simple element tag.
+     */
+    public static String getSimpleElementText(Element node) {
+        StringBuffer sb = new StringBuffer();
+        NodeList children = node.getChildNodes();
+
+        for (int i = 0; i < children.getLength(); i++) {
+            Node child = children.item(i);
+            if (child instanceof Text) {
+                sb.append(child.getNodeValue());
+            }
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/xml/XMLUtils.java b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/xml/XMLUtils.java
new file mode 100644
index 0000000..0b3ee9e
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/java/org/apache/oodt/commons/xml/XMLUtils.java
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.commons.xml;
+
+//JDK imports
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.OutputKeys;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.InputSource;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLDecoder;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * 
+ * <p>
+ * A Utility class containing methods to write and transform XML objects.
+ * </p>
+ */
+
+public class XMLUtils {
+
+    /* our log stream */
+    private final static Logger LOG = Logger
+            .getLogger(XMLUtils.class.getName());
+
+    /**
+     * <p>
+     * This method writes a DOM document to a file
+     * </p>.
+     * 
+     * @param doc
+     *            The DOM document to write.
+     * @param filename
+     *            The filename to write the DOM document to.
+     */
+    public static void writeXmlFile(Document doc, String filename) {
+        // Prepare the output file
+        Result result = new StreamResult(filename);
+        transform(doc, result);
+    }
+
+    public static void writeXmlToStream(Document doc, OutputStream stream) {
+        Result result = new StreamResult(stream);
+        transform(doc, result);
+    }
+
+    private static void transform(Document doc, Result result) {
+        try {
+            // Prepare the DOM document for writing
+            Source source = new DOMSource(doc);
+
+            // Write the DOM document to the file
+            Transformer xformer = TransformerFactory.newInstance()
+                    .newTransformer();
+            xformer.setOutputProperty(OutputKeys.INDENT, "yes");
+            xformer.transform(source, result);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public static List readMany(Element root, String elt) {
+        return readMany(root, elt, "UTF-8");
+    }
+
+    public static List readMany(Element root, String elt, String encoding) {
+        NodeList valueNodes = root.getElementsByTagName(elt);
+        List values = new Vector();
+
+        for (int i = 0; i < valueNodes.getLength(); i++) {
+            Element valElem = (Element) valueNodes.item(i);
+            String value = null;
+
+            try {
+                value = URLDecoder.decode(
+                        DOMUtil.getSimpleElementText(valElem), encoding);
+                values.add(value);
+            } catch (Exception e) {
+                e.printStackTrace();
+                LOG.log(Level.WARNING, "Error decoding tag: [" + elt
+                        + "]: val: [" + DOMUtil.getSimpleElementText(valElem)
+                        + "] from metadata. Message: " + e.getMessage());
+            }
+        }
+
+        return values;
+    }
+
+    public static String read(Element root, String elt) {
+        return read(root, elt, "UTF-8");
+    }
+
+    public static String read(Element root, String elt, String encoding) {
+
+        String value = null;
+        try {
+            value = URLDecoder.decode(DOMUtil.getSimpleElementText(root, elt),
+                    encoding);
+        } catch (Exception e) {
+            LOG.log(Level.WARNING, "Error decoding " + elt + "from metadata. "
+                    + "Message: " + e.getMessage());
+        }
+        return value;
+    }
+
+    public static Element getFirstElement(String name, Element root) {
+        NodeList list = root.getElementsByTagName(name);
+        if (list != null) {
+            return (Element) list.item(0);
+        } else
+            return null;
+    }
+
+    public static String getSimpleElementText(Element node, boolean trim) {
+        if (node.getChildNodes().item(0) instanceof Text) {
+            String elemTxt = null;
+            if (trim) {
+                elemTxt = node.getChildNodes().item(0).getNodeValue().trim();
+            } else {
+                elemTxt = node.getChildNodes().item(0).getNodeValue();
+            }
+
+            return elemTxt;
+        } else
+            return null;
+    }
+
+    public static String getSimpleElementText(Element node) {
+        return getSimpleElementText(node, false);
+    }
+
+    public static String getElementText(String elemName, Element root,
+            boolean trim) {
+        Element elem = getFirstElement(elemName, root);
+        if (elem != null) {
+            return getSimpleElementText(elem, trim);
+        } else
+            return null;
+    }
+
+    public static String getElementText(String elemName, Element root) {
+        return getElementText(elemName, root, false);
+    }
+
+    public static Document getDocumentRoot(InputStream is) {
+        // open up the XML file
+        DocumentBuilderFactory factory = null;
+        DocumentBuilder parser = null;
+        Document document = null;
+        InputSource inputSource = null;
+
+        inputSource = new InputSource(is);
+
+        try {
+            factory = DocumentBuilderFactory.newInstance();
+            parser = factory.newDocumentBuilder();
+            document = parser.parse(inputSource);
+        } catch (Exception e) {
+            LOG.log(Level.WARNING, "Unable to parse xml stream"
+                    + ": Reason is [" + e + "]");
+            return null;
+        }
+
+        return document;
+    }
+
+    public static Element addNode(Document doc, Node parent, String name) {
+        Element child = doc.createElement(name);
+        parent.appendChild(child);
+        return child;
+    }
+
+    public static void addNode(Document doc, Node parent, String name,
+            String text) {
+        Element child = doc.createElement(name);
+        child.appendChild(doc.createTextNode(text));
+        parent.appendChild(child);
+    }
+
+    public static void addNode(Document doc, Node parent, String ns,
+            String name, String text, Map NS_MAP) {
+        Element child = doc.createElementNS((String) NS_MAP.get(ns), ns + ":"
+                + name);
+        child.appendChild(doc.createTextNode(text));
+        parent.appendChild(child);
+    }
+
+    public static void addAttribute(Document doc, Element node, String name,
+            String value) {
+        Attr attribute = doc.createAttribute(name);
+        attribute.setValue(value);
+        node.getAttributes().setNamedItem(attribute);
+    }
+
+}
diff --git a/0.8.1-rc1/commons/src/main/resources/conf/app.properties b/0.8.1-rc1/commons/src/main/resources/conf/app.properties
new file mode 100644
index 0000000..21af54e
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/resources/conf/app.properties
@@ -0,0 +1,15 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more contributor
+# license agreements.  See the NOTICE.txt 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.
+foo=bar
diff --git a/0.8.1-rc1/commons/src/main/resources/conf/entities.xml b/0.8.1-rc1/commons/src/main/resources/conf/entities.xml
new file mode 100644
index 0000000..5f09797
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/resources/conf/entities.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE entities [
+<!ELEMENT entities (pi, filename)*>
+<!ELEMENT pi (#PCDATA)>
+<!ELEMENT filename (#PCDATA)>
+]>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<entities>
+  <pi>-//JPL//DTD EDA Directory Objects 1.0//EN</pi>
+  <filename>dir.dtd</filename>
+  <pi>-//JPL//DTD EDA Email Type Query 1.0//EN</pi>
+  <filename>emailTypeQuery.dtd</filename>
+  <pi>-//JPL//DTD EDA Kerberos Credential 1.0//EN</pi>
+  <filename>kerberosCredential.dtd</filename>
+  <pi>-//JPL//DTD EDA LDAP Credential 1.0//EN</pi>
+  <filename>ldapCredential.dtd</filename>
+  <pi>-//JPL//DTD EDA Organization Query 1.0//EN</pi>
+  <filename>organizationQuery.dtd</filename>
+  <pi>-//JPL//DTD EDA Person Query 1.0//EN</pi>
+  <filename>personQuery.dtd</filename>
+  <pi>-//JPL//DTD EDA Person Type Query 1.0//EN</pi>
+  <filename>personTypeQuery.dtd</filename>
+  <pi>-//JPL//DTD EDA Server Status 1.0//EN</pi>
+  <filename>serverStatus.dtd</filename>
+  <pi>-//JPL//DTD OODT Metadata 1.0//EN</pi>
+  <filename>metadata.dtd</filename>
+  <pi>-//JPL//DTD OODT Query 1.0//EN</pi>
+  <filename>query.dtd</filename>
+  <pi>-//JPL//DTD Profile 1.0//EN</pi>
+  <filename>prof.dtd</filename>
+  <pi>-//JPL//DTD Profile 1.1//EN</pi>
+  <filename>prof.dtd</filename>
+  <pi>-//JPL//DTD EDA Server Network 1.0.0//EN</pi>
+  <filename>network.dtd</filename>
+  <pi>-//JPL//DTD Metadata Schema 1.0.0//EN</pi>
+  <filename>metadataSchema.dtd</filename>
+  <pi>-//JPL//DTD TEST ENTRY DO NOT REMOVE//EN</pi>
+  <filename>test-entry-do-not-remove.dtd</filename>
+</entities>
diff --git a/0.8.1-rc1/commons/src/main/resources/dtd/Configuration.dtd b/0.8.1-rc1/commons/src/main/resources/dtd/Configuration.dtd
new file mode 100644
index 0000000..6df19f3
--- /dev/null
+++ b/0.8.1-rc1/commons/src/main/resources/dtd/Configuration.dtd
@@ -0,0 +1,99 @@
+<!--
+FPI is "-//JPL//DTD EDA Configuration 1.0//EN"
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+
+configuration.dtd
+
+Document Type for the Apache Object Oriented Data Technology
+configuration file, used by the class Configuration.
+-->
+
+<!ELEMENT configuration (webServer, nameServer, ldapServer?, xml?, serverMgr?, properties?, programs?)>
+
+<!-- Location of the web server -->
+<!ELEMENT webServer (host, port, dir?)>
+
+<!-- Location of the name server -->
+<!ELEMENT nameServer (iiop | rir)>
+
+<!-- How often to save state; unspecified or <= 0 means never -->
+<!ATTLIST nameServer stateFrequency CDATA #IMPLIED>
+
+<!-- An IIOP address -->
+<!ELEMENT iiop (version?, host, port?, objectKey?)>
+
+<!-- An RIR address -->
+<!ELEMENT rir (objectKey?)>
+
+<!-- Location of the LDAP server -->
+<!ELEMENT ldapServer (host, port?, managerDN?, password?)>
+
+<!-- XML configuration -->
+<!ELEMENT xml (parser?, entityRef?)>
+
+<!-- Preferred XML parser -->
+<!ELEMENT parser (#PCDATA)>
+
+<!-- Where to resolve entity references -->
+<!ELEMENT entityRef (dir*)>
+
+<!-- A directory where an entity reference might be resolved -->
+<!ELEMENT dir (#PCDATA)>
+
+<!-- The server manager -->
+<!ELEMENT serverMgr (port)>
+
+<!-- A collection of Java properties -->
+<!ELEMENT properties (key, value)*>
+
+<!-- A series of programs to execute or that can be executed -->
+<!ELEMENT programs (execServer | client)*>
+
+<!-- A program executed by the ExecServer class -->
+<!ELEMENT execServer (class, objectKey, host?, properties?)>
+
+<!-- A program that you execute by hand -->
+<!ELEMENT client (class, properties?)>
+
+<!-- A fully-qualified Java class name -->
+<!ELEMENT class (#PCDATA)>
+
+<!-- An Internet host name or dotted IP decimal address -->
+<!ELEMENT host (#PCDATA)>
+
+<!-- An Internet port number -->
+<!ELEMENT port (#PCDATA)>
+
+<!-- An Internet or CORBA protocol name -->
+<!ELEMENT protocol (#PCDATA)>
+
+<!-- A CORBA object key -->
+<!ELEMENT objectKey (#PCDATA)>
+
+<!-- An LDAP manager's distinguished name -->
+<!ELEMENT managerDN (#PCDATA)>
+
+<!-- A password -->
+<!ELEMENT password (#PCDATA)>
+
+<!-- A CORBA object version -->
+<!ELEMENT version (#PCDATA)>
+
+<!-- A property key -->
+<!ELEMENT key (#PCDATA)>
+
+<!-- A property value -->
+<!ELEMENT value (#PCDATA)>
diff --git a/0.8.1-rc1/commons/src/site/resources/images/cas-commons.jpg b/0.8.1-rc1/commons/src/site/resources/images/cas-commons.jpg
new file mode 100644
index 0000000..356399e
--- /dev/null
+++ b/0.8.1-rc1/commons/src/site/resources/images/cas-commons.jpg
Binary files differ
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/AbstractTestCase.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/AbstractTestCase.java
new file mode 100644
index 0000000..144d545
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/AbstractTestCase.java
@@ -0,0 +1,55 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Abstract base class for test cases.
+ *
+ * @author <a href="jason@zenplex.com">Jason van Zyl</a>
+ */
+public abstract class AbstractTestCase
+    extends TestCase 
+{
+    /** 
+     * Basedir for all file I/O. Important when running tests from
+     * the reactor.
+     */
+    public String basedir = System.getProperty("basedir");
+    
+    /**
+     * Constructor.
+     */
+    public AbstractTestCase(String testName)
+    {
+        super(testName);
+    }
+    
+    /**
+     * Get test input file.
+     *
+     * @param path Path to test input file.
+     */
+    public String getTestFile(String path)
+    {
+        return new File(basedir,path).getAbsolutePath();
+    }
+}
+
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/AppTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/AppTest.java
new file mode 100644
index 0000000..52e65db
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/AppTest.java
@@ -0,0 +1,54 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+package org.apache.oodt.commons;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ *
+ * @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
+ */
+public class AppTest 
+    extends AbstractTestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertEquals( "maven kicks ass", "maven kicks ass" );
+    }
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/ConfigurationTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/ConfigurationTest.java
new file mode 100644
index 0000000..a90ee42
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/ConfigurationTest.java
@@ -0,0 +1,103 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons;
+
+import java.io.*;
+import java.net.MalformedURLException;
+import java.util.*;
+import junit.framework.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** Unit test the {@link Configuration} class.
+ *
+ * @author Kelly
+ */ 
+public class ConfigurationTest extends TestCase {
+	/** Construct the test case for the {@link Configuration} class. */
+	public ConfigurationTest(String name) {
+		super(name);
+	}
+
+	protected void setUp() throws Exception {
+		// Create a temporary test configuration file.
+		tmpFile = File.createTempFile("conf", ".xml");
+		BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(tmpFile));
+		byte[] doc = TEST_DOC.getBytes();
+		out.write(doc, 0, doc.length);
+		out.close();
+		oldValue = System.getProperty(Configuration.ENTITY_DIRS_PROP);
+		System.setProperty(Configuration.ENTITY_DIRS_PROP, "/dir/1,/dir/2");
+	}
+
+	protected void tearDown() throws Exception {
+		// Nuke the temporary test configuration file.
+		tmpFile.delete();
+		if (oldValue == null)
+			System.getProperties().remove(Configuration.ENTITY_DIRS_PROP);
+		else
+			System.setProperty(Configuration.ENTITY_DIRS_PROP, oldValue);
+	}
+
+	/** Test the various property methods. */
+	public void testConfiguration() throws IOException, SAXException, MalformedURLException {
+		Configuration c = new Configuration(tmpFile.toURL());
+		Properties props = new Properties();
+		props.setProperty("globalKey1", "preset-value");
+		c.mergeProperties(props);
+		assertEquals("preset-value", props.getProperty("globalKey1"));
+		assertEquals("globalValue2", props.getProperty("globalKey2"));
+		assertEquals("http://testhost.test.domain:12345", c.getWebServerBaseURL());
+		assertEquals("http://testhost.test.domain:12345/ns.ior", c.getNameServerURL());
+		assertEquals(42, c.getNameServerStateFrequency());
+		assertEquals(4, c.getEntityRefDirs().size());
+		assertTrue(c.getEntityRefDirs().contains("/dir/one"));
+		assertTrue(c.getEntityRefDirs().contains("/dir/two"));
+		assertTrue(c.getEntityRefDirs().contains("/dir/1"));
+		assertTrue(c.getEntityRefDirs().contains("/dir/2"));
+		assertEquals("/dir/1,/dir/2,/dir/one,/dir/two", System.getProperty(Configuration.ENTITY_DIRS_PROP));
+		Collection servers = c.getExecServerConfigs();
+		assertEquals(2, servers.size());
+		for (Iterator each = servers.iterator(); each.hasNext();) {
+			ExecServerConfig esc = (ExecServerConfig) each.next();
+			if (esc.getClassName().equals("test.Class1")) {
+				assertEquals("Name1", esc.getObjectKey());
+				assertEquals(1, esc.getProperties().size());
+			} else if (esc.getClassName().equals("test.Class2")) {
+				assertEquals("Name2", esc.getObjectKey());
+				assertEquals(3, esc.getProperties().size());
+				for (Iterator i = esc.getProperties().entrySet().iterator(); i.hasNext();) {
+					Map.Entry entry = (Map.Entry) i.next();
+					if (entry.getKey().equals("localKey1"))
+						assertEquals("localKey2", entry.getValue());
+					else if (entry.getKey().equals("globalKey2"))
+						assertEquals("local-override", entry.getValue());
+					else if (entry.getKey().equals("org.apache.oodt.commons.Configuration.url"))
+						; // This one's OK.
+					else fail("Unknown local property \"" + entry.getKey() + "\" in exec server");
+				}
+			} else fail("Unknown ExecServerConfig \"" + esc.getClassName() + "\" in servers from Configuration");
+		}
+	}
+
+	/** The temporary test configuration file. */
+	private File tmpFile;
+
+	/** Old value of the {@link Configuration#ENTITY_DIRS_PROP} system property. */
+	public String oldValue;
+
+	private static final String TEST_DOC = "<?xml version=\"1.0\"?>\n<!DOCTYPE configuration PUBLIC \"-//JPL//DTD EDA Configuration 1.0//EN\" \"http://enterprise.jpl.nasa.gov/dtd/configuration.dtd\">\n<configuration><webServer><host>testhost.test.domain</host><port>12345</port></webServer><nameServer stateFrequency=\"42\"><iiop><version>1.2</version><host>testhost.test.domain</host><port>12345</port><objectKey>TestService</objectKey></iiop></nameServer><xml><entityRef><dir>/dir/one</dir><dir>/dir/two</dir></entityRef></xml><properties><key>globalKey1</key><value>globalValue1</value><key>globalKey2</key><value>globalValue2</value></properties><programs><execServer><class>test.Class1</class><objectKey>Name1</objectKey></execServer><execServer><class>test.Class2</class><objectKey>Name2</objectKey><properties><key>localKey1</key><value>localKey2</value><key>globalKey2</key><value>local-override</value></properties></execServer></programs></configuration>";
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/ConfiguredTestCaseTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/ConfiguredTestCaseTest.java
new file mode 100644
index 0000000..0e062a1
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/ConfiguredTestCaseTest.java
@@ -0,0 +1,66 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons;
+
+import junit.framework.TestCase;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Unit test the ConfiguredTestCase class.
+ *
+ * @author Kelly
+ */ 
+public class ConfiguredTestCaseTest extends TestCase {
+	/** Construct the test case for the ConfiguredTestCaseTest class.
+	 *
+	 * @param name Case name
+	 */
+	public ConfiguredTestCaseTest(String name) {
+		super(name);
+	}
+
+	public void testIt() throws Exception {
+		Case c = new Case();
+		try {
+ 			c.setUp();
+			assertNotNull(Configuration.configuration);
+		} finally {
+			c.tearDown();
+		}			
+	}
+
+	public void testItAgain() throws Exception {
+		Case c = new Case();
+		try {
+			c.setUp();
+			assertNotNull(Configuration.configuration);
+		} finally {
+			c.tearDown();
+		}			
+	}
+
+	private static class Case extends ConfiguredTestCase {
+		Case() {
+			super("test");
+		}
+		public void setUp() throws Exception {
+			super.setUp();
+		}
+		public void tearDown() throws Exception {
+			super.tearDown();
+		}
+	}		
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/MultiServerTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/MultiServerTest.java
new file mode 100644
index 0000000..9db1de4
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/MultiServerTest.java
@@ -0,0 +1,100 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons;
+
+import junit.framework.TestCase;
+import java.io.InputStream;
+import java.io.IOException;
+import org.xml.sax.InputSource;
+import java.rmi.server.RemoteObject;
+import javax.xml.parsers.ParserConfigurationException;
+import java.lang.reflect.InvocationTargetException;
+import org.xml.sax.SAXException;
+
+/**
+ * Unit test the MultiServer class.
+ *
+ * @author Kelly
+ */ 
+public class MultiServerTest extends TestCase {
+	/**
+	 * Construct the test case for the MultiServer class.
+	 *
+	 * @param name Case name
+	 */
+	public MultiServerTest(String name) {
+		super(name);
+	}
+
+	protected void setUp() throws Exception {
+		super.setUp();
+		testConfig = getClass().getResourceAsStream("/test-multiserver.xml");
+		if (testConfig == null) throw new IOException("Cannot find `test-multiserver.xml'");
+		System.setProperty("my.other.setting", "Don't override");
+	}
+
+	public void testParsing() throws ParserConfigurationException, SAXException, IOException, ClassNotFoundException,
+		NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
+		InputSource is = new InputSource(testConfig);
+		MultiServer.parseConfig(is);
+		assertEquals("test.app", MultiServer.getAppName());
+		assertEquals(4, MultiServer.getServers().size());
+
+		MultiServer.Server server = (MultiServer.Server) MultiServer.getServers().get("urn:eda:rmi:Test1");
+		assertEquals("org.apache.oodt.commons.MultiServerTest$Svr1", server.getClassName());
+		assertEquals(MultiServer.BINDING, server.getBindingBehavior());
+
+		server = (MultiServer.Server) MultiServer.getServers().get("urn:eda:rmi:Test2");
+		assertEquals("org.apache.oodt.commons.MultiServerTest$Svr2", server.getClassName());
+		assertEquals(MultiServer.NONBINDING, server.getBindingBehavior());
+
+		server = (MultiServer.Server) MultiServer.getServers().get("urn:eda:rmi:Test3");
+		assertEquals("org.apache.oodt.commons.MultiServerTest$Svr3", server.getClassName());
+		assertEquals(MultiServer.REBINDING, server.getBindingBehavior());
+
+		MultiServer.AutobindingServer s = (MultiServer.AutobindingServer) MultiServer.getServers().get("urn:eda:rmi:Test4");
+		assertEquals("org.apache.oodt.commons.MultiServerTest$Svr4", s.getClassName());
+		assertEquals(MultiServer.AUTO, s.getBindingBehavior());
+		assertEquals(360000L, s.getPeriod());
+
+		assertEquals("My Value", System.getProperty("my.setting"));
+		assertEquals("Don't override", System.getProperty("my.other.setting"));
+	}
+
+	public void tearDown() throws Exception {
+		if (testConfig != null) try {
+			testConfig.close();
+		} catch (IOException ignore) {}
+		System.getProperties().remove("my.setting");
+		System.getProperties().remove("my.other.setting");
+		super.tearDown();
+	}
+
+	private InputStream testConfig;
+
+	public static class Svr1 extends RemoteObject {
+		public Svr1(ExecServer e) {}
+	}
+	public static class Svr2 extends RemoteObject {
+		public Svr2(ExecServer e) {}
+	}
+	public static class Svr3 extends RemoteObject {
+		public Svr3(ExecServer e) {}
+	}
+	public static class Svr4 extends RemoteObject {
+		public Svr4(ExecServer e) {}
+	}
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/NaughtyTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/NaughtyTest.java
new file mode 100644
index 0000000..a825b7e
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/NaughtyTest.java
@@ -0,0 +1,55 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ *
+ * @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
+ */
+public class NaughtyTest
+    extends AbstractTestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public NaughtyTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( NaughtyTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        // Crash and burn!
+    }
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/ActivityStoppedTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/ActivityStoppedTest.java
new file mode 100755
index 0000000..a75f056
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/ActivityStoppedTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import junit.framework.TestCase;

+

+/**

+ * Test the <code>ActivityStopped</code> class.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public class ActivityStoppedTest extends TestCase {

+	/**

+	 * Creates a new {@link ActivityStoppedTest} instance.

+	 *

+	 * @param name Case name.

+	 */

+	public ActivityStoppedTest(String name) {

+		super(name);

+	}

+

+	/**

+	 * Test basic <code>ActivityStopped</code> methods.

+	 */

+	public void testActivityStopped() {

+		ActivityStopped a = new ActivityStopped();

+		try {

+			Thread.sleep(100);

+		} catch (InterruptedException ignore) {}

+		ActivityStopped b = new ActivityStopped();

+		assertTrue(!a.equals(b));

+		assertTrue(!b.equals(a));

+		assertTrue(a.getTime().compareTo(b.getTime()) < 0);

+		// Really not much else we can test...

+	}

+}

diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/ActivityTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/ActivityTest.java
new file mode 100755
index 0000000..8e43773
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/ActivityTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import junit.framework.TestCase;

+

+/**

+ * Test the {@link Activity} class.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public class ActivityTest extends TestCase {

+	/**

+	 * Creates a new {@link ActivityTest} instance.

+	 *

+	 * @param name Case name.

+	 */

+	public ActivityTest(String name) {

+		super(name);

+	}

+

+	/**

+	 * Test basic Activity methods.

+	 */

+	public void testActivities() {

+		TestActivity ta = new TestActivity();				       // Create test activity

+		assertTrue(!"new-id".equals(ta.getID()));			       // It should generate a unique ID

+		ta.setID("new-id");						       // Change its ID

+		assertEquals("new-id", ta.getID());				       // Make sure it got the change

+		Incident i = new Incident();					       // Now create an incident and...

+		ta.log(i);							       // ...log it with the activity

+		assertEquals(incident, i);					       // See if it recorded the incident

+		ta.stop();							       // Now stop the activity

+		assertEquals(ActivityStopped.class, incident.getClass());	       // And see if it recorded a "stop" incident

+	}

+

+	/** Last received incident from the test activity. */

+	private Incident incident;

+	

+	/**

+	 * Testing activity that records incidents to the test case.

+	 */

+	private class TestActivity extends Activity {

+		/**

+		 * Creates a new {@link TestActivity} instance.

+		 */

+		public TestActivity() {

+			super();

+		}

+

+		/**

+		 * Record the last incident to the test case.

+		 *

+		 * @param incident an {@link Incident} value.

+		 */

+		protected void recordIncident(Incident incident) {

+			ActivityTest.this.incident = incident;

+		}

+	}

+}

diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/ActivityTrackerTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/ActivityTrackerTest.java
new file mode 100755
index 0000000..a0672b5
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/ActivityTrackerTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import junit.framework.TestCase;

+

+/**

+ * Test the {@link ActivityTracker} class.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public class ActivityTrackerTest extends TestCase {

+	/**

+	 * Creates a new {@link ActivityTrackerTest} instance.

+	 *

+	 * @param name Case name.

+	 */

+	public ActivityTrackerTest(String name) {

+		super(name);

+	}

+

+	/**

+	 * Save old values of the <code>org.apache.oodt.commons.activity.factories</code> and

+	 * <code>activity.factories</code> properties.

+	 *

+	 * @throws Exception if an error occurs.

+	 */

+	protected void setUp() throws Exception {

+		super.setUp();

+		longName = System.getProperty("org.apache.oodt.commons.activity.factories");

+		shortName = System.getProperty("activity.factories");

+	}

+

+	/**

+	 * Test initialization of the activity tracker.

+	 *

+	 * @throws Exception if an error occurs.

+	 */

+	public void testInitialization() throws Exception {

+		System.getProperties().remove("org.apache.oodt.commons.activity.factories");           // Clear the long property

+		System.getProperties().remove("activity.factories");		       // And the short one

+		ActivityTracker.initializeFactories();				       // And initalize

+		Activity activity = ActivityTracker.createActivity();		       // Have it make an activity

+		assertTrue(activity instanceof NullActivity);			       // With neither set, it must be NullActivity

+

+		System.setProperty("org.apache.oodt.commons.activity.factories",		       // Now set the long name

+			"org.apache.oodt.commons.activity.ActivityTrackerTest$TestFactory");	       // to point to our test factory

+		System.setProperty("activity.factories", "non-existent-class");	       // And set the short name to nonsense

+		ActivityTracker.initializeFactories();				       // And initialize

+		activity = ActivityTracker.createActivity();			       // Have it make an activity

+		assertTrue(activity instanceof TestActivity);			       // With just one, it must be our TestActivity

+

+		System.getProperties().remove("org.apache.oodt.commons.activity.factories");           // Clear the long so it must look at short

+		System.setProperty("activity.factories",			       // And set the short name to...

+			"org.apache.oodt.commons.activity.ActivityTrackerTest$TestFactory"	       // ...not one, but...

+			+ ",org.apache.oodt.commons.activity.ActivityTrackerTest$TestFactory");	       // ...two factories

+		ActivityTracker.initializeFactories();				       // And initialize

+		activity = ActivityTracker.createActivity();			       // Now create an activity

+		assertTrue(activity instanceof CompositeActivity);		       // With > 1, it must be a CompositeActivity

+	}

+

+	/**

+	 * Restore old values of the <code>org.apache.oodt.commons.activity.factories</code> and

+	 * <code>activity.factories</code> properties.

+	 *

+	 * @throws Exception if an error occurs.

+	 */

+	protected void tearDown() throws Exception {

+		if (longName == null)

+			System.getProperties().remove("org.apache.oodt.commons.activity.factories");

+		else

+			System.setProperty("org.apache.oodt.commons.activity.factories", longName);

+		if (shortName == null)

+			System.getProperties().remove("activity.factories");

+		else

+			System.setProperty("activity.factories", shortName);

+		super.tearDown();

+	}

+

+	/**

+	 * A test activity that does nothing.

+	 */

+	static class TestActivity extends Activity {

+		protected void recordIncident(Incident incident) {}

+	}

+

+	/**

+	 * A test activity factory that generates test activities.

+	 */

+	static class TestFactory implements ActivityFactory {

+		public Activity createActivity() {

+			return new TestActivity();

+		}

+	}

+

+	/** Old value of the <code>org.apache.oodt.commons.activity.factories</code> property. */

+	private String longName;

+

+	/** Old value of the <code>activity.factories</code> property. */

+	private String shortName;

+}

diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/CompositeActivityTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/CompositeActivityTest.java
new file mode 100755
index 0000000..7444fd6
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/CompositeActivityTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.util.Collections;

+import junit.framework.TestCase;

+

+/**

+ * Test the {@link CompositeActivity} class.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public class CompositeActivityTest extends TestCase {

+	/**

+	 * Creates a new {@link CompositeActivityTest} instance.

+	 *

+	 * @param name Case name.

+	 */

+	public CompositeActivityTest(String name) {

+		super(name);

+	}

+

+	public void testIt() {

+		try {

+			new CompositeActivity(null);

+			fail("Can contruct CompositeActivity with null collection");

+		} catch (IllegalArgumentException good) {}

+		try {

+			new CompositeActivity(Collections.singleton("hello"));

+			fail("Can construct CompositeActivity with non-Activity in collection");

+		} catch (IllegalArgumentException good) {}

+		CompositeActivity ca = new CompositeActivity(Collections.singleton(new TestActivity()));

+		Incident i = new Incident();

+		ca.log(i);

+		assertEquals(i, incident);

+	}

+

+	/** Last received incident. */

+	private Incident incident;

+

+	/**

+	 * Test activity that records last incidents received into the test case.

+	 */

+	private class TestActivity extends Activity {

+		protected void recordIncident(Incident i) {

+			incident = i;

+		}

+	}

+}

diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/DatagramLoggingActivityFactoryTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/DatagramLoggingActivityFactoryTest.java
new file mode 100755
index 0000000..c49c9eb
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/DatagramLoggingActivityFactoryTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons.activity;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.SocketException;
+import junit.framework.TestCase;
+
+/**
+ * Test the {@link DatagramLoggingActivityFactory} class.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1 $
+ */
+public class DatagramLoggingActivityFactoryTest extends TestCase {
+	/**
+	 * Creates a new {@link DatagramLoggingActivityFactoryTest} instance.
+	 *
+	 * @param name Case name.
+	 */
+	public DatagramLoggingActivityFactoryTest(String name) {
+		super(name);
+	}
+
+	protected void setUp() throws Exception {
+		super.setUp();
+		oldLongHost = System.getProperty("org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.host");
+		oldShortHost = System.getProperty("activity.host");
+		oldLongPort = System.getProperty("org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.port");
+		oldShortPort = System.getProperty("activity.port");
+	}
+
+	protected void tearDown() throws Exception {
+		restore("org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.host", oldLongHost);
+		restore("activity.host", oldShortHost);
+		restore("org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.port", oldLongPort);
+		restore("activity.port", oldShortPort);
+		super.tearDown();
+	}
+
+	/**
+	 * Test use of the system properties.
+	 *
+	 * @throws SocketException if an error occurs.
+	 */
+	public void testPropertyPriority() throws SocketException {
+		System.getProperties().remove("org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.host");
+		System.getProperties().remove("org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.port");
+		System.getProperties().remove("activity.host");
+		System.getProperties().remove("activity.port");
+		try {
+			new DatagramLoggingActivityFactory();
+			fail("Can make a DatagramLoggingActivityFactory without host property set");
+		} catch (IllegalStateException ex) {}
+
+		System.setProperty("org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.host", "localhost");
+		System.setProperty("activity.host", "non-existent-host");
+		DatagramLoggingActivityFactory fac = new DatagramLoggingActivityFactory();
+		assertEquals(org.apache.oodt.commons.net.Net.getLoopbackAddress(), fac.host);
+		assertEquals(4556, fac.port);
+		fac.socket.close();
+
+		System.getProperties().remove("org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.host");
+		System.setProperty("activity.host", "localhost");
+		fac = new DatagramLoggingActivityFactory();
+		assertEquals(org.apache.oodt.commons.net.Net.getLoopbackAddress(), fac.host);
+		assertEquals(4556, fac.port);
+		fac.socket.close();
+
+		DatagramSocket soc = new DatagramSocket();
+		int portNum = soc.getLocalPort();
+		System.setProperty("org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.port", String.valueOf(portNum));
+		System.setProperty("activity.port", "illegal-port-value");
+		fac = new DatagramLoggingActivityFactory();
+		assertEquals(portNum, fac.port);
+		fac.socket.close();
+
+		System.getProperties().remove("org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.port");
+		System.setProperty("activity.port", String.valueOf(portNum));
+		fac = new DatagramLoggingActivityFactory();
+		assertEquals(portNum, fac.port);
+		fac.socket.close();
+		soc.close();
+	}
+
+	/**
+	 * Test construction and transmission of datagrams.
+	 *
+	 * @throws SocketException if an error occurs.
+	 * @throws IOException if an error occurs.
+	 * @throws ClassNotFoundException if an error occurs.
+	 */
+	public void testActivityReceipt() throws SocketException, IOException, ClassNotFoundException {
+		DatagramSocket socket = null;
+		try {
+			byte[] buf = new byte[512];
+			DatagramPacket packet = new DatagramPacket(buf, buf.length);
+			socket = new DatagramSocket();
+			System.setProperty("activity.host", "localhost");
+			System.setProperty("activity.port", String.valueOf(socket.getLocalPort()));
+			DatagramLoggingActivityFactory fac = new DatagramLoggingActivityFactory();
+			Activity a = fac.createActivity();
+			Incident i = new Incident();
+			a.log(i);
+			socket.receive(packet);
+			ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(packet.getData(), packet.getOffset(),
+				packet.getLength()));
+			Incident j = (Incident) ois.readObject();
+			assertEquals(i, j);
+		} finally {
+			if (socket != null)
+				socket.close();
+		}
+	}
+
+	/**
+	 * Restore a system property.
+	 *
+	 * @param propName Name of the property to restore.
+	 * @param value Old value of the system property, or null if the property wasn't previously set.
+	 */
+	private static void restore(String propName, String value) {
+		if (value == null)
+			System.getProperties().remove(propName);
+		else
+			System.setProperty(propName, value);
+	}
+
+	/** Old value of <code>org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.host</code>. */
+	private String oldLongHost;
+
+	/** Old value of <code>activity.host</code>. */
+	private String oldShortHost;
+
+	/** Old value of <code>org.apache.oodt.commons.activity.DatagramLoggingActivityFactory.port</code>. */
+	private String oldLongPort;
+
+	/** Old value of <code>activity.port</code>. */
+	private String oldShortPort;
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/HistoryTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/HistoryTest.java
new file mode 100755
index 0000000..d54ec2f
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/HistoryTest.java
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons.activity;
+
+import java.util.List;
+import junit.framework.TestCase;
+
+/**
+ * Test the {@link History} class.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1 $
+ */
+public class HistoryTest extends TestCase implements Storage {
+	/**
+	 * Creates a new {@link HistoryTest} instance.
+	 *
+	 * @param name Case name.
+	 */
+	public HistoryTest(String name) {
+		super(name);
+	}
+
+	/**
+	 * Save the old idle and close times.
+	 *
+	 * @throws Exception if an error occurs.
+	 */
+	protected void setUp() throws Exception {
+		super.setUp();
+		oldIdle = History.idleTime;
+		oldClose = History.closeTime;
+	}
+
+	/**
+	 * Restore the old idle and close times.
+	 *
+	 * @throws Exception if an error occurs.
+	 */
+	protected void tearDown() throws Exception {
+		History.idleTime = oldIdle;
+		History.closeTime = oldClose;
+		super.tearDown();
+	}
+
+	public void testIllegalIncidents() {
+		History.closeTime = 50;
+		Incident one = new Incident();
+		one.setActivityID(new String("a"));				       // Want unique objects
+		Incident two = new Incident();
+		two.setActivityID(new String("a"));				       // Want unique objects
+		Incident three = new Incident();
+		three.setActivityID("b");
+		History history = new History(one, this);
+		history.addIncident(two);
+		try {
+			history.addIncident(three);
+			fail("Able to add Incidents with non-matching activity IDs");
+		} catch (IllegalArgumentException good) {}
+	}
+
+	/**
+	 * Test a normal, well-behaved lifecylce of (incident, incident, stop) with no
+	 * idle times.
+	 */
+	public void testLifecycle() {
+		History.closeTime = 50;
+		Incident one = new Incident();
+		one.setActivityID("test");
+		History history = new History(one, this);
+		rest();
+		Incident two = new Incident();
+		two.setActivityID("test");
+		history.addIncident(two);
+		rest();
+		ActivityStopped three = new ActivityStopped();
+		three.setActivityID("test");
+		history.addIncident(three);
+		rest();
+		assertNotNull("History never called store", id);
+		assertEquals("test", id);
+		assertNotNull(incidents);
+		assertEquals(3, incidents.size());
+		assertEquals(one, incidents.get(0));
+		assertEquals(two, incidents.get(1));
+		assertEquals(three, incidents.get(2));
+	}
+
+	/**
+	 * Test arrival and recording of incidents <i>after</i> the stop incident.
+	 */
+	public void testPostCloseIncidents() {
+		History.closeTime = 300;
+		Incident one = new Incident();
+		one.setActivityID("test");
+		rest();
+		ActivityStopped two = new ActivityStopped();
+		two.setActivityID("test");
+		rest();
+		Incident three = new Incident();
+		three.setActivityID("test");
+
+		History history = new History(one, this);
+		history.addIncident(two);
+		rest();
+		history.addIncident(three);
+		rest(1200);
+
+		assertNotNull("History never called store", id);
+		assertEquals("test", id);
+		assertNotNull(incidents);
+		assertEquals(3, incidents.size());
+		assertEquals(one, incidents.get(0));
+		assertEquals(two, incidents.get(1));
+		assertEquals(three, incidents.get(2));
+	}
+
+	/**
+	 * Test if an idle history is committed when a stop incident is late.
+	 */
+	public void testIdleHistory() {
+		History.idleTime = 300;
+		History.closeTime = 100;
+		Incident one = new Incident();
+		one.setActivityID("test");
+		rest();
+		Incident two = new Incident();
+		two.setActivityID("test");
+		rest();
+		ActivityStopped three = new ActivityStopped();
+		three.setActivityID("test");
+
+		History history = new History(one, this);
+		rest();
+		history.addIncident(two);
+		rest(500);
+		history.addIncident(three);
+
+		assertNotNull("History never called store", id);
+		assertEquals("test", id);
+		assertNotNull(incidents);
+		assertEquals(2, incidents.size());
+		assertEquals(one, incidents.get(0));
+		assertEquals(two, incidents.get(1));
+	}
+
+	/**
+	 * Test if an idle history is committed and the stop incident arrives in time to
+	 * be recorded.
+	 */
+	public void testPostCommitActivityStop() {
+		History.idleTime = 300;
+		History.closeTime = 500;
+		Incident one = new Incident();
+		one.setActivityID("test");
+		rest();
+		Incident two = new Incident();
+		two.setActivityID("test");
+		rest();
+		ActivityStopped three = new ActivityStopped();
+		three.setActivityID("test");
+
+		History history = new History(one, this);
+		rest();
+		history.addIncident(two);
+		rest(500);
+		history.addIncident(three);
+		rest(400);
+
+		assertNotNull("History never called store", id);
+		assertEquals("test", id);
+		assertNotNull(incidents);
+		assertEquals(3, incidents.size());
+		assertEquals(one, incidents.get(0));
+		assertEquals(two, incidents.get(1));
+		assertEquals(three, incidents.get(2));
+	}
+
+	/**
+	 * Our test storage just saves the last received ID and list of incidents.
+	 *
+	 * @param id ID, which should always be <code>test</code>.
+	 * @param incidents {@link List} of received {@link Incident}s.
+	 */
+	public void store(String id, List incidents) {
+		this.id = id;
+		this.incidents = incidents;
+	}
+
+	/**
+	 * Pause the current thread for the given time.
+	 *
+	 * @param time Milliseconds to sleep.
+	 */
+	private static void rest(long time) {
+		try {
+			Thread.sleep(time);
+		} catch (InterruptedException ignore) {}
+	}
+
+	/**
+	 * Pause the current thread for 100 milliseconds.
+	 */
+	private static void rest() {
+		rest(100);
+	}
+
+	/** Last stored ID. */
+	private String id;
+
+	/** Last stored list of {@link Incident}s. */
+	private List incidents;
+
+	/** Idle time to restore. */
+	private long oldIdle;
+
+	/** Close time to restore. */
+	private long oldClose;
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/IncidentTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/IncidentTest.java
new file mode 100755
index 0000000..779d4c7
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/activity/IncidentTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+

+package org.apache.oodt.commons.activity;

+

+import java.util.Date;

+import junit.framework.TestCase;

+

+/**

+ * Test the {@link Incident} class.

+ *

+ * @author Kelly

+ * @version $Revision: 1.1 $

+ */

+public class IncidentTest extends TestCase {

+	/**

+	 * Creates a new {@link IncidentTest} instance.

+	 *

+	 * @param name Case name.

+	 */

+	public IncidentTest(String name) {

+		super(name);

+	}

+

+	/**

+	 * Make sure incidents get timestamped.

+	 */

+	public void testTimestamping() {

+		Incident i = new Incident();

+		rest();

+		assertTrue(new Date().compareTo(i.getTime()) > 0);

+	}

+

+	/**

+	 * See if incidents are "well-behaved" objects.

+	 */

+	public void testObjectMethods() {

+		Incident a = new Incident();

+		rest();

+		Incident b = new Incident();

+

+		assertEquals(a, a);

+		assertTrue(!a.equals(b));

+		assertTrue(a.compareTo(b) < 0);

+		assertTrue(b.compareTo(a) > 0);

+		int ignore = a.hashCode();

+

+		b.setActivityID("test");

+		assertTrue(!b.equals(a));

+		assertTrue(a.compareTo(b) < 0);

+		assertTrue(b.compareTo(a) > 0);

+		ignore = b.hashCode();

+	}

+

+	/**

+	 * Pause current thread for 10 whole milliseconds.

+	 */

+	private static void rest() {

+		try {

+			Thread.sleep(10);

+		} catch (InterruptedException ignore) {}

+	}

+}

diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/exec/TestEnvUtilities.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/exec/TestEnvUtilities.java
new file mode 100644
index 0000000..61d02dc
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/exec/TestEnvUtilities.java
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons.exec;
+
+//JDK imports
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Properties;
+
+//Apache Commons
+import org.apache.commons.lang.SystemUtils;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @author mstarch
+ * @version $Revision$
+ * 
+ * <p>
+ * Test case for {@link EnvUtilities}
+ * </p>.
+ */
+public class TestEnvUtilities extends TestCase {
+
+    private static final String envVarStr = "TOMCAT_HOME=/usr/local/tomcat\nPROMPT=\\u \\p\n";
+
+    private static final String expectedVarStr = "TOMCAT_HOME=/usr/local/tomcat\nPROMPT=\\\\u \\\\p\n";
+
+    /**
+     * @since OODT-178
+     * 
+     */
+    public void testPreProcessInputStream() {
+        ByteArrayInputStream is = new ByteArrayInputStream(envVarStr.getBytes());
+        InputStream translatedIs = null;
+        try {
+            translatedIs = EnvUtilities.preProcessInputStream(is);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(translatedIs);
+        String translatedEnvStr = null;
+        try {
+            translatedEnvStr = EnvUtilities.slurp(translatedIs);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+        assertNotNull(translatedEnvStr);
+        assertEquals(translatedEnvStr, expectedVarStr);
+
+    }
+    /**
+     * Tests two environment variables that should exist in any build 
+     * environment. USER, HOME
+     * By calling (EnvUtilities.getEnv(String))
+     */
+    public void testSetEnvironmentVar() {
+        //Test if an only if HOME and USER is defined (Assumed to be true on unix)
+        if (SystemUtils.IS_OS_UNIX) {
+            //Makes the assumption that System.properties() is correct.
+            String userHomeTruth = System.getProperty("user.home");
+            String userNameTruth = System.getProperty("user.name");
+            //Test values
+            String userHomeTest = EnvUtilities.getEnv("HOME");
+            String userNameTest = EnvUtilities.getEnv("USER");
+            //Check all three tests
+            assertEquals(userHomeTruth,userHomeTest);
+            assertEquals(userNameTruth,userNameTest);
+        } 
+    }
+    /**
+     * Tests two environment variables that should exist in any build 
+     * environment. USER, HOME
+     * By getting the environment (EnvUtilities.getEnv()) and reading from this.
+     */
+    public void testGetEnvironment() {
+        //Test if an only if HOME and USER is defined (Assumed to be true on unix)
+        if (SystemUtils.IS_OS_UNIX) {
+            //Makes the assumption that System.properties() is correct.
+            String userHomeTruth = System.getProperty("user.home");
+            String userNameTruth = System.getProperty("user.name");
+            Properties env = EnvUtilities.getEnv();
+            //Test values
+            String userHomeTest = env.getProperty("HOME");
+            String userNameTest = env.getProperty("USER");
+            //Check all three tests
+            assertEquals(userHomeTruth,userHomeTest);
+            assertEquals(userNameTruth,userNameTest);
+        } 
+    }
+    /**
+     * Tests for consistency between the two methods for getting environment variables
+     * in EnvUtilities calling getEnv(String) and calling getEnv().getProperty(String).
+     */
+    public void testGetEnvironmentConsistency() {
+        //Test if an only if HOME and USER is defined (Assumed to be true on unix)
+        if (SystemUtils.IS_OS_UNIX) {
+            Properties env = EnvUtilities.getEnv();
+            //Test values
+            String userHomeTest1 = env.getProperty("HOME");
+            String userNameTest1 = env.getProperty("USER");
+            String userHomeTest2 = EnvUtilities.getEnv("HOME");
+            String userNameTest2 = EnvUtilities.getEnv("USER");
+            //Check all three tests
+            assertEquals(userHomeTest1,userHomeTest2);
+            assertEquals(userNameTest1,userNameTest2);
+        }
+    }
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/filter/TestTimeEventWeightedHash.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/filter/TestTimeEventWeightedHash.java
new file mode 100644
index 0000000..53c1243
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/filter/TestTimeEventWeightedHash.java
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.commons.filter;
+
+//JDK imports
+import java.util.LinkedList;
+import java.util.List;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Test case for {@link TimeEventWeightedHash}
+ * </p>.
+ */
+public class TestTimeEventWeightedHash extends TestCase {
+
+	public void testBuildHash() {
+	      List<TimeEvent> events = new LinkedList<TimeEvent>();
+	      events.add(new ObjectTimeEvent<String>(31, 32, 2, "1"));
+	      events.add(new ObjectTimeEvent<String>(20, 30, 1, "2"));
+	      events.add(new ObjectTimeEvent<String>(1, 8, 2, "3"));
+	      events.add(new ObjectTimeEvent<String>(8, 15, 1, "4"));
+	      events.add(new ObjectTimeEvent<String>(18, 20, 3, "5"));
+	      events.add(new ObjectTimeEvent<String>(10, 12, 1, "6"));
+	      events.add(new ObjectTimeEvent<String>(20, 30, 2, "7"));
+	      events.add(new ObjectTimeEvent<String>(1, 20, 1, "8"));
+	      events.add(new ObjectTimeEvent<String>(11, 13, 1, "9"));
+	      events.add(new ObjectTimeEvent<String>(15, 20, 1, "10"));
+	      events.add(new ObjectTimeEvent<String>(18, 20, 2, "11"));
+	      events.add(new ObjectTimeEvent<String>(1, 15, 1, "12"));
+	      events.add(new ObjectTimeEvent<String>(1, 18, 2, "13"));
+	      TimeEventWeightedHash timeEventHash = TimeEventWeightedHash.buildHash(events);
+	      
+	      List<ObjectTimeEvent> orderedEvents = (List<ObjectTimeEvent>) timeEventHash.getGreatestWeightedPathAsOrderedList();
+	      assertEquals(orderedEvents.size(), 3);
+	      assertEquals(orderedEvents.get(0).getTimeObject().toString(), "13");
+	      assertEquals(orderedEvents.get(1).getTimeObject().toString(), "7");
+	      assertEquals(orderedEvents.get(2).getTimeObject().toString(), "1");
+	      
+	      events = new LinkedList<TimeEvent>();
+	      events.add(new ObjectTimeEvent<String>(33, 215, 1, "1"));
+	      events.add(new ObjectTimeEvent<String>(215, 359, 1, "2"));
+	      events.add(new ObjectTimeEvent<String>(358, 541, 1, "3"));
+	      events.add(new ObjectTimeEvent<String>(541, 723, 1, "4"));
+	      events.add(new ObjectTimeEvent<String>(723, 904, 1, "5"));
+	      events.add(new ObjectTimeEvent<String>(904, 904, 1, "6"));
+	      events.add(new ObjectTimeEvent<String>(904, 1045, 1, "7"));
+	      events.add(new ObjectTimeEvent<String>(905, 905, 1, "8"));
+	      events.add(new ObjectTimeEvent<String>(906, 907, 1, "9"));
+	      events.add(new ObjectTimeEvent<String>(907, 908, 1, "10"));
+	      events.add(new ObjectTimeEvent<String>(908, 908, 1, "11"));
+	      events.add(new ObjectTimeEvent<String>(908, 909, 1, "12"));
+	      events.add(new ObjectTimeEvent<String>(923, 924, 1, "13"));
+	      events.add(new ObjectTimeEvent<String>(926, 927, 1, "14"));
+	      events.add(new ObjectTimeEvent<String>(927, 928, 1, "15"));
+	      events.add(new ObjectTimeEvent<String>(942, 943, 1, "16"));
+	      events.add(new ObjectTimeEvent<String>(945, 946, 1, "17"));
+	      events.add(new ObjectTimeEvent<String>(946, 946, 1, "18"));
+	      events.add(new ObjectTimeEvent<String>(947, 947, 1, "19"));
+	      events.add(new ObjectTimeEvent<String>(1004, 1005, 1, "20"));
+	      events.add(new ObjectTimeEvent<String>(1005, 1005, 1, "21"));
+	      events.add(new ObjectTimeEvent<String>(1006, 1006, 1, "22"));
+	      events.add(new ObjectTimeEvent<String>(1007, 1007, 1, "23"));
+	      events.add(new ObjectTimeEvent<String>(1025, 1026, 1, "24"));
+	      events.add(new ObjectTimeEvent<String>(1026, 1026, 1, "25"));
+	      events.add(new ObjectTimeEvent<String>(1027, 1028, 1, "26"));
+	      events.add(new ObjectTimeEvent<String>(1045, 1046, 1, "27"));
+	      events.add(new ObjectTimeEvent<String>(1045, 1225, 1, "28"));
+	      events.add(new ObjectTimeEvent<String>(1225, 1406, 1, "29"));
+	      events.add(new ObjectTimeEvent<String>(1225, 1226, 1, "30"));
+	      events.add(new ObjectTimeEvent<String>(1226, 1227, 1, "31"));
+	      events.add(new ObjectTimeEvent<String>(1227, 1227, 1, "32"));
+	      events.add(new ObjectTimeEvent<String>(1228, 1228, 1, "33"));
+	      events.add(new ObjectTimeEvent<String>(1406, 1546, 1, "34"));
+	      events.add(new ObjectTimeEvent<String>(1545, 1725, 1, "35"));
+	      events.add(new ObjectTimeEvent<String>(1545, 1554, 1, "36"));
+	      events.add(new ObjectTimeEvent<String>(1725, 1906, 1, "37"));
+	      events.add(new ObjectTimeEvent<String>(1906, 2047, 1, "38"));
+	      events.add(new ObjectTimeEvent<String>(1906, 1922, 1, "39"));
+	      events.add(new ObjectTimeEvent<String>(2047, 2228, 1, "40"));
+	      events.add(new ObjectTimeEvent<String>(2228, 2412, 1, "41"));
+	      timeEventHash = TimeEventWeightedHash.buildHash(events, 2);
+	      
+	      orderedEvents = (List<ObjectTimeEvent>) timeEventHash.getGreatestWeightedPathAsOrderedList();
+	      assertEquals(orderedEvents.size(), 14);
+	      assertEquals(orderedEvents.get(0).getTimeObject().toString(), "1");
+	      assertEquals(orderedEvents.get(1).getTimeObject().toString(), "2");
+	      assertEquals(orderedEvents.get(2).getTimeObject().toString(), "3");
+	      assertEquals(orderedEvents.get(3).getTimeObject().toString(), "4");
+	      assertEquals(orderedEvents.get(4).getTimeObject().toString(), "5");
+	      assertEquals(orderedEvents.get(5).getTimeObject().toString(), "7");
+	      assertEquals(orderedEvents.get(6).getTimeObject().toString(), "28");
+	      assertEquals(orderedEvents.get(7).getTimeObject().toString(), "29");
+	      assertEquals(orderedEvents.get(8).getTimeObject().toString(), "34");
+	      assertEquals(orderedEvents.get(9).getTimeObject().toString(), "35");
+	      assertEquals(orderedEvents.get(10).getTimeObject().toString(), "37");
+	      assertEquals(orderedEvents.get(11).getTimeObject().toString(), "38");
+	      assertEquals(orderedEvents.get(12).getTimeObject().toString(), "40");
+	      assertEquals(orderedEvents.get(13).getTimeObject().toString(), "41");
+	}
+	
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/io/FixedBufferOutputStreamTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/io/FixedBufferOutputStreamTest.java
new file mode 100644
index 0000000..a3efa38
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/io/FixedBufferOutputStreamTest.java
@@ -0,0 +1,183 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import junit.framework.TestCase;
+
+/** Unit test for the {@link FixedBufferOutputStream} class.
+ *
+ * @author Kelly
+ */
+public class FixedBufferOutputStreamTest extends TestCase {
+	/** Construct the test case for the {@link FixedBufferOutputStream} class.
+	 *
+	 * @param name Case name.
+	 */
+	public FixedBufferOutputStreamTest(String name) {
+		super(name);
+	}
+
+	/** Test the fixed buffer output stream's methods with various illegal arguments.
+	 */
+	public void testIllegalArgs() throws IOException {
+		try {
+			new FixedBufferOutputStream(-1);
+			fail("Illegal size failed to throw exception");
+		} catch (IllegalArgumentException good) {}
+		FixedBufferOutputStream out = new FixedBufferOutputStream(100);
+		try {
+			out.write(null);
+			fail("Writing a null byte array failed to throw exception");
+		} catch (NullPointerException good) {}
+		try {
+			out.write(null, 0, 10);
+			fail("Writing a null byte array failed to throw exception");
+		} catch (NullPointerException good) {}
+		try {
+			out.write(TEST_DATA, -1, 10);
+			fail("Writing with negative offset failed to throw exception");
+		} catch (IndexOutOfBoundsException good) {}
+		try {
+			out.write(TEST_DATA, TEST_DATA.length + 1, 10);
+			fail("Writing with offset past end of array failed to throw exception");
+		} catch (IndexOutOfBoundsException good) {}
+		try {
+			out.write(TEST_DATA, 0, -1);
+			fail("Writing with negative length array failed to throw exception");
+		} catch (IndexOutOfBoundsException good) {}
+		try {
+			out.write(TEST_DATA, 2, 5);
+			fail("Writing with offset and length exceeding end of array failed to throw exception");
+		} catch (IndexOutOfBoundsException good) {}
+	}
+
+	/** Test a stream with space for no bytes at all.
+	 */
+	public void testZeroSizeStream() throws IOException {
+		FixedBufferOutputStream out = new FixedBufferOutputStream(0);			    // Space for no byte at all
+		out.write(1);									    // Write a 1 
+		out.write(2);									    // ...and a 2
+		out.write(3);									    // ...and a 3
+		out.write(TEST_DATA);								    // ...and a byte array
+		byte[] buffer = out.getBuffer();						    // Get the buffer
+		assertNotNull(buffer);								    // It should never be null
+		assertEquals(0, buffer.length);							    // But it should be empty
+	}
+
+	/** Test a stream under various conditions.
+	 */
+	public void testStream() throws IOException {
+		FixedBufferOutputStream out = new FixedBufferOutputStream(10);			    // Space for 10 bytes
+		byte[] buffer = out.getBuffer();						    // Get the buffer
+		assertNotNull(buffer);								    // It should never be null
+		assertEquals(0, buffer.length);							    // Nothing written => 0 length
+		out.write(1);									    // [1]
+		buffer = out.getBuffer();							    // Get the buffer
+		assertNotNull(buffer);								    // It should never be null
+		assertEquals(1, buffer.length);							    // Only 1 byte so far
+		assertEquals(1, buffer[0]);							    // And it should be a 1
+		out.write(2);									    // [1,2]
+		buffer = out.getBuffer();							    // Get the buffer
+		assertNotNull(buffer);								    // It should never be null
+		assertEquals(2, buffer.length);							    // Two bytes so far
+		assertEquals(1, buffer[0]);							    // And it should be a 1...
+		assertEquals(2, buffer[1]);							    // ...and a 2
+		out.write(3);									    // [1,2,3]
+		buffer = out.getBuffer();							    // Get the buffer
+		assertNotNull(buffer);								    // It should never be null
+		assertEquals(3, buffer.length);							    // 3 bytes so far
+		assertEquals(1, buffer[0]);							    // They are 1
+		assertEquals(2, buffer[1]);							    // ...and 2
+		assertEquals(3, buffer[2]);							    // ...and 3
+
+		out.write(TEST_DATA);								    // [1,2,3,8,9,10,11]
+		buffer = out.getBuffer();							    // Get the buffer
+		assertNotNull(buffer);								    // It should never be null
+		assertEquals(7, buffer.length);							    // 7 bytes so far, right?
+		assertEquals(1, buffer[0]);							    // They are 1
+		assertEquals(2, buffer[1]);							    // ...and 2
+		assertEquals(3, buffer[2]);							    // ...and 3
+		assertEquals(8, buffer[3]);							    // ...and 8
+		assertEquals(9, buffer[4]);							    // ...and 9
+		assertEquals(10, buffer[5]);							    // ...and 10
+		assertEquals(11, buffer[6]);							    // ...and 11
+
+		out.write(TEST_DATA);								    // [2,3,8,9,10,11,8,9,10,11]
+		out.write(TEST_DATA, 1, 2);							    // [8,9,10,11,8,9,10,11,9,10]
+		buffer = out.getBuffer();							    // Get the buffer
+		assertNotNull(buffer);								    // It should never be null
+		assertEquals(10, buffer.length);						    // Full buffer
+		assertEquals(8, buffer[0]);							    // They are 8
+		assertEquals(9, buffer[1]);							    // ...and 9
+		assertEquals(10, buffer[2]);							    // ...and 10
+		assertEquals(11, buffer[3]);							    // ...and 11
+		assertEquals(8, buffer[4]);							    // ...and 8
+		assertEquals(9, buffer[5]);							    // ...and 9
+		assertEquals(10, buffer[6]);							    // ...and 10
+		assertEquals(11, buffer[7]);							    // ...and 11
+		assertEquals(9, buffer[8]);							    // ...and 9
+		assertEquals(10, buffer[9]);							    // ...and 10
+
+		out.write(TEST_DATA);								    // [8,9,10,11,9,10,8,9,10,11]
+		out.write(TEST_DATA, 0, 1);							    // [9,10,11,9,10,8,9,10,11,8]
+		out.write(42);									    // [10,11,9,10,8,9,10,11,8,42]
+		out.write(99);									    // [11,9,10,8,9,10,11,8,42,99]
+		out.write(TEST_DATA, 1, 3);							    // [8,9,10,11,8,42,99,9,10,11]
+		buffer = out.getBuffer();							    // Get the buffer
+		assertNotNull(buffer);								    // It should never be null
+		assertEquals(10, buffer.length);						    // Full buffer
+		assertEquals(8, buffer[0]);							    // They are 8
+		assertEquals(9, buffer[1]);							    // ...and 9
+		assertEquals(10, buffer[2]);							    // ...and 10
+		assertEquals(11, buffer[3]);							    // ...and 11
+		assertEquals(8, buffer[4]);							    // ...and 8
+		assertEquals(42, buffer[5]);							    // ...and 42
+		assertEquals(99, buffer[6]);							    // ...and 99
+		assertEquals(9, buffer[7]);							    // ...and 9
+		assertEquals(10, buffer[8]);							    // ...and 10
+		assertEquals(11, buffer[9]);							    // ...and 11
+
+		byte[] array = new byte[buffer.length];						    // New test data array that's
+		System.arraycopy(buffer, 0, array, 0, buffer.length);				    // the same as the current buf
+		out.write(array);								    // ...and write that
+		buffer = out.getBuffer();							    // Get the buffer
+		assertNotNull(buffer);								    // It should never be null
+		assertTrue(Arrays.equals(array, buffer));					    // Should get same result
+
+		byte[] big = new byte[buffer.length * 3];					    // More new test data array
+		System.arraycopy(buffer, 0, big, 0, buffer.length);				    // ...and add some data
+		System.arraycopy(buffer, 0, big, buffer.length, buffer.length);			    // ...and more data
+		System.arraycopy(buffer, 0, big, buffer.length * 2, buffer.length);		    // ...and LOTS of data
+		out.write(big, buffer.length, buffer.length * 2);				    // Write the last third of it
+		buffer = out.getBuffer();							    // Get the buffer
+		assertNotNull(buffer);								    // It should never be null
+		assertTrue(Arrays.equals(array, buffer));					    // Should get same result!
+
+		out.close();									    // Close it
+		try {										    // ...and try...
+			out.write(1);								    // ...to write to it
+			fail("Writing to a closed stream failed to throw an exception");	    // Shouldn't get here
+		} catch (IOException good) {}							    // Should get here
+	}
+
+	/** Some test data in an array. */
+	private static final byte[] TEST_DATA = new byte[] {
+		(byte) 8, (byte) 9, (byte) 10, (byte) 11
+	};
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/io/NullInputStreamTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/io/NullInputStreamTest.java
new file mode 100644
index 0000000..cf92b7f
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/io/NullInputStreamTest.java
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import junit.framework.TestCase;
+
+/**
+ * Unit test the {@link NullInputStream} class.
+ *
+ * @author Kelly
+ */ 
+public class NullInputStreamTest extends TestCase {
+        /**
+	 * Creates a new <code>NullInputStreamTest</code> instance.
+	 *
+	 * @param name Test case name.
+	 */
+	public NullInputStreamTest(String name) {
+                super(name);
+        }
+
+        protected void setUp() throws Exception {
+                in = new NullInputStream();
+        }
+
+        public void testClosing() {
+                try {
+                        in.close();
+                } catch (IOException ex) {
+                        fail("Should not throw an exception on close: " + ex.getMessage());
+                }
+                try {
+                        in.read();
+                        fail("Should not be able to read a closed stream");
+                } catch (IOException ignore) {}
+                try {
+                        in.close();
+                        fail("Should not be able to close a closed stream");
+                } catch (IOException ignore) {}
+        }
+
+        public void testReading() {
+                try {
+                        assertEquals(-1, in.read());
+                } catch (IOException ex) {
+                        fail("Should not throw an exception on reading: " + ex.getMessage());
+                }
+        }
+
+        /** The {@link NullInputStream} we're testing. */
+        private NullInputStream in;
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/io/NullOutputStreamTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/io/NullOutputStreamTest.java
new file mode 100644
index 0000000..b6a234e
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/io/NullOutputStreamTest.java
@@ -0,0 +1,79 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.io;
+
+import java.io.*;
+import java.util.*;
+import junit.framework.*;
+
+/** Unit test the {@link NullOutputStream} class.
+ *
+ * @author Kelly
+ */ 
+public class NullOutputStreamTest extends TestCase {
+	/** Construct the test case for the {@link NullOutputStream} class. */
+	public NullOutputStreamTest(String name) {
+		super(name);
+	}
+
+	protected void setUp() throws Exception {
+		out = new NullOutputStream();
+	}
+
+	public void testClosing() {
+		try {
+			out.close();
+		} catch (IOException ex) {
+			fail("Should not throw an exception on close: " + ex.getMessage());
+		}
+		try {
+			out.write(1);
+			fail("Should not be able to write to a closed stream");
+		} catch (IOException ignore) {}
+		try {
+			out.flush();
+			fail("Should not be able to flush a closed stream");
+		} catch (IOException ignore) {}
+		try {
+			out.close();
+			fail("Should not be able to close a closed stream");
+		} catch (IOException ignore) {}
+	}
+
+	public void testFlush() {
+		try {
+			out.flush();
+		} catch (IOException ex) {
+			fail("Should not throw an exception on flush: " + ex.getMessage());
+		}
+	}
+
+	public void testWriting() {
+		try {
+			byte[] array = new byte[]{(byte)0, (byte)1, (byte)2};
+			out.write(1);
+			out.write(array);
+			out.write(array, 1, 1);
+		} catch (IOException ex) {
+			fail("Should not throw an exception on writing: " + ex.getMessage());
+		}
+	}
+
+	/** The {@link NullOutputStream} we're testing. */
+	private NullOutputStream out;
+
+}
+
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/io/TestLoggerOutputStream.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/io/TestLoggerOutputStream.java
new file mode 100644
index 0000000..5c17b69
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/io/TestLoggerOutputStream.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.commons.io;
+
+//JDK imports
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link LoggerOutputStream}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestLoggerOutputStream extends TestCase {
+
+   public void testLogging() throws InstantiationException, IOException {
+      final List<LogRecord> records = new ArrayList<LogRecord>();
+      Logger logger = Logger.getLogger(TestLoggerOutputStream.class.getName());
+      logger.addHandler(new Handler() {
+         @Override
+         public void close() throws SecurityException {}
+         @Override
+         public void flush() {}
+         @Override
+         public void publish(LogRecord record) {
+            records.add(record);
+         }
+      });
+      LoggerOutputStream los = new LoggerOutputStream(logger, 10, Level.INFO);
+      los.write("This is a test write to a log file".getBytes());
+      los.close();
+      assertEquals("This is a ", records.get(0).getMessage());
+      assertEquals("test write", records.get(1).getMessage());
+      assertEquals(" to a log ", records.get(2).getMessage());
+      assertEquals("file", records.get(3).getMessage());
+   }
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/net/NetTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/net/NetTest.java
new file mode 100644
index 0000000..197c706
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/net/NetTest.java
@@ -0,0 +1,51 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.net;
+
+import java.net.InetAddress;
+import junit.framework.*;
+
+/** Unit test the {@link Net} class.
+ *
+ * @author Kelly
+ */ 
+public class NetTest extends TestCase {
+	/** Construct the test case for the {@link Net} class.
+	 */
+	public NetTest(String name) {
+		super(name);
+	}
+
+	/** Test the {@link Net#getLoopbackAddress} method.
+	 */
+	public void testGetLoopbackAddress() {
+		InetAddress addr = Net.getLoopbackAddress();
+		assertNotNull(addr);
+		byte[] bytes = addr.getAddress();
+		assertNotNull(bytes);
+		assertEquals(4, bytes.length);
+		assertEquals(127, bytes[0]);
+		assertEquals(0, bytes[1]);
+		assertEquals(0, bytes[2]);
+		assertEquals(1, bytes[3]);
+	}
+
+	public void testGetLocalHost() {
+		InetAddress addr = Net.getLocalHost();
+		assertNotNull(addr);
+	}
+}
+
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/object/jndi/ObjectContextTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/object/jndi/ObjectContextTest.java
new file mode 100644
index 0000000..e328afa
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/object/jndi/ObjectContextTest.java
@@ -0,0 +1,203 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.object.jndi;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import javax.naming.Binding;
+import javax.naming.NameClassPair;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import org.apache.oodt.commons.object.jndi.ObjectContext;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for {@link ObjectContext}.
+ *
+ * @author Kelly
+ * @version $Revision: 1.2 $
+ */
+public class ObjectContextTest extends TestCase {
+	/**
+	 * Creates a new <code>ObjectContextTest</code> instance.
+	 *
+	 * @param caseName a <code>String</code> value.
+	 */
+	public ObjectContextTest(String caseName) {
+		super(caseName);
+	}
+
+	public void setUp() throws Exception {
+		super.setUp();
+
+		aliasFile = File.createTempFile("test", ".properties");
+		aliasFile.deleteOnExit();
+		Properties aliases = new Properties();
+		aliases.setProperty("urn:alias:x", "urn:a:x");
+		FileOutputStream out = new FileOutputStream(aliasFile);
+		aliases.save(out, "Temporary properties");
+		out.close();
+
+		a1 = new TestContext("urn:a");
+		a2 = new TestContext("urn:a");
+		b = new TestContext("urn:b");
+
+		oldValue = System.getProperty("org.apache.oodt.commons.object.jndi.aliases");
+		System.setProperty("org.apache.oodt.commons.object.jndi.aliases", aliasFile.toString());
+
+		List contexts = new ArrayList();
+		contexts.add(a1);
+		contexts.add(a2);
+		contexts.add(b);
+		context = new ObjectContext(contexts);
+	}
+
+	public void tearDown() throws Exception {
+		aliasFile.delete();
+		if (oldValue == null)
+			System.getProperties().remove("org.apache.oodt.commons.object.jndi.aliases");
+		else
+			System.setProperty("org.apache.oodt.commons.object.jndi.aliases", oldValue);
+		super.tearDown();
+	}
+
+	/**
+	 * Test various aspects of the object context.
+	 *
+	 * @throws NamingException if an error occurs.
+	 */
+	public void testObjectContext() throws NamingException {
+		// Test retrieval of nonexistent bindings
+		try {
+			context.lookup("urn:a:x");
+			fail("Found nonexistent object");
+		} catch (NamingException ex) {}
+
+		// Test binding names that don't match any delegate's namespace prefix.
+		try {
+			context.bind("urn:c:x", this);
+			fail("Bound nonconforming name");
+		} catch (NamingException ex) {}
+
+		// Test binding and retrieval
+		context.bind("urn:a:x", this);					       // Bind something
+		assertSame(this, context.lookup("urn:a:x"));			       // Look it up
+		assertSame(this, context.lookup("urn:alias:x"));		       // Try the alias
+		assertTrue(a1.bindings.values().contains(this));		       // It should be in both a1...
+		assertTrue(a2.bindings.values().contains(this));		       // ...and a2
+		assertTrue(!b.bindings.values().contains(this));		       // But not b.
+
+		context.bind("urn:b:x", getClass());				       // Now bind something for b
+		assertSame(getClass(), context.lookup("urn:b:x"));		       // Look it up
+		assertTrue(!a1.bindings.values().contains(getClass()));		       // It should not be in a1...
+		assertTrue(!a2.bindings.values().contains(getClass()));		       // ...nor a2
+		assertTrue(b.bindings.values().contains(getClass()));		       // But should be in b.
+
+		// Test binding a bound name
+		try {
+			context.bind("urn:a:x", "");
+			fail("Able to bind an already-bound name");
+		} catch (NamingException ex) {}
+
+		// Test rebinding a bound name
+		context.rebind("urn:a:x", context);				       // Bind to a different object
+		assertSame(context, context.lookup("urn:a:x"));			       // Look it up
+		assertTrue(!a1.bindings.values().contains(this));		       // The old object should be gone from a1...
+		assertTrue(!a2.bindings.values().contains(this));		       // ...and from a2
+		assertTrue(!b.bindings.values().contains(context));		       // And the new object isn't in b
+
+		// Test renaming
+		context.rename("urn:a:x", "urn:a:y");				       // Change x to y
+		try {
+			context.lookup("urn:a:x");				       // Look it up
+			fail("Found object under old name");
+		} catch (NamingException ex) {}
+		assertSame(context, context.lookup("urn:a:y"));			       // Just the name has changed
+		assertTrue(a1.bindings.keySet().contains("urn:a:y"));		       // The new name is in a1
+		assertTrue(!a1.bindings.keySet().contains("urn:a:x"));		       // But not the old
+		assertTrue(a2.bindings.keySet().contains("urn:a:y"));		       // The new name is in a2
+		assertTrue(!a2.bindings.keySet().contains("urn:a:x"));		       // But not the old
+		assertTrue(!b.bindings.values().contains(context));		       // It was never in b
+
+		// Test listing
+		int count = 0;
+		boolean sawA = false;
+		boolean sawB = false;
+		NamingEnumeration e = context.list("");
+		while (e.hasMore()) {
+			NameClassPair p = (NameClassPair) e.next();
+			if ("urn:a:y".equals(p.getName()) && context.getClass().getName().equals(p.getClassName()))
+				sawA = true;
+			else if ("urn:b:x".equals(p.getName()) && "java.lang.Class".equals(p.getClassName()))
+				sawB = true;
+			else
+				fail("Unexpected binding \"" + p.getName() + "\" to " + p.getClassName());
+			++count;
+		}
+		assertEquals(3, count);
+		assertTrue(sawA);
+		assertTrue(sawB);
+
+		// Test listing of bindings
+		count = 0;
+		sawA = false;
+		sawB = false;
+		e = context.listBindings("");
+		while (e.hasMore()) {
+			Binding b = (Binding) e.next();
+			if ("urn:a:y".equals(b.getName()) && context == b.getObject())
+				sawA = true;
+			else if ("urn:b:x".equals(b.getName()) && getClass() == b.getObject())
+				sawB = true;
+			else
+				fail("Unexpected binding \"" + b.getName() + "\" to " + b.getObject());
+			++count;
+		}
+		assertEquals(3, count);
+		assertTrue(sawA);
+		assertTrue(sawB);
+			
+		// Test unbinding
+		context.unbind("urn:a:y");					       // Unbind it
+		try {
+			context.lookup("urn:a:y");				       // Look it up
+			fail("Found unbound object");
+		} catch (NamingException ex) {}
+		assertTrue(a1.bindings.isEmpty());				       // It's not in a1...
+		assertTrue(a2.bindings.isEmpty());				       // ...nor in a2
+	}
+
+	/** First delegate context for "urn:a" namespace. */
+	private TestContext a1;
+
+	/** Second delegate context for "urn:a" namespace. */
+	private TestContext a2;
+
+	/** Delegate context for "urn:b" namespace. */
+	private TestContext b;
+
+	/** Test subject: the object context. */
+	private ObjectContext context;
+
+	/** Test alias file. */
+	private File aliasFile;
+
+	/** Old value of sys prop org.apache.oodt.commons.object.jndi.aliases. */
+	private String oldValue;
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/object/jndi/TestContext.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/object/jndi/TestContext.java
new file mode 100644
index 0000000..59e5cc5
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/object/jndi/TestContext.java
@@ -0,0 +1,203 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.object.jndi;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import javax.naming.Binding;
+import javax.naming.CompositeName;
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameClassPair;
+import javax.naming.NameNotFoundException;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.OperationNotSupportedException;
+
+/**
+ * A context for testing.  This context uses a simple {@link Map} to track bindings.
+ * Names must start with a given prefix string or they cause {@link
+ * InvalidNameException}s.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1 $
+ */
+class TestContext implements Context {
+	/**
+	 * Creates a new <code>TestContext</code> instance.
+	 *
+	 * @param prefix What every name must start with.
+	 */
+	public TestContext(String prefix) {
+		this.prefix = prefix;
+	}
+
+	public Object lookup(Name name) throws NamingException {
+		return lookup(name.toString());
+	}
+	public Object lookup(String name) throws NamingException {
+		Object rc = bindings.get(name);
+		if (rc == null)
+			throw new NameNotFoundException(name);
+		return rc;
+	}
+	public void bind(Name name, Object obj) throws NamingException {
+		bind(name.toString(), obj);
+	}
+	public void bind(String name, Object obj) throws NamingException {
+		if (!name.startsWith(prefix)) throw new InvalidNameException("Name doesn't start with " + prefix);
+		if (bindings.containsKey(name))
+			throw new NameAlreadyBoundException(name);
+		bindings.put(name, obj);
+	}
+	public void rebind(Name name, Object obj) throws NamingException {
+		rebind(name.toString(), obj);
+	}
+	public void rebind(String name, Object obj) throws NamingException {
+		if (!name.startsWith(prefix)) throw new InvalidNameException("Name doesn't start with " + prefix);
+		bindings.put(name, obj);
+	}
+	public void unbind(Name name) throws NamingException {
+		unbind(name.toString());
+	}
+	public void unbind(String name) throws NamingException {
+		if (bindings.remove(name) == null)
+			throw new NameNotFoundException(name);
+	}
+	public void rename(Name oldName, Name newName) throws NamingException {
+		rename(oldName.toString(), newName.toString());
+	}
+	public void rename(String oldName, String newName) throws NamingException {
+		if (!bindings.containsKey(oldName))
+			throw new NameNotFoundException(oldName);
+		if (bindings.containsKey(newName))
+			throw new NameAlreadyBoundException(newName);
+		if (!newName.startsWith(prefix))
+			throw new InvalidNameException("Name doesn't start with " + prefix);
+		bindings.put(newName, bindings.remove(oldName));
+	}
+	public NamingEnumeration list(Name name) throws NamingException {
+		return list(name.toString());
+	}
+	public NamingEnumeration list(String name) throws NamingException {
+		if (name.length() > 0)
+			throw new OperationNotSupportedException("subcontexts not supported");
+		final Iterator i = bindings.entrySet().iterator();
+		return new NamingEnumeration() {
+			public Object next() {
+				Map.Entry e = (Map.Entry) i.next();
+				return new NameClassPair((String) e.getKey(), e.getValue().getClass().getName());
+			}
+			public boolean hasMore() {
+				return i.hasNext();
+			}
+			public void close() {}
+			public boolean hasMoreElements() {
+				return hasMore();
+			}
+			public Object nextElement() {
+				return next();
+			}
+		};
+	}
+	public NamingEnumeration listBindings(Name name) throws NamingException {
+		return listBindings(name.toString());
+	}
+	public NamingEnumeration listBindings(String name) throws NamingException {
+		if (name.length() > 0)
+			throw new OperationNotSupportedException("subcontexts not supported");
+		final Iterator i = bindings.entrySet().iterator();
+		return new NamingEnumeration() {
+			public Object next() {
+				Map.Entry e = (Map.Entry) i.next();
+				return new Binding((String) e.getKey(), e.getValue());
+			}
+			public boolean hasMore() {
+				return i.hasNext();
+			}
+			public void close() {}
+			public boolean hasMoreElements() {
+				return hasMore();
+			}
+			public Object nextElement() {
+				return next();
+			}
+
+		};
+	}
+	public void destroySubcontext(Name name) throws NamingException {
+		destroySubcontext(name.toString());
+	}
+	public void destroySubcontext(String name) throws NamingException {
+		throw new OperationNotSupportedException("subcontexts not supported");
+	}
+	public Context createSubcontext(Name name) throws NamingException {
+		return createSubcontext(name.toString());
+	}
+	public Context createSubcontext(String name) throws NamingException {
+		throw new OperationNotSupportedException("subcontexts not supported");
+	}
+	public Object lookupLink(Name name) throws NamingException {
+		return lookupLink(name.toString());
+	}
+	public Object lookupLink(String name) throws NamingException {
+		return lookup(name);
+	}
+	public NameParser getNameParser(Name name) {
+		return getNameParser(name.toString());
+	}
+	public NameParser getNameParser(String name) {
+		return new ObjectNameParser();
+	}
+	public String composeName(String name, String prefix) throws NamingException {
+		return composeName(new CompositeName(name), new CompositeName(prefix)).toString();
+	}
+	public Name composeName(Name name, Name prefix) throws NamingException {
+		Name result = (Name) prefix.clone();
+		result.addAll(name);
+		return result;
+	}
+	public Object addToEnvironment(String key, Object val) {
+		if (environment == null) environment = new Hashtable();
+		return environment.put(key, val);
+	}
+	public Object removeFromEnvironment(String key) {
+		if (environment == null) environment = new Hashtable();
+		return environment.remove(key);
+	}
+	public Hashtable getEnvironment() {
+		if (environment == null) environment = new Hashtable();
+		return environment;
+	}
+	public void close() {}
+	public String getNameInNamespace() {
+		return "";
+	}
+
+	/** What holds the bindings.  Keys are {@link String}s, values are {@link Object}s. */
+	Map bindings = new HashMap();
+
+	/** What every key must start with. */
+	private String prefix;
+
+	/** Context's environment. */
+	private Hashtable environment;
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/object/jndi/TestContextTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/object/jndi/TestContextTest.java
new file mode 100644
index 0000000..acf195f
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/object/jndi/TestContextTest.java
@@ -0,0 +1,96 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.object.jndi;
+
+import javax.naming.Binding;
+import javax.naming.InvalidNameException;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameClassPair;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for the test context.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1 $
+ */
+public class TestContextTest extends TestCase {
+	/**
+	 * Creates a new <code>TestContextTest</code> instance.
+	 *
+	 * @param caseName a <code>String</code> value.
+	 */
+	public TestContextTest(String caseName) {
+		super(caseName);
+	}
+
+	/**
+	 * Test various aspects of the test context.
+	 *
+	 * @throws NamingException if an error occurs.
+	 */
+	public void testTestContext() throws NamingException {
+		TestContext ctx = new TestContext("urn:x:");			       // Make it
+		try {
+			ctx.lookup("urn:x:y");					       // Lookup a nonexistent binding
+			fail("Got a binding that doesn't exist");		       // Got something?  Yikes.
+		} catch (NameNotFoundException ex) {}
+
+		try {
+			ctx.bind("urn:y:z", this);				       // Bind an invalid prefix
+			fail("Bound an invalid prefix");			       // Worked?  Dang.
+		} catch (InvalidNameException ex) {}
+
+		ctx.bind("urn:x:a", this);					       // Bind something.
+		assertSame(this, ctx.lookup("urn:x:a"));			       // Look it up
+
+		try {
+			ctx.bind("urn:x:a", getClass());			       // Bind it again
+			fail("Able to re-bind");				       // Worked?  Crap.
+		} catch (NameAlreadyBoundException ex) {}
+
+		ctx.rebind("urn:x:a", getClass());				       // Rebind it again
+		assertSame(getClass(), ctx.lookup("urn:x:a"));			       // Look it up
+
+		ctx.rename("urn:x:a", "urn:x:b");				       // Rename the binding
+		assertSame(getClass(), ctx.lookup("urn:x:b"));			       // Look it up
+
+		NamingEnumeration e = ctx.list("");				       // List the context
+		assertTrue(e.hasMore());					       // Got something?  Good.
+		NameClassPair p = (NameClassPair) e.next();			       // Get it
+		assertEquals("urn:x:b", p.getName());				       // Right name?  Good.
+		assertEquals("java.lang.Class", p.getClassName());		       // Right class?  Good.
+		assertTrue(!e.hasMore());					       // Got no more?  Good.
+
+		e = ctx.listBindings("");					       // List the bindings
+		assertTrue(e.hasMore());					       // Got something?  Good.
+		Binding b = (Binding) e.next();					       // Get it
+		assertEquals("urn:x:b", p.getName());				       // Right name?  Good.
+		assertSame(getClass(), b.getObject());				       // Right object?  Good.
+		assertTrue(!e.hasMore());					       // Got no more?  Good.
+
+		assertSame(getClass(), ctx.lookupLink("urn:x:b"));		       // Look up via the link
+
+		ctx.unbind("urn:x:b");						       // Unbind it
+		e = ctx.list("");						       // List the context
+		assertTrue(!e.hasMore());					       // Got no more?  Good.
+		e = ctx.listBindings("");					       // List the bindings
+		assertTrue(!e.hasMore());					       // Got no more?  Good.
+	}
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/Base64Test.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/Base64Test.java
new file mode 100644
index 0000000..9554b66
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/Base64Test.java
@@ -0,0 +1,40 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import java.util.*;
+import junit.framework.*;
+
+/** Unit test the {@link Base64} class.
+ *
+ * @author Kelly
+ */ 
+public class Base64Test extends TestCase {
+	/** Construct the test case for the {@link Base64} class. */
+	public Base64Test(String name) {
+		super(name);
+	}
+
+	/** Test encoding and decoding.
+	 */
+	public void testEncDec() {
+		byte[] a = Base64.encode("abcde".getBytes());
+		assertTrue("Base-64 encoding failed", Arrays.equals("YWJjZGU=".getBytes(), a));
+		byte[] b = Base64.decode("YWJjZGU=".getBytes());
+		assertTrue("Base-64 decoding failed", Arrays.equals("abcde".getBytes(), b));
+	}
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/CacheMapTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/CacheMapTest.java
new file mode 100644
index 0000000..a7c82e6
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/CacheMapTest.java
@@ -0,0 +1,112 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import java.util.*;
+import junit.framework.*;
+
+/** Unit test the {@link CacheMap} class.
+ *
+ * @author Kelly
+ */ 
+public class CacheMapTest extends TestCase {
+	/** Construct the test case for the {@link CacheMap} class. */
+	public CacheMapTest(String name) {
+		super(name);
+	}
+
+	/** Test the caching operation. */
+	public void testCache() {
+		CacheMap c = new CacheMap(3);
+		c.put("alpha", "1");
+		c.put("beta", "2");
+		c.put("gamma", "3");
+		// gamma beta alpha
+		assertEquals("2", c.get("beta"));
+		// beta gamma alpha
+		c.put("delta", "4");
+		// delta beta gamma
+		assertNull(c.get("alpha"));
+	}
+
+	/** Test the {@link CacheMap#size} and {@link CacheMap#isEmpty} methods. */
+	public void testSize() {
+		CacheMap c = new CacheMap(3);
+		assertEquals(0, c.size());
+		assertTrue(c.isEmpty());
+		c.put("alpha", "1");
+		// alpha
+		assertEquals(1, c.size());
+		c.put("beta", "2");
+		// beta alpha
+		assertEquals(2, c.size());
+		c.put("gamma", "3");
+		// gamma beta alpha
+		assertEquals(3, c.size());
+		c.put("delta", "4");
+		// delta gamma beta
+		assertEquals(3, c.size());
+		c.clear();
+		assertTrue(c.isEmpty());
+	}
+
+	/** Test the {@link CacheMap#containsKey} and {@link CacheMap#containsValue} methods. */
+	public void testContains() {
+		CacheMap c = new CacheMap(3);
+		c.put("alpha", "1");
+		c.put("beta", "2");
+		c.put("gamma", "3");
+
+		assertTrue(c.containsKey("alpha"));
+		assertTrue(!c.containsKey("hungus"));
+		assertTrue(c.containsValue("2"));
+		assertTrue(!c.containsValue("x"));
+	}
+
+	/** Test value replacement for the same key. */
+	public void testRePut() {
+		CacheMap c = new CacheMap(3);
+		c.put("alpha", "1");
+		c.put("beta", "2");
+		c.put("gamma", "3");
+		// (gamma, 3) (beta, 2) (alpha, 1)
+		c.put("alpha", "x");
+		// (alpha, x), (gamma, 3) (beta, 2)
+		assertEquals("x", c.get("alpha"));
+		// (alpha, x), (gamma, 3) (beta, 2)
+		c.put("delta", "y");
+		// (delta, y) (alpha, x), (gamma, 3)
+		assertEquals(3, c.size());
+		assertNull(c.get("beta"));
+	}
+
+	/** Test the {@link CacheMap#remove} method. */
+	public void testRemove() {
+		CacheMap c = new CacheMap(3);
+		c.put("alpha", "1");
+		c.put("beta", "2");
+		c.put("gamma", "3");
+		// gamma beta alpha
+		c.put("delta", "4");
+		// delta gamma beta
+		assertEquals("3", c.remove("gamma"));
+		// delta beta
+		assertNull(c.remove("gamma"));
+		assertNull(c.remove("alpha"));
+	}
+}
+
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/EnterpriseEntityResolverTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/EnterpriseEntityResolverTest.java
new file mode 100644
index 0000000..950fdcf
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/EnterpriseEntityResolverTest.java
@@ -0,0 +1,121 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+import junit.framework.TestCase;
+
+/**
+ * Unit test the EnterpriseEntityResolver class.
+ *
+ * @author Kelly
+ */ 
+public class EnterpriseEntityResolverTest extends TestCase {
+	/** Construct the test case for the XML class.
+	 *
+	 * @param name Case name
+	 */
+	public EnterpriseEntityResolverTest(String name) {
+		super(name);
+	}
+
+	/**
+	 * Create a temporary directory with a temporary file as the test entity.
+	 *
+	 * @throws Exception if an error occurs.
+	 */
+	public void setUp() throws Exception {
+		super.setUp();
+		testDir = File.createTempFile("eet", ".dir");
+		testDir.delete();
+		testDir.mkdir();
+		testFile = new File(testDir, "test-entry-do-not-remove.dtd");
+		if (!testFile.createNewFile())
+			throw new Exception(testFile + " already exists, but shouldn't");
+	}
+
+	/**
+	 * Delete the temporary file entity and test directory.
+	 *
+	 * @throws Exception if an error occurs.
+	 */
+	public void tearDown() throws Exception{
+		testFile.delete();
+		testDir.delete();
+		super.tearDown();
+	}
+
+	/**
+	 * Test if the entity parser works at initialization time.
+	 */
+	public void testEntityParsing() {
+		assertEquals("test-entry-do-not-remove.dtd",
+			EnterpriseEntityResolver.entities.get("-//JPL//DTD TEST ENTRY DO NOT REMOVE//EN"));
+	}
+
+	/**
+	 * Test if the resolver computes filenames based on public and system identifiers.
+	 */
+	public void testFilenameComputation() {
+		assertNull(EnterpriseEntityResolver.computeFilename(null, null));
+		assertNull(EnterpriseEntityResolver.computeFilename(null, "unknown"));
+		assertNull(EnterpriseEntityResolver.computeFilename("unknown", null));
+		assertNull(EnterpriseEntityResolver.computeFilename("unknown", "unknown"));
+
+		assertEquals("test-entry-do-not-remove.dtd",
+			EnterpriseEntityResolver.computeFilename("-//JPL//DTD TEST ENTRY DO NOT REMOVE//EN", null));
+		assertEquals("test-entry-do-not-remove.dtd",
+			EnterpriseEntityResolver.computeFilename(null, "http://oodt.jpl.nasa.gov/test-entry-do-not-remove.dtd"));
+		assertEquals("test-entry-do-not-remove.dtd",
+			EnterpriseEntityResolver.computeFilename("-//JPL//DTD TEST ENTRY DO NOT REMOVE//EN",
+				"illegal-url:test-entry-do-not-remove.dtd"));
+		assertEquals("test-entry-do-not-remove.dtd",
+			EnterpriseEntityResolver.computeFilename("illegal-FPI",
+				"http://oodt.jpl.nasa.gov/test-entry-do-not-remove.dtd"));
+		assertEquals("test-entry-do-not-remove.dtd",
+			EnterpriseEntityResolver.computeFilename("-//JPL//DTD TEST ENTRY DO NOT REMOVE//EN",
+				"http://oodt.jpl.nasa.gov/test-entry-do-not-remove.dtd"));
+	}
+
+	/**
+	 * Test if the resolver finds a file based on a list of directories and name.
+	 */
+	public void testFileFinding() {
+		List dirs = Collections.singletonList(testDir.toString());
+		assertEquals(testFile, EnterpriseEntityResolver.findFile(dirs, testFile.getName()));
+	}
+
+	/**
+	 * Test if the resolver can convert a string specification of entity references
+	 * into a {@link List}.
+	 */
+	public void testDirFinding() {
+		List dirs = EnterpriseEntityResolver.getEntityRefDirs("");
+		assertTrue(dirs.isEmpty());
+		dirs = EnterpriseEntityResolver.getEntityRefDirs("/tmp,/usr/local/xml");
+		assertEquals(2, dirs.size());
+		assertEquals("/tmp", dirs.get(0));
+		assertEquals("/usr/local/xml", dirs.get(1));
+	}
+
+	/** Test directory to hold <var>testFile</var>, the test entity. */
+	private File testDir;
+
+	/** The test entity. */
+	private File testFile;
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/LDAPTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/LDAPTest.java
new file mode 100644
index 0000000..9874643
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/LDAPTest.java
@@ -0,0 +1,39 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import java.util.*;
+import junit.framework.*;
+
+/** Unit test the {@link LDAP} class.
+ *
+ * @author Kelly
+ */ 
+public class LDAPTest extends TestCase {
+	/** Construct the test case for the {@link LDAP} class. */
+	public LDAPTest(String name) {
+		super(name);
+	}
+
+	/** Test the {@link LDAP#toLDAPString} method. */
+	public void testToLDAPString() {
+		String str = "Hello (World), \\How are you*?";
+		String result = LDAP.toLDAPString(str);
+		assertEquals("Hello \\28World\\29, \\5cHow are you\\2a?", result);
+	}
+}
+
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/UtilityTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/UtilityTest.java
new file mode 100644
index 0000000..ec1aa47
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/UtilityTest.java
@@ -0,0 +1,45 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.File;
+import java.io.IOException;
+import junit.framework.TestCase;
+
+public class UtilityTest extends TestCase {
+	public UtilityTest(String caseName) {
+		super(caseName);
+	}
+
+	public void testDelete() throws IOException {
+		File top = File.createTempFile("topdir", ".dir");
+		top.delete();
+		top.mkdir();
+		File f1 = File.createTempFile("nesteddir", ".file", top);
+		File f2 = File.createTempFile("nesteddir", ".file", top);
+		File d1 = File.createTempFile("nesteddir", ".dir", top);
+		d1.delete();
+		d1.mkdir();
+		File f3 = File.createTempFile("nesteddir", ".file", d1);
+		File d2 = File.createTempFile("nesteddir", ".dir", d1);
+		d2.delete();
+		d2.mkdir();
+		File f4 = File.createTempFile("nesteddir", ".file", d2);
+
+		assertTrue(Utility.delete(top));
+		assertTrue(!top.exists());
+	}
+}
diff --git a/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/XMLTest.java b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/XMLTest.java
new file mode 100644
index 0000000..d1954b5
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/java/org/apache/oodt/commons/util/XMLTest.java
@@ -0,0 +1,179 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import java.util.*;
+import junit.framework.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** Unit test the XML class.
+ *
+ * @author Kelly
+ */ 
+public class XMLTest extends TestCase {
+	/** Construct the test case for the XML class. */
+	public XMLTest(String name) {
+		super(name);
+	}
+
+	protected void setUp() throws Exception {
+		reader = new BufferedReader(new InputStreamReader(XMLTest.class.getResourceAsStream("/test.xml")));
+		inputSource = new InputSource(reader);
+	}
+
+	protected void tearDown() throws Exception {
+		reader.close();
+	}
+
+	/** Test the {@link XML#createDocument} method.
+	 */
+	public void testDocumentCreation() {
+		Document doc = XML.createDocument();
+		assertTrue(doc instanceof Document);
+	}
+
+	/** Test the {@link XML#createDOMParser} and {@link XML#serialize} methods.
+	 */
+	public void testDOM() throws Exception {
+		DOMParser p = XML.createDOMParser();
+		p.parse(inputSource);
+		Document doc = p.getDocument();
+		doc.normalize();
+		assertEquals("log", doc.getDocumentElement().getTagName());
+		java.util.zip.CRC32 crc = new java.util.zip.CRC32();
+		String result = XML.serialize(doc);
+		crc.update(result.getBytes());
+		long value = crc.getValue();
+		assertTrue("Stringified DOM document CRC mismatch, got value = " + value, 3880488030L == value || 2435419114L == value || /* added by Chris Mattmann: pretty print fix */3688328384L == value || /* other newline treatment */ 750262163L == value || 3738296466L == value /* Apache incubator warmed up the file, so it suffered thermal expansion */);
+	}
+
+	/** Test the {@link XML#createSAXParser} method.
+	 */
+	public void testSAXParser() throws Exception {
+		SAXParser p = XML.createSAXParser();
+		MyHandler handler = new MyHandler();
+		p.setContentHandler(handler);
+		p.parse(inputSource);
+		// 25 refers to the 25 elements in the test.xml document.
+		assertEquals(25, handler.getElementCount());
+	}
+
+	/** Test the {@link XML#dump(PrintWriter,Node)} method. */
+	public void testDump() throws Exception {
+		DOMParser p = XML.createDOMParser();
+		p.parse(inputSource);
+		Document doc = p.getDocument();
+		StringWriter stringWriter = new StringWriter();
+		PrintWriter printWriter = new PrintWriter(stringWriter);
+		XML.dump(printWriter, doc);
+		printWriter.close();
+		java.util.zip.CRC32 crc = new java.util.zip.CRC32();
+		crc.update(stringWriter.getBuffer().toString().getBytes());
+		long value = crc.getValue();
+		assertTrue("Dumped DOM tree CRC mismatch; got " + value, value == 828793L || value == 2241317601L);
+	}
+
+	/** Test the {@link XML#unwrappedText} method. */
+	public void testUnwrappedText() throws Exception {
+		DOMParser p = XML.createDOMParser();
+		p.parse(inputSource);
+		Document doc = p.getDocument();
+		doc.normalize();
+
+		Node node = doc.getDocumentElement().getFirstChild().getFirstChild().getNextSibling()
+			.getNextSibling().getFirstChild().getNextSibling().getNextSibling().getNextSibling().getNextSibling();
+		assertEquals("Geeba, geeba.  Geeba geeba geeba!  Geeba, geeba, blooor? Bloorien bloreinda!",
+			XML.unwrappedText(node));
+		assertNull(XML.unwrappedText(null));
+	}
+
+	/** Test the {@link XML#add(Node,String,String)} method. */
+	public void testAddString() throws Exception {
+		Document doc = XML.createDocument();
+		Element root = doc.createElement("root");
+		doc.appendChild(root);
+		XML.add(root, "child", "child text");
+		assertEquals("child", root.getFirstChild().getNodeName());
+		assertEquals("child text", root.getFirstChild().getFirstChild().getNodeValue());
+		NodeList children = root.getChildNodes();
+		assertEquals(1, children.getLength());
+		try {
+			XML.add(null, "child", "child text");
+		} catch (IllegalArgumentException ex) {
+			return;
+		}
+		fail("Adding to a null node should fail by throwing IllegalArgumentException");
+	}
+
+	/** Test the {@link XML#add(Node,String,Object)} method. */
+	public void testAddObject() throws Exception {
+		Object obj = new Object() {
+			public String toString() {
+				return "child text";
+			}
+		};
+		Document doc = XML.createDocument();
+		Element root = doc.createElement("root");
+		doc.appendChild(root);
+		XML.add(root, "child", obj);
+		assertEquals("child", root.getFirstChild().getNodeName());
+		assertEquals("child text", root.getFirstChild().getFirstChild().getNodeValue());
+		NodeList children = root.getChildNodes();
+		assertEquals(1, children.getLength());
+		try {
+			XML.add(null, "child", obj);
+		} catch (IllegalArgumentException ex) {
+			return;
+		}
+		fail("Adding to a null node should fail by throwing IllegalArgumentException");
+	}
+	
+	/** Test the {@link XML#escape} method. */
+	public void testEscape() {
+		assertEquals("", XML.escape(""));
+		assertEquals("So I said, &quot;She said, &apos;Both 3 &amp; 2 are &lt; 5 but &gt; 0&apos; but he said &#43981;",
+			XML.escape("So I said, \"She said, 'Both 3 & 2 are < 5 but > 0' but he said \uabcd"));
+	}
+
+
+	/** Test the {@link XML#getDOMImplementation} method. */
+	public void testGetDOMImplementation() {
+		DOMImplementation impl = XML.getDOMImplementation();
+		assertNotNull(impl);
+		DOMImplementation impl2 = XML.getDOMImplementation();
+		assertSame(impl, impl2);
+	}
+
+	/** Used by {@link #testSAXParser} */
+	private static class MyHandler extends org.xml.sax.helpers.DefaultHandler {
+		private int elementCount = 0;
+		public void endElement(String uri, String localName, String rawName) {
+			++elementCount;
+		}
+		public int getElementCount() {
+			return elementCount;
+		}
+	}
+
+	/** Reader for the test data file. */
+	private BufferedReader reader;
+
+	/** Input source for the {@link #reader}. */
+	private InputSource inputSource;
+}
+
diff --git a/0.8.1-rc1/commons/src/test/resources/test-multiserver.xml b/0.8.1-rc1/commons/src/test/resources/test-multiserver.xml
new file mode 100644
index 0000000..43a35bc
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/resources/test-multiserver.xml
@@ -0,0 +1,27 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<multiserver xmlns="http://oodt.jpl.nasa.gov/edm-commons/xml/multiserver" id="test.app">
+  <server class="org.apache.oodt.commons.MultiServerTest$Svr1" id="urn:eda:rmi:Test1" bind="true"   />
+  <server class="org.apache.oodt.commons.MultiServerTest$Svr2" id="urn:eda:rmi:Test2" bind="false"  />
+  <server class="org.apache.oodt.commons.MultiServerTest$Svr3" id="urn:eda:rmi:Test3" bind="rebind" />
+  <server class="org.apache.oodt.commons.MultiServerTest$Svr4" id="urn:eda:rmi:Test4" bind="360000" />
+  <properties>
+    <property name="my.setting">My Value</property>
+    <property name="my.other.setting">My Other Value</property>
+  </properties>
+</multiserver>
diff --git a/0.8.1-rc1/commons/src/test/resources/test.xml b/0.8.1-rc1/commons/src/test/resources/test.xml
new file mode 100755
index 0000000..119a8ab
--- /dev/null
+++ b/0.8.1-rc1/commons/src/test/resources/test.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log [
+<!ELEMENT log (stream*)>
+<!ELEMENT stream (streamID, analyst, message*)>
+<!ELEMENT streamID (#PCDATA)>
+<!ELEMENT analyst (#PCDATA)>
+<!ELEMENT message (server, host, time, code, text)>
+<!ELEMENT server (#PCDATA)>
+<!ELEMENT host (#PCDATA)>
+<!ELEMENT time (#PCDATA)>
+<!ELEMENT code (#PCDATA)>
+<!ELEMENT text (#PCDATA)>
+]>
+<log>
+  <stream>
+    <streamID>3</streamID>
+    <analyst>hyon</analyst>
+
+    <message>
+      <server>TDS</server>
+      <host>latte</host>
+      <time>1352</time>
+      <code>121</code>
+      <text>Geeba, geeba.  Geeba geeba geeba!  Geeba, geeba, blooor?
+        Bloorien bloreinda!
+      </text>
+    </message>
+
+    <message>
+      <server>Instrument</server>
+      <host>sorrento</host>
+      <time>1353</time>
+      <code>211</code>
+      <text>Geeba, bloor.</text>
+    </message>
+
+  </stream>
+
+
+  <stream>
+    <streamID>4</streamID>
+    <analyst>kelly</analyst>
+
+    <message>
+      <server>Analyst</server>
+      <host>killamanjaro</host>
+      <time>1354</time>
+      <code>212</code>
+      <text>Wahoo</text>
+    </message>
+  </stream>
+</log>
diff --git a/0.8.1-rc1/core/pom.xml b/0.8.1-rc1/core/pom.xml
new file mode 100644
index 0000000..6ef1baf
--- /dev/null
+++ b/0.8.1-rc1/core/pom.xml
@@ -0,0 +1,486 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+	<parent>
+	  <groupId>org.apache</groupId>
+	  <artifactId>apache</artifactId>
+	  <version>16</version>
+	  <relativePath />
+	</parent>    
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <name>OODT Core</name>
+    <packaging>pom</packaging>
+    <properties>
+        <organizationLogo>http://www.apache.org/images/feather.gif</organizationLogo>
+        <logo>/images/${project.artifactId}.jpg</logo>
+        <xdocVersion>${project.version}</xdocVersion>
+        <genDownloadLinks>false</genDownloadLinks>
+        <docsSrc>${basedir}/src/site/xdoc</docsSrc>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+    </properties>
+    <url>http://oodt.apache.org/</url>
+    <issueManagement>
+        <system>JIRA</system>
+        <url>https://issues.apache.org/jira/browse/OODT</url>
+    </issueManagement>
+    <inceptionYear>1999</inceptionYear>
+    <mailingLists>
+        <mailingList>
+              <name>dev</name>
+              <subscribe>dev-subscribe@oodt.apache.org</subscribe>
+              <unsubscribe>dev-unsubscribe@oodt.apache.org</unsubscribe>
+              <post>dev@oodt.apache.org</post>
+              <archive>http://mail-archives.apache.org/mod_mbox/oodt-dev/</archive>
+        </mailingList>
+        <mailingList>
+              <name>commits</name>
+              <subscribe>commits-subscribe@oodt.apache.org</subscribe>
+              <unsubscribe>commits-unsubscribe@oodt.apache.org</unsubscribe>
+              <archive>http://mail-archives.apache.org/mod_mbox/oodt-commits/</archive>
+        </mailingList>
+        <mailingList>
+              <name>private</name>
+              <subscribe>private-subscribe@oodt.apache.org</subscribe>
+              <unsubscribe>private-unsubscribe@oodt.apache.org</unsubscribe>
+              <post>private@oodt.apache.org</post>
+        </mailingList>
+    </mailingLists>
+    <developers>
+        <developer>
+            <id>thomas</id>
+            <name>Thomas Bennett</name>
+            <email>thomas@apache.org</email>
+            <organization>SKA South Africa</organization>
+            <timezone>+2</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>    
+        <developer>
+            <id>crichton</id>
+            <name>Daniel Crichton</name>
+            <email>crichton@apache.org</email>
+            <organization>NASA Jet Propulsion Laboratory</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>
+        <developer>
+            <id>bfoster</id>
+            <name>Brian Foster</name>
+            <email>bfoster@apache.org</email>
+            <organization>Google</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>     
+        <developer>
+            <id>joshuaga</id>
+            <name>Joshua Garcia</name>
+            <email>joshuaga@apache.org</email>
+            <organization>University of Southern California</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>           
+        <developer>
+            <id>goodale</id>
+            <name>Cameron Goodale</name>
+            <email>goodale@apache.org</email>
+            <organization>NASA Jet Propulsion Laboratory</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+            <properties>
+                <aim>nonflyt</aim>
+                <gtalk>sigep311@gmail.com</gtalk>
+            </properties>
+        </developer>
+        <developer>
+            <id>shardman</id>
+            <name>Sean Hardman</name>
+            <email>shardman@apache.org</email>
+            <organization>NASA Jet Propulsion Laboratory</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>        
+        <developer>
+            <id>ahart</id>
+            <name>Andrew Hart</name>
+            <email>ahart@apache.org</email>
+            <organization>NASA Jet Propulsion Laboratory</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>  
+        <developer>
+            <id>davekale</id>
+            <name>Dave Kale</name>
+            <email>davekale@apache.org</email>
+            <organization>Childrens Hospital Los Angeles</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>              
+        <developer>
+            <id>kelly</id>
+            <name>Sean Kelly</name>
+            <email>kelly@apache.org</email>
+            <url>http://seankelly.biz/</url>
+            <organization>Independent Consultant</organization>
+            <roles>
+                <role>committer</role>
+                <role>technologist</role>
+            </roles>
+            <timezone>-6</timezone>
+            <properties>
+                <picUrl>http://seankelly.biz/Members/kelly/sean-kelly/image</picUrl>
+                <blogUrl>http://seankelly.biz/blog</blogUrl>
+                <foaf>http://seankelly.biz/Members/kelly/sean-kellys-foaf</foaf>
+                <aim>InsanityPoet</aim>
+                <skype>InsanityPoet</skype>
+                <gtalk>sean.c.kelly@gmail.com</gtalk>
+                <mobileme>sean.c.kelly@me.com</mobileme>
+            </properties>
+        </developer>
+        <developer>
+            <id>mattmann</id>
+            <name>Chris Mattmann</name>
+            <email>Chris.Mattmann@jpl.nasa.gov</email>
+            <url>http://www-scf.usc.edu/~mattmann/</url>
+            <organization>NASA Jet Propulsion Laboratory</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+                <role>mentor</role>
+                <role>release engineer</role>
+            </roles>
+        </developer>
+        <developer>
+            <id>pramirez</id>
+            <name>Paul Ramirez</name>
+            <email>pramirez@apache.org</email>
+            <organization>NASA Jet Propulsion Laboratory</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>
+        <developer>
+            <id>smcclees</id>
+            <name>Sean McCleese</name>
+            <email>smcclees@apache.org</email>
+            <organization>NASA Jet Propulsion Laboratory</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>
+        <developer>
+            <id>gabe</id>
+            <name>Gabe Resneck</name>
+            <email>gabriel.m.resneck@jpl.nasa.gov</email>
+            <organization>NASA Jet Propulsion Laboratory</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>        
+        <developer>
+            <id>pvee</id>
+            <name>Paul Vee</name>
+            <email>pvee@apache.org</email>
+            <organization>Childrens Hospital Los Angeles</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>
+        <developer>
+            <id>riverma</id>
+            <name>Rishi Verma</name>
+            <email>riverma@apache.org</email>
+            <organization>NASA Jet Propulsion Laboratory</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>
+        <developer>
+            <id>woollard</id>
+            <name>David Woollard</name>
+            <email>woollard@apache.org</email>
+            <organization>Project WBS</organization>
+            <timezone>-8</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>
+        <developer>
+            <id>siriwardana</id>
+            <name>Rajith Siriwardana</name>
+            <email>siriwardana@apache.org</email>
+            <organization>Independent Consultant</organization>
+            <timezone>+5:30</timezone>
+            <roles>
+                <role>committer</role>
+            </roles>
+        </developer>
+    </developers>
+    <licenses>
+        <license>
+            <name>Apache 2</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <comments>The standard OSI-approved Apache license, friendly to commercial interests yet open.</comments>
+            <distribution>manual</distribution>
+        </license>
+    </licenses>
+    <organization>
+        <name>Apache OODT</name>
+        <url>http://oodt.apache.org/</url>
+    </organization>
+    <scm>
+    	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/core</connection>
+    	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/core</developerConnection>
+    	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/core</url>
+    </scm>
+    <build>
+        <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
+        <testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
+        <plugins>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.6</source>
+                    <target>1.6</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <index>true</index>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-eclipse-plugin</artifactId>
+                <version>2.6</version>
+            </plugin>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <includes>
+                        <include>**/*Test*.java</include>
+                    </includes>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>2.9</version>
+                <configuration>
+                    <outputEncoding>UTF-8</outputEncoding>
+                    <charset>UTF-8</charset>
+                    <docencoding>UTF-8</docencoding>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>attach-javadocs</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>javadoc</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>net.alchim31.maven</groupId>
+                <artifactId>scala-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>compile</id>
+                        <goals>
+                            <goal>compile</goal>
+                        </goals>
+                        <phase>compile</phase>
+                    </execution>
+                    <execution>
+                        <id>test-compile</id>
+                            <goals>
+                                <goal>testCompile</goal>
+                            </goals>
+                        <phase>test-compile</phase>
+                    </execution>
+                    <execution>
+                        <phase>process-resources</phase>
+                        <goals>
+                            <goal>compile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>net.alchim31.maven</groupId>
+                <artifactId>scala-maven-plugin</artifactId>
+                <version>3.2.0</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.tika</groupId>
+                <artifactId>tika-core</artifactId>
+                <version>1.7</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.tika</groupId>
+                <artifactId>tika-parsers</artifactId>
+                <version>1.7</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-io</groupId>
+                <artifactId>commons-io</artifactId>
+                <version>1.4</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+    <profiles>
+        <profile>
+            <id>audit</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>rat-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>check</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>    
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+    <reporting>
+        <plugins>
+            <!-- FIXME: currently produces a NullPointerException
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-changes-plugin</artifactId>
+                <version>2.0</version>
+                <configuration>
+                    <component>12311070</component>
+                    <resolutionIds>1</resolutionIds>
+                    <statusIds>5,6</statusIds>
+                    <fixVersionIds>${jira.fix.version.ids}</fixVersionIds>
+                </configuration>
+                <reportSets>
+                    <reportSet>
+                        <reports>
+                            <report>jira-report</report>
+                        </reports>
+                    </reportSet>
+                </reportSets>
+            </plugin> -->
+            <!-- Produce JavaDoc -->
+            <plugin>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>2.9</version>
+                <configuration>
+                    <outputEncoding>UTF-8</outputEncoding>
+                    <charset>UTF-8</charset>
+                    <docencoding>UTF-8</docencoding>
+                    <encoding>UTF-8</encoding>
+                    <aggregate>true</aggregate>
+                    <source>1.5</source>
+                </configuration>
+            </plugin>
+            <!-- Produce Source cross references -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jxr-plugin</artifactId>
+                <version>2.1</version>
+                <configuration>
+                    <aggregate>true</aggregate>
+                </configuration>
+            </plugin>
+            <!-- Unit tests report -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-report-plugin</artifactId>
+                <version>2.3</version>
+            </plugin>
+            <!-- "Release Audit" report (checks license headers etc.) -->
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>rat-maven-plugin</artifactId>
+                <version>1.0-alpha-3</version>
+            </plugin>
+            <!-- FindBugs Report -->
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>findbugs-maven-plugin</artifactId>
+                <version>2.3</version>
+                <configuration>
+                    <threshold>Normal</threshold>
+                    <effort>Default</effort>
+                </configuration>
+            </plugin>
+            <!-- Checkstyle report -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <version>2.1</version>
+                <configuration>
+                    <!--configLocation>checkstyle.xml</configLocation-->
+                    <enableRulesSummary>false</enableRulesSummary>
+                </configuration>
+            </plugin>
+            <!-- Project website generation -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-site-plugin</artifactId>
+                <version>2.0-beta-7</version>
+                <configuration>
+                    <outputEncoding>UTF-8</outputEncoding>
+                </configuration>
+            </plugin>
+        </plugins>
+    </reporting>
+</project>
diff --git a/0.8.1-rc1/core/src/site/site.xml b/0.8.1-rc1/core/src/site/site.xml
new file mode 100644
index 0000000..d934fbd
--- /dev/null
+++ b/0.8.1-rc1/core/src/site/site.xml
@@ -0,0 +1,23 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<project>
+    <publishDate position='left' format='dd-MMM-yyyy'/>
+    <body>
+        <menu ref='reports'/>
+    </body>
+</project>
diff --git a/0.8.1-rc1/crawler/pom.xml b/0.8.1-rc1/crawler/pom.xml
new file mode 100644
index 0000000..d815bd5
--- /dev/null
+++ b/0.8.1-rc1/crawler/pom.xml
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+	<parent>
+		<groupId>org.apache.oodt</groupId>
+		<artifactId>oodt-core</artifactId>
+		<version>0.8.1</version>
+		<relativePath>../core/pom.xml</relativePath>
+	</parent>
+	<artifactId>cas-crawler</artifactId>
+	<name>Catalog and Archive Crawling Framework</name>
+	<description>The Catalog and Archive Service Crawling Framework.</description>
+	<scm>
+		<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/crawler</connection>
+		<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/crawler</developerConnection>
+		<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/crawler</url>
+	</scm>
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-surefire-plugin</artifactId>
+				<version>2.4</version>
+				<configuration>
+					<forkMode>pertest</forkMode>
+					<useSystemClassLoader>false</useSystemClassLoader>
+					<systemProperties>
+						<property>
+							<name>java.util.logging.config.file</name>
+							<value>${basedir}/src/testdata/test.logging.properties</value>
+						</property>
+					</systemProperties>
+					<forkedProcessTimeoutInSeconds>0</forkedProcessTimeoutInSeconds>
+					<redirectTestOutputToFile>true</redirectTestOutputToFile>
+					<includes>
+						<include>**/*Test*.java</include>
+					</includes>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<version>2.2-beta-2</version>
+				<configuration>
+					<descriptors>
+						<descriptor>src/main/assembly/assembly.xml</descriptor>
+					</descriptors>
+					<archive>
+						<manifest>
+							<mainClass>org.apache.oodt.cas.crawl.CrawlerLauncher</mainClass>
+						</manifest>
+					</archive>
+				</configuration>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>single</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+		<resources>
+			<resource>
+				<targetPath>org/apache/oodt/cas/crawl</targetPath>
+				<directory>${basedir}/src/main/resources</directory>
+				<includes>
+					<include>action-beans.xml</include>
+					<include>crawler-beans.xml</include>
+					<include>crawler-config.xml</include>
+					<include>precondition-beans.xml</include>
+				</includes>
+			</resource>
+		</resources>
+	</build>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>oodt-commons</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>cas-metadata</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>cas-cli</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>cas-filemgr</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>cas-workflow</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-core</artifactId>
+			<version>2.5.4</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-beans</artifactId>
+			<version>2.5.4</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-context</artifactId>
+			<version>2.5.4</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-lang</groupId>
+			<artifactId>commons-lang</artifactId>
+			<version>2.1</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-io</groupId>
+			<artifactId>commons-io</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>commons-logging</groupId>
+			<artifactId>commons-logging</artifactId>
+			<version>1.0.3</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-httpclient</groupId>
+			<artifactId>commons-httpclient</artifactId>
+			<version>3.0</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-codec</groupId>
+			<artifactId>commons-codec</artifactId>
+			<version>1.3</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-collections</groupId>
+			<artifactId>commons-collections</artifactId>
+			<version>2.1</version>
+		</dependency>
+		<dependency>
+			<groupId>xmlrpc</groupId>
+			<artifactId>xmlrpc</artifactId>
+			<version>2.0.1</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.geronimo.javamail</groupId>
+			<artifactId>geronimo-javamail_1.4_mail</artifactId>
+			<version>1.8.1</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.geronimo.specs</groupId>
+			<artifactId>geronimo-activation_1.1_spec</artifactId>
+			<version>1.1</version>
+		</dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <version>3.1</version>
+      <scope>test</scope>
+    </dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.2</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+</project>
diff --git a/0.8.1-rc1/crawler/src/main/assembly/assembly.xml b/0.8.1-rc1/crawler/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..4662e93
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/assembly/assembly.xml
@@ -0,0 +1,85 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<assembly>
+	<id>dist</id>
+	<formats>
+		<format>tar.gz</format>
+		<format>zip</format>
+	</formats>
+	<includeBaseDirectory>true</includeBaseDirectory>
+	<baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
+	<includeSiteDirectory>false</includeSiteDirectory>
+	<fileSets>
+		<fileSet>
+			<directory>${basedir}</directory>
+			<outputDirectory>.</outputDirectory>
+			<includes>
+				<include>LICENSE.txt</include>
+				<include>CHANGES.txt</include>
+			</includes>
+		</fileSet>
+		<fileSet>
+			<directory>${basedir}/src/main/bin</directory>
+			<outputDirectory>bin</outputDirectory>
+			<includes />
+			<fileMode>755</fileMode>
+		</fileSet>
+		<fileSet>
+			<directory>${basedir}/src/main/resources</directory>
+			<outputDirectory>etc</outputDirectory>
+			<includes>
+				<include>logging.properties</include>
+			</includes>
+		</fileSet>
+		<fileSet>
+			<directory>${basedir}/src/main/resources</directory>
+			<outputDirectory>logs</outputDirectory>
+			<includes>
+				<include>REMOVE.log</include>
+			</includes>
+		</fileSet>
+		<fileSet>
+			<directory>${basedir}/src/main/resources/examples</directory>
+			<outputDirectory>policy</outputDirectory>
+			<includes>
+				<include>*.xml</include>
+			</includes>
+		</fileSet>
+		<fileSet>
+			<directory>${basedir}/src/main/resources</directory>
+			<outputDirectory>policy</outputDirectory>
+			<includes>
+				<include>*.xml</include>
+			</includes>
+		</fileSet>
+		<fileSet>
+			<directory>${basedir}/src/main/resources/extern-scripts</directory>
+			<outputDirectory>policy/extern-scripts</outputDirectory>
+			<includes />
+		</fileSet>
+	</fileSets>
+	<dependencySets>
+		<dependencySet>
+			<outputDirectory>lib</outputDirectory>
+			<unpack>false</unpack>
+			<useProjectArtifact>true</useProjectArtifact>
+			<useTransitiveDependencies>true</useTransitiveDependencies>
+			<unpackOptions />
+		</dependencySet>
+	</dependencySets>
+</assembly>
diff --git a/0.8.1-rc1/crawler/src/main/bin/crawlctl b/0.8.1-rc1/crawler/src/main/bin/crawlctl
new file mode 100644
index 0000000..37343da
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/bin/crawlctl
@@ -0,0 +1,18 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+##########################################################################
+
+java -Djava.util.logging.config.file=../etc/logging.properties -Djava.ext.dirs=../lib org.apache.oodt.cas.crawl.daemon.CrawlDaemonController $*
diff --git a/0.8.1-rc1/crawler/src/main/bin/crawler_launcher b/0.8.1-rc1/crawler/src/main/bin/crawler_launcher
new file mode 100644
index 0000000..f07f824
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/bin/crawler_launcher
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# 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.
+#
+
+if [ -z $JAVA_HOME ] ; then
+        JAVA_HOME=/path/to/java/home
+else
+        JAVA_HOME=${JAVA_HOME}
+fi
+
+export JAVA_HOME
+
+$JAVA_HOME/bin/java \
+        -Djava.ext.dirs=../lib \
+        -Djava.util.logging.config.file=../etc/logging.properties \
+        -Dorg.apache.oodt.cas.crawl.bean.repo=../policy/crawler-config.xml \
+        -Dorg.apache.oodt.cas.cli.action.spring.config=../policy/cmd-line-actions.xml \
+        -Dorg.apache.oodt.cas.cli.option.spring.config=../policy/cmd-line-options.xml \
+		-Dorg.apache.oodt.cas.filemgr.properties=/path/to/filemgr/properties \
+        org.apache.oodt.cas.crawl.CrawlerLauncher $*
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/AutoDetectProductCrawler.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/AutoDetectProductCrawler.java
new file mode 100644
index 0000000..dc037bd
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/AutoDetectProductCrawler.java
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.typedetection.MetExtractorSpec;
+import org.apache.oodt.cas.crawl.typedetection.MimeExtractorConfigReader;
+import org.apache.oodt.cas.crawl.typedetection.MimeExtractorRepo;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.metadata.MetExtractor;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.filenaming.NamingConvention;
+import org.apache.oodt.cas.metadata.preconditions.PreCondEvalUtils;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+import java.util.logging.Level;
+
+//APACHE imports
+import org.apache.tika.mime.MimeType; //for javadoc
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * <p>
+ * A {@link ProductCrawler} that uses a suite of files to define its crawling
+ * and ingestion policy:
+ * 
+ * <ul>
+ * <li><code>actions-map.xml</code> - This file is an XML specification for
+ * actions that the crawler should take in response to its 3 lifecycle phases:
+ * preIngest, postIngestSuccess, and postIngestFail. </li>
+ * <li><code>met-extr-preconditions.xml</code> - This file defines
+ * preconditions that {@link MetExtractor}s must pass before being called by
+ * the AutoDetectCrawler. </li>
+ * <li><code>mime-extractor-map.xml</code> - This file maps {@link MimeType}
+ * names to names of {@link MetExtractor}s to call for a particular
+ * {@link Product} {@link File} as it is encountered during a crawl (e.g.,
+ * assuming that {@link Metadata} needs to be generated, as oppossed to being
+ * available apriori). See
+ * <code>./src/resources/examples/mime-extractor-map.xml</code> for an example
+ * of the structure of this file. </li>
+ * <li><code>mimetypes.xml</code> - An <a
+ * href="http://tika.apache.org/">Apache Tika</a> style mimetypes
+ * file, augmented with the ability to have arbitrary regular expressions that
+ * define a particular {@link Product} {@link MimeType}. This {@link MimeType}
+ * is then mapped to an extractor vai the <code>mime-extractor-map.xml</code>
+ * file, described above. </li>
+ * </p>.
+ *
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public class AutoDetectProductCrawler extends ProductCrawler implements
+      CoreMetKeys {
+
+   public static final String MIME_TYPES_HIERARCHY = "MimeTypesHierarchy"; 
+
+   private MimeExtractorRepo mimeExtractorRepo;
+
+   @Override
+   protected Metadata getMetadataForProduct(File product) throws Exception {
+      List<MetExtractorSpec> specs = this.mimeExtractorRepo
+            .getExtractorSpecsForFile(product);
+      Metadata metadata = new Metadata();
+      metadata.addMetadata(MIME_TYPES_HIERARCHY,
+            mimeExtractorRepo.getMimeTypes(product));
+      for (int i = 0; i < specs.size(); i++) {
+         Metadata m = ((MetExtractorSpec) specs.get(i)).getMetExtractor()
+               .extractMetadata(product);
+         if (m != null) {
+            metadata.addMetadata(m.getHashtable(), true);
+         }
+      }
+      return metadata;
+   }
+
+   @Override
+   protected boolean passesPreconditions(File product) {
+      try {
+         List<MetExtractorSpec> specs = this.mimeExtractorRepo
+               .getExtractorSpecsForFile(product);
+         if (specs.size() > 0) {
+            if (this.getApplicationContext() != null) {
+               PreCondEvalUtils evalUtils = new PreCondEvalUtils(
+                     this.getApplicationContext());
+               for (int i = 0; i < specs.size(); i++) {
+                  List<String> preCondComparatorIds = ((MetExtractorSpec) specs
+                        .get(i)).getPreCondComparatorIds();
+                  if (!evalUtils.eval(preCondComparatorIds, product))
+                     return false;
+               }
+            }
+            return true;
+         } else {
+            LOG.log(Level.WARNING, "No extractor specs specified for "
+                  + product);
+            return false;
+         }
+      } catch (Exception e) {
+         LOG.log(Level.WARNING,
+               "Failed to evaluate preconditions : " + e.getMessage());
+         return false;
+      }
+   }
+
+   @Override
+   protected File renameProduct(File product, Metadata productMetadata)
+         throws Exception {
+      String namingConventionId = mimeExtractorRepo
+            .getNamingConventionId(mimeExtractorRepo.getMimeType(product));
+      if (namingConventionId != null) {
+         NamingConvention namingConvention = (NamingConvention) getApplicationContext()
+               .getBean(namingConventionId);
+         return namingConvention.rename(product, productMetadata);
+      } else {
+         return product;
+      }
+   }
+
+   @Required
+   public void setMimeExtractorRepo(String mimeExtractorRepo) throws Exception {
+      this.mimeExtractorRepo = MimeExtractorConfigReader
+            .read(mimeExtractorRepo);
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/CrawlerLauncher.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/CrawlerLauncher.java
new file mode 100644
index 0000000..9fd682c
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/CrawlerLauncher.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl;
+
+//JDK imports
+import java.io.IOException;
+
+//OODT imports
+import org.apache.oodt.cas.cli.CmdLineUtility;
+
+/**
+ * A command line interface to the new Spring enabled crawler.
+ * 
+ * @author bfoster (Brian Foster)
+ * @version $Revision$
+ * @since OODT-190
+ */
+public class CrawlerLauncher {
+
+   public static void main(String[] args) throws IOException {
+      CmdLineUtility cmdLineUtility = new CmdLineUtility();
+      cmdLineUtility.run(args);
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/MetExtractorProductCrawler.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/MetExtractorProductCrawler.java
new file mode 100644
index 0000000..c8e8bc4
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/MetExtractorProductCrawler.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.MetExtractor;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.oodt.cas.metadata.filenaming.NamingConvention;
+import org.apache.oodt.cas.metadata.preconditions.PreConditionComparator;
+
+//JDK imports
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A variant of the Standard Product Crawler where .met files are generated on
+ * the fly as product files are encountered.
+ * </p>
+ */
+public class MetExtractorProductCrawler extends ProductCrawler {
+
+    private MetExtractor metExtractor;
+
+    private String metExtractorConfig;
+
+    private List<String> preCondIds = new ArrayList<String>();
+
+    private String namingConventionId;
+
+    @Override
+    protected Metadata getMetadataForProduct(File product) throws Exception {
+        return metExtractor.extractMetadata(product);
+    }
+
+    @Override
+    protected boolean passesPreconditions(File product) {
+        if (this.getPreCondIds() != null) {
+            for (String preCondId : this.getPreCondIds()) {
+                if (!((PreConditionComparator<?>) this.getApplicationContext()
+                        .getBean(preCondId)).passes(product))
+                    return false;
+            }
+        }
+        return product.exists() && product.length() > 0;
+    }
+
+    @Override
+    protected File renameProduct(File product, Metadata productMetadata)
+          throws Exception {
+       if (getNamingConventionId() != null) {
+          NamingConvention namingConvention = (NamingConvention)
+                getApplicationContext().getBean(getNamingConventionId());
+          if (namingConvention == null) {
+             throw new Exception("NamingConvention Id '" + getNamingConventionId()
+                   + "' is not defined");
+          }
+          return namingConvention.rename(product, productMetadata);
+       } else {
+          return product;
+       }
+    }
+
+    @Required
+    public void setMetExtractor(String metExtractor)
+            throws MetExtractionException, InstantiationException,
+            IllegalAccessException, ClassNotFoundException {
+        this.metExtractor = (MetExtractor) Class.forName(metExtractor)
+                .newInstance();
+        if (metExtractorConfig != null && !metExtractorConfig.equals(""))
+            this.metExtractor.setConfigFile(metExtractorConfig);
+    }
+
+    @Required
+    public void setMetExtractorConfig(String metExtractorConfig)
+            throws MetExtractionException {
+        this.metExtractorConfig = metExtractorConfig;
+        if (this.metExtractor != null && metExtractorConfig != null
+                && !metExtractorConfig.equals(""))
+            this.metExtractor.setConfigFile(metExtractorConfig);
+    }
+
+    public List<String> getPreCondIds() {
+        return preCondIds;
+    }
+
+    public void setPreCondIds(List<String> preCondIds) {
+        this.preCondIds = preCondIds;
+    }
+
+    public void setNamingConventionId(String namingConventionId) {
+        this.namingConventionId = namingConventionId;
+    }
+
+    public String getNamingConventionId() {
+       return namingConventionId;
+    }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/ProductCrawler.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/ProductCrawler.java
new file mode 100644
index 0000000..3c7529b
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/ProductCrawler.java
@@ -0,0 +1,370 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.action.CrawlerAction;
+import org.apache.oodt.cas.crawl.action.CrawlerActionRepo;
+import org.apache.oodt.cas.crawl.config.ProductCrawlerBean;
+import org.apache.oodt.cas.crawl.status.IngestStatus;
+import org.apache.oodt.cas.filemgr.ingest.Ingester;
+import org.apache.oodt.cas.filemgr.ingest.StdIngester;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.metadata.Metadata;
+
+import com.google.common.annotations.VisibleForTesting;
+
+//JDK imports
+import java.io.File;
+import java.io.FileFilter;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * An abstract base class for Product Crawling. This class provides methods to
+ * communicate with the file manager and parse met files that show how to ingest
+ * a particular Product into the File Manager.
+ * 
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public abstract class ProductCrawler extends ProductCrawlerBean {
+
+   /* our log stream */
+   protected static Logger LOG = Logger.getLogger(ProductCrawler.class
+         .getName());
+
+   // filter to only find directories when doing a listFiles
+   protected static FileFilter DIR_FILTER = new FileFilter() {
+      public boolean accept(File file) {
+         return file.isDirectory();
+      }
+   };
+
+   // filter to only find product files, not met files
+   protected static FileFilter FILE_FILTER = new FileFilter() {
+      public boolean accept(File file) {
+         return file.isFile();
+      }
+   };
+
+   protected List<IngestStatus> ingestStatus = new Vector<IngestStatus>();
+   protected CrawlerActionRepo actionRepo;
+   protected Ingester ingester;
+
+   public void crawl() {
+      crawl(new File(getProductPath()));
+   }
+
+   public void crawl(File dirRoot) {
+      // Reset ingest status.
+      ingestStatus.clear();
+
+      // Load actions.
+      loadAndValidateActions();
+
+      // Create Ingester.
+      setupIngester();
+
+      // Verify valid crawl directory.
+      if (dirRoot == null || !dirRoot.exists()) {
+         throw new IllegalArgumentException("dir root is null or non existant!");
+      }
+
+      // Start crawling.
+      Stack<File> stack = new Stack<File>();
+      stack.push(dirRoot.isDirectory() ? dirRoot : dirRoot.getParentFile());
+      while (!stack.isEmpty()) {
+         File dir = (File) stack.pop();
+         LOG.log(Level.INFO, "Crawling " + dir);
+
+         File[] productFiles = null;
+         if (isCrawlForDirs()) {
+            productFiles = dir.listFiles(DIR_FILTER);
+         } else {
+            productFiles = dir.listFiles(FILE_FILTER);
+         }
+
+         for (int j = 0; j < productFiles.length; j++) {
+            ingestStatus.add(handleFile(productFiles[j]));
+         }
+
+         if (!isNoRecur()) {
+            File[] subdirs = dir.listFiles(DIR_FILTER);
+            if (subdirs != null) {
+               for (int j = 0; j < subdirs.length; j++) {
+                  stack.push(subdirs[j]);
+               }
+            }
+         }
+      }
+   }
+
+   public IngestStatus handleFile(File product) {
+      LOG.log(Level.INFO, "Handling file " + product);
+
+      // Check preconditions.
+      if (!passesPreconditions(product)) {
+         LOG.log(Level.WARNING,
+               "Failed to pass preconditions for ingest of product: ["
+                     + product.getAbsolutePath() + "]");
+         return createIngestStatus(product,
+               IngestStatus.Result.PRECONDS_FAILED,
+               "Failed to pass preconditions");
+      }
+
+      // Generate Metadata for product.
+      Metadata productMetadata = new Metadata();
+      productMetadata.addMetadata(getGlobalMetadata());
+      try {
+         productMetadata.replaceMetadata(getMetadataForProduct(product));
+      } catch (Exception e) {
+         LOG.log(Level.SEVERE,
+               "Failed to get metadata for product : " + e.getMessage(), e);
+         performPostIngestOnFailActions(product, productMetadata);
+         return createIngestStatus(product,
+               IngestStatus.Result.FAILURE,
+               "Failed to get metadata for product : " + e.getMessage());
+      }
+
+      // Rename the product.
+      try {
+         product = renameProduct(product, productMetadata);
+      } catch (Exception e) {
+         LOG.log(Level.SEVERE,
+               "Failed to rename product : " + e.getMessage(), e);
+         performPostIngestOnFailActions(product, productMetadata);
+         return createIngestStatus(product, IngestStatus.Result.FAILURE,
+               "Failed to rename product : " + e.getMessage());
+      }
+
+      // Set known metadata if not already specified.
+      addKnownMetadata(product, productMetadata);
+
+      // Check that metadata contains required metadata.
+      if (!containsRequiredMetadata(productMetadata)) {
+         LOG.log(Level.SEVERE, "Missing required metadata for product '"
+               + product + "'");
+         performPostIngestOnFailActions(product, productMetadata);
+         return createIngestStatus(product, IngestStatus.Result.FAILURE,
+               "Missing required metadata");
+      }
+
+      // Run preIngest actions.
+      if (!performPreIngestActions(product, productMetadata)) {
+         performPostIngestOnFailActions(product, productMetadata);
+         return createIngestStatus(product, IngestStatus.Result.FAILURE,
+            "PreIngest actions failed to complete");            
+      }
+
+      // Check if ingest has been turned off.
+      if (isSkipIngest()) {
+         LOG.log(Level.INFO, "Skipping ingest of product: ["
+               + product.getAbsolutePath() + "]");
+         return createIngestStatus(product, IngestStatus.Result.SKIPPED,
+               "Crawler ingest turned OFF");
+      }
+
+      // Ingest product.
+      boolean ingestSuccess = ingest(product, productMetadata);
+
+      // On Successful Ingest.
+      if (ingestSuccess) {
+         LOG.log(Level.INFO, "Successful ingest of product: ["
+               + product.getAbsolutePath() + "]");
+         performPostIngestOnSuccessActions(product, productMetadata);
+         return createIngestStatus(product,
+               IngestStatus.Result.SUCCESS, "Ingest was successful");
+
+      // On Failed Ingest.
+      } else {
+         LOG.log(Level.WARNING, "Failed to ingest product: ["
+               + product.getAbsolutePath()
+               + "]: performing postIngestFail actions");         
+         performPostIngestOnFailActions(product, productMetadata);
+         return createIngestStatus(product, IngestStatus.Result.FAILURE,
+               "Failed to ingest product");
+      }
+   }
+
+   public List<IngestStatus> getIngestStatus() {
+      return Collections.unmodifiableList(ingestStatus);
+   }
+
+   protected abstract boolean passesPreconditions(File product);
+
+   protected abstract Metadata getMetadataForProduct(File product)
+         throws Exception;
+
+   protected abstract File renameProduct(File product, Metadata productMetadata)
+         throws Exception;
+
+   @VisibleForTesting void setupIngester() {
+      ingester = new StdIngester(getClientTransferer());
+   }
+
+   @VisibleForTesting void loadAndValidateActions() {
+      if (actionRepo == null && getApplicationContext() != null) {
+         actionRepo = new CrawlerActionRepo();
+         actionRepo.loadActionsFromBeanFactory(
+               getApplicationContext(), getActionIds());
+         validateActions();
+      }
+   }
+
+   @VisibleForTesting void validateActions() {
+      StringBuffer actionErrors = new StringBuffer("");
+      for (CrawlerAction action : actionRepo.getActions()) {
+         try {
+            action.validate();
+         } catch (Exception e) {
+            actionErrors.append(" " + action.getId() + ": " + e.getMessage()
+                  + "\n");
+         }
+      }
+      if (actionErrors.length() > 0) {
+         throw new RuntimeException("Actions failed validation:\n"
+               + actionErrors);
+      }
+   }
+
+   @VisibleForTesting synchronized boolean containsRequiredMetadata(
+         Metadata productMetadata) {
+      for (String reqMetKey : getRequiredMetadata()) {
+         if (!productMetadata.containsKey(reqMetKey)) {
+            LOG.log(Level.WARNING, "Missing required metadata field "
+                  + reqMetKey);
+            return false;
+         }
+      }
+      return true;
+   }
+
+   @VisibleForTesting void addKnownMetadata(File product,
+         Metadata productMetadata) {
+      // Add ProductName if not specified.
+      if (!productMetadata.containsKey(PRODUCT_NAME)) {
+         productMetadata.addMetadata(PRODUCT_NAME, product.getName());
+      }
+      // Add Filename if not specified.
+      if (!productMetadata.containsKey(FILENAME)) {
+         productMetadata.addMetadata(FILENAME, product.getName());
+      }
+      // Add FileLocation if not specified.
+      if (!productMetadata.containsKey(FILE_LOCATION)) {
+         productMetadata.addMetadata(FILE_LOCATION, product
+               .getAbsoluteFile().getParentFile().getAbsolutePath());
+      }
+      // Add FileSize if not specified
+      if (!productMetadata.containsKey(FILE_SIZE)) {
+         productMetadata.addMetadata(FILE_SIZE,
+               Long.toString(product.length()));
+      }
+   }
+
+   @VisibleForTesting IngestStatus createIngestStatus(final File product,
+         final IngestStatus.Result result, final String message) {
+      return new IngestStatus() {
+         public File getProduct() {
+            return product;
+         }
+         public Result getResult() {
+            return result;
+         }
+         public String getMessage() {
+            return message;
+         }
+      };
+   }
+
+   @VisibleForTesting boolean ingest(File product, Metadata productMetdata) {
+      try {
+         LOG.log(Level.INFO, "ProductCrawler: Ready to ingest product: ["
+               + product + "]: ProductType: ["
+               + productMetdata.getMetadata(PRODUCT_TYPE) + "]");
+         String productId = ingester.ingest(new URL(getFilemgrUrl()),
+               product, productMetdata);
+         LOG.log(Level.INFO, "Successfully ingested product: [" + product
+               + "]: product id: " + productId);
+      } catch (Exception e) {
+         LOG.log(Level.WARNING,
+               "ProductCrawler: Exception ingesting product: [" + product
+                     + "]: Message: " + e.getMessage()
+                     + ": attempting to continue crawling", e);
+         return false;
+      }
+      return true;
+   }
+
+   @VisibleForTesting boolean performPreIngestActions(File product,
+         Metadata productMetadata) {
+      if (actionRepo != null) {
+         return performProductCrawlerActions(
+               actionRepo.getPreIngestActions(), product, productMetadata);
+      } else {
+         return true;
+      }
+   }
+
+   @VisibleForTesting boolean performPostIngestOnSuccessActions(File product,
+         Metadata productMetadata) {
+      if (actionRepo != null) {
+         return performProductCrawlerActions(
+               actionRepo.getPostIngestOnSuccessActions(), product,
+               productMetadata);
+      } else {
+         return true;
+      }
+   }
+
+   @VisibleForTesting boolean performPostIngestOnFailActions(File product,
+         Metadata productMetadata) {
+      if (actionRepo != null) {
+         return performProductCrawlerActions(
+               actionRepo.getPostIngestOnFailActions(), product,
+               productMetadata);
+      } else {
+         return true;
+      }
+   }
+
+   @VisibleForTesting boolean performProductCrawlerActions(
+         List<CrawlerAction> actions, File product, Metadata productMetadata) {
+      boolean allSucceeded = true;
+      for (CrawlerAction action : actions) {
+         try {
+            LOG.log(Level.INFO, "Performing action (id = " + action.getId()
+                  + " : description = " + action.getDescription() + ")");
+            if (!action.performAction(product, productMetadata)) {
+               throw new Exception("Action (id = " + action.getId()
+                     + " : description = " + action.getDescription()
+                     + ") returned false");
+            }
+         } catch (Exception e) {
+            allSucceeded = false;
+            LOG.log(Level.WARNING,
+                  "Failed to perform crawler action : " + e.getMessage(), e);
+         }
+      }
+      return allSucceeded;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/StdProductCrawler.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/StdProductCrawler.java
new file mode 100644
index 0000000..6bd72a9
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/StdProductCrawler.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.extractors.MetReaderExtractor;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Level;
+
+/**
+ * A generic Product Crawler for Products. The Crawler is given a root Product
+ * Path and it searches through all directories and sub-directories for .met
+ * files, which it uses to determine products to ingest into the file manger.
+ * The important .met file fields that this crawler requires are:
+ * 
+ * <ul>
+ * <li><code>FileLocation</code>: directory absolute path to location of product
+ * file</li>
+ * <li><code>Filename</code>: name of the product file to ingest</li>
+ * <li><code>ProductType</code>: the ProductType that will be sent to the file
+ * manager for the product file described by the .met file.</li>
+ * </ul>
+ * 
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public class StdProductCrawler extends ProductCrawler {
+
+   String metFileExtension;
+
+   public StdProductCrawler() {
+      this.metFileExtension = "met";
+   }
+
+   @Override
+   protected Metadata getMetadataForProduct(File product) throws Exception {
+      MetReaderExtractor extractor = new MetReaderExtractor(
+            this.metFileExtension);
+      return extractor.extractMetadata(product);
+   }
+
+   @Override
+   protected boolean passesPreconditions(File product) {
+      return new File(product.getAbsolutePath() + "." + this.metFileExtension)
+            .exists();
+   }
+
+   @Override
+   protected File renameProduct(File product, Metadata productMetadata) {
+      return product;
+   }
+
+   public void setMetFileExtension(String metFileExtension) {
+      this.metFileExtension = metFileExtension;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/CrawlerAction.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/CrawlerAction.java
new file mode 100644
index 0000000..5119658
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/CrawlerAction.java
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.crawl.action;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.commons.lang.Validate;
+import org.apache.oodt.commons.spring.SpringSetIdInjectionType;
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * An action taken by the crawler during success or fail of one of its lifecycle
+ * states: preIngest, postIngestSuccess, or postIngestFail .
+ * 
+ * @author bfoster (Brian Foster)
+ * @author mattmann (Chris Mattmann)
+ */
+public abstract class CrawlerAction implements SpringSetIdInjectionType {
+
+   public List<String> phases;
+
+   public static Logger LOG = Logger.getLogger(CrawlerAction.class.getName());
+
+   private String description;
+
+   private String id;
+
+   public CrawlerAction() {
+   }
+
+   @Override
+   public String getId() {
+      return id;
+   }
+
+   @Override
+   public void setId(String id) {
+      this.id = id;
+   }
+
+   @Required
+   public void setPhases(List<String> phases) {
+      this.phases = phases;
+   }
+
+   public List<String> getPhases() {
+      return this.phases;
+   }
+
+   public void setDescription(String description) {
+      this.description = description;
+   }
+
+   public String getDescription() {
+      return this.description;
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (obj instanceof CrawlerAction) {
+         return ((CrawlerAction) obj).id.equals(id);
+      } else {
+         return false;
+      }
+   }
+
+   @Override
+   public int hashCode() {
+      return id.hashCode();
+   }
+
+   public void validate() throws CrawlerActionException {
+      try {
+         Validate.notNull(id, "Must specify id");
+         Validate.notNull(phases, "Must specify phases");
+      } catch (Exception e) {
+         throw new CrawlerActionException(e);
+      }
+   }
+
+   public abstract boolean performAction(File product, Metadata productMetadata)
+         throws CrawlerActionException;
+
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/CrawlerActionPhases.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/CrawlerActionPhases.java
new file mode 100644
index 0000000..00cc7f6
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/CrawlerActionPhases.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+/**
+ * Supported Crawler Phases.
+ *
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public enum CrawlerActionPhases {
+   PRE_INGEST("preIngest"),
+   POST_INGEST_SUCCESS("postIngestSuccess"),
+   POST_INGEST_FAILURE("postIngestFailure");
+
+   private String name;
+
+   private CrawlerActionPhases(String name) {
+      this.name = name;
+   }
+
+   public String getName() {
+      return name;
+   }
+
+   public static CrawlerActionPhases getPhaseByName(String name) {
+      for (CrawlerActionPhases phase : CrawlerActionPhases.values()) {
+         if (phase.getName().equals(name)) {
+            return phase;
+         }
+      }
+      return null;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/CrawlerActionRepo.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/CrawlerActionRepo.java
new file mode 100644
index 0000000..a0ad145
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/CrawlerActionRepo.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//JDK imports
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+//Spring imports
+import org.springframework.context.ApplicationContext;
+
+import com.google.common.collect.Sets;
+
+/**
+ * A repository and reader for {@link CrawlerAction}s associated with Crawler
+ * lifecycle phases: preIngest, postIngestSuccess and postIngestFail.
+ * 
+ * @author bfoster (Brian Foster)
+ * @author mattmann (Chris Mattmann)
+ */
+public class CrawlerActionRepo {
+
+   private LinkedList<CrawlerAction> preIngestActions;
+   private LinkedList<CrawlerAction> postIngestOnFailActions;
+   private LinkedList<CrawlerAction> postIngestOnSuccessActions;
+
+   public CrawlerActionRepo() {
+      this.preIngestActions = new LinkedList<CrawlerAction>();
+      this.postIngestOnFailActions = new LinkedList<CrawlerAction>();
+      this.postIngestOnSuccessActions = new LinkedList<CrawlerAction>();
+   }
+
+   public Set<CrawlerAction> getActions() {
+      Set<CrawlerAction> actions = Sets.newHashSet();
+      actions.addAll(preIngestActions);
+      actions.addAll(postIngestOnFailActions);
+      actions.addAll(postIngestOnSuccessActions);
+      return actions;
+   }
+
+   public List<CrawlerAction> getPreIngestActions() {
+      return this.preIngestActions;
+   }
+
+   public List<CrawlerAction> getPostIngestOnFailActions() {
+      return this.postIngestOnFailActions;
+   }
+
+   public List<CrawlerAction> getPostIngestOnSuccessActions() {
+      return this.postIngestOnSuccessActions;
+   }
+
+   public void loadActionsFromBeanFactory(ApplicationContext context,
+         List<String> actionIds) {
+      for (String actionId : actionIds) {
+         CrawlerAction action = ((CrawlerAction) context.getBean(actionId,
+               CrawlerAction.class));
+         List<String> phases = action.getPhases();
+         for (String phase : phases) {
+            switch (CrawlerActionPhases.getPhaseByName(phase)) {
+               case PRE_INGEST:
+                  preIngestActions.add(action);
+                  break;
+               case POST_INGEST_SUCCESS:
+                  postIngestOnSuccessActions.add(action);
+                  break;
+               case POST_INGEST_FAILURE:
+                  postIngestOnFailActions.add(action);
+                  break;
+               default:
+                  throw new RuntimeException("Phase '" + phase
+                        + "' is not supported");
+            }
+         }
+      }
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/DeleteFile.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/DeleteFile.java
new file mode 100644
index 0000000..b98ad86
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/DeleteFile.java
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Level;
+
+//Apache imports
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * Deletes a product file as a {@link CrawlerAction} response.
+ * 
+ * @author bfoster (Brian Foster)
+ * @author mattmann (Chris Mattmann)
+ * @author luca (Luca Cinquini)
+ */
+public class DeleteFile extends CrawlerAction {
+
+   private File file;
+   private String fileExtension;
+
+   @Override
+   public boolean performAction(File product, Metadata productMetadata)
+         throws CrawlerActionException {
+      try {
+         File fileToDelete = product;
+         if (file != null) {
+            fileToDelete = file;
+         } else if (fileExtension != null) {
+            fileToDelete = new File(product.getAbsolutePath() + "." + fileExtension);
+         }
+
+         LOG.log(Level.INFO, "Deleting file " + fileToDelete.getAbsolutePath());
+         if (fileToDelete.isDirectory()) {
+         	// the following method will throw an exception if the directory cannot be deleted
+         	FileUtils.deleteDirectory(fileToDelete); 
+         	return true;
+         } else {
+        	 return fileToDelete.delete();
+         }
+         
+      } catch (Exception e) {
+         LOG.log(Level.SEVERE, "Error while deleting file for product '"
+               + product + "' : " + e.getMessage(), e);
+         return false;
+      }
+   }
+
+   @Override
+   public void validate() throws CrawlerActionException {
+      super.validate();
+      try {
+         Validate.isTrue(file == null || fileExtension == null,
+               "Must specify either file or fileExtension");
+      } catch (Exception e) {
+         throw new CrawlerActionException(e);
+      }
+   }
+
+   public void setFile(File file) {
+      this.file = file;
+   }
+
+   public void setFileExtension(String fileExtension) {
+      this.fileExtension = fileExtension;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/EmailNotification.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/EmailNotification.java
new file mode 100644
index 0000000..46539ab
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/EmailNotification.java
@@ -0,0 +1,168 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+import java.util.Properties;
+import javax.mail.Message;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.AddressException;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.action.CrawlerAction;
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * This action sends an email notification. It performs metadata and system
+ * property replacement on the subject, recipients, and message. This allows the
+ * notifications to be dynamically generated.
+ * 
+ * @author pramirez (Paul Ramirez)
+ * @author mattmann (Chris Mattmann)
+ * 
+ */
+public class EmailNotification extends CrawlerAction {
+
+   private String mailHost;
+   private String subject;
+   private String message;
+   private List<String> recipients;
+   private String sender;
+   private boolean ignoreInvalidAddresses;
+
+   public EmailNotification() {
+      this.ignoreInvalidAddresses = true;
+   }
+
+   @Override
+   public boolean performAction(File product, Metadata metadata)
+         throws CrawlerActionException {
+      try {
+         Properties props = new Properties();
+         props.put("mail.host", this.mailHost);
+         props.put("mail.transport.protocol", "smtp");
+         props.put("mail.from", this.sender);
+
+         Session session = Session.getDefaultInstance(props);
+         Message msg = new MimeMessage(session);
+         msg.setSubject(PathUtils.doDynamicReplacement(subject, metadata));
+         msg.setText(new String(PathUtils.doDynamicReplacement(message,
+               metadata).getBytes()));
+         for (String recipient : recipients) {
+            try {
+               msg.addRecipient(Message.RecipientType.TO, new InternetAddress(
+                     PathUtils.replaceEnvVariables(recipient.trim(), metadata),
+                     ignoreInvalidAddresses));
+               LOG.fine("Recipient: "
+                     + PathUtils.replaceEnvVariables(recipient.trim(), metadata));
+            } catch (AddressException ae) {
+               LOG.fine("Recipient: "
+                     + PathUtils.replaceEnvVariables(recipient.trim(), metadata));
+               LOG.warning(ae.getMessage());
+            }
+         }
+         LOG.fine("Subject: " + msg.getSubject());
+         LOG.fine("Message: "
+               + new String(PathUtils.doDynamicReplacement(message, metadata)
+                     .getBytes()));
+         Transport.send(msg);
+         return true;
+      } catch (Exception e) {
+         LOG.severe(e.getMessage());
+         return false;
+      }
+   }
+
+   @Override
+   public void validate() throws CrawlerActionException {
+      super.validate();
+      try {
+         Validate.notNull(mailHost, "Must specify mailHost");
+         Validate.notNull(subject, "Must specify subject");
+         Validate.notNull(message, "Must specify message");
+         Validate.notNull(recipients, "Must specify recipients");
+         Validate.notNull(sender, "Must specify sender");
+      } catch (Exception e) {
+         throw new CrawlerActionException(e);
+      }
+   }
+
+   @Required
+   public void setMailHost(String smtpHost) {
+      this.mailHost = smtpHost;
+   }
+
+   @Required
+   public void setSubject(String subject) {
+      this.subject = subject;
+   }
+
+   @Required
+   public void setMessage(String message) {
+      this.message = message;
+   }
+
+   public void setRecipients(String recipients) {
+      if (recipients != null) {
+         this.recipients = Lists.newArrayList(recipients.split(","));
+      }
+   }
+
+   public void setRecipients(List<String> recipients) {
+      this.recipients = recipients;
+   }
+
+   @Required
+   public void setSender(String sender) {
+      this.sender = sender;
+   }
+
+   public void setIgnoreInvalidAddresses(Boolean ignoreInvalidAddresses) {
+      this.ignoreInvalidAddresses = ignoreInvalidAddresses;
+   }
+
+   public static void main(String[] args) throws Exception {
+      if (args.length != 5) {
+         System.out.println("Usage: java " + EmailNotification.class.getName()
+               + " <mailhost> <sender> <recipients> <subject> <message>");
+         System.exit(-1);
+      }
+      EmailNotification notification = new EmailNotification();
+      notification.setMailHost(args[0]);
+      notification.setSender(args[1]);
+      notification.setRecipients(args[2]);
+      notification.setSubject(args[3]);
+      notification.setMessage(args[4]);
+      notification.performAction(new File(""), new Metadata());
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/ExternAction.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/ExternAction.java
new file mode 100644
index 0000000..bfbe5bb
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/ExternAction.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//OODT static imports
+import static org.apache.oodt.cas.metadata.util.PathUtils.doDynamicReplacement;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Level;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.commons.exec.ExecUtils;
+
+/**
+ * Execute some external command as a {@link CrawlerAction} response.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class ExternAction extends CrawlerAction {
+
+   private String executeCommand;
+   private String workingDir;
+
+   @Override
+   public boolean performAction(File product, Metadata productMetadata)
+         throws CrawlerActionException {
+      try {
+         String envReplacedExecuteCommand = doDynamicReplacement(
+               executeCommand, productMetadata);
+         return ExecUtils.callProgram(
+               envReplacedExecuteCommand,
+               LOG,
+               new File(workingDir != null ? doDynamicReplacement(workingDir,
+                     productMetadata) : product.getParent())) == 0;
+      } catch (Exception e) {
+         LOG.log(Level.SEVERE, "Failed to execute extern command '"
+               + executeCommand + "' : " + e.getMessage(), e);
+         return false;
+      }
+   }
+
+   @Override
+   public void validate() throws CrawlerActionException {
+      super.validate();
+      try {
+         Validate.notNull(executeCommand, "Must specify executeCommand");
+      } catch (Exception e) {
+         throw new CrawlerActionException(e);
+      }
+   }
+
+   public void setExecuteCommand(String executeCommand) {
+      this.executeCommand = executeCommand;
+   }
+
+   public void setWorkingDir(String workingDir) throws Exception {
+      this.workingDir = workingDir;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/FileBasedAction.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/FileBasedAction.java
new file mode 100755
index 0000000..e6d7da6
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/FileBasedAction.java
@@ -0,0 +1,113 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.action.CrawlerAction;
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * This class provides some basic support for actions revolving around files. It
+ * allows action to support file selection based on configuration, metadata, or
+ * the current file being handled by the crawler. In addition, it supports the
+ * usage of FileSettings to provide conformance amongst extending actions.
+ * Finally, it captures a flag for indicating whether the action should fail
+ * should the file not exist.
+ * 
+ * @author pramirez (Paul Ramirez)
+ * @author mattmann (Chris Mattmann)
+ * 
+ */
+public abstract class FileBasedAction extends CrawlerAction {
+   protected String file;
+   protected String fileKey;
+   protected FileSettings fileSettings;
+   protected boolean failMissingFile;
+
+   public FileBasedAction() {
+      fileSettings = new FileSettings();
+      this.failMissingFile = false;
+   }
+
+   public void setFilePrefix(String filePrefix) {
+      fileSettings.setFilePrefix(filePrefix);
+   }
+
+   public void setFileSuffix(String fileSuffix) {
+      fileSettings.setFileSuffix(fileSuffix);
+   }
+
+   public void setFileExtension(String fileExtension) {
+      fileSettings.setFileExtension(fileExtension);
+   }
+
+   public void setKeepExistingExtension(boolean keepExistingExtension) {
+      fileSettings.setKeepExistingExtension(keepExistingExtension);
+   }
+
+   public void setFile(String file) {
+      this.file = file;
+   }
+
+   public void setFileKey(String fileKey) {
+      this.fileKey = fileKey;
+   }
+
+   public void setFailMissingFile(boolean failMissingFile) {
+      this.failMissingFile = failMissingFile;
+   }
+
+   public File getSelectedFile(File product, Metadata metadata) {
+      File selectedFile = null;
+      if (file == null && fileKey == null) {
+         selectedFile = product;
+      } else if (file != null) {
+         selectedFile = new File(file);
+      } else {
+         selectedFile = new File(metadata.getMetadata(fileKey));
+      }
+      return selectedFile;
+   }
+
+   public boolean performAction(File product, Metadata metadata)
+         throws CrawlerActionException {
+      File selectedFile = this.getSelectedFile(product, metadata);
+      String selectedFileString = this.fileSettings
+            .getPreparedFileString(selectedFile);
+      File actionFile = new File(selectedFileString);
+
+      if (failMissingFile && !actionFile.exists()) {
+         LOG.severe("File does not exist: " + actionFile.getAbsolutePath());
+         return false;
+      }
+
+      if (actionFile.exists()) {
+         return this.performFileAction(actionFile, metadata);
+      } else {
+         LOG.fine("File does not exist: " + actionFile.getAbsolutePath());
+      }
+
+      return true;
+   }
+
+   public abstract boolean performFileAction(File actionFile, Metadata metadata)
+         throws CrawlerActionException;
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/FileSettings.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/FileSettings.java
new file mode 100755
index 0000000..66665b7
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/FileSettings.java
@@ -0,0 +1,99 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//JDK imports
+import java.io.File;
+
+/**
+ * This class captures settings used in FileBased actions and the FileExists
+ * precondition. It specifies how to prepare a file string and provides
+ * consistent features across the aforementioned. This preparation supports such
+ * converting from something such as image.jpg to cool_image_ancillary.png. In
+ * this scenario the filePrefix="cool_", fileSuffix="_ancillary",
+ * fileExtension="png", and keepExistingExtension=true. This conversion could
+ * take place by passing calling the getPreparedFileString method.
+ * 
+ * @author pramirez (Paul Ramirez)
+ * @author mattmann (Chris Mattmann)
+ * 
+ */
+public class FileSettings {
+   private String filePrefix;
+   private String fileSuffix;
+   private String fileExtension;
+   private boolean keepExistingExtension;
+
+   public FileSettings() {
+      this.keepExistingExtension = true;
+   }
+
+   public void setFilePrefix(String filePrefix) {
+      this.filePrefix = filePrefix;
+   }
+
+   public void setFileSuffix(String fileSuffix) {
+      this.fileSuffix = fileSuffix;
+   }
+
+   public void setFileExtension(String fileExtension) {
+      this.fileExtension = fileExtension;
+   }
+
+   public void setKeepExistingExtension(boolean keepExistingExtension) {
+      this.keepExistingExtension = keepExistingExtension;
+   }
+
+   public String getPreparedFileString(File file) {
+      StringBuffer fileString = new StringBuffer();
+
+      if (file.getParent() != null) {
+         fileString.append(file.getParent());
+         fileString.append(System.getProperties().getProperty("file.separator",
+               "/"));
+      }
+
+      if (filePrefix != null) {
+         fileString.append(filePrefix);
+      }
+
+      String existingExtension = "";
+      String filename = file.getName();
+      int existingIndex = filename.lastIndexOf(".");
+      if (existingIndex != -1) {
+         existingExtension = filename.substring(existingIndex);
+         filename = filename.substring(0, existingIndex);
+      }
+
+      fileString.append(filename);
+
+      if (fileSuffix != null) {
+         fileString.append(fileSuffix);
+      }
+
+      if (keepExistingExtension) {
+         fileString.append(existingExtension);
+      }
+
+      if (fileExtension != null) {
+         fileString.append(".");
+         fileString.append(fileExtension);
+      }
+
+      return fileString.toString();
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/FilemgrUniquenessChecker.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/FilemgrUniquenessChecker.java
new file mode 100644
index 0000000..96b6d5b
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/FilemgrUniquenessChecker.java
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//OODT static imports
+import static org.apache.oodt.cas.filemgr.metadata.CoreMetKeys.PRODUCT_NAME;
+
+//JDK imports
+import java.io.File;
+import java.net.URL;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * Check whether a product exists in the database already
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class FilemgrUniquenessChecker extends CrawlerAction {
+
+   private String filemgrUrl;
+
+   @Override
+   public boolean performAction(File product, Metadata productMetadata)
+         throws CrawlerActionException {
+      try {
+         Validate.notNull(productMetadata.getMetadata(PRODUCT_NAME),
+               PRODUCT_NAME + " was not found in metadata");
+
+         XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(
+               new URL(this.filemgrUrl));
+         return !fmClient.hasProduct(productMetadata.getMetadata(PRODUCT_NAME));
+      } catch (Exception e) {
+         throw new CrawlerActionException("Product failed uniqueness check : ["
+               + product + "] : " + e.getMessage());
+      }
+   }
+
+   @Override
+   public void validate() throws CrawlerActionException {
+      super.validate();
+      try {
+         Validate.notNull(filemgrUrl, "Must specify filemgrUrl");
+      } catch (Exception e) {
+         throw new CrawlerActionException(e);
+      }
+   }
+
+   public void setFilemgrUrl(String filemgrUrl) {
+      this.filemgrUrl = filemgrUrl;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/GroupAction.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/GroupAction.java
new file mode 100755
index 0000000..2e70a79
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/GroupAction.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.action.CrawlerAction;
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * Support of a GroupAction could go a ways to simplify command line
+ * specification of actions to run. Instead of having to list actions to run one
+ * would simply end up referencing the group. In addition, this may end up
+ * opening up the possibility to customize the behavior of GroupActions such as
+ * not continuing to run actions if one failed. Currently, the crawler continues
+ * executing actions even if an action fails this could be a way to tailor that
+ * behavior.
+ * 
+ * @author pramirez (Paul Ramirez)
+ */
+public class GroupAction extends CrawlerAction {
+   private List<CrawlerAction> actionsToCall;
+
+   @Override
+   public boolean performAction(File product, Metadata metadata)
+         throws CrawlerActionException {
+      boolean allSucceeded = true;
+      for (CrawlerAction action : actionsToCall) {
+         try {
+            LOG.info("Performing action (id = " + action.getId()
+                  + " : description = " + action.getDescription() + ")");
+            if (!action.performAction(product, metadata))
+               throw new Exception("Action (id = " + action.getId()
+                     + " : description = " + action.getDescription()
+                     + ") returned false");
+         } catch (Exception e) {
+            allSucceeded = false;
+            LOG.warning("Failed to perform crawler action : " + e.getMessage());
+         }
+
+      }
+      return allSucceeded;
+   }
+
+   @Override
+   public void validate() throws CrawlerActionException {
+      super.validate();
+      try {
+         Validate.notNull(actionsToCall, "Must specify actionsToCall");
+      } catch (Exception e) {
+         throw new CrawlerActionException(e);
+      }
+   }
+
+   public void setActionsToCall(List<CrawlerAction> actionsToCall) {
+      this.actionsToCall = actionsToCall;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/IngestAncillary.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/IngestAncillary.java
new file mode 100755
index 0000000..7cacd66
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/IngestAncillary.java
@@ -0,0 +1,207 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//JDK imports
+import java.io.File;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.filemgr.ingest.Ingester;
+import org.apache.oodt.cas.filemgr.ingest.StdIngester;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * This action allows the crawler to ingest an ancillary file while crawling
+ * other files. For example, if the crawler is configured to pick up images then
+ * this action could be used to pick up the thumbnails. The ancillary file will
+ * be submitted to the file manager given the product type specified and an
+ * identifier placed in the metadata of the file being ingested. One will have
+ * to set up the product type in the file manager policy to support this action.
+ * This action does not perform metadata extraction and if this is required one
+ * should consider using a server side metadata extractor configured with the
+ * file manager.
+ * 
+ * @author pramirez (Paul Ramirez)
+ * @author mattmann (Chris Mattmann)
+ */
+public class IngestAncillary extends FileBasedAction {
+  private String fileManagerUrl;
+  private String dataTransferService;
+  private String relatedKey;
+  private String productType;
+  private Map<String, List<String>> ancillaryMetadata;
+  private List<String> copyKeys;
+  private List<String> replaceDynamicKeys;
+  private List<String> writeBackKeys;
+  private String writeBackKeyPrefix;
+
+  public IngestAncillary() {
+    super();
+  }
+
+  @Override
+  public boolean performFileAction(File actionFile, Metadata metadata)
+      throws CrawlerActionException {
+    Metadata ingestMetadata = new Metadata();
+    if (ancillaryMetadata != null) {
+      for (String key : this.ancillaryMetadata.keySet()) {
+        for (String value : this.ancillaryMetadata.get(key)) {
+          ingestMetadata.addMetadata(key, PathUtils.replaceEnvVariables(value));
+        }
+      }
+    }
+
+    if (copyKeys != null) {
+      for (String copyKey : copyKeys) {
+        if (metadata.containsKey(copyKey)) {
+          ingestMetadata.addMetadata(copyKey, metadata.getAllMetadata(copyKey));
+        }
+      }
+    }
+
+    if (ingestMetadata.getMetadata(CoreMetKeys.FILE_LOCATION) == null) {
+      ingestMetadata.addMetadata(CoreMetKeys.FILE_LOCATION,
+          actionFile.getParent());
+    }
+    if (ingestMetadata.getMetadata(CoreMetKeys.FILENAME) == null) {
+      ingestMetadata.addMetadata(CoreMetKeys.FILENAME, actionFile.getName());
+    }
+    if (ingestMetadata.getMetadata(CoreMetKeys.PRODUCT_NAME) == null) {
+      ingestMetadata.addMetadata(CoreMetKeys.PRODUCT_NAME, actionFile.getName()
+          .substring(0, actionFile.getName().indexOf(".")));
+    }
+    if (ingestMetadata.getMetadata(CoreMetKeys.PRODUCT_TYPE) == null) {
+      ingestMetadata.addMetadata(CoreMetKeys.PRODUCT_TYPE, productType);
+    }
+
+    try {
+      Ingester ingester = new StdIngester(dataTransferService);
+      String identifier = ingester.ingest(new URL(this.fileManagerUrl),
+          actionFile, ingestMetadata);
+      if (identifier != null) {
+        LOG.info("Succesfully ingested ancillary file "
+            + actionFile.getAbsolutePath() + " with identifier " + identifier);
+      } else {
+        LOG.severe("Failed to ingest ancillary file "
+            + actionFile.getAbsolutePath()
+            + " identifer was not returned from file manager");
+      }
+
+      if (relatedKey != null) {
+        metadata.addMetadata(relatedKey, identifier);
+      }
+
+      if (writeBackKeys != null) {
+        if (writeBackKeyPrefix == null) {
+          writeBackKeyPrefix = "";
+        }
+        ingestMetadata.addMetadata(writeBackKeyPrefix + CoreMetKeys.PRODUCT_ID,
+            identifier);
+        for (String writeBackKey : writeBackKeys) {
+          metadata.addMetadata(writeBackKeyPrefix + writeBackKey,
+              ingestMetadata.getAllMetadata(writeBackKey));
+        }
+      }
+
+      if (replaceDynamicKeys != null) {
+        for (String replaceDynamicKey : replaceDynamicKeys) {
+          String value = PathUtils.replaceEnvVariables(
+              metadata.getMetadata(replaceDynamicKey), metadata);
+          metadata.removeMetadata(replaceDynamicKey);
+          metadata.addMetadata(replaceDynamicKey, value);
+        }
+      }
+
+    } catch (Exception ex) {
+      LOG.severe("Failed to ingest ancillary file "
+          + actionFile.getAbsolutePath());
+      LOG.severe(ex.getMessage());
+      return false;
+    }
+
+    return true;
+  }
+
+  public void setReplaceDynamicKeys(List<String> replaceDynamicKeys) {
+    this.replaceDynamicKeys = replaceDynamicKeys;
+  }
+
+  @Required
+  public void setFileManagerUrl(String fileManagerUrl) {
+    this.fileManagerUrl = fileManagerUrl;
+  }
+
+  @Required
+  public void setDataTransferService(String dataTransferService) {
+    this.dataTransferService = dataTransferService;
+  }
+
+  public void setRelatedKey(String relatedKey) {
+    this.relatedKey = relatedKey;
+  }
+
+  public void setAncillaryMetadata(Map<String, List<String>> ancillaryMetadata) {
+    this.ancillaryMetadata = ancillaryMetadata;
+  }
+
+  @Required
+  public void setProductType(String productType) {
+    this.productType = productType;
+  }
+
+  public void setCopyKeys(List<String> copyKeys) {
+    this.copyKeys = copyKeys;
+  }
+
+  public void setWriteBackKeys(List<String> writeBackKeys) {
+    this.writeBackKeys = writeBackKeys;
+  }
+
+  public void setWriteBackKeyPrefix(String writeBackKeyPrefix) {
+    this.writeBackKeyPrefix = writeBackKeyPrefix;
+  }
+
+  public static void main(String[] args) throws Exception {
+    if (args.length != 6) {
+      System.out
+          .println("Usage: java "
+              + IngestAncillary.class.getName()
+              + " <serviceUrl> <transferServiceClass> <productFile> <fileSuffix> <relatedKey> <productType");
+      System.exit(-1);
+    }
+    IngestAncillary ingest = new IngestAncillary();
+    ingest.setFileManagerUrl(args[0]);
+    ingest.setDataTransferService(args[1]);
+    File product = new File(args[2]);
+    ingest.setFileSuffix(args[3]);
+    ingest.setRelatedKey(args[4]);
+    ingest.setProductType(args[5]);
+    Metadata metadata = new Metadata();
+    ingest.performAction(product, metadata);
+    System.out.println("Ingested " + args[5] + ": "
+        + metadata.getMetadata(args[4]));
+  }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/MimeTypeCrawlerAction.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/MimeTypeCrawlerAction.java
new file mode 100644
index 0000000..b9e8ef1
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/MimeTypeCrawlerAction.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//OODT static imports
+import static org.apache.oodt.cas.crawl.AutoDetectProductCrawler.MIME_TYPES_HIERARCHY;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JDK imports
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * Calls a {@link CrawlerAction} if this {@link File} matches the specified set
+ * of internal {@link #mimeTypes}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class MimeTypeCrawlerAction extends CrawlerAction {
+
+   private CrawlerAction actionToCall;
+   private List<String> mimeTypes;
+
+   @Override
+   public boolean performAction(File product, Metadata productMetadata)
+         throws CrawlerActionException {
+      List<String> mimeTypeHierarchy = productMetadata
+            .getAllMetadata(MIME_TYPES_HIERARCHY);
+      if (mimeTypeHierarchy == null)
+         mimeTypeHierarchy = new Vector<String>();
+      if (mimeTypes == null
+            || (mimeTypes != null && !Collections.disjoint(mimeTypes,
+                  mimeTypeHierarchy))) {
+         return this.actionToCall.performAction(product, productMetadata);
+      } else {
+         LOG.log(Level.INFO, "Skipping action (id = " + this.getId()
+               + " : description = " + this.getDescription()
+               + " - doesn't apply to current product");
+         return true;
+      }
+   }
+
+   @Override
+   public void validate() throws CrawlerActionException {
+      super.validate();
+      try {
+         Validate.notNull(actionToCall, "Must specify actionToCall");
+      } catch (Exception e) {
+         throw new CrawlerActionException(e);
+      }
+   }
+
+   @Required
+   public void setActionToCall(CrawlerAction actionToCall) {
+      this.actionToCall = actionToCall;
+      this.setDescription("Mime-type restricted version of '"
+            + this.actionToCall.getId() + "' CrawlerAction");
+      this.setPhases(this.actionToCall.getPhases());
+   }
+
+   public List<String> getMimeTypes() {
+      return mimeTypes;
+   }
+
+   public void setMimeTypes(List<String> mimeTypes) {
+      this.mimeTypes = mimeTypes;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/MoveFile.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/MoveFile.java
new file mode 100644
index 0000000..462d598
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/MoveFile.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Level;
+
+//OODT imports
+import org.apache.commons.lang.Validate;
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+//File.Utils import to handle NFS mounted directories
+import org.apache.commons.io.FileUtils;
+
+
+/**
+ * Moves a {@link Product} file as a reponse to a Crawler lifecycle phase
+ * 
+ * @author bfoster (Brian Foster)
+ * @author mattmann (Chris Mattmann)
+ */
+public class MoveFile extends CrawlerAction {
+
+   private String file;
+   private String toDir;
+   private String fileExtension;
+   private boolean createToDir;
+
+   public MoveFile() {
+      super();
+      this.createToDir = false;
+   }
+
+   public boolean performAction(File product, Metadata productMetadata)
+         throws CrawlerActionException {
+      String mvFile = file;
+      try {
+         if (mvFile == null) {
+            mvFile = product.getAbsolutePath();
+            if (this.fileExtension != null)
+               mvFile += "." + this.fileExtension;
+         }
+         File srcFile = new File(mvFile);
+         File toFile = new File(toDir + "/" + srcFile.getName());
+         if (createToDir)
+            toFile.getParentFile().mkdirs();
+         LOG.log(Level.INFO, "Moving file " + srcFile.getAbsolutePath()
+               + " to " + toFile.getAbsolutePath());
+         if(!srcFile.renameTo(toFile)) {//If the file failed to copy
+        	 LOG.log(Level.INFO, "Moving failed, possibly because ingest dir is nfs mounted. Retrying to move " + srcFile.getAbsolutePath()
+                     + " to " + toFile.getAbsolutePath());
+        	 FileUtils.copyFileToDirectory(srcFile, toFile.getParentFile());
+        	 FileUtils.forceDelete(srcFile); //Need to delete the old file
+        	 return true; //File copied on second attempt
+         }
+         else
+        	 return true; //File copied
+      } catch (Exception e) {
+         throw new CrawlerActionException("Failed to move file from " + mvFile
+               + " to " + this.toDir + " : " + e.getMessage());
+      }
+   }
+
+   @Override
+   public void validate() throws CrawlerActionException {
+      super.validate();
+      try {
+         Validate.isTrue(file == null || fileExtension == null,
+               "Must specify either file or fileExtension");
+      } catch (Exception e) {
+         throw new CrawlerActionException(e);
+      }
+   }
+
+   public void setCreateToDir(boolean createToDir) {
+      this.createToDir = createToDir;
+   }
+
+   public void setFile(String file) {
+      this.file = file;
+   }
+
+   @Required
+   public void setToDir(String toDir) {
+      this.toDir = toDir;
+   }
+
+   public String getToDir() {
+      return toDir;
+   }
+
+   public void setFileExtension(String fileExtension) {
+      this.fileExtension = fileExtension;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/TernaryAction.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/TernaryAction.java
new file mode 100755
index 0000000..8c496e2
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/TernaryAction.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.action.CrawlerAction;
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * While branching seems more along the lines of a workflow deal having support
+ * for decisions based on success or failure of an action can help support
+ * slightly more complex ingest scenarios. Since an action returns a true or
+ * false this action could be as simple as taking one action as a condition
+ * action and then running either a success or failure action. This action
+ * should allow the success or failure action to remain unspecified.
+ * 
+ * @since OODT-36
+ * @author pramirez (Paul Ramirez)
+ */
+public class TernaryAction extends CrawlerAction {
+   private CrawlerAction conditionAction;
+   private CrawlerAction successAction;
+   private CrawlerAction failureAction;
+
+   @Override
+   public boolean performAction(File product, Metadata metadata)
+         throws CrawlerActionException {
+      LOG.info("Performing action (id = " + conditionAction.getId()
+            + " : description = " + conditionAction.getDescription() + ")");
+      boolean passedCondition = conditionAction
+            .performAction(product, metadata);
+      if (passedCondition) {
+         LOG.info("Performing action (id = " + successAction.getId()
+               + " : description = " + successAction.getDescription() + ")");
+         return (successAction == null) ? true : successAction.performAction(
+               product, metadata);
+      } else {
+         LOG.info("Performing action (id = " + failureAction.getId()
+               + " : description = " + failureAction.getDescription() + ")");
+         return (failureAction == null) ? true : failureAction.performAction(
+               product, metadata);
+      }
+   }
+
+   public void setConditionAction(CrawlerAction conditionAction) {
+      this.conditionAction = conditionAction;
+   }
+
+   public void setSuccessAction(CrawlerAction successAction) {
+      this.successAction = successAction;
+   }
+
+   public void setFailureAction(CrawlerAction failureAction) {
+      this.failureAction = failureAction;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/ToggleAction.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/ToggleAction.java
new file mode 100644
index 0000000..3a7fc61
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/ToggleAction.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+import java.util.logging.Level;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * Allows for cases where there are one of two (or more) actions which needs to
+ * run. For example: sometimes the same file types have different checksum files
+ * associated with it, this allows for either case.
+ * 
+ * @author pramirez (Paul Ramirez)
+ */
+public class ToggleAction extends CrawlerAction {
+
+   private List<Toggle> toggles;
+   private boolean shortCircuit;
+
+   @Override
+   public boolean performAction(File product, Metadata productMetadata)
+         throws CrawlerActionException {
+      if (this.toggles != null && this.toggles.size() > 0) {
+         boolean globalSuccess = false;
+         for (Toggle toggle : this.toggles) {
+            CrawlerAction currentAction = null;
+            try {
+               if (toggle.isOn(product, productMetadata)
+                     && (currentAction = toggle.getCrawlerAction())
+                           .performAction(product, productMetadata)) {
+                  globalSuccess = true;
+                  if (this.shortCircuit)
+                     return true;
+               }
+            } catch (Exception e) {
+               LOG.log(Level.WARNING, "Failed to run toggle action '"
+                     + (currentAction != null ? currentAction.getId() : null)
+                     + "' : " + e.getMessage());
+            }
+         }
+         return globalSuccess;
+      } else {
+         return true;
+      }
+   }
+
+   public void setToggles(List<Toggle> toggles) {
+      this.toggles = toggles;
+   }
+
+   public void setShortCircuit(boolean shortCircuit) {
+      this.shortCircuit = shortCircuit;
+   }
+
+   public abstract class Toggle {
+
+      private CrawlerAction action;
+
+      public void setCrawlerAction(CrawlerAction action) {
+         this.action = action;
+      }
+
+      public CrawlerAction getCrawlerAction() {
+         return this.action;
+      }
+
+      public abstract boolean isOn(File product, Metadata productMetadata);
+
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/WorkflowMgrStatusUpdate.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/WorkflowMgrStatusUpdate.java
new file mode 100644
index 0000000..652a875
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/action/WorkflowMgrStatusUpdate.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.action;
+
+//JDK imports
+import java.io.File;
+import java.net.URL;
+
+//OODT imports
+import org.apache.commons.lang.Validate;
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * Updates the Workflow Manager and notifies it that the crawled {@link Product}
+ * has been ingested successfully.
+ * 
+ * @author bfoster (Brian Foster)
+ * @author mattmann (Chris Mattmann)
+ */
+public class WorkflowMgrStatusUpdate extends CrawlerAction implements
+      CoreMetKeys {
+
+   private String ingestSuffix;
+   private String workflowMgrUrl;
+
+   public WorkflowMgrStatusUpdate() {
+      ingestSuffix = "Ingest";
+   }
+
+   public boolean performAction(File product, Metadata productMetadata)
+         throws CrawlerActionException {
+      try {
+         XmlRpcWorkflowManagerClient wClient = new XmlRpcWorkflowManagerClient(
+               new URL(this.workflowMgrUrl));
+         String ingestSuffix = this.ingestSuffix;
+         return wClient.sendEvent(productMetadata.getMetadata(PRODUCT_TYPE)
+               + ingestSuffix, productMetadata);
+      } catch (Exception e) {
+         throw new CrawlerActionException(
+               "Failed to update workflow manager : " + e.getMessage());
+      }
+   }
+
+   @Override
+   public void validate() throws CrawlerActionException {
+      super.validate();
+      try {
+         Validate.notNull(ingestSuffix, "Must specify ingestSuffix");
+      } catch (Exception e) {
+         throw new CrawlerActionException(e);
+      }
+   }
+
+   public void setIngestSuffix(String ingestSuffix) {
+      this.ingestSuffix = ingestSuffix;
+   }
+
+   @Required
+   public void setWorkflowMgrUrl(String workflowMgrUrl) {
+      this.workflowMgrUrl = workflowMgrUrl;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/action/CrawlerLauncherCliAction.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/action/CrawlerLauncherCliAction.java
new file mode 100644
index 0000000..cce8ea8
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/action/CrawlerLauncherCliAction.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.crawl.ProductCrawler;
+import org.apache.oodt.cas.crawl.daemon.CrawlDaemon;
+
+//Spring imports
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+/**
+ * A {@link CmdLineAction} which is responsible for launching crawlers.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class CrawlerLauncherCliAction extends CmdLineAction {
+
+   private String beanRepo;
+   private String crawlerId;
+
+   public CrawlerLauncherCliAction() {
+      this.beanRepo = System.getProperty("org.apache.oodt.cas.crawl.bean.repo",
+            "classpath:/org/apache/oodt/cas/crawl/crawler-config.xml");
+   }
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+
+      FileSystemXmlApplicationContext appContext = new FileSystemXmlApplicationContext(
+            this.beanRepo);
+
+      try {
+         ProductCrawler pc = (ProductCrawler) appContext
+               .getBean(crawlerId != null ? crawlerId : getName());
+         pc.setApplicationContext(appContext);
+         if (pc.getDaemonPort() != -1 && pc.getDaemonWait() != -1) {
+            new CrawlDaemon(pc.getDaemonWait(), pc, pc.getDaemonPort())
+                  .startCrawling();
+         } else {
+            pc.crawl();
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to launch crawler : "
+               + e.getMessage(), e);
+      }
+   }
+
+   public void setCrawlerId(String crawlerId) {
+      this.crawlerId = crawlerId;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/option/handler/BeanInfoHandler.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/option/handler/BeanInfoHandler.java
new file mode 100644
index 0000000..ec86875
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/option/handler/BeanInfoHandler.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.cli.option.handler;
+
+//JDK imports
+import java.io.OutputStream;
+
+//OODT imports
+import org.apache.oodt.cas.cli.option.handler.CmdLineOptionHandler;
+
+//Spring imports
+import org.springframework.context.ApplicationContext;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public abstract class BeanInfoHandler implements CmdLineOptionHandler {
+
+    private OutputStream outStream;
+    private ApplicationContext applicationContext;
+
+    public BeanInfoHandler() {
+        this.outStream = System.out;
+    }
+
+    public ApplicationContext getApplicationContext() {
+        return applicationContext;
+    }
+
+    public void setApplicationContext(ApplicationContext applicationContext) {
+        this.applicationContext = applicationContext;
+    }
+
+    public OutputStream getOutStream() {
+        return this.outStream;
+    }
+
+    public void setOutStream(OutputStream outStream) {
+        this.outStream = outStream;
+    }
+
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/option/handler/CrawlerActionInfoHandler.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/option/handler/CrawlerActionInfoHandler.java
new file mode 100644
index 0000000..656e2c2
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/option/handler/CrawlerActionInfoHandler.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.cli.option.handler;
+
+//JDK imports
+import java.io.PrintStream;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.crawl.action.CrawlerAction;
+import org.apache.oodt.cas.crawl.action.MimeTypeCrawlerAction;
+
+/**
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class CrawlerActionInfoHandler extends BeanInfoHandler {
+
+   @Override
+   public void initialize(CmdLineOption option) {
+      // Do nothing.
+   }
+
+   @Override
+   public void handleOption(CmdLineAction selectedAction, CmdLineOptionInstance optionInstance) {
+      String[] actionIds = this.getApplicationContext().getBeanNamesForType(
+            CrawlerAction.class);
+    PrintStream ps = new PrintStream(this.getOutStream());
+    ps.println("Actions:");
+    for (String actionId : actionIds) {
+        CrawlerAction ca = (CrawlerAction) this.getApplicationContext()
+                .getBean(actionId);
+        ps.println("  Action:");
+        ps.println("    Id: " + ca.getId());
+        ps.println("    Description: " + ca.getDescription());
+        ps.println("    Phases: " + ca.getPhases());
+        if (ca instanceof MimeTypeCrawlerAction)
+            ps.println("    MimeTypes: " 
+                    + ((MimeTypeCrawlerAction) ca).getMimeTypes());
+        ps.println();
+    }
+    ps.close();      
+   }
+
+   @Override
+   public String getHelp(CmdLineOption option) {
+      return null;
+   }
+
+   @Override
+   public String getArgDescription(CmdLineAction action, CmdLineOption option) {
+      return null;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/option/handler/CrawlerBeansPropHandler.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/option/handler/CrawlerBeansPropHandler.java
new file mode 100644
index 0000000..804b89f
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/option/handler/CrawlerBeansPropHandler.java
@@ -0,0 +1,80 @@
+/*  
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.cli.option.handler;
+
+//JDK imports 
+import java.util.List;
+
+//OODT imports 
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.cli.option.handler.CmdLineOptionHandler;
+import org.apache.oodt.cas.crawl.util.ActionBeanProperties;
+
+/** 
+ * A {@link CmdLineOptionHandler} which adds bean properties to
+ * {@link ActionBeanProperties} so that they can then be injected into 
+ * {@link ProductCrawler}s and {@link CrawlerAction}s.
+ *
+ * @author bfoster (Brian Foster) 
+ */
+
+public class CrawlerBeansPropHandler implements CmdLineOptionHandler {
+
+   private List<String> properties;
+
+   @Override
+   public void initialize(CmdLineOption option) {
+      // Do nothing.
+   }
+
+   @Override
+   public void handleOption(CmdLineAction selectedAction,
+         CmdLineOptionInstance optionInstance) {
+      for (String beanProperty : properties) {
+         if (optionInstance.getValues().size() > 1) {
+            for (int i = 0; i < optionInstance.getValues().size(); i++) {
+               ActionBeanProperties.setProperty(beanProperty + "[" + i + "]",
+                     optionInstance.getValues().get(i));
+            }
+         } else if (!optionInstance.getValues().isEmpty()) {
+            ActionBeanProperties.setProperty(beanProperty,
+                  optionInstance.getValues().get(0));
+         } else {
+            throw new RuntimeException(
+                  CrawlerBeansPropHandler.class.getCanonicalName()
+                        + " can't apply option '" + optionInstance.getOption()
+                        + "' since it has no value");
+         }
+      }
+   }
+
+   @Override
+   public String getHelp(CmdLineOption option) {
+      return "Set the following bean properties: " + properties;
+   }
+
+   @Override
+   public String getArgDescription(CmdLineAction action, CmdLineOption option) {
+      return null;
+   }
+
+   public void setProperties(List<String> properties) {
+      this.properties = properties;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/option/handler/PreconditionInfoHandler.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/option/handler/PreconditionInfoHandler.java
new file mode 100644
index 0000000..0916cae
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/cli/option/handler/PreconditionInfoHandler.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.cli.option.handler;
+
+//JDK imports
+import java.io.PrintStream;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.option.CmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+import org.apache.oodt.cas.metadata.preconditions.PreConditionComparator;
+
+/**
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class PreconditionInfoHandler extends BeanInfoHandler {
+
+   @Override
+   public void initialize(CmdLineOption option) {
+      // Do nothing.
+   }
+
+   @Override
+   public void handleOption(CmdLineAction selectedAction,
+         CmdLineOptionInstance optionInstance) {
+      String[] preCondIds = this.getApplicationContext().getBeanNamesForType(
+            PreConditionComparator.class);
+      PrintStream ps = new PrintStream(this.getOutStream());
+      ps.println("PreConditionComparators:");
+      for (String preCondId : preCondIds) {
+         PreConditionComparator<?> preCond = (PreConditionComparator<?>) this
+               .getApplicationContext().getBean(preCondId);
+         ps.println("  PreCondComparator:");
+         ps.println("    Id: " + preCondId);
+         ps.println("    Description: " + preCond.getDescription());
+         ps.println();
+      }
+      ps.close();
+   }
+
+   @Override
+   public String getHelp(CmdLineOption option) {
+      return null;
+   }
+
+   @Override
+   public String getArgDescription(CmdLineAction action, CmdLineOption option) {
+      return null;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/comparator/FilemgrUniquenessCheckComparator.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/comparator/FilemgrUniquenessCheckComparator.java
new file mode 100644
index 0000000..c172305
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/comparator/FilemgrUniquenessCheckComparator.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.crawl.comparator;
+
+//JDK imports
+import java.io.File;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.exceptions.PreconditionComparatorException;
+import org.apache.oodt.cas.metadata.preconditions.PreConditionComparator;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A pre-ingest, Metadata extractor level comparator that checks whether a
+ * product exists before generating metadata for it.
+ * </p>.
+ */
+public class FilemgrUniquenessCheckComparator extends
+        PreConditionComparator<Boolean> {
+
+    private String filemgrUrl;
+
+    @Override
+    protected int performCheck(File product, Boolean compareItem)
+            throws PreconditionComparatorException {
+        try {
+            boolean returnVal = new XmlRpcFileManagerClient(new URL(
+                    this.filemgrUrl)).hasProduct(product.getName());
+            return new Boolean(returnVal).compareTo(compareItem);
+        } catch (Exception e) {
+            throw new PreconditionComparatorException(
+                    "Failed to check for product " + product + " : "
+                            + e.getMessage());
+        }
+    }
+
+    @Required
+    public void setFilemgrUrl(String filemgrUrl) {
+        this.filemgrUrl = filemgrUrl;
+    }
+
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/config/ProductCrawlerBean.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/config/ProductCrawlerBean.java
new file mode 100644
index 0000000..47b56c5
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/config/ProductCrawlerBean.java
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.config;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.commons.spring.SpringSetIdInjectionType;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+import org.springframework.context.ApplicationContext;
+
+/** 
+ * Turns a {@link ProductCrawler} into a Spring-configurable entity.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public abstract class ProductCrawlerBean implements
+      SpringSetIdInjectionType, CoreMetKeys {
+
+    private HashSet<String> requiredMetadata;
+
+    private List<String> actionIds;
+
+    private String filemgrUrl;
+
+    private String clientTransferer;
+
+    private boolean noRecur, crawlForDirs, skipIngest;
+
+    private int daemonWait, daemonPort;
+
+    private String productPath;
+
+    private ApplicationContext applicationContext;
+
+    private String id;
+
+    private Metadata globalMetadata;
+    
+    public ProductCrawlerBean() {
+        this.actionIds = new LinkedList<String>();
+        this.requiredMetadata = new HashSet<String>();
+        this.requiredMetadata.add(PRODUCT_TYPE);
+        this.requiredMetadata.add(FILENAME);
+        this.requiredMetadata.add(FILE_LOCATION);
+        this.noRecur = false;
+        this.crawlForDirs = false;
+        this.skipIngest = false;
+        this.daemonPort = -1;
+        this.daemonWait = -1;
+        this.globalMetadata = new Metadata();
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setApplicationContext(ApplicationContext applicationContext) {
+        this.applicationContext = applicationContext;
+    }
+
+    public ApplicationContext getApplicationContext() {
+        return this.applicationContext;
+    }
+
+    public void setActionIds(List<String> actionIds) {
+        this.actionIds = actionIds;
+    }
+
+    public List<String> getActionIds() {
+        return this.actionIds;
+    }
+
+    public void setRequiredMetadata(List<String> requiredMetadata) {
+    	this.requiredMetadata.addAll(requiredMetadata);
+    }
+
+    @Required
+    public void setFilemgrUrl(String filemgrUrl) throws MalformedURLException {
+        this.filemgrUrl = filemgrUrl;
+    }
+
+    public String getFilemgrUrl() {
+        return this.filemgrUrl;
+    }
+
+    public List<String> getRequiredMetadata() {
+        return new LinkedList<String>(this.requiredMetadata);
+    }
+
+    @Required
+    public void setClientTransferer(String clientTransferer) {
+        this.clientTransferer = clientTransferer;
+    }
+
+    public String getClientTransferer() {
+        return this.clientTransferer;
+    }
+
+    public void setNoRecur(boolean noRecur) {
+        this.noRecur = noRecur;
+    }
+
+    public boolean isNoRecur() {
+        return this.noRecur;
+    }
+
+    public void setCrawlForDirs(boolean crawlForDirs) {
+        this.crawlForDirs = crawlForDirs;
+    }
+
+    public boolean isCrawlForDirs() {
+        return this.crawlForDirs;
+    }
+    
+    public void setSkipIngest(boolean skipIngest) {
+        this.skipIngest = skipIngest;
+    }
+    
+    public boolean isSkipIngest() {
+        return this.skipIngest;
+    }
+
+    public void setDaemonWait(int daemonWait) {
+        this.daemonWait = daemonWait;
+    }
+
+    public int getDaemonWait() {
+        return this.daemonWait;
+    }
+
+    public void setDaemonPort(int daemonPort) {
+        this.daemonPort = daemonPort;
+    }
+
+    public int getDaemonPort() {
+        return this.daemonPort;
+    }
+
+    @Required
+    public void setProductPath(String productPath) {
+        this.productPath = productPath;
+    }
+
+    public String getProductPath() {
+        return this.productPath;
+    }
+
+	public Metadata getGlobalMetadata() {
+		return globalMetadata;
+	}
+
+	public void setGlobalMetadata(Metadata globalMetadata) {
+		this.globalMetadata.addMetadata(globalMetadata.getHashtable());
+	}
+
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/daemon/CrawlDaemon.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/daemon/CrawlDaemon.java
new file mode 100644
index 0000000..0f3ff4e
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/daemon/CrawlDaemon.java
@@ -0,0 +1,189 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.crawl.daemon;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.ProductCrawler;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//APACHE imports
+import org.apache.xmlrpc.WebServer;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A daemon utility class for {@link ProductCrawler}s that allows a regular
+ * ProductCrawler to be run as a daemon, and statistics about crawling to be
+ * kept. The daemon is an XML-RPC accessible web service.
+ * </p>.
+ */
+public class CrawlDaemon {
+
+    /* our log stream */
+    private static Logger LOG = Logger.getLogger(CrawlDaemon.class.getName());
+
+    /* are we running or not? */
+    private boolean running = true;
+
+    /* wait interval in seconds between crawls */
+    private long waitInterval = -1;
+
+    /* number of times that the crawler has been called */
+    private int numCrawls = 0;
+
+    /* the amount of miliseconds spent crawling */
+    private long milisCrawling = 0L;
+
+    /* the product crawler that this daemon should use */
+    private ProductCrawler crawler = null;
+
+    /* the port that this crawl daemon should run on */
+    private int daemonPort = 9999;
+
+    public CrawlDaemon(int wait, ProductCrawler crawler, int port) {
+        this.waitInterval = wait;
+        this.crawler = crawler;
+        this.daemonPort = port;
+    }
+
+    public void startCrawling() {
+        // start up the web server
+        WebServer server = new WebServer(this.daemonPort);
+        server.addHandler("crawldaemon", this);
+        server.start();
+
+        LOG.log(Level.INFO, "Crawl Daemon started by "
+                + System.getProperty("user.name", "unknown"));
+
+        while (running) {
+            // okay, time to crawl
+            long timeBefore = System.currentTimeMillis();
+            crawler.crawl();
+            long timeAfter = System.currentTimeMillis();
+            milisCrawling += (timeAfter - timeBefore);
+            numCrawls++;
+
+            LOG.log(Level.INFO, "Sleeping for: [" + waitInterval + "] seconds");
+            // take a nap
+            try {
+                Thread.currentThread().sleep(waitInterval * 1000);
+            } catch (InterruptedException ignore) {
+            }
+        }
+
+        LOG.log(Level.INFO, "Crawl Daemon: Shutting down gracefully");
+        LOG.log(Level.INFO, "Num Crawls: [" + this.numCrawls + "]");
+        LOG.log(Level.INFO, "Total time spent crawling: ["
+                + (this.milisCrawling / 1000.0) + "] seconds");
+        LOG.log(Level.INFO, "Average Crawl Time: ["
+                + (this.getAverageCrawlTime() / 1000.0) + "] seconds");
+        server.shutdown();
+    }
+
+    public double getAverageCrawlTime() {
+        return (1.0 * milisCrawling) / (1.0 * numCrawls);
+    }
+
+    /**
+     * @return the crawler
+     */
+    public ProductCrawler getCrawler() {
+        return crawler;
+    }
+
+    /**
+     * @param crawler
+     *            the crawler to set
+     */
+    public void setCrawler(ProductCrawler crawler) {
+        this.crawler = crawler;
+    }
+
+    /**
+     * @return the milisCrawling
+     */
+    public int getMilisCrawling() {
+        return (int) milisCrawling;
+    }
+
+    /**
+     * @param milisCrawling
+     *            the milisCrawling to set
+     */
+    public void setMilisCrawling(long milisCrawling) {
+        this.milisCrawling = milisCrawling;
+    }
+
+    /**
+     * @return the numCrawls
+     */
+    public int getNumCrawls() {
+        return numCrawls;
+    }
+
+    /**
+     * @param numCrawls
+     *            the numCrawls to set
+     */
+    public void setNumCrawls(int numCrawls) {
+        this.numCrawls = numCrawls;
+    }
+
+    /**
+     * @return the running
+     */
+    public boolean isRunning() {
+        return running;
+    }
+
+    /**
+     * @param running
+     *            the running to set
+     */
+    public boolean stop() {
+        this.running = false;
+        return this.running;
+    }
+
+    /**
+     * @return the waitInterval
+     */
+    public int getWaitInterval() {
+        return (int) waitInterval;
+    }
+
+    /**
+     * @param waitInterval
+     *            the waitInterval to set
+     */
+    public void setWaitInterval(long waitInterval) {
+        this.waitInterval = waitInterval;
+    }
+
+    private static void main(String[] args) throws InstantiationException {
+        throw new InstantiationException(
+                "Don't call a crawl daemon by its main function!");
+    }
+
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/daemon/CrawlDaemonController.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/daemon/CrawlDaemonController.java
new file mode 100644
index 0000000..1628fa5
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/daemon/CrawlDaemonController.java
@@ -0,0 +1,218 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.crawl.daemon;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlException;
+
+//JDK imports
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Vector;
+
+//APACHE imports
+import org.apache.xmlrpc.XmlRpcClient;
+import org.apache.xmlrpc.XmlRpcException;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Controller class for the Crawl Daemons
+ * </p>.
+ */
+public class CrawlDaemonController {
+
+    /* our xml rpc client */
+    private XmlRpcClient client = null;
+
+    public CrawlDaemonController(String crawlUrlStr)
+            throws InstantiationException {
+        try {
+            client = new XmlRpcClient(new URL(crawlUrlStr));
+        } catch (MalformedURLException e) {
+            throw new InstantiationException(e.getMessage());
+        }
+    }
+
+    public double getAverageCrawlTime() throws CrawlException {
+        Vector argList = new Vector();
+
+        double avgCrawlTime = -1.0d;
+
+        try {
+            avgCrawlTime = ((Double) client.execute(
+                    "crawldaemon.getAverageCrawlTime", argList)).doubleValue();
+        } catch (XmlRpcException e) {
+            throw new CrawlException(e.getMessage());
+        } catch (IOException e) {
+            throw new CrawlException(e.getMessage());
+        }
+
+        return avgCrawlTime;
+    }
+
+    public int getMilisCrawling() throws CrawlException {
+        Vector argList = new Vector();
+
+        int milisCrawling = -1;
+
+        try {
+            milisCrawling = ((Integer) client.execute(
+                    "crawldaemon.getMilisCrawling", argList)).intValue();
+        } catch (XmlRpcException e) {
+            throw new CrawlException(e.getMessage());
+        } catch (IOException e) {
+            throw new CrawlException(e.getMessage());
+        }
+
+        return milisCrawling;
+    }
+
+    public int getWaitInterval() throws CrawlException {
+        Vector argList = new Vector();
+
+        int waitInterval = -1;
+
+        try {
+            waitInterval = ((Integer) client.execute(
+                    "crawldaemon.getWaitInterval", argList)).intValue();
+        } catch (XmlRpcException e) {
+            throw new CrawlException(e.getMessage());
+        } catch (IOException e) {
+            throw new CrawlException(e.getMessage());
+        }
+
+        return waitInterval;
+    }
+
+    public int getNumCrawls() throws CrawlException {
+        Vector argList = new Vector();
+        int numCrawls = -1;
+
+        try {
+            numCrawls = ((Integer) client.execute("crawldaemon.getNumCrawls",
+                    argList)).intValue();
+        } catch (XmlRpcException e) {
+            throw new CrawlException(e.getMessage());
+        } catch (IOException e) {
+            throw new CrawlException(e.getMessage());
+        }
+
+        return numCrawls;
+
+    }
+
+    public boolean isRunning() throws CrawlException {
+        Vector argList = new Vector();
+        boolean running = false;
+
+        try {
+            running = ((Boolean) client.execute("crawldaemon.isRunning",
+                    argList)).booleanValue();
+        } catch (XmlRpcException e) {
+            throw new CrawlException(e.getMessage());
+        } catch (IOException e) {
+            throw new CrawlException(e.getMessage());
+        }
+
+        return running;
+    }
+
+    public void stop() throws CrawlException {
+        Vector argList = new Vector();
+        boolean running = false;
+
+        try {
+            running = ((Boolean) client.execute("crawldaemon.stop", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            throw new CrawlException(e.getMessage());
+        } catch (IOException e) {
+            throw new CrawlException(e.getMessage());
+        }
+
+        if (running) {
+            throw new CrawlException("Stop attempt failed: crawl daemon: ["
+                    + this.client.getURL() + "] still running");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        String avgCrawlOperation = "--getAverageCrawlTime\n";
+        String getMilisCrawlOperation = "--getMilisCrawling\n";
+        String getNumCrawlsOperation = "--getNumCrawls\n";
+        String getWaitIntervalOperation = "--getWaitInterval\n";
+        String isRunningOperation = "--isRunning\n";
+        String stopOperation = "--stop\n";
+
+        String usage = "CrawlController --url <url to xml rpc service> --operation [<operation> [params]]\n"
+                + "operations:\n"
+                + avgCrawlOperation
+                + getMilisCrawlOperation
+                + getNumCrawlsOperation
+                + getWaitIntervalOperation
+                + isRunningOperation + stopOperation;
+
+        String operation = null, url = null;
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--operation")) {
+                operation = args[++i];
+            } else if (args[i].equals("--url")) {
+                url = args[++i];
+            }
+        }
+
+        if (operation == null) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        // create the controller
+        CrawlDaemonController controller = new CrawlDaemonController(url);
+
+        if (operation.equals("--getAverageCrawlTime")) {
+            double avgCrawlTime = controller.getAverageCrawlTime();
+            System.out.println("Average Crawl Time: [" + avgCrawlTime + "]");
+        } else if (operation.equals("--getMilisCrawling")) {
+            int crawlTime = controller.getMilisCrawling();
+            System.out.println("Total Crawl Time: [" + crawlTime
+                    + "] miliseconds");
+        } else if (operation.equals("--getNumCrawls")) {
+            int numCrawls = controller.getNumCrawls();
+            System.out.println("Num Crawls: [" + numCrawls + "]");
+        } else if (operation.equals("--getWaitInterval")) {
+            int waitInterval = controller.getWaitInterval();
+            System.out.println("Wait Interval: [" + waitInterval + "]");
+        } else if (operation.equals("--isRunning")) {
+            boolean running = controller.isRunning();
+            System.out.println(running ? "Yes" : "No");
+        } else if (operation.equals("--stop")) {
+            controller.stop();
+            System.out.println("Crawl Daemon: [" + controller.client.getURL()
+                    + "]: shutdown successful");
+        } else
+            throw new IllegalArgumentException("Unknown Operation!");
+
+    }
+
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/status/IngestStatus.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/status/IngestStatus.java
new file mode 100644
index 0000000..0b6110a
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/status/IngestStatus.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.crawl.status;
+
+//JDK imports
+import java.io.File;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Product's Ingest Status
+ * </p>.
+ */
+public interface IngestStatus {
+
+	public static enum Result {
+		SUCCESS, FAILURE, SKIPPED, PRECONDS_FAILED;
+	}
+	
+	public File getProduct();
+	
+	public Result getResult();
+	
+	public String getMessage();
+	
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/structs/exceptions/CrawlException.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/structs/exceptions/CrawlException.java
new file mode 100644
index 0000000..f48f9c2
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/structs/exceptions/CrawlException.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.crawl.structs.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A general exception thrown by a component in the crawling framework
+ * </p>.
+ */
+public class CrawlException extends Exception {
+
+    // serial version UID
+    private static final long serialVersionUID = 4271047772572710953L;
+
+    /**
+     * 
+     */
+    public CrawlException() {
+        super();
+        // TODO Auto-generated constructor stub
+    }
+
+    /**
+     * @param arg0
+     * @param arg1
+     */
+    public CrawlException(String arg0, Throwable arg1) {
+        super(arg0, arg1);
+        // TODO Auto-generated constructor stub
+    }
+
+    /**
+     * @param arg0
+     */
+    public CrawlException(String arg0) {
+        super(arg0);
+        // TODO Auto-generated constructor stub
+    }
+
+    /**
+     * @param arg0
+     */
+    public CrawlException(Throwable arg0) {
+        super(arg0);
+        // TODO Auto-generated constructor stub
+    }
+
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/structs/exceptions/CrawlerActionException.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/structs/exceptions/CrawlerActionException.java
new file mode 100644
index 0000000..81f34b9
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/structs/exceptions/CrawlerActionException.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.structs.exceptions;
+
+/**
+ * An Exception thrown by a {@link CrawlerAction}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class CrawlerActionException extends Exception {
+
+    private static final long serialVersionUID = -218864170546125844L;
+
+    public CrawlerActionException() {
+        super();
+    }
+
+    public CrawlerActionException(String msg) {
+        super(msg);
+    }
+
+    public CrawlerActionException(Throwable t) {
+       super(t);
+    }
+
+    public CrawlerActionException(String msg, Throwable t) {
+       super(msg, t);
+    }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/typedetection/MetExtractorSpec.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/typedetection/MetExtractorSpec.java
new file mode 100644
index 0000000..7c81dfe
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/typedetection/MetExtractorSpec.java
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.crawl.typedetection;
+
+// OODT imports
+import java.io.FileNotFoundException;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.oodt.cas.metadata.MetExtractor;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A specification for instantiating {@link MetExtractor}s
+ * </p>.
+ */
+public class MetExtractorSpec {
+
+    private MetExtractor metExtractor;
+
+    private List<String> preCondComparatorIds;
+
+    private String configFile;
+
+    /**
+     * Default Constructor.
+     */
+    public MetExtractorSpec() {
+    }
+
+    /**
+     * Constructs a new spec with the given parameters.
+     * 
+     * @param className
+     *            The name of the {@link MetExtractor} impl class.
+     * @param configFile
+     *            The name of the configuration file used to configure This
+     *            {@link MetExtractor} described by this class.
+     * @throws InstantiationException
+     */
+    public MetExtractorSpec(String className, String configFile,
+            List<String> preCondComparatorIds) throws InstantiationException {
+        try {
+            this.setMetExtractor(className);
+            this.setExtractorConfigFile(configFile);
+            this.preCondComparatorIds = preCondComparatorIds;
+        } catch (Exception e) {
+            throw new InstantiationException(
+                  "Failed to create MetExtractorSpec object : "
+                            + e.getMessage());
+        }
+    }
+
+    /**
+     * @return the extractorClassName
+     */
+    public MetExtractor getMetExtractor() {
+        return this.metExtractor;
+    }
+
+    /**
+     * @param extractorClassName
+     *            the extractorClassName to set
+     * @throws ClassNotFoundException
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     * @throws MetExtractionException
+     */
+    public void setMetExtractor(String extractorClassName)
+            throws InstantiationException, IllegalAccessException,
+            ClassNotFoundException, MetExtractionException {
+        this.metExtractor = (MetExtractor) Class.forName(extractorClassName)
+                .newInstance();
+        if (this.configFile != null)
+            this.metExtractor.setConfigFile(this.configFile);
+    }
+
+    /**
+     * @param extractorConfigFile
+     *            the extractorConfigFile to set
+     * @throws MetExtractionException
+     */
+    public void setExtractorConfigFile(String extractorConfigFile)
+            throws MetExtractionException {
+        this.configFile = extractorConfigFile;
+        if (this.configFile != null && this.metExtractor != null)
+            this.metExtractor.setConfigFile(this.configFile);
+    }
+
+    /**
+     * @return List<Preconiditions> specified in the extractor preconditions
+     *         file
+     */
+    public List<String> getPreCondComparatorIds() {
+        return this.preCondComparatorIds != null ? this.preCondComparatorIds
+                : new LinkedList<String>();
+    }
+
+    /**
+     * @param preconditionsFile
+     *            The extractor preconditions file
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     * @throws ClassNotFoundException
+     * @throws FileNotFoundException
+     */
+    public void setPreConditionComparatorIds(List<String> preCondComparatorIds) {
+        this.preCondComparatorIds = preCondComparatorIds;
+    }
+
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/typedetection/MimeExtractorConfigMetKeys.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/typedetection/MimeExtractorConfigMetKeys.java
new file mode 100644
index 0000000..fa8ca4d
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/typedetection/MimeExtractorConfigMetKeys.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.crawl.typedetection;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * XML Config file Met Keys for the {@link MimeExtractorConfig}
+ * </p>.
+ */
+public interface MimeExtractorConfigMetKeys {
+
+    public static final String MAGIC_ATTR = "magic";
+
+    public static final String MIME_REPO_ATTR = "mimeRepo";
+
+    public static final String DEFAULT_EXTRACTOR_TAG = "default";
+
+    public static final String EXTRACTOR_TAG = "extractor";
+
+    public static final String NAMING_CONVENTION_TAG = "namingConvention";
+
+    public static final String EXTRACTOR_CLASS_TAG = "extractorClass";
+
+    public static final String EXTRACTOR_CONFIG_TAG = "config";
+
+    public static final String EXTRACTOR_PRECONDITIONS_TAG = "preconditions";
+
+    public static final String MIME_TAG = "mime";
+
+    public static final String MIME_TYPE_ATTR = "type";
+
+    public static final String CLASS_ATTR = "class";
+
+    public static final String FILE_ATTR = "file";
+
+    public static final String ENV_REPLACE_ATTR = "envReplace";
+    
+    public static final String PRECONDITION_COMPARATORS_TAG = "preCondComparators";
+    
+    public static final String PRECONDITION_COMPARATOR_TAG = "preCondComparator";
+    
+    public static final String ID_ATTR = "id";
+    	
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/typedetection/MimeExtractorConfigReader.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/typedetection/MimeExtractorConfigReader.java
new file mode 100644
index 0000000..1a39b39
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/typedetection/MimeExtractorConfigReader.java
@@ -0,0 +1,193 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.typedetection;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.filenaming.NamingConvention;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.LinkedList;
+
+//W3C imports
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+//Google imports
+import com.google.common.base.Strings;
+
+/**
+ * Static reader class for {@link MimeExtractor}s.
+ *
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public final class MimeExtractorConfigReader implements
+        MimeExtractorConfigMetKeys {
+
+    private MimeExtractorConfigReader() throws InstantiationException {
+        throw new InstantiationException("Don't construct reader classes!");
+    }
+
+    public static MimeExtractorRepo read(String mapFilePath) throws Exception {
+        try {
+            Document doc = XMLUtils.getDocumentRoot(new FileInputStream(
+                    mapFilePath));
+            Element root = doc.getDocumentElement();
+
+            MimeExtractorRepo extractorRepo = new MimeExtractorRepo();
+            extractorRepo.setMagic(Boolean.valueOf(
+                    root.getAttribute(MAGIC_ATTR)).booleanValue());
+            String mimeTypeFile = PathUtils.replaceEnvVariables(root
+                  .getAttribute(MIME_REPO_ATTR));
+            if (!mimeTypeFile.startsWith("/")) {
+               mimeTypeFile = new File(new File(mapFilePath).getParentFile(),
+                     mimeTypeFile).getAbsolutePath();
+            }
+            extractorRepo.setMimeRepoFile(mimeTypeFile);
+
+            Element defaultExtractorElem = XMLUtils.getFirstElement(
+                    DEFAULT_EXTRACTOR_TAG, root);
+            if (defaultExtractorElem != null) {
+                NodeList defaultExtractorElems = defaultExtractorElem
+                        .getElementsByTagName(EXTRACTOR_TAG);
+                LinkedList<MetExtractorSpec> defaultExtractorSpecs = new LinkedList<MetExtractorSpec>();
+                for (int i = 0; i < defaultExtractorElems.getLength(); i++) {
+                    Element extractorElem = (Element) defaultExtractorElems
+                            .item(i);
+                    Element preCondsElem = XMLUtils.getFirstElement(
+                          PRECONDITION_COMPARATORS_TAG, extractorElem);
+                    LinkedList<String> preCondComparatorIds = new LinkedList<String>();
+                    if (preCondsElem != null) {
+                       NodeList preCondComparators = 
+                          preCondsElem.getElementsByTagName(PRECONDITION_COMPARATOR_TAG);
+                       for (int k = 0; k < preCondComparators.getLength(); k++)
+                           preCondComparatorIds.add(((Element) preCondComparators
+                                   .item(k)).getAttribute(ID_ATTR));
+                    }
+                    // This seems wrong, so added support for CLASS_ATTR while still
+                    //  supporting EXTRACTOR_CLASS_TAG as an attribute for specifying
+                    //  extractor class.
+                    String extractorClass = extractorElem.getAttribute(CLASS_ATTR);
+                    if (Strings.isNullOrEmpty(extractorClass)) {
+                       extractorClass = extractorElem.getAttribute(EXTRACTOR_CLASS_TAG);
+                    }
+                    String extractorConfigFile = getFilePathFromElement(
+                          extractorElem, EXTRACTOR_CONFIG_TAG);
+                    if (extractorConfigFile != null && !extractorConfigFile.startsWith("/")) {
+                       extractorConfigFile = new File(new File(mapFilePath).getParentFile(),
+                             extractorConfigFile).getAbsolutePath();
+                    }
+                    defaultExtractorSpecs
+                            .add(new MetExtractorSpec(extractorClass,
+                                    extractorConfigFile,
+                                    preCondComparatorIds));
+                }
+                extractorRepo
+                        .setDefaultMetExtractorSpecs(defaultExtractorSpecs);
+                extractorRepo.setDefaultNamingConventionId(
+                      getNamingConventionId(defaultExtractorElem));
+            }
+
+            NodeList mimeElems = root.getElementsByTagName(MIME_TAG);
+            for (int i = 0; i < mimeElems.getLength(); i++) {
+                Element mimeElem = (Element) mimeElems.item(i);
+                String mimeType = mimeElem.getAttribute(MIME_TYPE_ATTR);
+                LinkedList<MetExtractorSpec> specs = new LinkedList<MetExtractorSpec>();
+
+                // Load naming convention class.
+                extractorRepo.setNamingConventionId(mimeType,
+                      getNamingConventionId(mimeElem));
+
+                NodeList extractorSpecElems = mimeElem
+                        .getElementsByTagName(EXTRACTOR_TAG);
+                if (extractorSpecElems != null
+                        && extractorSpecElems.getLength() > 0) {
+                    for (int j = 0; j < extractorSpecElems.getLength(); j++) {
+                        Element extractorSpecElem = (Element) extractorSpecElems
+                                .item(j);
+                        MetExtractorSpec spec = new MetExtractorSpec();
+                        spec.setMetExtractor(extractorSpecElem
+                                .getAttribute(CLASS_ATTR));
+
+                        // get config file if specified
+                        String configFilePath = getFilePathFromElement(
+                                extractorSpecElem, EXTRACTOR_CONFIG_TAG);
+                        if (configFilePath != null) {
+                           if (!configFilePath.startsWith("/")) {
+                              configFilePath = new File(new File(mapFilePath).getParentFile(),
+                                    configFilePath).getAbsolutePath();
+                           }
+                           spec.setExtractorConfigFile(configFilePath);
+                        }
+
+                        // get preconditions file if specified
+                        Element preCondsElem = XMLUtils.getFirstElement(
+                              PRECONDITION_COMPARATORS_TAG, extractorSpecElem);
+                        if (preCondsElem != null) {
+                           NodeList preCondComparators = preCondsElem
+                                 .getElementsByTagName(PRECONDITION_COMPARATOR_TAG);
+                           LinkedList<String> preCondComparatorIds = new LinkedList<String>();
+                           for (int k = 0; k < preCondComparators.getLength(); k++)
+                               preCondComparatorIds
+                                       .add(((Element) preCondComparators.item(k))
+                                               .getAttribute(ID_ATTR));
+                           spec.setPreConditionComparatorIds(preCondComparatorIds);
+                        }
+
+                        specs.add(spec);
+                    }
+                }
+                extractorRepo.addMetExtractorSpecs(mimeType, specs);
+            }
+            return extractorRepo;
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw e;
+        }
+    }
+
+    private static String getNamingConventionId(Element parent) throws Exception {
+       NodeList namingConventions = parent
+             .getElementsByTagName(NAMING_CONVENTION_TAG);
+       if (namingConventions != null && namingConventions.getLength() > 0) {
+          if (namingConventions.getLength() > 1) {
+             throw new Exception("Can only have 1 '"
+                   + NAMING_CONVENTION_TAG + "' tag per mimetype");
+          }
+          Element namingConvention = (Element) namingConventions.item(0);
+          return namingConvention.getAttribute(ID_ATTR);
+       }
+       return null;
+    }
+
+    private static String getFilePathFromElement(Element root, String elemName) {
+        String filePath = null;
+        Element elem = XMLUtils.getFirstElement(elemName, root);
+        if (elem != null) {
+            filePath = elem.getAttribute(FILE_ATTR);
+            if (Boolean.valueOf(elem.getAttribute(ENV_REPLACE_ATTR))
+                    .booleanValue())
+                filePath = PathUtils.replaceEnvVariables(filePath);
+        }
+        return filePath;
+    }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/typedetection/MimeExtractorRepo.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/typedetection/MimeExtractorRepo.java
new file mode 100644
index 0000000..8115bef
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/typedetection/MimeExtractorRepo.java
@@ -0,0 +1,215 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.typedetection;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.MimeTypeUtils;
+
+//Google imports
+import com.google.common.collect.Maps;
+
+/**
+ * Repo of extractor spec and naming conventions mapped by mime-type.
+ *
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public class MimeExtractorRepo {
+
+	private List<MetExtractorSpec> defaultExtractorSpecs;
+	private String defaultNamingConventionId;
+	private MimeTypeUtils mimeRepo;
+	private boolean magic;
+	private Map<String, List<MetExtractorSpec>> mimeTypeToMetExtractorSpecsMap;
+	private Map<String, String> mimeTypeToNamingConventionIdMap;
+
+	/**
+	 * Default Constructor
+	 * 
+	 * @throws FileNotFoundException
+	 * 
+	 */
+	public MimeExtractorRepo() throws FileNotFoundException {
+		this(new LinkedList<MetExtractorSpec>(), null, null, false);
+	}
+
+	/**
+	 * Constructs a new MimeExtractorMappingFile with the given parameters.
+	 * 
+	 * @param defaultExtractorClassName
+	 *            The name of the default extractor to call if the mime type
+	 *            can't be determined.
+	 * @param repo
+	 *            The Mime Repository to use for mime resolution.
+	 * @param magic
+	 *            Whether or not mime magic should be used or not in resolution.
+	 * 
+	 * @param mappings
+	 *            {@link List} of {@link MimeExtractorMapping}s.
+	 * @throws FileNotFoundException
+	 */
+	public MimeExtractorRepo(List<MetExtractorSpec> defaultExtractorSpecs,
+	      String defaultNamingConventionId, String mimeRepoFile,
+	      boolean magic) throws FileNotFoundException {
+		setDefaultMetExtractorSpecs(defaultExtractorSpecs);
+		setDefaultNamingConventionId(defaultNamingConventionId);
+		setMimeRepoFile(mimeRepoFile);
+		setMagic(magic);
+		mimeTypeToMetExtractorSpecsMap = Maps.newHashMap();
+		mimeTypeToNamingConventionIdMap = Maps.newHashMap();
+	}
+
+	public synchronized void setNamingConventionId(String mimeType,
+	      String namingConventionId) {
+	   mimeTypeToNamingConventionIdMap.put(mimeType, namingConventionId);
+	}
+
+	public synchronized String getNamingConventionId(String mimeType) {
+	   String namingConventionId =  mimeTypeToNamingConventionIdMap.get(
+	         mimeType);
+	   if (namingConventionId == null) {
+	      return getDefaultNamingConventionId();
+	   }
+	   return namingConventionId;
+	}
+
+	public synchronized void addMetExtractorSpec(String mimeType,
+			MetExtractorSpec spec) {
+		List<MetExtractorSpec> specs = this.mimeTypeToMetExtractorSpecsMap
+				.remove(mimeType);
+		if (specs == null)
+			specs = new LinkedList<MetExtractorSpec>();
+		specs.add(spec);
+		this.mimeTypeToMetExtractorSpecsMap.put(mimeType, specs);
+	}
+
+	public synchronized void addMetExtractorSpecs(String mimeType,
+			List<MetExtractorSpec> specs) {
+		List<MetExtractorSpec> existingSpecs = this.mimeTypeToMetExtractorSpecsMap
+				.remove(mimeType);
+		if (existingSpecs == null)
+			existingSpecs = new LinkedList<MetExtractorSpec>();
+		existingSpecs.addAll(specs);
+		this.mimeTypeToMetExtractorSpecsMap.put(mimeType, existingSpecs);
+	}
+
+	public synchronized List<MetExtractorSpec> getExtractorSpecsForMimeType(
+			String mimeType) {
+		List<MetExtractorSpec> extractorSpecs = new LinkedList<MetExtractorSpec>();
+		while (mimeType != null && !mimeType.equals("application/octet-stream")) {
+			List<MetExtractorSpec> specs = this.mimeTypeToMetExtractorSpecsMap.get(mimeType);
+			if (specs != null)
+				extractorSpecs.addAll(specs);
+			mimeType = this.mimeRepo.getSuperTypeForMimeType(mimeType);
+		}
+		return !extractorSpecs.isEmpty() ? extractorSpecs : this
+				.getDefaultMetExtractorSpecs();
+	}
+
+	public synchronized List<MetExtractorSpec> getExtractorSpecsForFile(
+			File file) throws FileNotFoundException, IOException {
+		String mimeType = this.mimeRepo.getMimeType(file);
+		if (mimeType == null && magic)
+			mimeType = this.mimeRepo.getMimeTypeByMagic(MimeTypeUtils
+					.readMagicHeader(new FileInputStream(file)));
+		return this.getExtractorSpecsForMimeType(mimeType);
+	}
+
+	/**
+	 * @return the defaultExtractorClassName
+	 */
+	public List<MetExtractorSpec> getDefaultMetExtractorSpecs() {
+		return this.defaultExtractorSpecs != null ? this.defaultExtractorSpecs
+				: new LinkedList<MetExtractorSpec>();
+	}
+
+	/**
+	 * @param defaultExtractorClassName
+	 *            the defaultExtractorClassName to set
+	 */
+	public void setDefaultMetExtractorSpecs(
+			List<MetExtractorSpec> defaultExtractorSpecs) {
+		this.defaultExtractorSpecs = defaultExtractorSpecs;
+	}
+
+	public void setDefaultNamingConventionId(
+	      String defaultNamingConventionId) {
+	   this.defaultNamingConventionId = defaultNamingConventionId;
+	}
+
+	public String getDefaultNamingConventionId() {
+	   return defaultNamingConventionId;
+	}
+
+	/**
+	 * @return the magic
+	 */
+	public boolean isMagic() {
+		return this.magic;
+	}
+
+	/**
+	 * @param magic
+	 *            the magic to set
+	 */
+	public void setMagic(boolean magic) {
+		this.magic = magic;
+		if (this.mimeRepo != null)
+			this.mimeRepo.setMimeMagic(magic);
+	}
+
+	/**
+	 * @param mimeRepo
+	 *            the mimeRepo to set
+	 * @throws FileNotFoundException
+	 */
+	public void setMimeRepoFile(String mimeRepoFile)
+			throws FileNotFoundException {
+		if (mimeRepoFile != null)
+			this.mimeRepo = new MimeTypeUtils(mimeRepoFile, this.magic);
+	}
+
+	public String getMimeType(File file) {
+	   return mimeRepo.getMimeType(file);
+	}
+
+	/**
+	 * Gets the mime-type hierarchy. Index 0 is this files mime-type,
+	 * index 1 is index 0's mime-type's parent mime-type, and so on. 
+	 * @param file
+	 * @return
+	 */
+	public List<String> getMimeTypes(File file) {
+	    List<String> mimeTypes = new Vector<String>();
+	    String mimeType = getMimeType(file);
+	    mimeTypes.add(mimeType);
+	    while ((mimeType = this.mimeRepo.getSuperTypeForMimeType(mimeType)) != null
+                && !mimeType.equals("application/octet-stream"))
+	        mimeTypes.add(mimeType);
+	    return mimeTypes;
+	}
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/util/ActionBeanProperties.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/util/ActionBeanProperties.java
new file mode 100644
index 0000000..1100488
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/util/ActionBeanProperties.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.util;
+
+//JDK imports
+import java.util.Properties;
+
+/**
+ * A collection of bean properties which are used by
+ * {@link CasPropertyOverrideConfigurer} to set properties on
+ * {@link ProductCrawler}s and {@link CrawlerAction}s.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class ActionBeanProperties {
+
+   private static Properties properties = new Properties();
+
+   private ActionBeanProperties() throws InstantiationException {
+      throw new InstantiationException("Do not instantiate ActionBeanProperties");
+   }
+
+   public static void setProperty(String key, String value) {
+      System.out.println("Setting property '" + key + "'");
+      properties.setProperty(key, value);
+   }
+
+   public static Properties getProperties() {
+      return properties;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/util/CasPropertyList.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/util/CasPropertyList.java
new file mode 100644
index 0000000..aae5e01
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/util/CasPropertyList.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.crawl.util;
+
+//JDK imports
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class CasPropertyList extends LinkedList<String> {
+
+    private static final long serialVersionUID = -5956500397967590724L;
+
+    public void setValues(String values) {
+        this.addAll(this.getAsList(values));
+    }
+
+    private List<String> getAsList(String values) {
+        Vector<String> propList = new Vector<String>();
+        StringTokenizer st = new StringTokenizer(values, ",");
+        while (st.hasMoreTokens()) {
+            propList.add(st.nextToken().trim());
+        }
+        return propList;
+    }
+
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/util/CasPropertyOverrideConfigurer.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/util/CasPropertyOverrideConfigurer.java
new file mode 100644
index 0000000..4e21f7d
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/util/CasPropertyOverrideConfigurer.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.util;
+
+//JDK imports
+import java.io.IOException;
+
+//Spring imports
+import org.springframework.beans.factory.config.PropertyOverrideConfigurer;
+
+/**
+ * A {@link PropertyOverrideConfigurer} which sets properties stored in
+ * {@link ActionBeanProperties}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class CasPropertyOverrideConfigurer extends PropertyOverrideConfigurer {
+
+   public CasPropertyOverrideConfigurer() throws IOException {
+      super();
+      setProperties(ActionBeanProperties.getProperties());
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/util/CasPropertyPlaceholderConfigurer.java b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/util/CasPropertyPlaceholderConfigurer.java
new file mode 100644
index 0000000..5e78e4a
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/java/org/apache/oodt/cas/crawl/util/CasPropertyPlaceholderConfigurer.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.crawl.util;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//Spring imports
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class CasPropertyPlaceholderConfigurer extends
+        PropertyPlaceholderConfigurer {
+
+    @Override
+    protected String convertPropertyValue(String value) {
+        try {
+            return PathUtils.doDynamicReplacement(value);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return value;
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/crawler/src/main/resources/REMOVE.log b/0.8.1-rc1/crawler/src/main/resources/REMOVE.log
new file mode 100644
index 0000000..cb27d16
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/REMOVE.log
@@ -0,0 +1,18 @@
+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.
+
+
+You can remove this file. It was only included to ensure that the log directory for this
+distribution was created on assembly.
diff --git a/0.8.1-rc1/crawler/src/main/resources/action-beans.xml b/0.8.1-rc1/crawler/src/main/resources/action-beans.xml
new file mode 100644
index 0000000..333b081
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/action-beans.xml
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor" />
+	<bean class="org.apache.oodt.cas.crawl.util.CasPropertyPlaceholderConfigurer">
+
+		<!-- Allow for system-level properties to override all properties below -->
+		<property name="systemPropertiesMode" value="2" />
+
+		<!-- Default Properties -->
+		<property name="properties">
+			<props>
+				<prop key="crawler.failure.dir">[FAILURE_DIR]</prop>
+				<prop key="crawler.backup.dir">[BACKUP_DIR]</prop>
+				<prop key="crawler.workflowmgr.url">[WORKFLOW_URL]</prop>
+				<prop key="crawler.filemgr.url">[FILEMGR_URL]</prop>
+				<prop key="crawler.client.transferer">org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory</prop>
+				<prop key="crawler.met.file.ext">met</prop>
+				<prop key="crawler.pushpull.met.file.ext">[PUSHPULL_MET_FILE_EXT]</prop>
+				<prop key="crawler.anc.file.ext">anc</prop>
+				<prop key="crawler.anc.file.suffix"></prop>
+				<prop key="notification.mail.host"></prop>
+				<prop key="notification.sender"></prop>
+				<prop key="notification.success.subject"></prop>
+				<prop key="notification.success.message"></prop>
+				<prop key="notification.success.recipients"></prop>
+			</props>
+		</property>
+
+		<!-- File Properties - overrides default properties -->
+		<!-- property name="location" value="/org/apache/oodt/cas/crawl/crawler.properties" 
+			/ -->
+	</bean>
+
+	<!-- DELETE Actions -->
+	<bean id="DeleteDataFile" lazy-init="true" class="org.apache.oodt.cas.crawl.action.DeleteFile">
+		<property name="description" value="Deletes the current data file" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestSuccess</value>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="DeleteMetadataFile" lazy-init="true" class="org.apache.oodt.cas.crawl.action.DeleteFile">
+		<property name="description" value="Deletes the metadata file for the current data file" />
+		<property name="fileExtension" value="${crawler.met.file.ext}" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestSuccess</value>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="DeletePushpullMetFile" lazy-init="true" class="org.apache.oodt.cas.crawl.action.DeleteFile">
+		<property name="description" value="Deletes the push-pull metadata file for the current data file" />
+		<property name="fileExtension" value="${crawler.pushpull.met.file.ext}" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestSuccess</value>
+			</list>
+		</property>
+	</bean>
+
+	<!-- MOVE to FAILURE_DIR Actions -->
+	<bean id="MoveDataFileToFailureDir" lazy-init="true" class="org.apache.oodt.cas.crawl.action.MoveFile">
+		<property name="description" value="Moves the current data file to failure directory" />
+		<property name="toDir" value="${crawler.failure.dir}" />
+		<property name="createToDir" value="true" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestFailure</value>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="MoveMetadataFileToFailureDir" lazy-init="true" class="org.apache.oodt.cas.crawl.action.MoveFile">
+		<property name="description" value="Moves the metadata file for the current data file to failure directory" />
+		<property name="fileExtension" value="${crawler.met.file.ext}" />
+		<property name="toDir" value="${crawler.failure.dir}" />
+		<property name="createToDir" value="true" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestFailure</value>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="MovePushpullMetFileToFailureDir" lazy-init="true" class="org.apache.oodt.cas.crawl.action.MoveFile">
+		<property name="description" value="Moves the push-pull metadata file for the current data file to failure directory" />
+		<property name="createToDir" value="true" />
+		<property name="fileExtension" value="${crawler.pushpull.met.file.ext}" />
+		<property name="toDir" value="${crawler.failure.dir}" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestFailure</value>
+			</list>
+		</property>
+	</bean>
+
+	<!-- MOVE to BACKUP_DIR Actions -->
+	<bean id="MovePushpullMetFileToBackupDir" lazy-init="true" class="org.apache.oodt.cas.crawl.action.MoveFile">
+		<property name="description" value="Moves the push-pull metadata file for the current data file to success directory" />
+		<property name="fileExtension" value="${crawler.pushpull.met.file.ext}" />
+		<property name="toDir" value="${crawler.backup.dir}" />
+		<property name="createToDir" value="true" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestSuccess</value>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="MoveMetadataFileToBackupDir" lazy-init="true" class="org.apache.oodt.cas.crawl.action.MoveFile">
+		<property name="description" value="Moves the metadata file for the current data file to success directory" />
+		<property name="fileExtension" value="${crawler.met.file.ext}" />
+		<property name="toDir" value="${crawler.backup.dir}" />
+		<property name="createToDir" value="true" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestSuccess</value>
+			</list>
+		</property>
+	</bean>
+
+	<!-- Workflow Manager Actions -->
+	<bean id="TriggerPostIngestWorkflow" lazy-init="true" class="org.apache.oodt.cas.crawl.action.WorkflowMgrStatusUpdate">
+		<property name="description" value="Triggers workflow event with the name [ProductType]Ingest" />
+		<property name="ingestSuffix" value="Ingest" />
+		<property name="workflowMgrUrl" value="${crawler.workflowmgr.url}" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestSuccess</value>
+			</list>
+		</property>
+	</bean>
+
+	<!-- File Manager Actions -->
+	<bean id="Unique" lazy-init="true" class="org.apache.oodt.cas.crawl.action.FilemgrUniquenessChecker">
+		<property name="description" value="Checks the filemgr against the PRODUCT_NAME for the current data file to make sure it has not yet been ingested" />
+		<property name="filemgrUrl" value="${crawler.filemgr.url}" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">preIngest</value>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="IngestAncillaryFile" lazy-init="true" class="org.apache.oodt.cas.crawl.action.IngestAncillary">
+		<property name="description" value="This will ingest an associated file along with the current file being ingested by the crawler." />
+		<property name="fileManagerUrl" value="${crawler.filemgr.url}" />
+		<property name="fileExtension" value="${crawler.anc.file.ext}" />
+		<property name="fileSuffix" value="${crawler.anc.file.suffix}" />
+		<property name="keepExistingExtension">
+			<value type="java.lang.Boolean">false</value>
+		</property>
+		<property name="dataTransferService" value="${crawler.client.transferer}" />
+		<property name="relatedKey" value="CAS.ProductId" />
+		<property name="copyKeys">
+			<list>
+				<value type="java.lang.String">MetKey1</value>
+			</list>
+		</property>
+		<property name="productType" value="GenericFile" />
+		<property name="failMissingFile">
+			<value type="java.lang.Boolean">true</value>
+		</property>
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">preIngest</value>
+			</list>
+		</property>
+	</bean>
+
+	<!-- Existence Check Actions -->
+	<bean id="CheckMetFileExists" lazy-init="true" class="org.apache.oodt.cas.crawl.action.ExternAction">
+		<property name="description" value="Checks if metadata file was created -- make sure check-exists.sh is on your PATH" />
+		<property name="executeCommand" value="./check-exists.sh [Filename].met" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">preIngest</value>
+			</list>
+		</property>
+	</bean>
+
+	<!-- Email Actions -->
+	<bean id="SendNotification" lazy-init="true" class="org.apache.oodt.cas.crawl.action.EmailNotification">
+		<property name="description" value="This will send an email that indicates the submission to the catalog was successful." />
+		<property name="mailHost" value="${notification.mail.host}" />
+		<property name="sender" value="${notification.sender}" />
+		<property name="subject" value="${notification.success.subject}" />
+		<property name="message" value="${notification.success.message}" />
+		<property name="recipients" value="${notification.success.recipients}" />
+		<property name="ignoreInvalidAddresses">
+			<value type="java.lang.Boolean">true</value>
+		</property>
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestSuccess</value>
+			</list>
+		</property>
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/crawler/src/main/resources/cmd-line-actions.xml b/0.8.1-rc1/crawler/src/main/resources/cmd-line-actions.xml
new file mode 100644
index 0000000..d83fb89
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/cmd-line-actions.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean id="launchStdCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.cli.action.CrawlerLauncherCliAction">
+    <property name="description" value="Triggers StdProductCrawler" />
+    <property name="crawlerId" value="StdProductCrawler" />
+  </bean>
+
+  <bean id="launchMetCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.cli.action.CrawlerLauncherCliAction">
+    <property name="description" value="Triggers MetExtractorProductCrawler" />
+    <property name="crawlerId" value="MetExtractorProductCrawler" />
+  </bean>
+
+  <bean id="launchAutoCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.cli.action.CrawlerLauncherCliAction">
+    <property name="description" value="Triggers AutoDetectProductCrawler" />
+    <property name="crawlerId" value="AutoDetectProductCrawler" />
+  </bean>
+</beans>
diff --git a/0.8.1-rc1/crawler/src/main/resources/cmd-line-options.xml b/0.8.1-rc1/crawler/src/main/resources/cmd-line-options.xml
new file mode 100755
index 0000000..b92ef89
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/cmd-line-options.xml
@@ -0,0 +1,913 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean id="operation" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="op" />
+    <property name="longOption" value="operation" />
+    <property name="description" value="Declare that you wish to present an operation" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="true" />
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="launchStdCrawler" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="launchMetCrawler" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="launchAutoCrawler" p:required="false" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- launchStdCrawler Options -->
+  <bean id="launchStdCrawler" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="stdPC" />
+    <property name="longOption" value="launchStdCrawler" />
+    <property name="description" value="Triggers StdProductCrawler" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>launchStdCrawler</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchStdCrawler" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- launchMetCrawler Options -->
+  <bean id="launchMetCrawler" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="metPC" />
+    <property name="longOption" value="launchMetCrawler" />
+    <property name="description" value="Triggers MetExtractorProductCrawler" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>launchMetCrawler</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchMetCrawler" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- launchAutoCrawler Options -->
+  <bean id="launchAutoCrawler" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="autoPC" />
+    <property name="longOption" value="launchAutoCrawler" />
+    <property name="description" value="Triggers AutoDetectProductCrawler" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>launchAutoCrawler</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchAutoCrawler" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+	<bean id="printSupportedCrawlerActions" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="psca" />
+		<property name="longOption" value="printSupportedCrawlerActions" />
+		<property name="description" value="Prints a list and description of all supported CrawlerActions" />
+		<property name="hasArgs" value="false" />
+		<property name="required" value="false" />
+		<property name="performAndQuit" value="true" />
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerActionInfoHandler">
+				<property name="applicationContext">
+					<bean class="org.springframework.context.support.FileSystemXmlApplicationContext">
+						<constructor-arg value="../policy/action-beans.xml" />
+					</bean>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="printSupportedPreconditions" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="psp" />
+		<property name="longOption" value="printSupportedPreconditions" />
+		<property name="description" value="Prints a list and description of all supported Preconditions" />
+		<property name="hasArgs" value="false" />
+		<property name="required" value="false" />
+		<property name="performAndQuit" value="true" />
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.PreconditionInfoHandler">
+				<property name="applicationContext">
+					<bean class="org.springframework.context.support.FileSystemXmlApplicationContext">
+						<constructor-arg value="../policy/precondition-beans.xml" />
+					</bean>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="filemgrUrl" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="fm" />
+		<property name="longOption" value="filemgrUrl" />
+		<property name="description" value="File Manager URL" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="url" />
+		<property name="required" value="true" />
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.filemgrUrl</value>
+						<value>MetExtractorProductCrawler.filemgrUrl</value>
+						<value>AutoDetectProductCrawler.filemgrUrl</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+					<property name="allowedArgs">
+						<list>
+							<value>http://.*:\d*</value>
+						</list>
+					</property>
+				</bean>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="failureDir" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="fd" />
+		<property name="longOption" value="failureDir" />
+		<property name="description" value="Directory where files will be moved on failure" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="directory" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+      </list>
+    </property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>MoveMetadataFileToFailureDir.toDir</value>
+						<value>MovePushpullMetFileToFailureDir.toDir</value>
+						<value>MoveDataFileToFailureDir.toDir</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="successDir" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="sd" />
+		<property name="longOption" value="successDir" />
+		<property name="description" value="Directory where files will be moved on success" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="directory" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>MovePushpullMetFileToBackupDir.toDir</value>
+						<value>MoveMetadataFileToBackupDir.toDir</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="workflowMgrUrl" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="wm" />
+		<property name="longOption" value="workflowMgrUrl" />
+		<property name="description" value="Workflow Manager URL" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="url" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>UpdateWorkflowStatusToIngest.workflowMgrUrl</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+					<property name="allowedArgs">
+						<list>
+							<value>http://.*:\d*</value>
+						</list>
+					</property>
+				</bean>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="clientTransferer" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="ct" />
+		<property name="longOption" value="clientTransferer" />
+		<property name="description" value="File Manager data transferer factory class" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="class" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.clientTransferer</value>
+						<value>MetExtractorProductCrawler.clientTransferer</value>
+						<value>AutoDetectProductCrawler.clientTransferer</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.ClassExistsCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="requiredMetadata" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="rqm" />
+		<property name="longOption" value="requiredMetadata" />
+		<property name="type" value="java.util.List" />
+		<property name="description" value="Metadata required for ingest to take place" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="metadata_elements" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.requiredMetadata</value>
+						<value>MetExtractorProductCrawler.requiredMetadata</value>
+						<value>AutoDetectProductCrawler.requiredMetadata</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="actionIds" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="ais" />
+		<property name="longOption" value="actionIds" />
+		<property name="type" value="java.util.List" />
+		<property name="description" value="CrawlerActions that should be performed" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="CrawlerAction ids" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.actionIds</value>
+						<value>MetExtractorProductCrawler.actionIds</value>
+						<value>AutoDetectProductCrawler.actionIds</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="preCondIds" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="pids" />
+		<property name="longOption" value="preCondIds" />
+		<property name="type" value="java.util.List" />
+		<property name="description" value="PreConditionComparator ids that must pass before any metadata extraction will run" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="PreConditionComparator ids" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>MetExtractorProductCrawler.preCondIds</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+  <bean id="namingConventionId" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="ncid" />
+    <property name="longOption" value="namingConventionId" />
+    <property name="description" value="ID of the NamingConvention to use to rename products before ingest" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="NamingConvention ID" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>MetExtractorProductCrawler.namingConventionId</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+	<bean id="noRecur" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="nr" />
+		<property name="longOption" value="noRecur" />
+		<property name="description" value="Turns off recursive crawling - will only process files in productPath directory" />
+		<property name="type" value="boolean" />
+		<property name="hasArgs" value="false" />
+                <property name="staticArgs">
+			<list>
+				<value>true</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.noRecur</value>
+						<value>MetExtractorProductCrawler.noRecur</value>
+						<value>AutoDetectProductCrawler.noRecur</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="crawlForDirs" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="cfd" />
+		<property name="longOption" value="crawlForDirs" />
+		<property name="description" value="Will crawl for directories instead of files" />
+		<property name="type" value="boolean" />
+		<property name="hasArgs" value="false" />
+                <property name="staticArgs">
+			<list>
+				<value>true</value>
+			</list>
+		</property>
+		<property name="required" value="false" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.crawlForDirs</value>
+						<value>MetExtractorProductCrawler.crawlForDirs</value>
+						<value>AutoDetectProductCrawler.crawlForDirs</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="skipIngest" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="si" />
+		<property name="longOption" value="skipIngest" />
+		<property name="description" value="Will skip ingest to file manager and any post ingest actions" />
+		<property name="type" value="boolean" />
+		<property name="hasArgs" value="false" />
+                <property name="staticArgs">
+			<list>
+				<value>true</value>
+			</list>
+		</property>
+		<property name="required" value="false" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.skipIngest</value>
+						<value>MetExtractorProductCrawler.skipIngest</value>
+						<value>AutoDetectProductCrawler.skipIngest</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="daemonPort" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="dp" />
+		<property name="longOption" value="daemonPort" />
+		<property name="type" value="int" />
+		<property name="description" value="Cause crawler to become a daemon with a XML-RPC webserver started on the given port number" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="portNum" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.daemonPort</value>
+						<value>MetExtractorProductCrawler.daemonPort</value>
+						<value>AutoDetectProductCrawler.daemonPort</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+					<property name="allowedArgs">
+						<list>
+							<value>\d*</value>
+						</list>
+					</property>
+				</bean>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="daemonWait" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="dw" />
+		<property name="longOption" value="daemonWait" />
+		<property name="type" value="int" />
+		<property name="description" value="Cause crawler to become a daemon and sleep for given number of seconds between crawls" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="seconds" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.daemonWait</value>
+						<value>MetExtractorProductCrawler.daemonWait</value>
+						<value>AutoDetectProductCrawler.daemonWait</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+					<property name="allowedArgs">
+						<list>
+							<value>\d*</value>
+						</list>
+					</property>
+				</bean>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="productPath" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="pp" />
+		<property name="longOption" value="productPath" />
+		<property name="description" value="Root directory to crawl" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="directory" />
+		<property name="required" value="true" />
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.productPath</value>
+						<value>MetExtractorProductCrawler.productPath</value>
+						<value>AutoDetectProductCrawler.productPath</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="metFileExtension" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="mfx" />
+		<property name="longOption" value="metFileExtension" />
+		<property name="description" value="The file extension of existing and to be created PCS metadata files" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="file extension" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchStdCrawler" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.metFileExtension</value>
+						<value>DeleteMetadataFile.fileExtension</value>
+						<value>MoveMetadataFileToBackupDir.fileExtension</value>
+						<value>MoveMetadataFileToFailureDir.fileExtension</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="metExtractor" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="mx" />
+		<property name="longOption" value="metExtractor" />
+		<property name="description" value="Metadata extractor class to use" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="class" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>MetExtractorProductCrawler.metExtractor</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.ClassExistsCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="metExtractorConfig" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="mxc" />
+		<property name="longOption" value="metExtractorConfig" />
+		<property name="description" value="Config file for metadata extractor" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="file" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>MetExtractorProductCrawler.metExtractorConfig</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="mimeExtractorRepo" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="mxr" />
+		<property name="longOption" value="mimeExtractorRepo" />
+		<property name="description" value="Mime-type to metadata extractor mapping xml file" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="file" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchAutoCrawler" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>AutoDetectProductCrawler.mimeExtractorRepo</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="pushpullMetFileExtension" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="ppmfx" />
+		<property name="longOption" value="pushpullMetFileExtension" />
+		<property name="description" value="File extension of push-pull metadata files" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="file extension" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>DeletePushpullMetFile.fileExtension</value>
+						<value>MovePushpullMetFileToBackupDir.fileExtension</value>
+						<value>MovePushpullMetFileToFailureDir.fileExtension</value>
+						<value>CheckThatPushPullMetFileExists.fileExtension</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+  <bean id="notification" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="n" />
+    <property name="longOption" value="notification" />
+    <property name="description" value="Declare that your want email notification" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="false" />
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="mailHost" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="sender" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="subject" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="message" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="recipients" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="ignoreInvalidAddresses" p:required="false" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="mailHost" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="mh" />
+    <property name="longOption" value="mailHost" />
+    <property name="description" value="Email Host" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="host" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>SendNotification.emailHost</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="sender" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="sdr" />
+    <property name="longOption" value="sender" />
+    <property name="description" value="Email sender" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="email address" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>SendNotification.sender</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="subject" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="sub" />
+    <property name="longOption" value="subject" />
+    <property name="description" value="Email subject" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="email subject" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>SendNotification.subject</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="message" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="msg" />
+    <property name="longOption" value="message" />
+    <property name="description" value="Email message body" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="email message" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>SendNotification.message</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="recipients" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="rcpts" />
+    <property name="longOption" value="recipients" />
+    <property name="description" value="List of recipient emails" />
+    <property name="type" value="java.util.List" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="email addresses" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>SendNotification.recipients</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="ignoreInvalidAddresses" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="iias" />
+    <property name="longOption" value="ignoreInvalidAddresses" />
+    <property name="description" value="If invalid addresses should just be ignored" />
+    <property name="type" value="boolean" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+    <list>
+        <value>true</value>
+    </list>
+    </property>
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>SendNotification.ignoreInvalidAddresses</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+</beans>
diff --git a/0.8.1-rc1/crawler/src/main/resources/crawler-beans.xml b/0.8.1-rc1/crawler/src/main/resources/crawler-beans.xml
new file mode 100644
index 0000000..a479119
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/crawler-beans.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<!-- Product Crawlers -->
+	<bean id="StdProductCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.StdProductCrawler">
+		<description>Ingests data files based on existing metadata files</description>
+	</bean>
+
+	<bean id="MetExtractorProductCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.MetExtractorProductCrawler">
+		<description>Ingests data files after generating a metadata file for it with a given metadata extractor</description>
+	</bean>
+
+	<bean id="AutoDetectProductCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.AutoDetectProductCrawler">
+		<description>Ingests data files by choosing metadata extractors based on mimetypes given in specified mimetype xml file</description>
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/crawler/src/main/resources/crawler-config.xml b/0.8.1-rc1/crawler/src/main/resources/crawler-config.xml
new file mode 100755
index 0000000..4250c35
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/crawler-config.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean class="org.apache.oodt.cas.crawl.util.CasPropertyOverrideConfigurer" />
+
+	<import resource="crawler-beans.xml" />
+	<import resource="action-beans.xml" />
+	<import resource="precondition-beans.xml" />
+  <import resource="naming-beans.xml" />
+
+</beans>
diff --git a/0.8.1-rc1/crawler/src/main/resources/examples/mime-extractor-map.xml b/0.8.1-rc1/crawler/src/main/resources/examples/mime-extractor-map.xml
new file mode 100644
index 0000000..f07ab00
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/examples/mime-extractor-map.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<cas:mimetypemap xmlns:cas="http://oodt.jpl.nassa.gov/1.0/cas" magic="true or false" mimeRepo="path/to/tika-mimetypes/xml/file">
+	
+	<!-- extractor specs for mime-type from mimetypes.xml (one or more) -->
+	<mime type="some/mime-type">
+
+    <!-- naming convention for renaming file (zero or one) -->
+    <namingConvention id="id_from_application_context_bean_file" />
+
+		<!-- extractor spec for given mime-type (one or more) -->
+		<extractor class="extractor.class">
+			
+			<!-- extractor config file (zero or one) -->
+			<config file="extractor/config/file"/>
+			
+			<!-- precondition comparators (zero or one) -->
+			<preCondComparators>
+				
+				<!-- precondition comparator id (one or more) -->
+				<preCondComparator id="id_from_application_context_bean_file"/>
+				
+			</preCondComparators>
+			
+		</extractor>
+		
+	</mime>
+	
+</cas:mimetypemap>
diff --git a/0.8.1-rc1/crawler/src/main/resources/examples/mimetypes.xml b/0.8.1-rc1/crawler/src/main/resources/examples/mimetypes.xml
new file mode 100644
index 0000000..02feaf0
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/examples/mimetypes.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<mime-info>
+	
+	<!-- mime-type declaration (one or more) -->
+	<mime-type type="some/mime-type">
+		
+		<!-- super-type, MetExtractorSpecs defined for this type and
+			it's parent types will also be used (zero or one) -->
+		<sub-class-of type="another/mime-type"/>
+		
+		<!-- any regular expression parsable by Java Pattern (one or more) -->
+		<glob pattern="regExpr"/>
+		
+	</mime-type>
+	
+</mime-info>
diff --git a/0.8.1-rc1/crawler/src/main/resources/extern-scripts/check-exists.sh b/0.8.1-rc1/crawler/src/main/resources/extern-scripts/check-exists.sh
new file mode 100644
index 0000000..b292736
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/extern-scripts/check-exists.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# 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.
+
+if [ ! -f $1 ]; then
+	exit 1
+fi
diff --git a/0.8.1-rc1/crawler/src/main/resources/legacy-cmd-line-actions.xml b/0.8.1-rc1/crawler/src/main/resources/legacy-cmd-line-actions.xml
new file mode 100644
index 0000000..1259eab
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/legacy-cmd-line-actions.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<!-- Product Crawlers -->
+	<bean id="StdProductCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.cli.action.CrawlerLauncherCliAction">
+    <property name="description" value="Triggers StdProductCrawler" />
+	</bean>
+
+	<bean id="MetExtractorProductCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.cli.action.CrawlerLauncherCliAction">
+    <property name="description" value="Triggers MetExtractorProductCrawler" />
+	</bean>
+
+	<bean id="AutoDetectProductCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.cli.action.CrawlerLauncherCliAction">
+    <property name="description" value="Triggers AutoDetectProductCrawler" />
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/crawler/src/main/resources/legacy-cmd-line-options.xml b/0.8.1-rc1/crawler/src/main/resources/legacy-cmd-line-options.xml
new file mode 100755
index 0000000..99d2786
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/legacy-cmd-line-options.xml
@@ -0,0 +1,672 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean id="crawlerId" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption">
+		<property name="shortOption" value="cid" />
+		<property name="longOption" value="crawlerId" />
+		<property name="description" value="The ProductCrawler to use" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="ProductCrawler id" />
+		<property name="required" value="true" />
+	</bean>
+
+	<bean id="printSupportedCrawlerActions" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="psca" />
+		<property name="longOption" value="printSupportedCrawlerActions" />
+		<property name="description" value="Prints a list and description of all supported CrawlerActions" />
+		<property name="hasArgs" value="false" />
+		<property name="required" value="false" />
+		<property name="performAndQuit" value="true" />
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerActionInfoHandler">
+				<property name="applicationContext">
+					<bean class="org.springframework.context.support.FileSystemXmlApplicationContext">
+						<constructor-arg value="../policy/action-beans.xml" />
+					</bean>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="printSupportedPreconditions" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="psp" />
+		<property name="longOption" value="printSupportedPreconditions" />
+		<property name="description" value="Prints a list and description of all supported Preconditions" />
+		<property name="hasArgs" value="false" />
+		<property name="required" value="false" />
+		<property name="performAndQuit" value="true" />
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.PreconditionInfoHandler">
+				<property name="applicationContext">
+					<bean class="org.springframework.context.support.FileSystemXmlApplicationContext">
+						<constructor-arg value="../policy/precondition-beans.xml" />
+					</bean>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="filemgrUrl" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="fm" />
+		<property name="longOption" value="filemgrUrl" />
+		<property name="description" value="File Manager URL" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="url" />
+		<property name="required" value="true" />
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.filemgrUrl</value>
+						<value>MetExtractorProductCrawler.filemgrUrl</value>
+						<value>AutoDetectProductCrawler.filemgrUrl</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+					<property name="allowedArgs">
+						<list>
+							<value>http://.*:\d*</value>
+						</list>
+					</property>
+				</bean>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="failureDir" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="fd" />
+		<property name="longOption" value="failureDir" />
+		<property name="description" value="Directory where files will be moved on failure" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="directory" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="StdProductCrawler" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="AutoDetectProductCrawler" p:relation="OPTIONAL" />
+      </list>
+    </property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>MoveMetadataFileToFailureDir.toDir</value>
+						<value>MovePushpullMetFileToFailureDir.toDir</value>
+						<value>MoveDataFileToFailureDir.toDir</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="successDir" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="sd" />
+		<property name="longOption" value="successDir" />
+		<property name="description" value="Directory where files will be moved on success" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="directory" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="StdProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="AutoDetectProductCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>MovePushpullMetFileToBackupDir.toDir</value>
+						<value>MoveMetadataFileToBackupDir.toDir</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="workflowMgrUrl" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="wm" />
+		<property name="longOption" value="workflowMgrUrl" />
+		<property name="description" value="Workflow Manager URL" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="url" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="StdProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="AutoDetectProductCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>UpdateWorkflowStatusToIngest.workflowMgrUrl</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+					<property name="allowedArgs">
+						<list>
+							<value>http://.*:\d*</value>
+						</list>
+					</property>
+				</bean>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="clientTransferer" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="ct" />
+		<property name="longOption" value="clientTransferer" />
+		<property name="description" value="File Manager data transferer factory class" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="class" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="StdProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="AutoDetectProductCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.clientTransferer</value>
+						<value>MetExtractorProductCrawler.clientTransferer</value>
+						<value>AutoDetectProductCrawler.clientTransferer</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.ClassExistsCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="requiredMetadata" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="rqm" />
+		<property name="longOption" value="requiredMetadata" />
+		<property name="type" value="java.util.List" />
+		<property name="description" value="Metadata required for ingest to take place" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="metadata_elements" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="StdProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="AutoDetectProductCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.requiredMetadata</value>
+						<value>MetExtractorProductCrawler.requiredMetadata</value>
+						<value>AutoDetectProductCrawler.requiredMetadata</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="actionIds" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="ais" />
+		<property name="longOption" value="actionIds" />
+		<property name="type" value="java.util.List" />
+		<property name="description" value="CrawlerActions that should be performed" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="CrawlerAction ids" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="StdProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="AutoDetectProductCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.actionIds</value>
+						<value>MetExtractorProductCrawler.actionIds</value>
+						<value>AutoDetectProductCrawler.actionIds</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="preCondIds" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="pids" />
+		<property name="longOption" value="preCondIds" />
+		<property name="type" value="java.util.List" />
+		<property name="description" value="PreConditionComparator ids that must pass before any metadata extraction will run" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="PreConditionComparator ids" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>MetExtractorProductCrawler.preCondIds</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="noRecur" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="nr" />
+		<property name="longOption" value="noRecur" />
+		<property name="description" value="Turns off recursive crawling - will only process files in productPath directory" />
+		<property name="type" value="boolean" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+	        <list>
+				<value>true</value>
+	        </list>
+        </property>
+        <property name="required" value="false" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="StdProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="AutoDetectProductCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.noRecur</value>
+						<value>MetExtractorProductCrawler.noRecur</value>
+						<value>AutoDetectProductCrawler.noRecur</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="crawlForDirs" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="cfd" />
+		<property name="longOption" value="crawlForDirs" />
+		<property name="description" value="Will crawl for directories instead of files" />
+		<property name="type" value="boolean" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+	        <list>
+				<value>true</value>
+	        </list>
+        </property>
+		<property name="required" value="false" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="StdProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="AutoDetectProductCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.crawlForDirs</value>
+						<value>MetExtractorProductCrawler.crawlForDirs</value>
+						<value>AutoDetectProductCrawler.crawlForDirs</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="skipIngest" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="si" />
+		<property name="longOption" value="skipIngest" />
+		<property name="description" value="Will skip ingest to file manager and any post ingest actions" />
+		<property name="hasArgs" value="false" />
+		<property name="required" value="false" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="StdProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="AutoDetectProductCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.skipIngest</value>
+						<value>MetExtractorProductCrawler.skipIngest</value>
+						<value>AutoDetectProductCrawler.skipIngest</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="daemonPort" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="dp" />
+		<property name="longOption" value="daemonPort" />
+		<property name="type" value="int" />
+		<property name="description" value="Cause crawler to become a daemon with a XML-RPC webserver started on the given port number" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="portNum" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="StdProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="AutoDetectProductCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.daemonPort</value>
+						<value>MetExtractorProductCrawler.daemonPort</value>
+						<value>AutoDetectProductCrawler.daemonPort</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+					<property name="allowedArgs">
+						<list>
+							<value>\d*</value>
+						</list>
+					</property>
+				</bean>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="daemonWait" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="dw" />
+		<property name="longOption" value="daemonWait" />
+		<property name="type" value="int" />
+		<property name="description" value="Cause crawler to become a daemon and sleep for given number of seconds between crawls" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="seconds" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="StdProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="AutoDetectProductCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.daemonWait</value>
+						<value>MetExtractorProductCrawler.daemonWait</value>
+						<value>AutoDetectProductCrawler.daemonWait</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+					<property name="allowedArgs">
+						<list>
+							<value>\d*</value>
+						</list>
+					</property>
+				</bean>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="productPath" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="pp" />
+		<property name="longOption" value="productPath" />
+		<property name="description" value="Root directory to crawl" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="directory" />
+		<property name="required" value="true" />
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.productPath</value>
+						<value>MetExtractorProductCrawler.productPath</value>
+						<value>AutoDetectProductCrawler.productPath</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="metFileExtension" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="mfx" />
+		<property name="longOption" value="metFileExtension" />
+		<property name="description" value="The file extension of existing and to be created PCS metadata files" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="file extension" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="StdProductCrawler" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="AutoDetectProductCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>StdProductCrawler.metFileExtension</value>
+						<value>DeleteMetadataFile.fileExtension</value>
+						<value>MoveMetadataFileToBackupDir.fileExtension</value>
+						<value>MoveMetadataFileToFailureDir.fileExtension</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="metExtractor" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="mx" />
+		<property name="longOption" value="metExtractor" />
+		<property name="description" value="Metadata extractor class to use" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="class" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>MetExtractorProductCrawler.metExtractor</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.ClassExistsCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="metExtractorConfig" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="mxc" />
+		<property name="longOption" value="metExtractorConfig" />
+		<property name="description" value="Config file for metadata extractor" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="file" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>MetExtractorProductCrawler.metExtractorConfig</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="mimeExtractorRepo" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="mxr" />
+		<property name="longOption" value="mimeExtractorRepo" />
+		<property name="description" value="Mime-type to metadata extractor mapping xml file" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="file" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="AutoDetectProductCrawler" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>AutoDetectProductCrawler.mimeExtractorRepo</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+		<property name="validators">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="pushpullMetFileExtension" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="ppmfx" />
+		<property name="longOption" value="pushpullMetFileExtension" />
+		<property name="description" value="File extension of push-pull metadata files" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="file extension" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="StdProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="MetExtractorProductCrawler" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="AutoDetectProductCrawler" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+				<property name="properties">
+					<list>
+						<value>DeletePushpullMetFile.fileExtension</value>
+						<value>MovePushpullMetFileToBackupDir.fileExtension</value>
+						<value>MovePushpullMetFileToFailureDir.fileExtension</value>
+						<value>CheckThatPushPullMetFileExists.fileExtension</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/crawler/src/main/resources/logging.properties b/0.8.1-rc1/crawler/src/main/resources/logging.properties
new file mode 100644
index 0000000..f3244d6
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/logging.properties
@@ -0,0 +1,64 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.FileHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = ../logs/cas_crawler%g.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 5
+java.util.logging.FileHandler.append = true
+java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging level for the subsystems
+
+org.apache.oodt.cas.crawl.level = ALL
+
+org.apache.oodt.cas.crawl.action.level = ALL
+
+org.apache.oodt.cas.crawl.typedetection.level = ALL
+
+org.apache.oodt.cas.crawl.util.level = ALL
+
+org.apache.oodt.cas.crawl.config.level = ALL
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = INFO
+httpclient.wire.header.level = INFO
+httpclient.wire.level = INFO
+
+# spring framework logging
+org.springframework.beans.level = SEVERE
+org.springframework.core.level = SEVERE
+org.springframework.level = SEVERE
+org.springframework.beans.factory.level = SEVERE
+org.springframework.beans.factory.config.level = SEVERE
+org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.level = SEVERE
+org.apache.oodt.cas.crawl.util.CasPropertyPlaceholderConfigurer.level = SEVERE
+sun.net.level = SEVERE
diff --git a/0.8.1-rc1/crawler/src/main/resources/naming-beans.xml b/0.8.1-rc1/crawler/src/main/resources/naming-beans.xml
new file mode 100644
index 0000000..c8da5ef
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/naming-beans.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean id="ExampleNamingConv" class="org.apache.oodt.cas.metadata.filenaming.PathUtilsNamingConvention">
+    <property name="namingConv" value="[ProductType].[NominalDate].txt" />
+  </bean>
+</beans>
diff --git a/0.8.1-rc1/crawler/src/main/resources/precondition-beans.xml b/0.8.1-rc1/crawler/src/main/resources/precondition-beans.xml
new file mode 100644
index 0000000..574cd7c
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/main/resources/precondition-beans.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor" />
+  <bean class="org.apache.oodt.cas.crawl.util.CasPropertyPlaceholderConfigurer">
+
+    <!-- Allow for system-level properties to override all properties below -->
+    <property name="systemPropertiesMode" value="2" />
+
+    <!-- Default Properties -->
+    <property name="properties">
+      <props>
+        <prop key="crawler.pushpull.met.file.ext">[PUSHPULL_MET_FILE_EXT]</prop>
+        <prop key="crawler.filemgr.url">[FILEMGR_URL]</prop>
+      </props>
+    </property>
+  </bean>
+
+	<!-- Precondition Comparators -->
+	<bean id="CheckThatPushPullMetFileExists" lazy-init="true" class="org.apache.oodt.cas.metadata.preconditions.ExistanceCheckComparator">
+    <property name="fileExtension" value="${crawler.pushpull.met.file.ext}" />
+		<property name="description" value="Checks if the push-pull metadata file exists for the current data file" />
+		<property name="compareItem">
+			<value type="java.lang.Boolean">true</value>
+		</property>
+		<property name="type" value="equal_to" />
+	</bean>
+
+	<bean id="CheckThatDataFileSizeIsGreaterThanZero" lazy-init="true" class="org.apache.oodt.cas.metadata.preconditions.FileSizeComparator">
+		<property name="description" value="Check if the current data file size is greater than zero" />
+		<property name="compareItem">
+			<value type="java.lang.Long">0</value>
+		</property>
+		<property name="type" value="greater_than" />
+	</bean>
+
+	<bean id="AprioriUniquessCheckWithFilemgr" lazy-init="true" class="org.apache.oodt.cas.crawl.comparator.FilemgrUniquenessCheckComparator">
+		<property name="description" value="Checks where the current data file existing in the filemgr based on its FILENAME" />
+		<property name="compareItem">
+			<value type="java.lang.Boolean">false</value>
+		</property>
+		<property name="type" value="equal_to" />
+		<property name="filemgrUrl" value="${crawler.filemgr.url}" />
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/crawler/src/site/resources/images/cas-crawler.jpg b/0.8.1-rc1/crawler/src/site/resources/images/cas-crawler.jpg
new file mode 100644
index 0000000..d910046
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/site/resources/images/cas-crawler.jpg
Binary files differ
diff --git a/0.8.1-rc1/crawler/src/site/resources/images/cas-crawler.psd b/0.8.1-rc1/crawler/src/site/resources/images/cas-crawler.psd
new file mode 100644
index 0000000..e04e899
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/site/resources/images/cas-crawler.psd
Binary files differ
diff --git a/0.8.1-rc1/crawler/src/site/resources/images/crawler-extension-points.png b/0.8.1-rc1/crawler/src/site/resources/images/crawler-extension-points.png
new file mode 100644
index 0000000..c1ba315
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/site/resources/images/crawler-extension-points.png
Binary files differ
diff --git a/0.8.1-rc1/crawler/src/site/resources/images/crawler-object-model.png b/0.8.1-rc1/crawler/src/site/resources/images/crawler-object-model.png
new file mode 100644
index 0000000..7c3394a
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/site/resources/images/crawler-object-model.png
Binary files differ
diff --git a/0.8.1-rc1/crawler/src/site/resources/images/crawler-state-diagram.png b/0.8.1-rc1/crawler/src/site/resources/images/crawler-state-diagram.png
new file mode 100644
index 0000000..d815e3a
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/site/resources/images/crawler-state-diagram.png
Binary files differ
diff --git a/0.8.1-rc1/crawler/src/site/resources/images/crawler-use-case-1.png b/0.8.1-rc1/crawler/src/site/resources/images/crawler-use-case-1.png
new file mode 100644
index 0000000..d4c09de
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/site/resources/images/crawler-use-case-1.png
Binary files differ
diff --git a/0.8.1-rc1/crawler/src/site/resources/images/crawler_phases.png b/0.8.1-rc1/crawler/src/site/resources/images/crawler_phases.png
new file mode 100644
index 0000000..60251ed
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/site/resources/images/crawler_phases.png
Binary files differ
diff --git a/0.8.1-rc1/crawler/src/site/site.xml b/0.8.1-rc1/crawler/src/site/site.xml
new file mode 100644
index 0000000..00d8684
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/site/site.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<project name="cas-crawler">
+
+  <body>
+    <links>
+      <item name="OODT" href="../oodt-site/"/>
+    </links>
+
+    <menu ref="reports" inherit="bottom"/>
+    <menu name="Software Documentation">
+      <item name="User Guide" href="user/"/>
+    </menu>
+  </body>
+</project>
diff --git a/0.8.1-rc1/crawler/src/site/xdoc/user/index.xml b/0.8.1-rc1/crawler/src/site/xdoc/user/index.xml
new file mode 100644
index 0000000..845c432
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/site/xdoc/user/index.xml
@@ -0,0 +1,487 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS Crawler User Guide</title>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+   </properties>
+
+   <body>
+      <section name="User Guide">
+        <p>
+          This is the user guide for the OODT Catalog and Archive Service (CAS) Crawler Framework, 
+          or CAS Crawler for short. This guide explains the CAS Crawler architecture 
+          including its extension points. The guide also discusses available services provided 
+          by the CAS Crawler, how to utilize them, and the different APIs that exist. The guide 
+          concludes with a description of CAS Crawler use cases.
+        </p>     
+      </section>
+      <section name="Architecture">
+        <p>The CAS Crawler Framework represents an effort to standardize the common ingestion activities 
+        that occur in data acquisition and archival. These types of activities regularly involve identification 
+        of files and directories to crawl (based on e.g., mime type, regular expressions, or direct user 
+        input), satisfaction of ingestion pre-conditions (e.g., the current crawled file has not been 
+        previously ingested), followed by metadata extraction. After metadata extraction, crawled data follows 
+        a standard three state lifecycle:
+        </p>
+          <ol>
+           <li>preIngestion - where e.g., a file may be unzipped or pre-processed prior to ingestion;</li>
+           <li>postIngestion success, indicating a successful ingestion to the file management component has occurred 
+           and e.g., the origin data file from the ingest area should be deleted; and</li>
+           <li>postIngestion failure, indicating that ingestion was not successful and some corrective action, 
+           e.g., moving the failed file to a failure area for later examination, should occur.</li>
+          </ol>
+
+          <p><img src='../images/crawler_phases.png' alt='Crawler Phase Model'/></p>
+          <p><img src='../images/crawler-state-diagram.png' alt='Detailed Crawler Phase Model'/></p>
+          
+         <p>The critical objects managed by the CAS Crawler framework include:</p>
+        
+        <ul>
+         <li>Crawler Config - Configures a Product Crawler, providing specialized options, such as specifying
+         the Crawler Framework URL to talk to, specifying the Met Extractor to call (in the case of the Met Extractor Product
+         Crawler), or specifying some property for a Crawler Action.</li>
+         <li>Product Crawler - Crawlers crawl a starting product path, looking for Products, which are collections of 
+         one or more files, and an associated Metadata object. Metadata can be:
+           <ul>
+            <li>Provided ahead of time - in this case, the Product Crawler reads the Metadata file, looking for <code>Filename</code>, 
+            <code>FileLocation</code>, and <code>ProductType</code> met keys. The Crawler Framework provides a <code>StdProductCrawler</code>
+            for this scenario.</li>
+            <li>Generated on the fly, using a CAS Met Extractor - in this case, the Product Crawler calls a CAS Met Extractor, and configures
+            it with an associated Met Extractor Config File, and uses this mechanism to obtain the Metadata for a Product. After the Metadata is
+            obtained, the Product Crawler engages in the same procedure as for the StdProductCrawler case. The Crawler Framework provides a
+            <code>MetExtractorProductCrawler</code> for this scenario.</li>
+            <li>Generated on the fly, using a CAS Met Extractor defined by a particualr Product mime type, or regular expression identifier - in this
+            case, Met Extractors are called on the fly to generate a Product's metadata. The Met Extractors are called based on a Product's mime type association, 
+            or by a regular expression identifying the Product file(s)'s pattern. The Crawler Framework provides an <code>AutoDetectProductCrawler</code> for this
+            scenario.</li>
+           </ul>
+         </li>
+         <li>Action - Crawler Actions are tasks that the Crawler can perform that are associated with one of the three above phases. Each Action can be associated
+         with zero or more Crawler Phases. Examples of Crawler Actions are provided in the Appendix.</li>
+         <li>Crawler Phase - Crawler Phases are one of the three aforementioned phases of the Crawler lifecycle: preIngest, postIngestSuccess, or postIngestFailure. Each
+         Phase can have zero or more associated Crawler Actions.</li>
+        </ul>
+
+        <p>Each Product Crawler is configured by exactly one Crawler Config. Each Product Crawler has 1...* Crawler Actions
+        which are each associated with 1...* Crawler Phases. Each Product Crawler crawls 1...* Products, which are each associated
+        with exactly 1 Metadata object. These relationships are shown in the below figure.</p>
+        
+        <p><img src="../images/crawler-object-model.png" alt="Crawler Object Model"/></p>
+      
+        <subsection name="Extension Points">
+          <p>
+          There are several extension points for the Crawler Framework. An extension point is an interface 
+          within the crawler framework that can have many implementations. This is particularly useful when 
+          it comes to software component configuration because it allows different implementations of an 
+          existing interface to be selected at deployment time. So, the crawler framework may 
+          leverage a preIngest action that checks against a Crawler Framework Catalog to determine if a Product has
+          already been ingested, or the crawler may choose a preIngest action that performs an MD5 checksum
+          on the Product before ingesting. The selection of the actual component implementations is handled 
+          entirely by the extension point mechanism. Using extension points, it is fairly simple to support many 
+          different types of what are typically referred to as &quot;plug-in architectures&quot; Each of the core 
+          extension points for the Crawler Framework is described below:</p>
+          
+          <table>
+            <tr>
+              <td>Crawler Daemon</td>
+              <td>The Crawler Daemon extension point is responsible for periodically (as defined by the User) 
+              executing a particular ProductCrawler, as well as providing statistics on crawls (number of crawls,
+              average crawl time, etc.).
+              </td>
+            </tr>
+            <tr>
+              <td>Product Crawler</td>
+              <td>The Product Crawler extension point is responsible for defining the method in which Crawler
+              Preconditions are checked before ingestion, for managing the 3-phase ingestion process, and for dictating
+              the method by which Metadata is obtained for a particular product. In addition, the extension point
+              also specifies how Product files are crawled on disk.
+              </td>
+            </tr>
+            <tr>
+              <td>Mime Type Extractor Repository</td>
+              <td>The Mime Type Extractor Repository is an extension point that specifies how
+              Met Extractors are associated with mime types related to a Product file being ingested. 
+              </td>
+            </tr>
+            <tr>
+              <td>Crawler Action Repository</td>
+              <td>The Crawler Action Repository is a home for all Crawler Actions, mapping each Action
+              to a lifecycle phase (preIngest, postIngestSuccess, or postIngestFailure).
+              </td>
+            </tr>
+             <tr>
+              <td>Precondition Comparator</td>
+              <td>The Precondition Comparator extension point allows for the specification of preconditions
+              that must be satisfied before metadata is extracted for a particular crawled Product, and ultimately
+              which must be satisfied before ingestion.
+              </td>
+            </tr>
+             <tr>
+              <td>Met Extractor, Met Extractor Config, Met Extractor Config Reader</td>
+              <td>The Crawler Framework leverages CAS Metadata's Met Extractor, Met Extractor Config, and
+              Met Extractor Config Reader extension point. Each Met Extractor is provided a Met Extractor Config
+              file, which is read by an associated Met Extractor Config Reader, allowing a User to entirely customize
+              how Metadata is extracted for a particular Product file.
+              </td>
+            </tr>          
+          
+          </table>
+          
+          <p>The relationships between the extension points for the Crawler Framework are shown in the below
+          figure.
+          </p>
+          
+          <p><img width='600' src="../images/crawler-extension-points.png" alt="Crawler Extension Points"/></p>
+        
+        </subsection>
+        <subsection name="Key Capabilities">
+        <p>The Crawler Framework is responsible for providing the necessary key capabilities for manually 
+        and automatically ingesting files and metadata. Each high level capability provided by the 
+        Crawler Framework is detailed below:</p>
+        
+        <ol>
+          <li>Automatic and manual ingesting of Products - The Crawler Framework can easily be configured
+          as a Daemon process that periodically crawls a starting directory for Products, or as a 
+          standalone program, performing ingestion and then terminating.
+          </li>
+          <li>Command-line interface, as well as APIs - The Crawler Framework can be called from a simple
+          command line interface, allowing GNU-style options to configure a crawler, and start ingesting. In
+          addition, the Crawler also provides Java-based APIs that allows a user to integrate crawling into
+          her Java application with ease.
+          </li>
+          <li>Configurable Actions, and Action Extensibility Mechanism - The Crawler Framework ships with a set
+          of predefined actions out of the box (delete data file, after postIngestSuccess, delete met file, after
+          the same, check on pre ingest for product uniqueness, etc.) that provide an excellent starting point for
+          leveraging the Crawler Framework in a user's application. If more specific functionality is required, a
+          user has the ability to write her own Crawler Action by implementing the Crawler Action interface.</li>    
+          <li>Configurable and extensible Preconditions for Met Extraction - Much like Crawler Actions, Preconditions
+          allow a user to customize the Crawler Framework, specifying if, how, and when, Met Extractors should be called
+          by a Crawler to extract metadata from an underlying Product.
+          </li>
+          <li>Support for a wide variety of Product file identification mechanisms - The Crawler Framework provides three
+          different crawlers out of the box that enforce a particular Product file identification strategy, e.g., StdProductCrawler
+          looks for Metadata files, MetExtractorProductCrawler generates Metadata files on the fly, and AutoDetectProductCrawler
+          uses mime type information and file regular expressions to identify Prouct files to crawl. If more customized functionality
+          is required, the user can extend one of these existing ProductCrawlers, or write an entirely new crawler.</li>
+          <li>Ability to plug in Met Extraction rules - A user can leverage a custom developed Met Extractor to generate Product metadata
+          used by the crawler during the ingestion process. Met Extractors are easily plugged in using Java's class loading mechanism
+          the capabilities of the <a href="../../metadata/">CAS Metadata Framework</a>.</li>
+          <li>Communication over lightweight, standard protocols – The Crawler Framework uses XML-RPC, as its main 
+          external interface, when the Crawler runs in Daemon mode. XML-RPC, the little brother of SOAP, is 
+          fast, extensible, and uses the underlying HTTP protocol for data transfer.</li>
+         </ol>
+          
+          <p>This capability set is not exhaustive, and is meant to give the user a &quot;feel&quot; for what 
+          general features are provided by the Crawler Framework. Most likely the user will find that the 
+          Crawler Framework provides many other capabilities besides those described here.</p>
+          
+        </subsection>
+        <subsection name="Current Extension Point Implementations">
+        
+         <p>There is at least one implementation of all of the aforementioned extension points for 
+         Crawler Framework. Each existing extension point implementation is detailed below:</p>
+
+         <ul>
+           <li><b>Crawler Actions</b><br/>
+            <ol>
+             <li>Delete File – deletes an origin data file from its location in the staging area. Tied to
+             the postIngestSuccess stage.</li>
+             <li>FilemgrUniquenessChecker - Checks with the Crawler Framework after Metadata extraction has occured and
+             determines if the product has been ingested into the Crawler Framework. Tied to the preIngest stage.</li>
+             <li>MimeTypeCrawlerAction - Calls a specified Crawler Action is the Product matches a specified list of
+             mime-types. Tied to the preIngest stage.</li>
+             <li>WorkflowMgrStatusUpdate - Notifies the Workflow Manager that a file has been ingested into the File
+             Manager successfully. Tied to the postIngestSuccess stage.</li>
+           </ol>
+           </li>
+           <li><b>Crawler Precondition Comparators</b><br/>
+             <ol>
+               <li>FilemgrUniqunessCheckComparator - Determines, before Metadata extraction has occured, whether or not
+               a Product has been ingested into the Crawler Framework.
+               </li>
+             </ol>
+           </li>
+           <li><b>Crawler Daemons (Controller and Daemon)</b><br/>
+             <ol>
+               <li>XML-RPC – The default implementation of the Crawl Daemon Controller and the Crawler Daemon leverage
+               XML-RPC, the little brother of SOAP, as their mode of communication.
+               </li>
+             </ol>
+           </li>  	
+           </ul>  
+        
+        </subsection>
+      
+      </section>
+      <section name="Configuration and Installation">
+       <p>
+       To install the Crawler Framework, you need to download a release
+       of the software, available from its home web site. For bleeding-edge features, you can
+       also check out the cas-crawler trunk project from the Apache OODT subversion repository. You can browse 
+       the repository using ViewCVS, located at:</p>
+       
+       <screen>http://svn.apache.org/viewvc/oodt/</screen>
+       
+       <p>The actual web url for the repository is located at:</p>
+       
+       <screen>https://svn.apache.org/repos/asf/oodt</screen>
+
+       <p>To check out the Crawler Framework, use your favorite Subversion client.</p>
+      
+      <subsection name="Project Organization">
+        <p>
+       The cas-crawler project follows the traditional Subversion-style <code>trunk</code>, <code>tag</code>
+       and <code>branches</code> format. Trunk corresponds to the latest and greatest development on the
+       cas-crawler. Tags are official release versions of the project. Branches correspond to deviations 
+       from the trunk large enough to warrant a separate development tree. </p>
+
+       <p>For the purposes of this the User Guide, we'll assume you already have downloaded a built release
+       of the Crawler Framework, from its web site. If you were building cas-crawler from the trunk, a tagged release 
+       (or branch) the process would be quite similar. To build cas-crawler, you would need the Apache Maven 
+       software. Maven is an XML-based, project management system similar to Apache Ant, but with many extra 
+       bells and whistles. Maven makes cross-platform project development a snap. You can download Maven from:
+
+       <a href="http://maven.apache.org">http://maven.apache.org/</a>
+
+       All cas-crawler releases post 1.x.0 are now <b>Maven 2 compatible</b>. This is <b>very</b> important. 
+       That means that if you have any cas-crawler release > 1.x.0, you will need Maven 2 to compile the software, 
+       and Maven 1 will no longer work.</p>
+       
+       <p>Follow the procedures in the below Sections to build a fresh copy of the Crawler Framework. These procedures
+       are specifically targeted on using Maven 2 to build the software: 
+        </p>      
+      
+      </subsection>
+      
+      <subsection name="Building the Crawler Framework">
+        <p>
+          <ol>
+            <li>cd to cas-crawler, and then type:
+           <source># mvn package</source>
+           This will perform several tasks, including compiling the source code, downloading 
+           required jar files, running unit tests, and so on. When the command completes, cd 
+           to the <code>target</code> directory within cas-crawler. This will contain the build of the 
+           Crawler Framework component, of the following form:
+           
+           <source>
+            cas-crawler-${version}-dist.tar.gz
+           </source>
+           
+           This is a distribution tar ball, that you would copy to a deployment directory, such as
+           <code>/usr/local/</code>, and then unpack using <code># tar xvzf </code>. The resultant directory 
+           layout from the unpacked tarball is as follows:
+           
+           <source>
+            bin/ etc/ logs/ doc/ lib/ policy/ LICENSE.txt CHANGES.txt
+           </source>
+            <ul>
+              <li>bin - contains the &quot;crawler_launcher&quot; server script, and the &quot;crawlctl&quot; client script.</li>
+              <li>etc - contains the logging.properties file for the Crawler Framework.</li>
+              <li>logs - the default directory for log files to be written to.</li>
+              <li>doc - contains Javadoc documentation, and user guides for using the particular CAS component.</li>
+              <li>lib - the required Java jar files to run the Crawler Framework.</li>
+              <li>policy – the default Spring-XML based configuration for Crawler Actions, Preconditions, Command Line options, and Crawlers.</li>
+              <li>CHANGES.txt - contains the CHANGES present in this released version of the CAS component.</li>
+              <li>LICENSE.txt - the LICENSE for the CAS Crawler Framework project.</li>
+            </ul>
+          </li>
+         </ol>        
+        </p>
+      
+      </subsection>
+      <subsection name="Deploying the Crawler Framework">
+      <p>To deploy the Crawler Framework, you'll need to create an installation directory. Typically this 
+      would be somewhere in /usr/local (on *nix style systems), or C:\Program Files\ (on windows 
+      style systems). We'll assume that you're installing on a *nix style system though the Windows 
+      instructions are quite similar.</p>
+
+      <p>Follow the process below to deploy the Crawler Framework:</p>
+
+        <ol>
+         <li>Copy the binary distribution to the deployment directory
+         <source># cp -R cas-crawler/trunk/target/cas-crawler-${version}-dist.tar.gz /usr/local/</source>
+         </li>
+         <li>Untar the distribution
+         <source># cd /usr/local ; tar xvzf cas-crawler-${version}-dist.tar.gz</source>
+         </li>
+         <li>Set up a symlink
+         <source># ln -s /usr/local/cas-crawler-${version} /usr/local/crawler</source>
+         </li>
+         <li>Set your <code>JAVA_HOME</code> environment variable to point to the location of your 
+         installed JRE runtime.
+         </li>
+       </ol>
+   
+     <p>Other configuration options are possible: check the <a href="../apidocs">API documentation</a>, 
+     as well as the comments within the XML files in the policy directory to find out the rest of the configurable 
+     properties for the extension points you choose. A full listing of all the extension point factory 
+     class names are provided in the Appendix. After step 4, you are officially done configuring the Crawler
+     Framework for deployment.</p>   
+      
+      </subsection>
+      <subsection name="Running the Crawler Framework">
+      <p>To run the crawler_launcher, cd to <code>/usr/local/crawler/bin</code> and type:</p>
+
+      <source># ./crawler_launcher -h</source>
+
+      <p>This will print the help options for the Crawler launcher script. Your Crawler Framework 
+      is now ready to run! You can test out the Crawler Framework by running a simple ingest 
+      command shown below. Be sure that a separate File Manager instance is up and running on the default
+      port of 9000, running on localhost, before starting this test command (see the 
+      <a href="../../filemgr/user/">File Manager User Guide</a> for more information).
+      
+      First create a simple text file called &quot;blah.txt&quot; and place it inside a test directory, e.g., <code>/data/test</code>. Then, create a default 
+      metadata file for the product, using the schema or DTD
+      provided in the cas-metadata project. An example XML file might be:</p>
+      
+      <!-- FIXME: change namespace URI? -->
+      <source>
+        &lt;cas:metadata xmlns:cas=&quot;http://oodt.jpl.nasa.gov/1.0/cas&quot;&gt;
+         &lt;keyval&gt;
+           &lt;key&gt;Filename&lt;/key&gt;
+           &lt;val&gt;blah.txt&lt;/val&gt;
+         &lt;/keyval&gt;
+         &lt;keyval&gt;
+           &lt;key&gt;FileLocation&lt;/key&gt;
+           &lt;val&gt;/data/test&lt;/val&gt;
+         &lt;/keyval&gt;         
+         &lt;keyval&gt;
+           &lt;key&gt;ProductType&lt;/key&gt;
+           &lt;val&gt;GenericFile&lt;/val&gt;
+         &lt;/keyval&gt;   
+        &lt;/cas:metadata&gt;
+      </source>
+      
+      <p>Call this metadata file <code>blah.txt.met</code>, and place it also in <code>/data/test</code>. 
+      Then, run the below command, assuming that you started a File Manager on localhost on the default port of <code>9000</code>:</p>
+
+      <source># ./crawler_launcher \
+               --crawlerId StdProductCrawler \
+               --productPath /data/test \
+               --filemgrUrl http://localhost:9000/ \
+               --failureDir /tmp \
+               --actionIds DeleteDataFile MoveDataFileToFailureDir Unique \
+               --metFileExtension met \
+               --clientTransferer org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory
+      </source>
+
+      <p>You should see a response message at the end similar to:</p>
+
+      <source>
+      log4j:WARN No appenders could be found for logger (org.springframework.context.support.FileSystemXmlApplicationContext).
+      log4j:WARN Please initialize the log4j system properly.
+      http://localhost:9000/
+      StdProductCrawler
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.crawl.ProductCrawler crawl
+      INFO: Crawling /data/test
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.crawl.ProductCrawler handleFile
+      INFO: Handling file /data/test/blah.txt
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.metadata.extractors.MetReaderExtractor extrMetadata
+      INFO: Reading metadata from /data/test/blah.txt.met
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.crawl.ProductCrawler ingest
+      INFO: ProductCrawler: Ready to ingest product: [/data/test/blah.txt]: ProductType: [GenericFile]
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.filemgr.ingest.StdIngester setFileManager
+      INFO: StdIngester: connected to file manager: [http://localhost:9000/]
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferer setFileManagerUrl
+      INFO: Local Data Transfer to: [http://localhost:9000/] enabled
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.filemgr.ingest.StdIngester ingest
+      INFO: StdIngester: ingesting product: ProductName: [blah.txt]: ProductType: [GenericFile]: FileLocation: [/data/test/]
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.filemgr.versioning.VersioningUtils createBasicDataStoreRefsFlat
+      FINE: VersioningUtils: Generated data store ref: file:/Users/mattmann/files/blah.txt/blah.txt from origRef: file:/data/test/blah.txt
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.filemgr.system.XmlRpcFileManager runExtractors
+      INFO: Running Met Extractor: [org.apache.oodt.cas.filemgr.metadata.extractors.CoreMetExtractor] for product type: [GenericFile]
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.filemgr.system.XmlRpcFileManager runExtractors
+      INFO: Running Met Extractor: [org.apache.oodt.cas.filemgr.metadata.extractors.examples.MimeTypeExtractor] for product type: [GenericFile]
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.filemgr.catalog.LuceneCatalog toDoc
+      WARNING: No Metadata specified for product [blah.txt] for required field [DataVersion]: Attempting to continue processing metadata
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient ingestProduct
+      FINEST: File Manager Client: clientTransfer enabled: transfering product [blah.txt]
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferer moveFile
+      INFO: LocalDataTransfer: Moving File: file:/data/test/blah.txt to file:/Users/mattmann/files/blah.txt/blah.txt
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.filemgr.catalog.LuceneCatalog toDoc
+      WARNING: No Metadata specified for product [blah.txt] for required field [DataVersion]: Attempting to continue processing metadata
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.crawl.ProductCrawler ingest
+      INFO: Successfully ingested product: [/data/test/blah.txt]: product id: 72db4bba-658a-11de-bedb-77f2d752c436
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.crawl.ProductCrawler handleFile
+      INFO: Successful ingest of product: [/data/test/blah.txt]
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.crawl.ProductCrawler performProductCrawlerActions
+      INFO: Performing action (id = DeleteDataFile : description = Deletes the current data file)
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.crawl.action.DeleteFile performAction
+      INFO: Deleting file /data/test/blah.txt
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.crawl.ProductCrawler handleFile
+      INFO: Handling file /data/test/blah.txt.met
+      Jun 30, 2009 8:26:57 AM org.apache.oodt.cas.crawl.ProductCrawler handleFile
+      WARNING: Failed to pass preconditions for ingest of product: [/data/test/blah.txt.met]
+      </source>
+
+    <p>which means that everything installed okay!</p>
+
+      </subsection>
+      
+      </section>
+      <section name="Use Cases">
+        <p>
+          The Crawler Framework was built to support several of the above capabilities outlined in 
+          Section 3. In particular there were several use cases that we wanted to support, some 
+          of which are described below.        
+        </p>
+      
+         <p><img width='600' src="../images/crawler-use-case-1.png" alt="Crawler Framework Ingest Use Case"/></p>
+         
+         <p>The numbers in the above Figure correspond to a sequence of steps that occurs and a 
+         series of interactions between the different Crawler Framework extension points in order to 
+         perform the file ingestion activity. In Step 1, the Crawler Daemon determines if the Product 
+         file in the staging area matches a specified File Filter regular expression. In step 2, if the
+         Product file does match the desired filter, the Crawler Daemon checks with the File Manager 
+         (using the Ingester) to determine whether or not the Product file has been ingested. In step 3,
+         assuming that the Product file has <b>not</b> been ingested, then the Crawler Daemon ingests
+         the Product file into the File Manager using the Ingester interface. During the ingestion, 
+         Metadata is first extracted (in sub-step 1) and then the File Manager client interface is 
+         used (in sub-step 2) to ingest into the File Manager. During ingestion, the File Manager is
+         responsible for moving the Product file(s) into controlled access-storage and cataloging the
+         provided Product metadata.</p>
+         
+      </section>
+      <section name="Appendix">
+       <p>
+         Full list of Crawler Framework extension point classes and their associated property names from the 
+         Spring Bean XML files:       
+       </p>
+    
+       <table>
+         <tr>
+           <td>actions</td>
+           <td>org.apache.oodt.cas.crawl.action.DeleteFile<br/>
+               org.apache.oodt.cas.crawl.action.FilemgrUniquenessChecker<br/>
+               org.apache.oodt.cas.crawl.action.MimeTypeCrawlerAction<br/>
+               org.apache.oodt.cas.crawl.action.MoveFile<br/>
+               org.apache.oodt.cas.crawl.action.WorkflowMgrStatusUpdate
+           </td>
+         </tr>
+         <tr>
+           <td>preconditions</td>
+           <td>org.apache.oodt.cas.crawl.comparator.FilemgrUniquenessCheckComparator
+           </td>
+         </tr>
+       </table>
+      
+      </section>
+   </body>
+   
+</document>
diff --git a/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/StateAwareProductCrawler.java b/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/StateAwareProductCrawler.java
new file mode 100644
index 0000000..1c0ff61
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/StateAwareProductCrawler.java
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * {@link ProductCrawler} used for testing the appropriated states are
+ * entered for each part of the crawler's workflow.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class StateAwareProductCrawler extends ProductCrawler{
+
+   private boolean passPreconditions = true;
+   private boolean passExtraction = true;
+   private boolean passRenaming = true;
+   private boolean passRequiredMetadata = true;
+   private boolean passPreIngestActions = true;
+   private boolean passIngest = true;
+
+   private boolean ranPreconditions = false;
+   private boolean ranExtraction = false;
+   private boolean ranRenaming = false;
+   private boolean ranRequiredMetadata = false;
+   private boolean ranPreIngestActions = false;
+   private boolean ranIngest = false;
+   private boolean ranPostIngestSuccessActions = false;
+   private boolean ranPostIngestFailActions = false;
+
+   public void markFailPreconditions() {
+      passPreconditions = false;
+   }
+   
+   public void markFailExtraction() {
+      passExtraction = false;
+   }
+
+   public void markFailRenaming() {
+      passRenaming = false;
+   }
+
+   public void markFailRequiredMetadata() {
+      passRequiredMetadata = false;
+   }
+
+   public void markFailPreIngestActions() {
+      passPreIngestActions = false;
+   }
+
+   public void markSkipIngest() {
+      this.setSkipIngest(true);
+   }
+
+   public void markFailIngest() {
+      passIngest = false;
+   }
+
+   public boolean ranPreconditions() {
+      return ranPreconditions;
+   }
+
+   public boolean ranExtraction() {
+      return ranExtraction;
+   }
+
+   public boolean ranRenaming() {
+      return ranRenaming;
+   }
+
+   public boolean ranRequiredMetadata() {
+      return ranRequiredMetadata;
+   }
+
+   public boolean ranPreIngestActions() {
+      return ranPreIngestActions;
+   }
+
+   public boolean ranIngest() {
+      return ranIngest;
+   }
+
+   public boolean ranPostIngestSuccessActions() {
+      return ranPostIngestSuccessActions;
+   }
+
+   public boolean ranPostIngestFailActions() {
+      return ranPostIngestFailActions;
+   }
+
+   @Override
+   protected boolean passesPreconditions(File p) {
+      ranPreconditions = true;
+      return passPreconditions;
+   }
+
+   @Override
+   protected Metadata getMetadataForProduct(File p)
+      throws Exception {
+      ranExtraction = true;
+      if (passExtraction) {
+         return new Metadata();
+      } else {
+         throw new Exception("Failed Extraction");
+      }
+   }
+
+   @Override
+   protected File renameProduct(File p, Metadata m)
+         throws Exception {
+      ranRenaming = true;
+      if (passRenaming) {
+         return p;
+      } else {
+         throw new Exception("Failed Renaming");
+      }
+   }
+   
+   @Override
+   boolean containsRequiredMetadata(Metadata m) {
+      ranRequiredMetadata = true;
+      return passRequiredMetadata;
+   }
+
+   @Override
+   boolean performPreIngestActions(File p, Metadata m) {
+      ranPreIngestActions = true;
+      return passPreIngestActions;
+   }
+
+   @Override
+   boolean ingest(File p, Metadata m) {
+      ranIngest = true;
+      return passIngest;
+   }
+
+   @Override
+   boolean performPostIngestOnSuccessActions(File p, Metadata m) {
+      ranPostIngestSuccessActions = true;
+      return true;
+   }
+
+   @Override
+   boolean performPostIngestOnFailActions(File p, Metadata m) {
+      ranPostIngestFailActions = true;
+      return true;
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/TestProductCrawler.java b/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/TestProductCrawler.java
new file mode 100644
index 0000000..f0acef1
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/TestProductCrawler.java
@@ -0,0 +1,627 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl;
+
+//EasyMock static imports
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+//JDK imports
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.action.CrawlerAction;
+import org.apache.oodt.cas.crawl.action.CrawlerActionRepo;
+import org.apache.oodt.cas.crawl.status.IngestStatus;
+import org.apache.oodt.cas.crawl.structs.exceptions.CrawlerActionException;
+import org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory;
+import org.apache.oodt.cas.filemgr.ingest.Ingester;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.exceptions.IngestException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Spring imports
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+//Google imports
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link ProductCrawler}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestProductCrawler extends TestCase {
+
+   private static final String CRAWLER_CONFIG =
+      "src/main/resources/crawler-config.xml";
+
+   // Case1:
+   //  - Preconditions: fail
+   public void testHandleFileCase1() {
+      File p = new File("/tmp/data.dat");
+
+      // Setup Crawler.
+      StateAwareProductCrawler pc = new StateAwareProductCrawler();
+      pc.markFailPreconditions();
+
+      // Run Crawler.
+      IngestStatus status = pc.handleFile(p);
+
+      // Verify IngestStatus.
+      assertEquals(IngestStatus.Result.PRECONDS_FAILED, status.getResult());
+      assertEquals(p, status.getProduct());
+
+      // Verify correct methods were run. 
+      assertTrue(pc.ranPreconditions());
+      assertFalse(pc.ranExtraction());
+      assertFalse(pc.ranRenaming());
+      assertFalse(pc.ranRequiredMetadata());
+      assertFalse(pc.ranPreIngestActions());
+      assertFalse(pc.ranIngest());
+      assertFalse(pc.ranPostIngestSuccessActions());
+      assertFalse(pc.ranPostIngestFailActions());
+   }
+
+   // Case2:
+   //  - Preconditions: pass
+   //  - FailExtraction: fail
+   public void testHandleFileCase2() {
+      File p = new File("/tmp/data.dat");
+
+      // Setup Crawler.
+      StateAwareProductCrawler pc = new StateAwareProductCrawler();
+      pc.markFailExtraction();
+
+      // Run Crawler.
+      IngestStatus status = pc.handleFile(p);
+
+      // Verify IngestStatus.
+      assertEquals(IngestStatus.Result.FAILURE, status.getResult());
+      assertEquals(p, status.getProduct());
+
+      // Verify correct methods were run. 
+      assertTrue(pc.ranPreconditions());
+      assertTrue(pc.ranExtraction());
+      assertFalse(pc.ranRenaming());
+      assertFalse(pc.ranRequiredMetadata());
+      assertFalse(pc.ranPreIngestActions());
+      assertFalse(pc.ranIngest());
+      assertFalse(pc.ranPostIngestSuccessActions());
+      assertTrue(pc.ranPostIngestFailActions());
+   }
+
+   // Case3:
+   //  - Preconditions: pass
+   //  - FailExtraction: pass
+   //  - RenameProduct: fail
+   public void testHandleFileCase3() {
+      File p = new File("/tmp/data.dat");
+
+      // Setup Crawler.
+      StateAwareProductCrawler pc = new StateAwareProductCrawler();
+      pc.markFailRenaming();
+
+      // Run Crawler.
+      IngestStatus status = pc.handleFile(p);
+
+      // Verify IngestStatus.
+      assertEquals(IngestStatus.Result.FAILURE, status.getResult());
+      assertEquals(p, status.getProduct());
+
+      // Verify correct methods were run. 
+      assertTrue(pc.ranPreconditions());
+      assertTrue(pc.ranExtraction());
+      assertTrue(pc.ranRenaming());
+      assertFalse(pc.ranRequiredMetadata());
+      assertFalse(pc.ranPreIngestActions());
+      assertFalse(pc.ranIngest());
+      assertFalse(pc.ranPostIngestSuccessActions());
+      assertTrue(pc.ranPostIngestFailActions());
+   }
+
+   // Case4:
+   //  - Preconditions: pass
+   //  - FailExtraction: pass
+   //  - RenameProduct: pass
+   //  - RequiredMetadata: fail
+   public void testHandleFileCase4() {
+      File p = new File("/tmp/data.dat");
+
+      // Setup Crawler.
+      StateAwareProductCrawler pc = new StateAwareProductCrawler();
+      pc.markFailRequiredMetadata();
+
+      // Run Crawler.
+      IngestStatus status = pc.handleFile(p);
+
+      // Verify IngestStatus.
+      assertEquals(IngestStatus.Result.FAILURE, status.getResult());
+      assertEquals(p, status.getProduct());
+
+      // Verify correct methods were run. 
+      assertTrue(pc.ranPreconditions());
+      assertTrue(pc.ranExtraction());
+      assertTrue(pc.ranRenaming());
+      assertTrue(pc.ranRequiredMetadata());
+      assertFalse(pc.ranPreIngestActions());
+      assertFalse(pc.ranIngest());
+      assertFalse(pc.ranPostIngestSuccessActions());
+      assertTrue(pc.ranPostIngestFailActions());
+   }
+
+   // Case5:
+   //  - Preconditions: pass
+   //  - FailExtraction: pass
+   //  - RenameProduct: pass
+   //  - RequiredMetadata: pass
+   //  - PreIngestActions: fail
+   public void testHandleFileCase5() {
+      File p = new File("/tmp/data.dat");
+
+      // Setup Crawler.
+      StateAwareProductCrawler pc = new StateAwareProductCrawler();
+      pc.markFailPreIngestActions();
+
+      // Run Crawler.
+      IngestStatus status = pc.handleFile(p);
+
+      // Verify IngestStatus.
+      assertEquals(IngestStatus.Result.FAILURE, status.getResult());
+      assertEquals(p, status.getProduct());
+
+      // Verify correct methods were run. 
+      assertTrue(pc.ranPreconditions());
+      assertTrue(pc.ranExtraction());
+      assertTrue(pc.ranRenaming());
+      assertTrue(pc.ranRequiredMetadata());
+      assertTrue(pc.ranPreIngestActions());
+      assertFalse(pc.ranIngest());
+      assertFalse(pc.ranPostIngestSuccessActions());
+      assertTrue(pc.ranPostIngestFailActions());
+   }
+
+   // Case6:
+   //  - Preconditions: pass
+   //  - FailExtraction: pass
+   //  - RenameProduct: pass
+   //  - RequiredMetadata: pass
+   //  - PreIngestActions: pass
+   //  - SkipIngest: true
+   public void testHandleFileCase6() {
+      File p = new File("/tmp/data.dat");
+
+      // Setup Crawler.
+      StateAwareProductCrawler pc = new StateAwareProductCrawler();
+      pc.markSkipIngest();
+
+      // Run Crawler.
+      IngestStatus status = pc.handleFile(p);
+
+      // Verify IngestStatus.
+      assertEquals(IngestStatus.Result.SKIPPED, status.getResult());
+      assertEquals(p, status.getProduct());
+
+      // Verify correct methods were run. 
+      assertTrue(pc.ranPreconditions());
+      assertTrue(pc.ranExtraction());
+      assertTrue(pc.ranRenaming());
+      assertTrue(pc.ranRequiredMetadata());
+      assertTrue(pc.ranPreIngestActions());
+      assertFalse(pc.ranIngest());
+      assertFalse(pc.ranPostIngestSuccessActions());
+      assertFalse(pc.ranPostIngestFailActions());
+   }
+
+   // Case7:
+   //  - Preconditions: pass
+   //  - FailExtraction: pass
+   //  - RenameProduct: pass
+   //  - RequiredMetadata: pass
+   //  - PreIngestActions: pass
+   //  - SkipIngest: false
+   //  - Ingest: fail
+   public void testHandleFileCase7() {
+      File p = new File("/tmp/data.dat");
+
+      // Setup Crawler.
+      StateAwareProductCrawler pc = new StateAwareProductCrawler();
+      pc.markFailIngest();
+
+      // Run Crawler.
+      IngestStatus status = pc.handleFile(p);
+
+      // Verify IngestStatus.
+      assertEquals(IngestStatus.Result.FAILURE, status.getResult());
+      assertEquals(p, status.getProduct());
+
+      // Verify correct methods were run. 
+      assertTrue(pc.ranPreconditions());
+      assertTrue(pc.ranExtraction());
+      assertTrue(pc.ranRenaming());
+      assertTrue(pc.ranRequiredMetadata());
+      assertTrue(pc.ranPreIngestActions());
+      assertTrue(pc.ranIngest());
+      assertFalse(pc.ranPostIngestSuccessActions());
+      assertTrue(pc.ranPostIngestFailActions());
+   }
+
+   // Case8:
+   //  - Preconditions: pass
+   //  - FailExtraction: pass
+   //  - RenameProduct: pass
+   //  - RequiredMetadata: pass
+   //  - PreIngestActions: pass
+   //  - SkipIngest: false
+   //  - Ingest: pass
+   public void testHandleFileCase8() {
+      File p = new File("/tmp/data.dat");
+
+      // Setup Crawler.
+      StateAwareProductCrawler pc = new StateAwareProductCrawler();
+
+      // Run Crawler.
+      IngestStatus status = pc.handleFile(p);
+
+      // Verify IngestStatus.
+      assertEquals(IngestStatus.Result.SUCCESS, status.getResult());
+      assertEquals(p, status.getProduct());
+
+      // Verify correct methods were run. 
+      assertTrue(pc.ranPreconditions());
+      assertTrue(pc.ranExtraction());
+      assertTrue(pc.ranRenaming());
+      assertTrue(pc.ranRequiredMetadata());
+      assertTrue(pc.ranPreIngestActions());
+      assertTrue(pc.ranIngest());
+      assertTrue(pc.ranPostIngestSuccessActions());
+      assertFalse(pc.ranPostIngestFailActions());
+   }
+
+   public void testSetupIngester() {
+      ProductCrawler pc = createDummyCrawler();
+      pc.setClientTransferer(LocalDataTransferFactory.class.getCanonicalName());
+      pc.setupIngester();
+      assertNotNull(pc.ingester);
+   }
+
+   public void testLoadAndValidateActions() {
+      ProductCrawler pc = createDummyCrawler();
+      pc.setApplicationContext(new FileSystemXmlApplicationContext(
+            CRAWLER_CONFIG));
+      pc.loadAndValidateActions();
+      assertEquals(0, pc.actionRepo.getActions().size());
+
+      pc = createDummyCrawler();
+      pc.setApplicationContext(new FileSystemXmlApplicationContext(
+            CRAWLER_CONFIG));
+      pc.setActionIds(Lists.newArrayList("Unique", "DeleteDataFile"));
+      pc.loadAndValidateActions();
+      assertEquals(Sets.newHashSet(
+            pc.getApplicationContext().getBean("Unique"),
+            pc.getApplicationContext().getBean("DeleteDataFile")),
+            pc.actionRepo.getActions());
+   }
+
+   public void testValidateActions() throws CrawlerActionException {
+      // Test case invalid action.
+      ProductCrawler pc = createDummyCrawler();
+      pc.actionRepo = createMock(CrawlerActionRepo.class);
+
+      CrawlerAction action = createMock(CrawlerAction.class);
+      action.validate();
+      expectLastCall().andThrow(new CrawlerActionException());
+      expect(action.getId()).andReturn("ActionId");
+      replay(action);
+
+      expect(pc.actionRepo.getActions()).andReturn(
+            Sets.newHashSet(action));
+      replay(pc.actionRepo);
+      try {
+         pc.validateActions();
+         fail("Should have thrown RuntimeException");
+      } catch (RuntimeException e) { /* expect throw */ }
+      verify(pc.actionRepo);
+      verify(action);
+
+      // Test case valid action.
+      pc = createDummyCrawler();
+      pc.actionRepo = createMock(CrawlerActionRepo.class);
+      action = createMock(CrawlerAction.class);
+      expect(pc.actionRepo.getActions()).andReturn(
+            Sets.newHashSet(action));
+      action.validate();
+      replay(pc.actionRepo);
+      replay(action);
+      pc.validateActions();
+      verify(pc.actionRepo);
+      verify(action);
+   }
+
+   public void testContainsRequiredMetadata() {
+      ProductCrawler pc = createDummyCrawler();
+      Metadata m = new Metadata();
+      m.replaceMetadata(CoreMetKeys.PRODUCT_TYPE, "GenericFile");
+      m.replaceMetadata(CoreMetKeys.FILENAME, "TestFile.txt");
+      m.replaceMetadata(CoreMetKeys.FILE_LOCATION, "/tmp/dir");
+      m.replaceMetadata(CoreMetKeys.FILE_SIZE, "0");
+      assertTrue(pc.containsRequiredMetadata(m));
+      assertFalse(pc.containsRequiredMetadata(new Metadata()));
+   }
+
+   public void testAddKnowMetadata() {
+      File p = new File("/tmp/data.dat");
+      Metadata m = new Metadata();
+      ProductCrawler pc = createDummyCrawler();
+      pc.addKnownMetadata(p, m);
+      assertEquals(4, m.getAllKeys().size());
+      assertEquals(p.getName(), m.getMetadata(CoreMetKeys.PRODUCT_NAME));
+      assertEquals(p.getName(), m.getMetadata(CoreMetKeys.FILENAME));
+      assertEquals(p.getParentFile().getAbsolutePath(),
+            m.getMetadata(CoreMetKeys.FILE_LOCATION));
+      assertEquals(String.valueOf(p.length()), m.getMetadata(CoreMetKeys.FILE_SIZE));
+   }
+
+   public void testCreateIngestStatus() {
+      File p = new File("/tmp/data.dat");
+      IngestStatus.Result result = IngestStatus.Result.SUCCESS;
+      String message = "Ingest OK";
+      ProductCrawler pc = createDummyCrawler();
+      IngestStatus status = pc.createIngestStatus(p, result, message);
+      assertEquals(p, status.getProduct());
+      assertEquals(result, status.getResult());
+      assertEquals(message, status.getMessage());
+   }
+
+   public void testIngest() throws MalformedURLException, IngestException {
+      File p = new File("/tmp/data.dat");
+      Metadata m = new Metadata();
+
+      // Test successful ingest.
+      ProductCrawler pc = createDummyCrawler();
+      pc.setFilemgrUrl("http://localhost:9000");
+      pc.ingester = createMock(Ingester.class);
+      expect(pc.ingester.ingest(new URL("http://localhost:9000"), p, m))
+         .andReturn("TestProductId");
+      replay(pc.ingester);
+      assertTrue(pc.ingest(p, m));
+      verify(pc.ingester);
+
+      // Test failed ingest.
+      pc = createDummyCrawler();
+      pc.setFilemgrUrl("http://localhost:9000");
+      pc.ingester = createMock(Ingester.class);
+      expect(pc.ingester.ingest(new URL("http://localhost:9000"), p, m))
+         .andThrow(new IngestException());
+      replay(pc.ingester);
+      assertFalse(pc.ingest(p, m));
+      verify(pc.ingester);
+   }
+
+   public void testPerformPreIngestActions() throws CrawlerActionException {
+      ProductCrawler pc = createDummyCrawler();
+      File p = new File("/tmp/data.dat");
+      Metadata m = new Metadata();
+
+      // Test actionRepo == null.
+      assertTrue(pc.performPreIngestActions(p, m));
+
+      // Test actionRepo != null and performAction return true.
+      CrawlerAction action = createMock(CrawlerAction.class);
+      expect(action.getId()).andReturn("ActionId");
+      expect(action.getDescription()).andReturn("Action Description");
+      expect(action.performAction(p, m)).andReturn(true);
+      replay(action);
+
+      pc.actionRepo = createMock(CrawlerActionRepo.class);
+      expect(pc.actionRepo.getPreIngestActions())
+         .andReturn(Lists.newArrayList(action));
+      replay(pc.actionRepo);
+
+      assertTrue(pc.performPreIngestActions(p, m));
+      verify(action);
+      verify(pc.actionRepo);
+
+      // Test actionRepo != null and performAction return false.
+      action = createMock(CrawlerAction.class);
+      expect(action.getId()).andReturn("ActionId");
+      expect(action.getDescription()).andReturn("Action Description");
+      expect(action.performAction(p, m)).andReturn(false);
+      expect(action.getId()).andReturn("ActionId");
+      expect(action.getDescription()).andReturn("Action Description");
+      replay(action);
+
+      pc.actionRepo = createMock(CrawlerActionRepo.class);
+      expect(pc.actionRepo.getPreIngestActions())
+         .andReturn(Lists.newArrayList(action));
+      replay(pc.actionRepo);
+
+      assertFalse(pc.performPreIngestActions(p, m));
+      verify(action);
+      verify(pc.actionRepo);
+   }
+
+   public void testPerformPostIngestOnSuccessActions() throws CrawlerActionException {
+      ProductCrawler pc = createDummyCrawler();
+      File p = new File("/tmp/data.dat");
+      Metadata m = new Metadata();
+
+      // Test actionRepo == null.
+      assertTrue(pc.performPostIngestOnSuccessActions(p, m));
+
+      // Test actionRepo != null and performAction return true.
+      CrawlerAction action = createMock(CrawlerAction.class);
+      expect(action.getId()).andReturn("ActionId");
+      expect(action.getDescription()).andReturn("Action Description");
+      expect(action.performAction(p, m)).andReturn(true);
+      replay(action);
+
+      pc.actionRepo = createMock(CrawlerActionRepo.class);
+      expect(pc.actionRepo.getPostIngestOnSuccessActions())
+         .andReturn(Lists.newArrayList(action));
+      replay(pc.actionRepo);
+
+      assertTrue(pc.performPostIngestOnSuccessActions(p, m));
+      verify(action);
+      verify(pc.actionRepo);
+
+      // Test actionRepo != null and performAction return false.
+      action = createMock(CrawlerAction.class);
+      expect(action.getId()).andReturn("ActionId");
+      expect(action.getDescription()).andReturn("Action Description");
+      expect(action.performAction(p, m)).andReturn(false);
+      expect(action.getId()).andReturn("ActionId");
+      expect(action.getDescription()).andReturn("Action Description");
+      replay(action);
+
+      pc.actionRepo = createMock(CrawlerActionRepo.class);
+      expect(pc.actionRepo.getPostIngestOnSuccessActions())
+         .andReturn(Lists.newArrayList(action));
+      replay(pc.actionRepo);
+
+      assertFalse(pc.performPostIngestOnSuccessActions(p, m));
+      verify(action);
+      verify(pc.actionRepo);
+   }
+
+   public void testPerformPostIngestOnFailActions() throws CrawlerActionException {
+      ProductCrawler pc = createDummyCrawler();
+      File p = new File("/tmp/data.dat");
+      Metadata m = new Metadata();
+
+      // Test actionRepo == null.
+      assertTrue(pc.performPostIngestOnFailActions(p, m));
+
+      // Test actionRepo != null and performAction return true.
+      CrawlerAction action = createMock(CrawlerAction.class);
+      expect(action.getId()).andReturn("ActionId");
+      expect(action.getDescription()).andReturn("Action Description");
+      expect(action.performAction(p, m)).andReturn(true);
+      replay(action);
+
+      pc.actionRepo = createMock(CrawlerActionRepo.class);
+      expect(pc.actionRepo.getPostIngestOnFailActions())
+         .andReturn(Lists.newArrayList(action));
+      replay(pc.actionRepo);
+
+      assertTrue(pc.performPostIngestOnFailActions(p, m));
+      verify(action);
+      verify(pc.actionRepo);
+
+      // Test actionRepo != null and performAction return false.
+      action = createMock(CrawlerAction.class);
+      expect(action.getId()).andReturn("ActionId");
+      expect(action.getDescription()).andReturn("Action Description");
+      expect(action.performAction(p, m)).andReturn(false);
+      expect(action.getId()).andReturn("ActionId");
+      expect(action.getDescription()).andReturn("Action Description");
+      replay(action);
+
+      pc.actionRepo = createMock(CrawlerActionRepo.class);
+      expect(pc.actionRepo.getPostIngestOnFailActions())
+         .andReturn(Lists.newArrayList(action));
+      replay(pc.actionRepo);
+
+      assertFalse(pc.performPostIngestOnFailActions(p, m));
+      verify(action);
+      verify(pc.actionRepo);
+   }
+
+   public void testPerformProductCrawlerActions() throws CrawlerActionException {
+      ProductCrawler pc = createDummyCrawler();
+      File p = new File("/tmp/data.dat");
+      Metadata m = new Metadata();
+
+      // Test no actions.
+      assertTrue(pc.performProductCrawlerActions(
+            Collections.<CrawlerAction>emptyList(), p, m));
+
+      // Test 1 action pass.
+      CrawlerAction action = createMock(CrawlerAction.class);
+      expect(action.getId()).andReturn("ActionId");
+      expect(action.getDescription()).andReturn("Action Description");
+      expect(action.performAction(p, m)).andReturn(true);
+      replay(action);
+      assertTrue(pc.performProductCrawlerActions(
+            Lists.newArrayList(action), p, m));
+      verify(action);
+
+      // Test 1 action fail.
+      action = createMock(CrawlerAction.class);
+      expect(action.getId()).andReturn("ActionId");
+      expect(action.getDescription()).andReturn("Action Description");
+      expect(action.performAction(p, m)).andReturn(false);
+      expect(action.getId()).andReturn("ActionId");
+      expect(action.getDescription()).andReturn("Action Description");
+      replay(action);
+      assertFalse(pc.performProductCrawlerActions(
+            Lists.newArrayList(action), p, m));
+      verify(action);
+
+      // Test 1 action pass and 1 action fail.
+      CrawlerAction passAction = createMock(CrawlerAction.class);
+      expect(passAction.getId()).andReturn("ActionId");
+      expect(passAction.getDescription()).andReturn("Action Description");
+      expect(passAction.performAction(p, m)).andReturn(true);
+      replay(passAction);
+      CrawlerAction failAction = createMock(CrawlerAction.class);
+      expect(failAction.getId()).andReturn("ActionId");
+      expect(failAction.getDescription()).andReturn("Action Description");
+      expect(failAction.performAction(p, m)).andReturn(false);
+      expect(failAction.getId()).andReturn("ActionId");
+      expect(failAction.getDescription()).andReturn("Action Description");
+      replay(failAction);
+      assertFalse(pc.performProductCrawlerActions(
+            Lists.newArrayList(passAction, failAction), p, m));
+      verify(passAction);
+      verify(failAction);
+   }
+
+   private static ProductCrawler createDummyCrawler() {
+      return createDummyCrawler(true, new Metadata(), null); 
+   }
+
+   private static ProductCrawler createDummyCrawler(
+         final boolean passesPreconditions, final Metadata productMetadata,
+         final File renamedFile) {
+      return new ProductCrawler() {
+         @Override
+         protected boolean passesPreconditions(File product) {
+            return passesPreconditions;
+         }
+         @Override
+         protected Metadata getMetadataForProduct(File product) {
+            return productMetadata;
+         }
+         @Override
+         protected File renameProduct(File product, Metadata productMetadata)
+               throws Exception {
+            return renamedFile == null ? product : renamedFile;
+         }
+      };
+   }    
+}
diff --git a/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/cli/option/handler/TestCrawlerBeansPropHandler.java b/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/cli/option/handler/TestCrawlerBeansPropHandler.java
new file mode 100644
index 0000000..d1a90e8
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/cli/option/handler/TestCrawlerBeansPropHandler.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.cli.option.handler;
+
+//OODT static imports
+import static org.apache.oodt.cas.crawl.util.ActionBeanProperties.getProperties;
+
+//JDK imports
+import java.util.Collections;
+
+//OODT imports
+import org.apache.oodt.cas.cli.option.AdvancedCmdLineOption;
+import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link CrawlerBeansPropHandler}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestCrawlerBeansPropHandler extends TestCase {
+
+   public void testHandleOption() {
+      AdvancedCmdLineOption option = new AdvancedCmdLineOption();
+      option.setShortOption("t");
+      option.setLongOption("test");
+      option.setHasArgs(true);
+
+      // Test 1 value specified.
+      CmdLineOptionInstance instance = new CmdLineOptionInstance(
+            option, Lists.newArrayList("value"));
+      CrawlerBeansPropHandler handler = new CrawlerBeansPropHandler();
+      handler.initialize(option);
+      handler.setProperties(Lists.newArrayList("TestBean.prop"));
+      handler.handleOption(null, instance);
+      assertEquals(1, getProperties().size());
+      assertEquals("value", getProperties().getProperty("TestBean.prop"));
+      getProperties().clear();
+
+      // Test multiple values specified.
+      instance = new CmdLineOptionInstance(
+            option, Lists.newArrayList("value1", "value2"));
+      handler = new CrawlerBeansPropHandler();
+      handler.initialize(option);
+      handler.setProperties(Lists.newArrayList("TestBean.prop"));
+      handler.handleOption(null, instance);
+      assertEquals(2, getProperties().size());
+      assertEquals("value1", getProperties().getProperty("TestBean.prop[0]"));
+      assertEquals("value2", getProperties().getProperty("TestBean.prop[1]"));
+      getProperties().clear();
+
+      // Test no values specified.
+      try {
+         instance = new CmdLineOptionInstance(
+               option, Collections.<String>emptyList());
+         handler = new CrawlerBeansPropHandler();
+         handler.initialize(option);
+         handler.setProperties(Lists.newArrayList("TestBean.prop"));
+         handler.handleOption(null, instance);
+         fail("Should have thrown RuntimeException");
+      } catch (RuntimeException e) { /* expect throw */ }
+   }
+}
diff --git a/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/option/TestBooleanOptions.java b/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/option/TestBooleanOptions.java
new file mode 100644
index 0000000..63d2a94
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/option/TestBooleanOptions.java
@@ -0,0 +1,60 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.cas.crawl.option;
+
+//Junit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.MetExtractorProductCrawler;
+import org.apache.oodt.cas.crawl.ProductCrawler; // for javadoc
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * @since OODT-241
+ * 
+ * <p>
+ * Class ensures that boolean options such as --noRecur and --crawlForDirs are
+ * settable in {@link ProductCrawler} derivatives
+ * </p>.
+ */
+public final class TestBooleanOptions extends TestCase {
+
+    public void testSetBooleanOptions() {
+        MetExtractorProductCrawler crawler = new MetExtractorProductCrawler();
+        try {
+            crawler.getClass().getMethod("setNoRecur",
+                    new Class[] { boolean.class }).invoke(crawler,
+                    new Object[] { new Boolean(true) });
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        try {
+            crawler.getClass().getMethod("setCrawlForDirs",
+                    new Class[] { boolean.class }).invoke(crawler,
+                    new Object[] { new Boolean(true) });
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertTrue(crawler.isNoRecur());
+        assertTrue(crawler.isCrawlForDirs());
+
+    }
+
+}
diff --git a/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/typedetection/TestMimeExtractorConfigReader.java b/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/typedetection/TestMimeExtractorConfigReader.java
new file mode 100644
index 0000000..4a7e410
--- /dev/null
+++ b/0.8.1-rc1/crawler/src/test/java/org/apache/oodt/cas/crawl/typedetection/TestMimeExtractorConfigReader.java
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.crawl.typedetection;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+import java.util.UUID;
+
+//Apache imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.extractors.CopyAndRewriteExtractor;
+import org.apache.oodt.cas.metadata.extractors.MetReaderExtractor;
+import org.apache.oodt.cas.metadata.filenaming.PathUtilsNamingConvention;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link MimeExtractorConfigReader}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestMimeExtractorConfigReader extends TestCase {
+
+   private File mimeTypesFile;
+   private File defaultExtractorConfig;
+   private File tmpDir;
+
+   @Override
+   public void setUp() throws Exception {
+      File tmpFile = File.createTempFile("bogus", "bogus");
+      tmpDir = new File(tmpFile.getParentFile(), UUID.randomUUID().toString());
+      tmpFile.delete();
+      if (!tmpDir.mkdirs()) {
+         throw new Exception("Failed to create temp directory");
+      }
+      mimeTypesFile = new File(tmpDir, "mime-types.xml");
+      FileUtils.touch(mimeTypesFile);
+      defaultExtractorConfig = new File(tmpDir, "default-extractor.properties");
+      FileUtils.touch(defaultExtractorConfig);
+   }
+
+   @Override
+   public void tearDown() throws Exception {
+      FileUtils.forceDelete(tmpDir);
+   }
+
+   public void testReadWithDefaults() throws Exception {
+      String namingConvId = "PathUtilsNC";
+      String defaultPreconditionId = "TestPrecondition";
+      String preconditionId1 = "Precondition1";
+      String preconditionId2 = "Precondition2";
+      String xmlFileContents =
+           "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+         + "<cas:mimetypemap xmlns:cas=\"http://oodt.jpl.nassa.gov/1.0/cas\""
+               + " magic=\"false\" mimeRepo=\""
+               + mimeTypesFile.getAbsolutePath() + "\">\n"
+         + "<default>\n"
+         + "   <namingConvention id=\"" + namingConvId + "\" />\n"
+         + "   <extractor class=\""
+               + CopyAndRewriteExtractor.class.getCanonicalName() + "\">\n"
+         + "      <config file=\"" + defaultExtractorConfig.getAbsolutePath()
+                     + "\"/>\n"
+         + "      <preCondComparators>\n"
+         + "         <preCondComparator id=\"" + defaultPreconditionId + "\"/>\n"
+         + "      </preCondComparators>\n"
+         + "   </extractor>\n"
+         + "</default>\n"
+         + "<mime type=\"some/mime-type\">\n"
+         + "   <extractor class=\""
+               + MetReaderExtractor.class.getCanonicalName() + "\">\n"
+         + "      <config file=\"" + defaultExtractorConfig.getAbsolutePath()
+                     + "\"/>\n"
+         + "      <preCondComparators>\n"
+         + "         <preCondComparator id=\"" + preconditionId1 + "\"/>\n"
+         + "         <preCondComparator id=\"" + preconditionId2 + "\"/>\n"
+         + "      </preCondComparators>\n"
+         + "   </extractor>\n"
+         + "</mime>\n"
+         + "</cas:mimetypemap>\n";
+      File xmlMimeRepo = new File(tmpDir, "mime-repo.xml");
+      FileUtils.writeStringToFile(xmlMimeRepo, xmlFileContents, "UTF-8");
+      assertTrue(xmlMimeRepo.exists());
+      MimeExtractorRepo mimeRepo = MimeExtractorConfigReader.read(
+            xmlMimeRepo.getAbsolutePath());
+      assertEquals(namingConvId, mimeRepo.getNamingConventionId("some/mime-type"));
+      List<MetExtractorSpec> specs = mimeRepo.getExtractorSpecsForMimeType("some/mime-type");
+      assertEquals(1, specs.size());
+      assertEquals(MetReaderExtractor.class,
+            specs.get(0).getMetExtractor().getClass());
+      assertEquals(Lists.newArrayList(preconditionId1, preconditionId2),
+            specs.get(0).getPreCondComparatorIds());
+      specs = mimeRepo.getExtractorSpecsForMimeType("someother/mime-type");
+      assertEquals(1, specs.size());
+      assertEquals(CopyAndRewriteExtractor.class,
+            specs.get(0).getMetExtractor().getClass());
+      assertEquals(Lists.newArrayList(defaultPreconditionId),
+            specs.get(0).getPreCondComparatorIds());
+   }
+
+   public void testReadWithoutDefaults() throws Exception {
+      String namingConvId = "PathUtilsNC";
+      String preconditionId1 = "Precondition1";
+      String preconditionId2 = "Precondition2";
+      String xmlFileContents =
+           "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+         + "<cas:mimetypemap xmlns:cas=\"http://oodt.jpl.nassa.gov/1.0/cas\""
+               + " magic=\"false\" mimeRepo=\""
+               + mimeTypesFile.getAbsolutePath() + "\">\n"
+         + "<mime type=\"some/mime-type\">\n"
+         + "   <namingConvention id=\"" + namingConvId + "\" />\n"
+         + "   <extractor class=\""
+               + MetReaderExtractor.class.getCanonicalName() + "\">\n"
+         + "      <config file=\"" + defaultExtractorConfig.getAbsolutePath()
+                     + "\"/>\n"
+         + "      <preCondComparators>\n"
+         + "         <preCondComparator id=\"" + preconditionId1 + "\"/>\n"
+         + "         <preCondComparator id=\"" + preconditionId2 + "\"/>\n"
+         + "      </preCondComparators>\n"
+         + "   </extractor>\n"
+         + "</mime>\n"
+         + "</cas:mimetypemap>\n";
+      File xmlMimeRepo = new File(tmpDir, "mime-repo.xml");
+      FileUtils.writeStringToFile(xmlMimeRepo, xmlFileContents, "UTF-8");
+      assertTrue(xmlMimeRepo.exists());
+      MimeExtractorRepo mimeRepo = MimeExtractorConfigReader.read(
+            xmlMimeRepo.getAbsolutePath());
+      assertEquals(namingConvId, mimeRepo.getNamingConventionId("some/mime-type"));
+      List<MetExtractorSpec> specs = mimeRepo.getExtractorSpecsForMimeType("some/mime-type");
+      assertEquals(1, specs.size());
+      assertEquals(MetReaderExtractor.class,
+            specs.get(0).getMetExtractor().getClass());
+      assertEquals(Lists.newArrayList(preconditionId1, preconditionId2),
+            specs.get(0).getPreCondComparatorIds());
+      specs = mimeRepo.getExtractorSpecsForMimeType("someother/mime-type");
+      assertEquals(0, specs.size());
+   }
+}
diff --git a/0.8.1-rc1/curator/pom.xml b/0.8.1-rc1/curator/pom.xml
new file mode 100644
index 0000000..977f717
--- /dev/null
+++ b/0.8.1-rc1/curator/pom.xml
@@ -0,0 +1,165 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>cas-curator</artifactId>
+  <packaging>war</packaging>
+  <name>CAS Curation Interface</name>
+  <description>A web application for managing policy for products and files and metadata that have been ingested via the CAS component.</description>
+  <scm>
+   	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/curator</connection>
+   	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/curator</developerConnection>
+   	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/curator</url>
+  </scm>
+  <build>
+    <plugins /> 
+  </build>
+  <profiles>
+    <profile>
+      <id>audit</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>rat-maven-plugin</artifactId>
+            <configuration>
+              <excludes>
+                <exclude>**/jquery*</exclude>
+                <exclude>**/jquery/*</exclude>
+                <exclude>**/src/jquery*</exclude>
+                <exclude>**/jquery-treeview/*</exclude>
+                <exclude>**/jquery-treeview/demo/*</exclude>
+                <exclude>**/jquery-treeview/lib/*</exclude>
+                <exclude>**/jquery-ui/*</exclude>
+                <exclude>**/jquery-ui/css/smoothness/jquery-ui-1.7.2.custom.css</exclude>
+                <exclude>**/src/MIT-License.txt</exclude>
+                <exclude>**/media/Bach-SuiteNo2.mp3</exclude>
+              </excludes>
+            </configuration>
+            <executions>
+              <execution>
+                <phase>verify</phase>
+                <goals>
+                  <goal>check</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+  <repositories>
+    <repository>
+      <id>ibiblio</id>
+      <name>Ibiblio Repository</name>
+      <layout>default</layout>
+      <url>http://mirrors.ibiblio.org/pub/mirrors/maven2</url>
+      <releases>
+        <enabled>true</enabled>
+        <updatePolicy>always</updatePolicy>
+        <checksumPolicy>warn</checksumPolicy>
+      </releases>
+      <snapshots>
+        <enabled>false</enabled>
+      </snapshots>
+    </repository>
+    <repository>
+      <id>maven2-repository.dev.java.net</id>
+      <name>Java.net Repository for Maven</name>
+      <url>http://download.java.net/maven/2/</url>
+      <layout>default</layout>
+    </repository> 
+  </repositories>
+  
+  <dependencies>
+	<dependency>
+		<groupId>commons-fileupload</groupId>
+		<artifactId>commons-fileupload</artifactId>
+		<version>1.2.1</version>
+	</dependency>
+	<dependency>
+		<groupId>commons-io</groupId>
+		<artifactId>commons-io</artifactId>
+	</dependency>
+	<dependency>
+	    <groupId>commons-lang</groupId>
+	    <artifactId>commons-lang</artifactId>
+	    <version>2.3</version>
+	</dependency>
+	<dependency>
+	    <groupId>commons-collections</groupId>
+	    <artifactId>commons-collections</artifactId>
+	    <version>3.2.1</version>
+	</dependency>
+    <dependency>
+       <groupId>javax.servlet</groupId>
+       <artifactId>servlet-api</artifactId>
+       <version>2.4</version>
+       <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-filemgr</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-sso</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-crawler</artifactId>
+      <version>${project.parent.version}</version>
+      <exclusions>
+        <exclusion>
+          <artifactId>tika</artifactId>
+          <groupId>org.apache.tika</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-metadata</artifactId>
+      <version>${project.parent.version}</version>
+      <type>jar</type>
+    </dependency>
+    <dependency>
+      <groupId>net.sf.json-lib</groupId>
+      <artifactId>json-lib</artifactId>
+      <version>2.3</version>
+      <classifier>jdk15</classifier>
+    </dependency>
+   <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+      <version>2.6.0</version>
+   </dependency>
+  </dependencies>
+
+</project>
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/CurationService.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/CurationService.java
new file mode 100644
index 0000000..903d65d
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/CurationService.java
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.curation.service;
+
+//OODT imports
+import org.apache.oodt.cas.curation.servlet.CuratorConfMetKeys;
+import org.apache.oodt.cas.curation.util.SSOUtils;
+import org.apache.oodt.security.sso.SingleSignOn;
+
+//JDK imports
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.UriInfo;
+
+//JAX-RS imports
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+
+//APACHE imports
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * 
+ * 
+ * The Main Curation Web Service responsible for providing basic tools and
+ * functionality for performing ingestion into the CAS filemgr, and management
+ * of the staging area for ingestion.
+ * 
+ * @author pramirez
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class CurationService extends HttpServlet implements CuratorConfMetKeys {
+
+  private static final long serialVersionUID = -5370697580594691669L;
+  
+  private static final Logger LOG = Logger.getLogger(CurationService.class
+      .getName());
+  
+  protected static CurationServiceConfig config = null;
+  
+  protected final static String FORMAT_JSON = "json";
+  
+  protected final static String FORMAT_HTML = "html";
+  
+  protected final static String UNKNOWN_OUT_FORMAT = "Unsupported Output Format!";
+  
+  protected SingleSignOn sso;
+
+  /**
+   * Default Constructor.
+   */
+  public CurationService() {
+  }
+
+  @Override
+  public void init(ServletConfig conf) throws ServletException {
+    super.init(conf);
+    this.config = CurationServiceConfig.getInstance(conf);
+  }
+
+  /**
+   * Gets the staging area as a JSON formatted response object.
+   * 
+   * @param base
+   *          The base directory to read files from, should be the staging area
+   *          root.
+   * @param path
+   *          The particular child path within the staging area.
+   * @param showFiles
+   *          Whether or not to show {@link File#isFile()} files or not.
+   * @return A String representation formatting using
+   *         {@link JSONObject#toString()}.
+   */
+  public String getDirectoryAreaAsJSON(String base, String path,
+      boolean showFiles) {
+    String startingPath = (base + "/" + path);
+    startingPath = StringUtils.replace(startingPath, "source", "/");
+    String f[] = getFilesInDirectory(startingPath, showFiles);
+
+    List<Map<String, Object>> items = new ArrayList<Map<String, Object>>();
+    for (int i = 0; i < f.length; i++) {
+      Map<String, Object> entry = new HashMap<String, Object>();
+      String children[] = getFilesInDirectory(startingPath + "/" + f[i],
+          showFiles);
+      entry.put("text", f[i]);
+      entry.put("id", path + "/" + f[i]);
+      entry.put("expanded", false);
+      entry.put("hasChildren", children != null && (children.length > 0));
+      entry.put("isFile", new File(startingPath + "/" + f[i]).isFile());
+      items.add(entry);
+    }
+
+    return JSONArray.fromObject(items).toString();
+  }
+
+  protected String[] getFilesInDirectory(String directory,
+      final boolean showFiles) {
+    File dir = new File(directory);
+    FilenameFilter filter = new FilenameFilter() {
+
+      public boolean accept(File dir, String name) {
+
+        return !name.startsWith(".")
+            && (showFiles || !new File(dir, name).isFile());
+      }
+    };
+    return dir.list(filter);
+  }
+
+  protected void sendRedirect(String page, UriInfo uriInfo,
+      HttpServletResponse response) throws IOException {
+    response.sendRedirect(uriInfo.getBaseUriBuilder().path("../" + page)
+        .build().toASCIIString());
+  }
+
+  protected String cleansePath(String path) throws UnsupportedEncodingException {
+    String newPath = path;
+    if (newPath.startsWith("/")) {
+      newPath = path.substring(1);
+    }
+    newPath = URLDecoder.decode(newPath, "UTF-8");
+    return newPath;
+
+  }
+  
+  /**
+   * Configures the web context persistence layer for the CAS SSO so that all
+   * services ({@link HttpServlet}s) that extend this implementation get the
+   * ability to configure an SSO object for free, essentially.
+   * 
+   * @param req
+   *          The HTTP request object.
+   * @param res
+   *          The HTTP response object.
+   */
+  protected void configureSingleSignOn(HttpServletRequest req,
+      HttpServletResponse res) {
+    this.sso = SSOUtils.getWebSingleSignOn(CurationService.config, req, res);
+  }
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/CurationServiceConfig.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/CurationServiceConfig.java
new file mode 100644
index 0000000..dc497ed
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/CurationServiceConfig.java
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.curation.service;
+
+//OODT imports
+import org.apache.oodt.cas.curation.servlet.CuratorConfMetKeys;
+import org.apache.oodt.cas.filemgr.datatransfer.DataTransferFactory;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//JDK imports
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+
+/**
+ * 
+ * 
+ * Configures the {@link CurationService} by reading the parameters out of the
+ * <code>context.xml</code> file, doing a
+ * {@link PathUtils#replaceEnvVariables(String)} on each property in the
+ * context.xml. This allows you to specify environment variables using the
+ * traditional CAS syntax of:
+ * 
+ * <pre>
+ *   [VAR_NAME], e.g., [CAS_CURATOR_HOME]/some/other/path
+ * </pre>
+ * 
+ * The configuration parameters are read once upon loading the instance of this
+ * object.
+ * 
+ * @author pramirez
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class CurationServiceConfig implements CuratorConfMetKeys {
+  private static CurationServiceConfig instance;
+
+  private final Map<String, String> parameters = new HashMap<String, String>();
+
+  private XmlRpcFileManagerClient fmClient = null;
+
+  private static final Logger LOG = Logger
+      .getLogger(CurationServiceConfig.class.getName());
+
+  /**
+   * Gets a singleton static instance of the global
+   * {@link CurationServiceConfig} for the CAS Curator Webapp.
+   * 
+   * @param conf
+   *          The {@link ServletConfig} read on startup of the webapp. This is
+   *          typically specified in a <code>context.xml</code> file, but can
+   *          also be specified in <code>web.xml</code>.
+   * @return A singleton instance of the global {@link link
+   *         CurationServiceConfig}.
+   * @throws InstantiationException
+   *           If there is any error constructing the config.
+   */
+  public static CurationServiceConfig getInstance(ServletConfig conf) {
+    if (instance == null) {
+      instance = new CurationServiceConfig(conf);
+    }
+    return instance;
+  }
+
+  /**
+   * 
+   * @return The metadata output file path.
+   */
+  public String getMetAreaPath() {
+    return this.evaluateParameter(MET_AREA_PATH);
+  }
+  
+  /**
+   * 
+   * @return The extension of metadata files that will be generated and consumed
+   *         by CAS curator.
+   */
+  public String getMetExtension() {
+    return this.evaluateParameter(MET_EXTENSION);
+  }
+
+  /**
+   * 
+   * @return The path to the staging area where the CAS curator is ingesting
+   *         files from.
+   */
+  public String getStagingAreaPath() {
+    return this.evaluateParameter(STAGING_AREA_PATH);
+  }
+
+  /**
+   * 
+   * @return A {@link String} representation of the CAS File Manager {@link URL}
+   *         .
+   */
+  public String getFileMgrURL() {
+    return this.evaluateParameter(FM_URL);
+  }
+
+  /**
+   * 
+   * @return The full {@link XmlRpcFileManagerClient} built from the CAS curator
+   *         property <code>filemgr.url</code>.
+   */
+  public XmlRpcFileManagerClient getFileManagerClient() {
+    try {
+      return new XmlRpcFileManagerClient(new URL(this.getFileMgrURL()));
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  /**
+   * 
+   * @return The java class name (fully-qualified) of the CAS SSO security
+   *         implementation.
+   */
+  public String getSSOImplClass() {
+    return this.evaluateParameter(SSO_IMPL_CLASS);
+  }
+
+  /**
+   * 
+   * @return The display name of the project.
+   */
+  public String getProjectDisplayName() {
+    return this.evaluateParameter(PROJECT_DISPLAY_NAME);
+  }
+
+  /**
+   * 
+   * @return The upload path for metadata extractor config files.
+   */
+  public String getMetExtrConfUploadPath() {
+    return this.evaluateParameter(MET_EXTRACTOR_CONF_UPLOAD_PATH);
+  }
+
+  /**
+   * 
+   * @return The path to the crawler config file.
+   */
+  public String getCrawlerConfFile() {
+    return this.evaluateParameter(CRAWLER_CONF_FILE);
+  }
+
+  /**
+   * 
+   * @return The path to the location where policy directories should be
+   *         uploaded to.
+   */
+  public String getPolicyUploadPath() {
+    return this.evaluateParameter(POLICY_UPLOAD_PATH);
+  }
+
+  /**
+   * 
+   * @return The default CAS File Manager {@link DataTransferFactory} classname.
+   */
+  public String getDefaultTransferFactory() {
+    return this.evaluateParameter(DEFAULT_TRANSFER_FACTORY);
+  }
+
+  /**
+   * Gets a property from the CAS Curator config without calling
+   * {@link PathUtils#replaceEnvVariables(String)}.
+   * 
+   * @param name
+   *          The name of the parameter to return.
+   * @return The un-evaluated property value from the config.
+   */
+  public String getParameter(String name) {
+    return this.parameters.get(name);
+  }
+  
+  public String getFileMgrProps() {
+    return this.evaluateParameter(FM_PROPS);
+  }
+
+  private String evaluateParameter(String name) {
+    return PathUtils.replaceEnvVariables(this.parameters.get(name));
+  }
+
+  // Note that the constructor is private
+  private CurationServiceConfig(ServletConfig conf) {
+    readContextParams(conf.getServletContext());
+    try {
+      fmClient = new XmlRpcFileManagerClient(new URL(this.getFileMgrURL()));
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Unable to build CurationServiceConfig: Message: " + e.getMessage());
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  private void readContextParams(ServletContext context) {
+    for (Enumeration<String> names = context.getInitParameterNames(); names
+        .hasMoreElements();) {
+      String name = names.nextElement();
+      parameters.put(name, context.getInitParameter(name));
+    }
+    LOG.log(Level.INFO, "Init Parameters: " + parameters);
+  }
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/DirectoryResource.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/DirectoryResource.java
new file mode 100644
index 0000000..2700a69
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/DirectoryResource.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.curation.service;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//JAX-RS imports
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+
+
+@Path("directory")
+/**
+ * 
+ * A web service endpoint to a service providing views of the staging area, the
+ * archive area, and the met output area.
+ * 
+ * @author pramirez
+ * @version $Id$
+ */
+public class DirectoryResource extends CurationService {
+  private static final Logger LOG = Logger.getLogger(DirectoryResource.class
+      .getName());
+
+  @Context
+  UriInfo uriInfo;
+  
+  private static final long serialVersionUID = 715126227357637464L;
+
+  @GET
+  @Path("staging")
+  @Produces("text/plain")
+  public String showStagingArea(
+      @DefaultValue("/") @QueryParam("path") String path,
+      @DefaultValue("true") @QueryParam("showFiles") boolean showFiles,
+      @DefaultValue(FORMAT_HTML) @QueryParam("format") String format) {
+    if (FORMAT_HTML.equals(format)) {
+      String response = this.getDirectoryAreaAsHTML(CurationService.config
+          .getStagingAreaPath(), path, showFiles);
+      return response;
+    }
+    return this.getDirectoryAreaAsJSON(CurationService.config
+        .getStagingAreaPath(), path, showFiles);
+  }
+
+  @GET
+  @Path("metadata")
+  @Produces("text/plain")
+  public String showMetArea(@DefaultValue("/") @QueryParam("path") String path,
+      @DefaultValue("true") @QueryParam("showFiles") boolean showFiles) {
+    return this.getDirectoryAreaAsJSON(CurationService.config.getMetAreaPath(),
+        path, showFiles);
+  }
+
+  @GET
+  @Path("catalog")
+  @Produces("text/plain")
+  public String showArchiveArea(@QueryParam("policy") String policy,
+      @QueryParam("productType") String productType,
+      @DefaultValue("20") @QueryParam("num") int numberOfResults,
+      @DefaultValue("0") @QueryParam("start") int start) {
+
+    // Figure out where the product type root path is and display contents
+    return productType;
+  }
+
+
+  public String getDirectoryAreaAsHTML(String base, String path,
+      boolean showFiles) {
+    StringBuffer html = new StringBuffer();
+    String relativePath = null;
+    try {
+      relativePath = this.cleansePath(path);
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Error decoding path: [" + path + "]: Message: "
+          + e.getMessage());
+      return html.toString();
+    }
+
+    String startingPath = (base + "/" + relativePath);
+    String f[] = this.getFilesInDirectory(startingPath, showFiles);
+
+    html.append("<ul class=\"fileTree\">\r\n");
+    // Loop through and list directories first. Nicer for UI to get these first
+    for (int i = 0; i < f.length; i++) {
+      if (new File(startingPath + "/" + f[i]).isDirectory()) {
+        html.append(" <li class=\"directory collapsed\">");
+        html.append("<a href=\"#\" rel=\"").append(relativePath).append("/")
+            .append(f[i]).append("\">").append(f[i]).append("</a>");
+        html.append("</li>\r\n");
+      }
+    }
+    // If we are showing files now loop through and show files
+    if (showFiles) {
+      for (int i = 0; i < f.length; i++) {
+        if (new File(startingPath + "/" + f[i]).isFile()) {
+          String filename = new File(startingPath + "/" + f[i]).getName();
+          String ext = filename.substring(filename.lastIndexOf('.') + 1);
+          html.append(" <li class=\"file draggy ext_").append(ext)
+              .append("\">");
+          html.append("<a href=\"#\" rel=\"").append(relativePath).append("/")
+              .append(f[i]).append("\">").append(f[i]).append("</a>");
+          html.append("</li>\r\n");
+        }
+      }
+    }
+    html.append("</ul>");
+
+    return html.toString();
+  }
+  
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/IngestionResource.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/IngestionResource.java
new file mode 100644
index 0000000..2ea61bb
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/IngestionResource.java
@@ -0,0 +1,352 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.curation.service;
+
+//OODT imports
+import org.apache.oodt.cas.curation.structs.IngestionTask;
+import org.apache.oodt.cas.curation.util.DateUtils;
+import org.apache.oodt.cas.curation.util.ExtractorConfigReader;
+import org.apache.oodt.cas.filemgr.ingest.Ingester;
+import org.apache.oodt.cas.filemgr.ingest.StdIngester;
+import org.apache.oodt.cas.filemgr.structs.exceptions.IngestException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JDK imports
+import java.io.File;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//JAX-RS imports
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+//JSON imports
+import net.sf.json.JSONObject;
+
+/**
+ * 
+ * Leverages CAS {@link Ingester} interface to ingest Products into the CAS File
+ * Manager via CAS Curator and a REST-ful interface.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+@Path("ingest")
+public class IngestionResource extends CurationService {
+
+  private static final long serialVersionUID = -7514150767897700936L;
+
+  private static final Logger LOG = Logger.getLogger(IngestionResource.class
+      .getName());
+
+  private static final String DATA_TRANSFER_SERVICE = "org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory";
+
+  private static final String RESP_SUCCESS = "success";
+
+  private IngestionTaskList taskList;
+
+  public IngestionResource() {
+    super();
+    this.taskList = new IngestionTaskList();
+    IngestionTask task = new IngestionTask();
+    task.setCreateDate(new Date());
+
+  }
+
+  @Context
+  UriInfo uriInfo;
+
+  @GET
+  @Path("create")
+  @Produces("text/plain")
+  public String createTask(@QueryParam("files") String fileList,
+      @QueryParam("numfiles") Integer numFiles,
+      @QueryParam("metExtCfgId") String metExtractorConfigId,
+      @QueryParam("policy") String policy,
+      @QueryParam("ptype") String productType) {
+
+    IngestionTask newTask = new IngestionTask();
+    newTask.setCreateDate(new Date());
+    try {
+      newTask.setExtConf(ExtractorConfigReader.readFromDirectory(new File(
+          CurationService.config.getMetExtrConfUploadPath()),
+          metExtractorConfigId));
+    } catch (Exception e) {
+      e.printStackTrace();
+      String errorMsg = "Unable to load extractor config from metExtCfgId: ["
+          + metExtractorConfigId + "]";
+      LOG.log(Level.WARNING, errorMsg);
+      return errorMsg;
+    }
+    newTask.setFileList(deducePaths(Arrays.asList(fileList.split(","))));
+    newTask.setPolicy(policy);
+    newTask.setProductType(productType);
+    newTask.setStatus(IngestionTask.NOT_STARTED);
+    return this.taskList.addIngestionTask(newTask);
+  }
+
+  @GET
+  @Path("remove")
+  @Produces("text/plain")
+  public void removeTask(@QueryParam("taskId") String ingestTaskId) {
+	  this.taskList.removeIngestionTask(ingestTaskId);
+  }
+
+  @GET
+  @Path("list")
+  @Produces("text/plain")
+  public String getIngestTaskList(
+      @QueryParam("format") @DefaultValue(FORMAT_HTML) String format) {
+    if (format.equals(FORMAT_HTML)) {
+      return this.encodeTaskListAsHTML(this.taskList.getTaskList());
+    } else if (format.equals(FORMAT_JSON)) {
+      return this.encodeTaskListAsJSON(this.taskList.getTaskList());
+    } else {
+      return "Unsupported Format!";
+    }
+  }
+
+  @GET
+  @Path("start")
+  @Produces("text/plain")
+  public String doIngest(@QueryParam("taskId") String ingestTaskId) {
+    IngestionTask task = this.taskList.getIngestionTaskById(ingestTaskId);
+    if (task == null) {
+      String errorMsg = "Task with ID [" + ingestTaskId
+          + "] is not being managed by this Ingestion Resource!";
+      LOG.log(Level.WARNING, errorMsg);
+      return this.encodeIngestResponseAsJSON(false, errorMsg);
+    }
+
+    Ingester ingest = this.configureIngester();
+    MetadataResource metService = new MetadataResource();
+    for (String file : task.getFileList()) {
+      Metadata fileMet = null;
+      try {
+        String vFilePath = this.getVirtualPath(CurationService.config
+            .getStagingAreaPath(), file);
+        LOG.log(Level.FINE,
+            "IngestionResource: getting staging metadata for virtual path: ["
+                + vFilePath + "]");
+        fileMet = metService.getStagingMetadata(vFilePath, task.getExtConf()
+            .getIdentifier(), false);
+      } catch (Exception e) {
+        e.printStackTrace();
+        return this.encodeIngestResponseAsHTML(false, e.getMessage());
+      }
+
+      try {
+        ingest.ingest(safeGetUrl(CurationService.config.getFileMgrURL()),
+            new File(file), fileMet);
+      } catch (IngestException e) {
+        e.printStackTrace();
+        return this.encodeIngestResponseAsHTML(false, e.getMessage());
+      }
+
+      // set task status to success
+      task.setStatus(IngestionTask.FINISHED);
+    }
+
+    return this.encodeIngestResponseAsHTML(true, null);
+  }
+
+  private String encodeTaskListAsHTML(List<IngestionTask> taskList) {
+    StringBuffer out = new StringBuffer();
+
+    for (IngestionTask task : taskList) {
+      out.append("<tr>");
+      out.append("<td>");
+      out.append(task.getId());
+      out.append("</td><td>");
+      out.append(DateUtils.getDateAsISO8601String(task.getCreateDate()));
+      out.append("</td><td>");
+      out.append(task.getFileList().size());
+      out.append("</td><td>");
+      out.append(task.getPolicy());
+      out.append("</td><td>");
+      out.append(task.getProductType());
+      out.append("</td><td>");
+      out.append(task.getExtConf().getIdentifier());
+      out.append("</td><td>");
+      out.append(task.getExtConf().getConfigFiles().size());
+      out.append("</td><td id='");
+      out.append(task.getId());
+      out.append("_Status'>");
+      out.append(task.getStatus());
+      out.append("</td>");
+      if (!task.getStatus().equals(IngestionTask.FINISHED)) {
+        out.append("<td><input type=\"button\" rel=\"_taskid_\" value=\"Start\" onclick=\"startIngestionTask('");
+        out.append(task.getId());
+        out.append("')\"/></td>");
+      } else {
+		out.append("<td><input type=\"button\" rel=\"_taskid_\" value=\"Remove\" onclick=\"removeIngestionTask('");
+		out.append(task.getId());
+		out.append("')\"></td>");
+      }
+
+      out.append("</tr>");
+    }
+    return out.toString();
+  }
+
+  private String encodeTaskListAsJSON(List<IngestionTask> taskList) {
+    List<Map<String, String>> jsonFriendlyTaskList = new Vector<Map<String, String>>();
+    for (IngestionTask task : taskList) {
+      Map<String, String> taskPropMap = new HashMap<String, String>();
+      taskPropMap.put("id", task.getId());
+      taskPropMap.put("createDate", DateUtils.getDateAsISO8601String(task
+          .getCreateDate()));
+      taskPropMap.put("policy", task.getPolicy());
+      taskPropMap.put("productType", task.getProductType());
+      taskPropMap.put("status", task.getStatus());
+      taskPropMap.put("fileList", task.getFileList().toString());
+      taskPropMap.put("extractorClass", task.getExtConf().getClassName());
+      taskPropMap.put("extractorConfFiles", task.getExtConf().getConfigFiles()
+          .toString());
+      jsonFriendlyTaskList.add(taskPropMap);
+    }
+
+    JSONObject resObj = new JSONObject();
+    resObj.put("taskList", jsonFriendlyTaskList);
+    return resObj.toString();
+
+  }
+
+  private String encodeIngestResponseAsHTML(boolean success, String msg) {
+    StringBuffer out = new StringBuffer();
+    if (success) {
+      out.append("Success");
+    } else {
+      out.append(msg);
+    }
+    return out.toString();
+  }
+
+  private String encodeIngestResponseAsJSON(boolean success, String msg) {
+    Map<String, Object> resMap = new HashMap<String, Object>();
+    resMap.put("success", success);
+    resMap.put("msg", msg);
+    JSONObject resObj = new JSONObject();
+    resObj.putAll(resMap);
+    return resObj.toString();
+
+  }
+
+  private Ingester configureIngester() {
+    StdIngester ingest = new StdIngester(DATA_TRANSFER_SERVICE);
+    return ingest;
+  }
+
+  private URL safeGetUrl(String urlStr) {
+    try {
+      return new URL(urlStr);
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  private List<String> deducePaths(List<String> vPaths) {
+    List<String> absolutePaths = new Vector<String>();
+    String stagingIngestPath = CurationService.config.getStagingAreaPath();
+    if (!stagingIngestPath.endsWith("/")) {
+      stagingIngestPath += "/";
+    }
+
+    for (String vPath : vPaths) {
+      String realPath = stagingIngestPath + vPath;
+      absolutePaths.add(realPath);
+    }
+
+    return absolutePaths;
+  }
+
+  private String getVirtualPath(String stagingAreaPath, String fullFilePath) {
+    int startIdx = stagingAreaPath.length();
+    try {
+      return fullFilePath.substring(startIdx);
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  class IngestionTaskList {
+
+    private HashMap<String, IngestionTask> taskMap;
+
+    public IngestionTaskList() {
+      this.taskMap = new HashMap<String, IngestionTask>();
+    }
+
+    public synchronized String addIngestionTask(IngestionTask task) {
+      this.provideTaskId(task);
+      taskMap.put(task.getId(), task);
+      return task.getId();
+    }
+
+    public synchronized void removeIngestionTask(String taskId) {
+      taskMap.remove(taskId);
+    }
+
+    public IngestionTask getIngestionTaskById(String taskId) {
+      return taskMap.get(taskId);
+    }
+
+    public List<IngestionTask> getTaskList() {
+      List<IngestionTask> taskList = Arrays.asList(taskMap.values().toArray(
+          new IngestionTask[taskMap.values().size()]));
+      Collections.sort(taskList, new Comparator<IngestionTask>() {
+
+        public int compare(IngestionTask o1, IngestionTask o2) {
+          if (o1.getCreateDate().before(o2.getCreateDate())) {
+            return -1;
+          } else if (o1.getCreateDate().equals(o2.getCreateDate())) {
+            return 0;
+          } else
+            return 1;
+        }
+      });
+      return taskList;
+    }
+
+    private void provideTaskId(IngestionTask task) {
+      UUID id = UUID.randomUUID();
+      task.setId(id.toString());
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/MetadataResource.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/MetadataResource.java
new file mode 100644
index 0000000..e7ed3db
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/MetadataResource.java
@@ -0,0 +1,972 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.curation.service;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+//JAX-RS imports
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+
+
+//JSON imports
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+import net.sf.json.JSONSerializer;
+
+
+
+//OODT imports
+import org.apache.oodt.cas.curation.service.CurationService;
+import org.apache.oodt.cas.curation.structs.ExtractorConfig;
+import org.apache.oodt.cas.curation.util.CurationXmlStructFactory;
+import org.apache.oodt.cas.curation.util.ExtractorConfigReader;
+import org.apache.oodt.cas.filemgr.catalog.Catalog;
+import org.apache.oodt.cas.filemgr.repository.XMLRepositoryManager;
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.filemgr.util.GenericFileManagerObjectFactory;
+import org.apache.oodt.cas.filemgr.validation.XMLValidationLayer;
+import org.apache.oodt.cas.metadata.MetExtractor;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.oodt.cas.metadata.util.GenericMetadataObjectFactory;
+
+//SPRING imports
+import org.springframework.util.StringUtils;
+
+@Path("metadata")
+/**
+ * 
+ * A web-service endpoint for dealing with CAS {@link Metadata} object.
+ * 
+ * @author pramirez
+ * @version $Id$
+ */
+public class MetadataResource extends CurationService {
+  
+  @Context
+  UriInfo uriInfo;
+  
+  @Context 
+  private ServletContext context;
+
+  private static final long serialVersionUID = 1930946924218765724L;
+
+  public static final String STAGING = "staging";
+
+  public static final String CATALOG = "catalog";
+
+  public static final String PRODUCT_TYPE = "productType";
+  
+  public static final String UPDATE = "update";
+  
+  public static final String DELETE = "delete";
+  
+  // single instance of CAS catalog shared among all requests
+  private Catalog catalog = null;
+    
+  public MetadataResource(){
+    
+  }
+
+  public MetadataResource(@Context ServletContext context) {
+  	
+  }
+
+  @GET
+  @Path(STAGING)
+  @Produces("text/plain")
+  public String getStagingMetadata(@QueryParam("id") String id,
+      @DefaultValue(FORMAT_HTML) @QueryParam("format") String format,
+      @QueryParam("configId") String configId,
+      @DefaultValue("false") @QueryParam("overwrite") Boolean overwrite,
+      @Context HttpServletRequest req, @Context HttpServletResponse res) {
+    
+      // this.sendRedirect("login.jsp", uriInfo, res);
+
+      Metadata metadata = null;
+      
+      try {
+        metadata = this.getStagingMetadata(id, configId, overwrite);
+      } catch (Exception e) {
+        return "<div class=\"error\">" + e.getMessage() + "</div>";
+      }
+      
+      if (FORMAT_HTML.equals(format)) {
+        return this.getMetadataAsHTML(metadata);
+      }
+      return this.getMetadataAsJSON(metadata).toString();
+  }
+  
+  @GET
+  @Path("extractor/config")
+  @Produces("text/plain")
+  public String getMetExtractorConfigList(
+      @DefaultValue("") @QueryParam("current") String current,
+      @DefaultValue(FORMAT_HTML) @QueryParam("format") String format) {
+    String[] configIds = this.getFilesInDirectory(this.config
+        .getMetExtrConfUploadPath(), false);
+
+    if (FORMAT_HTML.equals(format)) {
+      return this.getExtractorConfigIdsAsHTML(configIds, current);
+    }
+    return this.getExtractorConfigIdsAsJSON(configIds);
+  }
+
+  protected String getExtractorConfigIdsAsHTML(String[] configIds,
+      String current) {
+    StringBuffer html = new StringBuffer();
+    for (int i = 0; i < configIds.length; i++) {
+      html.append("<option ");
+      if (configIds[i].equals(current)) {
+        html.append("selected ");
+      }
+      html.append("value=\"");
+      html.append(configIds[i]);
+      html.append("\">");
+      html.append(configIds[i]);
+      html.append("</option>\r\n");
+    }
+    return html.toString();
+  }
+  
+  protected String getExtractorConfigIdsAsJSON(String[] configIds) {
+    // TODO: Support JSON
+    return "Not Implemented...";
+  }
+
+  /**
+   * 
+   * @param id
+   *          Relative path from staging root to product. The met extension will
+   *          be added to this id to look up and see if a met file exists with
+   *          in the met area.
+   * @param configId
+   *          Reference to the extractor config. {@link ExtractorConfigReader}
+   *          will load the configuration
+   * @param overwrite
+   *          Flag to indicate whether or not to overwrite a met file if present
+   *          in the staging area.
+   * @return The {@link Metadata} retrieved from the met area path if present or
+   *         extracted using the met extractor config.
+   * @throws FileNotFoundException
+   * @throws InstantiationException
+   * @throws IOException
+   * @throws MetExtractionException
+   */
+  protected Metadata getStagingMetadata(String id, String configId,
+      Boolean overwrite) throws FileNotFoundException, InstantiationException,
+      IOException, MetExtractionException {
+    if (configId == null || configId.trim().length() == 0) {
+      return this.readMetFile(id + CurationService.config.getMetExtension());
+    } else {
+      String relMetPath = id.startsWith("/") ? id : "/" + id;
+      String pathToMetFile = CurationService.config.getMetAreaPath()
+          + relMetPath + CurationService.config.getMetExtension();
+      if (!overwrite && new File(pathToMetFile).exists()) {
+        return this.readMetFile(id + CurationService.config.getMetExtension());
+      } else {
+        // Make sure the parent directory exists
+        new File(pathToMetFile).getParentFile().mkdirs();
+        Metadata metadata = this.runMetExtractor(id, ExtractorConfigReader
+            .readFromDirectory(
+                new File(CurationService.config
+                .getMetExtrConfUploadPath()), configId));
+        this.writeMetFile(id, metadata);
+        return metadata;
+      }
+    }
+  }
+
+  /**
+   * 
+   * @param id
+   *          Relative path from staging root to the product
+   * @param config
+   *          Configuration to run this met extractor
+   * @return
+   * @throws MetExtractionException
+   */
+  protected Metadata runMetExtractor(String id, ExtractorConfig config)
+      throws MetExtractionException {
+    MetExtractor metExtractor = GenericMetadataObjectFactory
+        .getMetExtractorFromClassName(config.getClassName());
+    metExtractor.setConfigFile(config.getConfigFiles().get(0));
+    return metExtractor.extractMetadata(CurationService.config
+        .getStagingAreaPath()
+        + "/" + id);
+  }
+  
+  @GET
+  @Path(CATALOG)
+  @Produces("text/plain")
+  public String getCatalogMetadata(@QueryParam("id") String id,
+      @DefaultValue(FORMAT_HTML) @QueryParam("format") String format,
+      @Context HttpServletRequest req, @Context HttpServletResponse res) {
+
+      // this.sendRedirect("login.jsp", uriInfo, res);
+      // Call file manager to get metadata
+      Product prod;
+      Metadata metadata;
+      String productId = id.substring(id.lastIndexOf("/") + 1);
+
+      try {
+        prod = CurationService.config.getFileManagerClient().getProductById(
+          productId);
+        metadata = this.getCatalogMetadata(prod);
+      } catch (Exception e) {
+        return "<div class=\"error\">" + e.getMessage() + "</div>";
+      }
+
+      if (FORMAT_HTML.equals(format)) {
+        return this.getMetadataAsHTML(metadata);
+      }
+      return this.getMetadataAsJSON(metadata).toString();
+  }
+
+  @POST
+  @Path(CATALOG)
+  @Consumes("application/x-www-form-urlencoded")
+  @Produces("text/plain")
+  public String setCatalogMetadata(MultivaluedMap<String, String> formParams,
+      @FormParam("id") String id) {
+  	
+    Product prod;
+    Metadata metadata = this.getMetadataFromMap(formParams);
+    
+    String productId = id.substring(id.lastIndexOf("/") + 1);
+
+    try {
+      prod = CurationService.config.getFileManagerClient().getProductById(
+          productId);
+      this.updateCatalogMetadata(prod, metadata);
+    } catch (Exception e) {
+      e.printStackTrace();
+      return "<div class=\"error\">" + e.getMessage() + "</div>";
+    }
+
+    return this.getMetadataAsHTML(metadata);
+  }
+  
+  @GET
+  @Path(PRODUCT_TYPE)
+  @Produces("text/plain")
+  public String getProductTypeMetadata(@QueryParam("id") String id,
+      @DefaultValue(FORMAT_HTML) @QueryParam("format") String format,
+      @Context HttpServletRequest req, @Context HttpServletResponse res) {
+
+    // this.sendRedirect("login.jsp", uriInfo, res);
+
+    Metadata metadata;
+    String[] idParts = id.split("/", 3);
+    String policy = idParts[1];
+    String productType = idParts[2];
+    productType = productType.substring(0, productType.lastIndexOf("/"));
+    try {
+      metadata = getProductTypeMetadataForPolicy(policy, productType);
+    } catch (Exception e) {
+      return "<div class=\"error\">" + e.getMessage() + "</div>";
+    }
+
+    if (FORMAT_HTML.equals(format)) {
+      return this.getMetadataAsHTML(metadata);
+    }
+    return this.getMetadataAsJSON(metadata).toString();
+  }
+  
+
+  @POST
+  @Path(PRODUCT_TYPE)
+  @Consumes("application/x-www-form-urlencoded")
+  @Produces("text/plain")
+  public String setProductTypeMetadata(MultivaluedMap<String, String> formParams) {
+    String[] idParts = formParams.getFirst("id").split("/");
+    String policy = idParts[1];
+    String productType = idParts[2];
+    try {
+    this.writeProductTypeMetadata(policy, productType, this
+        .getMetadataFromMap(formParams));
+    } catch (Exception e) {
+      return "<div class=\"error\">" + e.getMessage() + "</div>";
+    }
+    return "";
+  }
+
+  @POST
+  @Path(STAGING)
+  @Consumes("application/x-www-form-urlencoded")
+  @Produces("text/plain")
+  public String setStagingMetadata(MultivaluedMap<String, String> formParams) {
+    try {
+      this.writeMetFile(formParams.getFirst("id"), this
+          .getMetadataFromMap(formParams));
+    } catch (Exception e) {
+      return "<div class=\"error\">" + e.getMessage() + "</div>";
+    }
+    return "";
+  }
+
+  @GET
+  @Path("staging/info")
+  @Produces("text/plain")
+  public String getMetadataInfo(@QueryParam("id") String id) {
+
+      return "Staging met info";
+  }
+  
+
+  private JSONObject getMetadataAsJSON(Metadata metadata) {
+    return JSONObject.fromObject(metadata.getHashtable());
+  }
+
+  private Metadata getMetadataFromJSON(String metadataJSON) {
+    JSONObject json = (JSONObject) JSONSerializer.toJSON(metadataJSON);
+    Metadata metadata = new Metadata();
+
+    Set<String> keys = json.keySet();
+    for (String key : keys) {
+      List values = (List) JSONSerializer.toJava((JSONArray) json.get(key));
+      metadata.addMetadata(key, values);
+    }
+
+    return metadata;
+  }
+  
+  private Metadata getMetadataFromMap(MultivaluedMap<String, String> formParams) {
+    Metadata metadata = new Metadata();
+    
+    for (String key : formParams.keySet()) {
+      if (key.startsWith("metadata.")) {
+        String newKey = key.substring(key.indexOf('.') + 1);
+        for (String value : formParams.get(key)) {
+          metadata.addMetadata(newKey, value);
+        }
+      }
+    }
+    
+    return metadata;
+  }
+  
+  protected String getMetadataAsHTML(Metadata metadata) {
+    if (metadata == null) {
+      return "<table></table>";
+    }
+
+    StringBuffer html = new StringBuffer();
+
+    html.append("<table>\r\n");
+    for (String key : (Set<String>) metadata.getHashtable().keySet()) {
+      html.append(" <tr>\r\n");
+      html.append("  <th>").append(key).append("</th>\r\n");
+      html.append("  <td class=\"").append(key).append("\">");
+      List<String> values = metadata.getAllMetadata(key);
+      for (Iterator<String> i = values.iterator(); i.hasNext();) {
+        html.append("<span>").append(i.next()).append("</span>");
+        if (i.hasNext()) {
+          html.append(", ");
+        }
+      }
+      for (String value : (List<String>) metadata.getAllMetadata(key)) {
+      }
+      html.append("</td>\r\n");
+      html.append(" </tr>\r\n");
+    }
+    html.append("</table>\r\n");
+
+    return html.toString();
+  }
+  
+
+  /**
+   * Reads a {@link Metadata} object from a String representation of a .met
+   * {@link File}.
+   * 
+   * @param file
+   *          The full path to the .met {@link File}.
+   * @return The read-in CAS {@link Metadata} object.
+   * @throws InstantiationException
+   * @throws InstantiationException
+   *           If there is an error instantiating the {@link Metadata} class.
+   * @throws IOException
+   * @throws FileNotFoundException
+   * @throws FileNotFoundException
+   *           If the .met {@link File} is not found.
+   * @throws IOException
+   *           If there is an IO problem opening the met file.
+   */
+  public Metadata readMetFile(String file) throws InstantiationException,
+      FileNotFoundException, IOException {
+    SerializableMetadata metadata = new SerializableMetadata("UTF-8", false);
+    metadata.loadMetadataFromXmlStream(new FileInputStream(config
+        .getMetAreaPath()
+        + "/" + file));
+
+    return metadata;
+  }
+
+  /**
+   * Retrieves the cataloged {@link Metadata} associated with a {@link Product}.
+   * 
+   * @param product
+   *          The {@link Product} to obtain cataloged {@link Metadata} for.
+   * @return The cataloged {@link Metadata} for {@link Product}.
+   * @throws CatalogException
+   *           If there is an error talking to the CAS File Manager
+   *           {@link Catalog}.
+   */
+  public Metadata getCatalogMetadata(Product product) throws CatalogException {
+    return CurationService.config.getFileManagerClient().getMetadata(
+        CurationService.config.getFileManagerClient().getProductById(
+            product.getProductId()));
+  }
+
+  /**
+   * Writes a CAS {@link Metadata} {@link File} using the given identifier.
+   * 
+   * @param id
+   *          The identifier of the .met file to write.
+   * @param metadata
+   *          The {@link Metadata} object to persist and write to a {@link File}
+   *          .
+   * @throws FileNotFoundException
+   *           If the .met {@link File} cannot be written.
+   * @throws IOException
+   *           If there is an IO exception writing the {@link File}.
+   */
+  public void writeMetFile(String id, Metadata metadata)
+      throws FileNotFoundException, IOException {
+    SerializableMetadata serMet = new SerializableMetadata(metadata, "UTF-8",
+        false);
+    serMet.writeMetadataToXmlStream(new FileOutputStream(new File(config
+        .getMetAreaPath(), id + config.getMetExtension())));
+  }
+  
+  /**
+   * Method to update the catalog metadata for a given product. 
+   * All current metadata fields will be preserved, 
+   * except those specified in the HTTP POST request as 'metadata.<field_name>=<field_value>'.
+   * 
+   * @param id
+   * 	identifier of CAS product - either 'id' or 'name' must be specified
+   * @param name
+   * 	name of CAS product - either 'id' or 'name' must be specified
+   * @param formParams
+   * 	HTTP (name, value) form parameters. The parameter names MUST start with "metadata."
+   * @param replace
+   * 	optional flag set to false to add the new metadata values to the existing values, for the given flags
+   */
+  @POST
+  @Path(UPDATE)
+  @Consumes("application/x-www-form-urlencoded")
+  @Produces("text/plain")
+  public String updateMetadata(MultivaluedMap<String, String> formParams, 
+		  @FormParam("id") String id, 
+		  @FormParam("name") String name, 
+		  @DefaultValue("true") @FormParam("replace") boolean replace,
+		  @DefaultValue("false") @FormParam("remove") boolean remove) {
+  		      
+  	// new metadata from HTTP POST request
+    Metadata newMetadata = this.getMetadataFromMap(formParams);
+    
+    // client for interacting with remote File Manager
+    XmlRpcFileManagerClient fmClient = CurationService.config.getFileManagerClient();
+ 
+    // empty metadata
+    Metadata metadata = new Metadata();
+    
+    try {
+    
+      // retrieve product from catalog
+      Product product = null;
+      if (StringUtils.hasText(id)) {
+    	  id = id.substring(id.lastIndexOf("/") + 1);
+    	  product = fmClient.getProductById(id);
+      } else if (StringUtils.hasText(name)) {
+    	  product = fmClient.getProductByName(name);
+      } else {
+    	  throw new Exception("Either the HTTP parameter 'id' or the HTTP parameter 'name' must be specified");
+      }
+            
+      // retrieve existing metadata
+      metadata = fmClient.getMetadata(product);
+
+      // remove product references (as they will be added later)
+      metadata.removeMetadata("reference_orig");
+      metadata.removeMetadata("reference_data_store");
+      metadata.removeMetadata("reference_fileSize");
+      metadata.removeMetadata("reference_mimeType");
+      
+      // merge new and existing metadata
+      metadata.addMetadata(newMetadata);
+      
+      // replace metadata values for keys specified in HTTP request (not others)
+      if (replace) {
+    	  for (String key : newMetadata.getAllKeys()) {
+    		  metadata.replaceMetadata(key, newMetadata.getAllMetadata(key));
+    	  }
+      }
+      
+      // remove metadata tags
+      if (remove) {
+	      for (String key : newMetadata.getAllKeys()) {
+	      	metadata.removeMetadata(key);
+	      }
+      }
+      
+      // insert old and new metadata
+      fmClient.updateMetadata(product, metadata);
+      
+      // return product id to downstream processors
+      return "id="+product.getProductId();
+          
+    } catch (Exception e) {
+    	
+      e.printStackTrace();
+      // return error message
+      throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
+
+    }
+
+  }
+
+  /**
+   * Updates the cataloged {@link Metadata} for a {@link Product} in the CAS
+   * File Manager.
+   * 
+   * @param product
+   *          The {@link Product} to update {@link Metadata} for.
+   * @param metadata
+   *          The new {@link Metadata} to persist into the {@link Catalog}.
+   * @throws CatalogException
+   *           If any error occurs during the update.
+   * @throws IOException
+   * @throws FileNotFoundException
+   */
+  public void updateCatalogMetadata(Product product, Metadata newMetadata)
+      throws CatalogException, FileNotFoundException, IOException {
+    System.getProperties().load(
+        new FileInputStream(CurationService.config.getFileMgrProps()));
+    Catalog catalog = this.getCatalog();
+    
+    Metadata oldMetadata = catalog.getMetadata(product);
+    List<Reference> references = catalog.getProductReferences(product);
+    Product newProduct = new Product(product.getProductName(), product
+        .getProductType(), product.getProductStructure(), product
+        .getTransferStatus(), product.getProductReferences());
+    // Constructor is bugged and doesn't set transfer status
+    newProduct.setTransferStatus(product.getTransferStatus());
+    catalog.removeMetadata(oldMetadata, product);
+    catalog.removeProduct(product);
+    newProduct.setProductId(product.getProductId());
+    catalog.addProduct(newProduct);
+    newProduct.setProductReferences(references);
+    catalog.addProductReferences(newProduct);
+    catalog.addMetadata(newMetadata, newProduct);
+  }
+
+  /**
+   * Method to delete a specific product from the catalog
+   * 
+   * @param id
+   * 	identifier of CAS product - either 'id' or 'name' must be specified
+   * @param name
+   * 	name of CAS product - either 'id' or 'name' must be specified
+   * @return the product ID of the deleted product if deletion successful
+   */
+  @POST
+  @Path(DELETE)
+  @Consumes("application/x-www-form-urlencoded")
+  @Produces("text/plain")
+  public String deleteCatalogMetadata(
+		  @FormParam("id") String id, 
+		  @FormParam("name") String name) {
+
+	  try {
+		  // retrieve product from catalog
+		  Product product = null;
+		  if (StringUtils.hasText(id)) {
+			  id = id.substring(id.lastIndexOf("/") + 1);
+			  product = CurationService.config.getFileManagerClient().getProductById(id);
+		  } else if (StringUtils.hasText(name)) {
+			  product = CurationService.config.getFileManagerClient().getProductByName(name);
+		  } else {
+			  throw new Exception("Either the HTTP parameter 'id' or the HTTP parameter 'name' must be specified");
+		  }
+
+		  // remove product from catalog
+		  this.deleteCatalogProduct(product);
+
+		  // return product id to downstream processors
+		  return "id="+product.getProductId();
+
+	  } catch (Exception e) {
+
+		  e.printStackTrace();
+		  // return error message
+		  throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
+
+	  }
+  }  
+
+  /**
+   * Deletes a given product from the catalog
+   * 
+   * @param product
+   *          The {@link Product} to delete
+   * @throws FileNotFoundException
+   * @throws IOException
+   * @throws CatalogException
+   *           If any error occurs during this delete operation.
+   */
+  public void deleteCatalogProduct(Product product) 
+  throws FileNotFoundException, IOException, CatalogException {
+	  CurationService.config.getFileManagerClient().removeProduct(product);
+  }  
+
+  private Metadata getProductTypeMetadataForPolicy(String policy,
+      String productTypeName) throws MalformedURLException,
+      InstantiationException, RepositoryManagerException {
+    String rootPolicyPath = this.cleanse(CurationService.config
+        .getPolicyUploadPath());
+    String policyPath = new File(rootPolicyPath + policy).toURL()
+        .toExternalForm();
+    String[] policies = { policyPath };
+    XMLRepositoryManager repMgr = new XMLRepositoryManager(Arrays
+        .asList(policies));
+    ProductType productType = repMgr.getProductTypeByName(productTypeName);
+    
+    return productType.getTypeMetadata();
+  }
+  
+  private Metadata writeProductTypeMetadata(String policy,
+      String productTypeName, Metadata metadata) throws Exception {
+    String rootPolicyPath = this.cleanse(CurationService.config
+        .getPolicyUploadPath());
+    String policyPath = new File(rootPolicyPath + policy).toURL()
+        .toExternalForm();
+    String[] policies = { policyPath };
+    XMLRepositoryManager repMgr = new XMLRepositoryManager(Arrays
+        .asList(policies));
+
+    ProductType productType = repMgr.getProductTypeByName(productTypeName);
+    productType.setTypeMetadata(metadata);
+    
+    CurationXmlStructFactory.writeProductTypeXmlDocument(repMgr
+        .getProductTypes(), rootPolicyPath + policy + "/product-types.xml");
+
+    // refresh the config on the fm end
+    CurationService.config.getFileManagerClient().refreshConfigAndPolicy();
+    
+    return productType.getTypeMetadata();
+  }
+  
+  private String cleanse(String origPath) {
+    String retStr = origPath;
+    if (!retStr.endsWith("/")) {
+      retStr += "/";
+    }
+    return retStr;
+  }
+  
+  // Method to instantiate the CAS catalog, if not done already.
+  private synchronized Catalog getCatalog() {
+  	
+  	if (catalog==null) {
+  		String catalogFactoryClass = this.context.getInitParameter(CATALOG_FACTORY_CLASS);
+  		// preserve backward compatibility
+  		if (!StringUtils.hasText(catalogFactoryClass))
+  			catalogFactoryClass = "org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory";
+  		catalog = GenericFileManagerObjectFactory.getCatalogServiceFromFactory(catalogFactoryClass);
+  	}
+  	
+  	return catalog;
+  }
+  
+  @DELETE
+  @Path(PRODUCT_TYPE+"/remove")
+  @Produces("text/plain")
+  public boolean removeProductType(
+		  @FormParam("policy") String policy, 
+		  @FormParam("id") String id) {
+    XMLRepositoryManager xmlRepo = getRepo(policy);
+    try {
+      ProductType type = xmlRepo.getProductTypeById(id);
+      xmlRepo.removeProductType(type);
+      return true;
+    } catch (RepositoryManagerException e) {
+      e.printStackTrace();
+      return false;
+    }
+  }
+  
+  @GET
+  @Path(PRODUCT_TYPE+"/parentmap")
+  @Produces("text/plain")
+  public String getParentTypeMap(
+      @FormParam("policy") String policy) {
+    XMLValidationLayer vLayer = getValidationLayer(policy);
+    return JSONSerializer.toJSON(vLayer.getSubToSuperMap()).toString();
+  }
+	 
+  @POST
+  @Path(PRODUCT_TYPE+"/parent/add")
+  @Produces("text/plain")
+  public boolean addParentForProductType(
+      @FormParam("policy") String policy, 
+      @FormParam("id") String id, 
+      @FormParam("parentId") String parentId) {
+    XMLValidationLayer vLayer = getValidationLayer(policy);
+    XMLRepositoryManager xmlRepo = getRepo(policy);
+    try {
+      ProductType type = xmlRepo.getProductTypeById(id);
+      vLayer.addParentForProductType(type, parentId);
+      return true;
+    } catch (RepositoryManagerException e) {
+      e.printStackTrace();
+    } catch (ValidationLayerException e) {
+      e.printStackTrace();
+    }
+    return false;
+  }
+  
+  @DELETE
+  @Path(PRODUCT_TYPE+"/parent/remove")
+  @Produces("text/plain")
+  public boolean removeParentForProductType(
+      @FormParam("policy") String policy, 
+      @FormParam("id") String id) 
+          throws ValidationLayerException {
+    XMLValidationLayer vLayer = getValidationLayer(policy);
+    XMLRepositoryManager xmlRepo = getRepo(policy);
+    try {
+      ProductType type = xmlRepo.getProductTypeById(id);
+      vLayer.removeParentForProductType(type);
+      return true;
+    } catch (RepositoryManagerException e) {
+      e.printStackTrace();
+    }
+    return false;
+  }
+  
+  @POST
+  @Path(PRODUCT_TYPE+"/elements/add")
+  @Produces("text/plain")
+  public boolean addElementsForProductType(
+		  @FormParam("policy") String policy, 
+		  @FormParam("id") String id,  
+		  @FormParam("elementIds") String elementIds) {
+    XMLValidationLayer vLayer = getValidationLayer(policy);
+    XMLRepositoryManager xmlRepo = getRepo(policy);
+    try {
+      ProductType type = xmlRepo.getProductTypeById(id);
+      for(String elementid: elementIds.split(",")) {
+        Element element = vLayer.getElementById(elementid);
+        if(element == null) {
+          element = new Element(elementid, elementid, "", "", "Automatically added", "");
+          vLayer.addElement(element);
+        }
+        vLayer.addElementToProductType(type, element);
+      }
+      return true;
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    return false;
+  }
+  
+  @GET
+  @Path(PRODUCT_TYPE+"/elements")
+  @Produces("text/plain")
+  public String getElementsForProductType(
+		  @FormParam("policy") String policy, 
+		  @FormParam("id") String id, 
+		  @FormParam("direct") boolean direct) {
+    XMLValidationLayer vLayer = getValidationLayer(policy);
+    XMLRepositoryManager xmlRepo = getRepo(policy);
+    try {
+      ProductType type = xmlRepo.getProductTypeById(id);
+      ArrayList<String> elementIds = new ArrayList<String>();
+      for(Element el : vLayer.getElements(type, direct)) {
+        elementIds.add(el.getElementId());
+      }
+      return JSONSerializer.toJSON(elementIds).toString();
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    return null;
+  }
+  
+  @DELETE
+  @Path(PRODUCT_TYPE+"/elements/remove/all")
+  @Produces("text/plain")
+  public boolean removeAllElementsForProductType(
+		  @FormParam("policy") String policy, 
+		  @FormParam("id") String id) {
+    XMLValidationLayer vLayer = getValidationLayer(policy);
+    XMLRepositoryManager xmlRepo = getRepo(policy);
+    try {
+      ProductType type = xmlRepo.getProductTypeById(id);
+      List<Element> elementList = vLayer.getElements(type);
+      for(Element element: elementList) {
+        vLayer.removeElementFromProductType(type, element);
+      }
+      this.removeUnusedElements(elementList, xmlRepo, vLayer);
+      return true;
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    return false;
+  }
+
+  @DELETE
+  @Path(PRODUCT_TYPE+"/elements/remove")
+  @Produces("text/plain")
+  public boolean removeElementsForProductType(
+		  @FormParam("policy") String policy, 
+		  @FormParam("id") String id, 
+		  @FormParam("elementIds") String elementIds) {
+    XMLValidationLayer vLayer = getValidationLayer(policy);
+    XMLRepositoryManager xmlRepo = getRepo(policy);
+    try {
+      ProductType type = xmlRepo.getProductTypeById(id);
+      ArrayList<Element> elements = new ArrayList<Element>();
+      for(String elementId: elementIds.split(",")) {
+        Element element = vLayer.getElementById(elementId);
+        if(element != null) {
+          vLayer.removeElementFromProductType(type, element);
+          elements.add(element);
+        }
+      }
+      this.removeUnusedElements(elements, xmlRepo, vLayer);
+      return true;
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    return false;
+  }
+  
+  @GET
+  @Path(PRODUCT_TYPE+"/typeswithelement/{elementId}")
+  @Produces("text/plain")
+  public String getProductTypeIdsHavingElement(
+		  @FormParam("policy") String policy, 
+		  @PathParam("elementId") String elementId) {
+	  XMLValidationLayer vLayer = getValidationLayer(policy);
+	  XMLRepositoryManager xmlRepo = getRepo(policy);
+	  ArrayList<String> typeids = new ArrayList<String>();
+      try {
+    	  for(ProductType type : xmlRepo.getProductTypes()) {
+    		  for(Element el : vLayer.getElements(type)) {
+    			  if(el.getElementId().equals(elementId))
+    				  typeids.add(type.getProductTypeId());
+    		  }
+    	  }
+      } catch (Exception e) {
+          e.printStackTrace();
+      }
+      return JSONSerializer.toJSON(typeids).toString();
+  }
+  
+  
+  /*
+   * Private helper functions
+   */
+  private void removeUnusedElements(List<Element> elements, 
+		  XMLRepositoryManager xmlRepo, XMLValidationLayer vLayer) 
+				  throws ValidationLayerException, RepositoryManagerException {
+      // Remove Elements that aren't used in any product type
+      List<ProductType> ptypelist = xmlRepo.getProductTypes();
+      HashMap<String, Boolean> usedElementIds = new HashMap<String, Boolean>();
+      for(ProductType ptype: ptypelist) {
+          List<Element> ptypeElements = 
+              vLayer.getElements(ptype);
+          for(Element el: ptypeElements) {
+              usedElementIds.put(el.getElementId(), true);
+          }
+      }
+      for(Element el: elements) {
+          if(!usedElementIds.containsKey(el.getElementId()))
+             vLayer.removeElement(el);
+      }
+  }  
+
+	private XMLRepositoryManager getRepo(String policy) {
+		XMLRepositoryManager xmlRepo = null;
+		String url = "file://" + CurationService.config.getPolicyUploadPath() + "/" + policy;
+
+		try {
+			xmlRepo = new XMLRepositoryManager(Collections.singletonList(url));
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+		return xmlRepo;
+	}
+
+	private XMLValidationLayer getValidationLayer(String policy) {
+		XMLValidationLayer vLayer = null;
+		String url = "file://" + CurationService.config.getPolicyUploadPath() + "/" + policy;
+
+		try {
+			vLayer = new XMLValidationLayer(Collections.singletonList(url));
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return vLayer;
+	}
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/PolicyResource.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/PolicyResource.java
new file mode 100644
index 0000000..ff98753
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/PolicyResource.java
@@ -0,0 +1,310 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.curation.service;
+
+//OODT imports
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.oodt.cas.filemgr.repository.XMLRepositoryManager;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+
+//JDK imports
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//JAX-RS imports
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+//JSON imports
+import net.sf.json.JSONObject;
+
+@Path("policy")
+public class PolicyResource extends CurationService {
+
+  @Context
+  UriInfo uriInfo;
+
+  private static final long serialVersionUID = -3757481221589264709L;
+
+  private static final Logger LOG = Logger.getLogger(PolicyResource.class
+      .getName());
+
+  private static final FilenameFilter DIR_FILTER = new FilenameFilter() {
+
+    public boolean accept(File dir, String name) {
+      return new File(dir, name).isDirectory()
+          && !new File(dir, name).getName().startsWith(".");
+    }
+  };
+  
+  public PolicyResource(@Context ServletContext context){
+    
+  }
+
+  @GET
+  @Path("browse")
+  @Produces("text/plain")
+  public String browseCatalog(
+      @QueryParam("path") @DefaultValue("/") String path,
+      @DefaultValue(FORMAT_HTML) @QueryParam("format") String format,
+      @DefaultValue("1") @QueryParam("pageNum") Integer pageNum,
+      @Context HttpServletRequest req, @Context HttpServletResponse res)
+      throws IOException {
+    
+    // TODO: Send a not authorized response if not logged in. This should be a
+    // utility method as a part of CurationService that every service interface
+    // calls.
+
+    String[] pathToks = tokenizeVirtualPath(path);
+    String policy = null;
+    String productType = null;
+
+    if (pathToks == null) {
+      LOG.log(Level.WARNING, "malformed path token string: "
+          + Arrays.asList(pathToks));
+      return "";
+    }
+
+    policy = pathToks.length > 0 ? pathToks[0]:null;
+    productType = pathToks.length > 1 ? pathToks[1] : null;
+
+    if (policy != null) {
+      if (productType != null) {
+        return getProductsForProductType(policy, productType, format, pageNum);
+      } else {
+        return getProductTypesForPolicy(policy, format);
+      }
+    } else {
+      return getPolicies(format);
+    }
+
+  }
+  
+  private String getProductsForProductType(String policy,
+      String productTypeName,
+      String format, int pageNum) {
+    
+    ProductType productType;
+    ProductPage page;
+    try {
+      productType = this.config.getFileManagerClient().getProductTypeByName(
+          productTypeName);
+      page = this.config.getFileManagerClient().pagedQuery(new Query(),
+          productType, pageNum);
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Unable to obtain products for product type: ["
+          + productTypeName + "]: Message: " + e.getMessage());
+      return "";
+    }
+
+    if (format.equals(FORMAT_HTML)) {
+      return encodeProductsAsHTML(page, policy, productTypeName);
+    } else if (format.equals(FORMAT_JSON)) {
+      return encodeProductsAsJSON(page, policy, productTypeName);
+    } else {
+      return UNKNOWN_OUT_FORMAT;
+    }
+  }
+  
+  private String encodeProductsAsHTML(ProductPage page, String policy,
+      String productTypeName) {
+    StringBuffer html = new StringBuffer();
+    html.append("<ul class=\"fileTree\" >\r\n");
+    
+    for (Product product : page.getPageProducts()) {
+      html.append(" <li class=\"file\">");
+      html.append("<a href=\"#\" rel=\"/");
+      html.append(policy);
+      html.append("/");
+      html.append(productTypeName);
+      html.append("/");
+      html.append(product.getProductId());
+      html.append("\">");
+      html.append(product.getProductName());
+      html.append("</a>");
+      html.append("</li>\r\n");
+    }
+
+    html.append("</ul>");
+    return html.toString();
+  }
+  
+  private String encodeProductsAsJSON(ProductPage page, String policy,
+      String productTypeName) {
+    return "NOT IMPLENTED YET";
+  }
+
+  private String getPolicies(String format) {
+    String policyPath = this.cleanse(CurationService.config
+        .getPolicyUploadPath());
+    String[] policyDirs = new File(policyPath).list(DIR_FILTER);
+
+    if (format.equals(FORMAT_HTML)) {
+      return encodePoliciesAsHTML(policyDirs);
+    } else if (format.equals(FORMAT_JSON)) {
+      return encodePoliciesAsJSON(policyDirs);
+    } else {
+      return UNKNOWN_OUT_FORMAT;
+    }
+
+  }
+
+  private String getProductTypesForPolicy(String policy, String format) {
+    String[] typeNames = null;
+    try {
+      typeNames = this.getProductTypeNamesForPolicy(policy);
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Unable to obtain product type names for policy: [" + policy
+              + "]: Message: " + e.getMessage());
+      return "";
+    }
+
+    if (format.equals(FORMAT_HTML)) {
+      return encodeProductTypesAsHTML(policy, typeNames);
+    } else if (format.equals(FORMAT_JSON)) {
+      return encodeProductTypesAsJSON(policy, typeNames);
+    } else {
+      return UNKNOWN_OUT_FORMAT;
+    }
+
+  }
+
+  private String encodePoliciesAsHTML(String[] policyDirs) {
+    StringBuffer out = new StringBuffer();
+    out.append("<ul class=\"fileTree\" >");
+    for (String policy : policyDirs) {
+      out.append("<li class=\"directory collapsed\"><a href=\"#\" rel=\"/");
+      out.append(StringEscapeUtils.escapeHtml(policy));
+      out.append("/\">");
+      out.append(StringEscapeUtils.escapeHtml(policy));
+      out.append("</a></li>");
+    }
+    out.append("</ul>");
+    return out.toString();
+  }
+
+  private String encodePoliciesAsJSON(String[] policyDirs) {
+    Map<String, String> retMap = new HashMap<String, String>();
+    for (String policyDir : policyDirs) {
+      retMap.put("policy", policyDir);
+    }
+    JSONObject resObj = new JSONObject();
+    resObj.put("policies", retMap);
+    resObj.put("succeed", true);
+    return resObj.toString();
+  }
+
+  private String encodeProductTypesAsHTML(String policy, String[] typeNames) {
+    StringBuffer out = new StringBuffer();
+    out.append("<ul class=\"fileTree\" >");
+    for (String type : typeNames) {
+      out
+          .append("<li class=\"directory collapsed productType\"><a href=\"#\" rel=\"/");
+      out.append(StringEscapeUtils.escapeHtml(policy));
+      out.append("/");
+      out.append(StringEscapeUtils.escapeHtml(type));
+      out.append("/\">");
+      out.append(StringEscapeUtils.escapeHtml(type));
+      out.append("</a></li>");
+    }
+
+    out.append("</ul>");
+    return out.toString();
+  }
+
+  private String encodeProductTypesAsJSON(String policy, String[] typeNames) {
+    Map<String, Object> retMap = new HashMap<String, Object>();
+    retMap.put("policy", policy);
+    List<Map<String, String>> typeList = new Vector<Map<String, String>>();
+    for (String typeName : typeNames) {
+      Map<String, String> typeMap = new HashMap<String, String>();
+      typeMap.put("name", typeName);
+      typeList.add(typeMap);
+    }
+    retMap.put("productTypes", typeList);
+    JSONObject resObj = new JSONObject();
+    resObj.putAll(retMap);
+    return resObj.toString();
+  }
+
+  private String[] getProductTypeNamesForPolicy(String policy)
+      throws MalformedURLException, InstantiationException,
+      RepositoryManagerException {
+    String rootPolicyPath = this.cleanse(CurationService.config
+        .getPolicyUploadPath());
+    String policyPath = new File(rootPolicyPath + policy).toURL()
+        .toExternalForm();
+    String[] policies = { policyPath };
+    XMLRepositoryManager repMgr = new XMLRepositoryManager(Arrays
+        .asList(policies));
+    List<ProductType> types = repMgr.getProductTypes();
+    String[] typeNames = new String[types.size()];
+    int i = 0;
+    for (ProductType type : types) {
+      typeNames[i] = type.getName();
+      i++;
+    }
+
+    return typeNames;
+  }
+
+  private String cleanse(String origPath) {
+    String retStr = origPath;
+    if (!retStr.endsWith("/")) {
+      retStr += "/";
+    }
+    return retStr;
+  }
+
+  private String[] tokenizeVirtualPath(String path) {
+    String vPath = path;
+    if (vPath.startsWith("/") && vPath.length() != 1) {
+      vPath = vPath.substring(1);
+    }
+    String[] pathToks = vPath.split("/");
+    LOG.log(Level.INFO, "origPath: ["+path+"]");
+    LOG.log(Level.INFO, "pathToks: "+Arrays.asList(pathToks));
+    return pathToks;
+  }
+
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/SystemResource.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/SystemResource.java
new file mode 100644
index 0000000..784d383
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/service/SystemResource.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.curation.service;
+
+//JAX-RS imports
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+@Path("system")
+public class SystemResource extends CurationService {
+
+  @Context
+  UriInfo uriInfo;
+  
+  private static final long serialVersionUID = -2318607955517605998L;
+
+  /**
+   * This is what will go in the upper left box on landing page. To gather
+   * information such as is the file manager up If this needs to be something
+   * that gets updated periodically then it would change into a JSON feed
+   */
+  @GET
+  @Path("stats")
+  @Produces("text/html")
+  public String getStatistics() {
+    return "<div>Server Stats</div>";
+  }
+
+  /**
+   * This returns the configuration information that is set in the context.xml
+   * file.
+   */
+  @GET
+  @Path("config")
+  @Produces("text/html")
+  public String getConfig() {
+    return "";
+  }
+
+  /**
+   * This will return the information that appears in the upper right box on
+   * landing page.
+   */
+  @GET
+  @Path("feed")
+  @Produces("text/html")
+  public String getFeed() {
+    return "<div>Latest Products?</div>";
+  }
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/servlet/CuratorConfMetKeys.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/servlet/CuratorConfMetKeys.java
new file mode 100644
index 0000000..6233775
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/servlet/CuratorConfMetKeys.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.curation.servlet;
+
+/**
+ * 
+ * Met keys used in the <code>context.xml</code> file to configure the CAS
+ * curator webapp.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface CuratorConfMetKeys {
+
+  final String MET_EXTRACTOR_CONF_UPLOAD_PATH = "org.apache.oodt.cas.curator.metExtractorConf.uploadPath";
+
+  final String POLICY_UPLOAD_PATH = "org.apache.oodt.cas.curator.dataDefinition.uploadPath";
+
+  final String FM_URL = "org.apache.oodt.cas.fm.url";
+
+  final String SSO_IMPL_CLASS = "org.apache.oodt.security.sso.implClass";
+
+  final String DEFAULT_TRANSFER_FACTORY = "org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory";
+
+  final String CRAWLER_CONF_FILE = "classpath:/org.apache/oodt/cas/crawl/crawler-config.xml";
+
+  final String PROJECT_DISPLAY_NAME = "org.apache.oodt.cas.curator.projectName";
+
+  final String STAGING_AREA_PATH = "org.apache.oodt.cas.curator.stagingAreaPath";
+
+  final String MET_AREA_PATH = "org.apache.oodt.cas.curator.metAreaPath";
+  
+  final String MET_EXTENSION = "org.apache.oodt.cas.curator.metExtension";
+  
+  final String FM_PROPS = "org.apache.oodt.cas.curator.fmProps";
+  
+  final String CATALOG_FACTORY_CLASS = "org.apache.oodt.cas.curator.catalogFactoryClass";
+  
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/structs/ExtractorConfig.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/structs/ExtractorConfig.java
new file mode 100644
index 0000000..b2914aa
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/structs/ExtractorConfig.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.curation.structs;
+
+import java.io.File;
+import java.util.List;
+
+public class ExtractorConfig {
+  
+  public final static String PROP_CLASS_NAME = "extractor.classname";
+
+  public final static String PROP_CONFIG_FILES = "extractor.config.files";
+  
+  private final List<File> configFiles;
+
+  private final String className;
+
+  private final String identifier;
+  
+  public ExtractorConfig(String identifier, String className,
+      List<File> configFiles) {
+    this.configFiles = configFiles;
+    this.className = className;
+    this.identifier = identifier;
+  }
+  
+  public List<File> getConfigFiles() {
+    return this.configFiles;
+  }
+  
+  public String getClassName() {
+    return this.className;
+  }
+  
+  public String getIdentifier() {
+    return this.identifier;
+  }
+  
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/structs/IngestionTask.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/structs/IngestionTask.java
new file mode 100644
index 0000000..d6bb4ca
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/structs/IngestionTask.java
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.curation.structs;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.ingest.Ingester;
+
+//JDK imports
+import java.util.Date;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * 
+ * A specification for ingestion using the {@link Ingester} interface in the
+ * CAS.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class IngestionTask implements IngestionTaskStatus {
+
+  private String id;
+
+  private Date createDate;
+
+  private List<String> fileList;
+
+  private String policy;
+
+  private String productType;
+
+  private String status;
+
+  private ExtractorConfig extConf;
+
+  public IngestionTask() {
+    this.id = null;
+    this.createDate = null;
+    this.fileList = new Vector<String>();
+    this.policy = null;
+    this.productType = null;
+    this.extConf = new ExtractorConfig(null, null, null);
+  }
+
+  /**
+   * @return the id
+   */
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * @param id
+   *          the id to set
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * @return the createDate
+   */
+  public Date getCreateDate() {
+    return createDate;
+  }
+
+  /**
+   * @param createDate
+   *          the createDate to set
+   */
+  public void setCreateDate(Date createDate) {
+    this.createDate = createDate;
+  }
+
+  /**
+   * @return the fileList
+   */
+  public List<String> getFileList() {
+    return fileList;
+  }
+
+  /**
+   * @param fileList
+   *          the fileList to set
+   */
+  public void setFileList(List<String> fileList) {
+    this.fileList = fileList;
+  }
+
+  /**
+   * @return the policy
+   */
+  public String getPolicy() {
+    return policy;
+  }
+
+  /**
+   * @param policy
+   *          the policy to set
+   */
+  public void setPolicy(String policy) {
+    this.policy = policy;
+  }
+
+  /**
+   * @return the productType
+   */
+  public String getProductType() {
+    return productType;
+  }
+
+  /**
+   * @param productType
+   *          the productType to set
+   */
+  public void setProductType(String productType) {
+    this.productType = productType;
+  }
+
+  /**
+   * @return the status
+   */
+  public String getStatus() {
+    return status;
+  }
+
+  /**
+   * @param status
+   *          the status to set
+   */
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  /**
+   * @return the extConf
+   */
+  public ExtractorConfig getExtConf() {
+    return extConf;
+  }
+
+  /**
+   * @param extConf
+   *          the extConf to set
+   */
+  public void setExtConf(ExtractorConfig extConf) {
+    this.extConf = extConf;
+  }
+
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/structs/IngestionTaskStatus.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/structs/IngestionTaskStatus.java
new file mode 100644
index 0000000..7527060
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/structs/IngestionTaskStatus.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.curation.structs;
+
+/**
+ *
+ * Met keys for the {@link IngestionTask#getStatus()} field.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public interface IngestionTaskStatus {
+
+  public static final String FINISHED = "Finished";
+  
+  public static final String STARTED = "Started";
+  
+  public static final String NOT_STARTED = "Not Started";
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/CurationXmlStructFactory.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/CurationXmlStructFactory.java
new file mode 100644
index 0000000..ec04c37
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/CurationXmlStructFactory.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.curation.util;
+
+//JDK imports
+import java.net.URLEncoder;
+import java.util.List;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.util.XmlStructFactory;
+
+/**
+ * 
+ * Until we solve the serialization problem in CAS 1.8.0 for adding metadata and
+ * extractor information to {@link XmlStructFactory}, this class will suffice to
+ * get us the actual policy management that we need.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class CurationXmlStructFactory {
+
+  public static void writeProductTypeXmlDocument(
+      List<ProductType> productTypes, String xmlFilePath) throws Exception {
+    XMLUtils.writeXmlFile(getProductTypeXmlDocument(productTypes), xmlFilePath);
+  }
+
+  public static Document getProductTypeXmlDocument(
+      List<ProductType> productTypes) throws Exception {
+    Document doc = XmlStructFactory.getProductTypeXmlDocument(productTypes);
+
+    // for every product type, i want to add in the versioner info and the
+    // met extractor info
+
+    Element rootElem = doc.getDocumentElement();
+    NodeList typeNodeList = rootElem.getElementsByTagName("type");
+    if (typeNodeList != null && typeNodeList.getLength() > 0) {
+      for (int i = 0; i < typeNodeList.getLength(); i++) {
+        Element typeElem = (Element) typeNodeList.item(i);
+        augmentElement(productTypes, typeElem, doc);
+      }
+    }
+
+    return doc;
+  }
+
+  private static void augmentElement(List<ProductType> productTypes,
+      Element typeElem, Document doc) throws Exception {
+    String productTypeName = typeElem.getAttribute("name");
+    ProductType type = getType(productTypes, productTypeName);
+
+    Element metadataRootElem = doc.createElement("metadata");
+    
+    for (Object metKey : type.getTypeMetadata().getHashtable().keySet()) {
+      String key = (String) metKey;
+      List<String> vals = type.getTypeMetadata().getAllMetadata(key);
+
+      Element metadataElem = doc.createElement("keyval");
+      Element keyElem = doc.createElement("key");
+      keyElem.appendChild(doc.createTextNode(URLEncoder.encode(key, "UTF-8")));
+
+      metadataElem.appendChild(keyElem);
+      for (String val : vals) {
+        Element valElem = doc.createElement("val");
+        if (val == null) {
+          throw new Exception("Attempt to write null value "
+              + "for property: [" + key + "]: val: [" + val + "]");
+        }
+
+        valElem
+            .appendChild(doc.createTextNode(URLEncoder.encode(val, "UTF-8")));
+        metadataElem.appendChild(valElem);
+      }
+
+      metadataRootElem.appendChild(metadataElem);
+      typeElem.appendChild(metadataRootElem);
+
+    }
+
+  }
+
+  private static ProductType getType(List<ProductType> types, String name) {
+    for (ProductType type : types) {
+      if (type.getName().equals(name)) {
+        return type;
+      }
+    }
+
+    return null;
+  }
+
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/DateUtils.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/DateUtils.java
new file mode 100644
index 0000000..27cbad4
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/DateUtils.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.curation.util;
+
+//JDK imports
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * 
+ * Sample ISO 8601 date utility methods taken from:
+ * 
+ * <a href="http://www.dynamicobjects.com/d2r/archives/003057.html">http://www.
+ * dynamicobjects.com/d2r/archives/003057.html</a>
+ * 
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public final class DateUtils {
+
+  public static SimpleDateFormat ISO8601FORMAT = new SimpleDateFormat(
+      "yyyy-MM-dd'T'HH:mm:ssZ");
+
+  public static SimpleDateFormat RFC822DATEFORMAT = new SimpleDateFormat(
+      "EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z", Locale.US);
+
+  public static String getDateAsRFC822String(Date date) {
+    return RFC822DATEFORMAT.format(date);
+  }
+
+  public static String getDateAsISO8601String(Date date) {
+    String result = ISO8601FORMAT.format(date);
+    // convert YYYYMMDDTHH:mm:ss+HH00 into YYYYMMDDTHH:mm:ss+HH:00
+    // - note the added colon for the Timezone
+    result = result.substring(0, result.length() - 2) + ":"
+        + result.substring(result.length() - 2);
+    return result;
+  }
+
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/ExtractorConfigReader.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/ExtractorConfigReader.java
new file mode 100644
index 0000000..a355d67
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/ExtractorConfigReader.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.curation.util;
+
+
+import org.apache.oodt.cas.curation.structs.ExtractorConfig;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+public class ExtractorConfigReader {
+  public static ExtractorConfig readFromDirectory(File directory,
+      String configId) throws FileNotFoundException, IOException {
+    File propsFileDir = new File(directory, configId);
+    Properties props = new Properties();
+    props
+        .load(new FileInputStream(new File(propsFileDir,
+        "config.properties")));
+    
+    String identifier = configId;
+    String className = props.getProperty(ExtractorConfig.PROP_CLASS_NAME);
+    List<File> files = new ArrayList<File>();
+    String[] fileList = props.getProperty(ExtractorConfig.PROP_CONFIG_FILES)
+        .split(",");
+    for (int i = 0; i < fileList.length; i++) {
+      files.add(new File(PathUtils.replaceEnvVariables(fileList[0])));
+    }
+    
+    return new ExtractorConfig(identifier, className, files);
+  }
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/ExtractorConfigWriter.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/ExtractorConfigWriter.java
new file mode 100644
index 0000000..3e3488d
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/ExtractorConfigWriter.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.curation.util;
+
+
+import org.apache.oodt.cas.curation.structs.ExtractorConfig;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.Iterator;
+
+public class ExtractorConfigWriter {
+  
+  public static void saveToDirectory(ExtractorConfig config, File dir)
+      throws FileNotFoundException, IOException {
+    Properties props = new Properties();
+    props.setProperty(ExtractorConfig.PROP_CLASS_NAME, config.getClassName());
+    File configDir = new File(dir, config.getIdentifier());
+    configDir.mkdirs();
+    StringBuffer files = new StringBuffer();
+    for (Iterator<File> i = config.getConfigFiles().iterator(); i.hasNext();) {
+      File file = i.next();
+      files.append(file.toURI());
+      if (i.hasNext())
+        files.append(",");
+    }
+    props.setProperty(ExtractorConfig.PROP_CONFIG_FILES, files.toString());
+    props
+        .store(new FileOutputStream(new File(configDir, "config.properties")),
+        "");
+  }
+
+}
diff --git a/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/SSOUtils.java b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/SSOUtils.java
new file mode 100644
index 0000000..a5fa0e8
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/java/org/apache/oodt/cas/curation/util/SSOUtils.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.curation.util;
+
+//JDK imports
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+//OODT imports
+import org.apache.oodt.cas.curation.service.CurationServiceConfig;
+import org.apache.oodt.cas.curation.servlet.CuratorConfMetKeys;
+import org.apache.oodt.security.sso.AbstractWebBasedSingleSignOn;
+import org.apache.oodt.security.sso.SingleSignOnFactory;
+
+/**
+ * 
+ * Utilities for configuring the {@link AbstractWebBasedSingleSignOn} for use
+ * in the CAS curator webapp.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class SSOUtils implements CuratorConfMetKeys {
+
+  public static AbstractWebBasedSingleSignOn getWebSingleSignOn(
+      ServletContext context, HttpServletRequest req, HttpServletResponse res) {
+    AbstractWebBasedSingleSignOn sso = SingleSignOnFactory
+        .getWebBasedSingleSignOn(context.getInitParameter(SSO_IMPL_CLASS));
+    sso.setReq(req);
+    sso.setRes(res);
+    return sso;
+  }
+  
+  public static AbstractWebBasedSingleSignOn getWebSingleSignOn(
+      CurationServiceConfig cfg, HttpServletRequest req, HttpServletResponse res) {
+    AbstractWebBasedSingleSignOn sso = SingleSignOnFactory
+        .getWebBasedSingleSignOn(cfg.getParameter(SSO_IMPL_CLASS));
+    sso.setReq(req);
+    sso.setRes(res);
+    return sso;
+  }
+}
diff --git a/0.8.1-rc1/curator/src/main/webapp/META-INF/context.xml b/0.8.1-rc1/curator/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..0158712
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,50 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<Context path="/cas-curator" docBase="/path/to/cas-curation-0.1.war">
+
+    <Parameter name="org.apache.oodt.cas.curator.projectName"
+        value="OODT"/>
+
+	<Parameter name="org.apache.oodt.cas.curator.metExtractorConf.uploadPath"
+		value="[CAS_CURATOR_HOME]/aux/met_def/cas_curator" />
+
+	<Parameter name="org.apache.oodt.cas.curator.dataDefinition.uploadPath"
+		value="[CAS_CURATOR_HOME]/policy" />
+		
+    <Parameter name="org.apache.oodt.cas.curator.stagingAreaPath"
+        value="/data/ingest"/>
+    
+    <Parameter name="org.apache.oodt.cas.curator.metAreaPath"
+    value="/data/met"/>
+    
+    <Parameter name="org.apache.oodt.cas.curator.fmProps"
+        value="[CAS_CURATOR_HOME]/filemgr/etc/filemgr.properties"/>
+    
+    <Parameter name="org.apache.oodt.cas.curator.metExtension"
+        value=".met"/>
+		
+	<Parameter name="org.apache.oodt.cas.fm.url"
+	    value="http://localhost:9000"/>
+	    
+	<Parameter name="org.apache.oodt.security.sso.implClass"
+	          value="org.apache.oodt.security.sso.DummyImpl"/>
+	          
+	<Parameter name="org.apache.oodt.cas.curator.catalogFactoryClass" 
+			   value="org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory" />
+
+</Context>
diff --git a/0.8.1-rc1/curator/src/main/webapp/WEB-INF/web.xml b/0.8.1-rc1/curator/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..c55e884
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+	<display-name>curate</display-name>
+	<servlet>
+	 <servlet-name>CXFServlet</servlet-name>
+	 <servlet-class>
+	   org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet
+	 </servlet-class>
+	 <init-param>
+	  <param-name>jaxrs.serviceClasses</param-name>
+	  <param-value>
+	    org.apache.oodt.cas.curation.service.DirectoryResource
+	    org.apache.oodt.cas.curation.service.IngestionResource
+	    org.apache.oodt.cas.curation.service.MetadataResource
+	    org.apache.oodt.cas.curation.service.PolicyResource
+	    org.apache.oodt.cas.curation.service.SystemResource
+	  </param-value>
+	 </init-param>
+	<load-on-startup>1</load-on-startup>
+	</servlet>
+
+   <servlet>
+        <display-name>Curation Service</display-name>
+        <servlet-name>Curation Service</servlet-name>
+        <servlet-class>org.apache.oodt.cas.curation.service.CurationService</servlet-class>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    
+
+	<servlet-mapping>
+		<servlet-name>CXFServlet</servlet-name>
+		<url-pattern>/services/*</url-pattern>
+	</servlet-mapping>
+
+</web-app>
diff --git a/0.8.1-rc1/curator/src/main/webapp/error.jsp b/0.8.1-rc1/curator/src/main/webapp/error.jsp
new file mode 100755
index 0000000..d8ba28f
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/error.jsp
@@ -0,0 +1,22 @@
+<%
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+%>
+<jsp:include page="views/common/cas-curator-header.jsp" />
+<div id="page">
+<h3> There was an error processing your request.</h3>
+<%= session.getAttribute("errorMsg") %>
+</div>
+<jsp:include page="views/common/cas-curator-footer.jsp" />
diff --git a/0.8.1-rc1/curator/src/main/webapp/home.jsp b/0.8.1-rc1/curator/src/main/webapp/home.jsp
new file mode 100644
index 0000000..c78d546
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/home.jsp
@@ -0,0 +1,160 @@
+<%
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+%>
+<% /* 
+	* External libraries that might be used for this JSP (maybe none) 
+	*/ 
+%>
+<%@ page
+	import="java.util.List"
+	import="java.util.ArrayList"
+	import="java.util.Iterator"
+	import="java.util.Map"
+%>
+
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+    pageEncoding="ISO-8859-1"
+%>
+
+<%@page 
+    import="org.apache.oodt.cas.curation.servlet.CuratorConfMetKeys"
+%>
+<jsp:include page="views/common/cas-curator-header.jsp" />
+
+<%@ include file="tools/requireLogin.jsp"%>
+
+
+<div class="page">
+	<div class="container browsers">
+		<div id="browseStagingContainer">
+		<h5>Staging Area</h5>
+			<div id="browseStagingPath" class="pathbar">initializing...</div>
+			<div id="browseStaging" class="browser">
+				<div id="browseStagingNav">
+					<ul class="fileTree">
+						<li class="directory nav"><a id="stagingNavUpRoot" href="#" rel=".">.</a></li>
+						<li class="directory nav"><a id="stagingNavUpOne"  href="#" rel="..">..</a></li>
+					</ul>
+				</div>
+				<div id="browseStagingContents"></div>
+			</div>
+			<div id="stagedMetadataWorkbench"   class="editor">
+				<div id="infoNoMetadataExtractorDefined" class="info overlay">
+					<div class="infoContent">
+						No Metadata Detected...<br/>
+					</div>
+				</div>
+				<div id="stagingMetContainer">				
+					<div id="stagingMetExtractorSelection">
+						<select id="stagingMetExtractorConfigList">
+							<option value="-1">Initializing...</option>
+						</select>
+						<input id="stagingMetExtractorRefreshButton" type="button" value="Refresh"/>
+						&nbsp;
+						
+					</div>
+					<div id="stagedMetadataWorkbenchContent"></div>
+				</div>
+			</div>
+		</div>
+		<div id="browseCatalogContainer">
+		<h5>File Manager Catalog</h5>
+			<div id="browseCatalogPath" class="pathbar">initializing...</div>
+			<div id="browseCatalog" class="browser">
+				<div id="browseCatalogNav">
+					<ul class="fileTree">
+						<li class="directory nav"><a id="catalogNavUpRoot" href="#" rel=".">.</a></li>
+						<li class="directory nav"><a id="catalogNavUpOne"  href="#" rel="..">..</a></li>
+					</ul>
+				</div>
+				<div id="browseCatalogContents"></div>
+			</div>
+			<div id="catalogMetadataWorkbench" class="editor">
+				<div id="catalogMetadataWorkbenchContent"></div>
+			</div>
+		</div>
+		<br class="clr"/>
+	</div>
+	<div class="container tasks">
+		<div id="ingestionTaskList">
+			<h5>File Manager Ingestion Task List</h5>
+			<div id="ingestionTaskListContent">
+			<table cellspacing="0" cellpadding="0" id="ingestionTaskListItems">
+			  <thead>
+			  <tr>
+			    <th style="width:50px;">TaskId</th>
+			    <th>Created</th>
+			    <th>Files</th>
+			    <th>Policy</th>
+			    <th>ProductType</th>
+			    <th>MetExtractor</th>
+			    <th>MetExt Config</th>
+			    <th>Status</th>
+			    <th style="border-right-width:0px;">Action</th>
+			  </tr>
+			  </thead>
+			  <tbody>
+			  
+			</table>
+			</div>
+		</div>
+	</div>
+</div>
+
+<!-- product type workbench -->
+<div id="productTypeWorkbenchContents" style="display:none">
+	<ul>
+		<li><a href='#ptwbAddProducts'>Add Products</a></li>
+		<li><a href='#ptwbMetadata'>View Metadata</a></li>
+	</ul><br class="clr"/>
+	<div id="ptwbAddProducts">
+		<span class="instructions">
+		Add files from the staging area by dragging them into the target box below. Once you have 
+		Finished, click 'Save as Ingestion Task' to finalize.
+		</span>
+		<div id="droppedFileTarget" class="ptwbSectionBox">
+			<h5>File Drop Target...</h5>
+		
+		</div>
+		<div id="droppedFileList" class="ptwbSectionBox">
+			<h5>Files to be ingested...</h5>
+			<ul></ul>
+		</div>
+		<div id="itMetExtractorSelector" class="ptwbSectionBox">
+			<h5>Metadata Extraction Configuration...</h5>
+			<span class="instructions">Choose a metadata extractor configuration from
+				the list below:
+			</span>
+			<select name="itMetExtractorConfigId" id="itMetExtractorConfigId">
+				<option value="">Initializing...</option>
+			</select><br/><br/>
+		</div>
+		<div id="itCreateIngestionTaskButton">
+			<span class="instructions">Click here to create an ingestion task for these files</span>
+			<input type="button" value="Save as Ingestion Task" onclick="createIngestionTask();"/>
+		</div>
+	
+	</div>
+    <div id="ptwbMetadata">
+      	<span class="instructions">
+      		The following metadata has been defined for this product type.
+      	</span>
+      	<div class="ptwbMetadataList"></div>
+    </div>
+</div>
+
+
+<jsp:include page="views/common/cas-curator-footer.jsp"/>
diff --git a/0.8.1-rc1/curator/src/main/webapp/index.jsp b/0.8.1-rc1/curator/src/main/webapp/index.jsp
new file mode 100644
index 0000000..5a53dc6
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/index.jsp
@@ -0,0 +1,20 @@
+<%
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+%>
+
+<%
+response.sendRedirect("home.jsp");
+%>
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/editing.js b/0.8.1-rc1/curator/src/main/webapp/js/editing.js
new file mode 100644
index 0000000..bb44844
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/editing.js
@@ -0,0 +1,149 @@
+/*
+  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.
+*/
+
+
+/**
+ * Metadata editors
+ *
+ */
+
+function makeStagedMetadataEditable() {
+	makeMetadataEditable(
+		$("#stagedMetadataWorkbenchContent > table > tbody > tr >  td"),
+		updateStagedMetadata);
+}
+
+function makeProductMetadataEditable() {
+	makeMetadataEditable(
+		$("#catalogMetadataWorkbenchContent > table > tbody > tr > td"),
+		updateProductMetadata);		
+}
+
+function makeProductTypeMetadataEditable() {
+	makeMetadataEditable(
+		$("#liveProductTypeWorkbenchContents div.ptwbMetadataList > table > tbody > tr > td"),
+		updateProductTypeMetadata);
+}
+
+function updateStagedMetadata() {
+	// Data is the collection of <tr/> elements that contain metadata key/value pairs
+	var data = getMetadataFromSource($('#stagedMetadataWorkbenchContent > table > tbody > tr'));
+	var qstr = getQueryStringFromMetadata(_paths.currentStagedFile, data);
+	
+	$.post('./services/metadata/staging',
+		qstr,
+		function(data, textStatus) {
+			// alert(data);
+		}
+	);
+}
+
+function updateProductMetadata() {
+	// Data is the collection of <tr/> elements that contain metadata key/value pairs
+	var data = getMetadataFromSource($('#catalogMetadataWorkbenchContent > table > tbody > tr'));
+	var qstr = getQueryStringFromMetadata(_paths.currentCatalogedFile, data);
+
+	$.post('./services/metadata/catalog',
+		qstr,
+		function(data, textStatus) {
+			// alert(data);
+		}
+	);
+}
+
+function updateProductTypeMetadata() {
+	// Data is the collection of <tr/> elements that contain metadata key/value pairs
+	var data = getMetadataFromSource($('#liveProductTypeWorkbenchContents div.ptwbMetadataList > table > tbody > tr'));
+	var qstr = getQueryStringFromMetadata(_paths.currentProductType, data);
+
+	$.post('./services/metadata/productType',
+		qstr,
+		function(data, textStatus) {
+			// alert(data);
+		}
+	);
+}
+
+
+
+/**
+ * Utility functions to encapsulate common functionality
+ *
+ */
+
+// source:   the collection of <td/> objects containing metadata values
+// callback: the function to be called to persist the edits
+function makeMetadataEditable(source, callback) {
+	// Set up the i/f to display the icon only when the user is hovering over
+	// the field
+	source.click(function() {
+		var $met = $(this);
+		var metValue = $met; // the <td> itself
+			var metKey = $(this).prev().text();
+			jPromptMulti(
+					metKey,
+					metValue,
+					'Update Metadata',
+					function(r) {
+
+						if (r) {
+							// turn r into a comma-separated string of values
+							htmlResult = '<span>' + r.join('</span>, <span>') + '</span>';
+							// alert( 'You entered ' + htmlResult )
+							$met.html(htmlResult);
+							callback();
+						}
+					});
+		});
+}
+
+function getMetadataFromSource( source ) {
+	
+	// Keys are 1 per row in <th/> elements
+	// Values are 1 per row in <td/> elements
+	
+	var $table = source;
+	var data   = Array();
+	$table.each( function () {
+		// Create a key/value mapping of the staged metadata
+		var $valueElmt = $(this).children('td');
+		// All values are wrapped in <span/> elements and there can be
+		// an unlimited number of them, so build an array.
+		var $values    = $valueElmt.children('span');
+		var valueData  = Array();
+		for (var i = 0; i < $values.length; i ++ ) {
+			valueData.push($values[i].textContent);
+		}
+		// Assign the value data to the correct element
+		data.push( { 'key' : $(this).children('th').text(), 'value' : valueData } );
+	});
+	
+	return data;
+}
+
+function getQueryStringFromMetadata(id,data) {
+	// Build the query string that will be sent to the server
+	var qstr      = '';
+	qstr         += 'id=' + id;
+	for ( var i = 0; i < data.length; i++ ) {
+		for ( var j = 0; j < data[i].value.length; j++ ) {
+			qstr += '&metadata.' + data[i].key + '=' + data[i].value[j];
+		}
+	}
+	
+	return qstr;
+}
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/fileTree.js b/0.8.1-rc1/curator/src/main/webapp/js/fileTree.js
new file mode 100644
index 0000000..2004638
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/fileTree.js
@@ -0,0 +1,97 @@
+/*
+  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.
+*/
+
+
+var _staging = '/';	// current root path in staging area browser
+var _catalog = '/';	// current root path in catalog browser
+var _paths   = { "staging" :  '/', 
+                 "catalog" :  '/',
+                 "currentStagedFile" : '',
+                 "currentCatalogedFile" : '',
+                 "currentProductType" : ''}
+
+if(jQuery) (function($){
+	
+	$.extend($.fn, {
+		fileTree: function(o, h, i) {
+			// Defaults
+			if( !o ) var o = {};
+			if( o.root == undefined ) o.root = '/';
+			if( o.folderEvent == undefined ) o.folderEvent = 'dblclick';
+			if( o.expandSpeed == undefined ) o.expandSpeed= 500;
+			if( o.collapseSpeed == undefined ) o.collapseSpeed= 500;
+			if( o.expandEasing == undefined ) o.expandEasing = null;
+			if( o.collapseEasing == undefined ) o.collapseEasing = null;
+			if( o.multiFolder == undefined ) o.multiFolder = true;
+			if( o.loadMessage == undefined ) o.loadMessage = 'Loading...';
+			
+			// Understand which of the two browsers to apply nav actions to
+			if (o.which == undefined) { alert('please specify \'which\' (options are: "staging"|"catalog") '); o.which = "staging";}
+			
+			// Ensure a script has been provided
+			if (o.script == undefined) { alert('please specify a target script \'script\' in fileTree options'); }
+			
+			// Get a handle to the outer UL
+			o.outerContainer = '#' + $(this).attr('id');
+			if (o.outerContainer == undefined) { alert('container must have unique id') };
+			
+			$(this).each( function() {
+				
+				function showTree(c, t) {
+					$(c).addClass('wait');
+					$(".fileTree.start").remove();
+					$.get(o.script, { path: t }, function(data) {
+						$(c).find('.start').html('');
+						$(c).removeClass('wait').html(data);
+						if (o.which == "staging")
+							_paths.staging = escape(t);
+						else
+							_paths.catalog = escape(t);
+						bindTree(c);
+						updateNav(o.which);
+						clearMetadataWorkbenchContent(o.which);
+						initDraggables();
+					});
+				}
+				
+				function bindTree(t) {
+					$(o.outerContainer).find('UL LI A').bind('click', function() {
+						if ($(this).parent().hasClass('productType')) {
+							i($(this).attr('rel'));
+						} else if ($(this).parent().hasClass('file')) {
+							h($(this).attr('rel'));
+						}
+					}).bind('dblclick', function() {
+						if ($(this).parent().hasClass('directory') ) {
+							$(this).parent().find('UL').remove(); // cleanup
+							showTree( $(o.outerContainer), escape($(this).attr('rel')) );
+						}
+					});
+					
+					// Prevent A from triggering the # on non-click events
+					if( o.folderEvent.toLowerCase != 'click' ) $(t).find('LI A').bind('click', function() { return false; });
+				}
+				
+				// Loading message
+				$(this).html('<ul class="fileTree start"><li class="wait">' + o.loadMessage + '<li></ul>');
+				
+				// Get the initial file list
+				showTree( $(this), escape((o.which == "staging" ) ? _paths.staging : _paths.catalog) );
+			});
+		}
+	});
+})(jQuery);
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/filemgr.js b/0.8.1-rc1/curator/src/main/webapp/js/filemgr.js
new file mode 100644
index 0000000..8d46078
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/filemgr.js
@@ -0,0 +1,19 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE.txt 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.    
+
+function popWin(url)
+{
+   window.open(url,'_newWin','scrollbars=yes,resizable=yes,menubar=0,status=no,width=525,height=450,top=100,left=200');
+}
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-1.3.2.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery-1.3.2.js
new file mode 100644
index 0000000..9263574
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-1.3.2.js
@@ -0,0 +1,4376 @@
+/*!
+ * jQuery JavaScript Library v1.3.2
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
+ * Revision: 6246
+ */
+(function(){
+
+var 
+	// Will speed up references to window, and allows munging its name.
+	window = this,
+	// Will speed up references to undefined, and allows munging its name.
+	undefined,
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+	// Map over the $ in case of overwrite
+	_$ = window.$,
+
+	jQuery = window.jQuery = window.$ = function( selector, context ) {
+		// The jQuery object is actually just the init constructor 'enhanced'
+		return new jQuery.fn.init( selector, context );
+	},
+
+	// A simple way to check for HTML strings or ID strings
+	// (both of which we optimize for)
+	quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
+	// Is it a simple selector
+	isSimple = /^.[^:#\[\.,]*$/;
+
+jQuery.fn = jQuery.prototype = {
+	init: function( selector, context ) {
+		// Make sure that a selection was provided
+		selector = selector || document;
+
+		// Handle $(DOMElement)
+		if ( selector.nodeType ) {
+			this[0] = selector;
+			this.length = 1;
+			this.context = selector;
+			return this;
+		}
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			// Are we dealing with HTML string or an ID?
+			var match = quickExpr.exec( selector );
+
+			// Verify a match, and that no context was specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] )
+					selector = jQuery.clean( [ match[1] ], context );
+
+				// HANDLE: $("#id")
+				else {
+					var elem = document.getElementById( match[3] );
+
+					// Handle the case where IE and Opera return items
+					// by name instead of ID
+					if ( elem && elem.id != match[3] )
+						return jQuery().find( selector );
+
+					// Otherwise, we inject the element directly into the jQuery object
+					var ret = jQuery( elem || [] );
+					ret.context = document;
+					ret.selector = selector;
+					return ret;
+				}
+
+			// HANDLE: $(expr, [context])
+			// (which is just equivalent to: $(content).find(expr)
+			} else
+				return jQuery( context ).find( selector );
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) )
+			return jQuery( document ).ready( selector );
+
+		// Make sure that old selector state is passed along
+		if ( selector.selector && selector.context ) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return this.setArray(jQuery.isArray( selector ) ?
+			selector :
+			jQuery.makeArray(selector));
+	},
+
+	// Start with an empty selector
+	selector: "",
+
+	// The current version of jQuery being used
+	jquery: "1.3.2",
+
+	// The number of elements contained in the matched element set
+	size: function() {
+		return this.length;
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num === undefined ?
+
+			// Return a 'clean' array
+			Array.prototype.slice.call( this ) :
+
+			// Return just the object
+			this[ num ];
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems, name, selector ) {
+		// Build a new jQuery matched element set
+		var ret = jQuery( elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		ret.context = this.context;
+
+		if ( name === "find" )
+			ret.selector = this.selector + (this.selector ? " " : "") + selector;
+		else if ( name )
+			ret.selector = this.selector + "." + name + "(" + selector + ")";
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Force the current matched set of elements to become
+	// the specified array of elements (destroying the stack in the process)
+	// You should use pushStack() in order to do this, but maintain the stack
+	setArray: function( elems ) {
+		// Resetting the length to 0, then using the native Array push
+		// is a super-fast way to populate an object with array-like properties
+		this.length = 0;
+		Array.prototype.push.apply( this, elems );
+
+		return this;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	// Determine the position of an element within
+	// the matched set of elements
+	index: function( elem ) {
+		// Locate the position of the desired element
+		return jQuery.inArray(
+			// If it receives a jQuery object, the first element is used
+			elem && elem.jquery ? elem[0] : elem
+		, this );
+	},
+
+	attr: function( name, value, type ) {
+		var options = name;
+
+		// Look for the case where we're accessing a style value
+		if ( typeof name === "string" )
+			if ( value === undefined )
+				return this[0] && jQuery[ type || "attr" ]( this[0], name );
+
+			else {
+				options = {};
+				options[ name ] = value;
+			}
+
+		// Check to see if we're setting style values
+		return this.each(function(i){
+			// Set all the styles
+			for ( name in options )
+				jQuery.attr(
+					type ?
+						this.style :
+						this,
+					name, jQuery.prop( this, options[ name ], type, i, name )
+				);
+		});
+	},
+
+	css: function( key, value ) {
+		// ignore negative width and height values
+		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
+			value = undefined;
+		return this.attr( key, value, "curCSS" );
+	},
+
+	text: function( text ) {
+		if ( typeof text !== "object" && text != null )
+			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+
+		var ret = "";
+
+		jQuery.each( text || this, function(){
+			jQuery.each( this.childNodes, function(){
+				if ( this.nodeType != 8 )
+					ret += this.nodeType != 1 ?
+						this.nodeValue :
+						jQuery.fn.text( [ this ] );
+			});
+		});
+
+		return ret;
+	},
+
+	wrapAll: function( html ) {
+		if ( this[0] ) {
+			// The elements to wrap the target around
+			var wrap = jQuery( html, this[0].ownerDocument ).clone();
+
+			if ( this[0].parentNode )
+				wrap.insertBefore( this[0] );
+
+			wrap.map(function(){
+				var elem = this;
+
+				while ( elem.firstChild )
+					elem = elem.firstChild;
+
+				return elem;
+			}).append(this);
+		}
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		return this.each(function(){
+			jQuery( this ).contents().wrapAll( html );
+		});
+	},
+
+	wrap: function( html ) {
+		return this.each(function(){
+			jQuery( this ).wrapAll( html );
+		});
+	},
+
+	append: function() {
+		return this.domManip(arguments, true, function(elem){
+			if (this.nodeType == 1)
+				this.appendChild( elem );
+		});
+	},
+
+	prepend: function() {
+		return this.domManip(arguments, true, function(elem){
+			if (this.nodeType == 1)
+				this.insertBefore( elem, this.firstChild );
+		});
+	},
+
+	before: function() {
+		return this.domManip(arguments, false, function(elem){
+			this.parentNode.insertBefore( elem, this );
+		});
+	},
+
+	after: function() {
+		return this.domManip(arguments, false, function(elem){
+			this.parentNode.insertBefore( elem, this.nextSibling );
+		});
+	},
+
+	end: function() {
+		return this.prevObject || jQuery( [] );
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: [].push,
+	sort: [].sort,
+	splice: [].splice,
+
+	find: function( selector ) {
+		if ( this.length === 1 ) {
+			var ret = this.pushStack( [], "find", selector );
+			ret.length = 0;
+			jQuery.find( selector, this[0], ret );
+			return ret;
+		} else {
+			return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
+				return jQuery.find( selector, elem );
+			})), "find", selector );
+		}
+	},
+
+	clone: function( events ) {
+		// Do the clone
+		var ret = this.map(function(){
+			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
+				// IE copies events bound via attachEvent when
+				// using cloneNode. Calling detachEvent on the
+				// clone will also remove the events from the orignal
+				// In order to get around this, we use innerHTML.
+				// Unfortunately, this means some modifications to
+				// attributes in IE that are actually only stored
+				// as properties will not be copied (such as the
+				// the name attribute on an input).
+				var html = this.outerHTML;
+				if ( !html ) {
+					var div = this.ownerDocument.createElement("div");
+					div.appendChild( this.cloneNode(true) );
+					html = div.innerHTML;
+				}
+
+				return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
+			} else
+				return this.cloneNode(true);
+		});
+
+		// Copy the events from the original to the clone
+		if ( events === true ) {
+			var orig = this.find("*").andSelf(), i = 0;
+
+			ret.find("*").andSelf().each(function(){
+				if ( this.nodeName !== orig[i].nodeName )
+					return;
+
+				var events = jQuery.data( orig[i], "events" );
+
+				for ( var type in events ) {
+					for ( var handler in events[ type ] ) {
+						jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
+					}
+				}
+
+				i++;
+			});
+		}
+
+		// Return the cloned set
+		return ret;
+	},
+
+	filter: function( selector ) {
+		return this.pushStack(
+			jQuery.isFunction( selector ) &&
+			jQuery.grep(this, function(elem, i){
+				return selector.call( elem, i );
+			}) ||
+
+			jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
+				return elem.nodeType === 1;
+			}) ), "filter", selector );
+	},
+
+	closest: function( selector ) {
+		var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
+			closer = 0;
+
+		return this.map(function(){
+			var cur = this;
+			while ( cur && cur.ownerDocument ) {
+				if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
+					jQuery.data(cur, "closest", closer);
+					return cur;
+				}
+				cur = cur.parentNode;
+				closer++;
+			}
+		});
+	},
+
+	not: function( selector ) {
+		if ( typeof selector === "string" )
+			// test special case where just one selector is passed in
+			if ( isSimple.test( selector ) )
+				return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
+			else
+				selector = jQuery.multiFilter( selector, this );
+
+		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+		return this.filter(function() {
+			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
+		});
+	},
+
+	add: function( selector ) {
+		return this.pushStack( jQuery.unique( jQuery.merge(
+			this.get(),
+			typeof selector === "string" ?
+				jQuery( selector ) :
+				jQuery.makeArray( selector )
+		)));
+	},
+
+	is: function( selector ) {
+		return !!selector && jQuery.multiFilter( selector, this ).length > 0;
+	},
+
+	hasClass: function( selector ) {
+		return !!selector && this.is( "." + selector );
+	},
+
+	val: function( value ) {
+		if ( value === undefined ) {			
+			var elem = this[0];
+
+			if ( elem ) {
+				if( jQuery.nodeName( elem, 'option' ) )
+					return (elem.attributes.value || {}).specified ? elem.value : elem.text;
+				
+				// We need to handle select boxes special
+				if ( jQuery.nodeName( elem, "select" ) ) {
+					var index = elem.selectedIndex,
+						values = [],
+						options = elem.options,
+						one = elem.type == "select-one";
+
+					// Nothing was selected
+					if ( index < 0 )
+						return null;
+
+					// Loop through all the selected options
+					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+						var option = options[ i ];
+
+						if ( option.selected ) {
+							// Get the specifc value for the option
+							value = jQuery(option).val();
+
+							// We don't need an array for one selects
+							if ( one )
+								return value;
+
+							// Multi-Selects return an array
+							values.push( value );
+						}
+					}
+
+					return values;				
+				}
+
+				// Everything else, we just grab the value
+				return (elem.value || "").replace(/\r/g, "");
+
+			}
+
+			return undefined;
+		}
+
+		if ( typeof value === "number" )
+			value += '';
+
+		return this.each(function(){
+			if ( this.nodeType != 1 )
+				return;
+
+			if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
+				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
+					jQuery.inArray(this.name, value) >= 0);
+
+			else if ( jQuery.nodeName( this, "select" ) ) {
+				var values = jQuery.makeArray(value);
+
+				jQuery( "option", this ).each(function(){
+					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
+						jQuery.inArray( this.text, values ) >= 0);
+				});
+
+				if ( !values.length )
+					this.selectedIndex = -1;
+
+			} else
+				this.value = value;
+		});
+	},
+
+	html: function( value ) {
+		return value === undefined ?
+			(this[0] ?
+				this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
+				null) :
+			this.empty().append( value );
+	},
+
+	replaceWith: function( value ) {
+		return this.after( value ).remove();
+	},
+
+	eq: function( i ) {
+		return this.slice( i, +i + 1 );
+	},
+
+	slice: function() {
+		return this.pushStack( Array.prototype.slice.apply( this, arguments ),
+			"slice", Array.prototype.slice.call(arguments).join(",") );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function(elem, i){
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	andSelf: function() {
+		return this.add( this.prevObject );
+	},
+
+	domManip: function( args, table, callback ) {
+		if ( this[0] ) {
+			var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
+				scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
+				first = fragment.firstChild;
+
+			if ( first )
+				for ( var i = 0, l = this.length; i < l; i++ )
+					callback.call( root(this[i], first), this.length > 1 || i > 0 ?
+							fragment.cloneNode(true) : fragment );
+		
+			if ( scripts )
+				jQuery.each( scripts, evalScript );
+		}
+
+		return this;
+		
+		function root( elem, cur ) {
+			return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
+				(elem.getElementsByTagName("tbody")[0] ||
+				elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+				elem;
+		}
+	}
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+function evalScript( i, elem ) {
+	if ( elem.src )
+		jQuery.ajax({
+			url: elem.src,
+			async: false,
+			dataType: "script"
+		});
+
+	else
+		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+
+	if ( elem.parentNode )
+		elem.parentNode.removeChild( elem );
+}
+
+function now(){
+	return +new Date;
+}
+
+jQuery.extend = jQuery.fn.extend = function() {
+	// copy reference to target object
+	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
+
+	// Handle a deep copy situation
+	if ( typeof target === "boolean" ) {
+		deep = target;
+		target = arguments[1] || {};
+		// skip the boolean and the target
+		i = 2;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target !== "object" && !jQuery.isFunction(target) )
+		target = {};
+
+	// extend jQuery itself if only one argument is passed
+	if ( length == i ) {
+		target = this;
+		--i;
+	}
+
+	for ( ; i < length; i++ )
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null )
+			// Extend the base object
+			for ( var name in options ) {
+				var src = target[ name ], copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy )
+					continue;
+
+				// Recurse if we're merging object values
+				if ( deep && copy && typeof copy === "object" && !copy.nodeType )
+					target[ name ] = jQuery.extend( deep, 
+						// Never move original objects, clone them
+						src || ( copy.length != null ? [ ] : { } )
+					, copy );
+
+				// Don't bring in undefined values
+				else if ( copy !== undefined )
+					target[ name ] = copy;
+
+			}
+
+	// Return the modified object
+	return target;
+};
+
+// exclude the following css properties to add px
+var	exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
+	// cache defaultView
+	defaultView = document.defaultView || {},
+	toString = Object.prototype.toString;
+
+jQuery.extend({
+	noConflict: function( deep ) {
+		window.$ = _$;
+
+		if ( deep )
+			window.jQuery = _jQuery;
+
+		return jQuery;
+	},
+
+	// See test/unit/core.js for details concerning isFunction.
+	// Since version 1.3, DOM methods and functions like alert
+	// aren't supported. They return false on IE (#2968).
+	isFunction: function( obj ) {
+		return toString.call(obj) === "[object Function]";
+	},
+
+	isArray: function( obj ) {
+		return toString.call(obj) === "[object Array]";
+	},
+
+	// check if an element is in a (or is an) XML document
+	isXMLDoc: function( elem ) {
+		return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+			!!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
+	},
+
+	// Evalulates a script in a global context
+	globalEval: function( data ) {
+		if ( data && /\S/.test(data) ) {
+			// Inspired by code by Andrea Giammarchi
+			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+			var head = document.getElementsByTagName("head")[0] || document.documentElement,
+				script = document.createElement("script");
+
+			script.type = "text/javascript";
+			if ( jQuery.support.scriptEval )
+				script.appendChild( document.createTextNode( data ) );
+			else
+				script.text = data;
+
+			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
+			// This arises when a base node is used (#2709).
+			head.insertBefore( script, head.firstChild );
+			head.removeChild( script );
+		}
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+	},
+
+	// args is for internal usage only
+	each: function( object, callback, args ) {
+		var name, i = 0, length = object.length;
+
+		if ( args ) {
+			if ( length === undefined ) {
+				for ( name in object )
+					if ( callback.apply( object[ name ], args ) === false )
+						break;
+			} else
+				for ( ; i < length; )
+					if ( callback.apply( object[ i++ ], args ) === false )
+						break;
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( length === undefined ) {
+				for ( name in object )
+					if ( callback.call( object[ name ], name, object[ name ] ) === false )
+						break;
+			} else
+				for ( var value = object[0];
+					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
+		}
+
+		return object;
+	},
+
+	prop: function( elem, value, type, i, name ) {
+		// Handle executable functions
+		if ( jQuery.isFunction( value ) )
+			value = value.call( elem, i );
+
+		// Handle passing in a number to a CSS property
+		return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
+			value + "px" :
+			value;
+	},
+
+	className: {
+		// internal only, use addClass("class")
+		add: function( elem, classNames ) {
+			jQuery.each((classNames || "").split(/\s+/), function(i, className){
+				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
+					elem.className += (elem.className ? " " : "") + className;
+			});
+		},
+
+		// internal only, use removeClass("class")
+		remove: function( elem, classNames ) {
+			if (elem.nodeType == 1)
+				elem.className = classNames !== undefined ?
+					jQuery.grep(elem.className.split(/\s+/), function(className){
+						return !jQuery.className.has( classNames, className );
+					}).join(" ") :
+					"";
+		},
+
+		// internal only, use hasClass("class")
+		has: function( elem, className ) {
+			return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
+		}
+	},
+
+	// A method for quickly swapping in/out CSS properties to get correct calculations
+	swap: function( elem, options, callback ) {
+		var old = {};
+		// Remember the old values, and insert the new ones
+		for ( var name in options ) {
+			old[ name ] = elem.style[ name ];
+			elem.style[ name ] = options[ name ];
+		}
+
+		callback.call( elem );
+
+		// Revert the old values
+		for ( var name in options )
+			elem.style[ name ] = old[ name ];
+	},
+
+	css: function( elem, name, force, extra ) {
+		if ( name == "width" || name == "height" ) {
+			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+
+			function getWH() {
+				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+
+				if ( extra === "border" )
+					return;
+
+				jQuery.each( which, function() {
+					if ( !extra )
+						val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+					if ( extra === "margin" )
+						val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
+					else
+						val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+				});
+			}
+
+			if ( elem.offsetWidth !== 0 )
+				getWH();
+			else
+				jQuery.swap( elem, props, getWH );
+
+			return Math.max(0, Math.round(val));
+		}
+
+		return jQuery.curCSS( elem, name, force );
+	},
+
+	curCSS: function( elem, name, force ) {
+		var ret, style = elem.style;
+
+		// We need to handle opacity special in IE
+		if ( name == "opacity" && !jQuery.support.opacity ) {
+			ret = jQuery.attr( style, "opacity" );
+
+			return ret == "" ?
+				"1" :
+				ret;
+		}
+
+		// Make sure we're using the right name for getting the float value
+		if ( name.match( /float/i ) )
+			name = styleFloat;
+
+		if ( !force && style && style[ name ] )
+			ret = style[ name ];
+
+		else if ( defaultView.getComputedStyle ) {
+
+			// Only "float" is needed here
+			if ( name.match( /float/i ) )
+				name = "float";
+
+			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
+
+			var computedStyle = defaultView.getComputedStyle( elem, null );
+
+			if ( computedStyle )
+				ret = computedStyle.getPropertyValue( name );
+
+			// We should always get a number back from opacity
+			if ( name == "opacity" && ret == "" )
+				ret = "1";
+
+		} else if ( elem.currentStyle ) {
+			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
+				return letter.toUpperCase();
+			});
+
+			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+
+			// From the awesome hack by Dean Edwards
+			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+			// If we're not dealing with a regular pixel number
+			// but a number that has a weird ending, we need to convert it to pixels
+			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
+				// Remember the original values
+				var left = style.left, rsLeft = elem.runtimeStyle.left;
+
+				// Put in the new values to get a computed value out
+				elem.runtimeStyle.left = elem.currentStyle.left;
+				style.left = ret || 0;
+				ret = style.pixelLeft + "px";
+
+				// Revert the changed values
+				style.left = left;
+				elem.runtimeStyle.left = rsLeft;
+			}
+		}
+
+		return ret;
+	},
+
+	clean: function( elems, context, fragment ) {
+		context = context || document;
+
+		// !context.createElement fails in IE with an error but returns typeof 'object'
+		if ( typeof context.createElement === "undefined" )
+			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+
+		// If a single string is passed in and it's a single tag
+		// just do a createElement and skip the rest
+		if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
+			var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
+			if ( match )
+				return [ context.createElement( match[1] ) ];
+		}
+
+		var ret = [], scripts = [], div = context.createElement("div");
+
+		jQuery.each(elems, function(i, elem){
+			if ( typeof elem === "number" )
+				elem += '';
+
+			if ( !elem )
+				return;
+
+			// Convert html string into DOM nodes
+			if ( typeof elem === "string" ) {
+				// Fix "XHTML"-style tags in all browsers
+				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
+					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
+						all :
+						front + "></" + tag + ">";
+				});
+
+				// Trim whitespace, otherwise indexOf won't work as expected
+				var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
+
+				var wrap =
+					// option or optgroup
+					!tags.indexOf("<opt") &&
+					[ 1, "<select multiple='multiple'>", "</select>" ] ||
+
+					!tags.indexOf("<leg") &&
+					[ 1, "<fieldset>", "</fieldset>" ] ||
+
+					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+					[ 1, "<table>", "</table>" ] ||
+
+					!tags.indexOf("<tr") &&
+					[ 2, "<table><tbody>", "</tbody></table>" ] ||
+
+				 	// <thead> matched above
+					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
+					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
+
+					!tags.indexOf("<col") &&
+					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
+
+					// IE can't serialize <link> and <script> tags normally
+					!jQuery.support.htmlSerialize &&
+					[ 1, "div<div>", "</div>" ] ||
+
+					[ 0, "", "" ];
+
+				// Go to html and back, then peel off extra wrappers
+				div.innerHTML = wrap[1] + elem + wrap[2];
+
+				// Move to the right depth
+				while ( wrap[0]-- )
+					div = div.lastChild;
+
+				// Remove IE's autoinserted <tbody> from table fragments
+				if ( !jQuery.support.tbody ) {
+
+					// String was a <table>, *may* have spurious <tbody>
+					var hasBody = /<tbody/i.test(elem),
+						tbody = !tags.indexOf("<table") && !hasBody ?
+							div.firstChild && div.firstChild.childNodes :
+
+						// String was a bare <thead> or <tfoot>
+						wrap[1] == "<table>" && !hasBody ?
+							div.childNodes :
+							[];
+
+					for ( var j = tbody.length - 1; j >= 0 ; --j )
+						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
+							tbody[ j ].parentNode.removeChild( tbody[ j ] );
+
+					}
+
+				// IE completely kills leading whitespace when innerHTML is used
+				if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
+					div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
+				
+				elem = jQuery.makeArray( div.childNodes );
+			}
+
+			if ( elem.nodeType )
+				ret.push( elem );
+			else
+				ret = jQuery.merge( ret, elem );
+
+		});
+
+		if ( fragment ) {
+			for ( var i = 0; ret[i]; i++ ) {
+				if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+				} else {
+					if ( ret[i].nodeType === 1 )
+						ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
+					fragment.appendChild( ret[i] );
+				}
+			}
+			
+			return scripts;
+		}
+
+		return ret;
+	},
+
+	attr: function( elem, name, value ) {
+		// don't set attributes on text and comment nodes
+		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+			return undefined;
+
+		var notxml = !jQuery.isXMLDoc( elem ),
+			// Whether we are setting (or getting)
+			set = value !== undefined;
+
+		// Try to normalize/fix the name
+		name = notxml && jQuery.props[ name ] || name;
+
+		// Only do all the following if this is a node (faster for style)
+		// IE elem.getAttribute passes even for style
+		if ( elem.tagName ) {
+
+			// These attributes require special treatment
+			var special = /href|src|style/.test( name );
+
+			// Safari mis-reports the default selected property of a hidden option
+			// Accessing the parent's selectedIndex property fixes it
+			if ( name == "selected" && elem.parentNode )
+				elem.parentNode.selectedIndex;
+
+			// If applicable, access the attribute via the DOM 0 way
+			if ( name in elem && notxml && !special ) {
+				if ( set ){
+					// We can't allow the type property to be changed (since it causes problems in IE)
+					if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
+						throw "type property can't be changed";
+
+					elem[ name ] = value;
+				}
+
+				// browsers index elements by id/name on forms, give priority to attributes.
+				if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
+					return elem.getAttributeNode( name ).nodeValue;
+
+				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+				if ( name == "tabIndex" ) {
+					var attributeNode = elem.getAttributeNode( "tabIndex" );
+					return attributeNode && attributeNode.specified
+						? attributeNode.value
+						: elem.nodeName.match(/(button|input|object|select|textarea)/i)
+							? 0
+							: elem.nodeName.match(/^(a|area)$/i) && elem.href
+								? 0
+								: undefined;
+				}
+
+				return elem[ name ];
+			}
+
+			if ( !jQuery.support.style && notxml &&  name == "style" )
+				return jQuery.attr( elem.style, "cssText", value );
+
+			if ( set )
+				// convert the value to a string (all browsers do this but IE) see #1070
+				elem.setAttribute( name, "" + value );
+
+			var attr = !jQuery.support.hrefNormalized && notxml && special
+					// Some attributes require a special call on IE
+					? elem.getAttribute( name, 2 )
+					: elem.getAttribute( name );
+
+			// Non-existent attributes return null, we normalize to undefined
+			return attr === null ? undefined : attr;
+		}
+
+		// elem is actually elem.style ... set the style
+
+		// IE uses filters for opacity
+		if ( !jQuery.support.opacity && name == "opacity" ) {
+			if ( set ) {
+				// IE has trouble with opacity if it does not have layout
+				// Force it by setting the zoom level
+				elem.zoom = 1;
+
+				// Set the alpha filter to set the opacity
+				elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
+					(parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
+			}
+
+			return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
+				(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
+				"";
+		}
+
+		name = name.replace(/-([a-z])/ig, function(all, letter){
+			return letter.toUpperCase();
+		});
+
+		if ( set )
+			elem[ name ] = value;
+
+		return elem[ name ];
+	},
+
+	trim: function( text ) {
+		return (text || "").replace( /^\s+|\s+$/g, "" );
+	},
+
+	makeArray: function( array ) {
+		var ret = [];
+
+		if( array != null ){
+			var i = array.length;
+			// The window, strings (and functions) also have 'length'
+			if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
+				ret[0] = array;
+			else
+				while( i )
+					ret[--i] = array[i];
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, array ) {
+		for ( var i = 0, length = array.length; i < length; i++ )
+		// Use === because on IE, window == document
+			if ( array[ i ] === elem )
+				return i;
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		// We have to loop this way because IE & Opera overwrite the length
+		// expando of getElementsByTagName
+		var i = 0, elem, pos = first.length;
+		// Also, we need to make sure that the correct elements are being returned
+		// (IE returns comment nodes in a '*' query)
+		if ( !jQuery.support.getAll ) {
+			while ( (elem = second[ i++ ]) != null )
+				if ( elem.nodeType != 8 )
+					first[ pos++ ] = elem;
+
+		} else
+			while ( (elem = second[ i++ ]) != null )
+				first[ pos++ ] = elem;
+
+		return first;
+	},
+
+	unique: function( array ) {
+		var ret = [], done = {};
+
+		try {
+
+			for ( var i = 0, length = array.length; i < length; i++ ) {
+				var id = jQuery.data( array[ i ] );
+
+				if ( !done[ id ] ) {
+					done[ id ] = true;
+					ret.push( array[ i ] );
+				}
+			}
+
+		} catch( e ) {
+			ret = array;
+		}
+
+		return ret;
+	},
+
+	grep: function( elems, callback, inv ) {
+		var ret = [];
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( var i = 0, length = elems.length; i < length; i++ )
+			if ( !inv != !callback( elems[ i ], i ) )
+				ret.push( elems[ i ] );
+
+		return ret;
+	},
+
+	map: function( elems, callback ) {
+		var ret = [];
+
+		// Go through the array, translating each of the items to their
+		// new value (or values).
+		for ( var i = 0, length = elems.length; i < length; i++ ) {
+			var value = callback( elems[ i ], i );
+
+			if ( value != null )
+				ret[ ret.length ] = value;
+		}
+
+		return ret.concat.apply( [], ret );
+	}
+});
+
+// Use of jQuery.browser is deprecated.
+// It's included for backwards compatibility and plugins,
+// although they should work to migrate away.
+
+var userAgent = navigator.userAgent.toLowerCase();
+
+// Figure out what browser is being used
+jQuery.browser = {
+	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
+	safari: /webkit/.test( userAgent ),
+	opera: /opera/.test( userAgent ),
+	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
+	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
+};
+
+jQuery.each({
+	parent: function(elem){return elem.parentNode;},
+	parents: function(elem){return jQuery.dir(elem,"parentNode");},
+	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
+	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
+	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
+	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
+	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
+	children: function(elem){return jQuery.sibling(elem.firstChild);},
+	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
+}, function(name, fn){
+	jQuery.fn[ name ] = function( selector ) {
+		var ret = jQuery.map( this, fn );
+
+		if ( selector && typeof selector == "string" )
+			ret = jQuery.multiFilter( selector, ret );
+
+		return this.pushStack( jQuery.unique( ret ), name, selector );
+	};
+});
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function(name, original){
+	jQuery.fn[ name ] = function( selector ) {
+		var ret = [], insert = jQuery( selector );
+
+		for ( var i = 0, l = insert.length; i < l; i++ ) {
+			var elems = (i > 0 ? this.clone(true) : this).get();
+			jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
+			ret = ret.concat( elems );
+		}
+
+		return this.pushStack( ret, name, selector );
+	};
+});
+
+jQuery.each({
+	removeAttr: function( name ) {
+		jQuery.attr( this, name, "" );
+		if (this.nodeType == 1)
+			this.removeAttribute( name );
+	},
+
+	addClass: function( classNames ) {
+		jQuery.className.add( this, classNames );
+	},
+
+	removeClass: function( classNames ) {
+		jQuery.className.remove( this, classNames );
+	},
+
+	toggleClass: function( classNames, state ) {
+		if( typeof state !== "boolean" )
+			state = !jQuery.className.has( this, classNames );
+		jQuery.className[ state ? "add" : "remove" ]( this, classNames );
+	},
+
+	remove: function( selector ) {
+		if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
+			// Prevent memory leaks
+			jQuery( "*", this ).add([this]).each(function(){
+				jQuery.event.remove(this);
+				jQuery.removeData(this);
+			});
+			if (this.parentNode)
+				this.parentNode.removeChild( this );
+		}
+	},
+
+	empty: function() {
+		// Remove element nodes and prevent memory leaks
+		jQuery(this).children().remove();
+
+		// Remove any remaining nodes
+		while ( this.firstChild )
+			this.removeChild( this.firstChild );
+	}
+}, function(name, fn){
+	jQuery.fn[ name ] = function(){
+		return this.each( fn, arguments );
+	};
+});
+
+// Helper function used by the dimensions and offset modules
+function num(elem, prop) {
+	return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
+}
+var expando = "jQuery" + now(), uuid = 0, windowData = {};

+

+jQuery.extend({

+	cache: {},

+

+	data: function( elem, name, data ) {

+		elem = elem == window ?

+			windowData :

+			elem;

+

+		var id = elem[ expando ];

+

+		// Compute a unique ID for the element

+		if ( !id )

+			id = elem[ expando ] = ++uuid;

+

+		// Only generate the data cache if we're

+		// trying to access or manipulate it

+		if ( name && !jQuery.cache[ id ] )

+			jQuery.cache[ id ] = {};

+

+		// Prevent overriding the named cache with undefined values

+		if ( data !== undefined )

+			jQuery.cache[ id ][ name ] = data;

+

+		// Return the named cache data, or the ID for the element

+		return name ?

+			jQuery.cache[ id ][ name ] :

+			id;

+	},

+

+	removeData: function( elem, name ) {

+		elem = elem == window ?

+			windowData :

+			elem;

+

+		var id = elem[ expando ];

+

+		// If we want to remove a specific section of the element's data

+		if ( name ) {

+			if ( jQuery.cache[ id ] ) {

+				// Remove the section of cache data

+				delete jQuery.cache[ id ][ name ];

+

+				// If we've removed all the data, remove the element's cache

+				name = "";

+

+				for ( name in jQuery.cache[ id ] )

+					break;

+

+				if ( !name )

+					jQuery.removeData( elem );

+			}

+

+		// Otherwise, we want to remove all of the element's data

+		} else {

+			// Clean up the element expando

+			try {

+				delete elem[ expando ];

+			} catch(e){

+				// IE has trouble directly removing the expando

+				// but it's ok with using removeAttribute

+				if ( elem.removeAttribute )

+					elem.removeAttribute( expando );

+			}

+

+			// Completely remove the data cache

+			delete jQuery.cache[ id ];

+		}

+	},

+	queue: function( elem, type, data ) {

+		if ( elem ){

+	

+			type = (type || "fx") + "queue";

+	

+			var q = jQuery.data( elem, type );

+	

+			if ( !q || jQuery.isArray(data) )

+				q = jQuery.data( elem, type, jQuery.makeArray(data) );

+			else if( data )

+				q.push( data );

+	

+		}

+		return q;

+	},

+

+	dequeue: function( elem, type ){

+		var queue = jQuery.queue( elem, type ),

+			fn = queue.shift();

+		

+		if( !type || type === "fx" )

+			fn = queue[0];

+			

+		if( fn !== undefined )

+			fn.call(elem);

+	}

+});

+

+jQuery.fn.extend({

+	data: function( key, value ){

+		var parts = key.split(".");

+		parts[1] = parts[1] ? "." + parts[1] : "";

+

+		if ( value === undefined ) {

+			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);

+

+			if ( data === undefined && this.length )

+				data = jQuery.data( this[0], key );

+

+			return data === undefined && parts[1] ?

+				this.data( parts[0] ) :

+				data;

+		} else

+			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){

+				jQuery.data( this, key, value );

+			});

+	},

+

+	removeData: function( key ){

+		return this.each(function(){

+			jQuery.removeData( this, key );

+		});

+	},

+	queue: function(type, data){

+		if ( typeof type !== "string" ) {

+			data = type;

+			type = "fx";

+		}

+

+		if ( data === undefined )

+			return jQuery.queue( this[0], type );

+

+		return this.each(function(){

+			var queue = jQuery.queue( this, type, data );

+			

+			 if( type == "fx" && queue.length == 1 )

+				queue[0].call(this);

+		});

+	},

+	dequeue: function(type){

+		return this.each(function(){

+			jQuery.dequeue( this, type );

+		});

+	}

+});/*!
+ * Sizzle CSS Selector Engine - v0.9.3
+ *  Copyright 2009, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
+	done = 0,
+	toString = Object.prototype.toString;
+
+var Sizzle = function(selector, context, results, seed) {
+	results = results || [];
+	context = context || document;
+
+	if ( context.nodeType !== 1 && context.nodeType !== 9 )
+		return [];
+	
+	if ( !selector || typeof selector !== "string" ) {
+		return results;
+	}
+
+	var parts = [], m, set, checkSet, check, mode, extra, prune = true;
+	
+	// Reset the position of the chunker regexp (start from head)
+	chunker.lastIndex = 0;
+	
+	while ( (m = chunker.exec(selector)) !== null ) {
+		parts.push( m[1] );
+		
+		if ( m[2] ) {
+			extra = RegExp.rightContext;
+			break;
+		}
+	}
+
+	if ( parts.length > 1 && origPOS.exec( selector ) ) {
+		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+			set = posProcess( parts[0] + parts[1], context );
+		} else {
+			set = Expr.relative[ parts[0] ] ?
+				[ context ] :
+				Sizzle( parts.shift(), context );
+
+			while ( parts.length ) {
+				selector = parts.shift();
+
+				if ( Expr.relative[ selector ] )
+					selector += parts.shift();
+
+				set = posProcess( selector, set );
+			}
+		}
+	} else {
+		var ret = seed ?
+			{ expr: parts.pop(), set: makeArray(seed) } :
+			Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
+		set = Sizzle.filter( ret.expr, ret.set );
+
+		if ( parts.length > 0 ) {
+			checkSet = makeArray(set);
+		} else {
+			prune = false;
+		}
+
+		while ( parts.length ) {
+			var cur = parts.pop(), pop = cur;
+
+			if ( !Expr.relative[ cur ] ) {
+				cur = "";
+			} else {
+				pop = parts.pop();
+			}
+
+			if ( pop == null ) {
+				pop = context;
+			}
+
+			Expr.relative[ cur ]( checkSet, pop, isXML(context) );
+		}
+	}
+
+	if ( !checkSet ) {
+		checkSet = set;
+	}
+
+	if ( !checkSet ) {
+		throw "Syntax error, unrecognized expression: " + (cur || selector);
+	}
+
+	if ( toString.call(checkSet) === "[object Array]" ) {
+		if ( !prune ) {
+			results.push.apply( results, checkSet );
+		} else if ( context.nodeType === 1 ) {
+			for ( var i = 0; checkSet[i] != null; i++ ) {
+				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
+					results.push( set[i] );
+				}
+			}
+		} else {
+			for ( var i = 0; checkSet[i] != null; i++ ) {
+				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+					results.push( set[i] );
+				}
+			}
+		}
+	} else {
+		makeArray( checkSet, results );
+	}
+
+	if ( extra ) {
+		Sizzle( extra, context, results, seed );
+
+		if ( sortOrder ) {
+			hasDuplicate = false;
+			results.sort(sortOrder);
+
+			if ( hasDuplicate ) {
+				for ( var i = 1; i < results.length; i++ ) {
+					if ( results[i] === results[i-1] ) {
+						results.splice(i--, 1);
+					}
+				}
+			}
+		}
+	}
+
+	return results;
+};
+
+Sizzle.matches = function(expr, set){
+	return Sizzle(expr, null, null, set);
+};
+
+Sizzle.find = function(expr, context, isXML){
+	var set, match;
+
+	if ( !expr ) {
+		return [];
+	}
+
+	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+		var type = Expr.order[i], match;
+		
+		if ( (match = Expr.match[ type ].exec( expr )) ) {
+			var left = RegExp.leftContext;
+
+			if ( left.substr( left.length - 1 ) !== "\\" ) {
+				match[1] = (match[1] || "").replace(/\\/g, "");
+				set = Expr.find[ type ]( match, context, isXML );
+				if ( set != null ) {
+					expr = expr.replace( Expr.match[ type ], "" );
+					break;
+				}
+			}
+		}
+	}
+
+	if ( !set ) {
+		set = context.getElementsByTagName("*");
+	}
+
+	return {set: set, expr: expr};
+};
+
+Sizzle.filter = function(expr, set, inplace, not){
+	var old = expr, result = [], curLoop = set, match, anyFound,
+		isXMLFilter = set && set[0] && isXML(set[0]);
+
+	while ( expr && set.length ) {
+		for ( var type in Expr.filter ) {
+			if ( (match = Expr.match[ type ].exec( expr )) != null ) {
+				var filter = Expr.filter[ type ], found, item;
+				anyFound = false;
+
+				if ( curLoop == result ) {
+					result = [];
+				}
+
+				if ( Expr.preFilter[ type ] ) {
+					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+					if ( !match ) {
+						anyFound = found = true;
+					} else if ( match === true ) {
+						continue;
+					}
+				}
+
+				if ( match ) {
+					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
+						if ( item ) {
+							found = filter( item, match, i, curLoop );
+							var pass = not ^ !!found;
+
+							if ( inplace && found != null ) {
+								if ( pass ) {
+									anyFound = true;
+								} else {
+									curLoop[i] = false;
+								}
+							} else if ( pass ) {
+								result.push( item );
+								anyFound = true;
+							}
+						}
+					}
+				}
+
+				if ( found !== undefined ) {
+					if ( !inplace ) {
+						curLoop = result;
+					}
+
+					expr = expr.replace( Expr.match[ type ], "" );
+
+					if ( !anyFound ) {
+						return [];
+					}
+
+					break;
+				}
+			}
+		}
+
+		// Improper expression
+		if ( expr == old ) {
+			if ( anyFound == null ) {
+				throw "Syntax error, unrecognized expression: " + expr;
+			} else {
+				break;
+			}
+		}
+
+		old = expr;
+	}
+
+	return curLoop;
+};
+
+var Expr = Sizzle.selectors = {
+	order: [ "ID", "NAME", "TAG" ],
+	match: {
+		ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+		CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
+		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+		TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
+		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
+		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
+		PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
+	},
+	attrMap: {
+		"class": "className",
+		"for": "htmlFor"
+	},
+	attrHandle: {
+		href: function(elem){
+			return elem.getAttribute("href");
+		}
+	},
+	relative: {
+		"+": function(checkSet, part, isXML){
+			var isPartStr = typeof part === "string",
+				isTag = isPartStr && !/\W/.test(part),
+				isPartStrNotTag = isPartStr && !isTag;
+
+			if ( isTag && !isXML ) {
+				part = part.toUpperCase();
+			}
+
+			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+				if ( (elem = checkSet[i]) ) {
+					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+					checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
+						elem || false :
+						elem === part;
+				}
+			}
+
+			if ( isPartStrNotTag ) {
+				Sizzle.filter( part, checkSet, true );
+			}
+		},
+		">": function(checkSet, part, isXML){
+			var isPartStr = typeof part === "string";
+
+			if ( isPartStr && !/\W/.test(part) ) {
+				part = isXML ? part : part.toUpperCase();
+
+				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+					var elem = checkSet[i];
+					if ( elem ) {
+						var parent = elem.parentNode;
+						checkSet[i] = parent.nodeName === part ? parent : false;
+					}
+				}
+			} else {
+				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+					var elem = checkSet[i];
+					if ( elem ) {
+						checkSet[i] = isPartStr ?
+							elem.parentNode :
+							elem.parentNode === part;
+					}
+				}
+
+				if ( isPartStr ) {
+					Sizzle.filter( part, checkSet, true );
+				}
+			}
+		},
+		"": function(checkSet, part, isXML){
+			var doneName = done++, checkFn = dirCheck;
+
+			if ( !part.match(/\W/) ) {
+				var nodeCheck = part = isXML ? part : part.toUpperCase();
+				checkFn = dirNodeCheck;
+			}
+
+			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
+		},
+		"~": function(checkSet, part, isXML){
+			var doneName = done++, checkFn = dirCheck;
+
+			if ( typeof part === "string" && !part.match(/\W/) ) {
+				var nodeCheck = part = isXML ? part : part.toUpperCase();
+				checkFn = dirNodeCheck;
+			}
+
+			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
+		}
+	},
+	find: {
+		ID: function(match, context, isXML){
+			if ( typeof context.getElementById !== "undefined" && !isXML ) {
+				var m = context.getElementById(match[1]);
+				return m ? [m] : [];
+			}
+		},
+		NAME: function(match, context, isXML){
+			if ( typeof context.getElementsByName !== "undefined" ) {
+				var ret = [], results = context.getElementsByName(match[1]);
+
+				for ( var i = 0, l = results.length; i < l; i++ ) {
+					if ( results[i].getAttribute("name") === match[1] ) {
+						ret.push( results[i] );
+					}
+				}
+
+				return ret.length === 0 ? null : ret;
+			}
+		},
+		TAG: function(match, context){
+			return context.getElementsByTagName(match[1]);
+		}
+	},
+	preFilter: {
+		CLASS: function(match, curLoop, inplace, result, not, isXML){
+			match = " " + match[1].replace(/\\/g, "") + " ";
+
+			if ( isXML ) {
+				return match;
+			}
+
+			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+				if ( elem ) {
+					if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
+						if ( !inplace )
+							result.push( elem );
+					} else if ( inplace ) {
+						curLoop[i] = false;
+					}
+				}
+			}
+
+			return false;
+		},
+		ID: function(match){
+			return match[1].replace(/\\/g, "");
+		},
+		TAG: function(match, curLoop){
+			for ( var i = 0; curLoop[i] === false; i++ ){}
+			return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
+		},
+		CHILD: function(match){
+			if ( match[1] == "nth" ) {
+				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+					match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
+					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+				// calculate the numbers (first)n+(last) including if they are negative
+				match[2] = (test[1] + (test[2] || 1)) - 0;
+				match[3] = test[3] - 0;
+			}
+
+			// TODO: Move to normal caching system
+			match[0] = done++;
+
+			return match;
+		},
+		ATTR: function(match, curLoop, inplace, result, not, isXML){
+			var name = match[1].replace(/\\/g, "");
+			
+			if ( !isXML && Expr.attrMap[name] ) {
+				match[1] = Expr.attrMap[name];
+			}
+
+			if ( match[2] === "~=" ) {
+				match[4] = " " + match[4] + " ";
+			}
+
+			return match;
+		},
+		PSEUDO: function(match, curLoop, inplace, result, not){
+			if ( match[1] === "not" ) {
+				// If we're dealing with a complex expression, or a simple one
+				if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
+					match[3] = Sizzle(match[3], null, null, curLoop);
+				} else {
+					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+					if ( !inplace ) {
+						result.push.apply( result, ret );
+					}
+					return false;
+				}
+			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+				return true;
+			}
+			
+			return match;
+		},
+		POS: function(match){
+			match.unshift( true );
+			return match;
+		}
+	},
+	filters: {
+		enabled: function(elem){
+			return elem.disabled === false && elem.type !== "hidden";
+		},
+		disabled: function(elem){
+			return elem.disabled === true;
+		},
+		checked: function(elem){
+			return elem.checked === true;
+		},
+		selected: function(elem){
+			// Accessing this property makes selected-by-default
+			// options in Safari work properly
+			elem.parentNode.selectedIndex;
+			return elem.selected === true;
+		},
+		parent: function(elem){
+			return !!elem.firstChild;
+		},
+		empty: function(elem){
+			return !elem.firstChild;
+		},
+		has: function(elem, i, match){
+			return !!Sizzle( match[3], elem ).length;
+		},
+		header: function(elem){
+			return /h\d/i.test( elem.nodeName );
+		},
+		text: function(elem){
+			return "text" === elem.type;
+		},
+		radio: function(elem){
+			return "radio" === elem.type;
+		},
+		checkbox: function(elem){
+			return "checkbox" === elem.type;
+		},
+		file: function(elem){
+			return "file" === elem.type;
+		},
+		password: function(elem){
+			return "password" === elem.type;
+		},
+		submit: function(elem){
+			return "submit" === elem.type;
+		},
+		image: function(elem){
+			return "image" === elem.type;
+		},
+		reset: function(elem){
+			return "reset" === elem.type;
+		},
+		button: function(elem){
+			return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
+		},
+		input: function(elem){
+			return /input|select|textarea|button/i.test(elem.nodeName);
+		}
+	},
+	setFilters: {
+		first: function(elem, i){
+			return i === 0;
+		},
+		last: function(elem, i, match, array){
+			return i === array.length - 1;
+		},
+		even: function(elem, i){
+			return i % 2 === 0;
+		},
+		odd: function(elem, i){
+			return i % 2 === 1;
+		},
+		lt: function(elem, i, match){
+			return i < match[3] - 0;
+		},
+		gt: function(elem, i, match){
+			return i > match[3] - 0;
+		},
+		nth: function(elem, i, match){
+			return match[3] - 0 == i;
+		},
+		eq: function(elem, i, match){
+			return match[3] - 0 == i;
+		}
+	},
+	filter: {
+		PSEUDO: function(elem, match, i, array){
+			var name = match[1], filter = Expr.filters[ name ];
+
+			if ( filter ) {
+				return filter( elem, i, match, array );
+			} else if ( name === "contains" ) {
+				return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
+			} else if ( name === "not" ) {
+				var not = match[3];
+
+				for ( var i = 0, l = not.length; i < l; i++ ) {
+					if ( not[i] === elem ) {
+						return false;
+					}
+				}
+
+				return true;
+			}
+		},
+		CHILD: function(elem, match){
+			var type = match[1], node = elem;
+			switch (type) {
+				case 'only':
+				case 'first':
+					while (node = node.previousSibling)  {
+						if ( node.nodeType === 1 ) return false;
+					}
+					if ( type == 'first') return true;
+					node = elem;
+				case 'last':
+					while (node = node.nextSibling)  {
+						if ( node.nodeType === 1 ) return false;
+					}
+					return true;
+				case 'nth':
+					var first = match[2], last = match[3];
+
+					if ( first == 1 && last == 0 ) {
+						return true;
+					}
+					
+					var doneName = match[0],
+						parent = elem.parentNode;
+	
+					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
+						var count = 0;
+						for ( node = parent.firstChild; node; node = node.nextSibling ) {
+							if ( node.nodeType === 1 ) {
+								node.nodeIndex = ++count;
+							}
+						} 
+						parent.sizcache = doneName;
+					}
+					
+					var diff = elem.nodeIndex - last;
+					if ( first == 0 ) {
+						return diff == 0;
+					} else {
+						return ( diff % first == 0 && diff / first >= 0 );
+					}
+			}
+		},
+		ID: function(elem, match){
+			return elem.nodeType === 1 && elem.getAttribute("id") === match;
+		},
+		TAG: function(elem, match){
+			return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
+		},
+		CLASS: function(elem, match){
+			return (" " + (elem.className || elem.getAttribute("class")) + " ")
+				.indexOf( match ) > -1;
+		},
+		ATTR: function(elem, match){
+			var name = match[1],
+				result = Expr.attrHandle[ name ] ?
+					Expr.attrHandle[ name ]( elem ) :
+					elem[ name ] != null ?
+						elem[ name ] :
+						elem.getAttribute( name ),
+				value = result + "",
+				type = match[2],
+				check = match[4];
+
+			return result == null ?
+				type === "!=" :
+				type === "=" ?
+				value === check :
+				type === "*=" ?
+				value.indexOf(check) >= 0 :
+				type === "~=" ?
+				(" " + value + " ").indexOf(check) >= 0 :
+				!check ?
+				value && result !== false :
+				type === "!=" ?
+				value != check :
+				type === "^=" ?
+				value.indexOf(check) === 0 :
+				type === "$=" ?
+				value.substr(value.length - check.length) === check :
+				type === "|=" ?
+				value === check || value.substr(0, check.length + 1) === check + "-" :
+				false;
+		},
+		POS: function(elem, match, i, array){
+			var name = match[2], filter = Expr.setFilters[ name ];
+
+			if ( filter ) {
+				return filter( elem, i, match, array );
+			}
+		}
+	}
+};
+
+var origPOS = Expr.match.POS;
+
+for ( var type in Expr.match ) {
+	Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
+}
+
+var makeArray = function(array, results) {
+	array = Array.prototype.slice.call( array );
+
+	if ( results ) {
+		results.push.apply( results, array );
+		return results;
+	}
+	
+	return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+try {
+	Array.prototype.slice.call( document.documentElement.childNodes );
+
+// Provide a fallback method if it does not work
+} catch(e){
+	makeArray = function(array, results) {
+		var ret = results || [];
+
+		if ( toString.call(array) === "[object Array]" ) {
+			Array.prototype.push.apply( ret, array );
+		} else {
+			if ( typeof array.length === "number" ) {
+				for ( var i = 0, l = array.length; i < l; i++ ) {
+					ret.push( array[i] );
+				}
+			} else {
+				for ( var i = 0; array[i]; i++ ) {
+					ret.push( array[i] );
+				}
+			}
+		}
+
+		return ret;
+	};
+}
+
+var sortOrder;
+
+if ( document.documentElement.compareDocumentPosition ) {
+	sortOrder = function( a, b ) {
+		var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
+		if ( ret === 0 ) {
+			hasDuplicate = true;
+		}
+		return ret;
+	};
+} else if ( "sourceIndex" in document.documentElement ) {
+	sortOrder = function( a, b ) {
+		var ret = a.sourceIndex - b.sourceIndex;
+		if ( ret === 0 ) {
+			hasDuplicate = true;
+		}
+		return ret;
+	};
+} else if ( document.createRange ) {
+	sortOrder = function( a, b ) {
+		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
+		aRange.selectNode(a);
+		aRange.collapse(true);
+		bRange.selectNode(b);
+		bRange.collapse(true);
+		var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
+		if ( ret === 0 ) {
+			hasDuplicate = true;
+		}
+		return ret;
+	};
+}
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+	// We're going to inject a fake input element with a specified name
+	var form = document.createElement("form"),
+		id = "script" + (new Date).getTime();
+	form.innerHTML = "<input name='" + id + "'/>";
+
+	// Inject it into the root element, check its status, and remove it quickly
+	var root = document.documentElement;
+	root.insertBefore( form, root.firstChild );
+
+	// The workaround has to do additional checks after a getElementById
+	// Which slows things down for other browsers (hence the branching)
+	if ( !!document.getElementById( id ) ) {
+		Expr.find.ID = function(match, context, isXML){
+			if ( typeof context.getElementById !== "undefined" && !isXML ) {
+				var m = context.getElementById(match[1]);
+				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
+			}
+		};
+
+		Expr.filter.ID = function(elem, match){
+			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+			return elem.nodeType === 1 && node && node.nodeValue === match;
+		};
+	}
+
+	root.removeChild( form );
+})();
+
+(function(){
+	// Check to see if the browser returns only elements
+	// when doing getElementsByTagName("*")
+
+	// Create a fake element
+	var div = document.createElement("div");
+	div.appendChild( document.createComment("") );
+
+	// Make sure no comments are found
+	if ( div.getElementsByTagName("*").length > 0 ) {
+		Expr.find.TAG = function(match, context){
+			var results = context.getElementsByTagName(match[1]);
+
+			// Filter out possible comments
+			if ( match[1] === "*" ) {
+				var tmp = [];
+
+				for ( var i = 0; results[i]; i++ ) {
+					if ( results[i].nodeType === 1 ) {
+						tmp.push( results[i] );
+					}
+				}
+
+				results = tmp;
+			}
+
+			return results;
+		};
+	}
+
+	// Check to see if an attribute returns normalized href attributes
+	div.innerHTML = "<a href='#'></a>";
+	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+			div.firstChild.getAttribute("href") !== "#" ) {
+		Expr.attrHandle.href = function(elem){
+			return elem.getAttribute("href", 2);
+		};
+	}
+})();
+
+if ( document.querySelectorAll ) (function(){
+	var oldSizzle = Sizzle, div = document.createElement("div");
+	div.innerHTML = "<p class='TEST'></p>";
+
+	// Safari can't handle uppercase or unicode characters when
+	// in quirks mode.
+	if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+		return;
+	}
+	
+	Sizzle = function(query, context, extra, seed){
+		context = context || document;
+
+		// Only use querySelectorAll on non-XML documents
+		// (ID selectors don't work in non-HTML documents)
+		if ( !seed && context.nodeType === 9 && !isXML(context) ) {
+			try {
+				return makeArray( context.querySelectorAll(query), extra );
+			} catch(e){}
+		}
+		
+		return oldSizzle(query, context, extra, seed);
+	};
+
+	Sizzle.find = oldSizzle.find;
+	Sizzle.filter = oldSizzle.filter;
+	Sizzle.selectors = oldSizzle.selectors;
+	Sizzle.matches = oldSizzle.matches;
+})();
+
+if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
+	var div = document.createElement("div");
+	div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+	// Opera can't find a second classname (in 9.6)
+	if ( div.getElementsByClassName("e").length === 0 )
+		return;
+
+	// Safari caches class attributes, doesn't catch changes (in 3.2)
+	div.lastChild.className = "e";
+
+	if ( div.getElementsByClassName("e").length === 1 )
+		return;
+
+	Expr.order.splice(1, 0, "CLASS");
+	Expr.find.CLASS = function(match, context, isXML) {
+		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+			return context.getElementsByClassName(match[1]);
+		}
+	};
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+	var sibDir = dir == "previousSibling" && !isXML;
+	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+		var elem = checkSet[i];
+		if ( elem ) {
+			if ( sibDir && elem.nodeType === 1 ){
+				elem.sizcache = doneName;
+				elem.sizset = i;
+			}
+			elem = elem[dir];
+			var match = false;
+
+			while ( elem ) {
+				if ( elem.sizcache === doneName ) {
+					match = checkSet[elem.sizset];
+					break;
+				}
+
+				if ( elem.nodeType === 1 && !isXML ){
+					elem.sizcache = doneName;
+					elem.sizset = i;
+				}
+
+				if ( elem.nodeName === cur ) {
+					match = elem;
+					break;
+				}
+
+				elem = elem[dir];
+			}
+
+			checkSet[i] = match;
+		}
+	}
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+	var sibDir = dir == "previousSibling" && !isXML;
+	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+		var elem = checkSet[i];
+		if ( elem ) {
+			if ( sibDir && elem.nodeType === 1 ) {
+				elem.sizcache = doneName;
+				elem.sizset = i;
+			}
+			elem = elem[dir];
+			var match = false;
+
+			while ( elem ) {
+				if ( elem.sizcache === doneName ) {
+					match = checkSet[elem.sizset];
+					break;
+				}
+
+				if ( elem.nodeType === 1 ) {
+					if ( !isXML ) {
+						elem.sizcache = doneName;
+						elem.sizset = i;
+					}
+					if ( typeof cur !== "string" ) {
+						if ( elem === cur ) {
+							match = true;
+							break;
+						}
+
+					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+						match = elem;
+						break;
+					}
+				}
+
+				elem = elem[dir];
+			}
+
+			checkSet[i] = match;
+		}
+	}
+}
+
+var contains = document.compareDocumentPosition ?  function(a, b){
+	return a.compareDocumentPosition(b) & 16;
+} : function(a, b){
+	return a !== b && (a.contains ? a.contains(b) : true);
+};
+
+var isXML = function(elem){
+	return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+		!!elem.ownerDocument && isXML( elem.ownerDocument );
+};
+
+var posProcess = function(selector, context){
+	var tmpSet = [], later = "", match,
+		root = context.nodeType ? [context] : context;
+
+	// Position selectors must be done after the filter
+	// And so must :not(positional) so we move all PSEUDOs to the end
+	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+		later += match[0];
+		selector = selector.replace( Expr.match.PSEUDO, "" );
+	}
+
+	selector = Expr.relative[selector] ? selector + "*" : selector;
+
+	for ( var i = 0, l = root.length; i < l; i++ ) {
+		Sizzle( selector, root[i], tmpSet );
+	}
+
+	return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+jQuery.find = Sizzle;
+jQuery.filter = Sizzle.filter;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+
+Sizzle.selectors.filters.hidden = function(elem){
+	return elem.offsetWidth === 0 || elem.offsetHeight === 0;
+};
+
+Sizzle.selectors.filters.visible = function(elem){
+	return elem.offsetWidth > 0 || elem.offsetHeight > 0;
+};
+
+Sizzle.selectors.filters.animated = function(elem){
+	return jQuery.grep(jQuery.timers, function(fn){
+		return elem === fn.elem;
+	}).length;
+};
+
+jQuery.multiFilter = function( expr, elems, not ) {
+	if ( not ) {
+		expr = ":not(" + expr + ")";
+	}
+
+	return Sizzle.matches(expr, elems);
+};
+
+jQuery.dir = function( elem, dir ){
+	var matched = [], cur = elem[dir];
+	while ( cur && cur != document ) {
+		if ( cur.nodeType == 1 )
+			matched.push( cur );
+		cur = cur[dir];
+	}
+	return matched;
+};
+
+jQuery.nth = function(cur, result, dir, elem){
+	result = result || 1;
+	var num = 0;
+
+	for ( ; cur; cur = cur[dir] )
+		if ( cur.nodeType == 1 && ++num == result )
+			break;
+
+	return cur;
+};
+
+jQuery.sibling = function(n, elem){
+	var r = [];
+
+	for ( ; n; n = n.nextSibling ) {
+		if ( n.nodeType == 1 && n != elem )
+			r.push( n );
+	}
+
+	return r;
+};
+
+return;
+
+window.Sizzle = Sizzle;
+
+})();
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+	// Bind an event to an element
+	// Original by Dean Edwards
+	add: function(elem, types, handler, data) {
+		if ( elem.nodeType == 3 || elem.nodeType == 8 )
+			return;
+
+		// For whatever reason, IE has trouble passing the window object
+		// around, causing it to be cloned in the process
+		if ( elem.setInterval && elem != window )
+			elem = window;
+
+		// Make sure that the function being executed has a unique ID
+		if ( !handler.guid )
+			handler.guid = this.guid++;
+
+		// if data is passed, bind to handler
+		if ( data !== undefined ) {
+			// Create temporary function pointer to original handler
+			var fn = handler;
+
+			// Create unique handler function, wrapped around original handler
+			handler = this.proxy( fn );
+
+			// Store data in unique handler
+			handler.data = data;
+		}
+
+		// Init the element's event structure
+		var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
+			handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
+				// Handle the second event of a trigger and when
+				// an event is called after a page has unloaded
+				return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
+					jQuery.event.handle.apply(arguments.callee.elem, arguments) :
+					undefined;
+			});
+		// Add elem as a property of the handle function
+		// This is to prevent a memory leak with non-native
+		// event in IE.
+		handle.elem = elem;
+
+		// Handle multiple events separated by a space
+		// jQuery(...).bind("mouseover mouseout", fn);
+		jQuery.each(types.split(/\s+/), function(index, type) {
+			// Namespaced event handlers
+			var namespaces = type.split(".");
+			type = namespaces.shift();
+			handler.type = namespaces.slice().sort().join(".");
+
+			// Get the current list of functions bound to this event
+			var handlers = events[type];
+			
+			if ( jQuery.event.specialAll[type] )
+				jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
+
+			// Init the event handler queue
+			if (!handlers) {
+				handlers = events[type] = {};
+
+				// Check for a special event handler
+				// Only use addEventListener/attachEvent if the special
+				// events handler returns false
+				if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
+					// Bind the global event handler to the element
+					if (elem.addEventListener)
+						elem.addEventListener(type, handle, false);
+					else if (elem.attachEvent)
+						elem.attachEvent("on" + type, handle);
+				}
+			}
+
+			// Add the function to the element's handler list
+			handlers[handler.guid] = handler;
+
+			// Keep track of which events have been used, for global triggering
+			jQuery.event.global[type] = true;
+		});
+
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	guid: 1,
+	global: {},
+
+	// Detach an event or set of events from an element
+	remove: function(elem, types, handler) {
+		// don't do events on text and comment nodes
+		if ( elem.nodeType == 3 || elem.nodeType == 8 )
+			return;
+
+		var events = jQuery.data(elem, "events"), ret, index;
+
+		if ( events ) {
+			// Unbind all events for the element
+			if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
+				for ( var type in events )
+					this.remove( elem, type + (types || "") );
+			else {
+				// types is actually an event object here
+				if ( types.type ) {
+					handler = types.handler;
+					types = types.type;
+				}
+
+				// Handle multiple events seperated by a space
+				// jQuery(...).unbind("mouseover mouseout", fn);
+				jQuery.each(types.split(/\s+/), function(index, type){
+					// Namespaced event handlers
+					var namespaces = type.split(".");
+					type = namespaces.shift();
+					var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+					if ( events[type] ) {
+						// remove the given handler for the given type
+						if ( handler )
+							delete events[type][handler.guid];
+
+						// remove all handlers for the given type
+						else
+							for ( var handle in events[type] )
+								// Handle the removal of namespaced events
+								if ( namespace.test(events[type][handle].type) )
+									delete events[type][handle];
+									
+						if ( jQuery.event.specialAll[type] )
+							jQuery.event.specialAll[type].teardown.call(elem, namespaces);
+
+						// remove generic event handler if no more handlers exist
+						for ( ret in events[type] ) break;
+						if ( !ret ) {
+							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
+								if (elem.removeEventListener)
+									elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+								else if (elem.detachEvent)
+									elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+							}
+							ret = null;
+							delete events[type];
+						}
+					}
+				});
+			}
+
+			// Remove the expando if it's no longer used
+			for ( ret in events ) break;
+			if ( !ret ) {
+				var handle = jQuery.data( elem, "handle" );
+				if ( handle ) handle.elem = null;
+				jQuery.removeData( elem, "events" );
+				jQuery.removeData( elem, "handle" );
+			}
+		}
+	},
+
+	// bubbling is internal
+	trigger: function( event, data, elem, bubbling ) {
+		// Event object or event type
+		var type = event.type || event;
+
+		if( !bubbling ){
+			event = typeof event === "object" ?
+				// jQuery.Event object
+				event[expando] ? event :
+				// Object literal
+				jQuery.extend( jQuery.Event(type), event ) :
+				// Just the event type (string)
+				jQuery.Event(type);
+
+			if ( type.indexOf("!") >= 0 ) {
+				event.type = type = type.slice(0, -1);
+				event.exclusive = true;
+			}
+
+			// Handle a global trigger
+			if ( !elem ) {
+				// Don't bubble custom events when global (to avoid too much overhead)
+				event.stopPropagation();
+				// Only trigger if we've ever bound an event for it
+				if ( this.global[type] )
+					jQuery.each( jQuery.cache, function(){
+						if ( this.events && this.events[type] )
+							jQuery.event.trigger( event, data, this.handle.elem );
+					});
+			}
+
+			// Handle triggering a single element
+
+			// don't do events on text and comment nodes
+			if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
+				return undefined;
+			
+			// Clean up in case it is reused
+			event.result = undefined;
+			event.target = elem;
+			
+			// Clone the incoming data, if any
+			data = jQuery.makeArray(data);
+			data.unshift( event );
+		}
+
+		event.currentTarget = elem;
+
+		// Trigger the event, it is assumed that "handle" is a function
+		var handle = jQuery.data(elem, "handle");
+		if ( handle )
+			handle.apply( elem, data );
+
+		// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
+		if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
+			event.result = false;
+
+		// Trigger the native events (except for clicks on links)
+		if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
+			this.triggered = true;
+			try {
+				elem[ type ]();
+			// prevent IE from throwing an error for some hidden elements
+			} catch (e) {}
+		}
+
+		this.triggered = false;
+
+		if ( !event.isPropagationStopped() ) {
+			var parent = elem.parentNode || elem.ownerDocument;
+			if ( parent )
+				jQuery.event.trigger(event, data, parent, true);
+		}
+	},
+
+	handle: function(event) {
+		// returned undefined or false
+		var all, handlers;
+
+		event = arguments[0] = jQuery.event.fix( event || window.event );
+		event.currentTarget = this;
+		
+		// Namespaced event handlers
+		var namespaces = event.type.split(".");
+		event.type = namespaces.shift();
+
+		// Cache this now, all = true means, any handler
+		all = !namespaces.length && !event.exclusive;
+		
+		var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+		handlers = ( jQuery.data(this, "events") || {} )[event.type];
+
+		for ( var j in handlers ) {
+			var handler = handlers[j];
+
+			// Filter the functions by class
+			if ( all || namespace.test(handler.type) ) {
+				// Pass in a reference to the handler function itself
+				// So that we can later remove it
+				event.handler = handler;
+				event.data = handler.data;
+
+				var ret = handler.apply(this, arguments);
+
+				if( ret !== undefined ){
+					event.result = ret;
+					if ( ret === false ) {
+						event.preventDefault();
+						event.stopPropagation();
+					}
+				}
+
+				if( event.isImmediatePropagationStopped() )
+					break;
+
+			}
+		}
+	},
+
+	props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+
+	fix: function(event) {
+		if ( event[expando] )
+			return event;
+
+		// store a copy of the original event object
+		// and "clone" to set read-only properties
+		var originalEvent = event;
+		event = jQuery.Event( originalEvent );
+
+		for ( var i = this.props.length, prop; i; ){
+			prop = this.props[ --i ];
+			event[ prop ] = originalEvent[ prop ];
+		}
+
+		// Fix target property, if necessary
+		if ( !event.target )
+			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+
+		// check if target is a textnode (safari)
+		if ( event.target.nodeType == 3 )
+			event.target = event.target.parentNode;
+
+		// Add relatedTarget, if necessary
+		if ( !event.relatedTarget && event.fromElement )
+			event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
+
+		// Calculate pageX/Y if missing and clientX/Y available
+		if ( event.pageX == null && event.clientX != null ) {
+			var doc = document.documentElement, body = document.body;
+			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
+			event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+		}
+
+		// Add which for key events
+		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
+			event.which = event.charCode || event.keyCode;
+
+		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+		if ( !event.metaKey && event.ctrlKey )
+			event.metaKey = event.ctrlKey;
+
+		// Add which for click: 1 == left; 2 == middle; 3 == right
+		// Note: button is not normalized, so don't use it
+		if ( !event.which && event.button )
+			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+
+		return event;
+	},
+
+	proxy: function( fn, proxy ){
+		proxy = proxy || function(){ return fn.apply(this, arguments); };
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
+		// So proxy can be declared as an argument
+		return proxy;
+	},
+
+	special: {
+		ready: {
+			// Make sure the ready event is setup
+			setup: bindReady,
+			teardown: function() {}
+		}
+	},
+	
+	specialAll: {
+		live: {
+			setup: function( selector, namespaces ){
+				jQuery.event.add( this, namespaces[0], liveHandler );
+			},
+			teardown:  function( namespaces ){
+				if ( namespaces.length ) {
+					var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
+					
+					jQuery.each( (jQuery.data(this, "events").live || {}), function(){
+						if ( name.test(this.type) )
+							remove++;
+					});
+					
+					if ( remove < 1 )
+						jQuery.event.remove( this, namespaces[0], liveHandler );
+				}
+			}
+		}
+	}
+};
+
+jQuery.Event = function( src ){
+	// Allow instantiation without the 'new' keyword
+	if( !this.preventDefault )
+		return new jQuery.Event(src);
+	
+	// Event object
+	if( src && src.type ){
+		this.originalEvent = src;
+		this.type = src.type;
+	// Event type
+	}else
+		this.type = src;
+
+	// timeStamp is buggy for some events on Firefox(#3843)
+	// So we won't rely on the native value
+	this.timeStamp = now();
+	
+	// Mark it as fixed
+	this[expando] = true;
+};
+
+function returnFalse(){
+	return false;
+}
+function returnTrue(){
+	return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+	preventDefault: function() {
+		this.isDefaultPrevented = returnTrue;
+
+		var e = this.originalEvent;
+		if( !e )
+			return;
+		// if preventDefault exists run it on the original event
+		if (e.preventDefault)
+			e.preventDefault();
+		// otherwise set the returnValue property of the original event to false (IE)
+		e.returnValue = false;
+	},
+	stopPropagation: function() {
+		this.isPropagationStopped = returnTrue;
+
+		var e = this.originalEvent;
+		if( !e )
+			return;
+		// if stopPropagation exists run it on the original event
+		if (e.stopPropagation)
+			e.stopPropagation();
+		// otherwise set the cancelBubble property of the original event to true (IE)
+		e.cancelBubble = true;
+	},
+	stopImmediatePropagation:function(){
+		this.isImmediatePropagationStopped = returnTrue;
+		this.stopPropagation();
+	},
+	isDefaultPrevented: returnFalse,
+	isPropagationStopped: returnFalse,
+	isImmediatePropagationStopped: returnFalse
+};
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function(event) {
+	// Check if mouse(over|out) are still within the same parent element
+	var parent = event.relatedTarget;
+	// Traverse up the tree
+	while ( parent && parent != this )
+		try { parent = parent.parentNode; }
+		catch(e) { parent = this; }
+	
+	if( parent != this ){
+		// set the correct event type
+		event.type = event.data;
+		// handle event if we actually just moused on to a non sub-element
+		jQuery.event.handle.apply( this, arguments );
+	}
+};
+	
+jQuery.each({ 
+	mouseover: 'mouseenter', 
+	mouseout: 'mouseleave'
+}, function( orig, fix ){
+	jQuery.event.special[ fix ] = {
+		setup: function(){
+			jQuery.event.add( this, orig, withinElement, fix );
+		},
+		teardown: function(){
+			jQuery.event.remove( this, orig, withinElement );
+		}
+	};			   
+});
+
+jQuery.fn.extend({
+	bind: function( type, data, fn ) {
+		return type == "unload" ? this.one(type, data, fn) : this.each(function(){
+			jQuery.event.add( this, type, fn || data, fn && data );
+		});
+	},
+
+	one: function( type, data, fn ) {
+		var one = jQuery.event.proxy( fn || data, function(event) {
+			jQuery(this).unbind(event, one);
+			return (fn || data).apply( this, arguments );
+		});
+		return this.each(function(){
+			jQuery.event.add( this, type, one, fn && data);
+		});
+	},
+
+	unbind: function( type, fn ) {
+		return this.each(function(){
+			jQuery.event.remove( this, type, fn );
+		});
+	},
+
+	trigger: function( type, data ) {
+		return this.each(function(){
+			jQuery.event.trigger( type, data, this );
+		});
+	},
+
+	triggerHandler: function( type, data ) {
+		if( this[0] ){
+			var event = jQuery.Event(type);
+			event.preventDefault();
+			event.stopPropagation();
+			jQuery.event.trigger( event, data, this[0] );
+			return event.result;
+		}		
+	},
+
+	toggle: function( fn ) {
+		// Save reference to arguments for access in closure
+		var args = arguments, i = 1;
+
+		// link all the functions, so any of them can unbind this click handler
+		while( i < args.length )
+			jQuery.event.proxy( fn, args[i++] );
+
+		return this.click( jQuery.event.proxy( fn, function(event) {
+			// Figure out which function to execute
+			this.lastToggle = ( this.lastToggle || 0 ) % i;
+
+			// Make sure that clicks stop
+			event.preventDefault();
+
+			// and execute the function
+			return args[ this.lastToggle++ ].apply( this, arguments ) || false;
+		}));
+	},
+
+	hover: function(fnOver, fnOut) {
+		return this.mouseenter(fnOver).mouseleave(fnOut);
+	},
+
+	ready: function(fn) {
+		// Attach the listeners
+		bindReady();
+
+		// If the DOM is already ready
+		if ( jQuery.isReady )
+			// Execute the function immediately
+			fn.call( document, jQuery );
+
+		// Otherwise, remember the function for later
+		else
+			// Add the function to the wait list
+			jQuery.readyList.push( fn );
+
+		return this;
+	},
+	
+	live: function( type, fn ){
+		var proxy = jQuery.event.proxy( fn );
+		proxy.guid += this.selector + type;
+
+		jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
+
+		return this;
+	},
+	
+	die: function( type, fn ){
+		jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
+		return this;
+	}
+});
+
+function liveHandler( event ){
+	var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
+		stop = true,
+		elems = [];
+
+	jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
+		if ( check.test(fn.type) ) {
+			var elem = jQuery(event.target).closest(fn.data)[0];
+			if ( elem )
+				elems.push({ elem: elem, fn: fn });
+		}
+	});
+
+	elems.sort(function(a,b) {
+		return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
+	});
+	
+	jQuery.each(elems, function(){
+		if ( this.fn.call(this.elem, event, this.fn.data) === false )
+			return (stop = false);
+	});
+
+	return stop;
+}
+
+function liveConvert(type, selector){
+	return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
+}
+
+jQuery.extend({
+	isReady: false,
+	readyList: [],
+	// Handle when the DOM is ready
+	ready: function() {
+		// Make sure that the DOM is not already loaded
+		if ( !jQuery.isReady ) {
+			// Remember that the DOM is ready
+			jQuery.isReady = true;
+
+			// If there are functions bound, to execute
+			if ( jQuery.readyList ) {
+				// Execute all of them
+				jQuery.each( jQuery.readyList, function(){
+					this.call( document, jQuery );
+				});
+
+				// Reset the list of functions
+				jQuery.readyList = null;
+			}
+
+			// Trigger any bound ready events
+			jQuery(document).triggerHandler("ready");
+		}
+	}
+});
+
+var readyBound = false;
+
+function bindReady(){
+	if ( readyBound ) return;
+	readyBound = true;
+
+	// Mozilla, Opera and webkit nightlies currently support this event
+	if ( document.addEventListener ) {
+		// Use the handy event callback
+		document.addEventListener( "DOMContentLoaded", function(){
+			document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
+			jQuery.ready();
+		}, false );
+
+	// If IE event model is used
+	} else if ( document.attachEvent ) {
+		// ensure firing before onload,
+		// maybe late but safe also for iframes
+		document.attachEvent("onreadystatechange", function(){
+			if ( document.readyState === "complete" ) {
+				document.detachEvent( "onreadystatechange", arguments.callee );
+				jQuery.ready();
+			}
+		});
+
+		// If IE and not an iframe
+		// continually check to see if the document is ready
+		if ( document.documentElement.doScroll && window == window.top ) (function(){
+			if ( jQuery.isReady ) return;
+
+			try {
+				// If IE is used, use the trick by Diego Perini
+				// http://javascript.nwbox.com/IEContentLoaded/
+				document.documentElement.doScroll("left");
+			} catch( error ) {
+				setTimeout( arguments.callee, 0 );
+				return;
+			}
+
+			// and execute any waiting functions
+			jQuery.ready();
+		})();
+	}
+
+	// A fallback to window.onload, that will always work
+	jQuery.event.add( window, "load", jQuery.ready );
+}
+
+jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
+	"mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
+	"change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
+
+	// Handle event binding
+	jQuery.fn[name] = function(fn){
+		return fn ? this.bind(name, fn) : this.trigger(name);
+	};
+});
+
+// Prevent memory leaks in IE
+// And prevent errors on refresh with events like mouseover in other browsers
+// Window isn't included so as not to unbind existing unload events
+jQuery( window ).bind( 'unload', function(){ 
+	for ( var id in jQuery.cache )
+		// Skip the window
+		if ( id != 1 && jQuery.cache[ id ].handle )
+			jQuery.event.remove( jQuery.cache[ id ].handle.elem );
+}); 
+(function(){
+
+	jQuery.support = {};
+
+	var root = document.documentElement,
+		script = document.createElement("script"),
+		div = document.createElement("div"),
+		id = "script" + (new Date).getTime();
+
+	div.style.display = "none";
+	div.innerHTML = '   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
+
+	var all = div.getElementsByTagName("*"),
+		a = div.getElementsByTagName("a")[0];
+
+	// Can't get basic test support
+	if ( !all || !all.length || !a ) {
+		return;
+	}
+
+	jQuery.support = {
+		// IE strips leading whitespace when .innerHTML is used
+		leadingWhitespace: div.firstChild.nodeType == 3,
+		
+		// Make sure that tbody elements aren't automatically inserted
+		// IE will insert them into empty tables
+		tbody: !div.getElementsByTagName("tbody").length,
+		
+		// Make sure that you can get all elements in an <object> element
+		// IE 7 always returns no results
+		objectAll: !!div.getElementsByTagName("object")[0]
+			.getElementsByTagName("*").length,
+		
+		// Make sure that link elements get serialized correctly by innerHTML
+		// This requires a wrapper element in IE
+		htmlSerialize: !!div.getElementsByTagName("link").length,
+		
+		// Get the style information from getAttribute
+		// (IE uses .cssText insted)
+		style: /red/.test( a.getAttribute("style") ),
+		
+		// Make sure that URLs aren't manipulated
+		// (IE normalizes it by default)
+		hrefNormalized: a.getAttribute("href") === "/a",
+		
+		// Make sure that element opacity exists
+		// (IE uses filter instead)
+		opacity: a.style.opacity === "0.5",
+		
+		// Verify style float existence
+		// (IE uses styleFloat instead of cssFloat)
+		cssFloat: !!a.style.cssFloat,
+
+		// Will be defined later
+		scriptEval: false,
+		noCloneEvent: true,
+		boxModel: null
+	};
+	
+	script.type = "text/javascript";
+	try {
+		script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
+	} catch(e){}
+
+	root.insertBefore( script, root.firstChild );
+	
+	// Make sure that the execution of code works by injecting a script
+	// tag with appendChild/createTextNode
+	// (IE doesn't support this, fails, and uses .text instead)
+	if ( window[ id ] ) {
+		jQuery.support.scriptEval = true;
+		delete window[ id ];
+	}
+
+	root.removeChild( script );
+
+	if ( div.attachEvent && div.fireEvent ) {
+		div.attachEvent("onclick", function(){
+			// Cloning a node shouldn't copy over any
+			// bound event handlers (IE does this)
+			jQuery.support.noCloneEvent = false;
+			div.detachEvent("onclick", arguments.callee);
+		});
+		div.cloneNode(true).fireEvent("onclick");
+	}
+
+	// Figure out if the W3C box model works as expected
+	// document.body must exist before we can do this
+	jQuery(function(){
+		var div = document.createElement("div");
+		div.style.width = div.style.paddingLeft = "1px";
+
+		document.body.appendChild( div );
+		jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
+		document.body.removeChild( div ).style.display = 'none';
+	});
+})();
+
+var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
+
+jQuery.props = {
+	"for": "htmlFor",
+	"class": "className",
+	"float": styleFloat,
+	cssFloat: styleFloat,
+	styleFloat: styleFloat,
+	readonly: "readOnly",
+	maxlength: "maxLength",
+	cellspacing: "cellSpacing",
+	rowspan: "rowSpan",
+	tabindex: "tabIndex"
+};
+jQuery.fn.extend({
+	// Keep a copy of the old load
+	_load: jQuery.fn.load,
+
+	load: function( url, params, callback ) {
+		if ( typeof url !== "string" )
+			return this._load( url );
+
+		var off = url.indexOf(" ");
+		if ( off >= 0 ) {
+			var selector = url.slice(off, url.length);
+			url = url.slice(0, off);
+		}
+
+		// Default to a GET request
+		var type = "GET";
+
+		// If the second parameter was provided
+		if ( params )
+			// If it's a function
+			if ( jQuery.isFunction( params ) ) {
+				// We assume that it's the callback
+				callback = params;
+				params = null;
+
+			// Otherwise, build a param string
+			} else if( typeof params === "object" ) {
+				params = jQuery.param( params );
+				type = "POST";
+			}
+
+		var self = this;
+
+		// Request the remote document
+		jQuery.ajax({
+			url: url,
+			type: type,
+			dataType: "html",
+			data: params,
+			complete: function(res, status){
+				// If successful, inject the HTML into all the matched elements
+				if ( status == "success" || status == "notmodified" )
+					// See if a selector was specified
+					self.html( selector ?
+						// Create a dummy div to hold the results
+						jQuery("<div/>")
+							// inject the contents of the document in, removing the scripts
+							// to avoid any 'Permission Denied' errors in IE
+							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+
+							// Locate the specified elements
+							.find(selector) :
+
+						// If not, just inject the full result
+						res.responseText );
+
+				if( callback )
+					self.each( callback, [res.responseText, status, res] );
+			}
+		});
+		return this;
+	},
+
+	serialize: function() {
+		return jQuery.param(this.serializeArray());
+	},
+	serializeArray: function() {
+		return this.map(function(){
+			return this.elements ? jQuery.makeArray(this.elements) : this;
+		})
+		.filter(function(){
+			return this.name && !this.disabled &&
+				(this.checked || /select|textarea/i.test(this.nodeName) ||
+					/text|hidden|password|search/i.test(this.type));
+		})
+		.map(function(i, elem){
+			var val = jQuery(this).val();
+			return val == null ? null :
+				jQuery.isArray(val) ?
+					jQuery.map( val, function(val, i){
+						return {name: elem.name, value: val};
+					}) :
+					{name: elem.name, value: val};
+		}).get();
+	}
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
+	jQuery.fn[o] = function(f){
+		return this.bind(o, f);
+	};
+});
+
+var jsc = now();
+
+jQuery.extend({
+  
+	get: function( url, data, callback, type ) {
+		// shift arguments if data argument was ommited
+		if ( jQuery.isFunction( data ) ) {
+			callback = data;
+			data = null;
+		}
+
+		return jQuery.ajax({
+			type: "GET",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get(url, null, callback, "script");
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get(url, data, callback, "json");
+	},
+
+	post: function( url, data, callback, type ) {
+		if ( jQuery.isFunction( data ) ) {
+			callback = data;
+			data = {};
+		}
+
+		return jQuery.ajax({
+			type: "POST",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	ajaxSetup: function( settings ) {
+		jQuery.extend( jQuery.ajaxSettings, settings );
+	},
+
+	ajaxSettings: {
+		url: location.href,
+		global: true,
+		type: "GET",
+		contentType: "application/x-www-form-urlencoded",
+		processData: true,
+		async: true,
+		/*
+		timeout: 0,
+		data: null,
+		username: null,
+		password: null,
+		*/
+		// Create the request object; Microsoft failed to properly
+		// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+		// This function can be overriden by calling jQuery.ajaxSetup
+		xhr:function(){
+			return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+		},
+		accepts: {
+			xml: "application/xml, text/xml",
+			html: "text/html",
+			script: "text/javascript, application/javascript",
+			json: "application/json, text/javascript",
+			text: "text/plain",
+			_default: "*/*"
+		}
+	},
+
+	// Last-Modified header cache for next request
+	lastModified: {},
+
+	ajax: function( s ) {
+		// Extend the settings, but re-extend 's' so that it can be
+		// checked again later (in the test suite, specifically)
+		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
+
+		var jsonp, jsre = /=\?(&|$)/g, status, data,
+			type = s.type.toUpperCase();
+
+		// convert data if not already a string
+		if ( s.data && s.processData && typeof s.data !== "string" )
+			s.data = jQuery.param(s.data);
+
+		// Handle JSONP Parameter Callbacks
+		if ( s.dataType == "jsonp" ) {
+			if ( type == "GET" ) {
+				if ( !s.url.match(jsre) )
+					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+			} else if ( !s.data || !s.data.match(jsre) )
+				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+			s.dataType = "json";
+		}
+
+		// Build temporary JSONP function
+		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
+			jsonp = "jsonp" + jsc++;
+
+			// Replace the =? sequence both in the query string and the data
+			if ( s.data )
+				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+			// We need to make sure
+			// that a JSONP style response is executed properly
+			s.dataType = "script";
+
+			// Handle JSONP-style loading
+			window[ jsonp ] = function(tmp){
+				data = tmp;
+				success();
+				complete();
+				// Garbage collect
+				window[ jsonp ] = undefined;
+				try{ delete window[ jsonp ]; } catch(e){}
+				if ( head )
+					head.removeChild( script );
+			};
+		}
+
+		if ( s.dataType == "script" && s.cache == null )
+			s.cache = false;
+
+		if ( s.cache === false && type == "GET" ) {
+			var ts = now();
+			// try replacing _= if it is there
+			var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+			// if nothing was replaced, add timestamp to the end
+			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
+		}
+
+		// If data is available, append data to url for get requests
+		if ( s.data && type == "GET" ) {
+			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
+
+			// IE likes to send both get and post data, prevent this
+			s.data = null;
+		}
+
+		// Watch for a new set of requests
+		if ( s.global && ! jQuery.active++ )
+			jQuery.event.trigger( "ajaxStart" );
+
+		// Matches an absolute URL, and saves the domain
+		var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
+
+		// If we're requesting a remote document
+		// and trying to load JSON or Script with a GET
+		if ( s.dataType == "script" && type == "GET" && parts
+			&& ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
+
+			var head = document.getElementsByTagName("head")[0];
+			var script = document.createElement("script");
+			script.src = s.url;
+			if (s.scriptCharset)
+				script.charset = s.scriptCharset;
+
+			// Handle Script loading
+			if ( !jsonp ) {
+				var done = false;
+
+				// Attach handlers for all browsers
+				script.onload = script.onreadystatechange = function(){
+					if ( !done && (!this.readyState ||
+							this.readyState == "loaded" || this.readyState == "complete") ) {
+						done = true;
+						success();
+						complete();
+
+						// Handle memory leak in IE
+						script.onload = script.onreadystatechange = null;
+						head.removeChild( script );
+					}
+				};
+			}
+
+			head.appendChild(script);
+
+			// We handle everything using the script element injection
+			return undefined;
+		}
+
+		var requestDone = false;
+
+		// Create the request object
+		var xhr = s.xhr();
+
+		// Open the socket
+		// Passing null username, generates a login popup on Opera (#2865)
+		if( s.username )
+			xhr.open(type, s.url, s.async, s.username, s.password);
+		else
+			xhr.open(type, s.url, s.async);
+
+		// Need an extra try/catch for cross domain requests in Firefox 3
+		try {
+			// Set the correct header, if data is being sent
+			if ( s.data )
+				xhr.setRequestHeader("Content-Type", s.contentType);
+
+			// Set the If-Modified-Since header, if ifModified mode.
+			if ( s.ifModified )
+				xhr.setRequestHeader("If-Modified-Since",
+					jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+
+			// Set header so the called script knows that it's an XMLHttpRequest
+			xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+
+			// Set the Accepts header for the server, depending on the dataType
+			xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+				s.accepts[ s.dataType ] + ", */*" :
+				s.accepts._default );
+		} catch(e){}
+
+		// Allow custom headers/mimetypes and early abort
+		if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
+			// Handle the global AJAX counter
+			if ( s.global && ! --jQuery.active )
+				jQuery.event.trigger( "ajaxStop" );
+			// close opended socket
+			xhr.abort();
+			return false;
+		}
+
+		if ( s.global )
+			jQuery.event.trigger("ajaxSend", [xhr, s]);
+
+		// Wait for a response to come back
+		var onreadystatechange = function(isTimeout){
+			// The request was aborted, clear the interval and decrement jQuery.active
+			if (xhr.readyState == 0) {
+				if (ival) {
+					// clear poll interval
+					clearInterval(ival);
+					ival = null;
+					// Handle the global AJAX counter
+					if ( s.global && ! --jQuery.active )
+						jQuery.event.trigger( "ajaxStop" );
+				}
+			// The transfer is complete and the data is available, or the request timed out
+			} else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
+				requestDone = true;
+
+				// clear poll interval
+				if (ival) {
+					clearInterval(ival);
+					ival = null;
+				}
+
+				status = isTimeout == "timeout" ? "timeout" :
+					!jQuery.httpSuccess( xhr ) ? "error" :
+					s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
+					"success";
+
+				if ( status == "success" ) {
+					// Watch for, and catch, XML document parse errors
+					try {
+						// process the data (runs the xml through httpData regardless of callback)
+						data = jQuery.httpData( xhr, s.dataType, s );
+					} catch(e) {
+						status = "parsererror";
+					}
+				}
+
+				// Make sure that the request was successful or notmodified
+				if ( status == "success" ) {
+					// Cache Last-Modified header, if ifModified mode.
+					var modRes;
+					try {
+						modRes = xhr.getResponseHeader("Last-Modified");
+					} catch(e) {} // swallow exception thrown by FF if header is not available
+
+					if ( s.ifModified && modRes )
+						jQuery.lastModified[s.url] = modRes;
+
+					// JSONP handles its own success callback
+					if ( !jsonp )
+						success();
+				} else
+					jQuery.handleError(s, xhr, status);
+
+				// Fire the complete handlers
+				complete();
+
+				if ( isTimeout )
+					xhr.abort();
+
+				// Stop memory leaks
+				if ( s.async )
+					xhr = null;
+			}
+		};
+
+		if ( s.async ) {
+			// don't attach the handler to the request, just poll it instead
+			var ival = setInterval(onreadystatechange, 13);
+
+			// Timeout checker
+			if ( s.timeout > 0 )
+				setTimeout(function(){
+					// Check to see if the request is still happening
+					if ( xhr && !requestDone )
+						onreadystatechange( "timeout" );
+				}, s.timeout);
+		}
+
+		// Send the data
+		try {
+			xhr.send(s.data);
+		} catch(e) {
+			jQuery.handleError(s, xhr, null, e);
+		}
+
+		// firefox 1.5 doesn't fire statechange for sync requests
+		if ( !s.async )
+			onreadystatechange();
+
+		function success(){
+			// If a local callback was specified, fire it and pass it the data
+			if ( s.success )
+				s.success( data, status );
+
+			// Fire the global callback
+			if ( s.global )
+				jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
+		}
+
+		function complete(){
+			// Process result
+			if ( s.complete )
+				s.complete(xhr, status);
+
+			// The request was completed
+			if ( s.global )
+				jQuery.event.trigger( "ajaxComplete", [xhr, s] );
+
+			// Handle the global AJAX counter
+			if ( s.global && ! --jQuery.active )
+				jQuery.event.trigger( "ajaxStop" );
+		}
+
+		// return XMLHttpRequest to allow aborting the request etc.
+		return xhr;
+	},
+
+	handleError: function( s, xhr, status, e ) {
+		// If a local callback was specified, fire it
+		if ( s.error ) s.error( xhr, status, e );
+
+		// Fire the global callback
+		if ( s.global )
+			jQuery.event.trigger( "ajaxError", [xhr, s, e] );
+	},
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Determines if an XMLHttpRequest was successful or not
+	httpSuccess: function( xhr ) {
+		try {
+			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+			return !xhr.status && location.protocol == "file:" ||
+				( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
+		} catch(e){}
+		return false;
+	},
+
+	// Determines if an XMLHttpRequest returns NotModified
+	httpNotModified: function( xhr, url ) {
+		try {
+			var xhrRes = xhr.getResponseHeader("Last-Modified");
+
+			// Firefox always returns 200. check Last-Modified date
+			return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
+		} catch(e){}
+		return false;
+	},
+
+	httpData: function( xhr, type, s ) {
+		var ct = xhr.getResponseHeader("content-type"),
+			xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
+			data = xml ? xhr.responseXML : xhr.responseText;
+
+		if ( xml && data.documentElement.tagName == "parsererror" )
+			throw "parsererror";
+			
+		// Allow a pre-filtering function to sanitize the response
+		// s != null is checked to keep backwards compatibility
+		if( s && s.dataFilter )
+			data = s.dataFilter( data, type );
+
+		// The filter can actually parse the response
+		if( typeof data === "string" ){
+
+			// If the type is "script", eval it in global context
+			if ( type == "script" )
+				jQuery.globalEval( data );
+
+			// Get the JavaScript object, if JSON is used.
+			if ( type == "json" )
+				data = window["eval"]("(" + data + ")");
+		}
+		
+		return data;
+	},
+
+	// Serialize an array of form elements or a set of
+	// key/values into a query string
+	param: function( a ) {
+		var s = [ ];
+
+		function add( key, value ){
+			s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
+		};
+
+		// If an array was passed in, assume that it is an array
+		// of form elements
+		if ( jQuery.isArray(a) || a.jquery )
+			// Serialize the form elements
+			jQuery.each( a, function(){
+				add( this.name, this.value );
+			});
+
+		// Otherwise, assume that it's an object of key/value pairs
+		else
+			// Serialize the key/values
+			for ( var j in a )
+				// If the value is an array then the key names need to be repeated
+				if ( jQuery.isArray(a[j]) )
+					jQuery.each( a[j], function(){
+						add( j, this );
+					});
+				else
+					add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
+
+		// Return the resulting serialization
+		return s.join("&").replace(/%20/g, "+");
+	}
+
+});
+var elemdisplay = {},
+	timerId,
+	fxAttrs = [
+		// height animations
+		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+		// width animations
+		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+		// opacity animations
+		[ "opacity" ]
+	];
+
+function genFx( type, num ){
+	var obj = {};
+	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
+		obj[ this ] = type;
+	});
+	return obj;
+}
+
+jQuery.fn.extend({
+	show: function(speed,callback){
+		if ( speed ) {
+			return this.animate( genFx("show", 3), speed, callback);
+		} else {
+			for ( var i = 0, l = this.length; i < l; i++ ){
+				var old = jQuery.data(this[i], "olddisplay");
+				
+				this[i].style.display = old || "";
+				
+				if ( jQuery.css(this[i], "display") === "none" ) {
+					var tagName = this[i].tagName, display;
+					
+					if ( elemdisplay[ tagName ] ) {
+						display = elemdisplay[ tagName ];
+					} else {
+						var elem = jQuery("<" + tagName + " />").appendTo("body");
+						
+						display = elem.css("display");
+						if ( display === "none" )
+							display = "block";
+						
+						elem.remove();
+						
+						elemdisplay[ tagName ] = display;
+					}
+					
+					jQuery.data(this[i], "olddisplay", display);
+				}
+			}
+
+			// Set the display of the elements in a second loop
+			// to avoid the constant reflow
+			for ( var i = 0, l = this.length; i < l; i++ ){
+				this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
+			}
+			
+			return this;
+		}
+	},
+
+	hide: function(speed,callback){
+		if ( speed ) {
+			return this.animate( genFx("hide", 3), speed, callback);
+		} else {
+			for ( var i = 0, l = this.length; i < l; i++ ){
+				var old = jQuery.data(this[i], "olddisplay");
+				if ( !old && old !== "none" )
+					jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
+			}
+
+			// Set the display of the elements in a second loop
+			// to avoid the constant reflow
+			for ( var i = 0, l = this.length; i < l; i++ ){
+				this[i].style.display = "none";
+			}
+
+			return this;
+		}
+	},
+
+	// Save the old toggle function
+	_toggle: jQuery.fn.toggle,
+
+	toggle: function( fn, fn2 ){
+		var bool = typeof fn === "boolean";
+
+		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
+			this._toggle.apply( this, arguments ) :
+			fn == null || bool ?
+				this.each(function(){
+					var state = bool ? fn : jQuery(this).is(":hidden");
+					jQuery(this)[ state ? "show" : "hide" ]();
+				}) :
+				this.animate(genFx("toggle", 3), fn, fn2);
+	},
+
+	fadeTo: function(speed,to,callback){
+		return this.animate({opacity: to}, speed, callback);
+	},
+
+	animate: function( prop, speed, easing, callback ) {
+		var optall = jQuery.speed(speed, easing, callback);
+
+		return this[ optall.queue === false ? "each" : "queue" ](function(){
+		
+			var opt = jQuery.extend({}, optall), p,
+				hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
+				self = this;
+	
+			for ( p in prop ) {
+				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+					return opt.complete.call(this);
+
+				if ( ( p == "height" || p == "width" ) && this.style ) {
+					// Store display property
+					opt.display = jQuery.css(this, "display");
+
+					// Make sure that nothing sneaks out
+					opt.overflow = this.style.overflow;
+				}
+			}
+
+			if ( opt.overflow != null )
+				this.style.overflow = "hidden";
+
+			opt.curAnim = jQuery.extend({}, prop);
+
+			jQuery.each( prop, function(name, val){
+				var e = new jQuery.fx( self, opt, name );
+
+				if ( /toggle|show|hide/.test(val) )
+					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+				else {
+					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+						start = e.cur(true) || 0;
+
+					if ( parts ) {
+						var end = parseFloat(parts[2]),
+							unit = parts[3] || "px";
+
+						// We need to compute starting value
+						if ( unit != "px" ) {
+							self.style[ name ] = (end || 1) + unit;
+							start = ((end || 1) / e.cur(true)) * start;
+							self.style[ name ] = start + unit;
+						}
+
+						// If a +=/-= token was provided, we're doing a relative animation
+						if ( parts[1] )
+							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+
+						e.custom( start, end, unit );
+					} else
+						e.custom( start, val, "" );
+				}
+			});
+
+			// For JS strict compliance
+			return true;
+		});
+	},
+
+	stop: function(clearQueue, gotoEnd){
+		var timers = jQuery.timers;
+
+		if (clearQueue)
+			this.queue([]);
+
+		this.each(function(){
+			// go in reverse order so anything added to the queue during the loop is ignored
+			for ( var i = timers.length - 1; i >= 0; i-- )
+				if ( timers[i].elem == this ) {
+					if (gotoEnd)
+						// force the next step to be the last
+						timers[i](true);
+					timers.splice(i, 1);
+				}
+		});
+
+		// start the next in the queue if the last step wasn't forced
+		if (!gotoEnd)
+			this.dequeue();
+
+		return this;
+	}
+
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+	slideDown: genFx("show", 1),
+	slideUp: genFx("hide", 1),
+	slideToggle: genFx("toggle", 1),
+	fadeIn: { opacity: "show" },
+	fadeOut: { opacity: "hide" }
+}, function( name, props ){
+	jQuery.fn[ name ] = function( speed, callback ){
+		return this.animate( props, speed, callback );
+	};
+});
+
+jQuery.extend({
+
+	speed: function(speed, easing, fn) {
+		var opt = typeof speed === "object" ? speed : {
+			complete: fn || !fn && easing ||
+				jQuery.isFunction( speed ) && speed,
+			duration: speed,
+			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
+		};
+
+		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+			jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
+
+		// Queueing
+		opt.old = opt.complete;
+		opt.complete = function(){
+			if ( opt.queue !== false )
+				jQuery(this).dequeue();
+			if ( jQuery.isFunction( opt.old ) )
+				opt.old.call( this );
+		};
+
+		return opt;
+	},
+
+	easing: {
+		linear: function( p, n, firstNum, diff ) {
+			return firstNum + diff * p;
+		},
+		swing: function( p, n, firstNum, diff ) {
+			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+		}
+	},
+
+	timers: [],
+
+	fx: function( elem, options, prop ){
+		this.options = options;
+		this.elem = elem;
+		this.prop = prop;
+
+		if ( !options.orig )
+			options.orig = {};
+	}
+
+});
+
+jQuery.fx.prototype = {
+
+	// Simple function for setting a style value
+	update: function(){
+		if ( this.options.step )
+			this.options.step.call( this.elem, this.now, this );
+
+		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+
+		// Set display property to block for height/width animations
+		if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
+			this.elem.style.display = "block";
+	},
+
+	// Get the current size
+	cur: function(force){
+		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
+			return this.elem[ this.prop ];
+
+		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+	},
+
+	// Start an animation from one number to another
+	custom: function(from, to, unit){
+		this.startTime = now();
+		this.start = from;
+		this.end = to;
+		this.unit = unit || this.unit || "px";
+		this.now = this.start;
+		this.pos = this.state = 0;
+
+		var self = this;
+		function t(gotoEnd){
+			return self.step(gotoEnd);
+		}
+
+		t.elem = this.elem;
+
+		if ( t() && jQuery.timers.push(t) && !timerId ) {
+			timerId = setInterval(function(){
+				var timers = jQuery.timers;
+
+				for ( var i = 0; i < timers.length; i++ )
+					if ( !timers[i]() )
+						timers.splice(i--, 1);
+
+				if ( !timers.length ) {
+					clearInterval( timerId );
+					timerId = undefined;
+				}
+			}, 13);
+		}
+	},
+
+	// Simple 'show' function
+	show: function(){
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+		this.options.show = true;
+
+		// Begin the animation
+		// Make sure that we start at a small width/height to avoid any
+		// flash of content
+		this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
+
+		// Start by showing the element
+		jQuery(this.elem).show();
+	},
+
+	// Simple 'hide' function
+	hide: function(){
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+		this.options.hide = true;
+
+		// Begin the animation
+		this.custom(this.cur(), 0);
+	},
+
+	// Each step of an animation
+	step: function(gotoEnd){
+		var t = now();
+
+		if ( gotoEnd || t >= this.options.duration + this.startTime ) {
+			this.now = this.end;
+			this.pos = this.state = 1;
+			this.update();
+
+			this.options.curAnim[ this.prop ] = true;
+
+			var done = true;
+			for ( var i in this.options.curAnim )
+				if ( this.options.curAnim[i] !== true )
+					done = false;
+
+			if ( done ) {
+				if ( this.options.display != null ) {
+					// Reset the overflow
+					this.elem.style.overflow = this.options.overflow;
+
+					// Reset the display
+					this.elem.style.display = this.options.display;
+					if ( jQuery.css(this.elem, "display") == "none" )
+						this.elem.style.display = "block";
+				}
+
+				// Hide the element if the "hide" operation was done
+				if ( this.options.hide )
+					jQuery(this.elem).hide();
+
+				// Reset the properties, if the item has been hidden or shown
+				if ( this.options.hide || this.options.show )
+					for ( var p in this.options.curAnim )
+						jQuery.attr(this.elem.style, p, this.options.orig[p]);
+					
+				// Execute the complete function
+				this.options.complete.call( this.elem );
+			}
+
+			return false;
+		} else {
+			var n = t - this.startTime;
+			this.state = n / this.options.duration;
+
+			// Perform the easing function, defaults to swing
+			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+			this.now = this.start + ((this.end - this.start) * this.pos);
+
+			// Perform the next step of the animation
+			this.update();
+		}
+
+		return true;
+	}
+
+};
+
+jQuery.extend( jQuery.fx, {
+	speeds:{
+		slow: 600,
+ 		fast: 200,
+ 		// Default speed
+ 		_default: 400
+	},
+	step: {
+
+		opacity: function(fx){
+			jQuery.attr(fx.elem.style, "opacity", fx.now);
+		},
+
+		_default: function(fx){
+			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
+				fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+			else
+				fx.elem[ fx.prop ] = fx.now;
+		}
+	}
+});
+if ( document.documentElement["getBoundingClientRect"] )
+	jQuery.fn.offset = function() {
+		if ( !this[0] ) return { top: 0, left: 0 };
+		if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+		var box  = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
+			clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
+			top  = box.top  + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
+			left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
+		return { top: top, left: left };
+	};
+else 
+	jQuery.fn.offset = function() {
+		if ( !this[0] ) return { top: 0, left: 0 };
+		if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+		jQuery.offset.initialized || jQuery.offset.initialize();
+
+		var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
+			doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
+			body = doc.body, defaultView = doc.defaultView,
+			prevComputedStyle = defaultView.getComputedStyle(elem, null),
+			top = elem.offsetTop, left = elem.offsetLeft;
+
+		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+			computedStyle = defaultView.getComputedStyle(elem, null);
+			top -= elem.scrollTop, left -= elem.scrollLeft;
+			if ( elem === offsetParent ) {
+				top += elem.offsetTop, left += elem.offsetLeft;
+				if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
+					top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
+					left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+				prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
+			}
+			if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
+				top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
+				left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+			prevComputedStyle = computedStyle;
+		}
+
+		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
+			top  += body.offsetTop,
+			left += body.offsetLeft;
+
+		if ( prevComputedStyle.position === "fixed" )
+			top  += Math.max(docElem.scrollTop, body.scrollTop),
+			left += Math.max(docElem.scrollLeft, body.scrollLeft);
+
+		return { top: top, left: left };
+	};
+
+jQuery.offset = {
+	initialize: function() {
+		if ( this.initialized ) return;
+		var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
+			html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
+
+		rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
+		for ( prop in rules ) container.style[prop] = rules[prop];
+
+		container.innerHTML = html;
+		body.insertBefore(container, body.firstChild);
+		innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
+
+		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
+		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+
+		innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
+		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+
+		body.style.marginTop = '1px';
+		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
+		body.style.marginTop = bodyMarginTop;
+
+		body.removeChild(container);
+		this.initialized = true;
+	},
+
+	bodyOffset: function(body) {
+		jQuery.offset.initialized || jQuery.offset.initialize();
+		var top = body.offsetTop, left = body.offsetLeft;
+		if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
+			top  += parseInt( jQuery.curCSS(body, 'marginTop',  true), 10 ) || 0,
+			left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
+		return { top: top, left: left };
+	}
+};
+
+
+jQuery.fn.extend({
+	position: function() {
+		var left = 0, top = 0, results;
+
+		if ( this[0] ) {
+			// Get *real* offsetParent
+			var offsetParent = this.offsetParent(),
+
+			// Get correct offsets
+			offset       = this.offset(),
+			parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+			// Subtract element margins
+			// note: when an element has margin: auto the offsetLeft and marginLeft 
+			// are the same in Safari causing offset.left to incorrectly be 0
+			offset.top  -= num( this, 'marginTop'  );
+			offset.left -= num( this, 'marginLeft' );
+
+			// Add offsetParent borders
+			parentOffset.top  += num( offsetParent, 'borderTopWidth'  );
+			parentOffset.left += num( offsetParent, 'borderLeftWidth' );
+
+			// Subtract the two offsets
+			results = {
+				top:  offset.top  - parentOffset.top,
+				left: offset.left - parentOffset.left
+			};
+		}
+
+		return results;
+	},
+
+	offsetParent: function() {
+		var offsetParent = this[0].offsetParent || document.body;
+		while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
+			offsetParent = offsetParent.offsetParent;
+		return jQuery(offsetParent);
+	}
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ['Left', 'Top'], function(i, name) {
+	var method = 'scroll' + name;
+	
+	jQuery.fn[ method ] = function(val) {
+		if (!this[0]) return null;
+
+		return val !== undefined ?
+
+			// Set the scroll offset
+			this.each(function() {
+				this == window || this == document ?
+					window.scrollTo(
+						!i ? val : jQuery(window).scrollLeft(),
+						 i ? val : jQuery(window).scrollTop()
+					) :
+					this[ method ] = val;
+			}) :
+
+			// Return the scroll offset
+			this[0] == window || this[0] == document ?
+				self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
+					jQuery.boxModel && document.documentElement[ method ] ||
+					document.body[ method ] :
+				this[0][ method ];
+	};
+});
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function(i, name){
+
+	var tl = i ? "Left"  : "Top",  // top or left
+		br = i ? "Right" : "Bottom", // bottom or right
+		lower = name.toLowerCase();
+
+	// innerHeight and innerWidth
+	jQuery.fn["inner" + name] = function(){
+		return this[0] ?
+			jQuery.css( this[0], lower, false, "padding" ) :
+			null;
+	};
+
+	// outerHeight and outerWidth
+	jQuery.fn["outer" + name] = function(margin) {
+		return this[0] ?
+			jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
+			null;
+	};
+	
+	var type = name.toLowerCase();
+
+	jQuery.fn[ type ] = function( size ) {
+		// Get window width or height
+		return this[0] == window ?
+			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
+			document.body[ "client" + name ] :
+
+			// Get document width or height
+			this[0] == document ?
+				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+				Math.max(
+					document.documentElement["client" + name],
+					document.body["scroll" + name], document.documentElement["scroll" + name],
+					document.body["offset" + name], document.documentElement["offset" + name]
+				) :
+
+				// Get or set width or height on the element
+				size === undefined ?
+					// Get width or height on the element
+					(this.length ? jQuery.css( this[0], type ) : null) :
+
+					// Set the width or height on the element (default to pixels if value is unitless)
+					this.css( type, typeof size === "string" ? size : size + "px" );
+	};
+
+});
+})();
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/changelog.txt b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/changelog.txt
new file mode 100644
index 0000000..44a94e8
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/changelog.txt
@@ -0,0 +1,29 @@
+1.4
+---
+
+* Added changelog (this file)
+* Fixed tree control to search only for anchors, allowing images or other elements inside the controls, while keeping the control usable with the keyboard
+* Restructured folder layout: root contains plugin resources, lib contains script dependencies, demo contains demos and related files
+* Added prerendered option: If set to true, assumes all hitarea divs and classes already rendered, speeding up initialization for big trees, but more obtrusive
+* Added jquery.treeview.async.js for ajax-lazy-loading trees, see async.html demo
+* Exposed $.fn.treeview.classes for custom classes if necessary
+* Show treecontrol only when JavaScript is enabled
+* Completely reworked themeing via CSS sprites, resulting in only two files per theme
+  * updated dotted, black, gray and red theme
+  * added famfamfam theme (no lines)
+* Improved cookie persistence to allow multiple persisted trees per page via cookieId option
+* Improved location persistence by making it case-insensitive
+* Improved swapClass and replaceClass plugin implementations
+* Added folder-closed.gif to filetree example
+
+1.3
+---
+
+* Fixes for all outstanding bugs
+* Added persistence features
+      * location based: click on a link in the treeview and reopen that link after the page loaded
+      * cookie based: save the state of the tree in a cookie on each click and load that on reload
+* smoothed animations, fixing flickering in both IE and Opera
+* Tested in Firefox 2, IE 6 & 7, Opera 9, Safari 3
+* Moved documentation to jQuery wiki
+* Requires jQuery 1.2+
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/async.html b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/async.html
new file mode 100644
index 0000000..399a241
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/async.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+<html xmlns="http://www.w3.org/1999/xhtml">

+<head>

+

+	<meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/>

+	<title>jQuery async treeview</title>

+	

+	<link rel="stylesheet" href="../jquery.treeview.css" />
+    <link rel="stylesheet" href="../red-treeview.css" />
+	<link rel="stylesheet" href="screen.css" />
+	
+	<script src="../lib/jquery.js" type="text/javascript"></script>
+	<script src="../lib/jquery.cookie.js" type="text/javascript"></script>
+	<script src="../jquery.treeview.js" type="text/javascript"></script>

+	<script src="../jquery.treeview.async.js" type="text/javascript"></script>
+	

+	<script type="text/javascript">

+	$(document).ready(function(){

+		$("#black").treeview({

+			url: "source.php"

+		})

+	});

+	</script>

+	

+	</head>

+	<body>

+	

+	<h1 id="banner"><a href="http://bassistance.de/jquery-plugins/jquery-plugin-treeview/">jQuery Treeview Plugin</a> Demo</h1>

+	<div id="main">
+	
+	<ul>
+		<li><a href=".">Main Demo</a></li>
+		<li><a href="source.phps">Server component used</a></li>
+	</ul>

+		

+	<h4>Lazy-loading tree</h4>

+	

+	<ul id="black">

+	</ul>

+	

+		

+</div>

+ 

+</body></html>
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/bg.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/bg.gif
new file mode 100644
index 0000000..d7d6fc2
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/bg.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/demo.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/demo.js
new file mode 100644
index 0000000..70dc04e
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/demo.js
@@ -0,0 +1,43 @@
+$(document).ready(function(){
+		
+	// first example
+	$("#navigation").treeview({
+		persist: "location",
+		collapsed: true,
+		unique: true
+	});
+	
+	// second example
+	$("#browser").treeview();
+	$("#add").click(function() {
+		var branches = $("<li><span class='folder'>New Sublist</span><ul>" + 
+			"<li><span class='file'>Item1</span></li>" + 
+			"<li><span class='file'>Item2</span></li></ul></li>").appendTo("#browser");
+		$("#browser").treeview({
+			add: branches
+		});
+		branches = $("<li class='closed'><span class='folder'>New Sublist</span><ul><li><span class='file'>Item1</span></li><li><span class='file'>Item2</span></li></ul></li>").prependTo("#folder21");
+		$("#browser").treeview({
+			add: branches
+		});
+	});
+	
+	// third example
+	$("#red").treeview({
+		animated: "fast",
+		collapsed: true,
+		unique: true,
+		persist: "cookie",
+		toggle: function() {
+			window.console && console.log("%o was toggled", this);
+		}
+	});
+	
+	// fourth example
+	$("#black, #gray").treeview({
+		control: "#treecontrol",
+		persist: "cookie",
+		cookieId: "treeview-black"
+	});
+
+});
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/images.html b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/images.html
new file mode 100644
index 0000000..c0627a4
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/images.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+<html xmlns="http://www.w3.org/1999/xhtml">

+<head>

+

+	<meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/>

+	<title>jQuery treeView</title>

+	

+	<link rel="stylesheet" href="../jquery.treeview.css" />

+    <link rel="stylesheet" href="../red-treeview.css" />

+	<link rel="stylesheet" href="screen.css" />
+	

+	<script src="../lib/jquery.js" type="text/javascript"></script>

+	<script src="../lib/jquery.cookie.js" type="text/javascript"></script>

+	<script src="../jquery.treeview.js" type="text/javascript"></script>
+	

+	<script type="text/javascript">

+		$(function() {

+			$("#browser").treeview();

+		});

+	</script>

+	

+	</head>

+	<body>

+	

+	<h1 id="banner"><a href="http://bassistance.de/jquery-plugins/jquery-plugin-treeview/">jQuery Treeview Plugin</a> Demo</h1>

+	<div id="main">

+

+	<h4>Sample 1 - default</h4>

+	<ul id="browser" class="filetree">

+		<li><img src="../images/folder.gif" /> 123</span>

+			<ul>

+				<li>blabla <img src="../images/file.gif" /></li>

+			</ul>

+		</li>

+		<li><img src="../images/folder.gif" />

+			<ul>

+				<li><img src="../images/folder.gif" />

+					<ul id="folder21">

+						<li><img src="../images/file.gif" /> more text</li>

+						<li>and here, too<img src="../images/file.gif" /></li>

+					</ul>

+				</li>

+				<li><img src="../images/file.gif" /></li>

+			</ul>

+		</li>

+		<li class="closed">this is closed! <img src="../images/folder.gif" />

+			<ul>

+				<li><img src="../images/file.gif" /></li>

+			</ul>

+		</li>

+		<li><img src="../images/file.gif" /></li>

+	</ul>

+		

+</div>

+ 

+</body></html>
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/index.html b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/index.html
new file mode 100644
index 0000000..ea6a804
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/index.html
@@ -0,0 +1,340 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+<html xmlns="http://www.w3.org/1999/xhtml">

+<head>

+

+	<meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/>

+	<title>jQuery treeView</title>

+	

+	<link rel="stylesheet" href="../jquery.treeview.css" />

+	<link rel="stylesheet" href="screen.css" />
+	

+	<script src="../lib/jquery.js" type="text/javascript"></script>

+	<script src="../lib/jquery.cookie.js" type="text/javascript"></script>

+	<script src="../jquery.treeview.js" type="text/javascript"></script>
+	

+	<script type="text/javascript" src="demo.js"></script>

+	

+	</head>

+	<body>

+	

+	<h1 id="banner"><a href="http://bassistance.de/jquery-plugins/jquery-plugin-treeview/">jQuery Treeview Plugin</a> Demo</h1>

+	<div id="main">

+	

+	<a href="demo.js">Pagecode</a>
+	
+	<h3>Other demos</h3>
+	<ul>
+		<li><a href="large.html">Large Tree Demo</a></li>
+		<li><a href="prerendered.html">Prerendered Large Tree Demo</a></li>
+		<li><a href="async.html">Async Tree Demo</a></li>
+		<li><a href="simple.html">Simple Tree Demo, famfamfam theme (no lines)</a></li>
+	</ul>

+		

+	<h4>Sample 0 - navigation</h4>

+	

+	<ul id="navigation">

+		<li><a href="?1">Item 1</a>

+			<ul>

+				<li><a href="?1.0">Item 1.0</a>

+					<ul>

+						<li><a href="?1.0.0">Item 1.0.0</a></li>

+					</ul>

+				</li>

+				<li><a href="?1.1">Item 1.1</a></li>

+				<li><a href="?1.2">Item 1.2</a>

+					<ul>

+						<li><a href="?1.2.0">Item 1.2.0</a>

+						<ul>

+							<li><a href="?1.2.0.0">Item 1.2.0.0</a></li>

+							<li><a href="?1.2.0.1">Item 1.2.0.1</a></li>

+							<li><a href="?1.2.0.2">Item 1.2.0.2</a></li>

+						</ul>

+					</li>

+						<li><a href="?1.2.1">Item 1.2.1</a>

+						<ul>

+							<li><a href="?1.2.1.0">Item 1.2.1.0</a></li>

+						</ul>

+					</li>

+						<li><a href="?1.2.2">Item 1.2.2</a>

+						<ul>

+							<li><a href="?1.2.2.0">Item 1.2.2.0</a></li>

+							<li><a href="?1.2.2.1">Item 1.2.2.1</a></li>

+							<li><a href="?1.2.2.2">Item 1.2.2.2</a></li>

+						</ul>

+					</li>

+					</ul>

+				</li>

+			</ul>

+		</li>

+		<li><a href="?2">Item 2</a>

+			<ul>

+				<li><span>Item 2.0</span>

+					<ul>

+						<li><a href="?2.0.0">Item 2.0.0</a>

+						<ul>

+							<li><a href="?2.0.0.0">Item 2.0.0.0</a></li>

+							<li><a href="?2.0.0.1">Item 2.0.0.1</a></li>

+						</ul>

+					</li>

+					</ul>

+				</li>

+				<li><a href="?2.1">Item 2.1</a>

+					<ul>

+						<li><a href="?2.1.0">Item 2.1.0</a>

+						<ul>

+							<li><a href="?2.1.0.0">Item 2.1.0.0</a></li>

+						</ul>

+					</li>

+						<li><a href="?2.1.1">Item 2.1.1</a>

+						<ul>

+							<li><a href="?2.1.1.0abc">Item 2.1.1.0</a></li>

+							<li><a href="?2.1.1.1">Item 2.1.1.1</a></li>

+							<li><a href="?2.1.1.2">Item 2.1.1.2</a></li>

+						</ul>

+					</li>

+						<li><a href="?2.1.2">Item 2.1.2</a>

+						<ul>

+							<li><a href="?2.1.2.0">Item 2.1.2.0</a></li>

+							<li><a href="?2.1.2.1">Item 2.1.2.1</a></li>

+							<li><a href="?2.1.2.2">Item 2.1.2.2</a></li>

+						</ul>

+					</li>

+					</ul>

+				</li>

+			</ul>

+		</li>

+		<li><a href="?3">Item 3</a>

+			<ul>

+				<li class="open"><a href="?3.0">Item 3.0</a>

+					<ul>

+						<li><a href="?3.0.0">Item 3.0.0</a></li>

+						<li><a href="?3.0.1">Item 3.0.1</a>

+							<ul>

+								<li><a href="?3.0.1.0">Item 3.0.1.0</a></li>

+								<li><a href="?3.0.1.1">Item 3.0.1.1</a></li>

+							</ul>

+						</li>

+						<li><a href="?3.0.2">Item 3.0.2</a>

+							<ul>

+								<li><a href="?3.0.2.0">Item 3.0.2.0</a></li>

+								<li><a href="?3.0.2.1">Item 3.0.2.1</a></li>

+								<li><a href="?3.0.2.2">Item 3.0.2.2</a></li>

+							</ul>

+						</li>

+					</ul>

+				</li>

+			</ul>

+		</li>

+	</ul>

+	

+	

+	<h4>Sample 1 - default</h4>

+	<ul id="browser" class="filetree">

+		<li><span class="folder">Folder 1</span>

+			<ul>

+				<li><span class="file">Item 1.1</span></li>

+			</ul>

+		</li>

+		<li><span class="folder">Folder 2</span>

+			<ul>

+				<li><span class="folder">Subfolder 2.1</span>

+					<ul id="folder21">

+						<li><span class="file">File 2.1.1</span></li>

+						<li><span class="file">File 2.1.2</span></li>

+					</ul>

+				</li>

+				<li><span class="file">File 2.2</span></li>

+			</ul>

+		</li>

+		<li class="closed"><span class="folder">Folder 3 (closed at start)</span>

+			<ul>

+				<li><span class="file">File 3.1</span></li>

+			</ul>

+		</li>

+		<li><span class="file">File 4</span></li>

+	</ul>

+	

+	<button id="add">Add!</button>

+	

+	<h4>Sample 2 - fast animations, all branches collapsed at first, red theme, cookie-based persistance</h4>

+	<ul id="red" class="treeview-red">

+	<li><span>Item 1</span>

+		<ul>

+			<li><span>Item 1.0</span>

+				<ul>

+					<li><span>Item 1.0.0</span></li>

+				</ul>

+			</li>

+			<li><span>Item 1.1</span></li>

+			<li><span>Item 1.2</span>

+				<ul>

+					<li><span>Item 1.2.0</span>

+					<ul>

+						<li><span>Item 1.2.0.0</span></li>

+						<li><span>Item 1.2.0.1</span></li>

+						<li><span>Item 1.2.0.2</span></li>

+					</ul>

+				</li>

+					<li><span>Item 1.2.1</span>

+					<ul>

+						<li><span>Item 1.2.1.0</span></li>

+					</ul>

+				</li>

+					<li><span>Item 1.2.2</span>

+					<ul>

+						<li><span>Item 1.2.2.0</span></li>

+						<li><span>Item 1.2.2.1</span></li>

+						<li><span>Item 1.2.2.2</span></li>

+					</ul>

+				</li>

+				</ul>

+			</li>

+		</ul>

+	</li>

+	<li><span>Item 2</span>

+		<ul>

+			<li><span>Item 2.0</span>

+				<ul>

+					<li><span>Item 2.0.0</span>

+					<ul>

+						<li><span>Item 2.0.0.0</span></li>

+						<li><span>Item 2.0.0.1</span></li>

+					</ul>

+				</li>

+				</ul>

+			</li>

+			<li><span>Item 2.1</span>

+				<ul>

+					<li><span>Item 2.1.0</span>

+					<ul>

+						<li><span>Item 2.1.0.0</span></li>

+					</ul>

+				</li>

+					<li><span>Item 2.1.1</span>

+					<ul>

+						<li><span>Item 2.1.1.0</span></li>

+						<li><span>Item 2.1.1.1</span></li>

+						<li><span>Item 2.1.1.2</span></li>

+					</ul>

+				</li>

+					<li><span>Item 2.1.2</span>

+					<ul>

+						<li><span>Item 2.1.2.0</span></li>

+						<li><span>Item 2.1.2.1</span></li>

+						<li><span>Item 2.1.2.2</span></li>

+					</ul>

+				</li>

+				</ul>

+			</li>

+		</ul>

+	</li>

+	<li class="open"><span>Item 3</span>

+		<ul>

+			<li class="open"><span>Item 3.0</span>

+				<ul>

+					<li><span>Item 3.0.0</span></li>

+					<li><span>Item 3.0.1</span>

+					<ul>

+						<li><span>Item 3.0.1.0</span></li>

+						<li><span>Item 3.0.1.1</span></li>

+					</ul>

+					

+				</li>

+					<li><span>Item 3.0.2</span>

+					<ul>

+						<li><span>Item 3.0.2.0</span></li>

+						<li><span>Item 3.0.2.1</span></li>

+						<li><span>Item 3.0.2.2</span></li>

+					</ul>

+				</li>

+				</ul>

+			</li>

+		</ul>

+	</li>

+	</ul>

+	

+	<h4>Sample 3 - two trees with one tree control, black and gray theme, cookie-based persistance</h4>

+	<div id="treecontrol">

+		<a title="Collapse the entire tree below" href="#"><img src="../images/minus.gif" /> Collapse All</a>

+		<a title="Expand the entire tree below" href="#"><img src="../images/plus.gif" /> Expand All</a>

+		<a title="Toggle the tree below, opening closed branches, closing open branches" href="#">Toggle All</a>

+	</div>

+	<ul id="black" class="treeview-black">

+		<li>Item 1</li>

+		<li>

+			<span>Item 2</span>

+			<ul>

+				<li>

+					<span>Item 2.1</span>

+					<ul>

+						<li>Item 2.1.1</li>

+						<li>Item 2.1.2</li>

+					</ul>

+				</li>

+				<li>Item 2.2</li>

+				<li class="closed">

+					<span>Item 2.3 (closed at start)</span>

+					<ul>

+						<li>Item 2.3.1</li>

+						<li>Item 2.3.2</li>

+					</ul>

+				</li>

+			</ul>

+		</li>

+	</ul>

+	<ul id="gray" class="treeview-gray">

+		<li>Item 1</li>

+		<li>

+			<span>Item 2</span>

+			<ul>

+				<li class="closed">

+					<span>Item 2.1 (closed at start)</span>

+					<ul>

+						<li>Item 2.1.1</li>

+						<li>Item 2.1.2</li>

+					</ul>

+				</li>

+				<li>Item 2.2.1</li>

+				<li>Item 2.2.2</li>

+				<li>Item 2.2.3</li>

+				<li>Item 2.2.4</li>

+				<li>Item 2.2.5</li>

+				<li>Item 2.2.6</li>

+				<li>Item 2.2.7</li>

+				<li>Item 2.2.8</li>

+				<li>

+					<span>Item 2.3</span>

+					<ul>

+						<li>Item 2.3.1</li>

+						<li>Item 2.3.2</li>

+						<li>Item 2.3.3</li>

+						<li>Item 2.3.4</li>

+						<li>Item 2.3.5</li>

+						<li>Item 2.3.6</li>

+						<li>Item 2.3.7</li>

+						<li>Item 2.3.8</li>

+						<li>Item 2.3.9</li>

+					</ul>

+				</li>

+				<li>

+					<span>Item 2.4</span>

+					<ul>

+						<li>Item 2.4.1</li>

+						<li>Item 2.4.2</li>

+						<li>Item 2.4.3</li>

+						<li>Item 2.4.4</li>

+						<li>Item 2.4.5</li>

+						<li>Item 2.4.6</li>

+						<li>Item 2.4.7</li>

+						<li>Item 2.4.8</li>

+						<li>Item 2.4.9</li>

+					</ul>

+				</li>

+			</ul>

+		</li>

+		<li>Item 3</li>

+	</ul>	

+	

+</div>

+ 

+</body></html>
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/large.html b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/large.html
new file mode 100644
index 0000000..86b48ec
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/large.html
@@ -0,0 +1,559 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+
+<link rel="stylesheet" href="../jquery.treeview.css" />
+<link rel="stylesheet" href="../red-treeview.css" />
+<link rel="stylesheet" href="screen.css" />
+
+<script src="../lib/jquery.js" type="text/javascript"></script>
+<script src="../lib/jquery.cookie.js" type="text/javascript"></script>
+<script src="../jquery.treeview.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+		$(function() {
+			$("#tree").treeview({
+				collapsed: true,
+				animated: "medium",
+				control:"#sidetreecontrol",
+				persist: "location"
+			});
+		})
+		
+	</script>
+
+</head>
+<body>
+
+<h1 id="banner"><a href="http://bassistance.de/jquery-plugins/jquery-plugin-treeview/">jQuery Treeview Plugin</a> Demo</h1>
+<div id="main"><a href=".">Main Demo</a>
+
+<div id="sidetree">
+<div class="treeheader">&nbsp;</div>
+<div id="sidetreecontrol"><a href="?#">Collapse All</a> | <a href="?#">Expand All</a></div>
+
+<ul id="tree">
+	<li><a href="?/index.cfm"><strong>Home</strong></a>
+	<ul>
+		<li><a href="?/enewsletters/index.cfm">Airdrie eNewsletters </a></li>
+		<li><a href="?/index.cfm">Airdrie Directories</a></li>
+		<li><a href="?/economic_development/video/index.cfm">Airdrie Life Video</a></li>
+
+		<li><a href="?/index.cfm">Airdrie News</a></li>
+		<li><a href="?/index.cfm">Airdrie Quick Links</a></li>
+		<li><a href="?http://weather.ibegin.com/ca/ab/airdrie/">Airdrie Weather</a></li>
+		<li><a href="?/human_resources/index.cfm">Careers</a> | <a href="?/contact_us/index.cfm">Contact Us</a> | <a href="?/site_map/index.cfm">Site Map</a> | <a href="?/links/index.cfm">Links</a></li>
+
+		<li><a href="?/calendars/index.cfm">Community Calendar </a></li>
+		<li><a href="?/conditions_of_use/index.cfm">Conditions of Use and Privacy Statement</a></li>
+		<li><a href="?/index.cfm">I'd like to find out about... </a></li>
+		<li><a href="?/index.cfm">Opportunities</a></li>
+		<li><a href="?/links/index.cfm">Resource Links</a></li>
+		<li><a href="?/index.cfm">Special Notices</a></li>
+
+	</ul>
+	</li>
+	<li><span><strong>City Services</strong></span>
+	<ul>
+		<li><a href="?/assessment/index.cfm">Assessment</a>
+		<ul>
+			<li><a href="?/assessment/assessment_faqs.cfm">Assessment FAQs</a></li>
+
+			<li><a href="?/assessment/property_assessment_notices.cfm">2007 Property Assessment Notices</a></li>
+			<li><a href="?http://www.creb.com/">CREB</a></li>
+			<li><a href="?/assessment/non_residential_assessment_tax_comparisons.cfm">Non-Residential Assessment / Tax Comparisons</a></li>
+			<li><a href="?/assessment/how_to_file_a_complaint.cfm">How to File a Complaint</a></li>
+			<li><a href="?/assessment/supplementary_assessment_tax.cfm">Supplementary Assessment and Tax</a></li>
+		</ul>
+
+		</li>
+		<li><a href="?/building_development/index.cfm">Building &amp; Development </a>
+		<ul>
+			<li><a href="?/building_inspections/index.cfm">Building Inspections</a>
+			<ul>
+				<li><a href="?/building_inspections/builder_forums.cfm">Builder Forums</a></li>
+				<li><a href="?/building_inspections/contact_us.cfm">Contact Us</a></li>
+				<li><a href="?/building_inspections/contractor_notices.cfm">Contractor Notices</a></li>
+				<li><a href="?/building_inspections/inspector_guidelines.cfm">Inspector Guidelines</a></li>
+				<li><a href="?/building_inspections/links.cfm">Links</a></li>
+				<li><a href="?/building_inspections/statistics_2007.cfm">Statistics</a>
+				<ul>
+
+					<li><a href="?/building_inspections/statistics_2006.cfm">Statistics 2006</a></li>
+					<li><a href="?/building_inspections/statistics_2005.cfm">Statistics 2005</a></li>
+				</ul>
+				</li>
+			</ul>
+			</li>
+			<li><a title="City Infrastructure" href="?/building_development/city_infrastructure/index.cfm">City Infrastructure</a>
+			<ul>
+
+				<li><a href="?/building_development/city_infrastructure/roadway_improvement.cfm">Roadway Improvement</a></li>
+				<li><a href="?/building_development/city_infrastructure/traffic.cfm">Traffic</a></li>
+				<li><a href="?/building_development/city_infrastructure/transportation_planning.cfm">Transportation &amp; Infrastructure Planning</a></li>
+				<li><a href="?/building_development/city_infrastructure/water_sewer_construction.cfm">Water &amp; Sewer Construction</a></li>
+
+			</ul>
+			</li>
+			<li><a title="Commercial/Industrial Development" href="?/building_development/commercial_industrial_development/index.cfm">Commercial / Industrial / Multi-Family Development</a>
+			<ul>
+				<li><a title="Call Before You Dig" href="?/building_development/commercial_industrial_development/call_before_you_dig.cfm">Call Before You Dig</a></li>
+				<li><a title="New Development" href="?/building_development/commercial_industrial_development/new_development.cfm">New Development</a></li>
+				<li><a title="Existing Development" href="?/building_development/commercial_industrial_development/existing_development.cfm">Existing Development</a></li>
+				<li><a title="Signage" href="?/building_development/commercial_industrial_development/signage.cfm">Signage</a></li>
+				<li><a title="Notice of Development" href="?/building_development/planning/notice_of_development/notice_of_development.cfm">Notice of Development</a></li>
+				<li><a title="Appeals" href="?/public_meetings/appeals/index.cfm">Appeals</a></li>
+				<li><a title="Customer Feedback" href="?/building_development/commercial_industrial_development/customer_feedback.cfm">Customer Feedback</a></li>
+				<li><a title="Certificate of Compliance" href="?/building_development/commercial_industrial_development/certificate_of_compliance.cfm">Certificate of Compliance</a></li>
+				<li><a title="Permit Applications &amp; Forms" href="?/building_development/commercial_industrial_development/permit_applications_forms.cfm">Permit Applications &amp; Forms</a></li>
+				<li><a title="Fees" href="?/building_development/commercial_industrial_development/fees.cfm">Fees</a></li>
+			</ul>
+			</li>
+			<li><!-- This links to an empty content page (25 Sept 2007) --> <a title="Residential Development" href="?/building_development/residential_development/index.cfm">Residential Development</a>
+			<ul>
+				<li><a title="Call Before You Dig" href="?/building_development/residential_construction/building_permit_requirements.cfm">Building Permit Requirements</a></li>
+				<li><a title="New Development" href="?/building_development/residential_construction/new_homes.cfm">New Homes</a></li>
+				<li><a title="Existing Development" href="?/building_development/residential_construction/basements.cfm">Basements</a></li>
+				<li><a title="Signage" href="?/building_development/commercial_industrial_development/call_before_you_dig.cfm">Call Before You Dig</a></li>
+				<li><a title="Decks" href="?/building_development/residential_development/decks.cfm">Decks</a></li>
+				<li><a title="Detached Garages or Accessory Building" href="?/building_development/residential_development/detached_garages_or_accessory_building.cfm">Detached Garages or Accessory Building</a></li>
+				<li><a title="Grading" href="?/building_development/residential_development/grading.cfm">Grading</a></li>
+				<li><a title="Fences" href="?/building_development/residential_development/fences.cfm">Fences</a></li>
+				<li><a title="Applications, Permits &amp; Checklists" href="?/building_development/residential_development/applications_permits_checklists.cfm">Applications, Permits &amp; Checklists</a></li>
+				<li><a title="Certificate of Compliance" href="?/building_development/commercial_industrial_development/certificate_of_compliance.cfm">Certificate of Compliance</a></li>
+				<li><a title="Fees" href="?/building_development/residential_development/fees.cfm">Fees</a></li>
+				<li><a title="Notice of Development" href="?/building_development/planning/notice_of_development/notice_of_development.cfm">Notice of Development</a></li>
+				<li><a title="Street Addresses for New Construction" href="?/gis/index.cfm">Street Addresses for New Construction</a></li>
+			</ul>
+			</li>
+		</ul>
+		</li>
+		<li><a href="?/community_safety/index.cfm">Community Safety</a>
+		<ul>
+			<li><a href="?/disaster_services/index.cfm">Disaster Services</a></li>
+
+			<li><a href="?/emergency_services/index.cfm">Emergency Services</a></li>
+			<li><a href="?/municipal_enforcement/index.cfm">Municipal Enforcement</a></li>
+			<li><a href="?/rcmp/index.cfm">Royal Canadian Mounted Police</a>
+			<ul>
+				<li><a title="Community Partnership Programs" href="?/rcmp/community_partnership_programs.cfm">Community Partnership Programs</a></li>
+				<li><a title="Traffic Services" href="?/rcmp/traffic_services.cfm">Traffic Services</a></li>
+
+			</ul>
+			</li>
+		</ul>
+		</li>
+		<li><a href="?/community_services/index.cfm">Community Services</a>
+		<ul>
+			<li><a href="?/directories/community_directory/index.cfm">Community Directory</a></li>
+			<li><a href="?/calendars/index.cfm">Community Calendar</a></li>
+
+		</ul>
+		</li>
+		<li><a href="?/engineering/index.cfm">Engineering Services </a></li>
+		<li><a href="?/finance/index.cfm">Finance</a></li>
+		<li><a href="?/gis/index.cfm">Maps (GIS)</a></li>
+		<li><a href="?/parks/parks_recreation.cfm">Parks &amp; Recreation</a></li>
+
+		<li><a href="?/public_works/index.cfm">Public Works</a></li>
+		<li><a href="?/recycling_waste/index.cfm">Recycling, Waste &amp; Composting</a>
+		<ul>
+			<li><a href="?/environmental_services/index.cfm">Environmental Services </a></li>
+		</ul>
+		</li>
+
+		<li><a href="?/social_planning/index.cfm">Social Planning</a></li>
+		<li><a href="?/taxation/index.cfm">Taxation</a></li>
+		<li><a href="?/transit/index.cfm">Transit</a></li>
+		<li><a href="?/utilities/index.cfm">Water &amp; Sewer (Utilities)</a></li>
+	</ul>
+	</li>
+
+	<li><span><strong>News</strong></span>
+	<ul>
+		<li><a href="?/enewsletters/index.cfm">Airdrie eNewsletters</a>
+		<ul>
+			<li><a href="?http://www.industrymailout.com/Industry/View.aspx?id=50169&amp;p=679b">Airdrie Today eNewsletter</a></li>
+			<li><a href="?http://www.industrymailout.com/Industry/View.aspx?id=47265&amp;q=0&amp;qz=4c4af0">Airdrie @Work eNewsletter</a></li>
+			<li><a href="?http://www.industrymailout.com/Industry/Archives.aspx?m=2682&amp;qz=73249dbb">Airdrie eNewsletter Archive</a></li>
+
+		</ul>
+		</li>
+		<li><a href="?/calendars/index.cfm">Community Calendar</a></li>
+		<li><a href="?/community_news/index.cfm">Community News</a></li>
+		<li><a href="?/news_release/index.cfm">News Releases</a> (2007)
+		<ul>
+			<li><a href="?/news_release/2006/index.cfm" title="2006 News Releases">2006 News Releases</a></li>
+
+			<li><a href="?/news_release/2005/index.cfm" title="2005 News Releases">2005 News Releases</a></li>
+			<li><a href="?/news_release/2004/index.cfm" title="2004 News Releases">2004 News Releases</a></li>
+		</ul>
+		</li>
+		<li><a href="?/building_development/planning/notice_of_development/notice_of_development.cfm">Notice of Development </a></li>
+		<li><a href="?/photogallery/index.cfm">Photo Gallery</a></li>
+		<li><a href="?/public_meetings/index.cfm">Public Meetings</a>
+
+		<ul>
+			<li><a href="?/public_meetings/appeals/index.cfm">Appeals</a></li>
+			<li><a href="?/public_meetings/open_houses/index.cfm">Open Houses</a></li>
+			<li><a href="?/public_meetings/public_hearings/index.cfm">Public Hearings</a></li>
+		</ul>
+		</li>
+		<li><a href="?/publications/index.cfm">Publications</a>
+
+		<ul>
+			<li><a href="?/publications/pdf/AirdrieLIFE_fall2006.pdf">Airdrie Life Magazine</a> (16MB, .PDF)</li>
+			<li><a href="?/publications/pdf/report_for_2005.pdf">Annual Economic Report</a> (5 MB, .PDF)</li>
+			<li><a href="?/publications/pdf/Airdrie%20community%20report%20for%202006_sm.pdf">Annual Community Report</a></li>
+		</ul>
+
+		</li>
+	</ul>
+	</li>
+	<li><span><strong>City Council &amp; Administration </strong></span>
+	<ul>
+		<li><a href="?/election/index.cfm">2007 Election</a>
+		<ul>
+
+			<li><a href="?/election/city_council.cfm" title="City Council">City Council</a></li>
+			<li><a href="?/election/candidates.cfm" title="Candidates">Candidates</a></li>
+			<li><a href="?/election/candidate_information_package.cfm" title="Candidate Information Package">Candidate Information Package</a></li>
+			<li><a href="?/election/faq.cfm" title="Frequently Asked Questions">Frequently Asked Questions</a></li>
+			<li><a href="?/election/how_to_vote.cfm" title="How to Vote">How to Vote</a></li>
+			<li><a href="?/election/media.cfm" title="Media">Media</a></li>
+
+			<li><a href="?/election/past_elections.cfm" title="Past Elections">Past Elections</a></li>
+		</ul>
+		</li>
+		<li><a href="?/finance/budget_at_a_glance.cfm">Budget</a></li>
+		<li><a href="?/city_council/bylaws/index.cfm">Bylaws</a>
+		<ul>
+			<li><a href="?/city_council/bylaws/how_bylaws_are_passed.cfm">How Bylaws Are Passed</a></li>
+
+			<li><a href="?/city_council/bylaws/new_laws.cfm">New Laws</a></li>
+			<li><a href="?/city_council/policies.cfm">Policies</a></li>
+		</ul>
+		</li>
+		<li><a href="?/economic_development/census/index.cfm">Census</a></li>
+		<li><a href="?/city_council/index.cfm">City Council</a></li>
+
+	</ul>
+	<ul>
+		<li><a href="?/city_council/board_appointments.cfm">Board Appointments</a></li>
+		<li><a href="?/city_council/committees_boards_commission.cfm">Committees / Boards / Commssion</a>
+		<ul>
+			<li><a href="?/city_council/library_board.cfm" title="Airdrie Municipal Library Board">Airdrie Municipal Library Board</a></li>
+			<li><a href="?/city_council/assessment_review_board.cfm" title="Assessment Review Board">Assessment Review Board</a></li>
+
+			<li><a href="?/city_council/community_service_advisory_board.cfm" title="Community Services Advisory Board">Community Services Advisory Board</a></li>
+			<li><a href="?/city_council/enviromental_advisory_board.cfm" title="Environmental Advisory Board">Environmental Advisory Board</a></li>
+			<li><a href="?/city_council/finance_committee.cfm" title="Finance Advisory Committee">Finance Advisory Committee</a></li>
+			<li><a href="?/city_council/municipal_planning_commission.cfm" title="Municipal Planning Commission">Municipal Planning Commission</a></li>
+			<li><a href="?/city_council/municipal_police_committee.cfm" title="Municipal Police Committee">Municipal Police Committee</a></li>
+			<li><a href="?/city_council/subdivision_development_appeal_board.cfm" title="Subdivision and Development Appeal Board">Subdivision and Development Appeal Board</a></li>
+
+		</ul>
+		</li>
+		<li><a href="?/city_council/faq.cfm">Frequently Asked Questions (FAQ's)</a></li>
+		<li><a href="?/city_council/mayors_message.cfm">Mayor's Message</a></li>
+		<li><a href="?/city_council/mission_vision.cfm">Mission and Vision</a></li>
+		<li><a href="?/city_council/meet_your_council.cfm">Meet Your Council</a></li>
+		<li><a href="?/city_council/strategic_priorities.cfm">Strategic Priorities</a>
+
+		<ul>
+			<li><a href="?/city_council/strategic_priorities.cfm" title="Strategic Priorities 2008">Strategic Priorities 2008</a></li>
+			<li><a href="?/city_council/strategic_priorities_07.cfm" title="Strategic Priorities 2007">Strategic Priorities 2007</a></li>
+			<li><a href="?/city_council/strategic_priorities_06.cfm" title="Strategic Priorities 2006">Strategic Priorities 2006</a></li>
+			<li><a href="?/city_council/strategic_priorities_05.cfm" title="Strategic Priorities 2005">Strategic Priorities 2005</a></li>
+			<li><a href="?/city_council/strategic_priorities_04.cfm" title="Strategic Priorities 2004">Strategic Priorities 2004</a></li>
+
+		</ul>
+		</li>
+		<li><a href="?/city_council/city_council_meetings.cfm">City Council Meetings</a>
+		<ul>
+			<li><a href="?/city_council/agendas/2007_agendas.cfm">City Council Meeting Agendas</a>
+			<ul>
+				<li><a href="?/city_council/agendas/2007_agendas.cfm" title="2007 Agendas">2007 City Council Meeting Agendas</a></li>
+
+				<li><a href="?/city_council/agendas/2006_agendas.cfm" title="2006 Agendas">2006 City Council Meeting Agendas</a></li>
+				<li><a href="?/city_council/agendas/2005_agendas.cfm" title="2005 Agendas">2005 City Council Meeting Agendas</a></li>
+				<li><a href="?/city_council/agendas/2004_agendas.cfm" title="2004 Agendas">2004 City Council Meeting Agendas</a></li>
+			</ul>
+			</li>
+			<li><a href="?/city_council/minutes/2007_minutes.cfm">City Council Meeting Minutes</a>
+			<ul>
+
+				<li><a href="?/city_council/minutes/2007_minutes.cfm" title="2007 City Council Meeting Minutes">2007 City Council Meeting Minutes</a></li>
+				<li><a href="?/city_council/minutes/2006_minutes.cfm" title="2006 City Council Meeting Minutes">2006 City Council Meeting Minutes</a></li>
+				<li><a href="?/city_council/minutes/2005_minutes.cfm" title="2005 City Council Meeting Minutes">2005 City Council Meeting Minutes</a></li>
+				<li><a href="?/city_council/minutes/2004_minutes.cfm" title="2004 City Council Meeting Minutes">2004 City Council Meeting Minutes</a></li>
+			</ul>
+			</li>
+			<li><a href="?/city_council/synopsis/2007_synopsis.cfm">City Council Meeting Synopsis</a>
+
+			<ul>
+				<li><a href="?/city_council/synopsis/2007_synopsis.cfm" title="2007 City Council Meeting Synopsis">2007 City Council Meeting Synopsis</a></li>
+				<li><a href="?/city_council/synopsis/2006_synopsis.cfm" title="2006 City Council Meeting Synopsis">2006 City Council Meeting Synopsis</a></li>
+				<li><a href="?/city_council/synopsis/2005_synopsis.cfm" title="2005 City Council Meeting Synopsis">2005 City Council Meeting Synopsis</a></li>
+				<li><a href="?/city_council/synopsis/2004_synopsis.cfm" title="2004 City Council Meeting Synopsis">2004 City Council Meeting Synopsis</a></li>
+			</ul>
+			</li>
+
+			<li><a href="?/city_council/how_to_go_to_council.cfm">How to Go to Council</a></li>
+		</ul>
+		</li>
+		<li><a href="?/city_council/foip.cfm">FOIP</a></li>
+		<li><a href="?/city_council/how_government_works.cfm">How Government Works</a></li>
+		<li><a href="?/city_council/legislative_admin_services.cfm">Legislative &amp; Admin Services</a>
+
+		<ul>
+			<li><a href="?/city_council/city_managers_message.cfm">City Manager's Message</a></li>
+		</ul>
+		</li>
+		<li><a href="?/org_chart/index.cfm">Organizational Chart</a></li>
+	</ul>
+	</li>
+	<li><strong><a href="?#">Lifestyle</a></strong>
+
+	<ul>
+		<li><a href="?/about_airdrie/index.cfm">About Airdrie</a>
+		<ul>
+			<li><a href="?/about_airdrie/history.cfm">History</a></li>
+		</ul>
+		</li>
+		<li><a href="?/arts_culture/index.cfm">Arts &amp; Culture</a>
+
+		<ul>
+			<li><a href="?/arts_culture/airdrie_art.cfm">Airdrie Art</a></li>
+			<li><a href="?http://www.airdriepubliclibrary.ca/">Airdrie Public Library</a></li>
+			<li><a href="?/arts_culture/airdrie_rodeo_ranch.cfm">Airdrie Rodeo Ranch</a></li>
+			<li><a href="?/bert_church_theatre/index.cfm">Bert Church LIVE Theatre</a></li>
+			<li><a href="?/twinning_program/index.cfm">Korean Twinning Program</a></li>
+
+			<li><a href="?/arts_culture/little_theatre_association.cfm">Little Theatre Association</a></li>
+			<li><a href="?/sport_community_facilities/nose_creek_valley_museum.cfm">Nose Creek Valley Museum</a></li>
+			<li><a href="?http://www.rockyview.ab.ca/rvae/">Rocky View Adult Education</a></li>
+		</ul>
+		</li>
+		<li><a href="?/bert_church_theatre/index.cfm">Bert Church LIVE Theatre</a>
+		<ul>
+
+			<li><a href="?/bert_church_theatre/about_us.cfm" title="About Us">About Us</a></li>
+			<li><a href="?/bert_church_theatre/season_program.cfm" title="Current Season Program">Current Season Program</a></li>
+			<li><a href="?/bert_church_theatre/box_office.cfm" title="Box Office">Box Office</a></li>
+			<li><a href="?/bert_church_theatre/theatre_rental.cfm" title="Theatre Rental">Theatre Rental</a></li>
+			<li><a href="?/bert_church_theatre/technical_specifications.cfm" title="Technical Specifications">Technical Specifications</a></li>
+			<li><a href="?/bert_church_theatre/contact_us.cfm" title="Contact Us">Contact Us</a></li>
+
+			<li><a href="?/bert_church_theatre/photogallery.cfm" title="Photo Gallery">Photo Gallery</a></li>
+			<li><a href="?/bert_church_theatre/links.cfm" title="Links">Links</a></li>
+			<li><a href="?http://www.theresawasden.com/music_in_common.htm" title="Performing Arts Classes">Performing Arts Classes</a></li>
+		</ul>
+		</li>
+		<li><a href="?/elrwc/index.cfm">East Lake Recreation &amp; Wellness Centre</a>
+
+		<ul>
+			<li><a href="?/elrwc/about_facility.cfm" title="About the Facility">About the Facility</a></li>
+			<li><a href="?/elrwc/contact.cfm" title="Contact Us">Contact Us</a></li>
+			<li><a href="?/elrwc/forms.cfm" title="Forms">Forms</a></li>
+			<li><a href="?/elrwc/future_phases.cfm" title="Future Phases">Future Phases</a></li>
+			<li><a href="?/elrwc/hours_operation.cfm" title="Hours of Operation &amp; Schedules">Hours of Operation &amp; Schedules</a>
+
+			<ul>
+				<li><a href="?/elrwc/schedules.cfm">Schedules</a></li>
+			</ul>
+			</li>
+			<li><a href="?/elrwc/city_guide.cfm" title="In the City Guide">In the City Guide</a></li>
+			<li><a href="?/elrwc/opportunities_events.cfm" title="Opportunities &amp; Events">Opportunities &amp; Events</a></li>
+
+			<li><a href="?/elrwc/programs_services.cfm" title="Programs &amp; Services">Programs &amp; Services</a>
+			<ul>
+				<li><a title="Aquatics" href="?/elrwc/aquatics.cfm">Aquatics</a>
+				<ul>
+					<li><a title="Water Drop-in Classes" href="?/elrwc/water_classes.cfm">Water Drop-in Classes</a></li>
+
+				</ul>
+				</li>
+				<li><a title="Child Care Services" href="?/elrwc/child_services.cfm">Child Care Services</a></li>
+				<li><a title="Children Activities" href="?/elrwc/children_activities.cfm">Children Activities</a></li>
+				<li><a title="Fitness &amp; Wellness" href="?/elrwc/fitness_wellness.cfm">Fitness &amp; Wellness</a>
+
+				<ul>
+					<li><a title="Dry Land Drop-in Classes" href="?/elrwc/land_classes.cfm">Dry Land Drop-in Classes</a></li>
+					<li><a title="Fitness &amp; Wellness Services" href="?/elrwc/fitness_wellness_services.cfm">Fitness &amp; Wellness Services</a></li>
+				</ul>
+				</li>
+				<li><a title="Party Packages" href="?/elrwc/party_packages.cfm">Party Packages</a></li>
+
+				<li><a title="Room Rentals" href="?/elrwc/room_rentals.cfm">Room Rentals</a></li>
+			</ul>
+			</li>
+			<li><a href="?/elrwc/rates_fees.cfm" title="Rates &amp; Fees">Rates &amp; Fees</a></li>
+			<li><a href="?/elrwc/register_now.cfm" title="Register Now">Register Now</a></li>
+
+		</ul>
+		</li>
+		<li><a href="?/education/index.cfm">Education</a></li>
+		<li><a href="?/health/index.cfm">Health</a></li>
+		<li><a href="?/gis/index.cfm">Maps (GIS)</a></li>
+		<li><a href="?/parks/parks_recreation.cfm">Parks &amp; Recreation</a></li>
+
+		<li><a title="Parks" href="?/parks/index.cfm">Parks</a>
+		<ul>
+			<li><a title="City Parks Programs" href="?city_parks_programs.cfm">City Parks Programs</a>
+			<ul>
+				<li><a href="?airdrie_horticulture_society.cfm" title="Airdrie Horticulture Society">Airdrie Horticulture Society</a></li>
+				<li><a href="?communities_in_bloom.cfm" title="Communities in Bloom">Communities in Bloom</a></li>
+				<li><a href="?community_garden.cfm" title="Community Garden">Community Garden</a></li>
+
+				<li><a href="?landscape_awards_program.cfm" title="Landscape Awards Program">Landscape Awards Program</a></li>
+			</ul>
+			</li>
+			<li><a title="Maintenance" href="?maintenance.cfm">Maintenance</a>
+			<ul>
+				<li><a href="?dandelions.cfm" title="Dandelions">Dandelions</a></li>
+				<li><a href="?gophers.cfm" title="Gophers">Gophers</a></li>
+
+				<li><a href="?grass_cutting.cfm" title="Grass Cutting">Grass Cutting</a></li>
+				<li><a href="?pathway_snow_removal.cfm" title="Pathway Snow Removal">Pathway Snow Removal</a></li>
+			</ul>
+			</li>
+			<li><a title="Maps" href="?/gis/index.cfm">Maps</a></li>
+			<li><a title="Outdoor Facilities" href="?outdoor_facilities.cfm">Outdoor Facilities</a>
+			<ul>
+
+				<li><a title="Ball Diamonds" href="?ball_diamonds.cfm">Ball Diamonds</a></li>
+				<li><a title="BMX Track" href="?bmx_track.cfm">BMX Track</a></li>
+				<li><a title="Bookings" href="?bookings.cfm">Bookings</a></li>
+				<li><a title="Cemetery" href="?cemetery.cfm">Cemetery</a></li>
+				<li><a title="Fire Pits" href="?fire_pits.cfm">Fire Pits</a></li>
+				<li><a title="Gwacheon Park" href="?/twinning_program/index.cfm#gwacheon">Gwacheon Park</a></li>
+
+				<li><a title="Off-Leash Areas" href="?off_leash_areas.cfm">Off-Leash Areas</a></li>
+				<li><a title="Outdoor Rinks" href="?outdoor_rinks.cfm">Outdoor Rinks</a></li>
+				<li><a title="Parks &amp; Playgrounds" href="?parks_playgrounds.cfm">Parks & Playgrounds</a></li>
+				<li><a title="Skate Park" href="?skate_park.cfm">Skate Park</a></li>
+				<li><a title="Soccer/Athletic Fields" href="?soccer_athletic_fields.cfm">Soccer/Athletic Fields</a></li>
+				<li><a title="Splash Park" href="?splash_park.cfm">Splash Park</a></li>
+
+				<li><a title="Tennis Courts" href="?tennis_courts.cfm">Tennis Courts</a></li>
+			</ul>
+			</li>
+			<li><a title="Parks Planning &amp; Construction" href="?parks_planning_construction.cfm">Parks Planning & Construction</a>
+			<ul>
+				<li><a href="?construction.cfm" title="Construction">Construction</a></li>
+				<li><a href="?plans.cfm" title="Plans">Plans</a></li>
+
+			</ul>
+			</li>
+			<li><a title="Urban Forest" href="?urban_forest.cfm">Urban Forest</a>
+			<ul>
+				<li><a href="?city_trees.cfm" title="City Trees">City Trees</a></li>
+				<li><a href="?tree_planting.cfm" title="Tree Planting">Tree Planting</a></li>
+			</ul>
+
+			</li>
+			<li><a title="Weeds &amp; Pests" href="?weeds_pests.cfm">Weeds & Pests</a>
+			<ul>
+				<li><a href="?mosquito_control.cfm" title="Mosquito Control">Mosquito Control</a></li>
+				<li><a href="?pest_control.cfm" title="Pest Control">Pest Control</a></li>
+				<li><a href="?weed_control_plant_disease.cfm" title="Weed Control &amp; Plant Disease">Weed Control &amp; Plant Disease</a></li>
+
+			</ul>
+			</li>
+		</ul>
+		</li>
+		<li><a title="Sport &amp; Community Facilities" href="?/sport_community_facilities/index.cfm">Sport &amp; Community Facilities</a>
+		<ul>
+			<li><a title="Indoor Facilities" href="?/sport_community_facilities/indoor_facilities.cfm">Indoor Facilities</a>
+
+			<ul>
+				<li><a title="Arenas/Gymnastics" href="?/sport_community_facilities/arenas_gymnastics.cfm">Arenas/Gymnastics</a></li>
+				<li><a title="Curling Rink" href="?/sport_community_facilities/curling_rink.cfm">Curling Rink</a></li>
+				<li><a title="East Lake Recreation &amp; Wellness Centre" href="?/elrwc/index.cfm">East Lake Recreation &amp; Wellness Centre</a></li>
+				<li><a title="Nose Creek Valley Museum" href="?/sport_community_facilities/nose_creek_valley_museum.cfm">Nose Creek Valley Museum</a></li>
+				<li><a title="Over 50 Club" href="?/sport_community_facilities/over_50_club.cfm">Over 50 Club</a></li>
+
+				<li><a title="Town &amp; Country" href="?/sport_community_facilities/town_country.cfm">Town &amp; Country</a></li>
+			</ul>
+			</li>
+			<li><a title="Outdoor Facilities" href="?/parks/outdoor_facilities.cfm">Outdoor Facilities</a></li>
+		</ul>
+		</li>
+	</ul>
+
+	</li>
+	<li><strong><a href="?#">Visiting</a></strong>
+	<ul>
+		<li><a href="?/economic_development/video/index.cfm">Airdrie LIFE Video</a></li>
+		<li><a href="?/gis/recreation_map/index.cfm">Community Map</a></li>
+		<li><a href="?/events/index.cfm">Events</a>
+		<ul>
+
+			<li><a href="?http://www.airdriefestivaloflights.com">Airdrie Festival of Lights</a></li>
+			<li><a href="?http://www.airdrieprorodeo.net/">Airdrie Pro Rodeo</a></li>
+			<li><a href="?http://www.pch.gc.ca/special/canada/index_e.cfm">Canada Day</a></li>
+		</ul>
+		</li>
+		<li><a href="?/parks/parks_recreation.cfm">Parks &amp; Recreation</a></li>
+
+		<li><a href="?/economic_development/tourist_information/tourist_information.cfm">Tourist Information</a>
+		<ul>
+			<li><a href="?/economic_development/entertainment/entertainment.cfm">Entertainment</a></li>
+			<li><a href="?/economic_development/hotels/hotels.cfm">Hotels</a></li>
+			<li><a href="?/economic_development/restaurants/restaurants.cfm">Restaurants</a></li>
+			<li><a href="?/economic_development/shopping/shopping.cfm">Shopping</a></li>
+
+			<li><a href="?http://www1.travelalberta.com/en-ab/index.cfm?country=CA&amp;state=AB&amp;setlocale=1">Travel Alberta</a></li>
+		</ul>
+		</li>
+		<li><a href="?http://www.woodsidegc.com/contact.html">Woodside Golf Course</a></li>
+	</ul>
+	</li>
+	<li><strong><a href="?/economic_development/index.cfm">Doing Business</a></strong>
+
+	<ul>
+		<li><a href="?/economic_development/business_attraction/index.cfm">Business Attraction</a>
+		<ul>
+			<li><a href="?http://www.albertafirst.com/profiles/statspack/20365.html">Airdrie Profile</a></li>
+			<li><a href="?/economic_development/business_attraction/business_case.cfm">Business Case For Airdrie</a></li>
+			<li><a href="?/economic_development/census/index.cfm">Census Data </a></li>
+			<li><a href="?http://www.albertafirst.com/realestate/">Properties and Businesses For Sale</a></li>
+
+			<li><a href="?/taxation/non_residential_comparisons.cfm">Taxation</a></li>
+		</ul>
+		</li>
+		<li><a href="?/economic_development/business_development/index.cfm">Business Development</a>
+		<ul>
+			<li><a href="?/economic_development/business_development/business_associations.cfm">Business Associations</a></li>
+			<li><a href="?/economic_development/business_development/business_resources.cfm">Business Resources</a></li>
+
+			<li><a href="?/economic_development/business_development/business_services.cfm">Business Services</a></li>
+			<li><a href="?/corporate_properties/index.cfm">Corporate Properties</a></li>
+			<li><a href="?/economic_development/business_development/home_businesses.cfm">Home Based Businesses</a></li>
+		</ul>
+		</li>
+		<li><a href="?/directories/business_directory/index.cfm">Business Directory</a></li>
+
+		<li><a href="?/economic_development/business_licenses/index.cfm">Business Licenses</a>
+		<ul>
+			<li><a href="?/economic_development/business_licenses/municipal_licenses_permits.cfm">Municipal Licenses &amp; Permits</a></li>
+			<li><a href="?/economic_development/business_licenses/provincial_licenses_permits.cfm">Provincial Licenses &amp; Permits</a></li>
+			<li><a href="?/economic_development/business_licenses/registry_services.cfm">Registry Services</a></li>
+
+		</ul>
+		</li>
+		<li><a href="?http://bsa.canadabusiness.ca/gol/bsa/site.nsf/en/index.html">How to Start a Business</a></li>
+		<li><a href="?/finance/procurement_services.cfm">Procurement Services</a></li>
+	</ul>
+	</li>
+	<li><strong><a href="?https://vch.airdrie.ca/index.cfm">Online Services</a></strong></li>
+
+</ul>
+</div>
+
+</div>
+
+</body>
+
+</html>
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/prerendered.html b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/prerendered.html
new file mode 100644
index 0000000..957822f
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/prerendered.html
@@ -0,0 +1,621 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+
+	<link rel="stylesheet" href="../jquery.treeview.css" />
+    <link rel="stylesheet" href="../red-treeview.css" />
+	<link rel="stylesheet" href="screen.css" />
+	
+	<script src="../lib/jquery.js" type="text/javascript"></script>
+	<script src="../lib/jquery.cookie.js" type="text/javascript"></script>
+	<script src="../jquery.treeview.js" type="text/javascript"></script>
+	
+	<script type="text/javascript">
+		$(function() {
+			$("#tree").treeview({
+				collapsed: true,
+				animated: "medium",
+				control:"#sidetreecontrol",
+				prerendered: true,
+				persist: "location"
+			});
+		})
+		
+	</script>
+
+</head>
+<body>
+
+	<h1 id="banner"><a href="http://bassistance.de/jquery-plugins/jquery-plugin-treeview/">jQuery Treeview Plugin</a> Demo</h1>
+	<div id="main">
+	
+	<a href=".">Main Demo</a>
+
+<div id="sidetree">
+  <div class="treeheader">&nbsp;</div>
+  <div id="sidetreecontrol"> <a href="?#">Collapse All</a> | <a href="?#">Expand All</a> </div>
+
+  <ul class="treeview" id="tree">
+
+	<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/index.cfm"><strong>Home</strong></a>
+	<ul style="display: none;">
+		<li><a href="?/enewsletters/index.cfm">Airdrie eNewsletters </a></li>
+		<li><a href="?/index.cfm">Airdrie Directories</a></li>
+		<li><a href="?/economic_development/video/index.cfm">Airdrie Life Video</a></li>
+
+		<li><a href="?/index.cfm">Airdrie News</a></li>
+
+		<li><a href="?/index.cfm">Airdrie Quick Links</a></li>
+		<li><a href="?http://weather.ibegin.com/ca/ab/airdrie/" target="_blank">Airdrie Weather</a></li>
+		<li><a href="?/human_resources/index.cfm">Careers</a> | <a href="?/contact_us/index.cfm">Contact Us</a> | <a href="?/site_map/index.cfm">Site Map</a> | <a href="?/links/index.cfm">Links</a></li>
+
+		<li><a href="?/calendars/index.cfm">Community Calendar </a></li>
+		<li><a href="?/conditions_of_use/index.cfm">Conditions of Use and Privacy Statement</a></li>
+		<li><a href="?/index.cfm">I'd like to find out about... </a></li>
+		<li><a href="?/index.cfm">Opportunities</a></li>
+		<li><a href="?/links/index.cfm">Resource Links</a></li>
+		<li class="last"><a href="?/index.cfm">Special Notices</a></li>
+
+	</ul>
+	</li>
+	<li class="expandable"><div class="hitarea expandable-hitarea"></div><span><strong>City Services</strong></span>
+	<ul style="display: none;">
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/assessment/index.cfm">Assessment</a>
+		<ul style="display: none;">
+			<li><a href="?/assessment/assessment_faqs.cfm">Assessment FAQs</a></li>
+
+			<li><a href="?/assessment/property_assessment_notices.cfm">2007 Property Assessment Notices</a></li>
+			<li><a href="?http://www.creb.com/" target="_blank">CREB</a></li>
+			<li><a href="?/assessment/non_residential_assessment_tax_comparisons.cfm">Non-Residential Assessment / Tax Comparisons</a></li>
+			<li><a href="?/assessment/how_to_file_a_complaint.cfm">How to File a Complaint</a></li>
+			<li class="last"><a href="?/assessment/supplementary_assessment_tax.cfm">Supplementary Assessment and Tax</a></li>
+		</ul>
+
+		</li>
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/building_development/index.cfm">Building &amp; Development </a>
+		<ul style="display: none;">
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/building_inspections/index.cfm">Building Inspections</a>
+			<ul style="display: none;">
+				<li><a href="?/building_inspections/builder_forums.cfm">Builder Forums</a></li>
+
+				<li><a href="?/building_inspections/contact_us.cfm">Contact Us</a></li>
+				<li><a href="?/building_inspections/contractor_notices.cfm">Contractor Notices</a></li>
+				<li><a href="?/building_inspections/inspector_guidelines.cfm">Inspector Guidelines</a></li>
+				<li><a href="?/building_inspections/links.cfm">Links</a></li>
+				<li class="expandable lastExpandable"><div class="hitarea expandable-hitarea lastExpandable-hitarea"></div><a href="?/building_inspections/statistics_2007.cfm">Statistics</a>
+				<ul style="display: none;">
+
+					<li><a href="?/building_inspections/statistics_2006.cfm">Statistics 2006</a></li>
+					<li class="last"><a href="?/building_inspections/statistics_2005.cfm">Statistics 2005</a></li>
+				</ul>
+				</li>
+			</ul>
+			</li>
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a title="City Infrastructure" href="?/building_development/city_infrastructure/index.cfm">City Infrastructure</a>
+
+			<ul style="display: none;">
+
+				<li><a href="?/building_development/city_infrastructure/roadway_improvement.cfm">Roadway Improvement</a></li>
+				<li><a href="?/building_development/city_infrastructure/traffic.cfm">Traffic</a></li>
+				<li><a href="?/building_development/city_infrastructure/transportation_planning.cfm">Transportation &amp; Infrastructure Planning</a></li>
+				<li class="last"><a href="?/building_development/city_infrastructure/water_sewer_construction.cfm">Water &amp; Sewer Construction</a></li>
+
+			</ul>
+			</li>
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a title="Commercial/Industrial Development" href="?/building_development/commercial_industrial_development/index.cfm">Commercial / Industrial / Multi-Family Development</a>
+			<ul style="display: none;">
+				<li><a title="Call Before You Dig" href="?/building_development/commercial_industrial_development/call_before_you_dig.cfm">Call Before You Dig</a></li>
+				<li><a title="New Development" href="?/building_development/commercial_industrial_development/new_development.cfm">New Development</a></li>
+				<li><a title="Existing Development" href="?/building_development/commercial_industrial_development/existing_development.cfm">Existing Development</a></li>
+
+				<li><a title="Signage" href="?/building_development/commercial_industrial_development/signage.cfm">Signage</a></li>
+				<li><a title="Notice of Development" href="?/building_development/planning/notice_of_development/notice_of_development.cfm">Notice of Development</a></li>
+				<li><a title="Appeals" href="?/public_meetings/appeals/index.cfm">Appeals</a></li>
+				<li><a title="Customer Feedback" href="?/building_development/commercial_industrial_development/customer_feedback.cfm">Customer Feedback</a></li>
+				<li><a title="Certificate of Compliance" href="?/building_development/commercial_industrial_development/certificate_of_compliance.cfm">Certificate of Compliance</a></li>
+				<li><a title="Permit Applications &amp; Forms" href="?/building_development/commercial_industrial_development/permit_applications_forms.cfm">Permit Applications &amp; Forms</a></li>
+
+				<li class="last"><a title="Fees" href="?/building_development/commercial_industrial_development/fees.cfm">Fees</a></li>
+			</ul>
+			</li>
+			<li class="expandable lastExpandable"><div class="hitarea expandable-hitarea lastExpandable-hitarea"></div><!-- This links to an empty content page (25 Sept 2007) --> <a title="Residential Development" href="?/building_development/residential_development/index.cfm">Residential Development</a>
+			<ul style="display: none;">
+				<li><a title="Call Before You Dig" href="?/building_development/residential_construction/building_permit_requirements.cfm">Building Permit Requirements</a></li>
+				<li><a title="New Development" href="?/building_development/residential_construction/new_homes.cfm">New Homes</a></li>
+
+				<li><a title="Existing Development" href="?/building_development/residential_construction/basements.cfm">Basements</a></li>
+				<li><a title="Signage" href="?/building_development/commercial_industrial_development/call_before_you_dig.cfm">Call Before You Dig</a></li>
+				<li><a title="Decks" href="?/building_development/residential_development/decks.cfm">Decks</a></li>
+				<li><a title="Detached Garages or Accessory Building" href="?/building_development/residential_development/detached_garages_or_accessory_building.cfm">Detached Garages or Accessory Building</a></li>
+				<li><a title="Grading" href="?/building_development/residential_development/grading.cfm">Grading</a></li>
+				<li><a title="Fences" href="?/building_development/residential_development/fences.cfm">Fences</a></li>
+
+				<li><a title="Applications, Permits &amp; Checklists" href="?/building_development/residential_development/applications_permits_checklists.cfm">Applications, Permits &amp; Checklists</a></li>
+				<li><a title="Certificate of Compliance" href="?/building_development/commercial_industrial_development/certificate_of_compliance.cfm">Certificate of Compliance</a></li>
+				<li><a title="Fees" href="?/building_development/residential_development/fees.cfm">Fees</a></li>
+				<li><a title="Notice of Development" href="?/building_development/planning/notice_of_development/notice_of_development.cfm">Notice of Development</a></li>
+				<li class="last"><a title="Street Addresses for New Construction" href="?/gis/index.cfm">Street Addresses for New Construction</a></li>
+
+			</ul>
+			</li>
+		</ul>
+		</li>
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/community_safety/index.cfm">Community Safety</a>
+		<ul style="display: none;">
+			<li><a href="?/disaster_services/index.cfm">Disaster Services</a></li>
+
+			<li><a href="?/emergency_services/index.cfm">Emergency Services</a></li>
+			<li><a href="?/municipal_enforcement/index.cfm">Municipal Enforcement</a></li>
+			<li class="expandable lastExpandable"><div class="hitarea expandable-hitarea lastExpandable-hitarea"></div><a href="?/rcmp/index.cfm">Royal Canadian Mounted Police</a>
+			<ul style="display: none;">
+				<li><a title="Community Partnership Programs" href="?/rcmp/community_partnership_programs.cfm">Community Partnership Programs</a></li>
+				<li class="last"><a title="Traffic Services" href="?/rcmp/traffic_services.cfm">Traffic Services</a></li>
+
+			</ul>
+			</li>
+		</ul>
+		</li>
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/community_services/index.cfm">Community Services</a>
+		<ul style="display: none;">
+			<li><a href="?/directories/community_directory/index.cfm">Community Directory</a></li>
+
+			<li class="last"><a href="?/calendars/index.cfm">Community Calendar</a></li>
+
+		</ul>
+		</li>
+		<li><a href="?/engineering/index.cfm">Engineering Services </a></li>
+		<li><a href="?/finance/index.cfm">Finance</a></li>
+		<li><a href="?/gis/index.cfm">Maps (GIS)</a></li>
+
+		<li><a href="?/parks/parks_recreation.cfm">Parks &amp; Recreation</a></li>
+
+		<li><a href="?/public_works/index.cfm">Public Works</a></li>
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/recycling_waste/index.cfm">Recycling, Waste &amp; Composting</a>
+		<ul style="display: none;">
+			<li class="last"><a href="?/environmental_services/index.cfm">Environmental Services </a></li>
+
+		</ul>
+		</li>
+
+		<li><a href="?/social_planning/index.cfm">Social Planning</a></li>
+		<li><a href="?/taxation/index.cfm">Taxation</a></li>
+		<li><a href="?/transit/index.cfm">Transit</a></li>
+		<li class="last"><a href="?/utilities/index.cfm">Water &amp; Sewer (Utilities)</a></li>
+
+	</ul>
+	</li>
+
+	<li class="expandable"><div class="hitarea expandable-hitarea"></div><span><strong>News</strong></span>
+	<ul style="display: none;">
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/enewsletters/index.cfm">Airdrie eNewsletters</a>
+		<ul style="display: none;">
+			<li><a href="?http://www.industrymailout.com/Industry/View.aspx?id=50169&amp;p=679b" target="_new">Airdrie Today eNewsletter</a></li>
+
+			<li><a href="?http://www.industrymailout.com/Industry/View.aspx?id=47265&amp;q=0&amp;qz=4c4af0" target="_new">Airdrie @Work eNewsletter</a></li>
+			<li class="last"><a href="?http://www.industrymailout.com/Industry/Archives.aspx?m=2682&amp;qz=73249dbb" target="_new">Airdrie eNewsletter Archive</a></li>
+
+		</ul>
+		</li>
+		<li><a href="?/calendars/index.cfm">Community Calendar</a></li>
+		<li><a href="?/community_news/index.cfm">Community News</a></li>
+
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/news_release/index.cfm">News Releases</a> (2007)
+		<ul style="display: none;">
+			<li><a href="?/news_release/2006/index.cfm" title="2006 News Releases">2006 News Releases</a></li>
+
+			<li><a href="?/news_release/2005/index.cfm" title="2005 News Releases">2005 News Releases</a></li>
+			<li class="last"><a href="?/news_release/2004/index.cfm" title="2004 News Releases">2004 News Releases</a></li>
+		</ul>
+
+		</li>
+		<li><a href="?/building_development/planning/notice_of_development/notice_of_development.cfm">Notice of Development </a></li>
+		<li><a href="?/photogallery/index.cfm">Photo Gallery</a></li>
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/public_meetings/index.cfm">Public Meetings</a>
+
+		<ul style="display: none;">
+			<li><a href="?/public_meetings/appeals/index.cfm">Appeals</a></li>
+
+			<li><a href="?/public_meetings/open_houses/index.cfm">Open Houses</a></li>
+			<li class="last"><a href="?/public_meetings/public_hearings/index.cfm">Public Hearings</a></li>
+		</ul>
+		</li>
+		<li class="expandable lastExpandable"><div class="hitarea expandable-hitarea lastExpandable-hitarea"></div><a href="?/publications/index.cfm">Publications</a>
+
+		<ul style="display: none;">
+			<li><a href="?/publications/pdf/AirdrieLIFE_fall2006.pdf">Airdrie Life Magazine</a> (16MB, .PDF)</li>
+
+			<li><a href="?/publications/pdf/report_for_2005.pdf">Annual Economic Report</a> (5 MB, .PDF)</li>
+			<li class="last"><a href="?/publications/pdf/Airdrie%20community%20report%20for%202006_sm.pdf">Annual Community Report</a></li>
+		</ul>
+
+		</li>
+	</ul>
+	</li>
+
+	<li class="expandable"><div class="hitarea expandable-hitarea"></div><span><strong>City Council &amp; Administration </strong></span>
+	<ul style="display: none;">
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/election/index.cfm">2007 Election</a>
+		<ul style="display: none;">
+
+			<li><a href="?/election/city_council.cfm" title="City Council">City Council</a></li>
+			<li><a href="?/election/candidates.cfm" title="Candidates">Candidates</a></li>
+
+			<li><a href="?/election/candidate_information_package.cfm" title="Candidate Information Package">Candidate Information Package</a></li>
+			<li><a href="?/election/faq.cfm" title="Frequently Asked Questions">Frequently Asked Questions</a></li>
+			<li><a href="?/election/how_to_vote.cfm" title="How to Vote">How to Vote</a></li>
+			<li><a href="?/election/media.cfm" title="Media">Media</a></li>
+
+			<li class="last"><a href="?/election/past_elections.cfm" title="Past Elections">Past Elections</a></li>
+		</ul>
+
+		</li>
+		<li><a href="?/finance/budget_at_a_glance.cfm">Budget</a></li>
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/city_council/bylaws/index.cfm">Bylaws</a>
+		<ul style="display: none;">
+			<li><a href="?/city_council/bylaws/how_bylaws_are_passed.cfm">How Bylaws Are Passed</a></li>
+
+			<li><a href="?/city_council/bylaws/new_laws.cfm">New Laws</a></li>
+
+			<li class="last"><a href="?/city_council/policies.cfm">Policies</a></li>
+		</ul>
+		</li>
+		<li><a href="?/economic_development/census/index.cfm">Census</a></li>
+		<li class="last"><a href="?/city_council/index.cfm">City Council</a></li>
+
+	</ul>
+	<ul style="display: none;">
+
+		<li><a href="?/city_council/board_appointments.cfm">Board Appointments</a></li>
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/city_council/committees_boards_commission.cfm">Committees / Boards / Commssion</a>
+		<ul style="display: none;">
+			<li><a href="?/city_council/library_board.cfm" title="Airdrie Municipal Library Board">Airdrie Municipal Library Board</a></li>
+			<li><a href="?/city_council/assessment_review_board.cfm" title="Assessment Review Board">Assessment Review Board</a></li>
+
+			<li><a href="?/city_council/community_service_advisory_board.cfm" title="Community Services Advisory Board">Community Services Advisory Board</a></li>
+
+			<li><a href="?/city_council/enviromental_advisory_board.cfm" title="Environmental Advisory Board">Environmental Advisory Board</a></li>
+			<li><a href="?/city_council/finance_committee.cfm" title="Finance Advisory Committee">Finance Advisory Committee</a></li>
+			<li><a href="?/city_council/municipal_planning_commission.cfm" title="Municipal Planning Commission">Municipal Planning Commission</a></li>
+			<li><a href="?/city_council/municipal_police_committee.cfm" title="Municipal Police Committee">Municipal Police Committee</a></li>
+			<li class="last"><a href="?/city_council/subdivision_development_appeal_board.cfm" title="Subdivision and Development Appeal Board">Subdivision and Development Appeal Board</a></li>
+
+		</ul>
+
+		</li>
+		<li><a href="?/city_council/faq.cfm">Frequently Asked Questions (FAQ's)</a></li>
+		<li><a href="?/city_council/mayors_message.cfm">Mayor's Message</a></li>
+		<li><a href="?/city_council/mission_vision.cfm">Mission and Vision</a></li>
+		<li><a href="?/city_council/meet_your_council.cfm">Meet Your Council</a></li>
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/city_council/strategic_priorities.cfm">Strategic Priorities</a>
+
+		<ul style="display: none;">
+			<li><a href="?/city_council/strategic_priorities.cfm" title="Strategic Priorities 2008">Strategic Priorities 2008</a></li>
+			<li><a href="?/city_council/strategic_priorities_07.cfm" title="Strategic Priorities 2007">Strategic Priorities 2007</a></li>
+			<li><a href="?/city_council/strategic_priorities_06.cfm" title="Strategic Priorities 2006">Strategic Priorities 2006</a></li>
+			<li><a href="?/city_council/strategic_priorities_05.cfm" title="Strategic Priorities 2005">Strategic Priorities 2005</a></li>
+			<li class="last"><a href="?/city_council/strategic_priorities_04.cfm" title="Strategic Priorities 2004">Strategic Priorities 2004</a></li>
+
+		</ul>
+		</li>
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/city_council/city_council_meetings.cfm">City Council Meetings</a>
+		<ul style="display: none;">
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/city_council/agendas/2007_agendas.cfm">City Council Meeting Agendas</a>
+			<ul style="display: none;">
+				<li><a href="?/city_council/agendas/2007_agendas.cfm" title="2007 Agendas">2007 City Council Meeting Agendas</a></li>
+
+				<li><a href="?/city_council/agendas/2006_agendas.cfm" title="2006 Agendas">2006 City Council Meeting Agendas</a></li>
+				<li><a href="?/city_council/agendas/2005_agendas.cfm" title="2005 Agendas">2005 City Council Meeting Agendas</a></li>
+				<li class="last"><a href="?/city_council/agendas/2004_agendas.cfm" title="2004 Agendas">2004 City Council Meeting Agendas</a></li>
+			</ul>
+			</li>
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/city_council/minutes/2007_minutes.cfm">City Council Meeting Minutes</a>
+
+			<ul style="display: none;">
+
+				<li><a href="?/city_council/minutes/2007_minutes.cfm" title="2007 City Council Meeting Minutes">2007 City Council Meeting Minutes</a></li>
+				<li><a href="?/city_council/minutes/2006_minutes.cfm" title="2006 City Council Meeting Minutes">2006 City Council Meeting Minutes</a></li>
+				<li><a href="?/city_council/minutes/2005_minutes.cfm" title="2005 City Council Meeting Minutes">2005 City Council Meeting Minutes</a></li>
+				<li class="last"><a href="?/city_council/minutes/2004_minutes.cfm" title="2004 City Council Meeting Minutes">2004 City Council Meeting Minutes</a></li>
+			</ul>
+
+			</li>
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/city_council/synopsis/2007_synopsis.cfm">City Council Meeting Synopsis</a>
+
+			<ul style="display: none;">
+				<li><a href="?/city_council/synopsis/2007_synopsis.cfm" title="2007 City Council Meeting Synopsis">2007 City Council Meeting Synopsis</a></li>
+				<li><a href="?/city_council/synopsis/2006_synopsis.cfm" title="2006 City Council Meeting Synopsis">2006 City Council Meeting Synopsis</a></li>
+				<li><a href="?/city_council/synopsis/2005_synopsis.cfm" title="2005 City Council Meeting Synopsis">2005 City Council Meeting Synopsis</a></li>
+
+				<li class="last"><a href="?/city_council/synopsis/2004_synopsis.cfm" title="2004 City Council Meeting Synopsis">2004 City Council Meeting Synopsis</a></li>
+			</ul>
+			</li>
+
+			<li class="last"><a href="?/city_council/how_to_go_to_council.cfm">How to Go to Council</a></li>
+		</ul>
+		</li>
+		<li><a href="?/city_council/foip.cfm">FOIP</a></li>
+
+		<li><a href="?/city_council/how_government_works.cfm">How Government Works</a></li>
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/city_council/legislative_admin_services.cfm">Legislative &amp; Admin Services</a>
+
+		<ul style="display: none;">
+			<li class="last"><a href="?/city_council/city_managers_message.cfm">City Manager's Message</a></li>
+		</ul>
+		</li>
+
+		<li class="last"><a href="?/org_chart/index.cfm">Organizational Chart</a></li>
+	</ul>
+	</li>
+	<li class="expandable"><div class="hitarea expandable-hitarea"></div><strong><a href="?#">Lifestyle</a></strong>
+
+	<ul style="display: none;">
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/about_airdrie/index.cfm">About Airdrie</a>
+		<ul style="display: none;">
+
+			<li class="last"><a href="?/about_airdrie/history.cfm">History</a></li>
+		</ul>
+		</li>
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/arts_culture/index.cfm">Arts &amp; Culture</a>
+
+		<ul style="display: none;">
+			<li><a href="?/arts_culture/airdrie_art.cfm">Airdrie Art</a></li>
+
+			<li><a href="?http://www.airdriepubliclibrary.ca/" target="_new">Airdrie Public Library</a></li>
+			<li><a href="?/arts_culture/airdrie_rodeo_ranch.cfm">Airdrie Rodeo Ranch</a></li>
+			<li><a href="?/bert_church_theatre/index.cfm">Bert Church LIVE Theatre</a></li>
+			<li><a href="?/twinning_program/index.cfm">Korean Twinning Program</a></li>
+
+			<li><a href="?/arts_culture/little_theatre_association.cfm">Little Theatre Association</a></li>
+			<li><a href="?/sport_community_facilities/nose_creek_valley_museum.cfm" target="_new">Nose Creek Valley Museum</a></li>
+
+			<li class="last"><a href="?http://www.rockyview.ab.ca/rvae/" target="_new">Rocky View Adult Education</a></li>
+		</ul>
+		</li>
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/bert_church_theatre/index.cfm">Bert Church LIVE Theatre</a>
+		<ul style="display: none;">
+
+			<li><a href="?/bert_church_theatre/about_us.cfm" title="About Us">About Us</a></li>
+			<li><a href="?/bert_church_theatre/season_program.cfm" title="Current Season Program">Current Season Program</a></li>
+
+			<li><a href="?/bert_church_theatre/box_office.cfm" title="Box Office">Box Office</a></li>
+			<li><a href="?/bert_church_theatre/theatre_rental.cfm" title="Theatre Rental">Theatre Rental</a></li>
+			<li><a href="?/bert_church_theatre/technical_specifications.cfm" title="Technical Specifications">Technical Specifications</a></li>
+			<li><a href="?/bert_church_theatre/contact_us.cfm" title="Contact Us">Contact Us</a></li>
+
+			<li><a href="?/bert_church_theatre/photogallery.cfm" title="Photo Gallery">Photo Gallery</a></li>
+			<li><a href="?/bert_church_theatre/links.cfm" title="Links">Links</a></li>
+
+			<li class="last"><a href="?http://www.theresawasden.com/music_in_common.htm" target="_blank" title="Performing Arts Classes">Performing Arts Classes</a></li>
+		</ul>
+		</li>
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/elrwc/index.cfm">East Lake Recreation &amp; Wellness Centre</a>
+
+		<ul style="display: none;">
+			<li><a href="?/elrwc/about_facility.cfm" title="About the Facility">About the Facility</a></li>
+
+			<li><a href="?/elrwc/contact.cfm" title="Contact Us">Contact Us</a></li>
+			<li><a href="?/elrwc/forms.cfm" title="Forms">Forms</a></li>
+			<li><a href="?/elrwc/future_phases.cfm" title="Future Phases">Future Phases</a></li>
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/elrwc/hours_operation.cfm" title="Hours of Operation &amp; Schedules">Hours of Operation &amp; Schedules</a>
+
+			<ul style="display: none;">
+
+				<li class="last"><a href="?/elrwc/schedules.cfm">Schedules</a></li>
+			</ul>
+			</li>
+			<li><a href="?/elrwc/city_guide.cfm" title="In the City Guide">In the City Guide</a></li>
+			<li><a href="?/elrwc/opportunities_events.cfm" title="Opportunities &amp; Events">Opportunities &amp; Events</a></li>
+
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/elrwc/programs_services.cfm" title="Programs &amp; Services">Programs &amp; Services</a>
+
+			<ul style="display: none;">
+				<li class="expandable"><div class="hitarea expandable-hitarea"></div><a title="Aquatics" href="?/elrwc/aquatics.cfm">Aquatics</a>
+				<ul style="display: none;">
+					<li class="last"><a title="Water Drop-in Classes" href="?/elrwc/water_classes.cfm">Water Drop-in Classes</a></li>
+
+				</ul>
+				</li>
+				<li><a title="Child Care Services" href="?/elrwc/child_services.cfm">Child Care Services</a></li>
+
+				<li><a title="Children Activities" href="?/elrwc/children_activities.cfm">Children Activities</a></li>
+				<li class="expandable"><div class="hitarea expandable-hitarea"></div><a title="Fitness &amp; Wellness" href="?/elrwc/fitness_wellness.cfm">Fitness &amp; Wellness</a>
+
+				<ul style="display: none;">
+					<li><a title="Dry Land Drop-in Classes" href="?/elrwc/land_classes.cfm">Dry Land Drop-in Classes</a></li>
+					<li class="last"><a title="Fitness &amp; Wellness Services" href="?/elrwc/fitness_wellness_services.cfm">Fitness &amp; Wellness Services</a></li>
+
+				</ul>
+				</li>
+				<li><a title="Party Packages" href="?/elrwc/party_packages.cfm">Party Packages</a></li>
+
+				<li class="last"><a title="Room Rentals" href="?/elrwc/room_rentals.cfm">Room Rentals</a></li>
+			</ul>
+			</li>
+			<li><a href="?/elrwc/rates_fees.cfm" title="Rates &amp; Fees">Rates &amp; Fees</a></li>
+
+			<li class="last"><a href="?/elrwc/register_now.cfm" title="Register Now">Register Now</a></li>
+
+		</ul>
+		</li>
+		<li><a href="?/education/index.cfm">Education</a></li>
+		<li><a href="?/health/index.cfm">Health</a></li>
+		<li><a href="?/gis/index.cfm">Maps (GIS)</a></li>
+
+		<li><a href="?/parks/parks_recreation.cfm">Parks &amp; Recreation</a></li>
+
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a title="Parks" href="?/parks/index.cfm">Parks</a>
+		<ul style="display: none;">
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a title="City Parks Programs" href="?city_parks_programs.cfm">City Parks Programs</a>
+			<ul style="display: none;">
+				<li><a href="?airdrie_horticulture_society.cfm" title="Airdrie Horticulture Society">Airdrie Horticulture Society</a></li>
+
+				<li><a href="?communities_in_bloom.cfm" title="Communities in Bloom">Communities in Bloom</a></li>
+				<li><a href="?community_garden.cfm" title="Community Garden">Community Garden</a></li>
+
+				<li class="last"><a href="?landscape_awards_program.cfm" title="Landscape Awards Program">Landscape Awards Program</a></li>
+			</ul>
+			</li>
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a title="Maintenance" href="?maintenance.cfm">Maintenance</a>
+
+			<ul style="display: none;">
+				<li><a href="?dandelions.cfm" title="Dandelions">Dandelions</a></li>
+				<li><a href="?gophers.cfm" title="Gophers">Gophers</a></li>
+
+				<li><a href="?grass_cutting.cfm" title="Grass Cutting">Grass Cutting</a></li>
+				<li class="last"><a href="?pathway_snow_removal.cfm" title="Pathway Snow Removal">Pathway Snow Removal</a></li>
+			</ul>
+
+			</li>
+			<li><a title="Maps" href="?/gis/index.cfm">Maps</a></li>
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a title="Outdoor Facilities" href="?outdoor_facilities.cfm">Outdoor Facilities</a>
+			<ul style="display: none;">
+
+				<li><a title="Ball Diamonds" href="?ball_diamonds.cfm">Ball Diamonds</a></li>
+				<li><a title="BMX Track" href="?bmx_track.cfm">BMX Track</a></li>
+
+				<li><a title="Bookings" href="?bookings.cfm">Bookings</a></li>
+				<li><a title="Cemetery" href="?cemetery.cfm">Cemetery</a></li>
+				<li><a title="Fire Pits" href="?fire_pits.cfm">Fire Pits</a></li>
+				<li><a title="Gwacheon Park" href="?/twinning_program/index.cfm#gwacheon">Gwacheon Park</a></li>
+
+				<li><a title="Off-Leash Areas" href="?off_leash_areas.cfm">Off-Leash Areas</a></li>
+				<li><a title="Outdoor Rinks" href="?outdoor_rinks.cfm">Outdoor Rinks</a></li>
+
+				<li><a title="Parks &amp; Playgrounds" href="?parks_playgrounds.cfm">Parks &amp; Playgrounds</a></li>
+				<li><a title="Skate Park" href="?skate_park.cfm">Skate Park</a></li>
+				<li><a title="Soccer/Athletic Fields" href="?soccer_athletic_fields.cfm">Soccer/Athletic Fields</a></li>
+				<li><a title="Splash Park" href="?splash_park.cfm">Splash Park</a></li>
+
+				<li class="last"><a title="Tennis Courts" href="?tennis_courts.cfm">Tennis Courts</a></li>
+
+			</ul>
+			</li>
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a title="Parks Planning &amp; Construction" href="?parks_planning_construction.cfm">Parks Planning &amp; Construction</a>
+			<ul style="display: none;">
+				<li><a href="?construction.cfm" title="Construction">Construction</a></li>
+				<li class="last"><a href="?plans.cfm" title="Plans">Plans</a></li>
+
+			</ul>
+			</li>
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a title="Urban Forest" href="?urban_forest.cfm">Urban Forest</a>
+			<ul style="display: none;">
+				<li><a href="?city_trees.cfm" title="City Trees">City Trees</a></li>
+				<li class="last"><a href="?tree_planting.cfm" title="Tree Planting">Tree Planting</a></li>
+			</ul>
+
+			</li>
+			<li class="expandable lastExpandable"><div class="hitarea expandable-hitarea lastExpandable-hitarea"></div><a title="Weeds &amp; Pests" href="?weeds_pests.cfm">Weeds &amp; Pests</a>
+			<ul style="display: none;">
+				<li><a href="?mosquito_control.cfm" title="Mosquito Control">Mosquito Control</a></li>
+				<li><a href="?pest_control.cfm" title="Pest Control">Pest Control</a></li>
+				<li class="last"><a href="?weed_control_plant_disease.cfm" title="Weed Control &amp; Plant Disease">Weed Control &amp; Plant Disease</a></li>
+
+			</ul>
+			</li>
+		</ul>
+		</li>
+		<li class="expandable lastExpandable"><div class="hitarea expandable-hitarea lastExpandable-hitarea"></div><a title="Sport &amp; Community Facilities" href="?/sport_community_facilities/index.cfm">Sport &amp; Community Facilities</a>
+		<ul style="display: none;">
+			<li class="expandable"><div class="hitarea expandable-hitarea"></div><a title="Indoor Facilities" href="?/sport_community_facilities/indoor_facilities.cfm">Indoor Facilities</a>
+
+			<ul style="display: none;">
+				<li><a title="Arenas/Gymnastics" href="?/sport_community_facilities/arenas_gymnastics.cfm">Arenas/Gymnastics</a></li>
+				<li><a title="Curling Rink" href="?/sport_community_facilities/curling_rink.cfm">Curling Rink</a></li>
+				<li><a title="East Lake Recreation &amp; Wellness Centre" href="?/elrwc/index.cfm">East Lake Recreation &amp; Wellness Centre</a></li>
+				<li><a title="Nose Creek Valley Museum" href="?/sport_community_facilities/nose_creek_valley_museum.cfm">Nose Creek Valley Museum</a></li>
+
+				<li><a title="Over 50 Club" href="?/sport_community_facilities/over_50_club.cfm">Over 50 Club</a></li>
+
+				<li class="last"><a title="Town &amp; Country" href="?/sport_community_facilities/town_country.cfm">Town &amp; Country</a></li>
+			</ul>
+			</li>
+			<li class="last"><a title="Outdoor Facilities" href="?/parks/outdoor_facilities.cfm">Outdoor Facilities</a></li>
+		</ul>
+
+		</li>
+	</ul>
+
+	</li>
+	<li class="expandable"><div class="hitarea expandable-hitarea"></div><strong><a href="?#">Visiting</a></strong>
+	<ul style="display: none;">
+		<li><a href="?/economic_development/video/index.cfm">Airdrie LIFE Video</a></li>
+		<li><a href="?/gis/recreation_map/index.cfm">Community Map</a></li>
+
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/events/index.cfm">Events</a>
+		<ul style="display: none;">
+
+			<li><a href="?http://www.airdriefestivaloflights.com" target="_new">Airdrie Festival of Lights</a></li>
+			<li><a href="?http://www.airdrieprorodeo.net/" target="_new">Airdrie Pro Rodeo</a></li>
+			<li class="last"><a href="?http://www.pch.gc.ca/special/canada/index_e.cfm" target="_new">Canada Day</a></li>
+		</ul>
+
+		</li>
+		<li><a href="?/parks/parks_recreation.cfm">Parks &amp; Recreation</a></li>
+
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/economic_development/tourist_information/tourist_information.cfm">Tourist Information</a>
+		<ul style="display: none;">
+			<li><a href="?/economic_development/entertainment/entertainment.cfm">Entertainment</a></li>
+			<li><a href="?/economic_development/hotels/hotels.cfm">Hotels</a></li>
+
+			<li><a href="?/economic_development/restaurants/restaurants.cfm">Restaurants</a></li>
+			<li><a href="?/economic_development/shopping/shopping.cfm">Shopping</a></li>
+
+			<li class="last"><a href="?http://www1.travelalberta.com/en-ab/index.cfm?country=CA&amp;state=AB&amp;setlocale=1" target="_new">Travel Alberta</a></li>
+		</ul>
+		</li>
+		<li class="last"><a href="?http://www.woodsidegc.com/contact.html" target="_new">Woodside Golf Course</a></li>
+
+	</ul>
+	</li>
+	<li class="expandable"><div class="hitarea expandable-hitarea"></div><strong><a href="?/economic_development/index.cfm">Doing Business</a></strong>
+
+	<ul style="display: none;">
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/economic_development/business_attraction/index.cfm">Business Attraction</a>
+		<ul style="display: none;">
+			<li><a href="?http://www.albertafirst.com/profiles/statspack/20365.html" target="_new">Airdrie Profile</a></li>
+
+			<li><a href="?/economic_development/business_attraction/business_case.cfm">Business Case For Airdrie</a></li>
+			<li><a href="?/economic_development/census/index.cfm">Census Data </a></li>
+			<li><a href="?http://www.albertafirst.com/realestate/" target="_new">Properties and Businesses For Sale</a></li>
+
+			<li class="last"><a href="?/taxation/non_residential_comparisons.cfm">Taxation</a></li>
+		</ul>
+		</li>
+
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/economic_development/business_development/index.cfm">Business Development</a>
+		<ul style="display: none;">
+			<li><a href="?/economic_development/business_development/business_associations.cfm">Business Associations</a></li>
+			<li><a href="?/economic_development/business_development/business_resources.cfm">Business Resources</a></li>
+
+			<li><a href="?/economic_development/business_development/business_services.cfm">Business Services</a></li>
+			<li><a href="?/corporate_properties/index.cfm">Corporate Properties</a></li>
+
+			<li class="last"><a href="?/economic_development/business_development/home_businesses.cfm">Home Based Businesses</a></li>
+		</ul>
+		</li>
+		<li><a href="?/directories/business_directory/index.cfm">Business Directory</a></li>
+
+		<li class="expandable"><div class="hitarea expandable-hitarea"></div><a href="?/economic_development/business_licenses/index.cfm">Business Licenses</a>
+		<ul style="display: none;">
+			<li><a href="?/economic_development/business_licenses/municipal_licenses_permits.cfm">Municipal Licenses &amp; Permits</a></li>
+
+			<li><a href="?/economic_development/business_licenses/provincial_licenses_permits.cfm">Provincial Licenses &amp; Permits</a></li>
+			<li class="last"><a href="?/economic_development/business_licenses/registry_services.cfm">Registry Services</a></li>
+
+		</ul>
+		</li>
+		<li><a href="?http://bsa.canadabusiness.ca/gol/bsa/site.nsf/en/index.html" target="_new">How to Start a Business</a></li>
+		<li class="last"><a href="?/finance/procurement_services.cfm">Procurement Services</a></li>
+
+	</ul>
+	</li>
+	<li class="last"><strong><a href="?https://vch.airdrie.ca/index.cfm">Online Services</a></strong></li>
+
+</ul>
+</div>
+
+</div>
+
+</body>
+
+</html>
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/screen.css b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/screen.css
new file mode 100644
index 0000000..f9bf38d
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/screen.css
@@ -0,0 +1,24 @@
+html, body {height:100%; margin: 0; padding: 0; }

+

+html>body {

+	font-size: 16px; 

+	font-size: 68.75%;

+} /* Reset Base Font Size */

+

+body {

+	font-family: Verdana, helvetica, arial, sans-serif;

+	font-size: 68.75%;

+	background: #fff;

+	color: #333;

+}

+

+h1, h2 { font-family: 'trebuchet ms', verdana, arial; padding: 10px; margin: 0 }

+h1 { font-size: large }

+

+#banner { padding: 15px; background-color: #06b; color: white; font-size: large; border-bottom: 1px solid #ccc;

+    background: url(bg.gif) repeat-x; text-align: center }

+#banner a { color: white; }

+

+#main { padding: 1em; }
+
+a img { border: none; }
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/simple.html b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/simple.html
new file mode 100644
index 0000000..6f208c8
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/simple.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+<html xmlns="http://www.w3.org/1999/xhtml">

+<head>

+

+	<meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/>

+	<title>jQuery treeView</title>

+	

+	<link rel="stylesheet" href="../jquery.treeview.css" />
+    <link rel="stylesheet" href="../red-treeview.css" />
+	<link rel="stylesheet" href="screen.css" />
+	
+	<script src="../lib/jquery.js" type="text/javascript"></script>
+	<script src="../lib/jquery.cookie.js" type="text/javascript"></script>
+	<script src="../jquery.treeview.js" type="text/javascript"></script>
+	

+	<script type="text/javascript">

+	$(document).ready(function(){

+		$("#browser").treeview({

+			toggle: function() {

+				console.log("%s was toggled.", $(this).find(">span").text());

+			}

+		});

+		

+		$("#add").click(function() {

+			var branches = $("<li><span class='folder'>New Sublist</span><ul>" + 

+				"<li><span class='file'>Item1</span></li>" + 

+				"<li><span class='file'>Item2</span></li></ul></li>").appendTo("#browser");

+			$("#browser").treeview({

+				add: branches

+			});

+		});

+	});

+	</script>

+	</head>

+	<body>

+	

+	<h1 id="banner"><a href="http://bassistance.de/jquery-plugins/jquery-plugin-treeview/">jQuery Treeview Plugin</a> Demo</h1>

+	<div id="main">
+	
+	<a href=".">Main Demo</a>

+		

+	<ul id="browser" class="filetree treeview-famfamfam">

+		<li><span class="folder">Folder 1</span>

+			<ul>

+				<li><span class="folder">Item 1.1</span>
+					<ul>
+						<li><span class="file">Item 1.1.1</span></li>
+					</ul>
+				</li>
+				<li><span class="folder">Folder 2</span>
+					<ul>
+						<li><span class="folder">Subfolder 2.1</span>
+							<ul id="folder21">
+								<li><span class="file">File 2.1.1</span></li>
+								<li><span class="file">File 2.1.2</span></li>
+							</ul>
+						</li>
+						<li><span class="folder">Subfolder 2.2</span>
+							<ul>
+								<li><span class="file">File 2.2.1</span></li>
+								<li><span class="file">File 2.2.2</span></li>
+							</ul>
+						</li>
+					</ul>
+				</li>
+				<li class="closed"><span class="folder">Folder 3 (closed at start)</span>
+					<ul>
+						<li><span class="file">File 3.1</span></li>
+					</ul>
+				</li>
+				<li><span class="file">File 4</span></li>

+			</ul>

+		</li>

+	</ul>

+	

+	<button id="add">Add!</button>

+	

+	<p>+/- Icons from <a href="http://www.famfamfam.com/lab/icons/">famfamfam</a></p>

+	

+</div>

+ 

+</body></html>
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/source.php b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/source.php
new file mode 100644
index 0000000..6b589d9
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/source.php
@@ -0,0 +1,87 @@
+<?php

+if ($_REQUEST['root'] == "source"):

+?>

+[

+	{

+		"text": "1. Pre Lunch (120 min)",

+		"expanded": true,

+		"classes": "important",

+		"children":

+		[

+			{

+				"text": "1.1 The State of the Powerdome (30 min)"

+			},

+		 	{

+				"text": "1.2 The Future of jQuery (30 min)"

+			},

+		 	{

+				"text": "1.2 jQuery UI - A step to richnessy (60 min)"

+			}

+		]

+	},

+	{

+		"text": "2. Lunch  (60 min)"

+	},

+	{

+		"text": "3. After Lunch  (120+ min)",

+		"children":

+		[

+			{

+				"text": "3.1 jQuery Calendar Success Story (20 min)"

+			},

+		 	{

+				"text": "3.2 jQuery and Ruby Web Frameworks (20 min)"

+			},

+		 	{

+				"text": "3.3 Hey, I Can Do That! (20 min)"

+			},

+		 	{

+				"text": "3.4 Taconite and Form (20 min)"

+			},

+		 	{

+				"text": "3.5 Server-side JavaScript with jQuery and AOLserver (20 min)"

+			},

+		 	{

+				"text": "3.6 The Onion: How to add features without adding features (20 min)",

+				"id": "36",

+				"hasChildren": true

+			},

+		 	{

+				"text": "3.7 Visualizations with JavaScript and Canvas (20 min)"

+			},

+		 	{

+				"text": "3.8 ActiveDOM (20 min)"

+			},

+		 	{

+				"text": "3.8 Growing jQuery (20 min)"

+			}

+		]

+	}

+]

+<?php else: ?>

+[

+	{

+		"text": "1. Review of existing structures",

+		"expanded": true,

+		"children":

+		[

+			{

+				"text": "1.1 jQuery core"

+			},

+		 	{

+				"text": "1.2 metaplugins"

+			}

+		]

+	},

+	{

+		"text": "2. Wrapper plugins"

+	},

+	{

+		"text": "3. Summary"

+	},

+	{

+		"text": "4. Questions and answers"

+	}

+	

+]

+<?php endif; ?>
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/source.phps b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/source.phps
new file mode 100644
index 0000000..6b589d9
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/demo/source.phps
@@ -0,0 +1,87 @@
+<?php

+if ($_REQUEST['root'] == "source"):

+?>

+[

+	{

+		"text": "1. Pre Lunch (120 min)",

+		"expanded": true,

+		"classes": "important",

+		"children":

+		[

+			{

+				"text": "1.1 The State of the Powerdome (30 min)"

+			},

+		 	{

+				"text": "1.2 The Future of jQuery (30 min)"

+			},

+		 	{

+				"text": "1.2 jQuery UI - A step to richnessy (60 min)"

+			}

+		]

+	},

+	{

+		"text": "2. Lunch  (60 min)"

+	},

+	{

+		"text": "3. After Lunch  (120+ min)",

+		"children":

+		[

+			{

+				"text": "3.1 jQuery Calendar Success Story (20 min)"

+			},

+		 	{

+				"text": "3.2 jQuery and Ruby Web Frameworks (20 min)"

+			},

+		 	{

+				"text": "3.3 Hey, I Can Do That! (20 min)"

+			},

+		 	{

+				"text": "3.4 Taconite and Form (20 min)"

+			},

+		 	{

+				"text": "3.5 Server-side JavaScript with jQuery and AOLserver (20 min)"

+			},

+		 	{

+				"text": "3.6 The Onion: How to add features without adding features (20 min)",

+				"id": "36",

+				"hasChildren": true

+			},

+		 	{

+				"text": "3.7 Visualizations with JavaScript and Canvas (20 min)"

+			},

+		 	{

+				"text": "3.8 ActiveDOM (20 min)"

+			},

+		 	{

+				"text": "3.8 Growing jQuery (20 min)"

+			}

+		]

+	}

+]

+<?php else: ?>

+[

+	{

+		"text": "1. Review of existing structures",

+		"expanded": true,

+		"children":

+		[

+			{

+				"text": "1.1 jQuery core"

+			},

+		 	{

+				"text": "1.2 metaplugins"

+			}

+		]

+	},

+	{

+		"text": "2. Wrapper plugins"

+	},

+	{

+		"text": "3. Summary"

+	},

+	{

+		"text": "4. Questions and answers"

+	}

+	

+]

+<?php endif; ?>
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/file.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/file.gif
new file mode 100644
index 0000000..c83b824
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/file.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/folder-closed.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/folder-closed.gif
new file mode 100644
index 0000000..596f752
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/folder-closed.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/folder.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/folder.gif
new file mode 100644
index 0000000..e5fd557
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/folder.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/minus.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/minus.gif
new file mode 100644
index 0000000..7ec89a8
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/minus.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/plus.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/plus.gif
new file mode 100644
index 0000000..1a096f5
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/plus.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-black-line.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-black-line.gif
new file mode 100644
index 0000000..069e58d
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-black-line.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-black.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-black.gif
new file mode 100644
index 0000000..6d51cad
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-black.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-default-line.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-default-line.gif
new file mode 100644
index 0000000..b3be066
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-default-line.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-default.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-default.gif
new file mode 100644
index 0000000..92d139b
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-default.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-famfamfam-line.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-famfamfam-line.gif
new file mode 100644
index 0000000..fa31b6f
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-famfamfam-line.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-famfamfam.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-famfamfam.gif
new file mode 100644
index 0000000..4cc3e83
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-famfamfam.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-gray-line.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-gray-line.gif
new file mode 100644
index 0000000..7b34160
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-gray-line.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-gray.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-gray.gif
new file mode 100644
index 0000000..be0dda3
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-gray.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-red-line.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-red-line.gif
new file mode 100644
index 0000000..24191de
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-red-line.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-red.gif b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-red.gif
new file mode 100644
index 0000000..74ca136
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/images/treeview-red.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.async.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.async.js
new file mode 100644
index 0000000..502de51
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.async.js
@@ -0,0 +1,72 @@
+/*

+ * Async Treeview 0.1 - Lazy-loading extension for Treeview

+ * 

+ * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/

+ *

+ * Copyright (c) 2007 Jörn Zaefferer

+ *

+ * Dual licensed under the MIT and GPL licenses:

+ *   http://www.opensource.org/licenses/mit-license.php

+ *   http://www.gnu.org/licenses/gpl.html

+ *

+ * Revision: $Id$

+ *

+ */

+

+;(function($) {

+

+function load(settings, root, child, container) {

+	$.getJSON(settings.url, {root: root}, function(response) {

+		function createNode(parent) {

+			var current = $("<li/>").attr("id", this.id || "").html("<span>" + this.text + "</span>").appendTo(parent);

+			if (this.classes) {

+				current.children("span").addClass(this.classes);

+			}

+			if (this.expanded) {

+				current.addClass("open");

+			}

+			if (this.hasChildren || this.children && this.children.length) {

+				var branch = $("<ul/>").appendTo(current);

+				if (this.hasChildren) {

+					current.addClass("hasChildren");

+					createNode.call({

+						text:"placeholder",

+						id:"placeholder",

+						children:[]

+					}, branch);

+				}

+				if (this.children && this.children.length) {

+					$.each(this.children, createNode, [branch])

+				}

+			}

+		}

+		$.each(response, createNode, [child]);

+        $(container).treeview({add: child});

+    });

+}

+

+var proxied = $.fn.treeview;

+$.fn.treeview = function(settings) {

+	if (!settings.url) {

+		return proxied.apply(this, arguments);

+	}

+	var container = this;

+	load(settings, "source", this, container);

+	var userToggle = settings.toggle;

+	return proxied.call(this, $.extend({}, settings, {

+		collapsed: true,

+		toggle: function() {

+			var $this = $(this);

+			if ($this.hasClass("hasChildren")) {

+				var childList = $this.removeClass("hasChildren").find("ul");

+				childList.empty();

+				load(settings, this.id, childList, container);

+			}

+			if (userToggle) {

+				userToggle.apply(this, arguments);

+			}

+		}

+	}));

+};

+

+})(jQuery);
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.css b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.css
new file mode 100644
index 0000000..4a91096
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.css
@@ -0,0 +1,68 @@
+.treeview, .treeview ul { 

+	padding: 0;

+	margin: 0;

+	list-style: none;
+}
+
+.treeview ul {
+	background-color: white;
+	margin-top: 4px;
+}

+

+.treeview .hitarea {

+	background: url(images/treeview-default.gif) -64px -25px no-repeat;

+	height: 16px;

+	width: 16px;

+	margin-left: -16px;

+	float: left;

+	cursor: pointer;

+}

+/* fix for IE6 */

+* html .hitarea {

+	display: inline;

+	float:none;
+}

+

+.treeview li { 

+	margin: 0;

+	padding: 3px 0pt 3px 16px;

+}

+

+.treeview a.selected {

+	background-color: #eee;

+}

+

+#treecontrol { margin: 1em 0; display: none; }

+

+.treeview .hover { color: red; cursor: pointer; }

+

+.treeview li { background: url(images/treeview-default-line.gif) 0 0 no-repeat; }

+.treeview li.collapsable, .treeview li.expandable { background-position: 0 -176px; }

+

+.treeview .expandable-hitarea { background-position: -80px -3px; }

+

+.treeview li.last { background-position: 0 -1766px }

+.treeview li.lastCollapsable, .treeview li.lastExpandable { background-image: url(images/treeview-default.gif); }  
+.treeview li.lastCollapsable { background-position: 0 -111px }
+.treeview li.lastExpandable { background-position: -32px -67px }

+

+.treeview div.lastCollapsable-hitarea, .treeview div.lastExpandable-hitarea { background-position: 0; }
+

+.treeview-red li { background-image: url(images/treeview-red-line.gif); }

+.treeview-red .hitarea, .treeview-red li.lastCollapsable, .treeview-red li.lastExpandable { background-image: url(images/treeview-red.gif); } 

+

+.treeview-black li { background-image: url(images/treeview-black-line.gif); }

+.treeview-black .hitarea, .treeview-black li.lastCollapsable, .treeview-black li.lastExpandable { background-image: url(images/treeview-black.gif); }  

+

+.treeview-gray li { background-image: url(images/treeview-gray-line.gif); }

+.treeview-gray .hitarea, .treeview-gray li.lastCollapsable, .treeview-gray li.lastExpandable { background-image: url(images/treeview-gray.gif); } 

+

+.treeview-famfamfam li { background-image: url(images/treeview-famfamfam-line.gif); }

+.treeview-famfamfam .hitarea, .treeview-famfamfam li.lastCollapsable, .treeview-famfamfam li.lastExpandable { background-image: url(images/treeview-famfamfam.gif); } 

+

+

+.filetree li { padding: 3px 0 2px 16px; }

+.filetree span.folder, .filetree span.file { padding: 1px 0 1px 16px; display: block; }

+.filetree span.folder { background: url(images/folder.gif) 0 0 no-repeat; }

+.filetree li.expandable span.folder { background: url(images/folder-closed.gif) 0 0 no-repeat; }

+.filetree span.file { background: url(images/file.gif) 0 0 no-repeat; }

diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.js
new file mode 100644
index 0000000..96e686a
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.js
@@ -0,0 +1,251 @@
+/*
+ * Treeview 1.4 - jQuery plugin to hide and show branches of a tree
+ * 
+ * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
+ * http://docs.jquery.com/Plugins/Treeview
+ *
+ * Copyright (c) 2007 Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id: jquery.treeview.js 4684 2008-02-07 19:08:06Z joern.zaefferer $
+ *
+ */
+
+;(function($) {
+
+	$.extend($.fn, {
+		swapClass: function(c1, c2) {
+			var c1Elements = this.filter('.' + c1);
+			this.filter('.' + c2).removeClass(c2).addClass(c1);
+			c1Elements.removeClass(c1).addClass(c2);
+			return this;
+		},
+		replaceClass: function(c1, c2) {
+			return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
+		},
+		hoverClass: function(className) {
+			className = className || "hover";
+			return this.hover(function() {
+				$(this).addClass(className);
+			}, function() {
+				$(this).removeClass(className);
+			});
+		},
+		heightToggle: function(animated, callback) {
+			animated ?
+				this.animate({ height: "toggle" }, animated, callback) :
+				this.each(function(){
+					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
+					if(callback)
+						callback.apply(this, arguments);
+				});
+		},
+		heightHide: function(animated, callback) {
+			if (animated) {
+				this.animate({ height: "hide" }, animated, callback);
+			} else {
+				this.hide();
+				if (callback)
+					this.each(callback);				
+			}
+		},
+		prepareBranches: function(settings) {
+			if (!settings.prerendered) {
+				// mark last tree items
+				this.filter(":last-child:not(ul)").addClass(CLASSES.last);
+				// collapse whole tree, or only those marked as closed, anyway except those marked as open
+				this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
+			}
+			// return all items with sublists
+			return this.filter(":has(>ul)");
+		},
+		applyClasses: function(settings, toggler) {
+			this.filter(":has(>ul):not(:has(>a))").find(">span").click(function(event) {
+				toggler.apply($(this).next());
+			}).add( $("a", this) ).hoverClass();
+			
+			if (!settings.prerendered) {
+				// handle closed ones first
+				this.filter(":has(>ul:hidden)")
+						.addClass(CLASSES.expandable)
+						.replaceClass(CLASSES.last, CLASSES.lastExpandable);
+						
+				// handle open ones
+				this.not(":has(>ul:hidden)")
+						.addClass(CLASSES.collapsable)
+						.replaceClass(CLASSES.last, CLASSES.lastCollapsable);
+						
+	            // create hitarea
+				this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea).each(function() {
+					var classes = "";
+					$.each($(this).parent().attr("class").split(" "), function() {
+						classes += this + "-hitarea ";
+					});
+					$(this).addClass( classes );
+				});
+			}
+			
+			// apply event to hitarea
+			this.find("div." + CLASSES.hitarea).click( toggler );
+		},
+		treeview: function(settings) {
+			
+			settings = $.extend({
+				cookieId: "treeview"
+			}, settings);
+			
+			if (settings.add) {
+				return this.trigger("add", [settings.add]);
+			}
+			
+			if ( settings.toggle ) {
+				var callback = settings.toggle;
+				settings.toggle = function() {
+					return callback.apply($(this).parent()[0], arguments);
+				};
+			}
+		
+			// factory for treecontroller
+			function treeController(tree, control) {
+				// factory for click handlers
+				function handler(filter) {
+					return function() {
+						// reuse toggle event handler, applying the elements to toggle
+						// start searching for all hitareas
+						toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
+							// for plain toggle, no filter is provided, otherwise we need to check the parent element
+							return filter ? $(this).parent("." + filter).length : true;
+						}) );
+						return false;
+					};
+				}
+				// click on first element to collapse tree
+				$("a:eq(0)", control).click( handler(CLASSES.collapsable) );
+				// click on second to expand tree
+				$("a:eq(1)", control).click( handler(CLASSES.expandable) );
+				// click on third to toggle tree
+				$("a:eq(2)", control).click( handler() ); 
+			}
+		
+			// handle toggle event
+			function toggler() {
+				$(this)
+					.parent()
+					// swap classes for hitarea
+					.find(">.hitarea")
+						.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+						.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
+					.end()
+					// swap classes for parent li
+					.swapClass( CLASSES.collapsable, CLASSES.expandable )
+					.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+					// find child lists
+					.find( ">ul" )
+					// toggle them
+					.heightToggle( settings.animated, settings.toggle );
+				if ( settings.unique ) {
+					$(this).parent()
+						.siblings()
+						// swap classes for hitarea
+						.find(">.hitarea")
+							.replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+							.replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
+						.end()
+						.replaceClass( CLASSES.collapsable, CLASSES.expandable )
+						.replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+						.find( ">ul" )
+						.heightHide( settings.animated, settings.toggle );
+				}
+			}
+			
+			function serialize() {
+				function binary(arg) {
+					return arg ? 1 : 0;
+				}
+				var data = [];
+				branches.each(function(i, e) {
+					data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
+				});
+				$.cookie(settings.cookieId, data.join("") );
+			}
+			
+			function deserialize() {
+				var stored = $.cookie(settings.cookieId);
+				if ( stored ) {
+					var data = stored.split("");
+					branches.each(function(i, e) {
+						$(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
+					});
+				}
+			}
+			
+			// add treeview class to activate styles
+			this.addClass("treeview");
+			
+			// prepare branches and find all tree items with child lists
+			var branches = this.find("li").prepareBranches(settings);
+			
+			switch(settings.persist) {
+			case "cookie":
+				var toggleCallback = settings.toggle;
+				settings.toggle = function() {
+					serialize();
+					if (toggleCallback) {
+						toggleCallback.apply(this, arguments);
+					}
+				};
+				deserialize();
+				break;
+			case "location":
+				var current = this.find("a").filter(function() { return this.href.toLowerCase() == location.href.toLowerCase(); });
+				if ( current.length ) {
+					current.addClass("selected").parents("ul, li").add( current.next() ).show();
+				}
+				break;
+			}
+			
+			branches.applyClasses(settings, toggler);
+				
+			// if control option is set, create the treecontroller and show it
+			if ( settings.control ) {
+				treeController(this, settings.control);
+				$(settings.control).show();
+			}
+			
+			return this.bind("add", function(event, branches) {
+				$(branches).prev()
+					.removeClass(CLASSES.last)
+					.removeClass(CLASSES.lastCollapsable)
+					.removeClass(CLASSES.lastExpandable)
+				.find(">.hitarea")
+					.removeClass(CLASSES.lastCollapsableHitarea)
+					.removeClass(CLASSES.lastExpandableHitarea);
+				$(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings, toggler);
+			});
+		}
+	});
+	
+	// classes used by the plugin
+	// need to be styled via external stylesheet, see first example
+	var CLASSES = $.fn.treeview.classes = {
+		open: "open",
+		closed: "closed",
+		expandable: "expandable",
+		expandableHitarea: "expandable-hitarea",
+		lastExpandableHitarea: "lastExpandable-hitarea",
+		collapsable: "collapsable",
+		collapsableHitarea: "collapsable-hitarea",
+		lastCollapsableHitarea: "lastCollapsable-hitarea",
+		lastCollapsable: "lastCollapsable",
+		lastExpandable: "lastExpandable",
+		last: "last",
+		hitarea: "hitarea"
+	};
+	
+	// provide backwards compability
+	$.fn.Treeview = $.fn.treeview;
+	
+})(jQuery);
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.min.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.min.js
new file mode 100644
index 0000000..5b3861a
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.min.js
@@ -0,0 +1,15 @@
+/*
+ * Treeview 1.4 - jQuery plugin to hide and show branches of a tree
+ * 
+ * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
+ * http://docs.jquery.com/Plugins/Treeview
+ *
+ * Copyright (c) 2007 Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id: jquery.treeview.js 4684 2008-02-07 19:08:06Z joern.zaefferer $
+ *
+ */;(function($){$.extend($.fn,{swapClass:function(c1,c2){var c1Elements=this.filter('.'+c1);this.filter('.'+c2).removeClass(c2).addClass(c1);c1Elements.removeClass(c1).addClass(c2);return this;},replaceClass:function(c1,c2){return this.filter('.'+c1).removeClass(c1).addClass(c2).end();},hoverClass:function(className){className=className||"hover";return this.hover(function(){$(this).addClass(className);},function(){$(this).removeClass(className);});},heightToggle:function(animated,callback){animated?this.animate({height:"toggle"},animated,callback):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();if(callback)callback.apply(this,arguments);});},heightHide:function(animated,callback){if(animated){this.animate({height:"hide"},animated,callback);}else{this.hide();if(callback)this.each(callback);}},prepareBranches:function(settings){if(!settings.prerendered){this.filter(":last-child:not(ul)").addClass(CLASSES.last);this.filter((settings.collapsed?"":"."+CLASSES.closed)+":not(."+CLASSES.open+")").find(">ul").hide();}return this.filter(":has(>ul)");},applyClasses:function(settings,toggler){this.filter(":has(>ul):not(:has(>a))").find(">span").click(function(event){toggler.apply($(this).next());}).add($("a",this)).hoverClass();if(!settings.prerendered){this.filter(":has(>ul:hidden)").addClass(CLASSES.expandable).replaceClass(CLASSES.last,CLASSES.lastExpandable);this.not(":has(>ul:hidden)").addClass(CLASSES.collapsable).replaceClass(CLASSES.last,CLASSES.lastCollapsable);this.prepend("<div class=\""+CLASSES.hitarea+"\"/>").find("div."+CLASSES.hitarea).each(function(){var classes="";$.each($(this).parent().attr("class").split(" "),function(){classes+=this+"-hitarea ";});$(this).addClass(classes);});}this.find("div."+CLASSES.hitarea).click(toggler);},treeview:function(settings){settings=$.extend({cookieId:"treeview"},settings);if(settings.add){return this.trigger("add",[settings.add]);}if(settings.toggle){var callback=settings.toggle;settings.toggle=function(){return callback.apply($(this).parent()[0],arguments);};}function treeController(tree,control){function handler(filter){return function(){toggler.apply($("div."+CLASSES.hitarea,tree).filter(function(){return filter?$(this).parent("."+filter).length:true;}));return false;};}$("a:eq(0)",control).click(handler(CLASSES.collapsable));$("a:eq(1)",control).click(handler(CLASSES.expandable));$("a:eq(2)",control).click(handler());}function toggler(){$(this).parent().find(">.hitarea").swapClass(CLASSES.collapsableHitarea,CLASSES.expandableHitarea).swapClass(CLASSES.lastCollapsableHitarea,CLASSES.lastExpandableHitarea).end().swapClass(CLASSES.collapsable,CLASSES.expandable).swapClass(CLASSES.lastCollapsable,CLASSES.lastExpandable).find(">ul").heightToggle(settings.animated,settings.toggle);if(settings.unique){$(this).parent().siblings().find(">.hitarea").replaceClass(CLASSES.collapsableHitarea,CLASSES.expandableHitarea).replaceClass(CLASSES.lastCollapsableHitarea,CLASSES.lastExpandableHitarea).end().replaceClass(CLASSES.collapsable,CLASSES.expandable).replaceClass(CLASSES.lastCollapsable,CLASSES.lastExpandable).find(">ul").heightHide(settings.animated,settings.toggle);}}function serialize(){function binary(arg){return arg?1:0;}var data=[];branches.each(function(i,e){data[i]=$(e).is(":has(>ul:visible)")?1:0;});$.cookie(settings.cookieId,data.join(""));}function deserialize(){var stored=$.cookie(settings.cookieId);if(stored){var data=stored.split("");branches.each(function(i,e){$(e).find(">ul")[parseInt(data[i])?"show":"hide"]();});}}this.addClass("treeview");var branches=this.find("li").prepareBranches(settings);switch(settings.persist){case"cookie":var toggleCallback=settings.toggle;settings.toggle=function(){serialize();if(toggleCallback){toggleCallback.apply(this,arguments);}};deserialize();break;case"location":var current=this.find("a").filter(function(){return this.href.toLowerCase()==location.href.toLowerCase();});if(current.length){current.addClass("selected").parents("ul, li").add(current.next()).show();}break;}branches.applyClasses(settings,toggler);if(settings.control){treeController(this,settings.control);$(settings.control).show();}return this.bind("add",function(event,branches){$(branches).prev().removeClass(CLASSES.last).removeClass(CLASSES.lastCollapsable).removeClass(CLASSES.lastExpandable).find(">.hitarea").removeClass(CLASSES.lastCollapsableHitarea).removeClass(CLASSES.lastExpandableHitarea);$(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings,toggler);});}});var CLASSES=$.fn.treeview.classes={open:"open",closed:"closed",expandable:"expandable",expandableHitarea:"expandable-hitarea",lastExpandableHitarea:"lastExpandable-hitarea",collapsable:"collapsable",collapsableHitarea:"collapsable-hitarea",lastCollapsableHitarea:"lastCollapsable-hitarea",lastCollapsable:"lastCollapsable",lastExpandable:"lastExpandable",last:"last",hitarea:"hitarea"};$.fn.Treeview=$.fn.treeview;})(jQuery);
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.pack.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.pack.js
new file mode 100644
index 0000000..90407ce
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/jquery.treeview.pack.js
@@ -0,0 +1,16 @@
+/*
+ * Treeview 1.4 - jQuery plugin to hide and show branches of a tree
+ * 
+ * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
+ * http://docs.jquery.com/Plugins/Treeview
+ *
+ * Copyright (c) 2007 Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id: jquery.treeview.js 4684 2008-02-07 19:08:06Z joern.zaefferer $
+ *
+ */
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}(';(4($){$.1l($.F,{E:4(b,c){l a=3.n(\'.\'+b);3.n(\'.\'+c).o(c).m(b);a.o(b).m(c);8 3},s:4(a,b){8 3.n(\'.\'+a).o(a).m(b).P()},1n:4(a){a=a||"1j";8 3.1j(4(){$(3).m(a)},4(){$(3).o(a)})},1h:4(b,a){b?3.1g({1e:"p"},b,a):3.x(4(){T(3)[T(3).1a(":U")?"H":"D"]();7(a)a.A(3,O)})},12:4(b,a){7(b){3.1g({1e:"D"},b,a)}1L{3.D();7(a)3.x(a)}},11:4(a){7(!a.1k){3.n(":r-1H:G(9)").m(k.r);3.n((a.1F?"":"."+k.X)+":G(."+k.W+")").6(">9").D()}8 3.n(":y(>9)")},S:4(b,c){3.n(":y(>9):G(:y(>a))").6(">1z").C(4(a){c.A($(3).19())}).w($("a",3)).1n();7(!b.1k){3.n(":y(>9:U)").m(k.q).s(k.r,k.t);3.G(":y(>9:U)").m(k.u).s(k.r,k.v);3.1r("<J 14=\\""+k.5+"\\"/>").6("J."+k.5).x(4(){l a="";$.x($(3).B().1o("14").13(" "),4(){a+=3+"-5 "});$(3).m(a)})}3.6("J."+k.5).C(c)},z:4(g){g=$.1l({N:"z"},g);7(g.w){8 3.1K("w",[g.w])}7(g.p){l d=g.p;g.p=4(){8 d.A($(3).B()[0],O)}}4 1m(b,c){4 L(a){8 4(){K.A($("J."+k.5,b).n(4(){8 a?$(3).B("."+a).1i:1I}));8 1G}}$("a:10(0)",c).C(L(k.u));$("a:10(1)",c).C(L(k.q));$("a:10(2)",c).C(L())}4 K(){$(3).B().6(">.5").E(k.Z,k.Y).E(k.I,k.M).P().E(k.u,k.q).E(k.v,k.t).6(">9").1h(g.1f,g.p);7(g.1E){$(3).B().1D().6(">.5").s(k.Z,k.Y).s(k.I,k.M).P().s(k.u,k.q).s(k.v,k.t).6(">9").12(g.1f,g.p)}}4 1d(){4 1C(a){8 a?1:0}l b=[];j.x(4(i,e){b[i]=$(e).1a(":y(>9:1B)")?1:0});$.V(g.N,b.1A(""))}4 1c(){l b=$.V(g.N);7(b){l a=b.13("");j.x(4(i,e){$(e).6(">9")[1y(a[i])?"H":"D"]()})}}3.m("z");l j=3.6("Q").11(g);1x(g.1w){18"V":l h=g.p;g.p=4(){1d();7(h){h.A(3,O)}};1c();17;18"1b":l f=3.6("a").n(4(){8 3.16.15()==1b.16.15()});7(f.1i){f.m("1v").1u("9, Q").w(f.19()).H()}17}j.S(g,K);7(g.R){1m(3,g.R);$(g.R).H()}8 3.1t("w",4(a,b){$(b).1s().o(k.r).o(k.v).o(k.t).6(">.5").o(k.I).o(k.M);$(b).6("Q").1q().11(g).S(g,K)})}});l k=$.F.z.1J={W:"W",X:"X",q:"q",Y:"q-5",M:"t-5",u:"u",Z:"u-5",I:"v-5",v:"v",t:"t",r:"r",5:"5"};$.F.1p=$.F.z})(T);',62,110,'|||this|function|hitarea|find|if|return|ul||||||||||||var|addClass|filter|removeClass|toggle|expandable|last|replaceClass|lastExpandable|collapsable|lastCollapsable|add|each|has|treeview|apply|parent|click|hide|swapClass|fn|not|show|lastCollapsableHitarea|div|toggler|handler|lastExpandableHitarea|cookieId|arguments|end|li|control|applyClasses|jQuery|hidden|cookie|open|closed|expandableHitarea|collapsableHitarea|eq|prepareBranches|heightHide|split|class|toLowerCase|href|break|case|next|is|location|deserialize|serialize|height|animated|animate|heightToggle|length|hover|prerendered|extend|treeController|hoverClass|attr|Treeview|andSelf|prepend|prev|bind|parents|selected|persist|switch|parseInt|span|join|visible|binary|siblings|unique|collapsed|false|child|true|classes|trigger|else'.split('|'),0,{}))
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/lib/jquery.cookie.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/lib/jquery.cookie.js
new file mode 100644
index 0000000..db69218
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/lib/jquery.cookie.js
@@ -0,0 +1,92 @@
+/**
+ * Cookie plugin
+ *
+ * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+/**
+ * Create a cookie with the given name and value and other optional parameters.
+ *
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Set the value of a cookie.
+ * @example $.cookie('the_cookie', 'the_value', {expires: 7, path: '/', domain: 'jquery.com', secure: true});
+ * @desc Create a cookie with all available options.
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Create a session cookie.
+ * @example $.cookie('the_cookie', null);
+ * @desc Delete a cookie by passing null as value.
+ *
+ * @param String name The name of the cookie.
+ * @param String value The value of the cookie.
+ * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
+ * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
+ *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
+ *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
+ *                             when the the browser exits.
+ * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
+ * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
+ * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
+ *                        require a secure protocol (like HTTPS).
+ * @type undefined
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+
+/**
+ * Get the value of a cookie with the given name.
+ *
+ * @example $.cookie('the_cookie');
+ * @desc Get the value of a cookie.
+ *
+ * @param String name The name of the cookie.
+ * @return The value of the cookie.
+ * @type String
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+jQuery.cookie = function(name, value, options) {
+    if (typeof value != 'undefined') { // name and value given, set cookie
+        options = options || {};
+        if (value === null) {
+            value = '';
+            options.expires = -1;
+        }
+        var expires = '';
+        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
+            var date;
+            if (typeof options.expires == 'number') {
+                date = new Date();
+                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
+            } else {
+                date = options.expires;
+            }
+            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
+        }
+        var path = options.path ? '; path=' + options.path : '';
+        var domain = options.domain ? '; domain=' + options.domain : '';
+        var secure = options.secure ? '; secure' : '';
+        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
+    } else { // only name given, get cookie
+        var cookieValue = null;
+        if (document.cookie && document.cookie != '') {
+            var cookies = document.cookie.split(';');
+            for (var i = 0; i < cookies.length; i++) {
+                var cookie = jQuery.trim(cookies[i]);
+                // Does this cookie string begin with the name we want?
+                if (cookie.substring(0, name.length + 1) == (name + '=')) {
+                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
+                    break;
+                }
+            }
+        }
+        return cookieValue;
+    }
+};
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/lib/jquery.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/lib/jquery.js
new file mode 100644
index 0000000..b660baa
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/lib/jquery.js
@@ -0,0 +1,3363 @@
+(function(){
+/*
+ * jQuery 1.2.2b2 - New Wave Javascript
+ *
+ * Copyright (c) 2007 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2007-12-20 14:36:56 +0100 (Don, 20 Dez 2007) $
+ * $Rev: 4251 $
+ */
+
+// Map over jQuery in case of overwrite
+if ( window.jQuery )
+	var _jQuery = window.jQuery;
+
+var jQuery = window.jQuery = function( selector, context ) {
+	// The jQuery object is actually just the init constructor 'enhanced'
+	return new jQuery.prototype.init( selector, context );
+};
+
+// Map over the $ in case of overwrite
+if ( window.$ )
+	var _$ = window.$;
+	
+// Map the jQuery namespace to the '$' one
+window.$ = jQuery;
+
+// A simple way to check for HTML strings or ID strings
+// (both of which we optimize for)
+var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
+
+// Is it a simple selector
+var isSimple = /^.[^:#\[\.]*$/;
+
+jQuery.fn = jQuery.prototype = {
+	init: function( selector, context ) {
+		// Make sure that a selection was provided
+		selector = selector || document;
+
+		// Handle $(DOMElement)
+		if ( selector.nodeType ) {
+			this[0] = selector;
+			this.length = 1;
+			return this;
+
+		// Handle HTML strings
+		} else if ( typeof selector == "string" ) {
+			// Are we dealing with HTML string or an ID?
+			var match = quickExpr.exec( selector );
+
+			// Verify a match, and that no context was specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] )
+					selector = jQuery.clean( [ match[1] ], context );
+
+				// HANDLE: $("#id")
+				else {
+					var elem = document.getElementById( match[3] );
+
+					// Make sure an element was located
+					if ( elem )
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id != match[3] )
+							return jQuery().find( selector );
+
+						// Otherwise, we inject the element directly into the jQuery object
+						else {
+							this[0] = elem;
+							this.length = 1;
+							return this;
+						}
+
+					else
+						selector = [];
+				}
+
+			// HANDLE: $(expr, [context])
+			// (which is just equivalent to: $(content).find(expr)
+			} else
+				return new jQuery( context ).find( selector );
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) )
+			return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
+
+		return this.setArray(
+			// HANDLE: $(array)
+			selector.constructor == Array && selector ||
+
+			// HANDLE: $(arraylike)
+			// Watch for when an array-like object, contains DOM nodes, is passed in as the selector
+			(selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) ||
+
+			// HANDLE: $(*)
+			[ selector ] );
+	},
+	
+	// The current version of jQuery being used
+	jquery: "@VERSION",
+
+	// The number of elements contained in the matched element set
+	size: function() {
+		return this.length;
+	},
+	
+	// The number of elements contained in the matched element set
+	length: 0,
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num == undefined ?
+
+			// Return a 'clean' array
+			jQuery.makeArray( this ) :
+
+			// Return just the object
+			this[ num ];
+	},
+	
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems ) {
+		// Build a new jQuery matched element set
+		var ret = jQuery( elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		// Return the newly-formed element set
+		return ret;
+	},
+	
+	// Force the current matched set of elements to become
+	// the specified array of elements (destroying the stack in the process)
+	// You should use pushStack() in order to do this, but maintain the stack
+	setArray: function( elems ) {
+		// Resetting the length to 0, then using the native Array push
+		// is a super-fast way to populate an object with array-like properties
+		this.length = 0;
+		Array.prototype.push.apply( this, elems );
+		
+		return this;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	// Determine the position of an element within 
+	// the matched set of elements
+	index: function( elem ) {
+		var ret = -1;
+
+		// Locate the position of the desired element
+		this.each(function(i){
+			if ( this == elem )
+				ret = i;
+		});
+
+		return ret;
+	},
+
+	attr: function( name, value, type ) {
+		var options = name;
+		
+		// Look for the case where we're accessing a style value
+		if ( name.constructor == String )
+			if ( value == undefined )
+				return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined;
+
+			else {
+				options = {};
+				options[ name ] = value;
+			}
+		
+		// Check to see if we're setting style values
+		return this.each(function(i){
+			// Set all the styles
+			for ( name in options )
+				jQuery.attr(
+					type ?
+						this.style :
+						this,
+					name, jQuery.prop( this, options[ name ], type, i, name )
+				);
+		});
+	},
+
+	css: function( key, value ) {
+		// ignore negative width and height values
+		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
+			value = undefined;
+		return this.attr( key, value, "curCSS" );
+	},
+
+	text: function( text ) {
+		if ( typeof text != "object" && text != null )
+			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+
+		var ret = "";
+
+		jQuery.each( text || this, function(){
+			jQuery.each( this.childNodes, function(){
+				if ( this.nodeType != 8 )
+					ret += this.nodeType != 1 ?
+						this.nodeValue :
+						jQuery.fn.text( [ this ] );
+			});
+		});
+
+		return ret;
+	},
+
+	wrapAll: function( html ) {
+		if ( this[0] )
+			// The elements to wrap the target around
+			jQuery( html, this[0].ownerDocument )
+				.clone()
+				.insertBefore( this[0] )
+				.map(function(){
+					var elem = this;
+
+					while ( elem.firstChild )
+						elem = elem.firstChild;
+
+					return elem;
+				})
+				.append(this);
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		return this.each(function(){
+			jQuery( this ).contents().wrapAll( html );
+		});
+	},
+
+	wrap: function( html ) {
+		return this.each(function(){
+			jQuery( this ).wrapAll( html );
+		});
+	},
+
+	append: function() {
+		return this.domManip(arguments, true, false, function(elem){
+			if (this.nodeType == 1)
+				this.appendChild( elem );
+		});
+	},
+
+	prepend: function() {
+		return this.domManip(arguments, true, true, function(elem){
+			if (this.nodeType == 1)
+				this.insertBefore( elem, this.firstChild );
+		});
+	},
+	
+	before: function() {
+		return this.domManip(arguments, false, false, function(elem){
+			this.parentNode.insertBefore( elem, this );
+		});
+	},
+
+	after: function() {
+		return this.domManip(arguments, false, true, function(elem){
+			this.parentNode.insertBefore( elem, this.nextSibling );
+		});
+	},
+
+	end: function() {
+		return this.prevObject || jQuery( [] );
+	},
+
+	find: function( selector ) {
+		var elems = jQuery.map(this, function(elem){
+			return jQuery.find( selector, elem );
+		});
+
+		return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
+			jQuery.unique( elems ) :
+			elems );
+	},
+
+	clone: function( events ) {
+		// Do the clone
+		var ret = this.map(function(){
+			if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
+				// IE copies events bound via attachEvent when
+				// using cloneNode. Calling detachEvent on the
+				// clone will also remove the events from the orignal
+				// In order to get around this, we use innerHTML.
+				// Unfortunately, this means some modifications to 
+				// attributes in IE that are actually only stored 
+				// as properties will not be copied (such as the
+				// the name attribute on an input).
+				var clone = this.cloneNode(true),
+					container = document.createElement("div"),
+					container2 = document.createElement("div");
+				container.appendChild(clone);
+				container2.innerHTML = container.innerHTML;
+				return container2.firstChild;
+			} else
+				return this.cloneNode(true);
+		});
+
+		// Need to set the expando to null on the cloned set if it exists
+		// removeData doesn't work here, IE removes it from the original as well
+		// this is primarily for IE but the data expando shouldn't be copied over in any browser
+		var clone = ret.find("*").andSelf().each(function(){
+			if ( this[ expando ] != undefined )
+				this[ expando ] = null;
+		});
+		
+		// Copy the events from the original to the clone
+		if ( events === true )
+			this.find("*").andSelf().each(function(i){
+				var events = jQuery.data( this, "events" );
+
+				for ( var type in events )
+					for ( var handler in events[ type ] )
+						jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
+			});
+
+		// Return the cloned set
+		return ret;
+	},
+
+	filter: function( selector ) {
+		return this.pushStack(
+			jQuery.isFunction( selector ) &&
+			jQuery.grep(this, function(elem, i){
+				return selector.call( elem, i );
+			}) ||
+
+			jQuery.multiFilter( selector, this ) );
+	},
+
+	not: function( selector ) {
+		if ( selector.constructor == String )
+			// test special case where just one selector is passed in
+			if ( isSimple.test( selector ) )
+				return this.pushStack( jQuery.multiFilter( selector, this, true ) );
+			else
+				selector = jQuery.multiFilter( selector, this );
+
+		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+		return this.filter(function() {
+			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
+		});
+	},
+
+	add: function( selector ) {
+		return !selector ? this : this.pushStack( jQuery.merge( 
+			this.get(),
+			selector.constructor == String ? 
+				jQuery( selector ).get() :
+				selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ?
+					selector : [selector] ) );
+	},
+
+	is: function( selector ) {
+		return selector ?
+			jQuery.multiFilter( selector, this ).length > 0 :
+			false;
+	},
+
+	hasClass: function( selector ) {
+		return this.is( "." + selector );
+	},
+	
+	val: function( value ) {
+		if ( value == undefined ) {
+
+			if ( this.length ) {
+				var elem = this[0];
+
+				// We need to handle select boxes special
+				if ( jQuery.nodeName( elem, "select" ) ) {
+					var index = elem.selectedIndex,
+						values = [],
+						options = elem.options,
+						one = elem.type == "select-one";
+					
+					// Nothing was selected
+					if ( index < 0 )
+						return null;
+
+					// Loop through all the selected options
+					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+						var option = options[ i ];
+
+						if ( option.selected ) {
+							// Get the specifc value for the option
+							value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
+							
+							// We don't need an array for one selects
+							if ( one )
+								return value;
+							
+							// Multi-Selects return an array
+							values.push( value );
+						}
+					}
+					
+					return values;
+					
+				// Everything else, we just grab the value
+				} else
+					return (this[0].value || "").replace(/\r/g, "");
+
+			}
+
+			return undefined;
+		}
+
+		return this.each(function(){
+			if ( this.nodeType != 1 )
+				return;
+
+			if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
+				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
+					jQuery.inArray(this.name, value) >= 0);
+
+			else if ( jQuery.nodeName( this, "select" ) ) {
+				var values = value.constructor == Array ?
+					value :
+					[ value ];
+
+				jQuery( "option", this ).each(function(){
+					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
+						jQuery.inArray( this.text, values ) >= 0);
+				});
+
+				if ( !values.length )
+					this.selectedIndex = -1;
+
+			} else
+				this.value = value;
+		});
+	},
+	
+	html: function( value ) {
+		return value == undefined ?
+			(this.length ?
+				this[0].innerHTML :
+				null) :
+			this.empty().append( value );
+	},
+
+	replaceWith: function( value ) {
+		return this.after( value ).remove();
+	},
+
+	eq: function( i ) {
+		return this.slice( i, i + 1 );
+	},
+
+	slice: function() {
+		return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function(elem, i){
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	andSelf: function() {
+		return this.add( this.prevObject );
+	},
+	
+	domManip: function( args, table, reverse, callback ) {
+		var clone = this.length > 1, elems; 
+
+		return this.each(function(){
+			if ( !elems ) {
+				elems = jQuery.clean( args, this.ownerDocument );
+
+				if ( reverse )
+					elems.reverse();
+			}
+
+			var obj = this;
+
+			if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
+				obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
+
+			var scripts = jQuery( [] );
+
+			jQuery.each(elems, function(){
+				var elem = clone ?
+					jQuery( this ).clone( true )[0] :
+					this;
+
+				// execute all scripts after the elements have been injected
+				if ( jQuery.nodeName( elem, "script" ) ) {
+					scripts = scripts.add( elem );
+				} else {
+					// Remove any inner scripts for later evaluation
+					if ( elem.nodeType == 1 )
+						scripts = scripts.add( jQuery( "script", elem ).remove() );
+
+					// Inject the elements into the document
+					callback.call( obj, elem );
+				}
+			});
+
+			scripts.each( evalScript );
+		});
+	}
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.prototype.init.prototype = jQuery.prototype;
+
+function evalScript( i, elem ) {
+	if ( elem.src )
+		jQuery.ajax({
+			url: elem.src,
+			async: false,
+			dataType: "script"
+		});
+
+	else
+		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+
+	if ( elem.parentNode )
+		elem.parentNode.removeChild( elem );
+}
+
+jQuery.extend = jQuery.fn.extend = function() {
+	// copy reference to target object
+	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
+
+	// Handle a deep copy situation
+	if ( target.constructor == Boolean ) {
+		deep = target;
+		target = arguments[1] || {};
+		// skip the boolean and the target
+		i = 2;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target != "object" && typeof target != "function" )
+		target = {};
+
+	// extend jQuery itself if only one argument is passed
+	if ( length == 1 ) {
+		target = this;
+		i = 0;
+	}
+
+	for ( ; i < length; i++ )
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null )
+			// Extend the base object
+			for ( var name in options ) {
+				// Prevent never-ending loop
+				if ( target === options[ name ] )
+					continue;
+
+				// Recurse if we're merging object values
+				if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType )
+					target[ name ] = jQuery.extend( target[ name ], options[ name ] );
+
+				// Don't bring in undefined values
+				else if ( options[ name ] != undefined )
+					target[ name ] = options[ name ];
+
+			}
+
+	// Return the modified object
+	return target;
+};
+
+var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {};
+
+// exclude the following css properties to add px
+var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
+
+jQuery.extend({
+	noConflict: function( deep ) {
+		window.$ = _$;
+
+		if ( deep )
+			window.jQuery = _jQuery;
+
+		return jQuery;
+	},
+
+	// This may seem like some crazy code, but trust me when I say that this
+	// is the only cross-browser way to do this. --John
+	isFunction: function( fn ) {
+		return !!fn && typeof fn != "string" && !fn.nodeName && 
+			fn.constructor != Array && /function/i.test( fn + "" );
+	},
+	
+	// check if an element is in a (or is an) XML document
+	isXMLDoc: function( elem ) {
+		return elem.documentElement && !elem.body ||
+			elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
+	},
+
+	// Evalulates a script in a global context
+	globalEval: function( data ) {
+		data = jQuery.trim( data );
+
+		if ( data ) {
+			// Inspired by code by Andrea Giammarchi
+			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+			var head = document.getElementsByTagName("head")[0] || document.documentElement,
+				script = document.createElement("script");
+
+			script.type = "text/javascript";
+			if ( jQuery.browser.msie )
+				script.text = data;
+			else
+				script.appendChild( document.createTextNode( data ) );
+
+			head.appendChild( script );
+			head.removeChild( script );
+		}
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+	},
+	
+	cache: {},
+	
+	data: function( elem, name, data ) {
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var id = elem[ expando ];
+
+		// Compute a unique ID for the element
+		if ( !id ) 
+			id = elem[ expando ] = ++uuid;
+
+		// Only generate the data cache if we're
+		// trying to access or manipulate it
+		if ( name && !jQuery.cache[ id ] )
+			jQuery.cache[ id ] = {};
+		
+		// Prevent overriding the named cache with undefined values
+		if ( data != undefined )
+			jQuery.cache[ id ][ name ] = data;
+		
+		// Return the named cache data, or the ID for the element	
+		return name ?
+			jQuery.cache[ id ][ name ] :
+			id;
+	},
+	
+	removeData: function( elem, name ) {
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var id = elem[ expando ];
+
+		// If we want to remove a specific section of the element's data
+		if ( name ) {
+			if ( jQuery.cache[ id ] ) {
+				// Remove the section of cache data
+				delete jQuery.cache[ id ][ name ];
+
+				// If we've removed all the data, remove the element's cache
+				name = "";
+
+				for ( name in jQuery.cache[ id ] )
+					break;
+
+				if ( !name )
+					jQuery.removeData( elem );
+			}
+
+		// Otherwise, we want to remove all of the element's data
+		} else {
+			// Clean up the element expando
+			try {
+				delete elem[ expando ];
+			} catch(e){
+				// IE has trouble directly removing the expando
+				// but it's ok with using removeAttribute
+				if ( elem.removeAttribute )
+					elem.removeAttribute( expando );
+			}
+
+			// Completely remove the data cache
+			delete jQuery.cache[ id ];
+		}
+	},
+
+	// args is for internal usage only
+	each: function( object, callback, args ) {
+		if ( args ) {
+			if ( object.length == undefined )
+				for ( var name in object )
+					callback.apply( object[ name ], args );
+			else
+				for ( var i = 0, length = object.length; i < length; i++ )
+					if ( callback.apply( object[ i ], args ) === false )
+						break;
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( object.length == undefined )
+				for ( var name in object )
+					callback.call( object[ name ], name, object[ name ] );
+			else
+				for ( var i = 0, length = object.length, value = object[0]; 
+					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
+		}
+
+		return object;
+	},
+	
+	prop: function( elem, value, type, i, name ) {
+			// Handle executable functions
+			if ( jQuery.isFunction( value ) )
+				value = value.call( elem, i );
+				
+			// Handle passing in a number to a CSS property
+			return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
+				value + "px" :
+				value;
+	},
+
+	className: {
+		// internal only, use addClass("class")
+		add: function( elem, classNames ) {
+			jQuery.each((classNames || "").split(/\s+/), function(i, className){
+				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
+					elem.className += (elem.className ? " " : "") + className;
+			});
+		},
+
+		// internal only, use removeClass("class")
+		remove: function( elem, classNames ) {
+			if (elem.nodeType == 1)
+				elem.className = classNames != undefined ?
+					jQuery.grep(elem.className.split(/\s+/), function(className){
+						return !jQuery.className.has( classNames, className );	
+					}).join(" ") :
+					"";
+		},
+
+		// internal only, use is(".class")
+		has: function( elem, className ) {
+			return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
+		}
+	},
+
+	// A method for quickly swapping in/out CSS properties to get correct calculations
+	swap: function( elem, options, callback ) {
+		var old = {};
+		// Remember the old values, and insert the new ones
+		for ( var name in options ) {
+			old[ name ] = elem.style[ name ];
+			elem.style[ name ] = options[ name ];
+		}
+
+		callback.call( elem );
+
+		// Revert the old values
+		for ( var name in options )
+			elem.style[ name ] = old[ name ];
+	},
+
+	css: function( elem, name, force ) {
+		if ( name == "width" || name == "height" ) {
+			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+		
+			function getWH() {
+				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+				var padding = 0, border = 0;
+				jQuery.each( which, function() {
+					padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+					border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+				});
+				val -= Math.round(padding + border);
+			}
+		
+			if ( jQuery(elem).is(":visible") )
+				getWH();
+			else
+				jQuery.swap( elem, props, getWH );
+			
+			return Math.max(0, val);
+		}
+		
+		return jQuery.curCSS( elem, name, force );
+	},
+
+	curCSS: function( elem, name, force ) {
+		var ret;
+
+		// A helper method for determining if an element's values are broken
+		function color( elem ) {
+			if ( !jQuery.browser.safari )
+				return false;
+
+			var ret = document.defaultView.getComputedStyle( elem, null );
+			return !ret || ret.getPropertyValue("color") == "";
+		}
+
+		// We need to handle opacity special in IE
+		if ( name == "opacity" && jQuery.browser.msie ) {
+			ret = jQuery.attr( elem.style, "opacity" );
+
+			return ret == "" ?
+				"1" :
+				ret;
+		}
+		// Opera sometimes will give the wrong display answer, this fixes it, see #2037
+		if ( jQuery.browser.opera && name == "display" ) {
+			var save = elem.style.display;
+			elem.style.display = "block";
+			elem.style.display = save;
+		}
+		
+		// Make sure we're using the right name for getting the float value
+		if ( name.match( /float/i ) )
+			name = styleFloat;
+
+		if ( !force && elem.style[ name ] )
+			ret = elem.style[ name ];
+
+		else if ( document.defaultView && document.defaultView.getComputedStyle ) {
+
+			// Only "float" is needed here
+			if ( name.match( /float/i ) )
+				name = "float";
+
+			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
+
+			var getComputedStyle = document.defaultView.getComputedStyle( elem, null );
+
+			if ( getComputedStyle && !color( elem ) )
+				ret = getComputedStyle.getPropertyValue( name );
+
+			// If the element isn't reporting its values properly in Safari
+			// then some display: none elements are involved
+			else {
+				var swap = [], stack = [];
+
+				// Locate all of the parent display: none elements
+				for ( var a = elem; a && color(a); a = a.parentNode )
+					stack.unshift(a);
+
+				// Go through and make them visible, but in reverse
+				// (It would be better if we knew the exact display type that they had)
+				for ( var i = 0; i < stack.length; i++ )
+					if ( color( stack[ i ] ) ) {
+						swap[ i ] = stack[ i ].style.display;
+						stack[ i ].style.display = "block";
+					}
+
+				// Since we flip the display style, we have to handle that
+				// one special, otherwise get the value
+				ret = name == "display" && swap[ stack.length - 1 ] != null ?
+					"none" :
+					( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || "";
+
+				// Finally, revert the display styles back
+				for ( var i = 0; i < swap.length; i++ )
+					if ( swap[ i ] != null )
+						stack[ i ].style.display = swap[ i ];
+			}
+
+			// We should always get a number back from opacity
+			if ( name == "opacity" && ret == "" )
+				ret = "1";
+
+		} else if ( elem.currentStyle ) {
+			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
+				return letter.toUpperCase();
+			});
+
+			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+
+			// From the awesome hack by Dean Edwards
+			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+			// If we're not dealing with a regular pixel number
+			// but a number that has a weird ending, we need to convert it to pixels
+			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
+				// Remember the original values
+				var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left;
+
+				// Put in the new values to get a computed value out
+				elem.runtimeStyle.left = elem.currentStyle.left;
+				elem.style.left = ret || 0;
+				ret = elem.style.pixelLeft + "px";
+
+				// Revert the changed values
+				elem.style.left = style;
+				elem.runtimeStyle.left = runtimeStyle;
+			}
+		}
+
+		return ret;
+	},
+	
+	clean: function( elems, context ) {
+		var ret = [];
+		context = context || document;
+		// !context.createElement fails in IE with an error but returns typeof 'object'
+		if (typeof context.createElement == 'undefined') 
+			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+
+		jQuery.each(elems, function(i, elem){
+			if ( !elem )
+				return;
+
+			if ( elem.constructor == Number )
+				elem = elem.toString();
+			
+			// Convert html string into DOM nodes
+			if ( typeof elem == "string" ) {
+				// Fix "XHTML"-style tags in all browsers
+				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
+					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area)$/i) ?
+						all :
+						front + "></" + tag + ">";
+				});
+
+				// Trim whitespace, otherwise indexOf won't work as expected
+				var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
+
+				var wrap =
+					// option or optgroup
+					!tags.indexOf("<opt") &&
+					[ 1, "<select multiple='multiple'>", "</select>" ] ||
+					
+					!tags.indexOf("<leg") &&
+					[ 1, "<fieldset>", "</fieldset>" ] ||
+					
+					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+					[ 1, "<table>", "</table>" ] ||
+					
+					!tags.indexOf("<tr") &&
+					[ 2, "<table><tbody>", "</tbody></table>" ] ||
+					
+				 	// <thead> matched above
+					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
+					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
+					
+					!tags.indexOf("<col") &&
+					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
+
+					// IE can't serialize <link> and <script> tags normally
+					jQuery.browser.msie &&
+					[ 1, "div<div>", "</div>" ] ||
+					
+					[ 0, "", "" ];
+
+				// Go to html and back, then peel off extra wrappers
+				div.innerHTML = wrap[1] + elem + wrap[2];
+				
+				// Move to the right depth
+				while ( wrap[0]-- )
+					div = div.lastChild;
+				
+				// Remove IE's autoinserted <tbody> from table fragments
+				if ( jQuery.browser.msie ) {
+					
+					// String was a <table>, *may* have spurious <tbody>
+					var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
+						div.firstChild && div.firstChild.childNodes :
+						
+						// String was a bare <thead> or <tfoot>
+						wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
+							div.childNodes :
+							[];
+				
+					for ( var j = tbody.length - 1; j >= 0 ; --j )
+						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
+							tbody[ j ].parentNode.removeChild( tbody[ j ] );
+					
+					// IE completely kills leading whitespace when innerHTML is used	
+					if ( /^\s/.test( elem ) )	
+						div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
+				
+				}
+				
+				elem = jQuery.makeArray( div.childNodes );
+			}
+
+			if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
+				return;
+
+			if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
+				ret.push( elem );
+
+			else
+				ret = jQuery.merge( ret, elem );
+
+		});
+
+		return ret;
+	},
+	
+	attr: function( elem, name, value ) {
+		// don't set attributes on text and comment nodes
+		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+			return undefined;
+
+		var fix = jQuery.isXMLDoc( elem ) ?
+			{} :
+			jQuery.props;
+
+		// Safari mis-reports the default selected property of a hidden option
+		// Accessing the parent's selectedIndex property fixes it
+		if ( name == "selected" && jQuery.browser.safari )
+			elem.parentNode.selectedIndex;
+		
+		// Certain attributes only work when accessed via the old DOM 0 way
+		if ( fix[ name ] ) {
+			if ( value != undefined )
+				elem[ fix[ name ] ] = value;
+
+			return elem[ fix[ name ] ];
+
+		} else if ( jQuery.browser.msie && name == "style" )
+			return jQuery.attr( elem.style, "cssText", value );
+
+		else if ( value == undefined && jQuery.browser.msie && jQuery.nodeName( elem, "form" ) && (name == "action" || name == "method") )
+			return elem.getAttributeNode( name ).nodeValue;
+
+		// IE elem.getAttribute passes even for style
+		else if ( elem.tagName ) {
+
+			if ( value != undefined ) {
+				// We can't allow the type property to be changed (since it causes problems in IE)
+				if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
+					throw "type property can't be changed";
+
+				// convert the value to a string (all browsers do this but IE) see #1070
+				elem.setAttribute( name, "" + value );
+			}
+
+			if ( jQuery.browser.msie && /href|src/.test( name ) && !jQuery.isXMLDoc( elem ) ) 
+				return elem.getAttribute( name, 2 );
+
+			return elem.getAttribute( name );
+
+		// elem is actually elem.style ... set the style
+		} else {
+			// IE actually uses filters for opacity
+			if ( name == "opacity" && jQuery.browser.msie ) {
+				if ( value != undefined ) {
+					// IE has trouble with opacity if it does not have layout
+					// Force it by setting the zoom level
+					elem.zoom = 1; 
+	
+					// Set the alpha filter to set the opacity
+					elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
+						(parseFloat( value ).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
+				}
+	
+				return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
+					(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() :
+					"";
+			}
+
+			name = name.replace(/-([a-z])/ig, function(all, letter){
+				return letter.toUpperCase();
+			});
+
+			if ( value != undefined )
+				elem[ name ] = value;
+
+			return elem[ name ];
+		}
+	},
+	
+	trim: function( text ) {
+		return (text || "").replace( /^\s+|\s+$/g, "" );
+	},
+
+	makeArray: function( array ) {
+		var ret = [];
+
+		// Need to use typeof to fight Safari childNodes crashes
+		if ( typeof array != "array" )
+			for ( var i = 0, length = array.length; i < length; i++ )
+				ret.push( array[ i ] );
+		else
+			ret = array.slice( 0 );
+
+		return ret;
+	},
+
+	inArray: function( elem, array ) {
+		for ( var i = 0, length = array.length; i < length; i++ )
+			if ( array[ i ] == elem )
+				return i;
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		// We have to loop this way because IE & Opera overwrite the length
+		// expando of getElementsByTagName
+
+		// Also, we need to make sure that the correct elements are being returned
+		// (IE returns comment nodes in a '*' query)
+		if ( jQuery.browser.msie ) {
+			for ( var i = 0; second[ i ]; i++ )
+				if ( second[ i ].nodeType != 8 )
+					first.push( second[ i ] );
+
+		} else
+			for ( var i = 0; second[ i ]; i++ )
+				first.push( second[ i ] );
+
+		return first;
+	},
+
+	unique: function( array ) {
+		var ret = [], done = {};
+
+		try {
+
+			for ( var i = 0, length = array.length; i < length; i++ ) {
+				var id = jQuery.data( array[ i ] );
+
+				if ( !done[ id ] ) {
+					done[ id ] = true;
+					ret.push( array[ i ] );
+				}
+			}
+
+		} catch( e ) {
+			ret = array;
+		}
+
+		return ret;
+	},
+
+	grep: function( elems, callback, inv ) {
+		// If a string is passed in for the function, make a function
+		// for it (a handy shortcut)
+		if ( typeof callback == "string" )
+			callback = eval("false||function(a,i){return " + callback + "}");
+
+		var ret = [];
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( var i = 0, length = elems.length; i < length; i++ )
+			if ( !inv && callback( elems[ i ], i ) || inv && !callback( elems[ i ], i ) )
+				ret.push( elems[ i ] );
+
+		return ret;
+	},
+
+	map: function( elems, callback ) {
+		var ret = [];
+
+		// Go through the array, translating each of the items to their
+		// new value (or values).
+		for ( var i = 0, length = elems.length; i < length; i++ ) {
+			var value = callback( elems[ i ], i );
+
+			if ( value !== null && value != undefined ) {
+				if ( value.constructor != Array )
+					value = [ value ];
+
+				ret = ret.concat( value );
+			}
+		}
+
+		return ret;
+	}
+});
+
+var userAgent = navigator.userAgent.toLowerCase();
+
+// Figure out what browser is being used
+jQuery.browser = {
+	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
+	safari: /webkit/.test( userAgent ),
+	opera: /opera/.test( userAgent ),
+	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
+	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
+};
+
+var styleFloat = jQuery.browser.msie ?
+	"styleFloat" :
+	"cssFloat";
+	
+jQuery.extend({
+	// Check to see if the W3C box model is being used
+	boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
+	
+	props: {
+		"for": "htmlFor",
+		"class": "className",
+		"float": styleFloat,
+		cssFloat: styleFloat,
+		styleFloat: styleFloat,
+		innerHTML: "innerHTML",
+		className: "className",
+		value: "value",
+		disabled: "disabled",
+		checked: "checked",
+		readonly: "readOnly",
+		selected: "selected",
+		maxlength: "maxLength",
+		selectedIndex: "selectedIndex",
+		defaultValue: "defaultValue",
+		tagName: "tagName",
+		nodeName: "nodeName"
+	}
+});
+
+jQuery.each({
+	parent: "elem.parentNode",
+	parents: "jQuery.dir(elem,'parentNode')",
+	next: "jQuery.nth(elem,2,'nextSibling')",
+	prev: "jQuery.nth(elem,2,'previousSibling')",
+	nextAll: "jQuery.dir(elem,'nextSibling')",
+	prevAll: "jQuery.dir(elem,'previousSibling')",
+	siblings: "jQuery.sibling(elem.parentNode.firstChild,elem)",
+	children: "jQuery.sibling(elem.firstChild)",
+	contents: "jQuery.nodeName(elem,'iframe')?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes)"
+}, function(name, fn){
+	fn = eval("false||function(elem){return " + fn + "}");
+
+	jQuery.fn[ name ] = function( selector ) {
+		var ret = jQuery.map( this, fn );
+
+		if ( selector && typeof selector == "string" )
+			ret = jQuery.multiFilter( selector, ret );
+
+		return this.pushStack( jQuery.unique( ret ) );
+	};
+});
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function(name, original){
+	jQuery.fn[ name ] = function() {
+		var args = arguments;
+
+		return this.each(function(){
+			for ( var i = 0, length = args.length; i < length; i++ )
+				jQuery( args[ i ] )[ original ]( this );
+		});
+	};
+});
+
+jQuery.each({
+	removeAttr: function( name ) {
+		jQuery.attr( this, name, "" );
+		if (this.nodeType == 1) 
+			this.removeAttribute( name );
+	},
+
+	addClass: function( classNames ) {
+		jQuery.className.add( this, classNames );
+	},
+
+	removeClass: function( classNames ) {
+		jQuery.className.remove( this, classNames );
+	},
+
+	toggleClass: function( classNames ) {
+		jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
+	},
+
+	remove: function( selector ) {
+		if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
+			// Prevent memory leaks
+			jQuery( "*", this ).add(this).each(function(){
+				jQuery.event.remove(this);
+				jQuery.removeData(this);
+			});
+			if (this.parentNode)
+				this.parentNode.removeChild( this );
+		}
+	},
+
+	empty: function() {
+		// Remove element nodes and prevent memory leaks
+		jQuery( ">*", this ).remove();
+		
+		// Remove any remaining nodes
+		while ( this.firstChild )
+			this.removeChild( this.firstChild );
+	}
+}, function(name, fn){
+	jQuery.fn[ name ] = function(){
+		return this.each( fn, arguments );
+	};
+});
+
+jQuery.each([ "Height", "Width" ], function(i, name){
+	var type = name.toLowerCase();
+	
+	jQuery.fn[ type ] = function( size ) {
+		// Get window width or height
+		return this[0] == window ?
+			// Opera reports document.body.client[Width/Height] properly in both quirks and standards
+			jQuery.browser.opera && document.body[ "client" + name ] || 
+			
+			// Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
+			jQuery.browser.safari && window[ "inner" + name ] ||
+			
+			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
+		
+			// Get document width or height
+			this[0] == document ?
+				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+				Math.max( 
+					Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]), 
+					Math.max(document.body["offset" + name], document.documentElement["offset" + name]) 
+				) :
+
+				// Get or set width or height on the element
+				size == undefined ?
+					// Get width or height on the element
+					(this.length ? jQuery.css( this[0], type ) : null) :
+
+					// Set the width or height on the element (default to pixels if value is unitless)
+					this.css( type, size.constructor == String ? size : size + "px" );
+	};
+});
+
+var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
+		"(?:[\\w*_-]|\\\\.)" :
+		"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
+	quickChild = new RegExp("^>\\s*(" + chars + "+)"),
+	quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
+	quickClass = new RegExp("^([#.]?)(" + chars + "*)");
+
+jQuery.extend({
+	expr: {
+		"": "m[2]=='*'||jQuery.nodeName(a,m[2])",
+		"#": "a.getAttribute('id')==m[2]",
+		":": {
+			// Position Checks
+			lt: "i<m[3]-0",
+			gt: "i>m[3]-0",
+			nth: "m[3]-0==i",
+			eq: "m[3]-0==i",
+			first: "i==0",
+			last: "i==r.length-1",
+			even: "i%2==0",
+			odd: "i%2",
+
+			// Child Checks
+			"first-child": "a.parentNode.getElementsByTagName('*')[0]==a",
+			"last-child": "jQuery.nth(a.parentNode.lastChild,1,'previousSibling')==a",
+			"only-child": "!jQuery.nth(a.parentNode.lastChild,2,'previousSibling')",
+
+			// Parent Checks
+			parent: "a.firstChild",
+			empty: "!a.firstChild",
+
+			// Text Check
+			contains: "(a.textContent||a.innerText||jQuery(a).text()||'').indexOf(m[3])>=0",
+
+			// Visibility
+			visible: '"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden"',
+			hidden: '"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden"',
+
+			// Form attributes
+			enabled: "!a.disabled",
+			disabled: "a.disabled",
+			checked: "a.checked",
+			selected: "a.selected||jQuery.attr(a,'selected')",
+
+			// Form elements
+			text: "'text'==a.type",
+			radio: "'radio'==a.type",
+			checkbox: "'checkbox'==a.type",
+			file: "'file'==a.type",
+			password: "'password'==a.type",
+			submit: "'submit'==a.type",
+			image: "'image'==a.type",
+			reset: "'reset'==a.type",
+			button: '"button"==a.type||jQuery.nodeName(a,"button")',
+			input: "/input|select|textarea|button/i.test(a.nodeName)",
+
+			// :has()
+			has: "jQuery.find(m[3],a).length",
+
+			// :header
+			header: "/h\\d/i.test(a.nodeName)",
+
+			// :animated
+			animated: "jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length"
+		}
+	},
+	
+	// The regular expressions that power the parsing engine
+	parse: [
+		// Match: [@value='test'], [@foo]
+		/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
+
+		// Match: :contains('foo')
+		/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
+
+		// Match: :even, :last-chlid, #id, .class
+		new RegExp("^([:.#]*)(" + chars + "+)")
+	],
+
+	multiFilter: function( expr, elems, not ) {
+		var old, cur = [];
+
+		while ( expr && expr != old ) {
+			old = expr;
+			var f = jQuery.filter( expr, elems, not );
+			expr = f.t.replace(/^\s*,\s*/, "" );
+			cur = not ? elems = f.r : jQuery.merge( cur, f.r );
+		}
+
+		return cur;
+	},
+
+	find: function( t, context ) {
+		// Quickly handle non-string expressions
+		if ( typeof t != "string" )
+			return [ t ];
+
+		// check to make sure context is a DOM element or a document
+		if ( context && context.nodeType != 1 && context.nodeType != 9)
+			return [ ];
+
+		// Set the correct context (if none is provided)
+		context = context || document;
+
+		// Initialize the search
+		var ret = [context], done = [], last, nodeName;
+
+		// Continue while a selector expression exists, and while
+		// we're no longer looping upon ourselves
+		while ( t && last != t ) {
+			var r = [];
+			last = t;
+
+			t = jQuery.trim(t);
+
+			var foundToken = false;
+
+			// An attempt at speeding up child selectors that
+			// point to a specific element tag
+			var re = quickChild;
+			var m = re.exec(t);
+
+			if ( m ) {
+				nodeName = m[1].toUpperCase();
+
+				// Perform our own iteration and filter
+				for ( var i = 0; ret[i]; i++ )
+					for ( var c = ret[i].firstChild; c; c = c.nextSibling )
+						if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
+							r.push( c );
+
+				ret = r;
+				t = t.replace( re, "" );
+				if ( t.indexOf(" ") == 0 ) continue;
+				foundToken = true;
+			} else {
+				re = /^([>+~])\s*(\w*)/i;
+
+				if ( (m = re.exec(t)) != null ) {
+					r = [];
+
+					var merge = {};
+					nodeName = m[2].toUpperCase();
+					m = m[1];
+
+					for ( var j = 0, rl = ret.length; j < rl; j++ ) {
+						var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
+						for ( ; n; n = n.nextSibling )
+							if ( n.nodeType == 1 ) {
+								var id = jQuery.data(n);
+
+								if ( m == "~" && merge[id] ) break;
+								
+								if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
+									if ( m == "~" ) merge[id] = true;
+									r.push( n );
+								}
+								
+								if ( m == "+" ) break;
+							}
+					}
+
+					ret = r;
+
+					// And remove the token
+					t = jQuery.trim( t.replace( re, "" ) );
+					foundToken = true;
+				}
+			}
+
+			// See if there's still an expression, and that we haven't already
+			// matched a token
+			if ( t && !foundToken ) {
+				// Handle multiple expressions
+				if ( !t.indexOf(",") ) {
+					// Clean the result set
+					if ( context == ret[0] ) ret.shift();
+
+					// Merge the result sets
+					done = jQuery.merge( done, ret );
+
+					// Reset the context
+					r = ret = [context];
+
+					// Touch up the selector string
+					t = " " + t.substr(1,t.length);
+
+				} else {
+					// Optimize for the case nodeName#idName
+					var re2 = quickID;
+					var m = re2.exec(t);
+					
+					// Re-organize the results, so that they're consistent
+					if ( m ) {
+						m = [ 0, m[2], m[3], m[1] ];
+
+					} else {
+						// Otherwise, do a traditional filter check for
+						// ID, class, and element selectors
+						re2 = quickClass;
+						m = re2.exec(t);
+					}
+
+					m[2] = m[2].replace(/\\/g, "");
+
+					var elem = ret[ret.length-1];
+
+					// Try to do a global search by ID, where we can
+					if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
+						// Optimization for HTML document case
+						var oid = elem.getElementById(m[2]);
+						
+						// Do a quick check for the existence of the actual ID attribute
+						// to avoid selecting by the name attribute in IE
+						// also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
+						if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
+							oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
+
+						// Do a quick check for node name (where applicable) so
+						// that div#foo searches will be really fast
+						ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
+					} else {
+						// We need to find all descendant elements
+						for ( var i = 0; ret[i]; i++ ) {
+							// Grab the tag name being searched for
+							var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
+
+							// Handle IE7 being really dumb about <object>s
+							if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
+								tag = "param";
+
+							r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
+						}
+
+						// It's faster to filter by class and be done with it
+						if ( m[1] == "." )
+							r = jQuery.classFilter( r, m[2] );
+
+						// Same with ID filtering
+						if ( m[1] == "#" ) {
+							var tmp = [];
+
+							// Try to find the element with the ID
+							for ( var i = 0; r[i]; i++ )
+								if ( r[i].getAttribute("id") == m[2] ) {
+									tmp = [ r[i] ];
+									break;
+								}
+
+							r = tmp;
+						}
+
+						ret = r;
+					}
+
+					t = t.replace( re2, "" );
+				}
+
+			}
+
+			// If a selector string still exists
+			if ( t ) {
+				// Attempt to filter it
+				var val = jQuery.filter(t,r);
+				ret = r = val.r;
+				t = jQuery.trim(val.t);
+			}
+		}
+
+		// An error occurred with the selector;
+		// just return an empty set instead
+		if ( t )
+			ret = [];
+
+		// Remove the root context
+		if ( ret && context == ret[0] )
+			ret.shift();
+
+		// And combine the results
+		done = jQuery.merge( done, ret );
+
+		return done;
+	},
+
+	classFilter: function(r,m,not){
+		m = " " + m + " ";
+		var tmp = [];
+		for ( var i = 0; r[i]; i++ ) {
+			var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
+			if ( !not && pass || not && !pass )
+				tmp.push( r[i] );
+		}
+		return tmp;
+	},
+
+	filter: function(t,r,not) {
+		var last;
+
+		// Look for common filter expressions
+		while ( t && t != last ) {
+			last = t;
+
+			var p = jQuery.parse, m;
+
+			for ( var i = 0; p[i]; i++ ) {
+				m = p[i].exec( t );
+
+				if ( m ) {
+					// Remove what we just matched
+					t = t.substring( m[0].length );
+
+					m[2] = m[2].replace(/\\/g, "");
+					break;
+				}
+			}
+
+			if ( !m )
+				break;
+
+			// :not() is a special case that can be optimized by
+			// keeping it out of the expression list
+			if ( m[1] == ":" && m[2] == "not" )
+				// optimize if only one selector found (most common case)
+				r = isSimple.test( m[3] ) ?
+					jQuery.filter(m[3], r, true).r :
+					jQuery( r ).not( m[3] );
+
+			// We can get a big speed boost by filtering by class here
+			else if ( m[1] == "." )
+				r = jQuery.classFilter(r, m[2], not);
+
+			else if ( m[1] == "[" ) {
+				var tmp = [], type = m[3];
+				
+				for ( var i = 0, rl = r.length; i < rl; i++ ) {
+					var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
+					
+					if ( z == null || /href|src|selected/.test(m[2]) )
+						z = jQuery.attr(a,m[2]) || '';
+
+					if ( (type == "" && !!z ||
+						 type == "=" && z == m[5] ||
+						 type == "!=" && z != m[5] ||
+						 type == "^=" && z && !z.indexOf(m[5]) ||
+						 type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
+						 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
+							tmp.push( a );
+				}
+				
+				r = tmp;
+
+			// We can get a speed boost by handling nth-child here
+			} else if ( m[1] == ":" && m[2] == "nth-child" ) {
+				var merge = {}, tmp = [],
+					// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+					test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+						m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
+						!/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
+					// calculate the numbers (first)n+(last) including if they are negative
+					first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
+ 
+				// loop through all the elements left in the jQuery object
+				for ( var i = 0, rl = r.length; i < rl; i++ ) {
+					var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
+
+					if ( !merge[id] ) {
+						var c = 1;
+
+						for ( var n = parentNode.firstChild; n; n = n.nextSibling )
+							if ( n.nodeType == 1 )
+								n.nodeIndex = c++;
+
+						merge[id] = true;
+					}
+
+					var add = false;
+
+					if ( first == 0 ) {
+						if ( node.nodeIndex == last )
+							add = true;
+					} else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
+						add = true;
+
+					if ( add ^ not )
+						tmp.push( node );
+				}
+
+				r = tmp;
+
+			// Otherwise, find the expression to execute
+			} else {
+				var f = jQuery.expr[m[1]];
+				if ( typeof f != "string" )
+					f = jQuery.expr[m[1]][m[2]];
+
+				// Build a custom macro to enclose it
+				f = eval("false||function(a,i){return " + f + "}");
+
+				// Execute it against the current filter
+				r = jQuery.grep( r, f, not );
+			}
+		}
+
+		// Return an array of filtered elements (r)
+		// and the modified expression string (t)
+		return { r: r, t: t };
+	},
+
+	dir: function( elem, dir ){
+		var matched = [];
+		var cur = elem[dir];
+		while ( cur && cur != document ) {
+			if ( cur.nodeType == 1 )
+				matched.push( cur );
+			cur = cur[dir];
+		}
+		return matched;
+	},
+	
+	nth: function(cur,result,dir,elem){
+		result = result || 1;
+		var num = 0;
+
+		for ( ; cur; cur = cur[dir] )
+			if ( cur.nodeType == 1 && ++num == result )
+				break;
+
+		return cur;
+	},
+	
+	sibling: function( n, elem ) {
+		var r = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType == 1 && (!elem || n != elem) )
+				r.push( n );
+		}
+
+		return r;
+	}
+});
+
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code orignated from 
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+	// Bind an event to an element
+	// Original by Dean Edwards
+	add: function(elem, types, handler, data) {
+		if ( elem.nodeType == 3 || elem.nodeType == 8 )
+			return;
+
+		// For whatever reason, IE has trouble passing the window object
+		// around, causing it to be cloned in the process
+		if ( jQuery.browser.msie && elem.setInterval != undefined )
+			elem = window;
+
+		// Make sure that the function being executed has a unique ID
+		if ( !handler.guid )
+			handler.guid = this.guid++;
+			
+		// if data is passed, bind to handler 
+		if( data != undefined ) { 
+			// Create temporary function pointer to original handler 
+			var fn = handler; 
+
+			// Create unique handler function, wrapped around original handler 
+			handler = function() { 
+				// Pass arguments and context to original handler 
+				return fn.apply(this, arguments); 
+			};
+
+			// Store data in unique handler 
+			handler.data = data;
+
+			// Set the guid of unique handler to the same of original handler, so it can be removed 
+			handler.guid = fn.guid;
+		}
+
+		// Init the element's event structure
+		var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
+			handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
+				// returned undefined or false
+				var val;
+
+				// Handle the second event of a trigger and when
+				// an event is called after a page has unloaded
+				if ( typeof jQuery == "undefined" || jQuery.event.triggered )
+					return val;
+		
+				val = jQuery.event.handle.apply(elem, arguments);
+		
+				return val;
+			});
+			
+			// Handle multiple events seperated by a space
+			// jQuery(...).bind("mouseover mouseout", fn);
+			jQuery.each(types.split(/\s+/), function(index, type) {
+				// Namespaced event handlers
+				var parts = type.split(".");
+				type = parts[0];
+				handler.type = parts[1];
+
+				// Get the current list of functions bound to this event
+				var handlers = events[type];
+
+				// Init the event handler queue
+				if (!handlers) {
+					handlers = events[type] = {};
+		
+					// Check for a special event handler
+					// Only use addEventListener/attachEvent if the special
+					// events handler returns false
+					if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
+						// Bind the global event handler to the element
+						if (elem.addEventListener)
+							elem.addEventListener(type, handle, false);
+						else if (elem.attachEvent)
+							elem.attachEvent("on" + type, handle);
+					}
+				}
+
+				// Add the function to the element's handler list
+				handlers[handler.guid] = handler;
+
+				// Keep track of which events have been used, for global triggering
+				jQuery.event.global[type] = true;
+			});
+	},
+
+	guid: 1,
+	global: {},
+
+	// Detach an event or set of events from an element
+	remove: function(elem, types, handler) {
+		// don't do events on text and comment nodes
+		if ( elem.nodeType == 3 || elem.nodeType == 8 )
+			return;
+
+		var events = jQuery.data(elem, "events"), ret, index;
+
+		if ( events ) {
+			// Unbind all events for the element
+			if ( types == undefined )
+				for ( var type in events )
+					this.remove( elem, type );
+			else {
+				// types is actually an event object here
+				if ( types.type ) {
+					handler = types.handler;
+					types = types.type;
+				}
+				
+				// Handle multiple events seperated by a space
+				// jQuery(...).unbind("mouseover mouseout", fn);
+				jQuery.each(types.split(/\s+/), function(index, type){
+					// Namespaced event handlers
+					var parts = type.split(".");
+					type = parts[0];
+					
+					if ( events[type] ) {
+						// remove the given handler for the given type
+						if ( handler )
+							delete events[type][handler.guid];
+			
+						// remove all handlers for the given type
+						else
+							for ( handler in events[type] )
+								// Handle the removal of namespaced events
+								if ( !parts[1] || events[type][handler].type == parts[1] )
+									delete events[type][handler];
+
+						// remove generic event handler if no more handlers exist
+						for ( ret in events[type] ) break;
+						if ( !ret ) {
+							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
+								if (elem.removeEventListener)
+									elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+								else if (elem.detachEvent)
+									elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+							}
+							ret = null;
+							delete events[type];
+						}
+					}
+				});
+			}
+
+			// Remove the expando if it's no longer used
+			for ( ret in events ) break;
+			if ( !ret ) {
+				jQuery.removeData( elem, "events" );
+				jQuery.removeData( elem, "handle" );
+			}
+		}
+	},
+
+	trigger: function(type, data, elem, donative, extra) {
+		// Clone the incoming data, if any
+		data = jQuery.makeArray(data || []);
+
+		// Handle a global trigger
+		if ( !elem ) {
+			// Only trigger if we've ever bound an event for it
+			if ( this.global[type] )
+				jQuery("*").add([window, document]).trigger(type, data);
+
+		// Handle triggering a single element
+		} else {
+			// don't do events on text and comment nodes
+			if ( elem.nodeType == 3 || elem.nodeType == 8 )
+				return undefined;
+
+			var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
+				// Check to see if we need to provide a fake event, or not
+				event = !data[0] || !data[0].preventDefault;
+			
+			// Pass along a fake event
+			if ( event )
+				data.unshift( this.fix({ type: type, target: elem }) );
+
+			// Enforce the right trigger type
+			data[0].type = type;
+
+			// Trigger the event
+			if ( jQuery.isFunction( jQuery.data(elem, "handle") ) )
+				val = jQuery.data(elem, "handle").apply( elem, data );
+
+			// Handle triggering native .onfoo handlers
+			if ( !fn && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
+				val = false;
+
+			// Extra functions don't get the custom event object
+			if ( event )
+				data.shift();
+
+			// Handle triggering of extra function
+			if ( extra && jQuery.isFunction( extra ) ) {
+				// call the extra function and tack the current return value on the end for possible inspection
+				var ret = extra.apply( elem, data.concat( val ) );
+				// if anything is returned, give it precedence and have it overwrite the previous value
+				if (ret !== undefined)
+					val = ret;
+			}
+
+			// Trigger the native events (except for clicks on links)
+			if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
+				this.triggered = true;
+				try {
+					elem[ type ]();
+				// prevent IE from throwing an error for some hidden elements
+				} catch (e) {}
+			}
+
+			this.triggered = false;
+		}
+
+		return val;
+	},
+
+	handle: function(event) {
+		// returned undefined or false
+		var val;
+
+		// Empty object is for triggered events with no data
+		event = jQuery.event.fix( event || window.event || {} ); 
+
+		// Namespaced event handlers
+		var parts = event.type.split(".");
+		event.type = parts[0];
+
+		var handlers = jQuery.data(this, "events") && jQuery.data(this, "events")[event.type], args = Array.prototype.slice.call( arguments, 1 );
+		args.unshift( event );
+
+		for ( var j in handlers ) {
+			var handler = handlers[j];
+			// Pass in a reference to the handler function itself
+			// So that we can later remove it
+			args[0].handler = handler;
+			args[0].data = handler.data;
+
+			// Filter the functions by class
+			if ( !parts[1] || handler.type == parts[1] ) {
+				var ret = handler.apply( this, args );
+
+				if ( val !== false )
+					val = ret;
+
+				if ( ret === false ) {
+					event.preventDefault();
+					event.stopPropagation();
+				}
+			}
+		}
+
+		// Clean up added properties in IE to prevent memory leak
+		if (jQuery.browser.msie)
+			event.target = event.preventDefault = event.stopPropagation =
+				event.handler = event.data = null;
+
+		return val;
+	},
+
+	fix: function(event) {
+		// Short-circuit if the event has already been fixed by jQuery.event.fix
+		if ( event[ expando ] )
+			return event;
+			
+		// store a copy of the original event object 
+		// and clone to set read-only properties
+		var originalEvent = event;
+		event = jQuery.extend({}, originalEvent);
+		
+		// Mark the event as fixed by jQuery.event.fix
+		event[ expando ] = true;
+		
+		// add preventDefault and stopPropagation since 
+		// they will not work on the clone
+		event.preventDefault = function() {
+			// if preventDefault exists run it on the original event
+			if (originalEvent.preventDefault)
+				originalEvent.preventDefault();
+			// otherwise set the returnValue property of the original event to false (IE)
+			originalEvent.returnValue = false;
+		};
+		event.stopPropagation = function() {
+			// if stopPropagation exists run it on the original event
+			if (originalEvent.stopPropagation)
+				originalEvent.stopPropagation();
+			// otherwise set the cancelBubble property of the original event to true (IE)
+			originalEvent.cancelBubble = true;
+		};
+		
+		// Fix target property, if necessary
+		if ( !event.target )
+			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+				
+		// check if target is a textnode (safari)
+		if ( event.target.nodeType == 3 )
+			event.target = originalEvent.target.parentNode;
+
+		// Add relatedTarget, if necessary
+		if ( !event.relatedTarget && event.fromElement )
+			event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
+
+		// Calculate pageX/Y if missing and clientX/Y available
+		if ( event.pageX == null && event.clientX != null ) {
+			var doc = document.documentElement, body = document.body;
+			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
+			event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+		}
+			
+		// Add which for key events
+		if ( !event.which && (event.charCode || event.keyCode) )
+			event.which = event.charCode || event.keyCode;
+		
+		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+		if ( !event.metaKey && event.ctrlKey )
+			event.metaKey = event.ctrlKey;
+
+		// Add which for click: 1 == left; 2 == middle; 3 == right
+		// Note: button is not normalized, so don't use it
+		if ( !event.which && event.button )
+			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+			
+		return event;
+	},
+	
+	special: {
+		ready: {
+			setup: function() {
+				// Make sure the ready event is setup
+				bindReady();
+				return;
+			},
+			
+			teardown: function() { return; }
+		},
+		
+		mouseenter: {
+			setup: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
+				return true;
+			},
+		
+			teardown: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
+				return true;
+			},
+			
+			handler: function(event) {
+				// If we actually just moused on to a sub-element, ignore it
+				if ( withinElement(event, this) ) return true;
+				// Execute the right handlers by setting the event type to mouseenter
+				arguments[0].type = "mouseenter";
+				return jQuery.event.handle.apply(this, arguments);
+			}
+		},
+	
+		mouseleave: {
+			setup: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
+				return true;
+			},
+		
+			teardown: function() {
+				if ( jQuery.browser.msie ) return false;
+				jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
+				return true;
+			},
+			
+			handler: function(event) {
+				// If we actually just moused on to a sub-element, ignore it
+				if ( withinElement(event, this) ) return true;
+				// Execute the right handlers by setting the event type to mouseleave
+				arguments[0].type = "mouseleave";
+				return jQuery.event.handle.apply(this, arguments);
+			}
+		}
+	}
+};
+
+jQuery.fn.extend({
+	bind: function( type, data, fn ) {
+		return type == "unload" ? this.one(type, data, fn) : this.each(function(){
+			jQuery.event.add( this, type, fn || data, fn && data );
+		});
+	},
+	
+	one: function( type, data, fn ) {
+		return this.each(function(){
+			jQuery.event.add( this, type, function(event) {
+				jQuery(this).unbind(event);
+				return (fn || data).apply( this, arguments);
+			}, fn && data);
+		});
+	},
+
+	unbind: function( type, fn ) {
+		return this.each(function(){
+			jQuery.event.remove( this, type, fn );
+		});
+	},
+
+	trigger: function( type, data, fn ) {
+		return this.each(function(){
+			jQuery.event.trigger( type, data, this, true, fn );
+		});
+	},
+
+	triggerHandler: function( type, data, fn ) {
+		if ( this[0] )
+			return jQuery.event.trigger( type, data, this[0], false, fn );
+		return undefined;
+	},
+
+	toggle: function() {
+		// Save reference to arguments for access in closure
+		var args = arguments;
+
+		return this.click(function(event) {
+			// Figure out which function to execute
+			this.lastToggle = 0 == this.lastToggle ? 1 : 0;
+			
+			// Make sure that clicks stop
+			event.preventDefault();
+			
+			// and execute the function
+			return args[this.lastToggle].apply( this, arguments ) || false;
+		});
+	},
+
+	hover: function(fnOver, fnOut) {
+		return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
+	},
+	
+	ready: function(fn) {
+		// Attach the listeners
+		bindReady();
+
+		// If the DOM is already ready
+		if ( jQuery.isReady )
+			// Execute the function immediately
+			fn.call( document, jQuery );
+			
+		// Otherwise, remember the function for later
+		else
+			// Add the function to the wait list
+			jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
+	
+		return this;
+	}
+});
+
+jQuery.extend({
+	isReady: false,
+	readyList: [],
+	// Handle when the DOM is ready
+	ready: function() {
+		// Make sure that the DOM is not already loaded
+		if ( !jQuery.isReady ) {
+			// Remember that the DOM is ready
+			jQuery.isReady = true;
+			
+			// If there are functions bound, to execute
+			if ( jQuery.readyList ) {
+				// Execute all of them
+				jQuery.each( jQuery.readyList, function(){
+					this.apply( document );
+				});
+				
+				// Reset the list of functions
+				jQuery.readyList = null;
+			}
+		
+			// Trigger any bound ready events
+			$(document).triggerHandler("ready");
+		}
+	}
+});
+
+var readyBound = false;
+
+function bindReady(){
+	if ( readyBound ) return;
+	readyBound = true;
+
+	// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
+	if ( document.addEventListener && !jQuery.browser.opera)
+		// Use the handy event callback
+		document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
+	
+	// If IE is used and is not in a frame
+	// Continually check to see if the document is ready
+	if ( jQuery.browser.msie && window == top ) (function(){
+		if (jQuery.isReady) return;
+		try {
+			// If IE is used, use the trick by Diego Perini
+			// http://javascript.nwbox.com/IEContentLoaded/
+			document.documentElement.doScroll("left");
+		} catch( error ) {
+			setTimeout( arguments.callee, 0 );
+			return;
+		}
+		// and execute any waiting functions
+		jQuery.ready();
+	})();
+
+	if ( jQuery.browser.opera )
+		document.addEventListener( "DOMContentLoaded", function () {
+			if (jQuery.isReady) return;
+			for (var i = 0; i < document.styleSheets.length; i++)
+				if (document.styleSheets[i].disabled) {
+					setTimeout( arguments.callee, 0 );
+					return;
+				}
+			// and execute any waiting functions
+			jQuery.ready();
+		}, false);
+
+	if ( jQuery.browser.safari ) {
+		var numStyles;
+		(function(){
+			if (jQuery.isReady) return;
+			if ( document.readyState != "loaded" && document.readyState != "complete" ) {
+				setTimeout( arguments.callee, 0 );
+				return;
+			}
+			if ( numStyles === undefined )
+				numStyles = jQuery("style, link[rel=stylesheet]").length;
+			if ( document.styleSheets.length != numStyles ) {
+				setTimeout( arguments.callee, 0 );
+				return;
+			}
+			// and execute any waiting functions
+			jQuery.ready();
+		})();
+	}
+
+	// A fallback to window.onload, that will always work
+	jQuery.event.add( window, "load", jQuery.ready );
+}
+
+jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
+	"mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + 
+	"submit,keydown,keypress,keyup,error").split(","), function(i, name){
+	
+	// Handle event binding
+	jQuery.fn[name] = function(fn){
+		return fn ? this.bind(name, fn) : this.trigger(name);
+	};
+});
+
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function(event, elem) {
+	// Check if mouse(over|out) are still within the same parent element
+	var parent = event.relatedTarget;
+	// Traverse up the tree
+	while ( parent && parent != elem ) try { parent = parent.parentNode } catch(error) { parent = elem; };
+	// Return true if we actually just moused on to a sub-element
+	return parent == elem;
+};
+
+// Prevent memory leaks in IE
+// And prevent errors on refresh with events like mouseover in other browsers
+// Window isn't included so as not to unbind existing unload events
+jQuery(window).bind("unload", function() {
+	jQuery("*").add(document).unbind();
+});
+jQuery.fn.extend({
+	load: function( url, params, callback ) {
+		if ( jQuery.isFunction( url ) )
+			return this.bind("load", url);
+
+		var off = url.indexOf(" ");
+		if ( off >= 0 ) {
+			var selector = url.slice(off, url.length);
+			url = url.slice(0, off);
+		}
+
+		callback = callback || function(){};
+
+		// Default to a GET request
+		var type = "GET";
+
+		// If the second parameter was provided
+		if ( params )
+			// If it's a function
+			if ( jQuery.isFunction( params ) ) {
+				// We assume that it's the callback
+				callback = params;
+				params = null;
+
+			// Otherwise, build a param string
+			} else {
+				params = jQuery.param( params );
+				type = "POST";
+			}
+
+		var self = this;
+
+		// Request the remote document
+		jQuery.ajax({
+			url: url,
+			type: type,
+			dataType: "html",
+			data: params,
+			complete: function(res, status){
+				// If successful, inject the HTML into all the matched elements
+				if ( status == "success" || status == "notmodified" )
+					// See if a selector was specified
+					self.html( selector ?
+						// Create a dummy div to hold the results
+						jQuery("<div/>")
+							// inject the contents of the document in, removing the scripts
+							// to avoid any 'Permission Denied' errors in IE
+							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+
+							// Locate the specified elements
+							.find(selector) :
+
+						// If not, just inject the full result
+						res.responseText );
+
+				self.each( callback, [res.responseText, status, res] );
+			}
+		});
+		return this;
+	},
+
+	serialize: function() {
+		return jQuery.param(this.serializeArray());
+	},
+	serializeArray: function() {
+		return this.map(function(){
+			return jQuery.nodeName(this, "form") ?
+				jQuery.makeArray(this.elements) : this;
+		})
+		.filter(function(){
+			return this.name && !this.disabled && 
+				(this.checked || /select|textarea/i.test(this.nodeName) || 
+					/text|hidden|password/i.test(this.type));
+		})
+		.map(function(i, elem){
+			var val = jQuery(this).val();
+			return val == null ? null :
+				val.constructor == Array ?
+					jQuery.map( val, function(val, i){
+						return {name: elem.name, value: val};
+					}) :
+					{name: elem.name, value: val};
+		}).get();
+	}
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
+	jQuery.fn[o] = function(f){
+		return this.bind(o, f);
+	};
+});
+
+var jsc = (new Date).getTime();
+
+jQuery.extend({
+	get: function( url, data, callback, type ) {
+		// shift arguments if data argument was ommited
+		if ( jQuery.isFunction( data ) ) {
+			callback = data;
+			data = null;
+		}
+		
+		return jQuery.ajax({
+			type: "GET",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get(url, null, callback, "script");
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get(url, data, callback, "json");
+	},
+
+	post: function( url, data, callback, type ) {
+		if ( jQuery.isFunction( data ) ) {
+			callback = data;
+			data = {};
+		}
+
+		return jQuery.ajax({
+			type: "POST",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	ajaxSetup: function( settings ) {
+		jQuery.extend( jQuery.ajaxSettings, settings );
+	},
+
+	ajaxSettings: {
+		global: true,
+		type: "GET",
+		timeout: 0,
+		contentType: "application/x-www-form-urlencoded",
+		processData: true,
+		async: true,
+		data: null
+	},
+	
+	// Last-Modified header cache for next request
+	lastModified: {},
+
+	ajax: function( s ) {
+		var jsonp, jsre = /=\?(&|$)/g, status, data;
+
+		// Extend the settings, but re-extend 's' so that it can be
+		// checked again later (in the test suite, specifically)
+		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
+
+		// convert data if not already a string
+		if ( s.data && s.processData && typeof s.data != "string" )
+			s.data = jQuery.param(s.data);
+
+		// Handle JSONP Parameter Callbacks
+		if ( s.dataType == "jsonp" ) {
+			if ( s.type.toLowerCase() == "get" ) {
+				if ( !s.url.match(jsre) )
+					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+			} else if ( !s.data || !s.data.match(jsre) )
+				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+			s.dataType = "json";
+		}
+
+		// Build temporary JSONP function
+		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
+			jsonp = "jsonp" + jsc++;
+
+			// Replace the =? sequence both in the query string and the data
+			if ( s.data )
+				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+			// We need to make sure
+			// that a JSONP style response is executed properly
+			s.dataType = "script";
+
+			// Handle JSONP-style loading
+			window[ jsonp ] = function(tmp){
+				data = tmp;
+				success();
+				complete();
+				// Garbage collect
+				window[ jsonp ] = undefined;
+				try{ delete window[ jsonp ]; } catch(e){}
+				if ( head )
+					head.removeChild( script );
+			};
+		}
+
+		if ( s.dataType == "script" && s.cache == null )
+			s.cache = false;
+
+		if ( s.cache === false && s.type.toLowerCase() == "get" ) {
+			var ts = (new Date()).getTime();
+			// try replacing _= if it is there
+			var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+			// if nothing was replaced, add timestamp to the end
+			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
+		}
+
+		// If data is available, append data to url for get requests
+		if ( s.data && s.type.toLowerCase() == "get" ) {
+			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
+
+			// IE likes to send both get and post data, prevent this
+			s.data = null;
+		}
+
+		// Watch for a new set of requests
+		if ( s.global && ! jQuery.active++ )
+			jQuery.event.trigger( "ajaxStart" );
+
+		// If we're requesting a remote document
+		// and trying to load JSON or Script with a GET
+		if ( (!s.url.indexOf("http") || !s.url.indexOf("//")) && ( s.dataType == "script" || s.dataType =="json" ) && s.type.toLowerCase() == "get" ) {
+			var head = document.getElementsByTagName("head")[0];
+			var script = document.createElement("script");
+			script.src = s.url;
+			if (s.scriptCharset)
+				script.charset = s.scriptCharset;
+
+			// Handle Script loading
+			if ( !jsonp ) {
+				var done = false;
+
+				// Attach handlers for all browsers
+				script.onload = script.onreadystatechange = function(){
+					if ( !done && (!this.readyState || 
+							this.readyState == "loaded" || this.readyState == "complete") ) {
+						done = true;
+						success();
+						complete();
+						head.removeChild( script );
+					}
+				};
+			}
+
+			head.appendChild(script);
+
+			// We handle everything using the script element injection
+			return undefined;
+		}
+
+		var requestDone = false;
+
+		// Create the request object; Microsoft failed to properly
+		// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+		var xml = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+
+		// Open the socket
+		xml.open(s.type, s.url, s.async);
+
+		// Need an extra try/catch for cross domain requests in Firefox 3
+		try {
+			// Set the correct header, if data is being sent
+			if ( s.data )
+				xml.setRequestHeader("Content-Type", s.contentType);
+
+			// Set the If-Modified-Since header, if ifModified mode.
+			if ( s.ifModified )
+				xml.setRequestHeader("If-Modified-Since",
+					jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+
+			// Set header so the called script knows that it's an XMLHttpRequest
+			xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+		} catch(e){}
+
+		// Allow custom headers/mimetypes
+		if ( s.beforeSend )
+			s.beforeSend(xml);
+			
+		if ( s.global )
+			jQuery.event.trigger("ajaxSend", [xml, s]);
+
+		// Wait for a response to come back
+		var onreadystatechange = function(isTimeout){
+			// The transfer is complete and the data is available, or the request timed out
+			if ( !requestDone && xml && (xml.readyState == 4 || isTimeout == "timeout") ) {
+				requestDone = true;
+				
+				// clear poll interval
+				if (ival) {
+					clearInterval(ival);
+					ival = null;
+				}
+				
+				status = isTimeout == "timeout" && "timeout" ||
+					!jQuery.httpSuccess( xml ) && "error" ||
+					s.ifModified && jQuery.httpNotModified( xml, s.url ) && "notmodified" ||
+					"success";
+
+				if ( status == "success" ) {
+					// Watch for, and catch, XML document parse errors
+					try {
+						// process the data (runs the xml through httpData regardless of callback)
+						data = jQuery.httpData( xml, s.dataType );
+					} catch(e) {
+						status = "parsererror";
+					}
+				}
+
+				// Make sure that the request was successful or notmodified
+				if ( status == "success" ) {
+					// Cache Last-Modified header, if ifModified mode.
+					var modRes;
+					try {
+						modRes = xml.getResponseHeader("Last-Modified");
+					} catch(e) {} // swallow exception thrown by FF if header is not available
+	
+					if ( s.ifModified && modRes )
+						jQuery.lastModified[s.url] = modRes;
+
+					// JSONP handles its own success callback
+					if ( !jsonp )
+						success();	
+				} else
+					jQuery.handleError(s, xml, status);
+
+				// Fire the complete handlers
+				complete();
+
+				// Stop memory leaks
+				if ( s.async )
+					xml = null;
+			}
+		};
+		
+		if ( s.async ) {
+			// don't attach the handler to the request, just poll it instead
+			var ival = setInterval(onreadystatechange, 13); 
+
+			// Timeout checker
+			if ( s.timeout > 0 )
+				setTimeout(function(){
+					// Check to see if the request is still happening
+					if ( xml ) {
+						// Cancel the request
+						xml.abort();
+	
+						if( !requestDone )
+							onreadystatechange( "timeout" );
+					}
+				}, s.timeout);
+		}
+			
+		// Send the data
+		try {
+			xml.send(s.data);
+		} catch(e) {
+			jQuery.handleError(s, xml, null, e);
+		}
+		
+		// firefox 1.5 doesn't fire statechange for sync requests
+		if ( !s.async )
+			onreadystatechange();
+
+		function success(){
+			// If a local callback was specified, fire it and pass it the data
+			if ( s.success )
+				s.success( data, status );
+
+			// Fire the global callback
+			if ( s.global )
+				jQuery.event.trigger( "ajaxSuccess", [xml, s] );
+		}
+
+		function complete(){
+			// Process result
+			if ( s.complete )
+				s.complete(xml, status);
+
+			// The request was completed
+			if ( s.global )
+				jQuery.event.trigger( "ajaxComplete", [xml, s] );
+
+			// Handle the global AJAX counter
+			if ( s.global && ! --jQuery.active )
+				jQuery.event.trigger( "ajaxStop" );
+		}
+		
+		// return XMLHttpRequest to allow aborting the request etc.
+		return xml;
+	},
+
+	handleError: function( s, xml, status, e ) {
+		// If a local callback was specified, fire it
+		if ( s.error ) s.error( xml, status, e );
+
+		// Fire the global callback
+		if ( s.global )
+			jQuery.event.trigger( "ajaxError", [xml, s, e] );
+	},
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Determines if an XMLHttpRequest was successful or not
+	httpSuccess: function( r ) {
+		try {
+			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+			return !r.status && location.protocol == "file:" ||
+				( r.status >= 200 && r.status < 300 ) || r.status == 304 || r.status == 1223 ||
+				jQuery.browser.safari && r.status == undefined;
+		} catch(e){}
+		return false;
+	},
+
+	// Determines if an XMLHttpRequest returns NotModified
+	httpNotModified: function( xml, url ) {
+		try {
+			var xmlRes = xml.getResponseHeader("Last-Modified");
+
+			// Firefox always returns 200. check Last-Modified date
+			return xml.status == 304 || xmlRes == jQuery.lastModified[url] ||
+				jQuery.browser.safari && xml.status == undefined;
+		} catch(e){}
+		return false;
+	},
+
+	httpData: function( r, type ) {
+		var ct = r.getResponseHeader("content-type");
+		var xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0;
+		var data = xml ? r.responseXML : r.responseText;
+
+		if ( xml && data.documentElement.tagName == "parsererror" )
+			throw "parsererror";
+
+		// If the type is "script", eval it in global context
+		if ( type == "script" )
+			jQuery.globalEval( data );
+
+		// Get the JavaScript object, if JSON is used.
+		if ( type == "json" )
+			data = eval("(" + data + ")");
+
+		return data;
+	},
+
+	// Serialize an array of form elements or a set of
+	// key/values into a query string
+	param: function( a ) {
+		var s = [];
+
+		// If an array was passed in, assume that it is an array
+		// of form elements
+		if ( a.constructor == Array || a.jquery )
+			// Serialize the form elements
+			jQuery.each( a, function(){
+				s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
+			});
+
+		// Otherwise, assume that it's an object of key/value pairs
+		else
+			// Serialize the key/values
+			for ( var j in a )
+				// If the value is an array then the key names need to be repeated
+				if ( a[j] && a[j].constructor == Array )
+					jQuery.each( a[j], function(){
+						s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
+					});
+				else
+					s.push( encodeURIComponent(j) + "=" + encodeURIComponent( a[j] ) );
+
+		// Return the resulting serialization
+		return s.join("&").replace(/%20/g, "+");
+	}
+
+});
+jQuery.fn.extend({
+	show: function(speed,callback){
+		return speed ?
+			this.animate({
+				height: "show", width: "show", opacity: "show"
+			}, speed, callback) :
+			
+			this.filter(":hidden").each(function(){
+				this.style.display = this.oldblock || "";
+				if ( jQuery.css(this,"display") == "none" ) {
+					var elem = jQuery("<" + this.tagName + " />").appendTo("body");
+					this.style.display = elem.css("display");
+					elem.remove();
+				}
+			}).end();
+	},
+	
+	hide: function(speed,callback){
+		return speed ?
+			this.animate({
+				height: "hide", width: "hide", opacity: "hide"
+			}, speed, callback) :
+			
+			this.filter(":visible").each(function(){
+				this.oldblock = this.oldblock || jQuery.css(this,"display");
+				this.style.display = "none";
+			}).end();
+	},
+
+	// Save the old toggle function
+	_toggle: jQuery.fn.toggle,
+	
+	toggle: function( fn, fn2 ){
+		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
+			this._toggle( fn, fn2 ) :
+			fn ?
+				this.animate({
+					height: "toggle", width: "toggle", opacity: "toggle"
+				}, fn, fn2) :
+				this.each(function(){
+					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
+				});
+	},
+	
+	slideDown: function(speed,callback){
+		return this.animate({height: "show"}, speed, callback);
+	},
+	
+	slideUp: function(speed,callback){
+		return this.animate({height: "hide"}, speed, callback);
+	},
+
+	slideToggle: function(speed, callback){
+		return this.animate({height: "toggle"}, speed, callback);
+	},
+	
+	fadeIn: function(speed, callback){
+		return this.animate({opacity: "show"}, speed, callback);
+	},
+	
+	fadeOut: function(speed, callback){
+		return this.animate({opacity: "hide"}, speed, callback);
+	},
+	
+	fadeTo: function(speed,to,callback){
+		return this.animate({opacity: to}, speed, callback);
+	},
+	
+	animate: function( prop, speed, easing, callback ) {
+		var optall = jQuery.speed(speed, easing, callback);
+
+		return this[ optall.queue === false ? "each" : "queue" ](function(){
+			if ( this.nodeType != 1)
+				return false;
+
+			var opt = jQuery.extend({}, optall);
+			var hidden = jQuery(this).is(":hidden"), self = this;
+			
+			for ( var p in prop ) {
+				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+					return jQuery.isFunction(opt.complete) && opt.complete.apply(this);
+
+				if ( p == "height" || p == "width" ) {
+					// Store display property
+					opt.display = jQuery.css(this, "display");
+
+					// Make sure that nothing sneaks out
+					opt.overflow = this.style.overflow;
+				}
+			}
+
+			if ( opt.overflow != null )
+				this.style.overflow = "hidden";
+
+			opt.curAnim = jQuery.extend({}, prop);
+			
+			jQuery.each( prop, function(name, val){
+				var e = new jQuery.fx( self, opt, name );
+
+				if ( /toggle|show|hide/.test(val) )
+					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+				else {
+					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+						start = e.cur(true) || 0;
+
+					if ( parts ) {
+						var end = parseFloat(parts[2]),
+							unit = parts[3] || "px";
+
+						// We need to compute starting value
+						if ( unit != "px" ) {
+							self.style[ name ] = (end || 1) + unit;
+							start = ((end || 1) / e.cur(true)) * start;
+							self.style[ name ] = start + unit;
+						}
+
+						// If a +=/-= token was provided, we're doing a relative animation
+						if ( parts[1] )
+							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+
+						e.custom( start, end, unit );
+					} else
+						e.custom( start, val, "" );
+				}
+			});
+
+			// For JS strict compliance
+			return true;
+		});
+	},
+	
+	queue: function(type, fn){
+		if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
+			fn = type;
+			type = "fx";
+		}
+
+		if ( !type || (typeof type == "string" && !fn) )
+			return queue( this[0], type );
+
+		return this.each(function(){
+			if ( this.nodeType != 1)
+				return;
+
+			if ( fn.constructor == Array )
+				queue(this, type, fn);
+			else {
+				queue(this, type).push( fn );
+			
+				if ( queue(this, type).length == 1 )
+					fn.apply(this);
+			}
+		});
+	},
+
+	stop: function(clearQueue, gotoEnd){
+		var timers = jQuery.timers;
+
+		if (clearQueue)
+			this.queue([]);
+
+		this.each(function(){
+			// go in reverse order so anything added to the queue during the loop is ignored
+			for ( var i = timers.length - 1; i >= 0; i-- )
+				if ( timers[i].elem == this ) {
+					if (gotoEnd)
+						// force the next step to be the last
+						timers[i](true);
+					timers.splice(i, 1);
+				}
+		});
+
+		// start the next in the queue if the last step wasn't forced
+		if (!gotoEnd)
+			this.dequeue();
+
+		return this;
+	}
+
+});
+
+var queue = function( elem, type, array ) {
+	if ( !elem )
+		return undefined;
+
+	type = type || "fx";
+
+	var q = jQuery.data( elem, type + "queue" );
+
+	if ( !q || array )
+		q = jQuery.data( elem, type + "queue", 
+			array ? jQuery.makeArray(array) : [] );
+
+	return q;
+};
+
+jQuery.fn.dequeue = function(type){
+	type = type || "fx";
+
+	return this.each(function(){
+		var q = queue(this, type);
+
+		q.shift();
+
+		if ( q.length )
+			q[0].apply( this );
+	});
+};
+
+jQuery.extend({
+	
+	speed: function(speed, easing, fn) {
+		var opt = speed && speed.constructor == Object ? speed : {
+			complete: fn || !fn && easing || 
+				jQuery.isFunction( speed ) && speed,
+			duration: speed,
+			easing: fn && easing || easing && easing.constructor != Function && easing
+		};
+
+		opt.duration = (opt.duration && opt.duration.constructor == Number ? 
+			opt.duration : 
+			{ slow: 600, fast: 200 }[opt.duration]) || 400;
+	
+		// Queueing
+		opt.old = opt.complete;
+		opt.complete = function(){
+			if ( opt.queue !== false )
+				jQuery(this).dequeue();
+			if ( jQuery.isFunction( opt.old ) )
+				opt.old.apply( this );
+		};
+	
+		return opt;
+	},
+	
+	easing: {
+		linear: function( p, n, firstNum, diff ) {
+			return firstNum + diff * p;
+		},
+		swing: function( p, n, firstNum, diff ) {
+			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+		}
+	},
+	
+	timers: [],
+	timerId: null,
+
+	fx: function( elem, options, prop ){
+		this.options = options;
+		this.elem = elem;
+		this.prop = prop;
+
+		if ( !options.orig )
+			options.orig = {};
+	}
+
+});
+
+jQuery.fx.prototype = {
+
+	// Simple function for setting a style value
+	update: function(){
+		if ( this.options.step )
+			this.options.step.apply( this.elem, [ this.now, this ] );
+
+		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+
+		// Set display property to block for height/width animations
+		if ( this.prop == "height" || this.prop == "width" )
+			this.elem.style.display = "block";
+	},
+
+	// Get the current size
+	cur: function(force){
+		if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
+			return this.elem[ this.prop ];
+
+		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+	},
+
+	// Start an animation from one number to another
+	custom: function(from, to, unit){
+		this.startTime = (new Date()).getTime();
+		this.start = from;
+		this.end = to;
+		this.unit = unit || this.unit || "px";
+		this.now = this.start;
+		this.pos = this.state = 0;
+		this.update();
+
+		var self = this;
+		function t(gotoEnd){
+			return self.step(gotoEnd);
+		}
+
+		t.elem = this.elem;
+
+		jQuery.timers.push(t);
+
+		if ( jQuery.timerId == null ) {
+			jQuery.timerId = setInterval(function(){
+				var timers = jQuery.timers;
+				
+				for ( var i = 0; i < timers.length; i++ )
+					if ( !timers[i]() )
+						timers.splice(i--, 1);
+
+				if ( !timers.length ) {
+					clearInterval( jQuery.timerId );
+					jQuery.timerId = null;
+				}
+			}, 13);
+		}
+	},
+
+	// Simple 'show' function
+	show: function(){
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+		this.options.show = true;
+
+		// Begin the animation
+		this.custom(0, this.cur());
+
+		// Make sure that we start at a small width/height to avoid any
+		// flash of content
+		if ( this.prop == "width" || this.prop == "height" )
+			this.elem.style[this.prop] = "1px";
+		
+		// Start by showing the element
+		jQuery(this.elem).show();
+	},
+
+	// Simple 'hide' function
+	hide: function(){
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+		this.options.hide = true;
+
+		// Begin the animation
+		this.custom(this.cur(), 0);
+	},
+
+	// Each step of an animation
+	step: function(gotoEnd){
+		var t = (new Date()).getTime();
+
+		if ( gotoEnd || t > this.options.duration + this.startTime ) {
+			this.now = this.end;
+			this.pos = this.state = 1;
+			this.update();
+
+			this.options.curAnim[ this.prop ] = true;
+
+			var done = true;
+			for ( var i in this.options.curAnim )
+				if ( this.options.curAnim[i] !== true )
+					done = false;
+
+			if ( done ) {
+				if ( this.options.display != null ) {
+					// Reset the overflow
+					this.elem.style.overflow = this.options.overflow;
+				
+					// Reset the display
+					this.elem.style.display = this.options.display;
+					if ( jQuery.css(this.elem, "display") == "none" )
+						this.elem.style.display = "block";
+				}
+
+				// Hide the element if the "hide" operation was done
+				if ( this.options.hide )
+					this.elem.style.display = "none";
+
+				// Reset the properties, if the item has been hidden or shown
+				if ( this.options.hide || this.options.show )
+					for ( var p in this.options.curAnim )
+						jQuery.attr(this.elem.style, p, this.options.orig[p]);
+			}
+
+			// If a callback was provided, execute it
+			if ( done && jQuery.isFunction( this.options.complete ) )
+				// Execute the complete function
+				this.options.complete.apply( this.elem );
+
+			return false;
+		} else {
+			var n = t - this.startTime;
+			this.state = n / this.options.duration;
+
+			// Perform the easing function, defaults to swing
+			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+			this.now = this.start + ((this.end - this.start) * this.pos);
+
+			// Perform the next step of the animation
+			this.update();
+		}
+
+		return true;
+	}
+
+};
+
+jQuery.fx.step = {
+	scrollLeft: function(fx){
+		fx.elem.scrollLeft = fx.now;
+	},
+
+	scrollTop: function(fx){
+		fx.elem.scrollTop = fx.now;
+	},
+
+	opacity: function(fx){
+		jQuery.attr(fx.elem.style, "opacity", fx.now);
+	},
+
+	_default: function(fx){
+		fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+	}
+};
+// The Offset Method
+// Originally By Brandon Aaron, part of the Dimension Plugin
+// http://jquery.com/plugins/project/dimensions
+jQuery.fn.offset = function() {
+	var left = 0, top = 0, elem = this[0], results;
+	
+	if ( elem ) with ( jQuery.browser ) {
+		var parent       = elem.parentNode, 
+		    offsetChild  = elem,
+		    offsetParent = elem.offsetParent, 
+		    doc          = elem.ownerDocument,
+		    safari2      = safari && parseInt(version) < 522,
+		    fixed        = jQuery.css(elem, "position") == "fixed";
+	
+		// Use getBoundingClientRect if available
+		if ( elem.getBoundingClientRect ) {
+			var box = elem.getBoundingClientRect();
+		
+			// Add the document scroll offsets
+			add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
+				box.top  + Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
+		
+			// IE adds the HTML element's border, by default it is medium which is 2px
+			// IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
+			// IE 7 standards mode, the border is always 2px
+			// This border/offset is typically represented by the clientLeft and clientTop properties
+			// However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
+			// Therefore this method will be off by 2px in IE while in quirksmode
+			add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
+	
+		// Otherwise loop through the offsetParents and parentNodes
+		} else {
+		
+			// Initial element offsets
+			add( elem.offsetLeft, elem.offsetTop );
+			
+			// Get parent offsets
+			while ( offsetParent ) {
+				// Add offsetParent offsets
+				add( offsetParent.offsetLeft, offsetParent.offsetTop );
+			
+				// Mozilla and Safari > 2 does not include the border on offset parents
+				// However Mozilla adds the border for table or table cells
+				if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
+					border( offsetParent );
+					
+				// Add the document scroll offsets if position is fixed on any offsetParent
+				if ( !fixed && jQuery.css(offsetParent, "position") == "fixed" )
+					fixed = true;
+			
+				// Set offsetChild to previous offsetParent unless it is the body element
+				offsetChild  = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
+				// Get next offsetParent
+				offsetParent = offsetParent.offsetParent;
+			}
+		
+			// Get parent scroll offsets
+			while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
+				// Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
+				if ( !/^inline|table.*$/i.test(jQuery.css(parent, "display")) )
+					// Subtract parent scroll offsets
+					add( -parent.scrollLeft, -parent.scrollTop );
+			
+				// Mozilla does not add the border for a parent that has overflow != visible
+				if ( mozilla && jQuery.css(parent, "overflow") != "visible" )
+					border( parent );
+			
+				// Get next parent
+				parent = parent.parentNode;
+			}
+		
+			// Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
+			// Mozilla doubles body offsets with a non-absolutely positioned offsetChild
+			if ( (safari2 && (fixed || jQuery.css(offsetChild, "position") == "absolute")) || 
+				(mozilla && jQuery.css(offsetChild, "position") != "absolute") )
+					add( -doc.body.offsetLeft, -doc.body.offsetTop );
+			
+			// Add the document scroll offsets if position is fixed
+			if ( fixed )
+				add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
+					Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
+		}
+
+		// Return an object with top and left properties
+		results = { top: top, left: left };
+	}
+
+	function border(elem) {
+		add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
+	}
+
+	function add(l, t) {
+		left += parseInt(l) || 0;
+		top += parseInt(t) || 0;
+	}
+
+	return results;
+};
+})();
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/todo b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/todo
new file mode 100644
index 0000000..107bbc5
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-treeview/todo
@@ -0,0 +1,8 @@
+1.5

+---

+

+* add classes and rules for root items

+* lazy-loading: render the complete tree, but only apply hitzones and hiding of children to the first level on load

+* async treeview

+  * support animations

+  * support persist options
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 0000000..df26116
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644
index 0000000..11e907d
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644
index 0000000..1bbdbda
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644
index 0000000..07931ee
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644
index 0000000..5136256
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644
index 0000000..c914507
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644
index 0000000..7d7e9be
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644
index 0000000..c87441d
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_222222_256x240.png b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_222222_256x240.png
new file mode 100644
index 0000000..eea26f2
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_222222_256x240.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_2e83ff_256x240.png b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_2e83ff_256x240.png
new file mode 100644
index 0000000..87e08f0
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_2e83ff_256x240.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_454545_256x240.png b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_454545_256x240.png
new file mode 100644
index 0000000..5718536
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_454545_256x240.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_888888_256x240.png b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_888888_256x240.png
new file mode 100644
index 0000000..cd6f0f1
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_888888_256x240.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_cd0a0a_256x240.png b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_cd0a0a_256x240.png
new file mode 100644
index 0000000..3e2443d
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/images/ui-icons_cd0a0a_256x240.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/jquery-ui-1.7.2.custom.css b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/jquery-ui-1.7.2.custom.css
new file mode 100644
index 0000000..444486b
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/css/smoothness/jquery-ui-1.7.2.custom.css
@@ -0,0 +1,406 @@
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+*/
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+.ui-helper-clearfix { display: inline-block; }
+/* required comment for clearfix to work in Opera \*/
+* html .ui-helper-clearfix { height:1%; }
+.ui-helper-clearfix { display:block; }
+/* end clearfix */
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
+
+
+
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+*/
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
+.ui-widget-content a { color: #222222; }
+.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
+.ui-widget-header a { color: #222222; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; outline: none; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; outline: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; outline: none; }
+.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; outline: none; text-decoration: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
+.ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; }
+.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
+.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
+.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
+.ui-corner-right {  -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
+.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
+.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }/* Accordion
+----------------------------------*/
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
+.ui-accordion .ui-accordion-li-fix { display: inline; }
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
+.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker
+----------------------------------*/
+.ui-datepicker { width: 17em; padding: .2em .2em 0; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month, 
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+    display: none; /*sorry for IE5*/
+    display/**/: block; /*sorry for IE5*/
+    position: absolute; /*must have*/
+    z-index: -1; /*must have*/
+    filter: mask(); /*must have*/
+    top: -4px; /*must have*/
+    left: -4px; /*must have*/
+    width: 200px; /*must have*/
+    height: 200px; /*must have*/
+}/* Dialog
+----------------------------------*/
+.ui-dialog { position: relative; padding: .2em; width: 300px; }
+.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative;  }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } 
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
+/* Progressbar
+----------------------------------*/
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable
+----------------------------------*/
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider
+----------------------------------*/
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
+----------------------------------*/
+.ui-tabs { padding: .2em; zoom: 1; }
+.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
+.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/index.html b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/index.html
new file mode 100644
index 0000000..a788c0b
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/index.html
@@ -0,0 +1,367 @@
+<!DOCTYPE html>

+<html>

+	<head>

+		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

+		<title>jQuery UI Example Page</title>

+		<link type="text/css" href="css/smoothness/jquery-ui-1.7.2.custom.css" rel="stylesheet" />	

+		<script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>

+		<script type="text/javascript" src="js/jquery-ui-1.7.2.custom.min.js"></script>

+		<script type="text/javascript">

+			$(function(){

+

+				// Accordion

+				$("#accordion").accordion({ header: "h3" });

+	

+				// Tabs

+				$('#tabs').tabs();

+	

+

+				// Dialog			

+				$('#dialog').dialog({

+					autoOpen: false,

+					width: 600,

+					buttons: {

+						"Ok": function() { 

+							$(this).dialog("close"); 

+						}, 

+						"Cancel": function() { 

+							$(this).dialog("close"); 

+						} 

+					}

+				});

+				

+				// Dialog Link

+				$('#dialog_link').click(function(){

+					$('#dialog').dialog('open');

+					return false;

+				});

+

+				// Datepicker

+				$('#datepicker').datepicker({

+					inline: true

+				});

+				

+				// Slider

+				$('#slider').slider({

+					range: true,

+					values: [17, 67]

+				});

+				

+				// Progressbar

+				$("#progressbar").progressbar({

+					value: 20 

+				});

+				

+				//hover states on the static widgets

+				$('#dialog_link, ul#icons li').hover(

+					function() { $(this).addClass('ui-state-hover'); }, 

+					function() { $(this).removeClass('ui-state-hover'); }

+				);

+				

+			});

+		</script>

+		<style type="text/css">

+			/*demo page css*/

+			body{ font: 62.5% "Trebuchet MS", sans-serif; margin: 50px;}

+			.demoHeaders { margin-top: 2em; }

+			#dialog_link {padding: .4em 1em .4em 20px;text-decoration: none;position: relative;}

+			#dialog_link span.ui-icon {margin: 0 5px 0 0;position: absolute;left: .2em;top: 50%;margin-top: -8px;}

+			ul#icons {margin: 0; padding: 0;}

+			ul#icons li {margin: 2px; position: relative; padding: 4px 0; cursor: pointer; float: left;  list-style: none;}

+			ul#icons span.ui-icon {float: left; margin: 0 4px;}

+		</style>	

+	</head>

+	<body>

+	<h1>Welcome to jQuery UI!</h1>

+	<p style="font-size: 1.3em; line-height: 1.5; margin: 1em 0; width: 50%;">This page demonstrates the widgets you downloaded using the theme you selected in the download builder. We've included and linked to minified versions of <a href="js/jquery-1.3.2.min.js">jQuery</a>, your personalized copy of <a href="js/jquery-ui-1.7.2.custom.min.js">jQuery UI (js/jquery-ui-1.7.2.custom.min.js)</a>, and <a href="css/smoothness/jquery-ui-1.7.2.custom.css">css/smoothness/jquery-ui-1.7.2.custom.css</a> which imports the entire jQuery UI CSS Framework. You can choose to link a subset of the CSS Framework depending on your needs. </p>

+	<p style="font-size: 1.2em; line-height: 1.5; margin: 1em 0; width: 50%;">You've downloaded components and a theme that are compatible with jQuery 1.3+. Please make sure you are using jQuery 1.3+ in your production environment. <em>If you need jQuery UI components that work with an earlier version of jQuery, you can choose an older version in the <a href="http://jqueryui.com/download">jQuery UI download builder</a>.</em></p>	

+

+	<p style="font-weight: bold; margin: 2em 0 1em; font-size: 1.3em;">YOUR COMPONENTS:</p>

+		

+		<!-- Accordion -->

+		<h2 class="demoHeaders">Accordion</h2>

+		<div id="accordion">

+			<div>

+				<h3><a href="#">First</a></h3>

+				<div>Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.</div>

+			</div>

+			<div>

+				<h3><a href="#">Second</a></h3>

+				<div>Phasellus mattis tincidunt nibh.</div>

+			</div>

+			<div>

+				<h3><a href="#">Third</a></h3>

+				<div>Nam dui erat, auctor a, dignissim quis.</div>

+			</div>

+		</div>

+	

+		<!-- Tabs -->

+		<h2 class="demoHeaders">Tabs</h2>

+		<div id="tabs">

+			<ul>

+				<li><a href="#tabs-1">First</a></li>

+				<li><a href="#tabs-2">Second</a></li>

+				<li><a href="#tabs-3">Third</a></li>

+			</ul>

+			<div id="tabs-1">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>

+			<div id="tabs-2">Phasellus mattis tincidunt nibh. Cras orci urna, blandit id, pretium vel, aliquet ornare, felis. Maecenas scelerisque sem non nisl. Fusce sed lorem in enim dictum bibendum.</div>

+			<div id="tabs-3">Nam dui erat, auctor a, dignissim quis, sollicitudin eu, felis. Pellentesque nisi urna, interdum eget, sagittis et, consequat vestibulum, lacus. Mauris porttitor ullamcorper augue.</div>

+		</div>

+	

+		<!-- Dialog NOTE: Dialog is not generated by UI in this demo so it can be visually styled in themeroller-->

+		<h2 class="demoHeaders">Dialog</h2>

+		<p><a href="#" id="dialog_link" class="ui-state-default ui-corner-all"><span class="ui-icon ui-icon-newwin"></span>Open Dialog</a></p>

+		

+		

+		<h2 class="demoHeaders">Overlay and Shadow Classes <em>(not currently used in UI widgets)</em></h2>

+		<div style="position: relative; width: 96%; height: 200px; padding:1% 4%; overflow:hidden;" class="fakewindowcontain">

+			<p>Lorem ipsum dolor sit amet,  Nulla nec tortor. Donec id elit quis purus consectetur consequat. </p><p>Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. </p><p>Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. </p><p>Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. </p><p>Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. </p><p>Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. </p>

+			

+			<!-- ui-dialog -->

+			<div class="ui-overlay"><div class="ui-widget-overlay"></div><div class="ui-widget-shadow ui-corner-all" style="width: 302px; height: 152px; position: absolute; left: 50px; top: 30px;"></div></div>

+			<div style="position: absolute; width: 280px; height: 130px;left: 50px; top: 30px; padding: 10px;" class="ui-widget ui-widget-content ui-corner-all">

+				<div class="ui-dialog-content ui-widget-content" style="background: none; border: 0;">

+					<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>

+				</div>

+			</div>

+		

+		</div>

+

+		

+		<!-- ui-dialog -->

+		<div id="dialog" title="Dialog Title">

+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>

+		</div>

+			

+				

+				

+		<h2 class="demoHeaders">Framework Icons (content color preview)</h2>

+		<ul id="icons" class="ui-widget ui-helper-clearfix">

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-carat-1-n"><span class="ui-icon ui-icon-carat-1-n"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-carat-1-ne"><span class="ui-icon ui-icon-carat-1-ne"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-carat-1-e"><span class="ui-icon ui-icon-carat-1-e"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-carat-1-se"><span class="ui-icon ui-icon-carat-1-se"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-carat-1-s"><span class="ui-icon ui-icon-carat-1-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-carat-1-sw"><span class="ui-icon ui-icon-carat-1-sw"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-carat-1-w"><span class="ui-icon ui-icon-carat-1-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-carat-1-nw"><span class="ui-icon ui-icon-carat-1-nw"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-carat-2-n-s"><span class="ui-icon ui-icon-carat-2-n-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-carat-2-e-w"><span class="ui-icon ui-icon-carat-2-e-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-n"><span class="ui-icon ui-icon-triangle-1-n"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-ne"><span class="ui-icon ui-icon-triangle-1-ne"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-e"><span class="ui-icon ui-icon-triangle-1-e"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-se"><span class="ui-icon ui-icon-triangle-1-se"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-s"><span class="ui-icon ui-icon-triangle-1-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-sw"><span class="ui-icon ui-icon-triangle-1-sw"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-w"><span class="ui-icon ui-icon-triangle-1-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-nw"><span class="ui-icon ui-icon-triangle-1-nw"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-2-n-s"><span class="ui-icon ui-icon-triangle-2-n-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-2-e-w"><span class="ui-icon ui-icon-triangle-2-e-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-n"><span class="ui-icon ui-icon-arrow-1-n"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-ne"><span class="ui-icon ui-icon-arrow-1-ne"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-e"><span class="ui-icon ui-icon-arrow-1-e"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-se"><span class="ui-icon ui-icon-arrow-1-se"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-s"><span class="ui-icon ui-icon-arrow-1-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-sw"><span class="ui-icon ui-icon-arrow-1-sw"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-w"><span class="ui-icon ui-icon-arrow-1-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-nw"><span class="ui-icon ui-icon-arrow-1-nw"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-2-n-s"><span class="ui-icon ui-icon-arrow-2-n-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-2-ne-sw"><span class="ui-icon ui-icon-arrow-2-ne-sw"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-2-e-w"><span class="ui-icon ui-icon-arrow-2-e-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-2-se-nw"><span class="ui-icon ui-icon-arrow-2-se-nw"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowstop-1-n"><span class="ui-icon ui-icon-arrowstop-1-n"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowstop-1-e"><span class="ui-icon ui-icon-arrowstop-1-e"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowstop-1-s"><span class="ui-icon ui-icon-arrowstop-1-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowstop-1-w"><span class="ui-icon ui-icon-arrowstop-1-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-n"><span class="ui-icon ui-icon-arrowthick-1-n"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-ne"><span class="ui-icon ui-icon-arrowthick-1-ne"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-e"><span class="ui-icon ui-icon-arrowthick-1-e"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-se"><span class="ui-icon ui-icon-arrowthick-1-se"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-s"><span class="ui-icon ui-icon-arrowthick-1-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-sw"><span class="ui-icon ui-icon-arrowthick-1-sw"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-w"><span class="ui-icon ui-icon-arrowthick-1-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-nw"><span class="ui-icon ui-icon-arrowthick-1-nw"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-2-n-s"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-2-ne-sw"><span class="ui-icon ui-icon-arrowthick-2-ne-sw"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-2-e-w"><span class="ui-icon ui-icon-arrowthick-2-e-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-2-se-nw"><span class="ui-icon ui-icon-arrowthick-2-se-nw"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthickstop-1-n"><span class="ui-icon ui-icon-arrowthickstop-1-n"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthickstop-1-e"><span class="ui-icon ui-icon-arrowthickstop-1-e"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthickstop-1-s"><span class="ui-icon ui-icon-arrowthickstop-1-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthickstop-1-w"><span class="ui-icon ui-icon-arrowthickstop-1-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturnthick-1-w"><span class="ui-icon ui-icon-arrowreturnthick-1-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturnthick-1-n"><span class="ui-icon ui-icon-arrowreturnthick-1-n"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturnthick-1-e"><span class="ui-icon ui-icon-arrowreturnthick-1-e"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturnthick-1-s"><span class="ui-icon ui-icon-arrowreturnthick-1-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturn-1-w"><span class="ui-icon ui-icon-arrowreturn-1-w"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturn-1-n"><span class="ui-icon ui-icon-arrowreturn-1-n"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturn-1-e"><span class="ui-icon ui-icon-arrowreturn-1-e"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturn-1-s"><span class="ui-icon ui-icon-arrowreturn-1-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowrefresh-1-w"><span class="ui-icon ui-icon-arrowrefresh-1-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowrefresh-1-n"><span class="ui-icon ui-icon-arrowrefresh-1-n"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowrefresh-1-e"><span class="ui-icon ui-icon-arrowrefresh-1-e"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowrefresh-1-s"><span class="ui-icon ui-icon-arrowrefresh-1-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-4"><span class="ui-icon ui-icon-arrow-4"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-4-diag"><span class="ui-icon ui-icon-arrow-4-diag"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-extlink"><span class="ui-icon ui-icon-extlink"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-newwin"><span class="ui-icon ui-icon-newwin"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-refresh"><span class="ui-icon ui-icon-refresh"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-shuffle"><span class="ui-icon ui-icon-shuffle"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-transfer-e-w"><span class="ui-icon ui-icon-transfer-e-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-transferthick-e-w"><span class="ui-icon ui-icon-transferthick-e-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-folder-collapsed"><span class="ui-icon ui-icon-folder-collapsed"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-folder-open"><span class="ui-icon ui-icon-folder-open"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-document"><span class="ui-icon ui-icon-document"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-document-b"><span class="ui-icon ui-icon-document-b"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-note"><span class="ui-icon ui-icon-note"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-mail-closed"><span class="ui-icon ui-icon-mail-closed"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-mail-open"><span class="ui-icon ui-icon-mail-open"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-suitcase"><span class="ui-icon ui-icon-suitcase"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-comment"><span class="ui-icon ui-icon-comment"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-person"><span class="ui-icon ui-icon-person"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-print"><span class="ui-icon ui-icon-print"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-trash"><span class="ui-icon ui-icon-trash"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-locked"><span class="ui-icon ui-icon-locked"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-unlocked"><span class="ui-icon ui-icon-unlocked"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-bookmark"><span class="ui-icon ui-icon-bookmark"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-tag"><span class="ui-icon ui-icon-tag"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-home"><span class="ui-icon ui-icon-home"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-flag"><span class="ui-icon ui-icon-flag"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-calculator"><span class="ui-icon ui-icon-calculator"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-cart"><span class="ui-icon ui-icon-cart"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-pencil"><span class="ui-icon ui-icon-pencil"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-clock"><span class="ui-icon ui-icon-clock"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-disk"><span class="ui-icon ui-icon-disk"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-calendar"><span class="ui-icon ui-icon-calendar"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-zoomin"><span class="ui-icon ui-icon-zoomin"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-zoomout"><span class="ui-icon ui-icon-zoomout"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-search"><span class="ui-icon ui-icon-search"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-wrench"><span class="ui-icon ui-icon-wrench"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-gear"><span class="ui-icon ui-icon-gear"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-heart"><span class="ui-icon ui-icon-heart"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-star"><span class="ui-icon ui-icon-star"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-link"><span class="ui-icon ui-icon-link"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-cancel"><span class="ui-icon ui-icon-cancel"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-plus"><span class="ui-icon ui-icon-plus"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-plusthick"><span class="ui-icon ui-icon-plusthick"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-minus"><span class="ui-icon ui-icon-minus"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-minusthick"><span class="ui-icon ui-icon-minusthick"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-close"><span class="ui-icon ui-icon-close"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-closethick"><span class="ui-icon ui-icon-closethick"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-key"><span class="ui-icon ui-icon-key"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-lightbulb"><span class="ui-icon ui-icon-lightbulb"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-scissors"><span class="ui-icon ui-icon-scissors"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-clipboard"><span class="ui-icon ui-icon-clipboard"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-copy"><span class="ui-icon ui-icon-copy"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-contact"><span class="ui-icon ui-icon-contact"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-image"><span class="ui-icon ui-icon-image"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-video"><span class="ui-icon ui-icon-video"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-script"><span class="ui-icon ui-icon-script"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-alert"><span class="ui-icon ui-icon-alert"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-info"><span class="ui-icon ui-icon-info"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-notice"><span class="ui-icon ui-icon-notice"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-help"><span class="ui-icon ui-icon-help"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-check"><span class="ui-icon ui-icon-check"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-bullet"><span class="ui-icon ui-icon-bullet"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-radio-off"><span class="ui-icon ui-icon-radio-off"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-radio-on"><span class="ui-icon ui-icon-radio-on"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-pin-w"><span class="ui-icon ui-icon-pin-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-pin-s"><span class="ui-icon ui-icon-pin-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-play"><span class="ui-icon ui-icon-play"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-pause"><span class="ui-icon ui-icon-pause"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-seek-next"><span class="ui-icon ui-icon-seek-next"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-seek-prev"><span class="ui-icon ui-icon-seek-prev"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-seek-end"><span class="ui-icon ui-icon-seek-end"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-seek-first"><span class="ui-icon ui-icon-seek-first"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-stop"><span class="ui-icon ui-icon-stop"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-eject"><span class="ui-icon ui-icon-eject"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-volume-off"><span class="ui-icon ui-icon-volume-off"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-volume-on"><span class="ui-icon ui-icon-volume-on"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-power"><span class="ui-icon ui-icon-power"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-signal-diag"><span class="ui-icon ui-icon-signal-diag"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-signal"><span class="ui-icon ui-icon-signal"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-battery-0"><span class="ui-icon ui-icon-battery-0"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-battery-1"><span class="ui-icon ui-icon-battery-1"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-battery-2"><span class="ui-icon ui-icon-battery-2"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-battery-3"><span class="ui-icon ui-icon-battery-3"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-plus"><span class="ui-icon ui-icon-circle-plus"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-minus"><span class="ui-icon ui-icon-circle-minus"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-close"><span class="ui-icon ui-icon-circle-close"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-triangle-e"><span class="ui-icon ui-icon-circle-triangle-e"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-triangle-s"><span class="ui-icon ui-icon-circle-triangle-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-triangle-w"><span class="ui-icon ui-icon-circle-triangle-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-triangle-n"><span class="ui-icon ui-icon-circle-triangle-n"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-arrow-e"><span class="ui-icon ui-icon-circle-arrow-e"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-arrow-s"><span class="ui-icon ui-icon-circle-arrow-s"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-arrow-w"><span class="ui-icon ui-icon-circle-arrow-w"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-arrow-n"><span class="ui-icon ui-icon-circle-arrow-n"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-zoomin"><span class="ui-icon ui-icon-circle-zoomin"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-zoomout"><span class="ui-icon ui-icon-circle-zoomout"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-check"><span class="ui-icon ui-icon-circle-check"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circlesmall-plus"><span class="ui-icon ui-icon-circlesmall-plus"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circlesmall-minus"><span class="ui-icon ui-icon-circlesmall-minus"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-circlesmall-close"><span class="ui-icon ui-icon-circlesmall-close"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-squaresmall-plus"><span class="ui-icon ui-icon-squaresmall-plus"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-squaresmall-minus"><span class="ui-icon ui-icon-squaresmall-minus"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-squaresmall-close"><span class="ui-icon ui-icon-squaresmall-close"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-dotted-vertical"><span class="ui-icon ui-icon-grip-dotted-vertical"></span></li>

+		

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-dotted-horizontal"><span class="ui-icon ui-icon-grip-dotted-horizontal"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-solid-vertical"><span class="ui-icon ui-icon-grip-solid-vertical"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-solid-horizontal"><span class="ui-icon ui-icon-grip-solid-horizontal"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-gripsmall-diagonal-se"><span class="ui-icon ui-icon-gripsmall-diagonal-se"></span></li>

+		<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-diagonal-se"><span class="ui-icon ui-icon-grip-diagonal-se"></span></li>

+		</ul>

+

+	

+		<!-- Slider -->

+		<h2 class="demoHeaders">Slider</h2>

+		<div id="slider"></div>

+	

+		<!-- Datepicker -->

+		<h2 class="demoHeaders">Datepicker</h2>

+		<div id="datepicker"></div>

+	

+		<!-- Progressbar -->

+		<h2 class="demoHeaders">Progressbar</h2>	

+		<div id="progressbar"></div>

+			

+		<!-- Highlight / Error -->

+		<h2 class="demoHeaders">Highlight / Error</h2>

+		<div class="ui-widget">

+			<div class="ui-state-highlight ui-corner-all" style="margin-top: 20px; padding: 0 .7em;"> 

+				<p><span class="ui-icon ui-icon-info" style="float: left; margin-right: .3em;"></span>

+				<strong>Hey!</strong> Sample ui-state-highlight style.</p>

+			</div>

+		</div>

+		<br/>

+		<div class="ui-widget">

+			<div class="ui-state-error ui-corner-all" style="padding: 0 .7em;"> 

+				<p><span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span> 

+				<strong>Alert:</strong> Sample ui-state-error style.</p>

+			</div>

+		</div>

+

+	</body>

+</html>

+

+

diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/jquery-1.3.2.min.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/jquery-1.3.2.min.js
new file mode 100644
index 0000000..a0fb883
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/jquery-1.3.2.min.js
@@ -0,0 +1,19 @@
+/*
+ * jQuery JavaScript Library v1.3.2
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
+ * Revision: 6246
+ */
+(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G<E;G++){L.call(K(this[G],H),this.length>1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"},isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){if(G&&/\S/.test(G)){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\s+/),function(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+"></"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/<tbody/i.test(S),N=!O.indexOf("<table")&&!R?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){return o.nth(E,2,"previousSibling")},nextAll:function(E){return o.dir(E,"nextSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(G){var J=[],L=o(G);for(var K=0,H=L.length;K<H;K++){var I=(K>0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
+/*
+ * Sizzle CSS Selector Engine - v0.9.3
+ *  Copyright 2009, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa<ab.length;aa++){if(ab[aa]===ab[aa-1]){ab.splice(aa--,1)}}}}}return ab};F.matches=function(T,U){return F(T,null,null,U)};F.find=function(aa,T,ab){var Z,X;if(!aa){return[]}for(var W=0,V=I.order.length;W<V;W++){var Y=I.order[W],X;if((X=I.match[Y].exec(aa))){var U=RegExp.leftContext;if(U.substr(U.length-1)!=="\\"){X[1]=(X[1]||"").replace(/\\/g,"");Z=I.find[Y](X,T,ab);if(Z!=null){aa=aa.replace(I.match[Y],"");break}}}}if(!Z){Z=T.getElementsByTagName("*")}return{set:Z,expr:aa}};F.filter=function(ad,ac,ag,W){var V=ad,ai=[],aa=ac,Y,T,Z=ac&&ac[0]&&Q(ac[0]);while(ad&&ac.length){for(var ab in I.filter){if((Y=I.match[ab].exec(ad))!=null){var U=I.filter[ab],ah,af;T=false;if(aa==ai){ai=[]}if(I.preFilter[ab]){Y=I.preFilter[ab](Y,aa,ag,ai,W,Z);if(!Y){T=ah=true}else{if(Y===true){continue}}}if(Y){for(var X=0;(af=aa[X])!=null;X++){if(af){ah=U(af,Y,X,aa);var ae=W^!!ah;if(ag&&ah!=null){if(ae){T=true}else{aa[X]=false}}else{if(ae){ai.push(af);T=true}}}}}if(ah!==g){if(!ag){aa=ai}ad=ad.replace(I.match[ab],"");if(!T){return[]}break}}}if(ad==V){if(T==null){throw"Syntax error, unrecognized expression: "+ad}else{break}}V=ad}return aa};var I=F.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(T){return T.getAttribute("href")}},relative:{"+":function(aa,T,Z){var X=typeof T==="string",ab=X&&!/\W/.test(T),Y=X&&!ab;if(ab&&!Z){T=T.toUpperCase()}for(var W=0,V=aa.length,U;W<V;W++){if((U=aa[W])){while((U=U.previousSibling)&&U.nodeType!==1){}aa[W]=Y||U&&U.nodeName===T?U||false:U===T}}if(Y){F.filter(T,aa,true)}},">":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){var W=Y.parentNode;Z[V]=W.nodeName===U?W:false}}}else{for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){Z[V]=X?Y.parentNode:Y.parentNode===U}}if(X){F.filter(U,Z,true)}}},"":function(W,U,Y){var V=L++,T=S;if(!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("parentNode",U,V,W,X,Y)},"~":function(W,U,Y){var V=L++,T=S;if(typeof U==="string"&&!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("previousSibling",U,V,W,X,Y)}},find:{ID:function(U,V,W){if(typeof V.getElementById!=="undefined"&&!W){var T=V.getElementById(U[1]);return T?[T]:[]}},NAME:function(V,Y,Z){if(typeof Y.getElementsByName!=="undefined"){var U=[],X=Y.getElementsByName(V[1]);for(var W=0,T=X.length;W<T;W++){if(X[W].getAttribute("name")===V[1]){U.push(X[W])}}return U.length===0?null:U}},TAG:function(T,U){return U.getElementsByTagName(T[1])}},preFilter:{CLASS:function(W,U,V,T,Z,aa){W=" "+W[1].replace(/\\/g,"")+" ";if(aa){return W}for(var X=0,Y;(Y=U[X])!=null;X++){if(Y){if(Z^(Y.className&&(" "+Y.className+" ").indexOf(W)>=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return U<T[3]-0},gt:function(V,U,T){return U>T[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W<T;W++){if(Y[W]===Z){return false}}return true}}}},CHILD:function(T,W){var Z=W[1],U=T;switch(Z){case"only":case"first":while(U=U.previousSibling){if(U.nodeType===1){return false}}if(Z=="first"){return true}U=T;case"last":while(U=U.nextSibling){if(U.nodeType===1){return false}}return true;case"nth":var V=W[2],ac=W[3];if(V==1&&ac==0){return true}var Y=W[0],ab=T.parentNode;if(ab&&(ab.sizcache!==Y||!T.nodeIndex)){var X=0;for(U=ab.firstChild;U;U=U.nextSibling){if(U.nodeType===1){U.nodeIndex=++X}}ab.sizcache=Y}var aa=T.nodeIndex-ac;if(V==0){return aa==0}else{return(aa%V==0&&aa/V>=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V<T;V++){U.push(X[V])}}else{for(var V=0;X[V];V++){U.push(X[V])}}}return U}}var G;if(document.documentElement.compareDocumentPosition){G=function(U,T){var V=U.compareDocumentPosition(T)&4?-1:U===T?0:1;if(V===0){hasDuplicate=true}return V}}else{if("sourceIndex" in document.documentElement){G=function(U,T){var V=U.sourceIndex-T.sourceIndex;if(V===0){hasDuplicate=true}return V}}else{if(document.createRange){G=function(W,U){var V=W.ownerDocument.createRange(),T=U.ownerDocument.createRange();V.selectNode(W);V.collapse(true);T.selectNode(U);T.collapse(true);var X=V.compareBoundaryPoints(Range.START_TO_END,T);if(X===0){hasDuplicate=true}return X}}}}(function(){var U=document.createElement("form"),V="script"+(new Date).getTime();U.innerHTML="<input name='"+V+"'/>";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="<a href='#'></a>";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="<p class='TEST'></p>";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="<div class='test e'></div><div class='test'></div>";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1&&!ac){T.sizcache=Y;T.sizset=W}if(T.nodeName===Z){X=T;break}T=T[U]}ad[W]=X}}}function S(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1){if(!ac){T.sizcache=Y;T.sizset=W}if(typeof Z!=="string"){if(T===Z){X=true;break}}else{if(F.filter(Z,[T]).length>0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z<U;Z++){F(T,V[Z],W)}return F.filter(X,W)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(T){return T.offsetWidth===0||T.offsetHeight===0};F.selectors.filters.visible=function(T){return T.offsetWidth>0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}return this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});F.sort(function(J,I){return o.data(J.elem,"closest")-o.data(I.elem,"closest")});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){return(G=false)}});return G}function i(F,E){return["live",F,E.replace(/\./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false,readyList:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&l==l.top){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML='   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H<F;H++){this[H].style.display=o.data(this[H],"olddisplay")||""}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G],"olddisplay",o.css(this[G],"display"))}}for(var G=0,F=this.length;G<F;G++){this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cur(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n);n=g}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})();
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/jquery-ui-1.7.2.custom.min.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/jquery-ui-1.7.2.custom.min.js
new file mode 100644
index 0000000..5497feb
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/jquery-ui-1.7.2.custom.min.js
@@ -0,0 +1,298 @@
+/*
+ * jQuery UI 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI
+ */
+jQuery.ui||(function(c){var i=c.fn.remove,d=c.browser.mozilla&&(parseFloat(c.browser.version)<1.9);c.ui={version:"1.7.2",plugin:{add:function(k,l,n){var m=c.ui[k].prototype;for(var j in n){m.plugins[j]=m.plugins[j]||[];m.plugins[j].push([l,n[j]])}},call:function(j,l,k){var n=j.plugins[l];if(!n||!j.element[0].parentNode){return}for(var m=0;m<n.length;m++){if(j.options[n[m][0]]){n[m][1].apply(j.element,k)}}}},contains:function(k,j){return document.compareDocumentPosition?k.compareDocumentPosition(j)&16:k!==j&&k.contains(j)},hasScroll:function(m,k){if(c(m).css("overflow")=="hidden"){return false}var j=(k&&k=="left")?"scrollLeft":"scrollTop",l=false;if(m[j]>0){return true}m[j]=1;l=(m[j]>0);m[j]=0;return l},isOverAxis:function(k,j,l){return(k>j)&&(k<(j+l))},isOver:function(o,k,n,m,j,l){return c.ui.isOverAxis(o,n,j)&&c.ui.isOverAxis(k,m,l)},keyCode:{BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};if(d){var f=c.attr,e=c.fn.removeAttr,h="http://www.w3.org/2005/07/aaa",a=/^aria-/,b=/^wairole:/;c.attr=function(k,j,l){var m=l!==undefined;return(j=="role"?(m?f.call(this,k,j,"wairole:"+l):(f.apply(this,arguments)||"").replace(b,"")):(a.test(j)?(m?k.setAttributeNS(h,j.replace(a,"aaa:"),l):f.call(this,k,j.replace(a,"aaa:"))):f.apply(this,arguments)))};c.fn.removeAttr=function(j){return(a.test(j)?this.each(function(){this.removeAttributeNS(h,j.replace(a,""))}):e.call(this,j))}}c.fn.extend({remove:function(){c("*",this).add(this).each(function(){c(this).triggerHandler("remove")});return i.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","").unbind("selectstart.ui")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})},scrollParent:function(){var j;if((c.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){j=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(c.curCSS(this,"position",1))&&(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}else{j=this.parents().filter(function(){return(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!j.length?c(document):j}});c.extend(c.expr[":"],{data:function(l,k,j){return !!c.data(l,j[3])},focusable:function(k){var l=k.nodeName.toLowerCase(),j=c.attr(k,"tabindex");return(/input|select|textarea|button|object/.test(l)?!k.disabled:"a"==l||"area"==l?k.href||!isNaN(j):!isNaN(j))&&!c(k)["area"==l?"parents":"closest"](":hidden").length},tabbable:function(k){var j=c.attr(k,"tabindex");return(isNaN(j)||j>=0)&&c(k).is(":focusable")}});function g(m,n,o,l){function k(q){var p=c[m][n][q]||[];return(typeof p=="string"?p.split(/,?\s+/):p)}var j=k("getter");if(l.length==1&&typeof l[0]=="string"){j=j.concat(k("getterSetter"))}return(c.inArray(o,j)!=-1)}c.widget=function(k,j){var l=k.split(".")[0];k=k.split(".")[1];c.fn[k]=function(p){var n=(typeof p=="string"),o=Array.prototype.slice.call(arguments,1);if(n&&p.substring(0,1)=="_"){return this}if(n&&g(l,k,p,o)){var m=c.data(this[0],k);return(m?m[p].apply(m,o):undefined)}return this.each(function(){var q=c.data(this,k);(!q&&!n&&c.data(this,k,new c[l][k](this,p))._init());(q&&n&&c.isFunction(q[p])&&q[p].apply(q,o))})};c[l]=c[l]||{};c[l][k]=function(o,n){var m=this;this.namespace=l;this.widgetName=k;this.widgetEventPrefix=c[l][k].eventPrefix||k;this.widgetBaseClass=l+"-"+k;this.options=c.extend({},c.widget.defaults,c[l][k].defaults,c.metadata&&c.metadata.get(o)[k],n);this.element=c(o).bind("setData."+k,function(q,p,r){if(q.target==o){return m._setData(p,r)}}).bind("getData."+k,function(q,p){if(q.target==o){return m._getData(p)}}).bind("remove",function(){return m.destroy()})};c[l][k].prototype=c.extend({},c.widget.prototype,j);c[l][k].getterSetter="option"};c.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").removeAttr("aria-disabled")},option:function(l,m){var k=l,j=this;if(typeof l=="string"){if(m===undefined){return this._getData(l)}k={};k[l]=m}c.each(k,function(n,o){j._setData(n,o)})},_getData:function(j){return this.options[j]},_setData:function(j,k){this.options[j]=k;if(j=="disabled"){this.element[k?"addClass":"removeClass"](this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").attr("aria-disabled",k)}},enable:function(){this._setData("disabled",false)},disable:function(){this._setData("disabled",true)},_trigger:function(l,m,n){var p=this.options[l],j=(l==this.widgetEventPrefix?l:this.widgetEventPrefix+l);m=c.Event(m);m.type=j;if(m.originalEvent){for(var k=c.event.props.length,o;k;){o=c.event.props[--k];m[o]=m.originalEvent[o]}}this.element.trigger(m,n);return !(c.isFunction(p)&&p.call(this.element[0],m,n)===false||m.isDefaultPrevented())}};c.widget.defaults={disabled:false};c.ui.mouse={_mouseInit:function(){var j=this;this.element.bind("mousedown."+this.widgetName,function(k){return j._mouseDown(k)}).bind("click."+this.widgetName,function(k){if(j._preventClickEvent){j._preventClickEvent=false;k.stopImmediatePropagation();return false}});if(c.browser.msie){this._mouseUnselectable=this.element.attr("unselectable");this.element.attr("unselectable","on")}this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName);(c.browser.msie&&this.element.attr("unselectable",this._mouseUnselectable))},_mouseDown:function(l){l.originalEvent=l.originalEvent||{};if(l.originalEvent.mouseHandled){return}(this._mouseStarted&&this._mouseUp(l));this._mouseDownEvent=l;var k=this,m=(l.which==1),j=(typeof this.options.cancel=="string"?c(l.target).parents().add(l.target).filter(this.options.cancel).length:false);if(!m||j||!this._mouseCapture(l)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){k.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(l)&&this._mouseDelayMet(l)){this._mouseStarted=(this._mouseStart(l)!==false);if(!this._mouseStarted){l.preventDefault();return true}}this._mouseMoveDelegate=function(n){return k._mouseMove(n)};this._mouseUpDelegate=function(n){return k._mouseUp(n)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);(c.browser.safari||l.preventDefault());l.originalEvent.mouseHandled=true;return true},_mouseMove:function(j){if(c.browser.msie&&!j.button){return this._mouseUp(j)}if(this._mouseStarted){this._mouseDrag(j);return j.preventDefault()}if(this._mouseDistanceMet(j)&&this._mouseDelayMet(j)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,j)!==false);(this._mouseStarted?this._mouseDrag(j):this._mouseUp(j))}return !this._mouseStarted},_mouseUp:function(j){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=(j.target==this._mouseDownEvent.target);this._mouseStop(j)}return false},_mouseDistanceMet:function(j){return(Math.max(Math.abs(this._mouseDownEvent.pageX-j.pageX),Math.abs(this._mouseDownEvent.pageY-j.pageY))>=this.options.distance)},_mouseDelayMet:function(j){return this.mouseDelayMet},_mouseStart:function(j){},_mouseDrag:function(j){},_mouseStop:function(j){},_mouseCapture:function(j){return true}};c.ui.mouse.defaults={cancel:null,distance:1,delay:0}})(jQuery);;/*
+ * jQuery UI Draggable 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(a){a.widget("ui.draggable",a.extend({},a.ui.mouse,{_init:function(){if(this.options.helper=="original"&&!(/^(?:r|a|f)/).test(this.element.css("position"))){this.element[0].style.position="relative"}(this.options.addClasses&&this.element.addClass("ui-draggable"));(this.options.disabled&&this.element.addClass("ui-draggable-disabled"));this._mouseInit()},destroy:function(){if(!this.element.data("draggable")){return}this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy()},_mouseCapture:function(b){var c=this.options;if(this.helper||c.disabled||a(b.target).is(".ui-resizable-handle")){return false}this.handle=this._getHandle(b);if(!this.handle){return false}return true},_mouseStart:function(b){var c=this.options;this.helper=this._createHelper(b);this._cacheHelperProportions();if(a.ui.ddmanager){a.ui.ddmanager.current=this}this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(b);this.originalPageX=b.pageX;this.originalPageY=b.pageY;if(c.cursorAt){this._adjustOffsetFromHelper(c.cursorAt)}if(c.containment){this._setContainment()}this._trigger("start",b);this._cacheHelperProportions();if(a.ui.ddmanager&&!c.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,b)}this.helper.addClass("ui-draggable-dragging");this._mouseDrag(b,true);return true},_mouseDrag:function(b,d){this.position=this._generatePosition(b);this.positionAbs=this._convertPositionTo("absolute");if(!d){var c=this._uiHash();this._trigger("drag",b,c);this.position=c.position}if(!this.options.axis||this.options.axis!="y"){this.helper[0].style.left=this.position.left+"px"}if(!this.options.axis||this.options.axis!="x"){this.helper[0].style.top=this.position.top+"px"}if(a.ui.ddmanager){a.ui.ddmanager.drag(this,b)}return false},_mouseStop:function(c){var d=false;if(a.ui.ddmanager&&!this.options.dropBehaviour){d=a.ui.ddmanager.drop(this,c)}if(this.dropped){d=this.dropped;this.dropped=false}if((this.options.revert=="invalid"&&!d)||(this.options.revert=="valid"&&d)||this.options.revert===true||(a.isFunction(this.options.revert)&&this.options.revert.call(this.element,d))){var b=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){b._trigger("stop",c);b._clear()})}else{this._trigger("stop",c);this._clear()}return false},_getHandle:function(b){var c=!this.options.handle||!a(this.options.handle,this.element).length?true:false;a(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==b.target){c=true}});return c},_createHelper:function(c){var d=this.options;var b=a.isFunction(d.helper)?a(d.helper.apply(this.element[0],[c])):(d.helper=="clone"?this.element.clone():this.element);if(!b.parents("body").length){b.appendTo((d.appendTo=="parent"?this.element[0].parentNode:d.appendTo))}if(b[0]!=this.element[0]&&!(/(fixed|absolute)/).test(b.css("position"))){b.css("position","absolute")}return b},_adjustOffsetFromHelper:function(b){if(b.left!=undefined){this.offset.click.left=b.left+this.margins.left}if(b.right!=undefined){this.offset.click.left=this.helperProportions.width-b.right+this.margins.left}if(b.top!=undefined){this.offset.click.top=b.top+this.margins.top}if(b.bottom!=undefined){this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top}},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])){b.left+=this.scrollParent.scrollLeft();b.top+=this.scrollParent.scrollTop()}if((this.offsetParent[0]==document.body)||(this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)){b={top:0,left:0}}return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var b=this.element.position();return{top:b.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:b.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else{return{top:0,left:0}}},_cacheMargins:function(){this.margins={left:(parseInt(this.element.css("marginLeft"),10)||0),top:(parseInt(this.element.css("marginTop"),10)||0)}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e=this.options;if(e.containment=="parent"){e.containment=this.helper[0].parentNode}if(e.containment=="document"||e.containment=="window"){this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(e.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(e.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]}if(!(/^(document|window|parent)$/).test(e.containment)&&e.containment.constructor!=Array){var c=a(e.containment)[0];if(!c){return}var d=a(e.containment).offset();var b=(a(c).css("overflow")!="hidden");this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(b?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(b?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}else{if(e.containment.constructor==Array){this.containment=e.containment}}},_convertPositionTo:function(f,h){if(!h){h=this.position}var c=f=="absolute"?1:-1;var e=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=(/(html|body)/i).test(b[0].tagName);return{top:(h.top+this.offset.relative.top*c+this.offset.parent.top*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(g?0:b.scrollTop()))*c)),left:(h.left+this.offset.relative.left*c+this.offset.parent.left*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:b.scrollLeft())*c))}},_generatePosition:function(e){var h=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,i=(/(html|body)/i).test(b[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0])){this.offset.relative=this._getRelativeOffset()}var d=e.pageX;var c=e.pageY;if(this.originalPosition){if(this.containment){if(e.pageX-this.offset.click.left<this.containment[0]){d=this.containment[0]+this.offset.click.left}if(e.pageY-this.offset.click.top<this.containment[1]){c=this.containment[1]+this.offset.click.top}if(e.pageX-this.offset.click.left>this.containment[2]){d=this.containment[2]+this.offset.click.left}if(e.pageY-this.offset.click.top>this.containment[3]){c=this.containment[3]+this.offset.click.top}}if(h.grid){var g=this.originalPageY+Math.round((c-this.originalPageY)/h.grid[1])*h.grid[1];c=this.containment?(!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:(!(g-this.offset.click.top<this.containment[1])?g-h.grid[1]:g+h.grid[1])):g;var f=this.originalPageX+Math.round((d-this.originalPageX)/h.grid[0])*h.grid[0];d=this.containment?(!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:(!(f-this.offset.click.left<this.containment[0])?f-h.grid[0]:f+h.grid[0])):f}}return{top:(c-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(i?0:b.scrollTop())))),left:(d-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:b.scrollLeft())))}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");if(this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval){this.helper.remove()}this.helper=null;this.cancelHelperRemoval=false},_trigger:function(b,c,d){d=d||this._uiHash();a.ui.plugin.call(this,b,[c,d]);if(b=="drag"){this.positionAbs=this._convertPositionTo("absolute")}return a.widget.prototype._trigger.call(this,b,c,d)},plugins:{},_uiHash:function(b){return{helper:this.helper,position:this.position,absolutePosition:this.positionAbs,offset:this.positionAbs}}}));a.extend(a.ui.draggable,{version:"1.7.2",eventPrefix:"drag",defaults:{addClasses:true,appendTo:"parent",axis:false,cancel:":input,option",connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,delay:0,distance:1,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false}});a.ui.plugin.add("draggable","connectToSortable",{start:function(c,e){var d=a(this).data("draggable"),f=d.options,b=a.extend({},e,{item:d.element});d.sortables=[];a(f.connectToSortable).each(function(){var g=a.data(this,"sortable");if(g&&!g.options.disabled){d.sortables.push({instance:g,shouldRevert:g.options.revert});g._refreshItems();g._trigger("activate",c,b)}})},stop:function(c,e){var d=a(this).data("draggable"),b=a.extend({},e,{item:d.element});a.each(d.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;d.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert){this.instance.options.revert=true}this.instance._mouseStop(c);this.instance.options.helper=this.instance.options._helper;if(d.options.helper=="original"){this.instance.currentItem.css({top:"auto",left:"auto"})}}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",c,b)}})},drag:function(c,f){var e=a(this).data("draggable"),b=this;var d=function(i){var n=this.offset.click.top,m=this.offset.click.left;var g=this.positionAbs.top,k=this.positionAbs.left;var j=i.height,l=i.width;var p=i.top,h=i.left;return a.ui.isOver(g+n,k+m,p,h,j,l)};a.each(e.sortables,function(g){this.instance.positionAbs=e.positionAbs;this.instance.helperProportions=e.helperProportions;this.instance.offset.click=e.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=a(b).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return f.helper[0]};c.target=this.instance.currentItem[0];this.instance._mouseCapture(c,true);this.instance._mouseStart(c,true,true);this.instance.offset.click.top=e.offset.click.top;this.instance.offset.click.left=e.offset.click.left;this.instance.offset.parent.left-=e.offset.parent.left-this.instance.offset.parent.left;this.instance.offset.parent.top-=e.offset.parent.top-this.instance.offset.parent.top;e._trigger("toSortable",c);e.dropped=this.instance.element;e.currentItem=e.element;this.instance.fromOutside=e}if(this.instance.currentItem){this.instance._mouseDrag(c)}}else{if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",c,this.instance._uiHash(this.instance));this.instance._mouseStop(c,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();if(this.instance.placeholder){this.instance.placeholder.remove()}e._trigger("fromSortable",c);e.dropped=false}}})}});a.ui.plugin.add("draggable","cursor",{start:function(c,d){var b=a("body"),e=a(this).data("draggable").options;if(b.css("cursor")){e._cursor=b.css("cursor")}b.css("cursor",e.cursor)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._cursor){a("body").css("cursor",d._cursor)}}});a.ui.plugin.add("draggable","iframeFix",{start:function(b,c){var d=a(this).data("draggable").options;a(d.iframeFix===true?"iframe":d.iframeFix).each(function(){a('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1000}).css(a(this).offset()).appendTo("body")})},stop:function(b,c){a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});a.ui.plugin.add("draggable","opacity",{start:function(c,d){var b=a(d.helper),e=a(this).data("draggable").options;if(b.css("opacity")){e._opacity=b.css("opacity")}b.css("opacity",e.opacity)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._opacity){a(c.helper).css("opacity",d._opacity)}}});a.ui.plugin.add("draggable","scroll",{start:function(c,d){var b=a(this).data("draggable");if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!="HTML"){b.overflowOffset=b.scrollParent.offset()}},drag:function(d,e){var c=a(this).data("draggable"),f=c.options,b=false;if(c.scrollParent[0]!=document&&c.scrollParent[0].tagName!="HTML"){if(!f.axis||f.axis!="x"){if((c.overflowOffset.top+c.scrollParent[0].offsetHeight)-d.pageY<f.scrollSensitivity){c.scrollParent[0].scrollTop=b=c.scrollParent[0].scrollTop+f.scrollSpeed}else{if(d.pageY-c.overflowOffset.top<f.scrollSensitivity){c.scrollParent[0].scrollTop=b=c.scrollParent[0].scrollTop-f.scrollSpeed}}}if(!f.axis||f.axis!="y"){if((c.overflowOffset.left+c.scrollParent[0].offsetWidth)-d.pageX<f.scrollSensitivity){c.scrollParent[0].scrollLeft=b=c.scrollParent[0].scrollLeft+f.scrollSpeed}else{if(d.pageX-c.overflowOffset.left<f.scrollSensitivity){c.scrollParent[0].scrollLeft=b=c.scrollParent[0].scrollLeft-f.scrollSpeed}}}}else{if(!f.axis||f.axis!="x"){if(d.pageY-a(document).scrollTop()<f.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()-f.scrollSpeed)}else{if(a(window).height()-(d.pageY-a(document).scrollTop())<f.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()+f.scrollSpeed)}}}if(!f.axis||f.axis!="y"){if(d.pageX-a(document).scrollLeft()<f.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()-f.scrollSpeed)}else{if(a(window).width()-(d.pageX-a(document).scrollLeft())<f.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()+f.scrollSpeed)}}}}if(b!==false&&a.ui.ddmanager&&!f.dropBehaviour){a.ui.ddmanager.prepareOffsets(c,d)}}});a.ui.plugin.add("draggable","snap",{start:function(c,d){var b=a(this).data("draggable"),e=b.options;b.snapElements=[];a(e.snap.constructor!=String?(e.snap.items||":data(draggable)"):e.snap).each(function(){var g=a(this);var f=g.offset();if(this!=b.element[0]){b.snapElements.push({item:this,width:g.outerWidth(),height:g.outerHeight(),top:f.top,left:f.left})}})},drag:function(u,p){var g=a(this).data("draggable"),q=g.options;var y=q.snapTolerance;var x=p.offset.left,w=x+g.helperProportions.width,f=p.offset.top,e=f+g.helperProportions.height;for(var v=g.snapElements.length-1;v>=0;v--){var s=g.snapElements[v].left,n=s+g.snapElements[v].width,m=g.snapElements[v].top,A=m+g.snapElements[v].height;if(!((s-y<x&&x<n+y&&m-y<f&&f<A+y)||(s-y<x&&x<n+y&&m-y<e&&e<A+y)||(s-y<w&&w<n+y&&m-y<f&&f<A+y)||(s-y<w&&w<n+y&&m-y<e&&e<A+y))){if(g.snapElements[v].snapping){(g.options.snap.release&&g.options.snap.release.call(g.element,u,a.extend(g._uiHash(),{snapItem:g.snapElements[v].item})))}g.snapElements[v].snapping=false;continue}if(q.snapMode!="inner"){var c=Math.abs(m-e)<=y;var z=Math.abs(A-f)<=y;var j=Math.abs(s-w)<=y;var k=Math.abs(n-x)<=y;if(c){p.position.top=g._convertPositionTo("relative",{top:m-g.helperProportions.height,left:0}).top-g.margins.top}if(z){p.position.top=g._convertPositionTo("relative",{top:A,left:0}).top-g.margins.top}if(j){p.position.left=g._convertPositionTo("relative",{top:0,left:s-g.helperProportions.width}).left-g.margins.left}if(k){p.position.left=g._convertPositionTo("relative",{top:0,left:n}).left-g.margins.left}}var h=(c||z||j||k);if(q.snapMode!="outer"){var c=Math.abs(m-f)<=y;var z=Math.abs(A-e)<=y;var j=Math.abs(s-x)<=y;var k=Math.abs(n-w)<=y;if(c){p.position.top=g._convertPositionTo("relative",{top:m,left:0}).top-g.margins.top}if(z){p.position.top=g._convertPositionTo("relative",{top:A-g.helperProportions.height,left:0}).top-g.margins.top}if(j){p.position.left=g._convertPositionTo("relative",{top:0,left:s}).left-g.margins.left}if(k){p.position.left=g._convertPositionTo("relative",{top:0,left:n-g.helperProportions.width}).left-g.margins.left}}if(!g.snapElements[v].snapping&&(c||z||j||k||h)){(g.options.snap.snap&&g.options.snap.snap.call(g.element,u,a.extend(g._uiHash(),{snapItem:g.snapElements[v].item})))}g.snapElements[v].snapping=(c||z||j||k||h)}}});a.ui.plugin.add("draggable","stack",{start:function(b,c){var e=a(this).data("draggable").options;var d=a.makeArray(a(e.stack.group)).sort(function(g,f){return(parseInt(a(g).css("zIndex"),10)||e.stack.min)-(parseInt(a(f).css("zIndex"),10)||e.stack.min)});a(d).each(function(f){this.style.zIndex=e.stack.min+f});this[0].style.zIndex=e.stack.min+d.length}});a.ui.plugin.add("draggable","zIndex",{start:function(c,d){var b=a(d.helper),e=a(this).data("draggable").options;if(b.css("zIndex")){e._zIndex=b.css("zIndex")}b.css("zIndex",e.zIndex)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._zIndex){a(c.helper).css("zIndex",d._zIndex)}}})})(jQuery);;/*
+ * jQuery UI Droppable 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Droppables
+ *
+ * Depends:
+ *	ui.core.js
+ *	ui.draggable.js
+ */
+(function(a){a.widget("ui.droppable",{_init:function(){var c=this.options,b=c.accept;this.isover=0;this.isout=1;this.options.accept=this.options.accept&&a.isFunction(this.options.accept)?this.options.accept:function(e){return e.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};a.ui.ddmanager.droppables[this.options.scope]=a.ui.ddmanager.droppables[this.options.scope]||[];a.ui.ddmanager.droppables[this.options.scope].push(this);(this.options.addClasses&&this.element.addClass("ui-droppable"))},destroy:function(){var b=a.ui.ddmanager.droppables[this.options.scope];for(var c=0;c<b.length;c++){if(b[c]==this){b.splice(c,1)}}this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable")},_setData:function(b,c){if(b=="accept"){this.options.accept=c&&a.isFunction(c)?c:function(e){return e.is(c)}}else{a.widget.prototype._setData.apply(this,arguments)}},_activate:function(c){var b=a.ui.ddmanager.current;if(this.options.activeClass){this.element.addClass(this.options.activeClass)}(b&&this._trigger("activate",c,this.ui(b)))},_deactivate:function(c){var b=a.ui.ddmanager.current;if(this.options.activeClass){this.element.removeClass(this.options.activeClass)}(b&&this._trigger("deactivate",c,this.ui(b)))},_over:function(c){var b=a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.hoverClass){this.element.addClass(this.options.hoverClass)}this._trigger("over",c,this.ui(b))}},_out:function(c){var b=a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.hoverClass){this.element.removeClass(this.options.hoverClass)}this._trigger("out",c,this.ui(b))}},_drop:function(c,d){var b=d||a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return false}var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var f=a.data(this,"droppable");if(f.options.greedy&&a.ui.intersect(b,a.extend(f,{offset:f.element.offset()}),f.options.tolerance)){e=true;return false}});if(e){return false}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.activeClass){this.element.removeClass(this.options.activeClass)}if(this.options.hoverClass){this.element.removeClass(this.options.hoverClass)}this._trigger("drop",c,this.ui(b));return this.element}return false},ui:function(b){return{draggable:(b.currentItem||b.element),helper:b.helper,position:b.position,absolutePosition:b.positionAbs,offset:b.positionAbs}}});a.extend(a.ui.droppable,{version:"1.7.2",eventPrefix:"drop",defaults:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"}});a.ui.intersect=function(q,j,o){if(!j.offset){return false}var e=(q.positionAbs||q.position.absolute).left,d=e+q.helperProportions.width,n=(q.positionAbs||q.position.absolute).top,m=n+q.helperProportions.height;var g=j.offset.left,c=g+j.proportions.width,p=j.offset.top,k=p+j.proportions.height;switch(o){case"fit":return(g<e&&d<c&&p<n&&m<k);break;case"intersect":return(g<e+(q.helperProportions.width/2)&&d-(q.helperProportions.width/2)<c&&p<n+(q.helperProportions.height/2)&&m-(q.helperProportions.height/2)<k);break;case"pointer":var h=((q.positionAbs||q.position.absolute).left+(q.clickOffset||q.offset.click).left),i=((q.positionAbs||q.position.absolute).top+(q.clickOffset||q.offset.click).top),f=a.ui.isOver(i,h,p,g,j.proportions.height,j.proportions.width);return f;break;case"touch":return((n>=p&&n<=k)||(m>=p&&m<=k)||(n<p&&m>k))&&((e>=g&&e<=c)||(d>=g&&d<=c)||(e<g&&d>c));break;default:return false;break}};a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(e,g){var b=a.ui.ddmanager.droppables[e.options.scope];var f=g?g.type:null;var h=(e.currentItem||e.element).find(":data(droppable)").andSelf();droppablesLoop:for(var d=0;d<b.length;d++){if(b[d].options.disabled||(e&&!b[d].options.accept.call(b[d].element[0],(e.currentItem||e.element)))){continue}for(var c=0;c<h.length;c++){if(h[c]==b[d].element[0]){b[d].proportions.height=0;continue droppablesLoop}}b[d].visible=b[d].element.css("display")!="none";if(!b[d].visible){continue}b[d].offset=b[d].element.offset();b[d].proportions={width:b[d].element[0].offsetWidth,height:b[d].element[0].offsetHeight};if(f=="mousedown"){b[d]._activate.call(b[d],g)}}},drop:function(b,c){var d=false;a.each(a.ui.ddmanager.droppables[b.options.scope],function(){if(!this.options){return}if(!this.options.disabled&&this.visible&&a.ui.intersect(b,this,this.options.tolerance)){d=this._drop.call(this,c)}if(!this.options.disabled&&this.visible&&this.options.accept.call(this.element[0],(b.currentItem||b.element))){this.isout=1;this.isover=0;this._deactivate.call(this,c)}});return d},drag:function(b,c){if(b.options.refreshPositions){a.ui.ddmanager.prepareOffsets(b,c)}a.each(a.ui.ddmanager.droppables[b.options.scope],function(){if(this.options.disabled||this.greedyChild||!this.visible){return}var e=a.ui.intersect(b,this,this.options.tolerance);var g=!e&&this.isover==1?"isout":(e&&this.isover==0?"isover":null);if(!g){return}var f;if(this.options.greedy){var d=this.element.parents(":data(droppable):eq(0)");if(d.length){f=a.data(d[0],"droppable");f.greedyChild=(g=="isover"?1:0)}}if(f&&g=="isover"){f.isover=0;f.isout=1;f._out.call(f,c)}this[g]=1;this[g=="isout"?"isover":"isout"]=0;this[g=="isover"?"_over":"_out"].call(this,c);if(f&&g=="isout"){f.isout=0;f.isover=1;f._over.call(f,c)}})}}})(jQuery);;/*
+ * jQuery UI Resizable 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Resizables
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(c){c.widget("ui.resizable",c.extend({},c.ui.mouse,{_init:function(){var e=this,j=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(j.aspectRatio),aspectRatio:j.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:j.helper||j.ghost||j.animate?j.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){if(/relative/.test(this.element.css("position"))&&c.browser.opera){this.element.css({position:"relative",top:"auto",left:"auto"})}this.element.wrap(c('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=j.handles||(!c(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var k=this.handles.split(",");this.handles={};for(var f=0;f<k.length;f++){var h=c.trim(k[f]),d="ui-resizable-"+h;var g=c('<div class="ui-resizable-handle '+d+'"></div>');if(/sw|se|ne|nw/.test(h)){g.css({zIndex:++j.zIndex})}if("se"==h){g.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[h]=".ui-resizable-"+h;this.element.append(g)}}this._renderAxis=function(p){p=p||this.element;for(var m in this.handles){if(this.handles[m].constructor==String){this.handles[m]=c(this.handles[m],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var n=c(this.handles[m],this.element),o=0;o=/sw|ne|nw|se|n|s/.test(m)?n.outerHeight():n.outerWidth();var l=["padding",/ne|nw|n/.test(m)?"Top":/se|sw|s/.test(m)?"Bottom":/^e$/.test(m)?"Right":"Left"].join("");p.css(l,o);this._proportionallyResize()}if(!c(this.handles[m]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!e.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}e.axis=i&&i[1]?i[1]:"se"}});if(j.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){c(this).removeClass("ui-resizable-autohide");e._handles.show()},function(){if(!e.resizing){c(this).addClass("ui-resizable-autohide");e._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var d=function(f){c(f).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){d(this.element);var e=this.element;e.parent().append(this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")})).end().remove()}this.originalElement.css("resize",this.originalResizeStyle);d(this.originalElement)},_mouseCapture:function(e){var f=false;for(var d in this.handles){if(c(this.handles[d])[0]==e.target){f=true}}return this.options.disabled||!!f},_mouseStart:function(f){var i=this.options,e=this.element.position(),d=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(d.is(".ui-draggable")||(/absolute/).test(d.css("position"))){d.css({position:"absolute",top:e.top,left:e.left})}if(c.browser.opera&&(/relative/).test(d.css("position"))){d.css({position:"relative",top:"auto",left:"auto"})}this._renderProxy();var j=b(this.helper.css("left")),g=b(this.helper.css("top"));if(i.containment){j+=c(i.containment).scrollLeft()||0;g+=c(i.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:j,top:g};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:j,top:g};this.sizeDiff={width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:f.pageX,top:f.pageY};this.aspectRatio=(typeof i.aspectRatio=="number")?i.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var h=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",h=="auto"?this.axis+"-resize":h);d.addClass("ui-resizable-resizing");this._propagate("start",f);return true},_mouseDrag:function(d){var g=this.helper,f=this.options,l={},p=this,i=this.originalMousePosition,m=this.axis;var q=(d.pageX-i.left)||0,n=(d.pageY-i.top)||0;var h=this._change[m];if(!h){return false}var k=h.apply(this,[d,q,n]),j=c.browser.msie&&c.browser.version<7,e=this.sizeDiff;if(this._aspectRatio||d.shiftKey){k=this._updateRatio(k,d)}k=this._respectSize(k,d);this._propagate("resize",d);g.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(k);this._trigger("resize",d,this.ui());return false},_mouseStop:function(g){this.resizing=false;var h=this.options,l=this;if(this._helper){var f=this._proportionallyResizeElements,d=f.length&&(/textarea/i).test(f[0].nodeName),e=d&&c.ui.hasScroll(f[0],"left")?0:l.sizeDiff.height,j=d?0:l.sizeDiff.width;var m={width:(l.size.width-j),height:(l.size.height-e)},i=(parseInt(l.element.css("left"),10)+(l.position.left-l.originalPosition.left))||null,k=(parseInt(l.element.css("top"),10)+(l.position.top-l.originalPosition.top))||null;if(!h.animate){this.element.css(c.extend(m,{top:k,left:i}))}l.helper.height(l.size.height);l.helper.width(l.size.width);if(this._helper&&!h.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",g);if(this._helper){this.helper.remove()}return false},_updateCache:function(d){var e=this.options;this.offset=this.helper.offset();if(a(d.left)){this.position.left=d.left}if(a(d.top)){this.position.top=d.top}if(a(d.height)){this.size.height=d.height}if(a(d.width)){this.size.width=d.width}},_updateRatio:function(g,f){var h=this.options,i=this.position,e=this.size,d=this.axis;if(g.height){g.width=(e.height*this.aspectRatio)}else{if(g.width){g.height=(e.width/this.aspectRatio)}}if(d=="sw"){g.left=i.left+(e.width-g.width);g.top=null}if(d=="nw"){g.top=i.top+(e.height-g.height);g.left=i.left+(e.width-g.width)}return g},_respectSize:function(k,f){var i=this.helper,h=this.options,q=this._aspectRatio||f.shiftKey,p=this.axis,s=a(k.width)&&h.maxWidth&&(h.maxWidth<k.width),l=a(k.height)&&h.maxHeight&&(h.maxHeight<k.height),g=a(k.width)&&h.minWidth&&(h.minWidth>k.width),r=a(k.height)&&h.minHeight&&(h.minHeight>k.height);if(g){k.width=h.minWidth}if(r){k.height=h.minHeight}if(s){k.width=h.maxWidth}if(l){k.height=h.maxHeight}var e=this.originalPosition.left+this.originalSize.width,n=this.position.top+this.size.height;var j=/sw|nw|w/.test(p),d=/nw|ne|n/.test(p);if(g&&j){k.left=e-h.minWidth}if(s&&j){k.left=e-h.maxWidth}if(r&&d){k.top=n-h.minHeight}if(l&&d){k.top=n-h.maxHeight}var m=!k.width&&!k.height;if(m&&!k.left&&k.top){k.top=null}else{if(m&&!k.top&&k.left){k.left=null}}return k},_proportionallyResize:function(){var j=this.options;if(!this._proportionallyResizeElements.length){return}var f=this.helper||this.element;for(var e=0;e<this._proportionallyResizeElements.length;e++){var g=this._proportionallyResizeElements[e];if(!this.borderDif){var d=[g.css("borderTopWidth"),g.css("borderRightWidth"),g.css("borderBottomWidth"),g.css("borderLeftWidth")],h=[g.css("paddingTop"),g.css("paddingRight"),g.css("paddingBottom"),g.css("paddingLeft")];this.borderDif=c.map(d,function(k,m){var l=parseInt(k,10)||0,n=parseInt(h[m],10)||0;return l+n})}if(c.browser.msie&&!(!(c(f).is(":hidden")||c(f).parents(":hidden").length))){continue}g.css({height:(f.height()-this.borderDif[0]-this.borderDif[2])||0,width:(f.width()-this.borderDif[1]-this.borderDif[3])||0})}},_renderProxy:function(){var e=this.element,h=this.options;this.elementOffset=e.offset();if(this._helper){this.helper=this.helper||c('<div style="overflow:hidden;"></div>');var d=c.browser.msie&&c.browser.version<7,f=(d?1:0),g=(d?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+g,height:this.element.outerHeight()+g,position:"absolute",left:this.elementOffset.left-f+"px",top:this.elementOffset.top-f+"px",zIndex:++h.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(f,e,d){return{width:this.originalSize.width+e}},w:function(g,e,d){var i=this.options,f=this.originalSize,h=this.originalPosition;return{left:h.left+e,width:f.width-e}},n:function(g,e,d){var i=this.options,f=this.originalSize,h=this.originalPosition;return{top:h.top+d,height:f.height-d}},s:function(f,e,d){return{height:this.originalSize.height+d}},se:function(f,e,d){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[f,e,d]))},sw:function(f,e,d){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[f,e,d]))},ne:function(f,e,d){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[f,e,d]))},nw:function(f,e,d){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[f,e,d]))}},_propagate:function(e,d){c.ui.plugin.call(this,e,[d,this.ui()]);(e!="resize"&&this._trigger(e,d,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}));c.extend(c.ui.resizable,{version:"1.7.2",eventPrefix:"resize",defaults:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,cancel:":input,option",containment:false,delay:0,distance:1,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000}});c.ui.plugin.add("resizable","alsoResize",{start:function(e,f){var d=c(this).data("resizable"),g=d.options;_store=function(h){c(h).each(function(){c(this).data("resizable-alsoresize",{width:parseInt(c(this).width(),10),height:parseInt(c(this).height(),10),left:parseInt(c(this).css("left"),10),top:parseInt(c(this).css("top"),10)})})};if(typeof(g.alsoResize)=="object"&&!g.alsoResize.parentNode){if(g.alsoResize.length){g.alsoResize=g.alsoResize[0];_store(g.alsoResize)}else{c.each(g.alsoResize,function(h,i){_store(h)})}}else{_store(g.alsoResize)}},resize:function(f,h){var e=c(this).data("resizable"),i=e.options,g=e.originalSize,k=e.originalPosition;var j={height:(e.size.height-g.height)||0,width:(e.size.width-g.width)||0,top:(e.position.top-k.top)||0,left:(e.position.left-k.left)||0},d=function(l,m){c(l).each(function(){var p=c(this),q=c(this).data("resizable-alsoresize"),o={},n=m&&m.length?m:["width","height","top","left"];c.each(n||["width","height","top","left"],function(r,t){var s=(q[t]||0)+(j[t]||0);if(s&&s>=0){o[t]=s||null}});if(/relative/.test(p.css("position"))&&c.browser.opera){e._revertToRelativePosition=true;p.css({position:"absolute",top:"auto",left:"auto"})}p.css(o)})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.nodeType){c.each(i.alsoResize,function(l,m){d(l,m)})}else{d(i.alsoResize)}},stop:function(e,f){var d=c(this).data("resizable");if(d._revertToRelativePosition&&c.browser.opera){d._revertToRelativePosition=false;el.css({position:"relative"})}c(this).removeData("resizable-alsoresize-start")}});c.ui.plugin.add("resizable","animate",{stop:function(h,m){var n=c(this).data("resizable"),i=n.options;var g=n._proportionallyResizeElements,d=g.length&&(/textarea/i).test(g[0].nodeName),e=d&&c.ui.hasScroll(g[0],"left")?0:n.sizeDiff.height,k=d?0:n.sizeDiff.width;var f={width:(n.size.width-k),height:(n.size.height-e)},j=(parseInt(n.element.css("left"),10)+(n.position.left-n.originalPosition.left))||null,l=(parseInt(n.element.css("top"),10)+(n.position.top-n.originalPosition.top))||null;n.element.animate(c.extend(f,l&&j?{top:l,left:j}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var o={width:parseInt(n.element.css("width"),10),height:parseInt(n.element.css("height"),10),top:parseInt(n.element.css("top"),10),left:parseInt(n.element.css("left"),10)};if(g&&g.length){c(g[0]).css({width:o.width,height:o.height})}n._updateCache(o);n._propagate("resize",h)}})}});c.ui.plugin.add("resizable","containment",{start:function(e,q){var s=c(this).data("resizable"),i=s.options,k=s.element;var f=i.containment,j=(f instanceof c)?f.get(0):(/parent/.test(f))?k.parent().get(0):f;if(!j){return}s.containerElement=c(j);if(/document/.test(f)||f==document){s.containerOffset={left:0,top:0};s.containerPosition={left:0,top:0};s.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var m=c(j),h=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){h[p]=b(m.css("padding"+o))});s.containerOffset=m.offset();s.containerPosition=m.position();s.containerSize={height:(m.innerHeight()-h[3]),width:(m.innerWidth()-h[1])};var n=s.containerOffset,d=s.containerSize.height,l=s.containerSize.width,g=(c.ui.hasScroll(j,"left")?j.scrollWidth:l),r=(c.ui.hasScroll(j)?j.scrollHeight:d);s.parentData={element:j,left:n.left,top:n.top,width:g,height:r}}},resize:function(f,p){var s=c(this).data("resizable"),h=s.options,e=s.containerSize,n=s.containerOffset,l=s.size,m=s.position,q=s._aspectRatio||f.shiftKey,d={top:0,left:0},g=s.containerElement;if(g[0]!=document&&(/static/).test(g.css("position"))){d=n}if(m.left<(s._helper?n.left:0)){s.size.width=s.size.width+(s._helper?(s.position.left-n.left):(s.position.left-d.left));if(q){s.size.height=s.size.width/h.aspectRatio}s.position.left=h.helper?n.left:0}if(m.top<(s._helper?n.top:0)){s.size.height=s.size.height+(s._helper?(s.position.top-n.top):s.position.top);if(q){s.size.width=s.size.height*h.aspectRatio}s.position.top=s._helper?n.top:0}s.offset.left=s.parentData.left+s.position.left;s.offset.top=s.parentData.top+s.position.top;var k=Math.abs((s._helper?s.offset.left-d.left:(s.offset.left-d.left))+s.sizeDiff.width),r=Math.abs((s._helper?s.offset.top-d.top:(s.offset.top-n.top))+s.sizeDiff.height);var j=s.containerElement.get(0)==s.element.parent().get(0),i=/relative|absolute/.test(s.containerElement.css("position"));if(j&&i){k-=s.parentData.left}if(k+s.size.width>=s.parentData.width){s.size.width=s.parentData.width-k;if(q){s.size.height=s.size.width/s.aspectRatio}}if(r+s.size.height>=s.parentData.height){s.size.height=s.parentData.height-r;if(q){s.size.width=s.size.height*s.aspectRatio}}},stop:function(e,m){var p=c(this).data("resizable"),f=p.options,k=p.position,l=p.containerOffset,d=p.containerPosition,g=p.containerElement;var i=c(p.helper),q=i.offset(),n=i.outerWidth()-p.sizeDiff.width,j=i.outerHeight()-p.sizeDiff.height;if(p._helper&&!f.animate&&(/relative/).test(g.css("position"))){c(this).css({left:q.left-d.left-l.left,width:n,height:j})}if(p._helper&&!f.animate&&(/static/).test(g.css("position"))){c(this).css({left:q.left-d.left-l.left,width:n,height:j})}}});c.ui.plugin.add("resizable","ghost",{start:function(f,g){var d=c(this).data("resizable"),h=d.options,e=d.size;d.ghost=d.originalElement.clone();d.ghost.css({opacity:0.25,display:"block",position:"relative",height:e.height,width:e.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof h.ghost=="string"?h.ghost:"");d.ghost.appendTo(d.helper)},resize:function(e,f){var d=c(this).data("resizable"),g=d.options;if(d.ghost){d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})}},stop:function(e,f){var d=c(this).data("resizable"),g=d.options;if(d.ghost&&d.helper){d.helper.get(0).removeChild(d.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(d,l){var n=c(this).data("resizable"),g=n.options,j=n.size,h=n.originalSize,i=n.originalPosition,m=n.axis,k=g._aspectRatio||d.shiftKey;g.grid=typeof g.grid=="number"?[g.grid,g.grid]:g.grid;var f=Math.round((j.width-h.width)/(g.grid[0]||1))*(g.grid[0]||1),e=Math.round((j.height-h.height)/(g.grid[1]||1))*(g.grid[1]||1);if(/^(se|s|e)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e}else{if(/^(ne)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e;n.position.top=i.top-e}else{if(/^(sw)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e;n.position.left=i.left-f}else{n.size.width=h.width+f;n.size.height=h.height+e;n.position.top=i.top-e;n.position.left=i.left-f}}}}});var b=function(d){return parseInt(d,10)||0};var a=function(d){return !isNaN(parseInt(d,10))}})(jQuery);;/*
+ * jQuery UI Selectable 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Selectables
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(a){a.widget("ui.selectable",a.extend({},a.ui.mouse,{_init:function(){var b=this;this.element.addClass("ui-selectable");this.dragged=false;var c;this.refresh=function(){c=a(b.options.filter,b.element[0]);c.each(function(){var d=a(this);var e=d.offset();a.data(this,"selectable-item",{element:this,$element:d,left:e.left,top:e.top,right:e.left+d.outerWidth(),bottom:e.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"),selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=c.addClass("ui-selectee");this._mouseInit();this.helper=a(document.createElement("div")).css({border:"1px dotted black"}).addClass("ui-selectable-helper")},destroy:function(){this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy()},_mouseStart:function(d){var b=this;this.opos=[d.pageX,d.pageY];if(this.options.disabled){return}var c=this.options;this.selectees=a(c.filter,this.element[0]);this._trigger("start",d);a(c.appendTo).append(this.helper);this.helper.css({"z-index":100,position:"absolute",left:d.clientX,top:d.clientY,width:0,height:0});if(c.autoRefresh){this.refresh()}this.selectees.filter(".ui-selected").each(function(){var e=a.data(this,"selectable-item");e.startselected=true;if(!d.metaKey){e.$element.removeClass("ui-selected");e.selected=false;e.$element.addClass("ui-unselecting");e.unselecting=true;b._trigger("unselecting",d,{unselecting:e.element})}});a(d.target).parents().andSelf().each(function(){var e=a.data(this,"selectable-item");if(e){e.$element.removeClass("ui-unselecting").addClass("ui-selecting");e.unselecting=false;e.selecting=true;e.selected=true;b._trigger("selecting",d,{selecting:e.element});return false}})},_mouseDrag:function(i){var c=this;this.dragged=true;if(this.options.disabled){return}var e=this.options;var d=this.opos[0],h=this.opos[1],b=i.pageX,g=i.pageY;if(d>b){var f=b;b=d;d=f}if(h>g){var f=g;g=h;h=f}this.helper.css({left:d,top:h,width:b-d,height:g-h});this.selectees.each(function(){var j=a.data(this,"selectable-item");if(!j||j.element==c.element[0]){return}var k=false;if(e.tolerance=="touch"){k=(!(j.left>b||j.right<d||j.top>g||j.bottom<h))}else{if(e.tolerance=="fit"){k=(j.left>d&&j.right<b&&j.top>h&&j.bottom<g)}}if(k){if(j.selected){j.$element.removeClass("ui-selected");j.selected=false}if(j.unselecting){j.$element.removeClass("ui-unselecting");j.unselecting=false}if(!j.selecting){j.$element.addClass("ui-selecting");j.selecting=true;c._trigger("selecting",i,{selecting:j.element})}}else{if(j.selecting){if(i.metaKey&&j.startselected){j.$element.removeClass("ui-selecting");j.selecting=false;j.$element.addClass("ui-selected");j.selected=true}else{j.$element.removeClass("ui-selecting");j.selecting=false;if(j.startselected){j.$element.addClass("ui-unselecting");j.unselecting=true}c._trigger("unselecting",i,{unselecting:j.element})}}if(j.selected){if(!i.metaKey&&!j.startselected){j.$element.removeClass("ui-selected");j.selected=false;j.$element.addClass("ui-unselecting");j.unselecting=true;c._trigger("unselecting",i,{unselecting:j.element})}}}});return false},_mouseStop:function(d){var b=this;this.dragged=false;var c=this.options;a(".ui-unselecting",this.element[0]).each(function(){var e=a.data(this,"selectable-item");e.$element.removeClass("ui-unselecting");e.unselecting=false;e.startselected=false;b._trigger("unselected",d,{unselected:e.element})});a(".ui-selecting",this.element[0]).each(function(){var e=a.data(this,"selectable-item");e.$element.removeClass("ui-selecting").addClass("ui-selected");e.selecting=false;e.selected=true;e.startselected=true;b._trigger("selected",d,{selected:e.element})});this._trigger("stop",d);this.helper.remove();return false}}));a.extend(a.ui.selectable,{version:"1.7.2",defaults:{appendTo:"body",autoRefresh:true,cancel:":input,option",delay:0,distance:0,filter:"*",tolerance:"touch"}})})(jQuery);;/*
+ * jQuery UI Sortable 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Sortables
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(a){a.widget("ui.sortable",a.extend({},a.ui.mouse,{_init:function(){var b=this.options;this.containerCache={};this.element.addClass("ui-sortable");this.refresh();this.floating=this.items.length?(/left|right/).test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--){this.items[b].item.removeData("sortable-item")}},_mouseCapture:function(e,f){if(this.reverting){return false}if(this.options.disabled||this.options.type=="static"){return false}this._refreshItems(e);var d=null,c=this,b=a(e.target).parents().each(function(){if(a.data(this,"sortable-item")==c){d=a(this);return false}});if(a.data(e.target,"sortable-item")==c){d=a(e.target)}if(!d){return false}if(this.options.handle&&!f){var g=false;a(this.options.handle,d).find("*").andSelf().each(function(){if(this==e.target){g=true}});if(!g){return false}}this.currentItem=d;this._removeCurrentsFromItems();return true},_mouseStart:function(e,f,b){var g=this.options,c=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(e);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");a.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(e);this.originalPageX=e.pageX;this.originalPageY=e.pageY;if(g.cursorAt){this._adjustOffsetFromHelper(g.cursorAt)}this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};if(this.helper[0]!=this.currentItem[0]){this.currentItem.hide()}this._createPlaceholder();if(g.containment){this._setContainment()}if(g.cursor){if(a("body").css("cursor")){this._storedCursor=a("body").css("cursor")}a("body").css("cursor",g.cursor)}if(g.opacity){if(this.helper.css("opacity")){this._storedOpacity=this.helper.css("opacity")}this.helper.css("opacity",g.opacity)}if(g.zIndex){if(this.helper.css("zIndex")){this._storedZIndex=this.helper.css("zIndex")}this.helper.css("zIndex",g.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){this.overflowOffset=this.scrollParent.offset()}this._trigger("start",e,this._uiHash());if(!this._preserveHelperProportions){this._cacheHelperProportions()}if(!b){for(var d=this.containers.length-1;d>=0;d--){this.containers[d]._trigger("activate",e,c._uiHash(this))}}if(a.ui.ddmanager){a.ui.ddmanager.current=this}if(a.ui.ddmanager&&!g.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,e)}this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(e);return true},_mouseDrag:function(f){this.position=this._generatePosition(f);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs){this.lastPositionAbs=this.positionAbs}if(this.options.scroll){var g=this.options,b=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if((this.overflowOffset.top+this.scrollParent[0].offsetHeight)-f.pageY<g.scrollSensitivity){this.scrollParent[0].scrollTop=b=this.scrollParent[0].scrollTop+g.scrollSpeed}else{if(f.pageY-this.overflowOffset.top<g.scrollSensitivity){this.scrollParent[0].scrollTop=b=this.scrollParent[0].scrollTop-g.scrollSpeed}}if((this.overflowOffset.left+this.scrollParent[0].offsetWidth)-f.pageX<g.scrollSensitivity){this.scrollParent[0].scrollLeft=b=this.scrollParent[0].scrollLeft+g.scrollSpeed}else{if(f.pageX-this.overflowOffset.left<g.scrollSensitivity){this.scrollParent[0].scrollLeft=b=this.scrollParent[0].scrollLeft-g.scrollSpeed}}}else{if(f.pageY-a(document).scrollTop()<g.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()-g.scrollSpeed)}else{if(a(window).height()-(f.pageY-a(document).scrollTop())<g.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()+g.scrollSpeed)}}if(f.pageX-a(document).scrollLeft()<g.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()-g.scrollSpeed)}else{if(a(window).width()-(f.pageX-a(document).scrollLeft())<g.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()+g.scrollSpeed)}}}if(b!==false&&a.ui.ddmanager&&!g.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,f)}}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y"){this.helper[0].style.left=this.position.left+"px"}if(!this.options.axis||this.options.axis!="x"){this.helper[0].style.top=this.position.top+"px"}for(var d=this.items.length-1;d>=0;d--){var e=this.items[d],c=e.item[0],h=this._intersectsWithPointer(e);if(!h){continue}if(c!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=c&&!a.ui.contains(this.placeholder[0],c)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],c):true)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(e)){this._rearrange(f,e)}else{break}this._trigger("change",f,this._uiHash());break}}this._contactContainers(f);if(a.ui.ddmanager){a.ui.ddmanager.drag(this,f)}this._trigger("sort",f,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(c,d){if(!c){return}if(a.ui.ddmanager&&!this.options.dropBehaviour){a.ui.ddmanager.drop(this,c)}if(this.options.revert){var b=this;var e=b.placeholder.offset();b.reverting=true;a(this.helper).animate({left:e.left-this.offset.parent.left-b.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-b.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){b._clear(c)})}else{this._clear(c,d)}return false},cancel:function(){var b=this;if(this.dragging){this._mouseUp();if(this.options.helper=="original"){this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else{this.currentItem.show()}for(var c=this.containers.length-1;c>=0;c--){this.containers[c]._trigger("deactivate",null,b._uiHash(this));if(this.containers[c].containerCache.over){this.containers[c]._trigger("out",null,b._uiHash(this));this.containers[c].containerCache.over=0}}}if(this.placeholder[0].parentNode){this.placeholder[0].parentNode.removeChild(this.placeholder[0])}if(this.options.helper!="original"&&this.helper&&this.helper[0].parentNode){this.helper.remove()}a.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});if(this.domPosition.prev){a(this.domPosition.prev).after(this.currentItem)}else{a(this.domPosition.parent).prepend(this.currentItem)}return true},serialize:function(d){var b=this._getItemsAsjQuery(d&&d.connected);var c=[];d=d||{};a(b).each(function(){var e=(a(d.item||this).attr(d.attribute||"id")||"").match(d.expression||(/(.+)[-=_](.+)/));if(e){c.push((d.key||e[1]+"[]")+"="+(d.key&&d.expression?e[1]:e[2]))}});return c.join("&")},toArray:function(d){var b=this._getItemsAsjQuery(d&&d.connected);var c=[];d=d||{};b.each(function(){c.push(a(d.item||this).attr(d.attribute||"id")||"")});return c},_intersectsWith:function(m){var e=this.positionAbs.left,d=e+this.helperProportions.width,k=this.positionAbs.top,j=k+this.helperProportions.height;var f=m.left,c=f+m.width,n=m.top,i=n+m.height;var o=this.offset.click.top,h=this.offset.click.left;var g=(k+o)>n&&(k+o)<i&&(e+h)>f&&(e+h)<c;if(this.options.tolerance=="pointer"||this.options.forcePointerForContainers||(this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>m[this.floating?"width":"height"])){return g}else{return(f<e+(this.helperProportions.width/2)&&d-(this.helperProportions.width/2)<c&&n<k+(this.helperProportions.height/2)&&j-(this.helperProportions.height/2)<i)}},_intersectsWithPointer:function(d){var e=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,d.top,d.height),c=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,d.left,d.width),g=e&&c,b=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();if(!g){return false}return this.floating?(((f&&f=="right")||b=="down")?2:1):(b&&(b=="down"?2:1))},_intersectsWithSides:function(e){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,e.top+(e.height/2),e.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,e.left+(e.width/2),e.width),b=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();if(this.floating&&f){return((f=="right"&&d)||(f=="left"&&!d))}else{return b&&((b=="down"&&c)||(b=="up"&&!c))}},_getDragVerticalDirection:function(){var b=this.positionAbs.top-this.lastPositionAbs.top;return b!=0&&(b>0?"down":"up")},_getDragHorizontalDirection:function(){var b=this.positionAbs.left-this.lastPositionAbs.left;return b!=0&&(b>0?"right":"left")},refresh:function(b){this._refreshItems(b);this.refreshPositions()},_connectWith:function(){var b=this.options;return b.connectWith.constructor==String?[b.connectWith]:b.connectWith},_getItemsAsjQuery:function(b){var l=this;var g=[];var e=[];var h=this._connectWith();if(h&&b){for(var d=h.length-1;d>=0;d--){var k=a(h[d]);for(var c=k.length-1;c>=0;c--){var f=a.data(k[c],"sortable");if(f&&f!=this&&!f.options.disabled){e.push([a.isFunction(f.options.items)?f.options.items.call(f.element):a(f.options.items,f.element).not(".ui-sortable-helper"),f])}}}}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper"),this]);for(var d=e.length-1;d>=0;d--){e[d][0].each(function(){g.push(this)})}return a(g)},_removeCurrentsFromItems:function(){var d=this.currentItem.find(":data(sortable-item)");for(var c=0;c<this.items.length;c++){for(var b=0;b<d.length;b++){if(d[b]==this.items[c].item[0]){this.items.splice(c,1)}}}},_refreshItems:function(b){this.items=[];this.containers=[this];var h=this.items;var p=this;var f=[[a.isFunction(this.options.items)?this.options.items.call(this.element[0],b,{item:this.currentItem}):a(this.options.items,this.element),this]];var l=this._connectWith();if(l){for(var e=l.length-1;e>=0;e--){var m=a(l[e]);for(var d=m.length-1;d>=0;d--){var g=a.data(m[d],"sortable");if(g&&g!=this&&!g.options.disabled){f.push([a.isFunction(g.options.items)?g.options.items.call(g.element[0],b,{item:this.currentItem}):a(g.options.items,g.element),g]);this.containers.push(g)}}}}for(var e=f.length-1;e>=0;e--){var k=f[e][1];var c=f[e][0];for(var d=0,n=c.length;d<n;d++){var o=a(c[d]);o.data("sortable-item",k);h.push({item:o,instance:k,width:0,height:0,left:0,top:0})}}},refreshPositions:function(b){if(this.offsetParent&&this.helper){this.offset.parent=this._getParentOffset()}for(var d=this.items.length-1;d>=0;d--){var e=this.items[d];if(e.instance!=this.currentContainer&&this.currentContainer&&e.item[0]!=this.currentItem[0]){continue}var c=this.options.toleranceElement?a(this.options.toleranceElement,e.item):e.item;if(!b){e.width=c.outerWidth();e.height=c.outerHeight()}var f=c.offset();e.left=f.left;e.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers){this.options.custom.refreshContainers.call(this)}else{for(var d=this.containers.length-1;d>=0;d--){var f=this.containers[d].element.offset();this.containers[d].containerCache.left=f.left;this.containers[d].containerCache.top=f.top;this.containers[d].containerCache.width=this.containers[d].element.outerWidth();this.containers[d].containerCache.height=this.containers[d].element.outerHeight()}}},_createPlaceholder:function(d){var b=d||this,e=b.options;if(!e.placeholder||e.placeholder.constructor==String){var c=e.placeholder;e.placeholder={element:function(){var f=a(document.createElement(b.currentItem[0].nodeName)).addClass(c||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!c){f.style.visibility="hidden"}return f},update:function(f,g){if(c&&!e.forcePlaceholderSize){return}if(!g.height()){g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10))}if(!g.width()){g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=a(e.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);e.placeholder.update(b,b.placeholder)},_contactContainers:function(d){for(var c=this.containers.length-1;c>=0;c--){if(this._intersectsWith(this.containers[c].containerCache)){if(!this.containers[c].containerCache.over){if(this.currentContainer!=this.containers[c]){var h=10000;var g=null;var e=this.positionAbs[this.containers[c].floating?"left":"top"];for(var b=this.items.length-1;b>=0;b--){if(!a.ui.contains(this.containers[c].element[0],this.items[b].item[0])){continue}var f=this.items[b][this.containers[c].floating?"left":"top"];if(Math.abs(f-e)<h){h=Math.abs(f-e);g=this.items[b]}}if(!g&&!this.options.dropOnEmpty){continue}this.currentContainer=this.containers[c];g?this._rearrange(d,g,null,true):this._rearrange(d,null,this.containers[c].element,true);this._trigger("change",d,this._uiHash());this.containers[c]._trigger("change",d,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder)}this.containers[c]._trigger("over",d,this._uiHash(this));this.containers[c].containerCache.over=1}}else{if(this.containers[c].containerCache.over){this.containers[c]._trigger("out",d,this._uiHash(this));this.containers[c].containerCache.over=0}}}},_createHelper:function(c){var d=this.options;var b=a.isFunction(d.helper)?a(d.helper.apply(this.element[0],[c,this.currentItem])):(d.helper=="clone"?this.currentItem.clone():this.currentItem);if(!b.parents("body").length){a(d.appendTo!="parent"?d.appendTo:this.currentItem[0].parentNode)[0].appendChild(b[0])}if(b[0]==this.currentItem[0]){this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}}if(b[0].style.width==""||d.forceHelperSize){b.width(this.currentItem.width())}if(b[0].style.height==""||d.forceHelperSize){b.height(this.currentItem.height())}return b},_adjustOffsetFromHelper:function(b){if(b.left!=undefined){this.offset.click.left=b.left+this.margins.left}if(b.right!=undefined){this.offset.click.left=this.helperProportions.width-b.right+this.margins.left}if(b.top!=undefined){this.offset.click.top=b.top+this.margins.top}if(b.bottom!=undefined){this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top}},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])){b.left+=this.scrollParent.scrollLeft();b.top+=this.scrollParent.scrollTop()}if((this.offsetParent[0]==document.body)||(this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)){b={top:0,left:0}}return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var b=this.currentItem.position();return{top:b.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:b.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else{return{top:0,left:0}}},_cacheMargins:function(){this.margins={left:(parseInt(this.currentItem.css("marginLeft"),10)||0),top:(parseInt(this.currentItem.css("marginTop"),10)||0)}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e=this.options;if(e.containment=="parent"){e.containment=this.helper[0].parentNode}if(e.containment=="document"||e.containment=="window"){this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(e.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(e.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]}if(!(/^(document|window|parent)$/).test(e.containment)){var c=a(e.containment)[0];var d=a(e.containment).offset();var b=(a(c).css("overflow")!="hidden");this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(b?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(b?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(f,h){if(!h){h=this.position}var c=f=="absolute"?1:-1;var e=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=(/(html|body)/i).test(b[0].tagName);return{top:(h.top+this.offset.relative.top*c+this.offset.parent.top*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(g?0:b.scrollTop()))*c)),left:(h.left+this.offset.relative.left*c+this.offset.parent.left*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:b.scrollLeft())*c))}},_generatePosition:function(e){var h=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,i=(/(html|body)/i).test(b[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0])){this.offset.relative=this._getRelativeOffset()}var d=e.pageX;var c=e.pageY;if(this.originalPosition){if(this.containment){if(e.pageX-this.offset.click.left<this.containment[0]){d=this.containment[0]+this.offset.click.left}if(e.pageY-this.offset.click.top<this.containment[1]){c=this.containment[1]+this.offset.click.top}if(e.pageX-this.offset.click.left>this.containment[2]){d=this.containment[2]+this.offset.click.left}if(e.pageY-this.offset.click.top>this.containment[3]){c=this.containment[3]+this.offset.click.top}}if(h.grid){var g=this.originalPageY+Math.round((c-this.originalPageY)/h.grid[1])*h.grid[1];c=this.containment?(!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:(!(g-this.offset.click.top<this.containment[1])?g-h.grid[1]:g+h.grid[1])):g;var f=this.originalPageX+Math.round((d-this.originalPageX)/h.grid[0])*h.grid[0];d=this.containment?(!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:(!(f-this.offset.click.left<this.containment[0])?f-h.grid[0]:f+h.grid[0])):f}}return{top:(c-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(i?0:b.scrollTop())))),left:(d-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:b.scrollLeft())))}},_rearrange:function(g,f,c,e){c?c[0].appendChild(this.placeholder[0]):f.item[0].parentNode.insertBefore(this.placeholder[0],(this.direction=="down"?f.item[0]:f.item[0].nextSibling));this.counter=this.counter?++this.counter:1;var d=this,b=this.counter;window.setTimeout(function(){if(b==d.counter){d.refreshPositions(!e)}},0)},_clear:function(d,e){this.reverting=false;var f=[],b=this;if(!this._noFinalSort&&this.currentItem[0].parentNode){this.placeholder.before(this.currentItem)}this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var c in this._storedCSS){if(this._storedCSS[c]=="auto"||this._storedCSS[c]=="static"){this._storedCSS[c]=""}}this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else{this.currentItem.show()}if(this.fromOutside&&!e){f.push(function(g){this._trigger("receive",g,this._uiHash(this.fromOutside))})}if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!e){f.push(function(g){this._trigger("update",g,this._uiHash())})}if(!a.ui.contains(this.element[0],this.currentItem[0])){if(!e){f.push(function(g){this._trigger("remove",g,this._uiHash())})}for(var c=this.containers.length-1;c>=0;c--){if(a.ui.contains(this.containers[c].element[0],this.currentItem[0])&&!e){f.push((function(g){return function(h){g._trigger("receive",h,this._uiHash(this))}}).call(this,this.containers[c]));f.push((function(g){return function(h){g._trigger("update",h,this._uiHash(this))}}).call(this,this.containers[c]))}}}for(var c=this.containers.length-1;c>=0;c--){if(!e){f.push((function(g){return function(h){g._trigger("deactivate",h,this._uiHash(this))}}).call(this,this.containers[c]))}if(this.containers[c].containerCache.over){f.push((function(g){return function(h){g._trigger("out",h,this._uiHash(this))}}).call(this,this.containers[c]));this.containers[c].containerCache.over=0}}if(this._storedCursor){a("body").css("cursor",this._storedCursor)}if(this._storedOpacity){this.helper.css("opacity",this._storedOpacity)}if(this._storedZIndex){this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex)}this.dragging=false;if(this.cancelHelperRemoval){if(!e){this._trigger("beforeStop",d,this._uiHash());for(var c=0;c<f.length;c++){f[c].call(this,d)}this._trigger("stop",d,this._uiHash())}return false}if(!e){this._trigger("beforeStop",d,this._uiHash())}this.placeholder[0].parentNode.removeChild(this.placeholder[0]);if(this.helper[0]!=this.currentItem[0]){this.helper.remove()}this.helper=null;if(!e){for(var c=0;c<f.length;c++){f[c].call(this,d)}this._trigger("stop",d,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){if(a.widget.prototype._trigger.apply(this,arguments)===false){this.cancel()}},_uiHash:function(c){var b=c||this;return{helper:b.helper,placeholder:b.placeholder||a([]),position:b.position,absolutePosition:b.positionAbs,offset:b.positionAbs,item:b.currentItem,sender:c?c.element:null}}}));a.extend(a.ui.sortable,{getter:"serialize toArray",version:"1.7.2",eventPrefix:"sort",defaults:{appendTo:"parent",axis:false,cancel:":input,option",connectWith:false,containment:false,cursor:"auto",cursorAt:false,delay:0,distance:1,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1000}})})(jQuery);;/*
+ * jQuery UI Accordion 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Accordion
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(a){a.widget("ui.accordion",{_init:function(){var d=this.options,b=this;this.running=0;if(d.collapsible==a.ui.accordion.defaults.collapsible&&d.alwaysOpen!=a.ui.accordion.defaults.alwaysOpen){d.collapsible=!d.alwaysOpen}if(d.navigation){var c=this.element.find("a").filter(d.navigationFilter);if(c.length){if(c.filter(d.header).length){this.active=c}else{this.active=c.parent().parent().prev();c.addClass("ui-accordion-content-active")}}}this.element.addClass("ui-accordion ui-widget ui-helper-reset");if(this.element[0].nodeName=="UL"){this.element.children("li").addClass("ui-accordion-li-fix")}this.headers=this.element.find(d.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){a(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){a(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){a(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){a(this).removeClass("ui-state-focus")});this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");this.active=this._findActive(this.active||d.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");this.active.next().addClass("ui-accordion-content-active");a("<span/>").addClass("ui-icon "+d.icons.header).prependTo(this.headers);this.active.find(".ui-icon").toggleClass(d.icons.header).toggleClass(d.icons.headerSelected);if(a.browser.msie){this.element.find("a").css("zoom","1")}this.resize();this.element.attr("role","tablist");this.headers.attr("role","tab").bind("keydown",function(e){return b._keydown(e)}).next().attr("role","tabpanel");this.headers.not(this.active||"").attr("aria-expanded","false").attr("tabIndex","-1").next().hide();if(!this.active.length){this.headers.eq(0).attr("tabIndex","0")}else{this.active.attr("aria-expanded","true").attr("tabIndex","0")}if(!a.browser.safari){this.headers.find("a").attr("tabIndex","-1")}if(d.event){this.headers.bind((d.event)+".accordion",function(e){return b._clickHandler.call(b,e,this)})}},destroy:function(){var c=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role").unbind(".accordion").removeData("accordion");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");this.headers.find("a").removeAttr("tabindex");this.headers.children(".ui-icon").remove();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");if(c.autoHeight||c.fillHeight){b.css("height","")}},_setData:function(b,c){if(b=="alwaysOpen"){b="collapsible";c=!c}a.widget.prototype._setData.apply(this,arguments)},_keydown:function(e){var g=this.options,f=a.ui.keyCode;if(g.disabled||e.altKey||e.ctrlKey){return}var d=this.headers.length;var b=this.headers.index(e.target);var c=false;switch(e.keyCode){case f.RIGHT:case f.DOWN:c=this.headers[(b+1)%d];break;case f.LEFT:case f.UP:c=this.headers[(b-1+d)%d];break;case f.SPACE:case f.ENTER:return this._clickHandler({target:e.target},e.target)}if(c){a(e.target).attr("tabIndex","-1");a(c).attr("tabIndex","0");c.focus();return false}return true},resize:function(){var e=this.options,d;if(e.fillSpace){if(a.browser.msie){var b=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}d=this.element.parent().height();if(a.browser.msie){this.element.parent().css("overflow",b)}this.headers.each(function(){d-=a(this).outerHeight()});var c=0;this.headers.next().each(function(){c=Math.max(c,a(this).innerHeight()-a(this).height())}).height(Math.max(0,d-c)).css("overflow","auto")}else{if(e.autoHeight){d=0;this.headers.next().each(function(){d=Math.max(d,a(this).outerHeight())}).height(d)}}},activate:function(b){var c=this._findActive(b)[0];this._clickHandler({target:c},c)},_findActive:function(b){return b?typeof b=="number"?this.headers.filter(":eq("+b+")"):this.headers.not(this.headers.not(b)):b===false?a([]):this.headers.filter(":eq(0)")},_clickHandler:function(b,f){var d=this.options;if(d.disabled){return false}if(!b.target&&d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");var h=this.active.next(),e={options:d,newHeader:a([]),oldHeader:d.active,newContent:a([]),oldContent:h},c=(this.active=a([]));this._toggle(c,h,e);return false}var g=a(b.currentTarget||f);var i=g[0]==this.active[0];if(this.running||(!d.collapsible&&i)){return false}this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");if(!i){g.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").find(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);g.next().addClass("ui-accordion-content-active")}var c=g.next(),h=this.active.next(),e={options:d,newHeader:i&&d.collapsible?a([]):g,oldHeader:this.active,newContent:i&&d.collapsible?a([]):c.find("> *"),oldContent:h.find("> *")},j=this.headers.index(this.active[0])>this.headers.index(g[0]);this.active=i?a([]):g;this._toggle(c,h,e,i,j);return false},_toggle:function(b,i,g,j,k){var d=this.options,m=this;this.toShow=b;this.toHide=i;this.data=g;var c=function(){if(!m){return}return m._completed.apply(m,arguments)};this._trigger("changestart",null,this.data);this.running=i.size()===0?b.size():i.size();if(d.animated){var f={};if(d.collapsible&&j){f={toShow:a([]),toHide:i,complete:c,down:k,autoHeight:d.autoHeight||d.fillSpace}}else{f={toShow:b,toHide:i,complete:c,down:k,autoHeight:d.autoHeight||d.fillSpace}}if(!d.proxied){d.proxied=d.animated}if(!d.proxiedDuration){d.proxiedDuration=d.duration}d.animated=a.isFunction(d.proxied)?d.proxied(f):d.proxied;d.duration=a.isFunction(d.proxiedDuration)?d.proxiedDuration(f):d.proxiedDuration;var l=a.ui.accordion.animations,e=d.duration,h=d.animated;if(!l[h]){l[h]=function(n){this.slide(n,{easing:h,duration:e||700})}}l[h](f)}else{if(d.collapsible&&j){b.toggle()}else{i.hide();b.show()}c(true)}i.prev().attr("aria-expanded","false").attr("tabIndex","-1").blur();b.prev().attr("aria-expanded","true").attr("tabIndex","0").focus()},_completed:function(b){var c=this.options;this.running=b?0:--this.running;if(this.running){return}if(c.clearStyle){this.toShow.add(this.toHide).css({height:"",overflow:""})}this._trigger("change",null,this.data)}});a.extend(a.ui.accordion,{version:"1.7.2",defaults:{active:null,alwaysOpen:true,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()==location.href.toLowerCase()}},animations:{slide:function(j,h){j=a.extend({easing:"swing",duration:300},j,h);if(!j.toHide.size()){j.toShow.animate({height:"show"},j);return}if(!j.toShow.size()){j.toHide.animate({height:"hide"},j);return}var c=j.toShow.css("overflow"),g,d={},f={},e=["height","paddingTop","paddingBottom"],b;var i=j.toShow;b=i[0].style.width;i.width(parseInt(i.parent().width(),10)-parseInt(i.css("paddingLeft"),10)-parseInt(i.css("paddingRight"),10)-(parseInt(i.css("borderLeftWidth"),10)||0)-(parseInt(i.css("borderRightWidth"),10)||0));a.each(e,function(k,m){f[m]="hide";var l=(""+a.css(j.toShow[0],m)).match(/^([\d+-.]+)(.*)$/);d[m]={value:l[1],unit:l[2]||"px"}});j.toShow.css({height:0,overflow:"hidden"}).show();j.toHide.filter(":hidden").each(j.complete).end().filter(":visible").animate(f,{step:function(k,l){if(l.prop=="height"){g=(l.now-l.start)/(l.end-l.start)}j.toShow[0].style[l.prop]=(g*d[l.prop].value)+d[l.prop].unit},duration:j.duration,easing:j.easing,complete:function(){if(!j.autoHeight){j.toShow.css("height","")}j.toShow.css("width",b);j.toShow.css({overflow:c});j.complete()}})},bounceslide:function(b){this.slide(b,{easing:b.down?"easeOutBounce":"swing",duration:b.down?1000:200})},easeslide:function(b){this.slide(b,{easing:"easeinout",duration:700})}}})})(jQuery);;/*
+ * jQuery UI Dialog 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Dialog
+ *
+ * Depends:
+ *	ui.core.js
+ *	ui.draggable.js
+ *	ui.resizable.js
+ */
+(function(c){var b={dragStart:"start.draggable",drag:"drag.draggable",dragStop:"stop.draggable",maxHeight:"maxHeight.resizable",minHeight:"minHeight.resizable",maxWidth:"maxWidth.resizable",minWidth:"minWidth.resizable",resizeStart:"start.resizable",resize:"drag.resizable",resizeStop:"stop.resizable"},a="ui-dialog ui-widget ui-widget-content ui-corner-all ";c.widget("ui.dialog",{_init:function(){this.originalTitle=this.element.attr("title");var l=this,m=this.options,j=m.title||this.originalTitle||"&nbsp;",e=c.ui.dialog.getTitleId(this.element),k=(this.uiDialog=c("<div/>")).appendTo(document.body).hide().addClass(a+m.dialogClass).css({position:"absolute",overflow:"hidden",zIndex:m.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(n){(m.closeOnEscape&&n.keyCode&&n.keyCode==c.ui.keyCode.ESCAPE&&l.close(n))}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(n){l.moveToTop(false,n)}),g=this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(k),f=(this.uiDialogTitlebar=c("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(k),i=c('<a href="#"/>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){i.addClass("ui-state-hover")},function(){i.removeClass("ui-state-hover")}).focus(function(){i.addClass("ui-state-focus")}).blur(function(){i.removeClass("ui-state-focus")}).mousedown(function(n){n.stopPropagation()}).click(function(n){l.close(n);return false}).appendTo(f),h=(this.uiDialogTitlebarCloseText=c("<span/>")).addClass("ui-icon ui-icon-closethick").text(m.closeText).appendTo(i),d=c("<span/>").addClass("ui-dialog-title").attr("id",e).html(j).prependTo(f);f.find("*").add(f).disableSelection();(m.draggable&&c.fn.draggable&&this._makeDraggable());(m.resizable&&c.fn.resizable&&this._makeResizable());this._createButtons(m.buttons);this._isOpen=false;(m.bgiframe&&c.fn.bgiframe&&k.bgiframe());(m.autoOpen&&this.open())},destroy:function(){(this.overlay&&this.overlay.destroy());this.uiDialog.hide();this.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");this.uiDialog.remove();(this.originalTitle&&this.element.attr("title",this.originalTitle))},close:function(f){var d=this;if(false===d._trigger("beforeclose",f)){return}(d.overlay&&d.overlay.destroy());d.uiDialog.unbind("keypress.ui-dialog");(d.options.hide?d.uiDialog.hide(d.options.hide,function(){d._trigger("close",f)}):d.uiDialog.hide()&&d._trigger("close",f));c.ui.dialog.overlay.resize();d._isOpen=false;if(d.options.modal){var e=0;c(".ui-dialog").each(function(){if(this!=d.uiDialog[0]){e=Math.max(e,c(this).css("z-index"))}});c.ui.dialog.maxZ=e}},isOpen:function(){return this._isOpen},moveToTop:function(f,e){if((this.options.modal&&!f)||(!this.options.stack&&!this.options.modal)){return this._trigger("focus",e)}if(this.options.zIndex>c.ui.dialog.maxZ){c.ui.dialog.maxZ=this.options.zIndex}(this.overlay&&this.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=++c.ui.dialog.maxZ));var d={scrollTop:this.element.attr("scrollTop"),scrollLeft:this.element.attr("scrollLeft")};this.uiDialog.css("z-index",++c.ui.dialog.maxZ);this.element.attr(d);this._trigger("focus",e)},open:function(){if(this._isOpen){return}var e=this.options,d=this.uiDialog;this.overlay=e.modal?new c.ui.dialog.overlay(this):null;(d.next().length&&d.appendTo("body"));this._size();this._position(e.position);d.show(e.show);this.moveToTop(true);(e.modal&&d.bind("keypress.ui-dialog",function(h){if(h.keyCode!=c.ui.keyCode.TAB){return}var g=c(":tabbable",this),i=g.filter(":first")[0],f=g.filter(":last")[0];if(h.target==f&&!h.shiftKey){setTimeout(function(){i.focus()},1)}else{if(h.target==i&&h.shiftKey){setTimeout(function(){f.focus()},1)}}}));c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();this._trigger("open");this._isOpen=true},_createButtons:function(g){var f=this,d=false,e=c("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");this.uiDialog.find(".ui-dialog-buttonpane").remove();(typeof g=="object"&&g!==null&&c.each(g,function(){return !(d=true)}));if(d){c.each(g,function(h,i){c('<button type="button"></button>').addClass("ui-state-default ui-corner-all").text(h).click(function(){i.apply(f.element[0],arguments)}).hover(function(){c(this).addClass("ui-state-hover")},function(){c(this).removeClass("ui-state-hover")}).focus(function(){c(this).addClass("ui-state-focus")}).blur(function(){c(this).removeClass("ui-state-focus")}).appendTo(e)});e.appendTo(this.uiDialog)}},_makeDraggable:function(){var d=this,f=this.options,e;this.uiDialog.draggable({cancel:".ui-dialog-content",handle:".ui-dialog-titlebar",containment:"document",start:function(){e=f.height;c(this).height(c(this).height()).addClass("ui-dialog-dragging");(f.dragStart&&f.dragStart.apply(d.element[0],arguments))},drag:function(){(f.drag&&f.drag.apply(d.element[0],arguments))},stop:function(){c(this).removeClass("ui-dialog-dragging").height(e);(f.dragStop&&f.dragStop.apply(d.element[0],arguments));c.ui.dialog.overlay.resize()}})},_makeResizable:function(g){g=(g===undefined?this.options.resizable:g);var d=this,f=this.options,e=typeof g=="string"?g:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",alsoResize:this.element,maxWidth:f.maxWidth,maxHeight:f.maxHeight,minWidth:f.minWidth,minHeight:f.minHeight,start:function(){c(this).addClass("ui-dialog-resizing");(f.resizeStart&&f.resizeStart.apply(d.element[0],arguments))},resize:function(){(f.resize&&f.resize.apply(d.element[0],arguments))},handles:e,stop:function(){c(this).removeClass("ui-dialog-resizing");f.height=c(this).height();f.width=c(this).width();(f.resizeStop&&f.resizeStop.apply(d.element[0],arguments));c.ui.dialog.overlay.resize()}}).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_position:function(i){var e=c(window),f=c(document),g=f.scrollTop(),d=f.scrollLeft(),h=g;if(c.inArray(i,["center","top","right","bottom","left"])>=0){i=[i=="right"||i=="left"?i:"center",i=="top"||i=="bottom"?i:"middle"]}if(i.constructor!=Array){i=["center","middle"]}if(i[0].constructor==Number){d+=i[0]}else{switch(i[0]){case"left":d+=0;break;case"right":d+=e.width()-this.uiDialog.outerWidth();break;default:case"center":d+=(e.width()-this.uiDialog.outerWidth())/2}}if(i[1].constructor==Number){g+=i[1]}else{switch(i[1]){case"top":g+=0;break;case"bottom":g+=e.height()-this.uiDialog.outerHeight();break;default:case"middle":g+=(e.height()-this.uiDialog.outerHeight())/2}}g=Math.max(g,h);this.uiDialog.css({top:g,left:d})},_setData:function(e,f){(b[e]&&this.uiDialog.data(b[e],f));switch(e){case"buttons":this._createButtons(f);break;case"closeText":this.uiDialogTitlebarCloseText.text(f);break;case"dialogClass":this.uiDialog.removeClass(this.options.dialogClass).addClass(a+f);break;case"draggable":(f?this._makeDraggable():this.uiDialog.draggable("destroy"));break;case"height":this.uiDialog.height(f);break;case"position":this._position(f);break;case"resizable":var d=this.uiDialog,g=this.uiDialog.is(":data(resizable)");(g&&!f&&d.resizable("destroy"));(g&&typeof f=="string"&&d.resizable("option","handles",f));(g||this._makeResizable(f));break;case"title":c(".ui-dialog-title",this.uiDialogTitlebar).html(f||"&nbsp;");break;case"width":this.uiDialog.width(f);break}c.widget.prototype._setData.apply(this,arguments)},_size:function(){var e=this.options;this.element.css({height:0,minHeight:0,width:"auto"});var d=this.uiDialog.css({height:"auto",width:e.width}).height();this.element.css({minHeight:Math.max(e.minHeight-d,0),height:e.height=="auto"?"auto":Math.max(e.height-d,0)})}});c.extend(c.ui.dialog,{version:"1.7.2",defaults:{autoOpen:true,bgiframe:false,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:"center",resizable:true,show:null,stack:true,title:"",width:300,zIndex:1000},getter:"isOpen",uuid:0,maxZ:0,getTitleId:function(d){return"ui-dialog-title-"+(d.attr("id")||++this.uuid)},overlay:function(d){this.$el=c.ui.dialog.overlay.create(d)}});c.extend(c.ui.dialog.overlay,{instances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(d){return d+".dialog-overlay"}).join(" "),create:function(e){if(this.instances.length===0){setTimeout(function(){if(c.ui.dialog.overlay.instances.length){c(document).bind(c.ui.dialog.overlay.events,function(f){var g=c(f.target).parents(".ui-dialog").css("zIndex")||0;return(g>c.ui.dialog.overlay.maxZ)})}},1);c(document).bind("keydown.dialog-overlay",function(f){(e.options.closeOnEscape&&f.keyCode&&f.keyCode==c.ui.keyCode.ESCAPE&&e.close(f))});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var d=c("<div></div>").appendTo(document.body).addClass("ui-widget-overlay").css({width:this.width(),height:this.height()});(e.options.bgiframe&&c.fn.bgiframe&&d.bgiframe());this.instances.push(d);return d},destroy:function(d){this.instances.splice(c.inArray(this.instances,d),1);if(this.instances.length===0){c([document,window]).unbind(".dialog-overlay")}d.remove();var e=0;c.each(this.instances,function(){e=Math.max(e,this.css("z-index"))});this.maxZ=e},height:function(){if(c.browser.msie&&c.browser.version<7){var e=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);var d=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);if(e<d){return c(window).height()+"px"}else{return e+"px"}}else{return c(document).height()+"px"}},width:function(){if(c.browser.msie&&c.browser.version<7){var d=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);var e=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);if(d<e){return c(window).width()+"px"}else{return d+"px"}}else{return c(document).width()+"px"}},resize:function(){var d=c([]);c.each(c.ui.dialog.overlay.instances,function(){d=d.add(this)});d.css({width:0,height:0}).css({width:c.ui.dialog.overlay.width(),height:c.ui.dialog.overlay.height()})}});c.extend(c.ui.dialog.overlay.prototype,{destroy:function(){c.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);;/*
+ * jQuery UI Slider 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Slider
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(a){a.widget("ui.slider",a.extend({},a.ui.mouse,{_init:function(){var b=this,c=this.options;this._keySliding=false;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all");this.range=a([]);if(c.range){if(c.range===true){this.range=a("<div></div>");if(!c.values){c.values=[this._valueMin(),this._valueMin()]}if(c.values.length&&c.values.length!=2){c.values=[c.values[0],c.values[0]]}}else{this.range=a("<div></div>")}this.range.appendTo(this.element).addClass("ui-slider-range");if(c.range=="min"||c.range=="max"){this.range.addClass("ui-slider-range-"+c.range)}this.range.addClass("ui-widget-header")}if(a(".ui-slider-handle",this.element).length==0){a('<a href="#"></a>').appendTo(this.element).addClass("ui-slider-handle")}if(c.values&&c.values.length){while(a(".ui-slider-handle",this.element).length<c.values.length){a('<a href="#"></a>').appendTo(this.element).addClass("ui-slider-handle")}}this.handles=a(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(d){d.preventDefault()}).hover(function(){if(!c.disabled){a(this).addClass("ui-state-hover")}},function(){a(this).removeClass("ui-state-hover")}).focus(function(){if(!c.disabled){a(".ui-slider .ui-state-focus").removeClass("ui-state-focus");a(this).addClass("ui-state-focus")}else{a(this).blur()}}).blur(function(){a(this).removeClass("ui-state-focus")});this.handles.each(function(d){a(this).data("index.ui-slider-handle",d)});this.handles.keydown(function(i){var f=true;var e=a(this).data("index.ui-slider-handle");if(b.options.disabled){return}switch(i.keyCode){case a.ui.keyCode.HOME:case a.ui.keyCode.END:case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:f=false;if(!b._keySliding){b._keySliding=true;a(this).addClass("ui-state-active");b._start(i,e)}break}var g,d,h=b._step();if(b.options.values&&b.options.values.length){g=d=b.values(e)}else{g=d=b.value()}switch(i.keyCode){case a.ui.keyCode.HOME:d=b._valueMin();break;case a.ui.keyCode.END:d=b._valueMax();break;case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:if(g==b._valueMax()){return}d=g+h;break;case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:if(g==b._valueMin()){return}d=g-h;break}b._slide(i,e,d);return f}).keyup(function(e){var d=a(this).data("index.ui-slider-handle");if(b._keySliding){b._stop(e,d);b._change(e,d);b._keySliding=false;a(this).removeClass("ui-state-active")}});this._refreshValue()},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");this._mouseDestroy()},_mouseCapture:function(d){var e=this.options;if(e.disabled){return false}this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();var h={x:d.pageX,y:d.pageY};var j=this._normValueFromMouse(h);var c=this._valueMax()-this._valueMin()+1,f;var k=this,i;this.handles.each(function(l){var m=Math.abs(j-k.values(l));if(c>m){c=m;f=a(this);i=l}});if(e.range==true&&this.values(1)==e.min){f=a(this.handles[++i])}this._start(d,i);k._handleIndex=i;f.addClass("ui-state-active").focus();var g=f.offset();var b=!a(d.target).parents().andSelf().is(".ui-slider-handle");this._clickOffset=b?{left:0,top:0}:{left:d.pageX-g.left-(f.width()/2),top:d.pageY-g.top-(f.height()/2)-(parseInt(f.css("borderTopWidth"),10)||0)-(parseInt(f.css("borderBottomWidth"),10)||0)+(parseInt(f.css("marginTop"),10)||0)};j=this._normValueFromMouse(h);this._slide(d,i,j);return true},_mouseStart:function(b){return true},_mouseDrag:function(d){var b={x:d.pageX,y:d.pageY};var c=this._normValueFromMouse(b);this._slide(d,this._handleIndex,c);return false},_mouseStop:function(b){this.handles.removeClass("ui-state-active");this._stop(b,this._handleIndex);this._change(b,this._handleIndex);this._handleIndex=null;this._clickOffset=null;return false},_detectOrientation:function(){this.orientation=this.options.orientation=="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(d){var c,h;if("horizontal"==this.orientation){c=this.elementSize.width;h=d.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{c=this.elementSize.height;h=d.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}var f=(h/c);if(f>1){f=1}if(f<0){f=0}if("vertical"==this.orientation){f=1-f}var e=this._valueMax()-this._valueMin(),i=f*e,b=i%this.options.step,g=this._valueMin()+i-b;if(b>(this.options.step/2)){g+=this.options.step}return parseFloat(g.toFixed(5))},_start:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("start",d,b)},_slide:function(f,e,d){var g=this.handles[e];if(this.options.values&&this.options.values.length){var b=this.values(e?0:1);if((this.options.values.length==2&&this.options.range===true)&&((e==0&&d>b)||(e==1&&d<b))){d=b}if(d!=this.values(e)){var c=this.values();c[e]=d;var h=this._trigger("slide",f,{handle:this.handles[e],value:d,values:c});var b=this.values(e?0:1);if(h!==false){this.values(e,d,(f.type=="mousedown"&&this.options.animate),true)}}}else{if(d!=this.value()){var h=this._trigger("slide",f,{handle:this.handles[e],value:d});if(h!==false){this._setData("value",d,(f.type=="mousedown"&&this.options.animate))}}}},_stop:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("stop",d,b)},_change:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("change",d,b)},value:function(b){if(arguments.length){this._setData("value",b);this._change(null,0)}return this._value()},values:function(b,e,c,d){if(arguments.length>1){this.options.values[b]=e;this._refreshValue(c);if(!d){this._change(null,b)}}if(arguments.length){if(this.options.values&&this.options.values.length){return this._values(b)}else{return this.value()}}else{return this._values()}},_setData:function(b,d,c){a.widget.prototype._setData.apply(this,arguments);switch(b){case"disabled":if(d){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.attr("disabled","disabled")}else{this.handles.removeAttr("disabled")}case"orientation":this._detectOrientation();this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue(c);break;case"value":this._refreshValue(c);break}},_step:function(){var b=this.options.step;return b},_value:function(){var b=this.options.value;if(b<this._valueMin()){b=this._valueMin()}if(b>this._valueMax()){b=this._valueMax()}return b},_values:function(b){if(arguments.length){var c=this.options.values[b];if(c<this._valueMin()){c=this._valueMin()}if(c>this._valueMax()){c=this._valueMax()}return c}else{return this.options.values}},_valueMin:function(){var b=this.options.min;return b},_valueMax:function(){var b=this.options.max;return b},_refreshValue:function(c){var f=this.options.range,d=this.options,l=this;if(this.options.values&&this.options.values.length){var i,h;this.handles.each(function(p,n){var o=(l.values(p)-l._valueMin())/(l._valueMax()-l._valueMin())*100;var m={};m[l.orientation=="horizontal"?"left":"bottom"]=o+"%";a(this).stop(1,1)[c?"animate":"css"](m,d.animate);if(l.options.range===true){if(l.orientation=="horizontal"){(p==0)&&l.range.stop(1,1)[c?"animate":"css"]({left:o+"%"},d.animate);(p==1)&&l.range[c?"animate":"css"]({width:(o-lastValPercent)+"%"},{queue:false,duration:d.animate})}else{(p==0)&&l.range.stop(1,1)[c?"animate":"css"]({bottom:(o)+"%"},d.animate);(p==1)&&l.range[c?"animate":"css"]({height:(o-lastValPercent)+"%"},{queue:false,duration:d.animate})}}lastValPercent=o})}else{var j=this.value(),g=this._valueMin(),k=this._valueMax(),e=k!=g?(j-g)/(k-g)*100:0;var b={};b[l.orientation=="horizontal"?"left":"bottom"]=e+"%";this.handle.stop(1,1)[c?"animate":"css"](b,d.animate);(f=="min")&&(this.orientation=="horizontal")&&this.range.stop(1,1)[c?"animate":"css"]({width:e+"%"},d.animate);(f=="max")&&(this.orientation=="horizontal")&&this.range[c?"animate":"css"]({width:(100-e)+"%"},{queue:false,duration:d.animate});(f=="min")&&(this.orientation=="vertical")&&this.range.stop(1,1)[c?"animate":"css"]({height:e+"%"},d.animate);(f=="max")&&(this.orientation=="vertical")&&this.range[c?"animate":"css"]({height:(100-e)+"%"},{queue:false,duration:d.animate})}}}));a.extend(a.ui.slider,{getter:"value values",version:"1.7.2",eventPrefix:"slide",defaults:{animate:false,delay:0,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null}})})(jQuery);;/*
+ * jQuery UI Tabs 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Tabs
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(a){a.widget("ui.tabs",{_init:function(){if(this.options.deselectable!==undefined){this.options.collapsible=this.options.deselectable}this._tabify(true)},_setData:function(b,c){if(b=="selected"){if(this.options.collapsible&&c==this.options.selected){return}this.select(c)}else{this.options[b]=c;if(b=="deselectable"){this.options.collapsible=c}this._tabify()}},_tabId:function(b){return b.title&&b.title.replace(/\s/g,"_").replace(/[^A-Za-z0-9\-_:\.]/g,"")||this.options.idPrefix+a.data(b)},_sanitizeSelector:function(b){return b.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+a.data(this.list[0]));return a.cookie.apply(null,[b].concat(a.makeArray(arguments)))},_ui:function(c,b){return{tab:c,panel:b,index:this.anchors.index(c)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=a(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(n){this.list=this.element.children("ul:first");this.lis=a("li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return a("a",this)[0]});this.panels=a([]);var p=this,d=this.options;var c=/^#.+/;this.anchors.each(function(r,o){var q=a(o).attr("href");var s=q.split("#")[0],u;if(s&&(s===location.toString().split("#")[0]||(u=a("base")[0])&&s===u.href)){q=o.hash;o.href=q}if(c.test(q)){p.panels=p.panels.add(p._sanitizeSelector(q))}else{if(q!="#"){a.data(o,"href.tabs",q);a.data(o,"load.tabs",q.replace(/#.*$/,""));var w=p._tabId(o);o.href="#"+w;var v=a("#"+w);if(!v.length){v=a(d.panelTemplate).attr("id",w).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(p.panels[r-1]||p.list);v.data("destroy.tabs",true)}p.panels=p.panels.add(v)}else{d.disabled.push(r)}}});if(n){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all");this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(d.selected===undefined){if(location.hash){this.anchors.each(function(q,o){if(o.hash==location.hash){d.selected=q;return false}})}if(typeof d.selected!="number"&&d.cookie){d.selected=parseInt(p._cookie(),10)}if(typeof d.selected!="number"&&this.lis.filter(".ui-tabs-selected").length){d.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))}d.selected=d.selected||0}else{if(d.selected===null){d.selected=-1}}d.selected=((d.selected>=0&&this.anchors[d.selected])||d.selected<0)?d.selected:0;d.disabled=a.unique(d.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(q,o){return p.lis.index(q)}))).sort();if(a.inArray(d.selected,d.disabled)!=-1){d.disabled.splice(a.inArray(d.selected,d.disabled),1)}this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active");if(d.selected>=0&&this.anchors.length){this.panels.eq(d.selected).removeClass("ui-tabs-hide");this.lis.eq(d.selected).addClass("ui-tabs-selected ui-state-active");p.element.queue("tabs",function(){p._trigger("show",null,p._ui(p.anchors[d.selected],p.panels[d.selected]))});this.load(d.selected)}a(window).bind("unload",function(){p.lis.add(p.anchors).unbind(".tabs");p.lis=p.anchors=p.panels=null})}else{d.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))}this.element[d.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");if(d.cookie){this._cookie(d.selected,d.cookie)}for(var g=0,m;(m=this.lis[g]);g++){a(m)[a.inArray(g,d.disabled)!=-1&&!a(m).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled")}if(d.cache===false){this.anchors.removeData("cache.tabs")}this.lis.add(this.anchors).unbind(".tabs");if(d.event!="mouseover"){var f=function(o,i){if(i.is(":not(.ui-state-disabled)")){i.addClass("ui-state-"+o)}};var j=function(o,i){i.removeClass("ui-state-"+o)};this.lis.bind("mouseover.tabs",function(){f("hover",a(this))});this.lis.bind("mouseout.tabs",function(){j("hover",a(this))});this.anchors.bind("focus.tabs",function(){f("focus",a(this).closest("li"))});this.anchors.bind("blur.tabs",function(){j("focus",a(this).closest("li"))})}var b,h;if(d.fx){if(a.isArray(d.fx)){b=d.fx[0];h=d.fx[1]}else{b=h=d.fx}}function e(i,o){i.css({display:""});if(a.browser.msie&&o.opacity){i[0].style.removeAttribute("filter")}}var k=h?function(i,o){a(i).closest("li").removeClass("ui-state-default").addClass("ui-tabs-selected ui-state-active");o.hide().removeClass("ui-tabs-hide").animate(h,h.duration||"normal",function(){e(o,h);p._trigger("show",null,p._ui(i,o[0]))})}:function(i,o){a(i).closest("li").removeClass("ui-state-default").addClass("ui-tabs-selected ui-state-active");o.removeClass("ui-tabs-hide");p._trigger("show",null,p._ui(i,o[0]))};var l=b?function(o,i){i.animate(b,b.duration||"normal",function(){p.lis.removeClass("ui-tabs-selected ui-state-active").addClass("ui-state-default");i.addClass("ui-tabs-hide");e(i,b);p.element.dequeue("tabs")})}:function(o,i,q){p.lis.removeClass("ui-tabs-selected ui-state-active").addClass("ui-state-default");i.addClass("ui-tabs-hide");p.element.dequeue("tabs")};this.anchors.bind(d.event+".tabs",function(){var o=this,r=a(this).closest("li"),i=p.panels.filter(":not(.ui-tabs-hide)"),q=a(p._sanitizeSelector(this.hash));if((r.hasClass("ui-tabs-selected")&&!d.collapsible)||r.hasClass("ui-state-disabled")||r.hasClass("ui-state-processing")||p._trigger("select",null,p._ui(this,q[0]))===false){this.blur();return false}d.selected=p.anchors.index(this);p.abort();if(d.collapsible){if(r.hasClass("ui-tabs-selected")){d.selected=-1;if(d.cookie){p._cookie(d.selected,d.cookie)}p.element.queue("tabs",function(){l(o,i)}).dequeue("tabs");this.blur();return false}else{if(!i.length){if(d.cookie){p._cookie(d.selected,d.cookie)}p.element.queue("tabs",function(){k(o,q)});p.load(p.anchors.index(this));this.blur();return false}}}if(d.cookie){p._cookie(d.selected,d.cookie)}if(q.length){if(i.length){p.element.queue("tabs",function(){l(o,i)})}p.element.queue("tabs",function(){k(o,q)});p.load(p.anchors.index(this))}else{throw"jQuery UI Tabs: Mismatching fragment identifier."}if(a.browser.msie){this.blur()}});this.anchors.bind("click.tabs",function(){return false})},destroy:function(){var b=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var c=a.data(this,"href.tabs");if(c){this.href=c}var d=a(this).unbind(".tabs");a.each(["href","load","cache"],function(e,f){d.removeData(f+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){if(a.data(this,"destroy.tabs")){a(this).remove()}else{a(this).removeClass(["ui-state-default","ui-corner-top","ui-tabs-selected","ui-state-active","ui-state-hover","ui-state-focus","ui-state-disabled","ui-tabs-panel","ui-widget-content","ui-corner-bottom","ui-tabs-hide"].join(" "))}});if(b.cookie){this._cookie(null,b.cookie)}},add:function(e,d,c){if(c===undefined){c=this.anchors.length}var b=this,g=this.options,i=a(g.tabTemplate.replace(/#\{href\}/g,e).replace(/#\{label\}/g,d)),h=!e.indexOf("#")?e.replace("#",""):this._tabId(a("a",i)[0]);i.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var f=a("#"+h);if(!f.length){f=a(g.panelTemplate).attr("id",h).data("destroy.tabs",true)}f.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(c>=this.lis.length){i.appendTo(this.list);f.appendTo(this.list[0].parentNode)}else{i.insertBefore(this.lis[c]);f.insertBefore(this.panels[c])}g.disabled=a.map(g.disabled,function(k,j){return k>=c?++k:k});this._tabify();if(this.anchors.length==1){i.addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){b._trigger("show",null,b._ui(b.anchors[0],b.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[c],this.panels[c]))},remove:function(b){var d=this.options,e=this.lis.eq(b).remove(),c=this.panels.eq(b).remove();if(e.hasClass("ui-tabs-selected")&&this.anchors.length>1){this.select(b+(b+1<this.anchors.length?1:-1))}d.disabled=a.map(a.grep(d.disabled,function(g,f){return g!=b}),function(g,f){return g>=b?--g:g});this._tabify();this._trigger("remove",null,this._ui(e.find("a")[0],c[0]))},enable:function(b){var c=this.options;if(a.inArray(b,c.disabled)==-1){return}this.lis.eq(b).removeClass("ui-state-disabled");c.disabled=a.grep(c.disabled,function(e,d){return e!=b});this._trigger("enable",null,this._ui(this.anchors[b],this.panels[b]))},disable:function(c){var b=this,d=this.options;if(c!=d.selected){this.lis.eq(c).addClass("ui-state-disabled");d.disabled.push(c);d.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[c],this.panels[c]))}},select:function(b){if(typeof b=="string"){b=this.anchors.index(this.anchors.filter("[href$="+b+"]"))}else{if(b===null){b=-1}}if(b==-1&&this.options.collapsible){b=this.options.selected}this.anchors.eq(b).trigger(this.options.event+".tabs")},load:function(e){var c=this,g=this.options,b=this.anchors.eq(e)[0],d=a.data(b,"load.tabs");this.abort();if(!d||this.element.queue("tabs").length!==0&&a.data(b,"cache.tabs")){this.element.dequeue("tabs");return}this.lis.eq(e).addClass("ui-state-processing");if(g.spinner){var f=a("span",b);f.data("label.tabs",f.html()).html(g.spinner)}this.xhr=a.ajax(a.extend({},g.ajaxOptions,{url:d,success:function(i,h){a(c._sanitizeSelector(b.hash)).html(i);c._cleanup();if(g.cache){a.data(b,"cache.tabs",true)}c._trigger("load",null,c._ui(c.anchors[e],c.panels[e]));try{g.ajaxOptions.success(i,h)}catch(j){}c.element.dequeue("tabs")}}))},abort:function(){this.element.queue([]);this.panels.stop(false,true);if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup()},url:function(c,b){this.anchors.eq(c).removeData("cache.tabs").data("load.tabs",b)},length:function(){return this.anchors.length}});a.extend(a.ui.tabs,{version:"1.7.2",getter:"length",defaults:{ajaxOptions:null,cache:false,cookie:null,collapsible:false,disabled:[],event:"click",fx:null,idPrefix:"ui-tabs-",panelTemplate:"<div></div>",spinner:"<em>Loading&#8230;</em>",tabTemplate:'<li><a href="#{href}"><span>#{label}</span></a></li>'}});a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(d,f){var b=this,g=this.options;var c=b._rotate||(b._rotate=function(h){clearTimeout(b.rotation);b.rotation=setTimeout(function(){var i=g.selected;b.select(++i<b.anchors.length?i:0)},d);if(h){h.stopPropagation()}});var e=b._unrotate||(b._unrotate=!f?function(h){if(h.clientX){b.rotate(null)}}:function(h){t=g.selected;c()});if(d){this.element.bind("tabsshow",c);this.anchors.bind(g.event+".tabs",e);c()}else{clearTimeout(b.rotation);this.element.unbind("tabsshow",c);this.anchors.unbind(g.event+".tabs",e);delete this._rotate;delete this._unrotate}}})})(jQuery);;/*
+ * jQuery UI Datepicker 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Datepicker
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function($){$.extend($.ui,{datepicker:{version:"1.7.2"}});var PROP_NAME="datepicker";function Datepicker(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._datepickerShowing=false;this._inDialog=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass="ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],dateFormat:"mm/dd/yy",firstDay:0,isRTL:false};this._defaults={showOn:"focus",showAnim:"show",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,showMonthAfterYear:false,yearRange:"-10:+10",showOtherMonths:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"normal",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false};$.extend(this._defaults,this.regional[""]);this.dpDiv=$('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>')}$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",log:function(){if(this.debug){console.log.apply("",arguments)}},setDefaults:function(settings){extendRemove(this._defaults,settings||{});return this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase();var inline=(nodeName=="div"||nodeName=="span");if(!target.id){target.id="dp"+(++this.uuid)}var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{});if(nodeName=="input"){this._connectDatepicker(target,inst)}else{if(inline){this._inlineDatepicker(target,inst)}}},_newInst:function(target,inline){var id=target[0].id.replace(/([:\[\]\.])/g,"\\\\$1");return{id:id,input:target,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:inline,dpDiv:(!inline?this.dpDiv:$('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}},_connectDatepicker:function(target,inst){var input=$(target);inst.append=$([]);inst.trigger=$([]);if(input.hasClass(this.markerClassName)){return}var appendText=this._get(inst,"appendText");var isRTL=this._get(inst,"isRTL");if(appendText){inst.append=$('<span class="'+this._appendClass+'">'+appendText+"</span>");input[isRTL?"before":"after"](inst.append)}var showOn=this._get(inst,"showOn");if(showOn=="focus"||showOn=="both"){input.focus(this._showDatepicker)}if(showOn=="button"||showOn=="both"){var buttonText=this._get(inst,"buttonText");var buttonImage=this._get(inst,"buttonImage");inst.trigger=$(this._get(inst,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:buttonImage,alt:buttonText,title:buttonText}):$('<button type="button"></button>').addClass(this._triggerClass).html(buttonImage==""?buttonText:$("<img/>").attr({src:buttonImage,alt:buttonText,title:buttonText})));input[isRTL?"before":"after"](inst.trigger);inst.trigger.click(function(){if($.datepicker._datepickerShowing&&$.datepicker._lastInput==target){$.datepicker._hideDatepicker()}else{$.datepicker._showDatepicker(target)}return false})}input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).bind("setData.datepicker",function(event,key,value){inst.settings[key]=value}).bind("getData.datepicker",function(event,key){return this._get(inst,key)});$.data(target,PROP_NAME,inst)},_inlineDatepicker:function(target,inst){var divSpan=$(target);if(divSpan.hasClass(this.markerClassName)){return}divSpan.addClass(this.markerClassName).append(inst.dpDiv).bind("setData.datepicker",function(event,key,value){inst.settings[key]=value}).bind("getData.datepicker",function(event,key){return this._get(inst,key)});$.data(target,PROP_NAME,inst);this._setDate(inst,this._getDefaultDate(inst));this._updateDatepicker(inst);this._updateAlternate(inst)},_dialogDatepicker:function(input,dateText,onSelect,settings,pos){var inst=this._dialogInst;if(!inst){var id="dp"+(++this.uuid);this._dialogInput=$('<input type="text" id="'+id+'" size="1" style="position: absolute; top: -100px;"/>');this._dialogInput.keydown(this._doKeyDown);$("body").append(this._dialogInput);inst=this._dialogInst=this._newInst(this._dialogInput,false);inst.settings={};$.data(this._dialogInput[0],PROP_NAME,inst)}extendRemove(inst.settings,settings||{});this._dialogInput.val(dateText);this._pos=(pos?(pos.length?pos:[pos.pageX,pos.pageY]):null);if(!this._pos){var browserWidth=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;var browserHeight=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;var scrollX=document.documentElement.scrollLeft||document.body.scrollLeft;var scrollY=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[(browserWidth/2)-100+scrollX,(browserHeight/2)-150+scrollY]}this._dialogInput.css("left",this._pos[0]+"px").css("top",this._pos[1]+"px");inst.settings.onSelect=onSelect;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);if($.blockUI){$.blockUI(this.dpDiv)}$.data(this._dialogInput[0],PROP_NAME,inst);return this},_destroyDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();$.removeData(target,PROP_NAME);if(nodeName=="input"){inst.append.remove();inst.trigger.remove();$target.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress)}else{if(nodeName=="div"||nodeName=="span"){$target.removeClass(this.markerClassName).empty()}}},_enableDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();if(nodeName=="input"){target.disabled=false;inst.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else{if(nodeName=="div"||nodeName=="span"){var inline=$target.children("."+this._inlineClass);inline.children().removeClass("ui-state-disabled")}}this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value)})},_disableDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();if(nodeName=="input"){target.disabled=true;inst.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else{if(nodeName=="div"||nodeName=="span"){var inline=$target.children("."+this._inlineClass);inline.children().addClass("ui-state-disabled")}}this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value)});this._disabledInputs[this._disabledInputs.length]=target},_isDisabledDatepicker:function(target){if(!target){return false}for(var i=0;i<this._disabledInputs.length;i++){if(this._disabledInputs[i]==target){return true}}return false},_getInst:function(target){try{return $.data(target,PROP_NAME)}catch(err){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(target,name,value){var inst=this._getInst(target);if(arguments.length==2&&typeof name=="string"){return(name=="defaults"?$.extend({},$.datepicker._defaults):(inst?(name=="all"?$.extend({},inst.settings):this._get(inst,name)):null))}var settings=name||{};if(typeof name=="string"){settings={};settings[name]=value}if(inst){if(this._curInst==inst){this._hideDatepicker(null)}var date=this._getDateDatepicker(target);extendRemove(inst.settings,settings);this._setDateDatepicker(target,date);this._updateDatepicker(inst)}},_changeDatepicker:function(target,name,value){this._optionDatepicker(target,name,value)},_refreshDatepicker:function(target){var inst=this._getInst(target);if(inst){this._updateDatepicker(inst)}},_setDateDatepicker:function(target,date,endDate){var inst=this._getInst(target);if(inst){this._setDate(inst,date,endDate);this._updateDatepicker(inst);this._updateAlternate(inst)}},_getDateDatepicker:function(target){var inst=this._getInst(target);if(inst&&!inst.inline){this._setDateFromField(inst)}return(inst?this._getDate(inst):null)},_doKeyDown:function(event){var inst=$.datepicker._getInst(event.target);var handled=true;var isRTL=inst.dpDiv.is(".ui-datepicker-rtl");inst._keyEvent=true;if($.datepicker._datepickerShowing){switch(event.keyCode){case 9:$.datepicker._hideDatepicker(null,"");break;case 13:var sel=$("td."+$.datepicker._dayOverClass+", td."+$.datepicker._currentClass,inst.dpDiv);if(sel[0]){$.datepicker._selectDay(event.target,inst.selectedMonth,inst.selectedYear,sel[0])}else{$.datepicker._hideDatepicker(null,$.datepicker._get(inst,"duration"))}return false;break;case 27:$.datepicker._hideDatepicker(null,$.datepicker._get(inst,"duration"));break;case 33:$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,"stepBigMonths"):-$.datepicker._get(inst,"stepMonths")),"M");break;case 34:$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,"stepBigMonths"):+$.datepicker._get(inst,"stepMonths")),"M");break;case 35:if(event.ctrlKey||event.metaKey){$.datepicker._clearDate(event.target)}handled=event.ctrlKey||event.metaKey;break;case 36:if(event.ctrlKey||event.metaKey){$.datepicker._gotoToday(event.target)}handled=event.ctrlKey||event.metaKey;break;case 37:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,(isRTL?+1:-1),"D")}handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey){$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,"stepBigMonths"):-$.datepicker._get(inst,"stepMonths")),"M")}break;case 38:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,-7,"D")}handled=event.ctrlKey||event.metaKey;break;case 39:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,(isRTL?-1:+1),"D")}handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey){$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,"stepBigMonths"):+$.datepicker._get(inst,"stepMonths")),"M")}break;case 40:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,+7,"D")}handled=event.ctrlKey||event.metaKey;break;default:handled=false}}else{if(event.keyCode==36&&event.ctrlKey){$.datepicker._showDatepicker(this)}else{handled=false}}if(handled){event.preventDefault();event.stopPropagation()}},_doKeyPress:function(event){var inst=$.datepicker._getInst(event.target);if($.datepicker._get(inst,"constrainInput")){var chars=$.datepicker._possibleChars($.datepicker._get(inst,"dateFormat"));var chr=String.fromCharCode(event.charCode==undefined?event.keyCode:event.charCode);return event.ctrlKey||(chr<" "||!chars||chars.indexOf(chr)>-1)}},_showDatepicker:function(input){input=input.target||input;if(input.nodeName.toLowerCase()!="input"){input=$("input",input.parentNode)[0]}if($.datepicker._isDisabledDatepicker(input)||$.datepicker._lastInput==input){return}var inst=$.datepicker._getInst(input);var beforeShow=$.datepicker._get(inst,"beforeShow");extendRemove(inst.settings,(beforeShow?beforeShow.apply(input,[input,inst]):{}));$.datepicker._hideDatepicker(null,"");$.datepicker._lastInput=input;$.datepicker._setDateFromField(inst);if($.datepicker._inDialog){input.value=""}if(!$.datepicker._pos){$.datepicker._pos=$.datepicker._findPos(input);$.datepicker._pos[1]+=input.offsetHeight}var isFixed=false;$(input).parents().each(function(){isFixed|=$(this).css("position")=="fixed";return !isFixed});if(isFixed&&$.browser.opera){$.datepicker._pos[0]-=document.documentElement.scrollLeft;$.datepicker._pos[1]-=document.documentElement.scrollTop}var offset={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null;inst.rangeStart=null;inst.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});$.datepicker._updateDatepicker(inst);offset=$.datepicker._checkOffset(inst,offset,isFixed);inst.dpDiv.css({position:($.datepicker._inDialog&&$.blockUI?"static":(isFixed?"fixed":"absolute")),display:"none",left:offset.left+"px",top:offset.top+"px"});if(!inst.inline){var showAnim=$.datepicker._get(inst,"showAnim")||"show";var duration=$.datepicker._get(inst,"duration");var postProcess=function(){$.datepicker._datepickerShowing=true;if($.browser.msie&&parseInt($.browser.version,10)<7){$("iframe.ui-datepicker-cover").css({width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4})}};if($.effects&&$.effects[showAnim]){inst.dpDiv.show(showAnim,$.datepicker._get(inst,"showOptions"),duration,postProcess)}else{inst.dpDiv[showAnim](duration,postProcess)}if(duration==""){postProcess()}if(inst.input[0].type!="hidden"){inst.input[0].focus()}$.datepicker._curInst=inst}},_updateDatepicker:function(inst){var dims={width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4};var self=this;inst.dpDiv.empty().append(this._generateHTML(inst)).find("iframe.ui-datepicker-cover").css({width:dims.width,height:dims.height}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){$(this).removeClass("ui-state-hover");if(this.className.indexOf("ui-datepicker-prev")!=-1){$(this).removeClass("ui-datepicker-prev-hover")}if(this.className.indexOf("ui-datepicker-next")!=-1){$(this).removeClass("ui-datepicker-next-hover")}}).bind("mouseover",function(){if(!self._isDisabledDatepicker(inst.inline?inst.dpDiv.parent()[0]:inst.input[0])){$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");$(this).addClass("ui-state-hover");if(this.className.indexOf("ui-datepicker-prev")!=-1){$(this).addClass("ui-datepicker-prev-hover")}if(this.className.indexOf("ui-datepicker-next")!=-1){$(this).addClass("ui-datepicker-next-hover")}}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();var numMonths=this._getNumberOfMonths(inst);var cols=numMonths[1];var width=17;if(cols>1){inst.dpDiv.addClass("ui-datepicker-multi-"+cols).css("width",(width*cols)+"em")}else{inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("")}inst.dpDiv[(numMonths[0]!=1||numMonths[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");inst.dpDiv[(this._get(inst,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");if(inst.input&&inst.input[0].type!="hidden"&&inst==$.datepicker._curInst){$(inst.input[0]).focus()}},_checkOffset:function(inst,offset,isFixed){var dpWidth=inst.dpDiv.outerWidth();var dpHeight=inst.dpDiv.outerHeight();var inputWidth=inst.input?inst.input.outerWidth():0;var inputHeight=inst.input?inst.input.outerHeight():0;var viewWidth=(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)+$(document).scrollLeft();var viewHeight=(window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight)+$(document).scrollTop();offset.left-=(this._get(inst,"isRTL")?(dpWidth-inputWidth):0);offset.left-=(isFixed&&offset.left==inst.input.offset().left)?$(document).scrollLeft():0;offset.top-=(isFixed&&offset.top==(inst.input.offset().top+inputHeight))?$(document).scrollTop():0;offset.left-=(offset.left+dpWidth>viewWidth&&viewWidth>dpWidth)?Math.abs(offset.left+dpWidth-viewWidth):0;offset.top-=(offset.top+dpHeight>viewHeight&&viewHeight>dpHeight)?Math.abs(offset.top+dpHeight+inputHeight*2-viewHeight):0;return offset},_findPos:function(obj){while(obj&&(obj.type=="hidden"||obj.nodeType!=1)){obj=obj.nextSibling}var position=$(obj).offset();return[position.left,position.top]},_hideDatepicker:function(input,duration){var inst=this._curInst;if(!inst||(input&&inst!=$.data(input,PROP_NAME))){return}if(inst.stayOpen){this._selectDate("#"+inst.id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear))}inst.stayOpen=false;if(this._datepickerShowing){duration=(duration!=null?duration:this._get(inst,"duration"));var showAnim=this._get(inst,"showAnim");var postProcess=function(){$.datepicker._tidyDialog(inst)};if(duration!=""&&$.effects&&$.effects[showAnim]){inst.dpDiv.hide(showAnim,$.datepicker._get(inst,"showOptions"),duration,postProcess)}else{inst.dpDiv[(duration==""?"hide":(showAnim=="slideDown"?"slideUp":(showAnim=="fadeIn"?"fadeOut":"hide")))](duration,postProcess)}if(duration==""){this._tidyDialog(inst)}var onClose=this._get(inst,"onClose");if(onClose){onClose.apply((inst.input?inst.input[0]:null),[(inst.input?inst.input.val():""),inst])}this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if($.blockUI){$.unblockUI();$("body").append(this.dpDiv)}}this._inDialog=false}this._curInst=null},_tidyDialog:function(inst){inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(event){if(!$.datepicker._curInst){return}var $target=$(event.target);if(($target.parents("#"+$.datepicker._mainDivId).length==0)&&!$target.hasClass($.datepicker.markerClassName)&&!$target.hasClass($.datepicker._triggerClass)&&$.datepicker._datepickerShowing&&!($.datepicker._inDialog&&$.blockUI)){$.datepicker._hideDatepicker(null,"")}},_adjustDate:function(id,offset,period){var target=$(id);var inst=this._getInst(target[0]);if(this._isDisabledDatepicker(target[0])){return}this._adjustInstDate(inst,offset+(period=="M"?this._get(inst,"showCurrentAtPos"):0),period);this._updateDatepicker(inst)},_gotoToday:function(id){var target=$(id);var inst=this._getInst(target[0]);if(this._get(inst,"gotoCurrent")&&inst.currentDay){inst.selectedDay=inst.currentDay;inst.drawMonth=inst.selectedMonth=inst.currentMonth;inst.drawYear=inst.selectedYear=inst.currentYear}else{var date=new Date();inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear()}this._notifyChange(inst);this._adjustDate(target)},_selectMonthYear:function(id,select,period){var target=$(id);var inst=this._getInst(target[0]);inst._selectingMonthYear=false;inst["selected"+(period=="M"?"Month":"Year")]=inst["draw"+(period=="M"?"Month":"Year")]=parseInt(select.options[select.selectedIndex].value,10);this._notifyChange(inst);this._adjustDate(target)},_clickMonthYear:function(id){var target=$(id);var inst=this._getInst(target[0]);if(inst.input&&inst._selectingMonthYear&&!$.browser.msie){inst.input[0].focus()}inst._selectingMonthYear=!inst._selectingMonthYear},_selectDay:function(id,month,year,td){var target=$(id);if($(td).hasClass(this._unselectableClass)||this._isDisabledDatepicker(target[0])){return}var inst=this._getInst(target[0]);inst.selectedDay=inst.currentDay=$("a",td).html();inst.selectedMonth=inst.currentMonth=month;inst.selectedYear=inst.currentYear=year;if(inst.stayOpen){inst.endDay=inst.endMonth=inst.endYear=null}this._selectDate(id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear));if(inst.stayOpen){inst.rangeStart=this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay));this._updateDatepicker(inst)}},_clearDate:function(id){var target=$(id);var inst=this._getInst(target[0]);inst.stayOpen=false;inst.endDay=inst.endMonth=inst.endYear=inst.rangeStart=null;this._selectDate(target,"")},_selectDate:function(id,dateStr){var target=$(id);var inst=this._getInst(target[0]);dateStr=(dateStr!=null?dateStr:this._formatDate(inst));if(inst.input){inst.input.val(dateStr)}this._updateAlternate(inst);var onSelect=this._get(inst,"onSelect");if(onSelect){onSelect.apply((inst.input?inst.input[0]:null),[dateStr,inst])}else{if(inst.input){inst.input.trigger("change")}}if(inst.inline){this._updateDatepicker(inst)}else{if(!inst.stayOpen){this._hideDatepicker(null,this._get(inst,"duration"));this._lastInput=inst.input[0];if(typeof(inst.input[0])!="object"){inst.input[0].focus()}this._lastInput=null}}},_updateAlternate:function(inst){var altField=this._get(inst,"altField");if(altField){var altFormat=this._get(inst,"altFormat")||this._get(inst,"dateFormat");var date=this._getDate(inst);dateStr=this.formatDate(altFormat,date,this._getFormatConfig(inst));$(altField).each(function(){$(this).val(dateStr)})}},noWeekends:function(date){var day=date.getDay();return[(day>0&&day<6),""]},iso8601Week:function(date){var checkDate=new Date(date.getFullYear(),date.getMonth(),date.getDate());var firstMon=new Date(checkDate.getFullYear(),1-1,4);var firstDay=firstMon.getDay()||7;firstMon.setDate(firstMon.getDate()+1-firstDay);if(firstDay<4&&checkDate<firstMon){checkDate.setDate(checkDate.getDate()-3);return $.datepicker.iso8601Week(checkDate)}else{if(checkDate>new Date(checkDate.getFullYear(),12-1,28)){firstDay=new Date(checkDate.getFullYear()+1,1-1,4).getDay()||7;if(firstDay>4&&(checkDate.getDay()||7)<firstDay-3){return 1}}}return Math.floor(((checkDate-firstMon)/86400000)/7)+1},parseDate:function(format,value,settings){if(format==null||value==null){throw"Invalid arguments"}value=(typeof value=="object"?value.toString():value+"");if(value==""){return null}var shortYearCutoff=(settings?settings.shortYearCutoff:null)||this._defaults.shortYearCutoff;var dayNamesShort=(settings?settings.dayNamesShort:null)||this._defaults.dayNamesShort;var dayNames=(settings?settings.dayNames:null)||this._defaults.dayNames;var monthNamesShort=(settings?settings.monthNamesShort:null)||this._defaults.monthNamesShort;var monthNames=(settings?settings.monthNames:null)||this._defaults.monthNames;var year=-1;var month=-1;var day=-1;var doy=-1;var literal=false;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches){iFormat++}return matches};var getNumber=function(match){lookAhead(match);var origSize=(match=="@"?14:(match=="y"?4:(match=="o"?3:2)));var size=origSize;var num=0;while(size>0&&iValue<value.length&&value.charAt(iValue)>="0"&&value.charAt(iValue)<="9"){num=num*10+parseInt(value.charAt(iValue++),10);size--}if(size==origSize){throw"Missing number at position "+iValue}return num};var getName=function(match,shortNames,longNames){var names=(lookAhead(match)?longNames:shortNames);var size=0;for(var j=0;j<names.length;j++){size=Math.max(size,names[j].length)}var name="";var iInit=iValue;while(size>0&&iValue<value.length){name+=value.charAt(iValue++);for(var i=0;i<names.length;i++){if(name==names[i]){return i+1}}size--}throw"Unknown name at position "+iInit};var checkLiteral=function(){if(value.charAt(iValue)!=format.charAt(iFormat)){throw"Unexpected literal at position "+iValue}iValue++};var iValue=0;for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{checkLiteral()}}else{switch(format.charAt(iFormat)){case"d":day=getNumber("d");break;case"D":getName("D",dayNamesShort,dayNames);break;case"o":doy=getNumber("o");break;case"m":month=getNumber("m");break;case"M":month=getName("M",monthNamesShort,monthNames);break;case"y":year=getNumber("y");break;case"@":var date=new Date(getNumber("@"));year=date.getFullYear();month=date.getMonth()+1;day=date.getDate();break;case"'":if(lookAhead("'")){checkLiteral()}else{literal=true}break;default:checkLiteral()}}}if(year==-1){year=new Date().getFullYear()}else{if(year<100){year+=new Date().getFullYear()-new Date().getFullYear()%100+(year<=shortYearCutoff?0:-100)}}if(doy>-1){month=1;day=doy;do{var dim=this._getDaysInMonth(year,month-1);if(day<=dim){break}month++;day-=dim}while(true)}var date=this._daylightSavingAdjust(new Date(year,month-1,day));if(date.getFullYear()!=year||date.getMonth()+1!=month||date.getDate()!=day){throw"Invalid date"}return date},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TIMESTAMP:"@",W3C:"yy-mm-dd",formatDate:function(format,date,settings){if(!date){return""}var dayNamesShort=(settings?settings.dayNamesShort:null)||this._defaults.dayNamesShort;var dayNames=(settings?settings.dayNames:null)||this._defaults.dayNames;var monthNamesShort=(settings?settings.monthNamesShort:null)||this._defaults.monthNamesShort;var monthNames=(settings?settings.monthNames:null)||this._defaults.monthNames;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches){iFormat++}return matches};var formatNumber=function(match,value,len){var num=""+value;if(lookAhead(match)){while(num.length<len){num="0"+num}}return num};var formatName=function(match,value,shortNames,longNames){return(lookAhead(match)?longNames[value]:shortNames[value])};var output="";var literal=false;if(date){for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{output+=format.charAt(iFormat)}}else{switch(format.charAt(iFormat)){case"d":output+=formatNumber("d",date.getDate(),2);break;case"D":output+=formatName("D",date.getDay(),dayNamesShort,dayNames);break;case"o":var doy=date.getDate();for(var m=date.getMonth()-1;m>=0;m--){doy+=this._getDaysInMonth(date.getFullYear(),m)}output+=formatNumber("o",doy,3);break;case"m":output+=formatNumber("m",date.getMonth()+1,2);break;case"M":output+=formatName("M",date.getMonth(),monthNamesShort,monthNames);break;case"y":output+=(lookAhead("y")?date.getFullYear():(date.getYear()%100<10?"0":"")+date.getYear()%100);break;case"@":output+=date.getTime();break;case"'":if(lookAhead("'")){output+="'"}else{literal=true}break;default:output+=format.charAt(iFormat)}}}}return output},_possibleChars:function(format){var chars="";var literal=false;for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{chars+=format.charAt(iFormat)}}else{switch(format.charAt(iFormat)){case"d":case"m":case"y":case"@":chars+="0123456789";break;case"D":case"M":return null;case"'":if(lookAhead("'")){chars+="'"}else{literal=true}break;default:chars+=format.charAt(iFormat)}}}return chars},_get:function(inst,name){return inst.settings[name]!==undefined?inst.settings[name]:this._defaults[name]},_setDateFromField:function(inst){var dateFormat=this._get(inst,"dateFormat");var dates=inst.input?inst.input.val():null;inst.endDay=inst.endMonth=inst.endYear=null;var date=defaultDate=this._getDefaultDate(inst);var settings=this._getFormatConfig(inst);try{date=this.parseDate(dateFormat,dates,settings)||defaultDate}catch(event){this.log(event);date=defaultDate}inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear();inst.currentDay=(dates?date.getDate():0);inst.currentMonth=(dates?date.getMonth():0);inst.currentYear=(dates?date.getFullYear():0);this._adjustInstDate(inst)},_getDefaultDate:function(inst){var date=this._determineDate(this._get(inst,"defaultDate"),new Date());var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);return date},_determineDate:function(date,defaultDate){var offsetNumeric=function(offset){var date=new Date();date.setDate(date.getDate()+offset);return date};var offsetString=function(offset,getDaysInMonth){var date=new Date();var year=date.getFullYear();var month=date.getMonth();var day=date.getDate();var pattern=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;var matches=pattern.exec(offset);while(matches){switch(matches[2]||"d"){case"d":case"D":day+=parseInt(matches[1],10);break;case"w":case"W":day+=parseInt(matches[1],10)*7;break;case"m":case"M":month+=parseInt(matches[1],10);day=Math.min(day,getDaysInMonth(year,month));break;case"y":case"Y":year+=parseInt(matches[1],10);day=Math.min(day,getDaysInMonth(year,month));break}matches=pattern.exec(offset)}return new Date(year,month,day)};date=(date==null?defaultDate:(typeof date=="string"?offsetString(date,this._getDaysInMonth):(typeof date=="number"?(isNaN(date)?defaultDate:offsetNumeric(date)):date)));date=(date&&date.toString()=="Invalid Date"?defaultDate:date);if(date){date.setHours(0);date.setMinutes(0);date.setSeconds(0);date.setMilliseconds(0)}return this._daylightSavingAdjust(date)},_daylightSavingAdjust:function(date){if(!date){return null}date.setHours(date.getHours()>12?date.getHours()+2:0);return date},_setDate:function(inst,date,endDate){var clear=!(date);var origMonth=inst.selectedMonth;var origYear=inst.selectedYear;date=this._determineDate(date,new Date());inst.selectedDay=inst.currentDay=date.getDate();inst.drawMonth=inst.selectedMonth=inst.currentMonth=date.getMonth();inst.drawYear=inst.selectedYear=inst.currentYear=date.getFullYear();if(origMonth!=inst.selectedMonth||origYear!=inst.selectedYear){this._notifyChange(inst)}this._adjustInstDate(inst);if(inst.input){inst.input.val(clear?"":this._formatDate(inst))}},_getDate:function(inst){var startDate=(!inst.currentYear||(inst.input&&inst.input.val()=="")?null:this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));return startDate},_generateHTML:function(inst){var today=new Date();today=this._daylightSavingAdjust(new Date(today.getFullYear(),today.getMonth(),today.getDate()));var isRTL=this._get(inst,"isRTL");var showButtonPanel=this._get(inst,"showButtonPanel");var hideIfNoPrevNext=this._get(inst,"hideIfNoPrevNext");var navigationAsDateFormat=this._get(inst,"navigationAsDateFormat");var numMonths=this._getNumberOfMonths(inst);var showCurrentAtPos=this._get(inst,"showCurrentAtPos");var stepMonths=this._get(inst,"stepMonths");var stepBigMonths=this._get(inst,"stepBigMonths");var isMultiMonth=(numMonths[0]!=1||numMonths[1]!=1);var currentDate=this._daylightSavingAdjust((!inst.currentDay?new Date(9999,9,9):new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");var drawMonth=inst.drawMonth-showCurrentAtPos;var drawYear=inst.drawYear;if(drawMonth<0){drawMonth+=12;drawYear--}if(maxDate){var maxDraw=this._daylightSavingAdjust(new Date(maxDate.getFullYear(),maxDate.getMonth()-numMonths[1]+1,maxDate.getDate()));maxDraw=(minDate&&maxDraw<minDate?minDate:maxDraw);while(this._daylightSavingAdjust(new Date(drawYear,drawMonth,1))>maxDraw){drawMonth--;if(drawMonth<0){drawMonth=11;drawYear--}}}inst.drawMonth=drawMonth;inst.drawYear=drawYear;var prevText=this._get(inst,"prevText");prevText=(!navigationAsDateFormat?prevText:this.formatDate(prevText,this._daylightSavingAdjust(new Date(drawYear,drawMonth-stepMonths,1)),this._getFormatConfig(inst)));var prev=(this._canAdjustMonth(inst,-1,drawYear,drawMonth)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+"', -"+stepMonths+", 'M');\" title=\""+prevText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"e":"w")+'">'+prevText+"</span></a>":(hideIfNoPrevNext?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+prevText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"e":"w")+'">'+prevText+"</span></a>"));var nextText=this._get(inst,"nextText");nextText=(!navigationAsDateFormat?nextText:this.formatDate(nextText,this._daylightSavingAdjust(new Date(drawYear,drawMonth+stepMonths,1)),this._getFormatConfig(inst)));var next=(this._canAdjustMonth(inst,+1,drawYear,drawMonth)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+"', +"+stepMonths+", 'M');\" title=\""+nextText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"w":"e")+'">'+nextText+"</span></a>":(hideIfNoPrevNext?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+nextText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"w":"e")+'">'+nextText+"</span></a>"));var currentText=this._get(inst,"currentText");var gotoDate=(this._get(inst,"gotoCurrent")&&inst.currentDay?currentDate:today);currentText=(!navigationAsDateFormat?currentText:this.formatDate(currentText,gotoDate,this._getFormatConfig(inst)));var controls=(!inst.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">'+this._get(inst,"closeText")+"</button>":"");var buttonPanel=(showButtonPanel)?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(isRTL?controls:"")+(this._isInRange(inst,gotoDate)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#'+inst.id+"');\">"+currentText+"</button>":"")+(isRTL?"":controls)+"</div>":"";var firstDay=parseInt(this._get(inst,"firstDay"),10);firstDay=(isNaN(firstDay)?0:firstDay);var dayNames=this._get(inst,"dayNames");var dayNamesShort=this._get(inst,"dayNamesShort");var dayNamesMin=this._get(inst,"dayNamesMin");var monthNames=this._get(inst,"monthNames");var monthNamesShort=this._get(inst,"monthNamesShort");var beforeShowDay=this._get(inst,"beforeShowDay");var showOtherMonths=this._get(inst,"showOtherMonths");var calculateWeek=this._get(inst,"calculateWeek")||this.iso8601Week;var endDate=inst.endDay?this._daylightSavingAdjust(new Date(inst.endYear,inst.endMonth,inst.endDay)):currentDate;var defaultDate=this._getDefaultDate(inst);var html="";for(var row=0;row<numMonths[0];row++){var group="";for(var col=0;col<numMonths[1];col++){var selectedDate=this._daylightSavingAdjust(new Date(drawYear,drawMonth,inst.selectedDay));var cornerClass=" ui-corner-all";var calender="";if(isMultiMonth){calender+='<div class="ui-datepicker-group ui-datepicker-group-';switch(col){case 0:calender+="first";cornerClass=" ui-corner-"+(isRTL?"right":"left");break;case numMonths[1]-1:calender+="last";cornerClass=" ui-corner-"+(isRTL?"left":"right");break;default:calender+="middle";cornerClass="";break}calender+='">'}calender+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+cornerClass+'">'+(/all|left/.test(cornerClass)&&row==0?(isRTL?next:prev):"")+(/all|right/.test(cornerClass)&&row==0?(isRTL?prev:next):"")+this._generateMonthYearHeader(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,row>0||col>0,monthNames,monthNamesShort)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var thead="";for(var dow=0;dow<7;dow++){var day=(dow+firstDay)%7;thead+="<th"+((dow+firstDay+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+dayNames[day]+'">'+dayNamesMin[day]+"</span></th>"}calender+=thead+"</tr></thead><tbody>";var daysInMonth=this._getDaysInMonth(drawYear,drawMonth);if(drawYear==inst.selectedYear&&drawMonth==inst.selectedMonth){inst.selectedDay=Math.min(inst.selectedDay,daysInMonth)}var leadDays=(this._getFirstDayOfMonth(drawYear,drawMonth)-firstDay+7)%7;var numRows=(isMultiMonth?6:Math.ceil((leadDays+daysInMonth)/7));var printDate=this._daylightSavingAdjust(new Date(drawYear,drawMonth,1-leadDays));for(var dRow=0;dRow<numRows;dRow++){calender+="<tr>";var tbody="";for(var dow=0;dow<7;dow++){var daySettings=(beforeShowDay?beforeShowDay.apply((inst.input?inst.input[0]:null),[printDate]):[true,""]);var otherMonth=(printDate.getMonth()!=drawMonth);var unselectable=otherMonth||!daySettings[0]||(minDate&&printDate<minDate)||(maxDate&&printDate>maxDate);tbody+='<td class="'+((dow+firstDay+6)%7>=5?" ui-datepicker-week-end":"")+(otherMonth?" ui-datepicker-other-month":"")+((printDate.getTime()==selectedDate.getTime()&&drawMonth==inst.selectedMonth&&inst._keyEvent)||(defaultDate.getTime()==printDate.getTime()&&defaultDate.getTime()==selectedDate.getTime())?" "+this._dayOverClass:"")+(unselectable?" "+this._unselectableClass+" ui-state-disabled":"")+(otherMonth&&!showOtherMonths?"":" "+daySettings[1]+(printDate.getTime()>=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?" "+this._currentClass:"")+(printDate.getTime()==today.getTime()?" ui-datepicker-today":""))+'"'+((!otherMonth||showOtherMonths)&&daySettings[2]?' title="'+daySettings[2]+'"':"")+(unselectable?"":" onclick=\"DP_jQuery.datepicker._selectDay('#"+inst.id+"',"+drawMonth+","+drawYear+', this);return false;"')+">"+(otherMonth?(showOtherMonths?printDate.getDate():"&#xa0;"):(unselectable?'<span class="ui-state-default">'+printDate.getDate()+"</span>":'<a class="ui-state-default'+(printDate.getTime()==today.getTime()?" ui-state-highlight":"")+(printDate.getTime()>=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?" ui-state-active":"")+'" href="#">'+printDate.getDate()+"</a>"))+"</td>";printDate.setDate(printDate.getDate()+1);printDate=this._daylightSavingAdjust(printDate)}calender+=tbody+"</tr>"}drawMonth++;if(drawMonth>11){drawMonth=0;drawYear++}calender+="</tbody></table>"+(isMultiMonth?"</div>"+((numMonths[0]>0&&col==numMonths[1]-1)?'<div class="ui-datepicker-row-break"></div>':""):"");group+=calender}html+=group}html+=buttonPanel+($.browser.msie&&parseInt($.browser.version,10)<7&&!inst.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':"");inst._keyEvent=false;return html},_generateMonthYearHeader:function(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,secondary,monthNames,monthNamesShort){minDate=(inst.rangeStart&&minDate&&selectedDate<minDate?selectedDate:minDate);var changeMonth=this._get(inst,"changeMonth");var changeYear=this._get(inst,"changeYear");var showMonthAfterYear=this._get(inst,"showMonthAfterYear");var html='<div class="ui-datepicker-title">';var monthHtml="";if(secondary||!changeMonth){monthHtml+='<span class="ui-datepicker-month">'+monthNames[drawMonth]+"</span> "}else{var inMinYear=(minDate&&minDate.getFullYear()==drawYear);var inMaxYear=(maxDate&&maxDate.getFullYear()==drawYear);monthHtml+='<select class="ui-datepicker-month" onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+"', this, 'M');\" onclick=\"DP_jQuery.datepicker._clickMonthYear('#"+inst.id+"');\">";for(var month=0;month<12;month++){if((!inMinYear||month>=minDate.getMonth())&&(!inMaxYear||month<=maxDate.getMonth())){monthHtml+='<option value="'+month+'"'+(month==drawMonth?' selected="selected"':"")+">"+monthNamesShort[month]+"</option>"}}monthHtml+="</select>"}if(!showMonthAfterYear){html+=monthHtml+((secondary||changeMonth||changeYear)&&(!(changeMonth&&changeYear))?"&#xa0;":"")}if(secondary||!changeYear){html+='<span class="ui-datepicker-year">'+drawYear+"</span>"}else{var years=this._get(inst,"yearRange").split(":");var year=0;var endYear=0;if(years.length!=2){year=drawYear-10;endYear=drawYear+10}else{if(years[0].charAt(0)=="+"||years[0].charAt(0)=="-"){year=drawYear+parseInt(years[0],10);endYear=drawYear+parseInt(years[1],10)}else{year=parseInt(years[0],10);endYear=parseInt(years[1],10)}}year=(minDate?Math.max(year,minDate.getFullYear()):year);endYear=(maxDate?Math.min(endYear,maxDate.getFullYear()):endYear);html+='<select class="ui-datepicker-year" onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+"', this, 'Y');\" onclick=\"DP_jQuery.datepicker._clickMonthYear('#"+inst.id+"');\">";for(;year<=endYear;year++){html+='<option value="'+year+'"'+(year==drawYear?' selected="selected"':"")+">"+year+"</option>"}html+="</select>"}if(showMonthAfterYear){html+=(secondary||changeMonth||changeYear?"&#xa0;":"")+monthHtml}html+="</div>";return html},_adjustInstDate:function(inst,offset,period){var year=inst.drawYear+(period=="Y"?offset:0);var month=inst.drawMonth+(period=="M"?offset:0);var day=Math.min(inst.selectedDay,this._getDaysInMonth(year,month))+(period=="D"?offset:0);var date=this._daylightSavingAdjust(new Date(year,month,day));var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear();if(period=="M"||period=="Y"){this._notifyChange(inst)}},_notifyChange:function(inst){var onChange=this._get(inst,"onChangeMonthYear");if(onChange){onChange.apply((inst.input?inst.input[0]:null),[inst.selectedYear,inst.selectedMonth+1,inst])}},_getNumberOfMonths:function(inst){var numMonths=this._get(inst,"numberOfMonths");return(numMonths==null?[1,1]:(typeof numMonths=="number"?[1,numMonths]:numMonths))},_getMinMaxDate:function(inst,minMax,checkRange){var date=this._determineDate(this._get(inst,minMax+"Date"),null);return(!checkRange||!inst.rangeStart?date:(!date||inst.rangeStart>date?inst.rangeStart:date))},_getDaysInMonth:function(year,month){return 32-new Date(year,month,32).getDate()},_getFirstDayOfMonth:function(year,month){return new Date(year,month,1).getDay()},_canAdjustMonth:function(inst,offset,curYear,curMonth){var numMonths=this._getNumberOfMonths(inst);var date=this._daylightSavingAdjust(new Date(curYear,curMonth+(offset<0?offset:numMonths[1]),1));if(offset<0){date.setDate(this._getDaysInMonth(date.getFullYear(),date.getMonth()))}return this._isInRange(inst,date)},_isInRange:function(inst,date){var newMinDate=(!inst.rangeStart?null:this._daylightSavingAdjust(new Date(inst.selectedYear,inst.selectedMonth,inst.selectedDay)));newMinDate=(newMinDate&&inst.rangeStart<newMinDate?inst.rangeStart:newMinDate);var minDate=newMinDate||this._getMinMaxDate(inst,"min");var maxDate=this._getMinMaxDate(inst,"max");return((!minDate||date>=minDate)&&(!maxDate||date<=maxDate))},_getFormatConfig:function(inst){var shortYearCutoff=this._get(inst,"shortYearCutoff");shortYearCutoff=(typeof shortYearCutoff!="string"?shortYearCutoff:new Date().getFullYear()%100+parseInt(shortYearCutoff,10));return{shortYearCutoff:shortYearCutoff,dayNamesShort:this._get(inst,"dayNamesShort"),dayNames:this._get(inst,"dayNames"),monthNamesShort:this._get(inst,"monthNamesShort"),monthNames:this._get(inst,"monthNames")}},_formatDate:function(inst,day,month,year){if(!day){inst.currentDay=inst.selectedDay;inst.currentMonth=inst.selectedMonth;inst.currentYear=inst.selectedYear}var date=(day?(typeof day=="object"?day:this._daylightSavingAdjust(new Date(year,month,day))):this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));return this.formatDate(this._get(inst,"dateFormat"),date,this._getFormatConfig(inst))}});function extendRemove(target,props){$.extend(target,props);for(var name in props){if(props[name]==null||props[name]==undefined){target[name]=props[name]}}return target}function isArray(a){return(a&&(($.browser.safari&&typeof a=="object"&&a.length)||(a.constructor&&a.constructor.toString().match(/\Array\(\)/))))}$.fn.datepicker=function(options){if(!$.datepicker.initialized){$(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv);$.datepicker.initialized=true}var otherArgs=Array.prototype.slice.call(arguments,1);if(typeof options=="string"&&(options=="isDisabled"||options=="getDate")){return $.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this[0]].concat(otherArgs))}if(options=="option"&&arguments.length==2&&typeof arguments[1]=="string"){return $.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this[0]].concat(otherArgs))}return this.each(function(){typeof options=="string"?$.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this].concat(otherArgs)):$.datepicker._attachDatepicker(this,options)})};$.datepicker=new Datepicker();$.datepicker.initialized=false;$.datepicker.uuid=new Date().getTime();$.datepicker.version="1.7.2";window.DP_jQuery=$})(jQuery);;/*
+ * jQuery UI Progressbar 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Progressbar
+ *
+ * Depends:
+ *   ui.core.js
+ */
+(function(a){a.widget("ui.progressbar",{_init:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this._valueMin(),"aria-valuemax":this._valueMax(),"aria-valuenow":this._value()});this.valueDiv=a('<div class="ui-progressbar-value ui-widget-header ui-corner-left"></div>').appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow").removeData("progressbar").unbind(".progressbar");this.valueDiv.remove();a.widget.prototype.destroy.apply(this,arguments)},value:function(b){if(b===undefined){return this._value()}this._setData("value",b);return this},_setData:function(b,c){switch(b){case"value":this.options.value=c;this._refreshValue();this._trigger("change",null,{});break}a.widget.prototype._setData.apply(this,arguments)},_value:function(){var b=this.options.value;if(b<this._valueMin()){b=this._valueMin()}if(b>this._valueMax()){b=this._valueMax()}return b},_valueMin:function(){var b=0;return b},_valueMax:function(){var b=100;return b},_refreshValue:function(){var b=this.value();this.valueDiv[b==this._valueMax()?"addClass":"removeClass"]("ui-corner-right");this.valueDiv.width(b+"%");this.element.attr("aria-valuenow",b)}});a.extend(a.ui.progressbar,{version:"1.7.2",defaults:{value:0}})})(jQuery);;/*
+ * jQuery UI Effects 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/
+ */
+jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(var f=0;f<h.length;f++){if(h[f]!==null){g.data("ec.storage."+h[f],g[0].style[h[f]])}}},restore:function(g,h){for(var f=0;f<h.length;f++){if(h[f]!==null){g.css(h[f],g.data("ec.storage."+h[f]))}}},setMode:function(f,g){if(g=="toggle"){g=f.is(":hidden")?"show":"hide"}return g},getBaseline:function(g,h){var i,f;switch(g[0]){case"top":i=0;break;case"middle":i=0.5;break;case"bottom":i=1;break;default:i=g[0]/h.height}switch(g[1]){case"left":f=0;break;case"center":f=0.5;break;case"right":f=1;break;default:f=g[1]/h.width}return{x:f,y:i}},createWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent()}var g={width:f.outerWidth(true),height:f.outerHeight(true),"float":f.css("float")};f.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');var j=f.parent();if(f.css("position")=="static"){j.css({position:"relative"});f.css({position:"relative"})}else{var i=f.css("top");if(isNaN(parseInt(i,10))){i="auto"}var h=f.css("left");if(isNaN(parseInt(h,10))){h="auto"}j.css({position:f.css("position"),top:i,left:h,zIndex:f.css("z-index")}).show();f.css({position:"relative",top:0,left:0})}j.css(g);return j},removeWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent().replaceWith(f)}return f},setTransition:function(g,i,f,h){h=h||{};d.each(i,function(k,j){unit=g.cssUnit(j);if(unit[0]>0){h[j]=unit[0]*f+unit[1]}});return h},animateClass:function(h,i,k,j){var f=(typeof k=="function"?k:(j?j:null));var g=(typeof k=="string"?k:null);return this.each(function(){var q={};var o=d(this);var p=o.attr("style")||"";if(typeof p=="object"){p=p.cssText}if(h.toggle){o.hasClass(h.toggle)?h.remove=h.toggle:h.add=h.toggle}var l=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.addClass(h.add)}if(h.remove){o.removeClass(h.remove)}var m=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.removeClass(h.add)}if(h.remove){o.addClass(h.remove)}for(var r in m){if(typeof m[r]!="function"&&m[r]&&r.indexOf("Moz")==-1&&r.indexOf("length")==-1&&m[r]!=l[r]&&(r.match(/color/i)||(!r.match(/color/i)&&!isNaN(parseInt(m[r],10))))&&(l.position!="static"||(l.position=="static"&&!r.match(/left|top|bottom|right/)))){q[r]=m[r]}}o.animate(q,i,g,function(){if(typeof d(this).attr("style")=="object"){d(this).attr("style")["cssText"]="";d(this).attr("style")["cssText"]=p}else{d(this).attr("style",p)}if(h.add){d(this).addClass(h.add)}if(h.remove){d(this).removeClass(h.remove)}if(f){f.apply(this,arguments)}})})}};function c(g,f){var i=g[1]&&g[1].constructor==Object?g[1]:{};if(f){i.mode=f}var h=g[1]&&g[1].constructor!=Object?g[1]:(i.duration?i.duration:g[2]);h=d.fx.off?0:typeof h==="number"?h:d.fx.speeds[h]||d.fx.speeds._default;var j=i.callback||(d.isFunction(g[1])&&g[1])||(d.isFunction(g[2])&&g[2])||(d.isFunction(g[3])&&g[3]);return[g[0],i,h,j]}d.fn.extend({_show:d.fn.show,_hide:d.fn.hide,__toggle:d.fn.toggle,_addClass:d.fn.addClass,_removeClass:d.fn.removeClass,_toggleClass:d.fn.toggleClass,effect:function(g,f,h,i){return d.effects[g]?d.effects[g].call(this,{method:g,options:f||{},duration:h,callback:i}):null},show:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._show.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"show"))}},hide:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._hide.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"hide"))}},toggle:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))||(d.isFunction(arguments[0])||typeof arguments[0]=="boolean")){return this.__toggle.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"toggle"))}},addClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{add:g},f,i,h]):this._addClass(g)},removeClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{remove:g},f,i,h]):this._removeClass(g)},toggleClass:function(g,f,i,h){return((typeof f!=="boolean")&&f)?d.effects.animateClass.apply(this,[{toggle:g},f,i,h]):this._toggleClass(g,f)},morph:function(f,h,g,j,i){return d.effects.animateClass.apply(this,[{add:h,remove:f},g,j,i])},switchClass:function(){return this.morph.apply(this,arguments)},cssUnit:function(f){var g=this.css(f),h=[];d.each(["em","px","%","pt"],function(j,k){if(g.indexOf(k)>0){h=[parseFloat(g),k]}});return h}});d.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(g,f){d.fx.step[f]=function(h){if(h.state==0){h.start=e(h.elem,f);h.end=b(h.end)}h.elem.style[f]="rgb("+[Math.max(Math.min(parseInt((h.pos*(h.end[0]-h.start[0]))+h.start[0],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[1]-h.start[1]))+h.start[1],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[2]-h.start[2]))+h.start[2],10),255),0)].join(",")+")"}});function b(g){var f;if(g&&g.constructor==Array&&g.length==3){return g}if(f=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(g)){return[parseInt(f[1],10),parseInt(f[2],10),parseInt(f[3],10)]}if(f=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(g)){return[parseFloat(f[1])*2.55,parseFloat(f[2])*2.55,parseFloat(f[3])*2.55]}if(f=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(g)){return[parseInt(f[1],16),parseInt(f[2],16),parseInt(f[3],16)]}if(f=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(g)){return[parseInt(f[1]+f[1],16),parseInt(f[2]+f[2],16),parseInt(f[3]+f[3],16)]}if(f=/rgba\(0, 0, 0, 0\)/.exec(g)){return a.transparent}return a[d.trim(g).toLowerCase()]}function e(h,f){var g;do{g=d.curCSS(h,f);if(g!=""&&g!="transparent"||d.nodeName(h,"body")){break}f="backgroundColor"}while(h=h.parentNode);return b(g)}var a={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]};d.easing.jswing=d.easing.swing;d.extend(d.easing,{def:"easeOutQuad",swing:function(g,h,f,j,i){return d.easing[d.easing.def](g,h,f,j,i)},easeInQuad:function(g,h,f,j,i){return j*(h/=i)*h+f},easeOutQuad:function(g,h,f,j,i){return -j*(h/=i)*(h-2)+f},easeInOutQuad:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h+f}return -j/2*((--h)*(h-2)-1)+f},easeInCubic:function(g,h,f,j,i){return j*(h/=i)*h*h+f},easeOutCubic:function(g,h,f,j,i){return j*((h=h/i-1)*h*h+1)+f},easeInOutCubic:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h+f}return j/2*((h-=2)*h*h+2)+f},easeInQuart:function(g,h,f,j,i){return j*(h/=i)*h*h*h+f},easeOutQuart:function(g,h,f,j,i){return -j*((h=h/i-1)*h*h*h-1)+f},easeInOutQuart:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h+f}return -j/2*((h-=2)*h*h*h-2)+f},easeInQuint:function(g,h,f,j,i){return j*(h/=i)*h*h*h*h+f},easeOutQuint:function(g,h,f,j,i){return j*((h=h/i-1)*h*h*h*h+1)+f},easeInOutQuint:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h*h+f}return j/2*((h-=2)*h*h*h*h+2)+f},easeInSine:function(g,h,f,j,i){return -j*Math.cos(h/i*(Math.PI/2))+j+f},easeOutSine:function(g,h,f,j,i){return j*Math.sin(h/i*(Math.PI/2))+f},easeInOutSine:function(g,h,f,j,i){return -j/2*(Math.cos(Math.PI*h/i)-1)+f},easeInExpo:function(g,h,f,j,i){return(h==0)?f:j*Math.pow(2,10*(h/i-1))+f},easeOutExpo:function(g,h,f,j,i){return(h==i)?f+j:j*(-Math.pow(2,-10*h/i)+1)+f},easeInOutExpo:function(g,h,f,j,i){if(h==0){return f}if(h==i){return f+j}if((h/=i/2)<1){return j/2*Math.pow(2,10*(h-1))+f}return j/2*(-Math.pow(2,-10*--h)+2)+f},easeInCirc:function(g,h,f,j,i){return -j*(Math.sqrt(1-(h/=i)*h)-1)+f},easeOutCirc:function(g,h,f,j,i){return j*Math.sqrt(1-(h=h/i-1)*h)+f},easeInOutCirc:function(g,h,f,j,i){if((h/=i/2)<1){return -j/2*(Math.sqrt(1-h*h)-1)+f}return j/2*(Math.sqrt(1-(h-=2)*h)+1)+f},easeInElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l)==1){return f+m}if(!k){k=l*0.3}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}return -(h*Math.pow(2,10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k))+f},easeOutElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l)==1){return f+m}if(!k){k=l*0.3}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}return h*Math.pow(2,-10*i)*Math.sin((i*l-j)*(2*Math.PI)/k)+m+f},easeInOutElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l/2)==2){return f+m}if(!k){k=l*(0.3*1.5)}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}if(i<1){return -0.5*(h*Math.pow(2,10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k))+f}return h*Math.pow(2,-10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k)*0.5+m+f},easeInBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}return k*(h/=j)*h*((i+1)*h-i)+f},easeOutBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}return k*((h=h/j-1)*h*((i+1)*h+i)+1)+f},easeInOutBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}if((h/=j/2)<1){return k/2*(h*h*(((i*=(1.525))+1)*h-i))+f}return k/2*((h-=2)*h*(((i*=(1.525))+1)*h+i)+2)+f},easeInBounce:function(g,h,f,j,i){return j-d.easing.easeOutBounce(g,i-h,0,j,i)+f},easeOutBounce:function(g,h,f,j,i){if((h/=i)<(1/2.75)){return j*(7.5625*h*h)+f}else{if(h<(2/2.75)){return j*(7.5625*(h-=(1.5/2.75))*h+0.75)+f}else{if(h<(2.5/2.75)){return j*(7.5625*(h-=(2.25/2.75))*h+0.9375)+f}else{return j*(7.5625*(h-=(2.625/2.75))*h+0.984375)+f}}}},easeInOutBounce:function(g,h,f,j,i){if(h<i/2){return d.easing.easeInBounce(g,h*2,0,j,i)*0.5+f}return d.easing.easeOutBounce(g,h*2-i,0,j,i)*0.5+j*0.5+f}})})(jQuery);;/*
+ * jQuery UI Effects Blind 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Blind
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.blind=function(b){return this.queue(function(){var d=a(this),c=["position","top","left"];var h=a.effects.setMode(d,b.options.mode||"hide");var g=b.options.direction||"vertical";a.effects.save(d,c);d.show();var j=a.effects.createWrapper(d).css({overflow:"hidden"});var e=(g=="vertical")?"height":"width";var i=(g=="vertical")?j.height():j.width();if(h=="show"){j.css(e,0)}var f={};f[e]=h=="show"?i:0;j.animate(f,b.duration,b.options.easing,function(){if(h=="hide"){d.hide()}a.effects.restore(d,c);a.effects.removeWrapper(d);if(b.callback){b.callback.apply(d[0],arguments)}d.dequeue()})})}})(jQuery);;/*
+ * jQuery UI Effects Bounce 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Bounce
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.bounce=function(b){return this.queue(function(){var e=a(this),l=["position","top","left"];var k=a.effects.setMode(e,b.options.mode||"effect");var n=b.options.direction||"up";var c=b.options.distance||20;var d=b.options.times||5;var g=b.duration||250;if(/show|hide/.test(k)){l.push("opacity")}a.effects.save(e,l);e.show();a.effects.createWrapper(e);var f=(n=="up"||n=="down")?"top":"left";var p=(n=="up"||n=="left")?"pos":"neg";var c=b.options.distance||(f=="top"?e.outerHeight({margin:true})/3:e.outerWidth({margin:true})/3);if(k=="show"){e.css("opacity",0).css(f,p=="pos"?-c:c)}if(k=="hide"){c=c/(d*2)}if(k!="hide"){d--}if(k=="show"){var h={opacity:1};h[f]=(p=="pos"?"+=":"-=")+c;e.animate(h,g/2,b.options.easing);c=c/2;d--}for(var j=0;j<d;j++){var o={},m={};o[f]=(p=="pos"?"-=":"+=")+c;m[f]=(p=="pos"?"+=":"-=")+c;e.animate(o,g/2,b.options.easing).animate(m,g/2,b.options.easing);c=(k=="hide")?c*2:c/2}if(k=="hide"){var h={opacity:0};h[f]=(p=="pos"?"-=":"+=")+c;e.animate(h,g/2,b.options.easing,function(){e.hide();a.effects.restore(e,l);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}})}else{var o={},m={};o[f]=(p=="pos"?"-=":"+=")+c;m[f]=(p=="pos"?"+=":"-=")+c;e.animate(o,g/2,b.options.easing).animate(m,g/2,b.options.easing,function(){a.effects.restore(e,l);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}})}e.queue("fx",function(){e.dequeue()});e.dequeue()})}})(jQuery);;/*
+ * jQuery UI Effects Clip 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Clip
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.clip=function(b){return this.queue(function(){var f=a(this),j=["position","top","left","height","width"];var i=a.effects.setMode(f,b.options.mode||"hide");var k=b.options.direction||"vertical";a.effects.save(f,j);f.show();var c=a.effects.createWrapper(f).css({overflow:"hidden"});var e=f[0].tagName=="IMG"?c:f;var g={size:(k=="vertical")?"height":"width",position:(k=="vertical")?"top":"left"};var d=(k=="vertical")?e.height():e.width();if(i=="show"){e.css(g.size,0);e.css(g.position,d/2)}var h={};h[g.size]=i=="show"?d:0;h[g.position]=i=="show"?0:d/2;e.animate(h,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(i=="hide"){f.hide()}a.effects.restore(f,j);a.effects.removeWrapper(f);if(b.callback){b.callback.apply(f[0],arguments)}f.dequeue()}})})}})(jQuery);;/*
+ * jQuery UI Effects Drop 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Drop
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.drop=function(b){return this.queue(function(){var e=a(this),d=["position","top","left","opacity"];var i=a.effects.setMode(e,b.options.mode||"hide");var h=b.options.direction||"left";a.effects.save(e,d);e.show();a.effects.createWrapper(e);var f=(h=="up"||h=="down")?"top":"left";var c=(h=="up"||h=="left")?"pos":"neg";var j=b.options.distance||(f=="top"?e.outerHeight({margin:true})/2:e.outerWidth({margin:true})/2);if(i=="show"){e.css("opacity",0).css(f,c=="pos"?-j:j)}var g={opacity:i=="show"?1:0};g[f]=(i=="show"?(c=="pos"?"+=":"-="):(c=="pos"?"-=":"+="))+j;e.animate(g,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(i=="hide"){e.hide()}a.effects.restore(e,d);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);;/*
+ * jQuery UI Effects Explode 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Explode
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.explode=function(b){return this.queue(function(){var k=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3;var e=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3;b.options.mode=b.options.mode=="toggle"?(a(this).is(":visible")?"hide":"show"):b.options.mode;var h=a(this).show().css("visibility","hidden");var l=h.offset();l.top-=parseInt(h.css("marginTop"),10)||0;l.left-=parseInt(h.css("marginLeft"),10)||0;var g=h.outerWidth(true);var c=h.outerHeight(true);for(var f=0;f<k;f++){for(var d=0;d<e;d++){h.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-d*(g/e),top:-f*(c/k)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:g/e,height:c/k,left:l.left+d*(g/e)+(b.options.mode=="show"?(d-Math.floor(e/2))*(g/e):0),top:l.top+f*(c/k)+(b.options.mode=="show"?(f-Math.floor(k/2))*(c/k):0),opacity:b.options.mode=="show"?0:1}).animate({left:l.left+d*(g/e)+(b.options.mode=="show"?0:(d-Math.floor(e/2))*(g/e)),top:l.top+f*(c/k)+(b.options.mode=="show"?0:(f-Math.floor(k/2))*(c/k)),opacity:b.options.mode=="show"?1:0},b.duration||500)}}setTimeout(function(){b.options.mode=="show"?h.css({visibility:"visible"}):h.css({visibility:"visible"}).hide();if(b.callback){b.callback.apply(h[0])}h.dequeue();a("div.ui-effects-explode").remove()},b.duration||500)})}})(jQuery);;/*
+ * jQuery UI Effects Fold 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Fold
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.fold=function(b){return this.queue(function(){var e=a(this),k=["position","top","left"];var h=a.effects.setMode(e,b.options.mode||"hide");var o=b.options.size||15;var n=!(!b.options.horizFirst);var g=b.duration?b.duration/2:a.fx.speeds._default/2;a.effects.save(e,k);e.show();var d=a.effects.createWrapper(e).css({overflow:"hidden"});var i=((h=="show")!=n);var f=i?["width","height"]:["height","width"];var c=i?[d.width(),d.height()]:[d.height(),d.width()];var j=/([0-9]+)%/.exec(o);if(j){o=parseInt(j[1],10)/100*c[h=="hide"?0:1]}if(h=="show"){d.css(n?{height:0,width:o}:{height:o,width:0})}var m={},l={};m[f[0]]=h=="show"?c[0]:o;l[f[1]]=h=="show"?c[1]:0;d.animate(m,g,b.options.easing).animate(l,g,b.options.easing,function(){if(h=="hide"){e.hide()}a.effects.restore(e,k);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(e[0],arguments)}e.dequeue()})})}})(jQuery);;/*
+ * jQuery UI Effects Highlight 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Highlight
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.highlight=function(b){return this.queue(function(){var e=a(this),d=["backgroundImage","backgroundColor","opacity"];var h=a.effects.setMode(e,b.options.mode||"show");var c=b.options.color||"#ffff99";var g=e.css("backgroundColor");a.effects.save(e,d);e.show();e.css({backgroundImage:"none",backgroundColor:c});var f={backgroundColor:g};if(h=="hide"){f.opacity=0}e.animate(f,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(h=="hide"){e.hide()}a.effects.restore(e,d);if(h=="show"&&a.browser.msie){this.style.removeAttribute("filter")}if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);;/*
+ * jQuery UI Effects Pulsate 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Pulsate
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.pulsate=function(b){return this.queue(function(){var d=a(this);var g=a.effects.setMode(d,b.options.mode||"show");var f=b.options.times||5;var e=b.duration?b.duration/2:a.fx.speeds._default/2;if(g=="hide"){f--}if(d.is(":hidden")){d.css("opacity",0);d.show();d.animate({opacity:1},e,b.options.easing);f=f-2}for(var c=0;c<f;c++){d.animate({opacity:0},e,b.options.easing).animate({opacity:1},e,b.options.easing)}if(g=="hide"){d.animate({opacity:0},e,b.options.easing,function(){d.hide();if(b.callback){b.callback.apply(this,arguments)}})}else{d.animate({opacity:0},e,b.options.easing).animate({opacity:1},e,b.options.easing,function(){if(b.callback){b.callback.apply(this,arguments)}})}d.queue("fx",function(){d.dequeue()});d.dequeue()})}})(jQuery);;/*
+ * jQuery UI Effects Scale 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Scale
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.puff=function(b){return this.queue(function(){var f=a(this);var c=a.extend(true,{},b.options);var h=a.effects.setMode(f,b.options.mode||"hide");var g=parseInt(b.options.percent,10)||150;c.fade=true;var e={height:f.height(),width:f.width()};var d=g/100;f.from=(h=="hide")?e:{height:e.height*d,width:e.width*d};c.from=f.from;c.percent=(h=="hide")?g:100;c.mode=h;f.effect("scale",c,b.duration,b.callback);f.dequeue()})};a.effects.scale=function(b){return this.queue(function(){var g=a(this);var d=a.extend(true,{},b.options);var j=a.effects.setMode(g,b.options.mode||"effect");var h=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:(j=="hide"?0:100));var i=b.options.direction||"both";var c=b.options.origin;if(j!="effect"){d.origin=c||["middle","center"];d.restore=true}var f={height:g.height(),width:g.width()};g.from=b.options.from||(j=="show"?{height:0,width:0}:f);var e={y:i!="horizontal"?(h/100):1,x:i!="vertical"?(h/100):1};g.to={height:f.height*e.y,width:f.width*e.x};if(b.options.fade){if(j=="show"){g.from.opacity=0;g.to.opacity=1}if(j=="hide"){g.from.opacity=1;g.to.opacity=0}}d.from=g.from;d.to=g.to;d.mode=j;g.effect("size",d,b.duration,b.callback);g.dequeue()})};a.effects.size=function(b){return this.queue(function(){var c=a(this),n=["position","top","left","width","height","overflow","opacity"];var m=["position","top","left","overflow","opacity"];var j=["width","height","overflow"];var p=["fontSize"];var k=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"];var f=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"];var g=a.effects.setMode(c,b.options.mode||"effect");var i=b.options.restore||false;var e=b.options.scale||"both";var o=b.options.origin;var d={height:c.height(),width:c.width()};c.from=b.options.from||d;c.to=b.options.to||d;if(o){var h=a.effects.getBaseline(o,d);c.from.top=(d.height-c.from.height)*h.y;c.from.left=(d.width-c.from.width)*h.x;c.to.top=(d.height-c.to.height)*h.y;c.to.left=(d.width-c.to.width)*h.x}var l={from:{y:c.from.height/d.height,x:c.from.width/d.width},to:{y:c.to.height/d.height,x:c.to.width/d.width}};if(e=="box"||e=="both"){if(l.from.y!=l.to.y){n=n.concat(k);c.from=a.effects.setTransition(c,k,l.from.y,c.from);c.to=a.effects.setTransition(c,k,l.to.y,c.to)}if(l.from.x!=l.to.x){n=n.concat(f);c.from=a.effects.setTransition(c,f,l.from.x,c.from);c.to=a.effects.setTransition(c,f,l.to.x,c.to)}}if(e=="content"||e=="both"){if(l.from.y!=l.to.y){n=n.concat(p);c.from=a.effects.setTransition(c,p,l.from.y,c.from);c.to=a.effects.setTransition(c,p,l.to.y,c.to)}}a.effects.save(c,i?n:m);c.show();a.effects.createWrapper(c);c.css("overflow","hidden").css(c.from);if(e=="content"||e=="both"){k=k.concat(["marginTop","marginBottom"]).concat(p);f=f.concat(["marginLeft","marginRight"]);j=n.concat(k).concat(f);c.find("*[width]").each(function(){child=a(this);if(i){a.effects.save(child,j)}var q={height:child.height(),width:child.width()};child.from={height:q.height*l.from.y,width:q.width*l.from.x};child.to={height:q.height*l.to.y,width:q.width*l.to.x};if(l.from.y!=l.to.y){child.from=a.effects.setTransition(child,k,l.from.y,child.from);child.to=a.effects.setTransition(child,k,l.to.y,child.to)}if(l.from.x!=l.to.x){child.from=a.effects.setTransition(child,f,l.from.x,child.from);child.to=a.effects.setTransition(child,f,l.to.x,child.to)}child.css(child.from);child.animate(child.to,b.duration,b.options.easing,function(){if(i){a.effects.restore(child,j)}})})}c.animate(c.to,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(g=="hide"){c.hide()}a.effects.restore(c,i?n:m);a.effects.removeWrapper(c);if(b.callback){b.callback.apply(this,arguments)}c.dequeue()}})})}})(jQuery);;/*
+ * jQuery UI Effects Shake 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Shake
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.shake=function(b){return this.queue(function(){var e=a(this),l=["position","top","left"];var k=a.effects.setMode(e,b.options.mode||"effect");var n=b.options.direction||"left";var c=b.options.distance||20;var d=b.options.times||3;var g=b.duration||b.options.duration||140;a.effects.save(e,l);e.show();a.effects.createWrapper(e);var f=(n=="up"||n=="down")?"top":"left";var p=(n=="up"||n=="left")?"pos":"neg";var h={},o={},m={};h[f]=(p=="pos"?"-=":"+=")+c;o[f]=(p=="pos"?"+=":"-=")+c*2;m[f]=(p=="pos"?"-=":"+=")+c*2;e.animate(h,g,b.options.easing);for(var j=1;j<d;j++){e.animate(o,g,b.options.easing).animate(m,g,b.options.easing)}e.animate(o,g,b.options.easing).animate(h,g/2,b.options.easing,function(){a.effects.restore(e,l);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}});e.queue("fx",function(){e.dequeue()});e.dequeue()})}})(jQuery);;/*
+ * jQuery UI Effects Slide 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Slide
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.slide=function(b){return this.queue(function(){var e=a(this),d=["position","top","left"];var i=a.effects.setMode(e,b.options.mode||"show");var h=b.options.direction||"left";a.effects.save(e,d);e.show();a.effects.createWrapper(e).css({overflow:"hidden"});var f=(h=="up"||h=="down")?"top":"left";var c=(h=="up"||h=="left")?"pos":"neg";var j=b.options.distance||(f=="top"?e.outerHeight({margin:true}):e.outerWidth({margin:true}));if(i=="show"){e.css(f,c=="pos"?-j:j)}var g={};g[f]=(i=="show"?(c=="pos"?"+=":"-="):(c=="pos"?"-=":"+="))+j;e.animate(g,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(i=="hide"){e.hide()}a.effects.restore(e,d);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);;/*
+ * jQuery UI Effects Transfer 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Transfer
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.transfer=function(b){return this.queue(function(){var f=a(this),h=a(b.options.to),e=h.offset(),g={top:e.top,left:e.left,height:h.innerHeight(),width:h.innerWidth()},d=f.offset(),c=a('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(b.options.className).css({top:d.top,left:d.left,height:f.innerHeight(),width:f.innerWidth(),position:"absolute"}).animate(g,b.duration,b.options.easing,function(){c.remove();(b.callback&&b.callback.apply(f[0],arguments));f.dequeue()})})}})(jQuery);;
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/jquery-ui-1.7.2.custom.zip b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/jquery-ui-1.7.2.custom.zip
new file mode 100644
index 0000000..119e646
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/jquery-ui-1.7.2.custom.zip
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/jquery-ui-1.7.2.full.min.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/jquery-ui-1.7.2.full.min.js
new file mode 100644
index 0000000..5497feb
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery-ui/jquery-ui-1.7.2.full.min.js
@@ -0,0 +1,298 @@
+/*
+ * jQuery UI 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI
+ */
+jQuery.ui||(function(c){var i=c.fn.remove,d=c.browser.mozilla&&(parseFloat(c.browser.version)<1.9);c.ui={version:"1.7.2",plugin:{add:function(k,l,n){var m=c.ui[k].prototype;for(var j in n){m.plugins[j]=m.plugins[j]||[];m.plugins[j].push([l,n[j]])}},call:function(j,l,k){var n=j.plugins[l];if(!n||!j.element[0].parentNode){return}for(var m=0;m<n.length;m++){if(j.options[n[m][0]]){n[m][1].apply(j.element,k)}}}},contains:function(k,j){return document.compareDocumentPosition?k.compareDocumentPosition(j)&16:k!==j&&k.contains(j)},hasScroll:function(m,k){if(c(m).css("overflow")=="hidden"){return false}var j=(k&&k=="left")?"scrollLeft":"scrollTop",l=false;if(m[j]>0){return true}m[j]=1;l=(m[j]>0);m[j]=0;return l},isOverAxis:function(k,j,l){return(k>j)&&(k<(j+l))},isOver:function(o,k,n,m,j,l){return c.ui.isOverAxis(o,n,j)&&c.ui.isOverAxis(k,m,l)},keyCode:{BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};if(d){var f=c.attr,e=c.fn.removeAttr,h="http://www.w3.org/2005/07/aaa",a=/^aria-/,b=/^wairole:/;c.attr=function(k,j,l){var m=l!==undefined;return(j=="role"?(m?f.call(this,k,j,"wairole:"+l):(f.apply(this,arguments)||"").replace(b,"")):(a.test(j)?(m?k.setAttributeNS(h,j.replace(a,"aaa:"),l):f.call(this,k,j.replace(a,"aaa:"))):f.apply(this,arguments)))};c.fn.removeAttr=function(j){return(a.test(j)?this.each(function(){this.removeAttributeNS(h,j.replace(a,""))}):e.call(this,j))}}c.fn.extend({remove:function(){c("*",this).add(this).each(function(){c(this).triggerHandler("remove")});return i.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","").unbind("selectstart.ui")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})},scrollParent:function(){var j;if((c.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){j=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(c.curCSS(this,"position",1))&&(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}else{j=this.parents().filter(function(){return(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!j.length?c(document):j}});c.extend(c.expr[":"],{data:function(l,k,j){return !!c.data(l,j[3])},focusable:function(k){var l=k.nodeName.toLowerCase(),j=c.attr(k,"tabindex");return(/input|select|textarea|button|object/.test(l)?!k.disabled:"a"==l||"area"==l?k.href||!isNaN(j):!isNaN(j))&&!c(k)["area"==l?"parents":"closest"](":hidden").length},tabbable:function(k){var j=c.attr(k,"tabindex");return(isNaN(j)||j>=0)&&c(k).is(":focusable")}});function g(m,n,o,l){function k(q){var p=c[m][n][q]||[];return(typeof p=="string"?p.split(/,?\s+/):p)}var j=k("getter");if(l.length==1&&typeof l[0]=="string"){j=j.concat(k("getterSetter"))}return(c.inArray(o,j)!=-1)}c.widget=function(k,j){var l=k.split(".")[0];k=k.split(".")[1];c.fn[k]=function(p){var n=(typeof p=="string"),o=Array.prototype.slice.call(arguments,1);if(n&&p.substring(0,1)=="_"){return this}if(n&&g(l,k,p,o)){var m=c.data(this[0],k);return(m?m[p].apply(m,o):undefined)}return this.each(function(){var q=c.data(this,k);(!q&&!n&&c.data(this,k,new c[l][k](this,p))._init());(q&&n&&c.isFunction(q[p])&&q[p].apply(q,o))})};c[l]=c[l]||{};c[l][k]=function(o,n){var m=this;this.namespace=l;this.widgetName=k;this.widgetEventPrefix=c[l][k].eventPrefix||k;this.widgetBaseClass=l+"-"+k;this.options=c.extend({},c.widget.defaults,c[l][k].defaults,c.metadata&&c.metadata.get(o)[k],n);this.element=c(o).bind("setData."+k,function(q,p,r){if(q.target==o){return m._setData(p,r)}}).bind("getData."+k,function(q,p){if(q.target==o){return m._getData(p)}}).bind("remove",function(){return m.destroy()})};c[l][k].prototype=c.extend({},c.widget.prototype,j);c[l][k].getterSetter="option"};c.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").removeAttr("aria-disabled")},option:function(l,m){var k=l,j=this;if(typeof l=="string"){if(m===undefined){return this._getData(l)}k={};k[l]=m}c.each(k,function(n,o){j._setData(n,o)})},_getData:function(j){return this.options[j]},_setData:function(j,k){this.options[j]=k;if(j=="disabled"){this.element[k?"addClass":"removeClass"](this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").attr("aria-disabled",k)}},enable:function(){this._setData("disabled",false)},disable:function(){this._setData("disabled",true)},_trigger:function(l,m,n){var p=this.options[l],j=(l==this.widgetEventPrefix?l:this.widgetEventPrefix+l);m=c.Event(m);m.type=j;if(m.originalEvent){for(var k=c.event.props.length,o;k;){o=c.event.props[--k];m[o]=m.originalEvent[o]}}this.element.trigger(m,n);return !(c.isFunction(p)&&p.call(this.element[0],m,n)===false||m.isDefaultPrevented())}};c.widget.defaults={disabled:false};c.ui.mouse={_mouseInit:function(){var j=this;this.element.bind("mousedown."+this.widgetName,function(k){return j._mouseDown(k)}).bind("click."+this.widgetName,function(k){if(j._preventClickEvent){j._preventClickEvent=false;k.stopImmediatePropagation();return false}});if(c.browser.msie){this._mouseUnselectable=this.element.attr("unselectable");this.element.attr("unselectable","on")}this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName);(c.browser.msie&&this.element.attr("unselectable",this._mouseUnselectable))},_mouseDown:function(l){l.originalEvent=l.originalEvent||{};if(l.originalEvent.mouseHandled){return}(this._mouseStarted&&this._mouseUp(l));this._mouseDownEvent=l;var k=this,m=(l.which==1),j=(typeof this.options.cancel=="string"?c(l.target).parents().add(l.target).filter(this.options.cancel).length:false);if(!m||j||!this._mouseCapture(l)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){k.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(l)&&this._mouseDelayMet(l)){this._mouseStarted=(this._mouseStart(l)!==false);if(!this._mouseStarted){l.preventDefault();return true}}this._mouseMoveDelegate=function(n){return k._mouseMove(n)};this._mouseUpDelegate=function(n){return k._mouseUp(n)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);(c.browser.safari||l.preventDefault());l.originalEvent.mouseHandled=true;return true},_mouseMove:function(j){if(c.browser.msie&&!j.button){return this._mouseUp(j)}if(this._mouseStarted){this._mouseDrag(j);return j.preventDefault()}if(this._mouseDistanceMet(j)&&this._mouseDelayMet(j)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,j)!==false);(this._mouseStarted?this._mouseDrag(j):this._mouseUp(j))}return !this._mouseStarted},_mouseUp:function(j){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=(j.target==this._mouseDownEvent.target);this._mouseStop(j)}return false},_mouseDistanceMet:function(j){return(Math.max(Math.abs(this._mouseDownEvent.pageX-j.pageX),Math.abs(this._mouseDownEvent.pageY-j.pageY))>=this.options.distance)},_mouseDelayMet:function(j){return this.mouseDelayMet},_mouseStart:function(j){},_mouseDrag:function(j){},_mouseStop:function(j){},_mouseCapture:function(j){return true}};c.ui.mouse.defaults={cancel:null,distance:1,delay:0}})(jQuery);;/*
+ * jQuery UI Draggable 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(a){a.widget("ui.draggable",a.extend({},a.ui.mouse,{_init:function(){if(this.options.helper=="original"&&!(/^(?:r|a|f)/).test(this.element.css("position"))){this.element[0].style.position="relative"}(this.options.addClasses&&this.element.addClass("ui-draggable"));(this.options.disabled&&this.element.addClass("ui-draggable-disabled"));this._mouseInit()},destroy:function(){if(!this.element.data("draggable")){return}this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy()},_mouseCapture:function(b){var c=this.options;if(this.helper||c.disabled||a(b.target).is(".ui-resizable-handle")){return false}this.handle=this._getHandle(b);if(!this.handle){return false}return true},_mouseStart:function(b){var c=this.options;this.helper=this._createHelper(b);this._cacheHelperProportions();if(a.ui.ddmanager){a.ui.ddmanager.current=this}this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(b);this.originalPageX=b.pageX;this.originalPageY=b.pageY;if(c.cursorAt){this._adjustOffsetFromHelper(c.cursorAt)}if(c.containment){this._setContainment()}this._trigger("start",b);this._cacheHelperProportions();if(a.ui.ddmanager&&!c.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,b)}this.helper.addClass("ui-draggable-dragging");this._mouseDrag(b,true);return true},_mouseDrag:function(b,d){this.position=this._generatePosition(b);this.positionAbs=this._convertPositionTo("absolute");if(!d){var c=this._uiHash();this._trigger("drag",b,c);this.position=c.position}if(!this.options.axis||this.options.axis!="y"){this.helper[0].style.left=this.position.left+"px"}if(!this.options.axis||this.options.axis!="x"){this.helper[0].style.top=this.position.top+"px"}if(a.ui.ddmanager){a.ui.ddmanager.drag(this,b)}return false},_mouseStop:function(c){var d=false;if(a.ui.ddmanager&&!this.options.dropBehaviour){d=a.ui.ddmanager.drop(this,c)}if(this.dropped){d=this.dropped;this.dropped=false}if((this.options.revert=="invalid"&&!d)||(this.options.revert=="valid"&&d)||this.options.revert===true||(a.isFunction(this.options.revert)&&this.options.revert.call(this.element,d))){var b=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){b._trigger("stop",c);b._clear()})}else{this._trigger("stop",c);this._clear()}return false},_getHandle:function(b){var c=!this.options.handle||!a(this.options.handle,this.element).length?true:false;a(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==b.target){c=true}});return c},_createHelper:function(c){var d=this.options;var b=a.isFunction(d.helper)?a(d.helper.apply(this.element[0],[c])):(d.helper=="clone"?this.element.clone():this.element);if(!b.parents("body").length){b.appendTo((d.appendTo=="parent"?this.element[0].parentNode:d.appendTo))}if(b[0]!=this.element[0]&&!(/(fixed|absolute)/).test(b.css("position"))){b.css("position","absolute")}return b},_adjustOffsetFromHelper:function(b){if(b.left!=undefined){this.offset.click.left=b.left+this.margins.left}if(b.right!=undefined){this.offset.click.left=this.helperProportions.width-b.right+this.margins.left}if(b.top!=undefined){this.offset.click.top=b.top+this.margins.top}if(b.bottom!=undefined){this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top}},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])){b.left+=this.scrollParent.scrollLeft();b.top+=this.scrollParent.scrollTop()}if((this.offsetParent[0]==document.body)||(this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)){b={top:0,left:0}}return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var b=this.element.position();return{top:b.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:b.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else{return{top:0,left:0}}},_cacheMargins:function(){this.margins={left:(parseInt(this.element.css("marginLeft"),10)||0),top:(parseInt(this.element.css("marginTop"),10)||0)}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e=this.options;if(e.containment=="parent"){e.containment=this.helper[0].parentNode}if(e.containment=="document"||e.containment=="window"){this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(e.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(e.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]}if(!(/^(document|window|parent)$/).test(e.containment)&&e.containment.constructor!=Array){var c=a(e.containment)[0];if(!c){return}var d=a(e.containment).offset();var b=(a(c).css("overflow")!="hidden");this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(b?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(b?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}else{if(e.containment.constructor==Array){this.containment=e.containment}}},_convertPositionTo:function(f,h){if(!h){h=this.position}var c=f=="absolute"?1:-1;var e=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=(/(html|body)/i).test(b[0].tagName);return{top:(h.top+this.offset.relative.top*c+this.offset.parent.top*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(g?0:b.scrollTop()))*c)),left:(h.left+this.offset.relative.left*c+this.offset.parent.left*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:b.scrollLeft())*c))}},_generatePosition:function(e){var h=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,i=(/(html|body)/i).test(b[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0])){this.offset.relative=this._getRelativeOffset()}var d=e.pageX;var c=e.pageY;if(this.originalPosition){if(this.containment){if(e.pageX-this.offset.click.left<this.containment[0]){d=this.containment[0]+this.offset.click.left}if(e.pageY-this.offset.click.top<this.containment[1]){c=this.containment[1]+this.offset.click.top}if(e.pageX-this.offset.click.left>this.containment[2]){d=this.containment[2]+this.offset.click.left}if(e.pageY-this.offset.click.top>this.containment[3]){c=this.containment[3]+this.offset.click.top}}if(h.grid){var g=this.originalPageY+Math.round((c-this.originalPageY)/h.grid[1])*h.grid[1];c=this.containment?(!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:(!(g-this.offset.click.top<this.containment[1])?g-h.grid[1]:g+h.grid[1])):g;var f=this.originalPageX+Math.round((d-this.originalPageX)/h.grid[0])*h.grid[0];d=this.containment?(!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:(!(f-this.offset.click.left<this.containment[0])?f-h.grid[0]:f+h.grid[0])):f}}return{top:(c-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(i?0:b.scrollTop())))),left:(d-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:b.scrollLeft())))}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");if(this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval){this.helper.remove()}this.helper=null;this.cancelHelperRemoval=false},_trigger:function(b,c,d){d=d||this._uiHash();a.ui.plugin.call(this,b,[c,d]);if(b=="drag"){this.positionAbs=this._convertPositionTo("absolute")}return a.widget.prototype._trigger.call(this,b,c,d)},plugins:{},_uiHash:function(b){return{helper:this.helper,position:this.position,absolutePosition:this.positionAbs,offset:this.positionAbs}}}));a.extend(a.ui.draggable,{version:"1.7.2",eventPrefix:"drag",defaults:{addClasses:true,appendTo:"parent",axis:false,cancel:":input,option",connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,delay:0,distance:1,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false}});a.ui.plugin.add("draggable","connectToSortable",{start:function(c,e){var d=a(this).data("draggable"),f=d.options,b=a.extend({},e,{item:d.element});d.sortables=[];a(f.connectToSortable).each(function(){var g=a.data(this,"sortable");if(g&&!g.options.disabled){d.sortables.push({instance:g,shouldRevert:g.options.revert});g._refreshItems();g._trigger("activate",c,b)}})},stop:function(c,e){var d=a(this).data("draggable"),b=a.extend({},e,{item:d.element});a.each(d.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;d.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert){this.instance.options.revert=true}this.instance._mouseStop(c);this.instance.options.helper=this.instance.options._helper;if(d.options.helper=="original"){this.instance.currentItem.css({top:"auto",left:"auto"})}}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",c,b)}})},drag:function(c,f){var e=a(this).data("draggable"),b=this;var d=function(i){var n=this.offset.click.top,m=this.offset.click.left;var g=this.positionAbs.top,k=this.positionAbs.left;var j=i.height,l=i.width;var p=i.top,h=i.left;return a.ui.isOver(g+n,k+m,p,h,j,l)};a.each(e.sortables,function(g){this.instance.positionAbs=e.positionAbs;this.instance.helperProportions=e.helperProportions;this.instance.offset.click=e.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=a(b).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return f.helper[0]};c.target=this.instance.currentItem[0];this.instance._mouseCapture(c,true);this.instance._mouseStart(c,true,true);this.instance.offset.click.top=e.offset.click.top;this.instance.offset.click.left=e.offset.click.left;this.instance.offset.parent.left-=e.offset.parent.left-this.instance.offset.parent.left;this.instance.offset.parent.top-=e.offset.parent.top-this.instance.offset.parent.top;e._trigger("toSortable",c);e.dropped=this.instance.element;e.currentItem=e.element;this.instance.fromOutside=e}if(this.instance.currentItem){this.instance._mouseDrag(c)}}else{if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",c,this.instance._uiHash(this.instance));this.instance._mouseStop(c,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();if(this.instance.placeholder){this.instance.placeholder.remove()}e._trigger("fromSortable",c);e.dropped=false}}})}});a.ui.plugin.add("draggable","cursor",{start:function(c,d){var b=a("body"),e=a(this).data("draggable").options;if(b.css("cursor")){e._cursor=b.css("cursor")}b.css("cursor",e.cursor)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._cursor){a("body").css("cursor",d._cursor)}}});a.ui.plugin.add("draggable","iframeFix",{start:function(b,c){var d=a(this).data("draggable").options;a(d.iframeFix===true?"iframe":d.iframeFix).each(function(){a('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1000}).css(a(this).offset()).appendTo("body")})},stop:function(b,c){a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});a.ui.plugin.add("draggable","opacity",{start:function(c,d){var b=a(d.helper),e=a(this).data("draggable").options;if(b.css("opacity")){e._opacity=b.css("opacity")}b.css("opacity",e.opacity)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._opacity){a(c.helper).css("opacity",d._opacity)}}});a.ui.plugin.add("draggable","scroll",{start:function(c,d){var b=a(this).data("draggable");if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!="HTML"){b.overflowOffset=b.scrollParent.offset()}},drag:function(d,e){var c=a(this).data("draggable"),f=c.options,b=false;if(c.scrollParent[0]!=document&&c.scrollParent[0].tagName!="HTML"){if(!f.axis||f.axis!="x"){if((c.overflowOffset.top+c.scrollParent[0].offsetHeight)-d.pageY<f.scrollSensitivity){c.scrollParent[0].scrollTop=b=c.scrollParent[0].scrollTop+f.scrollSpeed}else{if(d.pageY-c.overflowOffset.top<f.scrollSensitivity){c.scrollParent[0].scrollTop=b=c.scrollParent[0].scrollTop-f.scrollSpeed}}}if(!f.axis||f.axis!="y"){if((c.overflowOffset.left+c.scrollParent[0].offsetWidth)-d.pageX<f.scrollSensitivity){c.scrollParent[0].scrollLeft=b=c.scrollParent[0].scrollLeft+f.scrollSpeed}else{if(d.pageX-c.overflowOffset.left<f.scrollSensitivity){c.scrollParent[0].scrollLeft=b=c.scrollParent[0].scrollLeft-f.scrollSpeed}}}}else{if(!f.axis||f.axis!="x"){if(d.pageY-a(document).scrollTop()<f.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()-f.scrollSpeed)}else{if(a(window).height()-(d.pageY-a(document).scrollTop())<f.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()+f.scrollSpeed)}}}if(!f.axis||f.axis!="y"){if(d.pageX-a(document).scrollLeft()<f.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()-f.scrollSpeed)}else{if(a(window).width()-(d.pageX-a(document).scrollLeft())<f.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()+f.scrollSpeed)}}}}if(b!==false&&a.ui.ddmanager&&!f.dropBehaviour){a.ui.ddmanager.prepareOffsets(c,d)}}});a.ui.plugin.add("draggable","snap",{start:function(c,d){var b=a(this).data("draggable"),e=b.options;b.snapElements=[];a(e.snap.constructor!=String?(e.snap.items||":data(draggable)"):e.snap).each(function(){var g=a(this);var f=g.offset();if(this!=b.element[0]){b.snapElements.push({item:this,width:g.outerWidth(),height:g.outerHeight(),top:f.top,left:f.left})}})},drag:function(u,p){var g=a(this).data("draggable"),q=g.options;var y=q.snapTolerance;var x=p.offset.left,w=x+g.helperProportions.width,f=p.offset.top,e=f+g.helperProportions.height;for(var v=g.snapElements.length-1;v>=0;v--){var s=g.snapElements[v].left,n=s+g.snapElements[v].width,m=g.snapElements[v].top,A=m+g.snapElements[v].height;if(!((s-y<x&&x<n+y&&m-y<f&&f<A+y)||(s-y<x&&x<n+y&&m-y<e&&e<A+y)||(s-y<w&&w<n+y&&m-y<f&&f<A+y)||(s-y<w&&w<n+y&&m-y<e&&e<A+y))){if(g.snapElements[v].snapping){(g.options.snap.release&&g.options.snap.release.call(g.element,u,a.extend(g._uiHash(),{snapItem:g.snapElements[v].item})))}g.snapElements[v].snapping=false;continue}if(q.snapMode!="inner"){var c=Math.abs(m-e)<=y;var z=Math.abs(A-f)<=y;var j=Math.abs(s-w)<=y;var k=Math.abs(n-x)<=y;if(c){p.position.top=g._convertPositionTo("relative",{top:m-g.helperProportions.height,left:0}).top-g.margins.top}if(z){p.position.top=g._convertPositionTo("relative",{top:A,left:0}).top-g.margins.top}if(j){p.position.left=g._convertPositionTo("relative",{top:0,left:s-g.helperProportions.width}).left-g.margins.left}if(k){p.position.left=g._convertPositionTo("relative",{top:0,left:n}).left-g.margins.left}}var h=(c||z||j||k);if(q.snapMode!="outer"){var c=Math.abs(m-f)<=y;var z=Math.abs(A-e)<=y;var j=Math.abs(s-x)<=y;var k=Math.abs(n-w)<=y;if(c){p.position.top=g._convertPositionTo("relative",{top:m,left:0}).top-g.margins.top}if(z){p.position.top=g._convertPositionTo("relative",{top:A-g.helperProportions.height,left:0}).top-g.margins.top}if(j){p.position.left=g._convertPositionTo("relative",{top:0,left:s}).left-g.margins.left}if(k){p.position.left=g._convertPositionTo("relative",{top:0,left:n-g.helperProportions.width}).left-g.margins.left}}if(!g.snapElements[v].snapping&&(c||z||j||k||h)){(g.options.snap.snap&&g.options.snap.snap.call(g.element,u,a.extend(g._uiHash(),{snapItem:g.snapElements[v].item})))}g.snapElements[v].snapping=(c||z||j||k||h)}}});a.ui.plugin.add("draggable","stack",{start:function(b,c){var e=a(this).data("draggable").options;var d=a.makeArray(a(e.stack.group)).sort(function(g,f){return(parseInt(a(g).css("zIndex"),10)||e.stack.min)-(parseInt(a(f).css("zIndex"),10)||e.stack.min)});a(d).each(function(f){this.style.zIndex=e.stack.min+f});this[0].style.zIndex=e.stack.min+d.length}});a.ui.plugin.add("draggable","zIndex",{start:function(c,d){var b=a(d.helper),e=a(this).data("draggable").options;if(b.css("zIndex")){e._zIndex=b.css("zIndex")}b.css("zIndex",e.zIndex)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._zIndex){a(c.helper).css("zIndex",d._zIndex)}}})})(jQuery);;/*
+ * jQuery UI Droppable 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Droppables
+ *
+ * Depends:
+ *	ui.core.js
+ *	ui.draggable.js
+ */
+(function(a){a.widget("ui.droppable",{_init:function(){var c=this.options,b=c.accept;this.isover=0;this.isout=1;this.options.accept=this.options.accept&&a.isFunction(this.options.accept)?this.options.accept:function(e){return e.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};a.ui.ddmanager.droppables[this.options.scope]=a.ui.ddmanager.droppables[this.options.scope]||[];a.ui.ddmanager.droppables[this.options.scope].push(this);(this.options.addClasses&&this.element.addClass("ui-droppable"))},destroy:function(){var b=a.ui.ddmanager.droppables[this.options.scope];for(var c=0;c<b.length;c++){if(b[c]==this){b.splice(c,1)}}this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable")},_setData:function(b,c){if(b=="accept"){this.options.accept=c&&a.isFunction(c)?c:function(e){return e.is(c)}}else{a.widget.prototype._setData.apply(this,arguments)}},_activate:function(c){var b=a.ui.ddmanager.current;if(this.options.activeClass){this.element.addClass(this.options.activeClass)}(b&&this._trigger("activate",c,this.ui(b)))},_deactivate:function(c){var b=a.ui.ddmanager.current;if(this.options.activeClass){this.element.removeClass(this.options.activeClass)}(b&&this._trigger("deactivate",c,this.ui(b)))},_over:function(c){var b=a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.hoverClass){this.element.addClass(this.options.hoverClass)}this._trigger("over",c,this.ui(b))}},_out:function(c){var b=a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.hoverClass){this.element.removeClass(this.options.hoverClass)}this._trigger("out",c,this.ui(b))}},_drop:function(c,d){var b=d||a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return false}var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var f=a.data(this,"droppable");if(f.options.greedy&&a.ui.intersect(b,a.extend(f,{offset:f.element.offset()}),f.options.tolerance)){e=true;return false}});if(e){return false}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.activeClass){this.element.removeClass(this.options.activeClass)}if(this.options.hoverClass){this.element.removeClass(this.options.hoverClass)}this._trigger("drop",c,this.ui(b));return this.element}return false},ui:function(b){return{draggable:(b.currentItem||b.element),helper:b.helper,position:b.position,absolutePosition:b.positionAbs,offset:b.positionAbs}}});a.extend(a.ui.droppable,{version:"1.7.2",eventPrefix:"drop",defaults:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"}});a.ui.intersect=function(q,j,o){if(!j.offset){return false}var e=(q.positionAbs||q.position.absolute).left,d=e+q.helperProportions.width,n=(q.positionAbs||q.position.absolute).top,m=n+q.helperProportions.height;var g=j.offset.left,c=g+j.proportions.width,p=j.offset.top,k=p+j.proportions.height;switch(o){case"fit":return(g<e&&d<c&&p<n&&m<k);break;case"intersect":return(g<e+(q.helperProportions.width/2)&&d-(q.helperProportions.width/2)<c&&p<n+(q.helperProportions.height/2)&&m-(q.helperProportions.height/2)<k);break;case"pointer":var h=((q.positionAbs||q.position.absolute).left+(q.clickOffset||q.offset.click).left),i=((q.positionAbs||q.position.absolute).top+(q.clickOffset||q.offset.click).top),f=a.ui.isOver(i,h,p,g,j.proportions.height,j.proportions.width);return f;break;case"touch":return((n>=p&&n<=k)||(m>=p&&m<=k)||(n<p&&m>k))&&((e>=g&&e<=c)||(d>=g&&d<=c)||(e<g&&d>c));break;default:return false;break}};a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(e,g){var b=a.ui.ddmanager.droppables[e.options.scope];var f=g?g.type:null;var h=(e.currentItem||e.element).find(":data(droppable)").andSelf();droppablesLoop:for(var d=0;d<b.length;d++){if(b[d].options.disabled||(e&&!b[d].options.accept.call(b[d].element[0],(e.currentItem||e.element)))){continue}for(var c=0;c<h.length;c++){if(h[c]==b[d].element[0]){b[d].proportions.height=0;continue droppablesLoop}}b[d].visible=b[d].element.css("display")!="none";if(!b[d].visible){continue}b[d].offset=b[d].element.offset();b[d].proportions={width:b[d].element[0].offsetWidth,height:b[d].element[0].offsetHeight};if(f=="mousedown"){b[d]._activate.call(b[d],g)}}},drop:function(b,c){var d=false;a.each(a.ui.ddmanager.droppables[b.options.scope],function(){if(!this.options){return}if(!this.options.disabled&&this.visible&&a.ui.intersect(b,this,this.options.tolerance)){d=this._drop.call(this,c)}if(!this.options.disabled&&this.visible&&this.options.accept.call(this.element[0],(b.currentItem||b.element))){this.isout=1;this.isover=0;this._deactivate.call(this,c)}});return d},drag:function(b,c){if(b.options.refreshPositions){a.ui.ddmanager.prepareOffsets(b,c)}a.each(a.ui.ddmanager.droppables[b.options.scope],function(){if(this.options.disabled||this.greedyChild||!this.visible){return}var e=a.ui.intersect(b,this,this.options.tolerance);var g=!e&&this.isover==1?"isout":(e&&this.isover==0?"isover":null);if(!g){return}var f;if(this.options.greedy){var d=this.element.parents(":data(droppable):eq(0)");if(d.length){f=a.data(d[0],"droppable");f.greedyChild=(g=="isover"?1:0)}}if(f&&g=="isover"){f.isover=0;f.isout=1;f._out.call(f,c)}this[g]=1;this[g=="isout"?"isover":"isout"]=0;this[g=="isover"?"_over":"_out"].call(this,c);if(f&&g=="isout"){f.isout=0;f.isover=1;f._over.call(f,c)}})}}})(jQuery);;/*
+ * jQuery UI Resizable 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Resizables
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(c){c.widget("ui.resizable",c.extend({},c.ui.mouse,{_init:function(){var e=this,j=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(j.aspectRatio),aspectRatio:j.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:j.helper||j.ghost||j.animate?j.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){if(/relative/.test(this.element.css("position"))&&c.browser.opera){this.element.css({position:"relative",top:"auto",left:"auto"})}this.element.wrap(c('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=j.handles||(!c(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var k=this.handles.split(",");this.handles={};for(var f=0;f<k.length;f++){var h=c.trim(k[f]),d="ui-resizable-"+h;var g=c('<div class="ui-resizable-handle '+d+'"></div>');if(/sw|se|ne|nw/.test(h)){g.css({zIndex:++j.zIndex})}if("se"==h){g.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[h]=".ui-resizable-"+h;this.element.append(g)}}this._renderAxis=function(p){p=p||this.element;for(var m in this.handles){if(this.handles[m].constructor==String){this.handles[m]=c(this.handles[m],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var n=c(this.handles[m],this.element),o=0;o=/sw|ne|nw|se|n|s/.test(m)?n.outerHeight():n.outerWidth();var l=["padding",/ne|nw|n/.test(m)?"Top":/se|sw|s/.test(m)?"Bottom":/^e$/.test(m)?"Right":"Left"].join("");p.css(l,o);this._proportionallyResize()}if(!c(this.handles[m]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!e.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}e.axis=i&&i[1]?i[1]:"se"}});if(j.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){c(this).removeClass("ui-resizable-autohide");e._handles.show()},function(){if(!e.resizing){c(this).addClass("ui-resizable-autohide");e._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var d=function(f){c(f).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){d(this.element);var e=this.element;e.parent().append(this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")})).end().remove()}this.originalElement.css("resize",this.originalResizeStyle);d(this.originalElement)},_mouseCapture:function(e){var f=false;for(var d in this.handles){if(c(this.handles[d])[0]==e.target){f=true}}return this.options.disabled||!!f},_mouseStart:function(f){var i=this.options,e=this.element.position(),d=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(d.is(".ui-draggable")||(/absolute/).test(d.css("position"))){d.css({position:"absolute",top:e.top,left:e.left})}if(c.browser.opera&&(/relative/).test(d.css("position"))){d.css({position:"relative",top:"auto",left:"auto"})}this._renderProxy();var j=b(this.helper.css("left")),g=b(this.helper.css("top"));if(i.containment){j+=c(i.containment).scrollLeft()||0;g+=c(i.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:j,top:g};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:j,top:g};this.sizeDiff={width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:f.pageX,top:f.pageY};this.aspectRatio=(typeof i.aspectRatio=="number")?i.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var h=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",h=="auto"?this.axis+"-resize":h);d.addClass("ui-resizable-resizing");this._propagate("start",f);return true},_mouseDrag:function(d){var g=this.helper,f=this.options,l={},p=this,i=this.originalMousePosition,m=this.axis;var q=(d.pageX-i.left)||0,n=(d.pageY-i.top)||0;var h=this._change[m];if(!h){return false}var k=h.apply(this,[d,q,n]),j=c.browser.msie&&c.browser.version<7,e=this.sizeDiff;if(this._aspectRatio||d.shiftKey){k=this._updateRatio(k,d)}k=this._respectSize(k,d);this._propagate("resize",d);g.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(k);this._trigger("resize",d,this.ui());return false},_mouseStop:function(g){this.resizing=false;var h=this.options,l=this;if(this._helper){var f=this._proportionallyResizeElements,d=f.length&&(/textarea/i).test(f[0].nodeName),e=d&&c.ui.hasScroll(f[0],"left")?0:l.sizeDiff.height,j=d?0:l.sizeDiff.width;var m={width:(l.size.width-j),height:(l.size.height-e)},i=(parseInt(l.element.css("left"),10)+(l.position.left-l.originalPosition.left))||null,k=(parseInt(l.element.css("top"),10)+(l.position.top-l.originalPosition.top))||null;if(!h.animate){this.element.css(c.extend(m,{top:k,left:i}))}l.helper.height(l.size.height);l.helper.width(l.size.width);if(this._helper&&!h.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",g);if(this._helper){this.helper.remove()}return false},_updateCache:function(d){var e=this.options;this.offset=this.helper.offset();if(a(d.left)){this.position.left=d.left}if(a(d.top)){this.position.top=d.top}if(a(d.height)){this.size.height=d.height}if(a(d.width)){this.size.width=d.width}},_updateRatio:function(g,f){var h=this.options,i=this.position,e=this.size,d=this.axis;if(g.height){g.width=(e.height*this.aspectRatio)}else{if(g.width){g.height=(e.width/this.aspectRatio)}}if(d=="sw"){g.left=i.left+(e.width-g.width);g.top=null}if(d=="nw"){g.top=i.top+(e.height-g.height);g.left=i.left+(e.width-g.width)}return g},_respectSize:function(k,f){var i=this.helper,h=this.options,q=this._aspectRatio||f.shiftKey,p=this.axis,s=a(k.width)&&h.maxWidth&&(h.maxWidth<k.width),l=a(k.height)&&h.maxHeight&&(h.maxHeight<k.height),g=a(k.width)&&h.minWidth&&(h.minWidth>k.width),r=a(k.height)&&h.minHeight&&(h.minHeight>k.height);if(g){k.width=h.minWidth}if(r){k.height=h.minHeight}if(s){k.width=h.maxWidth}if(l){k.height=h.maxHeight}var e=this.originalPosition.left+this.originalSize.width,n=this.position.top+this.size.height;var j=/sw|nw|w/.test(p),d=/nw|ne|n/.test(p);if(g&&j){k.left=e-h.minWidth}if(s&&j){k.left=e-h.maxWidth}if(r&&d){k.top=n-h.minHeight}if(l&&d){k.top=n-h.maxHeight}var m=!k.width&&!k.height;if(m&&!k.left&&k.top){k.top=null}else{if(m&&!k.top&&k.left){k.left=null}}return k},_proportionallyResize:function(){var j=this.options;if(!this._proportionallyResizeElements.length){return}var f=this.helper||this.element;for(var e=0;e<this._proportionallyResizeElements.length;e++){var g=this._proportionallyResizeElements[e];if(!this.borderDif){var d=[g.css("borderTopWidth"),g.css("borderRightWidth"),g.css("borderBottomWidth"),g.css("borderLeftWidth")],h=[g.css("paddingTop"),g.css("paddingRight"),g.css("paddingBottom"),g.css("paddingLeft")];this.borderDif=c.map(d,function(k,m){var l=parseInt(k,10)||0,n=parseInt(h[m],10)||0;return l+n})}if(c.browser.msie&&!(!(c(f).is(":hidden")||c(f).parents(":hidden").length))){continue}g.css({height:(f.height()-this.borderDif[0]-this.borderDif[2])||0,width:(f.width()-this.borderDif[1]-this.borderDif[3])||0})}},_renderProxy:function(){var e=this.element,h=this.options;this.elementOffset=e.offset();if(this._helper){this.helper=this.helper||c('<div style="overflow:hidden;"></div>');var d=c.browser.msie&&c.browser.version<7,f=(d?1:0),g=(d?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+g,height:this.element.outerHeight()+g,position:"absolute",left:this.elementOffset.left-f+"px",top:this.elementOffset.top-f+"px",zIndex:++h.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(f,e,d){return{width:this.originalSize.width+e}},w:function(g,e,d){var i=this.options,f=this.originalSize,h=this.originalPosition;return{left:h.left+e,width:f.width-e}},n:function(g,e,d){var i=this.options,f=this.originalSize,h=this.originalPosition;return{top:h.top+d,height:f.height-d}},s:function(f,e,d){return{height:this.originalSize.height+d}},se:function(f,e,d){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[f,e,d]))},sw:function(f,e,d){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[f,e,d]))},ne:function(f,e,d){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[f,e,d]))},nw:function(f,e,d){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[f,e,d]))}},_propagate:function(e,d){c.ui.plugin.call(this,e,[d,this.ui()]);(e!="resize"&&this._trigger(e,d,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}));c.extend(c.ui.resizable,{version:"1.7.2",eventPrefix:"resize",defaults:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,cancel:":input,option",containment:false,delay:0,distance:1,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000}});c.ui.plugin.add("resizable","alsoResize",{start:function(e,f){var d=c(this).data("resizable"),g=d.options;_store=function(h){c(h).each(function(){c(this).data("resizable-alsoresize",{width:parseInt(c(this).width(),10),height:parseInt(c(this).height(),10),left:parseInt(c(this).css("left"),10),top:parseInt(c(this).css("top"),10)})})};if(typeof(g.alsoResize)=="object"&&!g.alsoResize.parentNode){if(g.alsoResize.length){g.alsoResize=g.alsoResize[0];_store(g.alsoResize)}else{c.each(g.alsoResize,function(h,i){_store(h)})}}else{_store(g.alsoResize)}},resize:function(f,h){var e=c(this).data("resizable"),i=e.options,g=e.originalSize,k=e.originalPosition;var j={height:(e.size.height-g.height)||0,width:(e.size.width-g.width)||0,top:(e.position.top-k.top)||0,left:(e.position.left-k.left)||0},d=function(l,m){c(l).each(function(){var p=c(this),q=c(this).data("resizable-alsoresize"),o={},n=m&&m.length?m:["width","height","top","left"];c.each(n||["width","height","top","left"],function(r,t){var s=(q[t]||0)+(j[t]||0);if(s&&s>=0){o[t]=s||null}});if(/relative/.test(p.css("position"))&&c.browser.opera){e._revertToRelativePosition=true;p.css({position:"absolute",top:"auto",left:"auto"})}p.css(o)})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.nodeType){c.each(i.alsoResize,function(l,m){d(l,m)})}else{d(i.alsoResize)}},stop:function(e,f){var d=c(this).data("resizable");if(d._revertToRelativePosition&&c.browser.opera){d._revertToRelativePosition=false;el.css({position:"relative"})}c(this).removeData("resizable-alsoresize-start")}});c.ui.plugin.add("resizable","animate",{stop:function(h,m){var n=c(this).data("resizable"),i=n.options;var g=n._proportionallyResizeElements,d=g.length&&(/textarea/i).test(g[0].nodeName),e=d&&c.ui.hasScroll(g[0],"left")?0:n.sizeDiff.height,k=d?0:n.sizeDiff.width;var f={width:(n.size.width-k),height:(n.size.height-e)},j=(parseInt(n.element.css("left"),10)+(n.position.left-n.originalPosition.left))||null,l=(parseInt(n.element.css("top"),10)+(n.position.top-n.originalPosition.top))||null;n.element.animate(c.extend(f,l&&j?{top:l,left:j}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var o={width:parseInt(n.element.css("width"),10),height:parseInt(n.element.css("height"),10),top:parseInt(n.element.css("top"),10),left:parseInt(n.element.css("left"),10)};if(g&&g.length){c(g[0]).css({width:o.width,height:o.height})}n._updateCache(o);n._propagate("resize",h)}})}});c.ui.plugin.add("resizable","containment",{start:function(e,q){var s=c(this).data("resizable"),i=s.options,k=s.element;var f=i.containment,j=(f instanceof c)?f.get(0):(/parent/.test(f))?k.parent().get(0):f;if(!j){return}s.containerElement=c(j);if(/document/.test(f)||f==document){s.containerOffset={left:0,top:0};s.containerPosition={left:0,top:0};s.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var m=c(j),h=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){h[p]=b(m.css("padding"+o))});s.containerOffset=m.offset();s.containerPosition=m.position();s.containerSize={height:(m.innerHeight()-h[3]),width:(m.innerWidth()-h[1])};var n=s.containerOffset,d=s.containerSize.height,l=s.containerSize.width,g=(c.ui.hasScroll(j,"left")?j.scrollWidth:l),r=(c.ui.hasScroll(j)?j.scrollHeight:d);s.parentData={element:j,left:n.left,top:n.top,width:g,height:r}}},resize:function(f,p){var s=c(this).data("resizable"),h=s.options,e=s.containerSize,n=s.containerOffset,l=s.size,m=s.position,q=s._aspectRatio||f.shiftKey,d={top:0,left:0},g=s.containerElement;if(g[0]!=document&&(/static/).test(g.css("position"))){d=n}if(m.left<(s._helper?n.left:0)){s.size.width=s.size.width+(s._helper?(s.position.left-n.left):(s.position.left-d.left));if(q){s.size.height=s.size.width/h.aspectRatio}s.position.left=h.helper?n.left:0}if(m.top<(s._helper?n.top:0)){s.size.height=s.size.height+(s._helper?(s.position.top-n.top):s.position.top);if(q){s.size.width=s.size.height*h.aspectRatio}s.position.top=s._helper?n.top:0}s.offset.left=s.parentData.left+s.position.left;s.offset.top=s.parentData.top+s.position.top;var k=Math.abs((s._helper?s.offset.left-d.left:(s.offset.left-d.left))+s.sizeDiff.width),r=Math.abs((s._helper?s.offset.top-d.top:(s.offset.top-n.top))+s.sizeDiff.height);var j=s.containerElement.get(0)==s.element.parent().get(0),i=/relative|absolute/.test(s.containerElement.css("position"));if(j&&i){k-=s.parentData.left}if(k+s.size.width>=s.parentData.width){s.size.width=s.parentData.width-k;if(q){s.size.height=s.size.width/s.aspectRatio}}if(r+s.size.height>=s.parentData.height){s.size.height=s.parentData.height-r;if(q){s.size.width=s.size.height*s.aspectRatio}}},stop:function(e,m){var p=c(this).data("resizable"),f=p.options,k=p.position,l=p.containerOffset,d=p.containerPosition,g=p.containerElement;var i=c(p.helper),q=i.offset(),n=i.outerWidth()-p.sizeDiff.width,j=i.outerHeight()-p.sizeDiff.height;if(p._helper&&!f.animate&&(/relative/).test(g.css("position"))){c(this).css({left:q.left-d.left-l.left,width:n,height:j})}if(p._helper&&!f.animate&&(/static/).test(g.css("position"))){c(this).css({left:q.left-d.left-l.left,width:n,height:j})}}});c.ui.plugin.add("resizable","ghost",{start:function(f,g){var d=c(this).data("resizable"),h=d.options,e=d.size;d.ghost=d.originalElement.clone();d.ghost.css({opacity:0.25,display:"block",position:"relative",height:e.height,width:e.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof h.ghost=="string"?h.ghost:"");d.ghost.appendTo(d.helper)},resize:function(e,f){var d=c(this).data("resizable"),g=d.options;if(d.ghost){d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})}},stop:function(e,f){var d=c(this).data("resizable"),g=d.options;if(d.ghost&&d.helper){d.helper.get(0).removeChild(d.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(d,l){var n=c(this).data("resizable"),g=n.options,j=n.size,h=n.originalSize,i=n.originalPosition,m=n.axis,k=g._aspectRatio||d.shiftKey;g.grid=typeof g.grid=="number"?[g.grid,g.grid]:g.grid;var f=Math.round((j.width-h.width)/(g.grid[0]||1))*(g.grid[0]||1),e=Math.round((j.height-h.height)/(g.grid[1]||1))*(g.grid[1]||1);if(/^(se|s|e)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e}else{if(/^(ne)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e;n.position.top=i.top-e}else{if(/^(sw)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e;n.position.left=i.left-f}else{n.size.width=h.width+f;n.size.height=h.height+e;n.position.top=i.top-e;n.position.left=i.left-f}}}}});var b=function(d){return parseInt(d,10)||0};var a=function(d){return !isNaN(parseInt(d,10))}})(jQuery);;/*
+ * jQuery UI Selectable 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Selectables
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(a){a.widget("ui.selectable",a.extend({},a.ui.mouse,{_init:function(){var b=this;this.element.addClass("ui-selectable");this.dragged=false;var c;this.refresh=function(){c=a(b.options.filter,b.element[0]);c.each(function(){var d=a(this);var e=d.offset();a.data(this,"selectable-item",{element:this,$element:d,left:e.left,top:e.top,right:e.left+d.outerWidth(),bottom:e.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"),selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=c.addClass("ui-selectee");this._mouseInit();this.helper=a(document.createElement("div")).css({border:"1px dotted black"}).addClass("ui-selectable-helper")},destroy:function(){this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy()},_mouseStart:function(d){var b=this;this.opos=[d.pageX,d.pageY];if(this.options.disabled){return}var c=this.options;this.selectees=a(c.filter,this.element[0]);this._trigger("start",d);a(c.appendTo).append(this.helper);this.helper.css({"z-index":100,position:"absolute",left:d.clientX,top:d.clientY,width:0,height:0});if(c.autoRefresh){this.refresh()}this.selectees.filter(".ui-selected").each(function(){var e=a.data(this,"selectable-item");e.startselected=true;if(!d.metaKey){e.$element.removeClass("ui-selected");e.selected=false;e.$element.addClass("ui-unselecting");e.unselecting=true;b._trigger("unselecting",d,{unselecting:e.element})}});a(d.target).parents().andSelf().each(function(){var e=a.data(this,"selectable-item");if(e){e.$element.removeClass("ui-unselecting").addClass("ui-selecting");e.unselecting=false;e.selecting=true;e.selected=true;b._trigger("selecting",d,{selecting:e.element});return false}})},_mouseDrag:function(i){var c=this;this.dragged=true;if(this.options.disabled){return}var e=this.options;var d=this.opos[0],h=this.opos[1],b=i.pageX,g=i.pageY;if(d>b){var f=b;b=d;d=f}if(h>g){var f=g;g=h;h=f}this.helper.css({left:d,top:h,width:b-d,height:g-h});this.selectees.each(function(){var j=a.data(this,"selectable-item");if(!j||j.element==c.element[0]){return}var k=false;if(e.tolerance=="touch"){k=(!(j.left>b||j.right<d||j.top>g||j.bottom<h))}else{if(e.tolerance=="fit"){k=(j.left>d&&j.right<b&&j.top>h&&j.bottom<g)}}if(k){if(j.selected){j.$element.removeClass("ui-selected");j.selected=false}if(j.unselecting){j.$element.removeClass("ui-unselecting");j.unselecting=false}if(!j.selecting){j.$element.addClass("ui-selecting");j.selecting=true;c._trigger("selecting",i,{selecting:j.element})}}else{if(j.selecting){if(i.metaKey&&j.startselected){j.$element.removeClass("ui-selecting");j.selecting=false;j.$element.addClass("ui-selected");j.selected=true}else{j.$element.removeClass("ui-selecting");j.selecting=false;if(j.startselected){j.$element.addClass("ui-unselecting");j.unselecting=true}c._trigger("unselecting",i,{unselecting:j.element})}}if(j.selected){if(!i.metaKey&&!j.startselected){j.$element.removeClass("ui-selected");j.selected=false;j.$element.addClass("ui-unselecting");j.unselecting=true;c._trigger("unselecting",i,{unselecting:j.element})}}}});return false},_mouseStop:function(d){var b=this;this.dragged=false;var c=this.options;a(".ui-unselecting",this.element[0]).each(function(){var e=a.data(this,"selectable-item");e.$element.removeClass("ui-unselecting");e.unselecting=false;e.startselected=false;b._trigger("unselected",d,{unselected:e.element})});a(".ui-selecting",this.element[0]).each(function(){var e=a.data(this,"selectable-item");e.$element.removeClass("ui-selecting").addClass("ui-selected");e.selecting=false;e.selected=true;e.startselected=true;b._trigger("selected",d,{selected:e.element})});this._trigger("stop",d);this.helper.remove();return false}}));a.extend(a.ui.selectable,{version:"1.7.2",defaults:{appendTo:"body",autoRefresh:true,cancel:":input,option",delay:0,distance:0,filter:"*",tolerance:"touch"}})})(jQuery);;/*
+ * jQuery UI Sortable 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Sortables
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(a){a.widget("ui.sortable",a.extend({},a.ui.mouse,{_init:function(){var b=this.options;this.containerCache={};this.element.addClass("ui-sortable");this.refresh();this.floating=this.items.length?(/left|right/).test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--){this.items[b].item.removeData("sortable-item")}},_mouseCapture:function(e,f){if(this.reverting){return false}if(this.options.disabled||this.options.type=="static"){return false}this._refreshItems(e);var d=null,c=this,b=a(e.target).parents().each(function(){if(a.data(this,"sortable-item")==c){d=a(this);return false}});if(a.data(e.target,"sortable-item")==c){d=a(e.target)}if(!d){return false}if(this.options.handle&&!f){var g=false;a(this.options.handle,d).find("*").andSelf().each(function(){if(this==e.target){g=true}});if(!g){return false}}this.currentItem=d;this._removeCurrentsFromItems();return true},_mouseStart:function(e,f,b){var g=this.options,c=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(e);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");a.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(e);this.originalPageX=e.pageX;this.originalPageY=e.pageY;if(g.cursorAt){this._adjustOffsetFromHelper(g.cursorAt)}this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};if(this.helper[0]!=this.currentItem[0]){this.currentItem.hide()}this._createPlaceholder();if(g.containment){this._setContainment()}if(g.cursor){if(a("body").css("cursor")){this._storedCursor=a("body").css("cursor")}a("body").css("cursor",g.cursor)}if(g.opacity){if(this.helper.css("opacity")){this._storedOpacity=this.helper.css("opacity")}this.helper.css("opacity",g.opacity)}if(g.zIndex){if(this.helper.css("zIndex")){this._storedZIndex=this.helper.css("zIndex")}this.helper.css("zIndex",g.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){this.overflowOffset=this.scrollParent.offset()}this._trigger("start",e,this._uiHash());if(!this._preserveHelperProportions){this._cacheHelperProportions()}if(!b){for(var d=this.containers.length-1;d>=0;d--){this.containers[d]._trigger("activate",e,c._uiHash(this))}}if(a.ui.ddmanager){a.ui.ddmanager.current=this}if(a.ui.ddmanager&&!g.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,e)}this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(e);return true},_mouseDrag:function(f){this.position=this._generatePosition(f);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs){this.lastPositionAbs=this.positionAbs}if(this.options.scroll){var g=this.options,b=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if((this.overflowOffset.top+this.scrollParent[0].offsetHeight)-f.pageY<g.scrollSensitivity){this.scrollParent[0].scrollTop=b=this.scrollParent[0].scrollTop+g.scrollSpeed}else{if(f.pageY-this.overflowOffset.top<g.scrollSensitivity){this.scrollParent[0].scrollTop=b=this.scrollParent[0].scrollTop-g.scrollSpeed}}if((this.overflowOffset.left+this.scrollParent[0].offsetWidth)-f.pageX<g.scrollSensitivity){this.scrollParent[0].scrollLeft=b=this.scrollParent[0].scrollLeft+g.scrollSpeed}else{if(f.pageX-this.overflowOffset.left<g.scrollSensitivity){this.scrollParent[0].scrollLeft=b=this.scrollParent[0].scrollLeft-g.scrollSpeed}}}else{if(f.pageY-a(document).scrollTop()<g.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()-g.scrollSpeed)}else{if(a(window).height()-(f.pageY-a(document).scrollTop())<g.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()+g.scrollSpeed)}}if(f.pageX-a(document).scrollLeft()<g.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()-g.scrollSpeed)}else{if(a(window).width()-(f.pageX-a(document).scrollLeft())<g.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()+g.scrollSpeed)}}}if(b!==false&&a.ui.ddmanager&&!g.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,f)}}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y"){this.helper[0].style.left=this.position.left+"px"}if(!this.options.axis||this.options.axis!="x"){this.helper[0].style.top=this.position.top+"px"}for(var d=this.items.length-1;d>=0;d--){var e=this.items[d],c=e.item[0],h=this._intersectsWithPointer(e);if(!h){continue}if(c!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=c&&!a.ui.contains(this.placeholder[0],c)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],c):true)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(e)){this._rearrange(f,e)}else{break}this._trigger("change",f,this._uiHash());break}}this._contactContainers(f);if(a.ui.ddmanager){a.ui.ddmanager.drag(this,f)}this._trigger("sort",f,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(c,d){if(!c){return}if(a.ui.ddmanager&&!this.options.dropBehaviour){a.ui.ddmanager.drop(this,c)}if(this.options.revert){var b=this;var e=b.placeholder.offset();b.reverting=true;a(this.helper).animate({left:e.left-this.offset.parent.left-b.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-b.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){b._clear(c)})}else{this._clear(c,d)}return false},cancel:function(){var b=this;if(this.dragging){this._mouseUp();if(this.options.helper=="original"){this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else{this.currentItem.show()}for(var c=this.containers.length-1;c>=0;c--){this.containers[c]._trigger("deactivate",null,b._uiHash(this));if(this.containers[c].containerCache.over){this.containers[c]._trigger("out",null,b._uiHash(this));this.containers[c].containerCache.over=0}}}if(this.placeholder[0].parentNode){this.placeholder[0].parentNode.removeChild(this.placeholder[0])}if(this.options.helper!="original"&&this.helper&&this.helper[0].parentNode){this.helper.remove()}a.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});if(this.domPosition.prev){a(this.domPosition.prev).after(this.currentItem)}else{a(this.domPosition.parent).prepend(this.currentItem)}return true},serialize:function(d){var b=this._getItemsAsjQuery(d&&d.connected);var c=[];d=d||{};a(b).each(function(){var e=(a(d.item||this).attr(d.attribute||"id")||"").match(d.expression||(/(.+)[-=_](.+)/));if(e){c.push((d.key||e[1]+"[]")+"="+(d.key&&d.expression?e[1]:e[2]))}});return c.join("&")},toArray:function(d){var b=this._getItemsAsjQuery(d&&d.connected);var c=[];d=d||{};b.each(function(){c.push(a(d.item||this).attr(d.attribute||"id")||"")});return c},_intersectsWith:function(m){var e=this.positionAbs.left,d=e+this.helperProportions.width,k=this.positionAbs.top,j=k+this.helperProportions.height;var f=m.left,c=f+m.width,n=m.top,i=n+m.height;var o=this.offset.click.top,h=this.offset.click.left;var g=(k+o)>n&&(k+o)<i&&(e+h)>f&&(e+h)<c;if(this.options.tolerance=="pointer"||this.options.forcePointerForContainers||(this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>m[this.floating?"width":"height"])){return g}else{return(f<e+(this.helperProportions.width/2)&&d-(this.helperProportions.width/2)<c&&n<k+(this.helperProportions.height/2)&&j-(this.helperProportions.height/2)<i)}},_intersectsWithPointer:function(d){var e=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,d.top,d.height),c=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,d.left,d.width),g=e&&c,b=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();if(!g){return false}return this.floating?(((f&&f=="right")||b=="down")?2:1):(b&&(b=="down"?2:1))},_intersectsWithSides:function(e){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,e.top+(e.height/2),e.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,e.left+(e.width/2),e.width),b=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();if(this.floating&&f){return((f=="right"&&d)||(f=="left"&&!d))}else{return b&&((b=="down"&&c)||(b=="up"&&!c))}},_getDragVerticalDirection:function(){var b=this.positionAbs.top-this.lastPositionAbs.top;return b!=0&&(b>0?"down":"up")},_getDragHorizontalDirection:function(){var b=this.positionAbs.left-this.lastPositionAbs.left;return b!=0&&(b>0?"right":"left")},refresh:function(b){this._refreshItems(b);this.refreshPositions()},_connectWith:function(){var b=this.options;return b.connectWith.constructor==String?[b.connectWith]:b.connectWith},_getItemsAsjQuery:function(b){var l=this;var g=[];var e=[];var h=this._connectWith();if(h&&b){for(var d=h.length-1;d>=0;d--){var k=a(h[d]);for(var c=k.length-1;c>=0;c--){var f=a.data(k[c],"sortable");if(f&&f!=this&&!f.options.disabled){e.push([a.isFunction(f.options.items)?f.options.items.call(f.element):a(f.options.items,f.element).not(".ui-sortable-helper"),f])}}}}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper"),this]);for(var d=e.length-1;d>=0;d--){e[d][0].each(function(){g.push(this)})}return a(g)},_removeCurrentsFromItems:function(){var d=this.currentItem.find(":data(sortable-item)");for(var c=0;c<this.items.length;c++){for(var b=0;b<d.length;b++){if(d[b]==this.items[c].item[0]){this.items.splice(c,1)}}}},_refreshItems:function(b){this.items=[];this.containers=[this];var h=this.items;var p=this;var f=[[a.isFunction(this.options.items)?this.options.items.call(this.element[0],b,{item:this.currentItem}):a(this.options.items,this.element),this]];var l=this._connectWith();if(l){for(var e=l.length-1;e>=0;e--){var m=a(l[e]);for(var d=m.length-1;d>=0;d--){var g=a.data(m[d],"sortable");if(g&&g!=this&&!g.options.disabled){f.push([a.isFunction(g.options.items)?g.options.items.call(g.element[0],b,{item:this.currentItem}):a(g.options.items,g.element),g]);this.containers.push(g)}}}}for(var e=f.length-1;e>=0;e--){var k=f[e][1];var c=f[e][0];for(var d=0,n=c.length;d<n;d++){var o=a(c[d]);o.data("sortable-item",k);h.push({item:o,instance:k,width:0,height:0,left:0,top:0})}}},refreshPositions:function(b){if(this.offsetParent&&this.helper){this.offset.parent=this._getParentOffset()}for(var d=this.items.length-1;d>=0;d--){var e=this.items[d];if(e.instance!=this.currentContainer&&this.currentContainer&&e.item[0]!=this.currentItem[0]){continue}var c=this.options.toleranceElement?a(this.options.toleranceElement,e.item):e.item;if(!b){e.width=c.outerWidth();e.height=c.outerHeight()}var f=c.offset();e.left=f.left;e.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers){this.options.custom.refreshContainers.call(this)}else{for(var d=this.containers.length-1;d>=0;d--){var f=this.containers[d].element.offset();this.containers[d].containerCache.left=f.left;this.containers[d].containerCache.top=f.top;this.containers[d].containerCache.width=this.containers[d].element.outerWidth();this.containers[d].containerCache.height=this.containers[d].element.outerHeight()}}},_createPlaceholder:function(d){var b=d||this,e=b.options;if(!e.placeholder||e.placeholder.constructor==String){var c=e.placeholder;e.placeholder={element:function(){var f=a(document.createElement(b.currentItem[0].nodeName)).addClass(c||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!c){f.style.visibility="hidden"}return f},update:function(f,g){if(c&&!e.forcePlaceholderSize){return}if(!g.height()){g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10))}if(!g.width()){g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=a(e.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);e.placeholder.update(b,b.placeholder)},_contactContainers:function(d){for(var c=this.containers.length-1;c>=0;c--){if(this._intersectsWith(this.containers[c].containerCache)){if(!this.containers[c].containerCache.over){if(this.currentContainer!=this.containers[c]){var h=10000;var g=null;var e=this.positionAbs[this.containers[c].floating?"left":"top"];for(var b=this.items.length-1;b>=0;b--){if(!a.ui.contains(this.containers[c].element[0],this.items[b].item[0])){continue}var f=this.items[b][this.containers[c].floating?"left":"top"];if(Math.abs(f-e)<h){h=Math.abs(f-e);g=this.items[b]}}if(!g&&!this.options.dropOnEmpty){continue}this.currentContainer=this.containers[c];g?this._rearrange(d,g,null,true):this._rearrange(d,null,this.containers[c].element,true);this._trigger("change",d,this._uiHash());this.containers[c]._trigger("change",d,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder)}this.containers[c]._trigger("over",d,this._uiHash(this));this.containers[c].containerCache.over=1}}else{if(this.containers[c].containerCache.over){this.containers[c]._trigger("out",d,this._uiHash(this));this.containers[c].containerCache.over=0}}}},_createHelper:function(c){var d=this.options;var b=a.isFunction(d.helper)?a(d.helper.apply(this.element[0],[c,this.currentItem])):(d.helper=="clone"?this.currentItem.clone():this.currentItem);if(!b.parents("body").length){a(d.appendTo!="parent"?d.appendTo:this.currentItem[0].parentNode)[0].appendChild(b[0])}if(b[0]==this.currentItem[0]){this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}}if(b[0].style.width==""||d.forceHelperSize){b.width(this.currentItem.width())}if(b[0].style.height==""||d.forceHelperSize){b.height(this.currentItem.height())}return b},_adjustOffsetFromHelper:function(b){if(b.left!=undefined){this.offset.click.left=b.left+this.margins.left}if(b.right!=undefined){this.offset.click.left=this.helperProportions.width-b.right+this.margins.left}if(b.top!=undefined){this.offset.click.top=b.top+this.margins.top}if(b.bottom!=undefined){this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top}},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])){b.left+=this.scrollParent.scrollLeft();b.top+=this.scrollParent.scrollTop()}if((this.offsetParent[0]==document.body)||(this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)){b={top:0,left:0}}return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var b=this.currentItem.position();return{top:b.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:b.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else{return{top:0,left:0}}},_cacheMargins:function(){this.margins={left:(parseInt(this.currentItem.css("marginLeft"),10)||0),top:(parseInt(this.currentItem.css("marginTop"),10)||0)}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e=this.options;if(e.containment=="parent"){e.containment=this.helper[0].parentNode}if(e.containment=="document"||e.containment=="window"){this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(e.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(e.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]}if(!(/^(document|window|parent)$/).test(e.containment)){var c=a(e.containment)[0];var d=a(e.containment).offset();var b=(a(c).css("overflow")!="hidden");this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(b?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(b?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(f,h){if(!h){h=this.position}var c=f=="absolute"?1:-1;var e=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=(/(html|body)/i).test(b[0].tagName);return{top:(h.top+this.offset.relative.top*c+this.offset.parent.top*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(g?0:b.scrollTop()))*c)),left:(h.left+this.offset.relative.left*c+this.offset.parent.left*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:b.scrollLeft())*c))}},_generatePosition:function(e){var h=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,i=(/(html|body)/i).test(b[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0])){this.offset.relative=this._getRelativeOffset()}var d=e.pageX;var c=e.pageY;if(this.originalPosition){if(this.containment){if(e.pageX-this.offset.click.left<this.containment[0]){d=this.containment[0]+this.offset.click.left}if(e.pageY-this.offset.click.top<this.containment[1]){c=this.containment[1]+this.offset.click.top}if(e.pageX-this.offset.click.left>this.containment[2]){d=this.containment[2]+this.offset.click.left}if(e.pageY-this.offset.click.top>this.containment[3]){c=this.containment[3]+this.offset.click.top}}if(h.grid){var g=this.originalPageY+Math.round((c-this.originalPageY)/h.grid[1])*h.grid[1];c=this.containment?(!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:(!(g-this.offset.click.top<this.containment[1])?g-h.grid[1]:g+h.grid[1])):g;var f=this.originalPageX+Math.round((d-this.originalPageX)/h.grid[0])*h.grid[0];d=this.containment?(!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:(!(f-this.offset.click.left<this.containment[0])?f-h.grid[0]:f+h.grid[0])):f}}return{top:(c-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(i?0:b.scrollTop())))),left:(d-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:b.scrollLeft())))}},_rearrange:function(g,f,c,e){c?c[0].appendChild(this.placeholder[0]):f.item[0].parentNode.insertBefore(this.placeholder[0],(this.direction=="down"?f.item[0]:f.item[0].nextSibling));this.counter=this.counter?++this.counter:1;var d=this,b=this.counter;window.setTimeout(function(){if(b==d.counter){d.refreshPositions(!e)}},0)},_clear:function(d,e){this.reverting=false;var f=[],b=this;if(!this._noFinalSort&&this.currentItem[0].parentNode){this.placeholder.before(this.currentItem)}this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var c in this._storedCSS){if(this._storedCSS[c]=="auto"||this._storedCSS[c]=="static"){this._storedCSS[c]=""}}this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else{this.currentItem.show()}if(this.fromOutside&&!e){f.push(function(g){this._trigger("receive",g,this._uiHash(this.fromOutside))})}if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!e){f.push(function(g){this._trigger("update",g,this._uiHash())})}if(!a.ui.contains(this.element[0],this.currentItem[0])){if(!e){f.push(function(g){this._trigger("remove",g,this._uiHash())})}for(var c=this.containers.length-1;c>=0;c--){if(a.ui.contains(this.containers[c].element[0],this.currentItem[0])&&!e){f.push((function(g){return function(h){g._trigger("receive",h,this._uiHash(this))}}).call(this,this.containers[c]));f.push((function(g){return function(h){g._trigger("update",h,this._uiHash(this))}}).call(this,this.containers[c]))}}}for(var c=this.containers.length-1;c>=0;c--){if(!e){f.push((function(g){return function(h){g._trigger("deactivate",h,this._uiHash(this))}}).call(this,this.containers[c]))}if(this.containers[c].containerCache.over){f.push((function(g){return function(h){g._trigger("out",h,this._uiHash(this))}}).call(this,this.containers[c]));this.containers[c].containerCache.over=0}}if(this._storedCursor){a("body").css("cursor",this._storedCursor)}if(this._storedOpacity){this.helper.css("opacity",this._storedOpacity)}if(this._storedZIndex){this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex)}this.dragging=false;if(this.cancelHelperRemoval){if(!e){this._trigger("beforeStop",d,this._uiHash());for(var c=0;c<f.length;c++){f[c].call(this,d)}this._trigger("stop",d,this._uiHash())}return false}if(!e){this._trigger("beforeStop",d,this._uiHash())}this.placeholder[0].parentNode.removeChild(this.placeholder[0]);if(this.helper[0]!=this.currentItem[0]){this.helper.remove()}this.helper=null;if(!e){for(var c=0;c<f.length;c++){f[c].call(this,d)}this._trigger("stop",d,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){if(a.widget.prototype._trigger.apply(this,arguments)===false){this.cancel()}},_uiHash:function(c){var b=c||this;return{helper:b.helper,placeholder:b.placeholder||a([]),position:b.position,absolutePosition:b.positionAbs,offset:b.positionAbs,item:b.currentItem,sender:c?c.element:null}}}));a.extend(a.ui.sortable,{getter:"serialize toArray",version:"1.7.2",eventPrefix:"sort",defaults:{appendTo:"parent",axis:false,cancel:":input,option",connectWith:false,containment:false,cursor:"auto",cursorAt:false,delay:0,distance:1,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1000}})})(jQuery);;/*
+ * jQuery UI Accordion 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Accordion
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(a){a.widget("ui.accordion",{_init:function(){var d=this.options,b=this;this.running=0;if(d.collapsible==a.ui.accordion.defaults.collapsible&&d.alwaysOpen!=a.ui.accordion.defaults.alwaysOpen){d.collapsible=!d.alwaysOpen}if(d.navigation){var c=this.element.find("a").filter(d.navigationFilter);if(c.length){if(c.filter(d.header).length){this.active=c}else{this.active=c.parent().parent().prev();c.addClass("ui-accordion-content-active")}}}this.element.addClass("ui-accordion ui-widget ui-helper-reset");if(this.element[0].nodeName=="UL"){this.element.children("li").addClass("ui-accordion-li-fix")}this.headers=this.element.find(d.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){a(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){a(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){a(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){a(this).removeClass("ui-state-focus")});this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");this.active=this._findActive(this.active||d.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");this.active.next().addClass("ui-accordion-content-active");a("<span/>").addClass("ui-icon "+d.icons.header).prependTo(this.headers);this.active.find(".ui-icon").toggleClass(d.icons.header).toggleClass(d.icons.headerSelected);if(a.browser.msie){this.element.find("a").css("zoom","1")}this.resize();this.element.attr("role","tablist");this.headers.attr("role","tab").bind("keydown",function(e){return b._keydown(e)}).next().attr("role","tabpanel");this.headers.not(this.active||"").attr("aria-expanded","false").attr("tabIndex","-1").next().hide();if(!this.active.length){this.headers.eq(0).attr("tabIndex","0")}else{this.active.attr("aria-expanded","true").attr("tabIndex","0")}if(!a.browser.safari){this.headers.find("a").attr("tabIndex","-1")}if(d.event){this.headers.bind((d.event)+".accordion",function(e){return b._clickHandler.call(b,e,this)})}},destroy:function(){var c=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role").unbind(".accordion").removeData("accordion");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");this.headers.find("a").removeAttr("tabindex");this.headers.children(".ui-icon").remove();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");if(c.autoHeight||c.fillHeight){b.css("height","")}},_setData:function(b,c){if(b=="alwaysOpen"){b="collapsible";c=!c}a.widget.prototype._setData.apply(this,arguments)},_keydown:function(e){var g=this.options,f=a.ui.keyCode;if(g.disabled||e.altKey||e.ctrlKey){return}var d=this.headers.length;var b=this.headers.index(e.target);var c=false;switch(e.keyCode){case f.RIGHT:case f.DOWN:c=this.headers[(b+1)%d];break;case f.LEFT:case f.UP:c=this.headers[(b-1+d)%d];break;case f.SPACE:case f.ENTER:return this._clickHandler({target:e.target},e.target)}if(c){a(e.target).attr("tabIndex","-1");a(c).attr("tabIndex","0");c.focus();return false}return true},resize:function(){var e=this.options,d;if(e.fillSpace){if(a.browser.msie){var b=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}d=this.element.parent().height();if(a.browser.msie){this.element.parent().css("overflow",b)}this.headers.each(function(){d-=a(this).outerHeight()});var c=0;this.headers.next().each(function(){c=Math.max(c,a(this).innerHeight()-a(this).height())}).height(Math.max(0,d-c)).css("overflow","auto")}else{if(e.autoHeight){d=0;this.headers.next().each(function(){d=Math.max(d,a(this).outerHeight())}).height(d)}}},activate:function(b){var c=this._findActive(b)[0];this._clickHandler({target:c},c)},_findActive:function(b){return b?typeof b=="number"?this.headers.filter(":eq("+b+")"):this.headers.not(this.headers.not(b)):b===false?a([]):this.headers.filter(":eq(0)")},_clickHandler:function(b,f){var d=this.options;if(d.disabled){return false}if(!b.target&&d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");var h=this.active.next(),e={options:d,newHeader:a([]),oldHeader:d.active,newContent:a([]),oldContent:h},c=(this.active=a([]));this._toggle(c,h,e);return false}var g=a(b.currentTarget||f);var i=g[0]==this.active[0];if(this.running||(!d.collapsible&&i)){return false}this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");if(!i){g.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").find(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);g.next().addClass("ui-accordion-content-active")}var c=g.next(),h=this.active.next(),e={options:d,newHeader:i&&d.collapsible?a([]):g,oldHeader:this.active,newContent:i&&d.collapsible?a([]):c.find("> *"),oldContent:h.find("> *")},j=this.headers.index(this.active[0])>this.headers.index(g[0]);this.active=i?a([]):g;this._toggle(c,h,e,i,j);return false},_toggle:function(b,i,g,j,k){var d=this.options,m=this;this.toShow=b;this.toHide=i;this.data=g;var c=function(){if(!m){return}return m._completed.apply(m,arguments)};this._trigger("changestart",null,this.data);this.running=i.size()===0?b.size():i.size();if(d.animated){var f={};if(d.collapsible&&j){f={toShow:a([]),toHide:i,complete:c,down:k,autoHeight:d.autoHeight||d.fillSpace}}else{f={toShow:b,toHide:i,complete:c,down:k,autoHeight:d.autoHeight||d.fillSpace}}if(!d.proxied){d.proxied=d.animated}if(!d.proxiedDuration){d.proxiedDuration=d.duration}d.animated=a.isFunction(d.proxied)?d.proxied(f):d.proxied;d.duration=a.isFunction(d.proxiedDuration)?d.proxiedDuration(f):d.proxiedDuration;var l=a.ui.accordion.animations,e=d.duration,h=d.animated;if(!l[h]){l[h]=function(n){this.slide(n,{easing:h,duration:e||700})}}l[h](f)}else{if(d.collapsible&&j){b.toggle()}else{i.hide();b.show()}c(true)}i.prev().attr("aria-expanded","false").attr("tabIndex","-1").blur();b.prev().attr("aria-expanded","true").attr("tabIndex","0").focus()},_completed:function(b){var c=this.options;this.running=b?0:--this.running;if(this.running){return}if(c.clearStyle){this.toShow.add(this.toHide).css({height:"",overflow:""})}this._trigger("change",null,this.data)}});a.extend(a.ui.accordion,{version:"1.7.2",defaults:{active:null,alwaysOpen:true,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()==location.href.toLowerCase()}},animations:{slide:function(j,h){j=a.extend({easing:"swing",duration:300},j,h);if(!j.toHide.size()){j.toShow.animate({height:"show"},j);return}if(!j.toShow.size()){j.toHide.animate({height:"hide"},j);return}var c=j.toShow.css("overflow"),g,d={},f={},e=["height","paddingTop","paddingBottom"],b;var i=j.toShow;b=i[0].style.width;i.width(parseInt(i.parent().width(),10)-parseInt(i.css("paddingLeft"),10)-parseInt(i.css("paddingRight"),10)-(parseInt(i.css("borderLeftWidth"),10)||0)-(parseInt(i.css("borderRightWidth"),10)||0));a.each(e,function(k,m){f[m]="hide";var l=(""+a.css(j.toShow[0],m)).match(/^([\d+-.]+)(.*)$/);d[m]={value:l[1],unit:l[2]||"px"}});j.toShow.css({height:0,overflow:"hidden"}).show();j.toHide.filter(":hidden").each(j.complete).end().filter(":visible").animate(f,{step:function(k,l){if(l.prop=="height"){g=(l.now-l.start)/(l.end-l.start)}j.toShow[0].style[l.prop]=(g*d[l.prop].value)+d[l.prop].unit},duration:j.duration,easing:j.easing,complete:function(){if(!j.autoHeight){j.toShow.css("height","")}j.toShow.css("width",b);j.toShow.css({overflow:c});j.complete()}})},bounceslide:function(b){this.slide(b,{easing:b.down?"easeOutBounce":"swing",duration:b.down?1000:200})},easeslide:function(b){this.slide(b,{easing:"easeinout",duration:700})}}})})(jQuery);;/*
+ * jQuery UI Dialog 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Dialog
+ *
+ * Depends:
+ *	ui.core.js
+ *	ui.draggable.js
+ *	ui.resizable.js
+ */
+(function(c){var b={dragStart:"start.draggable",drag:"drag.draggable",dragStop:"stop.draggable",maxHeight:"maxHeight.resizable",minHeight:"minHeight.resizable",maxWidth:"maxWidth.resizable",minWidth:"minWidth.resizable",resizeStart:"start.resizable",resize:"drag.resizable",resizeStop:"stop.resizable"},a="ui-dialog ui-widget ui-widget-content ui-corner-all ";c.widget("ui.dialog",{_init:function(){this.originalTitle=this.element.attr("title");var l=this,m=this.options,j=m.title||this.originalTitle||"&nbsp;",e=c.ui.dialog.getTitleId(this.element),k=(this.uiDialog=c("<div/>")).appendTo(document.body).hide().addClass(a+m.dialogClass).css({position:"absolute",overflow:"hidden",zIndex:m.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(n){(m.closeOnEscape&&n.keyCode&&n.keyCode==c.ui.keyCode.ESCAPE&&l.close(n))}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(n){l.moveToTop(false,n)}),g=this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(k),f=(this.uiDialogTitlebar=c("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(k),i=c('<a href="#"/>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){i.addClass("ui-state-hover")},function(){i.removeClass("ui-state-hover")}).focus(function(){i.addClass("ui-state-focus")}).blur(function(){i.removeClass("ui-state-focus")}).mousedown(function(n){n.stopPropagation()}).click(function(n){l.close(n);return false}).appendTo(f),h=(this.uiDialogTitlebarCloseText=c("<span/>")).addClass("ui-icon ui-icon-closethick").text(m.closeText).appendTo(i),d=c("<span/>").addClass("ui-dialog-title").attr("id",e).html(j).prependTo(f);f.find("*").add(f).disableSelection();(m.draggable&&c.fn.draggable&&this._makeDraggable());(m.resizable&&c.fn.resizable&&this._makeResizable());this._createButtons(m.buttons);this._isOpen=false;(m.bgiframe&&c.fn.bgiframe&&k.bgiframe());(m.autoOpen&&this.open())},destroy:function(){(this.overlay&&this.overlay.destroy());this.uiDialog.hide();this.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");this.uiDialog.remove();(this.originalTitle&&this.element.attr("title",this.originalTitle))},close:function(f){var d=this;if(false===d._trigger("beforeclose",f)){return}(d.overlay&&d.overlay.destroy());d.uiDialog.unbind("keypress.ui-dialog");(d.options.hide?d.uiDialog.hide(d.options.hide,function(){d._trigger("close",f)}):d.uiDialog.hide()&&d._trigger("close",f));c.ui.dialog.overlay.resize();d._isOpen=false;if(d.options.modal){var e=0;c(".ui-dialog").each(function(){if(this!=d.uiDialog[0]){e=Math.max(e,c(this).css("z-index"))}});c.ui.dialog.maxZ=e}},isOpen:function(){return this._isOpen},moveToTop:function(f,e){if((this.options.modal&&!f)||(!this.options.stack&&!this.options.modal)){return this._trigger("focus",e)}if(this.options.zIndex>c.ui.dialog.maxZ){c.ui.dialog.maxZ=this.options.zIndex}(this.overlay&&this.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=++c.ui.dialog.maxZ));var d={scrollTop:this.element.attr("scrollTop"),scrollLeft:this.element.attr("scrollLeft")};this.uiDialog.css("z-index",++c.ui.dialog.maxZ);this.element.attr(d);this._trigger("focus",e)},open:function(){if(this._isOpen){return}var e=this.options,d=this.uiDialog;this.overlay=e.modal?new c.ui.dialog.overlay(this):null;(d.next().length&&d.appendTo("body"));this._size();this._position(e.position);d.show(e.show);this.moveToTop(true);(e.modal&&d.bind("keypress.ui-dialog",function(h){if(h.keyCode!=c.ui.keyCode.TAB){return}var g=c(":tabbable",this),i=g.filter(":first")[0],f=g.filter(":last")[0];if(h.target==f&&!h.shiftKey){setTimeout(function(){i.focus()},1)}else{if(h.target==i&&h.shiftKey){setTimeout(function(){f.focus()},1)}}}));c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();this._trigger("open");this._isOpen=true},_createButtons:function(g){var f=this,d=false,e=c("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");this.uiDialog.find(".ui-dialog-buttonpane").remove();(typeof g=="object"&&g!==null&&c.each(g,function(){return !(d=true)}));if(d){c.each(g,function(h,i){c('<button type="button"></button>').addClass("ui-state-default ui-corner-all").text(h).click(function(){i.apply(f.element[0],arguments)}).hover(function(){c(this).addClass("ui-state-hover")},function(){c(this).removeClass("ui-state-hover")}).focus(function(){c(this).addClass("ui-state-focus")}).blur(function(){c(this).removeClass("ui-state-focus")}).appendTo(e)});e.appendTo(this.uiDialog)}},_makeDraggable:function(){var d=this,f=this.options,e;this.uiDialog.draggable({cancel:".ui-dialog-content",handle:".ui-dialog-titlebar",containment:"document",start:function(){e=f.height;c(this).height(c(this).height()).addClass("ui-dialog-dragging");(f.dragStart&&f.dragStart.apply(d.element[0],arguments))},drag:function(){(f.drag&&f.drag.apply(d.element[0],arguments))},stop:function(){c(this).removeClass("ui-dialog-dragging").height(e);(f.dragStop&&f.dragStop.apply(d.element[0],arguments));c.ui.dialog.overlay.resize()}})},_makeResizable:function(g){g=(g===undefined?this.options.resizable:g);var d=this,f=this.options,e=typeof g=="string"?g:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",alsoResize:this.element,maxWidth:f.maxWidth,maxHeight:f.maxHeight,minWidth:f.minWidth,minHeight:f.minHeight,start:function(){c(this).addClass("ui-dialog-resizing");(f.resizeStart&&f.resizeStart.apply(d.element[0],arguments))},resize:function(){(f.resize&&f.resize.apply(d.element[0],arguments))},handles:e,stop:function(){c(this).removeClass("ui-dialog-resizing");f.height=c(this).height();f.width=c(this).width();(f.resizeStop&&f.resizeStop.apply(d.element[0],arguments));c.ui.dialog.overlay.resize()}}).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_position:function(i){var e=c(window),f=c(document),g=f.scrollTop(),d=f.scrollLeft(),h=g;if(c.inArray(i,["center","top","right","bottom","left"])>=0){i=[i=="right"||i=="left"?i:"center",i=="top"||i=="bottom"?i:"middle"]}if(i.constructor!=Array){i=["center","middle"]}if(i[0].constructor==Number){d+=i[0]}else{switch(i[0]){case"left":d+=0;break;case"right":d+=e.width()-this.uiDialog.outerWidth();break;default:case"center":d+=(e.width()-this.uiDialog.outerWidth())/2}}if(i[1].constructor==Number){g+=i[1]}else{switch(i[1]){case"top":g+=0;break;case"bottom":g+=e.height()-this.uiDialog.outerHeight();break;default:case"middle":g+=(e.height()-this.uiDialog.outerHeight())/2}}g=Math.max(g,h);this.uiDialog.css({top:g,left:d})},_setData:function(e,f){(b[e]&&this.uiDialog.data(b[e],f));switch(e){case"buttons":this._createButtons(f);break;case"closeText":this.uiDialogTitlebarCloseText.text(f);break;case"dialogClass":this.uiDialog.removeClass(this.options.dialogClass).addClass(a+f);break;case"draggable":(f?this._makeDraggable():this.uiDialog.draggable("destroy"));break;case"height":this.uiDialog.height(f);break;case"position":this._position(f);break;case"resizable":var d=this.uiDialog,g=this.uiDialog.is(":data(resizable)");(g&&!f&&d.resizable("destroy"));(g&&typeof f=="string"&&d.resizable("option","handles",f));(g||this._makeResizable(f));break;case"title":c(".ui-dialog-title",this.uiDialogTitlebar).html(f||"&nbsp;");break;case"width":this.uiDialog.width(f);break}c.widget.prototype._setData.apply(this,arguments)},_size:function(){var e=this.options;this.element.css({height:0,minHeight:0,width:"auto"});var d=this.uiDialog.css({height:"auto",width:e.width}).height();this.element.css({minHeight:Math.max(e.minHeight-d,0),height:e.height=="auto"?"auto":Math.max(e.height-d,0)})}});c.extend(c.ui.dialog,{version:"1.7.2",defaults:{autoOpen:true,bgiframe:false,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:"center",resizable:true,show:null,stack:true,title:"",width:300,zIndex:1000},getter:"isOpen",uuid:0,maxZ:0,getTitleId:function(d){return"ui-dialog-title-"+(d.attr("id")||++this.uuid)},overlay:function(d){this.$el=c.ui.dialog.overlay.create(d)}});c.extend(c.ui.dialog.overlay,{instances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(d){return d+".dialog-overlay"}).join(" "),create:function(e){if(this.instances.length===0){setTimeout(function(){if(c.ui.dialog.overlay.instances.length){c(document).bind(c.ui.dialog.overlay.events,function(f){var g=c(f.target).parents(".ui-dialog").css("zIndex")||0;return(g>c.ui.dialog.overlay.maxZ)})}},1);c(document).bind("keydown.dialog-overlay",function(f){(e.options.closeOnEscape&&f.keyCode&&f.keyCode==c.ui.keyCode.ESCAPE&&e.close(f))});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var d=c("<div></div>").appendTo(document.body).addClass("ui-widget-overlay").css({width:this.width(),height:this.height()});(e.options.bgiframe&&c.fn.bgiframe&&d.bgiframe());this.instances.push(d);return d},destroy:function(d){this.instances.splice(c.inArray(this.instances,d),1);if(this.instances.length===0){c([document,window]).unbind(".dialog-overlay")}d.remove();var e=0;c.each(this.instances,function(){e=Math.max(e,this.css("z-index"))});this.maxZ=e},height:function(){if(c.browser.msie&&c.browser.version<7){var e=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);var d=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);if(e<d){return c(window).height()+"px"}else{return e+"px"}}else{return c(document).height()+"px"}},width:function(){if(c.browser.msie&&c.browser.version<7){var d=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);var e=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);if(d<e){return c(window).width()+"px"}else{return d+"px"}}else{return c(document).width()+"px"}},resize:function(){var d=c([]);c.each(c.ui.dialog.overlay.instances,function(){d=d.add(this)});d.css({width:0,height:0}).css({width:c.ui.dialog.overlay.width(),height:c.ui.dialog.overlay.height()})}});c.extend(c.ui.dialog.overlay.prototype,{destroy:function(){c.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);;/*
+ * jQuery UI Slider 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Slider
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(a){a.widget("ui.slider",a.extend({},a.ui.mouse,{_init:function(){var b=this,c=this.options;this._keySliding=false;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all");this.range=a([]);if(c.range){if(c.range===true){this.range=a("<div></div>");if(!c.values){c.values=[this._valueMin(),this._valueMin()]}if(c.values.length&&c.values.length!=2){c.values=[c.values[0],c.values[0]]}}else{this.range=a("<div></div>")}this.range.appendTo(this.element).addClass("ui-slider-range");if(c.range=="min"||c.range=="max"){this.range.addClass("ui-slider-range-"+c.range)}this.range.addClass("ui-widget-header")}if(a(".ui-slider-handle",this.element).length==0){a('<a href="#"></a>').appendTo(this.element).addClass("ui-slider-handle")}if(c.values&&c.values.length){while(a(".ui-slider-handle",this.element).length<c.values.length){a('<a href="#"></a>').appendTo(this.element).addClass("ui-slider-handle")}}this.handles=a(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(d){d.preventDefault()}).hover(function(){if(!c.disabled){a(this).addClass("ui-state-hover")}},function(){a(this).removeClass("ui-state-hover")}).focus(function(){if(!c.disabled){a(".ui-slider .ui-state-focus").removeClass("ui-state-focus");a(this).addClass("ui-state-focus")}else{a(this).blur()}}).blur(function(){a(this).removeClass("ui-state-focus")});this.handles.each(function(d){a(this).data("index.ui-slider-handle",d)});this.handles.keydown(function(i){var f=true;var e=a(this).data("index.ui-slider-handle");if(b.options.disabled){return}switch(i.keyCode){case a.ui.keyCode.HOME:case a.ui.keyCode.END:case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:f=false;if(!b._keySliding){b._keySliding=true;a(this).addClass("ui-state-active");b._start(i,e)}break}var g,d,h=b._step();if(b.options.values&&b.options.values.length){g=d=b.values(e)}else{g=d=b.value()}switch(i.keyCode){case a.ui.keyCode.HOME:d=b._valueMin();break;case a.ui.keyCode.END:d=b._valueMax();break;case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:if(g==b._valueMax()){return}d=g+h;break;case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:if(g==b._valueMin()){return}d=g-h;break}b._slide(i,e,d);return f}).keyup(function(e){var d=a(this).data("index.ui-slider-handle");if(b._keySliding){b._stop(e,d);b._change(e,d);b._keySliding=false;a(this).removeClass("ui-state-active")}});this._refreshValue()},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");this._mouseDestroy()},_mouseCapture:function(d){var e=this.options;if(e.disabled){return false}this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();var h={x:d.pageX,y:d.pageY};var j=this._normValueFromMouse(h);var c=this._valueMax()-this._valueMin()+1,f;var k=this,i;this.handles.each(function(l){var m=Math.abs(j-k.values(l));if(c>m){c=m;f=a(this);i=l}});if(e.range==true&&this.values(1)==e.min){f=a(this.handles[++i])}this._start(d,i);k._handleIndex=i;f.addClass("ui-state-active").focus();var g=f.offset();var b=!a(d.target).parents().andSelf().is(".ui-slider-handle");this._clickOffset=b?{left:0,top:0}:{left:d.pageX-g.left-(f.width()/2),top:d.pageY-g.top-(f.height()/2)-(parseInt(f.css("borderTopWidth"),10)||0)-(parseInt(f.css("borderBottomWidth"),10)||0)+(parseInt(f.css("marginTop"),10)||0)};j=this._normValueFromMouse(h);this._slide(d,i,j);return true},_mouseStart:function(b){return true},_mouseDrag:function(d){var b={x:d.pageX,y:d.pageY};var c=this._normValueFromMouse(b);this._slide(d,this._handleIndex,c);return false},_mouseStop:function(b){this.handles.removeClass("ui-state-active");this._stop(b,this._handleIndex);this._change(b,this._handleIndex);this._handleIndex=null;this._clickOffset=null;return false},_detectOrientation:function(){this.orientation=this.options.orientation=="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(d){var c,h;if("horizontal"==this.orientation){c=this.elementSize.width;h=d.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{c=this.elementSize.height;h=d.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}var f=(h/c);if(f>1){f=1}if(f<0){f=0}if("vertical"==this.orientation){f=1-f}var e=this._valueMax()-this._valueMin(),i=f*e,b=i%this.options.step,g=this._valueMin()+i-b;if(b>(this.options.step/2)){g+=this.options.step}return parseFloat(g.toFixed(5))},_start:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("start",d,b)},_slide:function(f,e,d){var g=this.handles[e];if(this.options.values&&this.options.values.length){var b=this.values(e?0:1);if((this.options.values.length==2&&this.options.range===true)&&((e==0&&d>b)||(e==1&&d<b))){d=b}if(d!=this.values(e)){var c=this.values();c[e]=d;var h=this._trigger("slide",f,{handle:this.handles[e],value:d,values:c});var b=this.values(e?0:1);if(h!==false){this.values(e,d,(f.type=="mousedown"&&this.options.animate),true)}}}else{if(d!=this.value()){var h=this._trigger("slide",f,{handle:this.handles[e],value:d});if(h!==false){this._setData("value",d,(f.type=="mousedown"&&this.options.animate))}}}},_stop:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("stop",d,b)},_change:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("change",d,b)},value:function(b){if(arguments.length){this._setData("value",b);this._change(null,0)}return this._value()},values:function(b,e,c,d){if(arguments.length>1){this.options.values[b]=e;this._refreshValue(c);if(!d){this._change(null,b)}}if(arguments.length){if(this.options.values&&this.options.values.length){return this._values(b)}else{return this.value()}}else{return this._values()}},_setData:function(b,d,c){a.widget.prototype._setData.apply(this,arguments);switch(b){case"disabled":if(d){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.attr("disabled","disabled")}else{this.handles.removeAttr("disabled")}case"orientation":this._detectOrientation();this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue(c);break;case"value":this._refreshValue(c);break}},_step:function(){var b=this.options.step;return b},_value:function(){var b=this.options.value;if(b<this._valueMin()){b=this._valueMin()}if(b>this._valueMax()){b=this._valueMax()}return b},_values:function(b){if(arguments.length){var c=this.options.values[b];if(c<this._valueMin()){c=this._valueMin()}if(c>this._valueMax()){c=this._valueMax()}return c}else{return this.options.values}},_valueMin:function(){var b=this.options.min;return b},_valueMax:function(){var b=this.options.max;return b},_refreshValue:function(c){var f=this.options.range,d=this.options,l=this;if(this.options.values&&this.options.values.length){var i,h;this.handles.each(function(p,n){var o=(l.values(p)-l._valueMin())/(l._valueMax()-l._valueMin())*100;var m={};m[l.orientation=="horizontal"?"left":"bottom"]=o+"%";a(this).stop(1,1)[c?"animate":"css"](m,d.animate);if(l.options.range===true){if(l.orientation=="horizontal"){(p==0)&&l.range.stop(1,1)[c?"animate":"css"]({left:o+"%"},d.animate);(p==1)&&l.range[c?"animate":"css"]({width:(o-lastValPercent)+"%"},{queue:false,duration:d.animate})}else{(p==0)&&l.range.stop(1,1)[c?"animate":"css"]({bottom:(o)+"%"},d.animate);(p==1)&&l.range[c?"animate":"css"]({height:(o-lastValPercent)+"%"},{queue:false,duration:d.animate})}}lastValPercent=o})}else{var j=this.value(),g=this._valueMin(),k=this._valueMax(),e=k!=g?(j-g)/(k-g)*100:0;var b={};b[l.orientation=="horizontal"?"left":"bottom"]=e+"%";this.handle.stop(1,1)[c?"animate":"css"](b,d.animate);(f=="min")&&(this.orientation=="horizontal")&&this.range.stop(1,1)[c?"animate":"css"]({width:e+"%"},d.animate);(f=="max")&&(this.orientation=="horizontal")&&this.range[c?"animate":"css"]({width:(100-e)+"%"},{queue:false,duration:d.animate});(f=="min")&&(this.orientation=="vertical")&&this.range.stop(1,1)[c?"animate":"css"]({height:e+"%"},d.animate);(f=="max")&&(this.orientation=="vertical")&&this.range[c?"animate":"css"]({height:(100-e)+"%"},{queue:false,duration:d.animate})}}}));a.extend(a.ui.slider,{getter:"value values",version:"1.7.2",eventPrefix:"slide",defaults:{animate:false,delay:0,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null}})})(jQuery);;/*
+ * jQuery UI Tabs 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Tabs
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(a){a.widget("ui.tabs",{_init:function(){if(this.options.deselectable!==undefined){this.options.collapsible=this.options.deselectable}this._tabify(true)},_setData:function(b,c){if(b=="selected"){if(this.options.collapsible&&c==this.options.selected){return}this.select(c)}else{this.options[b]=c;if(b=="deselectable"){this.options.collapsible=c}this._tabify()}},_tabId:function(b){return b.title&&b.title.replace(/\s/g,"_").replace(/[^A-Za-z0-9\-_:\.]/g,"")||this.options.idPrefix+a.data(b)},_sanitizeSelector:function(b){return b.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+a.data(this.list[0]));return a.cookie.apply(null,[b].concat(a.makeArray(arguments)))},_ui:function(c,b){return{tab:c,panel:b,index:this.anchors.index(c)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=a(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(n){this.list=this.element.children("ul:first");this.lis=a("li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return a("a",this)[0]});this.panels=a([]);var p=this,d=this.options;var c=/^#.+/;this.anchors.each(function(r,o){var q=a(o).attr("href");var s=q.split("#")[0],u;if(s&&(s===location.toString().split("#")[0]||(u=a("base")[0])&&s===u.href)){q=o.hash;o.href=q}if(c.test(q)){p.panels=p.panels.add(p._sanitizeSelector(q))}else{if(q!="#"){a.data(o,"href.tabs",q);a.data(o,"load.tabs",q.replace(/#.*$/,""));var w=p._tabId(o);o.href="#"+w;var v=a("#"+w);if(!v.length){v=a(d.panelTemplate).attr("id",w).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(p.panels[r-1]||p.list);v.data("destroy.tabs",true)}p.panels=p.panels.add(v)}else{d.disabled.push(r)}}});if(n){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all");this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(d.selected===undefined){if(location.hash){this.anchors.each(function(q,o){if(o.hash==location.hash){d.selected=q;return false}})}if(typeof d.selected!="number"&&d.cookie){d.selected=parseInt(p._cookie(),10)}if(typeof d.selected!="number"&&this.lis.filter(".ui-tabs-selected").length){d.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))}d.selected=d.selected||0}else{if(d.selected===null){d.selected=-1}}d.selected=((d.selected>=0&&this.anchors[d.selected])||d.selected<0)?d.selected:0;d.disabled=a.unique(d.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(q,o){return p.lis.index(q)}))).sort();if(a.inArray(d.selected,d.disabled)!=-1){d.disabled.splice(a.inArray(d.selected,d.disabled),1)}this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active");if(d.selected>=0&&this.anchors.length){this.panels.eq(d.selected).removeClass("ui-tabs-hide");this.lis.eq(d.selected).addClass("ui-tabs-selected ui-state-active");p.element.queue("tabs",function(){p._trigger("show",null,p._ui(p.anchors[d.selected],p.panels[d.selected]))});this.load(d.selected)}a(window).bind("unload",function(){p.lis.add(p.anchors).unbind(".tabs");p.lis=p.anchors=p.panels=null})}else{d.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))}this.element[d.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");if(d.cookie){this._cookie(d.selected,d.cookie)}for(var g=0,m;(m=this.lis[g]);g++){a(m)[a.inArray(g,d.disabled)!=-1&&!a(m).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled")}if(d.cache===false){this.anchors.removeData("cache.tabs")}this.lis.add(this.anchors).unbind(".tabs");if(d.event!="mouseover"){var f=function(o,i){if(i.is(":not(.ui-state-disabled)")){i.addClass("ui-state-"+o)}};var j=function(o,i){i.removeClass("ui-state-"+o)};this.lis.bind("mouseover.tabs",function(){f("hover",a(this))});this.lis.bind("mouseout.tabs",function(){j("hover",a(this))});this.anchors.bind("focus.tabs",function(){f("focus",a(this).closest("li"))});this.anchors.bind("blur.tabs",function(){j("focus",a(this).closest("li"))})}var b,h;if(d.fx){if(a.isArray(d.fx)){b=d.fx[0];h=d.fx[1]}else{b=h=d.fx}}function e(i,o){i.css({display:""});if(a.browser.msie&&o.opacity){i[0].style.removeAttribute("filter")}}var k=h?function(i,o){a(i).closest("li").removeClass("ui-state-default").addClass("ui-tabs-selected ui-state-active");o.hide().removeClass("ui-tabs-hide").animate(h,h.duration||"normal",function(){e(o,h);p._trigger("show",null,p._ui(i,o[0]))})}:function(i,o){a(i).closest("li").removeClass("ui-state-default").addClass("ui-tabs-selected ui-state-active");o.removeClass("ui-tabs-hide");p._trigger("show",null,p._ui(i,o[0]))};var l=b?function(o,i){i.animate(b,b.duration||"normal",function(){p.lis.removeClass("ui-tabs-selected ui-state-active").addClass("ui-state-default");i.addClass("ui-tabs-hide");e(i,b);p.element.dequeue("tabs")})}:function(o,i,q){p.lis.removeClass("ui-tabs-selected ui-state-active").addClass("ui-state-default");i.addClass("ui-tabs-hide");p.element.dequeue("tabs")};this.anchors.bind(d.event+".tabs",function(){var o=this,r=a(this).closest("li"),i=p.panels.filter(":not(.ui-tabs-hide)"),q=a(p._sanitizeSelector(this.hash));if((r.hasClass("ui-tabs-selected")&&!d.collapsible)||r.hasClass("ui-state-disabled")||r.hasClass("ui-state-processing")||p._trigger("select",null,p._ui(this,q[0]))===false){this.blur();return false}d.selected=p.anchors.index(this);p.abort();if(d.collapsible){if(r.hasClass("ui-tabs-selected")){d.selected=-1;if(d.cookie){p._cookie(d.selected,d.cookie)}p.element.queue("tabs",function(){l(o,i)}).dequeue("tabs");this.blur();return false}else{if(!i.length){if(d.cookie){p._cookie(d.selected,d.cookie)}p.element.queue("tabs",function(){k(o,q)});p.load(p.anchors.index(this));this.blur();return false}}}if(d.cookie){p._cookie(d.selected,d.cookie)}if(q.length){if(i.length){p.element.queue("tabs",function(){l(o,i)})}p.element.queue("tabs",function(){k(o,q)});p.load(p.anchors.index(this))}else{throw"jQuery UI Tabs: Mismatching fragment identifier."}if(a.browser.msie){this.blur()}});this.anchors.bind("click.tabs",function(){return false})},destroy:function(){var b=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var c=a.data(this,"href.tabs");if(c){this.href=c}var d=a(this).unbind(".tabs");a.each(["href","load","cache"],function(e,f){d.removeData(f+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){if(a.data(this,"destroy.tabs")){a(this).remove()}else{a(this).removeClass(["ui-state-default","ui-corner-top","ui-tabs-selected","ui-state-active","ui-state-hover","ui-state-focus","ui-state-disabled","ui-tabs-panel","ui-widget-content","ui-corner-bottom","ui-tabs-hide"].join(" "))}});if(b.cookie){this._cookie(null,b.cookie)}},add:function(e,d,c){if(c===undefined){c=this.anchors.length}var b=this,g=this.options,i=a(g.tabTemplate.replace(/#\{href\}/g,e).replace(/#\{label\}/g,d)),h=!e.indexOf("#")?e.replace("#",""):this._tabId(a("a",i)[0]);i.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var f=a("#"+h);if(!f.length){f=a(g.panelTemplate).attr("id",h).data("destroy.tabs",true)}f.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(c>=this.lis.length){i.appendTo(this.list);f.appendTo(this.list[0].parentNode)}else{i.insertBefore(this.lis[c]);f.insertBefore(this.panels[c])}g.disabled=a.map(g.disabled,function(k,j){return k>=c?++k:k});this._tabify();if(this.anchors.length==1){i.addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){b._trigger("show",null,b._ui(b.anchors[0],b.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[c],this.panels[c]))},remove:function(b){var d=this.options,e=this.lis.eq(b).remove(),c=this.panels.eq(b).remove();if(e.hasClass("ui-tabs-selected")&&this.anchors.length>1){this.select(b+(b+1<this.anchors.length?1:-1))}d.disabled=a.map(a.grep(d.disabled,function(g,f){return g!=b}),function(g,f){return g>=b?--g:g});this._tabify();this._trigger("remove",null,this._ui(e.find("a")[0],c[0]))},enable:function(b){var c=this.options;if(a.inArray(b,c.disabled)==-1){return}this.lis.eq(b).removeClass("ui-state-disabled");c.disabled=a.grep(c.disabled,function(e,d){return e!=b});this._trigger("enable",null,this._ui(this.anchors[b],this.panels[b]))},disable:function(c){var b=this,d=this.options;if(c!=d.selected){this.lis.eq(c).addClass("ui-state-disabled");d.disabled.push(c);d.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[c],this.panels[c]))}},select:function(b){if(typeof b=="string"){b=this.anchors.index(this.anchors.filter("[href$="+b+"]"))}else{if(b===null){b=-1}}if(b==-1&&this.options.collapsible){b=this.options.selected}this.anchors.eq(b).trigger(this.options.event+".tabs")},load:function(e){var c=this,g=this.options,b=this.anchors.eq(e)[0],d=a.data(b,"load.tabs");this.abort();if(!d||this.element.queue("tabs").length!==0&&a.data(b,"cache.tabs")){this.element.dequeue("tabs");return}this.lis.eq(e).addClass("ui-state-processing");if(g.spinner){var f=a("span",b);f.data("label.tabs",f.html()).html(g.spinner)}this.xhr=a.ajax(a.extend({},g.ajaxOptions,{url:d,success:function(i,h){a(c._sanitizeSelector(b.hash)).html(i);c._cleanup();if(g.cache){a.data(b,"cache.tabs",true)}c._trigger("load",null,c._ui(c.anchors[e],c.panels[e]));try{g.ajaxOptions.success(i,h)}catch(j){}c.element.dequeue("tabs")}}))},abort:function(){this.element.queue([]);this.panels.stop(false,true);if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup()},url:function(c,b){this.anchors.eq(c).removeData("cache.tabs").data("load.tabs",b)},length:function(){return this.anchors.length}});a.extend(a.ui.tabs,{version:"1.7.2",getter:"length",defaults:{ajaxOptions:null,cache:false,cookie:null,collapsible:false,disabled:[],event:"click",fx:null,idPrefix:"ui-tabs-",panelTemplate:"<div></div>",spinner:"<em>Loading&#8230;</em>",tabTemplate:'<li><a href="#{href}"><span>#{label}</span></a></li>'}});a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(d,f){var b=this,g=this.options;var c=b._rotate||(b._rotate=function(h){clearTimeout(b.rotation);b.rotation=setTimeout(function(){var i=g.selected;b.select(++i<b.anchors.length?i:0)},d);if(h){h.stopPropagation()}});var e=b._unrotate||(b._unrotate=!f?function(h){if(h.clientX){b.rotate(null)}}:function(h){t=g.selected;c()});if(d){this.element.bind("tabsshow",c);this.anchors.bind(g.event+".tabs",e);c()}else{clearTimeout(b.rotation);this.element.unbind("tabsshow",c);this.anchors.unbind(g.event+".tabs",e);delete this._rotate;delete this._unrotate}}})})(jQuery);;/*
+ * jQuery UI Datepicker 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Datepicker
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function($){$.extend($.ui,{datepicker:{version:"1.7.2"}});var PROP_NAME="datepicker";function Datepicker(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._datepickerShowing=false;this._inDialog=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass="ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],dateFormat:"mm/dd/yy",firstDay:0,isRTL:false};this._defaults={showOn:"focus",showAnim:"show",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,showMonthAfterYear:false,yearRange:"-10:+10",showOtherMonths:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"normal",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false};$.extend(this._defaults,this.regional[""]);this.dpDiv=$('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>')}$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",log:function(){if(this.debug){console.log.apply("",arguments)}},setDefaults:function(settings){extendRemove(this._defaults,settings||{});return this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase();var inline=(nodeName=="div"||nodeName=="span");if(!target.id){target.id="dp"+(++this.uuid)}var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{});if(nodeName=="input"){this._connectDatepicker(target,inst)}else{if(inline){this._inlineDatepicker(target,inst)}}},_newInst:function(target,inline){var id=target[0].id.replace(/([:\[\]\.])/g,"\\\\$1");return{id:id,input:target,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:inline,dpDiv:(!inline?this.dpDiv:$('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}},_connectDatepicker:function(target,inst){var input=$(target);inst.append=$([]);inst.trigger=$([]);if(input.hasClass(this.markerClassName)){return}var appendText=this._get(inst,"appendText");var isRTL=this._get(inst,"isRTL");if(appendText){inst.append=$('<span class="'+this._appendClass+'">'+appendText+"</span>");input[isRTL?"before":"after"](inst.append)}var showOn=this._get(inst,"showOn");if(showOn=="focus"||showOn=="both"){input.focus(this._showDatepicker)}if(showOn=="button"||showOn=="both"){var buttonText=this._get(inst,"buttonText");var buttonImage=this._get(inst,"buttonImage");inst.trigger=$(this._get(inst,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:buttonImage,alt:buttonText,title:buttonText}):$('<button type="button"></button>').addClass(this._triggerClass).html(buttonImage==""?buttonText:$("<img/>").attr({src:buttonImage,alt:buttonText,title:buttonText})));input[isRTL?"before":"after"](inst.trigger);inst.trigger.click(function(){if($.datepicker._datepickerShowing&&$.datepicker._lastInput==target){$.datepicker._hideDatepicker()}else{$.datepicker._showDatepicker(target)}return false})}input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).bind("setData.datepicker",function(event,key,value){inst.settings[key]=value}).bind("getData.datepicker",function(event,key){return this._get(inst,key)});$.data(target,PROP_NAME,inst)},_inlineDatepicker:function(target,inst){var divSpan=$(target);if(divSpan.hasClass(this.markerClassName)){return}divSpan.addClass(this.markerClassName).append(inst.dpDiv).bind("setData.datepicker",function(event,key,value){inst.settings[key]=value}).bind("getData.datepicker",function(event,key){return this._get(inst,key)});$.data(target,PROP_NAME,inst);this._setDate(inst,this._getDefaultDate(inst));this._updateDatepicker(inst);this._updateAlternate(inst)},_dialogDatepicker:function(input,dateText,onSelect,settings,pos){var inst=this._dialogInst;if(!inst){var id="dp"+(++this.uuid);this._dialogInput=$('<input type="text" id="'+id+'" size="1" style="position: absolute; top: -100px;"/>');this._dialogInput.keydown(this._doKeyDown);$("body").append(this._dialogInput);inst=this._dialogInst=this._newInst(this._dialogInput,false);inst.settings={};$.data(this._dialogInput[0],PROP_NAME,inst)}extendRemove(inst.settings,settings||{});this._dialogInput.val(dateText);this._pos=(pos?(pos.length?pos:[pos.pageX,pos.pageY]):null);if(!this._pos){var browserWidth=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;var browserHeight=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;var scrollX=document.documentElement.scrollLeft||document.body.scrollLeft;var scrollY=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[(browserWidth/2)-100+scrollX,(browserHeight/2)-150+scrollY]}this._dialogInput.css("left",this._pos[0]+"px").css("top",this._pos[1]+"px");inst.settings.onSelect=onSelect;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);if($.blockUI){$.blockUI(this.dpDiv)}$.data(this._dialogInput[0],PROP_NAME,inst);return this},_destroyDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();$.removeData(target,PROP_NAME);if(nodeName=="input"){inst.append.remove();inst.trigger.remove();$target.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress)}else{if(nodeName=="div"||nodeName=="span"){$target.removeClass(this.markerClassName).empty()}}},_enableDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();if(nodeName=="input"){target.disabled=false;inst.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else{if(nodeName=="div"||nodeName=="span"){var inline=$target.children("."+this._inlineClass);inline.children().removeClass("ui-state-disabled")}}this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value)})},_disableDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();if(nodeName=="input"){target.disabled=true;inst.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else{if(nodeName=="div"||nodeName=="span"){var inline=$target.children("."+this._inlineClass);inline.children().addClass("ui-state-disabled")}}this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value)});this._disabledInputs[this._disabledInputs.length]=target},_isDisabledDatepicker:function(target){if(!target){return false}for(var i=0;i<this._disabledInputs.length;i++){if(this._disabledInputs[i]==target){return true}}return false},_getInst:function(target){try{return $.data(target,PROP_NAME)}catch(err){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(target,name,value){var inst=this._getInst(target);if(arguments.length==2&&typeof name=="string"){return(name=="defaults"?$.extend({},$.datepicker._defaults):(inst?(name=="all"?$.extend({},inst.settings):this._get(inst,name)):null))}var settings=name||{};if(typeof name=="string"){settings={};settings[name]=value}if(inst){if(this._curInst==inst){this._hideDatepicker(null)}var date=this._getDateDatepicker(target);extendRemove(inst.settings,settings);this._setDateDatepicker(target,date);this._updateDatepicker(inst)}},_changeDatepicker:function(target,name,value){this._optionDatepicker(target,name,value)},_refreshDatepicker:function(target){var inst=this._getInst(target);if(inst){this._updateDatepicker(inst)}},_setDateDatepicker:function(target,date,endDate){var inst=this._getInst(target);if(inst){this._setDate(inst,date,endDate);this._updateDatepicker(inst);this._updateAlternate(inst)}},_getDateDatepicker:function(target){var inst=this._getInst(target);if(inst&&!inst.inline){this._setDateFromField(inst)}return(inst?this._getDate(inst):null)},_doKeyDown:function(event){var inst=$.datepicker._getInst(event.target);var handled=true;var isRTL=inst.dpDiv.is(".ui-datepicker-rtl");inst._keyEvent=true;if($.datepicker._datepickerShowing){switch(event.keyCode){case 9:$.datepicker._hideDatepicker(null,"");break;case 13:var sel=$("td."+$.datepicker._dayOverClass+", td."+$.datepicker._currentClass,inst.dpDiv);if(sel[0]){$.datepicker._selectDay(event.target,inst.selectedMonth,inst.selectedYear,sel[0])}else{$.datepicker._hideDatepicker(null,$.datepicker._get(inst,"duration"))}return false;break;case 27:$.datepicker._hideDatepicker(null,$.datepicker._get(inst,"duration"));break;case 33:$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,"stepBigMonths"):-$.datepicker._get(inst,"stepMonths")),"M");break;case 34:$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,"stepBigMonths"):+$.datepicker._get(inst,"stepMonths")),"M");break;case 35:if(event.ctrlKey||event.metaKey){$.datepicker._clearDate(event.target)}handled=event.ctrlKey||event.metaKey;break;case 36:if(event.ctrlKey||event.metaKey){$.datepicker._gotoToday(event.target)}handled=event.ctrlKey||event.metaKey;break;case 37:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,(isRTL?+1:-1),"D")}handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey){$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,"stepBigMonths"):-$.datepicker._get(inst,"stepMonths")),"M")}break;case 38:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,-7,"D")}handled=event.ctrlKey||event.metaKey;break;case 39:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,(isRTL?-1:+1),"D")}handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey){$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,"stepBigMonths"):+$.datepicker._get(inst,"stepMonths")),"M")}break;case 40:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,+7,"D")}handled=event.ctrlKey||event.metaKey;break;default:handled=false}}else{if(event.keyCode==36&&event.ctrlKey){$.datepicker._showDatepicker(this)}else{handled=false}}if(handled){event.preventDefault();event.stopPropagation()}},_doKeyPress:function(event){var inst=$.datepicker._getInst(event.target);if($.datepicker._get(inst,"constrainInput")){var chars=$.datepicker._possibleChars($.datepicker._get(inst,"dateFormat"));var chr=String.fromCharCode(event.charCode==undefined?event.keyCode:event.charCode);return event.ctrlKey||(chr<" "||!chars||chars.indexOf(chr)>-1)}},_showDatepicker:function(input){input=input.target||input;if(input.nodeName.toLowerCase()!="input"){input=$("input",input.parentNode)[0]}if($.datepicker._isDisabledDatepicker(input)||$.datepicker._lastInput==input){return}var inst=$.datepicker._getInst(input);var beforeShow=$.datepicker._get(inst,"beforeShow");extendRemove(inst.settings,(beforeShow?beforeShow.apply(input,[input,inst]):{}));$.datepicker._hideDatepicker(null,"");$.datepicker._lastInput=input;$.datepicker._setDateFromField(inst);if($.datepicker._inDialog){input.value=""}if(!$.datepicker._pos){$.datepicker._pos=$.datepicker._findPos(input);$.datepicker._pos[1]+=input.offsetHeight}var isFixed=false;$(input).parents().each(function(){isFixed|=$(this).css("position")=="fixed";return !isFixed});if(isFixed&&$.browser.opera){$.datepicker._pos[0]-=document.documentElement.scrollLeft;$.datepicker._pos[1]-=document.documentElement.scrollTop}var offset={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null;inst.rangeStart=null;inst.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});$.datepicker._updateDatepicker(inst);offset=$.datepicker._checkOffset(inst,offset,isFixed);inst.dpDiv.css({position:($.datepicker._inDialog&&$.blockUI?"static":(isFixed?"fixed":"absolute")),display:"none",left:offset.left+"px",top:offset.top+"px"});if(!inst.inline){var showAnim=$.datepicker._get(inst,"showAnim")||"show";var duration=$.datepicker._get(inst,"duration");var postProcess=function(){$.datepicker._datepickerShowing=true;if($.browser.msie&&parseInt($.browser.version,10)<7){$("iframe.ui-datepicker-cover").css({width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4})}};if($.effects&&$.effects[showAnim]){inst.dpDiv.show(showAnim,$.datepicker._get(inst,"showOptions"),duration,postProcess)}else{inst.dpDiv[showAnim](duration,postProcess)}if(duration==""){postProcess()}if(inst.input[0].type!="hidden"){inst.input[0].focus()}$.datepicker._curInst=inst}},_updateDatepicker:function(inst){var dims={width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4};var self=this;inst.dpDiv.empty().append(this._generateHTML(inst)).find("iframe.ui-datepicker-cover").css({width:dims.width,height:dims.height}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){$(this).removeClass("ui-state-hover");if(this.className.indexOf("ui-datepicker-prev")!=-1){$(this).removeClass("ui-datepicker-prev-hover")}if(this.className.indexOf("ui-datepicker-next")!=-1){$(this).removeClass("ui-datepicker-next-hover")}}).bind("mouseover",function(){if(!self._isDisabledDatepicker(inst.inline?inst.dpDiv.parent()[0]:inst.input[0])){$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");$(this).addClass("ui-state-hover");if(this.className.indexOf("ui-datepicker-prev")!=-1){$(this).addClass("ui-datepicker-prev-hover")}if(this.className.indexOf("ui-datepicker-next")!=-1){$(this).addClass("ui-datepicker-next-hover")}}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();var numMonths=this._getNumberOfMonths(inst);var cols=numMonths[1];var width=17;if(cols>1){inst.dpDiv.addClass("ui-datepicker-multi-"+cols).css("width",(width*cols)+"em")}else{inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("")}inst.dpDiv[(numMonths[0]!=1||numMonths[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");inst.dpDiv[(this._get(inst,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");if(inst.input&&inst.input[0].type!="hidden"&&inst==$.datepicker._curInst){$(inst.input[0]).focus()}},_checkOffset:function(inst,offset,isFixed){var dpWidth=inst.dpDiv.outerWidth();var dpHeight=inst.dpDiv.outerHeight();var inputWidth=inst.input?inst.input.outerWidth():0;var inputHeight=inst.input?inst.input.outerHeight():0;var viewWidth=(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)+$(document).scrollLeft();var viewHeight=(window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight)+$(document).scrollTop();offset.left-=(this._get(inst,"isRTL")?(dpWidth-inputWidth):0);offset.left-=(isFixed&&offset.left==inst.input.offset().left)?$(document).scrollLeft():0;offset.top-=(isFixed&&offset.top==(inst.input.offset().top+inputHeight))?$(document).scrollTop():0;offset.left-=(offset.left+dpWidth>viewWidth&&viewWidth>dpWidth)?Math.abs(offset.left+dpWidth-viewWidth):0;offset.top-=(offset.top+dpHeight>viewHeight&&viewHeight>dpHeight)?Math.abs(offset.top+dpHeight+inputHeight*2-viewHeight):0;return offset},_findPos:function(obj){while(obj&&(obj.type=="hidden"||obj.nodeType!=1)){obj=obj.nextSibling}var position=$(obj).offset();return[position.left,position.top]},_hideDatepicker:function(input,duration){var inst=this._curInst;if(!inst||(input&&inst!=$.data(input,PROP_NAME))){return}if(inst.stayOpen){this._selectDate("#"+inst.id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear))}inst.stayOpen=false;if(this._datepickerShowing){duration=(duration!=null?duration:this._get(inst,"duration"));var showAnim=this._get(inst,"showAnim");var postProcess=function(){$.datepicker._tidyDialog(inst)};if(duration!=""&&$.effects&&$.effects[showAnim]){inst.dpDiv.hide(showAnim,$.datepicker._get(inst,"showOptions"),duration,postProcess)}else{inst.dpDiv[(duration==""?"hide":(showAnim=="slideDown"?"slideUp":(showAnim=="fadeIn"?"fadeOut":"hide")))](duration,postProcess)}if(duration==""){this._tidyDialog(inst)}var onClose=this._get(inst,"onClose");if(onClose){onClose.apply((inst.input?inst.input[0]:null),[(inst.input?inst.input.val():""),inst])}this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if($.blockUI){$.unblockUI();$("body").append(this.dpDiv)}}this._inDialog=false}this._curInst=null},_tidyDialog:function(inst){inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(event){if(!$.datepicker._curInst){return}var $target=$(event.target);if(($target.parents("#"+$.datepicker._mainDivId).length==0)&&!$target.hasClass($.datepicker.markerClassName)&&!$target.hasClass($.datepicker._triggerClass)&&$.datepicker._datepickerShowing&&!($.datepicker._inDialog&&$.blockUI)){$.datepicker._hideDatepicker(null,"")}},_adjustDate:function(id,offset,period){var target=$(id);var inst=this._getInst(target[0]);if(this._isDisabledDatepicker(target[0])){return}this._adjustInstDate(inst,offset+(period=="M"?this._get(inst,"showCurrentAtPos"):0),period);this._updateDatepicker(inst)},_gotoToday:function(id){var target=$(id);var inst=this._getInst(target[0]);if(this._get(inst,"gotoCurrent")&&inst.currentDay){inst.selectedDay=inst.currentDay;inst.drawMonth=inst.selectedMonth=inst.currentMonth;inst.drawYear=inst.selectedYear=inst.currentYear}else{var date=new Date();inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear()}this._notifyChange(inst);this._adjustDate(target)},_selectMonthYear:function(id,select,period){var target=$(id);var inst=this._getInst(target[0]);inst._selectingMonthYear=false;inst["selected"+(period=="M"?"Month":"Year")]=inst["draw"+(period=="M"?"Month":"Year")]=parseInt(select.options[select.selectedIndex].value,10);this._notifyChange(inst);this._adjustDate(target)},_clickMonthYear:function(id){var target=$(id);var inst=this._getInst(target[0]);if(inst.input&&inst._selectingMonthYear&&!$.browser.msie){inst.input[0].focus()}inst._selectingMonthYear=!inst._selectingMonthYear},_selectDay:function(id,month,year,td){var target=$(id);if($(td).hasClass(this._unselectableClass)||this._isDisabledDatepicker(target[0])){return}var inst=this._getInst(target[0]);inst.selectedDay=inst.currentDay=$("a",td).html();inst.selectedMonth=inst.currentMonth=month;inst.selectedYear=inst.currentYear=year;if(inst.stayOpen){inst.endDay=inst.endMonth=inst.endYear=null}this._selectDate(id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear));if(inst.stayOpen){inst.rangeStart=this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay));this._updateDatepicker(inst)}},_clearDate:function(id){var target=$(id);var inst=this._getInst(target[0]);inst.stayOpen=false;inst.endDay=inst.endMonth=inst.endYear=inst.rangeStart=null;this._selectDate(target,"")},_selectDate:function(id,dateStr){var target=$(id);var inst=this._getInst(target[0]);dateStr=(dateStr!=null?dateStr:this._formatDate(inst));if(inst.input){inst.input.val(dateStr)}this._updateAlternate(inst);var onSelect=this._get(inst,"onSelect");if(onSelect){onSelect.apply((inst.input?inst.input[0]:null),[dateStr,inst])}else{if(inst.input){inst.input.trigger("change")}}if(inst.inline){this._updateDatepicker(inst)}else{if(!inst.stayOpen){this._hideDatepicker(null,this._get(inst,"duration"));this._lastInput=inst.input[0];if(typeof(inst.input[0])!="object"){inst.input[0].focus()}this._lastInput=null}}},_updateAlternate:function(inst){var altField=this._get(inst,"altField");if(altField){var altFormat=this._get(inst,"altFormat")||this._get(inst,"dateFormat");var date=this._getDate(inst);dateStr=this.formatDate(altFormat,date,this._getFormatConfig(inst));$(altField).each(function(){$(this).val(dateStr)})}},noWeekends:function(date){var day=date.getDay();return[(day>0&&day<6),""]},iso8601Week:function(date){var checkDate=new Date(date.getFullYear(),date.getMonth(),date.getDate());var firstMon=new Date(checkDate.getFullYear(),1-1,4);var firstDay=firstMon.getDay()||7;firstMon.setDate(firstMon.getDate()+1-firstDay);if(firstDay<4&&checkDate<firstMon){checkDate.setDate(checkDate.getDate()-3);return $.datepicker.iso8601Week(checkDate)}else{if(checkDate>new Date(checkDate.getFullYear(),12-1,28)){firstDay=new Date(checkDate.getFullYear()+1,1-1,4).getDay()||7;if(firstDay>4&&(checkDate.getDay()||7)<firstDay-3){return 1}}}return Math.floor(((checkDate-firstMon)/86400000)/7)+1},parseDate:function(format,value,settings){if(format==null||value==null){throw"Invalid arguments"}value=(typeof value=="object"?value.toString():value+"");if(value==""){return null}var shortYearCutoff=(settings?settings.shortYearCutoff:null)||this._defaults.shortYearCutoff;var dayNamesShort=(settings?settings.dayNamesShort:null)||this._defaults.dayNamesShort;var dayNames=(settings?settings.dayNames:null)||this._defaults.dayNames;var monthNamesShort=(settings?settings.monthNamesShort:null)||this._defaults.monthNamesShort;var monthNames=(settings?settings.monthNames:null)||this._defaults.monthNames;var year=-1;var month=-1;var day=-1;var doy=-1;var literal=false;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches){iFormat++}return matches};var getNumber=function(match){lookAhead(match);var origSize=(match=="@"?14:(match=="y"?4:(match=="o"?3:2)));var size=origSize;var num=0;while(size>0&&iValue<value.length&&value.charAt(iValue)>="0"&&value.charAt(iValue)<="9"){num=num*10+parseInt(value.charAt(iValue++),10);size--}if(size==origSize){throw"Missing number at position "+iValue}return num};var getName=function(match,shortNames,longNames){var names=(lookAhead(match)?longNames:shortNames);var size=0;for(var j=0;j<names.length;j++){size=Math.max(size,names[j].length)}var name="";var iInit=iValue;while(size>0&&iValue<value.length){name+=value.charAt(iValue++);for(var i=0;i<names.length;i++){if(name==names[i]){return i+1}}size--}throw"Unknown name at position "+iInit};var checkLiteral=function(){if(value.charAt(iValue)!=format.charAt(iFormat)){throw"Unexpected literal at position "+iValue}iValue++};var iValue=0;for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{checkLiteral()}}else{switch(format.charAt(iFormat)){case"d":day=getNumber("d");break;case"D":getName("D",dayNamesShort,dayNames);break;case"o":doy=getNumber("o");break;case"m":month=getNumber("m");break;case"M":month=getName("M",monthNamesShort,monthNames);break;case"y":year=getNumber("y");break;case"@":var date=new Date(getNumber("@"));year=date.getFullYear();month=date.getMonth()+1;day=date.getDate();break;case"'":if(lookAhead("'")){checkLiteral()}else{literal=true}break;default:checkLiteral()}}}if(year==-1){year=new Date().getFullYear()}else{if(year<100){year+=new Date().getFullYear()-new Date().getFullYear()%100+(year<=shortYearCutoff?0:-100)}}if(doy>-1){month=1;day=doy;do{var dim=this._getDaysInMonth(year,month-1);if(day<=dim){break}month++;day-=dim}while(true)}var date=this._daylightSavingAdjust(new Date(year,month-1,day));if(date.getFullYear()!=year||date.getMonth()+1!=month||date.getDate()!=day){throw"Invalid date"}return date},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TIMESTAMP:"@",W3C:"yy-mm-dd",formatDate:function(format,date,settings){if(!date){return""}var dayNamesShort=(settings?settings.dayNamesShort:null)||this._defaults.dayNamesShort;var dayNames=(settings?settings.dayNames:null)||this._defaults.dayNames;var monthNamesShort=(settings?settings.monthNamesShort:null)||this._defaults.monthNamesShort;var monthNames=(settings?settings.monthNames:null)||this._defaults.monthNames;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches){iFormat++}return matches};var formatNumber=function(match,value,len){var num=""+value;if(lookAhead(match)){while(num.length<len){num="0"+num}}return num};var formatName=function(match,value,shortNames,longNames){return(lookAhead(match)?longNames[value]:shortNames[value])};var output="";var literal=false;if(date){for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{output+=format.charAt(iFormat)}}else{switch(format.charAt(iFormat)){case"d":output+=formatNumber("d",date.getDate(),2);break;case"D":output+=formatName("D",date.getDay(),dayNamesShort,dayNames);break;case"o":var doy=date.getDate();for(var m=date.getMonth()-1;m>=0;m--){doy+=this._getDaysInMonth(date.getFullYear(),m)}output+=formatNumber("o",doy,3);break;case"m":output+=formatNumber("m",date.getMonth()+1,2);break;case"M":output+=formatName("M",date.getMonth(),monthNamesShort,monthNames);break;case"y":output+=(lookAhead("y")?date.getFullYear():(date.getYear()%100<10?"0":"")+date.getYear()%100);break;case"@":output+=date.getTime();break;case"'":if(lookAhead("'")){output+="'"}else{literal=true}break;default:output+=format.charAt(iFormat)}}}}return output},_possibleChars:function(format){var chars="";var literal=false;for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{chars+=format.charAt(iFormat)}}else{switch(format.charAt(iFormat)){case"d":case"m":case"y":case"@":chars+="0123456789";break;case"D":case"M":return null;case"'":if(lookAhead("'")){chars+="'"}else{literal=true}break;default:chars+=format.charAt(iFormat)}}}return chars},_get:function(inst,name){return inst.settings[name]!==undefined?inst.settings[name]:this._defaults[name]},_setDateFromField:function(inst){var dateFormat=this._get(inst,"dateFormat");var dates=inst.input?inst.input.val():null;inst.endDay=inst.endMonth=inst.endYear=null;var date=defaultDate=this._getDefaultDate(inst);var settings=this._getFormatConfig(inst);try{date=this.parseDate(dateFormat,dates,settings)||defaultDate}catch(event){this.log(event);date=defaultDate}inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear();inst.currentDay=(dates?date.getDate():0);inst.currentMonth=(dates?date.getMonth():0);inst.currentYear=(dates?date.getFullYear():0);this._adjustInstDate(inst)},_getDefaultDate:function(inst){var date=this._determineDate(this._get(inst,"defaultDate"),new Date());var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);return date},_determineDate:function(date,defaultDate){var offsetNumeric=function(offset){var date=new Date();date.setDate(date.getDate()+offset);return date};var offsetString=function(offset,getDaysInMonth){var date=new Date();var year=date.getFullYear();var month=date.getMonth();var day=date.getDate();var pattern=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;var matches=pattern.exec(offset);while(matches){switch(matches[2]||"d"){case"d":case"D":day+=parseInt(matches[1],10);break;case"w":case"W":day+=parseInt(matches[1],10)*7;break;case"m":case"M":month+=parseInt(matches[1],10);day=Math.min(day,getDaysInMonth(year,month));break;case"y":case"Y":year+=parseInt(matches[1],10);day=Math.min(day,getDaysInMonth(year,month));break}matches=pattern.exec(offset)}return new Date(year,month,day)};date=(date==null?defaultDate:(typeof date=="string"?offsetString(date,this._getDaysInMonth):(typeof date=="number"?(isNaN(date)?defaultDate:offsetNumeric(date)):date)));date=(date&&date.toString()=="Invalid Date"?defaultDate:date);if(date){date.setHours(0);date.setMinutes(0);date.setSeconds(0);date.setMilliseconds(0)}return this._daylightSavingAdjust(date)},_daylightSavingAdjust:function(date){if(!date){return null}date.setHours(date.getHours()>12?date.getHours()+2:0);return date},_setDate:function(inst,date,endDate){var clear=!(date);var origMonth=inst.selectedMonth;var origYear=inst.selectedYear;date=this._determineDate(date,new Date());inst.selectedDay=inst.currentDay=date.getDate();inst.drawMonth=inst.selectedMonth=inst.currentMonth=date.getMonth();inst.drawYear=inst.selectedYear=inst.currentYear=date.getFullYear();if(origMonth!=inst.selectedMonth||origYear!=inst.selectedYear){this._notifyChange(inst)}this._adjustInstDate(inst);if(inst.input){inst.input.val(clear?"":this._formatDate(inst))}},_getDate:function(inst){var startDate=(!inst.currentYear||(inst.input&&inst.input.val()=="")?null:this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));return startDate},_generateHTML:function(inst){var today=new Date();today=this._daylightSavingAdjust(new Date(today.getFullYear(),today.getMonth(),today.getDate()));var isRTL=this._get(inst,"isRTL");var showButtonPanel=this._get(inst,"showButtonPanel");var hideIfNoPrevNext=this._get(inst,"hideIfNoPrevNext");var navigationAsDateFormat=this._get(inst,"navigationAsDateFormat");var numMonths=this._getNumberOfMonths(inst);var showCurrentAtPos=this._get(inst,"showCurrentAtPos");var stepMonths=this._get(inst,"stepMonths");var stepBigMonths=this._get(inst,"stepBigMonths");var isMultiMonth=(numMonths[0]!=1||numMonths[1]!=1);var currentDate=this._daylightSavingAdjust((!inst.currentDay?new Date(9999,9,9):new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");var drawMonth=inst.drawMonth-showCurrentAtPos;var drawYear=inst.drawYear;if(drawMonth<0){drawMonth+=12;drawYear--}if(maxDate){var maxDraw=this._daylightSavingAdjust(new Date(maxDate.getFullYear(),maxDate.getMonth()-numMonths[1]+1,maxDate.getDate()));maxDraw=(minDate&&maxDraw<minDate?minDate:maxDraw);while(this._daylightSavingAdjust(new Date(drawYear,drawMonth,1))>maxDraw){drawMonth--;if(drawMonth<0){drawMonth=11;drawYear--}}}inst.drawMonth=drawMonth;inst.drawYear=drawYear;var prevText=this._get(inst,"prevText");prevText=(!navigationAsDateFormat?prevText:this.formatDate(prevText,this._daylightSavingAdjust(new Date(drawYear,drawMonth-stepMonths,1)),this._getFormatConfig(inst)));var prev=(this._canAdjustMonth(inst,-1,drawYear,drawMonth)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+"', -"+stepMonths+", 'M');\" title=\""+prevText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"e":"w")+'">'+prevText+"</span></a>":(hideIfNoPrevNext?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+prevText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"e":"w")+'">'+prevText+"</span></a>"));var nextText=this._get(inst,"nextText");nextText=(!navigationAsDateFormat?nextText:this.formatDate(nextText,this._daylightSavingAdjust(new Date(drawYear,drawMonth+stepMonths,1)),this._getFormatConfig(inst)));var next=(this._canAdjustMonth(inst,+1,drawYear,drawMonth)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+"', +"+stepMonths+", 'M');\" title=\""+nextText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"w":"e")+'">'+nextText+"</span></a>":(hideIfNoPrevNext?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+nextText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"w":"e")+'">'+nextText+"</span></a>"));var currentText=this._get(inst,"currentText");var gotoDate=(this._get(inst,"gotoCurrent")&&inst.currentDay?currentDate:today);currentText=(!navigationAsDateFormat?currentText:this.formatDate(currentText,gotoDate,this._getFormatConfig(inst)));var controls=(!inst.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">'+this._get(inst,"closeText")+"</button>":"");var buttonPanel=(showButtonPanel)?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(isRTL?controls:"")+(this._isInRange(inst,gotoDate)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#'+inst.id+"');\">"+currentText+"</button>":"")+(isRTL?"":controls)+"</div>":"";var firstDay=parseInt(this._get(inst,"firstDay"),10);firstDay=(isNaN(firstDay)?0:firstDay);var dayNames=this._get(inst,"dayNames");var dayNamesShort=this._get(inst,"dayNamesShort");var dayNamesMin=this._get(inst,"dayNamesMin");var monthNames=this._get(inst,"monthNames");var monthNamesShort=this._get(inst,"monthNamesShort");var beforeShowDay=this._get(inst,"beforeShowDay");var showOtherMonths=this._get(inst,"showOtherMonths");var calculateWeek=this._get(inst,"calculateWeek")||this.iso8601Week;var endDate=inst.endDay?this._daylightSavingAdjust(new Date(inst.endYear,inst.endMonth,inst.endDay)):currentDate;var defaultDate=this._getDefaultDate(inst);var html="";for(var row=0;row<numMonths[0];row++){var group="";for(var col=0;col<numMonths[1];col++){var selectedDate=this._daylightSavingAdjust(new Date(drawYear,drawMonth,inst.selectedDay));var cornerClass=" ui-corner-all";var calender="";if(isMultiMonth){calender+='<div class="ui-datepicker-group ui-datepicker-group-';switch(col){case 0:calender+="first";cornerClass=" ui-corner-"+(isRTL?"right":"left");break;case numMonths[1]-1:calender+="last";cornerClass=" ui-corner-"+(isRTL?"left":"right");break;default:calender+="middle";cornerClass="";break}calender+='">'}calender+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+cornerClass+'">'+(/all|left/.test(cornerClass)&&row==0?(isRTL?next:prev):"")+(/all|right/.test(cornerClass)&&row==0?(isRTL?prev:next):"")+this._generateMonthYearHeader(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,row>0||col>0,monthNames,monthNamesShort)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var thead="";for(var dow=0;dow<7;dow++){var day=(dow+firstDay)%7;thead+="<th"+((dow+firstDay+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+dayNames[day]+'">'+dayNamesMin[day]+"</span></th>"}calender+=thead+"</tr></thead><tbody>";var daysInMonth=this._getDaysInMonth(drawYear,drawMonth);if(drawYear==inst.selectedYear&&drawMonth==inst.selectedMonth){inst.selectedDay=Math.min(inst.selectedDay,daysInMonth)}var leadDays=(this._getFirstDayOfMonth(drawYear,drawMonth)-firstDay+7)%7;var numRows=(isMultiMonth?6:Math.ceil((leadDays+daysInMonth)/7));var printDate=this._daylightSavingAdjust(new Date(drawYear,drawMonth,1-leadDays));for(var dRow=0;dRow<numRows;dRow++){calender+="<tr>";var tbody="";for(var dow=0;dow<7;dow++){var daySettings=(beforeShowDay?beforeShowDay.apply((inst.input?inst.input[0]:null),[printDate]):[true,""]);var otherMonth=(printDate.getMonth()!=drawMonth);var unselectable=otherMonth||!daySettings[0]||(minDate&&printDate<minDate)||(maxDate&&printDate>maxDate);tbody+='<td class="'+((dow+firstDay+6)%7>=5?" ui-datepicker-week-end":"")+(otherMonth?" ui-datepicker-other-month":"")+((printDate.getTime()==selectedDate.getTime()&&drawMonth==inst.selectedMonth&&inst._keyEvent)||(defaultDate.getTime()==printDate.getTime()&&defaultDate.getTime()==selectedDate.getTime())?" "+this._dayOverClass:"")+(unselectable?" "+this._unselectableClass+" ui-state-disabled":"")+(otherMonth&&!showOtherMonths?"":" "+daySettings[1]+(printDate.getTime()>=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?" "+this._currentClass:"")+(printDate.getTime()==today.getTime()?" ui-datepicker-today":""))+'"'+((!otherMonth||showOtherMonths)&&daySettings[2]?' title="'+daySettings[2]+'"':"")+(unselectable?"":" onclick=\"DP_jQuery.datepicker._selectDay('#"+inst.id+"',"+drawMonth+","+drawYear+', this);return false;"')+">"+(otherMonth?(showOtherMonths?printDate.getDate():"&#xa0;"):(unselectable?'<span class="ui-state-default">'+printDate.getDate()+"</span>":'<a class="ui-state-default'+(printDate.getTime()==today.getTime()?" ui-state-highlight":"")+(printDate.getTime()>=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?" ui-state-active":"")+'" href="#">'+printDate.getDate()+"</a>"))+"</td>";printDate.setDate(printDate.getDate()+1);printDate=this._daylightSavingAdjust(printDate)}calender+=tbody+"</tr>"}drawMonth++;if(drawMonth>11){drawMonth=0;drawYear++}calender+="</tbody></table>"+(isMultiMonth?"</div>"+((numMonths[0]>0&&col==numMonths[1]-1)?'<div class="ui-datepicker-row-break"></div>':""):"");group+=calender}html+=group}html+=buttonPanel+($.browser.msie&&parseInt($.browser.version,10)<7&&!inst.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':"");inst._keyEvent=false;return html},_generateMonthYearHeader:function(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,secondary,monthNames,monthNamesShort){minDate=(inst.rangeStart&&minDate&&selectedDate<minDate?selectedDate:minDate);var changeMonth=this._get(inst,"changeMonth");var changeYear=this._get(inst,"changeYear");var showMonthAfterYear=this._get(inst,"showMonthAfterYear");var html='<div class="ui-datepicker-title">';var monthHtml="";if(secondary||!changeMonth){monthHtml+='<span class="ui-datepicker-month">'+monthNames[drawMonth]+"</span> "}else{var inMinYear=(minDate&&minDate.getFullYear()==drawYear);var inMaxYear=(maxDate&&maxDate.getFullYear()==drawYear);monthHtml+='<select class="ui-datepicker-month" onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+"', this, 'M');\" onclick=\"DP_jQuery.datepicker._clickMonthYear('#"+inst.id+"');\">";for(var month=0;month<12;month++){if((!inMinYear||month>=minDate.getMonth())&&(!inMaxYear||month<=maxDate.getMonth())){monthHtml+='<option value="'+month+'"'+(month==drawMonth?' selected="selected"':"")+">"+monthNamesShort[month]+"</option>"}}monthHtml+="</select>"}if(!showMonthAfterYear){html+=monthHtml+((secondary||changeMonth||changeYear)&&(!(changeMonth&&changeYear))?"&#xa0;":"")}if(secondary||!changeYear){html+='<span class="ui-datepicker-year">'+drawYear+"</span>"}else{var years=this._get(inst,"yearRange").split(":");var year=0;var endYear=0;if(years.length!=2){year=drawYear-10;endYear=drawYear+10}else{if(years[0].charAt(0)=="+"||years[0].charAt(0)=="-"){year=drawYear+parseInt(years[0],10);endYear=drawYear+parseInt(years[1],10)}else{year=parseInt(years[0],10);endYear=parseInt(years[1],10)}}year=(minDate?Math.max(year,minDate.getFullYear()):year);endYear=(maxDate?Math.min(endYear,maxDate.getFullYear()):endYear);html+='<select class="ui-datepicker-year" onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+"', this, 'Y');\" onclick=\"DP_jQuery.datepicker._clickMonthYear('#"+inst.id+"');\">";for(;year<=endYear;year++){html+='<option value="'+year+'"'+(year==drawYear?' selected="selected"':"")+">"+year+"</option>"}html+="</select>"}if(showMonthAfterYear){html+=(secondary||changeMonth||changeYear?"&#xa0;":"")+monthHtml}html+="</div>";return html},_adjustInstDate:function(inst,offset,period){var year=inst.drawYear+(period=="Y"?offset:0);var month=inst.drawMonth+(period=="M"?offset:0);var day=Math.min(inst.selectedDay,this._getDaysInMonth(year,month))+(period=="D"?offset:0);var date=this._daylightSavingAdjust(new Date(year,month,day));var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear();if(period=="M"||period=="Y"){this._notifyChange(inst)}},_notifyChange:function(inst){var onChange=this._get(inst,"onChangeMonthYear");if(onChange){onChange.apply((inst.input?inst.input[0]:null),[inst.selectedYear,inst.selectedMonth+1,inst])}},_getNumberOfMonths:function(inst){var numMonths=this._get(inst,"numberOfMonths");return(numMonths==null?[1,1]:(typeof numMonths=="number"?[1,numMonths]:numMonths))},_getMinMaxDate:function(inst,minMax,checkRange){var date=this._determineDate(this._get(inst,minMax+"Date"),null);return(!checkRange||!inst.rangeStart?date:(!date||inst.rangeStart>date?inst.rangeStart:date))},_getDaysInMonth:function(year,month){return 32-new Date(year,month,32).getDate()},_getFirstDayOfMonth:function(year,month){return new Date(year,month,1).getDay()},_canAdjustMonth:function(inst,offset,curYear,curMonth){var numMonths=this._getNumberOfMonths(inst);var date=this._daylightSavingAdjust(new Date(curYear,curMonth+(offset<0?offset:numMonths[1]),1));if(offset<0){date.setDate(this._getDaysInMonth(date.getFullYear(),date.getMonth()))}return this._isInRange(inst,date)},_isInRange:function(inst,date){var newMinDate=(!inst.rangeStart?null:this._daylightSavingAdjust(new Date(inst.selectedYear,inst.selectedMonth,inst.selectedDay)));newMinDate=(newMinDate&&inst.rangeStart<newMinDate?inst.rangeStart:newMinDate);var minDate=newMinDate||this._getMinMaxDate(inst,"min");var maxDate=this._getMinMaxDate(inst,"max");return((!minDate||date>=minDate)&&(!maxDate||date<=maxDate))},_getFormatConfig:function(inst){var shortYearCutoff=this._get(inst,"shortYearCutoff");shortYearCutoff=(typeof shortYearCutoff!="string"?shortYearCutoff:new Date().getFullYear()%100+parseInt(shortYearCutoff,10));return{shortYearCutoff:shortYearCutoff,dayNamesShort:this._get(inst,"dayNamesShort"),dayNames:this._get(inst,"dayNames"),monthNamesShort:this._get(inst,"monthNamesShort"),monthNames:this._get(inst,"monthNames")}},_formatDate:function(inst,day,month,year){if(!day){inst.currentDay=inst.selectedDay;inst.currentMonth=inst.selectedMonth;inst.currentYear=inst.selectedYear}var date=(day?(typeof day=="object"?day:this._daylightSavingAdjust(new Date(year,month,day))):this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));return this.formatDate(this._get(inst,"dateFormat"),date,this._getFormatConfig(inst))}});function extendRemove(target,props){$.extend(target,props);for(var name in props){if(props[name]==null||props[name]==undefined){target[name]=props[name]}}return target}function isArray(a){return(a&&(($.browser.safari&&typeof a=="object"&&a.length)||(a.constructor&&a.constructor.toString().match(/\Array\(\)/))))}$.fn.datepicker=function(options){if(!$.datepicker.initialized){$(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv);$.datepicker.initialized=true}var otherArgs=Array.prototype.slice.call(arguments,1);if(typeof options=="string"&&(options=="isDisabled"||options=="getDate")){return $.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this[0]].concat(otherArgs))}if(options=="option"&&arguments.length==2&&typeof arguments[1]=="string"){return $.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this[0]].concat(otherArgs))}return this.each(function(){typeof options=="string"?$.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this].concat(otherArgs)):$.datepicker._attachDatepicker(this,options)})};$.datepicker=new Datepicker();$.datepicker.initialized=false;$.datepicker.uuid=new Date().getTime();$.datepicker.version="1.7.2";window.DP_jQuery=$})(jQuery);;/*
+ * jQuery UI Progressbar 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Progressbar
+ *
+ * Depends:
+ *   ui.core.js
+ */
+(function(a){a.widget("ui.progressbar",{_init:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this._valueMin(),"aria-valuemax":this._valueMax(),"aria-valuenow":this._value()});this.valueDiv=a('<div class="ui-progressbar-value ui-widget-header ui-corner-left"></div>').appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow").removeData("progressbar").unbind(".progressbar");this.valueDiv.remove();a.widget.prototype.destroy.apply(this,arguments)},value:function(b){if(b===undefined){return this._value()}this._setData("value",b);return this},_setData:function(b,c){switch(b){case"value":this.options.value=c;this._refreshValue();this._trigger("change",null,{});break}a.widget.prototype._setData.apply(this,arguments)},_value:function(){var b=this.options.value;if(b<this._valueMin()){b=this._valueMin()}if(b>this._valueMax()){b=this._valueMax()}return b},_valueMin:function(){var b=0;return b},_valueMax:function(){var b=100;return b},_refreshValue:function(){var b=this.value();this.valueDiv[b==this._valueMax()?"addClass":"removeClass"]("ui-corner-right");this.valueDiv.width(b+"%");this.element.attr("aria-valuenow",b)}});a.extend(a.ui.progressbar,{version:"1.7.2",defaults:{value:0}})})(jQuery);;/*
+ * jQuery UI Effects 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/
+ */
+jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(var f=0;f<h.length;f++){if(h[f]!==null){g.data("ec.storage."+h[f],g[0].style[h[f]])}}},restore:function(g,h){for(var f=0;f<h.length;f++){if(h[f]!==null){g.css(h[f],g.data("ec.storage."+h[f]))}}},setMode:function(f,g){if(g=="toggle"){g=f.is(":hidden")?"show":"hide"}return g},getBaseline:function(g,h){var i,f;switch(g[0]){case"top":i=0;break;case"middle":i=0.5;break;case"bottom":i=1;break;default:i=g[0]/h.height}switch(g[1]){case"left":f=0;break;case"center":f=0.5;break;case"right":f=1;break;default:f=g[1]/h.width}return{x:f,y:i}},createWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent()}var g={width:f.outerWidth(true),height:f.outerHeight(true),"float":f.css("float")};f.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');var j=f.parent();if(f.css("position")=="static"){j.css({position:"relative"});f.css({position:"relative"})}else{var i=f.css("top");if(isNaN(parseInt(i,10))){i="auto"}var h=f.css("left");if(isNaN(parseInt(h,10))){h="auto"}j.css({position:f.css("position"),top:i,left:h,zIndex:f.css("z-index")}).show();f.css({position:"relative",top:0,left:0})}j.css(g);return j},removeWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent().replaceWith(f)}return f},setTransition:function(g,i,f,h){h=h||{};d.each(i,function(k,j){unit=g.cssUnit(j);if(unit[0]>0){h[j]=unit[0]*f+unit[1]}});return h},animateClass:function(h,i,k,j){var f=(typeof k=="function"?k:(j?j:null));var g=(typeof k=="string"?k:null);return this.each(function(){var q={};var o=d(this);var p=o.attr("style")||"";if(typeof p=="object"){p=p.cssText}if(h.toggle){o.hasClass(h.toggle)?h.remove=h.toggle:h.add=h.toggle}var l=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.addClass(h.add)}if(h.remove){o.removeClass(h.remove)}var m=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.removeClass(h.add)}if(h.remove){o.addClass(h.remove)}for(var r in m){if(typeof m[r]!="function"&&m[r]&&r.indexOf("Moz")==-1&&r.indexOf("length")==-1&&m[r]!=l[r]&&(r.match(/color/i)||(!r.match(/color/i)&&!isNaN(parseInt(m[r],10))))&&(l.position!="static"||(l.position=="static"&&!r.match(/left|top|bottom|right/)))){q[r]=m[r]}}o.animate(q,i,g,function(){if(typeof d(this).attr("style")=="object"){d(this).attr("style")["cssText"]="";d(this).attr("style")["cssText"]=p}else{d(this).attr("style",p)}if(h.add){d(this).addClass(h.add)}if(h.remove){d(this).removeClass(h.remove)}if(f){f.apply(this,arguments)}})})}};function c(g,f){var i=g[1]&&g[1].constructor==Object?g[1]:{};if(f){i.mode=f}var h=g[1]&&g[1].constructor!=Object?g[1]:(i.duration?i.duration:g[2]);h=d.fx.off?0:typeof h==="number"?h:d.fx.speeds[h]||d.fx.speeds._default;var j=i.callback||(d.isFunction(g[1])&&g[1])||(d.isFunction(g[2])&&g[2])||(d.isFunction(g[3])&&g[3]);return[g[0],i,h,j]}d.fn.extend({_show:d.fn.show,_hide:d.fn.hide,__toggle:d.fn.toggle,_addClass:d.fn.addClass,_removeClass:d.fn.removeClass,_toggleClass:d.fn.toggleClass,effect:function(g,f,h,i){return d.effects[g]?d.effects[g].call(this,{method:g,options:f||{},duration:h,callback:i}):null},show:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._show.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"show"))}},hide:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._hide.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"hide"))}},toggle:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))||(d.isFunction(arguments[0])||typeof arguments[0]=="boolean")){return this.__toggle.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"toggle"))}},addClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{add:g},f,i,h]):this._addClass(g)},removeClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{remove:g},f,i,h]):this._removeClass(g)},toggleClass:function(g,f,i,h){return((typeof f!=="boolean")&&f)?d.effects.animateClass.apply(this,[{toggle:g},f,i,h]):this._toggleClass(g,f)},morph:function(f,h,g,j,i){return d.effects.animateClass.apply(this,[{add:h,remove:f},g,j,i])},switchClass:function(){return this.morph.apply(this,arguments)},cssUnit:function(f){var g=this.css(f),h=[];d.each(["em","px","%","pt"],function(j,k){if(g.indexOf(k)>0){h=[parseFloat(g),k]}});return h}});d.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(g,f){d.fx.step[f]=function(h){if(h.state==0){h.start=e(h.elem,f);h.end=b(h.end)}h.elem.style[f]="rgb("+[Math.max(Math.min(parseInt((h.pos*(h.end[0]-h.start[0]))+h.start[0],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[1]-h.start[1]))+h.start[1],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[2]-h.start[2]))+h.start[2],10),255),0)].join(",")+")"}});function b(g){var f;if(g&&g.constructor==Array&&g.length==3){return g}if(f=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(g)){return[parseInt(f[1],10),parseInt(f[2],10),parseInt(f[3],10)]}if(f=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(g)){return[parseFloat(f[1])*2.55,parseFloat(f[2])*2.55,parseFloat(f[3])*2.55]}if(f=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(g)){return[parseInt(f[1],16),parseInt(f[2],16),parseInt(f[3],16)]}if(f=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(g)){return[parseInt(f[1]+f[1],16),parseInt(f[2]+f[2],16),parseInt(f[3]+f[3],16)]}if(f=/rgba\(0, 0, 0, 0\)/.exec(g)){return a.transparent}return a[d.trim(g).toLowerCase()]}function e(h,f){var g;do{g=d.curCSS(h,f);if(g!=""&&g!="transparent"||d.nodeName(h,"body")){break}f="backgroundColor"}while(h=h.parentNode);return b(g)}var a={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]};d.easing.jswing=d.easing.swing;d.extend(d.easing,{def:"easeOutQuad",swing:function(g,h,f,j,i){return d.easing[d.easing.def](g,h,f,j,i)},easeInQuad:function(g,h,f,j,i){return j*(h/=i)*h+f},easeOutQuad:function(g,h,f,j,i){return -j*(h/=i)*(h-2)+f},easeInOutQuad:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h+f}return -j/2*((--h)*(h-2)-1)+f},easeInCubic:function(g,h,f,j,i){return j*(h/=i)*h*h+f},easeOutCubic:function(g,h,f,j,i){return j*((h=h/i-1)*h*h+1)+f},easeInOutCubic:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h+f}return j/2*((h-=2)*h*h+2)+f},easeInQuart:function(g,h,f,j,i){return j*(h/=i)*h*h*h+f},easeOutQuart:function(g,h,f,j,i){return -j*((h=h/i-1)*h*h*h-1)+f},easeInOutQuart:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h+f}return -j/2*((h-=2)*h*h*h-2)+f},easeInQuint:function(g,h,f,j,i){return j*(h/=i)*h*h*h*h+f},easeOutQuint:function(g,h,f,j,i){return j*((h=h/i-1)*h*h*h*h+1)+f},easeInOutQuint:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h*h+f}return j/2*((h-=2)*h*h*h*h+2)+f},easeInSine:function(g,h,f,j,i){return -j*Math.cos(h/i*(Math.PI/2))+j+f},easeOutSine:function(g,h,f,j,i){return j*Math.sin(h/i*(Math.PI/2))+f},easeInOutSine:function(g,h,f,j,i){return -j/2*(Math.cos(Math.PI*h/i)-1)+f},easeInExpo:function(g,h,f,j,i){return(h==0)?f:j*Math.pow(2,10*(h/i-1))+f},easeOutExpo:function(g,h,f,j,i){return(h==i)?f+j:j*(-Math.pow(2,-10*h/i)+1)+f},easeInOutExpo:function(g,h,f,j,i){if(h==0){return f}if(h==i){return f+j}if((h/=i/2)<1){return j/2*Math.pow(2,10*(h-1))+f}return j/2*(-Math.pow(2,-10*--h)+2)+f},easeInCirc:function(g,h,f,j,i){return -j*(Math.sqrt(1-(h/=i)*h)-1)+f},easeOutCirc:function(g,h,f,j,i){return j*Math.sqrt(1-(h=h/i-1)*h)+f},easeInOutCirc:function(g,h,f,j,i){if((h/=i/2)<1){return -j/2*(Math.sqrt(1-h*h)-1)+f}return j/2*(Math.sqrt(1-(h-=2)*h)+1)+f},easeInElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l)==1){return f+m}if(!k){k=l*0.3}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}return -(h*Math.pow(2,10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k))+f},easeOutElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l)==1){return f+m}if(!k){k=l*0.3}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}return h*Math.pow(2,-10*i)*Math.sin((i*l-j)*(2*Math.PI)/k)+m+f},easeInOutElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l/2)==2){return f+m}if(!k){k=l*(0.3*1.5)}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}if(i<1){return -0.5*(h*Math.pow(2,10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k))+f}return h*Math.pow(2,-10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k)*0.5+m+f},easeInBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}return k*(h/=j)*h*((i+1)*h-i)+f},easeOutBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}return k*((h=h/j-1)*h*((i+1)*h+i)+1)+f},easeInOutBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}if((h/=j/2)<1){return k/2*(h*h*(((i*=(1.525))+1)*h-i))+f}return k/2*((h-=2)*h*(((i*=(1.525))+1)*h+i)+2)+f},easeInBounce:function(g,h,f,j,i){return j-d.easing.easeOutBounce(g,i-h,0,j,i)+f},easeOutBounce:function(g,h,f,j,i){if((h/=i)<(1/2.75)){return j*(7.5625*h*h)+f}else{if(h<(2/2.75)){return j*(7.5625*(h-=(1.5/2.75))*h+0.75)+f}else{if(h<(2.5/2.75)){return j*(7.5625*(h-=(2.25/2.75))*h+0.9375)+f}else{return j*(7.5625*(h-=(2.625/2.75))*h+0.984375)+f}}}},easeInOutBounce:function(g,h,f,j,i){if(h<i/2){return d.easing.easeInBounce(g,h*2,0,j,i)*0.5+f}return d.easing.easeOutBounce(g,h*2-i,0,j,i)*0.5+j*0.5+f}})})(jQuery);;/*
+ * jQuery UI Effects Blind 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Blind
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.blind=function(b){return this.queue(function(){var d=a(this),c=["position","top","left"];var h=a.effects.setMode(d,b.options.mode||"hide");var g=b.options.direction||"vertical";a.effects.save(d,c);d.show();var j=a.effects.createWrapper(d).css({overflow:"hidden"});var e=(g=="vertical")?"height":"width";var i=(g=="vertical")?j.height():j.width();if(h=="show"){j.css(e,0)}var f={};f[e]=h=="show"?i:0;j.animate(f,b.duration,b.options.easing,function(){if(h=="hide"){d.hide()}a.effects.restore(d,c);a.effects.removeWrapper(d);if(b.callback){b.callback.apply(d[0],arguments)}d.dequeue()})})}})(jQuery);;/*
+ * jQuery UI Effects Bounce 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Bounce
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.bounce=function(b){return this.queue(function(){var e=a(this),l=["position","top","left"];var k=a.effects.setMode(e,b.options.mode||"effect");var n=b.options.direction||"up";var c=b.options.distance||20;var d=b.options.times||5;var g=b.duration||250;if(/show|hide/.test(k)){l.push("opacity")}a.effects.save(e,l);e.show();a.effects.createWrapper(e);var f=(n=="up"||n=="down")?"top":"left";var p=(n=="up"||n=="left")?"pos":"neg";var c=b.options.distance||(f=="top"?e.outerHeight({margin:true})/3:e.outerWidth({margin:true})/3);if(k=="show"){e.css("opacity",0).css(f,p=="pos"?-c:c)}if(k=="hide"){c=c/(d*2)}if(k!="hide"){d--}if(k=="show"){var h={opacity:1};h[f]=(p=="pos"?"+=":"-=")+c;e.animate(h,g/2,b.options.easing);c=c/2;d--}for(var j=0;j<d;j++){var o={},m={};o[f]=(p=="pos"?"-=":"+=")+c;m[f]=(p=="pos"?"+=":"-=")+c;e.animate(o,g/2,b.options.easing).animate(m,g/2,b.options.easing);c=(k=="hide")?c*2:c/2}if(k=="hide"){var h={opacity:0};h[f]=(p=="pos"?"-=":"+=")+c;e.animate(h,g/2,b.options.easing,function(){e.hide();a.effects.restore(e,l);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}})}else{var o={},m={};o[f]=(p=="pos"?"-=":"+=")+c;m[f]=(p=="pos"?"+=":"-=")+c;e.animate(o,g/2,b.options.easing).animate(m,g/2,b.options.easing,function(){a.effects.restore(e,l);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}})}e.queue("fx",function(){e.dequeue()});e.dequeue()})}})(jQuery);;/*
+ * jQuery UI Effects Clip 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Clip
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.clip=function(b){return this.queue(function(){var f=a(this),j=["position","top","left","height","width"];var i=a.effects.setMode(f,b.options.mode||"hide");var k=b.options.direction||"vertical";a.effects.save(f,j);f.show();var c=a.effects.createWrapper(f).css({overflow:"hidden"});var e=f[0].tagName=="IMG"?c:f;var g={size:(k=="vertical")?"height":"width",position:(k=="vertical")?"top":"left"};var d=(k=="vertical")?e.height():e.width();if(i=="show"){e.css(g.size,0);e.css(g.position,d/2)}var h={};h[g.size]=i=="show"?d:0;h[g.position]=i=="show"?0:d/2;e.animate(h,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(i=="hide"){f.hide()}a.effects.restore(f,j);a.effects.removeWrapper(f);if(b.callback){b.callback.apply(f[0],arguments)}f.dequeue()}})})}})(jQuery);;/*
+ * jQuery UI Effects Drop 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Drop
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.drop=function(b){return this.queue(function(){var e=a(this),d=["position","top","left","opacity"];var i=a.effects.setMode(e,b.options.mode||"hide");var h=b.options.direction||"left";a.effects.save(e,d);e.show();a.effects.createWrapper(e);var f=(h=="up"||h=="down")?"top":"left";var c=(h=="up"||h=="left")?"pos":"neg";var j=b.options.distance||(f=="top"?e.outerHeight({margin:true})/2:e.outerWidth({margin:true})/2);if(i=="show"){e.css("opacity",0).css(f,c=="pos"?-j:j)}var g={opacity:i=="show"?1:0};g[f]=(i=="show"?(c=="pos"?"+=":"-="):(c=="pos"?"-=":"+="))+j;e.animate(g,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(i=="hide"){e.hide()}a.effects.restore(e,d);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);;/*
+ * jQuery UI Effects Explode 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Explode
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.explode=function(b){return this.queue(function(){var k=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3;var e=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3;b.options.mode=b.options.mode=="toggle"?(a(this).is(":visible")?"hide":"show"):b.options.mode;var h=a(this).show().css("visibility","hidden");var l=h.offset();l.top-=parseInt(h.css("marginTop"),10)||0;l.left-=parseInt(h.css("marginLeft"),10)||0;var g=h.outerWidth(true);var c=h.outerHeight(true);for(var f=0;f<k;f++){for(var d=0;d<e;d++){h.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-d*(g/e),top:-f*(c/k)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:g/e,height:c/k,left:l.left+d*(g/e)+(b.options.mode=="show"?(d-Math.floor(e/2))*(g/e):0),top:l.top+f*(c/k)+(b.options.mode=="show"?(f-Math.floor(k/2))*(c/k):0),opacity:b.options.mode=="show"?0:1}).animate({left:l.left+d*(g/e)+(b.options.mode=="show"?0:(d-Math.floor(e/2))*(g/e)),top:l.top+f*(c/k)+(b.options.mode=="show"?0:(f-Math.floor(k/2))*(c/k)),opacity:b.options.mode=="show"?1:0},b.duration||500)}}setTimeout(function(){b.options.mode=="show"?h.css({visibility:"visible"}):h.css({visibility:"visible"}).hide();if(b.callback){b.callback.apply(h[0])}h.dequeue();a("div.ui-effects-explode").remove()},b.duration||500)})}})(jQuery);;/*
+ * jQuery UI Effects Fold 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Fold
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.fold=function(b){return this.queue(function(){var e=a(this),k=["position","top","left"];var h=a.effects.setMode(e,b.options.mode||"hide");var o=b.options.size||15;var n=!(!b.options.horizFirst);var g=b.duration?b.duration/2:a.fx.speeds._default/2;a.effects.save(e,k);e.show();var d=a.effects.createWrapper(e).css({overflow:"hidden"});var i=((h=="show")!=n);var f=i?["width","height"]:["height","width"];var c=i?[d.width(),d.height()]:[d.height(),d.width()];var j=/([0-9]+)%/.exec(o);if(j){o=parseInt(j[1],10)/100*c[h=="hide"?0:1]}if(h=="show"){d.css(n?{height:0,width:o}:{height:o,width:0})}var m={},l={};m[f[0]]=h=="show"?c[0]:o;l[f[1]]=h=="show"?c[1]:0;d.animate(m,g,b.options.easing).animate(l,g,b.options.easing,function(){if(h=="hide"){e.hide()}a.effects.restore(e,k);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(e[0],arguments)}e.dequeue()})})}})(jQuery);;/*
+ * jQuery UI Effects Highlight 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Highlight
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.highlight=function(b){return this.queue(function(){var e=a(this),d=["backgroundImage","backgroundColor","opacity"];var h=a.effects.setMode(e,b.options.mode||"show");var c=b.options.color||"#ffff99";var g=e.css("backgroundColor");a.effects.save(e,d);e.show();e.css({backgroundImage:"none",backgroundColor:c});var f={backgroundColor:g};if(h=="hide"){f.opacity=0}e.animate(f,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(h=="hide"){e.hide()}a.effects.restore(e,d);if(h=="show"&&a.browser.msie){this.style.removeAttribute("filter")}if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);;/*
+ * jQuery UI Effects Pulsate 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Pulsate
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.pulsate=function(b){return this.queue(function(){var d=a(this);var g=a.effects.setMode(d,b.options.mode||"show");var f=b.options.times||5;var e=b.duration?b.duration/2:a.fx.speeds._default/2;if(g=="hide"){f--}if(d.is(":hidden")){d.css("opacity",0);d.show();d.animate({opacity:1},e,b.options.easing);f=f-2}for(var c=0;c<f;c++){d.animate({opacity:0},e,b.options.easing).animate({opacity:1},e,b.options.easing)}if(g=="hide"){d.animate({opacity:0},e,b.options.easing,function(){d.hide();if(b.callback){b.callback.apply(this,arguments)}})}else{d.animate({opacity:0},e,b.options.easing).animate({opacity:1},e,b.options.easing,function(){if(b.callback){b.callback.apply(this,arguments)}})}d.queue("fx",function(){d.dequeue()});d.dequeue()})}})(jQuery);;/*
+ * jQuery UI Effects Scale 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Scale
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.puff=function(b){return this.queue(function(){var f=a(this);var c=a.extend(true,{},b.options);var h=a.effects.setMode(f,b.options.mode||"hide");var g=parseInt(b.options.percent,10)||150;c.fade=true;var e={height:f.height(),width:f.width()};var d=g/100;f.from=(h=="hide")?e:{height:e.height*d,width:e.width*d};c.from=f.from;c.percent=(h=="hide")?g:100;c.mode=h;f.effect("scale",c,b.duration,b.callback);f.dequeue()})};a.effects.scale=function(b){return this.queue(function(){var g=a(this);var d=a.extend(true,{},b.options);var j=a.effects.setMode(g,b.options.mode||"effect");var h=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:(j=="hide"?0:100));var i=b.options.direction||"both";var c=b.options.origin;if(j!="effect"){d.origin=c||["middle","center"];d.restore=true}var f={height:g.height(),width:g.width()};g.from=b.options.from||(j=="show"?{height:0,width:0}:f);var e={y:i!="horizontal"?(h/100):1,x:i!="vertical"?(h/100):1};g.to={height:f.height*e.y,width:f.width*e.x};if(b.options.fade){if(j=="show"){g.from.opacity=0;g.to.opacity=1}if(j=="hide"){g.from.opacity=1;g.to.opacity=0}}d.from=g.from;d.to=g.to;d.mode=j;g.effect("size",d,b.duration,b.callback);g.dequeue()})};a.effects.size=function(b){return this.queue(function(){var c=a(this),n=["position","top","left","width","height","overflow","opacity"];var m=["position","top","left","overflow","opacity"];var j=["width","height","overflow"];var p=["fontSize"];var k=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"];var f=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"];var g=a.effects.setMode(c,b.options.mode||"effect");var i=b.options.restore||false;var e=b.options.scale||"both";var o=b.options.origin;var d={height:c.height(),width:c.width()};c.from=b.options.from||d;c.to=b.options.to||d;if(o){var h=a.effects.getBaseline(o,d);c.from.top=(d.height-c.from.height)*h.y;c.from.left=(d.width-c.from.width)*h.x;c.to.top=(d.height-c.to.height)*h.y;c.to.left=(d.width-c.to.width)*h.x}var l={from:{y:c.from.height/d.height,x:c.from.width/d.width},to:{y:c.to.height/d.height,x:c.to.width/d.width}};if(e=="box"||e=="both"){if(l.from.y!=l.to.y){n=n.concat(k);c.from=a.effects.setTransition(c,k,l.from.y,c.from);c.to=a.effects.setTransition(c,k,l.to.y,c.to)}if(l.from.x!=l.to.x){n=n.concat(f);c.from=a.effects.setTransition(c,f,l.from.x,c.from);c.to=a.effects.setTransition(c,f,l.to.x,c.to)}}if(e=="content"||e=="both"){if(l.from.y!=l.to.y){n=n.concat(p);c.from=a.effects.setTransition(c,p,l.from.y,c.from);c.to=a.effects.setTransition(c,p,l.to.y,c.to)}}a.effects.save(c,i?n:m);c.show();a.effects.createWrapper(c);c.css("overflow","hidden").css(c.from);if(e=="content"||e=="both"){k=k.concat(["marginTop","marginBottom"]).concat(p);f=f.concat(["marginLeft","marginRight"]);j=n.concat(k).concat(f);c.find("*[width]").each(function(){child=a(this);if(i){a.effects.save(child,j)}var q={height:child.height(),width:child.width()};child.from={height:q.height*l.from.y,width:q.width*l.from.x};child.to={height:q.height*l.to.y,width:q.width*l.to.x};if(l.from.y!=l.to.y){child.from=a.effects.setTransition(child,k,l.from.y,child.from);child.to=a.effects.setTransition(child,k,l.to.y,child.to)}if(l.from.x!=l.to.x){child.from=a.effects.setTransition(child,f,l.from.x,child.from);child.to=a.effects.setTransition(child,f,l.to.x,child.to)}child.css(child.from);child.animate(child.to,b.duration,b.options.easing,function(){if(i){a.effects.restore(child,j)}})})}c.animate(c.to,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(g=="hide"){c.hide()}a.effects.restore(c,i?n:m);a.effects.removeWrapper(c);if(b.callback){b.callback.apply(this,arguments)}c.dequeue()}})})}})(jQuery);;/*
+ * jQuery UI Effects Shake 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Shake
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.shake=function(b){return this.queue(function(){var e=a(this),l=["position","top","left"];var k=a.effects.setMode(e,b.options.mode||"effect");var n=b.options.direction||"left";var c=b.options.distance||20;var d=b.options.times||3;var g=b.duration||b.options.duration||140;a.effects.save(e,l);e.show();a.effects.createWrapper(e);var f=(n=="up"||n=="down")?"top":"left";var p=(n=="up"||n=="left")?"pos":"neg";var h={},o={},m={};h[f]=(p=="pos"?"-=":"+=")+c;o[f]=(p=="pos"?"+=":"-=")+c*2;m[f]=(p=="pos"?"-=":"+=")+c*2;e.animate(h,g,b.options.easing);for(var j=1;j<d;j++){e.animate(o,g,b.options.easing).animate(m,g,b.options.easing)}e.animate(o,g,b.options.easing).animate(h,g/2,b.options.easing,function(){a.effects.restore(e,l);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}});e.queue("fx",function(){e.dequeue()});e.dequeue()})}})(jQuery);;/*
+ * jQuery UI Effects Slide 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Slide
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.slide=function(b){return this.queue(function(){var e=a(this),d=["position","top","left"];var i=a.effects.setMode(e,b.options.mode||"show");var h=b.options.direction||"left";a.effects.save(e,d);e.show();a.effects.createWrapper(e).css({overflow:"hidden"});var f=(h=="up"||h=="down")?"top":"left";var c=(h=="up"||h=="left")?"pos":"neg";var j=b.options.distance||(f=="top"?e.outerHeight({margin:true}):e.outerWidth({margin:true}));if(i=="show"){e.css(f,c=="pos"?-j:j)}var g={};g[f]=(i=="show"?(c=="pos"?"+=":"-="):(c=="pos"?"-=":"+="))+j;e.animate(g,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(i=="hide"){e.hide()}a.effects.restore(e,d);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);;/*
+ * jQuery UI Effects Transfer 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Transfer
+ *
+ * Depends:
+ *	effects.core.js
+ */
+(function(a){a.effects.transfer=function(b){return this.queue(function(){var f=a(this),h=a(b.options.to),e=h.offset(),g={top:e.top,left:e.left,height:h.innerHeight(),width:h.innerWidth()},d=f.offset(),c=a('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(b.options.className).css({top:d.top,left:d.left,height:f.innerHeight(),width:f.innerWidth(),position:"absolute"}).animate(g,b.duration,b.options.easing,function(){c.remove();(b.callback&&b.callback.apply(f[0],arguments));f.dequeue()})})}})(jQuery);;
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery.alerts.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery.alerts.js
new file mode 100644
index 0000000..be28126
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery.alerts.js
@@ -0,0 +1,315 @@
+// jQuery Alert Dialogs Plugin

+//

+// Version 1.1

+//

+// Cory S.N. LaViska

+// A Beautiful Site (http://abeautifulsite.net/)

+// 14 May 2009

+//

+// Visit http://abeautifulsite.net/notebook/87 for more information

+//

+// Usage:

+//		jAlert( message, [title, callback] )

+//		jConfirm( message, [title, callback] )

+//		jPrompt( message, [value, title, callback] )

+//		jPromptMulti( message, [value, title, callback] )

+// 

+// History:

+//

+//		1.00 - Released (29 December 2008)

+//

+//		1.01 - Fixed bug where unbinding would destroy all resize events

+//

+// License:

+// 

+// This plugin is dual-licensed under the GNU General Public License and the MIT License and

+// is copyright 2008 A Beautiful Site, LLC. 

+//

+// UPDATED by Andrew Hart (andrew.f.hart@jpl.nasa.gov) to provide functionality for a 

+// multi-valued prompt. The multi-valued prompt offers the user the ability to specify

+// more than one value for a given identifier. If providing seed values (values to 

+// place in the editor when first showing the prompt, they need to adhere to the following

+// two conventions:

+//

+// 	1) Individual values must be wrapped in <span/> tags

+//  2) All <span/> tags must be wrapped in a single container tag (can be anything (li,div,td,etc))

+//

+// When calling jPromptMulti, pass a handle to the container tag as the 'value' parameter.

+// Example:

+//

+//    given html: <li id="myValues"><span>value1</span>, <span>value2</span></li>

+//

+//    you would call jPromptMulti('Update values',$('#myValues'),'title',callbackFn);

+//

+// If a callback function is provided (and only if the user clicks 'SAVE'), the callback

+// will be executed. The callback function should expect a single parameter (which will be 

+// the list of user-specified values represented as a regular JavaScript array).

+//

+//

+// jPromptMulti(

+(function($) {

+	

+	$.alerts = {

+		

+		// These properties can be read/written by accessing $.alerts.propertyName from your scripts at any time

+		

+		verticalOffset: -75,                // vertical offset of the dialog from center screen, in pixels

+		horizontalOffset: 0,                // horizontal offset of the dialog from center screen, in pixels/

+		repositionOnResize: true,           // re-centers the dialog on window resize

+		overlayOpacity: .01,                // transparency level of overlay

+		overlayColor: '#FFF',               // base color of overlay

+		draggable: true,                    // make the dialogs draggable (requires UI Draggables plugin)

+		okButton: '&nbsp;SAVE&nbsp;',         // text for the OK button

+		cancelButton: '&nbsp;Cancel&nbsp;', // text for the Cancel button

+		dialogClass: null,                  // if specified, this class will be applied to all dialogs

+		

+		// Public methods

+		

+		alert: function(message, title, callback) {

+			if( title == null ) title = 'Alert';

+			$.alerts._show(title, message, null, 'alert', function(result) {

+				if( callback ) callback(result);

+			});

+		},

+		

+		confirm: function(message, title, callback) {

+			if( title == null ) title = 'Confirm';

+			$.alerts._show(title, message, null, 'confirm', function(result) {

+				if( callback ) callback(result);

+			});

+		},

+			

+		prompt: function(message, value, title, callback) {

+			if( title == null ) title = 'title';

+			$.alerts._show(title, message, value, 'prompt', function(result) {

+				if( callback ) callback(result);

+			});

+		},

+		

+		promptMulti: function(message, value, title, callback) {

+			if( title == null) title = 'title';

+			$.alerts._show(title, message, value, 'promptMulti', function(result) {

+				if( callback ) callback(result);

+			});

+		},

+		

+		// Private methods

+		

+		_show: function(title, msg, value, type, callback) {

+			

+			$.alerts._hide();

+			$.alerts._overlay('show');

+			

+			$("BODY").append(

+			  '<div id="popup_container">' +

+			    '<h1 id="popup_title"></h1>' +

+			    '<div id="popup_content">' +

+			      '<div id="popup_message"></div>' +

+				'</div>' +

+			  '</div>');

+			

+			if( $.alerts.dialogClass ) $("#popup_container").addClass($.alerts.dialogClass);

+			

+			// IE6 Fix

+			var pos = ($.browser.msie && parseInt($.browser.version) <= 6 ) ? 'absolute' : 'fixed'; 

+			

+			$("#popup_container").css({

+				position: pos,

+				zIndex: 99999,

+				padding: 0,

+				margin: 0

+			});

+			

+			$("#popup_title").text(title);

+			$("#popup_content").addClass(type);

+			$("#popup_message").text(msg);

+			$("#popup_message").html( $("#popup_message").text().replace(/\n/g, '<br />') );

+			

+			$("#popup_container").css({

+				minWidth: $("#popup_container").outerWidth(),

+				maxWidth: $("#popup_container").outerWidth()

+			});

+			

+			$.alerts._reposition();

+			$.alerts._maintainPosition(true);

+			

+			switch( type ) {

+				case 'alert':

+					$("#popup_message").after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /></div>');

+					$("#popup_ok").click( function() {

+						$.alerts._hide();

+						callback(true);

+					});

+					$("#popup_ok").focus().keypress( function(e) {

+						if( e.keyCode == 13 || e.keyCode == 27 ) $("#popup_ok").trigger('click');

+					});

+				break;

+				case 'confirm':

+					$("#popup_message").after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /> <input type="button" value="' + $.alerts.cancelButton + '" id="popup_cancel" /></div>');

+					$("#popup_ok").click( function() {

+						$.alerts._hide();

+						if( callback ) callback(true);

+					});

+					$("#popup_cancel").click( function() {

+						$.alerts._hide();

+						if( callback ) callback(false);

+					});

+					$("#popup_ok").focus();

+					$("#popup_ok, #popup_cancel").keypress( function(e) {

+						if( e.keyCode == 13 ) $("#popup_ok").trigger('click');

+						if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');

+					});

+				break;

+				case 'prompt':

+					$("#popup_message").append('<br /><input type="text" size="30" id="popup_prompt" />').after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /> <input type="button" value="' + $.alerts.cancelButton + '" id="popup_cancel" /></div>');

+					$("#popup_prompt").width( $("#popup_message").width() );

+					$("#popup_ok").click( function() {

+						var val = $("#popup_prompt").val();

+						$.alerts._hide();

+						if( callback ) callback( val );

+					});

+					$("#popup_cancel").click( function() {

+						$.alerts._hide();

+						if( callback ) callback( null );

+					});

+					$("#popup_prompt, #popup_ok, #popup_cancel").keypress( function(e) {

+						if( e.keyCode == 13 ) $("#popup_ok").trigger('click');

+						if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');

+					});

+					if( value ) $("#popup_prompt").val(value);

+					$("#popup_prompt").focus().select();

+				break;

+				case 'promptMulti':

+					// In the case of a multiple value prompt, 'value' should be a jQuery DOM object containing

+					// a number of individual values wrapped in <span/> elements. Each <span/> element in 

+					// the provided message is inspected, and its text value is used.

+					// example: <td><span>value1</span>, <span>value2</span></td>

+					// would translate into 2 values (value1 and value2) being displayed for editing. 

+					

+					value.children('span').each(function() {

+						var $input = $('<input>')

+							.attr({'type':'text','size':'30','class':'popup_multiPrompt','value':$(this).text()});

+						$("#popup_message").append('<br/>').append($input);

+					});

+					$("#popup_message")

+						.after ('<br/><input type="button" id="multiPromptNewValue" value="+"/>&nbsp;Add a new value' +

+								'<div id="popup_panel"><input type="button" value="' + 

+								$.alerts.okButton + 

+								'" id="popup_ok" /> <input type="button" value="' +

+								$.alerts.cancelButton + 

+								'" id="popup_cancel" /></div>');

+					

+					$(".popup_multiPrompt").width( $("#popup_message").width() );

+					$("#multiPromptNewValue").click( function() {

+						$("#popup_message")

+							.append('<br /><input type="text" size="30" class="popup_multiPrompt" value=""/>');

+						$(".popup_multiPrompt").width( $("#popup_message").width() );

+					

+					});

+					$("#popup_ok").click( function() {

+						// Gather values

+						var values = Array();

+						$(".popup_multiPrompt").each( function() {

+							if ($(this).val()) values.push($(this).val());

+						});

+						$.alerts._hide();

+						if( callback ) callback( values );

+					});

+					$("#popup_cancel").click( function() {

+						$.alerts._hide();

+						if( callback ) callback( null );

+					});

+					$("#popup_prompt, #popup_ok, #popup_cancel").keypress( function(e) {

+						if( e.keyCode == 13 ) $("#popup_ok").trigger('click');

+						if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');

+					});

+					if( value ) $("#popup_prompt").val(value);

+					$("#popup_prompt").focus().select();

+				break;

+			}

+			

+			// Make draggable

+			if( $.alerts.draggable ) {

+				try {

+					$("#popup_container").draggable({ handle: $("#popup_title") });

+					$("#popup_title").css({ cursor: 'move' });

+				} catch(e) { /* requires jQuery UI draggables */ }

+			}

+		},

+		

+		_hide: function() {

+			$("#popup_container").remove();

+			$.alerts._overlay('hide');

+			$.alerts._maintainPosition(false);

+		},

+		

+		_overlay: function(status) {

+			switch( status ) {

+				case 'show':

+					$.alerts._overlay('hide');

+					$("BODY").append('<div id="popup_overlay"></div>');

+					$("#popup_overlay").css({

+						position: 'absolute',

+						zIndex: 99998,

+						top: '0px',

+						left: '0px',

+						width: '100%',

+						height: $(document).height(),

+						background: $.alerts.overlayColor,

+						opacity: $.alerts.overlayOpacity

+					});

+				break;

+				case 'hide':

+					$("#popup_overlay").remove();

+				break;

+			}

+		},

+		

+		_reposition: function() {

+			var top = (($(window).height() / 2) - ($("#popup_container").outerHeight() / 2)) + $.alerts.verticalOffset;

+			var left = (($(window).width() / 2) - ($("#popup_container").outerWidth() / 2)) + $.alerts.horizontalOffset;

+			if( top < 0 ) top = 0;

+			if( left < 0 ) left = 0;

+			

+			// IE6 fix

+			if( $.browser.msie && parseInt($.browser.version) <= 6 ) top = top + $(window).scrollTop();

+			

+			$("#popup_container").css({

+				top: top + 'px',

+				left: left + 'px'

+			});

+			$("#popup_overlay").height( $(document).height() );

+		},

+		

+		_maintainPosition: function(status) {

+			if( $.alerts.repositionOnResize ) {

+				switch(status) {

+					case true:

+						$(window).bind('resize', $.alerts._reposition);

+					break;

+					case false:

+						$(window).unbind('resize', $.alerts._reposition);

+					break;

+				}

+			}

+		}

+		

+	}

+	

+	// Shortuct functions

+	jAlert = function(message, title, callback) {

+		$.alerts.alert(message, title, callback);

+	}

+	

+	jConfirm = function(message, title, callback) {

+		$.alerts.confirm(message, title, callback);

+	};

+		

+	jPrompt = function(message, value, title, callback) {

+		$.alerts.prompt(message, value, title, callback);

+	};

+	

+	jPromptMulti = function(message, value, title, callback) {

+		$.alerts.promptMulti(message, value, title, callback);

+	};

+})(jQuery);
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery.periodicalupdater.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery.periodicalupdater.js
new file mode 100644
index 0000000..c4880a3
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery.periodicalupdater.js
@@ -0,0 +1,105 @@
+/**

+ * PeriodicalUpdater - jQuery plugin for timed, decaying ajax calls

+ *

+ * Smokejumper Version by Robert Fischer, Smokejumper IT

+ * Based on version from http://www.360innovate.co.uk

+ *

+ * Copyright (c) 2009 by the following:

+ *	 * Robert Fischer (http://smokejumperit.com)

+ *	 * 360innovate (http://www.360innovate.co.uk)

+ * Dual licensed under the MIT and GPL licenses:

+ * http://www.opensource.org/licenses/mit-license.php

+ * http://www.gnu.org/licenses/gpl.html

+ *

+ * Version: 2.0

+ */

+

+(function($) {

+		function pu_log(msg) {

+			try {

+				console.log(msg);

+			} catch(err) {}

+		}

+

+		// Now back to our regularly scheduled work

+		$.PeriodicalUpdater = function(url, options, callback){

+

+				var settings = jQuery.extend(true, {

+					url: url,								// URL of ajax request

+					cache: false,						// By default, don't allow caching

+					method: 'GET',					// method; get or post

+					data: '',								// array of values to be passed to the page - e.g. {name: "John", greeting: "hello"}

+					minTimeout: 1000,				// starting value for the timeout in milliseconds

+					maxTimeout: 8000,				// maximum length of time between requests

+					multiplier: 2						// if set to 2, timerInterval will double each time the response hasn't changed (up to maxTimeout)

+				}, options);

+				

+				// set some initial values, then begin

+				var timerInterval = settings.minTimeout;

+

+				// Function to boost the timer (nop unless multiplier > 1)

+				var boostPeriod = function() { return; };

+				if(settings.multiplier > 1) {

+					boostPeriod = function() { 

+						timerInterval = timerInterval * settings.multiplier;

+						

+						if(timerInterval > settings.maxTimeout) {

+								timerInterval = settings.maxTimeout;

+						}

+					};

+				} 

+

+				// Construct the settings for $.ajax based on settings

+				var ajaxSettings = jQuery.extend(true, {}, settings);

+				if(settings.type && !ajaxSettings.dataType) ajaxSettings.dataType = settings.type;

+				if(settings.sendData) ajaxSettings.data = settings.sendData;

+				ajaxSettings.type = settings.method; // 'type' is used internally for jQuery.  Who knew?

+				ajaxSettings.ifModified = true;

+

+				var remoteData = null;

+				var prevData = null;

+				

+				ajaxSettings.success = function(data) {

+					pu_log("Successful run! (In 'success')");

+					remoteData = data;

+					timerInterval = settings.minTimeout;

+				};

+				

+				ajaxSettings.complete = function(xhr, success) {

+					pu_log("Status of call: " + success + " (In 'complete')");

+

+					if(success == "success" || success == "notmodified") {

+						var rawData = $.trim(xhr.responseText);

+						if(prevData == rawData) {

+							boostPeriod();

+						} else {

+							timerInterval = settings.minTimeout;

+							prevData = rawData;

+							if(remoteData == null) remoteData = rawData;

+							if(settings.success) { settings.success(remoteData); }

+							if(callback) callback(remoteData);

+						}

+					}

+					

+					remoteData = null;

+					setTimeout(getdata, timerInterval);

+				}

+

+

+				ajaxSettings.error = function (xhr, textStatus) { 

+					pu_log("Error message: " + textStatus + " (In 'error')");

+					if(textStatus == "notmodified") {

+						boostPeriod();

+					} else {

+						prevData = null;

+						timerInterval = settings.minTimeout;

+					}

+					if(settings.error) { settings.error(xhr, textStatus); }

+				};

+

+				function getdata() { $.ajax(ajaxSettings); }

+

+				// Make the first call

+				$(function() { getdata(); });

+		};	

+})(jQuery);

diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery.treeview.zip b/0.8.1-rc1/curator/src/main/webapp/js/jquery.treeview.zip
new file mode 100644
index 0000000..339afe5
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery.treeview.zip
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery/jquery.blockUI.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery/jquery.blockUI.js
new file mode 100644
index 0000000..6aeed5c
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery/jquery.blockUI.js
@@ -0,0 +1,398 @@
+/*
+ * jQuery blockUI plugin
+ * Version 2.15 (1-MAR-2009)
+ * @requires jQuery v1.2.3 or later
+ *
+ * Examples at: http://malsup.com/jquery/block/
+ * Copyright (c) 2007-2008 M. Alsup
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Thanks to Amir-Hossein Sobhi for some excellent contributions!
+ */
+
+;(function($) {
+
+if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) {
+    alert('blockUI requires jQuery v1.2.3 or later!  You are using v' + $.fn.jquery);
+    return;
+}
+
+$.fn._fadeIn = $.fn.fadeIn;
+
+// global $ methods for blocking/unblocking the entire page
+$.blockUI   = function(opts) { install(window, opts); };
+$.unblockUI = function(opts) { remove(window, opts); };
+
+// convenience method for quick growl-like notifications  (http://www.google.com/search?q=growl)
+$.growlUI = function(title, message, timeout) {
+	var $m = $('<div class="growlUI"></div>');
+	if (title) $m.append('<h1>'+title+'</h1>');
+	if (message) $m.append('<h2>'+message+'</h2>');
+	if (timeout == undefined) timeout = 3000;
+    $.blockUI({
+		message: $m, fadeIn: 700, fadeOut: 1000, centerY: false,
+		timeout: timeout, showOverlay: false,
+		css: $.blockUI.defaults.growlCSS
+    });
+};
+
+// plugin method for blocking element content
+$.fn.block = function(opts) {
+    return this.each(function() {
+        if ($.css(this,'position') == 'static')
+            this.style.position = 'relative';
+        if ($.browser.msie)
+            this.style.zoom = 1; // force 'hasLayout'
+        install(this, opts);
+    });
+};
+
+// plugin method for unblocking element content
+$.fn.unblock = function(opts) {
+    return this.each(function() {
+        remove(this, opts);
+    });
+};
+
+$.blockUI.version = 2.14; // 2nd generation blocking at no extra cost!
+
+// override these in your code to change the default behavior and style
+$.blockUI.defaults = {
+    // message displayed when blocking (use null for no message)
+    message:  '<h1>Please wait...</h1>',
+
+    // styles for the message when blocking; if you wish to disable
+    // these and use an external stylesheet then do this in your code:
+    // $.blockUI.defaults.css = {};
+    css: {
+        padding:        0,
+        margin:         0,
+        width:          '30%',
+        top:            '40%',
+        left:           '35%',
+        textAlign:      'center',
+        color:          '#000',
+        border:         '3px solid #aaa',
+        backgroundColor:'#fff',
+        cursor:         'wait'
+    },
+
+    // styles for the overlay
+    overlayCSS:  {
+        backgroundColor: '#000',
+        opacity:         '0.6'
+    },
+
+	// styles applied when using $.growlUI
+	growlCSS: {
+		width:    '350px',
+		top:      '10px',
+		left:     '',
+		right:    '10px',
+	    border:   'none',
+	    padding:  '5px',
+	    opacity:  '0.6',
+		cursor:    null,
+	    color:    '#fff',
+	    backgroundColor: '#000',
+	    '-webkit-border-radius': '10px',
+	    '-moz-border-radius':    '10px'
+	},
+
+    // z-index for the blocking overlay
+    baseZ: 1000,
+
+    // set these to true to have the message automatically centered
+    centerX: true, // <-- only effects element blocking (page block controlled via css above)
+    centerY: true,
+
+    // allow body element to be stetched in ie6; this makes blocking look better
+    // on "short" pages.  disable if you wish to prevent changes to the body height
+    allowBodyStretch: true,
+
+    // be default blockUI will supress tab navigation from leaving blocking content;
+    constrainTabKey: true,
+
+    // fadeIn time in millis; set to 0 to disable fadeIn on block
+    fadeIn:  200,
+
+    // fadeOut time in millis; set to 0 to disable fadeOut on unblock
+    fadeOut:  400,
+
+	// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
+	timeout: 0,
+
+	// disable if you don't want to show the overlay
+	showOverlay: true,
+
+    // if true, focus will be placed in the first available input field when
+    // page blocking
+    focusInput: true,
+
+    // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
+    applyPlatformOpacityRules: true,
+
+    // callback method invoked when unblocking has completed; the callback is
+    // passed the element that has been unblocked (which is the window object for page
+    // blocks) and the options that were passed to the unblock call:
+    //     onUnblock(element, options)
+    onUnblock: null,
+
+    // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
+    quirksmodeOffsetHack: 4
+};
+
+// private data and functions follow...
+
+var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent);
+var pageBlock = null;
+var pageBlockEls = [];
+
+function install(el, opts) {
+    var full = (el == window);
+    var msg = opts && opts.message !== undefined ? opts.message : undefined;
+    opts = $.extend({}, $.blockUI.defaults, opts || {});
+    opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
+    var css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
+    msg = msg === undefined ? opts.message : msg;
+
+    // remove the current block (if there is one)
+    if (full && pageBlock)
+        remove(window, {fadeOut:0});
+
+    // if an existing element is being used as the blocking content then we capture
+    // its current place in the DOM (and current display style) so we can restore
+    // it when we unblock
+    if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
+        var node = msg.jquery ? msg[0] : msg;
+        var data = {};
+        $(el).data('blockUI.history', data);
+        data.el = node;
+        data.parent = node.parentNode;
+        data.display = node.style.display;
+        data.position = node.style.position;
+		if (data.parent)
+			data.parent.removeChild(node);
+    }
+
+    var z = opts.baseZ;
+
+    // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
+    // layer1 is the iframe layer which is used to supress bleed through of underlying content
+    // layer2 is the overlay layer which has opacity and a wait cursor
+    // layer3 is the message content that is displayed while blocking
+
+    var lyr1 = ($.browser.msie) ? $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="about:blank"></iframe>')
+                                : $('<div class="blockUI" style="display:none"></div>');
+    var lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;cursor:wait;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
+    var lyr3 = full ? $('<div class="blockUI blockMsg blockPage" style="z-index:'+z+';display:none;position:fixed"></div>')
+                    : $('<div class="blockUI blockMsg blockElement" style="z-index:'+z+';display:none;position:absolute"></div>');
+
+    // if we have a message, style it
+    if (msg)
+        lyr3.css(css);
+
+    // style the overlay
+    if (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform)))
+        lyr2.css(opts.overlayCSS);
+    lyr2.css('position', full ? 'fixed' : 'absolute');
+
+    // make iframe layer transparent in IE
+    if ($.browser.msie)
+        lyr1.css('opacity','0.0');
+
+    $([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
+
+    // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
+    var expr = $.browser.msie && (!$.boxModel || $('object,embed', full ? null : el).length > 0);
+    if (ie6 || expr && lyr3[0].style.setExpression) {
+        // give body 100% height
+        if (full && opts.allowBodyStretch && $.boxModel)
+            $('html,body').css('height','100%');
+
+        // fix ie6 issue when blocked element has a border width
+        if ((ie6 || !$.boxModel) && !full) {
+            var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
+            var fixT = t ? '(0 - '+t+')' : 0;
+            var fixL = l ? '(0 - '+l+')' : 0;
+        }
+
+        // simulate fixed position
+        $.each([lyr1,lyr2,lyr3], function(i,o) {
+            var s = o[0].style;
+            s.position = 'absolute';
+            if (i < 2) {
+                full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"')
+                     : s.setExpression('height','this.parentNode.offsetHeight + "px"');
+                full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"')
+                     : s.setExpression('width','this.parentNode.offsetWidth + "px"');
+                if (fixL) s.setExpression('left', fixL);
+                if (fixT) s.setExpression('top', fixT);
+            }
+            else if (opts.centerY) {
+                if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
+                s.marginTop = 0;
+            }
+			else if (!opts.centerY && full) {
+				var top = (opts.css && opts.css.top) ? parseInt(opts.css.top) : 0;
+				var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
+                s.setExpression('top',expression);
+			}
+        });
+    }
+
+    // show the message
+	if (msg) {
+		lyr3.append(msg);
+		if (msg.jquery || msg.nodeType)
+			$(msg).show();
+	}
+
+	if ($.browser.msie && opts.showOverlay)
+		lyr1.show(); // opacity is zero
+	if (opts.fadeIn) {
+		if (opts.showOverlay)
+			lyr2._fadeIn(opts.fadeIn);
+		if (msg)
+			lyr3.fadeIn(opts.fadeIn);
+	}
+	else {
+		if (opts.showOverlay)
+			lyr2.show();
+		if (msg)
+			lyr3.show();
+	}
+
+    // bind key and mouse events
+    bind(1, el, opts);
+
+    if (full) {
+        pageBlock = lyr3[0];
+        pageBlockEls = $(':input:enabled:visible',pageBlock);
+        if (opts.focusInput)
+            setTimeout(focus, 20);
+    }
+    else
+        center(lyr3[0], opts.centerX, opts.centerY);
+
+	if (opts.timeout) {
+		// auto-unblock
+		var to = setTimeout(function() {
+			full ? $.unblockUI(opts) : $(el).unblock(opts);
+		}, opts.timeout);
+		$(el).data('blockUI.timeout', to);
+	}
+};
+
+// remove the block
+function remove(el, opts) {
+    var full = el == window;
+	var $el = $(el);
+    var data = $el.data('blockUI.history');
+	var to = $el.data('blockUI.timeout');
+	if (to) {
+		clearTimeout(to);
+		$el.removeData('blockUI.timeout');
+	}
+    opts = $.extend({}, $.blockUI.defaults, opts || {});
+    bind(0, el, opts); // unbind events
+    var els = full ? $('body').children().filter('.blockUI') : $('.blockUI', el);
+
+    if (full)
+        pageBlock = pageBlockEls = null;
+
+    if (opts.fadeOut) {
+        els.fadeOut(opts.fadeOut);
+        setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
+    }
+    else
+        reset(els, data, opts, el);
+};
+
+// move blocking element back into the DOM where it started
+function reset(els,data,opts,el) {
+    els.each(function(i,o) {
+        // remove via DOM calls so we don't lose event handlers
+        if (this.parentNode)
+            this.parentNode.removeChild(this);
+    });
+
+    if (data && data.el) {
+        data.el.style.display = data.display;
+        data.el.style.position = data.position;
+		if (data.parent)
+			data.parent.appendChild(data.el);
+        $(data.el).removeData('blockUI.history');
+    }
+
+    if (typeof opts.onUnblock == 'function')
+        opts.onUnblock(el,opts);
+};
+
+// bind/unbind the handler
+function bind(b, el, opts) {
+    var full = el == window, $el = $(el);
+
+    // don't bother unbinding if there is nothing to unbind
+    if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
+        return;
+    if (!full)
+        $el.data('blockUI.isBlocked', b);
+
+    if (b && !opts.showOverlay) // don't prevent events when overlay not in use
+		return;
+
+    // bind anchors and inputs for mouse and key events
+    var events = 'mousedown mouseup keydown keypress';
+    b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler);
+
+// former impl...
+//    var $e = $('a,:input');
+//    b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
+};
+
+// event handler to suppress keyboard/mouse events when blocking
+function handler(e) {
+    // allow tab navigation (conditionally)
+    if (e.keyCode && e.keyCode == 9) {
+        if (pageBlock && e.data.constrainTabKey) {
+            var els = pageBlockEls;
+            var fwd = !e.shiftKey && e.target == els[els.length-1];
+            var back = e.shiftKey && e.target == els[0];
+            if (fwd || back) {
+                setTimeout(function(){focus(back)},10);
+                return false;
+            }
+        }
+    }
+    // allow events within the message content
+    if ($(e.target).parents('div.blockMsg').length > 0)
+        return true;
+
+    // allow events for content that is not being blocked
+    return $(e.target).parents().children().filter('div.blockUI').length == 0;
+};
+
+function focus(back) {
+    if (!pageBlockEls)
+        return;
+    var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
+    if (e)
+        e.focus();
+};
+
+function center(el, x, y) {
+    var p = el.parentNode, s = el.style;
+    var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
+    var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
+    if (x) s.left = l > 0 ? (l+'px') : '0';
+    if (y) s.top  = t > 0 ? (t+'px') : '0';
+};
+
+function sz(el, p) {
+    return parseInt($.css(el,p))||0;
+};
+
+})(jQuery);
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery/jquery.cookie.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery/jquery.cookie.js
new file mode 100644
index 0000000..79317f7
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery/jquery.cookie.js
@@ -0,0 +1,96 @@
+/**
+ * Cookie plugin
+ *
+ * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+/**
+ * Create a cookie with the given name and value and other optional parameters.
+ *
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Set the value of a cookie.
+ * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
+ * @desc Create a cookie with all available options.
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Create a session cookie.
+ * @example $.cookie('the_cookie', null);
+ * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
+ *       used when the cookie was set.
+ *
+ * @param String name The name of the cookie.
+ * @param String value The value of the cookie.
+ * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
+ * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
+ *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
+ *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
+ *                             when the the browser exits.
+ * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
+ * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
+ * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
+ *                        require a secure protocol (like HTTPS).
+ * @type undefined
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+
+/**
+ * Get the value of a cookie with the given name.
+ *
+ * @example $.cookie('the_cookie');
+ * @desc Get the value of a cookie.
+ *
+ * @param String name The name of the cookie.
+ * @return The value of the cookie.
+ * @type String
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+jQuery.cookie = function(name, value, options) {
+    if (typeof value != 'undefined') { // name and value given, set cookie
+        options = options || {};
+        if (value === null) {
+            value = '';
+            options.expires = -1;
+        }
+        var expires = '';
+        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
+            var date;
+            if (typeof options.expires == 'number') {
+                date = new Date();
+                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
+            } else {
+                date = options.expires;
+            }
+            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
+        }
+        // CAUTION: Needed to parenthesize options.path and options.domain
+        // in the following expressions, otherwise they evaluate to undefined
+        // in the packed version for some reason...
+        var path = options.path ? '; path=' + (options.path) : '';
+        var domain = options.domain ? '; domain=' + (options.domain) : '';
+        var secure = options.secure ? '; secure' : '';
+        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
+    } else { // only name given, get cookie
+        var cookieValue = null;
+        if (document.cookie && document.cookie != '') {
+            var cookies = document.cookie.split(';');
+            for (var i = 0; i < cookies.length; i++) {
+                var cookie = jQuery.trim(cookies[i]);
+                // Does this cookie string begin with the name we want?
+                if (cookie.substring(0, name.length + 1) == (name + '=')) {
+                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
+                    break;
+                }
+            }
+        }
+        return cookieValue;
+    }
+};
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery/jquery.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery/jquery.js
new file mode 100644
index 0000000..94e9c17
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery/jquery.js
@@ -0,0 +1,4241 @@
+/*!
+ * jQuery JavaScript Library v1.3.1
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-01-21 20:42:16 -0500 (Wed, 21 Jan 2009)
+ * Revision: 6158
+ */
+(function(){
+
+var 
+	// Will speed up references to window, and allows munging its name.
+	window = this,
+	// Will speed up references to undefined, and allows munging its name.
+	undefined,
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+	// Map over the $ in case of overwrite
+	_$ = window.$,
+
+	jQuery = window.jQuery = window.$ = function( selector, context ) {
+		// The jQuery object is actually just the init constructor 'enhanced'
+		return new jQuery.fn.init( selector, context );
+	},
+
+	// A simple way to check for HTML strings or ID strings
+	// (both of which we optimize for)
+	quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
+	// Is it a simple selector
+	isSimple = /^.[^:#\[\.,]*$/;
+
+jQuery.fn = jQuery.prototype = {
+	init: function( selector, context ) {
+		// Make sure that a selection was provided
+		selector = selector || document;
+
+		// Handle $(DOMElement)
+		if ( selector.nodeType ) {
+			this[0] = selector;
+			this.length = 1;
+			this.context = selector;
+			return this;
+		}
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			// Are we dealing with HTML string or an ID?
+			var match = quickExpr.exec( selector );
+
+			// Verify a match, and that no context was specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] )
+					selector = jQuery.clean( [ match[1] ], context );
+
+				// HANDLE: $("#id")
+				else {
+					var elem = document.getElementById( match[3] );
+
+					// Handle the case where IE and Opera return items
+					// by name instead of ID
+					if ( elem && elem.id != match[3] )
+						return jQuery().find( selector );
+
+					// Otherwise, we inject the element directly into the jQuery object
+					var ret = jQuery( elem || [] );
+					ret.context = document;
+					ret.selector = selector;
+					return ret;
+				}
+
+			// HANDLE: $(expr, [context])
+			// (which is just equivalent to: $(content).find(expr)
+			} else
+				return jQuery( context ).find( selector );
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) )
+			return jQuery( document ).ready( selector );
+
+		// Make sure that old selector state is passed along
+		if ( selector.selector && selector.context ) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return this.setArray(jQuery.makeArray(selector));
+	},
+
+	// Start with an empty selector
+	selector: "",
+
+	// The current version of jQuery being used
+	jquery: "1.3.1",
+
+	// The number of elements contained in the matched element set
+	size: function() {
+		return this.length;
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num === undefined ?
+
+			// Return a 'clean' array
+			jQuery.makeArray( this ) :
+
+			// Return just the object
+			this[ num ];
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems, name, selector ) {
+		// Build a new jQuery matched element set
+		var ret = jQuery( elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		ret.context = this.context;
+
+		if ( name === "find" )
+			ret.selector = this.selector + (this.selector ? " " : "") + selector;
+		else if ( name )
+			ret.selector = this.selector + "." + name + "(" + selector + ")";
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Force the current matched set of elements to become
+	// the specified array of elements (destroying the stack in the process)
+	// You should use pushStack() in order to do this, but maintain the stack
+	setArray: function( elems ) {
+		// Resetting the length to 0, then using the native Array push
+		// is a super-fast way to populate an object with array-like properties
+		this.length = 0;
+		Array.prototype.push.apply( this, elems );
+
+		return this;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	// Determine the position of an element within
+	// the matched set of elements
+	index: function( elem ) {
+		// Locate the position of the desired element
+		return jQuery.inArray(
+			// If it receives a jQuery object, the first element is used
+			elem && elem.jquery ? elem[0] : elem
+		, this );
+	},
+
+	attr: function( name, value, type ) {
+		var options = name;
+
+		// Look for the case where we're accessing a style value
+		if ( typeof name === "string" )
+			if ( value === undefined )
+				return this[0] && jQuery[ type || "attr" ]( this[0], name );
+
+			else {
+				options = {};
+				options[ name ] = value;
+			}
+
+		// Check to see if we're setting style values
+		return this.each(function(i){
+			// Set all the styles
+			for ( name in options )
+				jQuery.attr(
+					type ?
+						this.style :
+						this,
+					name, jQuery.prop( this, options[ name ], type, i, name )
+				);
+		});
+	},
+
+	css: function( key, value ) {
+		// ignore negative width and height values
+		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
+			value = undefined;
+		return this.attr( key, value, "curCSS" );
+	},
+
+	text: function( text ) {
+		if ( typeof text !== "object" && text != null )
+			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+
+		var ret = "";
+
+		jQuery.each( text || this, function(){
+			jQuery.each( this.childNodes, function(){
+				if ( this.nodeType != 8 )
+					ret += this.nodeType != 1 ?
+						this.nodeValue :
+						jQuery.fn.text( [ this ] );
+			});
+		});
+
+		return ret;
+	},
+
+	wrapAll: function( html ) {
+		if ( this[0] ) {
+			// The elements to wrap the target around
+			var wrap = jQuery( html, this[0].ownerDocument ).clone();
+
+			if ( this[0].parentNode )
+				wrap.insertBefore( this[0] );
+
+			wrap.map(function(){
+				var elem = this;
+
+				while ( elem.firstChild )
+					elem = elem.firstChild;
+
+				return elem;
+			}).append(this);
+		}
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		return this.each(function(){
+			jQuery( this ).contents().wrapAll( html );
+		});
+	},
+
+	wrap: function( html ) {
+		return this.each(function(){
+			jQuery( this ).wrapAll( html );
+		});
+	},
+
+	append: function() {
+		return this.domManip(arguments, true, function(elem){
+			if (this.nodeType == 1)
+				this.appendChild( elem );
+		});
+	},
+
+	prepend: function() {
+		return this.domManip(arguments, true, function(elem){
+			if (this.nodeType == 1)
+				this.insertBefore( elem, this.firstChild );
+		});
+	},
+
+	before: function() {
+		return this.domManip(arguments, false, function(elem){
+			this.parentNode.insertBefore( elem, this );
+		});
+	},
+
+	after: function() {
+		return this.domManip(arguments, false, function(elem){
+			this.parentNode.insertBefore( elem, this.nextSibling );
+		});
+	},
+
+	end: function() {
+		return this.prevObject || jQuery( [] );
+	},
+
+	// For internal use only.
+	// Behaves like an Array's .push method, not like a jQuery method.
+	push: [].push,
+
+	find: function( selector ) {
+		if ( this.length === 1 && !/,/.test(selector) ) {
+			var ret = this.pushStack( [], "find", selector );
+			ret.length = 0;
+			jQuery.find( selector, this[0], ret );
+			return ret;
+		} else {
+			var elems = jQuery.map(this, function(elem){
+				return jQuery.find( selector, elem );
+			});
+
+			return this.pushStack( /[^+>] [^+>]/.test( selector ) ?
+				jQuery.unique( elems ) :
+				elems, "find", selector );
+		}
+	},
+
+	clone: function( events ) {
+		// Do the clone
+		var ret = this.map(function(){
+			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
+				// IE copies events bound via attachEvent when
+				// using cloneNode. Calling detachEvent on the
+				// clone will also remove the events from the orignal
+				// In order to get around this, we use innerHTML.
+				// Unfortunately, this means some modifications to
+				// attributes in IE that are actually only stored
+				// as properties will not be copied (such as the
+				// the name attribute on an input).
+				var clone = this.cloneNode(true),
+					container = document.createElement("div");
+				container.appendChild(clone);
+				return jQuery.clean([container.innerHTML])[0];
+			} else
+				return this.cloneNode(true);
+		});
+
+		// Need to set the expando to null on the cloned set if it exists
+		// removeData doesn't work here, IE removes it from the original as well
+		// this is primarily for IE but the data expando shouldn't be copied over in any browser
+		var clone = ret.find("*").andSelf().each(function(){
+			if ( this[ expando ] !== undefined )
+				this[ expando ] = null;
+		});
+
+		// Copy the events from the original to the clone
+		if ( events === true )
+			this.find("*").andSelf().each(function(i){
+				if (this.nodeType == 3)
+					return;
+				var events = jQuery.data( this, "events" );
+
+				for ( var type in events )
+					for ( var handler in events[ type ] )
+						jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
+			});
+
+		// Return the cloned set
+		return ret;
+	},
+
+	filter: function( selector ) {
+		return this.pushStack(
+			jQuery.isFunction( selector ) &&
+			jQuery.grep(this, function(elem, i){
+				return selector.call( elem, i );
+			}) ||
+
+			jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
+				return elem.nodeType === 1;
+			}) ), "filter", selector );
+	},
+
+	closest: function( selector ) {
+		var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null;
+
+		return this.map(function(){
+			var cur = this;
+			while ( cur && cur.ownerDocument ) {
+				if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) )
+					return cur;
+				cur = cur.parentNode;
+			}
+		});
+	},
+
+	not: function( selector ) {
+		if ( typeof selector === "string" )
+			// test special case where just one selector is passed in
+			if ( isSimple.test( selector ) )
+				return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
+			else
+				selector = jQuery.multiFilter( selector, this );
+
+		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+		return this.filter(function() {
+			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
+		});
+	},
+
+	add: function( selector ) {
+		return this.pushStack( jQuery.unique( jQuery.merge(
+			this.get(),
+			typeof selector === "string" ?
+				jQuery( selector ) :
+				jQuery.makeArray( selector )
+		)));
+	},
+
+	is: function( selector ) {
+		return !!selector && jQuery.multiFilter( selector, this ).length > 0;
+	},
+
+	hasClass: function( selector ) {
+		return !!selector && this.is( "." + selector );
+	},
+
+	val: function( value ) {
+		if ( value === undefined ) {			
+			var elem = this[0];
+
+			if ( elem ) {
+				if( jQuery.nodeName( elem, 'option' ) )
+					return (elem.attributes.value || {}).specified ? elem.value : elem.text;
+				
+				// We need to handle select boxes special
+				if ( jQuery.nodeName( elem, "select" ) ) {
+					var index = elem.selectedIndex,
+						values = [],
+						options = elem.options,
+						one = elem.type == "select-one";
+
+					// Nothing was selected
+					if ( index < 0 )
+						return null;
+
+					// Loop through all the selected options
+					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+						var option = options[ i ];
+
+						if ( option.selected ) {
+							// Get the specifc value for the option
+							value = jQuery(option).val();
+
+							// We don't need an array for one selects
+							if ( one )
+								return value;
+
+							// Multi-Selects return an array
+							values.push( value );
+						}
+					}
+
+					return values;				
+				}
+
+				// Everything else, we just grab the value
+				return (elem.value || "").replace(/\r/g, "");
+
+			}
+
+			return undefined;
+		}
+
+		if ( typeof value === "number" )
+			value += '';
+
+		return this.each(function(){
+			if ( this.nodeType != 1 )
+				return;
+
+			if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
+				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
+					jQuery.inArray(this.name, value) >= 0);
+
+			else if ( jQuery.nodeName( this, "select" ) ) {
+				var values = jQuery.makeArray(value);
+
+				jQuery( "option", this ).each(function(){
+					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
+						jQuery.inArray( this.text, values ) >= 0);
+				});
+
+				if ( !values.length )
+					this.selectedIndex = -1;
+
+			} else
+				this.value = value;
+		});
+	},
+
+	html: function( value ) {
+		return value === undefined ?
+			(this[0] ?
+				this[0].innerHTML :
+				null) :
+			this.empty().append( value );
+	},
+
+	replaceWith: function( value ) {
+		return this.after( value ).remove();
+	},
+
+	eq: function( i ) {
+		return this.slice( i, +i + 1 );
+	},
+
+	slice: function() {
+		return this.pushStack( Array.prototype.slice.apply( this, arguments ),
+			"slice", Array.prototype.slice.call(arguments).join(",") );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function(elem, i){
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	andSelf: function() {
+		return this.add( this.prevObject );
+	},
+
+	domManip: function( args, table, callback ) {
+		if ( this[0] ) {
+			var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
+				scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
+				first = fragment.firstChild,
+				extra = this.length > 1 ? fragment.cloneNode(true) : fragment;
+
+			if ( first )
+				for ( var i = 0, l = this.length; i < l; i++ )
+					callback.call( root(this[i], first), i > 0 ? extra.cloneNode(true) : fragment );
+			
+			if ( scripts )
+				jQuery.each( scripts, evalScript );
+		}
+
+		return this;
+		
+		function root( elem, cur ) {
+			return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
+				(elem.getElementsByTagName("tbody")[0] ||
+				elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+				elem;
+		}
+	}
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+function evalScript( i, elem ) {
+	if ( elem.src )
+		jQuery.ajax({
+			url: elem.src,
+			async: false,
+			dataType: "script"
+		});
+
+	else
+		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+
+	if ( elem.parentNode )
+		elem.parentNode.removeChild( elem );
+}
+
+function now(){
+	return +new Date;
+}
+
+jQuery.extend = jQuery.fn.extend = function() {
+	// copy reference to target object
+	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
+
+	// Handle a deep copy situation
+	if ( typeof target === "boolean" ) {
+		deep = target;
+		target = arguments[1] || {};
+		// skip the boolean and the target
+		i = 2;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target !== "object" && !jQuery.isFunction(target) )
+		target = {};
+
+	// extend jQuery itself if only one argument is passed
+	if ( length == i ) {
+		target = this;
+		--i;
+	}
+
+	for ( ; i < length; i++ )
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null )
+			// Extend the base object
+			for ( var name in options ) {
+				var src = target[ name ], copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy )
+					continue;
+
+				// Recurse if we're merging object values
+				if ( deep && copy && typeof copy === "object" && !copy.nodeType )
+					target[ name ] = jQuery.extend( deep, 
+						// Never move original objects, clone them
+						src || ( copy.length != null ? [ ] : { } )
+					, copy );
+
+				// Don't bring in undefined values
+				else if ( copy !== undefined )
+					target[ name ] = copy;
+
+			}
+
+	// Return the modified object
+	return target;
+};
+
+// exclude the following css properties to add px
+var	exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
+	// cache defaultView
+	defaultView = document.defaultView || {},
+	toString = Object.prototype.toString;
+
+jQuery.extend({
+	noConflict: function( deep ) {
+		window.$ = _$;
+
+		if ( deep )
+			window.jQuery = _jQuery;
+
+		return jQuery;
+	},
+
+	// See test/unit/core.js for details concerning isFunction.
+	// Since version 1.3, DOM methods and functions like alert
+	// aren't supported. They return false on IE (#2968).
+	isFunction: function( obj ) {
+		return toString.call(obj) === "[object Function]";
+	},
+
+	isArray: function( obj ) {
+		return toString.call(obj) === "[object Array]";
+	},
+
+	// check if an element is in a (or is an) XML document
+	isXMLDoc: function( elem ) {
+		return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+			!!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
+	},
+
+	// Evalulates a script in a global context
+	globalEval: function( data ) {
+		data = jQuery.trim( data );
+
+		if ( data ) {
+			// Inspired by code by Andrea Giammarchi
+			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+			var head = document.getElementsByTagName("head")[0] || document.documentElement,
+				script = document.createElement("script");
+
+			script.type = "text/javascript";
+			if ( jQuery.support.scriptEval )
+				script.appendChild( document.createTextNode( data ) );
+			else
+				script.text = data;
+
+			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
+			// This arises when a base node is used (#2709).
+			head.insertBefore( script, head.firstChild );
+			head.removeChild( script );
+		}
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+	},
+
+	// args is for internal usage only
+	each: function( object, callback, args ) {
+		var name, i = 0, length = object.length;
+
+		if ( args ) {
+			if ( length === undefined ) {
+				for ( name in object )
+					if ( callback.apply( object[ name ], args ) === false )
+						break;
+			} else
+				for ( ; i < length; )
+					if ( callback.apply( object[ i++ ], args ) === false )
+						break;
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( length === undefined ) {
+				for ( name in object )
+					if ( callback.call( object[ name ], name, object[ name ] ) === false )
+						break;
+			} else
+				for ( var value = object[0];
+					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
+		}
+
+		return object;
+	},
+
+	prop: function( elem, value, type, i, name ) {
+		// Handle executable functions
+		if ( jQuery.isFunction( value ) )
+			value = value.call( elem, i );
+
+		// Handle passing in a number to a CSS property
+		return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
+			value + "px" :
+			value;
+	},
+
+	className: {
+		// internal only, use addClass("class")
+		add: function( elem, classNames ) {
+			jQuery.each((classNames || "").split(/\s+/), function(i, className){
+				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
+					elem.className += (elem.className ? " " : "") + className;
+			});
+		},
+
+		// internal only, use removeClass("class")
+		remove: function( elem, classNames ) {
+			if (elem.nodeType == 1)
+				elem.className = classNames !== undefined ?
+					jQuery.grep(elem.className.split(/\s+/), function(className){
+						return !jQuery.className.has( classNames, className );
+					}).join(" ") :
+					"";
+		},
+
+		// internal only, use hasClass("class")
+		has: function( elem, className ) {
+			return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
+		}
+	},
+
+	// A method for quickly swapping in/out CSS properties to get correct calculations
+	swap: function( elem, options, callback ) {
+		var old = {};
+		// Remember the old values, and insert the new ones
+		for ( var name in options ) {
+			old[ name ] = elem.style[ name ];
+			elem.style[ name ] = options[ name ];
+		}
+
+		callback.call( elem );
+
+		// Revert the old values
+		for ( var name in options )
+			elem.style[ name ] = old[ name ];
+	},
+
+	css: function( elem, name, force ) {
+		if ( name == "width" || name == "height" ) {
+			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+
+			function getWH() {
+				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+				var padding = 0, border = 0;
+				jQuery.each( which, function() {
+					padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+					border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+				});
+				val -= Math.round(padding + border);
+			}
+
+			if ( jQuery(elem).is(":visible") )
+				getWH();
+			else
+				jQuery.swap( elem, props, getWH );
+
+			return Math.max(0, val);
+		}
+
+		return jQuery.curCSS( elem, name, force );
+	},
+
+	curCSS: function( elem, name, force ) {
+		var ret, style = elem.style;
+
+		// We need to handle opacity special in IE
+		if ( name == "opacity" && !jQuery.support.opacity ) {
+			ret = jQuery.attr( style, "opacity" );
+
+			return ret == "" ?
+				"1" :
+				ret;
+		}
+
+		// Make sure we're using the right name for getting the float value
+		if ( name.match( /float/i ) )
+			name = styleFloat;
+
+		if ( !force && style && style[ name ] )
+			ret = style[ name ];
+
+		else if ( defaultView.getComputedStyle ) {
+
+			// Only "float" is needed here
+			if ( name.match( /float/i ) )
+				name = "float";
+
+			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
+
+			var computedStyle = defaultView.getComputedStyle( elem, null );
+
+			if ( computedStyle )
+				ret = computedStyle.getPropertyValue( name );
+
+			// We should always get a number back from opacity
+			if ( name == "opacity" && ret == "" )
+				ret = "1";
+
+		} else if ( elem.currentStyle ) {
+			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
+				return letter.toUpperCase();
+			});
+
+			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+
+			// From the awesome hack by Dean Edwards
+			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+			// If we're not dealing with a regular pixel number
+			// but a number that has a weird ending, we need to convert it to pixels
+			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
+				// Remember the original values
+				var left = style.left, rsLeft = elem.runtimeStyle.left;
+
+				// Put in the new values to get a computed value out
+				elem.runtimeStyle.left = elem.currentStyle.left;
+				style.left = ret || 0;
+				ret = style.pixelLeft + "px";
+
+				// Revert the changed values
+				style.left = left;
+				elem.runtimeStyle.left = rsLeft;
+			}
+		}
+
+		return ret;
+	},
+
+	clean: function( elems, context, fragment ) {
+		context = context || document;
+
+		// !context.createElement fails in IE with an error but returns typeof 'object'
+		if ( typeof context.createElement === "undefined" )
+			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+
+		// If a single string is passed in and it's a single tag
+		// just do a createElement and skip the rest
+		if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
+			var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
+			if ( match )
+				return [ context.createElement( match[1] ) ];
+		}
+
+		var ret = [], scripts = [], div = context.createElement("div");
+
+		jQuery.each(elems, function(i, elem){
+			if ( typeof elem === "number" )
+				elem += '';
+
+			if ( !elem )
+				return;
+
+			// Convert html string into DOM nodes
+			if ( typeof elem === "string" ) {
+				// Fix "XHTML"-style tags in all browsers
+				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
+					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
+						all :
+						front + "></" + tag + ">";
+				});
+
+				// Trim whitespace, otherwise indexOf won't work as expected
+				var tags = jQuery.trim( elem ).toLowerCase();
+
+				var wrap =
+					// option or optgroup
+					!tags.indexOf("<opt") &&
+					[ 1, "<select multiple='multiple'>", "</select>" ] ||
+
+					!tags.indexOf("<leg") &&
+					[ 1, "<fieldset>", "</fieldset>" ] ||
+
+					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+					[ 1, "<table>", "</table>" ] ||
+
+					!tags.indexOf("<tr") &&
+					[ 2, "<table><tbody>", "</tbody></table>" ] ||
+
+				 	// <thead> matched above
+					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
+					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
+
+					!tags.indexOf("<col") &&
+					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
+
+					// IE can't serialize <link> and <script> tags normally
+					!jQuery.support.htmlSerialize &&
+					[ 1, "div<div>", "</div>" ] ||
+
+					[ 0, "", "" ];
+
+				// Go to html and back, then peel off extra wrappers
+				div.innerHTML = wrap[1] + elem + wrap[2];
+
+				// Move to the right depth
+				while ( wrap[0]-- )
+					div = div.lastChild;
+
+				// Remove IE's autoinserted <tbody> from table fragments
+				if ( !jQuery.support.tbody ) {
+
+					// String was a <table>, *may* have spurious <tbody>
+					var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
+						div.firstChild && div.firstChild.childNodes :
+
+						// String was a bare <thead> or <tfoot>
+						wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
+							div.childNodes :
+							[];
+
+					for ( var j = tbody.length - 1; j >= 0 ; --j )
+						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
+							tbody[ j ].parentNode.removeChild( tbody[ j ] );
+
+					}
+
+				// IE completely kills leading whitespace when innerHTML is used
+				if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
+					div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
+				
+				elem = jQuery.makeArray( div.childNodes );
+			}
+
+			if ( elem.nodeType )
+				ret.push( elem );
+			else
+				ret = jQuery.merge( ret, elem );
+
+		});
+
+		if ( fragment ) {
+			for ( var i = 0; ret[i]; i++ ) {
+				if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+				} else {
+					if ( ret[i].nodeType === 1 )
+						ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
+					fragment.appendChild( ret[i] );
+				}
+			}
+			
+			return scripts;
+		}
+
+		return ret;
+	},
+
+	attr: function( elem, name, value ) {
+		// don't set attributes on text and comment nodes
+		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+			return undefined;
+
+		var notxml = !jQuery.isXMLDoc( elem ),
+			// Whether we are setting (or getting)
+			set = value !== undefined;
+
+		// Try to normalize/fix the name
+		name = notxml && jQuery.props[ name ] || name;
+
+		// Only do all the following if this is a node (faster for style)
+		// IE elem.getAttribute passes even for style
+		if ( elem.tagName ) {
+
+			// These attributes require special treatment
+			var special = /href|src|style/.test( name );
+
+			// Safari mis-reports the default selected property of a hidden option
+			// Accessing the parent's selectedIndex property fixes it
+			if ( name == "selected" && elem.parentNode )
+				elem.parentNode.selectedIndex;
+
+			// If applicable, access the attribute via the DOM 0 way
+			if ( name in elem && notxml && !special ) {
+				if ( set ){
+					// We can't allow the type property to be changed (since it causes problems in IE)
+					if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
+						throw "type property can't be changed";
+
+					elem[ name ] = value;
+				}
+
+				// browsers index elements by id/name on forms, give priority to attributes.
+				if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
+					return elem.getAttributeNode( name ).nodeValue;
+
+				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+				if ( name == "tabIndex" ) {
+					var attributeNode = elem.getAttributeNode( "tabIndex" );
+					return attributeNode && attributeNode.specified
+						? attributeNode.value
+						: elem.nodeName.match(/(button|input|object|select|textarea)/i)
+							? 0
+							: elem.nodeName.match(/^(a|area)$/i) && elem.href
+								? 0
+								: undefined;
+				}
+
+				return elem[ name ];
+			}
+
+			if ( !jQuery.support.style && notxml &&  name == "style" )
+				return jQuery.attr( elem.style, "cssText", value );
+
+			if ( set )
+				// convert the value to a string (all browsers do this but IE) see #1070
+				elem.setAttribute( name, "" + value );
+
+			var attr = !jQuery.support.hrefNormalized && notxml && special
+					// Some attributes require a special call on IE
+					? elem.getAttribute( name, 2 )
+					: elem.getAttribute( name );
+
+			// Non-existent attributes return null, we normalize to undefined
+			return attr === null ? undefined : attr;
+		}
+
+		// elem is actually elem.style ... set the style
+
+		// IE uses filters for opacity
+		if ( !jQuery.support.opacity && name == "opacity" ) {
+			if ( set ) {
+				// IE has trouble with opacity if it does not have layout
+				// Force it by setting the zoom level
+				elem.zoom = 1;
+
+				// Set the alpha filter to set the opacity
+				elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
+					(parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
+			}
+
+			return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
+				(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
+				"";
+		}
+
+		name = name.replace(/-([a-z])/ig, function(all, letter){
+			return letter.toUpperCase();
+		});
+
+		if ( set )
+			elem[ name ] = value;
+
+		return elem[ name ];
+	},
+
+	trim: function( text ) {
+		return (text || "").replace( /^\s+|\s+$/g, "" );
+	},
+
+	makeArray: function( array ) {
+		var ret = [];
+
+		if( array != null ){
+			var i = array.length;
+			// The window, strings (and functions) also have 'length'
+			if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
+				ret[0] = array;
+			else
+				while( i )
+					ret[--i] = array[i];
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, array ) {
+		for ( var i = 0, length = array.length; i < length; i++ )
+		// Use === because on IE, window == document
+			if ( array[ i ] === elem )
+				return i;
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		// We have to loop this way because IE & Opera overwrite the length
+		// expando of getElementsByTagName
+		var i = 0, elem, pos = first.length;
+		// Also, we need to make sure that the correct elements are being returned
+		// (IE returns comment nodes in a '*' query)
+		if ( !jQuery.support.getAll ) {
+			while ( (elem = second[ i++ ]) != null )
+				if ( elem.nodeType != 8 )
+					first[ pos++ ] = elem;
+
+		} else
+			while ( (elem = second[ i++ ]) != null )
+				first[ pos++ ] = elem;
+
+		return first;
+	},
+
+	unique: function( array ) {
+		var ret = [], done = {};
+
+		try {
+
+			for ( var i = 0, length = array.length; i < length; i++ ) {
+				var id = jQuery.data( array[ i ] );
+
+				if ( !done[ id ] ) {
+					done[ id ] = true;
+					ret.push( array[ i ] );
+				}
+			}
+
+		} catch( e ) {
+			ret = array;
+		}
+
+		return ret;
+	},
+
+	grep: function( elems, callback, inv ) {
+		var ret = [];
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( var i = 0, length = elems.length; i < length; i++ )
+			if ( !inv != !callback( elems[ i ], i ) )
+				ret.push( elems[ i ] );
+
+		return ret;
+	},
+
+	map: function( elems, callback ) {
+		var ret = [];
+
+		// Go through the array, translating each of the items to their
+		// new value (or values).
+		for ( var i = 0, length = elems.length; i < length; i++ ) {
+			var value = callback( elems[ i ], i );
+
+			if ( value != null )
+				ret[ ret.length ] = value;
+		}
+
+		return ret.concat.apply( [], ret );
+	}
+});
+
+// Use of jQuery.browser is deprecated.
+// It's included for backwards compatibility and plugins,
+// although they should work to migrate away.
+
+var userAgent = navigator.userAgent.toLowerCase();
+
+// Figure out what browser is being used
+jQuery.browser = {
+	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
+	safari: /webkit/.test( userAgent ),
+	opera: /opera/.test( userAgent ),
+	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
+	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
+};
+
+jQuery.each({
+	parent: function(elem){return elem.parentNode;},
+	parents: function(elem){return jQuery.dir(elem,"parentNode");},
+	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
+	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
+	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
+	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
+	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
+	children: function(elem){return jQuery.sibling(elem.firstChild);},
+	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
+}, function(name, fn){
+	jQuery.fn[ name ] = function( selector ) {
+		var ret = jQuery.map( this, fn );
+
+		if ( selector && typeof selector == "string" )
+			ret = jQuery.multiFilter( selector, ret );
+
+		return this.pushStack( jQuery.unique( ret ), name, selector );
+	};
+});
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function(name, original){
+	jQuery.fn[ name ] = function() {
+		var args = arguments;
+
+		return this.each(function(){
+			for ( var i = 0, length = args.length; i < length; i++ )
+				jQuery( args[ i ] )[ original ]( this );
+		});
+	};
+});
+
+jQuery.each({
+	removeAttr: function( name ) {
+		jQuery.attr( this, name, "" );
+		if (this.nodeType == 1)
+			this.removeAttribute( name );
+	},
+
+	addClass: function( classNames ) {
+		jQuery.className.add( this, classNames );
+	},
+
+	removeClass: function( classNames ) {
+		jQuery.className.remove( this, classNames );
+	},
+
+	toggleClass: function( classNames, state ) {
+		if( typeof state !== "boolean" )
+			state = !jQuery.className.has( this, classNames );
+		jQuery.className[ state ? "add" : "remove" ]( this, classNames );
+	},
+
+	remove: function( selector ) {
+		if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
+			// Prevent memory leaks
+			jQuery( "*", this ).add([this]).each(function(){
+				jQuery.event.remove(this);
+				jQuery.removeData(this);
+			});
+			if (this.parentNode)
+				this.parentNode.removeChild( this );
+		}
+	},
+
+	empty: function() {
+		// Remove element nodes and prevent memory leaks
+		jQuery( ">*", this ).remove();
+
+		// Remove any remaining nodes
+		while ( this.firstChild )
+			this.removeChild( this.firstChild );
+	}
+}, function(name, fn){
+	jQuery.fn[ name ] = function(){
+		return this.each( fn, arguments );
+	};
+});
+
+// Helper function used by the dimensions and offset modules
+function num(elem, prop) {
+	return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
+}
+var expando = "jQuery" + now(), uuid = 0, windowData = {};

+

+jQuery.extend({

+	cache: {},

+

+	data: function( elem, name, data ) {

+		elem = elem == window ?

+			windowData :

+			elem;

+

+		var id = elem[ expando ];

+

+		// Compute a unique ID for the element

+		if ( !id )

+			id = elem[ expando ] = ++uuid;

+

+		// Only generate the data cache if we're

+		// trying to access or manipulate it

+		if ( name && !jQuery.cache[ id ] )

+			jQuery.cache[ id ] = {};

+

+		// Prevent overriding the named cache with undefined values

+		if ( data !== undefined )

+			jQuery.cache[ id ][ name ] = data;

+

+		// Return the named cache data, or the ID for the element

+		return name ?

+			jQuery.cache[ id ][ name ] :

+			id;

+	},

+

+	removeData: function( elem, name ) {

+		elem = elem == window ?

+			windowData :

+			elem;

+

+		var id = elem[ expando ];

+

+		// If we want to remove a specific section of the element's data

+		if ( name ) {

+			if ( jQuery.cache[ id ] ) {

+				// Remove the section of cache data

+				delete jQuery.cache[ id ][ name ];

+

+				// If we've removed all the data, remove the element's cache

+				name = "";

+

+				for ( name in jQuery.cache[ id ] )

+					break;

+

+				if ( !name )

+					jQuery.removeData( elem );

+			}

+

+		// Otherwise, we want to remove all of the element's data

+		} else {

+			// Clean up the element expando

+			try {

+				delete elem[ expando ];

+			} catch(e){

+				// IE has trouble directly removing the expando

+				// but it's ok with using removeAttribute

+				if ( elem.removeAttribute )

+					elem.removeAttribute( expando );

+			}

+

+			// Completely remove the data cache

+			delete jQuery.cache[ id ];

+		}

+	},

+	queue: function( elem, type, data ) {

+		if ( elem ){

+	

+			type = (type || "fx") + "queue";

+	

+			var q = jQuery.data( elem, type );

+	

+			if ( !q || jQuery.isArray(data) )

+				q = jQuery.data( elem, type, jQuery.makeArray(data) );

+			else if( data )

+				q.push( data );

+	

+		}

+		return q;

+	},

+

+	dequeue: function( elem, type ){

+		var queue = jQuery.queue( elem, type ),

+			fn = queue.shift();

+		

+		if( !type || type === "fx" )

+			fn = queue[0];

+			

+		if( fn !== undefined )

+			fn.call(elem);

+	}

+});

+

+jQuery.fn.extend({

+	data: function( key, value ){

+		var parts = key.split(".");

+		parts[1] = parts[1] ? "." + parts[1] : "";

+

+		if ( value === undefined ) {

+			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);

+

+			if ( data === undefined && this.length )

+				data = jQuery.data( this[0], key );

+

+			return data === undefined && parts[1] ?

+				this.data( parts[0] ) :

+				data;

+		} else

+			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){

+				jQuery.data( this, key, value );

+			});

+	},

+

+	removeData: function( key ){

+		return this.each(function(){

+			jQuery.removeData( this, key );

+		});

+	},

+	queue: function(type, data){

+		if ( typeof type !== "string" ) {

+			data = type;

+			type = "fx";

+		}

+

+		if ( data === undefined )

+			return jQuery.queue( this[0], type );

+

+		return this.each(function(){

+			var queue = jQuery.queue( this, type, data );

+			

+			 if( type == "fx" && queue.length == 1 )

+				queue[0].call(this);

+		});

+	},

+	dequeue: function(type){

+		return this.each(function(){

+			jQuery.dequeue( this, type );

+		});

+	}

+});/*!
+ * Sizzle CSS Selector Engine - v0.9.3
+ *  Copyright 2009, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]+['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,
+	done = 0,
+	toString = Object.prototype.toString;
+
+var Sizzle = function(selector, context, results, seed) {
+	results = results || [];
+	context = context || document;
+
+	if ( context.nodeType !== 1 && context.nodeType !== 9 )
+		return [];
+	
+	if ( !selector || typeof selector !== "string" ) {
+		return results;
+	}
+
+	var parts = [], m, set, checkSet, check, mode, extra, prune = true;
+	
+	// Reset the position of the chunker regexp (start from head)
+	chunker.lastIndex = 0;
+	
+	while ( (m = chunker.exec(selector)) !== null ) {
+		parts.push( m[1] );
+		
+		if ( m[2] ) {
+			extra = RegExp.rightContext;
+			break;
+		}
+	}
+
+	if ( parts.length > 1 && origPOS.exec( selector ) ) {
+		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+			set = posProcess( parts[0] + parts[1], context );
+		} else {
+			set = Expr.relative[ parts[0] ] ?
+				[ context ] :
+				Sizzle( parts.shift(), context );
+
+			while ( parts.length ) {
+				selector = parts.shift();
+
+				if ( Expr.relative[ selector ] )
+					selector += parts.shift();
+
+				set = posProcess( selector, set );
+			}
+		}
+	} else {
+		var ret = seed ?
+			{ expr: parts.pop(), set: makeArray(seed) } :
+			Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
+		set = Sizzle.filter( ret.expr, ret.set );
+
+		if ( parts.length > 0 ) {
+			checkSet = makeArray(set);
+		} else {
+			prune = false;
+		}
+
+		while ( parts.length ) {
+			var cur = parts.pop(), pop = cur;
+
+			if ( !Expr.relative[ cur ] ) {
+				cur = "";
+			} else {
+				pop = parts.pop();
+			}
+
+			if ( pop == null ) {
+				pop = context;
+			}
+
+			Expr.relative[ cur ]( checkSet, pop, isXML(context) );
+		}
+	}
+
+	if ( !checkSet ) {
+		checkSet = set;
+	}
+
+	if ( !checkSet ) {
+		throw "Syntax error, unrecognized expression: " + (cur || selector);
+	}
+
+	if ( toString.call(checkSet) === "[object Array]" ) {
+		if ( !prune ) {
+			results.push.apply( results, checkSet );
+		} else if ( context.nodeType === 1 ) {
+			for ( var i = 0; checkSet[i] != null; i++ ) {
+				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
+					results.push( set[i] );
+				}
+			}
+		} else {
+			for ( var i = 0; checkSet[i] != null; i++ ) {
+				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+					results.push( set[i] );
+				}
+			}
+		}
+	} else {
+		makeArray( checkSet, results );
+	}
+
+	if ( extra ) {
+		Sizzle( extra, context, results, seed );
+	}
+
+	return results;
+};
+
+Sizzle.matches = function(expr, set){
+	return Sizzle(expr, null, null, set);
+};
+
+Sizzle.find = function(expr, context, isXML){
+	var set, match;
+
+	if ( !expr ) {
+		return [];
+	}
+
+	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+		var type = Expr.order[i], match;
+		
+		if ( (match = Expr.match[ type ].exec( expr )) ) {
+			var left = RegExp.leftContext;
+
+			if ( left.substr( left.length - 1 ) !== "\\" ) {
+				match[1] = (match[1] || "").replace(/\\/g, "");
+				set = Expr.find[ type ]( match, context, isXML );
+				if ( set != null ) {
+					expr = expr.replace( Expr.match[ type ], "" );
+					break;
+				}
+			}
+		}
+	}
+
+	if ( !set ) {
+		set = context.getElementsByTagName("*");
+	}
+
+	return {set: set, expr: expr};
+};
+
+Sizzle.filter = function(expr, set, inplace, not){
+	var old = expr, result = [], curLoop = set, match, anyFound;
+
+	while ( expr && set.length ) {
+		for ( var type in Expr.filter ) {
+			if ( (match = Expr.match[ type ].exec( expr )) != null ) {
+				var filter = Expr.filter[ type ], found, item;
+				anyFound = false;
+
+				if ( curLoop == result ) {
+					result = [];
+				}
+
+				if ( Expr.preFilter[ type ] ) {
+					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not );
+
+					if ( !match ) {
+						anyFound = found = true;
+					} else if ( match === true ) {
+						continue;
+					}
+				}
+
+				if ( match ) {
+					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
+						if ( item ) {
+							found = filter( item, match, i, curLoop );
+							var pass = not ^ !!found;
+
+							if ( inplace && found != null ) {
+								if ( pass ) {
+									anyFound = true;
+								} else {
+									curLoop[i] = false;
+								}
+							} else if ( pass ) {
+								result.push( item );
+								anyFound = true;
+							}
+						}
+					}
+				}
+
+				if ( found !== undefined ) {
+					if ( !inplace ) {
+						curLoop = result;
+					}
+
+					expr = expr.replace( Expr.match[ type ], "" );
+
+					if ( !anyFound ) {
+						return [];
+					}
+
+					break;
+				}
+			}
+		}
+
+		expr = expr.replace(/\s*,\s*/, "");
+
+		// Improper expression
+		if ( expr == old ) {
+			if ( anyFound == null ) {
+				throw "Syntax error, unrecognized expression: " + expr;
+			} else {
+				break;
+			}
+		}
+
+		old = expr;
+	}
+
+	return curLoop;
+};
+
+var Expr = Sizzle.selectors = {
+	order: [ "ID", "NAME", "TAG" ],
+	match: {
+		ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+		CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
+		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+		TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
+		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
+		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
+		PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
+	},
+	attrMap: {
+		"class": "className",
+		"for": "htmlFor"
+	},
+	attrHandle: {
+		href: function(elem){
+			return elem.getAttribute("href");
+		}
+	},
+	relative: {
+		"+": function(checkSet, part){
+			for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+				var elem = checkSet[i];
+				if ( elem ) {
+					var cur = elem.previousSibling;
+					while ( cur && cur.nodeType !== 1 ) {
+						cur = cur.previousSibling;
+					}
+					checkSet[i] = typeof part === "string" ?
+						cur || false :
+						cur === part;
+				}
+			}
+
+			if ( typeof part === "string" ) {
+				Sizzle.filter( part, checkSet, true );
+			}
+		},
+		">": function(checkSet, part, isXML){
+			if ( typeof part === "string" && !/\W/.test(part) ) {
+				part = isXML ? part : part.toUpperCase();
+
+				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+					var elem = checkSet[i];
+					if ( elem ) {
+						var parent = elem.parentNode;
+						checkSet[i] = parent.nodeName === part ? parent : false;
+					}
+				}
+			} else {
+				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+					var elem = checkSet[i];
+					if ( elem ) {
+						checkSet[i] = typeof part === "string" ?
+							elem.parentNode :
+							elem.parentNode === part;
+					}
+				}
+
+				if ( typeof part === "string" ) {
+					Sizzle.filter( part, checkSet, true );
+				}
+			}
+		},
+		"": function(checkSet, part, isXML){
+			var doneName = "done" + (done++), checkFn = dirCheck;
+
+			if ( !part.match(/\W/) ) {
+				var nodeCheck = part = isXML ? part : part.toUpperCase();
+				checkFn = dirNodeCheck;
+			}
+
+			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
+		},
+		"~": function(checkSet, part, isXML){
+			var doneName = "done" + (done++), checkFn = dirCheck;
+
+			if ( typeof part === "string" && !part.match(/\W/) ) {
+				var nodeCheck = part = isXML ? part : part.toUpperCase();
+				checkFn = dirNodeCheck;
+			}
+
+			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
+		}
+	},
+	find: {
+		ID: function(match, context, isXML){
+			if ( typeof context.getElementById !== "undefined" && !isXML ) {
+				var m = context.getElementById(match[1]);
+				return m ? [m] : [];
+			}
+		},
+		NAME: function(match, context, isXML){
+			if ( typeof context.getElementsByName !== "undefined" && !isXML ) {
+				return context.getElementsByName(match[1]);
+			}
+		},
+		TAG: function(match, context){
+			return context.getElementsByTagName(match[1]);
+		}
+	},
+	preFilter: {
+		CLASS: function(match, curLoop, inplace, result, not){
+			match = " " + match[1].replace(/\\/g, "") + " ";
+
+			var elem;
+			for ( var i = 0; (elem = curLoop[i]) != null; i++ ) {
+				if ( elem ) {
+					if ( not ^ (" " + elem.className + " ").indexOf(match) >= 0 ) {
+						if ( !inplace )
+							result.push( elem );
+					} else if ( inplace ) {
+						curLoop[i] = false;
+					}
+				}
+			}
+
+			return false;
+		},
+		ID: function(match){
+			return match[1].replace(/\\/g, "");
+		},
+		TAG: function(match, curLoop){
+			for ( var i = 0; curLoop[i] === false; i++ ){}
+			return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
+		},
+		CHILD: function(match){
+			if ( match[1] == "nth" ) {
+				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+					match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
+					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+				// calculate the numbers (first)n+(last) including if they are negative
+				match[2] = (test[1] + (test[2] || 1)) - 0;
+				match[3] = test[3] - 0;
+			}
+
+			// TODO: Move to normal caching system
+			match[0] = "done" + (done++);
+
+			return match;
+		},
+		ATTR: function(match){
+			var name = match[1].replace(/\\/g, "");
+			
+			if ( Expr.attrMap[name] ) {
+				match[1] = Expr.attrMap[name];
+			}
+
+			if ( match[2] === "~=" ) {
+				match[4] = " " + match[4] + " ";
+			}
+
+			return match;
+		},
+		PSEUDO: function(match, curLoop, inplace, result, not){
+			if ( match[1] === "not" ) {
+				// If we're dealing with a complex expression, or a simple one
+				if ( match[3].match(chunker).length > 1 ) {
+					match[3] = Sizzle(match[3], null, null, curLoop);
+				} else {
+					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+					if ( !inplace ) {
+						result.push.apply( result, ret );
+					}
+					return false;
+				}
+			} else if ( Expr.match.POS.test( match[0] ) ) {
+				return true;
+			}
+			
+			return match;
+		},
+		POS: function(match){
+			match.unshift( true );
+			return match;
+		}
+	},
+	filters: {
+		enabled: function(elem){
+			return elem.disabled === false && elem.type !== "hidden";
+		},
+		disabled: function(elem){
+			return elem.disabled === true;
+		},
+		checked: function(elem){
+			return elem.checked === true;
+		},
+		selected: function(elem){
+			// Accessing this property makes selected-by-default
+			// options in Safari work properly
+			elem.parentNode.selectedIndex;
+			return elem.selected === true;
+		},
+		parent: function(elem){
+			return !!elem.firstChild;
+		},
+		empty: function(elem){
+			return !elem.firstChild;
+		},
+		has: function(elem, i, match){
+			return !!Sizzle( match[3], elem ).length;
+		},
+		header: function(elem){
+			return /h\d/i.test( elem.nodeName );
+		},
+		text: function(elem){
+			return "text" === elem.type;
+		},
+		radio: function(elem){
+			return "radio" === elem.type;
+		},
+		checkbox: function(elem){
+			return "checkbox" === elem.type;
+		},
+		file: function(elem){
+			return "file" === elem.type;
+		},
+		password: function(elem){
+			return "password" === elem.type;
+		},
+		submit: function(elem){
+			return "submit" === elem.type;
+		},
+		image: function(elem){
+			return "image" === elem.type;
+		},
+		reset: function(elem){
+			return "reset" === elem.type;
+		},
+		button: function(elem){
+			return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
+		},
+		input: function(elem){
+			return /input|select|textarea|button/i.test(elem.nodeName);
+		}
+	},
+	setFilters: {
+		first: function(elem, i){
+			return i === 0;
+		},
+		last: function(elem, i, match, array){
+			return i === array.length - 1;
+		},
+		even: function(elem, i){
+			return i % 2 === 0;
+		},
+		odd: function(elem, i){
+			return i % 2 === 1;
+		},
+		lt: function(elem, i, match){
+			return i < match[3] - 0;
+		},
+		gt: function(elem, i, match){
+			return i > match[3] - 0;
+		},
+		nth: function(elem, i, match){
+			return match[3] - 0 == i;
+		},
+		eq: function(elem, i, match){
+			return match[3] - 0 == i;
+		}
+	},
+	filter: {
+		CHILD: function(elem, match){
+			var type = match[1], parent = elem.parentNode;
+
+			var doneName = match[0];
+			
+			if ( parent && (!parent[ doneName ] || !elem.nodeIndex) ) {
+				var count = 1;
+
+				for ( var node = parent.firstChild; node; node = node.nextSibling ) {
+					if ( node.nodeType == 1 ) {
+						node.nodeIndex = count++;
+					}
+				}
+
+				parent[ doneName ] = count - 1;
+			}
+
+			if ( type == "first" ) {
+				return elem.nodeIndex == 1;
+			} else if ( type == "last" ) {
+				return elem.nodeIndex == parent[ doneName ];
+			} else if ( type == "only" ) {
+				return parent[ doneName ] == 1;
+			} else if ( type == "nth" ) {
+				var add = false, first = match[2], last = match[3];
+
+				if ( first == 1 && last == 0 ) {
+					return true;
+				}
+
+				if ( first == 0 ) {
+					if ( elem.nodeIndex == last ) {
+						add = true;
+					}
+				} else if ( (elem.nodeIndex - last) % first == 0 && (elem.nodeIndex - last) / first >= 0 ) {
+					add = true;
+				}
+
+				return add;
+			}
+		},
+		PSEUDO: function(elem, match, i, array){
+			var name = match[1], filter = Expr.filters[ name ];
+
+			if ( filter ) {
+				return filter( elem, i, match, array );
+			} else if ( name === "contains" ) {
+				return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
+			} else if ( name === "not" ) {
+				var not = match[3];
+
+				for ( var i = 0, l = not.length; i < l; i++ ) {
+					if ( not[i] === elem ) {
+						return false;
+					}
+				}
+
+				return true;
+			}
+		},
+		ID: function(elem, match){
+			return elem.nodeType === 1 && elem.getAttribute("id") === match;
+		},
+		TAG: function(elem, match){
+			return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
+		},
+		CLASS: function(elem, match){
+			return match.test( elem.className );
+		},
+		ATTR: function(elem, match){
+			var result = Expr.attrHandle[ match[1] ] ? Expr.attrHandle[ match[1] ]( elem ) : elem[ match[1] ] || elem.getAttribute( match[1] ), value = result + "", type = match[2], check = match[4];
+			return result == null ?
+				type === "!=" :
+				type === "=" ?
+				value === check :
+				type === "*=" ?
+				value.indexOf(check) >= 0 :
+				type === "~=" ?
+				(" " + value + " ").indexOf(check) >= 0 :
+				!match[4] ?
+				result :
+				type === "!=" ?
+				value != check :
+				type === "^=" ?
+				value.indexOf(check) === 0 :
+				type === "$=" ?
+				value.substr(value.length - check.length) === check :
+				type === "|=" ?
+				value === check || value.substr(0, check.length + 1) === check + "-" :
+				false;
+		},
+		POS: function(elem, match, i, array){
+			var name = match[2], filter = Expr.setFilters[ name ];
+
+			if ( filter ) {
+				return filter( elem, i, match, array );
+			}
+		}
+	}
+};
+
+var origPOS = Expr.match.POS;
+
+for ( var type in Expr.match ) {
+	Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
+}
+
+var makeArray = function(array, results) {
+	array = Array.prototype.slice.call( array );
+
+	if ( results ) {
+		results.push.apply( results, array );
+		return results;
+	}
+	
+	return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+try {
+	Array.prototype.slice.call( document.documentElement.childNodes );
+
+// Provide a fallback method if it does not work
+} catch(e){
+	makeArray = function(array, results) {
+		var ret = results || [];
+
+		if ( toString.call(array) === "[object Array]" ) {
+			Array.prototype.push.apply( ret, array );
+		} else {
+			if ( typeof array.length === "number" ) {
+				for ( var i = 0, l = array.length; i < l; i++ ) {
+					ret.push( array[i] );
+				}
+			} else {
+				for ( var i = 0; array[i]; i++ ) {
+					ret.push( array[i] );
+				}
+			}
+		}
+
+		return ret;
+	};
+}
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+	// We're going to inject a fake input element with a specified name
+	var form = document.createElement("form"),
+		id = "script" + (new Date).getTime();
+	form.innerHTML = "<input name='" + id + "'/>";
+
+	// Inject it into the root element, check its status, and remove it quickly
+	var root = document.documentElement;
+	root.insertBefore( form, root.firstChild );
+
+	// The workaround has to do additional checks after a getElementById
+	// Which slows things down for other browsers (hence the branching)
+	if ( !!document.getElementById( id ) ) {
+		Expr.find.ID = function(match, context, isXML){
+			if ( typeof context.getElementById !== "undefined" && !isXML ) {
+				var m = context.getElementById(match[1]);
+				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
+			}
+		};
+
+		Expr.filter.ID = function(elem, match){
+			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+			return elem.nodeType === 1 && node && node.nodeValue === match;
+		};
+	}
+
+	root.removeChild( form );
+})();
+
+(function(){
+	// Check to see if the browser returns only elements
+	// when doing getElementsByTagName("*")
+
+	// Create a fake element
+	var div = document.createElement("div");
+	div.appendChild( document.createComment("") );
+
+	// Make sure no comments are found
+	if ( div.getElementsByTagName("*").length > 0 ) {
+		Expr.find.TAG = function(match, context){
+			var results = context.getElementsByTagName(match[1]);
+
+			// Filter out possible comments
+			if ( match[1] === "*" ) {
+				var tmp = [];
+
+				for ( var i = 0; results[i]; i++ ) {
+					if ( results[i].nodeType === 1 ) {
+						tmp.push( results[i] );
+					}
+				}
+
+				results = tmp;
+			}
+
+			return results;
+		};
+	}
+
+	// Check to see if an attribute returns normalized href attributes
+	div.innerHTML = "<a href='#'></a>";
+	if ( div.firstChild && div.firstChild.getAttribute("href") !== "#" ) {
+		Expr.attrHandle.href = function(elem){
+			return elem.getAttribute("href", 2);
+		};
+	}
+})();
+
+if ( document.querySelectorAll ) (function(){
+	var oldSizzle = Sizzle, div = document.createElement("div");
+	div.innerHTML = "<p class='TEST'></p>";
+
+	// Safari can't handle uppercase or unicode characters when
+	// in quirks mode.
+	if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+		return;
+	}
+	
+	Sizzle = function(query, context, extra, seed){
+		context = context || document;
+
+		// Only use querySelectorAll on non-XML documents
+		// (ID selectors don't work in non-HTML documents)
+		if ( !seed && context.nodeType === 9 && !isXML(context) ) {
+			try {
+				return makeArray( context.querySelectorAll(query), extra );
+			} catch(e){}
+		}
+		
+		return oldSizzle(query, context, extra, seed);
+	};
+
+	Sizzle.find = oldSizzle.find;
+	Sizzle.filter = oldSizzle.filter;
+	Sizzle.selectors = oldSizzle.selectors;
+	Sizzle.matches = oldSizzle.matches;
+})();
+
+if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) {
+	Expr.order.splice(1, 0, "CLASS");
+	Expr.find.CLASS = function(match, context) {
+		return context.getElementsByClassName(match[1]);
+	};
+}
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+		var elem = checkSet[i];
+		if ( elem ) {
+			elem = elem[dir];
+			var match = false;
+
+			while ( elem && elem.nodeType ) {
+				var done = elem[doneName];
+				if ( done ) {
+					match = checkSet[ done ];
+					break;
+				}
+
+				if ( elem.nodeType === 1 && !isXML )
+					elem[doneName] = i;
+
+				if ( elem.nodeName === cur ) {
+					match = elem;
+					break;
+				}
+
+				elem = elem[dir];
+			}
+
+			checkSet[i] = match;
+		}
+	}
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+		var elem = checkSet[i];
+		if ( elem ) {
+			elem = elem[dir];
+			var match = false;
+
+			while ( elem && elem.nodeType ) {
+				if ( elem[doneName] ) {
+					match = checkSet[ elem[doneName] ];
+					break;
+				}
+
+				if ( elem.nodeType === 1 ) {
+					if ( !isXML )
+						elem[doneName] = i;
+
+					if ( typeof cur !== "string" ) {
+						if ( elem === cur ) {
+							match = true;
+							break;
+						}
+
+					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+						match = elem;
+						break;
+					}
+				}
+
+				elem = elem[dir];
+			}
+
+			checkSet[i] = match;
+		}
+	}
+}
+
+var contains = document.compareDocumentPosition ?  function(a, b){
+	return a.compareDocumentPosition(b) & 16;
+} : function(a, b){
+	return a !== b && (a.contains ? a.contains(b) : true);
+};
+
+var isXML = function(elem){
+	return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+		!!elem.ownerDocument && isXML( elem.ownerDocument );
+};
+
+var posProcess = function(selector, context){
+	var tmpSet = [], later = "", match,
+		root = context.nodeType ? [context] : context;
+
+	// Position selectors must be done after the filter
+	// And so must :not(positional) so we move all PSEUDOs to the end
+	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+		later += match[0];
+		selector = selector.replace( Expr.match.PSEUDO, "" );
+	}
+
+	selector = Expr.relative[selector] ? selector + "*" : selector;
+
+	for ( var i = 0, l = root.length; i < l; i++ ) {
+		Sizzle( selector, root[i], tmpSet );
+	}
+
+	return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+jQuery.find = Sizzle;
+jQuery.filter = Sizzle.filter;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+
+Sizzle.selectors.filters.hidden = function(elem){
+	return "hidden" === elem.type ||
+		jQuery.css(elem, "display") === "none" ||
+		jQuery.css(elem, "visibility") === "hidden";
+};
+
+Sizzle.selectors.filters.visible = function(elem){
+	return "hidden" !== elem.type &&
+		jQuery.css(elem, "display") !== "none" &&
+		jQuery.css(elem, "visibility") !== "hidden";
+};
+
+Sizzle.selectors.filters.animated = function(elem){
+	return jQuery.grep(jQuery.timers, function(fn){
+		return elem === fn.elem;
+	}).length;
+};
+
+jQuery.multiFilter = function( expr, elems, not ) {
+	if ( not ) {
+		expr = ":not(" + expr + ")";
+	}
+
+	return Sizzle.matches(expr, elems);
+};
+
+jQuery.dir = function( elem, dir ){
+	var matched = [], cur = elem[dir];
+	while ( cur && cur != document ) {
+		if ( cur.nodeType == 1 )
+			matched.push( cur );
+		cur = cur[dir];
+	}
+	return matched;
+};
+
+jQuery.nth = function(cur, result, dir, elem){
+	result = result || 1;
+	var num = 0;
+
+	for ( ; cur; cur = cur[dir] )
+		if ( cur.nodeType == 1 && ++num == result )
+			break;
+
+	return cur;
+};
+
+jQuery.sibling = function(n, elem){
+	var r = [];
+
+	for ( ; n; n = n.nextSibling ) {
+		if ( n.nodeType == 1 && n != elem )
+			r.push( n );
+	}
+
+	return r;
+};
+
+return;
+
+window.Sizzle = Sizzle;
+
+})();
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+	// Bind an event to an element
+	// Original by Dean Edwards
+	add: function(elem, types, handler, data) {
+		if ( elem.nodeType == 3 || elem.nodeType == 8 )
+			return;
+
+		// For whatever reason, IE has trouble passing the window object
+		// around, causing it to be cloned in the process
+		if ( elem.setInterval && elem != window )
+			elem = window;
+
+		// Make sure that the function being executed has a unique ID
+		if ( !handler.guid )
+			handler.guid = this.guid++;
+
+		// if data is passed, bind to handler
+		if ( data !== undefined ) {
+			// Create temporary function pointer to original handler
+			var fn = handler;
+
+			// Create unique handler function, wrapped around original handler
+			handler = this.proxy( fn );
+
+			// Store data in unique handler
+			handler.data = data;
+		}
+
+		// Init the element's event structure
+		var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
+			handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
+				// Handle the second event of a trigger and when
+				// an event is called after a page has unloaded
+				return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
+					jQuery.event.handle.apply(arguments.callee.elem, arguments) :
+					undefined;
+			});
+		// Add elem as a property of the handle function
+		// This is to prevent a memory leak with non-native
+		// event in IE.
+		handle.elem = elem;
+
+		// Handle multiple events separated by a space
+		// jQuery(...).bind("mouseover mouseout", fn);
+		jQuery.each(types.split(/\s+/), function(index, type) {
+			// Namespaced event handlers
+			var namespaces = type.split(".");
+			type = namespaces.shift();
+			handler.type = namespaces.slice().sort().join(".");
+
+			// Get the current list of functions bound to this event
+			var handlers = events[type];
+			
+			if ( jQuery.event.specialAll[type] )
+				jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
+
+			// Init the event handler queue
+			if (!handlers) {
+				handlers = events[type] = {};
+
+				// Check for a special event handler
+				// Only use addEventListener/attachEvent if the special
+				// events handler returns false
+				if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
+					// Bind the global event handler to the element
+					if (elem.addEventListener)
+						elem.addEventListener(type, handle, false);
+					else if (elem.attachEvent)
+						elem.attachEvent("on" + type, handle);
+				}
+			}
+
+			// Add the function to the element's handler list
+			handlers[handler.guid] = handler;
+
+			// Keep track of which events have been used, for global triggering
+			jQuery.event.global[type] = true;
+		});
+
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	guid: 1,
+	global: {},
+
+	// Detach an event or set of events from an element
+	remove: function(elem, types, handler) {
+		// don't do events on text and comment nodes
+		if ( elem.nodeType == 3 || elem.nodeType == 8 )
+			return;
+
+		var events = jQuery.data(elem, "events"), ret, index;
+
+		if ( events ) {
+			// Unbind all events for the element
+			if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
+				for ( var type in events )
+					this.remove( elem, type + (types || "") );
+			else {
+				// types is actually an event object here
+				if ( types.type ) {
+					handler = types.handler;
+					types = types.type;
+				}
+
+				// Handle multiple events seperated by a space
+				// jQuery(...).unbind("mouseover mouseout", fn);
+				jQuery.each(types.split(/\s+/), function(index, type){
+					// Namespaced event handlers
+					var namespaces = type.split(".");
+					type = namespaces.shift();
+					var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+					if ( events[type] ) {
+						// remove the given handler for the given type
+						if ( handler )
+							delete events[type][handler.guid];
+
+						// remove all handlers for the given type
+						else
+							for ( var handle in events[type] )
+								// Handle the removal of namespaced events
+								if ( namespace.test(events[type][handle].type) )
+									delete events[type][handle];
+									
+						if ( jQuery.event.specialAll[type] )
+							jQuery.event.specialAll[type].teardown.call(elem, namespaces);
+
+						// remove generic event handler if no more handlers exist
+						for ( ret in events[type] ) break;
+						if ( !ret ) {
+							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
+								if (elem.removeEventListener)
+									elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+								else if (elem.detachEvent)
+									elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+							}
+							ret = null;
+							delete events[type];
+						}
+					}
+				});
+			}
+
+			// Remove the expando if it's no longer used
+			for ( ret in events ) break;
+			if ( !ret ) {
+				var handle = jQuery.data( elem, "handle" );
+				if ( handle ) handle.elem = null;
+				jQuery.removeData( elem, "events" );
+				jQuery.removeData( elem, "handle" );
+			}
+		}
+	},
+
+	// bubbling is internal
+	trigger: function( event, data, elem, bubbling ) {
+		// Event object or event type
+		var type = event.type || event;
+
+		if( !bubbling ){
+			event = typeof event === "object" ?
+				// jQuery.Event object
+				event[expando] ? event :
+				// Object literal
+				jQuery.extend( jQuery.Event(type), event ) :
+				// Just the event type (string)
+				jQuery.Event(type);
+
+			if ( type.indexOf("!") >= 0 ) {
+				event.type = type = type.slice(0, -1);
+				event.exclusive = true;
+			}
+
+			// Handle a global trigger
+			if ( !elem ) {
+				// Don't bubble custom events when global (to avoid too much overhead)
+				event.stopPropagation();
+				// Only trigger if we've ever bound an event for it
+				if ( this.global[type] )
+					jQuery.each( jQuery.cache, function(){
+						if ( this.events && this.events[type] )
+							jQuery.event.trigger( event, data, this.handle.elem );
+					});
+			}
+
+			// Handle triggering a single element
+
+			// don't do events on text and comment nodes
+			if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
+				return undefined;
+			
+			// Clean up in case it is reused
+			event.result = undefined;
+			event.target = elem;
+			
+			// Clone the incoming data, if any
+			data = jQuery.makeArray(data);
+			data.unshift( event );
+		}
+
+		event.currentTarget = elem;
+
+		// Trigger the event, it is assumed that "handle" is a function
+		var handle = jQuery.data(elem, "handle");
+		if ( handle )
+			handle.apply( elem, data );
+
+		// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
+		if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
+			event.result = false;
+
+		// Trigger the native events (except for clicks on links)
+		if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
+			this.triggered = true;
+			try {
+				elem[ type ]();
+			// prevent IE from throwing an error for some hidden elements
+			} catch (e) {}
+		}
+
+		this.triggered = false;
+
+		if ( !event.isPropagationStopped() ) {
+			var parent = elem.parentNode || elem.ownerDocument;
+			if ( parent )
+				jQuery.event.trigger(event, data, parent, true);
+		}
+	},
+
+	handle: function(event) {
+		// returned undefined or false
+		var all, handlers;
+
+		event = arguments[0] = jQuery.event.fix( event || window.event );
+
+		// Namespaced event handlers
+		var namespaces = event.type.split(".");
+		event.type = namespaces.shift();
+
+		// Cache this now, all = true means, any handler
+		all = !namespaces.length && !event.exclusive;
+		
+		var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+		handlers = ( jQuery.data(this, "events") || {} )[event.type];
+
+		for ( var j in handlers ) {
+			var handler = handlers[j];
+
+			// Filter the functions by class
+			if ( all || namespace.test(handler.type) ) {
+				// Pass in a reference to the handler function itself
+				// So that we can later remove it
+				event.handler = handler;
+				event.data = handler.data;
+
+				var ret = handler.apply(this, arguments);
+
+				if( ret !== undefined ){
+					event.result = ret;
+					if ( ret === false ) {
+						event.preventDefault();
+						event.stopPropagation();
+					}
+				}
+
+				if( event.isImmediatePropagationStopped() )
+					break;
+
+			}
+		}
+	},
+
+	props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+
+	fix: function(event) {
+		if ( event[expando] )
+			return event;
+
+		// store a copy of the original event object
+		// and "clone" to set read-only properties
+		var originalEvent = event;
+		event = jQuery.Event( originalEvent );
+
+		for ( var i = this.props.length, prop; i; ){
+			prop = this.props[ --i ];
+			event[ prop ] = originalEvent[ prop ];
+		}
+
+		// Fix target property, if necessary
+		if ( !event.target )
+			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+
+		// check if target is a textnode (safari)
+		if ( event.target.nodeType == 3 )
+			event.target = event.target.parentNode;
+
+		// Add relatedTarget, if necessary
+		if ( !event.relatedTarget && event.fromElement )
+			event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
+
+		// Calculate pageX/Y if missing and clientX/Y available
+		if ( event.pageX == null && event.clientX != null ) {
+			var doc = document.documentElement, body = document.body;
+			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
+			event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+		}
+
+		// Add which for key events
+		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
+			event.which = event.charCode || event.keyCode;
+
+		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+		if ( !event.metaKey && event.ctrlKey )
+			event.metaKey = event.ctrlKey;
+
+		// Add which for click: 1 == left; 2 == middle; 3 == right
+		// Note: button is not normalized, so don't use it
+		if ( !event.which && event.button )
+			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+
+		return event;
+	},
+
+	proxy: function( fn, proxy ){
+		proxy = proxy || function(){ return fn.apply(this, arguments); };
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
+		// So proxy can be declared as an argument
+		return proxy;
+	},
+
+	special: {
+		ready: {
+			// Make sure the ready event is setup
+			setup: bindReady,
+			teardown: function() {}
+		}
+	},
+	
+	specialAll: {
+		live: {
+			setup: function( selector, namespaces ){
+				jQuery.event.add( this, namespaces[0], liveHandler );
+			},
+			teardown:  function( namespaces ){
+				if ( namespaces.length ) {
+					var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
+					
+					jQuery.each( (jQuery.data(this, "events").live || {}), function(){
+						if ( name.test(this.type) )
+							remove++;
+					});
+					
+					if ( remove < 1 )
+						jQuery.event.remove( this, namespaces[0], liveHandler );
+				}
+			}
+		}
+	}
+};
+
+jQuery.Event = function( src ){
+	// Allow instantiation without the 'new' keyword
+	if( !this.preventDefault )
+		return new jQuery.Event(src);
+	
+	// Event object
+	if( src && src.type ){
+		this.originalEvent = src;
+		this.type = src.type;
+	// Event type
+	}else
+		this.type = src;
+
+	// timeStamp is buggy for some events on Firefox(#3843)
+	// So we won't rely on the native value
+	this.timeStamp = now();
+	
+	// Mark it as fixed
+	this[expando] = true;
+};
+
+function returnFalse(){
+	return false;
+}
+function returnTrue(){
+	return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+	preventDefault: function() {
+		this.isDefaultPrevented = returnTrue;
+
+		var e = this.originalEvent;
+		if( !e )
+			return;
+		// if preventDefault exists run it on the original event
+		if (e.preventDefault)
+			e.preventDefault();
+		// otherwise set the returnValue property of the original event to false (IE)
+		e.returnValue = false;
+	},
+	stopPropagation: function() {
+		this.isPropagationStopped = returnTrue;
+
+		var e = this.originalEvent;
+		if( !e )
+			return;
+		// if stopPropagation exists run it on the original event
+		if (e.stopPropagation)
+			e.stopPropagation();
+		// otherwise set the cancelBubble property of the original event to true (IE)
+		e.cancelBubble = true;
+	},
+	stopImmediatePropagation:function(){
+		this.isImmediatePropagationStopped = returnTrue;
+		this.stopPropagation();
+	},
+	isDefaultPrevented: returnFalse,
+	isPropagationStopped: returnFalse,
+	isImmediatePropagationStopped: returnFalse
+};
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function(event) {
+	// Check if mouse(over|out) are still within the same parent element
+	var parent = event.relatedTarget;
+	// Traverse up the tree
+	while ( parent && parent != this )
+		try { parent = parent.parentNode; }
+		catch(e) { parent = this; }
+	
+	if( parent != this ){
+		// set the correct event type
+		event.type = event.data;
+		// handle event if we actually just moused on to a non sub-element
+		jQuery.event.handle.apply( this, arguments );
+	}
+};
+	
+jQuery.each({ 
+	mouseover: 'mouseenter', 
+	mouseout: 'mouseleave'
+}, function( orig, fix ){
+	jQuery.event.special[ fix ] = {
+		setup: function(){
+			jQuery.event.add( this, orig, withinElement, fix );
+		},
+		teardown: function(){
+			jQuery.event.remove( this, orig, withinElement );
+		}
+	};			   
+});
+
+jQuery.fn.extend({
+	bind: function( type, data, fn ) {
+		return type == "unload" ? this.one(type, data, fn) : this.each(function(){
+			jQuery.event.add( this, type, fn || data, fn && data );
+		});
+	},
+
+	one: function( type, data, fn ) {
+		var one = jQuery.event.proxy( fn || data, function(event) {
+			jQuery(this).unbind(event, one);
+			return (fn || data).apply( this, arguments );
+		});
+		return this.each(function(){
+			jQuery.event.add( this, type, one, fn && data);
+		});
+	},
+
+	unbind: function( type, fn ) {
+		return this.each(function(){
+			jQuery.event.remove( this, type, fn );
+		});
+	},
+
+	trigger: function( type, data ) {
+		return this.each(function(){
+			jQuery.event.trigger( type, data, this );
+		});
+	},
+
+	triggerHandler: function( type, data ) {
+		if( this[0] ){
+			var event = jQuery.Event(type);
+			event.preventDefault();
+			event.stopPropagation();
+			jQuery.event.trigger( event, data, this[0] );
+			return event.result;
+		}		
+	},
+
+	toggle: function( fn ) {
+		// Save reference to arguments for access in closure
+		var args = arguments, i = 1;
+
+		// link all the functions, so any of them can unbind this click handler
+		while( i < args.length )
+			jQuery.event.proxy( fn, args[i++] );
+
+		return this.click( jQuery.event.proxy( fn, function(event) {
+			// Figure out which function to execute
+			this.lastToggle = ( this.lastToggle || 0 ) % i;
+
+			// Make sure that clicks stop
+			event.preventDefault();
+
+			// and execute the function
+			return args[ this.lastToggle++ ].apply( this, arguments ) || false;
+		}));
+	},
+
+	hover: function(fnOver, fnOut) {
+		return this.mouseenter(fnOver).mouseleave(fnOut);
+	},
+
+	ready: function(fn) {
+		// Attach the listeners
+		bindReady();
+
+		// If the DOM is already ready
+		if ( jQuery.isReady )
+			// Execute the function immediately
+			fn.call( document, jQuery );
+
+		// Otherwise, remember the function for later
+		else
+			// Add the function to the wait list
+			jQuery.readyList.push( fn );
+
+		return this;
+	},
+	
+	live: function( type, fn ){
+		var proxy = jQuery.event.proxy( fn );
+		proxy.guid += this.selector + type;
+
+		jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
+
+		return this;
+	},
+	
+	die: function( type, fn ){
+		jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
+		return this;
+	}
+});
+
+function liveHandler( event ){
+	var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
+		stop = true,
+		elems = [];
+
+	jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
+		if ( check.test(fn.type) ) {
+			var elem = jQuery(event.target).closest(fn.data)[0];
+			if ( elem )
+				elems.push({ elem: elem, fn: fn });
+		}
+	});
+
+	jQuery.each(elems, function(){
+		if ( this.fn.call(this.elem, event, this.fn.data) === false )
+			stop = false;
+	});
+
+	return stop;
+}
+
+function liveConvert(type, selector){
+	return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
+}
+
+jQuery.extend({
+	isReady: false,
+	readyList: [],
+	// Handle when the DOM is ready
+	ready: function() {
+		// Make sure that the DOM is not already loaded
+		if ( !jQuery.isReady ) {
+			// Remember that the DOM is ready
+			jQuery.isReady = true;
+
+			// If there are functions bound, to execute
+			if ( jQuery.readyList ) {
+				// Execute all of them
+				jQuery.each( jQuery.readyList, function(){
+					this.call( document, jQuery );
+				});
+
+				// Reset the list of functions
+				jQuery.readyList = null;
+			}
+
+			// Trigger any bound ready events
+			jQuery(document).triggerHandler("ready");
+		}
+	}
+});
+
+var readyBound = false;
+
+function bindReady(){
+	if ( readyBound ) return;
+	readyBound = true;
+
+	// Mozilla, Opera and webkit nightlies currently support this event
+	if ( document.addEventListener ) {
+		// Use the handy event callback
+		document.addEventListener( "DOMContentLoaded", function(){
+			document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
+			jQuery.ready();
+		}, false );
+
+	// If IE event model is used
+	} else if ( document.attachEvent ) {
+		// ensure firing before onload,
+		// maybe late but safe also for iframes
+		document.attachEvent("onreadystatechange", function(){
+			if ( document.readyState === "complete" ) {
+				document.detachEvent( "onreadystatechange", arguments.callee );
+				jQuery.ready();
+			}
+		});
+
+		// If IE and not an iframe
+		// continually check to see if the document is ready
+		if ( document.documentElement.doScroll && typeof window.frameElement === "undefined" ) (function(){
+			if ( jQuery.isReady ) return;
+
+			try {
+				// If IE is used, use the trick by Diego Perini
+				// http://javascript.nwbox.com/IEContentLoaded/
+				document.documentElement.doScroll("left");
+			} catch( error ) {
+				setTimeout( arguments.callee, 0 );
+				return;
+			}
+
+			// and execute any waiting functions
+			jQuery.ready();
+		})();
+	}
+
+	// A fallback to window.onload, that will always work
+	jQuery.event.add( window, "load", jQuery.ready );
+}
+
+jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
+	"mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
+	"change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
+
+	// Handle event binding
+	jQuery.fn[name] = function(fn){
+		return fn ? this.bind(name, fn) : this.trigger(name);
+	};
+});
+
+// Prevent memory leaks in IE
+// And prevent errors on refresh with events like mouseover in other browsers
+// Window isn't included so as not to unbind existing unload events
+jQuery( window ).bind( 'unload', function(){ 
+	for ( var id in jQuery.cache )
+		// Skip the window
+		if ( id != 1 && jQuery.cache[ id ].handle )
+			jQuery.event.remove( jQuery.cache[ id ].handle.elem );
+}); 
+(function(){
+
+	jQuery.support = {};
+
+	var root = document.documentElement,
+		script = document.createElement("script"),
+		div = document.createElement("div"),
+		id = "script" + (new Date).getTime();
+
+	div.style.display = "none";
+	div.innerHTML = '   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
+
+	var all = div.getElementsByTagName("*"),
+		a = div.getElementsByTagName("a")[0];
+
+	// Can't get basic test support
+	if ( !all || !all.length || !a ) {
+		return;
+	}
+
+	jQuery.support = {
+		// IE strips leading whitespace when .innerHTML is used
+		leadingWhitespace: div.firstChild.nodeType == 3,
+		
+		// Make sure that tbody elements aren't automatically inserted
+		// IE will insert them into empty tables
+		tbody: !div.getElementsByTagName("tbody").length,
+		
+		// Make sure that you can get all elements in an <object> element
+		// IE 7 always returns no results
+		objectAll: !!div.getElementsByTagName("object")[0]
+			.getElementsByTagName("*").length,
+		
+		// Make sure that link elements get serialized correctly by innerHTML
+		// This requires a wrapper element in IE
+		htmlSerialize: !!div.getElementsByTagName("link").length,
+		
+		// Get the style information from getAttribute
+		// (IE uses .cssText insted)
+		style: /red/.test( a.getAttribute("style") ),
+		
+		// Make sure that URLs aren't manipulated
+		// (IE normalizes it by default)
+		hrefNormalized: a.getAttribute("href") === "/a",
+		
+		// Make sure that element opacity exists
+		// (IE uses filter instead)
+		opacity: a.style.opacity === "0.5",
+		
+		// Verify style float existence
+		// (IE uses styleFloat instead of cssFloat)
+		cssFloat: !!a.style.cssFloat,
+
+		// Will be defined later
+		scriptEval: false,
+		noCloneEvent: true,
+		boxModel: null
+	};
+	
+	script.type = "text/javascript";
+	try {
+		script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
+	} catch(e){}
+
+	root.insertBefore( script, root.firstChild );
+	
+	// Make sure that the execution of code works by injecting a script
+	// tag with appendChild/createTextNode
+	// (IE doesn't support this, fails, and uses .text instead)
+	if ( window[ id ] ) {
+		jQuery.support.scriptEval = true;
+		delete window[ id ];
+	}
+
+	root.removeChild( script );
+
+	if ( div.attachEvent && div.fireEvent ) {
+		div.attachEvent("onclick", function(){
+			// Cloning a node shouldn't copy over any
+			// bound event handlers (IE does this)
+			jQuery.support.noCloneEvent = false;
+			div.detachEvent("onclick", arguments.callee);
+		});
+		div.cloneNode(true).fireEvent("onclick");
+	}
+
+	// Figure out if the W3C box model works as expected
+	// document.body must exist before we can do this
+	jQuery(function(){
+		var div = document.createElement("div");
+		div.style.width = "1px";
+		div.style.paddingLeft = "1px";
+
+		document.body.appendChild( div );
+		jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
+		document.body.removeChild( div );
+	});
+})();
+
+var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
+
+jQuery.props = {
+	"for": "htmlFor",
+	"class": "className",
+	"float": styleFloat,
+	cssFloat: styleFloat,
+	styleFloat: styleFloat,
+	readonly: "readOnly",
+	maxlength: "maxLength",
+	cellspacing: "cellSpacing",
+	rowspan: "rowSpan",
+	tabindex: "tabIndex"
+};
+jQuery.fn.extend({
+	// Keep a copy of the old load
+	_load: jQuery.fn.load,
+
+	load: function( url, params, callback ) {
+		if ( typeof url !== "string" )
+			return this._load( url );
+
+		var off = url.indexOf(" ");
+		if ( off >= 0 ) {
+			var selector = url.slice(off, url.length);
+			url = url.slice(0, off);
+		}
+
+		// Default to a GET request
+		var type = "GET";
+
+		// If the second parameter was provided
+		if ( params )
+			// If it's a function
+			if ( jQuery.isFunction( params ) ) {
+				// We assume that it's the callback
+				callback = params;
+				params = null;
+
+			// Otherwise, build a param string
+			} else if( typeof params === "object" ) {
+				params = jQuery.param( params );
+				type = "POST";
+			}
+
+		var self = this;
+
+		// Request the remote document
+		jQuery.ajax({
+			url: url,
+			type: type,
+			dataType: "html",
+			data: params,
+			complete: function(res, status){
+				// If successful, inject the HTML into all the matched elements
+				if ( status == "success" || status == "notmodified" )
+					// See if a selector was specified
+					self.html( selector ?
+						// Create a dummy div to hold the results
+						jQuery("<div/>")
+							// inject the contents of the document in, removing the scripts
+							// to avoid any 'Permission Denied' errors in IE
+							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+
+							// Locate the specified elements
+							.find(selector) :
+
+						// If not, just inject the full result
+						res.responseText );
+
+				if( callback )
+					self.each( callback, [res.responseText, status, res] );
+			}
+		});
+		return this;
+	},
+
+	serialize: function() {
+		return jQuery.param(this.serializeArray());
+	},
+	serializeArray: function() {
+		return this.map(function(){
+			return this.elements ? jQuery.makeArray(this.elements) : this;
+		})
+		.filter(function(){
+			return this.name && !this.disabled &&
+				(this.checked || /select|textarea/i.test(this.nodeName) ||
+					/text|hidden|password/i.test(this.type));
+		})
+		.map(function(i, elem){
+			var val = jQuery(this).val();
+			return val == null ? null :
+				jQuery.isArray(val) ?
+					jQuery.map( val, function(val, i){
+						return {name: elem.name, value: val};
+					}) :
+					{name: elem.name, value: val};
+		}).get();
+	}
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
+	jQuery.fn[o] = function(f){
+		return this.bind(o, f);
+	};
+});
+
+var jsc = now();
+
+jQuery.extend({
+  
+	get: function( url, data, callback, type ) {
+		// shift arguments if data argument was ommited
+		if ( jQuery.isFunction( data ) ) {
+			callback = data;
+			data = null;
+		}
+
+		return jQuery.ajax({
+			type: "GET",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get(url, null, callback, "script");
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get(url, data, callback, "json");
+	},
+
+	post: function( url, data, callback, type ) {
+		if ( jQuery.isFunction( data ) ) {
+			callback = data;
+			data = {};
+		}
+
+		return jQuery.ajax({
+			type: "POST",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	ajaxSetup: function( settings ) {
+		jQuery.extend( jQuery.ajaxSettings, settings );
+	},
+
+	ajaxSettings: {
+		url: location.href,
+		global: true,
+		type: "GET",
+		contentType: "application/x-www-form-urlencoded",
+		processData: true,
+		async: true,
+		/*
+		timeout: 0,
+		data: null,
+		username: null,
+		password: null,
+		*/
+		// Create the request object; Microsoft failed to properly
+		// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+		// This function can be overriden by calling jQuery.ajaxSetup
+		xhr:function(){
+			return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+		},
+		accepts: {
+			xml: "application/xml, text/xml",
+			html: "text/html",
+			script: "text/javascript, application/javascript",
+			json: "application/json, text/javascript",
+			text: "text/plain",
+			_default: "*/*"
+		}
+	},
+
+	// Last-Modified header cache for next request
+	lastModified: {},
+
+	ajax: function( s ) {
+		// Extend the settings, but re-extend 's' so that it can be
+		// checked again later (in the test suite, specifically)
+		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
+
+		var jsonp, jsre = /=\?(&|$)/g, status, data,
+			type = s.type.toUpperCase();
+
+		// convert data if not already a string
+		if ( s.data && s.processData && typeof s.data !== "string" )
+			s.data = jQuery.param(s.data);
+
+		// Handle JSONP Parameter Callbacks
+		if ( s.dataType == "jsonp" ) {
+			if ( type == "GET" ) {
+				if ( !s.url.match(jsre) )
+					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+			} else if ( !s.data || !s.data.match(jsre) )
+				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+			s.dataType = "json";
+		}
+
+		// Build temporary JSONP function
+		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
+			jsonp = "jsonp" + jsc++;
+
+			// Replace the =? sequence both in the query string and the data
+			if ( s.data )
+				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+			// We need to make sure
+			// that a JSONP style response is executed properly
+			s.dataType = "script";
+
+			// Handle JSONP-style loading
+			window[ jsonp ] = function(tmp){
+				data = tmp;
+				success();
+				complete();
+				// Garbage collect
+				window[ jsonp ] = undefined;
+				try{ delete window[ jsonp ]; } catch(e){}
+				if ( head )
+					head.removeChild( script );
+			};
+		}
+
+		if ( s.dataType == "script" && s.cache == null )
+			s.cache = false;
+
+		if ( s.cache === false && type == "GET" ) {
+			var ts = now();
+			// try replacing _= if it is there
+			var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+			// if nothing was replaced, add timestamp to the end
+			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
+		}
+
+		// If data is available, append data to url for get requests
+		if ( s.data && type == "GET" ) {
+			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
+
+			// IE likes to send both get and post data, prevent this
+			s.data = null;
+		}
+
+		// Watch for a new set of requests
+		if ( s.global && ! jQuery.active++ )
+			jQuery.event.trigger( "ajaxStart" );
+
+		// Matches an absolute URL, and saves the domain
+		var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
+
+		// If we're requesting a remote document
+		// and trying to load JSON or Script with a GET
+		if ( s.dataType == "script" && type == "GET" && parts
+			&& ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
+
+			var head = document.getElementsByTagName("head")[0];
+			var script = document.createElement("script");
+			script.src = s.url;
+			if (s.scriptCharset)
+				script.charset = s.scriptCharset;
+
+			// Handle Script loading
+			if ( !jsonp ) {
+				var done = false;
+
+				// Attach handlers for all browsers
+				script.onload = script.onreadystatechange = function(){
+					if ( !done && (!this.readyState ||
+							this.readyState == "loaded" || this.readyState == "complete") ) {
+						done = true;
+						success();
+						complete();
+						head.removeChild( script );
+					}
+				};
+			}
+
+			head.appendChild(script);
+
+			// We handle everything using the script element injection
+			return undefined;
+		}
+
+		var requestDone = false;
+
+		// Create the request object
+		var xhr = s.xhr();
+
+		// Open the socket
+		// Passing null username, generates a login popup on Opera (#2865)
+		if( s.username )
+			xhr.open(type, s.url, s.async, s.username, s.password);
+		else
+			xhr.open(type, s.url, s.async);
+
+		// Need an extra try/catch for cross domain requests in Firefox 3
+		try {
+			// Set the correct header, if data is being sent
+			if ( s.data )
+				xhr.setRequestHeader("Content-Type", s.contentType);
+
+			// Set the If-Modified-Since header, if ifModified mode.
+			if ( s.ifModified )
+				xhr.setRequestHeader("If-Modified-Since",
+					jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+
+			// Set header so the called script knows that it's an XMLHttpRequest
+			xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+
+			// Set the Accepts header for the server, depending on the dataType
+			xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+				s.accepts[ s.dataType ] + ", */*" :
+				s.accepts._default );
+		} catch(e){}
+
+		// Allow custom headers/mimetypes and early abort
+		if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
+			// Handle the global AJAX counter
+			if ( s.global && ! --jQuery.active )
+				jQuery.event.trigger( "ajaxStop" );
+			// close opended socket
+			xhr.abort();
+			return false;
+		}
+
+		if ( s.global )
+			jQuery.event.trigger("ajaxSend", [xhr, s]);
+
+		// Wait for a response to come back
+		var onreadystatechange = function(isTimeout){
+			// The request was aborted, clear the interval and decrement jQuery.active
+			if (xhr.readyState == 0) {
+				if (ival) {
+					// clear poll interval
+					clearInterval(ival);
+					ival = null;
+					// Handle the global AJAX counter
+					if ( s.global && ! --jQuery.active )
+						jQuery.event.trigger( "ajaxStop" );
+				}
+			// The transfer is complete and the data is available, or the request timed out
+			} else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
+				requestDone = true;
+
+				// clear poll interval
+				if (ival) {
+					clearInterval(ival);
+					ival = null;
+				}
+
+				status = isTimeout == "timeout" ? "timeout" :
+					!jQuery.httpSuccess( xhr ) ? "error" :
+					s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
+					"success";
+
+				if ( status == "success" ) {
+					// Watch for, and catch, XML document parse errors
+					try {
+						// process the data (runs the xml through httpData regardless of callback)
+						data = jQuery.httpData( xhr, s.dataType, s );
+					} catch(e) {
+						status = "parsererror";
+					}
+				}
+
+				// Make sure that the request was successful or notmodified
+				if ( status == "success" ) {
+					// Cache Last-Modified header, if ifModified mode.
+					var modRes;
+					try {
+						modRes = xhr.getResponseHeader("Last-Modified");
+					} catch(e) {} // swallow exception thrown by FF if header is not available
+
+					if ( s.ifModified && modRes )
+						jQuery.lastModified[s.url] = modRes;
+
+					// JSONP handles its own success callback
+					if ( !jsonp )
+						success();
+				} else
+					jQuery.handleError(s, xhr, status);
+
+				// Fire the complete handlers
+				complete();
+
+				if ( isTimeout )
+					xhr.abort();
+
+				// Stop memory leaks
+				if ( s.async )
+					xhr = null;
+			}
+		};
+
+		if ( s.async ) {
+			// don't attach the handler to the request, just poll it instead
+			var ival = setInterval(onreadystatechange, 13);
+
+			// Timeout checker
+			if ( s.timeout > 0 )
+				setTimeout(function(){
+					// Check to see if the request is still happening
+					if ( xhr && !requestDone )
+						onreadystatechange( "timeout" );
+				}, s.timeout);
+		}
+
+		// Send the data
+		try {
+			xhr.send(s.data);
+		} catch(e) {
+			jQuery.handleError(s, xhr, null, e);
+		}
+
+		// firefox 1.5 doesn't fire statechange for sync requests
+		if ( !s.async )
+			onreadystatechange();
+
+		function success(){
+			// If a local callback was specified, fire it and pass it the data
+			if ( s.success )
+				s.success( data, status );
+
+			// Fire the global callback
+			if ( s.global )
+				jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
+		}
+
+		function complete(){
+			// Process result
+			if ( s.complete )
+				s.complete(xhr, status);
+
+			// The request was completed
+			if ( s.global )
+				jQuery.event.trigger( "ajaxComplete", [xhr, s] );
+
+			// Handle the global AJAX counter
+			if ( s.global && ! --jQuery.active )
+				jQuery.event.trigger( "ajaxStop" );
+		}
+
+		// return XMLHttpRequest to allow aborting the request etc.
+		return xhr;
+	},
+
+	handleError: function( s, xhr, status, e ) {
+		// If a local callback was specified, fire it
+		if ( s.error ) s.error( xhr, status, e );
+
+		// Fire the global callback
+		if ( s.global )
+			jQuery.event.trigger( "ajaxError", [xhr, s, e] );
+	},
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Determines if an XMLHttpRequest was successful or not
+	httpSuccess: function( xhr ) {
+		try {
+			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+			return !xhr.status && location.protocol == "file:" ||
+				( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
+		} catch(e){}
+		return false;
+	},
+
+	// Determines if an XMLHttpRequest returns NotModified
+	httpNotModified: function( xhr, url ) {
+		try {
+			var xhrRes = xhr.getResponseHeader("Last-Modified");
+
+			// Firefox always returns 200. check Last-Modified date
+			return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
+		} catch(e){}
+		return false;
+	},
+
+	httpData: function( xhr, type, s ) {
+		var ct = xhr.getResponseHeader("content-type"),
+			xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
+			data = xml ? xhr.responseXML : xhr.responseText;
+
+		if ( xml && data.documentElement.tagName == "parsererror" )
+			throw "parsererror";
+			
+		// Allow a pre-filtering function to sanitize the response
+		// s != null is checked to keep backwards compatibility
+		if( s && s.dataFilter )
+			data = s.dataFilter( data, type );
+
+		// The filter can actually parse the response
+		if( typeof data === "string" ){
+
+			// If the type is "script", eval it in global context
+			if ( type == "script" )
+				jQuery.globalEval( data );
+
+			// Get the JavaScript object, if JSON is used.
+			if ( type == "json" )
+				data = window["eval"]("(" + data + ")");
+		}
+		
+		return data;
+	},
+
+	// Serialize an array of form elements or a set of
+	// key/values into a query string
+	param: function( a ) {
+		var s = [ ];
+
+		function add( key, value ){
+			s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
+		};
+
+		// If an array was passed in, assume that it is an array
+		// of form elements
+		if ( jQuery.isArray(a) || a.jquery )
+			// Serialize the form elements
+			jQuery.each( a, function(){
+				add( this.name, this.value );
+			});
+
+		// Otherwise, assume that it's an object of key/value pairs
+		else
+			// Serialize the key/values
+			for ( var j in a )
+				// If the value is an array then the key names need to be repeated
+				if ( jQuery.isArray(a[j]) )
+					jQuery.each( a[j], function(){
+						add( j, this );
+					});
+				else
+					add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
+
+		// Return the resulting serialization
+		return s.join("&").replace(/%20/g, "+");
+	}
+
+});
+var elemdisplay = {},
+	timerId,
+	fxAttrs = [
+		// height animations
+		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+		// width animations
+		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+		// opacity animations
+		[ "opacity" ]
+	];
+
+function genFx( type, num ){
+	var obj = {};
+	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
+		obj[ this ] = type;
+	});
+	return obj;
+}
+
+jQuery.fn.extend({
+	show: function(speed,callback){
+		if ( speed ) {
+			return this.animate( genFx("show", 3), speed, callback);
+		} else {
+			for ( var i = 0, l = this.length; i < l; i++ ){
+				var old = jQuery.data(this[i], "olddisplay");
+				
+				this[i].style.display = old || "";
+				
+				if ( jQuery.css(this[i], "display") === "none" ) {
+					var tagName = this[i].tagName, display;
+					
+					if ( elemdisplay[ tagName ] ) {
+						display = elemdisplay[ tagName ];
+					} else {
+						var elem = jQuery("<" + tagName + " />").appendTo("body");
+						
+						display = elem.css("display");
+						if ( display === "none" )
+							display = "block";
+						
+						elem.remove();
+						
+						elemdisplay[ tagName ] = display;
+					}
+					
+					this[i].style.display = jQuery.data(this[i], "olddisplay", display);
+				}
+			}
+			
+			return this;
+		}
+	},
+
+	hide: function(speed,callback){
+		if ( speed ) {
+			return this.animate( genFx("hide", 3), speed, callback);
+		} else {
+			for ( var i = 0, l = this.length; i < l; i++ ){
+				var old = jQuery.data(this[i], "olddisplay");
+				if ( !old && old !== "none" )
+					jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
+				this[i].style.display = "none";
+			}
+			return this;
+		}
+	},
+
+	// Save the old toggle function
+	_toggle: jQuery.fn.toggle,
+
+	toggle: function( fn, fn2 ){
+		var bool = typeof fn === "boolean";
+
+		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
+			this._toggle.apply( this, arguments ) :
+			fn == null || bool ?
+				this.each(function(){
+					var state = bool ? fn : jQuery(this).is(":hidden");
+					jQuery(this)[ state ? "show" : "hide" ]();
+				}) :
+				this.animate(genFx("toggle", 3), fn, fn2);
+	},
+
+	fadeTo: function(speed,to,callback){
+		return this.animate({opacity: to}, speed, callback);
+	},
+
+	animate: function( prop, speed, easing, callback ) {
+		var optall = jQuery.speed(speed, easing, callback);
+
+		return this[ optall.queue === false ? "each" : "queue" ](function(){
+		
+			var opt = jQuery.extend({}, optall), p,
+				hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
+				self = this;
+	
+			for ( p in prop ) {
+				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+					return opt.complete.call(this);
+
+				if ( ( p == "height" || p == "width" ) && this.style ) {
+					// Store display property
+					opt.display = jQuery.css(this, "display");
+
+					// Make sure that nothing sneaks out
+					opt.overflow = this.style.overflow;
+				}
+			}
+
+			if ( opt.overflow != null )
+				this.style.overflow = "hidden";
+
+			opt.curAnim = jQuery.extend({}, prop);
+
+			jQuery.each( prop, function(name, val){
+				var e = new jQuery.fx( self, opt, name );
+
+				if ( /toggle|show|hide/.test(val) )
+					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+				else {
+					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+						start = e.cur(true) || 0;
+
+					if ( parts ) {
+						var end = parseFloat(parts[2]),
+							unit = parts[3] || "px";
+
+						// We need to compute starting value
+						if ( unit != "px" ) {
+							self.style[ name ] = (end || 1) + unit;
+							start = ((end || 1) / e.cur(true)) * start;
+							self.style[ name ] = start + unit;
+						}
+
+						// If a +=/-= token was provided, we're doing a relative animation
+						if ( parts[1] )
+							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+
+						e.custom( start, end, unit );
+					} else
+						e.custom( start, val, "" );
+				}
+			});
+
+			// For JS strict compliance
+			return true;
+		});
+	},
+
+	stop: function(clearQueue, gotoEnd){
+		var timers = jQuery.timers;
+
+		if (clearQueue)
+			this.queue([]);
+
+		this.each(function(){
+			// go in reverse order so anything added to the queue during the loop is ignored
+			for ( var i = timers.length - 1; i >= 0; i-- )
+				if ( timers[i].elem == this ) {
+					if (gotoEnd)
+						// force the next step to be the last
+						timers[i](true);
+					timers.splice(i, 1);
+				}
+		});
+
+		// start the next in the queue if the last step wasn't forced
+		if (!gotoEnd)
+			this.dequeue();
+
+		return this;
+	}
+
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+	slideDown: genFx("show", 1),
+	slideUp: genFx("hide", 1),
+	slideToggle: genFx("toggle", 1),
+	fadeIn: { opacity: "show" },
+	fadeOut: { opacity: "hide" }
+}, function( name, props ){
+	jQuery.fn[ name ] = function( speed, callback ){
+		return this.animate( props, speed, callback );
+	};
+});
+
+jQuery.extend({
+
+	speed: function(speed, easing, fn) {
+		var opt = typeof speed === "object" ? speed : {
+			complete: fn || !fn && easing ||
+				jQuery.isFunction( speed ) && speed,
+			duration: speed,
+			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
+		};
+
+		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+			jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
+
+		// Queueing
+		opt.old = opt.complete;
+		opt.complete = function(){
+			if ( opt.queue !== false )
+				jQuery(this).dequeue();
+			if ( jQuery.isFunction( opt.old ) )
+				opt.old.call( this );
+		};
+
+		return opt;
+	},
+
+	easing: {
+		linear: function( p, n, firstNum, diff ) {
+			return firstNum + diff * p;
+		},
+		swing: function( p, n, firstNum, diff ) {
+			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+		}
+	},
+
+	timers: [],
+
+	fx: function( elem, options, prop ){
+		this.options = options;
+		this.elem = elem;
+		this.prop = prop;
+
+		if ( !options.orig )
+			options.orig = {};
+	}
+
+});
+
+jQuery.fx.prototype = {
+
+	// Simple function for setting a style value
+	update: function(){
+		if ( this.options.step )
+			this.options.step.call( this.elem, this.now, this );
+
+		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+
+		// Set display property to block for height/width animations
+		if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
+			this.elem.style.display = "block";
+	},
+
+	// Get the current size
+	cur: function(force){
+		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
+			return this.elem[ this.prop ];
+
+		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+	},
+
+	// Start an animation from one number to another
+	custom: function(from, to, unit){
+		this.startTime = now();
+		this.start = from;
+		this.end = to;
+		this.unit = unit || this.unit || "px";
+		this.now = this.start;
+		this.pos = this.state = 0;
+
+		var self = this;
+		function t(gotoEnd){
+			return self.step(gotoEnd);
+		}
+
+		t.elem = this.elem;
+
+		if ( t() && jQuery.timers.push(t) == 1 ) {
+			timerId = setInterval(function(){
+				var timers = jQuery.timers;
+
+				for ( var i = 0; i < timers.length; i++ )
+					if ( !timers[i]() )
+						timers.splice(i--, 1);
+
+				if ( !timers.length ) {
+					clearInterval( timerId );
+				}
+			}, 13);
+		}
+	},
+
+	// Simple 'show' function
+	show: function(){
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+		this.options.show = true;
+
+		// Begin the animation
+		// Make sure that we start at a small width/height to avoid any
+		// flash of content
+		this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
+
+		// Start by showing the element
+		jQuery(this.elem).show();
+	},
+
+	// Simple 'hide' function
+	hide: function(){
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+		this.options.hide = true;
+
+		// Begin the animation
+		this.custom(this.cur(), 0);
+	},
+
+	// Each step of an animation
+	step: function(gotoEnd){
+		var t = now();
+
+		if ( gotoEnd || t >= this.options.duration + this.startTime ) {
+			this.now = this.end;
+			this.pos = this.state = 1;
+			this.update();
+
+			this.options.curAnim[ this.prop ] = true;
+
+			var done = true;
+			for ( var i in this.options.curAnim )
+				if ( this.options.curAnim[i] !== true )
+					done = false;
+
+			if ( done ) {
+				if ( this.options.display != null ) {
+					// Reset the overflow
+					this.elem.style.overflow = this.options.overflow;
+
+					// Reset the display
+					this.elem.style.display = this.options.display;
+					if ( jQuery.css(this.elem, "display") == "none" )
+						this.elem.style.display = "block";
+				}
+
+				// Hide the element if the "hide" operation was done
+				if ( this.options.hide )
+					jQuery(this.elem).hide();
+
+				// Reset the properties, if the item has been hidden or shown
+				if ( this.options.hide || this.options.show )
+					for ( var p in this.options.curAnim )
+						jQuery.attr(this.elem.style, p, this.options.orig[p]);
+					
+				// Execute the complete function
+				this.options.complete.call( this.elem );
+			}
+
+			return false;
+		} else {
+			var n = t - this.startTime;
+			this.state = n / this.options.duration;
+
+			// Perform the easing function, defaults to swing
+			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+			this.now = this.start + ((this.end - this.start) * this.pos);
+
+			// Perform the next step of the animation
+			this.update();
+		}
+
+		return true;
+	}
+
+};
+
+jQuery.extend( jQuery.fx, {
+	speeds:{
+		slow: 600,
+ 		fast: 200,
+ 		// Default speed
+ 		_default: 400
+	},
+	step: {
+
+		opacity: function(fx){
+			jQuery.attr(fx.elem.style, "opacity", fx.now);
+		},
+
+		_default: function(fx){
+			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
+				fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+			else
+				fx.elem[ fx.prop ] = fx.now;
+		}
+	}
+});
+if ( document.documentElement["getBoundingClientRect"] )
+	jQuery.fn.offset = function() {
+		if ( !this[0] ) return { top: 0, left: 0 };
+		if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+		var box  = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
+			clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
+			top  = box.top  + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
+			left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
+		return { top: top, left: left };
+	};
+else 
+	jQuery.fn.offset = function() {
+		if ( !this[0] ) return { top: 0, left: 0 };
+		if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+		jQuery.offset.initialized || jQuery.offset.initialize();
+
+		var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
+			doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
+			body = doc.body, defaultView = doc.defaultView,
+			prevComputedStyle = defaultView.getComputedStyle(elem, null),
+			top = elem.offsetTop, left = elem.offsetLeft;
+
+		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+			computedStyle = defaultView.getComputedStyle(elem, null);
+			top -= elem.scrollTop, left -= elem.scrollLeft;
+			if ( elem === offsetParent ) {
+				top += elem.offsetTop, left += elem.offsetLeft;
+				if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
+					top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
+					left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+				prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
+			}
+			if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
+				top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
+				left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+			prevComputedStyle = computedStyle;
+		}
+
+		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
+			top  += body.offsetTop,
+			left += body.offsetLeft;
+
+		if ( prevComputedStyle.position === "fixed" )
+			top  += Math.max(docElem.scrollTop, body.scrollTop),
+			left += Math.max(docElem.scrollLeft, body.scrollLeft);
+
+		return { top: top, left: left };
+	};
+
+jQuery.offset = {
+	initialize: function() {
+		if ( this.initialized ) return;
+		var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
+			html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
+
+		rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
+		for ( prop in rules ) container.style[prop] = rules[prop];
+
+		container.innerHTML = html;
+		body.insertBefore(container, body.firstChild);
+		innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
+
+		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
+		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+
+		innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
+		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+
+		body.style.marginTop = '1px';
+		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
+		body.style.marginTop = bodyMarginTop;
+
+		body.removeChild(container);
+		this.initialized = true;
+	},
+
+	bodyOffset: function(body) {
+		jQuery.offset.initialized || jQuery.offset.initialize();
+		var top = body.offsetTop, left = body.offsetLeft;
+		if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
+			top  += parseInt( jQuery.curCSS(body, 'marginTop',  true), 10 ) || 0,
+			left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
+		return { top: top, left: left };
+	}
+};
+
+
+jQuery.fn.extend({
+	position: function() {
+		var left = 0, top = 0, results;
+
+		if ( this[0] ) {
+			// Get *real* offsetParent
+			var offsetParent = this.offsetParent(),
+
+			// Get correct offsets
+			offset       = this.offset(),
+			parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+			// Subtract element margins
+			// note: when an element has margin: auto the offsetLeft and marginLeft 
+			// are the same in Safari causing offset.left to incorrectly be 0
+			offset.top  -= num( this, 'marginTop'  );
+			offset.left -= num( this, 'marginLeft' );
+
+			// Add offsetParent borders
+			parentOffset.top  += num( offsetParent, 'borderTopWidth'  );
+			parentOffset.left += num( offsetParent, 'borderLeftWidth' );
+
+			// Subtract the two offsets
+			results = {
+				top:  offset.top  - parentOffset.top,
+				left: offset.left - parentOffset.left
+			};
+		}
+
+		return results;
+	},
+
+	offsetParent: function() {
+		var offsetParent = this[0].offsetParent || document.body;
+		while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
+			offsetParent = offsetParent.offsetParent;
+		return jQuery(offsetParent);
+	}
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ['Left', 'Top'], function(i, name) {
+	var method = 'scroll' + name;
+	
+	jQuery.fn[ method ] = function(val) {
+		if (!this[0]) return null;
+
+		return val !== undefined ?
+
+			// Set the scroll offset
+			this.each(function() {
+				this == window || this == document ?
+					window.scrollTo(
+						!i ? val : jQuery(window).scrollLeft(),
+						 i ? val : jQuery(window).scrollTop()
+					) :
+					this[ method ] = val;
+			}) :
+
+			// Return the scroll offset
+			this[0] == window || this[0] == document ?
+				self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
+					jQuery.boxModel && document.documentElement[ method ] ||
+					document.body[ method ] :
+				this[0][ method ];
+	};
+});
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function(i, name){
+
+	var tl = i ? "Left"  : "Top",  // top or left
+		br = i ? "Right" : "Bottom"; // bottom or right
+
+	// innerHeight and innerWidth
+	jQuery.fn["inner" + name] = function(){
+		return this[ name.toLowerCase() ]() +
+			num(this, "padding" + tl) +
+			num(this, "padding" + br);
+	};
+
+	// outerHeight and outerWidth
+	jQuery.fn["outer" + name] = function(margin) {
+		return this["inner" + name]() +
+			num(this, "border" + tl + "Width") +
+			num(this, "border" + br + "Width") +
+			(margin ?
+				num(this, "margin" + tl) + num(this, "margin" + br) : 0);
+	};
+	
+	var type = name.toLowerCase();
+
+	jQuery.fn[ type ] = function( size ) {
+		// Get window width or height
+		return this[0] == window ?
+			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
+			document.body[ "client" + name ] :
+
+			// Get document width or height
+			this[0] == document ?
+				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+				Math.max(
+					document.documentElement["client" + name],
+					document.body["scroll" + name], document.documentElement["scroll" + name],
+					document.body["offset" + name], document.documentElement["offset" + name]
+				) :
+
+				// Get or set width or height on the element
+				size === undefined ?
+					// Get width or height on the element
+					(this.length ? jQuery.css( this[0], type ) : null) :
+
+					// Set the width or height on the element (default to pixels if value is unitless)
+					this.css( type, typeof size === "string" ? size : size + "px" );
+	};
+
+});})();
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/jquery/ui.core.js b/0.8.1-rc1/curator/src/main/webapp/js/jquery/ui.core.js
new file mode 100644
index 0000000..9695d6a
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/jquery/ui.core.js
@@ -0,0 +1,291 @@
+/*

+ * jQuery UI 1.5.3

+ *

+ * Copyright (c) 2008 Paul Bakaus (ui.jquery.com)

+ * Dual licensed under the MIT (MIT-LICENSE.txt)

+ * and GPL (GPL-LICENSE.txt) licenses.

+ *

+ * http://docs.jquery.com/UI

+ */

+;(function($) {

+

+$.ui = {

+	plugin: {

+		add: function(module, option, set) {

+			var proto = $.ui[module].prototype;

+			for(var i in set) {

+				proto.plugins[i] = proto.plugins[i] || [];

+				proto.plugins[i].push([option, set[i]]);

+			}

+		},

+		call: function(instance, name, args) {

+			var set = instance.plugins[name];

+			if(!set) { return; }

+			

+			for (var i = 0; i < set.length; i++) {

+				if (instance.options[set[i][0]]) {

+					set[i][1].apply(instance.element, args);

+				}

+			}

+		}	

+	},

+	cssCache: {},

+	css: function(name) {

+		if ($.ui.cssCache[name]) { return $.ui.cssCache[name]; }

+		var tmp = $('<div class="ui-gen">').addClass(name).css({position:'absolute', top:'-5000px', left:'-5000px', display:'block'}).appendTo('body');

+		

+		//if (!$.browser.safari)

+			//tmp.appendTo('body'); 

+		

+		//Opera and Safari set width and height to 0px instead of auto

+		//Safari returns rgba(0,0,0,0) when bgcolor is not set

+		$.ui.cssCache[name] = !!(

+			(!(/auto|default/).test(tmp.css('cursor')) || (/^[1-9]/).test(tmp.css('height')) || (/^[1-9]/).test(tmp.css('width')) || 

+			!(/none/).test(tmp.css('backgroundImage')) || !(/transparent|rgba\(0, 0, 0, 0\)/).test(tmp.css('backgroundColor')))

+		);

+		try { $('body').get(0).removeChild(tmp.get(0));	} catch(e){}

+		return $.ui.cssCache[name];

+	},

+	disableSelection: function(el) {

+		$(el).attr('unselectable', 'on').css('MozUserSelect', 'none');

+	},

+	enableSelection: function(el) {

+		$(el).attr('unselectable', 'off').css('MozUserSelect', '');

+	},

+	hasScroll: function(e, a) {

+		var scroll = /top/.test(a||"top") ? 'scrollTop' : 'scrollLeft', has = false;

+		if (e[scroll] > 0) return true; e[scroll] = 1;

+		has = e[scroll] > 0 ? true : false; e[scroll] = 0;

+		return has;

+	}

+};

+

+

+/** jQuery core modifications and additions **/

+

+var _remove = $.fn.remove;

+$.fn.remove = function() {

+	$("*", this).add(this).triggerHandler("remove");

+	return _remove.apply(this, arguments );

+};

+

+// $.widget is a factory to create jQuery plugins

+// taking some boilerplate code out of the plugin code

+// created by Scott González and Jörn Zaefferer

+function getter(namespace, plugin, method) {

+	var methods = $[namespace][plugin].getter || [];

+	methods = (typeof methods == "string" ? methods.split(/,?\s+/) : methods);

+	return ($.inArray(method, methods) != -1);

+}

+

+$.widget = function(name, prototype) {

+	var namespace = name.split(".")[0];

+	name = name.split(".")[1];

+	

+	// create plugin method

+	$.fn[name] = function(options) {

+		var isMethodCall = (typeof options == 'string'),

+			args = Array.prototype.slice.call(arguments, 1);

+		

+		if (isMethodCall && getter(namespace, name, options)) {

+			var instance = $.data(this[0], name);

+			return (instance ? instance[options].apply(instance, args)

+				: undefined);

+		}

+		

+		return this.each(function() {

+			var instance = $.data(this, name);

+			if (isMethodCall && instance && $.isFunction(instance[options])) {

+				instance[options].apply(instance, args);

+			} else if (!isMethodCall) {

+				$.data(this, name, new $[namespace][name](this, options));

+			}

+		});

+	};

+	

+	// create widget constructor

+	$[namespace][name] = function(element, options) {

+		var self = this;

+		

+		this.widgetName = name;

+		this.widgetBaseClass = namespace + '-' + name;

+		

+		this.options = $.extend({}, $.widget.defaults, $[namespace][name].defaults, options);

+		this.element = $(element)

+			.bind('setData.' + name, function(e, key, value) {

+				return self.setData(key, value);

+			})

+			.bind('getData.' + name, function(e, key) {

+				return self.getData(key);

+			})

+			.bind('remove', function() {

+				return self.destroy();

+			});

+		this.init();

+	};

+	

+	// add widget prototype

+	$[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);

+};

+

+$.widget.prototype = {

+	init: function() {},

+	destroy: function() {

+		this.element.removeData(this.widgetName);

+	},

+	

+	getData: function(key) {

+		return this.options[key];

+	},

+	setData: function(key, value) {

+		this.options[key] = value;

+		

+		if (key == 'disabled') {

+			this.element[value ? 'addClass' : 'removeClass'](

+				this.widgetBaseClass + '-disabled');

+		}

+	},

+	

+	enable: function() {

+		this.setData('disabled', false);

+	},

+	disable: function() {

+		this.setData('disabled', true);

+	}

+};

+

+$.widget.defaults = {

+	disabled: false

+};

+

+

+/** Mouse Interaction Plugin **/

+

+$.ui.mouse = {

+	mouseInit: function() {

+		var self = this;

+	

+		this.element.bind('mousedown.'+this.widgetName, function(e) {

+			return self.mouseDown(e);

+		});

+		

+		// Prevent text selection in IE

+		if ($.browser.msie) {

+			this._mouseUnselectable = this.element.attr('unselectable');

+			this.element.attr('unselectable', 'on');

+		}

+		

+		this.started = false;

+	},

+	

+	// TODO: make sure destroying one instance of mouse doesn't mess with

+	// other instances of mouse

+	mouseDestroy: function() {

+		this.element.unbind('.'+this.widgetName);

+		

+		// Restore text selection in IE

+		($.browser.msie

+			&& this.element.attr('unselectable', this._mouseUnselectable));

+	},

+	

+	mouseDown: function(e) {

+		// we may have missed mouseup (out of window)

+		(this._mouseStarted && this.mouseUp(e));

+		

+		this._mouseDownEvent = e;

+		

+		var self = this,

+			btnIsLeft = (e.which == 1),

+			elIsCancel = (typeof this.options.cancel == "string" ? $(e.target).parents().add(e.target).filter(this.options.cancel).length : false);

+		if (!btnIsLeft || elIsCancel || !this.mouseCapture(e)) {

+			return true;

+		}

+		

+		this._mouseDelayMet = !this.options.delay;

+		if (!this._mouseDelayMet) {

+			this._mouseDelayTimer = setTimeout(function() {

+				self._mouseDelayMet = true;

+			}, this.options.delay);

+		}

+		

+		if (this.mouseDistanceMet(e) && this.mouseDelayMet(e)) {

+			this._mouseStarted = (this.mouseStart(e) !== false);

+			if (!this._mouseStarted) {

+				e.preventDefault();

+				return true;

+			}

+		}

+		

+		// these delegates are required to keep context

+		this._mouseMoveDelegate = function(e) {

+			return self.mouseMove(e);

+		};

+		this._mouseUpDelegate = function(e) {

+			return self.mouseUp(e);

+		};

+		$(document)

+			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)

+			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);

+		

+		return false;

+	},

+	

+	mouseMove: function(e) {

+		// IE mouseup check - mouseup happened when mouse was out of window

+		if ($.browser.msie && !e.button) {

+			return this.mouseUp(e);

+		}

+		

+		if (this._mouseStarted) {

+			this.mouseDrag(e);

+			return false;

+		}

+		

+		if (this.mouseDistanceMet(e) && this.mouseDelayMet(e)) {

+			this._mouseStarted =

+				(this.mouseStart(this._mouseDownEvent, e) !== false);

+			(this._mouseStarted ? this.mouseDrag(e) : this.mouseUp(e));

+		}

+		

+		return !this._mouseStarted;

+	},

+	

+	mouseUp: function(e) {

+		$(document)

+			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)

+			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);

+		

+		if (this._mouseStarted) {

+			this._mouseStarted = false;

+			this.mouseStop(e);

+		}

+		

+		return false;

+	},

+	

+	mouseDistanceMet: function(e) {

+		return (Math.max(

+				Math.abs(this._mouseDownEvent.pageX - e.pageX),

+				Math.abs(this._mouseDownEvent.pageY - e.pageY)

+			) >= this.options.distance

+		);

+	},

+	

+	mouseDelayMet: function(e) {

+		return this._mouseDelayMet;

+	},

+	

+	// These are placeholder methods, to be overriden by extending plugin

+	mouseStart: function(e) {},

+	mouseDrag: function(e) {},

+	mouseStop: function(e) {},

+	mouseCapture: function(e) { return true; }

+};

+

+$.ui.mouse.defaults = {

+	cancel: null,

+	distance: 1,

+	delay: 0

+};

+

+})(jQuery);

diff --git a/0.8.1-rc1/curator/src/main/webapp/js/main.js b/0.8.1-rc1/curator/src/main/webapp/js/main.js
new file mode 100644
index 0000000..9a34287
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/main.js
@@ -0,0 +1,428 @@
+/*
+  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.
+*/
+
+
+/********************************************************************
+ * INGESTION TASK SETUP
+ */
+
+
+// Keep track of dropped files. This is used to determine the files 
+// that will be included in an ingestion task
+var droppedFiles = Array();
+
+// The currently selected policy. This is the policy that will
+// be used in the ingestion task.
+var itPolicy;
+
+// The currently selected product type. This is the product typte that
+// will be used in the ingestion task
+var itProductType;
+
+
+// The currently selected Metadata Extractor Configuration Id
+// This is the configuration that will be sent with the ingestion task
+var itMetExtractorConfigId = 'default';
+
+
+
+function updateIngestionTaskMetExtractorConfigIds() {
+	$.get('./services/metadata/extractor/config',
+			{},
+			function(data,textState) {
+				$('#itMetExtractorConfigId').html(data);
+				itMetExtractorConfigId = $('#itMetExtractorConfigId').val();
+			});
+}
+
+function updateSelectedMetExtractorConfigId() {
+	itMetExtractorConfigId = $('#itMetExtractorConfigId').val();
+}
+
+function createIngestionTask() {
+	// The files to include are in droppedFiles
+	var files       = droppedFiles;
+	// The met extractor config id is in itMetExtractorConfigId
+	var metExtCfgId = itMetExtractorConfigId;
+	// The policy and product type are in itPolicy and itProductType
+	var policy      = itPolicy;
+	var productType = itProductType;
+	// Other variables we'll need
+	var numFiles = droppedFiles.length;
+	
+	// Send the information to the create ingestion task servlet
+	$.get('./services/ingest/create',
+			{
+				'files'      : files.join(','),
+				'numfiles'   : numFiles,
+				'metExtCfgId': metExtCfgId,
+				'policy'     : policy,
+				'ptype'      : productType
+			},
+			function (data,textState) {
+			   refreshIngestTaskList();		
+			}); 
+	
+   
+}
+
+function refreshIngestTaskList(){
+    $.get('./services/ingest/list',
+            { 'format': 'html'
+            },
+            function (data,textState) {
+                showIngestionTaskList(data);
+            });         
+}
+
+function showIngestionTaskList(data){
+    $('#ingestionTaskListItems > tbody').html(data);
+}
+
+function registerIngestionTaskListener(){
+    $.PeriodicalUpdater('./services/ingest/list', {
+        method: 'get',         
+        data: { 'format:': 'html'},          
+        minTimeout: 1000,
+        maxTimeout: 60000,
+        multiplier: 2
+      }, function (data) {
+          showIngestionTaskList(data);
+         });
+
+}
+
+function createIngestionTaskRow(data) {    
+    $('#ingestionTaskListItems > tbody').replace(data);
+}
+
+function removeIngestionTask(id) {
+	$.get('./services/ingest/remove',
+			{ 'taskId' : id },
+			refreshIngestTaskList()
+			);
+}
+
+function startIngestionTask(id) {
+	$.get('./services/ingest/start',
+			{ 'taskId' : id },
+			function(data,textState) {
+				$('#'+id+'_Status').html(data);	// 'started' or 'error'
+				refreshIngestTaskList();
+			});
+}
+
+/********************************************************************
+ * DRAG AND DROP INITIALIZATION AND CONFIGURATION
+ * 
+ */
+function initDraggables() {
+	$('.draggy').draggable({
+		revert:true, 
+		zIndex:'5000', 
+		appendTo:'body'
+		, 
+		helper: function() { 
+			return $('<li>')
+				.addClass('helper')
+				.addClass('file').addClass('ext_tiff')
+				.html($(this).children().clone());
+		}
+	});
+}
+function initDragAndDropTarget() {
+	$('#droppedFileTarget').droppable( {
+		drop: function(event, ui) {
+			droppedFiles.push(ui.draggable.children('a')[0].rel);
+			updateDroppedFilesList();
+		}
+	});
+}
+function updateDroppedFilesList() {
+	var i = droppedFiles.length -1;
+	$('#droppedFileList > ul').append(
+		'<li rel="'+droppedFiles[i]+'">'+droppedFiles[i]+'</li>'
+	);
+}
+function clearDroppedFilesList() {
+	droppedFiles = Array();				// clear the js array
+	$('#droppedFileList ul').html('');	// clear the interface display
+}
+
+
+/********************************************************************
+ * MAIN INITIALIZATION FUNCTION (ON DOM READY)
+ */
+$(document).ready( function() {
+
+	// Initialize the staging area browser
+	initStagingAreaBrowser();
+	
+	// Initialize the staging area navigation buttons
+	$('#stagingNavUpOne')
+    	.dblclick(stagingNavigateUpOne)
+    	.click( function(event) {event.preventDefault();});
+    $('#stagingNavUpRoot')
+    	.dblclick(stagingNavigateUpRoot)
+    	.click( function(event) {event.preventDefault();});
+
+
+	// Initialize the File Manager browser
+	initFileManagerBrowser();
+
+	// Initialize the catalog navigation buttons
+	$('#catalogNavUpOne')
+		.dblclick(catalogNavigateUpOne)
+    	.click( function(event) {event.preventDefault();});
+	$('#catalogNavUpRoot')
+		.dblclick(catalogNavigateUpRoot)
+    	.click( function(event) {event.preventDefault();});
+
+
+	// Make overlaid info messages semi-transparent
+	$('.info.overlay').fadeTo(0,0.8);
+	
+	// Connect staging met extractor refresh button
+	$('#stagingMetExtractorRefreshButton').click(refreshStagedMetadata);
+	
+});
+
+function updateNav(which) {
+	if (which == 'staging') 
+		$('#browseStagingPath').html('Path: ' + _paths.staging);
+		if ('/' == _paths.staging) {
+			// We are at the root, don't show . and ..
+			$('#browseStagingNav').hide();
+		} else {
+			$('#browseStagingNav').show();
+		}
+	if (which == 'catalog') {
+		// Catalog navigation is a little more complex
+		$('#browseCatalogPath').html('Path: ' + _paths.catalog);
+		if ('/' == _paths.catalog) {
+			// We are listing policies, don't show . and ..
+			$('#browseCatalogNav').hide();
+		} else {
+			$('#browseCatalogNav').show();
+		}
+
+	}
+}
+
+function clearMetadataWorkbenchContent(which) {
+	if (which == 'staging') {
+		$('#infoNoMetadataExtractorDefined').hide();
+		$('#stagedMetadataWorkbenchContent').html('');
+		hideStagingMetExtractorSelection();
+		_paths.currentStagedFile = '';
+	} else if (which == 'catalog') {
+		$('#catalogMetadataWorkbenchContent').html('');
+		_paths.currentCatalogedFile = '';
+		_paths.currentProductType   = '';
+	}
+}
+
+
+
+/********************************************************************
+ * STAGING AREA BROWSER FUNCTIONS
+ */
+
+var stagingMetExtractorConfigId = '';
+
+ 
+function initStagingAreaBrowser() {
+	 $('#browseStagingContents').fileTree(
+    	{ root:   '/',
+          which:  'staging',
+          script: './services/directory/staging' 
+        }, function(file) {
+        	getMetadataForStagedFile(file, false);
+      });
+     updateNav('staging');
+}
+
+function stagingNavigateUpOne() {
+	var pieces = _paths.staging.split('/');
+	var newpath = '';
+	for (var i=0; i < (pieces.length-2); i++) {
+		newpath += (pieces[i] + '/');
+	}
+	if ('' == newpath) {
+		newpath = '/';
+	}
+	_paths.staging = newpath;
+	initStagingAreaBrowser();
+	clearMetadataWorkbenchContent('staging');
+	return false;
+}
+
+function stagingNavigateUpRoot() {
+	// Re-Initialize the staging area browser
+	_paths.staging = '/';
+	initStagingAreaBrowser();
+	clearMetadataWorkbenchContent('staging');
+    return false;
+}
+
+function getMetadataForStagedFile(file, overwrite) {
+	$.get('./services/metadata/staging',
+			{ 'id' : file,
+		      'configId' : stagingMetExtractorConfigId,
+		      'overwrite' : overwrite
+			},
+			function(data,textStatus) {
+				displayStagedFileMetadata(file,data);
+			}, "html");
+}
+
+function displayStagedFileMetadata(file,data) {
+	showStagingMetExtractorSelection();
+	_paths.currentStagedFile = file;
+	if (! data.match('tr')) {
+		if (stagingMetExtractorConfigId == '') {
+			$('#infoNoMetadataExtractorDefined').show();
+		}
+	} else { 
+		$('#stagedMetadataWorkbenchContent').html(data);
+		makeStagedMetadataEditable();
+	}
+}
+
+function updateStagingMetExtractorConfigIds() {
+	$.get('./services/metadata/extractor/config',
+		{'current' : stagingMetExtractorConfigId },
+		function(data,textState) {
+			$('#stagingMetExtractorConfigList').html(data);
+			stagingMetExtractorConfigId = $('#stagingMetExtractorConfigList').val();
+		});
+}
+
+function showStagingMetExtractorSelection() {
+	$('#stagedMetadataWorkbenchContent').css('height','323px');
+	$('#stagingMetExtractorSelection').fadeIn('fast');
+	updateStagingMetExtractorConfigIds();
+}
+
+function hideStagingMetExtractorSelection() {
+	$('#stagingMetExtractorSelection').fadeOut('fast');
+	$('#stagedMetadataWorkbenchContent').css('height','350px');
+}
+
+function refreshStagedMetadata() {
+	stagingMetExtractorConfigId = $('#stagingMetExtractorConfigList').val();
+	getMetadataForStagedFile(_paths.currentStagedFile, true);
+}
+/********************************************************************
+ * FILE MANAGER BROWSER FUNCTIONS
+ */
+
+//
+// paths in this area are "virtual", that is, they reflect the logical
+// organization of the file manager catalog rather than the physical
+// organization of the products in the repository. As such, the virtual
+// path to a product is obtained by specifying both the 'policy' and 
+// 'productType':
+//
+// dem00001.tiff exists at "virtual" path: /Lmmp/DEM where
+// LMMP is the policy
+// and DEM is a product type defined within that policy
+//
+
+ 
+function initFileManagerBrowser() {
+	 $('#browseCatalogContents').fileTree(
+    	{ root:   '/',
+          which:  'catalog',
+          script: './services/policy/browse'
+        }, function(file) {
+        	getMetadataForCatalogedFile(file);
+        }, function(productType) {
+          getProductTypeWorkbench(productType);
+     });
+     updateNav('catalog');
+     
+}
+
+function catalogNavigateUpOne() {
+	
+	var pieces = _paths.catalog.split('/');
+	var newpath = '';
+	for (var i=0; i < (pieces.length-2); i++) {
+		newpath += (pieces[i] + '/');
+	}
+	if ('' == newpath) {
+		newpath = '/';
+	}
+	_paths.catalog = newpath;
+	initFileManagerBrowser();
+	clearMetadataWorkbenchContent('catalog');
+	return false;
+}
+
+function catalogNavigateUpRoot() {
+	// Re-Initialize the catalog browser
+	_paths.catalog = '/';
+	initFileManagerBrowser();
+	clearMetadataWorkbenchContent('catalog');
+	return false;
+}
+ 
+function getMetadataForCatalogedFile(file) {
+	$.get('./services/metadata/catalog',
+			{ 'id' : file },
+			function(data,textStatus) {
+				displayCatalogedFileMetadata(file,data);
+				}, "html");
+}
+ 
+function displayCatalogedFileMetadata(file,data) {
+	$('#catalogMetadataWorkbenchContent').html(data);
+	_paths.currentCatalogedFile = file;
+	makeProductMetadataEditable();
+}
+
+function getProductTypeWorkbench(productType) {
+	var pieces = productType.split('/');
+	var policy = pieces[1];
+	var ptype  = pieces[2];
+	$.get('./services/metadata/productType',
+			{ 'policy' : policy, 'productType' : ptype, 'id' : productType },
+			function(data,textStatus) {
+				displayProductTypeWorkbench(productType,data);
+			},"html");
+	itPolicy      = policy;
+	itProductType = ptype;
+}
+
+function displayProductTypeWorkbench(productType,data) {
+	$('#catalogMetadataWorkbenchContent').html('');	// clear the old contents
+	$('.ptwbMetadataList').html(data);				// add metadata from service		
+	
+	$('#productTypeWorkbenchContents')				// display pt workbench
+		.clone()
+		.attr('id','liveProductTypeWorkbenchContents')
+		.appendTo('#catalogMetadataWorkbenchContent')
+		.show()
+		.tabs();
+	clearDroppedFilesList();						// clear dropped files list
+	initDragAndDropTarget();						// set up the d&d target box
+	_paths.currentProductType = productType;		// set the path for the ptype
+	makeProductTypeMetadataEditable();				// allow ptype met editing
+	updateIngestionTaskMetExtractorConfigIds();
+}
+
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/MIT-License.txt b/0.8.1-rc1/curator/src/main/webapp/js/src/MIT-License.txt
new file mode 100644
index 0000000..b803767
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/MIT-License.txt
@@ -0,0 +1,7 @@
+Copyright (c) 2008-2009  Martin Wendt (http://wwWendt.de)

+

+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

+

+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

+

+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/jquery.dynatree.js b/0.8.1-rc1/curator/src/main/webapp/js/src/jquery.dynatree.js
new file mode 100644
index 0000000..6ad49e3
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/jquery.dynatree.js
@@ -0,0 +1,1594 @@
+/*************************************************************************
+	jquery.dynatree.js
+	Dynamic tree view control, with support for lazy loading of branches.
+
+	Copyright (c) 2008-2009  Martin Wendt (http://wwWendt.de)
+	Licensed under the MIT License (MIT-License.txt)
+
+	A current version and some documentation is available at
+		http://dynatree.googlecode.com/
+
+	Let me know, if you find bugs or improvements (martin at domain wwWendt.de).
+
+	$Version: 0.4.0$
+	$Revision: 196, 2009-03-12 09:01:35$
+
+ 	@depends: jquery.js
+ 	@depends: ui.core.js
+    @depends: jquery.cookie.js
+*************************************************************************/
+
+
+/*************************************************************************
+ *	Debug functions
+ */
+
+var _canLog = true;
+
+function _log(mode, msg) {
+	/**
+	 * Usage: logMsg("%o was toggled", this);
+	 */
+	if( !_canLog ) 
+		return;
+	// Remove first argument
+	var args = Array.prototype.slice.apply(arguments, [1]); 
+	// Prepend timestamp
+	var dt = new Date();
+	var tag = dt.getHours()+":"+dt.getMinutes()+":"+dt.getSeconds()+"."+dt.getMilliseconds();
+	args[0] = tag + " - " + args[0];
+
+	try {
+		switch( mode ) {
+		case "info":
+			window.console.info.apply(window.console, args);
+			break;
+		case "warn":
+			window.console.warn.apply(window.console, args);
+			break;
+		default:
+			window.console.log.apply(window.console, args);
+		}
+	} catch(e) {
+		if( !window.console )
+			_canLog = false; // Permanently disable, when logging is not supported by the browser 
+	}
+}
+
+function logMsg(msg) {
+	Array.prototype.unshift.apply(arguments, ["debug"]);
+	_log.apply(this, arguments);
+}
+
+
+/*************************************************************************
+ *	Constants
+ */
+var DTNodeStatus_Error   = -1;
+var DTNodeStatus_Loading = 1;
+var DTNodeStatus_Ok      = 0;
+
+
+// Start of local namespace
+;(function($) {
+
+/*************************************************************************
+ *	Common tool functions.
+ */
+
+var Class = {
+	create: function() {
+		return function() {
+			this.initialize.apply(this, arguments);
+		}
+	}
+}
+
+/*************************************************************************
+ *	Class DynaTreeNode
+ */
+var DynaTreeNode = Class.create();
+
+DynaTreeNode.prototype = {
+	initialize: function(parent, tree, data) {
+		this.parent = parent; 
+		this.tree = tree;
+		if ( typeof data == "string" ) 
+			data = { title: data };
+		if( data.key == undefined )
+			data.key = "_" + tree._nodeCount++;
+		this.data = $.extend({}, $.ui.dynatree.nodedatadefaults, data);
+		this.div = null; // not yet created
+		this.span = null; // not yet created
+		this.childList = null; // no subnodes yet
+		this.isRead = false; // Lazy content not yet read
+		this.hasSubSel = false;
+
+		if( tree.initMode == "cookie" ) {
+			// Init status from cookies
+			if( tree.initActiveKey == this.data.key )
+				tree.activeNode = this;
+			if( tree.initFocusKey == this.data.key )
+				tree.focusNode = this;
+			this.bExpanded = ($.inArray(this.data.key, tree.initExpandedKeys) >= 0);
+			this.bSelected = ($.inArray(this.data.key, tree.initSelectedKeys) >= 0);
+		} else {
+			// Init status from data (write to cookie after init phase)
+			if( data.activate )
+				tree.activeNode = this;
+			if( data.focus )
+				tree.focusNode = this;
+			this.bExpanded = ( data.expand == true ); // Collapsed by default
+			this.bSelected = ( data.select == true ); // Deselected by default
+		}
+		if( this.bExpanded )
+			tree.expandedNodes.push(this);
+		if( this.bSelected )
+			tree.selectedNodes.push(this);
+	},
+
+	toString: function() {
+		return "dtnode<" + this.data.key + ">: '" + this.data.title + "'";
+	},
+
+	toDict: function(recursive, callback) {
+		var dict = $.extend({}, this.data);
+		dict.activate = ( this.tree.activeNode === this );
+		dict.focus = ( this.tree.focusNode === this );
+		dict.expand = this.bExpanded;
+		dict.select = this.bSelected;
+		if( callback )
+			callback(dict);
+		if( recursive && this.childList ) {
+			dict.children = [];
+			for(var i=0; i<this.childList.length; i++ )
+				dict.children.push(this.childList[i].toDict(true, callback));
+		} else {
+			delete dict.children;
+		}
+		return dict;
+	},
+
+	_getInnerHtml: function() {
+		var opts = this.tree.options;
+		var cache = this.tree.cache;
+		// parent connectors
+		var rootParent = opts.rootVisible ? null : this.tree.tnRoot; 
+		var bHideFirstExpander = (opts.rootVisible && opts.minExpandLevel>0) || opts.minExpandLevel>1;
+		var bHideFirstConnector = opts.rootVisible || opts.minExpandLevel>0;
+
+		var res = "";
+		var p = this.parent;
+		while( p ) {
+			// Suppress first connector column, if visible top level is always expanded
+			if ( bHideFirstConnector && (p==rootParent  ) )
+				break;
+			res = ( p.isLastSibling() ? cache.tagEmpty : cache.tagVline) + res ;
+			p = p.parent;
+		}
+
+		// connector (expanded, expandable or simple)
+		if( bHideFirstExpander && this.parent==rootParent ) { 
+			// skip connector
+		} else if ( this.childList || this.data.isLazy) {
+   			res += cache.tagExpander;
+		} else {
+   			res += cache.tagConnector;
+		}
+		
+		// Checkbox mode
+		if( opts.checkbox && this.data.hideCheckbox!=true && !this.data.isStatusNode) {
+   			res += cache.tagCheckbox;
+		}
+		
+		// folder or doctype icon
+   		if ( this.data.icon ) {
+    		res += "<img src='" + opts.imagePath + this.data.icon + "' alt='' />";
+   		} else if ( this.data.icon == false ) {
+        	// icon == false means 'no icon'
+		} else {
+        	// icon == null means 'default icon'
+   			res += cache.tagNodeIcon;
+		}
+
+		// node name
+		var tooltip = ( this.data && typeof this.data.tooltip == "string" ) ? " title='" + this.data.tooltip + "'" : "";
+		res +=  "<a href='#'" + tooltip + ">" + this.data.title + "</a>";
+		return res;
+	},
+
+	render: function(bDeep, bHidden) {
+		/**
+		 * create <div><span>..</span> .. </div> tags for this node.
+		 * 
+		 * <div> // This div contains the node's span and list of child div's.
+		 *   <span>S S S A</span> // Span contains graphic spans and title <a> tag 
+		 *   <div>child1</div>
+		 *   <div>child2</div>
+		 * </div>
+		 */
+//		this.tree.logDebug("%o.render()", this);
+		// --- 
+		if( ! this.div ) {
+			this.span = document.createElement("span");
+			this.span.dtnode = this;
+			if( this.data.key )
+				this.span.id = this.tree.options.idPrefix + this.data.key;
+
+			this.div  = document.createElement("div");
+			this.div.appendChild(this.span);
+			if ( this.parent )
+				this.parent.div.appendChild(this.div);
+
+			if( this.parent==null && !this.tree.options.rootVisible )
+				this.span.style.display = "none";
+		}
+		// set node connector images, links and text
+		this.span.innerHTML = this._getInnerHtml();
+
+		// hide this node, if parent is collapsed
+		this.div.style.display = ( this.parent==null || this.parent.bExpanded ? "" : "none");
+
+		// Set classes for current status
+		var opts = this.tree.options;
+		var cn = opts.classNames;
+		var isLastSib = this.isLastSibling();
+		var cnList = [];
+		cnList.push( ( this.data.isFolder ) ? cn.folder : cn.document );
+		if( this.bExpanded )
+			cnList.push(cn.expanded);
+		if( this.data.isLazy && !this.isRead )
+			cnList.push(cn.lazy);
+		if( isLastSib )
+			cnList.push(cn.lastsib);
+		if( this.bSelected )
+			cnList.push(cn.selected);
+		if( this.hasSubSel )
+			cnList.push(cn.partsel);
+		if( this.tree.activeNode === this )
+			cnList.push(cn.active);
+		if( this.data.addClass )
+			cnList.push(this.data.addClass);
+		// IE6 doesn't correctly evaluate multiples class names,
+		// so we create combined class names that can be used in the CSS
+		cnList.push(cn.combinedExpanderPrefix
+				+ (this.bExpanded ? "e" : "c")
+				+ (this.data.isLazy && !this.isRead ? "d" : "")
+				+ (isLastSib ? "l" : "")
+				);
+		cnList.push(cn.combinedIconPrefix
+				+ (this.bExpanded ? "e" : "c")
+				+ (this.data.isFolder ? "f" : "")
+				);
+		this.span.className = cnList.join(" ");
+
+		if( bDeep && this.childList && (bHidden || this.bExpanded) ) {
+			for(var i=0; i<this.childList.length; i++) {
+				this.childList[i].render(bDeep, bHidden)
+			}
+		}
+	},
+
+	hasChildren: function() {
+		return this.childList != null;
+	},
+
+	isLastSibling: function() {
+		var p = this.parent;
+		if ( !p ) return true;
+		return p.childList[p.childList.length-1] === this;
+	},
+
+	prevSibling: function() {
+		if( !this.parent ) return null;
+		var ac = this.parent.childList;
+		for(var i=1; i<ac.length; i++) // start with 1, so prev(first) = null
+			if( ac[i] === this )
+				return ac[i-1];
+		return null;
+	},
+
+	nextSibling: function() {
+		if( !this.parent ) return null;
+		var ac = this.parent.childList;
+		for(var i=0; i<ac.length-1; i++) // up to length-2, so next(last) = null
+			if( ac[i] === this )
+				return ac[i+1];
+		return null;
+	},
+
+	_setStatusNode: function(data) {
+		// Create, modify or remove the status child node (pass 'null', to remove it).
+		var firstChild = ( this.childList ? this.childList[0] : null );
+		if( !data ) {
+			if ( firstChild ) {
+				this.div.removeChild(firstChild.div);
+				if( this.childList.length == 1 )
+					this.childList = null;
+				else
+					this.childList.shift();
+			}
+		} else if ( firstChild ) {
+			data.isStatusNode = true;
+			firstChild.data = data;
+			firstChild.render(false, false);
+		} else {
+			data.isStatusNode = true;
+//			firstChild = this._addChildNode(new DynaTreeNode(this, this.tree, data));
+			firstChild = this._addNode(data);
+		}
+	},
+
+	setLazyNodeStatus: function(lts) {
+		switch( lts ) {
+			case DTNodeStatus_Ok:
+				this._setStatusNode(null);
+				this.isRead = true;
+				this.render(false, false);
+				if( this.tree.options.autoFocus ) {
+					if( this === this.tree.tnRoot && !this.tree.options.rootVisible && this.childList ) {
+						// special case: using ajaxInit
+						this.childList[0].focus();
+					} else {
+						this.focus();
+					}
+				}
+				break;
+			case DTNodeStatus_Loading:
+				this._setStatusNode({
+					title: this.tree.options.strings.loading,
+//					icon: "ltWait.gif"
+					addClass: this.tree.options.classNames.nodeWait
+				});
+				break;
+			case DTNodeStatus_Error:
+				this._setStatusNode({
+					title: this.tree.options.strings.loadError,
+//					icon: "ltError.gif"
+					addClass: this.tree.options.classNames.nodeError
+				});
+				break;
+			default:
+				throw "Bad LazyNodeStatus: '" + lts + "'.";
+		}
+	},
+
+	_parentList: function(includeRoot, includeSelf) {
+		var l = new Array();
+		var dtn = includeSelf ? this : this.parent;
+		while( dtn ) {
+			if( includeRoot || dtn.parent )
+				l.unshift(dtn);
+			dtn = dtn.parent;
+		};
+		return l;
+	},
+
+	getLevel: function() {
+		var level = 0;
+		var dtn = this.parent;
+		while( dtn ) {
+			level++;
+			dtn = dtn.parent;
+		};
+		return level;
+	},
+
+	isVisible: function() {
+		// Return true, if all parents are expanded.
+		var parents = this._parentList(true, false);
+		for(var i=0; i<parents.length; i++)
+			if( ! parents[i].bExpanded ) return false;
+		return true;
+	},
+
+	makeVisible: function() {
+		// Make sure, all parents are expanded
+		var parents = this._parentList(true, false);
+		for(var i=0; i<parents.length; i++)
+			parents[i]._expand(true);
+	},
+
+	focus: function() {
+		// TODO: check, if we already have focus
+//		this.tree.logDebug("dtnode.focus(): %o", this);
+		this.makeVisible();
+		try {
+			$(this.span).find(">a").focus();
+		} catch(e) { }
+	},
+
+	isActive: function() {
+		return (this.tree.activeNode === this);
+	},
+	
+	activate: function() {
+		// Select - but not focus - this node.
+//		this.tree.logDebug("dtnode.activate(): %o", this);
+		var opts = this.tree.options;
+		if( this.data.isStatusNode )
+			return;
+		if ( opts.onQueryActivate && opts.onQueryActivate.call(this.span, true, this) == false )
+			return; // Callback returned false
+		if( this.tree.activeNode ) {
+			if( this.tree.activeNode === this )
+				return;
+			this.tree.activeNode.deactivate();
+		}
+		if( opts.activeVisible )
+			this.makeVisible();
+		this.tree.activeNode = this;
+        if( opts.persist )
+			$.cookie(opts.cookieId+"-active", this.data.key, opts.cookie);
+		$(this.span).addClass(opts.classNames.active);
+		if ( opts.onActivate ) // Pass element as 'this' (jQuery convention)
+			opts.onActivate.call(this.span, this);
+	},
+
+	deactivate: function() {
+//		this.tree.logDebug("dtnode.deactivate(): %o", this);
+		if( this.tree.activeNode === this ) {
+			var opts = this.tree.options;
+			if ( opts.onQueryActivate && opts.onQueryActivate.call(this.span, false, this) == false )
+				return; // Callback returned false
+			$(this.span).removeClass(opts.classNames.active);
+	        if( opts.persist )
+				$.cookie(opts.cookieId+"-active", "", opts.cookie);
+			this.tree.activeNode = null;
+			if ( opts.onDeactivate )
+				opts.onDeactivate.call(this.span, this);
+		}
+	},
+
+	_userActivate: function() {
+		// Handle user click / [space] / [enter], according to clickFolderMode.
+		var activate = true;
+		var expand = false;
+		if ( this.data.isFolder ) {
+			switch( this.tree.options.clickFolderMode ) {
+			case 2:
+				activate = false;
+				expand = true;
+				break;
+			case 3:
+				activate = expand = true;
+				break;
+			}
+		}
+		if( this.parent == null && this.tree.options.minExpandLevel>0 ) {
+			expand = false;
+		}
+		if( expand ) {
+			this.toggleExpand();
+			this.focus();
+		} 
+		if( activate ) {
+			this.activate();
+		}
+	},
+
+	_setSubSel: function(hasSubSel) {
+		if( hasSubSel ) {
+			this.hasSubSel = true;
+			$(this.span).addClass(this.tree.options.classNames.partsel);
+		} else {
+			this.hasSubSel = false;
+			$(this.span).removeClass(this.tree.options.classNames.partsel);
+		}
+	},
+
+	_fixSelectionState: function() {
+		// fix selection status, for multi-hier mode 
+//		this.tree.logDebug("_fixSelectionState(%o) - %o", this.bSelected, this);
+		if( this.bSelected ) {
+			// Select all children
+			this.visit(function(dtnode){
+				dtnode.parent._setSubSel(true);
+				dtnode._select(true, false, false);
+			});
+			// Select parents, if all children are selected
+			var p = this.parent;
+			while( p ) {
+				p._setSubSel(true);
+				var allChildsSelected = true;
+				for(var i=0; i<p.childList.length;  i++) {
+					var n = p.childList[i]; 
+					if( !n.bSelected && !n.data.isStatusNode ) {
+						allChildsSelected = false;
+						break;
+					}
+				}
+				if( allChildsSelected )
+					p._select(true, false, false);
+				p = p.parent;
+			}
+		} else {
+			// Deselect all children
+			this._setSubSel(false);
+			this.visit(function(dtnode){
+				dtnode._setSubSel(false);
+				dtnode._select(false, false, false);
+			});
+			// Deselect parents, and recalc hasSubSel
+			var p = this.parent;
+			while( p ) {
+				p._select(false, false, false);
+				var isPartSel = false;
+				for(var i=0; i<p.childList.length;  i++) {
+					if( p.childList[i].bSelected || p.childList[i].hasSubSel ) {
+						isPartSel = true;
+						break;
+					}
+				}
+				p._setSubSel(isPartSel);
+				p = p.parent;
+			}
+		}
+	},
+	
+	_select: function(sel, fireEvents, deep) {
+		// Select - but not focus - this node.
+//		this.tree.logDebug("dtnode._select(%o) - %o", sel, this);
+		var opts = this.tree.options;
+		if( this.data.isStatusNode )
+			return;
+		// 
+		if( this.bSelected == sel ) {
+//			this.tree.logDebug("dtnode._select(%o) IGNORED - %o", sel, this);
+			return;
+		}
+		// Allow event listener to abort selection
+		if ( fireEvents && opts.onQuerySelect && opts.onQuerySelect.call(this.span, sel, this) == false )
+			return; // Callback returned false
+		
+		// Force single-selection
+		if( opts.selectMode==1 && this.tree.selectedNodes.length && sel ) 
+			this.tree.selectedNodes[0]._select(false, false, false);
+
+		this.bSelected = sel;
+        this.tree._changeNodeList("select", this, sel);
+			
+		if( sel ) {
+			$(this.span).addClass(opts.classNames.selected);
+
+			if( deep && opts.selectMode==3 )
+				this._fixSelectionState();
+
+			if ( fireEvents && opts.onSelect )
+				opts.onSelect.call(this.span, true, this);
+
+		} else {
+			$(this.span).removeClass(opts.classNames.selected);
+
+	    	if( deep && opts.selectMode==3 )
+				this._fixSelectionState();
+
+	    	if ( fireEvents && opts.onSelect )
+				opts.onSelect.call(this.span, false, this);
+		}
+	},
+
+	isSelected: function() {
+		return this.bSelected;
+	},
+	
+	select: function(sel) {
+		// Select - but not focus - this node.
+//		this.tree.logDebug("dtnode.select(%o) - %o", sel, this);
+		return this._select(sel!=false, true, true);
+	},
+
+	toggleSelect: function() {
+//		this.tree.logDebug("dtnode.toggleSelect() - %o", this);
+		return this.select(!this.bSelected);
+	},
+
+	_expand: function(bExpand) {
+//		this.tree.logDebug("dtnode._expand(%o) - %o", bExpand, this);
+		if( this.bExpanded == bExpand ) {
+//			this.tree.logDebug("dtnode._expand(%o) IGNORED - %o", bExpand, this);
+			return;
+		}
+		var opts = this.tree.options;
+		if( !bExpand && this.getLevel()<opts.minExpandLevel ) {
+			this.tree.logDebug("dtnode._expand(%o) forced expand - %o", bExpand, this);
+			return;
+		}
+		if ( opts.onQueryExpand && opts.onQueryExpand.call(this.span, bExpand, this) == false )
+			return; // Callback returned false
+		this.bExpanded = bExpand;
+		// Persist expand state
+    	this.tree._changeNodeList("expand", this, bExpand);
+/*
+        if( bExpand ) {
+			$(this.span).addClass(opts.classNames.expanded);
+        } else {
+			$(this.span).removeClass(opts.classNames.expanded);
+        }
+*/
+        this.render(false);
+
+        // Auto-collapse mode: collapse all siblings
+		if( this.bExpanded && this.parent && opts.autoCollapse ) {
+			var parents = this._parentList(false, true);
+			for(var i=0; i<parents.length; i++)
+				parents[i].collapseSiblings();
+		}
+		// If current focus is now hidden, focus the first visible parent.
+		// TODO: doesn't make sense here(?) we should check if the currently focused node (not <this>) is visible.
+		// At the moment, _expand gets only called, after focus was set to <this>.
+		if( ! this.bExpanded && ! this.isVisible() ) {
+			this.tree.logDebug("Focus became invisible: setting to this.");
+			this.focus();
+		}
+		// If currently active node is now hidden, deactivate it
+		if( opts.activeVisible && this.tree.activeNode && ! this.tree.activeNode.isVisible() ) {
+			this.tree.activeNode.deactivate();
+		}
+		// Expanding a lazy node: set 'loading...' and call callback
+		if( bExpand && this.data.isLazy && !this.isRead ) {
+			try {
+				this.tree.logDebug("_expand: start lazy - %o", this);
+				this.setLazyNodeStatus(DTNodeStatus_Loading);
+				if( true == opts.onLazyRead.call(this.span, this) ) {
+					// If function returns 'true', we assume that the loading is done:
+					this.setLazyNodeStatus(DTNodeStatus_Ok);
+					// Otherwise (i.e. if the loading was started as an asynchronous process)
+					// the onLazyRead(dtnode) handler is expected to call dtnode.setLazyNodeStatus(DTNodeStatus_Ok/_Error) when done.
+					this.tree.logDebug("_expand: lazy succeeded - %o", this);
+				}
+			} catch(e) {
+				this.setLazyNodeStatus(DTNodeStatus_Error);
+			}
+			return;
+		}
+//		this.tree.logDebug("_expand: start div toggle - %o", this);
+
+		if( opts.fx ) {
+			var duration = opts.fx.duration || 200;
+			$(">DIV", this.div).animate(opts.fx, duration);
+		} else {
+//			$(">DIV", this.div).toggle();
+			var $d = $(">DIV", this.div);
+//			this.tree.logDebug("_expand: got div, start toggle - %o", this);
+			$d.toggle();
+		}
+//		this.tree.logDebug("_expand: end div toggle - %o", this);
+
+		if ( opts.onExpand )
+			opts.onExpand.call(this.span, bExpand, this);
+	},
+
+	expand: function(flag) {
+		if( !this.childList && !this.data.isLazy )
+			return;
+		if( this.parent == null && this.tree.options.minExpandLevel>0 && !flag)
+			return; // Prevent collapsing the root
+		this._expand(flag);
+	},
+
+	toggleExpand: function() {
+		this.expand(!this.bExpanded);
+/*		
+//		this.tree.logDebug("toggleExpand("+this.data.title+")...");
+		if( !this.childList && !this.data.isLazy )
+			return;
+		if( this.parent == null && this.tree.options.minExpandLevel>0 && this.bExpanded)
+			return; // Prevent collapsing the root
+		this._expand( ! this.bExpanded);
+//		this.tree.logDebug("toggleExpand("+this.data.title+") done.");
+*/
+	},
+
+	collapseSiblings: function() {
+		if( this.parent == null )
+			return;
+		var ac = this.parent.childList;
+		for (var i=0; i<ac.length; i++) {
+			if ( ac[i] !== this && ac[i].bExpanded )
+				ac[i]._expand(false);
+		}
+	},
+
+	onClick: function(event) {
+//		this.tree.logDebug("dtnode.onClick(" + event.type + "): dtnode:" + this + ", button:" + event.button + ", which: " + event.which);
+
+		if( $(event.target).hasClass(this.tree.options.classNames.expander) ) {
+			// Clicking the expander icon always expands/collapses
+			this.toggleExpand();
+		} else if( $(event.target).hasClass(this.tree.options.classNames.checkbox) ) {
+			// Clicking the checkbox always (de)selects
+			this.toggleSelect();
+		} else {
+			this._userActivate();
+			// Chrome and Safari don't focus the a-tag on click
+//			this.tree.logDebug("a tag: ", this.span.getElementsByTagName("a")[0]);
+			this.span.getElementsByTagName("a")[0].focus();
+//			alert("hasFocus=" + this.span.getElementsByTagName("a")[0].focused);
+		}
+		// Make sure that clicks stop, otherwise <a href='#'> jumps to the top
+		return false;
+	},
+
+	onDblClick: function(event) {
+//		this.tree.logDebug("dtnode.onDblClick(" + event.type + "): dtnode:" + this + ", button:" + event.button + ", which: " + event.which);
+	},
+
+	onKeydown: function(event) {
+//		this.tree.logDebug("dtnode.onKeydown(" + event.type + "): dtnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
+		var handled = true;
+//		alert("keyDown" + event.which);
+
+		switch( event.which ) {
+			// charCodes:
+//			case 43: // '+'
+			case 107: // '+'
+			case 187: // '+' @ Chrome, Safari
+				if( !this.bExpanded ) this.toggleExpand();
+				break;
+//			case 45: // '-'
+			case 109: // '-'
+			case 189: // '+' @ Chrome, Safari
+				if( this.bExpanded ) this.toggleExpand();
+				break;
+			//~ case 42: // '*'
+				//~ break;
+			//~ case 47: // '/'
+				//~ break;
+			// case 13: // <enter>
+				// <enter> on a focused <a> tag seems to generate a click-event. 
+				// this._userActivate();
+				// break;
+			case 32: // <space>
+				this._userActivate();
+				break;
+			case 8: // <backspace>
+				if( this.parent )
+					this.parent.focus();
+				break;
+			case 37: // <left>
+				if( this.bExpanded ) {
+					this.toggleExpand();
+					this.focus();
+				} else if( this.parent && (this.tree.options.rootVisible || this.parent.parent) ) {
+					this.parent.focus();
+				}
+				break;
+			case 39: // <right>
+				if( !this.bExpanded && (this.childList || this.data.isLazy) ) {
+					this.toggleExpand();
+					this.focus();
+				} else if( this.childList ) {
+					this.childList[0].focus();
+				}
+				break;
+			case 38: // <up>
+				var sib = this.prevSibling();
+				while( sib && sib.bExpanded )
+					sib = sib.childList[sib.childList.length-1];
+				if( !sib && this.parent && (this.tree.options.rootVisible || this.parent.parent) )
+					sib = this.parent;
+				if( sib ) sib.focus();
+				break;
+			case 40: // <down>
+				var sib;
+				if( this.bExpanded ) {
+					sib = this.childList[0];
+				} else {
+					var parents = this._parentList(false, true);
+					for(var i=parents.length-1; i>=0; i--) {
+						sib = parents[i].nextSibling();
+						if( sib ) break;
+					}
+				}
+				if( sib ) sib.focus();
+				break;
+			default:
+				handled = false;
+		}
+		// Return false, if handled, to prevent default processing
+		return !handled; 
+	},
+
+	onKeypress: function(event) {
+		// onKeypress is only hooked to allow user callbacks.
+		// We don't process it, because IE and Safari don't fire keypress for cursor keys.
+//		this.tree.logDebug("dtnode.onKeypress(" + event.type + "): dtnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
+	},
+	
+	onFocus: function(event) {
+		// Handles blur and focus events.
+//		this.tree.logDebug("dtnode.onFocus(%o): %o", event, this);
+		var opts = this.tree.options;
+		if ( event.type=="blur" || event.type=="focusout" ) {
+			if ( opts.onBlur ) // Pass element as 'this' (jQuery convention)
+				opts.onBlur.call(this.span, this);
+			if( this.tree.tnFocused )
+				$(this.tree.tnFocused.span).removeClass(opts.classNames.focused);
+			this.tree.tnFocused = null;
+	        if( opts.persist )
+				$.cookie(opts.cookieId+"-focus", null, opts.cookie);
+		} else if ( event.type=="focus" || event.type=="focusin") {
+			// Fix: sometimes the blur event is not generated
+			if( this.tree.tnFocused && this.tree.tnFocused !== this ) {
+				this.tree.logDebug("dtnode.onFocus: out of sync: curFocus: %o", this.tree.tnFocused);
+				$(this.tree.tnFocused.span).removeClass(opts.classNames.focused);
+			}
+			this.tree.tnFocused = this;
+			if ( opts.onFocus ) // Pass element as 'this' (jQuery convention)
+				opts.onFocus.call(this.span, this);
+			$(this.tree.tnFocused.span).addClass(opts.classNames.focused);
+	        if( opts.persist )
+				$.cookie(opts.cookieId+"-focus", this.data.key, opts.cookie);
+		}
+		// TODO: return anything?
+//		return false;
+	},
+
+	_postInit: function() {
+		// Called, when childs have been loaded.
+		if ( opts.onPostInit ) // Pass element as 'this' (jQuery convention)
+			opts.onPostInit.call(this.span, this);
+	},
+		
+	visit: function(fn, data, includeSelf) {
+		// Call fn(dtnode, data) for all child nodes. Stop iteration, if fn() returns false.
+		var n = 0;
+		if( includeSelf == true ) {
+			if( fn(this, data) == false )
+				return 1; 
+			n++; 
+		}
+		if ( this.childList )
+			for (var i=0; i<this.childList.length; i++)
+				n += this.childList[i].visit(fn, data, true);
+		return n;
+	},
+
+	remove: function() {
+        // Remove this node
+//		this.tree.logDebug ("%o.remove()", this);
+        if ( this === this.tree.root )
+            return false;
+        return this.parent.removeChild(this);
+	},
+
+	removeChild: function(tn) {
+		// Remove tn from list of direct children.
+		var ac = this.childList;
+		if( ac.length == 1 ) {
+			if( tn !== ac[0] )
+				throw "removeChild: invalid child";
+			return this.removeChildren();
+		}
+        if ( tn === this.tree.activeNode )
+        	tn.deactivate();
+        if ( tn.bSelected )
+        	this.tree._changeNodeList("select", tn, false);
+        if ( tn.bExpanded )
+        	this.tree._changeNodeList("expand", tn, false);
+		tn.removeChildren(true);
+		this.div.removeChild(tn.div);
+		for(var i=0; i<ac.length; i++) {
+			if( ac[i] === tn ) {
+				this.childList.splice(i, 1);
+				delete tn;
+				break;
+			}
+		}
+	},
+
+	removeChildren: function(recursive) {
+        // Remove all child nodes (more efficiently than recursive remove())
+//		this.tree.logDebug ("%o.removeChildren(%o)", this, recursive);
+		var tree = this.tree;
+        var ac = this.childList;
+        if( ac ) {
+        	for(var i=0; i<ac.length; i++) {
+				var tn=ac[i];
+//        		this.tree.logDebug ("del %o", tn);
+                if ( tn === tree.activeNode )
+                	tn.deactivate();
+                if ( tn.bSelected )
+                	this.tree._changeNodeList("select", tn, false);
+                if ( tn.bExpanded )
+                	this.tree._changeNodeList("expand", tn, false);
+                tn.removeChildren(true);
+				this.div.removeChild(tn.div);
+                delete tn;
+        	}
+        	this.childList = null;
+			if( ! recursive ) {
+				this._expand(false);
+				this.isRead = false;
+				this.render(false, false);
+			}
+        }
+	},
+
+	_addChildNode: function (dtnode) {
+//		this.tree.logDebug ("%o._addChildNode(%o)", this, dtnode);
+		var opts = this.tree.options;
+		if ( this.childList==null ) {
+			this.childList = new Array();
+		} else {
+			// Fix 'lastsib'
+			$(this.childList[this.childList.length-1].span).removeClass(opts.classNames.lastsib);
+		}
+
+		this.childList.push (dtnode);
+		dtnode.parent = this; // TODO: only need to assert this
+
+		// Expand the parent, if it's below minExpandLevel, or marked as expanded
+//		this.tree.logDebug ("%o._addChildNode(%o), l=%o", this, dtnode, dtnode.getLevel());
+		if ( dtnode.data.expand || opts.minExpandLevel >= dtnode.getLevel() )
+			this.bExpanded = true;
+
+		// In multi-hier mode, update the parents selction state
+		if( !dtnode.data.isStatusNode && opts.selectMode==3 )
+			dtnode._fixSelectionState();
+
+		if ( this.tree.bEnableUpdate )
+			this.render(true, true);
+
+		return dtnode;
+	},
+
+	_addNode: function(data) {
+		return this._addChildNode(new DynaTreeNode(this, this.tree, data));
+	},
+
+	append: function(obj) {
+		/*
+		Data format: array of node objects, with optional 'children' attributes.
+		[
+			{ title: "t1", isFolder: true, ... }
+			{ title: "t2", isFolder: true, ...,
+				children: [
+					{title: "t2.1", ..},
+					{..}
+					]
+			}
+		]
+		A simple object is also accepted instead of an array.
+		*/
+//		this.tree.logDebug ("%o.append(%o)", this, obj);
+		if( !obj || obj.length==0 ) // Passed null or undefined or empty array
+			return;
+		if( !obj.length ) // Passed a single node
+			obj = [ obj ];
+//			return this._addNode(obj);
+
+		var prevFlag = this.tree.enableUpdate(false);
+
+		var tnFirst = null;
+		for (var i=0; i<obj.length; i++) {
+			var data = obj[i];
+			var dtnode = this._addNode(data);
+			if( !tnFirst ) tnFirst = dtnode;
+			if( data.children )
+				dtnode.append(data.children);
+		}
+		this.tree.enableUpdate(prevFlag);
+		return tnFirst;
+	},
+
+	appendAjax: function(ajaxOptions) {
+		this.setLazyNodeStatus(DTNodeStatus_Loading);
+		// Ajax option inheritance: $.ajaxSetup < $.ui.dynatree.defaults.ajaxDefaults < tree.options.ajaxDefaults < ajaxOptions
+		var self = this;
+		var ajaxOptions = $.extend({}, this.tree.options.ajaxDefaults, ajaxOptions, {
+       		success: function(data, textStatus){
+				self.append(data);
+				self.setLazyNodeStatus(DTNodeStatus_Ok);
+       			},
+       		error: function(XMLHttpRequest, textStatus, errorThrown){
+				self.setLazyNodeStatus(DTNodeStatus_Error);
+       			}
+		});
+       	$.ajax(ajaxOptions);
+	},
+	// --- end of class
+	lastentry: undefined
+}
+
+/*************************************************************************
+ * class DynaTree
+ */
+
+var DynaTree = Class.create();
+
+// static members
+DynaTree.version = "$Version: 0.4.0$"; 
+
+DynaTree.prototype = {
+	// Constructor
+	initialize: function(divContainer, options) {
+		// instance members
+		this.options = options;
+
+		this.bEnableUpdate = true;
+		this._nodeCount = 0;
+
+		// Initial status is read from cookies, if persistence is active and 
+		// cookies are already present.
+		// Otherwise the status is read from the data attributes and then persisted.
+		this.initMode = "data";
+
+		this.activeNode = null;
+		this.selectedNodes = new Array();
+		this.expandedNodes = new Array();
+
+		if( this.options.persist ) {
+			// Requires jquery.cookie.js:
+			this.initActiveKey = $.cookie(this.options.cookieId + "-active");
+			if( cookie || this.initActiveKey != null )
+				this.initMode = "cookie";
+
+			this.initFocusKey = $.cookie(this.options.cookieId + "-focus");
+
+			var cookie = $.cookie(this.options.cookieId + "-expand");
+            if( cookie != null )
+                this.initMode = "cookie";
+			this.initExpandedKeys = cookie ? cookie.split(",") : [];
+
+			cookie = $.cookie(this.options.cookieId + "-select");
+			this.initSelectedKeys = cookie ? cookie.split(",") : [];
+		}
+		this.logDebug("initMode: %o, active: %o, expanded: %o, selected: %o", this.initMode, this.initActiveKey, this.initExpandedKeys, this.initSelectedKeys);
+
+		// Cached tag strings
+		this.cache = {
+			tagEmpty: "<span class='" + options.classNames.empty + "'></span>",
+			tagVline: "<span class='" + options.classNames.vline + "'></span>",
+			tagExpander: "<span class='" + options.classNames.expander + "'></span>",
+			tagConnector: "<span class='" + options.classNames.connector + "'></span>",
+			tagNodeIcon: "<span class='" + options.classNames.nodeIcon + "'></span>",
+			tagCheckbox: "<span class='" + options.classNames.checkbox + "'></span>",
+			lastentry: undefined
+		};
+
+		// find container element
+		this.divTree = divContainer;
+		// create the root element
+		this.tnRoot = new DynaTreeNode(null, this, {title: this.options.title, key: "root"});
+		this.tnRoot.data.isFolder = true;
+		this.tnRoot.render(false, false);
+		this.divRoot = this.tnRoot.div;
+		this.divRoot.className = this.options.classNames.container;
+		// add root to container
+		this.divTree.appendChild(this.divRoot);
+	},
+
+	// member functions
+
+	toString: function() {
+		return "DynaTree '" + this.options.title + "'";
+	},
+
+	toDict: function() {
+		return this.tnRoot.toDict(true);
+	},
+	
+	logDebug: function(msg) {
+		if( this.options.debugLevel >= 2 ) {
+			Array.prototype.unshift.apply(arguments, ["debug"]);
+			_log.apply(this, arguments);
+		}
+	},
+
+	logInfo: function(msg) {
+		if( this.options.debugLevel >= 1 ) {
+			Array.prototype.unshift.apply(arguments, ["info"]);
+			_log.apply(this, arguments);
+		}
+	},
+
+	logWarning: function(msg) {
+		Array.prototype.unshift.apply(arguments, ["warn"]);
+		_log.apply(this, arguments);
+	},
+
+	isInitializing: function() {
+		return ( this.initMode=="data" || this.initMode=="cookie" || this.initMode=="postInit" );
+	},
+	
+	_changeNodeList: function(mode, node, bAdd) {
+		// Add or remove key from a key list and optionally write cookie.
+		if( !node )
+			return false;
+		var cookieName = this.options.cookieId + "-" + mode;
+		var nodeList = ( mode=="expand" ) ? this.expandedNodes : this.selectedNodes;  
+		var idx = $.inArray(node, nodeList);
+//		this.logDebug("_changeNodeList(%o): nodeList:%o, idx:%o", mode, nodeList, idx);
+		if( bAdd ) {
+			if( idx >=0 )
+				return false;
+			nodeList.push(node);
+		} else {
+			if( idx < 0 )
+				return false;
+			nodeList.splice(idx, 1);
+		}
+//		this.logDebug("  -->: nodeList:%o", nodeList);
+		if( this.options.persist ) {
+			var keyList = $.map(nodeList, function(e,i){return e.data.key});
+//			this.logDebug("_changeNodeList: write cookie <%s> = '%s'", cookieName, keyList.join("', '"));
+			$.cookie(cookieName, keyList.join(","), this.options.cookie);
+		} else {
+//			this.logDebug("_changeNodeListCookie: %o", nodeList);
+		}
+	},
+	
+	redraw: function() {
+		this.logDebug("dynatree.redraw()...");
+		this.tnRoot.render(true, true);
+		this.logDebug("dynatree.redraw() done.");
+	},
+
+	getRoot: function() {
+		return this.tnRoot;
+	},
+
+	getNodeByKey: function(key) {
+		// $("#...") has problems, if the key contains '.', so we use getElementById()
+//		return $("#" + this.options.idPrefix + key).attr("dtnode");
+		var el = document.getElementById(this.options.idPrefix + key);
+		return ( el && el.dtnode ) ? el.dtnode : null;
+	},
+
+	getActiveNode: function() {
+		return this.activeNode;
+	},
+
+	getSelectedNodes: function(stopOnParents) {
+		if( stopOnParents == true ) {
+			var nodeList = [];
+			this.tnRoot.visit(function(dtnode){
+				if( dtnode.bSelected ) {
+					nodeList.push(dtnode);
+					return false; // stop processing this branch
+				}
+			});
+			return nodeList;
+		} else {
+			return this.selectedNodes;
+		}
+	},
+
+	activateKey: function(key) {
+		var dtnode = this.getNodeByKey(key);
+		if( !dtnode ) {
+			this.activeNode = null;
+			return null;
+		}
+		dtnode.focus();
+		dtnode.activate();
+		return dtnode;
+	},
+
+	selectKey: function(key, select) {
+		var dtnode = this.getNodeByKey(key);
+		if( !dtnode )
+			return null;
+		dtnode.select(select);
+		return dtnode;
+	},
+
+	enableUpdate: function(bEnable) {
+		if ( this.bEnableUpdate==bEnable )
+			return bEnable;
+		this.bEnableUpdate = bEnable;
+		if ( bEnable )
+			this.redraw();
+		return !bEnable; // return previous value
+	},
+
+	visit: function(fn, data, includeRoot) {
+		return this.tnRoot.visit(fn, data, includeRoot);
+	},
+
+	_createFromTag: function(parentTreeNode, $ulParent) {
+		// Convert a <UL>...</UL> list into children of the parent tree node.
+		var self = this;
+/*
+TODO: better?
+		this.$lis = $("li:has(a[href])", this.element);
+		this.$tabs = this.$lis.map(function() { return $("a", this)[0]; });
+ */
+		$ulParent.find(">li").each(function() {
+			var $li = $(this);
+			var $liSpan = $li.find(">span:first");
+			var title;
+			if( $liSpan.length ) {
+				// If a <li><span> tag is specified, use it literally.
+				title = $liSpan.html();
+			} else {
+				// If only a <li> tag is specified, use the trimmed string up to the next child <ul> tag.
+				title = $li.html();
+				var iPos = title.search(/<ul/i);
+				if( iPos>=0 )
+					title = $.trim(title.substring(0, iPos));
+				else
+					title = $.trim(title);
+//				self.logDebug("%o", title);
+			}
+			// Parse node options from ID, title and class attributes
+			var data = {
+				title: title,
+				isFolder: $li.hasClass("folder"),
+				isLazy: $li.hasClass("lazy"),
+				expand: $li.hasClass("expanded"),
+				select: $li.hasClass("selected"),
+				activate: $li.hasClass("active"),
+				focus: $li.hasClass("focused")
+			};
+			if( $li.attr("title") )
+				data.tooltip = $li.attr("title");
+			if( $li.attr("id") )
+				data.key = $li.attr("id");
+			// If a data attribute is present, evaluate as a javascript object
+			if( $li.attr("data") ) {
+				var dataAttr = $.trim($li.attr("data"));
+				if( dataAttr ) {
+					if( dataAttr.charAt(0) != "{" )
+						dataAttr = "{" + dataAttr + "}"
+					try {
+						$.extend(data, eval("(" + dataAttr + ")"));
+					} catch(e) {
+						throw ("Error parsing node data: " + e + "\ndata:\n'" + dataAttr + "'");
+					}
+				}
+			}
+			childNode = parentTreeNode._addNode(data);
+			// Recursive reading of child nodes, if LI tag contains an UL tag
+			var $ul = $li.find(">ul:first");
+			if( $ul.length ) {
+				self._createFromTag(childNode, $ul); // must use 'self', because 'this' is the each() context
+			}
+		});
+	},
+	// --- end of class
+	lastentry: undefined
+};
+
+/*************************************************************************
+ * widget $(..).dynatree
+ */
+
+
+$.widget("ui.dynatree", {
+	init: function() {
+        // ui.core 1.6 renamed init() to _init(): this stub assures backward compatibility
+//        logMsg("ui.dynatree.init() was called, you should upgrade to ui.core.js v1.6 or higher.");
+        return this._init();
+    },
+
+	_init: function() {
+		logMsg("Dynatree._init(): version='%s', debugLevel=%o.", DynaTree.version, this.options.debugLevel);
+
+		// The widget framework supplies this.element and this.options.
+		this.options.event += ".dynatree"; // namespace event
+
+		// Create DynaTree
+		var $this = this.element;
+		var opts = this.options;
+
+		// Guess skin path, if not specified
+		if(!opts.imagePath) {
+			$("script").each( function () {
+				if( this.src.search(/.*dynatree[^/]*\.js$/i) >= 0 ) {
+                    if( this.src.indexOf("/")>=0 ) // issue #47
+					    opts.imagePath = this.src.slice(0, this.src.lastIndexOf("/")) + "/skin/";
+                    else
+					    opts.imagePath = "skin/";
+					logMsg("Guessing imagePath from '%s': '%s'", this.src, opts.imagePath);
+					return false; // first match
+				}
+			});
+		}
+		// Attach the tree object to parent element
+		var divContainer = $this.get(0);
+
+		// Clear container, in case it contained some 'waiting' or 'error' 
+		// for clients that don't support JS
+		if( opts.children || (opts.initAjax && opts.initAjax.url) || opts.initId )
+			$(divContainer).empty();
+
+		this.tree = new DynaTree(divContainer, opts);
+		var root = this.tree.getRoot();
+
+		var prevFlag = this.tree.enableUpdate(false); // Speedup by 13s -> 1,5 s 
+		this.tree.logDebug("Start init tree structure...");
+		// Init tree structure
+		if( opts.children ) {
+			// Read structure from node array
+			root.append(opts.children);
+
+		} else if( opts.initAjax && opts.initAjax.url ) {
+			// Init tree from AJAX request
+			root.appendAjax(opts.initAjax);
+
+		} else if( opts.initId ) {
+			// Init tree from another UL element
+			this.tree._createFromTag(root, $("#"+opts.initId));
+
+		} else {
+			// Init tree from the first UL element inside the container <div>
+			var $ul = $this.find(">ul").hide();
+			this.tree._createFromTag(root, $ul);
+			$ul.remove();
+		}
+		this.tree.enableUpdate(prevFlag);
+		this.tree.logDebug("Init tree structure... done.");
+
+		// bind event handlers
+		this.bind();
+
+        // Fire expand/select/focus/activate events for all nodes that were initialized
+		this.tree.initMode = "postInit";
+		
+/*	TODO: re-fire expand events is not required:
+          Nodes are already rendered by _addChidNode and .expandedNodes[] is valid. 
+    
+//		logMsg("_init: expandedNodes: %o, re-fireing events", this.tree.expandedNodes);
+//		var nodeList = this.tree.expandedNodes.slice();
+//		this.tree.expandedNodes = [];
+		var nodeList = this.tree.expandedNodes;
+		for(var i=0; i<nodeList.length; i++ ) {
+			var dtnode = nodeList[i];
+			logMsg("Expand on init: %o", dtnode);
+//			dtnode.bExpanded = false; // make sure this is not ignored
+			dtnode._expand(true);
+		}
+//		logMsg("_init: expandedNodes: %o, after ", this.tree.expandedNodes);
+*/
+
+		// Re-fire select events, so we have the checks according to selectMode
+		// and also the user may react on the events
+		nodeList = this.tree.selectedNodes.slice();
+		this.tree.selectedNodes = [];
+		for(var i=0; i<nodeList.length; i++ ) {
+			var dtnode = nodeList[i];
+			this.tree.logDebug("Re-select on init: %o", dtnode);
+			dtnode.bSelected = false; // make sure this is not ignored
+			dtnode.select(true);
+		}
+
+		// Focus, that was initialized as 'active'
+		if( this.tree.focusNode ) {
+			this.tree.logDebug("Focus on init: %o", this.tree.focusNode);
+			this.tree.focusNode.focus();
+		}
+		// Activate node, that was initialized as 'active'
+		if( this.tree.activeNode ) {
+			var dtnode = this.tree.activeNode;
+			this.tree.activeNode = null; // make sure this is not ignored
+			this.tree.logDebug("Activate on init: %o", dtnode);
+			dtnode._userActivate();
+		}
+		this.tree.initMode = "running";
+	},
+
+	bind: function() {
+		var $this = this.element;
+		var o = this.options;
+
+		// Prevent duplicate binding
+		this.unbind();
+		
+		// Tool function to get dtnode from the event target:
+		function __getNodeFromElement(el) {
+			var iMax = 4;
+			do {
+				if( el.dtnode ) return el.dtnode;
+				el = el.parentNode;
+			} while( iMax-- );
+			return null;
+		}
+
+		$this.bind("click.dynatree dblclick.dynatree keypress.dynatree keydown.dynatree", function(event){
+			var dtnode = __getNodeFromElement(event.target);
+			
+			if( !dtnode )
+				return false;
+//			dtnode.tree.logDebug("bind(" + event.type + "): dtnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
+			dtnode.tree.logDebug("bind(%o): dtnode: %o", event, dtnode);
+
+			switch(event.type) {
+			case "click":
+				return ( o.onClick && o.onClick(dtnode, event)===false ) ? false : dtnode.onClick(event);
+			case "dblclick":
+				return ( o.onDblClick && o.onDblClick(dtnode, event)===false ) ? false : dtnode.onDblClick(event);
+			case "keydown":
+				return ( o.onKeydown && o.onKeydown(dtnode, event)===false ) ? false : dtnode.onKeydown(event);
+			case "keypress":
+				return ( o.onKeypress && o.onKeypress(dtnode, event)===false ) ? false : dtnode.onKeypress(event);
+			};
+		});
+		
+		// focus/blur don't bubble, i.e. are not delegated to parent <div> tags,
+		// so we use the addEventListener capturing phase.
+		// See http://www.howtocreate.co.uk/tutorials/javascript/domevents
+		function __focusHandler(event) {
+			// Handles blur and focus.
+			// Fix event for IE:
+			event = arguments[0] = $.event.fix( event || window.event );
+			var dtnode = __getNodeFromElement(event.target);
+			return dtnode ? dtnode.onFocus(event) : false;
+		}
+		var div = this.tree.divTree;
+		if( div.addEventListener ) {
+			div.addEventListener("focus", __focusHandler, true);
+			div.addEventListener("blur", __focusHandler, true);
+		} else {
+			div.onfocusin = div.onfocusout = __focusHandler;
+		}
+		// EVENTS
+		// disable click if event is configured to something else
+//		if (!(/^click/).test(o.event))
+//			this.$tabs.bind("click.tabs", function() { return false; });
+		
+	},
+	
+	unbind: function() {
+		this.element.unbind(".dynatree");
+	},
+	
+	enable: function() {
+		this.bind();
+		// Enable and remove -disabled from css: 
+		this._setData("disabled", false);
+	},
+	
+	disable: function() {
+		this.unbind();
+		// Disable and add -disabled to css: 
+		this._setData("disabled", true);
+	},
+	
+	// --- getter methods (i.e. NOT returning a reference to $)
+	getTree: function() {
+		return this.tree;
+	},
+
+	getRoot: function() {
+		return this.tree.getRoot();
+	},
+
+	getActiveNode: function() {
+		return this.tree.getActiveNode();
+	},
+
+	getSelectedNodes: function() {
+		return this.tree.getSelectedNodes();
+	},
+
+	// ------------------------------------------------------------------------
+	lastentry: undefined
+});
+
+
+// The following methods return a value (thus breaking the jQuery call chain):
+
+$.ui.dynatree.getter = "getTree getRoot getActiveNode getSelectedNodes";
+
+
+// Plugin default options:
+
+$.ui.dynatree.defaults = {
+	title: "Dynatree root", // Name of the root node.
+	rootVisible: false, // Set to true, to make the root node visible.
+ 	minExpandLevel: 1, // 1: root node is not collapsible
+	imagePath: null, // Path to a folder containing icons. Defaults to 'skin/' subdirectory.
+	children: null, // Init tree structure from this object array.
+	initId: null, // Init tree structure from a <ul> element with this ID.
+	initAjax: null, // Ajax options used to initialize the tree strucuture.
+	autoFocus: true, // Set focus to first child, when expanding or lazy-loading.
+	keyboard: true, // Support keyboard navigation.
+    persist: false, // Persist expand-status to a cookie
+	autoCollapse: false, // Automatically collapse all siblings, when a node is expanded.
+	clickFolderMode: 3, // 1:activate, 2:expand, 3:activate and expand
+	activeVisible: true, // Make sure, active nodes are visible (expanded).
+	checkbox: false, // Show checkbox
+	selectMode: 2, // 1:single, 2:multi, 3:multi-hier
+	fx: null, // Animations, e.g. null or { height: "toggle", duration: 200 }
+
+	// Low level event handlers: onEvent(dtnode, event): return false, to stop default processing
+	onClick: null, // null: generate focus, expand, activate, select events.
+	onDblClick: null, // (No default actions.)
+	onKeydown: null, // null: generate keyboard navigation (focus, expand, activate).
+	onKeypress: null, // (No default actions.)
+	onFocus: null, // null: handle focus.
+	onBlur: null, // null: handle unfocus.
+
+	// Pre-event handlers onQueryEvent(flag, dtnode): return false, to stop processing
+	onQueryActivate: null, // Callback(flag, dtnode) before a node is (de)activated.
+	onQuerySelect: null, // Callback(flag, dtnode) before a node is (de)selected.
+	onQueryExpand: null, // Callback(flag, dtnode) before a node is expanded/collpsed.
+	
+	// High level event handlers
+	onActivate: null, // Callback(dtnode) when a node is activated.
+	onDeactivate: null, // Callback(dtnode) when a node is deactivated.
+	onSelect: null, // Callback(flag, dtnode) when a node is (de)selected.
+	onExpand: null, // Callback(dtnode) when a node is expanded/collapsed.
+//	onCollapse: null, // Callback(dtnode) when a node is collapsed.
+	onLazyRead: null, // Callback(dtnode) when a lazy node is expanded for the first time.
+	
+	ajaxDefaults: { // Used by initAjax option
+		cache: false, // false: Append random '_' argument to the request url to prevent caching.
+		dataType: "json" // Expect json format and pass json object to callbacks.
+	},
+	strings: {
+		loading: "Loading&#8230;",
+		loadError: "Load error!"
+	},
+	idPrefix: "ui-dynatree-id-", // Used to generate node id's like <span id="ui-dynatree-id-<key>">.
+    cookieId: "ui-dynatree-cookie", // Choose a more unique name, to allow multiple trees.
+	cookie: {
+		expires: null //7, // Days or Date; null: session cookie
+//		path: "/", // Defaults to current page
+//		domain: "jquery.com",
+//		secure: true
+	},
+    
+	classNames: {
+		container: "ui-dynatree-container",
+		folder: "ui-dynatree-folder",
+		document: "ui-dynatree-document",
+		empty: "ui-dynatree-empty",
+		vline: "ui-dynatree-vline",
+		expander: "ui-dynatree-expander",
+		connector: "ui-dynatree-connector",
+		checkbox: "ui-dynatree-checkbox",
+		nodeIcon: "ui-dynatree-icon",
+		nodeError: "ui-dynatree-statusnode-error",
+		nodeWait: "ui-dynatree-statusnode-wait",
+		hidden: "ui-dynatree-hidden",
+		combinedExpanderPrefix: "ui-dynatree-exp-",
+		combinedIconPrefix: "ui-dynatree-ico-",
+//		disabled: "ui-dynatree-disabled",
+//		hasChildren: "ui-dynatree-has-children",
+		active: "ui-dynatree-active",
+		selected: "ui-dynatree-selected",
+		expanded: "ui-dynatree-expanded",
+		lazy: "ui-dynatree-lazy",
+		focused: "ui-dynatree-focused",
+		partsel: "ui-dynatree-partsel",
+		lastsib: "ui-dynatree-lastsib"
+	},
+	debugLevel: 1,
+
+	// ------------------------------------------------------------------------
+	lastentry: undefined
+};
+
+/**
+ * Reserved data attributes for a tree node.
+ */
+$.ui.dynatree.nodedatadefaults = {
+	title: null, // (required) Displayed name of the node (html is allowed here)
+	key: null, // May be used with select(), find(), ...
+	isFolder: false, // Use a folder icon. Also the node is expandable but not selectable.
+	isLazy: false, // Call onLazyRead(), when the node is expanded for the first time to allow for delayed creation of children.
+	tooltip: null, // Show this popup text.
+	icon: null, // Use a custom image (filename relative to tree.options.imagePath). 'null' for default icon, 'false' for no icon.
+	addClass: null, // Class name added to the node's span tag.  
+	activate: false, // Initial active status.
+	focus: false, // Initial focused status.
+	expand: false, // Initial expanded status.
+	select: false, // Initial selected status.
+//	hideCheckbox: null, // Suppress checkbox for this node.
+//	unselectable: false, // Prevent selection.
+//  disabled: null,	
+	// The following attributes are only valid if passed to some functions:
+	children: null, // Array of child nodes.
+	// NOTE: we can also add custom attributes here.
+	// This may then also be used in the onSelect() or onLazyTree() callbacks.
+	// ------------------------------------------------------------------------
+	lastentry: undefined
+};
+
+
+// ---------------------------------------------------------------------------
+})(jQuery);
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/jquery.dynatree.min.js b/0.8.1-rc1/curator/src/main/webapp/js/src/jquery.dynatree.min.js
new file mode 100644
index 0000000..684eed8
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/jquery.dynatree.min.js
@@ -0,0 +1,161 @@
+// jquery.dynatree.js build 0.4.0

+// Revision: 196, date: 2009-03-12 09:01:35

+// Copyright (c) 2008-09  Martin Wendt (http://dynatree.googlecode.com/)

+// Licensed under the MIT License.

+

+var _canLog=true;function _log(mode,msg){if(!_canLog)

+return;var args=Array.prototype.slice.apply(arguments,[1]);var dt=new Date();var tag=dt.getHours()+":"+dt.getMinutes()+":"+dt.getSeconds()+"."+dt.getMilliseconds();args[0]=tag+" - "+args[0];try{switch(mode){case"info":window.console.info.apply(window.console,args);break;case"warn":window.console.warn.apply(window.console,args);break;default:window.console.log.apply(window.console,args);}}catch(e){if(!window.console)

+_canLog=false;}}

+function logMsg(msg){Array.prototype.unshift.apply(arguments,["debug"]);_log.apply(this,arguments);}

+var DTNodeStatus_Error=-1;var DTNodeStatus_Loading=1;var DTNodeStatus_Ok=0;;(function($){var Class={create:function(){return function(){this.initialize.apply(this,arguments);}}}

+var DynaTreeNode=Class.create();DynaTreeNode.prototype={initialize:function(parent,tree,data){this.parent=parent;this.tree=tree;if(typeof data=="string")

+data={title:data};if(data.key==undefined)

+data.key="_"+tree._nodeCount++;this.data=$.extend({},$.ui.dynatree.nodedatadefaults,data);this.div=null;this.span=null;this.childList=null;this.isRead=false;this.hasSubSel=false;if(tree.initMode=="cookie"){if(tree.initActiveKey==this.data.key)

+tree.activeNode=this;if(tree.initFocusKey==this.data.key)

+tree.focusNode=this;this.bExpanded=($.inArray(this.data.key,tree.initExpandedKeys)>=0);this.bSelected=($.inArray(this.data.key,tree.initSelectedKeys)>=0);}else{if(data.activate)

+tree.activeNode=this;if(data.focus)

+tree.focusNode=this;this.bExpanded=(data.expand==true);this.bSelected=(data.select==true);}

+if(this.bExpanded)

+tree.expandedNodes.push(this);if(this.bSelected)

+tree.selectedNodes.push(this);},toString:function(){return"dtnode<"+this.data.key+">: '"+this.data.title+"'";},toDict:function(recursive,callback){var dict=$.extend({},this.data);dict.activate=(this.tree.activeNode===this);dict.focus=(this.tree.focusNode===this);dict.expand=this.bExpanded;dict.select=this.bSelected;if(callback)

+callback(dict);if(recursive&&this.childList){dict.children=[];for(var i=0;i<this.childList.length;i++)

+dict.children.push(this.childList[i].toDict(true,callback));}else{delete dict.children;}

+return dict;},_getInnerHtml:function(){var opts=this.tree.options;var cache=this.tree.cache;var rootParent=opts.rootVisible?null:this.tree.tnRoot;var bHideFirstExpander=(opts.rootVisible&&opts.minExpandLevel>0)||opts.minExpandLevel>1;var bHideFirstConnector=opts.rootVisible||opts.minExpandLevel>0;var res="";var p=this.parent;while(p){if(bHideFirstConnector&&(p==rootParent))

+break;res=(p.isLastSibling()?cache.tagEmpty:cache.tagVline)+res;p=p.parent;}

+if(bHideFirstExpander&&this.parent==rootParent){}else if(this.childList||this.data.isLazy){res+=cache.tagExpander;}else{res+=cache.tagConnector;}

+if(opts.checkbox&&this.data.hideCheckbox!=true&&!this.data.isStatusNode){res+=cache.tagCheckbox;}

+if(this.data.icon){res+="<img src='"+opts.imagePath+this.data.icon+"' alt='' />";}else if(this.data.icon==false){}else{res+=cache.tagNodeIcon;}

+var tooltip=(this.data&&typeof this.data.tooltip=="string")?" title='"+this.data.tooltip+"'":"";res+="<a href='#'"+tooltip+">"+this.data.title+"</a>";return res;},render:function(bDeep,bHidden){if(!this.div){this.span=document.createElement("span");this.span.dtnode=this;if(this.data.key)

+this.span.id=this.tree.options.idPrefix+this.data.key;this.div=document.createElement("div");this.div.appendChild(this.span);if(this.parent)

+this.parent.div.appendChild(this.div);if(this.parent==null&&!this.tree.options.rootVisible)

+this.span.style.display="none";}

+this.span.innerHTML=this._getInnerHtml();this.div.style.display=(this.parent==null||this.parent.bExpanded?"":"none");var opts=this.tree.options;var cn=opts.classNames;var isLastSib=this.isLastSibling();var cnList=[];cnList.push((this.data.isFolder)?cn.folder:cn.document);if(this.bExpanded)

+cnList.push(cn.expanded);if(this.data.isLazy&&!this.isRead)

+cnList.push(cn.lazy);if(isLastSib)

+cnList.push(cn.lastsib);if(this.bSelected)

+cnList.push(cn.selected);if(this.hasSubSel)

+cnList.push(cn.partsel);if(this.tree.activeNode===this)

+cnList.push(cn.active);if(this.data.addClass)

+cnList.push(this.data.addClass);cnList.push(cn.combinedExpanderPrefix

++(this.bExpanded?"e":"c")

++(this.data.isLazy&&!this.isRead?"d":"")

++(isLastSib?"l":""));cnList.push(cn.combinedIconPrefix

++(this.bExpanded?"e":"c")

++(this.data.isFolder?"f":""));this.span.className=cnList.join(" ");if(bDeep&&this.childList&&(bHidden||this.bExpanded)){for(var i=0;i<this.childList.length;i++){this.childList[i].render(bDeep,bHidden)}}},hasChildren:function(){return this.childList!=null;},isLastSibling:function(){var p=this.parent;if(!p)return true;return p.childList[p.childList.length-1]===this;},prevSibling:function(){if(!this.parent)return null;var ac=this.parent.childList;for(var i=1;i<ac.length;i++)

+if(ac[i]===this)

+return ac[i-1];return null;},nextSibling:function(){if(!this.parent)return null;var ac=this.parent.childList;for(var i=0;i<ac.length-1;i++)

+if(ac[i]===this)

+return ac[i+1];return null;},_setStatusNode:function(data){var firstChild=(this.childList?this.childList[0]:null);if(!data){if(firstChild){this.div.removeChild(firstChild.div);if(this.childList.length==1)

+this.childList=null;else

+this.childList.shift();}}else if(firstChild){data.isStatusNode=true;firstChild.data=data;firstChild.render(false,false);}else{data.isStatusNode=true;firstChild=this._addNode(data);}},setLazyNodeStatus:function(lts){switch(lts){case DTNodeStatus_Ok:this._setStatusNode(null);this.isRead=true;this.render(false,false);if(this.tree.options.autoFocus){if(this===this.tree.tnRoot&&!this.tree.options.rootVisible&&this.childList){this.childList[0].focus();}else{this.focus();}}

+break;case DTNodeStatus_Loading:this._setStatusNode({title:this.tree.options.strings.loading,addClass:this.tree.options.classNames.nodeWait});break;case DTNodeStatus_Error:this._setStatusNode({title:this.tree.options.strings.loadError,addClass:this.tree.options.classNames.nodeError});break;default:throw"Bad LazyNodeStatus: '"+lts+"'.";}},_parentList:function(includeRoot,includeSelf){var l=new Array();var dtn=includeSelf?this:this.parent;while(dtn){if(includeRoot||dtn.parent)

+l.unshift(dtn);dtn=dtn.parent;};return l;},getLevel:function(){var level=0;var dtn=this.parent;while(dtn){level++;dtn=dtn.parent;};return level;},isVisible:function(){var parents=this._parentList(true,false);for(var i=0;i<parents.length;i++)

+if(!parents[i].bExpanded)return false;return true;},makeVisible:function(){var parents=this._parentList(true,false);for(var i=0;i<parents.length;i++)

+parents[i]._expand(true);},focus:function(){this.makeVisible();try{$(this.span).find(">a").focus();}catch(e){}},isActive:function(){return(this.tree.activeNode===this);},activate:function(){var opts=this.tree.options;if(this.data.isStatusNode)

+return;if(opts.onQueryActivate&&opts.onQueryActivate.call(this.span,true,this)==false)

+return;if(this.tree.activeNode){if(this.tree.activeNode===this)

+return;this.tree.activeNode.deactivate();}

+if(opts.activeVisible)

+this.makeVisible();this.tree.activeNode=this;if(opts.persist)

+$.cookie(opts.cookieId+"-active",this.data.key,opts.cookie);$(this.span).addClass(opts.classNames.active);if(opts.onActivate)

+opts.onActivate.call(this.span,this);},deactivate:function(){if(this.tree.activeNode===this){var opts=this.tree.options;if(opts.onQueryActivate&&opts.onQueryActivate.call(this.span,false,this)==false)

+return;$(this.span).removeClass(opts.classNames.active);if(opts.persist)

+$.cookie(opts.cookieId+"-active","",opts.cookie);this.tree.activeNode=null;if(opts.onDeactivate)

+opts.onDeactivate.call(this.span,this);}},_userActivate:function(){var activate=true;var expand=false;if(this.data.isFolder){switch(this.tree.options.clickFolderMode){case 2:activate=false;expand=true;break;case 3:activate=expand=true;break;}}

+if(this.parent==null&&this.tree.options.minExpandLevel>0){expand=false;}

+if(expand){this.toggleExpand();this.focus();}

+if(activate){this.activate();}},_setSubSel:function(hasSubSel){if(hasSubSel){this.hasSubSel=true;$(this.span).addClass(this.tree.options.classNames.partsel);}else{this.hasSubSel=false;$(this.span).removeClass(this.tree.options.classNames.partsel);}},_fixSelectionState:function(){if(this.bSelected){this.visit(function(dtnode){dtnode.parent._setSubSel(true);dtnode._select(true,false,false);});var p=this.parent;while(p){p._setSubSel(true);var allChildsSelected=true;for(var i=0;i<p.childList.length;i++){var n=p.childList[i];if(!n.bSelected&&!n.data.isStatusNode){allChildsSelected=false;break;}}

+if(allChildsSelected)

+p._select(true,false,false);p=p.parent;}}else{this._setSubSel(false);this.visit(function(dtnode){dtnode._setSubSel(false);dtnode._select(false,false,false);});var p=this.parent;while(p){p._select(false,false,false);var isPartSel=false;for(var i=0;i<p.childList.length;i++){if(p.childList[i].bSelected||p.childList[i].hasSubSel){isPartSel=true;break;}}

+p._setSubSel(isPartSel);p=p.parent;}}},_select:function(sel,fireEvents,deep){var opts=this.tree.options;if(this.data.isStatusNode)

+return;if(this.bSelected==sel){return;}

+if(fireEvents&&opts.onQuerySelect&&opts.onQuerySelect.call(this.span,sel,this)==false)

+return;if(opts.selectMode==1&&this.tree.selectedNodes.length&&sel)

+this.tree.selectedNodes[0]._select(false,false,false);this.bSelected=sel;this.tree._changeNodeList("select",this,sel);if(sel){$(this.span).addClass(opts.classNames.selected);if(deep&&opts.selectMode==3)

+this._fixSelectionState();if(fireEvents&&opts.onSelect)

+opts.onSelect.call(this.span,true,this);}else{$(this.span).removeClass(opts.classNames.selected);if(deep&&opts.selectMode==3)

+this._fixSelectionState();if(fireEvents&&opts.onSelect)

+opts.onSelect.call(this.span,false,this);}},isSelected:function(){return this.bSelected;},select:function(sel){return this._select(sel!=false,true,true);},toggleSelect:function(){return this.select(!this.bSelected);},_expand:function(bExpand){if(this.bExpanded==bExpand){return;}

+var opts=this.tree.options;if(!bExpand&&this.getLevel()<opts.minExpandLevel){this.tree.logDebug("dtnode._expand(%o) forced expand - %o",bExpand,this);return;}

+if(opts.onQueryExpand&&opts.onQueryExpand.call(this.span,bExpand,this)==false)

+return;this.bExpanded=bExpand;this.tree._changeNodeList("expand",this,bExpand);this.render(false);if(this.bExpanded&&this.parent&&opts.autoCollapse){var parents=this._parentList(false,true);for(var i=0;i<parents.length;i++)

+parents[i].collapseSiblings();}

+if(!this.bExpanded&&!this.isVisible()){this.tree.logDebug("Focus became invisible: setting to this.");this.focus();}

+if(opts.activeVisible&&this.tree.activeNode&&!this.tree.activeNode.isVisible()){this.tree.activeNode.deactivate();}

+if(bExpand&&this.data.isLazy&&!this.isRead){try{this.tree.logDebug("_expand: start lazy - %o",this);this.setLazyNodeStatus(DTNodeStatus_Loading);if(true==opts.onLazyRead.call(this.span,this)){this.setLazyNodeStatus(DTNodeStatus_Ok);this.tree.logDebug("_expand: lazy succeeded - %o",this);}}catch(e){this.setLazyNodeStatus(DTNodeStatus_Error);}

+return;}

+if(opts.fx){var duration=opts.fx.duration||200;$(">DIV",this.div).animate(opts.fx,duration);}else{var $d=$(">DIV",this.div);$d.toggle();}

+if(opts.onExpand)

+opts.onExpand.call(this.span,bExpand,this);},expand:function(flag){if(!this.childList&&!this.data.isLazy)

+return;if(this.parent==null&&this.tree.options.minExpandLevel>0&&!flag)

+return;this._expand(flag);},toggleExpand:function(){this.expand(!this.bExpanded);},collapseSiblings:function(){if(this.parent==null)

+return;var ac=this.parent.childList;for(var i=0;i<ac.length;i++){if(ac[i]!==this&&ac[i].bExpanded)

+ac[i]._expand(false);}},onClick:function(event){if($(event.target).hasClass(this.tree.options.classNames.expander)){this.toggleExpand();}else if($(event.target).hasClass(this.tree.options.classNames.checkbox)){this.toggleSelect();}else{this._userActivate();this.span.getElementsByTagName("a")[0].focus();}

+return false;},onDblClick:function(event){},onKeydown:function(event){var handled=true;switch(event.which){case 107:case 187:if(!this.bExpanded)this.toggleExpand();break;case 109:case 189:if(this.bExpanded)this.toggleExpand();break;case 32:this._userActivate();break;case 8:if(this.parent)

+this.parent.focus();break;case 37:if(this.bExpanded){this.toggleExpand();this.focus();}else if(this.parent&&(this.tree.options.rootVisible||this.parent.parent)){this.parent.focus();}

+break;case 39:if(!this.bExpanded&&(this.childList||this.data.isLazy)){this.toggleExpand();this.focus();}else if(this.childList){this.childList[0].focus();}

+break;case 38:var sib=this.prevSibling();while(sib&&sib.bExpanded)

+sib=sib.childList[sib.childList.length-1];if(!sib&&this.parent&&(this.tree.options.rootVisible||this.parent.parent))

+sib=this.parent;if(sib)sib.focus();break;case 40:var sib;if(this.bExpanded){sib=this.childList[0];}else{var parents=this._parentList(false,true);for(var i=parents.length-1;i>=0;i--){sib=parents[i].nextSibling();if(sib)break;}}

+if(sib)sib.focus();break;default:handled=false;}

+return!handled;},onKeypress:function(event){},onFocus:function(event){var opts=this.tree.options;if(event.type=="blur"||event.type=="focusout"){if(opts.onBlur)

+opts.onBlur.call(this.span,this);if(this.tree.tnFocused)

+$(this.tree.tnFocused.span).removeClass(opts.classNames.focused);this.tree.tnFocused=null;if(opts.persist)

+$.cookie(opts.cookieId+"-focus",null,opts.cookie);}else if(event.type=="focus"||event.type=="focusin"){if(this.tree.tnFocused&&this.tree.tnFocused!==this){this.tree.logDebug("dtnode.onFocus: out of sync: curFocus: %o",this.tree.tnFocused);$(this.tree.tnFocused.span).removeClass(opts.classNames.focused);}

+this.tree.tnFocused=this;if(opts.onFocus)

+opts.onFocus.call(this.span,this);$(this.tree.tnFocused.span).addClass(opts.classNames.focused);if(opts.persist)

+$.cookie(opts.cookieId+"-focus",this.data.key,opts.cookie);}},_postInit:function(){if(opts.onPostInit)

+opts.onPostInit.call(this.span,this);},visit:function(fn,data,includeSelf){var n=0;if(includeSelf==true){if(fn(this,data)==false)

+return 1;n++;}

+if(this.childList)

+for(var i=0;i<this.childList.length;i++)

+n+=this.childList[i].visit(fn,data,true);return n;},remove:function(){if(this===this.tree.root)

+return false;return this.parent.removeChild(this);},removeChild:function(tn){var ac=this.childList;if(ac.length==1){if(tn!==ac[0])

+throw"removeChild: invalid child";return this.removeChildren();}

+if(tn===this.tree.activeNode)

+tn.deactivate();if(tn.bSelected)

+this.tree._changeNodeList("select",tn,false);if(tn.bExpanded)

+this.tree._changeNodeList("expand",tn,false);tn.removeChildren(true);this.div.removeChild(tn.div);for(var i=0;i<ac.length;i++){if(ac[i]===tn){this.childList.splice(i,1);delete tn;break;}}},removeChildren:function(recursive){var tree=this.tree;var ac=this.childList;if(ac){for(var i=0;i<ac.length;i++){var tn=ac[i];if(tn===tree.activeNode)

+tn.deactivate();if(tn.bSelected)

+this.tree._changeNodeList("select",tn,false);if(tn.bExpanded)

+this.tree._changeNodeList("expand",tn,false);tn.removeChildren(true);this.div.removeChild(tn.div);delete tn;}

+this.childList=null;if(!recursive){this._expand(false);this.isRead=false;this.render(false,false);}}},_addChildNode:function(dtnode){var opts=this.tree.options;if(this.childList==null){this.childList=new Array();}else{$(this.childList[this.childList.length-1].span).removeClass(opts.classNames.lastsib);}

+this.childList.push(dtnode);dtnode.parent=this;if(dtnode.data.expand||opts.minExpandLevel>=dtnode.getLevel())

+this.bExpanded=true;if(!dtnode.data.isStatusNode&&opts.selectMode==3)

+dtnode._fixSelectionState();if(this.tree.bEnableUpdate)

+this.render(true,true);return dtnode;},_addNode:function(data){return this._addChildNode(new DynaTreeNode(this,this.tree,data));},append:function(obj){if(!obj||obj.length==0)

+return;if(!obj.length)

+obj=[obj];var prevFlag=this.tree.enableUpdate(false);var tnFirst=null;for(var i=0;i<obj.length;i++){var data=obj[i];var dtnode=this._addNode(data);if(!tnFirst)tnFirst=dtnode;if(data.children)

+dtnode.append(data.children);}

+this.tree.enableUpdate(prevFlag);return tnFirst;},appendAjax:function(ajaxOptions){this.setLazyNodeStatus(DTNodeStatus_Loading);var self=this;var ajaxOptions=$.extend({},this.tree.options.ajaxDefaults,ajaxOptions,{success:function(data,textStatus){self.append(data);self.setLazyNodeStatus(DTNodeStatus_Ok);},error:function(XMLHttpRequest,textStatus,errorThrown){self.setLazyNodeStatus(DTNodeStatus_Error);}});$.ajax(ajaxOptions);},lastentry:undefined}

+var DynaTree=Class.create();DynaTree.version="$Version: 0.4.0$";DynaTree.prototype={initialize:function(divContainer,options){this.options=options;this.bEnableUpdate=true;this._nodeCount=0;this.initMode="data";this.activeNode=null;this.selectedNodes=new Array();this.expandedNodes=new Array();if(this.options.persist){this.initActiveKey=$.cookie(this.options.cookieId+"-active");if(cookie||this.initActiveKey!=null)

+this.initMode="cookie";this.initFocusKey=$.cookie(this.options.cookieId+"-focus");var cookie=$.cookie(this.options.cookieId+"-expand");if(cookie!=null)

+this.initMode="cookie";this.initExpandedKeys=cookie?cookie.split(","):[];cookie=$.cookie(this.options.cookieId+"-select");this.initSelectedKeys=cookie?cookie.split(","):[];}

+this.logDebug("initMode: %o, active: %o, expanded: %o, selected: %o",this.initMode,this.initActiveKey,this.initExpandedKeys,this.initSelectedKeys);this.cache={tagEmpty:"<span class='"+options.classNames.empty+"'></span>",tagVline:"<span class='"+options.classNames.vline+"'></span>",tagExpander:"<span class='"+options.classNames.expander+"'></span>",tagConnector:"<span class='"+options.classNames.connector+"'></span>",tagNodeIcon:"<span class='"+options.classNames.nodeIcon+"'></span>",tagCheckbox:"<span class='"+options.classNames.checkbox+"'></span>",lastentry:undefined};this.divTree=divContainer;this.tnRoot=new DynaTreeNode(null,this,{title:this.options.title,key:"root"});this.tnRoot.data.isFolder=true;this.tnRoot.render(false,false);this.divRoot=this.tnRoot.div;this.divRoot.className=this.options.classNames.container;this.divTree.appendChild(this.divRoot);},toString:function(){return"DynaTree '"+this.options.title+"'";},toDict:function(){return this.tnRoot.toDict(true);},logDebug:function(msg){if(this.options.debugLevel>=2){Array.prototype.unshift.apply(arguments,["debug"]);_log.apply(this,arguments);}},logInfo:function(msg){if(this.options.debugLevel>=1){Array.prototype.unshift.apply(arguments,["info"]);_log.apply(this,arguments);}},logWarning:function(msg){Array.prototype.unshift.apply(arguments,["warn"]);_log.apply(this,arguments);},isInitializing:function(){return(this.initMode=="data"||this.initMode=="cookie"||this.initMode=="postInit");},_changeNodeList:function(mode,node,bAdd){if(!node)

+return false;var cookieName=this.options.cookieId+"-"+mode;var nodeList=(mode=="expand")?this.expandedNodes:this.selectedNodes;var idx=$.inArray(node,nodeList);if(bAdd){if(idx>=0)

+return false;nodeList.push(node);}else{if(idx<0)

+return false;nodeList.splice(idx,1);}

+if(this.options.persist){var keyList=$.map(nodeList,function(e,i){return e.data.key});$.cookie(cookieName,keyList.join(","),this.options.cookie);}else{}},redraw:function(){this.logDebug("dynatree.redraw()...");this.tnRoot.render(true,true);this.logDebug("dynatree.redraw() done.");},getRoot:function(){return this.tnRoot;},getNodeByKey:function(key){var el=document.getElementById(this.options.idPrefix+key);return(el&&el.dtnode)?el.dtnode:null;},getActiveNode:function(){return this.activeNode;},getSelectedNodes:function(stopOnParents){if(stopOnParents==true){var nodeList=[];this.tnRoot.visit(function(dtnode){if(dtnode.bSelected){nodeList.push(dtnode);return false;}});return nodeList;}else{return this.selectedNodes;}},activateKey:function(key){var dtnode=this.getNodeByKey(key);if(!dtnode){this.activeNode=null;return null;}

+dtnode.focus();dtnode.activate();return dtnode;},selectKey:function(key,select){var dtnode=this.getNodeByKey(key);if(!dtnode)

+return null;dtnode.select(select);return dtnode;},enableUpdate:function(bEnable){if(this.bEnableUpdate==bEnable)

+return bEnable;this.bEnableUpdate=bEnable;if(bEnable)

+this.redraw();return!bEnable;},visit:function(fn,data,includeRoot){return this.tnRoot.visit(fn,data,includeRoot);},_createFromTag:function(parentTreeNode,$ulParent){var self=this;$ulParent.find(">li").each(function(){var $li=$(this);var $liSpan=$li.find(">span:first");var title;if($liSpan.length){title=$liSpan.html();}else{title=$li.html();var iPos=title.search(/<ul/i);if(iPos>=0)

+title=$.trim(title.substring(0,iPos));else

+title=$.trim(title);}

+var data={title:title,isFolder:$li.hasClass("folder"),isLazy:$li.hasClass("lazy"),expand:$li.hasClass("expanded"),select:$li.hasClass("selected"),activate:$li.hasClass("active"),focus:$li.hasClass("focused")};if($li.attr("title"))

+data.tooltip=$li.attr("title");if($li.attr("id"))

+data.key=$li.attr("id");if($li.attr("data")){var dataAttr=$.trim($li.attr("data"));if(dataAttr){if(dataAttr.charAt(0)!="{")

+dataAttr="{"+dataAttr+"}"

+try{$.extend(data,eval("("+dataAttr+")"));}catch(e){throw("Error parsing node data: "+e+"\ndata:\n'"+dataAttr+"'");}}}

+childNode=parentTreeNode._addNode(data);var $ul=$li.find(">ul:first");if($ul.length){self._createFromTag(childNode,$ul);}});},lastentry:undefined};$.widget("ui.dynatree",{init:function(){return this._init();},_init:function(){logMsg("Dynatree._init(): version='%s', debugLevel=%o.",DynaTree.version,this.options.debugLevel);this.options.event+=".dynatree";var $this=this.element;var opts=this.options;if(!opts.imagePath){$("script").each(function(){if(this.src.search(/.*dynatree[^/]*\.js$/i)>=0){if(this.src.indexOf("/")>=0)

+opts.imagePath=this.src.slice(0,this.src.lastIndexOf("/"))+"/skin/";else

+opts.imagePath="skin/";logMsg("Guessing imagePath from '%s': '%s'",this.src,opts.imagePath);return false;}});}

+var divContainer=$this.get(0);if(opts.children||(opts.initAjax&&opts.initAjax.url)||opts.initId)

+$(divContainer).empty();this.tree=new DynaTree(divContainer,opts);var root=this.tree.getRoot();var prevFlag=this.tree.enableUpdate(false);this.tree.logDebug("Start init tree structure...");if(opts.children){root.append(opts.children);}else if(opts.initAjax&&opts.initAjax.url){root.appendAjax(opts.initAjax);}else if(opts.initId){this.tree._createFromTag(root,$("#"+opts.initId));}else{var $ul=$this.find(">ul").hide();this.tree._createFromTag(root,$ul);$ul.remove();}

+this.tree.enableUpdate(prevFlag);this.tree.logDebug("Init tree structure... done.");this.bind();this.tree.initMode="postInit";nodeList=this.tree.selectedNodes.slice();this.tree.selectedNodes=[];for(var i=0;i<nodeList.length;i++){var dtnode=nodeList[i];this.tree.logDebug("Re-select on init: %o",dtnode);dtnode.bSelected=false;dtnode.select(true);}

+if(this.tree.focusNode){this.tree.logDebug("Focus on init: %o",this.tree.focusNode);this.tree.focusNode.focus();}

+if(this.tree.activeNode){var dtnode=this.tree.activeNode;this.tree.activeNode=null;this.tree.logDebug("Activate on init: %o",dtnode);dtnode._userActivate();}

+this.tree.initMode="running";},bind:function(){var $this=this.element;var o=this.options;this.unbind();function __getNodeFromElement(el){var iMax=4;do{if(el.dtnode)return el.dtnode;el=el.parentNode;}while(iMax--);return null;}

+$this.bind("click.dynatree dblclick.dynatree keypress.dynatree keydown.dynatree",function(event){var dtnode=__getNodeFromElement(event.target);if(!dtnode)

+return false;dtnode.tree.logDebug("bind(%o): dtnode: %o",event,dtnode);switch(event.type){case"click":return(o.onClick&&o.onClick(dtnode,event)===false)?false:dtnode.onClick(event);case"dblclick":return(o.onDblClick&&o.onDblClick(dtnode,event)===false)?false:dtnode.onDblClick(event);case"keydown":return(o.onKeydown&&o.onKeydown(dtnode,event)===false)?false:dtnode.onKeydown(event);case"keypress":return(o.onKeypress&&o.onKeypress(dtnode,event)===false)?false:dtnode.onKeypress(event);};});function __focusHandler(event){event=arguments[0]=$.event.fix(event||window.event);var dtnode=__getNodeFromElement(event.target);return dtnode?dtnode.onFocus(event):false;}

+var div=this.tree.divTree;if(div.addEventListener){div.addEventListener("focus",__focusHandler,true);div.addEventListener("blur",__focusHandler,true);}else{div.onfocusin=div.onfocusout=__focusHandler;}},unbind:function(){this.element.unbind(".dynatree");},enable:function(){this.bind();this._setData("disabled",false);},disable:function(){this.unbind();this._setData("disabled",true);},getTree:function(){return this.tree;},getRoot:function(){return this.tree.getRoot();},getActiveNode:function(){return this.tree.getActiveNode();},getSelectedNodes:function(){return this.tree.getSelectedNodes();},lastentry:undefined});$.ui.dynatree.getter="getTree getRoot getActiveNode getSelectedNodes";$.ui.dynatree.defaults={title:"Dynatree root",rootVisible:false,minExpandLevel:1,imagePath:null,children:null,initId:null,initAjax:null,autoFocus:true,keyboard:true,persist:false,autoCollapse:false,clickFolderMode:3,activeVisible:true,checkbox:false,selectMode:2,fx:null,onClick:null,onDblClick:null,onKeydown:null,onKeypress:null,onFocus:null,onBlur:null,onQueryActivate:null,onQuerySelect:null,onQueryExpand:null,onActivate:null,onDeactivate:null,onSelect:null,onExpand:null,onLazyRead:null,ajaxDefaults:{cache:false,dataType:"json"},strings:{loading:"Loading&#8230;",loadError:"Load error!"},idPrefix:"ui-dynatree-id-",cookieId:"ui-dynatree-cookie",cookie:{expires:null},classNames:{container:"ui-dynatree-container",folder:"ui-dynatree-folder",document:"ui-dynatree-document",empty:"ui-dynatree-empty",vline:"ui-dynatree-vline",expander:"ui-dynatree-expander",connector:"ui-dynatree-connector",checkbox:"ui-dynatree-checkbox",nodeIcon:"ui-dynatree-icon",nodeError:"ui-dynatree-statusnode-error",nodeWait:"ui-dynatree-statusnode-wait",hidden:"ui-dynatree-hidden",combinedExpanderPrefix:"ui-dynatree-exp-",combinedIconPrefix:"ui-dynatree-ico-",active:"ui-dynatree-active",selected:"ui-dynatree-selected",expanded:"ui-dynatree-expanded",lazy:"ui-dynatree-lazy",focused:"ui-dynatree-focused",partsel:"ui-dynatree-partsel",lastsib:"ui-dynatree-lastsib"},debugLevel:1,lastentry:undefined};$.ui.dynatree.nodedatadefaults={title:null,key:null,isFolder:false,isLazy:false,tooltip:null,icon:null,addClass:null,activate:false,focus:false,expand:false,select:false,children:null,lastentry:undefined};})(jQuery);
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbChecked.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbChecked.gif
new file mode 100644
index 0000000..26859f0
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbChecked.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbChecked_hover.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbChecked_hover.gif
new file mode 100644
index 0000000..7f8347f
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbChecked_hover.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbIntermediate.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbIntermediate.gif
new file mode 100644
index 0000000..88a67d5
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbIntermediate.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbIntermediate_hover.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbIntermediate_hover.gif
new file mode 100644
index 0000000..70f8b7a
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbIntermediate_hover.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbUnchecked.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbUnchecked.gif
new file mode 100644
index 0000000..d1eae0d
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbUnchecked.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbUnchecked_hover.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbUnchecked_hover.gif
new file mode 100644
index 0000000..849b820
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/cbUnchecked_hover.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/customDoc1.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/customDoc1.gif
new file mode 100644
index 0000000..d2dc581
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/customDoc1.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/customFolder1.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/customFolder1.gif
new file mode 100644
index 0000000..9033eec
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/customFolder1.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltD_ne.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltD_ne.gif
new file mode 100644
index 0000000..768a6ac
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltD_ne.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltD_nes.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltD_nes.gif
new file mode 100644
index 0000000..f53bca1
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltD_nes.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltDoc.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltDoc.gif
new file mode 100644
index 0000000..2835a53
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltDoc.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltError.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltError.gif
new file mode 100644
index 0000000..fe6b571
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltError.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltFld.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltFld.gif
new file mode 100644
index 0000000..2cdadfa
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltFld.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltFld_o.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltFld_o.gif
new file mode 100644
index 0000000..6d226ec
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltFld_o.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltL_.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltL_.gif
new file mode 100644
index 0000000..2dbfaa4
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltL_.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltL_ne.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltL_ne.gif
new file mode 100644
index 0000000..bd8854d
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltL_ne.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltL_nes.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltL_nes.gif
new file mode 100644
index 0000000..f53ab7b
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltL_nes.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltL_ns.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltL_ns.gif
new file mode 100644
index 0000000..9535fa8
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltL_ns.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltM_ne.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltM_ne.gif
new file mode 100644
index 0000000..61c7a22
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltM_ne.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltM_nes.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltM_nes.gif
new file mode 100644
index 0000000..231f119
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltM_nes.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltP_ne.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltP_ne.gif
new file mode 100644
index 0000000..da150e3
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltP_ne.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltP_nes.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltP_nes.gif
new file mode 100644
index 0000000..a72cbd8
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltP_nes.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltWait.gif b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltWait.gif
new file mode 100644
index 0000000..757393e
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ltWait.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ui.dynatree.css b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ui.dynatree.css
new file mode 100644
index 0000000..d922e9e
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/js/src/skin/ui.dynatree.css
@@ -0,0 +1,266 @@
+/*

+  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.

+*/

+

+

+/******************************************************************************* 

+ * Tree container

+ */

+div.ui-dynatree-container

+{

+	font-family: tahoma, arial, helvetica;

+	font-size: 10pt; /* font size should not be too big */

+	white-space: nowrap; 

+	padding: 3px;

+	

+	background-color: white; 

+	border: 1px dotted gray;

+}

+

+/* Style, when control is disabled */

+.ui-dynatree-disabled div.ui-dynatree-container

+{

+	opacity: 0.5;

+/*	filter: alpha(opacity=50); /* Yields a css warning */

+	background-color: silver; 

+}

+

+

+/******************************************************************************* 

+ * Vertical line image

+ */

+div.ui-dynatree-container img

+{

+	width: 16px;

+	height: 16px;

+	margin-left: 3px;

+	vertical-align: top;

+	border-style: none;

+}

+

+/******************************************************************************* 

+ * Common icon definitions

+ */

+span.ui-dynatree-empty,

+span.ui-dynatree-vline,

+span.ui-dynatree-connector,

+span.ui-dynatree-expander,

+span.ui-dynatree-icon,

+span.ui-dynatree-checkbox

+{

+	width: 16px;

+	height: 16px;

+	display: -moz-inline-box; /* @ FF 1+2 */

+	display: inline-block; /* Required to make a span sizeable */

+	vertical-align: top;

+	background-repeat: no-repeat;

+	background-position: left;

+}

+

+/******************************************************************************* 

+ * Lines and connectors

+ */

+span.ui-dynatree-empty

+{

+}

+span.ui-dynatree-vline

+{

+	background-image: url("ltL_ns.gif");

+}

+span.ui-dynatree-connector

+{

+	background-image: url("ltL_nes.gif");

+}

+.ui-dynatree-lastsib span.ui-dynatree-connector

+{

+	background-image: url("ltL_ne.gif");

+}

+

+/******************************************************************************* 

+ * Expander icon

+ * Note: IE6 doesn't correctly evaluate multiples class names,

+ *		 so we create combined class names that can be used in the CSS.

+ *

+ * Prefix: ui-dynatree-exp-

+ * 1st character: 'e': expanded, 'c': collapsed

+ * 2nd character (optional): 'd': lazy (Delayed)

+ * 3rd character (optional): 'l': Last sibling       

+ */

+ 

+span.ui-dynatree-expander

+{

+	background-image: url("ltP_nes.gif");

+	cursor: pointer;

+}

+.ui-dynatree-exp-cl span.ui-dynatree-expander /* Collapsed, not delayed, last sibling */

+{

+	background-image: url("ltP_ne.gif");

+}

+.ui-dynatree-exp-cd span.ui-dynatree-expander /* Collapsed, delayed, not last sibling */

+{

+	background-image: url("ltD_nes.gif");

+}

+.ui-dynatree-exp-cdl span.ui-dynatree-expander /* Collapsed, delayed, last sibling */

+{

+	background-image: url("ltD_ne.gif");

+}

+.ui-dynatree-exp-e span.ui-dynatree-expander,  /* Expanded, not delayed, not last sibling */

+.ui-dynatree-exp-ed span.ui-dynatree-expander  /* Expanded, delayed, not last sibling */

+{

+	background-image: url("ltM_nes.gif");

+}

+.ui-dynatree-exp-el span.ui-dynatree-expander,  /* Expanded, not delayed, last sibling */

+.ui-dynatree-exp-edl span.ui-dynatree-expander  /* Expanded, delayed, last sibling */

+{

+	background-image: url("ltM_ne.gif");

+}

+

+

+/******************************************************************************* 

+ * Checkbox icon

+ */

+span.ui-dynatree-checkbox

+{

+	margin-left: 3px;

+	background-image: url("cbUnchecked.gif");

+}

+span.ui-dynatree-checkbox:hover

+{

+	background-image: url("cbUnchecked_hover.gif");

+}

+

+.ui-dynatree-partsel span.ui-dynatree-checkbox

+{

+	background-image: url("cbIntermediate.gif");

+}

+.ui-dynatree-partsel span.ui-dynatree-checkbox:hover

+{

+	background-image: url("cbIntermediate_hover.gif");

+}

+

+.ui-dynatree-selected span.ui-dynatree-checkbox

+{

+	background-image: url("cbChecked.gif");

+}

+.ui-dynatree-selected span.ui-dynatree-checkbox:hover

+{

+	background-image: url("cbChecked_hover.gif");

+}

+

+/******************************************************************************* 

+ * Node type icon

+ * Note: IE6 doesn't correctly evaluate multiples class names,

+ *		 so we create combined class names that can be used in the CSS.

+ *

+ * Prefix: ui-dynatree-ico-

+ * 1st character: 'e': expanded, 'c': collapsed

+ * 2nd character (optional): 'f': folder

+ */

+ 

+span.ui-dynatree-icon /* Default icon */

+{

+	margin-left: 3px;

+	background-image: url("ltDoc.gif");

+}

+

+.ui-dynatree-ico-cf span.ui-dynatree-icon  /* Collapsed Folder */

+{

+	background-image: url("ltFld.gif");

+}

+

+.ui-dynatree-ico-ef span.ui-dynatree-icon  /* Expanded Folder */

+{

+	background-image: url("ltFld_o.gif");

+}

+

+/* Status node icons */

+

+.ui-dynatree-statusnode-wait span.ui-dynatree-icon

+{

+	background-image: url("ltWait.gif");

+}

+

+.ui-dynatree-statusnode-error span.ui-dynatree-icon

+{

+	background-image: url("ltError.gif");

+}

+

+/******************************************************************************* 

+ * Node titles

+ */

+

+/* Remove blue color and underline from title links */

+div.ui-dynatree-container a 

+{

+	color: black; /* inherit doesn't work on IE */

+	text-decoration: none;

+	vertical-align: top;

+	margin: 0px;

+	margin-left: 3px;

+/*	outline: 0; /* @ Firefox, prevent dotted border after click */

+}

+

+div.ui-dynatree-container a:hover

+{

+	text-decoration: underline;

+}

+

+span.ui-dynatree-document a,

+span.ui-dynatree-folder a

+{

+	display: inline-block; /* Better alignment, when title contains <br> */  

+/*	vertical-align: top;*/

+	padding-left: 3px;

+	padding-right: 3px; /* Otherwise italic font will be outside bounds */

+	/*	line-height: 16px; /* should be the same as img height, in case 16 px */

+}

+span.ui-dynatree-folder a

+{

+	font-weight: bold;

+}

+

+div.ui-dynatree-container a:focus,

+span.ui-dynatree-focused a:link  /* @IE */

+{

+	background-color: #EFEBDE; /* gray */

+}

+

+

+span.ui-dynatree-expanded a

+{

+}

+

+span.ui-dynatree-selected a 

+{

+	color: green; 

+	font-style: italic;

+}

+

+span.ui-dynatree-active a

+{

+	background-color: #3169C6 !important;

+	color: white !important; /* @ IE6 */

+}

+

+/******************************************************************************* 

+ * Custom node classes (sample)

+ */

+

+span.custom1 a

+{

+	background-color: maroon;

+	color: yellow;

+}

diff --git a/0.8.1-rc1/curator/src/main/webapp/login.jsp b/0.8.1-rc1/curator/src/main/webapp/login.jsp
new file mode 100644
index 0000000..b9dc3e2
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/login.jsp
@@ -0,0 +1,69 @@
+<%
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+%>
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+    pageEncoding="ISO-8859-1"
+%>
+
+
+<%@page import="org.apache.oodt.cas.curation.servlet.CuratorConfMetKeys"%>
+<jsp:include page="views/common/cas-curator-header.jsp" />
+
+<% String projectName =  application.getInitParameter(CuratorConfMetKeys.PROJECT_DISPLAY_NAME);%>  
+<h1 class="sectionTitle" style="width: auto; font-size: 22px; font-weight: bold; margin-top: 24px; text-align: center;">Please Log In to the <%=(projectName != null ? projectName+"-":"") %>CAS Curation Interface</h1>
+<p>&nbsp;</p>
+
+<form id="login-form" method="post" action="sso_login.jsp" name="login_form">
+ <input name="from" value="<%=request.getParameter("from")%>" type="hidden">
+ <center>
+  <%
+   if(request.getParameter("loginFail") != null){
+  %>
+   	<div class="error" style="margin:0px;margin-bottom:5px;width:230px;font-size:90%">Invalid Credentials...<br/>Please try again.</div>
+  <%
+   }
+ 
+   if(request.getParameter("loginConnectFail") != null){
+   %>
+ 	<div class="error" style="margin:0px;margin-bottom:5px;width:230px;font-size:90%">Unable to contact LDAP authentication server...<br/>Please try again later.</div>
+   <% 
+   }
+   %>
+  <table>
+   <tbody><tr>
+     <td>Username</td>
+     <td><input id="login-username" name="username" value="" size="20" maxlength="255" type="text"></td>
+   </tr>
+   <tr>
+     <td>Password</td>
+     <td><input name="password" value="" size="20" maxlength="255" type="password"></td>
+   </tr>
+   <tr>
+     <td>&nbsp;</td>
+     <td><input name="login_submit" value="Log In" type="submit"></td>
+   </tr>
+ </tbody></table>
+ </center>
+</form>
+
+
+
+<div style=""></div>
+<script type="text/javascript">
+	document.getElementById('login-username').focus();
+</script>
+
+<jsp:include page="views/common/cas-curator-footer.jsp" />
diff --git a/0.8.1-rc1/curator/src/main/webapp/logout.jsp b/0.8.1-rc1/curator/src/main/webapp/logout.jsp
new file mode 100644
index 0000000..c14555d
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/logout.jsp
@@ -0,0 +1,25 @@
+<%@page import="org.apache.oodt.cas.curation.util.SSOUtils"%>
+<%@page import="org.apache.oodt.security.sso.SingleSignOn"%>
+<%
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+// use new single sign on API
+SingleSignOn auth = SSOUtils.getWebSingleSignOn(application, request,response);
+
+String refererUrl = request.getParameter("from");
+auth.logout();
+response.sendRedirect(refererUrl);
+%>
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/curation.png b/0.8.1-rc1/curator/src/main/webapp/media/img/curation.png
new file mode 100644
index 0000000..be83f28
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/curation.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/application.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/application.png
new file mode 100644
index 0000000..707c2c5
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/application.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/code.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/code.png
new file mode 100644
index 0000000..607cb3f
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/code.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/css.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/css.png
new file mode 100644
index 0000000..e537f61
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/css.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/db.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/db.png
new file mode 100644
index 0000000..64bad04
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/db.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/directory.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/directory.png
new file mode 100644
index 0000000..cf31d63
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/directory.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/doc.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/doc.png
new file mode 100644
index 0000000..f2b1701
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/doc.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/file.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/file.png
new file mode 100644
index 0000000..e107523
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/file.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/film.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/film.png
new file mode 100644
index 0000000..8db51be
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/film.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/flash.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/flash.png
new file mode 100644
index 0000000..65f0b72
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/flash.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/folder_open.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/folder_open.png
new file mode 100644
index 0000000..5460345
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/folder_open.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/html.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/html.png
new file mode 100644
index 0000000..551aa3b
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/html.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/java.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/java.png
new file mode 100644
index 0000000..ac7b62e
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/java.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/linux.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/linux.png
new file mode 100644
index 0000000..971bfea
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/linux.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/music.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/music.png
new file mode 100644
index 0000000..fa429b2
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/music.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/pdf.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/pdf.png
new file mode 100644
index 0000000..216344d
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/pdf.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/php.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/php.png
new file mode 100644
index 0000000..f73cee1
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/php.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/picture.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/picture.png
new file mode 100644
index 0000000..077082a
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/picture.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/ppt.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/ppt.png
new file mode 100644
index 0000000..7383a26
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/ppt.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/psd.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/psd.png
new file mode 100644
index 0000000..30efb2a
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/psd.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/ruby.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/ruby.png
new file mode 100644
index 0000000..4030738
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/ruby.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/script.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/script.png
new file mode 100644
index 0000000..89ef1ed
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/script.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/spinner.gif b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/spinner.gif
new file mode 100644
index 0000000..8c00687
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/spinner.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/txt.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/txt.png
new file mode 100644
index 0000000..b98d22c
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/txt.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/xls.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/xls.png
new file mode 100644
index 0000000..43f1cc6
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/xls.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/zip.png b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/zip.png
new file mode 100644
index 0000000..03e91aa
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/fileTree/zip.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/green_dot.png b/0.8.1-rc1/curator/src/main/webapp/media/img/green_dot.png
new file mode 100644
index 0000000..ff1b656
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/green_dot.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/help.gif b/0.8.1-rc1/curator/src/main/webapp/media/img/help.gif
new file mode 100644
index 0000000..f8dd635
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/help.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/icon-new-dataset.png b/0.8.1-rc1/curator/src/main/webapp/media/img/icon-new-dataset.png
new file mode 100644
index 0000000..7b35cf7
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/icon-new-dataset.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/icon-new-dataset_smaller.png b/0.8.1-rc1/curator/src/main/webapp/media/img/icon-new-dataset_smaller.png
new file mode 100644
index 0000000..13f7c9f
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/icon-new-dataset_smaller.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/icon-new-product.png b/0.8.1-rc1/curator/src/main/webapp/media/img/icon-new-product.png
new file mode 100644
index 0000000..46663b1
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/icon-new-product.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/icon-new-product_smaller.png b/0.8.1-rc1/curator/src/main/webapp/media/img/icon-new-product_smaller.png
new file mode 100644
index 0000000..8fcd5c5
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/icon-new-product_smaller.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/icons/pencil.png b/0.8.1-rc1/curator/src/main/webapp/media/img/icons/pencil.png
new file mode 100755
index 0000000..9a1ce95
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/icons/pencil.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/important.gif b/0.8.1-rc1/curator/src/main/webapp/media/img/important.gif
new file mode 100644
index 0000000..f69ea9e
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/important.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/info.gif b/0.8.1-rc1/curator/src/main/webapp/media/img/info.gif
new file mode 100644
index 0000000..ccb992c
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/info.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/ingestion.png b/0.8.1-rc1/curator/src/main/webapp/media/img/ingestion.png
new file mode 100644
index 0000000..3e12cb9
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/ingestion.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/red_dot.png b/0.8.1-rc1/curator/src/main/webapp/media/img/red_dot.png
new file mode 100644
index 0000000..70c24ab
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/red_dot.png
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/img/title.gif b/0.8.1-rc1/curator/src/main/webapp/media/img/title.gif
new file mode 100644
index 0000000..b578ea6
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/img/title.gif
Binary files differ
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/skin/editing.css b/0.8.1-rc1/curator/src/main/webapp/media/skin/editing.css
new file mode 100644
index 0000000..d67d6d3
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/skin/editing.css
@@ -0,0 +1,41 @@
+/*
+  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.
+*/
+
+@CHARSET "UTF-8";
+
+div.editor table tr td {
+	
+	position:relative;
+	padding-left:5px;
+	cursor:pointer;
+	_cursor:hand;
+	
+}
+
+div.editor table tr td img.pencil {
+	
+	position:relative;
+	left:0px;
+	cursor:pointer;
+	_cursor:hand;
+	
+}
+
+
+.ptwbMetadataList table {
+	border-top:solid 1px #ccc;
+}
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/skin/fileTree.css b/0.8.1-rc1/curator/src/main/webapp/media/skin/fileTree.css
new file mode 100644
index 0000000..97a4ec1
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/skin/fileTree.css
@@ -0,0 +1,115 @@
+/*
+  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.
+*/
+
+
+UL.fileTree {
+	font-family: Verdana, sans-serif;
+	font-size: 11px;
+	line-height: 18px;
+	padding: 0px;
+	margin: 0px;
+}
+
+LI.helper {
+	font-family: Verdana, sans-serif;
+	font-size:11px;
+	line-height:18px;
+}
+
+UL.fileTree LI, LI.helper {
+	list-style: none;
+	padding: 0px;
+	padding-left: 20px;
+	margin: 0px;
+	white-space: nowrap;
+}
+
+UL.fileTree A, LI.helper A {
+	color: #333;
+	text-decoration: none;
+	display: block;
+	padding: 0px 2px;
+}
+
+UL.fileTree A:hover, LI.helper A {
+	background: #BDF;
+}
+
+/* Core Styles */
+.fileTree LI.directory, LI.helper.directory { background: url(../img/fileTree/directory.png) left top no-repeat; }
+.fileTree LI.expanded, LI.helper.expanded   { background: url(../img/fileTree/folder_open.png) left top no-repeat; }
+.fileTree LI.file, LI.helper.file           { background: url(../img/fileTree/file.png) left top no-repeat; }
+.fileTree LI.wait, LI.helper.wait           { background: url(../img/fileTree/spinner.gif) left top no-repeat; }
+/* File Extensions*/
+.fileTree LI.ext_3gp, LI.helper.ext_3gp { background: url(../img/fileTree/film.png) left top no-repeat; }
+.fileTree LI.ext_afp, LI.helper.ext_afp { background: url(../img/fileTree/code.png) left top no-repeat; }
+.fileTree LI.ext_afpa, LI.helper.ext_afpa { background: url(../img/fileTree/code.png) left top no-repeat; }
+.fileTree LI.ext_asp, LI.helper.ext_asp { background: url(../img/fileTree/code.png) left top no-repeat; }
+.fileTree LI.ext_aspx, LI.helper.ext_aspx { background: url(../img/fileTree/code.png) left top no-repeat; }
+.fileTree LI.ext_avi, LI.helper.ext_avi { background: url(../img/fileTree/film.png) left top no-repeat; }
+.fileTree LI.ext_bat, LI.helper.ext_bat { background: url(../img/fileTree/application.png) left top no-repeat; }
+.fileTree LI.ext_bmp, LI.helper.ext_bmp { background: url(../img/fileTree/picture.png) left top no-repeat; }
+.fileTree LI.ext_c, LI.helper.ext_c { background: url(../img/fileTree/code.png) left top no-repeat; }
+.fileTree LI.ext_cfm, LI.helper.ext_cfm { background: url(../img/fileTree/code.png) left top no-repeat; }
+.fileTree LI.ext_cgi, LI.helper.ext_cgi { background: url(../img/fileTree/code.png) left top no-repeat; }
+.fileTree LI.ext_com, LI.helper.ext_com { background: url(../img/fileTree/application.png) left top no-repeat; }
+.fileTree LI.ext_cpp, LI.helper.ext_cpp { background: url(../img/fileTree/code.png) left top no-repeat; }
+.fileTree LI.ext_css, LI.helper.ext_css { background: url(../img/fileTree/css.png) left top no-repeat; }
+.fileTree LI.ext_doc, LI.helper.ext_doc { background: url(../img/fileTree/doc.png) left top no-repeat; }
+.fileTree LI.ext_exe, LI.helper.ext_exe { background: url(../img/fileTree/application.png) left top no-repeat; }
+.fileTree LI.ext_gif, LI.helper.ext_gif { background: url(../img/fileTree/picture.png) left top no-repeat; }
+.fileTree LI.ext_fla, LI.helper.ext_fla { background: url(../img/fileTree/flash.png) left top no-repeat; }
+.fileTree LI.ext_h, LI.helper.ext_h { background: url(../img/fileTree/code.png) left top no-repeat; }
+.fileTree LI.ext_htm, LI.helper.ext_htm { background: url(../img/fileTree/html.png) left top no-repeat; }
+.fileTree LI.ext_html, LI.helper.ext_html { background: url(../img/fileTree/html.png) left top no-repeat; }
+.fileTree LI.ext_jar, LI.helper.ext_jar { background: url(../img/fileTree/java.png) left top no-repeat; }
+.fileTree LI.ext_jpg, LI.helper.ext_jpg { background: url(../img/fileTree/picture.png) left top no-repeat; }
+.fileTree LI.ext_jpeg, LI.helper.ext_jpeg { background: url(../img/fileTree/picture.png) left top no-repeat; }
+.fileTree LI.ext_js, LI.helper.ext_js { background: url(../img/fileTree/script.png) left top no-repeat; }
+.fileTree LI.ext_lasso, LI.helper.ext_lasso { background: url(../img/fileTree/code.png) left top no-repeat; }
+.fileTree LI.ext_log, LI.helper.ext_log { background: url(../img/fileTree/txt.png) left top no-repeat; }
+.fileTree LI.ext_m4p, LI.helper.ext_m4p { background: url(../img/fileTree/music.png) left top no-repeat; }
+.fileTree LI.ext_mov, LI.helper.ext_mov { background: url(../img/fileTree/film.png) left top no-repeat; }
+.fileTree LI.ext_mp3, LI.helper.ext_mp3 { background: url(../img/fileTree/music.png) left top no-repeat; }
+.fileTree LI.ext_mp4, LI.helper.ext_mp4 { background: url(../img/fileTree/film.png) left top no-repeat; }
+.fileTree LI.ext_mpg, LI.helper.ext_mpg { background: url(../img/fileTree/film.png) left top no-repeat; }
+.fileTree LI.ext_mpeg, LI.helper.ext_mpeg { background: url(../img/fileTree/film.png) left top no-repeat; }
+.fileTree LI.ext_ogg, LI.helper.ext_ogg { background: url(../img/fileTree/music.png) left top no-repeat; }
+.fileTree LI.ext_pcx, LI.helper.ext_pcx { background: url(../img/fileTree/picture.png) left top no-repeat; }
+.fileTree LI.ext_pdf, LI.helper.ext_pdf { background: url(../img/fileTree/pdf.png) left top no-repeat; }
+.fileTree LI.ext_php, LI.helper.ext_php { background: url(../img/fileTree/php.png) left top no-repeat; }
+.fileTree LI.ext_png, LI.helper.ext_png { background: url(../img/fileTree/picture.png) left top no-repeat; }
+.fileTree LI.ext_ppt, LI.helper.ext_ppt { background: url(../img/fileTree/ppt.png) left top no-repeat; }
+.fileTree LI.ext_psd, LI.helper.ext_psd { background: url(../img/fileTree/psd.png) left top no-repeat; }
+.fileTree LI.ext_pl, LI.helper.ext_pl { background: url(../img/fileTree/script.png) left top no-repeat; }
+.fileTree LI.ext_py, LI.helper.ext_py { background: url(../img/fileTree/script.png) left top no-repeat; }
+.fileTree LI.ext_rb, LI.helper.ext_rb { background: url(../img/fileTree/ruby.png) left top no-repeat; }
+.fileTree LI.ext_rbx, LI.helper.ext_rbx { background: url(../img/fileTree/ruby.png) left top no-repeat; }
+.fileTree LI.ext_rhtml, LI.helper.ext_rhtml { background: url(../img/fileTree/ruby.png) left top no-repeat; }
+.fileTree LI.ext_rpm, LI.helper.ext_rpm { background: url(../img/fileTree/linux.png) left top no-repeat; }
+.fileTree LI.ext_ruby, LI.helper.ext_ruby { background: url(../img/fileTree/ruby.png) left top no-repeat; }
+.fileTree LI.ext_sql, LI.helper.ext_sql { background: url(../img/fileTree/db.png) left top no-repeat; }
+.fileTree LI.ext_swf, LI.helper.ext_swf { background: url(../img/fileTree/flash.png) left top no-repeat; }
+.fileTree LI.ext_tif, LI.helper.ext_tif { background: url(../img/fileTree/picture.png) left top no-repeat; }
+.fileTree LI.ext_tiff, LI.helper.ext_tiff { background: url(../img/fileTree/picture.png) left top no-repeat; }
+.fileTree LI.ext_txt, LI.helper.ext_txt { background: url(../img/fileTree/txt.png) left top no-repeat; }
+.fileTree LI.ext_vb, LI.helper.ext_vb { background: url(../img/fileTree/code.png) left top no-repeat; }
+.fileTree LI.ext_wav, LI.helper.ext_wav { background: url(../img/fileTree/music.png) left top no-repeat; }
+.fileTree LI.ext_wmv, LI.helper.ext_wmv { background: url(../img/fileTree/film.png) left top no-repeat; }
+.fileTree LI.ext_xls, LI.helper.ext_xls { background: url(../img/fileTree/xls.png) left top no-repeat; }
+.fileTree LI.ext_xml, LI.helper.ext_xml { background: url(../img/fileTree/code.png) left top no-repeat; }
+.fileTree LI.ext_zip, LI.helper.ext_zip { background: url(../img/fileTree/zip.png) left top no-repeat; }
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/skin/jquery.alerts.css b/0.8.1-rc1/curator/src/main/webapp/media/skin/jquery.alerts.css
new file mode 100644
index 0000000..ace2edd
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/skin/jquery.alerts.css
@@ -0,0 +1,77 @@
+/*
+  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.
+*/
+
+#popup_container {
+	font-family: Arial, sans-serif;
+	font-size: 12px;
+	min-width: 300px; /* Dialog will be no smaller than this */
+	max-width: 600px; /* Dialog will wrap after this width */
+	background: #FFF;
+	border: solid 5px #999;
+	color: #000;
+	-moz-border-radius: 5px;
+	-webkit-border-radius: 5px;
+	border-radius: 5px;
+}
+
+#popup_title {
+	font-size: 14px;
+	font-weight: bold;
+	text-align: center;
+	line-height: 1.75em;
+	color: #666;
+	background: #CCC url(images/title.gif) top repeat-x;
+	border: solid 1px #FFF;
+	border-bottom: solid 1px #999;
+	cursor: default;
+	padding: 0em;
+	margin: 0em;
+}
+
+#popup_content {
+	background: 16px 16px no-repeat url(images/info.gif);
+	padding: 1em 1.75em;
+	margin: 0em;
+}
+
+#popup_content.alert {
+	background-image: url(images/info.gif);
+}
+
+#popup_content.confirm {
+	background-image: url(images/important.gif);
+}
+
+#popup_content.prompt {
+	background-image: url(images/help.gif);
+}
+
+#popup_message {
+	padding-left: 48px;
+}
+
+#popup_panel {
+	text-align: center;
+	margin: 1em 0em 0em 1em;
+}
+
+#popup_prompt {
+	margin: .5em 0em;
+}
+.popup_multiPrompt {
+	margin: 0.5em 0em;
+}
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/skin/main.css b/0.8.1-rc1/curator/src/main/webapp/media/skin/main.css
new file mode 100644
index 0000000..669374a
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/skin/main.css
@@ -0,0 +1,501 @@
+/*
+  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.
+*/
+
+
+@CHARSET "UTF-8";
+
+
+/**
+ * CAS Header Styles
+ *
+ * These describe the basic layout of the header code in /views/common/cas-curator-header.jsp
+ */
+
+/* DIV.CAS-HEADER */
+div#cas-header {
+	position:relative;
+	height:56px;
+	padding:5px;
+	text-align:right;
+	border-bottom:solid 1px #000;
+	overflow:none;
+	background:url(../../img/blackfade-syncd.jpg) scroll 0px 0px repeat-x;
+	background-color:#000;
+}
+
+/* DIV.CAS-LOGO-LEFT */
+div#cas-logo-left {
+	position:absolute;
+	top:0px;
+	left:0px;
+	height:67px;
+	width:500px;
+}
+/* DIV.CAS-LOGO-RIGHT */
+div#cas-logo-right {
+	position:absolute;
+	top:0px;
+	right:0px;
+	height:67px;
+	width:290px;
+}
+
+/* H2.APP-TITLE */
+h2.app-title {
+	position:absolute;
+	top:67px;
+	right:0px;
+	margin:0px;
+	width:100%;
+	padding:5px;
+	padding-left:0px;
+	font-weight:normal;
+	font-size:15px;
+	letter-spacing:0.03em;
+}
+/* DIV.USERDETAILS */
+div.userdetails {
+	position:absolute;
+	top:102px;
+	right:5px;
+	font-size:75%;
+	z-index:10
+}
+div.userdetails a {
+	
+}
+
+/* DIV#BREADCRUMBS */
+div#breadcrumbs {
+	position:relative;
+	margin-top:30px;
+	padding:4px;
+	padding-right:5px;
+	padding-left:5px;
+	padding-bottom:5px;
+	font-size:85%;
+}
+div#breadcrumbs ul {
+	list-style:none;
+	margin:0px;
+	padding:0px;
+}
+div#breadcrumbs ul li {
+	display:inline;
+}
+
+div#breadcrumbs ul li a {
+	font-weight:normal;
+	text-decoration:underline;	
+}
+
+/**
+ * CAS Footer Styles
+ *
+ * These describe the basic layout of the footer code in /views/common/cas-curator-footer.jsp
+ */
+ 
+div#footer {
+	font-size:90%;
+	text-align:center;
+	margin-top:35px;
+	border-top:solid 1px #ddd;
+	padding-top:15px;
+	padding-bottom:8px;
+}
+
+div#footer img {
+	border:none;
+	padding-left:2px;
+	margin-left:5px;	
+}
+
+
+
+
+
+
+
+/**
+ * CAS Interface Styles
+ *
+ * These describe the layout of the main curator interface located at /main.jsp
+ */
+ 
+ 
+ 
+/* DIV.ERROR
+ * A red 'error' box suitable for displaying error messages.
+ */
+div.error {
+	background-color:#fcc;
+	padding:5px;
+	margin-right:15px;
+	border:solid 1px #f44;
+}
+
+/* DIV.SUCCESS
+ * A green 'success' box suitable for displaying success messages.
+ */
+div.success  {
+	padding:5px;
+	border:solid 1px green;
+	background-color:#cfc;	
+	margin-right:10px;
+}
+
+/* HEADERS (H1,H2,H3,......) */
+h2.title {
+	padding:5px;
+	margin:0px;
+	border-top:solid 2px #900;
+	border-bottom:solid 1px #300;
+	font-weight:normal;
+	font-size:15px;
+}
+
+h4 {
+	border-bottom:dotted 1px #888;
+}
+
+
+/**
+ * PAGE STRUCTURE
+ *
+ */
+ 
+/* LOGIN FORM */
+form#login-form {
+	border:solid 0px #f66;
+	background-color:#fff;
+	margin:5px;
+	padding:3px;
+	text-align:center;
+}
+form#login-form h3 {
+	color:#333;
+	margin-top:0px;
+	border-bottom:dotted 0px #444;
+		
+}
+form#login-form input[type=text], form#login-form input[type=password] {
+	border:solid 1px #888;
+	padding:3px;
+	width:150px;
+}
+form#login-form table {
+	color:#333;
+	margin:5px;
+	margin-top:0px;
+	border:solid 1px #ccc;
+	width:242px;
+}
+form#login-form input[type=submit] {
+	padding:3px;
+}
+
+
+
+/* MAIN INTERFACE STRUCTURES */
+div.container {
+	position:relative;
+	border:solid 1px grey;
+	padding:5px;
+}
+
+div#browseStagingContainer, div#browseCatalogContainer {
+	position:relative;
+	width:47%;
+	border:solid 2px #ccc;
+	padding:2px;
+}
+div#browseStagingContainer {
+	position:relative;
+	float:left;
+}
+
+div#browseCatalogContainer {
+	position:relative;
+	float:right;
+}
+
+div#browseStaging {
+	position:relative;
+	float:left;
+	width:33%;
+	border:solid 1px #ccc;
+	overflow:scroll;	
+}
+div#browseCatalog {
+	position:relative;
+	float:left;
+	width:33%;
+	border:solid 1px #ccc;
+	overflow:scroll;	
+}
+div#stagingMetContainer {
+	position:relative;
+	float:right;
+	width:60%;
+	height:350px;
+	font-size:12px;
+}
+div#stagingMetExtractorSelection {
+	position:relative;
+	margin-bottom:3px;
+	display:none;
+}
+
+div#stagedMetadataWorkbenchContent {
+	position:relative;
+	height:323px;
+	background-color:#fff;
+	overflow:scroll;
+	border:solid 1px #ccc;	
+}
+div#catalogMetadataWorkbenchContent {
+	position:relative;
+	float:right;
+	width:60%;
+	height:350px;
+	background-color:#fff;
+	overflow:scroll;
+	border:solid 1px #ccc;	
+}
+
+.browser {
+	background:#FFFFFF none repeat scroll 0 0;
+	border-color:#BBBBBB #FFFFFF #FFFFFF #BBBBBB;
+	border-style:solid;
+	border-width:1px;
+	height:350px;
+	padding:5px;
+	width:200px;
+}
+.container.browsers, .container.tasks {
+	background-color:#EEEEEE;
+	border:solid 1px #ccc;
+	padding-top:18px;
+	margin:5px 0px;
+}
+.container h5 {
+	position:relative;
+	margin:-20px -4px 5px;
+	padding:0px;
+	font-family:arial,sans-serif;
+	text-transform:uppercase;
+	color:#999;	
+}
+
+.pathbar {
+	border:solid 1px #ccc;
+	background-color:#f4f4f4;
+	color:#222;
+	padding:3px;
+	margin-bottom:2px;	
+	font-family:courier,sans-serif;
+	font-size:11px;
+}
+
+
+/* METADATA EDITOR */
+div.editor {
+	position:relative;
+	padding:0px;	
+}
+
+div.editor.info {
+	padding:5px;	
+}
+
+div.editor table {
+	font-size:11px;
+	width:100%;
+}
+
+div.editor table tr {
+	
+}
+
+div.editor table tr th {
+	border-right:solid 1px #ccc;
+	border-bottom:solid 1px #ccc;
+	padding:5px;
+	text-align:left;
+	background-color:#f6f6f6;
+	color:#555;
+}
+
+div.editor table tr td {
+	border-right:solid 1px #ccc;
+	border-bottom:solid 1px #ccc;
+	padding:5px;
+}
+
+/* 
+ * INGESTION TASK LIST 
+ */
+
+
+.container.tasks {
+	padding:5px;
+	padding-top:20px;
+}
+.container.tasks h5 {
+	margin:-18px 0px 2px;
+}
+div#ingestionTaskList {
+	
+}
+div#ingestionTaskListContent {
+	background-color:#fff;
+	min-height:100px;
+	border:solid 1px #ccc;	
+}
+
+div#ingestionTaskListContent table {
+	font-size:11px;
+	width:100%;
+}
+
+div#ingestionTaskListContent table tr{
+
+}
+div#ingestionTaskListContent table tr th{
+	padding:4px;
+	border-right:solid 1px #ccc;
+	border-bottom:solid 1px #ccc;
+	background-color:#f6f6f6;
+}
+div#ingestionTaskListContent table tr td{
+	padding:4px;
+	border-right:solid 1px #ccc;
+	border-bottom:solid 1px #ccc;
+}
+
+
+/* PRODUCTTYPE WORKBENCH */
+
+div#productTypeWorkbenchLabel {
+	font-size:12px;
+	font-family:arial,sans-serif;
+	text-transform:uppercase;
+	color:#555;
+	font-weight:normal;
+	padding:1px 1px 1px 4px;	
+}
+
+div#ptwbAddProducts {
+	padding:5px;	
+}
+
+div#productTypeWorkbenchContents .instructions {
+	font-size:90%;
+	color:#444;	
+}
+
+div#ptwbMetadataList table {
+	border:solid 1px #ccc;	
+}
+
+div#droppedFileList {
+
+	overflow:scroll;
+	min-height:50px;
+		
+}
+
+div.ptwbSectionBox {
+	border:solid 1px #ccc;
+	padding:2px;
+	margin:5px 0px 2px 0px;	
+}
+
+div.ptwbSectionBox h5 {
+	margin:0 0 4px;
+	padding:0px;	
+}
+
+div#droppedFileTarget {
+	height:30px;
+	border-color:#bdb;
+	background-color:#dfd;	
+}
+
+div#itMetExtractorSelector {
+	
+}
+
+div#itCreateIngestionTaskButton {
+	margin-top:5px;	
+}
+
+/* INFORMATIONAL MESSAGES */
+/* all absolutely positioned infos are at z-index 1000-1100)
+ */
+div.info {
+	font-size:13px;
+	background-color:#acf;
+	font-family:arial,sans-serif;
+	color:#345;	
+	display:none;	
+}
+div.info input[type=button] {
+	padding:2px;
+	margin:5px 0px;
+}
+div#infoNoMetadataExtractorDefined {
+	position:absolute;
+	border:solid 1px #ccc;
+	top:28px;
+	right:-2px;
+	z-index:1000;
+	width:60%;	
+	line-height:18px;
+}
+div.infoContent {
+	padding:5px;	
+}
+
+/* LINKS */
+
+a {
+	color:#222;
+	text-decoration:none;
+}
+a:hover {
+	text-decoration:underline;
+}
+a.actionlink {
+	color:#48a;
+	padding-left:5px;	
+}
+div#breadcrumbs a {
+	color:#fff;
+}
+
+
+
+/**
+ * .CLR
+ * This is a utility which serves to reset things after a 
+ * series of floated elements
+ */
+.clr {
+	clear:both;
+}
+
diff --git a/0.8.1-rc1/curator/src/main/webapp/media/skin/ui.tabs.css b/0.8.1-rc1/curator/src/main/webapp/media/skin/ui.tabs.css
new file mode 100644
index 0000000..8735763
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/media/skin/ui.tabs.css
@@ -0,0 +1,38 @@
+/*
+  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.
+*/
+
+/* Tabs
+----------------------------------*/
+
+.ui-tabs { padding: 0em; zoom: 1; font-size:11px; }
+.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: 0px; }
+.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0; margin: 0 .2em; padding: 0; }
+.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 3px; border-bottom-color:#fff; margin-bottom:-2px; overflow:none; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { padding: 1em 0em; display: block; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
+
+
+
+.ui-tabs .ui-tabs-nav li { border: solid 1px #ccc; background-color: #bbb; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected {  background-color: #fff; color: #555; }
+.ui-tabs .ui-tabs-nav li a { color: #fff; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a { color:  #555; }
+.ui-tabs .ui-tabs-nav {  }
+.ui-tabs .ui-tabs-panel { padding: 1em 0em; margin: 0em; border-top: solid 1px #ccc;}
diff --git a/0.8.1-rc1/curator/src/main/webapp/sso_login.jsp b/0.8.1-rc1/curator/src/main/webapp/sso_login.jsp
new file mode 100644
index 0000000..1966574
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/sso_login.jsp
@@ -0,0 +1,34 @@
+<%@page import="org.apache.oodt.cas.curation.util.SSOUtils"%>
+<%@page import="org.apache.oodt.security.sso.SingleSignOn"%>
+<%
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+// use new single sign on API
+SingleSignOn auth = SSOUtils.getWebSingleSignOn(application, request,response);
+String ldapUser = request.getParameter("username");
+String ldapPass = request.getParameter("password");
+String refererUrl = request.getParameter("from");
+
+if (auth.login(ldapUser, ldapPass)) {
+	response.sendRedirect(refererUrl);
+} else {
+	if (auth.getLastConnectionStatus()) {
+	    response.sendRedirect("login.jsp?loginFail=true&from="+refererUrl);
+	} else {
+		response.sendRedirect("login.jsp?loginConnectFail=true&from="+refererUrl);
+	}
+}
+%>
diff --git a/0.8.1-rc1/curator/src/main/webapp/tools/logout.jsp b/0.8.1-rc1/curator/src/main/webapp/tools/logout.jsp
new file mode 100644
index 0000000..3a17b3e
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/tools/logout.jsp
@@ -0,0 +1,24 @@
+<%@page import="org.apache.oodt.cas.curation.util.SSOUtils"%>
+<%@page import="org.apache.oodt.security.sso.SingleSignOn"%>
+<%
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+// use new single sign on API
+SingleSignOn auth = SSOUtils.getWebSingleSignOn(application, request,response);
+String refererUrl = request.getParameter("from");
+auth.logout();
+response.sendRedirect(refererUrl);
+%>
diff --git a/0.8.1-rc1/curator/src/main/webapp/tools/requireLogin.jsp b/0.8.1-rc1/curator/src/main/webapp/tools/requireLogin.jsp
new file mode 100644
index 0000000..b370abe
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/tools/requireLogin.jsp
@@ -0,0 +1,27 @@
+<!--
+  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.
+-->
+
+<%@page import="org.apache.oodt.cas.curation.util.SSOUtils"%>
+<%@page import="org.apache.oodt.security.sso.SingleSignOn"%>
+<%
+SingleSignOn auth = SSOUtils.getWebSingleSignOn(application, request,response);
+String refererUrl = request.getRequestURI();
+
+ if(!auth.isLoggedIn()){
+   response.sendRedirect("login.jsp?from="+refererUrl);
+ }
+%>
diff --git a/0.8.1-rc1/curator/src/main/webapp/views/common/cas-curator-footer.jsp b/0.8.1-rc1/curator/src/main/webapp/views/common/cas-curator-footer.jsp
new file mode 100644
index 0000000..1be5e3b
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/views/common/cas-curator-footer.jsp
@@ -0,0 +1,26 @@
+<%
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+%>
+
+</div>
+<!--  end main content -->
+<div id="footer">
+	NASA Jet Propulsion Laboratory.<br/>
+	<a href="http://jpl.nasa.gov">jpl.nasa.gov</a><br/>
+	Built On <a href="http://oodt.jpl.nasa.gov">OODT</a>
+</div>
+</body>
+</html>
diff --git a/0.8.1-rc1/curator/src/main/webapp/views/common/cas-curator-header.jsp b/0.8.1-rc1/curator/src/main/webapp/views/common/cas-curator-header.jsp
new file mode 100644
index 0000000..d742c18
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/views/common/cas-curator-header.jsp
@@ -0,0 +1,119 @@
+<%@page import="org.apache.oodt.security.sso.SingleSignOn"%>
+<%
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+	// Set up parameters for single signon authentication
+	SingleSignOn auth = SSOUtils.getWebSingleSignOn(application, request, response);
+	String refererUrl = request.getRequestURI();
+	String userDetails = "";
+
+	// Determine text to show in the user details area 
+	if(auth.isLoggedIn()){
+    	userDetails = "Logged in as " + auth.getCurrentUsername() 
+    		+ " &nbsp;<a href=\"" + request.getContextPath() + "/tools/logout.jsp?from=" 
+    		+ refererUrl + "\">Log Out</a>";
+	} else { 
+		userDetails = "Not logged in. <a href=\"" + request.getContextPath() 
+			+ "/login.jsp?from=" + refererUrl + "\">Log In</a>";
+	}
+ 	
+	// Retrieve the breadcrumbs to display on this page
+	String breadcrumbString = "";
+	if (session.getAttribute("breadcrumbs") != null) {
+ 		String breadcrumbs[] = (String[]) session.getAttribute("breadcrumbs");
+		for (int i = 0; i < breadcrumbs.length; i++) {
+			// Breadcrumbs are specified on individual pages as an array
+			// of String objects, each with the following format:
+			// either:	label (for a non-clickable breadcrumb)
+			// or:		label:url (for a clickable link breadcrumb)
+			String[] parts = (String[]) ((String)breadcrumbs[i]).split(":");
+			if (parts.length == 2) {
+				if (parts[1].startsWith("/")) {
+					// Process a breadcrumb with an absolute clickable link
+					breadcrumbString += (" / " + "<a href=\"" 
+						+ request.getContextPath() + parts[1] + "\">" 
+						+ parts[0] + "</a>");
+				} else {
+					// Process a breadcrumb with a relative clickable link
+					breadcrumbString += (" / " + "<a href=\"" 
+						+ parts[1] + "\">" + parts[0] + "</a>");
+				}
+			} else {
+				// Process a non-clickable breadcrumb
+				breadcrumbString += (" / " + parts[0]);	
+			}
+		}
+		// Clear the breadcrumb data from the session after processing.
+		// This prevents a page which does not explicitly set its own breadcrumb data from
+		// displaying breadcrumbs left over from a previous page
+		session.setAttribute("breadcrumbs",null);
+	}
+%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<%@page import="org.apache.oodt.cas.curation.util.SSOUtils"%>
+<%@page import="org.apache.oodt.security.sso.AbstractWebBasedSingleSignOn"%>
+<%@page import="org.apache.oodt.security.sso.SingleSignOn"%>
+<%@page import="org.apache.oodt.cas.curation.servlet.CuratorConfMetKeys"%><html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+	
+	<!-- CSS Stylesheets -->
+	<link rel="stylesheet" type="text/css" href="<%=request.getContextPath() %>/media/skin/main.css" />
+	<link rel="stylesheet" type="text/css" href="<%=request.getContextPath() %>/media/skin/ui.tabs.css"/>
+	<link rel="stylesheet" type="text/css" href="<%=request.getContextPath() %>/media/skin/fileTree.css"/>
+	<link rel="stylesheet" type="text/css" href="<%=request.getContextPath() %>/media/skin/jquery.alerts.css"/>
+	<link rel="stylesheet" type="text/css" href="<%=request.getContextPath() %>/media/skin/custom/custom.css"/>
+	<link rel="stylesheet" type="text/css" href="<%=request.getContextPath() %>/media/skin/editing.css"/>
+
+
+	<!-- JavaScript Libraries -->
+	<script type="text/javascript" src="js/jquery-1.3.2.js"></script>
+	<script type="text/javascript" src="js/jquery-ui/jquery-ui-1.7.2.full.min.js"></script>
+	<script type="text/javascript" src="js/fileTree.js"></script>
+	<script type="text/javascript" src="js/jquery.alerts.js"></script>
+	<script type="text/javascript" src="js/main.js"></script>
+	<script type="text/javascript" src="js/editing.js"></script>
+	<script type="text/javascript" src="js/jquery.periodicalupdater.js"></script>
+	
+
+	
+	<% String projectName =  application.getInitParameter(CuratorConfMetKeys.PROJECT_DISPLAY_NAME);%>
+	<title><%=(projectName != null ? projectName+" :: ":"")%>CAS</title>
+</head>
+<body onload="refreshIngestTaskList();registerIngestionTaskListener();">
+<div id="page">
+	<div id="cas-header">
+		<div id="cas-logo-left"><!--  cas logo lhs --></div>
+		<div id="cas-logo-right"><!-- cas logo rhs --></div>
+		<h2 class="app-title"><%=(projectName != null ? projectName:"")%> CAS Curation</h2>
+			<div class="userdetails">
+		      <%=userDetails %>
+		   </div>
+		</div>
+	</div>
+	
+	<div class="menu">
+		<!-- Breadcrumbs Area -->
+		<div id="breadcrumbs"/>
+		<div style="margin-left: 10px;padding-left: 10px;">
+
+		<a href="home.jsp">Home</a>&nbsp;<%=breadcrumbString %></div>
+		</div>
+	</div>
+
+<!-- begin main content -->
+<div style="position:relative;min-height:300px;">
diff --git a/0.8.1-rc1/curator/src/main/webapp/views/common/login-status.jsp b/0.8.1-rc1/curator/src/main/webapp/views/common/login-status.jsp
new file mode 100644
index 0000000..975c5fd
--- /dev/null
+++ b/0.8.1-rc1/curator/src/main/webapp/views/common/login-status.jsp
@@ -0,0 +1,32 @@
+<%@page import="org.apache.oodt.security.sso.SingleSignOn"%>
+<%@page import="org.apache.oodt.cas.curation.util.SSOUtils"" %>
+<%
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+ SingleSignOn auth = SSOUtils.getWebSingleSignOn(application, request,response);
+ String refererUrl = request.getRequestURI();
+ 
+ if(auth.isLoggedIn()){
+   %>
+    Logged in as <%=auth.getCurrentUsername() %>. <a href="<%=request.getContextPath() %>/logout.jsp?from=<%=refererUrl%>">Log Out</a>
+   <%
+  }
+  else{
+   %>
+    Not logged in. <a href="<%=request.getContextPath() %>/login.jsp?from=<%=refererUrl%>">Log In</a>
+   <%
+  }
+%>
diff --git a/0.8.1-rc1/curator/src/site/resources/images/basic_extractor.jpg b/0.8.1-rc1/curator/src/site/resources/images/basic_extractor.jpg
new file mode 100644
index 0000000..88a9107
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/resources/images/basic_extractor.jpg
Binary files differ
diff --git a/0.8.1-rc1/curator/src/site/resources/images/basic_filemgr.jpg b/0.8.1-rc1/curator/src/site/resources/images/basic_filemgr.jpg
new file mode 100644
index 0000000..03c69ec
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/resources/images/basic_filemgr.jpg
Binary files differ
diff --git a/0.8.1-rc1/curator/src/site/resources/images/basic_ingest.jpg b/0.8.1-rc1/curator/src/site/resources/images/basic_ingest.jpg
new file mode 100644
index 0000000..bff8c0f
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/resources/images/basic_ingest.jpg
Binary files differ
diff --git a/0.8.1-rc1/curator/src/site/resources/images/basic_login.jpg b/0.8.1-rc1/curator/src/site/resources/images/basic_login.jpg
new file mode 100644
index 0000000..7743f64
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/resources/images/basic_login.jpg
Binary files differ
diff --git a/0.8.1-rc1/curator/src/site/resources/images/basic_page.jpg b/0.8.1-rc1/curator/src/site/resources/images/basic_page.jpg
new file mode 100644
index 0000000..f94903c
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/resources/images/basic_page.jpg
Binary files differ
diff --git a/0.8.1-rc1/curator/src/site/resources/images/basic_staging.jpg b/0.8.1-rc1/curator/src/site/resources/images/basic_staging.jpg
new file mode 100644
index 0000000..37f4d01
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/resources/images/basic_staging.jpg
Binary files differ
diff --git a/0.8.1-rc1/curator/src/site/resources/images/cas-curator.jpg b/0.8.1-rc1/curator/src/site/resources/images/cas-curator.jpg
new file mode 100644
index 0000000..be2a82e
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/resources/images/cas-curator.jpg
Binary files differ
diff --git a/0.8.1-rc1/curator/src/site/resources/images/cas-curator.psd b/0.8.1-rc1/curator/src/site/resources/images/cas-curator.psd
new file mode 100644
index 0000000..3b2c06e
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/resources/images/cas-curator.psd
Binary files differ
diff --git a/0.8.1-rc1/curator/src/site/resources/media/Bach-SuiteNo2.mp3 b/0.8.1-rc1/curator/src/site/resources/media/Bach-SuiteNo2.mp3
new file mode 100644
index 0000000..2ecd809
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/resources/media/Bach-SuiteNo2.mp3
Binary files differ
diff --git a/0.8.1-rc1/curator/src/site/site.xml b/0.8.1-rc1/curator/src/site/site.xml
new file mode 100644
index 0000000..1a643a2
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/site.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<project name="cas-curator">
+
+  <body>
+    <links>
+      <item name="OODT" href="../oodt-site/"/>
+    </links>
+
+    <menu ref="reports" inherit="bottom"/>
+    <menu name="Software Documentation">
+      <item name="Basic User's Guide" href="user/basic.html"/>
+      <item name="Advanced User's Guide" href="user/advanced.html"/>
+      <item name="REST API Guide" href="api/index.html"/>
+    </menu>
+  </body>
+</project>
diff --git a/0.8.1-rc1/curator/src/site/xdoc/api/index.xml b/0.8.1-rc1/curator/src/site/xdoc/api/index.xml
new file mode 100644
index 0000000..e71e160
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/xdoc/api/index.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+ -->
+<document>
+  <properties>
+    <title>How to use the REST API of the CAS Curator</title>
+    <author email="joshuaga@apache.org">Joshua Garcia</author>
+    <author email="mattmann@apache.org">Chris Mattmann</author>
+  </properties>
+
+  <body>
+    <section name="Introduction">
+      <p>The curator has a REST interface that allows services to be accessed through HTTP requests.  </p>
+      
+      <p>The remainder of this guide is separated into the following 
+      sections:</p>
+      <ul>
+        <li><a href="#section1">Retrieving a List of Ingestion Tasks</a></li>
+        <li><a href="#section2">Creating an Ingestion Task in the Curator Queue</a></li>
+        <li><a href="#section3">Starting an Ingestion Task</a></li>
+      </ul>
+      
+    </section>
+    
+    <a name="section1"/>
+    <section name="Retrieving a List of Ingestion Tasks">
+      <p>A list of ingestion tasks can be retrieved in either <a href="http://www.json.org/">json</a> or html format</p>
+      
+      <p>The format of the URL is the following: http://yourhost/curator/services/ingest/list?format={json|html} <br/>
+      yourhost is the host that is running the tomcat server with the curator.  For example, yourhost can be www.mycurator.com <br/>
+      The format parameter takes either json or html as a value and returns the respective formatted list of ingestion tasks.</p>
+      
+      <p>For example, the URL http://yourhost/curator/services/ingest/list?format=json returns output that looks like: </p>
+      
+      <p>
+      <source><![CDATA[
+      {"taskList":[{"productType":"he5","policy":"mls","extractorClass":"org.apache.oodt.cas.metadata.extractors.ExternMetExtractor","extractorConfFiles":"[/home/joshuaga/extractors/odlextractor/he5extractor.config]","status":"Not Started","createDate":"2010-05-10T00:59:35-07:00","fileList":"[/home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v01-52-c01_2007d055.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v01-52-c01_2007d036.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d168.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v01-51-c01_2005d365.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v01-51-c01_2005d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d095.he5]","id":"2c6df1dc-bfc1-4e22-889e-7b2c262c7db3"},{"productType":"he5","policy":"mls","extractorClass":"org.apache.oodt.cas.metadata.extractors.ExternMetExtractor","extractorConfFiles":"[/home/joshuaga/extractors/odlextractor/he5extractor.config]","status":"Not Started","createDate":"2010-05-10T00:59:35-07:00","fileList":"[/home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v01-51-c01_2005d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c02_2008d106.he5]","id":"0cdd55f6-b954-4aae-b8de-79dc52e85029"},{"productType":"he5","policy":"mls","extractorClass":"org.apache.oodt.cas.metadata.extractors.ExternMetExtractor","extractorConfFiles":"[/home/joshuaga/extractors/odlextractor/he5extractor.config]","status":"Not Started","createDate":"2010-05-10T00:59:35-07:00","fileList":"[/home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v01-52-c01_2007d009.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v01-52-c01_2007d036.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d103.he5]","id":"93b5b803-4b25-49dc-9fe7-02f907c1dcb5"},{"productType":"he5","policy":"mls","extractorClass":"org.apache.oodt.cas.metadata.extractors.ExternMetExtractor","extractorConfFiles":"[/home/joshuaga/extractors/odlextractor/he5extractor.config]","status":"Not Started","createDate":"2010-05-10T00:59:35-07:00","fileList":"[/home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v01-52-c01_2007d055.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v01-51-c01_2005d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v01-52-c01_2007d036.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c02_2008d106.he5]","id":"8c54b4d8-0db5-4389-8c99-3fe3ba6d7a6b"},{"productType":"he5","policy":"mls","extractorClass":"org.apache.oodt.cas.metadata.extractors.ExternMetExtractor","extractorConfFiles":"[/home/joshuaga/extractors/odlextractor/he5extractor.config]","status":"Not Started","createDate":"2010-05-10T00:59:35-07:00","fileList":"[/home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v01-51-c01_2005d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d300.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d300.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d112.he5]","id":"60491675-d870-4fc8-aa1c-ff5503ad2ae9"},{"productType":"he5","policy":"mls","extractorClass":"org.apache.oodt.cas.metadata.extractors.ExternMetExtractor","extractorConfFiles":"[/home/joshuaga/extractors/odlextractor/he5extractor.config]","status":"Not Started","createDate":"2010-05-10T00:59:35-07:00","fileList":"[/home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v01-52-c01_2007d055.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d168.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d097.he5]","id":"19ec6b4b-dc2b-440d-96e2-0bfc13c54d37"},{"productType":"he5","policy":"mls","extractorClass":"org.apache.oodt.cas.metadata.extractors.ExternMetExtractor","extractorConfFiles":"[/home/joshuaga/extractors/odlextractor/he5extractor.config]","status":"Not Started","createDate":"2010-05-10T00:59:35-07:00","fileList":"[/home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d300.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v01-51-c03_2005d001.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v01-52-c01_2007d009.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d110.he5]","id":"ae0043de-f1b0-442c-a097-1989834bf6a0"},{"productType":"he5","policy":"mls","extractorClass":"org.apache.oodt.cas.metadata.extractors.ExternMetExtractor","extractorConfFiles":"[/home/joshuaga/extractors/odlextractor/he5extractor.config]","status":"Not Started","createDate":"2010-05-10T00:59:35-07:00","fileList":"[/home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v01-52-c01_2007d055.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v01-51-c03_2005d001.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d112.he5]","id":"5531d217-e9f7-4aac-a7a6-f7932ea61f5d"},{"productType":"he5","policy":"mls","extractorClass":"org.apache.oodt.cas.metadata.extractors.ExternMetExtractor","extractorConfFiles":"[/home/joshuaga/extractors/odlextractor/he5extractor.config]","status":"Not Started","createDate":"2010-05-10T00:59:35-07:00","fileList":"[/home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d168.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v01-52-c01_2007d009.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d168.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v01-52-c01_2007d009.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d168.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v01-51-c01_2005d365.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d098.he5]","id":"ff564e6d-58cc-4832-971c-09efa817544f"},{"productType":"he5","policy":"mls","extractorClass":"org.apache.oodt.cas.metadata.extractors.ExternMetExtractor","extractorConfFiles":"[/home/joshuaga/extractors/odlextractor/he5extractor.config]","status":"Not Started","createDate":"2010-05-10T00:59:35-07:00","fileList":"[/home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d300.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v01-51-c03_2005d001.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v01-51-c01_2005d365.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d168.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v01-52-c01_2007d009.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d103.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d300.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d108.he5]","id":"a756c587-dafd-4077-8afb-b321154e8839"},{"productType":"he5","policy":"mls","extractorClass":"org.apache.oodt.cas.metadata.extractors.ExternMetExtractor","extractorConfFiles":"[/home/joshuaga/extractors/odlextractor/he5extractor.config]","status":"Not Started","createDate":"2010-05-10T00:59:35-07:00","fileList":"[/home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v01-52-c01_2007d036.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v01-51-c01_2005d365.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v01-51-c03_2005d001.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-GPH_v02-23-c01_2008d114.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d116.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c02_2008d102.he5]","id":"bbde0494-a4ac-460a-9d13-55cdd7466bcf"},{"productType":"he5","policy":"mls","extractorClass":"org.apache.oodt.cas.metadata.extractors.ExternMetExtractor","extractorConfFiles":"[/home/joshuaga/extractors/odlextractor/he5extractor.config]","status":"Not Started","createDate":"2010-05-10T00:59:35-07:00","fileList":"[/home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d107.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v01-51-c01_2005d365.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d093.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d098.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d117.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c02_2008d121.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CH3CN_v01-52-c01_2007d009.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c02_2008d092.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d105.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-OH_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c02_2008d106.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c02_2008d102.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d115.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-N2O_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-DGG_v02-23-c01_2008d300.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-BrO_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d120.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v01-52-c01_2007d036.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d099.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-IWC_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d112.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d097.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d109.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c01_2008d110.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d100.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCN_v02-23-c01_2008d108.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d095.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-O3_v02-23-c01_2008d119.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HO2_v02-23-c01_2008d104.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-RHI_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HOCl_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HNO3_v02-23-c01_2008d110.he5]","id":"5734fa27-adff-439b-ad45-b4d30a1b7001"},{"productType":"he5","policy":"mls","extractorClass":"org.apache.oodt.cas.metadata.extractors.ExternMetExtractor","extractorConfFiles":"[/home/joshuaga/extractors/odlextractor/he5extractor.config]","status":"Not Started","createDate":"2010-05-10T00:59:35-07:00","fileList":"[/home/joshuaga/staging/products/mls/MLS-Aura_L2GP-HCl_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d096.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-H2O_v02-23-c01_2008d118.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-ClO_v02-23-c01_2008d101.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-Temperature_v02-23-c01_2008d094.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d113.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-CO_v02-23-c02_2008d111.he5, /home/joshuaga/staging/products/mls/MLS-Aura_L2GP-SO2_v02-23-c01_2008d100.he5]","id":"3661e118-5ae1-4d6a-b349-c07cd06afe50"}]}
+      ]]></source>
+      </p>
+      
+    </section> 
+    
+    <a name="section2"/>
+    <section name="Creating an Ingestion Task in the Curator Queue">
+      <p>
+      An ingestion task can be added to the curator through the REST interface using the following command: <br/>
+      <source><![CDATA[
+      http://yourhost/curator/services/ingest/create?files=<file1,file2>&numfiles=N&metExtCfgId=something&policy=mls&ptype=<product type> <br/>
+      ]]></source>
+      </p>
+      
+      <p>
+      <ul>
+        <li>yourhost is the host that is running the tomcat server with the curator. For example, your host can be www.mycurator.com</li>
+        <li>files takes as a value a list of files to be ingested</li>
+        <li>numfiles takes the number of files to be ingested</li>
+        <li>metExtCfgId is the num of the metadata extractor to be used.  For example, mp3extractor.</li>
+        <li>policy is ?</li>
+        <li>ptype takes as a valueis the product type of the files to be ingested.  For example, mp3.</li>
+      </ul>
+      </p>
+      
+      <p>
+      An example URL is the following:<br/>
+      <source><![CDATA[
+      http://yourhost/curator/services/ingest/create?files=mls%2FMLS-Aura_L2GP-CO_v02-23-c01_2008d107.he5%2Cmls%2FMLS-Aura_L2GP-Temperature_v01-52-c01_2007d055.he5%2Cmls%2FMLS-Aura_L2GP-Temperature_v02-23-c01_2008d110.he5&policy=mls&ptype=he5&numfiles=3&metExtCfgId=odlextractor
+      ]]></source>
+      The result is the task id for the ingestion task. For example, 2c6df1dc-bfc1-4e22-889e-7b2c262c7db3.
+      </p>
+        
+    </section> 
+    
+    <a name="section3"/>
+    <section name="Starting an Ingestion Task">
+      <p>
+      To run the ingestion task, the following URL can be used:<br/>
+      <source><![CDATA[
+      http://yourhost/curator/services/ingest/start?taskId=<task Id>
+      ]]></source>
+      </p>
+      
+      <p>
+      <ul>
+        <li>yourhost is the host that is running the tomcat server with the curator. For example, yourhost can be www.mycurator.com</li>
+        <li>task Id is the task id for the ingestion task. For example, 2c6df1dc-bfc1-4e22-889e-7b2c262c7db3, which was the result of the creation task example of the previous section.</li>
+      </ul>
+      </p>
+          
+    </section> 
+  </body>
+</document>
\ No newline at end of file
diff --git a/0.8.1-rc1/curator/src/site/xdoc/development/maven.xml b/0.8.1-rc1/curator/src/site/xdoc/development/maven.xml
new file mode 100755
index 0000000..4207fa0
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/xdoc/development/maven.xml
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+  <properties>
+    <title>Using Maven</title>
+    <author email="woollard@jpl.nasa.gov">David Woollard</author>
+  </properties>
+
+  <body>
+    <section name="Using Maven">
+      <p>Apache OODT uses <a href="http://maven.apache.org/">Maven</a> for 
+      managing our build environment. Maven is an open source product from the 
+      <a href="http://www.apache.org/">Apache Software Foundation</a> that improves 
+      on <a href="http://ant.apache.org/">Ant</a> in the area of build management, 
+      which it turn was an improvement on Make. This document describes the use of 
+      Maven for OODT build management.</p>
+    </section>
+    
+    <section name="Setup">
+      <p>Maven can be downloaded from the 
+      <a href="http://maven.apache.org/download.html">Maven Download</a> 
+      page. OODT is using version 2.0 and above. Maven was developed in Java so it 
+      will run on the popular platforms (e.g., Windows, Mac OSX, etc.). Beyond 
+      making sure the <i>mvn</i> executable is in your path, there is very little 
+      setup required.</p>
+
+      <p>Maven is based on the concept of a Project Object Model (POM) which is 
+      contained in the <i>pom.xml</i> file found at the root of each project. 
+      The POM allows Maven to manage a project's build, reporting and documentation. 
+      For OODT, much of the default information for managing the projects is 
+      contained in a parent POM, which is located in the <i>oodt-core</i> project. So, 
+      in order to build any of the other projects (e.g., cas-curator, cas-filemgr, 
+      etc.) the parent POM must be downloaded from the OODT Maven repository. The 
+      local <i>pom.xml</i> files for each of the projects have been configured to 
+      retrieve the parent POM automatically.</p>
+      
+      <p>Once Maven has been setup, the first step to building a project with Maven 
+      is to checkout a project's source code into the developer's work area. See the 
+      <a href="../development/subversion.html">Using Subversion</a> document for how to 
+      check out projects from the CM repository.</p>
+    </section>
+    
+    <section name="Project Structure">
+      <p>In order for default Maven functions to operate properly, there is a 
+      suggested project directory structure. The structure is as follows:</p>
+      
+      <source>
+/
+  src/             Source Code (everything)
+    main/            Program Source
+      assembly/        Package Descriptor
+      java/            Java Source
+      resources/       Scripts, Config File, etc.
+        ...
+    test/            Test Source
+      java/
+      resources/
+        ...
+    site/            Site Documentation
+      apt/             Docs in APT Format
+        index.apt
+        ...
+      xdoc/            Docs in XDOC Format
+        index.xml
+        ...
+      resources/
+        images/
+      site.xml         Menu Structure
+
+  target/          Build Results (binaries, docs and packages)
+    ...
+
+  LICENSE.txt
+  README.txt
+  pom.xml          Project Object Model (POM)
+      </source>
+    </section>
+    
+    <section name="Standard Commands">
+    <p>There are few standard commands that developers will use on a daily basis 
+    and they are related to building and cleaning a project.</p>
+    <subsection name="Build a Project">
+      <p>Build the project's libraries and executables with the following 
+      command:</p>
+      <source>
+mvn compile
+      </source>
+      <p>The above command will generate the artifacts in the <i>target/</i> 
+      directory.</p>      
+    </subsection>
+    <subsection name="Install a Project">
+      <p>Install the project's artifacts locally with the following command:</p>
+      <source>
+mvn install
+      </source>
+      <p>Prior to installation, the above command will compile the source code, 
+      if necessary, and execute the unit tests. The result of the above command 
+      is to install the generated artifacts (e.g. pom, jar, etc.) in the user's 
+      local Maven repository ($HOME/.m2/repository/). This is useful when the 
+      artifact is a dependency for another project but has yet to be deployed 
+      to the SWSA Maven repository.</p>
+    </subsection>
+    <subsection name="Package a Project">
+      <p>Create the project's distribution package with the following command:</p>
+      <source>
+mvn package
+      </source>
+      <p>Prior to package creation, the above command will compile the source 
+      code, if necessary, and execute the unit tests. The above command will 
+      create the package(s) in the target/ directory.</p>
+    </subsection>
+    <subsection name="Build a Project's Web Site">
+      <p>Build the project's web site with the following command:</p>
+      <source>
+mvn site
+      </source>
+      <p>The above command will generate the web site in the <i>target/site/</i>
+      directory. View the site by pointing your web browser at the 
+      <i>index.html</i> file within that directory.</p>
+    </subsection> 
+    <subsection name="Clean a Project">
+      <p>Clean out the project directory of generated artifacts with the 
+      following command:</p>
+      <source>
+mvn clean
+      </source>
+      <p>The above command will remove the <i>target/</i> directory and its 
+      contents.</p>
+    </subsection>
+    <subsection name="Useful Command Arguments">
+      <p>There a couple of useful arguments which can be appended to the 
+      commands above to limit the scope of the command.</p>
+      <p>In order to skip unit test execution, add the following argument:</p>
+      <source>
+mvn [command] -Dmaven.test.skip=true
+      </source>
+      <p>The above command is most useful with the <i>install</i>, 
+      <i>package</i> and <i>site</i> commands.</p>
+      <p>When a project has modules defined in the POM, the command can be 
+      performed against the top level of the project instead of the modules by 
+      adding the following argument:</p>
+      <source>
+mvn [command] --non-recursive
+      </source>
+    </subsection>
+    </section>
+    <section name="Acknowledgments">
+      <p>Much of the material in this Maven guide was originally authored 
+      by Sean Hardman under the sponsorship of NASA Jet Propulsion 
+      Laboratory's Planetary Data System. </p>
+    </section>
+    <section name="References">
+      <p>Here is a list of Maven resources:</p>
+      <ul>
+        <li><a href="http://maven.apache.org/guides/index.html">Online 
+        Documentation Index</a></li>
+      </ul>
+    </section>
+  </body>
+</document>
diff --git a/0.8.1-rc1/curator/src/site/xdoc/user/advanced.xml b/0.8.1-rc1/curator/src/site/xdoc/user/advanced.xml
new file mode 100644
index 0000000..707fe78
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/xdoc/user/advanced.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+  <properties>
+    <title>Setting Up the CAS-Curator</title>
+    <author email="woollard@jpl.nasa.gov">David Woollard</author>
+  </properties>
+
+  <body>
+    <section name="Introduction">
+    
+    <p>This document serves as an advanced user's guide for the CAS-Curator
+      project. The goal of the document is to explore advanced topics such as 
+      security setup and changing the look and feel of the CAS-Curator
+      to match your project. For basic topics, such as checking out, 
+      building, and installing the base version of the CAS-Curator, as well 
+      as performing basic configuration tasks, please see our 
+      <a href="../user/basic.html">Basic Guide.</a></p>
+    
+    <p>The remainder of this guide is separated into the following 
+      sections:</p>
+      
+    <ul>
+      <li><a href="#section1">Security Setup</a></li>
+      <li><a href="#section2">Look and Feel</a></li>
+    </ul>
+    </section>
+    
+    
+    <a name="section1"/>
+    <section name="Security Setup">
+    <p>Coming Soon...</p>
+    </section>
+    
+    <a name="section2"/>
+    <section name="Look and Feel">
+    <p>Coming Soon...</p>
+    </section>
+   
+  </body>
+</document>  
diff --git a/0.8.1-rc1/curator/src/site/xdoc/user/basic.xml b/0.8.1-rc1/curator/src/site/xdoc/user/basic.xml
new file mode 100644
index 0000000..65195d4
--- /dev/null
+++ b/0.8.1-rc1/curator/src/site/xdoc/user/basic.xml
@@ -0,0 +1,690 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+  <properties>
+    <title>Setting Up the CAS-Curator</title>
+    <author email="woollard@jpl.nasa.gov">David Woollard</author>
+  </properties>
+
+  <body>
+    <section name="Introduction">
+      <p>This document serves as a basic user's guide for the CAS-Curator
+      project. The goal of the document is to allow users to check out,
+      build, and install the base version of the CAS-Curator, as well
+      as perform basic configuration tasks. For advanced topics, such 
+      as customizing the look and feel of the CAS-Curator for your
+      project, please see our <a href="../user/advanced.html">Advanced 
+      Guide.</a></p>
+      
+      <p>The remainder of this guide is separated into the following 
+      sections:</p>
+      <ul>
+        <li><a href="#section1">Download and Build</a></li>
+        <li><a href="#section2">Tomcat Deployment</a></li>
+        <li><a href="#section3">Staging Area Setup</a></li>
+        <li><a href="#section4">Extractor Setup</a></li>
+        <li><a href="#section5">File Manager Configuration</a></li>
+      </ul>
+      
+    </section>
+    
+    <a name="section1"/>
+    <section name="Download And Build">
+      <p>The most recent CAS-Curator project can be downloaded from
+      the OODT <a href="http://oodt.apache.org/">website</a> or it can
+      be checked out from the OODT repository using Subversion. The 
+      We recommend checking
+      out the latest released version (v1.0.0 at the time of writing).
+      </p>
+      
+      <p>Maven is the build management system used for OODT projects. We
+      currently support Maven 2.0 and later. For more information on 
+      Maven, see our <a href="../development/maven.html">Maven Guide.</a>
+      </p>
+      
+      <p>Assuming a *nix-like environment, with both Maven and Subversion 
+      clients installed and on your path, an example of the checkout and 
+      build process is presented below:</p>
+      
+      <source>
+> mkdir /usr/local/src
+> cd /usr/local/src
+> svn checkout http://oodt/repo/cas-curator/tags/1_0_0_release \
+    cas-curator-v1.0.0       
+      </source>
+        
+      <p>After the Subversion command completes, you will have the source
+      for the CAS-Curator project in the <code>/usr/local/src/cas-curator-v1.0.0</code>
+      directory.</p>
+      
+      <p>In order to build the WAR (Web ARchive) file from this source,
+      issue the following commands:</p>
+      
+      <source>
+> cd /usr/local/src/cas-curator-v1.0.0
+> mvn package    
+      </source>   
+      
+      <p>Once the Maven command completes successfully, you should have a 
+      <code>target</code> directory under <code>cas-curator-v1.0.0/</code>. The 
+      WAR file, called <code>cas-curator-1.0.0.war</code>, can be found under 
+      <code>target/</code>.</p>
+      
+      <p>In the next section, we will discuss deploying this WAR file to
+      a Tomcat instance.</p>   
+      
+    </section> 
+    
+    <a name="section2"/>
+    <section name="Tomcat Deployment">
+      <p>Once you have built a war file, it is necessary to deploy the web
+      application using a servlet container such as 
+      <a href="http://tomcat.apache.org/">Tomcat</a> or 
+      <a href="http://www.mortbay.org/jetty/">Jetty</a>. For the purposes of 
+      this guide, we will assume that you are using Tomcat. Tomcat can be
+      installed in a user account or at the system level. The base configuration
+      launches a web server on port 8080. You can learn more about Tomcat and 
+      download the latest release from their 
+      <a href="http://tomcat.apache.org/">website</a>. NOTE: There are two
+      concurrent versions of Tomcat: 5.5.X and 6.0.X. CAS-Curator is compatible
+      with both versions.</p>
+      
+      <p>We will assume that you have downloaded Tomcat to an appropriate 
+      directory, are using the default configuration, and have taken the 
+      appropriate steps to allow access to port 8080. See your System 
+      Administrator is you have any questions about firewall security and policy
+      regarding port access. We will further assume that you have set an 
+      environment variable, <code>$TOMCAT_HOME</code>, to the base directory
+      of your Tomcat installation.</p>
+      
+      <p>There are a number of ways to deploy a WAR file to Tomcat, though we
+      recommend using a context file. A context file is a XML file that provides
+      Tomcat with "context" for using a particular web application. In order to 
+      create a context file for the CAS-Curator, open your favorite text editor
+      and copy and paste the following:</p>
+      
+      <source><![CDATA[<Context path="/my-curator"
+docBase="/usr/local/src/cas-curator-v1.0.0/target/cas-curator-1.0.0.war">  
+  <Parameter name="org.apache.oodt.security.sso.implClass"
+            value="org.apache.oodt.security.sso.DummyImpl"/>
+  <Parameter name="org.apache.oodt.cas.curator.projectName"
+        value="My Project"/>
+</Context>    
+      ]]></source>
+       
+      <p>Save the context file to 
+      <code>$TOMCAT_HOME/conf/Catalina/localhost/my-curator.xml</code>. Now you 
+      can point a web browser to <a href="http://localhost:8080/my-curator/">
+      http://localhost:8080/my-curator</a> and you should see a log-in screen
+      for CAS-Curator. <em>Note</em>: Tomcat will only use the path attribute 
+      if the context is defined in server.xml. Tomcat uses the xml file name 
+      instead. See the 
+      <a href="http://tomcat.apache.org/tomcat-5.5-doc/config/context.html" class="externalLink"> 
+      Tomcat documentation</a> for further information</p> 
+      
+      <img src="../images/basic_login.jpg"/>
+      
+      <p>The <code>org.apache.oodt.security.sso.implClass</code> parameter
+      that we set in the context file configures the CAS-Curator for a "dummy"
+      log-in to its Single Sign On service. Because of this, we are able to 
+      log into the web application with a blank user name and a blank password. 
+      For help in implementing security with CAS-Curator, see our 
+      <a href="../user/advanced.html">Advanced Guide.</a></p>
+      
+      <img src="../images/basic_page.jpg"/>
+      
+      <p>In the next sections, we will talk about setting up staging areas, 
+      metadata extractors, and launching a CAS-Filemgr instance into which 
+      CAS-Curator will ingest data products.</p>
+        
+    </section> 
+    
+    <a name="section3"/>
+    <section name="Staging Area Setup">
+      <p>Staging areas are directories on your local machine that hold data 
+      products to be curated. The staging area can have arbitrary structure. 
+      The only requirement that CAS-Curator has with regard to this structure 
+      is that the directory structure be mirrored in a metadata generation
+      area. This generation area is used by CAS-Curator to create metadata
+      files to associate with data products.</p>
+      
+      <p>For example, if there is a product, say an MP3 file of Bach's <i>Der 
+      Geist hilft unsrer Schwachheit auf</i>, in the staging area at:</p>
+      
+      <source> 
+[staging_area_base]/audio/classical/bach/Der_Geist_hilft.mp3   
+      </source>
+      
+      <p>Then the CAS-Curator will generate all associated metadata products
+      in <code>[metadata_gen_base]/audio/classical/bach/</code>.</p>
+      
+      <p>In order to set up the staging area and the metadata generation area,
+      we first create base directories for each, shown below:</p>
+      
+      <source>
+> mkdir /usr/local/staging
+> mkdir /usr/local/staging/products
+> mkdir /usr/local/staging/metadata
+      </source>
+      
+      <p>Next, we will set the following parameters in the CAS-Curator context file:</p>
+      
+<source><![CDATA[<Parameter name="org.apache.oodt.cas.curator.stagingAreaPath"
+        value="/usr/local/staging/products"/>
+    
+<Parameter name="org.apache.oodt.cas.curator.metAreaPath"
+        value="/usr/local/staging/metadata"/>
+    
+<Parameter name="org.apache.oodt.cas.curator.metExtension"
+        value=".met"/>]]></source>
+      
+    <p>The <code>org.apache.oodt.cas.curator.stagingAreaPath</code> parameter should 
+    be set to the product staging area and the 
+    <code>org.apache.oodt.cas.curator.metAreaPath</code> should be set to the metedata
+    generation area. Additionally, we specified the parameter 
+    <code>org.apache.oodt.cas.curator.metExtension</code> to be <code>.met</code>. 
+    This parameter specifies the extension for all of the metadata files produced in
+    the metadata generation area.</p>
+    
+    <p>For illustrative purposes, we will load an mp3 file into the staging area:</p>
+    
+    <source>
+> mkdir /usr/local/staging/products/mp3
+> cd /usr/local/staging/products/mp3
+> curl -LO http://oodt.apache.org/components/maven/curator/media/Bach-SuiteNo2.mp3
+    </source>
+    
+    <p>We should note that this music file was produced by the 
+    <a href="http://www.fuldaer-symphonisches-orchester.de/">Fulda Symphonic 
+    Orchestra</a> and is freely distributed under the
+    <a href="http://www.eff.org/about/">EFF Open Audio License</a>, version 1.0. We 
+    have edited the ID3 tag of this file (in order to make the later metadata extraction
+    example more interesting), but original authorship is retained. Now back to the 
+    tutorial...</p>
+    
+    <p>Remember that we need to mirror the product staging area and the metadata 
+    generation area, so will also need to create the matching directory structure 
+    there:</p>
+    
+    <source>
+> mkdir /usr/local/staging/metadata/mp3
+    </source>
+    
+    <p>Once you restart Tomcat, the changes you have made to the context file will be
+    used. The staging area will now be set to <code>/usr/local/staging/products</code>.
+    See the screenshot below:</p>
+ 
+    <img src="../images/basic_staging.jpg"/>    
+    
+    <p>Double-clicking on "mp3", we can see that the staging area path in the top left 
+    is now <code>/mp3</code> and <code>Bach-SuiteNo2.mp3</code> can be seen the main 
+    left staging pane. For the time-being, there is no metadata detected (as reported 
+    in the main right staging pane), but in the next section, we will be setting up a 
+    basic, command-line metadata extractor in order to show how extractors are 
+    integrated into CAS-Curator.</p>
+          
+    </section> 
+    
+    <a name="section4"/>
+    <section name="Extractor Setup">
+    <p>The CAS-Curator uses ancillary programs called metadata extractors to produce
+    the metadata that it associates with products. More information about metadata 
+    extractors can be found in the 
+    <a href="../../metadata/user/extractorBasics.html">
+    Extractor Basics</a> User's Guide.</p>
+    
+    <p>Like the staging area, we first need to set up an area in the file system for
+    metadata extractors. We will call this directory <code>extractors</code>:</p>
+    
+    <source>
+ > mkdir /usr/local/extractors   
+    </source> 
+    
+    <p>In order to register the metadata extractor path with the CAS-Curator, we will 
+    need to add another parameter to the web application's context file. Add the
+    following parameter:</p>
+    
+<source><![CDATA[<Parameter name="org.apache.oodt.cas.curator.metExtractorConf.uploadPath"
+		value="/usr/local/extractors" />    
+    ]]></source>
+    
+    <p>We are going to make a metadata extractor that will extractor ID3 tag metadata, 
+    such as author, title, resource type, etc from mp3s. As a first step, we will create 
+    a directory for the new extractor. The name of this directory is important, because
+    CAS-Curator will use the directory name to register the extractor. We will name this
+    directory <code>mp3extractor</code></p>
+    
+<source>
+> mkdir /usr/local/extractors/mp3extractor
+</source>
+
+    <p>While we could write a custom extractor in Java for the Cas-Curator, there are 
+    multiple existing software packages that read mp3 ID3 tags. For these situations,
+    where an external, command-line extractor exists, we have developed the 
+    <code>ExternMetExtractor</code> class in the CAS-Metadata project.</p>
+    
+    <p>For this example, we are going to leaverage an existing, open source mime-type
+    detector with text and metadata parsing capabilities called 
+    <a href="http://lucene.apache.org/tika/">Apache Tika</a>. Tika parses a number of 
+    different common data formats, including a number of audio formats like mp3.
+    I'll leave it to the reader of this guide to download and install Tika. We
+    will assume that the latest release of the tika-app jar is in the 
+    <code>mp3extractor</code> directory.</p>
+    
+    <p>We have a little work to do to convert the output of Tika into a metadata file
+    compatible with CAS-Curator. By default, Tika produces metadata in a "key: value"
+    format as shown in the command-line session below:</p>
+    
+<source><![CDATA[
+> java -jar tika-app-0.5-SNAPSHOT.jar -m \
+    /usr/local/staging/products/mp3/Bach-SuiteNo2.mp3
+Author: Johann Sebastian Bach
+Content-Type: audio/mpeg
+resourceName: Bach-SuiteNo2.mp3
+title: Bach Cello Suite No 2  
+    ]]></source>   
+    
+    <p>With a little AWK magic, we can convert this output to the Cas-Metadata xml
+    format:</p>
+    <!-- FIXME: change namespace URI? -->
+<source><![CDATA[
+> java -jar tika-app-0.5-SNAPSHOT.jar -m \
+  /usr/local/staging/products/mp3/Bach-SuiteNo2.mp3 | awk -F:\
+  'BEGIN \
+  {print "<cas:metadata xmlns:cas=\"http://oodt.jpl.nasa.gov/1.0/cas\">"}\
+  {print "<keyval><key>"$1"</key><val>"substr($2,2)"</val></keyval>"}\
+  END {print "</cas:metadata>"}'
+<cas:metadata xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<keyval><key>Author</key><val>Johann Sebastian Bach</val></keyval>
+<keyval><key>Content-Type</key><val>audio/mpeg</val></keyval>
+<keyval><key>resourceName</key><val>Bach-SuiteNo2.mp3</val></keyval>
+<keyval><key>title</key><val>Bach Cello Suite No 2</val></keyval>
+</cas:metadata>            
+    ]]></source> 
+    
+    <p>Cool as a one line format translater is, we are actually going to have to
+    do a little more work to create an extractor capable of producing metadata
+    for CAS-Curator. A requirement for metadata extractors that are to be integrated
+    with CAS-Curator is that they product three pieces of metadata:</p>
+    
+    <ul>
+      <li>ProductType</li>
+      <li>FileLocation</li>
+      <li>Filename</li>
+    </ul> 
+    
+    <p>We should note that this is NOT a general requirement of all metadata 
+    extractors, but a ramification of the current implementation of CAS-Curator.
+    In order to product this extra metadata, we will develop a small Python
+    script:</p> 
+
+<source><![CDATA[
+#!/usr/bin/python
+
+import os
+import sys
+
+fullPath = sys.argv[1]
+pathElements = fullPath.split("/");
+fileName = pathElements[len(pathElements)-1]
+fileLocation = fullPath[:(len(fullPath)-len(fileName))]
+productType = "MP3"
+
+cmd = "java -jar /Users/woollard/Desktop/extractors/mp3extractor/"
+cmd += "tika-app-0.5-SNAPSHOT.jar -m "+fullPath+" | awk -F:"
+cmd += " 'BEGIN {print \"<cas:metadata xmlns:cas="
+cmd += "\\\"http://oodt.jpl.nasa.gov/1.0/cas\\\">\"}"
+cmd += " {print \"<keyval><key>\"$1\"</key><val>\"substr($2,2)\""
+cmd += "</val></keyval>\"}' > "+fileName+".met"
+
+os.system(cmd)
+
+f = open(fileName+".met", 'a')
+f.write('<keyval><key>ProductType</key><val>+productType)
+f.write('</val></keyval>\n<keyval><key>Filename</key><val>')
+f.write(fileName+'</val></keyval>\n'<keyval><key>FileLocation')
+f.write('</key><val>'+fileLocation+'</val></keyval>\n')
+f.write('</cas:metadata>')
+f.close()
+]]></source>
+
+    <p>We'll assume that you have Python installed at <code>/usr/bin/python</code>
+    and you have named this script <code>mp3PythonExtractor.py</code> and placed
+    it in <code>/usr/local/extractors/mp3extractor</code>. We'll need
+    to make sure it is executable from the command-line:</p>
+
+<source><![CDATA[
+> cd /usr/local/extractors/mp3extractor
+> chmod +x mp3PythonExtractor.py
+> ./mp3PythonExtractor.py \
+ /usr/local/staging/products/mp3/Bach-SuiteNo2.mp3
+<cas:metadata xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<keyval><key>Author</key><val>Johann Sebastian Bach</val></keyval>
+<keyval><key>Content-Type</key><val>audio/mpeg</val></keyval>
+<keyval><key>resourceName</key><val>Bach-SuiteNo2.mp3</val></keyval>
+<keyval><key>title</key><val>Bach Cello Suite No 2</val></keyval>
+<keyval><key>ProductType</key><val>MP3</val></keyval>
+<keyval><key>Filename</key><val>Bach-SuiteNo2.mp3</val></keyval>
+<keyval><key>FileLocation</key><val>/usr/local/staging/products/mp3
+</val></keyval>
+</cas:metadata>
+]]></source>  
+    
+    <p>Now that we have a metadata extractor that meets our requirements (it's
+    callable from the command-line, it produces CAS-Metadata compatible XML, and
+    it extracts <i>ProductType</i>, <i>Filename</i>, and <i>FileLocation</i>),
+    the next step is to create an <code>ExternMetExtractor</code> configuration
+    file. This file will configure CAS-Metadata's <code>ExternMetExtractor</code>
+    to call the <code>mp3PythonExtractor.py</code> script correctly.</p> 
+    
+    <p>There is more information about <code>ExternMetExtractor</code> 
+    configuration available in CAS-Metadata's 
+    <a href="http://oodt.jpl.nasa.gov/cas-metadata/user/extractorBasics.html">
+    Extractor Basics</a> User's Guide. For the purposes of this guide, we will 
+    assume that the reader is familiar with configuration of this extractor, so we 
+    will just present the configuration below (we assume that you name this file 
+    <code>mp3PythonExtractor.config</code>):</p> 
+ 
+<source><![CDATA[    
+<?xml version="1.0" encoding="UTF-8"?>
+<cas:externextractor xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+   <exec workingDir="">
+      <extractorBinPath>
+/usr/local/extractors/mp3extractor/mp3PythonExtractor.py
+      </extractorBinPath>
+      <args>
+         <arg isDataFile="true"/>
+      </args>
+   </exec>
+</cas:externextractor>
+]]></source>    
+    
+    <p>The last step in configuring our mp3 metadata extractor is to provide a 
+    properties file for CAS-Curator so that it knows how to call the 
+    <code>ExternMetExtractor</code>. Each extractor used by CAS-Curator needs
+    a <code>config.properties</code> file. This file sets two properties:</p>
+    
+    <ul>
+      <li><code>extractor.classname</code></li>
+      <li><code>extractor.config.files</code></li>
+    </ul>  
+    
+    <p>Create a <code>config.properties</code> file (this name is important for 
+    CAS-Curator to pick up the cofiguration) in the 
+    <code>/usr/local/extractors/mp3extractor</code> directory. This file should
+    consist of the following parameters:</p>
+
+<source>
+extractor.classname=org.apache.oodt.cas.metadata.extractors.ExternMetExtractor
+extractor.config.files=/usr/local/extractors/mp3extractor/mp3PythonExtractor.config
+</source>
+
+    <p>To recap, we first created a Python script that calls
+    <a href="http://lucene.apache.org/tika/">Apache Tika</a> to extract metadata
+    from mp3 files. Then we created a configuration file that configures 
+    CAS-Metadata's <code>ExternMetExtractor</code> to call this python script.
+    Finally, we created a properties file for the CAS-Curator to call the 
+    <code>ExternMetExtractor</code>. To confirm the configuration of this 
+    extractor, we can long list the extractor directory:</p>
+    
+    <source>
+> cd /usr/local/extractors/mp3extractor
+> ls -l
+total 51448
+-rw-r--r--  1 -  -       167 Nov 27 13:50 config.properties
+-rw-r--r--  1 -  -       328 Nov 27 13:49 mp3PythonExtractor.config
+-rwxr-xr-x  1 -  -       702 Nov 27 13:49 mp3PythonExtractor.py
+-rw-r--r--  1 -  -  26325155 Nov 27 13:46 tika-app-0.5-SNAPSHOT.jar
+    </source>    
+
+    <p>Once you restart Tomcat, the change you have made to the context file will be
+    used. The extractor area will now be set to <code>/usr/local/extractors</code>.
+    See the screenshot below:</p>
+ 
+    <img src="../images/basic_extractor.jpg"/> 
+    
+    <p>In the above screenshot, we see that, upon clicking on the mp3 file, 
+    metadata produced by the <code>mp3extractor</code> is shown in the main right 
+    staging pane. Now staging and extraction are set up. In the next section, we
+    will set up a CAS-Filemgr instance and show how CAS-Curator can be used to 
+    ingest products.</p>
+    
+    </section>
+    
+    <a name="section5"/>
+    <section name="File Manager Configuration">
+    
+    <p>The final step in our basic configuration of CAS-Curator is to configure a 
+    CAS-Filemgr instance into which we will ingest our mp3s. There is a lot of
+    information on configuring the CAS-Filemgr in its
+    <a href="../../filemgr/user/">User's Guide</a>. We will 
+    assume familiarity with the CAS-Filemgr for the remainder of this guide.</p>
+    
+    <p>In this guide, we will focus on the basic configuration necessary to tailor
+    a vanilla build of the CAS-Filemgr for use with our CAS-Curator. We will assume 
+    that you have built the latest release of the CAS-Filemgr (v1.8.0 at the time of 
+    this writing) and installed it at:</p>
+    
+    <source>
+/usr/local/src/cas-filemgr-1.8.0/
+    </source>
+    
+    <p>The first step in configuring the CAS-Filemgr is to edit the 
+    <code>filemgr.properties</code> file in the <code>etc</code> directory. This 
+    file controls the basic configuration of the CAS-Filemgr, including its
+    various extension points. For this example, we are going to run the CAS-Filemgr
+    in a very basic configuration, with both its repository and validation layer
+    controlled by XML configuration, a local data transfer factory, and a 
+    <a href="http://lucene.apache.org/java/docs/">Lucene</a>-based metadata 
+    catalog.</p>
+    
+    <p>In order to create this configuration, we will change the following
+    parameters in the <code>filemgr.properties</code> file:</p>
+    
+    <ul>
+      <li>Set <code>org.apache.oodt.cas.filemgr.catalog.lucene.idxPath</code>
+      to <code>/usr/local/src/cas-filemgr-1.8.0/catalog</code>. This parameter
+      tells CAS-Filemgr where to create the Lucene index. The first time you start 
+      the CAS-Filemgr, make sure that this file does NOT exist. The CAS-Filemgr 
+      will take care of creating it and populating it with the appropriate files.
+      </li>
+      <li>Set <code>org.apache.oodt.cas.filemgr.repositorymgr.dirs</code> to
+      <code>file:///usr/local/src/cas-filemgr-1.8.0/policy/mp3</code>. The value needs
+      to be a URL and we are pointing to a policy folder we will create.</li>
+      <li>Set <code>org.apache.oodt.cas.filemgr.validation.dirs</code> to 
+      <code>file:///usr/local/src/cas-filemgr-1.8.0/policy/mp3</code>. Like the last 
+      parameter we configured, this parameter should be a URL and point to the 
+      same policy folder.</li>
+    </ul>
+    
+    <p>With these changes, you are ready to run the basic configuration of the 
+    CAS-Filemgr. In order to make this install of CAS-Filemgr work with our 
+    CAS-Curator, however, we will also need to augment the basic policy for both
+    the repository manager and validation layer.</p>
+    
+    <p>First, we will create a policy directory for our mp3 curator. We can do this
+    by moving the current policy files from the base <code>policy</code> directory to
+    a <code>mp3</code> directory:</p>
+    
+    <source>
+> cd /usr/local/src/cas-filemgr-1.8.0/policy
+> mkdir mp3
+> mv *.xml mp3/    
+    </source> 
+    
+    <p>Next, we will add a product type to our instance of the CAS-Filemgr. In order 
+    to do this, we will edit the <code>product-types.xml</code> file in the 
+    <code>policy/mp3</code> directory. We will add the following as a child of the 
+    <code>&lt;cas:producttypes&gt;</code> node (we purposefully elide any
+    commentary on the details of this configuration and leave it to the 
+    reader):</p>
+
+<source><![CDATA[ 
+<type id="urn:example:MP3" name="MP3">
+  <repository path="file:///usr/local/archive"/>
+  <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+  <description>A product type for mp3 audio files.</description>
+  <metExtractors>
+    <extractor
+   class="org.apache.oodt.cas.filemgr.metadata.extractors.CoreMetExtractor">
+      <configuration>
+        <property name="nsAware" value="true" />
+        <property name="elementNs" value="CAS" />
+        <property name="elements"
+              value="ProductReceivedTime,ProductName,ProductId" />
+      </configuration>
+    </extractor>
+  </metExtractors>
+</type>
+]]></source>
+    
+    <p>Next, we will create a number of elements in the <code>elements.xml</code>
+    file. There will be an element node for each of the metadata elements we
+    want to associate with MP3 products. We can do this be adding the following 
+    as children nodes of <code>&lt;cas:elements&gt;</code> tag:</p>
+ 
+<source><![CDATA[     
+<element id="urn:example:FileLocation" name="FileLocation">
+  <dcElement/>
+  <description/>
+</element>
+<element id="urn:example:ProductType" name="ProductType">
+  <dcElement/>
+  <description/>
+</element>
+<element id="urn:example:Author" name="Author">
+  <dcElement/>
+  <description/>
+</element>
+<element id="urn:example:Filename" name="Filename">
+  <dcElement/>
+  <description/>
+</element>
+<element id="urn:example:resourceName" name="resourceName">
+  <dcElement/>
+  <description/>
+</element>
+<element id="urn:example:title" name="title">
+  <dcElement/>
+  <description/>
+</element>
+<element id="urn:example:Content-Type" name="tContent-Type">
+  <dcElement/>
+  <description/>
+</element> 
+]]></source>    
+
+    <p>After we have configured the new metadata elements, we will need to map 
+    these elements to our MP3 product. We do this by editing the 
+    <code>product-type-element-map.xml</code> file in the <code>policy/mp3</code>
+    directory to add the following as a child node to 
+    <code>&lt;cas:producttypemap&gt;</code>:</p>
+    
+<source><![CDATA[       
+<type id="urn:example:MP3">
+  <element id="urn:example:FileLocation"/>
+  <element id="urn:example:ProductType"/>
+  <element id="urn:example:Author"/>
+  <element id="urn:example:Filename"/>
+  <element id="urn:example:resourceName"/>
+  <element id="urn:example:title"/>
+  <element id="urn:example:Content-Type"/> 
+</type>
+]]></source> 
+    
+    <p>A final configuration step will be to create the archive area for the 
+    CAS-Filemgr (You'll remember that we set the repository path for MP3 products 
+    in the <code>product-types.xml</code> file). In order to do this, we will just 
+    make the directory:</p>
+    
+    <source>
+> mkdir /usr/local/archive
+    </source>
+    
+    <p>We will now start the CAS-Filemgr instance. This instance will run on
+    port 9000 by default. In order to start the Filemgr, we will issue the 
+    following commands:</p>
+    
+    <source>
+> cd /usr/local/src/cas-filemgr-1.8.0/bin
+> ./filemgr start
+    </source>
+    
+    <p>Now that we have started the CAS-Filemgr, we will need to configure the
+    CAS-Curator to use this Filemgr instance. In order to do this, we will add
+    the following parameters to the CAS-Curator context file:</p>
+    
+<source><![CDATA[    
+<Parameter name="org.apache.oodt.cas.fm.url"
+        value="http://localhost:9000"/>
+            
+<Parameter name="org.apache.oodt.cas.curator.dataDefinition.uploadPath"
+        value="/usr/local/src/cas-filemgr-1.8.0/policy" />
+
+<Parameter name="org.apache.oodt.cas.curator.fmProps"
+        value="/usr/local/src/cas-filemgr-1.8.0/etc/filemgr.properties"/>        
+]]></source>    
+    
+    <p>Once we restart Tomcat, the CAS-Curator will now recognize the policy
+    and properties of the configured CAS-Filemgr instance and use this 
+    instance during the ingest process.</p>
+    
+    <img src="../images/basic_filemgr.jpg"/>
+    
+    <p>From the above image, you can see that the CAS-Filemgr configuration
+    has been picked up by CAS-Curator. If you double-click on MP3 in the left
+    filemgr main pane, you will see the product types that are contained in
+    the mp3 policy: <code>GenericFile</code> which was part of the default
+    configuration, and <code>MP3</code> which we added. Clicking on MP3,
+    we bring up the ingest interface in the right filemgr main pane.</p> 
+    
+    <img src="../images/basic_ingest.jpg"/>
+    
+    <p>Once we drag the Bach-SuiteNo2.mp3 from the staging pane to the green
+    box in the right filemgr main pane, we can then select a metadata extractor
+    from the pulldown menu and click on the "Save as Ingestion Task." This will
+    add the Ingest task to the bottom pane as illustrated in the above 
+    screenshot. In order to test file ingestion, we will click on the "Start"
+    button.</p>
+    
+    <p>As a final step, we will confirm that the mp3 file was archived. We 
+    can do this by listing the archive:</p>
+    
+    <source>
+> ls -lR /usr/local/archive
+total 0
+drwxr-xr-x  3 -  - 102 Nov 27 23:53 Bach-SuiteNo2.mp3
+
+/usr/local/archive//Bach-SuiteNo2.mp3:
+total 9344
+-rw-r--r--  1 -  -  4781079 Nov 25 20:14 Bach-SuiteNo2.mp3
+    </source>
+    
+    <p>Worth noting is the fact that our configuration of the CAS-Filemgr
+    included a selection of the <code>BasicVersioner</code> as the MP3 
+    product type versioner. This means that mp3s are placed at
+    [archive_base]/[filename]/[filename] during ingest.</p>
+    
+    <p>We have now completed a base configuration of the CAS-Curator. In
+    the <a href="../user/advanced.html">Advanced Guide</a>, we will cover 
+    topics like changing the look and feel of the Curator, and security 
+    configuration.</p>
+    
+    </section>
+  </body>
+</document>
diff --git a/0.8.1-rc1/docker/Dockerfile b/0.8.1-rc1/docker/Dockerfile
new file mode 100644
index 0000000..708e9bc
--- /dev/null
+++ b/0.8.1-rc1/docker/Dockerfile
@@ -0,0 +1,22 @@
+FROM ubuntu:latest
+MAINTAINER Tom Barber
+
+ENV JAVA_HOME /usr/lib/jvm/java-7-openjdk-amd64/
+
+RUN sudo apt-get update 
+RUN sudo apt-get install -y openjdk-7-jre-headless openjdk-7-jre maven curl
+#RUN sudo apt-get install maven2
+WORKDIR /usr/src
+
+RUN curl -s http://svn.apache.org/repos/asf/oodt/trunk/mvn/archetypes/radix/src/main/resources/bin/radix | bash
+RUN mv oodt oodt-src; cd oodt-src; mvn package
+RUN mkdir /usr/src/oodt; tar -xvf /usr/src/oodt-src/distribution/target/oodt-distribution-0.1-bin.tar.gz -C /usr/src/oodt
+
+EXPOSE 8080
+EXPOSE 9000
+EXPOSE 2001
+EXPOSE 9001
+EXPOSE 9200
+EXPOSE 9002
+
+CMD cd /usr/src/oodt/bin/ && ./oodt start && tail -f /usr/src/oodt/tomcat/logs/catalina.out 
diff --git a/0.8.1-rc1/filemgr/pom.xml b/0.8.1-rc1/filemgr/pom.xml
new file mode 100644
index 0000000..0cf149a
--- /dev/null
+++ b/0.8.1-rc1/filemgr/pom.xml
@@ -0,0 +1,324 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>cas-filemgr</artifactId>
+  <name>Catalog and Archive File Management Component</name>
+  <description>The file management component of a Catalog and Archive Service. This component
+     purposefully separates data stores and metadata stores as standard interfaces, and
+     provides some out of the box backend implementations of them (including one based
+     on the javax.sql.DataSource interface). This component provides everything that you need
+     to catalog, archive and manage files, and directories, and their associated metadata.</description>
+  <scm>
+   	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/filemgr</connection>
+   	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/filemgr</developerConnection>
+   	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/filemgr</url>
+  </scm>
+  <build>
+    <directory>target</directory>
+    <outputDirectory>target/classes</outputDirectory>
+    <finalName>${project.artifactId}-${project.version}</finalName>
+      <testOutputDirectory>target/test-classes</testOutputDirectory>
+      <testSourceDirectory>src/test/java</testSourceDirectory>
+      <sourceDirectory>src/main/java</sourceDirectory>
+      <resources>
+        <resource>
+          <directory>${project.basedir}/src/main/resources</directory>
+          <filtering>true</filtering>
+          <excludes>
+            <exclude>**/*</exclude>
+          </excludes>
+        </resource>
+      </resources>
+      <testResources>
+        <testResource>
+        <directory>${project.basedir}/src/test/resources</directory>
+        <includes>
+          <include>**/*</include>
+        </includes>
+        <!--targetPath>${project.basedir}/target/classes/</targetPath-->
+      </testResource>
+    </testResources>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <groupId>org.apache.maven.plugins</groupId>
+        <configuration>
+          <!--forkMode>pertest</forkMode-->
+          <forkMode>none</forkMode> <!-- so we can DEBUG -->
+          <argLine>-enableassertions</argLine>
+          <useSystemClassLoader>false</useSystemClassLoader>
+          <systemProperties>
+             <property>
+               <name>java.util.logging.config.file</name>
+               <value>src/test/resources/test.logging.properties</value>
+             </property>
+           </systemProperties>
+           <forkedProcessTimeoutInSeconds>0</forkedProcessTimeoutInSeconds>
+           <redirectTestOutputToFile>true</redirectTestOutputToFile>
+            <includes>
+              <include>**/*Test*.java</include>
+            </includes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-2</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/assembly/assembly.xml</descriptor>
+          </descriptors>
+          <archive>
+            <manifest>
+              <mainClass>org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient</mainClass>
+            </manifest>
+          </archive>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>audit</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>rat-maven-plugin</artifactId>
+            <configuration>
+              <excludes>
+                <exclude>**/testdata/*</exclude>
+                <exclude>**/testdata/**/*</exclude>
+              </excludes>
+            </configuration>
+            <executions>
+              <execution>
+                <phase>verify</phase>
+                <goals>
+                  <goal>check</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+  <repositories>
+    <repository>
+        <snapshots>
+            <enabled>true</enabled>
+        </snapshots>
+        <releases>
+            <enabled>true</enabled>
+        </releases>
+        <id>sonatype-nexus</id>
+        <url>https://oss.sonatype.org/content/groups/public</url>
+    </repository>
+  </repositories>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-commons</artifactId>
+      <version>${project.parent.version}</version>    
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-metadata</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-cli</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>   
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-core</artifactId>
+      <version>3.0.5.RELEASE</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-beans</artifactId>
+      <version>3.0.5.RELEASE</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+      <version>3.0.5.RELEASE</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-expression</artifactId>
+      <version>3.0.5.RELEASE</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>10.0.1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.0.3</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+      <version>3.0</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <version>1.3</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-dbcp</groupId>
+      <artifactId>commons-dbcp</artifactId>
+      <version>1.2.1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+      <version>2.1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-pool</groupId>
+      <artifactId>commons-pool</artifactId>
+      <version>1.2</version>
+    </dependency>  
+    <dependency>
+      <groupId>commons-cli</groupId>    
+      <artifactId>commons-cli</artifactId>
+      <version>1.2</version>
+    </dependency> 
+    <dependency>
+        <groupId>org.apache.solr</groupId>
+        <artifactId>solr-solrj</artifactId>
+        <version>1.3.0</version>
+        <exclusions>
+          <exclusion>
+            <groupId>org.apache.lucene</groupId>
+            <artifactId>lucene-core</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.apache.solr</groupId>
+            <artifactId>solr-lucene-core</artifactId>
+          </exclusion>
+        </exclusions>
+    </dependency>
+    <dependency>
+        <groupId>org.apache.solr</groupId>
+        <artifactId>solr-core</artifactId>
+        <version>1.3.0</version>
+        <exclusions>
+          <exclusion>
+            <groupId>org.apache.lucene</groupId>
+            <artifactId>lucene-core</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.apache.solr</groupId>
+            <artifactId>solr-lucene-core</artifactId>
+          </exclusion>
+          <exclusion>
+            <artifactId>wstx-asl</artifactId>
+            <groupId>woodstox</groupId>
+          </exclusion>
+        </exclusions>
+        <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.lucene</groupId>
+      <artifactId>lucene-core</artifactId>
+      <version>2.0.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.safehaus.jug</groupId>
+      <artifactId>jug</artifactId>
+      <version>2.0.0</version>
+      <classifier>asl</classifier>
+    </dependency>
+    <dependency>
+      <groupId>xmlrpc</groupId>
+      <artifactId>xmlrpc</artifactId>
+      <version>2.0.1</version>
+    </dependency>
+    <dependency>
+      <groupId>hsqldb</groupId>
+      <artifactId>hsqldb</artifactId>
+      <version>1.8.0.7</version>
+    </dependency>
+    <dependency>
+      <groupId>org.python</groupId>
+      <artifactId>jython</artifactId>
+      <version>2.2-beta1</version>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>mysql</groupId>
+      <artifactId>mysql-connector-java</artifactId>
+      <version>5.1.26</version>
+      <scope>test</scope>
+    </dependency>
+	<dependency>
+      <groupId>com.amazonaws</groupId>
+      <artifactId>aws-java-sdk</artifactId>
+      <version>1.7.4</version>
+	</dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.8.1</version>
+      <scope>test</scope>
+    </dependency>
+	<dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <version>1.9.5</version>
+      <scope>test</scope>
+	</dependency>
+	<dependency>
+	  <groupId>org.hamcrest</groupId>
+	  <artifactId>hamcrest-all</artifactId>
+	  <version>1.3</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/filemgr/src/main/assembly/assembly.xml b/0.8.1-rc1/filemgr/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..db50901
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/assembly/assembly.xml
@@ -0,0 +1,97 @@
+<!-- 
+/*
+ * 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.
+ */
+
+$Id$
+-->

+<assembly>

+  <id>dist</id>

+  <formats>

+    <format>tar.gz</format>
+    <format>zip</format>

+  </formats>
+  <includeBaseDirectory>true</includeBaseDirectory>
+  <baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>

+  <fileSets>

+    <fileSet>

+      <directory>${basedir}</directory>

+      <outputDirectory>.</outputDirectory>

+      <includes>

+        <include>LICENSE.txt</include>

+        <include>CHANGES.txt</include>

+      </includes>

+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/bin</directory>
+      <outputDirectory>bin</outputDirectory>
+      <includes/>
+      <fileMode>755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>logs</outputDirectory>
+      <includes>
+        <include>REMOVE.log</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>etc</outputDirectory>
+      <includes>
+        <include>filemgr.properties</include>
+        <include>logging.properties</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>etc</outputDirectory>
+      <includes>
+        <include>mime-types.xml</include>
+        <include>schema.xml</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>policy</outputDirectory>
+      <includes>
+        <include>cmd-line-actions.xml</include>
+        <include>cmd-line-options.xml</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/examples</directory>
+      <outputDirectory>policy</outputDirectory>
+      <includes/>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>

+  </fileSets>

+  <dependencySets>

+    <dependencySet>

+      <outputDirectory>lib</outputDirectory>

+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>

+      <unpackOptions/>

+    </dependencySet>

+  </dependencySets>

+</assembly>

diff --git a/0.8.1-rc1/filemgr/src/main/bin/convert_map b/0.8.1-rc1/filemgr/src/main/bin/convert_map
new file mode 100755
index 0000000..e2c8082
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/bin/convert_map
@@ -0,0 +1,22 @@
+#!/bin/bash
+#/*
+# * 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.
+# */
+#
+# Usage: convert_map [product-type-element-map.xml]
+
+awk '{FS="\""} /parent/ {print "  <type id=\"" $2 "\">"; print "      <parent id=\"" $4 "\"/>"} \
+    $0!~/parent/ {print $0}' $1
diff --git a/0.8.1-rc1/filemgr/src/main/bin/filemgr b/0.8.1-rc1/filemgr/src/main/bin/filemgr
new file mode 100644
index 0000000..2049ded
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/bin/filemgr
@@ -0,0 +1,92 @@
+#!/bin/sh
+#/*
+# * 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.
+# */
+#
+# init script for XmlRpcFileManager
+#
+# chkconfig: 345 88 22
+# description: CAS File Manager
+#
+
+[ -f /etc/sysconfig/java ] && . /etc/sysconfig/java
+
+SERVER_PORT=9000
+export SERVER_PORT
+
+if [ -z $JAVA_HOME ] ; then
+	JAVA_HOME=/path/to/java/home
+else
+	JAVA_HOME=${JAVA_HOME}
+fi
+
+export JAVA_HOME
+CAS_FILEMGR_HOME=..
+export CAS_FILEMGR_HOME
+RUN_HOME=${CAS_FILEMGR_HOME}/../run
+export RUN_HOME
+CAS_FILEMGR_PROPS=../etc/filemgr.properties
+export CAS_FILEMGR_PROPS
+
+PATH=${JAVA_HOME}/bin:${CAS_FILEMGR_HOME}/bin:/usr/bin:/bin:/usr/sbin:/sbin
+export PATH
+
+## make sure that casfile manager has a run directory
+## just to be on the safe side
+mkdir -p ${RUN_HOME}
+
+for file in `find ../lib/*.jar`; do
+     LIB_DEPS="${file}:${LIB_DEPS}"
+done
+
+# See how we were called.
+case "$1" in
+  start)
+        echo -n "Starting cas file manager: "
+        $JAVA_HOME/bin/java \
+        	-cp ${LIB_DEPS} \
+        	-Djava.util.logging.config.file=${CAS_FILEMGR_HOME}/etc/logging.properties \
+    	    -Dorg.apache.oodt.cas.filemgr.properties=${CAS_FILEMGR_PROPS} \
+        	org.apache.oodt.cas.filemgr.system.XmlRpcFileManager \
+        	--portNum $SERVER_PORT &       
+        echo $! > ${RUN_HOME}/cas.filemgr.pid 
+        echo "OK"
+        sleep 5
+        ;;
+  stop)
+        echo -n "Shutting down cas file manager: "
+        kill `cat ${RUN_HOME}/cas.filemgr.pid`
+        rm -f ${RUN_HOME}/cas.filemgr.pid
+        echo "OK"
+        ;;
+  restart)
+        $0 stop
+        $0 start
+        ;;
+  status)
+        if [ -e ${RUN_HOME}/cas.filemgr.pid ] ; then
+           pid=`cat ${RUN_HOME}/cas.filemgr.pid`
+           echo "cas filemgr is running with pid: $pid" 
+        else
+           echo "cas filemgr is not running"
+        fi
+        ;;
+  *)
+        echo "Usage: $0 {start|stop|restart|status}"
+        exit 1
+esac
+
+exit 0
diff --git a/0.8.1-rc1/filemgr/src/main/bin/filemgr-client b/0.8.1-rc1/filemgr/src/main/bin/filemgr-client
new file mode 100644
index 0000000..13c67dd
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/bin/filemgr-client
@@ -0,0 +1,37 @@
+#!/bin/sh
+#/*
+# * 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.
+# */
+#
+if [ -z $JAVA_HOME ] ; then
+	JAVA_HOME=/path/to/java/home
+else
+	JAVA_HOME=${JAVA_HOME}
+fi
+
+export JAVA_HOME
+
+for file in `find ../lib/*.jar`; do
+     LIB_DEPS="${file}:${LIB_DEPS}"
+done
+
+$JAVA_HOME/bin/java \
+	-cp ${LIB_DEPS} \
+	-Dorg.apache.oodt.cas.filemgr.properties=../etc/filemgr.properties \
+	-Djava.util.logging.config.file=../etc/logging.properties \
+	-Dorg.apache.oodt.cas.cli.action.spring.config=../policy/cmd-line-actions.xml \
+	-Dorg.apache.oodt.cas.cli.option.spring.config=../policy/cmd-line-options.xml \
+	org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient $*
diff --git a/0.8.1-rc1/filemgr/src/main/bin/migrate_xml_policy b/0.8.1-rc1/filemgr/src/main/bin/migrate_xml_policy
new file mode 100755
index 0000000..433197f
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/bin/migrate_xml_policy
@@ -0,0 +1,62 @@
+#!/usr/bin/env perl
+#/*
+# * 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.
+# */
+#
+# this tool migrates cas-filemgr 1.6 format specific to the versioner
+# and repository path to the 1.7 format
+# Author: John Tran
+#
+# usage:
+# ./migrate_xml_policy
+# 
+# in the directory where the product-types.xml file is located.
+
+`/bin/cp product-types.xml product-types.xml.save`;
+
+open(FP_IN, 'product-types.xml.save');
+open(FP_OUT, '>product-types.xml');
+
+while(<FP_IN>) {
+  $line = $_;
+  
+  if (/versionerClass/) {
+     $v = &GiveMeClean($line);
+     print FP_OUT "   <versioner class=\"$v\" />\n";
+  } elsif (/repositoryPath/) {
+     $p = &GiveMeClean($line);
+     print FP_OUT "   <repository path=\"$p\" />\n";
+  } else {
+     print FP_OUT $line;
+  }
+
+}
+
+close FP_IN;
+close FP_OUT;
+
+1;
+
+sub GiveMeClean {
+   $line = shift;
+   $line =~ s/\s//g;
+   $line =~ s/\>/ /g;
+   $line =~ s/\</ /g;
+
+   @a = split(/ /, $line);
+   print "LINE: $line \n";
+   return $a[2];
+}
diff --git a/0.8.1-rc1/filemgr/src/main/bin/query_tool b/0.8.1-rc1/filemgr/src/main/bin/query_tool
new file mode 100644
index 0000000..f6610cf
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/bin/query_tool
@@ -0,0 +1,23 @@
+#!/bin/sh
+#/*
+# * 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.
+# */
+#
+############ README - IMPORTANT ############
+# NOTE: This has been deprecated... use SqlQuery and LuceneQuery actions instead.
+############################################
+
+$JAVA_HOME/bin/java -Djava.ext.dirs=../lib org.apache.oodt.cas.filemgr.tools.QueryTool "$@"
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/Catalog.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/Catalog.java
new file mode 100644
index 0000000..1ebca26
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/Catalog.java
@@ -0,0 +1,340 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.util.Pagination;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Catalog is the front end object interface for a back end peristance layer
+ * for storing product references and metadata. Classes implementing this
+ * interface implement methods to retrieve and store product references and
+ * metadata from a particular backend repository.
+ * </p>
+ * 
+ */
+public interface Catalog extends Pagination {
+
+    public final static String X_POINT_ID = Catalog.class.getName();
+
+    /**
+     * <p>
+     * Ingests {@link Metadata} into the metadata store, and associates it with
+     * the given <code>productId</code>.
+     * </p>
+     * 
+     * @param m
+     *            The {@link Metadata} to ingest.
+     * @param product
+     *            The product to add the metadata for.
+     * @throws CatalogException
+     *             If any general error occurs.
+     */
+    public void addMetadata(Metadata m, Product product)
+            throws CatalogException;
+
+    /**
+     * <p>
+     * Removes {@link Metadata} from the metadata store, and disassociates it
+     * from the given <code>productId</code>.
+     * </p>
+     * 
+     * @param m
+     *            The {@link Metadata} to remove.
+     * @param product
+     *            The product for which the metadata is to be removed.
+     * @throws CatalogException
+     *             If any general error occurs.
+     */
+    public void removeMetadata(Metadata m, Product product)
+            throws CatalogException;
+
+    /**
+     * <p>
+     * Adds a Product to the Catalog.
+     * </p>
+     * 
+     * @param product
+     *            The {@link Product} to add.
+     * @throws CatalogException
+     *             If any error occurs during the add.
+     */
+    public void addProduct(Product product) throws CatalogException;
+
+    /**
+     * <p>
+     * Modifies an existing Product within the Catalog.
+     * </p>
+     * 
+     * @param product
+     *            The new {@link Product} information to modify the existing
+     *            Product with.
+     * @throws CatalogException
+     *             If any error occurs.
+     */
+    public void modifyProduct(Product product) throws CatalogException;
+
+    /**
+     * <p>
+     * Removes a {@link Product} from the Catalog.
+     * </p>
+     * 
+     * @param product
+     *            The product to remove.
+     * @throws CatalogException
+     *             If any error occurs.
+     */
+    public void removeProduct(Product product) throws CatalogException;
+
+    /**
+     * <p>
+     * Persists the <code>transferStatus</code> attribute of the given
+     * {@link Product} to the Catalog.
+     * 
+     * @param product
+     *            The Product whose transfer status will be persisted. The
+     *            caller should make sure that the product ID field is set.
+     * @throws CatalogException
+     */
+    public void setProductTransferStatus(Product product)
+            throws CatalogException;
+
+    /**
+     * <p>
+     * Adds the specified {@link List} of {@link Reference}s to the
+     * {@link Catalog}, and associates them with this {@link Product} specified
+     * by its <code>productId</code>.
+     * </p>
+     * 
+     * @param product
+     *            The product to add references for. The references are read
+     *            from the Products list of References.
+     * @throws CatalogException
+     *             If anything goes wrong.
+     */
+    public void addProductReferences(Product product) throws CatalogException;
+
+    /**
+     * <p>
+     * Gets a {@link Product}, with the specified <code>productId</code>.
+     * </p>
+     * 
+     * @param productId
+     *            The unique ID of the Product to retrieve.
+     * @return A {@link Product}, with the given ID. The implementer of this
+     *         method should ensure that the product {@link Reference}s are
+     *         populated as well.
+     * @throws CatalogException
+     *             If any error occurs.
+     */
+    public Product getProductById(String productId) throws CatalogException;
+
+    /**
+     * <p>
+     * Gets a {@link Product} with the specified <code>productName</code>.
+     * </p>
+     * 
+     * @param productName
+     *            The name of the Product to retrieve.
+     * @return A {@link Product} with the given name. The implementer of this
+     *         method should ensure that the product {@link Reference}s are
+     *         populated as well.
+     * @throws CatalogException
+     */
+    public Product getProductByName(String productName) throws CatalogException;
+
+    /**
+     * <p>
+     * Gets the {@link Reference}s associated with this Product.
+     * </p>
+     * 
+     * @param product
+     *            The {@link Product} to obtain the References for.
+     * @return A {@link List} of {@link Reference}s, associated with the
+     *         specified Product.
+     * @throws CatalogException
+     */
+    public List<Reference> getProductReferences(Product product) throws CatalogException;
+
+    /**
+     * <p>
+     * Gets all the {@link Product}s in the {@link Catalog}.
+     * </p>
+     * 
+     * @return A {@link List} of {@link Product}s in the {@link Catalog}.
+     * @throws CatalogException
+     *             If any error occurs.
+     */
+    public List<Product> getProducts() throws CatalogException;
+
+    /**
+     * <p>
+     * Gets the {@link Product}s associated with the specified ProductType in
+     * the {@link Catalog}.
+     * </p>
+     * 
+     * @param type
+     *            The {@link ProductType} to obtain the {@link Product}s for.
+     * @return A {@link List} of {@link Product}s that are associated with the
+     *         specified productType in the {@link Catalog}.
+     * @throws CatalogException
+     *             If any error occurs.
+     */
+    public List<Product> getProductsByProductType(ProductType type)
+            throws CatalogException;
+
+    /**
+     * <p>
+     * Gets the Metadata for a given Product.
+     * </p>
+     * 
+     * @param product
+     *            The {@link Product} to obtain the Metadata for.
+     * @return The {@link Metadata} for the given <code>productId</code>.
+     *         </p>
+     * @throws CatalogException
+     *             If any error occurs.
+     */
+    public Metadata getMetadata(Product product) throws CatalogException;
+
+    /**
+     * <p>
+     * Gets a reduced set of metadata for a give Product.
+     * </p>
+     * 
+     * @param product
+     *            The {@link Product} to obtain the Metadata for.
+     * @param elements
+     *            The set of metadata elements of interest.
+     * @return The reduced {@link Metadata} for the given <code>productId</code>.
+     * @throws CatalogException
+     *             If any error occurs.
+     */
+    public Metadata getReducedMetadata(Product product, List<String> elements)
+            throws CatalogException;
+
+    /**
+     * <p>
+     * Queries the Catalog with the specified {@link Query}
+     * </p>.
+     * 
+     * @param query
+     *            The set of criteria by which to query the Catalog.
+     * @param type
+     *            The {@link ProductType} that should be queried.
+     * @return A {@link List} of String product IDs that can be used to retrieve
+     *         products that match the query.
+     * @throws CatalogException
+     *             If any error occurs.
+     */
+    public List<String> query(Query query, ProductType type) throws CatalogException;
+
+    /**
+     * <p>
+     * Performs a query against the underlying {@link Catalog}, and then
+     * properly formulates a page of results to send back to the user. This
+     * method is useful when you would like to conserve memory and not send back
+     * the entire list of results, nor load them into memory. Of course, this
+     * method assumes that queries are deterministic, i.e., the same query
+     * issued 2x within a paginating session will produce the same set of
+     * results to paginate.
+     * </p>
+     * 
+     * @param query
+     *            The query to perform against the underlying Catalog.
+     * @param type
+     *            The {@link ProductType} that you are querying for.
+     * @param pageNum
+     *            The number of the {@link ProductPage} to return back to the
+     *            user.
+     * @return The requested {@link ProductPage} of results.
+     * @throws CatalogException
+     *             If any error occurs.
+     */
+    public ProductPage pagedQuery(Query query, ProductType type, int pageNum)
+            throws CatalogException;
+
+    /**
+     * <p>
+     * Gets the top <code>N</code> most recent products that have been
+     * cataloged.
+     * </p>
+     * 
+     * @param n
+     *            The amount of recent products to return.
+     * @return A {@link List} of {@link Product}s that have been cataloged
+     *         recently.
+     * @throws CatalogException
+     *             If any error occurs.
+     */
+    public List<Product> getTopNProducts(int n) throws CatalogException;
+
+    /**
+     * <p>
+     * Gets the top <code>N</code> most recent products that have been
+     * cataloged for the given {@link ProductType}.
+     * </p>
+     * 
+     * @param n
+     *            The amount of recent products to return.
+     * @param type
+     *            The ProductType to limit the query to.
+     * @return A {@link List} of {@link Product}s that have been cataloged
+     *         recently.
+     * @throws CatalogException
+     *             If any error occurs.
+     */
+    public List<Product> getTopNProducts(int n, ProductType type)
+            throws CatalogException;
+
+    /**
+     * 
+     * @return The {@link ValidationLayer} that is used by this Catalog.
+     * @throws CatalogException
+     *             If any error occurs (e.g., the layer isn't initialized).
+     */
+    public ValidationLayer getValidationLayer() throws CatalogException;
+
+    /**
+     * 
+     * @param type
+     *            The ProductType to count the number of products for.
+     * @return An integer count of the number of {@link Product}s for the
+     *         specified {@link ProductType}.
+     * @throws CatalogException
+     *             If any error occurs.
+     */
+    public int getNumProducts(ProductType type) throws CatalogException;
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/CatalogFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/CatalogFactory.java
new file mode 100644
index 0000000..46a0f75
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/CatalogFactory.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory interface for creating {@link Catalog}s.
+ * </p>
+ * 
+ */
+public interface CatalogFactory {
+
+	/**
+	 * @return A new {@link Catalog} object implementation.
+	 */
+	public Catalog createCatalog();
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/DataSourceCatalog.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/DataSourceCatalog.java
new file mode 100644
index 0000000..155e263
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/DataSourceCatalog.java
@@ -0,0 +1,2291 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.BooleanQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.QueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+import org.apache.oodt.cas.filemgr.util.DbStructFactory;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.commons.pagination.PaginationUtils;
+import org.apache.oodt.commons.util.DateConvert;
+
+//SPRING imports
+import org.springframework.util.StringUtils;
+
+
+
+//JDK imports
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeMap;
+import java.util.UUID;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.sql.DataSource;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @author luca
+ * @version $Revision$
+ * 
+ * <p>
+ * Implementation of a {@link Catalog} that is backed by a {@link DataSource}
+ * front-end to a SQL DBMS.
+ * </p>
+ * 
+ */
+public class DataSourceCatalog implements Catalog {
+
+    /* our sql data source */
+    protected DataSource dataSource = null;
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(DataSourceCatalog.class.getName());
+
+    /* our validation layer */
+    private ValidationLayer validationLayer = null;
+
+    /* boolean flag on whether or not product type id and element id are strings */
+    protected boolean fieldIdStringFlag = false;
+
+    /* size of pages of products within the catalog */
+    protected int pageSize = -1;
+    
+    /* flag to indicate whether the "product_id" key type should be treated as a string */
+    boolean productIdString = false;
+
+    protected boolean orderedValues = false;
+
+    /*
+     * cache of products per product type: [productTypeId]=>([ISO8601 time of
+     * last update]=>[List of products])
+     */
+    private static TreeMap<String, TreeMap<String, Object>> PRODUCT_CACHE = new TreeMap<String, TreeMap<String, Object>>();
+
+    /*
+     * the amount of minutes inbetween the time in which we should update the
+     * PRODUCT_CACHE
+     */
+    private long cacheUpdateMinutes = 0L;
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     * @throws  
+     */
+    public DataSourceCatalog(DataSource ds, ValidationLayer valLayer,
+			     boolean fieldId, int pageSize, long cacheUpdateMin, boolean productIdString, boolean orderedValues) {
+        this.dataSource = ds;
+        this.validationLayer = valLayer;
+        fieldIdStringFlag = fieldId;
+        this.pageSize = pageSize;
+        cacheUpdateMinutes = cacheUpdateMin;
+        this.productIdString = productIdString;
+        this.orderedValues = orderedValues;
+    }
+    
+    /**
+     * Constructor that assumes productIdString=false
+     * to support current subclasses.
+     * @param ds
+     * @param valLayer
+     * @param fieldId
+     * @param pageSize
+     * @param cacheUpdateMin
+     */
+    public DataSourceCatalog(DataSource ds, ValidationLayer valLayer,
+        boolean fieldId, int pageSize, long cacheUpdateMin) {
+    	this(ds, valLayer, fieldId, pageSize, cacheUpdateMin, false, false);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#addMetadata(org.apache.oodt.cas.metadata.Metadata,
+     *      org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void addMetadata(Metadata m, Product product)
+            throws CatalogException {
+        List<Element> metadataTypes = null;
+
+        try {
+            metadataTypes = validationLayer.getElements(product
+                    .getProductType());
+        } catch (ValidationLayerException e) {
+            e.printStackTrace();
+            throw new CatalogException(
+                    "ValidationLayerException when trying to obtain element list for product type: "
+                            + product.getProductType().getName()
+                            + ": Message: " + e.getMessage());
+        }
+
+        for (Iterator<Element> i = metadataTypes.iterator(); i.hasNext();) {
+            Element element = i.next();
+            List<String> values = m.getAllMetadata(element.getElementName());
+
+            if (values == null) {
+                LOG.log(Level.WARNING, "No Metadata specified for product ["
+                        + product.getProductName() + "] for required field ["
+                        + element.getElementName()
+                        + "]: Attempting to continue processing metadata");
+                continue;
+            }
+
+            for (Iterator<String> j = values.iterator(); j.hasNext();) {
+                String value = j.next();
+
+                try {
+                    addMetadataValue(element, product, value);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    LOG
+                            .log(
+                                    Level.WARNING,
+                                    "Exception ingesting metadata. Error inserting field: ["
+                                            + element.getElementId()
+                                            + "=>"
+                                            + value
+                                            + "]: for product: ["
+                                            + product.getProductName()
+                                            + "]: Message: "
+                                            + e.getMessage()
+                                            + ": Attempting to continue processing metadata");
+                }
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#addMetadata(org.apache.oodt.cas.metadata.Metadata,
+     *      org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void removeMetadata(Metadata m, Product product)
+            throws CatalogException {
+        List<Element> metadataTypes = null;
+
+        try {
+            metadataTypes = validationLayer.getElements(product
+                    .getProductType());
+        } catch (ValidationLayerException e) {
+            e.printStackTrace();
+            throw new CatalogException(
+                    "ValidationLayerException when trying to obtain element list for product type: "
+                            + product.getProductType().getName()
+                            + ": Message: " + e.getMessage());
+        }
+
+        for (Iterator<Element> i = metadataTypes.iterator(); i.hasNext();) {
+            Element element = i.next();
+            List<String> values = m.getAllMetadata(element.getElementName());
+
+            if (values != null) {
+                for (Iterator<String> j = values.iterator(); j.hasNext();) {
+                    String value = j.next();
+
+                    try {
+                        removeMetadataValue(element, product, value);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        LOG
+                                .log(
+                                        Level.WARNING,
+                                        "Exception removing metadata. Error deleting field: ["
+                                                + element.getElementId()
+                                                + "=>"
+                                                + value
+                                                + "]: for product: ["
+                                                + product.getProductName()
+                                                + "]: Message: "
+                                                + e.getMessage()
+                                                + ": Attempting to continue processing metadata");
+                    }
+                }
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#addProduct(org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void addProduct(Product product)
+            throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String addProductSql = null;
+            String productTypeIdStr = null;
+
+            if (fieldIdStringFlag) {
+                productTypeIdStr = "'"
+                        + product.getProductType().getProductTypeId() + "'";
+            } else {
+                productTypeIdStr = product.getProductType().getProductTypeId();
+            }
+
+						if (productIdString==false) {
+							
+	            addProductSql = "INSERT INTO products (product_name, product_structure, product_transfer_status, product_type_id) "
+	                + "VALUES ('"
+	                + product.getProductName()
+	                + "', '"
+	                + product.getProductStructure()
+	                + "', '"
+	                + product.getTransferStatus()
+	                + "', "
+	                + productTypeIdStr
+	                + ")";
+
+				        LOG.log(Level.FINE, "addProduct: Executing: " + addProductSql);
+				        statement.execute(addProductSql);
+				
+				        // read "product_id" value that was automatically assigned by the database
+				        String productId = new String();
+				
+				        String getProductIdSql = "SELECT MAX(product_id) AS max_id FROM products";
+				
+				        rs = statement.executeQuery(getProductIdSql);
+				
+				        while (rs.next()) {
+				            productId = String.valueOf(rs.getInt("max_id"));
+				        }
+				        
+		            product.setProductId(productId);
+		            conn.commit();
+							
+						} else {
+							
+							// reuse the existing product id if possible, or generate a new UUID string
+            	String productId = product.getProductId();
+            	if (!StringUtils.hasText(productId)) productId = UUID.randomUUID().toString();
+            	// insert product in database
+            	addProductSql = "INSERT INTO products (product_id, product_name, product_structure, product_transfer_status, product_type_id, product_datetime) "
+                    + "VALUES ('"
+                    + productId
+                    + "', '"
+                    + product.getProductName()
+                    + "', '"
+                    + product.getProductStructure()
+                    + "', '"
+                    + product.getTransferStatus()
+                    + "', "
+                    + productTypeIdStr
+                    +", now()"
+                    + ")";                       
+
+            	LOG.log(Level.FINE, "addProduct: Executing: " + addProductSql);
+            	statement.execute(addProductSql);
+            	
+              product.setProductId(productId);
+              conn.commit();
+
+						}
+
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception adding product. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback addProduct transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#modifyProduct(org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void modifyProduct(Product product)
+            throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String modifyProductSql = "UPDATE products SET product_name='"
+                    + product.getProductName() + "', product_structure='"
+                    + product.getProductStructure()
+                    + "', product_transfer_status='"
+                    + product.getTransferStatus() + "' "
+                    + "WHERE product_id = " + quoteIt(product.getProductId());
+
+            LOG
+                    .log(Level.FINE, "modifyProduct: Executing: "
+                            + modifyProductSql);
+            statement.execute(modifyProductSql);
+            conn.commit();
+
+            // now update the refs
+            updateReferences(product);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception modifying product. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback modifyProduct transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#removeProduct(org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void removeProduct(Product product)
+            throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String deleteProductSql = "DELETE FROM products WHERE product_id = "
+                    + quoteIt(product.getProductId());
+
+            LOG
+                    .log(Level.FINE, "removeProduct: Executing: "
+                            + deleteProductSql);
+            statement.execute(deleteProductSql);
+            deleteProductSql = "DELETE FROM "
+                    + product.getProductType().getName() + "_metadata "
+                    + " WHERE product_id = " + quoteIt(product.getProductId());
+            LOG
+                    .log(Level.FINE, "removeProduct: Executing: "
+                            + deleteProductSql);
+            statement.execute(deleteProductSql);
+            deleteProductSql = "DELETE FROM "
+                    + product.getProductType().getName() + "_reference "
+                    + " WHERE product_id = " + quoteIt(product.getProductId());
+            LOG
+                    .log(Level.FINE, "removeProduct: Executing: "
+                            + deleteProductSql);
+            statement.execute(deleteProductSql);
+            conn.commit();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception removing product. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback removeProduct transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#setProductTransferStatus(org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void setProductTransferStatus(Product product)
+            throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String modifyProductSql = "UPDATE products SET product_transfer_status='"
+                    + product.getTransferStatus()
+                    + "' "
+                    + "WHERE product_id = " + quoteIt(product.getProductId());
+
+            LOG.log(Level.FINE, "setProductTransferStatus: Executing: "
+                    + modifyProductSql);
+            statement.execute(modifyProductSql);
+            conn.commit();
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception setting transfer status for product. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback setProductTransferStatus transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#addProductReferences(org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void addProductReferences(Product product)
+            throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        String productRefTable = product.getProductType().getName()
+                + "_reference";
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            for (Iterator<Reference> i = product.getProductReferences().iterator(); i
+                    .hasNext();) {
+                Reference r = i.next();
+
+                String addRefSql = "INSERT INTO "
+                        + productRefTable
+                        + " "
+                        + "(product_id, product_orig_reference, product_datastore_reference, product_reference_filesize, product_reference_mimetype) "
+                        + "VALUES ("
+                        + quoteIt(product.getProductId())
+                        + ", '"
+                        + r.getOrigReference()
+                        + "', '"
+                        + r.getDataStoreReference()
+                        + "', "
+                        + r.getFileSize()
+                        + ",'"
+                        + ((r.getMimeType() == null) ? "" : r.getMimeType()
+                                .getName()) + "')";
+
+                LOG.log(Level.FINE, "addProductReferences: Executing: "
+                        + addRefSql);
+                statement.execute(addRefSql);
+            }
+
+            conn.commit();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception adding product references. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback addProductReferences transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProductById(java.lang.String)
+     */
+    public Product getProductById(String productId) throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        Product product = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getProductSql = "SELECT * " + "FROM products "
+                    + "WHERE product_id = " + quoteIt(productId);
+
+            LOG.log(Level.FINE, "getProductById: Executing: " + getProductSql);
+            rs = statement.executeQuery(getProductSql);
+
+            while (rs.next()) {
+                product = DbStructFactory.getProduct(rs, false, productIdString);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting product. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getProductById transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return product;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProductByName(java.lang.String)
+     */
+    public Product getProductByName(String productName) throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        Product product = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getProductSql = "SELECT products.* " + "FROM products "
+                    + "WHERE product_name = '" + productName + "'";
+
+            LOG
+                    .log(Level.FINE, "getProductByName: Executing: "
+                            + getProductSql);
+            rs = statement.executeQuery(getProductSql);
+
+            while (rs.next()) {
+                product = DbStructFactory.getProduct(rs, false, productIdString);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting product. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getProductByName transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return product;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProductReferences(org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public List<Reference> getProductReferences(Product product) throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        List<Reference> references = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getProductRefSql = "SELECT * FROM "
+                    + product.getProductType().getName() + "_reference"
+		+ " WHERE product_id = " + quoteIt(product.getProductId());
+
+            if(this.orderedValues) getProductRefSql += " ORDER BY pkey";
+
+            LOG.log(Level.FINE, "getProductReferences: Executing: "
+                    + getProductRefSql);
+            rs = statement.executeQuery(getProductRefSql);
+
+            references = new Vector<Reference>();
+            while (rs.next()) {
+                Reference r = DbStructFactory.getReference(rs);
+                references.add(r);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting product type. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getProductTypeById transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return references;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProducts()
+     */
+    public List<Product> getProducts() throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        List<Product> products = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getProductSql = "SELECT products.* " + "FROM products "
+                    + "ORDER BY products.product_id DESC";
+
+            LOG.log(Level.FINE, "getProducts: Executing: " + getProductSql);
+            rs = statement.executeQuery(getProductSql);
+            products = new Vector<Product>();
+
+            while (rs.next()) {
+                Product product = DbStructFactory.getProduct(rs, false, productIdString);
+                products.add(product);
+            }
+
+            if (products.size() == 0) {
+                products = null;
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting products. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getProductstransaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return products;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProductsByProductType(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public List<Product> getProductsByProductType(ProductType type)
+            throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        List<Product> products = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getProductSql = null;
+            String productTypeIdStr = null;
+
+            if (fieldIdStringFlag) {
+                productTypeIdStr = "'" + type.getProductTypeId() + "'";
+            } else {
+                productTypeIdStr = type.getProductTypeId();
+            }
+
+            getProductSql = "SELECT products.* " + "FROM products "
+                    + "WHERE products.product_type_id = " + productTypeIdStr;
+
+            LOG.log(Level.FINE, "getProductsByProductType: Executing: "
+                    + getProductSql);
+            rs = statement.executeQuery(getProductSql);
+            products = new Vector<Product>();
+
+            while (rs.next()) {
+                Product product = DbStructFactory.getProduct(rs, false, productIdString);
+                products.add(product);
+            }
+
+            if (products.size() == 0) {
+                products = null;
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting products. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getProductsByProductType transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return products;
+    }
+
+    public Metadata getMetadata(Product product) throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+        Metadata m = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String metadataSql = "SELECT * FROM "
+                    + product.getProductType().getName() + "_metadata"
+		+ " WHERE product_id = " + quoteIt(product.getProductId());
+ 
+	    if(this.orderedValues) metadataSql += " ORDER BY pkey";
+
+            LOG.log(Level.FINE, "getMetadata: Executing: " + metadataSql);
+            rs = statement.executeQuery(metadataSql);
+            
+            m = new Metadata();
+            List<Element> elements = null;
+
+            try {
+                elements = validationLayer.getElements(product.getProductType());
+            } catch (ValidationLayerException e) {
+                e.printStackTrace();
+                throw new CatalogException(
+                        "ValidationLayerException when trying to obtain element list for product type: "
+                                + product.getProductType().getName()
+                                + ": Message: " + e.getMessage());
+            }
+
+            while (rs.next()) {
+                for (Iterator<Element> i = elements.iterator(); i.hasNext();) {
+                    Element e = i.next();
+
+                    // right now, we just support STRING
+                    String elemValue = rs.getString("metadata_value");
+                    String elemId = rs.getString("element_id");
+
+                    if (elemId.equals(e.getElementId())) {
+                        elemValue = (elemValue != null ? elemValue : "");
+                        m.addMetadata(e.getElementName(), elemValue);
+                    }
+                }
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting metadata. Message: "
+                    + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return m;
+    }
+    
+    public Metadata getReducedMetadata(Product product, List<String> elems) throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+        Metadata m = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String elementIds = "";
+            if (elems.size() > 0) {
+                elementIds += " AND (element_id = '" + this.validationLayer.getElementByName(elems.get(0)).getElementId() + "'";
+                for (int i = 1; i < elems.size(); i++) 
+                    elementIds += " OR element_id = '" + this.validationLayer.getElementByName(elems.get(i)).getElementId() + "'";
+                elementIds += ")";
+            }
+            String metadataSql = "SELECT element_id,metadata_value FROM "
+                    + product.getProductType().getName() + "_metadata"
+		+ " WHERE product_id = " + quoteIt(product.getProductId()) + elementIds;
+            if(this.orderedValues) metadataSql += " ORDER BY pkey";
+
+            LOG.log(Level.FINE, "getMetadata: Executing: " + metadataSql);
+            rs = statement.executeQuery(metadataSql);
+
+            m = new Metadata();
+            List<Element> elements = null;
+
+            try {
+                elements = validationLayer.getElements(product.getProductType());
+            } catch (ValidationLayerException e) {
+                e.printStackTrace();
+                throw new CatalogException(
+                        "ValidationLayerException when trying to obtain element list for product type: "
+                                + product.getProductType().getName()
+                                + ": Message: " + e.getMessage());
+            }
+
+            while (rs.next()) {
+                for (Iterator<Element> i = elements.iterator(); i.hasNext();) {
+                    Element e = i.next();
+
+                    // right now, we just support STRING
+                    String elemValue = rs.getString("metadata_value");
+                    String elemId = rs.getString("element_id");
+
+                    if (elemId.equals(e.getElementId())) {
+                        elemValue = (elemValue != null ? elemValue : "");
+                        m.addMetadata(e.getElementName(), elemValue);
+                    }
+                }
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting metadata. Message: "
+                    + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return m;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#query(org.apache.oodt.cas.filemgr.structs.Query
+     *      org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public List<String> query(Query query, ProductType type) throws CatalogException {
+        return paginateQuery(query, type, -1);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getTopNProducts(int)
+     */
+    public List<Product> getTopNProducts(int n) throws CatalogException {
+        return getTopNProducts(n, null);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getTopNProducts(int,
+     *      org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public List<Product> getTopNProducts(int n, ProductType type)
+            throws CatalogException {
+        List<Product> products = null;
+
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+            statement.setMaxRows(n);
+
+            String getProductSql = "SELECT products.* " + "FROM products ";
+
+            if (type != null && type.getProductTypeId() != null) {
+                if (fieldIdStringFlag) {
+                    getProductSql += "WHERE products.product_type_id = '"
+                            + type.getProductTypeId() + "' ";
+                } else {
+                    getProductSql += "WHERE products.product_type_id = "
+                            + type.getProductTypeId() + " ";
+                }
+
+            }
+
+            getProductSql += "ORDER BY products.product_id DESC";
+
+            LOG.log(Level.FINE, "getTopNProducts: executing: " + getProductSql);
+
+            rs = statement.executeQuery(getProductSql);
+            products = new Vector<Product>();
+
+            while (rs.next()) {
+                Product product = DbStructFactory.getProduct(rs, false, productIdString);
+                products.add(product);
+            }
+
+            if (products.size() == 0) {
+                products = null;
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception getting top N products. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback get top N products. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return products;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getValidationLayer()
+     */
+    public ValidationLayer getValidationLayer() throws CatalogException {
+    	// note that validationLayer may be null to allow for leniency in subclasses
+    	return validationLayer;
+    }
+
+    private synchronized void addMetadataValue(Element element,
+            Product product, String value) throws CatalogException {
+
+        Connection conn = null;
+        Statement statement = null;
+
+        String metadataTable = product.getProductType().getName() + "_metadata";
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            // build up the sql statement
+            StringBuffer insertClauseSql = new StringBuffer();
+            StringBuffer valueClauseSql = new StringBuffer();
+
+            insertClauseSql.append("INSERT INTO " + metadataTable
+                    + " (product_id, element_id, metadata_value) ");
+            valueClauseSql.append("VALUES ");
+
+            // now do the value clause
+            if (fieldIdStringFlag) {
+                valueClauseSql.append("(" + product.getProductId() + ", '"
+                        + element.getElementId() + "', '" + value + "')");
+            } else {
+                valueClauseSql.append("(" + product.getProductId() + ", "
+                        + element.getElementId() + ", '" + value + "')");
+            }
+
+            String metaIngestSql = insertClauseSql.toString()
+                    + valueClauseSql.toString();
+            LOG
+                    .log(Level.FINE, "addMetadataValue: Executing: "
+                            + metaIngestSql);
+            statement.execute(metaIngestSql);
+            conn.commit();
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception adding metadata value. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback add metadata value. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+    }
+
+    private synchronized void removeMetadataValue(Element element,
+            Product product, String value) throws CatalogException {
+
+        Connection conn = null;
+        Statement statement = null;
+
+        String metadataTable = product.getProductType().getName() + "_metadata";
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            // build up the sql statement
+            String metRemoveSql = "DELETE FROM " + metadataTable + " WHERE ";
+            if (fieldIdStringFlag) {
+                metRemoveSql += "PRODUCT_ID = '" + product.getProductId()
+                        + "' AND ";
+                metRemoveSql += "ELEMENT_ID = '" + element.getElementId()
+                        + "' AND ";
+                metRemoveSql += "METADATA_VALUE = '" + value + "'";
+            } else {
+                metRemoveSql += "PRODUCT_ID = " + product.getProductId()
+                        + " AND ";
+                metRemoveSql += "ELEMENT_ID = " + element.getElementId()
+                        + " AND ";
+                metRemoveSql += "METADATA_VALUE = " + value;
+            }
+
+            LOG.log(Level.FINE, "removeMetadataValue: Executing: "
+                    + metRemoveSql);
+            statement.execute(metRemoveSql);
+            conn.commit();
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception removing metadata value. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback remove metadata value. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getNumProducts(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public int getNumProducts(ProductType type) throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        int numProducts = -1;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String getProductSql = "SELECT COUNT(products.product_id) AS numProducts "
+                    + "FROM products ";
+
+            if (fieldIdStringFlag) {
+                getProductSql += "WHERE products.product_type_id = '"
+                        + type.getProductTypeId() + "' ";
+            } else {
+                getProductSql += "WHERE products.product_type_id = "
+                        + type.getProductTypeId() + " ";
+            }
+
+            LOG.log(Level.FINE, "getNumProducts: executing: " + getProductSql);
+
+            rs = statement.executeQuery(getProductSql);
+
+            while (rs.next()) {
+                numProducts = rs.getInt("numProducts");
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting num products. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback get num products. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return numProducts;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.util.Pagination#getFirstPage(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public ProductPage getFirstPage(ProductType type) {
+        Query query = new Query();
+        ProductPage firstPage = null;
+
+        try {
+            firstPage = pagedQuery(query, type, 1);
+        } catch (CatalogException e) {
+            LOG.log(Level.WARNING, "Exception getting first page: Message: "
+                    + e.getMessage());
+        }
+        return firstPage;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.util.Pagination#getLastProductPage(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public ProductPage getLastProductPage(ProductType type) {
+        ProductPage lastPage = null;
+        ProductPage firstPage = getFirstPage(type);
+        Query query = new Query();
+        try {
+            lastPage = pagedQuery(query, type, firstPage.getTotalPages());
+        } catch (CatalogException e) {
+            LOG.log(Level.WARNING, "Exception getting last page: Message: "
+                    + e.getMessage());
+        }
+
+        return lastPage;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.util.Pagination#getNextPage(org.apache.oodt.cas.filemgr.structs.ProductType,
+     *      org.apache.oodt.cas.filemgr.structs.ProductPage)
+     */
+    public ProductPage getNextPage(ProductType type, ProductPage currentPage) {
+        if (currentPage == null) {
+            return getFirstPage(type);
+        }
+
+        if (currentPage.isLastPage()) {
+            return currentPage;
+        }
+
+        ProductPage nextPage = null;
+        Query query = new Query();
+
+        try {
+            nextPage = pagedQuery(query, type, currentPage.getPageNum() + 1);
+        } catch (CatalogException e) {
+            LOG.log(Level.WARNING, "Exception getting next page: Message: "
+                    + e.getMessage());
+        }
+
+        return nextPage;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.util.Pagination#getPrevPage(org.apache.oodt.cas.filemgr.structs.ProductType,
+     *      org.apache.oodt.cas.filemgr.structs.ProductPage)
+     */
+    public ProductPage getPrevPage(ProductType type, ProductPage currentPage) {
+        if (currentPage == null) {
+            return getFirstPage(type);
+        }
+
+        if (currentPage.isFirstPage()) {
+            return currentPage;
+        }
+        ProductPage prevPage = null;
+        Query query = new Query();
+
+        try {
+            prevPage = pagedQuery(query, type, currentPage.getPageNum() - 1);
+        } catch (CatalogException e) {
+            LOG.log(Level.WARNING, "Exception getting prev page: Message: "
+                    + e.getMessage());
+        }
+
+        return prevPage;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#pagedQuery(org.apache.oodt.cas.filemgr.structs.Query,
+     *      org.apache.oodt.cas.filemgr.structs.ProductType, int)
+     */
+    public ProductPage pagedQuery(Query query, ProductType type, int pageNum)
+            throws CatalogException {
+        int totalPages = PaginationUtils.getTotalPage(getResultListSize(query,
+                type), this.pageSize);
+
+        /*
+         * if there are 0 total pages in the result list size then don't bother
+         * returning a valid product page instead, return blank ProductPage
+         */
+        if (totalPages == 0) {
+            return ProductPage.blankPage();
+        }
+
+        ProductPage retPage = new ProductPage();
+        retPage.setPageNum(pageNum);
+        retPage.setPageSize(this.pageSize);
+        retPage.setTotalPages(totalPages);
+
+        List<String> productIds = paginateQuery(query, type, pageNum);
+
+        if (productIds != null && productIds.size() > 0) {
+            List<Product> products = new Vector<Product>(productIds.size());
+
+            for (Iterator<String> i = productIds.iterator(); i.hasNext();) {
+                String productId = i.next();
+                Product p = getProductById(productId);
+                products.add(p);
+            }
+
+            retPage.setPageProducts(products);
+        }
+
+        return retPage;
+    }
+
+    protected int getResultListSize(Query query, ProductType type)
+            throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        int resultCount = 0;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getProductSql = "";
+            String tableName = type.getName() + "_metadata";
+            String subSelectQueryBase = "SELECT product_id FROM " + tableName
+                    + " ";
+            StringBuffer selectClause = new StringBuffer(
+                    "SELECT COUNT(DISTINCT p.product_id) AS numResults ");
+            StringBuffer fromClause = new StringBuffer("FROM " + tableName
+                    + " p ");
+            StringBuffer whereClause = new StringBuffer("WHERE ");
+
+            boolean gotFirstClause = false;
+            int clauseNum = 0;
+
+            if (query.getCriteria() != null && query.getCriteria().size() > 0) {
+                for (Iterator<QueryCriteria> i = query.getCriteria().iterator(); i.hasNext();) {
+                    QueryCriteria criteria = i.next();
+                    clauseNum++;
+
+                    String elementIdStr = null;
+
+                    if (fieldIdStringFlag) {
+                        elementIdStr = "'" + this.validationLayer.getElementByName(criteria.getElementName()).getElementId() + "'";
+                    } else {
+                        elementIdStr = this.validationLayer.getElementByName(criteria.getElementName()).getElementId();
+                    }
+
+                    String clause = null;
+
+                    if (!gotFirstClause) {
+                        clause = "(p.element_id = " + elementIdStr + " AND ";
+                        if (criteria instanceof TermQueryCriteria) {
+                            clause += " metadata_value LIKE '%"
+                                    + ((TermQueryCriteria) criteria).getValue()
+                                    + "%') ";
+                        } else if (criteria instanceof RangeQueryCriteria) {
+                            String startVal = ((RangeQueryCriteria) criteria)
+                                    .getStartValue();
+                            String endVal = ((RangeQueryCriteria) criteria)
+                                    .getEndValue();
+                            boolean inclusive = ((RangeQueryCriteria) criteria)
+                                    .getInclusive();
+
+                            if ((startVal != null && !startVal.equals(""))
+                                    || (endVal != null && !endVal.equals(""))) {
+                                clause += " metadata_value ";
+
+                                boolean gotStart = false;
+
+                                if (startVal != null && !startVal.equals("")) {
+                                    if (inclusive)
+                                        clause += ">= '" + startVal + "'";
+                                    else
+                                        clause += "> '" + startVal + "'";
+                                    gotStart = true;
+                                }
+
+                                if (endVal != null && !endVal.equals("")) {
+                                    if (gotStart) {
+                                        if (inclusive)
+                                            clause += " AND metadata_value <= '"
+                                                    + endVal + "'";
+                                        else
+                                            clause += " AND metadata_value < '"
+                                                    + endVal + "'";
+                                    } else if (inclusive)
+                                        clause += "<= '" + endVal + "'";
+                                    else
+                                        clause += "< '" + endVal + "'";
+                                }
+
+                                clause += ") ";
+                            }
+                        }
+                        whereClause.append(clause);
+                        gotFirstClause = true;
+                    } else {
+                        String subSelectTblName = "p" + clauseNum;
+                        String subSelectQuery = subSelectQueryBase
+                                + "WHERE (element_id = " + elementIdStr
+                                + " AND ";
+                        if (criteria instanceof TermQueryCriteria) {
+                            subSelectQuery += " metadata_value LIKE '%"
+                                    + ((TermQueryCriteria) criteria).getValue()
+                                    + "%')";
+                        } else if (criteria instanceof RangeQueryCriteria) {
+                            String startVal = ((RangeQueryCriteria) criteria)
+                                    .getStartValue();
+                            String endVal = ((RangeQueryCriteria) criteria)
+                                    .getEndValue();
+
+                            if (startVal != null || endVal != null) {
+                                subSelectQuery += " metadata_value ";
+
+                                boolean gotStart = false;
+
+                                if (startVal != null && !startVal.equals("")) {
+                                    subSelectQuery += ">= '" + startVal + "'";
+                                    gotStart = true;
+                                }
+
+                                if (endVal != null && !endVal.equals("")) {
+                                    if (gotStart) {
+                                        subSelectQuery += " AND metadata_value <= '"
+                                                + endVal + "'";
+                                    } else
+                                        subSelectQuery += "<= '" + endVal + "'";
+                                }
+
+                                subSelectQuery += ") ";
+
+                            }
+                        }
+
+                        fromClause.append("INNER JOIN (" + subSelectQuery
+                                + ") " + subSelectTblName + " ON "
+                                + subSelectTblName
+                                + ".product_id = p.product_id ");
+
+                    }
+                }
+            }
+
+            getProductSql = selectClause.toString() + fromClause.toString();
+            if (gotFirstClause) {
+                getProductSql += whereClause.toString();
+            }
+
+
+            LOG.log(Level.FINE, "catalog get num results: executing: "
+                    + getProductSql);
+
+            rs = statement.executeQuery(getProductSql);
+
+            while (rs.next()) {
+                resultCount = rs.getInt("numResults");
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception performing get num results. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback get num results transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return resultCount;
+    }
+
+    private boolean stillFresh(String productTypeId) {
+        Date currentTime = new Date();
+
+        if (PRODUCT_CACHE.get(productTypeId) == null) {
+            return false;
+        } else {
+            TreeMap<String, Object> productListAndUpdateTime = PRODUCT_CACHE
+                    .get(productTypeId);
+            String lastUpdateTime = (String) productListAndUpdateTime
+                    .get("lastUpdateTime");
+            Date lastUpdateTimeDate = null;
+
+            try {
+                lastUpdateTimeDate = DateConvert.isoParse(lastUpdateTime);
+
+                long timeDifferenceMilis = currentTime.getTime()
+                        - lastUpdateTimeDate.getTime();
+                long timeDifferenceSeconds = timeDifferenceMilis * 1000;
+                long timeDifferenceMinutes = timeDifferenceSeconds / 60;
+
+                if (timeDifferenceMinutes >= cacheUpdateMinutes) {
+                    return false;
+                } else {
+                    return true;
+                }
+            } catch (Exception e) {
+                LOG.log(Level.WARNING,
+                        "Unable to parse last update time for product type: ["
+                                + productTypeId + "]: Message: "
+                                + e.getMessage());
+                return false;
+            }
+        }
+
+    }
+
+    @SuppressWarnings("unchecked")
+	private List<Product> getProductsFromCache(String productTypeId) {
+        List<Product> products = null;
+
+        if (PRODUCT_CACHE.get(productTypeId) == null) {
+            return null;
+        } else {
+            TreeMap<String, Object> productListAndUpdateTime = PRODUCT_CACHE
+                    .get(productTypeId);
+            products = (List<Product>) productListAndUpdateTime.get("productList");
+        }
+
+        return products;
+    }
+
+    private void flagCacheUpdate(String productTypeId, List<Product> products) {
+        Date currentDateTime = new Date();
+        String isoDateStr = DateConvert.isoFormat(currentDateTime);
+        TreeMap<String, Object> productListAndUpdateTime = new TreeMap<String, Object>();
+        productListAndUpdateTime.put("productList", products);
+        productListAndUpdateTime.put("lastUpdateTime", isoDateStr);
+        PRODUCT_CACHE.put(productTypeId, productListAndUpdateTime);
+    }
+
+    @SuppressWarnings("unused")
+	private List<Product> getProductsByProductTypeCached(ProductType type) {
+        List<Product> products = null;
+        // check the product cache first
+        if (stillFresh(type.getProductTypeId())) {
+            products = getProductsFromCache(type.getProductTypeId());
+        } else {
+            // go get a fresh set
+            try {
+                products = getProductsByProductType(type);
+                flagCacheUpdate(type.getProductTypeId(), products);
+            } catch (CatalogException e) {
+                LOG.log(Level.WARNING,
+                        "CatalogException getting cached products for type: ["
+                                + type.getProductTypeId() + "]: Message: "
+                                + e.getMessage());
+                return products;
+            }
+        }
+
+        return products;
+    }
+
+    private List<String> paginateQuery(Query query, ProductType type, int pageNum)
+            throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        boolean doSkip = true;
+        int numResults = -1;
+
+        if (pageNum == -1) {
+            doSkip = false;
+        } else {
+            numResults = getResultListSize(query, type);
+        }
+
+        try {
+            
+            conn = dataSource.getConnection();
+            statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
+                    ResultSet.CONCUR_READ_ONLY);
+
+            String getProductSql = null;
+            
+            if (!productIdString) {
+            	
+	            if (query.getCriteria().size() == 0) {
+	                getProductSql = "SELECT DISTINCT product_id FROM " + type.getName() + "_metadata";
+	            }else if (query.getCriteria().size() == 1) {
+	                getProductSql = this.getSqlQuery(query.getCriteria().get(0), type);
+	            }else {
+	                getProductSql = this.getSqlQuery(new BooleanQueryCriteria(query.getCriteria(), BooleanQueryCriteria.AND), type);
+	            }
+	            getProductSql += " ORDER BY product_id DESC ";
+            
+            } else {
+            	
+              if (query.getCriteria().size() == 0) {
+                getProductSql = "SELECT DISTINCT products.product_id FROM products, " + type.getName() + "_metadata"
+                				      + " WHERE products.product_id="+type.getName() + "_metadata.product_id";
+              }	else if (query.getCriteria().size() == 1) {
+                getProductSql = this.getSqlQuery(query.getCriteria().get(0), type);
+              }	else {
+                getProductSql = this.getSqlQuery(new BooleanQueryCriteria(query.getCriteria(), BooleanQueryCriteria.AND), type);
+              }
+              getProductSql += " ORDER BY products.product_datetime DESC ";
+              
+            }
+            
+            LOG.log(Level.FINE, "catalog query: executing: " + getProductSql);
+
+            rs = statement.executeQuery(getProductSql);
+
+            List<String> productIds = new Vector<String>();
+            if (doSkip) {
+                int startNum = (pageNum - 1) * pageSize;
+
+                if (startNum > numResults) {
+                    startNum = 0;
+                }
+
+                // must call next first, or else no relative cursor
+                if (rs.next()) {
+                    // grab the first one
+                    int numGrabbed = -1;
+
+                    if (pageNum == 1) {
+                        numGrabbed = 1;
+                        productIds.add(rs.getString("product_id"));
+                    } else {
+                        numGrabbed = 0;
+                    }
+
+                    // now move the cursor to the correct position
+                    if (pageNum != 1) {
+                        rs.relative(startNum - 1);
+                    }
+
+                    // grab the rest
+                    while (rs.next() && numGrabbed < pageSize) {
+                        String productId = rs.getString("product_id");
+                        productIds.add(productId);
+                        numGrabbed++;
+                    }
+                }
+
+            } else {
+                while (rs.next()) {
+                    String productId = rs.getString("product_id");
+                    productIds.add(productId);
+                }
+            }
+            
+            return productIds;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception performing query. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback query transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+    
+    protected String getSqlQuery(QueryCriteria queryCriteria, ProductType type) throws ValidationLayerException, CatalogException {
+        String sqlQuery = null;
+        if (queryCriteria instanceof BooleanQueryCriteria) {
+            BooleanQueryCriteria bqc = (BooleanQueryCriteria) queryCriteria;
+            if (bqc.getOperator() == BooleanQueryCriteria.NOT) {            	
+            		if (!this.productIdString) {
+            			sqlQuery = "SELECT DISTINCT product_id FROM " + type.getName() + "_metadata WHERE product_id NOT IN (" + this.getSqlQuery(bqc.getTerms().get(0), type) + ")";
+            		} else {
+            			sqlQuery = "SELECT DISTINCT products.product_id FROM products," + type.getName() + "_metadata"
+            							 + " WHERE products.product_id="+type.getName() + "_metadata.product_id" 
+            							 + " AND products.product_id NOT IN (" + this.getSqlQuery(bqc.getTerms().get(0), type) + ")";
+            		}
+            }else {
+                sqlQuery = "(" + this.getSqlQuery(bqc.getTerms().get(0), type);
+                String op = bqc.getOperator() == BooleanQueryCriteria.AND ? "INTERSECT" : "UNION";
+                for (int i = 1; i < bqc.getTerms().size(); i++) 
+                    sqlQuery += ") " + op + " (" + this.getSqlQuery(bqc.getTerms().get(i), type);
+                sqlQuery += ")";
+            }
+        }else {
+        	  String elementIdStr = this.validationLayer.getElementByName(queryCriteria.getElementName()).getElementId();
+            if (fieldIdStringFlag) 
+                elementIdStr = "'" + elementIdStr + "'";
+            if (!this.productIdString) {
+            	sqlQuery = "SELECT DISTINCT product_id FROM " + type.getName() + "_metadata WHERE element_id = " + elementIdStr + " AND ";
+            } else {
+            	sqlQuery = "SELECT DISTINCT products.product_id FROM products," + type.getName() + "_metadata"
+            	         + " WHERE products.product_id="+type.getName() + "_metadata.product_id" 
+            			     + " AND element_id = " + elementIdStr + " AND ";
+            }
+            if (queryCriteria instanceof TermQueryCriteria) {
+                sqlQuery += "metadata_value = '" + ((TermQueryCriteria) queryCriteria).getValue() + "'";
+            } else if (queryCriteria instanceof RangeQueryCriteria) {
+                RangeQueryCriteria rqc = (RangeQueryCriteria) queryCriteria;
+                String rangeSubQuery = null;
+                if (rqc.getStartValue() != null)
+                    rangeSubQuery = "metadata_value" + (rqc.getInclusive() ? " >= " : " > ") + "'" + rqc.getStartValue() + "'";
+                if (rqc.getEndValue() != null) {
+                    if (rangeSubQuery == null)
+                        rangeSubQuery = "metadata_value" + (rqc.getInclusive() ? " <= " : " < ") + "'" + rqc.getEndValue() + "'";
+                    else
+                        rangeSubQuery = "(" + rangeSubQuery + " AND metadata_value" + (rqc.getInclusive() ? " <= " : " < ") + "'" + rqc.getEndValue() + "')";
+                }
+                sqlQuery += rangeSubQuery;
+            } else {
+                throw new CatalogException("Invalid QueryCriteria [" + queryCriteria.getClass().getCanonicalName() + "]");
+            }
+        }
+
+        return sqlQuery;
+    }
+
+    private synchronized void updateReferences(Product product)
+            throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        String productRefTable = product.getProductType().getName()
+                + "_reference";
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            // first remove the refs
+            String deleteProductSql = "DELETE FROM "
+                    + product.getProductType().getName() + "_reference "
+                    + " WHERE product_id = " + quoteIt(product.getProductId());
+            LOG.log(Level.FINE, "updateProductReferences: Executing: "
+                    + deleteProductSql);
+            statement.execute(deleteProductSql);
+
+            // now add the new ones back in
+            for (Iterator<Reference> i = product.getProductReferences().iterator(); i
+                    .hasNext();) {
+                Reference r = i.next();
+
+                String addRefSql = "INSERT INTO "
+                        + productRefTable
+                        + " "
+                        + "(product_id, product_orig_reference, product_datastore_reference, product_reference_filesize,"
+                        + "product_reference_mimetype) " + "VALUES ("
+                        + product.getProductId() + ", '" + r.getOrigReference()
+                        + "', '" + r.getDataStoreReference() + "', "
+                        + r.getFileSize() + ",'" + r.getMimeType().getName()
+                        + "')";
+
+                LOG.log(Level.FINE, "updateProductReferences: Executing: "
+                        + addRefSql);
+                statement.execute(addRefSql);
+            }
+
+            conn.commit();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception updating product references. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback updateProductReferences transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+    
+    /**
+     * Utility method to quote the "productId" value 
+     * if the column type is "string".
+     * @param productId
+     * @return
+     */
+    protected String quoteIt(String productId) {
+    	if (this.productIdString) {
+    		return "'"+productId+"'";
+    	} else {
+    		return productId;
+    	}
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/DataSourceCatalogFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/DataSourceCatalogFactory.java
new file mode 100644
index 0000000..6975397
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/DataSourceCatalogFactory.java
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+//OODT imports
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+import org.apache.oodt.cas.filemgr.util.GenericFileManagerObjectFactory;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//JDK imports
+import javax.sql.DataSource;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory class for creating {@link DataSourceCatalog}s.
+ * </p>
+ * 
+ */
+public class DataSourceCatalogFactory implements CatalogFactory {
+    /* our data source */
+    protected DataSource dataSource = null;
+
+    /* our validation layer */
+    protected ValidationLayer validationLayer = null;
+
+    /* field Id Str: should product_type_id and element_id be quoted? */
+    protected boolean fieldIdStr = false;
+
+    /*
+     * page size: size of the pages used by the catalog to paginate products
+     * back to the user
+     */
+    protected int pageSize = -1;
+
+    /* the amount of minutes to allow between updating the product cache */
+    protected long cacheUpdateMinutes = -1L;
+    
+    /* Whether or not to enforce strict definition of metadata fields:
+  	 * 'lenient=false' means that all metadata fields need to be explicitly defined in the XML configuration file */
+    protected boolean lenientFields = false;
+  	
+    /* Flag to indicate whether the "product_id" key type should be treated as a string */
+    protected boolean productIdString = false;
+
+    protected boolean orderedValues = false;
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     */
+    public DataSourceCatalogFactory() {
+    	
+    	  // instantiate data source
+        String jdbcUrl = null, user = null, pass = null, driver = null;
+
+        jdbcUrl = PathUtils
+                .replaceEnvVariables(System
+                        .getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.url"));
+        user = PathUtils
+                .replaceEnvVariables(System
+                        .getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.user"));
+        pass = PathUtils
+                .replaceEnvVariables(System
+                        .getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.pass"));
+        driver = PathUtils
+                .replaceEnvVariables(System
+                        .getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.driver"));
+
+        dataSource = DatabaseConnectionBuilder.buildDataSource(user, pass,
+                driver, jdbcUrl);
+
+        this.configure();
+
+    }
+
+    /**
+     * <p>
+     * Constructs a new Factory from the specified {@link DataSource}.
+     * </p>
+     * 
+     * @param ds
+     *            The DataSource to construct this factory from.
+     */
+    public DataSourceCatalogFactory(DataSource ds) {
+       
+    		this.dataSource = ds;
+        
+     		this.configure();
+    		
+    }
+    
+    /** Method to configure the factory (and validation layer) from the environment properties,
+     *  before any Catalog instance is created 
+     **/
+    private void configure() {
+    
+  		lenientFields = Boolean.parseBoolean( System.getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.lenientFields", "false") );
+  		if (!lenientFields) {
+	        String validationLayerFactoryClass = System
+                .getProperty("filemgr.validationLayer.factory",
+                        "org.apache.oodt.cas.filemgr.validation.DataSourceValidationLayerFactory");
+	        validationLayer = GenericFileManagerObjectFactory
+              .getValidationLayerFromFactory(validationLayerFactoryClass);
+  		} 
+  		
+      fieldIdStr = Boolean
+      	.getBoolean("org.apache.oodt.cas.filemgr.catalog.datasource.quoteFields");
+
+			pageSize = Integer
+			      .getInteger(
+			              "org.apache.oodt.cas.filemgr.catalog.datasource.pageSize",
+			              20).intValue();
+			cacheUpdateMinutes = Long
+			      .getLong(
+			              "org.apache.oodt.cas.filemgr.catalog.datasource.cacheUpdateMinutes",
+			              5L).longValue();
+			
+			productIdString = Boolean.parseBoolean( 
+				System.getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.productId.string", "false") );
+  	
+			orderedValues = Boolean.parseBoolean(System.getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.orderedValues"));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.CatalogFactory#createCatalog()
+     */
+    public Catalog createCatalog() {
+    	if (validationLayer==null) {
+    			return new LenientDataSourceCatalog(dataSource, validationLayer, fieldIdStr,
+							    pageSize, cacheUpdateMinutes, productIdString, orderedValues);
+    	} else {
+        return new DataSourceCatalog(dataSource, validationLayer, fieldIdStr,
+				     pageSize, cacheUpdateMinutes, productIdString, orderedValues);
+    	}
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/LenientDataSourceCatalog.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/LenientDataSourceCatalog.java
new file mode 100644
index 0000000..2c567d4
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/LenientDataSourceCatalog.java
@@ -0,0 +1,827 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+// OODT imports
+import org.apache.oodt.cas.filemgr.structs.BooleanQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.QueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JDK imports
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.text.SimpleDateFormat;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.sql.DataSource;
+
+/**
+ * @author luca
+ * @version $Revision$
+ * 
+ * <p>
+ * Extension of {@link DataSourceCatalog} that can accomodate dynamic fields.
+ * </p>
+ * 
+ */
+public class LenientDataSourceCatalog extends DataSourceCatalog {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(LenientDataSourceCatalog.class.getName());
+    
+    // ISO date/time format for CAS.ProductReceivedTime 
+		private SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+		
+		// date/time format for database
+		private SimpleDateFormat dbFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     * @throws  
+     */
+    public LenientDataSourceCatalog(DataSource ds, ValidationLayer valLayer,
+				    boolean fieldId, int pageSize, long cacheUpdateMin, boolean productIdString, boolean orderedValues) {
+    	
+	super(ds, valLayer, fieldId, pageSize, cacheUpdateMin, productIdString, orderedValues);
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#addMetadata(org.apache.oodt.cas.metadata.Metadata,
+     *      org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void addMetadata(Metadata m, Product product)
+            throws CatalogException {
+    	
+    		// replace "CAS.ProductId"
+    		m.removeMetadata("CAS.ProductId");
+    		m.addMetadata("CAS.ProductId", product.getProductId());
+    	
+    		// map containing metadata type (id, name) pairs
+        Map<String, String> metadataTypes = getMetadataTypes(m, product);
+
+        // loop over metadata types
+        for (String metadataId : metadataTypes.keySet()) {
+        	String metadataName = metadataTypes.get(metadataId);
+        	
+            List<String> values = m.getAllMetadata(metadataName);
+
+            if (values == null) {
+                LOG.log(Level.WARNING, "No Metadata specified for product ["
+                        + product.getProductName() + "] for required field ["
+                        + metadataName
+                        + "]: Attempting to continue processing metadata");
+                continue;
+            }
+
+            for (Iterator<String> j = values.iterator(); j.hasNext();) {
+                String value = j.next();
+
+                try {
+                    addMetadataValue(metadataId, product, value);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    LOG
+                            .log(
+                                    Level.WARNING,
+                                    "Exception ingesting metadata. Error inserting field: ["
+                                            + metadataId
+                                            + "=>"
+                                            + value
+                                            + "]: for product: ["
+                                            + product.getProductName()
+                                            + "]: Message: "
+                                            + e.getMessage()
+                                            + ": Attempting to continue processing metadata");
+                }
+            }
+        }
+
+    }
+    
+    // Utility method to return a map of metadata (field id, field name)
+    private Map<String, String> getMetadataTypes(Metadata m, Product product) throws CatalogException {
+    	
+  		// map containing metadata type (id, name) pairs
+      Map<String, String> metadataTypes = new LinkedHashMap<String,String>();
+
+      if (getValidationLayer()!=null) {
+      	// validation layer: add valid metadata elements 
+        try {
+            for (Element element : getValidationLayer().getElements(product.getProductType())) {
+            	metadataTypes.put(element.getElementId(), element.getElementName());
+            }
+            
+        } catch (ValidationLayerException e) {
+            e.printStackTrace();
+            throw new CatalogException(
+                    "ValidationLayerException when trying to obtain element list for product type: "
+                            + product.getProductType().getName()
+                            + ": Message: " + e.getMessage());
+        }
+        
+      } else {
+      	
+      	// no validation layer: add ALL metadata elements
+      	// use (key, key) pairs (i.e. metadata id == metadata name)
+      	for (String key : m.getAllKeys()) {
+      		metadataTypes.put(key, key);
+      	}
+      	
+      }
+      
+      return metadataTypes;
+      
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#addMetadata(org.apache.oodt.cas.metadata.Metadata,
+     *      org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void removeMetadata(Metadata m, Product product)
+            throws CatalogException {
+    	
+  			// map containing metadata type (id, name) pairs
+      	Map<String, String> metadataTypes = getMetadataTypes(m, product);
+            
+        // loop over metadata types
+        for (String metadataId : metadataTypes.keySet()) {
+           	String metadataName = metadataTypes.get(metadataId);
+            	
+            List<String> values = m.getAllMetadata(metadataName);
+
+            if (values != null) {
+                for (Iterator<String> j = values.iterator(); j.hasNext();) {
+                    String value = j.next();
+
+                    try {
+                        removeMetadataValue(metadataId, product, value);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        LOG
+                                .log(
+                                        Level.WARNING,
+                                        "Exception removing metadata. Error deleting field: ["
+                                                + metadataId
+                                                + "=>"
+                                                + value
+                                                + "]: for product: ["
+                                                + product.getProductName()
+                                                + "]: Message: "
+                                                + e.getMessage()
+                                                + ": Attempting to continue processing metadata");
+                    }
+                }
+            }
+        }
+    }
+
+    public Metadata getMetadata(Product product) throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+        Metadata m = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String metadataSql = "SELECT * FROM "
+                    + product.getProductType().getName() + "_metadata "
+		+ "WHERE product_id = '" + product.getProductId()+"'";
+            if(this.orderedValues) metadataSql += " ORDER BY pkey" ;
+
+            LOG.log(Level.FINE, "getMetadata: Executing: " + metadataSql);
+            rs = statement.executeQuery(metadataSql);
+            
+            // parse SQL results
+            m = populateProductMetadata(rs, product);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting metadata. Message: "
+                    + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return m;
+    }
+    
+    /** Method to populate the product metadata from a SQL ResultSet. **/
+    private Metadata populateProductMetadata(ResultSet rs, Product product) throws CatalogException, SQLException {
+     
+    	Metadata m = new Metadata();
+
+      if (getValidationLayer()!=null) {
+        
+      	// validation layer: retrieve valid metadata elements
+        List<Element> elements = null;
+
+      	try {
+            elements = getValidationLayer().getElements(product.getProductType());
+        } catch (ValidationLayerException e) {
+            e.printStackTrace();
+            throw new CatalogException(
+                    "ValidationLayerException when trying to obtain element list for product type: "
+                            + product.getProductType().getName()
+                            + ": Message: " + e.getMessage());
+        }
+
+        while (rs.next()) {
+            for (Iterator<Element> i = elements.iterator(); i.hasNext();) {
+                Element e = i.next();
+
+                // right now, we just support STRING
+                String elemValue = rs.getString("metadata_value");
+                String elemId = rs.getString("element_id");
+
+                if (elemId.equals(e.getElementId())) {
+                    elemValue = (elemValue != null ? elemValue : "");
+                    m.addMetadata(e.getElementName(), elemValue);
+                }
+            }
+        }
+      
+      } else {
+      	
+      	// no validation layer - add all (name, value) pairs for this product_id query
+        while (rs.next()) {
+            // right now, we just support STRING
+            String elemValue = rs.getString("metadata_value");
+            String elemId = rs.getString("element_id");
+
+            elemValue = (elemValue != null ? elemValue : "");
+            m.addMetadata(elemId, elemValue);    
+        }
+        
+      }
+      
+      return m;
+      
+    }
+    
+    public Metadata getReducedMetadata(Product product, List<String> elems) throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+        Metadata m = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String elementIds = "";
+            if (elems.size() > 0) {
+            	
+            	  if (getValidationLayer()!=null) {
+            	  	// validation layer: column "element_id" contains the element identifier (e.g. "urn:oodt:ProductReceivedTime")
+	                elementIds += " AND (element_id = '" + this.getValidationLayer().getElementByName(elems.get(0)).getElementId() + "'";
+	                for (int i = 1; i < elems.size(); i++) 
+	                    elementIds += " OR element_id = '" + this.getValidationLayer().getElementByName(elems.get(i)).getElementId() + "'";
+	                elementIds += ")";
+            	 
+            	  } else {
+            	  	// no validation layer: column "element_id" contains the element name (e.g. "CAS.ProductReceivedTime")
+	                elementIds += " AND (element_id = '" + elems.get(0) + "'";
+	                for (int i = 1; i < elems.size(); i++) 
+	                    elementIds += " OR element_id = '" + elems.get(i) + "'";
+	                elementIds += ")";
+	                
+            	  }
+            	  
+            }
+            String metadataSql = "SELECT element_id,metadata_value FROM "
+                    + product.getProductType().getName() + "_metadata"
+		+ " WHERE product_id = " + quoteIt(product.getProductId()) + elementIds;
+            if(this.orderedValues) metadataSql += " ORDER BY pkey";
+
+            LOG.log(Level.FINE, "getMetadata: Executing: " + metadataSql);
+            rs = statement.executeQuery(metadataSql);
+
+            // parse SQL results
+            m = populateProductMetadata(rs, product);
+
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting metadata. Message: "
+                    + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return m;
+    }
+
+    private synchronized void addMetadataValue(String key,
+            Product product, String value) throws CatalogException {
+
+        Connection conn = null;
+        Statement statement = null;
+
+        String metadataTable = product.getProductType().getName() + "_metadata";
+                
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            // build up the sql statement
+            StringBuffer insertClauseSql = new StringBuffer();
+            StringBuffer valueClauseSql = new StringBuffer();
+
+            insertClauseSql.append("INSERT INTO " + metadataTable
+                    + " (product_id, element_id, metadata_value) ");
+            valueClauseSql.append("VALUES ");
+
+            // now do the value clause
+            if (fieldIdStringFlag) {
+                valueClauseSql.append("(" + quoteIt(product.getProductId()) + ", '"
+                        + key + "', '" + value + "')");
+            } else {
+                valueClauseSql.append("(" + product.getProductId() + ", "
+                        + key + ", '" + value + "')");
+            }
+
+            String metaIngestSql = insertClauseSql.toString()
+                    + valueClauseSql.toString();
+            LOG
+                    .log(Level.FINE, "addMetadataValue: Executing: "
+                            + metaIngestSql);
+            statement.execute(metaIngestSql);
+            
+            // synchronize CAS.ProductReceivedTime with products.product_datetime
+            if (key.equals("CAS.ProductReceivedTime") && this.productIdString) {
+            		// convert from "2012-12-18T09:00:14.068-08:00" --> "2012-12-18T09:00:14.068-0800" --> "2012-12-18T10:00:14"
+            		String datetime = dbFormat.format( isoFormat.parse( value.replaceAll(":00$", "00") ));
+            		String updateDateTimeSql = "UPDATE products SET product_datetime='"+datetime+"' WHERE product_id="+quoteIt(product.getProductId());
+            		LOG.log(Level.FINE, "addMetadataValue: Executing: "+updateDateTimeSql);
+            		statement.execute(updateDateTimeSql);
+            }
+            
+            conn.commit();
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception adding metadata value. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback add metadata value. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+    }
+
+    private synchronized void removeMetadataValue(String elementId,
+            Product product, String value) throws CatalogException {
+
+        Connection conn = null;
+        Statement statement = null;
+
+        String metadataTable = product.getProductType().getName() + "_metadata";
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            // build up the sql statement
+            String metRemoveSql = "DELETE FROM " + metadataTable + " WHERE ";
+            if (fieldIdStringFlag) {
+                metRemoveSql += "PRODUCT_ID = '" + product.getProductId()
+                        + "' AND ";
+                metRemoveSql += "ELEMENT_ID = '" + elementId
+                        + "' AND ";
+                metRemoveSql += "METADATA_VALUE = '" + value + "'";
+            } else {
+                metRemoveSql += "PRODUCT_ID = " + product.getProductId()
+                        + " AND ";
+                metRemoveSql += "ELEMENT_ID = " + elementId
+                        + " AND ";
+                metRemoveSql += "METADATA_VALUE = " + value;
+            }
+
+            LOG.log(Level.FINE, "removeMetadataValue: Executing: "
+                    + metRemoveSql);
+            statement.execute(metRemoveSql);
+            conn.commit();
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception removing metadata value. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback remove metadata value. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+    }
+
+    /**
+     * Overridden method from superclass to allow for null validation layer.
+     */
+    protected int getResultListSize(Query query, ProductType type)
+            throws CatalogException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        int resultCount = 0;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getProductSql = "";
+            String tableName = type.getName() + "_metadata";
+            String subSelectQueryBase = "SELECT product_id FROM " + tableName
+                    + " ";
+            StringBuffer selectClause = new StringBuffer(
+                    "SELECT COUNT(DISTINCT p.product_id) AS numResults ");
+            StringBuffer fromClause = new StringBuffer("FROM " + tableName
+                    + " p ");
+            StringBuffer whereClause = new StringBuffer("WHERE ");
+
+            boolean gotFirstClause = false;
+            int clauseNum = 0;
+
+            if (query.getCriteria() != null && query.getCriteria().size() > 0) {
+                for (Iterator<QueryCriteria> i = query.getCriteria().iterator(); i.hasNext();) {
+                    QueryCriteria criteria = i.next();
+                    clauseNum++;
+
+                    String elementIdStr = null;
+
+                    if (fieldIdStringFlag) {
+                    		if (getValidationLayer()!=null) {
+                    			elementIdStr = "'" + this.getValidationLayer().getElementByName(criteria.getElementName()).getElementId() + "'";
+                    		} else {
+                    			elementIdStr = "'" + criteria.getElementName() + "'";
+                    		}
+                    } else {
+                    	if (getValidationLayer()!=null) {
+                        elementIdStr = this.getValidationLayer().getElementByName(criteria.getElementName()).getElementId();
+                    	} else {
+                    		elementIdStr = criteria.getElementName();
+                    	}
+                    }
+
+                    String clause = null;
+
+                    if (!gotFirstClause) {
+                        clause = "(p.element_id = " + elementIdStr + " AND ";
+                        if (criteria instanceof TermQueryCriteria) {
+                            clause += " metadata_value LIKE '%"
+                                    + ((TermQueryCriteria) criteria).getValue()
+                                    + "%') ";
+                        } else if (criteria instanceof RangeQueryCriteria) {
+                            String startVal = ((RangeQueryCriteria) criteria)
+                                    .getStartValue();
+                            String endVal = ((RangeQueryCriteria) criteria)
+                                    .getEndValue();
+                            boolean inclusive = ((RangeQueryCriteria) criteria)
+                                    .getInclusive();
+
+                            if ((startVal != null && !startVal.equals(""))
+                                    || (endVal != null && !endVal.equals(""))) {
+                                clause += " metadata_value ";
+
+                                boolean gotStart = false;
+
+                                if (startVal != null && !startVal.equals("")) {
+                                    if (inclusive)
+                                        clause += ">= '" + startVal + "'";
+                                    else
+                                        clause += "> '" + startVal + "'";
+                                    gotStart = true;
+                                }
+
+                                if (endVal != null && !endVal.equals("")) {
+                                    if (gotStart) {
+                                        if (inclusive)
+                                            clause += " AND metadata_value <= '"
+                                                    + endVal + "'";
+                                        else
+                                            clause += " AND metadata_value < '"
+                                                    + endVal + "'";
+                                    } else if (inclusive)
+                                        clause += "<= '" + endVal + "'";
+                                    else
+                                        clause += "< '" + endVal + "'";
+                                }
+
+                                clause += ") ";
+                            }
+                        }
+                        whereClause.append(clause);
+                        gotFirstClause = true;
+                    } else {
+                        String subSelectTblName = "p" + clauseNum;
+                        String subSelectQuery = subSelectQueryBase
+                                + "WHERE (element_id = " + elementIdStr
+                                + " AND ";
+                        if (criteria instanceof TermQueryCriteria) {
+                            subSelectQuery += " metadata_value LIKE '%"
+                                    + ((TermQueryCriteria) criteria).getValue()
+                                    + "%')";
+                        } else if (criteria instanceof RangeQueryCriteria) {
+                            String startVal = ((RangeQueryCriteria) criteria)
+                                    .getStartValue();
+                            String endVal = ((RangeQueryCriteria) criteria)
+                                    .getEndValue();
+
+                            if (startVal != null || endVal != null) {
+                                subSelectQuery += " metadata_value ";
+
+                                boolean gotStart = false;
+
+                                if (startVal != null && !startVal.equals("")) {
+                                    subSelectQuery += ">= '" + startVal + "'";
+                                    gotStart = true;
+                                }
+
+                                if (endVal != null && !endVal.equals("")) {
+                                    if (gotStart) {
+                                        subSelectQuery += " AND metadata_value <= '"
+                                                + endVal + "'";
+                                    } else
+                                        subSelectQuery += "<= '" + endVal + "'";
+                                }
+
+                                subSelectQuery += ") ";
+
+                            }
+                        }
+
+                        fromClause.append("INNER JOIN (" + subSelectQuery
+                                + ") " + subSelectTblName + " ON "
+                                + subSelectTblName
+                                + ".product_id = p.product_id ");
+
+                    }
+                }
+            }
+
+            getProductSql = selectClause.toString() + fromClause.toString();
+            if (gotFirstClause) {
+                getProductSql += whereClause.toString();
+            }
+
+
+            LOG.log(Level.FINE, "catalog get num results: executing: "
+                    + getProductSql);
+
+            rs = statement.executeQuery(getProductSql);
+
+            while (rs.next()) {
+                resultCount = rs.getInt("numResults");
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception performing get num results. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback get num results transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new CatalogException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return resultCount;
+    }
+    
+    /**
+     * Overridden method from superclass to allow for null validation layer.
+     */
+    protected String getSqlQuery(QueryCriteria queryCriteria, ProductType type) throws ValidationLayerException, CatalogException {
+      String sqlQuery = null;
+      if (queryCriteria instanceof BooleanQueryCriteria) {
+          BooleanQueryCriteria bqc = (BooleanQueryCriteria) queryCriteria;
+          if (bqc.getOperator() == BooleanQueryCriteria.NOT) {
+          	  if (!this.productIdString) {
+          	  	sqlQuery = "SELECT DISTINCT product_id FROM " + type.getName() + "_metadata WHERE product_id NOT IN (" + this.getSqlQuery(bqc.getTerms().get(0), type) + ")";
+          	  } else {
+               	sqlQuery = "SELECT DISTINCT products.product_id FROM products," + type.getName() + "_metadata"
+               					 + " WHERE products.product_id="+type.getName() + "_metadata.product_id" 
+          	  			     + " AND products.product_id NOT IN (" + this.getSqlQuery(bqc.getTerms().get(0), type) + ")";
+          	  }
+          } else {
+              sqlQuery = "(" + this.getSqlQuery(bqc.getTerms().get(0), type);
+              String op = bqc.getOperator() == BooleanQueryCriteria.AND ? "INTERSECT" : "UNION";
+              for (int i = 1; i < bqc.getTerms().size(); i++) 
+                  sqlQuery += ") " + op + " (" + this.getSqlQuery(bqc.getTerms().get(i), type);
+              sqlQuery += ")";
+          }
+      }else {
+      	  String elementIdStr = queryCriteria.getElementName();
+      	  if (this.getValidationLayer()!=null) {
+      	  	elementIdStr = this.getValidationLayer().getElementByName(queryCriteria.getElementName()).getElementId();
+      	  }
+          
+          if (fieldIdStringFlag) 
+              elementIdStr = "'" + elementIdStr + "'";
+          if (!this.productIdString) {
+          	sqlQuery = "SELECT DISTINCT product_id FROM " + type.getName() + "_metadata WHERE element_id = " + elementIdStr + " AND ";
+          } else {
+          	sqlQuery = "SELECT DISTINCT products.product_id FROM products," + type.getName() + "_metadata"
+          	         + " WHERE products.product_id="+type.getName() + "_metadata.product_id" 
+          			     + " AND element_id = " + elementIdStr + " AND ";
+          }
+          if (queryCriteria instanceof TermQueryCriteria) {
+              sqlQuery += "metadata_value = '" + ((TermQueryCriteria) queryCriteria).getValue() + "'";
+          } else if (queryCriteria instanceof RangeQueryCriteria) {
+              RangeQueryCriteria rqc = (RangeQueryCriteria) queryCriteria;
+              String rangeSubQuery = null;
+              if (rqc.getStartValue() != null)
+                  rangeSubQuery = "metadata_value" + (rqc.getInclusive() ? " >= " : " > ") + "'" + rqc.getStartValue() + "'";
+              if (rqc.getEndValue() != null) {
+                  if (rangeSubQuery == null)
+                      rangeSubQuery = "metadata_value" + (rqc.getInclusive() ? " <= " : " < ") + "'" + rqc.getEndValue() + "'";
+                  else
+                      rangeSubQuery = "(" + rangeSubQuery + " AND metadata_value" + (rqc.getInclusive() ? " <= " : " < ") + "'" + rqc.getEndValue() + "')";
+              }
+              sqlQuery += rangeSubQuery;
+          } else {
+              throw new CatalogException("Invalid QueryCriteria [" + queryCriteria.getClass().getCanonicalName() + "]");
+          }
+      }
+
+      return sqlQuery;
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/LuceneCatalog.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/LuceneCatalog.java
new file mode 100644
index 0000000..5e375c4
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/LuceneCatalog.java
@@ -0,0 +1,1496 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//Lucene imports
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Hits;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.RangeQuery;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.WildcardQuery;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.BooleanQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.QueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.commons.pagination.PaginationUtils;
+
+//JUG imports
+import org.safehaus.uuid.UUID;
+import org.safehaus.uuid.UUIDGenerator;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @author luca
+ * @version $Revision$
+ * 
+ * <p>
+ * An implementation of a File {@link Catalog} using Apache's popular <a
+ * href="http://lucene.apache.org">Lucene</a> text indexing engine as a
+ * backend.
+ * </p>
+ * 
+ */
+public class LuceneCatalog implements Catalog {
+
+    /* the path to the index directory for this catalog */
+    private String indexFilePath = null;
+
+    /* validation layer */
+    private ValidationLayer valLayer = null;
+
+    /*
+     * temporary Cache of product/metadata/reference information before it is
+     * written to the index
+     */
+    private static HashMap<String, CompleteProduct> CATALOG_CACHE = new HashMap<String, CompleteProduct>();
+
+    /* our product ID generator */
+    private static UUIDGenerator generator = UUIDGenerator.getInstance();
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(LuceneCatalog.class.getName());
+
+    /* page size for pagination */
+    private int pageSize = -1;
+
+    /* write lock timeout for writing to the index */
+    private long writeLockTimeout = -1L;
+
+    /* commit lock timeout for writing/reading to the index */
+    private long commitLockTimeout = -1L;
+
+    /* lucene index merge factor */
+    private int mergeFactor = -1;
+
+    /**
+     * 
+     * @param idxFilePath
+     *            A file path pointing to the lucene index directory for this
+     *            catalog.
+     * @param vLayer
+     *            The validation layer to be used for this catalog.
+     * @param pgSize
+     *            The size of pages to be used when doing pagination of the
+     *            catalog.
+     * 
+     * @param commitTimeout
+     *            The amount of time (in seconds) that should be flowed down to
+     *            the Lucene IndexReader and IndexWriters for their commit lock
+     *            timeout property.
+     * 
+     * @param writeTimeout
+     *            The amount of time (in seconds) that should be flowed down to
+     *            the Lucene IndexWriters for their commit lock timeout
+     *            property.
+     * 
+     * @param mergeFactor
+     *            The merge factor to use when writing to the index.
+     */
+    public LuceneCatalog(String idxFilePath, ValidationLayer vLayer,
+            int pgSize, long commitTimeout, long writeTimeout, int mergeFactor) {
+        this.indexFilePath = idxFilePath;
+        this.valLayer = vLayer;
+        this.pageSize = pgSize;
+        this.writeLockTimeout = writeTimeout;
+        this.commitLockTimeout = commitTimeout;
+        this.mergeFactor = mergeFactor;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#addMetadata(org.apache.oodt.cas.metadata.Metadata,
+     *      org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void addMetadata(Metadata m, Product product)
+            throws CatalogException {
+        CompleteProduct p = CATALOG_CACHE.get(product.getProductId());
+
+        if (p == null) {
+        	// move product from index to cache
+        	// it will be moved back after metadata is added
+        	p = getCompleteProductById(product.getProductId(), true, true);
+        	LOG.log(Level.FINE, "Product not found in local cache, retrieved from index");
+        	removeProduct(product);        		
+        }
+        
+        if (p == null) {
+            throw new CatalogException("Product ["+ product.getProductName()
+            		                     + "] not found either in local cache or in index");
+
+        } else {
+            p.setMetadata(m);
+            if (hasMetadataAndRefs(p)) {
+                LOG.log(Level.FINE,
+                        "metadata and references present for product: ["
+                                + product.getProductId() + "]");
+                addCompleteProductToIndex(p);
+                // now remove its entry from the cache
+                CATALOG_CACHE.remove(product.getProductId());
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#removeMetadata(org.apache.oodt.cas.metadata.Metadata,
+     *      org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void removeMetadata(Metadata m, Product product)
+            throws CatalogException {
+        CompleteProduct p = CATALOG_CACHE.get(product.getProductId());
+        
+        if (p == null) {
+            // not in local cache, get doc and rewrite index
+            String prodId = product.getProductId();
+            p = getCompleteProductById(prodId, true, true);
+            removeProductDocument(product);
+        }
+
+        if (p == null) {
+            // not in index
+            throw new CatalogException(
+                    "Attempt to remove metadata to a product: ["
+                            + product.getProductName()
+                            + "] that isn't in the index or the local cache!");
+
+        }
+
+        Metadata currMet = p.getMetadata();
+        List<String> metadataTypes = new ArrayList<String>();
+
+        if (valLayer!=null) {
+	        try {
+	        		// remove metadata elements specified by validation layer
+	        		for (Element element : valLayer.getElements(product.getProductType())) {
+	        			metadataTypes.add(element.getElementName());
+	        		}
+	        } catch (ValidationLayerException e) {
+	            e.printStackTrace();
+	            throw new CatalogException(
+	                    "ValidationLayerException when trying to obtain element list for product type: "
+	                            + product.getProductType().getName()
+	                            + ": Message: " + e.getMessage());
+	        }
+        } else {
+        	// remove all metadata
+        	metadataTypes = currMet.getAllKeys();
+        }
+
+        for (String name : metadataTypes) {
+            currMet.removeMetadata(name);
+        }
+
+        p.setMetadata(currMet);
+
+        if (hasMetadataAndRefs(p)) {
+            LOG.log(Level.FINE,
+                    "metadata and references present for product: ["
+                            + product.getProductId() + "]");
+            addCompleteProductToIndex(p);
+            // now remove its entry from the cache
+            CATALOG_CACHE.remove(product.getProductId());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#addProduct(org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void addProduct(Product product)
+            throws CatalogException {
+        CompleteProduct p = CATALOG_CACHE.get(product
+                .getProductId());
+
+        if (p == null) {
+            // haven't cached this product yet, so let's cache it
+            CompleteProduct completeProduct = new CompleteProduct();
+
+            // NOTE: reuse existing ID if possible
+            if (product.getProductId() == null) {
+	            synchronized (completeProduct) {
+	                // now generate a unique ID for the product
+	                UUID prodUUID = generator.generateTimeBasedUUID();
+	                product.setProductId(prodUUID.toString());
+	            }
+            }
+
+            completeProduct.setProduct(product);
+            CATALOG_CACHE.put(product.getProductId(), completeProduct);
+
+        } else {
+            throw new CatalogException(
+                    "Attempt to add a product that already existed: product: ["
+                            + product.getProductName() + "]");
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#modifyProduct(org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void modifyProduct(Product product)
+            throws CatalogException {
+        if (CATALOG_CACHE.get(product.getProductId()) != null) {
+            LOG.log(Level.FINE, "Modifying product: [" + product.getProductId()
+                    + "]: found product in cache!");
+            CompleteProduct cp = CATALOG_CACHE.get(product
+                    .getProductId());
+            cp.setProduct(product);
+        } else {
+            // need to grab the metadata for the existing product, and make sure
+            // we don't lose it
+            Metadata metadata = getMetadata(product);
+
+            CompleteProduct completeProduct = new CompleteProduct();
+            completeProduct.setMetadata(metadata);
+
+            // now remove the product's document from the catalog
+            removeProductDocument(product);
+
+            // now add it back
+            completeProduct.setProduct(product);
+            addCompleteProductToIndex(completeProduct);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#removeProduct(org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void removeProduct(Product product)
+            throws CatalogException {
+        removeProductDocument(product);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#setProductTransferStatus(org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void setProductTransferStatus(Product product)
+            throws CatalogException {
+        LOG.log(Level.FINE,
+                "LuceneCatalog: seting product transfer status to: ["
+                        + product.getTransferStatus() + "] for " + "product: ["
+                        + product.getProductId() + "]");
+        modifyProduct(product);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#addProductReferences(org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public synchronized void addProductReferences(Product product)
+            throws CatalogException {
+        CompleteProduct p = CATALOG_CACHE.get(product
+                .getProductId());
+
+        if (p == null) {
+        	// move product from index to cache
+        	// it will be moved back after metadata is added
+        	p = getCompleteProductById(product.getProductId(), true, true);
+        	LOG.log(Level.FINE, "Product not found in local cache, retrieved from index");
+        	removeProduct(product);        		
+        }
+        
+        if (p == null) {
+            throw new CatalogException("Product ["+ product.getProductName()
+            		                     + "] not found either in local cache or in index");
+ 
+        } else {
+            p.getProduct().setProductReferences(product.getProductReferences());
+            if (hasMetadataAndRefs(p)) {
+                LOG.log(Level.FINE,
+                        "metadata and references present for product: ["
+                                + product.getProductId() + "]");
+                addCompleteProductToIndex(p);
+                // now remove its entry from the cache
+                CATALOG_CACHE.remove(product.getProductId());
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProductById(java.lang.String)
+     */
+    public Product getProductById(String productId) throws CatalogException {
+        CompleteProduct prod = getCompleteProductById(productId, false);
+        return prod.getProduct();
+    }
+
+    private Product getProductById(String productId, boolean getRefs)
+            throws CatalogException {
+        CompleteProduct prod = getCompleteProductById(productId, getRefs);
+        return prod.getProduct();
+    }
+
+    private CompleteProduct getCompleteProductById(String productId)
+            throws CatalogException {
+        return getCompleteProductById(productId, false);
+    }
+
+    private CompleteProduct getCompleteProductById(String productId,
+            boolean getRefs) throws CatalogException {
+        return getCompleteProductById(productId, getRefs, false);
+    }
+
+    private CompleteProduct getCompleteProductById(String productId,
+            boolean getRefs, boolean getMet) throws CatalogException {
+        IndexSearcher searcher = null;
+        try {
+            searcher = new IndexSearcher(indexFilePath);
+            Term productIdTerm = new Term("product_id", productId);
+            org.apache.lucene.search.Query query = new TermQuery(productIdTerm);
+            Hits hits = searcher.search(query);
+
+            // should be exactly 1 hit
+            if (hits.length() == 0) {
+            	throw new CatalogException("Product: [" + productId + "] NOT found in the catalog!");
+            } else if (hits.length() > 1) {
+                throw new CatalogException("Product: [" + productId+ "] is not unique in the catalog!");
+            }
+
+            Document productDoc = hits.doc(0);
+            CompleteProduct prod = toCompleteProduct(productDoc, getRefs,
+                    getMet);
+            return prod;
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: ["
+                            + indexFilePath + "] for search: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProductByName(java.lang.String)
+     */
+    public Product getProductByName(String productName) throws CatalogException {
+        return getProductByName(productName, false);
+    }
+
+    private Product getProductByName(String productName, boolean getRefs)
+            throws CatalogException {
+        IndexSearcher searcher = null;
+        try {
+            searcher = new IndexSearcher(indexFilePath);
+            Term productIdTerm = new Term("product_name", productName);
+            org.apache.lucene.search.Query query = new TermQuery(productIdTerm);
+            Sort sort = new Sort(new SortField("CAS.ProductReceivedTime",
+                    SortField.STRING, true));
+            Hits hits = searcher.search(query, sort);
+
+            // should be > 0 hits
+            if (hits.length() > 0) {
+                // just get the first hit back
+                Document productDoc = hits.doc(0);
+                CompleteProduct prod = toCompleteProduct(productDoc, getRefs,
+                        false);
+                return prod.getProduct();
+            } else {
+                LOG.log(Level.FINEST, "Request for product by name: ["
+                        + productName + "] returned no results");
+                return null;
+            }
+
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: ["
+                            + indexFilePath + "] for search: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProductReferences(org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    public List<Reference> getProductReferences(Product product) throws CatalogException {
+        Product prod = getProductById(product.getProductId(), true);
+        if (prod != null) {
+            return prod.getProductReferences();
+        } else
+            return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProducts()
+     */
+    public List<Product> getProducts() throws CatalogException {
+        return getProducts(false);
+    }
+
+    private List<Product> getProducts(boolean getRefs) throws CatalogException {
+        IndexSearcher searcher = null;
+        List<Product> products = null;
+
+        try {
+            searcher = new IndexSearcher(indexFilePath);
+            Term productIdTerm = new Term("myfield", "myvalue");
+            org.apache.lucene.search.Query query = new TermQuery(productIdTerm);
+            Sort sort = new Sort(new SortField("CAS.ProductReceivedTime",
+                    SortField.STRING, true));
+            Hits hits = searcher.search(query, sort);
+
+            // should be > 0 hits
+            if (hits.length() > 0) {
+                products = new Vector<Product>(hits.length());
+                for (int i = 0; i < hits.length(); i++) {
+                    Document productDoc = hits.doc(i);
+                    CompleteProduct prod = toCompleteProduct(productDoc,
+                            getRefs, false);
+                    products.add(prod.getProduct());
+                }
+            } else {
+                LOG.log(Level.FINEST,
+                        "Request for products returned no results");
+                return null;
+            }
+
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: ["
+                            + indexFilePath + "] for search: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+
+        return products;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProductsByProductType(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public List<Product> getProductsByProductType(ProductType type)
+            throws CatalogException {
+        return getProductsByProductType(type, false);
+    }
+
+    private List<Product> getProductsByProductType(ProductType type, boolean getRefs)
+            throws CatalogException {
+        IndexSearcher searcher = null;
+        List<Product> products = null;
+
+        try {
+            searcher = new IndexSearcher(indexFilePath);
+            Term productIdTerm = new Term("product_type_id", type
+                    .getProductTypeId());
+            org.apache.lucene.search.Query query = new TermQuery(productIdTerm);
+            Sort sort = new Sort(new SortField("CAS.ProductReceivedTime",
+                    SortField.STRING, true));
+            Hits hits = searcher.search(query, sort);
+
+            // should be > 0 hits
+            if (hits.length() > 0) {
+                products = new Vector<Product>(hits.length());
+                for (int i = 0; i < hits.length(); i++) {
+                    Document productDoc = hits.doc(i);
+                    CompleteProduct prod = toCompleteProduct(productDoc,
+                            getRefs, false);
+                    products.add(prod.getProduct());
+                }
+            } else {
+                LOG.log(Level.FINEST, "Request for products by type: ["
+                        + type.getProductTypeId() + "] returned no results");
+                return null;
+            }
+
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: ["
+                            + indexFilePath + "] for search: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+
+        return products;
+    }
+
+    public Metadata getMetadata(Product product) throws CatalogException {
+        IndexSearcher searcher = null;
+        try {
+            searcher = new IndexSearcher(indexFilePath);
+            Term productIdTerm = new Term("product_id", product.getProductId());
+            org.apache.lucene.search.Query query = new TermQuery(productIdTerm);
+            Hits hits = searcher.search(query);
+
+            // should be exactly 1 hit
+            if (hits.length() != 1) {
+                throw new CatalogException("Product: ["
+                        + product.getProductId()
+                        + "] is not unique in the catalog! Num Hits: ["
+                        + hits.length() + "]");
+            }
+
+            Document productDoc = hits.doc(0);
+            CompleteProduct prod = toCompleteProduct(productDoc, false, true);
+            return prod.getMetadata();
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: ["
+                            + indexFilePath + "] for search: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+    }
+    
+    public Metadata getReducedMetadata(Product product, List<String> elements) throws CatalogException {
+        Metadata fullMetadata = getMetadata(product);
+        Metadata reducedMetadata = new Metadata();
+        for (String element : elements) {
+            if (fullMetadata.containsKey(element))
+                reducedMetadata.replaceMetadata(element, fullMetadata.getAllMetadata(element));
+        }
+        return reducedMetadata;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#query(org.apache.oodt.cas.filemgr.structs.Query,
+     *      org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public List<String> query(Query query, ProductType type) throws CatalogException {
+        // paginate products returns full products, but the query method
+        // is expected to return product ids
+        List<Product> fullProducts = paginateQuery(query, type, -1, null);
+        List<String> productIds = null;
+
+        if (fullProducts != null && fullProducts.size() > 0) {
+            productIds = new Vector<String>(fullProducts.size());
+
+            for (Iterator<Product> i = fullProducts.iterator(); i.hasNext();) {
+                Product p = i.next();
+                productIds.add(p.getProductId());
+            }
+        }
+
+        return productIds;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getTopNProducts(int)
+     */
+    public List<Product> getTopNProducts(int n) throws CatalogException {
+        List<Product> products = null;
+        IndexSearcher searcher = null;
+
+        try {
+            searcher = new IndexSearcher(indexFilePath);
+
+            // construct a Boolean query here
+            BooleanQuery booleanQuery = new BooleanQuery();
+            TermQuery tq = new TermQuery(new Term("myfield", "myvalue"));
+            booleanQuery.add(tq, BooleanClause.Occur.MUST);
+
+            Sort sort = new Sort(new SortField("CAS.ProductReceivedTime",
+                    SortField.STRING, true));
+            LOG.log(Level.FINE, "Querying LuceneCatalog: q: [" + booleanQuery
+                    + "]");
+            Hits hits = searcher.search(booleanQuery, sort);
+            if (hits.length() > 0) {
+                products = new Vector<Product>(n);
+                int i = 0;
+                while (products.size() < Math.min(n, hits.length())) {
+                    Document productDoc = hits.doc(i);
+                    CompleteProduct prod = toCompleteProduct(productDoc, false,
+                            false);
+                    products.add(prod.getProduct());
+                    i++;
+                }
+            } else {
+                LOG.log(Level.WARNING, "Top N query produced no products!");
+            }
+
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: ["
+                            + indexFilePath + "] for search: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+
+        return products;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getTopNProducts(int,
+     *      org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public List<Product> getTopNProducts(int n, ProductType type)
+            throws CatalogException {
+        int numPages = 1;
+        if (n > this.pageSize) {
+            numPages = n / this.pageSize + (n % this.pageSize == 0 ? 0 : 1);
+        }
+
+        List<Product> products = new Vector<Product>(n);
+        Query query = new Query();
+
+        for (int pageNum = 1; pageNum < numPages + 1; pageNum++) {
+            List<Product> pageProducts = paginateQuery(query, type, pageNum, null);
+            products.addAll(pageProducts);
+        }
+
+        return products;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getValidationLayer()
+     */
+    public ValidationLayer getValidationLayer() throws CatalogException {
+        return valLayer;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getNumProducts(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public int getNumProducts(ProductType type) throws CatalogException {
+        Query query = new Query();
+        return getNumHits(query, type);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.util.Pagination#getFirstPage(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public ProductPage getFirstPage(ProductType type) {
+        ProductPage firstPage = new ProductPage();
+        List<Product> products = null;
+        Query query = new Query();
+        
+        // now construct the page
+        firstPage.setPageNum(1);
+        firstPage.setPageSize(pageSize);
+        try {
+          products = paginateQuery(query, type, 1, firstPage);
+        } catch (CatalogException e) {
+            LOG.log(Level.WARNING,
+                    "CatalogException getting first page for product type: ["
+                            + type.getProductTypeId()
+                            + "] from catalog: Message: " + e.getMessage());
+            return null;
+        }
+        // There are no products and thus no first page
+        if (products == null || (products != null && products.size() == 0)) {
+        		return null;
+        }
+
+        firstPage.setPageProducts(products);
+
+        return firstPage;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.util.Pagination#getLastProductPage(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public ProductPage getLastProductPage(ProductType type) {
+        ProductPage lastPage = new ProductPage();
+        ProductPage firstPage = getFirstPage(type);
+        List<Product> products = null;
+        Query query = new Query();
+        
+        // now construct the page
+        lastPage.setPageNum(firstPage.getTotalPages());
+        lastPage.setPageSize(pageSize);
+        try {
+            products = paginateQuery(query, type, firstPage.getTotalPages(), lastPage);
+        } catch (CatalogException e) {
+          	LOG.log(Level.WARNING,
+                  "CatalogException getting last page for product type: ["
+                          + type.getProductTypeId()
+                          + "] from catalog: Message: " + e.getMessage());
+          	return null;
+        }
+        // There are no products thus there is no last page
+        if (products == null || (products != null && products.size() == 0)) {
+        	  return null;
+        }
+        lastPage.setPageProducts(products);
+
+        return lastPage;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.util.Pagination#getNextPage(org.apache.oodt.cas.filemgr.structs.ProductType,
+     *      org.apache.oodt.cas.filemgr.structs.ProductPage)
+     */
+    public ProductPage getNextPage(ProductType type, ProductPage currentPage) {
+        if (currentPage == null) {
+            return getFirstPage(type);
+        }
+
+        if (currentPage.isLastPage()) {
+            return currentPage;
+        }
+
+        List<Product> products = null;
+        ProductPage nextPage = new ProductPage();
+        Query query = new Query();
+
+        // now construct the page
+        nextPage.setPageNum(currentPage.getPageNum() + 1);
+        nextPage.setPageSize(pageSize);
+        try {
+            products = paginateQuery(query, type, currentPage.getPageNum() + 1, nextPage);
+        } catch (CatalogException e) {
+            LOG.log(Level.WARNING,
+                  "CatalogException getting next page for product type: ["
+                          + type.getProductTypeId()
+                          + "] from catalog: Message: " + e.getMessage());
+            return null;
+        }
+        // There are no products and thus no next page
+        if (products == null || (products != null && products.size() == 0)) {
+        	  return null;
+        }
+        nextPage.setPageProducts(products);
+
+        return nextPage;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.util.Pagination#getPrevPage(org.apache.oodt.cas.filemgr.structs.ProductType,
+     *      org.apache.oodt.cas.filemgr.structs.ProductPage)
+     */
+    public ProductPage getPrevPage(ProductType type, ProductPage currentPage) {
+        if (currentPage == null) {
+            return getFirstPage(type);
+        }
+
+        if (currentPage.isFirstPage()) {
+            return currentPage;
+        }
+        List<Product> products = null;
+        ProductPage prevPage = new ProductPage();
+        Query query = new Query();
+
+        // now construct the page
+        prevPage = new ProductPage();
+        prevPage.setPageNum(currentPage.getPageNum() - 1);
+        prevPage.setPageSize(pageSize);
+        try {
+            products = paginateQuery(query, type, currentPage.getPageNum() - 1, prevPage);
+        } catch (CatalogException e) {
+            LOG.log(Level.WARNING,
+                    "CatalogException getting prev page for product type: ["
+                            + type.getProductTypeId()
+                            + "] from catalog: Message: " + e.getMessage());
+            return null;
+        }
+        
+        // There are no products and thus no pages
+        if (products == null || (products != null && products.size() == 0)) {
+        	  return null;
+        }
+        prevPage.setPageProducts(products);
+
+        return prevPage;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.Catalog#pagedQuery(org.apache.oodt.cas.filemgr.structs.Query,
+     *      org.apache.oodt.cas.filemgr.structs.ProductType, int)
+     */
+    public ProductPage pagedQuery(Query query, ProductType type, int pageNum)
+            throws CatalogException {
+        try {
+            ProductPage retPage = new ProductPage();
+            retPage.setPageNum(pageNum);
+            retPage.setPageSize(pageSize);
+            retPage.setPageProducts(paginateQuery(query, type, pageNum, retPage));
+            return retPage;
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "CatalogException when doing paged product query: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        }
+
+    }
+
+    private synchronized void removeProductDocument(Product product)
+            throws CatalogException {
+        IndexReader reader = null;
+
+        try {
+            reader = IndexReader.open(indexFilePath);
+            LOG.log(Level.FINE,
+                    "LuceneCatalog: remove document from index for product: ["
+                            + product.getProductId() + "]");
+            reader.deleteDocuments(new Term("product_id", product
+                    .getProductId()));
+        } catch (IOException e) {
+            LOG.log(Level.WARNING, "Exception removing product: ["
+                    + product.getProductName() + "] from index: Message: "
+                    + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (Exception ignore) {
+                }
+
+                reader = null;
+            }
+
+        }
+    }
+
+    private synchronized void addCompleteProductToIndex(CompleteProduct cp)
+            throws CatalogException {
+        IndexWriter writer = null;
+
+        File indexDir = new File(indexFilePath);
+
+        boolean createIndex = false;
+
+        if (indexDir.exists() && indexDir.isDirectory()) {
+            createIndex = false;
+        } else
+            createIndex = true;
+
+        try {
+            writer = new IndexWriter(indexFilePath, new StandardAnalyzer(),
+                    createIndex);
+            writer.setCommitLockTimeout(this.commitLockTimeout * 1000);
+            writer.setWriteLockTimeout(this.writeLockTimeout * 1000);
+            writer.setMergeFactor(this.mergeFactor);
+
+            Document doc = toDoc(cp.getProduct(), cp.getMetadata());
+            writer.addDocument(doc);
+            // take this out for now
+            // TODO: determine a better way to optimize the index
+            // writer.optimize();
+        } catch (IOException e) {
+            LOG.log(Level.WARNING, "Unable to index product: ["
+                    + cp.getProduct().getProductName() + "]: Message: "
+                    + e.getMessage(), e);
+            throw new CatalogException("Unable to index product: ["
+                    + cp.getProduct().getProductName() + "]: Message: "
+                    + e.getMessage());
+        } finally {
+            try {
+                writer.close();
+            } catch (Exception ignore) {
+            }
+            writer = null;
+        }
+
+    }
+
+    private CompleteProduct toCompleteProduct(Document doc) {
+        return toCompleteProduct(doc, true, true);
+    }
+
+    private CompleteProduct toCompleteProduct(Document doc, boolean getRefs,
+            boolean getMetadata) {
+        Product product = new Product();
+        Metadata metadata = new Metadata();
+        CompleteProduct completeProduct = new CompleteProduct();
+
+        product.setProductId(doc.get("product_id"));
+        product.setProductName(doc.get("product_name"));
+        product.setProductStructure(doc.get("product_structure"));
+        product.setTransferStatus(doc.get("product_transfer_status"));
+
+        ProductType type = new ProductType();
+        type.setDescription(doc.get("product_type_desc"));
+        type.setProductTypeId(doc.get("product_type_id"));
+        type.setName(doc.get("product_type_name"));
+        type.setProductRepositoryPath(doc.get("product_type_repoPath"));
+        type.setVersioner(doc.get("product_type_versioner"));
+        product.setProductType(type);
+
+        if (getMetadata) {
+            List<String> names = new ArrayList<String>();
+
+            if (valLayer!=null) {
+            	// only add metadata elements specified by validation layer
+	            try {
+	                for (Element element : valLayer.getElements(type)) {
+	                	names.add(element.getElementName());
+	                }
+	            } catch (ValidationLayerException e) {
+	                LOG.log(Level.WARNING,
+	                        "Unable to obtain metadata for product: ["
+	                                + product.getProductName() + "]: Message: "
+	                                + e.getMessage());
+	            }
+            } else {
+            	// add all metadata elements found in document
+            	Enumeration<Field> fields = doc.fields();
+            	while (fields.hasMoreElements()) {
+            		Field field = fields.nextElement();
+            		if (!names.contains(field.name())) {
+            				names.add(field.name());
+            		}
+            	}
+            	
+            }
+
+            // loop over field names to add to metadata
+            for (String name : names) {
+            		if (metadata.getAllMetadata(name)==null || metadata.getAllMetadata(name).size()==0) {
+	                String[] elemValues = doc.getValues(name);
+	                	
+	                if (elemValues != null && elemValues.length > 0) {
+	                    for (int j = 0; j < elemValues.length; j++) {
+	                        metadata.addMetadata(name, elemValues[j]);
+	                    }
+	                }
+            		}
+            }
+
+            completeProduct.setMetadata(metadata);
+        }
+
+        if (getRefs) {
+            // now add the references
+            String[] origRefs = doc.getValues("reference_orig");
+            String[] dataStoreRefs = doc.getValues("reference_data_store");
+            String[] refLengths = doc.getValues("reference_fileSize");
+            String[] refMimeTypes = doc.getValues("reference_mimeType");
+
+            if ((origRefs.length == dataStoreRefs.length)
+                    && (origRefs.length == refLengths.length)) {
+                List<Reference> references = new Vector<Reference>();
+                for (int i = 0; i < origRefs.length; i++) {
+                    Reference r = new Reference();
+                    r.setOrigReference(origRefs[i]);
+                    r.setDataStoreReference(dataStoreRefs[i]);
+                    r.setFileSize((Long.parseLong(refLengths[i])));
+                    if (refMimeTypes != null)
+                        r.setMimeType(refMimeTypes[i]);
+                    references.add(r);
+                }
+
+                product.setProductReferences(references);
+            } else {
+                LOG.log(Level.WARNING, "Number of original refs: ["
+                        + origRefs.length + "] for product: ["
+                        + product.getProductName()
+                        + "] not equivalent to number of data store refs: ["
+                        + dataStoreRefs.length
+                        + "]: Skipping product references");
+            }
+        }
+
+        completeProduct.setProduct(product);
+        return completeProduct;
+    }
+
+    private Document toDoc(Product product, Metadata metadata) {
+        Document doc = new Document();
+
+        // add the product information
+        doc.add(new Field("product_id", product.getProductId(),
+                Field.Store.YES, Field.Index.UN_TOKENIZED));
+        doc.add(new Field("product_name", product.getProductName(),
+                Field.Store.YES, Field.Index.UN_TOKENIZED));
+        doc.add(new Field("product_structure", product.getProductStructure(),
+                Field.Store.YES, Field.Index.UN_TOKENIZED));
+        doc
+                .add(new Field("product_transfer_status", product
+                        .getTransferStatus(), Field.Store.YES,
+                        Field.Index.UN_TOKENIZED));
+
+        // product type
+        doc
+                .add(new Field("product_type_id", product.getProductType()
+                        .getProductTypeId(), Field.Store.YES,
+                        Field.Index.UN_TOKENIZED));
+        doc.add(new Field("product_type_name", product.getProductType()
+                .getName(), Field.Store.YES, Field.Index.UN_TOKENIZED));
+        doc.add(new Field("product_type_desc", product.getProductType()
+                .getDescription() != null ? product.getProductType()
+                .getDescription() : "", Field.Store.YES, Field.Index.NO));
+        doc.add(new Field("product_type_repoPath", product.getProductType()
+                .getProductRepositoryPath() != null ? product.getProductType()
+                .getProductRepositoryPath() : "", Field.Store.YES,
+                Field.Index.NO));
+        doc.add(new Field("product_type_versioner", product.getProductType()
+                .getVersioner() != null ? product.getProductType()
+                .getVersioner() : "", Field.Store.YES, Field.Index.NO));
+        
+        // write metadata fields to the Lucene document
+        List<String> keys = new ArrayList<String>();
+        // validation layer: add only specifically configured keys
+        if (valLayer!=null) {
+        	List<Element> elements = quietGetElements(product.getProductType());
+        	for (Iterator<Element> i = elements.iterator(); i.hasNext();) {
+                Element element = i.next();
+                String key = element.getElementName();
+                keys.add(key);
+        	}
+        // no validation layer: add all keys that are NOT already in doc
+        // (otherwise some keys such as the product_* keys are duplicated)
+        } else {
+        	for (String key : metadata.getAllKeys()) {
+        		if (doc.getField(key)==null) {
+        				keys.add(key);
+        		}
+        	}
+        }
+
+
+        for (String key : keys) {
+          List<String> values = metadata.getAllMetadata(key);
+
+            if (values == null) {
+                LOG
+                        .log(
+                                Level.WARNING,
+                                "No Metadata specified for product ["
+                                        + product.getProductName()
+                                        + "] for required field ["
+                                        + key
+                                        + "]: Attempting to continue processing metadata");
+                continue;
+            }
+
+            for (Iterator<String> j = values.iterator(); j.hasNext();) {
+                String val = j.next();
+                doc.add(new Field(key, val, Field.Store.YES,
+                        Field.Index.UN_TOKENIZED));
+            }
+        }
+
+        // add the product references
+        for (Iterator<Reference> i = product.getProductReferences().iterator(); i
+                .hasNext();) {
+            Reference r = i.next();
+            doc.add(new Field("reference_orig", r.getOrigReference(),
+                    Field.Store.YES, Field.Index.NO));
+            doc
+                    .add(new Field("reference_data_store", r
+                            .getDataStoreReference(), Field.Store.YES,
+                            Field.Index.NO));
+            doc.add(new Field("reference_fileSize", String.valueOf(r
+                    .getFileSize()), Field.Store.YES, Field.Index.NO));
+            doc.add(new Field("reference_mimeType", r.getMimeType() != null ? r
+                    .getMimeType().getName() : "", Field.Store.YES,
+                    Field.Index.UN_TOKENIZED));
+        }
+
+        // add special field for all products
+        // then can use that field to retrieve back all products
+        doc.add(new Field("myfield", "myvalue", Field.Store.NO,
+                Field.Index.TOKENIZED));
+
+        return doc;
+    }
+
+    private boolean hasMetadataAndRefs(CompleteProduct cp) {
+        if (cp.getMetadata() != null && cp.getProduct() != null) {
+            if (cp.getReferences() != null && cp.getReferences().size() > 0) {
+                // make sure there is a data store ref for each of the refs
+                for (Iterator<Reference> i = cp.getReferences().iterator(); i.hasNext();) {
+                    Reference r = i.next();
+                    if (r.getDataStoreReference() == null
+                            || (r.getDataStoreReference() != null && r
+                                    .getDataStoreReference().equals(""))) {
+                        return false;
+                    }
+                }
+
+                return true;
+            } else
+                return false;
+        } else
+            return false;
+
+    }
+
+    private int getNumHits(Query query, ProductType type)
+            throws CatalogException {
+        IndexSearcher searcher = null;
+
+        int numHits = -1;
+
+        try {
+            searcher = new IndexSearcher(indexFilePath);
+
+            // construct a Boolean query here
+            BooleanQuery booleanQuery = new BooleanQuery();
+
+            // add the product type as the first clause
+            TermQuery prodTypeTermQuery = new TermQuery(new Term(
+                    "product_type_id", type.getProductTypeId()));
+            booleanQuery.add(prodTypeTermQuery, BooleanClause.Occur.MUST);
+
+            //convert filemgr query into a lucene query
+            for (QueryCriteria queryCriteria : query.getCriteria()) 
+                booleanQuery.add(this.getQuery(queryCriteria), BooleanClause.Occur.MUST);
+
+            LOG.log(Level.FINE, "Querying LuceneCatalog: q: [" + booleanQuery
+                    + "]");
+            Hits hits = searcher.search(booleanQuery);
+            numHits = hits.length();
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: ["
+                            + indexFilePath + "] for search: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+
+        return numHits;
+    }
+
+    private List<Product> paginateQuery(Query query, ProductType type, int pageNum, ProductPage page)
+            throws CatalogException {
+        List<Product> products = null;
+        IndexSearcher searcher = null;
+
+        boolean doSkip = true;
+
+        if (pageNum == -1) {
+            doSkip = false;
+        }
+
+        try {
+            searcher = new IndexSearcher(indexFilePath);
+
+            // construct a Boolean query here
+            BooleanQuery booleanQuery = new BooleanQuery();
+
+            // add the product type as the first clause
+            TermQuery prodTypeTermQuery = new TermQuery(new Term(
+                    "product_type_id", type.getProductTypeId()));
+            booleanQuery.add(prodTypeTermQuery, BooleanClause.Occur.MUST);
+            
+            //convert filemgr query into a lucene query
+            for (QueryCriteria queryCriteria : query.getCriteria()) 
+                booleanQuery.add(this.getQuery(queryCriteria), BooleanClause.Occur.MUST);
+            
+            Sort sort = new Sort(new SortField("CAS.ProductReceivedTime",
+                    SortField.STRING, true));
+            LOG.log(Level.FINE, "Querying LuceneCatalog: q: [" + booleanQuery
+                    + "]");
+            Hits hits = searcher.search(booleanQuery, sort);
+            
+            // Calculate page size and set it while we have the results
+            if (page != null) {
+            	page.setTotalPages(PaginationUtils.getTotalPage(hits.length(), pageSize));
+            }
+            
+            if (hits.length() > 0) {
+
+                int startNum = (pageNum - 1) * pageSize;
+                if (doSkip) {
+                    if (startNum > hits.length()) {
+                        startNum = 0;
+                    }
+
+                    products = new Vector<Product>(pageSize);
+
+                    for (int i = startNum; i < Math.min(hits.length(),
+                            (startNum + pageSize)); i++) {
+                        Document productDoc = hits.doc(i);
+                        CompleteProduct prod = toCompleteProduct(productDoc,
+                                false, false);
+                        products.add(prod.getProduct());
+                    }
+                } else {
+                    products = new Vector<Product>(hits.length());
+                    for (int i = 0; i < hits.length(); i++) {
+                        Document productDoc = hits.doc(i);
+                        CompleteProduct prod = toCompleteProduct(productDoc,
+                                false, false);
+                        products.add(prod.getProduct());
+                    }
+                }
+            } else {
+                LOG.log(Level.WARNING, "Query: [" + query
+                        + "] for Product Type: [" + type.getProductTypeId()
+                        + "] returned no results");
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: ["
+                            + indexFilePath + "] for search: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+
+        return products;
+    }
+
+    private org.apache.lucene.search.Query getQuery(QueryCriteria queryCriteria) throws CatalogException {
+        if (queryCriteria instanceof BooleanQueryCriteria) {
+            BooleanQuery booleanQuery = new BooleanQuery();
+            BooleanClause.Occur occur = null;
+            switch (((BooleanQueryCriteria) queryCriteria).getOperator()) {
+            case BooleanQueryCriteria.AND:
+                occur = BooleanClause.Occur.MUST;
+                break;
+            case BooleanQueryCriteria.OR:
+                occur = BooleanClause.Occur.SHOULD;
+                break;
+            case BooleanQueryCriteria.NOT:
+                occur = BooleanClause.Occur.MUST_NOT;
+                booleanQuery.add(new WildcardQuery(new Term(((BooleanQueryCriteria) queryCriteria)
+                        .getTerms().get(0).getElementName(), "*")), BooleanClause.Occur.SHOULD);
+                break;
+            default:
+                throw new CatalogException("Invalid BooleanQueryCriteria opertor [" 
+                        + ((BooleanQueryCriteria) queryCriteria).getOperator() + "]");
+            }
+            for (QueryCriteria qc : ((BooleanQueryCriteria) queryCriteria).getTerms())
+                booleanQuery.add(this.getQuery(qc), occur);
+
+            return booleanQuery;
+        } else if (queryCriteria instanceof TermQueryCriteria) {
+            String val = ((TermQueryCriteria) queryCriteria).getValue();
+            return new TermQuery(new Term(queryCriteria.getElementName(), val));
+        } else if (queryCriteria instanceof RangeQueryCriteria) {
+            String startVal = ((RangeQueryCriteria) queryCriteria).getStartValue();
+            String endVal = ((RangeQueryCriteria) queryCriteria).getEndValue();
+            boolean inclusive = ((RangeQueryCriteria) queryCriteria).getInclusive();
+            Term startTerm = null, endTerm = null;
+            if (!startVal.equals("")) {
+                startTerm = new Term(queryCriteria.getElementName(), startVal);
+            }
+
+            if (!endVal.equals("")) {
+                endTerm = new Term(queryCriteria.getElementName(), endVal);
+            }
+
+            return new RangeQuery(startTerm, endTerm, inclusive);
+        }else {
+            throw new CatalogException("Invalid QueryCriteria ["
+                    + queryCriteria.getClass().getCanonicalName() + "]");
+        }
+    }
+    
+    private List<Element> quietGetElements(ProductType type) {
+        List<Element> elementList = new Vector<Element>();
+
+        try {
+            elementList = valLayer.getElements(type);
+        } catch (Exception e) {
+            LOG.log(Level.WARNING,
+                    "Exception obtaining elements for product type: ["
+                            + type.getName() + "]: Message: " + e.getMessage());
+        }
+
+        return elementList;
+    }
+
+    private class CompleteProduct {
+        private Metadata metadata = null;
+
+        private Product product = null;
+
+        public CompleteProduct(Metadata met, List<Reference> refs, Product p) {
+            this.metadata = met;
+            this.product = p;
+            this.product.setProductReferences(refs);
+        }
+
+        public CompleteProduct() {
+        }
+
+        /**
+         * @return Returns the metadata.
+         */
+        public Metadata getMetadata() {
+            return metadata;
+        }
+
+        /**
+         * @param metadata
+         *            The metadata to set.
+         */
+        public void setMetadata(Metadata metadata) {
+            this.metadata = metadata;
+        }
+
+        /**
+         * @return Returns the product.
+         */
+        public Product getProduct() {
+            return product;
+        }
+
+        /**
+         * @param product
+         *            The product to set.
+         */
+        public void setProduct(Product product) {
+            this.product = product;
+        }
+
+        /**
+         * @return Returns the references.
+         */
+        public List<Reference> getReferences() {
+            return product.getProductReferences();
+        }
+
+        /**
+         * @param references
+         *            The references to set.
+         */
+        public void setReferences(List<Reference> references) {
+            this.product.setProductReferences(references);
+        }
+
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/LuceneCatalogFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/LuceneCatalogFactory.java
new file mode 100644
index 0000000..35bfe7c
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/LuceneCatalogFactory.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.util.GenericFileManagerObjectFactory;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+
+//Lucene imports
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.index.IndexWriter;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory for creating {@link Lucene}-based {@link Catalog}s.
+ * </p>
+ * 
+ */
+public class LuceneCatalogFactory implements CatalogFactory {
+
+	/* path to the index directory for lucene catalogs */
+	private String indexFilePath = null;
+
+	/* our validation layer */
+	private ValidationLayer validationLayer = null;
+	
+	/* the page size for pagination */
+	private int pageSize = -1;
+	
+	/* the write lock timeout */
+	private long writeLockTimeOut = -1L;
+	
+	/* the commit lock timeout */
+	private long commitLockTimeOut = -1L;
+	
+	/* the merge factor */
+	private int mergeFactor = -1;
+	
+	/* Whether or not to enforce strict definition of metadata fields:
+	 * 'lenient=false' means that all metadata fields need to be explicitly defined in the XML configuration file */
+	private boolean lenientFields = false;
+	
+	/* our log stream */
+    private static final Logger LOG = Logger.getLogger(LuceneCatalogFactory.class.getName());
+    
+	/**
+	 * 
+	 */
+	public LuceneCatalogFactory() throws IllegalArgumentException {
+		indexFilePath = System
+				.getProperty("org.apache.oodt.cas.filemgr.catalog.lucene.idxPath");
+		if (indexFilePath == null) {
+			throw new IllegalArgumentException(
+					"error initializing lucene catalog: "
+							+ "[org.apache.oodt.cas.filemgr.catalog.lucene.idxPath="
+							+ indexFilePath);
+		}
+
+		//do env var replacement
+		indexFilePath = PathUtils.replaceEnvVariables(indexFilePath);
+		
+		// instantiate validation layer, unless catalog is explicitly configured for lenient fields
+		lenientFields = Boolean.parseBoolean( System.getProperty("org.apache.oodt.cas.filemgr.catalog.lucene.lenientFields", "false") );
+		if (!lenientFields) {
+			String validationLayerFactoryClass = System
+				.getProperty("filemgr.validationLayer.factory",
+						"org.apache.oodt.cas.filemgr.validation.XMLValidationLayerFactory");
+			validationLayer = GenericFileManagerObjectFactory
+				.getValidationLayerFromFactory(validationLayerFactoryClass);
+		}
+		
+		pageSize = Integer.getInteger("org.apache.oodt.cas.filemgr.catalog.lucene.pageSize", 20).intValue();
+		
+		commitLockTimeOut = Long
+				.getLong(
+						"org.apache.oodt.cas.filemgr.catalog.lucene.commitLockTimeout.seconds",
+						60).longValue();
+		writeLockTimeOut = Long
+				.getLong(
+						"org.apache.oodt.cas.filemgr.catalog.lucene.writeLockTimeout.seconds",
+						60).longValue();
+		mergeFactor = Integer.getInteger(
+				"org.apache.oodt.cas.filemgr.catalog.lucene.mergeFactor", 20)
+				.intValue();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.apache.oodt.cas.filemgr.catalog.CatalogFactory#createCatalog()
+	 */
+	public Catalog createCatalog() {
+	    File indexDir = new File(indexFilePath);
+	    // Create the index if it does not already exist
+	    IndexWriter writer = null;
+	    if (!indexDir.exists()) {
+	        try { 
+	            writer = new IndexWriter(indexDir, new StandardAnalyzer(), true);
+	        } catch (Exception e) {
+	            LOG.severe("Unable to create index: " + e.getMessage());
+	        } finally {
+	            if (writer != null) {
+	                try {
+	                    writer.close();
+	                } catch (Exception e) {
+	                    LOG.severe("Unable to close index: " + e.getMessage());
+	                }
+	            }
+	        }
+	    }
+		return new LuceneCatalog(indexFilePath, validationLayer, pageSize,
+				commitLockTimeOut, writeLockTimeOut, mergeFactor);
+	}
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/MappedDataSourceCatalog.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/MappedDataSourceCatalog.java
new file mode 100644
index 0000000..39f5164
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/MappedDataSourceCatalog.java
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+//JDK imports
+import java.util.List;
+import java.util.Properties;
+import javax.sql.DataSource;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An extension to the {@link DataSourceCatalog} where product type names are
+ * mapped to the table names in the database (to deal with large product type
+ * names, which Oracle doesn't like)
+ * </p>.
+ */
+public class MappedDataSourceCatalog extends DataSourceCatalog {
+
+    private Properties typeMap;
+
+    /**
+     * Constructs a new MappedDataSourceCatalog.
+     * 
+     * @param ds
+     *            The {@link DataSource} connection to a DBMS catalog.
+     * @param valLayer
+     *            The {@link ValidationLayer} storign the element policy.
+     * @param fieldId
+     *            Whether or not field ids should be quoted.
+     * @param pageSize
+     *            The page size of returned products via Pagination API.
+     * @param cacheUpdateMin
+     *            The amount of minutes inbetween cache updates (if needed).
+     * @param typeMap
+     *            The mapping properties mapping product type names to table
+     *            name.
+     */
+    public MappedDataSourceCatalog(DataSource ds, ValidationLayer valLayer,
+            boolean fieldId, int pageSize, long cacheUpdateMin,
+            Properties typeMap) {
+        super(ds, valLayer, fieldId, pageSize, cacheUpdateMin);
+        this.typeMap = typeMap;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog#addMetadata(
+     *      org.apache.oodt.cas.metadata.Metadata,
+     *      org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    @Override
+    public synchronized void addMetadata(Metadata metadata, Product product)
+            throws CatalogException {
+        String origProductTypeName = product.getProductType().getName();
+        product.getProductType().setName(
+                getProductTypeTableName(origProductTypeName));
+        super.addMetadata(metadata, product);
+        product.getProductType().setName(origProductTypeName);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog#addProductReferences(
+     *      org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    @Override
+    public synchronized void addProductReferences(Product product)
+            throws CatalogException {
+        String origProductTypeName = product.getProductType().getName();
+        product.getProductType().setName(
+                getProductTypeTableName(origProductTypeName));
+        super.addProductReferences(product);
+        product.getProductType().setName(origProductTypeName);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog#getMetadata(
+     *      org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    @Override
+    public Metadata getMetadata(Product product) throws CatalogException {
+        String origProductTypeName = product.getProductType().getName();
+        product.getProductType().setName(
+                getProductTypeTableName(origProductTypeName));
+        Metadata met = super.getMetadata(product);
+        product.getProductType().setName(origProductTypeName);
+        return met;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog#getProductReferences(
+     *      org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    @Override
+    public List<Reference> getProductReferences(Product product) throws CatalogException {
+        String origProductTypeName = product.getProductType().getName();
+        product.getProductType().setName(
+                getProductTypeTableName(origProductTypeName));
+        List<Reference> refs = super.getProductReferences(product);
+        product.getProductType().setName(origProductTypeName);
+        return refs;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog#modifyProduct(
+     *      org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    @Override
+    public synchronized void modifyProduct(Product product)
+            throws CatalogException {
+        String origProductTypeName = product.getProductType().getName();
+        product.getProductType().setName(
+                getProductTypeTableName(origProductTypeName));
+        super.modifyProduct(product);
+        product.getProductType().setName(origProductTypeName);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog#removeMetadata(
+     *      org.apache.oodt.cas.metadata.Metadata,
+     *      org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    @Override
+    public synchronized void removeMetadata(Metadata metadata, Product product)
+            throws CatalogException {
+        String origProductTypeName = product.getProductType().getName();
+        product.getProductType().setName(
+                getProductTypeTableName(origProductTypeName));
+        super.removeMetadata(metadata, product);
+        product.getProductType().setName(origProductTypeName);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog#removeProduct(
+     *      org.apache.oodt.cas.filemgr.structs.Product)
+     */
+    @Override
+    public synchronized void removeProduct(Product product)
+            throws CatalogException {
+        String origProductTypeName = product.getProductType().getName();
+        product.getProductType().setName(
+                getProductTypeTableName(origProductTypeName));
+        super.removeProduct(product);
+        product.getProductType().setName(origProductTypeName);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog#pagedQuery(org.apache.oodt.cas.filemgr.structs.Query,
+     *      org.apache.oodt.cas.filemgr.structs.ProductType, int)
+     */
+    @Override
+    public ProductPage pagedQuery(Query query, ProductType type, int pageNum)
+            throws CatalogException {
+        String origProductTypeName = type.getName();
+        type.setName(getProductTypeTableName(origProductTypeName));
+        ProductPage page = super.pagedQuery(query, type, pageNum);
+        type.setName(origProductTypeName);
+        return page;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog#query(org.apache.oodt.cas.filemgr.structs.Query,
+     *      org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    @Override
+    public List<String> query(Query query, ProductType type) throws CatalogException {
+        String origProductTypeName = type.getName();
+        type.setName(getProductTypeTableName(origProductTypeName));
+        List<String> results = super.query(query, type);
+        type.setName(origProductTypeName);
+        return results;
+    }
+
+    protected String getProductTypeTableName(String origName) {
+        if (typeMap != null && typeMap.containsKey(origName)) {
+            return typeMap.getProperty(origName);
+        } else
+            return origName;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/MappedDataSourceCatalogFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/MappedDataSourceCatalogFactory.java
new file mode 100644
index 0000000..48c9592
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/MappedDataSourceCatalogFactory.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+//JDK imports
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.catalog.Catalog;
+import org.apache.oodt.cas.filemgr.catalog.DataSourceCatalogFactory;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Factory for constructing a special {@link DataSourceCatalog} called
+ * {@link MappedDataSourceCatalog} which is able to override the default
+ * policy of {@link ProductType#getName()}_metadata and {@link ProductType#getName()}_reference
+ * as the underlying table names
+ * </p>.
+ */
+public class MappedDataSourceCatalogFactory extends DataSourceCatalogFactory {
+
+    protected Properties typeMap;
+
+    private static final String TYPE_MAP_KEY = "org.apache.oodt.cas.filemgr."
+            + "catalog.mappeddatasource.mapFile";
+
+    public MappedDataSourceCatalogFactory() throws FileNotFoundException,
+            IOException {
+        super();
+        String mapFilePath = PathUtils.replaceEnvVariables(System
+                .getProperty(TYPE_MAP_KEY));
+        Properties props = new Properties();
+        props.load(new FileInputStream(mapFilePath));
+        this.typeMap = props;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.DataSourceCatalogFactory#createCatalog()
+     */
+    @Override
+    public Catalog createCatalog() {
+        return new MappedDataSourceCatalog(dataSource, validationLayer,
+                fieldIdStr, pageSize, cacheUpdateMinutes, typeMap);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/ScienceDataCatalog.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/ScienceDataCatalog.java
new file mode 100644
index 0000000..0074bb7
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/ScienceDataCatalog.java
@@ -0,0 +1,1233 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog;
+
+//JDK imports
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import javax.sql.DataSource;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.catalog.Catalog;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.util.DbStructFactory;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.commons.date.DateUtils;
+import org.apache.oodt.commons.pagination.PaginationUtils;
+
+/**
+ * 
+ * Provides a Catalog implementation that facilitate large-scale ingest of
+ * observational data into a relational schema.
+ * 
+ * @author ahart
+ * @author cgoodale
+ * @author mattmann
+ * 
+ */
+public class ScienceDataCatalog implements Catalog {
+
+  // Our SQL data source
+  protected DataSource dataSource = null;
+
+  // Our WRM val layer
+  protected ValidationLayer validationLayer = null;
+
+  protected int pageSize = -1;
+
+  // Our log stream
+  private Logger LOG = Logger.getLogger(ScienceDataCatalog.class
+      .getName());
+
+  public ScienceDataCatalog(DataSource dataSource,
+      ValidationLayer validationLayer, int pageSize) {
+    this.dataSource = dataSource;
+    this.validationLayer = validationLayer;
+    this.pageSize = pageSize;
+  }
+
+  public void addMetadata(Metadata m, Product p) throws CatalogException {
+
+    try {
+      // First, understand which dataset this metadata belongs to
+      // by examining the dataset_id metadata field
+      int datasetId = Integer.parseInt(m.getMetadata("dataset_id"));
+
+      // Then, create a record for the granule in the database,
+      // and store its id.
+      int granuleId = this.createGranule(datasetId,
+          m.getMetadata("granule_filename"));
+
+      // Then, create a record for any parameters detected in file
+      // that do not already exist in the database
+      Metadata paramMetadata = getMetadataSubset(m, Pattern.compile("param_*"));
+
+      for (Enumeration keys = paramMetadata.getHashtable().keys(); keys
+          .hasMoreElements();) {
+
+        String key = (String) keys.nextElement();
+        String keyName = key.substring(6); // trim "param_"
+
+        int paramId = this.createParameter(datasetId, keyName);
+        LOG.log(Level.INFO, "Currently extracting data for variable '"
+            + keyName + "' ");
+
+        // Create a record for each dataPoint for each parameter
+        // detected in the file
+
+        List<String> dataPoints = m.getAllMetadata("data_" + keyName);
+
+        LOG.log(Level.INFO, "Will now extract " + dataPoints.size()
+            + " data points for variable '" + keyName + "'... ");
+
+        StringBuffer queryBuffer = new StringBuffer(
+            "INSERT INTO `dataPoint` (`granule_id`,`dataset_id`,`parameter_id`,"
+                + "`latitude`,`longitude`,`vertical`,`time`,`value`) VALUES ");
+        // grab a count of items in the dataPoints list
+
+        LOG.log(Level.INFO, "there are " + dataPoints.size()
+            + " data points in the List");
+
+        // CGOODALE int to count how many times this thing loops
+        int iterCount = 0;
+        // String loopCounterString = "";
+
+        for (String dataPoint : dataPoints) {
+
+          // Decompose each dataPoint into its component parts:
+          // lat,lon,vertical,time,value
+          String[] components = dataPoint.split(",");
+
+          // Append the dataPoint to the StringBuffer
+          queryBuffer.append(" ( ");
+          queryBuffer.append(granuleId); // granuleId
+          queryBuffer.append(" , ");
+          queryBuffer.append(datasetId); // datasetId
+          queryBuffer.append(" , ");
+          queryBuffer.append(paramId); // parameterId
+          queryBuffer.append(" , ");
+          queryBuffer.append(components[0]); // Lat
+          queryBuffer.append(" , ");
+          queryBuffer.append(components[1]); // Lon
+          queryBuffer.append(" , ");
+          queryBuffer.append(components[2]); // vertical
+          queryBuffer.append(" , ");
+          queryBuffer.append('"'); // Conversion from ISO to MySQL Compliant
+          // DateTime Format
+          queryBuffer.append(components[3].substring(0, 4)); // YYYY
+          queryBuffer.append("-");
+          queryBuffer.append(components[3].substring(4, 6)); // MM
+          queryBuffer.append("-");
+          queryBuffer.append(components[3].substring(6, 8)); // DD
+          queryBuffer.append(" ");
+          queryBuffer.append(components[3].substring(9, 11)); // HH
+          queryBuffer.append(":");
+          queryBuffer.append(components[3].substring(11, 13)); // mm
+          // no datasets contain seconds at this time
+          // including this code would cause some datasets to
+          // parse Z, into seconds
+          // queryBuffer.append(":");
+          // queryBuffer.append(components[3].substring(13, 15)); //ss
+          queryBuffer.append('"'); // End time
+          queryBuffer.append(" , ");
+          queryBuffer.append(components[4]); // Value
+          queryBuffer.append(" ) ");
+
+          queryBuffer.append(',');// Statement seperator
+
+          // Periodically commit the query
+          if (iterCount > 100) {
+
+            queryBuffer.deleteCharAt(queryBuffer.length() - 1);
+            queryBuffer.append(";");
+
+            // Commit the query;
+            this.commitQuery(queryBuffer, null);
+
+            // RESET query
+            queryBuffer = new StringBuffer(
+                "INSERT INTO `dataPoint` (`granule_id`,`dataset_id`,`parameter_id`,`latitude`,"
+                    + "`longitude`,`vertical`,`time`,`value`) VALUES ");
+
+            // RESET iterCount
+            iterCount = 0;
+          } else {
+            // Increment the counter
+            iterCount++;
+          }
+        }
+
+        // Commit any remaining data points
+        queryBuffer.deleteCharAt(queryBuffer.length() - 1);
+        queryBuffer.append(";");
+        this.commitQuery(queryBuffer, null);
+
+        LOG.log(Level.INFO, "Extracted " + dataPoints.size()
+            + " data points for variable '" + keyName + "' ");
+      }
+
+    } catch (Exception e) {
+      LOG.log(Level.WARNING,
+          "Exception adding product metadata. Message: " + e.getMessage());
+      e.printStackTrace();
+      throw new CatalogException(e.getMessage());
+    }
+  }
+
+  public int createGranule(int datasetId, String filename)
+      throws CatalogException, SQLException {
+    // Detect duplicate granule
+    Connection conn = null;
+    Statement statement = null;
+    boolean alreadyExists = false;
+    int granuleId = 0;
+    String queryExists = "SELECT granule_id FROM `granule` WHERE `filename`='"
+        + filename + "' AND `dataset_id`='" + datasetId + "'; ";
+    try {
+      conn = this.dataSource.getConnection();
+      conn.setAutoCommit(true);
+      int count = 0;
+      statement = conn.createStatement();
+      ResultSet rs = statement.executeQuery(queryExists.toString());
+      while (rs.next()) {
+        granuleId = rs.getInt("granule_id");
+      }
+      alreadyExists = (granuleId > 0);
+    } catch (SQLException e) {
+      LOG.log(Level.WARNING,
+          "SQL Exception querying for granule existence. Last query was: "
+              + queryExists + " , Message: " + e.getMessage());
+      throw new SQLException(e.getMessage());
+    } finally {
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    if (!alreadyExists) {
+      String query = "INSERT INTO `granule` (`dataset_id`,`filename`) VALUES ('"
+          + datasetId + "','" + filename + "');";
+      try {
+        String maxQuery = "SELECT MAX(granule_id) AS max_id FROM granule";
+        granuleId = this.commitQuery(new StringBuffer(query), maxQuery);
+      } catch (Exception e) {
+        throw new CatalogException(e.getMessage());
+      }
+    }
+
+    // Return the granule id
+    return granuleId;
+  }
+
+  public int createParameter(int datasetId, String longName)
+      throws CatalogException, SQLException {
+    // Detect duplicate parameter
+    Connection conn = null;
+    Statement statement = null;
+    boolean alreadyExists = false;
+    int parameterId = 0;
+    String queryExists = "SELECT parameter_id FROM `parameter` WHERE `longName`='"
+        + longName + "' AND `dataset_id`='" + datasetId + "'; ";
+    try {
+      conn = this.dataSource.getConnection();
+      conn.setAutoCommit(true);
+      int count = 0;
+      statement = conn.createStatement();
+      ResultSet rs = statement.executeQuery(queryExists.toString());
+      while (rs.next()) {
+        parameterId = rs.getInt("parameter_id");
+      }
+      alreadyExists = (parameterId > 0);
+    } catch (SQLException e) {
+      LOG.log(Level.WARNING,
+          "SQL Exception querying for parameter existence. Last query was: "
+              + queryExists + " , Message: " + e.getMessage());
+      throw new SQLException(e.getMessage());
+    } finally {
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    if (!alreadyExists) {
+      // Insert the parameter into the database
+      String query = "INSERT INTO `parameter` (`longName`,`dataset_id`,`description`) VALUES ('"
+          + longName + "','" + datasetId + "','') ";
+
+      try {
+        String maxQuery = "SELECT MAX(parameter_id) AS max_id FROM parameter";
+        parameterId = this.commitQuery(new StringBuffer(query), maxQuery);
+      } catch (Exception e) {
+        throw new CatalogException(e.getMessage());
+      }
+    }
+
+    // Return the id of the parameter
+    return parameterId;
+  }
+
+  public int commitQuery(StringBuffer query, String maxQuery)
+      throws SQLException {
+    Connection conn = null;
+    Statement statement = null;
+    int returnId = 0;
+
+    // Try to commit the query
+    try {
+      // LOG.log(Level.INFO,"Query: " + query);
+      conn = this.dataSource.getConnection();
+      conn.setAutoCommit(false);
+      statement = conn.createStatement();
+      statement.execute(query.toString());
+
+      if (maxQuery != null) {
+        ResultSet rs = statement.executeQuery(maxQuery);
+        while (rs.next()) {
+          returnId = rs.getInt("max_id");
+        }
+      }
+      conn.commit();
+      return returnId;
+
+    } catch (SQLException e) {
+      // TODO Auto-generated catch block
+      LOG.log(Level.WARNING,
+          "SQL Exception adding product metadata. Last query was: " + query
+              + " , Message: " + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(
+            Level.SEVERE,
+            "Unable to rollback addMetadata transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new SQLException(e.getMessage());
+    } finally {
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+  }
+
+  public void addProduct(Product product) throws CatalogException {
+    // TODO Auto-generated method stub
+
+  }
+
+  public void addProductReferences(Product product) throws CatalogException {
+    // TODO Auto-generated method stub
+
+  }
+
+  public Metadata getMetadata(Product product) throws CatalogException {
+    Metadata met = new Metadata();
+    // met.addMetadata("StartDateTime", this.getStartDateTime(product));
+    // met.addMetadata("EndDateTime", this.getEndDateTime(product));
+    met.addMetadata("Filename", product.getProductName());
+    met.addMetadata("ProductType", product.getProductType().getName());
+    met.addMetadata("FileLocation", "Unknown");
+    met.addMetadata("CAS.ProductReceivedTime",
+        DateUtils.toString(Calendar.getInstance()));
+    return met;
+  }
+
+  public int getNumProducts(ProductType productType) throws CatalogException {
+    String sql = "SELECT COUNT(granule_id) as num_products FROM granule "
+        + "          WHERE dataset_id IN (SELECT dataset_id FROM dataset "
+        + "                               WHERE shortName = '"
+        + productType.getName() + "'" + "                           )";
+
+    ResultSet rs = null;
+    Statement statement = null;
+    Connection conn = null;
+    int numProducts = 0;
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        numProducts = rs.getInt("num_products");
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+    }
+
+    return numProducts;
+  }
+
+  public Product getProductById(String productId) throws CatalogException {
+    String sql = "SELECT granule_id, dataset_id, filename FROM granule WHERE granule_id = "
+        + productId;
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    Product product = null;
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        product = DbStructFactory.toScienceDataProduct(rs);
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+    return product;
+  }
+
+  public Product getProductByName(String productName) throws CatalogException {
+    String sql = "SELECT granule_id, dataset_id, filename FROM granule WHERE fileName = '"
+        + productName + "'";
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    Product product = null;
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        product = DbStructFactory.toScienceDataProduct(rs);
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+    return product;
+  }
+
+  public List<Reference> getProductReferences(Product product)
+      throws CatalogException {
+    return Collections.EMPTY_LIST;
+  }
+
+  public List<Product> getProducts() throws CatalogException {
+    String sql = "SELECT granule_id, dataset_id, filename FROM granule ORDER BY granule_id DESC";
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    List<Product> products = new Vector<Product>();
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        products.add(DbStructFactory.toScienceDataProduct(rs));
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+    return products;
+  }
+
+  public List<Product> getProductsByProductType(ProductType productType)
+      throws CatalogException {
+    String sql = "SELECT granule_id, dataset_id, filename FROM granule WHERE dataset_id = "
+        + productType.getProductTypeId() + " ORDER BY granule_id DESC";
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    List<Product> products = new Vector<Product>();
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        products.add(DbStructFactory.toScienceDataProduct(rs));
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+    return products;
+  }
+
+  public Metadata getReducedMetadata(Product product, List<String> metList)
+      throws CatalogException {
+
+    Metadata met = this.getMetadata(product);
+    Metadata finalMet = new Metadata();
+    for (String metKey : metList) {
+      finalMet.addMetadata(metKey, met.getAllMetadata(metKey));
+    }
+
+    return finalMet;
+
+  }
+
+  public List<Product> getTopNProducts(int num) throws CatalogException {
+    String sql = "SELECT granule_id, dataset_id, filename FROM granule ORDER BY granule_id DESC LIMIT "
+        + num;
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    List<Product> products = new Vector<Product>();
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      LOG.log(Level.INFO, "Executing: [" + sql + "]");
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        products.add(DbStructFactory.toScienceDataProduct(rs));
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+    return products;
+  }
+
+  public List<Product> getTopNProducts(int num, ProductType productType)
+      throws CatalogException {
+    String sql = "SELECT granule_id, dataset_id, filename FROM granule WHERE dataset_id = "
+        + productType.getProductTypeId()
+        + " ORDER BY granule_id DESC LIMIT "
+        + num;
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    List<Product> products = new Vector<Product>();
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      LOG.log(Level.INFO, "Executing: [" + sql + "]");
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        products.add(DbStructFactory.toScienceDataProduct(rs));
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+    return products;
+  }
+
+  public ValidationLayer getValidationLayer() throws CatalogException {
+    return this.validationLayer;
+  }
+
+  public void modifyProduct(Product arg0) throws CatalogException {
+    // TODO Auto-generated method stub
+
+  }
+
+  public List<String> query(Query arg0, ProductType arg1)
+      throws CatalogException {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  public void removeMetadata(Metadata arg0, Product arg1)
+      throws CatalogException {
+    // TODO Auto-generated method stub
+
+  }
+
+  public void removeProduct(Product arg0) throws CatalogException {
+    // TODO Auto-generated method stub
+
+  }
+
+  public void setProductTransferStatus(Product arg0) throws CatalogException {
+    // TODO Auto-generated method stub
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.util.Pagination#getFirstPage(org.apache.oodt
+   * .cas.filemgr.structs.ProductType)
+   */
+  public ProductPage getFirstPage(ProductType type) {
+    Query query = new Query();
+    ProductPage firstPage = null;
+
+    try {
+      firstPage = pagedQuery(query, type, 1);
+    } catch (CatalogException e) {
+      LOG.log(Level.WARNING,
+          "Exception getting first page: Message: " + e.getMessage());
+    }
+    return firstPage;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.util.Pagination#getLastProductPage(org.apache
+   * .oodt.cas.filemgr.structs.ProductType)
+   */
+  public ProductPage getLastProductPage(ProductType type) {
+    ProductPage lastPage = null;
+    ProductPage firstPage = getFirstPage(type);
+    Query query = new Query();
+    try {
+      lastPage = pagedQuery(query, type, firstPage.getTotalPages());
+    } catch (CatalogException e) {
+      LOG.log(Level.WARNING,
+          "Exception getting last page: Message: " + e.getMessage());
+    }
+
+    return lastPage;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.util.Pagination#getNextPage(org.apache.oodt
+   * .cas.filemgr.structs.ProductType,
+   * org.apache.oodt.cas.filemgr.structs.ProductPage)
+   */
+  public ProductPage getNextPage(ProductType type, ProductPage currentPage) {
+    if (currentPage == null) {
+      return getFirstPage(type);
+    }
+
+    if (currentPage.isLastPage()) {
+      return currentPage;
+    }
+
+    ProductPage nextPage = null;
+    Query query = new Query();
+
+    try {
+      nextPage = pagedQuery(query, type, currentPage.getPageNum() + 1);
+    } catch (CatalogException e) {
+      LOG.log(Level.WARNING,
+          "Exception getting next page: Message: " + e.getMessage());
+    }
+
+    return nextPage;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.util.Pagination#getPrevPage(org.apache.oodt
+   * .cas.filemgr.structs.ProductType,
+   * org.apache.oodt.cas.filemgr.structs.ProductPage)
+   */
+  public ProductPage getPrevPage(ProductType type, ProductPage currentPage) {
+    if (currentPage == null) {
+      return getFirstPage(type);
+    }
+
+    if (currentPage.isFirstPage()) {
+      return currentPage;
+    }
+    ProductPage prevPage = null;
+    Query query = new Query();
+
+    try {
+      prevPage = pagedQuery(query, type, currentPage.getPageNum() - 1);
+    } catch (CatalogException e) {
+      LOG.log(Level.WARNING,
+          "Exception getting prev page: Message: " + e.getMessage());
+    }
+
+    return prevPage;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.catalog.Catalog#pagedQuery(org.apache.oodt.
+   * cas.filemgr.structs.Query, org.apache.oodt.cas.filemgr.structs.ProductType,
+   * int)
+   */
+  public ProductPage pagedQuery(Query query, ProductType type, int pageNum)
+      throws CatalogException {
+    int totalPages = PaginationUtils.getTotalPage(
+        getResultListSize(query, type), this.pageSize);
+
+    /*
+     * if there are 0 total pages in the result list size then don't bother
+     * returning a valid product page instead, return blank ProductPage
+     */
+    if (totalPages == 0) {
+      return ProductPage.blankPage();
+    }
+
+    ProductPage retPage = new ProductPage();
+    retPage.setPageNum(pageNum);
+    retPage.setPageSize(this.pageSize);
+    retPage.setTotalPages(totalPages);
+
+    List<String> productIds = paginateQuery(query, type, pageNum);
+
+    if (productIds != null && productIds.size() > 0) {
+      List<Product> products = new Vector<Product>(productIds.size());
+
+      for (Iterator<String> i = productIds.iterator(); i.hasNext();) {
+        String productId = i.next();
+        Product p = getProductById(productId);
+        products.add(p);
+      }
+
+      retPage.setPageProducts(products);
+    }
+
+    return retPage;
+  }
+
+  private List<String> paginateQuery(Query query, ProductType type, int pageNum)
+      throws CatalogException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    List<String> productIds = new Vector<String>();
+
+    boolean doSkip = true;
+    int numResults = -1;
+
+    if (pageNum == -1) {
+      doSkip = false;
+    } else {
+      numResults = getResultListSize(query, type);
+    }
+
+    try {
+
+      conn = dataSource.getConnection();
+      statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
+          ResultSet.CONCUR_READ_ONLY);
+
+      String getProductSql = "SELECT DISTINCT granule_id FROM granule WHERE "
+          + "dataset_id = " + type.getProductTypeId()
+          + " ORDER BY granule_id DESC ";
+      LOG.log(Level.FINE, "Executing: [" + getProductSql + "]");
+      rs = statement.executeQuery(getProductSql);
+
+      if (doSkip) {
+        int startNum = (pageNum - 1) * pageSize;
+        if (startNum > numResults) {
+          startNum = 0;
+        }
+
+        // must call next first, or else no relative cursor
+        if (rs.next()) {
+          // grab the first one
+          int numGrabbed = -1;
+
+          if (pageNum == 1) {
+            numGrabbed = 1;
+            productIds.add(rs.getString("granule_id"));
+          } else {
+            numGrabbed = 0;
+          }
+
+          // now move the cursor to the correct position
+          if (pageNum != 1) {
+            rs.relative(startNum - 1);
+          }
+
+          // grab the rest
+          while (rs.next() && numGrabbed < pageSize) {
+            String productId = rs.getString("granule_id");
+            productIds.add(productId);
+            numGrabbed++;
+          }
+        }
+
+      } else {
+        while (rs.next()) {
+          String productId = rs.getString("granule_id");
+          productIds.add(productId);
+        }
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Exception performing query. Message: " + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE, "Unable to rollback query transaction. Message: "
+            + e2.getMessage());
+      }
+      throw new CatalogException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return productIds;
+
+  }
+
+  private int getResultListSize(Query query, ProductType productType) {
+    String sql = "SELECT COUNT(granule_id) as result_size FROM granule where dataset_id = "
+        + productType.getProductTypeId();
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    int size = -1;
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      LOG.log(Level.INFO, "Executing: [" + sql + "]");
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        size = rs.getInt("result_size");
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+    return size;
+  }
+
+  private String getStartDateTime(Product product) {
+    String sql = "SELECT MIN(time) as start_date_time FROM dataPoint "
+        + "          WHERE granule_id IN (SELECT granule_id FROM granule "
+        + "                               WHERE filename = '"
+        + product.getProductName() + "'" + "                           )";
+
+    ResultSet rs = null;
+    Statement statement = null;
+    Connection conn = null;
+    String startDateTime = null;
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(rs.getDate("start_date_time"));
+        startDateTime = DateUtils.toString(cal);
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+    }
+
+    return startDateTime;
+
+  }
+
+  private String getEndDateTime(Product product) {
+    String sql = "SELECT MAX(time) as end_date_time FROM dataPoint "
+        + "          WHERE granule_id IN (SELECT granule_id FROM granule "
+        + "                               WHERE filename = '"
+        + product.getProductName() + "'" + "                           )";
+
+    ResultSet rs = null;
+    Statement statement = null;
+    Connection conn = null;
+    String endDateTime = null;
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(rs.getDate("end_date_time"));
+        endDateTime = DateUtils.toString(cal);
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+    }
+
+    return endDateTime;
+
+  }
+
+  /**
+   * getMetadataSubset
+   * 
+   * Returns the subset of metadata keys in the provided Metadata object that
+   * match against the regular expression specified in pattern. Note that
+   * complete match is not required for success. This function utilizes the
+   * 'lookingAt()' function of the java.util.regex.Matcher class to determine
+   * whether the candidate string contains the pattern as a substring when
+   * starting from the zeroth index (the beginning).
+   * 
+   * @param m
+   *          The Metadata object containing keys from which a subset will be
+   *          extracted
+   * @param pattern
+   *          The regular expression to use in determining matching keys
+   * @return A Metadata object containing only those keys which matched
+   *         'pattern'
+   */
+  private static Metadata getMetadataSubset(Metadata m, Pattern pattern) {
+
+    Metadata subset = new Metadata();
+
+    for (Object key : m.getHashtable().keySet()) {
+
+      Matcher matcher = pattern.matcher((String) key);
+      if (matcher.lookingAt()) {
+        subset.addMetadata((String) key, m.getMetadata((String) key));
+      }
+    }
+
+    return subset;
+  }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/ScienceDataCatalogFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/ScienceDataCatalogFactory.java
new file mode 100644
index 0000000..19910b7
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/ScienceDataCatalogFactory.java
@@ -0,0 +1,75 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+//JDK imports
+import javax.sql.DataSource;
+
+//OODT imports
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+import org.apache.oodt.cas.filemgr.catalog.Catalog;
+import org.apache.oodt.cas.filemgr.catalog.CatalogFactory;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.filemgr.validation.ScienceDataValidationLayerFactory;
+
+/**
+ * Implements the CatalogFactory interface to provide a factory for
+ * {@link ScienceDataCatalog}. The properties referenced in this class can be
+ * edited in the filemgr.properties file in
+ * [filemgr_home]/etc/filemgr.properties
+ * 
+ * @author ahart
+ * @author cgoodale
+ * @author mattmann
+ * 
+ */
+public class ScienceDataCatalogFactory implements CatalogFactory {
+
+  // The data source
+  protected DataSource dataSource = null;
+
+  // The page size
+  protected int pageSize;
+
+  public ScienceDataCatalogFactory() {
+
+    String jdbcUrl = null, user = null, pass = null, driver = null;
+
+    jdbcUrl = PathUtils.replaceEnvVariables(System
+        .getProperty("org.apache.cas.filemgr.catalog.science.jdbc.url"));
+    user = PathUtils.replaceEnvVariables(System
+        .getProperty("org.apache.cas.filemgr.catalog.science.jdbc.user"));
+    pass = PathUtils.replaceEnvVariables(System
+        .getProperty("org.apache.cas.filemgr.catalog.science.jdbc.pass"));
+    driver = PathUtils.replaceEnvVariables(System
+        .getProperty("org.apache.cas.filemgr.catalog.science.jdbc.driver"));
+
+    dataSource = DatabaseConnectionBuilder.buildDataSource(user, pass, driver,
+        jdbcUrl);
+    pageSize = Integer.valueOf(PathUtils.replaceEnvVariables(System
+        .getProperty("org.apache.cas.filemgr.catalog.science.pageSize")));
+
+  }
+
+  public Catalog createCatalog() {
+    return new ScienceDataCatalog(dataSource,
+        new ScienceDataValidationLayerFactory().createValidationLayer(),
+        pageSize);
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/CompleteProduct.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/CompleteProduct.java
new file mode 100644
index 0000000..e12707b
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/CompleteProduct.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog.solr;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * Class that combines a Product and its associated Metadata.
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public class CompleteProduct {
+	
+	private Product product;
+	
+	private Metadata metadata;
+	
+	public CompleteProduct() {
+		
+		product = new Product();
+		product.setProductType(new ProductType());
+		metadata = new Metadata();
+		
+	}
+
+	public Product getProduct() {
+		return product;
+	}
+
+	public void setProduct(Product product) {
+		this.product = product;
+	}
+
+	public Metadata getMetadata() {
+		return metadata;
+	}
+
+	public void setMetadata(Metadata metadata) {
+		this.metadata = metadata;
+	}
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/DefaultProductSerializer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/DefaultProductSerializer.java
new file mode 100644
index 0000000..de60a5f
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/DefaultProductSerializer.java
@@ -0,0 +1,514 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog.solr;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * Default implementation of {@link ProductSerializer} 
+ * that transforms a CAS product into a single Solr document based on the following rules: 
+ * o) the core product attributes are used to generate Solr fields starting with "CAS...."
+ * o) the product references are converted to Solr fields starting with "CAS.Reference..." or "CAS.RootReference..."
+ * o) all other metadata fields are converted into Solr fields with the same name and number of values. 
+ *    Note that the field multiplicity must be consistent with its definition in the Solr schema.xml.
+ *    
+ * This class generates all Solr documents in XML format.
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public class DefaultProductSerializer implements ProductSerializer {
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String getMimeType() {
+		return Parameters.MIME_TYPE_XML;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<String> serialize(Product product, boolean create) {
+		
+		Map<String, List<String>> fields = new HashMap<String, List<String>>();
+		List<String> docs = new ArrayList<String>();
+		
+		// add core product attributes to map
+		this.addKeyValueToMap(fields, Parameters.PRODUCT_ID, product.getProductId());
+		this.addKeyValueToMap(fields, Parameters.PRODUCT_NAME, product.getProductName());
+		this.addKeyValueToMap(fields, Parameters.PRODUCT_STRUCTURE, product.getProductStructure());
+		this.addKeyValueToMap(fields, Parameters.PRODUCT_TRANSFER_STATUS, product.getTransferStatus());
+		ProductType productType = product.getProductType();
+		if (productType!=null) {
+			this.addKeyValueToMap(fields, Parameters.PRODUCT_TYPE_NAME, productType.getName());
+			this.addKeyValueToMap(fields, Parameters.PRODUCT_TYPE_ID, productType.getProductTypeId());				
+		}
+		if (create) {
+			// only insert date/time when product is first created
+			Date productDateTime = new Date(); // current datetime
+			this.addKeyValueToMap(fields, Parameters.PRODUCT_RECEIVED_TIME, Parameters.SOLR_DATE_TIME_FORMATTER.format(productDateTime));
+		}
+		
+		// create new product: use Solr id == CAS id
+		if (create) {			
+			docs.add( this.generateInsertDocuments(product.getProductId(), fields) );
+			
+		// update existing product
+		} else {			
+			docs.addAll( this.generateUpdateDocuments(product.getProductId(), fields, true) ); // replace=true
+		
+		}
+		
+		return docs;
+		
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public List<String> serialize(String productId, Reference rootReference, List<Reference> references, boolean replace) {
+		
+		Map<String, List<String>> fields = new HashMap<String, List<String>>();
+		
+		// product root reference
+		if (rootReference!=null) {
+			
+			addKeyValueToMap(fields, Parameters.ROOT_REFERENCE_ORIGINAL, rootReference.getOrigReference());
+			addKeyValueToMap(fields, Parameters.ROOT_REFERENCE_DATASTORE, rootReference.getDataStoreReference());
+			addKeyValueToMap(fields, Parameters.ROOT_REFERENCE_FILESIZE, ""+rootReference.getFileSize());
+			addKeyValueToMap(fields, Parameters.ROOT_REFERENCE_MIMETYPE, rootReference.getMimeType().toString());
+			
+		}
+		
+		// all other product references
+	  // note that Solr will preserve the indexing order.
+		for (Reference reference : references) {
+			
+			addKeyValueToMap(fields, Parameters.REFERENCE_ORIGINAL, reference.getOrigReference());
+			addKeyValueToMap(fields, Parameters.REFERENCE_DATASTORE, reference.getDataStoreReference());
+			addKeyValueToMap(fields, Parameters.REFERENCE_FILESIZE, ""+reference.getFileSize());
+			addKeyValueToMap(fields, Parameters.REFERENCE_MIMETYPE, reference.getMimeType().toString());
+			
+		}
+		
+		return generateUpdateDocuments(productId, fields, replace);
+		
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public QueryResponse deserialize(String xml) throws CatalogException {
+		
+		try {
+			
+			QueryResponse queryResponse = new QueryResponse();
+			
+			// parse XML into DOM
+			Document document = parseXml(xml);
+			
+			// extract information from DOM to Product
+			Element response = document.getDocumentElement();
+			Node result = response.getElementsByTagName("result").item(0);
+			queryResponse.setNumFound( Integer.parseInt( ((Element)result).getAttribute("numFound") ) );
+			queryResponse.setStart( Integer.parseInt( ((Element)result).getAttribute("start") ) );			
+			NodeList docs = result.getChildNodes();
+			for (int i=0; i< docs.getLength(); i++) {
+				Node node = docs.item(i);
+				if (node.getNodeName().equals("doc")) {
+					Element doc = (Element)node;					
+					CompleteProduct cp = this.deserialize(doc);
+					queryResponse.getCompleteProducts().add(cp);
+				}
+			}		
+			return queryResponse;
+		
+		} catch(Exception e) {
+			e.printStackTrace();
+			throw new CatalogException(e.getMessage());
+		}
+		
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public List<String> serialize(String productId, Metadata metadata, boolean replace) {
+		
+		Map<String, List<String>> fields = new HashMap<String, List<String>>();
+		
+		for (String key : metadata.getKeys()) {
+			if (! (key.startsWith(Parameters.NS)              // skip metadata keys starting with reserved namespace
+				     || Parameters.PRODUCT_TYPE_NAME.indexOf(key)>=0 // skip 'ProductType' as already stored as 'CAS.ProductTypeName'
+				     || Parameters.PRODUCT_STRUCTURE.indexOf(key)>=0)) { // skip 'ProductType' as already stored as 'CAS.ProductStructure'
+				for (String value : metadata.getAllMetadata(key)) {
+					this.addKeyValueToMap(fields, key, value);
+				}
+			}
+		}
+		
+		return this.generateUpdateDocuments(productId, fields, replace);
+		
+	}
+	
+	/**
+	 * Method to add a (key, value) to a multi-valued map with appropriate checks.
+	 * @param map
+	 * @param key
+	 * @param value
+	 */
+	protected void addKeyValueToMap(Map<String, List<String>> map, String key, String value) {
+		
+		if (!map.containsKey(key)) {
+			map.put(key, new ArrayList<String>());
+		}
+		if (value!=null) {
+			map.get(key).add(value);
+		} else {
+			// use special value to trigger key removal
+			map.get(key).add(Parameters.NULL);
+		}
+	}
+	
+	/**
+	 * Utility method to generate a Solr insert document.
+	 * 
+	 * @param productId
+	 * @param fields
+	 * @return
+	 */
+	protected String generateInsertDocuments(String productId, Map<String,List<String>> fields) {
+		
+		StringBuilder doc = new StringBuilder();
+		doc.append("<doc>");
+		
+		// product Solr id field
+		doc.append( encodeIndexField(Parameters.ID, productId) );
+		
+		// all other fields
+		for (String key : fields.keySet()) {
+			for (String value : fields.get(key)) {
+				doc.append( encodeIndexField(key, value) );
+			}
+		}
+
+		doc.append("</doc>");
+		return doc.toString();
+	}
+	
+	/**
+	 * Utility method to generate Solr update documents.
+	 * Note that the requests for setting/adding/deleting fields must be sent as separate documents to Solr
+	 * @param productId
+	 * @param fields
+	 * @param replace
+	 * @return
+	 */
+	protected List<String> generateUpdateDocuments(String productId, Map<String,List<String>> fields, boolean replace) {
+		
+		// list for different instruction types
+		List<String> setFields = new ArrayList<String>();
+		List<String> addFields = new ArrayList<String>();
+		List<String> delFields = new ArrayList<String>();
+		
+		// encode update instructions
+		for (String key : fields.keySet()) {
+			
+			List<String> values = fields.get(key);
+			
+			if (replace) {
+				
+				if (values.isEmpty()) {
+					// use special value to flag removal
+					delFields.add( this.encodeUpdateField(key, Parameters.NULL, replace) );
+					
+				} else {
+					for (String value : values) {
+						setFields.add( this.encodeUpdateField(key, value, replace) );
+					}
+				}
+				
+			} else {
+				for (String value : values) {
+					addFields.add( this.encodeUpdateField(key, value, replace) );
+				}
+			}
+			
+		}
+		
+		List<String> docs = new ArrayList<String>();
+		if (!delFields.isEmpty()) docs.add( toDoc(productId, delFields) );
+		if (!setFields.isEmpty()) docs.add( toDoc(productId, setFields) );
+		if (!addFields.isEmpty()) docs.add( toDoc(productId, addFields) );
+		return docs;
+		
+	}
+	
+	/**
+	 * Utility method to merge field update instructions into a single document.
+	 * @param productId
+	 * @param updates
+	 * @return
+	 */
+	private String toDoc(String productId, List<String> updates) {
+		
+		StringBuilder doc = new StringBuilder();
+		doc.append("<doc>");
+		
+		// reference product record id
+		doc.append( encodeIndexField(Parameters.ID, productId) );
+		
+		// loop over field update instructions
+		for (String update : updates) {
+			doc.append(update);
+		}
+		
+		doc.append("</doc>");
+		
+		return doc.toString();
+		
+	}
+	
+	/**
+	 * Method to encode a Solr field indexing instruction.
+	 * If the value is null, the empty string is returned.
+	 * @param key
+	 * @param value
+	 * @return
+	 */
+	protected String encodeIndexField(String key, String value) {
+		if (value==null || value.equals(Parameters.NULL)) {
+			return "";
+		} else {
+			return "<field name=\""+key+"\">" + value + "</field>";
+		}
+	}
+	
+	/**
+	 * Method to encode a field update instruction for the three possible cases:
+	 * add new values to a key (1), replace current values for a key (2), remove all values for a key (3).
+	 * 
+	 * @param key
+	 * @param value
+	 * @param replace
+	 * @return
+	 */
+	protected String encodeUpdateField(String key, String value, boolean replace) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("<field name=\""+key+"\"");
+		
+		if (replace) {
+			
+			if (value==null || value.equals(Parameters.NULL)) {
+				
+				// (3) remove all values for given key
+				sb.append(" update=\"set\" null=\"true\" />");
+				
+			} else {
+				
+				// (2) replace existing values with new values
+				sb.append(" update=\"set\">" + value + "</field>");
+			}
+			
+		} else {
+			
+			// (1) add new values to existing values
+			sb.append(" update=\"add\">"+value+"</field>");
+			
+		}
+
+		return sb.toString();
+	}
+	
+
+	
+	/**
+	 * Method that parses a single Solr document snippet
+	 * to extract Product and Metadata attributes.
+	 * 
+	 * @param doc
+	 * @return
+	 */
+	private CompleteProduct deserialize(Element doc) {
+		
+		CompleteProduct cp = new CompleteProduct();
+		Product product = cp.getProduct();
+		ProductType productType = product.getProductType();
+		Metadata metadata = cp.getMetadata();
+		List<Reference> references = product.getProductReferences();
+		Reference rootReference = product.getRootRef();
+		
+		NodeList children = doc.getChildNodes();
+		for (int j=0; j<children.getLength(); j++) {
+			
+			Node child = children.item(j);
+			Element element = (Element)child;
+			String name = element.getAttribute("name");
+			
+			/**
+			 *<arr name="ScanPointingSource">
+			 *	<str>G073.65+0.19</str>
+			 *	<str>J2015+3410</str>
+	     *  ..........
+			 */
+			if (child.getNodeName().equals("arr")) {
+				
+				NodeList values = element.getChildNodes();
+				List<String> vals = new ArrayList<String>();
+				for (int k=0; k<values.getLength(); k++) {
+					String value = ((Element)values.item(k)).getTextContent();
+					vals.add(value);
+				}
+				// CAS.reference.... fields
+				if (name.startsWith(Parameters.NS)) {					
+						for (int k=0; k<values.getLength(); k++) {
+							// create this reference
+							if (references.size()<=k) references.add(new Reference());
+							if (name.equals(Parameters.REFERENCE_ORIGINAL)) {
+								references.get(k).setOrigReference(vals.get(k));
+							} else if (name.equals(Parameters.REFERENCE_DATASTORE)) {
+								references.get(k).setDataStoreReference(vals.get(k));
+							} else if (name.equals(Parameters.REFERENCE_FILESIZE)) {
+								references.get(k).setFileSize(Long.parseLong(vals.get(k)));
+							} else if (name.equals(Parameters.REFERENCE_MIMETYPE)) {
+								references.get(k).setMimeType(vals.get(k));
+							}
+						}
+				// all other multi-valued fields
+				} else {
+					this.deserializeMultiValueField(name, vals, metadata);
+				}
+				
+			/**
+			 * 	<str name="id">6684d79d-a011-4bc0-b3b3-4f11817091c8</str>
+			 *  <str name="CAS.ProductId">6684d79d-a011-4bc0-b3b3-4f11817091c8</str>
+			 *  <str name="CAS.ProductName">tns_br145x4_20</str>
+			 *  <str name="FileLocation">/usr/local/ska-dc/data/archive</str>
+       *  ...........
+			 */
+			} else {
+				
+				String value = element.getTextContent();
+				
+				// core CAS fields
+				if (name.startsWith(Parameters.NS)) {
+					if (name.equals(Parameters.PRODUCT_ID)) {
+						product.setProductId(value);
+					} else if (name.equals(Parameters.PRODUCT_NAME)) {
+						product.setProductName(value);
+					} else if (name.equals(Parameters.PRODUCT_STRUCTURE)) {
+						product.setProductStructure(value);
+					} else if (name.equals(Parameters.PRODUCT_TRANSFER_STATUS)) {
+						product.setTransferStatus(value);
+					} else if (name.equals(Parameters.PRODUCT_TYPE_NAME)) {
+						productType.setName(value);
+					} else if (name.equals(Parameters.PRODUCT_TYPE_ID)) {
+						productType.setProductTypeId(value);
+					} else if (name.equals(Parameters.PRODUCT_RECEIVED_TIME)) {
+						// ignore ?
+						
+					// CAS root reference
+					} else if (name.startsWith(Parameters.NS+Parameters.ROOT)) {
+						if (rootReference==null) rootReference = new Reference();
+						if (name.equals(Parameters.ROOT_REFERENCE_ORIGINAL)) {
+							rootReference.setOrigReference(value);
+						} else if (name.equals(Parameters.ROOT_REFERENCE_DATASTORE)) {
+							rootReference.setDataStoreReference(value);
+						} else if (name.equals(Parameters.ROOT_REFERENCE_FILESIZE)) {
+							rootReference.setFileSize(Long.parseLong(value));
+						} else if (name.equals(Parameters.ROOT_REFERENCE_MIMETYPE)) {
+							rootReference.setMimeType(value);
+						}
+
+					}
+					
+				// non core single-valued fields
+				} else {
+					this.deserializeSingleValueField(name, value, metadata);
+				} // "CAS".... or not
+				
+			} // "arr" or anything else
+			
+		} // loop over <doc> children
+		
+		return cp;
+		
+	}
+	
+	private Document parseXml(String xml) throws Exception {
+		
+		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+		DocumentBuilder parser = factory.newDocumentBuilder();
+    Document document = parser.parse( new InputSource(new StringReader(xml)) );
+    return document;
+    
+	}
+	
+	/**
+	 * Method that deserializes a single-valued Solr field into a Metadata element.
+	 * This method can be overridden by sub-classes to provide custom behavior.
+	 * 
+	 * @param name : the Solr field name
+	 * @param value : the Solr field single value
+	 * @param metadata : the metadata container
+	 */
+	protected void deserializeSingleValueField(String name, String value, Metadata metadata) {
+		
+		if (name.equals(Parameters.ID)) {
+			// ignore Solr internal identifier (as it is duplicate information of CAS.ProductId)
+		} else {
+			metadata.addMetadata(name, value);
+		}
+
+	}
+	
+	/**
+	 * Method that deserializes a multi-valued Solr field into a Metadata element.
+	 * This method can be overridden by sub-classes to provide custom behavior.
+	 * 
+	 * @param name : the Solr field name
+	 * @param values : the Solr field multiple values
+	 * @param metadata : the metadata container
+	 */
+	protected void deserializeMultiValueField(String name, List<String> values, Metadata metadata) {
+		metadata.addMetadata(name, values);
+	}
+
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/NameProductIdGenerator.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/NameProductIdGenerator.java
new file mode 100644
index 0000000..ed08f91
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/NameProductIdGenerator.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog.solr;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+
+/**
+ * Implementation of {@link ProductIdGenerator} 
+ * that sets the Product identifier equal to the product name.
+ * This generator will cause a second submission of the same named Product
+ * to override the previous record inside the Solr index.
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public class NameProductIdGenerator implements ProductIdGenerator {
+
+	@Override
+	public String generateId(Product product) {
+		return product.getProductName();
+	}
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/Parameters.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/Parameters.java
new file mode 100644
index 0000000..fc62fa7
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/Parameters.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog.solr;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+
+/**
+ * Class holding parameters for Solr implementation of CAS File Manager.
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public class Parameters {
+	
+	// the Solr unique identifier field
+	public final static String ID = "id";
+	
+	public final static String NS = "CAS.";
+		
+	public final static String PRODUCT_ID = NS+"ProductId";
+	public final static String PRODUCT_NAME = NS+"ProductName";
+	public final static String PRODUCT_STRUCTURE = NS+"ProductStructure";
+	public final static String PRODUCT_TRANSFER_STATUS = NS+"ProductTransferStatus";
+	public final static String PRODUCT_RECEIVED_TIME = NS+"ProductReceivedTime";	
+	public final static String PRODUCT_TYPE_NAME = NS+"ProductTypeName";
+	public final static String PRODUCT_TYPE_ID = NS+"ProductTypeId";
+		
+	public final static String REFERENCE_ORIGINAL = NS+"ReferenceOriginal";
+	public final static String REFERENCE_DATASTORE = NS+"ReferenceDatastore";
+	public final static String REFERENCE_FILESIZE = NS+"ReferenceFileSize";
+	public final static String REFERENCE_MIMETYPE = NS+"ReferenceMimeType";
+	
+	public final static String ROOT = "Root";
+	public final static String ROOT_REFERENCE_ORIGINAL = NS+ROOT+REFERENCE_ORIGINAL;
+	public final static String ROOT_REFERENCE_DATASTORE = NS+ROOT+REFERENCE_DATASTORE;
+	public final static String ROOT_REFERENCE_FILESIZE = NS+ROOT+REFERENCE_FILESIZE;
+	public final static String ROOT_REFERENCE_MIMETYPE = NS+ROOT+REFERENCE_MIMETYPE;
+
+  // required date/time format for Solr documents
+  public static final String SOLR_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+  public static final DateFormat SOLR_DATE_TIME_FORMATTER = new SimpleDateFormat(SOLR_DATE_FORMAT);
+
+  // possible mime types for communication with Solr
+  public static final String MIME_TYPE_XML = "application/xml";
+  public static final String MIME_TYPE_JSON = "application/json";
+  
+  // page size for pagination
+  public static final int PAGE_SIZE = 20;
+	
+	// special value that indicates that the metadata field must be deleted
+	public final static String NULL = "__NULL__";
+	
+	private Parameters() {}
+	
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/ProductIdGenerator.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/ProductIdGenerator.java
new file mode 100644
index 0000000..c1577f4
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/ProductIdGenerator.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog.solr;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+
+/**
+ * API for generating a unique identifier for a CAS Product.
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public interface ProductIdGenerator {
+	
+	public String generateId(Product product);
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/ProductSerializer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/ProductSerializer.java
new file mode 100644
index 0000000..7fbe487
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/ProductSerializer.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog.solr;
+
+import java.util.List;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * API for serializing CAS objects (Products, Metadata and References) into documents to be indexed by Solr,
+ * and vice-versa deserializing Solr response documents into CAS objects.
+ * 
+ * Implementing classes are responsible for converting the CAS fields
+ * into corresponding Solr fields as defined in their specific Solr schema.xml, 
+ * and vice-versa for transforming the Solr fields into corresponding CAS fields.
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public interface ProductSerializer {
+	
+	/**
+	 * Method to transform a CAS Product into one or more documents to be indexed by Solr.
+	 * 
+	 * @param product : the product to be indexed
+	 * @param create: true to create a new product, false to update an existing one.
+	 * @return
+	 */
+	List<String> serialize(Product product, boolean create);
+	
+	/**
+	 * Method to transform a CAS Metadata object into one or more Solr "update" documents
+	 * (i.e. documents containing attributes of an existing product).
+	 * 
+	 * @param productId : the product unique identifier
+	 * @param metadata : the CAS metadata hash table
+	 * @param replace : true to override the existing metadata values, false to add new values to the existing ones.
+	 *                  Existing metadata fields not contained in the hash are left unchanged.
+	 *                  Note: the special value Parameters.NULL is used to indicate that the corresponding key must be removed
+	 *                  (as the Metadata object cannot store null or empty lists).
+	 * @return
+	 */
+	List<String> serialize(String productId, Metadata metadata, boolean replace);
+	
+	/**
+	 * Method to transform a CAS Product References object into one or more Solr "update" documents
+	 * (i.e. documents containing attributes of an existing product).
+	 * 
+	 * @param productId
+	 * @param rootReference : the product root reference, may be null
+	 * @param references : list of product references, may be empty
+	 * @param replace : true to replace the existing references, false to add new references to the existing ones
+	 * @return
+	 */
+	List<String> serialize(String productId, Reference rootReference, List<Reference> references, boolean replace);
+	
+	/**
+	 * Method to parse a full XML response document into a list of Product, References and Metadata objects.
+	 * 
+	 * @param xml : the Solr XML document to parse (input)
+	 * @return
+	 * @throws Exception
+	 */
+	QueryResponse deserialize(String xml) throws CatalogException;
+	
+	/**
+	 * Mime type of the documents generated by the specific implementation (XML, JSON etc.)
+	 * @return
+	 */
+	String getMimeType();
+
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/QueryResponse.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/QueryResponse.java
new file mode 100644
index 0000000..4fc5a40
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/QueryResponse.java
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog.solr;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+
+/**
+ * Class holding information returned from querying the Solr server.
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public class QueryResponse {
+
+	/**
+	 * Total number of results matching the query
+	 * (NOT the number of results returned, which is typically less).
+	 */
+	private int numFound = 0;
+	
+	/**
+	 * Offset into returned results.
+	 */
+	private int start = 0;
+	
+	/**
+	 * List of products matching the query,
+	 * with associated metadata and references.
+	 */
+	private List<CompleteProduct> completeProducts;
+	
+	public QueryResponse() {
+		completeProducts = new ArrayList<CompleteProduct>();
+	}
+
+	public void setNumFound(int numFound) {
+		this.numFound = numFound;
+	}
+
+	public void setStart(int start) {
+		this.start = start;
+	}
+
+	public void setResults(List<CompleteProduct> results) {
+		this.completeProducts = results;
+	}
+
+	public int getNumFound() {
+		return numFound;
+	}
+
+	public int getStart() {
+		return start;
+	}
+
+	public List<CompleteProduct> getCompleteProducts() {
+		return completeProducts;
+	}
+	
+	/**
+	 * Utility method to return only the 'product' part of the complete results.
+	 * @return
+	 */
+	public List<Product> getProducts() {
+		List<Product> products = new ArrayList<Product>();
+		for (CompleteProduct cp : completeProducts) {
+			products.add(cp.getProduct());
+		}
+		return products;
+	}
+	
+	
+	
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/SolrCatalog.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/SolrCatalog.java
new file mode 100644
index 0000000..1a9ca4d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/SolrCatalog.java
@@ -0,0 +1,548 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog.solr;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.filemgr.catalog.Catalog;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.QueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.commons.pagination.PaginationUtils;
+import org.springframework.util.StringUtils;
+
+/**
+ * Implementation of the CAS {@link Catalog} interface
+ * that uses a Solr back-end metadata store.
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public class SolrCatalog implements Catalog {
+	
+	// Class responsible for serializing/deserializing CAS products into Solr documents
+	ProductSerializer productSerializer;
+		
+	// Class responsible for generating unique identifiers for incoming Products
+	ProductIdGenerator productIdGenerator;
+	
+	// Class responsible for interacting with the Solr server
+	SolrClient solrClient;
+	
+	private static final Logger LOG = Logger.getLogger(SolrCatalog.class.getName());
+	
+	public SolrCatalog(String solrUrl, ProductIdGenerator productIdGenerator, ProductSerializer productSerializer) {
+		this.productIdGenerator = productIdGenerator;
+		this.productSerializer = productSerializer;
+		this.solrClient = new SolrClient(solrUrl);
+	}
+
+	@Override
+	public void addMetadata(Metadata metadata, Product product) throws CatalogException {
+		
+		LOG.info("Adding metadata for product:"+product.getProductName());
+		
+		// serialize metadadta to Solr document(s)
+	  // replace=false i.e. add metadata to existing values
+		List<String> docs = productSerializer.serialize(product.getProductId(), metadata, false); 
+				
+		// send documents to Solr server
+		solrClient.index(docs, true, productSerializer.getMimeType());
+
+	}
+
+	/**
+	 * This method implementation will remove the specified keys and values from the product metadata,
+	 * leaving all other metadata keys and values unchanged.
+	 * Note: ALL occurrences of each specified (key, value) pair will be removed, not just the first.
+	 */
+	@Override
+	public void removeMetadata(Metadata metadata, Product product) throws CatalogException {
+		
+		// retrieve full existing metadata
+		Metadata currentMetadata = getMetadata(product);
+		
+		// metadata to be updated
+		Metadata updateMetadata = new Metadata();
+		
+		// loop over keys of metadata be updated
+		for (String key : metadata.getKeys()) {
+			
+			// list of values remaining after removal
+			List<String> values = new ArrayList<String>();
+			if (currentMetadata.containsKey(key)) {
+				for (String value : currentMetadata.getAllMetadata(key)) {
+					if (!metadata.getAllMetadata(key).contains(value)) {
+						values.add(value);
+					}					
+				}
+
+				// add remaining values to updated metadata
+				if (values.isEmpty()) {
+					// special value because Metadata will NOT store an empty list
+					values.add(Parameters.NULL);
+				} 
+				updateMetadata.addMetadata(key, values);
+				
+			}
+		}
+		
+		// generate Solr update documents
+		// replace=true to override existing values
+		List<String> docs = productSerializer.serialize(product.getProductId(), updateMetadata, true);
+				
+		// send documents to Solr server
+		solrClient.index(docs, true, productSerializer.getMimeType());
+
+	}
+
+	/**
+	 * Method that adds a Product to the Catalog,
+	 * persisting its fundamental CAS attributes (id, name, type, ingestion time, etc.).
+	 * This method assigns the product a unique identifier, if not existing already.
+	 */
+	@Override
+	public void addProduct(Product product) throws CatalogException {
+		
+		LOG.info("Adding product:"+product.getProductName());
+		
+		// generate product identifier if not existing already
+		if (!StringUtils.hasText(product.getProductId())) {
+			String productId = this.productIdGenerator.generateId(product);
+			product.setProductId(productId);
+		}
+		
+		// serialize product for ingestion into Solr
+		List<String> docs = productSerializer.serialize(product, true); // create=true
+				
+		// send records to Solr
+		solrClient.index(docs, true, productSerializer.getMimeType());
+		
+	}
+
+	@Override
+	public void modifyProduct(Product product) throws CatalogException {
+		
+		LOG.info("Modifying product:"+product.getProductName());
+		
+		// serialize the update product information to Solr document(s)
+		List<String> docs = productSerializer.serialize(product, false); // create=false
+				
+		// send records to Solr
+		solrClient.index(docs, true, productSerializer.getMimeType());
+		
+
+	}
+
+	@Override
+	public void removeProduct(Product product) throws CatalogException {
+				
+		// send message to Solr server
+		solrClient.delete(product.getProductId(), true);
+
+	}
+
+	@Override
+	public void setProductTransferStatus(Product product) throws CatalogException {
+		
+		this.modifyProduct(product);
+
+	}
+
+	@Override
+	public void addProductReferences(Product product) throws CatalogException {
+				
+		// generate update documents (with replace=true)
+		List<String> docs = productSerializer.serialize(product.getProductId(), product.getRootRef(), product.getProductReferences(), true); 
+		
+		// send documents to Solr server
+		solrClient.index(docs, true, productSerializer.getMimeType());
+
+	}
+
+	@Override
+	public Product getProductById(String productId) throws CatalogException {
+				
+			CompleteProduct cp = getCompleteProductById(productId);
+			return cp.getProduct();
+		
+	}
+
+	@Override
+	public Product getProductByName(String productName) throws CatalogException {
+		
+		CompleteProduct cp = getCompleteProductByName(productName);	
+		if (cp!=null) {
+		    LOG.info("Found product name="+productName+" id="+cp.getProduct().getProductId());
+		    return cp.getProduct();
+		} else {
+		    LOG.info("Product with name="+productName+" not found");
+		    return null;
+		}
+		
+	}
+
+	@Override
+	public List<Reference> getProductReferences(Product product) throws CatalogException {
+		
+		CompleteProduct cp = getCompleteProductById(product.getProductId());
+		return cp.getProduct().getProductReferences();
+		
+	}
+
+	@Override
+	public List<Product> getProducts() throws CatalogException {
+				
+		// build query parameters
+		Map<String, String[]> params = new HashMap<String, String[]>();
+		params.put("q", new String[] { "*:*" } );
+		//params.put("rows", new String[] { "20" } ); // control pagination ?
+		
+		// query Solr for all matching products
+		return getProducts(params, 0, -1).getProducts(); // get ALL products
+		
+	}
+	
+	/**
+	 * Common utility to retrieve a range of products matching the specified {@link Query} and {@link ProductType}.
+	 * This method transforms the given constraints in a map of HTTP (name, value) pairs and delegates to the following method.
+	 * 
+	 * @param query
+	 * @param type
+	 * @param offset
+	 * @param limit
+	 * @return
+	 * @throws CatalogException
+	 */
+	private QueryResponse getProducts(Query query, ProductType type, int offset, int limit) throws CatalogException {
+		
+		// build HTTP request
+		HashMap<String, String[]> params = new HashMap<String, String[]>();
+		// product type constraint
+		params.put("q", new String[]{Parameters.PRODUCT_TYPE_NAME+":"+type.getName()} );
+    // convert filemgr query into a Solr query
+		List<String> qc = new ArrayList<String>();
+    for (QueryCriteria queryCriteria : query.getCriteria()) {
+    		LOG.info("Query criteria="+queryCriteria.toString());
+    		qc.add(queryCriteria.toString());
+    }
+    params.put("fq", qc.toArray( new String[ qc.size() ] ));
+    // sort
+    params.put("sort", new String[]{ Parameters.PRODUCT_RECEIVED_TIME+" desc"} );
+
+    return this.getProducts(params, offset, limit);
+		
+	}
+	
+	/**
+	 * Common utility to retrieve a range of products matching the specified query parameters
+	 * @param params : HTTP query parameters used for query to Solr
+	 * @param offset : the index of the first result, starting at 0
+	 * @param limit : the maximum number of returned results (use -1 to return ALL results)
+	 * @return
+	 */
+	private QueryResponse getProducts(Map<String, String[]> params, int offset, int limit) throws CatalogException {
+		
+		// combined results from pagination
+		QueryResponse queryResponse = new QueryResponse();
+		queryResponse.setStart(offset);
+		int start = offset;
+		while (queryResponse.getCompleteProducts().size()<limit || limit<0) {
+			
+			params.put("start", new String[] { ""+start } );
+			String response = solrClient.query(params, productSerializer.getMimeType());
+			QueryResponse qr = productSerializer.deserialize(response);
+			
+			for (CompleteProduct cp : qr.getCompleteProducts()) {
+				if (queryResponse.getCompleteProducts().size()<limit) {
+					queryResponse.getCompleteProducts().add( cp );
+				}
+			}
+			
+			queryResponse.setNumFound( qr.getNumFound() );
+			start = offset+queryResponse.getCompleteProducts().size();
+			if (limit<0) limit = queryResponse.getNumFound(); // retrieve ALL results
+			if (start>=queryResponse.getNumFound()) break; // don't query any longer
+			
+		}
+		
+		LOG.info("Total number of products found="+queryResponse.getNumFound());
+		LOG.info("Total number of products returned="+queryResponse.getCompleteProducts().size());
+		return queryResponse;
+		
+	}
+
+	@Override
+	public List<Product> getProductsByProductType(ProductType type) throws CatalogException {
+
+		// build query parameters
+		Map<String, String[]> params = new HashMap<String, String[]>();
+		params.put("q", new String[] { "*:*" } );
+		// use the product type name as query parameter
+		params.put("fq", new String[] { Parameters.PRODUCT_TYPE_NAME+":"+type.getName() } );
+		
+		// query Solr for all matching products
+		return getProducts(params, 0, -1).getProducts(); // get ALL products
+
+	}
+
+	@Override
+	public Metadata getMetadata(Product product) throws CatalogException {
+		
+		CompleteProduct cp = getCompleteProductById(product.getProductId());
+		return cp.getMetadata();
+		
+	}
+
+	@Override
+	public Metadata getReducedMetadata(Product product, List<String> elements) throws CatalogException {
+		
+		// build HTTP request
+		HashMap<String, String[]> params = new HashMap<String, String[]>();
+		params.put("q", new String[]{Parameters.PRODUCT_ID+":"+product.getProductId()} );
+		// request metadata elements explicitly
+		params.put("fl", elements.toArray(new String[elements.size()]) );
+		
+		// execute request
+		String doc = solrClient.query(params, productSerializer.getMimeType());
+		
+		// parse response
+		CompleteProduct cp = extractCompleteProduct(doc);
+		return cp.getMetadata();
+		
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * Note that this method implementation will return ALL products in the catalog matching the query criteria.
+	 */
+	@Override
+	public List<String> query(Query query, ProductType type) throws CatalogException {
+		
+    // execute request for ALL results
+    QueryResponse queryResponse =  this.getProducts(query, type, 0, -1); // get ALL products 
+
+		// extract ids from products
+		List<String> ids = new ArrayList<String>();
+		for (CompleteProduct cp : queryResponse.getCompleteProducts()) {
+			ids.add(cp.getProduct().getProductId());
+		}
+		
+		return ids;
+		
+	}
+
+	@Override
+	public List<Product> getTopNProducts(int n) throws CatalogException {		
+				
+		// retrieve most recent n products from Solr
+		String doc = solrClient.queryProductsByDate(n, productSerializer.getMimeType());
+		
+		// parse Solr response into Product objects
+		return this.getProductsFromDocument(doc);
+		
+	}
+	
+	@Override
+	public ProductPage pagedQuery(Query query, ProductType type, int pageNum) throws CatalogException {
+				
+		
+    // execute request for one page of results
+    int offset = (pageNum-1)*Parameters.PAGE_SIZE;
+    int limit = Parameters.PAGE_SIZE;
+    QueryResponse queryResponse = this.getProducts(query, type, offset, limit);
+
+    // build product page from query response
+    return newProductPage(pageNum, queryResponse);
+		
+	}
+	
+	@Override
+	public ProductPage getFirstPage(ProductType type) {
+		try {
+			return this.pagedQuery(new Query(), type, 1);
+			
+		} catch(CatalogException e) {
+			throw new RuntimeException(e.getMessage());
+		}
+	}
+
+	@Override
+	public ProductPage getLastProductPage(ProductType type) {
+		
+		try {
+			
+			// query for total number of products of this type
+			int numTotalResults = this.getNumProducts(type);
+			
+			// compute last page number
+			int numOfPages = PaginationUtils.getTotalPage(numTotalResults, Parameters.PAGE_SIZE);
+			
+			// request last page
+			return pagedQuery(new Query(), type, numOfPages);
+		
+		} catch(CatalogException e) {
+			throw new RuntimeException(e.getMessage());
+		}
+		
+	}
+
+	@Override
+	public ProductPage getNextPage(ProductType type, ProductPage currentPage) {
+		
+		int nextPageNumber = currentPage.getPageNum()+1;
+		if (nextPageNumber>currentPage.getTotalPages()) throw new RuntimeException("Invalid next page number: "+nextPageNumber);
+
+		try {
+			return this.pagedQuery(new Query(), type, currentPage.getPageNum()+1);
+			
+		} catch(CatalogException e) {
+			throw new RuntimeException(e.getMessage());
+		}
+		
+	}
+
+	@Override
+	public ProductPage getPrevPage(ProductType type, ProductPage currentPage) {
+		
+		int prevPageNumber = currentPage.getPageNum()-1;
+		if (prevPageNumber<=0) throw new RuntimeException("Invalid previous page number: "+prevPageNumber);
+		
+		try {
+			return this.pagedQuery(new Query(), type, prevPageNumber);
+			
+		} catch(CatalogException e) {
+			throw new RuntimeException(e.getMessage());
+		}
+		
+	}
+	
+	/**
+	 * Common functionality for extracting products from a Solr response document.
+	 * @param doc
+	 * @return
+	 */
+	private List<Product> getProductsFromDocument(String doc) throws CatalogException {
+		
+		// extract full product information from Solr response
+		QueryResponse queryResponse = productSerializer.deserialize(doc);
+		
+		// return products only
+		return queryResponse.getProducts();
+		
+	}
+
+	@Override
+	public List<Product> getTopNProducts(int n, ProductType type) throws CatalogException {
+		
+		// retrieve most recent n products from Solr
+		String doc = solrClient.queryProductsByDateAndType(n, type, productSerializer.getMimeType());
+		
+		// parse Solr response into Product objects
+		return this.getProductsFromDocument(doc);
+		
+	}
+
+	@Override
+	public ValidationLayer getValidationLayer() throws CatalogException {
+		// FIXME: must parse Solr schema.xmnl from:
+		// http://localhost:8080/solr/admin/file/?contentType=text/xml;charset=utf-8&file=schema.xml
+		throw new RuntimeException("Method 'getValidationLayer' not yet implemented");
+	}
+
+	@Override
+	public int getNumProducts(ProductType type) throws CatalogException {
+		
+		// build query parameters
+		Map<String, String[]> params = new HashMap<String, String[]>();
+		params.put("q", new String[] { "*:*" } );
+		params.put("rows", new String[] { "0" } ); // don't return any results
+		
+		// execute query
+		String response = solrClient.query(params, productSerializer.getMimeType());
+		
+		// parse response
+		QueryResponse queryResponse = productSerializer.deserialize(response);
+		return queryResponse.getNumFound();
+		
+	}
+	
+	private CompleteProduct getCompleteProductById(String productId) throws CatalogException {
+							
+		// request document with given id
+		String doc = solrClient.queryProductById(productId, productSerializer.getMimeType());
+		
+		// parse document into complete product
+		return extractCompleteProduct(doc);
+		
+	}
+	
+	private CompleteProduct getCompleteProductByName(String productName) throws CatalogException {	
+		
+		// request document with given id
+		String doc = solrClient.queryProductByName(productName, productSerializer.getMimeType());
+		
+		// parse document into complete product
+		return extractCompleteProduct(doc);
+		
+	}
+	
+	private CompleteProduct extractCompleteProduct(String doc) throws CatalogException {
+		
+		// deserialize document into Product
+		LOG.info("Parsing Solr document: "+doc);
+		QueryResponse queryResponse = productSerializer.deserialize(doc);
+		int numFound = queryResponse.getNumFound();
+		if (numFound>1) {
+			throw new CatalogException("Product query returned "+numFound+" results instead of 1!");
+		} else if (numFound==0) {
+			return null; // no product found
+		} else {
+			return queryResponse.getCompleteProducts().get(0);
+		}
+			
+	}
+
+	/**
+	 * Factory method to create a {@link ProductPage} from a {@link QueryResponse}.
+	 * @param pageNumber
+	 * @param queryResponse
+	 * @return
+	 */
+	private ProductPage newProductPage(int pageNum, QueryResponse queryResponse) {
+		
+		ProductPage page = new ProductPage();
+		page.setPageNum(pageNum);
+		page.setPageSize(queryResponse.getProducts().size());
+		page.setNumOfHits(queryResponse.getNumFound());
+		page.setPageProducts(queryResponse.getProducts());
+		page.setTotalPages(PaginationUtils.getTotalPage(queryResponse.getNumFound(), Parameters.PAGE_SIZE));
+		return page;
+		
+	}
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/SolrCatalogFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/SolrCatalogFactory.java
new file mode 100644
index 0000000..adaeabf
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/SolrCatalogFactory.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog.solr;
+
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.filemgr.catalog.Catalog;
+import org.apache.oodt.cas.filemgr.catalog.CatalogFactory;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+/**
+ * Factory class that creates a {@link SolrCatalog} instance
+ * configured with the properties specified in filemgr.properties.
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public class SolrCatalogFactory implements CatalogFactory {
+	
+	private String solrUrl;
+	private ProductIdGenerator productIdGenerator;
+	private ProductSerializer productSerializer;
+	
+	private static final Logger LOG = Logger.getLogger(SolrCatalogFactory.class.getName());
+	
+	public SolrCatalogFactory() throws IllegalArgumentException {
+		
+		// base Solr URL
+		String solrUrl = System.getProperty("org.apache.oodt.cas.filemgr.catalog.solr.url");
+		if (solrUrl==null) {
+			throw new IllegalArgumentException("Invalid Solr URL specified from property 'org.apache.oodt.cas.filemgr.catalog.solr.url'");
+		}
+		
+		this.solrUrl = PathUtils.replaceEnvVariables( solrUrl );
+		this.configure();
+		
+	}
+	
+	/**
+	 * Method to configure the specific flavor of the Solr catalog implementation
+	 * before the catalog is instantiated.
+	 */
+	private void configure() {
+		
+		// product serializer
+		String productSerializerClass = System.getProperty("org.apache.oodt.cas.filemgr.catalog.solr.productSerializer");
+		if (productSerializerClass!=null) {
+			try {
+				productSerializer = (ProductSerializer)Class.forName( PathUtils.replaceEnvVariables(productSerializerClass) ).newInstance();
+			} catch(Exception e) {
+				LOG.severe(e.getMessage());
+				System.exit(-1);
+			}
+		} else {
+			productSerializer = new DefaultProductSerializer();
+		}
+		
+		// product id generator
+		String productIdGeneratorClass = System.getProperty("org.apache.oodt.cas.filemgr.catalog.solr.productIdGenerator");
+		if (productIdGeneratorClass!=null) {
+			try {
+				productIdGenerator = (ProductIdGenerator)Class.forName( PathUtils.replaceEnvVariables(productIdGeneratorClass) ).newInstance();
+			} catch(Exception e) {
+				LOG.severe(e.getMessage());
+				System.exit(-1);
+			}
+		} else {
+			productIdGenerator = new UUIDProductIdGenerator();
+		}
+		
+	}
+
+	@Override
+	public Catalog createCatalog() {
+		LOG.info("Creating Solr Catalog for URL="+this.solrUrl);
+		return new SolrCatalog(solrUrl, productIdGenerator, productSerializer);
+	}
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/SolrClient.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/SolrClient.java
new file mode 100644
index 0000000..52196c6
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/SolrClient.java
@@ -0,0 +1,341 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog.solr;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+
+/**
+ * Class containing client-side functionality for interacting with a Solr server.
+ * This class uses an {@link HttpClient} for all HTTP communication.
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public class SolrClient {
+		
+	// base URL of Solr server
+	private String solrUrl;
+	
+	private final Logger LOG = Logger.getLogger(this.getClass().getName());
+	
+	/**
+	 * Constructor initializes the Solr URL
+	 * @param url
+	 */
+	public SolrClient(final String url) {
+		
+		solrUrl = url;
+		
+	}
+	
+	/**
+	 * Method to send one or more documents to be indexed to Solr.
+	 * 
+	 * @param document
+	 * @param commit
+	 * @param mimeType : the mime-type format of the documents
+	 * @return
+	 * @throws MalformedURLException
+	 */
+	public String index(List<String> docs, boolean commit, String mimeType) throws CatalogException {
+		
+		try {
+			
+			final String url = this.buildUpdateUrl();
+			
+			// build message
+			StringBuilder message = new StringBuilder("<add>");
+			for (String doc : docs) {
+				message.append(doc);
+			}
+			message.append("</add>");	
+	    
+	    // send POST request
+	    LOG.info("Posting message:"+message+" to URL:"+url);
+	    String response = doPost(url, message.toString(), mimeType);
+	    LOG.info(response);
+	    
+	    // commit changes ?
+	    if (commit) this.commit();
+	    
+	    LOG.info(response);
+	    return response;
+    
+		} catch(Exception e) {
+			e.printStackTrace();
+			throw new CatalogException(e.getMessage());
+		}
+    
+	}
+	
+	/**
+	 * Method to send a message containing a 'delete' instruction to Solr.
+	 * @param id
+	 * @param commit
+	 * @return
+	 * @throws Exception
+	 */
+	public String delete(String id, boolean commit) throws CatalogException {
+		
+		try {
+			
+			// build POST request
+			String url = this.buildUpdateUrl();
+			if (commit) url += "?commit=true";
+			String message = "<delete><query>id:"+id+"</query></delete>";
+			
+	    // send POST request
+	    LOG.info("Posting message:"+message+" to URL:"+url);
+	    String response = doPost(url, message, Parameters.MIME_TYPE_XML);
+
+	    return response;
+    
+		} catch(Exception e) {
+			e.printStackTrace();
+			throw new CatalogException(e.getMessage());
+		}
+		
+	}
+	
+	/**
+	 * Method to query the Solr index for a product with the specified id.
+	 * @param id
+	 * @return
+	 */
+	public String queryProductById(String id, String mimeType) throws CatalogException {
+		
+		HashMap<String, String[]> params = new HashMap<String, String[]>();
+		params.put("q", new String[]{Parameters.PRODUCT_ID+":"+id} );
+		return query(params, mimeType);
+		
+	}
+	
+	/**
+	 * Method to query the Solr index for a product with the specified name.
+	 * @param id
+	 * @return
+	 */
+	public String queryProductByName(String name, String mimeType) throws CatalogException {
+		
+		HashMap<String, String[]> params = new HashMap<String, String[]>();
+		params.put("q", new String[]{Parameters.PRODUCT_NAME+":"+name} );
+		return query(params, mimeType);
+		
+	}
+	
+	/**
+	 * Method to query Solr for the most recent 'n' products.
+	 * @param n
+	 * @return
+	 * @throws CatalogException
+	 */
+	public String queryProductsByDate(int n, String mimeType) throws CatalogException {
+		
+		HashMap<String, String[]> params = new HashMap<String, String[]>();
+		params.put("q", new String[]{ "*:*"} );
+		params.put("rows", new String[]{ ""+n} );
+		params.put("sort", new String[]{ Parameters.PRODUCT_RECEIVED_TIME+" desc"} );
+		return query(params, mimeType);
+		
+	}
+	
+	/**
+	 * Method to query Solr for the most recent 'n' products of a specified type.
+	 * @param n
+	 * @return
+	 * @throws CatalogException
+	 */
+	public String queryProductsByDateAndType(int n, ProductType type, String mimeType) throws CatalogException {
+		
+		HashMap<String, String[]> params = new HashMap<String, String[]>();
+		params.put("q", new String[]{ Parameters.PRODUCT_TYPE_NAME+type.getName() } );
+		params.put("rows", new String[]{ ""+n} );
+		params.put("sort", new String[]{ Parameters.PRODUCT_RECEIVED_TIME+" desc"} );
+		return query(params, mimeType);
+		
+	}
+	
+	/**
+	 * Method to commit the current changes to the Solr index.
+	 * @throws MalformedURLException
+	 */
+	public void commit() throws Exception {
+		
+		String message = "<commit waitSearcher=\"true\"/>";
+		String url =  this.buildUpdateUrl();
+		doPost(url, message, Parameters.MIME_TYPE_XML);
+		
+	}
+	
+	/**
+	 * Method to send a generic query to the Solr server.
+	 * 
+	 * @param parameters
+	 * @param mimeType : the desired mime type for the results (XML, JSON, ...)
+	 * @return
+	 */
+	public String query(Map<String, String[]> parameters, String mimeType) throws CatalogException {
+		
+		try {
+			
+			// build HTTP request
+			String url = this.buildSelectUrl();
+			
+			// execute request
+			String response = this.doGet(url, parameters, mimeType);
+			return response;
+		
+		} catch(Exception e) {
+			e.printStackTrace();
+			throw new CatalogException(e.getMessage());
+		}
+		
+	}
+		
+	/**
+	 * Method to execute a GET request to the given URL with the given parameters.
+	 * @param url
+	 * @param parameters
+	 * @return
+	 */
+	private String doGet(String url, Map<String, String[]> parameters, String mimeType)  throws Exception {
+				    
+		// build HTTP/GET request
+    GetMethod method = new GetMethod(url);
+    List<NameValuePair> nvps = new ArrayList<NameValuePair>();
+    for (String key : parameters.keySet()) {
+    	for (String value : parameters.get(key)) {
+    		nvps.add(new NameValuePair(key, value));
+    	}
+    }
+    // request results in JSON format
+    if (mimeType.equals(Parameters.MIME_TYPE_JSON)) nvps.add(new NameValuePair("wt", "json"));
+    method.setQueryString( nvps.toArray( new NameValuePair[nvps.size()] ) );
+    LOG.info("GET url: "+url+" query string: "+method.getQueryString());
+    
+    // send HTTP/GET request, return response
+    return doHttp(method);
+    
+  }
+	
+	/**
+	 * Method to execute a POST request to the given URL.
+	 * @param url
+	 * @param document
+	 * @return
+	 */
+	private String doPost(String url, String document, String mimeType) throws Exception {
+    
+		// build HTTP/POST request
+    PostMethod method = new PostMethod(url);
+    StringRequestEntity requestEntity = new StringRequestEntity(document, mimeType, "UTF-8");
+    method.setRequestEntity(requestEntity);
+    
+    // send HTTP/POST request, return response
+    return doHttp(method);
+		
+	}
+	
+	/**
+	 * Common functionality for HTTP GET and POST requests.
+	 * @param method
+	 * @return
+	 * @throws Exception
+	 */
+	private String doHttp(HttpMethod method) throws Exception {
+		
+		StringBuilder response = new StringBuilder();
+		BufferedReader br = null;
+		try {
+			
+	    // send request
+	    HttpClient httpClient = new HttpClient();
+            // OODT-719 Prevent httpclient from spawning closewait tcp connections
+            method.setRequestHeader("Connection", "close");
+
+	    int statusCode = httpClient.executeMethod(method);	    
+	    
+	    // read response
+	    if (statusCode != HttpStatus.SC_OK) {
+	    	
+	    	// still consume the response
+	    	method.getResponseBodyAsString();
+	      throw new CatalogException("HTTP method failed: " + method.getStatusLine());
+	      
+	    } else {
+	
+		    // read the response body.
+		    br = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
+        String readLine;
+        while(((readLine = br.readLine()) != null)) {
+          response.append(readLine);
+        }
+	    
+	    }
+	  	
+	  } finally {
+	    // must release the connection even if an exception occurred
+	    method.releaseConnection();
+	    if (br!=null) try { br.close(); } catch (Exception e) {}
+	  }  
+  
+	  return response.toString();
+  
+	}
+	
+	/**
+	 * Builds the URL used to update the Solr index.
+	 * 
+	 * Example: http://localhost:8983/solr/update?
+	 * @return
+	 */
+	private String buildUpdateUrl() {
+		
+		return solrUrl + (solrUrl.endsWith("/") ? "" : "/") + "update";
+		
+	}
+	
+	/**
+	 * Builds the URL used to query the Solr index.
+	 * 
+	 * Example: http://localhost:8983/solr/select?
+	 * @return
+	 */
+	private String buildSelectUrl() {
+		
+		return solrUrl + (solrUrl.endsWith("/") ? "" : "/") + "select";
+		
+	}
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/UUIDProductIdGenerator.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/UUIDProductIdGenerator.java
new file mode 100644
index 0000000..a43488d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/catalog/solr/UUIDProductIdGenerator.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog.solr;
+
+import java.util.UUID;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+
+/**
+ * Implementation of {@link ProductIdGenerator} that assigns the product
+ * identifier as a newly generated UUID.
+ * Note that this generator will cause multiple submissions of the same named product
+ * to result in as many records in the Solr index.
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public class UUIDProductIdGenerator implements ProductIdGenerator {
+
+	@Override
+	public String generateId(Product product) {
+		return UUID.randomUUID().toString();
+	}
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/AbstractDeleteProductCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/AbstractDeleteProductCliAction.java
new file mode 100644
index 0000000..72e4bdd
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/AbstractDeleteProductCliAction.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//OODT imports
+import java.io.File;
+import java.net.URI;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+/**
+ * A abstract {@link CmdLineAction} for deleting {@link Product}s.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public abstract class AbstractDeleteProductCliAction extends
+      FileManagerCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      Product p = null;
+      try {
+         XmlRpcFileManagerClient client = getClient();
+         p = getProductToDelete();
+         List<Reference> refs = client.getProductReferences(p);
+         if (refs == null) {
+            throw new Exception("FileManager returned null References");
+         }
+         for (Reference ref : refs) {
+            if (!client.removeFile(new File(new URI(ref.getDataStoreReference()))
+                  .getAbsolutePath())) {
+               throw new Exception("Failed to delete file '"
+                     + ref.getDataStoreReference() + "'");
+            }
+         }
+         if (client.removeProduct(p)) {
+            printer.println("Successfully deleted product '"
+                  + p.getProductName() + "'");
+         } else {
+            throw new Exception("Delete product returned false");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to delete product '" + p
+               + "' : " + e.getMessage(), e);
+      }
+   }
+
+   protected abstract Product getProductToDelete() throws Exception;
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/AbstractGetProductCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/AbstractGetProductCliAction.java
new file mode 100644
index 0000000..f166d78
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/AbstractGetProductCliAction.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+
+/**
+ * A {@link CmdLineAction} which gets information about a {@link Product}
+ * by ID.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public abstract class AbstractGetProductCliAction extends FileManagerCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer) throws CmdLineActionException {
+      try {
+         Product p = getProduct();
+         printer.println("Product:");
+         printer.println(" - ID: " + p.getProductId());
+         printer.println(" - Name: " + p.getProductName());
+         printer.println(" - ProductType: " + p.getProductType().getName());
+         printer.println(" - Structure: " + p.getProductStructure());
+         printer.println(" - Status: " + p.getTransferStatus());
+         if (p.getRootRef() != null) {
+            printer.println(" - RootRef: " + p.getRootRef().getDataStoreReference());
+         }
+         if (!p.getProductReferences().isEmpty()) {
+            printer.println(" - References: ");
+            for (Reference ref : p.getProductReferences()) {
+               printer.println("    - " + ref.getDataStoreReference()
+                     + " (" + ref.getFileSize() + ")");
+            }
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get product info : "
+               + e.getMessage(), e);
+      }
+   }
+
+   protected abstract Product getProduct() throws Exception;
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/AbstractQueryCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/AbstractQueryCliAction.java
new file mode 100644
index 0000000..7c15a44
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/AbstractQueryCliAction.java
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.query.ComplexQuery;
+import org.apache.oodt.cas.filemgr.structs.query.QueryFilter;
+import org.apache.oodt.cas.filemgr.structs.query.QueryResult;
+import org.apache.oodt.cas.filemgr.structs.query.conv.VersionConverter;
+import org.apache.oodt.cas.filemgr.structs.query.filter.FilterAlgor;
+
+/**
+ * Abstract query {@link CmdLineAction}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public abstract class AbstractQueryCliAction extends FileManagerCliAction {
+
+   private String sortBy;
+   private String outputFormat;
+   private String delimiter;
+
+   private FilterAlgor filterAlgor;
+   private String startDateTimeMetKey;
+   private String endDateTimeMetKey;
+   private String priorityMetKey;
+   private VersionConverter versionConverter;
+
+   public AbstractQueryCliAction() {
+      delimiter = "\n";
+   }
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         ComplexQuery complexQuery = getQuery();
+         complexQuery.setSortByMetKey(sortBy);
+         complexQuery.setToStringResultFormat(outputFormat);
+
+         if (filterAlgor != null) {
+            Validate.notNull(startDateTimeMetKey,
+                  "Must specify startDateTimeMetKey");
+            Validate.notNull(endDateTimeMetKey,
+                  "Must specify endDateTimeMetKey");
+            Validate.notNull(priorityMetKey, "Must specify priorityMetKey");
+            QueryFilter filter = new QueryFilter(startDateTimeMetKey,
+                  endDateTimeMetKey, priorityMetKey, filterAlgor);
+            if (versionConverter != null) {
+               filter.setConverter(versionConverter);
+            }
+            complexQuery.setQueryFilter(filter);
+         }
+         List<QueryResult> results = getClient().complexQuery(complexQuery);
+         StringBuffer returnString = new StringBuffer("");
+         for (QueryResult qr : results) {
+            returnString.append(qr.toString() + delimiter);
+         }
+         if (returnString.length() > 0) {
+            printer.println(returnString.substring(0, returnString.length()
+               - delimiter.length()));
+         } else {
+            printer.println("Query returned no results");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to perform sql query : "
+               + "sortBy '"
+               + sortBy
+               + "', "
+               + "outputFormat '"
+               + outputFormat
+               + "', and delimiter '"
+               + delimiter
+               + "', filterAlgor '"
+               + (filterAlgor != null ? filterAlgor.getClass()
+                     .getCanonicalName() : null)
+               + "', startDateTimeMetKey '"
+               + startDateTimeMetKey
+               + "', endDateTimeMetKey '"
+               + endDateTimeMetKey
+               + "', priorityMetKey '"
+               + priorityMetKey
+               + "', "
+               + (versionConverter != null ? versionConverter.getClass()
+                     .getCanonicalName() : null) + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public abstract ComplexQuery getQuery() throws Exception;
+
+   public void setSortBy(String sortBy) {
+      this.sortBy = sortBy;
+   }
+
+   public void setOutputFormat(String outputFormat) {
+      this.outputFormat = outputFormat;
+   }
+
+   public void setDelimiter(String delimiter) {
+      this.delimiter = delimiter;
+   }
+
+   public void setFilterAlgor(FilterAlgor filterAlgor) {
+      this.filterAlgor = filterAlgor;
+   }
+
+   public void setStartDateTimeMetKey(String startDateTimeMetKey) {
+      this.startDateTimeMetKey = startDateTimeMetKey;
+   }
+
+   public void setEndDateTimeMetKey(String endDateTimeMetKey) {
+      this.endDateTimeMetKey = endDateTimeMetKey;
+   }
+
+   public void setPriorityMetKey(String priorityMetKey) {
+      this.priorityMetKey = priorityMetKey;
+   }
+
+   public void setVersionConverter(VersionConverter versionConverter) {
+      this.versionConverter = versionConverter;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/AddProductTypeCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/AddProductTypeCliAction.java
new file mode 100644
index 0000000..b8f1637
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/AddProductTypeCliAction.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+
+/**
+ * A {@link CmdLineAction} which adds a {@link ProductType} to the file manager.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class AddProductTypeCliAction extends FileManagerCliAction {
+
+   private String productTypeName;
+   private String productTypeDescription;
+   private String fileRepositoryPath;
+   private String versioner;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(productTypeName, "Must specify productTypeName");
+         Validate.notNull(productTypeDescription,
+               "Must specify productTypeDescription");
+         Validate
+               .notNull(fileRepositoryPath, "Must specify fileRepositoryPath");
+         Validate.notNull(versioner, "Must specify versioner");
+
+         ProductType type = new ProductType();
+         type.setName(productTypeName);
+         type.setDescription(productTypeDescription);
+         type.setProductRepositoryPath(fileRepositoryPath);
+         type.setVersioner(versioner);
+
+         printer.println("addProductType: Result: "
+               + getClient().addProductType(type));
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to add product type with "
+               + "name '" + productTypeName + "', description '"
+               + productTypeDescription + "', repository '"
+               + fileRepositoryPath + ", and versioner '" + versioner + "' : "
+               + e.getMessage(), e);
+      }
+   }
+
+   public void setProductTypeName(String productTypeName) {
+      this.productTypeName = productTypeName;
+   }
+
+   public void setProductTypeDescription(String productTypeDescription) {
+      this.productTypeDescription = productTypeDescription;
+   }
+
+   public void setFileRepositoryPath(String fileRepositoryPath) {
+      this.fileRepositoryPath = fileRepositoryPath;
+   }
+
+   public void setVersioner(String versioner) {
+      this.versioner = versioner;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/DeleteProductByIdCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/DeleteProductByIdCliAction.java
new file mode 100644
index 0000000..49ab643
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/DeleteProductByIdCliAction.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+/**
+ * A {@link CmdLineAction} which deletes a {@link Product} by ID.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class DeleteProductByIdCliAction extends AbstractDeleteProductCliAction {
+
+   private String productId;
+
+   @Override
+   public Product getProductToDelete() throws Exception {
+      Validate.notNull(productId, "Must specify productId");
+
+      XmlRpcFileManagerClient client = getClient();
+      Product p = client.getProductById(productId);
+      if (p == null) {
+         throw new Exception("FileManager returned null for product '"
+               + productId + "'");
+      }
+      return p;
+   }
+
+   public void setProductId(String productId) {
+      this.productId = productId;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/DeleteProductByNameCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/DeleteProductByNameCliAction.java
new file mode 100644
index 0000000..254d02f
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/DeleteProductByNameCliAction.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+
+/**
+ * A {@link CmdLineAction} which deletes a {@link Product} by name.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class DeleteProductByNameCliAction extends
+      AbstractDeleteProductCliAction {
+
+   private String productName;
+
+   @Override
+   protected Product getProductToDelete() throws Exception {
+      Validate.notNull(productName, "Must specify productName");
+
+      Product p = getClient().getProductByName(productName);
+      if (p == null) {
+         throw new CmdLineActionException(
+               "FileManager returned null for product '" + productName + "'");
+      }
+      return p;
+   }
+
+   public void setProductName(String productName) {
+      this.productName = productName;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/DumpMetadataCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/DumpMetadataCliAction.java
new file mode 100644
index 0000000..4fb835a
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/DumpMetadataCliAction.java
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//OODT static imports
+import static org.apache.oodt.cas.filemgr.metadata.CoreMetKeys.FILENAME;
+import static org.apache.oodt.cas.filemgr.metadata.CoreMetKeys.PRODUCT_NAME;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+/**
+ * A {@link CmdLineAction} which dumps out metadata for a given {@link Product}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class DumpMetadataCliAction extends FileManagerCliAction {
+
+   private String productId;
+   private File outputDir;
+
+   @Override
+   public void execute(final ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(productId, "Must specify productId");
+
+         Product product = getClient().getProductById(productId);
+         if (product == null) {
+            throw new Exception("FileManager returned null product");
+         }
+         Metadata metadata = getClient().getMetadata(product);
+         if (metadata == null) {
+            throw new Exception("FileManager returned null metadata");
+         }
+         if (outputDir != null) {
+            if (outputDir.exists()) {
+               XMLUtils.writeXmlFile(
+                     new SerializableMetadata(metadata).toXML(), new File(
+                           outputDir.getAbsoluteFile(),
+                           generateFilename(metadata)).getAbsolutePath());
+            } else {
+               throw new Exception("Output dir '" + outputDir
+                     + "' does not exist");
+            }
+         } else {
+            OutputStream os = new OutputStream() {
+               private StringBuffer sb = new StringBuffer("");
+
+               @Override
+               public void write(int character) throws IOException {
+                  sb.append((char) character);
+               }
+
+               @Override
+               public void close() throws IOException {
+                  super.close();
+                  printer.println(sb.toString());
+               }
+            };
+            XMLUtils.writeXmlToStream(
+                  new SerializableMetadata(metadata).toXML(),
+                  os); 
+            os.close();
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get metadata for product '" + productId + "' : "
+                     + e.getMessage(), e);
+      }
+   }
+
+   public void setProductId(String productId) {
+      this.productId = productId;
+   }
+
+   public void setOutputDir(File outputDir) {
+      this.outputDir = outputDir;
+   }
+
+   private String generateFilename(Metadata metadata) {
+      String filename = metadata.getMetadata(FILENAME) != null ? metadata
+            .getMetadata(FILENAME) : metadata.getMetadata(PRODUCT_NAME);
+      return filename + ".met";
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/FileManagerCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/FileManagerCliAction.java
new file mode 100644
index 0000000..c91d5ab
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/FileManagerCliAction.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+/**
+ * Base {@link CmdLineAction} for File Manager.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public abstract class FileManagerCliAction extends CmdLineAction {
+
+   private XmlRpcFileManagerClient client;
+
+   public String getUrl() {
+      return System.getProperty("org.apache.oodt.cas.filemgr.url");
+   }
+
+   protected XmlRpcFileManagerClient getClient()
+         throws MalformedURLException, ConnectionException {
+      Validate.notNull(getUrl(), "Must specify url");
+
+      if (client != null) {
+         return client;
+      } else {
+         return new XmlRpcFileManagerClient(new URL(getUrl()), false);
+      }
+   }
+
+   public void setClient(XmlRpcFileManagerClient client) {
+      this.client = client;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetCurrentTransferCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetCurrentTransferCliAction.java
new file mode 100644
index 0000000..a6bfc48
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetCurrentTransferCliAction.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+
+/**
+ * A {@link CmdLineAction} which get the current {@link Product} file transfer.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetCurrentTransferCliAction extends FileManagerCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         FileTransferStatus status = getClient().getCurrentFileTransfer();
+         if (status == null) {
+            throw new NullPointerException(
+                  "FileManager returned null transfer status");
+         }
+         printer.println("File Transfer: [ref={orig="
+               + status.getFileRef().getOrigReference() + ",ds="
+               + status.getFileRef().getDataStoreReference() + "},product="
+               + status.getParentProduct().getProductName() + ",fileSize="
+               + status.getFileRef().getFileSize() + ",amtTransferred="
+               + status.getBytesTransferred() + ",pct="
+               + status.computePctTransferred() + "]");
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get current file transfer : " + e.getMessage(), e);
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetCurrentTransfersCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetCurrentTransfersCliAction.java
new file mode 100644
index 0000000..9e1ef7b
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetCurrentTransfersCliAction.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+
+/**
+ * A {@link CmdLineAction} which get list of current {@link Product} file
+ * transfers.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetCurrentTransfersCliAction extends FileManagerCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         List<FileTransferStatus> statuses = getClient()
+               .getCurrentFileTransfers();
+         if (statuses == null) {
+            throw new NullPointerException(
+                  "FileManager returned null file transfers");
+         }
+         for (FileTransferStatus status : statuses) {
+            printer.println("File Transfer: [ref={orig="
+                  + status.getFileRef().getOrigReference() + ",ds="
+                  + status.getFileRef().getDataStoreReference() + "},product="
+                  + status.getParentProduct().getProductName() + ",fileSize="
+                  + status.getFileRef().getFileSize() + ",amtTransferred="
+                  + status.getBytesTransferred() + ",pct="
+                  + status.computePctTransferred() + "]");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get list of current file transfers : "
+                     + e.getMessage(), e);
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetFilePercentTransferredCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetFilePercentTransferredCliAction.java
new file mode 100644
index 0000000..111e3ac
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetFilePercentTransferredCliAction.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.io.File;
+import java.net.URI;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+
+/**
+ * A {@link CmdLineAction} which get percent transferred for a given data file.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetFilePercentTransferredCliAction extends FileManagerCliAction {
+
+   private String origRef;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(origRef, "Must specify origRef");
+
+         Reference ref = new Reference();
+         ref.setOrigReference(getUri(origRef).toString());
+
+         printer.println("Reference: [origRef=" + origRef + ",transferPct="
+               + getClient().getRefPctTransferred(ref) + "]");
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get percent transfered for" + " file '" + origRef
+                     + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setOrigRef(String origRef) {
+      this.origRef = origRef;
+   }
+
+   private URI getUri(String filePath) {
+      if (new File(filePath).exists()) {
+         return new File(filePath).toURI();
+      } else {
+         return URI.create(filePath);
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetFirstPageCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetFirstPageCliAction.java
new file mode 100644
index 0000000..c65d2c2
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetFirstPageCliAction.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+/**
+ * A {@link CmdLineAction} which gets the first page of {@link Product}s of a
+ * given {@link ProductType}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetFirstPageCliAction extends FileManagerCliAction {
+
+   private String productTypeName;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(productTypeName, "Must specify productTypeName");
+
+         XmlRpcFileManagerClient client = getClient();
+         ProductType type = client.getProductTypeByName(productTypeName);
+         if (type == null) {
+            throw new Exception("FileManager returned null ProductType");
+         }
+         ProductPage firstPage = client.getFirstPage(type);
+         if (firstPage == null) {
+            throw new Exception("FileManager returned null product page");
+         }
+         printer.println("Page: [num=" + firstPage.getPageNum()
+               + ", totalPages=" + firstPage.getTotalPages() + ", pageSize="
+               + firstPage.getPageSize() + "]");
+         printer.println("Products:");
+
+         if (firstPage.getPageProducts() == null) {
+            throw new Exception("Page Products is null");
+         }
+         for (Product p : firstPage.getPageProducts()) {
+            printer.println("Product: [id=" + p.getProductId() + ",name="
+                  + p.getProductName() + ",type="
+                  + p.getProductType().getName() + ",structure="
+                  + p.getProductStructure() + ", transferStatus="
+                  + p.getTransferStatus() + "]");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get first page of products for"
+                     + " ProductType name '" + productTypeName + "' : "
+                     + e.getMessage(), e);
+      }
+   }
+
+   public void setProductTypeName(String productTypeName) {
+      this.productTypeName = productTypeName;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetLastPageCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetLastPageCliAction.java
new file mode 100644
index 0000000..6df6c5d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetLastPageCliAction.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+/**
+ * A {@link CmdLineAction} which gets the last page of {@link Product}s of a
+ * given {@link ProductType}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetLastPageCliAction extends FileManagerCliAction {
+
+   private String productTypeName;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(productTypeName, "Must specify productTypeName");
+
+         XmlRpcFileManagerClient client = getClient();
+
+         ProductType type = client.getProductTypeByName(productTypeName);
+         if (type == null) {
+            throw new Exception("FileManager returned null ProductType");
+         }
+         ProductPage lastPage = client.getLastPage(type);
+         if (lastPage == null) {
+            throw new Exception("FileManager returned null ProductPage");
+         }
+         printer.println("Page: [num=" + lastPage.getPageNum()
+               + ", totalPages=" + lastPage.getTotalPages() + ", pageSize="
+               + lastPage.getPageSize() + "]");
+         printer.println("Products:");
+
+         if (lastPage.getPageProducts() == null) {
+            throw new NullPointerException(
+                  "FileManager returned null page Products");
+         }
+         for (Product p : lastPage.getPageProducts()) {
+            printer.println("Product: [id=" + p.getProductId() + ",name="
+                  + p.getProductName() + ",type="
+                  + p.getProductType().getName() + ",structure="
+                  + p.getProductStructure() + ", transferStatus="
+                  + p.getTransferStatus() + "]");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get last page of "
+               + "product for ProductType name '" + productTypeName + "' : "
+               + e.getMessage(), e);
+      }
+   }
+
+   public void setProductTypeName(String productTypeName) {
+      this.productTypeName = productTypeName;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetNextPageCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetNextPageCliAction.java
new file mode 100644
index 0000000..391d283
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetNextPageCliAction.java
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+/**
+ * A {@link CmdLineAction} which gets the next page of {@link Product}s for a
+ * given {@link ProductType}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetNextPageCliAction extends FileManagerCliAction {
+
+   private String productTypeName;
+   private int currentPageNum = -1;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+
+      try {
+         Validate.notNull(productTypeName, "Must specify productTypeName");
+         Validate.isTrue(currentPageNum != -1, "Must specify currentPageNum");
+
+         XmlRpcFileManagerClient client = getClient();
+
+         ProductType type = client.getProductTypeByName(productTypeName);
+         if (type == null) {
+            throw new Exception("FileManager returned null ProductType");
+         }
+         ProductPage firstPage = client.getFirstPage(type);
+         if (firstPage == null) {
+            throw new Exception("FileManager returned null first ProductPage");
+         }
+         ProductPage currentPage = new ProductPage();
+         currentPage.setPageNum(currentPageNum);
+         currentPage.setPageSize(firstPage.getPageSize());
+         currentPage.setTotalPages(firstPage.getTotalPages());
+         ProductPage nextPage = client.getNextPage(type, currentPage);
+         if (nextPage == null) {
+            throw new Exception("FileManager returned null next ProductPage");
+         }
+         printer.println("Page: [num=" + nextPage.getPageNum()
+               + ", totalPages=" + nextPage.getTotalPages() + ", pageSize="
+               + nextPage.getPageSize() + "]");
+         printer.println("Products:");
+
+         if (nextPage.getPageProducts() == null) {
+            throw new NullPointerException(
+                  "FileManager returned null page Products");
+         }
+         for (Product p : nextPage.getPageProducts()) {
+            printer.println("Product: [id=" + p.getProductId() + ",name="
+                  + p.getProductName() + ",type="
+                  + p.getProductType().getName() + ",structure="
+                  + p.getProductStructure() + ", transferStatus="
+                  + p.getTransferStatus() + "]");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get next product page for"
+               + " ProductType name '" + productTypeName
+               + "'  and current page '" + currentPageNum + "' : "
+               + e.getMessage(), e);
+      }
+   }
+
+   public void setProductTypeName(String productTypeName) {
+      this.productTypeName = productTypeName;
+   }
+
+   public void setCurrentPageNum(int currentPageNum) {
+      this.currentPageNum = currentPageNum;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetNumProductsCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetNumProductsCliAction.java
new file mode 100644
index 0000000..9280494
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetNumProductsCliAction.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+/**
+ * A {@link CmdLineAction} which gets number of {@link Product}s of a given
+ * {@link ProuctType}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetNumProductsCliAction extends FileManagerCliAction {
+
+   private String productTypeName;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(productTypeName, "Must specify productTypeName");
+
+         XmlRpcFileManagerClient client = getClient();
+         ProductType pt = client.getProductTypeByName(productTypeName);
+         if (pt == null) {
+            throw new Exception("FileManager returned null ProductType");
+         }
+         printer.println("Type: ["
+               + productTypeName
+               + "], Num Products: ["
+               + client.getNumProducts(pt) + "]");
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get number of products for" + " ProductType name '"
+                     + productTypeName + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setProductTypeName(String productTypeName) {
+      this.productTypeName = productTypeName;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetPrevPageCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetPrevPageCliAction.java
new file mode 100644
index 0000000..030117b
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetPrevPageCliAction.java
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+/**
+ * A {@link CmdLineAction} which gets the previous page of {@link Product}s for
+ * a given {@link ProductType}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetPrevPageCliAction extends FileManagerCliAction {
+
+   private String productTypeName;
+   private int currentPageNum;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(productTypeName, "Must specify productTypeName");
+         Validate.notNull(currentPageNum, "Must specify currentPageNum");
+
+         XmlRpcFileManagerClient client = getClient();
+
+         ProductType type = client.getProductTypeByName(productTypeName);
+         if (type == null) {
+            throw new Exception("FileManager returned null ProductType");
+         }
+         ProductPage firstPage = client.getFirstPage(type);
+         if (firstPage == null) {
+            throw new Exception("FileManager returned null first ProductPage");
+         }
+         ProductPage currentPage = new ProductPage();
+         currentPage.setPageNum(currentPageNum);
+         currentPage.setPageSize(firstPage.getPageSize());
+         currentPage.setTotalPages(firstPage.getTotalPages());
+         ProductPage prevPage = client.getPrevPage(type, currentPage);
+         if (prevPage == null) {
+            throw new Exception("FileManager returned null previous ProductPage");
+         }
+         printer.println("Page: [num=" + prevPage.getPageNum()
+               + ", totalPages=" + prevPage.getTotalPages() + ", pageSize="
+               + prevPage.getPageSize() + "]");
+         printer.println("Products:");
+
+         if (prevPage.getPageProducts() == null) {
+            throw new NullPointerException(
+                  "FileManager returned null page Products");
+         }
+         for (Product p : prevPage.getPageProducts()) {
+            printer.println("Product: [id=" + p.getProductId() + ",name="
+                  + p.getProductName() + ",type="
+                  + p.getProductType().getName() + ",structure="
+                  + p.getProductStructure() + ", transferStatus="
+                  + p.getTransferStatus() + "]");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get previous page of products"
+                     + " for ProductType name '" + productTypeName
+                     + "' and current " + " page '" + currentPageNum + "' : "
+                     + e.getMessage(), e);
+      }
+   }
+
+   public void setProductTypeName(String productTypeName) {
+      this.productTypeName = productTypeName;
+   }
+
+   public void setCurrentPageNum(int currentPageNum) {
+      this.currentPageNum = currentPageNum;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetProductByIdCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetProductByIdCliAction.java
new file mode 100644
index 0000000..567b9c4
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetProductByIdCliAction.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+
+/**
+ * A {@link CmdLineAction} which gets information about a {@link Product}
+ * by ID.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class GetProductByIdCliAction extends AbstractGetProductCliAction {
+
+   private String productId;
+
+   @Override
+   public Product getProduct() throws Exception {
+      Validate.notNull(productId, "Must specify productId");
+
+      Product p = getClient().getProductById(productId);
+      if (p == null) {
+         throw new Exception("FileManager returned null product for id '"
+               + productId + "'");
+      }
+      return p;
+   }
+
+   public void setProductId(String productId) {
+      this.productId = productId;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetProductByNameCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetProductByNameCliAction.java
new file mode 100644
index 0000000..23e5715
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetProductByNameCliAction.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+
+/**
+ * A {@link CmdLineAction} which gets information about a {@link Product}
+ * by name.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class GetProductByNameCliAction extends AbstractGetProductCliAction {
+
+   private String productName;
+
+   @Override
+   public Product getProduct() throws Exception {
+      Validate.notNull(productName, "Must specify productName");
+
+      Product p = getClient().getProductByName(productName);
+      if (p == null) {
+         throw new Exception("FileManager returned null product for name '"
+               + productName + "'");
+      }
+      return p;
+   }
+
+   public void setProductName(String productName) {
+      this.productName = productName;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetProductPercentTransferredCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetProductPercentTransferredCliAction.java
new file mode 100644
index 0000000..ae91269
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetProductPercentTransferredCliAction.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+/**
+ * A {@link CmdLineAction} which get a {@link Product}'s data file transfers
+ * percent complete.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class GetProductPercentTransferredCliAction extends FileManagerCliAction {
+
+   private String productId;
+   private String productTypeName;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(productId, "Must specify productid");
+         Validate.notNull(productTypeName, "Must specify productTypeName");
+
+         XmlRpcFileManagerClient client = getClient();
+
+         Product product = new Product();
+         // TODO(bfoster): Not sure why ProductType is needed here.
+         ProductType pt = client.getProductTypeByName(productTypeName);
+         if (pt == null) {
+            throw new Exception("FileManager returned null ProductType");
+         }
+         product.setProductType(pt);
+         product.setProductId(productId);
+
+         printer.println("Product: [id=" + productId + ", transferPct="
+               + client.getProductPctTransferred(product) + "]");
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get percent transferred"
+               + " for product id '" + productId + "' and ProductType name '"
+               + productTypeName + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setProductId(String productId) {
+      this.productId = productId;
+   }
+
+   public void setProductTypeName(String productTypeName) {
+      this.productTypeName = productTypeName;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetProductTypeByNameCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetProductTypeByNameCliAction.java
new file mode 100644
index 0000000..1aa9d71
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/GetProductTypeByNameCliAction.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+
+/**
+ * A {@link CmdLineAction} which gets a {@link ProductType} by name.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetProductTypeByNameCliAction extends FileManagerCliAction {
+
+   private String productTypeName;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(productTypeName, "Must specify productTypeName");
+
+         ProductType type = getClient().getProductTypeByName(productTypeName);
+         if (type == null) {
+            throw new Exception("FileManager returned null ProductType");
+         }
+         printer.println("getProductTypeByName: Result: [name="
+               + type.getName() + ", description=" + type.getDescription()
+               + ", id=" + type.getProductTypeId() + ", versionerClass="
+               + type.getVersioner() + ", repositoryPath="
+               + type.getProductRepositoryPath() + "]");
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get product type by name '" + productTypeName
+                     + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setProductTypeName(String productTypeName) {
+      this.productTypeName = productTypeName;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/HasProductCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/HasProductCliAction.java
new file mode 100644
index 0000000..3445325
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/HasProductCliAction.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+
+/**
+ * A {@link CmdLineAction} which checks if the File Manager has a given
+ * {@link Product} ingested.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class HasProductCliAction extends FileManagerCliAction {
+
+   private String productName;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(productName, "Must specify productName");
+
+         printer.println("hasProduct: Result: "
+               + getClient().hasProduct(productName));
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to check for product '"
+               + productName + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setProductName(String productName) {
+      this.productName = productName;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/IngestProductCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/IngestProductCliAction.java
new file mode 100644
index 0000000..6f6bf9f
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/IngestProductCliAction.java
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//OODT static imports
+import static org.apache.oodt.cas.filemgr.structs.Product.STRUCTURE_HIERARCHICAL;
+import static org.apache.oodt.cas.filemgr.structs.Product.STRUCTURE_STREAM;
+import static org.apache.oodt.cas.filemgr.util.GenericFileManagerObjectFactory.getDataTransferServiceFromFactory;
+import static org.apache.oodt.cas.filemgr.versioning.VersioningUtils.addRefsFromUris;
+import static org.apache.oodt.cas.filemgr.versioning.VersioningUtils.getURIsFromDir;
+
+//JDK imports
+import java.io.File;
+import java.net.URI;
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * A {@link CmdLineAction} which ingests a {@link Product}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class IngestProductCliAction extends FileManagerCliAction {
+
+   private String productName;
+   private String productStructure;
+   private String productTypeName;
+   private String metadataFile;
+   private String dataTransferer;
+   private List<String> references;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(productName, "Must specify productName");
+         Validate.notNull(productStructure, "Must specify productStructure");
+         Validate.notNull(productTypeName, "Must specify productTypeName");
+         Validate.notNull(metadataFile, "Must specify metadataFile");
+         Validate.notNull(references, "Must specify references");
+
+         XmlRpcFileManagerClient client = getClient();
+
+         ProductType pt = client.getProductTypeByName(productTypeName);
+         if (pt == null) {
+            throw new Exception("FileManager returned null ProductType");
+         }
+
+         Product product = new Product();
+         product.setProductName(productName);
+         product.setProductStructure(productStructure);
+         product.setProductType(pt);
+
+         if (dataTransferer != null) {
+            client.setDataTransfer(getDataTransferServiceFromFactory(dataTransferer));
+         }
+
+         // need to build up the ref uri list in case the Product structure
+         // is heirarchical
+         if (product.getProductStructure().equals(STRUCTURE_HIERARCHICAL)) {
+            List<String> uriRefs = Lists.newArrayList();
+            URI hierRefUri = getUri(references.get(0));
+            uriRefs.add(hierRefUri.toString());
+            uriRefs.addAll(getURIsFromDir(new File(hierRefUri.getPath())));
+            references = uriRefs;
+         } else if (product.getProductStructure().equals(STRUCTURE_STREAM)) {
+            List<String> uriRefs = Lists.newArrayList();
+            for (String ref : references) {
+               URI uri = URI.create(ref);
+               if (!uri.getScheme().equals("stream"))
+                  throw new IllegalArgumentException("Streaming data must use 'stream' scheme not "+uri.getScheme());
+               uriRefs.add(uri.toString());
+            }
+            references = uriRefs;
+         } else {
+            List<String> uriRefs = Lists.newArrayList();
+            for (String reference : references) {
+               uriRefs.add(getUri(reference).toString());
+            }
+            references = uriRefs;
+         }
+
+         // add Product References from the URI list
+         addRefsFromUris(product, references);
+
+         printer.println("ingestProduct: Result: "
+               + client.ingestProduct(product,
+                     new SerializableMetadata(getUri(metadataFile).toURL()
+                           .openStream()), dataTransferer != null));
+      } catch (Exception e) {
+         e.printStackTrace();
+         throw new CmdLineActionException("Failed to ingest product '"
+               + productName + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setProductName(String productName) {
+      this.productName = productName;
+   }
+
+   public void setProductStructure(String productStructure) {
+      this.productStructure = productStructure;
+   }
+
+   public void setProductTypeName(String productTypeName) {
+      this.productTypeName = productTypeName;
+   }
+
+   public void setMetadataFile(String metadataFile) {
+      this.metadataFile = metadataFile;
+   }
+
+   public void setDataTransferer(String dataTransferer) {
+      this.dataTransferer = dataTransferer;
+   }
+
+   public void setReferences(List<String> references) {
+      this.references = references;
+   }
+
+   private URI getUri(String filePath) {
+      if (new File(filePath).exists()) {
+         return new File(filePath).getAbsoluteFile().toURI();
+      } else {
+         return URI.create(filePath);
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/LuceneQueryCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/LuceneQueryCliAction.java
new file mode 100644
index 0000000..cf1f1b7
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/LuceneQueryCliAction.java
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.PhraseQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.RangeQuery;
+import org.apache.lucene.search.TermQuery;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.BooleanQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.QueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.query.ComplexQuery;
+import org.apache.oodt.cas.filemgr.tools.CASAnalyzer;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * A {@link CmdLineAction} which converts a Lucene-like query into a File
+ * Manager {@link Query} and returns the results.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class LuceneQueryCliAction extends AbstractQueryCliAction {
+
+   private static final String FREE_TEXT_BLOCK = "__FREE__";
+
+   private String query;
+   private List<String> reducedProductTypes;
+   private List<String> reducedMetadataKeys;
+
+   public LuceneQueryCliAction() {
+      super();
+   }
+
+   @Override
+   public ComplexQuery getQuery() throws Exception {
+      Validate.notNull(query, "Must specify query");
+
+      ComplexQuery complexQuery = new ComplexQuery();
+      complexQuery.setCriteria(Lists.newArrayList(generateCASQuery(parseQuery(query))));
+      complexQuery.setReducedProductTypeNames(reducedProductTypes);
+      complexQuery.setReducedMetadata(reducedMetadataKeys);
+      return complexQuery;
+   }
+
+   public void setQuery(String query) {
+      this.query = query;
+   }
+
+   public void setReducedProductTypes(List<String> reducedProductTypes) {
+      this.reducedProductTypes = reducedProductTypes;
+   }
+
+   public void setReducedMetadataKeys(List<String> reducedMetadataKeys) {
+      this.reducedMetadataKeys = reducedMetadataKeys;
+   }
+
+   private Query parseQuery(String query) throws ParseException {
+      // note that "__FREE__" is a control work for free text searching
+      return (Query) new QueryParser(FREE_TEXT_BLOCK, new CASAnalyzer())
+            .parse(query);
+   }
+
+   private QueryCriteria generateCASQuery(Query luceneQuery)
+         throws Exception {
+      if (luceneQuery instanceof TermQuery) {
+         Term t = ((TermQuery) luceneQuery).getTerm();
+         if (t.field().equals(FREE_TEXT_BLOCK)) {
+            throw new Exception("Free text blocks not supported!");
+         } else {
+            return new TermQueryCriteria(t.field(), t.text());
+         }
+      } else if (luceneQuery instanceof PhraseQuery) {
+         Term[] t = ((PhraseQuery) luceneQuery).getTerms();
+         if (t[0].field().equals(FREE_TEXT_BLOCK)) {
+            throw new Exception("Free text blocks not supported!");
+         } else {
+            BooleanQueryCriteria bqc = new BooleanQueryCriteria();
+            bqc.setOperator(BooleanQueryCriteria.AND);
+            for (int i = 0; i < t.length; i++) {
+               bqc.addTerm(new TermQueryCriteria(t[i].field(), t[i]
+                     .text()));
+            }
+            return bqc;
+         }
+      } else if (luceneQuery instanceof RangeQuery) {
+         Term startT = ((RangeQuery) luceneQuery).getLowerTerm();
+         Term endT = ((RangeQuery) luceneQuery).getUpperTerm();
+         return new RangeQueryCriteria(startT.field(), startT
+               .text(), endT.text(), ((RangeQuery) luceneQuery).isInclusive());
+      } else if (luceneQuery instanceof BooleanQuery) {
+         BooleanClause[] clauses = ((BooleanQuery) luceneQuery).getClauses();
+         BooleanQueryCriteria bqc = new BooleanQueryCriteria();
+         bqc.setOperator(BooleanQueryCriteria.AND);
+         for (int i = 0; i < clauses.length; i++) {
+            if (clauses[i].getOccur().equals(BooleanClause.Occur.SHOULD)) {
+               bqc.setOperator(BooleanQueryCriteria.OR);
+            }
+            bqc.addTerm(generateCASQuery(clauses[i].getQuery()));
+         }
+         return bqc;
+      } else {
+         throw new Exception(
+               "Error parsing query! Cannot determine clause type: ["
+                     + luceneQuery.getClass().getName() + "] !");
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/RetrieveFilesCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/RetrieveFilesCliAction.java
new file mode 100644
index 0000000..187ef90
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/RetrieveFilesCliAction.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.datatransfer.DataTransfer;
+import org.apache.oodt.cas.filemgr.datatransfer.DataTransferFactory;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+/**
+ * Retrieves files for a given {@link Product}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class RetrieveFilesCliAction extends FileManagerCliAction {
+
+   private String productId;
+   private String productName;
+   private DataTransfer dt;
+   private File destination;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         XmlRpcFileManagerClient fmClient = getClient();
+         dt.setFileManagerUrl(fmClient.getFileManagerUrl());
+         Product product = null;
+         if (productId != null) {
+            product = fmClient.getProductById(productId);
+         } else if (productName != null) {
+            product = fmClient.getProductByName(productName);
+         } else {
+              throw new Exception("Must specify either productId or productName");
+         }
+         if (product != null) {
+            product.setProductReferences(fmClient.getProductReferences(product));
+            dt.retrieveProduct(product, destination);
+         } else {
+            throw new Exception("Product was not found");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to retrieve files for product : " + e.getMessage(), e);
+      }
+   }
+
+   public void setProductId(String productId) {
+      this.productId = productId;
+   }
+
+   public void setProductName(String productName) {
+      this.productName = productName;
+   }
+
+   public void setDataTransferFactory(DataTransferFactory dtFactory) {
+      dt = dtFactory.createDataTransfer();
+   }
+
+   public void setDestination(File destination) {
+      this.destination = destination;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/SqlQueryCliAction.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/SqlQueryCliAction.java
new file mode 100644
index 0000000..280603f
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/cli/action/SqlQueryCliAction.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.query.ComplexQuery;
+import org.apache.oodt.cas.filemgr.util.SqlParser;
+
+/**
+ * A {@link CmdLineAction} which queries the FileManager by parsing an SQL like
+ * query into a FileManager {@link Query}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class SqlQueryCliAction extends AbstractQueryCliAction {
+
+   private String query;
+
+   public SqlQueryCliAction() {
+      super();
+   }
+
+   @Override
+   public ComplexQuery getQuery() throws Exception {
+      Validate.notNull(query, "Must specify query");
+
+      return SqlParser.parseSqlQuery(query);
+   }
+
+   public void setQuery(String query) {
+      this.query = query;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/DataTransfer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/DataTransfer.java
new file mode 100644
index 0000000..b4708e2
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/DataTransfer.java
@@ -0,0 +1,77 @@
+/*

+ * 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.

+ */

+

+package org.apache.oodt.cas.filemgr.datatransfer;

+

+//OODT imports

+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;

+import org.apache.oodt.cas.filemgr.structs.Product;

+

+//JDK imports

+import java.io.File;

+import java.io.IOException;

+import java.net.URL;

+

+/**

+ * @author mattmann

+ * @version $Revision$

+ * 

+ * <p>

+ * Objects implementing this interface define how to transfer products to the

+ * {@link DataStore} repository.

+ * </p>

+ * 

+ */

+public interface DataTransfer {

+	/* extension point ID */

+	public static final String X_POINT_ID = DataTransfer.class.getName();

+	

+	/**

+	 * 

+	 * @param url The URL to the File Manager that this transferer will be

+	 * transferring Products to.

+	 */

+	public void setFileManagerUrl(URL url);

+	

+	/**

+	 * 

+	 * @param product

+	 *            The product that is being transferred. The product should have

+	 *            both its origFileLocation, as well as its dataStoreRefs filled

+	 *            in to perform the transfer.

+	 * @throws DataTransferException

+	 *             If a general error occurs during the transfer.

+	 * @throws IOException

+	 *             If there is an IO eerror when performing the transfer.

+	 */

+	public void transferProduct(Product product) throws DataTransferException,

+			IOException;

+

+	  /**

+    * Requires that the data store reference be set, nothing else is used

+    * @param product The product whose data store reference will be copied

+    * @param directory The directory where the data store reference will be copied to

+    * @throws DataTransferException

+    *             If a general error occurs during the transfer.

+    * @throws IOException

+    *             If there is an IO eerror when performing the transfer.

+    */

+   public void retrieveProduct(Product product, File directory) throws DataTransferException,

+         IOException;

+   

+   public void deleteProduct(Product product) throws DataTransferException, IOException;

+}

diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/DataTransferFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/DataTransferFactory.java
new file mode 100644
index 0000000..0f09d1b
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/DataTransferFactory.java
@@ -0,0 +1,33 @@
+/*

+ * 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.

+ */

+

+package org.apache.oodt.cas.filemgr.datatransfer;

+

+/**

+ * @author mattmann

+ * @version $Revision$

+ * 

+ * <p>A Factory for creating {@link DataTransfer} implementation objects.</p>

+ * 

+ */

+public interface DataTransferFactory {

+

+    /**

+     * @return A new {@link DataTransfer} implementation.

+     */

+    public DataTransfer createDataTransfer();

+}

diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/InPlaceDataTransferFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/InPlaceDataTransferFactory.java
new file mode 100644
index 0000000..944f931
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/InPlaceDataTransferFactory.java
@@ -0,0 +1,43 @@
+/*

+ * 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.

+ */

+

+package org.apache.oodt.cas.filemgr.datatransfer;

+

+/**

+ * @author woollard

+ * @version $Revision$

+ * 

+ * <p>Creates new {@link InPlaceDataTransferer}s.</p>

+ * 

+ */

+public class InPlaceDataTransferFactory implements DataTransferFactory {

+

+    /**

+     * <p>Default Constructor</p>

+     */

+    public InPlaceDataTransferFactory() {

+        super();

+    }

+

+    /* (non-Javadoc)

+     * @see org.apache.oodt.cas.datatransfer.DataTransferFactory#createDataTransfer()

+     */

+    public DataTransfer createDataTransfer() {

+        return new InPlaceDataTransferer();

+    }

+

+}

diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/InPlaceDataTransferer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/InPlaceDataTransferer.java
new file mode 100644
index 0000000..f67a239
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/InPlaceDataTransferer.java
@@ -0,0 +1,72 @@
+/*

+ * 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.

+ */

+package org.apache.oodt.cas.filemgr.datatransfer;

+

+//OODT imports

+import org.apache.oodt.cas.filemgr.structs.Product;

+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;

+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;

+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;

+

+//JDK imports

+import java.io.File;

+import java.io.IOException;

+import java.util.logging.Logger;

+import java.util.logging.Level;

+import java.net.URL;

+

+/** 

+ * An implementation of the {@link DataTransfer} interface that leaves

+ * products in the same place (i.e., "in place") and doesn't transfer

+ * them at all.

+ *

+ * @author mattmann@apache.org (Chris Mattmann)

+ */

+public class InPlaceDataTransferer implements DataTransfer {

+

+  private static final Logger LOG = Logger.getLogger(InPlaceDataTransferer.class.getName());

+

+  private XmlRpcFileManagerClient client = null;

+

+  public InPlaceDataTransferer() {}

+

+  public void setFileManagerUrl(URL url) {

+    try {

+      client = new XmlRpcFileManagerClient(url);

+      LOG.log(Level.INFO, "In Place Data Transfer to: [" + client.getFileManagerUrl().toString()

+          + "] enabled");

+    } catch (ConnectionException e) {

+      LOG.log(Level.WARNING, "Connection exception for filemgr: [" + url + "]");

+    }

+  }

+

+  @Override

+  public void transferProduct(Product product) throws DataTransferException, IOException {

+    // do nothing

+  }

+

+  @Override

+  public void retrieveProduct(Product product, File directory) throws DataTransferException,

+      IOException {

+    // do nothing

+  }

+

+  @Override

+  public void deleteProduct(Product product) throws DataTransferException, IOException {

+    // do nothing

+  }

+}

diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/LocalDataTransferFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/LocalDataTransferFactory.java
new file mode 100644
index 0000000..0504293
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/LocalDataTransferFactory.java
@@ -0,0 +1,43 @@
+/*

+ * 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.

+ */

+

+package org.apache.oodt.cas.filemgr.datatransfer;

+

+/**

+ * @author mattmann

+ * @version $Revision$

+ * 

+ * <p>Creates new {@link LocalDataTransferer}s.</p>

+ * 

+ */

+public class LocalDataTransferFactory implements DataTransferFactory {

+

+    /**

+     * <p>Default Constructor</p>

+     */

+    public LocalDataTransferFactory() {

+        super();

+    }

+

+    /* (non-Javadoc)

+     * @see org.apache.oodt.cas.datatransfer.DataTransferFactory#createDataTransfer()

+     */

+    public DataTransfer createDataTransfer() {

+        return new LocalDataTransferer();

+    }

+

+}

diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/LocalDataTransferer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/LocalDataTransferer.java
new file mode 100644
index 0000000..a385e91
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/LocalDataTransferer.java
@@ -0,0 +1,445 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.datatransfer;
+
+//APACHE Imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.versioning.VersioningUtils;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.tika.mime.MimeTypeException;
+import org.apache.tika.mime.MimeTypes;
+import org.apache.tika.mime.MimeTypesFactory;
+
+//JDK imports
+import java.io.IOException;
+import java.io.File;
+import java.util.List;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.net.URISyntaxException;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ *          <p>
+ *          An implementation of the {@link DataTransfer} interface that moves
+ *          products that are available via URIs on the same machine, through an
+ *          NFS mounted disk, or via the locally mounted file repository.
+ *          </p>
+ * 
+ */
+public class LocalDataTransferer implements DataTransfer {
+
+   /* our log stream */
+   private static final Logger LOG = Logger.getLogger(LocalDataTransferer.class
+         .getName());
+
+   /* file manager client */
+   private XmlRpcFileManagerClient client = null;
+
+   /**
+    * <p>
+    * Default Constructor
+    * </p>
+    */
+   public LocalDataTransferer() {
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see
+    * org.apache.oodt.cas.filemgr.datatransfer.DataTransfer#setFileManagerUrl
+    * (java.net.URL)
+    */
+   public void setFileManagerUrl(URL url) {
+      try {
+         client = new XmlRpcFileManagerClient(url);
+         LOG.log(Level.INFO, "Local Data Transfer to: ["
+               + client.getFileManagerUrl().toString() + "] enabled");
+      } catch (ConnectionException e) {
+         e.printStackTrace();
+      }
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see
+    * org.apache.oodt.cas.datatransfer.DataTransfer#transferProduct(org.apache
+    * .oodt.cas.data.structs.Product)
+    */
+   public void transferProduct(Product product) throws DataTransferException,
+         IOException {
+      // check whether or not it's a set of files, or it's actually a dir
+      // structure
+      if (product.getProductStructure().equals(Product.STRUCTURE_HIERARCHICAL)) {
+         try {
+            moveDirToProductRepo(product);
+         } catch (URISyntaxException e) {
+            LOG.log(
+                  Level.WARNING,
+                  "URI Syntax Exception when moving dir "
+                        + ((Reference) product.getProductReferences().get(0))
+                              .getOrigReference() + ": Message: "
+                        + e.getMessage());
+            throw new DataTransferException(e);
+         }
+      } else if (product.getProductStructure().equals(Product.STRUCTURE_FLAT)) {
+         try {
+            moveFilesToProductRepo(product);
+         } catch (URISyntaxException e) {
+            LOG.log(
+                  Level.WARNING,
+                  "URI Syntax Exception when moving files: Message: "
+                        + e.getMessage());
+            throw new DataTransferException(e);
+         }
+      } else if (product.getProductStructure().equals(Product.STRUCTURE_STREAM)) {
+            LOG.log(Level.INFO,"Streaming products are not moved.");
+      } else {
+         throw new DataTransferException(
+               "Cannot transfer product on unknown ProductStructure: "
+                     + product.getProductStructure());
+      }
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see
+    * org.apache.oodt.cas.filemgr.datatransfer.DataTransfer#retrieveProduct(org.
+    * apache.oodt.cas.filemgr.structs.Product, java.io.File)
+    */
+   public void retrieveProduct(Product product, File directory)
+         throws DataTransferException, IOException {
+      // check whether or not it's a set of files, or it's actually a dir
+      // structure
+      if (product.getProductStructure().equals(Product.STRUCTURE_HIERARCHICAL)) {
+         try {
+            copyDirToDir(product, directory);
+         } catch (URISyntaxException e) {
+            LOG.log(
+                  Level.WARNING,
+                  "URI Syntax Exception when moving dir "
+                        + ((Reference) product.getProductReferences().get(0))
+                              .getDataStoreReference() + ": Message: "
+                        + e.getMessage());
+            throw new DataTransferException(e);
+         }
+      } else if (product.getProductStructure().equals(Product.STRUCTURE_FLAT)) {
+         try {
+            copyFilesToDir(product, directory);
+         } catch (URISyntaxException e) {
+            LOG.log(
+                  Level.WARNING,
+                  "URI Syntax Exception when moving files: Message: "
+                        + e.getMessage());
+            throw new DataTransferException(e);
+         }
+      } else if (product.getProductStructure().equals(Product.STRUCTURE_STREAM)) {
+         LOG.log(Level.INFO,"Streaming products are not transfered.");
+      } else {
+         throw new DataTransferException(
+               "Cannot transfer product on unknown ProductStructure: "
+                     + product.getProductStructure());
+      }
+   }
+
+   @Override
+   public void deleteProduct(Product product) throws DataTransferException, IOException {
+     for (Reference ref : product.getProductReferences()) {
+       File dataFile = new File(URI.create(ref.getDataStoreReference()).toURL().getPath());
+       if (!dataFile.delete()) {
+        throw new IOException(String.format("Failed to delete file %s - delete returned false",
+            dataFile));
+       }
+     }
+   }
+   
+   /**
+    * @param args
+    */
+   public static void main(String[] args) throws DataTransferException,
+         IOException, URISyntaxException {
+      String usage = "LocalFileTransfer --productName <name> --productRepo <repo> [--dir <dirRef>] [--files <origRef 1>...<origRef N>]\n";
+
+      MimeTypes mimeTypeRepo;
+      try {
+         mimeTypeRepo = MimeTypesFactory
+               .create(System
+                     .getProperty("org.apache.oodt.cas.filemgr.mime.type.repository"));
+      } catch (MimeTypeException e) {
+         e.printStackTrace();
+         throw new IOException(e.getMessage());
+      }
+
+      String productName = null;
+      String productRepo = null;
+      String transferType = null;
+      Reference dirReference = null;
+
+      List<Reference> fileReferences = null;
+
+      for (int i = 0; i < args.length; i++) {
+         if (args[i].equals("--dir")) {
+            transferType = "dir";
+            dirReference = new Reference();
+            dirReference.setOrigReference(new File(new URI(args[++i])).toURI()
+                  .toString());
+            LOG.log(Level.FINER,
+                  "LocalFileTransfer.main: Generated orig reference: "
+                        + dirReference.getOrigReference());
+         } else if (args[i].equals("--files")) {
+            transferType = "files";
+            fileReferences = new Vector<Reference>();
+            for (int j = i + 1; j < args.length; j++) {
+               LOG.log(Level.FINER, "LocalFileTransfer.main: Adding file ref: "
+                     + args[j]);
+               fileReferences.add(new Reference(args[j], null,
+                     new File(args[j]).length(), mimeTypeRepo
+                           .getMimeType(args[j])));
+            }
+         } else if (args[i].equals("--productName")) {
+            productName = args[++i];
+         } else if (args[i].equals("--productRepo")) {
+            productRepo = args[++i];
+         }
+      }
+
+      if (transferType == null
+            || (transferType != null && ((transferType.equals("dir") && dirReference == null)
+                  || (transferType.equals("files") && fileReferences == null)
+                  || (transferType != null && !(transferType.equals("dir") || transferType
+                        .equals("files"))) || productName == null || productRepo == null))) {
+         System.err.println(usage);
+         System.exit(1);
+      }
+
+      // construct a new Product
+      Product p = new Product();
+      p.setProductName(productName);
+
+      if (transferType.equals("dir")) {
+         p.setProductStructure(Product.STRUCTURE_HIERARCHICAL);
+         dirReference.setDataStoreReference(new File(new URI(productRepo))
+               .toURI().toURL().toExternalForm()
+               + URLEncoder.encode(p.getProductName(), "UTF-8") + "/");
+         p.getProductReferences().add(dirReference);
+         /* we'll do a simple versioning scheme ourselves: no versioning! */
+         p.getProductReferences().addAll(
+               VersioningUtils.getReferencesFromDir(new File(new URI(
+                     dirReference.getOrigReference()))));
+         VersioningUtils.createBasicDataStoreRefsHierarchical(p
+               .getProductReferences());
+      } else if (transferType.equals("files")) {
+         p.setProductStructure("Flat");
+         p.getProductReferences().addAll(fileReferences);
+         VersioningUtils.createBasicDataStoreRefsFlat(productName, productRepo,
+               p.getProductReferences());
+      }
+
+      DataTransfer transfer = new LocalDataTransferer();
+      transfer.transferProduct(p);
+
+   }
+
+   private void copyDirToDir(Product product, File directory)
+         throws IOException, URISyntaxException {
+      Reference dirRef = (Reference) product.getProductReferences().get(0);
+      LOG.log(
+            Level.INFO,
+            "LocalDataTransferer: Staging Directory: "
+                  + dirRef.getDataStoreReference() + " into directory "
+                  + directory.getAbsolutePath());
+
+      for (Iterator<Reference> i = product.getProductReferences().iterator(); i
+            .hasNext();) {
+         Reference r = i.next();
+         File fileRef = new File(new URI(r.getDataStoreReference()));
+
+         if (fileRef.isFile()) {
+            copyFile(r, directory);
+         } else if (fileRef.isDirectory()
+               && (fileRef.list() != null && fileRef.list().length == 0)) {
+            // if it's a directory and it doesn't exist yet, we should
+            // create it
+             // just in case there's no files in it
+             File dest = new File(directory, fileRef.getName());
+             if (!new File(new URI(dest.getAbsolutePath())).exists()) {
+                 LOG.log(Level.FINER, "Directory: [" + dest.getAbsolutePath()
+                         + "] doesn't exist: creating it");
+                 try {
+                     FileUtils.forceMkdir(new File(new URI(dest.getAbsolutePath())));
+                 }
+                 catch(IOException e){
+                     LOG.log(
+                             Level.WARNING,
+                             "Unable to create directory: ["
+                                     + dest.getAbsolutePath()
+                                     + "] in local data transferer");
+
+                 }
+             }
+         }
+      }
+   }
+
+   private void moveDirToProductRepo(Product product) throws IOException,
+         URISyntaxException {
+      Reference dirRef = (Reference) product.getProductReferences().get(0);
+      LOG.log(
+            Level.INFO,
+            "LocalDataTransferer: Moving Directory: "
+                  + dirRef.getOrigReference() + " to "
+                  + dirRef.getDataStoreReference());
+
+      // notify the file manager that we started
+      quietNotifyTransferProduct(product);
+
+      for (Iterator<Reference> i = product.getProductReferences().iterator(); i
+            .hasNext();) {
+         Reference r = i.next();
+         File fileRef = new File(new URI(r.getOrigReference()));
+
+         if (fileRef.isFile()) {
+            moveFile(r, false);
+         } else if (fileRef.isDirectory()
+               && (fileRef.list() != null && fileRef.list().length == 0)) {
+            // if it's a directory and it doesn't exist yet, we should
+            // create it
+            // just in case there's no files in it
+             if (!new File(new URI(r.getDataStoreReference())).exists()) {
+                 LOG.log(Level.FINER, "Directory: [" + r.getDataStoreReference()
+                         + "] doesn't exist: creating it");
+                 try {
+                     FileUtils.forceMkdir(new File(new URI(r.getDataStoreReference())));
+                 }
+                 catch(IOException e){
+                     LOG.log(
+                             Level.WARNING,
+                             "Unable to create directory: ["
+                                     + r.getDataStoreReference()
+                                     + "] in local data transferer");
+                 }
+             }
+         }
+      }
+
+      // notify the file manager that we're done
+      quietNotifyProductTransferComplete(product);
+
+   }
+
+   private void moveFilesToProductRepo(Product product) throws IOException,
+         URISyntaxException {
+      List<Reference> refs = product.getProductReferences();
+
+      // notify the file manager that we started
+      quietNotifyTransferProduct(product);
+
+      for (Iterator<Reference> i = refs.iterator(); i.hasNext();) {
+         Reference r = (Reference) i.next();
+         moveFile(r, true);
+      }
+
+      // notify the file manager that we're done
+      quietNotifyProductTransferComplete(product);
+   }
+
+   private void copyFilesToDir(Product product, File directory)
+         throws IOException, URISyntaxException {
+      List<Reference> refs = product.getProductReferences();
+      for (Iterator<Reference> i = refs.iterator(); i.hasNext();) {
+         Reference r = (Reference) i.next();
+         copyFile(r, directory);
+      }
+   }
+
+   private void moveFile(Reference r, boolean log) throws IOException,
+         URISyntaxException {
+      if (log) {
+         LOG.log(Level.INFO,
+               "LocalDataTransfer: Moving File: " + r.getOrigReference()
+                     + " to " + r.getDataStoreReference());
+      }
+      File srcFileRef = new File(new URI(r.getOrigReference()));
+      File destFileRef = new File(new URI(r.getDataStoreReference()));
+
+      FileUtils.copyFile(srcFileRef, destFileRef);
+   }
+
+   private void copyFile(Reference r, File directory) throws IOException,
+         URISyntaxException {
+      File srcFileRef = new File(new URI(r.getDataStoreReference()));
+      LOG.log(Level.INFO,
+            "LocalDataTransfer: Copying File: " + r.getDataStoreReference()
+                  + " to file:" + directory.getAbsolutePath() + "/"
+                  + srcFileRef.getName());
+      FileUtils.copyFile(srcFileRef, new File(directory, srcFileRef.getName()));
+   }
+
+   private void quietNotifyTransferProduct(Product p) {
+      if (client == null) {
+         LOG.log(Level.WARNING,
+               "File Manager service not defined: this transfer will not be tracked");
+         return;
+      }
+
+      try {
+         client.transferringProduct(p);
+      } catch (DataTransferException e) {
+         e.printStackTrace();
+         LOG.log(Level.WARNING,
+               "Error notifying file manager of product transfer initiation for product: ["
+                     + p.getProductId() + "]: Message: " + e.getMessage());
+         return;
+      }
+   }
+
+   private void quietNotifyProductTransferComplete(Product p) {
+      if (client == null) {
+         LOG.log(Level.WARNING,
+               "File Manager service not defined: this transfer will not be tracked");
+         return;
+      }
+
+      try {
+         client.removeProductTransferStatus(p);
+      } catch (DataTransferException e) {
+         e.printStackTrace();
+         LOG.log(Level.WARNING,
+               "Error notifying file manager of product transfer completion for product: ["
+                     + p.getProductId() + "]: Message: " + e.getMessage());
+         return;
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/RemoteDataTransferFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/RemoteDataTransferFactory.java
new file mode 100644
index 0000000..7b4e95a
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/RemoteDataTransferFactory.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.datatransfer;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory for constructing {@link RemoteDataTransferer} objects.
+ * </p>
+ * 
+ */
+public class RemoteDataTransferFactory implements DataTransferFactory {
+
+    /* the chunk size for sending files remotely */
+    private int chunkSize = 0;
+
+    /* our log stream */
+    private static final Logger LOG = Logger
+            .getLogger(RemoteDataTransferFactory.class.getName());
+
+    /**
+     * 
+     */
+    public RemoteDataTransferFactory() throws InstantiationException {
+        chunkSize = Integer.getInteger(
+                "org.apache.oodt.cas.filemgr.datatransfer.remote.chunkSize",
+                1024).intValue();
+
+        LOG.log(Level.INFO, "RemoteDataTransfer enabled: using chunk size: ["
+                + chunkSize + "]");
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.datatransfer.DataTransferFactory#createDataTransfer()
+     */
+    public DataTransfer createDataTransfer() {
+        return new RemoteDataTransferer(chunkSize);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/RemoteDataTransferer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/RemoteDataTransferer.java
new file mode 100644
index 0000000..57a1d19
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/RemoteDataTransferer.java
@@ -0,0 +1,288 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.datatransfer;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ *          <p>
+ *          An implementation of the {@link DataTransfer} interface that
+ *          transfers files to a remote file manager over XML-RPC, using the
+ *          File Manager Client.
+ *          </p>
+ * 
+ */
+public class RemoteDataTransferer implements DataTransfer {
+
+   /*
+    * the url pointer to the file manager that we'll remotely transfer the file
+    * to
+    */
+   private URL fileManagerUrl = null;
+
+   /*
+    * the size of the chunks that files should be transferred over XML-RPC using
+    */
+   private int chunkSize = 1024;
+
+   /* our file manager client */
+   private XmlRpcFileManagerClient client = null;
+
+   /* our log stream */
+   private static final Logger LOG = Logger
+         .getLogger(RemoteDataTransferer.class.getName());
+
+   /**
+     * 
+     */
+   public RemoteDataTransferer(int chunkSz) {
+      this.chunkSize = chunkSz;
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see
+    * org.apache.oodt.cas.filemgr.datatransfer.DataTransfer#setFileManagerUrl
+    * (java.net.URL)
+    */
+   public void setFileManagerUrl(URL url) {
+      try {
+         client = new XmlRpcFileManagerClient(url);
+         this.fileManagerUrl = url;
+         LOG.log(Level.INFO, "Remote Data Transfer to: ["
+               + client.getFileManagerUrl().toString() + "] enabled");
+      } catch (ConnectionException e) {
+         LOG.log(Level.WARNING, "Connection exception for filemgr: [" + url
+               + "]");
+      }
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see
+    * org.apache.oodt.cas.filemgr.datatransfer.DataTransfer#transferProduct(
+    * org.apache.oodt.cas.filemgr.structs.Product)
+    */
+   public void transferProduct(Product product) throws DataTransferException,
+         IOException {
+
+      if (fileManagerUrl == null) {
+         throw new DataTransferException(
+               "No file manager url specified for remote data transfer: cannot transfer product: ["
+                     + product.getProductName() + "]!");
+      }
+
+      quietNotifyTransferProduct(product);
+
+      // for each file reference, transfer the file to the remote file manager
+      for (Iterator<Reference> i = product.getProductReferences().iterator(); i
+            .hasNext();) {
+         Reference r = i.next();
+         // test whether or not the reference is a directory or a file
+         File refFile = null;
+         try {
+            refFile = new File(new URI(r.getOrigReference()));
+         } catch (URISyntaxException e) {
+            LOG.log(Level.WARNING,
+                  "Unable to test if reference: [" + r.getOrigReference()
+                        + "] is a directory: skipping it");
+            continue;
+         }
+
+         if (!refFile.isDirectory()) {
+            LOG.log(Level.FINE, "Reference: [" + r.getOrigReference()
+                  + "] is file: transferring it");
+
+            try {
+               remoteTransfer(r, product);
+            } catch (URISyntaxException e) {
+               LOG.log(Level.WARNING,
+                     "Error transferring file: [" + r.getOrigReference()
+                           + "]: URISyntaxException: " + e.getMessage());
+            }
+         } else {
+            LOG.log(
+                  Level.FINE,
+                  "RemoteTransfer: skipping reference: ["
+                        + refFile.getAbsolutePath() + "] of product: ["
+                        + product.getProductName() + "]: ref is a directory");
+         }
+      }
+
+      quietNotifyProductTransferComplete(product);
+
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see
+    * org.apache.oodt.cas.filemgr.datatransfer.DataTransfer#retrieveProduct(org.
+    * apache.oodt.cas.filemgr.structs.Product, java.io.File)
+    */
+   public void retrieveProduct(Product product, File directory)
+         throws DataTransferException, IOException {
+      for (Reference reference : product.getProductReferences()) {
+         FileOutputStream fOut = null;
+         try {
+            File dataStoreFile = new File(new URI(
+                  reference.getDataStoreReference()));
+            File dest = new File(directory, dataStoreFile.getName());
+            fOut = new FileOutputStream(dest, false);
+            LOG.log(
+                  Level.INFO,
+                  "RemoteDataTransfer: Copying File: " + "fmp:"
+                        + dataStoreFile.getAbsolutePath() + " to " + "file:"
+                        + dest.getAbsolutePath());
+            byte[] fileData = null;
+            int offset = 0;
+            while (true) {
+               fileData = (byte[]) client.retrieveFile(
+                     dataStoreFile.getAbsolutePath(), offset, 1024);
+               if (fileData.length <= 0)
+                  break;
+               fOut.write(fileData);
+               if (fileData.length < 1024)
+                  break;
+               offset += 1024;
+            }
+         } catch (Exception e) {
+            throw new DataTransferException("", e);
+         } finally {
+            try {
+               fOut.close();
+            } catch (Exception e) {
+            }
+         }
+      }
+   }
+
+   @Override
+   public void deleteProduct(Product product) throws DataTransferException, IOException {
+     for (Reference ref : product.getProductReferences()) {
+       File dataFile = new File(URI.create(ref.getDataStoreReference()).toURL().getPath());
+       if (!dataFile.delete()) {
+        throw new IOException(String.format("Failed to delete file %s - delete returned false",
+            dataFile));
+       }
+     }
+   }
+   
+   private void remoteTransfer(Reference reference, Product product)
+         throws URISyntaxException {
+      // get the file path
+      File origFile = new File(new URI(reference.getOrigReference()));
+      File destFile = new File(new URI(reference.getDataStoreReference()));
+      String origFilePath = origFile.getAbsolutePath();
+      String destFilePath = destFile.getAbsolutePath();
+
+      // read the file in chunk by chunk
+
+      byte[] buf = new byte[chunkSize];
+
+      FileInputStream is = null;
+
+      try {
+         is = new FileInputStream(origFile);
+         int offset = 0;
+         int numBytes = 0;
+
+         // remove the file if it already exists: this operation
+         // is an overwrite
+         if (!client.removeFile(destFilePath)) {
+            LOG.log(Level.WARNING,
+                  "RemoteDataTransfer: attempt to perform overwrite of dest file: ["
+                        + destFilePath + "] failed");
+         }
+
+         while ((numBytes = is.read(buf, offset, chunkSize)) != -1) {
+            client.transferFile(destFilePath, buf, offset, numBytes);
+         }
+      } catch (IOException e) {
+         LOG.log(Level.WARNING,
+               "Error opening input stream to read file to transfer: Message: "
+                     + e.getMessage());
+         return;
+      } catch (DataTransferException e) {
+         LOG.log(
+               Level.WARNING,
+               "DataTransferException when transfering file: [" + origFilePath
+                     + "] to [" + destFilePath + "]: Message: "
+                     + e.getMessage());
+         return;
+      } finally {
+         if (is != null) {
+            try {
+               is.close();
+            } catch (Exception ignore) {
+            }
+
+            is = null;
+         }
+      }
+   }
+
+   private void quietNotifyTransferProduct(Product p) {
+      try {
+         client.transferringProduct(p);
+      } catch (DataTransferException e) {
+         e.printStackTrace();
+         LOG.log(Level.WARNING,
+               "Error notifying file manager of product transfer initiation for product: ["
+                     + p.getProductId() + "]: Message: " + e.getMessage());
+         return;
+      }
+   }
+
+   private void quietNotifyProductTransferComplete(Product p) {
+      try {
+         client.removeProductTransferStatus(p);
+      } catch (DataTransferException e) {
+         e.printStackTrace();
+         LOG.log(Level.WARNING,
+               "Error notifying file manager of product transfer completion for product: ["
+                     + p.getProductId() + "]: Message: " + e.getMessage());
+         return;
+      }
+   }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/S3DataTransferer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/S3DataTransferer.java
new file mode 100644
index 0000000..4af138b
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/S3DataTransferer.java
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.datatransfer;
+
+import static com.amazonaws.services.s3.model.ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.apache.tika.io.IOUtils;
+
+import com.amazonaws.AmazonClientException;
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.model.DeleteObjectRequest;
+import com.amazonaws.services.s3.model.GetObjectRequest;
+import com.amazonaws.services.s3.model.ObjectMetadata;
+import com.amazonaws.services.s3.model.PutObjectRequest;
+import com.amazonaws.services.s3.model.S3Object;
+import com.amazonaws.services.s3.model.S3ObjectInputStream;
+
+/**
+ * {@link DataTransfer} which put/gets files in/from Amazon S3 storage.
+ * 
+ * @author bfoster@apache.org (Brian Foster)
+ */
+public class S3DataTransferer implements DataTransfer {
+
+	private final AmazonS3 s3Client;
+	private final String bucketName;
+	private final boolean encrypt;
+
+	public S3DataTransferer(AmazonS3 s3Client, String bucketName, boolean encrypt) {
+		this.s3Client = checkNotNull(s3Client);
+		this.bucketName = checkNotNull(bucketName);
+		this.encrypt = encrypt;
+	}
+
+	@Override
+	public void setFileManagerUrl(URL url) {}
+
+	@Override
+	public void transferProduct(Product product) throws DataTransferException, IOException {
+		for (Reference ref : product.getProductReferences()) {
+      String origRef = stripProtocol(ref.getOrigReference(), false);
+		  String dataStoreRef = stripProtocol(ref.getDataStoreReference(), true);
+			try {
+			  PutObjectRequest request = new PutObjectRequest(
+			      bucketName, dataStoreRef, new File(origRef));
+			  if (encrypt) {
+  				ObjectMetadata requestMetadata = new ObjectMetadata();
+  				requestMetadata.setServerSideEncryption(AES_256_SERVER_SIDE_ENCRYPTION);     
+  				request.setMetadata(requestMetadata);
+			  }
+        s3Client.putObject(request);
+			} catch (AmazonClientException e) {
+				throw new DataTransferException(String.format(
+				    "Failed to upload product reference %s to S3 at %s", origRef,
+				    dataStoreRef), e);
+			}
+		}
+	}
+
+	@Override
+	public void retrieveProduct(Product product, File directory) throws DataTransferException,
+	    IOException {
+		for (Reference ref : product.getProductReferences()) {
+      GetObjectRequest request = new GetObjectRequest(bucketName, stripProtocol(
+          ref.getDataStoreReference(), true));
+			S3Object file = s3Client.getObject(request);
+			stageFile(file, ref, directory);
+		}
+	}
+
+  @Override
+  public void deleteProduct(Product product) throws DataTransferException, IOException {
+    for (Reference ref : product.getProductReferences()) {
+      DeleteObjectRequest request = new DeleteObjectRequest(bucketName, stripProtocol(
+          ref.getDataStoreReference(), true));
+      try {
+        s3Client.deleteObject(request);
+      } catch (AmazonClientException e) {
+        throw new DataTransferException(String.format(
+            "Failed to delete product reference %s from S3", ref.getDataStoreReference()), e);
+      }
+    }
+  }
+
+	private void stageFile(S3Object file, Reference ref, File directory) throws IOException {
+		S3ObjectInputStream inStream = null;
+		FileOutputStream outStream = null;
+		try {
+			inStream = file.getObjectContent();
+			outStream = new FileOutputStream(new File(directory, new File(
+			    stripProtocol(ref.getDataStoreReference(), false)).getName()));
+			IOUtils.copy(inStream, outStream);
+		} catch (IOException e) {
+			throw e;
+		} finally {
+			try { inStream.close(); } catch (Exception e) {}
+			try { outStream.close(); } catch (Exception e) {}
+		}
+	}
+
+	private String stripProtocol(String ref, boolean stripLeadingSeparator) throws IOException {
+	  try {
+      String path = new URI(ref).getPath();
+      if (stripLeadingSeparator) {
+        path = path.replaceAll("^/", "");
+      }
+      return path;
+    } catch (URISyntaxException e) {
+      throw new IOException(e);
+    }
+	}
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/S3DataTransfererFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/S3DataTransfererFactory.java
new file mode 100644
index 0000000..d87dd37
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/S3DataTransfererFactory.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.datatransfer;
+
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.regions.Region;
+import com.amazonaws.regions.Regions;
+import com.amazonaws.services.s3.AmazonS3Client;
+
+/**
+ * {@link DataTransferFactory} which creates {@link S3DataTransferer}s.
+ * 
+ * @author bfoster@apache.org (Brian Foster)
+ */
+public class S3DataTransfererFactory implements DataTransferFactory {
+
+	private static final String BUCKET_NAME_PROPERTY =
+			"org.apache.oodt.cas.filemgr.datatransfer.s3.bucket.name";
+	private static final String REGION_PROPERTY =
+			"org.apache.oodt.cas.filemgr.datatransfer.s3.region";
+	private static final String ACCESS_KEY_PROPERTY =
+			"org.apache.oodt.cas.filemgr.datatransfer.s3.access.key";
+	private static final String SECRET_KEY_PROPERTY =
+			"org.apache.oodt.cas.filemgr.datatransfer.s3.secret.key";
+  private static final String ENCRYPT_PROPERTY =
+      "org.apache.oodt.cas.filemgr.datatransfer.s3.encrypt";
+
+	@Override
+  public S3DataTransferer createDataTransfer() {
+		String bucketName = System.getProperty(BUCKET_NAME_PROPERTY);
+		String region = System.getProperty(REGION_PROPERTY);		
+		String accessKey = System.getProperty(ACCESS_KEY_PROPERTY);
+    String secretKey = System.getProperty(SECRET_KEY_PROPERTY);
+    boolean encrypt = Boolean.getBoolean(ENCRYPT_PROPERTY);
+
+		AmazonS3Client s3 = new AmazonS3Client(new BasicAWSCredentials(accessKey, secretKey));
+    s3.setRegion(Region.getRegion(Regions.valueOf(region)));
+
+    return new S3DataTransferer(s3, bucketName, encrypt);
+  }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/TransferStatusTracker.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/TransferStatusTracker.java
new file mode 100644
index 0000000..6cf8624
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/datatransfer/TransferStatusTracker.java
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.datatransfer;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.catalog.Catalog;
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+
+//JDK imports
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * An abstract base class for data transfers that uses an in-memory HashMap to
+ * keep track of data transfer status information.
+ * </p>
+ * 
+ */
+public class TransferStatusTracker {
+    /* HashMap containing a list of current product transfers */
+    protected HashMap<String, Product> currentProductTransfers = new HashMap<String, Product>();
+
+    /* our catalog object */
+    private Catalog catalog = null;
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(TransferStatusTracker.class
+            .getName());
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     * 
+     * @param catalog
+     *            The Catalog interface handed to it by the File Manager. It
+     *            needs this object to look up reference information.
+     */
+    public TransferStatusTracker(Catalog catalog) {
+        this.catalog = catalog;
+    }
+
+    public FileTransferStatus getCurrentFileTransfer() {
+        List<FileTransferStatus> transfers = getCurrentFileTransfers();
+
+        if (transfers != null && transfers.size() > 0) {
+            return (FileTransferStatus) transfers.get(0);
+        } else
+            return null;
+    }
+
+    public void transferringProduct(Product product) {
+        currentProductTransfers.put(product.getProductId(), product);
+    }
+
+    public List<FileTransferStatus> getCurrentFileTransfers() {
+        List<FileTransferStatus> currTransfers = new Vector<FileTransferStatus>();
+
+        for (Iterator<String> i = currentProductTransfers.keySet().iterator(); i
+                .hasNext();) {
+            String productId = i.next();
+            Product p = (Product) currentProductTransfers.get(productId);
+
+            // get its references
+            List<Reference> refs = quietGetReferences(p);
+
+            if (refs != null && refs.size() > 0) {
+                for (Iterator<Reference> j = refs.iterator(); j.hasNext();) {
+                    Reference r = j.next();
+
+                    long bytesTransferred = getBytesTransferred(r);
+
+                    if (bytesTransferred > 0
+                            && bytesTransferred < r.getFileSize() && !isDir(r)) {
+                        FileTransferStatus status = new FileTransferStatus();
+                        status.setBytesTransferred(bytesTransferred);
+                        status.setFileRef(r);
+                        status.setParentProduct(p);
+                        currTransfers.add(status);
+                    }
+                }
+            }
+        }
+
+        return currTransfers;
+    }
+
+    public double getPctTransferred(Product product) {
+        // get its references
+        List<Reference> refs = quietGetReferences(product);
+        long totalBytesTransferred = 0L;
+        long totalProductSize = 0L;
+
+        if (refs.size() > 0) {
+            for (Iterator<Reference> j = refs.iterator(); j.hasNext();) {
+                Reference r = (Reference) j.next();
+
+                long bytesTransferred = getBytesTransferred(r);
+
+                if (!isDir(r)) {
+                    // only add this if > 0
+                    if (bytesTransferred > 0) {
+                        totalBytesTransferred += bytesTransferred;
+                    }
+
+                    // add this no matter what
+                    totalProductSize += r.getFileSize();
+                }
+
+            }
+        }
+
+        return ((double) ((1.0 * totalBytesTransferred) / (1.0 * totalProductSize)));
+
+    }
+
+    public double getPctTransferred(Reference ref) {
+        long bytesTransferred = getBytesTransferred(ref);
+        return ((double) ((1.0 * bytesTransferred) / (1.0 * ref.getFileSize())));
+    }
+
+    public void removeProductTransferStatus(Product product) {
+        if (currentProductTransfers.get(product.getProductId()) != null) {
+            currentProductTransfers.remove(product.getProductId());
+        }
+    }
+
+    public boolean isTransferComplete(Product product) {
+        return getPctTransferred(product) == 1.0;
+    }
+
+    private long getBytesTransferred(Reference r) {
+        File destFile = null;
+
+        try {
+            destFile = new File(new URI(r.getDataStoreReference()));
+            long bytesTransferred = destFile.length();
+            return bytesTransferred;
+        } catch (URISyntaxException e) {
+            LOG.log(Level.WARNING,
+                    "URISyntaxException when checking size of destFile: ["
+                            + r.getDataStoreReference() + "]: Message: "
+                            + e.getMessage());
+            return -1L;
+        }
+    }
+
+    private List<Reference> quietGetReferences(Product p) {
+        List<Reference> refs = null;
+
+        try {
+            refs = catalog.getProductReferences(p);
+        } catch (CatalogException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Error retreiving references for product: ["
+                    + p.getProductId()
+                    + "] from catalog in transfer status tracker: Message: "
+                    + e.getMessage());
+            refs = new Vector<Reference>();
+        }
+
+        return refs;
+    }
+
+    private boolean isDir(Reference r) {
+        File fileRef = null;
+
+        try {
+            fileRef = new File(new URI(r.getDataStoreReference()));
+            return fileRef.isDirectory();
+        } catch (URISyntaxException e) {
+            return false;
+        }
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/AbstractCacheServerFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/AbstractCacheServerFactory.java
new file mode 100644
index 0000000..d78eacd
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/AbstractCacheServerFactory.java
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public abstract class AbstractCacheServerFactory implements CacheFactory {
+
+    protected String rangeQueryElementName;
+
+    protected String rangeStartDateTime;
+
+    protected String rangeEndDateTime;
+
+    protected String uniqueElementName;
+
+    protected List<String> productTypeNames;
+
+    protected URL fmUrl;
+
+    public AbstractCacheServerFactory() throws InstantiationException {
+        rangeQueryElementName = System
+                .getProperty("org.apache.oodt.cas.filemgr.ingest.cache.rangeQueryElementName");
+
+        // before we replace env vars, try to replace date vars
+        rangeStartDateTime = System
+                .getProperty("org.apache.oodt.cas.filemgr.ingest.cache.range.start");
+        rangeEndDateTime = System
+                .getProperty("org.apache.oodt.cas.filemgr.ingest.cache.range.end");
+
+        try {
+            rangeStartDateTime = PathUtils
+                    .doDynamicReplacement(rangeStartDateTime);
+            rangeEndDateTime = PathUtils.doDynamicReplacement(rangeEndDateTime);
+        } catch (Exception e) {
+            throw new InstantiationException(e.getMessage());
+        }
+
+        uniqueElementName = System
+                .getProperty("org.apache.oodt.cas.filemgr.ingest.cache.uniqueElementName");
+        productTypeNames = Arrays.asList(PathUtils.replaceEnvVariables(
+                System.getProperty("org.apache.oodt.cas.filemgr.ingest."
+                        + "cache.productType")).split(","));
+
+        try {
+            fmUrl = new URL(
+                    System
+                            .getProperty("org.apache.oodt.cas.filemgr.ingest.cache.filemgr.url"));
+        } catch (MalformedURLException e) {
+            throw new InstantiationException(
+                    "Unable to construct file manager url for: ["
+                            + System
+                                    .getProperty("org.apache.oodt.cas.filemgr.ingest.cache.filemgr.url")
+                            + "]: malformed URL exception.");
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.CacheFactory#createCache()
+     */
+    public abstract Cache createCache() throws InstantiationException;
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/Cache.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/Cache.java
new file mode 100644
index 0000000..66a8578
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/Cache.java
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.CacheException;
+
+//JDK imports
+import java.net.URL;
+import java.util.List;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The core interface for a cache of {@link Product}s (identified by a
+ * particular <code>uniqueElement</code>) from a File Manager.
+ * </p>.
+ */
+public interface Cache {
+
+    public static final String DEFAULT_UNIQUE_MET_KEY = "CAS.ProductName";
+
+    /**
+     * Clears the current cache. This should be used before a re-{@link #sync(String, String))}
+     * occurs.
+     * 
+     */
+    public void clear();
+
+    /**
+     * Checks the cache to determine if a {@link Product} with the given
+     * <code>productName</code> exists.
+     * 
+     * @param productName
+     *            The name of the {@link Product} to check for in the Cache.
+     * @return True if the {@link Product} is foudn in the Cache, False,
+     *         otherwise.
+     */
+    public boolean contains(String productName);
+
+    /**
+     * Specifies the {@link URL} to the File Manager to connect this Cache to.
+     * 
+     * @param fmUrl
+     *            The {@link URL} of the File Manager to cache {@link Product}s
+     *            from.
+     */
+    public void setFileManager(URL fmUrl);
+
+    /**
+     * 
+     * @return The size of the current {@link Product} cache.
+     */
+    public int size();
+
+    /**
+     * Synchronizes this Cache with the File Manager specified by the
+     * {@link #setFileManager(URL)} method.
+     * 
+     * @param uniqueElementProductTypeNames
+     *            The {@link List} {@link ProductType}s to cache
+     *            {@link Product}s from.
+     * @throws CacheException
+     *             If there is any error.
+     */
+    public void sync(List<String> uniqueElementProductTypeNames) throws CacheException;
+
+    /**
+     * Synchronizes this Cache with the File Manager specified by the
+     * {@link #setFileManager(URL)} method.
+     * 
+     * @param uniqueElementName
+     *            The met key identifier to use for determining {@link Product}
+     *            existance (if different than {@value #DEFAULT_UNIQUE_MET_KEY}).
+     * @param uniqueElementProductTypeNames
+     *            The {@link List} of {@link ProductType}s to cache
+     *            {@link Product}s from.
+     * @throws CacheException
+     *             If there is any error.
+     */
+    public void sync(String uniqueElementName,
+            List<String> uniqueElementProductTypeNames) throws CacheException;
+
+    /**
+     * Synchronizes this Cache with the File Manager specified by the
+     * {@link #setFileManager(URL)} method. This method also assumes that the
+     * unique element (identified by {@link #setUniqueElementName(String)} and
+     * the {@link List} of {@link ProductType}s have also been set appropriate
+     * (e.g., by using {@link #setUniqueElementProductTypeNames(List)}.
+     * 
+     * @throws CacheException
+     *             If any error occurs.
+     */
+    public void sync() throws CacheException;
+
+    /**
+     * Sets the names of the {@link ProductType}s to cache.
+     * 
+     * @param uniqueElementProductTypeNames
+     *            A {@link List} of java.util.String names of
+     *            {@link ProductType}s.
+     */
+    public void setUniqueElementProductTypeNames(
+            List<String> uniqueElementProductTypeNames);
+
+    /**
+     * Sets the name of the met element to use as the identifier of a
+     * {@link Product} for use in determining whether the Product is in the
+     * Cache.
+     * 
+     * @param uniqueElementName
+     *            The name of the met element used to uniquely identify
+     *            {@link Product}s.
+     */
+    public void setUniqueElementName(String uniqueElementName);
+
+    /**
+     * Gets the {@link URL} of the File Manager that this Cache communicates
+     * with.
+     * 
+     * @return The {@link URL} of the File Manager that this Cache communicates
+     *         with.
+     */
+    public URL getFileManagerUrl();
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/CacheFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/CacheFactory.java
new file mode 100644
index 0000000..a901ada
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/CacheFactory.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory class for creating {@link Cache}s
+ * </p>.
+ */
+public interface CacheFactory {
+
+    /**
+     * Create a new {@link Cache}.
+     * 
+     * @return A new {@link Cache}, constructed by the implementing Factory.
+     * @throws InstantiationException If the the particular {@link Cache} can
+     * not be created for some reason.
+     */
+    public Cache createCache() throws InstantiationException;
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/CachedIngester.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/CachedIngester.java
new file mode 100644
index 0000000..4c48b1c
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/CachedIngester.java
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.CacheException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.util.GenericFileManagerObjectFactory;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An extension of the {@link StdIngester} that uses a {@link Cache} to keep
+ * track of {@link Product} ingestion status. If the existing {@link Cache} used
+ * is already sync'ed to the requested File Manager (specified by the
+ * <code>fmUrl</code> parameter in {@link #hasProduct(URL, File)} or
+ * {@link #hasProduct(URL, String)}), then the {@link Cache} will simply return
+ * the value of {@link Cache#contains(String)}. Otherwise the {@link Cache}
+ * will be re-{@link Cache#sync()}'ed to the given File Manager before the
+ * contains method is invoked.
+ * </p>.
+ */
+public class CachedIngester extends StdIngester {
+
+    private Cache cache;
+
+    private static final Logger LOG = Logger.getLogger(CachedIngester.class
+            .getName());
+
+    /**
+     * @param transferService
+     *            The underlying data transfer service to use to ingest
+     *            {@link Product}s.
+     * @param cacheServiceFactory
+     *            The {@link CacheFactory} to use to construct this
+     *            {@link Ingester}'s {@link Cache}.
+     * @param cachePropFile
+     *            The file path to the cache properties file to load to
+     *            configure the {@link Cache}.
+     */
+    public CachedIngester(String transferService, String cacheServiceFactory,
+            String cachePropFile) throws InstantiationException {
+        super(transferService);
+        try {
+            System.getProperties().load(new FileInputStream(cachePropFile));
+        } catch (Exception e) {
+            throw new InstantiationException(
+                    "Unable to load cache properties from file: ["
+                            + cachePropFile + "]");
+        }
+        this.cache = GenericFileManagerObjectFactory
+                .getCacheFromFactory(cacheServiceFactory);
+        init(this.cache);
+
+    }
+
+    /**
+     * 
+     * @param transferService
+     *            The underlying data transfer service to use to ingest
+     *            {@link Product}s.
+     * @param cache
+     *            The {@link Cache} that this {@link Ingester} will use.
+     * @throws InstantiationException
+     *             If any error occurs.
+     */
+    public CachedIngester(String transferService, Cache cache)
+            throws InstantiationException {
+        super(transferService);
+        init(cache);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.StdIngester#hasProduct(java.net.URL,
+     *      java.io.File)
+     */
+    public boolean hasProduct(URL fmUrl, File prodFile) throws CatalogException {
+        return hasProduct(fmUrl, prodFile.getName());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.StdIngester#hasProduct(java.net.URL,
+     *      java.lang.String)
+     */
+    public boolean hasProduct(URL fmUrl, String productName)
+            throws CatalogException {
+        if (cache.getFileManagerUrl().equals(fmUrl)) {
+            return cache.contains(productName);
+        } else {
+            // need to re-sync
+            cache.setFileManager(fmUrl);
+            try {
+                cache.sync();
+            } catch (CacheException e) {
+                LOG.log(Level.WARNING,
+                        "Exception re-syncing cache to file manager: [" + fmUrl
+                                + "]: Message: " + e.getMessage());
+                throw new CatalogException(
+                        "Exception re-syncing cache to file manager: [" + fmUrl
+                                + "]: Message: " + e.getMessage());
+            }
+            return cache.contains(productName);
+        }
+    }
+
+    /**
+     * 
+     * @throws CacheException
+     */
+    public void resynsc() throws CacheException {
+        cache.sync();
+    }
+
+    private void init(Cache cache) throws InstantiationException {
+        this.cache = cache;
+        // upon inception, do an initial sync
+        try {
+            cache.sync();
+        } catch (CacheException e) {
+            throw new InstantiationException(
+                    "Unable to sync cache for CachedIngester: Message: "
+                            + e.getMessage());
+        }
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/CmdLineIngester.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/CmdLineIngester.java
new file mode 100644
index 0000000..b3706ec
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/CmdLineIngester.java
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.IngestException;
+import org.apache.oodt.cas.metadata.MetExtractor;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.metadata.util.GenericMetadataObjectFactory;
+
+
+//JDK imports
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A command line I/F for {@link Product} ingestion.
+ * </p>.
+ */
+public class CmdLineIngester extends StdIngester {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(CmdLineIngester.class
+            .getName());
+
+    public CmdLineIngester(String serviceFactory) {
+        super(serviceFactory);
+    }
+
+    /**
+     * @param args
+     * @throws IngestException
+     * @throws MalformedURLException
+     */
+    public static void main(String[] args) throws Exception {
+        String usage = CmdLineIngester.class.getName()
+                + " --url <filemgr url> [options]\n"
+                + "[--extractor <met extractor class name> <met conf file path>|"
+                + "--metFile <met file path>]\n"
+                + "--transferer <data transfer service factory>\n"
+                + "[--file <full path> | --in reads list of files from STDIN]\n";
+
+        String fmUrlStr = null, extractorClassName = null, filePath = null;
+        String transferServiceFactory = null, metConfFilePath = null;
+        String metFilePath = null;
+        boolean readFromStdin = false;
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--url")) {
+                fmUrlStr = args[++i];
+            } else if (args[i].equals("--extractor")) {
+                extractorClassName = args[++i];
+                metConfFilePath = args[++i];
+            } else if (args[i].equals("--file")) {
+                filePath = args[++i];
+            } else if (args[i].equals("--in")) {
+                readFromStdin = true;
+            } else if (args[i].equals("--transferer")) {
+                transferServiceFactory = args[++i];
+            } else if (args[i].equals("--metFile")) {
+                metFilePath = args[++i];
+            }
+        }
+
+        if (fmUrlStr == null
+                || ((extractorClassName == null || metConfFilePath == null) && metFilePath == null)
+                || (metFilePath != null && (metConfFilePath != null || extractorClassName != null))
+                || transferServiceFactory == null
+                || (filePath == null && !readFromStdin)
+                || (readFromStdin && metFilePath != null)
+                || (readFromStdin && filePath != null)) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        CmdLineIngester ingester = new CmdLineIngester(transferServiceFactory);
+        MetExtractor extractor = null;
+        if (readFromStdin) {
+            List<String> prods = readProdFilesFromStdin();
+            extractor = GenericMetadataObjectFactory
+                    .getMetExtractorFromClassName(extractorClassName);
+            ingester.ingest(new URL(fmUrlStr), prods, extractor, new File(
+                    metConfFilePath));
+        } else {
+            String productID = null;
+            if (metFilePath != null) {
+                productID = ingester.ingest(new URL(fmUrlStr), new File(
+                        filePath), new SerializableMetadata(
+                        new FileInputStream(metFilePath)));
+            } else {
+                extractor = GenericMetadataObjectFactory
+                        .getMetExtractorFromClassName(extractorClassName);
+                productID = ingester.ingest(new URL(fmUrlStr), new File(
+                        filePath), extractor, new File(metConfFilePath));
+            }
+
+            System.out.println("Result: " + productID);
+        }
+
+    }
+
+    private static List<String> readProdFilesFromStdin() {
+        List<String> prodFiles = new Vector<String>();
+        BufferedReader br = null;
+
+        br = new BufferedReader(new InputStreamReader(System.in));
+
+        String line = null;
+
+        try {
+            while ((line = br.readLine()) != null) {
+                prodFiles.add(line);
+            }
+        } catch (IOException e) {
+            LOG.log(Level.WARNING, "Error reading prod file: line: [" + line
+                    + "]: Message: " + e.getMessage(), e);
+        }
+
+        return prodFiles;
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/Ingester.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/Ingester.java
new file mode 100644
index 0000000..45e71d4
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/Ingester.java
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.IngestException;
+import org.apache.oodt.cas.metadata.MetExtractor;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JDK imports
+import java.io.File;
+import java.net.URL;
+import java.util.List;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * An interface for ingesting {@link Product}s
+ * </p>.
+ */
+public interface Ingester {
+
+    /**
+     * Ingests a {@link Product} to the file manager service object identified
+     * by the given {@link URL} parameter. The product {@link Metadata} is
+     * extracted dynamically using the provided {@link MetExtractor} interface.
+     * 
+     * @param fmUrl
+     *            The {@link URL} pointer to the file manager service.
+     * @param prodFile
+     *            The {@link File} pointer to the product file.
+     * @param extractor
+     *            The given {@link MetExtractor} to use to extract
+     *            {@link Metadata} from the {@link Product}.
+     * @param metConfFile
+     *            A Config{@link File} for the {@link MetExtractor}.
+     * @return The ID returned by the file manager for the newly ingested
+     *         product.
+     * @throws IngestException
+     *             If there is an error ingesting the {@link Product}
+     */
+    public String ingest(URL fmUrl, File prodFile, MetExtractor extractor,
+            File metConfFile) throws IngestException;
+
+    /**
+     * Ingests a {@link Product} to the file manager service object identified
+     * by the given {@link URL} parameter. The product {@link Metadata} is
+     * provided a priori.
+     * 
+     * @param fmUrl
+     *            The {@link URL} pointer to the file manager service.
+     * @param prodFile
+     *            The {@link File} pointer to the product file.
+     * @param met
+     *            The given {@link Metadata} object already extracted from the
+     *            {@link Product}.
+     * @return The ID returned by the file manager for the newly ingested
+     *         product.
+     * @throws IngestException
+     *             If there is an error ingesting the {@link Product}
+     */
+    public String ingest(URL fmUrl, File prodFile, Metadata met)
+            throws IngestException;
+
+    /**
+     * 
+     * @param fmUrl
+     *            The {@link URL} pointer to the file manager service.
+     * @param prodFiles
+     *            A {@link List} of {@link String} filePaths pointing to
+     *            {@link Product} files to ingest.
+     * @param extractor
+     *            The given {@link MetExtractor} to use to extract
+     *            {@link Metadata} from the {@link Product}s.
+     * @param metConfFile
+     *            A Config{@link File} for the {@link MetExtractor}.
+     * @throws IngestException
+     *             If there is an error ingesting the {@link Product}s.
+     */
+    public void ingest(URL fmUrl, List<String> prodFiles, MetExtractor extractor,
+            File metConfFile) throws IngestException;
+
+    /**
+     * Checks the file manager at the given {@link URL} to see whether or not it
+     * knows about the provided {@link Product} {@link File} parameter. To do
+     * this, it uses {@link File#getName()} as the {@link Metadata} key
+     * <code>Filename</code>.
+     * 
+     * @param prodFile
+     *            The {@link File} to check for existance of within the file
+     *            manager at given {@link URL}.
+     * @url The {@link URL} pointer to the file manager service.
+     * @return
+     */
+    public boolean hasProduct(URL fmUrl, File prodFile) throws CatalogException;
+
+    /**
+     * Checks the file manager at the given {@link URL} to see whether or not it
+     * knows about the provided {@link Product} with the given
+     * <code>productName</code> parameter. To do this, it uses the provided
+     * <code>productName</code> key as the {@link Metadata} key to search for
+     * in the catalog.
+     * 
+     * @param fmUrl
+     *            The {@link URL} pointer to the file manager service.
+     * @param productName
+     *            The {@link Product} to search for, identified by its (possibly
+     *            not unique) name.
+     * @return True if the file manager has the product, false otherwise.
+     */
+    public boolean hasProduct(URL fmUrl, String productName) throws CatalogException;
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/LocalCache.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/LocalCache.java
new file mode 100644
index 0000000..795ac36
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/LocalCache.java
@@ -0,0 +1,316 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CacheException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//JDK imports
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ * <p>
+ * A cached way to determine product ingestion against a File Manager.
+ * </p>
+ * 
+ */
+public class LocalCache implements Cache {
+
+    private HashSet<String> uniqueElements;
+
+    private String uniqueElementName;
+
+    private List<String> uniqueElementProductTypeNames;
+
+    private String rangeQueryElementName;
+
+    private String startOfQuery;
+
+    private String endOfQuery;
+
+    private XmlRpcFileManagerClient fm;
+
+    private static final Logger LOG = Logger.getLogger(LocalCache.class
+            .getName());
+
+    /**
+     * 
+     * @param fmUrl
+     * @param uniqueElementName
+     * @param rangeQueryElementName
+     * @param startOfQuery
+     * @param endOfQuery
+     */
+    public LocalCache(URL fmUrl, String rangeQueryElementName,
+            String startOfQuery, String endOfQuery) {
+        this(fmUrl, null, null, rangeQueryElementName, startOfQuery, endOfQuery);
+
+    }
+
+    /**
+     * 
+     * @param fmUrl
+     * @param uniqueElementName
+     * @param uniqueElementProductType
+     * @param rangeQueryElementName
+     * @param startOfQuery
+     * @param endOfQuery
+     */
+    public LocalCache(URL fmUrl, String uniqueElementName,
+            List<String> uniqueElementProductTypes, String rangeQueryElementName,
+            String startOfQuery, String endOfQuery) {
+        this.uniqueElements = new HashSet<String>();
+        this.uniqueElementName = uniqueElementName;
+        this.uniqueElementProductTypeNames = uniqueElementProductTypes;
+        this.rangeQueryElementName = rangeQueryElementName;
+        this.startOfQuery = startOfQuery;
+        this.endOfQuery = endOfQuery;
+        setFileManager(fmUrl);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#sync(java.util.List)
+     */
+    public void sync(List<String> uniqueElementProductTypeNames) throws CacheException {
+        sync(DEFAULT_UNIQUE_MET_KEY, uniqueElementProductTypeNames);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#sync(java.lang.String,
+     *      java.util.List)
+     */
+    public void sync(String uniqueElementName,
+            List<String> uniqueElementProductTypeNames) throws CacheException {
+        try {
+            this.uniqueElementName = uniqueElementName;            
+            this.uniqueElementProductTypeNames = uniqueElementProductTypeNames;
+            List<Product> products = new Vector<Product>();
+            for (String productType : this.uniqueElementProductTypeNames)
+                products.addAll(getProductsOverDateRange(
+                    this.rangeQueryElementName, productType, this.startOfQuery,
+                    this.endOfQuery));
+            clear();
+            for (Iterator<Product> i = products.iterator(); i.hasNext();) {
+                Product product = i.next();
+
+                String value = getValueForMetadata(product, uniqueElementName);
+                this.uniqueElements.add(value);
+            }
+        } catch (Exception e) {
+            throw new CacheException("Failed to sync with database : "
+                    + e.getMessage());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#clear()
+     */
+    public void clear() {
+        this.uniqueElements.clear();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#size()
+     */
+    public int size() {
+        return this.uniqueElements.size();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#contains(java.lang.String)
+     */
+    public boolean contains(String productName) {
+        return this.uniqueElements.contains(productName);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#setFileManager(java.net.URL)
+     */
+    public void setFileManager(URL fmUrl) {
+        try {
+            this.fm = new XmlRpcFileManagerClient(fmUrl);
+        } catch (ConnectionException e) {
+            LOG.log(Level.WARNING,
+                    "Exception setting file manager connection to: [" + fmUrl
+                            + "]");
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#sync()
+     */
+    public void sync() throws CacheException {
+        if (this.uniqueElementName == null
+                || (this.uniqueElementProductTypeNames == null || 
+                        (this.uniqueElementProductTypeNames != null && this.uniqueElementProductTypeNames.size() == 0))) {
+            throw new CacheException(
+                    "Both uniqueElementName and uniqueElementProductTypeName must "
+                            + "be defined in order to use this form of the sync operation!");
+        }
+
+        sync(this.uniqueElementName, this.uniqueElementProductTypeNames);
+
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#getFileManagerUrl()
+     */
+    public URL getFileManagerUrl() {
+        return this.fm.getFileManagerUrl();
+    }
+
+    /**
+     * Performs a {@link XmlRpcFileManagerClient#hasProduct(String)} check
+     * against a live File Manager, bypassing the {@link Cache}.
+     * 
+     * @param uniqueElementName
+     *            The product identifier element to identify whether the product
+     *            was received yet.
+     * @param uniqueElementValue
+     *            The value of the product identifier element.
+     * @param productTypeName
+     *            The {@link ProductType} of the Product that you would like to
+     *            check existence for.
+     * @return True if the given Product (identified by its
+     *         <code>uniqueElement</code>) exists, False otherwise.
+     * @throws CacheException
+     *             If any error occurs.
+     */
+    public boolean liveHasProduct(String uniqueElementName,
+            String uniqueElementValue, String productTypeName)
+            throws CacheException {
+        Query query = new Query();
+        query.addCriterion(new TermQueryCriteria(uniqueElementName,
+                uniqueElementValue));
+        try {
+            return !(fm.query(query, fm.getProductTypeByName(productTypeName))
+                    .isEmpty());
+        } catch (Exception e) {
+            throw new CacheException(
+                    "Unable to check for product reception from file manager: ["
+                            + fm.getFileManagerUrl() + "]: Message: "
+                            + e.getMessage());
+        }
+    }
+
+    /**
+     * @return the uniqueElementName
+     */
+    public String getUniqueElementName() {
+        return uniqueElementName;
+    }
+
+    /**
+     * @param uniqueElementName
+     *            the uniqueElementName to set
+     */
+    public void setUniqueElementName(String uniqueElementName) {
+        this.uniqueElementName = uniqueElementName;
+    }
+
+    /**
+     * @return the uniqueElementProductTypeNames
+     */
+    public List<String> getUniqueElementProductTypeNames() {
+        return uniqueElementProductTypeNames;
+    }
+
+    /**
+     * @param uniqueElementProductTypeNames
+     *            the uniqueElementProductTypeNames to set
+     */
+    public void setUniqueElementProductTypeNames(
+            List<String> uniqueElementProductTypeNames) {
+        this.uniqueElementProductTypeNames = uniqueElementProductTypeNames;
+    }
+
+    private List<Product> getProductsOverDateRange(String elementName, String productType,
+            String startOfQuery, String endOfQuery) throws CacheException {
+        List<Product> products = new Vector<Product>();
+        try {        
+            Query query = new Query();
+            query.addCriterion(new RangeQueryCriteria(elementName,
+                    startOfQuery, endOfQuery));
+            if(this.uniqueElementProductTypeNames != null && 
+                    this.uniqueElementProductTypeNames.size() > 0){
+                for(Iterator<String> i = this.uniqueElementProductTypeNames.iterator(); i.hasNext(); ){
+                    String productTypeName = i.next();
+                    products.addAll(getProducts(query, productTypeName));
+                }
+                
+            }
+        } catch (Exception e) {
+            throw new CacheException("Failed to query for product via element "
+                    + elementName + " and range " + startOfQuery + " to "
+                    + endOfQuery + " : " + e.getMessage());
+        }
+        
+        return products;
+    }
+
+    private List<Product> getProducts(Query query, String productType)
+            throws CacheException {
+        try {
+            return fm.query(query, fm.getProductTypeByName(productType));
+        } catch (Exception e) {
+            throw new CacheException("Failed to get product list for query "
+                    + query + " : " + e.getMessage());
+        }
+    }
+
+    private String getValueForMetadata(Product product,
+            String metadataElementName) throws CacheException {
+        try {
+            return fm.getMetadata(product).getMetadata(metadataElementName);
+        } catch (Exception e) {
+            throw new CacheException("Failed to get metadata value for "
+                    + metadataElementName + " : " + e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/LocalCacheFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/LocalCacheFactory.java
new file mode 100644
index 0000000..9fd7d12
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/LocalCacheFactory.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Constructs new {@link LocalCache}s
+ * </p>.
+ */
+public class LocalCacheFactory extends AbstractCacheServerFactory {
+
+    public LocalCacheFactory() throws InstantiationException {
+        super();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.AbstractCacheServerFactory#createCache()
+     */
+    public Cache createCache() throws InstantiationException {
+        return new LocalCache(fmUrl, uniqueElementName, productTypeNames,
+                rangeQueryElementName, rangeStartDateTime, rangeEndDateTime);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RemoteableCache.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RemoteableCache.java
new file mode 100644
index 0000000..ab5ad93
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RemoteableCache.java
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//JDK imports
+import java.net.URL;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.List;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ *  A Java RMI {@link Remote}-able implementation of the {@link Cache}
+ *  interface.
+ * </p>.
+ */
+public interface RemoteableCache extends Remote{
+
+    public static final String DEFAULT_UNIQUE_MET_KEY = "CAS.ProductName";
+
+    /**
+     * Clears the current cache. This should be used before a re-{@link #sync(String, String))}
+     * occurs.
+     * 
+     */
+    public void clear() throws RemoteException;
+
+    /**
+     * Checks the cache to determine if a {@link Product} with the given
+     * <code>productName</code> exists.
+     * 
+     * @param productName
+     *            The name of the {@link Product} to check for in the Cache.
+     * @return True if the {@link Product} is foudn in the Cache, False,
+     *         otherwise.
+     */
+    public boolean contains(String productName) throws RemoteException;
+
+    /**
+     * Specifies the {@link URL} to the File Manager to connect this Cache to.
+     * 
+     * @param fmUrl
+     *            The {@link URL} of the File Manager to cache {@link Product}s
+     *            from.
+     */
+    public void setFileManager(URL fmUrl) throws RemoteException;
+
+    /**
+     * 
+     * @return The size of the current {@link Product} cache.
+     */
+    public int size() throws RemoteException;
+
+    /**
+     * Synchronizes this Cache with the File Manager specified by the
+     * {@link #setFileManager(URL)} method.
+     * 
+     * @param uniqueElementProductTypeNames
+     *            The {@link List} {@link ProductType}s to cache
+     *            {@link Product}s from.
+     * @throws RemoteException
+     *             If there is any error.
+     */
+    public void sync(List<String> uniqueElementProductTypeNames) throws RemoteException;
+
+    /**
+     * Synchronizes this Cache with the File Manager specified by the
+     * {@link #setFileManager(URL)} method.
+     * 
+     * @param uniqueElementName
+     *            The met key identifier to use for determining {@link Product}
+     *            existance (if different than {@value #DEFAULT_UNIQUE_MET_KEY}).
+     * @param uniqueElementProductTypeNames
+     *            The {@link List} of {@link ProductType}s to cache
+     *            {@link Product}s from.
+     * @throws RemoteException
+     *             If there is any error.
+     */
+    public void sync(String uniqueElementName,
+            List<String> uniqueElementProductTypeNames) throws RemoteException;
+
+    /**
+     * Synchronizes this Cache with the File Manager specified by the
+     * {@link #setFileManager(URL)} method. This method also assumes that the
+     * unique element (identified by {@link #setUniqueElementName(String)} and
+     * the {@link List} of {@link ProductType}s have also been set appropriate
+     * (e.g., by using {@link #setUniqueElementProductTypeNames(List)}.
+     * 
+     * @throws RemoteException
+     *             If any error occurs.
+     */
+    public void sync() throws RemoteException;
+
+    /**
+     * Sets the names of the {@link ProductType}s to cache.
+     * 
+     * @param uniqueElementProductTypeNames
+     *            A {@link List} of java.util.String names of
+     *            {@link ProductType}s.
+     */
+    public void setUniqueElementProductTypeNames(
+            List<String> uniqueElementProductTypeNames) throws RemoteException;
+
+    /**
+     * Sets the name of the met element to use as the identifier of a
+     * {@link Product} for use in determining whether the Product is in the
+     * Cache.
+     * 
+     * @param uniqueElementName
+     *            The name of the met element used to uniquely identify
+     *            {@link Product}s.
+     */
+    public void setUniqueElementName(String uniqueElementName)
+            throws RemoteException;
+
+    /**
+     * Gets the {@link URL} of the File Manager that this Cache communicates
+     * with.
+     * 
+     * @return The {@link URL} of the File Manager that this Cache communicates
+     *         with.
+     */
+    public URL getFileManagerUrl() throws RemoteException;
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RmiCache.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RmiCache.java
new file mode 100644
index 0000000..df3e2a9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RmiCache.java
@@ -0,0 +1,188 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.CacheException;
+
+//JDK imports
+import java.net.URL;
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.util.List;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * An RMI client to the {@link RmiCacheServer}, implementing an RMI front end
+ * to a {@link LocalCache}.
+ * </p>.
+ */
+public class RmiCache implements Cache {
+
+    private RemoteableCache rmiCacheServer;
+
+    public RmiCache(String rmiCacheServerUrn) throws InstantiationException {
+        try {
+            rmiCacheServer = (RemoteableCache) Naming.lookup(rmiCacheServerUrn);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new InstantiationException(
+                    "Unable to connect to Rmi Cache Server at: ["
+                            + rmiCacheServerUrn + "]");
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#clear()
+     */
+    public void clear() {
+        try {
+            rmiCacheServer.clear();
+        } catch (RemoteException e) {
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#contains(java.lang.String)
+     */
+    public boolean contains(String productName) {
+        try {
+            return rmiCacheServer.contains(productName);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#setFileManager(java.net.URL)
+     */
+    public void setFileManager(URL fmUrl) {
+        try {
+            rmiCacheServer.setFileManager(fmUrl);
+        } catch (RemoteException e) {
+            
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#size()
+     */
+    public int size() {
+        try {
+            return rmiCacheServer.size();
+        } catch (RemoteException e) {
+            return -1;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#sync(java.util.List)
+     */
+    public void sync(List<String> uniqueElementProductTypeNames) throws CacheException {
+        try {
+            rmiCacheServer.sync(uniqueElementProductTypeNames);
+        } catch (RemoteException e) {
+            throw new CacheException(e.getMessage());
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#sync(java.lang.String,
+     *      java.util.List)
+     */
+    public void sync(String uniqueElementName,
+            List<String> uniqueElementProductTypeNames) throws CacheException {
+        try {
+            rmiCacheServer.sync(uniqueElementName, uniqueElementProductTypeNames);
+        } catch (RemoteException e) {
+           throw new CacheException(e.getMessage());
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#setUniqueElementProductTypeName(java.util.List)
+     */
+    public void setUniqueElementProductTypeNames(
+            List<String> uniqueElementProductTypeNames) {
+        try {
+            rmiCacheServer
+                    .setUniqueElementProductTypeNames(uniqueElementProductTypeNames);
+        } catch (RemoteException e) {
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#sync()
+     */
+    public void sync() throws CacheException {
+        try {
+            rmiCacheServer.sync();
+        } catch (RemoteException e) {
+            throw new CacheException(e.getMessage());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#setUniqueElementName(java.lang.String)
+     */
+    public void setUniqueElementName(String uniqueElementName) {
+        try {
+            rmiCacheServer.setUniqueElementName(uniqueElementName);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.filemgr.ingest.Cache#getFileManagerUrl()
+     */
+    public URL getFileManagerUrl() {
+        try {
+            return rmiCacheServer.getFileManagerUrl();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RmiCacheFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RmiCacheFactory.java
new file mode 100644
index 0000000..e409972
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RmiCacheFactory.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Constructs new {@link RmiCache}s.
+ * </p>.
+ */
+public class RmiCacheFactory implements CacheFactory {
+
+    private String rmiCacheServerUrn;
+
+    public RmiCacheFactory() {
+        rmiCacheServerUrn = PathUtils
+                .replaceEnvVariables(System
+                        .getProperty("org.apache.oodt.cas.filemgr.ingest.cache.rmi.serverUrn"));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.CacheFactory#createCache()
+     */
+    public Cache createCache() throws InstantiationException {
+        return new RmiCache(rmiCacheServerUrn);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RmiCacheServer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RmiCacheServer.java
new file mode 100644
index 0000000..f34f0c6
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RmiCacheServer.java
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.CacheException;
+
+//JDK imports
+import java.io.Serializable;
+import java.net.URL;
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.List;
+
+/**
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ * A Java RMI based interface to a backend {@link LocalCache}.
+ * 
+ */
+public class RmiCacheServer extends UnicastRemoteObject implements RemoteableCache, Serializable{
+
+    private static final long serialVersionUID = -538329403363156379L;
+
+    private LocalCache cache;
+
+    private String uniqueElementName;
+
+    private List<String> uniqueElementProductTypeNames;
+    
+    private Registry reg;
+
+    public RmiCacheServer(URL fmUrl, String rangeQueryElementName,
+            String rangeStartDateTime, String rangeEndDateTime,
+            String uniqueElementName, List<String> productTypeNames)
+            throws RemoteException {
+        // initialize the cache
+        cache = new LocalCache(fmUrl, rangeQueryElementName,
+                rangeStartDateTime, rangeEndDateTime);
+        this.uniqueElementName = uniqueElementName;
+        this.uniqueElementProductTypeNames = productTypeNames;
+
+    }
+
+    public void launchServer(int rmiPort) throws RemoteException {
+        launchServer(this.cache.getFileManagerUrl(), rmiPort);
+    }
+
+    public void launchServer(URL filemgrUrl, int rmiPort)
+            throws RemoteException {
+        syncWith(filemgrUrl);
+        launchRmiServer(rmiPort);
+    }
+
+    public void stopServer(int port) throws RemoteException {
+        try {
+            Naming.unbind("rmi://localhost:" + port + "/RmiDatabaseServer");
+            UnicastRemoteObject.unexportObject(reg,true);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RemoteException(
+                    "Unable to unbind Database Server: reason: "
+                            + e.getMessage());
+        }
+    }
+
+    public void clear() throws RemoteException {
+        cache.clear();
+
+    }
+
+    public boolean contains(String productName) throws RemoteException {
+        return cache.contains(productName);
+    }
+
+    public void setFileManager(URL fmUrl) throws RemoteException {
+        cache.setFileManager(fmUrl);
+    }
+
+    public int size() throws RemoteException {
+        return cache.size();
+    }
+
+    public void sync(List<String> uniqueElementProductTypeNames) throws RemoteException {
+        try {
+            cache.sync(uniqueElementProductTypeNames);
+        } catch (CacheException e) {
+            throw new RemoteException(e.getMessage());
+        }
+
+    }
+
+    public void sync(String uniqueElementName,
+            List<String> uniqueElementProductTypeNames) throws RemoteException {
+        try {
+            cache.sync(uniqueElementName, uniqueElementProductTypeNames);
+        } catch (CacheException e) {
+            throw new RemoteException(e.getMessage());
+        }
+
+    }
+
+    public void sync() throws RemoteException {
+        if (this.uniqueElementName == null
+                || (this.uniqueElementProductTypeNames == null || (this.uniqueElementProductTypeNames != null && this.uniqueElementProductTypeNames
+                        .size() == 0))) {
+            throw new RemoteException(
+                    "Both uniqueElementName and uniqueElementProductTypeNames must "
+                            + "be defined in order to use this form of the sync operation!");
+        }
+
+        sync(this.uniqueElementName, this.uniqueElementProductTypeNames);
+
+    }
+
+    public URL getFileManagerUrl() throws RemoteException {
+        return cache.getFileManagerUrl();
+    }
+
+    /**
+     * @return the uniqueElementProductTypeNames
+     */
+    public List<String> getUniqueElementProductTypeNames() throws RemoteException {
+        return uniqueElementProductTypeNames;
+    }
+
+    /**
+     * @param uniqueElementProductTypeNames
+     *            the uniqueElementProductTypeNames to set
+     */
+    public void setUniqueElementProductTypeNames(
+            List<String> uniqueElementProductTypeNames) throws RemoteException {
+        this.uniqueElementProductTypeNames = uniqueElementProductTypeNames;
+    }
+
+    /**
+     * @return the uniqueElementName
+     */
+    public String getUniqueElementName() throws RemoteException {
+        return uniqueElementName;
+    }
+
+    /**
+     * @param uniqueElementName
+     *            the uniqueElementName to set
+     */
+    public void setUniqueElementName(String uniqueElementName)
+            throws RemoteException {
+        this.uniqueElementName = uniqueElementName;
+    }
+
+    private void syncWith(URL url) throws RemoteException {
+        cache.setFileManager(url);
+        try {
+            cache.sync(this.uniqueElementName,
+                    this.uniqueElementProductTypeNames);
+        } catch (CacheException e) {
+            throw new RemoteException(
+                    "Unable to sync cache with file manager: [" + url
+                            + "]: Message: " + e.getMessage());
+        }
+    }
+
+    private void launchRmiServer(int port) throws RemoteException {
+        try {
+            reg = LocateRegistry.createRegistry(port);
+            Naming.rebind("rmi://localhost:" + port + "/RmiDatabaseServer", this);
+            System.out.println("RMI server created at rmi://localhost:" + port
+                    + "/RmiDatabaseServer");
+        } catch (Exception e) {
+            throw new RemoteException("Failed to create RMI Server : "
+                    + e.getMessage());
+        }
+
+        
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RmiCacheServerFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RmiCacheServerFactory.java
new file mode 100644
index 0000000..d3eba9d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/RmiCacheServerFactory.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//JDK imports
+import java.io.FileInputStream;
+import java.net.URL;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Constructs new {@link RmiCacheServer}s.
+ * </p>.
+ */
+public class RmiCacheServerFactory extends AbstractCacheServerFactory{
+
+    /**
+     * @throws InstantiationException
+     */
+    public RmiCacheServerFactory() throws InstantiationException {
+        super();
+    }
+    
+    public Cache createCache() throws InstantiationException{
+        throw new InstantiationException("Don't call this method for the RmiCacheServer!");
+    }
+
+    public RmiCacheServer createRemoteCache() throws InstantiationException {
+        try {
+            return new RmiCacheServer(fmUrl, rangeQueryElementName,
+                    rangeStartDateTime, rangeEndDateTime, uniqueElementName,
+                    productTypeNames);
+
+        } catch (Exception e) {
+            throw new InstantiationException(e.getMessage());
+        }
+    }
+
+    public static void main(String[] args) {
+        String propFilePath = null, fileManagerUrl = null;
+        int rmiPort = -1;
+
+        String usage = "RmiCacheServer [options] \n"
+                + "--fileManagerUrl <url> \n" + "--rmiPort <port number> \n"
+                + "--propFile <path>\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--fileManagerUrl")) {
+                fileManagerUrl = args[++i];
+            } else if (args[i].equals("--propFile")) {
+                propFilePath = args[++i];
+            } else if (args[i].equals("--rmiPort")) {
+                rmiPort = Integer.parseInt(args[++i]);
+            }
+        }
+
+        if (propFilePath == null || fileManagerUrl == null || rmiPort == -1) {
+            System.out.println(usage);
+            return;
+        }
+
+        try {
+            System.getProperties().load(new FileInputStream(propFilePath));
+            RmiCacheServerFactory svrFactory = new RmiCacheServerFactory();
+            RmiCacheServer cache = (RmiCacheServer)svrFactory.createRemoteCache();
+            cache.launchServer(new URL(fileManagerUrl), rmiPort);
+        } catch (Exception e) {
+            System.err.println("Failed to launch RmiCacheServer : "
+                    + e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/StdIngester.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/StdIngester.java
new file mode 100644
index 0000000..4f56d0d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/ingest/StdIngester.java
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.IngestException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.filemgr.util.GenericFileManagerObjectFactory;
+import org.apache.oodt.cas.filemgr.versioning.VersioningUtils;
+import org.apache.oodt.cas.metadata.MetExtractor;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+//JDK imports
+import java.io.File;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * An implementation of the {@link Ingster} interface that uses the following
+ * pieces of {@link Metadata} information to determine how to ingest a
+ * {@link Product}:
+ * 
+ * <ul>
+ * <li>Filename - The name of the Product file to ingest.</li>
+ * <li>ProductType - The type of the Product to ingest.</li>
+ * <li>FileLocation - A full path pointer to directory containing the Product
+ * file to ingest.</li>
+ * </ul>
+ * 
+ * The {@link Ingester} supports overriding certain {@link Product} properties,
+ * including:
+ * 
+ * <ul>
+ * <li>Specification of <code>ProductStructure</code> parameter that will
+ * tell the {@link Ingester} whether or not the {@link Product} is a directory
+ * or a regular file.</li>
+ * <li>Specification of <code>ProductName</code> parameter that will tell the
+ * {@link Ingester} a name for the {@link Product} to use (default is using the
+ * specified {@link Metadata} field, <code>Filename</code>.</li>
+ * </ul>
+ * </p>.
+ */
+public class StdIngester implements Ingester, CoreMetKeys {
+
+    /* our log stream */
+    private final static Logger LOG = Logger.getLogger(StdIngester.class
+            .getName());
+
+    /* our file manager client */
+    private XmlRpcFileManagerClient fmClient = null;
+
+    /* client transfer service factory */
+    private String clientTransferServiceFactory = null;
+
+    public StdIngester(String transferService) {
+        this.clientTransferServiceFactory = transferService;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Ingester#ingest(java.net.URL,
+     *      java.io.File, org.apache.oodt.cas.metadata.MetExtractor,
+     *      java.io.File)
+     */
+    public String ingest(URL fmUrl, File prodFile, MetExtractor extractor,
+            File metConfFile) throws IngestException {
+        Metadata met = null;
+        try {
+            met = extractor.extractMetadata(prodFile, metConfFile);
+        } catch (MetExtractionException e) {
+            e.printStackTrace();
+            throw new IngestException("Met extraction exception on product: ["
+                    + prodFile + "]: Message: " + e.getMessage(), e);
+        }
+
+        return ingest(fmUrl, prodFile, met);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Ingester#ingest(java.net.URL,
+     *      java.util.List, org.apache.oodt.cas.metadata.MetExtractor,
+     *      java.io.File)
+     */
+    public void ingest(URL fmUrl, List<String> prodFiles, MetExtractor extractor,
+            File metConfFile) throws IngestException {
+        if (prodFiles != null && prodFiles.size() > 0) {
+            for (Iterator<String> i = prodFiles.iterator(); i.hasNext();) {
+                String prodFilePath = i.next();
+                String productID = ingest(fmUrl, new File(prodFilePath),
+                        extractor, metConfFile);
+                LOG.log(Level.INFO, "Product: [" + prodFilePath
+                        + "] ingested successfully! ID: [" + productID + "]");
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Ingester#ingest(java.net.URL,
+     *      java.io.File, org.apache.oodt.cas.metadata.Metadata)
+     */
+    public String ingest(URL fmUrl, File prodFile, Metadata met)
+            throws IngestException {
+        checkOrSetFileManager(fmUrl);
+        String productType = met.getMetadata(PRODUCT_TYPE);
+        String fileLocation = met.getMetadata(FILE_LOCATION);
+        String fileName = met.getMetadata(FILENAME);
+
+        if (!check(productType, PRODUCT_TYPE)
+                || !check(fileLocation, FILE_LOCATION)
+                || !check(fileName, FILENAME)) {
+            throw new IngestException("Must specify: " + PRODUCT_TYPE + " and "
+                    + FILENAME + "and " + FILE_LOCATION
+                    + " within metadata file. Cannot ingest product: ["
+                    + prodFile.getAbsolutePath() + "]");
+        }
+
+        // allow user to override default product name (Filename)
+        String productName = met.getMetadata(PRODUCT_NAME) != null ? met
+                .getMetadata(PRODUCT_NAME) : fileName;
+
+        // check to see if product structure was specified
+        String productStructure = met.getMetadata(PRODUCT_STRUCTURE);
+        if (productStructure == null) {
+            // try and guess the structure
+            if (prodFile.isDirectory()) {
+                productStructure = Product.STRUCTURE_HIERARCHICAL;
+            } else
+                productStructure = Product.STRUCTURE_FLAT;
+        }
+
+        // create the product
+        Product product = new Product();
+        product.setProductName(productName);
+        product.setProductStructure(productStructure);
+        product.setProductType(getProductType(productType));
+
+        List<String> references = new Vector<String>();
+        if (!fileLocation.endsWith("/")) {
+            fileLocation += "/";
+        }
+
+        String fullFilePath = fileLocation + fileName;
+
+        references.add(new File(fullFilePath).toURI().toString());
+
+        if (productStructure.equals(Product.STRUCTURE_HIERARCHICAL)) {
+            references.addAll(VersioningUtils.getURIsFromDir(new File(
+                    fullFilePath)));
+        }
+
+        // build refs and attach to product
+        VersioningUtils.addRefsFromUris(product, references);
+
+        LOG.log(Level.INFO, "StdIngester: ingesting product: " + PRODUCT_NAME
+                + ": [" + productName + "]: " + PRODUCT_TYPE + ": ["
+                + productType + "]: " + FILE_LOCATION + ": [" + fileLocation
+                + "]");
+
+        String productID = null;
+
+        try {
+            productID = fmClient.ingestProduct(product, met, true);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "exception ingesting product: ["
+                    + productName + "]: Message: " + e.getMessage());
+            throw new IngestException("exception ingesting product: ["
+                    + productName + "]: Message: " + e.getMessage());
+        }
+
+        return productID;
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Ingester#hasProduct(java.net.URL,
+     *      java.io.File)
+     */
+    public boolean hasProduct(URL fmUrl, File prodFile) throws CatalogException{
+        return hasProduct(fmUrl, prodFile.getName());
+    }
+
+    private boolean check(String property, String propName) {
+        if (property == null) {
+            LOG.log(Level.WARNING, "Property: [" + propName
+                    + "] is not provided");
+            return false;
+        } else
+            return true;
+    }
+
+    private void checkOrSetFileManager(URL url) {
+        if (this.fmClient != null && this.fmClient.getFileManagerUrl() != null) {
+
+            if (!this.fmClient.getFileManagerUrl().equals(url)) {
+                setFileManager(url);
+            }
+        } else {
+            setFileManager(url);
+        }
+    }
+
+    private void setFileManager(URL url) {
+        try {
+            fmClient = new XmlRpcFileManagerClient(url);
+            LOG.log(Level.INFO, "StdIngester: connected to file manager: ["
+                    + url + "]");
+            // instantiate the client transfer object
+            // the crawler will have the client perform the transfer
+            fmClient
+                    .setDataTransfer(GenericFileManagerObjectFactory
+                            .getDataTransferServiceFromFactory(this.clientTransferServiceFactory));
+        } catch (ConnectionException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Unable to connect to file manager: [" + url
+                    + "]: message: " + e.getMessage());
+        }
+
+    }
+
+    private ProductType getProductType(String productTypeName) {
+        ProductType type = null;
+
+        try {
+            type = fmClient.getProductTypeByName(productTypeName);
+        } catch (RepositoryManagerException e) {
+            LOG.log(Level.WARNING, "Unable to obtain product type: ["
+                    + productTypeName + "] from File Manager at: ["
+                    + fmClient.getFileManagerUrl() + "]: Message: "
+                    + e.getMessage());
+        }
+
+        return type;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.ingest.Ingester#hasProduct(java.net.URL,
+     *      java.lang.String)
+     */
+    public boolean hasProduct(URL fmUrl, String productName) throws CatalogException{
+        checkOrSetFileManager(fmUrl);
+        try {
+            return fmClient.hasProduct(productName);
+        } catch (CatalogException e) {
+            LOG.log(Level.WARNING,
+                    "Unable to check for existance of product: [" + productName
+                            + "]: Message: " + e.getMessage(), e);
+            throw e;
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/CoreMetKeys.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/CoreMetKeys.java
new file mode 100644
index 0000000..edd14d5
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/CoreMetKeys.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.metadata;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public interface CoreMetKeys {
+  
+  public static final String PRODUCT_NAME = "ProductName";
+  
+  public static final String PRODUCT_ID = "ProductId";
+  
+  public static final String PRODUCT_RECEVIED_TIME = "ProductReceivedTime";
+  
+  public static final String FILE_LOCATION = "FileLocation";
+  
+  public static final String FILENAME = "Filename";
+
+  public static final String FILE_SIZE = "FileSize";
+
+  public static final String PRODUCT_TYPE = "ProductType";
+  
+  public static final String PRODUCT_STRUCTURE = "ProductStructure";
+
+  public static final String MIME_TYPE = "MimeType";
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/ProductMetKeys.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/ProductMetKeys.java
new file mode 100644
index 0000000..05e59b3
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/ProductMetKeys.java
@@ -0,0 +1,54 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.metadata;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+/**
+ * 
+ * Met key field names used to augment {@link Product} {@link Metadata} in
+ * {@link XmlRpcFileManagerClient#getMetadata(org.apache.oodt.cas.filemgr.structs.Product)}
+ * and in
+ * {@link XmlRpcFileManagerClient#getReducedMetadata(org.apache.oodt.cas.filemgr.structs.Product, java.util.List)}
+ * .
+ * 
+ * @see http://issues.apache.org/jira/browse/OODT-72
+ * 
+ */
+public interface ProductMetKeys {
+
+  public static final String PRODUCT_ID = "ProductId";
+
+  public static final String PRODUCT_NAME = "ProductName";
+
+  public static final String PRODUCT_STRUCTURE = "ProductStructure";
+
+  public static final String PRODUCT_TRANSFER_STATUS = "ProductTransferStatus";
+
+  public static final String PRODUCT_ROOT_REFERENCE = "ProductRootReference";
+
+  public static final String PRODUCT_DATASTORE_REFS = "ProductDataStoreReferences";
+
+  public static final String PRODUCT_ORIG_REFS = "ProductOrigReferences";
+
+  public static final String PRODUCT_MIME_TYPES = "ProductMimeType";
+
+  public static final String PRODUCT_FILE_SIZES = "ProductFileSize";
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/AbstractFilemgrMetExtractor.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/AbstractFilemgrMetExtractor.java
new file mode 100644
index 0000000..b60f556
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/AbstractFilemgrMetExtractor.java
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.metadata.extractors;
+
+//JDK imports
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An abstract base class providing functionality to any sub-classing
+ * {@link FilemgrMetExtractor}s.
+ * </p>.
+ */
+public abstract class AbstractFilemgrMetExtractor implements
+        FilemgrMetExtractor {
+
+    protected Properties configuration;
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.metadata.extractors.
+     *      FilemgrMetExtractor#extractMetadata(org.apache.oodt.cas.filemgr.structs.Product,
+     *      org.apache.oodt.cas.metadata.Metadata)
+     */
+    public Metadata extractMetadata(Product product, Metadata met)
+            throws MetExtractionException {
+        validateProduct(product, met);
+        return doExtract(product, met);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.metadata.extractors.FilemgrMetExtractor#configure(java.util.Properties)
+     */
+    public void configure(Properties props) {
+        this.configuration = props;
+        doConfigure();
+    }
+
+    public abstract Metadata doExtract(Product product, Metadata met)
+            throws MetExtractionException;
+
+    public abstract void doConfigure();
+
+    protected void validateProduct(Product product, Metadata met)
+            throws MetExtractionException {
+        if (product.getProductType() == null
+                || (product.getProductType() != null && (product
+                        .getProductType().getName() == null || (product
+                        .getProductType().getName() != null && product
+                        .getProductType().getName().equals(""))))) {
+            throw new MetExtractionException("Product Type undefined");
+        }
+
+        if (product.getProductReferences() == null
+                || (product.getProductReferences() != null && product
+                        .getProductReferences().size() == 0)) {
+            throw new MetExtractionException("Product references undefined");
+        }
+
+        /*
+         * if (met == null || (met != null && (met.getHashtable() == null ||
+         * (met .getHashtable() != null && met.getHashtable().keySet() .size() ==
+         * 0)))) { throw new MetExtractionException("Metadata undefined"); }
+         */
+
+    }
+
+    protected void addMetadataIfUndefined(Metadata origMet, Metadata destMet,
+            String key, String val) {
+        if (!origMet.containsKey(key)) {
+            destMet.addMetadata(key, val);
+        }
+    }
+
+    protected void merge(Metadata src, Metadata dest) {
+        dest.addMetadata(src.getHashtable());
+    }
+
+    protected File getProductFile(Product product)
+            throws MetExtractionException {
+        File prodFile = null;
+
+        if (product.getProductStructure()
+                .equals(Product.STRUCTURE_HIERARCHICAL)) {
+            try {
+                prodFile = new File(getRootRefPath(product
+                        .getProductReferences(), product.getProductType()
+                        .getProductRepositoryPath()));
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new MetExtractionException("URI exception parsing: ["
+                        + product.getRootRef().getOrigReference() + "]");
+            }
+        } else {
+            try {
+                prodFile = new File(new URI(((Reference) product
+                        .getProductReferences().get(0)).getOrigReference()));
+            } catch (Exception e) {
+                throw new MetExtractionException("URI exception parsing: ["
+                        + ((Reference) product.getProductReferences().get(0))
+                                .getOrigReference() + "]");
+
+            }
+        }
+
+        return prodFile;
+    }
+
+    protected String getRootRefPath(List<Reference> refs,
+            String productTypeRepoPath) throws URISyntaxException {
+        return new File(new URI(refs.get(0)
+                .getOrigReference())).getAbsolutePath();
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/CoreMetExtractor.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/CoreMetExtractor.java
new file mode 100644
index 0000000..e58af79
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/CoreMetExtractor.java
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.metadata.extractors;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.oodt.commons.util.DateConvert;
+
+//JDK imports
+import java.io.File;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The core {@link FilemgrMetExtractor} providing the {@link CoreMetKeys}
+ * for this {@link Product}.
+ * </p>.
+ */
+public class CoreMetExtractor extends AbstractFilemgrMetExtractor implements
+        CoreMetKeys {
+
+    private boolean namespaceAware = false;
+
+    private String elementNs;
+
+    private static final String nsSeparator = ".";
+
+    private List<String> nsReplaceElements;
+
+    public CoreMetExtractor() {
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.metadata.extractors.
+     *      AbstractFilemgrMetExtractor#doExtract(org.apache.oodt.cas.filemgr.structs.Product,
+     *      org.apache.oodt.cas.metadata.Metadata)
+     */
+    public Metadata doExtract(Product product, Metadata met)
+            throws MetExtractionException {
+        Metadata extractMet = new Metadata();
+        /* copy through original metadata */
+        merge(met, extractMet);
+        File prodFile = null;
+        if (!product.getProductStructure().equals(Product.STRUCTURE_STREAM))
+        {
+            prodFile = getProductFile(product);
+        }
+        //GUID used when no file is associated with product i.e. stream
+        String guid=UUID.randomUUID().toString();
+        extractMet
+                .addMetadata(isNsReplace(PRODUCT_ID) ? elementNs + nsSeparator
+                        + PRODUCT_ID : PRODUCT_ID, product.getProductId());
+        addMetadataIfUndefined(met, extractMet,
+                isNsReplace(FILENAME) ? elementNs + nsSeparator + FILENAME
+                        : FILENAME, (prodFile == null)?guid:prodFile.getName());
+        addMetadataIfUndefined(met, extractMet,
+                isNsReplace(FILE_LOCATION) ? elementNs + nsSeparator
+                        + FILE_LOCATION : FILE_LOCATION, (prodFile==null)?guid:prodFile
+                        .getParentFile().getAbsolutePath());
+        addMetadataIfUndefined(met, extractMet,
+                isNsReplace(PRODUCT_NAME) ? elementNs + nsSeparator
+                        + PRODUCT_NAME : PRODUCT_NAME, product.getProductName());
+        addMetadataIfUndefined(met, extractMet,
+                isNsReplace(PRODUCT_STRUCTURE) ? elementNs + nsSeparator
+                        + PRODUCT_STRUCTURE : PRODUCT_STRUCTURE, product
+                        .getProductStructure());
+        extractMet.addMetadata(isNsReplace(PRODUCT_RECEVIED_TIME) ? elementNs
+                + nsSeparator + PRODUCT_RECEVIED_TIME : PRODUCT_RECEVIED_TIME,
+                DateConvert.isoFormat(new Date()));
+        addMetadataIfUndefined(met, extractMet,
+                isNsReplace(PRODUCT_TYPE) ? elementNs + nsSeparator
+                        + PRODUCT_TYPE : PRODUCT_TYPE, product.getProductType()
+                        .getName());
+
+        return extractMet;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.metadata.extractors.AbstractFilemgrMetExtractor#doConfigure()
+     */
+    public void doConfigure() {
+        if (this.configuration != null) {
+            namespaceAware = Boolean.valueOf(
+                    this.configuration.getProperty("nsAware")).booleanValue();
+
+            if (namespaceAware) {
+                elementNs = this.configuration.getProperty("elementNs");
+                String replaceElemStr = this.configuration
+                        .getProperty("elements");
+                nsReplaceElements = Arrays.asList(replaceElemStr.split(","));
+            }
+        }
+    }
+
+    private boolean isNsReplace(String elemName) {
+        if (this.nsReplaceElements == null
+                || (this.nsReplaceElements != null && this.nsReplaceElements
+                        .size() == 0)) {
+            return false;
+        }
+
+        return namespaceAware && this.nsReplaceElements.contains(elemName);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/FilemgrMetExtractor.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/FilemgrMetExtractor.java
new file mode 100644
index 0000000..64f1e87
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/FilemgrMetExtractor.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.metadata.extractors;
+
+//JDK imports
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * The core interface for {@link Metadata} extraction on the File Manager server
+ * side.
+ * </p>.
+ */
+public interface FilemgrMetExtractor {
+
+    /**
+     * Extracts {@link Metadata} from the given {@link Product}.
+     * 
+     * @param product
+     *            The given {@link Product}.
+     * @param met
+     *            The original {@link Metadata} provided during ingestion.
+     * @return Extracted {@link Metadata} derived from the existing
+     *         {@link Metadata} and {@link Product} provided.
+     */
+    public Metadata extractMetadata(Product product, Metadata met)
+            throws MetExtractionException;
+
+    /**
+     * Sets the configuration for this Metadata extractor.
+     * 
+     * @param props
+     *            The {@link Properties} object to configure this Metadata
+     *            extractor with.
+     */
+    public void configure(Properties props);
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/DateTimeExpandMetExtractor.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/DateTimeExpandMetExtractor.java
new file mode 100644
index 0000000..e95594a
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/DateTimeExpandMetExtractor.java
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.metadata.extractors.examples;
+
+// OODT imports
+import org.apache.oodt.cas.filemgr.metadata.extractors.AbstractFilemgrMetExtractor;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+// Google imports
+import com.google.common.base.Strings;
+
+/**
+ * Expands a given metadata date time field out into multiple metadata fields (i.e. year, month,
+ * day, hour, minute, and second).
+ * 
+ * @author bfoster@apache.org (Brian Foster)
+ */
+public class DateTimeExpandMetExtractor extends AbstractFilemgrMetExtractor {
+
+  private static final String FULL_DATE_TIME_KEY = "FullDateTimeKey";
+  private static final String FULL_DATE_TIME_FORMAT = "FullDateTimeFormat";
+
+  private static final String YEAR_KEY = "YearKey";
+  private static final String MONTH_KEY = "MonthKey";
+  private static final String DAY_KEY = "DayKey";
+  private static final String HOUR_KEY = "HourKey";
+  private static final String MINUTE_KEY = "MinuteKey";
+  private static final String SECOND_KEY = "SecondKey";
+
+  private String fullDateTimeKey;
+  private String fullDateTimeFormat;
+  private String yearKey;
+  private String monthKey;
+  private String dayKey;
+  private String hourKey;
+  private String minuteKey;
+  private String secondKey;
+
+  @Override
+  public void doConfigure() {
+    fullDateTimeKey = getKey(FULL_DATE_TIME_KEY);
+    fullDateTimeFormat = getKey(FULL_DATE_TIME_FORMAT);
+    yearKey = getKey(YEAR_KEY);
+    monthKey = getKey(MONTH_KEY);
+    dayKey = getKey(DAY_KEY);
+    hourKey = getKey(HOUR_KEY);
+    minuteKey = getKey(MINUTE_KEY);
+    secondKey = getKey(SECOND_KEY);
+  }
+
+  @Override
+  public Metadata doExtract(Product product, Metadata metadata) throws MetExtractionException {
+    String fullDateTime = getFullDateTime(metadata);
+
+    createDateField(metadata, yearKey, fullDateTime, fullDateTimeFormat, "yyyy");
+    createDateField(metadata, monthKey, fullDateTime, fullDateTimeFormat, "MM");
+    createDateField(metadata, dayKey, fullDateTime, fullDateTimeFormat, "dd");
+    createDateField(metadata, hourKey, fullDateTime, fullDateTimeFormat, "HH");
+    createDateField(metadata, minuteKey, fullDateTime, fullDateTimeFormat, "mm");
+    createDateField(metadata, secondKey, fullDateTime, fullDateTimeFormat, "ss");
+    return metadata;
+  }
+
+  private String getKey(String key) {
+    if (configuration.containsKey(key)) {
+      return configuration.getProperty(key);
+    } else {
+      return null;
+    }
+  }
+
+  private String getFullDateTime(Metadata metadata)
+       throws MetExtractionException {
+    if (!Strings.isNullOrEmpty(fullDateTimeKey)) {
+      return metadata.getMetadata(fullDateTimeKey);
+    } else {
+      throw new MetExtractionException("Failed to find DateTimeKey " + fullDateTimeKey);
+    }
+  }
+
+  private void createDateField(Metadata metadata, String fieldKey, String fullDateTime,
+      String fullDateTimeFormat, String fieldFormat) throws MetExtractionException {
+    if (!Strings.isNullOrEmpty(fieldKey)) {
+      try {
+        metadata.addMetadata(fieldKey, PathUtils.doDynamicReplacement(String.format(
+            "[FORMAT(%s,%s,%s)]", fullDateTimeFormat, fullDateTime, fieldFormat)));
+      } catch (Exception e) {
+        throw new MetExtractionException(String.format(
+            "Failed to create field for key %s from fullDateTime %s and fullDateTimeFormat %s",
+            fieldKey, fullDateTime, fullDateTimeFormat), e);
+      }
+    }
+  }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/FilenameRegexMetExtractor.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/FilenameRegexMetExtractor.java
new file mode 100644
index 0000000..c89af63
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/FilenameRegexMetExtractor.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.metadata.extractors.examples;
+
+//JDK imports
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.extractors.AbstractFilemgrMetExtractor;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+/**
+ * @author nchung
+ * @version $Revision$
+ * 
+ * <p>
+ * Extracts {@link Metadata} from a {@link Product} filename that matches 
+ * a provided regular expression.
+ * </p>.
+ */
+public class FilenameRegexMetExtractor extends AbstractFilemgrMetExtractor {
+
+   private String filenamePattern;
+   private List<String> metadataKeys;
+
+   public void doConfigure() {
+      if (this.configuration != null) {
+         this.filenamePattern = this.configuration
+               .getProperty("filenamePattern");
+         this.metadataKeys = Arrays.asList(this.configuration.getProperty(
+               "metadataKeys").split(","));
+      }
+   }
+
+   public Metadata doExtract(Product product, Metadata met)
+         throws MetExtractionException {
+      Metadata extractMet = new Metadata();
+      merge(met, extractMet);
+      
+      Pattern pattern = Pattern.compile(this.filenamePattern);
+      Matcher matcher = pattern.matcher(getProductFile(product).getName());
+      if (matcher.matches()) {
+         for (int i = 0; i < this.metadataKeys.size(); i++) {
+            String key = this.metadataKeys.get(i);
+            String value = matcher.group(i + 1);
+            extractMet.addMetadata(key, value);
+         }
+      } else {
+         throw new MetExtractionException("Filename does not conform to the pattern "
+               + this.filenamePattern);
+      }
+      return extractMet;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/FinalFileLocationExtractor.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/FinalFileLocationExtractor.java
new file mode 100644
index 0000000..7e786e8
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/FinalFileLocationExtractor.java
@@ -0,0 +1,112 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.metadata.extractors.examples;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.metadata.extractors.AbstractFilemgrMetExtractor;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.filemgr.util.GenericFileManagerObjectFactory;
+import org.apache.oodt.cas.filemgr.versioning.Versioner;
+import org.apache.oodt.cas.filemgr.versioning.VersioningUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+/**
+ * 
+ * Extracts the final <code>FILE_LOCATION</code> met field from the underlying
+ * {@link Product} and sets it appropriately in the {@link Product}
+ * {@link Metadata}.
+ * 
+ */
+public class FinalFileLocationExtractor extends AbstractFilemgrMetExtractor
+    implements CoreMetKeys {
+
+  private boolean replaceLocation;
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.metadata.extractors.AbstractFilemgrMetExtractor
+   * #doConfigure()
+   */
+  @Override
+  public void doConfigure() {
+    if (this.configuration != null) {
+      this.replaceLocation = Boolean.parseBoolean(this.configuration
+          .getProperty("replace"));
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.metadata.extractors.AbstractFilemgrMetExtractor
+   * #doExtract(org.apache.oodt.cas.filemgr.structs.Product,
+   * org.apache.oodt.cas.metadata.Metadata)
+   */
+  @Override
+  public Metadata doExtract(Product product, Metadata met)
+      throws MetExtractionException {
+    Metadata extractMet = new Metadata();
+    merge(met, extractMet);
+    // get the Versioner
+    Versioner versioner = GenericFileManagerObjectFactory
+        .getVersionerFromClassName(product.getProductType().getVersioner());
+    try {
+      versioner.createDataStoreReferences(product, met);
+    } catch (VersioningException e) {
+      throw new MetExtractionException(
+          "Unable to generate final FileLocation: Reason: " + e.getMessage());
+    }
+
+    Reference r = product.getProductReferences().get(0);
+    String finalLocation = VersioningUtils.getAbsolutePathFromUri(r
+        .getDataStoreReference());
+    if (this.replaceLocation) {
+      extractMet.replaceMetadata(FILE_LOCATION,
+          new File(finalLocation).getParent());
+    } else {
+      extractMet
+          .addMetadata(FILE_LOCATION, new File(finalLocation).getParent());
+    }
+
+    this.scrubRefs(product);
+
+    return extractMet;
+
+  }
+
+  private void scrubRefs(Product p) {
+    if (p.getProductReferences() == null)
+      return;
+
+    for (Reference r : p.getProductReferences()) {
+      r.setDataStoreReference("");
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/MimeTypeExtractor.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/MimeTypeExtractor.java
new file mode 100644
index 0000000..83665f0
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/MimeTypeExtractor.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.metadata.extractors.examples;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.extractors.AbstractFilemgrMetExtractor;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+//OODT static imports
+import static org.apache.oodt.cas.filemgr.metadata.CoreMetKeys.*;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An example {@link FilemgrMetExtractor} to extract out a Product's 
+ * Mime Type.
+ * </p>.
+ */
+public class MimeTypeExtractor extends AbstractFilemgrMetExtractor {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.metadata.extractors.AbstractFilemgrMetExtractor#doConfigure()
+     */
+    public void doConfigure() {
+        // TODO Auto-generated method stub
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.metadata.extractors.AbstractFilemgrMetExtractor#doExtract(org.apache.oodt.cas.filemgr.structs.Product,
+     *      org.apache.oodt.cas.metadata.Metadata)
+     */
+    public Metadata doExtract(Product product, Metadata met)
+            throws MetExtractionException {
+        Metadata extractMet = new Metadata();
+        merge(met, extractMet);
+
+        if (product.getProductStructure().equals(Product.STRUCTURE_FLAT)) {
+            Reference prodRef = (Reference) product.getProductReferences().get(
+                    0);
+            /*Reference mimeRef = new Reference(prodRef.getOrigReference(),
+                    prodRef.getDataStoreReference(), prodRef.getFileSize());*/
+
+            extractMet.addMetadata(MIME_TYPE, prodRef.getMimeType().getName());
+            extractMet.addMetadata(MIME_TYPE, prodRef.getMimeType()
+                    .getType().getType());
+            extractMet.addMetadata(MIME_TYPE, prodRef.getMimeType()
+                    .getType().getSubtype());
+        }
+
+        return extractMet;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/DataSourceRepositoryManager.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/DataSourceRepositoryManager.java
new file mode 100644
index 0000000..6769469
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/DataSourceRepositoryManager.java
@@ -0,0 +1,532 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.repository;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.util.DbStructFactory;
+
+//JDK imports
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.sql.DataSource;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * An implementation of the {@link RepositoryManager} interface that is backed
+ * by a {@link DataSource} for storing and retreiving {@link Product} policy in
+ * the form of {@link ProductType}s.
+ * </p>
+ * 
+ */
+public class DataSourceRepositoryManager implements RepositoryManager {
+
+    /* our sql data source */
+    private DataSource dataSource = null;
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(DataSourceRepositoryManager.class
+            .getName());
+
+    /**
+     * 
+     * <p>
+     * Default Constructor
+     * </p>.
+     * 
+     * @param ds
+     *            The DataSource to initialize this repository manager with.
+     */
+    public DataSourceRepositoryManager(DataSource ds) {
+        this.dataSource = ds;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManager#addProductType(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public synchronized void addProductType(ProductType productType)
+            throws RepositoryManagerException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String addProductTypeSql = "INSERT INTO product_types (product_type_name, product_type_description, product_type_repository_path, product_type_versioner_class) "
+                    + "VALUES ('"
+                    + productType.getName()
+                    + "', '"
+                    + productType.getDescription()
+                    + "', '"
+                    + productType.getProductRepositoryPath()
+                    + "', '"
+                    + productType.getVersioner() + "')";
+
+            LOG.log(Level.FINE, "addProductType: Executing: "
+                    + addProductTypeSql);
+            statement.execute(addProductTypeSql);
+
+            String productTypeId = new String();
+            String getProductTypeIdSql = "SELECT MAX(product_type_id) AS max_id FROM product_types";
+
+            rs = statement.executeQuery(getProductTypeIdSql);
+
+            while (rs.next()) {
+                productTypeId = String.valueOf(rs.getInt("max_id"));
+            }
+
+            productType.setProductTypeId(productTypeId);
+
+            // create the references table
+            String createRefSql = "CREATE TABLE product_reference_"
+                    + productTypeId
+                    + " (product_id int NOT NULL, product_orig_reference varchar(255), product_datastore_reference varchar(255))";
+            LOG.log(Level.FINE, "addProductType: Executing: " + createRefSql);
+            statement.execute(createRefSql);
+
+            // create the metadata table
+            String createMetaSql = "CREATE TABLE product_metadata_"
+                    + productTypeId
+                    + " (product_id int NOT NULL, element_id int NOT NULL, metadata_value varchar(2000) NOT NULL)";
+            LOG.log(Level.FINE, "addProductType: Executing: " + createMetaSql);
+            statement.execute(createMetaSql);
+            conn.commit();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception adding product type. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback addProductType transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new RepositoryManagerException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManager#modifyProductType(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public synchronized void modifyProductType(ProductType productType)
+            throws RepositoryManagerException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String modifyProductTypeSql = "UPDATE product_types SET product_type_name='"
+                    + productType.getName()
+                    + "', product_type_description='"
+                    + productType.getDescription()
+                    + "', "
+                    + "product_type_versioner_class='"
+                    + productType.getVersioner()
+                    + "', product_type_repository_path='"
+                    + productType.getProductRepositoryPath()
+                    + "' "
+                    + "WHERE product_type_id = "
+                    + productType.getProductTypeId();
+
+            LOG.log(Level.FINE, "modifyProductType: Executing: "
+                    + modifyProductTypeSql);
+            statement.execute(modifyProductTypeSql);
+            conn.commit();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception modifying product type. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback modifyProductType transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new RepositoryManagerException(e.getMessage());
+        } finally {
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManager#removeProductType(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public void removeProductType(ProductType productType)
+            throws RepositoryManagerException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String deleteProductTypeSql = "DELETE FROM product_types WHERE product_type_id = "
+                    + productType.getProductTypeId();
+
+            LOG.log(Level.FINE, "removeProductType: Executing: "
+                    + deleteProductTypeSql);
+            statement.execute(deleteProductTypeSql);
+
+            // TODO: Decide if it makes sense to delete the references table
+            // and the metadata table here. For now, we won't because maybe
+            // they'll just want to remove the ability to deal with this product
+            // type
+            // rather than remove all of the metdata and references for the
+            // products with it
+            conn.commit();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception removing product type. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback removeProductType transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new RepositoryManagerException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManager#getProductTypeById(java.lang.String)
+     */
+    public ProductType getProductTypeById(String productTypeId)
+            throws RepositoryManagerException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        ProductType productType = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getProductTypeSql = "SELECT * from product_types WHERE product_type_id = "
+                    + productTypeId;
+
+            LOG.log(Level.FINE, "getProductTypeById: Executing: "
+                    + getProductTypeSql);
+            rs = statement.executeQuery(getProductTypeSql);
+
+            while (rs.next()) {
+                productType = DbStructFactory.getProductType(rs);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting product type. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getProductTypeById transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new RepositoryManagerException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return productType;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManager#getProductTypeByName(java.lang.String)
+     */
+    public ProductType getProductTypeByName(String productTypeName)
+            throws RepositoryManagerException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        ProductType productType = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getProductTypeSql = "SELECT * from product_types WHERE product_type_name = '"
+                    + productTypeName + "'";
+
+            LOG.log(Level.FINE, "getProductTypeByName: Executing: "
+                    + getProductTypeSql);
+            rs = statement.executeQuery(getProductTypeSql);
+
+            while (rs.next()) {
+                productType = DbStructFactory.getProductType(rs);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting product type. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getProductTypeByName transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new RepositoryManagerException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return productType;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManager#getProductTypes()
+     */
+    public List<ProductType> getProductTypes() throws RepositoryManagerException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        List<ProductType> productTypes = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getProductTypeSql = "SELECT * from product_types";
+
+            LOG.log(Level.FINE, "getProductTypes: Executing: "
+                    + getProductTypeSql);
+            rs = statement.executeQuery(getProductTypeSql);
+
+            productTypes = new Vector<ProductType>();
+            while (rs.next()) {
+                ProductType productType = DbStructFactory.getProductType(rs);
+                productTypes.add(productType);
+            }
+
+            if (productTypes.size() == 0) {
+                productTypes = null;
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting product types. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getProductTypes transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new RepositoryManagerException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return productTypes;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/DataSourceRepositoryManagerFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/DataSourceRepositoryManagerFactory.java
new file mode 100644
index 0000000..d369bc9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/DataSourceRepositoryManagerFactory.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.repository;
+
+//OODT imports
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+
+//JDK imports
+import javax.sql.DataSource;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory for creating {@link DataSourceRepositoryManager}s.
+ * </p>
+ * 
+ */
+public class DataSourceRepositoryManagerFactory implements
+        RepositoryManagerFactory {
+
+    /* our data source */
+    private DataSource dataSource = null;
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     */
+    public DataSourceRepositoryManagerFactory() throws Exception {
+        String jdbcUrl = null, user = null, pass = null, driver = null;
+
+        jdbcUrl = System
+                .getProperty("org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.url");
+        user = System
+                .getProperty("org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.user");
+        pass = System
+                .getProperty("org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.pass");
+        driver = System
+                .getProperty("org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.driver");
+
+        dataSource = DatabaseConnectionBuilder.buildDataSource(user, pass,
+                driver, jdbcUrl);
+    }
+
+    /**
+     * <p>
+     * Constructs a RepositoryManager from the given {@link DataSource}.
+     * </p>
+     * 
+     * @param ds
+     *            The DataSource to construct the RepositoryManager from.
+     */
+    public DataSourceRepositoryManagerFactory(DataSource ds) {
+        dataSource = ds;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManagerFactory#createRepositoryManager()
+     */
+    public RepositoryManager createRepositoryManager() {
+        return new DataSourceRepositoryManager(dataSource);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/RepositoryManager.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/RepositoryManager.java
new file mode 100644
index 0000000..e05dd9e
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/RepositoryManager.java
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.repository;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+
+//JDK imports
+import java.util.List;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * A Repository Manager is an extension point that is responsible for managing
+ * {@link ProductType} information which boils down to policy information about
+ * {@link Product}s that are ingested into the File Manager. This includes
+ * information such as the root repository path for a product type, what type of
+ * URI generation scheme to apply, etc.
+ * </p>
+ * 
+ */
+public interface RepositoryManager {
+
+    /* extension point ID */
+    public static String X_POINT_ID = RepositoryManager.class.getName();
+
+    /**
+     * <p>
+     * Adds a ProductType to the RepositoryManager.
+     * </p>
+     * 
+     * @param productType
+     *            The {@link ProductType} to add.
+     * @throws RepositoryManagerException
+     */
+    public void addProductType(ProductType productType)
+            throws RepositoryManagerException;
+
+    /**
+     * <p>
+     * Modifies a ProductType in the RepositoryManager with the specified ID
+     * field of the <code>productType</code>.
+     * </p>
+     * 
+     * @param productType
+     *            The new {@link ProductType} information.
+     * @throws RepositoryManagerException
+     *             If any error occurs.
+     */
+    public void modifyProductType(ProductType productType)
+            throws RepositoryManagerException;
+
+    /**
+     * <p>
+     * Removes a ProductType from the RepositoryManager
+     * </p>.
+     * 
+     * @param productType
+     *            The productType to remove.
+     * @throws RepositoryManagerException
+     *             If any error occurs during the removal.
+     */
+    public void removeProductType(ProductType productType)
+            throws RepositoryManagerException;
+
+    /**
+     * <p>
+     * Gets a {link ProductType} from the RepositoryManager identified by its
+     * <code>productTypeId</code>.
+     * </p>
+     * 
+     * @param productTypeId
+     *            The ID of the ProductType to retrieve.
+     * @return The {@link ProductType} corresponding to the specified
+     *         <code>productTypeId</code>.
+     * @throws RepositoryManagerException
+     *             If any error occurs.
+     */
+    public ProductType getProductTypeById(String productTypeId)
+            throws RepositoryManagerException;
+
+    /**
+     * <p>
+     * Gets a {@link ProductType} specified by its <code>productTypeName</code>,
+     * from the RepositoryManager.
+     * </p>
+     * 
+     * @param productTypeName
+     *            The name of the ProductType to get.
+     * @return A {@link ProductType}, with the specified name.
+     * @throws RepositoryManagerException
+     *             If any error occurs.
+     */
+    public ProductType getProductTypeByName(String productTypeName)
+            throws RepositoryManagerException;
+
+    /**
+     * <p>
+     * Gets all the {@link ProductType}s from the repository.
+     * </p>
+     * 
+     * @return A {@link List} of {@link ProductType}s from the repository.
+     * @throws RepositoryManagerException
+     *             If any error occurs.
+     */
+    public List<ProductType> getProductTypes() throws RepositoryManagerException;
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/RepositoryManagerFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/RepositoryManagerFactory.java
new file mode 100644
index 0000000..d533d5e
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/RepositoryManagerFactory.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.repository;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory interface for creating {@link RepositoryManager} objects.
+ * </p>
+ * 
+ */
+public interface RepositoryManagerFactory {
+
+    public RepositoryManager createRepositoryManager();
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/ScienceDataRepositoryManager.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/ScienceDataRepositoryManager.java
new file mode 100644
index 0000000..8d889fc
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/ScienceDataRepositoryManager.java
@@ -0,0 +1,350 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.repository;
+
+//JDK imports
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.sql.DataSource;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.repository.RepositoryManager;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.util.DbStructFactory;
+
+/**
+ * 
+ * Leverages the information in the {@link ScienceDataCatalog}'s dataset table
+ * to list out {@link ProductType}s.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ScienceDataRepositoryManager implements RepositoryManager {
+
+  private static final Logger LOG = Logger
+      .getLogger(ScienceDataRepositoryManager.class.getName());
+
+  private DataSource dataSource;
+
+  public ScienceDataRepositoryManager(DataSource dataSource) {
+    this.dataSource = dataSource;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.repository.RepositoryManager#addProductType
+   * (org.apache.oodt.cas.filemgr.structs.ProductType)
+   */
+  public void addProductType(ProductType productType)
+      throws RepositoryManagerException {
+    String sql = "INSERT INTO dataset (longName, shortName, description) VALUES ('"
+        + productType.getName()
+        + "', '"
+        + productType.getName()
+        + "', '"
+        + productType.getDescription() + "'";
+    Connection conn = null;
+    Statement statement = null;
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      statement.execute(sql);
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.repository.RepositoryManager#getProductTypeById
+   * (java.lang.String)
+   */
+  public ProductType getProductTypeById(String productTypeId)
+      throws RepositoryManagerException {
+    String sql = "SELECT dataset_id, shortName, longName, source, referenceURL, description from dataset WHERE dataset_id = "
+        + productTypeId;
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    ProductType productType = null;
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      LOG.log(Level.FINE, "Executing: [" + sql + "]");
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        productType = DbStructFactory.toScienceDataProductType(rs);
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+    return productType;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.repository.RepositoryManager#getProductTypeByName
+   * (java.lang.String)
+   */
+  public ProductType getProductTypeByName(String productTypeName)
+      throws RepositoryManagerException {
+    String sql = "SELECT dataset_id, shortName, longName, source, referenceURL, description from dataset WHERE shortName = '"
+        + productTypeName + "'";
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    ProductType productType = null;
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        productType = DbStructFactory.toScienceDataProductType(rs);
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+    return productType;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.repository.RepositoryManager#getProductTypes ()
+   */
+  public List<ProductType> getProductTypes() throws RepositoryManagerException {
+    String sql = "SELECT dataset_id, shortName, longName, source, referenceURL, description from dataset ORDER BY dataset_id DESC";
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    List<ProductType> productTypes = new Vector<ProductType>();
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        productTypes.add(DbStructFactory.toScienceDataProductType(rs));
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+    }
+
+    return productTypes;
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.repository.RepositoryManager#modifyProductType
+   * (org.apache.oodt.cas.filemgr.structs.ProductType)
+   */
+  public void modifyProductType(ProductType productType)
+      throws RepositoryManagerException {
+    String sql = "UPDATE dataset SET shortName='" + productType.getName()
+        + "',description='" + productType.getDescription()
+        + "' WHERE dataset_id = " + productType.getProductTypeId();
+
+    Connection conn = null;
+    Statement statement = null;
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      statement.execute(sql);
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.repository.RepositoryManager#removeProductType
+   * (org.apache.oodt.cas.filemgr.structs.ProductType)
+   */
+  public void removeProductType(ProductType productType)
+      throws RepositoryManagerException {
+    String sql = "DELETE FROM dataset WHERE dataset_id = "
+        + productType.getProductTypeId();
+
+    Connection conn = null;
+    Statement statement = null;
+
+    try {
+      conn = this.dataSource.getConnection();
+      statement = conn.createStatement();
+      statement.execute(sql);
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/ScienceDataRepositoryManagerFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/ScienceDataRepositoryManagerFactory.java
new file mode 100644
index 0000000..70a5c50
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/ScienceDataRepositoryManagerFactory.java
@@ -0,0 +1,72 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.repository;
+
+//JDK imports
+import javax.sql.DataSource;
+
+//OODT imports
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+import org.apache.oodt.cas.filemgr.repository.RepositoryManager;
+import org.apache.oodt.cas.filemgr.repository.RepositoryManagerFactory;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+/**
+ * 
+ * Constructs new {@link ScienceDataRepositoryManager}s.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ScienceDataRepositoryManagerFactory implements
+    RepositoryManagerFactory {
+
+  private DataSource dataSource;
+
+  public ScienceDataRepositoryManagerFactory() {
+    String jdbcUrl = null, user = null, pass = null, driver = null;
+
+    jdbcUrl = PathUtils
+        .replaceEnvVariables(System
+            .getProperty("org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.url"));
+    user = PathUtils
+        .replaceEnvVariables(System
+            .getProperty("org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.user"));
+    pass = PathUtils
+        .replaceEnvVariables(System
+            .getProperty("org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.pass"));
+    driver = PathUtils
+        .replaceEnvVariables(System
+            .getProperty("org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.driver"));
+
+    this.dataSource = DatabaseConnectionBuilder.buildDataSource(user, pass,
+        driver, jdbcUrl);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @seeorg.apache.oodt.oodt.cas.filemgr.repository.RepositoryManagerFactory#
+   * createRepositoryManager()
+   */
+  public RepositoryManager createRepositoryManager() {
+    return new ScienceDataRepositoryManager(this.dataSource);
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/XMLRepositoryManager.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/XMLRepositoryManager.java
new file mode 100644
index 0000000..4730e1d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/XMLRepositoryManager.java
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.repository;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.util.XmlStructFactory;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A {@link RepositoryManager} that manages {@link Product} policy based on an
+ * xml file called <code>product-types.xml</code>.
+ * </p>
+ * </p>
+ * 
+ */
+public class XMLRepositoryManager implements RepositoryManager {
+
+    /* URIs pointing to directories containing product-types.xml files */
+    private List<String> productTypeHomeUris = null;
+
+    /* our map of product types that the system knows about */
+    private HashMap<String, ProductType> productTypeMap = new HashMap<String, ProductType>();
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(XMLRepositoryManager.class
+            .getName());
+
+    /**
+     * 
+     */
+    public XMLRepositoryManager(List<String> uris) throws InstantiationException {
+        if (uris == null) {
+            throw new InstantiationException(
+                    "Attempt to construct XMLRepositoryManager with a NULL list of  product type home URIs!");
+        }
+
+        this.productTypeHomeUris = uris;
+        loadProductTypes(productTypeHomeUris);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManager#addProductType(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public void addProductType(ProductType productType)
+            throws RepositoryManagerException {
+        productTypeMap.put(productType.getProductTypeId(), productType);
+        saveProductTypes();
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManager#modifyProductType(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public void modifyProductType(ProductType productType)
+            throws RepositoryManagerException {
+        productTypeMap.put(productType.getProductTypeId(), productType);
+        saveProductTypes();
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManager#removeProductType(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public void removeProductType(ProductType productType)
+            throws RepositoryManagerException {
+        productTypeMap.remove(productType.getProductTypeId());
+        saveProductTypes();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManager#getProductTypeById(java.lang.String)
+     */
+    public ProductType getProductTypeById(String productTypeId)
+            throws RepositoryManagerException {
+        return (ProductType) productTypeMap.get(productTypeId);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManager#getProductTypeByName(java.lang.String)
+     */
+    public ProductType getProductTypeByName(String productTypeName)
+            throws RepositoryManagerException {
+        for (Iterator<String> i = productTypeMap.keySet().iterator(); i.hasNext();) {
+            String typeId = (String) i.next();
+            ProductType type = (ProductType) productTypeMap.get(typeId);
+            if (type.getName().equals(productTypeName)) {
+                return type;
+            }
+        }
+
+        LOG.log(Level.WARNING,
+                "XMLRepositoryManager: Unable to find product type: ["
+                        + productTypeName + "], returning null");
+
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManager#getProductTypes()
+     */
+    public List<ProductType> getProductTypes() throws RepositoryManagerException {
+        return Arrays.asList(productTypeMap.values().toArray(new ProductType[productTypeMap.values().size()]));
+    }
+
+    private void saveProductTypes() {
+        for (Iterator<String> i = productTypeHomeUris.iterator(); i.hasNext();) {
+            String dirUri = i.next();
+            File productTypeDir = null;
+
+            try {
+                productTypeDir = new File(new URI(dirUri));
+
+                if (!productTypeDir.isDirectory()) {
+                    LOG
+                            .log(
+                                    Level.WARNING,
+                                    "Product type directory: "
+                                            + dirUri
+                                            + " is not "
+                                            + "a directory: skipping product type saving to it.");
+                    continue;
+                }
+
+                String productTypeDirStr = productTypeDir.getAbsolutePath();
+                if (!productTypeDirStr.endsWith("/")) {
+                    productTypeDirStr += "/";
+                }
+
+                String productTypeXmlFile = productTypeDirStr
+                        + "product-types.xml";
+                XmlStructFactory.writeProductTypeXmlDocument(Arrays
+                        .asList(productTypeMap.values().toArray(new ProductType[productTypeMap.values().size()])),
+                        productTypeXmlFile);
+            } catch (URISyntaxException e) {
+                LOG.log(Level.WARNING,
+                        "URISyntaxException when saving product "
+                                + "type directory URI: " + dirUri
+                                + ": Skipping Product Type saving"
+                                + "for it: Message: " + e.getMessage());
+                continue;
+            }
+
+        }
+
+    }
+
+    private void loadProductTypes(List<String> dirUris) {
+        for (Iterator<String> i = dirUris.iterator(); i.hasNext();) {
+            File productTypeDir = null;
+            String dirUri = i.next();
+
+            try {
+                productTypeDir = new File(new URI(dirUri));
+
+                if (!productTypeDir.isDirectory()) {
+                    LOG
+                            .log(
+                                    Level.WARNING,
+                                    "Product type directory: "
+                                            + dirUri
+                                            + " is not "
+                                            + "a directory: skipping product type loading from it.");
+                    continue;
+                }
+
+                String productTypeDirStr = productTypeDir.getAbsolutePath();
+                if (!productTypeDirStr.endsWith("/")) {
+                    productTypeDirStr += "/";
+                }
+
+                String productTypeXmlFile = productTypeDirStr
+                        + "product-types.xml";
+                Document productTypeDoc = getDocumentRoot(productTypeXmlFile);
+
+                // now load the product types from it
+                if (productTypeDoc != null) {
+                    Element productTypeRoot = productTypeDoc
+                            .getDocumentElement();
+
+                    NodeList productTypeNodeList = productTypeRoot
+                            .getElementsByTagName("type");
+
+                    if (productTypeNodeList != null
+                            && productTypeNodeList.getLength() > 0) {
+                        for (int j = 0; j < productTypeNodeList.getLength(); j++) {
+                            Node productTypeNode = productTypeNodeList.item(j);
+                            ProductType type = XmlStructFactory
+                                    .getProductType(productTypeNode);
+                            LOG.log(Level.FINE,
+                                    "XMLRepositoryManager: found product type: ["
+                                            + type.getName() + "]");
+                            productTypeMap.put(type.getProductTypeId(), type);
+                        }
+                    }
+                }
+            } catch (URISyntaxException e) {
+                LOG.log(Level.WARNING,
+                        "URISyntaxException when loading product "
+                                + "type directory URI: " + dirUri
+                                + ": Skipping Product Type loading"
+                                + "for it: Message: " + e.getMessage());
+                continue;
+            }
+        }
+    }
+
+    private Document getDocumentRoot(String xmlFile) {
+        // open up the XML file
+        DocumentBuilderFactory factory = null;
+        DocumentBuilder parser = null;
+        Document document = null;
+        InputSource inputSource = null;
+
+        InputStream xmlInputStream = null;
+
+        try {
+            xmlInputStream = new File(xmlFile).toURI().toURL().openStream();
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when getting input stream from [" + xmlFile
+                            + "]: returning null document root");
+            return null;
+        }
+
+        inputSource = new InputSource(xmlInputStream);
+
+        try {
+            factory = DocumentBuilderFactory.newInstance();
+            parser = factory.newDocumentBuilder();
+            document = parser.parse(inputSource);
+        } catch (Exception e) {
+            LOG.warning("Unable to parse xml file [" + xmlFile + "]."
+                    + "Reason is [" + e + "]");
+            return null;
+        }
+
+        return document;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/XMLRepositoryManagerFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/XMLRepositoryManagerFactory.java
new file mode 100644
index 0000000..b2e952e
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/repository/XMLRepositoryManagerFactory.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.repository;
+
+//JDK imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory class for creating {@link XMLRepositoryManager} objects.
+ * </p>
+ * 
+ */
+public class XMLRepositoryManagerFactory implements RepositoryManagerFactory {
+
+    /* list of dir uris specifying file paths to productType directories */
+    private List<String> productTypeDirList = null;
+
+    /* our log stream */
+    private static final Logger LOG = Logger
+            .getLogger(XMLRepositoryManagerFactory.class.getName());
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     */
+    public XMLRepositoryManagerFactory() {
+        String productTypeDirUris = System
+                .getProperty("org.apache.oodt.cas.filemgr.repositorymgr.dirs");
+
+        if (productTypeDirUris != null) {
+            productTypeDirUris = PathUtils
+                    .replaceEnvVariables(productTypeDirUris);
+            String[] dirUris = productTypeDirUris.split(",");
+            productTypeDirList = Arrays.asList(dirUris);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.repository.RepositoryManagerFactory#createRepositoryManager()
+     */
+    public RepositoryManager createRepositoryManager() {
+        if (productTypeDirList != null) {
+            RepositoryManager repositoryManager = null;
+            try {
+                repositoryManager = new XMLRepositoryManager(productTypeDirList);
+            } catch (Exception ignore) {
+            }
+
+            return repositoryManager;
+        } else {
+            LOG
+                    .log(
+                            Level.WARNING,
+                            "Cannot create XML Repository Manager: no product type dir uris specified: value: "
+                                    + System
+                                            .getProperty("org.apache.oodt.cas.filemgr.repositorymgr.dirs"));
+            return null;
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/BooleanQueryCriteria.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/BooleanQueryCriteria.java
new file mode 100644
index 0000000..9b2d9f6
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/BooleanQueryCriteria.java
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.QueryFormulationException;
+
+/**
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Boolean Query Citeria that allows combination of a number of terms into a
+ * query with a boolean operator (AND, OR, NOT). The NOT operator can only be
+ * applied to one term.
+ * </p>
+ * 
+ */
+
+public class BooleanQueryCriteria extends QueryCriteria {
+
+    /**
+     * Constants
+     */
+    public static final int AND = 0;
+
+    public static final int OR = 1;
+
+    public static final int NOT = 2;
+
+    private static final long serialVersionUID = 4718948237682772671L;
+
+    private int operator;
+
+    private List<QueryCriteria> terms;
+
+    /**
+     * Default constructor. Uses the AND operator.
+     */
+    public BooleanQueryCriteria() {
+        operator = AND;
+        terms = new Vector<QueryCriteria>();
+    }
+
+    /**
+     * Boolean query constructor. This query is a boolean combination of term,
+     * range, and other boolean queries. The supported operators are AND, OR and
+     * NOT. Note that the NOT operator can only be used with one (1) term. This
+     * method throws the QueryFormulationException if more than one term is used
+     * with NOT.
+     * 
+     * @param terms
+     *            The criteria onto which to apply the boolean operator
+     * @param op
+     *            The boolean operator to be applied
+     */
+    public BooleanQueryCriteria(List<QueryCriteria> terms, int op)
+            throws QueryFormulationException {
+        operator = op;
+        if (op == NOT && terms.size() > 1) {
+            throw new QueryFormulationException(
+                    "BooleanQueryCriteria: NOT operator "
+                            + "cannot be applied to multiple terms");
+        } else {
+            this.terms = terms;
+        }
+    }
+
+    /**
+     * Method to add a term to the boolean query. Note that a NOT operator can
+     * only be applied to one term. Method throws the QueryFormulationException
+     * if this rule is violated.
+     * 
+     * @param t
+     *            Term to be added to the query
+     */
+    public void addTerm(QueryCriteria t) throws QueryFormulationException {
+        if (operator == NOT && !terms.isEmpty()) {
+            throw new QueryFormulationException(
+                    "BooleanQueryCriteria: NOT operator "
+                            + "cannot be applied to multiple terms");
+        } else {
+            terms.add(t);
+        }
+    }
+
+    /**
+     * Accessor method for the list of terms in the query.
+     * 
+     * @return The list of terms
+     */
+    public List<QueryCriteria> getTerms() {
+        return terms;
+    }
+
+    /**
+     * Mutator method for the boolean operator. Note that this method throws the
+     * QueryFormulationException if the operator is set to NOT and multiple
+     * terms are already defined.
+     * 
+     * @param op
+     *            Boolean operator
+     */
+    public void setOperator(int op) throws QueryFormulationException {
+        if (op == NOT && terms.size() > 1) {
+            throw new QueryFormulationException(
+                    "BooleanQueryCriteria: NOT operator "
+                            + "cannot be applied to multiple terms");
+        } else {
+            operator = op;
+        }
+    }
+
+    /**
+     * Accessor method for the boolean operator.
+     * 
+     * @return the boolean operator
+     */
+    public int getOperator() {
+        return operator;
+    }
+
+    /**
+     * Method is not used in this class...
+     */
+    public String getElementName() {
+        return null;
+    }
+
+    /**
+     * Method is not used in this class...
+     */
+    public void setElementName(String elementName) {
+    }
+
+    /**
+     * Method to convert the query to a string.
+     * 
+     * @return string equivement of the query
+     */
+    public String toString() {
+        String query = new String();
+        if (operator == AND)
+            query += "AND(";
+        else if (operator == OR)
+            query += "OR(";
+        else
+            query += "NOT(";
+
+        for (int i = 0; i < terms.size(); i++) {
+            query += ((QueryCriteria) terms.get(i)).toString();
+            if (i < (terms.size() - 1))
+                query += ", ";
+        }
+        query += ")";
+        return query;
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/Element.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/Element.java
new file mode 100644
index 0000000..01fc620
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/Element.java
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+import org.apache.oodt.cas.filemgr.structs.type.TypeHandler;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A metadata element.
+ * </p>
+ * 
+ */
+public class Element {
+
+    /* the element id */
+    private String elementId = null;
+
+    /* the element name */
+    private String elementName = null;
+
+    /* the corresponding DC element for this CAS element */
+    private String dcElement = null;
+
+    /* the element's string description. */
+    private String description = null;
+
+    /**
+     * <p>
+     * Default constructor
+     * </p>
+     * 
+     */
+    public Element() {
+    }
+
+    /**
+     * <p>
+     * Constructs a new CAS element
+     * </p>
+     * 
+     * @param elementId
+     *            The element's Id from the database.
+     * @param elementName
+     *            The element name.
+     * @param element
+     *            The DC element that corresponds to this archive element.
+     * 
+     * @param desc
+     *            The element's description.
+     * 
+     */
+    public Element(String elementId, String elementName,
+            String elemMetadataColumn, String element, 
+            String desc, String typeHandler) {
+        this.elementId = elementId;
+        this.elementName = elementName;
+        this.dcElement = element;
+        this.description = desc;
+    }
+
+    @Override
+    public int hashCode() {
+       return this.elementId.hashCode();
+    }
+    
+    /**
+     * @return Returns the dcElement.
+     */
+    public String getDCElement() {
+        return dcElement;
+    }
+
+    /**
+     * @param element
+     *            The dcElement to set.
+     */
+    public void setDCElement(String element) {
+        dcElement = element;
+    }
+
+    /**
+     * @return Returns the elementId.
+     */
+    public String getElementId() {
+        return elementId;
+    }
+
+    /**
+     * @param elementId
+     *            The elementId to set.
+     */
+    public void setElementId(String elementId) {
+        this.elementId = elementId;
+    }
+
+    /**
+     * @return Returns the elementName.
+     */
+    public String getElementName() {
+        return elementName;
+    }
+
+    /**
+     * @param elementName
+     *            The elementName to set.
+     */
+    public void setElementName(String elementName) {
+        this.elementName = elementName;
+    }
+
+    /**
+     * @return Returns the description.
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * @param description
+     *            The description to set.
+     */
+    public void setDescription(String description) {
+        this.description = description;
+    }  
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/ExtractorSpec.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/ExtractorSpec.java
new file mode 100644
index 0000000..2019ae7
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/ExtractorSpec.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+//JDK imports
+import java.util.Properties;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A specification class showing how to constract
+ * a {@link FilemgrMetExtractor}.
+ * </p>.
+ */
+public class ExtractorSpec {
+
+    private String className;
+
+    private Properties configuration;
+
+    public ExtractorSpec() {
+
+    }
+
+    /**
+     * @param className
+     * @param configuration
+     */
+    public ExtractorSpec(String className, Properties configuration) {
+        super();
+        this.className = className;
+        this.configuration = configuration;
+    }
+
+    /**
+     * @return the className
+     */
+    public String getClassName() {
+        return className;
+    }
+
+    /**
+     * @param className
+     *            the className to set
+     */
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
+    /**
+     * @return the configuration
+     */
+    public Properties getConfiguration() {
+        return configuration;
+    }
+
+    /**
+     * @param configuration
+     *            the configuration to set
+     */
+    public void setConfiguration(Properties configuration) {
+        this.configuration = configuration;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/FileTransferStatus.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/FileTransferStatus.java
new file mode 100644
index 0000000..eedffb7
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/FileTransferStatus.java
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A class to represent the status of a transfer for a file reference belonging
+ * to a {@link Product}.
+ * </p>
+ * 
+ */
+public class FileTransferStatus {
+
+    /* the file reference that is being transferred */
+    private Reference fileRef = null;
+
+    /* the amount of bytes transferred so far */
+    private long bytesTransferred = 0L;
+
+    /* the associated Product */
+    private Product parentProduct = null;
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     */
+    public FileTransferStatus() {
+        super();
+        // TODO Auto-generated constructor stub
+    }
+
+    /**
+     * @param fileRef
+     *            The file reference being transferred.
+     * @param bytesTransferred
+     *            The number of bytes transferred so far for this file.
+     * @param parentProduct
+     *            The parent Product that this file reference belongs to.
+     */
+    public FileTransferStatus(Reference fileRef, long fileSize,
+            long bytesTransferred, Product parentProduct) {
+        this.fileRef = fileRef;
+        this.bytesTransferred = bytesTransferred;
+        this.parentProduct = parentProduct;
+    }
+
+    /**
+     * @return Returns the bytesTransferred.
+     */
+    public long getBytesTransferred() {
+        return bytesTransferred;
+    }
+
+    /**
+     * @param bytesTransferred
+     *            The bytesTransferred to set.
+     */
+    public void setBytesTransferred(long bytesTransferred) {
+        this.bytesTransferred = bytesTransferred;
+    }
+
+    /**
+     * @return Returns the fileRef.
+     */
+    public Reference getFileRef() {
+        return fileRef;
+    }
+
+    /**
+     * @param fileRef
+     *            The fileRef to set.
+     */
+    public void setFileRef(Reference fileRef) {
+        this.fileRef = fileRef;
+    }
+
+    /**
+     * @return Returns the parentProduct.
+     */
+    public Product getParentProduct() {
+        return parentProduct;
+    }
+
+    /**
+     * @param parentProduct
+     *            The parentProduct to set.
+     */
+    public void setParentProduct(Product parentProduct) {
+        this.parentProduct = parentProduct;
+    }
+
+    /**
+     * 
+     * @return The percentage of the file that has been transferred so far.
+     */
+    public double computePctTransferred() {
+        return ((double) (bytesTransferred * 1.0) / (fileRef.getFileSize() * 1.0));
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/FreeTextQueryCriteria.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/FreeTextQueryCriteria.java
new file mode 100644
index 0000000..4b69f67
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/FreeTextQueryCriteria.java
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Free Text Criteria element for a Query to the Catalog.
+ * </p>
+ * 
+ */
+public class FreeTextQueryCriteria extends QueryCriteria {
+
+    private static final long serialVersionUID = 1L;
+
+    private String elementName;
+
+    private List<String> values;
+
+    private static final String[] noiseWords = { "a", "all", "am", "an", "and",
+            "any", "are", "as", "at", "be", "but", "can", "did", "do", "does",
+            "for", "from", "had", "has", "have", "here", "how", "i", "if",
+            "in", "is", "it", "no", "not", "of", "on", "or", "so", "that",
+            "the", "then", "there", "this", "to", "too", "up", "use", "what",
+            "when", "where", "who", "why", "you" };
+
+    private static HashSet<String> noiseWordHash;
+
+    /**
+     * Default constructor.
+     */
+    public FreeTextQueryCriteria() {
+        elementName = new String();
+        values = new ArrayList<String>();
+
+        noiseWordHash = new HashSet<String>();
+        for (int i = 0; i < noiseWords.length; i++)
+            noiseWordHash.add(noiseWords[i]);
+    }
+
+    /**
+     * Constructor for the FreeTextQueryECriteria Class.
+     * 
+     * @param elementId
+     *            The name of the element to search on.
+     * @param v
+     *            A List of terms to search for.
+     */
+    public FreeTextQueryCriteria(String elementName, List<String> v) {
+        this.elementName = elementName;
+        values = v;
+
+        noiseWordHash = new HashSet<String>();
+        for (int i = 0; i < noiseWords.length; i++)
+            noiseWordHash.add(noiseWords[i]);
+    }
+
+    /**
+     * Accessor method for the values of the element to search on.
+     * 
+     * @return The values of the element to search on as a List of Strings.
+     */
+    public List<String> getValues() {
+        return values;
+    }
+
+    /**
+     * Mutator method for the values of the element to search on. This method
+     * should be used when keywords have been parsed out of user-entered free
+     * text. The query will JOIN on all of these values. In order to add
+     * unparsed free text to a Query, see the addFreeText method of this class.
+     * 
+     * @param value
+     *            The values of the element to search on as a List of Strings.
+     */
+    public void setValue(List<String> v) {
+        this.values = v;
+    }
+
+    /**
+     * A method for adding a value to search on to the list of values.
+     * 
+     * @param v
+     *            The value to be added to the search as a String.
+     */
+    public void addValue(String v) {
+        values.add(v);
+    }
+
+    /**
+     * A method for adding unparsed free text to the FreeTextCriteria. Free text
+     * entered as a string is tokenized and punctuation and common words are
+     * dropped before the values are added to the query. In order to query for
+     * pre-parsed keywords, see the setValues method of this class.
+     * 
+     * @param text
+     *            The free text to be parsed and searched on.
+     */
+    public void addFreeText(String text) {
+        // remove punctuation from the text
+        text = text.replaceAll("\\p{Punct}+", "");
+
+        // tokenize string using default delimiters
+        StringTokenizer tok = new StringTokenizer(text);
+        String token = null;
+
+        // filter noise words and add to values vector
+        while (tok.hasMoreElements()) {
+            token = tok.nextToken();
+            if (!noiseWordHash.contains(token))
+                values.add(token);
+        }
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * accessing the element ID to search on.
+     * 
+     * @return The element ID to search on as a String.
+     */
+    public String getElementName() {
+        return elementName;
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * mutating the element ID to search on.
+     * 
+     * @param elementId
+     *            The element ID to search on as a String.
+     */
+    public void setElementName(String elementName) {
+        this.elementName = elementName;
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * generating a human-parsable string version of the query criteria. Note
+     * that the returned String follows the Lucene query language.
+     * 
+     * @return The query as a String.
+     */
+    public String toString() {
+        String serial = elementName + ":(";
+        for (int i = 0; i < values.size(); i++)
+            serial += "+" + (String) values.get(i);
+        serial += ")";
+        return serial;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/Product.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/Product.java
new file mode 100644
index 0000000..32e3156
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/Product.java
@@ -0,0 +1,368 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+//JDK imports
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.catalog.Catalog; //for javadoc
+import org.apache.oodt.commons.xml.XMLUtils;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Product is a set of files, or a heirarchical, directory structure that
+ * should be ingested into the {@link Catalog}.
+ * </p>
+ * 
+ */
+public class Product {
+
+    /* our product id */
+    private String productId = null;
+
+    /* our product name */
+    private String productName = null;
+
+    /* our product type */
+    private ProductType productType = null;
+
+    /* our product structure: can be Heirarchical, or Flat */
+    private String productStructure = null;
+
+    /* a set of {@link References} to the items that make up this product */
+    private List<Reference> references = null;
+
+    /*
+     * the transfer status of this product: is it TRANSFERING, has it been
+     * RECEIVED?
+     */
+    private String transferStatus = null;
+
+    /*
+     * the root reference for this product: if it's a dir, it's the root of the
+     * dir tree if the product is flat, it's the first (and possibly) only ref.
+     */
+    private Reference rootRef;
+
+    /* a couple of static final Strings to represent the TransferStatus */
+    public static final String STATUS_TRANSFER = "TRANSFERING";
+
+    public static final String STATUS_RECEIVED = "RECEIVED";
+
+    /* a couple of static final Strings to represent the productStructure */
+    public static final String STRUCTURE_FLAT = "Flat";
+
+    public static final String STRUCTURE_HIERARCHICAL = "Hierarchical";
+
+    public static final String STRUCTURE_STREAM = "Stream";
+
+    private static String[] VALID_STRUCTURES = new String[]{STRUCTURE_FLAT,STRUCTURE_HIERARCHICAL,STRUCTURE_STREAM};
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(Product.class.getName());
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>
+     * 
+     */
+    public Product() {
+        references = new Vector<Reference>();
+
+    }
+
+    public Product(InputStream is) throws InstantiationException {
+        if (is == null) {
+            throw new InstantiationException(
+                    "Unable to parse product stream: stream not set!");
+        }
+
+        try {
+            DocumentBuilderFactory factory = DocumentBuilderFactory
+                    .newInstance();
+            factory.setNamespaceAware(true);
+            DocumentBuilder parser = factory.newDocumentBuilder();
+            references = new Vector<Reference>();
+            parse(parser.parse(new InputSource(is)));
+        } catch (Exception e) {
+            throw new InstantiationException(
+                    "Unable to parse metadata stream.[" + e.getMessage() + "]");
+        }
+    }
+
+    /**
+     * <p>
+     * Constructs a new Product with the specified parameters.
+     * </p>
+     * 
+     * @param name
+     *            The Product's name.
+     * @param pType
+     *            The Product's {@link ProductType}.
+     * @param structure
+     *            The structure of the product: either Hierarchical, or Flat.
+     * @param transferStatus
+     *            The status of this product's transfer to the DataStore:
+     *            TRANSFERING, or RECEIVED would work
+     * @param refs
+     *            A {@link List} of {@link Reference}s pointing to the items
+     *            that make up this product.
+     */
+    public Product(String name, ProductType pType, String structure,
+            String transferStatus, List<Reference> refs) {
+        productName = name;
+        productType = pType;
+        productStructure = structure;
+        references = refs;
+        this.transferStatus = transferStatus;
+    }
+
+    /**
+     * @return Returns the productType.
+     */
+    public ProductType getProductType() {
+        return productType;
+    }
+
+    /**
+     * @param productType
+     *            The productType to set.
+     */
+    public void setProductType(ProductType productType) {
+        this.productType = productType;
+    }
+
+    /**
+     * @return Returns the productStructure.
+     */
+    public String getProductStructure() {
+        return productStructure;
+    }
+
+    /**
+     * @param productStructure
+     *            The productStructure to set.
+     */
+    public void setProductStructure(String productStructure) {
+        //Guard clause, according to a unit test null is a valid value
+        if (!java.util.Arrays.asList(VALID_STRUCTURES).contains(productStructure) && productStructure != null)
+            throw new IllegalArgumentException("Undefined product structure: "+productStructure);
+        this.productStructure = productStructure;
+    }
+
+    /**
+     * @return Returns the references.
+     */
+    public List<Reference> getProductReferences() {
+        return references;
+    }
+
+    /**
+     * @param references
+     *            The references to set.
+     */
+    public void setProductReferences(List<Reference> references) {
+        this.references = references;
+    }
+
+    /**
+     * @return Returns the productName.
+     */
+    public String getProductName() {
+        return productName;
+    }
+
+    /**
+     * @param productName
+     *            The productName to set.
+     */
+    public void setProductName(String productName) {
+        this.productName = productName;
+    }
+
+    /**
+     * @return Returns the productId.
+     */
+    public String getProductId() {
+        return productId;
+    }
+
+    /**
+     * @param productId
+     *            The productId to set.
+     */
+    public void setProductId(String productId) {
+        this.productId = productId;
+    }
+
+    /**
+     * @return Returns the transferStatus.
+     */
+    public String getTransferStatus() {
+        return transferStatus;
+    }
+
+    /**
+     * @param transferStatus
+     *            The transferStatus to set.
+     */
+    public void setTransferStatus(String transferStatus) {
+        this.transferStatus = transferStatus;
+    }
+
+    /**
+     * @return the rootRef
+     */
+    public Reference getRootRef() {
+        return rootRef;
+    }
+
+    /**
+     * @param rootRef
+     *            the rootRef to set
+     */
+    public void setRootRef(Reference rootRef) {
+        this.rootRef = rootRef;
+    }
+
+    public static final Product getDefaultFlatProduct(String name,
+            String defaultProductTypeId) {
+        Product defaultProduct = new Product();
+        defaultProduct.setProductName(name);
+        defaultProduct.setProductReferences(new Vector<Reference>());
+        defaultProduct.setProductStructure(Product.STRUCTURE_FLAT);
+        ProductType pType = new ProductType();
+        pType.setProductTypeId(defaultProductTypeId);
+        defaultProduct.setProductType(pType);
+        defaultProduct.setTransferStatus(Product.STATUS_TRANSFER);
+        return defaultProduct;
+    }
+
+    public Document toXML() throws Exception {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        Document doc = null;
+
+        try {
+            DocumentBuilder builder = factory.newDocumentBuilder();
+            doc = builder.newDocument();
+
+            Element root = (Element) doc.createElement("cas:product");
+            XMLUtils.addAttribute(doc, root, "xmlns:cas",
+                    "http://oodt.jpl.nasa.gov/1.0/cas");
+            XMLUtils.addAttribute(doc, root, "id", this.productId);
+            XMLUtils.addAttribute(doc, root, "name", URLEncoder.encode(
+                    this.productName, "UTF-8"));
+            doc.appendChild(root);
+
+            XMLUtils.addNode(doc, root, "structure", this.productStructure);
+            XMLUtils.addNode(doc, root, "transferStatus", this.transferStatus);
+            XMLUtils.addNode(doc, root, "type",
+                    this.productType != null ? this.productType.getName() : "");
+
+            if (this.getProductReferences() != null
+                    && this.getProductReferences().size() > 0) {
+                Element refsElem = XMLUtils.addNode(doc, root, "references");
+                for (Iterator<Reference> i = this.getProductReferences().iterator(); i
+                        .hasNext();) {
+                    Reference r = i.next();
+                    Element refElem = XMLUtils.addNode(doc, refsElem,
+                            "reference");
+                    XMLUtils.addAttribute(doc, refElem, "orig", r
+                            .getOrigReference());
+                    XMLUtils.addAttribute(doc, refElem, "dataStore", r
+                            .getDataStoreReference());
+                    XMLUtils.addAttribute(doc, refElem, "size", String
+                            .valueOf(r.getFileSize()));
+
+                }
+            }
+
+        } catch (ParserConfigurationException pce) {
+            LOG.log(Level.WARNING, "Error generating product xml file!: "
+                    + pce.getMessage());
+            throw new Exception("Error generating product xml file!: "
+                    + pce.getMessage());
+        }
+
+        return doc;
+    }
+
+    private void parse(Document doc) {
+        Element root = doc.getDocumentElement();
+
+        this.productId = root.getAttribute("id");
+        try {
+            this.productName = URLDecoder.decode(root.getAttribute("name"),
+                    "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            LOG.log(Level.WARNING,
+                    "Unable to set product name: error decoding encoded string: Message: "
+                            + e.getMessage());
+
+        }
+
+        this.productStructure = XMLUtils.getElementText("structure", root);
+        this.productType = new ProductType();
+        this.productType.setName(XMLUtils.getElementText("type", root));
+        this.transferStatus = XMLUtils.getElementText("transferStatus", root);
+
+        Element refsElem = XMLUtils.getFirstElement("references", root);
+
+        if (refsElem != null) {
+            NodeList refNodeList = refsElem.getElementsByTagName("reference");
+
+            if (refNodeList != null && refNodeList.getLength() > 0) {
+                for (int i = 0; i < refNodeList.getLength(); i++) {
+                    Element refElem = (Element) refNodeList.item(i);
+                    Reference r = new Reference();
+                    r.setOrigReference(refElem.getAttribute("orig"));
+                    r.setDataStoreReference(refElem.getAttribute("dataStore"));
+                    r.setFileSize(Long.valueOf(refElem.getAttribute("size"))
+                            .longValue());
+                    this.references.add(r);
+                }
+            }
+        }
+
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/ProductPage.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/ProductPage.java
new file mode 100644
index 0000000..e70c19e
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/ProductPage.java
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Page of {@link Product}s returned from the <code>File Manager</code>.
+ * </p>
+ * 
+ */
+public class ProductPage {
+
+    /* the number of this page */
+    private int pageNum = -1;
+
+    /* the total number of pages in the set */
+    private int totalPages = -1;
+
+    /* the size of the number of products on this page */
+    private int pageSize = -1;
+
+    /* the list of produdcts associated with this page */
+    private List<Product> pageProducts = null;
+    
+    /* the computed number of total hits for the query */
+    private long numOfHits;
+
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     */
+    public ProductPage() {
+        pageProducts = new Vector<Product>();
+    }
+
+    /**
+     * @param pageNum
+     *            The number of this page.
+     * @param totalPages
+     *            The total number of pages in the set.
+     * @param pageSize
+     *            The size of this page.
+     * @param pageProducts
+     *            The products associated with this page.
+     */
+    public ProductPage(int pageNum, int totalPages, int pageSize,
+            List<Product> pageProducts) {
+        this.pageNum = pageNum;
+        this.totalPages = totalPages;
+        this.pageSize = pageSize;
+        this.pageProducts = pageProducts;
+    }
+
+    /**
+     * @return Returns the pageNum.
+     */
+    public int getPageNum() {
+        return pageNum;
+    }
+
+    /**
+     * @param pageNum
+     *            The pageNum to set.
+     */
+    public void setPageNum(int pageNum) {
+        this.pageNum = pageNum;
+    }
+
+    /**
+     * @return Returns the pageProducts.
+     */
+    public List<Product> getPageProducts() {
+        return pageProducts;
+    }
+
+    /**
+     * @param pageProducts
+     *            The pageProducts to set.
+     */
+    public void setPageProducts(List<Product> pageProducts) {
+        this.pageProducts = pageProducts;
+    }
+
+    /**
+     * @return Returns the pageSize.
+     */
+    public int getPageSize() {
+        return pageSize;
+    }
+
+    /**
+     * @param pageSize
+     *            The pageSize to set.
+     */
+    public void setPageSize(int pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * @return Returns the totalPages.
+     */
+    public int getTotalPages() {
+        return totalPages;
+    }
+
+    /**
+     * @param totalPages
+     *            The totalPages to set.
+     */
+    public void setTotalPages(int totalPages) {
+        this.totalPages = totalPages;
+    }
+
+    /**
+     * 
+     * @return True if this is the last page in the set, false otherwise.
+     */
+    public boolean isLastPage() {
+        return pageNum == totalPages;
+    }
+
+    /**
+     * 
+     * @return True if this is the fist page of the set, false otherwise.
+     */
+    public boolean isFirstPage() {
+        return pageNum == 1;
+    }
+
+
+    /**
+     * @return the numOfHits
+     */
+    public long getNumOfHits() {
+      return numOfHits;
+    }
+
+    /**
+     * @param numOfHits the numOfHits to set
+     */
+    public void setNumOfHits(long numOfHits) {
+      this.numOfHits = numOfHits;
+    }    
+
+    /**
+     * 
+     * @return A blank, unpopulated {@link ProductPage}.
+     */
+    public static ProductPage blankPage() {
+        ProductPage blank = new ProductPage();
+        blank.setPageNum(0);
+        blank.setTotalPages(0);
+        blank.setPageSize(0);
+        return blank;
+    }
+    
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/ProductType.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/ProductType.java
new file mode 100644
index 0000000..aea6d99
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/ProductType.java
@@ -0,0 +1,204 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.type.TypeHandler;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A ProductType is a type of content that will be ingested into the data store
+ * element of the CAS File Manager. The {@link MetadataStore} also needs to know
+ * about the ProductType, because {@link Element}s are associated with them to
+ * define how the metadata is stored for a particular product.
+ * </p>
+ * 
+ */
+public class ProductType {
+
+    /* the unique ID representing this product type */
+    private String productTypeId = null;
+
+    /* the name of this product type */
+    private String name = null;
+
+    /* a description of this product type */
+    private String description = null;
+
+    /* the path to the repository for this product type */
+    private String productRepositoryPath = null;
+
+    /*
+     * the name of the class that implements the versioning scheme for this
+     * product type
+     */
+    private String versioner = null;
+
+    /* metadata describing the product type */
+    private Metadata typeMetadata = null;
+
+    /* list of {@link ExtractorSpec}s associated with this product type */
+    private List<ExtractorSpec> extractors = null;
+
+    private List<TypeHandler> handlers = null;
+    
+    public ProductType() {
+        typeMetadata = new Metadata();
+        extractors = new Vector<ExtractorSpec>();
+    }
+
+    public ProductType(String id, String name, String description,
+            String repository, String versioner) {
+        productTypeId = id;
+        this.name = name;
+        this.description = description;
+        productRepositoryPath = repository;
+        this.versioner = versioner;
+        typeMetadata = new Metadata();
+    }
+
+    /**
+     * @return Returns the description.
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * @param description
+     *            The description to set.
+     */
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    /**
+     * @return Returns the name.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @param name
+     *            The name to set.
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * @return Returns the productTypeId.
+     */
+    public String getProductTypeId() {
+        return productTypeId;
+    }
+
+    /**
+     * @param productTypeId
+     *            The productTypeId to set.
+     */
+    public void setProductTypeId(String productTypeId) {
+        this.productTypeId = productTypeId;
+    }
+
+    /**
+     * @return Returns the productRepositoryPath.
+     */
+    public String getProductRepositoryPath() {
+        return productRepositoryPath;
+    }
+
+    /**
+     * @param productRepositoryPath
+     *            The productRepositoryPath to set.
+     */
+    public void setProductRepositoryPath(String productRepositoryPath) {
+        this.productRepositoryPath = productRepositoryPath;
+    }
+
+    /**
+     * @return Returns the versioner.
+     */
+    public String getVersioner() {
+        return versioner;
+    }
+
+    /**
+     * @param versioner
+     *            The versioner to set.
+     */
+    public void setVersioner(String versioner) {
+        this.versioner = versioner;
+    }
+
+    /**
+     * @return the typeMetadata
+     */
+    public Metadata getTypeMetadata() {
+        return typeMetadata;
+    }
+
+    /**
+     * @param typeMetadata
+     *            the typeMetadata to set
+     */
+    public void setTypeMetadata(Metadata typeMetadata) {
+        this.typeMetadata = typeMetadata;
+    }
+
+    /**
+     * @return the extractors
+     */
+    public List<ExtractorSpec> getExtractors() {
+        return extractors;
+    }
+
+    /**
+     * @param extractors
+     *            the extractors to set
+     */
+    public void setExtractors(List<ExtractorSpec> extractors) {
+        this.extractors = extractors;
+    }
+
+    public List<TypeHandler> getHandlers() {
+        return handlers;
+    }
+
+    public void setHandlers(List<TypeHandler> handlers) {
+        this.handlers = handlers;
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        return this.name;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/Query.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/Query.java
new file mode 100644
index 0000000..3b4f19a
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/Query.java
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Query is a {@link List} of {@link QueryCriteria}.
+ * </p>
+ * 
+ */
+public class Query {
+
+    /* the set of {@link QueryCriteria} for this Query */
+    private List<QueryCriteria> criteria = null;
+    
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     */
+    public Query() {
+        criteria = new Vector<QueryCriteria>();
+    }
+
+    /**
+     * @param criteria
+     */
+    public Query(List<QueryCriteria> criteria) {
+        if (criteria == null)
+            this.criteria = new Vector<QueryCriteria>();
+        else
+            this.criteria = criteria;
+    }
+
+    /**
+     * @return Returns the criteria.
+     */
+    public List<QueryCriteria> getCriteria() {
+        return criteria;
+    }
+
+    /**
+     * @param criteria
+     *            The criteria to set.
+     */
+    public void setCriteria(List<QueryCriteria> criteria) {
+        if (criteria != null)
+            this.criteria = criteria;
+    }
+
+    public void addCriterion(QueryCriteria qc) {
+        criteria.add(qc);
+    }
+    
+    /**
+     * @return A String representation of this Query.
+     */
+    public String toString() {
+        StringBuffer rStr = new StringBuffer();
+
+        rStr.append("q=");
+
+        int numCriteria = criteria.size();
+        for (int i = 0; i < numCriteria; i++) {
+            QueryCriteria c = (QueryCriteria) criteria.get(i);
+            rStr.append(c.toString());
+            if (i != numCriteria - 1)
+                rStr.append(" AND ");
+        }
+
+        return rStr.toString();
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/QueryCriteria.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/QueryCriteria.java
new file mode 100644
index 0000000..d01777f
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/QueryCriteria.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+/**
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * This is an abstract base class for a number of different criteria searches
+ * such as term search, range search and free text search. Subclasses are added
+ * to Query instances in order to search the Catalog.
+ * </p>
+ * 
+ * <ul>
+ * <lh>Known Subclasses:</lh>
+ * <li>FreeTextQueryCriteria
+ * <li>RangeQueryCriteria
+ * <li>TermQueryCriteria
+ * </ul>
+ */
+public abstract class QueryCriteria implements Cloneable {
+
+    /**
+     * Abstract accessor method for the Element name to search on.
+     * 
+     * @return The ElementName in the form of a String.
+     */
+    public abstract String getElementName();
+
+    /**
+     * Abstract mutator method for the Elment name to search on.
+     * 
+     * @param Element Name
+     */
+    public abstract void setElementName(String elementName);
+
+    /**
+     * Abstract method for converting the QueryCriteria to a human-parsable
+     * String.
+     */
+    public abstract String toString();
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/RangeQueryCriteria.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/RangeQueryCriteria.java
new file mode 100644
index 0000000..4aa74dc
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/RangeQueryCriteria.java
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+/**
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Range Criteria element for a Query to the Catalog.
+ * </p>
+ * 
+ */
+public class RangeQueryCriteria extends QueryCriteria {
+
+    private static final long serialVersionUID = 1L;
+
+    private String elementName;
+
+    private String startValue;
+
+    private String endValue;
+
+    private boolean inclusive;
+
+    /**
+     * Default constructor.
+     */
+    public RangeQueryCriteria() {
+        elementName = null;
+        startValue = null;
+        endValue = null;
+        inclusive = true;
+    }
+
+    /**
+     * Constructor for the RangeQuerycriteria class. Note that this default
+     * range is inclusive.
+     * 
+     * @param elementName
+     *            The name of the element to search on.
+     * @param start
+     *            The start value for the range search as a String.
+     * @param end
+     *            The end value for the range search as a String.
+     */
+    public RangeQueryCriteria(String elementName, String start, String end) {
+        this.elementName = elementName;
+        startValue = start;
+        endValue = end;
+        inclusive = true;
+    }
+
+    /**
+     * Constructor for the RangeQueryCriteria clas that can be used to specify
+     * both inclusive and exclusive ranges.
+     * 
+     * @param elementName
+     *            The name of the element to search on.
+     * @param start
+     *            The start value for the range search as a String.
+     * @param end
+     *            The end value for the range search as a String.
+     * @param inclusive
+     *            Boolean: true for inclusive, false for exclusive.
+     */
+    public RangeQueryCriteria(String elementName, String start, String end,
+            boolean inclusive) {
+        this.elementName = elementName;
+        startValue = start;
+        endValue = end;
+        this.inclusive = inclusive;
+    }
+
+    /**
+     * Accessor method for the start value of the element to search on.
+     * 
+     * @return The start value of the element to search on as a String.
+     */
+    public String getStartValue() {
+        return startValue;
+    }
+
+    /**
+     * Mutator method for the start value fo the element to search on.
+     * 
+     * @param value
+     *            The start value of the range as a String.
+     */
+    public void setStartValue(String value) {
+        startValue = value;
+    }
+
+    /**
+     * Accessor method for the end value of the element to search on.
+     * 
+     * @return The end value of the element to search on as a String.
+     */
+    public String getEndValue() {
+        return endValue;
+    }
+
+    /**
+     * Mutator method for the end value fo the element to search on.
+     * 
+     * @param value
+     *            The end value of the range as a String.
+     */
+    public void setEndValue(String value) {
+        endValue = value;
+    }
+
+    /**
+     * Accessor method for the inclusive setting for the range.
+     * 
+     * @return The boolean inclusive/exclusive flag.
+     */
+    public boolean getInclusive() {
+        return inclusive;
+    }
+
+    /**
+     * Mutator method for the inclusive setting for the range. Note that flag
+     * should be set to true for inclusive, false for exclusive.
+     * 
+     * @param inclusive
+     *            The boolean inclusive/exclusive flag.
+     */
+    public void setInclusive(boolean flag) {
+        inclusive = flag;
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * accessing the element name to search on.
+     * 
+     * @return The element name to search on as a String.
+     */
+    public String getElementName() {
+        return elementName;
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * mutating the element name to search on.
+     * 
+     * @param elementName
+     *            The element name to search on as a String.
+     */
+    public void setElementName(String elementName) {
+        this.elementName = elementName;
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * generating a human-parsable string version of the query criteria. Note
+     * that the returned String follows the Lucene query language.
+     * 
+     * @return The query as a String.
+     */
+    public String toString() {
+        String serial = elementName + ":[" + startValue + " TO " + endValue + "]";
+        return serial;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/Reference.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/Reference.java
new file mode 100644
index 0000000..e53e36f
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/Reference.java
@@ -0,0 +1,244 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.tika.Tika;
+import org.apache.tika.config.TikaConfig;
+import org.apache.tika.mime.MimeType;
+import org.apache.tika.mime.MimeTypeException;
+import org.apache.tika.mime.MimeTypes;
+import org.apache.tika.mime.MimeTypesFactory;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A reference stores the original item reference, and also the item's data
+ * store reference, which describes its location within the data store.
+ * </p>
+ * 
+ */
+public class Reference {
+
+    /* the item's original location */
+    private String origReference = null;
+
+    /* the location of the item within the data store */
+    private String dataStoreReference = null;
+
+    /* the size of the file that this reference refers to */
+    private long fileSize = 0L;
+
+    /* the mime-type of the file that this reference refers to */
+    private MimeType mimeType = null;
+
+    private static MimeTypes mimeTypeRepository;
+
+    public static String STREAM_REFERENCE_DELIMITER = "-";
+
+    /* the static reference to the Mime-Type repository */
+    static {
+        try {
+          mimeTypeRepository = MimeTypesFactory.create(new FileInputStream(new File(PathUtils
+                  .replaceEnvVariables(System.getProperty(
+                          "org.apache.oodt.cas.filemgr.mime.type.repository",
+                          "mime-types.xml")))));
+        } catch (Exception e){
+          mimeTypeRepository = TikaConfig.getDefaultConfig().getMimeRepository();
+        }
+    }
+
+    /**
+     * <p>
+     * Copy Constructor
+     * </p>
+     * 
+     * @param r
+     *            The Reference object to copy
+     */
+    public Reference(Reference r) {
+        this(r.getOrigReference(), r.getDataStoreReference(), r.getFileSize(),
+                r.getMimeType());
+    }
+
+    /**
+     * <p>
+     * Default constructor
+     * </p>
+     */
+    public Reference() {
+        super();
+    }
+
+    /**
+     * <p>
+     * Constructs a new Reference with the specified parameters.
+     * </p>
+     * 
+     * @param origRef
+     *            The item's original location.
+     * @param dataRef
+     *            The item's location within the data store.
+     * @param size
+     *            The size of the file that this reference refers to.
+     */
+    public Reference(String origRef, String dataRef, long size) {
+        origReference = origRef;
+        dataStoreReference = dataRef;
+        fileSize = size;
+        // TODO: since no mimetype was specified, do the dirty work
+        // ourselves to determine the which MimeType class to associate
+        // with this reference.
+        try {
+            this.mimeType = mimeTypeRepository.forName(new Tika().detect(origRef));
+        } catch (MimeTypeException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    /**
+     * <p>
+     * Constructs a new Reference with the specified parameters. In particular,
+     * a MimeType object is explicitly supplied. This object represents the
+     * mime-type of the item this reference refers to
+     * </p>
+     * 
+     * @param origRef
+     *            The item's original location.
+     * @param dataRef
+     *            The item's location within the data store.
+     * @param size
+     *            The size of the file that this reference refers to.
+     * @param mime
+     *            A MimeType object representing the mime-type of the item
+     */
+    public Reference(String origRef, String dataRef, long size, MimeType mime) {
+        origReference = origRef;
+        dataStoreReference = dataRef;
+        fileSize = size;
+        mimeType = mime;
+    }
+
+    /**
+     * @return Returns the dataStoreReference.
+     */
+    public String getDataStoreReference() {
+        return dataStoreReference;
+    }
+
+    /**
+     * @param dataStoreReference
+     *            The dataStoreReference to set.
+     */
+    public void setDataStoreReference(String dataStoreReference) {
+        this.dataStoreReference = dataStoreReference;
+    }
+
+    /**
+     * @return Returns the origReference.
+     */
+    public String getOrigReference() {
+        return origReference;
+    }
+
+    /**
+     * @param origReference
+     *            The origReference to set.
+     */
+    public void setOrigReference(String origReference) {
+        this.origReference = origReference;
+    }
+
+    /**
+     * @return Returns the fileSize.
+     */
+    public long getFileSize() {
+        return fileSize;
+    }
+
+    /**
+     * @param fileSize
+     *            The fileSize to set.
+     */
+    public void setFileSize(long fileSize) {
+        this.fileSize = fileSize;
+    }
+
+    /**
+     * @return returns a MimeType obj representing the mime-type of this
+     *         reference
+     */
+    public MimeType getMimeType() {
+        return mimeType;
+    }
+
+    /**
+     * @param mime
+     *            the MimeType object to set for this reference
+     */
+    public void setMimeType(MimeType mime) {
+        this.mimeType = mime;
+    }
+
+    /**
+     * @param name
+     *            the String name of the mimetype of this reference
+     */
+    public void setMimeType(String name) {
+        if(name == null || (name != null && 
+            name.equals(""))) return;
+        
+        try {
+          this.mimeType = mimeTypeRepository.forName(name);
+        } catch (MimeTypeException e) {
+           e.printStackTrace();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        StringBuffer buf = new StringBuffer();
+        buf.append("[orig=");
+        buf.append(this.origReference);
+        buf.append(",dest=");
+        buf.append(this.dataStoreReference);
+        buf.append(",size=");
+        buf.append(this.fileSize);
+        buf.append(",mime=");
+        buf.append(this.mimeType != null ? this.mimeType.toString() : "N/A");
+        buf.append("]");
+        return buf.toString();
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/TermQueryCriteria.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/TermQueryCriteria.java
new file mode 100644
index 0000000..01541b1
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/TermQueryCriteria.java
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+/**
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Term Criteria element for a Query to the Catalog.
+ * </p>
+ * 
+ */
+public class TermQueryCriteria extends QueryCriteria {
+
+    private static final long serialVersionUID = 1L;
+
+    private String elementName;
+
+    private String value;
+
+    /**
+     * Default constructor.
+     */
+    public TermQueryCriteria() {
+        elementName = null;
+        value = null;
+    }
+
+    /**
+     * Constructor for the TermQueryECriteria Class.
+     * 
+     * @param elementName
+     *            The name of the element to search on.
+     * @param v
+     *            The value of the term.
+     */
+    public TermQueryCriteria(String elementName, String v) {
+        this.elementName = elementName;
+        value = v;
+    }
+
+    /**
+     * Accessor method for the value of the element to search on.
+     * 
+     * @return The value of the element to search on as a String.
+     */
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * Mutator method for the value of the element to search on
+     * 
+     * @param value
+     *            The value of the element to search on as a String.
+     */
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * accessing the element name to search on.
+     * 
+     * @return The element name to search on as a String.
+     */
+    public String getElementName() {
+        return elementName;
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * mutating the element name to search on.
+     * 
+     * @param elementName
+     *            The element name to search on as a String.
+     */
+    public void setElementName(String elementName) {
+        this.elementName = elementName;
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * generating a human-parsable string version of the query criteria. Note
+     * that the returned String follows the Lucene query language.
+     * 
+     * @return The query as a String.
+     */
+    public String toString() {
+        String serial = this.elementName + ":" + value;
+        return serial;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/CacheException.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/CacheException.java
new file mode 100644
index 0000000..e3278cb
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/CacheException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * 
+ */
+public class CacheException extends Exception {
+
+    private static final long serialVersionUID = 2154843096944174319L;
+
+    public CacheException() {
+        super();
+    }
+
+    public CacheException(String msg) {
+        super(msg);
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/CatalogException.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/CatalogException.java
new file mode 100644
index 0000000..2ac74c0
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/CatalogException.java
@@ -0,0 +1,43 @@
+/*

+ * 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.

+ */

+

+package org.apache.oodt.cas.filemgr.structs.exceptions;

+

+/**

+ * @author mattmann

+ * @version $Revision$

+ * 

+ * <p>A generic exception that occured when dealing with the

+ * Catalog.</p>

+ * 

+ */

+public class CatalogException extends Exception {

+

+    private static final long serialVersionUID = 3690753990686029110L;

+

+    public CatalogException() {

+        super();

+    }

+

+    public CatalogException(String message) {

+        super(message);

+    }

+

+    public CatalogException(String message, Throwable t) {

+        super(message, t);

+    }

+}

diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/ConnectionException.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/ConnectionException.java
new file mode 100644
index 0000000..ac3fc7b
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/ConnectionException.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.exceptions;
+
+/**
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>An exception that is thrown when a connection cannot
+ * be established by a client.</p>
+ * 
+ */
+public class ConnectionException extends Exception {
+
+	private static final long serialVersionUID = -7260478787886603401L;
+
+    /**
+     * <p>Default Constructor</p>
+     */
+    public ConnectionException() {
+        super();
+    }
+
+    /**
+     * @param message The message for this exception.
+     */
+    public ConnectionException(String message) {
+        super(message);
+    }
+
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/DataTransferException.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/DataTransferException.java
new file mode 100644
index 0000000..dd8c0cc
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/DataTransferException.java
@@ -0,0 +1,62 @@
+/*

+ * 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.

+ */

+

+package org.apache.oodt.cas.filemgr.structs.exceptions;

+

+/**

+ * @author mattmann

+ * @version $Revision$

+ * 

+ * <p>An exception thrown during data transfer.</p>

+ * 

+ */

+public class DataTransferException extends Exception {

+

+    /* serial version UID */

+    private static final long serialVersionUID = 3976741354426479924L;

+

+    /**

+     * 

+     */

+    public DataTransferException() {

+        super();

+    }

+

+    /**

+     * @param message

+     */

+    public DataTransferException(String message) {

+        super(message);

+    }

+

+    /**

+     * @param cause

+     */

+    public DataTransferException(Throwable cause) {

+        super(cause);

+    }

+

+    /**

+     * @param message

+     * @param cause

+     */

+    public DataTransferException(String message, Throwable cause) {

+        super(message, cause);

+    }

+

+

+}

diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/IngestException.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/IngestException.java
new file mode 100644
index 0000000..b0426f2
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/IngestException.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>An exception when ingesting a product.</p>
+ *
+ */
+public class IngestException extends Exception {
+
+	/**
+   * 
+   */
+  private static final long serialVersionUID = 4134078866650777281L;
+
+  /**
+	 * 
+	 */
+	public IngestException() {
+		super();
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public IngestException(String arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 * @param arg1
+	 */
+	public IngestException(String arg0, Throwable arg1) {
+		super(arg0, arg1);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public IngestException(Throwable arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param args
+	 */
+	public static void main(String[] args) {
+		// TODO Auto-generated method stub
+
+	}
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/QueryFormulationException.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/QueryFormulationException.java
new file mode 100644
index 0000000..09ad6eb
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/QueryFormulationException.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.exceptions;
+
+/**
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>A generic exception that occured when dealing with the
+ * Catalog.</p>
+ * 
+ */
+public class QueryFormulationException extends Exception {
+
+	private static final long serialVersionUID = 1641381629886581382L;
+
+	/**
+     * <p>Default Constructor</p>
+     */
+    public QueryFormulationException() {
+        super();
+    }
+
+    /**
+     * @param message The message for this exception.
+     */
+    public QueryFormulationException(String message) {
+        super(message);
+    }
+
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/RepositoryManagerException.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/RepositoryManagerException.java
new file mode 100644
index 0000000..e69ed11
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/RepositoryManagerException.java
@@ -0,0 +1,47 @@
+/*

+ * 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.

+ */

+

+package org.apache.oodt.cas.filemgr.structs.exceptions;

+

+/**

+ * @author mattmann

+ * @version $Revision$

+ * 

+ * <p>An exception thrown from the {@link org.apache.oodt.cas.filemgr.repository.RepositoryManager} 

+ * interface.</p>

+ * 

+ */

+public class RepositoryManagerException extends Exception {

+

+    private static final long serialVersionUID = 3688502208018920497L;

+

+    /**

+     * 

+     */

+    public RepositoryManagerException() {

+        super();

+    }

+

+    /**

+     * @param message

+     */

+    public RepositoryManagerException(String message) {

+        super(message);

+    }

+

+

+}

diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/ValidationLayerException.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/ValidationLayerException.java
new file mode 100644
index 0000000..bf00200
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/ValidationLayerException.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>An exception thrown by the validation layer.</p>
+ *
+ */
+public class ValidationLayerException extends Exception {
+
+    /* serial version UID */
+	private static final long serialVersionUID = -929293299393L;
+
+	/**
+	 * 
+	 */
+	public ValidationLayerException() {
+		super();
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public ValidationLayerException(String arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 * @param arg1
+	 */
+	public ValidationLayerException(String arg0, Throwable arg1) {
+		super(arg0, arg1);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public ValidationLayerException(Throwable arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/VersioningException.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/VersioningException.java
new file mode 100644
index 0000000..21fd810
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/exceptions/VersioningException.java
@@ -0,0 +1,65 @@
+/*

+ * 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.

+ */

+

+package org.apache.oodt.cas.filemgr.structs.exceptions;

+

+//OODT imports

+import org.apache.oodt.cas.filemgr.versioning.Versioner; //for javadoc

+

+

+/**

+ * @author mattmann

+ * @version $Revision$

+ * 

+ * <p>An exception thrown during Versioning by a {@link Versioner}.</p>

+ * 

+ */

+public class VersioningException extends Exception {

+

+    /* default serial UID */

+    private static final long serialVersionUID = 3256999960552615984L;

+

+    /**

+     * 

+     */

+    public VersioningException() {

+        super();

+    }

+

+    /**

+     * @param message

+     */

+    public VersioningException(String message) {

+        super(message);

+    }

+

+    /**

+     * @param cause

+     */

+    public VersioningException(Throwable cause) {

+        super(cause);

+    }

+

+    /**

+     * @param message

+     * @param cause

+     */

+    public VersioningException(String message, Throwable cause) {

+        super(message, cause);

+    }

+

+}

diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/ComplexQuery.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/ComplexQuery.java
new file mode 100644
index 0000000..ee696e9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/ComplexQuery.java
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.query;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.QueryCriteria;
+
+//JDK imports
+import java.util.List;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Complex query allows for querying the filemgr across multiple product-types,
+ * reducing the metadata queried for, filtering the results, and sorting the results
+ * in a single query
+ * </p>
+ */
+public class ComplexQuery extends Query {
+
+    private List<String> reducedProductTypeNames;
+    private List<String> reducedMetadata;
+    private QueryFilter queryFilter;
+    private String sortByMetKey;
+    private String toStringResultFormat;
+    
+    public ComplexQuery() {
+        super();
+    }
+    
+    public ComplexQuery(List<QueryCriteria> criteria) {
+        super(criteria);
+    }
+    
+    public List<String> getReducedProductTypeNames() {
+        return reducedProductTypeNames;
+    }
+
+    public void setReducedProductTypeNames(List<String> reducedProductTypeNames) {
+        this.reducedProductTypeNames = reducedProductTypeNames;
+    }
+
+    public List<String> getReducedMetadata() {
+        return reducedMetadata;
+    }
+
+    public void setReducedMetadata(List<String> reducedMetadata) {
+        this.reducedMetadata = reducedMetadata;
+        if (this.sortByMetKey != null && this.reducedMetadata != null 
+                && !this.reducedMetadata.contains(this.sortByMetKey))
+            this.reducedMetadata.add(this.sortByMetKey);
+    }
+
+    public QueryFilter getQueryFilter() {
+        return queryFilter;
+    }
+
+    public void setQueryFilter(QueryFilter queryFilter) {
+        this.queryFilter = queryFilter;
+    }
+    
+    public String getSortByMetKey() {
+        return sortByMetKey;
+    }
+
+    public void setSortByMetKey(String sortByMetKey) {
+        this.sortByMetKey = sortByMetKey;
+        if (this.reducedMetadata != null && this.sortByMetKey != null 
+                && !this.reducedMetadata.contains(this.sortByMetKey))
+            this.reducedMetadata.add(this.sortByMetKey);
+    }
+    
+    public String getToStringResultFormat() {
+        return this.toStringResultFormat;
+    }
+
+    public void setToStringResultFormat(String toStringResultFormat) {
+        this.toStringResultFormat = toStringResultFormat;
+    }
+    
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/QueryFilter.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/QueryFilter.java
new file mode 100644
index 0000000..0f38412
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/QueryFilter.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.query;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.query.conv.AsciiSortableVersionConverter;
+import org.apache.oodt.cas.filemgr.structs.query.conv.VersionConverter;
+import org.apache.oodt.cas.filemgr.structs.query.filter.FilterAlgor;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A query filter that allows user to filter results in a complex query
+ * <p>
+ */
+public class QueryFilter {
+
+    private String startDateTimeMetKey, endDateTimeMetKey, priorityMetKey;
+    private FilterAlgor filterAlgor;
+    private VersionConverter converter;
+
+    public QueryFilter(String startDateTimeMetKey, String endDateTimeMetKey,
+            String priorityMetKey, FilterAlgor filterAlgor) {
+        this.startDateTimeMetKey = startDateTimeMetKey;
+        this.endDateTimeMetKey = endDateTimeMetKey;
+        this.priorityMetKey = priorityMetKey;
+        this.filterAlgor = filterAlgor;
+        this.converter = new AsciiSortableVersionConverter();
+    }
+
+    public String getStartDateTimeMetKey() {
+        return startDateTimeMetKey;
+    }
+
+    public void setStartDateTimeMetKey(String startDateTimeMetKey) {
+        this.startDateTimeMetKey = startDateTimeMetKey;
+    }
+
+    public String getEndDateTimeMetKey() {
+        return endDateTimeMetKey;
+    }
+
+    public void setEndDateTimeMetKey(String endDateTimeMetKey) {
+        this.endDateTimeMetKey = endDateTimeMetKey;
+    }
+
+    public String getPriorityMetKey() {
+        return priorityMetKey;
+    }
+
+    public void setPriorityMetKey(String priorityMetKey) {
+        this.priorityMetKey = priorityMetKey;
+    }
+
+    public FilterAlgor getFilterAlgor() {
+        return filterAlgor;
+    }
+
+    public void setFilterAlgor(FilterAlgor filterAlgor) {
+        if (filterAlgor != null)
+            this.filterAlgor = filterAlgor;
+    }
+
+    public VersionConverter getConverter() {
+        return converter;
+    }
+
+    public void setConverter(VersionConverter converter) {
+        if (converter != null)
+            this.converter = converter;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/QueryResult.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/QueryResult.java
new file mode 100644
index 0000000..18c983c
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/QueryResult.java
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.query;
+
+//JDK imports
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.util.StringUtils;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A combination of a Product and its Metadata
+ * <p>
+ */
+public class QueryResult {
+
+    private Product product;
+    private Metadata metadata;
+    private String toStringFormat;
+    
+    public QueryResult(Product product, Metadata metadata) {
+        this.metadata = metadata;
+        this.product = product;
+    }
+    
+    public Product getProduct() {
+        return this.product;
+    }
+    
+    public void setProduct(Product product) {
+        this.product = product;
+    }
+    
+    public Metadata getMetadata() {
+        return this.metadata;
+    }
+    
+    public void setMetadata(Metadata metadata) {
+        this.metadata = metadata;
+    }
+        
+    public String getToStringFormat() {
+        return this.toStringFormat;
+    }
+
+    public void setToStringFormat(String toStringFormat) {
+        this.toStringFormat = toStringFormat;
+    }
+
+    public String toString() {
+        return convertMetadataToString(this.metadata, this.toStringFormat);
+    }
+    
+    private static String convertMetadataToString(Metadata metadata, String format) {
+        if (format == null)
+            return concatMetadataIntoString(metadata);
+        String outputString = format;
+        for (String key : metadata.getAllKeys())
+            outputString = outputString.replaceAll("\\$" + key,
+                StringUtils.collectionToCommaDelimitedString(metadata.getAllMetadata(key)));
+        return outputString;
+    }
+    
+    private static String concatMetadataIntoString(Metadata metadata) {
+        List<String> outputString = new ArrayList<String>();
+        for (String key : metadata.getAllKeys())
+            outputString.add(StringUtils.collectionToCommaDelimitedString(metadata.getAllMetadata(key)));
+        return StringUtils.collectionToCommaDelimitedString(outputString);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      if (this == obj)
+        return true;
+      if (obj == null)
+        return false;
+      if (getClass() != obj.getClass())
+        return false;
+      QueryResult other = (QueryResult) obj;
+      if (metadata == null) {
+        if (other.metadata != null)
+          return false;
+      } else if (!metadata.equals(other.metadata))
+        return false;
+      if (product == null) {
+        if (other.product != null)
+          return false;
+      } else if (!product.equals(other.product))
+        return false;
+      if (toStringFormat == null) {
+        if (other.toStringFormat != null)
+          return false;
+      } else if (!toStringFormat.equals(other.toStringFormat))
+        return false;
+      return true;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/QueryResultComparator.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/QueryResultComparator.java
new file mode 100644
index 0000000..9552d11
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/QueryResultComparator.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.query;
+
+//JDK imports
+import java.util.Comparator;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A Comparator that allows for sorting of QueryResults based on a 
+ * Metadata element
+ * <p>
+ */
+public class QueryResultComparator implements Comparator<QueryResult> {
+
+    private String sortByMetKey;
+
+    public String getSortByMetKey() {
+        return sortByMetKey;
+    }
+
+    public void setSortByMetKey(String sortByMetKey) {
+        this.sortByMetKey = sortByMetKey;
+    }
+
+    public int compare(QueryResult qr1, QueryResult qr2) {
+        String m1 = qr1.getMetadata().getMetadata(sortByMetKey);
+        String m2 = qr2.getMetadata().getMetadata(sortByMetKey);
+        if (m1 == m2)
+            return 0;
+        // return null last, since they are the least interesting
+        if (m1 == null)
+            return 1;
+        if (m2 == null)
+            return -1;
+        return m1.compareTo(m2);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/conv/AsciiSortableVersionConverter.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/conv/AsciiSortableVersionConverter.java
new file mode 100644
index 0000000..e56dfee
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/conv/AsciiSortableVersionConverter.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.query.conv;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * Converts a ascii sortable String version into a priority number
+ * <p>
+ */
+public class AsciiSortableVersionConverter implements VersionConverter {
+
+    public double convertToPriority(String version) throws Exception {
+        double priority = 0;
+        char[] versionCharArray = version.toCharArray();
+        for (int i = 0, j = versionCharArray.length - 1; i < versionCharArray.length; i++, j--)
+            priority += (((int) versionCharArray[i]) * Math.pow(10, j));
+        return priority;
+    }
+    
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/conv/VersionConverter.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/conv/VersionConverter.java
new file mode 100644
index 0000000..91cb252
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/conv/VersionConverter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.query.conv;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * An interface for converting a String version into a priority number
+ * <p>
+ */
+public interface VersionConverter {
+
+    public double convertToPriority(String version) throws Exception;
+    
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/filter/FilterAlgor.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/filter/FilterAlgor.java
new file mode 100644
index 0000000..96ffada
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/filter/FilterAlgor.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.query.filter;
+
+//JDK imports
+import java.util.List;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * An algorithm interface for defining how QueryFilter filters query results
+ * <p>
+ */
+public abstract class FilterAlgor {
+
+    protected long epsilon;
+    
+    public FilterAlgor() {
+        this.epsilon = 0;
+    }
+    
+    public void setEpsilon(long epsilon) {
+        this.epsilon = epsilon;
+    }
+    
+    public long getEpsilon() {
+        return this.epsilon;
+    }
+    
+    public abstract List<TimeEvent> filterEvents(List<TimeEvent> events); 
+    
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/filter/ObjectTimeEvent.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/filter/ObjectTimeEvent.java
new file mode 100644
index 0000000..4c16804
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/filter/ObjectTimeEvent.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.query.filter;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>A {@link TimeEvent} associated with a particular {@link Object}</p>.
+ */
+public class ObjectTimeEvent<objType> extends TimeEvent {
+
+    private objType timeObj;
+
+    public ObjectTimeEvent(long startTime, long endTime, objType timeObj) {
+        super(startTime, endTime);
+        this.timeObj = timeObj;
+    }
+
+    public ObjectTimeEvent(long startTime, long endTime, double priority,
+            objType timeObj) {
+        super(startTime, endTime, priority);
+        this.timeObj = timeObj;
+    }
+
+    public objType getTimeObject() {
+        return this.timeObj;
+    }
+
+    public boolean equals(Object obj) {
+        if (obj instanceof ObjectTimeEvent) {
+            ObjectTimeEvent<?> ote = (ObjectTimeEvent<?>) obj;
+            return super.equals(obj) && this.timeObj.equals(ote.timeObj);
+        } else
+            return false;
+    }
+
+    public String toString() {
+        return super.toString() + " - " + timeObj;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/filter/TimeEvent.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/filter/TimeEvent.java
new file mode 100644
index 0000000..bbc0a98
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/query/filter/TimeEvent.java
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.query.filter;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * A basis for time-based queries results over a start/end datetime with
+ * a duration
+ * </p>.
+ */
+public class TimeEvent implements Comparable<TimeEvent> {
+
+    protected long startTime, endTime, dur;
+
+    protected double priority;
+
+    public TimeEvent(long startTime, long endTime) {
+        this(startTime, endTime, 0);
+    }
+
+    public TimeEvent(long startTime, long endTime, double priority) {
+        this.startTime = startTime;
+        this.endTime = endTime;
+        this.dur = this.endTime - this.startTime;
+        this.priority = priority;
+    }
+
+    public void setPriority(double priority) {
+        this.priority = priority;
+    }
+
+    public double getPriority() {
+        return this.priority;
+    }
+
+    public long getStartTime() {
+        return this.startTime;
+    }
+
+    public long getEndTime() {
+        return this.endTime;
+    }
+
+    public long getDuration() {
+        return this.dur;
+    }
+
+    public boolean equals(Object obj) {
+        if (obj instanceof TimeEvent) {
+            TimeEvent te = (TimeEvent) obj;
+            return te.startTime == this.startTime && te.endTime == this.endTime;
+        } else
+            return false;
+    }
+
+    public String toString() {
+        return "[" + this.startTime + "," + this.endTime + "] - "
+                + this.priority;
+    }
+    
+    public static boolean happenAtSameTime(TimeEvent te1, TimeEvent te2) {
+        return te1.getStartTime() == te2.getStartTime() && te1.getEndTime() == te2.getEndTime();
+    }
+
+    public int compareTo(TimeEvent te) {
+        return new Long(this.startTime).compareTo(te.startTime);
+    }
+    
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/type/TypeHandler.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/type/TypeHandler.java
new file mode 100644
index 0000000..f9f6227
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/type/TypeHandler.java
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.type;
+
+//JDK imports
+import java.util.LinkedList;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.BooleanQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.QueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.QueryFormulationException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * A Metadata modification class that intercepts all Metadata flowing in and out
+ * of the Catalog.  Allows the Catalog to contain additional Metadata or modified
+ * Metadata while keeping it invisible to the user.  The purpose it to create 
+ * String queriable Metadata so that the Catalog can be queries accurately and
+ * without extra knowledge required on the user end.
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public abstract class TypeHandler {
+    
+    protected String elementName;
+
+    /**
+     * Sets the Element name that this TypeHandler is responsible for handling
+     * @param elementName The Element name for this TypeHandler
+     */
+    public void setElementName(String elementName) {
+        this.elementName = elementName;
+    }
+    
+    /**
+     * Get the Element name that this TypeHandler is responsible for handling
+     * @return The Element name for this TypeHandler
+     */
+    public String getElementName() {
+        return this.elementName;
+    }
+    
+    /**
+     * Converts this TypeHandler's element in the given Query into a Query
+     * with the necessary elements and values so the Catalog can be queried.
+     *    
+     *    NOTE: Original Query is modified . . . the argument query becomes
+     *    equal to the returned query (return of query is a convenience).
+     *    
+     * @param query Query for which the Catalog Query will be returned
+     * @return A Query with Catalog element values
+     * @throws QueryFormulationException
+     * @throws IllegalAccessException 
+     * @throws InstantiationException 
+     */
+    public Query preQueryHandle(Query query) throws QueryFormulationException {
+        LinkedList<QueryCriteria> qcList = new LinkedList<QueryCriteria>();
+        for (QueryCriteria qc : query.getCriteria())
+            qcList.add(this.handleQueryCriteria(qc));
+        query.setCriteria(qcList);
+        return query;
+    }
+    
+    private QueryCriteria handleQueryCriteria(QueryCriteria qc) throws QueryFormulationException {
+        if (qc instanceof BooleanQueryCriteria) {
+            LinkedList<QueryCriteria> qcList = new LinkedList<QueryCriteria>();
+            for (QueryCriteria criteria : ((BooleanQueryCriteria) qc).getTerms()) 
+                qcList.add(this.handleQueryCriteria(criteria));
+            BooleanQueryCriteria bqc = new BooleanQueryCriteria();
+            bqc.setOperator(((BooleanQueryCriteria) qc).getOperator());
+            bqc.setElementName(qc.getElementName());
+            for (QueryCriteria criteria : qcList)
+                bqc.addTerm(criteria);
+            return bqc;
+        }else if (qc.getElementName().equals(elementName) && qc instanceof TermQueryCriteria) {
+            return this.handleTermQueryCriteria((TermQueryCriteria) qc);
+        }else if (qc.getElementName().equals(elementName) && qc instanceof RangeQueryCriteria) {
+            return this.handleRangeQueryCriteria((RangeQueryCriteria) qc);
+        }else {
+            return qc;
+        }
+    }
+    
+    /**
+     * Handles converting any Catalog metadata element values to their original values.  
+     * Metadata elements can be added, modified, or replaced.
+     * 
+     * @param metadata The Catalog Metadata
+     */
+    public abstract void postGetMetadataHandle(Metadata metadata);
+    
+    /**
+     * Handles converting any metadata element to Catalog element values.  
+     * Metadata elements can be added, modified, or replaced.
+     * 
+     * @param metadata The Original Metadata
+     */
+    public abstract void preAddMetadataHandle(Metadata metadata);
+    
+    /**
+     * Converts the given RangeQueryCriteria into a QueryCriteria with the necessary
+     * Catalog elements and values to perform the query
+     * 
+     * 
+     * @param qc
+     * @return
+     */
+    protected abstract QueryCriteria handleRangeQueryCriteria(RangeQueryCriteria qc);
+    
+    /**
+     * Converts the given TermQueryCriteria into a QueryCriteria with the necessary
+     * Catalog elements and values to perform the query
+     * 
+     * @param qc
+     * @return
+     */
+    protected abstract QueryCriteria handleTermQueryCriteria(TermQueryCriteria qc);
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/type/ValueReplaceTypeHandler.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/type/ValueReplaceTypeHandler.java
new file mode 100644
index 0000000..639fabd
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/type/ValueReplaceTypeHandler.java
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.type;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.QueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * A Subset-TypeHandler which only allows for metadata value modification.
+ * It will automatically detected and replace the metadata values for 
+ * the metadata element which it is responsible for.  All the developer
+ * needs to supply is the convertion method between the original value
+ * and the Catalog value
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public abstract class ValueReplaceTypeHandler extends TypeHandler {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void postGetMetadataHandle(Metadata metadata) {
+        if (metadata.containsKey(elementName)) {
+            metadata.replaceMetadata(elementName, 
+                this.getOrigValue(metadata.getMetadata(elementName)));
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void preAddMetadataHandle(Metadata metadata) {
+        if (metadata.containsKey(elementName)) {
+            metadata.replaceMetadata(elementName, 
+                this.getCatalogValue(metadata.getMetadata(elementName)));
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected QueryCriteria handleRangeQueryCriteria(RangeQueryCriteria rqc) {
+        if (rqc.getEndValue() != null)
+            rqc.setEndValue(this.getCatalogValue(rqc.getEndValue()));
+        if (rqc.getStartValue() != null)
+            rqc.setStartValue(this.getCatalogValue(rqc.getStartValue()));
+        return rqc;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected QueryCriteria handleTermQueryCriteria(TermQueryCriteria tqc) {
+        if (tqc.getValue() != null)
+            tqc.setValue(this.getCatalogValue(tqc.getValue()));
+        return tqc;
+    }
+    
+    /**
+     * Converts the metadata element, for this TypeHandler, value to the 
+     * Catalog value
+     * @param origValue The value for the element which this TypeHandler
+     *  is responsible for
+     * @return The Catalog value
+     */
+    protected abstract String getCatalogValue(String origValue);
+    
+    /**
+     * Converts the metadata element, for this TypeHandler, value from the 
+     * Catalog value to the original value
+     * @param origValue The value for the element which this TypeHandler
+     *  is responsible for
+     * @return The original value
+     */
+    protected abstract String getOrigValue(String databaseValue);
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/type/examples/MajorMinorVersionTypeHandler.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/type/examples/MajorMinorVersionTypeHandler.java
new file mode 100644
index 0000000..5003787
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/structs/type/examples/MajorMinorVersionTypeHandler.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.type.examples;
+
+//APACHE imports
+import org.apache.commons.lang.StringUtils;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.type.ValueReplaceTypeHandler;
+
+/**
+ * Handler metadata element values whose original format is: \d{1,2}.\d{0,2}
+ * 
+ * Return Catalog value format:  \d\d.\d\d
+ * Return original value format: \d{1,2}.\d{1,2}
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class MajorMinorVersionTypeHandler extends ValueReplaceTypeHandler {
+
+    
+    @Override
+    protected String getCatalogValue(String origValue) {
+        String[] origValueSplit = origValue.split("\\.");
+        String majorVersion = origValueSplit[0];
+        String minorVersion = origValueSplit[1];
+        return StringUtils.leftPad(majorVersion, 2, "0") + "." 
+            + StringUtils.rightPad(minorVersion, 2, "0");
+    }
+
+    @Override
+    protected String getOrigValue(String databaseValue) {
+        return Double.toString(Double.parseDouble(databaseValue));
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/XmlRpcFileManager.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/XmlRpcFileManager.java
new file mode 100644
index 0000000..2338547
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/XmlRpcFileManager.java
@@ -0,0 +1,1369 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.system;
+
+//APACHE imports
+import org.apache.xmlrpc.WebServer;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.oodt.commons.date.DateUtils;
+import org.apache.oodt.cas.filemgr.catalog.Catalog;
+import org.apache.oodt.cas.filemgr.metadata.ProductMetKeys;
+import org.apache.oodt.cas.filemgr.metadata.extractors.FilemgrMetExtractor;
+import org.apache.oodt.cas.filemgr.repository.RepositoryManager;
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.ExtractorSpec;
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.QueryFormulationException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.filemgr.structs.query.ComplexQuery;
+import org.apache.oodt.cas.filemgr.structs.query.QueryFilter;
+import org.apache.oodt.cas.filemgr.structs.query.QueryResult;
+import org.apache.oodt.cas.filemgr.structs.query.QueryResultComparator;
+import org.apache.oodt.cas.filemgr.structs.query.filter.ObjectTimeEvent;
+import org.apache.oodt.cas.filemgr.structs.query.filter.TimeEvent;
+import org.apache.oodt.cas.filemgr.structs.type.TypeHandler;
+import org.apache.oodt.cas.filemgr.datatransfer.DataTransfer;
+import org.apache.oodt.cas.filemgr.util.GenericFileManagerObjectFactory;
+import org.apache.oodt.cas.filemgr.util.XmlRpcStructFactory;
+import org.apache.oodt.cas.filemgr.versioning.Versioner;
+import org.apache.oodt.cas.filemgr.versioning.VersioningUtils;
+import org.apache.oodt.cas.filemgr.datatransfer.TransferStatusTracker;
+
+import com.google.common.collect.Lists;
+
+
+
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Vector;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * An XML RPC-based File manager.
+ * </p>
+ * 
+ */
+public class XmlRpcFileManager {
+
+    /* the port to run the XML RPC web server on, default is 1999 */
+    private int webServerPort = 1999;
+
+    /* our Catalog */
+    private Catalog catalog = null;
+
+    /* our RepositoryManager */
+    private RepositoryManager repositoryManager = null;
+
+    /* our DataTransfer */
+    private DataTransfer dataTransfer = null;
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(XmlRpcFileManager.class.getName());
+
+    /* our xml rpc web server */
+    private WebServer webServer = null;
+
+    /* our data transfer status tracker */
+    private TransferStatusTracker transferStatusTracker = null;
+    
+    /* whether or not to expand a product instance into met */
+    private boolean expandProductMet;
+    
+    /**
+     * <p>
+     * Creates a new XmlRpcFileManager with the given metadata store factory,
+     * and the given data store factory, on the given port.
+     * </p>
+     * 
+     * @param port
+     *            The web server port to run the XML Rpc server on, defaults to
+     *            1999.
+     */
+    public XmlRpcFileManager(int port) throws Exception {
+        webServerPort = port;
+
+        // start up the web server
+        webServer = new WebServer(webServerPort);
+        webServer.addHandler("filemgr", this);
+        webServer.start();
+
+        this.loadConfiguration();
+        LOG.log(Level.INFO, "File Manager started by "
+                + System.getProperty("user.name", "unknown"));
+
+    }
+    
+    public void setCatalog(Catalog catalog) {
+        this.catalog = catalog;
+    }
+
+    public boolean isAlive() {
+        return true;
+    }
+    
+    public boolean refreshConfigAndPolicy() {
+      boolean status = false;
+
+      try {
+        this.loadConfiguration();
+        status = true;
+      } catch (Exception e) {
+        e.printStackTrace();
+        LOG
+            .log(
+                Level.SEVERE,
+                "Unable to refresh configuration for file manager " +
+                "server: server may be in inoperable state: Message: "
+                    + e.getMessage());
+      }
+  
+      return status;
+    }
+
+    public boolean transferringProduct(Hashtable<String, Object> productHash) {
+        Product p = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+        transferStatusTracker.transferringProduct(p);
+        return true;
+    }
+
+    public Hashtable<String, Object> getCurrentFileTransfer() {
+        FileTransferStatus status = transferStatusTracker
+                .getCurrentFileTransfer();
+        if (status == null) {
+            return new Hashtable<String, Object>();
+        } else
+            return XmlRpcStructFactory.getXmlRpcFileTransferStatus(status);
+    }
+
+    public Vector<Hashtable<String, Object>> getCurrentFileTransfers() {
+        List<FileTransferStatus> currentTransfers = transferStatusTracker.getCurrentFileTransfers();
+
+        if (currentTransfers != null && currentTransfers.size() > 0) {
+            return XmlRpcStructFactory
+                    .getXmlRpcFileTransferStatuses(currentTransfers);
+        } else
+            return new Vector<Hashtable<String, Object>>();
+    }
+
+    public double getProductPctTransferred(Hashtable<String, Object> productHash) {
+        Product product = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+        double pct = transferStatusTracker.getPctTransferred(product);
+        return pct;
+    }
+
+    public double getRefPctTransferred(Hashtable<String, Object> refHash) {
+        Reference reference = XmlRpcStructFactory
+                .getReferenceFromXmlRpc(refHash);
+        double pct = 0.0;
+
+        try {
+            pct = transferStatusTracker.getPctTransferred(reference);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception getting transfer percentage for ref: ["
+                            + reference.getOrigReference() + "]: Message: "
+                            + e.getMessage());
+        }
+        return pct;
+    }
+
+    public boolean removeProductTransferStatus(Hashtable<String, Object> productHash) {
+        Product product = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+        transferStatusTracker.removeProductTransferStatus(product);
+        return true;
+    }
+
+    public boolean isTransferComplete(Hashtable<String, Object> productHash) {
+        Product product = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+        return transferStatusTracker.isTransferComplete(product);
+    }
+
+    public Hashtable<String, Object> pagedQuery(
+            Hashtable<String, Object> queryHash,
+            Hashtable<String, Object> productTypeHash,
+            int pageNum) throws CatalogException {
+        ProductType type = XmlRpcStructFactory
+                .getProductTypeFromXmlRpc(productTypeHash);
+        Query query = XmlRpcStructFactory.getQueryFromXmlRpc(queryHash);
+
+        ProductPage prodPage = null;
+
+        try {
+            prodPage = catalog.pagedQuery(this.getCatalogQuery(query, type), type, pageNum);
+
+            if (prodPage == null) {
+                prodPage = ProductPage.blankPage();
+            } else {
+                // it is possible here that the underlying catalog did not
+                // set the ProductType
+                // to obey the contract of the File Manager, we need to make
+                // sure its set here
+                setProductType(prodPage.getPageProducts());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Catalog exception performing paged query for product type: ["
+                            + type.getProductTypeId() + "] query: [" + query
+                            + "]: Message: " + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        }
+
+        return XmlRpcStructFactory.getXmlRpcProductPage(prodPage);
+    }
+
+    public Hashtable<String, Object> getFirstPage(
+            Hashtable<String, Object> productTypeHash) {
+        ProductType type = XmlRpcStructFactory
+                .getProductTypeFromXmlRpc(productTypeHash);
+        ProductPage page = catalog.getFirstPage(type);
+        try {
+            setProductType(page.getPageProducts());
+        } catch (Exception e) {
+            LOG.log(Level.WARNING,
+                    "Unable to set product types for product page list: ["
+                            + page + "]");
+        }
+        return XmlRpcStructFactory.getXmlRpcProductPage(page);
+    }
+
+    public Hashtable<String, Object> getLastPage(
+            Hashtable<String, Object> productTypeHash) {
+        ProductType type = XmlRpcStructFactory
+                .getProductTypeFromXmlRpc(productTypeHash);
+        ProductPage page = catalog.getLastProductPage(type);
+        try {
+            setProductType(page.getPageProducts());
+        } catch (Exception e) {
+            LOG.log(Level.WARNING,
+                    "Unable to set product types for product page list: ["
+                            + page + "]");
+        }
+        return XmlRpcStructFactory.getXmlRpcProductPage(page);
+    }
+
+    public Hashtable<String, Object> getNextPage(
+            Hashtable<String, Object> productTypeHash,
+            Hashtable<String, Object> currentPageHash) {
+        ProductType type = XmlRpcStructFactory
+                .getProductTypeFromXmlRpc(productTypeHash);
+        ProductPage currPage = XmlRpcStructFactory
+                .getProductPageFromXmlRpc(currentPageHash);
+        ProductPage page = catalog.getNextPage(type, currPage);
+        try {
+            setProductType(page.getPageProducts());
+        } catch (Exception e) {
+            LOG.log(Level.WARNING,
+                    "Unable to set product types for product page list: ["
+                            + page + "]");
+        }
+        return XmlRpcStructFactory.getXmlRpcProductPage(page);
+    }
+
+    public Hashtable<String, Object> getPrevPage(
+            Hashtable<String, Object> productTypeHash,
+            Hashtable<String, Object> currentPageHash) {
+        ProductType type = XmlRpcStructFactory
+                .getProductTypeFromXmlRpc(productTypeHash);
+        ProductPage currPage = XmlRpcStructFactory
+                .getProductPageFromXmlRpc(currentPageHash);
+        ProductPage page = catalog.getPrevPage(type, currPage);
+        try {
+            setProductType(page.getPageProducts());
+        } catch (Exception e) {
+            LOG.log(Level.WARNING,
+                    "Unable to set product types for product page list: ["
+                            + page + "]");
+        }
+        return XmlRpcStructFactory.getXmlRpcProductPage(page);
+    }
+
+    public String addProductType(Hashtable<String, Object> productTypeHash)
+            throws RepositoryManagerException {
+        ProductType productType = XmlRpcStructFactory
+                .getProductTypeFromXmlRpc(productTypeHash);
+        repositoryManager.addProductType(productType);
+        return productType.getProductTypeId();
+
+    }
+
+    public synchronized boolean setProductTransferStatus(
+            Hashtable<String, Object> productHash)
+            throws CatalogException {
+        Product product = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+        catalog.setProductTransferStatus(product);
+        return true;
+    }
+
+    public int getNumProducts(Hashtable<String, Object> productTypeHash)
+            throws CatalogException {
+        int numProducts = -1;
+
+        ProductType type = XmlRpcStructFactory
+                .getProductTypeFromXmlRpc(productTypeHash);
+
+        try {
+            numProducts = catalog.getNumProducts(type);
+        } catch (CatalogException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception when getting num products: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        }
+
+        return numProducts;
+    }
+
+    public Vector<Hashtable<String, Object>> getTopNProducts(int n)
+            throws CatalogException {
+        List<Product> topNProducts = null;
+
+        try {
+            topNProducts = catalog.getTopNProducts(n);
+            return XmlRpcStructFactory.getXmlRpcProductList(topNProducts);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception when getting topN products: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        }
+    }
+
+    public Vector<Hashtable<String, Object>> getTopNProducts(int n,
+            Hashtable<String, Object> productTypeHash)
+            throws CatalogException {
+        ProductType type = XmlRpcStructFactory
+                .getProductTypeFromXmlRpc(productTypeHash);
+        List<Product> topNProducts = null;
+
+        try {
+            topNProducts = catalog.getTopNProducts(n, type);
+            return XmlRpcStructFactory.getXmlRpcProductList(topNProducts);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception when getting topN products by product type: ["
+                            + type.getProductTypeId() + "]: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        }
+
+    }
+
+    public boolean hasProduct(String productName) throws CatalogException {
+        Product p = catalog.getProductByName(productName);
+        return p != null
+                && p.getTransferStatus().equals(Product.STATUS_RECEIVED);
+    }
+
+    public Hashtable<String, Object> getMetadata(
+            Hashtable<String, Object> productHash) throws CatalogException {
+        Product product = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+        return this.getMetadata(product).getHashtable();
+    }
+
+    public Hashtable<String, Object> getReducedMetadata(
+            Hashtable<String, Object> productHash, Vector<String> elements)
+            throws CatalogException {
+        Product product = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+        return this.getReducedMetadata(product, elements).getHashtable();
+    }
+
+    public Vector<Hashtable<String, Object>> getProductTypes()
+            throws RepositoryManagerException {
+        List<ProductType> productTypeList = null;
+
+        try {
+            productTypeList = repositoryManager.getProductTypes();
+            return XmlRpcStructFactory
+                    .getXmlRpcProductTypeList(productTypeList);
+        } catch (RepositoryManagerException e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE,
+                    "Unable to obtain product types from repository manager: Message: "
+                            + e.getMessage());
+            throw new RepositoryManagerException(e.getMessage());
+        }
+    }
+
+    public Vector<Hashtable<String, Object>> getProductReferences(
+            Hashtable<String, Object> productHash)
+            throws CatalogException {
+        List<Reference> referenceList = null;
+        Product product = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+
+        try {
+            referenceList = catalog.getProductReferences(product);
+            return XmlRpcStructFactory.getXmlRpcReferences(referenceList);
+        } catch (CatalogException e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE, "Unable to obtain references for product: ["
+                    + product.getProductName() + "]: Message: "
+                    + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        }
+
+    }
+
+    public Hashtable<String, Object> getProductById(String productId)
+            throws CatalogException {
+        Product product = null;
+
+        try {
+            product = catalog.getProductById(productId);
+            // it is possible here that the underlying catalog did not
+            // set the ProductType
+            // to obey the contract of the File Manager, we need to make
+            // sure its set here
+            product.setProductType(this.repositoryManager
+                    .getProductTypeById(product.getProductType()
+                            .getProductTypeId()));
+            return XmlRpcStructFactory.getXmlRpcProduct(product);
+        } catch (CatalogException e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE, "Unable to obtain product by id: ["
+                    + productId + "]: Message: " + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } catch (RepositoryManagerException e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE, "Unable to obtain product type by id: ["
+                    + product.getProductType().getProductTypeId()
+                    + "]: Message: " + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        }
+
+    }
+
+    public Hashtable<String, Object> getProductByName(String productName)
+            throws CatalogException {
+        Product product = null;
+
+        try {
+            product = catalog.getProductByName(productName);
+            // it is possible here that the underlying catalog did not
+            // set the ProductType
+            // to obey the contract of the File Manager, we need to make
+            // sure its set here
+            product.setProductType(this.repositoryManager
+                    .getProductTypeById(product.getProductType()
+                            .getProductTypeId()));
+            return XmlRpcStructFactory.getXmlRpcProduct(product);
+        } catch (CatalogException e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE, "Unable to obtain product by name: ["
+                    + productName + "]: Message: " + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        } catch (RepositoryManagerException e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE, "Unable to obtain product type by id: ["
+                    + product.getProductType().getProductTypeId()
+                    + "]: Message: " + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        }
+    }
+
+    public Vector<Hashtable<String, Object>> getProductsByProductType(
+            Hashtable<String, Object> productTypeHash)
+            throws CatalogException {
+        ProductType type = XmlRpcStructFactory
+                .getProductTypeFromXmlRpc(productTypeHash);
+        List<Product> productList = null;
+
+        try {
+            productList = catalog.getProductsByProductType(type);
+            return XmlRpcStructFactory.getXmlRpcProductList(productList);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE,
+                    "Exception obtaining products by product type for type: ["
+                            + type.getName() + "]: Message: " + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        }
+    }
+
+    public Vector<Hashtable<String, Object>> getElementsByProductType(
+            Hashtable<String, Object> productTypeHash)
+            throws ValidationLayerException {
+        ProductType type = XmlRpcStructFactory
+                .getProductTypeFromXmlRpc(productTypeHash);
+        List<Element> elementList = null;
+
+        try {
+            elementList = catalog.getValidationLayer().getElements(type);
+            return XmlRpcStructFactory.getXmlRpcElementList(elementList);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE,
+                    "Exception obtaining elements for product type: ["
+                            + type.getName() + "]: Message: " + e.getMessage());
+            throw new ValidationLayerException(e.getMessage());
+        }
+
+    }
+
+    public Hashtable<String, Object> getElementById(String elementId)
+            throws ValidationLayerException {
+        Element element = null;
+
+        try {
+            element = catalog.getValidationLayer().getElementById(elementId);
+            return XmlRpcStructFactory.getXmlRpcElement(element);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE, "exception retrieving element by id: ["
+                    + elementId + "]: Message: " + e.getMessage());
+            throw new ValidationLayerException(e.getMessage());
+        }
+    }
+
+    public Hashtable<String, Object> getElementByName(String elementName)
+            throws ValidationLayerException {
+        Element element = null;
+
+        try {
+            element = catalog.getValidationLayer()
+                    .getElementByName(elementName);
+            return XmlRpcStructFactory.getXmlRpcElement(element);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE, "exception retrieving element by name: ["
+                    + elementName + "]: Message: " + e.getMessage());
+            throw new ValidationLayerException(e.getMessage());
+        }
+    }
+
+    public Vector<Hashtable<String, Object>> complexQuery(
+            Hashtable<String, Object> complexQueryHash) throws CatalogException {
+        try {
+            ComplexQuery complexQuery = XmlRpcStructFactory
+                    .getComplexQueryFromXmlRpc(complexQueryHash);
+
+            // get ProductTypes
+            List<ProductType> productTypes = null;
+            if (complexQuery.getReducedProductTypeNames() == null) {
+                productTypes = this.repositoryManager.getProductTypes();
+            } else {
+                productTypes = new Vector<ProductType>();
+                for (String productTypeName : complexQuery
+                        .getReducedProductTypeNames())
+                    productTypes.add(this.repositoryManager
+                            .getProductTypeByName(productTypeName));
+            }
+
+            // get Metadata
+            List<QueryResult> queryResults = new LinkedList<QueryResult>();
+            for (ProductType productType : productTypes) {
+                List<String> productIds = catalog.query(this.getCatalogQuery(
+                        complexQuery, productType), productType);
+                for (String productId : productIds) {
+                    Product product = catalog.getProductById(productId);
+                    product.setProductType(productType);
+                    QueryResult qr = new QueryResult(product, this
+                            .getReducedMetadata(product, complexQuery
+                                    .getReducedMetadata()));
+                    qr.setToStringFormat(complexQuery
+                            .getToStringResultFormat());
+                    queryResults.add(qr);
+                }
+            }
+
+            LOG.log(Level.INFO, "Query returned " + queryResults.size()
+                    + " results");
+
+            // filter query results
+            if (complexQuery.getQueryFilter() != null) {
+                queryResults = applyFilterToResults(queryResults, complexQuery
+                        .getQueryFilter());
+                LOG.log(Level.INFO, "Filter returned " + queryResults.size()
+                        + " results");
+            }
+
+            // sort query results
+            if (complexQuery.getSortByMetKey() != null)
+                queryResults = sortQueryResultList(queryResults, complexQuery
+                        .getSortByMetKey());
+
+            return XmlRpcStructFactory.getXmlRpcQueryResults(queryResults);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new CatalogException("Failed to perform complex query : "
+                    + e.getMessage());
+        }
+    }
+    
+    public Vector<Hashtable<String, Object>> query(
+            Hashtable<String, Object> queryHash,
+            Hashtable<String, Object> productTypeHash)
+            throws CatalogException {
+        Query query = XmlRpcStructFactory.getQueryFromXmlRpc(queryHash);
+        ProductType type = XmlRpcStructFactory
+                .getProductTypeFromXmlRpc(productTypeHash);
+        return XmlRpcStructFactory.getXmlRpcProductList(this.query(query, type));
+    }
+
+    public Hashtable<String, Object> getProductTypeByName(String productTypeName)
+            throws RepositoryManagerException {
+        ProductType type = repositoryManager
+                .getProductTypeByName(productTypeName);
+        return XmlRpcStructFactory.getXmlRpcProductType(type);
+    }
+
+    public Hashtable<String, Object> getProductTypeById(String productTypeId)
+            throws RepositoryManagerException {
+        ProductType type = null;
+
+        try {
+            type = repositoryManager.getProductTypeById(productTypeId);
+            return XmlRpcStructFactory.getXmlRpcProductType(type);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE,
+                    "Exception obtaining product type by id for product type: ["
+                            + productTypeId + "]: Message: " + e.getMessage());
+            throw new RepositoryManagerException(e.getMessage());
+        }
+    }
+    
+    public synchronized boolean updateMetadata(Hashtable<String, Object> productHash, 
+        Hashtable<String, Object> metadataHash) throws CatalogException{
+        Product product = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+        Metadata met = new Metadata();
+        met.addMetadata(metadataHash);
+        Metadata oldMetadata = catalog.getMetadata(product);
+        catalog.removeMetadata(oldMetadata, product);
+        catalog.addMetadata(met, product);
+        return true;
+    }
+
+    public synchronized String catalogProduct(Hashtable<String, Object> productHash)
+            throws CatalogException {
+        Product p = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+        return catalogProduct(p);
+    }
+
+    public synchronized boolean addMetadata(Hashtable<String, Object> productHash,
+            Hashtable<String, String> metadata) throws CatalogException {
+        Product p = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+        Metadata m = new Metadata();
+        m.addMetadata((Hashtable)metadata);
+        return addMetadata(p, m) != null;
+    }
+
+    public synchronized boolean addProductReferences(Hashtable<String, Object> productHash)
+            throws CatalogException {
+        Product product = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+        return addProductReferences(product);
+    }
+
+    public String ingestProduct(Hashtable<String, Object> productHash,
+      Hashtable<String, String> metadata, boolean clientTransfer)
+      throws VersioningException, RepositoryManagerException,
+      DataTransferException, CatalogException {
+
+    Product p = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+
+    try {
+      // first, create the product
+      p.setTransferStatus(Product.STATUS_TRANSFER);
+      catalogProduct(p);
+
+      // now add the metadata
+      Metadata m = new Metadata();
+      m.addMetadata((Hashtable)metadata);
+      Metadata expandedMetdata = addMetadata(p, m);
+
+      // version the product
+      if (!clientTransfer || (clientTransfer
+          && Boolean.getBoolean("org.apache.oodt.cas.filemgr.serverside.versioning"))) {
+        Versioner versioner = null;
+        try {
+          versioner = GenericFileManagerObjectFactory
+              .getVersionerFromClassName(p.getProductType().getVersioner());
+          versioner.createDataStoreReferences(p, expandedMetdata);
+        } catch (Exception e) {
+          LOG.log(Level.SEVERE,
+              "ingestProduct: VersioningException when versioning Product: "
+                  + p.getProductName() + " with Versioner "
+                  + p.getProductType().getVersioner() + ": Message: "
+                  + e.getMessage());
+          throw new VersioningException(e);
+        }
+
+        // add the newly versioned references to the data store
+        addProductReferences(p);
+      }
+
+      if (!clientTransfer) {
+        LOG.log(Level.FINEST,
+              "File Manager: ingest: no client transfer enabled, "
+                  + "server transfering product: [" + p.getProductName() + "]");
+
+        // now transfer the product
+        try {
+          dataTransfer.transferProduct(p);
+          // now update the product's transfer status in the data store
+          p.setTransferStatus(Product.STATUS_RECEIVED);
+
+          try {
+            catalog.setProductTransferStatus(p);
+          } catch (CatalogException e) {
+            LOG.log(Level.SEVERE, "ingestProduct: CatalogException "
+                + "when updating product transfer status for Product: "
+                + p.getProductName() + " Message: " + e.getMessage());
+            throw e;
+          }
+        } catch (Exception e) {
+          LOG.log(Level.SEVERE,
+              "ingestProduct: DataTransferException when transfering Product: "
+                  + p.getProductName() + ": Message: " + e.getMessage());
+          throw new DataTransferException(e);
+        }
+      }
+
+      // that's it!
+      return p.getProductId();
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw new CatalogException("Error ingesting product [" + p + "] : "
+          + e.getMessage());
+    }
+
+  }
+
+   public byte[] retrieveFile(String filePath, int offset, int numBytes)
+         throws DataTransferException {
+      FileInputStream is = null;
+      try {
+         byte[] fileData = new byte[numBytes];
+         (is = new FileInputStream(filePath)).skip(offset);
+         int bytesRead = is.read(fileData);
+         if (bytesRead != -1) {
+            byte[] fileDataTruncated = new byte[bytesRead];
+            System.arraycopy(fileData, 0, fileDataTruncated, 0, bytesRead);
+            return fileDataTruncated;
+         } else {
+            return new byte[0];
+         }
+      } catch (Exception e) {
+         LOG.log(Level.SEVERE, "Failed to read '" + numBytes
+               + "' bytes from file '" + filePath + "' at index '" + offset
+               + "' : " + e.getMessage(), e);
+         throw new DataTransferException("Failed to read '" + numBytes
+               + "' bytes from file '" + filePath + "' at index '" + offset
+               + "' : " + e.getMessage(), e);
+      } finally {
+         try { is.close(); } catch (Exception e) {}
+      }
+   }
+    
+    public boolean transferFile(String filePath, byte[] fileData, int offset,
+            int numBytes) {
+        File outFile = new File(filePath);
+        boolean success = true;
+
+        FileOutputStream fOut = null;
+
+        if (outFile.exists()) {
+            try {
+                fOut = new FileOutputStream(outFile, true);
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+                LOG.log(Level.SEVERE,
+                        "FileNotFoundException when trying to use RandomAccess file on "
+                                + filePath + ": Message: " + e.getMessage());
+                success = false;
+            }
+        } else {
+            // create the output directory
+            String outFileDirPath = outFile.getAbsolutePath().substring(0,
+                    outFile.getAbsolutePath().lastIndexOf("/"));
+            LOG.log(Level.INFO, "Outfile directory: " + outFileDirPath);
+            File outFileDir = new File(outFileDirPath);
+            outFileDir.mkdirs();
+
+            try {
+                fOut = new FileOutputStream(outFile, false);
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+                LOG.log(Level.SEVERE,
+                        "FileNotFoundException when trying to use RandomAccess file on "
+                                + filePath + ": Message: " + e.getMessage());
+                success = false;
+            }
+        }
+
+        if (success) {
+            try {
+                fOut.write(fileData, (int) offset, (int) numBytes);
+            } catch (IOException e) {
+                e.printStackTrace();
+                LOG.log(Level.SEVERE, "IOException when trying to write file "
+                        + filePath + ": Message: " + e.getMessage());
+                success = false;
+            } finally {
+                if (fOut != null) {
+                    try {
+                        fOut.close();
+                    } catch (Exception ignore) {
+                    }
+
+                    fOut = null;
+                }
+            }
+        }
+
+        outFile = null;
+        return success;
+    }
+
+    public boolean moveProduct(Hashtable<String, Object> productHash, String newPath)
+            throws DataTransferException {
+
+        Product p = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+
+        // first thing we care about is if the product is flat or heirarchical
+        if (p.getProductStructure().equals(Product.STRUCTURE_FLAT)) {
+            // we just need to get its first reference
+            if (p.getProductReferences() == null
+                    || (p.getProductReferences() != null && p
+                            .getProductReferences().size() != 1)) {
+                throw new DataTransferException(
+                        "Flat products must have a single reference: cannot move");
+            }
+
+            // okay, it's fine to move it
+            // first, we need to update the data store ref
+            Reference r = (Reference) p.getProductReferences().get(0);
+            if (r.getDataStoreReference().equals(
+                    new File(newPath).toURI().toString())) {
+                throw new DataTransferException("cannot move product: ["
+                        + p.getProductName() + "] to same location: ["
+                        + r.getDataStoreReference() + "]");
+            }
+
+            // create a copy of the current data store path: we'll need it to
+            // do the data transfer
+            Reference copyRef = new Reference(r);
+
+            // update the copyRef to have the data store ref as the orig ref
+            // the the newLoc as the new ref
+            copyRef.setOrigReference(r.getDataStoreReference());
+            copyRef.setDataStoreReference(new File(newPath).toURI().toString());
+
+            p.getProductReferences().clear();
+            p.getProductReferences().add(copyRef);
+
+            // now transfer it
+            try {
+                this.dataTransfer.transferProduct(p);
+            } catch (IOException e) {
+                throw new DataTransferException(e.getMessage());
+            }
+
+            // now delete the original copy
+            try {
+                if (!new File(new URI(copyRef.getOrigReference())).delete()) {
+                    LOG.log(Level.WARNING, "Deletion of original file: ["
+                            + r.getDataStoreReference()
+                            + "] on product move returned false");
+                }
+            } catch (URISyntaxException e) {
+                throw new DataTransferException(
+                        "URI Syntax exception trying to remove original product ref: Message: "
+                                + e.getMessage());
+            }
+
+            // now save the updated reference
+            try {
+                this.catalog.modifyProduct(p);
+                return true;
+            } catch (CatalogException e) {
+                throw new DataTransferException(e.getMessage());
+            }
+        } else
+            throw new UnsupportedOperationException(
+                    "Moving of heirarhical and stream products not supported yet");
+    }
+
+    public boolean removeFile(String filePath) throws DataTransferException, IOException {
+      // TODO(bfoster): Clean this up so that it deletes by product not file.
+      Product product = new Product();
+      Reference r = new Reference();
+      r.setDataStoreReference(filePath);
+      product.setProductReferences(Lists.newArrayList(r));
+      dataTransfer.deleteProduct(product);
+      return true;
+    }
+
+    public boolean modifyProduct(Hashtable<?, ?> productHash) throws CatalogException {
+        Product p = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+
+        try {
+            catalog.modifyProduct(p);
+        } catch (CatalogException e) {
+            LOG.log(Level.WARNING, "Exception modifying product: ["
+                    + p.getProductId() + "]: Message: " + e.getMessage(), e);
+            throw e;
+        }
+
+        return true;
+    }
+
+    public boolean removeProduct(Hashtable<String, Object> productHash) throws CatalogException {
+        Product p = XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+
+        try {
+            catalog.removeProduct(p);
+        } catch (CatalogException e) {
+            LOG.log(Level.WARNING, "Exception modifying product: ["
+                    + p.getProductId() + "]: Message: " + e.getMessage(), e);
+            throw e;
+        }
+
+        return true;
+    }
+    
+    public Hashtable<String, Object> getCatalogValues(
+            Hashtable<String, Object> metadataHash,
+            Hashtable<String, Object> productTypeHash)
+            throws RepositoryManagerException {
+        Metadata m = new Metadata();
+        m.addMetadata(metadataHash);
+        ProductType productType = XmlRpcStructFactory.getProductTypeFromXmlRpc(productTypeHash);
+        return this.getCatalogValues(m, productType).getHashtable();
+    }
+    
+    public Hashtable<String, Object> getOrigValues(
+            Hashtable<String, Object> metadataHash,
+            Hashtable<String, Object> productTypeHash)
+            throws RepositoryManagerException {
+        Metadata m = new Metadata();
+        m.addMetadata(metadataHash);
+        ProductType productType = XmlRpcStructFactory.getProductTypeFromXmlRpc(productTypeHash);
+        return this.getOrigValues(m, productType).getHashtable();
+    }
+    
+    public Hashtable<String, Object> getCatalogQuery(
+            Hashtable<String, Object> queryHash,
+            Hashtable<String, Object> productTypeHash)
+            throws RepositoryManagerException, QueryFormulationException {
+        Query query = XmlRpcStructFactory.getQueryFromXmlRpc(queryHash);
+        ProductType productType = XmlRpcStructFactory.getProductTypeFromXmlRpc(productTypeHash);
+        return XmlRpcStructFactory.getXmlRpcQuery(this.getCatalogQuery(query, productType));
+    }
+
+    public static void main(String[] args) throws Exception {
+        int portNum = -1;
+        String usage = "FileManager --portNum <port number for xml rpc service>\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--portNum")) {
+                portNum = Integer.parseInt(args[++i]);
+            }
+        }
+
+        if (portNum == -1) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+        
+        @SuppressWarnings("unused")
+        XmlRpcFileManager manager = new XmlRpcFileManager(portNum);
+
+        for (;;)
+            try {
+                Thread.currentThread().join();
+            } catch (InterruptedException ignore) {
+            }
+    }
+
+    public boolean shutdown() {
+        if (this.webServer != null) {
+            this.webServer.shutdown();
+            this.webServer = null;
+            return true;
+        } else
+            return false;
+    }
+
+    private synchronized String catalogProduct(Product p)
+            throws CatalogException {
+        try {
+            catalog.addProduct(p);
+        } catch (CatalogException e) {
+            LOG.log(Level.SEVERE,
+                    "ingestProduct: CatalogException when adding Product: "
+                            + p.getProductName() + " to Catalog: Message: "
+                            + e.getMessage());
+            throw e;
+        }
+
+        return p.getProductId();
+    }
+
+    private synchronized Metadata addMetadata(Product p, Metadata m)
+            throws CatalogException {
+        
+        //apply handlers
+        try {
+            m = this.getCatalogValues(m, p.getProductType());
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, "Failed to get handlers for product '" + p
+                    + "' : " + e.getMessage());
+        }
+        
+        // first do server side metadata extraction
+        Metadata metadata = runExtractors(p, m);
+
+        try {
+            catalog.addMetadata(metadata, p);
+        } catch (CatalogException e) {
+            LOG.log(Level.SEVERE,
+                    "ingestProduct: CatalogException when adding metadata "
+                            + metadata + " for product: " + p.getProductName()
+                            + ": Message: " + e.getMessage());
+            throw e;
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE,
+                    "ingestProduct: General Exception when adding metadata "
+                            + metadata + " for product: " + p.getProductName()
+                            + ": Message: " + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        }
+
+        return metadata;
+    }
+
+    private Metadata runExtractors(Product product, Metadata metadata) {
+        // make sure that the product type definition is present
+        try {
+            product.setProductType(repositoryManager.getProductTypeById(product
+                    .getProductType().getProductTypeId()));
+        } catch (RepositoryManagerException e) {
+            LOG.log(Level.SEVERE, "Failed to load ProductType " + product
+              .getProductType().getProductTypeId(), e);
+            return null;
+        }
+
+        Metadata met = new Metadata();
+        met.addMetadata(metadata.getHashtable());
+
+        if (product.getProductType().getExtractors() != null) {
+            for (ExtractorSpec spec: product.getProductType().getExtractors()) {
+                FilemgrMetExtractor extractor = GenericFileManagerObjectFactory
+                        .getExtractorFromClassName(spec.getClassName());
+                extractor.configure(spec.getConfiguration());
+                LOG.log(Level.INFO, "Running Met Extractor: ["
+                        + extractor.getClass().getName()
+                        + "] for product type: ["
+                        + product.getProductType().getName() + "]");
+                try {
+                    met = extractor.extractMetadata(product, met);
+                } catch (MetExtractionException e) {
+                    LOG.log(Level.SEVERE,
+                            "Exception extractor metadata from product: ["
+                                    + product.getProductName()
+                                    + "]: using extractor: ["
+                                    + extractor.getClass().getName()
+                                    + "]: Message: " + e.getMessage(), e);
+                }
+            }
+        }
+
+        return met;
+    }
+
+    private synchronized boolean addProductReferences(Product product)
+            throws CatalogException {
+        catalog.addProductReferences(product);
+        return true;
+    }
+
+    private void setProductType(List<Product> products) throws Exception {
+        if (products != null && products.size() > 0) {
+            for (Iterator<Product> i = products.iterator(); i.hasNext();) {
+                Product p = i.next();
+                try {
+                    p.setProductType(repositoryManager.getProductTypeById(p
+                            .getProductType().getProductTypeId()));
+                } catch (RepositoryManagerException e) {
+                    throw new Exception(e.getMessage());
+                }
+            }
+        }
+    }
+    
+    private List<Product> query(Query query, ProductType productType) throws CatalogException {
+        List<String> productIdList = null;
+        List<Product> productList = null;
+
+        try {            
+            productIdList = catalog.query(this.getCatalogQuery(query, productType), productType);
+
+            if (productIdList != null && productIdList.size() > 0) {
+                productList = new Vector<Product>(productIdList.size());
+                for (Iterator<String> i = productIdList.iterator(); i.hasNext();) {
+                    String productId = i.next();
+                    Product product = catalog.getProductById(productId);
+                    // it is possible here that the underlying catalog did not
+                    // set the ProductType
+                    // to obey the contract of the File Manager, we need to make
+                    // sure its set here
+                    product.setProductType(this.repositoryManager
+                            .getProductTypeById(product.getProductType()
+                                    .getProductTypeId()));
+                    productList.add(product);
+                }
+                return productList;
+            } else {
+                return new Vector<Product>(); // null values not supported by XML-RPC
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE,
+                    "Exception performing query against catalog for product type: ["
+                            + productType.getName() + "] Message: " + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        }
+    }
+    
+    private Metadata getReducedMetadata(Product product, List<String> elements) throws CatalogException {
+        try {
+            Metadata m = null;
+            if (elements != null && elements.size() > 0) {
+                m = catalog.getReducedMetadata(product, elements);
+            }else {
+                m = this.getMetadata(product);
+            }
+            if(this.expandProductMet) m = this.buildProductMetadata(product, m);            
+            return this.getOrigValues(m, product.getProductType());
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE,
+                    "Exception obtaining metadata from catalog for product: ["
+                            + product.getProductId() + "]: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        }
+    }
+    
+    private Metadata getMetadata(Product product) throws CatalogException {
+        try {
+            Metadata m = catalog.getMetadata(product);
+            if(this.expandProductMet) m = this.buildProductMetadata(product, m);
+            return this.getOrigValues(m, product.getProductType());
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE,
+                    "Exception obtaining metadata from catalog for product: ["
+                            + product.getProductId() + "]: Message: "
+                            + e.getMessage());
+            throw new CatalogException(e.getMessage());
+        }
+    }
+    
+    private Metadata getOrigValues(Metadata metadata, ProductType productType) 
+            throws RepositoryManagerException {
+        List<TypeHandler> handlers = this.repositoryManager.getProductTypeById(
+                productType.getProductTypeId()).getHandlers();
+        if (handlers != null) {
+            for (Iterator<TypeHandler> iter = handlers.iterator(); iter
+                    .hasNext();)
+                iter.next().postGetMetadataHandle(metadata);
+        }
+        return metadata;
+    }
+    
+    private Metadata getCatalogValues(Metadata metadata, ProductType productType) 
+            throws RepositoryManagerException {
+        List<TypeHandler> handlers = this.repositoryManager.getProductTypeById(
+                productType.getProductTypeId()).getHandlers();
+        if (handlers != null) {
+            for (Iterator<TypeHandler> iter = handlers.iterator(); iter
+                    .hasNext();)
+                iter.next().preAddMetadataHandle(metadata);
+        }
+        return metadata;
+    }
+    
+    private Query getCatalogQuery(Query query, ProductType productType)
+            throws RepositoryManagerException, QueryFormulationException {
+        List<TypeHandler> handlers = this.repositoryManager.getProductTypeById(
+                productType.getProductTypeId()).getHandlers();
+        if (handlers != null) {
+            for (Iterator<TypeHandler> iter = handlers.iterator(); iter
+                    .hasNext();)
+                iter.next().preQueryHandle(query);
+        }
+        return query;
+    }
+
+    @SuppressWarnings("unchecked")
+    private List<QueryResult> applyFilterToResults(
+            List<QueryResult> queryResults, QueryFilter queryFilter)
+            throws Exception {
+        List<TimeEvent> events = new LinkedList<TimeEvent>();
+        for (QueryResult queryResult : queryResults) {
+            Metadata m = new Metadata();
+            m.addMetadata(queryFilter.getPriorityMetKey(), queryResult
+                .getMetadata().getMetadata(queryFilter.getPriorityMetKey()));
+            events.add(new ObjectTimeEvent<QueryResult>(
+                DateUtils.getTimeInMillis(DateUtils.toCalendar(queryResult
+                    .getMetadata().getMetadata(queryFilter.getStartDateTimeMetKey()),
+                    DateUtils.FormatType.UTC_FORMAT), DateUtils.julianEpoch), 
+                DateUtils.getTimeInMillis(DateUtils.toCalendar(queryResult.getMetadata()
+                    .getMetadata(queryFilter.getEndDateTimeMetKey()),
+                    DateUtils.FormatType.UTC_FORMAT),
+                DateUtils.julianEpoch), queryFilter.getConverter()
+                    .convertToPriority(this.getCatalogValues(m,
+                    queryResult.getProduct().getProductType())
+                    .getMetadata(queryFilter.getPriorityMetKey())),
+                queryResult));
+        }
+        events = queryFilter.getFilterAlgor().filterEvents(events);
+        List<QueryResult> filteredQueryResults = new LinkedList<QueryResult>();
+        for (TimeEvent event : events)
+            filteredQueryResults.add(((ObjectTimeEvent<QueryResult>) event)
+                    .getTimeObject());
+
+        return filteredQueryResults;
+    }
+
+    private List<QueryResult> sortQueryResultList(List<QueryResult> queryResults,
+      String sortByMetKey) {
+    QueryResult[] resultsArray = queryResults
+        .toArray(new QueryResult[queryResults.size()]);
+    QueryResultComparator qrComparator = new QueryResultComparator();
+    qrComparator.setSortByMetKey(sortByMetKey);
+    Arrays.sort(resultsArray, qrComparator);
+    return Arrays.asList(resultsArray);
+  }
+
+    private Metadata buildProductMetadata(Product product, Metadata metadata)
+      throws CatalogException {
+    Metadata pMet = new Metadata();
+    pMet.replaceMetadata(ProductMetKeys.PRODUCT_ID, product.getProductId() != null ? 
+        product.getProductId():"unknown");
+    pMet.replaceMetadata(ProductMetKeys.PRODUCT_NAME, product.getProductName() != null ? 
+        product.getProductName():"unknown");
+    pMet.replaceMetadata(ProductMetKeys.PRODUCT_STRUCTURE, product
+        .getProductStructure() != null ? product.getProductStructure():"unknown");
+    pMet.replaceMetadata(ProductMetKeys.PRODUCT_TRANSFER_STATUS, product
+        .getTransferStatus() != null ? product.getTransferStatus():"unknown");
+    pMet.replaceMetadata(ProductMetKeys.PRODUCT_ROOT_REFERENCE, product.getRootRef() != null ? 
+        VersioningUtils
+        .getAbsolutePathFromUri(product.getRootRef().getDataStoreReference()):"unknown");
+
+    List<Reference> refs = product.getProductReferences();
+
+    if (refs == null || (refs != null && refs.size() == 0)) {
+      refs = this.catalog.getProductReferences(product);
+    }
+
+    for (Reference r : refs) {
+      pMet.replaceMetadata(ProductMetKeys.PRODUCT_ORIG_REFS, r.getOrigReference() != null
+          ? VersioningUtils
+          .getAbsolutePathFromUri(r.getOrigReference()):"unknown");
+      pMet.replaceMetadata(ProductMetKeys.PRODUCT_DATASTORE_REFS,
+          r.getDataStoreReference() != null ? 
+              VersioningUtils.getAbsolutePathFromUri(r.getDataStoreReference()):"unknown");
+      pMet.replaceMetadata(ProductMetKeys.PRODUCT_FILE_SIZES, String.valueOf(r
+          .getFileSize()));
+      pMet.replaceMetadata(ProductMetKeys.PRODUCT_MIME_TYPES,
+          r.getMimeType() != null ? r.getMimeType().getName() : "unknown");
+    }
+
+    return pMet;
+  }
+    
+    private void loadConfiguration() throws FileNotFoundException, IOException {
+    // set up the configuration, if there is any
+    if (System.getProperty("org.apache.oodt.cas.filemgr.properties") != null) {
+      String configFile = System
+          .getProperty("org.apache.oodt.cas.filemgr.properties");
+      LOG.log(Level.INFO,
+          "Loading File Manager Configuration Properties from: [" + configFile
+              + "]");
+      System.getProperties().load(new FileInputStream(new File(configFile)));
+    }
+
+    String metaFactory = null, dataFactory = null, transferFactory = null;
+
+    metaFactory = System.getProperty("filemgr.catalog.factory",
+        "org.apache.oodt.cas.filemgr.catalog.DataSourceCatalogFactory");
+    dataFactory = System
+        .getProperty("filemgr.repository.factory",
+            "org.apache.oodt.cas.filemgr.repository.DataSourceRepositoryManagerFactory");
+    transferFactory = System.getProperty("filemgr.datatransfer.factory",
+        "org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory");
+
+    catalog = GenericFileManagerObjectFactory
+        .getCatalogServiceFromFactory(metaFactory);
+    repositoryManager = GenericFileManagerObjectFactory
+        .getRepositoryManagerServiceFromFactory(dataFactory);
+    dataTransfer = GenericFileManagerObjectFactory
+        .getDataTransferServiceFromFactory(transferFactory);
+
+    transferStatusTracker = new TransferStatusTracker(catalog);
+
+    // got to start the server before setting up the transfer client since
+    // it
+    // checks for a live server
+    dataTransfer
+        .setFileManagerUrl(new URL("http://localhost:" + webServerPort));
+
+    expandProductMet = Boolean
+        .getBoolean("org.apache.oodt.cas.filemgr.metadata.expandProduct");
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/XmlRpcFileManagerClient.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/XmlRpcFileManagerClient.java
new file mode 100644
index 0000000..7ea3129
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/XmlRpcFileManagerClient.java
@@ -0,0 +1,1387 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.system;
+
+//APACHE imports
+import org.apache.xmlrpc.CommonsXmlRpcTransport;
+import org.apache.xmlrpc.XmlRpcClient;
+import org.apache.xmlrpc.XmlRpcClientException;
+import org.apache.xmlrpc.XmlRpcException;
+import org.apache.xmlrpc.XmlRpcTransport;
+import org.apache.xmlrpc.XmlRpcTransportFactory;
+//JDK imports
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.File;
+//OODT imports
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.HttpMethodRetryHandler;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.cli.CmdLineUtility;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.util.GenericFileManagerObjectFactory;
+import org.apache.oodt.cas.filemgr.util.XmlRpcStructFactory;
+import org.apache.oodt.cas.filemgr.versioning.Versioner;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.filemgr.datatransfer.DataTransfer;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.query.ComplexQuery;
+import org.apache.oodt.cas.filemgr.structs.query.QueryResult;
+
+/**
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ * @version $Revision$
+ * 
+ * <p>
+ * The XML RPC based file manager client.
+ * </p>
+ * 
+ */
+public class XmlRpcFileManagerClient {
+
+    /* our xml rpc client */
+    private XmlRpcClient client = null;
+
+    /* our log stream */
+    private static Logger LOG = Logger.getLogger(XmlRpcFileManagerClient.class
+            .getName());
+
+    /* file manager url */
+    private URL fileManagerUrl = null;
+
+    /* data transferer needed if client is request to move files itself */
+    private DataTransfer dataTransfer = null;
+
+    public XmlRpcFileManagerClient(final URL url) throws ConnectionException {
+       this(url, true);
+    }
+
+    /**
+     * <p>
+     * Constructs a new XmlRpcFileManagerClient with the given <code>url</code>.
+     * </p>
+     * 
+     * @param url
+     *            The url pointer to the xml rpc file manager service.
+     * @param testConnection
+     *            Whether or not to check if server at given url is alive.
+     */
+    public XmlRpcFileManagerClient(final URL url, boolean testConnection)
+          throws ConnectionException {
+        // set up the configuration, if there is any
+        if (System.getProperty("org.apache.oodt.cas.filemgr.properties") != null) {
+            String configFile = System
+                    .getProperty("org.apache.oodt.cas.filemgr.properties");
+            LOG.log(Level.INFO,
+                    "Loading File Manager Configuration Properties from: ["
+                            + configFile + "]");
+            try {
+                System.getProperties().load(
+                        new FileInputStream(new File(configFile)));
+            } catch (Exception e) {
+                LOG.log(Level.INFO,
+                        "Error loading configuration properties from: ["
+                                + configFile + "]");
+            }
+
+        }
+
+        XmlRpcTransportFactory transportFactory = new XmlRpcTransportFactory() {
+
+            public XmlRpcTransport createTransport()
+                    throws XmlRpcClientException {
+                HttpClient client = new HttpClient();
+                client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
+                        new HttpMethodRetryHandler() {
+
+                            public boolean retryMethod(HttpMethod method,
+                                    IOException e, int count) {
+                                if (count < Integer
+                                        .getInteger(
+                                                "org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retries",
+                                                3).intValue()) {
+                                    try {
+                                        Thread
+                                                .sleep(Integer
+                                                        .getInteger(
+                                                                "org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retry.interval.seconds",
+                                                                0).intValue() * 1000);
+                                        return true;
+                                    } catch (Exception e1) {
+                                    }
+                                }
+                                return false;
+                            }
+
+                        });
+                CommonsXmlRpcTransport transport = new CommonsXmlRpcTransport(
+                        url, client);
+                transport
+                        .setConnectionTimeout(Integer
+                                .getInteger(
+                                        "org.apache.oodt.cas.filemgr.system.xmlrpc.connectionTimeout.minutes",
+                                        20).intValue() * 60 * 1000);
+                transport
+                        .setTimeout(Integer
+                                .getInteger(
+                                        "org.apache.oodt.cas.filemgr.system.xmlrpc.requestTimeout.minutes",
+                                        60).intValue() * 60 * 1000);
+
+                return transport;
+            }
+
+            public void setProperty(String arg0, Object arg1) {
+            }
+
+        };
+
+        client = new XmlRpcClient(url, transportFactory);
+        fileManagerUrl = url;
+
+        if (testConnection && !isAlive()) {
+            throw new ConnectionException("Exception connecting to filemgr: ["
+                    + this.fileManagerUrl + "]");
+        }
+
+    }
+    
+    public boolean refreshConfigAndPolicy() {
+      boolean success = false;
+  
+      Vector<Object> argList = new Vector<Object>();
+      try {
+        success = ((Boolean) client.execute("filemgr.refreshConfigAndPolicy",
+            argList)).booleanValue();
+      } catch (XmlRpcException e) {
+        LOG.log(Level.WARNING, "XmlRpcException when connecting to filemgr: ["
+            + this.fileManagerUrl + "]");
+        success = false;
+      } catch (IOException e) {
+        LOG.log(Level.WARNING, "IOException when connecting to filemgr: ["
+            + this.fileManagerUrl + "]");
+        success = false;
+      }
+  
+      return success;
+  }
+
+    public boolean isAlive() {
+        boolean connected = false;
+
+        Vector<Object> argList = new Vector<Object>();
+        try {
+            connected = ((Boolean) client.execute("filemgr.isAlive", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            LOG.log(Level.WARNING,
+                    "XmlRpcException when connecting to filemgr: ["
+                            + this.fileManagerUrl + "]");
+            connected = false;
+        } catch (IOException e) {
+            LOG.log(Level.WARNING, "IOException when connecting to filemgr: ["
+                    + this.fileManagerUrl + "]");
+            connected = false;
+        }
+
+        return connected;
+    }
+
+    public boolean transferringProduct(Product product)
+            throws DataTransferException {
+        Vector<Object> argList = new Vector<Object>();
+        Hashtable<String, Object> productHash = XmlRpcStructFactory
+                .getXmlRpcProduct(product);
+        argList.add(productHash);
+
+        boolean success = false;
+
+        try {
+            success = ((Boolean) client.execute("filemgr.transferringProduct",
+                    argList)).booleanValue();
+        } catch (XmlRpcException e) {
+            throw new DataTransferException(e.getMessage());
+        } catch (IOException e) {
+            throw new DataTransferException(e.getMessage());
+        }
+
+        return success;
+    }
+
+    public boolean removeProductTransferStatus(Product product)
+            throws DataTransferException {
+        Hashtable<String, Object> productHash = XmlRpcStructFactory
+                .getXmlRpcProduct(product);
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(productHash);
+
+        boolean success = false;
+
+        try {
+            success = ((Boolean) client.execute(
+                    "filemgr.removeProductTransferStatus", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            throw new DataTransferException(e.getMessage());
+        } catch (IOException e) {
+            throw new DataTransferException(e.getMessage());
+        }
+
+        return success;
+    }
+
+    public boolean isTransferComplete(Product product)
+            throws DataTransferException {
+        Hashtable<String, Object> productHash = XmlRpcStructFactory
+                .getXmlRpcProduct(product);
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(productHash);
+
+        boolean success = false;
+
+        try {
+            success = ((Boolean) client.execute("filemgr.isTransferComplete",
+                    argList)).booleanValue();
+        } catch (XmlRpcException e) {
+            throw new DataTransferException(e.getMessage());
+        } catch (IOException e) {
+            throw new DataTransferException(e.getMessage());
+        }
+
+        return success;
+    }
+
+    public boolean moveProduct(Product product, String newPath)
+            throws DataTransferException {
+        Hashtable<String, Object> productHash = XmlRpcStructFactory
+                .getXmlRpcProduct(product);
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(productHash);
+        argList.add(newPath);
+
+        boolean success = false;
+
+        try {
+            success = ((Boolean) client.execute("filemgr.moveProduct", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            throw new DataTransferException(e.getMessage());
+        } catch (IOException e) {
+            throw new DataTransferException(e.getMessage());
+        }
+
+        return success;
+    }
+
+    public boolean modifyProduct(Product product) throws CatalogException {
+        Hashtable<String, Object> productHash = XmlRpcStructFactory
+                .getXmlRpcProduct(product);
+
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(productHash);
+
+        boolean success = false;
+
+        try {
+            success = ((Boolean) client.execute("filemgr.modifyProduct",
+                    argList)).booleanValue();
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        return success;
+
+    }
+
+    public boolean removeProduct(Product product) throws CatalogException {
+        Hashtable<String, Object> productHash = XmlRpcStructFactory
+                .getXmlRpcProduct(product);
+
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(productHash);
+
+        boolean success = false;
+
+        try {
+            success = ((Boolean) client.execute("filemgr.removeProduct",
+                    argList)).booleanValue();
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        return success;
+
+    }
+
+    @SuppressWarnings("unchecked")
+    public FileTransferStatus getCurrentFileTransfer()
+            throws DataTransferException {
+        Vector<Object> argList = new Vector<Object>();
+
+        Hashtable<String, Object> statusHash = null;
+        FileTransferStatus status = null;
+
+        try {
+            statusHash = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getCurrentFileTransfer", argList);
+        } catch (XmlRpcException e) {
+            throw new DataTransferException(e.getMessage());
+        } catch (IOException e) {
+            throw new DataTransferException(e.getMessage());
+        }
+
+        if (statusHash != null) {
+            status = XmlRpcStructFactory
+                    .getFileTransferStatusFromXmlRpc(statusHash);
+        }
+
+        return status;
+    }
+
+    @SuppressWarnings("unchecked")
+    public List<FileTransferStatus> getCurrentFileTransfers()
+            throws DataTransferException {
+        Vector<Object> argList = new Vector<Object>();
+
+        Vector<Hashtable<String, Object>> statusVector = null;
+        List<FileTransferStatus> statuses = null;
+
+        try {
+            statusVector = (Vector<Hashtable<String, Object>>) client.execute(
+                    "filemgr.getCurrentFileTransfers", argList);
+        } catch (XmlRpcException e) {
+            throw new DataTransferException(e.getMessage());
+        } catch (IOException e) {
+            throw new DataTransferException(e.getMessage());
+        }
+
+        if (statusVector != null) {
+            statuses = XmlRpcStructFactory
+                    .getFileTransferStatusesFromXmlRpc(statusVector);
+        }
+
+        return statuses;
+    }
+
+    public double getProductPctTransferred(Product product)
+            throws DataTransferException {
+        Vector<Object> argList = new Vector<Object>();
+        Hashtable<String, Object> productHash = XmlRpcStructFactory
+                .getXmlRpcProduct(product);
+        argList.add(productHash);
+        Double pct = null;
+
+        try {
+            pct = (Double) client.execute("filemgr.getProductPctTransferred",
+                    argList);
+        } catch (XmlRpcException e) {
+            throw new DataTransferException(e.getMessage());
+        } catch (IOException e) {
+            throw new DataTransferException(e.getMessage());
+        }
+
+        if (pct != null) {
+            return pct.doubleValue();
+        }
+
+        return -1.0;
+    }
+
+    public double getRefPctTransferred(Reference reference)
+            throws DataTransferException {
+        Vector<Object> argList = new Vector<Object>();
+        Hashtable<String, Object> refHash = XmlRpcStructFactory
+                .getXmlRpcReference(reference);
+        argList.add(refHash);
+        Double pct = null;
+
+        try {
+            pct = (Double) client.execute("filemgr.getRefPctTransferred",
+                    argList);
+        } catch (XmlRpcException e) {
+            throw new DataTransferException(e.getMessage());
+        } catch (IOException e) {
+            throw new DataTransferException(e.getMessage());
+        }
+
+        if (pct != null) {
+            return pct.doubleValue();
+        }
+
+        return -1.0;
+    }
+
+    @SuppressWarnings("unchecked")
+    public ProductPage pagedQuery(Query query, ProductType type, int pageNum)
+            throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        Hashtable<String, Object> queryHash = XmlRpcStructFactory
+                .getXmlRpcQuery(query);
+        Hashtable<String, Object> typeHash = XmlRpcStructFactory
+                .getXmlRpcProductType(type);
+        argList.add(queryHash);
+        argList.add(typeHash);
+        argList.add(new Integer(pageNum));
+
+        Hashtable<String, Object> pageHash = null;
+
+        try {
+            pageHash = (Hashtable<String, Object>) client.execute(
+                    "filemgr.pagedQuery", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        return XmlRpcStructFactory.getProductPageFromXmlRpc(pageHash);
+    }
+
+    @SuppressWarnings("unchecked")
+    public ProductPage getFirstPage(ProductType type) throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(XmlRpcStructFactory.getXmlRpcProductType(type));
+
+        ProductPage page = null;
+        Hashtable<String, Object> pageHash = null;
+
+        try {
+            pageHash = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getFirstPage", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        if (pageHash != null) {
+            page = XmlRpcStructFactory.getProductPageFromXmlRpc(pageHash);
+        }
+
+        return page;
+
+    }
+
+    @SuppressWarnings("unchecked")
+    public ProductPage getLastPage(ProductType type) throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(XmlRpcStructFactory.getXmlRpcProductType(type));
+
+        ProductPage page = null;
+        Hashtable<String, Object> pageHash = null;
+
+        try {
+            pageHash = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getLastPage", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        if (pageHash != null) {
+            page = XmlRpcStructFactory.getProductPageFromXmlRpc(pageHash);
+        }
+
+        return page;
+    }
+
+    @SuppressWarnings("unchecked")
+    public ProductPage getNextPage(ProductType type, ProductPage currPage)
+            throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(XmlRpcStructFactory.getXmlRpcProductType(type));
+        argList.add(XmlRpcStructFactory.getXmlRpcProductPage(currPage));
+
+        ProductPage page = null;
+        Hashtable<String, Object> pageHash = null;
+
+        try {
+            pageHash = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getNextPage", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        if (pageHash != null) {
+            page = XmlRpcStructFactory.getProductPageFromXmlRpc(pageHash);
+        }
+
+        return page;
+    }
+
+    @SuppressWarnings("unchecked")
+    public ProductPage getPrevPage(ProductType type, ProductPage currPage)
+            throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(XmlRpcStructFactory.getXmlRpcProductType(type));
+        argList.add(XmlRpcStructFactory.getXmlRpcProductPage(currPage));
+
+        ProductPage page = null;
+        Hashtable<String, Object> pageHash = null;
+
+        try {
+            pageHash = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getPrevPage", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        if (pageHash != null) {
+            page = XmlRpcStructFactory.getProductPageFromXmlRpc(pageHash);
+        }
+
+        return page;
+    }
+
+    public String addProductType(ProductType type)
+            throws RepositoryManagerException {
+        String productTypeId = null;
+        Vector<Object> argList = new Vector<Object>();
+        Hashtable<String, Object> typeHash = XmlRpcStructFactory
+                .getXmlRpcProductType(type);
+        argList.add(typeHash);
+
+        try {
+            productTypeId = (String) client.execute("filemgr.addProductType",
+                    argList);
+        } catch (XmlRpcException e) {
+            throw new RepositoryManagerException(e.getMessage());
+        } catch (IOException e) {
+            throw new RepositoryManagerException(e.getMessage());
+        }
+
+        return productTypeId;
+
+    }
+
+    public boolean hasProduct(String productName) throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(productName);
+
+        boolean hasProduct = false;
+
+        try {
+            hasProduct = ((Boolean) client.execute("filemgr.hasProduct",
+                    argList)).booleanValue();
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        return hasProduct;
+
+    }
+
+    public int getNumProducts(ProductType type) throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(XmlRpcStructFactory.getXmlRpcProductType(type));
+
+        Integer numProducts = new Integer(-1);
+
+        try {
+            numProducts = (Integer) client.execute("filemgr.getNumProducts",
+                    argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        return numProducts.intValue();
+    }
+
+    @SuppressWarnings("unchecked")
+    public List<Product> getTopNProducts(int n) throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(new Integer(n));
+
+        Vector<Hashtable<String, Object>> topNProducts = null;
+
+        try {
+            topNProducts = (Vector<Hashtable<String, Object>>) client.execute(
+                    "filemgr.getTopNProducts", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        List<Product> topNProductList = XmlRpcStructFactory
+                .getProductListFromXmlRpc(topNProducts);
+        return topNProductList;
+    }
+
+    @SuppressWarnings("unchecked")
+    public List<Product> getTopNProducts(int n, ProductType type)
+            throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(new Integer(n));
+        Hashtable<String, Object> productTypeHash = XmlRpcStructFactory
+                .getXmlRpcProductType(type);
+        argList.add(productTypeHash);
+
+        Vector<Hashtable<String, Object>> topNProducts = null;
+
+        try {
+            topNProducts = (Vector<Hashtable<String, Object>>) client.execute(
+                    "filemgr.getTopNProducts", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        List<Product> topNProductList = XmlRpcStructFactory
+                .getProductListFromXmlRpc(topNProducts);
+        return topNProductList;
+    }
+
+    public void setProductTransferStatus(Product product)
+            throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        Hashtable<String, Object> productHash = XmlRpcStructFactory
+                .getXmlRpcProduct(product);
+        argList.add(productHash);
+
+        try {
+            client.execute("filemgr.setProductTransferStatus", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+    }
+
+    public void addProductReferences(Product product) throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        Hashtable<String, Object> productHash = XmlRpcStructFactory
+                .getXmlRpcProduct(product);
+        argList.add(productHash);
+
+        try {
+            client.execute("filemgr.addProductReferences", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+    }
+
+  public void addMetadata(Product product, Metadata metadata)
+      throws CatalogException {
+
+    Vector<Object> argList = new Vector<Object>();
+    argList.add(XmlRpcStructFactory.getXmlRpcProduct(product));
+    argList.add(metadata.getHashtable());
+
+    try {
+      client.execute("filemgr.addMetadata", argList);
+    } catch (XmlRpcException e) {
+      throw new CatalogException(e.getMessage());
+    } catch (IOException e) {
+      throw new CatalogException(e.getMessage());
+    }
+  }
+
+  public boolean updateMetadata(Product product, Metadata met)
+      throws CatalogException {
+    Vector<Object> argList = new Vector<Object>();
+    argList.add(XmlRpcStructFactory.getXmlRpcProduct(product));
+    argList.add(met.getHashtable());
+
+    boolean result = false;
+
+    try {
+      result = (Boolean) client.execute("filemgr.updateMetadata", argList);
+    } catch (XmlRpcException e) {
+      throw new CatalogException(e.getMessage());
+    } catch (IOException e) {
+      throw new CatalogException(e.getMessage());
+    }
+
+    return result;
+
+  }
+
+    public String catalogProduct(Product product) throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(XmlRpcStructFactory.getXmlRpcProduct(product));
+
+        String productId = null;
+
+        try {
+            productId = (String) client.execute("filemgr.catalogProduct",
+                    argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        return productId;
+    }
+
+    @SuppressWarnings("unchecked")
+    public Metadata getMetadata(Product product) throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        Hashtable<String, Object> productHash = XmlRpcStructFactory
+                .getXmlRpcProduct(product);
+        argList.add(productHash);
+
+        Hashtable<String, Object> metadata = null;
+
+        try {
+            metadata = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getMetadata", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        Metadata m = new Metadata();
+        m.addMetadata(metadata);
+        return m;
+
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public Metadata getReducedMetadata(Product product, List<?> elements)
+            throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        Hashtable<String, Object> productHash = XmlRpcStructFactory
+                .getXmlRpcProduct(product);
+        argList.add(productHash);
+        argList.add(new Vector(elements));
+
+        Hashtable<String, Object> metadata = null;
+
+        try {
+            metadata = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getReducedMetadata", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        Metadata m = new Metadata();
+        m.addMetadata(metadata);
+        return m;
+
+    }
+
+    public boolean removeFile(String filePath) throws DataTransferException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(filePath);
+
+        boolean success = false;
+
+        try {
+            success = ((Boolean) client.execute("filemgr.removeFile", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            throw new DataTransferException(e.getMessage());
+        } catch (IOException e) {
+            throw new DataTransferException(e.getMessage());
+        }
+
+        return success;
+    }
+
+   public byte[] retrieveFile(String filePath, int offset, int numBytes)
+         throws DataTransferException {
+      Vector<Object> argList = new Vector<Object>();
+      argList.add(filePath);
+      argList.add(new Integer(offset));
+      argList.add(new Integer(numBytes));
+
+      try {
+         return (byte[]) client.execute("filemgr.retrieveFile", argList);
+      } catch (XmlRpcException e) {
+         throw new DataTransferException(e.getMessage());
+      } catch (IOException e) {
+         throw new DataTransferException(e.getMessage());
+      }
+   }
+
+    public void transferFile(String filePath, byte[] fileData, int offset,
+            int numBytes) throws DataTransferException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(filePath);
+        argList.add(fileData);
+        argList.add(new Integer(offset));
+        argList.add(new Integer(numBytes));
+
+        try {
+            client.execute("filemgr.transferFile", argList);
+        } catch (XmlRpcException e) {
+            throw new DataTransferException(e.getMessage());
+        } catch (IOException e) {
+            throw new DataTransferException(e.getMessage());
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public List<Product> getProductsByProductType(ProductType type)
+            throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        Hashtable<String, Object> productTypeHash = XmlRpcStructFactory
+                .getXmlRpcProductType(type);
+        argList.add(productTypeHash);
+
+        Vector<Hashtable<String, Object>> productVector = null;
+
+        try {
+            productVector = (Vector<Hashtable<String, Object>>) client.execute(
+                    "filemgr.getProductsByProductType", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        if (productVector == null) {
+            return null;
+        } else {
+            return XmlRpcStructFactory.getProductListFromXmlRpc(productVector);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public List<Element> getElementsByProductType(ProductType type)
+            throws ValidationLayerException {
+        Vector<Object> argList = new Vector<Object>();
+        Hashtable<String, Object> productTypeHash = XmlRpcStructFactory
+                .getXmlRpcProductType(type);
+
+        argList.add(productTypeHash);
+
+        Vector<Hashtable<String, Object>> elementVector = null;
+
+        try {
+            elementVector = (Vector<Hashtable<String, Object>>) client.execute(
+                    "filemgr.getElementsByProductType", argList);
+        } catch (XmlRpcException e) {
+            throw new ValidationLayerException(e.getMessage());
+        } catch (IOException e) {
+            throw new ValidationLayerException(e.getMessage());
+        }
+
+        if (elementVector == null) {
+            return null;
+        } else {
+            return XmlRpcStructFactory.getElementListFromXmlRpc(elementVector);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public Element getElementById(String elementId)
+            throws ValidationLayerException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(elementId);
+
+        Hashtable<String, Object> elementHash = null;
+
+        try {
+            elementHash = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getElementById", argList);
+        } catch (XmlRpcException e) {
+            throw new ValidationLayerException(e.getMessage());
+        } catch (IOException e) {
+            throw new ValidationLayerException(e.getMessage());
+        }
+
+        if (elementHash == null) {
+            return null;
+        } else {
+            return XmlRpcStructFactory.getElementFromXmlRpc(elementHash);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public Element getElementByName(String elementName)
+            throws ValidationLayerException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(elementName);
+
+        Hashtable<String, Object> elementHash = null;
+
+        try {
+            elementHash = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getElementByName", argList);
+        } catch (XmlRpcException e) {
+            throw new ValidationLayerException(e.getMessage());
+        } catch (IOException e) {
+            throw new ValidationLayerException(e.getMessage());
+        }
+
+        if (elementHash == null) {
+            return null;
+        } else {
+            return XmlRpcStructFactory.getElementFromXmlRpc(elementHash);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public Element getElementByName(String elementName, ProductType type)
+            throws ValidationLayerException {
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(elementName);
+        argList.add(XmlRpcStructFactory.getXmlRpcProductType(type));
+
+        Hashtable<String, Object> elementHash = null;
+
+        try {
+            elementHash = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getElementByName", argList);
+        } catch (XmlRpcException e) {
+            throw new ValidationLayerException(e.getMessage());
+        } catch (IOException e) {
+            throw new ValidationLayerException(e.getMessage());
+        }
+
+        if (elementHash == null) {
+            return null;
+        } else {
+            return XmlRpcStructFactory.getElementFromXmlRpc(elementHash);
+        }
+    }
+
+    public List<QueryResult> complexQuery(ComplexQuery complexQuery)
+            throws CatalogException {
+        try {
+            Hashtable<String, Object> complexQueryHash = XmlRpcStructFactory
+                    .getXmlRpcComplexQuery(complexQuery);
+            Vector<Object> argList = new Vector<Object>();
+            argList.add(complexQueryHash);
+            @SuppressWarnings("unchecked")
+            Vector<Hashtable<String, Object>> queryResultHashVector = (Vector<Hashtable<String, Object>>) client
+                    .execute("filemgr.complexQuery", argList);
+            return XmlRpcStructFactory
+                    .getQueryResultsFromXmlRpc(queryResultHashVector);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new CatalogException(e.getMessage());
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public List<Product> query(Query query, ProductType type)
+            throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+        Hashtable<String, Object> queryHash = XmlRpcStructFactory
+                .getXmlRpcQuery(query);
+        Hashtable<String, Object> typeHash = XmlRpcStructFactory
+                .getXmlRpcProductType(type);
+        argList.add(queryHash);
+        argList.add(typeHash);
+
+        Vector<Hashtable<String, Object>> productVector = null;
+
+        try {
+            productVector = (Vector<Hashtable<String, Object>>) client.execute(
+                    "filemgr.query", argList);
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new CatalogException(e.getMessage());
+
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new CatalogException(e.getMessage());
+        }
+
+        if (productVector == null) {
+            return null;
+        } else {
+            return XmlRpcStructFactory.getProductListFromXmlRpc(productVector);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public ProductType getProductTypeByName(String productTypeName)
+            throws RepositoryManagerException {
+        Hashtable<String, Object> productTypeHash = new Hashtable<String, Object>();
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(productTypeName);
+
+        try {
+            productTypeHash = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getProductTypeByName", argList);
+        } catch (XmlRpcException e) {
+            throw new RepositoryManagerException(e.getLocalizedMessage());
+        } catch (IOException e) {
+            throw new RepositoryManagerException(e.getMessage());
+        }
+
+        if (productTypeHash == null) {
+            return null;
+        } else
+            return XmlRpcStructFactory
+                    .getProductTypeFromXmlRpc(productTypeHash);
+    }
+
+    @SuppressWarnings("unchecked")
+    public ProductType getProductTypeById(String productTypeId)
+            throws RepositoryManagerException {
+        Hashtable<String, Object> productTypeHash = new Hashtable<String, Object>();
+        Vector<Object> argList = new Vector<Object>();
+        argList.add(productTypeId);
+
+        try {
+            productTypeHash = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getProductTypeById", argList);
+        } catch (XmlRpcException e) {
+            throw new RepositoryManagerException(e.getMessage());
+        } catch (IOException e) {
+            throw new RepositoryManagerException(e.getMessage());
+        }
+
+        if (productTypeHash == null) {
+            return null;
+        } else
+            return XmlRpcStructFactory
+                    .getProductTypeFromXmlRpc(productTypeHash);
+    }
+
+    @SuppressWarnings("unchecked")
+    public List<ProductType> getProductTypes()
+            throws RepositoryManagerException {
+        Vector<Object> argList = new Vector<Object>();
+
+        Vector<Hashtable<String, Object>> productTypeVector = null;
+
+        try {
+            productTypeVector = (Vector<Hashtable<String, Object>>) client
+                    .execute("filemgr.getProductTypes", argList);
+        } catch (XmlRpcException e) {
+            throw new RepositoryManagerException(e.getMessage());
+        } catch (IOException e) {
+            throw new RepositoryManagerException(e.getMessage());
+        }
+
+        if (productTypeVector == null) {
+            return null;
+        } else {
+            return XmlRpcStructFactory
+                    .getProductTypeListFromXmlRpc(productTypeVector);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public List<Reference> getProductReferences(Product product)
+            throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+
+        Vector<Hashtable<String, Object>> productReferenceVector = null;
+        Hashtable<String, Object> productHash = XmlRpcStructFactory
+                .getXmlRpcProduct(product);
+        argList.add(productHash);
+
+        try {
+            productReferenceVector = (Vector<Hashtable<String, Object>>) client
+                    .execute("filemgr.getProductReferences", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        if (productReferenceVector == null) {
+            return null;
+        } else {
+            return XmlRpcStructFactory
+                    .getReferencesFromXmlRpc(productReferenceVector);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public Product getProductById(String productId) throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+
+        Hashtable<String, Object> productHash = null;
+        argList.add(productId);
+
+        try {
+            productHash = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getProductById", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        if (productHash == null) {
+            return null;
+        } else {
+            return XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public Product getProductByName(String productName) throws CatalogException {
+        Vector<Object> argList = new Vector<Object>();
+
+        Hashtable<String, Object> productHash = null;
+        argList.add(productName);
+
+        try {
+            productHash = (Hashtable<String, Object>) client.execute(
+                    "filemgr.getProductByName", argList);
+        } catch (XmlRpcException e) {
+            throw new CatalogException(e.getMessage());
+        } catch (IOException e) {
+            throw new CatalogException(e.getMessage());
+        }
+
+        if (productHash == null) {
+            return null;
+        } else {
+            return XmlRpcStructFactory.getProductFromXmlRpc(productHash);
+        }
+    }
+
+    public String ingestProduct(Product product, Metadata metadata,
+            boolean clientTransfer) throws Exception {
+        try {
+            // ingest product
+            Vector<Object> argList = new Vector<Object>();
+            Hashtable<String, Object> productHash = XmlRpcStructFactory
+                    .getXmlRpcProduct(product);
+            argList.add(productHash);
+            argList.add(metadata.getHashtable());
+            argList.add(Boolean.valueOf(clientTransfer));
+            String productId = (String) client.execute("filemgr.ingestProduct",
+                    argList);
+
+            if (clientTransfer) {
+                LOG.log(Level.FINEST,
+                        "File Manager Client: clientTransfer enabled: "
+                                + "transfering product ["
+                                + product.getProductName() + "]");
+
+                // we need to transfer the product ourselves
+                // make sure we have the product ID
+                if (productId == null) {
+                    throw new Exception("Request to ingest product: "
+                            + product.getProductName()
+                            + " but no product ID returned from File "
+                            + "Manager ingest");
+                }
+
+                if (dataTransfer == null) {
+                    throw new Exception("Request to ingest product: ["
+                            + product.getProductName()
+                            + "] using client transfer, but no "
+                            + "dataTransferer specified!");
+                }
+
+                product.setProductId(productId);
+
+                if (!Boolean.getBoolean("org.apache.oodt.cas.filemgr.serverside.versioning")) {
+                  // version the product
+                  Versioner versioner = GenericFileManagerObjectFactory
+                          .getVersionerFromClassName(product.getProductType()
+                                  .getVersioner());
+                  versioner.createDataStoreReferences(product, metadata);
+                  
+                  // add the newly versioned references to the data store
+                  try {
+                      addProductReferences(product);
+                  } catch (CatalogException e) {
+                      LOG
+                              .log(
+                                      Level.SEVERE,
+                                      "ingestProduct: RepositoryManagerException "
+                                              + "when adding Product References for Product : "
+                                              + product.getProductName()
+                                              + " to RepositoryManager: Message: "
+                                              + e.getMessage());
+                      throw e;
+                  }
+                } else {
+                  product.setProductReferences(getProductReferences(product));
+                }
+                
+                // now transfer the product
+                try {
+                    dataTransfer.transferProduct(product);
+                    // now update the product's transfer status in the data
+                    // store
+                    product.setTransferStatus(Product.STATUS_RECEIVED);
+
+                    try {
+                        setProductTransferStatus(product);
+                    } catch (CatalogException e) {
+                        LOG
+                                .log(
+                                        Level.SEVERE,
+                                        "ingestProduct: RepositoryManagerException "
+                                                + "when updating product transfer status for Product: "
+                                                + product.getProductName()
+                                                + " Message: " + e.getMessage());
+                        throw e;
+                    }
+                } catch (Exception e) {
+                    LOG.log(Level.SEVERE,
+                            "ingestProduct: DataTransferException when transfering Product: "
+                                    + product.getProductName() + ": Message: "
+                                    + e.getMessage());
+                    throw new DataTransferException(e);
+                }
+
+            }
+            return productId;
+
+            // error versioning file
+        } catch (VersioningException e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE,
+                "ingestProduct: VersioningException when versioning Product: "
+                        + product.getProductName() + " with Versioner "
+                        + product.getProductType().getVersioner()
+                        + ": Message: " + e.getMessage());
+            throw new VersioningException(e);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE, "Failed to ingest product [" + product
+                    + "] : " + e.getMessage() + " -- rolling back ingest");
+            try {
+                Vector<Object> argList = new Vector<Object>();
+                Hashtable<String, Object> productHash = XmlRpcStructFactory
+                        .getXmlRpcProduct(product);
+                argList.add(productHash);
+                client.execute("filemgr.removeProduct", argList);
+            } catch (Exception e1) {
+                LOG.log(Level.SEVERE, "Failed to rollback ingest of product ["
+                        + product + "] : " + e.getMessage());
+            }
+            throw new Exception("Failed to ingest product [" + product + "] : "
+                    + e.getMessage());
+        }
+
+    }
+
+    @SuppressWarnings("unchecked")
+    public Metadata getCatalogValues(Metadata metadata, ProductType productType)
+            throws XmlRpcException, IOException {
+        Vector<Object> args = new Vector<Object>();
+        args.add(metadata.getHashtable());
+        args.add(XmlRpcStructFactory.getXmlRpcProductType(productType));
+
+        Metadata m = new Metadata();
+        m.addMetadata((Hashtable<String, Object>) this.client.execute(
+                "filemgr.getCatalogValues", args));
+
+        return m;
+    }
+
+    @SuppressWarnings("unchecked")
+    public Metadata getOrigValues(Metadata metadata, ProductType productType)
+            throws XmlRpcException, IOException {
+        Vector<Object> args = new Vector<Object>();
+        args.add(metadata.getHashtable());
+        args.add(XmlRpcStructFactory.getXmlRpcProductType(productType));
+
+        Metadata m = new Metadata();
+        m.addMetadata((Hashtable<String, Object>) this.client.execute(
+                "filemgr.getOrigValues", args));
+
+        return m;
+    }
+
+    @SuppressWarnings("unchecked")
+    public Query getCatalogQuery(Query query, ProductType productType)
+            throws XmlRpcException, IOException {
+        Vector<Object> args = new Vector<Object>();
+        args.add(XmlRpcStructFactory.getXmlRpcQuery(query));
+        args.add(XmlRpcStructFactory.getXmlRpcProductType(productType));
+        return XmlRpcStructFactory
+                .getQueryFromXmlRpc((Hashtable<String, Object>) this.client
+                        .execute("filemgr.getCatalogQuery", args));
+    }
+
+    public static void main(String[] args) {
+       CmdLineUtility cmdLineUtility = new CmdLineUtility();
+       cmdLineUtility.run(args);
+    }
+
+    /**
+     * @return Returns the fileManagerUrl.
+     */
+    public URL getFileManagerUrl() {
+        return fileManagerUrl;
+    }
+
+    /**
+     * @param fileManagerUrl
+     *            The fileManagerUrl to set.
+     */
+    public void setFileManagerUrl(URL fileManagerUrl) {
+        this.fileManagerUrl = fileManagerUrl;
+
+        // reset the client
+        this.client = new XmlRpcClient(fileManagerUrl);
+    }
+
+    /**
+     * @return Returns the dataTransfer.
+     */
+    public DataTransfer getDataTransfer() {
+        return dataTransfer;
+    }
+
+    /**
+     * @param dataTransfer
+     *            The dataTransfer to set.
+     */
+    public void setDataTransfer(DataTransfer dataTransfer) {
+        this.dataTransfer = dataTransfer;
+        this.dataTransfer.setFileManagerUrl(this.fileManagerUrl);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/auth/Dispatcher.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/auth/Dispatcher.java
new file mode 100644
index 0000000..5dd68ca
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/auth/Dispatcher.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.system.auth;
+
+//JDK imports
+import java.util.List;
+
+/**
+ * A guard to ensure that any XML-RPC method called for the filemgr server is
+ * properly authenticated with a username and password.
+ * 
+ * 
+ * @author kelly
+ */
+public interface Dispatcher {
+
+    /**
+     * Handles an XML-RPC request, provided that the given <code>user</code>name
+     * and <code>password</code> are correct.
+     * 
+     * @param methodSpecifier
+     *            The name of the XML-RPC method to call.
+     * @param params
+     *            The parameters to the method.
+     * @param user
+     *            The user name who is calling the method.
+     * @param password
+     *            The user's password.
+     * @return The result of the method call.
+     * @throws Exception
+     *             If any error occurs.
+     */
+    public Result handleRequest(String methodSpecifier, List params,
+            String user, String password) throws Exception;
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/auth/Result.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/auth/Result.java
new file mode 100644
index 0000000..90f443a
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/auth/Result.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.system.auth;
+
+/**
+ * A Python-friendly wrapper that wraps an XML-RPC result.
+ * 
+ * @author kelly
+ */
+public class Result {
+
+    /**
+     * Default Constructor.
+     * 
+     * @param kind
+     *            The class name of the return result.
+     * @param value
+     *            The result value.
+     * @throws Throwable
+     *             If any error occurs.
+     */
+    public Result(Class kind, Object value) throws Throwable {
+        if (kind != null) {
+            java.lang.reflect.Constructor ctor = kind.getConstructor(ARGS);
+            this.value = ctor.newInstance(new Object[] { value });
+        } else
+            this.value = value;
+    }
+
+    /**
+     * Gets the result value.
+     * 
+     * @return The result value.
+     */
+    public Object getValue() {
+        return value;
+    }
+
+    private Object value;
+
+    private static Class[] ARGS = { String.class };
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/auth/SecureWebServer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/auth/SecureWebServer.java
new file mode 100644
index 0000000..c6fc861
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/system/auth/SecureWebServer.java
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.system.auth;
+
+//JDK imports
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.Vector;
+import java.io.IOException;
+
+//XML-RPC imports
+import org.apache.xmlrpc.AuthenticatedXmlRpcHandler;
+
+/**
+ * An XML-RPC Web Server that requires authentication and authorization.
+ * 
+ * @author kelly
+ */
+public final class SecureWebServer extends org.apache.xmlrpc.WebServer
+        implements AuthenticatedXmlRpcHandler {
+
+    /**
+     * Initializes the XML-RPC web server on the given <code>port</code> and
+     * adds a default handler that traps all calls and makes them authenticated.
+     * 
+     * @param port
+     *            The port to run the XML-RPC webserver on.
+     * @throws IOException
+     *             If any error occurs.
+     */
+    public SecureWebServer(int port) throws IOException {
+        super(port);
+        addHandler("$default", this);
+    }
+
+    /**
+     * Executes the XML-RPC method, first authenticating the given user and
+     * authorizing him based on his roles.
+     * 
+     * @param methodSpecifier
+     *            the name of the XML-RPC method to call.
+     * @param params
+     *            the parameters passed to the method.
+     * @user The username to authenticate to call the method.
+     * @pass The password to use for the user.
+     */
+    public Object execute(String methodSpecifier, Vector params, String user,
+            String password) throws Exception {
+        for (Iterator i = dispatchers.iterator(); i.hasNext();) {
+            Result rc = ((Dispatcher) i.next()).handleRequest(methodSpecifier,
+                    params, user, password);
+            if (rc != null)
+                return rc.getValue();
+        }
+        throw new IllegalStateException(
+                "No request dispatcher was able to return a non-null value to the XML-RPC caller");
+    }
+
+    /**
+     * Adds an authenticated XML-RPC dispatcher.
+     * 
+     * @param dispatcher
+     *            The dispatcher to add which will service the authenticated
+     *            XML-RPC method calls
+     * 
+     */
+    public void addDispatcher(Dispatcher dispatcher) {
+        if (dispatcher == null)
+            throw new IllegalArgumentException(
+                    "Non-null dispatchers are illegal");
+        dispatchers.add(dispatcher);
+    }
+
+    private List dispatchers = new ArrayList();
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/CASAnalyzer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/CASAnalyzer.java
new file mode 100644
index 0000000..7d883bf
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/CASAnalyzer.java
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//JDK imports
+import java.io.Reader;
+import java.util.Set;
+
+//Lucene imports
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.StopAnalyzer;
+import org.apache.lucene.analysis.StopFilter;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.WhitespaceTokenizer;
+import org.apache.lucene.analysis.standard.StandardFilter;
+import org.apache.lucene.analysis.standard.StandardTokenizer;
+
+/**
+ * 
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * An analyzer used in the CatalogSearch program.
+ * </p>
+ * 
+ */
+public class CASAnalyzer extends Analyzer {
+    private Set stopSet;
+
+    /**
+     * An array containing some common English words that are usually not useful
+     * for searching.
+     */
+    public static final String[] STOP_WORDS = StopAnalyzer.ENGLISH_STOP_WORDS;
+
+    /** Builds an analyzer. */
+    public CASAnalyzer() {
+        this(STOP_WORDS);
+    }
+
+    /** Builds an analyzer with the given stop words. */
+    public CASAnalyzer(String[] stopWords) {
+        stopSet = StopFilter.makeStopSet(stopWords);
+    }
+
+    /**
+     * Constructs a {@link StandardTokenizer} filtered by a {@link
+     * StandardFilter}, a {@link LowerCaseFilter} and a {@link StopFilter}.
+     */
+    public TokenStream tokenStream(String fieldName, Reader reader) {
+        TokenStream result = new WhitespaceTokenizer(reader);
+        result = new StandardFilter(result);
+        result = new StopFilter(result, stopSet);
+        return result;
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/CatalogSearch.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/CatalogSearch.java
new file mode 100644
index 0000000..9519a8e
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/CatalogSearch.java
@@ -0,0 +1,400 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//JDK imports
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+//Lucene imports
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.PhraseQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.RangeQuery;
+import org.apache.lucene.search.TermQuery;
+
+/**
+ * 
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * A command line-search tool for the File Manager.
+ * </p>
+ * 
+ */
+public class CatalogSearch {
+
+    private static QueryParser parser;
+
+    private static XmlRpcFileManagerClient client;
+
+    private static String freeTextBlock = "__FREE__";
+
+    private static String productFilter = "";
+
+    public CatalogSearch() {
+    }
+
+    public static void PostQuery(
+            org.apache.oodt.cas.filemgr.structs.Query casQuery) {
+        Vector products = new Vector();
+        try {
+            products = (Vector) client.getProductTypes();
+        } catch (RepositoryManagerException e) {
+            System.out
+                    .println("Error getting available product types from the File Manager.");
+            e.printStackTrace();
+        }
+        for (int i = 0; i < products.size(); i++) {
+            PostQuery(((ProductType) products.get(i)).getProductTypeId(),
+                    casQuery);
+        }
+    }
+
+    public static void PostQuery(String product,
+            org.apache.oodt.cas.filemgr.structs.Query casQuery) {
+        Vector results = new Vector();
+        ProductType productType = null;
+
+        try {
+            productType = client.getProductTypeById(product);
+        } catch (RepositoryManagerException e) {
+            System.out.println("Could not access Product Type information");
+            System.exit(-1);
+        }
+
+        try {
+            results = (Vector) client.query(casQuery, productType);
+        } catch (CatalogException ignore) {
+            System.out.println("Error querying the File Manager");
+            ignore.printStackTrace();
+            System.exit(-1);
+        }
+
+        if (results.isEmpty()) {
+            System.out.println("No Products Found Matching This Criteria.");
+        } else {
+            System.out.println("Products Matching Query");
+            for (int i = 0; i < results.size(); i++) {
+                System.out.print(((Product) results.get(i)).getProductName()
+                        + "\t");
+                System.out.println(((Product) results.get(i)).getProductId());
+            }
+        }
+    }
+
+    public static void setFilter(String filter) {
+        productFilter = filter;
+        try {
+            client.getProductTypeById(filter);
+        } catch (RepositoryManagerException e) {
+            System.out.println("No product found with ID: " + filter);
+            productFilter = "";
+        }
+        if (!productFilter.equals(""))
+            System.out.println("Filtering for " + productFilter + " products.");
+    }
+
+    public static void removeFilter() {
+        productFilter = "";
+    }
+
+    public static void ListProducts() {
+        Vector products = new Vector();
+        try {
+            products = (Vector) client.getProductTypes();
+        } catch (RepositoryManagerException e) {
+            System.out
+                    .println("Error getting available product types from the File Manager.");
+            e.printStackTrace();
+        }
+        for (int i = 0; i < products.size(); i++) {
+            System.out.print(((ProductType) products.get(i)).getProductTypeId()
+                    + "\t");
+            System.out.println(((ProductType) products.get(i)).getName());
+        }
+    }
+
+    public static void listElements() {
+        Vector products = new Vector();
+        try {
+            products = (Vector) client.getProductTypes();
+            for (int i = 0; i < products.size(); i++) {
+                listElements(((ProductType) products.get(i)).getProductTypeId());
+            }
+        } catch (RepositoryManagerException e) {
+            System.out
+                    .println("Error getting available product types from the File Manager.");
+            e.printStackTrace();
+        }
+
+    }
+
+    public static void listElements(String prodID) {
+        Vector elements = new Vector();
+        ProductType type;
+
+        try {
+            type = client.getProductTypeById(prodID);
+            elements = (Vector) client.getElementsByProductType(type);
+        } catch (RepositoryManagerException e1) {
+            System.out.println("Could not find a ProductType with the ID: "
+                    + prodID);
+        } catch (ValidationLayerException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+        for (int i = 0; i < elements.size(); i++) {
+            Element e = (Element) elements.get(i);
+            System.out.print(e.getElementId() + "\t");
+            System.out.println(e.getElementName());
+        }
+    }
+
+    public static void printHelp() {
+        String add_filter = "add filter [productType]\n";
+        add_filter += "\tAdd a filter on query results to only return products\n";
+        add_filter += "\tmatching the specified productType.";
+
+        String remove_filter = "remove filter\n";
+        remove_filter += "\tRemove filters on query results.";
+
+        String get_products = "get products\n";
+        get_products += "\tReturns all ProductTypeIDs known to the Repository.";
+
+        String get_elements = "get elements\n";
+        get_elements += "\tReturns all Elements known to the Validation Layer.";
+
+        String get_elements_for_product = "get elements for [productType]\n";
+        get_elements_for_product += "\tReturns all Elements known to the ";
+        get_elements_for_product += "Validation Layer\n\tfor the specified ";
+        get_elements_for_product += "productType.";
+
+        String query = "query [query]\n";
+        query += "\tQueries the Catalog for all products matching the \n";
+        query += "\tspecified query. If the filter is set, only products\n";
+        query += "\tmatching the productType set in the filter will be\n";
+        query += "\treturned. More details about query syntax can be found\n";
+        query += "\tat http://lucene.apache.org/java/docs/queryparsersyntax.html";
+
+        String quit = "quit\n";
+        quit += "\tExits the program.";
+
+        System.out.println("Available Commands:");
+        System.out.println(add_filter);
+        System.out.println(remove_filter);
+        System.out.println(get_products);
+        System.out.println(get_elements);
+        System.out.println(get_elements_for_product);
+        System.out.println(query);
+        System.out.println(quit);
+    }
+
+    public static Query ParseQuery(String query) {
+        // note that "__FREE__" is a control work for free text searching
+        parser = new QueryParser(freeTextBlock, new CASAnalyzer());
+        Query luceneQ = null;
+        try {
+            luceneQ = (Query) parser.parse(query);
+        } catch (ParseException e) {
+            System.out.println("Error parsing query text.");
+            System.exit(-1);
+        }
+        return luceneQ;
+    }
+
+    public static void GenerateCASQuery(
+            org.apache.oodt.cas.filemgr.structs.Query casQuery,
+            Query luceneQuery) {
+        if (luceneQuery instanceof TermQuery) {
+            Term t = ((TermQuery) luceneQuery).getTerm();
+            if (t.field().equals(freeTextBlock)) {
+                // if(casQuery.getCriteria().isEmpty())
+                // casQuery.addCriterion(new FreeTextQueryCriteria());
+                // ((FreeTextQueryCriteria)casQuery.getCriteria().get(0)).addValue(t.text());
+            } else {
+                casQuery
+                        .addCriterion(new TermQueryCriteria(t.field(), t.text()));
+            }
+        } else if (luceneQuery instanceof PhraseQuery) {
+            Term[] t = ((PhraseQuery) luceneQuery).getTerms();
+            if (t[0].field().equals(freeTextBlock)) {
+                // if(casQuery.getCriteria().isEmpty())
+                // casQuery.addCriterion(new FreeTextQueryCriteria());
+                // for(int i=0;i<t.length;i++)
+                // ((FreeTextQueryCriteria)casQuery.getCriteria().get(0)).addValue(t[i].text());
+            } else {
+                for (int i = 0; i < t.length; i++)
+                    casQuery.addCriterion(new TermQueryCriteria(t[i].field(),
+                            t[i].text()));
+            }
+        } else if (luceneQuery instanceof RangeQuery) {
+            Term startT = ((RangeQuery) luceneQuery).getLowerTerm();
+            Term endT = ((RangeQuery) luceneQuery).getUpperTerm();
+            casQuery.addCriterion(new RangeQueryCriteria(startT.field(), startT
+                    .text(), endT.text()));
+        } else if (luceneQuery instanceof BooleanQuery) {
+            BooleanClause[] clauses = ((BooleanQuery) luceneQuery).getClauses();
+            for (int i = 0; i < clauses.length; i++) {
+                GenerateCASQuery(casQuery, (clauses[i]).getQuery());
+            }
+        } else {
+            System.out.println("Error Parsing Query");
+            System.exit(-1);
+        }
+    }
+
+    public static void CommandParser(String command) {
+        StringTokenizer tok = new StringTokenizer(command, " ");
+        int tokCount = tok.countTokens();
+
+        if (tokCount > 0) {
+            String com = tok.nextToken();
+            if (com.equalsIgnoreCase("get")) {
+                if (tokCount > 1) {
+                    String subcom = tok.nextToken();
+                    if (subcom.equalsIgnoreCase("products")) {
+                        ListProducts();
+                    } else if (subcom.equalsIgnoreCase("elements")) {
+                        if (tokCount == 4
+                                && tok.nextToken().equalsIgnoreCase("for")) {
+                            String prodElements = tok.nextToken();
+                            listElements(prodElements);
+                        } else {
+                            if (tokCount == 2) {
+                                listElements();
+                            } else {
+                                System.out.println("Error parsing command");
+                                return;
+                            }
+                        }
+                    }
+                } else {
+                    System.out.println("Error parsing command");
+                    return;
+                }
+            } else if (com.equalsIgnoreCase("add")) {
+                if (tokCount == 3 && tok.nextToken().equalsIgnoreCase("filter")) {
+                    setFilter(tok.nextToken());
+                } else {
+                    System.out.println("Error parsing command");
+                    return;
+                }
+            } else if (com.equalsIgnoreCase("remove")) {
+                if (tokCount == 2 && tok.nextToken().equalsIgnoreCase("filter")) {
+                    removeFilter();
+                } else {
+                    System.out.println("Error parsing command");
+                    return;
+                }
+            } else if (com.equalsIgnoreCase("help")) {
+                printHelp();
+            } else if (com.equalsIgnoreCase("exit")
+                    || com.equalsIgnoreCase("quit")) {
+                System.out.println("Exiting...");
+                System.exit(0);
+            } else if (com.equalsIgnoreCase("query")) {
+                String query = new String();
+                while (tok.hasMoreTokens()) {
+                    query += tok.nextToken() + " ";
+                }
+                System.out.println("querying for: " + query);
+                Query parsedQuery = ParseQuery(query);
+                org.apache.oodt.cas.filemgr.structs.Query casQuery = new org.apache.oodt.cas.filemgr.structs.Query();
+
+                GenerateCASQuery(casQuery, parsedQuery);
+                PostQuery(productFilter, casQuery);
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+
+        String fileManagerUrl = null;
+        String welcomeMessage = "CatalogSearch v0.1\n";
+        welcomeMessage += "Copyright 2006. California Institute of Technology.\n";
+        String usage = "CatalogSearch --url <url to File Manager service>\n";
+        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+        CatalogSearch cs = new CatalogSearch();
+
+        // determine url
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--url")) {
+                fileManagerUrl = args[++i];
+            }
+        }
+
+        if (fileManagerUrl == null) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        // connect with Filemgr Client
+        boolean clientConnect = true;
+        try {
+            client = new XmlRpcFileManagerClient(new URL(fileManagerUrl));
+        } catch (Exception e) {
+            System.out
+                    .println("Exception when communicating with file manager, errors to follow: message: "
+                            + e.getMessage());
+            clientConnect = false;
+        }
+
+        if (clientConnect) {
+
+            System.out.println(welcomeMessage);
+
+            String command = "";
+
+            for (;;) {
+                System.out.print("CatalogSearch>");
+
+                try {
+                    command = in.readLine();
+                    CommandParser(command);
+
+                } catch (IOException e) {
+                    System.out.println("\nError Reading Query\n");
+                    System.exit(-1);
+                }
+            }
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/DeleteProduct.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/DeleteProduct.java
new file mode 100644
index 0000000..16bb237
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/DeleteProduct.java
@@ -0,0 +1,223 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//JDK imports
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * A utility class that deletes products in the File Manager Catalog based on
+ * productID.
+ * </p>
+ * 
+ */
+@Deprecated
+public class DeleteProduct {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(DeleteProduct.class.getName());
+
+    /* our File Manager client */
+    private static XmlRpcFileManagerClient client = null;
+
+    /* whether or not we should commit our deletions */
+    private boolean commit = true;
+
+    public DeleteProduct(String fileManagerUrl, boolean commit) {
+        try {
+            client = new XmlRpcFileManagerClient(new URL(fileManagerUrl));
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE,
+                    "Unable to create file manager client: Message: "
+                            + e.getMessage() + ": errors to follow");
+        }
+
+        this.commit = commit;
+
+        if (!this.commit) {
+            LOG.log(Level.INFO, "Commit disabled.");
+        } else {
+            LOG.log(Level.INFO, "Commit enabled.");
+        }
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) {
+        String productId = null;
+        String fileManagerUrl = null;
+        boolean commitChanges = true;
+        boolean readFromStdIn = false;
+
+        String usage = "DeleteProduct --productID <product id> "
+                + "--fileManagerUrl <url to file manager> [--read] [--nocommit]\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--productID")) {
+                productId = args[++i];
+            } else if (args[i].equals("--fileManagerUrl")) {
+                fileManagerUrl = args[++i];
+            } else if (args[i].equals("--read")) {
+                readFromStdIn = true;
+            } else if (args[i].equals("--nocommit")) {
+                commitChanges = false;
+            }
+        }
+
+        if ((productId == null && !readFromStdIn) || fileManagerUrl == null) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        DeleteProduct remover = new DeleteProduct(fileManagerUrl, commitChanges);
+        if (readFromStdIn) {
+            List prodIds = readProdIdsFromStdin();
+            for (Iterator i = prodIds.iterator(); i.hasNext();) {
+                String prodId = (String) i.next();
+                remover.remove(prodId);
+            }
+        } else
+            remover.remove(productId);
+
+    }
+
+    private static List readProdIdsFromStdin() {
+        List prodIds = new Vector();
+        BufferedReader br = null;
+
+        br = new BufferedReader(new InputStreamReader(System.in));
+
+        String line = null;
+
+        try {
+            while ((line = br.readLine()) != null) {
+                prodIds.add(line);
+            }
+        } catch (IOException e) {
+            LOG.log(Level.WARNING, "Error reading prod id: line: [" + line
+                    + "]: Message: " + e.getMessage(), e);
+        } finally {
+            if (br != null) {
+                try {
+                    br.close();
+                } catch (Exception ignore) {
+                }
+
+                br = null;
+            }
+        }
+
+        return prodIds;
+    }
+
+    private void remove(String productId) {
+        Product target = null;
+
+        try {
+            target = client.getProductById(productId);
+        } catch (CatalogException e) {
+            LOG.log(Level.WARNING, "Unable to obtain product : [" + productId
+                    + "] from file manager: [" + client.getFileManagerUrl()
+                    + "]: Message: " + e.getMessage());
+        }
+
+        if (target == null) {
+            // could not file product
+            return;
+        }
+
+        // delete references first
+        Vector refs = new Vector();
+
+        try {
+            refs = (Vector) client.getProductReferences(target);
+        } catch (CatalogException e) {
+            LOG.log(Level.WARNING,
+                    "Unable to obtain references for product : [" + productId
+                            + "] from file manager: ["
+                            + client.getFileManagerUrl() + "]: Message: "
+                            + e.getMessage());
+        }
+
+        for (int i = 0; i < refs.size(); i++) {
+            Reference ref = (Reference) refs.get(i);
+
+            if (commit) {
+                try {
+                    client.removeFile(new File(new URI(ref
+                            .getDataStoreReference())).getAbsolutePath());
+                } catch (DataTransferException e) {
+                    LOG.log(Level.WARNING, "Unable to delete reference : ["
+                            + ref.getDataStoreReference() + "] for product : ["
+                            + productId + "] from file manager : ["
+                            + client.getFileManagerUrl() + "]: Message: "
+                            + e.getMessage());
+                } catch (URISyntaxException e) {
+                    LOG.log(Level.WARNING,
+                            "uri syntax exception getting file absolute path from URI: ["
+                                    + ref.getDataStoreReference()
+                                    + "]: Message: " + e.getMessage());
+                }
+            } else {
+                LOG.log(Level.INFO, "Delete file: ["
+                        + ref.getDataStoreReference() + "]");
+            }
+
+        }
+
+        if (commit) {
+
+            // now delete product
+            try {
+                client.removeProduct(target);
+            } catch (CatalogException e) {
+                LOG.log(Level.WARNING, "Unable to remove product : ["
+                        + productId + "] from file manager: ["
+                        + client.getFileManagerUrl() + "]: Message: "
+                        + e.getMessage());
+            }
+        } else {
+            LOG.log(Level.INFO, "Remote catalog entry for product: ["
+                    + target.getProductName() + "]");
+        }
+
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/DumpDbElementsToXml.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/DumpDbElementsToXml.java
new file mode 100644
index 0000000..0982219
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/DumpDbElementsToXml.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.util.XmlStructFactory;
+import org.apache.oodt.cas.filemgr.validation.DataSourceValidationLayerFactory;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Simple program to dump XML elements out of a DataSourceValidationLayer and
+ * into an XML file.
+ * </p>
+ * 
+ */
+public final class DumpDbElementsToXml {
+
+    private DumpDbElementsToXml() throws InstantiationException {
+        throw new InstantiationException(
+                "Don't construct private constructors!");
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) throws Exception {
+        String propFile = null, outXmlFile = null;
+        String usage = "DumpDbElementsToXml --propFile </path/to/propFile> --out </path/to/xml/file>\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--propFile")) {
+                propFile = args[++i];
+            } else if (args[i].equals("--out")) {
+                outXmlFile = args[++i];
+            }
+        }
+
+        if (propFile == null || outXmlFile == null) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        System.out.println("Loading properties file: [" + propFile + "]");
+        System.getProperties().load(new FileInputStream(new File(propFile)));
+
+        ValidationLayer dbLayer = new DataSourceValidationLayerFactory()
+                .createValidationLayer();
+
+        List elementList = dbLayer.getElements();
+        XmlStructFactory.writeElementXmlDocument(elementList, outXmlFile);
+
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/ExpImpCatalog.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/ExpImpCatalog.java
new file mode 100644
index 0000000..9d124c9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/ExpImpCatalog.java
@@ -0,0 +1,448 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.tools;
+
+// JDK imports
+import java.io.File;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+// OODT imports
+import org.apache.oodt.cas.filemgr.catalog.Catalog;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.filemgr.util.GenericFileManagerObjectFactory;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Tool to export from a source file manager catalog and import into a dest
+ * file manager catalog.
+ * </p>
+ * 
+ */
+public class ExpImpCatalog {
+
+    /* the client to the source catalog to export */
+    private XmlRpcFileManagerClient sourceClient = null;
+
+    /* the client to the dest catalog to import into */
+    private XmlRpcFileManagerClient destClient = null;
+
+    /* a source catalog I/F to export from (if no fm client is desired) */
+    private Catalog srcCatalog = null;
+
+    /* a dest catalog I/F to import into (if no fm client is desired) */
+    private Catalog destCatalog = null;
+
+    /* whether or not we should ensure a product doesn't exist before copying */
+    private boolean ensureUnique = false;
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(ExpImpCatalog.class
+            .getName());
+
+    /**
+     * Default Constructor.
+     * 
+     * @param sUrl
+     *            The url to the source file manager to export from.
+     * @param dUrl
+     *            The url to the dest file manager to import into.
+     * @param unique
+     *            Whether or not the import tool should ensure that the product
+     *            from the source does not exist in the dest.
+     */
+    public ExpImpCatalog(URL sUrl, URL dUrl, boolean unique) {
+        try {
+            sourceClient = new XmlRpcFileManagerClient(sUrl);
+        } catch (ConnectionException e) {
+            LOG.log(Level.WARNING, "Unable to connect to source filemgr: ["
+                    + sUrl + "]");
+            throw new RuntimeException(e);
+        }
+
+        try {
+            destClient = new XmlRpcFileManagerClient(dUrl);
+        } catch (ConnectionException e) {
+            LOG.log(Level.WARNING, "Unable to connect to dest filemgr: ["
+                    + dUrl + "]");
+            throw new RuntimeException(e);
+        }
+
+        this.ensureUnique = unique;
+    }
+
+    public ExpImpCatalog(String sPropFilePath, String dPropFilePath,
+            boolean unique) throws InstantiationException {
+        this.ensureUnique = unique;
+
+        LOG.log(Level.INFO, "Constructing tool using catalog interfaces");
+        // first load the source prop file
+        try {
+            System.getProperties().load(
+                    new File(sPropFilePath).toURL().openStream());
+        } catch (Exception e) {
+            throw new InstantiationException(e.getMessage());
+        }
+
+        // now construct the source catalog
+        String srcCatFactoryStr = System.getProperty("filemgr.catalog.factory");
+        LOG.log(Level.INFO, "source catalog factory: [" + srcCatFactoryStr
+                + "]");
+        this.srcCatalog = GenericFileManagerObjectFactory
+                .getCatalogServiceFromFactory(srcCatFactoryStr);
+
+        // first load the dest prop file
+        try {
+            System.getProperties().load(
+                    new File(dPropFilePath).toURL().openStream());
+        } catch (Exception e) {
+            throw new InstantiationException(e.getMessage());
+        }
+
+        String destCatFactoryStr = System
+                .getProperty("filemgr.catalog.factory");
+        LOG
+                .log(Level.INFO, "dest catalog factory: [" + destCatFactoryStr
+                        + "]");
+        this.destCatalog = GenericFileManagerObjectFactory
+                .getCatalogServiceFromFactory(destCatFactoryStr);
+
+    }
+
+    public void doExpImport(List sourceProductTypes) throws Exception {
+
+        if (this.sourceClient != null && this.destClient != null) {
+            // do validation of source/dest types
+            // otherwise, user is on their own discretion
+            List destProductTypes = destClient.getProductTypes();
+
+            if (!typesExist(sourceProductTypes, destProductTypes)) {
+                throw new Exception(
+                        "The source product types must be present in the dest file manager!");
+            } else {
+                LOG
+                        .log(Level.INFO,
+                                "Source types and Dest types match: beginning processing");
+            }
+        } else
+            LOG.log(Level.INFO,
+                    "Skipping type validation: catalog i/f impls being used.");
+
+        // we'll use the get product page method for each product type
+        // paginate through products using source product type
+
+        for (Iterator i = sourceProductTypes.iterator(); i.hasNext();) {
+            ProductType type = (ProductType) i.next();
+            try {
+                exportTypeToDest(type);
+            } catch (Exception e) {
+                LOG.log(Level.WARNING, "Error exporting product type: ["
+                        + type.getName() + "] from source to dest: Message: "
+                        + e.getMessage(), e);
+                throw e;
+            }
+        }
+
+    }
+
+    public void doExpImport() throws Exception {
+        if (sourceClient == null)
+            throw new RuntimeException(
+                    "Cannot request exp/imp of all product types if no filemgr url specified!");
+        List sourceProductTypes = sourceClient.getProductTypes();
+        doExpImport(sourceProductTypes);
+    }
+
+    private void exportTypeToDest(ProductType type) throws Exception {
+        ProductPage page = null;
+
+        if (this.srcCatalog != null) {
+            page = srcCatalog.getFirstPage(type);
+        } else {
+            page = sourceClient.getFirstPage(type);
+        }
+
+        if (page == null)
+            return;
+
+        exportProductsToDest(page.getPageProducts(), type);
+        while (!page.isLastPage()) {
+            if (this.srcCatalog != null) {
+                page = srcCatalog.getNextPage(type, page);
+            } else
+                page = sourceClient.getNextPage(type, page);
+            if (page == null)
+                break;
+            exportProductsToDest(page.getPageProducts(), type);
+        }
+    }
+
+    private void exportProductsToDest(List products, ProductType type)
+            throws Exception {
+        if (products != null && products.size() > 0) {
+            for (Iterator i = products.iterator(); i.hasNext();) {
+                Product p = (Product) i.next();
+
+                if (ensureUnique) {
+                    boolean hasProduct = safeHasProductTypeByName(p
+                            .getProductName());
+                    if (hasProduct) {
+                        LOG.log(Level.INFO, "Skipping product: ["
+                                + p.getProductName()
+                                + "]: ensure unique enabled: "
+                                + "product exists in dest catalog");
+                        continue;
+                    }
+                }
+
+                p.setProductType(type);
+                if (sourceClient != null) {
+                    p
+                            .setProductReferences(sourceClient
+                                    .getProductReferences(p));
+                } else
+                    p.setProductReferences(srcCatalog.getProductReferences(p));
+
+                Metadata met = null;
+
+                if (sourceClient != null) {
+                    met = sourceClient.getMetadata(p);
+                } else {
+                    met = srcCatalog.getMetadata(p);
+                }
+
+                LOG
+                        .log(
+                                Level.INFO,
+                                "Source Product: ["
+                                        + p.getProductName()
+                                        + "]: Met Extraction and "
+                                        + "Reference Extraction successful: writing to dest file manager");
+
+                // OODT-543
+                if(sourceClient != null){
+                  // remove the default CAS fields for metadata
+                  met.removeMetadata("CAS.ProductId");
+                  met.removeMetadata("CAS.ProductReceivedTime");
+                  met.removeMetadata("CAS.ProductName");
+                }
+
+                Product destProduct = new Product();
+                // copy through
+                destProduct.setProductName(p.getProductName());
+                destProduct.setProductStructure(p.getProductStructure());
+                destProduct.setProductType((destClient != null) ? destClient
+                        .getProductTypeById(type.getProductTypeId()) : type);
+                destProduct.setTransferStatus(p.getTransferStatus());
+
+                LOG.log(Level.INFO, "Cataloging Product: ["
+                        + p.getProductName() + "]");
+                String destProductId = null;
+                if (destCatalog != null) {
+                    destCatalog.addProduct(destProduct);
+                    destProductId = destProduct.getProductId();
+                } else
+                    destProductId = destClient.catalogProduct(destProduct);
+                LOG.log(Level.INFO, "Catalog successful: dest product id: ["
+                        + destProductId + "]");
+                destProduct.setProductId(destProductId);
+
+                LOG.log(Level.INFO, "Adding references for dest product: ["
+                        + destProductId + "]");
+                destProduct.setProductReferences(p.getProductReferences());
+                if (destCatalog != null) {
+                    destCatalog.addProductReferences(destProduct);
+                } else
+                    destClient.addProductReferences(destProduct);
+                LOG.log(Level.INFO,
+                        "Reference addition successful for dest product: ["
+                                + destProductId + "]");
+
+                LOG.log(Level.INFO, "Adding metadata for dest product: ["
+                        + destProductId + "]");
+                if (destCatalog != null) {
+                    destCatalog.addMetadata(met, destProduct);
+                } else
+                    destClient.addMetadata(destProduct, met);
+                LOG.log(Level.INFO,
+                        "Met addition successful for dest product: ["
+                                + destProductId + "]");
+
+                LOG.log(Level.INFO, "Successful import of product: ["
+                        + p.getProductName() + "] into dest file manager");
+            }
+        }
+    }
+
+    /**
+     * @return Returns the ensureUnique.
+     */
+    public boolean isEnsureUnique() {
+        return ensureUnique;
+    }
+
+    /**
+     * @param ensureUnique
+     *            The ensureUnique to set.
+     */
+    public void setEnsureUnique(boolean ensureUnique) {
+        this.ensureUnique = ensureUnique;
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) throws Exception {
+        String sourceUrl = null, destUrl = null, srcCatPropFile = null, destCatPropFile = null;
+        boolean unique = false;
+        List types = null;
+
+        String usage = "ExpImpCatalog [options] \n" + "--source <url>\n"
+                + "--dest <url>\n " + "--unique\n"
+                + "[--types <comma separate list of product type names>]\n"
+                + "[--sourceCatProps <file> --destCatProps <file>]\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--source")) {
+                sourceUrl = args[++i];
+            } else if (args[i].equals("--dest")) {
+                destUrl = args[++i];
+            } else if (args[i].equals("--unique")) {
+                unique = true;
+            } else if (args[i].equals("--types")) {
+                String[] typesAndIdsEnc = args[++i].split(",");
+
+                types = new Vector(typesAndIdsEnc.length);
+                for (int j = 0; j < typesAndIdsEnc.length; j++) {
+                    String[] typeIdToks = typesAndIdsEnc[j].split("\\|");
+                    ProductType type = new ProductType();
+                    type.setName(typeIdToks[0]);
+                    type.setProductTypeId(typeIdToks[1]);
+                    types.add(type);
+                }
+            } else if (args[i].equals("--sourceCatProps")) {
+                srcCatPropFile = args[++i];
+            } else if (args[i].equals("--destCatProps")) {
+                destCatPropFile = args[++i];
+            }
+        }
+
+        if (((sourceUrl == null || destUrl == null) && (srcCatPropFile == null || destCatPropFile == null))
+                || (sourceUrl != null && destUrl != null && (srcCatPropFile != null || destCatPropFile != null))
+                || ((srcCatPropFile != null && destCatPropFile == null) || (destCatPropFile != null && srcCatPropFile == null))) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        ExpImpCatalog tool = null;
+
+        if (srcCatPropFile != null) {
+            tool = new ExpImpCatalog(srcCatPropFile, destCatPropFile, unique);
+        } else
+            tool = new ExpImpCatalog(new URL(sourceUrl), new URL(destUrl),
+                    unique);
+
+        if (types != null && types.size() > 0) {
+            tool.doExpImport(types);
+        } else
+            tool.doExpImport();
+    }
+
+    private boolean typesExist(List sourceList, List destList) {
+        if (sourceList == null
+                || (sourceList != null && sourceList.size() == 0)) {
+            return false;
+        }
+
+        if (destList == null || (destList != null && destList.size() == 0)) {
+            return false;
+        }
+
+        // iterate through the source types and try and find the type in the
+        // destList
+        for (Iterator i = sourceList.iterator(); i.hasNext();) {
+            ProductType type = (ProductType) i.next();
+            if (!typeInList(type, destList)) {
+                LOG.log(Level.WARNING, "Source type: [" + type.getName()
+                        + "] not present in dest file manager");
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private boolean typeInList(ProductType type, List typeList) {
+        if (typeList == null || (typeList != null && typeList.size() == 0)) {
+            return false;
+        }
+
+        for (Iterator i = typeList.iterator(); i.hasNext();) {
+            ProductType destType = (ProductType) i.next();
+            if (destType.getProductTypeId().equals(type.getProductTypeId())
+                    && destType.getName().equals(type.getName())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private boolean safeHasProductTypeByName(String productName) {
+
+        if (destCatalog != null) {
+            try {
+                return (destCatalog.getProductByName(productName) != null);
+            } catch (CatalogException e) {
+                e.printStackTrace();
+                LOG
+                        .log(Level.WARNING,
+                                "Exceptiong checking for product type by name: ["
+                                        + productName + "]: Message: "
+                                        + e.getMessage());
+                return false;
+            }
+        } else {
+            try {
+                return destClient.hasProduct(productName);
+            } catch (CatalogException e) {
+                e.printStackTrace();
+                LOG
+                        .log(Level.WARNING,
+                                "Exceptiong checking for product type by name: ["
+                                        + productName + "]: Message: "
+                                        + e.getMessage());
+                return false;
+            }
+
+        }
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/MetadataBasedProductMover.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/MetadataBasedProductMover.java
new file mode 100644
index 0000000..d5c4302
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/MetadataBasedProductMover.java
@@ -0,0 +1,175 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//JDK imports
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A tool to move products based on their metadata attributes.
+ * </p>
+ * 
+ */
+public class MetadataBasedProductMover {
+
+    /*
+     * the metadata path sepc string, e.g.,
+     * /path/to/final/loc/[LocalDay]/[Filename]
+     */
+    private String pathSpec = null;
+
+    /* the client to the file manager */
+    private XmlRpcFileManagerClient fmgrClient = null;
+
+    /* our log stream */
+    private static final Logger LOG = Logger
+            .getLogger(MetadataBasedProductMover.class.getName());
+
+    /**
+     * Default constructor.
+     * 
+     * @param pathSpec
+     *            A path specification based on the product metadata for the
+     *            final data store location.
+     * @param fmUrl
+     *            A string URL to the file manager.
+     * @throws InstantiationException
+     *             If the passed in url is malformed.
+     */
+    public MetadataBasedProductMover(String pathSpec, String fmUrl)
+            throws InstantiationException {
+        this.pathSpec = pathSpec;
+        try {
+            this.fmgrClient = new XmlRpcFileManagerClient(new URL(fmUrl));
+        } catch (MalformedURLException e) {
+            throw new InstantiationException(e.getMessage());
+        } catch (ConnectionException e) {
+            throw new InstantiationException(e.getMessage());
+        }
+    }
+
+    public void moveProducts(ProductType type) throws Exception {
+        // paginate through the product list
+
+        ProductPage page = fmgrClient.getFirstPage(type);
+
+        for (int i = 0; i < page.getTotalPages(); i++) {
+            if (page.getPageProducts() != null
+                    && page.getPageProducts().size() > 0) {
+                for (Iterator j = page.getPageProducts().iterator(); j
+                        .hasNext();) {
+                    Product p = (Product) j.next();
+                    p.setProductReferences(fmgrClient.getProductReferences(p));
+                    Metadata met = fmgrClient.getMetadata(p);
+                    Reference r = ((Reference) p.getProductReferences().get(0));
+                    String newLocPath = PathUtils.replaceEnvVariables(
+                            this.pathSpec, met);
+                    
+                    if (locationsMatch(r.getDataStoreReference(), newLocPath)) {
+                    	LOG.log(Level.INFO, "Current and New locations match. "+p.getProductName()+" was not moved.");
+                    	continue;
+                    }
+                    
+                    LOG.log(Level.INFO, "Moving product: ["
+                            + p.getProductName() + "] from: ["
+                            + new File(new URI(r.getDataStoreReference()))
+                            + "] to: [" + newLocPath + "]");
+                    long timeBefore = System.currentTimeMillis();
+                    fmgrClient.moveProduct(p, newLocPath);
+                    long timeAfter = System.currentTimeMillis();
+                    double seconds = ((timeAfter - timeBefore) * 1.0) / (1000.0);
+                    LOG.log(Level.INFO, "Product: [" + p.getProductName()
+                            + "] move successful: took: [" + seconds
+                            + "] seconds");
+                }
+
+                if (!page.isLastPage()) {
+                    page = fmgrClient.getNextPage(type, page);
+                }
+            }
+        }
+    }
+
+    private boolean locationsMatch(String currentLocation, String newLocation) throws java.net.URISyntaxException {
+    	String currentLocationURI = new URI(currentLocation).getSchemeSpecificPart();
+    	String newLocationURI = new URI(newLocation).getSchemeSpecificPart();
+
+    	if (currentLocationURI.equals(newLocationURI)) {
+    		return true;
+    	}
+    	else {
+    		return false;
+    	}
+    	
+    }
+    
+    public void moveProducts(String typeName) throws Exception {
+        moveProducts(fmgrClient.getProductTypeByName(typeName));
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) throws Exception {
+        String typeName = null, pathSpec = null, fmUrlStr = null;
+        String usage = "MetadataBasedProductMover [options]\n"
+                + "--typeName <product type>\n"
+                + "--fileManagerUrl <url to file manager>\n"
+                + "--pathSpec <path spec using '[' and ']' to delimit met fields>\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--typeName")) {
+                typeName = args[++i];
+            } else if (args[i].equals("--pathSpec")) {
+                pathSpec = args[++i];
+            } else if (args[i].equals("--fileManagerUrl")) {
+                fmUrlStr = args[++i];
+            }
+        }
+
+        if (typeName == null || pathSpec == null || fmUrlStr == null) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        MetadataBasedProductMover mover = new MetadataBasedProductMover(
+                pathSpec, fmUrlStr);
+        mover.moveProducts(typeName);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/MetadataDumper.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/MetadataDumper.java
new file mode 100644
index 0000000..86a0cf8
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/MetadataDumper.java
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JDK imports
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A simple tool to write out a .met {@link Metadata} file for a specified
+ * {@link Product}.
+ * </p>.
+ */
+@Deprecated
+public final class MetadataDumper {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(MetadataDumper.class
+            .getName());
+
+    /* our file manager client */
+    private XmlRpcFileManagerClient fmClient = null;
+
+    private final static String FILENAME = "Filename";
+
+    private final static String PRODUCT_NAME = "CAS.ProductName";
+
+    public MetadataDumper(String fmUrlStr) throws InstantiationException {
+        try {
+            this.fmClient = new XmlRpcFileManagerClient(new URL(fmUrlStr));
+        } catch (MalformedURLException e) {
+            LOG.log(Level.SEVERE, "malformed file manager url: [" + fmUrlStr
+                    + "]", e);
+            throw new InstantiationException(e.getMessage());
+        } catch (ConnectionException e) {
+            LOG.log(Level.SEVERE, "unable to connect to file manager: ["
+                    + fmUrlStr + "]", e);
+            throw new InstantiationException(e.getMessage());
+        }
+    }
+
+    private Metadata getMetadata(String productId) {
+        Product product = null;
+
+        try {
+            product = this.fmClient.getProductById(productId);
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to retrieve product:["
+                    + productId + "] by id");
+        }
+
+        Metadata met = null;
+
+        try {
+            met = this.fmClient.getMetadata(product);
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to get metadata for product: ["
+                    + product.getProductName() + "]");
+        }
+
+        return met;
+    }
+
+    private void writeMetFileToDir(Metadata met, String fullMetFilePath) {
+        try {
+            XMLUtils.writeXmlFile(new SerializableMetadata(met).toXML(), fullMetFilePath);
+        } catch (Exception e) {
+            LOG.log(Level.WARNING, "Met file not generated: reason: "
+                    + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Dumps the {@link Metadata} from the {@link Product} identified by the
+     * given <code>productId</code>. The {@link Metadata} is written to the
+     * local directory <code>.</code>, where this program was invoked from.
+     * 
+     * @param productId
+     *            The string identifier of the product to dump {@link Metadata}
+     *            from.
+     */
+    public void dumpMetadata(String productId) {
+        dumpMetadata(productId, new File(".").getAbsolutePath());
+    }
+
+    /**
+     * Dumps the {@link Metadata} from the {@link Product} identified by the
+     * given <code>productId</code>. The {@link Metadata} is written to the
+     * specified <code>outDirPath</code>.
+     * 
+     * @param productId
+     *            The string identifier of the product to dump {@link Metadata}
+     *            from.
+     * @param outDirPath
+     *            The path on the local filesystem to write the {@link Metadata}
+     *            file to.
+     */
+    public void dumpMetadata(String productId, String outDirPath) {
+        Metadata met = getMetadata(productId);
+        String fullMetFilePath = outDirPath;
+        fullMetFilePath = (fullMetFilePath.endsWith("/")) ? fullMetFilePath
+                : fullMetFilePath + "/";
+        String filename = met.getMetadata(FILENAME) != null ? met
+                .getMetadata(FILENAME) : met.getMetadata(PRODUCT_NAME);
+        fullMetFilePath += filename + ".met";
+        writeMetFileToDir(met, fullMetFilePath);
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) throws Exception {
+        String fileManagerUrlStr = null, productId = null, outDirPath = null;
+        String usage = "MetadataDumper --url <filemgr url> --productId <id> [--out <dir path>]\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--url")) {
+                fileManagerUrlStr = args[++i];
+            } else if (args[i].equals("--productId")) {
+                productId = args[++i];
+            } else if (args[i].equals("--out")) {
+                outDirPath = args[++i];
+            }
+        }
+
+        if (fileManagerUrlStr == null || productId == null) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        MetadataDumper dumper = new MetadataDumper(fileManagerUrlStr);
+        if (outDirPath != null) {
+            dumper.dumpMetadata(productId, outDirPath);
+        } else
+            dumper.dumpMetadata(productId);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/OptimizeLuceneCatalog.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/OptimizeLuceneCatalog.java
new file mode 100644
index 0000000..d490e29
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/OptimizeLuceneCatalog.java
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//JDK imports
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//Lucene imports
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.index.IndexWriter;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Tool to optimize a {@link LuceneCatalog}'s index directory for search.
+ * </p>
+ * 
+ */
+public class OptimizeLuceneCatalog {
+
+    /* the path to the lucene index directory */
+    private String catalogPath = null;
+
+    /* the merge factor to use when optimizing the index */
+    private int mergeFactor = 20;
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(OptimizeLuceneCatalog.class
+            .getName());
+
+    /**
+     * Default constructor.
+     */
+    public OptimizeLuceneCatalog(String catPath, int mf) {
+        this.catalogPath = catPath;
+        this.mergeFactor = mf;
+    }
+
+    public void doOptimize() throws Exception {
+        IndexWriter writer = null;
+        boolean createIndex = false;
+
+        try {
+            writer = new IndexWriter(catalogPath, new StandardAnalyzer(),
+                    createIndex);
+            writer.setMergeFactor(this.mergeFactor);
+            long timeBefore = System.currentTimeMillis();
+            writer.optimize();
+            long timeAfter = System.currentTimeMillis();
+            double numSeconds = ((timeAfter - timeBefore) * 1.0) / 1000.0;
+            LOG.log(Level.INFO, "LuceneCatalog: [" + this.catalogPath
+                    + "] optimized: took: [" + numSeconds + "] seconds");
+        } catch (IOException e) {
+            LOG.log(Level.WARNING, "Unable to optimize lucene index: ["
+                    + catalogPath + "]: Message: " + e.getMessage());
+        } finally {
+            try {
+                writer.close();
+            } catch (Exception ignore) {
+            }
+            writer = null;
+        }
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) throws Exception {
+        String usage = "OptimizeLuceneCatalog [options]\n"
+                + "--catalogPath <path to lucene catalog>\n"
+                + "[--mergeFactor <merge factor for index>]\n";
+
+        String catPath = null;
+        int mergeFactor = -1;
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--catalogPath")) {
+                catPath = args[++i];
+            } else if (args[i].equals("--mergeFactor")) {
+                mergeFactor = Integer.parseInt(args[++i]);
+            }
+        }
+
+        if (catPath == null) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        if (mergeFactor == -1) {
+            mergeFactor = 20; // default
+        }
+
+        OptimizeLuceneCatalog optimizer = new OptimizeLuceneCatalog(catPath,
+                mergeFactor);
+        optimizer.doOptimize();
+
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/ProductDumper.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/ProductDumper.java
new file mode 100644
index 0000000..245185e
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/ProductDumper.java
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JDK imports
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A simple tool to write out a .product {@link Product} file containing product
+ * information and {@link Reference}s.
+ * </p>.
+ */
+public final class ProductDumper {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(ProductDumper.class
+            .getName());
+
+    /* our file manager client */
+    private XmlRpcFileManagerClient fmClient = null;
+
+    private final static String FILENAME = "Filename";
+
+    private final static String PRODUCT_NAME = "CAS.ProductName";
+
+    public ProductDumper(String fmUrlStr) throws InstantiationException {
+        try {
+            this.fmClient = new XmlRpcFileManagerClient(new URL(fmUrlStr));
+        } catch (MalformedURLException e) {
+            LOG.log(Level.SEVERE, "malformed file manager url: [" + fmUrlStr
+                    + "]", e);
+            throw new InstantiationException(e.getMessage());
+        } catch (ConnectionException e) {
+            LOG.log(Level.SEVERE, "unable to connect to file manager: ["
+                    + fmUrlStr + "]", e);
+            throw new InstantiationException(e.getMessage());
+        }
+    }
+
+    private Product getProduct(String productId) {
+        Product product = null;
+
+        try {
+            product = this.fmClient.getProductById(productId);
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to retrieve product:["
+                    + productId + "] by id");
+        }
+        try {
+            product.setProductReferences(this.fmClient
+                    .getProductReferences(product));
+        } catch (CatalogException e) {
+            LOG.log(Level.WARNING,
+                    "Unable to obtain product references! Message: "
+                            + e.getMessage());
+        }
+
+        return product;
+    }
+
+    private void writeProductFileToDir(Product p, String fullProdFilePath) {
+        try {
+            XMLUtils.writeXmlFile(p.toXML(), fullProdFilePath);
+        } catch (Exception e) {
+            LOG.log(Level.WARNING, "product xml file not generated: reason: "
+                    + e.getMessage(), e);
+        }
+    }
+
+    private Metadata getMetadata(Product product) {
+        Metadata met = null;
+
+        try {
+            met = this.fmClient.getMetadata(product);
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to get metadata for product: ["
+                    + product.getProductName() + "]");
+        }
+
+        return met;
+    }
+
+    /**
+     * Dumps a {@link Product} in XML format identified by the given
+     * <code>productId</code>. The {@link Product}XML is written to the
+     * local directory <code>.</code>, where this program was invoked from.
+     * 
+     * @param productId
+     *            The string identifier of the product to dump {@link Product}
+     *            info from.
+     */
+    public void dumpProduct(String productId) {
+        dumpProduct(productId, new File(".").getAbsolutePath());
+    }
+
+    /**
+     * Dumps a {@link Product} in XML format identified by the given
+     * <code>productId</code>. The {@link Product}XML is written to the
+     * specified <code>outDirPath</code>.
+     * 
+     * @param productId
+     *            The string identifier of the product to dump {@link Product}
+     *            info from.
+     * @param outDirPath
+     *            The path on the local filesystem to write the {@link Product}
+     *            xml file to.
+     */
+    public void dumpProduct(String productId, String outDirPath) {
+        Product product = getProduct(productId);
+        String fullProdFilePath = outDirPath;
+        fullProdFilePath = (fullProdFilePath.endsWith("/")) ? fullProdFilePath
+                : fullProdFilePath + "/";
+        Metadata met = getMetadata(product);
+        String filename = met.getMetadata(FILENAME) != null ? met
+                .getMetadata(FILENAME) : met.getMetadata(PRODUCT_NAME);
+        fullProdFilePath += filename + ".product";
+        writeProductFileToDir(product, fullProdFilePath);
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) throws Exception {
+        String fileManagerUrlStr = null, productId = null, outDirPath = null;
+        String usage = "ProductDumper --url <filemgr url> --productId <id> [--out <dir path>]\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--url")) {
+                fileManagerUrlStr = args[++i];
+            } else if (args[i].equals("--productId")) {
+                productId = args[++i];
+            } else if (args[i].equals("--out")) {
+                outDirPath = args[++i];
+            }
+        }
+
+        if (fileManagerUrlStr == null || productId == null) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        ProductDumper dumper = new ProductDumper(fileManagerUrlStr);
+        if (outDirPath != null) {
+            dumper.dumpProduct(productId, outDirPath);
+        } else
+            dumper.dumpProduct(productId);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/ProductTypeDocTool.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/ProductTypeDocTool.java
new file mode 100644
index 0000000..fac190d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/ProductTypeDocTool.java
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//JDK imports
+import java.io.File;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+//APACHE imports
+import org.apache.commons.io.FileUtils;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A tool to output HTML documentation for {@link ProductType} policy xml files.
+ * </p>.
+ */
+public final class ProductTypeDocTool {
+
+    private String xslFilePath;
+
+    private String outputDirPath;
+
+    public ProductTypeDocTool(String xslFilePath, String outputDirPath) {
+        this.xslFilePath = xslFilePath;
+        this.outputDirPath = outputDirPath;
+        if (!this.outputDirPath.endsWith("/")) {
+            this.outputDirPath += "/";
+        }
+    }
+
+    public void doProductTypeDoc(String productTypeXmlFilePath,
+            String elementXmlFilePath) throws Exception {
+        // copy element xml to current path
+        FileUtils.copyFileToDirectory(new File(elementXmlFilePath), new File(
+                "."));
+        // copy product type xsl to current path
+        FileUtils.copyFileToDirectory(new File(xslFilePath), new File("."));
+
+        String xslLocalFilePath = new File(".").getAbsolutePath();
+        if (!xslLocalFilePath.endsWith("/")) {
+            xslLocalFilePath += "/";
+        }
+        xslLocalFilePath += new File(xslFilePath).getName();
+
+        String elementLocalFilePath = new File(".").getAbsolutePath();
+        if (!elementLocalFilePath.endsWith("/")) {
+            elementLocalFilePath += "/";
+        }
+
+        elementLocalFilePath += new File(elementXmlFilePath).getName();
+
+        Transformer xformer = TransformerFactory.newInstance().newTransformer(
+                new StreamSource(new File(xslLocalFilePath)));
+
+        xformer.setOutputProperty(OutputKeys.INDENT, "yes");
+        String productTypeFileName = new File(productTypeXmlFilePath).getName();
+        String outputProductTypeDocFileName = productTypeFileName.replaceAll(
+                "xml", "html");
+
+        Result result = new StreamResult(new File(outputDirPath
+                + outputProductTypeDocFileName));
+
+        xformer.transform(new StreamSource(new File(productTypeXmlFilePath)),
+                result);
+
+        // now cleanup
+        new File(xslLocalFilePath).delete();
+        new File(elementLocalFilePath).delete();
+    }
+
+    public static void main(String[] args) throws Exception {
+        String productTypeXmlFilePath = null, xslFilePath = null, outputDirPath = null, elementXmlFilePath = null;
+        String usage = "ProductTypeDocTool --productTypeXml <path> "
+                + "--elementXml <path> --xsl <path> --out <dir path>\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--productTypeXml")) {
+                productTypeXmlFilePath = args[++i];
+            } else if (args[i].equals("--xsl")) {
+                xslFilePath = args[++i];
+            } else if (args[i].equals("--out")) {
+                outputDirPath = args[++i];
+            } else if (args[i].equals("--elementXml")) {
+                elementXmlFilePath = args[++i];
+            }
+        }
+
+        if (productTypeXmlFilePath == null || xslFilePath == null
+                || outputDirPath == null || elementXmlFilePath == null) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        ProductTypeDocTool tool = new ProductTypeDocTool(xslFilePath,
+                outputDirPath);
+        tool.doProductTypeDoc(productTypeXmlFilePath, elementXmlFilePath);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/QueryTool.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/QueryTool.java
new file mode 100644
index 0000000..b761530
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/QueryTool.java
@@ -0,0 +1,263 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.QueryFormulationException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.structs.query.ComplexQuery;
+import org.apache.oodt.cas.filemgr.structs.query.QueryResult;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.filemgr.util.SqlParser;
+
+//APACHE imports
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.PhraseQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.RangeQuery;
+import org.apache.lucene.search.TermQuery;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A tool to return product ids given a {@link Query} against the File Manager.
+ * </p>
+ */
+@Deprecated
+public final class QueryTool {
+
+    private static String freeTextBlock = "__FREE__";
+
+    private XmlRpcFileManagerClient client = null;
+
+    private static enum QueryType { LUCENE, SQL }; 
+    
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(QueryTool.class.getName());
+
+    public QueryTool(URL fmUrl) throws InstantiationException {
+        try {
+            client = new XmlRpcFileManagerClient(fmUrl);
+        } catch (ConnectionException e) {
+            throw new InstantiationException(e.getMessage());
+        }
+    }
+
+    public static Query parseQuery(String query) {
+        QueryParser parser;
+        // note that "__FREE__" is a control work for free text searching
+        parser = new QueryParser(freeTextBlock, new CASAnalyzer());
+        Query luceneQ = null;
+        try {
+            luceneQ = (Query) parser.parse(query);
+        } catch (ParseException e) {
+            System.out.println("Error parsing query text.");
+            System.exit(-1);
+        }
+        return luceneQ;
+    }
+
+    public List query(org.apache.oodt.cas.filemgr.structs.Query query) {
+        List prodIds = new Vector();
+        List products = new Vector();
+
+        List productTypes = safeGetProductTypes();
+
+        if (productTypes != null && productTypes.size() > 0) {
+            for (Iterator i = productTypes.iterator(); i.hasNext();) {
+                ProductType type = (ProductType) i.next();
+                try {
+                    products = client.query(query, type);
+                    if (products != null && products.size() > 0) {
+                        for (Iterator j = products.iterator(); j.hasNext();) {
+                            Product product = (Product) j.next();
+                            prodIds.add(product.getProductId());
+                        }
+                    }
+                } catch (CatalogException e) {
+                    LOG.log(Level.WARNING, "Exception querying for: ["
+                            + type.getName() + "] products: Message: "
+                            + e.getMessage());
+                }
+
+            }
+
+        }
+
+        return prodIds;
+
+    }
+
+    public void generateCASQuery(
+            org.apache.oodt.cas.filemgr.structs.Query casQuery,
+            Query luceneQuery) {
+        if (luceneQuery instanceof TermQuery) {
+            Term t = ((TermQuery) luceneQuery).getTerm();
+            if (t.field().equals(freeTextBlock)) {
+                // nothing for now
+            } else {
+                casQuery.addCriterion(new TermQueryCriteria(t.field(), 
+                        t.text()));
+            }
+        } else if (luceneQuery instanceof PhraseQuery) {
+            Term[] t = ((PhraseQuery) luceneQuery).getTerms();
+            if (t[0].field().equals(freeTextBlock)) {
+                // nothing for now
+            } else {
+                for (int i = 0; i < t.length; i++)
+                    casQuery.addCriterion(new TermQueryCriteria(
+                            t[i].field(), t[i].text()));
+            }
+        } else if (luceneQuery instanceof RangeQuery) {
+            Term startT = ((RangeQuery) luceneQuery).getLowerTerm();
+            Term endT = ((RangeQuery) luceneQuery).getUpperTerm();
+            casQuery.addCriterion(new RangeQueryCriteria(startT
+                    .field(), startT.text(), endT.text()));
+        } else if (luceneQuery instanceof BooleanQuery) {
+            BooleanClause[] clauses = ((BooleanQuery) luceneQuery).getClauses();
+            for (int i = 0; i < clauses.length; i++) {
+                generateCASQuery(casQuery, (clauses[i]).getQuery());
+            }
+        } else {
+            throw new RuntimeException(
+                    "Error parsing query! Cannot determine clause type: ["
+                            + luceneQuery.getClass().getName() + "] !");
+        }
+    }
+
+    private List safeGetProductTypes() {
+        List prodTypes = null;
+
+        try {
+            prodTypes = client.getProductTypes();
+        } catch (RepositoryManagerException e) {
+            LOG.log(Level.WARNING,
+                    "Error obtaining product types from file manager: ["
+                            + client.getFileManagerUrl() + "]: Message: "
+                            + e.getMessage());
+        }
+
+        return prodTypes;
+    }
+
+    public static void main(String[] args) throws Exception {
+        String usage = "Usage: QueryTool [options] \n"
+            + "options: \n"
+            + "--url <fm url> \n"
+            + "  Lucene like query options: \n"
+            + "    --lucene \n"
+            + "         -query <query> \n"
+            + "  SQL like query options: \n"
+            + "    --sql \n"
+            + "         -query <query> \n"
+            + "         -sortBy <metadata-key> \n"
+            + "         -outputFormat <output-format-string> \n";
+            		
+        String fmUrlStr = null, queryStr = null, sortBy = null, outputFormat = null, delimiter = null;
+        QueryType queryType = null;
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--lucene")) {
+                if (queryType != null)
+                    exit("ERROR: Can only perform one query at a time! \n" + usage);
+                if (args[++i].equals("-query"))
+                    queryStr = args[++i];
+                else 
+                    exit("ERROR: Must specify a query! \n" + usage);
+                queryType = QueryType.LUCENE;
+            }else if (args[i].equals("--sql")) {
+                if (queryType != null)
+                    exit("ERROR: Can only perform one query at a time! \n" + usage);
+                if (args[++i].equals("-query"))
+                    queryStr = args[++i];
+                else 
+                    exit("ERROR: Must specify a query! \n" + usage);
+                for (; i < args.length; i++) {
+                    if (args[i].equals("-sortBy"))
+                        sortBy = args[++i];
+                    else if (args[i].equals("-outputFormat"))
+                        outputFormat = args[++i];
+                    else if (args[i].equals("-delimiter"))
+                        delimiter = args[++i];
+                }
+                queryType = QueryType.SQL;
+            }else if (args[i].equals("--url")) {
+                fmUrlStr = args[++i];
+            }
+        }
+
+        if (queryStr == null || fmUrlStr == null) 
+            exit("Must specify a query and filemgr url! \n" + usage);
+        
+        if (queryType == QueryType.LUCENE) {
+            URL fmUrl = new URL(fmUrlStr);
+            QueryTool queryTool = new QueryTool(fmUrl);
+            org.apache.oodt.cas.filemgr.structs.Query casQuery = new org.apache.oodt.cas.filemgr.structs.Query();
+            queryTool.generateCASQuery(casQuery, parseQuery(queryStr));
+    
+            List prodIds = queryTool.query(casQuery);
+            if (prodIds != null && prodIds.size() > 0) {
+                for (Iterator i = prodIds.iterator(); i.hasNext();) {
+                    String prodId = (String) i.next();
+                    System.out.println(prodId);
+                }
+            }
+        }else {
+            System.out.println(performSqlQuery(queryStr, sortBy, outputFormat, delimiter != null ? delimiter : "\n", fmUrlStr));
+        }
+
+    }
+    
+    private static String performSqlQuery(String query, String sortBy, String outputFormat, String delimiter, String filemgrUrl) 
+            throws MalformedURLException, CatalogException, ConnectionException, QueryFormulationException {
+        ComplexQuery complexQuery = SqlParser.parseSqlQuery(query);
+        complexQuery.setSortByMetKey(sortBy);
+        complexQuery.setToStringResultFormat(outputFormat);
+        List<QueryResult> results = new XmlRpcFileManagerClient(new URL(filemgrUrl)).complexQuery(complexQuery);
+        StringBuffer returnString = new StringBuffer("");
+        for (QueryResult qr : results) 
+            returnString.append(qr.toString() + delimiter);
+        return returnString.substring(0, returnString.length() - delimiter.length());
+    }
+    
+    private static void exit(String msg) {
+        System.err.println(msg);
+        System.exit(1);
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/RangeQueryTester.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/RangeQueryTester.java
new file mode 100644
index 0000000..86d6029
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/RangeQueryTester.java
@@ -0,0 +1,329 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//JDK imports
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//Lucene imports
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Hits;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.RangeQuery;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.search.TermQuery;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Utility command line program to test RangeQueries against an underlying
+ * Lucene-based Product Catalog.
+ * </p>
+ * 
+ */
+public final class RangeQueryTester {
+
+    private String startFieldName = null;
+
+    private String endFieldName = null;
+
+    private String startFieldStartValue = null;
+
+    private String startFieldEndValue = null;
+
+    private String endFieldStartValue = null;
+
+    private String endFieldEndValue = null;
+
+    private String indexPath = null;
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(RangeQueryTester.class
+            .getName());
+
+    /**
+     * 
+     */
+    public RangeQueryTester() {
+    }
+
+    public List doRangeQuery(String productTypeId) {
+        List products = null;
+        IndexSearcher searcher = null;
+
+        try {
+            searcher = new IndexSearcher(this.indexPath);
+
+            // construct a Boolean query here
+            BooleanQuery booleanQuery = new BooleanQuery();
+
+            // add the product type as the first clause
+            TermQuery prodTypeTermQuery = new TermQuery(new Term(
+                    "product_type_id", productTypeId));
+            booleanQuery.add(prodTypeTermQuery, BooleanClause.Occur.MUST);
+
+            Term startFieldStartTerm = null, startFieldEndTerm = null;
+
+            if (this.startFieldStartValue != null) {
+                startFieldStartTerm = new Term(this.startFieldName,
+                        this.startFieldStartValue);
+            }
+
+            if (this.startFieldEndValue != null) {
+                startFieldEndTerm = new Term(this.startFieldName,
+                        this.startFieldEndValue);
+            }
+
+            RangeQuery query1 = new RangeQuery(startFieldStartTerm,
+                    startFieldEndTerm, true);
+            booleanQuery.add(query1, BooleanClause.Occur.MUST);
+
+            if (this.endFieldName != null
+                    && (this.endFieldStartValue != null || this.endFieldEndValue != null)) {
+                Term endFieldEndTerm = null, endFieldStartTerm = null;
+
+                if (this.endFieldStartValue != null) {
+                    endFieldStartTerm = new Term(this.endFieldName,
+                            this.endFieldStartValue);
+                }
+
+                if (this.endFieldEndValue != null) {
+                    endFieldEndTerm = new Term(this.endFieldName,
+                            this.endFieldEndValue);
+                }
+
+                RangeQuery query2 = new RangeQuery(endFieldStartTerm,
+                        endFieldEndTerm, true);
+                booleanQuery.add(query2, BooleanClause.Occur.MUST);
+            }
+
+            Sort sort = new Sort(new SortField("CAS.ProductReceivedTime",
+                    SortField.STRING, true));
+            Hits hits = searcher.search(booleanQuery, sort);
+            if (hits.length() > 0) {
+                products = new Vector(hits.length());
+                for (int i = 0; i < hits.length(); i++) {
+                    Document productDoc = hits.doc(i);
+                    products.add(productDoc.get("reference_data_store"));
+                }
+            } else {
+                LOG.log(Level.WARNING, "Query: [" + query1
+                        + "] for Product Type: [" + productTypeId
+                        + "] returned no results");
+            }
+
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: ["
+                            + this.indexPath + "] for search: Message: "
+                            + e.getMessage());
+            throw new RuntimeException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+
+        return products;
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) {
+        String usage = "RangeQueryTester [options]\n"
+                + "\t--idxPath </path/to/lucene/index>\n"
+                + "\t--productTypeId <product type>\n"
+                + "\t--startField <field for start range>\n"
+                + "\t--endField <field for end range>\n"
+                + "\t--startFieldStart <value>\n"
+                + "\t--startFieldEnd <value>\n" + "\t--endFieldStart <value>\n"
+                + "\t--endFieldEnd <value>\n";
+
+        String idxPath = null, startField = null, endField = null;
+        String startFieldStart = null, startFieldEnd = null;
+        String endFieldStart = null, endFieldEnd = null;
+        String productTypeId = null;
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--idxPath")) {
+                idxPath = args[++i];
+            } else if (args[i].equals("--startField")) {
+                startField = args[++i];
+            } else if (args[i].equals("--endField")) {
+                endField = args[++i];
+            } else if (args[i].equals("--startFieldStart")) {
+                startFieldStart = args[++i];
+            } else if (args[i].equals("--startFieldEnd")) {
+                startFieldEnd = args[++i];
+            } else if (args[i].equals("--endFieldStart")) {
+                endFieldStart = args[++i];
+            } else if (args[i].equals("--endFieldEnd")) {
+                endFieldEnd = args[++i];
+            } else if (args[i].equals("--productTypeId")) {
+                productTypeId = args[++i];
+            }
+        }
+
+        if (idxPath == null || productTypeId == null || startField == null
+                || (startFieldStart == null && startFieldEnd == null)) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        RangeQueryTester queryTester = new RangeQueryTester();
+        queryTester.setIndexPath(idxPath);
+        queryTester.setStartFieldEndValue(startFieldEnd);
+        queryTester.setStartFieldStartValue(startFieldStart);
+        queryTester.setStartFieldName(startField);
+        queryTester.setEndFieldName(endField);
+        queryTester.setEndFieldStartValue(endFieldStart);
+        queryTester.setEndFieldEndValue(endFieldEnd);
+
+        List productFiles = queryTester.doRangeQuery(productTypeId);
+
+        if (productFiles != null && productFiles.size() > 0) {
+            for (Iterator i = productFiles.iterator(); i.hasNext();) {
+                String productFile = (String) i.next();
+                System.out.println(productFile);
+            }
+        } else
+            System.out.println("No results found!");
+    }
+
+    /**
+     * @return Returns the endFieldName.
+     */
+    public String getEndFieldName() {
+        return endFieldName;
+    }
+
+    /**
+     * @param endFieldName
+     *            The endFieldName to set.
+     */
+    public void setEndFieldName(String endFieldName) {
+        this.endFieldName = endFieldName;
+    }
+
+    /**
+     * @return Returns the indexPath.
+     */
+    public String getIndexPath() {
+        return indexPath;
+    }
+
+    /**
+     * @param indexPath
+     *            The indexPath to set.
+     */
+    public void setIndexPath(String indexPath) {
+        this.indexPath = indexPath;
+    }
+
+    /**
+     * @return Returns the startFieldName.
+     */
+    public String getStartFieldName() {
+        return startFieldName;
+    }
+
+    /**
+     * @param startFieldName
+     *            The startFieldName to set.
+     */
+    public void setStartFieldName(String startFieldName) {
+        this.startFieldName = startFieldName;
+    }
+
+    /**
+     * @return Returns the endFieldEndValue.
+     */
+    public String getEndFieldEndValue() {
+        return endFieldEndValue;
+    }
+
+    /**
+     * @param endFieldEndValue
+     *            The endFieldEndValue to set.
+     */
+    public void setEndFieldEndValue(String endFieldEndValue) {
+        this.endFieldEndValue = endFieldEndValue;
+    }
+
+    /**
+     * @return Returns the endFieldStartValue.
+     */
+    public String getEndFieldStartValue() {
+        return endFieldStartValue;
+    }
+
+    /**
+     * @param endFieldStartValue
+     *            The endFieldStartValue to set.
+     */
+    public void setEndFieldStartValue(String endFieldStartValue) {
+        this.endFieldStartValue = endFieldStartValue;
+    }
+
+    /**
+     * @return Returns the startFieldEndValue.
+     */
+    public String getStartFieldEndValue() {
+        return startFieldEndValue;
+    }
+
+    /**
+     * @param startFieldEndValue
+     *            The startFieldEndValue to set.
+     */
+    public void setStartFieldEndValue(String startFieldEndValue) {
+        this.startFieldEndValue = startFieldEndValue;
+    }
+
+    /**
+     * @return Returns the startFieldStartValue.
+     */
+    public String getStartFieldStartValue() {
+        return startFieldStartValue;
+    }
+
+    /**
+     * @param startFieldStartValue
+     *            The startFieldStartValue to set.
+     */
+    public void setStartFieldStartValue(String startFieldStartValue) {
+        this.startFieldStartValue = startFieldStartValue;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/SolrIndexer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/SolrIndexer.java
new file mode 100755
index 0000000..367358f
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/tools/SolrIndexer.java
@@ -0,0 +1,798 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//JDK imports
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
+import org.apache.solr.common.SolrInputDocument;
+import org.springframework.util.StringUtils;
+
+/**
+ * Indexes products from the File Manager catalog to a Solr instance. Uses an
+ * associated config file, indexer.properties to specify how to perform the
+ * indexing. See indexer.properties in the src/main/resources directory for
+ * specific documentation.
+ */
+public class SolrIndexer {
+	private final static String SOLR_INDEXER_CONFIG = "SOLR_INDEXER_CONFIG";
+	private final static String SOLR_URL = "solr.url";
+	private final static String FILEMGR_URL = "filemgr.url";
+	private final static String ACCESS_KEY = "access.key";
+	private final static String ACCESS_URL = "access.url";
+	private final static String PRODUCT_NAME = "CAS.ProductName";
+	private IndexerConfig config = null;
+	private final SolrServer server;
+	private String fmUrl;
+	private String solrUrl;
+	private static Logger LOG = Logger.getLogger(SolrIndexer.class.getName());
+	private final static SimpleDateFormat solrFormat = new SimpleDateFormat(
+	    "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+
+	/**
+	 * Constructor reads in the configuration and initiates the connection to the
+	 * Solr instance.
+	 * 
+	 * @param solrUrl
+	 *          URL for the Solr instance.
+	 * @param fmUrl
+	 *          URL for the File Manager instance.
+	 */
+	public SolrIndexer(String solrUrl, String fmUrl)
+	    throws InstantiationException {
+		InputStream input = null;
+		String filename = null;
+
+		try {
+			LOG.info("System property " + SOLR_INDEXER_CONFIG + " set to "
+			    + System.getProperty(SOLR_INDEXER_CONFIG));
+			filename = System.getProperty(SOLR_INDEXER_CONFIG);
+			if (filename != null) {
+				LOG.info("Reading config from " + filename);
+				input = new FileInputStream(filename);
+			} else {
+				LOG.info("Config file not found, reading config from classpath");
+				input = SolrIndexer.class.getResourceAsStream("/indexer.properties");
+			}
+			config = new IndexerConfig(input);
+		} catch (IOException e) {
+			LOG
+			    .severe("Could not read in configuration for indexer from classpath or file");
+			throw new InstantiationException(e.getMessage());
+		} finally {
+			if (input != null) {
+				try {
+					input.close();
+				} catch (IOException e) {
+					// no op
+				}
+			}
+		}
+
+		this.solrUrl = solrUrl;
+		if (this.solrUrl == null) {
+			this.solrUrl = config.getProperty(SOLR_URL);
+		}
+
+		this.fmUrl = fmUrl;
+		if (this.fmUrl == null) {
+			this.fmUrl = config.getProperty(FILEMGR_URL);
+		}
+
+		LOG.info("Using Solr: " + this.solrUrl + " FileManager: " + this.fmUrl);
+
+		try {
+			server = new CommonsHttpSolrServer(this.solrUrl);
+		} catch (MalformedURLException e) {
+			LOG.severe("Could not connect to Solr server " + this.solrUrl);
+			throw new InstantiationException(e.getMessage());
+		}
+
+	}
+
+	/**
+	 * This method deletes all entries from the Solr index.
+	 */
+	public void delete() throws SolrServerException, IOException {
+		server.deleteByQuery("*:*");
+	}
+
+	/**
+	 * This method commits all of the modifications to the Solr index.
+	 */
+	public void commit() throws SolrServerException, IOException {
+		server.commit();
+	}
+
+	/**
+	 * This method optimizes the Solr index.
+	 */
+	public void optimize() throws SolrServerException, IOException {
+		server.optimize();
+	}
+
+	/**
+	 * This method transforms the product metadata into a Solr document.
+	 * 
+	 * @param metadata
+	 *          The metadata object for the product to index.
+	 * @return Returns the SolrInputDocument containing product metadata.
+	 */
+	private SolrInputDocument getSolrDocument(Metadata metadata) {
+		SolrInputDocument doc = new SolrInputDocument();
+		// Only grab metadata which have a mapping in the indexer.properties
+		for (Object objKey : config.getMapProperties().keySet()) {
+			// The key in the metadata object
+			String key = (String) objKey;
+			// The solr field name this metadata key will be mapped to
+			String fieldName = config.getMapProperties().getProperty(key);
+			List<String> values = metadata.getAllMetadata(key);
+			if (values != null) {
+				for (String value : values) {
+					// Add each metadata value into the
+					if (value != null && !config.getIgnoreValues().contains(value.trim())) {
+						LOG.fine("Adding field: " + fieldName + " value: " + value);
+						doc.addField(fieldName, value);
+					}
+				}
+			}
+		}
+		return doc;
+	}
+
+	/**
+	 * This method adds a single product extracted from a metadata file to the
+	 * Solr index.
+	 * 
+	 * @param file
+	 *          The file containing product metadata.
+	 * @param delete
+	 *          Flag indicating whether the entry should be deleted from the
+	 *          index.
+	 * @throws SolrServerException
+	 *           When an error occurs communicating with the Solr server instance.
+	 */
+	public void indexMetFile(File file, boolean delete)
+	    throws InstantiationException, FileNotFoundException, IOException,
+	    SolrServerException {
+		LOG.info("Attempting to index product from metadata file.");
+		try {
+			SerializableMetadata metadata = new SerializableMetadata("UTF-8", false);
+			metadata.loadMetadataFromXmlStream(new FileInputStream(file));
+			metadata.addMetadata("id", metadata.getMetadata("CAS."
+			    + CoreMetKeys.PRODUCT_ID));
+			metadata.addMetadata(config.getProperty(ACCESS_KEY), config
+			    .getProperty(ACCESS_URL)
+			    + metadata.getMetadata("CAS." + CoreMetKeys.PRODUCT_ID));
+			if (delete) {
+				server
+				    .deleteById(metadata.getMetadata("CAS." + CoreMetKeys.PRODUCT_ID));
+			}
+			server.add(this.getSolrDocument(metadata));
+			LOG.info("Indexed product: "
+			    + metadata.getMetadata("CAS." + CoreMetKeys.PRODUCT_ID));
+		} catch (InstantiationException e) {
+			LOG.severe("Could not instantiate metadata object: " + e.getMessage());
+		} catch (FileNotFoundException e) {
+			LOG.severe("Could not find metadata file: " + e.getMessage());
+		} catch (IOException e) {
+			LOG.severe("Could not delete product from index: " + e.getMessage());
+		}
+	}
+
+	/**
+	 * This method indexes all product types retrieved from the File Manager to
+	 * the Solr index.
+	 * 
+	 * @param delete
+	 *          Flag indicating whether each product type retrieved from the File
+	 *          Manager should be deleted from the index.
+	 * @throws SolrServerException
+	 *           When an error occurs communicating with the Solr server instance.
+	 */
+	public void indexProductTypes(boolean delete) {
+		LOG.info("Indexing product types...");
+		try {
+			XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(new URL(
+			    this.fmUrl));
+			LOG.info("Retrieving list of product types.");
+			List<ProductType> types = fmClient.getProductTypes();
+			for (ProductType type : types) {
+				if (!config.getIgnoreTypes().contains(type.getName().trim())) {
+					Metadata metadata = new Metadata();
+					metadata.addMetadata("id", type.getProductTypeId());
+					metadata.addMetadata("CAS.ProductTypeId", type.getProductTypeId());
+					metadata.addMetadata("CAS.ProductTypeDescription", type
+					    .getDescription());
+					metadata.addMetadata("CAS.ProductTypeRepositoryPath", type
+					    .getProductRepositoryPath());
+					metadata.addMetadata("CAS.ProductTypeVersioner", type.getVersioner());
+					metadata.addMetadata("CAS.ProductTypeName", type.getName());
+					metadata.addMetadata("ProductType", "ProductType");
+					metadata.replaceMetadata(type.getTypeMetadata());
+					if (delete) {
+						try {
+							server.deleteById(type.getProductTypeId());
+						} catch (Exception e) {
+							LOG.severe("Could not delete product type " + type.getName()
+							    + " from index: " + e.getMessage());
+						}
+					}
+					try {
+						performSubstitution(metadata);
+						server.add(this.getSolrDocument(metadata));
+						LOG.info("Indexed product type: " + type.getName());
+					} catch (Exception e) {
+						LOG.severe("Could not index " + type.getName() + ": "
+						    + e.getMessage());
+					}
+				} else {
+					LOG.info("Ignoring product type: " + type.getName());
+				}
+			}
+		} catch (MalformedURLException e) {
+			LOG.severe("File Manager URL is malformed: " + e.getMessage());
+		} catch (ConnectionException e) {
+			LOG.severe("Could not connect to File Manager: " + e.getMessage());
+		} catch (RepositoryManagerException e) {
+			LOG.severe("Could not retrieve product types from File Manager: "
+			    + e.getMessage());
+		}
+		LOG.info("Finished indexing product types.");
+	}
+	
+	/**
+	 * Suppresses exception that occurred with older file managers. 
+	 */
+	private ProductPage safeFirstPage(XmlRpcFileManagerClient fmClient, ProductType type) {
+		ProductPage page = null;
+		try {
+			page = fmClient.getFirstPage(type);
+		} catch (Exception e) {
+			LOG.info("No products found for: " + type.getName());
+		}
+		return page;
+	}
+
+	/**
+	 * This method indexes all products retrieved from the File Manager to the
+	 * Solr index. Metadata from the product's associated ProductType is also
+	 * included.
+	 * 
+	 * @param delete
+	 *          Flag indicating whether each product retrieved from the File
+	 *          Manager should be deleted from the index.
+	 * @throws SolrServerException
+	 *           When an error occurs communicating with the Solr server instance.
+	 */
+	public void indexAll(boolean delete) {
+		LOG.info("Indexing products...");
+		try {
+			XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(new URL(
+			    this.fmUrl));
+			LOG.info("Retrieving list of product types.");
+			List<ProductType> types = fmClient.getProductTypes();
+			for (ProductType type : types) {
+				if (!config.getIgnoreTypes().contains(type.getName().trim())) {
+					LOG.info("Paging through products for product type: "
+					    + type.getName());
+					for (ProductPage page = safeFirstPage(fmClient, type); page != null && !page
+					    .isLastPage(); page = fmClient.getNextPage(type, page)) {
+						for (Product product : page.getPageProducts()) {
+							try {
+								this.indexProduct(product.getProductId(), fmClient
+								    .getMetadata(product), type.getTypeMetadata());
+							} catch (Exception e) {
+								LOG.severe("Could not index " + product.getProductId() + ": "
+								    + e.getMessage());
+							}
+						}
+					}
+				}
+			}
+			LOG.info("Finished indexing products.");
+		} catch (MalformedURLException e) {
+			LOG.severe("File Manager URL is malformed: " + e.getMessage());
+		} catch (ConnectionException e) {
+			LOG.severe("Could not connect to File Manager: " + e.getMessage());
+		} catch (CatalogException e) {
+			LOG.severe("Could not retrieve products from File Manager: "
+			    + e.getMessage());
+		} catch (RepositoryManagerException e) {
+			LOG.severe("Could not retrieve product types from File Manager: "
+			    + e.getMessage());
+		}
+	}
+
+	/**
+	 * This method adds a single product retrieved from the File Manager by its
+	 * product identifier to the Solr index. Metadata from the ProductType is also
+	 * included.
+	 * 
+	 * @param productId
+	 *          The identifier of the product (CAS.ProductId).
+	 * @throws SolrServerException
+	 *           When an error occurs communicating with the Solr server instance.
+	 */
+	public void indexProduct(String productId)
+	    throws SolrServerException {
+		LOG.info("Attempting to index product: " + productId);
+		try {
+			XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(new URL(
+			    this.fmUrl));
+			Product product = fmClient.getProductById(productId);
+			Metadata productMetadata = fmClient.getMetadata(product);
+			indexProduct(product.getProductId(), productMetadata, product
+			    .getProductType().getTypeMetadata());
+		} catch (MalformedURLException e) {
+			LOG.severe("File Manager URL is malformed: " + e.getMessage());
+		} catch (ConnectionException e) {
+			LOG.severe("Could not connect to File Manager: " + e.getMessage());
+		} catch (CatalogException e) {
+			LOG.severe("Could not retrieve product from File Manager: "
+			    + e.getMessage());
+		} catch (java.text.ParseException e) {
+			LOG.severe("Could not format date: " + e.getMessage());
+		}
+	}
+	
+	/**
+	 * This method adds a single product retrieved from the File Manager by its
+	 * product name to the Solr index. Metadata from the ProductType is also
+	 * included.
+	 * 
+	 * @param productName
+	 *          The identifier of the product (CAS.ProductId).
+	 * @param delete
+	 *          Flag indicating whether the entry should be deleted from the
+	 *          index.
+	 * @throws SolrServerException
+	 *           When an error occurs communicating with the Solr server instance.
+	 */
+	public void indexProductByName(String productName, boolean delete) throws SolrServerException {
+		
+		LOG.info("Attempting to index product: " + productName);
+		try {
+
+			// Try to delete product by name
+			// Note: the standard field "CAS.ProductName" must be mapped to some Solr field in file indexer.properties
+			if (delete) {
+				try {
+					String productNameField = config.mapProperties.getProperty(PRODUCT_NAME);
+					if (StringUtils.hasText(productNameField)) {
+						server.deleteByQuery(productNameField+":"+productName);
+					} else {
+						LOG.warning("Metadata field "+PRODUCT_NAME+" is not mapped to any Solr field, cannot delete product by name");
+					}
+				} catch(Exception e) {
+					LOG.warning("Could not delete product: "+productName+" from Solr index");
+				}
+			}
+
+			XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(new URL(
+			    this.fmUrl));
+			Product product = fmClient.getProductByName(productName);
+			Metadata productMetadata = fmClient.getMetadata(product);
+			// NOTE: delete (by id) is now false
+			indexProduct(product.getProductId(), productMetadata, product.getProductType().getTypeMetadata());
+			
+		} catch (MalformedURLException e) {
+			LOG.severe("File Manager URL is malformed: " + e.getMessage());
+		} catch (ConnectionException e) {
+			LOG.severe("Could not connect to File Manager: " + e.getMessage());
+		} catch (CatalogException e) {
+			LOG.severe("Could not retrieve product from File Manager: "
+			    + e.getMessage());
+		} catch (java.text.ParseException e) {
+			LOG.severe("Could not format date: " + e.getMessage());
+		}
+	}
+
+	private void indexProduct(String productId, Metadata productMetadata,
+	    Metadata typeMetadata) throws SolrServerException,
+	    java.text.ParseException {
+		Metadata metadata = new Metadata();
+		metadata.addMetadata("id", productId);
+		// Add in product type metadata
+		if (typeMetadata != null) {
+			metadata.addMetadata(typeMetadata);
+		}
+		if (productMetadata != null) {
+			String accessKey = config.getProperty(ACCESS_KEY);
+			// Product metadata takes precedence
+			metadata.replaceMetadata(productMetadata);
+			// If there is an access url configured add it to the metadata
+			if (config.getProperty(ACCESS_URL) != null) {
+				metadata.addMetadata(accessKey, config.getProperty(ACCESS_URL));
+			}
+			// Replace values for metadata keys specified in config. This allows
+			// for metadata substitution. For instance, if a key named "product_url"
+			// has a value of
+			// http://localhost:8080/cas-product/data?productID=[CAS.ProductId]
+			// the value in brakets will be updated with the value from the
+			// CAS.ProductId.
+			performSubstitution(metadata);
+			try {
+				server.add(this.getSolrDocument(metadata));
+				LOG.info("Indexed product: " + productId);
+			} catch (IOException e) {
+				LOG.severe("Could not index product: " + productId);
+			}
+		} else {
+			LOG.info("Could not find metadata for product: " + productId);
+		}
+	}
+
+	/**
+	 * This method deletes a single product identified by a productID from the Solr index
+	 * 
+	 * @param productId
+	 * @throws IOException
+	 * @throws SolrServerException
+	 */
+	public void deleteProduct(String productId) throws IOException, SolrServerException {
+		LOG.info("Attempting to delete product: " + productId);
+		this.deleteProductFromIndex(productId);
+	}
+
+	/**
+	 * This method deletes a product(s) from the Solr index identified by a given name
+	 * 
+	 * @param productName
+	 * @throws IOException
+	 * @throws SolrServerException
+	 */
+	public void deleteProductByName(String productName) throws IOException, SolrServerException {
+		LOG.info("Attempting to delete product: " + productName);
+
+		try {
+			String productNameField = config.mapProperties.getProperty(PRODUCT_NAME);
+			if (StringUtils.hasText(productNameField)) {
+				server.deleteByQuery(productNameField+":"+productName);
+			} else {
+				LOG.warning("Metadata field "+PRODUCT_NAME+" is not mapped to any Solr field, cannot delete product by name");
+			}
+		} catch(Exception e) {
+			LOG.warning("Could not delete product: "+productName+" from Solr index");
+		}
+
+	}
+
+	private void deleteProductFromIndex(String productId) throws IOException, SolrServerException {
+		server.deleteById(productId);
+	}
+	
+	/**
+	 * Quick helper method to do substitution on the keys specified in the config
+	 * 
+	 * @param metadata
+	 *          to substitute on
+	 * @throws java.text.ParseException
+	 */
+	private void performSubstitution(Metadata metadata)
+	    throws java.text.ParseException {
+		// Do metadata replacement
+		for (String key : config.getReplacementKeys()) {
+			List<String> values = metadata.getAllMetadata(key);
+			if (values != null) {
+				List<String> newValues = new ArrayList<String>();
+				for (String value : values) {
+					newValues.add(PathUtils.replaceEnvVariables(value, metadata));
+				}
+				metadata.removeMetadata(key);
+				metadata.addMetadata(key, newValues);
+			}
+		}
+		// Format dates
+		for (Object key : config.getFormatProperties().keySet()) {
+			String keyString = (String) key;
+			if (metadata.containsKey(keyString)) {
+				List<String> values = metadata.getAllMetadata(keyString);
+				if (values != null) {
+					List<String> newValues = new ArrayList<String>();
+					SimpleDateFormat format = new SimpleDateFormat(config
+					    .getFormatProperties().getProperty(keyString).trim());
+					for (String value : values) {
+						newValues.add(formatDate(format, value));
+					}
+					metadata.removeMetadata(keyString);
+					metadata.addMetadata(keyString, newValues);
+				}
+			}
+		}
+	}
+
+	private String formatDate(SimpleDateFormat format, String value)
+	    throws java.text.ParseException {
+		// Ignore formating if its an ignore value
+		if (config.getIgnoreValues().contains(value.trim()))
+			return value;
+		return solrFormat.format(format.parse(value));
+	}
+
+	/**
+	 * This method builds the command-line options.
+	 * 
+	 * @return Returns the supported Options.
+	 */
+	@SuppressWarnings("static-access")
+	public static Options buildCommandLine() {
+		Options options = new Options();
+
+		options.addOption(new Option("h", "help", false, "Print this message"));
+		options.addOption(new Option("o", "optimize", false,
+		    "Optimize the Solr index"));
+		options.addOption(new Option("d", "delete", false,
+		    "Delete item before indexing"));
+		options.addOption(OptionBuilder.withArgName("Solr URL").hasArg()
+		    .withDescription("URL to the Solr instance").withLongOpt("solrUrl")
+		    .create("su"));
+		options.addOption(OptionBuilder.withArgName("Filemgr URL").hasArg()
+		    .withDescription("URL to the File Manager").withLongOpt("fmUrl")
+		    .create("fmu"));
+
+		OptionGroup group = new OptionGroup();
+		Option all = new Option("a", "all", false,
+		    "Index all products from the File Manager");
+		Option product = OptionBuilder.withArgName("productId").hasArg()
+		    .withDescription("Index the product from the File Manager")
+		    .withLongOpt("product").create("p");
+		Option met = OptionBuilder.withArgName("file").hasArg().withDescription(
+		    "Index the product from a metadata file").withLongOpt("metFile")
+		    .create("mf");
+		Option read = new Option("r", "read", false,
+		    "Index all products based on a list of product identifiers passed in");
+		Option types = new Option("t", "types", false,
+		    "Index all product types from the File Manager");
+		Option deleteAll = new Option("da", "deleteAll", false,
+		    "Delete all products/types from the Solr index");
+
+		group.addOption(all);
+		group.addOption(product);
+		group.addOption(met);
+		group.addOption(read);
+		group.addOption(types);
+		group.addOption(deleteAll);
+		options.addOptionGroup(group);
+
+		return options;
+	}
+
+	/**
+	 * The main method. Execution without argument displays help message.
+	 * 
+	 * @param args
+	 *          Command-line arguments.
+	 */
+	public static void main(String[] args) throws Exception {
+		Options options = SolrIndexer.buildCommandLine();
+		CommandLineParser parser = new GnuParser();
+		CommandLine line = null;
+
+		try {
+			line = parser.parse(options, args);
+		} catch (ParseException e) {
+			LOG.severe("Could not parse command line: " + e.getMessage());
+		}
+
+		if (line == null || line.hasOption("help") || line.getOptions().length == 0) {
+			HelpFormatter formatter = new HelpFormatter();
+			formatter.printHelp("java " + SolrIndexer.class.getName(), options);
+		} else if (line.hasOption("all") || line.hasOption("product")
+		    || line.hasOption("metFile") || line.hasOption("read")
+		    || line.hasOption("types") || line.hasOption("deleteAll")) {
+			SolrIndexer indexer = null;
+			String solrUrl = null;
+			String fmUrl = null;
+			if (line.hasOption("solrUrl")) {
+				solrUrl = line.getOptionValue("solrUrl");
+			}
+			if (line.hasOption("fmUrl")) {
+				fmUrl = line.getOptionValue("fmUrl");
+			}
+			try {
+				indexer = new SolrIndexer(solrUrl, fmUrl);
+				if (line.hasOption("all")) {
+					indexer.indexAll(line.hasOption("delete"));
+				} else if (line.hasOption("product")) {
+					indexer.indexProduct(line.getOptionValue("product"));
+				} else if (line.hasOption("metFile")) {
+					indexer.indexMetFile(new File(line.getOptionValue("metFile")), line
+					    .hasOption("delete"));
+				} else if (line.hasOption("read")) {
+					for (String productId : readProductIdsFromStdin()) {
+						indexer.indexProduct(productId);
+					}
+				} else if (line.hasOption("types")) {
+					indexer.indexProductTypes(line.hasOption("delete"));
+				} else if (line.hasOption("deleteAll")) {
+					indexer.delete();
+				} else {
+					LOG.severe("Option not supported.");
+				}
+				indexer.commit();
+				if (line.hasOption("optimize")) {
+					indexer.optimize();
+				}
+			} catch (Exception e) {
+				LOG.severe("An error occurred indexing: " + e.getMessage());
+				LOG
+				    .severe("If the above message is related to accessing the Solr instance, see the Application Server's log for additional information.");
+			}
+		}
+	}
+
+	/**
+	 * This method reads product identifiers from the standard input.
+	 * 
+	 * @return Returns a List of product identifiers.
+	 */
+	private static List<String> readProductIdsFromStdin() {
+		List<String> productIds = new ArrayList<String>();
+		BufferedReader br = null;
+
+		br = new BufferedReader(new InputStreamReader(System.in));
+		String line = null;
+
+		try {
+			while ((line = br.readLine()) != null) {
+				productIds.add(line);
+			}
+		} catch (IOException e) {
+			LOG.severe("Error reading product id: line: [" + line + "]: Message: "
+			    + e.getMessage());
+		} finally {
+			if (br != null) {
+				try {
+					br.close();
+				} catch (Exception ignore) {
+				}
+				br = null;
+			}
+		}
+		return productIds;
+	}
+
+	/**
+	 * This class manages the Indexer configuration.
+	 */
+	public class IndexerConfig {
+		private final static String PREFIX_CONFIG = "config.";
+		private final static String PREFIX_MET = "map.";
+		private final static String PREFIX_FORMAT = "format.";
+		private final static String IGNORE_TYPES = "ignore.types";
+		private final static String IGNORE_VALUES = "ignore.values";
+		private final static String REPLACEMENT_KEYS = "replacement.keys";
+		// Used to hold general properties for indexer configuration
+		private Properties properties = new Properties();
+		// Used to hold mappings for filemanager -> solr for keys
+		private Properties mapProperties = new Properties();
+		// Used to define the date format for a field
+		private Properties formatProperties = new Properties();
+		private List<String> ignoreTypes = new ArrayList<String>();
+		private List<String> ignoreValues = new ArrayList<String>();
+		private List<String> replacementKeys = new ArrayList<String>();
+
+		public IndexerConfig(InputStream inputStream) throws IOException {
+			Properties props = new Properties();
+			props.load(inputStream);
+			for (Object objKey : props.keySet()) {
+				String key = (String) objKey;
+				if (key.startsWith(PREFIX_CONFIG)) {
+					properties.put(key.substring(PREFIX_CONFIG.length()), props
+					    .getProperty(key));
+				} else if (key.startsWith(PREFIX_MET)) {
+					mapProperties.put(key.substring(PREFIX_MET.length()), props
+					    .getProperty(key));
+				} else if (key.startsWith(PREFIX_FORMAT)) {
+					formatProperties.put(key.substring(PREFIX_FORMAT.length()), props
+					    .getProperty(key));
+				}
+			}
+
+			if (properties.getProperty(IGNORE_TYPES) != null) {
+				String[] values = properties.getProperty(IGNORE_TYPES).trim()
+				    .split(",");
+				for (String value : values) {
+					ignoreTypes.add(value);
+				}
+			}
+
+			if (properties.getProperty(IGNORE_VALUES) != null) {
+				String[] values = properties.getProperty(IGNORE_VALUES).trim().split(
+				    ",");
+				for (String value : values) {
+					ignoreValues.add(value);
+				}
+			}
+
+			if (properties.getProperty(REPLACEMENT_KEYS) != null) {
+				String[] values = properties.getProperty(REPLACEMENT_KEYS).trim()
+				    .split(",");
+				for (String value : values) {
+					replacementKeys.add(value);
+				}
+			}
+		}
+
+		public String getProperty(String key) {
+			return properties.getProperty(key);
+		}
+
+		public String getProperty(String key, String defaultValue) {
+			return properties.getProperty(key, defaultValue);
+		}
+
+		public Properties getMapProperties() {
+			return mapProperties;
+		}
+
+		public Properties getFormatProperties() {
+			return formatProperties;
+		}
+
+		public List<String> getIgnoreTypes() {
+			return this.ignoreTypes;
+		}
+
+		public List<String> getIgnoreValues() {
+			return this.ignoreValues;
+		}
+
+		public List<String> getReplacementKeys() {
+			return this.replacementKeys;
+		}
+	}
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/DbStructFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/DbStructFactory.java
new file mode 100644
index 0000000..389fb9c
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/DbStructFactory.java
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.util;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JDK imports
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * @author mattmann
+ * @version $Revsion$
+ * 
+ * <p>
+ * Object creation utilities to create File Manager objects from SQL
+ * {@link ResultSet}s.
+ * </p>
+ * 
+ */
+public final class DbStructFactory {
+
+    public static ProductType getProductType(ResultSet rs) throws SQLException {
+        ProductType type = new ProductType();
+        type.setDescription(rs.getString("product_type_description"));
+        type.setName(rs.getString("product_type_name"));
+        type.setProductRepositoryPath(rs
+                .getString("product_type_repository_path"));
+        type.setProductTypeId(String.valueOf(rs.getInt("product_type_id")));
+        type.setVersioner(rs.getString("product_type_versioner_class"));
+
+        return type;
+    }
+
+    public static Product getProduct(ResultSet rs) throws SQLException {
+        return getProduct(rs, true, false);
+    }
+
+    public static Product getProduct(ResultSet rs, boolean getType, boolean productIdString)
+            throws SQLException {
+        Product product = new Product();
+        if (productIdString) {
+        	product.setProductId(rs.getString("product_id"));
+        } else {
+        	product.setProductId(String.valueOf(rs.getInt("product_id")));
+        }
+        product.setProductName(rs.getString("product_name"));
+        product.setProductStructure(rs.getString("product_structure"));
+        product.setTransferStatus(rs.getString("product_transfer_status"));
+        if (getType) {
+            product.setProductType(getProductType(rs));
+        } else {
+            // still grab the ID
+            ProductType type = new ProductType();
+            type.setProductTypeId(rs.getString("product_type_id"));
+            product.setProductType(type);
+        }
+
+        return product;
+    }
+
+    public static Reference getReference(ResultSet rs) throws SQLException {
+        Reference r = new Reference();
+        r.setOrigReference(rs.getString("product_orig_reference"));
+        r.setDataStoreReference(rs.getString("product_datastore_reference"));
+        r.setFileSize(rs.getLong("product_reference_filesize"));
+        r.setMimeType(rs.getString("product_reference_mimetype"));
+        return r;
+    }
+
+    public static Element getElement(ResultSet rs) throws SQLException {
+        Element element = new Element();
+        element.setElementId(String.valueOf(rs.getInt("element_id")));
+        element.setElementName(rs.getString("element_name"));
+        element.setDCElement(rs.getString("dc_element"));
+        element.setDescription(rs.getString("element_description"));
+        return element;
+
+    }
+
+    public static String getParent(ResultSet rs) throws SQLException {
+        String parent = rs.getString("parent_id");
+        return parent;
+    }
+    
+    public static Element toScienceDataElement(ResultSet rs) throws SQLException {
+      Element element = new Element();
+      element.setElementId(rs.getString("parameter_id"));
+      element.setElementName(rs.getString("shortName"));
+      element.setDescription(rs.getString("description"));
+      return element;
+    }
+
+    public static Product toScienceDataProduct(ResultSet rs) throws SQLException {
+      Product product = new Product();
+      product.setProductId(rs.getString("granule_id"));
+      product.setProductName(rs.getString("filename"));
+      product.setProductStructure(Product.STRUCTURE_FLAT);
+      product.setTransferStatus(Product.STATUS_RECEIVED);
+      ProductType type = new ProductType();
+      type.setProductTypeId(rs.getString("dataset_id"));
+      product.setProductType(type);
+      return product;
+    }
+
+    public static ProductType toScienceDataProductType(ResultSet rs) throws SQLException {
+      ProductType type = new ProductType();
+      type.setProductTypeId(rs.getString("dataset_id"));
+      type.setDescription(rs.getString("description"));
+      type.setName(rs.getString("shortName"));
+      type.setVersioner("gov.nasa.jpl.oodt.cas.filemgr.versioning.BasicVersioner"); // use
+                                                                                    // basic
+                                                                                    // versioner
+      type.setProductRepositoryPath("file:///tmp"); // not moving files anyways
+
+      Metadata typeMet = new Metadata();
+      typeMet.addMetadata("DatasetId", type.getProductTypeId());
+      typeMet.addMetadata("DatasetShortName",
+          type.getName() != null ? type.getName() : "");
+      typeMet.addMetadata("DatasetLongName",
+          rs.getString("longName") != null ? rs.getString("longName") : "");
+      typeMet.addMetadata("Description",
+          type.getDescription() != null ? type.getDescription() : "");
+      typeMet.addMetadata("Source",
+          rs.getString("source") != null ? rs.getString("source") : "");
+      typeMet.addMetadata("ReferenceURL",
+          rs.getString("referenceURL") != null ? rs.getString("referenceURL")
+              : "");
+      type.setTypeMetadata(typeMet);
+      return type;
+    }    
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/GenericFileManagerObjectFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/GenericFileManagerObjectFactory.java
new file mode 100644
index 0000000..57a4345
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/GenericFileManagerObjectFactory.java
@@ -0,0 +1,352 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.util;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+
+
+
+
+
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.datatransfer.DataTransfer;
+import org.apache.oodt.cas.filemgr.datatransfer.DataTransferFactory;
+import org.apache.oodt.cas.filemgr.ingest.Cache;
+import org.apache.oodt.cas.filemgr.ingest.CacheFactory;
+import org.apache.oodt.cas.filemgr.metadata.extractors.FilemgrMetExtractor;
+import org.apache.oodt.cas.filemgr.repository.RepositoryManager;
+import org.apache.oodt.cas.filemgr.repository.RepositoryManagerFactory;
+import org.apache.oodt.cas.filemgr.structs.query.conv.VersionConverter;
+import org.apache.oodt.cas.filemgr.structs.query.filter.FilterAlgor;
+import org.apache.oodt.cas.filemgr.structs.type.TypeHandler;
+import org.apache.oodt.cas.filemgr.catalog.Catalog;
+import org.apache.oodt.cas.filemgr.catalog.CatalogFactory;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayerFactory;
+import org.apache.oodt.cas.filemgr.versioning.Versioner;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Generic object creation utilities for FileManager objects from their
+ * interface class names.
+ * </p>
+ * 
+ */
+public final class GenericFileManagerObjectFactory {
+
+    /* our log stream */
+    private static final Logger LOG = Logger
+            .getLogger(GenericFileManagerObjectFactory.class.getName());
+
+    private GenericFileManagerObjectFactory() throws InstantiationException {
+        throw new InstantiationException(
+                "Don't construct final factory classes!");
+    }
+    
+    /**
+     * <p>
+     * Constructs a new {@link DataTransfer} from the specified
+     * <code>serviceFactory</code>.
+     * </p>
+     * 
+     * @param serviceFactory
+     *            The Service Factory class name that will be instantiated to
+     *            provide DataTransfer objects.
+     * @return A newly instantiated {@link DataTransfer} object.
+     */
+    @SuppressWarnings("unchecked")
+    public static DataTransfer getDataTransferServiceFromFactory(
+            String serviceFactory) {
+        DataTransferFactory dataTransferFactory = null;
+        Class<DataTransferFactory> dataTransferFactoryClass = null;
+
+        try {
+            dataTransferFactoryClass = (Class<DataTransferFactory>) Class.forName(serviceFactory);
+            dataTransferFactory = dataTransferFactoryClass.newInstance();
+            return dataTransferFactory.createDataTransfer();
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "ClassNotFoundException when loading data transfer factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        } catch (InstantiationException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "InstantiationException when loading data transfer factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "IllegalAccessException when loading data transfer factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        }
+
+        return null;
+    }
+
+    /**
+     * <p>
+     * Constructs a new {@link RepositoryManager} from the specified
+     * <code>serviceFactory</code>.
+     * </p>
+     * 
+     * @param serviceFactory
+     *            The class name of the service factory used to create new
+     *            RepositoryManager objects.
+     * @return A newly constructed {@link RepositoryManager} object.
+     */
+    @SuppressWarnings("unchecked")
+    public static RepositoryManager getRepositoryManagerServiceFromFactory(
+            String serviceFactory) {
+        RepositoryManagerFactory factory = null;
+        Class<RepositoryManagerFactory> clazz = null;
+
+        try {
+            clazz = (Class<RepositoryManagerFactory>) Class.forName(serviceFactory);
+            factory = clazz.newInstance();
+            return factory.createRepositoryManager();
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "ClassNotFoundException when loading data store factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        } catch (InstantiationException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "InstantiationException when loading data store factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "IllegalAccessException when loading data store factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        }
+
+        return null;
+    }
+
+    /**
+     * <p>
+     * Constructs a new {@link Catalog} from the specified
+     * <code>serviceFactory</code>.
+     * </p>
+     * 
+     * @param serviceFactory
+     *            The class name of the service factory used to create new
+     *            Catalog objects.
+     * @return A newly constructed {@link Catalog} object.
+     */
+    @SuppressWarnings("unchecked")
+    public static Catalog getCatalogServiceFromFactory(String serviceFactory) {
+        CatalogFactory factory = null;
+        Class<CatalogFactory> clazz = null;
+
+        try {
+            clazz = (Class<CatalogFactory>) Class.forName(serviceFactory);
+            factory = clazz.newInstance();
+            return factory.createCatalog();
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "ClassNotFoundException when loading metadata store factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        } catch (InstantiationException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "InstantiationException when loading metadata store factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "IllegalAccessException when loading metadata store factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        }
+
+        return null;
+    }
+
+    /**
+     * <p>
+     * Creates a {@link ValidationLayer} from the specified
+     * <code>serviceFactory</code>.
+     * </p>
+     * 
+     * @param serviceFactory
+     *            The classname of the ValidationLayerFactory to use to create
+     *            the ValidationLayer.
+     * @return A new {@link ValidationLayer}, created from the specified
+     *         ValidationLayerFactory.
+     */
+    @SuppressWarnings("unchecked")
+    public static ValidationLayer getValidationLayerFromFactory(
+            String serviceFactory) {
+        ValidationLayerFactory factory = null;
+        Class<ValidationLayerFactory> clazz = null;
+
+        try {
+            clazz = (Class<ValidationLayerFactory>) Class.forName(serviceFactory);
+            factory = clazz.newInstance();
+            return factory.createValidationLayer();
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "ClassNotFoundException when loading validation layer factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        } catch (InstantiationException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "InstantiationException when loading validation layer factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "IllegalAccessException when loading validation layer factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        }
+
+        return null;
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static Cache getCacheFromFactory(String serviceFactory){
+        CacheFactory factory = null;
+        Class<CacheFactory> clazz = null;
+
+        try {
+            clazz = (Class<CacheFactory>) Class.forName(serviceFactory);
+            factory = clazz.newInstance();
+            return factory.createCache();
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "ClassNotFoundException when loading cache factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        } catch (InstantiationException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "InstantiationException when loading cache factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "IllegalAccessException when loading cache factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        }
+
+        return null;        
+    }
+
+    /**
+     * <p>
+     * Constructs a new {@link Versioner} from the specified
+     * <code>className</code>.
+     * </p>
+     * 
+     * @param className
+     *            The class name of the Versioner object to create.
+     * @return A newly constructed {@link Versioner} object.
+     */
+    public static Versioner getVersionerFromClassName(String className) {
+        try {
+            @SuppressWarnings("unchecked")
+            Class<Versioner> versionerClass = (Class<Versioner>) Class.forName(className);
+            return versionerClass.newInstance();
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "ClassNotFoundException when loading versioner class "
+                            + className + " Message: " + e.getMessage());
+        } catch (InstantiationException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "InstantiationException when loading versioner class "
+                            + className + " Message: " + e.getMessage());
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "IllegalAccessException when loading versioner class "
+                            + className + " Message: " + e.getMessage());
+        }
+
+        return null;
+    }
+
+    public static FilemgrMetExtractor getExtractorFromClassName(String className) {
+        try {
+            @SuppressWarnings("unchecked")
+            Class<FilemgrMetExtractor> extractorClass = (Class<FilemgrMetExtractor>) Class.forName(className);
+            return extractorClass.newInstance();
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "ClassNotFoundException when loading extractor class "
+                            + className + " Message: " + e.getMessage());
+        } catch (InstantiationException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "InstantiationException when loading extractor class "
+                            + className + " Message: " + e.getMessage());
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "IllegalAccessException when loading extractor class "
+                            + className + " Message: " + e.getMessage());
+        }
+        return null;
+    }
+    
+    public static TypeHandler getTypeHandlerFromClassName(String className) {
+        try {
+            return (TypeHandler) Class.forName(className).newInstance();
+        }catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Failed to load TypeHandler class '" + className + "' : " + e.getMessage());
+        }
+        return null;
+    }
+    
+    public static FilterAlgor getFilterAlgorFromClassName(String className) {
+        try {
+            return (FilterAlgor) Class.forName(className).newInstance();
+        }catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Failed to load TypeHandler class '" + className + "' : " + e.getMessage());
+        }
+        return null;
+    }
+    
+    public static VersionConverter getVersionConverterFromClassName(String className) {
+        try {
+            return (VersionConverter) Class.forName(className).newInstance();
+        }catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Failed to load TypeHandler class '" + className + "' : " + e.getMessage());
+        }
+        return null;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/Pagination.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/Pagination.java
new file mode 100644
index 0000000..6a95829
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/Pagination.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.util;
+
+//CAS imports
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.Product; //for javadoc
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+
+//JDK imports
+import java.util.List; //for javadoc
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An interface for pagination of {@link Product} {@link List}s..
+ * </p>
+ * 
+ */
+public interface Pagination {
+
+    /**
+     * @param type
+     *            The ProductType to obtain the first {@link ProductPage} for.
+     * @return The first page of products for a particular {@link ProductType}.
+     */
+    public ProductPage getFirstPage(ProductType type);
+
+    /**
+     * 
+     * @param type
+     *            The ProductType to obtain the last {@link ProductPage} for.
+     * @return The last page of products for a particular {@link ProductType}.
+     */
+    public ProductPage getLastProductPage(ProductType type);
+
+    /**
+     * 
+     * @param type
+     *            The ProductType to obtain the next page for, given the
+     *            <code>currentPage</code>.
+     * @param currentPage
+     *            The current page that tells the function what the next page to
+     *            obtain is.
+     * @return The next page in the ProductType product list, given the
+     *         currentPage.
+     */
+    public ProductPage getNextPage(ProductType type, ProductPage currentPage);
+
+    /**
+     * 
+     * @param type
+     *            The ProductType to obtain the previous page for, given the
+     *            <code>currentPage</code>.
+     * @param currentPage
+     *            The currentPage that tells the function what the previous page
+     *            to obtain is.
+     * @return The previous page in the ProductType product list, given the
+     *         currentPage.
+     */
+    public ProductPage getPrevPage(ProductType type, ProductPage currentPage);
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/QueryUtils.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/QueryUtils.java
new file mode 100644
index 0000000..f5ee4a9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/QueryUtils.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.util;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.query.QueryResult;
+
+//JDK imports
+import java.util.List;
+
+
+/**
+ * @author bfoster
+ * @version $Revsion$
+ * 
+ * <p>
+ * Utility Class
+ * </p>
+ * 
+ */
+public class QueryUtils {
+
+    public static String getQueryResultsAsString(List<QueryResult> queryResults) {
+        return getQueryResultsAsString(queryResults, ",");
+    }
+    
+    public static String getQueryResultsAsString(
+            List<QueryResult> queryResults, String delimiter) {
+        StringBuffer returnString = new StringBuffer("");
+        for (QueryResult qr : queryResults) 
+            returnString.append(qr.toString() + delimiter);
+        return returnString.substring(0, returnString.length() - delimiter.length());
+    }
+    
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/SqlParser.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/SqlParser.java
new file mode 100644
index 0000000..25ebc40
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/SqlParser.java
@@ -0,0 +1,462 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.util;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.BooleanQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.QueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.QueryFormulationException;
+import org.apache.oodt.cas.filemgr.structs.query.ComplexQuery;
+import org.apache.oodt.cas.filemgr.structs.query.QueryFilter;
+import org.apache.oodt.cas.filemgr.structs.query.filter.FilterAlgor;
+
+
+//JDK imports
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ *          <p>
+ *          A fairly robust SQL parser, based on the Shunting yard
+ *          algorithm
+ *          </p>
+ *          
+ *          <p>
+ *          Evaluates SQL like string statements contained in a string. The SQL
+ *          statement should be enclosed within: SQL ({@literal <sql_arguments>}
+ *          ) { {@literal <sql_statement>} . the {@literal <sql_arguments>} can
+ *          be either FORMAT, SORT_BY, or FILTER. Syntax: SQL (FORMAT='<metadata
+ *          formated output>',SORT_BY='<metadata name>', FILTER='<start_time
+ *          metadata element>, <end_time metadata element>, <priority metadata
+ *          element>, <filter type>') { SELECT
+ *          <list-of-comma-segregated-metadata-elements-to-query-on> FROM
+ *          <productTypes-comma-segregated> WHERE <metadata-boolean-expressions>
+ *          } Here is an example SQL statement: SQL (FORMAT='FileLocation/Filename',
+ *          SORT_BY='FileSize',FILTER=<StartDateTime,EndDateTime,DataVersion,
+ *          TakeHighestPriority) { SELECT FileLocation,Filename,FileSize FROM IASI_L1C 
+ *          WHERE ProductionDateTime >= '2007-12-01T00:00:00.000000Z' } This example
+ *          would query the cas-filemgr for metadata values:
+ *          FileLocation,Filename,FileSize for any data file where the
+ *          ProductType == IASI_L1C and the ProductionDateTime >=
+ *          2007-12-01T00:00:00.000000Z. It would then combine the return data
+ *          files metadata via the specified FORMAT. Each data file's metadata
+ *          will be formated to a string representation of (with the actual
+ *          values replaced in the location of the metadata keys):
+ *          FileLocation/Filename. They will be concatenated together, in
+ *          FileSize order.
+ *          </p>
+ */
+public class SqlParser {
+    
+    private SqlParser() {
+    }
+    
+    public static ComplexQuery parseSqlQueryMethod(String sqlStringQueryMethod)
+            throws QueryFormulationException {
+        if (!Pattern.matches("((?:SQL)|(?:sql))\\s*(.*)\\s*\\{\\s*SELECT.*FROM.*(?:WHERE.*){0,1}\\}", sqlStringQueryMethod))
+            throw new QueryFormulationException("Malformed SQL method");
+        
+        try {
+            ComplexQuery complexQuery = parseSqlQuery(stripOutSqlDefinition(sqlStringQueryMethod));
+            
+            for (Expression expr : getSqlStatementArgs(sqlStringQueryMethod)) {
+                if (expr.getKey().toUpperCase().equals("FORMAT"))
+                    complexQuery.setToStringResultFormat(expr.getValue());
+                else if (expr.getKey().toUpperCase().equals("SORT_BY"))
+                    complexQuery.setSortByMetKey(expr.getValue());
+                else if (expr.getKey().toUpperCase().equals("FILTER")) 
+                    complexQuery.setQueryFilter(createFilter(expr));
+            }
+            
+            return complexQuery;
+        }catch (Exception e) {
+            e.printStackTrace();
+            throw new QueryFormulationException("Failed to parse SQL method : " + e.getMessage());
+        }
+    }
+    
+    public static ComplexQuery parseSqlQuery(String sqlStringQuery)
+            throws QueryFormulationException {
+        String[] splitSqlStatement = sqlStringQuery
+                .split("((?:SELECT)|(?:FROM)|(?:WHERE))");
+        String[] selectValues = (splitSqlStatement[1].trim() + ",").split(",");
+        String[] fromValues = (splitSqlStatement[2].trim() + ",").split(",");
+        ComplexQuery sq = new ComplexQuery();
+        List<String> selectValuesList = Arrays.asList(selectValues);
+        if (!selectValuesList.contains("*"))
+            sq.setReducedMetadata(Arrays.asList(selectValues));
+        List<String> fromValuesList = Arrays.asList(fromValues);
+        if (!fromValuesList.contains("*"))
+            sq.setReducedProductTypeNames(fromValuesList);
+        
+        if (splitSqlStatement.length > 3)
+            sq.addCriterion(parseStatement(toPostFix(splitSqlStatement[3]
+                    .trim())));
+        return sq;
+    }
+    
+    public static QueryCriteria parseSqlWhereClause(String sqlWhereClause) 
+            throws QueryFormulationException {
+        return parseStatement(toPostFix(sqlWhereClause.trim()));
+    }
+    
+    public static String unparseSqlQuery(ComplexQuery complexQuery) throws QueryFormulationException {
+        LinkedList<String> outputArgs = new LinkedList<String>();
+        if (complexQuery.getToStringResultFormat() != null)
+            outputArgs.add("FORMAT = '" + complexQuery.getToStringResultFormat() + "'");
+        if (complexQuery.getSortByMetKey() != null)
+            outputArgs.add("SORT_BY = '" + complexQuery.getSortByMetKey() + "'");
+        if (complexQuery.getQueryFilter() != null) {
+            String filterString = "FILTER = '"
+                    + complexQuery.getQueryFilter().getStartDateTimeMetKey() + ","
+                    + complexQuery.getQueryFilter().getEndDateTimeMetKey() + ","
+                    + complexQuery.getQueryFilter().getPriorityMetKey() + ","
+                    + complexQuery.getQueryFilter().getFilterAlgor().getClass().getCanonicalName() + ","
+                    + complexQuery.getQueryFilter().getFilterAlgor().getEpsilon();
+            outputArgs.add(filterString + "'");
+        }
+        String sqlQueryString = getInfixCriteriaString(complexQuery.getCriteria());
+        if (sqlQueryString != null && sqlQueryString.startsWith("(") && sqlQueryString.endsWith(")"))
+                sqlQueryString = sqlQueryString.substring(1, sqlQueryString.length() - 1);
+        return "SQL ("
+                + listToString(outputArgs)
+                + ") { SELECT " + listToString(complexQuery.getReducedMetadata())
+                + " FROM " + (complexQuery.getReducedProductTypeNames() != null ? listToString(complexQuery.getReducedProductTypeNames()) : "*")
+                + (sqlQueryString != null ? " WHERE " + sqlQueryString : "") + " }";
+    }
+
+    public static String getInfixCriteriaString(List<QueryCriteria> criteriaList) throws QueryFormulationException {
+        if (criteriaList.size() > 1)
+            return getInfixCriteriaString(new BooleanQueryCriteria(criteriaList, BooleanQueryCriteria.AND));
+        else if (criteriaList.size() == 1)
+            return getInfixCriteriaString(criteriaList.get(0));
+        else 
+            return null;
+    }
+    
+    public static String getInfixCriteriaString(QueryCriteria criteria) {
+        String returnString = "";
+        if (criteria instanceof BooleanQueryCriteria) {
+            BooleanQueryCriteria bqc = (BooleanQueryCriteria) criteria;
+            List<QueryCriteria> terms = bqc.getTerms();
+            switch(bqc.getOperator()){
+            case 0:
+                returnString = "(" + getInfixCriteriaString((QueryCriteria) terms.get(0));
+                for (int i = 1; i < terms.size(); i++)
+                    returnString += " AND " + getInfixCriteriaString((QueryCriteria) terms.get(i));
+                returnString += ")";
+                break;
+            case 1:
+                returnString = "(" + getInfixCriteriaString((QueryCriteria) terms.get(0));
+                for (int i = 1; i < terms.size(); i++)
+                    returnString += " OR " + getInfixCriteriaString((QueryCriteria) terms.get(i));
+                returnString += ")";
+                break;
+            case 2:
+                QueryCriteria qc = bqc.getTerms().get(0);
+                if (qc instanceof TermQueryCriteria) {
+                    TermQueryCriteria tqc = (TermQueryCriteria) qc;
+                    returnString = tqc.getElementName() + " != '" + tqc.getValue() + "'";
+                }else {
+                    returnString = "NOT(" + getInfixCriteriaString(qc) + ")";
+                }
+                break;
+            }
+        }else if (criteria instanceof RangeQueryCriteria) {
+            RangeQueryCriteria rqc = (RangeQueryCriteria) criteria;
+            String opString = rqc.getInclusive() ? "=" : "";
+            if (rqc.getStartValue() != null) {
+                opString = ">" + opString + " '" + rqc.getStartValue() + "'";
+            }else
+                opString = "<" + opString + " '" + rqc.getEndValue() + "'";
+            returnString = rqc.getElementName() + " " + opString;
+        }else if (criteria instanceof TermQueryCriteria) {
+            TermQueryCriteria tqc = (TermQueryCriteria) criteria;
+            returnString = tqc.getElementName() + " == '" + tqc.getValue() + "'";
+        }
+        return returnString;
+    }
+    
+    private static String stripOutSqlDefinition(String sqlStringQueryMethod) {
+        return sqlStringQueryMethod.trim().replaceAll("((?:SQL)|(?:sql))\\s*(.*)\\s*\\{", "").replaceAll("}$", "").trim();
+    }
+    
+    private static List<Expression> getSqlStatementArgs(String sqlStringQueryMethod) throws QueryFormulationException {
+        boolean inExpr = false;
+        int startArgs = 0;
+        for (int i = 0; i < sqlStringQueryMethod.length(); i++) {
+            char curChar = sqlStringQueryMethod.charAt(i);
+            switch (curChar) {
+            case '(':
+                startArgs = i + 1;
+                break;
+            case ')':
+                if (!inExpr) {
+                    String[] args = sqlStringQueryMethod.substring(startArgs, i).trim().split("'\\s*,");
+                    LinkedList<Expression> argsList = new LinkedList<Expression>();
+                    for (String arg : args)
+                        argsList.add(new Expression((arg = arg.trim()).endsWith("'") ? arg : (arg + "'")));
+                    return argsList;
+                } else {
+                    break;
+                }
+            case '\'':
+                inExpr = !inExpr;
+                break;
+            }
+        }
+        throw new QueryFormulationException("Failed to read in args");
+    }
+    
+    private static QueryFilter createFilter(Expression expr) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+        String[] filterArgs = expr.getValue().split(",");
+        FilterAlgor filterAlgor = (FilterAlgor) Class.forName(filterArgs[3]).newInstance();
+        QueryFilter qf = new QueryFilter(filterArgs[0], filterArgs[1], filterArgs[2], filterAlgor);
+        filterAlgor.setEpsilon(Integer.parseInt(filterArgs[4]));
+        return qf;
+    }
+
+    /**
+     * Uses "Shunting yard algorithm" (see:
+     * http://en.wikipedia.org/wiki/Shunting_yard_algorithm)
+     */
+    private static LinkedList<String> toPostFix(String statement) {
+        LinkedList<String> postFix = new LinkedList<String>();
+        Stack<String> stack = new Stack<String>();
+
+        for (int i = 0; i < statement.length(); i++) {
+            char curChar = statement.charAt(i);
+            switch (curChar) {
+            case '(':
+                stack.push(new String("("));
+                break;
+            case ')':
+                String value = null;
+                while (!(value = stack.pop()).equals("("))
+                    postFix.add(value);
+                if (stack.peek().equals("NOT"))
+                    postFix.add(stack.pop());
+                break;
+            case ' ':
+                break;
+            default:
+                if (statement.substring(i, i + 3).equals("AND")) {
+                    while (!stack.isEmpty()
+                            && (stack.peek().equals("AND")))
+                        postFix.add(stack.pop());
+                    stack.push("AND");
+                    i += 2;
+                } else if (statement.substring(i, i + 2).equals("OR")) {
+                    while (!stack.isEmpty()
+                            && (stack.peek().equals("AND") || stack.peek()
+                                    .equals("OR")))
+                        postFix.add(stack.pop());
+                    stack.push("OR");
+                    i += 1;
+                } else if (statement.substring(i, i + 3).equals("NOT")) {
+                    stack.push("NOT");
+                    i += 2;
+                } else {
+                    int endIndex = statement.indexOf('\'', statement.indexOf(
+                            '\'', i) + 1) + 1;
+                    postFix.add(statement.substring(i, endIndex));
+                    i = endIndex - 1;
+                }
+            }
+        }
+
+        while (!stack.isEmpty())
+            postFix.add(stack.pop());
+
+        return postFix;
+    }
+
+    private static QueryCriteria parseStatement(LinkedList<String> postFixStatement)
+            throws QueryFormulationException {
+        Stack<QueryCriteria> stack = new Stack<QueryCriteria>();
+        for (String item : postFixStatement) {
+            if (item.equals("AND")) {
+                BooleanQueryCriteria bQC = new BooleanQueryCriteria();
+                bQC.addTerm(stack.pop());
+                bQC.addTerm(stack.pop());
+                stack.push(bQC);
+            } else if (item.equals("OR")) {
+                BooleanQueryCriteria bQC = new BooleanQueryCriteria();
+                bQC.setOperator(BooleanQueryCriteria.OR);
+                bQC.addTerm(stack.pop());
+                bQC.addTerm(stack.pop());
+                stack.push(bQC);
+            } else if (item.equals("NOT")) {
+                BooleanQueryCriteria bQC = new BooleanQueryCriteria();
+                bQC.setOperator(BooleanQueryCriteria.NOT);
+                bQC.addTerm(stack.pop());
+                stack.push(bQC);
+            } else {
+                stack.push(new Expression(item).convertToQueryCriteria());
+            }
+        }
+        return stack.pop();
+    }
+
+    private static String listToString(List<String> list) {
+        String arrayString = "";
+        if (list.size() > 0) {
+            arrayString = list.get(0);
+            for (int i = 1; i < list.size(); i++)
+                arrayString += "," + list.get(i);
+        }  
+        return arrayString;
+    }
+
+
+    private static class Expression {
+
+        public static final short GREATER_THAN = 12;
+
+        public static final short LESS_THAN = 3;
+
+        public static final short EQUAL_TO = 9;
+
+        public static final short NOT_EQUAL_TO = 15;
+
+        public static final short GREATER_THAN_OR_EQUAL_TO = 13;
+
+        public static final short LESS_THAN_OR_EQUAL_TO = 11;
+
+        public static final short NOT = 6;
+
+        private String[] stringValues = new String[] { "`", "`", "`", "<", "`",
+                "`", "!", "`", "`", "=", "`", "<=", ">", ">=", "`", "!=" };
+
+        private String expression;
+
+        private String key;
+
+        private String val;
+
+        private int op;
+
+        public Expression(String expression) {
+            this.parseExpression(this.expression = expression);
+        }
+
+        public Expression(String key, int op, String val) {
+            this.key = key.trim();
+            this.op = op;
+            this.val = this.removeTickBounds(val.trim());
+        }
+
+        private void parseExpression(String expression) {
+            Matcher matcher = Pattern.compile("((?:>=)|(?:<=)|(?:==)|(?:!=)|(?:=)|(?:>)|(?:<))").matcher(expression);
+            matcher.find();
+            this.key = expression.substring(0, matcher.start()).trim();
+            this.val = this.removeTickBounds(expression.substring(matcher.end()).trim());
+            String opString = matcher.group();
+            for (char c : opString.toCharArray())
+                this.op = this.op | this.getShortValueForOp(c);
+        }
+
+        private String removeTickBounds(String value) {
+            if (value.startsWith("'") && value.endsWith("'"))
+                value = value.substring(1, value.length() - 1);
+            return value;
+        }
+
+        private int getShortValueForOp(char op) {
+            switch (op) {
+            case '>':
+                return GREATER_THAN;
+            case '<':
+                return LESS_THAN;
+            case '=':
+                return EQUAL_TO;
+            case '!':
+                return NOT;
+            default:
+                return 0;
+            }
+        }
+
+        public QueryCriteria convertToQueryCriteria()
+                throws QueryFormulationException {
+            switch (this.op) {
+            case GREATER_THAN:
+                return new RangeQueryCriteria(this.key, this.val, null, false);
+            case LESS_THAN:
+                return new RangeQueryCriteria(this.key, null, this.val, false);
+            case EQUAL_TO:
+                return new TermQueryCriteria(this.key, this.val);
+            case NOT_EQUAL_TO:
+                BooleanQueryCriteria notEqBQC = new BooleanQueryCriteria();
+                notEqBQC.setOperator(BooleanQueryCriteria.NOT);
+                notEqBQC.addTerm(new TermQueryCriteria(this.key, this.val));
+                return notEqBQC;
+            case GREATER_THAN_OR_EQUAL_TO:
+                return new RangeQueryCriteria(this.key, this.val, null, true);
+            case LESS_THAN_OR_EQUAL_TO:
+                return new RangeQueryCriteria(this.key, null, this.val, true);
+            }
+            throw new QueryFormulationException(
+                    "Was not able to form query . . . probably an invalid operator -- "
+                            + this.toString());
+        }
+
+        public String getKey() {
+            return this.key;
+        }
+
+        public String getValue() {
+            return this.val;
+        }
+
+        public int getOp() {
+            return this.op;
+        }
+
+        public String getExpression() {
+            return this.expression;
+        }
+
+        public String toString() {
+            return this.key + " " + this.stringValues[this.op] + " " + this.val;
+        }
+
+    }
+    
+    public static void main(String[] args) throws QueryFormulationException {
+        String query = "SELECT * FROM IASI_L1C WHERE one == '1' AND two == '2' OR NOT(five == '5') OR three == '3' AND four == '4'";
+        System.out.println("query: " + query);
+        System.out.println("query after : " + unparseSqlQuery(parseSqlQuery(query)));
+        query = "SELECT * FROM IASI_L1C";
+        System.out.println("query: " + query);
+        System.out.println("query after : " + unparseSqlQuery(parseSqlQuery(query)));
+        query = "SELECT * FROM *";
+        System.out.println("query: " + query);
+        System.out.println("query after : " + unparseSqlQuery(parseSqlQuery(query)));
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/XmlRpcStructFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/XmlRpcStructFactory.java
new file mode 100644
index 0000000..3becd30
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/XmlRpcStructFactory.java
@@ -0,0 +1,721 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.util;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.BooleanQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.ExtractorSpec;
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.QueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.QueryFormulationException;
+import org.apache.oodt.cas.filemgr.structs.query.ComplexQuery;
+import org.apache.oodt.cas.filemgr.structs.query.QueryFilter;
+import org.apache.oodt.cas.filemgr.structs.query.QueryResult;
+import org.apache.oodt.cas.filemgr.structs.query.filter.FilterAlgor;
+import org.apache.oodt.cas.filemgr.structs.type.TypeHandler;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JDK imports
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.List;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A factory class for creating File Manager structures suitable for transfer
+ * over the XML-RPC pipe, and for reading objects from the XML-RPC pipe into
+ * File Manager structs.
+ * </p>
+ * 
+ */
+public final class XmlRpcStructFactory {
+
+    private XmlRpcStructFactory() throws InstantiationException {
+        throw new InstantiationException(
+                "Don't instantiate XmlRpcStructFactories!");
+    }
+
+    public static Hashtable<String, Object> getXmlRpcFileTransferStatus(
+            FileTransferStatus status) {
+        Hashtable<String, Object> statusHash = new Hashtable<String, Object>();
+        statusHash.put("bytesTransferred",Long.toString(status
+                .getBytesTransferred()));
+        statusHash.put("parentProduct", getXmlRpcProduct(status
+                .getParentProduct()));
+        statusHash.put("fileRef", getXmlRpcReference(status.getFileRef()));
+        return statusHash;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static FileTransferStatus getFileTransferStatusFromXmlRpc(
+            Hashtable<String, Object> statusHash) {
+        FileTransferStatus status = new FileTransferStatus();
+        status.setBytesTransferred(Long.parseLong(statusHash
+                .get("bytesTransferred").toString()));
+        status.setParentProduct(getProductFromXmlRpc((Hashtable<String, Object>) statusHash.get("parentProduct")));
+        status.setFileRef(getReferenceFromXmlRpc((Hashtable<String, Object>) statusHash.get("fileRef")));
+        return status;
+    }
+
+    public static Vector<Hashtable<String, Object>> getXmlRpcFileTransferStatuses(List<FileTransferStatus> statuses) {
+        Vector<Hashtable<String, Object>> statusVector = new Vector<Hashtable<String, Object>>();
+
+        if (statuses != null && statuses.size() > 0) {
+
+            for (Iterator<FileTransferStatus> i = statuses.iterator(); i.hasNext();) {
+                FileTransferStatus status = i.next();
+                statusVector.add(getXmlRpcFileTransferStatus(status));
+            }
+        }
+
+        return statusVector;
+    }
+
+    public static List<FileTransferStatus> getFileTransferStatusesFromXmlRpc(Vector<Hashtable<String, Object>> statusVector) {
+        List<FileTransferStatus> statuses = new Vector<FileTransferStatus>();
+
+        if (statusVector != null && statusVector.size() > 0) {
+            for (Iterator<Hashtable<String, Object>> i = statusVector.iterator(); i.hasNext();) {
+                Hashtable<String, Object> statusHash = i.next();
+                FileTransferStatus status = getFileTransferStatusFromXmlRpc(statusHash);
+                statuses.add(status);
+            }
+        }
+
+        return statuses;
+    }
+
+    public static Hashtable<String, Object> getXmlRpcProductPage(ProductPage page) {
+        Hashtable<String, Object>productPageHash = new Hashtable<String, Object>();
+        productPageHash.put("totalPages", new Integer(page.getTotalPages()));
+        productPageHash.put("pageNum", new Integer(page.getPageNum()));
+        productPageHash.put("pageSize", new Integer(page.getPageSize()));
+        productPageHash.put("pageProducts", getXmlRpcProductList(page
+                .getPageProducts()));
+        return productPageHash;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static ProductPage getProductPageFromXmlRpc(Hashtable<String, Object> productPageHash) {
+        ProductPage page = new ProductPage();
+        page.setPageNum(((Integer) productPageHash.get("pageNum")).intValue());
+        page
+                .setPageSize(((Integer) productPageHash.get("pageSize"))
+                        .intValue());
+        page.setTotalPages(((Integer) productPageHash.get("totalPages"))
+                .intValue());
+        page.setPageProducts(getProductListFromXmlRpc((Vector<Hashtable<String, Object>>) productPageHash
+                .get("pageProducts")));
+        return page;
+    }
+    
+    public static Hashtable<String, Object> getXmlRpcComplexQuery(ComplexQuery complexQuery) {
+        Hashtable<String, Object> complexQueryHash = getXmlRpcQuery(complexQuery);
+        if (complexQuery.getReducedProductTypeNames() != null)
+            complexQueryHash.put("reducedProductTypeNames", new Vector<String>(complexQuery.getReducedProductTypeNames()));
+        else 
+            complexQueryHash.put("reducedProductTypeNames", new Vector<String>());
+        if (complexQuery.getReducedMetadata() != null)
+            complexQueryHash.put("reducedMetadata", new Vector<String>(complexQuery.getReducedMetadata()));
+        else 
+            complexQueryHash.put("reducedMetadata", new Vector<String>());
+        if (complexQuery.getSortByMetKey() != null)
+            complexQueryHash.put("sortByMetKey", complexQuery.getSortByMetKey());
+        if (complexQuery.getToStringResultFormat() != null)
+            complexQueryHash.put("toStringResultFormat", complexQuery.getToStringResultFormat());
+        if (complexQuery.getQueryFilter() != null)
+            complexQueryHash.put("queryFilter", getXmlRpcQueryFilter(complexQuery.getQueryFilter()));
+        return complexQueryHash;
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static ComplexQuery getComplexQueryFromXmlRpc(Hashtable<String, Object> complexQueryHash) {
+        ComplexQuery complexQuery = new ComplexQuery();
+        complexQuery.setCriteria(getQueryFromXmlRpc(complexQueryHash).getCriteria());
+        if (((Vector<String>) complexQueryHash.get("reducedProductTypeNames")).size() > 0)
+            complexQuery.setReducedProductTypeNames((Vector<String>) complexQueryHash.get("reducedProductTypeNames"));
+        if (((Vector<String>) complexQueryHash.get("reducedMetadata")).size() > 0)
+            complexQuery.setReducedMetadata((Vector<String>) complexQueryHash.get("reducedMetadata"));
+        complexQuery.setSortByMetKey((String) complexQueryHash.get("sortByMetKey"));
+        complexQuery.setToStringResultFormat((String) complexQueryHash.get("toStringResultFormat"));
+        if (complexQueryHash.get("queryFilter") != null)
+            complexQuery.setQueryFilter(getQueryFilterFromXmlRpc((Hashtable<String, Object>) complexQueryHash.get("queryFilter")));
+        return complexQuery;
+    }
+    
+    public static Hashtable<String, Object> getXmlRpcQueryFilter(QueryFilter queryFilter) {
+        Hashtable<String, Object> queryFilterHash = new Hashtable<String, Object>();
+        queryFilterHash.put("startDateTimeMetKey", queryFilter.getStartDateTimeMetKey());
+        queryFilterHash.put("endDateTimeMetKey", queryFilter.getEndDateTimeMetKey());
+        queryFilterHash.put("priorityMetKey", queryFilter.getPriorityMetKey());
+        queryFilterHash.put("filterAlgor", getXmlRpcFilterAlgor(queryFilter.getFilterAlgor()));
+        queryFilterHash.put("versionConverterClass", queryFilter.getConverter().getClass().getCanonicalName());
+        return queryFilterHash;
+    }
+    
+    public static QueryFilter getQueryFilterFromXmlRpc(Hashtable<String, Object> queryFilterHash) {
+        String startDateTimeMetKey = (String) queryFilterHash.get("startDateTimeMetKey");
+        String endDateTimeMetKey = (String) queryFilterHash.get("endDateTimeMetKey");
+        String priorityMetKey = (String) queryFilterHash.get("priorityMetKey");
+        @SuppressWarnings("unchecked")
+        FilterAlgor filterAlgor = getFilterAlgorFromXmlRpc((Hashtable<String, Object>) queryFilterHash.get("filterAlgor"));
+        QueryFilter queryFilter = new QueryFilter(startDateTimeMetKey, endDateTimeMetKey, priorityMetKey, filterAlgor);
+        queryFilter.setConverter(GenericFileManagerObjectFactory.getVersionConverterFromClassName((String) queryFilterHash.get("versionConverterClass")));
+        return queryFilter;
+    }
+
+    public static Hashtable<String, Object> getXmlRpcFilterAlgor(FilterAlgor filterAlgor) {
+        Hashtable<String, Object> filterAlgorHash = new Hashtable<String, Object>();
+        filterAlgorHash.put("class", filterAlgor.getClass().getCanonicalName());
+        filterAlgorHash.put("epsilon", Long.toString(filterAlgor.getEpsilon()));
+        return filterAlgorHash;
+    }
+    
+    public static FilterAlgor getFilterAlgorFromXmlRpc(Hashtable<String, Object> filterAlgorHash) {
+        FilterAlgor filterAlgor = GenericFileManagerObjectFactory.getFilterAlgorFromClassName((String) filterAlgorHash.get("class"));
+        filterAlgor.setEpsilon(Long.parseLong((String) filterAlgorHash.get("epsilon")));
+        return filterAlgor;
+    }
+    
+    public static Vector<Hashtable<String, Object>> getXmlRpcQueryResults(List<QueryResult> queryResults) {
+        Vector<Hashtable<String, Object>> queryResultHashVector = new Vector<Hashtable<String, Object>>();
+        for (QueryResult queryResult : queryResults)
+            queryResultHashVector.add(getXmlRpcQueryResult(queryResult));
+        return queryResultHashVector;
+    }
+    
+    public static List<QueryResult> getQueryResultsFromXmlRpc(Vector<Hashtable<String, Object>> queryResultHashVector) {
+        List<QueryResult> queryResults = new Vector<QueryResult>();
+        for (Hashtable<String, Object> queryResultHash : queryResultHashVector)
+            queryResults.add(getQueryResultFromXmlRpc(queryResultHash));
+        return queryResults;
+    }
+        
+    public static Hashtable<String, Object> getXmlRpcQueryResult(QueryResult queryResult) {
+        Hashtable<String, Object> queryResultHash = new Hashtable<String, Object>();
+        if (queryResult.getToStringFormat() != null)
+            queryResultHash.put("toStringFormat", queryResult.getToStringFormat());
+        queryResultHash.put("product", getXmlRpcProduct(queryResult.getProduct()));
+        queryResultHash.put("metadata", queryResult.getMetadata().getHashtable());
+        return queryResultHash;
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static QueryResult getQueryResultFromXmlRpc(Hashtable<String, Object> queryResultHash) {
+        Product product = getProductFromXmlRpc((Hashtable<String, Object>) queryResultHash.get("product"));
+        Metadata metadata = new Metadata();
+        metadata.addMetadata((Hashtable<String, Object>) queryResultHash.get("metadata"));
+        QueryResult queryResult = new QueryResult(product, metadata);
+        queryResult.setToStringFormat((String) queryResultHash.get("toStringFormat"));
+        return queryResult;
+    }
+    
+    public static Hashtable<String, Object> getXmlRpcProduct(Product product) {
+        Hashtable<String, Object> productHash = new Hashtable<String, Object>();
+        if (product.getProductId() != null) {
+           productHash.put("id", product.getProductId());
+        }
+        if (product.getProductName() != null) {
+           productHash.put("name", product.getProductName());
+        }
+        if (product.getProductType() != null) {
+           productHash.put("type", getXmlRpcProductType(product.getProductType()));
+        }
+        if (product.getProductStructure() != null) {
+           productHash.put("structure", product.getProductStructure());
+        }
+        if (product.getTransferStatus() != null) {
+           productHash.put("transferStatus", product.getTransferStatus());
+        }
+        if (product.getProductReferences() != null) {
+           productHash.put("references", getXmlRpcReferences(product
+                .getProductReferences()));
+        }
+        if (product.getRootRef() != null) {
+           productHash.put("rootReference", getXmlRpcReference(product
+                 .getRootRef()));
+        }
+        return productHash;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static Product getProductFromXmlRpc(Hashtable<?, ?> productHash) {
+        Product product = new Product();
+        product.setProductId((String) productHash.get("id"));
+        product.setProductName((String) productHash.get("name"));
+        if (productHash.get("type") != null) {
+           product.setProductType(getProductTypeFromXmlRpc(
+                 (Hashtable<String, Object>) productHash.get("type")));
+        }
+        product.setProductStructure((String) productHash.get("structure"));
+        product.setTransferStatus((String) productHash.get("transferStatus"));
+        if (productHash.get("references") != null) {
+           product.setProductReferences(getReferencesFromXmlRpc(
+                 (Vector<Hashtable<String, Object>>) productHash
+                        .get("references")));
+        }
+        if (productHash.get("rootReference") != null) {
+           product.setRootRef(getReferenceFromXmlRpc(
+                 (Hashtable<String, Object>) productHash.get("rootReference")));
+        }
+        return product;
+    }
+
+    public static List<Product> getProductListFromXmlRpc(Vector<Hashtable<String, Object>> productVector) {
+        List<Product> productList = new Vector<Product>();
+
+        for (Iterator<Hashtable<String, Object>> i = productVector.iterator(); i.hasNext();) {
+            Hashtable<String, Object> productHash = i.next();
+            Product product = getProductFromXmlRpc(productHash);
+            productList.add(product);
+        }
+
+        return productList;
+    }
+
+    public static Vector<Hashtable<String, Object>> getXmlRpcProductList(List<Product> products) {
+        Vector<Hashtable<String, Object>> productVector = new Vector<Hashtable<String, Object>>();
+
+        if (products == null) {
+            return productVector;
+        }
+
+        for (Iterator<Product> i = products.iterator(); i.hasNext();) {
+            Product product = i.next();
+            Hashtable<String, Object> productHash = getXmlRpcProduct(product);
+            productVector.add(productHash);
+        }
+
+        return productVector;
+    }
+
+    public static Vector<Hashtable<String, Object>> getXmlRpcProductTypeList(List<ProductType> productTypes) {
+        Vector<Hashtable<String, Object>> productTypeVector = new Vector<Hashtable<String, Object>>();
+
+        if (productTypes == null) {
+            return productTypeVector;
+        }
+
+        for (Iterator<ProductType> i = productTypes.iterator(); i.hasNext();) {
+            ProductType type = i.next();
+            Hashtable<String, Object> typeHash = getXmlRpcProductType(type);
+            productTypeVector.add(typeHash);
+        }
+        return productTypeVector;
+    }
+
+    public static List<ProductType> getProductTypeListFromXmlRpc(Vector<Hashtable<String, Object>> productTypeVector) {
+        List<ProductType> productTypeList = new Vector<ProductType>();
+        for (Iterator<Hashtable<String, Object>> i = productTypeVector.iterator(); i.hasNext();) {
+            Hashtable<String, Object> productTypeHash = i.next();
+            ProductType type = getProductTypeFromXmlRpc(productTypeHash);
+            productTypeList.add(type);
+        }
+
+        return productTypeList;
+    }
+
+    public static Hashtable<String, Object> getXmlRpcProductType(ProductType type) {
+        Hashtable<String, Object> productTypeHash = new Hashtable<String, Object>();
+        // TODO(bfoster): ProductType ID is currently required by XmlRpcFileManager.
+        productTypeHash.put("id", type.getProductTypeId());
+        if (type.getName() != null) {
+           productTypeHash.put("name", type.getName());
+        }
+        if (type.getDescription() != null) {
+           productTypeHash.put("description", type.getDescription());  
+        }
+        if (type.getProductRepositoryPath() != null) {
+           productTypeHash.put("repositoryPath",type.getProductRepositoryPath());
+        }
+        if (type.getVersioner() != null) {
+           productTypeHash.put("versionerClass", type.getVersioner());
+        }
+        if (type.getTypeMetadata() != null) {
+           productTypeHash.put("typeMetadata", type.getTypeMetadata().getHashtable());
+        }
+        if (type.getExtractors() != null) {
+           productTypeHash.put("typeExtractors", getXmlRpcTypeExtractors(type.getExtractors()));
+        }
+        if (type.getHandlers() != null) {
+           productTypeHash.put("typeHandlers", getXmlRpcTypeHandlers(type.getHandlers()));
+        }
+        return productTypeHash;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static ProductType getProductTypeFromXmlRpc(Hashtable<String, Object> productTypeHash) {
+        ProductType type = new ProductType();
+        type.setDescription((String) productTypeHash.get("description"));
+        type.setName((String) productTypeHash.get("name"));
+        type.setProductRepositoryPath((String) productTypeHash.get("repositoryPath"));
+        type.setProductTypeId((String) productTypeHash.get("id"));
+        type.setVersioner((String) productTypeHash.get("versionerClass"));
+        if (productTypeHash.get("typeMetadata") != null) {
+           Metadata typeMet = new Metadata();
+           typeMet.addMetadata((Hashtable<String, Object>) productTypeHash.get("typeMetadata"));
+           type.setTypeMetadata(typeMet);
+        }
+        if (productTypeHash.get("typeExtractors") != null) {
+            type.setExtractors(getTypeExtractorsFromXmlRpc(
+                  (Vector<Hashtable<String, Object>>) productTypeHash
+                     .get("typeExtractors")));
+        }
+        if (productTypeHash.get("typeHandlers") != null) {
+            type.setHandlers(getTypeHandlersFromXmlRpc(
+                  (Vector<Hashtable<String, Object>>) productTypeHash
+                        .get("typeHandlers")));
+        }
+        return type;
+    }
+
+    public static Vector<Hashtable<String, Object>> getXmlRpcTypeExtractors(List<ExtractorSpec> extractors) {
+        Vector<Hashtable<String, Object>> extractorsVector = new Vector<Hashtable<String, Object>>();
+
+        if (extractors != null && extractors.size() > 0) {
+            for (Iterator<ExtractorSpec> i = extractors.iterator(); i.hasNext();) {
+                ExtractorSpec spec = i.next();
+                extractorsVector.add(getXmlRpcExtractorSpec(spec));
+            }
+        }
+
+        return extractorsVector;
+    }
+
+    public static Hashtable<String, Object> getXmlRpcExtractorSpec(ExtractorSpec spec) {
+        Hashtable<String, Object> extractorHash = new Hashtable<String, Object>();
+        extractorHash.put("className", spec.getClassName());
+        extractorHash.put("config",
+                getXmlRpcProperties(spec.getConfiguration()));
+        return extractorHash;
+    }
+    
+    public static Vector<Hashtable<String, Object>> getXmlRpcTypeHandlers(List<TypeHandler> typeHandlers) {
+        Vector<Hashtable<String, Object>> handlersVector = new Vector<Hashtable<String, Object>>();
+
+        if (typeHandlers != null && typeHandlers.size() > 0) {
+            for (Iterator<TypeHandler> i = typeHandlers.iterator(); i.hasNext();) {
+                TypeHandler typeHandler = i.next();
+                handlersVector.add(getXmlRpcTypeHandler(typeHandler));
+            }
+        }
+
+        return handlersVector;
+    }
+    
+    public static Hashtable<String, Object> getXmlRpcTypeHandler(TypeHandler typeHandler) {
+        Hashtable<String, Object> handlerHash = new Hashtable<String, Object>();
+        handlerHash.put("className", typeHandler != null ? 
+            typeHandler.getClass().getCanonicalName():"");
+        handlerHash.put("elementName", typeHandler != null ? 
+            typeHandler.getElementName():"");
+        return handlerHash;
+    }
+
+    public static List<ExtractorSpec> getTypeExtractorsFromXmlRpc(Vector<Hashtable<String, Object>> extractorsVector) {
+        List<ExtractorSpec> extractors = new Vector<ExtractorSpec>();
+
+        if (extractorsVector != null && extractorsVector.size() > 0) {
+            for (Iterator<Hashtable<String, Object>> i = extractorsVector.iterator(); i.hasNext();) {
+                Hashtable<String, Object> extractorSpecHash = i.next();
+                extractors.add(getExtractorSpecFromXmlRpc(extractorSpecHash));
+            }
+        }
+
+        return extractors;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static ExtractorSpec getExtractorSpecFromXmlRpc(
+            Hashtable<String, Object> extractorSpecHash) {
+        ExtractorSpec spec = new ExtractorSpec();
+        spec.setClassName((String) extractorSpecHash.get("className"));
+        spec
+                .setConfiguration(getPropertiesFromXmlRpc((Hashtable<String, String>) extractorSpecHash
+                        .get("config")));
+        return spec;
+    }
+    
+    public static List<TypeHandler> getTypeHandlersFromXmlRpc(Vector<Hashtable<String, Object>> handlersVector) {
+        List<TypeHandler> handlers = new Vector<TypeHandler>();
+
+        if (handlersVector != null && handlersVector.size() > 0) {
+            for (Iterator<Hashtable<String, Object>> i = handlersVector.iterator(); i.hasNext();) {
+                Hashtable<String, Object> typeHandlerHash = i.next();
+                handlers.add(getTypeHandlerFromXmlRpc(typeHandlerHash));
+            }
+        }
+
+        return handlers;
+    }
+    
+    public static TypeHandler getTypeHandlerFromXmlRpc(
+            Hashtable<String, Object> typeHandlerHash) {
+        TypeHandler typeHandler = GenericFileManagerObjectFactory
+            .getTypeHandlerFromClassName((String) typeHandlerHash.get("className"));
+        if(typeHandler != null)
+          typeHandler.setElementName((String) typeHandlerHash.get("elementName"));
+        return typeHandler;
+    }
+
+    public static Properties getPropertiesFromXmlRpc(Hashtable<String, String> propHash) {
+        Properties props = new Properties();
+
+        if (propHash != null && propHash.keySet().size() > 0) {
+            for (Iterator<String> i = propHash.keySet().iterator(); i.hasNext();) {
+                String propName = i.next();
+                String propValue = propHash.get(propName);
+                props.setProperty(propName, propValue);
+            }
+        }
+
+        return props;
+    }
+
+    public static Hashtable<String, String> getXmlRpcProperties(Properties props) {
+        Hashtable<String, String> propHash = new Hashtable<String, String>();
+
+        if (props != null && props.keySet().size() > 0) {
+            for (Iterator<Object> i = props.keySet().iterator(); i.hasNext();) {
+                String propName = (String) i.next();
+                String propValue = props.getProperty(propName);
+                propHash.put(propName, propValue);
+            }
+        }
+
+        return propHash;
+    }
+
+    public static Vector<Hashtable<String, Object>> getXmlRpcReferences(List<Reference> references) {
+        Vector<Hashtable<String, Object>> refVector = new Vector<Hashtable<String, Object>>();
+
+        if (references == null) {
+            return refVector;
+        }
+
+        for (Iterator<Reference> i = references.iterator(); i.hasNext();) {
+            Hashtable<String, Object> refHash = getXmlRpcReference(i.next());
+            refVector.add(refHash);
+        }
+
+        return refVector;
+    }
+
+    public static List<Reference> getReferencesFromXmlRpc(Vector<Hashtable<String, Object>> referenceVector) {
+        List<Reference> references = new Vector<Reference>();
+        for (Iterator<Hashtable<String, Object>> i = referenceVector.iterator(); i.hasNext();) {
+            Reference r = getReferenceFromXmlRpc(i.next());
+            references.add(r);
+        }
+        return references;
+    }
+
+    public static Hashtable<String, Object> getXmlRpcReference(Reference reference) {
+        Hashtable<String, Object> referenceHash = new Hashtable<String, Object>();
+        referenceHash.put("origReference", reference.getOrigReference());
+        referenceHash.put("dataStoreReference", reference
+                .getDataStoreReference() != null ? reference
+                .getDataStoreReference() : "");
+        referenceHash.put("fileSize",
+                Long.toString(reference.getFileSize()));
+        referenceHash.put("mimeType", (reference.getMimeType() == null) ? ""
+                : reference.getMimeType().getName());
+        return referenceHash;
+    }
+
+    public static Reference getReferenceFromXmlRpc(Hashtable<String, Object> referenceHash) {
+        Reference reference = new Reference();
+        reference.setDataStoreReference((String) referenceHash
+                .get("dataStoreReference"));
+        reference.setOrigReference((String) referenceHash.get("origReference"));
+        reference.setFileSize(Long.parseLong(referenceHash.get("fileSize").toString()));
+        reference.setMimeType((String) referenceHash.get("mimeType"));
+        return reference;
+    }
+
+    public static Vector<Hashtable<String, Object>> getXmlRpcElementList(List<Element> elementList) {
+        Vector<Hashtable<String, Object>> elementVector = new Vector<Hashtable<String, Object>>(elementList.size());
+        for (Iterator<Element> i = elementList.iterator(); i.hasNext();) {
+            Element element = i.next();
+            Hashtable<String, Object> elementHash = getXmlRpcElement(element);
+            elementVector.add(elementHash);
+        }
+        return elementVector;
+    }
+
+    public static List<Element> getElementListFromXmlRpc(Vector<Hashtable<String, Object>> elementVector) {
+        List<Element> elementList = new Vector<Element>(elementVector.size());
+        for (Iterator<Hashtable<String, Object>> i = elementVector.iterator(); i.hasNext();) {
+            Hashtable<String, Object> elementHash = i.next();
+            Element element = getElementFromXmlRpc(elementHash);
+            elementList.add(element);
+        }
+        return elementList;
+    }
+
+    public static Hashtable<String, Object> getXmlRpcElement(Element element) {
+        Hashtable<String, Object> elementHash = new Hashtable<String, Object>();
+
+        elementHash.put("id", element.getElementId());
+        elementHash.put("name", element.getElementName());
+        elementHash.put("dcElement", element.getDCElement() != null ? element
+                .getDCElement() : "");
+        elementHash.put("description",
+                element.getDescription() != null ? element.getDescription()
+                        : "");
+
+        return elementHash;
+    }
+
+    public static Element getElementFromXmlRpc(Hashtable<String, Object> elementHash) {
+        Element element = new Element();
+        element.setElementId((String) elementHash.get("id"));
+        element.setElementName((String) elementHash.get("name"));
+        element.setDescription((String) elementHash.get("description"));
+        element.setDCElement((String) elementHash.get("dcElement"));
+
+        return element;
+    }
+
+    public static Hashtable<String, Object> getXmlRpcQuery(Query query) {
+        Hashtable<String, Object> queryHash = new Hashtable<String, Object>();
+        Vector<Hashtable<String, Object>> criteriaVector = getXmlRpcQueryCriteriaList(query.getCriteria());
+        queryHash.put("criteria", criteriaVector);
+        return queryHash;
+    }
+
+    public static Query getQueryFromXmlRpc(Hashtable<String, Object> queryHash) {
+        Query query = new Query();
+        @SuppressWarnings("unchecked")
+        List<QueryCriteria> criteria = getQueryCriteriaListFromXmlRpc((Vector<Hashtable<String, Object>>) queryHash
+                .get("criteria"));
+        query.setCriteria(criteria);
+        return query;
+    }
+
+    public static Vector<Hashtable<String, Object>> getXmlRpcQueryCriteriaList(List<QueryCriteria> criteriaList) {
+        Vector<Hashtable<String, Object>> criteriaVector = new Vector<Hashtable<String, Object>>(criteriaList.size());
+        for (Iterator<QueryCriteria> i = criteriaList.iterator(); i.hasNext();) {
+            QueryCriteria criteria = i.next();
+            Hashtable<String, Object> criteriaHash = getXmlRpcQueryCriteria(criteria);
+            criteriaVector.add(criteriaHash);
+        }
+
+        return criteriaVector;
+    }
+
+    public static List<QueryCriteria> getQueryCriteriaListFromXmlRpc(Vector<Hashtable<String, Object>> criteriaVector) {
+
+        List<QueryCriteria> criteriaList = new Vector<QueryCriteria>(criteriaVector.size());
+        for (Iterator<Hashtable<String, Object>> i = criteriaVector.iterator(); i.hasNext();) {
+            Hashtable<String, Object> criteriaHash = i.next();
+            QueryCriteria criteria = getQueryCriteriaFromXmlRpc(criteriaHash);
+            criteriaList.add(criteria);
+        }
+        return criteriaList;
+    }
+
+    public static Hashtable<String, Object> getXmlRpcQueryCriteria(QueryCriteria criteria) {
+        Hashtable<String, Object> criteriaHash = new Hashtable<String, Object>();
+        criteriaHash.put("class",criteria.getClass().getCanonicalName());
+        
+        if(criteria instanceof TermQueryCriteria){  
+            criteriaHash.put("elementName", criteria.getElementName());
+            criteriaHash.put("elementValue", ((TermQueryCriteria)criteria).getValue());
+        } else if(criteria instanceof RangeQueryCriteria){
+            criteriaHash.put("elementName", criteria.getElementName());
+            criteriaHash.put("elementStartValue", ((RangeQueryCriteria)criteria).getStartValue() != null ?
+                    ((RangeQueryCriteria)criteria).getStartValue():"");
+            criteriaHash.put("elementEndValue", ((RangeQueryCriteria)criteria).getEndValue() != null ?
+                    ((RangeQueryCriteria)criteria).getEndValue():"");
+            criteriaHash.put("inclusive", Boolean.toString(((RangeQueryCriteria) criteria).getInclusive())); 
+        } else if(criteria instanceof BooleanQueryCriteria){
+            BooleanQueryCriteria boolQuery = (BooleanQueryCriteria) criteria;
+            criteriaHash.put("operator", new Integer(boolQuery.getOperator()));
+            Vector<Hashtable<String, Object>> termsHash = new Vector<Hashtable<String, Object>>();
+            List<QueryCriteria> terms = boolQuery.getTerms();
+            
+            for(int i=0;i<terms.size();i++){
+                QueryCriteria term = terms.get(i);
+                Hashtable<String, Object> termHash = getXmlRpcQueryCriteria(term);
+                termsHash.add(termHash);
+            }
+            criteriaHash.put("terms", termsHash);
+            
+        } else {
+            //should not happen
+        }
+        return criteriaHash;
+    }
+    
+    public static QueryCriteria getQueryCriteriaFromXmlRpc(Hashtable<String, Object> criteriaHash) {
+        QueryCriteria criteria = null;
+        if(((String)criteriaHash.get("class")).equals(TermQueryCriteria.class.getCanonicalName())){
+            criteria = new TermQueryCriteria();
+            criteria.setElementName((String) criteriaHash.get("elementName"));
+            ((TermQueryCriteria)criteria).setValue((String) criteriaHash.get("elementValue"));
+        } else if(((String)criteriaHash.get("class")).equals(RangeQueryCriteria.class.getCanonicalName())){
+            criteria = new RangeQueryCriteria();
+            criteria.setElementName((String) criteriaHash.get("elementName"));
+            String startVal = criteriaHash.get("elementStartValue").equals("") ? 
+                    null : (String)criteriaHash.get("elementStartValue");
+            String endVal = criteriaHash.get("elementEndValue").equals("") ?
+                    null : (String)criteriaHash.get("elementEndValue");
+            ((RangeQueryCriteria)criteria).setStartValue(startVal);
+            ((RangeQueryCriteria)criteria).setEndValue(endVal);
+            ((RangeQueryCriteria)criteria).setInclusive(Boolean.parseBoolean((String) criteriaHash.get("inclusive")));
+        } else if(((String)criteriaHash.get("class")).equals(BooleanQueryCriteria.class.getCanonicalName())){
+            criteria = new BooleanQueryCriteria();
+            try{
+              ((BooleanQueryCriteria)criteria).setOperator( ((Integer)criteriaHash.get("operator")).intValue() );
+            } catch (QueryFormulationException e){
+                System.out.println("Error generating Boolean Query.");
+            }
+            @SuppressWarnings("unchecked")
+            List<Hashtable<String, Object>> terms = (List<Hashtable<String, Object>>) criteriaHash.get("terms");
+            for(int i=0;i<terms.size();i++){
+                Hashtable<String, Object> term = terms.get(i);
+                QueryCriteria termCriteria = getQueryCriteriaFromXmlRpc(term);
+                try{
+                    ((BooleanQueryCriteria)criteria).addTerm(termCriteria);
+                } catch (QueryFormulationException e){
+                    System.out.println("Error generating Boolean Query.");
+                }
+            }
+            
+        }
+
+        return criteria;        
+        
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/XmlStructFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/XmlStructFactory.java
new file mode 100644
index 0000000..eea37b7
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/util/XmlStructFactory.java
@@ -0,0 +1,494 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.util;
+
+//JDK imports
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.ExtractorSpec;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.type.TypeHandler;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Generic class for constructing File Manager objects out of XML {@link Node}s.
+ * </p>
+ * 
+ */
+public final class XmlStructFactory {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(XmlStructFactory.class
+            .getName());
+
+    private XmlStructFactory() throws InstantiationException {
+        throw new InstantiationException("Don't construct XmlStructFactories!");
+    }
+
+    public static ProductType getProductType(Node productTypeNode) {
+        org.w3c.dom.Element productTypeElem = (org.w3c.dom.Element) productTypeNode;
+
+        String id = productTypeElem.getAttribute("id");
+        String name = productTypeElem.getAttribute("name");
+
+        org.w3c.dom.Element repositoryElem = XMLUtils.getFirstElement(
+                "repository", productTypeElem);
+
+        String repositoryPath = repositoryElem.getAttribute("path");
+
+        org.w3c.dom.Element versionerElem = XMLUtils.getFirstElement(
+                "versioner", productTypeElem);
+
+        String versionerClass = versionerElem.getAttribute("class");
+
+        org.w3c.dom.Element descElem = XMLUtils.getFirstElement("description",
+                productTypeElem);
+
+        String description = null;
+        if (descElem.getAttribute("trim") != null
+                && !descElem.getAttribute("trim").equals("")
+                && !Boolean.valueOf(descElem.getAttribute("trim"))) {
+            description = XMLUtils.getElementText("description",
+                    productTypeElem);
+        } else {
+            description = XMLUtils.getElementText("description",
+                    productTypeElem, true);
+        }
+
+        repositoryPath = PathUtils.replaceEnvVariables(repositoryPath);
+
+        // grab metadata
+        Metadata met = null;
+        Element metadataRoot = XMLUtils.getFirstElement("metadata",
+                productTypeElem);
+        if (metadataRoot != null) {
+            Hashtable<String, Object> metHash = new Hashtable<String, Object>();
+            met = new Metadata();
+            NodeList keyValElems = metadataRoot.getElementsByTagName("keyval");
+
+            for (int i = 0; i < keyValElems.getLength(); i++) {
+                Element keyValElem = (Element) keyValElems.item(i);
+
+                String elemName = XMLUtils.read(keyValElem, "key");
+                @SuppressWarnings("unchecked")
+                List<String> elemValues = XMLUtils.readMany(keyValElem, "val");
+                metHash.put(elemName, elemValues);
+            }
+
+            met.replaceMetadata(metHash);
+        }
+
+        // grab extractors
+        List<ExtractorSpec> extractors = null;
+        Element extractorRoot = XMLUtils.getFirstElement("metExtractors",
+                productTypeElem);
+
+        if (extractorRoot != null) {
+            NodeList extractorNodes = extractorRoot
+                    .getElementsByTagName("extractor");
+            extractors = new Vector<ExtractorSpec>();
+            if (extractorNodes != null && extractorNodes.getLength() > 0) {
+                for (int i = 0; i < extractorNodes.getLength(); i++) {
+                    Element extractorElem = (Element) extractorNodes.item(i);
+                    ExtractorSpec spec = new ExtractorSpec();
+                    String className = extractorElem.getAttribute("class");
+                    spec.setClassName(className);
+
+                    // see if there are any configuration properties
+                    Element configuration = XMLUtils.getFirstElement(
+                            "configuration", extractorElem);
+
+                    if (configuration != null) {
+                        Properties config = new Properties();
+                        NodeList propertyNodes = configuration
+                                .getElementsByTagName("property");
+
+                        if (propertyNodes != null
+                                && propertyNodes.getLength() > 0) {
+                            for (int j = 0; j < propertyNodes.getLength(); j++) {
+                                Element propertyElem = (Element) propertyNodes
+                                        .item(j);
+                                String propertyName = propertyElem
+                                        .getAttribute("name");
+                                String propertyValue = propertyElem
+                                        .getAttribute("value");
+                                if (Boolean
+                                        .valueOf(
+                                                propertyElem
+                                                        .getAttribute("envReplace"))
+                                        .booleanValue()) {
+                                    propertyValue = PathUtils
+                                            .replaceEnvVariables(propertyValue);
+                                }
+
+                                config.setProperty(propertyName, propertyValue);
+                            }
+
+                            spec.setConfiguration(config);
+                        }
+                    }
+
+                    extractors.add(spec);
+                }
+
+            }
+        }
+        
+        List<TypeHandler> handlers = null;
+        Element handlerRoot = XMLUtils.getFirstElement("typeHandlers",
+                productTypeElem);
+        if (handlerRoot != null) {
+            NodeList handlerNodes = handlerRoot.getElementsByTagName("typeHandler");
+            if (handlerNodes != null && handlerNodes.getLength() > 0) {
+                handlers = new Vector<TypeHandler>();
+                for (int i = 0; i < handlerNodes.getLength(); i++) {
+                    Node handlerNode = handlerNodes.item(i);
+                    String handlerClass = ((Element) handlerNode).getAttribute("class");
+                    String elementName = ((Element) handlerNode).getAttribute("elementName");
+                    try {
+                        TypeHandler typeHandler = (TypeHandler) Class.forName(handlerClass).newInstance();
+                        typeHandler.setElementName(elementName);
+                        handlers.add(typeHandler);
+                    }catch (Exception e) {
+                        e.printStackTrace();
+                        LOG.log(Level.WARNING, "Failed to load handler for ProductType [name = " + name 
+                                + "] and element [name = " + elementName + "] : " + e.getMessage());
+                    }
+                }
+            }
+        }
+        
+        ProductType productType = new ProductType();
+        productType.setName(name);
+        productType.setProductTypeId(id);
+        productType.setProductRepositoryPath(repositoryPath);
+        productType.setVersioner(versionerClass);
+        productType.setDescription(description);
+        productType.setTypeMetadata(met);
+        productType.setExtractors(extractors);
+        productType.setHandlers(handlers);
+
+        return productType;
+    }
+
+    public static void writeProductTypeMapXmLDocument(HashMap<String, List<org.apache.oodt.cas.filemgr.structs.Element>> productTypeMap,
+            HashMap<String, String> subToSuperMap, String xmlFilePath) {
+        XMLUtils.writeXmlFile(getProductTypeMapXmlDocument(productTypeMap,
+                subToSuperMap), xmlFilePath);
+    }
+
+    public static void writeElementXmlDocument(List<org.apache.oodt.cas.filemgr.structs.Element> elements, String xmlFilePath) {
+        XMLUtils.writeXmlFile(getElementXmlDocument(elements), xmlFilePath);
+    }
+
+    public static void writeProductTypeXmlDocument(List<ProductType> productTypes,
+            String xmlFilePath) {
+        XMLUtils.writeXmlFile(getProductTypeXmlDocument(productTypes),
+                xmlFilePath);
+    }
+
+    public static Document getProductTypeMapXmlDocument(HashMap<String, List<org.apache.oodt.cas.filemgr.structs.Element>> productTypeMap,
+            HashMap<String, String> subToSuperMap) {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        Document document = null;
+
+        try {
+            DocumentBuilder builder = factory.newDocumentBuilder();
+            document = builder.newDocument();
+
+            Element root = (Element) document
+                    .createElement("cas:producttypemap");
+            root.setAttribute("xmlns:cas", "http://oodt.jpl.nasa.gov/1.0/cas");
+            document.appendChild(root);
+
+            // Also print types without elements but just with parents
+            ArrayList<String> allTypes = new ArrayList<String>(productTypeMap.keySet());
+            for(String type: subToSuperMap.keySet()) {
+                if(!allTypes.contains(type))
+                    allTypes.add(type);
+            }
+            
+            for (Iterator<String> i = allTypes.iterator(); i.hasNext();) {
+                String typeId = i.next();
+
+                Element typeElem = document.createElement("type");
+                typeElem.setAttribute("id", typeId);
+
+                boolean hasParent = false;
+                if (subToSuperMap.containsKey(typeId)) {
+                    typeElem.setAttribute("parent", subToSuperMap
+                            .get(typeId));
+                    hasParent = true;
+                }
+
+                List<org.apache.oodt.cas.filemgr.structs.Element> elementIds = productTypeMap.get(typeId);
+                if(!hasParent && (elementIds == null || elementIds.size() == 0)) {
+                    // If no parent, and no elements, don't add this type to the xml
+                    continue;
+                }
+                if(elementIds != null) {
+                    for (Iterator<org.apache.oodt.cas.filemgr.structs.Element> j = elementIds.iterator(); j.hasNext();) {
+                        String elementId = j.next().getElementId();
+
+                        Element elementElem = document.createElement("element");
+                        elementElem.setAttribute("id", elementId);
+                        typeElem.appendChild(elementElem);
+                    }
+                }
+
+                root.appendChild(typeElem);
+            }
+
+            return document;
+
+        } catch (ParserConfigurationException pce) {
+            LOG.log(Level.WARNING,
+                    "Error generating product-type-element-map xml file!: "
+                            + pce.getMessage());
+        }
+
+        return null;
+    }
+
+    public static Document getElementXmlDocument(List<org.apache.oodt.cas.filemgr.structs.Element> elements) {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        Document document = null;
+
+        try {
+            DocumentBuilder builder = factory.newDocumentBuilder();
+            document = builder.newDocument();
+
+            Element root = (Element) document.createElement("cas:elements");
+            root.setAttribute("xmlns:cas", "http://oodt.jpl.nasa.gov/1.0/cas");
+            document.appendChild(root);
+
+            for (Iterator<org.apache.oodt.cas.filemgr.structs.Element> i = elements.iterator(); i.hasNext();) {
+                org.apache.oodt.cas.filemgr.structs.Element element = i.next();
+                Element elementElem = document.createElement("element");
+                elementElem.setAttribute("id", friendlyXml(element.getElementId()));
+                elementElem.setAttribute("name", friendlyXml(element.getElementName()));
+
+                Element descriptionElem = document.createElement("description");
+                descriptionElem.appendChild(document.createTextNode(friendlyXml(element
+                        .getDescription())));
+                elementElem.appendChild(descriptionElem);
+
+                Element dcElementElem = document.createElement("dcElement");
+                dcElementElem.appendChild(document.createTextNode(friendlyXml(element
+                        .getDCElement())));
+                elementElem.appendChild(dcElementElem);
+                
+                root.appendChild(elementElem);
+            }
+
+            return document;
+
+        } catch (ParserConfigurationException pce) {
+            LOG.log(Level.WARNING, "Error generating elements xml file!: "
+                    + pce.getMessage());
+        }
+
+        return null;
+    }
+
+    public static Document getProductTypeXmlDocument(List<ProductType> productTypes) {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        Document document = null;
+
+        try {
+            DocumentBuilder builder = factory.newDocumentBuilder();
+            document = builder.newDocument();
+
+            Element root = (Element) document.createElement("cas:producttypes");
+            root.setAttribute("xmlns:cas", "http://oodt.jpl.nasa.gov/1.0/cas");
+            document.appendChild(root);
+
+            // now add the set of metadata elements in the properties object
+            for (Iterator<ProductType> i = productTypes.iterator(); i.hasNext();) {
+                ProductType type = i.next();
+
+                Element typeElem = document.createElement("type");
+                typeElem.setAttribute("id", type.getProductTypeId());
+                typeElem.setAttribute("name", type.getName());
+
+                Element descriptionElem = document.createElement("description");
+                descriptionElem.appendChild(document.createTextNode(type
+                        .getDescription()));
+                typeElem.appendChild(descriptionElem);
+
+                Element repositoryPathElem = document
+                        .createElement("repository");
+                repositoryPathElem.setAttribute("path", type
+                        .getProductRepositoryPath());
+                typeElem.appendChild(repositoryPathElem);
+
+                Element versionerClassPathElem = document
+                        .createElement("versioner");
+                versionerClassPathElem.setAttribute("class", type
+                        .getVersioner());
+                typeElem.appendChild(versionerClassPathElem);
+
+                // add extractor info
+                Element metExtractorsElem = document.createElement("metExtractors");
+                for (Object specObject : type.getExtractors()) {
+                    ExtractorSpec spec = (ExtractorSpec) specObject;
+                    Element extractorElem = document.createElement("extractor");
+                    extractorElem.setAttribute("class", spec.getClassName());
+                    
+                    if (spec.getConfiguration() != null) {
+                        Element extractorConfigElem = document.createElement("configuration");
+                        Enumeration e = spec.getConfiguration().propertyNames();
+                        
+                        while (e.hasMoreElements()) {
+                            String key = (String) e.nextElement();
+                            
+                            Element propertyElem = document.createElement("property");
+                            propertyElem.setAttribute("name", key);
+                            propertyElem.setAttribute("value", spec.getConfiguration().getProperty(key));
+                            
+                            extractorConfigElem.appendChild(propertyElem);
+                        }
+                        
+                        extractorElem.appendChild(extractorConfigElem);
+                    }
+                    
+                    metExtractorsElem.appendChild(extractorElem);
+                }
+                typeElem.appendChild(metExtractorsElem);
+                
+                // add type metadata
+                Element metElem = document.createElement("metadata");
+                for (String key : type.getTypeMetadata().getAllKeys()) {
+                    Element keyValElem = document.createElement("keyval");
+                    Element keyElem = document.createElement("key");
+                    Element valElem = document.createElement("val");
+                    
+                    keyElem.appendChild(document.createTextNode(key));
+                    valElem.appendChild(document.createTextNode(
+                            type.getTypeMetadata().getMetadata(key)));
+                    keyValElem.appendChild(keyElem);
+                    keyValElem.appendChild(valElem);
+                    
+                    metElem.appendChild(keyValElem);
+                }
+                typeElem.appendChild(metElem);
+
+                root.appendChild(typeElem);
+            }
+
+            return document;
+        } catch (ParserConfigurationException pce) {
+            LOG.log(Level.WARNING, "Error generating producttypes xml file!: "
+                    + pce.getMessage());
+        }
+
+        return null;
+
+    }
+
+    public static org.apache.oodt.cas.filemgr.structs.Element getElement(
+            Node elementNode) {
+        org.w3c.dom.Element elementElem = (org.w3c.dom.Element) elementNode;
+
+        String id = elementElem.getAttribute("id");
+        String name = elementElem.getAttribute("name");
+
+        String dcElement = XMLUtils.getElementText("dcElement", elementElem);
+
+        org.w3c.dom.Element descElem = XMLUtils.getFirstElement("description",
+                elementElem);
+        String description = null;
+        if (descElem.getAttribute("trim") != null
+                && !descElem.getAttribute("trim").equals("")
+                && !Boolean.valueOf(descElem.getAttribute("trim"))) {
+            description = XMLUtils.getElementText("description", elementElem);
+        } else {
+            description = XMLUtils.getElementText("description", elementElem,
+                    true);
+        }
+
+        org.apache.oodt.cas.filemgr.structs.Element element = new org.apache.oodt.cas.filemgr.structs.Element();
+        element.setDCElement(dcElement);
+        element.setDescription(description);
+        element.setElementId(id);
+        element.setElementName(name);
+        return element;
+    }
+
+    public static HashMap<String, List<org.apache.oodt.cas.filemgr.structs.Element>> 
+            getProductTypeElementList(Node typeMapNode, HashMap<String, org.apache.oodt.cas.filemgr.structs.Element> elements) {
+        org.w3c.dom.Element typeMapElement = (org.w3c.dom.Element) typeMapNode;
+
+        String typeId = typeMapElement.getAttribute("id");
+
+        HashMap<String, List<org.apache.oodt.cas.filemgr.structs.Element>> productTypeElementMap = new HashMap<String, List<org.apache.oodt.cas.filemgr.structs.Element>>();
+
+        org.w3c.dom.Element elementListRoot = XMLUtils.getFirstElement(
+                "elements", typeMapElement);
+        NodeList elementNodeList = elementListRoot
+                .getElementsByTagName("element");
+
+        List<org.apache.oodt.cas.filemgr.structs.Element> elementList = new Vector<org.apache.oodt.cas.filemgr.structs.Element>(elementNodeList.getLength());
+
+        for (int i = 0; i < elementNodeList.getLength(); i++) {
+            org.w3c.dom.Element elementElem = (org.w3c.dom.Element) elementNodeList
+                    .item(i);
+            String elementId = elementElem.getAttribute("id");
+            org.apache.oodt.cas.filemgr.structs.Element element = elements
+                    .get(elementId);
+            elementList.add(element);
+        }
+
+        productTypeElementMap.put(typeId, elementList);
+        return productTypeElementMap;
+    }
+    
+    private static String friendlyXml(String value){
+      return value != null ? value:"";
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/DataSourceValidationLayer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/DataSourceValidationLayer.java
new file mode 100644
index 0000000..38a5664
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/DataSourceValidationLayer.java
@@ -0,0 +1,853 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.validation;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+import org.apache.oodt.cas.filemgr.util.DbStructFactory;
+
+//JDK imports
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import javax.sql.DataSource;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * An implementation of a ValidationLayer that queries a {@link DataSource}
+ * backed database for validation information.
+ * </p>
+ * 
+ */
+public class DataSourceValidationLayer implements ValidationLayer {
+
+    /* our log stream */
+    private static final Logger LOG = Logger
+            .getLogger(DataSourceValidationLayer.class.getName());
+
+    /* our data source */
+    private DataSource dataSource = null;
+
+    /* should we quote product_type_id? */
+    private boolean quoteFields = false;
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     */
+    public DataSourceValidationLayer(DataSource ds, boolean fieldQuote) {
+        dataSource = ds;
+        quoteFields = fieldQuote;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#addElement(org.apache.oodt.cas.filemgr.structs.Element)
+     */
+    public void addElement(Element element) throws ValidationLayerException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String addMetaElemSql = "INSERT INTO elements (element_name, dc_element, element_description) VALUES ('"
+                    + element.getElementName()
+                    + ", '"
+                    + element.getDCElement()
+                    + "', '" + element.getDescription() + "')";
+
+            LOG.log(Level.FINE, "addMetadataElement: Executing: "
+                    + addMetaElemSql);
+            statement.execute(addMetaElemSql);
+
+            String elementId = new String();
+
+            String getMetaIdSql = "SELECT MAX(element_id) AS max_id FROM elements";
+            LOG.log(Level.FINE, "addElement: Executing: " + getMetaIdSql);
+            rs = statement.executeQuery(getMetaIdSql);
+
+            while (rs.next()) {
+                elementId = String.valueOf(rs.getInt("max_id"));
+            }
+
+            element.setElementId(elementId);
+            conn.commit();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG
+                    .log(Level.WARNING, "Exception adding element "
+                            + element.getElementName() + ". Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback addElement transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new ValidationLayerException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#modifyElement(org.apache.oodt.cas.filemgr.structs.Element)
+     */
+    public void modifyElement(Element element) throws ValidationLayerException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String elementSql = "UPDATE elements SET element_name = '"
+                    + element.getElementName() + "', dc_element='"
+                    + element.getDCElement() + "', " + "element_description='"
+                    + element.getDescription() + "' WHERE " + "element_id = "
+                    + element.getElementId();
+
+            LOG.log(Level.FINE, "modifyElement: Executing: " + elementSql);
+            statement.execute(elementSql);
+            conn.commit();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception modifying element. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback modifyElement transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new ValidationLayerException(e.getMessage());
+        } finally {
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#removeElement(org.apache.oodt.cas.filemgr.structs.Element)
+     */
+    public void removeElement(Element element) throws ValidationLayerException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String deleteElementSql = "DELETE FROM elements WHERE element_id = "
+                    + element.getElementId();
+
+            LOG
+                    .log(Level.FINE, "removeElement: Executing: "
+                            + deleteElementSql);
+            statement.execute(deleteElementSql);
+            conn.commit();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception removing element. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback removeElement transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new ValidationLayerException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#addElementToProductType(org.apache.oodt.cas.filemgr.structs.ProductType,
+     *      org.apache.oodt.cas.filemgr.structs.Element)
+     */
+    public void addElementToProductType(ProductType type, Element element)
+            throws ValidationLayerException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String addMetaElemSql = "INSERT INTO product_type_element_map (product_type_id, element_id) VALUES(";
+
+            if (quoteFields) {
+                addMetaElemSql += "'" + type.getProductTypeId() + "',";
+            } else {
+                addMetaElemSql += type.getProductTypeId() + ",";
+            }
+            addMetaElemSql += " " + element.getElementId() + ")";
+
+            LOG.log(Level.FINE, "addElementToProductType: Executing: "
+                    + addMetaElemSql);
+            statement.execute(addMetaElemSql);
+            conn.commit();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception adding element "
+                    + element.getElementName() + " to product type "
+                    + type.getName() + " . Message: " + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback addElementToProductType transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new ValidationLayerException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#removeElementFromProductType(org.apache.oodt.cas.filemgr.structs.ProductType,
+     *      org.apache.oodt.cas.filemgr.structs.Element)
+     */
+    public void removeElementFromProductType(ProductType type, Element element)
+            throws ValidationLayerException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String deleteElemSql = "DELETE FROM product_type_element_map WHERE product_type_id = ";
+
+            if (quoteFields) {
+                deleteElemSql += "'" + type.getProductTypeId() + "'";
+            } else {
+                deleteElemSql += type.getProductTypeId();
+            }
+
+            deleteElemSql += " AND element_id = " + element.getElementId();
+
+            LOG.log(Level.FINE, "removeElementFromProductType: Executing: "
+                    + deleteElemSql);
+            statement.execute(deleteElemSql);
+            conn.commit();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception removing element "
+                    + element.getElementName() + " from product type "
+                    + type.getName() + ". Message: " + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback removeElementFromProductType transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new ValidationLayerException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    public void addParentToProductType(ProductType type, String parent)
+            throws ValidationLayerException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String addParentInfoSql = "INSERT INTO sub_to_super_map (product_type_id, parent_id) VALUES(";
+            if (quoteFields) {
+                addParentInfoSql += "'" + type.getProductTypeId() + "','"
+                        + parent + "')";
+            } else {
+                addParentInfoSql += type.getProductTypeId() + "," + parent
+                        + ")";
+            }
+
+            LOG.log(Level.FINE, "addParentToProductType: Executing: "
+                    + addParentInfoSql);
+            statement.execute(addParentInfoSql);
+            conn.commit();
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception adding parent info to product type "
+                            + type.getName() + " . Message: " + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback addParentToProductType transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new ValidationLayerException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+    }
+
+    public void removeParentFromProductType(ProductType type, String parent)
+            throws ValidationLayerException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String deleteParSql = "DELETE FROM sub_to_super_map WHERE product_type_id = ";
+
+            if (quoteFields) {
+                deleteParSql += "'" + type.getProductTypeId()
+                        + "' AND parent_id ='" + parent + "'";
+            } else {
+                deleteParSql += type.getProductTypeId() + " AND parent_id ="
+                        + parent;
+            }
+
+            LOG.log(Level.FINE, "removeParentFromProductType: Executing: "
+                    + deleteParSql);
+            statement.execute(deleteParSql);
+            conn.commit();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception removing parent from product type "
+                            + type.getName() + ". Message: " + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback removeParentFromProductType transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new ValidationLayerException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#getElements(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public List<Element> getElements(ProductType type)
+            throws ValidationLayerException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+        List<Element> elements = null;
+
+        elements = new Vector<Element>();
+
+        String currProduct = type.getProductTypeId();
+        while (currProduct != null) {
+
+            try {
+                conn = dataSource.getConnection();
+                statement = conn.createStatement();
+
+                String elementSql = "SELECT elements.* from elements, product_type_element_map WHERE product_type_element_map.product_type_id = ";
+
+                if (quoteFields) {
+                    elementSql += "'" + currProduct + "'";
+                } else {
+                    elementSql += currProduct;
+                }
+
+                elementSql += " AND product_type_element_map.element_id = elements.element_id";
+
+                LOG.log(Level.FINE, "getElements: Executing: " + elementSql);
+                rs = statement.executeQuery(elementSql);
+
+                while (rs.next()) {
+                    Element element = DbStructFactory.getElement(rs);
+                    elements.add(element);
+                }
+
+            } catch (Exception e) {
+                e.printStackTrace();
+                LOG.log(Level.WARNING, "Exception reading elements. Message: "
+                        + e.getMessage());
+                throw new ValidationLayerException(e.getMessage());
+            } finally {
+
+                if (rs != null) {
+                    try {
+                        rs.close();
+                    } catch (SQLException ignore) {
+                    }
+
+                    rs = null;
+                }
+
+                if (statement != null) {
+                    try {
+                        statement.close();
+                    } catch (SQLException ignore) {
+                    }
+
+                    statement = null;
+                }
+
+                if (conn != null) {
+                    try {
+                        conn.close();
+
+                    } catch (SQLException ignore) {
+                    }
+
+                    conn = null;
+                }
+            }
+
+            // advance to the product parent
+            try {
+                conn = dataSource.getConnection();
+                statement = conn.createStatement();
+
+                String getParentSql = "SELECT parent_id from sub_to_super_map where product_type_id = ";
+                if (quoteFields) {
+                    getParentSql += "'" + currProduct + "'";
+                } else {
+                    getParentSql += currProduct;
+                }
+
+                LOG.log(Level.FINE, "getElements: Executing: " + getParentSql);
+                rs = statement.executeQuery(getParentSql);
+
+                currProduct = null;
+                while (rs.next()) {
+                    currProduct = DbStructFactory.getParent(rs);
+                }
+
+            } catch (Exception e) {
+                e.printStackTrace();
+                LOG.log(Level.WARNING,
+                        "Exception reading product parent. Message: "
+                                + e.getMessage());
+                throw new ValidationLayerException(e.getMessage());
+            } finally {
+                if (rs != null) {
+                    try {
+                        rs.close();
+                    } catch (SQLException ignore) {
+                    }
+                    rs = null;
+                }
+                if (statement != null) {
+                    try {
+                        statement.close();
+                    } catch (SQLException ignore) {
+                    }
+                    statement = null;
+                }
+                if (conn != null) {
+                    try {
+                        conn.close();
+                    } catch (SQLException ignore) {
+                    }
+                    conn = null;
+                }
+            }
+
+        }
+
+        return elements;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#getElements()
+     */
+    public List<Element> getElements() throws ValidationLayerException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+        List<Element> elements = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String dataTypeSql = "SELECT * from elements";
+
+            LOG.log(Level.FINE, "getElements: Executing: " + dataTypeSql);
+            rs = statement.executeQuery(dataTypeSql);
+
+            elements = new Vector<Element>();
+
+            while (rs.next()) {
+                Element element = DbStructFactory.getElement(rs);
+                LOG.log(Level.FINE, "getElements: adding element: "
+                        + element.getElementName());
+                elements.add(element);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception reading elements. Message: "
+                    + e.getMessage());
+            throw new ValidationLayerException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return elements;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#getElementById(java.lang.String)
+     */
+    public Element getElementById(String elementId)
+            throws ValidationLayerException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+        Element element = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String elementSql = "SELECT * from elements WHERE element_id = "
+                    + elementId;
+
+            LOG.log(Level.FINE, "getElementById: Executing: " + elementSql);
+            rs = statement.executeQuery(elementSql);
+
+            while (rs.next()) {
+                element = DbStructFactory.getElement(rs);
+                LOG.log(Level.FINE, "getElementById: adding element: "
+                        + element.getElementName());
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception reading element. Message: "
+                    + e.getMessage());
+            throw new ValidationLayerException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return element;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#getElementByName(java.lang.String)
+     */
+    public Element getElementByName(String elementName)
+            throws ValidationLayerException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+        Element element = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String elementSql = "SELECT * from elements WHERE element_name = "
+                    + elementName;
+
+            LOG.log(Level.FINE, "getElementByName: Executing: " + elementSql);
+            rs = statement.executeQuery(elementSql);
+
+            while (rs.next()) {
+                element = DbStructFactory.getElement(rs);
+                LOG.log(Level.FINE, "getElementByName: adding element: "
+                        + element.getElementName());
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception reading element. Message: "
+                    + e.getMessage());
+            throw new ValidationLayerException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return element;
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/DataSourceValidationLayerFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/DataSourceValidationLayerFactory.java
new file mode 100644
index 0000000..ee9547f
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/DataSourceValidationLayerFactory.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.validation;
+
+//OODT imports
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+
+//JDK imports
+import javax.sql.DataSource;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory class for creating {@link DataSourceValidationLayer}s.
+ * </p>
+ * 
+ */
+public class DataSourceValidationLayerFactory implements ValidationLayerFactory {
+    /* our data source */
+    private DataSource dataSource = null;
+
+    /* should we quote fields or not? */
+    private boolean quoteFields = false;
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>
+     */
+    public DataSourceValidationLayerFactory() throws Exception {
+        String jdbcUrl = null, user = null, pass = null, driver = null;
+
+        jdbcUrl = System
+                .getProperty("org.apache.oodt.cas.filemgr.validation.datasource.jdbc.url");
+        user = System
+                .getProperty("org.apache.oodt.cas.filemgr.validation.datasource.jdbc.user");
+        pass = System
+                .getProperty("org.apache.oodt.cas.filemgr.validation.datasource.jdbc.pass");
+        driver = System
+                .getProperty("org.apache.oodt.cas.filemgr.validation.datasource.jdbc.driver");
+
+        dataSource = DatabaseConnectionBuilder.buildDataSource(user, pass,
+                driver, jdbcUrl);
+        quoteFields = Boolean
+                .getBoolean("org.apache.oodt.cas.filemgr.validation.datasource.quoteFields");
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayerFactory#createValidationLayer()
+     */
+    public ValidationLayer createValidationLayer() {
+        return new DataSourceValidationLayer(dataSource, quoteFields);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/ScienceDataValidationLayer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/ScienceDataValidationLayer.java
new file mode 100644
index 0000000..18f003e
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/ScienceDataValidationLayer.java
@@ -0,0 +1,480 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.validation;
+
+//JDK imports
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+import java.util.Vector;
+import javax.sql.DataSource;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.catalog.ScienceDataCatalog;
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.filemgr.util.DbStructFactory;
+
+/**
+ * 
+ * Determines the mapping of {@Element}s to {@link ProductType}s by
+ * reading the {@link ScienceDataCatalog} catalog schema tables concerning parameters and datasets.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ScienceDataValidationLayer implements ValidationLayer {
+
+  private DataSource ds;
+
+  public ScienceDataValidationLayer(DataSource ds) {
+    this.ds = ds;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.validation.ValidationLayer#addElement(gov
+   * .nasa.jpl.oodt.cas.filemgr.structs.Element)
+   */
+  public void addElement(Element element) throws ValidationLayerException {
+    String sql = "INSERT INTO parameter (dataset_id, longName, shortName, description) "
+        + "VALUES (-1, '"
+        + element.getElementName()
+        + "','"
+        + element.getElementName() + "', '" + element.getDescription() + "')";
+    Connection conn = null;
+    Statement statement = null;
+
+    try {
+      conn = ds.getConnection();
+      statement = conn.createStatement();
+      statement.execute(sql);
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @seeorg.apache.oodt.cas.filemgr.validation.ValidationLayer#
+   * addElementToProductType(org.apache.oodt.cas.filemgr.structs.ProductType,
+   * org.apache.oodt.cas.filemgr.structs.Element)
+   */
+  public void addElementToProductType(ProductType productType, Element element)
+      throws ValidationLayerException {
+    String sql = "INSERT INTO dpMap (dataset_id, parameter_id) VALUES ("
+        + productType.getProductTypeId() + ", " + element.getElementId() + ")";
+    Connection conn = null;
+    Statement statement = null;
+
+    try {
+      conn = ds.getConnection();
+      statement = conn.createStatement();
+      statement.execute(sql);
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.validation.ValidationLayer#getElementById
+   * (java.lang.String)
+   */
+  public Element getElementById(String elementId)
+      throws ValidationLayerException {
+    String sql = "SELECT parameter_id, shortName, description from parameter WHERE parameter_id = "
+        + elementId;
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    Element element = null;
+
+    try {
+      conn = ds.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        element = DbStructFactory.toScienceDataElement(rs);
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+    return element;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.validation.ValidationLayer#getElementByName
+   * (java.lang.String)
+   */
+  public Element getElementByName(String elementName)
+      throws ValidationLayerException {
+    String sql = "SELECT parameter_id, shortName, description from parameter WHERE shortName = '"
+        + elementName + "'";
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    Element element = null;
+
+    try {
+      conn = ds.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        element = DbStructFactory.toScienceDataElement(rs);
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+    return element;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#getElements()
+   */
+  public List<Element> getElements() throws ValidationLayerException {
+    String sql = "SELECT parameter_id, shortName, description from parameter ORDER by parameter_id DESC";
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    List<Element> elements = new Vector<Element>();
+
+    try {
+      conn = ds.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        elements.add(DbStructFactory.toScienceDataElement(rs));
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+    return elements;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.validation.ValidationLayer#getElements(gov
+   * .nasa.jpl.oodt.cas.filemgr.structs.ProductType)
+   */
+  public List<Element> getElements(ProductType productType) {
+    String sql = "SELECT parameter_id, shortName, description from parameter WHERE dataset_id = "
+        + productType.getProductTypeId() + " ORDER by parameter_id DESC";
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    List<Element> elements = new Vector<Element>();
+
+    try {
+      conn = ds.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sql);
+      while (rs.next()) {
+        elements.add(DbStructFactory.toScienceDataElement(rs));
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (Exception ignore) {
+        }
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+    return elements;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.validation.ValidationLayer#modifyElement(
+   * org.apache.oodt.cas.filemgr.structs.Element)
+   */
+  public void modifyElement(Element element) throws ValidationLayerException {
+    String sql = "UPDATE parameter SET longName='" + element.getElementName()
+        + "', shortName='" + element.getElementName() + "',description='"
+        + element.getDescription() + "' WHERE parameter_id = "
+        + element.getElementId();
+
+    Connection conn = null;
+    Statement statement = null;
+
+    try {
+      conn = ds.getConnection();
+      statement = conn.createStatement();
+      statement.execute(sql);
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.validation.ValidationLayer#removeElement(
+   * org.apache.oodt.cas.filemgr.structs.Element)
+   */
+  public void removeElement(Element element) throws ValidationLayerException {
+    String sql = "DELETE FROM parameter WHERE parameter_id = "
+        + element.getElementId();
+
+    Connection conn = null;
+    Statement statement = null;
+
+    try {
+      conn = ds.getConnection();
+      statement = conn.createStatement();
+      statement.execute(sql);
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @seeorg.apache.oodt.cas.filemgr.validation.ValidationLayer#
+   * removeElementFromProductType
+   * (org.apache.oodt.cas.filemgr.structs.ProductType,
+   * org.apache.oodt.cas.filemgr.structs.Element)
+   */
+  public void removeElementFromProductType(ProductType productType,
+      Element element) throws ValidationLayerException {
+    String sql = "DELETE FROM dpMap WHERE parameter_id = "
+        + element.getElementId() + " and dataset_id = "
+        + productType.getProductTypeId();
+
+    Connection conn = null;
+    Statement statement = null;
+
+    try {
+      conn = ds.getConnection();
+      statement = conn.createStatement();
+      statement.execute(sql);
+    } catch (SQLException e) {
+      e.printStackTrace();
+    } finally {
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+        conn = null;
+      }
+
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/ScienceDataValidationLayerFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/ScienceDataValidationLayerFactory.java
new file mode 100644
index 0000000..48f343e
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/ScienceDataValidationLayerFactory.java
@@ -0,0 +1,72 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.validation;
+
+//JDK imports
+import javax.sql.DataSource;
+
+//OODT imports
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayerFactory;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+/**
+ * 
+ * Constructs new {@link ScienceDataValidationLayer}s.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ScienceDataValidationLayerFactory implements
+    ValidationLayerFactory {
+
+  private DataSource dataSource;
+
+  public ScienceDataValidationLayerFactory() {
+    String jdbcUrl = null, user = null, pass = null, driver = null;
+
+    jdbcUrl = PathUtils
+        .replaceEnvVariables(System
+            .getProperty("org.apache.oodt.cas.filemgr.validation.science.jdbc.url"));
+    user = PathUtils
+        .replaceEnvVariables(System
+            .getProperty("org.apache.oodt.cas.filemgr.validation.science.jdbc.user"));
+    pass = PathUtils
+        .replaceEnvVariables(System
+            .getProperty("org.apache.oodt.cas.filemgr.validation.science.jdbc.pass"));
+    driver = PathUtils
+        .replaceEnvVariables(System
+            .getProperty("org.apache.oodt.cas.filemgr.validation.science.jdbc.driver"));
+
+    this.dataSource = DatabaseConnectionBuilder.buildDataSource(user, pass,
+        driver, jdbcUrl);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @seeorg.apache.oodt.cas.filemgr.validation.ValidationLayerFactory#
+   * createValidationLayer()
+   */
+  public ValidationLayer createValidationLayer() {
+    return new ScienceDataValidationLayer(this.dataSource);
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/ValidationLayer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/ValidationLayer.java
new file mode 100644
index 0000000..a901bc2
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/ValidationLayer.java
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.validation;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+
+//JDK imports
+import java.util.List;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The Validation Layer for the File Manager, allowing {@link Element}s to be
+ * mapped to {@link ProductType}s.
+ * </p>
+ * 
+ */
+public interface ValidationLayer {
+
+    /**
+     * <p>
+     * Adds the <code>Element</code> to the ValidationLayer.
+     * </p>
+     * 
+     * @param element
+     *            The element to add.
+     * @throws ValidationLayerException
+     *             If any error occurs during the add.
+     */
+    public void addElement(Element element) throws ValidationLayerException;
+
+    /**
+     * <p>
+     * Modifies an existing {@link Element} in the ValidationLayer.
+     * </p>
+     * 
+     * @param element
+     *            The new {@link Element} data to update.
+     * @throws ValidationLayerException
+     *             If any error occurs.
+     */
+    public void modifyElement(Element element) throws ValidationLayerException;
+
+    /**
+     * <p>
+     * Removes a metadata {@link Element} from the ValidationLayer.
+     * 
+     * @param element
+     *            The element to remove.
+     * @throws ValidationLayerException
+     *             If any error occurs.
+     */
+    public void removeElement(Element element) throws ValidationLayerException;
+
+    /**
+     * <p>
+     * Adds the specified <code>element</code> to the {@link ProductType}
+     * specified by its <code>productTypeId</code>.
+     * 
+     * @param type
+     *            The {@link ProductType} to associate the metadata Element
+     *            with.
+     * @param element
+     *            The {@link Element} to associate with the ProductType.
+     * @throws ValidationLayerException
+     *             If any error occurs.
+     */
+    public void addElementToProductType(ProductType type, Element element)
+            throws ValidationLayerException;
+
+    /**
+     * <p>
+     * Removes a metadata {@link Element} from the specified
+     * <code>productTypeId</code>.
+     * </p>
+     * 
+     * @param type
+     *            The {@link ProductType} to remove the association of the
+     *            specified <code>element</code> with.
+     * @param element
+     *            The element whose association will be removed from the
+     *            specified ProductType.
+     * @throws ValidationLayerException
+     *             If any error occurs.
+     */
+    public void removeElementFromProductType(ProductType type, Element element)
+            throws ValidationLayerException;
+
+    /**
+     * <p>
+     * Returns a {@link List} of {@link Element}s corresponding to the given
+     * ProductType.
+     * 
+     * @param type
+     *            The product type to retrieve the metadata {@link Element}s
+     *            for.
+     * @return A {@link List} of {@link Element}s corresponding to the given
+     *         ProductType.
+     * @throws ValidationLayerException
+     *             If any error occurs.
+     */
+    public List<Element> getElements(ProductType type)
+            throws ValidationLayerException;
+
+    /**
+     * @return A {@link List} of all the metadata {@link Element}s in the
+     *         ValidationLayer.
+     * @throws ValidationLayerException
+     *             If any error occurs.
+     */
+    public List<Element> getElements() throws ValidationLayerException;
+
+    /**
+     * Gets an element by its String identifier.
+     * 
+     * @param elementId
+     *            The String identifier of the {@link Element} to get.
+     * @return An {@link Element} by its String identifier.
+     * @throws ValidationLayerException
+     *             If any error occurs.
+     */
+    public Element getElementById(String elementId)
+            throws ValidationLayerException;
+
+    /**
+     * Gets an element by its String name.
+     * 
+     * @param elementName
+     *            The String name of the {@link Element} to get.
+     * @return An {@link Element} by its String name.
+     * @throws ValidationLayerException
+     *             If any error occurs.
+     */
+    public Element getElementByName(String elementName)
+            throws ValidationLayerException;
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/ValidationLayerFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/ValidationLayerFactory.java
new file mode 100644
index 0000000..73b89ff
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/ValidationLayerFactory.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.validation;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory for creating {@link ValidationLayer}s.
+ * </p>
+ * 
+ */
+public interface ValidationLayerFactory {
+
+    public ValidationLayer createValidationLayer();
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/XMLValidationLayer.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/XMLValidationLayer.java
new file mode 100644
index 0000000..d6e427b
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/XMLValidationLayer.java
@@ -0,0 +1,501 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.validation;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+import org.apache.oodt.cas.filemgr.util.XmlStructFactory;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * An XML ValidationLayer based on two xml files, <code>elements.xml</code>,
+ * and <code>product-type-element-map.xml</code>.
+ * </p>
+ * 
+ */
+public class XMLValidationLayer implements ValidationLayer {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(XMLValidationLayer.class
+            .getName());
+
+    /* product type ID to element map */
+    private HashMap<String, List<Element>> productTypeElementMap = new HashMap<String, List<Element>>();
+
+    /* sub-type to super-type map */
+    private HashMap<String, String> subToSuperMap = new HashMap<String, String>();
+
+    /* element map */
+    private HashMap<String, Element> elementMap = new HashMap<String, Element>();
+
+    /*
+     * URIs pointing to directories with product-type-element-map.xml and
+     * elements.xml files
+     */
+    private List<String> xmlFileDirUris = null;
+
+    /**
+     * 
+     */
+    public XMLValidationLayer(List<String> uris) {
+        this.xmlFileDirUris = uris;
+        loadElements(xmlFileDirUris);
+        loadProductTypeMap(xmlFileDirUris);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#addElement(org.apache.oodt.cas.filemgr.structs.Element)
+     */
+    public void addElement(Element element) throws ValidationLayerException {
+        elementMap.put(element.getElementId(), element);
+        saveElementsAndMappings();
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#modifyElement(org.apache.oodt.cas.filemgr.structs.Element)
+     */
+    public void modifyElement(Element element) throws ValidationLayerException {
+        for(Element elem: elementMap.values()){
+           if(elem.getElementId().equals(element.getElementId())){
+             elem.setElementName(element.getElementName());
+             elem.setDescription(elem.getDescription());
+             elem.setDCElement(element.getDCElement());
+           }
+        }
+        saveElementsAndMappings();
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#removeElement(org.apache.oodt.cas.filemgr.structs.Element)
+     */
+    public void removeElement(Element element) throws ValidationLayerException {
+        elementMap.remove(element.getElementId());
+        saveElementsAndMappings();
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#addElementToProductType(org.apache.oodt.cas.filemgr.structs.ProductType,
+     *      org.apache.oodt.cas.filemgr.structs.Element)
+     */
+    public void addElementToProductType(ProductType type, Element element)
+            throws ValidationLayerException {
+        List<Element> elements = productTypeElementMap.get(type
+                .getProductTypeId());
+
+        if (elements == null) {
+            elements = new Vector<Element>();
+            productTypeElementMap.put(type.getProductTypeId(), elements);
+        }
+        elements.add(element);
+        saveElementsAndMappings();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#removeElementFromProductType(org.apache.oodt.cas.filemgr.structs.ProductType,
+     *      org.apache.oodt.cas.filemgr.structs.Element)
+     */
+    public void removeElementFromProductType(ProductType type, Element element)
+            throws ValidationLayerException {
+        List<Element> elements = productTypeElementMap.get(type
+                .getProductTypeId());
+
+        for (Iterator<Element> i = elements.iterator(); i.hasNext();) {
+            Element elementObj = i.next();
+            if (elementObj.getElementId().equals(element.getElementId())) {
+                elements.remove(elementObj);
+                saveElementsAndMappings();
+                break;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#getElements(org.apache.oodt.cas.filemgr.structs.ProductType)
+     */
+    public List<Element> getElements(ProductType type)
+            throws ValidationLayerException {
+    	return this.getElements(type, false);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#getElements()
+     */
+    public List<Element> getElements() throws ValidationLayerException {
+        return Arrays.asList(elementMap.values().toArray(
+                new Element[elementMap.size()]));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#getElementById(java.lang.String)
+     */
+    public Element getElementById(String elementId)
+            throws ValidationLayerException {
+        return elementMap.get(elementId);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayer#getElementByName(java.lang.String)
+     */
+    public Element getElementByName(String elementName)
+            throws ValidationLayerException {
+        for (Iterator<String> i = elementMap.keySet().iterator(); i.hasNext();) {
+            String elementId = i.next();
+            Element element = (Element) elementMap.get(elementId);
+            if (element.getElementName().equals(elementName)) {
+                return element;
+            }
+        }
+
+        return null;
+
+    }
+    
+    /**
+     * Returns the declared elements for a {@link ProductType}
+     * @param type The {@link ProductType} to get the elements for
+     * @param direct If false, return elements of the parent product types as well
+     * @return A list of all {@link Element} of the Product type
+     * @throws ValidationLayerException
+     * 				If any error occurs
+     */
+    public List<Element> getElements(ProductType type, boolean direct)
+            throws ValidationLayerException {
+        List<Element> elems = new Vector<Element>();
+        String currType = type.getProductTypeId();
+        if (productTypeElementMap.containsKey(currType)) {
+            elems.addAll(productTypeElementMap.get(currType));
+        }
+
+        if(!direct) {
+	        while (subToSuperMap.containsKey(currType)) {
+	            currType = subToSuperMap.get(currType);
+	            if (productTypeElementMap.containsKey(currType)) {
+	                elems.addAll(productTypeElementMap.get(currType));
+	            }
+	        }
+        }
+
+        return elems;
+    }
+    
+    /**
+     * Gets the parent-child relationship between product types
+     * 
+     * @return HashMap of {@link ProductType} ids mapped to their parent id
+     */
+    public HashMap<String, String> getSubToSuperMap() {
+    	return subToSuperMap;
+    }
+    
+    /**
+     * Sets a parentId for an existing {@link ProductType}
+     * @param type The {@link ProductType} to add a parent for
+     * @param parentId The id of the parent {@link ProductType}
+     * @throws ValidationLayerException
+     * 				If any error occurs
+     */
+    public void addParentForProductType(ProductType type, String parentId)
+            throws ValidationLayerException {
+        subToSuperMap.put(type.getProductTypeId(), parentId);
+        saveElementsAndMappings();
+    }
+
+    /**
+     * Removes the parent for a {@link ProductType}
+     * @param type The {@link ProductType} to remove the parent from
+     * @throws ValidationLayerException
+     * 				If any error occurs
+     */
+    public void removeParentForProductType(ProductType type)
+            throws ValidationLayerException {
+        subToSuperMap.remove(type.getProductTypeId());
+        saveElementsAndMappings();
+    }
+    
+
+    private void saveElementsAndMappings() {
+        for (Iterator<String> i = xmlFileDirUris.iterator(); i.hasNext();) {
+            String dirUri = i.next();
+            File elementDir = null;
+
+            try {
+                elementDir = new File(new URI(dirUri));
+
+                if (!elementDir.isDirectory()) {
+                    LOG
+                            .log(
+                                    Level.WARNING,
+                                    "Element directory: "
+                                            + dirUri
+                                            + " is not "
+                                            + "a directory: skipping element and product type map saving to it.");
+                    continue;
+                }
+
+                String elementDirStr = elementDir.getAbsolutePath();
+                if (!elementDirStr.endsWith("/")) {
+                    elementDirStr += "/";
+                }
+
+                String elementXmlFile = elementDirStr + "elements.xml";
+
+                String productTypeMapXmlFile = elementDirStr
+                        + "product-type-element-map.xml";
+
+                XmlStructFactory.writeElementXmlDocument(Arrays
+                        .asList(elementMap.values().toArray(
+                                new Element[elementMap.size()])),
+                        elementXmlFile);
+
+                XmlStructFactory.writeProductTypeMapXmLDocument(
+                        productTypeElementMap, subToSuperMap,
+                        productTypeMapXmlFile);
+
+            } catch (URISyntaxException e) {
+                LOG
+                        .log(
+                                Level.WARNING,
+                                "URISyntaxException when saving element "
+                                        + "directory URI: "
+                                        + dirUri
+                                        + ": Skipping Element and Product Type map saving"
+                                        + "for it: Message: " + e.getMessage());
+                continue;
+            }
+
+        }
+
+    }
+
+    private void loadElements(List<String> dirUris) {
+        for (Iterator<String> i = dirUris.iterator(); i.hasNext();) {
+            File elementDir = null;
+            String dirUri = i.next();
+
+            try {
+                elementDir = new File(new URI(dirUri));
+
+                if (!elementDir.isDirectory()) {
+                    LOG.log(Level.WARNING, "Element directory: " + dirUri
+                            + " is not "
+                            + "a directory: skipping element loading from it.");
+                    continue;
+                }
+
+                String elementDirStr = elementDir.getAbsolutePath();
+                if (!elementDirStr.endsWith("/")) {
+                    elementDirStr += "/";
+                }
+
+                String elementXmlFile = elementDirStr + "elements.xml";
+                Document elementDoc = getDocumentRoot(elementXmlFile);
+
+                org.w3c.dom.Element elementRootElem = elementDoc
+                        .getDocumentElement();
+
+                NodeList elementNodeList = elementRootElem
+                        .getElementsByTagName("element");
+
+                if (elementNodeList != null && elementNodeList.getLength() > 0) {
+                    for (int j = 0; j < elementNodeList.getLength(); j++) {
+                        Node elementNode = elementNodeList.item(j);
+                        Element element = XmlStructFactory
+                                .getElement(elementNode);
+                        elementMap.put(element.getElementId(), element);
+                    }
+                }
+
+            } catch (URISyntaxException e) {
+                LOG.log(Level.WARNING,
+                        "URISyntaxException when loading element "
+                                + "directory URI: " + dirUri
+                                + ": Skipping element loading"
+                                + "for it: Message: " + e.getMessage());
+                continue;
+            }
+        }
+    }
+
+    private void loadProductTypeMap(List<String> dirUris) {
+        for (Iterator<String> i = dirUris.iterator(); i.hasNext();) {
+            File elementDir = null;
+            String dirUri = i.next();
+
+            try {
+                elementDir = new File(new URI(dirUri));
+
+                if (!elementDir.isDirectory()) {
+                    LOG
+                            .log(
+                                    Level.WARNING,
+                                    "Element directory: "
+                                            + dirUri
+                                            + " is not "
+                                            + "a directory: skipping product type element map loading from it.");
+                    continue;
+                }
+
+                String elementDirStr = elementDir.getAbsolutePath();
+                if (!elementDirStr.endsWith("/")) {
+                    elementDirStr += "/";
+                }
+
+                String productTypeMapXmlFile = elementDirStr
+                        + "product-type-element-map.xml";
+                Document productTypeMapDoc = getDocumentRoot(productTypeMapXmlFile);
+
+                org.w3c.dom.Element mapRootElem = productTypeMapDoc
+                        .getDocumentElement();
+
+                NodeList typeNodeList = mapRootElem
+                        .getElementsByTagName("type");
+
+                if (typeNodeList != null && typeNodeList.getLength() > 0) {
+                    for (int j = 0; j < typeNodeList.getLength(); j++) {
+                        org.w3c.dom.Element typeElement = (org.w3c.dom.Element) typeNodeList
+                                .item(j);
+                        String typeId = typeElement.getAttribute("id");
+
+                        // get inheritance info
+                        String typeParent = typeElement.getAttribute("parent");
+                        if (typeParent != null) {
+                            subToSuperMap.put(typeId, typeParent);
+                        }
+
+                        // get its element list
+                        NodeList elementIdNodeList = typeElement
+                                .getElementsByTagName("element");
+
+                        // allow for 0 sized element list
+                        List<Element> productTypeElementList = new Vector<Element>();
+
+                        if (elementIdNodeList != null
+                                && elementIdNodeList.getLength() > 0) {
+                            productTypeElementList = new Vector<Element>(
+                                    elementIdNodeList.getLength());
+                            for (int k = 0; k < elementIdNodeList.getLength(); k++) {
+                                org.w3c.dom.Element elementIdElement = (org.w3c.dom.Element) elementIdNodeList
+                                        .item(k);
+                                String elementId = elementIdElement
+                                        .getAttribute("id");
+
+                                if (elementMap.get(elementId) != null) {
+                                    productTypeElementList.add(elementMap
+                                            .get(elementId));
+                                }
+                            }
+                        }
+
+                        productTypeElementMap.put(typeId,
+                                productTypeElementList);
+                    }
+                }
+
+            } catch (URISyntaxException e) {
+                LOG.log(Level.WARNING,
+                        "URISyntaxException when loading element "
+                                + "directory URI: " + dirUri
+                                + ": Skipping product type map loading"
+                                + "for it: Message: " + e.getMessage());
+                continue;
+            }
+        }
+    }
+
+    private Document getDocumentRoot(String xmlFile) {
+        // open up the XML file
+        DocumentBuilderFactory factory = null;
+        DocumentBuilder parser = null;
+        Document document = null;
+        InputSource inputSource = null;
+
+        InputStream xmlInputStream = null;
+
+        try {
+            xmlInputStream = new File(xmlFile).toURL().openStream();
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when getting input stream from [" + xmlFile
+                            + "]: returning null document root");
+            return null;
+        }
+
+        inputSource = new InputSource(xmlInputStream);
+
+        try {
+            factory = DocumentBuilderFactory.newInstance();
+            parser = factory.newDocumentBuilder();
+            document = parser.parse(inputSource);
+        } catch (Exception e) {
+            LOG.warning("Unable to parse xml file [" + xmlFile + "]."
+                    + "Reason is [" + e + "]");
+            return null;
+        }
+
+        return document;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/XMLValidationLayerFactory.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/XMLValidationLayerFactory.java
new file mode 100644
index 0000000..26d3c83
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/validation/XMLValidationLayerFactory.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.validation;
+
+//JDk imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory class for creating XMLValidationLayer objects.
+ * </p>
+ * 
+ */
+public class XMLValidationLayerFactory implements ValidationLayerFactory {
+
+    /*
+     * list of dir uris specifying file paths to elements and product type map
+     * directories
+     */
+    private List<String> dirList = null;
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     */
+    public XMLValidationLayerFactory() {
+        String dirUris = System
+                .getProperty("org.apache.oodt.cas.filemgr.validation.dirs");
+
+        if (dirUris != null) {
+            dirUris = PathUtils.replaceEnvVariables(dirUris);
+            String[] dirUriList = dirUris.split(",");
+            dirList = Arrays.asList(dirUriList);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.validation.ValidationLayerFactory#createValidationLayer()
+     */
+    public ValidationLayer createValidationLayer() {
+        return new XMLValidationLayer(dirList);
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/AcquisitionDateVersioner.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/AcquisitionDateVersioner.java
new file mode 100644
index 0000000..9f6dee9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/AcquisitionDateVersioner.java
@@ -0,0 +1,105 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//JDK imports
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+/**
+ * 
+ * Store products under /[AcquisitionDate]/[Filename].
+ * 
+ * Assumes the existence of:
+ * 
+ * <pre>
+ *   &lt;code&gt;AcquisitionDate&lt;/code&gt; - if present, takes as is, and assumes 
+ *   it is in the yyMMdd format.&lt;br/&gt;
+ *   &lt;code&gt;StartDateTime&lt;/code&gt; - if present, assumes it is in yyyy-MM-ddTHH:mm:ss.000Z, 
+ *   or ISO8601 format, reformats it to yyMMdd, and then uses it for the value
+ *   of &lt;code&gt;AcquisitionDate&lt;/code&gt;&lt;br/&gt;
+ * </pre>
+ * 
+ * If neither of the above met fields are present, the Versioner will generate a
+ * new DateTime, and use the value of it (formatted as yyMMdd) for the
+ * AcquisitionDate.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class AcquisitionDateVersioner extends MetadataBasedFileVersioner {
+
+  private String filePathSpec = "/[AcquisitionDate]/[Filename]";
+
+  protected final static String ACQUISITION_DATE = "AcquisitionDate";
+
+  protected static String ACQ_DATE_FORMAT = "yyMMdd";
+
+  protected final static String START_DATE_TIME = "StartDateTime";
+
+  public AcquisitionDateVersioner() {
+    setFilePathSpec(filePathSpec);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.filemgr.versioning.MetadataBasedFileVersioner#
+   * createDataStoreReferences(org.apache.oodt.cas.filemgr.structs.Product,
+   * org.apache.oodt.cas.metadata.Metadata)
+   */
+  @Override
+  public void createDataStoreReferences(Product product, Metadata metadata)
+      throws VersioningException {
+
+    // compute AcquisitionDate
+    // grab CAS.ProductReceivedTime
+    // parse it as an ISO8601 date
+    // then reformat and add using ACQ_DATE_FORMAT
+    if (metadata.getMetadata(ACQUISITION_DATE) == null) {
+      SimpleDateFormat acqDateFormatter = new SimpleDateFormat(ACQ_DATE_FORMAT);
+      acqDateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
+      Date casProdReceivedTime = new Date();
+      if (metadata.getMetadata(START_DATE_TIME) != null) {
+        try {
+          metadata.replaceMetadata(ACQUISITION_DATE, PathUtils
+              .doDynamicReplacement("[FORMAT(yyyy-MM-dd'T'HH:mm:ss.SSS'Z',"
+                  + metadata.getMetadata(START_DATE_TIME) + ","
+                  + ACQ_DATE_FORMAT + ")]"));
+        } catch (Exception e) {
+          throw new VersioningException("Failed to parse StartDateTime : "
+              + e.getMessage(), e);
+        }
+      } else {
+        metadata.replaceMetadata(ACQUISITION_DATE, acqDateFormatter
+            .format(casProdReceivedTime));
+      }
+    }
+
+    super.createDataStoreReferences(product, metadata);
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/BasicVersioner.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/BasicVersioner.java
new file mode 100644
index 0000000..4d1695e
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/BasicVersioner.java
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//JDK imports
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.net.MalformedURLException;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A basic versioner that doesn't do anything special: it just creates data
+ * store refs from product refs using the product name and product repo path.
+ * </p>
+ * 
+ */
+public class BasicVersioner implements Versioner {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(BasicVersioner.class.getName());
+
+    /**
+     * 
+     */
+    public BasicVersioner() {
+        super();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.versioning.Versioner#createDataStoreReferences(org.apache.oodt.cas.data.structs.Product)
+     */
+    public void createDataStoreReferences(Product product, Metadata metadata)
+            throws VersioningException {
+
+        String productName = product.getProductName();
+        String productRepoPath = product.getProductType()
+                .getProductRepositoryPath();
+
+        if (product.getProductStructure()
+                .equals(Product.STRUCTURE_HIERARCHICAL)) {
+
+            if (product.getProductReferences() == null
+                    || (product.getProductReferences() != null && product
+                            .getProductReferences().size() == 0)) {
+                throw new VersioningException(
+                        "Hierarchical product and references not set!");
+            }
+
+            // get the first reference, it tells us what directory to move it
+            // to
+            // TODO: fix that hack :-)
+            Reference r = (Reference) product.getProductReferences().get(0);
+
+            String dataStoreRef = null;
+
+            try {
+                dataStoreRef = new File(new URI(productRepoPath)).toURL()
+                        .toExternalForm();
+                if(!dataStoreRef.endsWith("/")){
+                  dataStoreRef+="/";
+                }
+                
+                dataStoreRef+= URLEncoder.encode(productName, "UTF-8") + "/";
+                LOG.log(Level.INFO, "BasicVersioner: generated DataStore ref: "
+                        + dataStoreRef + " from origRef: "
+                        + r.getOrigReference());
+                r.setDataStoreReference(dataStoreRef);
+                VersioningUtils.createBasicDataStoreRefsHierarchical(product
+                        .getProductReferences());
+            } catch (URISyntaxException e) {
+                LOG.log(Level.WARNING,
+                        "BasicVersioner: URISyntaxException while generating initial "
+                                + "data store ref for origRef: "
+                                + r.getOrigReference());
+                throw new VersioningException(e);
+            } catch (MalformedURLException e) {
+                LOG.log(Level.WARNING,
+                        "BasicVersioner: MalformedURLException while generating initial "
+                                + "data store ref for origRef: "
+                                + r.getOrigReference());
+                throw new VersioningException(e);
+            } catch (UnsupportedEncodingException e) {
+                LOG.log(Level.WARNING,
+                        "BasicVersioner: UnsupportedEncodingException while generating "
+                                + "initial data store ref for origRef: "
+                                + r.getOrigReference());
+                throw new VersioningException(e);
+            }
+
+        } else if (product.getProductStructure().equals(Product.STRUCTURE_FLAT)) {
+            // just use the VersioningUtils
+            VersioningUtils.createBasicDataStoreRefsFlat(productName,
+                    productRepoPath, product.getProductReferences());
+        } else if (product.getProductStructure().equals(Product.STRUCTURE_STREAM)) {
+            VersioningUtils.createBasicDataStoreRefsStream(productName,
+                    productRepoPath, product.getProductReferences(),"");
+        } else {
+            throw new VersioningException("Unsupported product structure: "
+                    + product.getProductStructure());
+        }
+
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/ConfigurableMetadataBasedFileVersioner.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/ConfigurableMetadataBasedFileVersioner.java
new file mode 100644
index 0000000..69a6596
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/ConfigurableMetadataBasedFileVersioner.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.versioning;
+
+// JDK imports
+import java.util.Properties;
+
+// OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+// Google imports
+import com.google.common.base.Strings;
+
+/**
+ * A {@link MetadataBasedFileVersioner} which is configurable via java properties.  Set the
+ * following java property to configure file_spec per product type:
+ *    org.apache.oodt.cas.filemgr.versioning.configuration.<product_type_name>
+ * Or set the following java property to configure all product types:
+ *    org.apache.oodt.cas.filemgr.versioning.configuration.all_product_types
+ * 
+ * @author bfoster@apache.org (Brian Foster)
+ */
+public class ConfigurableMetadataBasedFileVersioner extends MetadataBasedFileVersioner {
+
+  private static final String BASE_PROPERTY =
+      "org.apache.oodt.cas.filemgr.versioning.configuration.";
+  private static final String ALL = "all_product_types";
+
+  private final Properties properties;
+
+  public ConfigurableMetadataBasedFileVersioner() {
+    this(System.getProperties());
+  }
+
+  public ConfigurableMetadataBasedFileVersioner(Properties properties) {
+    this.properties = properties;
+  }
+
+  @Override
+  public void createDataStoreReferences(Product product, Metadata metadata)
+      throws VersioningException {
+    setFilePathSpec(getFilePathSpec(product.getProductType()));
+    super.createDataStoreReferences(product, metadata);
+  }
+
+  private String getFilePathSpec(ProductType productType) throws VersioningException {
+    String fileSpec = properties.getProperty(BASE_PROPERTY + productType.getName().toLowerCase());
+    if (Strings.isNullOrEmpty(fileSpec)) {
+      fileSpec = properties.getProperty(BASE_PROPERTY + ALL);
+      if (Strings.isNullOrEmpty(fileSpec)) {
+        throw new VersioningException("Not defined for product type " + productType.getName());
+      }
+    }
+    return fileSpec;
+  }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/DateTimeVersioner.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/DateTimeVersioner.java
new file mode 100644
index 0000000..b07bfab
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/DateTimeVersioner.java
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.commons.util.DateConvert;
+
+//JDK imports
+import java.text.SimpleDateFormat;
+import java.text.ParseException;
+import java.util.Iterator;
+import java.util.Date;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.MalformedURLException;
+import java.net.URLEncoder;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A simple versioning scheme that versions {@link Product}s with their
+ * production date time.
+ * </p>
+ * 
+ */
+public class DateTimeVersioner implements Versioner {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(DateTimeVersioner.class.getName());
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>
+     */
+    public DateTimeVersioner() {
+        super();
+        // TODO Auto-generated constructor stub
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.versioning.Versioner#createDataStoreReferences(org.apache.
+     *      oodt.cas.data.structs.Product)
+     */
+    public void createDataStoreReferences(Product product, Metadata metadata)
+            throws VersioningException {
+        // first, we need to know if its heirarchical, or flat
+        if (product.getProductStructure() == null) {
+            LOG
+                    .log(Level.WARNING,
+                            "DateTimeVersioner: Product Structure must be defined in order to version!");
+            return;
+        }
+
+        SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyyddMM.HHmmss");
+        String productionDateTime = metadata
+                .getMetadata("CAS.ProductReceivedTime");
+        if (productionDateTime == null) { // generate it ourselves then
+            productionDateTime = dateFormatter.format(new Date());
+        } else {
+            Date prodDateTime = null;
+            try {
+                prodDateTime = DateConvert.isoParse(productionDateTime);
+            } catch (ParseException e) {
+                LOG.log(Level.WARNING,
+                        "Unable to parse production date time CAS.ProductReceivedTime: "
+                                + productionDateTime
+                                + ": generating it ourselves");
+                prodDateTime = new Date();
+            }
+            productionDateTime = dateFormatter.format(prodDateTime);
+        }
+
+        if (product.getProductStructure().equals(Product.STRUCTURE_FLAT)) {
+            // if its flat, just return references that include
+            // productTypeRepo/productName/fileName.productionDateTime
+            // we'll use the format: yyyy.dd.MM.HH.mm.ss
+
+            for (Iterator<Reference> i = product.getProductReferences().iterator(); i
+                    .hasNext();) {
+                Reference r = i.next();
+                String dataStoreRef = null;
+
+                try {
+                    dataStoreRef = new File(new URI(product.getProductType()
+                            .getProductRepositoryPath())).toURL()
+                            .toExternalForm()
+                            + "/"
+                            + product.getProductName()
+                            + "/"
+                            + new File(new URI(r.getOrigReference())).getName()
+                            + "." + productionDateTime;
+                    LOG.log(Level.FINER,
+                            "DateTimeVersioner: Generated dataStoreRef: "
+                                    + dataStoreRef + " from original ref: "
+                                    + r.getOrigReference());
+                    r.setDataStoreReference(dataStoreRef);
+                } catch (URISyntaxException e) {
+                    LOG
+                            .log(
+                                    Level.WARNING,
+                                    "DateTimeVersioner: Error generating URI to get name "
+                                            + "of original ref while generating data store ref for orig ref: "
+                                            + r.getOrigReference()
+                                            + ": Message: " + e.getMessage());
+                    // try and keep generating
+                } catch (MalformedURLException e) {
+                    LOG.log(Level.WARNING,
+                            "DateTimeVersioner: Error getting URL for product repository path "
+                                    + product.getProductType()
+                                            .getProductRepositoryPath()
+                                    + ": Message: " + e.getMessage());
+                    // try and keep generating
+                }
+
+            }
+        } else if (product.getProductStructure().equals(Product.STRUCTURE_STREAM)) {
+                VersioningUtils.createBasicDataStoreRefsStream(product.getProductName(), product.getProductType().getProductRepositoryPath(),
+                        product.getProductReferences(), productionDateTime);
+        } else if (product.getProductStructure().equals(
+                Product.STRUCTURE_HIERARCHICAL)) {
+            // if its heirarchical, then we'll version the files within the
+            // directory
+            // first, we need to get a list of all the references from the
+            // original dir
+            Reference origDirRef = (Reference) product.getProductReferences()
+                    .get(0);
+
+            try {
+                String dataStoreRef = new File(new URI(product.getProductType()
+                        .getProductRepositoryPath())).toURL().toExternalForm()
+                        + URLEncoder.encode(product.getProductName(), "UTF-8")
+                        + "/";
+                LOG.log(Level.INFO,
+                        "DateTimeVersioner: generated DataStore ref: "
+                                + dataStoreRef + " from origDirRef: "
+                                + origDirRef.getOrigReference());
+                origDirRef.setDataStoreReference(dataStoreRef);
+            } catch (MalformedURLException e) {
+                LOG.log(Level.WARNING,
+                        "DateTimeVersioner: MalformedURLException while generating "
+                                + "initial data store ref for origRef: "
+                                + origDirRef.getOrigReference());
+                throw new VersioningException(e);
+            } catch (URISyntaxException e) {
+                LOG.log(Level.WARNING,
+                        "DateTimeVersioner: Error creating File reference from original dir URI: "
+                                + origDirRef.getOrigReference() + ": Message: "
+                                + e.getMessage());
+                throw new VersioningException(
+                        "Unable to generate references from original dir reference for product: "
+                                + product.getProductName() + ": Message: "
+                                + e.getMessage());
+            } catch (UnsupportedEncodingException e) {
+                LOG.log(Level.WARNING,
+                        "DateTimeVersioner: UnsupportedEncodingException while generating "
+                                + "initial data store ref for origRef: "
+                                + origDirRef.getOrigReference());
+                throw new VersioningException(e);
+            }
+
+            // create the basic data store refs
+            VersioningUtils.createBasicDataStoreRefsHierarchical(product
+                    .getProductReferences());
+
+            // add the production date time
+            addProductDateTimeToReferences(product.getProductReferences(),
+                    productionDateTime);
+
+        }
+    }
+
+    private void addProductDateTimeToReferences(List<Reference> references,
+            String productionDateTime) {
+        for (Iterator<Reference> i = references.iterator(); i.hasNext();) {
+            Reference r = i.next();
+            if (!r.getOrigReference().endsWith("/")) {
+                r.setDataStoreReference(r.getDataStoreReference() + "."
+                        + productionDateTime);
+            }
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/DirectoryProductVersioner.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/DirectoryProductVersioner.java
new file mode 100644
index 0000000..54aa496
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/DirectoryProductVersioner.java
@@ -0,0 +1,68 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.filemgr.versioning.VersioningUtils;
+
+/**
+ * A {@link Versioner} for Hierarchical directory products.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class DirectoryProductVersioner extends MetadataBasedFileVersioner {
+
+  /**
+   * <p>
+   * Default constructor
+   * </p>
+   */
+  public DirectoryProductVersioner() {
+    setFlatProducts(false);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.filemgr.versioning.MetadataBasedFileVersioner#
+   * createDataStoreReferences(org.apache.oodt.cas.filemgr.structs.Product,
+   * org.apache.oodt.cas.metadata.Metadata)
+   */
+  public void createDataStoreReferences(Product product, Metadata metadata)
+      throws VersioningException {
+    // first generate the first correct reference
+    super.createDataStoreReferences(product, metadata);
+
+    Reference root = (Reference) product.getProductReferences().get(0);
+    if (!root.getDataStoreReference().endsWith("/")) {
+      root.setDataStoreReference(root.getDataStoreReference() + "/");
+    }
+
+    // now add the heirarchical refs
+    VersioningUtils.createBasicDataStoreRefsHierarchical(product
+        .getProductReferences());
+
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/InPlaceVersioner.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/InPlaceVersioner.java
new file mode 100644
index 0000000..fe6a6c5
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/InPlaceVersioner.java
@@ -0,0 +1,70 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//JDK imports
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+
+/**
+ * 
+ * A Inplace versioner that ingests the file without moving the actual file. It
+ * just copies the file's orgin ref to its datastor ref.
+ * 
+ * @author davoodi
+ * 
+ */
+public class InPlaceVersioner implements Versioner {
+
+  /* our log stream */
+  private static final Logger LOG = Logger.getLogger(InPlaceVersioner.class
+      .getName());
+
+  /**
+     * 
+     */
+  public InPlaceVersioner() {
+    super();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.versioning.Versioner#createDataStoreReferences(org.
+   * apache.oodt.cas.data.structs.Product)
+   */
+  public void createDataStoreReferences(Product product, Metadata metadata)
+      throws VersioningException {
+      for (Reference r : product.getProductReferences()) {
+        r.setDataStoreReference(r.getOrigReference());
+        LOG.log(Level.INFO, "in-place ingestion at datastore path: "
+            + r.getDataStoreReference()
+            + ".which is the same as the product's origin: "
+            + r.getOrigReference());
+      }
+
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/MetadataBasedFileVersioner.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/MetadataBasedFileVersioner.java
new file mode 100644
index 0000000..99e7d19
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/MetadataBasedFileVersioner.java
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Versioner class that uses {@link Metadata} fields and a given
+ * <code>filePathSpec</code> to version references. The filePathSpec should be
+ * of the form:<br>
+ * <br>
+ * 
+ * <code>/[FieldName1]/other/text/.../[FieldName2]...</code>
+ * 
+ * where <code>FieldName1</code> and <code>FieldName2</code> are Metadata
+ * fields provided by the given Metadata object.
+ * </p>.
+ */
+public class MetadataBasedFileVersioner implements Versioner {
+
+    /* file path spec denoted by metadata fields and static path */
+    private String filePathSpec = null;
+
+    /* our log stream */
+    private static final Logger LOG = Logger
+            .getLogger(MetadataBasedFileVersioner.class.getName());
+
+    /* whether or not we only handle flat products */
+    private boolean flatProducts = true;
+
+    public MetadataBasedFileVersioner() {
+        filePathSpec = "/[Filename]";
+    }
+
+    public MetadataBasedFileVersioner(String filePathSpec) {
+        this.filePathSpec = filePathSpec;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.versioning.Versioner#createDataStoreReferences(gov.nasa.
+     *      jpl.oodt.cas.filemgr.structs.Product,
+     *      org.apache.oodt.cas.metadata.Metadata)
+     */
+    public void createDataStoreReferences(Product product, Metadata metadata)
+            throws VersioningException {
+
+        // since we need the metadata, if the metadata is null, throw an
+        // exception
+        if (metadata == null) {
+            throw new VersioningException(
+                    "Unable to version product with no metadata!");
+        }
+
+        // we also only deal with Flat products, that is, Products with a single
+        // reference
+        if (flatProducts
+                && !product.getProductStructure()
+                        .equals(Product.STRUCTURE_FLAT)) {
+            throw new VersioningException(
+                    "Can only handle FLAT product structures");
+        }
+
+        // get the product type repo path
+        String productTypeRepoPath = VersioningUtils
+                .getAbsolutePathFromUri(product.getProductType()
+                        .getProductRepositoryPath());
+
+        // parse the file path spec
+        String filePathRef = parseFilePathSpec(filePathSpec,
+                productTypeRepoPath, metadata);
+        String filePathUri = new File(filePathRef).toURI().toString();
+
+        Reference r = (Reference) product.getProductReferences().get(0);
+        LOG.log(Level.INFO, "Generated data store ref: [" + filePathUri
+                + "] from origRef: [" + r.getOrigReference() + "]");
+        r.setDataStoreReference(filePathUri);
+    }
+
+    private String parseFilePathSpec(String filePathSpec,
+            String productTypeRepoPath, Metadata metadata) {
+        StringBuffer finalFilePath = new StringBuffer();
+        finalFilePath.append(productTypeRepoPath);
+
+        if (finalFilePath.charAt(finalFilePath.length() - 1) == '/') {
+            finalFilePath.deleteCharAt(finalFilePath.length() - 1);
+        }
+
+        if (!filePathSpec.startsWith("/")) {
+            filePathSpec = "/" + filePathSpec;
+        }
+
+        finalFilePath.append(PathUtils.replaceEnvVariables(filePathSpec,
+                metadata));
+        return finalFilePath.toString();
+    }
+
+    /**
+     * @return the filePathSpec
+     */
+    public String getFilePathSpec() {
+        return filePathSpec;
+    }
+
+    /**
+     * @param filePathSpec
+     *            the filePathSpec to set
+     */
+    public void setFilePathSpec(String filePathSpec) {
+        this.filePathSpec = filePathSpec;
+    }
+
+    /**
+     * @return the flatProducts
+     */
+    public boolean isFlatProducts() {
+        return flatProducts;
+    }
+
+    /**
+     * @param flatProducts
+     *            the flatProducts to set
+     */
+    public void setFlatProducts(boolean flatProducts) {
+        this.flatProducts = flatProducts;
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/ProductTypeMetVersioner.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/ProductTypeMetVersioner.java
new file mode 100644
index 0000000..0ddfc69
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/ProductTypeMetVersioner.java
@@ -0,0 +1,56 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * A simple versioner that lets a user define the filePathSpec needed by the
+ * {@link MetadataBasedFileVersioner} in a Product's ProductType metadata. Use
+ * the key name filePathSpec, and then provide it for easily configurable use of
+ * the {@link MetadataBasedFileVersioner}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ProductTypeMetVersioner extends MetadataBasedFileVersioner {
+
+  public ProductTypeMetVersioner() {
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.filemgr.versioning.MetadataBasedFileVersioner#
+   * createDataStoreReferences(org.apache.oodt.cas.filemgr.structs.Product,
+   * org.apache.oodt.cas.metadata.Metadata)
+   */
+  @Override
+  public void createDataStoreReferences(Product product, Metadata metadata)
+      throws VersioningException {
+    setFilePathSpec(product.getProductType().getTypeMetadata()
+        .getMetadata("filePathSpec"));
+    super.createDataStoreReferences(product, metadata);
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/SingleFileBasicVersioner.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/SingleFileBasicVersioner.java
new file mode 100644
index 0000000..cc40d0e
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/SingleFileBasicVersioner.java
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A {@link Versioner} that handles single file {@link Product}s by storing
+ * them in <code>productTypeRepoPath/Filename</code>.
+ * </p>
+ * 
+ */
+public class SingleFileBasicVersioner implements Versioner {
+
+    /* filename fields */
+    public static final String FILENAME_FIELD = "Filename";
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(SingleFileBasicVersioner.class
+            .getName());
+
+    /**
+     * 
+     */
+    public SingleFileBasicVersioner() {
+        super();
+        // TODO Auto-generated constructor stub
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.versioning.Versioner#createDataStoreReferences(gov.nasa.
+     *      jpl.oodt.cas.filemgr.structs.Product,
+     *      org.apache.oodt.cas.metadata.Metadata)
+     */
+    public void createDataStoreReferences(Product product, Metadata metadata)
+            throws VersioningException {
+        // we only handle single files, so throw exception if product is
+        // heirarhical
+
+        if (!product.getProductStructure().equals(Product.STRUCTURE_FLAT)) {
+            throw new VersioningException(
+                    "SingleFileVersioner: unable to version" + " Product: ["
+                            + product.getProductName()
+                            + "] with heirarchical/stream structure");
+        }
+
+        // we need the Filename Metadata parameter for this to work
+        String filename = metadata.getMetadata(FILENAME_FIELD);
+
+        if (filename == null || (filename != null && filename.equals(""))) {
+            throw new VersioningException(
+                    "SingleFileVersioner: unable to version without "
+                            + "Filename metadata field specified!");
+        }
+
+        // now we need the product type repo path
+        String productTypeRepoPathUri = product.getProductType()
+                .getProductRepositoryPath();
+        String productTypeRepoPath = VersioningUtils
+                .getAbsolutePathFromUri(productTypeRepoPathUri);
+
+        if (!productTypeRepoPath.endsWith("/")) {
+            productTypeRepoPath += "/";
+        }
+
+        // final file location is:
+        // /productTypeRepoPath/Filename
+
+        String dataStorePath = productTypeRepoPath + filename;
+        String dataStoreRef = new File(dataStorePath).toURI().toString();
+
+        // get the first reference back
+        // set its data store ref
+        Reference ref = (Reference) product.getProductReferences().get(0);
+        LOG.log(Level.INFO, "Generated data store ref: [" + dataStoreRef
+                + "] from origRef: [" + ref.getOrigReference() + "]");
+        ref.setDataStoreReference(dataStoreRef);
+
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/Versioner.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/Versioner.java
new file mode 100644
index 0000000..2b274f3
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/Versioner.java
@@ -0,0 +1,42 @@
+/*

+ * 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.

+ */

+

+package org.apache.oodt.cas.filemgr.versioning;

+

+//OODT imports

+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;

+import org.apache.oodt.cas.filemgr.structs.Product;

+import org.apache.oodt.cas.metadata.Metadata;

+

+/**

+ * @author mattmann

+ * @version $Revision$

+ * 

+ * <p>

+ * This interface defines a versioning scheme for generating the DataStore

+ * references for the items in a {@link Product}.

+ * </p>

+ * 

+ */

+public interface Versioner {

+

+    public static final String X_POINT_ID = Versioner.class.getName();

+

+    public void createDataStoreReferences(Product product, Metadata metadata)

+            throws VersioningException;

+

+}

diff --git a/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/VersioningUtils.java b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/VersioningUtils.java
new file mode 100644
index 0000000..08f1b72
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/java/org/apache/oodt/cas/filemgr/versioning/VersioningUtils.java
@@ -0,0 +1,300 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//OODT imports
+import org.apache.commons.lang.StringUtils;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.Product;
+
+//JDK imports
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Utility component to help out with versioning.
+ * </p>
+ * 
+ * 
+ */
+public final class VersioningUtils {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(VersioningUtils.class
+            .getName());
+
+    // filter to only find directories when doing a listFiles
+    private static FileFilter DIR_FILTER = new FileFilter() {
+        public boolean accept(File file) {
+            return file.isDirectory();
+        }
+    };
+
+    // filter to only find files when doing a listFiles
+    private static FileFilter FILE_FILTER = new FileFilter() {
+        public boolean accept(File file) {
+            return file.isFile();
+        }
+    };
+
+    public static List<Reference> getReferencesFromDir(File dirRoot) {
+        List<Reference> references = null;
+
+        if (dirRoot == null)
+            throw new IllegalArgumentException("null");
+        if (!dirRoot.isDirectory())
+            dirRoot = dirRoot.getParentFile();
+
+        references = new Vector<Reference>();
+
+        Stack<File> stack = new Stack<File>();
+        stack.push(dirRoot);
+        while (!stack.isEmpty()) {
+            File dir = stack.pop();
+            // add the reference for the dir
+            // except if it's the rootDir, then, skip it
+            if (!dir.equals(dirRoot)) {
+                try {
+                    Reference r = new Reference();
+                    r.setOrigReference(dir.toURL().toExternalForm());
+                    r.setFileSize(dir.length());
+                    references.add(r);
+                } catch (MalformedURLException e) {
+                    e.printStackTrace();
+                    LOG.log(Level.WARNING,
+                            "MalformedURLException when generating reference for dir: "
+                                    + dir);
+                }
+            }
+
+            File[] files = dir.listFiles(FILE_FILTER);
+
+            for (int i = 0; i < files.length; i++) {
+                // add the file references
+                try {
+                    Reference r = new Reference();
+                    r.setOrigReference(files[i].toURL().toExternalForm());
+                    r.setFileSize(files[i].length());
+                    references.add(r);
+                } catch (MalformedURLException e) {
+                    e.printStackTrace();
+                    LOG.log(Level.WARNING,
+                            "MalformedURLException when generating reference for file: "
+                                    + files[i]);
+                }
+
+            }
+            File[] subdirs = dir.listFiles(DIR_FILTER);
+            if (subdirs != null)
+                for (int i = 0; i < subdirs.length; i++) {
+                    stack.push(subdirs[i]);
+                }
+        }
+
+        return references;
+    }
+
+    public static List<String> getURIsFromDir(File dirRoot) {
+        List<String> uris = null;
+
+        if (dirRoot == null)
+            throw new IllegalArgumentException("null");
+        if (!dirRoot.isDirectory())
+            dirRoot = dirRoot.getParentFile();
+
+        uris = new Vector<String>();
+
+        Stack<File> stack = new Stack<File>();
+        stack.push(dirRoot);
+        while (!stack.isEmpty()) {
+            File dir = stack.pop();
+            // add the reference for the dir
+            // except if it's the rootDir, then, skip it
+            if (!dir.equals(dirRoot)) {
+                uris.add(dir.toURI().toString());
+            }
+
+            File[] files = dir.listFiles(FILE_FILTER);
+
+            for (int i = 0; i < files.length; i++) {
+                // add the file references
+                uris.add(files[i].toURI().toString());
+            }
+
+            File[] subdirs = dir.listFiles(DIR_FILTER);
+            if (subdirs != null)
+                for (int i = 0; i < subdirs.length; i++) {
+                    stack.push(subdirs[i]);
+                }
+        }
+
+        return uris;
+    }
+
+    public static void createBasicDataStoreRefsHierarchical(List<Reference> references) {
+        // file:///www/folder1
+        // file:///www/folder1/file1
+        // file:///www/folder1/file2
+        // file:///www/folder1/folder2/
+        // file:///www/folder1/folder2/file3
+
+        // toDir: file:///www/myfolder/product1
+        // origDir: file:///www/folder1
+
+        String toDirRef = references.get(0)
+                .getDataStoreReference();
+        String origDirRef = references.get(0).getOrigReference();
+        String origDirRefName = new File(origDirRef).getName();
+
+        for (Iterator<Reference> i = references.iterator(); i.hasNext();) {
+            Reference r = i.next();
+
+            // don't bother with the first one, because it's already set
+            // correctly
+            if (r.getOrigReference().equals(origDirRef)) {
+                continue;
+            }
+
+            // get the first occurence of the origDir name in the string
+            // then, the ref becomes:
+            // toDir+r.getOrigRef.substring(first occurence of
+            // origDir).substring(first occurence of '/'+1)
+
+            String dataStoreRef = toDirRef;
+            int firstOccurenceOfOrigDir = r.getOrigReference().indexOf(
+                    origDirRefName);
+            String tmpRef = r.getOrigReference().substring(
+                    firstOccurenceOfOrigDir);
+            LOG.log(Level.FINER, "tmpRef: " + tmpRef);
+            int firstOccurenceSlash = tmpRef.indexOf("/");
+            dataStoreRef += tmpRef.substring(firstOccurenceSlash + 1);
+
+            LOG.log(Level.FINE, "VersioningUtils: Generated data store ref: "
+                    + dataStoreRef + " from origRef: " + r.getOrigReference());
+            r.setDataStoreReference(dataStoreRef);
+        }
+
+    }
+
+    public static void createBasicDataStoreRefsFlat(String productName,
+            String productRepoPath, List<Reference> references) {
+        for (Iterator<Reference> i = references.iterator(); i.hasNext();) {
+            Reference r = i.next();
+
+            String dataStoreRef = null;
+            String productRepoPathRef = null;
+
+            try {
+                productRepoPathRef = new File(new URI(productRepoPath)).toURL()
+                        .toExternalForm();
+
+                if (!productRepoPathRef.endsWith("/")) {
+                    productRepoPathRef += "/";
+                }
+
+                dataStoreRef = productRepoPathRef
+                        + URLEncoder.encode(productName, "UTF-8") + "/"
+                        + new File(new URI(r.getOrigReference())).getName();
+            } catch (IOException e) {
+                LOG.log(Level.WARNING,
+                        "VersioningUtils: Error generating dataStoreRef for "
+                                + r.getOrigReference() + ": Message: "
+                                + e.getMessage());
+            } catch (URISyntaxException e) {
+                LOG.log(Level.WARNING,
+                        "VersioningUtils: Error generating dataStoreRef for "
+                                + r.getOrigReference() + ": Message: "
+                                + e.getMessage());
+            }
+
+            LOG.log(Level.FINE, "VersioningUtils: Generated data store ref: "
+                    + dataStoreRef + " from origRef: " + r.getOrigReference());
+            r.setDataStoreReference(dataStoreRef);
+        }
+
+    }
+    public static void createBasicDataStoreRefsStream(String productName,
+        String productRepoPath, List<Reference> references,String postfix) {
+        for (Iterator<Reference> i = references.iterator(); i.hasNext();) {
+            Reference r = i.next();
+            createDataStoreRefStream(productName,productRepoPath,r,postfix);
+        }
+
+    }
+    public static void createDataStoreRefStream(String pn, String productRepoPath, Reference ref, String postfix) {
+        URI uri = URI.create(ref.getOrigReference());
+        String[] parts = (postfix.equals(""))?new String[] {uri.toString()}:new String[] {uri.toString(),postfix};
+        ref.setDataStoreReference(StringUtils.join(parts,Reference.STREAM_REFERENCE_DELIMITER));
+    }
+    public static void addRefsFromUris(Product p, List<String> uris) {
+        // add the refs to the Product
+        for (Iterator<String> i = uris.iterator(); i.hasNext();) {
+            String ref = i.next();
+            Reference r = new Reference(ref, null, (p.getProductStructure().equals(Product.STRUCTURE_STREAM)?-1:quietGetFileSizeFromUri(ref)));
+            p.getProductReferences().add(r);
+        }
+    }
+
+    public static String getAbsolutePathFromUri(String uriStr) {
+        URI uri = null;
+        String absPath = null;
+
+        try {
+            uri = new URI(uriStr);
+            absPath = new File(uri).getAbsolutePath();
+        } catch (URISyntaxException e) {
+            LOG.log(Level.WARNING,
+                    "URISyntaxException getting URI from URI str: [" + uriStr
+                            + "]");
+        }
+
+        return absPath;
+    }
+
+    private static long quietGetFileSizeFromUri(String uri) {
+        File fileRef = null;
+
+        try {
+            fileRef = new File(new URI(uri));
+        } catch (URISyntaxException e) {
+            LOG.log(Level.WARNING,
+                    "URISyntaxException when getting file size from uri: ["
+                            + uri + "]: Message: " + e.getMessage());
+            return -1L;
+        }
+
+        return fileRef.length();
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/main/php/BooleanQueryCriteria.class.php b/0.8.1-rc1/filemgr/src/main/php/BooleanQueryCriteria.class.php
new file mode 100644
index 0000000..f820264
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/php/BooleanQueryCriteria.class.php
@@ -0,0 +1,140 @@
+<?php
+/*
+ * 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.
+ */
+
+require_once("XML/RPC.php");
+
+/**
+ * @author resneck
+ *
+ * <p>A PHP port of the core filemgr data structure.</p>
+ */
+ class CAS_Filemgr_BooleanQueryCriteria {
+ 
+ 	// These variables will function as constants to define boolean operators
+ 	public static $AND_OP = 0;
+    public static $OR_OP = 1;
+    public static $NOT_OP = 2;
+    
+    public $operator;
+    public $terms;
+    
+     /**
+     * Default constructor. Uses the AND operator.
+     */
+	function __construct(){
+    	$this->operator = self::$AND_OP;
+    	$this->terms = array();
+	}
+	
+	/**
+     * This query is a boolean combination of term,
+     * range, and other boolean queries. The supported operators are AND, OR and
+     * NOT. Note that the NOT operator can only be used with one (1) term. This
+     * function will not operate if more than one term is used with the NOT
+     * operator.
+     * 
+     * @param terms
+     *            The criteria onto which to apply the boolean operator
+     * @param op
+     *            The boolean operator to be applied
+     */
+	function __init($terms, $op){
+		if(!($op == self::$NOT_OP && count($terms) > 1)){
+			$this->terms = $terms;
+			$this->operator = $op;
+		}
+	}
+	
+	function __initXmlRpc($xmlRpcData){
+    	$this->operator = (isset($xmlRpcData['operator']))
+			? intval($xmlRpcData['operator']) 
+			: self::$AND_OP;
+		$this->terms = (isset($xmlRpcData['terms']))
+			? $xmlRpcData['terms'] 
+			: array();
+	}
+	
+	/**
+     * Method to add a term to the boolean query. Note that a NOT operator can
+     * only be applied to one term. This function will not operate if more than 
+     * one term is used with the NOT operator.
+     * 
+     * @param t
+     *            Term to be added to the query
+     */
+	function addTerm($t){
+		if(!($this->operator == self::$NOT_OP && count($this->terms))){
+			array_push($this->terms, $t);
+		}
+	}
+	
+	/**
+     * Accessor method for the list of terms in the query.
+     * 
+     * @return The list of terms
+     */
+    function getTerms() {
+        return $this->terms;
+    }
+
+    /**
+     * Mutator method for the boolean operator. This function will not operate if more than 
+     * one term is used with the NOT operator.
+     * 
+     * @param op
+     *            Boolean operator
+     */
+    function setOperator($op){
+    	if(!($op == self::$NOT_OP && count($this->terms) > 1)){
+    		$this->operator = $op;
+    	}
+    }
+
+    /**
+     * Accessor method for the boolean operator.
+     * 
+     * @return the boolean operator
+     */
+    function getOperator() {
+        return $this->operator;
+    }
+    
+    function toAssocArray(){
+		$assocArray = array(
+			'operator' => $this->operator,
+			'terms' => array());
+		foreach($this->terms as $t){
+			array_push($assocArray['terms'], $t->toAssocArray());
+		}
+		return $assocArray;
+	}
+	
+	function toXmlRpcStruct(){
+		$termArray = array();
+		foreach($this->terms as $t){
+			array_push($termArray, $t->toXmlRpcStruct());
+		}
+		return new XML_RPC_Value(array(
+			'class' => new XML_RPC_Value('org.apache.oodt.cas.filemgr.structs.BooleanQueryCriteria', 'string'),
+			'terms' => new XML_RPC_Value($termArray, 'array'),
+			'operator' => new XML_RPC_Value($this->operator, 'int')), 'struct');
+	}
+ 
+ }
+ 
+ ?>
diff --git a/0.8.1-rc1/filemgr/src/main/php/Element.class.php b/0.8.1-rc1/filemgr/src/main/php/Element.class.php
new file mode 100644
index 0000000..142268b
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/php/Element.class.php
@@ -0,0 +1,150 @@
+<?php
+/*
+ * 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.
+ */
+
+require_once("XML/RPC.php");
+
+/**
+ * @author resneck
+ *
+ * <p>A PHP port of the core filemgr data structure.</p>
+ */
+class CAS_Filemgr_Element {
+
+	/* the element id */
+	public $elementId;
+
+    /* the element name */
+    public $elementName;
+
+    /* the corresponding DC element for this CAS element */
+    public $dcElement;
+
+    /* the element's string description. */
+    public $description;
+    
+    /**
+	 * <p>Default Constructor.</p>
+	 */
+	function __construct(){
+		$this->elementId = null;
+		$this->elementName = null;
+		$this->dcElement = null;
+		$this->description = null;
+	}
+	
+	function __init($elementId, $elementName, $dcElement, $description){
+		$this->elementId = $elementId;
+		$this->elementName = $elementName;
+		$this->dcElement = $dcElement;
+		$this->description = $description;
+	}
+	
+	function __initXmlRpc($xmlRpcData){
+		$this->elementId = (isset($xmlRpcData['id']))
+			? $xmlRpcData['id']
+			: null;
+		$this->elementName = (isset($xmlRpcData['name']))
+			? $xmlRpcData['name']
+			: null;
+		$this->dcElement = (isset($xmlRpcData['dcElement']))
+			? $xmlRpcData['dcElement']
+			: null;
+		$this->description = (isset($xmlRpcData['description']))
+			? $xmlRpcData['description']
+			: null;
+	}
+	
+	/**
+     * @return The ID of this Element.
+     */
+	function getElementID(){
+		return $this->elementId;
+	}
+	
+	/**
+     * @param elementId
+     *            The new ID for this Element.
+     */
+	function setElementID($elementId){
+		$this->elementId = $elementId;
+	}
+	
+	/**
+     * @return The name of this Element.
+     */
+	function getElementName(){
+		return $this->elementName;
+	}
+	
+	/**
+     * @param elementName
+     *            The new name for this Element.
+     */
+	function setElementName($elementName){
+		$this->elementName = $elementName;
+	}
+
+	/**
+     * @return The dcElement of this Element...whatever that means.
+     */
+	function getDcElement(){
+		return $this->dcElement;
+	}
+	
+	/**
+     * @param dcElement
+     *            The new dcElement for this Element.
+     */
+	function setDcElement($dcElement){
+		$this->dcElement = $dcElement;
+	}
+	
+	/**
+     * @return The description of this Element.
+     */
+	function getDescription(){
+		return $this->description;
+	}
+	
+	/**
+     * @param description
+     *            The new description for this Element.
+     */
+	function setDescription($description){
+		$this->description = $description;
+	}
+	
+	function toAssocArray(){
+    	return array(
+			'elementId' => $this->elementId,
+			'elementName' => $this->elementName,
+			'dcElement' => $this->dcElement,
+			'description' => $this->description);
+    }
+	
+	function toXmlRpcStruct(){
+    	return new XML_RPC_Value(array(
+			'elementId' => new XML_RPC_Value($this->elementId,'string'),
+			'elementName' => new XML_RPC_Value($this->elementName,'string'),
+			'dcElement' => new XML_RPC_Value($this->dcElement,'string'),
+			'description' => new XML_RPC_Value($this->description, 'string')), 'struct');
+    }
+
+}
+
+?>
diff --git a/0.8.1-rc1/filemgr/src/main/php/Metadata.class.php b/0.8.1-rc1/filemgr/src/main/php/Metadata.class.php
new file mode 100644
index 0000000..d0df6ac
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/php/Metadata.class.php
@@ -0,0 +1,84 @@
+<?php
+/*
+ * 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.
+ */
+
+require_once ("XML/RPC.php");
+
+/**
+ * @author mattmann
+ * 
+ * A PHP representation of the CAS metadata data structure, which
+ * is a structure of key=>List of String values.
+ */
+class CAS_Filemgr_Metadata {
+
+	public $elemMap;
+
+	function __construct($xmlRpcData = array ()) {
+		$this->elemMap = $xmlRpcData;
+	}
+
+	function __destruct() {
+
+	}
+
+	function toXmlRpcStruct() {
+		$xmlRpcStruct = array ();
+		foreach ($this->elemMap as $key => $val) {
+			$valList = array ();
+			foreach ($val as $v) {
+				array_push($valList, new XML_RPC_VALUE($v, 'string'));
+			}
+			$xmlRpcStruct[$key] = new XML_RPC_VALUE($valList, 'array');
+		}
+
+		return new XML_RPC_VALUE($xmlRpcStruct, 'struct');
+	}
+
+	function toAssocArray() {
+		return $this->elemMap;
+	}
+
+	function addMetadata($key, $value) {
+		array_push($this->elemMap[$key], $value);
+	}
+
+	function replaceMetadata($key, $value) {
+		$this->elemMap[$key] = $value;
+	}
+
+	function removeMetadata($key) {
+		unset ($this->elemMap[$key]);
+	}
+
+	function getAllMetadata($key) {
+		return $this->elemMap[$key];
+	}
+
+	function getMetadata($key) {
+		return $this->elemMap[$key][0];
+	}
+
+	function containsKey($key) {
+		return array_key_exists($key, $this->elemMap);
+	}
+
+	function isMultiValued($key) {
+		return array_count_values($this->elemMap[$key]) > 1;
+	}
+}
+?>
diff --git a/0.8.1-rc1/filemgr/src/main/php/Product.class.php b/0.8.1-rc1/filemgr/src/main/php/Product.class.php
new file mode 100644
index 0000000..2761f72
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/php/Product.class.php
@@ -0,0 +1,102 @@
+<?php
+/*
+ * 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.
+ */
+
+require_once("XML/RPC.php");
+
+/**
+ * @author ahart
+ * @author gabe
+ * <p>The core file manager data structure, ported
+ * to PHP.
+ * </p>
+ */
+class CAS_Filemgr_Product {
+	
+	 public $id;
+	 public $name;
+	 public $type;
+	 public $structure;
+	 public $transferStatus;
+	 public $references;
+	
+
+	function __construct($xmlRpcData = array()) {
+		$this->id = (isset($xmlRpcData['id']))
+			? $xmlRpcData['id'] 
+			: '';
+		$this->name = (isset($xmlRpcData['name']))
+			? $xmlRpcData['name'] 
+			: '';
+		$this->type = (isset($xmlRpcData['type']))
+			? new CAS_Filemgr_ProductType($xmlRpcData['type']) 
+			: new CAS_Filemgr_ProductType();
+		$this->structure = (isset($xmlRpcData['structure']))
+			? $xmlRpcData['structure'] 
+			: '';
+		$this->transferStatus = (isset($xmlRpcData['transferStatus']))
+			? $xmlRpcData['transferStatus'] 
+			: '';
+		$this->references = (isset($xmlRpcData['references']))
+			? $xmlRpcData['references'] 
+			: array();
+	}
+	
+	function __destruct() {
+		
+	}
+	
+	function toAssocArray(){
+		return array(
+			'id' => $this->id,
+			'name' => $this->name,
+			'type' => $this->type->toAssocArray(),
+			'structure' => $this->structure,
+			'transferStatus' => $this->transferStatus,
+			'references' => $this->references);
+	}
+	
+	function toXmlRpcStruct(){
+		return new XML_RPC_VALUE(array(
+			'id' => new XML_RPC_Value($this->id,'string'),
+			'name' => new XML_RPC_Value($this->name,'string'),
+			'type' => $this->type->toXmlRpcStruct(),
+			'structure' => new XML_RPC_Value($this->structure,'string'),
+			'transferStatus' => new XML_RPC_Value($this->transferStatus,'string'),
+			'references' => new XML_RPC_Value($this->references,'array')),'struct');
+	}
+	
+	/*
+	 * Getter/Setter functions
+	 */
+	function getId(){return $this->id;}
+	function getName(){return $this->name;}
+	function getType(){return $this->type;}
+	function getStructure(){return $this->structure;}
+	function getTransferStatus(){return $this->transferStatus;}
+	function getReferences(){return $this->references;}
+	
+	function setId($val){$this->id = $val;}
+	function setName($val){$this->name = $val;}
+	function setType($val){$this->type = $val;}
+	function setStructure($val){$this->structure = $val;}
+	function setTransferStatus(){$this->transferStatus = $val;}
+	function setReferences($val){$this->references = $val;}
+	
+}
+
+?>
diff --git a/0.8.1-rc1/filemgr/src/main/php/ProductPage.class.php b/0.8.1-rc1/filemgr/src/main/php/ProductPage.class.php
new file mode 100644
index 0000000..fe1e479
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/php/ProductPage.class.php
@@ -0,0 +1,225 @@
+<?php
+/*
+ * 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.
+ */
+
+require_once("XML/RPC.php");
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * A Page of {@link Product}s returned from the <code>File Manager</code>.
+ * 
+ */
+class CAS_Filemgr_ProductPage {
+
+	/* the number of this page */
+	private $pageNum = -1;
+
+	/* the total number of pages in the set */
+	private $totalPages = -1;
+	
+	/* the number of total hits for the query */
+	private $numOfHits = -1;
+	
+	/* the size of the number of products on this page */
+	private $pageSize = -1;
+
+	/* the list of produdcts associated with this page */
+	private $pageProducts = null;
+
+	/**
+	 * <p>
+	 * Default Constructor
+	 * </p>.
+	 */
+	function __construct() {
+		$this->pageProducts = array ();
+	}
+
+	/**
+	 * @param pageNum
+	 *            The number of this page.
+	 * @param totalPages
+	 *            The total number of pages in the set.
+	 * @param pageSize
+	 *            The size of this page.
+	 * @param pageProducts
+	 *            The products associated with this page.
+	 */
+	function __init($pageNum, $totalPages, $numOfHits, $pageSize, $pageProducts) {
+		$this->pageNum = $pageNum;
+		$this->totalPages = $totalPages;
+		$this->numOfHits = $numOfHits;
+		$this->pageSize = $pageSize;
+		$this->pageProducts = $pageProducts;
+	}
+
+    function __initXmlRpc($xmlRpcData){
+		$this->pageNum = (isset($xmlRpcData['pageNum']))
+			? intval($xmlRpcData['pageNum'])
+			: -1;
+		$this->totalPages = (isset($xmlRpcData['totalPages']))
+			? intval($xmlRpcData['totalPages']) 
+			: -1;
+		$this->numOfHits = (isset($xmlRpcData['numOfHits']))
+			? intval($xmlRpcData['numOfHits']) 
+			: -1;
+		$this->pageSize = (isset($xmlRpcData['pageSize']))
+			? intval($xmlRpcData['pageSize']) 
+			: -1;
+		$this->pageProducts = array();
+		if(isset($xmlRpcData['pageProducts'])){
+			foreach($xmlRpcData['pageProducts'] as $p){
+				array_push($this->pageProducts, new CAS_Filemgr_Product($p));
+			}
+		}
+    }
+    
+    
+	/**
+	 * @return Returns the pageNum.
+	 */
+	public function getPageNum() {
+		return $this->pageNum;
+	}
+
+	/**
+	 * @param pageNum
+	 *            The pageNum to set.
+	 */
+	public function setPageNum($pageNum) {
+		$this->pageNum = $pageNum;
+	}
+
+	/**
+	 * @return Returns the pageProducts.
+	 */
+	public function getPageProducts() {
+		return $this->pageProducts;
+	}
+
+	/**
+	 * @param pageProducts
+	 *            The pageProducts to set.
+	 */
+	public function setPageProducts($pageProducts) {
+		$this->pageProducts = $pageProducts;
+	}
+
+	/**
+	 * @return Returns the pageSize.
+	 */
+	public function getPageSize() {
+		return $this->pageSize;
+	}
+
+	/**
+	 * @param pageSize
+	 *            The pageSize to set.
+	 */
+	public function setPageSize($pageSize) {
+		$this->pageSize = $pageSize;
+	}
+
+	/**
+	 * @return Returns the totalPages.
+	 * If totalPages is not set check to see if numOfHits is used instead
+	 */
+	public function getTotalPages() {
+		if ($this->totalPages != -1 ) {
+			return $this->totalPages;
+		} elseif ( $this->numOfHits > 0 ) {
+			return (ceil($this->numOfHits/$this->pageSize));
+		}
+		return $this->totalPages;
+	}
+
+	/**
+	 * @param totalPages
+	 *            The totalPages to set.
+	 */
+	public function setTotalPages($totalPages) {
+		$this->totalPages = $totalPages;
+	}
+
+	/**
+	 * @return Returns the numOfHits.
+	 */
+	public function getNumOfHits() {
+		return $this->numOfHits;
+	}
+
+	/**
+	 * @param totalPages
+	 *            The totalPages to set.
+	 */
+	public function setNumOfHits($numOfHits) {
+		$this->numOfHits = $numOfHits;
+	}	
+
+	/**
+	 * 
+	 * @return True if this is the last page in the set, false otherwise.
+	 */
+	public function isLastPage() {
+		return $this->pageNum == $this->totalPages;
+	}
+
+	/**
+	 * 
+	 * @return True if this is the fist page of the set, false otherwise.
+	 */
+	public function isFirstPage() {
+		return $this->pageNum == 1;
+	}
+
+	public function toXmlRpcStruct() {
+	  return new XML_RPC_Value(array(
+					 'pageNum' => new XML_RPC_Value($this->pageNum,'int'),
+					 'pageSize' => new XML_RPC_Value($this->pageSize,'int'),
+					 'totalPages' => new XML_RPC_Value($this->totalPages,'int'),
+					 'numOfHits' => new XML_RPC_Value($this->numOfHits,'int'),
+	  				 'pageProducts' => $this->toXmlRpcProductList($this->pageProducts)), 'struct');
+	}
+
+	/**
+	 * 
+	 * @return A blank, unpopulated {@link ProductPage}.
+	 */
+	public static function blankPage() {
+		$blank = new CAS_Filemgr_ProductPage();
+		$blank->setPageNum(0);
+		$blank->setTotalPages(0);
+		$blank->setNumOfHits(0);
+		$blank->setPageSize(0);
+		return $blank;
+	}
+	
+	
+	private function toXmlRpcProductList($prodList){
+		$prodEncodedArr = array();
+		
+		foreach ($prodList as $product){
+			$prodEncodedArr[] = $product->toXmlRpcStruct();
+		}
+		
+		return new XML_RPC_Value($prodEncodedArr, 'array');
+	}
+
+}
+?>
diff --git a/0.8.1-rc1/filemgr/src/main/php/ProductType.class.php b/0.8.1-rc1/filemgr/src/main/php/ProductType.class.php
new file mode 100644
index 0000000..8671e7a
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/php/ProductType.class.php
@@ -0,0 +1,104 @@
+<?php
+/*
+ * 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.
+ */
+
+require_once("XML/RPC.php");
+require_once("Metadata.class.php");
+
+/**
+ * Ports the core file manager data structure, 
+ * ProductType, to PHP.
+ * 
+ * @author ahart
+ * @author mattmann
+ * @author gabe
+ * 
+ */
+class CAS_Filemgr_ProductType {
+	
+	 public $id;
+	 public $name;
+	 public $description;
+	 public $repositoryPath;
+	 public $versionerClass;
+	 public $typeMetadata;
+	
+	function __construct($xmlRpcData = array()){
+		$this->id = (isset($xmlRpcData['id']))
+			? $xmlRpcData['id'] 
+			: '';
+		$this->name = (isset($xmlRpcData['name']))
+			? $xmlRpcData['name'] 
+			: '';
+		$this->description = (isset($xmlRpcData['description']))
+			? $xmlRpcData['description'] 
+			: '';
+		$this->repositoryPath = (isset($xmlRpcData['repositoryPath']))
+			? $xmlRpcData['repositoryPath'] 
+			: '';
+		$this->versionerClass = (isset($xmlRpcData['versionerClass']))
+			? $xmlRpcData['versionerClass'] 
+			: '';
+		$this->typeMetadata = (isset($xmlRpcData['typeMetadata'])) 
+		    ? new CAS_Filemgr_Metadata($xmlRpcData['typeMetadata'])
+		    : new CAS_Filemgr_Metadata();
+	}
+	
+	function __destruct(){
+		
+	}
+	
+	function toAssocArray(){
+		return array(
+			'id' => $this->id,
+			'name' => $this->name,
+			'description' => $this->description,
+			'repositoryPath' => $this->repositoryPath,
+			'versionerClass' => $this->versionerClass,
+			'typeMetadata' => $this->typeMetadata->toAssocArray());
+	}
+	
+	function toXmlRpcStruct(){
+		return new XML_RPC_Value(array(
+			'id' => new XML_RPC_Value($this->id,'string'),
+			'name' => new XML_RPC_Value($this->name,'string'),
+			'description' => new XML_RPC_Value($this->description,'string'),
+			'repositoryPath' => new XML_RPC_Value($this->repositoryPath,'string'),
+			'versionerClass' => new XML_RPC_Value($this->versionerClass,'string'),
+            'typeMetadata' => $this->typeMetadata->toXmlRpcStruct()), 'struct');
+	}
+	
+	/*
+	 * Getter/Setter Functions
+	 */
+	function getId(){return $this->id;}
+	function getName(){return $this->name;}
+	function getDescription(){return $this->description;}
+	function getRepositoryPath(){return $this->repositoryPath;}
+	function getVersionerClass(){return $this->versionerClass;}
+	function getTypeMetadata(){return $this->typeMetadata;}
+	
+	function setId($val){$this->id = $val;}
+	function setName($val){$this->name = $val;}
+	function setDescription($val){$this->description = $val;}
+	function setRepositoryPath($val){$this->repositoryPath = $val;}
+	function setVersionerClass($val){$this->versionerClass = $val;}
+	function setTypeMetadata($val){$this->typeMetadata = $val;}
+	
+}
+
+?>
diff --git a/0.8.1-rc1/filemgr/src/main/php/Query.class.php b/0.8.1-rc1/filemgr/src/main/php/Query.class.php
new file mode 100644
index 0000000..2cc0daf
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/php/Query.class.php
@@ -0,0 +1,93 @@
+<?php
+/*
+ * 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.
+ */
+
+require_once("XML/RPC.php");
+
+/**
+ * @author resneck
+ *
+ * <p>A PHP port of the core filemgr data structure.</p>
+ */
+class CAS_Filemgr_Query {
+
+	/**
+	 *<p>The set of QueryCriteria for this Query.</p>
+	 */
+	public $criteria = null;
+	
+	/**
+	 * <p>Default Constructor.</p>
+	 */
+	function __construct(){
+		$this->criteria = array();
+	}
+	
+	function __init($criteria){
+		$this->criteria = $criteria;
+	}
+	
+	function __initXmlRpc($xmlRpcData){
+		$this->criteria = (isset($xmlRpcData['criteria']))
+			? $xmlRpcData['criteria']
+			: array();
+	}
+	
+	/**
+     * @return Returns the criteria.
+     */
+	function getCriteria(){
+		return $this->criteria;
+	}
+	
+	/**
+     * @param criteria
+     *            The criteria to set.
+     */
+	function setCriteria($criteria){
+		$this->criteria = $criteria;
+	}
+	
+	/**
+     * @param criterion
+     *            The criterion to add to the query.
+     */
+	function addCriterion($criterion){
+		array_push($this->criteria, $criterion);
+	}
+	
+	function toAssocArray(){
+		$assocArray = array(
+			'criteria' => array());
+		foreach($this->criteria as $c){
+			array_push($assocArray['criteria'], $c->toAssocArray());
+		}
+		return $assocArray;
+	}
+	
+	function toXmlRpcStruct(){
+		$critArray = array();
+		foreach($this->criteria as $c){
+			array_push($critArray, $c->toXmlRpcStruct());
+		}
+		return new XML_RPC_Value(array(
+			'criteria' => new XML_RPC_Value($critArray,'array')), 'struct');
+	}
+
+}
+
+?>
diff --git a/0.8.1-rc1/filemgr/src/main/php/RangeQueryCriteria.class.php b/0.8.1-rc1/filemgr/src/main/php/RangeQueryCriteria.class.php
new file mode 100644
index 0000000..a4b8835
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/php/RangeQueryCriteria.class.php
@@ -0,0 +1,178 @@
+<?php
+/*
+ * 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.
+ */
+
+require_once("XML/RPC.php");
+
+/**
+ * @author resneck
+ *
+ * <p>A PHP port of the core filemgr data structure.</p>
+ */
+ class CAS_Filemgr_RangeQueryCriteria {
+ 
+ 	public $elementName;
+    public $startValue;
+    public $endValue;
+    public $inclusive;
+ 
+ 	/**
+	 * <p>
+	 * Default Constructor
+	 * </p>.
+	 */
+	function __construct(){
+		$this->elementName = '';
+		$this->startValue = '';
+		$this->endValue = '';
+		$this->inclusive = true;
+	}
+	
+	/**
+     * @param elementName
+     *            The name of the element to search on.
+     * @param start
+     *            The start value for the range search as a String.
+     * @param end
+     *            The end value for the range search as a String.
+     * @param inclusive
+     *            Boolean: true for inclusive, false for exclusive.
+     */
+	function __init($elementName, $start, $end, $inclusive){
+		$this->elementName = $elementName;
+		$this->startValue = $start;
+		$this->endValue = $end;
+		$this->inclusive = $inclusive;
+	}
+	
+	function __initXmlRpc($xmlRpcData){
+		$this->elementName = (isset($xmlRpcData['elementName']))
+			? $xmlRpcData['elementName'] 
+			: '';
+		$this->value = (isset($xmlRpcData['start']))
+			? $xmlRpcData['start'] 
+			: '';
+		$this->value = (isset($xmlRpcData['end']))
+			? $xmlRpcData['end'] 
+			: '';
+		$this->value = (isset($xmlRpcData['inclusive']))
+			? (bool)$xmlRpcData['inclusive'] 
+			: true;
+	}
+	
+	/**
+     * Accessor method for the start value of the element to search on.
+     * 
+     * @return The start value of the element to search on as a String.
+     */
+    function getStartValue() {
+        return $this->startValue;
+    }
+
+    /**
+     * Mutator method for the start value fo the element to search on.
+     * 
+     * @param value
+     *            The start value of the range as a String.
+     */
+    function setStartValue($value) {
+        $this->startValue = $value;
+    }
+
+    /**
+     * Accessor method for the end value of the element to search on.
+     * 
+     * @return The end value of the element to search on as a String.
+     */
+    function getEndValue() {
+        return $this->endValue;
+    }
+
+    /**
+     * Mutator method for the end value fo the element to search on.
+     * 
+     * @param value
+     *            The end value of the range as a String.
+     */
+    function setEndValue($value) {
+        $this->endValue = $value;
+    }
+
+    /**
+     * Accessor method for the inclusive setting for the range.
+     * 
+     * @return The boolean inclusive/exclusive flag.
+     */
+    function getInclusive() {
+        return $this->inclusive;
+    }
+
+    /**
+     * Mutator method for the inclusive setting for the range. Note that flag
+     * should be set to true for inclusive, false for exclusive.
+     * 
+     * @param inclusive
+     *            The boolean inclusive/exclusive flag.
+     */
+    function setInclusive($flag) {
+        $this->inclusive = $flag;
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * accessing the element name to search on.
+     * 
+     * @return The element name to search on as a String.
+     */
+    function getElementName() {
+        return $this->elementName;
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * mutating the element name to search on.
+     * 
+     * @param elementName
+     *            The element name to search on as a String.
+     */
+    function setElementName($elementName) {
+        $this->elementName = $elementName;
+    }
+    
+    function toAssocArray(){
+    	return array(
+			'startValue' => $this->startValue,
+			'endValue' => $this->endValue,
+			'elementName' => $this->elementName,
+			'inclusive' => $this->inclusive);
+    }
+    
+    function toXmlRpcStruct(){
+    	$inclusiveStr = ($this->inclusive)
+			? 'true'
+			: 'false';
+    	return new XML_RPC_Value(array(
+    		'class' => new XML_RPC_Value('org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria', 'string'),
+			'elementStartValue' => new XML_RPC_Value($this->startValue,'string'),
+			'elementEndValue' => new XML_RPC_Value($this->endValue,'string'),
+			'elementName' => new XML_RPC_Value($this->elementName,'string'),
+			'inclusive' => new XML_RPC_Value($inclusiveStr, 'string')), 'struct');
+    }
+ 
+ }
+ 
+ ?>
diff --git a/0.8.1-rc1/filemgr/src/main/php/TermQueryCriteria.class.php b/0.8.1-rc1/filemgr/src/main/php/TermQueryCriteria.class.php
new file mode 100644
index 0000000..7d67edc
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/php/TermQueryCriteria.class.php
@@ -0,0 +1,116 @@
+<?php
+/*
+ * 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.
+ */
+
+require_once("XML/RPC.php");
+
+/**
+ * @author resneck
+ *
+ * <p>A PHP port of the core filemgr data structure.</p>
+ */
+class CAS_Filemgr_TermQueryCriteria {
+
+	public $elementName;
+	public $value;
+	
+	/**
+	 * <p>
+	 * Default Constructor
+	 * </p>.
+	 */
+	function __construct(){
+		$this->elementName = '';
+		$this->value = '';
+	}
+	
+	/**
+     * @param elementName
+     *            The name of the element to search on.
+     * @param v
+     *            The value of the term.
+     */
+	function __init($elementName, $value){
+		$this->elementName = $elementName;
+		$this->value = $value;
+	}
+	
+	function __initXmlRpc($xmlRpcData){
+		$this->elementName = (isset($xmlRpcData['elementName']))
+			? $xmlRpcData['elementName'] 
+			: '';
+		$this->value = (isset($xmlRpcData['value']))
+			? $xmlRpcData['value'] 
+			: '';
+	}
+	
+	/**
+     * Accessor method for the value of the element to search on.
+     * 
+     * @return The value of the element to search on as a String.
+     */
+    function getValue() {
+        return $this->value;
+    }
+
+    /**
+     * Mutator method for the value of the element to search on
+     * 
+     * @param value
+     *            The value of the element to search on as a String.
+     */
+    function setValue($value) {
+        $this->value = $value;
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * accessing the element name to search on.
+     * 
+     * @return The element name to search on as a String.
+     */
+    function getElementName() {
+        return $this->elementName;
+    }
+
+    /**
+     * Implementation of the abstract method inherited from QueryCriteria for
+     * mutating the element name to search on.
+     * 
+     * @param elementName
+     *            The element name to search on as a String.
+     */
+    function setElementName($elementName) {
+        $this->elementName = $elementName;
+    }
+    
+    function toAssocArray(){
+    	return array(
+			'value' => $this->value,
+			'elementName' => $this->elementName);
+    }
+    
+    function toXmlRpcStruct(){
+    	return new XML_RPC_Value(array(
+    		'class' => new XML_RPC_Value('org.apache.oodt.cas.filemgr.structs.TermQueryCriteria', 'string'),
+			'elementValue' => new XML_RPC_Value($this->value,'string'),
+			'elementName' => new XML_RPC_Value($this->elementName,'string')), 'struct');
+    }
+
+}
+
+?>
diff --git a/0.8.1-rc1/filemgr/src/main/php/XmlRpcFilemgrClient.class.php b/0.8.1-rc1/filemgr/src/main/php/XmlRpcFilemgrClient.class.php
new file mode 100644
index 0000000..e866a79
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/php/XmlRpcFilemgrClient.class.php
@@ -0,0 +1,452 @@
+<?php
+/*
+ * 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.
+ */
+
+require_once("XML/RPC.php");
+
+/**
+ * XML-RPC PHP version of the file manager client.
+ * 
+ * Not all of the core functionality/methods are ported yet
+ * but this is a good start.
+ * 
+ * @author ahart
+ * @author resneck
+ * 
+ */
+class CAS_Filemgr_XmlRpcFilemgrClient {
+	private $client;		// The XML/RPC client
+	public $serverURL;		// The base URL of the server (default is localhost:9000)
+	public $serverPath;		// The path to the XMLRPC handler (/path/to/xmlrpc)
+	
+	function __construct($serverURL = 'localhost:9000',$serverPath = '/'){
+		$this->serverURL = $serverURL;
+		$this->serverPath = $serverPath;
+		try {
+			$this->client = new XML_RPC_Client($this->serverPath,$this->serverURL);
+		} catch (Exception $e) {
+			echo "<h4>Error creating XMLRPC client: " . $e.getMessage() . "</h4>";
+			exit();
+		}
+	}
+	
+	function __destruct(){}
+
+	/**
+	 * @param methodStr
+     *		The string for the method to be invoked on ther server.
+	 *
+	 * @param params
+     *		An array of XML-RPC encoded parameters to the method that will be invoked on the server.
+     *
+     * @param falseOnFail
+     *		If set to true, sendMessage will return false on a failure, rather than exiting.
+	 *
+	 * @return The un-decoded data from the method invoked on the server.
+	 */
+	private function sendMessage($methodStr, $params){
+		$message = new XML_RPC_Message($methodStr, $params);
+		$response = $this->client->send($message);
+		if (!$response){
+			throw new XmlRpcFilemgrException("No response was received from Xml-Rpc Client\nError msg: " . $this->client->errstr);
+		}
+		if (!$response->faultCode()) {
+			$value = $response->value();
+			$data = XML_RPC_decode($value);
+			if(isset($data->faultString)){
+				throw new XmlRpcFilemgrException("Fault String in Xml-Rpc response: " . $data["faultString"]);
+			}
+			return $data;
+		} else {
+			throw new XmlRpcFilemgrException("Fault Code in Xml-Rpc response: " . $response->faultCode);
+		}
+	}
+	
+	/**
+	 * Throws an XmlRpcFilemgrException that gives more information than the one given.
+	 * 
+	 * @param e
+	 * 		The exception that needs more info included.
+	 * 
+	 * @param funcName
+	 * 		The name of the function in which this the original erroe/exception occurred.
+	 */
+	private function reportError($e, $funcName){
+		throw new XmlRpcFilemgrException("An error occurred while performing function " . $funcName . "\n" . $e->getMessage());
+	}
+	
+	/**
+	 * @return A boolean indicating whether the FileManager is still running.
+	 */
+	public function isAlive( $returnObject = true ) {
+       	$params = array();
+       	try{
+	       	$data = $this->sendMessage("filemgr.isAlive", $params, $returnObject);
+       	}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "isAlive");
+       	}
+       	return $data;
+    }
+
+	/**
+	 * @param productID
+     *		The id of the desired Product.
+     *
+     * @param returnObject
+     *		Whether data should be returned as an object as opposed to an associative array.
+	 *
+	 * @return The Product corresponding to the given id.
+	 */
+	function getProductById($productID, $returnObject = true){
+		$params = array(new XML_RPC_Value($productID,'string'));
+		try{
+			$data = $this->sendMessage("filemgr.getProductById", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "getProductById");
+       	}
+		if($returnObject){
+			$product = new CAS_Filemgr_Product($data);
+			return $product;
+		}else{
+			return $data;
+		}
+	}
+	
+	/**
+	 * @param product
+     *		The product containing the desired references.
+	 *
+	 * @return An associative array specifying the references contained in the given Product.
+	 */
+	function getProductReferences($product){
+		$params = array($product->toXmlRpcStruct());
+		try{
+			$data = $this->sendMessage("filemgr.getProductReferences", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "getProductReferences");
+       	}
+		return $data;
+	}
+	
+	/**
+	 * @param product
+     *		The product specified by the desired metadata.
+     *
+     * @param returnObject
+     *		Whether data should be returned as an object as opposed to an associative array.
+	 *
+	 * @return The metadata specifiying the given Product.
+	 */
+	function getMetadata($product, $returnObject = true){	
+		$params = array($product->toXmlRpcStruct());
+		try{
+			$data = $this->sendMessage("filemgr.getMetadata", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "getMetadata");
+       	}
+		if($returnObject){
+			$metadata = new CAS_Filemgr_Metadata($data);
+			return $metadata;
+		}else{
+			return $data;
+		}
+	}
+	
+	/**
+	 * @param typeID
+     *		The ID of the desired ProductType defined for this instance of the File Manager.
+     *
+     * @param returnObject
+     *		Whether data should be returned as an object as opposed to an associative array.
+	 *
+	 * @return The ProductType coresponding to the given ID.
+	 */
+	function getProductTypeById($typeID, $returnObject = true){
+		$params = array(new XML_RPC_Value($typeID,'string'));
+		try{
+			$data = $this->sendMessage("filemgr.getProductTypeById", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "getProductTypeById");
+       	}
+		if($returnObject){
+			$pt = new CAS_Filemgr_ProductType($data);
+			return $pt;
+		}else{
+			return $data;
+		}
+	}
+	
+	/**
+	 * @param typeName
+     *		The name of the desired ProductType defined for this instance of the File Manager.
+     *
+     * @param returnObject
+     *		Whether data should be returned as an object as opposed to an associative array.
+	 *
+	 * @return The ProductType coresponding to the given name.
+	 */
+	function getProductTypeByName($typeName, $returnObject = true){
+		$params = array(new XML_RPC_Value($typeName,'string'));
+		try{
+			$data = $this->sendMessage("filemgr.getProductTypeByName", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "getProductTypeByName");
+       	}
+		if($returnObject){
+			$pt = new CAS_Filemgr_ProductType($data);
+			return $pt;
+		}else{
+			return $data;
+		}
+	}
+	
+	/**
+	 * @param type
+     *		The desired ProductType defined for this instance of the File Manager.
+     *
+     * @param returnObject
+     *		Whether data should be returned as an object as opposed to an associative array.
+	 *
+	 * @return An array of all Products in the repository of the given ProductType.
+	 */
+	function getProductsByProductType($type, $returnObject = true){
+		$params = array($type->toXmlRpcStruct());
+		try{
+			$data = $this->sendMessage("filemgr.getProductsByProductType", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "getProductsByProductType");
+       	}
+		if($returnObject){
+			$products = array();
+			foreach($data as $d){
+				$p = new CAS_Filemgr_Product($d);
+				array_push($products, $p);
+			}
+			return $products;
+		}else{
+			return $data;
+		}
+	}
+
+	/**
+	 * @param returnObject
+     *		Whether data should be returned as an object as opposed to an associative array.
+	 *
+	 * @return An array of all ProductTypes defined for this instance of the File Manager.
+	 */
+	function getProductTypes($returnObject = true){
+		$params = array();
+		try{
+			$data = $this->sendMessage("filemgr.getProductTypes", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "getProductTypes");
+       	}
+		if($returnObject){
+			$types = array();
+			foreach($data as $d){
+				$pt = new CAS_Filemgr_ProductType($d);
+				array_push($types, $pt);
+			}
+			return $types;
+		}else{
+			return $data;
+		}
+	}
+	
+	/**
+	 * @param type
+     *		The desired ProductType defined for this instance of the File Manager.
+	 *
+	 * @return The number of products of the given ProductType in the repository.
+	 */
+    function getNumProducts($type){
+		$params = array($type->toXmlRpcStruct());
+		try{
+			$data = $this->sendMessage("filemgr.getNumProducts", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "getNumProducts");
+       	}
+		return $data;
+	}
+	
+	/**
+	 * @param query
+     *		A Query object containing QueryCrteria objects defining the search.
+	 *
+	 * @param type
+     *		A ProductType object defining what types to search.
+     *
+     * @param pageNum
+     *		The desired number of the page in the set of query results.
+     *
+     * @param returnObject
+     *		Whether data should be returned as an object as opposed to an associative array.
+	 *
+	 * @return A ProductPage object containing query results
+	 */
+	function pagedQuery($query, $type, $pageNum, $returnObject = true){
+		$params = array(
+			$query->toXmlRpcStruct(),
+			$type->toXmlRpcStruct(),
+			new XML_RPC_Value($pageNum,'int'));
+		try{
+			$data = $this->sendMessage("filemgr.pagedQuery", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "pagedQuery");
+       	}
+		if($returnObject){
+			$productPage = new CAS_Filemgr_ProductPage();
+			$productPage->__initXmlRpc($data);
+			return $productPage;
+		}else{
+			return $data;
+		}
+	}
+	
+	/**
+	 * @param query
+     *		A Query object containing QueryCrteria objects defining the search.
+	 *
+	 * @param type
+     *		A ProductType object defining what types to search.
+     *
+     * @param returnObject
+     *		Whether data should be returned as an object as opposed to an associative array.
+	 *
+	 * @return An array of Product objects as query results.
+	 */
+	function query($query, $type, $returnObject = true){
+		$params = array(
+			$query->toXmlRpcStruct(),
+			$type->toXmlRpcStruct());
+		try{
+			$data = $this->sendMessage("filemgr.query", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "query");
+       	}
+		if($returnObject){
+			$products = array();
+			foreach($data as $d){
+				$p = new CAS_Filemgr_Product($d);
+				array_push($products, $p);
+			}
+			return $products;
+		}else{
+			return $data;
+		}
+	}
+	
+	/**
+	 * @param type
+     *		The desired ProductType defined for this instance of the File Manager.
+     *
+     * @param returnObject
+     *		Whether data should be returned as an object as opposed to an associative array.
+	 *
+	 * @return An array of Element objects that are mapped to the given ProductType.
+	 */
+	function getElementsByProductType($type, $returnObject = true){
+		$params = array($type->toXmlRpcStruct());
+		try{
+			$data = $this->sendMessage("filemgr.getElementsByProductType", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "getElementsByProductType");
+       	}
+		if($returnObject){
+			$elements = array();
+			foreach($data as $d){
+				$e = new CAS_Filemgr_Element();
+				$e->__initXmlRpc($d);
+				array_push($elements, $e);
+			}
+			return $elements;
+		}else{
+			return $data;
+		}
+	}
+	
+	/* Pagination API */
+	
+	function getFirstPage($type, $returnObject = true){
+		$params = array($type->toXmlRpcStruct());
+		try{
+			$data = $this->sendMessage("filemgr.getFirstPage", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "getFirstPage");
+       	}
+		if($returnObject){
+			$page = new CAS_Filemgr_ProductPage();
+			$page->__initXmlRpc($data);
+			return $page;
+		}else{
+			return $data;
+		}
+	}
+	
+	function getNextPage($type, $page, $returnObject = true){
+		$params = array($type->toXmlRpcStruct(), $page->toXmlRpcStruct());
+		try{
+			$data = $this->sendMessage("filemgr.getNextPage", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "getNextPage");
+       	}
+		if($returnObject){
+			$page = new CAS_Filemgr_ProductPage();
+			$page->__initXmlRpc($data);
+			return $page;
+		}else{
+			return $data;
+		}	
+	}
+	
+	function getPrevPage($type, $page, $returnObject = true){
+		$params = array($type->toXmlRpcStruct(), $page->toXmlRpcStruct());
+		try{
+			$data = $this->sendMessage("filemgr.getPrevPage", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "getPrevPage");
+       	}
+		if($returnObject){
+			$page = new CAS_Filemgr_ProductPage();
+			$page->__initXmlRpc($data);
+			return $page;
+		}else{
+			return $data;
+		}			
+	}
+	
+	function getLastPage($type, $returnObject = true){
+		$params = array($type->toXmlRpcStruct());
+		try{
+			$data = $this->sendMessage("filemgr.getLastPage", $params);
+		}catch(XmlRpcFilemgrException $e){
+       		$this->reportError($e, "getLastPage");
+       	}
+		if($returnObject){
+			$page = new CAS_Filemgr_ProductPage();
+			$page->__initXmlRpc($data);
+			return $page;
+		}else{
+			return $data;
+		}		
+	}
+	
+}
+
+class XmlRpcFilemgrException extends Exception{}
+
+?>
diff --git a/0.8.1-rc1/filemgr/src/main/php/package.xml b/0.8.1-rc1/filemgr/src/main/php/package.xml
new file mode 100644
index 0000000..8ee83ec
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/php/package.xml
@@ -0,0 +1,108 @@
+<?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.
+ */
+
+  @package CAS_Filemgr
+  @author Chris A. Mattmann
+-->
+<package version="2.0" xmlns="http://pear.php.net/dtd/package-2.0"
+  xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0.xsd
+         http://pear.php.net/dtd/package-2.0
+         http://pear.php.net/dtd/package-2.0.xsd">
+  <name>Apache_OODT_CAS_Filemgr</name>
+  <channel>pear.apache.org/oodt</channel>
+  <summary>PHP CAS Filemgr Client and supporting API classes</summary>
+  <description>
+    This package provides a PHP-based XML-RPC client for the CAS filemgr
+    component. Though incomplete, the long term goals are to support the same
+    command line and API access that the Java-based client provides.
+  </description>
+  <lead>
+    <name>Chris Mattmann</name>
+    <user>mattmann</user>
+    <email>chris.mattmann@jpl.nasa.gov</email>
+    <active>yes</active>
+  </lead>
+  <date>2013-06-29</date>
+  <version>
+    <release>0.6.0</release>
+    <api>0.6.0</api>
+  </version>
+  <stability>
+    <release>stable</release>
+    <api>stable</api>
+  </stability>
+  <license
+    uri="http://www.apache.org/licenses/LICENSE-2.0">
+    Apache License, Version 2.0
+  </license>
+  <notes>
+    This package provides a PHP-based XML-RPC client for the CAS filemgr
+    component. Though incomplete, the long term goals are to support the same
+    command line and API access that the Java-based client provides.
+  </notes>
+  <contents>
+    <dir name="/" baseinstalldir="CAS/Filemgr">
+      <file name="BooleanQueryCriteria.class.php" role="php" />
+      <file name="Element.class.php" role="php" />
+      <file name="Metadata.class.php" role="php" />
+      <file name="Product.class.php" role="php" />
+      <file name="ProductPage.class.php" role="php" />
+      <file name="ProductType.class.php" role="php" />
+      <file name="Query.class.php" role="php" />
+      <file name="RangeQueryCriteria.class.php" role="php" />
+      <file name="TermQueryCriteria.class.php" role="php" />
+      <file name="XmlRpcFilemgrClient.class.php" role="php" />
+    </dir><!-- / -->
+  </contents>
+  <dependencies>
+    <required>
+      <php>
+        <min>5.1.6</min>
+      </php>
+      <pearinstaller>
+        <min>1.6.1</min>
+      </pearinstaller>
+    </required>
+  </dependencies>
+  <phprelease />
+  <changelog>
+    <release>
+      <version>
+        <release>1.0.0</release>
+        <api>1.0.0</api>
+      </version>
+      <stability>
+        <release>stable</release>
+        <api>stable</api>
+      </stability>
+      <date>2008-10-24</date>
+      <license
+        uri="http://www.apache.org/licenses/LICENCE-2.0">
+        Apache License, Version 2.0
+      </license>
+      <notes>
+        This package provides a PHP-based XML-RPC client for the CAS filemgr
+        component. Though incomplete, the long term goals are to support the
+        same command line and API access that the Java-based client provides.
+      </notes>
+    </release>
+  </changelog>
+</package>
diff --git a/0.8.1-rc1/filemgr/src/main/python/fm.conf b/0.8.1-rc1/filemgr/src/main/python/fm.conf
new file mode 100644
index 0000000..dae6438
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/python/fm.conf
@@ -0,0 +1,43 @@
+# 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.
+# */
+
+[index]
+# The path gives the name of the directory where the Lucene search engine
+# will build its indexes.  The path refers to a directory; it will be created
+# if it doesn't exist.  If it does exist, it must refer to an
+# existing Lucene index with correct sub-files present.  So, don't make this
+# directory manually, or you'll be confused by error messages!
+path = @INDEX_PATH@
+pageSize = 20
+
+[policies]
+# The 'repo' and 'validation' are comma-separated lists of URLs.  Typically, they
+# contain a single "file:" style URL that names a directory with policy XML files
+# within.  The 'user' identifies the user database.  It'll be created if it
+# doesn't exist.
+repo = @REPO_POLICY_URLS@
+validation = @VALIDATION_POLICY_URLS@
+user = @USER_DB_PATH@
+
+[factories]
+# There's no need to change anything here unless you really know what you're doing,
+# and trust me, you don't.  Don't take it personally.  It's just a fact.
+catalog = org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory
+repository = org.apache.oodt.cas.filemgr.repository.XMLRepositoryManagerFactory
+datatransfer = org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory
+validation =org.apache.oodt.cas.filemgr.validation.XMLValidationLayerFactory
diff --git a/0.8.1-rc1/filemgr/src/main/python/fm.py b/0.8.1-rc1/filemgr/src/main/python/fm.py
new file mode 100644
index 0000000..5eed046
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/python/fm.py
@@ -0,0 +1,554 @@
+#!/usr/bin/env python
+# 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.
+# */
+'''
+CAS Filemgr Python Server
+
+This is the Python server API for an authenticated Catalog and Archive System.  It uses the
+OODT Catalog and Archive System as its core, adding user/password-based authentication
+and role-based authorization.
+'''
+
+import sys, os, os.path
+import getopt, sha, pickle
+
+from ConfigParser import ConfigParser
+from org.apache.oodt.cas.filemgr.system.auth import SecureWebServer, Dispatcher, Result
+from org.apache.oodt.cas.filemgr.datatransfer import TransferStatusTracker
+from org.apache.oodt.cas.filemgr.structs import Product
+from org.apache.oodt.cas.filemgr.util import GenericFileManagerObjectFactory
+from org.apache.oodt.cas.filemgr.util import XmlRpcStructFactory as Structs
+from org.apache.oodt.cas.metadata import Metadata
+from java.lang import Boolean, Double, Integer
+from java.util import Hashtable, Vector
+
+# We choose these default factory classes because it minimizes our dependencies
+# on heavyweight external packages, like smelly old SQL databases.
+_defaultFactories = {
+	'catalog': 'org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory',
+	'repository': 'org.apache.oodt.cas.filemgr.repository.XMLRepositoryManagerFactory',
+	'datatransfer': 'org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory',
+	'validation': 'org.apache.oodt.cas.filemgr.validation.XMLValidationLayerFactory'
+}
+
+# All available permissions.  By default, the "root" user will be in the "wheel"
+# group and will have these permissions.
+_allPerms = [
+	'filemgr.addMetadata',
+	'filemgr.addProductReferences',
+	'filemgr.addProductType',
+	'filemgr.catalogProduct',
+	'filemgr.getCurrentFileTransfer',
+	'filemgr.getCurrentFileTransfers',
+	'filemgr.getElementById',
+	'filemgr.getElementByName',
+	'filemgr.getElementsByProductType',
+	'filemgr.getFirstPage',
+	'filemgr.getLastPage',
+	'filemgr.getMetadata',
+	'filemgr.getNextPage',
+	'filemgr.getNumProducts',
+	'filemgr.getPrevPage',
+	'filemgr.getProductById',
+	'filemgr.getProductByName',
+	'filemgr.getProductPctTransferred',
+	'filemgr.getProductReferences',
+	'filemgr.getProductsByProductType',
+	'filemgr.getProductTypeById',
+	'filemgr.getProductTypeByName',
+	'filemgr.getProductTypes',
+	'filemgr.getRefPctTransferred',
+	'filemgr.getTopNProducts',
+	'filemgr.handleRequest',
+	'filemgr.hasProduct',
+	'filemgr.ingestProduct',
+	'filemgr.isTransferComplete',
+	'filemgr.pagedQuery',
+	'filemgr.query',
+	'filemgr.removeFile',
+	'filemgr.removeProductTransferStatus',
+	'filemgr.setProductTransferStatus',
+	'filemgr.transferFile',
+	'filemgr.transferringProduct',
+	'usermgr.addGroup',
+	'usermgr.addPermissionToGroup',
+	'usermgr.addUser',
+	'usermgr.addUserToGroup',
+	'usermgr.removeGroup',
+	'usermgr.removePermissionFromGroup',
+	'usermgr.removeUser',
+	'usermgr.removeUserFromGroup'
+]
+
+def _toJavaBoolean(truthiness):
+	'''Convert a Python boolean into the string format that Java uses: true or false.
+	'''
+	if truthiness:
+		return 'true'
+	else:
+		return 'false'
+	
+
+def _encodePassword(pw):
+	'''Encode a password using an SHA-1 digest.
+	'''
+	return sha.new(pw).digest()
+	
+
+class User:
+	'''A user of the CAS.  Users don't have permissions directly; instead they receive
+	them implicitly by being members of groups, which do have permissions.
+	'''
+	def __init__(self, userID, name, email, password, groups=[]):
+		self.userID, self.name, self.email, self.password, self.groups = userID, name, email, password, groups
+		
+	def __cmp__(self, other):
+		return cmp(self.userID, other.userID)
+		
+	def __hash__(self):
+		return hash(self.userID)
+	
+	def __repr__(self):
+		return 'User(userID=%s,name=%s,email=%s,password=%s,groups=%r)' % (
+			self.userID, self.name, self.email, self.password, self.groups
+		)
+	
+
+class Group:
+	'''A CAS group.  The group contains a sequence of permissions, which are strings
+	that name the XML-RPC methods that the group is allowed to call.
+	'''
+	def __init__(self, groupID, name, email, perms=[]):
+		self.groupID, self.name, self.email, self.perms = groupID, name, email, perms
+		
+	def __cmp__(self, other):
+		return cmp(self.groupID, other.groupID)
+		
+	def __hash__(self):
+		return hash(self.groupID)
+		
+	def __repr__(self):
+		return 'Group(groupdID=%s,name=%s,email=%s,perms=%r)' % (self.groupdID, self.name, self.email, self.perms)
+	
+
+class UserDB:
+	'''The user database records all the users and groups.
+	'''
+	def __init__(self, users, groups, filename):
+		self.users, self.groups, self.filename = users, groups, filename
+		
+	def authenticate(self, name, password):
+		'''Authenticate a user by checking the user name and password.
+		Return true if the user's password matches the given one.  The
+		password given should be in SHA-1 digest format.
+		'''
+		user = self.users[name]
+		return user.userID == name and user.password == password
+	
+	def authorize(self, name, perm):
+		'''Authorize if the user has the given permission.  Return true if
+		the user can do it, false otherwise.
+		'''
+		user = self.users[name]
+		for group in user.groups:
+			if perm in group.perms:
+				return True
+		return False
+	
+	def save(self):
+		'''Save the user database to disk.
+		'''
+		f = file(self.filename, 'wb')
+		pickle.dump(self, f)
+		f.close()
+	
+
+class FileMgrDispatcher(Dispatcher):
+	'''The file manager dispatcher handles all XML-RPC calls.
+	'''
+	def __init__(self, catalog, repo, xfer, userDB):
+		self.catalog, self.repo, self.xfer, self.userDB = catalog, repo, xfer, userDB
+		self.tracker = TransferStatusTracker(self.catalog)
+	
+	def handleRequest(self, methodSpecifier, params, user, password):
+		'''Handle an XML-RPC request.  First, authenticate the user.  If the user's
+		authentic (by dint of providing a correct user ID and password pair), then
+		authorize if the method the user is trying to call is available.
+		'''
+		password = _encodePassword(password)
+		if self.userDB.authenticate(user, password):
+			if self.userDB.authorize(user, methodSpecifier):
+				obj, method = methodSpecifier.split('.')
+				if obj not in ('filemgr', 'usermgr'):
+					raise ValueError('Unknown object')
+				func = getattr(self, method)
+				return func(params)
+			raise ValueError('Not authorized for "%s"' % methodSpecifier)
+		raise ValueError('Illegal user name "%s" and/or password' % user)
+	
+	def getProductTypeByName(self, params):
+		return Result(None, Structs.getXmlRpcProductType(self.repo.getProductTypeByName(params[0])))
+	
+	def ingestProduct(self, params):
+		productHash, metadata, clientXfer = params
+		p = Structs.getProductFromXmlRpc(productHash)
+		p.setTransferStatus(Product.STATUS_TRANSFER)
+		self.catalog.addProduct(p)
+		
+		m = Metadata()
+		m.addMetadata(metadata)
+		self.catalog.addMetadata(m, p)
+		
+		if not clientXfer:
+	                versioner = GenericFileManagerObjectFactory.getVersionerFromClassName(p.getProductType().getVersioner())
+			versioner.createDataStoreReferences(p, m)
+			self.catalog.addProductReferences(p)
+			self.xfer.transferProduct(p)
+			p.setTransferStatus(Product.STATUS_RECEIVED)
+			self.catalog.setProductTranfserStatus(p)
+		return Result(None, p.getProductId())
+	
+	def addProductReferences(self, params):
+		self.catalog.addProductReferences(Structs.getProductFromXmlRpc(params[0]))
+		return Result(Boolean, 'true')
+	
+	def transferringProduct(self, params):
+		self.tracker.transferringProduct(Structs.getProductFromXmlRpc(params[0]))
+		return Result(Boolean, 'true')
+	
+	def removeProductTransferStatus(self, params):
+		self.tracker.removeProductTransferStatus(Structs.getProductFromXmlRpc(params[0]))
+		return Result(Boolean, 'true')
+	
+	def setProductTransferStatus(self, params):
+		self.catalog.setProductTransferStatus(Structs.getProductFromXmlRpc(params[0]))
+		return Result(Boolean, 'true')
+		
+	def getCurrentFileTransfer(self, params):
+		status = self.tracker.getCurrentFileTransfer()
+		if status is None:
+			return Result(None, Hashtable())
+		else:
+			return Result(None, Structs.getXmlRpcFileTransferStatus(status))
+	
+	def getCurrentFileTransfers(self, params):
+		xfers = self.tracker.getCurrentFileTransfers()
+		if xfers is not None and len(xfers) > 0:
+			return Result(None, Structs.getXmlRpcFileTransferStatuses(xfers))
+		else:
+			return Result(None, Vector())
+	
+	def getProductPctTransferred(self, params):
+		return Result(Double, str(self.tracker.getPctTransferred((Structs.getProductFromXmlRpc(params[0])))))
+	
+	def getRefPctTransferred(self, params):
+		pct = self.tracker.getPctTransferred(Structs.getReferenceFromXmlRpc(params[0]))
+		return Result(Double, str(pct))
+	
+	def isTransferComplete(self, params):
+		return Result(Boolean, _toJavaBoolean(self.tracker.isTransferComplete(Structs.getProductFromXmlRpc(params[0]))))
+	
+	def pagedQuery(self, params):
+		ptype = Structs.getProductTypeFromXmlRpc(params[1])
+		query = Structs.getQueryFromXmlRpc(params[0])
+		return Result(None, Structs.getXmlRpcProductPage(self.catalog.pagedQuery(query, ptype, params[2])))
+	
+	def getFirstPage(self, params):
+		ptype = Structs.getProductTypeFromXmlRpc(params[0])
+		return Result(None, Structs.getXmlRpcProductPage(self.catalog.getFirstPage(ptype)))
+	
+	def getLastPage(self, params):
+		ptype = Structs.getProductTypeFromXmlRpc(params[0])
+		return Result(None, Structs.getXmlRpcProductPage(self.catalog.getLastProductPage(ptype)))
+	
+	def getNextPage(self, params):
+		ptype = Structs.getProductTypeFromXmlRpc(params[0])
+		page = Structs.getProductPageFromXmlRpc(params[1])
+		return Result(None, Structs.getXmlRpcProductPage(self.catalog.getNextPage(ptype, page)))
+	
+	def getPrevPage(self, params):
+		ptype = Structs.getProductTypeFromXmlRpc(params[0])
+		page = Structs.getProductPageFromXmlRpc(params[1])
+		return Result(None, Structs.getXmlRpcProductPage(self.catalog.getPrevPage(ptype, page)))
+		
+	def addProductType(self, params):
+		ptype = Structs.getProductTypeFromXmlRpc(params[0])
+		self.repo.addProductType(ptype)
+		return Result(None, ptype.getProductTypeId())
+	
+	def getNumProducts(self, params):
+		ptype = Structs.getProductTypeFromXmlRpc(params[0])
+		return Result(Integer, str(self.catalog.getNumProducts(ptype)))
+	
+	def getTopNProducts(self, params):
+		if len(params) == 1:
+			return Result(None, Structs.getXmlRpcProductList(self.catalog.getTopNProducts(params[0])))
+		ptype = Structs.getProductTypeFromXmlRpc(params[1])
+		return Result(None, Structs.getXmlRpcProductList(self.catalog.getTopNProducts(params[0], ptype)))
+	
+	def hasProduct(self, params):
+		p = self.catalog.getProductByName(params[0])
+		return Result(Boolean, _toJavaBoolean(p is not None and p.transferStatus == Product.STATUS_RECEIVED))
+	
+	def getMetadata(self, params):
+		return Result(None, self.catalog.getMetadata(Structs.getProductFromXmlRpc(params[0])).getHashtable())
+	
+	def getProductTypes(self, params):
+		return Result(None, Structs.getXmlRpcProductList(self.repo.getProductTypes()))
+	
+	def getProductReferences(self, params):
+		p = Structs.getProductFromXmlRpc(params[0])
+		return Result(None, Structs.getXmlRpcReferences(self.catalog.getProductReferences(p)))
+	
+	def getProductById(self, params):
+		return Result(None, Structs.getXmlRpcProduct(self.catalog.getProductById(params[0])))
+	
+	def getProductByName(self, params):
+		return Result(None, Structs.getXmlRpcProduct(self.catalog.getProductByName(params[0])))
+	
+	def getProductsByProductType(self, params):
+		ptype = Structs.getProductTypeFromXmlRpc(params[0])
+		return Result(None, Structs.getXmlRpcProductList(self.catalog.getProductsByProductType(ptype)))
+	
+	def getElementsByProductType(self, params):
+		ptype = Structs.getProductTypeFromXmlRpc(params[0])
+		return Structs.getXmlRpcElementList(self.catalog.getValidationLayer().getElements(ptype))
+	
+	def getElementById(self, params):
+		return Structs.getXmlRpcElement(self.catalog.getValidationLayer().getElementById(params[0]))
+		
+	def getElementByName(self, params):
+		return Structs.getXmlRpcElement(self.catalog.getValidationLayer().getElementByName(params[0]))
+	
+	def query(self, params):
+		q = Structs.getQueryFromXmlRpc(params[0])
+		ptype = Structs.getProductTypeFromXmlRpc(params[1])
+		ids = self.catalog.query(q, ptype)
+		if ids is not None and len(ids) > 0:
+			return Result(None, [self.catalog.getProductById(i) for i in ids])
+		return Result(None, Vector())
+	
+	def getProductTypeById(self, params):
+		ptype = self.repo.getProductTypeById(params[0])
+		return Result(None, Structs.getXmlRpcProductType(ptype))
+	
+	def catalogProduct(self, params):
+		p = Structs.getProductFromXmlRpc(params[0])
+		return Result(None, self.catalog.addProduct(p))
+	
+	def addMetadata(self, params):
+		p = Structs.getProductFromXmlRpc(params[0])
+		m = Metadata()
+		m.addMetadata(params[1])
+		self.catalog.addMetadata(m, p)
+		return Result(Boolean, 'true')
+		
+	def transferFile(self, params):
+		outFile, data, offset, numBytes = params
+		if os.path.exists(outFile):
+			out = file(outFile, 'ab')
+		else:
+			dirPath = os.dirname(outFile)
+			os.makedirs(dirPath)
+			out = file(outFile, 'wb')
+		out.seek(offset)
+		out.write(data)
+		out.close()
+		return Result(Boolean, 'true')
+	
+	def removeFile(self, params):
+		os.remove(params[0])
+		return Result(Boolean, 'true')
+		
+	def addUser(self, params):
+		userID = params[0]
+		user = User(userID, params[1], params[2], _encodePassword(params[3]), [])
+		self.userDB.users[userID] = user
+		self.userDB.save()
+		return Result(Boolean, 'true')
+		
+	def removeUser(self, params):
+		del self.userDB.users[params[0]]
+		return Result(Boolean, 'true')
+	
+	def addGroup(self, params):
+		groupID = params[0]
+		group = Group(groupID, params[1], params[2])
+		self.userDB.groups[groupID] = group
+		self.userDB.save()
+		return Result(Boolean, 'true')
+	
+	def removeGroup(self, params):
+		groupID = params[0]
+		del self.userDB.groups[groupID]
+		for user in self.userDB.users.itervalues():
+			indexes = []
+			index = 0
+			for group in user.groups:
+				if group.groupID == groupID:
+					indexes.append(index)
+				index += 1
+			indexes.reverse()
+			for index in indexes:
+				del user.groups[index]
+		self.userDB.save()
+		return Result(Boolean, 'true')
+		
+	def addUserToGroup(self, params):
+		self.userDB.users[params[0]].groups.append(self.userDB.groups[params[1]])
+		return Result(Boolean, 'true')
+
+	def removeUserFromGroup(self, params):
+		groupID = params[1]
+		user = self.userDB.users[params[0]]
+		indexes = []
+		index = 0
+		for group in user.group:
+			if group.groupID == groupID:
+				indexes.append(index)
+			index += 1
+		indexes.reverse()
+		for index in indexes:
+			del user.groups[index]
+		self.userDB.save()
+		return Result(Boolean, 'true')
+		
+	def addPermissionToGroup(self, params):
+		self.userDB.groups[params[0]].perms.append(params[1])
+		self.userDB.save()
+		return Result(Boolean, 'true')
+		
+	def removePermissionFromGroup(self, params):
+		permName = params[1]
+		group = self.userDB.groups[params[0]]
+		indexes = []
+		index = 0
+		for perm in group.perms:
+			if perm == permName:
+				indexes.append(index)
+		indexes.reverse()
+		for index in indexes:
+			del group.perms[index]
+		self.userDB.save()
+		return Result(Boolean, 'true')
+	
+
+def _usage():
+	'''Show a usage message to the stderr and quit.
+	'''
+	print >>sys.stderr, 'Usage: %s [-c <configFile>]' % sys.argv[0]
+	print >>sys.stderr, '   or: %s [--config=<configFile>]' % sys.argv[0]
+	sys.exit(2)
+	
+
+def _parseCommandLine():
+	'''Parse the command line options.  If any.  The only option is -c (or --config)
+	that names a configuration file to use.  If none given, reasonable defaults are
+	used.  Well, mostly reasonable.
+	'''
+	try:
+		opts, args = getopt.getopt(sys.argv[1:], 'c:', 'config=')
+	except getopt.GetoptError:
+		_usage()
+	configFile = None
+	for option, arg in opts:
+		if option in ('-c', '--config'):
+			configFile = arg
+			if configFile is None or len(configFile) == 0:
+				_usage()
+	return configFile
+	
+
+def _getConfig(configFile):
+	'''Get the configuration.  This populates a configuration with default values
+	and then overwrites them with the configFile, which may be None (in which case,
+	no overwriting happens).
+	'''
+	configParser = ConfigParser()
+	configParser.add_section('factories')
+	for key, val in _defaultFactories.iteritems():
+		configParser.set('factories', key, val)
+
+	configParser.add_section('index')
+	configParser.set('index', 'path', 'index')
+	configParser.set('index', 'pageSize', '20')
+
+	current = '/'.join(os.path.split(os.getcwd()))
+	configParser.add_section('policies')
+	configParser.set('policies', 'repo', 'file:%s/policy' % current)
+	configParser.set('policies', 'validation', 'file:%s/policy' % current)
+	configParser.set('policies', 'user', '%s/user.db' % current)
+
+	if configFile is not None:
+		configParser.readfp(file(configFile))
+	return configParser
+	
+
+def _setJavaProperties(config):
+	'''Set Java-based properties.  The Java-based cas expects a whole bunch of
+	system properties to be set, sort of like global variables.  Woot!  Global
+	variables!
+	'''
+	from java.lang import System
+	System.setProperty('org.apache.oodt.cas.filemgr.catalog.lucene.idxPath', config.get('index', 'path'))
+	System.setProperty('org.apache.oodt.cas.filemgr.catalog.lucene.pageSize', config.get('index', 'pageSize'))
+	System.setProperty('org.apache.oodt.cas.filemgr.repositorymgr.dirs', config.get('policies', 'repo'))
+	System.setProperty('org.apache.oodt.cas.filemgr.validation.dirs', config.get('policies', 'validation'))
+	System.setProperty('org.apache.oodt.cas.filemgr.datatransfer.remote.chunkSize', '1024')
+	System.setProperty('filemgr.repository.factory', config.get('factories', 'repository'))
+	System.setProperty('filemgr.catalog.factory', config.get('factories', 'catalog'))
+	System.setProperty('filemgr.datatransfer.factory', config.get('factories', 'datatransfer'))
+	System.setProperty('filemgr.validationLayer.factory', config.get('factories', 'validation'))
+	
+def _getUserDB(path):
+	'''Get the user database, creating it if necessary.
+	'''
+	try:
+		f = file(path, 'rb')
+		db = pickle.load(f)
+		f.close()
+		db.filename = path
+		db.save()
+	except:
+		wheel = Group('wheel', 'Administrators', 'teh.power@power.users', _allPerms)
+		root = User('root', 'Super User', 'teh.root@power.users', _encodePassword('poipu'), [wheel])
+		db = UserDB({'root': root}, {'wheel': wheel}, path)
+		db.save()
+	return db
+	
+
+def main():
+	'''Start the CAS Filemgr Backend.
+	'''
+	configFile = _parseCommandLine()
+	configParser = _getConfig(configFile)
+	_setJavaProperties(configParser)
+
+	catalog = GenericFileManagerObjectFactory.getCatalogServiceFromFactory(configParser.get('factories', 'catalog'))
+	repo = GenericFileManagerObjectFactory.getRepositoryManagerServiceFromFactory(configParser.get('factories', 'repository'))
+	xfer = GenericFileManagerObjectFactory.getDataTransferServiceFromFactory(configParser.get('factories', 'datatransfer'))
+	userDB = _getUserDB(configParser.get('policies', 'user'))
+
+	ws = SecureWebServer(1999)
+	ws.addDispatcher(FileMgrDispatcher(catalog, repo, xfer, userDB))
+	ws.start()
+	
+
+if __name__ == '__main__':
+	main()
+	
diff --git a/0.8.1-rc1/filemgr/src/main/python/setclasspath.sh b/0.8.1-rc1/filemgr/src/main/python/setclasspath.sh
new file mode 100755
index 0000000..1fbfc48
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/python/setclasspath.sh
@@ -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.
+# */
+setenv CLASSPATH ${HOME}/.m2/repository/org.apache.oodt.cas-filemgr/1.7.0-dev/cas-filemgr-1.7.0-dev.jar:${HOME}/.m2/repository/xmlrpc/xmlrpc/2.1-dev/xmlrpc-2.1-dev.jar:${HOME}/.m2/repository/org.apache.oodt.cas-metadata/1.5.0/cas-metadata-1.5.0.jar:${HOME}/.m2/repository/org/apache/lucene/lucene-core/2.0.0/lucene-core-2.0.0.jar:${HOME}/.m2/repository/jug/jug-asl/2.0.0/jug-asl-2.0.0.jar
diff --git a/0.8.1-rc1/filemgr/src/main/resources/CAS File Manager User Guide.doc b/0.8.1-rc1/filemgr/src/main/resources/CAS File Manager User Guide.doc
new file mode 100644
index 0000000..b24fd2f
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/CAS File Manager User Guide.doc
Binary files differ
diff --git a/0.8.1-rc1/filemgr/src/main/resources/bash_aliases.txt b/0.8.1-rc1/filemgr/src/main/resources/bash_aliases.txt
new file mode 100644
index 0000000..17ca480
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/bash_aliases.txt
@@ -0,0 +1,30 @@
+#  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.
+#
+###############BASH SHELL ALIASES###############
+#
+# The following aliases must be used within a filemgr's
+# bin directory since relative pathing is being used.  This block also
+# assumes that the filemgr is running on port 9000 (the default port of filemgr)
+#
+# For complete documentation see: 
+#     https://cwiki.apache.org/confluence/display/OODT/BASH+and+TCSH+shell+tools+for+File+Manager
+#
+alias lucenequery="java -Dorg.apache.oodt.cas.filemgr.properties=../etc/filemgr.properties -Djava.ext.dirs=../lib org.apache.oodt.cas.filemgr.tools.QueryTool --url http://localhost:9000 --lucene -query "
+alias sqlquery="java -Dorg.apache.oodt.cas.filemgr.properties=../etc/filemgr.properties -Djava.ext.dirs=../lib org.apache.oodt.cas.filemgr.tools.QueryTool --url http://localhost:9000 --sql -query "
+alias fmdel="java -Dorg.apache.oodt.cas.filemgr.properties=../etc/filemgr.properties -Djava.ext.dirs=../lib org.apache.oodt.cas.filemgr.tools.DeleteProduct --fileManagerUrl http://localhost:9000 --read"
+alias metdump="java -Djava.ext.dirs=../lib org.apache.oodt.cas.filemgr.tools.MetadataDumper --url http://localhost:9000 --out . --productId "
+#
+################################################
\ No newline at end of file
diff --git a/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-core-schema-oracle.sql b/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-core-schema-oracle.sql
new file mode 100644
index 0000000..3422ab2
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-core-schema-oracle.sql
@@ -0,0 +1,42 @@
+--  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.

+

+

+SET ECHO ON;

+ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD hh24:mi:ss';

+

+CREATE TABLE PRODUCTS (

+  PRODUCT_ID number(11) NOT NULL ,

+  PRODUCT_STRUCTURE VARCHAR(20)  DEFAULT  ''NOT NULL, 

+  PRODUCT_TYPE_ID number(11)  DEFAULT  '0'NOT NULL, 

+  PRODUCT_NAME VARCHAR(255)  DEFAULT  ''NOT NULL, 

+  PRODUCT_TRANSFER_STATUS VARCHAR(255) DEFAULT 'TRANSFERING' NOT NULL,

+  PRIMARY KEY  (PRODUCT_ID)

+);

+

+-- Example PRODUCTS table using PRODUCT_ID of type string

+-- CREATE TABLE PRODUCTS (

+--   PRODUCT_ID VARCHAR(100) NOT NULL ,

+--   PRODUCT_STRUCTURE VARCHAR(20)  DEFAULT  ''NOT NULL, 

+--   PRODUCT_TYPE_ID number(11)  DEFAULT  '0'NOT NULL, 

+--   PRODUCT_NAME VARCHAR(255)  DEFAULT  ''NOT NULL, 

+--   PRODUCT_TRANSFER_STATUS VARCHAR(255) DEFAULT 'TRANSFERING' NOT NULL,

+--   PRODUCT_DATETIME DATE NOT NULL,

+--  PRIMARY KEY  (PRODUCT_ID)

+--);

+

+CREATE INDEX PRODUCTS_idx ON PRODUCTS(product_id);  

+

+EXIT;

diff --git a/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-dyn-catalog-schema.sql b/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-dyn-catalog-schema.sql
new file mode 100644
index 0000000..b5b0d64
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-dyn-catalog-schema.sql
@@ -0,0 +1,35 @@
+--  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.
+
+
+CREATE TABLE YourProductTypeName_metadata
+(
+  pkey int(10) unsigned primary KEY AUTO_INCREMENT, 
+  product_id int NOT NULL,
+  element_id varchar(1000) NOT NULL,
+  metadata_value varchar(2500) NOT NULL
+)
+
+CREATE TABLE YourProductTypeName_reference
+(
+  pkey int(10) unsigned primary KEY AUTO_INCREMENT,
+  product_id int NOT NULL,
+  product_orig_reference varchar(2000) NOT NULL,
+  product_datastore_reference varchar(2000), 
+  product_reference_filesize int NOT NULL,
+  product_reference_mimetype varchar(50)
+)
+
+
diff --git a/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-repositorymgr-schema-oracle.sql b/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-repositorymgr-schema-oracle.sql
new file mode 100644
index 0000000..fc1fff0
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-repositorymgr-schema-oracle.sql
@@ -0,0 +1,31 @@
+--  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.

+

+

+SET ECHO ON;

+ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD hh24:mi:ss';

+

+CREATE TABLE PRODUCT_TYPES (

+  PRODUCT_TYPE_ID number(11) NOT NULL ,

+  PRODUCT_TYPE_NAME VARCHAR(255)  DEFAULT  ''NOT NULL, 

+  PRODUCT_TYPE_DESCRIPTION VARCHAR(255)  DEFAULT  ''NOT NULL, 

+  PRODUCT_TYPE_VERSIONER_CLASS VARCHAR(255) DEFAULT '',

+  PRODUCT_TYPE_REPOSITORY_PATH VARCHAR(255)  DEFAULT  ''NOT NULL, 

+  PRIMARY KEY  (PRODUCT_TYPE_ID)

+);

+ 

+CREATE INDEX PRODUCT_TYPES_IDX  ON  PRODUCT_TYPES(seqno);  

+

+EXIT;

diff --git a/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-schema-mysql.sql b/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-schema-mysql.sql
new file mode 100644
index 0000000..b0f9e5a
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-schema-mysql.sql
@@ -0,0 +1,84 @@
+#  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.
+
+# Connection: localhost

+# Host: spawn

+# Saved: 2006-01-02 18:12:06

+# 

+
+# Host: spawn
+# Database: test_cas
+# Table: 'elements'
+# 
+CREATE TABLE `elements` (
+  `element_id` int(11) NOT NULL auto_increment,
+  `element_name` varchar(255) NOT NULL default '',
+  `data_type_id` int(11) NOT NULL default '0',
+  `dc_element` varchar(100) default '',
+  `element_description` varchar(255) NOT NULL default '',
+  PRIMARY KEY  (`element_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1; 
+
+# Host: spawn
+# Database: test_cas
+# Table: 'product_type_element_map'
+# 
+CREATE TABLE `product_type_element_map` (
+  `product_type_element_map_id` int(11) NOT NULL auto_increment,
+  `product_type_id` int(11) NOT NULL default '0',
+  `element_id` int(11) NOT NULL default '0',
+  PRIMARY KEY  (`product_type_element_map_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1; 
+
+# Host: spawn
+# Database: test_cas
+# Table: 'product_types'
+# 
+CREATE TABLE `product_types` (
+  `product_type_id` int(11) NOT NULL auto_increment,
+  `product_type_name` varchar(255) NOT NULL default '',
+  `product_type_description` varchar(255) NOT NULL default '',
+  `product_type_versioner_class` varchar(255) default '',
+  `product_type_repository_path` varchar(255) NOT NULL default '',
+  PRIMARY KEY  (`product_type_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1; 
+
+# Host: spawn
+# Database: test_cas
+# Table: 'products'
+# 
+CREATE TABLE `products` (
+  `product_id` int(11) NOT NULL auto_increment,
+  `product_structure` varchar(20) NOT NULL default '',
+  `product_type_id` int(11) NOT NULL default '0',
+  `product_name` varchar(255) NOT NULL default '',

+  `product_transfer_status` varchar(255) NOT NULL default 'TRANSFERING',
+  PRIMARY KEY  (`product_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1; 
+
+# Example of 'products' table using a 'product_id' column of type string
+# Host: spawn
+# Database: test_cas
+# Table: 'products'
+# 
+#CREATE TABLE `products` (
+#  `product_id` varchar(100) NOT NULL,
+#  `product_structure` varchar(20) NOT NULL default '',
+#  `product_type_id` int(11) NOT NULL default '0',
+#  `product_name` varchar(255) NOT NULL default '',
+#  `product_transfer_status` varchar(255) NOT NULL default 'TRANSFERING',
+#  `product_datetime` datetime NOT NULL,
+#  PRIMARY KEY  (`product_id`)
+#) ENGINE=MyISAM DEFAULT CHARSET=latin1; 
\ No newline at end of file
diff --git a/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-validationlayer-schema-oracle.sql b/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-validationlayer-schema-oracle.sql
new file mode 100644
index 0000000..2e53a4d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/cas-filemgr-validationlayer-schema-oracle.sql
@@ -0,0 +1,45 @@
+--  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.

+

+

+SET ECHO ON;

+ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD hh24:mi:ss';

+

+CREATE TABLE ELEMENTS (

+  ELEMENT_ID number(11) NOT NULL ,

+  ELEMENT_NAME VARCHAR(255)  DEFAULT  ''NOT NULL, 

+  DATA_TYPE_ID number(11)  DEFAULT  '0'NOT NULL, 

+  DC_ELEMENT VARCHAR(100) DEFAULT '',

+  ELEMENT_DESCRIPTION VARCHAR(255)  DEFAULT  ''NOT NULL, 

+  PRIMARY KEY  (ELEMENT_ID)

+);

+

+CREATE TABLE PRODUCT_TYPE_ELEMENT_MAP (

+  PRODUCT_TYPE_ELEMENT_MAP_ID number(11) NOT NULL ,

+  PRODUCT_TYPE_ID number(11)  DEFAULT  '0'NOT NULL, 

+  ELEMENT_ID number(11)  DEFAULT  '0'NOT NULL, 

+  PRIMARY KEY  (PRODUCT_TYPE_ELEMENT_MAP_ID)

+);

+

+CREATE TABLE SUB_TO_SUPER_MAP (

+  PRODUCT_TYPE_ID number(11) DEFAULT '0'NOT NULL,

+  PARENT_ID number(11) DEFAULT '0'NOT NULL,

+  PRIMARY KEY (PRODUCT_TYPE_ID)

+);	

+

+CREATE INDEX ELEMENTS_IDX  ON  ELEMENTS(seqno);  

+CREATE INDEX PRDCT_TYP_LMNT_MP_DX  ON  PRODUCT_TYPE_ELEMENT_MAP(seqno);  

+CREATE INDEX SUB_TO_SUPER_MP_DX ON SUB_TO_SUPER_MAP(seqno);

+EXIT;

diff --git a/0.8.1-rc1/filemgr/src/main/resources/cas_filemgr_create_oracle_sequences.sql b/0.8.1-rc1/filemgr/src/main/resources/cas_filemgr_create_oracle_sequences.sql
new file mode 100644
index 0000000..40f98d2
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/cas_filemgr_create_oracle_sequences.sql
@@ -0,0 +1,76 @@
+/*
+  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.
+*/
+
+create sequence products_seq
+start with 1
+increment by 1
+nomaxvalue;
+
+create trigger products_trigger
+before insert on products
+for each row
+begin
+select products_seq.nextval into :new.product_id from dual;
+end;
+
+create sequence product_types_seq
+start with 1
+increment by 1
+nomaxvalue;
+
+create trigger product_types_trigger
+before insert on product_types
+for each row
+begin
+select product_types_seq.nextval into :new.product_type_id from dual;
+end;
+
+create sequence elements_seq
+start with 1
+increment by 1
+nomaxvalue;
+
+create trigger elements_trigger
+before insert on elements
+for each row
+begin
+select elements_seq.nextval into :new.element_id from dual;
+end;
+
+create sequence product_type_element_map_seq
+start with 1
+increment by 1
+nomaxvalue;
+
+create trigger ptype_element_map_trigger
+before insert on product_type_element_map
+for each row
+begin
+select product_type_element_map_seq.nextval into :new.product_type_element_map_id from dual;
+end;
+
+create sequence data_types_seq
+start with 1
+increment by 1
+nomaxvalue;
+
+create trigger data_types_trigger
+before insert on data_types
+for each row
+begin
+select data_types_seq.nextval into :new.data_type_id from dual;
+end;
diff --git a/0.8.1-rc1/filemgr/src/main/resources/catalog.typemap.properties b/0.8.1-rc1/filemgr/src/main/resources/catalog.typemap.properties
new file mode 100644
index 0000000..3453124
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/catalog.typemap.properties
@@ -0,0 +1,23 @@
+#  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.
+
+# Example Product Type to Table Mappings
+# (for product types with LONG names, allows us to get
+# around Oracle's sad 31 char table name limit)
+
+# Note, the key on the left is the actual return of {@link ProductType#getName()}
+# and the value on the right is the mapped table name
+
+GenericFile=file
diff --git a/0.8.1-rc1/filemgr/src/main/resources/cmd-line-actions.xml b/0.8.1-rc1/filemgr/src/main/resources/cmd-line-actions.xml
new file mode 100644
index 0000000..12b71e9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/cmd-line-actions.xml
@@ -0,0 +1,123 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+	<bean id="addProductType" class="org.apache.oodt.cas.filemgr.cli.action.AddProductTypeCliAction">
+		<property name="description" value="Adds a ProductType to list of supported ProductTypes" />
+	</bean>
+  <bean id="deleteProductByName" class="org.apache.oodt.cas.filemgr.cli.action.DeleteProductByNameCliAction">
+    <property name="description" value="Delete Product by name" />
+  </bean>
+  <bean id="deleteProductById" class="org.apache.oodt.cas.filemgr.cli.action.DeleteProductByIdCliAction">
+    <property name="description" value="Delete Product by ID" />
+  </bean>
+  <bean id="dumpMetadata" class="org.apache.oodt.cas.filemgr.cli.action.DumpMetadataCliAction">
+    <property name="description" value="Dumps Product Metadata out to XML" />
+  </bean>
+	<bean id="getCurrentTransfer" class="org.apache.oodt.cas.filemgr.cli.action.GetCurrentTransferCliAction">
+    <property name="description" value="Gets the status of the current Product file transfer" />
+  </bean>
+  <bean id="getCurrentTransfers" class="org.apache.oodt.cas.filemgr.cli.action.GetCurrentTransfersCliAction">
+    <property name="description" value="Gets the status of the current Product file transfers" />
+  </bean>
+  <bean id="getFilePercentTransferred" class="org.apache.oodt.cas.filemgr.cli.action.GetFilePercentTransferredCliAction">
+    <property name="description" value="Gets the percent amount transferred of given file" />
+  </bean>
+  <bean id="getFirstPage" class="org.apache.oodt.cas.filemgr.cli.action.GetFirstPageCliAction">
+    <property name="description" value="Gets first page of Products of given ProductType" />
+  </bean>
+  <bean id="getLastPage" class="org.apache.oodt.cas.filemgr.cli.action.GetLastPageCliAction">
+    <property name="description" value="Gets last page of Products of given ProductType" />
+  </bean>
+  <bean id="getNextPage" class="org.apache.oodt.cas.filemgr.cli.action.GetNextPageCliAction">
+    <property name="description" value="Gets next page of Products of given ProductType" />
+  </bean>
+  <bean id="getNumProducts" class="org.apache.oodt.cas.filemgr.cli.action.GetNumProductsCliAction">
+    <property name="description" value="Gets number of Products ingested for a given ProductType" />
+  </bean>
+  <bean id="getPrevPage" class="org.apache.oodt.cas.filemgr.cli.action.GetPrevPageCliAction">
+    <property name="description" value="Gets prev page of Products of given ProductType" />
+  </bean>
+  <bean id="getProductByName" class="org.apache.oodt.cas.filemgr.cli.action.GetProductByNameCliAction">
+    <property name="description" value="Get Product info by name" />
+  </bean>
+  <bean id="getProductById" class="org.apache.oodt.cas.filemgr.cli.action.GetProductByIdCliAction">
+    <property name="description" value="Gets Product info by ID" />
+  </bean>
+  <bean id="getProductPercentTransferred" class="org.apache.oodt.cas.filemgr.cli.action.GetProductPercentTransferredCliAction">
+    <property name="description" value="Gets percent amount transferred of a Products data files" />
+  </bean>
+  <bean id="getProductTypeByName" class="org.apache.oodt.cas.filemgr.cli.action.GetProductTypeByNameCliAction">
+    <property name="description" value="Gets a ProductType by its name" />
+  </bean>
+  <bean id="hasProduct" class="org.apache.oodt.cas.filemgr.cli.action.HasProductCliAction">
+    <property name="description" value="Checks if Product with given name has been ingested" />
+  </bean>
+  <bean id="ingestProduct" class="org.apache.oodt.cas.filemgr.cli.action.IngestProductCliAction">
+    <property name="description" value="Ingests a Product" />
+  </bean>
+  <bean id="luceneQuery" class="org.apache.oodt.cas.filemgr.cli.action.LuceneQueryCliAction">
+    <property name="description" value="Queries by parsing an Lucene-like query into a FileManager Query" />
+  </bean>
+  <bean id="retrieveFilesById" class="org.apache.oodt.cas.filemgr.cli.action.RetrieveFilesCliAction">
+    <property name="description" value="Retrieve a Product's files by Product ID" />
+  </bean>
+  <bean id="retrieveFilesByName" class="org.apache.oodt.cas.filemgr.cli.action.RetrieveFilesCliAction">
+    <property name="description" value="Retrieve a Product's files by Product name" />
+  </bean>
+  <bean id="sqlQuery" class="org.apache.oodt.cas.filemgr.cli.action.SqlQueryCliAction">
+    <property name="description" value="Queries by parsing an SQL-like query into a FileManager Query" />
+    <property name="detailedDescription">
+      <value>
+ This supports sending queries to the FileManager in form of
+  SELECT [Elements] FROM [ProductTypes] WHERE [where-clause], where:
+   - [Elements]: is a comma separated list of Element names; may also be * which
+    represents all Elements
+   - [ProductTypes]: is a comma separated list of ProductType names; may also
+    be * which represents all ProductTypes
+   - [where-clause]: is an optional Element name filter supporting the following:
+      * AND and OR boolean operators
+      * () grouping of queries
+      * element-name == 'element-value'
+      * element-name &#60; 'element-value'
+      * element-name &#62; 'element-value'
+      * element-name &#60;= 'element-value'
+      * element-name &#62;= 'element-value'"
+
+ An additional post-query FilterAlgor can also be specified where you specify
+  which Metadata fields which should be used as each Product's StartDateTime,
+  EndDateTime, and Priority values
+      </value>
+    </property>
+    <property name="examples">
+      <value>
+ (Assume you have a ProductType, GenericFile, which supports the
+    Elements: Filename, NominalDate, Group, and DataVersion)
+  $ ./filemgr-client -u http://localhost:9000 -op -sql
+    -q "SELECT Filename FROM GenericFile WHERE (NominalDate == '2011-20-10' OR
+      NominalDate == '2011-20-11') AND Group == 'Test' AND DataVersion > '1.0'"
+ (Returns all Products in FileManager -- use with care)
+  $ ./filemgr-client -u http://localhost:9000 -op -sql -q "SELECT * FROM *"
+      </value>
+    </property>
+  </bean>
+</beans>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/cmd-line-options.xml b/0.8.1-rc1/filemgr/src/main/resources/cmd-line-options.xml
new file mode 100644
index 0000000..f560299
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/cmd-line-options.xml
@@ -0,0 +1,1175 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+	<bean id="url" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="u" />
+		<property name="longOption" value="url" />
+		<property name="description" value="File Manager URL" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="url" />
+		<property name="required" value="true" />
+		<property name="handler">
+			<bean
+				class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+				<property name="propertyNames">
+					<list>
+						<value>org.apache.oodt.cas.filemgr.url</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="operation" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+		<property name="shortOption" value="op" />
+		<property name="longOption" value="operation" />
+		<property name="description"
+			value="Declare that you wish to present an operation" />
+		<property name="hasArgs" value="false" />
+		<property name="required" value="true" />
+		<property name="subOptions">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="addProductType" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="deleteProductById" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="deleteProductByName" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="ingestProduct" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="hasProduct" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getProductTypeByName" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getNumProducts" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getFirstPage" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getNextPage" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getPrevPage" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getLastPage" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getCurrentTransfer" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getCurrentTransfers" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getProductById" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getProductByName" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getProductPctTransferred" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getFilePctTransferred" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="sqlQuery" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="dumpMetadata" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="luceneQuery" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="retrieveFilesById" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="retrieveFilesByName" p:required="false" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- AddProductType Options -->
+	<bean id="addProductType" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="addPT" />
+		<property name="longOption" value="addProductType" />
+		<property name="description" value="Triggers addProductType Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>addProductType</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addProductType" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+  <bean id="typeName" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="tn" />
+    <property name="longOption" value="typeName" />
+    <property name="description" value="ProductType name" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="product-type-name" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="addProductType" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="addProductType" p:methodName="setProductTypeName" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="typeDesc" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="td" />
+    <property name="longOption" value="typeDesc" />
+    <property name="description" value="ProductType description" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="description" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="addProductType" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="addProductType" p:methodName="setProductTypeDescription" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="repository" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="repo" />
+    <property name="longOption" value="repository" />
+    <property name="description" value="ProductType repository" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-path" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="addProductType" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="addProductType" p:methodName="setFileRepositoryPath" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="versionClass" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="vc" />
+    <property name="longOption" value="versionClass" />
+    <property name="description" value="ProductType versioner class" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="addProductType" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="addProductType" p:methodName="setVersioner" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <!-- IngestProduct Options -->
+  <bean id="ingestProduct" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="ingest" />
+    <property name="longOption" value="ingestProduct" />
+    <property name="description" value="Triggers ingestProduct Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>ingestProduct</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="productStructure" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="ps" />
+    <property name="longOption" value="productStructure" />
+    <property name="description" value="Hierarchical | Flat" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="structure-type" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="ingestProduct" p:methodName="setProductStructure" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="metadataFile" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="mf" />
+    <property name="longOption" value="metadataFile" />
+    <property name="description" value="Metadata XML file path or URL" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-path-or-url" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="clientTransfer" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="ct" />
+    <property name="longOption" value="clientTransfer" />
+    <property name="description" value="User client transferer" />
+    <property name="hasArgs" value="false" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="dataTransfer" p:required="true" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="dataTransfer" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="dt" />
+    <property name="longOption" value="dataTransfer" />
+    <property name="description" value="DataTransferer factory class" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="ingestProduct" p:methodName="setDataTransferer" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="refs" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="rs" />
+    <property name="longOption" value="refs" />
+    <property name="description" value="Data file path or URL" />
+    <property name="type" value="java.util.List" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-path-or-url" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="ingestProduct" p:methodName="setReferences" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <!-- HasProduct Options -->
+  <bean id="hasProduct" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="product" />
+    <property name="longOption" value="hasProduct" />
+    <property name="description" value="Triggers hasProduct Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>hasProduct</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="hasProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetProductTypeByName Options -->
+  <bean id="getProductTypeByName" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="ptbyn" />
+    <property name="longOption" value="getProductTypeByName" />
+    <property name="description" value="Triggers getProductTypeByName Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getProductTypeByName</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductTypeByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetNumProducts Options -->
+  <bean id="getNumProducts" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="num" />
+    <property name="longOption" value="getNumProducts" />
+    <property name="description" value="Triggers getNumProducts Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getNumProducts</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNumProducts" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetFirstPage Options -->
+  <bean id="getFirstPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="page1" />
+    <property name="longOption" value="getFirstPage" />
+    <property name="description" value="Triggers getFirstPage Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getFirstPage</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getFirstPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetNextPage Options -->
+  <bean id="getNextPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="next" />
+    <property name="longOption" value="getNextPage" />
+    <property name="description" value="Triggers getNextPage Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getNextPage</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNextPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetPrevPage Options -->
+  <bean id="getPrevPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="prev" />
+    <property name="longOption" value="getPrevPage" />
+    <property name="description" value="Triggers getPrevPage Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getPrevPage</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getPrevPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetLastPage Options -->
+  <bean id="getLastPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="last" />
+    <property name="longOption" value="getLastPage" />
+    <property name="description" value="Triggers getLastPage Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getLastPage</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getLastPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetCurrentTransfer Options -->
+  <bean id="getCurrentTransfer" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="curTran" />
+    <property name="longOption" value="getCurrentTransfer" />
+    <property name="description" value="Triggers getCurrentTransfer Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getCurrentTransfer</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getCurrentTransfer" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetCurrentTransfers Options -->
+  <bean id="getCurrentTransfers" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="curTrans" />
+    <property name="longOption" value="getCurrentTransfers" />
+    <property name="description" value="Triggers getCurrentTransfers Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getCurrentTransfers</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getCurrentTransfers" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetProductPercentTransferred Options -->
+  <bean id="getProductPctTransferred" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="pctTrans" />
+    <property name="longOption" value="getProductPctTransferred" />
+    <property name="description" value="Triggers getProductPercentTransferred Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getProductPercentTransferred</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductPercentTransferred" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetFilePercentTransferred Options -->
+  <bean id="getFilePctTransferred" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="filePctTrans" />
+    <property name="longOption" value="getFilePctTransferred" />
+    <property name="description" value="Triggers getFilePercentTransferred Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getFilePercentTransferred</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getFilePercentTransferred" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="origRef" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="or" />
+    <property name="longOption" value="origRef" />
+    <property name="description" value="Original reference" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-path-or-url" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getFilePercentTransferred" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <!-- SqlQuery Options -->
+  <bean id="sqlQuery" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="sql" />
+    <property name="longOption" value="sqlQuery" />
+    <property name="description" value="Triggers sqlQuery Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>sqlQuery</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+
+
+  <!-- GetProductById Options -->
+  <bean id="getProductById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="pbyid" />
+    <property name="longOption" value="getProductById" />
+    <property name="description" value="Triggers getProductById Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getProductById</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductById" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetProductByName Options -->
+  <bean id="getProductByName" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="pbyn" />
+    <property name="longOption" value="getProductByName" />
+    <property name="description" value="Triggers getProductByName Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getProductByName</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- DeleteProductById Options -->
+  <bean id="deleteProductById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="dbyid" />
+    <property name="longOption" value="deleteProductById" />
+    <property name="description" value="Triggers deleteProductById Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>deleteProductById</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="deleteProductById" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- DeleteProductByName Options -->
+  <bean id="deleteProductByName" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="dbyn" />
+    <property name="longOption" value="deleteProductByName" />
+    <property name="description" value="Triggers deleteProductByName Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>deleteProductByName</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="deleteProductByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- DumpMetadata Options -->
+  <bean id="dumpMetadata" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="dmet" />
+    <property name="longOption" value="dumpMetadata" />
+    <property name="description" value="Triggers dumpMetadata Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>dumpMetadata</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="dumpMetadata" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="outputDir" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="out" />
+    <property name="longOption" value="outputDir" />
+    <property name="description" value="Output directory" />
+    <property name="type" value="java.io.File" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-dir" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="dumpMetadata" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <!-- LuceneQuery Options -->
+  <bean id="luceneQuery" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="lucene" />
+    <property name="longOption" value="luceneQuery" />
+    <property name="description" value="Triggers luceneQuery Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>luceneQuery</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="reducedProductTypes" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="pts" />
+    <property name="longOption" value="reducedProductTypes" />
+    <property name="description" value="Limit query ProductTypes queried against" />
+    <property name="type" value="java.util.List" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="list-of-product-types" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="reducedMetadataKeys" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="metKeys" />
+    <property name="longOption" value="reducedMetadataKeys" />
+    <property name="description" value="Limit Elements returned by query" />
+    <property name="type" value="java.util.List" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="list-of-elements" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <!-- retrieveFiles Options -->
+  <bean id="retrieveFilesById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="rfbyid" />
+    <property name="longOption" value="retrieveFilesById" />
+    <property name="description" value="Triggers retrieveFilesById Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>retrieveFilesById</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesById" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="retrieveFilesByName" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="rfbyn" />
+    <property name="longOption" value="retrieveFilesByName" />
+    <property name="description" value="Triggers retrieveFilesByName Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>retrieveFilesByName</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="transferer" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="trans" />
+    <property name="longOption" value="transferer" />
+    <property name="description" value="Factory for creating DataTransfer which will perform the file transfer(s)" />
+    <property name="type" value="org.apache.oodt.cas.filemgr.datatransfer.DataTransferFactory" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="transfer factory class" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesById" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="retrieveFilesById" p:methodName="setDataTransferFactory" />
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="retrieveFilesByName" p:methodName="setDataTransferFactory" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="destination" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="dest" />
+    <property name="longOption" value="destination" />
+    <property name="description" value="Directory to transfer Product file to" />
+    <property name="type" value="java.io.File" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="directory" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesById" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+	<!-- Options used for multiple Actions -->
+  <bean id="productId" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="pid" />
+    <property name="longOption" value="productId" />
+    <property name="description" value="Product ID" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="product-id" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductPercentTransferred" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductById" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="deleteProductById" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="dumpMetadata" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesById" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+	
+  <bean id="productName" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="pn" />
+    <property name="longOption" value="productName" />
+    <property name="description" value="Product name" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="product-name" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="hasProduct" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductByName" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="deleteProductByName" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="productTypeName" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="ptn" />
+    <property name="longOption" value="productTypeName" />
+    <property name="description" value="ProductType name" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="product-type-name" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductTypeByName" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNumProducts" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getFirstPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNextPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getPrevPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getLastPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductPercentTransferred" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+  
+  <bean id="currentPageNum" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="curPage" />
+    <property name="longOption" value="currentPageNum" />
+    <property name="description" value="Current Page Number" />
+    <property name="type" value="int" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="page-number" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNextPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getPrevPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="query" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="q" />
+    <property name="longOption" value="query" />
+    <property name="description" value="File Manager query" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="query" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="sortBy" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="sb" />
+    <property name="longOption" value="sortBy" />
+    <property name="description" value="Metadata field to sort query results by" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="metadata field" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="outputFormat" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="of" />
+    <property name="longOption" value="outputFormat" />
+    <property name="description" value="Output format string (i.e. Filename = $Filename)" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="output-format-string" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="delimiter" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="dlmtr" />
+    <property name="longOption" value="delimiter" />
+    <property name="description" value="String to use the separate query results" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="delimiter-string" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="filter" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="f" />
+    <property name="longOption" value="filter" />
+    <property name="description" value="Query filter" />
+    <property name="hasArgs" value="false" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="algor" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="converter" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="startDateTimeMetKey" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="endDateTimeMetKey" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="priorityMetKey" p:required="true" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="algor" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="algor" />
+    <property name="longOption" value="algor" />
+    <property name="description" value="FilterAlgor class" />
+    <property name="type" value="org.apache.oodt.cas.filemgr.structs.query.filter.FilterAlgor" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+  
+  <bean id="converter" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="conv" />
+    <property name="longOption" value="converter" />
+    <property name="description" value="VersionConverter class" />
+    <property name="type" value="org.apache.oodt.cas.filemgr.structs.query.conv.VersionConverter" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="startDateTimeMetKey" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="sdtMetKey" />
+    <property name="longOption" value="startDateTimeMetKey" />
+    <property name="description" value="Start date time metadata key" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="metadata-key" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+  
+  <bean id="endDateTimeMetKey" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="edtMetKey" />
+    <property name="longOption" value="endDateTimeMetKey" />
+    <property name="description" value="End date time metadata key" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="metadata-key" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+  
+  <bean id="priorityMetKey" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="prMetKey" />
+    <property name="longOption" value="priorityMetKey" />
+    <property name="description" value="Priority metadata key" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="metadata-key" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+</beans>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/examples/core/elements.xml b/0.8.1-rc1/filemgr/src/main/resources/examples/core/elements.xml
new file mode 100644
index 0000000..830ccdc
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/examples/core/elements.xml
@@ -0,0 +1,77 @@
+<?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.
+-->
+<cas:elements xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<element id="urn:oodt:ProductId" name="CAS.ProductId">
+		<dcElement>Identifier</dcElement>
+        <!--  
+         You can optionally specify a 'trim' tag to identify whether
+         or not you want newlines trimmed from the element description. To
+         turn off trimming (now done by default), include the following with your
+         description definition: trim="false"       
+         -->
+		<description>
+			A Product's unique identifier within the CAS namespace.
+		</description>
+	</element>
+	<element id="urn:oodt:ProductName" name="CAS.ProductName">
+		<dcElement>Title</dcElement>
+		<description>
+			A Product's name within the CAS namespace.
+		</description>
+	</element>
+	<element id="urn:oodt:ProductReceivedTime"
+		name="CAS.ProductReceivedTime">
+		<dcElement />
+		<description>
+			The ISO 8601 formatted time that the Product was received.
+		</description>
+	</element>
+	<element id="urn:oodt:Filename" name="Filename">
+		<description>
+			The names of the files that represent this product.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:FileLocation" name="FileLocation">
+		<description>
+			The locations of the files that represent this product.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:ProductType" name="ProductType">
+		<description>
+			Type of product, as specified by, e.g., a data bible.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:ProductStructure" name="ProductStructure">
+		<description>
+			Whether or not a product is Flat (e.g., a set of independent
+			files), or hierarchical, e.g., a dir structure.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:MimeType" name="MimeType">
+		<description>The IETF mime type of this product.</description>
+		<dcElement />
+	</element>
+	<element id="urn:test:DataVersion" name="DataVersion">
+		<description>The version of the data product</description>
+		<dcElement />
+	</element>
+</cas:elements>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/examples/core/product-type-element-map.xml b/0.8.1-rc1/filemgr/src/main/resources/examples/core/product-type-element-map.xml
new file mode 100644
index 0000000..8df0b62
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/examples/core/product-type-element-map.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<cas:producttypemap xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+ <!--  can set the "parent" attribute on types below to allow inheritance
+       of elements between the types 
+  -->
+   <type id="urn:oodt:GenericFile">
+       <element id="urn:oodt:ProductReceivedTime"/>
+       <element id="urn:oodt:ProductName"/>
+       <element id="urn:oodt:ProductId"/>
+       <element id="urn:oodt:ProductType"/>
+       <element id="urn:oodt:ProductStructure"/>
+       <element id="urn:oodt:Filename"/>
+       <element id="urn:oodt:FileLocation"/>
+       <element id="urn:oodt:MimeType"/>
+       <element id="urn:test:DataVersion"/>
+  </type>
+</cas:producttypemap>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/examples/core/product-types.xml b/0.8.1-rc1/filemgr/src/main/resources/examples/core/product-types.xml
new file mode 100644
index 0000000..757fd51
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/examples/core/product-types.xml
@@ -0,0 +1,94 @@
+<?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.
+-->
+<cas:producttypes xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+  <type id="urn:oodt:GenericFile" name="GenericFile">
+    <repository path="file://[HOME]/files"/>
+    <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+    <!--  
+     You can optionally specify a 'trim' tag to identify whether
+     or not you want newlines trimmed from the product type description. To
+     turn off trimming (now done by default), include the following attribute with your
+     description definition: trim="false"       
+     -->
+    <description>The default product type for any kind of file.</description>
+    <!-- Global aggregate product type metadata: you can declare this in the 
+         same way you'd wire together a CAS met file, even using multiple values
+         per key.
+         
+         This metadata can be looked up via the Product Type API, and also used 
+         in browsers and so forth to display global metadata about the collection 
+         of Products part of this product type.
+    -->
+    <metadata>
+      <keyval>
+        <key>ProductType</key>
+        <val>GenericFile</val>
+      </keyval>
+      <!-- if you are using the org.apache.oodt.cas.filemgr.versioning.ProductTypeMetVersioner 
+           you can set a met key like below to define your filePathSpec
+      <keyval>
+        <key>filePathSpec</key>
+        <val>/[Filename]</val>
+      </keyval>
+      -->
+    </metadata>
+    <metExtractors>
+      <extractor
+        class="org.apache.oodt.cas.filemgr.metadata.extractors.CoreMetExtractor">
+        <configuration>
+          <!--  you can optionally include the envReplace tag to turn on/off environment var replacement -->
+          <property name="nsAware" value="true" />
+          <property name="elementNs" value="CAS" />
+          <property name="elements"
+            value="ProductReceivedTime,ProductName,ProductId" />
+        </configuration>
+      </extractor>
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.MimeTypeExtractor" />
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.FinalFileLocationExtractor">
+        <configuration>
+          <!-- this property specifies whether you want the FILE_LOCATION field
+               computed by this extractor to replace any other FILE_LOCATION met 
+               attribute.
+           -->
+           <property name="replace" value="true"/>
+        </configuration>
+      </extractor>
+      
+      <!-- 
+        The below enables the FilenameRegexMetExtractor.
+        It allows a user to specify a filename pattern with Java Regex that identifies groups 
+        within a particular file name. Those groups are then mapped to Metadata key names, and 
+        extracted as metadta from a file's name.
+        
+        In the example below, there are two groups, Filename, and ProductId, for files
+        of the form:
+        
+        Filename_ProductId.txt
+        
+        <extractor class="org.apache.oodt.cas.filemgr.metadata.extrctors.examples.FilenameRegexMetExtractor">
+          <configuration>
+            <property name="filenamePattern" value="(\\w*)_(\\d*)\\.txt"/>
+            <property name="metadataKeys" value="Filename,ProductId"/>
+          </configuration>
+        
+        </extractor>
+      
+       -->
+    </metExtractors>
+  </type>
+</cas:producttypes>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/examples/geo/elements.xml b/0.8.1-rc1/filemgr/src/main/resources/examples/geo/elements.xml
new file mode 100644
index 0000000..affc010
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/examples/geo/elements.xml
@@ -0,0 +1,37 @@
+<?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.
+-->
+<cas:elements xmlns:cas="http://oodt.apache.org/components/cas">
+  <element id="urn:oodt:Latitude" name="Latitude">
+    <!--
+      You can optionally specify a 'trim' tag to identify whether or not you
+      want newlines trimmed from the element description. To turn off trimming
+      (now done by default), include the following with your description
+      definition: trim="false"
+    -->
+    <description>
+      Geographical latitude data for a product.
+    </description>
+    <dcElement />
+  </element>
+  <element id="urn:oodt:Longitude" name="Longitude">
+    <description>
+      Geographical longitude data for a product.
+    </description>
+    <dcElement />
+  </element>
+</cas:elements>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/examples/geo/product-type-element-map.xml b/0.8.1-rc1/filemgr/src/main/resources/examples/geo/product-type-element-map.xml
new file mode 100644
index 0000000..2b6a6eb
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/examples/geo/product-type-element-map.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<cas:producttypemap xmlns:cas="http://oodt.apache.org/components/cas">
+  <!--
+    You can set the "parent" attribute on types below to allow inheritance of
+    elements between the types.
+  -->
+  <type id="urn:oodt:LocationAwareProduct" parent="urn:oodt:GenericFile">
+    <element id="urn:oodt:Latitude"/>
+    <element id="urn:oodt:Longitude"/>
+  </type>
+</cas:producttypemap>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/examples/geo/product-types.xml b/0.8.1-rc1/filemgr/src/main/resources/examples/geo/product-types.xml
new file mode 100644
index 0000000..427d4f0
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/examples/geo/product-types.xml
@@ -0,0 +1,79 @@
+<?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.
+-->
+<cas:producttypes xmlns:cas="http://oodt.apache.org/components/cas">
+  <type id="urn:oodt:LocationAwareProduct" name="LocationAwareProduct">
+    <repository path="file://[HOME]/files"/>
+    <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+    <!--
+      You can optionally specify a 'trim' tag to identify whether or not you
+      want newlines trimmed from the product type description.  To turn off
+      trimming (now done by default), include the following attribute with
+      your description definition: trim="false"
+    -->
+    <description>A product type with location metadata.</description>
+    <!--
+      Global aggregate product type metadata: you can declare this in the
+      same way you'd wire together a CAS met file, even using multiple values
+      per key.
+      
+      This metadata can be looked up via the Product Type API, and also used
+      in browsers and so forth to display global metadata about the collection
+      of Products part of this product type.
+    -->
+    <metadata>
+      <keyval>
+        <key>ProductType</key>
+        <val>LocationAwareProduct</val>
+      </keyval>
+      <!-- if you are using the org.apache.oodt.cas.filemgr.versioning.ProductTypeMetVersioner 
+           you can set a met key like below to define your filePathSpec
+      <keyval>
+        <key>filePathSpec</key>
+        <val>/[Filename]</val>
+      </keyval>
+      -->      
+    </metadata>
+    <metExtractors>
+      <extractor
+        class="org.apache.oodt.cas.filemgr.metadata.extractors.CoreMetExtractor">
+        <configuration>
+          <!--
+            You can optionally include the envReplace tag to turn on/off
+            environment var replacement.
+          -->
+          <property name="nsAware" value="true" />
+          <property name="elementNs" value="CAS" />
+          <property name="elements"
+            value="ProductReceivedTime,ProductName,ProductId" />
+        </configuration>
+      </extractor>
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.MimeTypeExtractor" />
+      <extractor
+        class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.FinalFileLocationExtractor">
+        <configuration>
+          <!--
+            This property specifies whether you want the FILE_LOCATION field
+            computed by this extractor to replace any other FILE_LOCATION met
+            attribute.
+          -->
+          <property name="replace" value="true"/>
+        </configuration>
+      </extractor>
+    </metExtractors>
+  </type>
+</cas:producttypes>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/examples/trace/elements.xml b/0.8.1-rc1/filemgr/src/main/resources/examples/trace/elements.xml
new file mode 100644
index 0000000..2fefacf
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/examples/trace/elements.xml
@@ -0,0 +1,95 @@
+<?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.
+-->
+<cas:elements xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+   <element id="urn:oodt:InputFiles" name="InputFiles">
+        <!--  
+         You can optionally specify a 'trim' tag to identify whether
+         or not you want newlines trimmed from the element description. To
+         turn off trimming (now done by default), include the following with your
+         description definition: trim="false"       
+         -->   
+       <description>The set of input files that went into producing this file.</description>
+       <dcElement/>
+   </element>
+   <element id="urn:oodt:OutputFiles" name="OutputFiles">
+        <description>The set of output files that included this file in its input.</description>
+        <dcElement/>
+   </element>
+   
+   <element id="urn:oodt:JobId" name="JobId">
+       <description>The unique identifier generated by the workflow manager for the job
+       that produced this file.</description>
+       <dcElement/>   
+   </element>
+   
+   <element id="urn:oodt:ProductionDateTime" name="ProductionDateTime">
+       <description>The date/time stamp that this file was produced either by ingestion 
+       or processing.</description>
+       <dcElement/>
+   </element>
+   
+   <element id="urn:oodt:ExecutablePathnames" name="ExecutablePathnames">
+    <description>The pathnames to the exectuables used to generate this product.</description>
+    <dcElement/>
+  </element>
+
+  <element id="urn:oodt:ExecutableVersions" name="ExecutableVersions">
+    <description>The versions of the exectuables used to generate this product.</description>
+    <dcElement/>
+  </element>
+
+  <element id="urn:oodt:ApplicationSuccessFlag" name="ApplicationSuccessFlag">
+    <description>An indication of whether the generating application completed
+      successfully.</description>
+    <dcElement/>
+  </element>
+  
+  <element id="urn:oodt:TaskSuccessFlag" name="TaskSuccessFlag">
+    <description>An indication of whether the PCS Workflow Task that ran the PGE completed
+      successfully.</description>
+    <dcElement/>
+  </element>
+
+  <element id="urn:oodt:JobSuccessFlag" name="JobSuccessFlag">
+    <description>An indication of whether the PCS job ran by the PCS to create the product completed
+      successfully.</description>
+    <dcElement/>
+  </element>
+  
+  <element id="urn:oodt:PGEVersion" name="PGEVersion">
+    <description>Captures the version of the algorithm that has been run on the data.</description>
+    <dcElement/>
+  </element>
+
+  <element id="urn:oodt:ProcessingNode" name="ProcessingNode">
+    <description>The node that the job that produced this product was run on.</description>
+    <dcElement/>
+  </element>
+     
+ <element id="urn:oodt:ExecutionTime" name="ExecutionTime">
+    <description>The amount of time that the job that produced this product took to run.</description>
+    <dcElement/>
+ </element>
+
+  <element id="urn:oodt:CmdLineParameters" name="CmdLineParameters">
+    <description>The command line parameters that were used to invoke this job.</description>
+    <dcElement/>
+  </element>  
+    
+   
+</cas:elements>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/examples/trace/product-type-element-map.xml b/0.8.1-rc1/filemgr/src/main/resources/examples/trace/product-type-element-map.xml
new file mode 100644
index 0000000..038a58c
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/examples/trace/product-type-element-map.xml
@@ -0,0 +1,37 @@
+<?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.
+-->
+<cas:producttypemap xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+ <!--  can set the "parent" attribute on types below to allow inheritance
+       of elements between the types 
+  -->
+  <type id="urn:oodt:TraceableFile" parent="urn:oodt:GenericFile">
+       <element id="urn:oodt:InputFiles"/>
+       <element id="urn:oodt:OutputFiles"/>
+       <element id="urn:oodt:JobId"/>
+       <element id="urn:oodt:ProductionDateTime"/>
+       <element id="urn:oodt:ExecutablePathnames"/> 
+       <element id="urn:oodt:ExecutableVersions"/>
+       <element id="urn:oodt:ApplicationSuccessFlag"/>
+       <element id="urn:oodt:TaskSuccessFlag" />
+       <element id="urn:oodt:JobSuccessFlag"/>
+       <element id="urn:oodt:PGEVersion"/>
+       <element id="urn:oodt:ProcessingNode"/>
+       <element id="urn:oodt:ExecutionTime" />
+       <element id="urn:oodt:CmdLineParameters"/>       
+  </type>
+</cas:producttypemap>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/examples/trace/product-types.xml b/0.8.1-rc1/filemgr/src/main/resources/examples/trace/product-types.xml
new file mode 100644
index 0000000..1ec9c99
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/examples/trace/product-types.xml
@@ -0,0 +1,74 @@
+<?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.
+-->
+<cas:producttypes xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+  <type id="urn:oodt:TraceableFile" name="TraceableFile">
+    <repository path="file://[HOME]/files"/>
+    <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+    <!--                                                                                                                                                            
+     You can optionally specify a 'trim' tag to identify whether                                                                                                    
+     or not you want newlines trimmed from the product type description. To                                                                                         
+     turn off trimming (now done by default), include the following attribute with your                                                                             
+     description definition: trim="false"                                                                                                                           
+     -->
+    <description>A traceable product for use in provenance and algorithm execution.</description>
+    <!--
+      Global aggregate product type metadata: you can declare this in the
+      same way you'd wire together a CAS met file, even using multiple values
+      per key.
+      
+      This metadata can be looked up via the Product Type API, and also used
+      in browsers and so forth to display global metadata about the collection
+      of Products part of this product type.
+    -->
+    <metadata>
+      <keyval>
+        <key>ProductType</key>
+        <val>LocationAwareProduct</val>
+      </keyval>
+      <!-- if you are using the org.apache.oodt.cas.filemgr.versioning.ProductTypeMetVersioner 
+           you can set a met key like below to define your filePathSpec
+      <keyval>
+        <key>filePathSpec</key>
+        <val>/[Filename]</val>
+      </keyval>
+      -->      
+    </metadata>
+    <metExtractors>
+      <extractor
+        class="org.apache.oodt.cas.filemgr.metadata.extractors.CoreMetExtractor">
+        <configuration>
+          <!--  you can optionally include the envReplace tag to turn on/off environment var replacement -->
+          <property name="nsAware" value="true" />
+          <property name="elementNs" value="CAS" />
+          <property name="elements"
+            value="ProductReceivedTime,ProductName,ProductId" />
+        </configuration>
+      </extractor>
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.MimeTypeExtractor" />
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.FinalFileLocationExtractor">
+        <configuration>
+          <!-- this property specifies whether you want the FILE_LOCATION field                                                                                     
+               computed by this extractor to replace any other FILE_LOCATION met                                                                                    
+               attribute.                                                                                                                                           
+           -->
+           <property name="replace" value="true"/>
+        </configuration>
+      </extractor>
+    </metExtractors>
+  </type>
+</cas:producttypes>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/filemgr.properties b/0.8.1-rc1/filemgr/src/main/resources/filemgr.properties
new file mode 100644
index 0000000..e7169d9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/filemgr.properties
@@ -0,0 +1,156 @@
+#  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.
+
+# Configuration properties for the File Manager
+
+# repository factory
+filemgr.repository.factory=org.apache.oodt.cas.filemgr.repository.XMLRepositoryManagerFactory
+
+# catalog factory
+filemgr.catalog.factory=org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory
+
+# data transfer factory
+filemgr.datatransfer.factory=org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory
+
+# validation layer factory
+filemgr.validationLayer.factory=org.apache.oodt.cas.filemgr.validation.XMLValidationLayerFactory
+
+# xml rpc client configuration
+org.apache.oodt.cas.filemgr.system.xmlrpc.connectionTimeout.minutes=20
+org.apache.oodt.cas.filemgr.system.xmlrpc.requestTimeout.minutes=60
+#org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retries=0
+#org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retry.interval.seconds=3
+
+# data source catalog configuration
+org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.url=some_jdbc_url
+org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.user=user
+org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.pass=pass
+org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.driver=driver.class.name
+org.apache.oodt.cas.filemgr.catalog.datasource.quoteFields=false
+org.apache.oodt.cas.filemgr.catalog.datasource.pageSize=20
+org.apache.oodt.cas.filemgr.catalog.datasource.cacheUpdateMinutes=5
+org.apache.oodt.cas.filemgr.catalog.datasource.orderedValues=false
+# set the following property to 'true' to allow dynamic metadata fields,
+# effectively bypassing the validation layer.
+# by default the property is false
+#org.apache.oodt.cas.filemgr.catalog.datasource.lenientFields=true
+# set the following property to true to enable the column "product_id"
+# in table "products" to be of type string
+#org.apache.oodt.cas.filemgr.catalog.datasource.productId.string=false
+
+
+# mapped data source catalog configuration
+org.apache.oodt.cas.filemgr.catalog.mappeddatasource.mapFile=/path/to/ops.catalog.typemap.properties
+
+# science data catalog configuration
+org.apache.oodt.cas.filemgr.catalog.science.jdbc.url=some_jdbc_url
+org.apache.oodt.cas.filemgr.catalog.science.jdbc.user=user
+org.apache.oodt.cas.filemgr.catalog.science.jdbc.pass=pass
+org.apache.oodt.cas.filemgr.catalog.science.jdbc.driver=driver.class.name
+
+# lucene catalog configuration
+org.apache.oodt.cas.filemgr.catalog.lucene.idxPath=/tmp/test
+org.apache.oodt.cas.filemgr.catalog.lucene.pageSize=20
+org.apache.oodt.cas.filemgr.catalog.lucene.commitLockTimeout.seconds=60
+org.apache.oodt.cas.filemgr.catalog.lucene.writeLockTimeout.seconds=60
+org.apache.oodt.cas.filemgr.catalog.lucene.mergeFactor=20
+
+# solr catalog configuration
+org.apache.oodt.cas.filemgr.catalog.solr.url=http://localhost:8983/solr
+#org.apache.oodt.cas.filemgr.catalog.solr.url=http://localhost:8080/solr
+org.apache.oodt.cas.filemgr.catalog.solr.productSerializer=org.apache.oodt.cas.filemgr.catalog.solr.DefaultProductSerializer
+org.apache.oodt.cas.filemgr.catalog.solr.productIdGenerator=org.apache.oodt.cas.filemgr.catalog.solr.UUIDProductIdGenerator
+#org.apache.oodt.cas.filemgr.catalog.solr.productIdGenerator=org.apache.oodt.cas.filemgr.catalog.solr.NameProductIdGenerator
+
+
+# data source repository manager configuration
+org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.url=some_jdbc_url
+org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.user=user
+org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.pass=pass
+org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.driver=driver.class.name
+
+# science data repository manager configuration
+org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.url=some_jdbc_url
+org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.user=user
+org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.pass=pass
+org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.driver=driver.class.name
+
+# XML repository manager configuration
+org.apache.oodt.cas.filemgr.repositorymgr.dirs=file:///dir1,file:///dir2
+
+# XML validation layer configuration
+org.apache.oodt.cas.filemgr.validation.dirs=file:///dir1,file:///dir2
+
+# set the following property to 'true' to allow dynamic metadata fields,
+# effectively bypassing the validation layer.
+# by default the property is false
+#org.apache.oodt.cas.filemgr.catalog.lucene.lenientFields=true
+
+# data source validation layer configuration
+org.apache.oodt.cas.filemgr.validation.datasource.jdbc.url=some_jdbc_url
+org.apache.oodt.cas.filemgr.validation.datasource.jdbc.user=user
+org.apache.oodt.cas.filemgr.validation.datasource.jdbc.pass=pass
+org.apache.oodt.cas.filemgr.validation.datasource.jdbc.driver=driver.class.name
+org.apache.oodt.cas.filemgr.validation.datasource.quoteFields=false
+
+# science data validation layer configuration
+org.apache.oodt.cas.filemgr.validation.science.jdbc.url=some_jdbc_url
+org.apache.oodt.cas.filemgr.validation.science.jdbc.user=user
+org.apache.oodt.cas.filemgr.validation.science.jdbc.pass=pass
+org.apache.oodt.cas.filemgr.validation.science.jdbc.driver=driver.class.name
+
+# remote data transfer configuration
+org.apache.oodt.cas.filemgr.datatransfer.remote.chunkSize=1024
+
+# Amazon S3 data transfer configuration.
+# Region can be any of the values found here:
+#   http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/regions/Regions.html
+org.apache.oodt.cas.filemgr.datatransfer.s3.bucket.name=some_bucket_name
+org.apache.oodt.cas.filemgr.datatransfer.s3.region=EU_WEST_1
+org.apache.oodt.cas.filemgr.datatransfer.s3.access.key=s3_access_key
+org.apache.oodt.cas.filemgr.datatransfer.s3.secret.key=s3_secret_key
+org.apache.oodt.cas.filemgr.datatransfer.s3.encrypt=false
+
+# location of Mime-Type repository
+org.apache.oodt.cas.filemgr.mime.type.repository=/path/to/mime-types.xml
+
+# tells the file manager system layer to include product instance metadata
+# NOTE: here are the expected field mappings
+#
+#      product.getProductId() -> ProductId
+#      product.getProductName() -> ProductName
+#      product.getProductStructure() -> ProductStructure
+#      product.getTransferStatus() -> ProductTransferStatus
+#      product.getRootRef() -> ProductRootReference
+
+# for the references returned by product.getProductReferences() the following 
+# metadata fields will be added (order will be maintained, such that data store 
+# ref at index 0 will map to orig ref at index 0, etc.)
+#
+#      ProductDataStoreReferences (list of all data store references: 
+#       note already translated into path, not URI)
+#      ProductOrigReferences (list of all orig references: 
+#       note already translated into path, not URI)
+#      ProductMimeType (list of all references' mime-types)
+#      ProductFileSize (list of all references' file sizes)
+
+org.apache.oodt.cas.filemgr.metadata.expandProduct=false
+
+# ConfigurableMetadataBasedVersioning configuration
+#org.apache.oodt.cas.filemgr.versioning.configuration.all_product_types=[Year]/[Month]/[Filename]
+#org.apache.oodt.cas.filemgr.versioning.configuration.<product_type>=[Year]/[Month]/[Filename]
+
+# Enable to use only server-side versioning.
+#org.apache.oodt.cas.filemgr.serverside.versioning=true
diff --git a/0.8.1-rc1/filemgr/src/main/resources/indexer.properties b/0.8.1-rc1/filemgr/src/main/resources/indexer.properties
new file mode 100755
index 0000000..b3157e2
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/indexer.properties
@@ -0,0 +1,62 @@
+#  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.
+
+# Configures the Solr Indexer tool
+
+# basic config properties
+
+# a set of product types to ignore dumping
+config.ignore.types=SomeProductType
+
+# any met values to ignore indexing
+config.ignore.values=TBD
+
+# the URL path to Solr
+config.solr.url=http://localhost:8983/solr
+
+# the URL path to the File Manager
+config.filemgr.url=http://localhost:9001
+
+# Data access for the products
+config.access.key=ProductURL
+config.access.url=http://localhost:8080/cas-product/data?productID=[ProductId]
+
+# Add a comma seperated list of values for keys 
+# that will go through metadata replacement. 
+# For example the ProductURL above will fill in
+# the actual value for the [ProductId]
+config.replacement.keys=ProductURL
+
+# Must have map for unique id in Solr
+map.CAS.ProductId=id
+
+# Must map this field to enable deletion of Solr records by name
+map.CAS.ProductName=ProductName
+
+# Map from File Manager terminology into Solr 
+# index doc field terminology. Only mapped fields 
+# will be added to the Solr index.
+map.MimeType=mimetype
+map.CAS.ProductReceivedTime=receivedtime
+map.FileSize=filesize
+map.FileName=filename
+# map.ProductURL=producturl
+
+# Formatting of date fields can be specified for a
+# field coming from Solr. Solr requires a specific 
+# format when you want to map to a date so one must
+# specify the source format in the filemanager.  
+format.CAS.ProductReceivedTime=yyyy-MM-dd'T'HH:mm:ss.SSS
+
diff --git a/0.8.1-rc1/filemgr/src/main/resources/ingestcache.properties b/0.8.1-rc1/filemgr/src/main/resources/ingestcache.properties
new file mode 100644
index 0000000..81ddffc
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/ingestcache.properties
@@ -0,0 +1,43 @@
+#  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.
+
+# A file to describe properties for the gov.nasa.jpl.oodt.filemgr.ingest.Cache
+
+
+org.apache.oodt.cas.filemgr.ingest.cache.rangeQueryElementName=CAS.ProductReceivedTime
+
+# these properties can be replaced using env var replacement (as is shown by default)
+# even before env var replacement, you can also use date var 
+# replacement, e.g.,
+# 
+# org.apache.oodt.cas.filemgr.ingest.cache.range.start=[DATE-3200.YEAR][DATE-3200.MONTH][DATE-3200.DAY]000000
+# org.apache.oodt.cas.filemgr.ingest.cache.range.end=[DATE.YEAR][DATE.MONTH][DATE.DAY]000000
+#
+# Which would say: the range start is the current date - 3200 roll days, or 10 year prior
+#                  the range end is the current date
+
+org.apache.oodt.cas.filemgr.ingest.cache.range.start=[CACHE_RANGE_START]
+org.apache.oodt.cas.filemgr.ingest.cache.range.end=[CACHE_RANGE_END]
+
+org.apache.oodt.cas.filemgr.ingest.cache.uniqueElementName=CAS.ProductName
+
+# this property can be replaced using env var replacement
+# this property can also be a multi-valued list, by comma separating
+# the list of product types
+org.apache.oodt.cas.filemgr.ingest.cache.productType=GenericFile
+
+# rmi cache server URN (used by the rmi cache client)
+# note: this property can be replaced using en var replacement
+org.apache.oodt.cas.filemgr.ingest.cache.rmi.serverUrn=//localhost:9050/RmiDatabaseServer
diff --git a/0.8.1-rc1/filemgr/src/main/resources/logging.properties b/0.8.1-rc1/filemgr/src/main/resources/logging.properties
new file mode 100644
index 0000000..2e53039
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/logging.properties
@@ -0,0 +1,75 @@
+#  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.
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.FileHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = ../logs/cas_filemgr%g.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 5
+java.util.logging.FileHandler.append = true
+java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging level for the subsystems
+
+# catalog subsystem
+org.apache.oodt.cas.filemgr.catalog.level = INFO
+
+# repository subsystem
+org.apache.oodt.cas.filemgr.repository.level = FINE
+
+# system subsystem
+org.apache.oodt.cas.filemgr.system.level = INFO
+
+# versioning subsystem
+org.apache.oodt.cas.filemgr.versioning.level = INFO
+
+# data transfer subsystem
+org.apache.oodt.cas.filemgr.datatransfer.level = FINE
+
+# util
+org.apache.oodt.cas.filemgr.util.level = INFO
+
+# validation
+org.apache.oodt.cas.filemgr.validation.level = INFO
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = INFO
+httpclient.wire.header.level = INFO
+httpclient.wire.level = INFO
+
+# spring framework logging
+org.springframework.beans.level = SEVERE
+org.springframework.core.level = SEVERE
+org.springframework.level = SEVERE
+org.springframework.beans.factory.level = SEVERE
+org.springframework.beans.factory.config.level = SEVERE
+org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.level = SEVERE
+org.apache.oodt.cas.crawl.util.CasPropertyPlaceholderConfigurer.level = SEVERE
+sun.net.level = SEVERE
+
diff --git a/0.8.1-rc1/filemgr/src/main/resources/mime-types.xml b/0.8.1-rc1/filemgr/src/main/resources/mime-types.xml
new file mode 100644
index 0000000..a007e81
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/mime-types.xml
@@ -0,0 +1,4119 @@
+<?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.
+-->
+<!--
+  Description: This xml file defines the valid mime types used by Tika.
+  The mime type data within this file is based on information from various
+  sources like Apache Nutch, Apache HTTP Server, the file(1) command, etc.
+-->
+<mime-info>
+
+  <mime-type type="application/activemessage"/>
+  <mime-type type="application/andrew-inset">
+    <glob pattern="*.ez"/>
+  </mime-type>
+  <mime-type type="application/applefile"/>
+  <mime-type type="application/applixware">
+    <glob pattern="*.aw"/>
+  </mime-type>
+
+  <mime-type type="application/atom+xml">
+    <root-XML localName="feed" namespaceURI="http://purl.org/atom/ns#"/>
+    <glob pattern="*.atom"/>
+  </mime-type>
+
+  <mime-type type="application/atomcat+xml">
+    <glob pattern="*.atomcat"/>
+  </mime-type>
+  <mime-type type="application/atomicmail"/>
+  <mime-type type="application/atomsvc+xml">
+    <glob pattern="*.atomsvc"/>
+  </mime-type>
+  <mime-type type="application/auth-policy+xml"/>
+  <mime-type type="application/batch-smtp"/>
+  <mime-type type="application/beep+xml"/>
+  <mime-type type="application/cals-1840"/>
+  <mime-type type="application/ccxml+xml">
+    <glob pattern="*.ccxml"/>
+  </mime-type>
+  <mime-type type="application/cea-2018+xml"/>
+  <mime-type type="application/cellml+xml"/>
+  <mime-type type="application/cnrp+xml"/>
+  <mime-type type="application/commonground"/>
+  <mime-type type="application/conference-info+xml"/>
+  <mime-type type="application/cpl+xml"/>
+  <mime-type type="application/csta+xml"/>
+  <mime-type type="application/cstadata+xml"/>
+  <mime-type type="application/cu-seeme">
+    <glob pattern="*.cu"/>
+  </mime-type>
+  <mime-type type="application/cybercash"/>
+  <mime-type type="application/davmount+xml">
+    <glob pattern="*.davmount"/>
+  </mime-type>
+  <mime-type type="application/dca-rft"/>
+  <mime-type type="application/dec-dx"/>
+  <mime-type type="application/dialog-info+xml"/>
+  <mime-type type="application/dicom"/>
+  <mime-type type="application/dns"/>
+  <mime-type type="application/dvcs"/>
+  <mime-type type="application/ecmascript">
+    <glob pattern="*.ecma"/>
+  </mime-type>
+  <mime-type type="application/edi-consent"/>
+  <mime-type type="application/edi-x12"/>
+  <mime-type type="application/edifact"/>
+  <mime-type type="application/emma+xml">
+    <glob pattern="*.emma"/>
+  </mime-type>
+  <mime-type type="application/epp+xml"/>
+
+  <mime-type type="application/epub+zip">
+    <acronym>EPUB</acronym>
+    <_comment>Electronic Publication</_comment>
+    <magic priority="50">
+      <match value="PK\003\004" type="string" offset="0">
+        <match value="mimetypeapplication/epub+zip" type="string" offset="30"/>
+      </match>
+    </magic>
+    <glob pattern="*.epub"/>
+  </mime-type>
+
+  <mime-type type="application/eshop"/>
+  <mime-type type="application/example"/>
+  <mime-type type="application/fastinfoset"/>
+  <mime-type type="application/fastsoap"/>
+  <mime-type type="application/fits"/>
+  <mime-type type="application/font-tdpfr">
+    <glob pattern="*.pfr"/>
+  </mime-type>
+  <mime-type type="application/h224"/>
+  <mime-type type="application/http"/>
+  <mime-type type="application/hyperstudio">
+    <glob pattern="*.stk"/>
+  </mime-type>
+  <mime-type type="application/ibe-key-request+xml"/>
+  <mime-type type="application/ibe-pkg-reply+xml"/>
+  <mime-type type="application/ibe-pp-data"/>
+  <mime-type type="application/iges"/>
+  <mime-type type="application/im-iscomposing+xml"/>
+  <mime-type type="application/index"/>
+  <mime-type type="application/index.cmd"/>
+  <mime-type type="application/index.obj"/>
+  <mime-type type="application/index.response"/>
+  <mime-type type="application/index.vnd"/>
+  <mime-type type="application/iotp"/>
+  <mime-type type="application/ipp"/>
+  <mime-type type="application/isup"/>
+
+  <mime-type type="application/java-archive">
+    <sub-class-of type="application/zip"/>
+    <glob pattern="*.jar"/>
+  </mime-type>
+
+  <mime-type type="application/java-serialized-object">
+    <glob pattern="*.ser"/>
+  </mime-type>
+
+  <mime-type type="application/javascript">
+    <sub-class-of type="text/plain"/>
+    <glob pattern="*.js"/>
+  </mime-type>
+
+  <mime-type type="application/json">
+    <sub-class-of type="application/javascript"/>
+    <glob pattern="*.json"/>
+  </mime-type>
+
+  <mime-type type="application/java-vm">
+    <magic priority="40">
+      <match value="0xcafebabe" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.class"/>
+  </mime-type>
+
+  <mime-type type="application/kpml-request+xml"/>
+  <mime-type type="application/kpml-response+xml"/>
+  <mime-type type="application/lost+xml">
+    <glob pattern="*.lostxml"/>
+  </mime-type>
+
+  <mime-type type="application/mac-binhex40">
+    <alias type="application/mac-binhex"/>
+    <alias type="application/binhex"/>
+    <magic priority="50">
+      <match value="must\ be\ converted\ with\ BinHex" type="string" offset="11"/>
+    </magic>
+    <glob pattern="*.hqx"/>
+  </mime-type>
+
+  <mime-type type="application/mac-compactpro">
+    <glob pattern="*.cpt"/>
+  </mime-type>
+
+  <mime-type type="application/macwriteii"/>
+  <mime-type type="application/marc">
+    <glob pattern="*.mrc"/>
+  </mime-type>
+  <mime-type type="application/mathematica">
+    <glob pattern="*.ma"/>
+    <glob pattern="*.nb"/>
+    <glob pattern="*.mb"/>
+  </mime-type>
+  <mime-type type="application/mathml+xml">
+    <glob pattern="*.mathml"/>
+  </mime-type>
+  <mime-type type="application/mbms-associated-procedure-description+xml"/>
+  <mime-type type="application/mbms-deregister+xml"/>
+  <mime-type type="application/mbms-envelope+xml"/>
+  <mime-type type="application/mbms-msk+xml"/>
+  <mime-type type="application/mbms-msk-response+xml"/>
+  <mime-type type="application/mbms-protection-description+xml"/>
+  <mime-type type="application/mbms-reception-report+xml"/>
+  <mime-type type="application/mbms-register+xml"/>
+  <mime-type type="application/mbms-register-response+xml"/>
+  <mime-type type="application/mbms-user-service-description+xml"/>
+  <mime-type type="application/mbox">
+    <sub-class-of type="text/plain"/>
+    <glob pattern="*.mbox"/>
+  </mime-type>
+  <mime-type type="application/media_control+xml"/>
+  <mime-type type="application/mediaservercontrol+xml">
+    <glob pattern="*.mscml"/>
+  </mime-type>
+  <mime-type type="application/mikey"/>
+  <mime-type type="application/moss-keys"/>
+  <mime-type type="application/moss-signature"/>
+  <mime-type type="application/mosskey-data"/>
+  <mime-type type="application/mosskey-request"/>
+  <mime-type type="application/mp4">
+    <glob pattern="*.mp4s"/>
+  </mime-type>
+  <mime-type type="application/mpeg4-generic"/>
+  <mime-type type="application/mpeg4-iod"/>
+  <mime-type type="application/mpeg4-iod-xmt"/>
+
+  <!-- http://www.iana.org/assignments/media-types/application/msword -->
+  <mime-type type="application/msword">
+    <!-- Use org.apache.tika.detect.ContainerAwareDetector for more reliable detection of OLE2 documents -->
+    <alias type="application/vnd.ms-word"/>
+    <_comment>Microsoft Word Document</_comment>
+    <magic priority="50">
+      <match value="Microsoft\ Word\ 6.0\ Document" type="string" offset="2080"/>
+      <match value="Documento\ Microsoft\ Word\ 6" type="string" offset="2080"/>
+      <match value="MSWordDoc" type="string" offset="2112"/>
+      <match value="0x31be0000" type="big32" offset="0"/>
+      <match value="PO^Q`" type="string" offset="0"/>
+      <match value="\376\067\0\043" type="string" offset="0"/>
+      <match value="\333\245-\0\0\0" type="string" offset="0"/>
+      <match value="\354\245\301" type="string" offset="512"/>
+      <match value="\320\317\021\340\241\261\032\341" type="string" offset="0"/>
+      <match value="\224\246\056" type="string" offset="0"/>
+      <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+         <match value="W\x00o\x00r\x00d\x00D\x00o\x00c\x00u\x00m\x00e\x00n\x00t" type="string" offset="1152:4096" />
+      </match>
+    </magic>
+    <glob pattern="*.doc"/>
+    <glob pattern="*.dot"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/mxf">
+    <glob pattern="*.mxf"/>
+  </mime-type>
+  <mime-type type="application/nasdata"/>
+  <mime-type type="application/news-checkgroups"/>
+  <mime-type type="application/news-groupinfo"/>
+  <mime-type type="application/news-transmission"/>
+  <mime-type type="application/nss"/>
+  <mime-type type="application/ocsp-request"/>
+  <mime-type type="application/ocsp-response"/>
+
+  <mime-type type="application/octet-stream">
+    <magic priority="50">
+      <match value="#\ This\ is\ a\ shell\ archive" type="string" offset="10"/>
+      <match value="\037\036" type="string" offset="0"/>
+      <match value="017437" type="host16" offset="0"/>
+      <match value="0x1fff" type="host16" offset="0"/>
+      <match value="\377\037" type="string" offset="0"/>
+      <match value="0145405" type="host16" offset="0"/>
+    </magic>
+    <glob pattern="*.bin"/>
+    <glob pattern="*.dms"/>
+    <glob pattern="*.lha"/>
+    <glob pattern="*.lrf"/>
+    <glob pattern="*.lzh"/>
+    <glob pattern="*.so"/>
+    <glob pattern="*.iso"/>
+    <glob pattern="*.dmg"/>
+    <glob pattern="*.dist"/>
+    <glob pattern="*.distz"/>
+    <glob pattern="*.pkg"/>
+    <glob pattern="*.bpk"/>
+    <glob pattern="*.dump"/>
+    <glob pattern="*.elc"/>
+    <glob pattern="*.deploy"/>
+  </mime-type>
+
+  <mime-type type="application/oda">
+    <glob pattern="*.oda"/>
+  </mime-type>
+  <mime-type type="application/oebps-package+xml">
+    <glob pattern="*.opf"/>
+  </mime-type>
+
+  <mime-type type="application/ogg">
+    <alias type="application/x-ogg"/>
+    <magic priority="50">
+      <match value="OggS" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.ogx"/>
+  </mime-type>
+
+  <mime-type type="application/onenote">
+    <glob pattern="*.onetoc"/>
+    <glob pattern="*.onetoc2"/>
+    <glob pattern="*.onetmp"/>
+    <glob pattern="*.onepkg"/>
+  </mime-type>
+  <mime-type type="application/parityfec"/>
+  <mime-type type="application/patch-ops-error+xml">
+    <glob pattern="*.xer"/>
+  </mime-type>
+
+  <mime-type type="application/pdf">
+    <alias type="application/x-pdf"/>
+    <acronym>PDF</acronym>
+    <_comment>Portable Document Format</_comment>
+    <magic priority="50">
+      <match value="%PDF-" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.pdf"/>
+  </mime-type>
+
+  <mime-type type="application/pgp-encrypted">
+    <glob pattern="*.pgp"/>
+  </mime-type>
+  <mime-type type="application/pgp-keys"/>
+  <mime-type type="application/pgp-signature">
+    <glob pattern="*.asc"/>
+    <glob pattern="*.sig"/>
+  </mime-type>
+  <mime-type type="application/pics-rules">
+    <glob pattern="*.prf"/>
+  </mime-type>
+  <mime-type type="application/pidf+xml"/>
+  <mime-type type="application/pidf-diff+xml"/>
+  <mime-type type="application/pkcs10">
+    <glob pattern="*.p10"/>
+  </mime-type>
+  <mime-type type="application/pkcs7-mime">
+    <glob pattern="*.p7m"/>
+    <glob pattern="*.p7c"/>
+  </mime-type>
+  <mime-type type="application/pkcs7-signature">
+    <glob pattern="*.p7s"/>
+  </mime-type>
+  <mime-type type="application/pkix-cert">
+    <glob pattern="*.cer"/>
+  </mime-type>
+  <mime-type type="application/pkix-crl">
+    <glob pattern="*.crl"/>
+  </mime-type>
+  <mime-type type="application/pkix-pkipath">
+    <glob pattern="*.pkipath"/>
+  </mime-type>
+  <mime-type type="application/pkixcmp">
+    <glob pattern="*.pki"/>
+  </mime-type>
+  <mime-type type="application/pls+xml">
+    <glob pattern="*.pls"/>
+  </mime-type>
+  <mime-type type="application/poc-settings+xml"/>
+
+  <mime-type type="application/postscript">
+    <_comment>PostScript</_comment>
+    <magic priority="50">
+      <match value="%!" type="string" offset="0" />
+      <match value="\004%!" type="string" offset="0" />
+      <!-- Windows format EPS -->
+      <match value="0xc5d0d3c6" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.ai"/>
+    <glob pattern="*.ps"/>
+    <glob pattern="*.eps"/>
+    <glob pattern="*.epsf"/>
+    <glob pattern="*.epsi"/>
+  </mime-type>
+
+  <mime-type type="application/prs.alvestrand.titrax-sheet"/>
+  <mime-type type="application/prs.cww">
+    <glob pattern="*.cww"/>
+  </mime-type>
+  <mime-type type="application/prs.nprend"/>
+  <mime-type type="application/prs.plucker"/>
+  <mime-type type="application/qsig"/>
+
+  <mime-type type="application/rdf+xml">
+    <root-XML localName="RDF"/>
+    <root-XML localName="RDF" namespaceURI="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
+    <sub-class-of type="application/xml"/>
+    <acronym>RDF/XML</acronym>
+    <_comment>XML syntax for RDF graphs</_comment>
+    <glob pattern="*.rdf"/>
+    <glob pattern="*.owl"/>
+    <glob pattern="^rdf$" isregex="true"/>
+    <glob pattern="^owl$" isregex="true"/>
+  </mime-type>
+
+  <mime-type type="application/reginfo+xml">
+    <glob pattern="*.rif"/>
+  </mime-type>
+  <mime-type type="application/relax-ng-compact-syntax">
+    <sub-class-of type="text/plain"/>
+    <glob pattern="*.rnc"/>
+  </mime-type>
+  <mime-type type="application/remote-printing"/>
+  <mime-type type="application/resource-lists+xml">
+    <glob pattern="*.rl"/>
+  </mime-type>
+  <mime-type type="application/resource-lists-diff+xml">
+    <glob pattern="*.rld"/>
+  </mime-type>
+  <mime-type type="application/riscos"/>
+  <mime-type type="application/rlmi+xml"/>
+  <mime-type type="application/rls-services+xml">
+    <glob pattern="*.rs"/>
+  </mime-type>
+  <mime-type type="application/rsd+xml">
+    <glob pattern="*.rsd"/>
+  </mime-type>
+
+  <mime-type type="application/rss+xml">
+    <alias type="text/rss"/>
+    <root-XML localName="rss"/>
+    <root-XML namespaceURI="http://purl.org/rss/1.0/"/>
+    <glob pattern="*.rss"/>
+  </mime-type>
+
+  <mime-type type="application/rtf">
+    <alias type="text/rtf"/>
+    <magic priority="50">
+      <match value="{\\rtf" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.rtf"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="application/rtx"/>
+  <mime-type type="application/samlassertion+xml"/>
+  <mime-type type="application/samlmetadata+xml"/>
+  <mime-type type="application/sbml+xml">
+    <glob pattern="*.sbml"/>
+  </mime-type>
+  <mime-type type="application/scvp-cv-request">
+    <glob pattern="*.scq"/>
+  </mime-type>
+  <mime-type type="application/scvp-cv-response">
+    <glob pattern="*.scs"/>
+  </mime-type>
+  <mime-type type="application/scvp-vp-request">
+    <glob pattern="*.spq"/>
+  </mime-type>
+  <mime-type type="application/scvp-vp-response">
+    <glob pattern="*.spp"/>
+  </mime-type>
+  <mime-type type="application/sdp">
+    <glob pattern="*.sdp"/>
+  </mime-type>
+  <mime-type type="application/set-payment"/>
+  <mime-type type="application/set-payment-initiation">
+    <glob pattern="*.setpay"/>
+  </mime-type>
+  <mime-type type="application/set-registration"/>
+  <mime-type type="application/set-registration-initiation">
+    <glob pattern="*.setreg"/>
+  </mime-type>
+  <mime-type type="application/sgml"/>
+  <mime-type type="application/sgml-open-catalog"/>
+  <mime-type type="application/shf+xml">
+    <glob pattern="*.shf"/>
+  </mime-type>
+  <mime-type type="application/sieve"/>
+  <mime-type type="application/simple-filter+xml"/>
+  <mime-type type="application/simple-message-summary"/>
+  <mime-type type="application/simplesymbolcontainer"/>
+  <mime-type type="application/slate"/>
+  <mime-type type="application/smil"/>
+  <mime-type type="application/smil+xml">
+    <glob pattern="*.smi"/>
+    <glob pattern="*.smil"/>
+  </mime-type>
+  <mime-type type="application/soap+fastinfoset"/>
+  <mime-type type="application/soap+xml"/>
+  <mime-type type="application/sparql-query">
+    <glob pattern="*.rq"/>
+  </mime-type>
+  <mime-type type="application/sparql-results+xml">
+    <glob pattern="*.srx"/>
+  </mime-type>
+  <mime-type type="application/spirits-event+xml"/>
+  <mime-type type="application/srgs">
+    <glob pattern="*.gram"/>
+  </mime-type>
+  <mime-type type="application/srgs+xml">
+    <glob pattern="*.grxml"/>
+  </mime-type>
+  <mime-type type="application/ssml+xml">
+    <glob pattern="*.ssml"/>
+  </mime-type>
+  <mime-type type="application/timestamp-query"/>
+  <mime-type type="application/timestamp-reply"/>
+  <mime-type type="application/tve-trigger"/>
+  <mime-type type="application/ulpfec"/>
+  <mime-type type="application/vemmi"/>
+  <mime-type type="application/vividence.scriptfile"/>
+  <mime-type type="application/vnd.3gpp.bsf+xml"/>
+  <mime-type type="application/vnd.3gpp.pic-bw-large">
+    <glob pattern="*.plb"/>
+  </mime-type>
+  <mime-type type="application/vnd.3gpp.pic-bw-small">
+    <glob pattern="*.psb"/>
+  </mime-type>
+  <mime-type type="application/vnd.3gpp.pic-bw-var">
+    <glob pattern="*.pvb"/>
+  </mime-type>
+  <mime-type type="application/vnd.3gpp.sms"/>
+  <mime-type type="application/vnd.3gpp2.bcmcsinfo+xml"/>
+  <mime-type type="application/vnd.3gpp2.sms"/>
+  <mime-type type="application/vnd.3gpp2.tcap">
+    <glob pattern="*.tcap"/>
+  </mime-type>
+  <mime-type type="application/vnd.3m.post-it-notes">
+    <glob pattern="*.pwn"/>
+  </mime-type>
+  <mime-type type="application/vnd.accpac.simply.aso">
+    <glob pattern="*.aso"/>
+  </mime-type>
+  <mime-type type="application/vnd.accpac.simply.imp">
+    <glob pattern="*.imp"/>
+  </mime-type>
+  <mime-type type="application/vnd.acucobol">
+    <glob pattern="*.acu"/>
+  </mime-type>
+  <mime-type type="application/vnd.acucorp">
+    <glob pattern="*.atc"/>
+    <glob pattern="*.acutc"/>
+  </mime-type>
+  <mime-type type="application/vnd.adobe.air-application-installer-package+zip">
+    <glob pattern="*.air"/>
+  </mime-type>
+  <mime-type type="application/vnd.adobe.xdp+xml">
+    <glob pattern="*.xdp"/>
+  </mime-type>
+  <mime-type type="application/vnd.adobe.xfdf">
+    <glob pattern="*.xfdf"/>
+  </mime-type>
+  <mime-type type="application/vnd.aether.imp"/>
+  <mime-type type="application/vnd.airzip.filesecure.azf">
+    <glob pattern="*.azf"/>
+  </mime-type>
+  <mime-type type="application/vnd.airzip.filesecure.azs">
+    <glob pattern="*.azs"/>
+  </mime-type>
+  <mime-type type="application/vnd.amazon.ebook">
+    <glob pattern="*.azw"/>
+  </mime-type>
+  <mime-type type="application/vnd.americandynamics.acc">
+    <glob pattern="*.acc"/>
+  </mime-type>
+  <mime-type type="application/vnd.amiga.ami">
+    <glob pattern="*.ami"/>
+  </mime-type>
+  <mime-type type="application/vnd.android.package-archive">
+    <glob pattern="*.apk"/>
+  </mime-type>
+  <mime-type type="application/vnd.anser-web-certificate-issue-initiation">
+    <glob pattern="*.cii"/>
+  </mime-type>
+  <mime-type type="application/vnd.anser-web-funds-transfer-initiation">
+    <glob pattern="*.fti"/>
+  </mime-type>
+  <mime-type type="application/vnd.antix.game-component">
+    <glob pattern="*.atx"/>
+  </mime-type>
+  <mime-type type="application/vnd.apple.installer+xml">
+    <glob pattern="*.mpkg"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.apple.iwork">
+    <sub-class-of type="application/zip"/>
+    <glob pattern="*.key"/>
+    <glob pattern="*.pages"/>
+    <glob pattern="*.numbers"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.apple.keynote">
+    <root-XML localName="presentation" namespaceURI="http://developer.apple.com/namespaces/keynote2" />
+  </mime-type>
+  <mime-type type="application/vnd.apple.pages">
+    <root-XML localName="document" namespaceURI="http://developer.apple.com/namespaces/sl" />
+  </mime-type>
+  <mime-type type="application/vnd.apple.numbers">
+    <root-XML localName="document" namespaceURI="http://developer.apple.com/namespaces/ls" />
+  </mime-type>
+  <mime-type type="application/vnd.arastra.swi">
+    <glob pattern="*.swi"/>
+  </mime-type>
+  <mime-type type="application/vnd.audiograph">
+    <glob pattern="*.aep"/>
+  </mime-type>
+  <mime-type type="application/vnd.autopackage"/>
+  <mime-type type="application/vnd.avistar+xml"/>
+  <mime-type type="application/vnd.blueice.multipass">
+    <glob pattern="*.mpm"/>
+  </mime-type>
+  <mime-type type="application/vnd.bluetooth.ep.oob"/>
+  <mime-type type="application/vnd.bmi">
+    <glob pattern="*.bmi"/>
+  </mime-type>
+  <mime-type type="application/vnd.businessobjects">
+    <glob pattern="*.rep"/>
+  </mime-type>
+  <mime-type type="application/vnd.cab-jscript"/>
+  <mime-type type="application/vnd.canon-cpdl"/>
+  <mime-type type="application/vnd.canon-lips"/>
+  <mime-type type="application/vnd.cendio.thinlinc.clientconf"/>
+  <mime-type type="application/vnd.chemdraw+xml">
+    <glob pattern="*.cdxml"/>
+  </mime-type>
+  <mime-type type="application/vnd.chipnuts.karaoke-mmd">
+    <glob pattern="*.mmd"/>
+  </mime-type>
+  <mime-type type="application/vnd.cinderella">
+    <glob pattern="*.cdy"/>
+  </mime-type>
+  <mime-type type="application/vnd.cirpack.isdn-ext"/>
+  <mime-type type="application/vnd.claymore">
+    <glob pattern="*.cla"/>
+  </mime-type>
+  <mime-type type="application/vnd.clonk.c4group">
+    <glob pattern="*.c4g"/>
+    <glob pattern="*.c4d"/>
+    <glob pattern="*.c4f"/>
+    <glob pattern="*.c4p"/>
+    <glob pattern="*.c4u"/>
+  </mime-type>
+  <mime-type type="application/vnd.commerce-battelle"/>
+  <mime-type type="application/vnd.commonspace">
+    <glob pattern="*.csp"/>
+  </mime-type>
+  <mime-type type="application/vnd.contact.cmsg">
+    <glob pattern="*.cdbcmsg"/>
+  </mime-type>
+  <mime-type type="application/vnd.cosmocaller">
+    <glob pattern="*.cmc"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker">
+    <glob pattern="*.clkx"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker.keyboard">
+    <glob pattern="*.clkk"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker.palette">
+    <glob pattern="*.clkp"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker.template">
+    <glob pattern="*.clkt"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker.wordbank">
+    <glob pattern="*.clkw"/>
+  </mime-type>
+  <mime-type type="application/vnd.criticaltools.wbs+xml">
+    <glob pattern="*.wbs"/>
+  </mime-type>
+  <mime-type type="application/vnd.ctc-posml">
+    <glob pattern="*.pml"/>
+  </mime-type>
+  <mime-type type="application/vnd.ctct.ws+xml"/>
+  <mime-type type="application/vnd.cups-pdf"/>
+  <mime-type type="application/vnd.cups-postscript"/>
+  <mime-type type="application/vnd.cups-ppd">
+    <glob pattern="*.ppd"/>
+  </mime-type>
+  <mime-type type="application/vnd.cups-raster"/>
+  <mime-type type="application/vnd.cups-raw"/>
+  <mime-type type="application/vnd.curl.car">
+    <glob pattern="*.car"/>
+  </mime-type>
+  <mime-type type="application/vnd.curl.pcurl">
+    <glob pattern="*.pcurl"/>
+  </mime-type>
+  <mime-type type="application/vnd.cybank"/>
+  <mime-type type="application/vnd.data-vision.rdz">
+    <glob pattern="*.rdz"/>
+  </mime-type>
+  <mime-type type="application/vnd.denovo.fcselayout-link">
+    <glob pattern="*.fe_launch"/>
+  </mime-type>
+  <mime-type type="application/vnd.dir-bi.plate-dl-nosuffix"/>
+  <mime-type type="application/vnd.dna">
+    <glob pattern="*.dna"/>
+  </mime-type>
+  <mime-type type="application/vnd.dolby.mlp">
+    <glob pattern="*.mlp"/>
+  </mime-type>
+  <mime-type type="application/vnd.dolby.mobile.1"/>
+  <mime-type type="application/vnd.dolby.mobile.2"/>
+  <mime-type type="application/vnd.dpgraph">
+    <glob pattern="*.dpg"/>
+  </mime-type>
+  <mime-type type="application/vnd.dreamfactory">
+    <glob pattern="*.dfac"/>
+  </mime-type>
+  <mime-type type="application/vnd.dvb.esgcontainer"/>
+  <mime-type type="application/vnd.dvb.ipdcdftnotifaccess"/>
+  <mime-type type="application/vnd.dvb.ipdcesgaccess"/>
+  <mime-type type="application/vnd.dvb.ipdcroaming"/>
+  <mime-type type="application/vnd.dvb.iptv.alfec-base"/>
+  <mime-type type="application/vnd.dvb.iptv.alfec-enhancement"/>
+  <mime-type type="application/vnd.dvb.notif-aggregate-root+xml"/>
+  <mime-type type="application/vnd.dvb.notif-container+xml"/>
+  <mime-type type="application/vnd.dvb.notif-generic+xml"/>
+  <mime-type type="application/vnd.dvb.notif-ia-msglist+xml"/>
+  <mime-type type="application/vnd.dvb.notif-ia-registration-request+xml"/>
+  <mime-type type="application/vnd.dvb.notif-ia-registration-response+xml"/>
+  <mime-type type="application/vnd.dvb.notif-init+xml"/>
+  <mime-type type="application/vnd.dxr"/>
+  <mime-type type="application/vnd.dynageo">
+    <glob pattern="*.geo"/>
+  </mime-type>
+  <mime-type type="application/vnd.ecdis-update"/>
+  <mime-type type="application/vnd.ecowin.chart">
+    <glob pattern="*.mag"/>
+  </mime-type>
+  <mime-type type="application/vnd.ecowin.filerequest"/>
+  <mime-type type="application/vnd.ecowin.fileupdate"/>
+  <mime-type type="application/vnd.ecowin.series"/>
+  <mime-type type="application/vnd.ecowin.seriesrequest"/>
+  <mime-type type="application/vnd.ecowin.seriesupdate"/>
+  <mime-type type="application/vnd.emclient.accessrequest+xml"/>
+  <mime-type type="application/vnd.enliven">
+    <glob pattern="*.nml"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.esf">
+    <glob pattern="*.esf"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.msf">
+    <glob pattern="*.msf"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.quickanime">
+    <glob pattern="*.qam"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.salt">
+    <glob pattern="*.slt"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.ssf">
+    <glob pattern="*.ssf"/>
+  </mime-type>
+  <mime-type type="application/vnd.ericsson.quickcall"/>
+  <mime-type type="application/vnd.eszigno3+xml">
+    <glob pattern="*.es3"/>
+    <glob pattern="*.et3"/>
+  </mime-type>
+  <mime-type type="application/vnd.etsi.aoc+xml"/>
+  <mime-type type="application/vnd.etsi.cug+xml"/>
+  <mime-type type="application/vnd.etsi.iptvcommand+xml"/>
+  <mime-type type="application/vnd.etsi.iptvdiscovery+xml"/>
+  <mime-type type="application/vnd.etsi.iptvprofile+xml"/>
+  <mime-type type="application/vnd.etsi.iptvsad-bc+xml"/>
+  <mime-type type="application/vnd.etsi.iptvsad-cod+xml"/>
+  <mime-type type="application/vnd.etsi.iptvsad-npvr+xml"/>
+  <mime-type type="application/vnd.etsi.iptvueprofile+xml"/>
+  <mime-type type="application/vnd.etsi.mcid+xml"/>
+  <mime-type type="application/vnd.etsi.sci+xml"/>
+  <mime-type type="application/vnd.etsi.simservs+xml"/>
+  <mime-type type="application/vnd.eudora.data"/>
+  <mime-type type="application/vnd.ezpix-album">
+    <glob pattern="*.ez2"/>
+  </mime-type>
+  <mime-type type="application/vnd.ezpix-package">
+    <glob pattern="*.ez3"/>
+  </mime-type>
+  <mime-type type="application/vnd.f-secure.mobile"/>
+  <mime-type type="application/vnd.fdf">
+    <glob pattern="*.fdf"/>
+  </mime-type>
+  <mime-type type="application/vnd.fdsn.mseed">
+    <glob pattern="*.mseed"/>
+  </mime-type>
+  <mime-type type="application/vnd.fdsn.seed">
+    <glob pattern="*.seed"/>
+    <glob pattern="*.dataless"/>
+  </mime-type>
+  <mime-type type="application/vnd.ffsns"/>
+  <mime-type type="application/vnd.fints"/>
+  <mime-type type="application/vnd.flographit">
+    <glob pattern="*.gph"/>
+  </mime-type>
+  <mime-type type="application/vnd.fluxtime.clip">
+    <glob pattern="*.ftc"/>
+  </mime-type>
+  <mime-type type="application/vnd.font-fontforge-sfd"/>
+  <mime-type type="application/vnd.framemaker">
+    <glob pattern="*.fm"/>
+    <glob pattern="*.frame"/>
+    <glob pattern="*.maker"/>
+    <glob pattern="*.book"/>
+  </mime-type>
+  <mime-type type="application/vnd.frogans.fnc">
+    <glob pattern="*.fnc"/>
+  </mime-type>
+  <mime-type type="application/vnd.frogans.ltf">
+    <glob pattern="*.ltf"/>
+  </mime-type>
+  <mime-type type="application/vnd.fsc.weblaunch">
+    <glob pattern="*.fsc"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasys">
+    <glob pattern="*.oas"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasys2">
+    <glob pattern="*.oa2"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasys3">
+    <glob pattern="*.oa3"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasysgp">
+    <glob pattern="*.fg5"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasysprs">
+    <glob pattern="*.bh2"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujixerox.art-ex"/>
+  <mime-type type="application/vnd.fujixerox.art4"/>
+  <mime-type type="application/vnd.fujixerox.hbpl"/>
+  <mime-type type="application/vnd.fujixerox.ddd">
+    <glob pattern="*.ddd"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujixerox.docuworks">
+    <glob pattern="*.xdw"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujixerox.docuworks.binder">
+    <glob pattern="*.xbd"/>
+  </mime-type>
+  <mime-type type="application/vnd.fut-misnet"/>
+  <mime-type type="application/vnd.fuzzysheet">
+    <glob pattern="*.fzs"/>
+  </mime-type>
+  <mime-type type="application/vnd.genomatix.tuxedo">
+    <glob pattern="*.txd"/>
+  </mime-type>
+  <mime-type type="application/vnd.geogebra.file">
+    <glob pattern="*.ggb"/>
+  </mime-type>
+  <mime-type type="application/vnd.geogebra.tool">
+    <glob pattern="*.ggt"/>
+  </mime-type>
+  <mime-type type="application/vnd.geometry-explorer">
+    <glob pattern="*.gex"/>
+    <glob pattern="*.gre"/>
+  </mime-type>
+  <mime-type type="application/vnd.gmx">
+    <glob pattern="*.gmx"/>
+  </mime-type>
+  <mime-type type="application/vnd.google-earth.kml+xml">
+    <glob pattern="*.kml"/>
+  </mime-type>
+  <mime-type type="application/vnd.google-earth.kmz">
+    <glob pattern="*.kmz"/>
+  </mime-type>
+  <mime-type type="application/vnd.grafeq">
+    <glob pattern="*.gqf"/>
+    <glob pattern="*.gqs"/>
+  </mime-type>
+  <mime-type type="application/vnd.gridmp"/>
+  <mime-type type="application/vnd.groove-account">
+    <glob pattern="*.gac"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-help">
+    <glob pattern="*.ghf"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-identity-message">
+    <glob pattern="*.gim"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-injector">
+    <glob pattern="*.grv"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-tool-message">
+    <glob pattern="*.gtm"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-tool-template">
+    <glob pattern="*.tpl"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-vcard">
+    <glob pattern="*.vcg"/>
+  </mime-type>
+  <mime-type type="application/vnd.handheld-entertainment+xml">
+    <glob pattern="*.zmm"/>
+  </mime-type>
+  <mime-type type="application/vnd.hbci">
+    <glob pattern="*.hbci"/>
+  </mime-type>
+  <mime-type type="application/vnd.hcl-bireports"/>
+  <mime-type type="application/vnd.hhe.lesson-player">
+    <glob pattern="*.les"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-hpgl">
+    <glob pattern="*.hpgl"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-hpid">
+    <glob pattern="*.hpid"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-hps">
+    <glob pattern="*.hps"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-jlyt">
+    <glob pattern="*.jlt"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-pcl">
+    <glob pattern="*.pcl"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-pclxl">
+    <glob pattern="*.pclxl"/>
+  </mime-type>
+  <mime-type type="application/vnd.httphone"/>
+  <mime-type type="application/vnd.hydrostatix.sof-data">
+    <glob pattern="*.sfd-hdstx"/>
+  </mime-type>
+  <mime-type type="application/vnd.hzn-3d-crossword">
+    <glob pattern="*.x3d"/>
+  </mime-type>
+  <mime-type type="application/vnd.ibm.afplinedata"/>
+  <mime-type type="application/vnd.ibm.electronic-media"/>
+  <mime-type type="application/vnd.ibm.minipay">
+    <glob pattern="*.mpy"/>
+  </mime-type>
+  <mime-type type="application/vnd.ibm.modcap">
+    <glob pattern="*.afp"/>
+    <glob pattern="*.listafp"/>
+    <glob pattern="*.list3820"/>
+  </mime-type>
+  <mime-type type="application/vnd.ibm.rights-management">
+    <glob pattern="*.irm"/>
+  </mime-type>
+  <mime-type type="application/vnd.ibm.secure-container">
+    <glob pattern="*.sc"/>
+  </mime-type>
+  <mime-type type="application/vnd.iccprofile">
+    <glob pattern="*.icc"/>
+    <glob pattern="*.icm"/>
+  </mime-type>
+  <mime-type type="application/vnd.igloader">
+    <glob pattern="*.igl"/>
+  </mime-type>
+  <mime-type type="application/vnd.immervision-ivp">
+    <glob pattern="*.ivp"/>
+  </mime-type>
+  <mime-type type="application/vnd.immervision-ivu">
+    <glob pattern="*.ivu"/>
+  </mime-type>
+  <mime-type type="application/vnd.informedcontrol.rms+xml"/>
+  <mime-type type="application/vnd.informix-visionary"/>
+  <mime-type type="application/vnd.intercon.formnet">
+    <glob pattern="*.xpw"/>
+    <glob pattern="*.xpx"/>
+  </mime-type>
+  <mime-type type="application/vnd.intertrust.digibox"/>
+  <mime-type type="application/vnd.intertrust.nncp"/>
+  <mime-type type="application/vnd.intu.qbo">
+    <glob pattern="*.qbo"/>
+  </mime-type>
+  <mime-type type="application/vnd.intu.qfx">
+    <glob pattern="*.qfx"/>
+  </mime-type>
+  <mime-type type="application/vnd.iptc.g2.conceptitem+xml"/>
+  <mime-type type="application/vnd.iptc.g2.knowledgeitem+xml"/>
+  <mime-type type="application/vnd.iptc.g2.newsitem+xml"/>
+  <mime-type type="application/vnd.iptc.g2.packageitem+xml"/>
+  <mime-type type="application/vnd.ipunplugged.rcprofile">
+    <glob pattern="*.rcprofile"/>
+  </mime-type>
+  <mime-type type="application/vnd.irepository.package+xml">
+    <glob pattern="*.irp"/>
+  </mime-type>
+  <mime-type type="application/vnd.is-xpr">
+    <glob pattern="*.xpr"/>
+  </mime-type>
+  <mime-type type="application/vnd.jam">
+    <glob pattern="*.jam"/>
+  </mime-type>
+  <mime-type type="application/vnd.japannet-directory-service"/>
+  <mime-type type="application/vnd.japannet-jpnstore-wakeup"/>
+  <mime-type type="application/vnd.japannet-payment-wakeup"/>
+  <mime-type type="application/vnd.japannet-registration"/>
+  <mime-type type="application/vnd.japannet-registration-wakeup"/>
+  <mime-type type="application/vnd.japannet-setstore-wakeup"/>
+  <mime-type type="application/vnd.japannet-verification"/>
+  <mime-type type="application/vnd.japannet-verification-wakeup"/>
+  <mime-type type="application/vnd.jcp.javame.midlet-rms">
+    <glob pattern="*.rms"/>
+  </mime-type>
+  <mime-type type="application/vnd.jisp">
+    <glob pattern="*.jisp"/>
+  </mime-type>
+  <mime-type type="application/vnd.joost.joda-archive">
+    <glob pattern="*.joda"/>
+  </mime-type>
+  <mime-type type="application/vnd.kahootz">
+    <glob pattern="*.ktz"/>
+    <glob pattern="*.ktr"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.karbon">
+    <glob pattern="*.karbon"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kchart">
+    <glob pattern="*.chrt"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kformula">
+    <glob pattern="*.kfo"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kivio">
+    <glob pattern="*.flw"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kontour">
+    <glob pattern="*.kon"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kpresenter">
+    <glob pattern="*.kpr"/>
+    <glob pattern="*.kpt"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kspread">
+    <glob pattern="*.ksp"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kword">
+    <glob pattern="*.kwd"/>
+    <glob pattern="*.kwt"/>
+  </mime-type>
+  <mime-type type="application/vnd.kenameaapp">
+    <glob pattern="*.htke"/>
+  </mime-type>
+  <mime-type type="application/vnd.kidspiration">
+    <glob pattern="*.kia"/>
+  </mime-type>
+  <mime-type type="application/vnd.kinar">
+    <glob pattern="*.kne"/>
+    <glob pattern="*.knp"/>
+  </mime-type>
+  <mime-type type="application/vnd.koan">
+    <alias type="application/x-koan"/>
+    <_comment>SSEYO Koan File</_comment>
+    <glob pattern="*.skp"/>
+    <glob pattern="*.skd"/>
+    <glob pattern="*.skt"/>
+    <glob pattern="*.skm"/>
+  </mime-type>
+  <mime-type type="application/vnd.kodak-descriptor">
+    <glob pattern="*.sse"/>
+  </mime-type>
+  <mime-type type="application/vnd.liberty-request+xml"/>
+  <mime-type type="application/vnd.llamagraphics.life-balance.desktop">
+    <glob pattern="*.lbd"/>
+  </mime-type>
+  <mime-type type="application/vnd.llamagraphics.life-balance.exchange+xml">
+    <glob pattern="*.lbe"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-1-2-3">
+    <glob pattern="*.123"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-approach">
+    <glob pattern="*.apr"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-freelance">
+    <glob pattern="*.pre"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-notes">
+    <glob pattern="*.nsf"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-organizer">
+    <glob pattern="*.org"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-screencam">
+    <glob pattern="*.scm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.lotus-wordpro">
+    <magic priority="50">
+      <match value="WordPro\0" type="string" offset="0" />
+      <match value="WordPro\r\373" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.lwp"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.macports.portpkg">
+    <glob pattern="*.portpkg"/>
+  </mime-type>
+  <mime-type type="application/vnd.marlin.drm.actiontoken+xml"/>
+  <mime-type type="application/vnd.marlin.drm.conftoken+xml"/>
+  <mime-type type="application/vnd.marlin.drm.license+xml"/>
+  <mime-type type="application/vnd.marlin.drm.mdcf"/>
+  <mime-type type="application/vnd.mcd">
+    <glob pattern="*.mcd"/>
+  </mime-type>
+  <mime-type type="application/vnd.medcalcdata">
+    <glob pattern="*.mc1"/>
+  </mime-type>
+  <mime-type type="application/vnd.mediastation.cdkey">
+    <glob pattern="*.cdkey"/>
+  </mime-type>
+  <mime-type type="application/vnd.meridian-slingshot"/>
+  <mime-type type="application/vnd.mfer">
+    <glob pattern="*.mwf"/>
+  </mime-type>
+  <mime-type type="application/vnd.mfmp">
+    <glob pattern="*.mfm"/>
+  </mime-type>
+  <mime-type type="application/vnd.micrografx.flo">
+    <glob pattern="*.flo"/>
+  </mime-type>
+  <mime-type type="application/vnd.micrografx.igx">
+    <glob pattern="*.igx"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.mif">
+    <_comment>FrameMaker MIF document</_comment>
+    <alias type="application/x-mif"/>
+    <alias type="application/x-frame"/>
+    <magic priority="50">
+      <match value="\&lt;MakerFile" type="string" offset="0" />
+      <match value="\&lt;MIFFile" type="string" offset="0" />
+      <match value="\&lt;MakerDictionary" type="string" offset="0" />
+      <match value="\&lt;MakerScreenFont" type="string" offset="0" />
+      <match value="\&lt;MML" type="string" offset="0" />
+      <match value="\&lt;Book" type="string" offset="0" />
+      <match value="\&lt;Maker" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.mif"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.minisoft-hp3000-save"/>
+  <mime-type type="application/vnd.mitsubishi.misty-guard.trustweb"/>
+  <mime-type type="application/vnd.mobius.daf">
+    <glob pattern="*.daf"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.dis">
+    <glob pattern="*.dis"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.mbk">
+    <glob pattern="*.mbk"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.mqy">
+    <glob pattern="*.mqy"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.msl">
+    <glob pattern="*.msl"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.plc">
+    <glob pattern="*.plc"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.txf">
+    <glob pattern="*.txf"/>
+  </mime-type>
+  <mime-type type="application/vnd.mophun.application">
+    <glob pattern="*.mpn"/>
+  </mime-type>
+  <mime-type type="application/vnd.mophun.certificate">
+    <glob pattern="*.mpc"/>
+  </mime-type>
+  <mime-type type="application/vnd.motorola.flexsuite"/>
+  <mime-type type="application/vnd.motorola.flexsuite.adsi"/>
+  <mime-type type="application/vnd.motorola.flexsuite.fis"/>
+  <mime-type type="application/vnd.motorola.flexsuite.gotap"/>
+  <mime-type type="application/vnd.motorola.flexsuite.kmr"/>
+  <mime-type type="application/vnd.motorola.flexsuite.ttc"/>
+  <mime-type type="application/vnd.motorola.flexsuite.wem"/>
+  <mime-type type="application/vnd.motorola.iprm"/>
+  <mime-type type="application/vnd.mozilla.xul+xml">
+    <glob pattern="*.xul"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-artgalry">
+    <glob pattern="*.cil"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-asf"/>
+  <mime-type type="application/vnd.ms-cab-compressed">
+    <glob pattern="*.cab"/>
+  </mime-type>
+
+  <!-- http://www.iana.org/assignments/media-types/application/vnd.ms-excel -->
+  <mime-type type="application/vnd.ms-excel">
+    <!-- Use org.apache.tika.detect.ContainerAwareDetector for more reliable detection of OLE2 documents -->
+    <alias type="application/msexcel" />
+    <_comment>Microsoft Excel Spreadsheet</_comment>
+    <magic priority="50">
+      <match value="Microsoft\ Excel\ 5.0\ Worksheet" type="string" offset="2080"/>
+      <match value="Foglio\ di\ lavoro\ Microsoft\ Exce" type="string" offset="2080"/>
+      <match value="Biff5" type="string" offset="2114"/>
+      <match value="Biff5" type="string" offset="2121"/>
+      <match value="\x09\x04\x06\x00\x00\x00\x10\x00" type="string" offset="0"/>
+      <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+         <match value="W\x00o\x00r\x00k\x00b\x00o\x00o\x00k" type="string" offset="1152:4096" />
+      </match>
+    </magic>
+    <glob pattern="*.xls"/>
+    <glob pattern="*.xlm"/>
+    <glob pattern="*.xla"/>
+    <glob pattern="*.xlc"/>
+    <glob pattern="*.xlt"/>
+    <glob pattern="*.xlw"/>
+    <glob pattern="*.xll"/>
+    <glob pattern="*.xld"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.addin.macroenabled.12">
+    <_comment>Office Open XML Workbook Add-in (macro-enabled)</_comment>
+    <glob pattern="*.xlam"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.sheet.macroenabled.12">
+    <_comment>Office Open XML Workbook (macro-enabled)</_comment>
+    <glob pattern="*.xlsm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.sheet.binary.macroenabled.12">
+    <_comment>Microsoft Excel 2007 Binary Spreadsheet</_comment>
+    <glob pattern="*.xlsb"/>
+    <sub-class-of type="application/vnd.ms-excel"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.template.macroenabled.12">
+    <glob pattern="*.xltm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-fontobject">
+    <glob pattern="*.eot"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-htmlhelp">
+    <glob pattern="*.chm"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-ims">
+    <glob pattern="*.ims"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-lrm">
+    <glob pattern="*.lrm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-outlook">
+    <_comment>Microsoft Outlook Message</_comment>
+    <glob pattern="*.msg" />
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-pki.seccat">
+    <glob pattern="*.cat"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-pki.stl">
+    <glob pattern="*.stl"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-playready.initiator+xml"/>
+
+  <!-- http://www.iana.org/assignments/media-types/application/vnd.ms-powerpoint -->
+  <mime-type type="application/vnd.ms-powerpoint">
+    <!-- Use org.apache.tika.detect.ContainerAwareDetector for more reliable detection of OLE2 documents -->
+    <alias type="application/mspowerpoint"/>
+    <_comment>Microsoft Powerpoint Presentation</_comment>
+    <magic priority="50">
+      <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+         <match value="P\x00o\x00w\x00e\x00r\x00P\x00o\x00i\x00n\x00t\x00 D\x00o\x00c\x00u\x00m\x00e\x00n\x00t" type="string" offset="1152:4096" />
+      </match>
+    </magic>
+    <glob pattern="*.ppz"/>
+    <glob pattern="*.ppt"/>
+    <glob pattern="*.pps"/>
+    <glob pattern="*.pot"/>
+    <glob pattern="*.ppa"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.addin.macroenabled.12">
+    <_comment>Office Open XML Presentation Add-in (macro-enabled)</_comment>
+    <glob pattern="*.ppam"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.presentation.macroenabled.12">
+    <_comment>Office Open XML Presentation (macro-enabled)</_comment>
+    <glob pattern="*.pptm"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.slide.macroenabled.12">
+    <glob pattern="*.sldm"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.slideshow.macroenabled.12">
+    <_comment>Office Open XML Presentation Slideshow (macro-enabled)</_comment>
+    <glob pattern="*.ppsm"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.template.macroenabled.12">
+    <glob pattern="*.potm"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-project">
+    <glob pattern="*.mpp"/>
+    <glob pattern="*.mpt"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-tnef">
+    <alias type="application/ms-tnef" />
+    <magic priority="50">
+      <match value="0x223e9f78" type="little16" offset="0" />
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-wmdrm.lic-chlg-req"/>
+  <mime-type type="application/vnd.ms-wmdrm.lic-resp"/>
+  <mime-type type="application/vnd.ms-wmdrm.meter-chlg-req"/>
+  <mime-type type="application/vnd.ms-wmdrm.meter-resp"/>
+
+  <mime-type type="application/vnd.ms-word.document.macroenabled.12">
+    <_comment>Office Open XML Document (macro-enabled)</_comment>
+    <glob pattern="*.docm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-word.template.macroenabled.12">
+    <_comment>Office Open XML Document Template (macro-enabled)</_comment>
+    <glob pattern="*.dotm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-works">
+    <glob pattern="*.wps"/>
+    <glob pattern="*.wks"/>
+    <glob pattern="*.wcm"/>
+    <glob pattern="*.wdb"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-wpl">
+    <glob pattern="*.wpl"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-xpsdocument">
+    <glob pattern="*.xps"/>
+  </mime-type>
+  <mime-type type="application/vnd.mseq">
+    <glob pattern="*.mseq"/>
+  </mime-type>
+  <mime-type type="application/vnd.msign"/>
+  <mime-type type="application/vnd.multiad.creator"/>
+  <mime-type type="application/vnd.multiad.creator.cif"/>
+  <mime-type type="application/vnd.music-niff"/>
+  <mime-type type="application/vnd.musician">
+    <glob pattern="*.mus"/>
+  </mime-type>
+  <mime-type type="application/vnd.muvee.style">
+    <glob pattern="*.msty"/>
+  </mime-type>
+  <mime-type type="application/vnd.ncd.control"/>
+  <mime-type type="application/vnd.ncd.reference"/>
+  <mime-type type="application/vnd.nervana"/>
+  <mime-type type="application/vnd.netfpx"/>
+  <mime-type type="application/vnd.neurolanguage.nlu">
+    <glob pattern="*.nlu"/>
+  </mime-type>
+  <mime-type type="application/vnd.noblenet-directory">
+    <glob pattern="*.nnd"/>
+  </mime-type>
+  <mime-type type="application/vnd.noblenet-sealer">
+    <glob pattern="*.nns"/>
+  </mime-type>
+  <mime-type type="application/vnd.noblenet-web">
+    <glob pattern="*.nnw"/>
+  </mime-type>
+  <mime-type type="application/vnd.nokia.catalogs"/>
+  <mime-type type="application/vnd.nokia.conml+wbxml"/>
+  <mime-type type="application/vnd.nokia.conml+xml"/>
+  <mime-type type="application/vnd.nokia.isds-radio-presets"/>
+  <mime-type type="application/vnd.nokia.iptv.config+xml"/>
+  <mime-type type="application/vnd.nokia.landmark+wbxml"/>
+  <mime-type type="application/vnd.nokia.landmark+xml"/>
+  <mime-type type="application/vnd.nokia.landmarkcollection+xml"/>
+  <mime-type type="application/vnd.nokia.n-gage.ac+xml"/>
+  <mime-type type="application/vnd.nokia.n-gage.data">
+    <glob pattern="*.ngdat"/>
+  </mime-type>
+  <mime-type type="application/vnd.nokia.n-gage.symbian.install">
+    <glob pattern="*.n-gage"/>
+  </mime-type>
+  <mime-type type="application/vnd.nokia.ncd"/>
+  <mime-type type="application/vnd.nokia.pcd+wbxml"/>
+  <mime-type type="application/vnd.nokia.pcd+xml"/>
+  <mime-type type="application/vnd.nokia.radio-preset">
+    <glob pattern="*.rpst"/>
+  </mime-type>
+  <mime-type type="application/vnd.nokia.radio-presets">
+    <glob pattern="*.rpss"/>
+  </mime-type>
+  <mime-type type="application/vnd.novadigm.edm">
+    <glob pattern="*.edm"/>
+  </mime-type>
+  <mime-type type="application/vnd.novadigm.edx">
+    <glob pattern="*.edx"/>
+  </mime-type>
+  <mime-type type="application/vnd.novadigm.ext">
+    <glob pattern="*.ext"/>
+  </mime-type>
+
+  <!-- =================================================================== -->
+  <!-- Open Document Format for Office Applications (OpenDocument) v1.0    -->
+  <!-- http://www.oasis-open.org/specs/index.php#opendocumentv1.0          -->
+  <!-- =================================================================== -->
+
+  <mime-type type="application/vnd.oasis.opendocument.chart">
+    <alias type="application/x-vnd.oasis.opendocument.chart"/>
+    <_comment>OpenDocument v1.0: Chart document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.chart"/>
+      </match>
+    </magic>
+    <glob pattern="*.odc"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.chart-template">
+    <alias type="application/x-vnd.oasis.opendocument.chart-template"/>
+    <_comment>OpenDocument v1.0: Chart document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.chart-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.otc"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.database">
+    <glob pattern="*.odb"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.formula">
+    <alias type="application/x-vnd.oasis.opendocument.formula"/>
+    <_comment>OpenDocument v1.0: Formula document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.formula" />
+      </match>
+    </magic>
+    <glob pattern="*.odf"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.formula-template">
+    <alias type="application/x-vnd.oasis.opendocument.formula-template"/>
+    <_comment>OpenDocument v1.0: Formula document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.formula-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.odft"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.graphics">
+    <alias type="application/x-vnd.oasis.opendocument.graphics"/>
+    <_comment>OpenDocument v1.0: Graphics document (Drawing)</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.graphics"/>
+      </match>
+    </magic>
+    <glob pattern="*.odg"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.graphics-template">
+    <alias type="application/x-vnd.oasis.opendocument.graphics-template"/>
+    <_comment>OpenDocument v1.0: Graphics document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.graphics-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.otg"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.image">
+    <alias type="application/x-vnd.oasis.opendocument.image"/>
+    <_comment>OpenDocument v1.0: Image document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.image"/>
+      </match>
+    </magic>
+    <glob pattern="*.odi"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.image-template">
+    <alias type="application/x-vnd.oasis.opendocument.image-template"/>
+    <_comment>OpenDocument v1.0: Image document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.image-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.oti"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.presentation">
+    <alias type="application/x-vnd.oasis.opendocument.presentation"/>
+    <_comment>OpenDocument v1.0: Presentation document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.presentation"/>
+      </match>
+    </magic>
+    <glob pattern="*.odp"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.presentation-template">
+    <alias type="application/x-vnd.oasis.opendocument.presentation-template"/>
+    <_comment>OpenDocument v1.0: Presentation document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+              value="mimetypeapplication/vnd.oasis.opendocument.presentation-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.otp"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.spreadsheet">
+    <alias type="application/x-vnd.oasis.opendocument.spreadsheet"/>
+    <_comment>OpenDocument v1.0: Spreadsheet document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.spreadsheet"/>
+      </match>
+    </magic>
+    <glob pattern="*.ods"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.spreadsheet-template">
+    <alias type="application/x-vnd.oasis.opendocument.spreadsheet-template"/>
+    <_comment>OpenDocument v1.0: Spreadsheet document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.spreadsheet-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.ots"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.text">
+    <alias type="application/x-vnd.oasis.opendocument.text"/>
+    <_comment>OpenDocument v1.0: Text document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.text"/>
+      </match>
+    </magic>
+    <glob pattern="*.odt"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.text-master">
+    <alias type="application/x-vnd.oasis.opendocument.text-master"/>
+    <_comment>OpenDocument v1.0: Global Text document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.text-master"/>
+      </match>
+    </magic>
+    <glob pattern="*.otm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.text-template">
+    <alias type="application/x-vnd.oasis.opendocument.text-template"/>
+    <_comment>OpenDocument v1.0: Text document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+              value="mimetypeapplication/vnd.oasis.opendocument.text-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.ott"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.text-web">
+    <alias type="application/x-vnd.oasis.opendocument.text-web"/>
+    <_comment>OpenDocument v1.0: Text document used as template for HTML documents</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+              value="mimetypeapplication/vnd.oasis.opendocument.text-web"/>
+      </match>
+    </magic>
+    <glob pattern="*.oth"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.obn"/>
+  <mime-type type="application/vnd.olpc-sugar">
+    <glob pattern="*.xo"/>
+  </mime-type>
+  <mime-type type="application/vnd.oma-scws-config"/>
+  <mime-type type="application/vnd.oma-scws-http-request"/>
+  <mime-type type="application/vnd.oma-scws-http-response"/>
+  <mime-type type="application/vnd.oma.bcast.associated-procedure-parameter+xml"/>
+  <mime-type type="application/vnd.oma.bcast.drm-trigger+xml"/>
+  <mime-type type="application/vnd.oma.bcast.imd+xml"/>
+  <mime-type type="application/vnd.oma.bcast.ltkm"/>
+  <mime-type type="application/vnd.oma.bcast.notification+xml"/>
+  <mime-type type="application/vnd.oma.bcast.provisioningtrigger"/>
+  <mime-type type="application/vnd.oma.bcast.sgboot"/>
+  <mime-type type="application/vnd.oma.bcast.sgdd+xml"/>
+  <mime-type type="application/vnd.oma.bcast.sgdu"/>
+  <mime-type type="application/vnd.oma.bcast.simple-symbol-container"/>
+  <mime-type type="application/vnd.oma.bcast.smartcard-trigger+xml"/>
+  <mime-type type="application/vnd.oma.bcast.sprov+xml"/>
+  <mime-type type="application/vnd.oma.bcast.stkm"/>
+  <mime-type type="application/vnd.oma.dcd"/>
+  <mime-type type="application/vnd.oma.dcdc"/>
+  <mime-type type="application/vnd.oma.dd2+xml">
+    <glob pattern="*.dd2"/>
+  </mime-type>
+  <mime-type type="application/vnd.oma.drm.risd+xml"/>
+  <mime-type type="application/vnd.oma.group-usage-list+xml"/>
+  <mime-type type="application/vnd.oma.poc.detailed-progress-report+xml"/>
+  <mime-type type="application/vnd.oma.poc.final-report+xml"/>
+  <mime-type type="application/vnd.oma.poc.groups+xml"/>
+  <mime-type type="application/vnd.oma.poc.invocation-descriptor+xml"/>
+  <mime-type type="application/vnd.oma.poc.optimized-progress-report+xml"/>
+  <mime-type type="application/vnd.oma.xcap-directory+xml"/>
+  <mime-type type="application/vnd.omads-email+xml"/>
+  <mime-type type="application/vnd.omads-file+xml"/>
+  <mime-type type="application/vnd.omads-folder+xml"/>
+  <mime-type type="application/vnd.omaloc-supl-init"/>
+
+  <mime-type type="application/vnd.openofficeorg.extension">
+    <glob pattern="*.oxt"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.presentation">
+    <_comment>Office Open XML Presentation</_comment>
+    <glob pattern="*.pptx"/>
+    <glob pattern="*.thmx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slide">
+    <glob pattern="*.sldx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slideshow">
+    <glob pattern="*.ppsx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.template">
+    <_comment>Office Open XML Presentation Template</_comment>
+    <glob pattern="*.potx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slideshow">
+    <_comment>Office Open XML Presentation Slideshow</_comment>
+    <glob pattern="*.ppsx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
+    <_comment>Office Open XML Workbook</_comment>
+    <glob pattern="*.xlsx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.spreadsheetml.template">
+    <_comment>Office Open XML Workbook Template</_comment>
+    <glob pattern="*.xltx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.template.macroenabled.12">
+    <_comment>Office Open XML Workbook Template (macro-enabled)</_comment>
+    <glob pattern="*.xltm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.document">
+    <_comment>Office Open XML Document</_comment>
+    <glob pattern="*.docx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.template">
+    <_comment>Office Open XML Document Template</_comment>
+    <glob pattern="*.dotx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.osa.netdeploy"/>
+  <mime-type type="application/vnd.osgi.bundle"/>
+  <mime-type type="application/vnd.osgi.dp">
+    <glob pattern="*.dp"/>
+  </mime-type>
+  <mime-type type="application/vnd.otps.ct-kip+xml"/>
+  <mime-type type="application/vnd.palm">
+    <glob pattern="*.pdb"/>
+    <glob pattern="*.pqa"/>
+    <glob pattern="*.oprc"/>
+  </mime-type>
+  <mime-type type="application/vnd.paos.xml"/>
+  <mime-type type="application/vnd.pg.format">
+    <glob pattern="*.str"/>
+  </mime-type>
+  <mime-type type="application/vnd.pg.osasli">
+    <glob pattern="*.ei6"/>
+  </mime-type>
+  <mime-type type="application/vnd.piaccess.application-licence"/>
+  <mime-type type="application/vnd.picsel">
+    <glob pattern="*.efif"/>
+  </mime-type>
+  <mime-type type="application/vnd.poc.group-advertisement+xml"/>
+  <mime-type type="application/vnd.pocketlearn">
+    <glob pattern="*.plf"/>
+  </mime-type>
+  <mime-type type="application/vnd.powerbuilder6">
+    <glob pattern="*.pbd"/>
+  </mime-type>
+  <mime-type type="application/vnd.powerbuilder6-s"/>
+  <mime-type type="application/vnd.powerbuilder7"/>
+  <mime-type type="application/vnd.powerbuilder7-s"/>
+  <mime-type type="application/vnd.powerbuilder75"/>
+  <mime-type type="application/vnd.powerbuilder75-s"/>
+  <mime-type type="application/vnd.preminet"/>
+  <mime-type type="application/vnd.previewsystems.box">
+    <glob pattern="*.box"/>
+  </mime-type>
+  <mime-type type="application/vnd.proteus.magazine">
+    <glob pattern="*.mgz"/>
+  </mime-type>
+  <mime-type type="application/vnd.publishare-delta-tree">
+    <glob pattern="*.qps"/>
+  </mime-type>
+  <mime-type type="application/vnd.pvi.ptid1">
+    <glob pattern="*.ptid"/>
+  </mime-type>
+  <mime-type type="application/vnd.pwg-multiplexed"/>
+  <mime-type type="application/vnd.pwg-xhtml-print+xml"/>
+  <mime-type type="application/vnd.qualcomm.brew-app-res"/>
+  <mime-type type="application/vnd.quark.quarkxpress">
+    <glob pattern="*.qxd"/>
+    <glob pattern="*.qxt"/>
+    <glob pattern="*.qwd"/>
+    <glob pattern="*.qwt"/>
+    <glob pattern="*.qxl"/>
+    <glob pattern="*.qxb"/>
+  </mime-type>
+  <mime-type type="application/vnd.rapid"/>
+  <mime-type type="application/vnd.recordare.musicxml">
+    <glob pattern="*.mxl"/>
+  </mime-type>
+  <mime-type type="application/vnd.recordare.musicxml+xml">
+    <glob pattern="*.musicxml"/>
+  </mime-type>
+  <mime-type type="application/vnd.renlearn.rlprint"/>
+  <mime-type type="application/vnd.rim.cod">
+    <glob pattern="*.cod"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.rn-realmedia">
+    <magic priority="50">
+      <match value=".RMF" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.rm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.route66.link66+xml">
+    <glob pattern="*.link66"/>
+  </mime-type>
+  <mime-type type="application/vnd.ruckus.download"/>
+  <mime-type type="application/vnd.s3sms"/>
+  <mime-type type="application/vnd.sbm.cid"/>
+  <mime-type type="application/vnd.sbm.mid2"/>
+  <mime-type type="application/vnd.scribus"/>
+  <mime-type type="application/vnd.sealed.3df"/>
+  <mime-type type="application/vnd.sealed.csf"/>
+  <mime-type type="application/vnd.sealed.doc"/>
+  <mime-type type="application/vnd.sealed.eml"/>
+  <mime-type type="application/vnd.sealed.mht"/>
+  <mime-type type="application/vnd.sealed.net"/>
+  <mime-type type="application/vnd.sealed.ppt"/>
+  <mime-type type="application/vnd.sealed.tiff"/>
+  <mime-type type="application/vnd.sealed.xls"/>
+  <mime-type type="application/vnd.sealedmedia.softseal.html"/>
+  <mime-type type="application/vnd.sealedmedia.softseal.pdf"/>
+  <mime-type type="application/vnd.seemail">
+    <glob pattern="*.see"/>
+  </mime-type>
+  <mime-type type="application/vnd.sema">
+    <glob pattern="*.sema"/>
+  </mime-type>
+  <mime-type type="application/vnd.semd">
+    <glob pattern="*.semd"/>
+  </mime-type>
+  <mime-type type="application/vnd.semf">
+    <glob pattern="*.semf"/>
+  </mime-type>
+  <mime-type type="application/vnd.shana.informed.formdata">
+    <glob pattern="*.ifm"/>
+  </mime-type>
+  <mime-type type="application/vnd.shana.informed.formtemplate">
+    <glob pattern="*.itp"/>
+  </mime-type>
+  <mime-type type="application/vnd.shana.informed.interchange">
+    <glob pattern="*.iif"/>
+  </mime-type>
+  <mime-type type="application/vnd.shana.informed.package">
+    <glob pattern="*.ipk"/>
+  </mime-type>
+  <mime-type type="application/vnd.simtech-mindmapper">
+    <glob pattern="*.twd"/>
+    <glob pattern="*.twds"/>
+  </mime-type>
+  <mime-type type="application/vnd.smaf">
+    <glob pattern="*.mmf"/>
+  </mime-type>
+  <mime-type type="application/vnd.smart.teacher">
+    <glob pattern="*.teacher"/>
+  </mime-type>
+  <mime-type type="application/vnd.software602.filler.form+xml"/>
+  <mime-type type="application/vnd.software602.filler.form-xml-zip"/>
+  <mime-type type="application/vnd.solent.sdkm+xml">
+    <glob pattern="*.sdkm"/>
+    <glob pattern="*.sdkd"/>
+  </mime-type>
+  <mime-type type="application/vnd.spotfire.dxp">
+    <glob pattern="*.dxp"/>
+  </mime-type>
+  <mime-type type="application/vnd.spotfire.sfs">
+    <glob pattern="*.sfs"/>
+  </mime-type>
+  <mime-type type="application/vnd.sss-cod"/>
+  <mime-type type="application/vnd.sss-dtf"/>
+  <mime-type type="application/vnd.sss-ntf"/>
+  <mime-type type="application/vnd.stardivision.calc">
+    <glob pattern="*.sdc"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.draw">
+    <glob pattern="*.sda"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.impress">
+    <glob pattern="*.sdd"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.math">
+    <glob pattern="*.smf"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.writer">
+    <glob pattern="*.sdw"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.writer">
+    <glob pattern="*.vor"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.writer-global">
+    <glob pattern="*.sgl"/>
+  </mime-type>
+  <mime-type type="application/vnd.street-stream"/>
+  <mime-type type="application/vnd.sun.xml.calc">
+    <glob pattern="*.sxc"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.calc.template">
+    <glob pattern="*.stc"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.draw">
+    <glob pattern="*.sxd"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.draw.template">
+    <glob pattern="*.std"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.impress">
+    <glob pattern="*.sxi"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.impress.template">
+    <glob pattern="*.sti"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.math">
+    <glob pattern="*.sxm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.sun.xml.writer">
+    <alias type="application/x-vnd.sun.xml.writer"/>
+    <_comment>OpenOffice v1.0: Writer Document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+          value="mimetypeapplication/vnd.sun.xml.writer"/>
+      </match>
+    </magic>
+    <glob pattern="*.sxw"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.sun.xml.writer.global">
+    <glob pattern="*.sxg"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.writer.template">
+    <glob pattern="*.stw"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.wadl+xml"/>
+  <mime-type type="application/vnd.sus-calendar">
+    <glob pattern="*.sus"/>
+    <glob pattern="*.susp"/>
+  </mime-type>
+  <mime-type type="application/vnd.svd">
+    <glob pattern="*.svd"/>
+  </mime-type>
+  <mime-type type="application/vnd.swiftview-ics"/>
+
+  <mime-type type="application/vnd.symbian.install">
+    <magic priority="50">
+      <match value="0x10000419" type="little32" offset="8" />
+    </magic>
+    <glob pattern="*.sis"/>
+    <glob pattern="*.sisx"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.syncml+xml">
+    <glob pattern="*.xsm"/>
+  </mime-type>
+  <mime-type type="application/vnd.syncml.dm+wbxml">
+    <glob pattern="*.bdm"/>
+  </mime-type>
+  <mime-type type="application/vnd.syncml.dm+xml">
+    <glob pattern="*.xdm"/>
+  </mime-type>
+  <mime-type type="application/vnd.syncml.dm.notification"/>
+  <mime-type type="application/vnd.syncml.ds.notification"/>
+  <mime-type type="application/vnd.tao.intent-module-archive">
+    <glob pattern="*.tao"/>
+  </mime-type>
+  <mime-type type="application/vnd.tmobile-livetv">
+    <glob pattern="*.tmo"/>
+  </mime-type>
+  <mime-type type="application/vnd.trid.tpt">
+    <glob pattern="*.tpt"/>
+  </mime-type>
+  <mime-type type="application/vnd.triscape.mxs">
+    <glob pattern="*.mxs"/>
+  </mime-type>
+  <mime-type type="application/vnd.trueapp">
+    <glob pattern="*.tra"/>
+  </mime-type>
+  <mime-type type="application/vnd.truedoc"/>
+  <mime-type type="application/vnd.ufdl">
+    <glob pattern="*.ufd"/>
+    <glob pattern="*.ufdl"/>
+  </mime-type>
+  <mime-type type="application/vnd.uiq.theme">
+    <glob pattern="*.utz"/>
+  </mime-type>
+  <mime-type type="application/vnd.umajin">
+    <glob pattern="*.umj"/>
+  </mime-type>
+  <mime-type type="application/vnd.unity">
+    <glob pattern="*.unityweb"/>
+  </mime-type>
+  <mime-type type="application/vnd.uoml+xml">
+    <glob pattern="*.uoml"/>
+  </mime-type>
+  <mime-type type="application/vnd.uplanet.alert"/>
+  <mime-type type="application/vnd.uplanet.alert-wbxml"/>
+  <mime-type type="application/vnd.uplanet.bearer-choice"/>
+  <mime-type type="application/vnd.uplanet.bearer-choice-wbxml"/>
+  <mime-type type="application/vnd.uplanet.cacheop"/>
+  <mime-type type="application/vnd.uplanet.cacheop-wbxml"/>
+  <mime-type type="application/vnd.uplanet.channel"/>
+  <mime-type type="application/vnd.uplanet.channel-wbxml"/>
+  <mime-type type="application/vnd.uplanet.list"/>
+  <mime-type type="application/vnd.uplanet.list-wbxml"/>
+  <mime-type type="application/vnd.uplanet.listcmd"/>
+  <mime-type type="application/vnd.uplanet.listcmd-wbxml"/>
+  <mime-type type="application/vnd.uplanet.signal"/>
+  <mime-type type="application/vnd.vcx">
+    <glob pattern="*.vcx"/>
+  </mime-type>
+  <mime-type type="application/vnd.vd-study"/>
+  <mime-type type="application/vnd.vectorworks"/>
+  <mime-type type="application/vnd.vidsoft.vidconference"/>
+
+  <!-- http://www.iana.org/assignments/media-types/application/vnd.visio -->
+  <mime-type type="application/vnd.visio">
+    <_comment>Microsoft Visio Diagram</_comment>
+    <glob pattern="*.vsd"/>
+    <glob pattern="*.vst"/>
+    <glob pattern="*.vss"/>
+    <glob pattern="*.vsw"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.visionary">
+    <glob pattern="*.vis"/>
+  </mime-type>
+  <mime-type type="application/vnd.vividence.scriptfile"/>
+  <mime-type type="application/vnd.vsf">
+    <glob pattern="*.vsf"/>
+  </mime-type>
+  <mime-type type="application/vnd.wap.sic"/>
+  <mime-type type="application/vnd.wap.slc"/>
+
+  <mime-type type="application/vnd.wap.wbxml">
+    <glob pattern="*.wbxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.wap.wmlc">
+    <_comment>Compiled WML Document</_comment>
+    <glob pattern="*.wmlc"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.wap.wmlscriptc">
+    <_comment>Compiled WML Script</_comment>
+    <glob pattern="*.wmlsc"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.webturbo">
+    <glob pattern="*.wtb"/>
+  </mime-type>
+  <mime-type type="application/vnd.wfa.wsc"/>
+  <mime-type type="application/vnd.wmc"/>
+  <mime-type type="application/vnd.wmf.bootstrap"/>
+  <mime-type type="application/vnd.wordperfect">
+    <glob pattern="*.wpd"/>
+  </mime-type>
+  <mime-type type="application/vnd.wqd">
+    <glob pattern="*.wqd"/>
+  </mime-type>
+  <mime-type type="application/vnd.wrq-hp3000-labelled"/>
+  <mime-type type="application/vnd.wt.stf">
+    <glob pattern="*.stf"/>
+  </mime-type>
+  <mime-type type="application/vnd.wv.csp+wbxml"/>
+  <mime-type type="application/vnd.wv.csp+xml"/>
+  <mime-type type="application/vnd.wv.ssp+xml"/>
+  <mime-type type="application/vnd.xara">
+    <glob pattern="*.xar"/>
+  </mime-type>
+  <mime-type type="application/vnd.xfdl">
+    <glob pattern="*.xfdl"/>
+  </mime-type>
+  <mime-type type="application/vnd.xfdl.webform"/>
+  <mime-type type="application/vnd.xmi+xml"/>
+  <mime-type type="application/vnd.xmpie.cpkg"/>
+  <mime-type type="application/vnd.xmpie.dpkg"/>
+  <mime-type type="application/vnd.xmpie.plan"/>
+  <mime-type type="application/vnd.xmpie.ppkg"/>
+  <mime-type type="application/vnd.xmpie.xlim"/>
+  <mime-type type="application/vnd.yamaha.hv-dic">
+    <glob pattern="*.hvd"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.hv-script">
+    <glob pattern="*.hvs"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.hv-voice">
+    <glob pattern="*.hvp"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.openscoreformat">
+    <glob pattern="*.osf"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.openscoreformat.osfpvg+xml">
+    <glob pattern="*.osfpvg"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.smaf-audio">
+    <glob pattern="*.saf"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.smaf-phrase">
+    <glob pattern="*.spf"/>
+  </mime-type>
+  <mime-type type="application/vnd.yellowriver-custom-menu">
+    <glob pattern="*.cmp"/>
+  </mime-type>
+  <mime-type type="application/vnd.zul">
+    <glob pattern="*.zir"/>
+    <glob pattern="*.zirz"/>
+  </mime-type>
+  <mime-type type="application/vnd.zzazz.deck+xml">
+    <glob pattern="*.zaz"/>
+  </mime-type>
+  <mime-type type="application/voicexml+xml">
+    <glob pattern="*.vxml"/>
+  </mime-type>
+  <mime-type type="application/watcherinfo+xml"/>
+  <mime-type type="application/whoispp-query"/>
+  <mime-type type="application/whoispp-response"/>
+  <mime-type type="application/winhlp">
+    <glob pattern="*.hlp"/>
+  </mime-type>
+  <mime-type type="application/wita"/>
+  <mime-type type="application/wordperfect5.1"/>
+  <mime-type type="application/wsdl+xml">
+    <glob pattern="*.wsdl"/>
+  </mime-type>
+  <mime-type type="application/wspolicy+xml">
+    <glob pattern="*.wspolicy"/>
+  </mime-type>
+
+  <mime-type type="application/x-123">
+    <magic priority="50">
+      <match value="0x00001a00" type="big32" offset="0" />
+      <match value="0x00000200" type="big32" offset="0" />
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-abiword">
+    <glob pattern="*.abw"/>
+  </mime-type>
+  <mime-type type="application/x-ace-compressed">
+    <glob pattern="*.ace"/>
+  </mime-type>
+
+  <mime-type type="application/x-adobe-indesign">
+    <acronym>INDD</acronym>
+    <_comment>Adobe InDesign document</_comment>
+    <glob pattern="*.indd"/>
+  </mime-type>
+
+  <mime-type type="application/x-adobe-indesign-interchange">
+    <acronym>INX</acronym>
+    <_comment>Adobe InDesign Interchange format</_comment>
+    <magic priority="50">
+      <match value="&lt;?aid" type="string" offset="0:100"/>
+    </magic>
+    <glob pattern="*.inx"/>
+    <sub-class-of type="application/xml"/>
+  </mime-type>
+
+  <mime-type type="application/x-archive">
+    <magic priority="50">
+      <match value="=&lt;ar&gt;" type="string" offset="0"/>
+      <match value="=!&lt;arch&gt;" type="string" offset="0"/>
+    </magic>
+    <glob patter="*.ar"/>
+  </mime-type>
+
+  <mime-type type="application/x-authorware-bin">
+    <glob pattern="*.aab"/>
+    <glob pattern="*.x32"/>
+    <glob pattern="*.u32"/>
+    <glob pattern="*.vox"/>
+  </mime-type>
+  <mime-type type="application/x-authorware-map">
+    <glob pattern="*.aam"/>
+  </mime-type>
+  <mime-type type="application/x-authorware-seg">
+    <glob pattern="*.aas"/>
+  </mime-type>
+  <mime-type type="application/x-bcpio">
+    <glob pattern="*.bcpio"/>
+  </mime-type>
+
+  <mime-type type="application/x-berkeley-db">
+    <magic priority="50">
+      <match value="0x00061561" type="big32" offset="0"/>
+      <match value="0x00061561" type="host32" offset="12"/>
+      <match value="0x00061561" type="big32" offset="12"/>
+      <match value="0x00061561" type="little32" offset="12"/>
+      <match value="0x00053162" type="host32" offset="12"/>
+      <match value="0x00053162" type="big32" offset="12"/>
+      <match value="0x00053162" type="little32" offset="12"/>
+      <match value="0x00042253" type="host32" offset="12"/>
+      <match value="0x00042253" type="big32" offset="12"/>
+      <match value="0x00042253" type="little32" offset="12"/>
+      <match value="0x00040988" type="host32" offset="12"/>
+      <match value="0x00040988" type="little32" offset="12"/>
+      <match value="0x00040988" type="big32" offset="12"/>
+      <match value="0x00053162" type="host32" offset="0"/>
+      <match value="0x00053162" type="big32" offset="0"/>
+      <match value="0x00053162" type="little32" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-bibtex-text-file">
+    <magic priority="50">
+      <match value="%\ BibTeX\ `" type="string" offset="0"/>
+      <match value="%%%\ \ " type="string" offset="73"/>
+      <match value="%\ BibTeX\ standard\ bibliography\ " type="string" offset="0"/>
+      <match value="%%%\ \ @BibTeX-style-file{" type="string" offset="73"/>
+      <match value="@article{" type="string" offset="0"/>
+      <match value="@book{" type="string" offset="0"/>
+      <match value="@inbook{" type="string" offset="0"/>
+      <match value="@incollection{" type="string" offset="0"/>
+      <match value="@inproceedings{" type="string" offset="0"/>
+      <match value="@manual{" type="string" offset="0"/>
+      <match value="@misc{" type="string" offset="0"/>
+      <match value="@preamble{" type="string" offset="0"/>
+      <match value="@phdthesis{" type="string" offset="0"/>
+      <match value="@techreport{" type="string" offset="0"/>
+      <match value="@unpublished{" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.bib"/>
+    <glob pattern="*.bibtex"/>
+  </mime-type>
+
+  <mime-type type="application/x-bittorrent">
+    <magic priority="50">
+      <match value="d8:announce" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.torrent"/>
+  </mime-type>
+
+  <mime-type type="application/x-bzip">
+    <magic priority="40">
+      <match value="BZh" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.bz"/>
+    <glob pattern="*.tbz"/>
+  </mime-type>
+
+  <mime-type type="application/x-bzip2">
+    <glob pattern="*.bz2"/>
+    <glob pattern="*.tbz2"/>
+    <glob pattern="*.boz"/>
+    <sub-class-of type="application/x-bzip"/>
+  </mime-type>
+
+  <mime-type type="application/x-cdlink">
+    <_comment>Virtual CD-ROM CD Image File</_comment>
+    <glob pattern="*.vcd"/>
+  </mime-type>
+
+  <mime-type type="application/x-chat">
+    <glob pattern="*.chat"/>
+  </mime-type>
+  <mime-type type="application/x-chess-pgn">
+    <glob pattern="*.pgn"/>
+  </mime-type>
+
+  <mime-type type="application/x-compress">
+    <magic priority="50">
+      <match value="\037\235" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.z"/>
+  </mime-type>
+
+  <mime-type type="application/x-corelpresentations">
+    <glob pattern="*.shw"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+  
+  <mime-type type="application/x-cpio">
+    <magic priority="50">
+      <match value="070707" type="little16" offset="0"/>
+      <match value="070707" type="big16" offset="0"/>
+      <match value="070707" type="string" offset="0"/>
+      <match value="070701" type="string" offset="0"/>
+      <match value="070702" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.cpio"/>
+  </mime-type>
+
+  <mime-type type="application/x-csh">
+    <glob pattern="*.csh"/>
+  </mime-type>
+
+  <mime-type type="application/x-debian-package">
+    <glob pattern="*.deb"/>
+    <glob pattern="*.udeb"/>
+  </mime-type>
+
+  <mime-type type="application/x-director">
+    <_comment>Shockwave Movie</_comment>
+    <glob pattern="*.dir"/>
+    <glob pattern="*.dcr"/>
+    <glob pattern="*.dxr"/>
+    <glob pattern="*.cst"/>
+    <glob pattern="*.cct"/>
+    <glob pattern="*.cxt"/>
+    <glob pattern="*.w3d"/>
+    <glob pattern="*.fgd"/>
+    <glob pattern="*.swa"/>
+  </mime-type>
+
+  <mime-type type="application/x-doom">
+    <glob pattern="*.wad"/>
+  </mime-type>
+  <mime-type type="application/x-dtbncx+xml">
+    <glob pattern="*.ncx"/>
+  </mime-type>
+  <mime-type type="application/x-dtbook+xml">
+    <glob pattern="*.dtb"/>
+  </mime-type>
+  <mime-type type="application/x-dtbresource+xml">
+    <glob pattern="*.res"/>
+  </mime-type>
+
+  <mime-type type="application/x-dvi">
+    <magic priority="50">
+      <match value="\367\002" type="string" offset="0"/>
+      <match value="0x02f7" type="little16" offset="0"/>
+    </magic>
+    <glob pattern="*.dvi"/>
+  </mime-type>
+
+  <mime-type type="application/x-elc">
+    <_comment>Emacs Lisp bytecode</_comment>
+    <magic priority="50">
+      <!-- Emacs 18 -->
+      <match value="\012(" type="string" offset="0" />
+      <!-- Emacs 19 -->
+      <match value=";ELC\023\000\000\000" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.elc"/>
+  </mime-type>
+
+  <mime-type type="application/x-font-bdf">
+    <glob pattern="*.bdf"/>
+  </mime-type>
+  <mime-type type="application/x-font-dos"/>
+  <mime-type type="application/x-font-framemaker"/>
+  <mime-type type="application/x-font-ghostscript">
+    <glob pattern="*.gsf"/>
+  </mime-type>
+  <mime-type type="application/x-font-libgrx"/>
+  <mime-type type="application/x-font-linux-psf">
+    <glob pattern="*.psf"/>
+  </mime-type>
+
+  <mime-type type="application/x-font-otf">
+    <acronym>OTF</acronym>
+    <_comment>OpenType Font</_comment>
+    <glob pattern="*.otf"/>
+  </mime-type>
+
+  <mime-type type="application/x-font-pcf">
+    <glob pattern="*.pcf"/>
+  </mime-type>
+  <mime-type type="application/x-font-snf">
+    <glob pattern="*.snf"/>
+  </mime-type>
+  <mime-type type="application/x-font-speedo"/>
+  <mime-type type="application/x-font-sunos-news"/>
+
+  <mime-type type="application/x-font-ttf">
+    <acronym>TTF</acronym>
+    <_comment>TrueType Font</_comment>
+    <glob pattern="*.ttf"/>
+    <glob pattern="*.ttc"/>
+    <magic priority="40">
+      <match value="0x00010000" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-font-type1">
+    <glob pattern="*.pfa"/>
+    <glob pattern="*.pfb"/>
+    <glob pattern="*.pfm"/>
+    <glob pattern="*.afm"/>
+  </mime-type>
+  <mime-type type="application/x-font-vfont"/>
+
+  <mime-type type="application/x-futuresplash">
+    <_comment>Macromedia FutureSplash File</_comment>
+    <glob pattern="*.spl"/>
+  </mime-type>
+
+  <mime-type type="application/x-gnucash">
+    <glob pattern="*.gnucash" />
+  </mime-type>
+
+  <mime-type type="application/x-gnumeric">
+    <alias type="application/x-Gnumeric-spreadsheet"/>
+    <magic priority="50">
+      <match value="=&lt;gmr:Workbook" type="string" offset="39" />
+    </magic>
+    <glob pattern="*.gnumeric"/>
+  </mime-type>
+
+  <mime-type type="application/x-gtar">
+    <magic priority="40">
+      <!-- GNU tar archive -->
+      <match value="ustar  \0" type="string" offset="257" />
+    </magic>
+    <glob pattern="*.gtar"/>
+    <sub-class-of type="application/x-tar"/>
+  </mime-type>
+
+  <mime-type type="application/x-gzip">
+    <magic priority="40">
+      <match value="\037\213" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.tgz" />
+    <glob pattern="*.gz" />
+    <glob pattern="*-gz" />
+    <glob pattern="*.emz" />
+  </mime-type>
+
+  <mime-type type="application/x-hdf">
+    <magic priority="50">
+      <match value="0x0e031301" type="big32" offset="0"/>
+      <match value="\211HDF\r\n\032" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.hdf"/>
+    <glob pattern="*.he5"/>
+  </mime-type>
+
+  <mime-type type="application/x-hwp">
+    <magic priority="50">
+      <!--
+        TIKA-330: Detection pattern based on signature strings from
+        the hwpfilter/source/hwpfile.cpp file in OpenOffice.org.
+      -->
+      <match value="HWP Document File V" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-iso9660-image">
+    <magic priority="50">
+      <match value="CD001" type="string" offset="37633"/>
+    </magic>
+    <glob pattern="*.iso" />
+  </mime-type>
+
+  <mime-type type="application/x-java-jnlp-file">
+    <glob pattern="*.jnlp"/>
+  </mime-type>
+
+  <mime-type type="application/x-kdelnk">
+    <magic priority="50">
+      <match value="[KDE\ Desktop\ Entry]" type="string" offset="0"/>
+      <match value="#\ KDE\ Config\ File" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-latex">
+    <_comment>LaTeX Source Document</_comment>
+    <magic priority="50">
+      <match value="%\ -*-latex-*-" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.latex"/>
+  </mime-type>
+
+  <mime-type type="application/x-lha">
+    <magic priority="50">
+      <match value="-lzs-" type="string" offset="2"/>
+      <match value="-lh\40-" type="string" offset="2"/>
+      <match value="-lhd-" type="string" offset="2"/>
+      <match value="-lh2-" type="string" offset="2"/>
+      <match value="-lh3-" type="string" offset="2"/>
+      <match value="-lh4-" type="string" offset="2"/>
+      <match value="-lh5-" type="string" offset="2"/>
+      <match value="-lh6-" type="string" offset="2"/>
+      <match value="-lh7-" type="string" offset="2"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-lharc">
+    <magic priority="50">
+      <match value="-lh0-" type="string" offset="2"/>
+      <match value="-lh1-" type="string" offset="2"/>
+      <match value="-lz4-" type="string" offset="2"/>
+      <match value="-lz5-" type="string" offset="2"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-mobipocket-ebook">
+    <glob pattern="*.prc"/>
+    <glob pattern="*.mobi"/>
+  </mime-type>
+  <mime-type type="application/x-ms-application">
+    <glob pattern="*.application"/>
+  </mime-type>
+  <mime-type type="application/x-ms-wmd">
+    <glob pattern="*.wmd"/>
+  </mime-type>
+  <mime-type type="application/x-ms-wmz">
+    <sub-class-of type="application/x-gzip"/>
+    <glob pattern="*.wmz"/>
+  </mime-type>
+  <mime-type type="application/x-ms-xbap">
+    <glob pattern="*.xbap"/>
+  </mime-type>
+  <mime-type type="application/x-msaccess">
+    <glob pattern="*.mdb"/>
+  </mime-type>
+  <mime-type type="application/x-msbinder">
+    <glob pattern="*.obd"/>
+  </mime-type>
+  <mime-type type="application/x-mscardfile">
+    <glob pattern="*.crd"/>
+  </mime-type>
+  <mime-type type="application/x-msclip">
+    <glob pattern="*.clp"/>
+  </mime-type>
+  <mime-type type="application/x-msdownload">
+    <glob pattern="*.exe"/>
+    <glob pattern="*.dll"/>
+    <glob pattern="*.com"/>
+    <glob pattern="*.bat"/>
+    <glob pattern="*.msi"/>
+  </mime-type>
+  <mime-type type="application/x-msmediaview">
+    <glob pattern="*.mvb"/>
+    <glob pattern="*.m13"/>
+    <glob pattern="*.m14"/>
+  </mime-type>
+  <mime-type type="application/x-msmetafile">
+    <alias type="image/x-emf"/>
+    <alias type="image/x-wmf"/>
+    <acronym>WMF</acronym>
+    <_comment>Windows Metafile</_comment>
+    <glob pattern="*.wmf"/>
+    <glob pattern="*.emf"/>
+  </mime-type>
+  <mime-type type="application/x-msmoney">
+    <glob pattern="*.mny"/>
+  </mime-type>
+  <mime-type type="application/x-mspublisher">
+    <glob pattern="*.pub"/>
+  </mime-type>
+  <mime-type type="application/x-msschedule">
+    <glob pattern="*.scd"/>
+  </mime-type>
+  <mime-type type="application/x-msterminal">
+    <glob pattern="*.trm"/>
+  </mime-type>
+  <mime-type type="application/x-mswrite">
+    <glob pattern="*.wri"/>
+  </mime-type>
+  <mime-type type="application/x-netcdf">
+    <glob pattern="*.nc"/>
+    <glob pattern="*.cdf"/>
+  </mime-type>
+  <mime-type type="application/x-pkcs12">
+    <glob pattern="*.p12"/>
+    <glob pattern="*.pfx"/>
+  </mime-type>
+  <mime-type type="application/x-pkcs7-certificates">
+    <glob pattern="*.p7b"/>
+    <glob pattern="*.spc"/>
+  </mime-type>
+  <mime-type type="application/x-pkcs7-certreqresp">
+    <glob pattern="*.p7r"/>
+  </mime-type>
+
+  <mime-type type="application/x-quattro-pro">
+    <glob pattern="*.qpw"/>
+    <glob pattern="*.wb1"/>
+    <glob pattern="*.wb2"/>
+    <glob pattern="*.wb3"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+  
+  <mime-type type="application/x-rar-compressed">
+    <alias type="application/x-rar"/>
+    <magic priority="50">
+      <match value="Rar!" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.rar"/>
+  </mime-type>
+
+  <mime-type type="application/x-rpm">
+    <glob pattern="*.rpm"/>
+  </mime-type>
+
+  <mime-type type="application/x-sc">
+    <magic priority="50">
+      <match value="Spreadsheet" type="string" offset="38"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-sh">
+    <magic priority="50">
+      <match value="#!/" type="string" offset="0"/>
+      <match value="#!\ /" type="string" offset="0"/>
+      <match value="#!\t/" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.sh"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="application/x-shar">
+    <glob pattern="*.shar"/>
+  </mime-type>
+
+  <mime-type type="application/x-shockwave-flash">
+    <acronym>Flash</acronym>
+    <_comment>Adobe Flash</_comment>
+    <magic priority="50">
+      <match value="FWS" type="string" offset="0"/> <!-- F = Uncompressed -->
+      <match value="CWS" type="string" offset="0"/> <!-- C = Compressed   -->
+    </magic>
+    <glob pattern="*.swf"/>
+  </mime-type>
+
+  <mime-type type="application/x-silverlight-app">
+    <glob pattern="*.xap"/>
+  </mime-type>
+
+  <mime-type type="application/x-stuffit">
+    <magic priority="50">
+      <match value="StuffIt" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.sit"/>
+  </mime-type>
+
+  <mime-type type="application/x-stuffitx">
+    <glob pattern="*.sitx"/>
+  </mime-type>
+  <mime-type type="application/x-sv4cpio">
+    <glob pattern="*.sv4cpio"/>
+  </mime-type>
+  <mime-type type="application/x-sv4crc">
+    <glob pattern="*.sv4crc"/>
+  </mime-type>
+
+  <mime-type type="application/x-tar">
+    <magic priority="40">
+      <!-- POSIX tar archive -->
+      <match value="ustar\0" type="string" offset="257" />
+    </magic>
+    <glob pattern="*.tar"/>
+  </mime-type>
+
+  <mime-type type="application/x-tcl">
+    <alias type="text/x-tcl"/>
+    <glob pattern="*.tcl"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="application/x-tex">
+    <alias type="text/x-tex"/>
+    <magic priority="50">
+      <match value="\\input" type="string" offset="0"/>
+      <match value="\\section" type="string" offset="0"/>
+      <match value="\\setlength" type="string" offset="0"/>
+      <match value="\\documentstyle" type="string" offset="0"/>
+      <match value="\\chapter" type="string" offset="0"/>
+      <match value="\\documentclass" type="string" offset="0"/>
+      <match value="\\relax" type="string" offset="0"/>
+      <match value="\\contentsline" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.tex"/>
+  </mime-type>
+
+  <mime-type type="application/x-tex-tfm">
+    <glob pattern="*.tfm"/>
+  </mime-type>
+
+  <mime-type type="application/x-texinfo">
+    <alias type="text/x-texinfo" />
+    <magic priority="50">
+      <match value="\\input\ texinfo" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.texinfo"/>
+    <glob pattern="*.texi"/>
+  </mime-type>
+
+  <!-- =================================================================== -->
+  <!-- Microsoft Office binary file formats                                -->
+  <!-- http://www.microsoft.com/interop/docs/OfficeBinaryFormats.mspx      -->
+  <!-- =================================================================== -->
+  <mime-type type="application/x-tika-msoffice">
+    <magic>
+      <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8"/>
+    </magic>
+  </mime-type>
+
+  <!-- =================================================================== -->
+  <!-- Office Open XML file formats                                        -->
+  <!-- http://www.ecma-international.org/publications/standards/Ecma-376.htm -->
+  <!-- =================================================================== -->
+  <mime-type type="application/x-tika-ooxml">
+    <sub-class-of type="application/zip"/>
+    <magic priority="50">
+      <match value="PK\003\004" type="string" offset="0">
+        <match value="[Content_Types].xml" type="string" offset="30"/>
+      </match>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-ustar">
+    <glob pattern="*.ustar"/>
+  </mime-type>
+  <mime-type type="application/x-wais-source">
+    <glob pattern="*.src"/>
+  </mime-type>
+  <mime-type type="application/x-x509-ca-cert">
+    <glob pattern="*.der"/>
+    <glob pattern="*.crt"/>
+  </mime-type>
+  <mime-type type="application/x-xfig">
+    <glob pattern="*.fig"/>
+  </mime-type>
+  <mime-type type="application/x-xpinstall">
+    <glob pattern="*.xpi"/>
+  </mime-type>
+
+  <mime-type type="application/x-zoo">
+    <magic priority="50">
+      <match value="0xfdc4a7dc" type="little32" offset="20"/>
+    </magic>
+    <glob pattern="*.zoo"/>
+  </mime-type>
+
+  <mime-type type="application/x400-bp"/>
+  <mime-type type="application/xcap-att+xml"/>
+  <mime-type type="application/xcap-caps+xml"/>
+  <mime-type type="application/xcap-el+xml"/>
+  <mime-type type="application/xcap-error+xml"/>
+  <mime-type type="application/xcap-ns+xml"/>
+  <mime-type type="application/xcon-conference-info-diff+xml"/>
+  <mime-type type="application/xcon-conference-info+xml"/>
+  <mime-type type="application/xenc+xml">
+    <glob pattern="*.xenc"/>
+  </mime-type>
+
+  <mime-type type="application/xhtml+xml">
+    <magic priority="50">
+      <match value="&lt;html xmlns=" type="string" offset="0:8192"/>
+    </magic>
+    <root-XML namespaceURI="http://www.w3.org/1999/xhtml" localName="html"/>
+    <glob pattern="*.xhtml"/>
+    <glob pattern="*.xht"/>
+  </mime-type>
+
+  <mime-type type="application/xhtml-voice+xml"/>
+
+  <mime-type type="application/xml">
+    <alias type="text/xml"/>
+    <magic priority="50">
+      <match value="&lt;?xml" type="string" offset="0"/>
+      <match value="&lt;?XML" type="string" offset="0"/>
+      <match value="&lt;!--" type="string" offset="0"/>
+      <match value="0xFFFE3C003F0078006D006C00" type="string" offset="0"/>
+      <match value="0xFEFF003C003F0078006D006C" type="string" offset="0"/>
+      <!-- TODO: Add matches for the other possible XML encoding schemes -->
+    </magic>
+    <glob pattern="*.xml"/>
+    <glob pattern="*.xsl"/>
+    <glob pattern="*.xsd"/>
+    <sub-class-of type="text/plain" />
+  </mime-type>
+
+  <mime-type type="application/xml-dtd">
+    <sub-class-of type="text/plain"/>
+    <glob pattern="*.dtd"/>
+  </mime-type>
+  <mime-type type="application/xml-external-parsed-entity"/>
+  <mime-type type="application/xmpp+xml"/>
+  <mime-type type="application/xop+xml">
+    <glob pattern="*.xop"/>
+  </mime-type>
+
+  <mime-type type="application/xslt+xml">
+    <alias type="text/xsl"/>
+    <acronym>XSLT</acronym>
+    <_comment>XSL Transformations</_comment>
+    <root-XML localName="stylesheet"
+              namespaceURI="http://www.w3.org/1999/XSL/Transform"/>
+    <glob pattern="*.xslt"/>
+  </mime-type>
+
+  <mime-type type="application/xspf+xml">
+    <glob pattern="*.xspf"/>
+  </mime-type>
+  <mime-type type="application/xv+xml">
+    <glob pattern="*.mxml"/>
+    <glob pattern="*.xhvml"/>
+    <glob pattern="*.xvml"/>
+    <glob pattern="*.xvm"/>
+  </mime-type>
+
+  <mime-type type="application/zip">
+    <alias type="application/x-zip-compressed"/>
+    <magic priority="40">
+      <match value="PK\003\004" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.zip"/>
+  </mime-type>
+
+  <mime-type type="audio/32kadpcm"/>
+  <mime-type type="audio/3gpp"/>
+  <mime-type type="audio/3gpp2"/>
+  <mime-type type="audio/ac3"/>
+  <mime-type type="audio/adpcm">
+    <glob pattern="*.adp"/>
+  </mime-type>
+  <mime-type type="audio/amr"/>
+  <mime-type type="audio/amr-wb"/>
+  <mime-type type="audio/amr-wb+"/>
+  <mime-type type="audio/asc"/>
+
+  <mime-type type="audio/basic">
+    <magic priority="20">
+      <match value=".snd" type="string" offset="0">
+        <match value="1" type="big32" offset="12"/>
+        <match value="2" type="big32" offset="12"/>
+        <match value="3" type="big32" offset="12"/>
+        <match value="4" type="big32" offset="12"/>
+        <match value="5" type="big32" offset="12"/>
+        <match value="6" type="big32" offset="12"/>
+        <match value="7" type="big32" offset="12"/>
+      </match>
+    </magic>
+    <glob pattern="*.au"/>
+    <glob pattern="*.snd"/>
+  </mime-type>
+
+  <mime-type type="audio/bv16"/>
+  <mime-type type="audio/bv32"/>
+  <mime-type type="audio/clearmode"/>
+  <mime-type type="audio/cn"/>
+  <mime-type type="audio/dat12"/>
+  <mime-type type="audio/dls"/>
+  <mime-type type="audio/dsr-es201108"/>
+  <mime-type type="audio/dsr-es202050"/>
+  <mime-type type="audio/dsr-es202211"/>
+  <mime-type type="audio/dsr-es202212"/>
+  <mime-type type="audio/dvi4"/>
+  <mime-type type="audio/eac3"/>
+  <mime-type type="audio/evrc"/>
+  <mime-type type="audio/evrc-qcp"/>
+  <mime-type type="audio/evrc0"/>
+  <mime-type type="audio/evrc1"/>
+  <mime-type type="audio/evrcb"/>
+  <mime-type type="audio/evrcb0"/>
+  <mime-type type="audio/evrcb1"/>
+  <mime-type type="audio/evrcwb"/>
+  <mime-type type="audio/evrcwb0"/>
+  <mime-type type="audio/evrcwb1"/>
+  <mime-type type="audio/example"/>
+  <mime-type type="audio/g719"/>
+  <mime-type type="audio/g722"/>
+  <mime-type type="audio/g7221"/>
+  <mime-type type="audio/g723"/>
+  <mime-type type="audio/g726-16"/>
+  <mime-type type="audio/g726-24"/>
+  <mime-type type="audio/g726-32"/>
+  <mime-type type="audio/g726-40"/>
+  <mime-type type="audio/g728"/>
+  <mime-type type="audio/g729"/>
+  <mime-type type="audio/g7291"/>
+  <mime-type type="audio/g729d"/>
+  <mime-type type="audio/g729e"/>
+  <mime-type type="audio/gsm"/>
+  <mime-type type="audio/gsm-efr"/>
+  <mime-type type="audio/ilbc"/>
+  <mime-type type="audio/l16"/>
+  <mime-type type="audio/l20"/>
+  <mime-type type="audio/l24"/>
+  <mime-type type="audio/l8"/>
+  <mime-type type="audio/lpc"/>
+
+  <mime-type type="audio/midi">
+    <acronym>MIDI</acronym>
+    <_comment>Musical Instrument Digital Interface</_comment>
+    <magic priority ="20">
+      <match type="string" value="MThd" offset="0"/>
+    </magic>
+    <glob pattern="*.mid"/>
+    <glob pattern="*.midi"/>
+    <glob pattern="*.kar"/>
+    <glob pattern="*.rmi"/>
+  </mime-type>
+
+  <mime-type type="audio/mobile-xmf"/>
+  <mime-type type="audio/mp4">
+    <alias type="audio/x-mp4a"/>
+    <glob pattern="*.mp4a"/>
+  </mime-type>
+  <mime-type type="audio/mp4a-latm"/>
+  <mime-type type="audio/mpa"/>
+  <mime-type type="audio/mpa-robust"/>
+
+  <mime-type type="audio/mpeg">
+    <acronym>MP3</acronym>
+    <_comment>MPEG-1 Audio Layer 3</_comment>
+    <magic priority="20">
+      <!-- http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html -->
+      <!-- Bit pattern for first two bytes: 11111111 111VVLLC    -->
+      <!-- VV = MPEG Audio Version ID; 10 = V2, 11 = V1          -->
+      <!-- LL = Layer description; 01 = L3, 10 = L2, 11 = L1     -->
+      <!-- C = Protection bit; 0 = CRC, 1 = no CRC               -->
+      <match value="0xfff2" type="string" offset="0"/> <!-- V2, L3, CRC -->
+      <match value="0xfff3" type="string" offset="0"/> <!-- V2, L3      -->
+      <match value="0xfff4" type="string" offset="0"/> <!-- V2, L2, CRC -->
+      <match value="0xfff5" type="string" offset="0"/> <!-- V2, L2      -->
+      <match value="0xfff6" type="string" offset="0"/> <!-- V2, L1, CRC -->
+      <match value="0xfff7" type="string" offset="0"/> <!-- V2, L1      -->
+      <match value="0xfffa" type="string" offset="0"/> <!-- V1, L3, CRC -->
+      <match value="0xfffb" type="string" offset="0"/> <!-- V1, L3      -->
+      <match value="0xfffc" type="string" offset="0"/> <!-- V1, L2, CRC -->
+      <match value="0xfffd" type="string" offset="0"/> <!-- V1, L2      -->
+      <!-- TIKA-417: This is the UTF-16 LE byte order mark! -->
+      <!-- match value="0xfffe" type="string" offset="0"/ --> <!-- V1, L1, CRC -->
+      <match value="0xffff" type="string" offset="0"/> <!-- V1, L1      -->
+      <match value="ID3" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.mpga"/>
+    <glob pattern="*.mp2"/>
+    <glob pattern="*.mp2a"/>
+    <glob pattern="*.mp3"/>
+    <glob pattern="*.m2a"/>
+    <glob pattern="*.m3a"/>
+  </mime-type>
+
+  <mime-type type="audio/mpeg4-generic"/>
+
+  <mime-type type="audio/ogg">
+    <glob pattern="*.oga"/>
+    <glob pattern="*.ogg"/>
+    <glob pattern="*.spx"/>
+    <sub-class-of type="application/ogg"/>
+  </mime-type>
+
+  <mime-type type="audio/parityfec"/>
+  <mime-type type="audio/pcma"/>
+  <mime-type type="audio/pcma-wb"/>
+  <mime-type type="audio/pcmu-wb"/>
+  <mime-type type="audio/pcmu"/>
+
+  <mime-type type="audio/prs.sid">
+    <magic priority="50">
+      <match value="PSID" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="audio/qcelp"/>
+  <mime-type type="audio/red"/>
+  <mime-type type="audio/rtp-enc-aescm128"/>
+  <mime-type type="audio/rtp-midi"/>
+  <mime-type type="audio/rtx"/>
+  <mime-type type="audio/smv"/>
+  <mime-type type="audio/smv0"/>
+  <mime-type type="audio/smv-qcp"/>
+  <mime-type type="audio/sp-midi"/>
+  <mime-type type="audio/t140c"/>
+  <mime-type type="audio/t38"/>
+  <mime-type type="audio/telephone-event"/>
+  <mime-type type="audio/tone"/>
+  <mime-type type="audio/ulpfec"/>
+  <mime-type type="audio/vdvi"/>
+  <mime-type type="audio/vmr-wb"/>
+  <mime-type type="audio/vnd.3gpp.iufp"/>
+  <mime-type type="audio/vnd.4sb"/>
+  <mime-type type="audio/vnd.audiokoz"/>
+  <mime-type type="audio/vnd.celp"/>
+  <mime-type type="audio/vnd.cisco.nse"/>
+  <mime-type type="audio/vnd.cmles.radio-events"/>
+  <mime-type type="audio/vnd.cns.anp1"/>
+  <mime-type type="audio/vnd.cns.inf1"/>
+  <mime-type type="audio/vnd.digital-winds">
+    <glob pattern="*.eol"/>
+  </mime-type>
+  <mime-type type="audio/vnd.dlna.adts"/>
+  <mime-type type="audio/vnd.dolby.heaac.1"/>
+  <mime-type type="audio/vnd.dolby.heaac.2"/>
+  <mime-type type="audio/vnd.dolby.mlp"/>
+  <mime-type type="audio/vnd.dolby.mps"/>
+  <mime-type type="audio/vnd.dolby.pl2"/>
+  <mime-type type="audio/vnd.dolby.pl2x"/>
+  <mime-type type="audio/vnd.dolby.pl2z"/>
+  <mime-type type="audio/vnd.dts">
+    <glob pattern="*.dts"/>
+  </mime-type>
+  <mime-type type="audio/vnd.dts.hd">
+    <glob pattern="*.dtshd"/>
+  </mime-type>
+  <mime-type type="audio/vnd.everad.plj"/>
+  <mime-type type="audio/vnd.hns.audio"/>
+  <mime-type type="audio/vnd.lucent.voice">
+    <glob pattern="*.lvp"/>
+  </mime-type>
+  <mime-type type="audio/vnd.ms-playready.media.pya">
+    <glob pattern="*.pya"/>
+  </mime-type>
+  <mime-type type="audio/vnd.nokia.mobile-xmf"/>
+  <mime-type type="audio/vnd.nortel.vbk"/>
+  <mime-type type="audio/vnd.nuera.ecelp4800">
+    <glob pattern="*.ecelp4800"/>
+  </mime-type>
+  <mime-type type="audio/vnd.nuera.ecelp7470">
+    <glob pattern="*.ecelp7470"/>
+  </mime-type>
+  <mime-type type="audio/vnd.nuera.ecelp9600">
+    <glob pattern="*.ecelp9600"/>
+  </mime-type>
+  <mime-type type="audio/vnd.octel.sbc"/>
+  <mime-type type="audio/vnd.qcelp"/>
+  <mime-type type="audio/vnd.rhetorex.32kadpcm"/>
+  <mime-type type="audio/vnd.sealedmedia.softseal.mpeg"/>
+  <mime-type type="audio/vnd.vmx.cvsd"/>
+  <mime-type type="audio/vorbis"/>
+  <mime-type type="audio/vorbis-config"/>
+  <mime-type type="audio/x-aac">
+    <glob pattern="*.aac"/>
+  </mime-type>
+
+  <mime-type type="audio/x-adbcm">
+    <magic priority="20">
+      <match value=".snd" type="string" offset="0">
+        <match value="23" type="big32" offset="12"/>
+      </match>
+    </magic>
+  </mime-type>
+
+  <mime-type type="audio/x-aiff">
+    <alias type="audio/aiff"/>
+    <acronym>AIFF</acronym>
+    <_comment>Audio Interchange File Format</_comment>
+    <magic priority="20">
+      <match value="FORM....AIFF" type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+      <match value="FORM....AIFC" type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+      <!-- Amiga IFF sound sample, somewhat like the more modern AIFF -->
+      <match value="FORM....8SVX" type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+    </magic>
+    <glob pattern="*.aif"/>
+    <glob pattern="*.aiff"/>
+    <glob pattern="*.aifc"/>
+  </mime-type>
+
+  <mime-type type="audio/x-dec-basic">
+    <magic priority="20">
+      <match value="0x0064732E" type="big32" offset="0">
+        <match value="1" type="big32" offset="12"/>
+        <match value="2" type="big32" offset="12"/>
+        <match value="3" type="big32" offset="12"/>
+        <match value="4" type="big32" offset="12"/>
+        <match value="5" type="big32" offset="12"/>
+        <match value="6" type="big32" offset="12"/>
+        <match value="7" type="big32" offset="12"/>
+      </match>
+    </magic>
+  </mime-type>
+
+  <mime-type type="audio/x-dec-adbcm">
+    <magic priority="20">
+      <match value="0x0064732E" type="big32" offset="0">
+        <match value="23" type="big32" offset="12"/>
+      </match>
+    </magic>
+  </mime-type>
+
+  <mime-type type="audio/x-flac">
+    <acronym>FLAC</acronym>
+    <_comment>Free Lossless Audio Codec</_comment>
+    <magic priority="50">
+      <match value="fLaC" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.flac"/>
+  </mime-type>
+
+  <mime-type type="audio/x-mod">
+    <acronym>MOD</acronym>
+    <magic priority="50">
+      <match value="Extended\ Module:" type="string" offset="0"/>
+      <match value="BMOD2STM" type="string" offset="21"/>
+      <match value="M.K." type="string" offset="1080"/>
+      <match value="M!K!" type="string" offset="1080"/>
+      <match value="FLT4" type="string" offset="1080"/>
+      <match value="FLT8" type="string" offset="1080"/>
+      <match value="4CHN" type="string" offset="1080"/>
+      <match value="6CHN" type="string" offset="1080"/>
+      <match value="8CHN" type="string" offset="1080"/>
+      <match value="CD81" type="string" offset="1080"/>
+      <match value="OKTA" type="string" offset="1080"/>
+      <match value="16CN" type="string" offset="1080"/>
+      <match value="32CN" type="string" offset="1080"/>
+      <match value="IMPM" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.mod"/>
+  </mime-type>
+
+  <mime-type type="audio/x-mpegurl">
+    <glob pattern="*.m3u"/>
+  </mime-type>
+  <mime-type type="audio/x-ms-wax">
+    <glob pattern="*.wax"/>
+  </mime-type>
+  <mime-type type="audio/x-ms-wma">
+    <glob pattern="*.wma"/>
+  </mime-type>
+
+  <mime-type type="audio/x-pn-realaudio">
+    <_comment>Real Audio</_comment>
+    <alias type="audio/x-realaudio" />
+    <magic priority="50">
+      <match value="0x2e7261fd" type="big32" offset="0"/>
+    </magic>
+    <glob pattern="*.ram"/>
+    <glob pattern="*.ra"/>
+  </mime-type>
+
+  <mime-type type="audio/x-pn-realaudio-plugin">
+    <glob pattern="*.rmp"/>
+  </mime-type>
+
+  <mime-type type="audio/x-wav">
+    <acronym>WAV</acronym>
+    <magic priority="20">
+      <match value="RIFF....WAVE" type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+    </magic>
+    <glob pattern="*.wav"/>
+  </mime-type>
+
+  <mime-type type="chemical/x-cdx">
+    <glob pattern="*.cdx"/>
+  </mime-type>
+  <mime-type type="chemical/x-cif">
+    <glob pattern="*.cif"/>
+  </mime-type>
+  <mime-type type="chemical/x-cmdf">
+    <glob pattern="*.cmdf"/>
+  </mime-type>
+  <mime-type type="chemical/x-cml">
+    <glob pattern="*.cml"/>
+  </mime-type>
+  <mime-type type="chemical/x-csml">
+    <glob pattern="*.csml"/>
+  </mime-type>
+  <mime-type type="chemical/x-pdb"/>
+  <mime-type type="chemical/x-xyz">
+    <glob pattern="*.xyz"/>
+  </mime-type>
+
+  <mime-type type="image/bmp">
+    <alias type="image/x-ms-bmp"/>
+    <acronym>BMP</acronym>
+    <_comment>Windows bitmap</_comment>
+    <magic priority="50">
+      <match value="BM" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.bmp"/>
+    <glob pattern="*.dib"/>
+  </mime-type>
+
+  <mime-type type="image/cgm">
+    <acronym>CGM</acronym>
+    <_comment>Computer Graphics Metafile</_comment>
+    <magic priority="50">
+      <match value="BEGMF" type="string" offset="0"/>
+      <match value="0x0020" mask="0xffe0" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.cgm"/>
+  </mime-type>
+
+  <mime-type type="image/example"/>
+  <mime-type type="image/fits"/>
+  <mime-type type="image/g3fax">
+    <glob pattern="*.g3"/>
+  </mime-type>
+
+  <mime-type type="image/gif">
+    <acronym>GIF</acronym>
+    <_comment>Graphics Interchange Format</_comment>
+    <magic priority="50">
+      <match value="GIF87a" type="string" offset="0"/>
+      <match value="GIF89a" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.gif"/>
+  </mime-type>
+
+  <mime-type type="image/ief">
+    <glob pattern="*.ief"/>
+  </mime-type>
+  <mime-type type="image/jp2"/>
+
+  <mime-type type="image/jpeg">
+    <acronym>JPEG</acronym>
+    <_comment>Joint Photographic Experts Group</_comment>
+    <magic priority="50">
+      <!-- FFD8 is the SOI (Start Of Image) marker.              -->
+      <!-- It is followed by another marker that starts with FF. -->
+      <match value="0xffd8ff" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.jpg"/>
+    <glob pattern="*.jpeg"/>
+    <glob pattern="*.jpe"/>
+    <glob pattern="*.jif"/>
+    <glob pattern="*.jfif"/>
+    <glob pattern="*.jfi"/>
+  </mime-type>
+
+  <mime-type type="image/jpm"/>
+  <mime-type type="image/jpx"/>
+  <mime-type type="image/naplps"/>
+
+  <mime-type type="image/png">
+    <acronym>PNG</acronym>
+    <_comment>Portable Network Graphics</_comment>
+    <magic priority="50">
+      <match value="\x89PNG\x0d\x0a\x1a\x0a" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.png"/>
+  </mime-type>
+
+  <mime-type type="image/prs.btif">
+    <glob pattern="*.btif"/>
+  </mime-type>
+  <mime-type type="image/prs.pti"/>
+
+  <mime-type type="image/svg+xml">
+    <sub-class-of type="application/xml"/>
+    <acronym>SVG</acronym>
+    <_comment>Scalable Vector Graphics</_comment>
+    <root-XML localName="svg" namespaceURI="http://www.w3.org/2000/svg"/>
+    <glob pattern="*.svg"/>
+    <glob pattern="*.svgz"/>
+  </mime-type>
+
+  <mime-type type="image/t38"/>
+
+  <mime-type type="image/tiff">
+    <acronym>TIFF</acronym>
+    <_comment>Tagged Image File Format</_comment>
+    <magic priority="50">
+      <!-- MM.* = Big endian (M=Motorola) and 0x002a in big endian    -->
+      <match value="MM\x00\x2a" type="string" offset="0"/>
+      <!-- II*. = Little endian (I=Intel) and 0x002a in little endian -->
+      <match value="II\x2a\x00" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.tiff"/>
+    <glob pattern="*.tif"/>
+  </mime-type>
+
+  <mime-type type="image/tiff-fx"/>
+
+  <mime-type type="image/vnd.adobe.photoshop">
+    <alias type="image/x-psd"/>
+    <glob pattern="*.psd"/>
+  </mime-type>
+
+  <mime-type type="image/vnd.cns.inf2"/>
+  <mime-type type="image/vnd.djvu">
+    <glob pattern="*.djvu"/>
+    <glob pattern="*.djv"/>
+  </mime-type>
+
+  <mime-type type="image/vnd.dwg">
+    <acronym>DWG</acronym>
+    <_comment>AutoCad Drawing</_comment>
+    <alias type="image/x-dwg"/>
+    <alias type="application/acad"/>
+    <alias type="application/x-acad"/>
+    <alias type="application/autocad_dwg"/>
+    <alias type="application/dwg"/>
+    <alias type="application/x-dwg"/>
+    <alias type="application/x-autocad"/>
+    <glob pattern="*.dwg"/>
+    <magic priority="50">
+      <!-- "AC" followed by four numbers -->
+      <match value="AC0000" type="string" offset="0"
+             mask="0xFFFFF0F0F0F0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="image/vnd.dxf">
+    <glob pattern="*.dxf"/>
+  </mime-type>
+  <mime-type type="image/vnd.fastbidsheet">
+    <glob pattern="*.fbs"/>
+  </mime-type>
+  <mime-type type="image/vnd.fpx">
+    <glob pattern="*.fpx"/>
+  </mime-type>
+  <mime-type type="image/vnd.fst">
+    <glob pattern="*.fst"/>
+  </mime-type>
+  <mime-type type="image/vnd.fujixerox.edmics-mmr">
+    <glob pattern="*.mmr"/>
+  </mime-type>
+  <mime-type type="image/vnd.fujixerox.edmics-rlc">
+    <glob pattern="*.rlc"/>
+  </mime-type>
+  <mime-type type="image/vnd.globalgraphics.pgb"/>
+  <mime-type type="image/vnd.microsoft.icon"/>
+  <mime-type type="image/vnd.mix"/>
+  <mime-type type="image/vnd.ms-modi">
+    <glob pattern="*.mdi"/>
+  </mime-type>
+  <mime-type type="image/vnd.net-fpx">
+    <glob pattern="*.npx"/>
+  </mime-type>
+  <mime-type type="image/vnd.radiance"/>
+  <mime-type type="image/vnd.sealed.png"/>
+  <mime-type type="image/vnd.sealedmedia.softseal.gif"/>
+  <mime-type type="image/vnd.sealedmedia.softseal.jpg"/>
+  <mime-type type="image/vnd.svf"/>
+
+  <mime-type type="image/vnd.wap.wbmp">
+    <_comment>Wireless Bitmap File Format</_comment>
+    <glob pattern="*.wbmp"/>
+  </mime-type>
+
+  <mime-type type="image/vnd.xiff">
+    <glob pattern="*.xif"/>
+  </mime-type>
+  <mime-type type="image/x-cmu-raster">
+    <glob pattern="*.ras"/>
+  </mime-type>
+  <mime-type type="image/x-cmx">
+    <glob pattern="*.cmx"/>
+  </mime-type>
+  <mime-type type="image/x-freehand">
+    <glob pattern="*.fh"/>
+    <glob pattern="*.fhc"/>
+    <glob pattern="*.fh4"/>
+    <glob pattern="*.fh5"/>
+    <glob pattern="*.fh7"/>
+  </mime-type>
+
+  <mime-type type="image/x-icon">
+    <magic priority="50">
+      <match value="\102\101\050\000\000\000\056\000\000\000\000\000\000\000"
+             type="string" offset="0"/>
+      <match value="\000\000\001\000" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.ico"/>
+  </mime-type>
+
+  <mime-type type="image/x-niff">
+    <_comment>Navy Interchange File Format</_comment>
+    <magic priority="50">
+      <match value="IIN1" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="image/x-pcx">
+    <glob pattern="*.pcx"/>
+  </mime-type>
+  <mime-type type="image/x-pict">
+    <glob pattern="*.pic"/>
+    <glob pattern="*.pct"/>
+  </mime-type>
+
+  <mime-type type="image/x-portable-anymap">
+    <acronym>PNM</acronym>
+    <_comment>Portable Any Map</_comment>
+    <glob pattern="*.pnm" />
+  </mime-type>
+
+  <mime-type type="image/x-portable-bitmap">
+    <sub-class-of type="image/x-portable-anymap"/>
+    <acronym>PBM</acronym>
+    <_comment>Portable Bit Map</_comment>
+    <magic priority="50">
+      <match value="P1" type="string" offset="0"/>
+      <match value="P4" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.pbm"/>
+  </mime-type>
+
+  <mime-type type="image/x-portable-graymap">
+    <sub-class-of type="image/x-portable-anymap"/>
+    <acronym>PGM</acronym>
+    <_comment>Portable Gray Map</_comment>
+    <magic priority="50">
+      <match value="P2" type="string" offset="0"/>
+      <match value="P5" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.pgm"/>
+  </mime-type>
+
+  <mime-type type="image/x-portable-pixmap">
+    <sub-class-of type="image/x-portable-anymap"/>
+    <acronym>PXM</acronym>
+    <_comment>Portable Pixel Map</_comment>
+    <magic priority="50">
+      <match value="P3" type="string" offset="0"/>
+      <match value="P6" type="string" offset="0"/>
+      <match value="P7" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.ppm"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-adobe">
+    <acronym>DNG</acronym>
+    <_comment>Adobe Digital Negative</_comment>
+    <glob pattern="*.dng"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-hasselblad">
+    <_comment>Hasselblad raw image</_comment>
+    <glob pattern="*.3fr"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-fuji">
+    <_comment>Fuji raw image</_comment>
+    <glob pattern="*.raf"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-canon">
+    <_comment>Canon raw image</_comment>
+    <glob pattern="*.crw"/>
+    <glob pattern="*.cr2"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-kodak">
+    <_comment>Kodak raw image</_comment>
+    <glob pattern="*.k25"/>
+    <glob pattern="*.kdc"/>
+    <glob pattern="*.dcs"/>
+    <glob pattern="*.drf"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-minolta">
+    <_comment>Minolta raw image</_comment>
+    <glob pattern="*.mrw"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-nikon">
+    <_comment>Nikon raw image</_comment>
+    <glob pattern="*.nef"/>
+    <glob pattern="*.nrw"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-olympus">
+    <_comment>Olympus raw image</_comment>
+    <glob pattern="*.orf"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-pentax">
+    <_comment>Pentax raw image</_comment>
+    <glob pattern="*.ptx"/>
+    <glob pattern="*.pef"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-sony">
+    <_comment>Sony raw image</_comment>
+    <glob pattern="*.arw"/>
+    <glob pattern="*.srf"/>
+    <glob pattern="*.sr2"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-sigma">
+    <_comment>Sigma raw image</_comment>
+    <glob pattern="*.x3f"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-epson">
+    <_comment>Epson raw image</_comment>
+    <glob pattern="*.erf"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-mamiya">
+    <_comment>Mamiya raw image</_comment>
+    <glob pattern="*.mef"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-leaf">
+    <_comment>Leaf raw image</_comment>
+    <glob pattern="*.mos"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-panasonic">
+    <_comment>Panasonic raw image</_comment>
+    <glob pattern="*.raw"/>
+    <glob pattern="*.rw2"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-phaseone">
+    <_comment>Phase One raw image</_comment>
+    <glob pattern="*.cap"/>
+    <glob pattern="*.iiq"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-red">
+    <_comment>Red raw image</_comment>
+    <glob pattern="*.r3d"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-imacon">
+    <_comment>Imacon raw image</_comment>
+    <glob pattern="*.fff"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-logitech">
+    <_comment>Logitech raw image</_comment>
+    <glob pattern="*.pxn"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-casio">
+    <_comment>Casio raw image</_comment>
+    <glob pattern="*.bay"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-rawzor">
+    <_comment>Rawzor raw image</_comment>
+    <glob pattern="*.rwz"/>
+  </mime-type>
+
+  <mime-type type="image/x-rgb">
+    <glob pattern="*.rgb"/>
+  </mime-type>
+
+  <mime-type type="image/x-xbitmap">
+    <magic priority="50">
+      <match value="/* XPM" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.xbm"/>
+    <sub-class-of type="text/x-c"/>
+  </mime-type>
+
+  <mime-type type="image/x-xcf">
+    <alias type="image/xcf"/>
+    <magic priority="50">
+      <match type="string" value="gimp xcf " offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="image/x-xpixmap">
+    <glob pattern="*.xpm"/>
+  </mime-type>
+  <mime-type type="image/x-xwindowdump">
+    <glob pattern="*.xwd"/>
+  </mime-type>
+
+  <mime-type type="message/cpim"/>
+  <mime-type type="message/delivery-status"/>
+  <mime-type type="message/disposition-notification"/>
+  <mime-type type="message/example"/>
+  <mime-type type="message/external-body"/>
+  <mime-type type="message/global"/>
+  <mime-type type="message/global-delivery-status"/>
+  <mime-type type="message/global-disposition-notification"/>
+  <mime-type type="message/global-headers"/>
+  <mime-type type="message/http"/>
+  <mime-type type="message/imdn+xml"/>
+
+  <mime-type type="message/news">
+    <magic priority="50">
+      <match value="Path:" type="string" offset="0" />
+      <match value="Xref:" type="string" offset="0" />
+      <match value="Article" type="string" offset="0" />
+    </magic>
+  </mime-type>
+
+  <mime-type type="message/partial"/>
+
+  <mime-type type="message/rfc822">
+    <magic priority="50">
+      <match value="Relay-Version:" type="string" offset="0"/>
+      <match value="#!\ rnews" type="string" offset="0"/>
+      <match value="N#!\ rnews" type="string" offset="0"/>
+      <match value="Forward\ to" type="string" offset="0"/>
+      <match value="Pipe\ to" type="string" offset="0"/>
+      <match value="Return-Path:" type="string" offset="0"/>
+      <match value="From:" type="string" offset="0"/>
+      <match value="Received:" type="string" offset="0"/>
+      <match type="string" value="Message-ID:" offset="0"/>
+      <match type="string" value="Date:" offset="0"/>
+    </magic>
+    <glob pattern="*.eml"/>
+    <glob pattern="*.mime"/>
+  </mime-type>
+
+  <mime-type type="message/s-http"/>
+  <mime-type type="message/sip"/>
+  <mime-type type="message/sipfrag"/>
+  <mime-type type="message/tracking-status"/>
+  <mime-type type="message/vnd.si.simp"/>
+
+  <mime-type type="model/example"/>
+
+  <mime-type type="model/iges">
+    <_comment>Initial Graphics Exchange Specification Format</_comment>
+    <glob pattern="*.igs"/>
+    <glob pattern="*.iges"/>
+  </mime-type>
+
+  <mime-type type="model/mesh">
+    <glob pattern="*.msh"/>
+    <glob pattern="*.mesh"/>
+    <glob pattern="*.silo"/>
+  </mime-type>
+
+  <mime-type type="model/vnd.dwf">
+    <glob pattern="*.dwf"/>
+  </mime-type>
+  <mime-type type="model/vnd.flatland.3dml"/>
+  <mime-type type="model/vnd.gdl">
+    <glob pattern="*.gdl"/>
+  </mime-type>
+  <mime-type type="model/vnd.gs-gdl"/>
+  <mime-type type="model/vnd.gs.gdl"/>
+  <mime-type type="model/vnd.gtw">
+    <glob pattern="*.gtw"/>
+  </mime-type>
+  <mime-type type="model/vnd.moml+xml"/>
+  <mime-type type="model/vnd.mts">
+    <glob pattern="*.mts"/>
+  </mime-type>
+  <mime-type type="model/vnd.parasolid.transmit.binary"/>
+  <mime-type type="model/vnd.parasolid.transmit.text"/>
+  <mime-type type="model/vnd.vtu">
+    <glob pattern="*.vtu"/>
+  </mime-type>
+
+  <mime-type type="model/vrml">
+    <glob pattern="*.wrl"/>
+    <glob pattern="*.vrml"/>
+  </mime-type>
+
+  <mime-type type="multipart/alternative"/>
+  <mime-type type="multipart/appledouble"/>
+  <mime-type type="multipart/byteranges"/>
+  <mime-type type="multipart/digest"/>
+  <mime-type type="multipart/encrypted"/>
+  <mime-type type="multipart/example"/>
+  <mime-type type="multipart/form-data"/>
+  <mime-type type="multipart/header-set"/>
+  <mime-type type="multipart/mixed"/>
+  <mime-type type="multipart/parallel"/>
+  <mime-type type="multipart/related"/>
+  <mime-type type="multipart/report"/>
+  <mime-type type="multipart/signed"/>
+  <mime-type type="multipart/voice-message"/>
+  <mime-type type="text/calendar">
+    <glob pattern="*.ics"/>
+    <glob pattern="*.ifb"/>
+  </mime-type>
+
+  <mime-type type="text/css">
+    <_comment>Cascading Style Sheet</_comment>
+    <glob pattern="*.css"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="text/csv">
+    <glob pattern="*.csv"/>
+  </mime-type>
+  <mime-type type="text/directory"/>
+  <mime-type type="text/dns"/>
+  <mime-type type="text/ecmascript"/>
+  <mime-type type="text/enriched"/>
+  <mime-type type="text/example"/>
+
+  <mime-type type="text/html">
+     <!-- TIKA-327: if you encounter tags in the HTML
+          with no declared namespace, it's not XHTML, it's just
+          bad HTML, unfortunately.
+     -->
+    <root-XML localName="html"/>
+    <root-XML localName="HTML"/>
+    <root-XML localName="link"/>
+    <root-XML localName="LINK"/>
+    <root-XML localName="body"/>
+    <root-XML localName="BODY"/>
+    <root-XML localName="p"/>
+    <root-XML localName="P"/>
+    <root-XML localName="script"/>
+    <root-XML localName="SCRIPT"/>
+    <root-XML localName="frameset"/>
+    <root-XML localName="FRAMESET"/>
+    <magic priority="50">
+      <match value="&lt;!DOCTYPE HTML" type="string" offset="0:64"/>
+      <match value="&lt;!doctype html" type="string" offset="0:64"/>
+      <match value="&lt;HEAD" type="string" offset="0:64"/>
+      <match value="&lt;head" type="string" offset="0:64"/>
+      <match value="&lt;TITLE" type="string" offset="0:64"/>
+      <match value="&lt;title" type="string" offset="0:64"/>
+      <!-- note on the offset value here: this can only be as big as
+           MimeTypes#getMinLength(). If you set the offset value to larger
+           than that size, the magic will only be compared to up to
+           MimeTypes#getMinLength() bytes.
+       -->
+      <match value="&lt;html" type="string" offset="0:8192"/>
+      <match value="&lt;HTML" type="string" offset="0:64"/>
+      <match value="&lt;BODY" type="string" offset="0"/>
+      <match value="&lt;body" type="string" offset="0"/>
+      <match value="&lt;TITLE" type="string" offset="0"/>
+      <match value="&lt;title" type="string" offset="0"/>
+      <match value="&lt;h1" type="string" offset="0"/>
+      <match value="&lt;H1" type="string" offset="0"/>
+      <match value="&lt;!doctype HTML" type="string" offset="0"/>
+      <match value="&lt;!DOCTYPE html" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.html"/>
+    <glob pattern="*.htm"/>
+  </mime-type>
+
+  <mime-type type="text/javascript"/>
+  <mime-type type="text/parityfec"/>
+
+  <mime-type type="text/plain">
+    <magic priority="20">
+      <match value="This is TeX," type="string" offset="0"/>
+      <match value="This is METAFONT," type="string" offset="0"/>
+      <match value="/*" type="string" offset="0"/>
+      <match value="//" type="string" offset="0"/>
+      <match value=";;" type="string" offset="0"/>
+      <!-- UTF-16BE BOM -->
+      <match value="0xfeff" type="string" offset="0"/>
+      <!-- UTF-16LE BOM -->
+      <match value="0xfffe" type="string" offset="0"/>
+      <!-- UTF-8 BOM -->
+      <match value="0xefbbbf" type="string" offset="0"/>
+    </magic>
+
+    <glob pattern="*.txt"/>
+    <glob pattern="*.text"/>
+    <glob pattern="*.conf"/>
+    <glob pattern="*.def"/>
+    <glob pattern="*.list"/>
+    <glob pattern="*.log"/>
+    <glob pattern="*.in"/>
+
+    <!-- TIKA-85: http://www.apache.org/dev/svn-eol-style.txt -->
+    <glob pattern="INSTALL"/>
+    <glob pattern="KEYS"/>
+    <glob pattern="Makefile"/>
+    <glob pattern="README"/>
+    <glob pattern="abs-linkmap"/>
+    <glob pattern="abs-menulinks"/>
+    <glob pattern="*.aart"/>
+    <glob pattern="*.ac"/>
+    <glob pattern="*.am"/>
+    <glob pattern="*.cgi"/>
+    <glob pattern="*.classpath"/>
+    <glob pattern="*.cmd"/>
+    <glob pattern="*.config"/>
+    <glob pattern="*.cwiki"/>
+    <glob pattern="*.data"/>
+    <glob pattern="*.dcl"/>
+    <glob pattern="*.egrm"/>
+    <glob pattern="*.ent"/>
+    <glob pattern="*.ft"/>
+    <glob pattern="*.fn"/>
+    <glob pattern="*.fv"/>
+    <glob pattern="*.grm"/>
+    <glob pattern="*.g"/>
+    <glob pattern=".htaccess"/>
+    <glob pattern="*.ihtml"/>
+    <glob pattern="*.jmx"/>
+    <glob pattern="*.jsp"/>
+    <glob pattern="*.junit"/>
+    <glob pattern="*.jx"/>
+    <glob pattern="*.manifest"/>
+    <glob pattern="*.m4"/>
+    <glob pattern="*.mf"/>
+    <glob pattern="*.MF"/>
+    <glob pattern="*.meta"/>
+    <glob pattern="*.n3"/>
+    <glob pattern="*.pen"/>
+    <glob pattern="*.pl"/>
+    <glob pattern="*.pm"/>
+    <glob pattern="*.pod"/>
+    <glob pattern="*.pom"/>
+    <glob pattern="*.project"/>
+    <glob pattern="*.properties"/>
+    <glob pattern="*.py"/>
+    <glob pattern="*.rb"/>
+    <glob pattern="*.rng"/>
+    <glob pattern="*.rnx"/>
+    <glob pattern="*.roles"/>
+    <glob pattern="*.sql"/>
+    <glob pattern="*.tld"/>
+    <glob pattern="*.types"/>
+    <glob pattern="*.vm"/>
+    <glob pattern="*.vsl"/>
+    <glob pattern="*.wsdd"/>
+    <glob pattern="*.xargs"/>
+    <glob pattern="*.xcat"/>
+    <glob pattern="*.xconf"/>
+    <glob pattern="*.xegrm"/>
+    <glob pattern="*.xgrm"/>
+    <glob pattern="*.xlex"/>
+    <glob pattern="*.xlog"/>
+    <glob pattern="*.xmap"/>
+    <glob pattern="*.xroles"/>
+    <glob pattern="*.xsamples"/>
+    <glob pattern="*.xsp"/>
+    <glob pattern="*.xweb"/>
+    <glob pattern="*.xwelcome"/>
+  </mime-type>
+
+  <mime-type type="text/prs.fallenstein.rst"/>
+  <mime-type type="text/prs.lines.tag">
+    <glob pattern="*.dsc"/>
+  </mime-type>
+  <mime-type type="text/red"/>
+  <mime-type type="text/rfc822-headers"/>
+  <mime-type type="text/richtext">
+    <glob pattern="*.rtx"/>
+  </mime-type>
+  <mime-type type="text/rtf"/>
+  <mime-type type="text/rtp-enc-aescm128"/>
+  <mime-type type="text/rtx"/>
+  <mime-type type="text/sgml">
+    <glob pattern="*.sgml"/>
+    <glob pattern="*.sgm"/>
+  </mime-type>
+  <mime-type type="text/t140"/>
+  <mime-type type="text/tab-separated-values">
+    <glob pattern="*.tsv"/>
+  </mime-type>
+
+  <mime-type type="text/troff">
+    <alias type="application/x-troff"/>
+    <alias type="application/x-troff-man"/>
+    <alias type="application/x-troff-me"/>
+    <alias type="application/x-troff-ms"/>
+    <magic priority="50">
+      <match value=".\\&quot;" type="string" offset="0"/>
+      <match value="'\\&quot;" type="string" offset="0"/>
+      <match value="'.\\&quot;" type="string" offset="0"/>
+      <match value="\\&quot;" type="string" offset="0"/>
+      <match value="'''" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.t"/>
+    <glob pattern="*.tr"/>
+    <glob pattern="*.roff"/>
+    <glob pattern="*.man"/>
+    <glob pattern="*.me"/>
+    <glob pattern="*.ms"/>
+  </mime-type>
+
+  <mime-type type="text/ulpfec"/>
+  <mime-type type="text/uri-list">
+    <glob pattern="*.uri"/>
+    <glob pattern="*.uris"/>
+    <glob pattern="*.urls"/>
+  </mime-type>
+  <mime-type type="text/vnd.abc"/>
+  <mime-type type="text/vnd.curl">
+    <glob pattern="*.curl"/>
+  </mime-type>
+  <mime-type type="text/vnd.curl.dcurl">
+    <glob pattern="*.dcurl"/>
+  </mime-type>
+  <mime-type type="text/vnd.curl.scurl">
+    <glob pattern="*.scurl"/>
+  </mime-type>
+  <mime-type type="text/vnd.curl.mcurl">
+    <glob pattern="*.mcurl"/>
+  </mime-type>
+  <mime-type type="text/vnd.dmclientscript"/>
+  <mime-type type="text/vnd.esmertec.theme-descriptor"/>
+  <mime-type type="text/vnd.fly">
+    <glob pattern="*.fly"/>
+  </mime-type>
+  <mime-type type="text/vnd.fmi.flexstor">
+    <glob pattern="*.flx"/>
+  </mime-type>
+  <mime-type type="text/vnd.graphviz">
+    <glob pattern="*.gv"/>
+  </mime-type>
+  <mime-type type="text/vnd.in3d.3dml">
+    <glob pattern="*.3dml"/>
+  </mime-type>
+  <mime-type type="text/vnd.in3d.spot">
+    <glob pattern="*.spot"/>
+  </mime-type>
+  <mime-type type="text/vnd.iptc.newsml"/>
+  <mime-type type="text/vnd.iptc.nitf"/>
+  <mime-type type="text/vnd.latex-z"/>
+  <mime-type type="text/vnd.motorola.reflex"/>
+  <mime-type type="text/vnd.ms-mediapackage"/>
+  <mime-type type="text/vnd.net2phone.commcenter.command"/>
+  <mime-type type="text/vnd.si.uricatalogue"/>
+  <mime-type type="text/vnd.sun.j2me.app-descriptor">
+    <glob pattern="*.jad"/>
+  </mime-type>
+  <mime-type type="text/vnd.trolltech.linguist"/>
+  <mime-type type="text/vnd.wap.si"/>
+  <mime-type type="text/vnd.wap.sl"/>
+  <mime-type type="text/vnd.wap.wml">
+    <glob pattern="*.wml"/>
+  </mime-type>
+
+  <mime-type type="text/vnd.wap.wmlscript">
+    <_comment>WML Script</_comment>
+    <glob pattern="*.wmls"/>
+  </mime-type>
+
+  <mime-type type="text/x-asm">
+    <glob pattern="*.s"/>
+    <glob pattern="*.asm"/>
+  </mime-type>
+
+  <mime-type type="text/x-c">
+    <glob pattern="*.c"/>
+    <glob pattern="*.cc"/>
+    <glob pattern="*.cxx"/>
+    <glob pattern="*.cpp"/>
+    <glob pattern="*.h"/>
+    <glob pattern="*.hh"/>
+    <glob pattern="*.dic"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="text/x-diff">
+    <magic priority="50">
+      <match value="diff\ " type="string" offset="0"/>
+      <match value="***\ " type="string" offset="0"/>
+      <match value="Only\ in\ " type="string" offset="0"/>
+      <match value="Common\ subdirectories:\ " type="string" offset="0"/>
+      <match value="Index:" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.diff"/>
+    <glob pattern="*.patch"/>
+  </mime-type>
+
+  <mime-type type="text/x-fortran">
+    <glob pattern="*.f"/>
+    <glob pattern="*.for"/>
+    <glob pattern="*.f77"/>
+    <glob pattern="*.f90"/>
+  </mime-type>
+  <mime-type type="text/x-pascal">
+    <glob pattern="*.p"/>
+    <glob pattern="*.pas"/>
+  </mime-type>
+
+  <mime-type type="text/x-java-source">
+    <glob pattern="*.java"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="text/x-setext">
+    <glob pattern="*.etx"/>
+  </mime-type>
+
+  <mime-type type="text/x-uuencode">
+    <glob pattern="*.uu"/>
+  </mime-type>
+  <mime-type type="text/x-vcalendar">
+    <glob pattern="*.vcs"/>
+  </mime-type>
+  <mime-type type="text/x-vcard">
+    <glob pattern="*.vcf"/>
+  </mime-type>
+  <mime-type type="text/xml"/>
+  <mime-type type="text/xml-external-parsed-entity"/>
+  <mime-type type="video/3gpp">
+    <glob pattern="*.3gp"/>
+  </mime-type>
+  <mime-type type="video/3gpp-tt"/>
+  <mime-type type="video/3gpp2">
+    <glob pattern="*.3g2"/>
+  </mime-type>
+  <mime-type type="video/bmpeg"/>
+  <mime-type type="video/bt656"/>
+  <mime-type type="video/celb"/>
+  <mime-type type="video/dv"/>
+  <mime-type type="video/example"/>
+  <mime-type type="video/h261">
+    <glob pattern="*.h261"/>
+  </mime-type>
+  <mime-type type="video/h263">
+    <glob pattern="*.h263"/>
+  </mime-type>
+  <mime-type type="video/h263-1998"/>
+  <mime-type type="video/h263-2000"/>
+  <mime-type type="video/h264">
+    <glob pattern="*.h264"/>
+  </mime-type>
+  <mime-type type="video/jpeg">
+    <glob pattern="*.jpgv"/>
+  </mime-type>
+  <mime-type type="video/jpeg2000"/>
+  <mime-type type="video/jpm">
+    <glob pattern="*.jpm"/>
+    <glob pattern="*.jpgm"/>
+  </mime-type>
+  <mime-type type="video/mj2">
+    <glob pattern="*.mj2"/>
+    <glob pattern="*.mjp2"/>
+  </mime-type>
+  <mime-type type="video/mp1s"/>
+  <mime-type type="video/mp2p"/>
+  <mime-type type="video/mp2t"/>
+  <mime-type type="video/mp4">
+    <glob pattern="*.mp4"/>
+    <glob pattern="*.mp4v"/>
+    <glob pattern="*.mpg4"/>
+  </mime-type>
+  <mime-type type="video/mp4v-es"/>
+
+  <mime-type type="video/mpeg">
+    <magic priority="50">
+      <match value="\000\000\001\263" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.mpeg"/>
+    <glob pattern="*.mpg"/>
+    <glob pattern="*.mpe"/>
+    <glob pattern="*.m1v"/>
+    <glob pattern="*.m2v"/>
+  </mime-type>
+
+  <mime-type type="video/vnd.mpegurl">
+    <glob pattern="*.mxu"/>
+  </mime-type>
+
+  <mime-type type="video/mpeg4-generic"/>
+  <mime-type type="video/mpv"/>
+  <mime-type type="video/nv"/>
+
+  <mime-type type="video/ogg">
+    <glob pattern="*.ogv"/>
+    <sub-class-of type="application/ogg"/>
+  </mime-type>
+
+  <mime-type type="video/parityfec"/>
+  <mime-type type="video/pointer"/>
+
+  <mime-type type="video/quicktime">
+    <magic priority="50">
+      <match value="moov" type="string" offset="4"/>
+      <match value="mdat" type="string" offset="4"/>
+      <match value="ftyp" type="string" offset="4"/>
+    </magic>
+    <glob pattern="*.qt"/>
+    <glob pattern="*.mov"/>
+  </mime-type>
+
+  <mime-type type="video/raw"/>
+  <mime-type type="video/rtp-enc-aescm128"/>
+  <mime-type type="video/rtx"/>
+  <mime-type type="video/smpte292m"/>
+  <mime-type type="video/ulpfec"/>
+  <mime-type type="video/vc1"/>
+  <mime-type type="video/vnd.cctv"/>
+  <mime-type type="video/vnd.dlna.mpeg-tts"/>
+  <mime-type type="video/vnd.fvt">
+    <glob pattern="*.fvt"/>
+  </mime-type>
+  <mime-type type="video/vnd.hns.video"/>
+  <mime-type type="video/vnd.iptvforum.1dparityfec-1010"/>
+  <mime-type type="video/vnd.iptvforum.1dparityfec-2005"/>
+  <mime-type type="video/vnd.iptvforum.2dparityfec-1010"/>
+  <mime-type type="video/vnd.iptvforum.2dparityfec-2005"/>
+  <mime-type type="video/vnd.iptvforum.ttsavc"/>
+  <mime-type type="video/vnd.iptvforum.ttsmpeg2"/>
+  <mime-type type="video/vnd.motorola.video"/>
+  <mime-type type="video/vnd.motorola.videop"/>
+  <mime-type type="video/vnd.mpegurl">
+    <glob pattern="*.mxu"/>
+    <glob pattern="*.m4u"/>
+  </mime-type>
+  <mime-type type="video/vnd.ms-playready.media.pyv">
+    <glob pattern="*.pyv"/>
+  </mime-type>
+  <mime-type type="video/vnd.nokia.interleaved-multimedia"/>
+  <mime-type type="video/vnd.nokia.videovoip"/>
+  <mime-type type="video/vnd.objectvideo"/>
+  <mime-type type="video/vnd.sealed.mpeg1"/>
+  <mime-type type="video/vnd.sealed.mpeg4"/>
+  <mime-type type="video/vnd.sealed.swf"/>
+  <mime-type type="video/vnd.sealedmedia.softseal.mov"/>
+  <mime-type type="video/vnd.vivo">
+    <glob pattern="*.viv"/>
+  </mime-type>
+  <mime-type type="video/x-f4v">
+    <glob pattern="*.f4v"/>
+  </mime-type>
+
+  <mime-type type="video/x-flc">
+    <glob pattern="*.flc"/>
+  </mime-type>
+
+  <mime-type type="video/x-fli">
+    <glob pattern="*.fli"/>
+  </mime-type>
+
+  <mime-type type="video/x-flv">
+    <magic priority="50">
+      <match value="FLV" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.flv"/>
+  </mime-type>
+
+  <mime-type type="video/x-jng">
+    <magic priority="50">
+      <match value="\x8bJNG" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.jng"/>
+  </mime-type>
+
+  <mime-type type="video/x-m4v">
+    <glob pattern="*.m4v"/>
+  </mime-type>
+
+  <mime-type type="video/x-mng">
+    <magic priority="50">
+      <match value="\x8aMNG" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.mng"/>
+  </mime-type>
+
+  <mime-type type="video/x-ms-asf">
+    <glob pattern="*.asf"/>
+    <glob pattern="*.asx"/>
+  </mime-type>
+  <mime-type type="video/x-ms-wm">
+    <glob pattern="*.wm"/>
+  </mime-type>
+  <mime-type type="video/x-ms-wmv">
+    <glob pattern="*.wmv"/>
+  </mime-type>
+  <mime-type type="video/x-ms-wmx">
+    <glob pattern="*.wmx"/>
+  </mime-type>
+  <mime-type type="video/x-ms-wvx">
+    <glob pattern="*.wvx"/>
+  </mime-type>
+
+  <mime-type type="video/x-msvideo">
+    <alias type="video/avi"/>
+    <alias type="video/msvideo"/>
+    <magic priority="50">
+      <match value="RIFF....AVI " type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+    </magic>
+    <glob pattern="*.avi"/>
+  </mime-type>
+
+  <mime-type type="video/x-sgi-movie">
+    <magic priority="50">
+      <match value="MOVI" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.movie"/>
+  </mime-type>
+
+  <mime-type type="x-conference/x-cooltalk">
+    <_comment>Cooltalk Audio</_comment>
+    <glob pattern="*.ice"/>
+  </mime-type>
+
+</mime-info>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/product-type-element-map.xsl b/0.8.1-rc1/filemgr/src/main/resources/product-type-element-map.xsl
new file mode 100644
index 0000000..e54a99f
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/product-type-element-map.xsl
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  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.
+-->
+<!-- 
+	Description: To use this stylesheet in your product-type-element map, add the following
+	line below the <?xml... ?> declaration in the map file:
+	
+	<?xml-stylesheet type="text/xsl" href="product-type-element-map.xsl"?>
+-->
+<!DOCTYPE xsl:stylesheet  [
+	<!ENTITY nbsp   "&#160;">
+	<!ENTITY copy   "&#169;">
+	<!ENTITY reg    "&#174;">
+	<!ENTITY trade  "&#8482;">
+	<!ENTITY mdash  "&#8212;">
+	<!ENTITY ldquo  "&#8220;">
+	<!ENTITY rdquo  "&#8221;"> 
+	<!ENTITY pound  "&#163;">
+	<!ENTITY yen    "&#165;">
+	<!ENTITY euro   "&#8364;">
+]>
+<xsl:stylesheet version="1.0"
+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+	xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<xsl:output method="html" encoding="ISO-8859-1"
+		doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
+		doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" />
+	<xsl:template match="/cas:producttypemap">
+
+		<html xmlns="http://www.w3.org/1999/xhtml">
+			<head>
+				<meta http-equiv="Content-Type"
+					content="text/html; charset=ISO-8859-1" />
+				<title>CAS Objects</title>
+			</head>
+
+			<xsl:variable name="elementList"
+				select="document('elements.xml')" />
+
+			<body>
+				<table border="0" style="font-family:Sans-Serif;">
+					<tr style="font-weight:bold">
+						<td>Object</td>
+						<td>Data Elements</td>
+					</tr>
+					<xsl:for-each select="type">
+						<tr valign="top">
+							<td height="40"
+								style="background-color:#dfd389;">
+								<xsl:value-of
+									select="substring(@id, 10)" />
+							</td>
+							<td rowspan="3">
+								<table
+									style="background-color:#889989;text-decoration:italic;">
+									<xsl:choose>
+										<xsl:when test="element">
+											<xsl:for-each
+												select="element">
+												<xsl:variable
+													name="elemId" select="@id" />
+												<tr>
+													<td>
+														<xsl:value-of
+															select="substring(@id, 10)" />
+													</td>
+													<td
+														style="font-size:11px;">
+														<xsl:value-of
+															select="$elementList/cas:elements/element[@id=$elemId]" />
+													</td>
+												</tr>
+											</xsl:for-each>
+										</xsl:when>
+										<xsl:otherwise>
+											<tr>
+												<td colspan="2">
+													No declared
+													elements: All
+													elements inherited
+												</td>
+											</tr>
+										</xsl:otherwise>
+									</xsl:choose>
+								</table>
+							</td>
+						</tr>
+						<tr valign="top" height="40">
+							<td align="left"
+								style="font-style:italic;">
+								Parent:
+								<xsl:value-of
+									select="substring(@parent, 10)" />
+							</td>
+						</tr>
+						<tr valign="top">
+							<td>
+								&nbsp;
+							</td>
+						</tr>
+					</xsl:for-each>
+				</table>
+
+			</body>
+		</html>
+
+	</xsl:template>
+</xsl:stylesheet>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/schema.xml b/0.8.1-rc1/filemgr/src/main/resources/schema.xml
new file mode 100644
index 0000000..d2a6975
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/schema.xml
@@ -0,0 +1,1025 @@
+<?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.
+-->
+
+<!--  
+ This is the Solr schema file. This file should be named "schema.xml" and
+ should be in the conf directory under the solr home
+ (i.e. ./solr/conf/schema.xml by default) 
+ or located where the classloader for the Solr webapp can find it.
+
+ This example schema is the recommended starting point for users.
+ It should be kept correct and concise, usable out-of-the-box.
+
+ For more information, on how to customize this file, please see
+ http://wiki.apache.org/solr/SchemaXml
+
+ PERFORMANCE NOTE: this schema includes many optional features and should not
+ be used for benchmarking.  To improve performance one could
+  - set stored="false" for all fields possible (esp large fields) when you
+    only need to search on the field but don't need to return the original
+    value.
+  - set indexed="false" if you don't need to search on the field, but only
+    return the field as a result of searching on other indexed fields.
+  - remove all unneeded copyField statements
+  - for best index size and searching performance, set "index" to false
+    for all general text fields, use copyField to copy them to the
+    catchall "text" field, and use that for searching.
+  - For maximum indexing performance, use the StreamingUpdateSolrServer
+    java client.
+  - Remember to run the JVM in server mode, and use a higher logging level
+    that avoids logging every request
+-->
+
+<schema name="Default Solr File Manager schema" version="1.5">
+  <!-- attribute "name" is the name of this schema and is only used for display purposes.
+       version="x.y" is Solr's version number for the schema syntax and 
+       semantics.  It should not normally be changed by applications.
+
+       1.0: multiValued attribute did not exist, all fields are multiValued 
+            by nature
+       1.1: multiValued attribute introduced, false by default 
+       1.2: omitTermFreqAndPositions attribute introduced, true by default 
+            except for text fields.
+       1.3: removed optional field compress feature
+       1.4: autoGeneratePhraseQueries attribute introduced to drive QueryParser
+            behavior when a single string produces multiple tokens.  Defaults 
+            to off for version >= 1.4
+       1.5: omitNorms defaults to true for primitive field types 
+            (int, float, boolean, string...)
+     -->
+
+ <fields>
+   <!-- Valid attributes for fields:
+     name: mandatory - the name for the field
+     type: mandatory - the name of a field type from the 
+       <types> fieldType section
+     indexed: true if this field should be indexed (searchable or sortable)
+     stored: true if this field should be retrievable
+     docValues: true if this field should have doc values. Doc values are
+       useful for faceting, grouping, sorting and function queries. Although not
+       required, doc values will make the index faster to load, more
+       NRT-friendly and more memory-efficient. They however come with some
+       limitations: they are currently only supported by StrField, UUIDField
+       and all Trie*Fields, and depending on the field type, they might
+       require the field to be single-valued, be required or have a default
+       value (check the documentation of the field type you're interested in
+       for more information)
+     multiValued: true if this field may contain multiple values per document
+     omitNorms: (expert) set to true to omit the norms associated with
+       this field (this disables length normalization and index-time
+       boosting for the field, and saves some memory).  Only full-text
+       fields or fields that need an index-time boost need norms.
+       Norms are omitted for primitive (non-analyzed) types by default.
+     termVectors: [false] set to true to store the term vector for a
+       given field.
+       When using MoreLikeThis, fields used for similarity should be
+       stored for best performance.
+     termPositions: Store position information with the term vector.  
+       This will increase storage costs.
+     termOffsets: Store offset information with the term vector. This 
+       will increase storage costs.
+     required: The field is required.  It will throw an error if the
+       value does not exist
+     default: a value that should be used if no value is specified
+       when adding a document.
+   -->
+
+   <!-- field names should consist of alphanumeric or underscore characters only and
+      not start with a digit.  This is not currently strictly enforced,
+      but other field names will not have first class support from all components
+      and back compatibility is not guaranteed.  Names with both leading and
+      trailing underscores (e.g. _version_) are reserved.
+   -->
+        
+     
+   <!-- Solr unique document identifier -->
+   <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> 
+
+   <!-- core CAS product attributes -->
+   <field name="CAS.ProductId" type="string" indexed="true" stored="true" required="true" multiValued="false" />
+   <field name="CAS.ProductName" type="string" indexed="true" stored="true" required="true" multiValued="false" />
+   <field name="CAS.ProductTypeName" type="string" indexed="true" stored="true" required="true" multiValued="false" />
+   <field name="CAS.ProductTypeId" type="string" indexed="true" stored="true" required="true" multiValued="false" />
+   <field name="CAS.ProductReceivedTime" type="date" indexed="true" stored="true" required="false" multiValued="false" />
+   <field name="CAS.ProductStructure" type="string" indexed="true" stored="true" required="false" multiValued="false" />
+   <field name="CAS.ProductTransferStatus" type="string" indexed="true" stored="true" required="false" multiValued="false" />
+
+   <field name="CAS.RootReferenceOriginal" type="string" indexed="true" stored="true" required="false" multiValued="true" />
+   <field name="CAS.RootReferenceDatastore" type="string" indexed="true" stored="true" required="false" multiValued="true" />
+   <field name="CAS.RootReferenceFileSize" type="long" indexed="true" stored="true" required="false" multiValued="true" />
+   <field name="CAS.RootReferenceMimeType" type="string" indexed="true" stored="true" required="false" multiValued="true" />
+
+   <field name="CAS.ReferenceOriginal" type="string" indexed="true" stored="true" required="false" multiValued="true" />
+   <field name="CAS.ReferenceDatastore" type="string" indexed="true" stored="true" required="false" multiValued="true" />
+   <field name="CAS.ReferenceFileSize" type="long" indexed="true" stored="true" required="false" multiValued="true" />
+   <field name="CAS.ReferenceMimeType" type="string" indexed="true" stored="true" required="false" multiValued="true" />
+
+   <!-- all unspecified fields ending in 'Date' or 'Time' are interpreted as single-value dates  -->
+   <field name="*Date" type="date" indexed="true" stored="true" required="false" multiValued="false" />
+   <field name="*Time" type="date" indexed="true" stored="true" required="false" multiValued="false" />
+
+   <!-- all other fields are indexed and stored as-is and can have multiple values -->
+   <dynamicField name="*" type="string" indexed="true" stored="true" omitNorms="true" multiValued="true" />
+
+   <!-- catch-all text fields for full free-text query -->
+   <copyField source="*" dest="text" />
+   <copyField source="*" dest="text_rev" />
+
+   <!-- Main body of document extracted by SolrCell.
+        NOTE: This field is not indexed by default, since it is also copied to "text"
+        using copyField below. This is to save space. Use this field for returning and
+        highlighting document content. Use the "text" field to search the content. -->
+   <field name="content" type="text_general" indexed="false" stored="true" multiValued="true"/>
+
+   <!-- catchall field, containing all other searchable text fields (implemented
+        via copyField further on in this schema  -->
+   <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
+
+   <!-- catchall text field that indexes tokens both normally and in reverse for efficient
+        leading wildcard queries. -->
+   <field name="text_rev" type="text_general_rev" indexed="true" stored="false" multiValued="true"/>
+
+   <!-- IMPORTANT: needed by Solr 4.X and above -->
+   <field name="_version_" type="long" indexed="true" stored="true"/>
+
+   <!-- uncomment the following to ignore any fields that don't already match an existing 
+        field name or dynamic field, rather than reporting them as an error. 
+        alternately, change the type="ignored" to some other type e.g. "text" if you want 
+        unknown fields indexed and/or stored by default --> 
+   <!--dynamicField name="*" type="ignored" multiValued="true" /-->
+   
+ </fields>
+
+
+ <!-- Field to use to determine and enforce document uniqueness. 
+      Unless this field is marked with required="false", it will be a required field
+   -->
+ <uniqueKey>id</uniqueKey>
+
+ <!-- DEPRECATED: The defaultSearchField is consulted by various query parsers when
+  parsing a query string that isn't explicit about the field.  Machine (non-user)
+  generated queries are best made explicit, or they can use the "df" request parameter
+  which takes precedence over this.
+  Note: Un-commenting defaultSearchField will be insufficient if your request handler
+  in solrconfig.xml defines "df", which takes precedence. That would need to be removed.
+ <defaultSearchField>text</defaultSearchField> -->
+
+ <!-- DEPRECATED: The defaultOperator (AND|OR) is consulted by various query parsers
+  when parsing a query string to determine if a clause of the query should be marked as
+  required or optional, assuming the clause isn't already marked by some operator.
+  The default is OR, which is generally assumed so it is not a good idea to change it
+  globally here.  The "q.op" request parameter takes precedence over this.
+ <solrQueryParser defaultOperator="OR"/> -->
+ 
+  <types>
+    <!-- field type definitions. The "name" attribute is
+       just a label to be used by field definitions.  The "class"
+       attribute and any other attributes determine the real
+       behavior of the fieldType.
+         Class names starting with "solr" refer to java classes in a
+       standard package such as org.apache.solr.analysis
+    -->
+
+    <!-- The StrField type is not analyzed, but indexed/stored verbatim.
+       It supports doc values but in that case the field needs to be
+       single-valued and either required or have a default value.
+      -->
+    <fieldType name="string" class="solr.StrField" sortMissingLast="true" />
+
+    <!-- boolean type: "true" or "false" -->
+    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
+
+    <!-- sortMissingLast and sortMissingFirst attributes are optional attributes are
+         currently supported on types that are sorted internally as strings
+         and on numeric types.
+	     This includes "string","boolean", and, as of 3.5 (and 4.x),
+	     int, float, long, date, double, including the "Trie" variants.
+       - If sortMissingLast="true", then a sort on this field will cause documents
+         without the field to come after documents with the field,
+         regardless of the requested sort order (asc or desc).
+       - If sortMissingFirst="true", then a sort on this field will cause documents
+         without the field to come before documents with the field,
+         regardless of the requested sort order.
+       - If sortMissingLast="false" and sortMissingFirst="false" (the default),
+         then default lucene sorting will be used which places docs without the
+         field first in an ascending sort and last in a descending sort.
+    -->    
+
+    <!--
+      Default numeric field types. For faster range queries, consider the tint/tfloat/tlong/tdouble types.
+
+      These fields support doc values, but they require the field to be
+      single-valued and either be required or have a default value.
+    -->
+    <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
+
+    <!--
+     Numeric field types that index each value at various levels of precision
+     to accelerate range queries when the number of values between the range
+     endpoints is large. See the javadoc for NumericRangeQuery for internal
+     implementation details.
+
+     Smaller precisionStep values (specified in bits) will lead to more tokens
+     indexed per value, slightly larger index size, and faster range queries.
+     A precisionStep of 0 disables indexing at different precision levels.
+    -->
+    <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
+    <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
+    <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
+    <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
+
+    <!-- The format for this date field is of the form 1995-12-31T23:59:59Z, and
+         is a more restricted form of the canonical representation of dateTime
+         http://www.w3.org/TR/xmlschema-2/#dateTime    
+         The trailing "Z" designates UTC time and is mandatory.
+         Optional fractional seconds are allowed: 1995-12-31T23:59:59.999Z
+         All other components are mandatory.
+
+         Expressions can also be used to denote calculations that should be
+         performed relative to "NOW" to determine the value, ie...
+
+               NOW/HOUR
+                  ... Round to the start of the current hour
+               NOW-1DAY
+                  ... Exactly 1 day prior to now
+               NOW/DAY+6MONTHS+3DAYS
+                  ... 6 months and 3 days in the future from the start of
+                      the current day
+                      
+         Consult the DateField javadocs for more information.
+
+         Note: For faster range queries, consider the tdate type
+      -->
+    <fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/>
+
+    <!-- A Trie based date field for faster date range queries and date faceting. -->
+    <fieldType name="tdate" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="0"/>
+
+
+    <!--Binary data type. The data should be sent/retrieved in as Base64 encoded Strings -->
+    <fieldtype name="binary" class="solr.BinaryField"/>
+
+    <!--
+      Note:
+      These should only be used for compatibility with existing indexes (created with lucene or older Solr versions).
+      Use Trie based fields instead. As of Solr 3.5 and 4.x, Trie based fields support sortMissingFirst/Last
+      
+      Plain numeric field types that store and index the text
+      value verbatim (and hence don't correctly support range queries, since the
+      lexicographic ordering isn't equal to the numeric ordering)
+    -->
+    <fieldType name="pint" class="solr.IntField"/>
+    <fieldType name="plong" class="solr.LongField"/>
+    <fieldType name="pfloat" class="solr.FloatField"/>
+    <fieldType name="pdouble" class="solr.DoubleField"/>
+    <fieldType name="pdate" class="solr.DateField" sortMissingLast="true"/>
+
+    <!-- The "RandomSortField" is not used to store or search any
+         data.  You can declare fields of this type it in your schema
+         to generate pseudo-random orderings of your docs for sorting 
+         or function purposes.  The ordering is generated based on the field
+         name and the version of the index. As long as the index version
+         remains unchanged, and the same field name is reused,
+         the ordering of the docs will be consistent.  
+         If you want different psuedo-random orderings of documents,
+         for the same version of the index, use a dynamicField and
+         change the field name in the request.
+     -->
+    <fieldType name="random" class="solr.RandomSortField" indexed="true" />
+
+    <!-- solr.TextField allows the specification of custom text analyzers
+         specified as a tokenizer and a list of token filters. Different
+         analyzers may be specified for indexing and querying.
+
+         The optional positionIncrementGap puts space between multiple fields of
+         this type on the same document, with the purpose of preventing false phrase
+         matching across fields.
+
+         For more info on customizing your analyzer chain, please see
+         http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters
+     -->
+
+    <!-- One can also specify an existing Analyzer class that has a
+         default constructor via the class attribute on the analyzer element.
+         Example:
+    <fieldType name="text_greek" class="solr.TextField">
+      <analyzer class="org.apache.lucene.analysis.el.GreekAnalyzer"/>
+    </fieldType>
+    -->
+
+    <!-- A text field that only splits on whitespace for exact matching of words -->
+    <fieldType name="text_ws" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A general text field that has reasonable, generic
+         cross-language defaults: it tokenizes with StandardTokenizer,
+	 removes stop words from case-insensitive "stopwords.txt"
+	 (empty by default), and down cases.  At query time only, it
+	 also applies synonyms. -->
+    <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A text field with defaults appropriate for English: it
+         tokenizes with StandardTokenizer, removes English stop words
+         (lang/stopwords_en.txt), down cases, protects words from protwords.txt, and
+         finally applies Porter's stemming.  The query time analyzer
+         also applies synonyms from synonyms.txt. -->
+    <fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        -->
+        <!-- Case insensitive stop word removal.
+          add enablePositionIncrements=true in both the index and query
+          analyzers to leave a 'gap' for more accurate phrase queries.
+        -->
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="lang/stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.LowerCaseFilterFactory"/>
+	<filter class="solr.EnglishPossessiveFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+	<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+	-->
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="lang/stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.LowerCaseFilterFactory"/>
+	<filter class="solr.EnglishPossessiveFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+	<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+	-->
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A text field with defaults appropriate for English, plus
+	 aggressive word-splitting and autophrase features enabled.
+	 This field is just like text_en, except it adds
+	 WordDelimiterFilter to enable splitting and matching of
+	 words on case-change, alpha numeric boundaries, and
+	 non-alphanumeric chars.  This means certain compound word
+	 cases will work, for example query "wi fi" will match
+	 document "WiFi" or "wi-fi".
+        -->
+    <fieldType name="text_en_splitting" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
+      <analyzer type="index">
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        -->
+        <!-- Case insensitive stop word removal.
+          add enablePositionIncrements=true in both the index and query
+          analyzers to leave a 'gap' for more accurate phrase queries.
+        -->
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="lang/stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="lang/stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Less flexible matching, but less false matches.  Probably not ideal for product names,
+         but may be good for SKUs.  Can insert dashes in the wrong place and still match. -->
+    <fieldType name="text_en_splitting_tight" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt"/>
+        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="0" generateNumberParts="0" catenateWords="1" catenateNumbers="1" catenateAll="0"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+        <!-- this filter can remove any duplicate tokens that appear at the same position - sometimes
+             possible with WordDelimiterFilter in conjuncton with stemming. -->
+        <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Just like text_general except it reverses the characters of
+	 each token, to enable more efficient leading wildcard queries. -->
+    <fieldType name="text_general_rev" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.ReversedWildcardFilterFactory" withOriginal="true"
+           maxPosAsterisk="3" maxPosQuestion="2" maxFractionAsterisk="0.33"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- charFilter + WhitespaceTokenizer  -->
+    <!--
+    <fieldType name="text_char_norm" class="solr.TextField" positionIncrementGap="100" >
+      <analyzer>
+        <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ISOLatin1Accent.txt"/>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+      </analyzer>
+    </fieldType>
+    -->
+
+    <!-- This is an example of using the KeywordTokenizer along
+         With various TokenFilterFactories to produce a sortable field
+         that does not include some properties of the source text
+      -->
+    <fieldType name="alphaOnlySort" class="solr.TextField" sortMissingLast="true" omitNorms="true">
+      <analyzer>
+        <!-- KeywordTokenizer does no actual tokenizing, so the entire
+             input string is preserved as a single token
+          -->
+        <tokenizer class="solr.KeywordTokenizerFactory"/>
+        <!-- The LowerCase TokenFilter does what you expect, which can be
+             when you want your sorting to be case insensitive
+          -->
+        <filter class="solr.LowerCaseFilterFactory" />
+        <!-- The TrimFilter removes any leading or trailing whitespace -->
+        <filter class="solr.TrimFilterFactory" />
+        <!-- The PatternReplaceFilter gives you the flexibility to use
+             Java Regular expression to replace any sequence of characters
+             matching a pattern with an arbitrary replacement string, 
+             which may include back references to portions of the original
+             string matched by the pattern.
+             
+             See the Java Regular Expression documentation for more
+             information on pattern and replacement string syntax.
+             
+             http://java.sun.com/j2se/1.6.0/docs/api/java/util/regex/package-summary.html
+          -->
+        <filter class="solr.PatternReplaceFilterFactory"
+                pattern="([^a-z])" replacement="" replace="all"
+        />
+      </analyzer>
+    </fieldType>
+    
+    <fieldtype name="phonetic" stored="false" indexed="true" class="solr.TextField" >
+      <analyzer>
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.DoubleMetaphoneFilterFactory" inject="false"/>
+      </analyzer>
+    </fieldtype>
+
+    <fieldtype name="payloads" stored="false" indexed="true" class="solr.TextField" >
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <!--
+        The DelimitedPayloadTokenFilter can put payloads on tokens... for example,
+        a token of "foo|1.4"  would be indexed as "foo" with a payload of 1.4f
+        Attributes of the DelimitedPayloadTokenFilterFactory : 
+         "delimiter" - a one character delimiter. Default is | (pipe)
+	 "encoder" - how to encode the following value into a playload
+	    float -> org.apache.lucene.analysis.payloads.FloatEncoder,
+	    integer -> o.a.l.a.p.IntegerEncoder
+	    identity -> o.a.l.a.p.IdentityEncoder
+            Fully Qualified class name implementing PayloadEncoder, Encoder must have a no arg constructor.
+         -->
+        <filter class="solr.DelimitedPayloadTokenFilterFactory" encoder="float"/>
+      </analyzer>
+    </fieldtype>
+
+    <!-- lowercases the entire field value, keeping it as a single token.  -->
+    <fieldType name="lowercase" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.KeywordTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory" />
+      </analyzer>
+    </fieldType>
+
+    <!-- 
+      Example of using PathHierarchyTokenizerFactory at index time, so
+      queries for paths match documents at that path, or in descendent paths
+    -->
+    <fieldType name="descendent_path" class="solr.TextField">
+      <analyzer type="index">
+	<tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" />
+      </analyzer>
+      <analyzer type="query">
+	<tokenizer class="solr.KeywordTokenizerFactory" />
+      </analyzer>
+    </fieldType>
+    <!-- 
+      Example of using PathHierarchyTokenizerFactory at query time, so
+      queries for paths match documents at that path, or in ancestor paths
+    -->
+    <fieldType name="ancestor_path" class="solr.TextField">
+      <analyzer type="index">
+	<tokenizer class="solr.KeywordTokenizerFactory" />
+      </analyzer>
+      <analyzer type="query">
+	<tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" />
+      </analyzer>
+    </fieldType>
+
+    <!-- since fields of this type are by default not stored or indexed,
+         any data added to them will be ignored outright.  --> 
+    <fieldtype name="ignored" stored="false" indexed="false" multiValued="true" class="solr.StrField" />
+
+    <!-- This point type indexes the coordinates as separate fields (subFields)
+      If subFieldType is defined, it references a type, and a dynamic field
+      definition is created matching *___<typename>.  Alternately, if 
+      subFieldSuffix is defined, that is used to create the subFields.
+      Example: if subFieldType="double", then the coordinates would be
+        indexed in fields myloc_0___double,myloc_1___double.
+      Example: if subFieldSuffix="_d" then the coordinates would be indexed
+        in fields myloc_0_d,myloc_1_d
+      The subFields are an implementation detail of the fieldType, and end
+      users normally should not need to know about them.
+     -->
+    <fieldType name="point" class="solr.PointType" dimension="2" subFieldSuffix="_d"/>
+
+    <!-- A specialized field for geospatial search. If indexed, this fieldType must not be multivalued. -->
+    <fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
+
+    <!-- An alternative geospatial field type new to Solr 4.  It supports multiValued and polygon shapes.
+      For more information about this and other Spatial fields new to Solr 4, see:
+      http://wiki.apache.org/solr/SolrAdaptersForLuceneSpatial4
+    -->
+    <fieldType name="location_rpt" class="solr.SpatialRecursivePrefixTreeFieldType"
+        geo="true" distErrPct="0.025" maxDistErr="0.000009" units="degrees" />
+
+   <!-- Money/currency field type. See http://wiki.apache.org/solr/MoneyFieldType
+        Parameters:
+          defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
+          precisionStep:   Specifies the precisionStep for the TrieLong field used for the amount
+          providerClass:   Lets you plug in other exchange provider backend:
+                           solr.FileExchangeRateProvider is the default and takes one parameter:
+                             currencyConfig: name of an xml file holding exchange rates
+                           solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
+                             ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
+                             refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
+   -->
+    <fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
+             
+
+
+   <!-- some examples for different languages (generally ordered by ISO code) -->
+
+    <!-- Arabic -->
+    <fieldType name="text_ar" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- for any non-arabic -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ar.txt" enablePositionIncrements="true"/>
+        <!-- normalizes ﻯ to ﻱ, etc -->
+        <filter class="solr.ArabicNormalizationFilterFactory"/>
+        <filter class="solr.ArabicStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Bulgarian -->
+    <fieldType name="text_bg" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/> 
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_bg.txt" enablePositionIncrements="true"/>
+        <filter class="solr.BulgarianStemFilterFactory"/>       
+      </analyzer>
+    </fieldType>
+    
+    <!-- Catalan -->
+    <fieldType name="text_ca" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- removes l', etc -->
+        <filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_ca.txt"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ca.txt" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Catalan"/>       
+      </analyzer>
+    </fieldType>
+    
+    <!-- CJK bigram (see text_ja for a Japanese configuration using morphological analysis) -->
+    <fieldType name="text_cjk" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- normalize width before bigram, as e.g. half-width dakuten combine  -->
+        <filter class="solr.CJKWidthFilterFactory"/>
+        <!-- for any non-CJK -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.CJKBigramFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Czech -->
+    <fieldType name="text_cz" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_cz.txt" enablePositionIncrements="true"/>
+        <filter class="solr.CzechStemFilterFactory"/>       
+      </analyzer>
+    </fieldType>
+    
+    <!-- Danish -->
+    <fieldType name="text_da" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_da.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Danish"/>       
+      </analyzer>
+    </fieldType>
+    
+    <!-- German -->
+    <fieldType name="text_de" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_de.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.GermanNormalizationFilterFactory"/>
+        <filter class="solr.GermanLightStemFilterFactory"/>
+        <!-- less aggressive: <filter class="solr.GermanMinimalStemFilterFactory"/> -->
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="German2"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Greek -->
+    <fieldType name="text_el" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- greek specific lowercase for sigma -->
+        <filter class="solr.GreekLowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="false" words="lang/stopwords_el.txt" enablePositionIncrements="true"/>
+        <filter class="solr.GreekStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Spanish -->
+    <fieldType name="text_es" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_es.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SpanishLightStemFilterFactory"/>
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="Spanish"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Basque -->
+    <fieldType name="text_eu" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_eu.txt" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Basque"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Persian -->
+    <fieldType name="text_fa" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <!-- for ZWNJ -->
+        <charFilter class="solr.PersianCharFilterFactory"/>
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.ArabicNormalizationFilterFactory"/>
+        <filter class="solr.PersianNormalizationFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_fa.txt" enablePositionIncrements="true"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Finnish -->
+    <fieldType name="text_fi" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_fi.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Finnish"/>
+        <!-- less aggressive: <filter class="solr.FinnishLightStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- French -->
+    <fieldType name="text_fr" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- removes l', etc -->
+        <filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_fr.txt"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_fr.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.FrenchLightStemFilterFactory"/>
+        <!-- less aggressive: <filter class="solr.FrenchMinimalStemFilterFactory"/> -->
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="French"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Irish -->
+    <fieldType name="text_ga" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- removes d', etc -->
+        <filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_ga.txt"/>
+        <!-- removes n-, etc. position increments is intentionally false! -->
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/hyphenations_ga.txt" enablePositionIncrements="false"/>
+        <filter class="solr.IrishLowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ga.txt" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Irish"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Galician -->
+    <fieldType name="text_gl" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_gl.txt" enablePositionIncrements="true"/>
+        <filter class="solr.GalicianStemFilterFactory"/>
+        <!-- less aggressive: <filter class="solr.GalicianMinimalStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Hindi -->
+    <fieldType name="text_hi" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <!-- normalizes unicode representation -->
+        <filter class="solr.IndicNormalizationFilterFactory"/>
+        <!-- normalizes variation in spelling -->
+        <filter class="solr.HindiNormalizationFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_hi.txt" enablePositionIncrements="true"/>
+        <filter class="solr.HindiStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Hungarian -->
+    <fieldType name="text_hu" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_hu.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Hungarian"/>
+        <!-- less aggressive: <filter class="solr.HungarianLightStemFilterFactory"/> -->   
+      </analyzer>
+    </fieldType>
+    
+    <!-- Armenian -->
+    <fieldType name="text_hy" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_hy.txt" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Armenian"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Indonesian -->
+    <fieldType name="text_id" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_id.txt" enablePositionIncrements="true"/>
+        <!-- for a less aggressive approach (only inflectional suffixes), set stemDerivational to false -->
+        <filter class="solr.IndonesianStemFilterFactory" stemDerivational="true"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Italian -->
+    <fieldType name="text_it" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- removes l', etc -->
+        <filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_it.txt"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_it.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.ItalianLightStemFilterFactory"/>
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="Italian"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Japanese using morphological analysis (see text_cjk for a configuration using bigramming)
+
+         NOTE: If you want to optimize search for precision, use default operator AND in your query
+         parser config with <solrQueryParser defaultOperator="AND"/> further down in this file.  Use 
+         OR if you would like to optimize for recall (default).
+    -->
+    <fieldType name="text_ja" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false">
+      <analyzer>
+      <!-- Kuromoji Japanese morphological analyzer/tokenizer (JapaneseTokenizer)
+
+           Kuromoji has a search mode (default) that does segmentation useful for search.  A heuristic
+           is used to segment compounds into its parts and the compound itself is kept as synonym.
+
+           Valid values for attribute mode are:
+              normal: regular segmentation
+              search: segmentation useful for search with synonyms compounds (default)
+            extended: same as search mode, but unigrams unknown words (experimental)
+
+           For some applications it might be good to use search mode for indexing and normal mode for
+           queries to reduce recall and prevent parts of compounds from being matched and highlighted.
+           Use <analyzer type="index"> and <analyzer type="query"> for this and mode normal in query.
+
+           Kuromoji also has a convenient user dictionary feature that allows overriding the statistical
+           model with your own entries for segmentation, part-of-speech tags and readings without a need
+           to specify weights.  Notice that user dictionaries have not been subject to extensive testing.
+
+           User dictionary attributes are:
+                     userDictionary: user dictionary filename
+             userDictionaryEncoding: user dictionary encoding (default is UTF-8)
+
+           See lang/userdict_ja.txt for a sample user dictionary file.
+
+           Punctuation characters are discarded by default.  Use discardPunctuation="false" to keep them.
+
+           See http://wiki.apache.org/solr/JapaneseLanguageSupport for more on Japanese language support.
+        -->
+        <tokenizer class="solr.JapaneseTokenizerFactory" mode="search"/>
+        <!--<tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>-->
+        <!-- Reduces inflected verbs and adjectives to their base/dictionary forms (辞書形) -->
+        <filter class="solr.JapaneseBaseFormFilterFactory"/>
+        <!-- Removes tokens with certain part-of-speech tags -->
+        <filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt" enablePositionIncrements="true"/>
+        <!-- Normalizes full-width romaji to half-width and half-width kana to full-width (Unicode NFKC subset) -->
+        <filter class="solr.CJKWidthFilterFactory"/>
+        <!-- Removes common tokens typically not useful for search, but have a negative effect on ranking -->
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt" enablePositionIncrements="true" />
+        <!-- Normalizes common katakana spelling variations by removing any last long sound character (U+30FC) -->
+        <filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
+        <!-- Lower-cases romaji characters -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Latvian -->
+    <fieldType name="text_lv" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_lv.txt" enablePositionIncrements="true"/>
+        <filter class="solr.LatvianStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Dutch -->
+    <fieldType name="text_nl" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_nl.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.StemmerOverrideFilterFactory" dictionary="lang/stemdict_nl.txt" ignoreCase="false"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Dutch"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Norwegian -->
+    <fieldType name="text_no" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_no.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Norwegian"/>
+        <!-- less aggressive: <filter class="solr.NorwegianLightStemFilterFactory"/> -->
+        <!-- singular/plural: <filter class="solr.NorwegianMinimalStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Portuguese -->
+    <fieldType name="text_pt" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_pt.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.PortugueseLightStemFilterFactory"/>
+        <!-- less aggressive: <filter class="solr.PortugueseMinimalStemFilterFactory"/> -->
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="Portuguese"/> -->
+        <!-- most aggressive: <filter class="solr.PortugueseStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Romanian -->
+    <fieldType name="text_ro" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ro.txt" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Romanian"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Russian -->
+    <fieldType name="text_ru" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ru.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Russian"/>
+        <!-- less aggressive: <filter class="solr.RussianLightStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Swedish -->
+    <fieldType name="text_sv" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_sv.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Swedish"/>
+        <!-- less aggressive: <filter class="solr.SwedishLightStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Thai -->
+    <fieldType name="text_th" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.ThaiWordFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_th.txt" enablePositionIncrements="true"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Turkish -->
+    <fieldType name="text_tr" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.TurkishLowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="false" words="lang/stopwords_tr.txt" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Turkish"/>
+      </analyzer>
+    </fieldType>
+
+ </types>
+  
+  <!-- Similarity is the scoring routine for each document vs. a query.
+       A custom Similarity or SimilarityFactory may be specified here, but 
+       the default is fine for most applications.  
+       For more info: http://wiki.apache.org/solr/SchemaXml#Similarity
+    -->
+  <!--
+     <similarity class="com.example.solr.CustomSimilarityFactory">
+       <str name="paramkey">param value</str>
+     </similarity>
+    -->
+
+</schema>
diff --git a/0.8.1-rc1/filemgr/src/main/resources/sdschema.sql b/0.8.1-rc1/filemgr/src/main/resources/sdschema.sql
new file mode 100644
index 0000000..1b9d9c1
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/sdschema.sql
@@ -0,0 +1,85 @@
+--- 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.
+
+--
+-- Table structure for table `dataPoint`
+--
+
+CREATE TABLE `dataPoint` (
+  `dataPoint_id` int(10) unsigned NOT NULL auto_increment,
+  `granule_id` int(10) unsigned NOT NULL,
+  `dataset_id` int(10) unsigned NOT NULL,
+  `parameter_id` int(10) unsigned NOT NULL,
+  `time` datetime default NULL,
+  `latitude` double default NULL,
+  `longitude` double default NULL,
+  `vertical` double default NULL,
+  `value` double default NULL,
+  PRIMARY KEY  (`dataPoint_id`)
+) ENGINE=MyISAM AUTO_INCREMENT=1143297 DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `dataset`
+--
+
+CREATE TABLE `dataset` (
+  `dataset_id` int(10) unsigned NOT NULL auto_increment,
+  `longName` varchar(120) default NULL,
+  `shortName` varchar(60) default NULL,
+  `description` text,
+  `source` varchar(255) default NULL,
+  `referenceURL` varchar(255) default NULL,
+  PRIMARY KEY  (`dataset_id`)
+) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `dpMap`
+--
+
+CREATE TABLE `dpMap` (
+  `dataset_id` int(10) unsigned NOT NULL,
+  `parameter_id` int(10) unsigned NOT NULL,
+  PRIMARY KEY  (`dataset_id`,`parameter_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `granule`
+--
+CREATE TABLE `granule` (
+  `granule_id` int(10) unsigned NOT NULL auto_increment,
+  `dataset_id` int(10) unsigned default NULL,
+  `filename` varchar(255) NOT NULL,
+  PRIMARY KEY  (`granule_id`),
+  KEY `dataset_id` (`dataset_id`)
+) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `parameter`
+--
+
+CREATE TABLE `parameter` (
+  `parameter_id` int(10) unsigned NOT NULL auto_increment,
+  `longName` varchar(120) default NULL,
+  `shortName` varchar(60) default NULL,
+  `description` text,
+  `referenceURL` varchar(255) default NULL,
+  `cellMethod` text,
+  `missingDataFlag` float default NULL,
+  `units` varchar(60) default NULL,
+  `verticalUnits` varchar(120) default NULL,
+  `database` varchar(80) NOT NULL,
+  `dataset_id` int(10) unsigned NOT NULL,
+  PRIMARY KEY  (`parameter_id`)
+) ENGINE=MyISAM AUTO_INCREMENT=41 DEFAULT CHARSET=latin1;
diff --git a/0.8.1-rc1/filemgr/src/main/resources/tcsh_aliases.txt b/0.8.1-rc1/filemgr/src/main/resources/tcsh_aliases.txt
new file mode 100644
index 0000000..9da0904
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/main/resources/tcsh_aliases.txt
@@ -0,0 +1,30 @@
+#  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.
+#
+###############TCSH SHELL ALIASES###############
+#
+# The following aliases must be used within a filemgr's
+# bin directory since relative pathing is being used.  This block also
+# assumes that the filemgr is running on port 9000 (the default port of filemgr)
+#
+# For complete documentation see: 
+#     https://cwiki.apache.org/confluence/display/OODT/BASH+and+TCSH+shell+tools+for+File+Manager
+#
+alias lucenequery 'java -Dorg.apache.oodt.cas.filemgr.properties=../etc/filemgr.properties -Djava.ext.dirs=../lib org.apache.oodt.cas.filemgr.tools.QueryTool --url http://localhost:9000 --lucene -query '
+alias sqlquery 'java -Dorg.apache.oodt.cas.filemgr.properties=../etc/filemgr.properties -Djava.ext.dirs=../lib org.apache.oodt.cas.filemgr.tools.QueryTool --url http://localhost:9000 --sql -query '
+alias fmdel 'java -Dorg.apache.oodt.cas.filemgr.properties=../etc/filemgr.properties -Djava.ext.dirs=../lib org.apache.oodt.cas.filemgr.tools.DeleteProduct --fileManagerUrl http://localhost:9000 --read'
+alias metdump 'java -Djava.ext.dirs=../lib org.apache.oodt.cas.filemgr.tools.MetadataDumper --url http://localhost:9000 --out . --productId '
+#
+################################################
\ No newline at end of file
diff --git a/0.8.1-rc1/filemgr/src/site/resources/css/guides.css b/0.8.1-rc1/filemgr/src/site/resources/css/guides.css
new file mode 100644
index 0000000..df4af72
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/resources/css/guides.css
@@ -0,0 +1,44 @@
+/*
+  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.
+*/
+
+.info, .success, .warning, .error, .validation {
+border: 1px solid;
+margin: 10px 0px;
+padding:15px 10px 15px 50px;
+background-repeat: no-repeat;
+background-position: 10px center;
+}
+.info {
+color: #00529B;
+background-color: #BDE5F8;
+background-image: url('../images/info.png');
+}
+.success {
+color: #4F8A10;
+background-color: #DFF2BF;
+background-image:url('../images/success.png');
+}
+.warning {
+color: #9F6000;
+background-color: #FEEFB3;
+background-image: url('../images/warning.png');
+}
+.error {
+color: #D8000C;
+background-color: #FFBABA;
+background-image: url('../images/error.png');
+}
diff --git a/0.8.1-rc1/filemgr/src/site/resources/images/cas-filemgr.jpg b/0.8.1-rc1/filemgr/src/site/resources/images/cas-filemgr.jpg
new file mode 100644
index 0000000..a3ddd78
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/resources/images/cas-filemgr.jpg
Binary files differ
diff --git a/0.8.1-rc1/filemgr/src/site/resources/images/cas-filemgr.psd b/0.8.1-rc1/filemgr/src/site/resources/images/cas-filemgr.psd
new file mode 100644
index 0000000..12450a9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/resources/images/cas-filemgr.psd
Binary files differ
diff --git a/0.8.1-rc1/filemgr/src/site/resources/images/error.png b/0.8.1-rc1/filemgr/src/site/resources/images/error.png
new file mode 100644
index 0000000..e1b169d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/resources/images/error.png
Binary files differ
diff --git a/0.8.1-rc1/filemgr/src/site/resources/images/fm_arch.jpg b/0.8.1-rc1/filemgr/src/site/resources/images/fm_arch.jpg
new file mode 100644
index 0000000..92318ec
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/resources/images/fm_arch.jpg
Binary files differ
diff --git a/0.8.1-rc1/filemgr/src/site/resources/images/fm_extension_points.png b/0.8.1-rc1/filemgr/src/site/resources/images/fm_extension_points.png
new file mode 100644
index 0000000..5b72c98
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/resources/images/fm_extension_points.png
Binary files differ
diff --git a/0.8.1-rc1/filemgr/src/site/resources/images/fm_object_model.png b/0.8.1-rc1/filemgr/src/site/resources/images/fm_object_model.png
new file mode 100644
index 0000000..189f518
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/resources/images/fm_object_model.png
Binary files differ
diff --git a/0.8.1-rc1/filemgr/src/site/resources/images/fm_use_case1.png b/0.8.1-rc1/filemgr/src/site/resources/images/fm_use_case1.png
new file mode 100644
index 0000000..e8a04fe
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/resources/images/fm_use_case1.png
Binary files differ
diff --git a/0.8.1-rc1/filemgr/src/site/resources/images/info.png b/0.8.1-rc1/filemgr/src/site/resources/images/info.png
new file mode 100644
index 0000000..fc5f780
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/resources/images/info.png
Binary files differ
diff --git a/0.8.1-rc1/filemgr/src/site/resources/images/success.png b/0.8.1-rc1/filemgr/src/site/resources/images/success.png
new file mode 100644
index 0000000..758f7df
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/resources/images/success.png
Binary files differ
diff --git a/0.8.1-rc1/filemgr/src/site/resources/images/warning.png b/0.8.1-rc1/filemgr/src/site/resources/images/warning.png
new file mode 100644
index 0000000..e6705f7
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/resources/images/warning.png
Binary files differ
diff --git a/0.8.1-rc1/filemgr/src/site/site.xml b/0.8.1-rc1/filemgr/src/site/site.xml
new file mode 100644
index 0000000..c7f16f9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/site.xml
@@ -0,0 +1,32 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<project name="cas-filemgr">
+
+  <body>
+    <links>
+      <item name="OODT" href="../oodt-site/"/>
+    </links>
+
+    <menu ref="reports" inherit="bottom"/>
+    <menu name="Software Documentation">
+      <item name="Developer Guide" href="development/developer.html"/>
+      <item name="Basic User Guide" href="user/basic.html"/>
+      <item name="Advanced User Guide" href="user/advanced.html"/>
+    </menu>
+  </body>
+</project>
diff --git a/0.8.1-rc1/filemgr/src/site/xdoc/development/developer.xml b/0.8.1-rc1/filemgr/src/site/xdoc/development/developer.xml
new file mode 100644
index 0000000..1a679b8
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/xdoc/development/developer.xml
@@ -0,0 +1,377 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS File Manager Developer Guide</title>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+      <author email="woollard@jpl.nasa.gov">Dave Woollard</author>
+   </properties>
+
+   <body>
+   
+      <section name="Introduction">
+        <p>
+          This is the developer guide for the Apache OODT Catalog and Archive Service (CAS) 
+          File Manager component, or File Manager for short. Primarily, this guide 
+          will explain the File Manager architecture and interfaces, including its 
+          tailorable extension points. For information on installation, configuration,
+          and examples, please see our <a href="../user/basic.html">User Guides.</a>
+          
+          <p>The remainder of this guide is separated into the following sections:</p>
+      <ul>
+        <li><a href="#section1">Project Description</a></li>
+        <li><a href="#section2">Architecture</a></li>
+        <li><a href="#section3">Extension Points</a></li>
+        <li><a href="#section4">Current Extension Point Implementations</a></li>
+      </ul>
+          
+        </p>     
+      </section>
+      
+      <a name="section1"/>
+      <section name="Project Description">
+        <p>The File Manager component is responsible for tracking, ingesting and moving 
+        file data and metadata between a client system and a server system. The File 
+        Manager is an extensible software component that provides an XML-RPC external 
+        interface, and a fully tailorable Java-based API for file management.</p> 
+      </section>
+      
+      <a name="section2"/>
+      <section name="Architecture">
+      
+        <p>In this section, we will describe the architecture of the File Manager,
+        including its constituent components, object model, and key capabilities.</p>
+      
+        <subsection name="Components">
+        
+        <p>The major components of the File Manager are the Client and Server, the 
+        Repository Manager, the Catalog, the Validation Layer, the Versioner, and 
+        the Transferer. The relationship between all of these components are shown in
+        the diagram below:</p>
+        
+        <p><img src="../images/fm_extension_points.png" alt="File Manager Architecture"/></p>
+        
+        <p>The File Manager Server contains both a Repository that manages products 
+        (and the products' location in the archive as specified by Versioner), and a
+        Catalog that validates metadata via the Validation Layer. Transfer of data 
+        products from the Client to the Server is the domain of the Transfer and can 
+        be initiated at either the Client or the Server.</p> 
+        
+        </subsection>
+        <subsection name="Object Model">
+        <p>The critical objects managed by the File Manager include:</p>
+        
+        <ul>
+          <li><strong>Products</strong> - Collections of one or more files, and their 
+          associated Metadata.</li>
+          
+          <li><strong>Metadata</strong> - A map of key->multiple values of descriptive 
+          information about a Product. See 
+          <a href="../../metadata/">CAS-Metadata</a> for more 
+          information on Metadata.</li>
+          
+          <li><strong>Reference</strong> - A pointer to a Product file's (or files') 
+          original location, and to its final resting location within the archive 
+          constructed by the File Manager.</li>
+          
+          <li><strong>Product Type</strong> - Descriptive information about a Product 
+          that includes what type of file URI generation scheme to use, the root 
+          repository location for a particular Product, and a description of the 
+          Product.</li>
+          
+          <li><strong>Element</strong> - A singular Metadata element, such as "Author", 
+          or "Creator". Elements may have additional metadata, in the form of the 
+          associated definition and even a corresponding 
+          <a href="http://dublincore.org/">Dublin Core</a> attribute. See 
+          <a href="../../metadata/">CAS-Metadata</a> for more 
+          information on Metadata Elements.</li>
+          
+          <li><strong>Versioner</strong> - A URI generation scheme for Product Types 
+          that defines the location within the archive (built by the File Manager) 
+          where a file belonging to a Product (that belongs to the associated Product 
+          Type) should be placed.</li>
+        </ul>
+
+        <p>Each Product contains 1 or more References, and one Metadata object. Each 
+        Product is a member of a single Product Type. The Metadata collected for each 
+        Product is defined by a mapping of Product Type->1...* Elements. Each Product 
+        Type has an associated Versioner. These relationships are shown in the below 
+        figure.</p>
+        
+        <img src="../images/fm_object_model.png" alt="File Manager Object Model"/> 
+        </subsection> 
+      
+        <subsection name="Key Capabilities">
+        <p>The File manager has been designed with a new of key capabilities in mind.
+        These capabilities include:</p>
+        
+        <p><strong>Easy management of different types of Products.</strong> The 
+        Repository Manager extension point is responsible for managing Product Types, 
+        and their associated information. Management of Product Types includes adding 
+        new types, deleting and updating existing types, and retrieving Product Type 
+        Objects, by their ID or by their name.</p>
+          
+        <p><strong>Support for different kinds of back end catalogs.</strong> The 
+        Catalog extension point allows Product instance metadata and file location 
+        information to be stored in different types of back end data stores quite 
+        easily. Existing implementations of the Catalog interface include a JDBC based 
+        back end database, along with a flat-file index powered by 
+        <a href="http://lucene.apache.org/">Lucene.</a></p>
+          
+        <p><strong>Management of Product instance information.</strong> Management 
+        includes adding, deleting and updating product instance information, including 
+        file locations (References), along with Product Metadata. It also includes 
+        retrieving Metadata and References associated with existing Products as well 
+        as obtaining the Products themselves.</p>
+          
+        <p><strong>Element management for Metadata.</strong> The File Manager's 
+        Validation Layer extension point allows for the management of Element policy 
+        information in different types of back end stores. For instance, Element policy 
+        could be stored in XML files, a Database, or a Metadata Registry.</p>
+          
+        <p><strong>Data transfer mechanism interface.</strong> By having 
+        an extension point for Data Transfer, the File Manager can support different 
+        Data Transfer protocols, both local and remote.</p>
+          
+        <p><strong>Advanced support for File Repository layouts.</strong> 
+        The Versioner extension point allows for different File Repository layouts 
+        based on Product Types.</p>
+          
+        <p><strong>Support for multiple Product structures.</strong> The File Manager 
+        Client allows for Products to be Flat, or Hierarchical-based. Flat products 
+        are collections of singular files that are aggregated together to make a 
+        Product. Hierarchical Products are Products that contain collections of 
+        directories, and sub-directories, and files.</p>
+          
+        <p><strong>Design for scalability.</strong> The File Manager uses the popular 
+        client-server paradigm, allowing new File Manager servers to be instantiated, 
+        as needed, without affecting the File Manager clients, and vice-versa.</p>
+          
+        <p><strong>Standard communication protocols.</strong> The File Manager uses 
+        XML-RPC as its main external interface between the File Manager client and 
+        server. XML-RPC, the little brother of SOAP, is fast, extensible, and uses 
+        the underlying HTTP protocol for data transfer.</p>
+          
+        <p><strong>RSS-based Product syndication.</strong> The File Manager web 
+        interface allows for the RSS-based syndication of Product feeds based on 
+        Product Type.</p>
+          
+        <p><strong>Data transfer status tracking.</strong> The File Manager tracks 
+        all current Product and File transfers and even publishes an RSS-feed of 
+        existing transfers.</p>
+         
+        <p>This capability set is not exhaustive, and is meant to give the user a 
+        <i>feel</i> for what general features are provided by the File Manager. Most 
+        likely the user will find that the File Manager provides many other 
+        capabilities besides those described here.</p>
+          
+        </subsection>
+      </section>
+      
+      <a name="section3"/>
+      <section name="Extension Points">
+          <p>We have constructed the File Manager making use of the <i>factory 
+          method pattern</i> to provide multiple extension points for the File Manager. An 
+          extension point is an interface within the File Manager that can have many 
+          implementations. This is particularly useful when it comes to software 
+          component configuration because it allows different implementations of 
+          an existing interface to be selected at deployment time.</p> 
+          
+          <div class="info">The factory method pattern is a creational pattern common to
+          object oriented design. Each File Manager extension point involves the 
+          implementation of two interfaces: an <i>extension factory</i> and an 
+          <i>extension</i> implementation. At run-time, the File Manager loads a 
+          properties file specifies a factory class to use during extension point
+          instantiation. For example, the File Manager may communicate with a 
+          database-based Catalog and an XML-based Element Store (called a Validation 
+          Layer), or it may use a Lucene-based Catalog and a database-based Validation 
+          Layer.</div> 
+          
+          <p>Using extension points, it is fairly simple to support many different types 
+          of what are typically referred to as "plug-in architectures." Each of the core 
+          extension points for the File Manager is described below:</p>
+          
+          <table>
+            <tr>
+              <td>Catalog</td>
+              <td>The Catalog extension point is responsible for storing all the 
+              instance data for Products, Metadata, and for file References. 
+              Additionally, the Catalog provides a query capability for Products.
+              </td>
+            </tr>
+            <tr>
+              <td>Data Transfer</td>
+              <td>The Data Transfer extension point allows for the movement of a 
+              Product to and from the archive managed by the File Manager component. 
+              Different protocols for Data Transfer may include local (disk-based) 
+              copy, or remote XML-RPC based transfer across networked machines.
+              </td>
+            </tr>
+            <tr>
+              <td>Repository Manager</td>
+              <td>The Repository Manager extension point provides a means for 
+              managing all of the policy information (i.e., the Product Types and 
+              their associated information) for Products managed by the File Manager. 
+              </td>
+            </tr>
+            <tr>
+              <td>Validation Layer</td>
+              <td>The Validation Layer extension point allows for the querying of 
+              element definitions associated with a particular Product Type. The 
+              extension point also maps Product Type to Elements.
+              </td>
+            </tr>
+             <tr>
+              <td>Versioning</td>
+              <td>The Versioning extension point allows for the definition of 
+              different URI generation schemes that define the final resting location 
+              of files for a particular Product.
+              </td>
+            </tr>
+             <tr>
+              <td>System</td>
+              <td>The extension point that provides the external interface to the 
+              File Manager services. This includes the File Manager server interface, 
+              as well as the associated File Manager client interface, that 
+              communicates with the server.
+              </td>
+            </tr>          
+          
+          </table>
+       </section>
+       
+       <a name="section4"/>   
+       <section name="Current Extension Point Implementations">
+        
+         <p>There are at least two implementations of all of the aforementioned 
+         extension points for the File Manager. Each extension point implementation 
+         is detailed in this section.</p>
+
+         <subsection name="Catalog">
+            <ul>
+             <li><strong>Data Source based Catalog.</strong> An implementation of 
+             the Catalog extension point interface that uses a JDBC accessible database 
+             backend.</li>
+             
+             <li><strong>Lucene based Catalog.</strong> An implementation of the 
+             Catalog extension point interface that uses the 
+             <a href="http://lucene.apache.org/">Lucene</a> free text index system to 
+             store Product instance information.</li>
+           </ul>
+         </subsection> 
+         
+         <subsection name="Data Transfer">
+             <ul>   
+               <li><strong>Local Data Transfer.</strong> An implementation of the Data 
+               Transfer interface that uses Apache's 
+               <a href="http://jakarta.apache.org/commons-io/">commons-io</a> to perform 
+               local, disk based filesystem data transfer. This implementation also 
+               supports locally accessible Network File System (NFS) disks.</li>
+               
+               <li><strong>Remote Data Transfer.</strong> An implementation of the Data 
+               Transfer interface that uses the XML-RPC File Manager client to transfer 
+               files to a remote XML-RPC File Manager server.</li>
+               
+               <li><strong>InPlace Data Transfer.</strong> An implementation of the Data 
+               Transfer interface that avoids transfering any products -- this can be used 
+               in the situation where metadata about a particular product should be 
+               recorded, but no physical transfer needs to occur.</li>
+             </ul>     
+         </subsection>
+         
+         <subsection name="Repository Manager">
+             <ul>
+               <li><strong>Data Source based Repository Manager.</strong> An 
+               implementation of the Repository Manager extension point that stores 
+               Product Type policy information in a JDBC accessible database.</li>
+               
+               <li><strong>XML based Repository Manager.</strong> An implementation of 
+               the Repository Manager extension point that stores Product Type policy 
+               information in an XML file called <code>product-types.xml</code></li>
+             </ul>
+         </subsection>
+         
+         <subsection name="Validation Layer">
+             <ul>
+               <li><strong>Data Source based Validation Layer.</strong> An 
+               implementation of the Validation Layer extension point that stores 
+               Element policy information in a JDBC accessible database.</li>
+               
+               <li><strong>XML based Validation Layer.</strong> An implementation of 
+               the Validation Layer extension point that stores Element policy 
+               information in 2 XML files called <code>elements.xml</code> and 
+               <code>product-type-element-map.xml</code></li>
+             </ul>
+         </subsection>
+         
+         <subsection name="System (File Manager client and File Manager server)">        
+             <ul>
+               <li><strong>XML-RPC based File Manager server.</strong> An 
+               implementation of the external server interface for the File Manager that 
+               uses XML-RPC as the transportation medium.</li>
+               
+               <li><strong>XML-RPC based File Manager client.</strong> An 
+               implementation of the client interface for the XML-RPC File Manager 
+               server that uses XML-RPC as the transportation medium.</li>
+             </ul>
+         </subsection> 
+         
+      </section>
+      
+      <section name="Use Cases">
+        <p>
+          The File Manager was built to support several of the above capabilities outlined in 
+          Section 3. In particular there were several use cases that we wanted to support, some 
+          of which are described below.        
+        </p>
+      
+         <img src="../images/fm_use_case1.png" alt="File Manager Ingest Use Case"/>
+         
+         <p>The red numbers in the above Figure correspond to a sequence of steps that occurs and a 
+         series of interactions between the different File Manager extension points in order to 
+         perform the file ingestion activity. In Step 1, a File Manager client is invoked for the 
+         ingest operation, which sends Metadata and References for a particular Product to ingest 
+         to the File Manager server’s System Interface extension point. The System Interface uses 
+         the information about Product Type policy made available by the Repository Manager in order 
+         to understand whether or not the product should be transferred, where it’s root repository 
+         path should be, and so on. The System Interface then catalogs the file References and Metadata 
+         using the Catalog extension point. During this catalog process, the Catalog extension point 
+         uses the Validation Layer to determine which Elements should be extracted for the particular 
+         Product, based upon its Product Type. After that, Data Transfer is initiated either at the 
+         client or server end, and the first step to Data Transfer is using the Product’s associated 
+         Versioner to generate final file References. After final file References have been determined, 
+         the file data is transferred by the server or by the client, using the Data Transfer extension 
+         point.</p>
+      </section>      
+      
+      <section name="Conclusion">
+      <p>The aim of this document is to provide information relevant to developers
+      about the CAS File Manager. Specifically, this document has described the File 
+      Manager's architecture, including its constituent components, object model and
+      key capabilities. Additionally, the this document provides an overview of the 
+      current implementations of the File Manager's extension points.</p> 
+      
+      <p>In the <a href="../user/basic.html">Basic User Guide</a> and 
+      <a href="../user/advanced.html">Advanced User Guide</a>, we will cover topics
+      like installation, configuration, and example uses as well as advanced topics
+      like scaling and other tips and tricks.</p> 
+      
+      </section>
+
+   </body>
+</document>
diff --git a/0.8.1-rc1/filemgr/src/site/xdoc/development/maven.xml b/0.8.1-rc1/filemgr/src/site/xdoc/development/maven.xml
new file mode 100755
index 0000000..74ad022
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/xdoc/development/maven.xml
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+  <properties>
+    <title>Using Maven</title>
+    <author email="woollard@jpl.nasa.gov">David Woollard</author>
+  </properties>
+
+  <body>
+    <section name="Using Maven">
+      <p>OODT uses <a href="http://maven.apache.org/">Maven</a> for 
+      managing our build environment. Maven is an open source product from the 
+      <a href="http://www.apache.org/">Apache Software Foundation</a> that improves 
+      on <a href="http://ant.apache.org/">Ant</a> in the area of build management, 
+      which it turn was an improvement on Make. This document describes the use of 
+      Maven for Apache OODT build management.</p>
+    </section>
+    
+    <section name="Setup">
+      <p>Maven can be downloaded from the 
+      <a href="http://maven.apache.org/download.html">Maven Download</a> 
+      page. OODT is using version 2.0 and above. Maven was developed in Java so it 
+      will run on the popular platforms (e.g., Windows, Mac OSX, etc.). Beyond 
+      making sure the <i>mvn</i> executable is in your path, there is very little 
+      setup required.</p>
+
+      <p>Maven is based on the concept of a Project Object Model (POM) which is 
+      contained in the <i>pom.xml</i> file found at the root of each project. 
+      The POM allows Maven to manage a project's build, reporting and documentation. 
+      For OODT, much of the default information for managing the projects is 
+      contained in a parent POM, which is located in the <i>oodt-core</i> project. So, 
+      in order to build any of the other projects (e.g., cas-curator, cas-filemgr, 
+      etc.) the parent POM must be downloaded from the OODT Maven repository. The 
+      local <i>pom.xml</i> files for each of the projects have been configured to 
+      retrieve the parent POM automatically.</p>
+      
+      <p>Once Maven has been setup, the first step to building a project with Maven 
+      is to checkout a project's source code into the developer's work area. See the 
+      <a href="../development/subversion.html">Using Subversion</a> document for how to 
+      check out projects from the CM repository.</p>
+    </section>
+    
+    <section name="Project Structure">
+      <p>In order for default Maven functions to operate properly, there is a 
+      suggested project directory structure. The structure is as follows:</p>
+      
+      <source>
+/
+  src/             Source Code (everything)
+    main/            Program Source
+      assembly/        Package Descriptor
+      java/            Java Source
+      resources/       Scripts, Config File, etc.
+        ...
+    test/            Test Source
+      java/
+      resources/
+        ...
+    site/            Site Documentation
+      apt/             Docs in APT Format
+        index.apt
+        ...
+      xdoc/            Docs in XDOC Format
+        index.xml
+        ...
+      resources/
+        images/
+      site.xml         Menu Structure
+
+  target/          Build Results (binaries, docs and packages)
+    ...
+
+  LICENSE.txt
+  README.txt
+  pom.xml          Project Object Model (POM)
+      </source>
+    </section>
+    
+    <section name="Standard Commands">
+    <p>There are few standard commands that developers will use on a daily basis 
+    and they are related to building and cleaning a project.</p>
+    <subsection name="Build a Project">
+      <p>Build the project's libraries and executables with the following 
+      command:</p>
+      <source>
+mvn compile
+      </source>
+      <p>The above command will generate the artifacts in the <i>target/</i> 
+      directory.</p>      
+    </subsection>
+    <subsection name="Install a Project">
+      <p>Install the project's artifacts locally with the following command:</p>
+      <source>
+mvn install
+      </source>
+      <p>Prior to installation, the above command will compile the source code, 
+      if necessary, and execute the unit tests. The result of the above command 
+      is to install the generated artifacts (e.g. pom, jar, etc.) in the user's 
+      local Maven repository ($HOME/.m2/repository/). This is useful when the 
+      artifact is a dependency for another project but has yet to be deployed 
+      to the Maven repository.</p>
+    </subsection>
+    <subsection name="Package a Project">
+      <p>Create the project's distribution package with the following command:</p>
+      <source>
+mvn package
+      </source>
+      <p>Prior to package creation, the above command will compile the source 
+      code, if necessary, and execute the unit tests. The above command will 
+      create the package(s) in the target/ directory.</p>
+    </subsection>
+    <subsection name="Build a Project's Web Site">
+      <p>Build the project's web site with the following command:</p>
+      <source>
+mvn site
+      </source>
+      <p>The above command will generate the web site in the <i>target/site/</i>
+      directory. View the site by pointing your web browser at the 
+      <i>index.html</i> file within that directory.</p>
+    </subsection> 
+    <subsection name="Clean a Project">
+      <p>Clean out the project directory of generated artifacts with the 
+      following command:</p>
+      <source>
+mvn clean
+      </source>
+      <p>The above command will remove the <i>target/</i> directory and its 
+      contents.</p>
+    </subsection>
+    <subsection name="Useful Command Arguments">
+      <p>There a couple of useful arguments which can be appended to the 
+      commands above to limit the scope of the command.</p>
+      <p>In order to skip unit test execution, add the following argument:</p>
+      <source>
+mvn [command] -Dmaven.test.skip=true
+      </source>
+      <p>The above command is most useful with the <i>install</i>, 
+      <i>package</i> and <i>site</i> commands.</p>
+      <p>When a project has modules defined in the POM, the command can be 
+      performed against the top level of the project instead of the modules by 
+      adding the following argument:</p>
+      <source>
+mvn [command] --non-recursive
+      </source>
+    </subsection>
+    </section>
+    <section name="Acknowledgments">
+      <p>Much of the material in this Maven guide was originally authored 
+      by Sean Hardman under the sponsorship of NASA Jet Propulsion 
+      Laboratory's Planetary Data System. </p>
+    </section>
+    <section name="References">
+      <p>Here is a list of Maven resources:</p>
+      <ul>
+        <li><a href="http://maven.apache.org/guides/index.html">Online 
+        Documentation Index</a></li>
+      </ul>
+    </section>
+  </body>
+</document>
diff --git a/0.8.1-rc1/filemgr/src/site/xdoc/user/advanced.xml b/0.8.1-rc1/filemgr/src/site/xdoc/user/advanced.xml
new file mode 100644
index 0000000..7f38699
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/xdoc/user/advanced.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS File Manager User Guide</title>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+      <author email="woollard@jpl.nasa.gov">Dave Woollard</author>
+   </properties>
+
+   <body>
+      <div class="warning">This document is in the process of being reorganized as
+      part of our ongoing documentation effort. Please check back for updates.</div>  
+   
+      <section name="Introduction">
+      
+      <p>In the CAS File Manager Advanced User Guide, we will cover a number of 
+      advanced topics related to using the CAS File Manager, including situations
+      that have arisen in the authors' experiences regarding the use of multiple
+      catalogs within a singe File Manager, address scaling issues, etc. Basic
+      concepts, such as installation and configuration, can be found in the 
+      <a href="../user/basic.html">Basic User Guide</a>.</p>
+      
+      <p>The remainder of this guide is separated into the following sections:</p>
+      <ul>
+        <li><a href="#section1">Multiple Catalog Configuration</a></li>
+        <li><a href="#section2">Scaling Issues</a></li>
+      </ul>
+      
+      </section>
+      
+      <a name="section1"/>
+      <section name="Multiple Catalog Configuration">
+      <p>Coming Soon...</p>
+      </section>
+      
+      <a name="section2"/>
+      <section name="Scaling Issues">
+      <p>Coming Soon...</p>
+      </section>
+      
+   </body>
+</document> 
diff --git a/0.8.1-rc1/filemgr/src/site/xdoc/user/basic.xml b/0.8.1-rc1/filemgr/src/site/xdoc/user/basic.xml
new file mode 100644
index 0000000..2582c7b
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/xdoc/user/basic.xml
@@ -0,0 +1,362 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS File Manager User Guide</title>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+      <author email="woollard@jpl.nasa.gov">Dave Woollard</author>
+   </properties>
+
+   <body>
+      <div class="warning">This document is in the process of being reorganized as
+      part of our ongoing documentation effort. Please check back for updates.</div>
+      
+      <section name="Introduction">
+      
+      <p>This document serves as a basic user's guide for the CAS File Manager 
+      project. The goal of the document is to allow users to check out, build, and 
+      install a base version of the CAS File Manager.  Additional information can
+      be found at the <a href="http://cwiki.apache.org/confluence/display/OODT/OODT+Filemgr+User+Guide">
+      Filemgr User Guide Wiki Page</a>. For advanced topics, such as configuring the File 
+      Manager to Scale and other tips and tricks, please see our 
+      <a href="../user/advanced.html">Advanced Guide.</a></p>
+      
+      <p>The remainder of this guide is separated into the following sections:</p>
+      <ul>
+        <li><a href="#section1">Download and Build OODT</a></li>
+        <li><a href="#section2">Configuration in 2 Minutes or Less</a></li>
+        <!-- 
+        <li><a href="#section3">Learn By Example</a></li>
+         -->
+      </ul>  
+      </section> 
+     
+      <a name="section1"/>
+      <section name="Download and Build OODT">
+      <div class="info">
+        <p><b>Pre-Requisite:</b> Maven 2.x installed on your machine and Java 1.6.
+        If you have the correct versions of Java and Maven installed then proceed
+        with the build process for OODT which will also build the File Manager
+        component.
+        </p>
+      </div>
+      
+      <div class="warning">  
+        <p><b>Mac OS X Users:</b> Apple is now upgrading their OS to include Maven 3
+        by default, which is not compatible with Apache OODT's build process.  For more 
+        information on Maven, see our <a href="../development/maven.html">Maven Guide.</a>
+        To determine which version of Maven is installed on your machine type the following 
+        command into a terminal.</p>
+        
+        <source>
+>mvn --version
+Apache Maven 2.2.1 (r801777; 2009-08-07 04:16:01+0900)
+Java version: 1.6.0_26
+		</source>
+		
+		<p>If your system returns Apache Maven 3.X then you will need to install Maven 2.2.1 using the
+		following steps:  (NOTE: This will replace Maven 3 with Maven 2.2.1 as your systems default Maven version)</p>
+		
+		<p>1. Download apache-maven-2.2.1-bin tar file from <a href="http://maven.apache.org/">http://maven.apache.org</a></p>
+  		<p>2. Install maven to /usr/share/</p> 
+  		<source>
+>sudo tar xzvf apache-maven-2.2.1-bin.tar.gz -C /usr/share
+  		</source>
+  		<p>3. Now hook it in as the default maven.</p>
+		<source>
+>sudo rm /usr/bin/mvn
+>sudo rm /usr/share/maven
+>sudo ln -s /usr/share/apache-maven-2.2.1 /usr/share/maven
+>sudo ln -s /usr/share/maven/bin/mvn /usr/bin/mvn
+		</source>
+		<p>4. Double check the maven version</p>
+		<source>
+>mvn --version
+Apache Maven 2.2.1 ...
+		</source>
+		<p><b>Now you can proceed with the check out and build of Apache OODT</b></p>
+      </div>
+      <br/>
+      <div id="checkout_build">
+      <p><b>Create a Directory to Checkout Source Code:</b></p>
+        <source>
+>mkdir /usr/local/src
+>cd /usr/local/src        
+		</source>
+		<p><b>Using a Tagged Release:</b></p>
+		<source>
+>svn co http://svn.apache.org/repos/asf/oodt/tags/{release_number}/ oodt
+        </source>
+		<p><b>Using the Latest Development Trunk:</b></p>
+		<source>
+>svn co http://svn.apache.org/repos/asf/oodt/trunk/ oodt
+        </source>
+        <p>Once the subversion command completes you should have a directory at <code>/usr/local/src/oodt</code>
+        which will contain all of the source code for OODT.  In order to build the project from source, 
+        issue the following commands:</p>
+        <source>
+>cd /usr/local/src/oodt
+>mvn clean install        
+        </source>
+        <p>Once you get the Maven Build Successful message you can proceed with the installation 
+        of the CAS-FileManager.</p>
+        <source>
+>mkdir /usr/local/oodt
+>cd filemgr/target
+>tar xzvf cas-filemgr-{version#}-dist.tar.gz -C /usr/local/oodt
+>cd /usr/local/oodt
+>ln -s cas-filemgr-{version#}/ cas-filemgr
+        </source>
+        </div>
+        <h3>
+        Our latest updated File Manager documentation has moved to the OODT wiki 
+        at <a href="http://cwiki.apache.org/confluence/display/OODT/OODT+Filemgr+User+Guide">OODT Filemgr
+        User Guide</a>
+        </h3>
+        
+      </section>
+        
+<!-- Previous Instructions might need to poach some of the text so commenting out for now     
+
+		This block no longer holds true.  You cannot just build the oodt-core then the filemgr component.
+		cgoodale tried on a clean m2 repo and it failed due to missing dependencies.  If this is still
+		desired, then it will need to be corrected and cleaned up.  Leaving the text here if that is
+		the final case.
+		
+		  
+        <p>Assuming a *nix-like environment, with both Maven and Subversion 
+        clients installed and on your path, an example of the checkout and 
+        build process is presented below:</p>
+        
+         <source>
+> mkdir /usr/local/src
+> cd /usr/local/src
+> svn checkout https://svn.apache.org/repos/asf/oodt/trunk/filemgr
+      </source>
+        
+      <p>After the Subversion command completes, you will have the source
+      for the CAS-Filemgr project in the <code>/usr/local/src/filemgr</code>
+      directory.</p>
+      
+      <p>In order to build the project from this source, issue the following 
+      commands:</p>
+      
+      <source>
+> cd /usr/local/src/filemgr
+> mvn package    
+      </source>   
+      
+      <p>Note that this command performs a number of tasks, including performing
+      unit tests which can take a long time depending on your system. It is not uncommon
+      for this build to last ten minutes or longer. At the end of the process,
+      you will see a Maven success banner.</p>
+      
+      <p>Once the Maven command completes successfully, you should have a 
+      <code>target</code> directory under <code>cas-filemgr-vX.Y.Z/</code>. 
+      The project has been built in this directory as a distribution tar ball.
+      In order to move the built project out of the source directory and unpack the
+      tar ball, issue the following commands:</p>
+      
+      <source>
+> cd /usr/local
+> mv src/filemgr/target/cas-filemgr-vX.Y.Z-dist.tar.gz ./
+> tar -xvzf cas-filemgr-vX.Y.Z-dist.tar.gz
+> export FILEMGR_HOME=/usr/local/cas-filemgr-vX.Y.Z
+      </source>       
+
+
+
+-->
+	  <br/>
+	  <br/>
+	  <br/>
+      <p>The resultant directory layout from the unpacked tarball is as follows:</p>
+           
+      <source>
+bin/ etc/ logs/ doc/ lib/ policy/
+      </source>
+      
+      <p>A basic description of the files and subdirectories of the deployment is 
+      presented below:</p>
+      <ul>
+         <li><strong>bin</strong> - contains scripts for running the File Manager, 
+         including the "filemgr" server script, and the "filemgr-client" client script.</li>
+         
+         <li><strong>etc</strong> - contains the logging.properties file for the 
+         File Manager, and the filemgr.properties file used to configure the server 
+         options.</li>
+         
+         <li><strong>logs</strong> - the default directory into which log files are 
+         written.</li>
+              
+         <li><strong>doc</strong> - contains Javadoc documentation, and user guides 
+         for using the File Manager.</li>
+         
+         <li><strong>lib</strong> - the required Java jar files to run the File 
+         Manager.</li>
+         
+         <li><strong>policy</strong> - the default XML-based element and product 
+         type policy in case the user is using the XML Repository Manager and/or the 
+         XML Validation Layer.</li>
+         
+       </ul>
+      
+      <p>Now you have a built File Manager at <code>/usr/local/oodt/cas-filemgr</code>.
+      In the next section, we will discuss how you can configure the File Manager for
+      basic operations.</p>
+      
+
+    <a name="section2"/>
+    <section name="Configuration in 2 Minutes or Less">
+      
+      <p>The reason for entitling this section "in 2 Minutes or Less" is to show that
+      in it's base deployment, with vary minimal configuration, we can have the File
+      Manager in a usable state, capable of archiving products and capturing basic 
+      metadata. For the record, I haven't timed it, but its pretty fast...</p>
+      
+      <p>We are going to set up the File Manager to use an XML-based Validation layer,
+      and XML product policy, and a Lucene metadata Catalog. The first step is to edit
+      the filemgr script in <code>$FILEMGR_HOME/bin</code>. Make the following 
+      changes:</p>
+     
+       <ul>
+         <li>Set the <code>SERVER_PORT</code> variable to the desired port on which 
+         you'd like to run the File Manager. Our default port is 9000.</li>
+         
+         <li>Set the <code>JAVA_HOME</code> variable to point to the location of your 
+         installed JRE runtime. If you do not know where this is, type <code>&gt; which 
+         java</code> and use that path.</li>
+         
+         <li>Set the <code>RUN_HOME</code> variable to point to the location to which
+         you'd like the File Manager PID file written. Typically this should default to 
+         <code>/var/run</code>, but not all system administrators allow users to write 
+         to <code>/var/run</code>.</li>
+       </ul>
+       
+       <p>The second step in configuration is to edit 
+       <code>$FILEMGR_HOME/bin/filemgr-client</code> script, making the following 
+       change:</p>
+       
+       <ul>
+          <li>Set the <code>JAVA_HOME</code> variable to point to the location of 
+          your installed JRE runtime.</li>
+       </ul>
+           
+       <p>In the third step of this configuration, you will set the File Manager's
+       various extension points. For more information about the functionality of
+       these extension points, see our 
+       <a href="../development/developer.html">Developer Guide.</a> By default, 
+       the File Manager is built to use the XML-based repository manager and 
+       validation layer extension points, the <a href="http://lucene.apache.org/">
+       Lucene</a>-based catalog extension point, and the local data transfer 
+       interface.</p> 
+       
+       <p>Make the following changes to 
+       <code>$FILEMGR_HOME/etc/filemgr.properties</code>:</p>
+       
+       
+       <ul>     
+         <li>Specify the path to the directory where the File Manager will create the
+         Lucene index and associated files by setting the 
+         <code>org.apache.oodt.cas.filemgr.catalog.lucene.idxPath</code> property
+         to <code>$FILEMGR_HOME/catalog</code>. Make sure that this directory does
+         NOT exist the first time you run the File Manager. If the File Manager does not find
+         a directory at the specified location, it will create all of the necessary 
+         directory structure and ancillary files.</li>
+         
+         <li>Specify the paths to the directories where the XML policy files are stored 
+         for the validation layer and for the repository manager. These paths are set by 
+         <code>org.apache.oodt.cas.filemgr.repositorymgr.dirs</code> and 
+         <code>org.apache.oodt.cas.filemgr.validation.dirs</code> respectively. The 
+         default location (and default policy files) are located at 
+         <code>$FILEMGR_HOME/policy</code> in the vanilla deployment of the File Manager.
+         Note that these properties need to be fully specified URLs (e.g., they should 
+         start with <code>file://</code>).</li>
+       </ul>
+
+       <div class="info">Optionally, you can change the default logging properties for
+       the CAS File Manager. This is done by editing 
+       <code>$FILEMGR_HOME/etc/logging.properties</code>. We have tried to select sensible
+       defaults for the average user, but if you would like more or less information 
+       generated in the File Manager logs, you can edit the levels of different catagories
+       of information in this proporties file. The following logging levels are available:
+       <code>INFO</code>, <code>WARNING</code>, <code>FINE</code>, <code>FINER</code>,
+       <code>FINEST</code>, and <code>ALL</code>.</div>
+   
+      <p>With this last step, you have configured the File Manager. In order to test your 
+      configuration, cd to <code>$FILEMGR_HOME/bin</code> and type:</p>
+
+      <source>
+> ./filemgr start
+      </source>
+
+
+      <p>This will startup the file manager XML-RPC server interface. Your File Manager 
+      is now ready to run! You can test out the file manager by running a simple ingest 
+      command using the filemgr-client command below. First create a simple text file 
+      called "blah.txt" and place it inside <code>$FILEMGR_HOME/bin</code> Then, create 
+      a blank metadata file for the product, using the 
+      <a href="http://svn.apache.org/repos/asf/oodt/trunk/metadata/src/main/conf/cas.metadata.xsd">schema</a>
+      or  <a href="http://svn.apache.org/repos/asf/oodt/trunk/metadata/src/main/conf/cas.metadata.dtd">DTD</a>
+      provided in the <a href="../../metadata">CAS-Metadata</a>
+      project. An example XML file might be:</p>
+      
+      <source>
+        &lt;cas:metadata xmlns:cas=&quot;http://oodt.apache.org/1.0/cas&quot;&gt;
+        &lt;/cas:metadata&gt;
+      </source>
+      
+      <p>Call this metadata file <code>blah.txt.met</code>, and place it also in 
+      <code>$FILEMGR_HOME/bin</code>. Then, run the command below, assuming that you 
+      started the File Manager on the default port of <code>9000</code>:</p>
+
+      <source>
+> ./filemgr-client --url http://localhost:9000 --operation \
+   --ingestProduct --productName blah.txt --productStructure Flat \
+   --productTypeName GenericFile \ 
+   --metadataFile file:///usr/local/oodt/cas-filemgr/bin/blah.txt.met \
+   --refs file:///usr/local/oodt/cas-filemgr/bin/blah.txt
+      </source>
+
+      <p>This command triggers the ingest process. You should see a response message that 
+      concludes with a line similar to:</p>
+
+      <source>
+      ingestProduct: Result: 3a812d86-148d-11db-a25a-f388f524a371
+      </source>
+
+      <p>If you see something similar to this message, you have successfully configured
+      the CAS File Manager, hopefully in 2 minutes or less (and even if it took a little 
+      more time, you have to admit it was by and large painless).</p>
+      </section>
+
+<!--      
+      <a name="section3"/>
+      <section name="Learn By Example">
+      <p>Coming Soon...</p>
+      </section>
+-->      
+      <section name="Conclusion">
+      <p>In this Basic User Guide, we have covered a number of topics, including File 
+      Manager installation, configuration, and a basic example of use. For more advanced 
+      topics, including the use of multiple catalogs and best practices for addressing
+      scaling issues, see our <a href="../user/advanced.html">Advanced Guide.</a></p>
+      </section>
+      
+   </body>
+</document> 
diff --git a/0.8.1-rc1/filemgr/src/site/xdoc/user/index.xml b/0.8.1-rc1/filemgr/src/site/xdoc/user/index.xml
new file mode 100644
index 0000000..5802a92
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/site/xdoc/user/index.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS File Manager User Guide</title>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+      <author email="woollard@jpl.nasa.gov">Dave Woollard</author>
+   </properties>
+
+   <body>
+  
+      <div class="warning">This document is in the process of being reorganized as
+      part of our ongoing documentation effort. Please follow the links below to find
+      information that has previously been hosted on this page.</div>
+ 
+
+      <p>We are in the process of upgrading OODT documentation. In the near
+      future, we hope to provide information for developers regarding each 
+      component, including its purpose, structure, interfaces, and 
+      configuration points in a <a href="../development/developer.html">Developer
+      Guide.</a></p>
+      
+      <p>Information for users, including installation and basic configuration,
+      as well as example usage are provided in a 
+      <a href="../user/basic.html">Basic User Guide.</a> Advanced topics, like
+      look and feel, lessons-learned, and best practices are provided in an
+      <a href="../user/advanced.html">Advanced User Guide.</a></p>
+      
+      <p>Finally, we are planning to provide a number of case studies in the 
+      future, in which multi-component deployments are configured to handle
+      common data and computation management scenarios.</p> 
+
+   </body>
+</document> 
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/MockCatalog.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/MockCatalog.java
new file mode 100644
index 0000000..6d8131c
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/MockCatalog.java
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog;
+
+//JDK imports
+import java.util.List;
+import java.util.Map;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Google imports
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * A Mock {@link Catalog}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class MockCatalog implements Catalog {
+
+   Map<String, Product> products;
+
+   public MockCatalog() {
+      products = Maps.newHashMap();
+   }
+
+   @Override
+   public ProductPage getFirstPage(ProductType type) {
+      return null;
+   }
+
+   @Override
+   public ProductPage getLastProductPage(ProductType type) {
+      return null;
+   }
+
+   @Override
+   public ProductPage getNextPage(ProductType type, ProductPage currentPage) {
+      return null;
+   }
+
+   @Override
+   public ProductPage getPrevPage(ProductType type, ProductPage currentPage) {
+      return null;
+   }
+
+   @Override
+   public void addMetadata(Metadata m, Product product) throws CatalogException {      
+   }
+
+   @Override
+   public void removeMetadata(Metadata m, Product product)
+         throws CatalogException {      
+   }
+
+   @Override
+   public void addProduct(Product product) throws CatalogException {   
+      products.put(product.getProductId(), product);
+   }
+
+   @Override
+   public void modifyProduct(Product product) throws CatalogException {
+      products.put(product.getProductId(), product);
+   }
+
+   @Override
+   public void removeProduct(Product product) throws CatalogException {
+      products.remove(product.getProductId());
+   }
+
+   @Override
+   public void setProductTransferStatus(Product product)
+         throws CatalogException {
+      Product ingestedProduct = products.get(product.getProductId());
+      ingestedProduct.setTransferStatus(product.getTransferStatus());
+   }
+
+   @Override
+   public void addProductReferences(Product product) throws CatalogException {
+      Product ingestedProduct = products.get(product.getProductId());
+      List<Reference> references = ingestedProduct.getProductReferences();
+      if (references == null) {
+         references = Lists.newArrayList();
+      }
+      references.addAll(product.getProductReferences());
+      ingestedProduct.setProductReferences(references);
+   }
+
+   @Override
+   public Product getProductById(String productId) throws CatalogException {
+      return products.get(productId);
+   }
+
+   @Override
+   public Product getProductByName(String productName) throws CatalogException {
+      for (Product product : products.values()) {
+         if (product.getProductName().equals(productName)) {
+            return product;
+         }
+      }
+      return null;
+   }
+
+   @Override
+   public List<Reference> getProductReferences(Product product)
+         throws CatalogException {
+      return null;
+   }
+
+   @Override
+   public List<Product> getProducts() throws CatalogException {
+      return Lists.newArrayList(products.values());
+   }
+
+   @Override
+   public List<Product> getProductsByProductType(ProductType type)
+         throws CatalogException {
+      return null;
+   }
+
+   @Override
+   public Metadata getMetadata(Product product) throws CatalogException {
+      return null;
+   }
+
+   @Override
+   public Metadata getReducedMetadata(Product product, List<String> elements)
+         throws CatalogException {
+      return null;
+   }
+
+   @Override
+   public List<String> query(Query query, ProductType type)
+         throws CatalogException {
+      return null;
+   }
+
+   @Override
+   public ProductPage pagedQuery(Query query, ProductType type, int pageNum)
+         throws CatalogException {
+      return null;
+   }
+
+   @Override
+   public List<Product> getTopNProducts(int n) throws CatalogException {
+      return null;
+   }
+
+   @Override
+   public List<Product> getTopNProducts(int n, ProductType type)
+         throws CatalogException {
+      return null;
+   }
+
+   @Override
+   public ValidationLayer getValidationLayer() throws CatalogException {
+      return null;
+   }
+
+   @Override
+   public int getNumProducts(ProductType type) throws CatalogException {
+      return 0;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/MockCatalogFactory.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/MockCatalogFactory.java
new file mode 100644
index 0000000..7b17fa8
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/MockCatalogFactory.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.catalog;
+
+/**
+ * A Mock {@link CatalogFactory}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class MockCatalogFactory implements CatalogFactory {
+
+   @Override
+   public MockCatalog createCatalog() {
+      return new MockCatalog();
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/TestDataSourceCatalog.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/TestDataSourceCatalog.java
new file mode 100644
index 0000000..eb3ef32
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/TestDataSourceCatalog.java
@@ -0,0 +1,508 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.List;
+import java.util.Properties;
+import javax.sql.DataSource;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+import org.apache.oodt.commons.database.SqlScript;
+import org.apache.oodt.cas.filemgr.util.SqlParser;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test suite for the {@link DataSourceCatalog} and
+ * {@link DataSourceCatalogFactory}.
+ * </p>.
+ */
+public class TestDataSourceCatalog extends TestCase {
+
+    protected Catalog myCat;
+
+    private String tmpDirPath = null;
+
+    private static final int catPageSize = 20;
+
+    private Properties initialProperties = new Properties(
+      System.getProperties());
+
+    public void setUpProperties() {
+
+        Properties properties = new Properties(System.getProperties());
+
+        // set the log levels
+        URL loggingPropertiesUrl = this.getClass().getResource(
+            "/test.logging.properties");
+        properties.setProperty("java.util.logging.config.file", new File(
+            loggingPropertiesUrl.getFile()).getAbsolutePath());
+
+        if(properties.getProperty("overrideProperties") == null){
+
+            try {
+                URL filemgrPropertiesUrl = this.getClass().getResource(
+                    "/filemgr.properties");
+                properties.load(new FileInputStream(
+                    filemgrPropertiesUrl.getFile()));
+            } catch (Exception e) {
+                fail(e.getMessage());
+            }
+
+
+        // first load the example configuration
+
+
+        // get a temp directory
+        File tempDir = null;
+        File tempFile = null;
+
+        try {
+            tempFile = File.createTempFile("foo", "bar");
+            tempFile.deleteOnExit();
+            tempDir = tempFile.getParentFile();
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        tmpDirPath = tempDir.getAbsolutePath();
+        if (!tmpDirPath.endsWith("/")) {
+            tmpDirPath += "/";
+        }
+
+        tmpDirPath += "testCat";
+
+        // now override the catalog ones
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.url",
+                "jdbc:hsqldb:file:" + tmpDirPath + "/testCat;shutdown=true");
+
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.user",
+                "sa");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.pass",
+                "");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.driver",
+                "org.hsqldb.jdbcDriver");
+        }
+        else{
+            try {
+                properties.load(new FileInputStream(
+                    properties.getProperty("overrideProperties")));
+            } catch (Exception e) {
+                fail(e.getMessage());
+            }
+        }
+        // now override the val layer ones
+        URL structFactoryUrl = this.getClass().getResource(
+            "/xmlrpc-struct-factory");
+        properties.setProperty("org.apache.oodt.cas.filemgr.validation.dirs",
+            "file://" + new File(structFactoryUrl.getFile()).getAbsolutePath());
+
+        // override quote fields
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.datasource.quoteFields",
+                "true");
+
+        System.setProperties(properties);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        setUpProperties();
+        myCat = getCatalog();
+        // now create the basic schema for the DB
+        createSchema();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        // now remove the temporary directory used
+        if (tmpDirPath != null) {
+            File tmpDir = new File(tmpDirPath);
+            File[] tmpFiles = tmpDir.listFiles();
+
+            if (tmpFiles != null && tmpFiles.length > 0) {
+                for (int i = 0; i < tmpFiles.length; i++) {
+                    tmpFiles[i].delete();
+                }
+
+                tmpDir.delete();
+            }
+
+        }
+
+        System.setProperties(initialProperties);
+    }
+
+    public void testRemoveProduct() {
+        Product productToRemove = getTestProduct();
+        // override name
+        productToRemove.setProductName("removeme");
+        try {
+            myCat.addProduct(productToRemove);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        Product retProduct = null;
+        ProductType type = new ProductType();
+        type.setName("GenericFile");
+        type.setProductTypeId("urn:oodt:GenericFile");
+
+        try {
+            retProduct = myCat.getProductByName("removeme");
+            retProduct.setProductType(type);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+        assertNotNull(retProduct);
+
+        try {
+            myCat.removeProduct(retProduct);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        Product retProdAfterRemove = null;
+        try {
+            retProdAfterRemove = myCat.getProductByName("removeme");
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNull(retProdAfterRemove);
+
+    }
+
+    public void testModifyProduct() {
+        Product testProduct = getTestProduct();
+        try {
+            myCat.addProduct(testProduct);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(testProduct);
+        assertEquals("test", testProduct.getProductName());
+        // now change something
+        testProduct.setProductName("f002");
+        try {
+            myCat.modifyProduct(testProduct);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(testProduct);
+
+        Product retProduct;
+        try {
+            retProduct = myCat.getProductByName("f002");
+            assertNotNull(retProduct);
+            assertEquals("f002", retProduct.getProductName());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+    }
+
+    /**
+     * @since OODT-133
+     * 
+     */
+    public void testFirstProductOnlyOnFirstPage() {
+        // add catPageSize of the test Product
+        // then add a product called "ShouldBeFirstForPage.txt"
+        // make sure it's the first one on the 1st page
+
+        Product testProd = getTestProduct();
+        Metadata met = getTestMetadata("test");
+
+        for (int i = 0; i < this.catPageSize; i++) {
+            try {
+                myCat.addProduct(testProd);
+                myCat.addMetadata(met, testProd);
+            } catch (Exception e) {
+                fail(e.getMessage());
+            }
+        }
+
+        testProd.setProductName("ShouldBeFirstForPage.txt");
+        met.replaceMetadata("CAS.ProdutName", "ShouldBeFirstForPage.txt");
+
+        try {
+            myCat.addProduct(testProd);
+            myCat.addMetadata(met, testProd);
+
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        try {
+            assertNotNull(myCat.getProducts());
+            assertEquals(21, myCat.getProducts().size());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        ProductType type = new ProductType();
+        type.setProductTypeId("urn:oodt:GenericFile");
+        type.setName("GenericFile");
+        assertNotNull(myCat.getFirstPage(type));
+        assertNotNull(myCat.getFirstPage(type).getPageProducts());
+        assertEquals(catPageSize, myCat.getFirstPage(type).getPageProducts()
+                .size());
+        assertNotNull(myCat.getFirstPage(type).getPageProducts().get(0));
+        assertEquals("ShouldBeFirstForPage.txt", ((Product)myCat.getFirstPage(type).getPageProducts().get(0)).getProductName());
+        ProductPage page = myCat.getNextPage(type, myCat.getFirstPage(type));
+        assertNotNull(page);
+        assertNotNull(page.getPageProducts());
+        assertEquals(1, page.getPageProducts().size());
+        assertEquals(2, page.getTotalPages());
+        assertNotNull(page.getPageProducts().get(0));
+        Product retProd = ((Product) page.getPageProducts().get(0));
+        assertEquals("test", retProd.getProductName());
+
+    }
+
+    public void testAddProduct() {
+
+        Product testProduct = getTestProduct();
+        try {
+            myCat.addProduct(testProduct);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        Product retProduct;
+        try {
+            retProduct = myCat.getProductByName("test");
+            assertNotNull(retProduct);
+            assertEquals("test", retProduct.getProductName());
+            assertEquals(Product.STRUCTURE_FLAT, retProduct
+                    .getProductStructure());
+            assertNotNull(retProduct.getProductType());
+            assertEquals("urn:oodt:GenericFile", retProduct.getProductType()
+                    .getProductTypeId());
+            assertEquals(Product.STATUS_TRANSFER, retProduct
+                    .getTransferStatus());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+    }
+
+    public void testAddMetadata() {
+        Metadata met = new Metadata();
+        met.addMetadata("ProductStructure", Product.STRUCTURE_FLAT);
+
+        Product testProduct = getTestProduct();
+        testProduct.setProductId("1"); // need to link metadata to prod
+
+        try {
+            myCat.addMetadata(met, testProduct);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        try {
+            Metadata retMet = myCat.getMetadata(testProduct);
+            assertNotNull(retMet);
+            assertTrue(retMet.containsKey(CoreMetKeys.PRODUCT_STRUCTURE));
+            assertEquals(Product.STRUCTURE_FLAT, retMet
+                    .getMetadata(CoreMetKeys.PRODUCT_STRUCTURE));
+        } catch (CatalogException e) {
+            fail(e.getMessage());
+        }
+
+    }
+
+    public void testRemoveMetadata() {
+        Metadata met = new Metadata();
+        met.addMetadata("Filename", "tempProduct");
+
+        Product testProduct = getTestProduct();
+        testProduct.setProductId("1"); // need to link metadata to prod
+
+        try {
+            myCat.addMetadata(met, testProduct);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        try {
+            myCat.removeMetadata(met, testProduct);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        try {
+            Metadata retMet = myCat.getMetadata(testProduct);
+            String retValue = retMet.getMetadata("Filename");
+            assertNull(retValue);
+        } catch (CatalogException e) {
+            fail(e.getMessage());
+        }
+    }
+
+    public void testQuery() throws Exception {
+        // ingest first file
+        Product testProduct = getTestProduct();
+        testProduct.setProductId("23");
+        Metadata prodMet = new Metadata();
+        URL ingestUrl = this.getClass().getResource(
+            "/ingest");
+        prodMet.addMetadata(CoreMetKeys.FILE_LOCATION, new File(
+            ingestUrl.getFile()).getCanonicalPath());
+        prodMet.addMetadata(CoreMetKeys.FILENAME, "test-file-1.txt");
+        prodMet.addMetadata("CAS.ProductName", "TestFile1");
+        prodMet.addMetadata(CoreMetKeys.PRODUCT_TYPE, "GenericFile");
+        prodMet.addMetadata("NominalDate", "2008-01-20");
+        prodMet.addMetadata("DataVersion", "3.6");
+        myCat.addMetadata(prodMet, testProduct);
+
+        // ingest second file
+        testProduct.setProductId("24");
+        prodMet.replaceMetadata(CoreMetKeys.FILENAME, "test-file-2.txt");
+        prodMet.replaceMetadata("CAS.ProductName", "TestFile2");
+        myCat.addMetadata(prodMet, testProduct);
+
+        // ingest thrid file
+        testProduct.setProductId("25");
+        prodMet.replaceMetadata(CoreMetKeys.FILENAME, "test-file-2.txt");
+        prodMet.replaceMetadata("CAS.ProductName", "TestFile3");
+        prodMet.replaceMetadata("DataVersion", "4.6");
+        myCat.addMetadata(prodMet, testProduct);
+
+        // perform first query
+        Query query = new Query();
+        query
+                .addCriterion(SqlParser
+                        .parseSqlWhereClause("CAS.ProductName != 'TestFile3' AND (Filename == 'test-file-1.txt' OR Filename == 'test-file-2.txt') AND CAS.ProductName != 'TestFile2'"));
+        System.out.println(query);
+        List<String> productIds = myCat.query(query, testProduct
+                .getProductType());
+        System.out.println(productIds);
+        assertEquals("[23]", productIds.toString());
+
+        // perform second query
+        query = new Query();
+        query
+                .addCriterion(SqlParser
+                        .parseSqlWhereClause("Filename == 'test-file-1.txt' OR (Filename == 'test-file-2.txt' AND CAS.ProductName != 'TestFile2')"));
+        System.out.println(query);
+        productIds = myCat.query(query, testProduct.getProductType());
+        System.out.println(productIds);
+        assertEquals("[25, 23]", productIds.toString());
+
+        // perform second query
+        query = new Query();
+        query
+                .addCriterion(SqlParser
+                        .parseSqlWhereClause("NominalDate == '2008-01-20' AND DataVersion >= '3.6' AND DataVersion <= '4.0'"));
+        System.out.println(query);
+        productIds = myCat.query(query, testProduct.getProductType());
+        System.out.println(productIds);
+        assertEquals("[24, 23]", productIds.toString());
+    }
+
+    protected String getSchemaPath() {
+        URL url = this.getClass().getResource(
+          "/testcat.sql");
+
+        return new File(url.getFile()).getAbsolutePath();
+    }
+    
+    protected void setCatalog(Catalog cat){
+        this.myCat = cat;
+    }
+
+    private Catalog getCatalog() {
+        return new DataSourceCatalogFactory().createCatalog();
+    }
+    
+    private void createSchema() {
+        String url = System
+                .getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.url");
+        String user = System
+                .getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.user");
+        String pass = System
+                .getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.pass");
+        String driver = System
+                .getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.driver");
+
+        DataSource ds = DatabaseConnectionBuilder.buildDataSource(user, pass,
+                driver, url);
+        try {
+            SqlScript coreSchemaScript = new SqlScript(
+                    new File(getSchemaPath()).getAbsolutePath(), ds);
+            coreSchemaScript.loadScript();
+            coreSchemaScript.execute();
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+    }
+
+    private static Product getTestProduct() {
+        Product testProduct = Product.getDefaultFlatProduct("test",
+                "urn:oodt:GenericFile");
+        testProduct.getProductType().setName("GenericFile");
+        return testProduct;
+    }
+
+    private static Metadata getTestMetadata(String prodName) {
+        Metadata met = new Metadata();
+        met.addMetadata("CAS.ProductName", prodName);
+        return met;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/TestLuceneCatalog.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/TestLuceneCatalog.java
new file mode 100644
index 0000000..7079115
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/TestLuceneCatalog.java
@@ -0,0 +1,548 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.Properties;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.catalog.LuceneCatalog;
+import org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.BooleanQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.metadata.Metadata;
+import com.google.common.collect.Lists;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author woollard
+ * @author mattmann
+ * 
+ * @version $Revision$
+ * 
+ * <p>
+ * Test suite for the {@link LuceneCatalog} and {@link LuceneCatalogFactory}.
+ * </p>.
+ */
+public class TestLuceneCatalog extends TestCase {
+
+    private LuceneCatalog myCat;
+
+    private String tmpDirPath = null;
+
+    private static final int catPageSize = 20;
+
+    private Properties initialProperties = new Properties(
+      System.getProperties());
+
+    public void setUpProperties() {
+
+        Properties properties = new Properties(System.getProperties());
+
+        // set the log levels
+        URL loggingPropertiesUrl = this.getClass().getResource(
+            "/test.logging.properties");
+        properties.setProperty("java.util.logging.config.file", new File(
+            loggingPropertiesUrl.getFile()).getAbsolutePath());
+
+        // first load the example configuration
+        try {
+            URL filemgrPropertiesUrl = this.getClass().getResource(
+                "/filemgr.properties");
+            properties.load(new FileInputStream(
+                filemgrPropertiesUrl.getFile()));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // get a temp directory
+
+        File tempDir = null;
+        File tempFile = null;
+
+        try {
+            tempFile = File.createTempFile("foo", "bar");
+            tempFile.deleteOnExit();
+            tempDir = tempFile.getParentFile();
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        tmpDirPath = tempDir.getAbsolutePath();
+        if (!tmpDirPath.endsWith("/")) {
+            tmpDirPath += "/";
+        }
+
+        tmpDirPath += "testCat/";
+
+        // now override the catalog ones
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.lucene.idxPath",
+                tmpDirPath);
+
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.lucene.pageSize", "20");
+
+        properties.setProperty(
+                        "org.apache.oodt.cas.filemgr.catalog.lucene.commitLockTimeout.seconds",
+                        "60");
+
+        properties.setProperty(
+                        "org.apache.oodt.cas.filemgr.catalog.lucene.writeLockTimeout.seconds",
+                        "60");
+
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.lucene.mergeFactor",
+                "20");
+
+        // now override the val layer ones
+        URL examplesCoreUrl = this.getClass().getResource(
+            "/examples/core");
+        properties.setProperty("org.apache.oodt.cas.filemgr.validation.dirs",
+            "file://" + new File(examplesCoreUrl.getFile()).getAbsolutePath());
+
+        System.setProperties(properties);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        setUpProperties();
+        myCat = (LuceneCatalog) new LuceneCatalogFactory().createCatalog();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        // now remove the temporary directory used
+
+        if (tmpDirPath != null) {
+            File tmpDir = new File(tmpDirPath);
+            File[] tmpFiles = tmpDir.listFiles();
+
+            if (tmpFiles != null && tmpFiles.length > 0) {
+                for (int i = 0; i < tmpFiles.length; i++) {
+                    tmpFiles[i].delete();
+                }
+
+                tmpDir.delete();
+            }
+
+            if (myCat != null) {
+                myCat = null;
+            }
+        }
+
+        System.setProperties(initialProperties);
+    }
+    
+    /**
+    * @since OODT-382
+    */
+    public void testNoCatalogDirectoryQueries() {
+        // Test querying against a catalog directory that has not yet been created or is empty. 
+        // The LuceneCatalogFactory should be creating the index directory if not there.
+        try {
+            myCat.getTopNProducts(10);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+    public void testGetMetadata() throws CatalogException {
+       Product product = getTestProduct();
+       myCat.addProduct(product);
+       myCat.addProductReferences(product);
+       Metadata m = new Metadata();
+       m.addMetadata(CoreMetKeys.FILE_LOCATION, Lists.newArrayList("/loc/1", "/loc/2"));
+       myCat.addMetadata(m, product);
+       Metadata rndTripMet = myCat.getMetadata(product);
+
+       assertNotNull(rndTripMet);
+       assertEquals(2, rndTripMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).size());
+       assertTrue(rndTripMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).contains("/loc/1"));
+       assertTrue(rndTripMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).contains("/loc/2"));
+    }
+    
+    public void testGetReducedMetadata() throws CatalogException {
+       Product product = getTestProduct();
+       myCat.addProduct(product);
+       myCat.addProductReferences(product);
+       Metadata m = new Metadata();
+       m.addMetadata(CoreMetKeys.FILE_LOCATION, Lists.newArrayList("/loc/1", "/loc/2"));
+       myCat.addMetadata(m, product);
+       Metadata rndTripMet = myCat.getReducedMetadata(product,
+             Lists.newArrayList(CoreMetKeys.FILE_LOCATION));
+
+       assertNotNull(rndTripMet);
+       assertEquals(2, rndTripMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).size());
+       assertTrue(rndTripMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).contains("/loc/1"));
+       assertTrue(rndTripMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).contains("/loc/2"));
+    }
+
+    public void testGetReducedMetadataNull() throws CatalogException {
+	      Product p = getTestProduct();
+	      myCat.addProduct(p);
+	      myCat.addProductReferences(p);
+	      myCat.addMetadata(new Metadata(), p);
+
+	      // should not throw NPE here
+	      Metadata rndTripMet = myCat.getReducedMetadata(p, Lists.newArrayList(CoreMetKeys.FILENAME));
+
+	      assertNotNull(rndTripMet);
+	      // should return null if met key has no value
+	      assertNull(rndTripMet.getAllMetadata(CoreMetKeys.FILENAME));
+    }
+
+    public void testRemoveProduct() {
+        Product productToRemove = getTestProduct();
+
+        // override name
+        productToRemove.setProductName("removeme");
+        try {
+            myCat.addProduct(productToRemove);
+            myCat.addMetadata(getTestMetadata("tempProduct"), productToRemove);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        Product retProduct = null;
+        ProductType type = new ProductType();
+        type.setName("GenericFile");
+        type.setProductTypeId("urn:oodt:GenericFile");
+
+        try {
+            retProduct = myCat.getProductByName("removeme");
+            retProduct.setProductType(type);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+        assertNotNull(retProduct);
+
+        try {
+            myCat.removeProduct(retProduct);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        Product retProdAfterRemove = null;
+        try {
+            retProdAfterRemove = myCat.getProductByName("removeme");
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNull(retProdAfterRemove);
+
+    }
+
+    public void testModifyProduct() {
+        Product testProduct = getTestProduct();
+        try {
+            myCat.addProduct(testProduct);
+            myCat.addMetadata(getTestMetadata("tempProduct"), testProduct);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(testProduct);
+        assertEquals("test", testProduct.getProductName());
+        // now change something
+        testProduct.setProductName("f002");
+        try {
+            myCat.modifyProduct(testProduct);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(testProduct);
+
+        Product retProduct;
+        try {
+            retProduct = myCat.getProductByName("f002");
+            assertNotNull(retProduct);
+            assertEquals("f002", retProduct.getProductName());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+    }
+
+    /**
+     * @since OODT-133
+     * 
+     */
+    public void testFirstProductOnlyOnFirstPage() {
+        // add catPageSize of the test Product
+        // then add a product called "ShouldBeFirstForPage.txt"
+        // make sure it's the first one on the 2nd page
+
+        Product testProd = getTestProduct();
+        Metadata met = getTestMetadata("test");
+
+        for (int i = 0; i < this.catPageSize; i++) {
+            try {
+                myCat.addProduct(testProd);
+                myCat.addMetadata(met, testProd);
+            } catch (Exception e) {
+                fail(e.getMessage());
+            }
+        }
+
+        testProd.setProductName("ShouldBeFirstForPage.txt");
+        met.replaceMetadata("CAS.ProdutName", "ShouldBeFirstForPage.txt");
+
+        try {
+            myCat.addProduct(testProd);
+            myCat.addMetadata(met, testProd);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        try {
+            assertNotNull(myCat.getProducts());
+            assertEquals(21, myCat.getProducts().size());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        ProductType type = new ProductType();
+        type.setProductTypeId("urn:oodt:GenericFile");
+        type.setName("GenericFile");
+        assertNotNull(myCat.getFirstPage(type));
+        assertNotNull(myCat.getFirstPage(type).getPageProducts());
+        assertEquals(catPageSize, myCat.getFirstPage(type).getPageProducts()
+                .size());
+        ProductPage page = myCat.getNextPage(type, myCat.getFirstPage(type));
+        assertNotNull(page);
+        assertNotNull(page.getPageProducts());
+        assertEquals(1, page.getPageProducts().size());
+        assertEquals(2, page.getTotalPages());
+        assertNotNull(page.getPageProducts().get(0));
+        Product retProd = ((Product) page.getPageProducts().get(0));
+        assertEquals("ShouldBeFirstForPage.txt", retProd.getProductName());
+    }
+    
+    /**
+     * @since OODT-141
+     */
+    public void testTopResults(){
+      Product testProduct = getTestProduct();
+      try{
+        myCat.addProduct(testProduct);
+        myCat.addMetadata(getTestMetadata("tempProduct"), testProduct);
+        myCat.getTopNProducts(20);
+      }
+      catch(Exception e){
+        e.printStackTrace();
+        fail(e.getMessage());
+      }
+    }
+
+    public void testAddProduct() {
+
+        Product testProduct = getTestProduct();
+        try {
+            myCat.addProduct(testProduct);
+            myCat.addMetadata(getTestMetadata("tempProduct"), testProduct);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        Product retProduct;
+        try {
+            retProduct = myCat.getProductByName("test");
+            assertNotNull(retProduct);
+            assertEquals("test", retProduct.getProductName());
+            assertEquals(Product.STRUCTURE_FLAT, retProduct
+                    .getProductStructure());
+            assertNotNull(retProduct.getProductType());
+            assertEquals("urn:oodt:GenericFile", retProduct.getProductType()
+                    .getProductTypeId());
+            assertEquals(Product.STATUS_TRANSFER, retProduct
+                    .getTransferStatus());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+    }
+
+    public void testAddMetadata() {
+        Metadata met = new Metadata();
+        met.addMetadata("ProductStructure", Product.STRUCTURE_FLAT);
+
+        Product testProduct = getTestProduct();
+        try {
+            myCat.addProduct(testProduct);
+            myCat.addMetadata(met, testProduct);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        try {
+            Metadata retMet = myCat.getMetadata(testProduct);
+            assertNotNull(retMet);
+            assertTrue(retMet.containsKey(CoreMetKeys.PRODUCT_STRUCTURE));
+            assertEquals(Product.STRUCTURE_FLAT, retMet
+                    .getMetadata(CoreMetKeys.PRODUCT_STRUCTURE));
+        } catch (CatalogException e) {
+            fail(e.getMessage());
+        }
+
+    }
+
+    public void testRemoveMetadata() {
+        Metadata met = new Metadata();
+        met.addMetadata("Filename", "tempProduct");
+        met.addMetadata("ProductStructure", "Flat");
+
+        Product testProduct = getTestProduct();
+        try {
+            myCat.addProduct(testProduct);
+            myCat.addMetadata(met, testProduct);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        try {
+            myCat.removeMetadata(met, testProduct);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        try {
+            Metadata retMet = myCat.getMetadata(testProduct);
+            String retValue = retMet.getMetadata("Filename");
+            assertNull(retValue);
+        } catch (CatalogException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+    }
+    
+    public void testPagedQuery(){
+    	// Add a couple of Products and associated Metadata
+    	Product testProduct = null;
+    	for(int i = 0; i < catPageSize + 1; i++){
+    		testProduct = Product.getDefaultFlatProduct("test" + i,
+					"urn:oodt:GenericFile");
+    		testProduct.getProductType().setName("GenericFile");
+    		Reference ref = new Reference("file:///foo.txt", "file:///bar.txt", 100);
+            Vector<Reference> references = new Vector<Reference>();
+            references.add(ref);
+            testProduct.setProductReferences(references);
+    		Metadata met = new Metadata();
+    		met.addMetadata("Filename", "tempProduct" + i);
+    		met.addMetadata("ProductStructure", "Flat");
+    		try {
+                myCat.addProduct(testProduct);
+                myCat.addMetadata(met, testProduct);
+            } catch (Exception e) {
+                e.printStackTrace();
+                fail(e.getMessage());
+            }
+    	}
+    	
+    	// Formulate a test query
+    	Query query = new Query();
+    	BooleanQueryCriteria bqc = new BooleanQueryCriteria();
+    	try{
+    		bqc.setOperator(BooleanQueryCriteria.AND);
+    	}catch (Exception e){
+    		e.printStackTrace();
+            fail(e.getMessage());
+    	}
+    	TermQueryCriteria tqc = new TermQueryCriteria();
+    	tqc.setElementName("ProductStructure");
+    	tqc.setValue("Flat");
+    	try{
+    		bqc.addTerm(tqc);
+    	}catch (Exception e){
+    		e.printStackTrace();
+            fail(e.getMessage());
+    	}
+    	tqc = new TermQueryCriteria();
+    	tqc.setElementName("Filename");
+    	tqc.setValue("tempProduct1");
+    	try{
+    		bqc.addTerm(tqc);
+    	}catch (Exception e){
+    		e.printStackTrace();
+            fail(e.getMessage());
+    	}
+    	query.addCriterion(bqc);
+    	
+    	// Perform the query and validate results
+    	ProductPage page = null;
+    	try{
+    		page = myCat.pagedQuery(query, testProduct.getProductType(), 1);
+    	}catch (Exception e){
+    		e.printStackTrace();
+            fail(e.getMessage());
+    	}
+    	assertEquals(page.getPageProducts().size(), 1);
+    	assertEquals(page.getPageProducts().get(0).getProductName(), "test1");
+    	assertEquals(page.getPageNum(), 1);
+    	assertEquals(page.getTotalPages(), 1);
+    }
+	
+    private static Product getTestProduct() {
+        Product testProduct = Product.getDefaultFlatProduct("test",
+                "urn:oodt:GenericFile");
+        testProduct.getProductType().setName("GenericFile");
+
+        // set references
+        Reference ref = new Reference("file:///foo.txt", "file:///bar.txt", 100);
+        Vector references = new Vector();
+        references.add(ref);
+        testProduct.setProductReferences(references);
+
+        return testProduct;
+    }
+
+    private static Metadata getTestMetadata(String prodName) {
+        Metadata met = new Metadata();
+        met.addMetadata("CAS.ProductName", prodName);
+        return met;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/TestMappedDataSourceCatalog.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/TestMappedDataSourceCatalog.java
new file mode 100644
index 0000000..b6efdb2
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/TestMappedDataSourceCatalog.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Properties;
+
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class TestMappedDataSourceCatalog extends TestDataSourceCatalog {
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // Get additional resources and set additional properties.
+        Properties properties = new Properties(System.getProperties());
+        URL url = this.getClass().getResource(
+          "/testcatalog.typemap.properties");
+        properties.setProperty(
+            "org.apache.oodt.cas.filemgr.catalog.mappeddatasource.mapFile",
+            new File(url.getFile()).getAbsolutePath());
+        System.setProperties(properties);
+
+        setCatalog(getCatalog());
+
+    }
+
+    protected Catalog getCatalog() {
+        try {
+            return new MappedDataSourceCatalogFactory().createCatalog();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.filemgr.catalog.TestDataSourceCatalog#getSchemaPath()
+     */
+    @Override
+    protected String getSchemaPath() {
+        URL url = this.getClass().getResource(
+            "/testcat.mapped.sql");
+
+        return new File(url.getFile()).getAbsolutePath();
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/TestOrderedDataSourceCatalog.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/TestOrderedDataSourceCatalog.java
new file mode 100644
index 0000000..a06ed5e
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/catalog/TestOrderedDataSourceCatalog.java
@@ -0,0 +1,116 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.catalog;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Properties;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ *          <p>
+ *          Describe your class here
+ *          </p>
+ *          .
+ */
+public class TestOrderedDataSourceCatalog extends TestDataSourceCatalog {
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+
+    // Set additional properties.
+    Properties properties = new Properties(System.getProperties());
+    properties.setProperty(
+        "org.apache.oodt.cas.filemgr.catalog.datasource.orderedValues", "true");
+    System.setProperties(properties);
+
+    setCatalog(getCatalog());
+
+  }
+
+  protected Catalog getCatalog() {
+    try {
+      return new DataSourceCatalogFactory().createCatalog();
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.filemgr.catalog.TestDataSourceCatalog#getSchemaPath()
+   */
+  @Override
+  protected String getSchemaPath() {
+      URL url = this.getClass().getResource(
+          "/testcat.ordered.sql");
+
+      return new File(url.getFile()).getAbsolutePath();
+  }
+
+  public void testOrdering() {
+    Product testProduct = getTestProduct();
+    Metadata testMet = getTestMetadata("test");
+
+    try {
+      myCat.addProduct(testProduct);
+      myCat.addMetadata(testMet, testProduct);
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+
+    Product retProduct;
+    try {
+      Metadata retMet = myCat.getMetadata(testProduct);
+      assertNotNull(retMet);
+      assertNotNull(retMet.getAllMetadata("CAS.ProductName"));
+      assertEquals(3, retMet.getAllMetadata("CAS.ProductName").size());
+      assertEquals("test", retMet.getAllMetadata("CAS.ProductName").get(0));
+      assertEquals("test2", retMet.getAllMetadata("CAS.ProductName").get(1));
+      assertEquals("test3", retMet.getAllMetadata("CAS.ProductName").get(2));
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+  }
+
+  private static Product getTestProduct() {
+    Product testProduct = Product.getDefaultFlatProduct("test",
+        "urn:oodt:GenericFile");
+    testProduct.getProductType().setName("GenericFile");
+    return testProduct;
+  }
+
+  private static Metadata getTestMetadata(String prodName) {
+    Metadata met = new Metadata();
+    met.addMetadata("CAS.ProductName", prodName);
+    met.addMetadata("CAS.ProductName", prodName + "2");
+    met.addMetadata("CAS.ProductName", prodName + "3");
+    return met;
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/TestFileManagerCli.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/TestFileManagerCli.java
new file mode 100644
index 0000000..bc47d9f
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/TestFileManagerCli.java
@@ -0,0 +1,410 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Properties;
+//JUnit imports
+import junit.framework.TestCase;
+
+//Apache imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.cli.CmdLineUtility;
+import org.apache.oodt.cas.cli.util.OptionPropertyRegister;
+import org.apache.oodt.cas.filemgr.datatransfer.InPlaceDataTransferFactory;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.query.ComplexQuery;
+import org.apache.oodt.cas.filemgr.system.MockXmlRpcFileManagerClient;
+import org.apache.oodt.cas.filemgr.system.MockXmlRpcFileManagerClient.MethodCallDetails;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * Tests File Manager Clients Command-line interface.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestFileManagerCli extends TestCase {
+
+   private CmdLineUtility cmdLineUtility;
+   private MockXmlRpcFileManagerClient client;
+   private Properties initialProperties = new Properties(
+     System.getProperties());
+
+   @Override
+   public void setUp() throws Exception {
+      super.setUp();
+
+      Properties properties = new Properties(System.getProperties());
+
+      properties.setProperty("org.apache.oodt.cas.cli.debug", "true");
+
+      URL actionsUrl = this.getClass().getResource("/cmd-line-actions.xml");
+      properties.setProperty("org.apache.oodt.cas.cli.action.spring.config",
+        "file:" + new File(actionsUrl.getFile()).getAbsolutePath());
+
+      URL optionsUrl = this.getClass().getResource("/cmd-line-options.xml");
+      properties.setProperty("org.apache.oodt.cas.cli.option.spring.config",
+        "file:" + new File(optionsUrl.getFile()).getAbsolutePath());
+
+      System.setProperties(properties);
+
+      cmdLineUtility = new CmdLineUtility();
+      UseMockClientCmdLineActionStore actionStore = new UseMockClientCmdLineActionStore();
+      client = actionStore.getClient();
+      cmdLineUtility.setActionStore(actionStore);
+   }
+
+   @Override
+   public void tearDown() throws Exception {
+      OptionPropertyRegister.clearRegister();
+      System.setProperties(initialProperties);
+   }
+
+   public void testAddProductType() throws MalformedURLException,
+         ConnectionException {
+      String productTypeName = "TestProductType";
+      String productTypeDesc = "ProductTypeDesc";
+      String productTypeRepo = "ProductTypeRepo";
+      String productTypeVersioner = "ProductTypeVersioner";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --addProductType"
+                  + " --typeName " + productTypeName + " --typeDesc "
+                  + productTypeDesc + " --repository " + productTypeRepo
+                  + " --versionClass " + productTypeVersioner).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("addProductType", methodCallDetails.getMethodName());
+      assertEquals(1, methodCallDetails.getArgs().size());
+      ProductType pt = (ProductType) methodCallDetails.getArgs().get(0);
+      assertEquals(productTypeName, pt.getName());
+      assertEquals(productTypeDesc, pt.getDescription());
+      assertEquals(productTypeRepo, pt.getProductRepositoryPath());
+      assertEquals(productTypeVersioner, pt.getVersioner());
+   }
+
+   public void testDeleteProductById() {
+      String productId = "TestProductId";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --deleteProductById"
+                  + " --productId " + productId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("removeProduct", methodCallDetails.getMethodName());
+      assertEquals(1, methodCallDetails.getArgs().size());
+      assertEquals(productId,
+            ((Product) methodCallDetails.getArgs().get(0)).getProductId());
+   }
+
+   public void testDeleteProductByName() {
+      String productName = "TestProductName";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --deleteProductByName"
+                  + " --productName " + productName).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("removeProduct", methodCallDetails.getMethodName());
+      assertEquals(1, methodCallDetails.getArgs().size());
+      assertEquals(productName,
+            ((Product) methodCallDetails.getArgs().get(0)).getProductName());
+   }
+
+   public void testGetCurrentTransfer() {
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --getCurrentTransfer")
+                  .split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getCurrentFileTransfer", methodCallDetails.getMethodName());
+      assertEquals(0, methodCallDetails.getArgs().size());
+   }
+
+   public void testGetCurrentTransfers() {
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --getCurrentTransfers")
+                  .split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getCurrentFileTransfers", methodCallDetails.getMethodName());
+      assertEquals(0, methodCallDetails.getArgs().size());
+   }
+
+   public void testGetFilePercentTransferred() {
+     URL refUrl = this.getClass().getResource("/ingest/test.txt");
+     String refPath = new File(refUrl.getFile()).getAbsolutePath();
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --getFilePctTransferred"
+                  + " --origRef " + refPath).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getRefPctTransferred", methodCallDetails.getMethodName());
+      assertTrue(((Reference) methodCallDetails.getArgs().get(0))
+            .getOrigReference().endsWith("test.txt"));
+   }
+
+   public void testGetFirstPage() {
+      String productTypeName = "ProductTypeName";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --getFirstPage"
+                  + " --productTypeName " + productTypeName).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getFirstPage", methodCallDetails.getMethodName());
+      assertEquals(productTypeName, ((ProductType) methodCallDetails.getArgs()
+            .get(0)).getName());
+   }
+
+   public void testGetLastPage() {
+      String productTypeName = "ProductTypeName";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --getLastPage"
+                  + " --productTypeName " + productTypeName).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getLastPage", methodCallDetails.getMethodName());
+      assertEquals(productTypeName, ((ProductType) methodCallDetails.getArgs()
+            .get(0)).getName());
+   }
+
+   public void testGetNextPage() {
+      String productTypeName = "ProductTypeName";
+      int curPage = 1;
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --getNextPage"
+                  + " --productTypeName " + productTypeName + " --curPage " + curPage)
+                  .split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getNextPage", methodCallDetails.getMethodName());
+      assertEquals(productTypeName, ((ProductType) methodCallDetails.getArgs()
+            .get(0)).getName());
+      assertEquals(curPage,
+            ((ProductPage) methodCallDetails.getArgs().get(1)).getPageNum());
+   }
+
+   public void testGetPrevPage() {
+      String productTypeName = "ProductTypeName";
+      int curPage = 1;
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --getPrevPage"
+                  + " --productTypeName " + productTypeName + " --curPage " + curPage)
+                  .split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getPrevPage", methodCallDetails.getMethodName());
+      assertEquals(productTypeName, ((ProductType) methodCallDetails.getArgs()
+            .get(0)).getName());
+      assertEquals(curPage,
+            ((ProductPage) methodCallDetails.getArgs().get(1)).getPageNum());
+   }
+
+   public void testGetNumProducts() {
+      String productTypeName = "ProductTypeName";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --getNumProducts"
+                  + " --productTypeName " + productTypeName).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getNumProducts", methodCallDetails.getMethodName());
+      assertEquals(productTypeName, ((ProductType) methodCallDetails.getArgs()
+            .get(0)).getName());
+   }
+
+   public void testGetProductById() {
+      String productId = "TestProductId";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --getProductById"
+                  + " --productId " + productId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getProductById", methodCallDetails.getMethodName());
+      assertEquals(productId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetProductByName() {
+      String productName = "TestProductName";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --getProductByName"
+                  + " --productName " + productName).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getProductByName", methodCallDetails.getMethodName());
+      assertEquals(productName, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetProductPercnetTransferred() {
+      String productId = "TestProductId";
+      String productTypeName = "TestProductType";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --getProductPctTransferred"
+                  + " --productId " + productId + " --productTypeName " + productTypeName)
+                  .split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getProductPctTransferred",
+            methodCallDetails.getMethodName());
+      assertEquals(productId,
+            ((Product) methodCallDetails.getArgs().get(0)).getProductId());
+   }
+
+   public void testGetProductTypeByName() {
+      String productTypeName = "TestProductType";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --getProductTypeByName"
+                  + " --productTypeName " + productTypeName).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getProductTypeByName", methodCallDetails.getMethodName());
+      assertEquals(productTypeName, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testHasProduct() {
+      String productName = "TestProductName";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --hasProduct"
+                  + " --productName " + productName).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("hasProduct", methodCallDetails.getMethodName());
+      assertEquals(productName, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testIngestProduct() {
+     URL refUrl = this.getClass().getResource("/ingest/test.txt");
+     URL metUrl = this.getClass().getResource("/ingest/test.txt.met");
+
+      String productName = "TestProductName";
+      String structure = Product.STRUCTURE_FLAT;
+      String productTypeName = "TestProductType";
+      String metadataFile = new File(metUrl.getFile()).getAbsolutePath();
+      String dataTransferer = InPlaceDataTransferFactory.class
+            .getCanonicalName();
+      String ref = new File(refUrl.getFile()).getAbsolutePath();
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --ingestProduct"
+                  + " --productName " + productName + " --productStructure "
+                  + structure + " --productTypeName " + productTypeName
+                  + " --metadataFile " + metadataFile + " --refs " + ref
+                  + " --clientTransfer --dataTransfer " + dataTransferer)
+                  .split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("ingestProduct", methodCallDetails.getMethodName());
+      assertEquals(productName,
+            ((Product) methodCallDetails.getArgs().get(0)).getProductName());
+      assertEquals(structure,
+            ((Product) methodCallDetails.getArgs().get(0))
+                  .getProductStructure());
+      assertEquals(productTypeName,
+            ((Product) methodCallDetails.getArgs().get(0)).getProductType()
+                  .getName());
+      assertTrue(((Product) methodCallDetails.getArgs().get(0))
+            .getProductReferences().get(0).getOrigReference().endsWith(ref));
+
+      assertEquals("test.txt",
+            ((Metadata) methodCallDetails.getArgs().get(1))
+                  .getMetadata("Filename"));
+      assertEquals("GenericFile", ((Metadata) methodCallDetails.getArgs()
+            .get(1)).getMetadata("ProductType"));
+      assertEquals(true, methodCallDetails.getArgs().get(2));
+   }
+
+   public void testDumpMetadata() throws IOException {
+      String productId = "TestProductId";
+      File bogusFile = File.createTempFile("bogus", "bogus");
+      File tmpFile = new File(bogusFile.getParentFile(), "CliDumpMetadata");
+      tmpFile.mkdirs();
+      bogusFile.delete();
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --dumpMetadata"
+                  + " --productId " + productId).split(" "));
+
+      OptionPropertyRegister.clearRegister();
+
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getMetadata", methodCallDetails.getMethodName());
+      assertEquals(productId,
+            ((Product) methodCallDetails.getArgs().get(0)).getProductId());
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --dumpMetadata"
+                  + " --productId " + productId + " --outputDir " + tmpFile
+                  .getAbsolutePath()).split(" "));
+      FileUtils.forceDelete(tmpFile);
+   }
+
+   public void testLuceneQuery() {
+      String query = "ProductId:TestProductId";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --luceneQuery"
+                  + " --query " + query).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("complexQuery", methodCallDetails.getMethodName());
+      assertEquals("ProductId", ((TermQueryCriteria) ((Query) methodCallDetails
+            .getArgs().get(0)).getCriteria().get(0)).getElementName());
+      assertEquals("TestProductId",
+            ((TermQueryCriteria) ((Query) methodCallDetails.getArgs().get(0))
+                  .getCriteria().get(0)).getValue());
+
+      OptionPropertyRegister.clearRegister();
+
+      String reducedMetadataKeys = "ProductId ProductType";
+      String outputFormat = "$ProductId";
+      String reducedProductTypes = "TestProductType";
+      String sortBy = "ProductId";
+      String delimiter = ",";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --luceneQuery"
+                  + " --query " + query + " --reducedMetadataKeys " + reducedMetadataKeys
+                  + " --outputFormat " + outputFormat
+                  + " --reducedProductTypes " + reducedProductTypes
+                  + " --sortBy " + sortBy
+                  + " --delimiter " + delimiter).split(" "));
+      methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("complexQuery", methodCallDetails.getMethodName());
+      ComplexQuery complexQuery = (ComplexQuery) methodCallDetails.getArgs().get(0);
+      assertEquals("ProductId", ((TermQueryCriteria) complexQuery.getCriteria().get(0)).getElementName());
+      assertEquals("TestProductId",
+            ((TermQueryCriteria) complexQuery.getCriteria().get(0)).getValue());
+      assertEquals(Lists.newArrayList(reducedMetadataKeys.split(" ")), complexQuery.getReducedMetadata());
+      assertEquals(outputFormat, complexQuery.getToStringResultFormat());
+      assertEquals(Lists.newArrayList(reducedProductTypes.split(" ")), complexQuery.getReducedProductTypeNames());
+      assertEquals(sortBy, complexQuery.getSortByMetKey());
+   }
+
+   public void testRetrieveFilesById() {
+      String productId = "TestProductId";
+      String destination = "/tmp/toDir";
+      String transferer = "org.apache.oodt.cas.filemgr.datatransfer.InPlaceDataTransferFactory";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --retrieveFilesById"
+                  + " --productId " + productId + " --destination " + destination
+                  + " --transferer " + transferer).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getProductReferences", methodCallDetails.getMethodName());
+      assertEquals(productId, ((Product) methodCallDetails.getArgs().get(0)).getProductId());
+   }
+
+   public void testRetrieveFilesByName() {
+      String productName = "TestProductName";
+      String destination = "/tmp/toDir";
+      String transferer = "org.apache.oodt.cas.filemgr.datatransfer.InPlaceDataTransferFactory";
+      cmdLineUtility
+            .run(("--url http://localhost:9000 --operation --retrieveFilesByName"
+                  + " --productName " + productName + " --destination " + destination
+                  + " --transferer " + transferer).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getProductReferences", methodCallDetails.getMethodName());
+      assertEquals(productName, ((Product) methodCallDetails.getArgs().get(0)).getProductName());
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/UseMockClientCmdLineActionStore.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/UseMockClientCmdLineActionStore.java
new file mode 100644
index 0000000..9d526e1
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/UseMockClientCmdLineActionStore.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli;
+
+//JDK imports
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.action.store.spring.SpringCmdLineActionStore;
+import org.apache.oodt.cas.cli.exception.CmdLineActionStoreException;
+import org.apache.oodt.cas.filemgr.cli.action.FileManagerCliAction;
+import org.apache.oodt.cas.filemgr.system.MockXmlRpcFileManagerClient;
+
+/**
+ * A {@link SpringCmdLineActionStore} which sets {@link WorkflowCliAction}s
+ * to use a {@link MockXmlRpcWorkflowManagerClient}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class UseMockClientCmdLineActionStore extends SpringCmdLineActionStore {
+
+   private MockXmlRpcFileManagerClient client;
+
+   public UseMockClientCmdLineActionStore() {
+      super(System.getProperty("org.apache.oodt.cas.cli.action.spring.config"));
+      try {
+         client = new MockXmlRpcFileManagerClient();
+      } catch (Exception e) {
+         throw new RuntimeException(e);
+      }
+   }
+
+   public Set<CmdLineAction> loadSupportedActions() throws CmdLineActionStoreException {
+      Set<CmdLineAction> actions = super.loadSupportedActions();
+      for (CmdLineAction action : actions) {
+         if (action instanceof FileManagerCliAction) {
+            ((FileManagerCliAction) action).setClient(client);
+         }
+      }
+      return actions;
+   }
+
+   public MockXmlRpcFileManagerClient getClient() {
+      return client;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestAddProductTypeCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestAddProductTypeCliAction.java
new file mode 100644
index 0000000..f347a62
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestAddProductTypeCliAction.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.filemgr.versioning.BasicVersioner;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link AddProductTypeCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestAddProductTypeCliAction extends TestCase {
+
+   private static final String PRODUCT_TYPE_NAME = "TestProductTypeName";
+   private static final String PRODUCT_TYPE_ID = "TestProductTypeId";
+   private static final String PRODUCT_TYPE_DESC = "TestProductTypeDesc";
+   private static final String PRODUCT_TYPE_REPO = "TestProductTypeRepo";
+   private static final String PRODUCT_TYPE_VERSIONER = BasicVersioner.class
+         .getCanonicalName();
+
+   private static ProductType productTypePassedToClient;
+
+   public void testValidateErrors() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockAddProductTypeCliAction cliAction = new MockAddProductTypeCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction.setProductTypeDescription(PRODUCT_TYPE_DESC);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction.setFileRepositoryPath(PRODUCT_TYPE_REPO);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction.setVersioner(PRODUCT_TYPE_VERSIONER);
+      cliAction.execute(printer); // Should not throw exception.
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      MockAddProductTypeCliAction cliAction = new MockAddProductTypeCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setProductTypeDescription(PRODUCT_TYPE_DESC);
+      cliAction.setFileRepositoryPath(PRODUCT_TYPE_REPO);
+      cliAction.setVersioner(PRODUCT_TYPE_VERSIONER);
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("addProductType: Result: " + PRODUCT_TYPE_ID, printer
+            .getPrintedMessages().get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+
+      assertEquals(PRODUCT_TYPE_NAME, productTypePassedToClient.getName());
+      assertEquals(PRODUCT_TYPE_DESC,
+            productTypePassedToClient.getDescription());
+      assertEquals(PRODUCT_TYPE_REPO,
+            productTypePassedToClient.getProductRepositoryPath());
+      assertEquals(PRODUCT_TYPE_VERSIONER,
+            productTypePassedToClient.getVersioner());
+   }
+
+   public class MockAddProductTypeCliAction extends AddProductTypeCliAction {
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            public String addProductType(ProductType type) {
+               productTypePassedToClient = type;
+               return PRODUCT_TYPE_ID;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestDeleteProductByIdCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestDeleteProductByIdCliAction.java
new file mode 100644
index 0000000..1dd0c2d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestDeleteProductByIdCliAction.java
@@ -0,0 +1,208 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link DeleteProductByIdCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestDeleteProductByIdCliAction extends TestCase {
+
+   private static final String PRODUCT_ID = "TestProductId";
+   private static final String PRODUCT_NAME = "TestProductName";
+   private static final String REF_1 = "file:/ds/ref/1/path";
+   private static final String REF_2 = "file:/ds/ref/2/path";
+
+   private Product clientSetProduct;
+
+   @Override
+   public void setUp() throws Exception {
+      super.setUp();
+      clientSetProduct = null;
+   }
+
+   public void testValidateErrors() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockDeleteProductByIdCliAction cliAction = new MockDeleteProductByIdCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction.setProductId(PRODUCT_ID);
+      cliAction.execute(printer); // Should not throw exception.
+      cliAction = new NullProductDeleteProductByIdCliAction();
+      cliAction.setProductId(PRODUCT_ID);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction = new FalseDeleteProductByIdCliAction();
+      cliAction.setProductId(PRODUCT_ID);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction = new NullRefsDeleteProductByIdCliAction();
+      cliAction.setProductId(PRODUCT_ID);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockDeleteProductByIdCliAction cliAction = new MockDeleteProductByIdCliAction();
+      cliAction.setProductId(PRODUCT_ID);
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("Successfully deleted product '" + PRODUCT_NAME + "'",
+            printer.getPrintedMessages().get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals(PRODUCT_ID, clientSetProduct.getProductId());
+      assertEquals(PRODUCT_NAME, clientSetProduct.getProductName());
+      assertEquals(2, clientSetProduct.getProductReferences().size());
+      assertEquals(REF_1, clientSetProduct.getProductReferences().get(0)
+            .getDataStoreReference());
+      assertEquals(REF_2, clientSetProduct.getProductReferences().get(1)
+            .getDataStoreReference());
+   }
+
+   public class MockDeleteProductByIdCliAction extends
+         DeleteProductByIdCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public Product getProductById(String productId) {
+               Product p = new Product();
+               p.setProductId(productId);
+               p.setProductName(PRODUCT_NAME);
+               return p;
+            }
+            @Override
+            public List<Reference> getProductReferences(Product product) {
+               product.setProductReferences(Lists.newArrayList(new Reference(
+                     "file:/file/path", REF_1, 2), new Reference(
+                     "file:/file/path", REF_2, 2)));
+               return product.getProductReferences();
+            }
+            @Override
+            public boolean removeProduct(Product p) {
+               clientSetProduct = p;
+               return true;
+            }
+            @Override
+            public boolean removeFile(String file) {
+               return true;
+            }
+         };
+      }
+   }
+
+   public class NullProductDeleteProductByIdCliAction extends
+         MockDeleteProductByIdCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public Product getProductById(String productId) {
+               return null;
+            }
+         };
+      }
+   }
+
+   public class NullRefsDeleteProductByIdCliAction extends
+         MockDeleteProductByIdCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public Product getProductById(String productId) {
+               Product p = new Product();
+               p.setProductId(productId);
+               p.setProductName(PRODUCT_NAME);
+               return p;
+            }
+            @Override
+            public List<Reference> getProductReferences(Product product) {
+               return null;
+            }
+         };
+      }
+   }
+
+   public class FalseDeleteProductByIdCliAction extends
+         MockDeleteProductByIdCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public Product getProductById(String productId) {
+               Product p = new Product();
+               p.setProductId(productId);
+               p.setProductName(PRODUCT_NAME);
+               return p;
+            }
+            @Override
+            public List<Reference> getProductReferences(Product product) {
+               product.setProductReferences(Lists.newArrayList(new Reference(
+                     "file:/file/path", REF_1, 2), new Reference(
+                     "file:/file/path", REF_2, 2)));
+               return product.getProductReferences();
+            }
+            @Override
+            public boolean removeProduct(Product p) {
+               return false;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestDeleteProductByNameCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestDeleteProductByNameCliAction.java
new file mode 100644
index 0000000..2a14d76
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestDeleteProductByNameCliAction.java
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link DeleteProductByNameCliAction}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestDeleteProductByNameCliAction extends TestCase {
+
+   private static final String PRODUCT_ID = "TestProductId";
+   private static final String PRODUCT_NAME = "TestProductName";
+   private static final String REF_1 = "file:/ds/ref/1/path";
+   private static final String REF_2 = "file:/ds/ref/2/path";
+
+   private Product clientSetProduct;
+
+   @Override
+   public void setUp() throws Exception {
+      super.setUp();
+      clientSetProduct = null;
+   }
+
+   public void testValidateErrors() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockDeleteProductByNameCliAction cliAction = new MockDeleteProductByNameCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction.setProductName(PRODUCT_NAME);
+      cliAction.execute(printer); // Should not throw exception.
+      cliAction = new NullProductDeleteProductByNameCliAction();
+      cliAction.setProductName(PRODUCT_NAME);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }      
+      cliAction = new FalseDeleteProductByNameCliAction();
+      cliAction.setProductName(PRODUCT_NAME);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction = new NullRefsDeleteProductByNameCliAction();
+      cliAction.setProductName(PRODUCT_ID);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockDeleteProductByNameCliAction cliAction = new MockDeleteProductByNameCliAction();
+      cliAction.setProductName(PRODUCT_NAME);
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("Successfully deleted product '" + PRODUCT_NAME + "'",
+            printer.getPrintedMessages().get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals(PRODUCT_ID, clientSetProduct.getProductId());
+      assertEquals(PRODUCT_NAME, clientSetProduct.getProductName());
+      assertEquals(2, clientSetProduct.getProductReferences().size());
+      assertEquals(REF_1, clientSetProduct.getProductReferences().get(0)
+            .getDataStoreReference());
+      assertEquals(REF_2, clientSetProduct.getProductReferences().get(1)
+            .getDataStoreReference());
+   }
+   
+   public class MockDeleteProductByNameCliAction extends DeleteProductByNameCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public Product getProductByName(String productName) {
+               Product p = new Product();
+               p.setProductId(PRODUCT_ID);
+               p.setProductName(productName);
+               return p;
+            }
+            @Override
+            public List<Reference> getProductReferences(Product product) {
+               product.setProductReferences(Lists.newArrayList(new Reference(
+                     "file:/file/path", REF_1, 2), new Reference(
+                     "file:/file/path", REF_2, 2)));
+               return product.getProductReferences();
+            }
+            @Override
+            public boolean removeProduct(Product p) {
+               clientSetProduct = p;
+               return true;
+            }
+            @Override
+            public boolean removeFile(String file) {
+               return true;
+            }
+         };
+      }
+   }
+
+   public class NullProductDeleteProductByNameCliAction extends MockDeleteProductByNameCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public Product getProductByName(String productName) {
+               return null;
+            }
+         };
+      }
+   }
+
+   public class NullRefsDeleteProductByNameCliAction extends
+         MockDeleteProductByNameCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public List<Reference> getProductReferences(Product product) {
+               return null;
+            }
+         };
+      }
+   }
+
+   public class FalseDeleteProductByNameCliAction extends MockDeleteProductByNameCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public boolean removeProduct(Product p) {
+               return false;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestDumpMetadataCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestDumpMetadataCliAction.java
new file mode 100644
index 0000000..133eac7
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestDumpMetadataCliAction.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//OODT static imports
+import static org.apache.oodt.cas.filemgr.metadata.CoreMetKeys.FILENAME;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//Apache imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link DumpMetadataCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestDumpMetadataCliAction extends TestCase {
+
+   private static final String PRODUCT_ID = "TestProductId";
+   private static final String FILE_NAME = "data.dat";
+
+   private File tmpFile;
+
+   @Override
+   public void setUp() throws Exception {
+      File bogusFile = File.createTempFile("bogus", "bogus");
+      tmpFile = new File(bogusFile.getParentFile(), "MetadataDump");
+      tmpFile.mkdirs();
+      bogusFile.delete();
+   }
+
+   @Override
+   public void tearDown() throws Exception {
+      FileUtils.forceDelete(tmpFile);
+   }
+
+   public void testDataFlow() throws CmdLineActionException, IOException {
+      MockDumpMetadataCliAction cliAction = new MockDumpMetadataCliAction();
+      cliAction.setProductId(PRODUCT_ID);
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      cliAction.execute(printer);
+      assertEquals(
+            "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
+          + "<cas:metadata xmlns:cas=\"http://oodt.jpl.nasa.gov/1.0/cas\">\n"
+          + "<keyval type=\"vector\">\n"
+          + "<key>Filename</key>\n"
+          + "<val>data.dat</val>\n"
+          + "</keyval>\n"
+          + "</cas:metadata>\n",
+            printer.getPrintedMessages().get(0));
+
+      cliAction.setOutputDir(tmpFile);
+      cliAction.execute(printer);
+      assertTrue(new File(tmpFile, FILE_NAME + ".met").exists());
+      assertEquals(
+            "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
+            + "<cas:metadata xmlns:cas=\"http://oodt.jpl.nasa.gov/1.0/cas\">\n"
+            + "<keyval type=\"vector\">\n"
+            + "<key>Filename</key>\n"
+            + "<val>data.dat</val>\n"
+            + "</keyval>\n"
+            + "</cas:metadata>\n",
+            FileUtils.readFileToString(new File(tmpFile, FILE_NAME + ".met")));
+   }
+
+   public class MockDumpMetadataCliAction extends DumpMetadataCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public Product getProductById(String productId) {
+               Product p = new Product();
+               p.setProductId(productId);
+               return p;
+            }
+            @Override
+            public Metadata getMetadata(Product product) {
+               Metadata m = new Metadata();
+               m.addMetadata(FILENAME, FILE_NAME);
+               return m;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetCurrentTransferCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetCurrentTransferCliAction.java
new file mode 100644
index 0000000..de979cf
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetCurrentTransferCliAction.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link GetCurrentTransferCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestGetCurrentTransferCliAction extends TestCase {
+
+   private static final String ORIG_REF = "file:/orig/path";
+   private static final String DS_REF = "file:/ds/path";
+   private static final long FILE_SIZE = 20;
+   private static final long BYTE_TRANS = 10;
+   private static final String PRODUCT_NAME = "ProductName";
+
+   private static FileTransferStatus status;
+
+   public void testValidateErrors() {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      NullStatusGetCurrentTransferCliAction cliAction = new NullStatusGetCurrentTransferCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetCurrentTransferCliAction cliAction = new MockGetCurrentTransferCliAction();
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("File Transfer: [ref={orig=" + ORIG_REF + ",ds=" + DS_REF
+            + "},product=" + PRODUCT_NAME + ",fileSize=" + FILE_SIZE
+            + ",amtTransferred=" + BYTE_TRANS + ",pct=0.5]", printer
+            .getPrintedMessages().get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+   }
+
+   public class MockGetCurrentTransferCliAction extends
+         GetCurrentTransferCliAction {
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            public FileTransferStatus getCurrentFileTransfer() {
+               status = new FileTransferStatus();
+               status.setFileRef(new Reference(ORIG_REF, DS_REF, FILE_SIZE));
+               status.setBytesTransferred(BYTE_TRANS);
+               Product parentProduct = new Product();
+               parentProduct.setProductName(PRODUCT_NAME);
+               status.setParentProduct(parentProduct);
+               return status;
+            }
+         };
+      }
+   }
+
+   public class NullStatusGetCurrentTransferCliAction extends
+         GetCurrentTransferCliAction {
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            public FileTransferStatus getCurrentFileTransfer() {
+               return null;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetCurrentTransfersCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetCurrentTransfersCliAction.java
new file mode 100644
index 0000000..f065499
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetCurrentTransfersCliAction.java
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link GetCurrentTransfersCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestGetCurrentTransfersCliAction extends TestCase {
+
+   private static final String ORIG_REF = "file:/orig/path";
+   private static final String DS_REF = "file:/ds/path";
+   private static final long FILE_SIZE = 20;
+   private static final long BYTE_TRANS = 10;
+   private static final String PRODUCT_NAME = "ProductName";
+
+   private static FileTransferStatus status;
+
+   @Override
+   public void setUp() {
+      status = null;
+   }
+
+   public void testValidateErrors() {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      NullStatusGetCurrentTransfersCliAction cliAction = new NullStatusGetCurrentTransfersCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetCurrentTransfersCliAction cliAction = new MockGetCurrentTransfersCliAction();
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("File Transfer: [ref={orig=" + ORIG_REF + ",ds=" + DS_REF
+            + "},product=" + PRODUCT_NAME + ",fileSize=" + FILE_SIZE
+            + ",amtTransferred=" + BYTE_TRANS + ",pct=0.5]", printer
+            .getPrintedMessages().get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+   }
+
+   public class MockGetCurrentTransfersCliAction extends GetCurrentTransfersCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public List<FileTransferStatus> getCurrentFileTransfers() {
+               status = new FileTransferStatus();
+               status.setFileRef(new Reference(ORIG_REF, DS_REF, FILE_SIZE));
+               status.setBytesTransferred(BYTE_TRANS);
+               Product parentProduct = new Product();
+               parentProduct.setProductName(PRODUCT_NAME);
+               status.setParentProduct(parentProduct);
+               return Lists.newArrayList(status);
+            }
+         };
+      }
+   }
+
+   public class NullStatusGetCurrentTransfersCliAction extends
+         GetCurrentTransfersCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public List<FileTransferStatus> getCurrentFileTransfers() {
+               return null;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetFilePercentTransferredCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetFilePercentTransferredCliAction.java
new file mode 100644
index 0000000..ac09963
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetFilePercentTransferredCliAction.java
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link GetFilePercentTransferredCliAction}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestGetFilePercentTransferredCliAction extends TestCase {
+
+   private static final String ORIG_REF = "file:/orig/path";
+   private static final double PERCENT_TRANS = 0.6;
+
+   private static Reference referencePassedToClient;
+
+   @Override
+   public void setUp() {
+      referencePassedToClient = null;
+   }
+
+   public void testValidateErrors() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetFilePercentTransferredCliAction cliAction = new MockGetFilePercentTransferredCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {}
+      cliAction.setOrigRef(ORIG_REF);
+      cliAction.execute(printer); // Should not throw exception.
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetFilePercentTransferredCliAction cliAction = new MockGetFilePercentTransferredCliAction();
+      cliAction.setOrigRef(ORIG_REF);
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("Reference: [origRef=" + ORIG_REF + ",transferPct="
+            + PERCENT_TRANS + "]", printer.getPrintedMessages().get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+
+      assertEquals(ORIG_REF, referencePassedToClient.getOrigReference());
+   }
+
+   public class MockGetFilePercentTransferredCliAction extends GetFilePercentTransferredCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public double getRefPctTransferred(Reference reference) {
+               referencePassedToClient = reference;
+               return PERCENT_TRANS;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetFirstPageCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetFirstPageCliAction.java
new file mode 100644
index 0000000..4afb20e
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetFirstPageCliAction.java
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link GetFirstPageCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestGetFirstPageCliAction extends TestCase {
+
+   private static final int PAGE_NUM = 1;
+   private static final int TOTAL_PAGES = 1;
+   private static final int PAGE_SIZE = 10;
+   private static final String PRODUCT_ID = "TestProductId";
+   private static final String PRODUCT_NAME = "TestProductName";
+   private static final String PRODUCT_STRUCTURE = "Flat";
+   private static final String PRODUCT_STATUS = "DONE";
+   private static final String PRODUCT_TYPE_NAME = "TestProductType";
+
+   public void testValidateErrors() {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetFirstPageCliAction cliAction = new MockGetFirstPageCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction = new NullPTGetFirstPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction = new NullPPGetFirstPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetFirstPageCliAction cliAction = new MockGetFirstPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.execute(printer);
+      assertEquals(6, printer.getPrintedMessages().size());
+      assertEquals("Page: [num=" + PAGE_NUM + ", totalPages=" + TOTAL_PAGES
+            + ", pageSize=" + PAGE_SIZE + "]", printer.getPrintedMessages()
+            .get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals("Products:", printer.getPrintedMessages().get(2));
+      assertEquals("\n", printer.getPrintedMessages().get(3));
+      assertEquals("Product: [id=" + PRODUCT_ID + ",name=" + PRODUCT_NAME
+            + ",type=" + PRODUCT_TYPE_NAME + ",structure=" + PRODUCT_STRUCTURE
+            + ", transferStatus=" + PRODUCT_STATUS + "]", printer
+            .getPrintedMessages().get(4));
+      assertEquals("\n", printer.getPrintedMessages().get(5));
+   }
+
+   public class MockGetFirstPageCliAction extends GetFirstPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               ProductType pt = new ProductType();
+               pt.setName(name);
+               return pt;
+            }
+
+            @Override
+            public ProductPage getFirstPage(ProductType pt) {
+               ProductPage pp = new ProductPage();
+               pp.setPageNum(PAGE_NUM);
+               pp.setTotalPages(TOTAL_PAGES);
+               pp.setPageSize(PAGE_SIZE);
+               Product p = new Product();
+               p.setProductId(PRODUCT_ID);
+               p.setProductName(PRODUCT_NAME);
+               p.setProductType(pt);
+               p.setProductStructure(PRODUCT_STRUCTURE);
+               p.setTransferStatus(PRODUCT_STATUS);
+               pp.setPageProducts(Lists.newArrayList(p));
+               return pp;
+            }
+         };
+      }
+   }
+
+   public class NullPTGetFirstPageCliAction extends MockGetFirstPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               return null;
+            }
+         };
+      }
+   }
+
+   public class NullPPGetFirstPageCliAction extends MockGetFirstPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               ProductType pt = new ProductType();
+               pt.setName(name);
+               return pt;
+            }
+
+            @Override
+            public ProductPage getFirstPage(ProductType pt) {
+               return null;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetLastPageCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetLastPageCliAction.java
new file mode 100644
index 0000000..42b750d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetLastPageCliAction.java
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link GetLastPageCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestGetLastPageCliAction extends TestCase {
+
+   private static final int PAGE_NUM = 1;
+   private static final int TOTAL_PAGES = 1;
+   private static final int PAGE_SIZE = 10;
+   private static final String PRODUCT_ID = "TestProductId";
+   private static final String PRODUCT_NAME = "TestProductName";
+   private static final String PRODUCT_STRUCTURE = "Flat";
+   private static final String PRODUCT_STATUS = "DONE";
+   private static final String PRODUCT_TYPE_NAME = "TestProductType";
+
+   public void testValidateErrors() {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetLastPageCliAction cliAction = new MockGetLastPageCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction = new NullPTGetLastPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction = new NullPPGetLastPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetLastPageCliAction cliAction = new MockGetLastPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.execute(printer);
+      assertEquals(6, printer.getPrintedMessages().size());
+      assertEquals("Page: [num=" + PAGE_NUM + ", totalPages=" + TOTAL_PAGES
+            + ", pageSize=" + PAGE_SIZE + "]", printer.getPrintedMessages()
+            .get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals("Products:", printer.getPrintedMessages().get(2));
+      assertEquals("\n", printer.getPrintedMessages().get(3));
+      assertEquals("Product: [id=" + PRODUCT_ID + ",name=" + PRODUCT_NAME
+            + ",type=" + PRODUCT_TYPE_NAME + ",structure=" + PRODUCT_STRUCTURE
+            + ", transferStatus=" + PRODUCT_STATUS + "]", printer
+            .getPrintedMessages().get(4));
+      assertEquals("\n", printer.getPrintedMessages().get(5));
+   }
+
+   public class MockGetLastPageCliAction extends GetLastPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               ProductType pt = new ProductType();
+               pt.setName(name);
+               return pt;
+            }
+
+            @Override
+            public ProductPage getLastPage(ProductType pt) {
+               ProductPage pp = new ProductPage();
+               pp.setPageNum(PAGE_NUM);
+               pp.setTotalPages(TOTAL_PAGES);
+               pp.setPageSize(PAGE_SIZE);
+               Product p = new Product();
+               p.setProductId(PRODUCT_ID);
+               p.setProductName(PRODUCT_NAME);
+               p.setProductType(pt);
+               p.setProductStructure(PRODUCT_STRUCTURE);
+               p.setTransferStatus(PRODUCT_STATUS);
+               pp.setPageProducts(Lists.newArrayList(p));
+               return pp;
+            }
+         };
+      }
+   }
+
+   public class NullPTGetLastPageCliAction extends MockGetLastPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               return null;
+            }
+         };
+      }
+   }
+
+   public class NullPPGetLastPageCliAction extends MockGetLastPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               ProductType pt = new ProductType();
+               pt.setName(name);
+               return pt;
+            }
+
+            @Override
+            public ProductPage getLastPage(ProductType pt) {
+               return null;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetNextPageCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetNextPageCliAction.java
new file mode 100644
index 0000000..1362498
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetNextPageCliAction.java
@@ -0,0 +1,220 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JUnit imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link GetNextPageCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestGetNextPageCliAction extends TestCase {
+
+   private static final int PAGE_NUM = 1;
+   private static final int TOTAL_PAGES = 2;
+   private static final int PAGE_SIZE = 3;
+   private static final String PRODUCT_ID_1 = "TestProductId1";
+   private static final String PRODUCT_NAME_1 = "TestProductName1";
+   private static final String PRODUCT_ID_2 = "TestProductId2";
+   private static final String PRODUCT_NAME_2 = "TestProductName2";
+   private static final String PRODUCT_ID_3 = "TestProductId3";
+   private static final String PRODUCT_NAME_3 = "TestProductName3";
+   private static final String PRODUCT_ID_4 = "TestProductId4";
+   private static final String PRODUCT_NAME_4 = "TestProductName4";
+   private static final String PRODUCT_STRUCTURE = "Flat";
+   private static final String PRODUCT_STATUS = "DONE";
+   private static final String PRODUCT_TYPE_NAME = "TestProductType";
+
+   public void testValidateErrors() {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetNextPageCliAction cliAction = new MockGetNextPageCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction = new NullPTGetNextPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setCurrentPageNum(1);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction = new NullPPGetNextPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setCurrentPageNum(1);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction = new NullNPGetNextPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setCurrentPageNum(1);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetNextPageCliAction cliAction = new MockGetNextPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setCurrentPageNum(PAGE_NUM);
+      cliAction.execute(printer);
+      assertEquals(6, printer.getPrintedMessages().size());
+      assertEquals("Page: [num=" + (PAGE_NUM + 1) + ", totalPages="
+            + TOTAL_PAGES + ", pageSize=" + PAGE_SIZE + "]", printer
+            .getPrintedMessages().get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals("Products:", printer.getPrintedMessages().get(2));
+      assertEquals("\n", printer.getPrintedMessages().get(3));
+      assertEquals("Product: [id=" + PRODUCT_ID_4 + ",name=" + PRODUCT_NAME_4
+            + ",type=" + PRODUCT_TYPE_NAME + ",structure=" + PRODUCT_STRUCTURE
+            + ", transferStatus=" + PRODUCT_STATUS + "]", printer
+            .getPrintedMessages().get(4));
+      assertEquals("\n", printer.getPrintedMessages().get(5));
+   }
+
+   public class MockGetNextPageCliAction extends GetNextPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new MockXmlRpcFileManagerClient();
+      }
+   }
+
+   public class NullPTGetNextPageCliAction extends MockGetNextPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new MockXmlRpcFileManagerClient() {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               return null;
+            }
+         };
+      }
+   }
+
+   public class NullPPGetNextPageCliAction extends MockGetNextPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new MockXmlRpcFileManagerClient() {
+            @Override
+            public ProductPage getFirstPage(ProductType pt) {
+               return null;
+            }
+         };
+      }
+   }
+
+   public class NullNPGetNextPageCliAction extends MockGetNextPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new MockXmlRpcFileManagerClient() {
+            @Override
+            public ProductPage getNextPage(ProductType pt,
+                  ProductPage currentPage) {
+               return null;
+            }
+         };
+      }
+   }
+
+   public static class MockXmlRpcFileManagerClient extends
+         XmlRpcFileManagerClient {
+      public MockXmlRpcFileManagerClient() throws MalformedURLException,
+            ConnectionException {
+         super(new URL("http://localhost:9000"), false);
+      }
+
+      @Override
+      public ProductType getProductTypeByName(String name) {
+         ProductType pt = new ProductType();
+         pt.setName(name);
+         return pt;
+      }
+
+      @Override
+      public ProductPage getFirstPage(ProductType pt) {
+         ProductPage pp = new ProductPage();
+         pp.setPageNum(PAGE_NUM);
+         pp.setTotalPages(TOTAL_PAGES);
+         pp.setPageSize(PAGE_SIZE);
+         Product p1 = new Product();
+         p1.setProductId(PRODUCT_ID_1);
+         p1.setProductName(PRODUCT_NAME_1);
+         p1.setProductType(pt);
+         p1.setProductStructure(PRODUCT_STRUCTURE);
+         p1.setTransferStatus(PRODUCT_STATUS);
+         Product p2 = new Product();
+         p2.setProductId(PRODUCT_ID_2);
+         p2.setProductName(PRODUCT_NAME_2);
+         p2.setProductType(pt);
+         p2.setProductStructure(PRODUCT_STRUCTURE);
+         p2.setTransferStatus(PRODUCT_STATUS);
+         Product p3 = new Product();
+         p3.setProductId(PRODUCT_ID_3);
+         p3.setProductName(PRODUCT_NAME_3);
+         p3.setProductType(pt);
+         p3.setProductStructure(PRODUCT_STRUCTURE);
+         p3.setTransferStatus(PRODUCT_STATUS);
+         pp.setPageProducts(Lists.newArrayList(p1, p2, p3));
+         return pp;
+      }
+
+      @Override
+      public ProductPage getNextPage(ProductType pt, ProductPage currentPage) {
+         ProductPage pp = new ProductPage();
+         pp.setPageNum(currentPage.getPageNum() + 1);
+         pp.setTotalPages(currentPage.getTotalPages());
+         pp.setPageSize(currentPage.getPageSize());
+         Product p4 = new Product();
+         p4.setProductId(PRODUCT_ID_4);
+         p4.setProductName(PRODUCT_NAME_4);
+         p4.setProductType(pt);
+         p4.setProductStructure(PRODUCT_STRUCTURE);
+         p4.setTransferStatus(PRODUCT_STATUS);
+         pp.setPageProducts(Lists.newArrayList(p4));
+         return pp;
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetNumProductsCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetNumProductsCliAction.java
new file mode 100644
index 0000000..56ae7c5
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetNumProductsCliAction.java
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+/**
+ * Test class for {@link GetNumProductsCliAction}. 
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestGetNumProductsCliAction extends TestCase {
+
+   private static final int NUM_PRODUCTS = 10;
+   private static final String PRODUCT_TYPE_NAME = "TestProductType";
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetNumProductsCliAction cliAction = new MockGetNumProductsCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("Type: [" + PRODUCT_TYPE_NAME+ "], Num Products: [" + NUM_PRODUCTS + "]", printer.getPrintedMessages().get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+   }
+
+   public void testValidateErrors() {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      NullPTGetNumProductsCliAction cliAction = new NullPTGetNumProductsCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+
+   public class MockGetNumProductsCliAction extends GetNumProductsCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               ProductType pt = new ProductType();
+               pt.setName(name);
+               return pt;
+            }
+            @Override
+            public int getNumProducts(ProductType productType) {
+               return NUM_PRODUCTS;
+            }
+         };
+      }
+   }
+
+   public class NullPTGetNumProductsCliAction extends MockGetNumProductsCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               return null;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetPrevPageCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetPrevPageCliAction.java
new file mode 100644
index 0000000..7248870
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetPrevPageCliAction.java
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JUnit imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link GetPrevPageCliAction}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestGetPrevPageCliAction extends TestCase {
+
+   private static final int PAGE_NUM = 2;
+   private static final int TOTAL_PAGES = 2;
+   private static final int PAGE_SIZE = 3;
+   private static final String PRODUCT_ID_1 = "TestProductId1";
+   private static final String PRODUCT_NAME_1 = "TestProductName1";
+   private static final String PRODUCT_ID_2 = "TestProductId2";
+   private static final String PRODUCT_NAME_2 = "TestProductName2";
+   private static final String PRODUCT_ID_3 = "TestProductId3";
+   private static final String PRODUCT_NAME_3 = "TestProductName3";
+   private static final String PRODUCT_ID_4 = "TestProductId4";
+   private static final String PRODUCT_NAME_4 = "TestProductName4";
+   private static final String PRODUCT_STRUCTURE = "Flat";
+   private static final String PRODUCT_STATUS = "DONE";
+   private static final String PRODUCT_TYPE_NAME = "TestProductType";
+
+   public void testValidateErrors() {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      GetPrevPageCliAction cliAction = new NullPTGetPrevPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setCurrentPageNum(1);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction = new NullPPGetPrevPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setCurrentPageNum(1);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction = new NullNPGetPrevPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setCurrentPageNum(1);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetPrevPageCliAction cliAction = new MockGetPrevPageCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setCurrentPageNum(PAGE_NUM);
+      cliAction.execute(printer);
+      assertEquals(6, printer.getPrintedMessages().size());
+      assertEquals("Page: [num=" + (PAGE_NUM - 1) + ", totalPages=" + TOTAL_PAGES
+            + ", pageSize=" + PAGE_SIZE + "]", printer.getPrintedMessages()
+            .get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals("Products:", printer.getPrintedMessages().get(2));
+      assertEquals("\n", printer.getPrintedMessages().get(3));
+      assertEquals("Product: [id=" + PRODUCT_ID_4 + ",name=" + PRODUCT_NAME_4
+            + ",type=" + PRODUCT_TYPE_NAME + ",structure=" + PRODUCT_STRUCTURE
+            + ", transferStatus=" + PRODUCT_STATUS + "]", printer
+            .getPrintedMessages().get(4));
+      assertEquals("\n", printer.getPrintedMessages().get(5));
+   }
+
+   public class MockGetPrevPageCliAction extends GetPrevPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new MockXmlRpcFileManagerClient();
+      }
+   }
+
+   public class NullPTGetPrevPageCliAction extends MockGetPrevPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new MockXmlRpcFileManagerClient() {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               return null;
+            }
+         };
+      }
+   }
+
+   public class NullPPGetPrevPageCliAction extends MockGetPrevPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new MockXmlRpcFileManagerClient() {
+            @Override
+            public ProductPage getFirstPage(ProductType pt) {
+               return null;
+            }
+         };
+      }
+   }
+
+   public class NullNPGetPrevPageCliAction extends MockGetPrevPageCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new MockXmlRpcFileManagerClient() {
+            @Override
+            public ProductPage getPrevPage(ProductType pt,
+                  ProductPage currentPage) {
+               return null;
+            }
+         };
+      }
+   }
+
+   public static class MockXmlRpcFileManagerClient extends XmlRpcFileManagerClient {
+      public MockXmlRpcFileManagerClient() throws MalformedURLException,
+            ConnectionException {
+         super(new URL("http://localhost:9000"), false);
+      }
+      @Override
+      public ProductType getProductTypeByName(String name) {
+         ProductType pt = new ProductType();
+         pt.setName(name);
+         return pt;
+      }
+
+      @Override
+      public ProductPage getFirstPage(ProductType pt) {
+         ProductPage pp = new ProductPage();
+         pp.setPageNum(PAGE_NUM);
+         pp.setTotalPages(TOTAL_PAGES);
+         pp.setPageSize(PAGE_SIZE);
+         Product p1 = new Product();
+         p1.setProductId(PRODUCT_ID_1);
+         p1.setProductName(PRODUCT_NAME_1);
+         p1.setProductType(pt);
+         p1.setProductStructure(PRODUCT_STRUCTURE);
+         p1.setTransferStatus(PRODUCT_STATUS);
+         Product p2 = new Product();
+         p2.setProductId(PRODUCT_ID_2);
+         p2.setProductName(PRODUCT_NAME_2);
+         p2.setProductType(pt);
+         p2.setProductStructure(PRODUCT_STRUCTURE);
+         p2.setTransferStatus(PRODUCT_STATUS);
+         Product p3 = new Product();
+         p3.setProductId(PRODUCT_ID_3);
+         p3.setProductName(PRODUCT_NAME_3);
+         p3.setProductType(pt);
+         p3.setProductStructure(PRODUCT_STRUCTURE);
+         p3.setTransferStatus(PRODUCT_STATUS);
+         pp.setPageProducts(Lists.newArrayList(p1, p2, p3));
+         return pp;
+      }
+
+      @Override
+      public ProductPage getPrevPage(ProductType pt, ProductPage currentPage) {
+         ProductPage pp = new ProductPage();
+         pp.setPageNum(currentPage.getPageNum() - 1);
+         pp.setTotalPages(currentPage.getTotalPages());
+         pp.setPageSize(currentPage.getPageSize());
+         Product p4 = new Product();
+         p4.setProductId(PRODUCT_ID_4);
+         p4.setProductName(PRODUCT_NAME_4);
+         p4.setProductType(pt);
+         p4.setProductStructure(PRODUCT_STRUCTURE);
+         p4.setTransferStatus(PRODUCT_STATUS);
+         pp.setPageProducts(Lists.newArrayList(p4));
+         return pp;
+      }
+   };
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetProductByIdCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetProductByIdCliAction.java
new file mode 100644
index 0000000..5377178
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetProductByIdCliAction.java
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link GetProductByIdCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestGetProductByIdCliAction extends TestCase {
+
+   private static final String PRODUCT_ID = "TestProductId";
+   private static final String PRODUCT_NAME = "TestProductName";
+   private static final String PRODUCT_TYPE_NAME = "TestProductType";
+   private static final String PRODUCT_STRUCTURE = Product.STRUCTURE_FLAT;
+   private static final String PRODUCT_STATUS = Product.STATUS_RECEIVED;
+   private static final String ROOT_REF = "file:/root/ref/path";
+   private static final String ORIG_REF_1 = "file:/orig/ref/1/path";
+   private static final String DS_REF_1 = "file:/ds/ref/1/path";
+   private static final int FILE_SIZE_REF_1 = 2;
+   private static final String ORIG_REF_2 = "file:/orig/ref/2/path";
+   private static final String DS_REF_2 = "file:/ds/ref/2/path";
+   private static final int FILE_SIZE_REF_2 = 2;
+
+   public void testValidateErrors() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetProductByIdCliAction cliAction = new MockGetProductByIdCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction.setProductId(PRODUCT_ID);
+      cliAction.execute(printer); // Should not throw exception.
+      cliAction = new NullProductGetProductByIdCliAction();
+      cliAction.setProductId(PRODUCT_ID);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetProductByIdCliAction cliAction = new MockGetProductByIdCliAction();
+      cliAction.setProductId(PRODUCT_ID);
+      cliAction.execute(printer);
+      assertEquals(20, printer.getPrintedMessages().size());
+      assertEquals("Product:", printer.getPrintedMessages().get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals(" - ID: " + PRODUCT_ID, printer.getPrintedMessages().get(2));
+      assertEquals("\n", printer.getPrintedMessages().get(3));
+      assertEquals(" - Name: " + PRODUCT_NAME, printer.getPrintedMessages()
+            .get(4));
+      assertEquals("\n", printer.getPrintedMessages().get(5));
+      assertEquals(" - ProductType: " + PRODUCT_TYPE_NAME, printer
+            .getPrintedMessages().get(6));
+      assertEquals("\n", printer.getPrintedMessages().get(7));
+      assertEquals(" - Structure: " + PRODUCT_STRUCTURE, printer
+            .getPrintedMessages().get(8));
+      assertEquals("\n", printer.getPrintedMessages().get(9));
+      assertEquals(" - Status: " + PRODUCT_STATUS, printer.getPrintedMessages()
+            .get(10));
+      assertEquals("\n", printer.getPrintedMessages().get(11));
+      assertEquals(" - RootRef: " + ROOT_REF,
+            printer.getPrintedMessages().get(12));
+      assertEquals("\n", printer.getPrintedMessages().get(13));
+      assertEquals(" - References: ", printer.getPrintedMessages().get(14));
+      assertEquals("\n", printer.getPrintedMessages().get(15));
+      assertEquals("    - " + DS_REF_1 + " (" + FILE_SIZE_REF_1 + ")", printer
+            .getPrintedMessages().get(16));
+      assertEquals("\n", printer.getPrintedMessages().get(17));
+      assertEquals("    - " + DS_REF_2 + " (" + FILE_SIZE_REF_2 + ")", printer
+            .getPrintedMessages().get(18));
+      assertEquals("\n", printer.getPrintedMessages().get(19));
+   }
+
+   public class MockGetProductByIdCliAction extends GetProductByIdCliAction {
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            public Product getProductById(String productId) {
+               Product p = new Product();
+               p.setProductId(productId);
+               p.setProductName(PRODUCT_NAME);
+               ProductType pt = new ProductType();
+               pt.setName(PRODUCT_TYPE_NAME);
+               p.setProductType(pt);
+               p.setProductStructure(PRODUCT_STRUCTURE);
+               p.setTransferStatus(PRODUCT_STATUS);
+               p.setRootRef(new Reference("file:/dummy/path", ROOT_REF, 2));
+               p.setProductReferences(Lists.newArrayList(new Reference(
+                     ORIG_REF_1, DS_REF_1, FILE_SIZE_REF_1), new Reference(
+                     ORIG_REF_2, DS_REF_2, FILE_SIZE_REF_2)));
+               return p;
+            }
+         };
+      }
+   }
+
+   public class NullProductGetProductByIdCliAction extends MockGetProductByIdCliAction {
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            public Product getProductById(String productId) {
+               return null;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetProductByNameCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetProductByNameCliAction.java
new file mode 100644
index 0000000..059b687
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetProductByNameCliAction.java
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link GetProductByNameCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestGetProductByNameCliAction extends TestCase {
+
+   private static final String PRODUCT_ID = "TestProductId";
+   private static final String PRODUCT_NAME = "TestProductName";
+   private static final String PRODUCT_TYPE_NAME = "TestProductType";
+   private static final String PRODUCT_STRUCTURE = Product.STRUCTURE_FLAT;
+   private static final String PRODUCT_STATUS = Product.STATUS_RECEIVED;
+   private static final String ROOT_REF = "file:/root/ref/path";
+   private static final String ORIG_REF_1 = "file:/orig/ref/1/path";
+   private static final String DS_REF_1 = "file:/ds/ref/1/path";
+   private static final int FILE_SIZE_REF_1 = 2;
+   private static final String ORIG_REF_2 = "file:/orig/ref/2/path";
+   private static final String DS_REF_2 = "file:/ds/ref/2/path";
+   private static final int FILE_SIZE_REF_2 = 2;
+
+   public void testValidateErrors() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      GetProductByNameCliAction cliAction = new MockGetProductByNameCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction.setProductName(PRODUCT_NAME);
+      cliAction.execute(printer); // Should not throw exception.
+      cliAction = new NullProductGetProductByNameCliAction();
+      cliAction.setProductName(PRODUCT_NAME);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetProductByNameCliAction cliAction = new MockGetProductByNameCliAction();
+      cliAction.setProductName(PRODUCT_NAME);
+      cliAction.execute(printer);
+      assertEquals(20, printer.getPrintedMessages().size());
+      assertEquals("Product:", printer.getPrintedMessages().get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals(" - ID: " + PRODUCT_ID, printer.getPrintedMessages().get(2));
+      assertEquals("\n", printer.getPrintedMessages().get(3));
+      assertEquals(" - Name: " + PRODUCT_NAME, printer.getPrintedMessages()
+            .get(4));
+      assertEquals("\n", printer.getPrintedMessages().get(5));
+      assertEquals(" - ProductType: " + PRODUCT_TYPE_NAME, printer
+            .getPrintedMessages().get(6));
+      assertEquals("\n", printer.getPrintedMessages().get(7));
+      assertEquals(" - Structure: " + PRODUCT_STRUCTURE, printer
+            .getPrintedMessages().get(8));
+      assertEquals("\n", printer.getPrintedMessages().get(9));
+      assertEquals(" - Status: " + PRODUCT_STATUS, printer.getPrintedMessages()
+            .get(10));
+      assertEquals("\n", printer.getPrintedMessages().get(11));
+      assertEquals(" - RootRef: " + ROOT_REF,
+            printer.getPrintedMessages().get(12));
+      assertEquals("\n", printer.getPrintedMessages().get(13));
+      assertEquals(" - References: ", printer.getPrintedMessages().get(14));
+      assertEquals("\n", printer.getPrintedMessages().get(15));
+      assertEquals("    - " + DS_REF_1 + " (" + FILE_SIZE_REF_1 + ")", printer
+            .getPrintedMessages().get(16));
+      assertEquals("\n", printer.getPrintedMessages().get(17));
+      assertEquals("    - " + DS_REF_2 + " (" + FILE_SIZE_REF_2 + ")", printer
+            .getPrintedMessages().get(18));
+      assertEquals("\n", printer.getPrintedMessages().get(19));
+   }
+
+   public class MockGetProductByNameCliAction extends GetProductByNameCliAction {
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            public Product getProductByName(String name) {
+               Product p = new Product();
+               p.setProductId(PRODUCT_ID);
+               p.setProductName(name);
+               ProductType pt = new ProductType();
+               pt.setName(PRODUCT_TYPE_NAME);
+               p.setProductType(pt);
+               p.setProductStructure(PRODUCT_STRUCTURE);
+               p.setTransferStatus(PRODUCT_STATUS);
+               p.setRootRef(new Reference("file:/dummy/path", ROOT_REF, 2));
+               p.setProductReferences(Lists.newArrayList(new Reference(
+                     ORIG_REF_1, DS_REF_1, FILE_SIZE_REF_1), new Reference(
+                     ORIG_REF_2, DS_REF_2, FILE_SIZE_REF_2)));
+               return p;
+            }
+         };
+      }
+   }
+
+   public class NullProductGetProductByNameCliAction extends MockGetProductByNameCliAction {
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            public Product getProductByName(String name) {
+               return null;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetProductPercentTransferredCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetProductPercentTransferredCliAction.java
new file mode 100644
index 0000000..f9393f9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetProductPercentTransferredCliAction.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link GetProductPercentTransferredCliAction}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestGetProductPercentTransferredCliAction extends TestCase {
+
+   private static final String PRODUCT_ID = "TestProductId";
+   private static final String PRODUCT_TYPE_NAME = "TestProductType";
+   private static final double PERCENT_TRANSFERRED = 0.5;
+
+   public void testValidateErrors() {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      GetProductPercentTransferredCliAction cliAction = new NullPTGetProductPercentTransferredCliAction();
+      cliAction.setProductId(PRODUCT_ID);
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetProductPercentTransferredCliAction cliAction = new MockGetProductPercentTransferredCliAction();
+      cliAction.setProductId(PRODUCT_ID);
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("Product: [id=" + PRODUCT_ID + ", transferPct="
+            + PERCENT_TRANSFERRED + "]", printer.getPrintedMessages()
+            .get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+   }
+
+   public class MockGetProductPercentTransferredCliAction extends GetProductPercentTransferredCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               ProductType pt = new ProductType();
+               pt.setName(name);
+               return pt;
+            }
+            @Override
+            public double getProductPctTransferred(Product product) {
+               return PERCENT_TRANSFERRED;
+            }
+         };
+      }
+   }
+
+   public class NullPTGetProductPercentTransferredCliAction extends MockGetProductPercentTransferredCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               return null;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetProductTypeByNameCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetProductTypeByNameCliAction.java
new file mode 100644
index 0000000..8b1e6f3
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestGetProductTypeByNameCliAction.java
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JUnit imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.filemgr.versioning.BasicVersioner;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link GetProductTypeByNameCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestGetProductTypeByNameCliAction extends TestCase {
+
+   private static final String PRODUCT_TYPE_ID = "urn:oodt:TestProductType";
+   private static final String PRODUCT_TYPE_NAME = "TestProductType";
+   private static final String PRODUCT_TYPE_DESC = "ProductTypeDesc";
+   private static final String PRODUCT_TYPE_VERSIONER = BasicVersioner.class.getCanonicalName();
+   private static final String PRODUCT_TYPE_REPO = "/path/to/repo";
+
+   public void testValidateErrors() {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      GetProductTypeByNameCliAction cliAction = new NullPTGetProductTypeByNameCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockGetProductTypeByNameCliAction cliAction = new MockGetProductTypeByNameCliAction();
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("getProductTypeByName: Result: [name="
+               + PRODUCT_TYPE_NAME + ", description=" + PRODUCT_TYPE_DESC
+               + ", id=" + PRODUCT_TYPE_ID + ", versionerClass="
+               + PRODUCT_TYPE_VERSIONER + ", repositoryPath="
+               + PRODUCT_TYPE_REPO + "]", printer.getPrintedMessages().get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+   }
+
+   public class MockGetProductTypeByNameCliAction extends GetProductTypeByNameCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               ProductType pt = new ProductType();
+               pt.setProductTypeId(PRODUCT_TYPE_ID);
+               pt.setName(name);
+               pt.setDescription(PRODUCT_TYPE_DESC);
+               pt.setVersioner(PRODUCT_TYPE_VERSIONER);
+               pt.setProductRepositoryPath(PRODUCT_TYPE_REPO);
+               return pt;
+            }
+         };
+      }
+   }
+
+   public class NullPTGetProductTypeByNameCliAction extends MockGetProductTypeByNameCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String name) {
+               return null;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestHasProductCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestHasProductCliAction.java
new file mode 100644
index 0000000..0e5ddff
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestHasProductCliAction.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link HasProductCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestHasProductCliAction extends TestCase {
+
+   private static final boolean HAS_PRODUCT = true;
+   private static final String PRODUCT_NAME = "ProductName";
+
+   public void testValidateErrors() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockHasProductCliAction cliAction = new MockHasProductCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction.setProductName(PRODUCT_NAME);
+      cliAction.execute(printer); // Should not throw exception.
+   }
+   
+   public void testDataFlow() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockHasProductCliAction cliAction = new MockHasProductCliAction();
+      cliAction.setProductName(PRODUCT_NAME);
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("hasProduct: Result: " + HAS_PRODUCT, printer.getPrintedMessages().get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+   }
+
+   public class MockHasProductCliAction extends HasProductCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public boolean hasProduct(String productName) {
+               return HAS_PRODUCT;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestIngestProductCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestIngestProductCliAction.java
new file mode 100644
index 0000000..7655f54
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestIngestProductCliAction.java
@@ -0,0 +1,344 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Comparator;
+
+//Apache imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.datatransfer.DataTransfer;
+import org.apache.oodt.cas.filemgr.datatransfer.InPlaceDataTransferFactory;
+import org.apache.oodt.cas.filemgr.datatransfer.InPlaceDataTransferer;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link IngestProductCliAction}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestIngestProductCliAction extends TestCase {
+
+   private static final String FILENAME_MET_KEY = "Filename";
+   private static final String FILENAME_MET_VAL = "data.dat";
+   private static final String NOMINAL_DATE_MET_KEY = "NominalDate";
+   private static final String NOMINAL_DATE_MET_VAL = "2011-01-20";
+
+   private static final String PRODUCT_ID = "TestProductId";
+   private static final String PRODUCT_NAME = "TestProductName";
+   private static final String PRODUCT_TYPE_NAME = "TestProductType";
+   private static final String DATA_TRANSFERER_FACTORY = InPlaceDataTransferFactory.class.getCanonicalName();
+   private static final String DATA_TRANSFERER = InPlaceDataTransferer.class.getCanonicalName();
+   private static final String FLAT_REF_NAME = "flat_ref.txt";
+   private static final String HIER_REF_NAME = "hier_ref";
+   private static final String SUB_REF_1 = "sub_ref1.txt";
+   private static final String SUB_REF_2 = "sub_ref2.txt";
+
+   private DataTransfer clientSetDataTransferer;
+   private Product clientSetProduct;
+   private Metadata clientSetMetadata;
+
+   private File tmpDir;
+   private File metadataFile;
+   private File hierRefFile;
+   private File flatRefFile;
+
+   @Override
+   public void setUp() throws Exception {
+      super.setUp();
+      clientSetDataTransferer = null;
+      clientSetProduct = null;
+      clientSetMetadata = null;
+      tmpDir = createTmpDir();
+      metadataFile = createMetadataFile();
+      hierRefFile = createHierarchicalReference();
+      flatRefFile = createFlatReference();
+   }
+
+   @Override
+   public void tearDown() throws Exception {
+      FileUtils.forceDelete(tmpDir);
+   }
+
+   public void testValidateErrors() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      IngestProductCliAction cliAction = new MockIngestProductCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction.setProductName(PRODUCT_NAME);
+      cliAction.setProductStructure(Product.STRUCTURE_FLAT);
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setMetadataFile(metadataFile.getAbsolutePath());
+      cliAction.setReferences(Lists.newArrayList(flatRefFile.getAbsolutePath()));
+      cliAction.execute(printer); // Should not throw exception.
+      cliAction.setDataTransferer(DATA_TRANSFERER_FACTORY);
+      cliAction.execute(printer); // Should not throw exception.
+
+      cliAction = new NullPTIngestProductCliAction();
+      cliAction.setProductName(PRODUCT_NAME);
+      cliAction.setProductStructure(Product.STRUCTURE_FLAT);
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setMetadataFile(metadataFile.getAbsolutePath());
+      cliAction.setReferences(Lists.newArrayList(flatRefFile.getAbsolutePath()));
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+   }
+   
+   public void testClientTransTrueAndFlatProduct() throws CmdLineActionException, IOException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockIngestProductCliAction cliAction = new MockIngestProductCliAction();
+      cliAction.setProductName(PRODUCT_NAME);
+      cliAction.setProductStructure(Product.STRUCTURE_FLAT);
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setMetadataFile(metadataFile.getAbsolutePath());
+      cliAction.setDataTransferer(DATA_TRANSFERER_FACTORY);
+      cliAction.setReferences(Lists.newArrayList(flatRefFile.getAbsolutePath()));
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("ingestProduct: Result: " + PRODUCT_ID, printer.getPrintedMessages().get(0)); 
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals(PRODUCT_NAME, clientSetProduct.getProductName());
+      assertEquals(Product.STRUCTURE_FLAT, clientSetProduct.getProductStructure());
+      assertEquals(PRODUCT_TYPE_NAME, clientSetProduct.getProductType().getName());
+      assertEquals(1, clientSetProduct.getProductReferences().size());
+      assertEquals("file:" + flatRefFile.getAbsolutePath(), clientSetProduct.getProductReferences().get(0).getOrigReference());
+      assertEquals(DATA_TRANSFERER, clientSetDataTransferer.getClass().getCanonicalName());
+      assertEquals(2, clientSetMetadata.getAllKeys().size());
+      assertEquals(FILENAME_MET_VAL, clientSetMetadata.getMetadata(FILENAME_MET_KEY));
+      assertEquals(NOMINAL_DATE_MET_VAL, clientSetMetadata.getMetadata(NOMINAL_DATE_MET_KEY));
+   }
+
+   public void testClientTransFalseAndFlatProduct() throws CmdLineActionException, IOException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockIngestProductCliAction cliAction = new MockIngestProductCliAction();
+      cliAction.setProductName(PRODUCT_NAME);
+      cliAction.setProductStructure(Product.STRUCTURE_FLAT);
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setMetadataFile(metadataFile.getAbsolutePath());
+      cliAction.setReferences(Lists.newArrayList(flatRefFile.getAbsolutePath()));
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("ingestProduct: Result: " + PRODUCT_ID, printer.getPrintedMessages().get(0)); 
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals(PRODUCT_NAME, clientSetProduct.getProductName());
+      assertEquals(Product.STRUCTURE_FLAT, clientSetProduct.getProductStructure());
+      assertEquals(PRODUCT_TYPE_NAME, clientSetProduct.getProductType().getName());
+      assertEquals(1, clientSetProduct.getProductReferences().size());
+      assertEquals("file:" + flatRefFile.getAbsolutePath(), clientSetProduct.getProductReferences().get(0).getOrigReference());
+      assertNull(clientSetDataTransferer);
+      assertEquals(2, clientSetMetadata.getAllKeys().size());
+      assertEquals(FILENAME_MET_VAL, clientSetMetadata.getMetadata(FILENAME_MET_KEY));
+      assertEquals(NOMINAL_DATE_MET_VAL, clientSetMetadata.getMetadata(NOMINAL_DATE_MET_KEY));
+   }
+
+   public void testClientTransTrueAndHierProduct() throws CmdLineActionException, IOException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockIngestProductCliAction cliAction = new MockIngestProductCliAction();
+      cliAction.setProductName(PRODUCT_NAME);
+      cliAction.setProductStructure(Product.STRUCTURE_HIERARCHICAL);
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setMetadataFile(metadataFile.getAbsolutePath());
+      cliAction.setDataTransferer(DATA_TRANSFERER_FACTORY);
+      cliAction.setReferences(Lists.newArrayList(hierRefFile.getAbsolutePath()));
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("ingestProduct: Result: " + PRODUCT_ID, printer.getPrintedMessages().get(0)); 
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals(PRODUCT_NAME, clientSetProduct.getProductName());
+      assertEquals(Product.STRUCTURE_HIERARCHICAL, clientSetProduct.getProductStructure());
+      assertEquals(PRODUCT_TYPE_NAME, clientSetProduct.getProductType().getName());
+      assertEquals(3, clientSetProduct.getProductReferences().size());
+      Collections.sort(clientSetProduct.getProductReferences(), new Comparator<Reference>() {
+         @Override
+         public int compare(Reference ref1, Reference ref2) {
+            return ref1.getOrigReference().compareTo(ref2.getOrigReference());
+         }
+      });
+      assertEquals("file:" + hierRefFile.getAbsolutePath() + "/", clientSetProduct.getProductReferences().get(0).getOrigReference());
+      assertEquals("file:" + new File(hierRefFile, SUB_REF_1).getAbsolutePath(), clientSetProduct.getProductReferences().get(1).getOrigReference());
+      assertEquals("file:" + new File(hierRefFile, SUB_REF_2).getAbsolutePath(), clientSetProduct.getProductReferences().get(2).getOrigReference());
+      assertEquals(DATA_TRANSFERER, clientSetDataTransferer.getClass().getCanonicalName());
+      assertEquals(2, clientSetMetadata.getAllKeys().size());
+      assertEquals(FILENAME_MET_VAL, clientSetMetadata.getMetadata(FILENAME_MET_KEY));
+      assertEquals(NOMINAL_DATE_MET_VAL, clientSetMetadata.getMetadata(NOMINAL_DATE_MET_KEY));
+   }
+
+   public void testClientTransFalseAndHierProduct() throws CmdLineActionException, IOException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockIngestProductCliAction cliAction = new MockIngestProductCliAction();
+      cliAction.setProductName(PRODUCT_NAME);
+      cliAction.setProductStructure(Product.STRUCTURE_HIERARCHICAL);
+      cliAction.setProductTypeName(PRODUCT_TYPE_NAME);
+      cliAction.setMetadataFile(metadataFile.getAbsolutePath());
+      cliAction.setReferences(Lists.newArrayList(hierRefFile.getAbsolutePath()));
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("ingestProduct: Result: " + PRODUCT_ID, printer.getPrintedMessages().get(0)); 
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals(PRODUCT_NAME, clientSetProduct.getProductName());
+      assertEquals(Product.STRUCTURE_HIERARCHICAL, clientSetProduct.getProductStructure());
+      assertEquals(PRODUCT_TYPE_NAME, clientSetProduct.getProductType().getName());
+      assertEquals(3, clientSetProduct.getProductReferences().size());
+      Collections.sort(clientSetProduct.getProductReferences(), new Comparator<Reference>() {
+         @Override
+         public int compare(Reference ref1, Reference ref2) {
+            return ref1.getOrigReference().compareTo(ref2.getOrigReference());
+         }
+      });
+      assertEquals("file:" + hierRefFile.getAbsolutePath() + "/", clientSetProduct.getProductReferences().get(0).getOrigReference());
+      assertEquals("file:" + new File(hierRefFile, SUB_REF_1).getAbsolutePath(), clientSetProduct.getProductReferences().get(1).getOrigReference());
+      assertEquals("file:" + new File(hierRefFile, SUB_REF_2).getAbsolutePath(), clientSetProduct.getProductReferences().get(2).getOrigReference());
+      assertNull(clientSetDataTransferer);
+      assertEquals(2, clientSetMetadata.getAllKeys().size());
+      assertEquals(FILENAME_MET_VAL, clientSetMetadata.getMetadata(FILENAME_MET_KEY));
+      assertEquals(NOMINAL_DATE_MET_VAL, clientSetMetadata.getMetadata(NOMINAL_DATE_MET_KEY));
+   }
+
+   private File createTmpDir() throws IOException {
+      File bogusDir = File.createTempFile("bogus", "bogus");
+      File tmpDir = bogusDir.getParentFile();
+      bogusDir.delete();
+      tmpDir = new File(tmpDir, "Metadata");
+      tmpDir.mkdirs();
+      return tmpDir;
+   }
+
+   private File createMetadataFile() throws IOException {
+      File metadataFile = new File(tmpDir, "test.met");
+      metadataFile.deleteOnExit();
+      PrintStream ps = null;
+      try {
+         ps = new PrintStream(new FileOutputStream(metadataFile));
+         ps.println("<cas:metadata xmlns:cas=\"http://oodt.jpl.nasa.gov/1.0/cas\">");
+         ps.println("  <keyval type=\"scalar\">");
+         ps.println("    <key>" + FILENAME_MET_KEY + "</key>");
+         ps.println("    <val>" + FILENAME_MET_VAL + "</val>");
+         ps.println("  </keyval>");
+         ps.println("  <keyval type=\"scalar\">");
+         ps.println("    <key>" +  NOMINAL_DATE_MET_KEY +"</key>");
+         ps.println("    <val>" +  NOMINAL_DATE_MET_VAL + "</val>");
+         ps.println("  </keyval>");
+         ps.println("</cas:metadata>");
+      } catch (IOException e) {
+         throw e;
+      } finally {
+         ps.close();
+      }
+      return metadataFile;
+   }
+
+   private File createHierarchicalReference() throws IOException {
+      File reference = new File(tmpDir, HIER_REF_NAME);
+      reference.mkdirs();
+      PrintStream ps = null;
+      for (String subRef :  Lists.newArrayList(SUB_REF_1, SUB_REF_2)) {
+         try {
+            ps = new PrintStream(new FileOutputStream(new File(reference, subRef)));
+            ps.println("This is a test sub-reference file");
+         } catch (IOException e) {
+            throw e;
+         } finally {
+            ps.close();
+         }
+      }
+      return reference;
+   }
+
+
+   private File createFlatReference() throws IOException {
+      File reference = new File(tmpDir, FLAT_REF_NAME);
+      PrintStream ps = null;
+      try {
+         ps = new PrintStream(new FileOutputStream(reference));
+         ps.println("This is a test sub-reference file");
+      } catch (IOException e) {
+         throw e;
+      } finally {
+         ps.close();
+      }
+      return reference;
+   }
+
+   public class MockIngestProductCliAction extends IngestProductCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String typeName) {
+               ProductType pt = new ProductType();
+               pt.setName(typeName);
+               return pt;
+            }
+            @Override
+            public void setDataTransfer(DataTransfer dataTransferer) {
+               clientSetDataTransferer = dataTransferer;
+            }
+            @Override
+            public String ingestProduct(Product product, Metadata metadata,
+                  boolean useClientTransfer) {
+               clientSetProduct = product;
+               clientSetMetadata = metadata;
+               return PRODUCT_ID;
+            }
+         };
+      }
+   }
+
+   public class NullPTIngestProductCliAction extends MockIngestProductCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public ProductType getProductTypeByName(String typeName) {
+               return null;
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestLuceneQueryCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestLuceneQueryCliAction.java
new file mode 100644
index 0000000..3de2515
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestLuceneQueryCliAction.java
@@ -0,0 +1,215 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.BooleanQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.query.ComplexQuery;
+import org.apache.oodt.cas.filemgr.structs.query.QueryResult;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link LuceneQueryCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestLuceneQueryCliAction extends TestCase {
+
+   private static final String TEST_FILENAME = "data.dat";
+
+   private ComplexQuery clientSetQuery;
+
+   public void testValidation() {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockLuceneQueryCliAction cliAction = new MockLuceneQueryCliAction();
+      cliAction.setQuery("ProductId=TestProductId");
+      try {
+         cliAction.execute(printer);
+         fail("Should have throw exception");
+      } catch (Exception ignore) {
+      }
+      cliAction.setQuery("");
+      try {
+         cliAction.execute(printer);
+         fail("Should have throw exception");
+      } catch (Exception ignore) {
+      }
+   }
+
+   public void testClientTransTrueAndFlatProduct()
+         throws CmdLineActionException, IOException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockLuceneQueryCliAction cliAction = new MockLuceneQueryCliAction();
+
+      cliAction.setQuery("ProductId:TestProductId");
+      cliAction.execute(printer);
+      assertEquals(1, clientSetQuery.getCriteria().size());
+      assertEquals("ProductId", ((TermQueryCriteria) clientSetQuery
+            .getCriteria().get(0)).getElementName());
+      assertEquals("TestProductId", ((TermQueryCriteria) clientSetQuery
+            .getCriteria().get(0)).getValue());
+
+      cliAction.setQuery("ProductId:TestProductId ProductName:TestProductName");
+      cliAction.execute(printer);
+      assertEquals(1, clientSetQuery.getCriteria().size());
+      BooleanQueryCriteria bqc = (BooleanQueryCriteria) clientSetQuery
+            .getCriteria().get(0);
+      assertEquals(2, bqc.getTerms().size());
+      assertEquals(BooleanQueryCriteria.OR, bqc.getOperator());
+      assertEquals("ProductId",
+            ((TermQueryCriteria) bqc.getTerms().get(0)).getElementName());
+      assertEquals("TestProductId",
+            ((TermQueryCriteria) bqc.getTerms().get(0)).getValue());
+      assertEquals("ProductName",
+            ((TermQueryCriteria) bqc.getTerms().get(1)).getElementName());
+      assertEquals("TestProductName", ((TermQueryCriteria) bqc.getTerms()
+            .get(1)).getValue());
+
+      cliAction
+            .setQuery("ProductId:TestProductId NominalDate:[20020101 TO 20030101]");
+      cliAction.execute(printer);
+      assertEquals(1, clientSetQuery.getCriteria().size());
+      bqc = (BooleanQueryCriteria) clientSetQuery.getCriteria().get(0);
+      assertEquals(2, bqc.getTerms().size());
+      assertEquals(BooleanQueryCriteria.OR, bqc.getOperator());
+      assertEquals("ProductId",
+            ((TermQueryCriteria) bqc.getTerms().get(0)).getElementName());
+      assertEquals("TestProductId",
+            ((TermQueryCriteria) bqc.getTerms().get(0)).getValue());
+      assertEquals("NominalDate",
+            ((RangeQueryCriteria) bqc.getTerms().get(1)).getElementName());
+      assertEquals("20020101",
+            ((RangeQueryCriteria) bqc.getTerms().get(1)).getStartValue());
+      assertEquals("20030101",
+            ((RangeQueryCriteria) bqc.getTerms().get(1)).getEndValue());
+      assertTrue(((RangeQueryCriteria) bqc.getTerms().get(1)).getInclusive());
+
+      cliAction
+            .setQuery("ProductId:TestProductId NominalDate:{20020101 TO 20030101}");
+      cliAction.execute(printer);
+      cliAction.execute(printer);
+      assertEquals(1, clientSetQuery.getCriteria().size());
+      bqc = (BooleanQueryCriteria) clientSetQuery.getCriteria().get(0);
+      assertEquals(2, bqc.getTerms().size());
+      assertEquals(BooleanQueryCriteria.OR, bqc.getOperator());
+      assertEquals("ProductId",
+            ((TermQueryCriteria) bqc.getTerms().get(0)).getElementName());
+      assertEquals("TestProductId",
+            ((TermQueryCriteria) bqc.getTerms().get(0)).getValue());
+      assertEquals("NominalDate",
+            ((RangeQueryCriteria) bqc.getTerms().get(1)).getElementName());
+      assertEquals("20020101",
+            ((RangeQueryCriteria) bqc.getTerms().get(1)).getStartValue());
+      assertEquals("20030101",
+            ((RangeQueryCriteria) bqc.getTerms().get(1)).getEndValue());
+      assertFalse(((RangeQueryCriteria) bqc.getTerms().get(1)).getInclusive());
+
+      cliAction
+            .setQuery("ProductId:TestProductId AND ProductName:TestProductName");
+      cliAction.execute(printer);
+      assertEquals(1, clientSetQuery.getCriteria().size());
+      bqc = (BooleanQueryCriteria) clientSetQuery.getCriteria().get(0);
+      assertEquals(2, bqc.getTerms().size());
+      assertEquals(BooleanQueryCriteria.AND, bqc.getOperator());
+      assertEquals("ProductId",
+            ((TermQueryCriteria) bqc.getTerms().get(0)).getElementName());
+      assertEquals("TestProductId",
+            ((TermQueryCriteria) bqc.getTerms().get(0)).getValue());
+      assertEquals("ProductName",
+            ((TermQueryCriteria) bqc.getTerms().get(1)).getElementName());
+      assertEquals("TestProductName", ((TermQueryCriteria) bqc.getTerms()
+            .get(1)).getValue());
+
+      cliAction
+            .setQuery("ProductId:TestProductId OR ProductName:TestProductName");
+      cliAction.execute(printer);
+      assertEquals(1, clientSetQuery.getCriteria().size());
+      bqc = (BooleanQueryCriteria) clientSetQuery.getCriteria().get(0);
+      assertEquals(2, bqc.getTerms().size());
+      assertEquals(BooleanQueryCriteria.OR, bqc.getOperator());
+      assertEquals("ProductId",
+            ((TermQueryCriteria) bqc.getTerms().get(0)).getElementName());
+      assertEquals("TestProductId",
+            ((TermQueryCriteria) bqc.getTerms().get(0)).getValue());
+      assertEquals("ProductName",
+            ((TermQueryCriteria) bqc.getTerms().get(1)).getElementName());
+      assertEquals("TestProductName", ((TermQueryCriteria) bqc.getTerms()
+            .get(1)).getValue());
+
+      cliAction
+            .setQuery("(ProductId:TestProductId OR ProductName:TestProductName) AND NominalDate:20110120");
+      cliAction.execute(printer);
+      assertEquals(1, clientSetQuery.getCriteria().size());
+      bqc = (BooleanQueryCriteria) clientSetQuery.getCriteria().get(0);
+      assertEquals(2, bqc.getTerms().size());
+      assertEquals(BooleanQueryCriteria.AND, bqc.getOperator());
+      BooleanQueryCriteria subBqc = (BooleanQueryCriteria) bqc.getTerms()
+            .get(0);
+      assertEquals("ProductId",
+            ((TermQueryCriteria) subBqc.getTerms().get(0)).getElementName());
+      assertEquals("TestProductId",
+            ((TermQueryCriteria) subBqc.getTerms().get(0)).getValue());
+      assertEquals("ProductName",
+            ((TermQueryCriteria) subBqc.getTerms().get(1)).getElementName());
+      assertEquals("TestProductName", ((TermQueryCriteria) subBqc.getTerms()
+            .get(1)).getValue());
+      assertEquals("NominalDate",
+            ((TermQueryCriteria) bqc.getTerms().get(1)).getElementName());
+      assertEquals("20110120",
+            ((TermQueryCriteria) bqc.getTerms().get(1)).getValue());
+   }
+
+   public class MockLuceneQueryCliAction extends LuceneQueryCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public List<QueryResult> complexQuery(ComplexQuery complexQuery) {
+               clientSetQuery = complexQuery;
+               Product p = new Product();
+               p.setProductId("TestProductId");
+               Metadata m = new Metadata();
+               m.addMetadata("Filename", TEST_FILENAME);
+               QueryResult qr = new QueryResult(p, m);
+               qr.setToStringFormat(complexQuery.getToStringResultFormat());
+               return Lists.newArrayList(qr);
+            }
+         };
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestSqlQueryCliAction.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestSqlQueryCliAction.java
new file mode 100644
index 0000000..b76cae4
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/cli/action/TestSqlQueryCliAction.java
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.cli.action;
+
+//JDK imports
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.query.ComplexQuery;
+import org.apache.oodt.cas.filemgr.structs.query.QueryResult;
+import org.apache.oodt.cas.filemgr.structs.query.conv.VersionConverter;
+import org.apache.oodt.cas.filemgr.structs.query.filter.FilterAlgor;
+import org.apache.oodt.cas.filemgr.structs.query.filter.TimeEvent;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link SqlQueryCliAction}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestSqlQueryCliAction extends TestCase {
+
+   private static final String QUERY = "SELECT * FROM *";
+   private static final String SORT_BY = "Filename";
+   private static final String OUTPUT_FORMAT = "Filename = $Filename";
+   private static final String DELIMITER = ",";
+   private static final FilterAlgor FILTER_ALGOR = new MockFilterAlgor();
+   private static final String START_DATE_TIME_MET_KEY = "StartDateTime";
+   private static final String END_DATE_TIME_MET_KEY = "EndDateTime";
+   private static final String PRIORITY_DATE_TIME_MET_KEY = "PriorityDateTime";
+   private static final VersionConverter VERSION_CONV = new MockVersionConverter();
+
+   private static final String TEST_FILENAME = "data.dat";
+
+   private ComplexQuery clientSetComplexQuery;
+
+   public void testValidateErrors() throws CmdLineActionException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockSqlQueryCliAction cliAction = new MockSqlQueryCliAction();
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction.setQuery(QUERY);
+      cliAction.execute(printer); // Should not throw exception.
+      cliAction.setFilterAlgor(FILTER_ALGOR);
+      try {
+         cliAction.execute(printer);
+         fail("Expected throw CmdLineActionException");
+      } catch (CmdLineActionException ignore) {
+      }
+      cliAction.setStartDateTimeMetKey(START_DATE_TIME_MET_KEY);
+      cliAction.setEndDateTimeMetKey(END_DATE_TIME_MET_KEY);
+      cliAction.setPriorityMetKey(PRIORITY_DATE_TIME_MET_KEY);
+      cliAction.execute(printer); // Should not throw exception.
+      cliAction.setVersionConverter(VERSION_CONV);
+      cliAction.execute(printer); // Should not throw exception.
+   }
+
+   public void testClientTransTrueAndFlatProduct() throws CmdLineActionException, IOException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockSqlQueryCliAction cliAction = new MockSqlQueryCliAction();
+      cliAction.setQuery(QUERY);
+      cliAction.setSortBy(SORT_BY);
+      cliAction.setOutputFormat(OUTPUT_FORMAT);
+      cliAction.setDelimiter(DELIMITER);
+      cliAction.setFilterAlgor(FILTER_ALGOR);
+      cliAction.setStartDateTimeMetKey(START_DATE_TIME_MET_KEY);
+      cliAction.setEndDateTimeMetKey(END_DATE_TIME_MET_KEY);
+      cliAction.setPriorityMetKey(PRIORITY_DATE_TIME_MET_KEY);
+      cliAction.setVersionConverter(VERSION_CONV);
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      assertEquals("Filename = data.dat", printer.getPrintedMessages().get(0));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals(SORT_BY, clientSetComplexQuery.getSortByMetKey());
+      assertEquals(OUTPUT_FORMAT, clientSetComplexQuery.getToStringResultFormat());
+      assertNull(clientSetComplexQuery.getReducedProductTypeNames());
+      assertNull(clientSetComplexQuery.getReducedMetadata());
+      assertEquals(FILTER_ALGOR, clientSetComplexQuery.getQueryFilter().getFilterAlgor());
+      assertEquals(START_DATE_TIME_MET_KEY, clientSetComplexQuery.getQueryFilter().getStartDateTimeMetKey());
+      assertEquals(END_DATE_TIME_MET_KEY, clientSetComplexQuery.getQueryFilter().getEndDateTimeMetKey());
+      assertEquals(PRIORITY_DATE_TIME_MET_KEY, clientSetComplexQuery.getQueryFilter().getPriorityMetKey());
+      assertEquals(VERSION_CONV, clientSetComplexQuery.getQueryFilter().getConverter());
+   }
+
+   public void testClientTransTrueAndFlatProductAndNoOutputFormat() throws CmdLineActionException, IOException {
+      ActionMessagePrinter printer = new ActionMessagePrinter();
+      MockSqlQueryCliAction cliAction = new MockSqlQueryCliAction();
+      cliAction.setQuery(QUERY);
+      cliAction.setSortBy(SORT_BY);
+      cliAction.setDelimiter(DELIMITER);
+      cliAction.setFilterAlgor(FILTER_ALGOR);
+      cliAction.setStartDateTimeMetKey(START_DATE_TIME_MET_KEY);
+      cliAction.setEndDateTimeMetKey(END_DATE_TIME_MET_KEY);
+      cliAction.setPriorityMetKey(PRIORITY_DATE_TIME_MET_KEY);
+      cliAction.setVersionConverter(VERSION_CONV);
+      cliAction.execute(printer);
+      assertEquals(2, printer.getPrintedMessages().size());
+      String msg = printer.getPrintedMessages().get(0);
+      assertTrue(msg.contains("data.dat"));
+      assertTrue(msg.contains("Bob,Billy"));
+      assertEquals(",", msg.replace("data.dat","").replace("Bob,Billy",""));
+      assertEquals("\n", printer.getPrintedMessages().get(1));
+      assertEquals(SORT_BY, clientSetComplexQuery.getSortByMetKey());
+      assertNull(clientSetComplexQuery.getToStringResultFormat());
+      assertNull(clientSetComplexQuery.getReducedProductTypeNames());
+      assertNull(clientSetComplexQuery.getReducedMetadata());
+      assertEquals(FILTER_ALGOR, clientSetComplexQuery.getQueryFilter().getFilterAlgor());
+      assertEquals(START_DATE_TIME_MET_KEY, clientSetComplexQuery.getQueryFilter().getStartDateTimeMetKey());
+      assertEquals(END_DATE_TIME_MET_KEY, clientSetComplexQuery.getQueryFilter().getEndDateTimeMetKey());
+      assertEquals(PRIORITY_DATE_TIME_MET_KEY, clientSetComplexQuery.getQueryFilter().getPriorityMetKey());
+      assertEquals(VERSION_CONV, clientSetComplexQuery.getQueryFilter().getConverter());
+   }
+
+   public class MockSqlQueryCliAction extends SqlQueryCliAction {
+      @Override
+      public XmlRpcFileManagerClient getClient() throws MalformedURLException,
+            ConnectionException {
+         return new XmlRpcFileManagerClient(new URL("http://localhost:9000"),
+               false) {
+            @Override
+            public List<QueryResult> complexQuery(ComplexQuery complexQuery) {
+               clientSetComplexQuery = complexQuery;
+               Product p = new Product();
+               p.setProductId("TestProductId");
+               Metadata m = new Metadata();
+               m.addMetadata("Filename", TEST_FILENAME);
+               m.addMetadata("Owners", Lists.newArrayList("Bob", "Billy"));
+               QueryResult qr = new QueryResult(p, m);
+               qr.setToStringFormat(complexQuery.getToStringResultFormat());
+               return Lists.newArrayList(qr);
+            }
+         };
+      }
+   }
+
+   public static class MockFilterAlgor extends FilterAlgor {
+      @Override
+      public List<TimeEvent> filterEvents(List<TimeEvent> events) {
+         return events;
+      }
+   }
+
+   public static class MockVersionConverter implements VersionConverter {
+      @Override
+      public double convertToPriority(String version) throws Exception {
+         return 0;
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/datatransfer/TestInPlaceDataTransferer.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/datatransfer/TestInPlaceDataTransferer.java
new file mode 100644
index 0000000..34eb6d9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/datatransfer/TestInPlaceDataTransferer.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.datatransfer;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+
+//JDK imports
+import java.io.File;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class TestInPlaceDataTransferer extends TestCase {
+
+    private InPlaceDataTransferer transfer;
+
+    private String productOrigLoc;
+
+    private String productExpectedLoc;
+
+    public TestInPlaceDataTransferer() {
+        transfer = (InPlaceDataTransferer) new InPlaceDataTransferFactory()
+                .createDataTransfer();
+        try {
+            File tempFileSrc = File.createTempFile("foo", ".txt");
+            tempFileSrc.deleteOnExit();
+            productOrigLoc = tempFileSrc.getAbsolutePath();
+            productExpectedLoc = tempFileSrc.getParent();
+            if (!productExpectedLoc.endsWith("/")) {
+                productExpectedLoc += "/";
+            }
+
+            productExpectedLoc += "foo2.txt";
+
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+    public void testTransfer() {
+        Product testProduct = Product.getDefaultFlatProduct("test",
+                "urn:oodt:GenericFile");
+        testProduct.getProductReferences().add(
+                new Reference("file:" + productOrigLoc, "file:"
+                        + productExpectedLoc, 0L));
+
+        try {
+            transfer.transferProduct(testProduct);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // assert that it didn't transfer the file anywhere
+        assertFalse(new File(productExpectedLoc).exists());
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/datatransfer/TestLocalDataTransferer.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/datatransfer/TestLocalDataTransferer.java
new file mode 100644
index 0000000..cde641d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/datatransfer/TestLocalDataTransferer.java
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.datatransfer;
+
+//Apache imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.UUID;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link LocalDataTransferer}.
+ *
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public class TestLocalDataTransferer extends TestCase {
+
+   private LocalDataTransferer transfer;
+
+   private File origFile;
+   private File testDir;
+   private File repoDir;
+   private File repoFile;
+   private File destDir;
+   private File destFile;
+
+   public void setUp() throws Exception {
+      transfer = (LocalDataTransferer) new LocalDataTransferFactory()
+         .createDataTransfer();
+      URL url = this.getClass().getResource("/test.txt");
+      origFile = new File(url.getFile());
+      File testFile = File.createTempFile("test", ".txt");
+      testDir = new File(testFile.getParentFile(), UUID.randomUUID().toString());
+      repoDir = new File(testDir, "repo");
+      if (!repoDir.mkdirs()) {
+         throw new Exception("Failed to create repo directory!");
+      }
+      repoFile = new File(repoDir, "test.txt"); 
+      destDir = new File(testDir, "dest");
+      if (!destDir.mkdirs()) {
+         throw new Exception("Failed to create destination directory!");
+      }
+      destFile = new File(destDir, "test.txt"); 
+   }
+
+   public void tearDown() throws Exception {
+      FileUtils.forceDelete(testDir);
+   }
+
+   public void testTransferAndRetrieve() throws DataTransferException, IOException {
+      Product testProduct = createDummyProduct();
+
+      // Test transfer.
+      transfer.transferProduct(testProduct);
+
+      // Check that file was successfully transfered.
+      assertTrue("Repo file does not exist", repoFile.exists());
+      assertTrue("Repo file does not have the same contents as orig file",
+            FileUtils.contentEquals(origFile, repoFile));
+
+      // Test retrieve
+      transfer.retrieveProduct(testProduct, destDir);
+
+      // Check that file was successfully transfered.
+      assertTrue("Destination file does not exist", destFile.exists());
+      assertTrue("Destination file does not have the same contents as orig file",
+            FileUtils.contentEquals(origFile, destFile));
+   }
+
+   private Product createDummyProduct() {
+      Product testProduct = Product.getDefaultFlatProduct("test",
+            "urn:oodt:GenericFile");
+      testProduct.getProductReferences().add(
+            new Reference(origFile.toURI().toString(), new File(repoDir,
+                  "test.txt").toURI().toString(), origFile.length()));
+      return testProduct;
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/datatransfer/TestS3DataTransferer.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/datatransfer/TestS3DataTransferer.java
new file mode 100644
index 0000000..dd02cc7
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/datatransfer/TestS3DataTransferer.java
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.datatransfer;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.model.DeleteObjectRequest;
+import com.amazonaws.services.s3.model.GetObjectRequest;
+import com.amazonaws.services.s3.model.PutObjectRequest;
+import com.amazonaws.services.s3.model.S3Object;
+import com.amazonaws.services.s3.model.S3ObjectInputStream;
+import com.google.common.collect.Lists;
+
+/**
+ * Test class for {@link S3DataTransferer}.
+ * 
+ * @author bfoster@apache.org (Brian Foster)
+ */
+@RunWith(JUnit4.class)
+public class TestS3DataTransferer {
+
+	private final static String S3_BUCKET_NAME = "TestBucket";
+	private final static String ORGINAL_REF = "file:/path/to/file";
+	private final static String DATA_STORE_REF = "s3:/path/in/s3/storage/file";
+  private final static String EXPECTED_ORGINAL_REF = "/path/to/file";
+	private final static String EXPECTED_DATA_STORE_REF = "path/in/s3/storage/file";
+
+	@Rule
+	public TemporaryFolder tempFolder = new TemporaryFolder();
+
+	@Mock private AmazonS3 s3Client;
+	@Mock private Product product;
+	@Mock private Reference reference;
+	@Mock private S3Object s3Object;
+	@Mock private S3ObjectInputStream s3InputStream;
+
+	private S3DataTransferer dataTransferer;
+	private File stagingDir;
+
+	@Before
+	public void setUp() throws IOException {
+		MockitoAnnotations.initMocks(this);
+
+		stagingDir = tempFolder.getRoot();
+		dataTransferer = new S3DataTransferer(s3Client, S3_BUCKET_NAME, true);
+
+		when(reference.getOrigReference()).thenReturn(ORGINAL_REF);
+		when(reference.getDataStoreReference()).thenReturn(DATA_STORE_REF);		
+		when(product.getProductReferences()).thenReturn(Lists.newArrayList(reference));
+		when(s3Client.getObject(Mockito.<GetObjectRequest>any())).thenReturn(s3Object);
+		when(s3Object.getObjectContent()).thenReturn(s3InputStream);
+		when(s3InputStream.read(Mockito.<byte[]>any())).thenReturn(-1);
+	}
+
+	@Test
+	public void testTransferProduct() throws DataTransferException, IOException {
+		dataTransferer.transferProduct(product);
+
+		ArgumentCaptor<PutObjectRequest> argument = ArgumentCaptor.forClass(PutObjectRequest.class);
+		verify(s3Client).putObject(argument.capture());
+
+		PutObjectRequest request = argument.getValue();
+		assertThat(request.getBucketName(), is(S3_BUCKET_NAME));
+		assertThat(request.getKey(), is(EXPECTED_DATA_STORE_REF));
+		assertThat(request.getFile().getAbsolutePath(), is(EXPECTED_ORGINAL_REF));
+	}
+
+	@Test
+	public void testRetrieveProduct() throws DataTransferException, IOException {
+		dataTransferer.retrieveProduct(product, stagingDir);
+
+		ArgumentCaptor<GetObjectRequest> argument = ArgumentCaptor.forClass(GetObjectRequest.class);
+		verify(s3Client).getObject(argument.capture());
+
+		GetObjectRequest request = argument.getValue();
+		assertThat(request.getBucketName(), is(S3_BUCKET_NAME));
+		assertThat(request.getKey(), is(EXPECTED_DATA_STORE_REF));
+	}
+
+	@Test
+	public void testDeleteProduct() throws DataTransferException, IOException {
+	  dataTransferer.deleteProduct(product);
+
+    ArgumentCaptor<DeleteObjectRequest> argument = ArgumentCaptor
+        .forClass(DeleteObjectRequest.class);
+	  verify(s3Client).deleteObject(argument.capture());
+
+	  DeleteObjectRequest request = argument.getValue();
+	  assertThat(request.getBucketName(), is(S3_BUCKET_NAME));
+	  assertThat(request.getKey(), is(EXPECTED_DATA_STORE_REF));
+	}
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/datatransfer/TestS3DataTransfererFactory.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/datatransfer/TestS3DataTransfererFactory.java
new file mode 100644
index 0000000..6571c02
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/datatransfer/TestS3DataTransfererFactory.java
@@ -0,0 +1,44 @@
+package org.apache.oodt.cas.filemgr.datatransfer;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Test class for {@link S3DataTransfererFactory}.
+ * 
+ * @author bfoster@apache.org (Brian Foster)
+ */
+@RunWith(JUnit4.class)
+public class TestS3DataTransfererFactory {
+
+  private static final String BUCKET_NAME_PROPERTY =
+      "org.apache.oodt.cas.filemgr.datatransfer.s3.bucket.name";
+  private static final String REGION_PROPERTY =
+      "org.apache.oodt.cas.filemgr.datatransfer.s3.region";
+  private static final String ACCESS_KEY_PROPERTY =
+      "org.apache.oodt.cas.filemgr.datatransfer.s3.access.key";
+  private static final String SECRET_KEY_PROPERTY =
+      "org.apache.oodt.cas.filemgr.datatransfer.s3.secret.key";
+  private static final String ENCRYPT_PROPERTY =
+      "org.apache.oodt.cas.filemgr.datatransfer.s3.encrypt";
+
+  @Test
+  public void testCreateDataTransferer() {
+    System.setProperty(BUCKET_NAME_PROPERTY, "test-bucket");
+    System.setProperty(REGION_PROPERTY, "US_WEST_1");
+    System.setProperty(ACCESS_KEY_PROPERTY, "23123123123");
+    System.setProperty(SECRET_KEY_PROPERTY, "00101010101");
+    System.setProperty(ENCRYPT_PROPERTY, "true");
+
+    S3DataTransfererFactory factory = new S3DataTransfererFactory();
+    S3DataTransferer transferer = factory.createDataTransfer();
+
+    assertThat(transferer, is(not(nullValue())));
+  }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/ingest/TestCachedIngester.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/ingest/TestCachedIngester.java
new file mode 100644
index 0000000..fa809f7
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/ingest/TestCachedIngester.java
@@ -0,0 +1,292 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CacheException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManager;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+
+// Jnit imports
+import org.apache.oodt.commons.util.DateConvert;
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test suite for the {@link CachedIngester}.
+ * </p>.
+ */
+public class TestCachedIngester extends TestCase {
+
+    private static final int FM_PORT = 50010;
+
+    private XmlRpcFileManager fm;
+
+    private String luceneCatLoc;
+
+    private CachedIngester ingester;
+
+    private static final String RANGE_QUERY_ELEM = "CAS.ProductReceivedTime";
+
+    private static final String UNIQUE_ELEM = "CAS.ProductName";
+
+    private static final String GENERIC_FILE_TYPE = "GenericFile";
+
+    private static String DATE_RANGE_START;
+
+    private static String DATE_RANGE_END;
+
+    private static List cachedProductTypes = new Vector();
+
+    private Properties initialProperties = new Properties(
+        System.getProperties());
+
+    static {
+        Date startDate = new Date();
+        Date endDate = new Date();
+        endDate.setHours(startDate.getHours() + 1);
+        DATE_RANGE_START = DateConvert.isoFormat(startDate);
+        DATE_RANGE_END = DateConvert.isoFormat(endDate);
+        cachedProductTypes.add(GENERIC_FILE_TYPE);
+
+    }
+
+    private static final String transferServiceFacClass = "org.apache.oodt.cas."
+            + "filemgr.datatransfer.LocalDataTransferFactory";
+
+    public TestCachedIngester() {
+    }
+
+    public void testHasProduct() {
+        try {
+            ingester.resynsc();
+        } catch (CacheException e) {
+            fail(e.getMessage());
+        }
+        try {
+            assertTrue(ingester.hasProduct(new URL("http://localhost:"
+                    + FM_PORT), "test.txt"));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+    public void testIngest() {
+        Metadata prodMet = null;
+
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            URL refUrl = this.getClass().getResource("/ingest/test.txt");
+            URL metUrl = this.getClass().getResource("/ingest/test.txt.met");
+
+            prodMet = new SerializableMetadata(new FileInputStream(
+                new File(metUrl.getFile())));
+
+            // now add the right file location
+            prodMet.addMetadata(CoreMetKeys.FILE_LOCATION, new File(
+                ingestUrl.getFile()).getCanonicalPath());
+            ingester.ingest(new URL("http://localhost:" + FM_PORT), new File(
+                refUrl.getFile()), prodMet);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // now make sure that the file is ingested
+        try {
+            XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(
+                    new URL("http://localhost:" + FM_PORT));
+            Product p = fmClient.getProductByName("test.txt");
+            assertNotNull(p);
+            assertEquals(Product.STATUS_RECEIVED, p.getTransferStatus());
+            assertTrue(fmClient.hasProduct("test.txt"));
+            fmClient = null;
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+
+        startXmlRpcFileManager();
+        ingestTestFile();
+        Cache cache = null;
+
+        try {
+            cache = new LocalCache(new URL("http://localhost:" + FM_PORT),
+                    UNIQUE_ELEM, cachedProductTypes, RANGE_QUERY_ELEM,
+                    DATE_RANGE_START, DATE_RANGE_END);
+        } catch (Exception e) {
+            fail("This should never happen");
+        }
+        try {
+            ingester = new CachedIngester(transferServiceFacClass, cache);
+        } catch (InstantiationException e) {
+            fail(e.getMessage());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        fm.shutdown();
+        fm = null;
+
+        // blow away lucene cat
+        deleteAllFiles(luceneCatLoc);
+
+        // blow away test file
+        deleteAllFiles("/tmp/test.txt");
+
+        // Reset the System properties to initial values.
+        System.setProperties(initialProperties);
+    }
+
+    private void ingestTestFile() {
+        Metadata prodMet = null;
+        StdIngester ingester = new StdIngester(transferServiceFacClass);
+
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            URL refUrl = this.getClass().getResource("/ingest/test.txt");
+            URL metUrl = this.getClass().getResource("/ingest/test.txt.met");
+
+            prodMet = new SerializableMetadata(new FileInputStream(
+                new File(metUrl.getFile())));
+
+            // now add the right file location
+            prodMet.addMetadata(CoreMetKeys.FILE_LOCATION, new File(
+                ingestUrl.getFile()).getCanonicalPath());
+            ingester.ingest(new URL("http://localhost:" + FM_PORT), new File(
+                refUrl.getFile()), prodMet);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+    private void deleteAllFiles(String startDir) {
+        File startDirFile = new File(startDir);
+        File[] delFiles = startDirFile.listFiles();
+
+        if (delFiles != null && delFiles.length > 0) {
+            for (int i = 0; i < delFiles.length; i++) {
+                delFiles[i].delete();
+            }
+        }
+
+        startDirFile.delete();
+
+    }
+
+    private void startXmlRpcFileManager() {
+
+        Properties properties = new Properties(System.getProperties());
+
+        // first make sure to load properties for the file manager
+        // and make sure to load logging properties as well
+
+        // set the log levels
+        URL loggingPropertiesUrl = this.getClass().getResource(
+            "/test.logging.properties");
+        properties.setProperty("java.util.logging.config.file", new File(
+            loggingPropertiesUrl.getFile()).getAbsolutePath());
+
+        // first load the example configuration
+        try {
+            URL filemgrPropertiesUrl = this.getClass().getResource(
+                "/filemgr.properties");
+            properties.load(
+                new FileInputStream(new File(filemgrPropertiesUrl.getFile())));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // override the catalog to use: we'll use lucene
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            luceneCatLoc = new File(ingestUrl.getFile()).getCanonicalPath()
+                + "/cat";
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        properties.setProperty("filemgr.catalog.factory",
+                "org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.lucene.idxPath",
+                luceneCatLoc);
+
+        // now override the repo mgr policy
+        try {
+            URL fmpolicyUrl = this.getClass().getResource("/ingest/fmpolicy");
+            properties.setProperty(
+                    "org.apache.oodt.cas.filemgr.repositorymgr.dirs",
+                    "file://"
+                        + new File(fmpolicyUrl.getFile()).getCanonicalPath());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // now override the val layer ones
+        URL examplesCoreUrl = this.getClass().getResource("/examples/core");
+        properties.setProperty("org.apache.oodt.cas.filemgr.validation.dirs",
+                "file://"
+                    + new File(examplesCoreUrl.getFile()).getAbsolutePath());
+
+        // set up mime repo path
+        URL mimeTypesUrl = this.getClass().getResource("/mime-types.xml");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.mime.type.repository", new File(
+                     mimeTypesUrl.getFile()).getAbsolutePath());
+
+        System.setProperties(properties);
+
+        try {
+            fm = new XmlRpcFileManager(FM_PORT);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/ingest/TestLocalCache.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/ingest/TestLocalCache.java
new file mode 100644
index 0000000..92703b1
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/ingest/TestLocalCache.java
@@ -0,0 +1,302 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManager;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.filemgr.util.XmlRpcStructFactory;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.commons.util.DateConvert;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test suite for the {@link LocalCache}.
+ * </p>.
+ */
+public class TestLocalCache extends TestCase {
+
+    private LocalCache cache;
+
+    private static final int FM_PORT = 50010;
+
+    private XmlRpcFileManager fm;
+
+    private String luceneCatLoc;
+
+    private StdIngester ingester = new StdIngester(transferServiceFacClass);
+
+    private static final String transferServiceFacClass = "org.apache.oodt.cas."
+            + "filemgr.datatransfer.LocalDataTransferFactory";
+
+    private static final String FM_URL = "http://localhost:" + FM_PORT;
+
+    private static final String RANGE_QUERY_ELEM = "CAS.ProductReceivedTime";
+
+    private static final String UNIQUE_ELEM = "CAS.ProductName";
+
+    private static final String UNIQUE_ELEM2 = "CAS.ProductId";
+
+    private static final String GENERIC_FILE_TYPE = "GenericFile";
+
+    private static String DATE_RANGE_START;
+
+    private static String DATE_RANGE_END;
+
+    private static List<String> cachedProductTypes = new Vector<String>();
+
+    private Properties initialProperties = new Properties(
+        System.getProperties());
+
+    static {
+        Date startDate = new Date();
+        Date endDate = new Date();
+        endDate.setHours(startDate.getHours() + 1);
+        DATE_RANGE_START = DateConvert.isoFormat(startDate);
+        DATE_RANGE_END = DateConvert.isoFormat(endDate);
+        cachedProductTypes.add(GENERIC_FILE_TYPE);
+
+    }
+
+    public TestLocalCache() {
+    }
+
+    public void testSync() {
+        try {
+            cache.sync();
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(cache);
+        assertEquals(1, cache.size());
+        assertTrue(cache.contains("test.txt"));
+    }
+    
+    public void testClearCache(){
+        try {
+            cache.sync();
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(cache);
+        assertEquals(1, cache.size());
+        assertTrue(cache.contains("test.txt"));
+        cache.clear();
+        assertNotNull(cache);
+        assertEquals(0, cache.size());
+        assertFalse(cache.contains("test.txt"));
+    }
+
+    public void testSyncUsingProductId() {
+        try {
+            cache.sync(UNIQUE_ELEM2, cachedProductTypes);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(cache);
+        assertEquals(1, cache.size());
+
+        Product prod = null;
+        try {
+            prod = XmlRpcStructFactory.getProductFromXmlRpc(fm
+                    .getProductByName("test.txt"));
+        } catch (CatalogException e) {
+            fail(e.getMessage());
+        }
+        assertTrue(cache.contains(prod.getProductId()));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        startXmlRpcFileManager();
+        doIngest();
+        try {
+            cache = new LocalCache(new URL(FM_URL), UNIQUE_ELEM,
+                    cachedProductTypes, RANGE_QUERY_ELEM, DATE_RANGE_START,
+                    DATE_RANGE_END);
+        } catch (Exception e) {
+            fail("This should never happen");
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        fm.shutdown();
+        fm = null;
+
+        // blow away lucene cat
+        deleteAllFiles(luceneCatLoc);
+
+        // blow away test file
+        deleteAllFiles("/tmp/test.txt");
+
+        // Reset the System properties to initial values.
+        System.setProperties(initialProperties);
+    }
+
+    private void doIngest() {
+        Metadata prodMet = null;
+
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            URL refUrl = this.getClass().getResource("/ingest/test.txt");
+            URL metUrl = this.getClass().getResource("/ingest/test.txt.met");
+
+            prodMet = new SerializableMetadata(new FileInputStream(
+                new File(metUrl.getFile())));
+
+            // now add the right file location
+            prodMet.addMetadata(CoreMetKeys.FILE_LOCATION, new File(
+                ingestUrl.getFile()).getCanonicalPath());
+            ingester.ingest(new URL("http://localhost:" + FM_PORT), new File(
+                refUrl.getFile()), prodMet);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        // now make sure that the file is ingested
+        try {
+            XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(
+                    new URL("http://localhost:" + FM_PORT));
+            Product p = fmClient.getProductByName("test.txt");
+            assertNotNull(p);
+            assertEquals(Product.STATUS_RECEIVED, p.getTransferStatus());
+            assertTrue(fmClient.hasProduct("test.txt"));
+            fmClient = null;
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+    private void deleteAllFiles(String startDir) {
+        File startDirFile = new File(startDir);
+        File[] delFiles = startDirFile.listFiles();
+
+        if (delFiles != null && delFiles.length > 0) {
+            for (int i = 0; i < delFiles.length; i++) {
+                delFiles[i].delete();
+            }
+        }
+
+        startDirFile.delete();
+
+    }
+
+    private void startXmlRpcFileManager() {
+
+        Properties properties = new Properties(System.getProperties());
+
+        // first make sure to load properties for the file manager
+        // and make sure to load logging properties as well
+
+        // set the log levels
+        URL loggingPropertiesUrl = this.getClass().getResource(
+            "/test.logging.properties");
+        properties.setProperty("java.util.logging.config.file", new File(
+            loggingPropertiesUrl.getFile()).getAbsolutePath());
+
+        // first load the example configuration
+        try {
+          URL filemgrPropertiesUrl = this.getClass().getResource(
+              "/filemgr.properties");
+          properties.load(
+              new FileInputStream(new File(filemgrPropertiesUrl.getFile())));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // override the catalog to use: we'll use lucene
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            luceneCatLoc = new File(ingestUrl.getFile()).getCanonicalPath()
+                + "/cat";
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        properties.setProperty("filemgr.catalog.factory",
+                "org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.lucene.idxPath",
+                luceneCatLoc);
+
+        // now override the repo mgr policy
+        try {
+            URL fmpolicyUrl = this.getClass().getResource("/ingest/fmpolicy");
+            properties.setProperty(
+                    "org.apache.oodt.cas.filemgr.repositorymgr.dirs",
+                    "file://"
+                        + new File(fmpolicyUrl.getFile()).getCanonicalPath());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // now override the val layer ones
+        URL examplesCoreUrl = this.getClass().getResource("/examples/core");
+        properties.setProperty("org.apache.oodt.cas.filemgr.validation.dirs",
+                "file://"
+                    + new File(examplesCoreUrl.getFile()).getAbsolutePath());
+
+        // set up mime repo path
+        URL mimeTypesUrl = this.getClass().getResource("/mime-types.xml");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.mime.type.repository", new File(
+                     mimeTypesUrl.getFile()).getAbsolutePath());
+
+        System.setProperties(properties);
+
+        try {
+            fm = new XmlRpcFileManager(FM_PORT);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/ingest/TestRmiCache.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/ingest/TestRmiCache.java
new file mode 100644
index 0000000..5b4f71a
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/ingest/TestRmiCache.java
@@ -0,0 +1,318 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManager;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.filemgr.util.XmlRpcStructFactory;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.commons.util.DateConvert;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test suite for the {@link RmiCache} and the {@link RmiCacheServer}
+ * </p>.
+ */
+public class TestRmiCache extends TestCase {
+
+    private RmiCache cache;
+
+    private RmiCacheServer cacheServer;
+
+    private static final int FM_PORT = 50010;
+
+    private static final int RMI_PORT = 50011;
+
+    private static final String rmiServerURN = "rmi://localhost:" + RMI_PORT
+            + "/RmiDatabaseServer";
+
+    private XmlRpcFileManager fm;
+
+    private String luceneCatLoc;
+
+    private StdIngester ingester = new StdIngester(transferServiceFacClass);
+
+    private static final String transferServiceFacClass = "org.apache.oodt.cas."
+            + "filemgr.datatransfer.LocalDataTransferFactory";
+
+    private static final String FM_URL = "http://localhost:" + FM_PORT;
+
+    private static final String RANGE_QUERY_ELEM = "CAS.ProductReceivedTime";
+
+    private static final String UNIQUE_ELEM = "CAS.ProductName";
+
+    private static final String UNIQUE_ELEM2 = "CAS.ProductId";
+
+    private static final String GENERIC_FILE_TYPE = "GenericFile";
+
+    private static String DATE_RANGE_START;
+
+    private static String DATE_RANGE_END;
+
+    private static List<String> cachedProductTypes = new Vector<String>();
+
+    private Properties initialProperties = new Properties(
+        System.getProperties());
+
+    static {
+        Date startDate = new Date();
+        Date endDate = new Date();
+        endDate.setHours(startDate.getHours() + 1);
+        DATE_RANGE_START = DateConvert.isoFormat(startDate);
+        DATE_RANGE_END = DateConvert.isoFormat(endDate);
+        cachedProductTypes.add(GENERIC_FILE_TYPE);
+
+    }
+
+    public TestRmiCache() {
+    }
+
+    public void testSync() {
+        try {
+            cache.sync();
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(cache);
+        assertEquals(1, cache.size());
+        assertTrue(cache.contains("test.txt"));
+    }
+
+    public void testClearCache() {
+        try {
+            cache.sync();
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(cache);
+        assertEquals(1, cache.size());
+        assertTrue(cache.contains("test.txt"));
+        cache.clear();
+        assertNotNull(cache);
+        assertEquals(0, cache.size());
+        assertFalse(cache.contains("test.txt"));
+    }
+
+    public void testSyncUsingProductId() {
+        try {
+            cache.sync(UNIQUE_ELEM2, cachedProductTypes);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(cache);
+        assertEquals(1, cache.size());
+
+        Product prod = null;
+        try {
+            prod = XmlRpcStructFactory.getProductFromXmlRpc(fm
+                    .getProductByName("test.txt"));
+        } catch (CatalogException e) {
+            fail(e.getMessage());
+        }
+        assertTrue(cache.contains(prod.getProductId()));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        startXmlRpcFileManager();
+        doIngest();
+        try {
+            cacheServer = new RmiCacheServer(new URL(FM_URL), RANGE_QUERY_ELEM,
+                    DATE_RANGE_START, DATE_RANGE_END, UNIQUE_ELEM,
+                    cachedProductTypes);
+            cacheServer.launchServer(new URL(FM_URL), RMI_PORT);
+            cache = new RmiCache(rmiServerURN);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail("Error performing test setup: Message: " + e.getMessage());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        fm.shutdown();
+        fm = null;
+
+        // blow away lucene cat
+        deleteAllFiles(luceneCatLoc);
+
+        // blow away test file
+        deleteAllFiles("/tmp/test.txt");
+
+        // clean up RMI
+        cacheServer.stopServer(RMI_PORT);
+        cacheServer = null;
+
+        cache = null;
+
+        // Reset the System properties to initial values.
+        System.setProperties(initialProperties);
+    }
+
+    private void doIngest() {
+        Metadata prodMet = null;
+
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            URL refUrl = this.getClass().getResource("/ingest/test.txt");
+            URL metUrl = this.getClass().getResource("/ingest/test.txt.met");
+
+            prodMet = new SerializableMetadata(new FileInputStream(
+                new File(metUrl.getFile())));
+
+            // now add the right file location
+            prodMet.addMetadata(CoreMetKeys.FILE_LOCATION, new File(
+                ingestUrl.getFile()).getCanonicalPath());
+            ingester.ingest(new URL("http://localhost:" + FM_PORT), new File(
+                refUrl.getFile()), prodMet);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        // now make sure that the file is ingested
+        try {
+            XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(
+                    new URL("http://localhost:" + FM_PORT));
+            Product p = fmClient.getProductByName("test.txt");
+            assertNotNull(p);
+            assertEquals(Product.STATUS_RECEIVED, p.getTransferStatus());
+            assertTrue(fmClient.hasProduct("test.txt"));
+            fmClient = null;
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+    private void deleteAllFiles(String startDir) {
+        File startDirFile = new File(startDir);
+        File[] delFiles = startDirFile.listFiles();
+
+        if (delFiles != null && delFiles.length > 0) {
+            for (int i = 0; i < delFiles.length; i++) {
+                delFiles[i].delete();
+            }
+        }
+
+        startDirFile.delete();
+
+    }
+
+    private void startXmlRpcFileManager() {
+
+        Properties properties = new Properties(System.getProperties());
+
+        // first make sure to load properties for the file manager
+        // and make sure to load logging properties as well
+
+        // set the log levels
+        URL loggingPropertiesUrl = this.getClass().getResource(
+            "/test.logging.properties");
+        properties.setProperty("java.util.logging.config.file", new File(
+            loggingPropertiesUrl.getFile()).getAbsolutePath());
+
+        // first load the example configuration
+        try {
+          URL filemgrPropertiesUrl = this.getClass().getResource(
+              "/filemgr.properties");
+          properties.load(
+              new FileInputStream(new File(filemgrPropertiesUrl.getFile())));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // override the catalog to use: we'll use lucene
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            luceneCatLoc = new File(ingestUrl.getFile()).getCanonicalPath()
+                + "/cat";
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        properties.setProperty("filemgr.catalog.factory",
+                "org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.lucene.idxPath",
+                luceneCatLoc);
+
+        // now override the repo mgr policy
+        try {
+            URL fmpolicyUrl = this.getClass().getResource("/ingest/fmpolicy");
+            properties.setProperty(
+                    "org.apache.oodt.cas.filemgr.repositorymgr.dirs",
+                    "file://"
+                        + new File(fmpolicyUrl.getFile()).getCanonicalPath());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // now override the val layer ones
+        URL examplesCoreUrl = this.getClass().getResource("/examples/core");
+        properties.setProperty("org.apache.oodt.cas.filemgr.validation.dirs",
+                "file://"
+                    + new File(examplesCoreUrl.getFile()).getAbsolutePath());
+
+        // set up mime repo path
+        URL mimeTypesUrl = this.getClass().getResource("/mime-types.xml");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.mime.type.repository", new File(
+                     mimeTypesUrl.getFile()).getAbsolutePath());
+
+        System.setProperties(properties);
+
+        try {
+            fm = new XmlRpcFileManager(FM_PORT);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/ingest/TestStdIngester.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/ingest/TestStdIngester.java
new file mode 100644
index 0000000..d1f4cfa
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/ingest/TestStdIngester.java
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.ingest;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.Properties;
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManager;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+
+// Jnit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class TestStdIngester extends TestCase {
+
+    private static final int FM_PORT = 50010;
+
+    private XmlRpcFileManager fm;
+
+    private String luceneCatLoc;
+
+    private StdIngester ingester;
+
+    private static final String transferServiceFacClass = "org.apache.oodt.cas."
+            + "filemgr.datatransfer.LocalDataTransferFactory";
+
+    private Properties initialProperties = new Properties(
+        System.getProperties());
+
+    public TestStdIngester() {
+        ingester = new StdIngester(transferServiceFacClass);
+    }
+
+    public void testIngest() {
+        Metadata prodMet = null;
+
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            URL refUrl = this.getClass().getResource("/ingest/test.txt");
+            URL metUrl = this.getClass().getResource("/ingest/test.txt.met");
+
+            prodMet = new SerializableMetadata(new FileInputStream(
+                new File(metUrl.getFile())));
+
+            // now add the right file location
+            prodMet.addMetadata(CoreMetKeys.FILE_LOCATION, new File(
+                ingestUrl.getFile()).getCanonicalPath());
+            ingester.ingest(new URL("http://localhost:" + FM_PORT), new File(
+                refUrl.getFile()), prodMet);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+        
+        // now make sure that the file is ingested
+        try {
+            XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(new URL("http://localhost:"+FM_PORT));
+            Product p = fmClient.getProductByName("test.txt");
+            assertNotNull(p);
+            assertEquals(Product.STATUS_RECEIVED, p.getTransferStatus());
+            assertTrue(fmClient.hasProduct("test.txt"));
+            fmClient = null;
+        } catch (Exception e){
+            fail(e.getMessage());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        startXmlRpcFileManager();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        fm.shutdown();
+        fm = null;
+
+        // blow away lucene cat
+        deleteAllFiles(luceneCatLoc);
+
+        // blow away test file
+        deleteAllFiles("/tmp/test.txt");
+
+        // Reset the System properties to initial values.
+        System.setProperties(initialProperties);
+    }
+
+    private void deleteAllFiles(String startDir) {
+        File startDirFile = new File(startDir);
+        File[] delFiles = startDirFile.listFiles();
+
+        if (delFiles != null && delFiles.length > 0) {
+            for (int i = 0; i < delFiles.length; i++) {
+                delFiles[i].delete();
+            }
+        }
+
+        startDirFile.delete();
+
+    }
+
+    private void startXmlRpcFileManager() {
+
+        Properties properties = new Properties(System.getProperties());
+
+        // first make sure to load properties for the file manager
+        // and make sure to load logging properties as well
+
+        // set the log levels
+        URL loggingPropertiesUrl = this.getClass().getResource(
+            "/test.logging.properties");
+        properties.setProperty("java.util.logging.config.file", new File(
+            loggingPropertiesUrl.getFile()).getAbsolutePath());
+
+        // first load the example configuration
+        try {
+          URL filemgrPropertiesUrl = this.getClass().getResource(
+              "/filemgr.properties");
+          properties.load(
+              new FileInputStream(new File(filemgrPropertiesUrl.getFile())));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // override the catalog to use: we'll use lucene
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            luceneCatLoc = new File(ingestUrl.getFile()).getCanonicalPath()
+                + "/cat";
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        properties.setProperty("filemgr.catalog.factory",
+                "org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.lucene.idxPath",
+                luceneCatLoc);
+
+        // now override the repo mgr policy
+        try {
+            URL fmpolicyUrl = this.getClass().getResource("/ingest/fmpolicy");
+            properties.setProperty(
+                    "org.apache.oodt.cas.filemgr.repositorymgr.dirs",
+                    "file://"
+                        + new File(fmpolicyUrl.getFile()).getCanonicalPath());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // now override the val layer ones
+        URL examplesCoreUrl = this.getClass().getResource("/examples/core");
+        properties.setProperty("org.apache.oodt.cas.filemgr.validation.dirs",
+                "file://"
+                    + new File(examplesCoreUrl.getFile()).getAbsolutePath());
+
+        // set up mime repo path
+        URL mimeTypesUrl = this.getClass().getResource("/mime-types.xml");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.mime.type.repository", new File(
+                     mimeTypesUrl.getFile()).getAbsolutePath());
+
+        System.setProperties(properties);
+
+        try {
+            fm = new XmlRpcFileManager(FM_PORT);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/TestAbstractFilemgrMetExtractor.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/TestAbstractFilemgrMetExtractor.java
new file mode 100644
index 0000000..4b1e1d8
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/TestAbstractFilemgrMetExtractor.java
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.metadata.extractors;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * @since OODT-256
+ * 
+ * <p>
+ * Test suite for the {@link AbstractFilemgrMetExtractor}.
+ * </p>.
+ */
+public class TestAbstractFilemgrMetExtractor extends TestCase {
+
+    AbstractFilemgrMetExtractor absExtractor;
+
+    static final String tmpDirName = "fooabsTest";
+
+    static String tmpDirFullPath;
+
+    static {
+        try {
+            tmpDirFullPath = File.createTempFile("foo", "bar1").getParent();
+            tmpDirFullPath = !tmpDirFullPath.endsWith("/") ? tmpDirFullPath += "/"
+                    : tmpDirFullPath;
+            tmpDirFullPath += tmpDirName;
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        // create temp dir
+        new File(tmpDirFullPath).mkdirs();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // delete tmp dir
+        new File(tmpDirFullPath).delete();
+    }
+
+    public void testGetProdFileHierarchicalProd() {
+        absExtractor = new AbstractFilemgrMetExtractor() {
+
+            @Override
+            public Metadata doExtract(Product product, Metadata met)
+                    throws MetExtractionException {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            @Override
+            public void doConfigure() {
+                // TODO Auto-generated method stub
+
+            }
+
+        };
+        Product prod = Product.getDefaultFlatProduct("footest",
+                "urn:oodt:GenericFile");
+        String refUri = null;
+        try {
+            refUri = new File(tmpDirFullPath).toURL().toExternalForm();
+            prod.setProductStructure(Product.STRUCTURE_HIERARCHICAL);
+            prod.getProductType()
+                    .setProductRepositoryPath(
+                            new File(tmpDirFullPath).getParentFile().toURL()
+                                    .toString());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+        prod.getProductReferences().add(new Reference(refUri, refUri, 0L));
+
+        try {
+            File prodFile = absExtractor.getProductFile(prod);
+            assertNotNull(prodFile);
+            assertTrue(prodFile.isDirectory());
+        } catch (MetExtractionException e) {
+            fail(e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/TestCoreMetExtractor.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/TestCoreMetExtractor.java
new file mode 100644
index 0000000..612ea7a
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/TestCoreMetExtractor.java
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.metadata.extractors;
+
+//JDK imports
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test suite for the {@link CoreMetExtractor}.
+ * </p>.
+ */
+public class TestCoreMetExtractor extends TestCase implements CoreMetKeys {
+
+    private CoreMetExtractor extractor = new CoreMetExtractor();
+    
+    public TestCoreMetExtractor(){
+        Properties config = new Properties();
+        config.setProperty("nsAware", String.valueOf(false));
+        config.setProperty("elementNs", "CAS");
+        extractor.configure(config);
+    }
+
+    public void testExtract() {
+        Reference ref = new Reference();
+        ref.setOrigReference("file:/foo/bar/file.ext");
+        ref.setDataStoreReference("file:/foo/bar/final/file.ext");
+
+        List refs = new Vector();
+        refs.add(ref);
+
+        Product product = new Product();
+        product.setProductId("1");
+        product.setProductName("foo");
+        product.setProductReferences(refs);
+        product.setProductStructure(Product.STRUCTURE_FLAT);
+        product.setRootRef(ref);
+
+        ProductType type = new ProductType();
+        type.setName("FooType");
+        product.setProductType(type);
+
+        Metadata met = new Metadata();
+        try {
+            met = extractor.doExtract(product, met);
+        } catch (MetExtractionException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(met);
+        assertTrue(met.containsKey(FILENAME));
+        assertTrue(met.containsKey(FILE_LOCATION));
+        assertTrue(met.containsKey(PRODUCT_TYPE));
+        assertTrue(met.containsKey(PRODUCT_STRUCTURE));
+        assertTrue(met.containsKey(PRODUCT_ID));
+        assertTrue(met.containsKey(PRODUCT_NAME));
+        assertTrue(met.containsKey(PRODUCT_RECEVIED_TIME));
+
+        assertEquals(met.getMetadata(FILENAME), "file.ext");
+        assertEquals(met.getMetadata(FILE_LOCATION), "/foo/bar");
+        assertEquals(met.getMetadata(PRODUCT_TYPE), "FooType");
+        assertEquals(met.getMetadata(PRODUCT_STRUCTURE), Product.STRUCTURE_FLAT);
+        assertEquals(met.getMetadata(PRODUCT_ID), "1");
+        assertEquals(met.getMetadata(PRODUCT_NAME), "foo");
+
+    }
+    
+    public void testExtractDirectoryProduct(){
+      Product p = Product.getDefaultFlatProduct("test", "urn:oodt:GenericFile");
+      p.setProductId("1");
+      p.setProductStructure(Product.STRUCTURE_HIERARCHICAL);
+      p.setProductName("somedir");
+      p.getProductType().setProductRepositoryPath("file:///archive/dirs");
+      p.getProductType().setName("GenericFile");
+      p.getProductType().setVersioner(
+          "org.apache.oodt.cas.filemgr.versioning.DirectoryProductVersioner");
+      p.getProductReferences()
+          .add(new Reference("file:///tmp/somedir", null, 4L));
+      p.getProductReferences().add(
+          new Reference("file:///tmp/somedir/file1.txt", null, 8L));
+      p.getProductReferences().add(
+          new Reference("file:///tmp/somedir/file2.txt", null, 8L));
+
+      Metadata met = new Metadata();
+      try {
+          met = extractor.doExtract(p, met);
+      } catch (MetExtractionException e) {
+          fail(e.getMessage());
+      }
+
+      assertNotNull(met);
+      assertTrue(met.containsKey(FILENAME));
+      assertTrue(met.containsKey(FILE_LOCATION));
+      assertTrue(met.containsKey(PRODUCT_TYPE));
+      assertTrue(met.containsKey(PRODUCT_STRUCTURE));
+      assertTrue(met.containsKey(PRODUCT_ID));
+      assertTrue(met.containsKey(PRODUCT_NAME));
+      assertTrue(met.containsKey(PRODUCT_RECEVIED_TIME));
+
+      assertEquals(met.getMetadata(FILENAME), "somedir");
+      assertEquals(met.getMetadata(FILE_LOCATION), "/tmp");
+      assertEquals(met.getMetadata(PRODUCT_TYPE), "GenericFile");
+      assertEquals(met.getMetadata(PRODUCT_STRUCTURE), Product.STRUCTURE_HIERARCHICAL);
+      assertEquals(met.getMetadata(PRODUCT_ID), "1");
+      assertEquals(met.getMetadata(PRODUCT_NAME), "somedir");
+      
+      
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/TestDateTimeExpandMetExtractor.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/TestDateTimeExpandMetExtractor.java
new file mode 100644
index 0000000..8d569aa
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/TestDateTimeExpandMetExtractor.java
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.metadata.extractors.examples;
+
+// JUnit static imports
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
+
+// JDK imports
+import java.util.Properties;
+
+// OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+// JUnit imports
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+// Mockito imports
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Test class for {@link DateTimeExpandMetExtractor}.
+ * 
+ * @author bfoster@apache.org (Brian Foster)
+ */
+@RunWith(JUnit4.class)
+public class TestDateTimeExpandMetExtractor {
+
+  @Rule public ExpectedException expectedException = ExpectedException.none();
+
+  @Mock private Properties configuration;
+
+  private Metadata metadata;
+  private DateTimeExpandMetExtractor extractor;
+
+  @Before
+  public void setUp() {
+    MockitoAnnotations.initMocks(this);
+
+    when(configuration.getProperty("FullDateTimeKey")).thenReturn("StartDateTime");
+    when(configuration.getProperty("FullDateTimeFormat")).thenReturn("yyyy-MM-dd HH:mm:ss");
+    when(configuration.getProperty("YearKey")).thenReturn("StartYear");
+    when(configuration.getProperty("MonthKey")).thenReturn("StartMonth");
+    when(configuration.getProperty("DayKey")).thenReturn("StartDay");
+    when(configuration.getProperty("HourKey")).thenReturn("StartHour");
+    when(configuration.getProperty("MinuteKey")).thenReturn("StartMinute");
+    when(configuration.getProperty("SecondKey")).thenReturn("StartSecond");
+
+    metadata = new Metadata();
+    metadata.addMetadata("StartDateTime", "2013-05-23 03:02:01");
+
+    extractor = new DateTimeExpandMetExtractor();
+  }
+
+  @Test
+  public void testExpandAll() throws MetExtractionException {
+    when(configuration.containsKey("FullDateTimeKey")).thenReturn(true);
+    when(configuration.containsKey("FullDateTimeFormat")).thenReturn(true);
+    when(configuration.containsKey("YearKey")).thenReturn(true);
+    when(configuration.containsKey("MonthKey")).thenReturn(true);
+    when(configuration.containsKey("DayKey")).thenReturn(true);
+    when(configuration.containsKey("HourKey")).thenReturn(true);
+    when(configuration.containsKey("MinuteKey")).thenReturn(true);
+    when(configuration.containsKey("SecondKey")).thenReturn(true);
+
+    extractor.configure(configuration);
+    Metadata extractedMetadata = extractor.doExtract(null, metadata);
+
+    assertThat(extractedMetadata.getMetadata("StartYear"), is("2013"));
+    assertThat(extractedMetadata.getMetadata("StartMonth"), is("05"));
+    assertThat(extractedMetadata.getMetadata("StartDay"), is("23"));
+    assertThat(extractedMetadata.getMetadata("StartHour"), is("03"));
+    assertThat(extractedMetadata.getMetadata("StartMinute"), is("02"));
+    assertThat(extractedMetadata.getMetadata("StartSecond"), is("01"));
+  }
+
+  @Test
+  public void testExpandSome() throws MetExtractionException {
+    when(configuration.containsKey("FullDateTimeKey")).thenReturn(true);
+    when(configuration.containsKey("FullDateTimeFormat")).thenReturn(true);
+    when(configuration.containsKey("YearKey")).thenReturn(true);
+    when(configuration.containsKey("MonthKey")).thenReturn(true);
+    when(configuration.containsKey("DayKey")).thenReturn(true);
+
+    extractor.configure(configuration);
+    Metadata extractedMetadata = extractor.doExtract(null, metadata);
+
+    assertThat(extractedMetadata.getMetadata("StartYear"), is("2013"));
+    assertThat(extractedMetadata.getMetadata("StartMonth"), is("05"));
+    assertThat(extractedMetadata.getMetadata("StartDay"), is("23"));
+    assertThat(extractedMetadata.containsKey("StartHour"), is(false));
+    assertThat(extractedMetadata.containsKey("StartMinute"), is(false));
+    assertThat(extractedMetadata.containsKey("StartSecond"), is(false));
+  }
+
+  @Test
+  public void testFailure() throws MetExtractionException {
+    when(configuration.containsKey("FullDateTimeKey")).thenReturn(false);
+
+    extractor.configure(configuration);
+    expectedException.expect(MetExtractionException.class);
+    extractor.doExtract(null, metadata);
+  }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/TestFilenameRegexMetExtractor.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/TestFilenameRegexMetExtractor.java
new file mode 100644
index 0000000..467b81d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/TestFilenameRegexMetExtractor.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.metadata.extractors.examples;
+
+//JDK imports
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.extractors.examples.FilenameRegexMetExtractor;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author nchung
+ * @version $Revision$
+ * 
+ * <p>
+ * Test suite for the {@link FilenameRegexMetExtractor}.
+ * </p>.
+ */
+public class TestFilenameRegexMetExtractor extends TestCase {
+
+   public void testExtract() {
+      Properties config = new Properties();
+      config.setProperty("filenamePattern", "(\\w*)_(\\d*)\\.txt");
+      config.setProperty("metadataKeys", "Name,ID");
+      FilenameRegexMetExtractor extractor = new FilenameRegexMetExtractor();
+      extractor.configure(config);
+
+      Reference ref = new Reference();
+      ref.setOrigReference("file:/foo/bar/foobar_001.txt");
+      ref.setDataStoreReference("file:/foo/bar/final/foobar_001.txt");
+
+      Product product = new Product();
+      product.getProductReferences().add(ref);
+      product.setProductStructure(Product.STRUCTURE_FLAT);
+
+      Metadata met = new Metadata();
+      try {
+         met = extractor.doExtract(product, met);
+      } catch (MetExtractionException e) {
+         fail(e.getMessage());
+      }
+
+      assertTrue(met.containsKey("Name"));
+      assertTrue(met.containsKey("ID"));
+
+      assertEquals("foobar", met.getMetadata("Name"));
+      assertEquals("001", met.getMetadata("ID"));
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/TestFinalFileLocationExtractor.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/TestFinalFileLocationExtractor.java
new file mode 100644
index 0000000..6777918
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/TestFinalFileLocationExtractor.java
@@ -0,0 +1,164 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.metadata.extractors.examples;
+
+//JDK imports
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test suite for the {@link FinalFileLocationExtractor}.
+ * 
+ * @since OODT-72
+ * 
+ */
+public class TestFinalFileLocationExtractor extends TestCase {
+
+  public void testExtract() {
+    String expectedFinalLocation = "/archive/somefile.txt";
+    Product p = Product.getDefaultFlatProduct("test", "urn:oodt:GenericFile");
+    p.setProductName("somefile.txt");
+    p.getProductType().setProductRepositoryPath("file:///archive");
+    p.getProductType().setVersioner(
+        "org.apache.oodt.cas.filemgr.versioning.BasicVersioner");
+    p.getProductReferences().add(
+        new Reference("file:///tmp/somefile.txt", null, 0L));
+    Properties config = new Properties();
+    config.setProperty("replace", "false");
+    Metadata met = new Metadata();
+    met.addMetadata(CoreMetKeys.FILE_LOCATION, "/tmp");
+    FinalFileLocationExtractor extractor = new FinalFileLocationExtractor();
+    extractor.configure(config);
+    Metadata extractMet = new Metadata();
+
+    try {
+      extractMet = extractor.doExtract(p, met);
+    } catch (MetExtractionException e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(extractMet);
+    assertTrue(extractMet.containsKey(CoreMetKeys.FILE_LOCATION));
+    assertEquals(2, extractMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).size());
+    assertEquals("/tmp", extractMet.getMetadata(CoreMetKeys.FILE_LOCATION));
+    assertEquals("expected final location: [" + expectedFinalLocation
+        + "] is not equal to generated location: ["
+        + extractMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).get(1) + "]",
+        expectedFinalLocation,
+        extractMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).get(1));
+
+    // ensure that the data store ref is blank
+    assertEquals("", p.getProductReferences().get(0).getDataStoreReference());
+
+    // reconfigure to replace
+    config.setProperty("replace", "true");
+    extractor.configure(config);
+
+    try {
+      extractMet = extractor.doExtract(p, met);
+    } catch (MetExtractionException e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(extractMet);
+    assertTrue(extractMet.containsKey(CoreMetKeys.FILE_LOCATION));
+    assertEquals(1, extractMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).size());
+    assertEquals(expectedFinalLocation,
+        extractMet.getMetadata(CoreMetKeys.FILE_LOCATION));
+
+    // ensure that the data store ref is blank
+    assertEquals("", p.getProductReferences().get(0).getDataStoreReference());
+
+  }
+
+  /**
+   * @since OODT-200
+   */
+  public void testExtractHierarchical() {
+    String expectedFinalLocation = "/archive/dirs";
+    Product p = Product.getDefaultFlatProduct("test", "urn:oodt:GenericFile");
+    p.setProductStructure(Product.STRUCTURE_HIERARCHICAL);
+    p.setProductName("somedir");
+    p.getProductType().setProductRepositoryPath("file:///archive/dirs");
+    p.getProductType().setVersioner(
+        "org.apache.oodt.cas.filemgr.versioning.DirectoryProductVersioner");
+    p.getProductReferences()
+        .add(new Reference("file:///tmp/somedir", null, 4L));
+    p.getProductReferences().add(
+        new Reference("file:///tmp/somedir/file1.txt", null, 8L));
+    p.getProductReferences().add(
+        new Reference("file:///tmp/somedir/file2.txt", null, 8L));
+    Properties config = new Properties();
+    config.setProperty("replace", "false");
+    Metadata met = new Metadata();
+    met.addMetadata(CoreMetKeys.FILE_LOCATION, "/tmp");
+    FinalFileLocationExtractor extractor = new FinalFileLocationExtractor();
+    extractor.configure(config);
+    Metadata extractMet = new Metadata();
+
+    try {
+      extractMet = extractor.doExtract(p, met);
+    } catch (MetExtractionException e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(extractMet);
+    assertTrue(extractMet.containsKey(CoreMetKeys.FILE_LOCATION));
+    assertEquals(2, extractMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).size());
+    assertEquals("/tmp", extractMet.getMetadata(CoreMetKeys.FILE_LOCATION));
+    assertEquals("expected final location: [" + expectedFinalLocation
+        + "] is not equal to generated location: ["
+        + extractMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).get(1) + "]",
+        expectedFinalLocation,
+        extractMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).get(1));
+
+    // ensure that the data store ref is blank
+    assertEquals("", p.getProductReferences().get(0).getDataStoreReference());
+
+    // reconfigure to replace
+    config.setProperty("replace", "true");
+    extractor.configure(config);
+
+    try {
+      extractMet = extractor.doExtract(p, met);
+    } catch (MetExtractionException e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(extractMet);
+    assertTrue(extractMet.containsKey(CoreMetKeys.FILE_LOCATION));
+    assertEquals(1, extractMet.getAllMetadata(CoreMetKeys.FILE_LOCATION).size());
+    assertEquals(expectedFinalLocation,
+        extractMet.getMetadata(CoreMetKeys.FILE_LOCATION));
+
+    // ensure that the data store ref is blank
+    assertEquals("", p.getProductReferences().get(0).getDataStoreReference());
+
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/TestMimeTypeExtractor.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/TestMimeTypeExtractor.java
new file mode 100644
index 0000000..8b4ef91
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/metadata/extractors/examples/TestMimeTypeExtractor.java
@@ -0,0 +1,82 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.metadata.extractors.examples;
+
+//Junit imports
+import java.io.File;
+import java.net.URL;
+import java.util.Properties;
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test harness for the {@link MimeTypeExtractor}.
+ * 
+ * @since OODT-58
+ * 
+ */
+public class TestMimeTypeExtractor extends TestCase implements CoreMetKeys {
+
+  private Properties initialProperties = new Properties(System.getProperties());
+
+  public void setUp() throws Exception {
+    Properties properties = new Properties(System.getProperties());
+    URL url = this.getClass().getResource("/mime-types.xml");
+    properties.setProperty("org.apache.oodt.cas.filemgr.mime.type.repository",
+        new File(url.getFile()).getAbsolutePath());
+    System.setProperties(properties);
+  }
+
+  public void tearDown() throws Exception {
+    System.setProperties(initialProperties);
+  }
+
+  /**
+   * @since OODT-58
+   */
+  public void testExtract() {
+    MimeTypeExtractor extractor = new MimeTypeExtractor();
+    Product p = Product.getDefaultFlatProduct("test", "urn:oodt:GenericFile");
+    Reference r = new Reference("file:///tmp/test.he5",
+        "file:///archive/test.he5/test.he5", 0L);
+    p.getProductReferences().add(r);
+    Metadata met = new Metadata();
+    try {
+      met = extractor.doExtract(p, met);
+    } catch (MetExtractionException e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(met);
+    assertNotNull(met.getAllMetadata(MIME_TYPE));
+    assertEquals(3, met.getAllMetadata(MIME_TYPE).size());
+    System.out.println(met.getAllMetadata(MIME_TYPE));
+    assertEquals("application/x-hdf", met.getAllMetadata(MIME_TYPE).get(0));
+    assertEquals("application", met.getAllMetadata(MIME_TYPE).get(1));
+    assertEquals("x-hdf", met.getAllMetadata(MIME_TYPE).get(2));
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/repository/TestXMLRepositoryManager.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/repository/TestXMLRepositoryManager.java
new file mode 100644
index 0000000..663cf5c
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/repository/TestXMLRepositoryManager.java
@@ -0,0 +1,315 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.repository;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.commons.exec.EnvUtilities;
+
+//JDK imports
+import java.io.File;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test case class for the XMLRepositoryManager.
+ * </p>
+ * 
+ */
+public class TestXMLRepositoryManager extends TestCase {
+
+    /* URI pointers to our test product-types.xml directories */
+    private List productTypeDirUris = new Vector();
+
+    /* our repository manager to test */
+    private XMLRepositoryManager repositoryManager = null;
+
+    private static final String expectedGenericFileBlankMetDesc = "The default product type for any kind of file, with blank metadata.";
+
+    private static final String expectedGenericFileDesc = "The default product type for any kind of file, with real metadata.";
+
+    private static final String expectedGenericFileNoMetDesc = "\n      The default product type for any kind of file, without metadata.\n    ";
+
+    private static final String expectedVersionerClassName = "org.apache.oodt.cas.filemgr.versioning.BasicVersioner";
+
+    private static final String expectedRepPath = "file://"
+            + EnvUtilities.getEnv("HOME") + "/files";
+
+    /**
+     * 
+     */
+    public TestXMLRepositoryManager() {
+        URL url = this.getClass().getResource("/repomgr");
+        productTypeDirUris.add(new File(url.getFile()).toURI().toString());
+        try {
+            repositoryManager = new XMLRepositoryManager(productTypeDirUris);
+        } catch (InstantiationException e) {
+            fail(e.getMessage());
+        }
+    }
+
+    public void testRepoPathEnvVarReplace() {
+        List productTypes = null;
+
+        try {
+            productTypes = repositoryManager.getProductTypes();
+        } catch (RepositoryManagerException e) {
+            fail(e.getMessage());
+        }
+
+        ProductType type = ((ProductType) productTypes.get(0));
+        String expectedPath = "file://" + System.getenv("HOME") + "/files";
+        assertEquals("The repo path: [" + type.getProductRepositoryPath()
+                + "] is " + "not equal to the exptected path: [" + expectedPath
+                + "]", expectedPath, type.getProductRepositoryPath());
+    }
+
+    public void testGetProductTypes() {
+        List productTypes = null;
+
+        try {
+            productTypes = repositoryManager.getProductTypes();
+        } catch (RepositoryManagerException e) {
+            fail(e.getMessage());
+        }
+
+        // should be exactly 3 product types
+        assertNotNull(productTypes);
+        assertEquals(3, productTypes.size());
+    }
+
+    public void testGetProductTypeByName() {
+        ProductType type = null;
+
+        try {
+            type = repositoryManager.getProductTypeByName("GenericFile");
+        } catch (RepositoryManagerException e) {
+            fail(e.getMessage());
+        }
+
+        // should be not null and name should be generic file
+        assertNotNull(type);
+        assertEquals("The type name: [" + type.getName()
+                + "] is not \"GenericFile\"", type.getName(), "GenericFile");
+    }
+
+    public void testGetProductTypeById() {
+        ProductType type = null;
+
+        try {
+            type = repositoryManager.getProductTypeById("urn:oodt:GenericFile");
+        } catch (RepositoryManagerException e) {
+            fail(e.getMessage());
+        }
+
+        // should be not null and should be generic file
+        assertNotNull(type);
+        assertEquals("The type id: [" + type.getProductTypeId()
+                + "] is not \"urn:oodt:GenericFile\"", type.getProductTypeId(),
+                "urn:oodt:GenericFile");
+
+    }
+
+    /**
+     * @since OODT-69
+     * 
+     */
+    public void testReadProductTypeWithMetadataWithBlankMet() {
+        ProductType type = null;
+
+        try {
+            type = repositoryManager
+                    .getProductTypeByName("GenericFileWithBlankMet");
+        } catch (RepositoryManagerException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(type);
+        assertNotNull(type.getTypeMetadata());
+
+    }
+
+    /**
+     * @since OODT-69
+     * 
+     */
+    public void testReadProductTypeWithMetadataWithNoMet() {
+        ProductType type = null;
+
+        try {
+            type = repositoryManager
+                    .getProductTypeByName("GenericFileNoTypeMetadata");
+        } catch (RepositoryManagerException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(type);
+        assertNull(type.getTypeMetadata());
+
+    }
+
+    /**
+     * @since OODT-69
+     * 
+     */
+    public void testReadProductTypeWithMetadata() {
+        ProductType type = null;
+
+        try {
+            type = repositoryManager.getProductTypeByName("GenericFile");
+        } catch (RepositoryManagerException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(type);
+        assertNotNull(type.getTypeMetadata());
+
+        assertTrue(type.getTypeMetadata().containsKey("Creator"));
+        assertTrue(type.getTypeMetadata().containsKey("Contributor"));
+        assertEquals(2, type.getTypeMetadata().getHashtable().keySet().size());
+        assertNotNull(type.getTypeMetadata().getAllMetadata("Creator"));
+        assertEquals(2, type.getTypeMetadata().getAllMetadata("Creator").size());
+        assertNotNull(type.getTypeMetadata().getAllMetadata("Contributor"));
+        assertEquals(1, type.getTypeMetadata().getAllMetadata("Contributor")
+                .size());
+
+        List contribValues = type.getTypeMetadata().getAllMetadata(
+                "Contributor");
+        assertEquals("File Manager Client", (String) contribValues.get(0));
+
+        List creatorValues = type.getTypeMetadata().getAllMetadata("Creator");
+        boolean hasFirstCreator = false, hasSecondCreator = false;
+
+        for (Iterator i = creatorValues.iterator(); i.hasNext();) {
+            String val = (String) i.next();
+            if (val.equals("Chris Mattmann")) {
+                hasFirstCreator = true;
+            } else if (val.equals("Paul Ramirez")) {
+                hasSecondCreator = true;
+            }
+        }
+
+        assertTrue(hasFirstCreator && hasSecondCreator);
+    }
+
+    /**
+     * @since OODT-219
+     * 
+     */
+    public void testReadBadFormattedDescriptionTrimImplicitTrue() {
+        ProductType type = null;
+
+        try {
+            type = repositoryManager
+                    .getProductTypeByName("GenericFileWithBlankMet");
+        } catch (RepositoryManagerException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(type);
+        assertNotNull(type.getDescription());
+        assertEquals(expectedGenericFileBlankMetDesc, type.getDescription());
+    }
+
+    /**
+     * @since OODT-219
+     * 
+     */
+    public void testReadDescriptionTrimExplicitFalse() {
+        ProductType type = null;
+
+        try {
+            type = repositoryManager
+                    .getProductTypeByName("GenericFileNoTypeMetadata");
+        } catch (RepositoryManagerException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(type);
+        assertNotNull(type.getDescription());
+        assertEquals(expectedGenericFileNoMetDesc, type.getDescription());
+
+    }
+
+    /**
+     * @since OODT-219
+     * 
+     */
+    public void testReadDescriptionTrimExplicitTrue() {
+        ProductType type = null;
+
+        try {
+            type = repositoryManager.getProductTypeByName("GenericFile");
+        } catch (RepositoryManagerException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(type);
+        assertNotNull(type.getDescription());
+        assertEquals(expectedGenericFileDesc, type.getDescription());
+
+    }
+
+    /**
+     * @since OODT-219
+     * 
+     */
+    public void testReadVersionerClass() {
+        ProductType type = null;
+
+        try {
+            type = repositoryManager.getProductTypeByName("GenericFile");
+        } catch (RepositoryManagerException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(type);
+        assertNotNull(type.getVersioner());
+        assertEquals(expectedVersionerClassName, type.getVersioner());
+
+    }
+
+    /**
+     * @since OODT-219
+     * 
+     */
+    public void testReadRepoPath() {
+        ProductType type = null;
+
+        try {
+            type = repositoryManager.getProductTypeByName("GenericFile");
+        } catch (RepositoryManagerException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(type);
+        assertNotNull(type.getProductRepositoryPath());
+        assertEquals(expectedRepPath, type.getProductRepositoryPath());
+    }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/TestProduct.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/TestProduct.java
new file mode 100644
index 0000000..f8f65e8
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/TestProduct.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.structs;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JDK imports
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Properties;
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test cases for serializing and deserializing XML representations of
+ * {@link Product}s.
+ * </p>.
+ */
+public class TestProduct extends TestCase {
+
+  private Properties initialProperties = new Properties(System.getProperties());
+
+  public void setUp() throws Exception {
+    Properties properties = new Properties(System.getProperties());
+
+    URL url = this.getClass().getResource("/mime-types.xml");
+    properties.setProperty("org.apache.oodt.cas.filemgr.mime.type.repository",
+        new File(url.getFile()).getAbsolutePath());
+
+    System.setProperties(properties);
+  }
+
+  public void tearDown() throws Exception {
+    System.setProperties(initialProperties);
+  }
+
+  /**
+   * @since OODT-41
+   */
+  public void testSetTransferStatus() {
+    Product p = new Product("foo", new ProductType(), Product.STRUCTURE_FLAT,
+        Product.STATUS_TRANSFER, Collections.EMPTY_LIST);
+    assertNotNull(p);
+    assertEquals(p.getTransferStatus(), Product.STATUS_TRANSFER);
+  }
+
+  public void testReadWriteProductWithProductType() {
+    Product p = new Product();
+    p.setProductId("testId");
+    p.setProductName("TestProduct");
+    p.setProductStructure("Flat");
+    p.setTransferStatus(Product.STATUS_RECEIVED);
+    ProductType type = new ProductType();
+    type.setName("BogusType");
+    p.setProductType(type);
+
+    Reference r = new Reference();
+    r.setDataStoreReference("file:///data.store");
+    r.setOrigReference("file:///data.orig");
+    r.setFileSize(99999L);
+    p.getProductReferences().add(r);
+    readWrite(p);
+  }
+
+  public void testReadWriteProductNoProductType() {
+    Product p = new Product();
+    p.setProductId("testId");
+    p.setProductName("TestProduct");
+    p.setProductStructure("Flat");
+    p.setTransferStatus(Product.STATUS_RECEIVED);
+
+    Reference r = new Reference();
+    r.setDataStoreReference("file:///data.store");
+    r.setOrigReference("file:///data.orig");
+    r.setFileSize(99999L);
+    p.getProductReferences().add(r);
+    readWrite(p);
+
+  }
+
+  private void readWrite(Product product) {
+    ByteArrayOutputStream os = new ByteArrayOutputStream();
+    try {
+      XMLUtils.writeXmlToStream(product.toXML(), os);
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+
+    Product readProduct = null;
+
+    try {
+      readProduct = new Product(new ByteArrayInputStream(os.toByteArray()));
+    } catch (InstantiationException e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(readProduct);
+    assertEquals("testId", readProduct.getProductId());
+    assertEquals("TestProduct", readProduct.getProductName());
+    assertEquals(Product.STRUCTURE_FLAT, readProduct.getProductStructure());
+    assertEquals(Product.STATUS_RECEIVED, readProduct.getTransferStatus());
+    assertNotNull(readProduct.getProductType());
+    assertNotNull(readProduct.getProductType().getName(), "BogusType");
+    assertNotNull(readProduct.getProductReferences());
+    assertEquals(1, readProduct.getProductReferences().size());
+    Reference readRef = (Reference) readProduct.getProductReferences().get(0);
+    assertNotNull(readRef);
+    assertEquals(readRef.getOrigReference(), "file:///data.orig");
+    assertEquals(readRef.getDataStoreReference(), "file:///data.store");
+    assertEquals(readRef.getFileSize(), 99999L);
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/TestReference.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/TestReference.java
new file mode 100644
index 0000000..5597095
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/TestReference.java
@@ -0,0 +1,81 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs;
+
+//JDK imports
+import java.io.File;
+import java.net.URL;
+import java.util.Properties;
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test harness for the Product {@link Reference} class. Currently 
+ * exercises that MIME type detection properly occurs.
+ * 
+ * @since OODT-58
+ * 
+ */
+public class TestReference extends TestCase {
+
+  private Properties initialProperties = new Properties(System.getProperties());
+
+  public void setUp() throws Exception {
+    Properties properties = new Properties(System.getProperties());
+
+    URL url = this.getClass().getResource("/mime-types.xml");
+    properties.setProperty("org.apache.oodt.cas.filemgr.mime.type.repository",
+        new File(url.getFile()).getAbsolutePath());
+
+    System.setProperties(properties);
+  }
+
+  public void tearDown() throws Exception {
+    System.setProperties(initialProperties);
+  }
+
+  /**
+   * @since OODT-58
+   */
+  public void testMimeType() {
+    Reference r = new Reference("file:///tmp/test.he5",
+        "file:///archive/test.he5/test.he5", 0L);
+    assertNotNull(r);
+    assertNotNull(r.getMimeType());
+    assertEquals("application/x-hdf", r.getMimeType().getName());
+  }
+  
+  /**
+   * @since OODT-136
+   */
+  public void testSetNullMimeType(){
+    Reference r = new Reference("file:///tmp/test.he5",
+        "file:///archive/test.he5/test.he5", 0L);
+    
+    String nullType = null;
+    try{
+      r.setMimeType("");
+      r.setMimeType(nullType);
+    }
+    catch(Exception e){
+      fail(e.getMessage());
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/query/TestQueryResult.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/query/TestQueryResult.java
new file mode 100644
index 0000000..13c6131
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/query/TestQueryResult.java
@@ -0,0 +1,95 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.structs.query;
+
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+public class TestQueryResult extends TestCase {
+
+  private QueryResult qr;
+
+  @Override
+  protected void setUp() throws Exception {
+    Product p = new Product();
+    p.setProductId("TestProductId");
+    Metadata m = new Metadata();
+    m.addMetadata(CoreMetKeys.FILENAME, "datafile.dat");
+    m.addMetadata("Owners", Arrays.asList("Bob", "Billy"));
+    qr = new QueryResult(p, m);
+  }
+
+  public void testToString() {
+    String str = qr.toString();
+    assertTrue(str.contains("datafile.dat"));
+    assertTrue(str.contains("Bob,Billy"));
+    assertEquals(",", str.replace("datafile.dat", "").replace("Bob,Billy",""));
+  }
+
+  public void testToStringFormat() {
+    qr.setToStringFormat("$Owners,$Filename");
+    assertEquals("Bob,Billy,datafile.dat", qr.toString());
+
+    qr.setToStringFormat("$Filename\t$Owners");
+    List<String> list = Arrays.asList(qr.toString().split("\t"));
+    assertEquals(2, list.size());
+    assertEquals("datafile.dat", list.get(0));
+    assertEquals("Bob,Billy", list.get(1));
+  }
+
+  public void testToStringEmpty() {
+    qr.setMetadata(new Metadata());
+    assertEquals("", qr.toString());
+  }
+
+  public void testEquals() {
+    assertEquals(qr, qr);
+    assertFalse(qr.equals(null));
+    assertFalse(qr.equals(0));
+
+    QueryResult metnull = new QueryResult(qr.getProduct(), null);
+    assertFalse(metnull.equals(qr));
+    assertFalse(qr.equals(metnull));
+    assertEquals(metnull, new QueryResult(qr.getProduct(), null));
+
+    QueryResult prodnull = new QueryResult(null, new Metadata(qr.getMetadata()));
+    assertFalse(prodnull.equals(qr));
+    assertFalse(qr.equals(prodnull));
+    assertEquals(prodnull, new QueryResult(null, new Metadata(qr.getMetadata())));
+
+    QueryResult equal = new QueryResult(qr.getProduct(), new Metadata(qr.getMetadata()));
+    assertEquals(qr, equal);
+    assertEquals(equal, qr);
+
+    QueryResult fmt = new QueryResult(qr.getProduct(), new Metadata(qr.getMetadata()));
+    fmt.setToStringFormat("blah");
+    assertFalse(qr.equals(fmt));
+    assertFalse(fmt.equals(qr));
+
+    QueryResult fmt2 = new QueryResult(qr.getProduct(), new Metadata(qr.getMetadata()));
+    fmt2.setToStringFormat("blah");
+    assertEquals(fmt, fmt2);
+    assertEquals(fmt2, fmt);
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/query/TestQueryResultComparator.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/query/TestQueryResultComparator.java
new file mode 100644
index 0000000..5b46777
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/query/TestQueryResultComparator.java
@@ -0,0 +1,91 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.structs.query;
+
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+public class TestQueryResultComparator extends TestCase {
+
+  private QueryResult qr1;
+  private QueryResult qr2;
+  private QueryResult qrfilename;
+  private QueryResult qrowners;
+  private QueryResult qrnull;
+  private QueryResult qrnull2;
+
+  @Override
+  protected void setUp() throws Exception {
+    Product p = new Product();
+    p.setProductId("TestProductID");
+    Metadata m = new Metadata();
+    m.addMetadata(CoreMetKeys.FILENAME, "datafile.dat");
+    m.addMetadata("Owners", Arrays.asList("Chad", "Cam"));
+    qr1 = new QueryResult(p, m);
+
+    Metadata m2 = new Metadata();
+    m2.addMetadata(CoreMetKeys.FILENAME, "textfile.dat");
+    m2.addMetadata("Owners", Arrays.asList("Bob", "Billy"));
+    qr2 = new QueryResult(p, m2);
+
+    Metadata filename = new Metadata();
+    filename.addMetadata(CoreMetKeys.FILENAME, "foo.txt");
+    qrfilename = new QueryResult(p, filename);
+
+    Metadata owners = new Metadata();
+    owners.addMetadata("Owners", Arrays.asList("Dave", "Dan"));
+    qrowners = new QueryResult(p, owners);
+
+    qrnull = new QueryResult(p, new Metadata());
+    qrnull2 = new QueryResult(p, new Metadata());
+  }
+
+  public void testCompare() {
+    List<QueryResult> list = Arrays.asList(qr1, qrowners, qrnull2, qr2, qrnull, qrfilename);
+    QueryResultComparator c = new QueryResultComparator();
+    c.setSortByMetKey(CoreMetKeys.FILENAME);
+
+    Collections.sort(list, c);
+    assertEquals(qr1, list.get(0));
+    assertEquals(qrfilename, list.get(1));
+    assertEquals(qr2, list.get(2));
+    List<QueryResult> sub = list.subList(3, list.size());
+    assertEquals(3, sub.size());
+    assertTrue(sub.contains(qrnull));
+    assertTrue(sub.contains(qrnull2));
+    assertTrue(sub.contains(qrowners));
+
+    c.setSortByMetKey("Owners");
+    Collections.sort(list, c);
+    assertEquals(qr2, list.get(0));
+    assertEquals(qr1, list.get(1));
+    assertEquals(qrowners, list.get(2));
+    sub = list.subList(3, list.size());
+    assertEquals(3, sub.size());
+    assertTrue(sub.contains(qrfilename));
+    assertTrue(sub.contains(qrnull));
+    assertTrue(sub.contains(qrnull2));
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/type/TestTypeHandler.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/type/TestTypeHandler.java
new file mode 100644
index 0000000..7c09e3a
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/structs/type/TestTypeHandler.java
@@ -0,0 +1,884 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.structs.type;
+
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+import org.apache.oodt.commons.database.SqlScript;
+import org.apache.oodt.commons.pagination.PaginationUtils;
+import org.apache.oodt.cas.filemgr.catalog.Catalog;
+import org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog;
+import org.apache.oodt.cas.filemgr.catalog.DataSourceCatalogFactory;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.QueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManager;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.metadata.Metadata;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.sql.DataSource;
+import org.apache.xmlrpc.XmlRpcException;
+import junit.framework.TestCase;
+
+public class TestTypeHandler extends TestCase {
+    
+    String tmpDirPath;
+    
+    DataSource publicDataSource;
+    
+    XmlRpcFileManager fmServer;
+    
+    int FILEMGR_PORT = 9999;
+
+    private Properties initialProperties = new Properties(
+        System.getProperties());
+
+    public void setUpProperties() {
+
+        Properties properties = new Properties(System.getProperties());
+
+        // set the log levels
+        URL loggingPropertiesUrl = this.getClass().getResource(
+            "/test.logging.properties");
+        properties.setProperty("java.util.logging.config.file", new File(
+            loggingPropertiesUrl.getFile()).getAbsolutePath());
+
+        // first load the example configuration
+        try {
+            URL filemgrPropertiesUrl = this.getClass().getResource(
+                "/filemgr.properties");
+            properties.load(new FileInputStream(
+                filemgrPropertiesUrl.getFile()));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // get a temp directory
+        File tempDir = null;
+        File tempFile = null;
+
+        try {
+            tempFile = File.createTempFile("foo", "bar");
+            tempFile.deleteOnExit();
+            tempDir = tempFile.getParentFile();
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        tmpDirPath = tempDir.getAbsolutePath();
+        if (!tmpDirPath.endsWith("/")) {
+            tmpDirPath += "/";
+        }
+
+        tmpDirPath += "testCat";
+
+        // now override the catalog ones
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.lucene.idxPath",
+                tmpDirPath);
+
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.url",
+                "jdbc:hsqldb:file:" + tmpDirPath + "/testCat;shutdown=true");
+
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.user",
+                "sa");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.pass",
+                "");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.driver",
+                "org.hsqldb.jdbcDriver");
+
+        // now override the val layer ones
+        URL structFactoryUrl = this.getClass().getResource(
+            "/xmlrpc-struct-factory");
+        properties.setProperty("org.apache.oodt.cas.filemgr.validation.dirs",
+            "file://" + new File(structFactoryUrl.getFile()).getAbsolutePath());
+        
+        properties.setProperty("org.apache.oodt.cas.filemgr.repositorymgr.dirs",
+            "file://" + new File(structFactoryUrl.getFile()).getAbsolutePath());
+
+        // override quote fields
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.datasource.quoteFields",
+                "true");
+
+        System.setProperties(properties);
+    }
+   
+    public void testAddAndGetMetadata() throws SQLException, MalformedURLException, ConnectionException {
+        Metadata met = new Metadata();
+        met.addMetadata("DataVersion", "4.0");
+        met.addMetadata("ProductName", "test");
+        Product testProduct = getTestProduct();
+
+        XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(new URL("http://localhost:" + FILEMGR_PORT));
+        try {
+            testProduct.setProductType(fmClient.getProductTypeByName("GenericFile"));
+            testProduct.setProductId(fmClient.ingestProduct(testProduct, met, false));
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        try {
+            Metadata retMet = fmClient.getMetadata(testProduct);
+            assertNotNull(retMet);
+            assertTrue(retMet.containsKey("DataVersion"));
+            assertEquals("4.0", retMet
+                    .getMetadata("DataVersion"));
+        } catch (CatalogException e) {
+            fail(e.getMessage());
+        }
+        
+        Statement statement = publicDataSource.getConnection().createStatement();
+        ResultSet rs = statement.executeQuery("SELECT metadata_value FROM GenericFile_metadata WHERE element_id = 'urn:test:DataVersion';");
+        rs.next();
+        assertEquals(rs.getString("metadata_value"), "04.00");
+    }
+    
+    public void testQuery() throws MalformedURLException, ConnectionException, CatalogException {
+        Metadata met = new Metadata();
+        met.addMetadata("DataVersion", "4.0");
+        met.addMetadata("ProductName", "test");
+        Product testProduct = getTestProduct();
+
+        ProductType genericFile = null;
+        XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(new URL("http://localhost:" + FILEMGR_PORT));
+        try {
+            testProduct.setProductType(genericFile = fmClient.getProductTypeByName("GenericFile"));
+            testProduct.setProductId(fmClient.ingestProduct(testProduct, met, false));
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+        
+        Query query = new Query();
+        TermQueryCriteria termQuery = new TermQueryCriteria();
+        termQuery.setElementName("DataVersion");
+        termQuery.setValue("4.0");
+        query.addCriterion(termQuery);
+        
+        List<Product> products = fmClient.query(query, genericFile);
+        assertEquals(products.get(0).getProductId(), testProduct.getProductId());
+    }
+    
+    public void testGetCatalogAndOrigValuesAndGetCatalogQuery() throws ConnectionException, RepositoryManagerException, XmlRpcException, IOException {
+        Metadata met = new Metadata();
+        met.addMetadata("DataVersion", "4.0");
+        met.addMetadata("ProductName", "test");
+        Product testProduct = getTestProduct();
+
+        XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(new URL("http://localhost:" + FILEMGR_PORT));
+        ProductType genericFile = fmClient.getProductTypeByName("GenericFile");
+        assertEquals("04.00", (met = fmClient.getCatalogValues(met, genericFile)).getMetadata("DataVersion"));
+        assertEquals("4.0", fmClient.getOrigValues(met, genericFile).getMetadata("DataVersion"));
+        
+        Query query = new Query();
+        TermQueryCriteria termQuery = new TermQueryCriteria();
+        termQuery.setElementName("DataVersion");
+        termQuery.setValue("4.0");
+        query.addCriterion(termQuery);
+        query = fmClient.getCatalogQuery(query, genericFile);
+        assertEquals("04.00", ((TermQueryCriteria) query.getCriteria().get(0)).getValue());
+    }
+    
+    private Product getTestProduct() throws MalformedURLException {
+        Product testProduct = Product.getDefaultFlatProduct("test",
+                "urn:oodt:GenericFile");
+        List<Reference> refs = new LinkedList<Reference>();
+        URL refUrl = this.getClass().getResource("/ingest/test.txt");
+        Reference ref = new Reference();
+        ref.setOrigReference(new File(refUrl.getFile()).toURL().toExternalForm());
+        ref.setFileSize(123);
+        refs.add(ref);
+        testProduct.setProductReferences(refs);
+        return testProduct;
+    }
+    
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        setUpProperties();
+        createSchema();
+        startXmlRpcFileManager();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        fmServer.shutdown();
+        // now remove the temporary directory used
+        if (tmpDirPath != null) {
+            File tmpDir = new File(tmpDirPath);
+            File[] tmpFiles = tmpDir.listFiles();
+
+            if (tmpFiles != null && tmpFiles.length > 0) {
+                for (int i = 0; i < tmpFiles.length; i++) {
+                    tmpFiles[i].delete();
+                }
+
+                tmpDir.delete();
+            }
+
+        }
+
+        System.setProperties(initialProperties);
+    }
+    
+    private void createSchema() {
+        String url = System
+                .getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.url");
+        String user = System
+                .getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.user");
+        String pass = System
+                .getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.pass");
+        String driver = System
+                .getProperty("org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.driver");
+
+        publicDataSource = DatabaseConnectionBuilder.buildDataSource(user, pass,
+                driver, url);
+        try {
+            URL scriptUrl = this.getClass().getResource("/testcat.sql");
+            SqlScript coreSchemaScript = new SqlScript(new File(
+                scriptUrl.getFile()).getAbsolutePath(), publicDataSource);
+            coreSchemaScript.loadScript();
+            coreSchemaScript.execute();
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+    }
+    
+    private void startXmlRpcFileManager() {
+        try {
+            fmServer = new XmlRpcFileManager(FILEMGR_PORT);
+            fmServer.setCatalog(new HsqlDbFriendlyDataSourceCatalogFatory().createCatalog());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+    
+    class HsqlDbFriendlyDataSourceCatalogFatory extends
+            DataSourceCatalogFactory {
+
+        public HsqlDbFriendlyDataSourceCatalogFatory() {
+            super();
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see
+         * org.apache.oodt.cas.filemgr.catalog.CatalogFactory#createCatalog()
+         */
+        public Catalog createCatalog() {
+            return new HsqlDbFriendlyDataSourceCatalog(dataSource,
+                    validationLayer, fieldIdStr, pageSize, cacheUpdateMinutes);
+        }
+    }
+    
+    class HsqlDbFriendlyDataSourceCatalog extends DataSourceCatalog {
+
+        public HsqlDbFriendlyDataSourceCatalog(DataSource ds,
+                ValidationLayer valLayer, boolean fieldId, int pageSize,
+                long cacheUpdateMin) {
+            super(ds, valLayer, fieldId, pageSize, cacheUpdateMin);
+        }
+
+        private final Logger LOG = Logger
+                .getLogger(HsqlDbFriendlyDataSourceCatalog.class.getName());
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog#pagedQuery(org.apache.oodt.cas.filemgr.structs.Query,
+         *      org.apache.oodt.cas.filemgr.structs.ProductType, int)
+         */
+        public ProductPage pagedQuery(Query query, ProductType type, int pageNum)
+                throws CatalogException {
+            int totalPages = PaginationUtils.getTotalPage(getResultListSize(
+                    query, type), this.pageSize);
+
+            /*
+             * if there are 0 total pages in the result list size then don't
+             * bother returning a valid product page instead, return blank
+             * ProductPage
+             */
+            if (totalPages == 0) {
+                return ProductPage.blankPage();
+            }
+
+            ProductPage retPage = new ProductPage();
+            retPage.setPageNum(pageNum);
+            retPage.setPageSize(this.pageSize);
+            retPage.setTotalPages(totalPages);
+
+            List productIds = paginateQuery(query, type, pageNum);
+
+            if (productIds != null && productIds.size() > 0) {
+                List products = new Vector(productIds.size());
+
+                for (Iterator i = productIds.iterator(); i.hasNext();) {
+                    String productId = (String) i.next();
+                    Product p = getProductById(productId);
+                    products.add(p);
+                }
+
+                retPage.setPageProducts(products);
+            }
+
+            return retPage;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog#getFirstPage(org.apache.oodt.cas.filemgr.structs.ProductType)
+         */
+        public ProductPage getFirstPage(ProductType type) {
+            Query query = new Query();
+            ProductPage firstPage = null;
+
+            try {
+                firstPage = pagedQuery(query, type, 1);
+            } catch (CatalogException e) {
+                LOG.log(Level.WARNING,
+                        "Exception getting first page: Message: "
+                                + e.getMessage());
+            }
+            return firstPage;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see org.apache.oodt.cas.filemgr.catalog.DataSourceCatalog#getNextPage(org.apache.oodt.cas.filemgr.structs.ProductType,
+         *      org.apache.oodt.cas.filemgr.structs.ProductPage)
+         */
+        public ProductPage getNextPage(ProductType type, ProductPage currentPage) {
+            if (currentPage == null) {
+                return getFirstPage(type);
+            }
+
+            if (currentPage.isLastPage()) {
+                return currentPage;
+            }
+
+            ProductPage nextPage = null;
+            Query query = new Query();
+
+            try {
+                nextPage = pagedQuery(query, type, currentPage.getPageNum() + 1);
+            } catch (CatalogException e) {
+                LOG.log(Level.WARNING, "Exception getting next page: Message: "
+                        + e.getMessage());
+            }
+
+            return nextPage;
+        }
+
+        private List paginateQuery(Query query, ProductType type, int pageNum)
+                throws CatalogException {
+            Connection conn = null;
+            Statement statement = null;
+            ResultSet rs = null;
+
+            List productIds = null;
+            boolean doSkip = true;
+            int numResults = -1;
+
+            if (pageNum == -1) {
+                doSkip = false;
+            } else {
+                numResults = getResultListSize(query, type);
+            }
+
+            try {
+                conn = dataSource.getConnection();
+                statement = conn.createStatement(
+                        ResultSet.TYPE_SCROLL_INSENSITIVE,
+                        ResultSet.CONCUR_READ_ONLY);
+
+                String getProductSql = "";
+                String tableName = type.getName() + "_metadata";
+                String subSelectQueryBase = "SELECT product_id FROM "
+                        + tableName + " ";
+                StringBuffer selectClause = new StringBuffer(
+                        "SELECT DISTINCT p.product_id ");
+                StringBuffer fromClause = new StringBuffer("FROM " + tableName
+                        + " p ");
+                StringBuffer whereClause = new StringBuffer("WHERE ");
+
+                boolean gotFirstClause = false;
+                int clauseNum = 0;
+
+                if (query.getCriteria() != null
+                        && query.getCriteria().size() > 0) {
+                    for (Iterator i = query.getCriteria().iterator(); i
+                            .hasNext();) {
+                        QueryCriteria criteria = (QueryCriteria) i.next();
+                        clauseNum++;
+
+                        String elementIdStr = null;
+
+                        if (fieldIdStringFlag) {
+                            elementIdStr = "'" + this.getValidationLayer().getElementByName(criteria.getElementName()).getElementId() + "'";
+                        } else {
+                            elementIdStr = this.getValidationLayer().getElementByName(criteria.getElementName()).getElementId();
+                        }
+
+                        String clause = null;
+
+                        if (!gotFirstClause) {
+                            clause = "(p.element_id = " + elementIdStr
+                                    + " AND ";
+                            if (criteria instanceof TermQueryCriteria) {
+                                clause += " metadata_value LIKE '%"
+                                        + ((TermQueryCriteria) criteria)
+                                                .getValue() + "%') ";
+                            } else if (criteria instanceof RangeQueryCriteria) {
+                                String startVal = ((RangeQueryCriteria) criteria)
+                                        .getStartValue();
+                                String endVal = ((RangeQueryCriteria) criteria)
+                                        .getEndValue();
+                                boolean inclusive = ((RangeQueryCriteria) criteria)
+                                        .getInclusive();
+
+                                if ((startVal != null && !startVal.equals(""))
+                                        || (endVal != null && !endVal
+                                                .equals(""))) {
+                                    clause += " metadata_value ";
+
+                                    boolean gotStart = false;
+
+                                    if (startVal != null
+                                            && !startVal.equals("")) {
+                                        if (inclusive)
+                                            clause += ">= '" + startVal + "'";
+                                        else
+                                            clause += "> '" + startVal + "'";
+                                        gotStart = true;
+                                    }
+
+                                    if (endVal != null && !endVal.equals("")) {
+                                        if (gotStart) {
+                                            if (inclusive)
+                                                clause += " AND metadata_value <= '"
+                                                        + endVal + "'";
+                                            else
+                                                clause += " AND metadata_value < '"
+                                                        + endVal + "'";
+                                        } else if (inclusive)
+                                            clause += "<= '" + endVal + "'";
+                                        else
+                                            clause += "< '" + endVal + "'";
+                                    }
+
+                                    clause += ") ";
+                                }
+                            }
+
+                            whereClause.append(clause);
+                            gotFirstClause = true;
+                        } else {
+                            String subSelectTblName = "p" + clauseNum;
+                            String subSelectQuery = subSelectQueryBase
+                                    + "WHERE (element_id = " + elementIdStr
+                                    + " AND ";
+                            if (criteria instanceof TermQueryCriteria) {
+                                subSelectQuery += " metadata_value LIKE '%"
+                                        + ((TermQueryCriteria) criteria)
+                                                .getValue() + "%')";
+                            } else if (criteria instanceof RangeQueryCriteria) {
+                                String startVal = ((RangeQueryCriteria) criteria)
+                                        .getStartValue();
+                                String endVal = ((RangeQueryCriteria) criteria)
+                                        .getEndValue();
+
+                                if (startVal != null || endVal != null) {
+                                    subSelectQuery += " metadata_value ";
+
+                                    boolean gotStart = false;
+
+                                    if (startVal != null
+                                            && !startVal.equals("")) {
+                                        subSelectQuery += ">= '" + startVal
+                                                + "'";
+                                        gotStart = true;
+                                    }
+
+                                    if (endVal != null && !endVal.equals("")) {
+                                        if (gotStart) {
+                                            subSelectQuery += " AND metadata_value <= '"
+                                                    + endVal + "'";
+                                        } else
+                                            subSelectQuery += "<= '" + endVal
+                                                    + "'";
+                                    }
+
+                                    subSelectQuery += ") ";
+
+                                }
+                            }
+                            fromClause.append("INNER JOIN (" + subSelectQuery
+                                    + ") " + subSelectTblName + " ON "
+                                    + subSelectTblName
+                                    + ".product_id = p.product_id ");
+
+                        }
+                    }
+                }
+                getProductSql = selectClause.toString() + fromClause.toString();
+                if (gotFirstClause) {
+                    getProductSql += whereClause.toString();
+                }
+
+                LOG.log(Level.FINE, "catalog query: executing: "
+                        + getProductSql);
+
+                rs = statement.executeQuery(getProductSql);
+                productIds = new Vector();
+
+                if (doSkip) {
+                    int startNum = (pageNum - 1) * pageSize;
+
+                    if (startNum > numResults) {
+                        startNum = 0;
+                    }
+
+                    // must call next first, or else no relative cursor
+                    if (rs.next()) {
+                        // grab the first one
+                        int numGrabbed = -1;
+
+                        if (pageNum == 1) {
+                            numGrabbed = 1;
+                            productIds.add(rs.getString("product_id"));
+                        } else {
+                            numGrabbed = 0;
+                        }
+
+                        // now move the cursor to the correct position
+                        if(pageNum != 1){
+                            rs.relative(startNum-1);
+                        }
+
+                        // grab the rest
+                        while (rs.next() && numGrabbed < pageSize) {
+                            String productId = rs.getString("product_id");
+                            productIds.add(productId);
+                            numGrabbed++;
+                        }
+                    }
+
+                } else {
+                    while (rs.next()) {
+                        String productId = rs.getString("product_id");
+                        productIds.add(productId);
+                    }
+                }
+
+                if (productIds.size() == 0) {
+                    productIds = null;
+                }
+
+            } catch (Exception e) {
+                e.printStackTrace();
+                LOG.log(Level.WARNING, "Exception performing query. Message: "
+                        + e.getMessage());
+                try {
+                    conn.rollback();
+                } catch (SQLException e2) {
+                    LOG.log(Level.SEVERE,
+                            "Unable to rollback query transaction. Message: "
+                                    + e2.getMessage());
+                }
+                throw new CatalogException(e.getMessage());
+            } finally {
+
+                if (rs != null) {
+                    try {
+                        rs.close();
+                    } catch (SQLException ignore) {
+                    }
+
+                    rs = null;
+                }
+
+                if (statement != null) {
+                    try {
+                        statement.close();
+                    } catch (SQLException ignore) {
+                    }
+
+                    statement = null;
+                }
+
+                if (conn != null) {
+                    try {
+                        conn.close();
+
+                    } catch (SQLException ignore) {
+                    }
+
+                    conn = null;
+                }
+            }
+
+            return productIds;
+        }
+
+        protected int getResultListSize(Query query, ProductType type)
+                throws CatalogException {
+            Connection conn = null;
+            Statement statement = null;
+            ResultSet rs = null;
+
+            int resultCount = 0;
+
+            try {
+                conn = dataSource.getConnection();
+                statement = conn.createStatement();
+
+                String getProductSql = "";
+                String tableName = type.getName() + "_metadata";
+                String subSelectQueryBase = "SELECT product_id FROM "
+                        + tableName + " ";
+                StringBuffer selectClause = new StringBuffer(
+                        "SELECT COUNT(DISTINCT p.product_id) AS numResults ");
+                StringBuffer fromClause = new StringBuffer("FROM " + tableName
+                        + " p ");
+                StringBuffer whereClause = new StringBuffer("WHERE ");
+
+                boolean gotFirstClause = false;
+                int clauseNum = 0;
+
+                if (query.getCriteria() != null
+                        && query.getCriteria().size() > 0) {
+                    for (Iterator i = query.getCriteria().iterator(); i
+                            .hasNext();) {
+                        QueryCriteria criteria = (QueryCriteria) i.next();
+                        clauseNum++;
+
+                        String elementIdStr = null;
+
+                        if (fieldIdStringFlag) {
+                            elementIdStr = "'" + this.getValidationLayer().getElementByName(criteria.getElementName()).getElementId() + "'";
+                        } else {
+                            elementIdStr = this.getValidationLayer().getElementByName(criteria.getElementName()).getElementId();
+                        }
+
+                        String clause = null;
+
+                        if (!gotFirstClause) {
+                            clause = "(p.element_id = " + elementIdStr
+                                    + " AND ";
+                            if (criteria instanceof TermQueryCriteria) {
+                                clause += " metadata_value LIKE '%"
+                                        + ((TermQueryCriteria) criteria)
+                                                .getValue() + "%') ";
+                            } else if (criteria instanceof RangeQueryCriteria) {
+                                String startVal = ((RangeQueryCriteria) criteria)
+                                        .getStartValue();
+                                String endVal = ((RangeQueryCriteria) criteria)
+                                        .getEndValue();
+                                boolean inclusive = ((RangeQueryCriteria) criteria)
+                                        .getInclusive();
+
+                                if ((startVal != null && !startVal.equals(""))
+                                        || (endVal != null && !endVal
+                                                .equals(""))) {
+                                    clause += " metadata_value ";
+
+                                    boolean gotStart = false;
+
+                                    if (startVal != null
+                                            && !startVal.equals("")) {
+                                        if (inclusive)
+                                            clause += ">= '" + startVal + "'";
+                                        else
+                                            clause += "> '" + startVal + "'";
+                                        gotStart = true;
+                                    }
+
+                                    if (endVal != null && !endVal.equals("")) {
+                                        if (gotStart) {
+                                            if (inclusive)
+                                                clause += " AND metadata_value <= '"
+                                                        + endVal + "'";
+                                            else
+                                                clause += " AND metadata_value < '"
+                                                        + endVal + "'";
+                                        } else if (inclusive)
+                                            clause += "<= '" + endVal + "'";
+                                        else
+                                            clause += "< '" + endVal + "'";
+                                    }
+
+                                    clause += ") ";
+                                }
+                            }
+                            whereClause.append(clause);
+                            gotFirstClause = true;
+                        } else {
+                            String subSelectTblName = "p" + clauseNum;
+                            String subSelectQuery = subSelectQueryBase
+                                    + "WHERE (element_id = " + elementIdStr
+                                    + " AND ";
+                            if (criteria instanceof TermQueryCriteria) {
+                                subSelectQuery += " metadata_value LIKE '%"
+                                        + ((TermQueryCriteria) criteria)
+                                                .getValue() + "%')";
+                            } else if (criteria instanceof RangeQueryCriteria) {
+                                String startVal = ((RangeQueryCriteria) criteria)
+                                        .getStartValue();
+                                String endVal = ((RangeQueryCriteria) criteria)
+                                        .getEndValue();
+
+                                if (startVal != null || endVal != null) {
+                                    subSelectQuery += " metadata_value ";
+
+                                    boolean gotStart = false;
+
+                                    if (startVal != null
+                                            && !startVal.equals("")) {
+                                        subSelectQuery += ">= '" + startVal
+                                                + "'";
+                                        gotStart = true;
+                                    }
+
+                                    if (endVal != null && !endVal.equals("")) {
+                                        if (gotStart) {
+                                            subSelectQuery += " AND metadata_value <= '"
+                                                    + endVal + "'";
+                                        } else
+                                            subSelectQuery += "<= '" + endVal
+                                                    + "'";
+                                    }
+
+                                    subSelectQuery += ") ";
+
+                                }
+                            }
+
+                            fromClause.append("INNER JOIN (" + subSelectQuery
+                                    + ") " + subSelectTblName + " ON "
+                                    + subSelectTblName
+                                    + ".product_id = p.product_id ");
+
+                        }
+                    }
+                }
+
+                getProductSql = selectClause.toString() + fromClause.toString();
+                if (gotFirstClause) {
+                    getProductSql += whereClause.toString();
+                }
+
+                LOG.log(Level.FINE, "catalog get num results: executing: "
+                        + getProductSql);
+
+                rs = statement.executeQuery(getProductSql);
+
+                while (rs.next()) {
+                    resultCount = rs.getInt("numResults");
+                }
+
+            } catch (Exception e) {
+                e.printStackTrace();
+                LOG.log(Level.WARNING,
+                        "Exception performing get num results. Message: "
+                                + e.getMessage());
+                try {
+                    conn.rollback();
+                } catch (SQLException e2) {
+                    LOG.log(Level.SEVERE,
+                            "Unable to rollback get num results transaction. Message: "
+                                    + e2.getMessage());
+                }
+                throw new CatalogException(e.getMessage());
+            } finally {
+
+                if (rs != null) {
+                    try {
+                        rs.close();
+                    } catch (SQLException ignore) {
+                    }
+
+                    rs = null;
+                }
+
+                if (statement != null) {
+                    try {
+                        statement.close();
+                    } catch (SQLException ignore) {
+                    }
+
+                    statement = null;
+                }
+
+                if (conn != null) {
+                    try {
+                        conn.close();
+
+                    } catch (SQLException ignore) {
+                    }
+
+                    conn = null;
+                }
+            }
+
+            return resultCount;
+        }
+    }
+
+    
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/system/MockXmlRpcFileManagerClient.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/system/MockXmlRpcFileManagerClient.java
new file mode 100644
index 0000000..cf80e91
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/system/MockXmlRpcFileManagerClient.java
@@ -0,0 +1,291 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.system;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.apache.oodt.cas.filemgr.structs.query.ComplexQuery;
+import org.apache.oodt.cas.filemgr.structs.query.QueryResult;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * A Mock {@link XmlRpcFileManagerClient}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class MockXmlRpcFileManagerClient extends XmlRpcFileManagerClient {
+
+   private MethodCallDetails lastMethodCallDetails;
+
+   public MockXmlRpcFileManagerClient() throws ConnectionException,
+         MalformedURLException {
+      super(new URL("http://localhost:9000"), false);
+   }
+
+   public MethodCallDetails getLastMethodCallDetails() {
+      return lastMethodCallDetails;
+   }
+
+   @Override
+   public String addProductType(ProductType productType) {
+      lastMethodCallDetails = new MethodCallDetails("addProductType",
+            Lists.newArrayList((Object) productType));
+      return "ProductTypeId";
+   }
+
+   @Override
+   public Product getProductById(String productId) {
+      lastMethodCallDetails = new MethodCallDetails("getProductById",
+            Lists.newArrayList((Object) productId));
+      Product p = new Product();
+      p.setProductId(productId);
+      p.setProductName("TestProductName");
+      p.setProductReferences(Lists.newArrayList(
+            new Reference("file:/orig/file", "file:/ds/file", 3)));
+      p.setProductStructure(Product.STRUCTURE_FLAT);
+      p.setTransferStatus(Product.STATUS_RECEIVED);
+      ProductType pt = new ProductType();
+      pt.setName("TestProductType");
+      p.setProductType(pt);
+      return p;
+   }
+
+   @Override
+   public Product getProductByName(String productName) {
+      lastMethodCallDetails = new MethodCallDetails("getProductByName",
+            Lists.newArrayList((Object) productName));
+      Product p = new Product();
+      p.setProductId("TestProductId");
+      p.setProductName(productName);
+      p.setProductReferences(Lists.newArrayList(
+            new Reference("file:/orig/file", "file:/ds/file", 3)));
+      p.setProductStructure(Product.STRUCTURE_FLAT);
+      p.setTransferStatus(Product.STATUS_RECEIVED);
+      ProductType pt = new ProductType();
+      pt.setName("TestProductType");
+      p.setProductType(pt);
+      return p;
+   }
+
+   @Override
+   public List<Reference> getProductReferences(Product product) {
+      lastMethodCallDetails = new MethodCallDetails("getProductReferences",
+            Lists.newArrayList((Object) product));
+      return Lists.newArrayList();
+   }
+
+   @Override
+   public boolean removeProduct(Product product) {
+      lastMethodCallDetails = new MethodCallDetails("removeProduct",
+            Lists.newArrayList((Object) product));
+      return true;
+   }
+
+   @Override
+   public boolean removeFile(String file) {
+      lastMethodCallDetails = new MethodCallDetails("removeFile",
+            Lists.newArrayList((Object) file));
+      return true;
+   }
+
+   @Override
+   public byte[] retrieveFile(String filePath, int offset, int numBytes)
+      throws DataTransferException {
+      lastMethodCallDetails = new MethodCallDetails("removeFile",
+            Lists.newArrayList((Object) filePath, offset, numBytes));
+      return new byte[0];
+   }
+
+   @Override
+   public FileTransferStatus getCurrentFileTransfer() {
+      lastMethodCallDetails = new MethodCallDetails("getCurrentFileTransfer",
+            Lists.newArrayList());
+      FileTransferStatus status = new FileTransferStatus();
+      status.setBytesTransferred(10);
+      status.setFileRef(new Reference("file:/orig/file", "file:/ds/file", 4));
+      Product p = new Product();
+      p.setProductId("TestProductId");
+      status.setParentProduct(p);
+      return status;
+   }
+
+   @Override
+   public List<FileTransferStatus> getCurrentFileTransfers() {
+      lastMethodCallDetails = new MethodCallDetails("getCurrentFileTransfers",
+            Lists.newArrayList());
+      FileTransferStatus status = new FileTransferStatus();
+      status.setBytesTransferred(10);
+      status.setFileRef(new Reference("file:/orig/file", "file:/ds/file", 4));
+      Product p = new Product();
+      p.setProductId("TestProductId");
+      status.setParentProduct(p);
+      return Lists.newArrayList(status);
+   }
+
+   @Override
+   public double getRefPctTransferred(Reference ref) {
+      lastMethodCallDetails = new MethodCallDetails("getRefPctTransferred",
+            Lists.newArrayList((Object) ref));
+      return 0.6;
+   }
+
+   @Override
+   public ProductType getProductTypeByName(String productTypeName) {
+      lastMethodCallDetails = new MethodCallDetails("getProductTypeByName",
+            Lists.newArrayList((Object) productTypeName));
+      ProductType pt = new ProductType();
+      pt.setName(productTypeName);
+      return pt;
+   }
+
+   @Override
+   public ProductPage getFirstPage(ProductType type) {
+      lastMethodCallDetails = new MethodCallDetails("getFirstPage",
+            Lists.newArrayList((Object) type));
+      ProductPage pp = new ProductPage();
+      pp.setNumOfHits(0);
+      pp.setPageProducts(new ArrayList<Product>());
+      pp.setPageSize(10);
+      pp.setTotalPages(0);
+      pp.setPageNum(1);
+      return pp;
+   }
+
+   @Override
+   public ProductPage getLastPage(ProductType type) {
+      lastMethodCallDetails = new MethodCallDetails("getLastPage",
+            Lists.newArrayList((Object) type));
+      ProductPage pp = new ProductPage();
+      pp.setNumOfHits(0);
+      pp.setPageProducts(new ArrayList<Product>());
+      pp.setPageSize(10);
+      pp.setTotalPages(0);
+      pp.setPageNum(1);
+      return pp;
+   }
+
+   @Override
+   public ProductPage getNextPage(ProductType type, ProductPage curPage) {
+      lastMethodCallDetails = new MethodCallDetails("getNextPage",
+            Lists.newArrayList((Object) type, curPage));
+      ProductPage pp = new ProductPage();
+      pp.setNumOfHits(0);
+      pp.setPageProducts(new ArrayList<Product>());
+      pp.setPageSize(10);
+      pp.setTotalPages(0);
+      pp.setPageNum(curPage.getPageNum() + 1);
+      return pp;
+   }
+
+   @Override
+   public ProductPage getPrevPage(ProductType type, ProductPage curPage) {
+      lastMethodCallDetails = new MethodCallDetails("getPrevPage",
+            Lists.newArrayList((Object) type, curPage));
+      ProductPage pp = new ProductPage();
+      pp.setNumOfHits(0);
+      pp.setPageProducts(new ArrayList<Product>());
+      pp.setPageSize(10);
+      pp.setTotalPages(0);
+      pp.setPageNum(curPage.getPageNum() - 1);
+      return pp;
+   }
+
+   @Override
+   public int getNumProducts(ProductType type) {
+      lastMethodCallDetails = new MethodCallDetails("getNumProducts",
+            Lists.newArrayList((Object) type));
+      return 0;
+   }
+
+   @Override
+   public double getProductPctTransferred(Product product) {
+      lastMethodCallDetails = new MethodCallDetails("getProductPctTransferred",
+            Lists.newArrayList((Object) product));
+      return 0.6;
+   }
+
+   @Override
+   public boolean hasProduct(String productName) {
+      lastMethodCallDetails = new MethodCallDetails("hasProduct",
+            Lists.newArrayList((Object) productName));
+      return true;
+   }
+
+   @Override
+   public String ingestProduct(Product p, Metadata m, boolean clientTransfer) {
+      lastMethodCallDetails = new MethodCallDetails("ingestProduct",
+            Lists.newArrayList((Object) p, m, clientTransfer));
+      return "TestProductId";
+   }
+
+   @Override
+   public List<ProductType> getProductTypes() {
+      lastMethodCallDetails = new MethodCallDetails("getProductTypes",
+            Lists.newArrayList());
+      ProductType pt = new ProductType();
+      pt.setName("TestProductType");
+      return Lists.newArrayList(pt);
+   }
+
+   @Override
+   public List<QueryResult> complexQuery(ComplexQuery query) {
+      lastMethodCallDetails = new MethodCallDetails("complexQuery",
+            Lists.newArrayList((Object) query));
+      return Lists.newArrayList();
+   }
+
+   @Override
+   public Metadata getMetadata(Product p) {
+      lastMethodCallDetails = new MethodCallDetails("getMetadata",
+            Lists.newArrayList((Object) p));
+      return new Metadata();
+   }
+
+   public class MethodCallDetails {
+      private String methodName;
+      private List<Object> args;
+
+      public MethodCallDetails(String methodName, List<Object> args) {
+         this.methodName = methodName;
+         this.args = args;
+      }
+
+      public String getMethodName() {
+         return methodName;
+      }
+
+      public List<Object> getArgs() {
+         return args;
+      }
+   }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/system/TestXmlRpcFileManager.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/system/TestXmlRpcFileManager.java
new file mode 100644
index 0000000..166c33d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/system/TestXmlRpcFileManager.java
@@ -0,0 +1,300 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.system;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Properties;
+//OODT imports
+import org.apache.oodt.cas.filemgr.ingest.StdIngester;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.metadata.ProductMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test harness for the XmlRpcFileManager.
+ * 
+ * @since OODT-72
+ * 
+ */
+public class TestXmlRpcFileManager extends TestCase {
+
+  private static final int FM_PORT = 50001;
+
+  private XmlRpcFileManager fm;
+
+  private String luceneCatLoc;
+
+  private static final String transferServiceFacClass = "org.apache.oodt.cas."
+      + "filemgr.datatransfer.LocalDataTransferFactory";
+
+  private Properties initialProperties = new Properties(
+      System.getProperties());
+
+  /**
+   * @since OODT-72
+   */
+  public void testExpandProductMet() {
+    XmlRpcFileManagerClient fmc = null;
+    try {
+      fmc = new XmlRpcFileManagerClient(new URL("http://localhost:" + FM_PORT));
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    Metadata met = null;
+    try {
+      met = fmc.getMetadata(fmc.getProductByName("test.txt"));
+    } catch (CatalogException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+
+    assertNotNull(met);
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_ID));
+    assertNotNull(met.getMetadata(ProductMetKeys.PRODUCT_ID));
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_NAME));
+    assertNotNull(met.getMetadata(ProductMetKeys.PRODUCT_NAME));
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_STRUCTURE));
+    assertEquals("Flat", met.getMetadata(ProductMetKeys.PRODUCT_STRUCTURE));
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_TRANSFER_STATUS));
+    assertEquals(Product.STATUS_RECEIVED, met
+        .getMetadata(ProductMetKeys.PRODUCT_TRANSFER_STATUS));
+
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_ORIG_REFS));
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_DATASTORE_REFS));
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_FILE_SIZES));
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_MIME_TYPES));
+
+    assertEquals(1, met.getAllMetadata(ProductMetKeys.PRODUCT_ORIG_REFS).size());
+    assertEquals(1, met.getAllMetadata(ProductMetKeys.PRODUCT_DATASTORE_REFS)
+        .size());
+    assertEquals(1, met.getAllMetadata(ProductMetKeys.PRODUCT_FILE_SIZES)
+        .size());
+    assertEquals(1, met.getAllMetadata(ProductMetKeys.PRODUCT_MIME_TYPES)
+        .size());
+
+    URL refUrl = this.getClass().getResource("/ingest/test.txt");
+
+    String origPath = null;
+    try {
+      origPath = new File(refUrl.getFile()).getCanonicalPath();
+    } catch (IOException e) {
+      fail(e.getMessage());
+    }
+    assertEquals(origPath, met.getMetadata(ProductMetKeys.PRODUCT_ORIG_REFS));
+    assertEquals("/tmp/test.txt/test.txt", met
+        .getMetadata(ProductMetKeys.PRODUCT_DATASTORE_REFS));
+
+    assertNotNull(met.getMetadata(ProductMetKeys.PRODUCT_FILE_SIZES));
+    assertEquals("text/plain", met
+        .getMetadata(ProductMetKeys.PRODUCT_MIME_TYPES));
+
+    try {
+      met = fmc.getReducedMetadata(fmc.getProductByName("test.txt"),
+          Collections.EMPTY_LIST);
+    } catch (CatalogException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+
+    assertNotNull(met);
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_ID));
+    assertNotNull(met.getMetadata(ProductMetKeys.PRODUCT_ID));
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_NAME));
+    assertNotNull(met.getMetadata(ProductMetKeys.PRODUCT_NAME));
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_STRUCTURE));
+    assertEquals("Flat", met.getMetadata(ProductMetKeys.PRODUCT_STRUCTURE));
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_TRANSFER_STATUS));
+    assertEquals(Product.STATUS_RECEIVED, met
+        .getMetadata(ProductMetKeys.PRODUCT_TRANSFER_STATUS));
+
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_ORIG_REFS));
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_DATASTORE_REFS));
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_FILE_SIZES));
+    assertTrue(met.containsKey(ProductMetKeys.PRODUCT_MIME_TYPES));
+
+    assertEquals(1, met.getAllMetadata(ProductMetKeys.PRODUCT_ORIG_REFS).size());
+    assertEquals(1, met.getAllMetadata(ProductMetKeys.PRODUCT_DATASTORE_REFS)
+        .size());
+    assertEquals(1, met.getAllMetadata(ProductMetKeys.PRODUCT_FILE_SIZES)
+        .size());
+    assertEquals(1, met.getAllMetadata(ProductMetKeys.PRODUCT_MIME_TYPES)
+        .size());
+
+    origPath = null;
+    try {
+      origPath = new File(refUrl.getFile()).getCanonicalPath();
+    } catch (IOException e) {
+      fail(e.getMessage());
+    }
+    assertEquals(origPath, met.getMetadata(ProductMetKeys.PRODUCT_ORIG_REFS));
+    assertEquals("/tmp/test.txt/test.txt", met
+        .getMetadata(ProductMetKeys.PRODUCT_DATASTORE_REFS));
+
+    assertNotNull(met.getMetadata(ProductMetKeys.PRODUCT_FILE_SIZES));
+    assertEquals("text/plain", met
+        .getMetadata(ProductMetKeys.PRODUCT_MIME_TYPES));
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#setUp()
+   */
+  protected void setUp() throws Exception {
+    startXmlRpcFileManager();
+    ingestTestFile();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#tearDown()
+   */
+  protected void tearDown() throws Exception {
+    fm.shutdown();
+    fm = null;
+
+    // blow away lucene cat
+    deleteAllFiles(luceneCatLoc);
+
+    // blow away test file
+    deleteAllFiles("/tmp/test.txt");
+
+    // Reset the System properties to initial values.
+    System.setProperties(initialProperties);
+  }
+
+  private void deleteAllFiles(String startDir) {
+    File startDirFile = new File(startDir);
+    File[] delFiles = startDirFile.listFiles();
+
+    if (delFiles != null && delFiles.length > 0) {
+      for (int i = 0; i < delFiles.length; i++) {
+        delFiles[i].delete();
+      }
+    }
+
+    startDirFile.delete();
+
+  }
+
+  private void ingestTestFile() {
+    Metadata prodMet = null;
+    StdIngester ingester = new StdIngester(transferServiceFacClass);
+
+    try {
+      URL ingestUrl = this.getClass().getResource("/ingest");
+      URL refUrl = this.getClass().getResource("/ingest/test.txt");
+      URL metUrl = this.getClass().getResource("/ingest/test.txt.met");
+
+      prodMet = new SerializableMetadata(new FileInputStream(
+        new File(metUrl.getFile())));
+
+      // now add the right file location
+      prodMet.addMetadata(CoreMetKeys.FILE_LOCATION, new File(
+        ingestUrl.getFile()).getCanonicalPath());
+      prodMet.addMetadata(CoreMetKeys.FILENAME, "test.txt");
+      prodMet.addMetadata(CoreMetKeys.PRODUCT_TYPE, "GenericFile");
+      ingester.ingest(new URL("http://localhost:" + FM_PORT), new File(
+        refUrl.getFile()), prodMet);
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+  }
+
+  private void startXmlRpcFileManager() {
+
+    Properties properties = new Properties(System.getProperties());
+
+    // first make sure to load properties for the file manager
+    // and make sure to load logging properties as well
+
+    // set the log levels
+    URL loggingPropertiesUrl = this.getClass().getResource(
+      "/test.logging.properties");
+    properties.setProperty("java.util.logging.config.file", new File(
+      loggingPropertiesUrl.getFile()).getAbsolutePath());
+
+    // first load the example configuration
+    try {
+      URL filemgrPropertiesUrl = this.getClass().getResource(
+        "/filemgr.properties");
+      properties.load(
+        new FileInputStream(new File(filemgrPropertiesUrl.getFile())));
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    // override the catalog to use: we'll use lucene
+    try {
+      URL ingestUrl = this.getClass().getResource("/ingest");
+      luceneCatLoc = new File(ingestUrl.getFile()).getCanonicalPath() + "/cat";
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    properties.setProperty("filemgr.catalog.factory",
+        "org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory");
+    properties.setProperty("org.apache.oodt.cas.filemgr.catalog.lucene.idxPath",
+        luceneCatLoc);
+
+    // now override the repo mgr policy
+    URL fmpolicyUrl = this.getClass().getResource("/ingest/fmpolicy");
+    try {
+      properties.setProperty("org.apache.oodt.cas.filemgr.repositorymgr.dirs",
+        "file://" + new File(fmpolicyUrl.getFile()).getCanonicalPath());
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    // now override the val layer ones
+    properties.setProperty("org.apache.oodt.cas.filemgr.validation.dirs",
+      "file://" + new File(fmpolicyUrl.getFile()).getAbsolutePath());
+
+    // set up mime repo path
+    URL mimeTypesUrl = this.getClass().getResource("/mime-types.xml");
+    properties.setProperty("org.apache.oodt.cas.filemgr.mime.type.repository",
+      new File(mimeTypesUrl.getFile()).getAbsolutePath());
+
+    // override expand product met
+    properties.setProperty("org.apache.oodt.cas.filemgr.metadata.expandProduct",
+      "true");
+
+    System.setProperties(properties);
+
+    try {
+      fm = new XmlRpcFileManager(FM_PORT);
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+  }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/system/TestXmlRpcFileManagerClient.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/system/TestXmlRpcFileManagerClient.java
new file mode 100644
index 0000000..0d0aba4
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/system/TestXmlRpcFileManagerClient.java
@@ -0,0 +1,347 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.system;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.ingest.StdIngester;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.query.ComplexQuery;
+import org.apache.oodt.cas.filemgr.structs.query.QueryResult;
+import org.apache.oodt.cas.filemgr.util.SqlParser;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test suite for the {@link XmlRpcFileManagerClient}
+ * </p>.
+ */
+public class TestXmlRpcFileManagerClient extends TestCase {
+
+    private static final int FM_PORT = 50001;
+
+    private XmlRpcFileManager fm;
+    
+    private String luceneCatLoc;
+
+    private static final String transferServiceFacClass = "org.apache.oodt.cas."
+            + "filemgr.datatransfer.LocalDataTransferFactory";
+
+    private Properties initialProperties = new Properties(
+      System.getProperties());
+
+    public TestXmlRpcFileManagerClient() {
+    }
+
+    
+    /**
+     * @since OODT-161
+     * 
+     */
+    public void testGetReducedMetadata() {
+        List arrayListElems = new ArrayList();
+        List vectorElemList = new Vector();
+        List linkedListElemList = new LinkedList();
+
+        arrayListElems.add(CoreMetKeys.FILENAME);
+        vectorElemList.add(CoreMetKeys.FILENAME);
+        linkedListElemList.add(CoreMetKeys.FILENAME);
+
+        try {
+            XmlRpcFileManagerClient fmc = new XmlRpcFileManagerClient(new URL(
+                    "http://localhost:" + FM_PORT));
+            
+            Metadata reducedMet = null;
+            List pTypes = fmc.getProductTypes();
+            assertNotNull(pTypes);
+            assertTrue(pTypes.size() > 0);
+            ProductType genericFileType = fmc.getProductTypeByName("GenericFile");
+            assertNotNull(genericFileType);
+            List products = fmc.getProductsByProductType(genericFileType);
+            assertNotNull(products);
+            assertTrue(products.size() > 0);
+            Product product = (Product) products.get(0);
+            assertNotNull(product);
+
+            reducedMet = fmc.getReducedMetadata(product, arrayListElems);
+            assertNotNull(reducedMet);
+            assertTrue(reducedMet.containsKey(CoreMetKeys.FILENAME));
+            assertEquals(reducedMet.getHashtable().keySet().size(), 1);
+
+            reducedMet = fmc.getReducedMetadata(product, vectorElemList);
+            assertNotNull(reducedMet);
+            assertTrue(reducedMet.containsKey(CoreMetKeys.FILENAME));
+            assertEquals(reducedMet.getHashtable().keySet().size(), 1);
+
+            reducedMet = fmc.getReducedMetadata(product, linkedListElemList);
+            assertNotNull(reducedMet);
+            assertTrue(reducedMet.containsKey(CoreMetKeys.FILENAME));
+            assertEquals(reducedMet.getHashtable().keySet().size(), 1);
+            
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }finally {
+            fm.shutdown();
+        }
+
+    }
+    
+    public void testIngest() throws Exception {
+        URL ingestUrl = this.getClass().getResource("/ingest");
+        URL refUrl = this.getClass().getResource("/ingest/test.txt");
+
+        Metadata prodMet = new Metadata();
+        prodMet.addMetadata(CoreMetKeys.FILE_LOCATION, new File(
+          ingestUrl.getFile()).getCanonicalPath());
+        prodMet.addMetadata(CoreMetKeys.FILENAME, "test.txt");
+        prodMet.addMetadata(CoreMetKeys.PRODUCT_NAME, "TestFile");
+        prodMet.addMetadata(CoreMetKeys.PRODUCT_TYPE, "GenericFile");
+
+        StdIngester ingester = new StdIngester(transferServiceFacClass);
+        String productId = ingester.ingest(
+          new URL("http://localhost:" + FM_PORT),
+          new File(refUrl.getFile()), prodMet);
+        XmlRpcFileManagerClient fmc = new XmlRpcFileManagerClient(new URL(
+                "http://localhost:" + FM_PORT));
+        Metadata m = fmc.getMetadata(fmc.getProductById(productId));
+        assertEquals(m.getMetadata("Filename"), "test.txt");
+        deleteAllFiles("/tmp/test-type");
+    }
+
+    /**
+     * @since OODT-404
+     *
+     */
+    public void testMetadataPersistence() throws Exception {
+        URL ingestUrl = this.getClass().getResource("/ingest");
+        URL refUrl = this.getClass().getResource("/ingest/test-file-3.txt");
+        URL metUrl = this.getClass().getResource("/ingest/test-file-3.txt.met");
+
+        Metadata prodMet = null;
+        StdIngester ingester = new StdIngester(transferServiceFacClass);
+        prodMet = new SerializableMetadata(new FileInputStream(
+            metUrl.getFile()));
+        // now add the right file location
+        prodMet.addMetadata(CoreMetKeys.FILE_LOCATION, new File(
+            ingestUrl.getFile()).getCanonicalPath());
+        String productId = ingester.ingest(
+            new URL("http://localhost:" + FM_PORT),
+            new File(refUrl.getFile()), prodMet);
+        XmlRpcFileManagerClient fmc = new XmlRpcFileManagerClient(new URL(
+                "http://localhost:" + FM_PORT));
+             
+        Metadata m = fmc.getMetadata(fmc.getProductById(productId));
+        assertEquals(m.getAllMetadata("TestElement").size(), 4);
+        assertEquals(m.getMetadata("TestElement"), "fe");
+    }
+
+    
+    public void testComplexQuery() throws Exception {
+        URL ingestUrl = this.getClass().getResource("/ingest");
+        URL refUrl1 = this.getClass().getResource("/ingest/test-file-1.txt");
+        URL refUrl2 = this.getClass().getResource("/ingest/test-file-2.txt");
+
+        StdIngester ingester = new StdIngester(transferServiceFacClass);
+
+        //ingest first file
+        Metadata prodMet = new Metadata();
+        prodMet.addMetadata(CoreMetKeys.FILE_LOCATION, new File(
+            ingestUrl.getFile()).getCanonicalPath());
+        prodMet.addMetadata(CoreMetKeys.FILENAME, "test-file-1.txt");
+        prodMet.addMetadata(CoreMetKeys.PRODUCT_NAME, "TestFile1");
+        prodMet.addMetadata(CoreMetKeys.PRODUCT_TYPE, "GenericFile");
+        ingester.ingest(new URL("http://localhost:" + FM_PORT), new File(
+            refUrl1.getFile()), prodMet);           
+        
+        //ingest second file
+        prodMet.replaceMetadata(CoreMetKeys.FILENAME, "test-file-2.txt");
+        prodMet.replaceMetadata(CoreMetKeys.PRODUCT_NAME, "TestFile2");
+        ingester.ingest(new URL("http://localhost:" + FM_PORT), new File(
+            refUrl2.getFile()), prodMet);   
+        
+        //perform complex query
+        ComplexQuery complexQuery = new ComplexQuery();
+        List<String> reducedMetadata = new Vector<String>();
+        reducedMetadata.add(CoreMetKeys.FILENAME);
+        complexQuery.setReducedMetadata(reducedMetadata);
+        List<String> productTypeNames = new Vector<String>();
+        productTypeNames.add("GenericFile");
+        complexQuery.setReducedProductTypeNames(productTypeNames);
+        complexQuery.setSortByMetKey(CoreMetKeys.FILENAME);
+        complexQuery.setToStringResultFormat("$" + CoreMetKeys.FILENAME);
+        complexQuery.addCriterion(SqlParser.parseSqlWhereClause("Filename != 'test.txt'"));
+        XmlRpcFileManagerClient fmc = new XmlRpcFileManagerClient(new URL(
+                "http://localhost:" + FM_PORT));
+        List<QueryResult> queryResults = fmc.complexQuery(complexQuery);
+        assertEquals("[test-file-1.txt, test-file-2.txt]", queryResults.toString());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        startXmlRpcFileManager();
+        ingestTestFile();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        fm.shutdown();
+        fm = null;
+        
+        // blow away lucene cat
+        deleteAllFiles(luceneCatLoc);
+
+        // blow away test file
+        deleteAllFiles("/tmp/test.txt");
+
+        // Reset the System properties to initial values.
+        System.setProperties(initialProperties);
+    }
+
+    private void deleteAllFiles(String startDir) {
+        File startDirFile = new File(startDir);
+        File[] delFiles = startDirFile.listFiles();
+
+        if (delFiles != null && delFiles.length > 0) {
+            for (int i = 0; i < delFiles.length; i++) {
+                delFiles[i].delete();
+            }
+        }
+
+        startDirFile.delete();
+
+    }
+
+    private void ingestTestFile() {
+        Metadata prodMet = null;
+        StdIngester ingester = new StdIngester(transferServiceFacClass);
+
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            URL refUrl = this.getClass().getResource("/ingest/test.txt");
+            URL metUrl = this.getClass().getResource("/ingest/test.txt.met");
+
+            prodMet = new SerializableMetadata(new FileInputStream(
+                new File(metUrl.getFile())));
+
+            // now add the right file location
+            prodMet.addMetadata(CoreMetKeys.FILE_LOCATION, new File(
+                ingestUrl.getFile()).getCanonicalPath());
+            prodMet.addMetadata(CoreMetKeys.FILENAME, "test.txt");
+            prodMet.addMetadata(CoreMetKeys.PRODUCT_TYPE, "GenericFile");
+            ingester.ingest(new URL("http://localhost:" + FM_PORT), new File(
+                refUrl.getFile()), prodMet);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+    private void startXmlRpcFileManager() {
+
+        Properties properties = new Properties(System.getProperties());
+
+        // first make sure to load properties for the file manager
+        // and make sure to load logging properties as well
+
+        // set the log levels
+        URL loggingPropertiesUrl = this.getClass().getResource(
+            "/test.logging.properties");
+        properties.setProperty("java.util.logging.config.file", new File(
+            loggingPropertiesUrl.getFile()).getAbsolutePath());
+
+        // first load the example configuration
+        try {
+            URL filemgrPropertiesUrl = this.getClass().getResource(
+                "/filemgr.properties");
+            properties.load(
+                new FileInputStream(new File(filemgrPropertiesUrl.getFile())));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // override the catalog to use: we'll use lucene
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            luceneCatLoc = new File(ingestUrl.getFile()).getCanonicalPath()
+                + "/cat";
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        properties.setProperty("filemgr.catalog.factory",
+                "org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.lucene.idxPath",
+                luceneCatLoc);
+
+        // now override the repo mgr policy
+        URL fmpolicyUrl = this.getClass().getResource("/ingest/fmpolicy");
+        try {
+            properties.setProperty(
+                "org.apache.oodt.cas.filemgr.repositorymgr.dirs",
+                "file://" + new File(fmpolicyUrl.getFile()).getCanonicalPath());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // now override the val layer ones
+        properties.setProperty("org.apache.oodt.cas.filemgr.validation.dirs",
+            "file://" + new File(fmpolicyUrl.getFile()).getAbsolutePath());
+
+        // set up mime repo path
+        URL mimeTypesUrl = this.getClass().getResource("/mime-types.xml");
+        properties.setProperty(
+            "org.apache.oodt.cas.filemgr.mime.type.repository",
+            new File(mimeTypesUrl.getFile()).getAbsolutePath());
+
+        System.setProperties(properties);
+
+        try {
+            fm = new XmlRpcFileManager(FM_PORT);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/tools/TestExpImpCatalog.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/tools/TestExpImpCatalog.java
new file mode 100644
index 0000000..53b07e0
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/tools/TestExpImpCatalog.java
@@ -0,0 +1,332 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.ingest.StdIngester;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManager;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class TestExpImpCatalog extends TestCase {
+
+    private static final int FM_PORT = 50010;
+
+    private XmlRpcFileManager fm;
+
+    private XmlRpcFileManager fm2;
+
+    private ExpImpCatalog expImp;
+
+    private static final String transferServiceFacClass = "org.apache.oodt.cas."
+            + "filemgr.datatransfer.LocalDataTransferFactory";
+
+    private Properties initialProperties = new Properties(
+        System.getProperties());
+
+    public TestExpImpCatalog() {
+    }
+    
+    public void testEnsureUniqueOn(){
+        expImp.setEnsureUnique(true);
+        
+        try {
+            expImp.doExpImport();
+            expImp.doExpImport();
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        // now test that 1 producs exist in the catalog, and that
+        // its name is test.txt
+        
+        try {
+            XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(
+                    new URL("http://localhost:" + (FM_PORT + 1)));
+            assertEquals(1, fmClient.getNumProducts(fmClient
+                    .getProductTypeByName("GenericFile")));
+
+            List prods = fmClient.getProductsByProductType(fmClient
+                    .getProductTypeByName("GenericFile"));
+            assertNotNull(prods);
+            assertEquals(1, prods.size());
+
+            int countProds = 0;
+
+            for (Iterator i = prods.iterator(); i.hasNext();) {
+                Product p = (Product) i.next();
+                if (p.getProductName().equals("test.txt")) {
+                    countProds++;
+                }
+            }
+
+            assertEquals(1, countProds);
+            fmClient = null;
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }        
+    }
+
+    public void testEnsureUniqueOff() {
+        expImp.setEnsureUnique(false);
+        
+        try {
+            expImp.doExpImport();
+            expImp.doExpImport();
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        // now test that 2 producs exist in the catalog, and that
+        // both of their names are test.txt
+
+        // now test that test.txt exists in cat 2
+        try {
+            XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(
+                    new URL("http://localhost:" + (FM_PORT + 1)));
+            assertEquals(2, fmClient.getNumProducts(fmClient
+                    .getProductTypeByName("GenericFile")));
+
+            List prods = fmClient.getProductsByProductType(fmClient
+                    .getProductTypeByName("GenericFile"));
+            assertNotNull(prods);
+            assertEquals(2, prods.size());
+
+            int countProds = 0;
+
+            for (Iterator i = prods.iterator(); i.hasNext();) {
+                Product p = (Product) i.next();
+                if (p.getProductName().equals("test.txt")) {
+                    countProds++;
+                }
+            }
+
+            assertEquals(2, countProds);
+            fmClient = null;
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+    }
+
+    public void testExpImp() {
+        try {
+            expImp.doExpImport();
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        // now test that test.txt exists in cat 2
+        try {
+            XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(
+                    new URL("http://localhost:" + (FM_PORT + 1)));
+            Product prod = fmClient.getProductByName("test.txt");
+            assertNotNull(prod);
+            Metadata met = fmClient.getMetadata(prod);
+            assertNotNull(met);
+            assertTrue(met.containsKey(CoreMetKeys.PRODUCT_STRUCTURE));
+            prod.setProductReferences(fmClient.getProductReferences(prod));
+            assertNotNull(prod.getProductReferences());
+            assertEquals(1, prod.getProductReferences().size());
+            fmClient = null;
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        System.out.println("Test set up");
+        URL ingestUrl = this.getClass().getResource("/ingest");
+        String cat1 = new File(ingestUrl.getFile()).getCanonicalPath() + "cat";
+        String cat2 = new File(ingestUrl.getFile()).getCanonicalPath() + "cat2";
+        fm = startXmlRpcFileManager(FM_PORT, cat1);
+        fm2 = startXmlRpcFileManager(FM_PORT + 1, cat2);
+        ingestTestFiles();
+        try {
+            expImp = new ExpImpCatalog(new URL("http://localhost:" + FM_PORT),
+                    new URL("http://localhost:" + (FM_PORT + 1)), true);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        fm.shutdown();
+        fm = null;
+        fm2.shutdown();
+        fm2 = null;
+
+        // blow away lucene cat
+        URL ingestUrl = this.getClass().getResource("/ingest");
+        String cat1 = new File(ingestUrl.getFile()).getCanonicalPath() + "cat";
+        String cat2 = new File(ingestUrl.getFile()).getCanonicalPath() + "cat2";
+        deleteAllFiles(cat1);
+        deleteAllFiles(cat2);
+
+        // blow away test file
+        deleteAllFiles("/tmp/test.txt");
+
+        // Reset the System properties to initial values.
+        System.setProperties(initialProperties);
+    }
+
+    private void ingestTestFiles() {
+        Metadata prodMet = null;
+        StdIngester ingester = new StdIngester(transferServiceFacClass);
+
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            URL refUrl = this.getClass().getResource("/ingest/test.txt");
+            URL metUrl = this.getClass().getResource("/ingest/test.txt.met");
+
+            prodMet = new SerializableMetadata(new FileInputStream(
+                new File(metUrl.getFile())));
+
+            // now add the right file location
+            prodMet.addMetadata(CoreMetKeys.FILE_LOCATION, new File(
+                ingestUrl.getFile()).getCanonicalPath());
+            ingester.ingest(new URL("http://localhost:" + FM_PORT), new File(
+                refUrl.getFile()), prodMet);
+            
+            prodMet.replaceMetadata(CoreMetKeys.PRODUCT_NAME, "TestTypeFile");
+            prodMet.replaceMetadata(CoreMetKeys.PRODUCT_TYPE, "TestType");
+            ingester.ingest(new URL("http://localhost:" + FM_PORT), new File(
+                refUrl.getFile()), prodMet);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+    private void deleteAllFiles(String startDir) {
+        File startDirFile = new File(startDir);
+        File[] delFiles = startDirFile.listFiles();
+
+        if (delFiles != null && delFiles.length > 0) {
+            for (int i = 0; i < delFiles.length; i++) {
+                delFiles[i].delete();
+            }
+        }
+
+        startDirFile.delete();
+
+    }
+
+    private XmlRpcFileManager startXmlRpcFileManager(int port, String catPath) {
+
+        Properties properties = new Properties(System.getProperties());
+
+        XmlRpcFileManager fileMgr = null;
+        
+        // first make sure to load properties for the file manager
+        // and make sure to load logging properties as well
+
+        // set the log levels
+        URL loggingPropertiesUrl = this.getClass().getResource(
+            "/test.logging.properties");
+        properties.setProperty("java.util.logging.config.file", new File(
+            loggingPropertiesUrl.getFile()).getAbsolutePath());
+        
+        
+        // first load the example configuration
+        try {
+            URL filemgrPropertiesUrl = this.getClass().getResource(
+                "/filemgr.properties");
+            properties.load(
+                new FileInputStream(new File(filemgrPropertiesUrl.getFile())));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // override the catalog to use: we'll use lucene
+        properties.setProperty("filemgr.catalog.factory",
+                "org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.lucene.idxPath",
+                catPath);
+
+        // now override the repo mgr policy
+        URL fmpolicyUrl = this.getClass().getResource("/ingest/fmpolicy");
+        try {
+          properties.setProperty(
+              "org.apache.oodt.cas.filemgr.repositorymgr.dirs",
+              "file://" + new File(fmpolicyUrl.getFile()).getCanonicalPath());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // now override the val layer ones
+        properties.setProperty("org.apache.oodt.cas.filemgr.validation.dirs",
+            "file://" + new File(fmpolicyUrl.getFile()).getAbsolutePath());
+
+        // set up mime repo path
+        URL mimeTypesUrl = this.getClass().getResource("/mime-types.xml");
+        properties.setProperty(
+            "org.apache.oodt.cas.filemgr.mime.type.repository",
+            new File(mimeTypesUrl.getFile()).getAbsolutePath());
+
+        System.setProperties(properties);
+
+        try {
+            fileMgr = new XmlRpcFileManager(port);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        return fileMgr;
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/tools/TestMetadataBasedProductMover.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/tools/TestMetadataBasedProductMover.java
new file mode 100644
index 0000000..42e50e0
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/tools/TestMetadataBasedProductMover.java
@@ -0,0 +1,242 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.tools;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.ingest.StdIngester;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManager;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.Properties;
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class TestMetadataBasedProductMover extends TestCase {
+
+    private static final int FM_PORT = 50010;
+
+    private XmlRpcFileManager fm;
+
+    private String luceneCatLoc;
+
+    private static final String transferServiceFacClass = "org.apache.oodt.cas."
+            + "filemgr.datatransfer.LocalDataTransferFactory";
+
+    private String testPathSpec = "/tmp/[MimeType]/[ProductStructure]/[CAS.ProductName]/[Filename]";
+
+    private String expectedLoc = "/tmp/text/plain/Flat/test.txt/test.txt";
+
+    private MetadataBasedProductMover mover;
+
+    private Properties initialProperties = new Properties(
+        System.getProperties());
+
+    public TestMetadataBasedProductMover() {
+    }
+
+    public void testMoveProducts() {
+        try {
+            mover.moveProducts("GenericFile");
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // make sure that there is a product at expectedLoc
+        assertTrue(new File(expectedLoc).exists());
+
+    }
+
+    private void ingestTestFile() {
+        Metadata prodMet = null;
+        StdIngester ingester = new StdIngester(transferServiceFacClass);
+
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            URL refUrl = this.getClass().getResource("/ingest/test.txt");
+            URL metUrl = this.getClass().getResource("/ingest/test.txt.met");
+
+            prodMet = new SerializableMetadata(new FileInputStream(
+                new File(metUrl.getFile())));
+
+            // now add the right file location
+            prodMet.addMetadata(CoreMetKeys.FILE_LOCATION, new File(
+                ingestUrl.getFile()).getCanonicalPath());
+            ingester.ingest(new URL("http://localhost:" + FM_PORT), new File(
+                refUrl.getFile()), prodMet);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        startXmlRpcFileManager();
+        ingestTestFile();
+        try {
+            mover = new MetadataBasedProductMover(testPathSpec,
+                    "http://localhost:" + FM_PORT);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        fm.shutdown();
+        fm = null;
+
+        // blow away lucene cat
+        deleteAllFiles(luceneCatLoc);
+
+        // blow away test file
+        deleteAllFiles("/tmp/test.txt");
+
+        // blow away test file
+        deleteAllFilesRecursive("/tmp/text");
+
+        // Reset the System properties to initial values.
+        System.setProperties(initialProperties);
+    }
+
+    private void deleteAllFilesRecursive(String startDirPath) {
+        File startDirFile = new File(startDirPath);
+        File[] dirFiles = startDirFile.listFiles();
+
+        if (dirFiles != null && dirFiles.length > 0) {
+            for (int i = 0; i < dirFiles.length; i++) {
+                if (dirFiles[i].isDirectory()) {
+                    deleteAllFilesRecursive(dirFiles[i].getAbsolutePath());
+                    // all dir files deleted, now delete dir
+                    dirFiles[i].delete();
+                } else {
+                    dirFiles[i].delete();
+                }
+            }
+        }
+
+        // now delete the root dir
+        startDirFile.delete();
+
+    }
+
+    private void deleteAllFiles(String startDir) {
+        File startDirFile = new File(startDir);
+        File[] delFiles = startDirFile.listFiles();
+
+        if (delFiles != null && delFiles.length > 0) {
+            for (int i = 0; i < delFiles.length; i++) {
+                delFiles[i].delete();
+            }
+        }
+
+        startDirFile.delete();
+
+    }
+
+    private void startXmlRpcFileManager() {
+
+        Properties properties = new Properties(System.getProperties());
+
+        // first make sure to load properties for the file manager
+        // and make sure to load logging properties as well
+
+        // set the log levels
+        URL loggingPropertiesUrl = this.getClass().getResource(
+            "/test.logging.properties");
+        properties.setProperty("java.util.logging.config.file", new File(
+            loggingPropertiesUrl.getFile()).getAbsolutePath());
+
+        // first load the example configuration
+        try {
+            URL filemgrPropertiesUrl = this.getClass().getResource(
+                "/filemgr.properties");
+            properties.load(
+              new FileInputStream(new File(filemgrPropertiesUrl.getFile())));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // override the catalog to use: we'll use lucene
+        try {
+            URL ingestUrl = this.getClass().getResource("/ingest");
+            luceneCatLoc = new File(ingestUrl.getFile()).getCanonicalPath()
+                + "/cat";
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        properties.setProperty("filemgr.catalog.factory",
+                "org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory");
+        properties.setProperty(
+                "org.apache.oodt.cas.filemgr.catalog.lucene.idxPath",
+                luceneCatLoc);
+
+        // now override the repo mgr policy
+        try {
+          URL fmpolicyUrl = this.getClass().getResource("/ingest/fmpolicy");
+          properties.setProperty(
+              "org.apache.oodt.cas.filemgr.repositorymgr.dirs",
+              "file://" + new File(fmpolicyUrl.getFile()).getCanonicalPath());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // now override the val layer ones
+        URL examplesCoreUrl = this.getClass().getResource("/examples/core");
+        properties.setProperty("org.apache.oodt.cas.filemgr.validation.dirs",
+            "file://" + new File(examplesCoreUrl.getFile()).getAbsolutePath());
+
+        // set up mime repo path
+        URL mimeTypesUrl = this.getClass().getResource("/mime-types.xml");
+        properties.setProperty(
+            "org.apache.oodt.cas.filemgr.mime.type.repository",
+            new File(mimeTypesUrl.getFile()).getAbsolutePath());
+
+        System.setProperties(properties);
+
+        try {
+            fm = new XmlRpcFileManager(FM_PORT);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/util/TestGenericFileManagerObjectStructFactory.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/util/TestGenericFileManagerObjectStructFactory.java
new file mode 100644
index 0000000..d2cd3d3
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/util/TestGenericFileManagerObjectStructFactory.java
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.util;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.catalog.Catalog;
+import org.apache.oodt.cas.filemgr.datatransfer.DataTransfer;
+import org.apache.oodt.cas.filemgr.metadata.extractors.FilemgrMetExtractor;
+import org.apache.oodt.cas.filemgr.repository.RepositoryManager;
+import org.apache.oodt.cas.filemgr.validation.ValidationLayer;
+import org.apache.oodt.cas.filemgr.versioning.Versioner;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class TestGenericFileManagerObjectStructFactory extends TestCase {
+
+    private static final String dataTransferServiceFactory = "org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory";
+
+    private static final String validationServiceFactory = "org.apache.oodt.cas.filemgr.validation.XMLValidationLayerFactory";
+
+    private static final String catalogServiceFactory = "org.apache.oodt.cas.filemgr.catalog.DataSourceCatalogFactory";
+
+    private static final String repositoryServiceFactory = "org.apache.oodt.cas.filemgr.repository.XMLRepositoryManagerFactory";
+
+    private static final String versionerClass = "org.apache.oodt.cas.filemgr.versioning.BasicVersioner";
+
+    private static final String extractorClass = "org.apache.oodt.cas.filemgr.metadata.extractors.CoreMetExtractor";
+
+    private Properties initialProperties = new Properties(
+        System.getProperties());
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+
+        Properties properties = new Properties(System.getProperties());
+
+      // set the log levels
+        URL loggingPropertiesUrl = this.getClass().getResource(
+            "/test.logging.properties");
+        properties.setProperty("java.util.logging.config.file", new File(
+            loggingPropertiesUrl.getFile()).getAbsolutePath());
+
+        // first load the example configuration
+        try {
+            URL filemgrPropertiesUrl = this.getClass().getResource(
+                "/filemgr.properties");
+            properties.load(new FileInputStream(
+                filemgrPropertiesUrl.getFile()));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        System.setProperties(properties);
+    }
+
+    protected void tearDown() throws Exception {
+        System.setProperties(initialProperties);
+    }
+
+    public void testGetDataTransferServiceFromFactory() {
+        DataTransfer transferer = GenericFileManagerObjectFactory
+                .getDataTransferServiceFromFactory(dataTransferServiceFactory);
+        assertNotNull(transferer);
+    }
+
+    public void testGetRepositoryManagerServiceFromFactory() {
+        RepositoryManager repMgr = GenericFileManagerObjectFactory
+                .getRepositoryManagerServiceFromFactory(repositoryServiceFactory);
+        assertNotNull(repMgr);
+
+    }
+
+    public void testGetCatalogServiceFromFactory() {
+        Catalog cat = GenericFileManagerObjectFactory
+                .getCatalogServiceFromFactory(catalogServiceFactory);
+        assertNotNull(cat);
+
+    }
+
+    public void testGetValidationLayerFromFactory() {
+        ValidationLayer valLayer = GenericFileManagerObjectFactory
+                .getValidationLayerFromFactory(validationServiceFactory);
+        assertNotNull(valLayer);
+
+    }
+
+    public void testGetVersionerFromClassName() {
+        Versioner versioner = GenericFileManagerObjectFactory
+                .getVersionerFromClassName(versionerClass);
+        assertNotNull(versioner);
+
+    }
+
+    public void testGetExtractorFromClassName() {
+        FilemgrMetExtractor extractor = GenericFileManagerObjectFactory
+                .getExtractorFromClassName(extractorClass);
+        assertNotNull(extractor);
+
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/util/TestXmlRpcStructFactory.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/util/TestXmlRpcStructFactory.java
new file mode 100644
index 0000000..bc34989
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/util/TestXmlRpcStructFactory.java
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.util;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.datatransfer.InPlaceDataTransferFactory;
+import org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory;
+import org.apache.oodt.cas.filemgr.structs.ExtractorSpec;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.structs.type.TypeHandler;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManager;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.Properties;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link XmlRpcStructFactory}.
+ *
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public class TestXmlRpcStructFactory extends TestCase {
+
+    final int FILEMGR_PORT = 9999;
+    XmlRpcFileManager fmServer;
+    private Properties initialProperties = new Properties(
+      System.getProperties());
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        startXmlRpcFileManager();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        fmServer.shutdown();
+
+        // Return system properties to their initial state from before this test
+        // was run.
+        System.setProperties(initialProperties);
+    }
+
+    public void testProductTypeMethods() throws RepositoryManagerException, MalformedURLException, ConnectionException {
+        XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(new URL("http://localhost:" + FILEMGR_PORT));
+        fmClient.setDataTransfer(new LocalDataTransferFactory().createDataTransfer());
+        
+        ProductType productType = fmClient.getProductTypeByName("GenericFile");
+        Hashtable<String, Object> productTypeHash = XmlRpcStructFactory.getXmlRpcProductType(productType);
+        ProductType convBackProdType = XmlRpcStructFactory.getProductTypeFromXmlRpc(productTypeHash);
+        
+        assertTrue(productType.getProductTypeId().equals(convBackProdType.getProductTypeId()));
+        assertTrue(productType.getName().equals(convBackProdType.getName()));
+        assertTrue(productType.getDescription().equals(convBackProdType.getDescription()));
+        assertTrue(productType.getVersioner().equals(convBackProdType.getVersioner()));
+        assertTrue(productType.getProductRepositoryPath().equals(convBackProdType.getProductRepositoryPath()));
+        for (int i = 0; i < productType.getExtractors().size(); i++) {
+            ExtractorSpec spec1 = productType.getExtractors().get(i);
+            ExtractorSpec spec2 = convBackProdType.getExtractors().get(i);
+            assertTrue(spec1.getClassName().equals(spec2.getClassName()));
+            assertTrue(spec1.getConfiguration().equals(spec2.getConfiguration()));
+        }
+        for (int i = 0; i < productType.getHandlers().size(); i++) {
+            TypeHandler handler1 = productType.getHandlers().get(i);
+            TypeHandler handler2 = convBackProdType.getHandlers().get(i);
+            assertTrue(handler1.getClass().getCanonicalName().equals(handler2.getClass().getCanonicalName()));
+            assertTrue(handler1.getElementName().equals(handler2.getElementName()));
+        }
+    }
+
+    public void testProductMethods() throws Exception {
+       XmlRpcFileManagerClient fmClient = new XmlRpcFileManagerClient(new URL("http://localhost:" + FILEMGR_PORT));
+       fmClient.setDataTransfer(new InPlaceDataTransferFactory().createDataTransfer());
+
+       Product product = new Product();
+       Product roundTripProduct = XmlRpcStructFactory.getProductFromXmlRpc(
+             XmlRpcStructFactory.getXmlRpcProduct(product));
+       assertEquals(product, roundTripProduct);
+
+       product = new Product();
+       product.setProductId("TestId");
+       product.setProductName("TestName");
+       product.setProductReferences(Lists.newArrayList(new Reference("file:///original/path", null, 2)));
+       product.setProductStructure("Flat");
+       product.setProductType(fmClient.getProductTypeByName("GenericFile"));
+       product.setRootRef(new Reference("file:///original/root", "file:///datastore/root", 3));
+       roundTripProduct = XmlRpcStructFactory.getProductFromXmlRpc(XmlRpcStructFactory.getXmlRpcProduct(product));
+       assertEquals(product, roundTripProduct);
+       Metadata m = new Metadata();
+       m.addMetadata("TestKey", "TestValue");
+       
+       roundTripProduct = fmClient.getProductById(
+             fmClient.ingestProduct(product, m, true));
+       assertEquals(product, roundTripProduct);
+    }
+
+    private void assertEquals(Product product1, Product product2) {
+       if (product1 == null) {
+          assertNull(product2);
+          return;
+       }
+       assertEquals(product1.getProductId(), product2.getProductId());       
+       assertEquals(product1.getProductName(), product2.getProductName());
+       assertEquals(product1.getProductStructure(), product2.getProductStructure());
+       assertEquals(product1.getTransferStatus(), product2.getTransferStatus());
+       if (product1.getProductReferences() == null) {
+          assertEquals(product1.getProductReferences(), product2.getProductReferences());
+       } else {
+          for (int i = 0; i < product1.getProductReferences().size(); i++) {
+             assertEquals(product1.getProductReferences().get(i),
+                   product2.getProductReferences().get(i));
+          }
+       }
+       if (product1.getProductType() == null) {
+          assertEquals(product1.getProductType(), product2.getProductType());
+       } else {
+          assertEquals(product1.getProductType().getDescription(), product2.getProductType().getDescription());          
+          assertEquals(product1.getProductType().getName(), product2.getProductType().getName());          
+          assertEquals(product1.getProductType().getProductRepositoryPath(), product2.getProductType().getProductRepositoryPath());          
+          assertEquals(product1.getProductType().getProductTypeId(), product2.getProductType().getProductTypeId());          
+          assertEquals(product1.getProductType().getVersioner(), product2.getProductType().getVersioner());          
+       }
+       assertEquals(product1.getRootRef(), product2.getRootRef());
+    }
+
+    private void assertEquals(Reference ref1, Reference ref2) {
+       if (ref1 == null) {
+          assertNull(ref2);
+          return;
+       }
+       assertNotNull(ref2.getDataStoreReference());
+       assertEquals(ref1.getFileSize(), ref2.getFileSize());
+       assertEquals(ref1.getOrigReference(), ref2.getOrigReference());
+       assertEquals(ref1.getMimeType(), ref2.getMimeType());
+    }
+
+    private void startXmlRpcFileManager() {
+
+        Properties properties = new Properties(System.getProperties());
+
+        // first make sure to load properties for the file manager
+        // and make sure to load logging properties as well
+
+        // set the log levels
+        URL loggingPropertiesUrl = this.getClass().getResource(
+            "/test.logging.properties");
+        properties.setProperty("java.util.logging.config.file",
+            new File(loggingPropertiesUrl.getFile()).getAbsolutePath());
+
+        // first load the example configuration
+        try {
+            URL filemgrPropertiesUrl = this.getClass().getResource(
+                "/filemgr.properties");
+            properties.load(new FileInputStream(
+                filemgrPropertiesUrl.getFile()));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        properties.setProperty("filemgr.catalog.factory",
+                "org.apache.oodt.cas.filemgr.catalog.MockCatalogFactory");
+
+        // now override the repo mgr policy
+        URL structFactoryUrl = this.getClass().getResource(
+            "/xmlrpc-struct-factory");
+        try {
+            properties.setProperty(
+              "org.apache.oodt.cas.filemgr.repositorymgr.dirs",
+              "file://" + new File(structFactoryUrl.getFile())
+                  .getCanonicalPath());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // now override the val layer ones
+        properties.setProperty("org.apache.oodt.cas.filemgr.validation.dirs",
+            "file://" + new File(structFactoryUrl.getFile()).getAbsolutePath());
+
+        // set up mime repo path
+        URL mimeTypesUrl = this.getClass().getResource("/mime-types.xml");
+        properties.setProperty(
+            "org.apache.oodt.cas.filemgr.mime.type.repository",
+            new File(mimeTypesUrl.getFile()).getAbsolutePath());
+
+        // Use the local properties object to set system properties.
+        System.setProperties(properties);
+
+        try {
+            fmServer = new XmlRpcFileManager(FILEMGR_PORT);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+    
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/util/TestXmlStructFactory.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/util/TestXmlStructFactory.java
new file mode 100644
index 0000000..201d623
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/util/TestXmlStructFactory.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.util;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.commons.exec.EnvUtilities;
+
+//JDK imports
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test Cases for the Xml Struct Factory.
+ * </p>.
+ */
+public class TestXmlStructFactory extends TestCase {
+
+    private static final String origRepoPath = "[HOME]/some/path";
+
+    private static final String HOME = EnvUtilities.getEnv("HOME");
+
+    private static final String expectedRepoPath = HOME + "/some/path";
+
+    public void testEnvVarReplace() {
+
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        Document document = null;
+
+        try {
+            DocumentBuilder builder = factory.newDocumentBuilder();
+            document = builder.newDocument();
+
+            Element productTypeElem = (Element) document.createElement("type");
+            productTypeElem.setAttribute("id", "blah");
+            productTypeElem.setAttribute("name", "foo");
+
+            Element repoPathElem = (Element) document
+                    .createElement("repository");
+            repoPathElem.setAttribute("path", origRepoPath);
+            productTypeElem.appendChild(repoPathElem);
+            
+            Element versionerClassElem = (Element)
+               document.createElement("versioner");
+            versionerClassElem.setAttribute("class", "foo.bar");
+            productTypeElem.appendChild(versionerClassElem);
+            
+            Element descElem = (Element)
+               document.createElement("description");
+            descElem.appendChild(document.createTextNode("foo"));
+            productTypeElem.appendChild(descElem);
+
+            ProductType type = XmlStructFactory.getProductType(productTypeElem);
+            assertEquals("The value of the repo path: ["
+                    + type.getProductRepositoryPath()
+                    + "] was not the expected value of: [" + expectedRepoPath
+                    + "]", type.getProductRepositoryPath(), expectedRepoPath);
+
+        } catch (ParserConfigurationException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/validation/TestXMLValidationLayer.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/validation/TestXMLValidationLayer.java
new file mode 100644
index 0000000..096dc35
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/validation/TestXMLValidationLayer.java
@@ -0,0 +1,283 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.validation;
+
+//OODT imports
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import static org.apache.oodt.cas.filemgr.metadata.CoreMetKeys.*;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+
+//JDK imports
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Unit tests for the XMLValidationLayer.
+ * </p>
+ * 
+ */
+public class TestXMLValidationLayer extends TestCase {
+
+    /* our test URIs containing elements.xml and product-type-element-map.xml */
+    private List testDirUris = new Vector();
+
+    /* our XML Validation layer for testing */
+    private XMLValidationLayer validationLayer = null;
+
+    private static final String expectedProductIdDefinition = "A Product's unique identifier within the CAS namespace.";
+
+    private static final String expectedProductNameDefinition = "\n          A Product's name within the CAS namespace.\n        ";
+
+    private static final String expectedProductReceivedTime = "The ISO 8601 formatted time that the Product was received.";
+
+    private static final String expectedFilenameDefinition = "The names of the files that represent this product.";
+
+    private static final String CAS_NS = "CAS";
+
+    public TestXMLValidationLayer() {
+    }
+
+    /**
+     * @since OODT-195
+     */
+    public void testModifyElement() {
+      Element elem = new Element();
+      String elemName = "TestFilename";
+      elem.setElementName(elemName);
+      elem.setElementId("urn:oodt:Filename");
+      try {
+        validationLayer.modifyElement(elem);
+      } catch (Exception e) {
+        fail(e.getMessage());
+      }
+  
+      ProductType type = new ProductType();
+      type.setProductTypeId("urn:oodt:GenericFile");
+      List<Element> retrievedElems = null;
+      try {
+        retrievedElems = validationLayer.getElements(type);
+      } catch (Exception e) {
+        fail(e.getMessage());
+      }
+      assertNotNull(retrievedElems);
+      boolean found = false;
+      for (Element e : retrievedElems) {
+        if (e.getElementName().equals(elemName)) {
+          found = true;
+        }
+      }
+      assertTrue(
+          "Unable to find updated element: ["+elemName+"]: Set contains : ["
+              + retrievedElems + "]", found);
+  }    
+
+    /**
+     * @since OODT-220
+     * 
+     */
+    public void testReadProperDescriptionTrimImplicitTrue() {
+        Element elem = null;
+        try {
+            elem = validationLayer.getElementByName(CAS_NS + "." + PRODUCT_ID);
+        } catch (ValidationLayerException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(elem);
+        assertNotNull(elem.getDescription());
+        assertEquals(expectedProductIdDefinition, elem.getDescription());
+    }
+
+    /**
+     * @since OODT-220
+     * 
+     */
+    public void testReadBadFormattedDescriptionTrimImplicitTrue() {
+        Element elem = null;
+        try {
+            elem = validationLayer.getElementByName(FILENAME);
+        } catch (ValidationLayerException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(elem);
+        assertNotNull(elem.getDescription());
+        assertEquals(expectedFilenameDefinition, elem.getDescription());
+    }
+
+    /**
+     * @since OODT-220
+     * 
+     */
+    public void testReadDescriptionTrimExplicitFalse() {
+        Element elem = null;
+        try {
+            elem = validationLayer
+                    .getElementByName(CAS_NS + "." + PRODUCT_NAME);
+        } catch (ValidationLayerException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(elem);
+        assertNotNull(elem.getDescription());
+        assertEquals(expectedProductNameDefinition, elem.getDescription());
+
+    }
+
+    /**
+     * @since OODT-220
+     * 
+     */
+    public void testReadDescriptionTrimExplicitTrue() {
+        Element elem = null;
+        try {
+            elem = validationLayer.getElementByName(CAS_NS + "."
+                    + PRODUCT_RECEVIED_TIME);
+        } catch (ValidationLayerException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(elem);
+        assertNotNull(elem.getDescription());
+        assertEquals(expectedProductReceivedTime, elem.getDescription());
+
+    }
+
+    public void testGetElements() {
+        List elementList = null;
+
+        try {
+            elementList = validationLayer.getElements();
+        } catch (ValidationLayerException e) {
+            fail(e.getMessage());
+        }
+
+        // should be 4 elements
+        assertNotNull(elementList);
+        assertEquals("There aren't exactly 4 elements in the test samples!", 4,
+                elementList.size());
+
+        // try and find one of them
+        // find produuct received time
+        boolean hasReceivedTime = false;
+        for (Iterator i = elementList.iterator(); i.hasNext();) {
+            Element element = (Element) i.next();
+            if (element.getElementName().equals("CAS.ProductReceivedTime")) {
+                hasReceivedTime = true;
+            }
+        }
+
+        if (!hasReceivedTime) {
+            fail("Didn't load the CAS.ProductReceivedTime element!");
+        }
+    }
+
+    public void testGetElementsForProductType() {
+        List elementList = null;
+        ProductType type = new ProductType();
+
+        type.setProductTypeId("urn:oodt:GenericFile");
+        type.setName("Generic File");
+
+        try {
+            elementList = validationLayer.getElements(type);
+        } catch (ValidationLayerException e) {
+            fail(e.getMessage());
+        }
+
+        // should be exactly 4 elements
+        assertNotNull(elementList);
+        assertEquals(
+                "There aren't exactly 4 elements for the product type [Generic File]!",
+                4, elementList.size());
+    }
+
+
+
+
+    /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#setUp()
+   */
+  @Override
+  protected void setUp() throws Exception {
+    try {
+      File tempDir = File.createTempFile("ignore", "txt").getParentFile();
+      // copy the val layer policy into the temp dir
+      URL url = this.getClass().getResource("/vallayer");
+      for (File f : new File(url.getFile())
+          .listFiles(new FileFilter() {
+
+            public boolean accept(File pathname) {
+              return pathname.isFile();
+            }
+          })) {
+        FileUtils.copyFileToDirectory(f, tempDir);
+      }
+
+      testDirUris.add(tempDir.toURI().toString());
+      validationLayer = new XMLValidationLayer(testDirUris);
+
+    } catch (IOException e) {
+      fail(e.getMessage());
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#tearDown()
+   */
+  @Override
+  protected void tearDown() throws Exception {
+    deleteAllFiles(new File(new URI((String) testDirUris.get(0)))
+        .getAbsolutePath());
+    testDirUris.clear();
+  }
+
+  private void deleteAllFiles(String startDir) {
+    File startDirFile = new File(startDir);
+    File[] delFiles = startDirFile.listFiles();
+
+    if (delFiles != null && delFiles.length > 0) {
+      for (int i = 0; i < delFiles.length; i++) {
+        delFiles[i].delete();
+      }
+    }
+
+    startDirFile.delete();
+
+  }    
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestAcquisitionDateVersioner.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestAcquisitionDateVersioner.java
new file mode 100644
index 0000000..39d9bbe
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestAcquisitionDateVersioner.java
@@ -0,0 +1,135 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//JDK imports
+import java.io.File;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Properties;
+import java.util.TimeZone;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test harness for the {@link AcquisitionDateVersioner}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestAcquisitionDateVersioner extends TestCase {
+
+  private Properties initialProperties = new Properties(System.getProperties());
+
+  public void setUp() throws Exception {
+    Properties properties = new Properties(System.getProperties());
+    URL url = this.getClass().getResource("/mime-types.xml");
+    properties.setProperty("org.apache.oodt.cas.filemgr.mime.type.repository",
+        new File(url.getFile()).getAbsolutePath());
+    System.setProperties(properties);
+  }
+
+  public void tearDown() throws Exception {
+    System.setProperties(initialProperties);
+  }
+
+  public void testVersionerWithNoStartDateTimeAndNoAcqDate() {
+    AcquisitionDateVersioner versioner = new AcquisitionDateVersioner();
+    Product p = Product.getDefaultFlatProduct("test", "urn:oodt:GenericFile");
+    p.getProductType().setProductRepositoryPath("file:///home/files");
+    Reference r = new Reference("file:///tmp/dir1/file1.txt", null, 4L);
+    p.getProductReferences().add(r);
+    Metadata met = new Metadata();
+    met.addMetadata(CoreMetKeys.FILENAME, "file1.txt");
+    SimpleDateFormat acqDateFormatter = new SimpleDateFormat(
+        AcquisitionDateVersioner.ACQ_DATE_FORMAT);
+    acqDateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
+    String expectedDateTimeStr = acqDateFormatter.format(new Date());
+    String expectedPath = "file:/home/files/" + expectedDateTimeStr
+        + "/file1.txt";
+    try {
+      versioner.createDataStoreReferences(p, met);
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+
+    assertNotNull(p.getProductReferences());
+    assertEquals(1, p.getProductReferences().size());
+    assertEquals(expectedPath, p.getProductReferences().get(0)
+        .getDataStoreReference());
+  }
+
+  public void testVersionerWithNoStartDateTimeAndAcqDate() {
+    AcquisitionDateVersioner versioner = new AcquisitionDateVersioner();
+    Product p = Product.getDefaultFlatProduct("test", "urn:oodt:GenericFile");
+    p.getProductType().setProductRepositoryPath("file:///home/files");
+    Reference r = new Reference("file:///tmp/dir1/file1.txt", null, 4L);
+    p.getProductReferences().add(r);
+    Metadata met = new Metadata();
+    met.addMetadata(CoreMetKeys.FILENAME, "file1.txt");
+    met.addMetadata("AcquisitionDate", "090910");
+    String expectedPath = "file:/home/files/"
+        + met.getMetadata("AcquisitionDate") + "/file1.txt";
+    try {
+      versioner.createDataStoreReferences(p, met);
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+
+    assertNotNull(p.getProductReferences());
+    assertEquals(1, p.getProductReferences().size());
+    assertEquals(expectedPath, p.getProductReferences().get(0)
+        .getDataStoreReference());
+  }
+
+  public void testVersionerWithStartDateTime() {
+    AcquisitionDateVersioner versioner = new AcquisitionDateVersioner();
+    Product p = Product.getDefaultFlatProduct("test", "urn:oodt:GenericFile");
+    p.getProductType().setProductRepositoryPath("file:///home/files");
+    Reference r = new Reference("file:///tmp/dir1/file1.txt", null, 4L);
+    p.getProductReferences().add(r);
+    Metadata met = new Metadata();
+    met.addMetadata(CoreMetKeys.FILENAME, "file1.txt");
+    met.addMetadata("StartDateTime", "2006-09-10T00:00:01.000Z");
+    String expectedPath = "file:/home/files/060910/file1.txt";
+    try {
+      versioner.createDataStoreReferences(p, met);
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+
+    assertNotNull(p.getProductReferences());
+    assertEquals(1, p.getProductReferences().size());
+    assertEquals(expectedPath, p.getProductReferences().get(0)
+        .getDataStoreReference());
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestBasicVersioner.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestBasicVersioner.java
new file mode 100644
index 0000000..c1f7e95
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestBasicVersioner.java
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//JDK imports
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Unit tests for the BasicVersioner class.
+ * </p>
+ * 
+ */
+public class TestBasicVersioner extends TestCase {
+
+	/* the BasicVersioner we're going to test out */
+	private BasicVersioner basicVersioner = new BasicVersioner();
+
+  private Properties initialProperties = new Properties(System.getProperties());
+
+  public void setUp() throws Exception {
+    Properties properties = new Properties(System.getProperties());
+    URL url = this.getClass().getResource("/mime-types.xml");
+    properties.setProperty("org.apache.oodt.cas.filemgr.mime.type.repository",
+        new File(url.getFile()).getAbsolutePath());
+    System.setProperties(properties);
+  }
+
+  public void tearDown() throws Exception {
+    System.setProperties(initialProperties);
+  }
+
+	public void testVersionFlat() {
+		Product p = new Product();
+		p.setProductName("test_product");
+		p.setProductStructure(Product.STRUCTURE_FLAT);
+		ProductType type = new ProductType();
+		type.setProductRepositoryPath("file:///foo/bar");
+		p.setProductType(type);
+
+		List refs = new Vector();
+		try {
+      URL url = this.getClass().getResource("/test.txt");
+      String refname = new File(url.getFile()).toURL().toExternalForm().toString();
+			refs.add(refname);
+		} catch (MalformedURLException e) {
+			fail(e.getMessage());
+		}
+		
+		VersioningUtils.addRefsFromUris(p, refs);
+
+		try {
+			basicVersioner.createDataStoreReferences(p, null);
+		} catch (VersioningException e) {
+			fail(e.getMessage());
+		}
+
+		String generatedRef = ((Reference) p.getProductReferences().get(0))
+				.getDataStoreReference();
+		assertNotNull(generatedRef);
+
+		assertEquals("Versioned refs not equal: ref=[" + generatedRef + "]",
+				"file:/foo/bar/test_product/test.txt", generatedRef);
+
+	}
+
+  public void testVersionHierarchical() {
+    String expected = "file:/archive/testdir/";
+    Product p = Product
+        .getDefaultFlatProduct("testdir", "urn:oodt:GenericFile");
+    p.setProductStructure(Product.STRUCTURE_HIERARCHICAL);
+    p.getProductType().setProductRepositoryPath("file:///archive");
+
+    p.getProductReferences().add(
+        new Reference("file:///tmp/somedir/", null, 4L));
+    p.getProductReferences().add(
+        new Reference("file:///tmp/somedir/file.txt", null, 4096L));
+
+    BasicVersioner versioner = new BasicVersioner();
+    try {
+      versioner.createDataStoreReferences(p, new Metadata());
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(p.getProductReferences());
+    assertEquals(2, p.getProductReferences().size());
+    assertEquals(expected, p.getProductReferences().get(0)
+        .getDataStoreReference());
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestConfigurableMetadataBasedFileVersioner.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestConfigurableMetadataBasedFileVersioner.java
new file mode 100644
index 0000000..74bd1eb
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestConfigurableMetadataBasedFileVersioner.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.filemgr.versioning;
+
+// JUnit static imports
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+// JDK imports
+import java.util.Properties;
+
+// OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+// JUnit imports
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+// Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * Test class for {@link ConfigurableMetadataBasedFileVersioner}.
+ *
+ * @author bfoster@apache.org (Brian Foster)
+ */
+@RunWith(JUnit4.class)
+public class TestConfigurableMetadataBasedFileVersioner {
+
+  @Rule public ExpectedException expectedException = ExpectedException.none();
+
+  private Properties properties;
+  private ConfigurableMetadataBasedFileVersioner versioner;
+  private Metadata metadata;
+  private Product product;
+
+  @Before
+  public void setUp() {
+    properties = new Properties();
+    properties.setProperty("org.apache.oodt.cas.filemgr.versioning.configuration.test_type",
+        "/[Year]/[Month]/[Day]/[Filename]");
+    versioner = new ConfigurableMetadataBasedFileVersioner(properties);
+    metadata = new Metadata();
+    metadata.addMetadata("Year", "2013");
+    metadata.addMetadata("Month", "03");
+    metadata.addMetadata("Day", "23");
+    metadata.addMetadata("Filename", "test.dat");
+    product = new Product();
+    product.setProductStructure(Product.STRUCTURE_FLAT);
+    ProductType pt = new ProductType();
+    pt.setProductRepositoryPath("file:/base/path");
+    pt.setName("TEST_TYPE");
+    product.setProductType(pt);
+    Reference ref = new Reference();
+    ref.setOrigReference("/path/to/file");
+    product.setProductReferences(Lists.newArrayList(ref));
+  }
+
+  @Test
+  public void testVersioningForProductType() throws VersioningException {
+    versioner.createDataStoreReferences(product, metadata);
+
+    assertThat(product.getProductReferences().size(), is(1));
+    assertThat(product.getProductReferences().get(0).getDataStoreReference(),
+        is("file:/base/path/2013/03/23/test.dat"));
+  }
+
+  @Test
+  public void testVersioningForProductTypeNotDefined() throws VersioningException {
+    ProductType pt = new ProductType();
+    pt.setProductRepositoryPath("file:/base/path");
+    pt.setName("TEST_TYPE2");
+    product.setProductType(pt);
+
+    expectedException.expect(VersioningException.class);
+    versioner.createDataStoreReferences(product, metadata);
+  }
+
+  @Test
+  public void testVersioningForAllProductTypesDoesntOverrideSpecific() throws VersioningException {
+    properties.setProperty("org.apache.oodt.cas.filemgr.versioning.configuration.all_product_types",
+        "/[Year]/[Month]/[Filename]");
+
+    versioner.createDataStoreReferences(product, metadata);
+    
+    assertThat(product.getProductReferences().size(), is(1));
+    assertThat(product.getProductReferences().get(0).getDataStoreReference(),
+        is("file:/base/path/2013/03/23/test.dat"));
+  }
+
+  @Test
+  public void testVersioningForAllProductTypes() throws VersioningException {
+    properties.setProperty("org.apache.oodt.cas.filemgr.versioning.configuration.all_product_types",
+        "/[Year]/[Month]/[Filename]");
+
+    ProductType pt = new ProductType();
+    pt.setProductRepositoryPath("file:/base/path");
+    pt.setName("TEST_TYPE2");
+    product.setProductType(pt);
+
+    versioner.createDataStoreReferences(product, metadata);
+
+    assertThat(product.getProductReferences().size(), is(1));
+    assertThat(product.getProductReferences().get(0).getDataStoreReference(),
+        is("file:/base/path/2013/03/test.dat"));
+  }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestDateTimeVersioner.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestDateTimeVersioner.java
new file mode 100644
index 0000000..15561a1
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestDateTimeVersioner.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+// JDK imports
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.commons.util.DateConvert;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Unit tests for the DateTimeVersioner class.
+ * </p>
+ * 
+ */
+public class TestDateTimeVersioner extends TestCase {
+
+	/* the versioner that we're going to test out */
+	private DateTimeVersioner dateTimeVersioner = new DateTimeVersioner();
+
+  private Properties initialProperties = new Properties(System.getProperties());
+
+  public void setUp() throws Exception {
+    Properties properties = new Properties(System.getProperties());
+    URL url = this.getClass().getResource("/mime-types.xml");
+    properties.setProperty("org.apache.oodt.cas.filemgr.mime.type.repository",
+        new File(url.getFile()).getAbsolutePath());
+    System.setProperties(properties);
+  }
+
+  public void tearDown() throws Exception {
+    System.setProperties(initialProperties);
+  }
+
+	public void testFlat() {
+		Metadata metadata = new Metadata();
+		Product product = new Product();
+		ProductType type = new ProductType();
+
+		type.setProductRepositoryPath("file:///foo/bar");
+		product.setProductName("test_product");
+		product.setProductStructure(Product.STRUCTURE_FLAT);
+		product.setProductType(type);
+
+	    Date prodDateTime = new Date();
+		String prodDateTimeStr = DateConvert.isoFormat(prodDateTime);
+		metadata.addMetadata("CAS.ProductReceivedTime", prodDateTimeStr);
+		
+
+        SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyyddMM.HHmmss");
+        String prodDateTimeNonIso = dateFormatter.format(prodDateTime);
+
+		List refs = new Vector();
+		try {
+      URL url = this.getClass().getResource("/test.txt");
+      String refname = new File(url.getFile()).toURL().toExternalForm().toString();
+			refs.add(refname);
+		} catch (MalformedURLException e) {
+			fail(e.getMessage());
+		}
+		
+		VersioningUtils.addRefsFromUris(product, refs);
+
+		try {
+			dateTimeVersioner.createDataStoreReferences(product, metadata);
+		} catch (VersioningException e) {
+			fail(e.getMessage());
+		}
+
+		String generatedRef = ((Reference) product.getProductReferences()
+				.get(0)).getDataStoreReference();
+		assertNotNull(generatedRef);
+		assertEquals(
+				"Generated ref does not equal expected ref: generatedRef=["
+						+ generatedRef + "], expected=[file:/foo/bar/test_product" +
+								"/test.txt."+prodDateTimeNonIso+"]", 
+								"file:/foo/bar/test_product/test.txt."
+						+ prodDateTimeNonIso, generatedRef);
+
+	}
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestDirectoryBasedProductVersioner.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestDirectoryBasedProductVersioner.java
new file mode 100644
index 0000000..1bfe520
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestDirectoryBasedProductVersioner.java
@@ -0,0 +1,85 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//JDK imports
+import java.io.File;
+
+import java.net.URL;
+import java.util.Properties;
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test harness for the {@link DirectoryProductVersioner}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestDirectoryBasedProductVersioner extends TestCase {
+
+  private Properties initialProperties = new Properties(System.getProperties());
+
+  public void setUp() throws Exception {
+    Properties properties = new Properties(System.getProperties());
+    URL url = this.getClass().getResource("/mime-types.xml");
+    properties.setProperty("org.apache.oodt.cas.filemgr.mime.type.repository",
+        new File(url.getFile()).getAbsolutePath());
+    System.setProperties(properties);
+  }
+
+  public void tearDown() throws Exception {
+    System.setProperties(initialProperties);
+  }
+
+  public void testVersioner() {
+    DirectoryProductVersioner versioner = new DirectoryProductVersioner();
+    Product p = Product.getDefaultFlatProduct("test", "urn:oodt:GenericFile");
+    p.setProductStructure(Product.STRUCTURE_HIERARCHICAL);
+    p.getProductType().setProductRepositoryPath("file:///home/files");
+    Reference r = new Reference("file:///tmp/dir1", null, 4L);
+    Reference r2 = new Reference("file:///tmp/dir1/file1.txt", null, 20L);
+    p.getProductReferences().add(r);
+    p.getProductReferences().add(r2);
+    Metadata met = new Metadata();
+    met.addMetadata(CoreMetKeys.FILENAME, "dir1");
+    try {
+      versioner.createDataStoreReferences(p, met);
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+
+    assertNotNull(p.getProductReferences());
+    assertEquals(2, p.getProductReferences().size());
+    assertEquals("file:/home/files/dir1/", p.getProductReferences().get(0)
+        .getDataStoreReference());
+    assertEquals("file:/home/files/dir1/file1.txt", p.getProductReferences()
+        .get(1).getDataStoreReference());
+
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestInPlaceVersioner.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestInPlaceVersioner.java
new file mode 100644
index 0000000..53f88fe
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestInPlaceVersioner.java
@@ -0,0 +1,79 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//Junit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * Test suite for the {@link InPlaceVersioner}.
+ * 
+ * @author davoodi
+ * @author mattmann
+ * 
+ */
+public class TestInPlaceVersioner extends TestCase {
+
+  /**
+   * @since OODT-108
+   */
+  public void testVersionerFlat() {
+    Product p = Product.getDefaultFlatProduct("test", "urn:oodt:GenericFile");
+    Reference r = new Reference("file:///tmp/test.txt", null, 0L);
+    p.getProductReferences().add(r);
+    InPlaceVersioner versioner = new InPlaceVersioner();
+    Metadata met = new Metadata();
+    try {
+      versioner.createDataStoreReferences(p, met);
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+    assertTrue(r.getDataStoreReference().equals(r.getOrigReference()));
+  }
+
+  /**
+   * @since OODT-108
+   */
+  public void testVersionerHierarchical() {
+    Product p = Product.getDefaultFlatProduct("test", "urn:oodt:GenericFile");
+    p.setProductStructure(Product.STRUCTURE_HIERARCHICAL);
+    Reference r = new Reference("file:///tmp", null, 0L);
+    Reference r2 = new Reference("file:///tmp/file1.txt", null, 4096L);
+    Reference r3 = new Reference("file:///tmp/file2.txt", null, 4096L);
+    p.getProductReferences().add(r);
+    p.getProductReferences().add(r2);
+    p.getProductReferences().add(r3);
+    InPlaceVersioner versioner = new InPlaceVersioner();
+    Metadata met = new Metadata();
+    try {
+      versioner.createDataStoreReferences(p, met);
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    for (Reference ref : p.getProductReferences()) {
+      assertEquals(ref.getDataStoreReference(), ref.getOrigReference());
+    }
+  }
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestMetadataBasedFileVersioner.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestMetadataBasedFileVersioner.java
new file mode 100644
index 0000000..b158236
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestMetadataBasedFileVersioner.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//JDK imports
+import java.io.File;
+
+import java.net.URL;
+import java.util.Properties;
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Test Case for the MetadataBasedFileVersioner.
+ * </p>.
+ */
+public class TestMetadataBasedFileVersioner extends TestCase {
+
+	private String productTypePath = "file:/foo/bar";
+
+  private Properties initialProperties = new Properties(System.getProperties());
+
+  public void setUp() throws Exception {
+    Properties properties = new Properties(System.getProperties());
+    URL url = this.getClass().getResource("/mime-types.xml");
+    properties.setProperty("org.apache.oodt.cas.filemgr.mime.type.repository",
+        new File(url.getFile()).getAbsolutePath());
+    System.setProperties(properties);
+  }
+
+  public void tearDown() throws Exception {
+    System.setProperties(initialProperties);
+  }
+
+	public void testVersionerNoStatic() {
+		String filePathSpec = "/[ProductType]/[ProductionDate]/[Filename]";
+		Product product = new Product();
+		product.setProductStructure(Product.STRUCTURE_FLAT);
+		ProductType type = new ProductType();
+		type.setProductRepositoryPath(productTypePath);
+		product.setProductType(type);
+
+		Metadata metadata = new Metadata();
+		metadata.addMetadata("ProductType", "FooFile");
+		metadata.addMetadata("ProductionDate", "060804");
+		metadata.addMetadata("Filename", "foo.txt");
+
+		Reference r = new Reference();
+		product.getProductReferences().add(r);
+
+		MetadataBasedFileVersioner versioner = new MetadataBasedFileVersioner(
+				filePathSpec);
+		try {
+			versioner.createDataStoreReferences(product, metadata);
+		} catch (VersioningException e) {
+			fail(e.getMessage());
+		}
+
+		String expected = "file:/foo/bar/FooFile/060804/foo.txt";
+		assertEquals("The reference: [" + r.getDataStoreReference()
+				+ "] is not equal to: [" + expected + "]", expected, r
+				.getDataStoreReference());
+	}
+
+	public void testVersionerWithStatic() {
+		String filePathSpec = "/[ProductType]/some/other/path[ProductionDate]/[Filename]";
+		Product product = new Product();
+		product.setProductStructure(Product.STRUCTURE_FLAT);
+		ProductType type = new ProductType();
+		type.setProductRepositoryPath(productTypePath);
+		product.setProductType(type);
+
+		Metadata metadata = new Metadata();
+		metadata.addMetadata("ProductType", "FooFile");
+		metadata.addMetadata("ProductionDate", "060804");
+		metadata.addMetadata("Filename", "foo.txt");
+
+		Reference r = new Reference();
+		product.getProductReferences().add(r);
+
+		MetadataBasedFileVersioner versioner = new MetadataBasedFileVersioner(
+				filePathSpec);
+		try {
+			versioner.createDataStoreReferences(product, metadata);
+		} catch (VersioningException e) {
+			fail(e.getMessage());
+		}
+
+		String expected = "file:/foo/bar/FooFile/some/other/path060804/foo.txt";
+		assertEquals("The reference: [" + r.getDataStoreReference()
+				+ "] is not equal to: [" + expected + "]", expected, r
+				.getDataStoreReference());
+	}
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestProductTypeMetVersioner.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestProductTypeMetVersioner.java
new file mode 100644
index 0000000..c201a93
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestProductTypeMetVersioner.java
@@ -0,0 +1,65 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test harness for ProductTypeMetVersioner.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestProductTypeMetVersioner extends TestCase {
+
+  private static final String expected = "file:/data/archive/130622/somefile.txt";
+
+  public void testVersion() {
+    Metadata met = new Metadata();
+    met.addMetadata("Filename", "somefile.txt");
+    met.addMetadata("AcquisitionDate", "130622");
+    Product prod = Product.getDefaultFlatProduct("foo", "urn:sometype:foo");
+    prod.getProductType().setProductRepositoryPath("file:///data/archive");
+    prod.getProductType().getTypeMetadata()
+        .addMetadata("filePathSpec", "/[AcquisitionDate]/[Filename]");
+    prod.getProductReferences().add(
+        new Reference("file:///data/staging/somefile.txt", null, 4L));
+    ProductTypeMetVersioner versioner = new ProductTypeMetVersioner();
+    try {
+      versioner.createDataStoreReferences(prod, met);
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(prod);
+    assertNotNull(prod.getProductReferences());
+    assertEquals(1, prod.getProductReferences().size());
+    assertEquals(expected, prod.getProductReferences().get(0)
+        .getDataStoreReference());
+
+  }
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestSingleFileBasicVersioner.java b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestSingleFileBasicVersioner.java
new file mode 100644
index 0000000..a2b47d2
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/java/org/apache/oodt/cas/filemgr/versioning/TestSingleFileBasicVersioner.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.filemgr.versioning;
+
+//JDK imports
+import java.io.File;
+
+import java.net.URL;
+import java.util.Properties;
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.VersioningException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>Test Case for the Single File Basic Versioner.</p>
+ *
+ */
+public class TestSingleFileBasicVersioner extends TestCase {
+
+	private String origFileRef = "file:/foo/bar/testfile.txt";
+	
+	private String expectedDestFileRef = "file:/foo/bar2/testfile.txt";
+	
+	private String productRepoPath = "file:/foo/bar2/";
+	
+  private Properties initialProperties = new Properties(System.getProperties());
+
+  public void setUp() throws Exception {
+    Properties properties = new Properties(System.getProperties());
+    URL url = this.getClass().getResource("/mime-types.xml");
+    properties.setProperty("org.apache.oodt.cas.filemgr.mime.type.repository",
+        new File(url.getFile()).getAbsolutePath());
+    System.setProperties(properties);
+  }
+
+  public void tearDown() throws Exception {
+    System.setProperties(initialProperties);
+  }
+	
+	public void testVersioning(){
+		Product product = new Product();
+		ProductType type = new ProductType();
+		type.setProductRepositoryPath(productRepoPath);
+		product.setProductStructure(Product.STRUCTURE_FLAT);
+		product.setProductType(type);
+		
+		Metadata metadata = new Metadata();
+		metadata.addMetadata(SingleFileBasicVersioner.FILENAME_FIELD, "testfile.txt");
+		
+		Reference r = new Reference();
+		r.setOrigReference(origFileRef);
+		
+		product.getProductReferences().add(r);
+		
+		SingleFileBasicVersioner versioner = new SingleFileBasicVersioner();
+		try{
+			versioner.createDataStoreReferences(product, metadata);
+		}
+		catch(VersioningException e){
+			fail(e.getMessage());
+		}
+		
+		assertEquals("The generated ref: ["+r.getDataStoreReference()+"] is not equal to the expected ref: ["+expectedDestFileRef+"]", expectedDestFileRef, r.getDataStoreReference());
+		
+		
+	}
+
+}
diff --git a/0.8.1-rc1/filemgr/src/test/resources/cmd-line-actions.xml b/0.8.1-rc1/filemgr/src/test/resources/cmd-line-actions.xml
new file mode 100644
index 0000000..12b71e9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/cmd-line-actions.xml
@@ -0,0 +1,123 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+	<bean id="addProductType" class="org.apache.oodt.cas.filemgr.cli.action.AddProductTypeCliAction">
+		<property name="description" value="Adds a ProductType to list of supported ProductTypes" />
+	</bean>
+  <bean id="deleteProductByName" class="org.apache.oodt.cas.filemgr.cli.action.DeleteProductByNameCliAction">
+    <property name="description" value="Delete Product by name" />
+  </bean>
+  <bean id="deleteProductById" class="org.apache.oodt.cas.filemgr.cli.action.DeleteProductByIdCliAction">
+    <property name="description" value="Delete Product by ID" />
+  </bean>
+  <bean id="dumpMetadata" class="org.apache.oodt.cas.filemgr.cli.action.DumpMetadataCliAction">
+    <property name="description" value="Dumps Product Metadata out to XML" />
+  </bean>
+	<bean id="getCurrentTransfer" class="org.apache.oodt.cas.filemgr.cli.action.GetCurrentTransferCliAction">
+    <property name="description" value="Gets the status of the current Product file transfer" />
+  </bean>
+  <bean id="getCurrentTransfers" class="org.apache.oodt.cas.filemgr.cli.action.GetCurrentTransfersCliAction">
+    <property name="description" value="Gets the status of the current Product file transfers" />
+  </bean>
+  <bean id="getFilePercentTransferred" class="org.apache.oodt.cas.filemgr.cli.action.GetFilePercentTransferredCliAction">
+    <property name="description" value="Gets the percent amount transferred of given file" />
+  </bean>
+  <bean id="getFirstPage" class="org.apache.oodt.cas.filemgr.cli.action.GetFirstPageCliAction">
+    <property name="description" value="Gets first page of Products of given ProductType" />
+  </bean>
+  <bean id="getLastPage" class="org.apache.oodt.cas.filemgr.cli.action.GetLastPageCliAction">
+    <property name="description" value="Gets last page of Products of given ProductType" />
+  </bean>
+  <bean id="getNextPage" class="org.apache.oodt.cas.filemgr.cli.action.GetNextPageCliAction">
+    <property name="description" value="Gets next page of Products of given ProductType" />
+  </bean>
+  <bean id="getNumProducts" class="org.apache.oodt.cas.filemgr.cli.action.GetNumProductsCliAction">
+    <property name="description" value="Gets number of Products ingested for a given ProductType" />
+  </bean>
+  <bean id="getPrevPage" class="org.apache.oodt.cas.filemgr.cli.action.GetPrevPageCliAction">
+    <property name="description" value="Gets prev page of Products of given ProductType" />
+  </bean>
+  <bean id="getProductByName" class="org.apache.oodt.cas.filemgr.cli.action.GetProductByNameCliAction">
+    <property name="description" value="Get Product info by name" />
+  </bean>
+  <bean id="getProductById" class="org.apache.oodt.cas.filemgr.cli.action.GetProductByIdCliAction">
+    <property name="description" value="Gets Product info by ID" />
+  </bean>
+  <bean id="getProductPercentTransferred" class="org.apache.oodt.cas.filemgr.cli.action.GetProductPercentTransferredCliAction">
+    <property name="description" value="Gets percent amount transferred of a Products data files" />
+  </bean>
+  <bean id="getProductTypeByName" class="org.apache.oodt.cas.filemgr.cli.action.GetProductTypeByNameCliAction">
+    <property name="description" value="Gets a ProductType by its name" />
+  </bean>
+  <bean id="hasProduct" class="org.apache.oodt.cas.filemgr.cli.action.HasProductCliAction">
+    <property name="description" value="Checks if Product with given name has been ingested" />
+  </bean>
+  <bean id="ingestProduct" class="org.apache.oodt.cas.filemgr.cli.action.IngestProductCliAction">
+    <property name="description" value="Ingests a Product" />
+  </bean>
+  <bean id="luceneQuery" class="org.apache.oodt.cas.filemgr.cli.action.LuceneQueryCliAction">
+    <property name="description" value="Queries by parsing an Lucene-like query into a FileManager Query" />
+  </bean>
+  <bean id="retrieveFilesById" class="org.apache.oodt.cas.filemgr.cli.action.RetrieveFilesCliAction">
+    <property name="description" value="Retrieve a Product's files by Product ID" />
+  </bean>
+  <bean id="retrieveFilesByName" class="org.apache.oodt.cas.filemgr.cli.action.RetrieveFilesCliAction">
+    <property name="description" value="Retrieve a Product's files by Product name" />
+  </bean>
+  <bean id="sqlQuery" class="org.apache.oodt.cas.filemgr.cli.action.SqlQueryCliAction">
+    <property name="description" value="Queries by parsing an SQL-like query into a FileManager Query" />
+    <property name="detailedDescription">
+      <value>
+ This supports sending queries to the FileManager in form of
+  SELECT [Elements] FROM [ProductTypes] WHERE [where-clause], where:
+   - [Elements]: is a comma separated list of Element names; may also be * which
+    represents all Elements
+   - [ProductTypes]: is a comma separated list of ProductType names; may also
+    be * which represents all ProductTypes
+   - [where-clause]: is an optional Element name filter supporting the following:
+      * AND and OR boolean operators
+      * () grouping of queries
+      * element-name == 'element-value'
+      * element-name &#60; 'element-value'
+      * element-name &#62; 'element-value'
+      * element-name &#60;= 'element-value'
+      * element-name &#62;= 'element-value'"
+
+ An additional post-query FilterAlgor can also be specified where you specify
+  which Metadata fields which should be used as each Product's StartDateTime,
+  EndDateTime, and Priority values
+      </value>
+    </property>
+    <property name="examples">
+      <value>
+ (Assume you have a ProductType, GenericFile, which supports the
+    Elements: Filename, NominalDate, Group, and DataVersion)
+  $ ./filemgr-client -u http://localhost:9000 -op -sql
+    -q "SELECT Filename FROM GenericFile WHERE (NominalDate == '2011-20-10' OR
+      NominalDate == '2011-20-11') AND Group == 'Test' AND DataVersion > '1.0'"
+ (Returns all Products in FileManager -- use with care)
+  $ ./filemgr-client -u http://localhost:9000 -op -sql -q "SELECT * FROM *"
+      </value>
+    </property>
+  </bean>
+</beans>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/cmd-line-options.xml b/0.8.1-rc1/filemgr/src/test/resources/cmd-line-options.xml
new file mode 100644
index 0000000..f560299
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/cmd-line-options.xml
@@ -0,0 +1,1175 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+	<bean id="url" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="u" />
+		<property name="longOption" value="url" />
+		<property name="description" value="File Manager URL" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="url" />
+		<property name="required" value="true" />
+		<property name="handler">
+			<bean
+				class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+				<property name="propertyNames">
+					<list>
+						<value>org.apache.oodt.cas.filemgr.url</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="operation" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+		<property name="shortOption" value="op" />
+		<property name="longOption" value="operation" />
+		<property name="description"
+			value="Declare that you wish to present an operation" />
+		<property name="hasArgs" value="false" />
+		<property name="required" value="true" />
+		<property name="subOptions">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="addProductType" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="deleteProductById" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="deleteProductByName" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="ingestProduct" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="hasProduct" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getProductTypeByName" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getNumProducts" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getFirstPage" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getNextPage" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getPrevPage" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getLastPage" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getCurrentTransfer" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getCurrentTransfers" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getProductById" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getProductByName" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getProductPctTransferred" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getFilePctTransferred" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="sqlQuery" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="dumpMetadata" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="luceneQuery" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="retrieveFilesById" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="retrieveFilesByName" p:required="false" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- AddProductType Options -->
+	<bean id="addProductType" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="addPT" />
+		<property name="longOption" value="addProductType" />
+		<property name="description" value="Triggers addProductType Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>addProductType</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addProductType" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+  <bean id="typeName" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="tn" />
+    <property name="longOption" value="typeName" />
+    <property name="description" value="ProductType name" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="product-type-name" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="addProductType" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="addProductType" p:methodName="setProductTypeName" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="typeDesc" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="td" />
+    <property name="longOption" value="typeDesc" />
+    <property name="description" value="ProductType description" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="description" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="addProductType" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="addProductType" p:methodName="setProductTypeDescription" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="repository" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="repo" />
+    <property name="longOption" value="repository" />
+    <property name="description" value="ProductType repository" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-path" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="addProductType" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="addProductType" p:methodName="setFileRepositoryPath" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="versionClass" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="vc" />
+    <property name="longOption" value="versionClass" />
+    <property name="description" value="ProductType versioner class" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="addProductType" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="addProductType" p:methodName="setVersioner" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <!-- IngestProduct Options -->
+  <bean id="ingestProduct" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="ingest" />
+    <property name="longOption" value="ingestProduct" />
+    <property name="description" value="Triggers ingestProduct Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>ingestProduct</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="productStructure" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="ps" />
+    <property name="longOption" value="productStructure" />
+    <property name="description" value="Hierarchical | Flat" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="structure-type" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="ingestProduct" p:methodName="setProductStructure" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="metadataFile" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="mf" />
+    <property name="longOption" value="metadataFile" />
+    <property name="description" value="Metadata XML file path or URL" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-path-or-url" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="clientTransfer" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="ct" />
+    <property name="longOption" value="clientTransfer" />
+    <property name="description" value="User client transferer" />
+    <property name="hasArgs" value="false" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="dataTransfer" p:required="true" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="dataTransfer" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="dt" />
+    <property name="longOption" value="dataTransfer" />
+    <property name="description" value="DataTransferer factory class" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="ingestProduct" p:methodName="setDataTransferer" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="refs" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="rs" />
+    <property name="longOption" value="refs" />
+    <property name="description" value="Data file path or URL" />
+    <property name="type" value="java.util.List" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-path-or-url" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="ingestProduct" p:methodName="setReferences" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <!-- HasProduct Options -->
+  <bean id="hasProduct" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="product" />
+    <property name="longOption" value="hasProduct" />
+    <property name="description" value="Triggers hasProduct Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>hasProduct</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="hasProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetProductTypeByName Options -->
+  <bean id="getProductTypeByName" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="ptbyn" />
+    <property name="longOption" value="getProductTypeByName" />
+    <property name="description" value="Triggers getProductTypeByName Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getProductTypeByName</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductTypeByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetNumProducts Options -->
+  <bean id="getNumProducts" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="num" />
+    <property name="longOption" value="getNumProducts" />
+    <property name="description" value="Triggers getNumProducts Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getNumProducts</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNumProducts" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetFirstPage Options -->
+  <bean id="getFirstPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="page1" />
+    <property name="longOption" value="getFirstPage" />
+    <property name="description" value="Triggers getFirstPage Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getFirstPage</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getFirstPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetNextPage Options -->
+  <bean id="getNextPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="next" />
+    <property name="longOption" value="getNextPage" />
+    <property name="description" value="Triggers getNextPage Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getNextPage</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNextPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetPrevPage Options -->
+  <bean id="getPrevPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="prev" />
+    <property name="longOption" value="getPrevPage" />
+    <property name="description" value="Triggers getPrevPage Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getPrevPage</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getPrevPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetLastPage Options -->
+  <bean id="getLastPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="last" />
+    <property name="longOption" value="getLastPage" />
+    <property name="description" value="Triggers getLastPage Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getLastPage</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getLastPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetCurrentTransfer Options -->
+  <bean id="getCurrentTransfer" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="curTran" />
+    <property name="longOption" value="getCurrentTransfer" />
+    <property name="description" value="Triggers getCurrentTransfer Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getCurrentTransfer</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getCurrentTransfer" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetCurrentTransfers Options -->
+  <bean id="getCurrentTransfers" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="curTrans" />
+    <property name="longOption" value="getCurrentTransfers" />
+    <property name="description" value="Triggers getCurrentTransfers Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getCurrentTransfers</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getCurrentTransfers" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetProductPercentTransferred Options -->
+  <bean id="getProductPctTransferred" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="pctTrans" />
+    <property name="longOption" value="getProductPctTransferred" />
+    <property name="description" value="Triggers getProductPercentTransferred Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getProductPercentTransferred</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductPercentTransferred" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetFilePercentTransferred Options -->
+  <bean id="getFilePctTransferred" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="filePctTrans" />
+    <property name="longOption" value="getFilePctTransferred" />
+    <property name="description" value="Triggers getFilePercentTransferred Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getFilePercentTransferred</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getFilePercentTransferred" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="origRef" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="or" />
+    <property name="longOption" value="origRef" />
+    <property name="description" value="Original reference" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-path-or-url" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getFilePercentTransferred" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <!-- SqlQuery Options -->
+  <bean id="sqlQuery" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="sql" />
+    <property name="longOption" value="sqlQuery" />
+    <property name="description" value="Triggers sqlQuery Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>sqlQuery</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+
+
+  <!-- GetProductById Options -->
+  <bean id="getProductById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="pbyid" />
+    <property name="longOption" value="getProductById" />
+    <property name="description" value="Triggers getProductById Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getProductById</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductById" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetProductByName Options -->
+  <bean id="getProductByName" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="pbyn" />
+    <property name="longOption" value="getProductByName" />
+    <property name="description" value="Triggers getProductByName Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getProductByName</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- DeleteProductById Options -->
+  <bean id="deleteProductById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="dbyid" />
+    <property name="longOption" value="deleteProductById" />
+    <property name="description" value="Triggers deleteProductById Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>deleteProductById</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="deleteProductById" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- DeleteProductByName Options -->
+  <bean id="deleteProductByName" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="dbyn" />
+    <property name="longOption" value="deleteProductByName" />
+    <property name="description" value="Triggers deleteProductByName Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>deleteProductByName</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="deleteProductByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- DumpMetadata Options -->
+  <bean id="dumpMetadata" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="dmet" />
+    <property name="longOption" value="dumpMetadata" />
+    <property name="description" value="Triggers dumpMetadata Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>dumpMetadata</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="dumpMetadata" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="outputDir" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="out" />
+    <property name="longOption" value="outputDir" />
+    <property name="description" value="Output directory" />
+    <property name="type" value="java.io.File" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-dir" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="dumpMetadata" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <!-- LuceneQuery Options -->
+  <bean id="luceneQuery" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="lucene" />
+    <property name="longOption" value="luceneQuery" />
+    <property name="description" value="Triggers luceneQuery Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>luceneQuery</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="reducedProductTypes" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="pts" />
+    <property name="longOption" value="reducedProductTypes" />
+    <property name="description" value="Limit query ProductTypes queried against" />
+    <property name="type" value="java.util.List" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="list-of-product-types" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="reducedMetadataKeys" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="metKeys" />
+    <property name="longOption" value="reducedMetadataKeys" />
+    <property name="description" value="Limit Elements returned by query" />
+    <property name="type" value="java.util.List" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="list-of-elements" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <!-- retrieveFiles Options -->
+  <bean id="retrieveFilesById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="rfbyid" />
+    <property name="longOption" value="retrieveFilesById" />
+    <property name="description" value="Triggers retrieveFilesById Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>retrieveFilesById</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesById" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="retrieveFilesByName" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="rfbyn" />
+    <property name="longOption" value="retrieveFilesByName" />
+    <property name="description" value="Triggers retrieveFilesByName Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>retrieveFilesByName</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="transferer" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="trans" />
+    <property name="longOption" value="transferer" />
+    <property name="description" value="Factory for creating DataTransfer which will perform the file transfer(s)" />
+    <property name="type" value="org.apache.oodt.cas.filemgr.datatransfer.DataTransferFactory" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="transfer factory class" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesById" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="retrieveFilesById" p:methodName="setDataTransferFactory" />
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="retrieveFilesByName" p:methodName="setDataTransferFactory" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="destination" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="dest" />
+    <property name="longOption" value="destination" />
+    <property name="description" value="Directory to transfer Product file to" />
+    <property name="type" value="java.io.File" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="directory" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesById" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+	<!-- Options used for multiple Actions -->
+  <bean id="productId" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="pid" />
+    <property name="longOption" value="productId" />
+    <property name="description" value="Product ID" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="product-id" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductPercentTransferred" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductById" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="deleteProductById" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="dumpMetadata" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesById" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+	
+  <bean id="productName" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="pn" />
+    <property name="longOption" value="productName" />
+    <property name="description" value="Product name" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="product-name" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="hasProduct" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductByName" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="deleteProductByName" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="productTypeName" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="ptn" />
+    <property name="longOption" value="productTypeName" />
+    <property name="description" value="ProductType name" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="product-type-name" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductTypeByName" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNumProducts" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getFirstPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNextPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getPrevPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getLastPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductPercentTransferred" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+  
+  <bean id="currentPageNum" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="curPage" />
+    <property name="longOption" value="currentPageNum" />
+    <property name="description" value="Current Page Number" />
+    <property name="type" value="int" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="page-number" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNextPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getPrevPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="query" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="q" />
+    <property name="longOption" value="query" />
+    <property name="description" value="File Manager query" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="query" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="sortBy" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="sb" />
+    <property name="longOption" value="sortBy" />
+    <property name="description" value="Metadata field to sort query results by" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="metadata field" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="outputFormat" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="of" />
+    <property name="longOption" value="outputFormat" />
+    <property name="description" value="Output format string (i.e. Filename = $Filename)" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="output-format-string" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="delimiter" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="dlmtr" />
+    <property name="longOption" value="delimiter" />
+    <property name="description" value="String to use the separate query results" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="delimiter-string" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="filter" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="f" />
+    <property name="longOption" value="filter" />
+    <property name="description" value="Query filter" />
+    <property name="hasArgs" value="false" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="algor" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="converter" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="startDateTimeMetKey" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="endDateTimeMetKey" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="priorityMetKey" p:required="true" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="algor" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="algor" />
+    <property name="longOption" value="algor" />
+    <property name="description" value="FilterAlgor class" />
+    <property name="type" value="org.apache.oodt.cas.filemgr.structs.query.filter.FilterAlgor" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+  
+  <bean id="converter" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="conv" />
+    <property name="longOption" value="converter" />
+    <property name="description" value="VersionConverter class" />
+    <property name="type" value="org.apache.oodt.cas.filemgr.structs.query.conv.VersionConverter" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="startDateTimeMetKey" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="sdtMetKey" />
+    <property name="longOption" value="startDateTimeMetKey" />
+    <property name="description" value="Start date time metadata key" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="metadata-key" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+  
+  <bean id="endDateTimeMetKey" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="edtMetKey" />
+    <property name="longOption" value="endDateTimeMetKey" />
+    <property name="description" value="End date time metadata key" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="metadata-key" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+  
+  <bean id="priorityMetKey" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="prMetKey" />
+    <property name="longOption" value="priorityMetKey" />
+    <property name="description" value="Priority metadata key" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="metadata-key" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+</beans>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/examples/core/elements.xml b/0.8.1-rc1/filemgr/src/test/resources/examples/core/elements.xml
new file mode 100644
index 0000000..830ccdc
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/examples/core/elements.xml
@@ -0,0 +1,77 @@
+<?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.
+-->
+<cas:elements xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<element id="urn:oodt:ProductId" name="CAS.ProductId">
+		<dcElement>Identifier</dcElement>
+        <!--  
+         You can optionally specify a 'trim' tag to identify whether
+         or not you want newlines trimmed from the element description. To
+         turn off trimming (now done by default), include the following with your
+         description definition: trim="false"       
+         -->
+		<description>
+			A Product's unique identifier within the CAS namespace.
+		</description>
+	</element>
+	<element id="urn:oodt:ProductName" name="CAS.ProductName">
+		<dcElement>Title</dcElement>
+		<description>
+			A Product's name within the CAS namespace.
+		</description>
+	</element>
+	<element id="urn:oodt:ProductReceivedTime"
+		name="CAS.ProductReceivedTime">
+		<dcElement />
+		<description>
+			The ISO 8601 formatted time that the Product was received.
+		</description>
+	</element>
+	<element id="urn:oodt:Filename" name="Filename">
+		<description>
+			The names of the files that represent this product.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:FileLocation" name="FileLocation">
+		<description>
+			The locations of the files that represent this product.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:ProductType" name="ProductType">
+		<description>
+			Type of product, as specified by, e.g., a data bible.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:ProductStructure" name="ProductStructure">
+		<description>
+			Whether or not a product is Flat (e.g., a set of independent
+			files), or hierarchical, e.g., a dir structure.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:MimeType" name="MimeType">
+		<description>The IETF mime type of this product.</description>
+		<dcElement />
+	</element>
+	<element id="urn:test:DataVersion" name="DataVersion">
+		<description>The version of the data product</description>
+		<dcElement />
+	</element>
+</cas:elements>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/examples/core/product-type-element-map.xml b/0.8.1-rc1/filemgr/src/test/resources/examples/core/product-type-element-map.xml
new file mode 100644
index 0000000..8df0b62
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/examples/core/product-type-element-map.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<cas:producttypemap xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+ <!--  can set the "parent" attribute on types below to allow inheritance
+       of elements between the types 
+  -->
+   <type id="urn:oodt:GenericFile">
+       <element id="urn:oodt:ProductReceivedTime"/>
+       <element id="urn:oodt:ProductName"/>
+       <element id="urn:oodt:ProductId"/>
+       <element id="urn:oodt:ProductType"/>
+       <element id="urn:oodt:ProductStructure"/>
+       <element id="urn:oodt:Filename"/>
+       <element id="urn:oodt:FileLocation"/>
+       <element id="urn:oodt:MimeType"/>
+       <element id="urn:test:DataVersion"/>
+  </type>
+</cas:producttypemap>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/examples/core/product-types.xml b/0.8.1-rc1/filemgr/src/test/resources/examples/core/product-types.xml
new file mode 100644
index 0000000..757fd51
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/examples/core/product-types.xml
@@ -0,0 +1,94 @@
+<?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.
+-->
+<cas:producttypes xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+  <type id="urn:oodt:GenericFile" name="GenericFile">
+    <repository path="file://[HOME]/files"/>
+    <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+    <!--  
+     You can optionally specify a 'trim' tag to identify whether
+     or not you want newlines trimmed from the product type description. To
+     turn off trimming (now done by default), include the following attribute with your
+     description definition: trim="false"       
+     -->
+    <description>The default product type for any kind of file.</description>
+    <!-- Global aggregate product type metadata: you can declare this in the 
+         same way you'd wire together a CAS met file, even using multiple values
+         per key.
+         
+         This metadata can be looked up via the Product Type API, and also used 
+         in browsers and so forth to display global metadata about the collection 
+         of Products part of this product type.
+    -->
+    <metadata>
+      <keyval>
+        <key>ProductType</key>
+        <val>GenericFile</val>
+      </keyval>
+      <!-- if you are using the org.apache.oodt.cas.filemgr.versioning.ProductTypeMetVersioner 
+           you can set a met key like below to define your filePathSpec
+      <keyval>
+        <key>filePathSpec</key>
+        <val>/[Filename]</val>
+      </keyval>
+      -->
+    </metadata>
+    <metExtractors>
+      <extractor
+        class="org.apache.oodt.cas.filemgr.metadata.extractors.CoreMetExtractor">
+        <configuration>
+          <!--  you can optionally include the envReplace tag to turn on/off environment var replacement -->
+          <property name="nsAware" value="true" />
+          <property name="elementNs" value="CAS" />
+          <property name="elements"
+            value="ProductReceivedTime,ProductName,ProductId" />
+        </configuration>
+      </extractor>
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.MimeTypeExtractor" />
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.FinalFileLocationExtractor">
+        <configuration>
+          <!-- this property specifies whether you want the FILE_LOCATION field
+               computed by this extractor to replace any other FILE_LOCATION met 
+               attribute.
+           -->
+           <property name="replace" value="true"/>
+        </configuration>
+      </extractor>
+      
+      <!-- 
+        The below enables the FilenameRegexMetExtractor.
+        It allows a user to specify a filename pattern with Java Regex that identifies groups 
+        within a particular file name. Those groups are then mapped to Metadata key names, and 
+        extracted as metadta from a file's name.
+        
+        In the example below, there are two groups, Filename, and ProductId, for files
+        of the form:
+        
+        Filename_ProductId.txt
+        
+        <extractor class="org.apache.oodt.cas.filemgr.metadata.extrctors.examples.FilenameRegexMetExtractor">
+          <configuration>
+            <property name="filenamePattern" value="(\\w*)_(\\d*)\\.txt"/>
+            <property name="metadataKeys" value="Filename,ProductId"/>
+          </configuration>
+        
+        </extractor>
+      
+       -->
+    </metExtractors>
+  </type>
+</cas:producttypes>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/examples/geo/elements.xml b/0.8.1-rc1/filemgr/src/test/resources/examples/geo/elements.xml
new file mode 100644
index 0000000..affc010
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/examples/geo/elements.xml
@@ -0,0 +1,37 @@
+<?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.
+-->
+<cas:elements xmlns:cas="http://oodt.apache.org/components/cas">
+  <element id="urn:oodt:Latitude" name="Latitude">
+    <!--
+      You can optionally specify a 'trim' tag to identify whether or not you
+      want newlines trimmed from the element description. To turn off trimming
+      (now done by default), include the following with your description
+      definition: trim="false"
+    -->
+    <description>
+      Geographical latitude data for a product.
+    </description>
+    <dcElement />
+  </element>
+  <element id="urn:oodt:Longitude" name="Longitude">
+    <description>
+      Geographical longitude data for a product.
+    </description>
+    <dcElement />
+  </element>
+</cas:elements>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/examples/geo/product-type-element-map.xml b/0.8.1-rc1/filemgr/src/test/resources/examples/geo/product-type-element-map.xml
new file mode 100644
index 0000000..2b6a6eb
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/examples/geo/product-type-element-map.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<cas:producttypemap xmlns:cas="http://oodt.apache.org/components/cas">
+  <!--
+    You can set the "parent" attribute on types below to allow inheritance of
+    elements between the types.
+  -->
+  <type id="urn:oodt:LocationAwareProduct" parent="urn:oodt:GenericFile">
+    <element id="urn:oodt:Latitude"/>
+    <element id="urn:oodt:Longitude"/>
+  </type>
+</cas:producttypemap>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/examples/geo/product-types.xml b/0.8.1-rc1/filemgr/src/test/resources/examples/geo/product-types.xml
new file mode 100644
index 0000000..427d4f0
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/examples/geo/product-types.xml
@@ -0,0 +1,79 @@
+<?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.
+-->
+<cas:producttypes xmlns:cas="http://oodt.apache.org/components/cas">
+  <type id="urn:oodt:LocationAwareProduct" name="LocationAwareProduct">
+    <repository path="file://[HOME]/files"/>
+    <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+    <!--
+      You can optionally specify a 'trim' tag to identify whether or not you
+      want newlines trimmed from the product type description.  To turn off
+      trimming (now done by default), include the following attribute with
+      your description definition: trim="false"
+    -->
+    <description>A product type with location metadata.</description>
+    <!--
+      Global aggregate product type metadata: you can declare this in the
+      same way you'd wire together a CAS met file, even using multiple values
+      per key.
+      
+      This metadata can be looked up via the Product Type API, and also used
+      in browsers and so forth to display global metadata about the collection
+      of Products part of this product type.
+    -->
+    <metadata>
+      <keyval>
+        <key>ProductType</key>
+        <val>LocationAwareProduct</val>
+      </keyval>
+      <!-- if you are using the org.apache.oodt.cas.filemgr.versioning.ProductTypeMetVersioner 
+           you can set a met key like below to define your filePathSpec
+      <keyval>
+        <key>filePathSpec</key>
+        <val>/[Filename]</val>
+      </keyval>
+      -->      
+    </metadata>
+    <metExtractors>
+      <extractor
+        class="org.apache.oodt.cas.filemgr.metadata.extractors.CoreMetExtractor">
+        <configuration>
+          <!--
+            You can optionally include the envReplace tag to turn on/off
+            environment var replacement.
+          -->
+          <property name="nsAware" value="true" />
+          <property name="elementNs" value="CAS" />
+          <property name="elements"
+            value="ProductReceivedTime,ProductName,ProductId" />
+        </configuration>
+      </extractor>
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.MimeTypeExtractor" />
+      <extractor
+        class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.FinalFileLocationExtractor">
+        <configuration>
+          <!--
+            This property specifies whether you want the FILE_LOCATION field
+            computed by this extractor to replace any other FILE_LOCATION met
+            attribute.
+          -->
+          <property name="replace" value="true"/>
+        </configuration>
+      </extractor>
+    </metExtractors>
+  </type>
+</cas:producttypes>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/examples/trace/elements.xml b/0.8.1-rc1/filemgr/src/test/resources/examples/trace/elements.xml
new file mode 100644
index 0000000..2fefacf
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/examples/trace/elements.xml
@@ -0,0 +1,95 @@
+<?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.
+-->
+<cas:elements xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+   <element id="urn:oodt:InputFiles" name="InputFiles">
+        <!--  
+         You can optionally specify a 'trim' tag to identify whether
+         or not you want newlines trimmed from the element description. To
+         turn off trimming (now done by default), include the following with your
+         description definition: trim="false"       
+         -->   
+       <description>The set of input files that went into producing this file.</description>
+       <dcElement/>
+   </element>
+   <element id="urn:oodt:OutputFiles" name="OutputFiles">
+        <description>The set of output files that included this file in its input.</description>
+        <dcElement/>
+   </element>
+   
+   <element id="urn:oodt:JobId" name="JobId">
+       <description>The unique identifier generated by the workflow manager for the job
+       that produced this file.</description>
+       <dcElement/>   
+   </element>
+   
+   <element id="urn:oodt:ProductionDateTime" name="ProductionDateTime">
+       <description>The date/time stamp that this file was produced either by ingestion 
+       or processing.</description>
+       <dcElement/>
+   </element>
+   
+   <element id="urn:oodt:ExecutablePathnames" name="ExecutablePathnames">
+    <description>The pathnames to the exectuables used to generate this product.</description>
+    <dcElement/>
+  </element>
+
+  <element id="urn:oodt:ExecutableVersions" name="ExecutableVersions">
+    <description>The versions of the exectuables used to generate this product.</description>
+    <dcElement/>
+  </element>
+
+  <element id="urn:oodt:ApplicationSuccessFlag" name="ApplicationSuccessFlag">
+    <description>An indication of whether the generating application completed
+      successfully.</description>
+    <dcElement/>
+  </element>
+  
+  <element id="urn:oodt:TaskSuccessFlag" name="TaskSuccessFlag">
+    <description>An indication of whether the PCS Workflow Task that ran the PGE completed
+      successfully.</description>
+    <dcElement/>
+  </element>
+
+  <element id="urn:oodt:JobSuccessFlag" name="JobSuccessFlag">
+    <description>An indication of whether the PCS job ran by the PCS to create the product completed
+      successfully.</description>
+    <dcElement/>
+  </element>
+  
+  <element id="urn:oodt:PGEVersion" name="PGEVersion">
+    <description>Captures the version of the algorithm that has been run on the data.</description>
+    <dcElement/>
+  </element>
+
+  <element id="urn:oodt:ProcessingNode" name="ProcessingNode">
+    <description>The node that the job that produced this product was run on.</description>
+    <dcElement/>
+  </element>
+     
+ <element id="urn:oodt:ExecutionTime" name="ExecutionTime">
+    <description>The amount of time that the job that produced this product took to run.</description>
+    <dcElement/>
+ </element>
+
+  <element id="urn:oodt:CmdLineParameters" name="CmdLineParameters">
+    <description>The command line parameters that were used to invoke this job.</description>
+    <dcElement/>
+  </element>  
+    
+   
+</cas:elements>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/examples/trace/product-type-element-map.xml b/0.8.1-rc1/filemgr/src/test/resources/examples/trace/product-type-element-map.xml
new file mode 100644
index 0000000..038a58c
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/examples/trace/product-type-element-map.xml
@@ -0,0 +1,37 @@
+<?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.
+-->
+<cas:producttypemap xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+ <!--  can set the "parent" attribute on types below to allow inheritance
+       of elements between the types 
+  -->
+  <type id="urn:oodt:TraceableFile" parent="urn:oodt:GenericFile">
+       <element id="urn:oodt:InputFiles"/>
+       <element id="urn:oodt:OutputFiles"/>
+       <element id="urn:oodt:JobId"/>
+       <element id="urn:oodt:ProductionDateTime"/>
+       <element id="urn:oodt:ExecutablePathnames"/> 
+       <element id="urn:oodt:ExecutableVersions"/>
+       <element id="urn:oodt:ApplicationSuccessFlag"/>
+       <element id="urn:oodt:TaskSuccessFlag" />
+       <element id="urn:oodt:JobSuccessFlag"/>
+       <element id="urn:oodt:PGEVersion"/>
+       <element id="urn:oodt:ProcessingNode"/>
+       <element id="urn:oodt:ExecutionTime" />
+       <element id="urn:oodt:CmdLineParameters"/>       
+  </type>
+</cas:producttypemap>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/examples/trace/product-types.xml b/0.8.1-rc1/filemgr/src/test/resources/examples/trace/product-types.xml
new file mode 100644
index 0000000..1ec9c99
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/examples/trace/product-types.xml
@@ -0,0 +1,74 @@
+<?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.
+-->
+<cas:producttypes xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+  <type id="urn:oodt:TraceableFile" name="TraceableFile">
+    <repository path="file://[HOME]/files"/>
+    <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+    <!--                                                                                                                                                            
+     You can optionally specify a 'trim' tag to identify whether                                                                                                    
+     or not you want newlines trimmed from the product type description. To                                                                                         
+     turn off trimming (now done by default), include the following attribute with your                                                                             
+     description definition: trim="false"                                                                                                                           
+     -->
+    <description>A traceable product for use in provenance and algorithm execution.</description>
+    <!--
+      Global aggregate product type metadata: you can declare this in the
+      same way you'd wire together a CAS met file, even using multiple values
+      per key.
+      
+      This metadata can be looked up via the Product Type API, and also used
+      in browsers and so forth to display global metadata about the collection
+      of Products part of this product type.
+    -->
+    <metadata>
+      <keyval>
+        <key>ProductType</key>
+        <val>LocationAwareProduct</val>
+      </keyval>
+      <!-- if you are using the org.apache.oodt.cas.filemgr.versioning.ProductTypeMetVersioner 
+           you can set a met key like below to define your filePathSpec
+      <keyval>
+        <key>filePathSpec</key>
+        <val>/[Filename]</val>
+      </keyval>
+      -->      
+    </metadata>
+    <metExtractors>
+      <extractor
+        class="org.apache.oodt.cas.filemgr.metadata.extractors.CoreMetExtractor">
+        <configuration>
+          <!--  you can optionally include the envReplace tag to turn on/off environment var replacement -->
+          <property name="nsAware" value="true" />
+          <property name="elementNs" value="CAS" />
+          <property name="elements"
+            value="ProductReceivedTime,ProductName,ProductId" />
+        </configuration>
+      </extractor>
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.MimeTypeExtractor" />
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.FinalFileLocationExtractor">
+        <configuration>
+          <!-- this property specifies whether you want the FILE_LOCATION field                                                                                     
+               computed by this extractor to replace any other FILE_LOCATION met                                                                                    
+               attribute.                                                                                                                                           
+           -->
+           <property name="replace" value="true"/>
+        </configuration>
+      </extractor>
+    </metExtractors>
+  </type>
+</cas:producttypes>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/filemgr.properties b/0.8.1-rc1/filemgr/src/test/resources/filemgr.properties
new file mode 100644
index 0000000..d79896a
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/filemgr.properties
@@ -0,0 +1,310 @@
+#  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.
+
+# Test Configuration properties for the File Manager
+
+# repository factory
+filemgr.repository.factory=org.apache.oodt.cas.filemgr.repository.XMLRepositoryManagerFactory
+
+# catalog factory
+filemgr.catalog.factory=org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory
+
+# data transfer factory
+filemgr.datatransfer.factory=org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory
+
+# validation layer factory
+filemgr.validationLayer.factory=org.apache.oodt.cas.filemgr.validation.XMLValidationLayerFactory
+
+# xml rpc client configuration
+org.apache.oodt.cas.filemgr.system.xmlrpc.connectionTimeout.minutes=20
+org.apache.oodt.cas.filemgr.system.xmlrpc.requestTimeout.minutes=60
+#org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retries=0
+#org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retry.interval.seconds=3
+
+# data source catalog configuration
+org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.url=jdbc:hsqldb:hsql://localhost/test
+org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.user=sa
+org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.pass=
+org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.driver=org.hsqldb.jdbc.JDBCDriver
+org.apache.oodt.cas.filemgr.catalog.datasource.quoteFields=false
+org.apache.oodt.cas.filemgr.catalog.datasource.pageSize=20
+org.apache.oodt.cas.filemgr.catalog.datasource.cacheUpdateMinutes=5
+org.apache.oodt.cas.filemgr.catalog.datasource.orderedValues=false
+# set the following property to 'true' to allow dynamic metadata fields,
+# effectively bypassing the validation layer.
+# by default the property is false
+#org.apache.oodt.cas.filemgr.catalog.datasource.lenientFields=true
+# set the following property to true to enable the column "product_id"
+# in table "products" to be of type string
+#org.apache.oodt.cas.filemgr.catalog.datasource.productId.string=false
+
+
+# mapped data source catalog configuration
+org.apache.oodt.cas.filemgr.catalog.mappeddatasource.mapFile=/path/to/ops.catalog.typemap.properties
+
+# science data catalog configuration
+org.apache.oodt.cas.filemgr.catalog.science.jdbc.url=jdbc:hsqldb:hsql://localhost/test
+org.apache.oodt.cas.filemgr.catalog.science.jdbc.user=sa
+org.apache.oodt.cas.filemgr.catalog.science.jdbc.pass=
+org.apache.oodt.cas.filemgr.catalog.science.jdbc.driver=org.hsqldb.jdbc.JDBCDriver
+
+# lucene catalog configuration
+org.apache.oodt.cas.filemgr.catalog.lucene.idxPath=file:/testdata/
+org.apache.oodt.cas.filemgr.catalog.lucene.pageSize=20
+org.apache.oodt.cas.filemgr.catalog.lucene.commitLockTimeout.seconds=60
+org.apache.oodt.cas.filemgr.catalog.lucene.writeLockTimeout.seconds=60
+org.apache.oodt.cas.filemgr.catalog.lucene.mergeFactor=20
+
+# solr catalog configuration
+org.apache.oodt.cas.filemgr.catalog.solr.url=http://localhost:8983/solr
+#org.apache.oodt.cas.filemgr.catalog.solr.url=http://localhost:8080/solr
+org.apache.oodt.cas.filemgr.catalog.solr.productSerializer=org.apache.oodt.cas.filemgr.catalog.solr.DefaultProductSerializer
+org.apache.oodt.cas.filemgr.catalog.solr.productIdGenerator=org.apache.oodt.cas.filemgr.catalog.solr.UUIDProductIdGenerator
+#org.apache.oodt.cas.filemgr.catalog.solr.productIdGenerator=org.apache.oodt.cas.filemgr.catalog.solr.NameProductIdGenerator
+
+
+# data source repository manager configuration
+org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.url=jdbc:hsqldb:hsql://localhost/test
+org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.user=sa
+org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.pass=
+org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.driver=org.hsqldb.jdbc.JDBCDriver
+
+# science data repository manager configuration
+org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.url=jdbc:hsqldb:hsql://localhost/test
+org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.user=sa
+org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.pass=
+org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.driver=org.hsqldb.jdbc.JDBCDriver
+
+# XML repository manager configuration
+org.apache.oodt.cas.filemgr.repositorymgr.dirs=file:///dir1,file:///dir2
+
+# XML validation layer configuration
+org.apache.oodt.cas.filemgr.validation.dirs=file:///dir1,file:///dir2
+
+# set the following property to 'true' to allow dynamic metadata fields,
+# effectively bypassing the validation layer.
+# by default the property is false
+#org.apache.oodt.cas.filemgr.catalog.lucene.lenientFields=true
+
+# data source validation layer configuration
+org.apache.oodt.cas.filemgr.validation.datasource.jdbc.url=jdbc:hsqldb:hsql://localhost/test
+org.apache.oodt.cas.filemgr.validation.datasource.jdbc.user=sa
+org.apache.oodt.cas.filemgr.validation.datasource.jdbc.pass=
+org.apache.oodt.cas.filemgr.validation.datasource.jdbc.driver=org.hsqldb.jdbc.JDBCDriver
+org.apache.oodt.cas.filemgr.validation.datasource.quoteFields=false
+
+# science data validation layer configuration
+org.apache.oodt.cas.filemgr.validation.science.jdbc.url=jdbc:hsqldb:hsql://localhost/test
+org.apache.oodt.cas.filemgr.validation.science.jdbc.user=sa
+org.apache.oodt.cas.filemgr.validation.science.jdbc.pass=
+org.apache.oodt.cas.filemgr.validation.science.jdbc.driver=org.hsqldb.jdbc.JDBCDriver
+
+# remote data transfer configuration
+org.apache.oodt.cas.filemgr.datatransfer.remote.chunkSize=1024
+
+# Amazon S3 data transfer configuration.
+# Region can be any of the values found here:
+#   http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/regions/Regions.html
+org.apache.oodt.cas.filemgr.datatransfer.s3.bucket.name=some_bucket_name
+org.apache.oodt.cas.filemgr.datatransfer.s3.region=EU_WEST_1
+org.apache.oodt.cas.filemgr.datatransfer.s3.access.key=s3_access_key
+org.apache.oodt.cas.filemgr.datatransfer.s3.secret.key=s3_secret_key
+
+# location of Mime-Type repository
+org.apache.oodt.cas.filemgr.mime.type.repository=file:/src/mime-types.xml
+
+# tells the file manager system layer to include product instance metadata
+# NOTE: here are the expected field mappings
+#
+#      product.getProductId() -> ProductId
+#      product.getProductName() -> ProductName
+#      product.getProductStructure() -> ProductStructure
+#      product.getTransferStatus() -> ProductTransferStatus
+#      product.getRootRef() -> ProductRootReference
+
+# for the references returned by product.getProductReferences() the following 
+# metadata fields will be added (order will be maintained, such that data store 
+# ref at index 0 will map to orig ref at index 0, etc.)
+#
+#      ProductDataStoreReferences (list of all data store references: 
+#       note already translated into path, not URI)
+#      ProductOrigReferences (list of all orig references: 
+#       note already translated into path, not URI)
+#      ProductMimeType (list of all references' mime-types)
+#      ProductFileSize (list of all references' file sizes)
+
+org.apache.oodt.cas.filemgr.metadata.expandProduct=false
+
+# ConfigurableMetadataBasedVersioning configuration
+#org.apache.oodt.cas.filemgr.versioning.configuration.all_product_types=[Year]/[Month]/[Filename]
+#org.apache.oodt.cas.filemgr.versioning.configuration.<product_type>=[Year]/[Month]/[Filename]
+
+# Enable to use only server-side versioning.
+#org.apache.oodt.cas.filemgr.serverside.versioning=true
+#  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.
+
+# Test Configuration properties for the File Manager
+
+# repository factory
+filemgr.repository.factory=org.apache.oodt.cas.filemgr.repository.XMLRepositoryManagerFactory
+
+# catalog factory
+filemgr.catalog.factory=org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory
+
+# data transfer factory
+filemgr.datatransfer.factory=org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory
+
+# validation layer factory
+filemgr.validationLayer.factory=org.apache.oodt.cas.filemgr.validation.XMLValidationLayerFactory
+
+# xml rpc client configuration
+org.apache.oodt.cas.filemgr.system.xmlrpc.connectionTimeout.minutes=20
+org.apache.oodt.cas.filemgr.system.xmlrpc.requestTimeout.minutes=60
+#org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retries=0
+#org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retry.interval.seconds=3
+
+# data source catalog configuration
+org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.url=jdbc:hsqldb:hsql://localhost/test
+org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.user=sa
+org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.pass=
+org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.driver=org.hsqldb.jdbc.JDBCDriver
+org.apache.oodt.cas.filemgr.catalog.datasource.quoteFields=false
+org.apache.oodt.cas.filemgr.catalog.datasource.pageSize=20
+org.apache.oodt.cas.filemgr.catalog.datasource.cacheUpdateMinutes=5
+org.apache.oodt.cas.filemgr.catalog.datasource.orderedValues=false
+# set the following property to 'true' to allow dynamic metadata fields,
+# effectively bypassing the validation layer.
+# by default the property is false
+#org.apache.oodt.cas.filemgr.catalog.datasource.lenientFields=true
+# set the following property to true to enable the column "product_id"
+# in table "products" to be of type string
+#org.apache.oodt.cas.filemgr.catalog.datasource.productId.string=false
+
+
+# mapped data source catalog configuration
+org.apache.oodt.cas.filemgr.catalog.mappeddatasource.mapFile=/path/to/ops.catalog.typemap.properties
+
+# science data catalog configuration
+org.apache.oodt.cas.filemgr.catalog.science.jdbc.url=jdbc:hsqldb:hsql://localhost/test
+org.apache.oodt.cas.filemgr.catalog.science.jdbc.user=sa
+org.apache.oodt.cas.filemgr.catalog.science.jdbc.pass=
+org.apache.oodt.cas.filemgr.catalog.science.jdbc.driver=org.hsqldb.jdbc.JDBCDriver
+
+# lucene catalog configuration
+org.apache.oodt.cas.filemgr.catalog.lucene.idxPath=file:/testdata/
+org.apache.oodt.cas.filemgr.catalog.lucene.pageSize=20
+org.apache.oodt.cas.filemgr.catalog.lucene.commitLockTimeout.seconds=60
+org.apache.oodt.cas.filemgr.catalog.lucene.writeLockTimeout.seconds=60
+org.apache.oodt.cas.filemgr.catalog.lucene.mergeFactor=20
+
+# solr catalog configuration
+org.apache.oodt.cas.filemgr.catalog.solr.url=http://localhost:8983/solr
+#org.apache.oodt.cas.filemgr.catalog.solr.url=http://localhost:8080/solr
+org.apache.oodt.cas.filemgr.catalog.solr.productSerializer=org.apache.oodt.cas.filemgr.catalog.solr.DefaultProductSerializer
+org.apache.oodt.cas.filemgr.catalog.solr.productIdGenerator=org.apache.oodt.cas.filemgr.catalog.solr.UUIDProductIdGenerator
+#org.apache.oodt.cas.filemgr.catalog.solr.productIdGenerator=org.apache.oodt.cas.filemgr.catalog.solr.NameProductIdGenerator
+
+
+# data source repository manager configuration
+org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.url=jdbc:hsqldb:hsql://localhost/test
+org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.user=sa
+org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.pass=
+org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.driver=org.hsqldb.jdbc.JDBCDriver
+
+# science data repository manager configuration
+org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.url=jdbc:hsqldb:hsql://localhost/test
+org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.user=sa
+org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.pass=
+org.apache.oodt.cas.filemgr.repositorymgr.science.jdbc.driver=org.hsqldb.jdbc.JDBCDriver
+
+# XML repository manager configuration
+org.apache.oodt.cas.filemgr.repositorymgr.dirs=file:///dir1,file:///dir2
+
+# XML validation layer configuration
+org.apache.oodt.cas.filemgr.validation.dirs=file:///dir1,file:///dir2
+
+# set the following property to 'true' to allow dynamic metadata fields,
+# effectively bypassing the validation layer.
+# by default the property is false
+#org.apache.oodt.cas.filemgr.catalog.lucene.lenientFields=true
+
+# data source validation layer configuration
+org.apache.oodt.cas.filemgr.validation.datasource.jdbc.url=jdbc:hsqldb:hsql://localhost/test
+org.apache.oodt.cas.filemgr.validation.datasource.jdbc.user=sa
+org.apache.oodt.cas.filemgr.validation.datasource.jdbc.pass=
+org.apache.oodt.cas.filemgr.validation.datasource.jdbc.driver=org.hsqldb.jdbc.JDBCDriver
+org.apache.oodt.cas.filemgr.validation.datasource.quoteFields=false
+
+# science data validation layer configuration
+org.apache.oodt.cas.filemgr.validation.science.jdbc.url=jdbc:hsqldb:hsql://localhost/test
+org.apache.oodt.cas.filemgr.validation.science.jdbc.user=sa
+org.apache.oodt.cas.filemgr.validation.science.jdbc.pass=
+org.apache.oodt.cas.filemgr.validation.science.jdbc.driver=org.hsqldb.jdbc.JDBCDriver
+
+# remote data transfer configuration
+org.apache.oodt.cas.filemgr.datatransfer.remote.chunkSize=1024
+
+# Amazon S3 data transfer configuration.
+# Region can be any of the values found here:
+#   http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/regions/Regions.html
+org.apache.oodt.cas.filemgr.datatransfer.s3.bucket.name=some_bucket_name
+org.apache.oodt.cas.filemgr.datatransfer.s3.region=EU_WEST_1
+org.apache.oodt.cas.filemgr.datatransfer.s3.access.key=s3_access_key
+org.apache.oodt.cas.filemgr.datatransfer.s3.secret.key=s3_secret_key
+
+# location of Mime-Type repository
+org.apache.oodt.cas.filemgr.mime.type.repository=file:/src/mime-types.xml
+
+# tells the file manager system layer to include product instance metadata
+# NOTE: here are the expected field mappings
+#
+#      product.getProductId() -> ProductId
+#      product.getProductName() -> ProductName
+#      product.getProductStructure() -> ProductStructure
+#      product.getTransferStatus() -> ProductTransferStatus
+#      product.getRootRef() -> ProductRootReference
+
+# for the references returned by product.getProductReferences() the following 
+# metadata fields will be added (order will be maintained, such that data store 
+# ref at index 0 will map to orig ref at index 0, etc.)
+#
+#      ProductDataStoreReferences (list of all data store references: 
+#       note already translated into path, not URI)
+#      ProductOrigReferences (list of all orig references: 
+#       note already translated into path, not URI)
+#      ProductMimeType (list of all references' mime-types)
+#      ProductFileSize (list of all references' file sizes)
+
+org.apache.oodt.cas.filemgr.metadata.expandProduct=false
+
+# ConfigurableMetadataBasedVersioning configuration
+#org.apache.oodt.cas.filemgr.versioning.configuration.all_product_types=[Year]/[Month]/[Filename]
+#org.apache.oodt.cas.filemgr.versioning.configuration.<product_type>=[Year]/[Month]/[Filename]
+
+# Enable to use only server-side versioning.
+#org.apache.oodt.cas.filemgr.serverside.versioning=true
\ No newline at end of file
diff --git a/0.8.1-rc1/filemgr/src/test/resources/ingest/fmpolicy/elements.xml b/0.8.1-rc1/filemgr/src/test/resources/ingest/fmpolicy/elements.xml
new file mode 100644
index 0000000..7d2b671
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/ingest/fmpolicy/elements.xml
@@ -0,0 +1,71 @@
+<?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.
+-->
+<cas:elements xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<element id="urn:oodt:ProductId" name="CAS.ProductId">
+		<dcElement>Identifier</dcElement>
+		<description>
+			A Product's unique identifier within the CAS namespace.
+		</description>
+	</element>
+	<element id="urn:oodt:ProductName" name="CAS.ProductName">
+		<dcElement>Title</dcElement>
+		<description>
+			A Product's name within the CAS namespace.
+		</description>
+	</element>
+	<element id="urn:oodt:ProductReceivedTime"
+		name="CAS.ProductReceivedTime">
+		<dcElement />
+		<description>
+			The ISO 8601 formatted time that the Product was received.
+		</description>
+	</element>
+	<element id="urn:oodt:Filename" name="Filename">
+		<description>
+			The names of the files that represent this product.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:FileLocation" name="FileLocation">
+		<description>
+			The locations of the files that represent this product.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:ProductType" name="ProductType">
+		<description>
+			Type of product, as specified by, e.g., a data bible.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:ProductStructure" name="ProductStructure">
+		<description>
+			Whether or not a product is Flat (e.g., a set of independent
+			files), or hierarchical, e.g., a dir structure.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:MimeType" name="MimeType">
+		<description>The IETF mime type of this product.</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:TestElement" name="TestElement">
+		<description>a test element</description>
+		<dcElement />
+	</element>
+</cas:elements>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/ingest/fmpolicy/product-type-element-map.xml b/0.8.1-rc1/filemgr/src/test/resources/ingest/fmpolicy/product-type-element-map.xml
new file mode 100644
index 0000000..4d24e11
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/ingest/fmpolicy/product-type-element-map.xml
@@ -0,0 +1,36 @@
+<?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.
+-->
+<cas:producttypemap xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+ <!--  can set the "parent" attribute on types below to allow inheritance
+       of elements between the types 
+  -->
+   <type id="urn:oodt:GenericFile">
+       <element id="urn:oodt:ProductReceivedTime"/>
+       <element id="urn:oodt:ProductName"/>
+       <element id="urn:oodt:ProductId"/>
+       <element id="urn:oodt:ProductType"/>
+       <element id="urn:oodt:ProductStructure"/>
+       <element id="urn:oodt:Filename"/>
+       <element id="urn:oodt:FileLocation"/>
+       <element id="urn:oodt:MimeType"/>
+   </type>
+ 
+   <type id="urn:oodt:TestType">
+       <element id="urn:oodt:TestElement"/>
+    </type>
+</cas:producttypemap>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/ingest/fmpolicy/product-types.xml b/0.8.1-rc1/filemgr/src/test/resources/ingest/fmpolicy/product-types.xml
new file mode 100644
index 0000000..24885b5
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/ingest/fmpolicy/product-types.xml
@@ -0,0 +1,40 @@
+<?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.
+-->
+<cas:producttypes xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+    <type id="urn:oodt:GenericFile" name="GenericFile">
+    <repository path="file:///tmp"/>
+    <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+    <description>The default product type for any kind of file.</description>
+    <metExtractors>
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.CoreMetExtractor">
+        <configuration>
+        <!--  you can optionally include the envReplace tag to turn on/off environment var replacement -->
+         <property name="nsAware" value="true"/>
+         <property name="elementNs" value="CAS"/>
+         <property name="elements" value="ProductReceivedTime,ProductName,ProductId"/>
+        </configuration>
+      </extractor>
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.MimeTypeExtractor"/>
+    </metExtractors>
+    </type>
+    <type id="urn:oodt:TestType" name="TestType">
+        <repository path="file:///tmp/test-type"/>
+        <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+        <description>The default product type for any kind of file.</description>
+    </type>
+</cas:producttypes>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/ingest/test-file-1.txt b/0.8.1-rc1/filemgr/src/test/resources/ingest/test-file-1.txt
new file mode 100644
index 0000000..d525e84
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/ingest/test-file-1.txt
@@ -0,0 +1 @@
+this is test-file-1
diff --git a/0.8.1-rc1/filemgr/src/test/resources/ingest/test-file-2.txt b/0.8.1-rc1/filemgr/src/test/resources/ingest/test-file-2.txt
new file mode 100644
index 0000000..871fcf7
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/ingest/test-file-2.txt
@@ -0,0 +1 @@
+this is test-file-2
diff --git a/0.8.1-rc1/filemgr/src/test/resources/ingest/test-file-3.txt b/0.8.1-rc1/filemgr/src/test/resources/ingest/test-file-3.txt
new file mode 100644
index 0000000..b9a2e97
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/ingest/test-file-3.txt
@@ -0,0 +1 @@
+This is just a file to test metadata
diff --git a/0.8.1-rc1/filemgr/src/test/resources/ingest/test-file-3.txt.met b/0.8.1-rc1/filemgr/src/test/resources/ingest/test-file-3.txt.met
new file mode 100644
index 0000000..516f989
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/ingest/test-file-3.txt.met
@@ -0,0 +1,17 @@
+<cas:metadata xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<keyval type="scalar">
+  <key>Filename</key>
+  <val>test-file-3.txt</val>
+</keyval>
+<keyval type="scalar">
+  <key>ProductType</key>
+  <val>TestType</val>
+</keyval>
+<keyval type="scalar">
+  <key>TestElement</key>
+  <val>fe</val>
+  <val>fi</val>
+  <val>fo</val>
+  <val>fum</val>
+</keyval>
+</cas:metadata>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/ingest/test.txt b/0.8.1-rc1/filemgr/src/test/resources/ingest/test.txt
new file mode 100644
index 0000000..65cdb12
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/ingest/test.txt
@@ -0,0 +1 @@
+this is a test text file
diff --git a/0.8.1-rc1/filemgr/src/test/resources/ingest/test.txt.met b/0.8.1-rc1/filemgr/src/test/resources/ingest/test.txt.met
new file mode 100644
index 0000000..6edb2fd
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/ingest/test.txt.met
@@ -0,0 +1,10 @@
+<cas:metadata xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<keyval type="scalar">
+  <key>Filename</key>
+  <val>test.txt</val>
+</keyval>
+<keyval type="scalar">
+  <key>ProductType</key>
+  <val>GenericFile</val>
+</keyval>
+</cas:metadata>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/mime-types.xml b/0.8.1-rc1/filemgr/src/test/resources/mime-types.xml
new file mode 100644
index 0000000..a007e81
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/mime-types.xml
@@ -0,0 +1,4119 @@
+<?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.
+-->
+<!--
+  Description: This xml file defines the valid mime types used by Tika.
+  The mime type data within this file is based on information from various
+  sources like Apache Nutch, Apache HTTP Server, the file(1) command, etc.
+-->
+<mime-info>
+
+  <mime-type type="application/activemessage"/>
+  <mime-type type="application/andrew-inset">
+    <glob pattern="*.ez"/>
+  </mime-type>
+  <mime-type type="application/applefile"/>
+  <mime-type type="application/applixware">
+    <glob pattern="*.aw"/>
+  </mime-type>
+
+  <mime-type type="application/atom+xml">
+    <root-XML localName="feed" namespaceURI="http://purl.org/atom/ns#"/>
+    <glob pattern="*.atom"/>
+  </mime-type>
+
+  <mime-type type="application/atomcat+xml">
+    <glob pattern="*.atomcat"/>
+  </mime-type>
+  <mime-type type="application/atomicmail"/>
+  <mime-type type="application/atomsvc+xml">
+    <glob pattern="*.atomsvc"/>
+  </mime-type>
+  <mime-type type="application/auth-policy+xml"/>
+  <mime-type type="application/batch-smtp"/>
+  <mime-type type="application/beep+xml"/>
+  <mime-type type="application/cals-1840"/>
+  <mime-type type="application/ccxml+xml">
+    <glob pattern="*.ccxml"/>
+  </mime-type>
+  <mime-type type="application/cea-2018+xml"/>
+  <mime-type type="application/cellml+xml"/>
+  <mime-type type="application/cnrp+xml"/>
+  <mime-type type="application/commonground"/>
+  <mime-type type="application/conference-info+xml"/>
+  <mime-type type="application/cpl+xml"/>
+  <mime-type type="application/csta+xml"/>
+  <mime-type type="application/cstadata+xml"/>
+  <mime-type type="application/cu-seeme">
+    <glob pattern="*.cu"/>
+  </mime-type>
+  <mime-type type="application/cybercash"/>
+  <mime-type type="application/davmount+xml">
+    <glob pattern="*.davmount"/>
+  </mime-type>
+  <mime-type type="application/dca-rft"/>
+  <mime-type type="application/dec-dx"/>
+  <mime-type type="application/dialog-info+xml"/>
+  <mime-type type="application/dicom"/>
+  <mime-type type="application/dns"/>
+  <mime-type type="application/dvcs"/>
+  <mime-type type="application/ecmascript">
+    <glob pattern="*.ecma"/>
+  </mime-type>
+  <mime-type type="application/edi-consent"/>
+  <mime-type type="application/edi-x12"/>
+  <mime-type type="application/edifact"/>
+  <mime-type type="application/emma+xml">
+    <glob pattern="*.emma"/>
+  </mime-type>
+  <mime-type type="application/epp+xml"/>
+
+  <mime-type type="application/epub+zip">
+    <acronym>EPUB</acronym>
+    <_comment>Electronic Publication</_comment>
+    <magic priority="50">
+      <match value="PK\003\004" type="string" offset="0">
+        <match value="mimetypeapplication/epub+zip" type="string" offset="30"/>
+      </match>
+    </magic>
+    <glob pattern="*.epub"/>
+  </mime-type>
+
+  <mime-type type="application/eshop"/>
+  <mime-type type="application/example"/>
+  <mime-type type="application/fastinfoset"/>
+  <mime-type type="application/fastsoap"/>
+  <mime-type type="application/fits"/>
+  <mime-type type="application/font-tdpfr">
+    <glob pattern="*.pfr"/>
+  </mime-type>
+  <mime-type type="application/h224"/>
+  <mime-type type="application/http"/>
+  <mime-type type="application/hyperstudio">
+    <glob pattern="*.stk"/>
+  </mime-type>
+  <mime-type type="application/ibe-key-request+xml"/>
+  <mime-type type="application/ibe-pkg-reply+xml"/>
+  <mime-type type="application/ibe-pp-data"/>
+  <mime-type type="application/iges"/>
+  <mime-type type="application/im-iscomposing+xml"/>
+  <mime-type type="application/index"/>
+  <mime-type type="application/index.cmd"/>
+  <mime-type type="application/index.obj"/>
+  <mime-type type="application/index.response"/>
+  <mime-type type="application/index.vnd"/>
+  <mime-type type="application/iotp"/>
+  <mime-type type="application/ipp"/>
+  <mime-type type="application/isup"/>
+
+  <mime-type type="application/java-archive">
+    <sub-class-of type="application/zip"/>
+    <glob pattern="*.jar"/>
+  </mime-type>
+
+  <mime-type type="application/java-serialized-object">
+    <glob pattern="*.ser"/>
+  </mime-type>
+
+  <mime-type type="application/javascript">
+    <sub-class-of type="text/plain"/>
+    <glob pattern="*.js"/>
+  </mime-type>
+
+  <mime-type type="application/json">
+    <sub-class-of type="application/javascript"/>
+    <glob pattern="*.json"/>
+  </mime-type>
+
+  <mime-type type="application/java-vm">
+    <magic priority="40">
+      <match value="0xcafebabe" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.class"/>
+  </mime-type>
+
+  <mime-type type="application/kpml-request+xml"/>
+  <mime-type type="application/kpml-response+xml"/>
+  <mime-type type="application/lost+xml">
+    <glob pattern="*.lostxml"/>
+  </mime-type>
+
+  <mime-type type="application/mac-binhex40">
+    <alias type="application/mac-binhex"/>
+    <alias type="application/binhex"/>
+    <magic priority="50">
+      <match value="must\ be\ converted\ with\ BinHex" type="string" offset="11"/>
+    </magic>
+    <glob pattern="*.hqx"/>
+  </mime-type>
+
+  <mime-type type="application/mac-compactpro">
+    <glob pattern="*.cpt"/>
+  </mime-type>
+
+  <mime-type type="application/macwriteii"/>
+  <mime-type type="application/marc">
+    <glob pattern="*.mrc"/>
+  </mime-type>
+  <mime-type type="application/mathematica">
+    <glob pattern="*.ma"/>
+    <glob pattern="*.nb"/>
+    <glob pattern="*.mb"/>
+  </mime-type>
+  <mime-type type="application/mathml+xml">
+    <glob pattern="*.mathml"/>
+  </mime-type>
+  <mime-type type="application/mbms-associated-procedure-description+xml"/>
+  <mime-type type="application/mbms-deregister+xml"/>
+  <mime-type type="application/mbms-envelope+xml"/>
+  <mime-type type="application/mbms-msk+xml"/>
+  <mime-type type="application/mbms-msk-response+xml"/>
+  <mime-type type="application/mbms-protection-description+xml"/>
+  <mime-type type="application/mbms-reception-report+xml"/>
+  <mime-type type="application/mbms-register+xml"/>
+  <mime-type type="application/mbms-register-response+xml"/>
+  <mime-type type="application/mbms-user-service-description+xml"/>
+  <mime-type type="application/mbox">
+    <sub-class-of type="text/plain"/>
+    <glob pattern="*.mbox"/>
+  </mime-type>
+  <mime-type type="application/media_control+xml"/>
+  <mime-type type="application/mediaservercontrol+xml">
+    <glob pattern="*.mscml"/>
+  </mime-type>
+  <mime-type type="application/mikey"/>
+  <mime-type type="application/moss-keys"/>
+  <mime-type type="application/moss-signature"/>
+  <mime-type type="application/mosskey-data"/>
+  <mime-type type="application/mosskey-request"/>
+  <mime-type type="application/mp4">
+    <glob pattern="*.mp4s"/>
+  </mime-type>
+  <mime-type type="application/mpeg4-generic"/>
+  <mime-type type="application/mpeg4-iod"/>
+  <mime-type type="application/mpeg4-iod-xmt"/>
+
+  <!-- http://www.iana.org/assignments/media-types/application/msword -->
+  <mime-type type="application/msword">
+    <!-- Use org.apache.tika.detect.ContainerAwareDetector for more reliable detection of OLE2 documents -->
+    <alias type="application/vnd.ms-word"/>
+    <_comment>Microsoft Word Document</_comment>
+    <magic priority="50">
+      <match value="Microsoft\ Word\ 6.0\ Document" type="string" offset="2080"/>
+      <match value="Documento\ Microsoft\ Word\ 6" type="string" offset="2080"/>
+      <match value="MSWordDoc" type="string" offset="2112"/>
+      <match value="0x31be0000" type="big32" offset="0"/>
+      <match value="PO^Q`" type="string" offset="0"/>
+      <match value="\376\067\0\043" type="string" offset="0"/>
+      <match value="\333\245-\0\0\0" type="string" offset="0"/>
+      <match value="\354\245\301" type="string" offset="512"/>
+      <match value="\320\317\021\340\241\261\032\341" type="string" offset="0"/>
+      <match value="\224\246\056" type="string" offset="0"/>
+      <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+         <match value="W\x00o\x00r\x00d\x00D\x00o\x00c\x00u\x00m\x00e\x00n\x00t" type="string" offset="1152:4096" />
+      </match>
+    </magic>
+    <glob pattern="*.doc"/>
+    <glob pattern="*.dot"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/mxf">
+    <glob pattern="*.mxf"/>
+  </mime-type>
+  <mime-type type="application/nasdata"/>
+  <mime-type type="application/news-checkgroups"/>
+  <mime-type type="application/news-groupinfo"/>
+  <mime-type type="application/news-transmission"/>
+  <mime-type type="application/nss"/>
+  <mime-type type="application/ocsp-request"/>
+  <mime-type type="application/ocsp-response"/>
+
+  <mime-type type="application/octet-stream">
+    <magic priority="50">
+      <match value="#\ This\ is\ a\ shell\ archive" type="string" offset="10"/>
+      <match value="\037\036" type="string" offset="0"/>
+      <match value="017437" type="host16" offset="0"/>
+      <match value="0x1fff" type="host16" offset="0"/>
+      <match value="\377\037" type="string" offset="0"/>
+      <match value="0145405" type="host16" offset="0"/>
+    </magic>
+    <glob pattern="*.bin"/>
+    <glob pattern="*.dms"/>
+    <glob pattern="*.lha"/>
+    <glob pattern="*.lrf"/>
+    <glob pattern="*.lzh"/>
+    <glob pattern="*.so"/>
+    <glob pattern="*.iso"/>
+    <glob pattern="*.dmg"/>
+    <glob pattern="*.dist"/>
+    <glob pattern="*.distz"/>
+    <glob pattern="*.pkg"/>
+    <glob pattern="*.bpk"/>
+    <glob pattern="*.dump"/>
+    <glob pattern="*.elc"/>
+    <glob pattern="*.deploy"/>
+  </mime-type>
+
+  <mime-type type="application/oda">
+    <glob pattern="*.oda"/>
+  </mime-type>
+  <mime-type type="application/oebps-package+xml">
+    <glob pattern="*.opf"/>
+  </mime-type>
+
+  <mime-type type="application/ogg">
+    <alias type="application/x-ogg"/>
+    <magic priority="50">
+      <match value="OggS" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.ogx"/>
+  </mime-type>
+
+  <mime-type type="application/onenote">
+    <glob pattern="*.onetoc"/>
+    <glob pattern="*.onetoc2"/>
+    <glob pattern="*.onetmp"/>
+    <glob pattern="*.onepkg"/>
+  </mime-type>
+  <mime-type type="application/parityfec"/>
+  <mime-type type="application/patch-ops-error+xml">
+    <glob pattern="*.xer"/>
+  </mime-type>
+
+  <mime-type type="application/pdf">
+    <alias type="application/x-pdf"/>
+    <acronym>PDF</acronym>
+    <_comment>Portable Document Format</_comment>
+    <magic priority="50">
+      <match value="%PDF-" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.pdf"/>
+  </mime-type>
+
+  <mime-type type="application/pgp-encrypted">
+    <glob pattern="*.pgp"/>
+  </mime-type>
+  <mime-type type="application/pgp-keys"/>
+  <mime-type type="application/pgp-signature">
+    <glob pattern="*.asc"/>
+    <glob pattern="*.sig"/>
+  </mime-type>
+  <mime-type type="application/pics-rules">
+    <glob pattern="*.prf"/>
+  </mime-type>
+  <mime-type type="application/pidf+xml"/>
+  <mime-type type="application/pidf-diff+xml"/>
+  <mime-type type="application/pkcs10">
+    <glob pattern="*.p10"/>
+  </mime-type>
+  <mime-type type="application/pkcs7-mime">
+    <glob pattern="*.p7m"/>
+    <glob pattern="*.p7c"/>
+  </mime-type>
+  <mime-type type="application/pkcs7-signature">
+    <glob pattern="*.p7s"/>
+  </mime-type>
+  <mime-type type="application/pkix-cert">
+    <glob pattern="*.cer"/>
+  </mime-type>
+  <mime-type type="application/pkix-crl">
+    <glob pattern="*.crl"/>
+  </mime-type>
+  <mime-type type="application/pkix-pkipath">
+    <glob pattern="*.pkipath"/>
+  </mime-type>
+  <mime-type type="application/pkixcmp">
+    <glob pattern="*.pki"/>
+  </mime-type>
+  <mime-type type="application/pls+xml">
+    <glob pattern="*.pls"/>
+  </mime-type>
+  <mime-type type="application/poc-settings+xml"/>
+
+  <mime-type type="application/postscript">
+    <_comment>PostScript</_comment>
+    <magic priority="50">
+      <match value="%!" type="string" offset="0" />
+      <match value="\004%!" type="string" offset="0" />
+      <!-- Windows format EPS -->
+      <match value="0xc5d0d3c6" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.ai"/>
+    <glob pattern="*.ps"/>
+    <glob pattern="*.eps"/>
+    <glob pattern="*.epsf"/>
+    <glob pattern="*.epsi"/>
+  </mime-type>
+
+  <mime-type type="application/prs.alvestrand.titrax-sheet"/>
+  <mime-type type="application/prs.cww">
+    <glob pattern="*.cww"/>
+  </mime-type>
+  <mime-type type="application/prs.nprend"/>
+  <mime-type type="application/prs.plucker"/>
+  <mime-type type="application/qsig"/>
+
+  <mime-type type="application/rdf+xml">
+    <root-XML localName="RDF"/>
+    <root-XML localName="RDF" namespaceURI="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
+    <sub-class-of type="application/xml"/>
+    <acronym>RDF/XML</acronym>
+    <_comment>XML syntax for RDF graphs</_comment>
+    <glob pattern="*.rdf"/>
+    <glob pattern="*.owl"/>
+    <glob pattern="^rdf$" isregex="true"/>
+    <glob pattern="^owl$" isregex="true"/>
+  </mime-type>
+
+  <mime-type type="application/reginfo+xml">
+    <glob pattern="*.rif"/>
+  </mime-type>
+  <mime-type type="application/relax-ng-compact-syntax">
+    <sub-class-of type="text/plain"/>
+    <glob pattern="*.rnc"/>
+  </mime-type>
+  <mime-type type="application/remote-printing"/>
+  <mime-type type="application/resource-lists+xml">
+    <glob pattern="*.rl"/>
+  </mime-type>
+  <mime-type type="application/resource-lists-diff+xml">
+    <glob pattern="*.rld"/>
+  </mime-type>
+  <mime-type type="application/riscos"/>
+  <mime-type type="application/rlmi+xml"/>
+  <mime-type type="application/rls-services+xml">
+    <glob pattern="*.rs"/>
+  </mime-type>
+  <mime-type type="application/rsd+xml">
+    <glob pattern="*.rsd"/>
+  </mime-type>
+
+  <mime-type type="application/rss+xml">
+    <alias type="text/rss"/>
+    <root-XML localName="rss"/>
+    <root-XML namespaceURI="http://purl.org/rss/1.0/"/>
+    <glob pattern="*.rss"/>
+  </mime-type>
+
+  <mime-type type="application/rtf">
+    <alias type="text/rtf"/>
+    <magic priority="50">
+      <match value="{\\rtf" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.rtf"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="application/rtx"/>
+  <mime-type type="application/samlassertion+xml"/>
+  <mime-type type="application/samlmetadata+xml"/>
+  <mime-type type="application/sbml+xml">
+    <glob pattern="*.sbml"/>
+  </mime-type>
+  <mime-type type="application/scvp-cv-request">
+    <glob pattern="*.scq"/>
+  </mime-type>
+  <mime-type type="application/scvp-cv-response">
+    <glob pattern="*.scs"/>
+  </mime-type>
+  <mime-type type="application/scvp-vp-request">
+    <glob pattern="*.spq"/>
+  </mime-type>
+  <mime-type type="application/scvp-vp-response">
+    <glob pattern="*.spp"/>
+  </mime-type>
+  <mime-type type="application/sdp">
+    <glob pattern="*.sdp"/>
+  </mime-type>
+  <mime-type type="application/set-payment"/>
+  <mime-type type="application/set-payment-initiation">
+    <glob pattern="*.setpay"/>
+  </mime-type>
+  <mime-type type="application/set-registration"/>
+  <mime-type type="application/set-registration-initiation">
+    <glob pattern="*.setreg"/>
+  </mime-type>
+  <mime-type type="application/sgml"/>
+  <mime-type type="application/sgml-open-catalog"/>
+  <mime-type type="application/shf+xml">
+    <glob pattern="*.shf"/>
+  </mime-type>
+  <mime-type type="application/sieve"/>
+  <mime-type type="application/simple-filter+xml"/>
+  <mime-type type="application/simple-message-summary"/>
+  <mime-type type="application/simplesymbolcontainer"/>
+  <mime-type type="application/slate"/>
+  <mime-type type="application/smil"/>
+  <mime-type type="application/smil+xml">
+    <glob pattern="*.smi"/>
+    <glob pattern="*.smil"/>
+  </mime-type>
+  <mime-type type="application/soap+fastinfoset"/>
+  <mime-type type="application/soap+xml"/>
+  <mime-type type="application/sparql-query">
+    <glob pattern="*.rq"/>
+  </mime-type>
+  <mime-type type="application/sparql-results+xml">
+    <glob pattern="*.srx"/>
+  </mime-type>
+  <mime-type type="application/spirits-event+xml"/>
+  <mime-type type="application/srgs">
+    <glob pattern="*.gram"/>
+  </mime-type>
+  <mime-type type="application/srgs+xml">
+    <glob pattern="*.grxml"/>
+  </mime-type>
+  <mime-type type="application/ssml+xml">
+    <glob pattern="*.ssml"/>
+  </mime-type>
+  <mime-type type="application/timestamp-query"/>
+  <mime-type type="application/timestamp-reply"/>
+  <mime-type type="application/tve-trigger"/>
+  <mime-type type="application/ulpfec"/>
+  <mime-type type="application/vemmi"/>
+  <mime-type type="application/vividence.scriptfile"/>
+  <mime-type type="application/vnd.3gpp.bsf+xml"/>
+  <mime-type type="application/vnd.3gpp.pic-bw-large">
+    <glob pattern="*.plb"/>
+  </mime-type>
+  <mime-type type="application/vnd.3gpp.pic-bw-small">
+    <glob pattern="*.psb"/>
+  </mime-type>
+  <mime-type type="application/vnd.3gpp.pic-bw-var">
+    <glob pattern="*.pvb"/>
+  </mime-type>
+  <mime-type type="application/vnd.3gpp.sms"/>
+  <mime-type type="application/vnd.3gpp2.bcmcsinfo+xml"/>
+  <mime-type type="application/vnd.3gpp2.sms"/>
+  <mime-type type="application/vnd.3gpp2.tcap">
+    <glob pattern="*.tcap"/>
+  </mime-type>
+  <mime-type type="application/vnd.3m.post-it-notes">
+    <glob pattern="*.pwn"/>
+  </mime-type>
+  <mime-type type="application/vnd.accpac.simply.aso">
+    <glob pattern="*.aso"/>
+  </mime-type>
+  <mime-type type="application/vnd.accpac.simply.imp">
+    <glob pattern="*.imp"/>
+  </mime-type>
+  <mime-type type="application/vnd.acucobol">
+    <glob pattern="*.acu"/>
+  </mime-type>
+  <mime-type type="application/vnd.acucorp">
+    <glob pattern="*.atc"/>
+    <glob pattern="*.acutc"/>
+  </mime-type>
+  <mime-type type="application/vnd.adobe.air-application-installer-package+zip">
+    <glob pattern="*.air"/>
+  </mime-type>
+  <mime-type type="application/vnd.adobe.xdp+xml">
+    <glob pattern="*.xdp"/>
+  </mime-type>
+  <mime-type type="application/vnd.adobe.xfdf">
+    <glob pattern="*.xfdf"/>
+  </mime-type>
+  <mime-type type="application/vnd.aether.imp"/>
+  <mime-type type="application/vnd.airzip.filesecure.azf">
+    <glob pattern="*.azf"/>
+  </mime-type>
+  <mime-type type="application/vnd.airzip.filesecure.azs">
+    <glob pattern="*.azs"/>
+  </mime-type>
+  <mime-type type="application/vnd.amazon.ebook">
+    <glob pattern="*.azw"/>
+  </mime-type>
+  <mime-type type="application/vnd.americandynamics.acc">
+    <glob pattern="*.acc"/>
+  </mime-type>
+  <mime-type type="application/vnd.amiga.ami">
+    <glob pattern="*.ami"/>
+  </mime-type>
+  <mime-type type="application/vnd.android.package-archive">
+    <glob pattern="*.apk"/>
+  </mime-type>
+  <mime-type type="application/vnd.anser-web-certificate-issue-initiation">
+    <glob pattern="*.cii"/>
+  </mime-type>
+  <mime-type type="application/vnd.anser-web-funds-transfer-initiation">
+    <glob pattern="*.fti"/>
+  </mime-type>
+  <mime-type type="application/vnd.antix.game-component">
+    <glob pattern="*.atx"/>
+  </mime-type>
+  <mime-type type="application/vnd.apple.installer+xml">
+    <glob pattern="*.mpkg"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.apple.iwork">
+    <sub-class-of type="application/zip"/>
+    <glob pattern="*.key"/>
+    <glob pattern="*.pages"/>
+    <glob pattern="*.numbers"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.apple.keynote">
+    <root-XML localName="presentation" namespaceURI="http://developer.apple.com/namespaces/keynote2" />
+  </mime-type>
+  <mime-type type="application/vnd.apple.pages">
+    <root-XML localName="document" namespaceURI="http://developer.apple.com/namespaces/sl" />
+  </mime-type>
+  <mime-type type="application/vnd.apple.numbers">
+    <root-XML localName="document" namespaceURI="http://developer.apple.com/namespaces/ls" />
+  </mime-type>
+  <mime-type type="application/vnd.arastra.swi">
+    <glob pattern="*.swi"/>
+  </mime-type>
+  <mime-type type="application/vnd.audiograph">
+    <glob pattern="*.aep"/>
+  </mime-type>
+  <mime-type type="application/vnd.autopackage"/>
+  <mime-type type="application/vnd.avistar+xml"/>
+  <mime-type type="application/vnd.blueice.multipass">
+    <glob pattern="*.mpm"/>
+  </mime-type>
+  <mime-type type="application/vnd.bluetooth.ep.oob"/>
+  <mime-type type="application/vnd.bmi">
+    <glob pattern="*.bmi"/>
+  </mime-type>
+  <mime-type type="application/vnd.businessobjects">
+    <glob pattern="*.rep"/>
+  </mime-type>
+  <mime-type type="application/vnd.cab-jscript"/>
+  <mime-type type="application/vnd.canon-cpdl"/>
+  <mime-type type="application/vnd.canon-lips"/>
+  <mime-type type="application/vnd.cendio.thinlinc.clientconf"/>
+  <mime-type type="application/vnd.chemdraw+xml">
+    <glob pattern="*.cdxml"/>
+  </mime-type>
+  <mime-type type="application/vnd.chipnuts.karaoke-mmd">
+    <glob pattern="*.mmd"/>
+  </mime-type>
+  <mime-type type="application/vnd.cinderella">
+    <glob pattern="*.cdy"/>
+  </mime-type>
+  <mime-type type="application/vnd.cirpack.isdn-ext"/>
+  <mime-type type="application/vnd.claymore">
+    <glob pattern="*.cla"/>
+  </mime-type>
+  <mime-type type="application/vnd.clonk.c4group">
+    <glob pattern="*.c4g"/>
+    <glob pattern="*.c4d"/>
+    <glob pattern="*.c4f"/>
+    <glob pattern="*.c4p"/>
+    <glob pattern="*.c4u"/>
+  </mime-type>
+  <mime-type type="application/vnd.commerce-battelle"/>
+  <mime-type type="application/vnd.commonspace">
+    <glob pattern="*.csp"/>
+  </mime-type>
+  <mime-type type="application/vnd.contact.cmsg">
+    <glob pattern="*.cdbcmsg"/>
+  </mime-type>
+  <mime-type type="application/vnd.cosmocaller">
+    <glob pattern="*.cmc"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker">
+    <glob pattern="*.clkx"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker.keyboard">
+    <glob pattern="*.clkk"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker.palette">
+    <glob pattern="*.clkp"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker.template">
+    <glob pattern="*.clkt"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker.wordbank">
+    <glob pattern="*.clkw"/>
+  </mime-type>
+  <mime-type type="application/vnd.criticaltools.wbs+xml">
+    <glob pattern="*.wbs"/>
+  </mime-type>
+  <mime-type type="application/vnd.ctc-posml">
+    <glob pattern="*.pml"/>
+  </mime-type>
+  <mime-type type="application/vnd.ctct.ws+xml"/>
+  <mime-type type="application/vnd.cups-pdf"/>
+  <mime-type type="application/vnd.cups-postscript"/>
+  <mime-type type="application/vnd.cups-ppd">
+    <glob pattern="*.ppd"/>
+  </mime-type>
+  <mime-type type="application/vnd.cups-raster"/>
+  <mime-type type="application/vnd.cups-raw"/>
+  <mime-type type="application/vnd.curl.car">
+    <glob pattern="*.car"/>
+  </mime-type>
+  <mime-type type="application/vnd.curl.pcurl">
+    <glob pattern="*.pcurl"/>
+  </mime-type>
+  <mime-type type="application/vnd.cybank"/>
+  <mime-type type="application/vnd.data-vision.rdz">
+    <glob pattern="*.rdz"/>
+  </mime-type>
+  <mime-type type="application/vnd.denovo.fcselayout-link">
+    <glob pattern="*.fe_launch"/>
+  </mime-type>
+  <mime-type type="application/vnd.dir-bi.plate-dl-nosuffix"/>
+  <mime-type type="application/vnd.dna">
+    <glob pattern="*.dna"/>
+  </mime-type>
+  <mime-type type="application/vnd.dolby.mlp">
+    <glob pattern="*.mlp"/>
+  </mime-type>
+  <mime-type type="application/vnd.dolby.mobile.1"/>
+  <mime-type type="application/vnd.dolby.mobile.2"/>
+  <mime-type type="application/vnd.dpgraph">
+    <glob pattern="*.dpg"/>
+  </mime-type>
+  <mime-type type="application/vnd.dreamfactory">
+    <glob pattern="*.dfac"/>
+  </mime-type>
+  <mime-type type="application/vnd.dvb.esgcontainer"/>
+  <mime-type type="application/vnd.dvb.ipdcdftnotifaccess"/>
+  <mime-type type="application/vnd.dvb.ipdcesgaccess"/>
+  <mime-type type="application/vnd.dvb.ipdcroaming"/>
+  <mime-type type="application/vnd.dvb.iptv.alfec-base"/>
+  <mime-type type="application/vnd.dvb.iptv.alfec-enhancement"/>
+  <mime-type type="application/vnd.dvb.notif-aggregate-root+xml"/>
+  <mime-type type="application/vnd.dvb.notif-container+xml"/>
+  <mime-type type="application/vnd.dvb.notif-generic+xml"/>
+  <mime-type type="application/vnd.dvb.notif-ia-msglist+xml"/>
+  <mime-type type="application/vnd.dvb.notif-ia-registration-request+xml"/>
+  <mime-type type="application/vnd.dvb.notif-ia-registration-response+xml"/>
+  <mime-type type="application/vnd.dvb.notif-init+xml"/>
+  <mime-type type="application/vnd.dxr"/>
+  <mime-type type="application/vnd.dynageo">
+    <glob pattern="*.geo"/>
+  </mime-type>
+  <mime-type type="application/vnd.ecdis-update"/>
+  <mime-type type="application/vnd.ecowin.chart">
+    <glob pattern="*.mag"/>
+  </mime-type>
+  <mime-type type="application/vnd.ecowin.filerequest"/>
+  <mime-type type="application/vnd.ecowin.fileupdate"/>
+  <mime-type type="application/vnd.ecowin.series"/>
+  <mime-type type="application/vnd.ecowin.seriesrequest"/>
+  <mime-type type="application/vnd.ecowin.seriesupdate"/>
+  <mime-type type="application/vnd.emclient.accessrequest+xml"/>
+  <mime-type type="application/vnd.enliven">
+    <glob pattern="*.nml"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.esf">
+    <glob pattern="*.esf"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.msf">
+    <glob pattern="*.msf"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.quickanime">
+    <glob pattern="*.qam"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.salt">
+    <glob pattern="*.slt"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.ssf">
+    <glob pattern="*.ssf"/>
+  </mime-type>
+  <mime-type type="application/vnd.ericsson.quickcall"/>
+  <mime-type type="application/vnd.eszigno3+xml">
+    <glob pattern="*.es3"/>
+    <glob pattern="*.et3"/>
+  </mime-type>
+  <mime-type type="application/vnd.etsi.aoc+xml"/>
+  <mime-type type="application/vnd.etsi.cug+xml"/>
+  <mime-type type="application/vnd.etsi.iptvcommand+xml"/>
+  <mime-type type="application/vnd.etsi.iptvdiscovery+xml"/>
+  <mime-type type="application/vnd.etsi.iptvprofile+xml"/>
+  <mime-type type="application/vnd.etsi.iptvsad-bc+xml"/>
+  <mime-type type="application/vnd.etsi.iptvsad-cod+xml"/>
+  <mime-type type="application/vnd.etsi.iptvsad-npvr+xml"/>
+  <mime-type type="application/vnd.etsi.iptvueprofile+xml"/>
+  <mime-type type="application/vnd.etsi.mcid+xml"/>
+  <mime-type type="application/vnd.etsi.sci+xml"/>
+  <mime-type type="application/vnd.etsi.simservs+xml"/>
+  <mime-type type="application/vnd.eudora.data"/>
+  <mime-type type="application/vnd.ezpix-album">
+    <glob pattern="*.ez2"/>
+  </mime-type>
+  <mime-type type="application/vnd.ezpix-package">
+    <glob pattern="*.ez3"/>
+  </mime-type>
+  <mime-type type="application/vnd.f-secure.mobile"/>
+  <mime-type type="application/vnd.fdf">
+    <glob pattern="*.fdf"/>
+  </mime-type>
+  <mime-type type="application/vnd.fdsn.mseed">
+    <glob pattern="*.mseed"/>
+  </mime-type>
+  <mime-type type="application/vnd.fdsn.seed">
+    <glob pattern="*.seed"/>
+    <glob pattern="*.dataless"/>
+  </mime-type>
+  <mime-type type="application/vnd.ffsns"/>
+  <mime-type type="application/vnd.fints"/>
+  <mime-type type="application/vnd.flographit">
+    <glob pattern="*.gph"/>
+  </mime-type>
+  <mime-type type="application/vnd.fluxtime.clip">
+    <glob pattern="*.ftc"/>
+  </mime-type>
+  <mime-type type="application/vnd.font-fontforge-sfd"/>
+  <mime-type type="application/vnd.framemaker">
+    <glob pattern="*.fm"/>
+    <glob pattern="*.frame"/>
+    <glob pattern="*.maker"/>
+    <glob pattern="*.book"/>
+  </mime-type>
+  <mime-type type="application/vnd.frogans.fnc">
+    <glob pattern="*.fnc"/>
+  </mime-type>
+  <mime-type type="application/vnd.frogans.ltf">
+    <glob pattern="*.ltf"/>
+  </mime-type>
+  <mime-type type="application/vnd.fsc.weblaunch">
+    <glob pattern="*.fsc"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasys">
+    <glob pattern="*.oas"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasys2">
+    <glob pattern="*.oa2"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasys3">
+    <glob pattern="*.oa3"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasysgp">
+    <glob pattern="*.fg5"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasysprs">
+    <glob pattern="*.bh2"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujixerox.art-ex"/>
+  <mime-type type="application/vnd.fujixerox.art4"/>
+  <mime-type type="application/vnd.fujixerox.hbpl"/>
+  <mime-type type="application/vnd.fujixerox.ddd">
+    <glob pattern="*.ddd"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujixerox.docuworks">
+    <glob pattern="*.xdw"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujixerox.docuworks.binder">
+    <glob pattern="*.xbd"/>
+  </mime-type>
+  <mime-type type="application/vnd.fut-misnet"/>
+  <mime-type type="application/vnd.fuzzysheet">
+    <glob pattern="*.fzs"/>
+  </mime-type>
+  <mime-type type="application/vnd.genomatix.tuxedo">
+    <glob pattern="*.txd"/>
+  </mime-type>
+  <mime-type type="application/vnd.geogebra.file">
+    <glob pattern="*.ggb"/>
+  </mime-type>
+  <mime-type type="application/vnd.geogebra.tool">
+    <glob pattern="*.ggt"/>
+  </mime-type>
+  <mime-type type="application/vnd.geometry-explorer">
+    <glob pattern="*.gex"/>
+    <glob pattern="*.gre"/>
+  </mime-type>
+  <mime-type type="application/vnd.gmx">
+    <glob pattern="*.gmx"/>
+  </mime-type>
+  <mime-type type="application/vnd.google-earth.kml+xml">
+    <glob pattern="*.kml"/>
+  </mime-type>
+  <mime-type type="application/vnd.google-earth.kmz">
+    <glob pattern="*.kmz"/>
+  </mime-type>
+  <mime-type type="application/vnd.grafeq">
+    <glob pattern="*.gqf"/>
+    <glob pattern="*.gqs"/>
+  </mime-type>
+  <mime-type type="application/vnd.gridmp"/>
+  <mime-type type="application/vnd.groove-account">
+    <glob pattern="*.gac"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-help">
+    <glob pattern="*.ghf"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-identity-message">
+    <glob pattern="*.gim"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-injector">
+    <glob pattern="*.grv"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-tool-message">
+    <glob pattern="*.gtm"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-tool-template">
+    <glob pattern="*.tpl"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-vcard">
+    <glob pattern="*.vcg"/>
+  </mime-type>
+  <mime-type type="application/vnd.handheld-entertainment+xml">
+    <glob pattern="*.zmm"/>
+  </mime-type>
+  <mime-type type="application/vnd.hbci">
+    <glob pattern="*.hbci"/>
+  </mime-type>
+  <mime-type type="application/vnd.hcl-bireports"/>
+  <mime-type type="application/vnd.hhe.lesson-player">
+    <glob pattern="*.les"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-hpgl">
+    <glob pattern="*.hpgl"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-hpid">
+    <glob pattern="*.hpid"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-hps">
+    <glob pattern="*.hps"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-jlyt">
+    <glob pattern="*.jlt"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-pcl">
+    <glob pattern="*.pcl"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-pclxl">
+    <glob pattern="*.pclxl"/>
+  </mime-type>
+  <mime-type type="application/vnd.httphone"/>
+  <mime-type type="application/vnd.hydrostatix.sof-data">
+    <glob pattern="*.sfd-hdstx"/>
+  </mime-type>
+  <mime-type type="application/vnd.hzn-3d-crossword">
+    <glob pattern="*.x3d"/>
+  </mime-type>
+  <mime-type type="application/vnd.ibm.afplinedata"/>
+  <mime-type type="application/vnd.ibm.electronic-media"/>
+  <mime-type type="application/vnd.ibm.minipay">
+    <glob pattern="*.mpy"/>
+  </mime-type>
+  <mime-type type="application/vnd.ibm.modcap">
+    <glob pattern="*.afp"/>
+    <glob pattern="*.listafp"/>
+    <glob pattern="*.list3820"/>
+  </mime-type>
+  <mime-type type="application/vnd.ibm.rights-management">
+    <glob pattern="*.irm"/>
+  </mime-type>
+  <mime-type type="application/vnd.ibm.secure-container">
+    <glob pattern="*.sc"/>
+  </mime-type>
+  <mime-type type="application/vnd.iccprofile">
+    <glob pattern="*.icc"/>
+    <glob pattern="*.icm"/>
+  </mime-type>
+  <mime-type type="application/vnd.igloader">
+    <glob pattern="*.igl"/>
+  </mime-type>
+  <mime-type type="application/vnd.immervision-ivp">
+    <glob pattern="*.ivp"/>
+  </mime-type>
+  <mime-type type="application/vnd.immervision-ivu">
+    <glob pattern="*.ivu"/>
+  </mime-type>
+  <mime-type type="application/vnd.informedcontrol.rms+xml"/>
+  <mime-type type="application/vnd.informix-visionary"/>
+  <mime-type type="application/vnd.intercon.formnet">
+    <glob pattern="*.xpw"/>
+    <glob pattern="*.xpx"/>
+  </mime-type>
+  <mime-type type="application/vnd.intertrust.digibox"/>
+  <mime-type type="application/vnd.intertrust.nncp"/>
+  <mime-type type="application/vnd.intu.qbo">
+    <glob pattern="*.qbo"/>
+  </mime-type>
+  <mime-type type="application/vnd.intu.qfx">
+    <glob pattern="*.qfx"/>
+  </mime-type>
+  <mime-type type="application/vnd.iptc.g2.conceptitem+xml"/>
+  <mime-type type="application/vnd.iptc.g2.knowledgeitem+xml"/>
+  <mime-type type="application/vnd.iptc.g2.newsitem+xml"/>
+  <mime-type type="application/vnd.iptc.g2.packageitem+xml"/>
+  <mime-type type="application/vnd.ipunplugged.rcprofile">
+    <glob pattern="*.rcprofile"/>
+  </mime-type>
+  <mime-type type="application/vnd.irepository.package+xml">
+    <glob pattern="*.irp"/>
+  </mime-type>
+  <mime-type type="application/vnd.is-xpr">
+    <glob pattern="*.xpr"/>
+  </mime-type>
+  <mime-type type="application/vnd.jam">
+    <glob pattern="*.jam"/>
+  </mime-type>
+  <mime-type type="application/vnd.japannet-directory-service"/>
+  <mime-type type="application/vnd.japannet-jpnstore-wakeup"/>
+  <mime-type type="application/vnd.japannet-payment-wakeup"/>
+  <mime-type type="application/vnd.japannet-registration"/>
+  <mime-type type="application/vnd.japannet-registration-wakeup"/>
+  <mime-type type="application/vnd.japannet-setstore-wakeup"/>
+  <mime-type type="application/vnd.japannet-verification"/>
+  <mime-type type="application/vnd.japannet-verification-wakeup"/>
+  <mime-type type="application/vnd.jcp.javame.midlet-rms">
+    <glob pattern="*.rms"/>
+  </mime-type>
+  <mime-type type="application/vnd.jisp">
+    <glob pattern="*.jisp"/>
+  </mime-type>
+  <mime-type type="application/vnd.joost.joda-archive">
+    <glob pattern="*.joda"/>
+  </mime-type>
+  <mime-type type="application/vnd.kahootz">
+    <glob pattern="*.ktz"/>
+    <glob pattern="*.ktr"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.karbon">
+    <glob pattern="*.karbon"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kchart">
+    <glob pattern="*.chrt"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kformula">
+    <glob pattern="*.kfo"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kivio">
+    <glob pattern="*.flw"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kontour">
+    <glob pattern="*.kon"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kpresenter">
+    <glob pattern="*.kpr"/>
+    <glob pattern="*.kpt"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kspread">
+    <glob pattern="*.ksp"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kword">
+    <glob pattern="*.kwd"/>
+    <glob pattern="*.kwt"/>
+  </mime-type>
+  <mime-type type="application/vnd.kenameaapp">
+    <glob pattern="*.htke"/>
+  </mime-type>
+  <mime-type type="application/vnd.kidspiration">
+    <glob pattern="*.kia"/>
+  </mime-type>
+  <mime-type type="application/vnd.kinar">
+    <glob pattern="*.kne"/>
+    <glob pattern="*.knp"/>
+  </mime-type>
+  <mime-type type="application/vnd.koan">
+    <alias type="application/x-koan"/>
+    <_comment>SSEYO Koan File</_comment>
+    <glob pattern="*.skp"/>
+    <glob pattern="*.skd"/>
+    <glob pattern="*.skt"/>
+    <glob pattern="*.skm"/>
+  </mime-type>
+  <mime-type type="application/vnd.kodak-descriptor">
+    <glob pattern="*.sse"/>
+  </mime-type>
+  <mime-type type="application/vnd.liberty-request+xml"/>
+  <mime-type type="application/vnd.llamagraphics.life-balance.desktop">
+    <glob pattern="*.lbd"/>
+  </mime-type>
+  <mime-type type="application/vnd.llamagraphics.life-balance.exchange+xml">
+    <glob pattern="*.lbe"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-1-2-3">
+    <glob pattern="*.123"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-approach">
+    <glob pattern="*.apr"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-freelance">
+    <glob pattern="*.pre"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-notes">
+    <glob pattern="*.nsf"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-organizer">
+    <glob pattern="*.org"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-screencam">
+    <glob pattern="*.scm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.lotus-wordpro">
+    <magic priority="50">
+      <match value="WordPro\0" type="string" offset="0" />
+      <match value="WordPro\r\373" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.lwp"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.macports.portpkg">
+    <glob pattern="*.portpkg"/>
+  </mime-type>
+  <mime-type type="application/vnd.marlin.drm.actiontoken+xml"/>
+  <mime-type type="application/vnd.marlin.drm.conftoken+xml"/>
+  <mime-type type="application/vnd.marlin.drm.license+xml"/>
+  <mime-type type="application/vnd.marlin.drm.mdcf"/>
+  <mime-type type="application/vnd.mcd">
+    <glob pattern="*.mcd"/>
+  </mime-type>
+  <mime-type type="application/vnd.medcalcdata">
+    <glob pattern="*.mc1"/>
+  </mime-type>
+  <mime-type type="application/vnd.mediastation.cdkey">
+    <glob pattern="*.cdkey"/>
+  </mime-type>
+  <mime-type type="application/vnd.meridian-slingshot"/>
+  <mime-type type="application/vnd.mfer">
+    <glob pattern="*.mwf"/>
+  </mime-type>
+  <mime-type type="application/vnd.mfmp">
+    <glob pattern="*.mfm"/>
+  </mime-type>
+  <mime-type type="application/vnd.micrografx.flo">
+    <glob pattern="*.flo"/>
+  </mime-type>
+  <mime-type type="application/vnd.micrografx.igx">
+    <glob pattern="*.igx"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.mif">
+    <_comment>FrameMaker MIF document</_comment>
+    <alias type="application/x-mif"/>
+    <alias type="application/x-frame"/>
+    <magic priority="50">
+      <match value="\&lt;MakerFile" type="string" offset="0" />
+      <match value="\&lt;MIFFile" type="string" offset="0" />
+      <match value="\&lt;MakerDictionary" type="string" offset="0" />
+      <match value="\&lt;MakerScreenFont" type="string" offset="0" />
+      <match value="\&lt;MML" type="string" offset="0" />
+      <match value="\&lt;Book" type="string" offset="0" />
+      <match value="\&lt;Maker" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.mif"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.minisoft-hp3000-save"/>
+  <mime-type type="application/vnd.mitsubishi.misty-guard.trustweb"/>
+  <mime-type type="application/vnd.mobius.daf">
+    <glob pattern="*.daf"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.dis">
+    <glob pattern="*.dis"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.mbk">
+    <glob pattern="*.mbk"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.mqy">
+    <glob pattern="*.mqy"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.msl">
+    <glob pattern="*.msl"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.plc">
+    <glob pattern="*.plc"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.txf">
+    <glob pattern="*.txf"/>
+  </mime-type>
+  <mime-type type="application/vnd.mophun.application">
+    <glob pattern="*.mpn"/>
+  </mime-type>
+  <mime-type type="application/vnd.mophun.certificate">
+    <glob pattern="*.mpc"/>
+  </mime-type>
+  <mime-type type="application/vnd.motorola.flexsuite"/>
+  <mime-type type="application/vnd.motorola.flexsuite.adsi"/>
+  <mime-type type="application/vnd.motorola.flexsuite.fis"/>
+  <mime-type type="application/vnd.motorola.flexsuite.gotap"/>
+  <mime-type type="application/vnd.motorola.flexsuite.kmr"/>
+  <mime-type type="application/vnd.motorola.flexsuite.ttc"/>
+  <mime-type type="application/vnd.motorola.flexsuite.wem"/>
+  <mime-type type="application/vnd.motorola.iprm"/>
+  <mime-type type="application/vnd.mozilla.xul+xml">
+    <glob pattern="*.xul"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-artgalry">
+    <glob pattern="*.cil"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-asf"/>
+  <mime-type type="application/vnd.ms-cab-compressed">
+    <glob pattern="*.cab"/>
+  </mime-type>
+
+  <!-- http://www.iana.org/assignments/media-types/application/vnd.ms-excel -->
+  <mime-type type="application/vnd.ms-excel">
+    <!-- Use org.apache.tika.detect.ContainerAwareDetector for more reliable detection of OLE2 documents -->
+    <alias type="application/msexcel" />
+    <_comment>Microsoft Excel Spreadsheet</_comment>
+    <magic priority="50">
+      <match value="Microsoft\ Excel\ 5.0\ Worksheet" type="string" offset="2080"/>
+      <match value="Foglio\ di\ lavoro\ Microsoft\ Exce" type="string" offset="2080"/>
+      <match value="Biff5" type="string" offset="2114"/>
+      <match value="Biff5" type="string" offset="2121"/>
+      <match value="\x09\x04\x06\x00\x00\x00\x10\x00" type="string" offset="0"/>
+      <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+         <match value="W\x00o\x00r\x00k\x00b\x00o\x00o\x00k" type="string" offset="1152:4096" />
+      </match>
+    </magic>
+    <glob pattern="*.xls"/>
+    <glob pattern="*.xlm"/>
+    <glob pattern="*.xla"/>
+    <glob pattern="*.xlc"/>
+    <glob pattern="*.xlt"/>
+    <glob pattern="*.xlw"/>
+    <glob pattern="*.xll"/>
+    <glob pattern="*.xld"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.addin.macroenabled.12">
+    <_comment>Office Open XML Workbook Add-in (macro-enabled)</_comment>
+    <glob pattern="*.xlam"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.sheet.macroenabled.12">
+    <_comment>Office Open XML Workbook (macro-enabled)</_comment>
+    <glob pattern="*.xlsm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.sheet.binary.macroenabled.12">
+    <_comment>Microsoft Excel 2007 Binary Spreadsheet</_comment>
+    <glob pattern="*.xlsb"/>
+    <sub-class-of type="application/vnd.ms-excel"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.template.macroenabled.12">
+    <glob pattern="*.xltm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-fontobject">
+    <glob pattern="*.eot"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-htmlhelp">
+    <glob pattern="*.chm"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-ims">
+    <glob pattern="*.ims"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-lrm">
+    <glob pattern="*.lrm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-outlook">
+    <_comment>Microsoft Outlook Message</_comment>
+    <glob pattern="*.msg" />
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-pki.seccat">
+    <glob pattern="*.cat"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-pki.stl">
+    <glob pattern="*.stl"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-playready.initiator+xml"/>
+
+  <!-- http://www.iana.org/assignments/media-types/application/vnd.ms-powerpoint -->
+  <mime-type type="application/vnd.ms-powerpoint">
+    <!-- Use org.apache.tika.detect.ContainerAwareDetector for more reliable detection of OLE2 documents -->
+    <alias type="application/mspowerpoint"/>
+    <_comment>Microsoft Powerpoint Presentation</_comment>
+    <magic priority="50">
+      <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+         <match value="P\x00o\x00w\x00e\x00r\x00P\x00o\x00i\x00n\x00t\x00 D\x00o\x00c\x00u\x00m\x00e\x00n\x00t" type="string" offset="1152:4096" />
+      </match>
+    </magic>
+    <glob pattern="*.ppz"/>
+    <glob pattern="*.ppt"/>
+    <glob pattern="*.pps"/>
+    <glob pattern="*.pot"/>
+    <glob pattern="*.ppa"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.addin.macroenabled.12">
+    <_comment>Office Open XML Presentation Add-in (macro-enabled)</_comment>
+    <glob pattern="*.ppam"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.presentation.macroenabled.12">
+    <_comment>Office Open XML Presentation (macro-enabled)</_comment>
+    <glob pattern="*.pptm"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.slide.macroenabled.12">
+    <glob pattern="*.sldm"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.slideshow.macroenabled.12">
+    <_comment>Office Open XML Presentation Slideshow (macro-enabled)</_comment>
+    <glob pattern="*.ppsm"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.template.macroenabled.12">
+    <glob pattern="*.potm"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-project">
+    <glob pattern="*.mpp"/>
+    <glob pattern="*.mpt"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-tnef">
+    <alias type="application/ms-tnef" />
+    <magic priority="50">
+      <match value="0x223e9f78" type="little16" offset="0" />
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-wmdrm.lic-chlg-req"/>
+  <mime-type type="application/vnd.ms-wmdrm.lic-resp"/>
+  <mime-type type="application/vnd.ms-wmdrm.meter-chlg-req"/>
+  <mime-type type="application/vnd.ms-wmdrm.meter-resp"/>
+
+  <mime-type type="application/vnd.ms-word.document.macroenabled.12">
+    <_comment>Office Open XML Document (macro-enabled)</_comment>
+    <glob pattern="*.docm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-word.template.macroenabled.12">
+    <_comment>Office Open XML Document Template (macro-enabled)</_comment>
+    <glob pattern="*.dotm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-works">
+    <glob pattern="*.wps"/>
+    <glob pattern="*.wks"/>
+    <glob pattern="*.wcm"/>
+    <glob pattern="*.wdb"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-wpl">
+    <glob pattern="*.wpl"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-xpsdocument">
+    <glob pattern="*.xps"/>
+  </mime-type>
+  <mime-type type="application/vnd.mseq">
+    <glob pattern="*.mseq"/>
+  </mime-type>
+  <mime-type type="application/vnd.msign"/>
+  <mime-type type="application/vnd.multiad.creator"/>
+  <mime-type type="application/vnd.multiad.creator.cif"/>
+  <mime-type type="application/vnd.music-niff"/>
+  <mime-type type="application/vnd.musician">
+    <glob pattern="*.mus"/>
+  </mime-type>
+  <mime-type type="application/vnd.muvee.style">
+    <glob pattern="*.msty"/>
+  </mime-type>
+  <mime-type type="application/vnd.ncd.control"/>
+  <mime-type type="application/vnd.ncd.reference"/>
+  <mime-type type="application/vnd.nervana"/>
+  <mime-type type="application/vnd.netfpx"/>
+  <mime-type type="application/vnd.neurolanguage.nlu">
+    <glob pattern="*.nlu"/>
+  </mime-type>
+  <mime-type type="application/vnd.noblenet-directory">
+    <glob pattern="*.nnd"/>
+  </mime-type>
+  <mime-type type="application/vnd.noblenet-sealer">
+    <glob pattern="*.nns"/>
+  </mime-type>
+  <mime-type type="application/vnd.noblenet-web">
+    <glob pattern="*.nnw"/>
+  </mime-type>
+  <mime-type type="application/vnd.nokia.catalogs"/>
+  <mime-type type="application/vnd.nokia.conml+wbxml"/>
+  <mime-type type="application/vnd.nokia.conml+xml"/>
+  <mime-type type="application/vnd.nokia.isds-radio-presets"/>
+  <mime-type type="application/vnd.nokia.iptv.config+xml"/>
+  <mime-type type="application/vnd.nokia.landmark+wbxml"/>
+  <mime-type type="application/vnd.nokia.landmark+xml"/>
+  <mime-type type="application/vnd.nokia.landmarkcollection+xml"/>
+  <mime-type type="application/vnd.nokia.n-gage.ac+xml"/>
+  <mime-type type="application/vnd.nokia.n-gage.data">
+    <glob pattern="*.ngdat"/>
+  </mime-type>
+  <mime-type type="application/vnd.nokia.n-gage.symbian.install">
+    <glob pattern="*.n-gage"/>
+  </mime-type>
+  <mime-type type="application/vnd.nokia.ncd"/>
+  <mime-type type="application/vnd.nokia.pcd+wbxml"/>
+  <mime-type type="application/vnd.nokia.pcd+xml"/>
+  <mime-type type="application/vnd.nokia.radio-preset">
+    <glob pattern="*.rpst"/>
+  </mime-type>
+  <mime-type type="application/vnd.nokia.radio-presets">
+    <glob pattern="*.rpss"/>
+  </mime-type>
+  <mime-type type="application/vnd.novadigm.edm">
+    <glob pattern="*.edm"/>
+  </mime-type>
+  <mime-type type="application/vnd.novadigm.edx">
+    <glob pattern="*.edx"/>
+  </mime-type>
+  <mime-type type="application/vnd.novadigm.ext">
+    <glob pattern="*.ext"/>
+  </mime-type>
+
+  <!-- =================================================================== -->
+  <!-- Open Document Format for Office Applications (OpenDocument) v1.0    -->
+  <!-- http://www.oasis-open.org/specs/index.php#opendocumentv1.0          -->
+  <!-- =================================================================== -->
+
+  <mime-type type="application/vnd.oasis.opendocument.chart">
+    <alias type="application/x-vnd.oasis.opendocument.chart"/>
+    <_comment>OpenDocument v1.0: Chart document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.chart"/>
+      </match>
+    </magic>
+    <glob pattern="*.odc"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.chart-template">
+    <alias type="application/x-vnd.oasis.opendocument.chart-template"/>
+    <_comment>OpenDocument v1.0: Chart document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.chart-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.otc"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.database">
+    <glob pattern="*.odb"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.formula">
+    <alias type="application/x-vnd.oasis.opendocument.formula"/>
+    <_comment>OpenDocument v1.0: Formula document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.formula" />
+      </match>
+    </magic>
+    <glob pattern="*.odf"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.formula-template">
+    <alias type="application/x-vnd.oasis.opendocument.formula-template"/>
+    <_comment>OpenDocument v1.0: Formula document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.formula-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.odft"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.graphics">
+    <alias type="application/x-vnd.oasis.opendocument.graphics"/>
+    <_comment>OpenDocument v1.0: Graphics document (Drawing)</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.graphics"/>
+      </match>
+    </magic>
+    <glob pattern="*.odg"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.graphics-template">
+    <alias type="application/x-vnd.oasis.opendocument.graphics-template"/>
+    <_comment>OpenDocument v1.0: Graphics document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.graphics-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.otg"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.image">
+    <alias type="application/x-vnd.oasis.opendocument.image"/>
+    <_comment>OpenDocument v1.0: Image document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.image"/>
+      </match>
+    </magic>
+    <glob pattern="*.odi"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.image-template">
+    <alias type="application/x-vnd.oasis.opendocument.image-template"/>
+    <_comment>OpenDocument v1.0: Image document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.image-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.oti"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.presentation">
+    <alias type="application/x-vnd.oasis.opendocument.presentation"/>
+    <_comment>OpenDocument v1.0: Presentation document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.presentation"/>
+      </match>
+    </magic>
+    <glob pattern="*.odp"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.presentation-template">
+    <alias type="application/x-vnd.oasis.opendocument.presentation-template"/>
+    <_comment>OpenDocument v1.0: Presentation document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+              value="mimetypeapplication/vnd.oasis.opendocument.presentation-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.otp"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.spreadsheet">
+    <alias type="application/x-vnd.oasis.opendocument.spreadsheet"/>
+    <_comment>OpenDocument v1.0: Spreadsheet document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.spreadsheet"/>
+      </match>
+    </magic>
+    <glob pattern="*.ods"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.spreadsheet-template">
+    <alias type="application/x-vnd.oasis.opendocument.spreadsheet-template"/>
+    <_comment>OpenDocument v1.0: Spreadsheet document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.spreadsheet-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.ots"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.text">
+    <alias type="application/x-vnd.oasis.opendocument.text"/>
+    <_comment>OpenDocument v1.0: Text document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.text"/>
+      </match>
+    </magic>
+    <glob pattern="*.odt"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.text-master">
+    <alias type="application/x-vnd.oasis.opendocument.text-master"/>
+    <_comment>OpenDocument v1.0: Global Text document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.text-master"/>
+      </match>
+    </magic>
+    <glob pattern="*.otm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.text-template">
+    <alias type="application/x-vnd.oasis.opendocument.text-template"/>
+    <_comment>OpenDocument v1.0: Text document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+              value="mimetypeapplication/vnd.oasis.opendocument.text-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.ott"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.text-web">
+    <alias type="application/x-vnd.oasis.opendocument.text-web"/>
+    <_comment>OpenDocument v1.0: Text document used as template for HTML documents</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+              value="mimetypeapplication/vnd.oasis.opendocument.text-web"/>
+      </match>
+    </magic>
+    <glob pattern="*.oth"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.obn"/>
+  <mime-type type="application/vnd.olpc-sugar">
+    <glob pattern="*.xo"/>
+  </mime-type>
+  <mime-type type="application/vnd.oma-scws-config"/>
+  <mime-type type="application/vnd.oma-scws-http-request"/>
+  <mime-type type="application/vnd.oma-scws-http-response"/>
+  <mime-type type="application/vnd.oma.bcast.associated-procedure-parameter+xml"/>
+  <mime-type type="application/vnd.oma.bcast.drm-trigger+xml"/>
+  <mime-type type="application/vnd.oma.bcast.imd+xml"/>
+  <mime-type type="application/vnd.oma.bcast.ltkm"/>
+  <mime-type type="application/vnd.oma.bcast.notification+xml"/>
+  <mime-type type="application/vnd.oma.bcast.provisioningtrigger"/>
+  <mime-type type="application/vnd.oma.bcast.sgboot"/>
+  <mime-type type="application/vnd.oma.bcast.sgdd+xml"/>
+  <mime-type type="application/vnd.oma.bcast.sgdu"/>
+  <mime-type type="application/vnd.oma.bcast.simple-symbol-container"/>
+  <mime-type type="application/vnd.oma.bcast.smartcard-trigger+xml"/>
+  <mime-type type="application/vnd.oma.bcast.sprov+xml"/>
+  <mime-type type="application/vnd.oma.bcast.stkm"/>
+  <mime-type type="application/vnd.oma.dcd"/>
+  <mime-type type="application/vnd.oma.dcdc"/>
+  <mime-type type="application/vnd.oma.dd2+xml">
+    <glob pattern="*.dd2"/>
+  </mime-type>
+  <mime-type type="application/vnd.oma.drm.risd+xml"/>
+  <mime-type type="application/vnd.oma.group-usage-list+xml"/>
+  <mime-type type="application/vnd.oma.poc.detailed-progress-report+xml"/>
+  <mime-type type="application/vnd.oma.poc.final-report+xml"/>
+  <mime-type type="application/vnd.oma.poc.groups+xml"/>
+  <mime-type type="application/vnd.oma.poc.invocation-descriptor+xml"/>
+  <mime-type type="application/vnd.oma.poc.optimized-progress-report+xml"/>
+  <mime-type type="application/vnd.oma.xcap-directory+xml"/>
+  <mime-type type="application/vnd.omads-email+xml"/>
+  <mime-type type="application/vnd.omads-file+xml"/>
+  <mime-type type="application/vnd.omads-folder+xml"/>
+  <mime-type type="application/vnd.omaloc-supl-init"/>
+
+  <mime-type type="application/vnd.openofficeorg.extension">
+    <glob pattern="*.oxt"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.presentation">
+    <_comment>Office Open XML Presentation</_comment>
+    <glob pattern="*.pptx"/>
+    <glob pattern="*.thmx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slide">
+    <glob pattern="*.sldx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slideshow">
+    <glob pattern="*.ppsx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.template">
+    <_comment>Office Open XML Presentation Template</_comment>
+    <glob pattern="*.potx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slideshow">
+    <_comment>Office Open XML Presentation Slideshow</_comment>
+    <glob pattern="*.ppsx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
+    <_comment>Office Open XML Workbook</_comment>
+    <glob pattern="*.xlsx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.spreadsheetml.template">
+    <_comment>Office Open XML Workbook Template</_comment>
+    <glob pattern="*.xltx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.template.macroenabled.12">
+    <_comment>Office Open XML Workbook Template (macro-enabled)</_comment>
+    <glob pattern="*.xltm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.document">
+    <_comment>Office Open XML Document</_comment>
+    <glob pattern="*.docx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.template">
+    <_comment>Office Open XML Document Template</_comment>
+    <glob pattern="*.dotx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.osa.netdeploy"/>
+  <mime-type type="application/vnd.osgi.bundle"/>
+  <mime-type type="application/vnd.osgi.dp">
+    <glob pattern="*.dp"/>
+  </mime-type>
+  <mime-type type="application/vnd.otps.ct-kip+xml"/>
+  <mime-type type="application/vnd.palm">
+    <glob pattern="*.pdb"/>
+    <glob pattern="*.pqa"/>
+    <glob pattern="*.oprc"/>
+  </mime-type>
+  <mime-type type="application/vnd.paos.xml"/>
+  <mime-type type="application/vnd.pg.format">
+    <glob pattern="*.str"/>
+  </mime-type>
+  <mime-type type="application/vnd.pg.osasli">
+    <glob pattern="*.ei6"/>
+  </mime-type>
+  <mime-type type="application/vnd.piaccess.application-licence"/>
+  <mime-type type="application/vnd.picsel">
+    <glob pattern="*.efif"/>
+  </mime-type>
+  <mime-type type="application/vnd.poc.group-advertisement+xml"/>
+  <mime-type type="application/vnd.pocketlearn">
+    <glob pattern="*.plf"/>
+  </mime-type>
+  <mime-type type="application/vnd.powerbuilder6">
+    <glob pattern="*.pbd"/>
+  </mime-type>
+  <mime-type type="application/vnd.powerbuilder6-s"/>
+  <mime-type type="application/vnd.powerbuilder7"/>
+  <mime-type type="application/vnd.powerbuilder7-s"/>
+  <mime-type type="application/vnd.powerbuilder75"/>
+  <mime-type type="application/vnd.powerbuilder75-s"/>
+  <mime-type type="application/vnd.preminet"/>
+  <mime-type type="application/vnd.previewsystems.box">
+    <glob pattern="*.box"/>
+  </mime-type>
+  <mime-type type="application/vnd.proteus.magazine">
+    <glob pattern="*.mgz"/>
+  </mime-type>
+  <mime-type type="application/vnd.publishare-delta-tree">
+    <glob pattern="*.qps"/>
+  </mime-type>
+  <mime-type type="application/vnd.pvi.ptid1">
+    <glob pattern="*.ptid"/>
+  </mime-type>
+  <mime-type type="application/vnd.pwg-multiplexed"/>
+  <mime-type type="application/vnd.pwg-xhtml-print+xml"/>
+  <mime-type type="application/vnd.qualcomm.brew-app-res"/>
+  <mime-type type="application/vnd.quark.quarkxpress">
+    <glob pattern="*.qxd"/>
+    <glob pattern="*.qxt"/>
+    <glob pattern="*.qwd"/>
+    <glob pattern="*.qwt"/>
+    <glob pattern="*.qxl"/>
+    <glob pattern="*.qxb"/>
+  </mime-type>
+  <mime-type type="application/vnd.rapid"/>
+  <mime-type type="application/vnd.recordare.musicxml">
+    <glob pattern="*.mxl"/>
+  </mime-type>
+  <mime-type type="application/vnd.recordare.musicxml+xml">
+    <glob pattern="*.musicxml"/>
+  </mime-type>
+  <mime-type type="application/vnd.renlearn.rlprint"/>
+  <mime-type type="application/vnd.rim.cod">
+    <glob pattern="*.cod"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.rn-realmedia">
+    <magic priority="50">
+      <match value=".RMF" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.rm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.route66.link66+xml">
+    <glob pattern="*.link66"/>
+  </mime-type>
+  <mime-type type="application/vnd.ruckus.download"/>
+  <mime-type type="application/vnd.s3sms"/>
+  <mime-type type="application/vnd.sbm.cid"/>
+  <mime-type type="application/vnd.sbm.mid2"/>
+  <mime-type type="application/vnd.scribus"/>
+  <mime-type type="application/vnd.sealed.3df"/>
+  <mime-type type="application/vnd.sealed.csf"/>
+  <mime-type type="application/vnd.sealed.doc"/>
+  <mime-type type="application/vnd.sealed.eml"/>
+  <mime-type type="application/vnd.sealed.mht"/>
+  <mime-type type="application/vnd.sealed.net"/>
+  <mime-type type="application/vnd.sealed.ppt"/>
+  <mime-type type="application/vnd.sealed.tiff"/>
+  <mime-type type="application/vnd.sealed.xls"/>
+  <mime-type type="application/vnd.sealedmedia.softseal.html"/>
+  <mime-type type="application/vnd.sealedmedia.softseal.pdf"/>
+  <mime-type type="application/vnd.seemail">
+    <glob pattern="*.see"/>
+  </mime-type>
+  <mime-type type="application/vnd.sema">
+    <glob pattern="*.sema"/>
+  </mime-type>
+  <mime-type type="application/vnd.semd">
+    <glob pattern="*.semd"/>
+  </mime-type>
+  <mime-type type="application/vnd.semf">
+    <glob pattern="*.semf"/>
+  </mime-type>
+  <mime-type type="application/vnd.shana.informed.formdata">
+    <glob pattern="*.ifm"/>
+  </mime-type>
+  <mime-type type="application/vnd.shana.informed.formtemplate">
+    <glob pattern="*.itp"/>
+  </mime-type>
+  <mime-type type="application/vnd.shana.informed.interchange">
+    <glob pattern="*.iif"/>
+  </mime-type>
+  <mime-type type="application/vnd.shana.informed.package">
+    <glob pattern="*.ipk"/>
+  </mime-type>
+  <mime-type type="application/vnd.simtech-mindmapper">
+    <glob pattern="*.twd"/>
+    <glob pattern="*.twds"/>
+  </mime-type>
+  <mime-type type="application/vnd.smaf">
+    <glob pattern="*.mmf"/>
+  </mime-type>
+  <mime-type type="application/vnd.smart.teacher">
+    <glob pattern="*.teacher"/>
+  </mime-type>
+  <mime-type type="application/vnd.software602.filler.form+xml"/>
+  <mime-type type="application/vnd.software602.filler.form-xml-zip"/>
+  <mime-type type="application/vnd.solent.sdkm+xml">
+    <glob pattern="*.sdkm"/>
+    <glob pattern="*.sdkd"/>
+  </mime-type>
+  <mime-type type="application/vnd.spotfire.dxp">
+    <glob pattern="*.dxp"/>
+  </mime-type>
+  <mime-type type="application/vnd.spotfire.sfs">
+    <glob pattern="*.sfs"/>
+  </mime-type>
+  <mime-type type="application/vnd.sss-cod"/>
+  <mime-type type="application/vnd.sss-dtf"/>
+  <mime-type type="application/vnd.sss-ntf"/>
+  <mime-type type="application/vnd.stardivision.calc">
+    <glob pattern="*.sdc"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.draw">
+    <glob pattern="*.sda"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.impress">
+    <glob pattern="*.sdd"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.math">
+    <glob pattern="*.smf"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.writer">
+    <glob pattern="*.sdw"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.writer">
+    <glob pattern="*.vor"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.writer-global">
+    <glob pattern="*.sgl"/>
+  </mime-type>
+  <mime-type type="application/vnd.street-stream"/>
+  <mime-type type="application/vnd.sun.xml.calc">
+    <glob pattern="*.sxc"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.calc.template">
+    <glob pattern="*.stc"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.draw">
+    <glob pattern="*.sxd"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.draw.template">
+    <glob pattern="*.std"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.impress">
+    <glob pattern="*.sxi"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.impress.template">
+    <glob pattern="*.sti"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.math">
+    <glob pattern="*.sxm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.sun.xml.writer">
+    <alias type="application/x-vnd.sun.xml.writer"/>
+    <_comment>OpenOffice v1.0: Writer Document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+          value="mimetypeapplication/vnd.sun.xml.writer"/>
+      </match>
+    </magic>
+    <glob pattern="*.sxw"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.sun.xml.writer.global">
+    <glob pattern="*.sxg"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.writer.template">
+    <glob pattern="*.stw"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.wadl+xml"/>
+  <mime-type type="application/vnd.sus-calendar">
+    <glob pattern="*.sus"/>
+    <glob pattern="*.susp"/>
+  </mime-type>
+  <mime-type type="application/vnd.svd">
+    <glob pattern="*.svd"/>
+  </mime-type>
+  <mime-type type="application/vnd.swiftview-ics"/>
+
+  <mime-type type="application/vnd.symbian.install">
+    <magic priority="50">
+      <match value="0x10000419" type="little32" offset="8" />
+    </magic>
+    <glob pattern="*.sis"/>
+    <glob pattern="*.sisx"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.syncml+xml">
+    <glob pattern="*.xsm"/>
+  </mime-type>
+  <mime-type type="application/vnd.syncml.dm+wbxml">
+    <glob pattern="*.bdm"/>
+  </mime-type>
+  <mime-type type="application/vnd.syncml.dm+xml">
+    <glob pattern="*.xdm"/>
+  </mime-type>
+  <mime-type type="application/vnd.syncml.dm.notification"/>
+  <mime-type type="application/vnd.syncml.ds.notification"/>
+  <mime-type type="application/vnd.tao.intent-module-archive">
+    <glob pattern="*.tao"/>
+  </mime-type>
+  <mime-type type="application/vnd.tmobile-livetv">
+    <glob pattern="*.tmo"/>
+  </mime-type>
+  <mime-type type="application/vnd.trid.tpt">
+    <glob pattern="*.tpt"/>
+  </mime-type>
+  <mime-type type="application/vnd.triscape.mxs">
+    <glob pattern="*.mxs"/>
+  </mime-type>
+  <mime-type type="application/vnd.trueapp">
+    <glob pattern="*.tra"/>
+  </mime-type>
+  <mime-type type="application/vnd.truedoc"/>
+  <mime-type type="application/vnd.ufdl">
+    <glob pattern="*.ufd"/>
+    <glob pattern="*.ufdl"/>
+  </mime-type>
+  <mime-type type="application/vnd.uiq.theme">
+    <glob pattern="*.utz"/>
+  </mime-type>
+  <mime-type type="application/vnd.umajin">
+    <glob pattern="*.umj"/>
+  </mime-type>
+  <mime-type type="application/vnd.unity">
+    <glob pattern="*.unityweb"/>
+  </mime-type>
+  <mime-type type="application/vnd.uoml+xml">
+    <glob pattern="*.uoml"/>
+  </mime-type>
+  <mime-type type="application/vnd.uplanet.alert"/>
+  <mime-type type="application/vnd.uplanet.alert-wbxml"/>
+  <mime-type type="application/vnd.uplanet.bearer-choice"/>
+  <mime-type type="application/vnd.uplanet.bearer-choice-wbxml"/>
+  <mime-type type="application/vnd.uplanet.cacheop"/>
+  <mime-type type="application/vnd.uplanet.cacheop-wbxml"/>
+  <mime-type type="application/vnd.uplanet.channel"/>
+  <mime-type type="application/vnd.uplanet.channel-wbxml"/>
+  <mime-type type="application/vnd.uplanet.list"/>
+  <mime-type type="application/vnd.uplanet.list-wbxml"/>
+  <mime-type type="application/vnd.uplanet.listcmd"/>
+  <mime-type type="application/vnd.uplanet.listcmd-wbxml"/>
+  <mime-type type="application/vnd.uplanet.signal"/>
+  <mime-type type="application/vnd.vcx">
+    <glob pattern="*.vcx"/>
+  </mime-type>
+  <mime-type type="application/vnd.vd-study"/>
+  <mime-type type="application/vnd.vectorworks"/>
+  <mime-type type="application/vnd.vidsoft.vidconference"/>
+
+  <!-- http://www.iana.org/assignments/media-types/application/vnd.visio -->
+  <mime-type type="application/vnd.visio">
+    <_comment>Microsoft Visio Diagram</_comment>
+    <glob pattern="*.vsd"/>
+    <glob pattern="*.vst"/>
+    <glob pattern="*.vss"/>
+    <glob pattern="*.vsw"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.visionary">
+    <glob pattern="*.vis"/>
+  </mime-type>
+  <mime-type type="application/vnd.vividence.scriptfile"/>
+  <mime-type type="application/vnd.vsf">
+    <glob pattern="*.vsf"/>
+  </mime-type>
+  <mime-type type="application/vnd.wap.sic"/>
+  <mime-type type="application/vnd.wap.slc"/>
+
+  <mime-type type="application/vnd.wap.wbxml">
+    <glob pattern="*.wbxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.wap.wmlc">
+    <_comment>Compiled WML Document</_comment>
+    <glob pattern="*.wmlc"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.wap.wmlscriptc">
+    <_comment>Compiled WML Script</_comment>
+    <glob pattern="*.wmlsc"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.webturbo">
+    <glob pattern="*.wtb"/>
+  </mime-type>
+  <mime-type type="application/vnd.wfa.wsc"/>
+  <mime-type type="application/vnd.wmc"/>
+  <mime-type type="application/vnd.wmf.bootstrap"/>
+  <mime-type type="application/vnd.wordperfect">
+    <glob pattern="*.wpd"/>
+  </mime-type>
+  <mime-type type="application/vnd.wqd">
+    <glob pattern="*.wqd"/>
+  </mime-type>
+  <mime-type type="application/vnd.wrq-hp3000-labelled"/>
+  <mime-type type="application/vnd.wt.stf">
+    <glob pattern="*.stf"/>
+  </mime-type>
+  <mime-type type="application/vnd.wv.csp+wbxml"/>
+  <mime-type type="application/vnd.wv.csp+xml"/>
+  <mime-type type="application/vnd.wv.ssp+xml"/>
+  <mime-type type="application/vnd.xara">
+    <glob pattern="*.xar"/>
+  </mime-type>
+  <mime-type type="application/vnd.xfdl">
+    <glob pattern="*.xfdl"/>
+  </mime-type>
+  <mime-type type="application/vnd.xfdl.webform"/>
+  <mime-type type="application/vnd.xmi+xml"/>
+  <mime-type type="application/vnd.xmpie.cpkg"/>
+  <mime-type type="application/vnd.xmpie.dpkg"/>
+  <mime-type type="application/vnd.xmpie.plan"/>
+  <mime-type type="application/vnd.xmpie.ppkg"/>
+  <mime-type type="application/vnd.xmpie.xlim"/>
+  <mime-type type="application/vnd.yamaha.hv-dic">
+    <glob pattern="*.hvd"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.hv-script">
+    <glob pattern="*.hvs"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.hv-voice">
+    <glob pattern="*.hvp"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.openscoreformat">
+    <glob pattern="*.osf"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.openscoreformat.osfpvg+xml">
+    <glob pattern="*.osfpvg"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.smaf-audio">
+    <glob pattern="*.saf"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.smaf-phrase">
+    <glob pattern="*.spf"/>
+  </mime-type>
+  <mime-type type="application/vnd.yellowriver-custom-menu">
+    <glob pattern="*.cmp"/>
+  </mime-type>
+  <mime-type type="application/vnd.zul">
+    <glob pattern="*.zir"/>
+    <glob pattern="*.zirz"/>
+  </mime-type>
+  <mime-type type="application/vnd.zzazz.deck+xml">
+    <glob pattern="*.zaz"/>
+  </mime-type>
+  <mime-type type="application/voicexml+xml">
+    <glob pattern="*.vxml"/>
+  </mime-type>
+  <mime-type type="application/watcherinfo+xml"/>
+  <mime-type type="application/whoispp-query"/>
+  <mime-type type="application/whoispp-response"/>
+  <mime-type type="application/winhlp">
+    <glob pattern="*.hlp"/>
+  </mime-type>
+  <mime-type type="application/wita"/>
+  <mime-type type="application/wordperfect5.1"/>
+  <mime-type type="application/wsdl+xml">
+    <glob pattern="*.wsdl"/>
+  </mime-type>
+  <mime-type type="application/wspolicy+xml">
+    <glob pattern="*.wspolicy"/>
+  </mime-type>
+
+  <mime-type type="application/x-123">
+    <magic priority="50">
+      <match value="0x00001a00" type="big32" offset="0" />
+      <match value="0x00000200" type="big32" offset="0" />
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-abiword">
+    <glob pattern="*.abw"/>
+  </mime-type>
+  <mime-type type="application/x-ace-compressed">
+    <glob pattern="*.ace"/>
+  </mime-type>
+
+  <mime-type type="application/x-adobe-indesign">
+    <acronym>INDD</acronym>
+    <_comment>Adobe InDesign document</_comment>
+    <glob pattern="*.indd"/>
+  </mime-type>
+
+  <mime-type type="application/x-adobe-indesign-interchange">
+    <acronym>INX</acronym>
+    <_comment>Adobe InDesign Interchange format</_comment>
+    <magic priority="50">
+      <match value="&lt;?aid" type="string" offset="0:100"/>
+    </magic>
+    <glob pattern="*.inx"/>
+    <sub-class-of type="application/xml"/>
+  </mime-type>
+
+  <mime-type type="application/x-archive">
+    <magic priority="50">
+      <match value="=&lt;ar&gt;" type="string" offset="0"/>
+      <match value="=!&lt;arch&gt;" type="string" offset="0"/>
+    </magic>
+    <glob patter="*.ar"/>
+  </mime-type>
+
+  <mime-type type="application/x-authorware-bin">
+    <glob pattern="*.aab"/>
+    <glob pattern="*.x32"/>
+    <glob pattern="*.u32"/>
+    <glob pattern="*.vox"/>
+  </mime-type>
+  <mime-type type="application/x-authorware-map">
+    <glob pattern="*.aam"/>
+  </mime-type>
+  <mime-type type="application/x-authorware-seg">
+    <glob pattern="*.aas"/>
+  </mime-type>
+  <mime-type type="application/x-bcpio">
+    <glob pattern="*.bcpio"/>
+  </mime-type>
+
+  <mime-type type="application/x-berkeley-db">
+    <magic priority="50">
+      <match value="0x00061561" type="big32" offset="0"/>
+      <match value="0x00061561" type="host32" offset="12"/>
+      <match value="0x00061561" type="big32" offset="12"/>
+      <match value="0x00061561" type="little32" offset="12"/>
+      <match value="0x00053162" type="host32" offset="12"/>
+      <match value="0x00053162" type="big32" offset="12"/>
+      <match value="0x00053162" type="little32" offset="12"/>
+      <match value="0x00042253" type="host32" offset="12"/>
+      <match value="0x00042253" type="big32" offset="12"/>
+      <match value="0x00042253" type="little32" offset="12"/>
+      <match value="0x00040988" type="host32" offset="12"/>
+      <match value="0x00040988" type="little32" offset="12"/>
+      <match value="0x00040988" type="big32" offset="12"/>
+      <match value="0x00053162" type="host32" offset="0"/>
+      <match value="0x00053162" type="big32" offset="0"/>
+      <match value="0x00053162" type="little32" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-bibtex-text-file">
+    <magic priority="50">
+      <match value="%\ BibTeX\ `" type="string" offset="0"/>
+      <match value="%%%\ \ " type="string" offset="73"/>
+      <match value="%\ BibTeX\ standard\ bibliography\ " type="string" offset="0"/>
+      <match value="%%%\ \ @BibTeX-style-file{" type="string" offset="73"/>
+      <match value="@article{" type="string" offset="0"/>
+      <match value="@book{" type="string" offset="0"/>
+      <match value="@inbook{" type="string" offset="0"/>
+      <match value="@incollection{" type="string" offset="0"/>
+      <match value="@inproceedings{" type="string" offset="0"/>
+      <match value="@manual{" type="string" offset="0"/>
+      <match value="@misc{" type="string" offset="0"/>
+      <match value="@preamble{" type="string" offset="0"/>
+      <match value="@phdthesis{" type="string" offset="0"/>
+      <match value="@techreport{" type="string" offset="0"/>
+      <match value="@unpublished{" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.bib"/>
+    <glob pattern="*.bibtex"/>
+  </mime-type>
+
+  <mime-type type="application/x-bittorrent">
+    <magic priority="50">
+      <match value="d8:announce" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.torrent"/>
+  </mime-type>
+
+  <mime-type type="application/x-bzip">
+    <magic priority="40">
+      <match value="BZh" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.bz"/>
+    <glob pattern="*.tbz"/>
+  </mime-type>
+
+  <mime-type type="application/x-bzip2">
+    <glob pattern="*.bz2"/>
+    <glob pattern="*.tbz2"/>
+    <glob pattern="*.boz"/>
+    <sub-class-of type="application/x-bzip"/>
+  </mime-type>
+
+  <mime-type type="application/x-cdlink">
+    <_comment>Virtual CD-ROM CD Image File</_comment>
+    <glob pattern="*.vcd"/>
+  </mime-type>
+
+  <mime-type type="application/x-chat">
+    <glob pattern="*.chat"/>
+  </mime-type>
+  <mime-type type="application/x-chess-pgn">
+    <glob pattern="*.pgn"/>
+  </mime-type>
+
+  <mime-type type="application/x-compress">
+    <magic priority="50">
+      <match value="\037\235" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.z"/>
+  </mime-type>
+
+  <mime-type type="application/x-corelpresentations">
+    <glob pattern="*.shw"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+  
+  <mime-type type="application/x-cpio">
+    <magic priority="50">
+      <match value="070707" type="little16" offset="0"/>
+      <match value="070707" type="big16" offset="0"/>
+      <match value="070707" type="string" offset="0"/>
+      <match value="070701" type="string" offset="0"/>
+      <match value="070702" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.cpio"/>
+  </mime-type>
+
+  <mime-type type="application/x-csh">
+    <glob pattern="*.csh"/>
+  </mime-type>
+
+  <mime-type type="application/x-debian-package">
+    <glob pattern="*.deb"/>
+    <glob pattern="*.udeb"/>
+  </mime-type>
+
+  <mime-type type="application/x-director">
+    <_comment>Shockwave Movie</_comment>
+    <glob pattern="*.dir"/>
+    <glob pattern="*.dcr"/>
+    <glob pattern="*.dxr"/>
+    <glob pattern="*.cst"/>
+    <glob pattern="*.cct"/>
+    <glob pattern="*.cxt"/>
+    <glob pattern="*.w3d"/>
+    <glob pattern="*.fgd"/>
+    <glob pattern="*.swa"/>
+  </mime-type>
+
+  <mime-type type="application/x-doom">
+    <glob pattern="*.wad"/>
+  </mime-type>
+  <mime-type type="application/x-dtbncx+xml">
+    <glob pattern="*.ncx"/>
+  </mime-type>
+  <mime-type type="application/x-dtbook+xml">
+    <glob pattern="*.dtb"/>
+  </mime-type>
+  <mime-type type="application/x-dtbresource+xml">
+    <glob pattern="*.res"/>
+  </mime-type>
+
+  <mime-type type="application/x-dvi">
+    <magic priority="50">
+      <match value="\367\002" type="string" offset="0"/>
+      <match value="0x02f7" type="little16" offset="0"/>
+    </magic>
+    <glob pattern="*.dvi"/>
+  </mime-type>
+
+  <mime-type type="application/x-elc">
+    <_comment>Emacs Lisp bytecode</_comment>
+    <magic priority="50">
+      <!-- Emacs 18 -->
+      <match value="\012(" type="string" offset="0" />
+      <!-- Emacs 19 -->
+      <match value=";ELC\023\000\000\000" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.elc"/>
+  </mime-type>
+
+  <mime-type type="application/x-font-bdf">
+    <glob pattern="*.bdf"/>
+  </mime-type>
+  <mime-type type="application/x-font-dos"/>
+  <mime-type type="application/x-font-framemaker"/>
+  <mime-type type="application/x-font-ghostscript">
+    <glob pattern="*.gsf"/>
+  </mime-type>
+  <mime-type type="application/x-font-libgrx"/>
+  <mime-type type="application/x-font-linux-psf">
+    <glob pattern="*.psf"/>
+  </mime-type>
+
+  <mime-type type="application/x-font-otf">
+    <acronym>OTF</acronym>
+    <_comment>OpenType Font</_comment>
+    <glob pattern="*.otf"/>
+  </mime-type>
+
+  <mime-type type="application/x-font-pcf">
+    <glob pattern="*.pcf"/>
+  </mime-type>
+  <mime-type type="application/x-font-snf">
+    <glob pattern="*.snf"/>
+  </mime-type>
+  <mime-type type="application/x-font-speedo"/>
+  <mime-type type="application/x-font-sunos-news"/>
+
+  <mime-type type="application/x-font-ttf">
+    <acronym>TTF</acronym>
+    <_comment>TrueType Font</_comment>
+    <glob pattern="*.ttf"/>
+    <glob pattern="*.ttc"/>
+    <magic priority="40">
+      <match value="0x00010000" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-font-type1">
+    <glob pattern="*.pfa"/>
+    <glob pattern="*.pfb"/>
+    <glob pattern="*.pfm"/>
+    <glob pattern="*.afm"/>
+  </mime-type>
+  <mime-type type="application/x-font-vfont"/>
+
+  <mime-type type="application/x-futuresplash">
+    <_comment>Macromedia FutureSplash File</_comment>
+    <glob pattern="*.spl"/>
+  </mime-type>
+
+  <mime-type type="application/x-gnucash">
+    <glob pattern="*.gnucash" />
+  </mime-type>
+
+  <mime-type type="application/x-gnumeric">
+    <alias type="application/x-Gnumeric-spreadsheet"/>
+    <magic priority="50">
+      <match value="=&lt;gmr:Workbook" type="string" offset="39" />
+    </magic>
+    <glob pattern="*.gnumeric"/>
+  </mime-type>
+
+  <mime-type type="application/x-gtar">
+    <magic priority="40">
+      <!-- GNU tar archive -->
+      <match value="ustar  \0" type="string" offset="257" />
+    </magic>
+    <glob pattern="*.gtar"/>
+    <sub-class-of type="application/x-tar"/>
+  </mime-type>
+
+  <mime-type type="application/x-gzip">
+    <magic priority="40">
+      <match value="\037\213" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.tgz" />
+    <glob pattern="*.gz" />
+    <glob pattern="*-gz" />
+    <glob pattern="*.emz" />
+  </mime-type>
+
+  <mime-type type="application/x-hdf">
+    <magic priority="50">
+      <match value="0x0e031301" type="big32" offset="0"/>
+      <match value="\211HDF\r\n\032" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.hdf"/>
+    <glob pattern="*.he5"/>
+  </mime-type>
+
+  <mime-type type="application/x-hwp">
+    <magic priority="50">
+      <!--
+        TIKA-330: Detection pattern based on signature strings from
+        the hwpfilter/source/hwpfile.cpp file in OpenOffice.org.
+      -->
+      <match value="HWP Document File V" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-iso9660-image">
+    <magic priority="50">
+      <match value="CD001" type="string" offset="37633"/>
+    </magic>
+    <glob pattern="*.iso" />
+  </mime-type>
+
+  <mime-type type="application/x-java-jnlp-file">
+    <glob pattern="*.jnlp"/>
+  </mime-type>
+
+  <mime-type type="application/x-kdelnk">
+    <magic priority="50">
+      <match value="[KDE\ Desktop\ Entry]" type="string" offset="0"/>
+      <match value="#\ KDE\ Config\ File" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-latex">
+    <_comment>LaTeX Source Document</_comment>
+    <magic priority="50">
+      <match value="%\ -*-latex-*-" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.latex"/>
+  </mime-type>
+
+  <mime-type type="application/x-lha">
+    <magic priority="50">
+      <match value="-lzs-" type="string" offset="2"/>
+      <match value="-lh\40-" type="string" offset="2"/>
+      <match value="-lhd-" type="string" offset="2"/>
+      <match value="-lh2-" type="string" offset="2"/>
+      <match value="-lh3-" type="string" offset="2"/>
+      <match value="-lh4-" type="string" offset="2"/>
+      <match value="-lh5-" type="string" offset="2"/>
+      <match value="-lh6-" type="string" offset="2"/>
+      <match value="-lh7-" type="string" offset="2"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-lharc">
+    <magic priority="50">
+      <match value="-lh0-" type="string" offset="2"/>
+      <match value="-lh1-" type="string" offset="2"/>
+      <match value="-lz4-" type="string" offset="2"/>
+      <match value="-lz5-" type="string" offset="2"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-mobipocket-ebook">
+    <glob pattern="*.prc"/>
+    <glob pattern="*.mobi"/>
+  </mime-type>
+  <mime-type type="application/x-ms-application">
+    <glob pattern="*.application"/>
+  </mime-type>
+  <mime-type type="application/x-ms-wmd">
+    <glob pattern="*.wmd"/>
+  </mime-type>
+  <mime-type type="application/x-ms-wmz">
+    <sub-class-of type="application/x-gzip"/>
+    <glob pattern="*.wmz"/>
+  </mime-type>
+  <mime-type type="application/x-ms-xbap">
+    <glob pattern="*.xbap"/>
+  </mime-type>
+  <mime-type type="application/x-msaccess">
+    <glob pattern="*.mdb"/>
+  </mime-type>
+  <mime-type type="application/x-msbinder">
+    <glob pattern="*.obd"/>
+  </mime-type>
+  <mime-type type="application/x-mscardfile">
+    <glob pattern="*.crd"/>
+  </mime-type>
+  <mime-type type="application/x-msclip">
+    <glob pattern="*.clp"/>
+  </mime-type>
+  <mime-type type="application/x-msdownload">
+    <glob pattern="*.exe"/>
+    <glob pattern="*.dll"/>
+    <glob pattern="*.com"/>
+    <glob pattern="*.bat"/>
+    <glob pattern="*.msi"/>
+  </mime-type>
+  <mime-type type="application/x-msmediaview">
+    <glob pattern="*.mvb"/>
+    <glob pattern="*.m13"/>
+    <glob pattern="*.m14"/>
+  </mime-type>
+  <mime-type type="application/x-msmetafile">
+    <alias type="image/x-emf"/>
+    <alias type="image/x-wmf"/>
+    <acronym>WMF</acronym>
+    <_comment>Windows Metafile</_comment>
+    <glob pattern="*.wmf"/>
+    <glob pattern="*.emf"/>
+  </mime-type>
+  <mime-type type="application/x-msmoney">
+    <glob pattern="*.mny"/>
+  </mime-type>
+  <mime-type type="application/x-mspublisher">
+    <glob pattern="*.pub"/>
+  </mime-type>
+  <mime-type type="application/x-msschedule">
+    <glob pattern="*.scd"/>
+  </mime-type>
+  <mime-type type="application/x-msterminal">
+    <glob pattern="*.trm"/>
+  </mime-type>
+  <mime-type type="application/x-mswrite">
+    <glob pattern="*.wri"/>
+  </mime-type>
+  <mime-type type="application/x-netcdf">
+    <glob pattern="*.nc"/>
+    <glob pattern="*.cdf"/>
+  </mime-type>
+  <mime-type type="application/x-pkcs12">
+    <glob pattern="*.p12"/>
+    <glob pattern="*.pfx"/>
+  </mime-type>
+  <mime-type type="application/x-pkcs7-certificates">
+    <glob pattern="*.p7b"/>
+    <glob pattern="*.spc"/>
+  </mime-type>
+  <mime-type type="application/x-pkcs7-certreqresp">
+    <glob pattern="*.p7r"/>
+  </mime-type>
+
+  <mime-type type="application/x-quattro-pro">
+    <glob pattern="*.qpw"/>
+    <glob pattern="*.wb1"/>
+    <glob pattern="*.wb2"/>
+    <glob pattern="*.wb3"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+  
+  <mime-type type="application/x-rar-compressed">
+    <alias type="application/x-rar"/>
+    <magic priority="50">
+      <match value="Rar!" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.rar"/>
+  </mime-type>
+
+  <mime-type type="application/x-rpm">
+    <glob pattern="*.rpm"/>
+  </mime-type>
+
+  <mime-type type="application/x-sc">
+    <magic priority="50">
+      <match value="Spreadsheet" type="string" offset="38"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-sh">
+    <magic priority="50">
+      <match value="#!/" type="string" offset="0"/>
+      <match value="#!\ /" type="string" offset="0"/>
+      <match value="#!\t/" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.sh"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="application/x-shar">
+    <glob pattern="*.shar"/>
+  </mime-type>
+
+  <mime-type type="application/x-shockwave-flash">
+    <acronym>Flash</acronym>
+    <_comment>Adobe Flash</_comment>
+    <magic priority="50">
+      <match value="FWS" type="string" offset="0"/> <!-- F = Uncompressed -->
+      <match value="CWS" type="string" offset="0"/> <!-- C = Compressed   -->
+    </magic>
+    <glob pattern="*.swf"/>
+  </mime-type>
+
+  <mime-type type="application/x-silverlight-app">
+    <glob pattern="*.xap"/>
+  </mime-type>
+
+  <mime-type type="application/x-stuffit">
+    <magic priority="50">
+      <match value="StuffIt" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.sit"/>
+  </mime-type>
+
+  <mime-type type="application/x-stuffitx">
+    <glob pattern="*.sitx"/>
+  </mime-type>
+  <mime-type type="application/x-sv4cpio">
+    <glob pattern="*.sv4cpio"/>
+  </mime-type>
+  <mime-type type="application/x-sv4crc">
+    <glob pattern="*.sv4crc"/>
+  </mime-type>
+
+  <mime-type type="application/x-tar">
+    <magic priority="40">
+      <!-- POSIX tar archive -->
+      <match value="ustar\0" type="string" offset="257" />
+    </magic>
+    <glob pattern="*.tar"/>
+  </mime-type>
+
+  <mime-type type="application/x-tcl">
+    <alias type="text/x-tcl"/>
+    <glob pattern="*.tcl"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="application/x-tex">
+    <alias type="text/x-tex"/>
+    <magic priority="50">
+      <match value="\\input" type="string" offset="0"/>
+      <match value="\\section" type="string" offset="0"/>
+      <match value="\\setlength" type="string" offset="0"/>
+      <match value="\\documentstyle" type="string" offset="0"/>
+      <match value="\\chapter" type="string" offset="0"/>
+      <match value="\\documentclass" type="string" offset="0"/>
+      <match value="\\relax" type="string" offset="0"/>
+      <match value="\\contentsline" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.tex"/>
+  </mime-type>
+
+  <mime-type type="application/x-tex-tfm">
+    <glob pattern="*.tfm"/>
+  </mime-type>
+
+  <mime-type type="application/x-texinfo">
+    <alias type="text/x-texinfo" />
+    <magic priority="50">
+      <match value="\\input\ texinfo" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.texinfo"/>
+    <glob pattern="*.texi"/>
+  </mime-type>
+
+  <!-- =================================================================== -->
+  <!-- Microsoft Office binary file formats                                -->
+  <!-- http://www.microsoft.com/interop/docs/OfficeBinaryFormats.mspx      -->
+  <!-- =================================================================== -->
+  <mime-type type="application/x-tika-msoffice">
+    <magic>
+      <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8"/>
+    </magic>
+  </mime-type>
+
+  <!-- =================================================================== -->
+  <!-- Office Open XML file formats                                        -->
+  <!-- http://www.ecma-international.org/publications/standards/Ecma-376.htm -->
+  <!-- =================================================================== -->
+  <mime-type type="application/x-tika-ooxml">
+    <sub-class-of type="application/zip"/>
+    <magic priority="50">
+      <match value="PK\003\004" type="string" offset="0">
+        <match value="[Content_Types].xml" type="string" offset="30"/>
+      </match>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-ustar">
+    <glob pattern="*.ustar"/>
+  </mime-type>
+  <mime-type type="application/x-wais-source">
+    <glob pattern="*.src"/>
+  </mime-type>
+  <mime-type type="application/x-x509-ca-cert">
+    <glob pattern="*.der"/>
+    <glob pattern="*.crt"/>
+  </mime-type>
+  <mime-type type="application/x-xfig">
+    <glob pattern="*.fig"/>
+  </mime-type>
+  <mime-type type="application/x-xpinstall">
+    <glob pattern="*.xpi"/>
+  </mime-type>
+
+  <mime-type type="application/x-zoo">
+    <magic priority="50">
+      <match value="0xfdc4a7dc" type="little32" offset="20"/>
+    </magic>
+    <glob pattern="*.zoo"/>
+  </mime-type>
+
+  <mime-type type="application/x400-bp"/>
+  <mime-type type="application/xcap-att+xml"/>
+  <mime-type type="application/xcap-caps+xml"/>
+  <mime-type type="application/xcap-el+xml"/>
+  <mime-type type="application/xcap-error+xml"/>
+  <mime-type type="application/xcap-ns+xml"/>
+  <mime-type type="application/xcon-conference-info-diff+xml"/>
+  <mime-type type="application/xcon-conference-info+xml"/>
+  <mime-type type="application/xenc+xml">
+    <glob pattern="*.xenc"/>
+  </mime-type>
+
+  <mime-type type="application/xhtml+xml">
+    <magic priority="50">
+      <match value="&lt;html xmlns=" type="string" offset="0:8192"/>
+    </magic>
+    <root-XML namespaceURI="http://www.w3.org/1999/xhtml" localName="html"/>
+    <glob pattern="*.xhtml"/>
+    <glob pattern="*.xht"/>
+  </mime-type>
+
+  <mime-type type="application/xhtml-voice+xml"/>
+
+  <mime-type type="application/xml">
+    <alias type="text/xml"/>
+    <magic priority="50">
+      <match value="&lt;?xml" type="string" offset="0"/>
+      <match value="&lt;?XML" type="string" offset="0"/>
+      <match value="&lt;!--" type="string" offset="0"/>
+      <match value="0xFFFE3C003F0078006D006C00" type="string" offset="0"/>
+      <match value="0xFEFF003C003F0078006D006C" type="string" offset="0"/>
+      <!-- TODO: Add matches for the other possible XML encoding schemes -->
+    </magic>
+    <glob pattern="*.xml"/>
+    <glob pattern="*.xsl"/>
+    <glob pattern="*.xsd"/>
+    <sub-class-of type="text/plain" />
+  </mime-type>
+
+  <mime-type type="application/xml-dtd">
+    <sub-class-of type="text/plain"/>
+    <glob pattern="*.dtd"/>
+  </mime-type>
+  <mime-type type="application/xml-external-parsed-entity"/>
+  <mime-type type="application/xmpp+xml"/>
+  <mime-type type="application/xop+xml">
+    <glob pattern="*.xop"/>
+  </mime-type>
+
+  <mime-type type="application/xslt+xml">
+    <alias type="text/xsl"/>
+    <acronym>XSLT</acronym>
+    <_comment>XSL Transformations</_comment>
+    <root-XML localName="stylesheet"
+              namespaceURI="http://www.w3.org/1999/XSL/Transform"/>
+    <glob pattern="*.xslt"/>
+  </mime-type>
+
+  <mime-type type="application/xspf+xml">
+    <glob pattern="*.xspf"/>
+  </mime-type>
+  <mime-type type="application/xv+xml">
+    <glob pattern="*.mxml"/>
+    <glob pattern="*.xhvml"/>
+    <glob pattern="*.xvml"/>
+    <glob pattern="*.xvm"/>
+  </mime-type>
+
+  <mime-type type="application/zip">
+    <alias type="application/x-zip-compressed"/>
+    <magic priority="40">
+      <match value="PK\003\004" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.zip"/>
+  </mime-type>
+
+  <mime-type type="audio/32kadpcm"/>
+  <mime-type type="audio/3gpp"/>
+  <mime-type type="audio/3gpp2"/>
+  <mime-type type="audio/ac3"/>
+  <mime-type type="audio/adpcm">
+    <glob pattern="*.adp"/>
+  </mime-type>
+  <mime-type type="audio/amr"/>
+  <mime-type type="audio/amr-wb"/>
+  <mime-type type="audio/amr-wb+"/>
+  <mime-type type="audio/asc"/>
+
+  <mime-type type="audio/basic">
+    <magic priority="20">
+      <match value=".snd" type="string" offset="0">
+        <match value="1" type="big32" offset="12"/>
+        <match value="2" type="big32" offset="12"/>
+        <match value="3" type="big32" offset="12"/>
+        <match value="4" type="big32" offset="12"/>
+        <match value="5" type="big32" offset="12"/>
+        <match value="6" type="big32" offset="12"/>
+        <match value="7" type="big32" offset="12"/>
+      </match>
+    </magic>
+    <glob pattern="*.au"/>
+    <glob pattern="*.snd"/>
+  </mime-type>
+
+  <mime-type type="audio/bv16"/>
+  <mime-type type="audio/bv32"/>
+  <mime-type type="audio/clearmode"/>
+  <mime-type type="audio/cn"/>
+  <mime-type type="audio/dat12"/>
+  <mime-type type="audio/dls"/>
+  <mime-type type="audio/dsr-es201108"/>
+  <mime-type type="audio/dsr-es202050"/>
+  <mime-type type="audio/dsr-es202211"/>
+  <mime-type type="audio/dsr-es202212"/>
+  <mime-type type="audio/dvi4"/>
+  <mime-type type="audio/eac3"/>
+  <mime-type type="audio/evrc"/>
+  <mime-type type="audio/evrc-qcp"/>
+  <mime-type type="audio/evrc0"/>
+  <mime-type type="audio/evrc1"/>
+  <mime-type type="audio/evrcb"/>
+  <mime-type type="audio/evrcb0"/>
+  <mime-type type="audio/evrcb1"/>
+  <mime-type type="audio/evrcwb"/>
+  <mime-type type="audio/evrcwb0"/>
+  <mime-type type="audio/evrcwb1"/>
+  <mime-type type="audio/example"/>
+  <mime-type type="audio/g719"/>
+  <mime-type type="audio/g722"/>
+  <mime-type type="audio/g7221"/>
+  <mime-type type="audio/g723"/>
+  <mime-type type="audio/g726-16"/>
+  <mime-type type="audio/g726-24"/>
+  <mime-type type="audio/g726-32"/>
+  <mime-type type="audio/g726-40"/>
+  <mime-type type="audio/g728"/>
+  <mime-type type="audio/g729"/>
+  <mime-type type="audio/g7291"/>
+  <mime-type type="audio/g729d"/>
+  <mime-type type="audio/g729e"/>
+  <mime-type type="audio/gsm"/>
+  <mime-type type="audio/gsm-efr"/>
+  <mime-type type="audio/ilbc"/>
+  <mime-type type="audio/l16"/>
+  <mime-type type="audio/l20"/>
+  <mime-type type="audio/l24"/>
+  <mime-type type="audio/l8"/>
+  <mime-type type="audio/lpc"/>
+
+  <mime-type type="audio/midi">
+    <acronym>MIDI</acronym>
+    <_comment>Musical Instrument Digital Interface</_comment>
+    <magic priority ="20">
+      <match type="string" value="MThd" offset="0"/>
+    </magic>
+    <glob pattern="*.mid"/>
+    <glob pattern="*.midi"/>
+    <glob pattern="*.kar"/>
+    <glob pattern="*.rmi"/>
+  </mime-type>
+
+  <mime-type type="audio/mobile-xmf"/>
+  <mime-type type="audio/mp4">
+    <alias type="audio/x-mp4a"/>
+    <glob pattern="*.mp4a"/>
+  </mime-type>
+  <mime-type type="audio/mp4a-latm"/>
+  <mime-type type="audio/mpa"/>
+  <mime-type type="audio/mpa-robust"/>
+
+  <mime-type type="audio/mpeg">
+    <acronym>MP3</acronym>
+    <_comment>MPEG-1 Audio Layer 3</_comment>
+    <magic priority="20">
+      <!-- http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html -->
+      <!-- Bit pattern for first two bytes: 11111111 111VVLLC    -->
+      <!-- VV = MPEG Audio Version ID; 10 = V2, 11 = V1          -->
+      <!-- LL = Layer description; 01 = L3, 10 = L2, 11 = L1     -->
+      <!-- C = Protection bit; 0 = CRC, 1 = no CRC               -->
+      <match value="0xfff2" type="string" offset="0"/> <!-- V2, L3, CRC -->
+      <match value="0xfff3" type="string" offset="0"/> <!-- V2, L3      -->
+      <match value="0xfff4" type="string" offset="0"/> <!-- V2, L2, CRC -->
+      <match value="0xfff5" type="string" offset="0"/> <!-- V2, L2      -->
+      <match value="0xfff6" type="string" offset="0"/> <!-- V2, L1, CRC -->
+      <match value="0xfff7" type="string" offset="0"/> <!-- V2, L1      -->
+      <match value="0xfffa" type="string" offset="0"/> <!-- V1, L3, CRC -->
+      <match value="0xfffb" type="string" offset="0"/> <!-- V1, L3      -->
+      <match value="0xfffc" type="string" offset="0"/> <!-- V1, L2, CRC -->
+      <match value="0xfffd" type="string" offset="0"/> <!-- V1, L2      -->
+      <!-- TIKA-417: This is the UTF-16 LE byte order mark! -->
+      <!-- match value="0xfffe" type="string" offset="0"/ --> <!-- V1, L1, CRC -->
+      <match value="0xffff" type="string" offset="0"/> <!-- V1, L1      -->
+      <match value="ID3" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.mpga"/>
+    <glob pattern="*.mp2"/>
+    <glob pattern="*.mp2a"/>
+    <glob pattern="*.mp3"/>
+    <glob pattern="*.m2a"/>
+    <glob pattern="*.m3a"/>
+  </mime-type>
+
+  <mime-type type="audio/mpeg4-generic"/>
+
+  <mime-type type="audio/ogg">
+    <glob pattern="*.oga"/>
+    <glob pattern="*.ogg"/>
+    <glob pattern="*.spx"/>
+    <sub-class-of type="application/ogg"/>
+  </mime-type>
+
+  <mime-type type="audio/parityfec"/>
+  <mime-type type="audio/pcma"/>
+  <mime-type type="audio/pcma-wb"/>
+  <mime-type type="audio/pcmu-wb"/>
+  <mime-type type="audio/pcmu"/>
+
+  <mime-type type="audio/prs.sid">
+    <magic priority="50">
+      <match value="PSID" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="audio/qcelp"/>
+  <mime-type type="audio/red"/>
+  <mime-type type="audio/rtp-enc-aescm128"/>
+  <mime-type type="audio/rtp-midi"/>
+  <mime-type type="audio/rtx"/>
+  <mime-type type="audio/smv"/>
+  <mime-type type="audio/smv0"/>
+  <mime-type type="audio/smv-qcp"/>
+  <mime-type type="audio/sp-midi"/>
+  <mime-type type="audio/t140c"/>
+  <mime-type type="audio/t38"/>
+  <mime-type type="audio/telephone-event"/>
+  <mime-type type="audio/tone"/>
+  <mime-type type="audio/ulpfec"/>
+  <mime-type type="audio/vdvi"/>
+  <mime-type type="audio/vmr-wb"/>
+  <mime-type type="audio/vnd.3gpp.iufp"/>
+  <mime-type type="audio/vnd.4sb"/>
+  <mime-type type="audio/vnd.audiokoz"/>
+  <mime-type type="audio/vnd.celp"/>
+  <mime-type type="audio/vnd.cisco.nse"/>
+  <mime-type type="audio/vnd.cmles.radio-events"/>
+  <mime-type type="audio/vnd.cns.anp1"/>
+  <mime-type type="audio/vnd.cns.inf1"/>
+  <mime-type type="audio/vnd.digital-winds">
+    <glob pattern="*.eol"/>
+  </mime-type>
+  <mime-type type="audio/vnd.dlna.adts"/>
+  <mime-type type="audio/vnd.dolby.heaac.1"/>
+  <mime-type type="audio/vnd.dolby.heaac.2"/>
+  <mime-type type="audio/vnd.dolby.mlp"/>
+  <mime-type type="audio/vnd.dolby.mps"/>
+  <mime-type type="audio/vnd.dolby.pl2"/>
+  <mime-type type="audio/vnd.dolby.pl2x"/>
+  <mime-type type="audio/vnd.dolby.pl2z"/>
+  <mime-type type="audio/vnd.dts">
+    <glob pattern="*.dts"/>
+  </mime-type>
+  <mime-type type="audio/vnd.dts.hd">
+    <glob pattern="*.dtshd"/>
+  </mime-type>
+  <mime-type type="audio/vnd.everad.plj"/>
+  <mime-type type="audio/vnd.hns.audio"/>
+  <mime-type type="audio/vnd.lucent.voice">
+    <glob pattern="*.lvp"/>
+  </mime-type>
+  <mime-type type="audio/vnd.ms-playready.media.pya">
+    <glob pattern="*.pya"/>
+  </mime-type>
+  <mime-type type="audio/vnd.nokia.mobile-xmf"/>
+  <mime-type type="audio/vnd.nortel.vbk"/>
+  <mime-type type="audio/vnd.nuera.ecelp4800">
+    <glob pattern="*.ecelp4800"/>
+  </mime-type>
+  <mime-type type="audio/vnd.nuera.ecelp7470">
+    <glob pattern="*.ecelp7470"/>
+  </mime-type>
+  <mime-type type="audio/vnd.nuera.ecelp9600">
+    <glob pattern="*.ecelp9600"/>
+  </mime-type>
+  <mime-type type="audio/vnd.octel.sbc"/>
+  <mime-type type="audio/vnd.qcelp"/>
+  <mime-type type="audio/vnd.rhetorex.32kadpcm"/>
+  <mime-type type="audio/vnd.sealedmedia.softseal.mpeg"/>
+  <mime-type type="audio/vnd.vmx.cvsd"/>
+  <mime-type type="audio/vorbis"/>
+  <mime-type type="audio/vorbis-config"/>
+  <mime-type type="audio/x-aac">
+    <glob pattern="*.aac"/>
+  </mime-type>
+
+  <mime-type type="audio/x-adbcm">
+    <magic priority="20">
+      <match value=".snd" type="string" offset="0">
+        <match value="23" type="big32" offset="12"/>
+      </match>
+    </magic>
+  </mime-type>
+
+  <mime-type type="audio/x-aiff">
+    <alias type="audio/aiff"/>
+    <acronym>AIFF</acronym>
+    <_comment>Audio Interchange File Format</_comment>
+    <magic priority="20">
+      <match value="FORM....AIFF" type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+      <match value="FORM....AIFC" type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+      <!-- Amiga IFF sound sample, somewhat like the more modern AIFF -->
+      <match value="FORM....8SVX" type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+    </magic>
+    <glob pattern="*.aif"/>
+    <glob pattern="*.aiff"/>
+    <glob pattern="*.aifc"/>
+  </mime-type>
+
+  <mime-type type="audio/x-dec-basic">
+    <magic priority="20">
+      <match value="0x0064732E" type="big32" offset="0">
+        <match value="1" type="big32" offset="12"/>
+        <match value="2" type="big32" offset="12"/>
+        <match value="3" type="big32" offset="12"/>
+        <match value="4" type="big32" offset="12"/>
+        <match value="5" type="big32" offset="12"/>
+        <match value="6" type="big32" offset="12"/>
+        <match value="7" type="big32" offset="12"/>
+      </match>
+    </magic>
+  </mime-type>
+
+  <mime-type type="audio/x-dec-adbcm">
+    <magic priority="20">
+      <match value="0x0064732E" type="big32" offset="0">
+        <match value="23" type="big32" offset="12"/>
+      </match>
+    </magic>
+  </mime-type>
+
+  <mime-type type="audio/x-flac">
+    <acronym>FLAC</acronym>
+    <_comment>Free Lossless Audio Codec</_comment>
+    <magic priority="50">
+      <match value="fLaC" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.flac"/>
+  </mime-type>
+
+  <mime-type type="audio/x-mod">
+    <acronym>MOD</acronym>
+    <magic priority="50">
+      <match value="Extended\ Module:" type="string" offset="0"/>
+      <match value="BMOD2STM" type="string" offset="21"/>
+      <match value="M.K." type="string" offset="1080"/>
+      <match value="M!K!" type="string" offset="1080"/>
+      <match value="FLT4" type="string" offset="1080"/>
+      <match value="FLT8" type="string" offset="1080"/>
+      <match value="4CHN" type="string" offset="1080"/>
+      <match value="6CHN" type="string" offset="1080"/>
+      <match value="8CHN" type="string" offset="1080"/>
+      <match value="CD81" type="string" offset="1080"/>
+      <match value="OKTA" type="string" offset="1080"/>
+      <match value="16CN" type="string" offset="1080"/>
+      <match value="32CN" type="string" offset="1080"/>
+      <match value="IMPM" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.mod"/>
+  </mime-type>
+
+  <mime-type type="audio/x-mpegurl">
+    <glob pattern="*.m3u"/>
+  </mime-type>
+  <mime-type type="audio/x-ms-wax">
+    <glob pattern="*.wax"/>
+  </mime-type>
+  <mime-type type="audio/x-ms-wma">
+    <glob pattern="*.wma"/>
+  </mime-type>
+
+  <mime-type type="audio/x-pn-realaudio">
+    <_comment>Real Audio</_comment>
+    <alias type="audio/x-realaudio" />
+    <magic priority="50">
+      <match value="0x2e7261fd" type="big32" offset="0"/>
+    </magic>
+    <glob pattern="*.ram"/>
+    <glob pattern="*.ra"/>
+  </mime-type>
+
+  <mime-type type="audio/x-pn-realaudio-plugin">
+    <glob pattern="*.rmp"/>
+  </mime-type>
+
+  <mime-type type="audio/x-wav">
+    <acronym>WAV</acronym>
+    <magic priority="20">
+      <match value="RIFF....WAVE" type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+    </magic>
+    <glob pattern="*.wav"/>
+  </mime-type>
+
+  <mime-type type="chemical/x-cdx">
+    <glob pattern="*.cdx"/>
+  </mime-type>
+  <mime-type type="chemical/x-cif">
+    <glob pattern="*.cif"/>
+  </mime-type>
+  <mime-type type="chemical/x-cmdf">
+    <glob pattern="*.cmdf"/>
+  </mime-type>
+  <mime-type type="chemical/x-cml">
+    <glob pattern="*.cml"/>
+  </mime-type>
+  <mime-type type="chemical/x-csml">
+    <glob pattern="*.csml"/>
+  </mime-type>
+  <mime-type type="chemical/x-pdb"/>
+  <mime-type type="chemical/x-xyz">
+    <glob pattern="*.xyz"/>
+  </mime-type>
+
+  <mime-type type="image/bmp">
+    <alias type="image/x-ms-bmp"/>
+    <acronym>BMP</acronym>
+    <_comment>Windows bitmap</_comment>
+    <magic priority="50">
+      <match value="BM" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.bmp"/>
+    <glob pattern="*.dib"/>
+  </mime-type>
+
+  <mime-type type="image/cgm">
+    <acronym>CGM</acronym>
+    <_comment>Computer Graphics Metafile</_comment>
+    <magic priority="50">
+      <match value="BEGMF" type="string" offset="0"/>
+      <match value="0x0020" mask="0xffe0" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.cgm"/>
+  </mime-type>
+
+  <mime-type type="image/example"/>
+  <mime-type type="image/fits"/>
+  <mime-type type="image/g3fax">
+    <glob pattern="*.g3"/>
+  </mime-type>
+
+  <mime-type type="image/gif">
+    <acronym>GIF</acronym>
+    <_comment>Graphics Interchange Format</_comment>
+    <magic priority="50">
+      <match value="GIF87a" type="string" offset="0"/>
+      <match value="GIF89a" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.gif"/>
+  </mime-type>
+
+  <mime-type type="image/ief">
+    <glob pattern="*.ief"/>
+  </mime-type>
+  <mime-type type="image/jp2"/>
+
+  <mime-type type="image/jpeg">
+    <acronym>JPEG</acronym>
+    <_comment>Joint Photographic Experts Group</_comment>
+    <magic priority="50">
+      <!-- FFD8 is the SOI (Start Of Image) marker.              -->
+      <!-- It is followed by another marker that starts with FF. -->
+      <match value="0xffd8ff" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.jpg"/>
+    <glob pattern="*.jpeg"/>
+    <glob pattern="*.jpe"/>
+    <glob pattern="*.jif"/>
+    <glob pattern="*.jfif"/>
+    <glob pattern="*.jfi"/>
+  </mime-type>
+
+  <mime-type type="image/jpm"/>
+  <mime-type type="image/jpx"/>
+  <mime-type type="image/naplps"/>
+
+  <mime-type type="image/png">
+    <acronym>PNG</acronym>
+    <_comment>Portable Network Graphics</_comment>
+    <magic priority="50">
+      <match value="\x89PNG\x0d\x0a\x1a\x0a" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.png"/>
+  </mime-type>
+
+  <mime-type type="image/prs.btif">
+    <glob pattern="*.btif"/>
+  </mime-type>
+  <mime-type type="image/prs.pti"/>
+
+  <mime-type type="image/svg+xml">
+    <sub-class-of type="application/xml"/>
+    <acronym>SVG</acronym>
+    <_comment>Scalable Vector Graphics</_comment>
+    <root-XML localName="svg" namespaceURI="http://www.w3.org/2000/svg"/>
+    <glob pattern="*.svg"/>
+    <glob pattern="*.svgz"/>
+  </mime-type>
+
+  <mime-type type="image/t38"/>
+
+  <mime-type type="image/tiff">
+    <acronym>TIFF</acronym>
+    <_comment>Tagged Image File Format</_comment>
+    <magic priority="50">
+      <!-- MM.* = Big endian (M=Motorola) and 0x002a in big endian    -->
+      <match value="MM\x00\x2a" type="string" offset="0"/>
+      <!-- II*. = Little endian (I=Intel) and 0x002a in little endian -->
+      <match value="II\x2a\x00" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.tiff"/>
+    <glob pattern="*.tif"/>
+  </mime-type>
+
+  <mime-type type="image/tiff-fx"/>
+
+  <mime-type type="image/vnd.adobe.photoshop">
+    <alias type="image/x-psd"/>
+    <glob pattern="*.psd"/>
+  </mime-type>
+
+  <mime-type type="image/vnd.cns.inf2"/>
+  <mime-type type="image/vnd.djvu">
+    <glob pattern="*.djvu"/>
+    <glob pattern="*.djv"/>
+  </mime-type>
+
+  <mime-type type="image/vnd.dwg">
+    <acronym>DWG</acronym>
+    <_comment>AutoCad Drawing</_comment>
+    <alias type="image/x-dwg"/>
+    <alias type="application/acad"/>
+    <alias type="application/x-acad"/>
+    <alias type="application/autocad_dwg"/>
+    <alias type="application/dwg"/>
+    <alias type="application/x-dwg"/>
+    <alias type="application/x-autocad"/>
+    <glob pattern="*.dwg"/>
+    <magic priority="50">
+      <!-- "AC" followed by four numbers -->
+      <match value="AC0000" type="string" offset="0"
+             mask="0xFFFFF0F0F0F0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="image/vnd.dxf">
+    <glob pattern="*.dxf"/>
+  </mime-type>
+  <mime-type type="image/vnd.fastbidsheet">
+    <glob pattern="*.fbs"/>
+  </mime-type>
+  <mime-type type="image/vnd.fpx">
+    <glob pattern="*.fpx"/>
+  </mime-type>
+  <mime-type type="image/vnd.fst">
+    <glob pattern="*.fst"/>
+  </mime-type>
+  <mime-type type="image/vnd.fujixerox.edmics-mmr">
+    <glob pattern="*.mmr"/>
+  </mime-type>
+  <mime-type type="image/vnd.fujixerox.edmics-rlc">
+    <glob pattern="*.rlc"/>
+  </mime-type>
+  <mime-type type="image/vnd.globalgraphics.pgb"/>
+  <mime-type type="image/vnd.microsoft.icon"/>
+  <mime-type type="image/vnd.mix"/>
+  <mime-type type="image/vnd.ms-modi">
+    <glob pattern="*.mdi"/>
+  </mime-type>
+  <mime-type type="image/vnd.net-fpx">
+    <glob pattern="*.npx"/>
+  </mime-type>
+  <mime-type type="image/vnd.radiance"/>
+  <mime-type type="image/vnd.sealed.png"/>
+  <mime-type type="image/vnd.sealedmedia.softseal.gif"/>
+  <mime-type type="image/vnd.sealedmedia.softseal.jpg"/>
+  <mime-type type="image/vnd.svf"/>
+
+  <mime-type type="image/vnd.wap.wbmp">
+    <_comment>Wireless Bitmap File Format</_comment>
+    <glob pattern="*.wbmp"/>
+  </mime-type>
+
+  <mime-type type="image/vnd.xiff">
+    <glob pattern="*.xif"/>
+  </mime-type>
+  <mime-type type="image/x-cmu-raster">
+    <glob pattern="*.ras"/>
+  </mime-type>
+  <mime-type type="image/x-cmx">
+    <glob pattern="*.cmx"/>
+  </mime-type>
+  <mime-type type="image/x-freehand">
+    <glob pattern="*.fh"/>
+    <glob pattern="*.fhc"/>
+    <glob pattern="*.fh4"/>
+    <glob pattern="*.fh5"/>
+    <glob pattern="*.fh7"/>
+  </mime-type>
+
+  <mime-type type="image/x-icon">
+    <magic priority="50">
+      <match value="\102\101\050\000\000\000\056\000\000\000\000\000\000\000"
+             type="string" offset="0"/>
+      <match value="\000\000\001\000" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.ico"/>
+  </mime-type>
+
+  <mime-type type="image/x-niff">
+    <_comment>Navy Interchange File Format</_comment>
+    <magic priority="50">
+      <match value="IIN1" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="image/x-pcx">
+    <glob pattern="*.pcx"/>
+  </mime-type>
+  <mime-type type="image/x-pict">
+    <glob pattern="*.pic"/>
+    <glob pattern="*.pct"/>
+  </mime-type>
+
+  <mime-type type="image/x-portable-anymap">
+    <acronym>PNM</acronym>
+    <_comment>Portable Any Map</_comment>
+    <glob pattern="*.pnm" />
+  </mime-type>
+
+  <mime-type type="image/x-portable-bitmap">
+    <sub-class-of type="image/x-portable-anymap"/>
+    <acronym>PBM</acronym>
+    <_comment>Portable Bit Map</_comment>
+    <magic priority="50">
+      <match value="P1" type="string" offset="0"/>
+      <match value="P4" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.pbm"/>
+  </mime-type>
+
+  <mime-type type="image/x-portable-graymap">
+    <sub-class-of type="image/x-portable-anymap"/>
+    <acronym>PGM</acronym>
+    <_comment>Portable Gray Map</_comment>
+    <magic priority="50">
+      <match value="P2" type="string" offset="0"/>
+      <match value="P5" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.pgm"/>
+  </mime-type>
+
+  <mime-type type="image/x-portable-pixmap">
+    <sub-class-of type="image/x-portable-anymap"/>
+    <acronym>PXM</acronym>
+    <_comment>Portable Pixel Map</_comment>
+    <magic priority="50">
+      <match value="P3" type="string" offset="0"/>
+      <match value="P6" type="string" offset="0"/>
+      <match value="P7" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.ppm"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-adobe">
+    <acronym>DNG</acronym>
+    <_comment>Adobe Digital Negative</_comment>
+    <glob pattern="*.dng"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-hasselblad">
+    <_comment>Hasselblad raw image</_comment>
+    <glob pattern="*.3fr"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-fuji">
+    <_comment>Fuji raw image</_comment>
+    <glob pattern="*.raf"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-canon">
+    <_comment>Canon raw image</_comment>
+    <glob pattern="*.crw"/>
+    <glob pattern="*.cr2"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-kodak">
+    <_comment>Kodak raw image</_comment>
+    <glob pattern="*.k25"/>
+    <glob pattern="*.kdc"/>
+    <glob pattern="*.dcs"/>
+    <glob pattern="*.drf"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-minolta">
+    <_comment>Minolta raw image</_comment>
+    <glob pattern="*.mrw"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-nikon">
+    <_comment>Nikon raw image</_comment>
+    <glob pattern="*.nef"/>
+    <glob pattern="*.nrw"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-olympus">
+    <_comment>Olympus raw image</_comment>
+    <glob pattern="*.orf"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-pentax">
+    <_comment>Pentax raw image</_comment>
+    <glob pattern="*.ptx"/>
+    <glob pattern="*.pef"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-sony">
+    <_comment>Sony raw image</_comment>
+    <glob pattern="*.arw"/>
+    <glob pattern="*.srf"/>
+    <glob pattern="*.sr2"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-sigma">
+    <_comment>Sigma raw image</_comment>
+    <glob pattern="*.x3f"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-epson">
+    <_comment>Epson raw image</_comment>
+    <glob pattern="*.erf"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-mamiya">
+    <_comment>Mamiya raw image</_comment>
+    <glob pattern="*.mef"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-leaf">
+    <_comment>Leaf raw image</_comment>
+    <glob pattern="*.mos"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-panasonic">
+    <_comment>Panasonic raw image</_comment>
+    <glob pattern="*.raw"/>
+    <glob pattern="*.rw2"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-phaseone">
+    <_comment>Phase One raw image</_comment>
+    <glob pattern="*.cap"/>
+    <glob pattern="*.iiq"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-red">
+    <_comment>Red raw image</_comment>
+    <glob pattern="*.r3d"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-imacon">
+    <_comment>Imacon raw image</_comment>
+    <glob pattern="*.fff"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-logitech">
+    <_comment>Logitech raw image</_comment>
+    <glob pattern="*.pxn"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-casio">
+    <_comment>Casio raw image</_comment>
+    <glob pattern="*.bay"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-rawzor">
+    <_comment>Rawzor raw image</_comment>
+    <glob pattern="*.rwz"/>
+  </mime-type>
+
+  <mime-type type="image/x-rgb">
+    <glob pattern="*.rgb"/>
+  </mime-type>
+
+  <mime-type type="image/x-xbitmap">
+    <magic priority="50">
+      <match value="/* XPM" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.xbm"/>
+    <sub-class-of type="text/x-c"/>
+  </mime-type>
+
+  <mime-type type="image/x-xcf">
+    <alias type="image/xcf"/>
+    <magic priority="50">
+      <match type="string" value="gimp xcf " offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="image/x-xpixmap">
+    <glob pattern="*.xpm"/>
+  </mime-type>
+  <mime-type type="image/x-xwindowdump">
+    <glob pattern="*.xwd"/>
+  </mime-type>
+
+  <mime-type type="message/cpim"/>
+  <mime-type type="message/delivery-status"/>
+  <mime-type type="message/disposition-notification"/>
+  <mime-type type="message/example"/>
+  <mime-type type="message/external-body"/>
+  <mime-type type="message/global"/>
+  <mime-type type="message/global-delivery-status"/>
+  <mime-type type="message/global-disposition-notification"/>
+  <mime-type type="message/global-headers"/>
+  <mime-type type="message/http"/>
+  <mime-type type="message/imdn+xml"/>
+
+  <mime-type type="message/news">
+    <magic priority="50">
+      <match value="Path:" type="string" offset="0" />
+      <match value="Xref:" type="string" offset="0" />
+      <match value="Article" type="string" offset="0" />
+    </magic>
+  </mime-type>
+
+  <mime-type type="message/partial"/>
+
+  <mime-type type="message/rfc822">
+    <magic priority="50">
+      <match value="Relay-Version:" type="string" offset="0"/>
+      <match value="#!\ rnews" type="string" offset="0"/>
+      <match value="N#!\ rnews" type="string" offset="0"/>
+      <match value="Forward\ to" type="string" offset="0"/>
+      <match value="Pipe\ to" type="string" offset="0"/>
+      <match value="Return-Path:" type="string" offset="0"/>
+      <match value="From:" type="string" offset="0"/>
+      <match value="Received:" type="string" offset="0"/>
+      <match type="string" value="Message-ID:" offset="0"/>
+      <match type="string" value="Date:" offset="0"/>
+    </magic>
+    <glob pattern="*.eml"/>
+    <glob pattern="*.mime"/>
+  </mime-type>
+
+  <mime-type type="message/s-http"/>
+  <mime-type type="message/sip"/>
+  <mime-type type="message/sipfrag"/>
+  <mime-type type="message/tracking-status"/>
+  <mime-type type="message/vnd.si.simp"/>
+
+  <mime-type type="model/example"/>
+
+  <mime-type type="model/iges">
+    <_comment>Initial Graphics Exchange Specification Format</_comment>
+    <glob pattern="*.igs"/>
+    <glob pattern="*.iges"/>
+  </mime-type>
+
+  <mime-type type="model/mesh">
+    <glob pattern="*.msh"/>
+    <glob pattern="*.mesh"/>
+    <glob pattern="*.silo"/>
+  </mime-type>
+
+  <mime-type type="model/vnd.dwf">
+    <glob pattern="*.dwf"/>
+  </mime-type>
+  <mime-type type="model/vnd.flatland.3dml"/>
+  <mime-type type="model/vnd.gdl">
+    <glob pattern="*.gdl"/>
+  </mime-type>
+  <mime-type type="model/vnd.gs-gdl"/>
+  <mime-type type="model/vnd.gs.gdl"/>
+  <mime-type type="model/vnd.gtw">
+    <glob pattern="*.gtw"/>
+  </mime-type>
+  <mime-type type="model/vnd.moml+xml"/>
+  <mime-type type="model/vnd.mts">
+    <glob pattern="*.mts"/>
+  </mime-type>
+  <mime-type type="model/vnd.parasolid.transmit.binary"/>
+  <mime-type type="model/vnd.parasolid.transmit.text"/>
+  <mime-type type="model/vnd.vtu">
+    <glob pattern="*.vtu"/>
+  </mime-type>
+
+  <mime-type type="model/vrml">
+    <glob pattern="*.wrl"/>
+    <glob pattern="*.vrml"/>
+  </mime-type>
+
+  <mime-type type="multipart/alternative"/>
+  <mime-type type="multipart/appledouble"/>
+  <mime-type type="multipart/byteranges"/>
+  <mime-type type="multipart/digest"/>
+  <mime-type type="multipart/encrypted"/>
+  <mime-type type="multipart/example"/>
+  <mime-type type="multipart/form-data"/>
+  <mime-type type="multipart/header-set"/>
+  <mime-type type="multipart/mixed"/>
+  <mime-type type="multipart/parallel"/>
+  <mime-type type="multipart/related"/>
+  <mime-type type="multipart/report"/>
+  <mime-type type="multipart/signed"/>
+  <mime-type type="multipart/voice-message"/>
+  <mime-type type="text/calendar">
+    <glob pattern="*.ics"/>
+    <glob pattern="*.ifb"/>
+  </mime-type>
+
+  <mime-type type="text/css">
+    <_comment>Cascading Style Sheet</_comment>
+    <glob pattern="*.css"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="text/csv">
+    <glob pattern="*.csv"/>
+  </mime-type>
+  <mime-type type="text/directory"/>
+  <mime-type type="text/dns"/>
+  <mime-type type="text/ecmascript"/>
+  <mime-type type="text/enriched"/>
+  <mime-type type="text/example"/>
+
+  <mime-type type="text/html">
+     <!-- TIKA-327: if you encounter tags in the HTML
+          with no declared namespace, it's not XHTML, it's just
+          bad HTML, unfortunately.
+     -->
+    <root-XML localName="html"/>
+    <root-XML localName="HTML"/>
+    <root-XML localName="link"/>
+    <root-XML localName="LINK"/>
+    <root-XML localName="body"/>
+    <root-XML localName="BODY"/>
+    <root-XML localName="p"/>
+    <root-XML localName="P"/>
+    <root-XML localName="script"/>
+    <root-XML localName="SCRIPT"/>
+    <root-XML localName="frameset"/>
+    <root-XML localName="FRAMESET"/>
+    <magic priority="50">
+      <match value="&lt;!DOCTYPE HTML" type="string" offset="0:64"/>
+      <match value="&lt;!doctype html" type="string" offset="0:64"/>
+      <match value="&lt;HEAD" type="string" offset="0:64"/>
+      <match value="&lt;head" type="string" offset="0:64"/>
+      <match value="&lt;TITLE" type="string" offset="0:64"/>
+      <match value="&lt;title" type="string" offset="0:64"/>
+      <!-- note on the offset value here: this can only be as big as
+           MimeTypes#getMinLength(). If you set the offset value to larger
+           than that size, the magic will only be compared to up to
+           MimeTypes#getMinLength() bytes.
+       -->
+      <match value="&lt;html" type="string" offset="0:8192"/>
+      <match value="&lt;HTML" type="string" offset="0:64"/>
+      <match value="&lt;BODY" type="string" offset="0"/>
+      <match value="&lt;body" type="string" offset="0"/>
+      <match value="&lt;TITLE" type="string" offset="0"/>
+      <match value="&lt;title" type="string" offset="0"/>
+      <match value="&lt;h1" type="string" offset="0"/>
+      <match value="&lt;H1" type="string" offset="0"/>
+      <match value="&lt;!doctype HTML" type="string" offset="0"/>
+      <match value="&lt;!DOCTYPE html" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.html"/>
+    <glob pattern="*.htm"/>
+  </mime-type>
+
+  <mime-type type="text/javascript"/>
+  <mime-type type="text/parityfec"/>
+
+  <mime-type type="text/plain">
+    <magic priority="20">
+      <match value="This is TeX," type="string" offset="0"/>
+      <match value="This is METAFONT," type="string" offset="0"/>
+      <match value="/*" type="string" offset="0"/>
+      <match value="//" type="string" offset="0"/>
+      <match value=";;" type="string" offset="0"/>
+      <!-- UTF-16BE BOM -->
+      <match value="0xfeff" type="string" offset="0"/>
+      <!-- UTF-16LE BOM -->
+      <match value="0xfffe" type="string" offset="0"/>
+      <!-- UTF-8 BOM -->
+      <match value="0xefbbbf" type="string" offset="0"/>
+    </magic>
+
+    <glob pattern="*.txt"/>
+    <glob pattern="*.text"/>
+    <glob pattern="*.conf"/>
+    <glob pattern="*.def"/>
+    <glob pattern="*.list"/>
+    <glob pattern="*.log"/>
+    <glob pattern="*.in"/>
+
+    <!-- TIKA-85: http://www.apache.org/dev/svn-eol-style.txt -->
+    <glob pattern="INSTALL"/>
+    <glob pattern="KEYS"/>
+    <glob pattern="Makefile"/>
+    <glob pattern="README"/>
+    <glob pattern="abs-linkmap"/>
+    <glob pattern="abs-menulinks"/>
+    <glob pattern="*.aart"/>
+    <glob pattern="*.ac"/>
+    <glob pattern="*.am"/>
+    <glob pattern="*.cgi"/>
+    <glob pattern="*.classpath"/>
+    <glob pattern="*.cmd"/>
+    <glob pattern="*.config"/>
+    <glob pattern="*.cwiki"/>
+    <glob pattern="*.data"/>
+    <glob pattern="*.dcl"/>
+    <glob pattern="*.egrm"/>
+    <glob pattern="*.ent"/>
+    <glob pattern="*.ft"/>
+    <glob pattern="*.fn"/>
+    <glob pattern="*.fv"/>
+    <glob pattern="*.grm"/>
+    <glob pattern="*.g"/>
+    <glob pattern=".htaccess"/>
+    <glob pattern="*.ihtml"/>
+    <glob pattern="*.jmx"/>
+    <glob pattern="*.jsp"/>
+    <glob pattern="*.junit"/>
+    <glob pattern="*.jx"/>
+    <glob pattern="*.manifest"/>
+    <glob pattern="*.m4"/>
+    <glob pattern="*.mf"/>
+    <glob pattern="*.MF"/>
+    <glob pattern="*.meta"/>
+    <glob pattern="*.n3"/>
+    <glob pattern="*.pen"/>
+    <glob pattern="*.pl"/>
+    <glob pattern="*.pm"/>
+    <glob pattern="*.pod"/>
+    <glob pattern="*.pom"/>
+    <glob pattern="*.project"/>
+    <glob pattern="*.properties"/>
+    <glob pattern="*.py"/>
+    <glob pattern="*.rb"/>
+    <glob pattern="*.rng"/>
+    <glob pattern="*.rnx"/>
+    <glob pattern="*.roles"/>
+    <glob pattern="*.sql"/>
+    <glob pattern="*.tld"/>
+    <glob pattern="*.types"/>
+    <glob pattern="*.vm"/>
+    <glob pattern="*.vsl"/>
+    <glob pattern="*.wsdd"/>
+    <glob pattern="*.xargs"/>
+    <glob pattern="*.xcat"/>
+    <glob pattern="*.xconf"/>
+    <glob pattern="*.xegrm"/>
+    <glob pattern="*.xgrm"/>
+    <glob pattern="*.xlex"/>
+    <glob pattern="*.xlog"/>
+    <glob pattern="*.xmap"/>
+    <glob pattern="*.xroles"/>
+    <glob pattern="*.xsamples"/>
+    <glob pattern="*.xsp"/>
+    <glob pattern="*.xweb"/>
+    <glob pattern="*.xwelcome"/>
+  </mime-type>
+
+  <mime-type type="text/prs.fallenstein.rst"/>
+  <mime-type type="text/prs.lines.tag">
+    <glob pattern="*.dsc"/>
+  </mime-type>
+  <mime-type type="text/red"/>
+  <mime-type type="text/rfc822-headers"/>
+  <mime-type type="text/richtext">
+    <glob pattern="*.rtx"/>
+  </mime-type>
+  <mime-type type="text/rtf"/>
+  <mime-type type="text/rtp-enc-aescm128"/>
+  <mime-type type="text/rtx"/>
+  <mime-type type="text/sgml">
+    <glob pattern="*.sgml"/>
+    <glob pattern="*.sgm"/>
+  </mime-type>
+  <mime-type type="text/t140"/>
+  <mime-type type="text/tab-separated-values">
+    <glob pattern="*.tsv"/>
+  </mime-type>
+
+  <mime-type type="text/troff">
+    <alias type="application/x-troff"/>
+    <alias type="application/x-troff-man"/>
+    <alias type="application/x-troff-me"/>
+    <alias type="application/x-troff-ms"/>
+    <magic priority="50">
+      <match value=".\\&quot;" type="string" offset="0"/>
+      <match value="'\\&quot;" type="string" offset="0"/>
+      <match value="'.\\&quot;" type="string" offset="0"/>
+      <match value="\\&quot;" type="string" offset="0"/>
+      <match value="'''" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.t"/>
+    <glob pattern="*.tr"/>
+    <glob pattern="*.roff"/>
+    <glob pattern="*.man"/>
+    <glob pattern="*.me"/>
+    <glob pattern="*.ms"/>
+  </mime-type>
+
+  <mime-type type="text/ulpfec"/>
+  <mime-type type="text/uri-list">
+    <glob pattern="*.uri"/>
+    <glob pattern="*.uris"/>
+    <glob pattern="*.urls"/>
+  </mime-type>
+  <mime-type type="text/vnd.abc"/>
+  <mime-type type="text/vnd.curl">
+    <glob pattern="*.curl"/>
+  </mime-type>
+  <mime-type type="text/vnd.curl.dcurl">
+    <glob pattern="*.dcurl"/>
+  </mime-type>
+  <mime-type type="text/vnd.curl.scurl">
+    <glob pattern="*.scurl"/>
+  </mime-type>
+  <mime-type type="text/vnd.curl.mcurl">
+    <glob pattern="*.mcurl"/>
+  </mime-type>
+  <mime-type type="text/vnd.dmclientscript"/>
+  <mime-type type="text/vnd.esmertec.theme-descriptor"/>
+  <mime-type type="text/vnd.fly">
+    <glob pattern="*.fly"/>
+  </mime-type>
+  <mime-type type="text/vnd.fmi.flexstor">
+    <glob pattern="*.flx"/>
+  </mime-type>
+  <mime-type type="text/vnd.graphviz">
+    <glob pattern="*.gv"/>
+  </mime-type>
+  <mime-type type="text/vnd.in3d.3dml">
+    <glob pattern="*.3dml"/>
+  </mime-type>
+  <mime-type type="text/vnd.in3d.spot">
+    <glob pattern="*.spot"/>
+  </mime-type>
+  <mime-type type="text/vnd.iptc.newsml"/>
+  <mime-type type="text/vnd.iptc.nitf"/>
+  <mime-type type="text/vnd.latex-z"/>
+  <mime-type type="text/vnd.motorola.reflex"/>
+  <mime-type type="text/vnd.ms-mediapackage"/>
+  <mime-type type="text/vnd.net2phone.commcenter.command"/>
+  <mime-type type="text/vnd.si.uricatalogue"/>
+  <mime-type type="text/vnd.sun.j2me.app-descriptor">
+    <glob pattern="*.jad"/>
+  </mime-type>
+  <mime-type type="text/vnd.trolltech.linguist"/>
+  <mime-type type="text/vnd.wap.si"/>
+  <mime-type type="text/vnd.wap.sl"/>
+  <mime-type type="text/vnd.wap.wml">
+    <glob pattern="*.wml"/>
+  </mime-type>
+
+  <mime-type type="text/vnd.wap.wmlscript">
+    <_comment>WML Script</_comment>
+    <glob pattern="*.wmls"/>
+  </mime-type>
+
+  <mime-type type="text/x-asm">
+    <glob pattern="*.s"/>
+    <glob pattern="*.asm"/>
+  </mime-type>
+
+  <mime-type type="text/x-c">
+    <glob pattern="*.c"/>
+    <glob pattern="*.cc"/>
+    <glob pattern="*.cxx"/>
+    <glob pattern="*.cpp"/>
+    <glob pattern="*.h"/>
+    <glob pattern="*.hh"/>
+    <glob pattern="*.dic"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="text/x-diff">
+    <magic priority="50">
+      <match value="diff\ " type="string" offset="0"/>
+      <match value="***\ " type="string" offset="0"/>
+      <match value="Only\ in\ " type="string" offset="0"/>
+      <match value="Common\ subdirectories:\ " type="string" offset="0"/>
+      <match value="Index:" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.diff"/>
+    <glob pattern="*.patch"/>
+  </mime-type>
+
+  <mime-type type="text/x-fortran">
+    <glob pattern="*.f"/>
+    <glob pattern="*.for"/>
+    <glob pattern="*.f77"/>
+    <glob pattern="*.f90"/>
+  </mime-type>
+  <mime-type type="text/x-pascal">
+    <glob pattern="*.p"/>
+    <glob pattern="*.pas"/>
+  </mime-type>
+
+  <mime-type type="text/x-java-source">
+    <glob pattern="*.java"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="text/x-setext">
+    <glob pattern="*.etx"/>
+  </mime-type>
+
+  <mime-type type="text/x-uuencode">
+    <glob pattern="*.uu"/>
+  </mime-type>
+  <mime-type type="text/x-vcalendar">
+    <glob pattern="*.vcs"/>
+  </mime-type>
+  <mime-type type="text/x-vcard">
+    <glob pattern="*.vcf"/>
+  </mime-type>
+  <mime-type type="text/xml"/>
+  <mime-type type="text/xml-external-parsed-entity"/>
+  <mime-type type="video/3gpp">
+    <glob pattern="*.3gp"/>
+  </mime-type>
+  <mime-type type="video/3gpp-tt"/>
+  <mime-type type="video/3gpp2">
+    <glob pattern="*.3g2"/>
+  </mime-type>
+  <mime-type type="video/bmpeg"/>
+  <mime-type type="video/bt656"/>
+  <mime-type type="video/celb"/>
+  <mime-type type="video/dv"/>
+  <mime-type type="video/example"/>
+  <mime-type type="video/h261">
+    <glob pattern="*.h261"/>
+  </mime-type>
+  <mime-type type="video/h263">
+    <glob pattern="*.h263"/>
+  </mime-type>
+  <mime-type type="video/h263-1998"/>
+  <mime-type type="video/h263-2000"/>
+  <mime-type type="video/h264">
+    <glob pattern="*.h264"/>
+  </mime-type>
+  <mime-type type="video/jpeg">
+    <glob pattern="*.jpgv"/>
+  </mime-type>
+  <mime-type type="video/jpeg2000"/>
+  <mime-type type="video/jpm">
+    <glob pattern="*.jpm"/>
+    <glob pattern="*.jpgm"/>
+  </mime-type>
+  <mime-type type="video/mj2">
+    <glob pattern="*.mj2"/>
+    <glob pattern="*.mjp2"/>
+  </mime-type>
+  <mime-type type="video/mp1s"/>
+  <mime-type type="video/mp2p"/>
+  <mime-type type="video/mp2t"/>
+  <mime-type type="video/mp4">
+    <glob pattern="*.mp4"/>
+    <glob pattern="*.mp4v"/>
+    <glob pattern="*.mpg4"/>
+  </mime-type>
+  <mime-type type="video/mp4v-es"/>
+
+  <mime-type type="video/mpeg">
+    <magic priority="50">
+      <match value="\000\000\001\263" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.mpeg"/>
+    <glob pattern="*.mpg"/>
+    <glob pattern="*.mpe"/>
+    <glob pattern="*.m1v"/>
+    <glob pattern="*.m2v"/>
+  </mime-type>
+
+  <mime-type type="video/vnd.mpegurl">
+    <glob pattern="*.mxu"/>
+  </mime-type>
+
+  <mime-type type="video/mpeg4-generic"/>
+  <mime-type type="video/mpv"/>
+  <mime-type type="video/nv"/>
+
+  <mime-type type="video/ogg">
+    <glob pattern="*.ogv"/>
+    <sub-class-of type="application/ogg"/>
+  </mime-type>
+
+  <mime-type type="video/parityfec"/>
+  <mime-type type="video/pointer"/>
+
+  <mime-type type="video/quicktime">
+    <magic priority="50">
+      <match value="moov" type="string" offset="4"/>
+      <match value="mdat" type="string" offset="4"/>
+      <match value="ftyp" type="string" offset="4"/>
+    </magic>
+    <glob pattern="*.qt"/>
+    <glob pattern="*.mov"/>
+  </mime-type>
+
+  <mime-type type="video/raw"/>
+  <mime-type type="video/rtp-enc-aescm128"/>
+  <mime-type type="video/rtx"/>
+  <mime-type type="video/smpte292m"/>
+  <mime-type type="video/ulpfec"/>
+  <mime-type type="video/vc1"/>
+  <mime-type type="video/vnd.cctv"/>
+  <mime-type type="video/vnd.dlna.mpeg-tts"/>
+  <mime-type type="video/vnd.fvt">
+    <glob pattern="*.fvt"/>
+  </mime-type>
+  <mime-type type="video/vnd.hns.video"/>
+  <mime-type type="video/vnd.iptvforum.1dparityfec-1010"/>
+  <mime-type type="video/vnd.iptvforum.1dparityfec-2005"/>
+  <mime-type type="video/vnd.iptvforum.2dparityfec-1010"/>
+  <mime-type type="video/vnd.iptvforum.2dparityfec-2005"/>
+  <mime-type type="video/vnd.iptvforum.ttsavc"/>
+  <mime-type type="video/vnd.iptvforum.ttsmpeg2"/>
+  <mime-type type="video/vnd.motorola.video"/>
+  <mime-type type="video/vnd.motorola.videop"/>
+  <mime-type type="video/vnd.mpegurl">
+    <glob pattern="*.mxu"/>
+    <glob pattern="*.m4u"/>
+  </mime-type>
+  <mime-type type="video/vnd.ms-playready.media.pyv">
+    <glob pattern="*.pyv"/>
+  </mime-type>
+  <mime-type type="video/vnd.nokia.interleaved-multimedia"/>
+  <mime-type type="video/vnd.nokia.videovoip"/>
+  <mime-type type="video/vnd.objectvideo"/>
+  <mime-type type="video/vnd.sealed.mpeg1"/>
+  <mime-type type="video/vnd.sealed.mpeg4"/>
+  <mime-type type="video/vnd.sealed.swf"/>
+  <mime-type type="video/vnd.sealedmedia.softseal.mov"/>
+  <mime-type type="video/vnd.vivo">
+    <glob pattern="*.viv"/>
+  </mime-type>
+  <mime-type type="video/x-f4v">
+    <glob pattern="*.f4v"/>
+  </mime-type>
+
+  <mime-type type="video/x-flc">
+    <glob pattern="*.flc"/>
+  </mime-type>
+
+  <mime-type type="video/x-fli">
+    <glob pattern="*.fli"/>
+  </mime-type>
+
+  <mime-type type="video/x-flv">
+    <magic priority="50">
+      <match value="FLV" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.flv"/>
+  </mime-type>
+
+  <mime-type type="video/x-jng">
+    <magic priority="50">
+      <match value="\x8bJNG" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.jng"/>
+  </mime-type>
+
+  <mime-type type="video/x-m4v">
+    <glob pattern="*.m4v"/>
+  </mime-type>
+
+  <mime-type type="video/x-mng">
+    <magic priority="50">
+      <match value="\x8aMNG" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.mng"/>
+  </mime-type>
+
+  <mime-type type="video/x-ms-asf">
+    <glob pattern="*.asf"/>
+    <glob pattern="*.asx"/>
+  </mime-type>
+  <mime-type type="video/x-ms-wm">
+    <glob pattern="*.wm"/>
+  </mime-type>
+  <mime-type type="video/x-ms-wmv">
+    <glob pattern="*.wmv"/>
+  </mime-type>
+  <mime-type type="video/x-ms-wmx">
+    <glob pattern="*.wmx"/>
+  </mime-type>
+  <mime-type type="video/x-ms-wvx">
+    <glob pattern="*.wvx"/>
+  </mime-type>
+
+  <mime-type type="video/x-msvideo">
+    <alias type="video/avi"/>
+    <alias type="video/msvideo"/>
+    <magic priority="50">
+      <match value="RIFF....AVI " type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+    </magic>
+    <glob pattern="*.avi"/>
+  </mime-type>
+
+  <mime-type type="video/x-sgi-movie">
+    <magic priority="50">
+      <match value="MOVI" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.movie"/>
+  </mime-type>
+
+  <mime-type type="x-conference/x-cooltalk">
+    <_comment>Cooltalk Audio</_comment>
+    <glob pattern="*.ice"/>
+  </mime-type>
+
+</mime-info>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/repomgr/elements.xml b/0.8.1-rc1/filemgr/src/test/resources/repomgr/elements.xml
new file mode 100644
index 0000000..da6dcf5
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/repomgr/elements.xml
@@ -0,0 +1,67 @@
+<?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.
+-->
+<cas:elements xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<element id="urn:oodt:ProductId" name="CAS.ProductId">
+		<dcElement>Identifier</dcElement>
+		<description>
+			A Product's unique identifier within the CAS namespace.
+		</description>
+	</element>
+	<element id="urn:oodt:ProductName" name="CAS.ProductName">
+		<dcElement>Title</dcElement>
+		<description>
+			A Product's name within the CAS namespace.
+		</description>
+	</element>
+	<element id="urn:oodt:ProductReceivedTime"
+		name="CAS.ProductReceivedTime">
+		<dcElement />
+		<description>
+			The ISO 8601 formatted time that the Product was received.
+		</description>
+	</element>
+	<element id="urn:oodt:Filename" name="Filename">
+		<description>
+			The names of the files that represent this product.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:FileLocation" name="FileLocation">
+		<description>
+			The locations of the files that represent this product.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:ProductType" name="ProductType">
+		<description>
+			Type of product, as specified by, e.g., a data bible.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:ProductStructure" name="ProductStructure">
+		<description>
+			Whether or not a product is Flat (e.g., a set of independent
+			files), or hierarchical, e.g., a dir structure.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:MimeType" name="MimeType">
+		<description>The IETF mime type of this product.</description>
+		<dcElement />
+	</element>
+</cas:elements>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/repomgr/product-type-element-map.xml b/0.8.1-rc1/filemgr/src/test/resources/repomgr/product-type-element-map.xml
new file mode 100644
index 0000000..b474fba
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/repomgr/product-type-element-map.xml
@@ -0,0 +1,38 @@
+<?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.
+-->
+<cas:producttypemap xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+ <!--  can set the "parent" attribute on types below to allow inheritance
+       of elements between the types 
+  -->
+   <type id="urn:oodt:GenericFile">
+       <element id="urn:oodt:ProductReceivedTime"/>
+       <element id="urn:oodt:ProductName"/>
+       <element id="urn:oodt:ProductId"/>
+       <element id="urn:oodt:ProductType"/>
+       <element id="urn:oodt:ProductStructure"/>
+       <element id="urn:oodt:Filename"/>
+       <element id="urn:oodt:FileLocation"/>
+       <element id="urn:oodt:MimeType"/>
+  </type>
+  
+  <type id="urn:oodt:GenericFileWithBlankMet"
+        parent="urn:oodt:GenericFile"/>
+  
+  <type id="urn:oodt:GenericFileNoTypeMetadata"
+        parent="urn:oodt:GenericFile"/>
+</cas:producttypemap>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/repomgr/product-types.xml b/0.8.1-rc1/filemgr/src/test/resources/repomgr/product-types.xml
new file mode 100644
index 0000000..30aee63
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/repomgr/product-types.xml
@@ -0,0 +1,52 @@
+<?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.
+-->
+<cas:producttypes xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+  <type id="urn:oodt:GenericFile" name="GenericFile">
+    <repository path="file://[HOME]/files"/>
+    <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+    <description trim="true">
+     The default product type for any kind of file, with real metadata.
+    </description>
+    <metadata>
+      <keyval>
+	      <key>Creator</key>
+	      <val>Chris Mattmann</val>
+	      <val>Paul Ramirez</val>
+	  </keyval>
+	  <keyval>
+	      <key>Contributor</key>
+	      <val>File Manager Client</val>
+	  </keyval>
+    </metadata>
+  </type>
+  <type id="urn:oodt:GenericFileWithBlankMet" name="GenericFileWithBlankMet">
+    <repository path="file://[HOME]/files"/>
+    <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+    <description>
+      The default product type for any kind of file, with blank metadata.
+    </description>
+    <metadata/>
+  </type>
+  <type id="urn:oodt:GenericFileNoTypeMetadata" name="GenericFileNoTypeMetadata">
+    <repository path="file://[HOME]/files"/>
+    <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+    <description trim="false">
+      The default product type for any kind of file, without metadata.
+    </description>
+  </type>
+</cas:producttypes>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/test.logging.properties b/0.8.1-rc1/filemgr/src/test/resources/test.logging.properties
new file mode 100644
index 0000000..4508d93
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/test.logging.properties
@@ -0,0 +1,59 @@
+#  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.
+
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler
+
+# Set the default logging level for the root logger
+.level = OFF
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = OFF
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# catalog subsystem
+org.apache.oodt.cas.filemgr.catalog.level = INFO
+
+# repository subsystem
+org.apache.oodt.cas.filemgr.repository.level = FINE
+
+# system subsystem
+org.apache.oodt.cas.filemgr.system.level = INFO
+
+# versioning subsystem
+org.apache.oodt.cas.filemgr.versioning.level = INFO
+
+# data transfer subsystem
+org.apache.oodt.cas.filemgr.datatransfer.level = FINE
+
+# util
+org.apache.oodt.cas.filemgr.util.level = INFO
+
+# validation
+org.apache.oodt.cas.filemgr.validation.level = INFO
+
+# tools
+org.apache.oodt.cas.filemgr.tools.level = SEVERE
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = INFO
+httpclient.wire.header.level = INFO
+httpclient.wire.level = INFO
+
diff --git a/0.8.1-rc1/filemgr/src/test/resources/test.txt b/0.8.1-rc1/filemgr/src/test/resources/test.txt
new file mode 100644
index 0000000..177fd76
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/test.txt
@@ -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.
+
+
+this is a test text file
diff --git a/0.8.1-rc1/filemgr/src/test/resources/testcat.mapped.sql b/0.8.1-rc1/filemgr/src/test/resources/testcat.mapped.sql
new file mode 100644
index 0000000..a230380
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/testcat.mapped.sql
@@ -0,0 +1,27 @@
+DROP TABLE foo_metadata IF EXISTS;
+DROP TABLE foo_reference IF EXISTS;
+DROP TABLE products IF EXISTS;
+
+CREATE TABLE foo_metadata
+(
+  product_id int NOT NULL,
+  element_id varchar(1000) NOT NULL,
+  metadata_value varchar(2500) NOT NULL
+);
+
+CREATE TABLE foo_reference
+(
+  product_id int NOT NULL,
+  product_orig_reference varchar(2000) NOT NULL,
+  product_datastore_reference varchar(2000), 
+  product_reference_filesize int NOT NULL,
+  product_reference_mimetype varchar(50)
+);
+
+CREATE TABLE products (
+  product_id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) PRIMARY KEY,
+  product_structure varchar(20) NOT NULL, 
+  product_type_id varchar(255) NOT NULL, 
+  product_name varchar(255) NOT NULL, 
+  product_transfer_status varchar(255) NOT NULL
+);
diff --git a/0.8.1-rc1/filemgr/src/test/resources/testcat.ordered.sql b/0.8.1-rc1/filemgr/src/test/resources/testcat.ordered.sql
new file mode 100644
index 0000000..f5e1425
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/testcat.ordered.sql
@@ -0,0 +1,29 @@
+DROP TABLE GenericFile_metadata IF EXISTS;
+DROP TABLE GenericFile_reference IF EXISTS;
+DROP TABLE products IF EXISTS;
+
+CREATE TABLE GenericFile_metadata
+(
+  pkey int GENERATED BY DEFAULT AS IDENTITY NOT NULL,
+  product_id int NOT NULL,
+  element_id varchar(1000) NOT NULL,
+  metadata_value varchar(2500) NOT NULL
+);
+
+CREATE TABLE GenericFile_reference
+(
+  pkey int GENERATED BY DEFAULT AS IDENTITY NOT NULL,
+  product_id int NOT NULL,
+  product_orig_reference varchar(2000) NOT NULL,
+  product_datastore_reference varchar(2000), 
+  product_reference_filesize int NOT NULL,
+  product_reference_mimetype varchar(50)
+);
+
+CREATE TABLE products (
+  product_id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) PRIMARY KEY,
+  product_structure varchar(20) NOT NULL, 
+  product_type_id varchar(255) NOT NULL, 
+  product_name varchar(255) NOT NULL, 
+  product_transfer_status varchar(255) NOT NULL
+);
diff --git a/0.8.1-rc1/filemgr/src/test/resources/testcat.sql b/0.8.1-rc1/filemgr/src/test/resources/testcat.sql
new file mode 100644
index 0000000..4c7d4db
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/testcat.sql
@@ -0,0 +1,27 @@
+DROP TABLE GenericFile_metadata IF EXISTS;
+DROP TABLE GenericFile_reference IF EXISTS;
+DROP TABLE products IF EXISTS;
+
+CREATE TABLE GenericFile_metadata
+(
+  product_id int NOT NULL,
+  element_id varchar(1000) NOT NULL,
+  metadata_value varchar(2500) NOT NULL
+);
+
+CREATE TABLE GenericFile_reference
+(
+  product_id int NOT NULL,
+  product_orig_reference varchar(2000) NOT NULL,
+  product_datastore_reference varchar(2000), 
+  product_reference_filesize int NOT NULL,
+  product_reference_mimetype varchar(50)
+);
+
+CREATE TABLE products (
+  product_id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) PRIMARY KEY,
+  product_structure varchar(20) NOT NULL, 
+  product_type_id varchar(255) NOT NULL, 
+  product_name varchar(255) NOT NULL, 
+  product_transfer_status varchar(255) NOT NULL
+);
diff --git a/0.8.1-rc1/filemgr/src/test/resources/testcatalog.typemap.properties b/0.8.1-rc1/filemgr/src/test/resources/testcatalog.typemap.properties
new file mode 100644
index 0000000..25724fa
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/testcatalog.typemap.properties
@@ -0,0 +1,24 @@
+#  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.
+
+
+# Test Product Type to Table Mappings
+# (for product types with LONG names, allows us to get
+# around Oracle's sad 31 char table name limit)
+
+# Note, the key on the left is the actual return of {@link ProductType#getName()}
+# and the value on the right is the mapped table name
+
+GenericFile=foo
diff --git a/0.8.1-rc1/filemgr/src/test/resources/vallayer/elements.xml b/0.8.1-rc1/filemgr/src/test/resources/vallayer/elements.xml
new file mode 100644
index 0000000..2de935d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/vallayer/elements.xml
@@ -0,0 +1,42 @@
+<?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.
+-->
+<cas:elements xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<element id="urn:oodt:ProductId" name="CAS.ProductId">
+		<dcElement>Identifier</dcElement>
+		<description>A Product's unique identifier within the CAS namespace.</description>
+	</element>
+	<element id="urn:oodt:ProductName" name="CAS.ProductName">
+		<dcElement>Title</dcElement>
+		<description trim="false">
+          A Product's name within the CAS namespace.
+        </description>
+	</element>
+	<element id="urn:oodt:ProductReceivedTime"
+		name="CAS.ProductReceivedTime">
+		<dcElement />
+		<description trim="true">
+			The ISO 8601 formatted time that the Product was received.
+		</description>
+	</element>
+	<element id="urn:oodt:Filename" name="Filename">
+		<description>
+			The names of the files that represent this product.
+		</description>
+		<dcElement />
+	</element>
+</cas:elements>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/vallayer/product-type-element-map.xml b/0.8.1-rc1/filemgr/src/test/resources/vallayer/product-type-element-map.xml
new file mode 100644
index 0000000..4473026
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/vallayer/product-type-element-map.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+<cas:producttypemap xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+ <!--  can set the "parent" attribute on types below to allow inheritance
+       of elements between the types 
+  -->
+   <type id="urn:oodt:GenericFile">
+       <element id="urn:oodt:ProductReceivedTime"/>
+       <element id="urn:oodt:ProductName"/>
+       <element id="urn:oodt:ProductId"/>
+       <element id="urn:oodt:Filename"/>
+  </type>
+</cas:producttypemap>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/vallayer/product-types.xml b/0.8.1-rc1/filemgr/src/test/resources/vallayer/product-types.xml
new file mode 100644
index 0000000..94360c1
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/vallayer/product-types.xml
@@ -0,0 +1,38 @@
+<?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.
+-->
+<cas:producttypes xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+  <type id="urn:oodt:GenericFile" name="GenericFile">
+    <repository path="file://[HOME]/files"/>
+    <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+    <description>The default product type for any kind of file.</description>
+    <metExtractors>
+      <extractor
+        class="org.apache.oodt.cas.filemgr.metadata.extractors.CoreMetExtractor">
+        <configuration>
+          <!--  you can optionally include the envReplace tag to turn on/off environment var replacement -->
+          <property name="nsAware" value="true" />
+          <property name="elementNs" value="CAS" />
+          <property name="elements"
+            value="ProductReceivedTime,ProductName,ProductId" />
+        </configuration>
+      </extractor>
+      <extractor
+        class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.MimeTypeExtractor" />
+    </metExtractors>
+  </type>
+</cas:producttypes>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/xmlrpc-struct-factory/elements.xml b/0.8.1-rc1/filemgr/src/test/resources/xmlrpc-struct-factory/elements.xml
new file mode 100644
index 0000000..05360a9
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/xmlrpc-struct-factory/elements.xml
@@ -0,0 +1,81 @@
+<?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.
+-->
+<cas:elements xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<element id="urn:oodt:ProductId" name="CAS.ProductId">
+		<dcElement>Identifier</dcElement>
+        <!--  
+         You can optionally specify a 'trim' tag to identify whether
+         or not you want newlines trimmed from the element description. To
+         turn off trimming (now done by default), include the following with your
+         description definition: trim="false"       
+         -->
+		<description>
+			A Product's unique identifier within the CAS namespace.
+		</description>
+	</element>
+	<element id="urn:oodt:ProductName" name="CAS.ProductName">
+		<dcElement>Title</dcElement>
+		<description>
+			A Product's name within the CAS namespace.
+		</description>
+	</element>
+	<element id="urn:oodt:ProductReceivedTime"
+		name="CAS.ProductReceivedTime">
+		<dcElement />
+		<description>
+			The ISO 8601 formatted time that the Product was received.
+		</description>
+	</element>
+	<element id="urn:oodt:Filename" name="Filename">
+		<description>
+			The names of the files that represent this product.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:FileLocation" name="FileLocation">
+		<description>
+			The locations of the files that represent this product.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:ProductType" name="ProductType">
+		<description>
+			Type of product, as specified by, e.g., a data bible.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:ProductStructure" name="ProductStructure">
+		<description>
+			Whether or not a product is Flat (e.g., a set of independent
+			files), or hierarchical, e.g., a dir structure.
+		</description>
+		<dcElement />
+	</element>
+	<element id="urn:oodt:MimeType" name="MimeType">
+		<description>The IETF mime type of this product.</description>
+		<dcElement />
+	</element>
+	<element id="urn:test:DataVersion" name="DataVersion">
+		<description>The version of the data file</description>
+		<dcElement />
+	</element>
+	<element id="urn:test:NominalDate" name="NominalDate">
+		<description>The version of the data file</description>
+		<dcElement />
+	</element>
+</cas:elements>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/xmlrpc-struct-factory/product-type-element-map.xml b/0.8.1-rc1/filemgr/src/test/resources/xmlrpc-struct-factory/product-type-element-map.xml
new file mode 100644
index 0000000..7540f7d
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/xmlrpc-struct-factory/product-type-element-map.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+<cas:producttypemap xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+ <!--  can set the "parent" attribute on types below to allow inheritance
+       of elements between the types 
+  -->
+   <type id="urn:oodt:GenericFile">
+       <element id="urn:oodt:ProductReceivedTime"/>
+       <element id="urn:oodt:ProductName"/>
+       <element id="urn:oodt:ProductId"/>
+       <element id="urn:oodt:ProductType"/>
+       <element id="urn:oodt:ProductStructure"/>
+       <element id="urn:oodt:Filename"/>
+       <element id="urn:oodt:FileLocation"/>
+       <element id="urn:oodt:MimeType"/>
+       <element id="urn:test:DataVersion"/>
+       <element id="urn:test:NominalDate"/>    
+  </type>
+</cas:producttypemap>
diff --git a/0.8.1-rc1/filemgr/src/test/resources/xmlrpc-struct-factory/product-types.xml b/0.8.1-rc1/filemgr/src/test/resources/xmlrpc-struct-factory/product-types.xml
new file mode 100644
index 0000000..2de8b54
--- /dev/null
+++ b/0.8.1-rc1/filemgr/src/test/resources/xmlrpc-struct-factory/product-types.xml
@@ -0,0 +1,58 @@
+<?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.
+-->
+<cas:producttypes xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+  <type id="urn:oodt:GenericFile" name="GenericFile">
+    <repository path="file://[HOME]/files"/>
+    <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+    <!--  
+     You can optionally specify a 'trim' tag to identify whether
+     or not you want newlines trimmed from the product type description. To
+     turn off trimming (now done by default), include the following attribute with your
+     description definition: trim="false"       
+     -->
+    <description>The default product type for any kind of file.</description>
+    
+    <!-- 
+      The metExtractors element is optional but included in OODT Unit testing for capability.
+      extractor property elements are extractor specific and located in 
+      AbstractFilemgrMetExtractor#doConfigure method.
+    -->
+    <metExtractors>
+      <extractor
+        class="org.apache.oodt.cas.filemgr.metadata.extractors.CoreMetExtractor">
+        <configuration>
+          <!--  you can optionally include the envReplace tag to turn on/off environment var replacement -->
+          <property name="nsAware" value="true" />
+          <property name="elementNs" value="CAS" />
+          <property name="elements"
+            value="ProductReceivedTime,ProductName,ProductId" />
+        </configuration>
+      </extractor>
+    </metExtractors>
+    
+    <!-- 
+      The metadata element is optional but included in OODT Unit testing for testing capability.
+      TODO
+    -->
+    <metadata>
+    </metadata>
+    <typeHandlers>
+      <typeHandler class="org.apache.oodt.cas.filemgr.structs.type.examples.MajorMinorVersionTypeHandler" elementName="DataVersion"/>
+    </typeHandlers>
+  </type>
+</cas:producttypes>
diff --git a/0.8.1-rc1/grid/pom.xml b/0.8.1-rc1/grid/pom.xml
new file mode 100644
index 0000000..c4fed20
--- /dev/null
+++ b/0.8.1-rc1/grid/pom.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>web-grid</artifactId>
+  <name>OODT Web Grid</name>
+  <packaging>war</packaging>
+  <description>The OODT grid services (product and profile services) use CORBA or
+    RMI as their underlying network transport.  However, limitations
+    of CORBA and RMI make them inappropriate for large-scale
+    deployments.  For one, both are procedural mechanisms, providing a
+    remote interface that resembles a method call.  This makes
+    streaming of data from a service impossible, because there are
+    limitations to the sizes of data structures that can be passed
+    over a remote method call.  Instead, repeated calls must be made
+    to retrieve each block of a product, making transfer speeds
+    horribly slow compared to HTTP or FTP.  (Block-based retrieval of
+    profiles was never implemented, resulting in out of memory
+    conditions for large profile results, which is another problem.)
+    Second, both CORBA and RMI rely on a central name registry.  The
+    registry makes an object independent of its network location,
+    enabling a client to call it by name (looking up its last known
+    location in the registry).  However, this requires that server
+    objects be able to make outbound network calls to the registry
+    (through any outbound firewall), and that the registry accept
+    those registrations (through any inbound firewall).  This required
+    administrative action at institutions hosting server objects and
+    at the institution hosting the registry.  Often, these firewall
+    exceptions would change without notice as system adminstrators
+    changed at each location (apparently firewall exceptions are
+    poorly documented everywhere).  Further, in the two major
+    deployments of OODT (PDS and EDRN), server objects have almost
+    never moved, nullifying any benefit of the registry.  This
+    project, OODT Web Grid Services, avoids the prolems of CORBA and
+    RMI by using HTTP as the transport mechanism for products and
+    profiles.  Further, it provides a password-protected mechanism to
+    add new sets of product and profile query handlers, enabling
+    seamless activation of additional capabilities.</description>
+  <scm>
+   	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/grid</connection>
+   	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/grid</developerConnection>
+   	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/grid</url>
+  </scm>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-war-plugin</artifactId>
+        <configuration>
+          <webResources />
+          <warSourceDirectory>src/main/webapp</warSourceDirectory>
+        </configuration>
+        <version>2.5</version>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-commons</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-profile</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-product</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-xmlquery</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.hp.hpl.jena</groupId>
+      <artifactId>jena</artifactId>
+      <version>2.6.3</version>
+    </dependency>
+    <dependency>
+       <groupId>javax.servlet</groupId>
+       <artifactId>servlet-api</artifactId>
+       <version>2.4</version>
+       <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>xerces</groupId>
+      <artifactId>xercesImpl</artifactId>
+      <version>2.9.1</version>
+    </dependency>
+    <dependency>
+        <groupId>xalan</groupId>
+        <artifactId>xalan</artifactId>
+        <version>2.7.1</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/AuthenticationRequiredException.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/AuthenticationRequiredException.java
new file mode 100755
index 0000000..3c152b8
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/AuthenticationRequiredException.java
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+/**
+ * Exception thrown to indicate that authentication is required to continue.
+ */
+public class AuthenticationRequiredException extends Exception {
+  /**
+   * Creates a new <code>AuthenticationRequiredException</code> instance.
+   */
+  public AuthenticationRequiredException() {
+    super("Authentication required");
+  }
+}
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ConfigBean.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ConfigBean.java
new file mode 100755
index 0000000..ba7afd6
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ConfigBean.java
@@ -0,0 +1,175 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * Bean containing login status for and configuration info.
+ */
+public class ConfigBean implements Serializable {
+  /**
+   * Return true is administrator is authenticated.
+   * 
+   * @return True if authentic, false otherwise.
+   */
+  public boolean isAuthentic() {
+    return authentic;
+  }
+
+  /**
+   * Set whether the administrator's been authenticated.
+   * 
+   * @param authentic
+   *          True if authentic, false otherwise.
+   */
+  void setAuthentic(boolean authentic) {
+    this.authentic = authentic;
+  }
+
+  /**
+   * Get any message to display. This should never be null.
+   * 
+   * @return A message to display
+   */
+  public String getMessage() {
+    return message;
+  }
+
+  /**
+   * Set the message to display.
+   * 
+   * @param message
+   *          Message to display.
+   */
+  public void setMessage(String message) {
+    if (message == null)
+      throw new IllegalArgumentException("message cannot be null");
+    this.message = message;
+  }
+
+  /**
+   * Get the configuration of web-grid.
+   * 
+   * @return a <code>Configuration</code> value.
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  public Configuration getConfiguration()
+      throws AuthenticationRequiredException {
+    checkAuthenticity();
+    return configuration;
+  }
+
+  /**
+   * Tell if HTTPS is required to access the web-grid configuration.
+   * 
+   * @return True if HTTPS is required to access the web-grid configuration.
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  public boolean isHttpsRequired() throws AuthenticationRequiredException {
+    checkAuthenticity();
+    return configuration.isHTTPSrequired();
+  }
+
+  /**
+   * Tell if admin access can come only from the localhost.
+   * 
+   * @return True if admin access can come only from the localhost.
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  public boolean isLocalhostRequired() throws AuthenticationRequiredException {
+    checkAuthenticity();
+    return configuration.isLocalhostRequired();
+  }
+
+  /**
+   * Get the list of {@link ProductServer}s that have been installed in this
+   * container.
+   * 
+   * @return a <code>List</code> of {@link ProductServer}s.
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  public List getProductServers() throws AuthenticationRequiredException {
+    checkAuthenticity();
+    return configuration.getProductServers();
+  }
+
+  /**
+   * Get the list of {@link ProfileServer}s that have been installed in this
+   * container.
+   * 
+   * @return a <code>List</code> of {@link ProfileServer}s.
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  public List getProfileServers() throws AuthenticationRequiredException {
+    checkAuthenticity();
+    return configuration.getProfileServers();
+  }
+
+  /**
+   * Set the configuration this bean will use.
+   * 
+   * @param configuration
+   *          a <code>Configuration</code> value.
+   */
+  void setConfiguration(Configuration configuration) {
+    this.configuration = configuration;
+  }
+
+  /**
+   * Get the properties defined for this container.
+   * 
+   * @return a <code>Properties</code> value.
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  public Properties getProperties() throws AuthenticationRequiredException {
+    checkAuthenticity();
+    return configuration.getProperties();
+  }
+
+  /**
+   * Check if the administrator is authentic. This method does nothing if the
+   * administrator is authentic, but throws an exception if not.
+   * 
+   * @throws AuthenticationRequiredException
+   *           if the administrator's not authenticated.
+   */
+  private void checkAuthenticity() throws AuthenticationRequiredException {
+    if (isAuthentic() && configuration != null)
+      return;
+    message = "";
+    throw new AuthenticationRequiredException();
+  }
+
+  /** True if administrator is authentic. */
+  private boolean authentic;
+
+  /** Any message to display. */
+  private String message = "";
+
+  /** The configuration for this container. */
+  private transient Configuration configuration;
+}
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ConfigServlet.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ConfigServlet.java
new file mode 100755
index 0000000..e9a744e
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ConfigServlet.java
@@ -0,0 +1,303 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Controller servlet for making changes to configuration.
+ */
+public class ConfigServlet extends GridServlet {
+  /**
+   * Handle updates to a configuration by saving them and directing back to the
+   * config page.
+   * 
+   * @param req
+   *          a <code>HttpServletRequest</code> value.
+   * @param res
+   *          a <code>HttpServletResponse</code> value.
+   * @throws ServletException
+   *           if an error occurs.
+   * @throws IOException
+   *           if an error occurs.
+   */
+  public void doPost(HttpServletRequest req, HttpServletResponse res)
+      throws ServletException, IOException {
+    Configuration config = getConfiguration(); // Get the singleton
+                                               // configuration
+    if (!approveAccess(config, req, res))
+      return; // Check if the user can access this page
+
+    ConfigBean cb = getConfigBean(req); // Get the bean
+    cb.setMessage(""); // Clear out any message
+    if (!cb.isAuthentic())
+      throw new ServletException(new AuthenticationRequiredException());
+    boolean needSave = false; // Assume no changes for now
+
+    String newPass = req.getParameter("password"); // See if she wants to change
+                                                   // password
+    if (newPass != null && newPass.length() > 0) { // Got a password, and it's
+                                                   // not empty?
+      config.setPassword(newPass.getBytes()); // Yes, set its bytes
+      needSave = true; // We need to save
+    }
+
+    boolean https = config.isHTTPSrequired(); // Are we currently using https?
+    String httpsParam = req.getParameter("https"); // Get her https param
+    boolean newHttps = httpsParam != null && "on".equals(httpsParam); // See if
+                                                                      // she
+                                                                      // wants
+                                                                      // to use
+                                                                      // https
+                                                                      // or not
+    if (https != newHttps) { // Different?
+      config.setHTTPSrequired(newHttps); // Yes, set the new state
+      needSave = true; // We need to save
+    }
+
+    boolean local = config.isLocalhostRequired(); // Are we requiring localhost?
+    String localhostParam = req.getParameter("localhost"); // Get her localhost
+                                                           // param
+    boolean newLocal = localhostParam != null && "on".equals(localhostParam); // See
+                                                                              // if
+                                                                              // she
+                                                                              // wants
+                                                                              // to
+                                                                              // require
+                                                                              // localhost
+    if (local != newLocal) { // Different?
+      config.setLocalhostRequired(newLocal); // Yes, set the new state
+      needSave = true; // We need to save
+    }
+
+    String newKey = req.getParameter("newkey"); // See if she's got a new
+                                                // property
+    if (newKey != null && newKey.length() > 0) { // And make sure it's nonempty
+      String newVal = req.getParameter("newval"); // Got one, get its value
+      if (newVal == null)
+        newVal = ""; // Make sure it's at least an empty string
+      config.getProperties().setProperty(newKey, newVal); // Set the new
+                                                          // property
+      needSave = true; // We need to save
+    }
+
+    needSave |= updateProperties(config.getProperties(), // Make any updates to
+                                                         // existing property
+        req.getParameterMap()); // values, and see note if we need to save
+    try {
+      needSave |= updateServers(config, req.getParameterMap(), 'd'); // Same
+                                                                     // goes for
+                                                                     // product
+                                                                     // servers
+      needSave |= updateServers(config, req.getParameterMap(), 'm'); // And
+                                                                     // profile
+                                                                     // servers
+      needSave |= updateCodeBases(config, req.getParameterMap()); // And for
+                                                                  // code bases
+    } catch (MalformedURLException ex) { // Make sure code base URLs are OK
+      cb.setMessage("Code bases must be valid URLs (" // Not OK?
+          + ex.getMessage() + "); no changes made"); // Let user know via a
+                                                     // message
+      req.getRequestDispatcher("config.jsp").forward(req, res); // And make no
+                                                                // changes until
+                                                                // she fixes it
+      return;
+    }
+
+    if (needSave) { // Do we need to save?
+      config.save(); // Then do it already!
+      cb.setMessage("Changes saved."); // And let the user know
+    } else {
+      cb.setMessage("No changes made."); // Oh, no changes were made, let user
+                                         // know
+    }
+    req.getRequestDispatcher("config.jsp").forward(req, res); // Back to the
+                                                              // config page
+  }
+
+  /**
+   * Update changes to the code bases.
+   * 
+   * @param config
+   *          a <code>Configuration</code> value.
+   * @param params
+   *          a <code>Map</code> value.
+   * @return True if changes need to be saved.
+   * @throws MalformedURLException
+   *           if an error occurs.
+   */
+  private boolean updateCodeBases(Configuration config, Map params)
+      throws MalformedURLException {
+    boolean needSave = false; // Assume no change
+    List codeBases = config.getCodeBases(); // Get the current code bases
+
+    List toRemove = new ArrayList(); // Hold indexes of code bases to remove
+    for (Iterator i = params.entrySet().iterator(); i.hasNext();) { // For each
+                                                                    // parameter
+      Map.Entry entry = (Map.Entry) i.next(); // Get its entry
+      String key = (String) entry.getKey(); // And its name
+      String value = ((String[]) entry.getValue())[0]; // And its zeroth value
+      if (key.startsWith("delcb-") && "on".equals(value)) { // If it's checked
+        Integer index = new Integer(key.substring(6)); // Parse out the index
+        toRemove.add(index); // Add it to the list
+      }
+    }
+    if (!toRemove.isEmpty()) { // And if we have any indexes
+      Collections.sort(toRemove); // Sort 'em and put 'em in reverse ...
+      Collections.reverse(toRemove); // ... order so we can safely remove them
+      for (Iterator i = toRemove.iterator(); i.hasNext();) { // For each index
+                                                             // to remove
+        int index = ((Integer) i.next()).intValue(); // Get the index value
+        codeBases.remove(index); // And buh-bye.
+      }
+      needSave = true; // Definitely need to save changes now
+    }
+
+    String[] newCBs = (String[]) params.get("newcb"); // Was there a new code
+                                                      // base specified?
+    if (newCBs != null && newCBs.length == 1) { // And was there exactly one
+                                                // value?
+      String newCB = newCBs[0]; // Get that exactly one value
+      if (newCB != null && newCB.length() > 0) { // Is it nonnull and nonempty?
+        URL newURL = new URL(newCB); // Treat is as an URL
+        codeBases.add(newURL); // Add it to the list
+        needSave = true; // Ad we gotta save
+      }
+    }
+    return needSave;
+  }
+
+  /**
+   * Update the list of product/profile servers based on request parameters.
+   * 
+   * @param config
+   *          System configuration
+   * @param params
+   *          Request parameters.
+   * @param type
+   *          <code>d</code> (data) if product servers, <code>m</code>
+   *          (metadata) if profile servers
+   * @return True if any changes were made, false if no changes were made
+   */
+  private boolean updateServers(Configuration config, Map params, char type) {
+    List servers = type == 'd' ? config.getProductServers() : config
+        .getProfileServers();
+    boolean needSave = false; // Assume no changes for now
+
+    List toRemove = new ArrayList(); // Start with empty list of indexes to
+                                     // remove
+    for (Iterator i = params.entrySet().iterator(); i.hasNext();) { // Go
+                                                                    // through
+                                                                    // each
+                                                                    // parameter
+      Map.Entry entry = (Map.Entry) i.next(); // Get its key/value
+      String name = (String) entry.getKey(); // The key is a String
+      if (name.startsWith(type + "rm-")) { // Is it an "drm-" or "mrm-"?
+        Integer index = new Integer(name.substring(4)); // Yes, get it sindex
+        toRemove.add(index); // Add it to the list
+      }
+    }
+
+    if (!toRemove.isEmpty()) { // Got any to remove?
+      Collections.sort(toRemove); // We need to go through them in reverse ord-
+      Collections.reverse(toRemove); // -er, so that removals don't shift
+                                     // indexes
+      for (Iterator i = toRemove.iterator(); i.hasNext();) { // For each index
+        int index = ((Integer) i.next()).intValue(); // Get its int value
+        servers.remove(index); // and buh-bye
+      }
+      needSave = true; // Gotta save after all that, whew.
+    }
+
+    if (params.containsKey(type + "-newcn")) { // Adding a new server?
+      String[] newClasses = (String[]) params.get(type + "-newcn"); // And the
+                                                                    // new class
+                                                                    // name
+      if (newClasses != null && newClasses.length == 1) { // Are present and
+                                                          // there's only one of
+                                                          // each
+        String newClass = newClasses[0]; // Get the new class
+        if (newClass != null && newClass.length() > 0) { // And nonempty
+          Server server;
+          if (type == 'd') // If it's data
+            server = new ProductServer(config, newClass); // It's a product
+                                                          // server
+          else
+            // otherwise it's metadata
+            server = new ProfileServer(config, newClass); // Which is a profile
+                                                          // server
+          servers.add(server); // Add it to the set of servers
+          needSave = true; // And after all this, we need to save!
+        }
+      }
+    }
+
+    return needSave;
+  }
+
+  /**
+   * Update properties based on request parameters.
+   * 
+   * @param props
+   *          <code>Properties</code> to update
+   * @param params
+   *          Request parameters
+   * @return True if changes need to be saved, false otherwise
+   */
+  private boolean updateProperties(Properties props, Map params) {
+    boolean needSave = false; // Assume no save for now
+    for (Iterator i = params.entrySet().iterator(); i.hasNext();) { // Go
+                                                                    // through
+                                                                    // each
+                                                                    // request
+                                                                    // parameter
+      Map.Entry entry = (Map.Entry) i.next(); // Get the key/value
+      String name = (String) entry.getKey(); // Key is always a string
+      String newValue = ((String[]) entry.getValue())[0]; // Value is String[],
+                                                          // get the zeroth
+      if (name.startsWith("val-")) { // If the param is "val-"
+        String key = name.substring(4); // Then find the key
+        if (props.containsKey(key)) { // If that key exists
+          String value = props.getProperty(key); // Find its value
+          if (value == null || !value.equals(newValue)) {// Are they different?
+            props.setProperty(key, newValue); // Yes, set the new value
+            needSave = true; // And we need to save
+          }
+        }
+      } else if (name.startsWith("del-")) { // If the param is "del-"
+        String key = name.substring(4); // Then find the key
+        if (props.containsKey(key)) { // If that key exists
+          props.remove(key); // Then remove its mapping
+          needSave = true; // And we need to save
+        }
+      }
+    }
+    return needSave;
+  }
+}
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/Configuration.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/Configuration.java
new file mode 100755
index 0000000..8ea5375
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/Configuration.java
@@ -0,0 +1,443 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.SAXException;
+
+import org.apache.oodt.commons.util.Base64;
+
+/**
+ * web-grid configuration. This holds all the runtime configuration of profile servers,
+ * product servers, properties, and other settings for the web-grid container.
+ *
+ */
+public class Configuration implements Serializable {
+    /**
+     * Creates a new <code>Configuration</code> instance.
+     *
+     * @param file File containing the serialized configuration.
+     * @throws IOException if an I/O error occurs.
+     * @throws SAXException if the file can't be parsed.
+     */
+    public Configuration(File file) throws IOException, SAXException {
+        this.file = file;
+        if (file.isFile() && file.length() > 0)
+            parse(file);
+    }
+
+    /**
+     * Convert the configuration to XML.
+     *
+     * @param owner Owning document.
+     * @return XML representation of this configuration.
+     */
+    public Node toXML(Document owner) {
+        Element elem = owner.createElement("configuration");                    // <configuration>
+        elem.setAttribute("xmlns", NS);                                         // Set default namespace
+        elem.setAttribute("https", httpsRequired? "true" : "false");            // Add https attribute
+        elem.setAttribute("localhost", localhostRequired? "true" : "false");    // Add localhost attribute
+
+        if (password != null && password.length > 0)                            // If we have a password
+            elem.setAttribute("password", encode(password));                    // Add passowrd attribute
+
+        for (Iterator i = productServers.iterator(); i.hasNext();) {            // For each product server
+            ProductServer ps = (ProductServer) i.next();                        // Get the product server
+            elem.appendChild(ps.toXML(owner));                                  // And add it under <configuration>
+        }
+
+        for (Iterator i = profileServers.iterator(); i.hasNext();) {            // For each profile server
+            ProfileServer ps = (ProfileServer) i.next();                        // Get the profile server
+            elem.appendChild(ps.toXML(owner));                                  // And add it under the <configuration>
+        }
+
+        if (!codeBases.isEmpty()) {                                             // Got any code bases?
+            Element cbs = owner.createElement("codeBases");                     // Boo yah.  Make a parent for 'em
+            elem.appendChild(cbs);                                              // Add parent
+            for (Iterator i = codeBases.iterator(); i.hasNext();) {             // Then, for each code base
+                URL url = (URL) i.next();                                       // Get the URL to it
+                Element cb = owner.createElement("codeBase");                   // And make a <codeBase> for it
+                cb.setAttribute("url", url.toString());                         // And an "url" attribute
+                cbs.appendChild(cb);                                            // Add it
+            }
+        }
+
+        if (!properties.isEmpty()) {                                            // If we have any properties>
+            Element props = owner.createElement("properties");                  // Add <properties> under <configuration>
+            props.setAttribute("xml:space", "preserve");                        // And make sure space is properly preserved
+            elem.appendChild(props);                                            // Add the space attribute
+            for (Iterator i = properties.entrySet().iterator(); i.hasNext();) { // For each property
+                Map.Entry entry = (Map.Entry) i.next();                         // Get the property key/value pair
+                String key = (String) entry.getKey();                           // Key is always a String
+                String value = (String) entry.getValue();                       // So is the value
+                Element prop = owner.createElement("property");                 // Create a <property> element
+                props.appendChild(prop);                                        // Add it under the <properties>
+                prop.setAttribute("key", key);                                  // Set the key as an attribute
+                Text text = owner.createTextNode(value);                        // Make text to hold the value
+                prop.appendChild(text);                                         // Add it under the <property>
+            }
+        }
+        return elem;
+    }
+
+    /**
+     * Get the properties.
+     *
+     * @return a <code>Properties</code> value.
+     */
+    public Properties getProperties() {
+        return properties;
+    }
+
+    /**
+     * Is localhost access required for the configuration?
+     *
+     * @return True if the configuration must be accessed from the localhost, false otherwise.
+     */
+    public boolean isLocalhostRequired() {
+        return localhostRequired;
+    }
+
+    /**
+     * Is https access required for the configuration?
+     *
+     * @return True if the configuration must be accessed via https, false if http is OK.
+     */
+    public boolean isHTTPSrequired() {
+        return httpsRequired;
+    }
+
+    /**
+     * Set if https is required to access the configuration.
+     *
+     * @param required True if the configuration must be accessed via https, false if http is OK.
+     */
+    public void setHTTPSrequired(boolean required) {
+        httpsRequired = required;
+    }
+
+    /**
+     * Set if localhost is required to access the configuration.
+     *
+     * @param required True if the configuration must be accessed from the localhost, false otherwise.
+     */
+    public void setLocalhostRequired(boolean required) {
+        localhostRequired = required;
+    }
+
+    /**
+     * Return the code bases.
+     *
+     * @return a <code>List</code> of {@link URL}s.
+     */
+    public List getCodeBases() {
+        return codeBases;
+    }
+
+    /**
+     * Get the product servers.
+     *
+     * @return a <code>List</code> of {@link ProductServer}s.
+     */
+    public List getProductServers() {
+        return productServers;
+    }
+
+    /**
+     * Get the profile servers.
+     *
+     * @return a <code>List</code> of {@link ProfileServer}s.
+     */
+    public List getProfileServers() {
+        return profileServers;
+    }
+
+    /**
+     * Get the administrator password.
+     *
+     * @return Administrator password.
+     */
+    public byte[] getPassword() {
+        return password;
+    }
+
+    /**
+     * Set the administrator password.
+     *
+     * @param password Administrator password.
+     */
+    public void setPassword(byte[] password) {
+        if (password == null)
+            throw new IllegalArgumentException("Non-null passwords not allowed");
+        this.password = password;
+    }
+
+    /**
+     * Save the configuration.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    public synchronized void save() throws IOException {
+        BufferedWriter writer = null;                           // Start w/no writer
+        try {                                                   // Then try ...
+            writer = new BufferedWriter(new FileWriter(file));  // Create a writer
+            Document doc;                                       // As for the doc...
+            synchronized (DOCUMENT_BUILDER) {                   // Using the document builder...
+                doc = DOCUMENT_BUILDER.newDocument();           // Create an empty document
+            }
+            Node root = toXML(doc);                             // Convert this config to XML
+            doc.appendChild(root);                              // Add it to the doc
+            DOMSource source = new DOMSource(doc);              // Use the source Luke
+            StreamResult result = new StreamResult(writer);     // And serialize it to the writer
+            TRANSFORMER.transform(source, result);              // Serialize
+        } catch (TransformerException ex) {
+            throw new IllegalStateException("Unexpected TransformerException: " + ex.getMessage());
+        } finally {
+            if (writer != null) try {                           // And if we got a writer, try ...
+                writer.close();                                 // to close it
+            } catch (IOException ignore) {}                     // Ignoring any error
+        }
+    }
+
+    /**
+     * Parse a serialized configuration document.
+     *
+     * @param file File to parse
+     * @throws IOException if an I/O error occurs.
+     * @throws SAXException if a parse error occurs.
+     */
+    private void parse(File file) throws IOException, SAXException {
+        Document doc;                                                               // Start with a doc ...
+        synchronized (DOCUMENT_BUILDER) {                                           // And using the DOCUMENT_BUILDER
+            doc = DOCUMENT_BUILDER.parse(file);                                     // Try to parse the file
+        }
+        Element root = doc.getDocumentElement();                                    // Assume the root element is <configuration>
+
+        String httpsAttr = root.getAttribute("https");                              // Get the https attribute
+        httpsRequired = httpsAttr != null && "true".equals(httpsAttr);              // See if it's "true"
+
+        String localhostAttr = root.getAttribute("localhost");                      // Get the localhost attribute
+        localhostRequired = localhostAttr != null && "true".equals(localhostAttr);  // See if it's "true"
+
+        String passwordAttr = root.getAttribute("password");                        // Get the password attribute
+        if (passwordAttr != null && passwordAttr.length() > 0)                      // If it's there, and non-empty
+            password = decode(passwordAttr);                                        // Then decode it
+
+        NodeList children = root.getChildNodes();                                   // Get the child nodes
+        for (int i = 0; i < children.getLength(); ++i) {                            // For each child node
+            Node child = children.item(i);                                          // Get the child
+            if (child.getNodeType() == Node.ELEMENT_NODE) {                         // An element?
+                if ("server".equals(child.getNodeName())) {                         // A <server>?
+                    Server server = Server.create(this, (Element) child);           // Create the correct server
+
+                    // Keep these in separate sets?
+                    if (server instanceof ProductServer)                            // Is a product server?
+                        productServers.add(server);                                 // Add to product servers
+                    else if (server instanceof ProfileServer)                       // Is a profile server?
+                        profileServers.add(server);                                 // Add to profile servers
+                    else throw new IllegalArgumentException("Unexpected server type " + server + " in " + file);
+                } else if ("properties".equals(child.getNodeName())) {              // Is it a <properties>?
+                    NodeList props = child.getChildNodes();                         // Get its children
+                    for (int j = 0; j < props.getLength(); ++j) {                   // For each child
+                        Node node = props.item(j);                                  // Get the chld
+                        if (node.getNodeType() == Node.ELEMENT_NODE                 // And element?
+                            && "property".equals(node.getNodeName())) {             // And it's <property>?
+                            Element propNode = (Element) node;                      // Great, use it as an element
+                            String key = propNode.getAttribute("key");              // Get its key attribute
+                            if (key == null || key.length() == 0)                   // Make sure it's there
+                                throw new SAXException("Required 'key' attribute missing from "
+                                    + "<property> element");
+                            properties.setProperty(key, text(propNode));            // And set it
+                        }
+                    }
+                } else if ("codeBases".equals(child.getNodeName())) {               // And yadda
+                    NodeList cbs = child.getChildNodes();                           // yadda
+                    for (int j = 0; j < cbs.getLength(); ++j) {                     // yadda.
+                        Node node = cbs.item(j);
+                        if (node.getNodeType() == Node.ELEMENT_NODE
+                            && "codeBase".equals(node.getNodeName())) {
+                            Element cbNode = (Element) node;
+                            String u = cbNode.getAttribute("url");
+                            if (u == null || u.length() == 0)
+                                throw new SAXException("Required 'url' attribute missing from "
+                                    + "<codeBase> element");
+                            try {
+                                codeBases.add(new URL(u));
+                            } catch (MalformedURLException ex) {
+                                throw new SAXException("url attribute " + u + " isn't a valid URL");
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Encode a password.  This just hides it so it's not plain text, but it's just as
+     * easy to decode it if you have a base-64 decoder handy.
+     *
+     * @param password a <code>byte[]</code> value.
+     * @return a <code>String</code> value.
+     */
+    static String encode(byte[] password) {
+        return new String(Base64.encode(password));
+    }
+
+    /**
+     * Decode a password.
+     *
+     * @param password a <code>String</code> value.
+     * @return a <code>byte[]</code> value.
+     */
+    static byte[] decode(String password) {
+        return Base64.decode(password.getBytes());
+    }
+
+    /**
+     * Get the text under an XML node.
+     *
+     * @param node a <code>Node</code> value.
+     * @return a <code>String</code> value.
+     */
+    private static String text(Node node) {
+        StringBuffer b = new StringBuffer();
+        text0(node, b);
+        return b.toString();
+    }
+
+    /**
+     * Get the text from an XML node into a StringBuffer. 
+     *
+     * @param node a <code>Node</code> value.
+     * @param b a <code>StringBuffer</code> value.
+     */
+    private static void text0(Node node, StringBuffer b) {
+        NodeList children = node.getChildNodes();
+        for (int i = 0; i < children.getLength(); ++i)
+            text0(children.item(i), b);
+        short type = node.getNodeType();
+        if (type == Node.CDATA_SECTION_NODE || type == Node.TEXT_NODE)
+            b.append(node.getNodeValue());
+    }
+
+    public boolean equals(Object obj) {
+        if (obj == this) return true;
+        if (obj instanceof Configuration) {
+            Configuration rhs = (Configuration) obj;
+            return codeBases.equals(rhs.codeBases) && productServers.equals(rhs.productServers)
+                && profileServers.equals(rhs.profileServers) && Arrays.equals(password, rhs.password)
+                && httpsRequired == rhs.httpsRequired && localhostRequired == rhs.localhostRequired
+                && properties.equals(rhs.properties);
+        }
+        return false;
+    }
+
+    public int hashCode() {
+        return codeBases.hashCode() ^ productServers.hashCode() ^ profileServers.hashCode();
+    }
+
+    /** List of {@link URL}s to code bases. */
+    private List codeBases = new ArrayList();
+
+    /** List of {@link ProductServer}s. */
+    private List productServers = new ArrayList();
+
+    /** List of {@link ProfileServer}s. */
+    private List profileServers = new ArrayList();
+
+    /** Admin password. */
+    private byte[] password = DEFAULT_PASSWORD;
+
+    /** True if https is requried. */
+    private boolean httpsRequired;
+
+    /** True if localhost access is required. */
+    private boolean localhostRequired;
+
+    /** Properties to set. */
+    private Properties properties = new Properties();
+
+    /** Where to save the file. */
+    private transient File file;
+
+    /** Default password. */
+    static final byte[] DEFAULT_PASSWORD = { (byte)'h', (byte)'a', (byte)'n', (byte)'a', (byte)'l', (byte)'e', (byte)'i' };
+
+    /** XML namespace */
+    public static final String NS = "http://oodt.jpl.nasa.gov/web-grid/ns/";
+
+    /** Sole document builder we'll need. */
+    private static final DocumentBuilder DOCUMENT_BUILDER;
+
+    /** Sole transfomer we'll need. */
+    private static final Transformer TRANSFORMER;
+
+    static {
+        try {
+            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+            documentBuilderFactory.setNamespaceAware(true);
+            documentBuilderFactory.setValidating(false);
+            documentBuilderFactory.setIgnoringElementContentWhitespace(false);
+            documentBuilderFactory.setExpandEntityReferences(true);
+            documentBuilderFactory.setIgnoringComments(true);
+            documentBuilderFactory.setCoalescing(true);
+            DOCUMENT_BUILDER = documentBuilderFactory.newDocumentBuilder();
+
+            TransformerFactory transformerFactory = TransformerFactory.newInstance();
+            TRANSFORMER = transformerFactory.newTransformer();
+            TRANSFORMER.setOutputProperty(OutputKeys.METHOD, "xml");
+            TRANSFORMER.setOutputProperty(OutputKeys.VERSION, "1.0");
+            TRANSFORMER.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+            TRANSFORMER.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+            TRANSFORMER.setOutputProperty(OutputKeys.INDENT, "yes");
+            TRANSFORMER.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+        } catch (ParserConfigurationException ex) {
+            throw new IllegalStateException("Cannot create document builder");
+        } catch (TransformerConfigurationException ex) {
+            throw new IllegalStateException("Cannot create transformer");
+        }
+    }
+}
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/GridServlet.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/GridServlet.java
new file mode 100755
index 0000000..0f5cf5d
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/GridServlet.java
@@ -0,0 +1,120 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.File;
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.xml.sax.SAXException;
+
+/**
+ * Grid servlet is an abstract servlet that provides basic behavior (configuration access)
+ * for grid servlets.
+ */
+public abstract class GridServlet extends HttpServlet {
+	/**
+	 * By default, grid servlets are POST only, so GETs get you the welcome page.
+	 *
+	 * @param req a <code>HttpServletRequest</code> value.
+	 * @param res a <code>HttpServletResponse</code> value.
+	 * @throws IOException if an error occurs.
+	 * @throws ServletException if an error occurs.
+	 */
+	public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
+		req.getRequestDispatcher("index.html").forward(req, res);
+	}
+
+	/**
+	 * Get the configuration.
+	 *
+	 * @return a <code>Configuration</code> value.
+	 * @throws ServletException if an error occurs.
+	 * @throws IOException if an error occurs.
+	 */
+	protected Configuration getConfiguration() throws ServletException, IOException {
+		if (configuration != null) return configuration;
+		String path = getServletContext().getInitParameter("org.apache.oodt.grid.GridServlet.config");
+		if (path == null) path = getServletContext().getRealPath("/WEB-INF/config.xml");
+		if (path == null)
+			throw new ServletException("The config.xml file can't be accessed. Are we running from a war file!??!");
+		File file = new File(path);
+		Configuration c = null;
+		try {
+			c = new Configuration(file);
+		} catch (SAXException ex) {
+			throw new ServletException("Cannot parse config.xml file", ex);
+		}
+		synchronized (GridServlet.class) {
+			while (configuration == null)
+				configuration = c;
+		}
+		return configuration;
+	}
+
+	/**
+	 * Get the config bean.
+	 *
+	 * @param req a <code>HttpServletRequest</code> value.
+	 * @return a <code>ConfigBean</code> value.
+	 * @throws ServletException if an error occurs.
+	 * @throws IOException if an error occurs.
+	 */
+	protected ConfigBean getConfigBean(HttpServletRequest req) throws ServletException, IOException {
+		HttpSession session = req.getSession(/*create*/true);
+		ConfigBean cb = (ConfigBean) session.getAttribute("cb");
+		if (cb == null) {
+			cb = new ConfigBean();
+			session.setAttribute("cb", cb);
+		}
+		Configuration config = getConfiguration();
+		cb.setConfiguration(config);
+		return cb;
+	}
+
+	/**
+	 * Check if administrative access is allowed.  This examines the request scheme
+	 * (http, ftp, https, etc.) and sees if https is required by the configuration.
+	 * It also checks the remote host and sees if localhost access is required.
+	 *
+	 * @param config a <code>Configuration</code> value.
+	 * @param req a <code>HttpServletRequest</code> value.
+	 * @param res a <code>HttpServletResponse</code> value.
+	 * @return True if access is approved, false otherwise.
+	 * @throws IOException if an error occurs.
+	 */
+	protected boolean approveAccess(Configuration config, HttpServletRequest req, HttpServletResponse res) throws IOException {
+		if (config.isHTTPSrequired() && !"https".equals(req.getScheme())) {
+			res.sendError(HttpServletResponse.SC_FORBIDDEN, "https required");
+			return false;
+		}
+
+		if (config.isLocalhostRequired() && !Utility.isLocalhost(req.getRemoteHost())) {
+			res.sendError(HttpServletResponse.SC_FORBIDDEN, "localhost access only");
+			return false;
+		}
+
+		return true;
+	}
+
+	/** Singleton configuration. */
+	private static volatile Configuration configuration;
+}
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/LoginServlet.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/LoginServlet.java
new file mode 100755
index 0000000..3fa9882
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/LoginServlet.java
@@ -0,0 +1,61 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.IOException;
+import java.util.Arrays;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Controller servlet that authenticates the administrator password.
+ * 
+ */
+public class LoginServlet extends GridServlet {
+	/**
+	 * Handle authentication from an administrator.
+	 *
+	 * @param req a <code>HttpServletRequest</code> value.
+	 * @param res a <code>HttpServletResponse</code> value.
+	 * @throws ServletException if an error occurs.
+	 * @throws IOException if an error occurs.
+	 */
+	public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
+		Configuration config = getConfiguration();			       // Get configuration
+		if (!approveAccess(config, req, res)) return;			       // Do https, localhost checking first
+
+		ConfigBean cb = getConfigBean(req);				       // Get bean
+		if (cb.isAuthentic()) {						       // Already authentic?
+			req.getRequestDispatcher("config.jsp").forward(req, res);      // Back to the config page with you!
+			return;
+		}
+
+		String password = req.getParameter("password");			       // Get submitted password
+		if (password == null) password = "";				       // If none, use an empty string
+		byte[] bytes = password.getBytes();				       // Get the bytes
+		if (!Arrays.equals(config.getPassword(), bytes)) {		       // Compare to stored password bytes 
+			cb.setMessage("Password incorrect");			       // Not equal!  Set message.
+			throw new ServletException(new AuthenticationRequiredException());
+		} else {
+			cb.setMessage("");					       // Equal, clear message
+			cb.setAuthentic(true);					       // You are now authenticated
+			req.getRequestDispatcher("config.jsp").forward(req, res);      // To the config page with you!
+		}
+	}
+}
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ProductQueryServlet.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ProductQueryServlet.java
new file mode 100755
index 0000000..c27f4f3
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ProductQueryServlet.java
@@ -0,0 +1,204 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.oodt.product.LargeProductQueryHandler;
+import org.apache.oodt.product.ProductException;
+import org.apache.oodt.product.QueryHandler;
+import org.apache.oodt.product.Retriever;
+import org.apache.oodt.xmlquery.LargeResult;
+import org.apache.oodt.xmlquery.Result;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+
+/**
+ * Product query servlet handles product queries.  It always returns the first matching
+ * product, if any.  If no handler can provide a product, it returns 404 Not Found.  If
+ * there are no query handlers, it returns 404 Not Found.
+ * 
+ */
+public class ProductQueryServlet extends QueryServlet {
+	/** {@inheritDoc} */
+	protected List getServers(Configuration config) {
+		return config.getProductServers();
+	}
+
+	/** {@inheritDoc} */
+	protected void handleQuery(XMLQuery query, List handlers, HttpServletRequest req, HttpServletResponse res)
+		throws IOException, ServletException {
+		if (handlers.isEmpty()) {
+			res.sendError(HttpServletResponse.SC_NOT_FOUND, "no query handlers available to handle query");
+			return;
+		}
+
+		try {								       // OK, let's try
+			for (Iterator i = handlers.iterator(); i.hasNext();) {	       // Try each query handler
+				QueryHandler handler = (QueryHandler) i.next();	       // Get the query handler
+				query = handler.query(query);			       // Give it the query
+				if (!query.getResults().isEmpty()) {		       // Did it give any result?
+					Result result = (Result) query.getResults().get(0); // Yes, get the result
+					deliverResult(handler, result, res);	       // And deliver it
+					return;					       // Done!
+				}
+			}
+		} catch (ProductException ex) {
+			res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getMessage());
+			return;
+		}
+
+		res.sendError(HttpServletResponse.SC_NOT_FOUND, "no matching products from any query handler");
+	}
+
+	/**
+	 * Deliver a result.  This streams the product data.
+	 *
+	 * @param handler Which handler produced the result.
+	 * @param result The result.
+	 * @param res The HTTP response to which to send the result data.
+	 * @throws IOException if an error occurs.
+	 */
+	private void deliverResult(QueryHandler handler, Result result, HttpServletResponse res) throws IOException {
+		characterize(handler, result, res);					       // First, describe it using HTTP headers
+		if (result instanceof LargeResult) {				       // Is it a large result?
+			LargeResult lr = (LargeResult) result;			       // Yes, this is gonna take some special work
+			LargeProductQueryHandler lpqh = (LargeProductQueryHandler) handler; // First treat 'em as large
+			ProductRetriever retriever = new ProductRetriever(lpqh);       // Large ones need a retriever
+			lr.setRetriever(retriever);				       // Set the retriever
+		}
+		BufferedInputStream in = null;					       // Start with no input stream
+		try {								       // Then try ...
+			in = new BufferedInputStream(result.getInputStream());	       // To open the input stream
+			byte[] buf = new byte[512];				       // And a byte buffer for data
+			int num;						       // And a place to count data
+			while ((num = in.read(buf)) != -1)			       // While we read
+				res.getOutputStream().write(buf, 0, num);	       // We write
+			res.getOutputStream().flush();				       // Flush to commit response
+		} finally {							       // And finally
+			if (in != null) try {					       // If we opened it
+				in.close();					       // Close it
+			} catch (IOException ignore) {}				       // Ignoring any error during closing
+		}								       // Because come on, it's just closing!
+	}									       // For fsck's sake!
+
+	/**
+	 * Characterize a result by using HTTP headers.
+	 *
+	 * @param result Result to characterize.
+	 * @param res HTTP response to set headers in.
+	 */
+	private void characterize(QueryHandler handler, Result result, HttpServletResponse res) {
+		String contentType = result.getMimeType();			       // Grab the content type
+		res.setContentType(contentType);				       // Set it
+		long size = result.getSize();					       // Grab the size
+		if (size >= 0)
+			res.addHeader("Content-Length", String.valueOf(size));	       // Don't use setContentLength(int)
+		if (!displayable(contentType))					       // Finally, if a browser can't show it
+			this.suggestFilename(handler, result, res);		       // Then suggest a save-as filename
+	}
+
+	/**
+	 * Tell if a result is displayable.  This compares its MIME type to a list of MIME
+	 * types commonly displayble by browsers.
+	 *
+	 * @param contentType MIME type.
+	 * @return a <code>boolean</code> value.
+	 */
+	protected static boolean displayable(String contentType) {
+		for (int i = 0; i < DISPLAYABLE_TYPES.length; ++i)		       // For each displayable type
+			if (DISPLAYABLE_TYPES[i].equals(contentType)) return true;     // Does it match?
+		return false;							       // None of 'em do, it's not displayable
+	}
+
+	/**
+	 * We can suggest a filename (if the client happens to be a browser) using a
+	 * content-disposition header.
+	 *
+	 * @param res a <code>HttpServletResponse</code> value.
+	 */
+	protected void suggestFilename(QueryHandler handler, Result result, HttpServletResponse res) {
+		
+		String resource = result.getResourceID();
+		if (resource == null || resource.length() == 0) resource = "product.dat";
+		
+		// suggest some names based on resource mime type
+		String contentType = res.getContentType();
+		
+		// "zip" mime types
+		if (contentType!=null) {
+			if (contentType.equals("application/x-compressed") || 
+				contentType.equals("application/x-zip-compressed") || 
+				contentType.equals("application/zip") || 
+				contentType.equals("multipart/x-zip") ) {
+				
+				// resource = resource.replaceAll("\\..+",".zip"); // replace extension with .zip 
+				resource = "products_" + resource + ".zip"; 				
+			}
+		}
+		
+		// set "Content-disposition" header
+		res.addHeader("Content-disposition", "attachment; filename=\"" + resource + "\"");
+		
+	}
+
+	/**
+	 * MIME types commonly displayable by browsers.
+	 */
+	private static final String[] DISPLAYABLE_TYPES = {
+		"text/plain", "text/richtext", "text/enriched", "text/tab-separated-values", "text/html", "text/xml", "text/rtf",
+		"message/rfc822", "message/partial", "message/external-body", "message/news", "message/http",
+		"message/delivery-status", "message/disposition-notification", "message/s-http", "application/rtf",
+		"application/pdf", "image/jpeg", "image/gif", "image/tiff", "image/png", "audio/basic", "audio/32kadpcm",
+		"audio/mpeg", "video/mpeg", "video/quicktime"
+	};
+
+	/**
+	 * Retriever that retrieves product data over a method call boundary to a large
+	 * product query handler.
+	 */
+	private static class ProductRetriever implements Retriever {
+		/**
+		 * Creates a new <code>ProductRetriever</code> instance.
+		 *
+		 * @param handler a <code>LargeProductQueryHandler</code> value.
+		 */
+		public ProductRetriever(LargeProductQueryHandler handler) {
+			this.handler = handler;
+		}
+
+		/** {@inheritDoc} */
+		public byte[] retrieveChunk(String id, long offset, int len) throws ProductException {
+			return handler.retrieveChunk(id, offset, len);
+		}
+
+		/** {@inheritDoc} */
+		public void close(String id) throws ProductException {
+			handler.close(id);
+		}
+
+		/** Handler to use. */
+		private LargeProductQueryHandler handler;
+	}
+}
+
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ProductServer.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ProductServer.java
new file mode 100755
index 0000000..ad16ff4
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ProductServer.java
@@ -0,0 +1,65 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+import org.apache.oodt.product.QueryHandler;
+
+/**
+ * A product server.
+ *
+ */
+public class ProductServer extends Server {
+	/**
+	 * Creates a new <code>ProductServer</code> instance.
+	 *
+	 * @param configuration System configuration.
+	 * @param className Class name of query handler.
+	 */
+	public ProductServer(Configuration configuration, String className) {
+		super (configuration, className);
+	}
+
+	/** {@inheritDoc} */
+	protected String getType() {
+		return "product";
+	}
+
+	public int hashCode() {
+		return super.hashCode() ^ 0xaaaaaaaa;
+	}
+
+	public boolean equals(Object obj) {
+		return super.equals(obj) && obj instanceof ProductServer;
+	}
+
+	public String toString() {
+		return "ProductServer[" + super.toString() + "]";
+	}
+
+	/**
+	 * Create a query handler from this server.
+	 *
+	 * @return a <code>QueryHandler</code> value.
+	 * @throws ClassNotFoundException if the class can't be found.
+	 * @throws InstantiationException if the handler can't be instantiated.
+	 * @throws IllegalAccessException if the handler has no public constructor.
+	 */
+	public QueryHandler createQueryHandler() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+		return (QueryHandler) createHandler();
+	}
+}
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ProfileQueryServlet.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ProfileQueryServlet.java
new file mode 100755
index 0000000..9bb96e8
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ProfileQueryServlet.java
@@ -0,0 +1,138 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.HashSet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.handlers.ProfileHandler;
+import org.apache.oodt.xmlquery.QueryElement;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+
+/**
+ * Profile query servlet handles profile queries.  It returns every matching profile from
+ * every query handler that provides matching profiles.  If no handlers are installed,
+ * then it returns an empty &lt;profiles&gt; document.
+ * 
+ */
+public class ProfileQueryServlet extends QueryServlet {
+	/** {@inheritDoc} */
+	protected List getServers(Configuration config) {
+		return config.getProfileServers();
+	}
+
+	/** {@inheritDoc} */
+	protected void handleQuery(XMLQuery query, List handlers, HttpServletRequest req, HttpServletResponse res)
+		throws IOException, ServletException {
+		// Find if the query should be targeted to specific handlers.
+		Set ids = new HashSet();
+		if (query.getFromElementSet() != null) {
+			for (Iterator i = query.getFromElementSet().iterator(); i.hasNext();) {
+				QueryElement qe = (QueryElement) i.next();
+				if ("handler".equals(qe.getRole()) && qe.getValue() != null)
+					ids.add(qe.getValue());
+			}
+		}
+		
+		res.setContentType("text/xml");					       // XML, comin' at ya
+		res.getWriter().println("<?xml version='1.0' encoding='UTF-8'?>");     // UTF-8 no less.  Boo-ya.
+		res.getWriter().println("<!DOCTYPE profiles PUBLIC '"		       // Get a doctype in there for the highly ...
+			+ Profile.PROFILES_DTD_FPI + "' '"			       // ... anal ...
+			+ Profile.PROFILES_DTD_URL + "'>");		               // ... retentive.
+		res.getWriter().println("<profiles>");				       // Start tag for the whole /sbin/fsck mess
+		Transformer transformer = null;					       // Start out w/no transformer and no doc
+		Document doc = null;						       // Don't make 'em if we don't need 'em
+		boolean sentAtLeastOne = false;					       // Track if we send any profiles at all
+		Exception exception = null;					       // And save any exception
+		for (Iterator i = handlers.iterator(); i.hasNext();) try {	       // To iterate over each handler
+			ProfileHandler handler = (ProfileHandler) i.next();            // Get the handler
+			String id = handler.getID();                                   // Get the ID, and if targeting to IDs
+			if (!ids.isEmpty() && !ids.contains(id)) continue;             // ... and it's not one we want, skip it.
+			List results = handler.findProfiles(query);                    // Have it find profiles
+			if (results == null) results = Collections.EMPTY_LIST;         // Assume nothing
+			for (Iterator j = results.iterator(); j.hasNext();) {          // For each matching profile
+				Profile profile = (Profile) j.next();	               // Get the profile
+				if (transformer == null) {		               // No transformer/doc yet?
+					transformer = createTransformer();             // Then make the transformer
+					doc = Profile.createProfileDocument();         // And the doc
+				}					               // And use the doc ...
+				Node profileNode = profile.toXML(doc);	               // To render the profile into XML
+				DOMSource source = new DOMSource(profileNode);         // And the XML becomes is source
+				StreamResult result = new StreamResult(res.getWriter()); // And the response is a result
+				transformer.transform(source, result);	               // And serialize into glorious text
+				sentAtLeastOne = true;				       // OK, we got at least one out the doo
+			}
+		} catch (Exception ex) {					       // Uh oh
+			exception = ex;						       // OK, just hold onto it for now
+		}
+		if (!sentAtLeastOne && exception != null) {			       // Got none out the door and had an error?
+			res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,    // Then we can report it.
+				exception.getMessage());
+			return;
+		}
+
+		// However, if we get here, we got at least one profile out the door. In
+		// that case, hide any error that might've occurred from subsequent
+		// handlers.  (Or, if we get here, there were no errors.  Yay.)
+		res.getWriter().println("</profiles>");				       // End tag for the whole fsck'n mess
+	}
+
+	/**
+	 * Create a transformer, properly configured for XML text serialization.
+	 *
+	 * @return a <code>Transformer</code> value.
+	 * @throws TransformerException if an error occurs.
+	 */
+	private static Transformer createTransformer() throws TransformerException {
+		Transformer transformer;
+		synchronized (TRANSFORMER_FACTORY) {
+			transformer = TRANSFORMER_FACTORY.newTransformer();
+		}
+		transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+		transformer.setOutputProperty(OutputKeys.VERSION, "1.0");
+		transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+		transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+		transformer.setOutputProperty(OutputKeys.STANDALONE, "no");
+		transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+		transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml");
+		transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+
+		return transformer;
+	}
+
+	/** Sole transformer factory this class will ever need. */
+	private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();
+}
+
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ProfileServer.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ProfileServer.java
new file mode 100755
index 0000000..f273fa6
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/ProfileServer.java
@@ -0,0 +1,71 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+import org.apache.oodt.profile.handlers.ProfileHandler;
+
+/**
+ * A profile server.
+ * 
+ */
+public class ProfileServer extends Server {
+  /**
+   * Creates a new <code>ProfileServer</code> instance.
+   * 
+   * @param configuration
+   *          System configuration.
+   * @param className
+   *          Class name of profile handler.
+   */
+  public ProfileServer(Configuration configuration, String className) {
+    super(configuration, className);
+  }
+
+  /** {@inheritDoc} */
+  protected String getType() {
+    return "profile";
+  }
+
+  public int hashCode() {
+    return super.hashCode() ^ 0x55555555;
+  }
+
+  public boolean equals(Object obj) {
+    return super.equals(obj) && obj instanceof ProfileServer;
+  }
+
+  public String toString() {
+    return "ProfileServer[" + super.toString() + "]";
+  }
+
+  /**
+   * Create a query handler from this server.
+   * 
+   * @return a <code>ProfileHandler</code> value.
+   * @throws ClassNotFoundException
+   *           if the class can't be found.
+   * @throws InstantiationException
+   *           if the handler can't be instantiated.
+   * @throws IllegalAccessException
+   *           if the handler has no public constructor.
+   */
+  public ProfileHandler createProfileHandler() throws ClassNotFoundException,
+      InstantiationException, IllegalAccessException {
+    return (ProfileHandler) createHandler();
+  }
+}
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/QueryServlet.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/QueryServlet.java
new file mode 100755
index 0000000..a3a7ad3
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/QueryServlet.java
@@ -0,0 +1,255 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.xml.sax.SAXException;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+/**
+ * Query servlet provides common query functionality for profile queries and product
+ * queries.  It treats GETs as POSTs, retrieves the complete XMLQuery (if the
+ * <code>xmlq</code> request parameter appears) or constructs a new XMLQuery (using the
+ * <code>q</code> request parameter, which contains just a query expression), updates
+ * system properties for the handlers, instantiates any new handlers, and then runs the
+ * query.
+ *
+ */
+public abstract class QueryServlet extends GridServlet {
+	/**
+	 * Get a list of {@link Server}s that will provide handlers to handle the query.
+	 * Subclasses implement this by returning a list of either {@link ProductServer}s
+	 * or {@link ProfileServer}s.
+	 *
+	 * @param config a <code>Configuration</code> value.
+	 * @return a <code>List</code> value of {@link Server}s of some kind.
+	 */
+	protected abstract List getServers(Configuration config);
+
+	/**
+	 * Handle the query.  Subclasses implement this by parsing the query and returning
+	 * some results.
+	 *
+	 * @param query The query to handle.
+	 * @param handlers A list of either product <code>QueryHandler</code>s or profile <code>ProfileHandler</code>s.
+	 * @param req a <code>HttpServletRequest</code> value.
+	 * @param res a <code>HttpServletResponse</code> value.
+	 * @throws IOException if an I/O error occurs.
+	 * @throws ServletException if a servlet error occurs.
+	 */
+	protected abstract void handleQuery(XMLQuery query, List handlers, HttpServletRequest req, HttpServletResponse res)
+		throws IOException, ServletException;
+
+	/**
+	 * Treat GETs as POSTs.
+	 *
+	 * @param req a <code>HttpServletRequest</code> value.
+	 * @param res a <code>HttpServletResponse</code> value.
+	 * @throws IOException if an error occurs.
+	 * @throws ServletException if an error occurs.
+	 */
+	public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
+		doPost(req, res);
+	}
+
+	/**
+	 * Handle the query.
+	 *
+	 * @param req a <code>HttpServletRequest</code> value.
+	 * @param res a <code>HttpServletResponse</code> value.
+	 * @throws IOException if an error occurs.
+	 * @throws ServletException if an error occurs.
+	 */
+	public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
+		try {
+			XMLQuery query = getQuery(req, res);			       // Get the query
+			if (query == null) return;				       // No query? My favorite case, right here!
+
+			Configuration config = getConfiguration();		       // Get the current configuration.
+			updateProperties(config);				       // Using it, update the system properties
+			updateHandlers(getServers(config));			       // And any servers.
+
+			List handlerObjects = new ArrayList(handlers.size());	       // Start with no handlers.
+			for (Iterator i = handlers.iterator(); i.hasNext();) {	       // For each server
+				InstantiedHandler ih = (InstantiedHandler) i.next();   // Get its handler
+				handlerObjects.add(ih.getHandler());		       // Add its handler
+			}
+			handleQuery(query, handlerObjects, req, res);		       // Handlers: handle query, please
+		} catch (RuntimeException ex) {
+			throw ex;
+		} catch (Exception ex) {
+			throw new ServletException(ex);
+		}
+	}
+
+	/**
+	 * Get the query from an HTTP request.  The request must have either a
+	 * <code>xmlq</code> parameter (which is given priority) or a <code>q</code>
+	 * parameter.  We expect <code>xmlq</code> to contain the XML text format of an
+	 * XMLQuery object.  <code>q</code> can contain just the query expression, from
+	 * which we'll construct a fresh <code>XMLQuery</code> with reasonable defaults.
+	 * If the user specifies the <code>q</code> paramater, we'll treat it as a parsed
+	 * query, letting the XMLQuery class parse it and build its various expression
+	 * stacks according to the DIS syntax.  The user can specify the <code>unp</code>
+	 * parameter to control this behavior, though.  Set to the string
+	 * <code>true</code> and we'll treat the query as <em>unparsed</em>, and the
+	 * XMLQuery class should leave it alone.  Otherwise, an other value (or
+	 * unspecified) will be interpreted as <code>false</code>, meaning the query will
+	 * be parsed.
+	 *
+	 * @param req a <code>HttpServletRequest</code> value.
+	 * @param res a <code>HttpServletResponse</code> value.
+	 * @return a <code>XMLQuery</code> value.
+	 * @throws IOException if an error occurs.
+	 */
+	protected XMLQuery getQuery(HttpServletRequest req, HttpServletResponse res) throws IOException {
+		String xmlq = req.getParameter("xmlq");				       // Grab any xmlq
+		String q = req.getParameter("q");				       // Grab any q
+		String unp = req.getParameter("unp");				       // And grab any unp (pronounced "unp")
+		if (xmlq == null) xmlq = "";					       // No xmlq?  Use epsilon
+		if (q == null) q = "";						       // No q?  Use lambda
+		if (unp == null) unp = "";					       // Use some other greek letter for empty str
+		String[] mimes = req.getParameterValues("mime");		       // Grab any mimes
+		if (mimes == null) mimes = EMPTY_STRING_ARRAY;			       // None?  Use empty array
+
+		if (xmlq.length() > 0) try {					       // Was there an xmlq?
+			return new XMLQuery(xmlq);				       // Use it in its entirety, ignoring the rest
+		} catch (SAXException ex) {					       // Can't parse it?
+			res.sendError(HttpServletResponse.SC_BAD_REQUEST,	       // Then that's a bad ...
+				"cannot parse xmlq: " + ex.getMessage());	       // ... request, which I hate
+			return null;						       // so flag it with a null
+		} else if (q.length() > 0) {					       // Was there a q?
+			boolean unparsed = "true".equals(unp);			       // If so, was there also an unp?
+			return new XMLQuery(q, "wgq", "Web Grid Query",		       // Use it to make an XMLQuery
+				"Query from Web-Grid", /*ddID*/null,                   // And all of these extra
+				/*resultModeId*/null, /*propType*/null,                // parameters really annoy
+				/*propLevels*/null, /*maxResults*/Integer.MAX_VALUE,   // the poop out of me
+				Arrays.asList(mimes), !unparsed);                      // It's just a query for /sbin/fsck sake!
+		}
+
+		res.sendError(HttpServletResponse.SC_BAD_REQUEST, "xmlq or q parameters required");
+		return null;
+	}
+
+	/**
+	 * Update the query handlers instantiated.
+	 *
+	 * @param servers a <code>List</code> of {@link Server}s.
+	 * @throws ClassNotFoundException if a class can't be found.
+	 * @throws InstantiationException if a class can't be instantiated.
+	 * @throws IllegalAccessException if a constructor isn't public.
+	 */
+	private synchronized void updateHandlers(List servers) throws ClassNotFoundException, InstantiationException,
+		IllegalAccessException {
+		eachServer:
+		for (Iterator i = servers.iterator(); i.hasNext();) {		       // For each server
+			Server server = (Server) i.next();			       // Grab the server
+			for (Iterator j = handlers.iterator(); j.hasNext();) {	       // For each handler
+				InstantiedHandler handler = (InstantiedHandler) j.next(); // Grab the handler
+				if (handler.getServer().equals(server))		       // Have we already instantiated?
+					continue eachServer;			       // Yes, try the next server
+			}
+			InstantiedHandler handler				       // No.  Create ...
+				= new InstantiedHandler(server, server.createHandler()); // ... a fresh handler
+			handlers.add(handler);					       // Save it
+		}
+
+		for (Iterator i = handlers.iterator(); i.hasNext();) {		       // Now, for each handler
+			InstantiedHandler handler = (InstantiedHandler) i.next();      // Grab the handler
+			if (!servers.contains(handler.getServer()))		       // Does its server still exist?
+				i.remove();					       // If not, remove the handler
+		}
+	}
+
+	/**
+	 * Update system properties used by query handlers, if any have changed.
+	 *
+	 * @param config a <code>Configuration</code> value.
+	 */
+	private synchronized void updateProperties(Configuration config) {
+		if (properties != null) {					       // Any old properties?
+			if (properties.equals(config.getProperties())) return;	       // Yes, any changes?  No?  Then done.
+			for (Iterator i = properties.keySet().iterator(); i.hasNext();)	// Yes, then grab each old setting
+				System.getProperties().remove(i.next());	       // and remove it.
+		}
+		properties = (Properties) config.getProperties().clone();	       // Now copy the new settings
+		System.getProperties().putAll(properties);			       // And set them!
+	}
+
+	/**
+	 * Instantiated query handlers.
+	 *
+	 * These are either <code>ProfileHandler</code>s or product <code>QueryHandler</code>s.
+	 */
+	protected List handlers = new ArrayList();
+
+	/** Current settings of system properties. */
+	private Properties properties;
+
+	/**
+	 * An instantiated handler.  This is a <code>ProfileHandler</code> or a product
+	 * <code>QueryHandler</code> along with the {@link Server} that defined it.
+	 */
+	private static class InstantiedHandler {
+		/**
+		 * Creates a new <code>InstantiedHandler</code> instance.
+		 *
+		 * @param server a <code>Server</code>.
+		 * @param handler a <code>ProfileHandler</code> or a product <code>QueryHandler</code>.
+		 */
+		InstantiedHandler(Server server, Object handler) {
+			this.server = server;
+			this.handler = handler;
+		}
+
+		/**
+		 * Get the server that defined this handler.
+		 *
+		 * @return a <code>Server</code> value.
+		 */
+		public Server getServer() {
+			return server;
+		}
+
+		/**
+		 * Get the handler.
+		 *
+		 * @return a <code>ProfileHandler</code> or a product <code>QueryHandler</code>.
+		 */
+		public Object getHandler() {
+			return handler;
+		}
+
+		/** Server that defines the handler. */
+		private Server server;
+
+		/** A <code>ProfileHandler</code> or a product <code>QueryHandler</code> */
+		private Object handler;
+	}
+
+	/** So we don't create a bunch of empty string arrays, here's the only one we'll ever need. */
+	private static final String[] EMPTY_STRING_ARRAY = new String[0];
+}
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/RestfulProductQueryServlet.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/RestfulProductQueryServlet.java
new file mode 100644
index 0000000..70eb625
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/RestfulProductQueryServlet.java
@@ -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.
+ */
+package org.apache.oodt.grid;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.oodt.xmlquery.XMLQuery;
+
+/**
+ * The {@link RestfulProductQueryServlet} is an alternative to the standard {@link ProductQueryServlet} 
+ * that allows clients to use a more intuitive syntax for encoding query constraints, than the traditional
+ * DIS-style syntax. 
+ * For example, instead of encoding a request as: 
+ * "?q=identifier+EQ+urn:nasa:pds:phx_lidar:reduced:LS075RLS_00902835894_1885M1+AND+package+EQ+TGZ"
+ * a client could encode it as:
+ * "?identifier=urn:nasa:pds:phx_lidar:reduced:LS075RLS_00902835894_1885M1&package=TGZ".
+ * Note that this servlet is meant to be back-ward compatible, i.e. it will first process a request by
+ * parsing the "xmlq=" and "q=" parameters. If those are not found, it will build a request by combining 
+ * all the available HTTP parameters in logical AND.
+ * Note also that this servlet is NOT enabled by default 
+ * (i.e. it must be explicitly configured by changing the web-grid deployment descriptor web.xml).
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public class RestfulProductQueryServlet extends ProductQueryServlet {
+	
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * Overridden implementation that defaults to the standard behavior if the parameters "q" or "xmlq" are found,
+	 * otherwise it uses the available request parameters to build a constraint query with logical AND.
+	 */
+	@Override
+	protected XMLQuery getQuery(HttpServletRequest req, HttpServletResponse res) throws IOException {
+		
+		// if DIS-style parameters are found, default to standard processing
+		if (req.getParameter("xmlq") !=null || req.getParameter("q")!=null) {
+			XMLQuery xmlQuery = super.getQuery(req, res);
+			return xmlQuery;
+			
+		// combine all HTTP (name, value) pairs into XML query string with logical AND
+		} else {
+			
+			StringBuffer q = new StringBuffer("");
+			Enumeration<String> parameterNames = req.getParameterNames();
+			while (parameterNames.hasMoreElements()) {
+				String paramName = parameterNames.nextElement();
+				String[] paramValues = req.getParameterValues(paramName);
+				for (int i = 0; i < paramValues.length; i++) {
+					if (q.length()>0) q.append(" AND ");
+					q.append(paramName+" EQ "+paramValues[i]);
+				}
+			}
+			
+			// build XMLQuery object from HTTP parameters
+			// no need to URL-encode since this request doesn't go over the network
+			System.out.println("Executing query="+q.toString());
+			return new XMLQuery(q.toString(), "wgq", "Web Grid Query",	
+					"Query from Web-Grid", /*ddID*/null,                   
+					/*resultModeId*/null, /*propType*/null,                
+					/*propLevels*/null, /*maxResults*/Integer.MAX_VALUE,   
+					new ArrayList<String>(), true);			
+		}
+		
+	}
+
+}
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/Server.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/Server.java
new file mode 100755
index 0000000..5d4eb3b
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/Server.java
@@ -0,0 +1,170 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.Serializable;
+import java.net.URL;
+import java.net.URLClassLoader;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+import java.util.List;
+
+/**
+ * An abstract server defines the code base and class name of a query handler.
+ * 
+ */
+public abstract class Server implements Serializable {
+  /**
+   * Creates a new <code>Server</code> instance.
+   * 
+   * @param configuration
+   *          System configuration.
+   * @param className
+   *          Class name of the query handler.
+   */
+  public Server(Configuration configuration, String className) {
+    this.configuration = configuration;
+    this.className = className;
+  }
+
+  /**
+   * Render this server into XML.
+   * 
+   * @param owner
+   *          Owning document.
+   * @return This server, as XML.
+   */
+  public Node toXML(Document owner) {
+    Element elem = owner.createElement("server");
+    elem.setAttribute("className", className);
+    elem.setAttribute("type", getType());
+    return elem;
+  }
+
+  /**
+   * Get the class name of the query handler.
+   * 
+   * @return Class name of the query handler.
+   */
+  public String getClassName() {
+    return className;
+  }
+
+  /**
+   * Create the handler.
+   * 
+   * @return an instantiated handlre.
+   * @throws ClassNotFoundException
+   *           if the handler class can't be found.
+   * @throws InstantiationException
+   *           if the handler object can't be created.
+   * @throws IllegalAccessException
+   *           if the handler class doesn't provide a public no-args
+   *           constructor.
+   */
+  public Object createHandler() throws ClassNotFoundException,
+      InstantiationException, IllegalAccessException {
+    List urlList = configuration.getCodeBases();
+    Class clazz;
+    if (urlList.isEmpty())
+      clazz = Class.forName(className);
+    else {
+      URL[] urls = (URL[]) urlList.toArray(EMPTY_URL_ARRAY);
+      URLClassLoader loader = new URLClassLoader(urls, getClass()
+          .getClassLoader());
+      clazz = loader.loadClass(className);
+    }
+    return clazz.newInstance();
+  }
+
+  /**
+   * Set the class name of the handler.
+   * 
+   * @param className
+   *          Class name of the handler.
+   */
+  public void setClassName(String className) {
+    this.className = className;
+  }
+
+  /**
+   * Return the type of the handler.
+   * 
+   * @return Either <code>product</code> or <code>profile</code>.
+   */
+  protected abstract String getType();
+
+  public int hashCode() {
+    return configuration.hashCode() ^ className.hashCode();
+  }
+
+  public boolean equals(Object obj) {
+    if (obj == this)
+      return true;
+    if (obj instanceof Server) {
+      Server rhs = (Server) obj;
+      return configuration.equals(configuration)
+          && className.equals(rhs.className);
+    }
+    return false;
+  }
+
+  public String toString() {
+    return "Server[className=" + className + "]";
+  }
+
+  /**
+   * Create a server from an XML element.
+   * 
+   * @param elem
+   *          XML element, presumed to be a &lt;server&gt; element.
+   * @return a <code>Server</code> subclass.
+   * @throws SAXException
+   *           if the element can't be properly parsed.
+   */
+  public static Server create(Configuration configuration, Element elem)
+      throws SAXException {
+    String type = elem.getAttribute("type");
+    if (type == null)
+      throw new SAXException("type attribute missing from <"
+          + elem.getNodeName() + ">");
+
+    String className = elem.getAttribute("className");
+    if (className == null)
+      throw new SAXException("className attribute missing from <"
+          + elem.getNodeName() + ">");
+
+    // Replace with a factory some day...
+    if ("product".equals(type))
+      return new ProductServer(configuration, className);
+    else if ("profile".equals(type))
+      return new ProfileServer(configuration, className);
+    else
+      throw new SAXException("unknown server type `" + type + "'");
+  }
+
+  /** Configuration. */
+  protected Configuration configuration;
+
+  /** Class name of the handler class. */
+  protected String className;
+
+  private static final URL[] EMPTY_URL_ARRAY = new URL[0];
+}
diff --git a/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/Utility.java b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/Utility.java
new file mode 100755
index 0000000..93cc215
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/java/org/apache/oodt/grid/Utility.java
@@ -0,0 +1,82 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+/**
+ * Utility methods for web grid.
+ * 
+ */
+public class Utility {
+  /**
+   * Provide XHTML-safe escaping for a string. Basically, this is the same as
+   * XML-escaping, but since some user agents don't recognize
+   * <code>&amp;apos;</code>, we use <code>&amp;#39;</code> instead.
+   * 
+   * @param str
+   *          String to escape.
+   * @return <var>str</var> escaped.
+   */
+  public static String esc(String str) {
+    StringBuffer s = new StringBuffer(str.length()); // Assume at least the same
+    // length
+    for (int i = 0; i < str.length(); ++i) { // For each character
+      char c = str.charAt(i); // Grab the character
+      switch (c) { // Now consider what it is ...
+      case '<': // A less than?
+        s.append("&lt;"); // Well, that's &lt;
+        break;
+      case '>': // A greater than?
+        s.append("&gt;"); // That's &gt;
+        break;
+      case '&': // An ampersand?
+        s.append("&amp;"); // We all know what that is
+        break;
+      case '\'': // A tick?
+        s.append("&#39;"); // Not &apos; ! TRICKY!
+        break;
+      case '\"': // A quote?
+        s.append("&quot;"); // Yadda, yadda, yadda
+        break;
+      default: // Anything else may pass
+        s.append(c); // ... through unchanged
+        break;
+      }
+    }
+    return s.toString(); // Donenacious.
+  }
+
+  /**
+   * Tell if a host name refers to the localhost. This checks the standard IPv6
+   * address, IPv4 address, and host name for localhost.
+   * 
+   * @param host
+   *          Host name to check.
+   * @return True if <var>host</var> names the localhost.
+   */
+  public static boolean isLocalhost(String host) {
+    return "0:0:0:0:0:0:0:1".equals(host) || "127.0.0.1".equals(host)
+        || "localhost".equals(host);
+  }
+
+  /**
+   * Do not call.
+   */
+  private Utility() {
+    throw new IllegalStateException("This is a \u00abutility\u00bb class");
+  }
+}
diff --git a/0.8.1-rc1/grid/src/main/webapp/META-INF/context.xml b/0.8.1-rc1/grid/src/main/webapp/META-INF/context.xml
new file mode 100755
index 0000000..a82645f
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<Context
+   cookies='true'
+   override='true'
+   privileged='false'
+   reloadable='false'
+   unpackWAR='true'/>
diff --git a/0.8.1-rc1/grid/src/main/webapp/WEB-INF/jetty-web.xml b/0.8.1-rc1/grid/src/main/webapp/WEB-INF/jetty-web.xml
new file mode 100755
index 0000000..52b2379
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/webapp/WEB-INF/jetty-web.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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 Configure PUBLIC '-//Mort Bay Consulting//DTD Configure 1.2//EN' 'http://jetty.mortbay.org/configure_1_2.dtd'>
+<Configure class='org.mortbay.jetty.servlet.WebApplicationContext'>
+  <Set name='extractWAR'>true</Set>
+</Configure>
diff --git a/0.8.1-rc1/grid/src/main/webapp/WEB-INF/web.xml b/0.8.1-rc1/grid/src/main/webapp/WEB-INF/web.xml
new file mode 100755
index 0000000..98dfcef
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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 web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+  <icon>
+    <small-icon>images/webapp-small.png</small-icon>
+    <large-icon>images/webapp-large.png</large-icon>
+  </icon>
+  <display-name>Web Grid</display-name>
+  <description>
+    Web Grid is an OODT web application that provides HTTP based
+    access to OODT profile and product query handlers.  It also
+    includes web accessible configuration and updates with a simple
+    administrative security policy.
+  </description>
+  <distributable/>
+  <servlet>
+    <servlet-name>product</servlet-name>
+    <display-name>Product</display-name>
+    <description>
+    </description>
+    <servlet-class>org.apache.oodt.grid.ProductQueryServlet</servlet-class>
+  </servlet>
+  <servlet>
+    <servlet-name>profile</servlet-name>
+    <display-name>Profile</display-name>
+    <description>
+    </description>
+    <servlet-class>org.apache.oodt.grid.ProfileQueryServlet</servlet-class>
+  </servlet>
+  <servlet>
+    <servlet-name>config</servlet-name>
+    <display-name>Configure</display-name>
+    <description>
+    </description>
+    <servlet-class>org.apache.oodt.grid.ConfigServlet</servlet-class>
+  </servlet>
+  <servlet>
+    <servlet-name>login</servlet-name>
+    <display-name>Login</display-name>
+    <description>
+    </description>
+    <servlet-class>org.apache.oodt.grid.LoginServlet</servlet-class>
+  </servlet>
+  <servlet-mapping>
+    <servlet-name>product</servlet-name>
+    <url-pattern>/prod</url-pattern>
+  </servlet-mapping>
+  <servlet-mapping>
+    <servlet-name>profile</servlet-name>
+    <url-pattern>/prof</url-pattern>
+  </servlet-mapping>
+  <servlet-mapping>
+    <servlet-name>config</servlet-name>
+    <url-pattern>/conf</url-pattern>
+  </servlet-mapping>
+  <servlet-mapping>
+    <servlet-name>login</servlet-name>
+    <url-pattern>/login</url-pattern>
+  </servlet-mapping>
+  <session-config>
+    <session-timeout>0</session-timeout>
+  </session-config>
+  <welcome-file-list>
+    <welcome-file>index.html</welcome-file>
+  </welcome-file-list>
+  <error-page>
+    <exception-type>org.apache.oodt.grid.AuthenticationRequiredException</exception-type>
+    <location>/error.jsp</location>
+  </error-page>
+</web-app>
diff --git a/0.8.1-rc1/grid/src/main/webapp/config.jsp b/0.8.1-rc1/grid/src/main/webapp/config.jsp
new file mode 100755
index 0000000..1c5c699
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/webapp/config.jsp
@@ -0,0 +1,205 @@
+<%@ page language="java" session="true" contentType="text/html; charset=UTF-8" info="Config" errorPage="error.jsp" 
+  import="java.util.Map,java.util.Iterator,org.apache.oodt.grid.Server,org.apache.oodt.grid.Utility,java.net.URL" %>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<jsp:useBean id="cb" scope="session" class="org.apache.oodt.grid.ConfigBean"/>
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
+  <head>
+    <title>Web Grid Configuration</title>
+    <link rel='stylesheet' type='text/css' href='style.css'/>
+  </head>
+  <body>
+    <h1>Web Grid Configuration</h1>
+
+    <% if (cb.getMessage().length() > 0) { %>
+      <div class='error'><jsp:getProperty name='cb' property='message'/></div>
+    <% } %>
+
+    <form action='conf' method='post'>
+
+      <fieldset>
+        <legend>Administrative Settings</legend>
+	<div class='field'>
+          <label for='passwordField'>New Administrator Password</label>
+          <div class='fieldHelp'>
+            Leave blank to leave password unchanged.
+          </div>
+	  <input id='passwordField' type='password' name='password'/>
+        </div>
+
+	<div class='field'>
+	  <label for='lhf'>Require Administrative Access from Local Host Only</label>
+	  <div class='fieldHelp'>
+	    Click Yes to enable administrative access from browsers
+	    running on the local web-server host only.  Click No to
+	    allow any host to access these administrative pages.
+	  </div>
+	  <input id='lhf' type='radio' name='localhost' value='on' <%= cb.isLocalhostRequired()? "checked='checked'" : "" %> />Yes
+	  <input type='radio' name='localhost' value='off' <%= !cb.isLocalhostRequired()? "checked='checked'" : "" %> />No
+	</div>
+
+        <div class='field'>
+          <label for='httpsField'>Require HTTPS for Administrative Access</label>
+          <div class='fieldHelp'>
+	    Click Yes to require HTTPS for access to these administrative pages. Note that this will require
+	    your web server to also support HTTPS. If you're not sure, <strong>click No</strong>.
+          </div>
+          <input id='httpsField' type='radio' name='https' value='on' <%= cb.isHttpsRequired()? "checked='checked'" : "" %> />Yes
+          <input type='radio' name='https' value='off' <%= !cb.isHttpsRequired()? "checked='checked'" : "" %> />No
+        </div>
+      </fieldset>
+
+      <fieldset>
+	<legend>System Properties</legend>
+	<div class='field'>
+	  <div class='fieldHelp'>To add a new system property, enter
+	    its key and value at the bottom.  You can change the values
+	    of existing properties. To delete an existing property,
+	    check the box to its right.</div>
+	  <table>
+	    <thead><tr><th>#</th><th>Key</th><th>Value</th><th>Delete?</th></tr></thead>
+	    <tbody>
+	    <% int row = 1; for (Iterator i = cb.getProperties().entrySet().iterator(); i.hasNext(); ++row) {
+	       Map.Entry entry = (Map.Entry) i.next();
+	       String key = (String) entry.getKey();
+	       String val = (String) entry.getValue();
+	    %>
+	      <tr class='<%= row % 2 == 0? "evenRow" : "oddRow"%>'>
+		<td><%= row %>.</td>
+		<td><span class='key'><%= Utility.esc(key) %></span></td>
+		<td><input type='text' name='val-<%= Utility.esc(key) %>' value='<%= Utility.esc(val) %>'/></td>
+		<td><input type='checkbox' name='del-<%= Utility.esc(key) %>'/></td>
+	      </tr>
+	    <% } %>
+	      <tr class='newRow'>
+		<td>(New)</td>
+		<td><input type='text' id='newkey' name='newkey'/></td>
+		<td><input type='text' id='newval' name='newval'/></td>
+		<td>&#x00a0;</td>
+	      </tr>
+	    </tbody>
+	  </table>
+	</div>
+      </fieldset>
+
+      <fieldset>
+	<legend>Code Bases</legend>
+	<div class='fieldHelp'>Specify a URL for each code base.  URLs
+	  to files are assumed to be jar files.  URLs that end in a
+	  <code>/</code> refer to directories containing class files.
+	  Check the box to delete a code base.
+	</div>
+
+	<table>
+	  <thead><tr><th>#</th><th>Code Base</th><th>Delete?</th></thead>
+	  <tbody>
+	  <% row = 0; for (Iterator i = cb.getConfiguration().getCodeBases().iterator(); i.hasNext(); ++row) {
+	    URL codeBaseURL = (URL) i.next();
+	  %>
+	    <tr class='<%= row+1 % 2 == 0? "evenRow" : "oddRow"%>'>
+	      <td><%= row+1 %>.</td>
+	      <td><%= Utility.esc(codeBaseURL.toString()) %></td>
+	      <td><input type='checkbox' name='delcb-<%= row %>'/></td>
+	    </tr>
+	  <% } %>
+	    <tr class='newRow'>
+	      <td>(New)</td>
+	      <td><input type='text' name='newcb'/></td>
+	      <td>&#x00a0;</td>
+	    </tr>
+	  </tbody>
+	</table>
+      </fieldset>
+
+      <table>
+        <caption>Query Handlers</caption>
+        <tbody>
+          <tr style="vertical-align: top;">
+            <td>
+	      <fieldset>
+		<legend>Product Query Handlers</legend>
+		<div class='field'>
+		  <div class='fieldHelp'>Specify the class name for each
+		    product query handler; the class must implement the
+		    <code>org.apache.oodt.product.QueryHandler</code> interface.</div>
+		  <table>
+		    <thead><tr><th>#</th><th>Class Name</th><th>Delete?</th></tr></thead>
+		    <tbody>
+		    <% row = 0; for (Iterator i = cb.getProductServers().iterator(); i.hasNext(); ++row) {
+		      Server server = (Server) i.next();
+		      String className = server.getClassName();
+		    %>
+		      <tr class='<%= row % 2 == 0? "oddRow" : "evenRow" %>'>
+			<td><%= row+1 %>.</td>
+			<td><code><%= Utility.esc(className) %></code></td>
+			<td><input type='checkbox' name='drm-<%= row %>'/></td>
+		      </tr>
+		    <% } %>
+		      <tr class='newRow'>
+			<td>(New)</td>
+			<td><input type='text' name='d-newcn'/></td>
+			<td>&#x00a0;</td>
+		      </tr>
+		    </tbody>
+		  </table>
+		</div>
+	      </fieldset>
+            </td>
+            <td>
+	      <fieldset>
+		<legend>Profile Query Handlers</legend>
+		<div class='field'>
+		  <div class='fieldHelp'>Specify the class name for each
+		    profile query handler; the class must implement the
+		    <code>org.apache.oodt.profile.handlers.ProfileHandler</code> interface.</div>
+		  <table>
+		    <thead><tr><th>#</th><th>Class Name</th><th>Delete?</th></tr></thead>
+		    <tbody>
+		    <% row = 0; for (Iterator i = cb.getProfileServers().iterator(); i.hasNext(); ++row) {
+		      Server server = (Server) i.next();
+		      String className = server.getClassName();
+		    %>
+		      <tr class='<%= row % 2 == 0? "oddRow" : "evenRow" %>'>
+			<td><%= row+1 %>.</td>
+			<td><code><%= Utility.esc(className) %></code></td>
+			<td><input type='checkbox' name='mrm-<%= row %>'/></td>
+		      </tr>
+		    <% } %>
+		      <tr class='newRow'>
+			<td>(New)</td>
+			<td><input type='text' name='m-newcn'/></td>
+			<td>&#x00a0;</td>
+		      </tr>
+		    </tbody>
+		  </table>
+		</div>
+	      </fieldset>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+
+      <div class='formControls'>
+        <input type='submit' name='submit' value='Save Changes'/>
+      </div>
+
+    </form>
+
+  </body>
+</html>
diff --git a/0.8.1-rc1/grid/src/main/webapp/error.jsp b/0.8.1-rc1/grid/src/main/webapp/error.jsp
new file mode 100755
index 0000000..3305a36
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/webapp/error.jsp
@@ -0,0 +1,60 @@
+<%@ page language="java" session="true" contentType="text/html; charset=UTF-8" info="Config" isErrorPage="true" 
+  import="org.apache.oodt.grid.AuthenticationRequiredException,java.io.StringWriter,java.io.PrintWriter"
+%>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<jsp:useBean id="cb" scope="session" class="org.apache.oodt.grid.ConfigBean"/>
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
+  <head>
+    <title>Web Grid</title>
+    <link rel='stylesheet' type='text/css' href='style.css'/>
+  </head>
+  <body>
+    <%! StringWriter s = new StringWriter();
+    PrintWriter w = new PrintWriter(s); %>
+    <% exception.printStackTrace(w); w.close(); %>
+
+    <h1>Web Grid</h1>
+    <% if (cb.getMessage().length() > 0) { %>
+      <div class='error'><jsp:getProperty name='cb' property='message'/></div>
+    <% } %>
+
+    <% if (exception instanceof AuthenticationRequiredException) { %>
+      <form action='login' method='post'>
+        <fieldset>
+	  <legend>Log In</legend>
+	  <div class='field'>
+	    <label for='pw'>Administrator password:</label>
+	    <div class='fieldHelp'>
+	      Passwords are case sensitve; check your CAPS LOCK key, if necessary.
+	    </div>
+	    <input id='pw' type='password' name='password'/>
+	  </div>
+	  <div class='formControls'>
+	    <input type='submit' name='submit' value='Log In'/>
+          </div>
+        </fieldset>
+      </form>
+   <% } else { %>
+     <h1>Error</h1>
+     <div>Exception <code><%= exception.getClass().getName() %></code>: <%= exception.getMessage() %></div>
+     <pre><%= s.getBuffer().toString() %></pre>
+   <% } %>
+  </body>
+</html>
diff --git a/0.8.1-rc1/grid/src/main/webapp/images/webapp-large.png b/0.8.1-rc1/grid/src/main/webapp/images/webapp-large.png
new file mode 100755
index 0000000..87a5bb0
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/webapp/images/webapp-large.png
Binary files differ
diff --git a/0.8.1-rc1/grid/src/main/webapp/images/webapp-small.png b/0.8.1-rc1/grid/src/main/webapp/images/webapp-small.png
new file mode 100755
index 0000000..d0dd963
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/webapp/images/webapp-small.png
Binary files differ
diff --git a/0.8.1-rc1/grid/src/main/webapp/index.html b/0.8.1-rc1/grid/src/main/webapp/index.html
new file mode 100755
index 0000000..3d2f161
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/webapp/index.html
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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 XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
+  <head>
+    <title>Web Grid</title>
+    <link rel="stylesheet" type="text/css" href="style.css" />
+  </head>
+  <h1>Web Grid</h1>
+  <ul>
+    <li><a href='config.jsp'>Configure</a> the system</li>
+    <li><a href='http://oodt.jpl.nasa.gov/web-grid/'>Learn more</a> about OODT web-based grid technologies</li>
+  </ul>
+  <p>OODT is a product of the <a href="http://www.apache.org/">Apache Software Foundation</a>. Check out 
+  our <a href="http://oodt.apache.org/">web page</a> for more information.
+  </p>
+</html>
diff --git a/0.8.1-rc1/grid/src/main/webapp/style.css b/0.8.1-rc1/grid/src/main/webapp/style.css
new file mode 100755
index 0000000..d976f01
--- /dev/null
+++ b/0.8.1-rc1/grid/src/main/webapp/style.css
@@ -0,0 +1,161 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+*/
+body {
+        font-family: "Lucida Grande", Helvetica, sans;
+	background-color: white;
+	color: black;
+	margin: 2em;
+	padding: 0;
+	vertical-align: top;
+}
+
+h1 {
+        font-size: 160%;
+}
+
+h2 {
+        font-size: 150%;
+}
+
+h3 {
+        font-size: 140%;
+	border-bottom: none;
+	font-weight: bold;
+}
+
+fieldset {
+        border: 1 solid #336699;
+	margin: 1em 0em 1em 0em;
+	padding: 0em 1em 1em 1em;
+	line-height: 1.5em;
+	width: auto;
+}
+
+legend {
+        background: white;
+	padding: 0.5em;
+	font-size: 90%;
+}
+
+form {
+        border: none;
+	margin: 0;
+}
+
+textarea {
+        font: 110% "American Typewriter", Courier, monospace; 
+        border: 1 solid #369;
+	color: black;
+	background-color: white;
+	width: 100%;
+}
+
+input {
+        font-family: <dtml-var fontFamily>;
+	visibility: visible;
+	border: 1 solid #369;
+	color: black;
+	background-color: white;
+	vertical-align: middle;
+}
+
+select {
+        border: 1 solid #369;
+	color: black;
+	vertical-align: top;
+}
+
+.field {
+        top: 0;
+	left: 0;
+	margin: 0 1em 1em 0; 
+}
+
+.field .field {
+        margin: 1em 0 0 0;
+}
+
+.field label {
+        font-size: 100%;
+        font-weight: bold;
+}
+
+.fieldRequired {
+        background: url(required.gif) center left no-repeat;
+        padding: 0 0 0 8px;
+        color: black;
+} 
+
+.fieldHelp {
+        font-size: 90%;
+        color: #666;
+        margin: 0 0 0.2em 0;
+}
+
+.formHelp:hover {
+        color: black;
+	cursor: default;
+}
+
+.formControls {
+        margin: 1em 0 0 0; 
+}
+
+.error {
+        /* Class for error indication in forms */
+	color: #ff6633;
+	border: 1 solid #ff6633;
+	padding: 1em;
+	margin: 0 0 1em 0;
+	width: 68% !important;
+}
+
+.evenRow {
+        background: #eee;
+}
+
+.newRow {
+	border-top: solid;
+	border-width: 1;
+	background: #ffe;
+}
+
+th {
+        border-bottom: solid;
+	border-width: 1px;
+        vertical-align: top;
+}
+
+tr {
+        vertical-align: top;
+}
+
+td {
+        vertical-align: top;
+}
+
+tbody {
+        vertical-align: top;
+}
+
+table {
+        vertical-align: top;
+}
+
+caption {
+	font-size: 150%
+}
diff --git a/0.8.1-rc1/grid/src/site/resources/images/web-grid.jpg b/0.8.1-rc1/grid/src/site/resources/images/web-grid.jpg
new file mode 100755
index 0000000..015bb43
--- /dev/null
+++ b/0.8.1-rc1/grid/src/site/resources/images/web-grid.jpg
Binary files differ
diff --git a/0.8.1-rc1/grid/src/site/resources/images/web-grid.psd b/0.8.1-rc1/grid/src/site/resources/images/web-grid.psd
new file mode 100755
index 0000000..e9d898e
--- /dev/null
+++ b/0.8.1-rc1/grid/src/site/resources/images/web-grid.psd
Binary files differ
diff --git a/0.8.1-rc1/grid/src/site/resources/slides.pdf b/0.8.1-rc1/grid/src/site/resources/slides.pdf
new file mode 100755
index 0000000..82f64ce
--- /dev/null
+++ b/0.8.1-rc1/grid/src/site/resources/slides.pdf
Binary files differ
diff --git a/0.8.1-rc1/grid/src/site/site.xml b/0.8.1-rc1/grid/src/site/site.xml
new file mode 100644
index 0000000..1a85fa9
--- /dev/null
+++ b/0.8.1-rc1/grid/src/site/site.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<project name="Web Grid">
+
+  <body>
+    <links>
+      <item name="OODT" href="../oodt-site/"/>
+      <item name="Grid" href="../grid/"/>
+    </links>
+
+  <menu ref="reports" inherit="bottom"/>
+  
+  </body>
+
+</project>
diff --git a/0.8.1-rc1/grid/src/site/xdoc/index.xml b/0.8.1-rc1/grid/src/site/xdoc/index.xml
new file mode 100755
index 0000000..78e4ea7
--- /dev/null
+++ b/0.8.1-rc1/grid/src/site/xdoc/index.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!--

+Licensed to the Apache Software Foundation (ASF) under one or more contributor

+license agreements.  See the NOTICE.txt 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.

+-->

+<document>

+  <properties>

+    <title>Web Grid</title>

+    <author email='Sean.Kelly@jpl.nasa.gov'>Sean Kelly</author>

+  </properties>

+  <!-- Sirius Isness - Irrational Substance -->

+  <body>

+    <section name='Web Grid'>

+      <p>The OODT <a href='/grid/'>grid services</a>

+	(<a href='/grid-product/'>product</a>

+	and <a href='/grid-profile/'>profile</a> services) use CORBA

+	or RMI as their underlying network transport.  However,

+	limitations of CORBA and RMI make them inappropriate for

+	large-scale deployments.  For one, both are procedural

+	mechanisms, providing a remote interface that resembles a

+	method call.  This makes streaming of data from a service

+	impossible, because there are limitations to the sizes of data

+	structures that can be passed over a remote method call.

+	Instead, repeated calls must be made to retrieve each block of

+	a product, making transfer speeds horribly slow compared to

+	HTTP or FTP.  (Block-based retrieval of profiles was never

+	implemented, resulting in out of memory conditions for large

+	profile results, which is another problem.)

+      </p>

+      <p>Second, both CORBA and RMI rely on a central name registry.

+	The registry makes an object independent of its network

+	location, enabling a client to call it by name (looking up its

+	last known location in the registry).  However, this requires

+	that server objects be able to make outbound network calls to

+	the registry (through any outbound firewall), and that the

+	registry accept those registrations (through any inbound

+	firewall).  This required administrative action at

+	institutions hosting server objects and at the institution

+	hosting the registry.  Often, these firewall exceptions would

+	change without notice as system adminstrators changed at each

+	location (apparently firewall exceptions are poorly documented

+	everywhere).

+      </p>

+      <p>Further, in the two major deployments of OODT (PDS and EDRN),

+	server objects have almost never moved, nullifying any benefit

+	of the registry.  This project, OODT Web Grid, avoids the

+	prolems of CORBA and RMI by using HTTP as the transport

+	mechanism for products and profiles.  Further, it provides a

+	password-protected mechanism to add new sets of product and

+	profile query handlers, enabling seamless activation of

+	additional capabilities.

+      </p>

+    </section>

+    <section name='Documentation'>

+      <p>Further documentation on Web Grid is forthcoming.  In the

+	mean time, check out these <a href='./slides.pdf'>presentation

+	slides</a>.  (Don't worry, they're not in PowerPoint format.)

+      </p>

+    </section>

+  </body>

+</document>

diff --git a/0.8.1-rc1/grid/src/test/org/apache/oodt/grid/ConfigurationTest.java b/0.8.1-rc1/grid/src/test/org/apache/oodt/grid/ConfigurationTest.java
new file mode 100755
index 0000000..e54281b
--- /dev/null
+++ b/0.8.1-rc1/grid/src/test/org/apache/oodt/grid/ConfigurationTest.java
@@ -0,0 +1,180 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.grid;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Arrays;
+import junit.framework.TestCase;
+import org.xml.sax.SAXException;
+
+/**
+ * Test the {@link Configuration} class.
+ * 
+ */
+public class ConfigurationTest extends TestCase {
+  /**
+   * Creates a new <code>ConfigurationTest</code> instance.
+   * 
+   * @param caseName
+   *          Test case name.
+   */
+  public ConfigurationTest(String caseName) {
+    super(caseName);
+  }
+
+  /**
+   * Set up by creating a temporary config file.
+   * 
+   * @throws Exception
+   *           if an error occurs.
+   */
+  public void setUp() throws Exception {
+    super.setUp();
+    System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
+        "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
+    System.setProperty("javax.xml.parsers.SAXParserFactory",
+        "org.apache.xerces.jaxp.SAXParserFactoryImpl");
+    System.setProperty("javax.xml.transform.TransformerFactory",
+        "org.apache.xalan.processor.TransformerFactoryImpl");
+    configFile = File.createTempFile("config", ".xml");
+    configFile.deleteOnExit();
+  }
+
+  /**
+   * Tear down by deleting the temporary config file.
+   * 
+   * @throws Exception
+   *           if an error occurs.
+   */
+  public void tearDown() throws Exception {
+    configFile.delete();
+    super.tearDown();
+  }
+
+  /**
+   * Test to see if the default values of the {@link Configuration} are
+   * reasonable.
+   * 
+   * @throws IOException
+   *           if an error occurs.
+   * @throws SAXException
+   *           if an error occurs.
+   */
+  public void testDefaults() throws IOException, SAXException {
+    Configuration config = new Configuration(configFile);
+    assertTrue("Expect localhost not required by default", !config
+        .isLocalhostRequired());
+    assertTrue("Expect https not required by default", !config
+        .isHTTPSrequired());
+    assertTrue("Expect no product servers by default", config
+        .getProductServers().isEmpty());
+    assertTrue("Expect no profile servers by default", config
+        .getProfileServers().isEmpty());
+    assertTrue("Default password not set", Arrays.equals(
+        Configuration.DEFAULT_PASSWORD, config.getPassword()));
+    assertTrue("Expect no properties", config.getProperties().isEmpty());
+    assertTrue("Expect no code bases", config.getCodeBases().isEmpty());
+  }
+
+  /**
+   * Test to see if the mutators work.
+   * 
+   * @throws IOException
+   *           if an error occurs.
+   * @throws SAXException
+   *           if an error occurs.
+   */
+  public void testMutators() throws IOException, SAXException {
+    Configuration config = new Configuration(configFile);
+
+    assertTrue(!config.isHTTPSrequired());
+    config.setHTTPSrequired(true);
+    assertTrue("Cannot set https as required", config.isHTTPSrequired());
+
+    assertTrue(!config.isLocalhostRequired());
+    config.setLocalhostRequired(true);
+    assertTrue("Cannot set localhost as required", config.isLocalhostRequired());
+
+    byte[] password = { (byte) 'x', (byte) 'y', (byte) 'z' };
+    assertTrue(Arrays.equals(Configuration.DEFAULT_PASSWORD, config
+        .getPassword()));
+    config.setPassword(password);
+    assertTrue("Cannot change password", Arrays.equals(password, config
+        .getPassword()));
+
+    try {
+      config.setPassword(null);
+      fail("Null password allowed");
+    } catch (IllegalArgumentException good) {
+    }
+
+    // Profile/product servers in the config have no mutators to test (they
+    // return references to each Set). Same with Properties and code bases.
+  }
+
+  /**
+   * Test to see if XML serialization works.
+   * 
+   * @throws IOException
+   *           if an error occurs.
+   * @throws SAXException
+   *           if an error occurs.
+   */
+  public void testSerialization() throws IOException, SAXException {
+    Configuration a = new Configuration(configFile);
+
+    byte[] password = { (byte) 'x', (byte) 'y', (byte) 'z' };
+    URL prodServerURL = new URL("http://localhost/prod.jar");
+    URL profServerURL = new URL("http://localhost/prof.jar");
+    ProductServer prod = new ProductServer(a, "prod");
+    ProfileServer prof = new ProfileServer(a, "prof");
+
+    a.setLocalhostRequired(true);
+    a.setHTTPSrequired(true);
+    a.setPassword(password);
+    a.getProductServers().add(prod);
+    a.getProfileServers().add(prof);
+    a.getProperties().setProperty("a", "b");
+    a.getCodeBases().add(prodServerURL);
+    a.getCodeBases().add(profServerURL);
+    a.save();
+
+    Configuration b = new Configuration(configFile);
+    assertTrue("localhost state not saved", b.isLocalhostRequired());
+    assertTrue("https state not saved", b.isHTTPSrequired());
+    assertTrue("Password not saved", Arrays.equals(password, b.getPassword()));
+    assertEquals("Product server not saved", 1, b.getProductServers().size());
+    assertEquals("Product server not saved properly", prod, b
+        .getProductServers().iterator().next());
+    assertEquals("Profile server not saved", 1, b.getProfileServers().size());
+    assertEquals("Profile server not saved properly", prof, b
+        .getProfileServers().iterator().next());
+    assertEquals("Properties not saved properly", "b", b.getProperties()
+        .getProperty("a"));
+    assertEquals("Code bases not saved properly", 2, b.getCodeBases().size());
+    assertTrue(b.getCodeBases().contains(prodServerURL));
+    assertTrue(b.getCodeBases().contains(profServerURL));
+
+    assertEquals("Configuration.equals doesn't work", a, b);
+  }
+
+  /** Test config file. */
+  private File configFile;
+}
diff --git a/0.8.1-rc1/grid/web-grid.iml b/0.8.1-rc1/grid/web-grid.iml
new file mode 100644
index 0000000..95c93b5
--- /dev/null
+++ b/0.8.1-rc1/grid/web-grid.iml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
+    <output url="file://$MODULE_DIR$/target/classes" />
+    <output-test url="file://$MODULE_DIR$/target/test-classes" />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/target" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="oodt-commons" />
+    <orderEntry type="library" name="Maven: commons-dbcp:commons-dbcp:1.2.1" level="project" />
+    <orderEntry type="library" name="Maven: commons-collections:commons-collections:2.1" level="project" />
+    <orderEntry type="library" name="Maven: commons-pool:commons-pool:1.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-lang:commons-lang:2.3" level="project" />
+    <orderEntry type="library" name="Maven: commons-logging:commons-logging:1.0.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-core:2.5.4" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-hibernate3:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: aopalliance:aopalliance:1.0" level="project" />
+    <orderEntry type="library" name="Maven: org.hibernate:hibernate:3.2.5.ga" level="project" />
+    <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache:1.2.3" level="project" />
+    <orderEntry type="library" name="Maven: asm:asm-attrs:1.5.3" level="project" />
+    <orderEntry type="library" name="Maven: dom4j:dom4j:1.6.1" level="project" />
+    <orderEntry type="library" name="Maven: antlr:antlr:2.7.6" level="project" />
+    <orderEntry type="library" name="Maven: cglib:cglib:2.1_3" level="project" />
+    <orderEntry type="library" name="Maven: asm:asm:1.5.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-beans:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-context:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-dao:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: xmlrpc:xmlrpc:2.0.1" level="project" />
+    <orderEntry type="module" module-name="oodt-profile" />
+    <orderEntry type="module" module-name="cas-filemgr" />
+    <orderEntry type="module" module-name="cas-metadata" />
+    <orderEntry type="module" module-name="pcs-input" />
+    <orderEntry type="module" module-name="cas-cli" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-expression:3.0.5.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: com.google.guava:guava:10.0.1" level="project" />
+    <orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
+    <orderEntry type="library" name="Maven: commons-cli:commons-cli:1.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.solr:solr-solrj:1.3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.solr:solr-common:1.3.0" level="project" />
+    <orderEntry type="library" name="Maven: commons-fileupload:commons-fileupload:1.2" level="project" />
+    <orderEntry type="library" name="Maven: stax:stax:1.2.0" level="project" />
+    <orderEntry type="library" name="Maven: stax:stax-api:1.0.1" level="project" />
+    <orderEntry type="library" name="Maven: net.java.dev.stax-utils:stax-utils:20040917" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.solr:solr-core:1.3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.solr:solr-lucene-analyzers:1.3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.solr:solr-lucene-highlighter:1.3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.solr:solr-lucene-queries:1.3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.solr:solr-lucene-snowball:1.3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.solr:solr-lucene-spellchecker:1.3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.solr:solr-commons-csv:1.3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.geronimo.specs:geronimo-stax-api_1.0_spec:1.0.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-core:2.0.0" level="project" />
+    <orderEntry type="library" name="Maven: org.safehaus.jug:jug:asl:2.0.0" level="project" />
+    <orderEntry type="library" name="Maven: hsqldb:hsqldb:1.8.0.7" level="project" />
+    <orderEntry type="library" scope="RUNTIME" name="Maven: org.python:jython:2.2-beta1" level="project" />
+    <orderEntry type="library" name="Maven: com.amazonaws:aws-java-sdk:1.7.4" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.2" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.1.1" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.1.1" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.1" level="project" />
+    <orderEntry type="library" name="Maven: joda-time:joda-time:2.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ibm.icu:icu4j:3.4.4" level="project" />
+    <orderEntry type="library" name="Maven: commons-httpclient:commons-httpclient:3.0-alpha1" level="project" />
+    <orderEntry type="library" name="Maven: commons-codec:commons-codec:1.3" level="project" />
+    <orderEntry type="module" module-name="oodt-product" />
+    <orderEntry type="library" name="Maven: commons-io:commons-io:1.4" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.tika:tika-core:1.7" level="project" />
+    <orderEntry type="module" module-name="oodt-xmlquery" />
+    <orderEntry type="library" name="Maven: com.hp.hpl.jena:jena:2.6.3" level="project" />
+    <orderEntry type="library" name="Maven: com.hp.hpl.jena:iri:0.8" level="project" />
+    <orderEntry type="library" name="Maven: com.hp.hpl.jena:iri:sources:0.8" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.5.8" level="project" />
+    <orderEntry type="library" scope="RUNTIME" name="Maven: org.slf4j:slf4j-log4j12:1.5.8" level="project" />
+    <orderEntry type="library" name="Maven: log4j:log4j:1.2.13" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: javax.servlet:servlet-api:2.4" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: junit:junit:3.8.2" level="project" />
+    <orderEntry type="library" name="Maven: xerces:xercesImpl:2.9.1" level="project" />
+    <orderEntry type="library" name="Maven: xml-apis:xml-apis:1.3.04" level="project" />
+    <orderEntry type="library" name="Maven: xalan:xalan:2.7.1" level="project" />
+    <orderEntry type="library" name="Maven: xalan:serializer:2.7.1" level="project" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/0.8.1-rc1/metadata/pom.xml b/0.8.1-rc1/metadata/pom.xml
new file mode 100644
index 0000000..df5b81b
--- /dev/null
+++ b/0.8.1-rc1/metadata/pom.xml
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>cas-metadata</artifactId>
+  <name>Catalog and Archive Service Generic Multi-valued Metadata Container</name>
+  <description>A Multi-valued, generic Metadata container class. The class uses an internal
+	Map of string keys pointing to vectors of strings. The data
+	structure looks like the following:
+
+	[std:string key]⇒std:vector of std:strings
+
+	The multi-valued nature of the class is handled transparently by this Metadata
+	container. Since all values are stored internally as string vectors, the difference
+	between a scalar value and a non-scalar is handled by determining whether the list of
+	values for a particular key is greater than 1.</description>
+  <scm>
+   	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/metadata</connection>
+   	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/metadata</developerConnection>
+   	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/metadata</url>
+  </scm>
+  <build>
+    <resources>
+      <resource>
+        <targetPath>org/apache/oodt/cas/metadata/util</targetPath>
+        <directory>${basedir}/src/main/resources</directory>
+        <includes>
+          <include>tika-mimetypes.xml</include>
+        </includes>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>2.8.1</version>
+        <configuration>
+          <redirectTestOutputToFile>true</redirectTestOutputToFile>
+
+        <systemProperties>
+           <property>
+              <name>java.io.tmpdir</name>
+              <value>${project.build.outputDirectory}</value>
+           </property>
+           <property>
+             <name>java.util.logging.config.file</name>
+             <value>${basedir}/src/main/resources/logging.properties</value>
+            </property>
+         </systemProperties>
+         <forkMode>never</forkMode>
+          <includes>
+            <include>**/*Test*.java</include>
+          </includes>
+          <excludes>
+            <exclude>org/apache/oodt/cas/metadata/MetadataTestCase.java</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>audit</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>rat-maven-plugin</artifactId>
+            <configuration>
+              <excludes>
+                <exclude>**/testdata/*</exclude>
+                <exclude>**/resources/examples/*</exclude>
+              </excludes>
+            </configuration>
+            <executions>
+              <execution>
+                <phase>verify</phase>
+                <goals>
+                  <goal>check</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-commons</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>pcs-input</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <version>2.3</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.0.3</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <version>1.3</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tika</groupId>
+      <artifactId>tika-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-core</artifactId>
+      <version>2.5.4</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-hibernate3</artifactId>
+      <version>2.0.8</version>
+      <exclusions>
+        <exclusion>
+          <groupId>javax.transaction</groupId>
+          <artifactId>jta</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>10.0.1</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.8.1</version>
+      <scope>test</scope>
+    </dependency>
+	<dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <version>1.9.5</version>
+      <scope>test</scope>
+	</dependency>
+	<dependency>
+	  <groupId>org.hamcrest</groupId>
+	  <artifactId>hamcrest-all</artifactId>
+	  <version>1.3</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/metadata/src/main/conf/cas.metadata.dtd b/0.8.1-rc1/metadata/src/main/conf/cas.metadata.dtd
new file mode 100644
index 0000000..0ea80a3
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/conf/cas.metadata.dtd
@@ -0,0 +1,36 @@
+<!--
+  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.
+-->
+<!--
+ A Multi-valued, generic Metadata container schema. The class uses a map of
+ string keys pointing to vectors of strings. The data structure looks like
+ the following:
+
+ [std:string key]=><std:vector of std:strings>
+
+ The multi-valued nature of the class is handled transparently by this Metadata
+ container. Since all values are stored internally as string vectors, the difference
+ between a scalar value and a non-scalar is handled by determing whether the list of
+ values for a particular key is greater than 1. 
+-->
+
+<!ELEMENT metadata (keyval)*>
+
+<!ELEMENT keyval (key, val+)>
+
+<!ELEMENT key (#PCDATA)>
+
+<!ELEMENT val (#PCDATA)>
diff --git a/0.8.1-rc1/metadata/src/main/conf/cas.metadata.xsd b/0.8.1-rc1/metadata/src/main/conf/cas.metadata.xsd
new file mode 100644
index 0000000..bd0a859
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/conf/cas.metadata.xsd
@@ -0,0 +1,46 @@
+<?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.

+-->

+<!--

+ A Multi-valued, generic Metadata container schema. The class uses a map of 

+ string keys pointing to vectors of strings. The data structure looks like 

+ the following: 

+

+ [std:string key]=><std:vector of std:strings>

+

+ The multi-valued nature of the class is handled transparently by this Metadata

+ container. Since all values are stored internally as string vectors, the difference

+ between a scalar value and a non-scalar is handled by determing whether the list of

+ values for a particular key is greater than 1. 

+-->

+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">

+	<xs:element name="key" type="xs:string"/>

+	<xs:complexType name="keyvalType">

+		<xs:sequence>

+			<xs:element ref="key"/>

+			<xs:element ref="val" maxOccurs="unbounded"/>

+		</xs:sequence>

+	</xs:complexType>

+	<xs:element name="metadata">

+		<xs:complexType>

+			<xs:sequence minOccurs="0" maxOccurs="unbounded">

+				<xs:element name="keyval" type="keyvalType"/>

+			</xs:sequence>

+		</xs:complexType>

+	</xs:element>

+	<xs:element name="val" type="xs:string"/>

+</xs:schema>

diff --git a/0.8.1-rc1/metadata/src/main/cpp/Makefile b/0.8.1-rc1/metadata/src/main/cpp/Makefile
new file mode 100644
index 0000000..b01b461
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/cpp/Makefile
@@ -0,0 +1,34 @@
+#  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.
+
+# make the Metadata library
+#
+CFLAGS= -g -Wall
+CC=gcc
+LIBRARIES = -lxerces-c -lstdc++
+INCLUDES = -I/usr/include/xercesc/
+
+all:    metadata.o
+
+# clean out the dross
+clean:
+		rm *.o test
+        
+metadata.o: Metadata.h XStr.h
+		$(CC) -c Metadata.cpp $(INCLUDES)
+
+test: metadata.o
+		$(CC) -g metadata.o testMetadata.cpp $(LIBRARIES) -o test
+		
diff --git a/0.8.1-rc1/metadata/src/main/cpp/Metadata.cpp b/0.8.1-rc1/metadata/src/main/cpp/Metadata.cpp
new file mode 100644
index 0000000..753b819
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/cpp/Metadata.cpp
@@ -0,0 +1,302 @@
+/*
+  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.
+*/
+
+#ifndef METADATA_CPP_
+#define METADATA_CPP_
+
+#include "Metadata.h"
+#include "XStr.h"
+#include <vector>
+#include <map>
+#include <string>
+#include <iostream>
+#include <xercesc/dom/DOM.hpp>
+#include<xercesc/dom/DOMDocument.hpp>
+#include<xercesc/dom/DOMElement.hpp>
+#include<xercesc/dom/DOMNodeList.hpp>
+#include <xercesc/util/PlatformUtils.hpp>
+#include <xercesc/util/XMLString.hpp>
+#include <xercesc/framework/StdOutFormatTarget.hpp>
+#include <xercesc/util/OutOfMemoryException.hpp>
+#ifdef XERCES_CPP_NAMESPACE_USE
+XERCES_CPP_NAMESPACE_USE
+#endif
+
+#define X(str) XStr(str).unicodeForm()
+
+//STD imports
+using namespace std;
+
+namespace cas
+{
+
+/**********************************************************************
+Implementation of the Metadata container methods.
+***********************************************************************/
+	
+vector<string> Metadata::EMPTY_VEC(0);
+string Metadata::EMPTY_STR;
+
+Metadata::Metadata()
+{
+	
+}
+
+Metadata::Metadata(DOMDocument *doc)
+{
+   DOMElement *metadataRootElem = doc->getDocumentElement();
+   
+   if(metadataRootElem == NULL){
+   	return;
+   }
+   
+   XMLCh *keyValStr = XMLString::transcode("keyval");
+   DOMNodeList *keyValElems = metadataRootElem->getElementsByTagName(keyValStr);
+   
+   const XMLSize_t nodeCount = keyValElems->getLength();
+   
+   //cout << "Metadata::constructor:  Found " << nodeCount << " keyval elements" << endl;
+   
+   for(XMLSize_t i = 0; i < nodeCount; i++){
+     DOMNode* currentNode = keyValElems->item(i) ;
+        
+     if(currentNode == NULL){
+       	  continue;
+     }
+     	
+     if( xercesc::DOMNode::ELEMENT_NODE != currentNode->getNodeType() ){
+       // not an element node -> not of interest here
+        continue ;
+     }
+
+     DOMElement* metadataElem = dynamic_cast< xercesc::DOMElement* >(currentNode);
+
+     
+     string key;
+     read(metadataElem, "key", key);
+     vector<string> values;
+     readMany(metadataElem, "val", values);
+     
+     /*cout << "Processing DOMElement (key, values): (" << key << ", ";
+     
+     for(int j=0; j < values.size(); j++){
+     	cout << values[j] << ", ";
+     }
+     
+     cout << ")" << endl;*/
+     
+     elementMap[key] = values;
+        	
+   }	
+}
+
+Metadata::~Metadata()
+{
+}
+
+
+void Metadata::read(DOMElement *elem, const string& key, string& value){
+	XMLCh *tagName = XMLString::transcode(key.c_str());
+	DOMNodeList *valueNodes = elem->getElementsByTagName(tagName);
+	
+	DOMNode* valElem = valueNodes->item(0);
+	value = getSimpleNodeText(valElem);
+}
+ 
+
+void Metadata::readMany(DOMElement *elem, const string& key, vector<string>& values){
+	XMLCh *tagName = XMLString::transcode(key.c_str());
+	DOMNodeList *valueNodes = elem->getElementsByTagName(tagName);
+	
+    for(int i=0; i < valueNodes->getLength(); i++){
+    	  DOMNode *valElem = valueNodes->item(i);
+    	  string value = getSimpleNodeText(valElem);
+    	  values.push_back(value);
+    }
+}
+
+bool Metadata::containsKey(const string& key) const{
+	return elementMap.find(key) != elementMap.end();
+}
+
+bool Metadata::isMultiValued(const string& key){
+    if(elementMap.find(key) != elementMap.end()){
+    	vector<string>& values = elementMap[key];
+    	return values.size() > 1;
+    }
+    else return false;
+}
+
+void Metadata::addMetadata(const string& key, const string& value){
+	if(elementMap.find(key) != elementMap.end()){	
+		vector<string>& values = elementMap[key];
+		values.push_back(value);
+	}
+	else{
+		vector<string> values;
+		values.push_back(value);
+		elementMap[key] = values;
+	}
+}
+
+void Metadata::addMetadata(const string& key, const vector<string>& values){
+	if(elementMap.find(key) != elementMap.end()){
+		vector<string>& existingValues = elementMap[key];
+		
+         for(int i=0; i < values.size(); i++){
+         	existingValues.push_back(values[i]);
+         }
+	}
+	else{
+		elementMap[key] = values;
+	}
+}
+
+void Metadata::removeMetadata(const string& key){
+	if(elementMap.find(key) != elementMap.end()){
+		elementMap.erase(key);
+	}
+}
+
+void Metadata::replaceMetadata(const string& key, const string& value){
+	removeMetadata(key);
+	vector<string> values;
+	values.push_back(value);
+	elementMap[key] = values;
+}
+		
+void Metadata::replaceMetadata(const string& key, const vector<string>& values){
+	removeMetadata(key);
+	elementMap[key] = values;
+}
+	
+const string& Metadata::getMetadata(const string& key){
+	if(elementMap.find(key) != elementMap.end()){
+		return (elementMap[key])[0];
+	}
+	else return EMPTY_STR;
+}
+
+const vector<string>& Metadata::getAllMetadata(const string& key){
+    if(elementMap.find(key) != elementMap.end()){
+    	    return elementMap[key];
+    }
+    else return EMPTY_VEC;
+    		
+}
+
+string Metadata::getSimpleNodeText(DOMNode* node){
+    string nodeTxt = "";
+    DOMNodeList *children = node->getChildNodes();
+    for(int i=0; i < children->getLength(); i++){
+      DOMNode *n = children->item(i);
+      if(n->getNodeType() == DOMNode::TEXT_NODE){
+         const XMLCh *xmlText = n->getNodeValue();
+         nodeTxt+=XMLString::transcode(xmlText);
+      }    
+    }
+
+   return nodeTxt;
+}
+
+DOMDocument* Metadata::toXML(void){
+    // Initialize the XML4C2 system.
+    try
+    {
+        XMLPlatformUtils::Initialize();
+    }
+
+    catch(const XMLException& toCatch)
+    {
+        char *pMsg = XMLString::transcode(toCatch.getMessage());
+        XERCES_STD_QUALIFIER cerr << "Error during Xerces-c Initialization.\n"
+             << "  Exception message:"
+             << pMsg;
+        XMLString::release(&pMsg);
+        return NULL;
+    }
+
+
+   {
+       DOMImplementation* impl =  DOMImplementationRegistry::getDOMImplementation(X("Core"));
+
+       if (impl != NULL)
+       {
+           try
+           {
+               DOMDocument* doc = impl->createDocument(
+                           // FIXME: change namespace URI?
+                           X("http://oodt.jpl.nasa.gov/1.0/cas"),                    // root element namespace URI.
+                           X("cas:metadata"),         // root element name
+                           NULL/*pDoctype*/);                   // document type object (DTD).
+
+               DOMElement* rootElem = doc->getDocumentElement();
+
+              for(map<string, vector<string> >::iterator i = elementMap.begin(); i != elementMap.end(); i++){
+              	DOMElement* metaElem = doc->createElement(X("keyval"));
+              	rootElem->appendChild(metaElem);
+              	
+              	DOMElement* keyElem = doc->createElement(X("key"));
+              	metaElem->appendChild(keyElem);
+              	
+              	DOMText* keyTextElem = doc->createTextNode(X(i->first));
+              	keyElem->appendChild(keyTextElem);
+              	
+              	if(i->second.size() > 1){
+              		metaElem->setAttribute(X("type"), X("vector"));
+              	}
+              	else{
+              		metaElem->setAttribute(X("type"), X("scalar"));
+              	}
+              	
+              	for(int j=0; j < i->second.size(); j++){
+              		DOMElement* valueElem = doc->createElement(X("val"));
+              	    DOMText* valTextElem = doc->createTextNode(X(i->second[j]));
+              	    valueElem->appendChild(valTextElem);
+                    metaElem->appendChild(valueElem);
+              	}
+              	
+              }
+
+               return doc;
+           }
+           catch (const OutOfMemoryException&)
+           {
+               XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
+           }
+           catch (const DOMException& e)
+           {
+               XERCES_STD_QUALIFIER cerr << "DOMException code is:  " << e.code << XERCES_STD_QUALIFIER endl;
+           }
+           catch (...)
+           {
+               XERCES_STD_QUALIFIER cerr << "An error occurred creating the document" << XERCES_STD_QUALIFIER endl;
+           }
+       }
+       else
+       {
+           XERCES_STD_QUALIFIER cerr << "Requested implementation is not supported" << XERCES_STD_QUALIFIER endl;
+       }
+   }
+
+   XMLPlatformUtils::Terminate();
+   return NULL;
+}
+
+}
+
+#endif /*METADATA_CPP_*/
diff --git a/0.8.1-rc1/metadata/src/main/cpp/Metadata.h b/0.8.1-rc1/metadata/src/main/cpp/Metadata.h
new file mode 100644
index 0000000..63c5fe5
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/cpp/Metadata.h
@@ -0,0 +1,178 @@
+/*
+  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.
+*/
+
+#ifndef METADATA_H_
+#define METADATA_H_
+
+#include <vector>
+#include <map>
+#include <string>
+#include <xercesc/dom/DOM.hpp>
+#ifdef XERCES_CPP_NAMESPACE_USE
+XERCES_CPP_NAMESPACE_USE
+#endif
+
+//STD imports
+using namespace std;
+
+namespace cas
+{
+
+/**********************************************************************
+A Multi-valued, generic Metadata container class. The class uses an internal
+STL map of STL string keys pointing to STL vectors of STL strings. The data 
+structure looks like the following: 
+
+[std:string key]=><std:vector of std:strings>
+
+The multi-valued nature of the class is handled transparently by this Metadata
+container. Since all values are stored internally as string vectors, the difference
+between a scalar value and a non-scalar is handled by determing whether the list of
+values for a particular key is greater than 1. 
+
+The class relies on <a href="http://xml.apache.org/xerces-c/">Apache's xerces-c 
+implementation</a> for outputting and reading in a Metadata container.
+***********************************************************************/
+class Metadata
+{
+public:
+    /**
+     * Constructs a new Metadata container object
+     */
+	Metadata();
+	
+	/**
+	 * Construct a new Metadata container object from an existing DOM stream.
+	 * This method is helpful when you have an external Metadata XML file that needs
+	 * to be read into a manipulateable object in memory.
+	 * 
+	 * @param doc The DOM document to parse and turn into a Metadata container object.
+	 */
+	Metadata(DOMDocument *doc);
+	
+	/**
+	 * Default Destructor, deletes the internal map.
+	 */
+	virtual ~Metadata();
+	
+	/**
+	 * Adds a single string value for the specified <code>key</code>.
+	 * 
+	 * @param key The key to add the string value for.
+	 * @param value The string value to add to the specified key.
+	 */
+	void addMetadata(const string& key, const string& value);
+	
+	/**
+	 * Adds a vector of string values (in order) for the specified <code>key</code>.
+	 * 
+	 * @param key The key to add the string value for.
+	 * @param values The vector of string values to append to the key's value list.
+	 */
+	void addMetadata(const string& key, const vector<string>& values);
+	
+	/**
+	 * Gets the first metadata value for the given <code>key</code>.
+	 * 
+	 * @param key The key to obtain the first string metadata value for.
+	 * @return The first metadata value for the specified key.
+	 */
+	const string& getMetadata(const string& key);
+	
+	/**
+	 * Gets All the metadata values for the given <code>key</code>, in order.
+	 * 
+	 * @param key The key to obtain all metadata values for.
+	 * @return an STL vector of STL strings, corresponding to all the values for a particular
+	 * metadata key.
+	 */
+	const vector<string>& getAllMetadata(const string& key);
+	
+	/**
+	 * Returns true if the specified <code>key</code> exists in the Metadata container, 
+	 * false otherwise.
+	 * 
+	 * @param key The key to check for existance of.
+	 * @return true if the key exists, false otherwise.
+	 */
+	bool containsKey(const string& key) const;
+	
+	/**
+	 * Returns true if the specified <code>key</code> has > 1 values in the Metadata
+	 * container, false otherwise.
+	 * 
+	 * @param key The key to check for > 1 values for.
+	 * @return True if there are > 1 values, false otherwise.
+	 */
+	bool isMultiValued(const string& key);
+	
+	/**
+	 * Removes the values, along with the existance of the specified
+	 * <code>key</code> within the Metadata container.
+	 * 
+	 * @param key The key to remove the values and the existance of.
+	 */
+	void removeMetadata(const string& key);
+	
+	/**
+	 * Replaces the values for the specified <code>key</code>, with the
+	 * scalar string <code>value</code> parameter.
+	 * 
+	 * @param key The key to replace the values for.
+	 * @param value The scalar string value to attach to the specified key.
+	 */
+	void replaceMetadata(const string& key, const string& value);
+	
+	/**
+	 * Replaces the values for the specified <code>key</code>, with the
+	 * vector of string <code>values</code> parameter.
+	 * 
+	 * @param key The key to replace the values for.
+	 * @param value The vector of string values to attach to the specified key.
+	 */
+	void replaceMetadata(const string& key, const vector<string>& values);
+	
+	/**
+	 * Serializes the Metadata container into a Xerces DOM document. Returns
+	 * a pointer to the DOMDocument, which can be used for serialization into
+	 * a file, or STDOUT/etc.
+	 * 
+	 * @return a Xerces DOM document (XML) representation of the Metadata container.
+	 */
+	DOMDocument* toXML(void); 
+	
+	// the default return value for methods that must return a vector: this
+	// vector is size 0, with no elements
+    static vector<string> EMPTY_VEC;
+    
+    // the default return value for methods that must return an stl string
+    static string EMPTY_STR;
+	
+
+private:
+    map<string, vector<string> > elementMap;
+    
+    void read(DOMElement *elem, const string& key, string& value);
+    void readMany(DOMElement *elem, const string& key, vector<string>& values);
+    string getSimpleNodeText(DOMNode *node);
+    
+};
+
+}
+
+#endif /*METADATA_H_*/
+
diff --git a/0.8.1-rc1/metadata/src/main/cpp/XStr.h b/0.8.1-rc1/metadata/src/main/cpp/XStr.h
new file mode 100644
index 0000000..628d2e4
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/cpp/XStr.h
@@ -0,0 +1,67 @@
+/*

+  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.

+*/

+

+#ifndef _XSTR_H_

+#define _XSTR_H_

+

+// ---------------------------------------------------------------------------

+//  This is a simple class that lets us do easy (though not terribly efficient)

+//  trancoding of char* data to XMLCh data.

+//  

+//  This class was taken from Apache's xerces-c samples.

+// ---------------------------------------------------------------------------

+class XStr

+{

+public :

+    // -----------------------------------------------------------------------

+    //  Constructors and Destructor

+    // -----------------------------------------------------------------------

+    XStr(const char* const toTranscode)

+    {

+        // Call the private transcoding method

+        fUnicodeForm = XMLString::transcode(toTranscode);

+    }

+    

+    XStr(const string& toTranscode){

+        fUnicodeForm = XMLString::transcode(toTranscode.c_str());	

+    }

+

+    ~XStr()

+    {

+        XMLString::release(&fUnicodeForm);

+    }

+

+

+    // -----------------------------------------------------------------------

+    //  Getter methods

+    // -----------------------------------------------------------------------

+    const XMLCh* unicodeForm() const

+    {

+        return fUnicodeForm;

+    }

+

+private :

+    // -----------------------------------------------------------------------

+    //  Private data members

+    //

+    //  fUnicodeForm

+    //      This is the Unicode XMLCh format of the string.

+    // -----------------------------------------------------------------------

+    XMLCh*   fUnicodeForm;

+};

+

+#endif //_XSTR_H_

diff --git a/0.8.1-rc1/metadata/src/main/cpp/data/sample.met.xml b/0.8.1-rc1/metadata/src/main/cpp/data/sample.met.xml
new file mode 100644
index 0000000..588984a
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/cpp/data/sample.met.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<!--
+  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.
+-->
+<!-- FIXME: change namespace URI? -->
+<cas:metadata xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+
+  <keyval type="scalar">
+    <key>key1</key>
+    <val>val1</val>
+  </keyval>
+
+  <keyval type="vector">
+    <key>key2</key>
+    <val>val1</val>
+    <val>val2</val>
+    <val>val3</val>
+  </keyval>
+
+  <keyval type="scalar">
+    <key>key3</key>
+    <val>val3</val>
+  </keyval>
+
+  <keyval type="vector">
+    <key>key5</key>
+    <val>key5_replaced_val1</val>
+    <val>key5_replaced_val2</val>
+  </keyval>
+
+  <keyval type="scalar">
+    <key>key6</key>
+    <val>key6_replaced_val1</val>
+  </keyval>
+
+</cas:metadata>
diff --git a/0.8.1-rc1/metadata/src/main/cpp/testMetadata.cpp b/0.8.1-rc1/metadata/src/main/cpp/testMetadata.cpp
new file mode 100644
index 0000000..035ea40
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/cpp/testMetadata.cpp
@@ -0,0 +1,183 @@
+/*
+  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.
+*/
+
+#include "Metadata.h"
+#include <string>
+#include <vector>
+#include <iostream> 
+#include <xercesc/dom/DOM.hpp>
+#include <xercesc/dom/DOMImplementation.hpp>
+#include <xercesc/dom/DOMImplementationLS.hpp>
+#include <xercesc/framework/StdOutFormatTarget.hpp>
+#include<xercesc/parsers/XercesDOMParser.hpp>
+
+#ifdef XERCES_CPP_NAMESPACE_USE
+XERCES_CPP_NAMESPACE_USE
+#endif
+
+//STD imports
+using namespace std;
+
+//CAS imports
+using namespace cas;
+
+/**********************************************************************
+Pseudo-unit tests for the Metadata container.
+***********************************************************************/
+
+int main(void){
+	
+	Metadata metadata;
+	
+	metadata.addMetadata("key1", "val1");
+	
+	vector<string> values;
+	
+	values.push_back("val1");
+	values.push_back("val2");
+	values.push_back("val3");
+	
+	metadata.addMetadata("key2", values);
+	
+	cout << "Checking the value of key1: Value: " << metadata.getMetadata("key1") << endl;
+	cout << "Checking the value of key2: Value: " << metadata.getMetadata("key2") << endl;
+
+	vector<string> key2Vals = metadata.getAllMetadata("key2");
+	cout << "Checking all values for key2: Values: " << endl;
+		
+	for(int i=0; i < key2Vals.size(); i++){
+		 cout << "Value: " << key2Vals[i] << endl;
+	}
+		
+    if(metadata.getAllMetadata("key3") == cas::Metadata::EMPTY_VEC){
+    	   cout << "No multiple values for key3!" << endl;
+    }
+    
+    if(metadata.getMetadata("key3") == cas::Metadata::EMPTY_STR){
+    	cout << "No singular value for key3!" << endl;
+    }
+	
+	metadata.addMetadata("key3", "val3");
+	
+	if(metadata.getMetadata("key3") != cas::Metadata::EMPTY_STR){
+		cout << "New value for key3: " << metadata.getMetadata("key3") << endl;
+	}
+	
+	if(!metadata.containsKey("blah")){
+		cout << "Metadata doesn't contain key blah: correct!" << endl;
+	}
+	
+	if(metadata.containsKey("key3")){
+		cout << "Metadata contains key key3: correct!" << endl;
+	}
+	
+	if(metadata.isMultiValued("key2")){
+		cout << "Key2 is correctly multi-valued: correct!" << endl;
+	}
+	
+	if(!metadata.isMultiValued("key3")){
+		cout << "Key3 is correctly NOT multi-valued: correct!" << endl;
+	}
+	
+	metadata.addMetadata("key4", "val99");
+	
+	if(metadata.getMetadata("key4") != cas::Metadata::EMPTY_STR){
+		cout << "Metadata exists for key4, now deleting key4 and retesting" << endl;
+		
+		metadata.removeMetadata("key4");
+		
+		if(metadata.getMetadata("key4") == cas::Metadata::EMPTY_STR){
+			cout << "Metadata successfully removed for key4! " << endl;
+		}
+	}
+	
+	vector<string> key5vals;
+	key5vals.push_back("key5val1");
+	key5vals.push_back("key5val2");
+	
+	metadata.addMetadata("key5", key5vals);
+	
+	vector<string> key5replvals;
+	key5replvals.push_back("key5_replaced_val1");
+	key5replvals.push_back("key5_replaced_val2");
+	
+	metadata.replaceMetadata("key5", key5replvals);
+
+	for(int i=0; i < metadata.getAllMetadata("key5").size(); i++){
+		 cout << "Value: " << metadata.getAllMetadata("key5")[i] << endl;
+	}	
+	
+	metadata.addMetadata("key6", "key6val1");
+	
+	if(metadata.getMetadata("key6") == "key6val1"){
+		cout << "key6: value = key6val1, as appropriate" << endl;
+	}
+	
+	metadata.replaceMetadata("key6", "key6_replaced_val1");
+	
+	if(metadata.getMetadata("key6") == "key6_replaced_val1"){
+		cout << "key6: value = key6_replaced_val1, as appropriate" << endl;
+	}
+	
+	
+	cout << "XML is: " << endl;
+    DOMDocument* doc = metadata.toXML();
+	XMLCh tempStr[100];
+ 
+
+	XMLString::transcode("LS", tempStr, 99);
+	DOMImplementation *impl          = DOMImplementationRegistry::getDOMImplementation(tempStr);
+    DOMLSSerializer* theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer();
+
+
+	if (theSerializer->getDomConfig()->canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true))
+	  theSerializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
+
+	XMLFormatTarget *myFormTarget;
+        myFormTarget = new StdOutFormatTarget();
+    DOMLSOutput* theOutput = ((DOMImplementationLS*)impl)->createLSOutput();
+    theOutput->setByteStream(myFormTarget);
+
+	theSerializer->write((DOMNode*)doc, theOutput);
+	
+	cout << "Now attempting to parse cas xml document: data/sample.met.xml" << endl;
+	
+	XercesDOMParser parser_;
+	
+	parser_.setValidationScheme( xercesc::XercesDOMParser::Val_Never ) ;
+	parser_.setDoNamespaces( false ) ;
+	parser_.setDoSchema( false ) ;
+	parser_.setLoadExternalDTD( false ) ;
+	
+	 parser_.parse("./data/sample.met.xml") ;
+
+    // there's no need to free this pointer -- it's
+    // owned by the parent parser object
+    DOMDocument* xmlDoc = parser_.getDocument() ;
+    
+    cout << "Metadata XML file parsed: constructing CAS Metadata object from it " << endl;
+    
+    Metadata newMetadata(xmlDoc);
+    
+    cout << "Outputting XML from CAS Metadata " << endl;
+        
+    DOMDocument *newDoc = newMetadata.toXML();
+    theSerializer->write((DOMNode*)doc, theOutput);
+    
+	return 1;
+		
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/AbstractMetExtractor.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/AbstractMetExtractor.java
new file mode 100644
index 0000000..05a9b52
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/AbstractMetExtractor.java
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+//JDK imports
+import java.io.File;
+import java.net.URI;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A core {@link MetExtractor} implementation, implementing all methods but {{@link #extractMetadata(File)}
+ * </p>.
+ */
+public abstract class AbstractMetExtractor implements MetExtractor {
+
+    protected MetExtractorConfig config;
+
+    protected MetExtractorConfigReader reader;
+
+    protected static final Logger LOG = Logger
+            .getLogger(AbstractMetExtractor.class.getName());
+
+    public AbstractMetExtractor(MetExtractorConfigReader reader) {
+        this.reader = reader;
+    }
+
+    /**
+     * Extracts {@link Metadata} from the given {@link File}
+     * 
+     * @param file
+     *            The {@link File} from which {@link Metadata} will be extracted
+     * @return The {@link Metadata} extracted
+     * @throws MetExtractionException
+     *             If any error occurs
+     */
+    protected abstract Metadata extrMetadata(File file)
+            throws MetExtractionException;
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.MetExtractor#extractMetadata(java.io.File)
+     */
+    public Metadata extractMetadata(File f) throws MetExtractionException {
+        if (f == null || !f.exists())
+            throw new MetExtractionException("File '" + f + "' does not exist");
+        return this.extrMetadata(this.safeGetCanonicalFile(f));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.MetExtractor#extractMetadata(java.lang.String)
+     */
+    public Metadata extractMetadata(String filePath)
+            throws MetExtractionException {
+        return extractMetadata(new File(filePath));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.MetExtractor#extractMetadata(java.net.URL)
+     */
+    public Metadata extractMetadata(URL fileUrl) throws MetExtractionException {
+        try {
+            return this.extractMetadata(this.safeGetFileFromUri(fileUrl));
+        } catch (Exception e) {
+            throw new MetExtractionException(
+                    "Failed to extract metadata from URL '" + fileUrl + "' : "
+                            + e.getMessage());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.MetExtractor#extractMetadata(java.io.File,
+     *      java.io.File)
+     */
+    public Metadata extractMetadata(File f, File configFile)
+            throws MetExtractionException {
+        this.setConfigFile(configFile);
+        return this.extractMetadata(f);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.MetExtractor#extractMetadata(java.io.File,
+     *      java.lang.String)
+     */
+    public Metadata extractMetadata(File f, String configFilePath)
+            throws MetExtractionException {
+        return extractMetadata(f, new File(configFilePath));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.MetExtractor#extractMetadata(java.io.File,
+     *      org.apache.oodt.cas.metadata.MetExtractorConfig)
+     */
+    public Metadata extractMetadata(File f, MetExtractorConfig config)
+            throws MetExtractionException {
+        this.setConfigFile(config);
+        return this.extractMetadata(f);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.MetExtractor#extractMetadata(java.net.URL,
+     *      org.apache.oodt.cas.metadata.MetExtractorConfig)
+     */
+    public Metadata extractMetadata(URL fileUrl, MetExtractorConfig config)
+            throws MetExtractionException {
+        this.setConfigFile(config);
+        return this.extractMetadata(fileUrl);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.MetExtractor#setConfigFile(java.io.File)
+     */
+    public void setConfigFile(File f) throws MetExtractionException {
+        try {
+            this.setConfigFile(this.reader.parseConfigFile(this
+                    .safeGetCanonicalFile(f)));
+        } catch (Exception e) {
+            throw new MetExtractionException("Failed to parse config file : "
+                    + e.getMessage());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.MetExtractor#setConfigFile(org.apache.oodt.cas.metadata.MetExtractorConfig)
+     */
+    public void setConfigFile(MetExtractorConfig config) {
+        this.config = config;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.MetExtractor#setConfigFile(java.lang.String)
+     */
+    public void setConfigFile(String filePath) throws MetExtractionException {
+        setConfigFile(new File(filePath));
+    }
+
+    private File safeGetFileFromUri(URL url) {
+        try {
+            return new File(new URI(url.toExternalForm()));
+        } catch (Exception e) {
+            LOG.log(Level.WARNING, "Exception constructing file from uri: ["
+                    + url + "]: Message: " + e.getMessage());
+            return null;
+        }
+    }
+
+    private File safeGetCanonicalFile(File f) {
+        try {
+            return f.getCanonicalFile();
+        } catch (Exception e) {
+            LOG.log(Level.WARNING, "Exception get canonical file for file : ["
+                    + f + "]: Message: " + e.getMessage());
+            return null;
+        }
+    }
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/MetExtractor.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/MetExtractor.java
new file mode 100644
index 0000000..699d7c6
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/MetExtractor.java
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+//JDK imports
+import java.io.File;
+import java.net.URL;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An interface for {@link Metadata} extraction. This interface expects the
+ * definition of the following two parameters:
+ * 
+ * <ul>
+ * <li><b>file</b> - the file to extract {@link Metadata} from.</li>
+ * <li><b>config file</b> - a pointer to the config file for this MetExtractor</li>
+ * </ul>
+ * </p>
+ * 
+ */
+public interface MetExtractor {
+
+    /**
+     * Extracts {@link Metadata} from a given {@link File}.
+     * 
+     * @param f
+     *            File object to extract Metadata from.
+     * @return Extracted {@link Metadata} from the given {@link File}.
+     * @throws MetExtractionException
+     *             If any error occurs.
+     */
+    public Metadata extractMetadata(File f) throws MetExtractionException;
+
+    /**
+     * Extracts {@link Metadata} from a given <code>/path/to/some/file</code>.
+     * 
+     * @param filePath
+     *            Path to a given file to extract Metadata from.
+     * @return Extracted {@link Metadata} from the given <code>filePath</code>.
+     * @throws MetExtractionException
+     *             If any error occurs.
+     */
+    public Metadata extractMetadata(String filePath)
+            throws MetExtractionException;
+
+    /**
+     * Extracts {@link Metadata} from a given {@link URL} pointer to a
+     * {@link File}.
+     * 
+     * @param fileUrl
+     *            The URL pointer to a File.
+     * @return Extracted {@link Metadata} from the given File {@link URL}.
+     * @throws MetExtractionException
+     *             If any error occurs.
+     */
+    public Metadata extractMetadata(URL fileUrl) throws MetExtractionException;
+
+    /**
+     * Sets the config file for this MetExtractor to the specified {@link File}
+     * <code>f</code>.
+     * 
+     * @param f
+     *            The config file for this MetExtractor.
+     * @throws MetExtractionException
+     */
+    public void setConfigFile(File f) throws MetExtractionException;
+
+    /**
+     * Sets the config file for this MetExtractor to the specified {@link File}
+     * identified by <code>filePath</code>.
+     * 
+     * @param filePath
+     *            The config file path for this MetExtractor.
+     * @throws MetExtractionException
+     */
+    public void setConfigFile(String filePath) throws MetExtractionException;
+
+    /**
+     * Sets the MetExtractorConfig for the MetExtractor
+     * 
+     * @param config
+     *            The MetExtractorConfig
+     */
+    public void setConfigFile(MetExtractorConfig config);
+
+    /**
+     * Extracts {@link Metadata} from the given {@link File} using the specified
+     * config file.
+     * 
+     * @param f
+     *            The File to extract Metadata from.
+     * @param configFile
+     *            The config file for this MetExtractor.
+     * @return Extracted {@link Metadata} from the given {@link File} using the
+     *         specified config file.
+     * @throws MetExtractionException
+     *             If any error occurs.
+     */
+    public Metadata extractMetadata(File f, File configFile)
+            throws MetExtractionException;
+
+    /**
+     * Extracts {@link Metadata} from the given {@link File} using the specified
+     * config file path.
+     * 
+     * @param f
+     *            The File to extract Metadata from.
+     * @param configFilePath
+     *            The path to the config file for this MetExtractor.
+     * @return Extracted {@link Metadata} from the given {@link File} using the
+     *         specified config file path.
+     * @throws MetExtractionException
+     *             If any error occurs.
+     */
+    public Metadata extractMetadata(File f, String configFilePath)
+            throws MetExtractionException;
+
+    /**
+     * Extracts {@link Metadata} from the given {@link File} using the specified
+     * {@link MetExtractorConfig}.
+     * 
+     * @param f
+     *            The {@link File} from which {@link Metadata} will be extracted
+     *            from
+     * @param config
+     *            The config file for the extractor
+     * @return {@link Metadata} extracted from the {@link File}
+     * @throws MetExtractionException
+     *             If any error occurs
+     */
+    public Metadata extractMetadata(File f, MetExtractorConfig config)
+            throws MetExtractionException;
+
+    /**
+     * Extracts {@link Metadata} from the given {@link URL} using the specified
+     * {@link MetExtractorConfig}.
+     * 
+     * @param fileUrl
+     *            The {@link URL} from which {@link Metadata} will be extracted
+     *            from
+     * @param config
+     *            The config file for the extractor
+     * @return {@link Metadata} extracted from the {@link URL}
+     * @throws MetExtractionException
+     *             If any error occurs
+     */
+    public Metadata extractMetadata(URL fileUrl, MetExtractorConfig config)
+            throws MetExtractionException;
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/MetExtractorConfig.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/MetExtractorConfig.java
new file mode 100644
index 0000000..5e5f110
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/MetExtractorConfig.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A {@link MetExtractor} config
+ * </p>.
+ */
+public interface MetExtractorConfig {
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/MetExtractorConfigReader.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/MetExtractorConfigReader.java
new file mode 100644
index 0000000..9f982b1
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/MetExtractorConfigReader.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.exceptions.MetExtractorConfigReaderException;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A reader interface which converts config {@link File}s into
+ * {@link MetExtractorConfig} objects
+ * </p>.
+ */
+public interface MetExtractorConfigReader {
+
+    /**
+     * Parses a config {@link File} into a {@link MetExtractorConfig} obj
+     * 
+     * @param configFile
+     *            The config {@link File} to be parsed
+     * @return The {@link MetExtractorConfig} obj created by parsing the input
+     *         config {@link File}
+     * @throws MetExtractorConfigReaderException
+     *             If any error occurs
+     */
+    public MetExtractorConfig parseConfigFile(File configFile)
+            throws MetExtractorConfigReaderException;
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/Metadata.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/Metadata.java
new file mode 100644
index 0000000..5a45444
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/Metadata.java
@@ -0,0 +1,579 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.cas.metadata;
+
+//JDK imports
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/**
+ * 
+ * Metadata is a {@link Map} of <code>String</code> keys mapped to Object
+ * values. So, each key can map to potentially many values, but also can map to
+ * null, or to a single value.
+ * 
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class Metadata {
+
+  private Group root;
+
+  public Metadata() {
+    this.root = this.createNewRoot();
+  }
+
+  public Metadata(Metadata metadata) {
+    this();
+    this.addMetadata(metadata);
+  }
+
+  /**
+   * Adds (Appends if key exists) from given metadata into this metadata
+   * 
+   * @param metadata
+   *          Metadata to add metadata from
+   */
+  public void addMetadata(Metadata metadata) {
+    for (String key : metadata.getAllKeys())
+      this.addMetadata(key, metadata.getAllMetadata(key));
+  }
+
+  public void addMetadata(String group, Metadata metadata) {
+    if (group == null) {
+      this.addMetadata(metadata);
+    } else {
+      for (String key : metadata.getAllKeys())
+        this.addMetadata(group + "/" + key, metadata.getAllMetadata(key));
+    }
+  }
+
+  /**
+   * Adds (Replaces if key exists) from given Metadata into this Metadata
+   * 
+   * @param metadata
+   */
+  public void replaceMetadata(Metadata metadata) {
+    for (String key : metadata.getAllKeys())
+      this.replaceMetadata(key, metadata.getAllMetadata(key));
+  }
+
+  public void replaceMetadata(String group, Metadata metadata) {
+    if (group == null) {
+      this.replaceMetadata(metadata);
+    } else {
+      for (String key : metadata.getAllKeys())
+        this.replaceMetadata(group + "/" + key, metadata.getAllMetadata(key));
+    }
+  }
+
+  /**
+   * Adds key (Appends if key exists)
+   * 
+   * @param key
+   *          Key to be added
+   * @param value
+   *          Value of key to be added
+   */
+  public void addMetadata(String key, String value) {
+    this.getGroup(key).addValue(value);
+  }
+
+  /**
+   * Adds key (Replaces if key exists)
+   * 
+   * @param key
+   *          Key to be added
+   * @param value
+   *          Value of key to be added
+   */
+  public void replaceMetadata(String key, String value) {
+    this.getGroup(key).setValue(value);
+  }
+
+  /**
+   * Adds key (Appends if key exists)
+   * 
+   * @param key
+   *          Key to be added
+   * @param values
+   *          Values of key to be added
+   */
+  public void addMetadata(String key, List<String> values) {
+    this.getGroup(key).addValues(values);
+  }
+
+  /**
+   * Adds key (Replaces if key exists)
+   * 
+   * @param key
+   *          Key to be added
+   * @param values
+   *          Values of key to be added
+   */
+  public void replaceMetadata(String key, List<String> values) {
+    this.getGroup(key).setValues(values);
+  }
+
+  /**
+   * Removes key
+   * 
+   * @param key
+   *          Key to remove
+   */
+  public void removeMetadata(String key) {
+    Group removeGroup = this.getGroup(key, false);
+    if (removeGroup != null && removeGroup.hasValues()) {
+      if (removeGroup.getChildren().size() > 0)
+        removeGroup.clearValues();
+      else
+        removeGroup.getParent().removeChild(removeGroup.getName());
+    }
+  }
+
+  /**
+   * Removes key
+   * 
+   * @param key
+   *          Key to remove
+   */
+  public void removeMetadataGroup(String group) {
+    Group removeGroup = this.getGroup(group, false);
+    if (removeGroup != null && removeGroup.getChildren().size() > 0)
+      removeGroup.getParent().removeChild(removeGroup.getName());
+  }
+
+  /**
+   * Checks if keys exists
+   * 
+   * @param key
+   *          Key to check for
+   * @return True if key exists, false otherwise
+   */
+  public boolean containsKey(String key) {
+    Group group = this.getGroup(key, false);
+    return group != null && group.hasValues();
+  }
+
+  /**
+   * Checks if key has more than one value
+   * 
+   * @param key
+   *          Key to check for
+   * @return True is key exists and has more than one value, false otherwise
+   */
+  public boolean isMultiValued(String key) {
+    Group group = this.getGroup(key, false);
+    return group != null && group.getValues().size() > 1;
+  }
+
+  /**
+   * Creates a Metadata from the given group
+   * 
+   * @param group
+   *          The Group to grab
+   * @return Metadata containing group and all keys below it
+   */
+  public Metadata getSubMetadata(String group) {
+    Metadata m = new Metadata();
+    Group newRoot = this.getGroup(group, false);
+    if (newRoot != null)
+      m.root.addChildren(newRoot.clone().getChildren());
+    return m;
+  }
+
+  /**
+   * Gets the first value for the given key
+   * 
+   * @param key
+   *          The key for which the first value will be returned
+   * @return First value for given key, or null if key does not exist
+   */
+  public String getMetadata(String key) {
+    Group group = this.getGroup(key, false);
+    if (group != null)
+      return group.getValue();
+    else
+      return null;
+  }
+
+  /**
+   * Gets all values for give key
+   * 
+   * @param key
+   *          The key for which all values will be return
+   * @return All values for given key, or null if key does not exist
+   */
+  public List<String> getAllMetadata(String key) {
+    Group group = this.getGroup(key, false);
+    if (group != null)
+      return new Vector<String>(group.getValues());
+    else
+      return null;
+  }
+
+  /**
+   * Gets All key in and below given group
+   * 
+   * @param group
+   *          The group in question
+   * @return All keys for the given group and below
+   */
+  public List<String> getKeys(String group) {
+    Group foundGroup = this.getGroup(group);
+    if (foundGroup != null)
+      return this.getKeys(foundGroup);
+    else
+      return new Vector<String>();
+  }
+
+  /**
+   * Gets all keys in this Metadata
+   * 
+   * @return All keys in this Metadata
+   */
+  public List<String> getKeys() {
+    return this.getKeys(this.root);
+  }
+
+  protected List<String> getKeys(Group group) {
+    Vector<String> keys = new Vector<String>();
+    for (Group child : group.getChildren())
+      if (child.hasValues())
+        keys.add(child.getFullPath());
+    return keys;
+  }
+
+  /**
+   * Gets All key in and below given group
+   * 
+   * @param group
+   *          The group in question
+   * @return All keys for the given group and below
+   */
+  public List<String> getAllKeys(String group) {
+    Group foundGroup = this.getGroup(group);
+    if (foundGroup != null)
+      return this.getAllKeys(foundGroup);
+    else
+      return new Vector<String>();
+  }
+
+  /**
+   * Gets all keys in this Metadata
+   * 
+   * @return All keys in this Metadata
+   */
+  public List<String> getAllKeys() {
+    return this.getAllKeys(this.root);
+  }
+
+  protected List<String> getAllKeys(Group group) {
+    Vector<String> keys = new Vector<String>();
+    for (Group child : group.getChildren()) {
+      if (child.hasValues())
+        keys.add(child.getFullPath());
+      keys.addAll(this.getAllKeys(child));
+    }
+    return keys;
+  }
+  
+  /**
+   * Get all keys whose leaf key name is equal to the given arg
+   * @param key leaf key name
+   * @return list of keys with the given leaf key name
+   */
+  public List<String> getAllKeysWithName(String key) {
+	  List<String> keys = new Vector<String>();
+	  Stack<Group> stack = new Stack<Group>();
+	  stack.add(this.root);
+	  while (!stack.empty()) {
+		  Group curGroup = stack.pop();
+		  if (curGroup.getName().equals(key) && curGroup.hasValues())
+			  keys.add(curGroup.getFullPath());
+		  stack.addAll(curGroup.getChildren());
+	  }
+	  return keys;
+  }
+
+  /**
+   * Gets Values in root group
+   * 
+   * @return All Values in root group
+   */
+  public List<String> getValues() {
+    Vector<String> values = new Vector<String>();
+    for (String key : this.getKeys())
+      values.addAll(this.getAllMetadata(key));
+    return values;
+  }
+
+  /**
+   * Gets values in given group
+   * 
+   * @param group
+   *          Group in question
+   * @return Values in given group
+   */
+  public List<String> getValues(String group) {
+    Vector<String> values = new Vector<String>();
+    for (String key : this.getKeys(group))
+      values.addAll(this.getAllMetadata(key));
+    return values;
+  }
+
+  /**
+   * Gets all values in this Metadata
+   * 
+   * @return All values in this Metadata
+   */
+  public List<String> getAllValues() {
+    Vector<String> values = new Vector<String>();
+    for (String key : this.getAllKeys())
+      values.addAll(this.getAllMetadata(key));
+    return values;
+  }
+
+  /**
+   * Gets All values in and below given group
+   * 
+   * @param group
+   *          Group in question
+   * @return All values in and below given group
+   */
+  public List<String> getAllValues(String group) {
+    Vector<String> values = new Vector<String>();
+    for (String key : this.getAllKeys(group))
+      values.addAll(this.getAllMetadata(key));
+    return values;
+  }
+
+  public void addMetadata(Hashtable<String, Object> metadata) {
+    addMetadata(metadata, false);
+  }
+
+  /**
+   * Takes a hashtable of String keys and Object values.  Values of type List
+   * must be a List of Strings; all other values will have its toString() method
+   * invoked.
+   * @param metadata Hashtable based metadata to add
+   * @param replace If true, existing keys will be replaced, other values will be
+   * combined.
+   */
+  public void addMetadata(Hashtable<String, Object> metadata, boolean replace) {
+    // for back compat: the old method allowed us to give it a
+    // Hashtable<String,String> and it still worked
+	for (String key : metadata.keySet()) {
+	  List<String> vals = (metadata.get(key) instanceof List) ? (List<String>) metadata
+        .get(key)
+        : Collections.singletonList(metadata.get(key).toString());
+      if (replace) {
+        this.replaceMetadata(key, vals);
+      } else {
+        this.addMetadata(key, vals);
+      }
+    }
+  }
+
+  public void replaceMetadata(Hashtable<String, Object> metadata) {
+    this.root = this.createNewRoot();
+    this.addMetadata(metadata);
+  }
+
+  public boolean containsGroup(String group) {
+    return this.getGroup(group, false) != null;
+  }
+
+  public List<String> getGroups() {
+    return this.getGroups(this.root);
+  }
+
+  public List<String> getGroups(String group) {
+    return this.getGroups(this.getGroup(group));
+  }
+
+  protected List<String> getGroups(Group group) {
+    Vector<String> groupNames = new Vector<String>();
+    for (Group child : group.getChildren())
+      groupNames.add(child.getName());
+    return groupNames;
+  }
+
+  protected Group getGroup(String key) {
+    return getGroup(key, true);
+  }
+
+  protected Group getGroup(String key, boolean create) {
+    if (key == null)
+      return this.root;
+    StringTokenizer tokenizer = new StringTokenizer(key, "/");
+    Group curGroup = this.root;
+    while (tokenizer.hasMoreTokens()) {
+      String groupName = tokenizer.nextToken();
+      Group childGroup = curGroup.getChild(groupName);
+      if (childGroup == null) {
+        if (!create)
+          return null;
+        childGroup = new Group(groupName);
+        curGroup.addChild(childGroup);
+      }
+      curGroup = childGroup;
+    }
+    return curGroup;
+  }
+
+  protected Group createNewRoot() {
+    return new Group(Group.ROOT_GROUP_NAME);
+  }
+
+  protected class Group {
+
+    private static final String ROOT_GROUP_NAME = "root";
+
+    private String name;
+    private List<String> values;
+    private Group parent;
+    private Map<String, Group> children;
+
+    public Group(String name) {
+      this.name = name;
+      this.values = new Vector<String>();
+      this.children = new HashMap<String, Group>();
+    }
+
+    public String getName() {
+      return this.name;
+    }
+
+    public String getFullPath() {
+      if (this.parent != null && !this.parent.getName().equals(ROOT_GROUP_NAME))
+        return this.parent.getFullPath() + "/" + this.name;
+      else
+        return this.name;
+    }
+
+    public Group getParent() {
+      return this.parent;
+    }
+
+    public void setValue(String value) {
+      this.values.clear();
+      this.values.add(value);
+    }
+
+    public void setValues(List<String> values) {
+      this.values.clear();
+      this.values.addAll(values);
+    }
+
+    public void clearValues() {
+      this.values.clear();
+    }
+
+    public void addValue(String value) {
+      this.values.add(value);
+    }
+
+    public void addValues(List<String> value) {
+      this.values.addAll(value);
+    }
+
+    public boolean hasValues() {
+      return this.values.size() > 0;
+    }
+
+    public String getValue() {
+      if (this.hasValues())
+        return this.values.get(0);
+      else
+        return null;
+    }
+
+    public List<String> getValues() {
+      return this.values;
+    }
+
+    public void addChild(Group child) {
+      this.children.put(child.getName(), child);
+      child.parent = this;
+    }
+
+    public void addChildren(List<Group> children) {
+      for (Group child : children)
+        this.addChild(child);
+    }
+
+    public List<Group> getChildren() {
+      return new Vector<Group>(this.children.values());
+    }
+
+    public void removeChild(String name) {
+      this.children.remove(name);
+    }
+
+    public Group getChild(String name) {
+      return this.children.get(name);
+    }
+
+    @Override
+    public Group clone() {
+      Group clone = new Group(this.name);
+      clone.setValues(this.values);
+      for (Group child : this.children.values())
+        clone.addChild(child.clone());
+      return clone;
+    }
+
+    @Override
+    public String toString() {
+      return this.getFullPath();
+    }
+
+  }
+
+  public Hashtable<String, Object> getHashtable() {
+    Hashtable<String, Object> table = new Hashtable<String, Object>();
+    for (String key : this.getAllKeys())
+      table.put(key, this.getAllMetadata(key));
+    return table;
+  }
+
+  public boolean equals(Object obj) {
+    if (obj instanceof Metadata) {
+      Metadata compMet = (Metadata) obj;
+      if (this.getKeys().equals(compMet.getKeys())) {
+        for (String key : this.getKeys())
+          if (!this.getAllMetadata(key).equals(compMet.getAllMetadata(key)))
+            return false;
+        return true;
+      } else {
+        return false;
+      }
+
+    } else {
+      return false;
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/SerializableMetadata.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/SerializableMetadata.java
new file mode 100644
index 0000000..34fae67
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/SerializableMetadata.java
@@ -0,0 +1,264 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.cas.metadata;
+
+//JDK imports
+import org.apache.oodt.commons.xml.XMLUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.net.URLEncoder;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * {@link Metadata} that's {@link Serializable}.
+ * </p>.
+ */
+public class SerializableMetadata extends Metadata implements Serializable {
+
+    private static final long serialVersionUID = 6863087581652632499L;
+
+    private String xmlEncoding;
+
+    private boolean useCDATA;
+    
+    public SerializableMetadata() {
+    	super();
+    	this.xmlEncoding = "UTF-8";
+    	this.useCDATA = false;
+    }
+    
+    /**
+     * Accepts any encoding which is supported by java.net.URLEncoder If
+     * useCDATA is set true then element text will be wrapped in a CDATA tag.
+     * 
+     * @param xmlEncoding
+     *            The encoding to use when generating XML version of a
+     *            SerializableMetadata
+     * @param useCDATA
+     *            whether or not to use CDATA tags around an element's text.
+     * @throws InstantiationException
+     *             if xmlEncoding equals null
+     */
+    public SerializableMetadata(String xmlEncoding, boolean useCDATA)
+            throws InstantiationException {
+        super();
+        if (xmlEncoding == null)
+            throw new InstantiationException("xmlEncoding cannot be null");
+        this.xmlEncoding = xmlEncoding;
+        this.useCDATA = useCDATA;
+    }
+
+    public SerializableMetadata(Metadata metadata) {
+    	this(metadata, "UTF-8", false);
+	}
+    
+    public SerializableMetadata(InputStream inputStream) throws IOException {
+    	this(inputStream, "UTF-8", false);
+    }
+    
+    public SerializableMetadata(InputStream inputStream, String xmlEncoding,
+            boolean useCDATA) throws IOException {
+        this.xmlEncoding = xmlEncoding;
+        this.useCDATA = useCDATA;
+    	this.loadMetadataFromXmlStream(inputStream);
+    }
+
+    
+    /**
+     * Builds a SerializableMetadata object from a Metadata object
+     * 
+     * @param metadata
+     * @param xmlEncoding
+     */
+    public SerializableMetadata(Metadata metadata, String xmlEncoding,
+            boolean useCDATA) {
+        this.replaceMetadata(metadata);
+        this.xmlEncoding = xmlEncoding;
+        this.useCDATA = useCDATA;
+    }
+
+    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
+        out.writeObject(this.xmlEncoding);
+        out.writeBoolean(useCDATA);
+        this.writeMetadataToXmlStream(out);
+    }
+
+    private void readObject(java.io.ObjectInputStream in) throws IOException,
+            ClassNotFoundException {
+        this.xmlEncoding = (String) in.readObject();
+        this.useCDATA = in.readBoolean();
+        this.loadMetadataFromXmlStream(in);
+    }
+
+    public String getEncoding() {
+        return this.xmlEncoding;
+    }
+
+    public boolean isUsingCDATA() {
+        return this.useCDATA;
+    }
+
+    /**
+     * Writes out this SerializableMetadata object in XML format to the
+     * OutputStream provided
+     * 
+     * @param os
+     *            The OutputStream this method writes to
+     * @throws IOException
+     *             for any Exception
+     */
+    public void writeMetadataToXmlStream(OutputStream os) throws IOException {
+        try {
+            // Prepare the DOM document for writing
+            Source source = new DOMSource(this.toXML());
+            Result result = new StreamResult(os);
+
+            // Write the DOM document to the file
+            Transformer xformer = TransformerFactory.newInstance()
+                    .newTransformer();
+            xformer.setOutputProperty(OutputKeys.ENCODING, this.xmlEncoding);
+            xformer.setOutputProperty(OutputKeys.INDENT, "yes");
+            xformer.transform(source, result);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new IOException("Error generating metadata xml file!: "
+                    + e.getMessage());
+        }
+    }
+
+    public Document toXML() throws IOException {
+        try {
+            DocumentBuilderFactory factory = DocumentBuilderFactory
+                    .newInstance();
+            factory.setNamespaceAware(true);
+            Document document = factory.newDocumentBuilder().newDocument();
+
+            Element root = document.createElementNS("http://oodt.jpl.nasa.gov/1.0/cas", "metadata");
+            root.setPrefix("cas");
+            document.appendChild(root);
+
+            // now add the set of metadata elements in the properties object
+            for (String key : this.getAllKeys()) {
+                Element metadataElem = document.createElement("keyval");
+                Element keyElem = document.createElement("key");
+                if (this.useCDATA)
+                    keyElem.appendChild(document.createCDATASection(key));
+                else
+                    keyElem.appendChild(document.createTextNode(URLEncoder.encode(key, this.xmlEncoding)));
+                
+                metadataElem.appendChild(keyElem);
+
+                metadataElem.setAttribute("type", "vector");
+
+                for (String value : this.getAllMetadata(key)) {
+                    Element valElem = document.createElement("val");
+                    if (value == null) {
+                        throw new Exception("Attempt to write null value "
+                                + "for property: [" + key + "]: val: ["
+                                + value + "]");
+                    }
+                    if (this.useCDATA)
+                        valElem.appendChild(document
+                                .createCDATASection(value));
+                    else
+                        valElem.appendChild(document.createTextNode(URLEncoder
+                                .encode(value, this.xmlEncoding)));
+                    metadataElem.appendChild(valElem);
+                }
+                root.appendChild(metadataElem);
+            }
+            return document;
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new IOException(
+                    "Failed to create XML DOM Document for SerializableMetadata : "
+                            + e.getMessage());
+        }
+    }
+
+    /**
+     * Reloads this SerializableMetadata from an InputStream in the format
+     * created by writeMetadataToXmlStream(OutputStream).
+     * 
+     * @param in
+     *            The InputStream which this object is loaded from
+     * @throws IOException
+     *             for any exception
+     */
+    public void loadMetadataFromXmlStream(InputStream in) throws IOException {
+        try {
+            DocumentBuilderFactory factory = DocumentBuilderFactory
+                    .newInstance();
+            factory.setNamespaceAware(true);
+            DocumentBuilder parser = factory.newDocumentBuilder();
+            Element root = parser.parse(new InputSource(in))
+                    .getDocumentElement();
+
+            NodeList keyValElems = root.getElementsByTagName("keyval");
+
+            for (int i = 0; i < keyValElems.getLength(); i++) {
+                Element keyValElem = (Element) keyValElems.item(i);
+
+                String elemName = XMLUtils.read(keyValElem, "key",
+                        this.xmlEncoding);
+                List<String> elemValues = XMLUtils.readMany(keyValElem, "val",
+                        this.xmlEncoding);
+                this.addMetadata(elemName, elemValues);
+            }
+        } catch (Exception e) {
+            throw new IOException(
+                    "Failed to load SerializableMetadata from ObjectInputStream : "
+                            + e.getMessage());
+        }
+    }
+
+    /**
+     * Converts SerializableMetadata into a plain metadata object
+     * 
+     * @return Metadata object with the same metadata that this
+     *         SerializableMetadata contains
+     */
+    public Metadata getMetadata() {
+        Metadata metadata = new Metadata();
+        metadata.addMetadata(this.getHashtable());
+        return metadata;
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/exceptions/MetExtractionException.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/exceptions/MetExtractionException.java
new file mode 100644
index 0000000..bae0370
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/exceptions/MetExtractionException.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Exception thrown by the Met Extraction framework.
+ * </p>
+ * 
+ */
+public class MetExtractionException extends Exception {
+	/* serial version UID */
+	private static final long serialVersionUID = -336708813946999791L;
+
+	/**
+	 * 
+	 */
+	public MetExtractionException() {
+		super();
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public MetExtractionException(String arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 * @param arg1
+	 */
+	public MetExtractionException(String arg0, Throwable arg1) {
+		super(arg0, arg1);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public MetExtractionException(Throwable arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/exceptions/MetExtractorConfigReaderException.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/exceptions/MetExtractorConfigReaderException.java
new file mode 100644
index 0000000..0ca2b0c
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/exceptions/MetExtractorConfigReaderException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.metadata.exceptions;
+
+/**
+ * Exception throw when error occurs while parsing a config {@link File} into a
+ * {@link MetExtractorConfig}
+ *
+ * @author bfoster@apache.org (Brian Foster)
+ */
+public class MetExtractorConfigReaderException extends Exception {
+
+	private static final long serialVersionUID = 6344695980144312225L;
+
+	public MetExtractorConfigReaderException() {
+		super();
+	}
+	
+	public MetExtractorConfigReaderException(String msg) {
+		super(msg);
+	}
+
+	public MetExtractorConfigReaderException(String msg, Throwable t) {
+	  super(msg, t);
+	}
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/exceptions/NamingConventionException.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/exceptions/NamingConventionException.java
new file mode 100644
index 0000000..e56b474
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/exceptions/NamingConventionException.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.metadata.exceptions;
+
+/**
+ * Exception throw by {@link NamingConvention} on error.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class NamingConventionException extends Exception {
+
+   private static final long serialVersionUID = 1L;
+
+   public NamingConventionException() {
+      super();
+   }
+
+   public NamingConventionException(String msg) {
+      super(msg);
+   }
+
+   public NamingConventionException(String msg, Throwable t) {
+      super(msg, t);
+   }
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/exceptions/PreconditionComparatorException.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/exceptions/PreconditionComparatorException.java
new file mode 100644
index 0000000..6a6b340
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/exceptions/PreconditionComparatorException.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.exceptions;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.preconditions.PreConditionComparator; //for javadoc
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * An exception throw by a {@link PreConditionComparator}
+ * </p>.
+ */
+public class PreconditionComparatorException extends Exception {
+
+    private static final long serialVersionUID = 529448149740045618L;
+
+    public PreconditionComparatorException() {
+        super();
+    }
+
+    public PreconditionComparatorException(String msg) {
+        super(msg);
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/AbstractSAXConfigReader.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/AbstractSAXConfigReader.java
new file mode 100644
index 0000000..fb370cf
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/AbstractSAXConfigReader.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.metadata.extractors;
+
+import org.apache.oodt.cas.metadata.MetExtractorConfig;
+import org.apache.oodt.cas.metadata.MetExtractorConfigReader;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractorConfigReaderException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.File;
+
+/**
+ * Parses an xml config file for MetExtractors using SAX.
+ *
+ * @author rickdn (Ricky Nguyen)
+ */
+public class AbstractSAXConfigReader extends DefaultHandler implements MetExtractorConfigReader, MetExtractorConfig {
+
+    @Override
+    public AbstractSAXConfigReader parseConfigFile(File configFile) throws MetExtractorConfigReaderException {
+        try {
+            SAXParser p = SAXParserFactory.newInstance().newSAXParser();
+            p.parse(configFile, this);
+        } catch (Exception e) {
+            throw new MetExtractorConfigReaderException(e.getMessage());
+        }
+        return this;
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/CmdLineMetExtractor.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/CmdLineMetExtractor.java
new file mode 100644
index 0000000..93ef68b
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/CmdLineMetExtractor.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//JDK imports
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.Properties;
+import java.util.logging.Level;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.AbstractMetExtractor;
+import org.apache.oodt.cas.metadata.MetExtractorConfigReader;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.commons.exec.EnvUtilities;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Metadata extraction interface for standalone met extractors that have the
+ * following command line interface:<br>
+ * 
+ * <code>/path/to/met_extractor &lt;file&gt; &lt;config file&gt;</code>
+ * </p>.
+ */
+public abstract class CmdLineMetExtractor extends AbstractMetExtractor {
+
+  public CmdLineMetExtractor(MetExtractorConfigReader reader) {
+      super(reader);
+  }
+
+  protected static void processMain(String[] args,
+          CmdLineMetExtractor extractor) throws Exception {
+      String usage = "Usage: " + extractor.getClass().getName()
+              + " <file> <configfile>";
+      String extractFilePath = null, configFilePath = null;
+
+      if (args.length < 2) {
+          System.err.println(usage);
+          System.exit(1);
+      }
+
+      extractFilePath = args[0].replaceAll("\\\\", "");
+      configFilePath = args[1];
+
+      Metadata met = extractor.extractMetadata(new File(extractFilePath),
+              configFilePath);
+      XMLUtils.writeXmlToStream(new SerializableMetadata(met).toXML(),
+              getMetFileOutputStream(extractFilePath));
+  }
+
+  protected static void processMain(String[] args,
+          CmdLineMetExtractor extractor, OutputStream os) throws Exception {
+      String usage = "Usage: " + extractor.getClass().getName()
+              + " <file> <configfile>";
+      String extractFilePath = null, configFilePath = null;
+
+      if (args.length < 2) {
+          System.err.println(usage);
+          System.exit(1);
+      }
+
+      extractFilePath = args[0].replaceAll("\\\\", "");
+      configFilePath = args[1];
+
+      Metadata met = extractor.extractMetadata(new File(extractFilePath),
+              configFilePath);
+      XMLUtils.writeXmlToStream(new SerializableMetadata(met).toXML(), os);
+
+  }
+
+  private static FileOutputStream getMetFileOutputStream(String filePath) {
+      Properties envVars = EnvUtilities.getEnv();
+      String cwd = envVars.getProperty("PWD");
+      if (cwd == null) {
+          throw new RuntimeException(
+                  "Unable to get current working directory: failing!");
+      }
+
+      if (!cwd.endsWith("/")) {
+          cwd += "/";
+      }
+
+      String metFilePath = cwd
+              + new File(filePath).getName().replaceAll("\\\\", "") + ".met";
+
+      // try and remove the met file, if it already exists
+      // for some reason below, the writeXmlFile method in
+      // XMLUtils doesn't overwrite, and throws an Exception
+      File metFile = new File(metFilePath);
+      if (!metFile.delete()) {
+          LOG.log(Level.WARNING, "Attempt to overwrite met file: ["
+                  + metFilePath + "] unsuccessful!");
+      }
+
+      try {
+          return new FileOutputStream(metFile);
+      } catch (FileNotFoundException e) {
+          LOG.log(Level.WARNING, "Could not create met file: [" + metFile
+                  + "]: Reason " + e.getMessage(), e);
+          return null;
+      }
+  }
+
+}
+
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/CopyAndRewriteConfig.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/CopyAndRewriteConfig.java
new file mode 100644
index 0000000..f241081
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/CopyAndRewriteConfig.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//JDK imports
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.MetExtractorConfig;
+
+/**
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * The {@link MetExtractorConfig} for the {@link CopyAndRewriteExtractor}
+ * </p>.
+ */
+public class CopyAndRewriteConfig extends Properties implements
+        MetExtractorConfig {
+
+    private static final long serialVersionUID = 6099066717717948612L;
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/CopyAndRewriteConfigReader.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/CopyAndRewriteConfigReader.java
new file mode 100644
index 0000000..016b59e
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/CopyAndRewriteConfigReader.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.MetExtractorConfig;
+import org.apache.oodt.cas.metadata.MetExtractorConfigReader;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractorConfigReaderException;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Config file reader class for {@link CopyAndRewriteExtractor}
+ * </p>.
+ */
+public class CopyAndRewriteConfigReader implements MetExtractorConfigReader {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.MetExtractorConfigReader#parseConfigFile(java.io.File)
+     */
+    public MetExtractorConfig parseConfigFile(File configFile)
+            throws MetExtractorConfigReaderException {
+        try {
+            CopyAndRewriteConfig config = new CopyAndRewriteConfig();
+            config.load(configFile.toURL().openStream());
+            return config;
+        } catch (Exception e) {
+            throw new MetExtractorConfigReaderException("Failed to parse '"
+                    + configFile + "' : " + e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/CopyAndRewriteExtractor.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/CopyAndRewriteExtractor.java
new file mode 100644
index 0000000..8cd7217
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/CopyAndRewriteExtractor.java
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Level;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.oodt.cas.metadata.extractors.CmdLineMetExtractor;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A {@link MetExtractor} that takes in a configuration file that is a java
+ * properties object with the following properties defined:
+ * 
+ * <ul>
+ * <li>numRewriteFields - The number of fields to rewrite within the original
+ * metadata file.</li>
+ * <li>rewriteFieldN - The name(s) of the fields to rewrite in the original
+ * {@link Metadata} file.</li>
+ * <li>orig.met.file.path - he original path to the {@link Metadata} XML file
+ * to draw the original properties from.</li>
+ * <li>fieldN.pattern - The string specification that details which fields to
+ * replace and to use in building the new field value.</li>
+ * </ul>
+ * 
+ * </p>.
+ */
+public class CopyAndRewriteExtractor extends CmdLineMetExtractor {
+
+  private final static String FILENAME = "Filename";
+
+  private final static String FILE_LOCATION = "FileLocation";
+
+  private static CopyAndRewriteConfigReader reader = new CopyAndRewriteConfigReader();
+
+  /**
+   * Default Constructor.
+   * 
+   */
+  public CopyAndRewriteExtractor() {
+      super(reader);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see gov.nasa.jpl.oodt.cas.metadata.AbstractMetExtractor#extractMetadata(java.io.File)
+   */
+  public Metadata extrMetadata(File file) throws MetExtractionException {
+      if (this.config == null) {
+          throw new MetExtractionException(
+                  "No config file defined: unable to copy and rewrite metadata!");
+      }
+
+      Metadata met = null;
+      
+      try {
+          met = new SerializableMetadata(new File(PathUtils
+                  .replaceEnvVariables(((CopyAndRewriteConfig) this.config)
+                          .getProperty("orig.met.file.path"))).toURL()
+                  .openStream());
+      } catch (Exception e) {
+          e.printStackTrace();
+          throw new MetExtractionException(
+                  "error parsing original met file: ["
+                          + ((CopyAndRewriteConfig) this.config)
+                                  .getProperty("orig.met.file.path")
+                          + "]: Message: " + e.getMessage());
+      }
+
+      addDefaultFields(file, met);
+
+      // now override
+      int numOverrideFields = Integer
+              .parseInt(((CopyAndRewriteConfig) this.config)
+                      .getProperty("numRewriteFields"));
+
+      LOG.log(Level.FINE, "Extracting metadata: num rewrite fields: ["
+              + numOverrideFields + "]");
+
+      for (int i = 0; i < numOverrideFields; i++) {
+          String rewriteFieldName = ((CopyAndRewriteConfig) this.config)
+                  .getProperty("rewriteField" + (i + 1));
+          String rewriteFieldStr = ((CopyAndRewriteConfig) this.config)
+                  .getProperty(rewriteFieldName + ".pattern");
+          LOG.log(Level.FINE, "Rewrite string: [" + rewriteFieldStr + "]");
+          rewriteFieldStr = PathUtils.replaceEnvVariables(rewriteFieldStr,
+                  met);
+          met.replaceMetadata(rewriteFieldName, rewriteFieldStr);
+      }
+
+      return met;
+
+  }
+
+  public static void main(String[] args) throws Exception {
+      processMain(args, new CopyAndRewriteExtractor());
+  }
+
+  private void addDefaultFields(File file, Metadata met) {
+      met.replaceMetadata(FILENAME, file.getName());
+      met.replaceMetadata(FILE_LOCATION, file.getParentFile()
+              .getAbsolutePath());
+  }
+
+}
+
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/DataSourceMetExtractor.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/DataSourceMetExtractor.java
new file mode 100644
index 0000000..821b9c6
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/DataSourceMetExtractor.java
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.metadata.extractors;
+
+// JDK imports
+import java.io.File;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+
+// JAVAX imports
+import javax.sql.DataSource;
+
+
+// OODT imports
+import org.apache.oodt.cas.metadata.AbstractMetExtractor;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+
+
+// Google imports
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Splitter;
+
+/**
+ * MetExtractor which uses input file's name as key for lookup into a sql database to get metadata.
+ *
+ * @author bfoster@apache.org (Brian Foster)
+ */
+public class DataSourceMetExtractor extends AbstractMetExtractor {
+
+  public DataSourceMetExtractor() {
+    super(new DataSourceMetExtractorConfigReader());
+  }
+
+  @Override
+  protected Metadata extrMetadata(File file) throws MetExtractionException {
+    String key = getKey(file);
+    DataSourceMetExtractorConfig dsConfig = (DataSourceMetExtractorConfig) config;
+    DataSource dataSource = DatabaseConnectionBuilder.buildDataSource(dsConfig.getUserName(),
+        dsConfig.getPassword(), dsConfig.getDriver(), dsConfig.getDatabaseUrl());
+
+    return getMetadata(dataSource, dsConfig.getQuery(), key);
+  }
+
+  @VisibleForTesting
+  protected String getKey(File file) {
+    return Splitter.on(".").split(file.getName()).iterator().next();
+  }
+
+  @VisibleForTesting
+  protected Metadata getMetadata(DataSource dataSource, String query, String key)
+      throws MetExtractionException {
+    String sqlQuery = String.format(query, key);
+
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+      rs = statement.executeQuery(sqlQuery);
+
+      return getMetadata(rs);
+    } catch (SQLException e) {
+      throw new MetExtractionException(
+          String.format("Failed to get metadaata for key '%s'", key), e);
+    } finally {
+      try { conn.close(); } catch (Exception e) { /* ignore */ }
+      try { statement.close(); } catch (Exception e) { /* ignore */ }
+      try { rs.close(); } catch (Exception e) { /* ignore */ }
+    }
+  }
+
+  private Metadata getMetadata(ResultSet rs) throws SQLException {
+    Metadata metadata = new Metadata();
+    if (rs.next()) {
+      for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
+        String metKey = rs.getMetaData().getColumnName(i+1);
+        String metVal = rs.getString(i+1);
+        metadata.addMetadata(metKey, metVal);
+      }
+    } else {
+      throw new SQLException("Failed to find metadata for result set");
+    }
+    return metadata;
+  }
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/DataSourceMetExtractorConfig.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/DataSourceMetExtractorConfig.java
new file mode 100644
index 0000000..ba8ba67
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/DataSourceMetExtractorConfig.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.metadata.extractors;
+
+// JDK imports
+import java.util.Properties;
+
+// OODT imports
+import org.apache.oodt.cas.metadata.MetExtractorConfig;
+
+/**
+ * MetExtractorConfig which loads configuration from a Java Property file.  Expects given keys
+ * to be set and provides easy read methods for those keys.
+ *
+ * @author bfoster@apache.org (Brian Foster)
+ */
+public class DataSourceMetExtractorConfig extends Properties implements MetExtractorConfig {
+
+  private static final long serialVersionUID = -437948882353764454L;
+
+  private static final String QUERY_KEY =
+      "org.apache.oodt.cas.metadata.extractors.datasource.query";
+  private static final String DATABASE_URL_KEY =
+      "org.apache.oodt.cas.metadata.extractors.datasource.db.url";
+  private static final String DRIVER_KEY =
+      "org.apache.oodt.cas.metadata.extractors.datasource.driver";
+  private static final String USER_NAME_KEY =
+      "org.apache.oodt.cas.metadata.extractors.datasource.username";
+  private static final String PASSWORD_KEY =
+      "org.apache.oodt.cas.metadata.extractors.datasource.password";
+
+  public String getQuery() {
+    return getProperty(QUERY_KEY);
+  }
+
+  public String getDatabaseUrl() {
+    return getProperty(DATABASE_URL_KEY);
+  }
+
+  public String getDriver() {
+    return getProperty(DRIVER_KEY);
+  }
+
+  public String getUserName() {
+    return getProperty(USER_NAME_KEY);
+  }
+
+  public String getPassword() {
+    return getProperty(PASSWORD_KEY);
+  }
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/DataSourceMetExtractorConfigReader.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/DataSourceMetExtractorConfigReader.java
new file mode 100644
index 0000000..c0c6bb2
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/DataSourceMetExtractorConfigReader.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.metadata.extractors;
+
+// JDK imports
+import java.io.File;
+
+// OODT imports
+import org.apache.oodt.cas.metadata.MetExtractorConfigReader;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractorConfigReaderException;
+
+/**
+ * {@link MetExtractorConfigReader} which reads configuration from a Java Properties file.
+ *
+ * @author bfoster@apache.org (Brian Foster)
+ */
+public class DataSourceMetExtractorConfigReader implements MetExtractorConfigReader {
+
+  @Override
+  public DataSourceMetExtractorConfig parseConfigFile(File configFile)
+      throws MetExtractorConfigReaderException {
+    try {
+      DataSourceMetExtractorConfig config = new DataSourceMetExtractorConfig();
+      config.load(configFile.toURI().toURL().openStream());
+      return config;
+    } catch (Exception e) {
+      throw new MetExtractorConfigReaderException(
+          String.format("Failed to parse '%s'", configFile), e);
+    }
+  }
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternConfigReader.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternConfigReader.java
new file mode 100644
index 0000000..c770763
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternConfigReader.java
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.MetExtractorConfig;
+import org.apache.oodt.cas.metadata.MetExtractorConfigReader;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractorConfigReaderException;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Vector;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Reader that reads {@link ExternalMetExtractorConfig}s from an XML file.
+ * </p>.
+ */
+public final class ExternConfigReader implements MetExtractorConfigReader,
+        ExternMetExtractorMetKeys, ExternConfigReaderMetKeys {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.MetExtractorConfigReader#parseConfigFile(java.io.File)
+     */
+    public MetExtractorConfig parseConfigFile(File file)
+            throws MetExtractorConfigReaderException {
+        try {
+            Document doc = XMLUtils.getDocumentRoot(new FileInputStream(file));
+
+            ExternalMetExtractorConfig config = new ExternalMetExtractorConfig();
+            Element docElem = doc.getDocumentElement();
+            Element execElement = XMLUtils.getFirstElement(EXEC_TAG, docElem);
+            config.setWorkingDirPath(PathUtils.replaceEnvVariables(execElement
+                    .getAttribute(WORKING_DIR_ATTR)));
+            String metFileExt = PathUtils.replaceEnvVariables(execElement
+                    .getAttribute(MET_FILE_EXT_ATTR));
+            if (!metFileExt.equals(""))
+                config.setMetFileExt(metFileExt);
+            Element binPathElem = XMLUtils.getFirstElement(
+                    EXTRACTOR_BIN_PATH_TAG, execElement);
+            String binPath = XMLUtils.getSimpleElementText(binPathElem);
+            if (Boolean.valueOf(binPathElem.getAttribute(ENV_REPLACE_ATTR))
+                    .booleanValue()) {
+                binPath = PathUtils.replaceEnvVariables(binPath);
+            }
+
+            // make sure to do path replacement on binPath because it's always
+            // going
+            // to be
+            // a path
+            binPath = binPath.replaceAll("^\\s+", "").replaceAll("\\s+$", "").replaceAll("\\s", "\\\\ ");
+
+            config.setExtractorBinPath(binPath);
+
+            Element argsElem = XMLUtils.getFirstElement(ARGS_TAG, execElement);
+            if (argsElem != null) {
+                NodeList argNodes = argsElem.getElementsByTagName(ARG_TAG);
+
+                if (argNodes != null && argNodes.getLength() > 0) {
+                    Vector argVector = new Vector();
+                    for (int i = 0; i < argNodes.getLength(); i++) {
+                        Element argElem = (Element) argNodes.item(i);
+                        String argStr = null;
+                        if (Boolean.valueOf(
+                                argElem.getAttribute(IS_DATA_FILE_ATTR)
+                                        .toLowerCase()).booleanValue())
+                            argStr = DATA_FILE_PLACE_HOLDER;
+                        else if (Boolean.valueOf(
+                                argElem.getAttribute(IS_MET_FILE_ATTR)
+                                        .toLowerCase()).booleanValue())
+                            argStr = MET_FILE_PLACE_HOLDER;
+                        else
+                            argStr = XMLUtils.getSimpleElementText(argElem);
+
+                        String appendExt = null;
+                        if (!(appendExt = argElem.getAttribute(APPEND_EXT_ATTR))
+                                .equals(""))
+                            argStr += "." + appendExt;
+
+                        if (Boolean.valueOf(
+                                argElem.getAttribute(ENV_REPLACE_ATTR))
+                                .booleanValue()) {
+                            argStr = PathUtils.replaceEnvVariables(argStr);
+                        }
+
+                        if (Boolean.valueOf(argElem.getAttribute(IS_PATH_ATTR))
+                                .booleanValue()) {
+                            argStr = argStr.replaceAll("\\s", "\\\\ ");
+                        }
+
+                        argVector.add(argStr);
+                    }
+
+                    config.setArgList((String[]) argVector
+                            .toArray(new String[] {}));
+                }
+            }
+
+            return config;
+        } catch (Exception e) {
+            throw new MetExtractorConfigReaderException("Failed to parser '"
+                    + file + "' : " + e.getMessage());
+        }
+
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternConfigReaderMetKeys.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternConfigReaderMetKeys.java
new file mode 100644
index 0000000..d638977
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternConfigReaderMetKeys.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Met keys for the {@link ExternConfigReader}
+ * </p>.
+ */
+public interface ExternConfigReaderMetKeys {
+
+    public static final String EXEC_TAG = "exec";
+
+    public static final String WORKING_DIR_ATTR = "workingDir";
+
+    public static final String MET_FILE_EXT_ATTR = "metFileExt";
+
+    public static final String EXTRACTOR_BIN_PATH_TAG = "extractorBinPath";
+
+    public static final String ENV_REPLACE_ATTR = "envReplace";
+
+    public static final String ARGS_TAG = "args";
+
+    public static final String ARG_TAG = "arg";
+
+    public static final String IS_DATA_FILE_ATTR = "isDataFile";
+
+    public static final String IS_MET_FILE_ATTR = "isMetFile";
+
+    public static final String APPEND_EXT_ATTR = "appendExt";
+
+    public static final String IS_PATH_ATTR = "isPath";
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternMetExtractor.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternMetExtractor.java
new file mode 100644
index 0000000..095f3d2
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternMetExtractor.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+
+//APACHE imports
+import org.apache.commons.lang.StringUtils;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.oodt.cas.metadata.extractors.CmdLineMetExtractor;
+import org.apache.oodt.commons.exec.ExecUtils;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Runs an external {@link MetExtractor} that is a command line program to
+ * extract {@link Metadata} from {@link Product} files.
+ * </p>.
+ */
+public class ExternMetExtractor extends CmdLineMetExtractor implements
+        ExternMetExtractorMetKeys {
+
+    private static ExternConfigReader reader = new ExternConfigReader();
+
+    public ExternMetExtractor() throws InstantiationException {
+        super(reader);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.AbstractMetExtractor#extractMetadata(java.io.File)
+     */
+    public Metadata extrMetadata(File file) throws MetExtractionException {
+
+        // determine working directory
+        String workingDirPath = ((ExternalMetExtractorConfig) this.config)
+                .getWorkingDirPath();
+        if (workingDirPath == null || workingDirPath.equals(""))
+            workingDirPath = file.getParentFile().getAbsolutePath();
+        File workingDir = new File(workingDirPath);
+
+        // determine met file path
+        String metFileName = file.getName() + "."
+                + ((ExternalMetExtractorConfig) this.config).getMetFileExt();
+        String metFilePath = workingDir.getAbsolutePath() + "/" + metFileName;
+        File metFile = new File(metFilePath);
+
+        // get exe args
+        List commandLineList = new Vector();
+        commandLineList.add(((ExternalMetExtractorConfig) this.config)
+                .getExtractorBinPath());
+        if (((ExternalMetExtractorConfig) this.config).getArgList() != null
+                && ((ExternalMetExtractorConfig) this.config).getArgList().length > 0)
+            commandLineList.addAll(Arrays
+                    .asList(((ExternalMetExtractorConfig) this.config)
+                            .getArgList()));
+        String[] commandLineArgs = new String[commandLineList.size()];
+        for (int i = 0; i < commandLineList.size(); i++)
+            commandLineArgs[i] = StringUtils.replace(StringUtils.replace(
+                    (String) commandLineList.get(i), MET_FILE_PLACE_HOLDER,
+                    metFilePath), DATA_FILE_PLACE_HOLDER, file
+                    .getAbsolutePath());
+
+        // generate metadata file
+        LOG.log(Level.INFO, "Generating met file for product file: ["
+                + file.getAbsolutePath() + "]");
+        int status = -1;
+        try {
+            LOG.log(Level.INFO, "Executing command line: ["
+                    + ExecUtils.printCommandLine(commandLineArgs)
+                    + "] with workingDir: [" + workingDir
+                    + "] to extract metadata");
+            status = ExecUtils.callProgram(commandLineArgs, workingDir);
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException running met extraction: commandLine: ["
+                            + ExecUtils.printCommandLine(commandLineArgs)
+                            + "]: Message: " + e.getMessage());
+            return null;
+        }
+
+        if (status != 0) {
+            throw new MetExtractionException(
+                    "Exit status for met extraction not 0");
+        } else if (!metFile.exists()) {
+            throw new MetExtractionException(
+                    "Met extractor failed to create metadata file");
+        } else {
+            LOG.log(Level.INFO, "Met extraction successful for product file: ["
+                    + file.getAbsolutePath() + "]");
+            try {
+                SerializableMetadata sm = new SerializableMetadata("UTF-8",
+                        false);
+                sm.loadMetadataFromXmlStream(new FileInputStream(metFile));
+                return sm;
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new MetExtractionException(e.getMessage());
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        processMain(args, new ExternMetExtractor());
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternMetExtractorMetKeys.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternMetExtractorMetKeys.java
new file mode 100644
index 0000000..85702dd
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternMetExtractorMetKeys.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+/**
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Met keys for the {@link ExternMetExtractor}
+ * </p>.
+ */
+public interface ExternMetExtractorMetKeys {
+
+    public static final String DATA_FILE_PLACE_HOLDER = "<DATA_FILE_PLACE_HOLDER>";
+
+    public static final String MET_FILE_PLACE_HOLDER = "<MET_FILE_PLACE_HOLDER>";
+
+    public static final String DEFAULT_MET_FILE_EXTENSION = "met";
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternalMetExtractorConfig.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternalMetExtractorConfig.java
new file mode 100644
index 0000000..91d3419
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ExternalMetExtractorConfig.java
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.MetExtractorConfig;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Configuration file for the {@link ExternMetExtractor}.
+ * </p>.
+ */
+public class ExternalMetExtractorConfig implements MetExtractorConfig,
+        ExternMetExtractorMetKeys {
+
+    private String workingDirPath;
+
+    private String extractorBinPath;
+
+    private String metFileExt;
+
+    private String[] argList;
+
+    public ExternalMetExtractorConfig() {
+        this(null, null, null);
+    }
+
+    public ExternalMetExtractorConfig(String workingDirPath,
+            String extractorBinPath, String[] argList) {
+        this.workingDirPath = workingDirPath;
+        this.extractorBinPath = extractorBinPath;
+        this.argList = argList;
+        this.metFileExt = DEFAULT_MET_FILE_EXTENSION;
+    }
+
+    /**
+     * @return the argList
+     */
+    public String[] getArgList() {
+        return argList;
+    }
+
+    /**
+     * @param argList
+     *            the argList to set
+     */
+    public void setArgList(String[] argList) {
+        this.argList = argList;
+    }
+
+    /**
+     * @return the extractorBinPath
+     */
+    public String getExtractorBinPath() {
+        return extractorBinPath;
+    }
+
+    /**
+     * @param extractorBinPath
+     *            the extractorBinPath to set
+     */
+    public void setExtractorBinPath(String extractorBinPath) {
+        this.extractorBinPath = extractorBinPath;
+    }
+
+    /**
+     * @return the workingDirPath
+     */
+    public String getWorkingDirPath() {
+        return workingDirPath;
+    }
+
+    /**
+     * @param workingDirPath
+     *            the workingDirPath to set
+     */
+    public void setWorkingDirPath(String workingDirPath) {
+        this.workingDirPath = workingDirPath;
+    }
+
+    /**
+     * @return the metFileExt
+     */
+    public String getMetFileExt() {
+        return metFileExt;
+    }
+
+    /**
+     * @param metFileExt
+     *            the metFileExt to set
+     */
+    public void setMetFileExt(String metFileExt) {
+        this.metFileExt = metFileExt;
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/FilenameTokenConfig.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/FilenameTokenConfig.java
new file mode 100644
index 0000000..815023d
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/FilenameTokenConfig.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.text.SimpleDateFormat;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.MetExtractorConfig;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import static org.apache.oodt.cas.metadata.extractors.FilenameTokenExtractorMetKeys.*;
+import org.apache.oodt.pcs.input.PGEConfigFileException;
+import org.apache.oodt.pcs.input.PGEConfigFileReader;
+import org.apache.oodt.pcs.input.PGEConfigurationFile;
+import org.apache.oodt.pcs.input.PGEGroup;
+import org.apache.oodt.pcs.input.PGEScalar;
+import org.apache.oodt.pcs.input.PGEVector;
+
+/**
+ * 
+ * Wraps a {@link PGEConfigurationFile} as a {@link MetExtractorConfig}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class FilenameTokenConfig implements MetExtractorConfig {
+
+  private PGEConfigurationFile conf;
+
+  public FilenameTokenConfig() {
+    this.conf = null;
+  }
+
+  public FilenameTokenConfig(PGEConfigurationFile conf) {
+    this.conf = conf;
+  }
+
+  public void setConfig(String confFilePath) throws FileNotFoundException,
+      PGEConfigFileException {
+    this.conf = new PGEConfigFileReader().read(new FileInputStream(new File(
+        confFilePath)));
+  }
+
+  public SimpleDateFormat getDateFormatter() {
+    return new SimpleDateFormat(this.conf.getPgeSpecificGroups().get(
+        PRODUCTION_DATE_TIME_GROUP).getScalar(DATETIME_SCALAR).getValue());
+  }
+
+  public boolean hasTokenNameList() {
+    return this.conf.getPgeSpecificGroups().get(TOKEN_LIST_GROUP) != null;
+  }
+
+  public String getTokenDelimeterScalar() {
+    return this.conf.getPgeSpecificGroups().get(TOKEN_LIST_GROUP).getScalar(
+        TOKEN_DELIMETER_SCALAR).getValue();
+  }
+
+  public List<String> getTokenMetKeyNames() {
+    return (List<String>) (List<?>) this.conf.getPgeSpecificGroups().get(
+        TOKEN_LIST_GROUP).getVector(TOKEN_MET_KEYS_VECTOR).getElements();
+  }
+
+  public Metadata getSubstringOffsetMet(File file) {
+    PGEGroup substrOffsetGroup = this.conf.getPgeSpecificGroups().get(
+        SUBSTRING_OFFSET_GROUP);
+    Metadata met = new Metadata();
+    if (substrOffsetGroup == null)
+      return met;
+    String filename = file.getName();
+
+    for (PGEVector vec : substrOffsetGroup.getVectors().values()) {
+      String metKeyName = vec.getName();
+      int offset = Integer.valueOf((String) vec.getElements().get(0)) - 1;
+      int length = Integer.valueOf((String) vec.getElements().get(1));
+      String metVal = filename.substring(offset, offset + length).trim();
+      met.addMetadata(metKeyName, metVal);
+    }
+
+    return met;
+  }
+
+  public Metadata getCommonMet() {
+    PGEGroup commonMetGroup = this.conf.getPgeSpecificGroups().get(
+        COMMON_METADATA_GROUP);
+    Metadata met = new Metadata();
+    for (String scalarName : commonMetGroup.getScalars().keySet()) {
+      PGEScalar scalar = commonMetGroup.getScalar(scalarName);
+      met.addMetadata(scalar.getName(), PathUtils.replaceEnvVariables(scalar
+          .getValue()));
+    }
+
+    for (String vecName : commonMetGroup.getVectors().keySet()) {
+      PGEVector vec = commonMetGroup.getVector(vecName);
+      for (String val : (List<String>) (List<?>) vec.getElements()) {
+        met.addMetadata(vecName, PathUtils.replaceEnvVariables(val));
+      }
+    }
+
+    return met;
+  }
+
+  /**
+   * @return the conf
+   */
+  public PGEConfigurationFile getConf() {
+    return conf;
+  }
+
+  /**
+   * @param conf
+   *          the conf to set
+   */
+  public void setConf(PGEConfigurationFile conf) {
+    this.conf = conf;
+  }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/FilenameTokenConfigReader.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/FilenameTokenConfigReader.java
new file mode 100644
index 0000000..d224681
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/FilenameTokenConfigReader.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.MetExtractorConfig;
+import org.apache.oodt.cas.metadata.MetExtractorConfigReader;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractorConfigReaderException;
+import org.apache.oodt.pcs.input.PGEConfigFileReader;
+import org.apache.oodt.pcs.input.PGEConfigurationFile;
+
+/**
+ * 
+ * Reads in a {@link FilenameTokenConfig} using the {@link PGEConfigFileReader}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class FilenameTokenConfigReader implements MetExtractorConfigReader {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.metadata.MetExtractorConfigReader#parseConfigFile
+   * (java.io.File)
+   */
+  public MetExtractorConfig parseConfigFile(File file)
+      throws MetExtractorConfigReaderException {
+    FilenameTokenConfig conf = new FilenameTokenConfig();
+    PGEConfigFileReader reader = new PGEConfigFileReader();
+    PGEConfigurationFile confFile;
+
+    try {
+      confFile = reader.read(new FileInputStream(file));
+    } catch (Exception e) {
+      throw new MetExtractorConfigReaderException(e.getMessage());
+    }
+
+    conf.setConf(confFile);
+    return conf;
+  }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/FilenameTokenExtractorMetKeys.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/FilenameTokenExtractorMetKeys.java
new file mode 100644
index 0000000..46b24ce
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/FilenameTokenExtractorMetKeys.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+/**
+ * 
+ * Met keys for the {@link FilenameTokenMetExtractor}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface FilenameTokenExtractorMetKeys {
+  
+  public static final String TIME_FORMAT_STRING_SCALAR = "TimeFormatString";
+  
+  public static final String SUBSTRING_OFFSET_GROUP = "SubstringOffsetGroup";
+    
+  public static final String TOKEN_LIST_GROUP = "TokenNameListGroup";
+  
+  public static final String TOKEN_DELIMETER_SCALAR = "Delimeter";
+
+  public static final String TOKEN_MET_KEYS_VECTOR = "TokenMetKeys";
+
+  public static final String PRODUCTION_DATE_TIME_GROUP = "ProductionDateTimeGroup";
+
+  public static final String DATETIME_SCALAR = "DateTimeFormat";
+
+  public static final String COMMON_METADATA_GROUP = "CommonMetadata";  
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/FilenameTokenMetExtractor.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/FilenameTokenMetExtractor.java
new file mode 100644
index 0000000..092c726
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/FilenameTokenMetExtractor.java
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//JDK imports
+import java.io.File;
+import java.text.ParseException;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.oodt.cas.metadata.extractors.CmdLineMetExtractor;
+import org.apache.oodt.commons.date.DateUtils;
+
+/**
+ * 
+ * Extracts out {@link Metadata} using the {@link File#getName()} and a
+ * {@link FilenameTokenConfig} to specify what pieces of the filename map to
+ * particular Metadata key names.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class FilenameTokenMetExtractor extends CmdLineMetExtractor implements
+    FilenameTokenExtractorMetKeys {
+
+  private static final Logger LOG = Logger
+      .getLogger(FilenameTokenMetExtractor.class.getName());
+
+  /**
+   * Default constructor.
+   */
+  public FilenameTokenMetExtractor() {
+    super(new FilenameTokenConfigReader());
+    // TODO Auto-generated constructor stub
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.metadata.AbstractMetExtractor#extrMetadata(java.io
+   * .File)
+   */
+  @Override
+  protected Metadata extrMetadata(File file) throws MetExtractionException {
+    Metadata met = new Metadata();
+    String filename = file.getName();
+    if (((FilenameTokenConfig) this.config).hasTokenNameList()) {
+      List<String> metKeyTokens = ((FilenameTokenConfig) this.config)
+          .getTokenMetKeyNames();
+      String[] filenameToks = filename.split("\\.")[0]
+          .split(((FilenameTokenConfig) this.config).getTokenDelimeterScalar());
+      for (int i = 0; i < filenameToks.length; i++) {
+        String keyName = metKeyTokens.get(i);
+        String keyVal = filenameToks[i];
+        if (keyName.equals("ProductionDateTime")) {
+          Calendar cal = GregorianCalendar.getInstance();
+          try {
+            cal.setTime(((FilenameTokenConfig) this.config).getDateFormatter()
+                .parse(keyVal));
+          } catch (ParseException e) {
+            throw new MetExtractionException(e.getMessage());
+          }
+          keyVal = DateUtils.toString(cal);
+        }
+
+        met.addMetadata(keyName, keyVal);
+      }
+    }
+
+    Metadata commonMet = ((FilenameTokenConfig) this.config).getCommonMet();
+    met.addMetadata(commonMet.getHashtable());
+    met.addMetadata(((FilenameTokenConfig) this.config)
+        .getSubstringOffsetMet(file));
+
+    met.addMetadata("Filename", file.getName());
+    met.addMetadata("FileLocation", file.getParentFile().getAbsolutePath());
+    return met;
+  }
+
+  public static void main(String[] args) throws Exception {
+    processMain(args, new FilenameTokenMetExtractor());
+  }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/MetReaderConfig.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/MetReaderConfig.java
new file mode 100644
index 0000000..9dba66f
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/MetReaderConfig.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//JDK imports
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.MetExtractorConfig;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class MetReaderConfig extends Properties implements MetExtractorConfig {
+
+	private static final long serialVersionUID = 8141507075338698680L;
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/MetReaderConfigReader.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/MetReaderConfigReader.java
new file mode 100644
index 0000000..bd023ac
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/MetReaderConfigReader.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.MetExtractorConfig;
+import org.apache.oodt.cas.metadata.MetExtractorConfigReader;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractorConfigReaderException;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Config file reader class for {@link MetReaderExtractor}
+ * </p>.
+ */
+public class MetReaderConfigReader implements MetExtractorConfigReader {
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.apache.oodt.cas.metadata.MetExtractorConfigReader#parseConfigFile(java.io.File)
+	 */
+	public MetExtractorConfig parseConfigFile(File configFile)
+			throws MetExtractorConfigReaderException {
+		try {
+			MetReaderConfig config = new MetReaderConfig();
+			config.load(new FileInputStream(configFile));
+			return config;
+		} catch (Exception e) {
+			throw new MetExtractorConfigReaderException(
+					"Failed to read config file " + configFile + " : "
+							+ e.getMessage());
+		}
+	}
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/MetReaderExtractor.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/MetReaderExtractor.java
new file mode 100644
index 0000000..fd6ce2f
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/MetReaderExtractor.java
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.logging.Level;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.oodt.cas.metadata.extractors.CmdLineMetExtractor;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Met Extractor that assumes that the .met file has already been generated.
+ * This extractor assumes the presence of the first parameter in
+ * {@link #extractMetadata(File, File)}, File.getAbsolutePath()+".met"
+ * </p>.
+ */
+public class MetReaderExtractor extends CmdLineMetExtractor {
+
+    /* the extension (e.g., .met) for the met file */
+    private String metFileExt;
+
+    public static final String DEFAULT_MET_FILE_EXT = "met";
+
+    protected static MetReaderConfigReader reader = new MetReaderConfigReader();
+
+    /**
+     * Default Constructor
+     */
+    public MetReaderExtractor() {
+        this(DEFAULT_MET_FILE_EXT);
+    }
+
+    /**
+     * Constructs a new MetReaderExtractor that looks for met files with the
+     * given <code>metFileExt</code>.
+     * 
+     * @param metFileExt
+     *            The met file extension.
+     */
+    public MetReaderExtractor(String metFileExt) {
+        super(reader);
+        this.metFileExt = metFileExt;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.metadata.AbstractMetExtractor#extractMetadata(java.io.File)
+     */
+    public Metadata extrMetadata(File file) throws MetExtractionException {
+        // don't really need conf file, we're assuming that there is an existing
+        // .met file
+        // for the given product file
+    	String extension = this.metFileExt;
+    	if (this.config != null)
+    		extension = ((MetReaderConfig) this.config)
+				.getProperty(
+						"org.apache.oodt.cas.metadata.extractors.MetReader.metFileExt",
+						this.metFileExt);
+        String metFileFullPath = file.getAbsolutePath() + "." + extension;
+    	LOG.log(Level.INFO, "Reading metadata from " + metFileFullPath);
+        // now read the met file and return it
+        if (!new File(metFileFullPath).exists()) {
+            throw new MetExtractionException("Met file: [" + metFileFullPath
+                    + "] does not exist: failing!");
+        }
+
+        try {
+            SerializableMetadata met = new SerializableMetadata("UTF-8", false);
+            met.loadMetadataFromXmlStream(new FileInputStream(metFileFullPath));
+            return met;
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new MetExtractionException(e.getMessage());
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        processMain(args, new MetReaderExtractor());
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ParentKeyDataSourceMetExtractor.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ParentKeyDataSourceMetExtractor.java
new file mode 100644
index 0000000..d43bb98
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ParentKeyDataSourceMetExtractor.java
@@ -0,0 +1,78 @@
+package org.apache.oodt.cas.metadata.extractors;
+
+import java.io.File;
+import java.util.List;
+
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
+
+/**
+ * Supports data source key look via parent key if files key is no good.
+ * 
+ * Expected file name:
+ * <parent_key>-<primary_key>.<post_fix>
+ * 
+ * @author bfoster@apache.com (Brian Foster)
+ */
+public class ParentKeyDataSourceMetExtractor extends DataSourceMetExtractor {
+
+  private String key;
+  
+  @Override
+  protected Metadata extrMetadata(File file) throws MetExtractionException {
+    try {
+      key = getPrimaryKey(file);
+      return super.extrMetadata(file);
+    } catch (MetExtractionException e) {
+      key = getParentKey(file);
+      if (key != null) {
+        return super.extrMetadata(file);
+      } else {
+        throw e;
+      }
+    }
+  }
+
+  @VisibleForTesting
+  protected String getKey(File file) {
+    return key;
+  }
+
+  private String getPrimaryKey(File file) {
+    String key = getKeyAtIndex(file, Index.PRIMARY);
+    return key == null ? super.getKey(file) : key;
+  }
+
+  private String getParentKey(File file) {
+    return getKeyAtIndex(file, Index.PARENT);
+  }
+
+  private String getKeyAtIndex(File file, Index index) {
+    String key = super.getKey(file);
+    List<String> splitKey = Lists.newArrayList(Splitter.on("_").split(key));
+    if (splitKey.size() == 2) {
+      return splitKey.get(index.getNumeric());
+    } else {
+      return null;
+    }
+  }
+
+  private enum Index {
+    PRIMARY(1),
+    PARENT(0);
+    
+    private int index;
+
+    Index(int index) {
+      this.index = index;
+    }
+
+    public int getNumeric() {
+      return index;
+    }
+  }
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ProdTypePatternMetExtractor.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ProdTypePatternMetExtractor.java
new file mode 100644
index 0000000..cc5b1cd
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/ProdTypePatternMetExtractor.java
@@ -0,0 +1,251 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.metadata.extractors;
+
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractorConfigReaderException;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Assigns a ProductType based on a filename pattern, while simultaneously assigning values to metadata elements
+ * embedded in the filename pattern.
+ * <p/>
+ * Suppose I have files in the staging area ready to be ingested. These files usually have information encoded into the
+ * filename in order to distinguish the contents of one file from other files. For example book-1234567890.txt might be
+ * the contents of a book with ISBN 1234567890. Or page-1234567890-12.txt might be the text on page 12 of book with ISBN
+ * 1234567890.
+ * <p/>
+ * It would be useful to generate metadata from the information encoded in the filename (think: filename => metadata).
+ * The {@link ProdTypePatternMetExtractor} allows this in a flexible manner using regular expressions. Let's take a look
+ * at the config file for this met extractor.
+ * <p/>
+ * <pre>
+ * product-type-patterns.xml
+ *
+ * {@code
+ * <config>
+ *   <!-- <element> MUST be defined before <product-type> so their patterns can be resolved -->
+ *   <!-- name MUST be an element defined in elements.xml (also only upper and lower case alpha chars) -->
+ *   <!-- regexp MUST be valid input to java.util.regex.Pattern.compile() -->
+ *   <element name="ISBN" regexp="[0-9]{10}"/>
+ *   <element name="Page" regexp="[0-9]*"/>
+ *
+ *   <!-- name MUST be a ProductType name defined in product-types.xml -->
+ *   <!-- metadata elements inside brackets MUST be mapped to the ProductType,
+ *        as defined in product-type-element-map.xml -->
+ *   <product-type name="Book" template="book-[ISBN].txt"/>
+ *   <product-type name="BookPage" template="page-[ISBN]-[Page].txt"/>
+ * </config>
+ * }
+ * </pre>
+ * <p/>
+ * <p/>
+ * This file defines a regular expression for the "ISBN" metadata element, in this case, a 10-digit number. Also, the
+ * "Page" metadata element is defined as a sequence of 0 or more digits.
+ * <p/>
+ * Next, the file defines a filename pattern for the "Book" product type. The pattern is compiled into a regular
+ * expression, substituting the previously defined regexes as capture groups. For example, "book-[ISBN].txt" compiles to
+ * "book-([0-9]{10}).txt", and the ISBN met element is assigned to capture group 1. When the filename matches this
+ * pattern, 2 metadata assignments occur: (1) the ISBN met element is set to the matched regex group, and (2) the
+ * ProductType met element is set to "Book".
+ * <p/>
+ * Similarly, the second pattern sets ISBN, Page, and ProductType for files matching "page-([0-9]{10})-([0-9]*).txt".
+ * <p/>
+ * This achieves several things: <ol> <li>assigning met elements based on regular expressions</li> <li>assigning product
+ * type based on easy-to-understand pattern with met elements clearly indicated</li> <li>reuse of met element regular
+ * expressions</li> </ol>
+ * <p/>
+ * Differences from {@link FilenameTokenMetExtractor}:
+ * <ol>
+ *     <li>Allows dynamic length metadata (does not rely on offset and length of metadata)</li>
+ *     <li>Assigns ProductType</li>
+ * </ol>
+ * <p/>
+ * Differences from {@link org.apache.oodt.cas.crawl.AutoDetectProductCrawler}:
+ * <ol>
+ *     <li>Does not require definition of custom MIME type and MIME-type regex. Really, all you want is to assign a
+ *     ProductType, rather than indirectly assigning a custom MIME type that maps to a Product Type.</li>
+ * </ol>
+ * <p/>
+ * Differences from {@link org.apache.oodt.cas.filemgr.metadata.extractors.examples.FilenameRegexMetExtractor}:
+ * <ol>
+ *     <li>Assigns ProductType. FilenameRegexMetExtractor runs after ProductType is already determined.</li>
+ *     <li>Runs on the client-side (crawler). FilenameRegexMetExtractor runs on the server-side (filemgr).</li>
+ *     <li>Different patterns for different ProductTypes. FilenameRegexMetExtractor config applies the same pattern to
+ *     all files.</li>
+ * </ol>
+ * <p/>
+ * Prerequisites:
+ * <ol>
+ *     <li>{@code <element>} tag occurs before {@code <product-type>} tag</li>
+ *     <li>{@code <element> @name} attribute <strong>MUST</strong> be defined in FileManager policy elements.xml</li>
+ *     <li>{@code <element> @regexp} attribute <strong>MUST</strong> be valid input to
+ *     {@link java.util.regex.Pattern#compile(String)}</li>
+ *     <li>{@code <product-type> @name} attribute <strong>MUST</strong> be a ProductType name (not ID) defined in
+ *     product-types.xml</li>
+ *     <li>met elements used in {@code <product-type> @template} attribute <strong>MUST</strong> be
+ *     mapped to the ProductType, as defined in product-type-element-map.xml</li>
+ * </ol>
+ * <p/>
+ * <strong>Words of Caution</strong>
+ * <ul>
+ *     <li><strong>Does not support nested met elements.</strong></li>
+ *     <li><strong>Each pattern should map to one product type.</strong> Watch out for similar patterns. Don't do this:
+ * <pre>
+ * {@code
+ * <element name="Page" regexp="[0-9]*"/>
+ * <element name="Chapter" regexp="[0-9]*"/>
+ *
+ * <product-type name="Page" template="data-[Page].txt"/>
+ * <product-type name="Chapter" template="data-[Chapter].txt"/>
+ * }</pre>
+ * Instead, encode the product type information into the filename, for example:
+ * <pre>
+ * {@code
+ * <element name="Page" regexp="[0-9]*"/>
+ * <element name="Chapter" regexp="[0-9]*"/>
+ *
+ * <product-type name="Page" template="page-[Page].txt"/>
+ * <product-type name="Chapter" template="chapter-[Chapter].txt"/>
+ * }</pre>
+ * </li>
+ * </ul>
+ *
+ * @author rickdn (Ricky Nguyen)
+ */
+public class ProdTypePatternMetExtractor extends CmdLineMetExtractor {
+
+    static class ConfigReader extends AbstractSAXConfigReader {
+        private static final String ELEMENT_TAG = "element";
+        private static final String ELEMENT_NAME_ATTR = "name";
+        private static final String ELEMENT_REGEXP_ATTR = "regexp";
+        private static final String PRODUCT_TYPE_TAG = "product-type";
+        private static final String PRODUCT_TYPE_NAME_ATTR = "name";
+        private static final String PRODUCT_TYPE_TEMPLATE_ATTR = "template";
+        private static final Pattern MET_TOKEN = Pattern.compile("\\[([A-Za-z]*)\\]");
+
+        /*
+         * full file name reg exp => prod type
+         */
+        private final Map<Pattern, String> prodTypePatterns = new HashMap<Pattern, String>();
+
+        /*
+         * prod type => list of met elements in the file name
+         */
+        private final Map<String, List<String>> prodTypeElements = new HashMap<String, List<String>>();
+
+        /*
+         * met elements => element reg exp patterns
+         */
+        private final Map<String, Pattern> elementPatterns = new HashMap<String, Pattern>();
+
+
+        Map<Pattern, String> getProdTypePatterns() {
+            return prodTypePatterns;
+        }
+
+        Map<String, List<String>> getProdTypeElements() {
+            return prodTypeElements;
+        }
+
+        void addProductType(String id, String template) {
+            template = template.replaceAll("\\.", "\\\\.");
+            Matcher m = MET_TOKEN.matcher(template);
+            List<String> elemList = prodTypeElements.get(id);
+            if (elemList == null) {
+                elemList = new ArrayList<String>();
+                prodTypeElements.put(id, elemList);
+            }
+            String newTemplate = template;
+            while (m.find()) {
+                String elem = m.group(1);
+                String regex = elementPatterns.get(elem).toString();
+                newTemplate = newTemplate.replaceAll("\\[" + elem + "\\]", "(" + regex + ")");
+                elemList.add(elem);
+            }
+            prodTypePatterns.put(Pattern.compile(newTemplate), id);
+        }
+
+        void addElement(String name, String regexp) {
+            elementPatterns.put(name, Pattern.compile(regexp));
+        }
+
+        @Override
+        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+            if (qName.equals(ELEMENT_TAG)) {
+                String name = attributes.getValue(ELEMENT_NAME_ATTR);
+                String regexp = attributes.getValue(ELEMENT_REGEXP_ATTR);
+                addElement(name, regexp);
+            } else if (qName.equals(PRODUCT_TYPE_TAG)) {
+                String id = attributes.getValue(PRODUCT_TYPE_NAME_ATTR);
+                String template = attributes.getValue(PRODUCT_TYPE_TEMPLATE_ATTR);
+                addProductType(id, template);
+            }
+        }
+
+        @Override
+        public AbstractSAXConfigReader parseConfigFile(File configFile) throws MetExtractorConfigReaderException {
+            // reset internal state whenever parsing a new config file
+            prodTypePatterns.clear();
+            prodTypeElements.clear();
+            elementPatterns.clear();
+            return super.parseConfigFile(configFile);
+        }
+    }
+
+    private static final String PRODUCT_TYPE_MET_KEY = "ProductType";
+
+    public ProdTypePatternMetExtractor() {
+        super(new ConfigReader());
+    }
+
+    @Override
+    protected Metadata extrMetadata(File file) throws MetExtractionException {
+        Metadata met = new Metadata();
+        ConfigReader mConfig = (ConfigReader) config;
+
+        for (Pattern p : mConfig.getProdTypePatterns().keySet()) {
+            Matcher m = p.matcher(file.getName());
+            if (m.matches()) {
+                String prodType = mConfig.getProdTypePatterns().get(p);
+                met.addMetadata(PRODUCT_TYPE_MET_KEY, prodType);
+                List<String> elemList = mConfig.getProdTypeElements().get(prodType);
+                for (int i = 0; i < m.groupCount(); i++) {
+                    met.addMetadata(elemList.get(i), m.group(i + 1));
+                }
+            }
+        }
+
+        return met;
+    }
+
+    public static void main(String[] args) throws Exception {
+        processMain(args, new ProdTypePatternMetExtractor());
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/TikaCmdLineMetExtractor.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/TikaCmdLineMetExtractor.java
new file mode 100644
index 0000000..4bba962
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/extractors/TikaCmdLineMetExtractor.java
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.tika.Tika;
+
+/**
+ * @author rverma
+ * @author arni
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Met Extractor that invokes Apache Tika to automatically detect
+ * relevant metadata for a given product.
+ * </p>
+ * .
+ * <p>
+ * To use this extractor, a met extractor config file must be referenced. 
+ * This can take the form of a Java properties file that includes, 
+ * at a minimum, the 'ProductType=...' metadata key specified.
+ * </p>
+ */
+public class TikaCmdLineMetExtractor extends CmdLineMetExtractor {
+
+    private static final Logger LOG = Logger
+            .getLogger(TikaCmdLineMetExtractor.class.getName());
+
+    protected static MetReaderConfigReader reader = 
+            new MetReaderConfigReader();
+
+    public TikaCmdLineMetExtractor() {
+        super(reader);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.oodt.cas.metadata.AbstractMetExtractor#extractMetadata(java
+     * .io.File)
+     */
+    @Override
+    public Metadata extrMetadata(File file) throws MetExtractionException {
+
+        try {
+            org.apache.tika.metadata.Metadata tikaMet = 
+                    new org.apache.tika.metadata.Metadata();
+            Metadata met = new Metadata();
+            InputStream is = new FileInputStream(file);
+
+            // extract met from prod using tika
+            LOG.fine("Invoking tika extractor on file ["
+                    + file.getAbsolutePath() + "]");
+            Tika tika = new Tika();
+            tika.parse(is, tikaMet); // extract metadata
+            tikaMet.add("content", tika.parseToString(file)); // extract content
+
+            LOG.fine("Number of captured tika metadata keys: ["
+                    + tikaMet.names().length + "]");
+
+            // copy tika met into oodt met
+            for (String key : tikaMet.names()) {
+                met.addMetadata(key, tikaMet.get(key));
+                LOG.fine("Added tika met key [" + key + "] with value ["
+                        + met.getMetadata(key) + "]");
+            }
+
+            MetReaderConfig myConfig = (MetReaderConfig) this.config;
+
+            // add config file met
+            Enumeration<Object> configMetKeys = myConfig.keys();
+            while (configMetKeys.hasMoreElements()) {
+                String configMetKey = (String) configMetKeys.nextElement();
+                String configMetKeyVal = (String) myConfig.get(configMetKey);
+
+                met.addMetadata(configMetKey, configMetKeyVal);
+                LOG.fine("Added config file met key [" + configMetKey + 
+                        "] with value [" + met.getMetadata(configMetKeyVal) + "]");
+            }
+
+            return met;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.severe(e.getMessage());
+            throw new MetExtractionException(e.getMessage());
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        processMain(args, new TikaCmdLineMetExtractor());
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/filenaming/NamingConvention.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/filenaming/NamingConvention.java
new file mode 100644
index 0000000..4d6a73d
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/filenaming/NamingConvention.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.metadata.filenaming;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.NamingConventionException;
+
+/**
+ * Interface for renaming files.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public interface NamingConvention {
+
+   public File rename(File file, Metadata metadata)
+         throws NamingConventionException;
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/filenaming/PathUtilsNamingConvention.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/filenaming/PathUtilsNamingConvention.java
new file mode 100644
index 0000000..17e5325
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/filenaming/PathUtilsNamingConvention.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.metadata.filenaming;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.NamingConventionException;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+/**
+ * A {@link NamingConvention} which utilizes {@link PathUtils}.
+ *
+ * @author bfoster (Brian Foster)
+ * @author mattmann (Chris Mattmann)
+ */
+public class PathUtilsNamingConvention implements NamingConvention {
+
+   private String namingConv;
+
+   private Metadata tmpReplaceMet;
+   
+   public PathUtilsNamingConvention(){
+	   this.tmpReplaceMet = new Metadata();
+   }
+   
+   public File rename(File file, Metadata metadata)
+         throws NamingConventionException {
+      try {
+         Validate.notNull(file, "Must specify file");
+         Validate.notNull(metadata, "Must specify metadata");
+
+         File newFile = new File(file.getParentFile(),
+               PathUtils.doDynamicReplacement(namingConv, metadata));
+         if (!file.renameTo(newFile)) {
+            throw new IOException("Renaming file [" + file + "] to [" + newFile
+                  + "] returned false");
+         }
+         return newFile;
+      } catch (Exception e) {
+         throw new NamingConventionException("Failed to renaming file [" + file
+               + "] : " + e.getMessage(), e);
+      }
+   }
+
+   public void setNamingConv(String namingConv) {
+      this.namingConv = namingConv;
+   }
+   
+	public void addTmpReplaceMet(String key, List<String> values) {
+		this.tmpReplaceMet.replaceMetadata(key, values);
+	}
+	
+	public Metadata getTmpReplaceMet() {
+		return this.tmpReplaceMet;
+	}
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/EndsWithComparator.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/EndsWithComparator.java
new file mode 100644
index 0000000..e42459a
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/EndsWithComparator.java
@@ -0,0 +1,52 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.metadata.preconditions;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.exceptions.PreconditionComparatorException;
+import org.apache.oodt.cas.metadata.preconditions.PreConditionComparator;
+
+/**
+ * 
+ * A {@link PreConditionComparator} that checks a file's extension and then
+ * skips extracting metadata from files that don't match this extension.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class EndsWithComparator extends PreConditionComparator<String> {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.metadata.preconditions.PreConditionComparator#performCheck
+   * (java.io.File, java.lang.Object)
+   */
+  @Override
+  protected int performCheck(File file, String ext)
+      throws PreconditionComparatorException {
+    return file.getName().substring(file.getName().lastIndexOf(".") + 1)
+        .compareTo(ext);
+  }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/ExistanceCheckComparator.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/ExistanceCheckComparator.java
new file mode 100644
index 0000000..7b5ecb2
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/ExistanceCheckComparator.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.preconditions;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.exceptions.PreconditionComparatorException;
+
+/**
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * The {@link Comparator} to use when determining {@link File} existance with
+ * {@link PreCondEvalUtils}
+ * </p>.
+ */
+public class ExistanceCheckComparator extends PreConditionComparator<Boolean> {
+
+    @Override
+    protected int performCheck(File product, Boolean compareItem)
+            throws PreconditionComparatorException {
+        return new Boolean(product.exists()).compareTo(compareItem);
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/FileSizeComparator.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/FileSizeComparator.java
new file mode 100644
index 0000000..463b8dc
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/FileSizeComparator.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.preconditions;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.exceptions.PreconditionComparatorException;
+
+/**
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * The compator to use when checking file size in {@link PreConEvalUtils}
+ * </p>.
+ */
+public class FileSizeComparator extends PreConditionComparator<Long> {
+
+    @Override
+    protected int performCheck(File product, Long compareItem)
+            throws PreconditionComparatorException {
+        return new Long(product.length()).compareTo(compareItem);
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/MimeTypeComparator.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/MimeTypeComparator.java
new file mode 100644
index 0000000..f57af04
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/MimeTypeComparator.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.preconditions;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.exceptions.PreconditionComparatorException;
+import org.apache.oodt.cas.metadata.util.MimeTypeUtils;
+
+/**
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A {@link PreConditionComparator} that uses Apache Tika for Mime detection
+ * </p>.
+ */
+public class MimeTypeComparator extends PreConditionComparator<String> {
+
+    private boolean useMagic;
+
+    private MimeTypeUtils mimeTypeUtils = new MimeTypeUtils();
+
+    public MimeTypeComparator() {
+        super();
+        this.useMagic = false;
+    }
+
+    @Override
+    protected int performCheck(File product, String mimeType)
+            throws PreconditionComparatorException {
+        try {
+            String tikaMimeType = this.mimeTypeUtils.getMimeType(product);
+            if (tikaMimeType == null && useMagic)
+                tikaMimeType = this.mimeTypeUtils
+                        .getMimeTypeByMagic(MimeTypeUtils
+                                .readMagicHeader(new FileInputStream(product)));
+            return tikaMimeType.compareTo(mimeType);
+        } catch (Throwable e) {
+            e.printStackTrace();
+            throw new PreconditionComparatorException(
+                    "Failed to get mime-type for " + product + " : "
+                            + e.getMessage());
+        }
+    }
+
+    public void setMimeTypeRepo(String mimeTypeRepo) {
+        try {
+            mimeTypeUtils = new MimeTypeUtils(mimeTypeRepo);
+        } catch (Exception e) {
+            mimeTypeUtils = new MimeTypeUtils();
+        }
+    }
+
+    public void setUseMagic(boolean useMagic) {
+        this.useMagic = useMagic;
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/PreCondEvalUtils.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/PreCondEvalUtils.java
new file mode 100644
index 0000000..6191b99
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/PreCondEvalUtils.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.preconditions;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//Spring imports
+import org.springframework.context.ApplicationContext;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.MetExtractor; // for javadoc
+
+/**
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Evaluation utility for metadata extractor preconditions
+ * </p>.
+ */
+public class PreCondEvalUtils implements PreConditionOperatorMetKeys {
+
+    private static Logger LOG = Logger.getLogger(PreCondEvalUtils.class
+            .getName());
+
+    private static ApplicationContext applicationContext;
+
+    public PreCondEvalUtils(ApplicationContext applicationContext) {
+        this.applicationContext = applicationContext;
+    }
+
+    /**
+     * Evaluates whether all preconditions pass or not
+     * 
+     * @param preconditions
+     *            The String identifiers of the {@link PreConditionComparator}s
+     *            in question
+     * @param product
+     *            the {@link File} to test the preconditions against to
+     *            determine whether or not the {@link MetExtractor} should be
+     *            run or not.
+     * @return True if all preconditions pass and false otherwise
+     */
+    public boolean eval(List<String> preCondComparatorIds, File product) {
+        for (String preCondComparatorId : preCondComparatorIds) {
+            if (!((PreConditionComparator<?>) this.applicationContext.getBean(
+                    preCondComparatorId, PreConditionComparator.class))
+                    .passes(product)) {
+                LOG.log(Level.INFO, "Failed precondition comparator id "
+                        + preCondComparatorId);
+                return false;
+            } else {
+                LOG.log(Level.INFO, "Passed precondition comparator id "
+                        + preCondComparatorId);
+            }
+        }
+
+        return true;
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/PreConditionComparator.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/PreConditionComparator.java
new file mode 100644
index 0000000..d457e30
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/PreConditionComparator.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.preconditions;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.commons.spring.SpringSetIdInjectionType;
+import org.apache.oodt.cas.metadata.MetExtractor;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.oodt.cas.metadata.exceptions.PreconditionComparatorException;
+import static org.apache.oodt.cas.metadata.preconditions.PreConditionOperatorMetKeys.*;
+
+//Spring imports
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * The abstract base class for evaluating {@link PreCondition} checks for
+ * running a {@link MetExtractor}
+ * </p>.
+ */
+public abstract class PreConditionComparator<CompareType> implements SpringSetIdInjectionType {
+
+    private String fileExtension;
+
+    private String type;
+
+    private CompareType compareItem;
+
+    private String description;
+
+    private String id;
+    
+    public String getId() {
+        return this.id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+    
+    public boolean passes(File product) {
+        try {
+            if (fileExtension != null)
+                product = new File(product.getAbsolutePath() + "."
+                        + this.fileExtension);
+            return eval(this.type, this.performCheck(product, this.compareItem));
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    protected abstract int performCheck(File product, CompareType compareItem)
+            throws PreconditionComparatorException;
+
+    public void setFileExtension(String fileExtension) {
+        this.fileExtension = fileExtension;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return this.description;
+    }
+
+    @Required
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    @Required
+    public void setCompareItem(CompareType compareItem) {
+        this.compareItem = compareItem;
+    }
+
+    private static boolean eval(String opKey, int preconditionResult)
+            throws MetExtractionException {
+        opKey = opKey.toUpperCase();
+        if (preconditionResult == 0)
+            return EQUAL_TO.equals(opKey);
+        else if (preconditionResult > 0)
+            return NOT_EQUAL_TO.equals(opKey) || GREATER_THAN.equals(opKey);
+        else if (preconditionResult < 0)
+            return NOT_EQUAL_TO.equals(opKey) || LESS_THAN.equals(opKey);
+        else
+            throw new MetExtractionException("evalType is not a valid type");
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/PreConditionOperatorMetKeys.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/PreConditionOperatorMetKeys.java
new file mode 100644
index 0000000..32938f0
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/PreConditionOperatorMetKeys.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.preconditions;
+
+/**
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Met keys for evaluating {@link MetExtractor} {@link PreCondition}s
+ * </p>.
+ */
+public interface PreConditionOperatorMetKeys {
+
+    public static String EQUAL_TO = "EQUAL_TO";
+
+    public static String NOT_EQUAL_TO = "NOT_EQUAL_TO";
+
+    public static String GREATER_THAN = "GREATER_THAN";
+
+    public static String LESS_THAN = "LESS_THAN";
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/SubProductExistenceCheckComparator.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/SubProductExistenceCheckComparator.java
new file mode 100644
index 0000000..00ffd1c
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/preconditions/SubProductExistenceCheckComparator.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.metadata.preconditions;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.metadata.exceptions.PreconditionComparatorException;
+
+/**
+ * A {@link PreConditionComparator} that checks for the existence of an arbitrary file (a "sub-product") 
+ * within the product directory.
+ * If the product is not a directory, or the filePath field is not specified, this class behaves
+ * exactly like the superclass {@link ExistanceCheckComparator}.
+ * 
+ * @author luca (Luca Cinquini)
+ *
+ */
+public class SubProductExistenceCheckComparator extends
+		ExistanceCheckComparator {
+	
+	private static final Logger LOG = Logger.getLogger(ExistanceCheckComparator.class.getName());
+	
+    private String filePath;
+
+	public String getFilePath() {
+		return filePath;
+	}
+
+	/**
+	 * Sets the sub-product file path (must be relative to the product absolute path).
+	 */
+	public void setFilePath(String filePath) {
+		this.filePath = filePath;
+	}
+	
+    @Override
+    protected int performCheck(File product, Boolean compareItem)
+            throws PreconditionComparatorException {
+    	
+    	if (product.isDirectory() && filePath!=null) {
+    		File file = new File(product.getAbsolutePath()+"/"+filePath);
+    		LOG.log(Level.INFO, "Checking existence of file="+file.getAbsolutePath());
+    		return new Boolean(file.exists()).compareTo(compareItem);
+    	} else {
+    		return new Boolean(product.exists()).compareTo(compareItem);
+    	}
+    }
+	
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/util/GenericMetadataObjectFactory.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/util/GenericMetadataObjectFactory.java
new file mode 100644
index 0000000..eed3a70
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/util/GenericMetadataObjectFactory.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.util;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.MetExtractor;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A generic object factory for Metadata framework objects.
+ * </p>.
+ */
+public final class GenericMetadataObjectFactory {
+
+  /* our log stream */
+  private final static Logger LOG = Logger
+      .getLogger(GenericMetadataObjectFactory.class.getName());
+
+  public static MetExtractor getMetExtractorFromClassName(String className) {
+    Class metExtractorClass = null;
+    MetExtractor extractor = null;
+
+    try {
+      metExtractorClass = Class.forName(className);
+      extractor = (MetExtractor) metExtractorClass.newInstance();
+      return extractor;
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading met extractor class "
+              + className + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading met extractor class "
+              + className + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading met extractor class "
+              + className + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/util/MimeTypeUtils.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/util/MimeTypeUtils.java
new file mode 100644
index 0000000..49a6946
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/util/MimeTypeUtils.java
@@ -0,0 +1,365 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.util;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//APACHE imports
+import org.apache.tika.Tika;
+import org.apache.tika.detect.DefaultDetector;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.mime.MimeType;
+import org.apache.tika.mime.MimeTypeException;
+import org.apache.tika.mime.MimeTypes;
+import org.apache.tika.mime.MimeTypesFactory;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * 
+ * <p>
+ * This is a facade class to insulate CAS Metadata from its underlying Mime Type
+ * substrate library, <a href="http://tika.apache.org/">Apache Tika</a>.
+ * Any mime handling code should be placed in this utility class, and hidden
+ * from the CAS Metadata classes that rely on it.
+ * </p>
+ */
+public final class MimeTypeUtils {
+
+    private static final String SEPARATOR = ";";
+
+    /* our Tika mime type registry */
+    private MimeTypes mimeTypes;
+
+    private Tika tika;
+
+    /* whether or not magic should be employed or not */
+    private boolean mimeMagic;
+
+    /* static resource path for the mimeTypesFile */
+    public final static String MIME_FILE_RES_PATH = "tika-mimetypes.xml";
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(MimeTypeUtils.class
+            .getName());
+
+    public MimeTypeUtils() {
+        this(MimeTypeUtils.class.getResourceAsStream(MIME_FILE_RES_PATH), true);
+    }
+
+    public MimeTypeUtils(String filePath) throws FileNotFoundException {
+        this(filePath, true);
+    }
+
+    public MimeTypeUtils(String filePath, boolean magic)
+            throws FileNotFoundException {
+        this(new FileInputStream(filePath), magic);
+    }
+
+    public MimeTypeUtils(InputStream mimeIs, boolean magic) {
+    	try {
+    		this.mimeTypes = MimeTypesFactory.create(mimeIs);
+    		this.mimeMagic = magic;
+    		this.tika = new Tika(new DefaultDetector(this.mimeTypes));
+    	}catch (Exception e) {
+    		LOG.log(Level.SEVERE, "Failed to load MimeType Registry : " + e.getMessage(), e);
+    	}
+    }
+
+    /**
+     * Cleans a {@link MimeType} name by removing out the actual
+     * {@link MimeType}, from a string of the form:
+     * 
+     * <pre>
+     *           &lt;primary type&gt;/&lt;sub type&gt; ; &lt; optional params
+     * </pre>
+     * 
+     * @param origType
+     *            The original mime type string to be cleaned.
+     * @return The primary type, and subtype, concatenated, e.g., the actual
+     *         mime type.
+     */
+    public static String cleanMimeType(String origType) {
+        if (origType == null)
+            return null;
+
+        // take the origType and split it on ';'
+        String[] tokenizedMimeType = origType.split(SEPARATOR);
+        if (tokenizedMimeType.length > 1) {
+            // there was a ';' in there, take the first value
+            return tokenizedMimeType[0];
+        } else {
+            // there wasn't a ';', so just return the orig type
+            return origType;
+        }
+    }
+
+    /**
+     * Same as {@link #autoResolveContentType(String, String, byte[])}, but
+     * this method passes <code>null</code> as the initial type.
+     * 
+     * @param url
+     *            The String URL to use to check glob patterns.
+     * @param data
+     *            The byte data to potentially use in magic detection.
+     * @return The String {@link MimeType}.
+     */
+    public String autoResolveContentType(String url, byte[] data) {
+        return autoResolveContentType(null, url, data);
+    }
+
+    /**
+     * A facade interface to trying all the possible mime type resolution
+     * strategies available within Tika. First, the mime type provided in
+     * <code>typeName</code> is cleaned, with {@link #cleanMimeType(String)}.
+     * Then the cleaned mime type is looked up in the underlying Tika
+     * {@link MimeTypes} registry, by its cleaned name. If the {@link MimeType}
+     * is found, then that mime type is used, otherwise {@link URL} resolution
+     * is used to try and determine the mime type. If that means is
+     * unsuccessful, and if <code>mime.type.magic</code> is enabled in
+     * {@link NutchConfiguration}, then mime type magic resolution is used to
+     * try and obtain a better-than-the-default approximation of the
+     * {@link MimeType}.
+     * 
+     * @param typeName
+     *            The original mime type, returned from a {@link ProtocolOutput}.
+     * @param url
+     *            The given {@link URL}, that Nutch was trying to crawl.
+     * @param data
+     *            The byte data, returned from the crawl, if any.
+     * @return The correctly, automatically guessed {@link MimeType} name.
+     */
+    public String autoResolveContentType(String typeName, String url,
+            byte[] data) {
+        MimeType type = null;
+        String cleanedMimeType = null;
+
+        try {
+            cleanedMimeType = MimeTypeUtils.cleanMimeType(typeName) != null ? this.mimeTypes
+                    .forName(MimeTypeUtils.cleanMimeType(typeName)).getName()
+                    : null;
+        } catch (MimeTypeException mte) {
+            // Seems to be a malformed mime type name...
+        }
+
+        // first try to get the type from the cleaned type name
+        try {
+            type = cleanedMimeType != null ? this.mimeTypes
+                    .forName(cleanedMimeType) : null;
+        } catch (MimeTypeException e) {
+            type = null;
+        }
+
+        // if returned null, or if it's the default type then try url resolution
+        if (type == null
+                || (type.getName().equals(MimeTypes.OCTET_STREAM))) {
+            // If no mime-type header, or cannot find a corresponding registered
+            // mime-type, then guess a mime-type from the url pattern
+            try {
+                type = mimeTypes.forName(tika.detect(url)) != null ? mimeTypes.forName(tika.detect(url)) : type;
+            } catch (Exception e) {
+                // MimeTypeException or IOException from tika.detect. Ignore.
+            }
+        }
+
+        // if magic is enabled use mime magic to guess if the mime type returned
+        // from the magic guess is different than the one that's already set so
+        // far
+        // if it is, and it's not the default mime type, then go with the mime
+        // type
+        // returned by the magic
+        if (this.mimeMagic) {
+            MimeType magicType;
+            try {
+                magicType =  mimeTypes.forName(tika.detect(data));
+            } catch (Exception e) {
+                magicType = null;
+            }
+            if (magicType != null
+                    && !magicType.getName().equals(MimeTypes.OCTET_STREAM)
+                    && type != null
+                    && !type.getName().equals(magicType.getName())) {
+                // If magic enabled and the current mime type differs from that
+                // of the
+                // one returned from the magic, take the magic mimeType
+                type = magicType;
+            }
+
+            // if type is STILL null after all the resolution strategies, go for
+            // the
+            // default type
+            if (type == null) {
+                try {
+                    type = this.mimeTypes.forName(MimeTypes.OCTET_STREAM);
+                } catch (Exception ignore) {
+                }
+            }
+        }
+
+        return type.getName();
+    }
+
+    /**
+     * Facade interface to Tika's underlying
+     * {@link tika.detect(String)} method.
+     *
+     * @param url
+     *            A string representation of the document {@link URL} to sense
+     *            the {@link MimeType} for.
+     * @return An appropriate {@link MimeType}, identified from the given
+     *         Document url in string form.
+     */
+    public String getMimeType(URL url) {
+        try {
+    	    return tika.detect(url);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    /**
+     * A facade interface to Tika's underlying {@link org.apache.tika.tika.detect(String)}
+     * method.
+     *
+     * @param name
+     *            The name of a valid {@link MimeType} in the Tika mime
+     *            registry.
+     * @return The object representation of the {@link MimeType}, if it exists,
+     *         or null otherwise.
+     */
+    public String getMimeType(String name) {
+        try {
+            return tika.detect(name);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * Facade interface to Tika's underlying {@link org.apache.tika.Tika#detect(File)}
+     * method.
+     *
+     * @param f
+     *            The {@link File} to sense the {@link MimeType} for.
+     * @return The {@link MimeType} of the given {@link File}, or null if it
+     *         cannot be determined.
+     */
+    public String getMimeType(File f) {
+        try {
+            return tika.detect(f);
+        } catch (Exception e) {
+            System.err.println("\n\n\n");
+            e.printStackTrace();
+            System.err.println("\n\n\n");
+            return null;
+        }
+    }
+
+    /**
+     * Utility method to act as a facade to
+     * {@link MimeTypes#getMimeType(byte[])}.
+     *
+     * @param data
+     *            The byte data to get the {@link MimeType} for.
+     * @return The String representation of the resolved {@link MimeType}, or
+     *         null if a suitable {@link MimeType} is not found.
+     */
+    public String getMimeTypeByMagic(byte[] data) {
+        try {
+            return tika.detect(data);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+    
+    public String getDescriptionForMimeType(String mimeType) {
+    	try {
+    		return this.mimeTypes.forName(mimeType).getDescription();
+    	}catch (Exception e) {
+    		LOG.log(Level.WARNING, "Failed to get description for mimetype " 
+    				+ mimeType + " : " + e.getMessage());
+    		return null;
+    	}
+    }
+
+    public String getSuperTypeForMimeType(String mimeType) {
+    	try {
+    		MediaType mediaType = this.mimeTypes.getMediaTypeRegistry().getSupertype(this.mimeTypes.forName(mimeType).getType());
+    		if (mediaType != null)
+    			return mediaType.getType() + "/" + mediaType.getSubtype();
+    		else
+    			return null;
+    	}catch (Exception e) {
+    		LOG.log(Level.WARNING, "Failed to get super-type for mimetype " 
+    				+ mimeType + " : " + e.getMessage());
+    		return null;
+    	}
+    }
+    
+    /**
+     * @return the mimeMagic
+     */
+    public boolean isMimeMagic() {
+        return mimeMagic;
+    }
+
+    /**
+     * @param mimeMagic the mimeMagic to set
+     */
+    public void setMimeMagic(boolean mimeMagic) {
+        this.mimeMagic = mimeMagic;
+    }
+    
+    public static byte[] readMagicHeader(InputStream stream) throws IOException {
+    	return readMagicHeader(stream, 1024);
+    }
+    
+    public static byte[] readMagicHeader(InputStream stream, int headerByteSize) 
+    		throws IOException {
+        if (stream == null) {
+            throw new IllegalArgumentException("InputStream is missing");
+        }
+
+        byte[] bytes = new byte[headerByteSize];
+        int totalRead = 0;
+
+        int lastRead = stream.read(bytes);
+        while (lastRead != -1) {
+            totalRead += lastRead;
+            if (totalRead == bytes.length) {
+                return bytes;
+            }
+            lastRead = stream.read(bytes, totalRead, bytes.length - totalRead);
+        }
+
+        byte[] shorter = new byte[totalRead];
+        System.arraycopy(bytes, 0, shorter, 0, totalRead);
+        return shorter;
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/util/PathUtils.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/util/PathUtils.java
new file mode 100644
index 0000000..7b6586a
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/util/PathUtils.java
@@ -0,0 +1,399 @@
+/*
+ * 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.
+ */
+
+
+//$Id$
+
+package org.apache.oodt.cas.metadata.util;
+
+//JDK imports
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+//APACHE imports
+import org.apache.commons.lang.StringUtils;
+
+//OODT imports
+import org.apache.oodt.commons.date.DateUtils;
+import org.apache.oodt.commons.exec.EnvUtilities;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Utility class for replacing environment variables and maniuplating file
+ * path strings.
+ * </p>.
+ */
+public final class PathUtils {
+
+    public static String DELIMITER = ",";
+
+    public static String replaceEnvVariables(String origPath) {
+        return replaceEnvVariables(origPath, null);
+    }
+
+    public static String replaceEnvVariables(String origPath, Metadata metadata) {
+        return replaceEnvVariables(origPath, metadata, false);
+    }
+
+    public static String replaceEnvVariables(String origPath,
+            Metadata metadata, boolean expand) {
+        StringBuffer finalPath = new StringBuffer();
+
+        for (int i = 0; i < origPath.length(); i++) {
+            if (origPath.charAt(i) == '[') {
+                VarData data = readEnvVarName(origPath, i);
+                String var = null;
+                if (metadata != null
+                        && metadata.getMetadata(data.getFieldName()) != null) {
+                    List valList = metadata.getAllMetadata(data.getFieldName());
+                    var = (String) valList.get(0);
+                    if (expand)
+                        for (int j = 1; j < valList.size(); j++)
+                            var += DELIMITER + (String) valList.get(j);
+                } else {
+                    var = EnvUtilities.getEnv(data.getFieldName());
+                }
+                finalPath.append(var);
+                i = data.getEndIdx();
+            } else {
+                finalPath.append(origPath.charAt(i));
+            }
+        }
+
+        return finalPath.toString();
+    }
+
+    public static String doDynamicReplacement(String string) throws Exception {
+        return doDynamicReplacement(string, null);
+    }
+
+    public static String doDynamicReplacement(String string, Metadata metadata)
+            throws Exception {
+        return PathUtils.replaceEnvVariables(doDynamicDateReplacement(
+        		   doDynamicDateRollReplacement(
+        			   doDynamicDateFormatReplacement(
+                           doDynamicUtcToTaiDateReplacement(
+                               doDynamicDateToSecsReplacement(
+                                   doDynamicDateToMillisReplacement(
+                                       string, metadata),
+                                   metadata),
+                               metadata),
+                           metadata), 
+                       metadata),
+                   metadata),
+               metadata, true);
+    }
+
+    public static String doDynamicDateReplacement(String string,
+            Metadata metadata) throws Exception {
+        Pattern datePattern = Pattern
+                .compile("\\[\\s*DATE\\s*(?:[+-]{1}[^\\.]{1,}?){0,1}\\.\\s*(?:(?:DAY)|(?:MONTH)|(?:YEAR)|(?:UTC)|(?:TAI)){1}\\s*\\]");
+        Matcher dateMatcher = datePattern.matcher(string);
+        while (dateMatcher.find()) {
+            String dateString = string.substring(dateMatcher.start(),
+                    dateMatcher.end());
+            GregorianCalendar gc = new GregorianCalendar();
+
+            // roll the date if roll days was specfied
+            int plusMinusIndex;
+            if ((plusMinusIndex = dateString.indexOf('-')) != -1
+                    || (plusMinusIndex = dateString.indexOf('+')) != -1) {
+                int dotIndex;
+                if ((dotIndex = dateString.indexOf('.', plusMinusIndex)) != -1) {
+                    int rollDays = Integer.parseInt(PathUtils
+                            .replaceEnvVariables(
+                                    dateString.substring(plusMinusIndex,
+                                            dotIndex), metadata).replaceAll(
+                                    "[\\+\\s]", ""));
+                    gc.add(GregorianCalendar.DAY_OF_YEAR, rollDays);
+                } else
+                    throw new Exception(
+                            "Malformed dynamic date replacement specified (no dot separator) - '"
+                                    + dateString + "'");
+            }
+
+            // determine type and make the appropriate replacement
+            String[] splitDate = dateString.split("\\.");
+            if (splitDate.length < 2)
+                throw new Exception("No date type specified - '" + dateString
+                        + "'");
+            String dateType = splitDate[1].replaceAll("[\\[\\]\\s]", "");
+            String replacement = "";
+            if (dateType.equals("DAY")) {
+                replacement = StringUtils.leftPad(gc
+                        .get(GregorianCalendar.DAY_OF_MONTH)
+                        + "", 2, "0");
+            } else if (dateType.equals("MONTH")) {
+                replacement = StringUtils.leftPad((gc
+                        .get(GregorianCalendar.MONTH) + 1)
+                        + "", 2, "0");
+            } else if (dateType.equals("YEAR")) {
+                replacement = gc.get(GregorianCalendar.YEAR) + "";
+            } else if (dateType.equals("UTC")) {
+                replacement = DateUtils.toString(DateUtils.toUtc(gc));
+            } else if (dateType.equals("TAI")) {
+                replacement = DateUtils.toString(DateUtils.toTai(gc));
+            } else {
+                throw new Exception("Invalid date type specified '"
+                        + dateString + "'");
+            }
+
+            string = StringUtils.replace(string, dateString, replacement);
+            dateMatcher = datePattern.matcher(string);
+        }
+        return string;
+    }
+
+    /**
+     * usage format: [DATE_ADD(<date>,<date-format>,<add-amount>,<hr | min | sec | day | mo | yr>)]
+     * example: [DATE_ADD(2009-12-31, yyyy-MM-dd, 1, day)] . . . output will be: 2010-01-01
+     * - dynamic replacement is allowed for the <date> as well, for example: 
+     *  [DATE_ADD([DATE.UTC], yyyy-MM-dd'T'HH:mm:ss.SSS'Z', 1, day)] will add one day to the 
+     *  current UTC time
+     */
+    public static String doDynamicDateRollReplacement(String string,
+            Metadata metadata) throws Exception {
+        Pattern dateFormatPattern = Pattern
+                .compile("\\[\\s*DATE_ADD\\s*\\(.{1,}?,.{1,}?,.{1,}?,.{1,}?\\)\\s*\\]");
+        Matcher dateFormatMatcher = dateFormatPattern.matcher(string);
+        while (dateFormatMatcher.find()) {
+            String dateFormatString = string.substring(dateFormatMatcher
+                    .start(), dateFormatMatcher.end());
+
+            // get arguments
+            Matcher argMatcher = Pattern.compile("\\(.*\\)").matcher(
+                    dateFormatString);
+            argMatcher.find();
+            String argsString = dateFormatString.substring(argMatcher.start() + 1,
+                    argMatcher.end() - 1); 
+            argsString = doDynamicReplacement(argsString, metadata);
+            String[] args = argsString.split(",");
+            String dateString = args[0].trim();
+            dateString = doDynamicReplacement(dateString, metadata);
+            String dateFormat = args[1].trim();
+            int addAmount = Integer.parseInt(args[2].trim());
+            String addUnits = args[3].trim().toLowerCase();
+
+            // reformat date
+            Date date = new SimpleDateFormat(dateFormat).parse(dateString);
+            Calendar calendar = (Calendar) Calendar.getInstance().clone();
+            calendar.setTime(date);
+            if (addUnits.equals("hr") || addUnits.equals("hour"))
+            	calendar.add(Calendar.HOUR_OF_DAY, addAmount);
+            else if (addUnits.equals("min") || addUnits.equals("minute"))
+            	calendar.add(Calendar.MINUTE, addAmount);
+            else if (addUnits.equals("sec") || addUnits.equals("second"))
+            	calendar.add(Calendar.SECOND, addAmount);
+            else if (addUnits.equals("day"))
+            	calendar.add(Calendar.DAY_OF_YEAR, addAmount);
+            else if (addUnits.equals("mo") || addUnits.equals("month"))
+            	calendar.add(Calendar.MONTH, addAmount);
+            else if (addUnits.equals("yr") || addUnits.equals("year"))
+            	calendar.add(Calendar.YEAR, addAmount);
+            
+            String newDateString = new SimpleDateFormat(dateFormat).format(calendar.getTime());
+            
+            // swap in date string
+            string = StringUtils.replace(string, dateFormatString,
+                    newDateString);
+            dateFormatMatcher = dateFormatPattern.matcher(string);
+        }
+
+        return string;
+    }
+    
+    public static String doDynamicDateFormatReplacement(String string,
+            Metadata metadata) throws Exception {
+        Pattern dateFormatPattern = Pattern
+                .compile("\\[\\s*FORMAT\\s*\\(.{1,}?,.{1,}?,.{1,}?\\)\\s*\\]");
+        Matcher dateFormatMatcher = dateFormatPattern.matcher(string);
+        while (dateFormatMatcher.find()) {
+            String dateFormatString = string.substring(dateFormatMatcher
+                    .start(), dateFormatMatcher.end());
+
+            // get arguments
+            Matcher argMatcher = Pattern.compile("\\(.*\\)").matcher(
+                    dateFormatString);
+            argMatcher.find();
+            String argsString = dateFormatString.substring(argMatcher.start() + 1,
+                    argMatcher.end() - 1); 
+            argsString = doDynamicReplacement(argsString, metadata);
+            String[] args = argsString.split(",");
+            String curFormat = args[0].trim();
+            String dateString = args[1].trim();
+            String newFormat = args[2].trim();
+
+            // reformat date
+            Date date = new SimpleDateFormat(curFormat).parse(dateString);
+            String newDateString = new SimpleDateFormat(newFormat).format(date);
+
+            // swap in date string
+            string = StringUtils.replace(string, dateFormatString,
+                    newDateString);
+            dateFormatMatcher = dateFormatPattern.matcher(string);
+        }
+
+        return string;
+    }
+    
+    /**
+     * Replaces String method of format [UTC_TO_TAI(<utc-string format: "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'">)]
+     * with TAI time with format: "yyyy-MM-dd'T'HH:mm:ss.SSS-0000<leapSecs>"
+     */
+    public static String doDynamicUtcToTaiDateReplacement(String string,
+            Metadata metadata) throws Exception {
+        Pattern utcToTaiPattern = Pattern.compile("\\[\\s*UTC_TO_TAI\\s*\\(.{1,}?\\)\\s*\\]");
+        Matcher matcher = utcToTaiPattern.matcher(string);
+        while (matcher.find()) {
+            String utcToTaiString = string.substring(matcher.start(), matcher.end());
+            Matcher argMatcher = Pattern.compile("\\(.*\\)").matcher(utcToTaiString);
+            argMatcher.find();
+            String utcDateString = 
+                utcToTaiString.substring(argMatcher.start() + 1, argMatcher.end() - 1).trim();
+            utcDateString = doDynamicReplacement(utcDateString, metadata);
+            string = StringUtils.replace(string, utcToTaiString, 
+                    DateUtils.toString(DateUtils.toTai(DateUtils.toCalendar(utcDateString, 
+                            DateUtils.FormatType.UTC_FORMAT))));
+            matcher = utcToTaiPattern.matcher(string);
+        }
+        return string;
+    }
+    
+    /**
+     * Replaces String method of format [DATE_TO_SECS(<date-string>,<DateUtils.FormatType>,<epoch-date format: "yyyy-MM-dd">)]
+     * with seconds between <epoch-date> and <date-string> 
+     */
+    public static String doDynamicDateToSecsReplacement(String string,
+            Metadata metadata) throws Exception {
+        Pattern utcToTaiPattern = Pattern.compile("\\[\\s*DATE_TO_SECS\\s*\\(.{1,}?\\,.{1,}?,.{1,}?\\)\\s*\\]");
+        Matcher matcher = utcToTaiPattern.matcher(string);
+        while (matcher.find()) {
+            String dateToSecsString = string.substring(matcher.start(), matcher.end());
+            Matcher argMatcher = Pattern.compile("\\(.*\\)").matcher(dateToSecsString);
+            argMatcher.find();
+            String argsString = dateToSecsString.substring(argMatcher.start() + 1,
+                    argMatcher.end() - 1);
+            argsString = doDynamicReplacement(argsString, metadata);
+            String[] args = argsString.split(",");
+            String dateString = args[0].trim();
+            String dateType = args[1].trim();
+            String epochString = args[2].trim();
+            Calendar date = DateUtils.toCalendar(dateString, DateUtils.FormatType.valueOf(dateType));
+            Calendar epoch = DateUtils.toLocalCustomFormatCalendar(epochString, "yyyy-MM-dd");
+            String seconds = DateUtils.toString(DateUtils.getTimeInSecs(date, epoch));
+            string = StringUtils.replace(string, dateToSecsString, seconds);
+            matcher = utcToTaiPattern.matcher(string);
+        }
+        return string;
+    }
+    
+    /**
+     * Replaces String method of format [DATE_TO_MILLIS(<date-string>,<DateUtils.FormatType>,<epoch-date format: "yyyy-MM-dd">)]
+     * with milliseconds between <epoch-date> and <date-string> 
+     */
+    public static String doDynamicDateToMillisReplacement(String string,
+            Metadata metadata) throws Exception {
+        Pattern utcToTaiPattern = Pattern.compile("\\[\\s*DATE_TO_MILLIS\\s*\\(.{1,}?\\,.{1,}?,.{1,}?\\)\\s*\\]");
+        Matcher matcher = utcToTaiPattern.matcher(string);
+        while (matcher.find()) {
+            String dateToMillisString = string.substring(matcher.start(), matcher.end());
+            Matcher argMatcher = Pattern.compile("\\(.*\\)").matcher(dateToMillisString);
+            argMatcher.find();
+            String argsString = dateToMillisString.substring(argMatcher.start() + 1,
+                    argMatcher.end() - 1);
+            argsString = doDynamicReplacement(argsString, metadata);
+            String[] args = argsString.split(",");
+            String dateString = args[0].trim();
+            String dateType = args[1].trim();
+            String epochString = args[2].trim();
+            Calendar date = DateUtils.toCalendar(dateString, DateUtils.FormatType.valueOf(dateType));
+            Calendar epoch = DateUtils.toLocalCustomFormatCalendar(epochString, "yyyy-MM-dd");
+            String milliseconds = DateUtils.getTimeInMillis(date, epoch) + "";
+            string = StringUtils.replace(string, dateToMillisString, milliseconds);
+            matcher = utcToTaiPattern.matcher(string);
+        }
+        return string;
+    }
+
+    private static VarData readEnvVarName(String origPathStr, int startIdx) {
+        StringBuffer varName = new StringBuffer();
+        int idx = startIdx + 1;
+
+        do {
+            varName.append(origPathStr.charAt(idx));
+            idx++;
+        } while (origPathStr.charAt(idx) != ']');
+
+        VarData data = new PathUtils().new VarData();
+        data.setFieldName(varName.toString());
+        data.setEndIdx(idx);
+        return data;
+
+    }
+
+    class VarData {
+
+        private String fieldName = null;
+
+        private int endIdx = -1;
+
+        public VarData() {
+        }
+
+        /**
+         * @return the endIdx
+         */
+        public int getEndIdx() {
+            return endIdx;
+        }
+
+        /**
+         * @param endIdx
+         *            the endIdx to set
+         */
+        public void setEndIdx(int endIdx) {
+            this.endIdx = endIdx;
+        }
+
+        /**
+         * @return the fieldName
+         */
+        public String getFieldName() {
+            return fieldName;
+        }
+
+        /**
+         * @param fieldName
+         *            the fieldName to set
+         */
+        public void setFieldName(String fieldName) {
+            this.fieldName = fieldName;
+        }
+
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/util/PropertiesUtils.java b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/util/PropertiesUtils.java
new file mode 100644
index 0000000..a566255
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/java/org/apache/oodt/cas/metadata/util/PropertiesUtils.java
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.util;
+
+//JDK imports
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/**
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Utility methods for handing property values
+ * </p>.
+ */
+public final class PropertiesUtils {
+
+    /**
+     * Loads a set of System properties that are specified as comma-delimited
+     * strings and returns an array of String values for the specified property.
+     * 
+     * @param property
+     *            The property to read from the system properties.
+     * @param defaultValues
+     *            A set of default values to use for the property.
+     * @return An array of String property values for the specified property.
+     */
+    public static String[] getProperties(String property, String[] defaultValues) {
+        String[] values = getProperties(property);
+        if (values.length < 1) {
+            values = new String[defaultValues.length];
+            System.arraycopy(defaultValues, 0, values, 0, defaultValues.length);
+        }
+        return values;
+    }
+
+    /**
+     * Loads and parses a given property
+     * 
+     * @param property
+     *            The property to be loaded and parsed
+     * @return A string array of properties values
+     */
+    public static String[] getProperties(String property) {
+        Vector propList = new Vector();
+        StringTokenizer st = new StringTokenizer(System.getProperty(property,
+                ""), ",");
+        while (st.hasMoreTokens()) {
+            propList.add(PathUtils.replaceEnvVariables(st.nextToken().trim()));
+        }
+        return (String[]) propList.toArray(new String[propList.size()]);
+    }
+    
+    /**
+     * Loads and parses a given property
+     * 
+     * @param property
+     *            The property to read from the system properties.
+     * @param defaultValues
+     *            A default value to use for the property.
+     * @return A string properties value
+     */
+    public static String getProperty(String property, String defaultValue) {
+        return getProperties(property, new String[] { defaultValue })[0];
+    }
+    
+    /**
+     * Loads and parses a given property
+     * 
+     * @param property
+     *            The property to be loaded and parsed
+     * @return A string properties value
+     */
+    public static String getProperty(String property) {
+        return getProperties(property)[0];
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/main/resources/examples/copyandrewrite.example.conf b/0.8.1-rc1/metadata/src/main/resources/examples/copyandrewrite.example.conf
new file mode 100644
index 0000000..883a898
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/resources/examples/copyandrewrite.example.conf
@@ -0,0 +1,6 @@
+numRewriteFields=2
+rewriteField1=ProductType
+rewriteField2=FileLocation
+orig.met.file.path=./src/resources/examples/samplemet.xml
+ProductType.pattern=NewProductType[ProductType]
+FileLocation.pattern=/new/loc/[FileLocation]
diff --git a/0.8.1-rc1/metadata/src/main/resources/examples/datasource_metextractor_example.properties b/0.8.1-rc1/metadata/src/main/resources/examples/datasource_metextractor_example.properties
new file mode 100644
index 0000000..0af5194
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/resources/examples/datasource_metextractor_example.properties
@@ -0,0 +1,5 @@
+org.apache.oodt.cas.metadata.extractors.datasource.query=select ProductName,FileSize from Products where ProductId = '%s'
+org.apache.oodt.cas.metadata.extractors.datasource.db.url=http://db.url
+org.apache.oodt.cas.metadata.extractors.datasource.driver=some.driver.class
+org.apache.oodt.cas.metadata.extractors.datasource.username=user
+org.apache.oodt.cas.metadata.extractors.datasource.password=pass
\ No newline at end of file
diff --git a/0.8.1-rc1/metadata/src/main/resources/examples/extern-config.xml b/0.8.1-rc1/metadata/src/main/resources/examples/extern-config.xml
new file mode 100644
index 0000000..e764f20
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/resources/examples/extern-config.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<!-- FIXME: change namespace URI? -->
+<cas:externextractor xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+
+	<!--  
+	    workingDir: specifies the directory that the external command line met extractor will
+	    be run in. 
+	    
+	    if workingDir is not specified, and if the external command line met extractor honors
+	    the workingDir contract (generating .met file in directory that it is called from), then 
+	    the .met file will be generated in /path/to/file's parent directory. Otherwise, if the
+	    external command let met extractor doesn't honor working dir, then all bets
+	    are off.
+	    
+	    metFileExt: specifies the file extension for the extern met extractor to look for when 
+	    reading the generated met file into Java as an in-memory CAS metadata object. The met 
+	    file extension is appended to the full file path of the original data file. If not specified, 
+	    then the met file extension defaults to &quot;.met&quot;.
+	-->
+	<exec workingDir="" metFileExt="">
+		<!--  this path can be absolute or relative -->
+		<!--  you can optionally specify envReplace tag (=true) 
+		      to turn on environment variable replacement
+		-->
+		<extractorBinPath envReplace="true">[PWD]/src/test/gov/nasa/jpl/oodt/cas/metadata/extractors/testExtractor</extractorBinPath>
+
+		<!--  make sure to use character entities if there are any weird
+			parameters here that would screw up the XML.
+			
+			args come after providing the file to this met extractor. So, in other
+			words, we assume that extractorBinPath &gt;file&lt; &lt;args...&gt;
+			
+			where the first parameter is always the file to extract metadata from,
+			and the remaining parameters are optional to provide to the underlying
+			met extractor.
+		-->
+		<args>
+			<arg isDataFile="true"/>
+			<arg isMetFile="true"/>
+			<arg>-Dtrue=always</arg>
+			<arg>foo</arg>
+			<arg>bar</arg>
+			<!--  you can optionally specify that you would like environment 
+			      variable replacement on a particular argument
+			      
+			      You can also optionally specify that the argument is a path
+			      and that you would like it to be treated as such using the
+			      isPath="true". If not specified, the path is treated as if
+			      isPath was specified as "false", and String.replaceAll("\\s", "\\\\ ")
+			      is not called. If called, all white spaces are replaced from the path
+			      (using the above regex), and replaced with the literal string
+			      "\ ".
+			      
+			      The appendExt parameter is used to augment an existing argument 
+			      with some specified extension. This is typically used on paths 
+			      to add another extension to an argument that's a path. For instance, 
+			      you could append the .cas metadata file extension to an existing 
+			      path, e.g., the data file path.
+			-->
+			<arg envReplace="true" isPath="true">[HOME]/test boo</arg>
+			<arg appendExt="cas">/full/path/to/somefile.txt</arg>
+		</args>
+	</exec>
+
+</cas:externextractor>
\ No newline at end of file
diff --git a/0.8.1-rc1/metadata/src/main/resources/examples/filename.extractor.config.xml b/0.8.1-rc1/metadata/src/main/resources/examples/filename.extractor.config.xml
new file mode 100644
index 0000000..6513e9d
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/resources/examples/filename.extractor.config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<input>
+
+   <group name="TokenNameListGroup">
+     <scalar name="Delimeter">_</scalar>
+     <vector name="TokenMetKeys">
+    
+     <!-- 
+     [sourcename]_[tablename]_[productiondatetime].[ext]
+     
+     ex file name: datasource_tablename_20101129122700.txt
+     -->
+       <element>SourceName</element>
+       <element>TableName</element>
+       <element>ProductionDateTime</element>
+     </vector>
+  
+   </group>
+
+
+    <group name="SubstringOffsetGroup">
+     <!--  the indices for the substring met key selection -->
+     <!--  the first element is the starting index in the string -->
+     <!--  NOTE: this assumes 1-indexed strings (and is internally converted to
+           0-indexed.
+      -->
+     <!--  the second element is the length -->
+     
+     <!--  MissionName_Date_StartOrbitNumber_StopOrbitNumber.txt -->
+     
+      <vector name="MissionName">
+        <element>1</element>
+        <element>11</element>      
+      </vector>
+      
+      <vector name="Date">
+        <element>13</element>
+        <element>4</element>
+      </vector>
+      
+      <vector name="StartOrbitNumber">
+        <element>18</element>
+        <element>16</element>
+      </vector>
+      
+      <vector name="StopOrbitNumber">
+        <element>35</element>
+        <element>15</element>
+      </vector>
+      
+   </group>
+   
+   <group name="ProductionDateTimeGroup">
+     <scalar name="DateTimeFormat">yyyyMMddHHmmss</scalar>
+   </group>   
+    
+    <group name="CommonMetadata">
+       <!--  can now use environment variable replacement in any of the values for 
+             scalars or vectors, just use CAS bracket style [ENV VAR NAME]
+         
+             Also can use vector to indicate multiple values for a particular met field.
+        -->
+        <scalar name="DataVersion">1.0</scalar>
+        <scalar name="CollectionName">Products extracted by the OODT Filename Met Extractor</scalar>
+        <scalar name="DataProvider">OODT</scalar>
+    </group>
+</input>
diff --git a/0.8.1-rc1/metadata/src/main/resources/examples/met_extr_preconditions.xml b/0.8.1-rc1/metadata/src/main/resources/examples/met_extr_preconditions.xml
new file mode 100644
index 0000000..867ad1d
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/resources/examples/met_extr_preconditions.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+    
+
+    <!-- Precondition Comparators -->
+    <bean id="PreconditionComparator" lazy-init="true" abstract="true" class="org.apache.oodt.cas.metadata.preconditions.PreConditionComparator"/>
+    
+    <bean id="OnlyExtractFileType" lazy-init="true" class="org.apache.oodt.cas.metadata.preconditions.EndsWithComparator">
+        <property name="description" value="Checks the file extension and only extracts met from those files."/>        
+        <property name="compareItem">
+            <value type="java.lang.String">file_ext</value>    
+        </property>
+        <property name="type" value="equal_to"/>
+    </bean>    
+    
+    
+    <bean id="CheckThatDataFileSizeIsGreaterThanZero" lazy-init="true" parent="PreconditionComparator" class="org.apache.oodt.cas.metadata.preconditions.FileSizeComparator">
+        <property name="description" value="Check if the current data file size is greater than zero"/>        
+        <property name="compareItem">
+            <value type="java.lang.Long">0</value>
+        </property>
+        <property name="type" value="greater_than"/>
+    </bean>
+    
+    <bean id="CheckThatDataFileExists" lazy-init="true" parent="PreconditionComparator" class="org.apache.oodt.cas.metadata.preconditions.ExistanceCheckComparator">
+        <property name="description" value="Check if the current data file exists"/>        
+        <property name="compareItem">
+            <value type="java.lang.Boolean">true</value>
+        </property>
+        <property name="type" value="equal_to"/>    
+    </bean>
+
+    <bean id="CheckDataFileMimeType" lazy-init="true" parent="PreconditionComparator" class="org.apache.oodt.cas.metadata.preconditions.MimeTypeComparator">
+        <property name="description" value="Check that data file mime type matches the specified mime type"/>        
+        <property name="compareItem">
+            <value type="java.lang.String">application/xml</value>
+        </property>
+        <property name="type" value="equal_to"/>   
+        <property name="mimeTypeRepo" value="./src/resources/tika-mimetypes.xml"/>
+        <property name="useMagic" value="true"/> 
+    </bean>
+
+</beans>
\ No newline at end of file
diff --git a/0.8.1-rc1/metadata/src/main/resources/examples/samplemet.xml b/0.8.1-rc1/metadata/src/main/resources/examples/samplemet.xml
new file mode 100644
index 0000000..890f004
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/resources/examples/samplemet.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- FIXME: change namespace URI? -->
+<cas:metadata xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+ <keyval>
+   <key>Filename</key>
+   <val>blah.txt</val>
+ </keyval>
+ <keyval>
+   <key>FileLocation</key>
+   <val>/tmp</val>
+ </keyval>
+ <keyval>
+   <key>ProductType</key>
+   <val>GenericFile</val>
+ </keyval>
+</cas:metadata>
diff --git a/0.8.1-rc1/metadata/src/main/resources/logging.properties b/0.8.1-rc1/metadata/src/main/resources/logging.properties
new file mode 100644
index 0000000..f42a015
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/resources/logging.properties
@@ -0,0 +1,42 @@
+#  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.
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# Set the default logging level for the subsystems
+org.apache.oodt.cas.metadata.level = SEVERE
+org.apache.oodt.cas.metadata.extractors.level = SEVERE
+org.apache.oodt.cas.metadata.preconditions.level = SEVERE
+org.apache.oodt.cas.metadata.util.level = SEVERE
+
+# quiet the unit tests
+org.springframework.beans.level = SEVERE
+org.springframework.core.level = SEVERE
+org.springframework.context.level = SEVERE
+org.springframework.util.level = SEVERE
+sun.net.www.protocol.http.level = SEVERE
+sun.net.www.level = SEVERE
diff --git a/0.8.1-rc1/metadata/src/main/resources/tika-mimetypes.xml b/0.8.1-rc1/metadata/src/main/resources/tika-mimetypes.xml
new file mode 100644
index 0000000..6a0f7a3
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/main/resources/tika-mimetypes.xml
@@ -0,0 +1,5925 @@
+<?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.
+-->
+<!--
+  Description: This xml file defines the valid mime types used by Tika.
+  The mime type data within this file is based on information from various
+  sources like Apache Nutch, Apache HTTP Server, the file(1) command, etc.
+
+  Notes:
+   * Tika supports a wider range of match types than Freedesktop does
+   * Glob patterns must be unique, if there's a clash assign to the most
+     popular format
+   * The main mime type should be the canonical one, use aliases for any
+     other widely used forms
+   * Where there's a hierarchy in the types, list it via a parent
+   * Highly specific magic matches get a high priority
+   * General magic matches which could trigger a false-positive need
+     a low one
+   * The priority for containers normally need to be higher than for
+     the things they contain, so they don't accidently get detected
+     as what's in them
+   * For logic too complex to be expressed in a magic match, do the best
+     you can here, then provide a Custom Detector for the rest
+-->
+<mime-info>
+
+    <mime-type type="application/activemessage"/>
+    <mime-type type="application/andrew-inset">
+        <glob pattern="*.ez"/>
+    </mime-type>
+    <mime-type type="application/applefile"/>
+    <mime-type type="application/applixware">
+        <glob pattern="*.aw"/>
+    </mime-type>
+
+    <mime-type type="application/atom+xml">
+        <root-XML localName="feed" namespaceURI="http://purl.org/atom/ns#"/>
+        <root-XML localName="feed" namespaceURI="http://www.w3.org/2005/Atom"/>
+        <glob pattern="*.atom"/>
+    </mime-type>
+
+    <mime-type type="application/atomcat+xml">
+        <glob pattern="*.atomcat"/>
+    </mime-type>
+    <mime-type type="application/atomicmail"/>
+    <mime-type type="application/atomsvc+xml">
+        <glob pattern="*.atomsvc"/>
+    </mime-type>
+    <mime-type type="application/auth-policy+xml"/>
+    <mime-type type="application/batch-smtp"/>
+    <mime-type type="application/beep+xml"/>
+
+    <mime-type type="application/bizagi-modeler">
+        <_comment>BizAgi Process Modeler</_comment>
+        <sub-class-of type="application/zip"/>
+        <glob pattern="*.bpm"/>
+    </mime-type>
+
+    <mime-type type="application/cals-1840"/>
+    <mime-type type="application/ccxml+xml">
+        <glob pattern="*.ccxml"/>
+    </mime-type>
+    <mime-type type="application/cea-2018+xml"/>
+    <mime-type type="application/cellml+xml"/>
+    <mime-type type="application/cnrp+xml"/>
+    <mime-type type="application/commonground"/>
+    <mime-type type="application/conference-info+xml"/>
+    <mime-type type="application/cpl+xml"/>
+    <mime-type type="application/csta+xml"/>
+    <mime-type type="application/cstadata+xml"/>
+    <mime-type type="application/cu-seeme">
+        <glob pattern="*.cu"/>
+    </mime-type>
+    <mime-type type="application/cybercash"/>
+    <mime-type type="application/davmount+xml">
+        <glob pattern="*.davmount"/>
+    </mime-type>
+    <mime-type type="application/dca-rft"/>
+    <mime-type type="application/dec-dx"/>
+    <mime-type type="application/dialog-info+xml"/>
+    <mime-type type="application/dicom"/>
+
+    <mime-type type="application/dita+xml">
+        <sub-class-of type="application/xml"/>
+        <_comment>Darwin Information Typing Architecture</_comment>
+    </mime-type>
+
+    <mime-type type="application/dita+xml;format=map">
+        <sub-class-of type="application/dita+xml"/>
+        <_comment>DITA Map</_comment>
+        <root-XML localName="map"/>
+        <root-XML localName="map" namespaceURI="http://docs.oasis-open.org/namespace"/>
+        <glob pattern="*.ditamap"/>
+    </mime-type>
+    <mime-type type="application/dita+xml;format=topic">
+        <sub-class-of type="application/dita+xml"/>
+        <_comment>DITA Topic</_comment>
+        <root-XML localName="topic"/>
+        <root-XML localName="topic" namespaceURI="http://docs.oasis-open.org/namespace"/>
+        <!-- Topic is the default, Task and Concept are specialisations -->
+        <glob pattern="*.dita"/>
+    </mime-type>
+    <mime-type type="application/dita+xml;format=task">
+        <sub-class-of type="application/dita+xml;format=task"/>
+        <_comment>DITA Task Topic</_comment>
+        <root-XML localName="task"/>
+        <root-XML localName="task" namespaceURI="http://docs.oasis-open.org/namespace"/>
+    </mime-type>
+    <mime-type type="application/dita+xml;format=concept">
+        <sub-class-of type="application/dita+xml;format=topic"/>
+        <_comment>DITA Concept Topic</_comment>
+        <root-XML localName="concept"/>
+        <root-XML localName="concept" namespaceURI="http://docs.oasis-open.org/namespace"/>
+    </mime-type>
+    <mime-type type="application/dita+xml;format=val">
+        <sub-class-of type="application/dita+xml"/>
+        <_comment>DITA Conditional Processing Profile</_comment>
+        <root-XML localName="val"/>
+        <root-XML localName="val" namespaceURI="http://docs.oasis-open.org/namespace"/>
+        <glob pattern="*.ditaval"/>
+    </mime-type>
+
+    <mime-type type="application/dns"/>
+    <mime-type type="application/dvcs"/>
+    <mime-type type="application/ecmascript">
+        <glob pattern="*.ecma"/>
+    </mime-type>
+    <mime-type type="application/edi-consent"/>
+    <mime-type type="application/edi-x12"/>
+    <mime-type type="application/edifact"/>
+    <mime-type type="application/emma+xml">
+        <glob pattern="*.emma"/>
+    </mime-type>
+    <mime-type type="application/epp+xml"/>
+
+    <mime-type type="application/epub+zip">
+        <acronym>EPUB</acronym>
+        <_comment>Electronic Publication</_comment>
+        <magic priority="50">
+            <match value="PK\003\004" type="string" offset="0">
+                <match value="mimetypeapplication/epub+zip" type="string" offset="30"/>
+            </match>
+        </magic>
+        <glob pattern="*.epub"/>
+    </mime-type>
+
+    <mime-type type="application/eshop"/>
+    <mime-type type="application/example"/>
+    <mime-type type="application/fastinfoset"/>
+    <mime-type type="application/fastsoap"/>
+
+    <mime-type type="application/fits">
+        <acronym>FITS</acronym>
+        <_comment>Flexible Image Transport System</_comment>
+        <tika:link>http://www.digitalpreservation.gov/formats/fdd/fdd000317.shtml</tika:link>
+        <magic priority="50">
+            <match value="SIMPLE  =                    T" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.fits"/>
+        <glob pattern="*.fit"/>
+        <glob pattern="*.fts"/>
+    </mime-type>
+
+    <mime-type type="application/font-tdpfr">
+        <glob pattern="*.pfr"/>
+    </mime-type>
+    <mime-type type="application/h224"/>
+    <mime-type type="application/http"/>
+    <mime-type type="application/hyperstudio">
+        <glob pattern="*.stk"/>
+    </mime-type>
+    <mime-type type="application/ibe-key-request+xml"/>
+    <mime-type type="application/ibe-pkg-reply+xml"/>
+    <mime-type type="application/ibe-pp-data"/>
+    <mime-type type="application/iges"/>
+
+    <mime-type type="application/illustrator">
+        <acronym>AI</acronym>
+        <_comment>Adobe Illustrator Artwork</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/Adobe_Illustrator_Artwork</tika:link>
+        <glob pattern="*.ai"/>]
+        <sub-class-of type="application/postscript"/>
+    </mime-type>
+
+    <mime-type type="application/im-iscomposing+xml"/>
+    <mime-type type="application/index"/>
+    <mime-type type="application/index.cmd"/>
+    <mime-type type="application/index.obj"/>
+    <mime-type type="application/index.response"/>
+    <mime-type type="application/index.vnd"/>
+    <mime-type type="application/iotp"/>
+    <mime-type type="application/ipp"/>
+    <mime-type type="application/isup"/>
+
+    <mime-type type="application/java-archive">
+        <_comment>Java Archive</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/.jar</tika:link>
+        <tika:uti>com.sun.java-archive</tika:uti>
+        <sub-class-of type="application/zip"/>
+        <glob pattern="*.jar"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.android.package-archive">
+        <sub-class-of type="application/java-archive"/>
+        <glob pattern="*.apk"/>
+    </mime-type>
+    <mime-type type="application/x-tika-java-enterprise-archive">
+        <sub-class-of type="application/java-archive"/>
+        <glob pattern="*.ear"/>
+    </mime-type>
+    <mime-type type="application/x-tika-java-web-archive">
+        <sub-class-of type="application/java-archive"/>
+        <glob pattern="*.war"/>
+    </mime-type>
+
+    <mime-type type="application/x-tika-unix-dump"/>
+
+    <mime-type type="application/java-serialized-object">
+        <glob pattern="*.ser"/>
+    </mime-type>
+
+    <mime-type type="application/javascript">
+        <alias type="application/x-javascript"/>
+        <alias type="text/javascript"/>
+        <sub-class-of type="text/plain"/>
+        <_comment>JavaScript Source Code</_comment>
+        <glob pattern="*.js"/>
+    </mime-type>
+
+    <mime-type type="application/json">
+        <sub-class-of type="application/javascript"/>
+        <glob pattern="*.json"/>
+    </mime-type>
+
+    <mime-type type="application/java-vm">
+        <_comment>Java Class File</_comment>
+        <alias type="application/x-java-vm"/>
+        <alias type="application/x-java"/>
+        <magic priority="40">
+            <match value="0xcafebabe" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.class"/>
+    </mime-type>
+
+    <mime-type type="application/x-java-jnilib">
+        <_comment>Java Native Library for OSX</_comment>
+        <magic priority="50">
+            <match value="0xcafebabe" type="string" offset="0">
+                <match value="0xfeedface" type="string" offset="4096"/>
+                <match value="0xfeedfacf" type="string" offset="4096"/>
+                <match value="0xcefaedfe" type="string" offset="4096"/>
+                <match value="0xcffaedfe" type="string" offset="4096"/>
+            </match>
+        </magic>
+        <glob pattern="*.jnilib"/>
+    </mime-type>
+
+    <mime-type type="application/kpml-request+xml"/>
+    <mime-type type="application/kpml-response+xml"/>
+    <mime-type type="application/lost+xml">
+        <glob pattern="*.lostxml"/>
+    </mime-type>
+
+    <mime-type type="application/mac-binhex40">
+        <alias type="application/mac-binhex"/>
+        <alias type="application/binhex"/>
+        <magic priority="50">
+            <match value="must\ be\ converted\ with\ BinHex" type="string" offset="11"/>
+        </magic>
+        <glob pattern="*.hqx"/>
+    </mime-type>
+
+    <mime-type type="application/mac-compactpro">
+        <glob pattern="*.cpt"/>
+    </mime-type>
+
+    <mime-type type="application/macwriteii"/>
+    <mime-type type="application/marc">
+        <glob pattern="*.mrc"/>
+    </mime-type>
+    <mime-type type="application/mathematica">
+        <glob pattern="*.ma"/>
+        <glob pattern="*.nb"/>
+        <glob pattern="*.mb"/>
+    </mime-type>
+    <mime-type type="application/mathml+xml">
+        <glob pattern="*.mathml"/>
+    </mime-type>
+    <mime-type type="application/mbms-associated-procedure-description+xml"/>
+    <mime-type type="application/mbms-deregister+xml"/>
+    <mime-type type="application/mbms-envelope+xml"/>
+    <mime-type type="application/mbms-msk+xml"/>
+    <mime-type type="application/mbms-msk-response+xml"/>
+    <mime-type type="application/mbms-protection-description+xml"/>
+    <mime-type type="application/mbms-reception-report+xml"/>
+    <mime-type type="application/mbms-register+xml"/>
+    <mime-type type="application/mbms-register-response+xml"/>
+    <mime-type type="application/mbms-user-service-description+xml"/>
+    <mime-type type="application/mbox">
+        <sub-class-of type="text/plain"/>
+        <glob pattern="*.mbox"/>
+    </mime-type>
+    <mime-type type="application/media_control+xml"/>
+    <mime-type type="application/mediaservercontrol+xml">
+        <glob pattern="*.mscml"/>
+    </mime-type>
+    <mime-type type="application/mikey"/>
+    <mime-type type="application/moss-keys"/>
+    <mime-type type="application/moss-signature"/>
+    <mime-type type="application/mosskey-data"/>
+    <mime-type type="application/mosskey-request"/>
+    <mime-type type="application/mp4">
+        <glob pattern="*.mp4s"/>
+    </mime-type>
+    <mime-type type="application/mpeg4-generic"/>
+    <mime-type type="application/mpeg4-iod"/>
+    <mime-type type="application/mpeg4-iod-xmt"/>
+
+    <!-- http://www.iana.org/assignments/media-types/application/msword -->
+    <mime-type type="application/msword">
+        <!-- Use DefaultDetector / org.apache.tika.parser.microsoft.POIFSContainerDetector for more reliable detection of OLE2 documents -->
+        <alias type="application/vnd.ms-word"/>
+        <_comment>Microsoft Word Document</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/.doc</tika:link>
+        <tika:uti>com.microsoft.word.doc</tika:uti>
+        <magic priority="50">
+            <match value="Microsoft\ Word\ 6.0\ Document" type="string" offset="2080"/>
+            <match value="Documento\ Microsoft\ Word\ 6" type="string" offset="2080"/>
+            <match value="MSWordDoc" type="string" offset="2112"/>
+            <match value="0x31be0000" type="big32" offset="0"/>
+            <match value="PO^Q`" type="string" offset="0"/>
+            <match value="\376\067\0\043" type="string" offset="0"/>
+            <match value="\333\245-\0\0\0" type="string" offset="0"/>
+            <match value="\224\246\056" type="string" offset="0"/>
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="W\x00o\x00r\x00d\x00D\x00o\x00c\x00u\x00m\x00e\x00n\x00t" type="string" offset="1152:4096" />
+            </match>
+        </magic>
+        <glob pattern="*.doc"/>
+        <glob pattern="*.dot"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/msword2">
+        <!-- Pre-OLE2, not a subtype of application/x-tika-msoffice -->
+        <_comment>Microsoft Word 2 Document</_comment>
+        <magic priority="50">
+            <match value="0x9ba5" type="string" />
+            <match value="0xdba5" type="string" />
+        </magic>
+    </mime-type>
+    <mime-type type="application/msword5">
+        <!-- Pre-OLE2, not a subtype of application/x-tika-msoffice -->
+        <_comment>Microsoft Word 5 Document</_comment>
+        <magic priority="50">
+            <match value="0xfe37" type="string" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/mxf">
+        <glob pattern="*.mxf"/>
+    </mime-type>
+    <mime-type type="application/nasdata"/>
+    <mime-type type="application/news-checkgroups"/>
+    <mime-type type="application/news-groupinfo"/>
+    <mime-type type="application/news-transmission"/>
+    <mime-type type="application/nss"/>
+    <mime-type type="application/ocsp-request"/>
+    <mime-type type="application/ocsp-response"/>
+
+    <mime-type type="application/octet-stream">
+        <magic priority="50">
+            <match value="#\ This\ is\ a\ shell\ archive" type="string" offset="10"/>
+            <match value="\037\036" type="string" offset="0"/>
+            <match value="017437" type="host16" offset="0"/>
+            <match value="0x1fff" type="host16" offset="0"/>
+            <match value="\377\037" type="string" offset="0"/>
+            <match value="0145405" type="host16" offset="0"/>
+        </magic>
+        <glob pattern="*.bin"/>
+        <glob pattern="*.dms"/>
+        <glob pattern="*.lha"/>
+        <glob pattern="*.lrf"/>
+        <glob pattern="*.lzh"/>
+        <glob pattern="*.so"/>
+        <glob pattern="*.dist"/>
+        <glob pattern="*.distz"/>
+        <glob pattern="*.pkg"/>
+        <glob pattern="*.bpk"/>
+        <glob pattern="*.dump"/>
+        <glob pattern="*.elc"/>
+        <glob pattern="*.deploy"/>
+    </mime-type>
+
+    <mime-type type="application/oda">
+        <glob pattern="*.oda"/>
+    </mime-type>
+    <mime-type type="application/oebps-package+xml">
+        <glob pattern="*.opf"/>
+    </mime-type>
+
+    <mime-type type="application/ogg">
+        <alias type="application/x-ogg"/>
+        <magic priority="50">
+            <match value="OggS" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.ogx"/>
+    </mime-type>
+    <mime-type type="application/kate">
+        <sub-class-of type="application/ogg"/>
+    </mime-type>
+
+    <mime-type type="application/onenote">
+        <glob pattern="*.onetoc"/>
+        <glob pattern="*.onetoc2"/>
+        <glob pattern="*.onetmp"/>
+        <glob pattern="*.onepkg"/>
+    </mime-type>
+    <mime-type type="application/parityfec"/>
+    <mime-type type="application/patch-ops-error+xml">
+        <glob pattern="*.xer"/>
+    </mime-type>
+
+    <mime-type type="application/pdf">
+        <alias type="application/x-pdf"/>
+        <acronym>PDF</acronym>
+        <_comment>Portable Document Format</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/PDF</tika:link>
+        <tika:link>http://www.adobe.com/devnet/pdf/pdf_reference_archive.html</tika:link>
+        <tika:uti>com.adobe.pdf</tika:uti>
+        <magic priority="50">
+            <match value="%PDF-" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.pdf"/>
+    </mime-type>
+
+    <mime-type type="application/pgp-encrypted">
+        <alias type="application/pgp"/>
+        <glob pattern="*.pgp"/>
+    </mime-type>
+
+    <mime-type type="application/pgp-keys"/>
+
+    <mime-type type="application/pgp-signature">
+        <glob pattern="*.asc"/>
+        <glob pattern="*.sig"/>
+    </mime-type>
+
+    <mime-type type="application/pics-rules">
+        <glob pattern="*.prf"/>
+    </mime-type>
+    <mime-type type="application/pidf+xml"/>
+    <mime-type type="application/pidf-diff+xml"/>
+    <mime-type type="application/pkcs10">
+        <glob pattern="*.p10"/>
+    </mime-type>
+
+    <mime-type type="application/pkcs7-mime">
+        <glob pattern="*.p7m"/>
+        <glob pattern="*.p7c"/>
+    </mime-type>
+
+    <mime-type type="application/pkcs7-signature">
+        <glob pattern="*.p7s"/>
+        <magic priority="50">
+            <match value="-----BEGIN PKCS7" type="string" offset="0"/>
+            <match value="0x3082FFFF06092a864886f70d0107FFa0" type="string"
+                   mask="0xFFFF0000FFFFFFFFFFFFFFFFFFFF00FF" offset="0"/>
+            <match value="0x308006092a864886f70d0107FFa0" type="string"
+                   mask="0xFFFFFFFFFFFFFFFFFFFFFFFF00FF" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/pkix-cert">
+        <glob pattern="*.cer"/>
+    </mime-type>
+    <mime-type type="application/pkix-crl">
+        <glob pattern="*.crl"/>
+    </mime-type>
+    <mime-type type="application/pkix-pkipath">
+        <glob pattern="*.pkipath"/>
+    </mime-type>
+    <mime-type type="application/pkixcmp">
+        <glob pattern="*.pki"/>
+    </mime-type>
+    <mime-type type="application/pls+xml">
+        <glob pattern="*.pls"/>
+    </mime-type>
+    <mime-type type="application/poc-settings+xml"/>
+
+    <mime-type type="application/postscript">
+        <_comment>PostScript</_comment>
+        <magic priority="50">
+            <match value="%!" type="string" offset="0" />
+            <match value="\004%!" type="string" offset="0" />
+            <!-- Windows format EPS -->
+            <match value="0xc5d0d3c6" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.ps"/>
+        <glob pattern="*.eps"/>
+        <glob pattern="*.epsf"/>
+        <glob pattern="*.epsi"/>
+    </mime-type>
+
+    <mime-type type="application/prs.alvestrand.titrax-sheet"/>
+    <mime-type type="application/prs.cww">
+        <glob pattern="*.cww"/>
+    </mime-type>
+    <mime-type type="application/prs.nprend"/>
+    <mime-type type="application/prs.plucker"/>
+    <mime-type type="application/qsig"/>
+
+    <mime-type type="application/rdf+xml">
+        <root-XML localName="RDF"/>
+        <root-XML localName="RDF" namespaceURI="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
+        <sub-class-of type="application/xml"/>
+        <acronym>RDF/XML</acronym>
+        <_comment>XML syntax for RDF graphs</_comment>
+        <glob pattern="*.rdf"/>
+        <glob pattern="*.owl"/>
+        <glob pattern="^rdf$" isregex="true"/>
+        <glob pattern="^owl$" isregex="true"/>
+        <glob pattern="*.xmp"/>
+    </mime-type>
+
+    <mime-type type="application/reginfo+xml">
+        <glob pattern="*.rif"/>
+    </mime-type>
+    <mime-type type="application/relax-ng-compact-syntax">
+        <sub-class-of type="text/plain"/>
+        <glob pattern="*.rnc"/>
+    </mime-type>
+    <mime-type type="application/remote-printing"/>
+    <mime-type type="application/resource-lists+xml">
+        <glob pattern="*.rl"/>
+    </mime-type>
+    <mime-type type="application/resource-lists-diff+xml">
+        <glob pattern="*.rld"/>
+    </mime-type>
+    <mime-type type="application/riscos"/>
+    <mime-type type="application/rlmi+xml"/>
+    <mime-type type="application/rls-services+xml">
+        <glob pattern="*.rs"/>
+    </mime-type>
+    <mime-type type="application/rsd+xml">
+        <glob pattern="*.rsd"/>
+    </mime-type>
+
+    <mime-type type="application/rss+xml">
+        <alias type="text/rss"/>
+        <root-XML localName="rss"/>
+        <root-XML namespaceURI="http://purl.org/rss/1.0/"/>
+        <glob pattern="*.rss"/>
+    </mime-type>
+
+    <mime-type type="application/rtf">
+        <_comment>Rich Text Format File</_comment>
+        <alias type="text/rtf"/>
+        <magic priority="50">
+            <match value="{\\rtf" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.rtf"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="application/rtx"/>
+    <mime-type type="application/samlassertion+xml"/>
+    <mime-type type="application/samlmetadata+xml"/>
+    <mime-type type="application/sbml+xml">
+        <glob pattern="*.sbml"/>
+    </mime-type>
+    <mime-type type="application/scvp-cv-request">
+        <glob pattern="*.scq"/>
+    </mime-type>
+    <mime-type type="application/scvp-cv-response">
+        <glob pattern="*.scs"/>
+    </mime-type>
+    <mime-type type="application/scvp-vp-request">
+        <glob pattern="*.spq"/>
+    </mime-type>
+    <mime-type type="application/scvp-vp-response">
+        <glob pattern="*.spp"/>
+    </mime-type>
+    <mime-type type="application/sdp">
+        <glob pattern="*.sdp"/>
+    </mime-type>
+    <mime-type type="application/set-payment"/>
+    <mime-type type="application/set-payment-initiation">
+        <glob pattern="*.setpay"/>
+    </mime-type>
+    <mime-type type="application/set-registration"/>
+    <mime-type type="application/set-registration-initiation">
+        <glob pattern="*.setreg"/>
+    </mime-type>
+    <mime-type type="application/sgml"/>
+    <mime-type type="application/sgml-open-catalog"/>
+    <mime-type type="application/shf+xml">
+        <glob pattern="*.shf"/>
+    </mime-type>
+    <mime-type type="application/sieve"/>
+    <mime-type type="application/simple-filter+xml"/>
+    <mime-type type="application/simple-message-summary"/>
+    <mime-type type="application/simplesymbolcontainer"/>
+    <mime-type type="application/slate"/>
+
+    <mime-type type="application/smil+xml">
+        <alias type="application/smil"/>
+        <_comment>SMIL Multimedia</_comment>
+        <glob pattern="*.smi"/>
+        <glob pattern="*.smil"/>
+        <glob pattern="*.sml"/>
+    </mime-type>
+
+    <mime-type type="application/soap+fastinfoset"/>
+    <mime-type type="application/soap+xml"/>
+
+    <mime-type type="application/sldworks">
+        <_comment>SolidWorks CAD program</_comment>
+        <glob pattern="*.sldprt" />
+        <glob pattern="*.sldasm" />
+        <glob pattern="*.slddrw" />
+        <sub-class-of type="application/x-tika-msoffice" />
+    </mime-type>
+
+    <mime-type type="application/sparql-query">
+        <glob pattern="*.rq"/>
+    </mime-type>
+    <mime-type type="application/sparql-results+xml">
+        <glob pattern="*.srx"/>
+    </mime-type>
+    <mime-type type="application/spirits-event+xml"/>
+    <mime-type type="application/srgs">
+        <glob pattern="*.gram"/>
+    </mime-type>
+    <mime-type type="application/srgs+xml">
+        <glob pattern="*.grxml"/>
+    </mime-type>
+    <mime-type type="application/ssml+xml">
+        <glob pattern="*.ssml"/>
+    </mime-type>
+    <mime-type type="application/timestamp-query"/>
+    <mime-type type="application/timestamp-reply"/>
+    <mime-type type="application/tve-trigger"/>
+    <mime-type type="application/ulpfec"/>
+    <mime-type type="application/vemmi"/>
+    <mime-type type="application/vividence.scriptfile"/>
+    <mime-type type="application/vnd.3gpp.bsf+xml"/>
+    <mime-type type="application/vnd.3gpp.pic-bw-large">
+        <glob pattern="*.plb"/>
+    </mime-type>
+    <mime-type type="application/vnd.3gpp.pic-bw-small">
+        <glob pattern="*.psb"/>
+    </mime-type>
+    <mime-type type="application/vnd.3gpp.pic-bw-var">
+        <glob pattern="*.pvb"/>
+    </mime-type>
+    <mime-type type="application/vnd.3gpp.sms"/>
+    <mime-type type="application/vnd.3gpp2.bcmcsinfo+xml"/>
+    <mime-type type="application/vnd.3gpp2.sms"/>
+    <mime-type type="application/vnd.3gpp2.tcap">
+        <glob pattern="*.tcap"/>
+    </mime-type>
+    <mime-type type="application/vnd.3m.post-it-notes">
+        <glob pattern="*.pwn"/>
+    </mime-type>
+    <mime-type type="application/vnd.accpac.simply.aso">
+        <glob pattern="*.aso"/>
+    </mime-type>
+    <mime-type type="application/vnd.accpac.simply.imp">
+        <glob pattern="*.imp"/>
+    </mime-type>
+    <mime-type type="application/vnd.acucobol">
+        <glob pattern="*.acu"/>
+    </mime-type>
+    <mime-type type="application/vnd.acucorp">
+        <glob pattern="*.atc"/>
+        <glob pattern="*.acutc"/>
+    </mime-type>
+    <mime-type type="application/vnd.adobe.air-application-installer-package+zip">
+        <glob pattern="*.air"/>
+    </mime-type>
+    <mime-type type="application/vnd.adobe.aftereffects.project">
+        <glob pattern="*.aep"/>
+    </mime-type>
+    <mime-type type="application/vnd.adobe.aftereffects.template">
+        <glob pattern="*.aet"/>
+    </mime-type>
+    <mime-type type="application/vnd.adobe.xdp+xml">
+        <glob pattern="*.xdp"/>
+    </mime-type>
+    <mime-type type="application/vnd.adobe.xfdf">
+        <glob pattern="*.xfdf"/>
+    </mime-type>
+    <mime-type type="application/vnd.aether.imp"/>
+    <mime-type type="application/vnd.airzip.filesecure.azf">
+        <glob pattern="*.azf"/>
+    </mime-type>
+    <mime-type type="application/vnd.airzip.filesecure.azs">
+        <glob pattern="*.azs"/>
+    </mime-type>
+    <mime-type type="application/vnd.amazon.ebook">
+        <glob pattern="*.azw"/>
+    </mime-type>
+    <mime-type type="application/vnd.americandynamics.acc">
+        <glob pattern="*.acc"/>
+    </mime-type>
+    <mime-type type="application/vnd.amiga.ami">
+        <glob pattern="*.ami"/>
+    </mime-type>
+    <mime-type type="application/vnd.anser-web-certificate-issue-initiation">
+        <glob pattern="*.cii"/>
+    </mime-type>
+    <mime-type type="application/vnd.anser-web-funds-transfer-initiation">
+        <glob pattern="*.fti"/>
+    </mime-type>
+    <mime-type type="application/vnd.antix.game-component">
+        <glob pattern="*.atx"/>
+    </mime-type>
+    <mime-type type="application/vnd.apple.installer+xml">
+        <glob pattern="*.mpkg"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.apple.iwork">
+        <sub-class-of type="application/zip"/>
+    </mime-type>
+    <mime-type type="application/vnd.apple.keynote">
+        <root-XML localName="presentation" namespaceURI="http://developer.apple.com/namespaces/keynote2" />
+        <sub-class-of type="application/vnd.apple.iwork" />
+        <glob pattern="*.key"/>
+    </mime-type>
+    <mime-type type="application/vnd.apple.pages">
+        <root-XML localName="document" namespaceURI="http://developer.apple.com/namespaces/sl" />
+        <sub-class-of type="application/vnd.apple.iwork" />
+        <glob pattern="*.pages"/>
+    </mime-type>
+    <mime-type type="application/vnd.apple.numbers">
+        <root-XML localName="document" namespaceURI="http://developer.apple.com/namespaces/ls" />
+        <sub-class-of type="application/vnd.apple.iwork" />
+        <glob pattern="*.numbers"/>
+    </mime-type>
+    <mime-type type="application/x-tika-iworks-protected">
+        <sub-class-of type="application/vnd.apple.iwork" />
+        <_comment>Password Protected iWorks File</_comment>
+    </mime-type>
+
+    <mime-type type="application/vnd.arastra.swi">
+        <glob pattern="*.swi"/>
+    </mime-type>
+    <mime-type type="application/vnd.audiograph"/>
+    <mime-type type="application/vnd.autopackage"/>
+    <mime-type type="application/vnd.avistar+xml"/>
+    <mime-type type="application/vnd.blueice.multipass">
+        <glob pattern="*.mpm"/>
+    </mime-type>
+    <mime-type type="application/vnd.bluetooth.ep.oob"/>
+    <mime-type type="application/vnd.bmi">
+        <glob pattern="*.bmi"/>
+    </mime-type>
+    <mime-type type="application/vnd.businessobjects">
+        <glob pattern="*.rep"/>
+    </mime-type>
+    <mime-type type="application/vnd.cab-jscript"/>
+    <mime-type type="application/vnd.canon-cpdl"/>
+    <mime-type type="application/vnd.canon-lips"/>
+    <mime-type type="application/vnd.cendio.thinlinc.clientconf"/>
+    <mime-type type="application/vnd.chemdraw+xml">
+        <glob pattern="*.cdxml"/>
+    </mime-type>
+    <mime-type type="application/vnd.chipnuts.karaoke-mmd">
+        <glob pattern="*.mmd"/>
+    </mime-type>
+    <mime-type type="application/vnd.cinderella">
+        <glob pattern="*.cdy"/>
+    </mime-type>
+    <mime-type type="application/vnd.cirpack.isdn-ext"/>
+    <mime-type type="application/vnd.claymore">
+        <glob pattern="*.cla"/>
+    </mime-type>
+    <mime-type type="application/vnd.clonk.c4group">
+        <glob pattern="*.c4g"/>
+        <glob pattern="*.c4d"/>
+        <glob pattern="*.c4f"/>
+        <glob pattern="*.c4p"/>
+        <glob pattern="*.c4u"/>
+    </mime-type>
+    <mime-type type="application/vnd.commerce-battelle"/>
+    <mime-type type="application/vnd.commonspace">
+        <glob pattern="*.csp"/>
+    </mime-type>
+    <mime-type type="application/vnd.contact.cmsg">
+        <glob pattern="*.cdbcmsg"/>
+    </mime-type>
+    <mime-type type="application/vnd.cosmocaller">
+        <glob pattern="*.cmc"/>
+    </mime-type>
+    <mime-type type="application/vnd.crick.clicker">
+        <glob pattern="*.clkx"/>
+    </mime-type>
+    <mime-type type="application/vnd.crick.clicker.keyboard">
+        <glob pattern="*.clkk"/>
+    </mime-type>
+    <mime-type type="application/vnd.crick.clicker.palette">
+        <glob pattern="*.clkp"/>
+    </mime-type>
+    <mime-type type="application/vnd.crick.clicker.template">
+        <glob pattern="*.clkt"/>
+    </mime-type>
+    <mime-type type="application/vnd.crick.clicker.wordbank">
+        <glob pattern="*.clkw"/>
+    </mime-type>
+    <mime-type type="application/vnd.criticaltools.wbs+xml">
+        <glob pattern="*.wbs"/>
+    </mime-type>
+    <mime-type type="application/vnd.ctc-posml">
+        <glob pattern="*.pml"/>
+    </mime-type>
+    <mime-type type="application/vnd.ctct.ws+xml"/>
+    <mime-type type="application/vnd.cups-pdf"/>
+    <mime-type type="application/vnd.cups-postscript"/>
+    <mime-type type="application/vnd.cups-ppd">
+        <glob pattern="*.ppd"/>
+    </mime-type>
+    <mime-type type="application/vnd.cups-raster"/>
+    <mime-type type="application/vnd.cups-raw"/>
+    <mime-type type="application/vnd.curl.car">
+        <glob pattern="*.car"/>
+    </mime-type>
+    <mime-type type="application/vnd.curl.pcurl">
+        <glob pattern="*.pcurl"/>
+    </mime-type>
+    <mime-type type="application/vnd.cybank"/>
+    <mime-type type="application/vnd.data-vision.rdz">
+        <glob pattern="*.rdz"/>
+    </mime-type>
+    <mime-type type="application/vnd.denovo.fcselayout-link">
+        <glob pattern="*.fe_launch"/>
+    </mime-type>
+    <mime-type type="application/vnd.dir-bi.plate-dl-nosuffix"/>
+    <mime-type type="application/vnd.dna">
+        <glob pattern="*.dna"/>
+    </mime-type>
+    <mime-type type="application/vnd.dolby.mlp">
+        <glob pattern="*.mlp"/>
+    </mime-type>
+    <mime-type type="application/vnd.dolby.mobile.1"/>
+    <mime-type type="application/vnd.dolby.mobile.2"/>
+    <mime-type type="application/vnd.dpgraph">
+        <glob pattern="*.dpg"/>
+    </mime-type>
+    <mime-type type="application/vnd.dreamfactory">
+        <glob pattern="*.dfac"/>
+    </mime-type>
+    <mime-type type="application/vnd.dvb.esgcontainer"/>
+    <mime-type type="application/vnd.dvb.ipdcdftnotifaccess"/>
+    <mime-type type="application/vnd.dvb.ipdcesgaccess"/>
+    <mime-type type="application/vnd.dvb.ipdcroaming"/>
+    <mime-type type="application/vnd.dvb.iptv.alfec-base"/>
+    <mime-type type="application/vnd.dvb.iptv.alfec-enhancement"/>
+    <mime-type type="application/vnd.dvb.notif-aggregate-root+xml"/>
+    <mime-type type="application/vnd.dvb.notif-container+xml"/>
+    <mime-type type="application/vnd.dvb.notif-generic+xml"/>
+    <mime-type type="application/vnd.dvb.notif-ia-msglist+xml"/>
+    <mime-type type="application/vnd.dvb.notif-ia-registration-request+xml"/>
+    <mime-type type="application/vnd.dvb.notif-ia-registration-response+xml"/>
+    <mime-type type="application/vnd.dvb.notif-init+xml"/>
+    <mime-type type="application/vnd.dxr"/>
+    <mime-type type="application/vnd.dynageo">
+        <glob pattern="*.geo"/>
+    </mime-type>
+    <mime-type type="application/vnd.ecdis-update"/>
+    <mime-type type="application/vnd.ecowin.chart">
+        <glob pattern="*.mag"/>
+    </mime-type>
+    <mime-type type="application/vnd.ecowin.filerequest"/>
+    <mime-type type="application/vnd.ecowin.fileupdate"/>
+    <mime-type type="application/vnd.ecowin.series"/>
+    <mime-type type="application/vnd.ecowin.seriesrequest"/>
+    <mime-type type="application/vnd.ecowin.seriesupdate"/>
+    <mime-type type="application/vnd.emclient.accessrequest+xml"/>
+    <mime-type type="application/vnd.enliven">
+        <glob pattern="*.nml"/>
+    </mime-type>
+    <mime-type type="application/vnd.epson.esf">
+        <glob pattern="*.esf"/>
+    </mime-type>
+    <mime-type type="application/vnd.epson.msf">
+        <glob pattern="*.msf"/>
+    </mime-type>
+    <mime-type type="application/vnd.epson.quickanime">
+        <glob pattern="*.qam"/>
+    </mime-type>
+    <mime-type type="application/vnd.epson.salt">
+        <glob pattern="*.slt"/>
+    </mime-type>
+    <mime-type type="application/vnd.epson.ssf">
+        <glob pattern="*.ssf"/>
+    </mime-type>
+    <mime-type type="application/vnd.ericsson.quickcall"/>
+    <mime-type type="application/vnd.eszigno3+xml">
+        <glob pattern="*.es3"/>
+        <glob pattern="*.et3"/>
+    </mime-type>
+    <mime-type type="application/vnd.etsi.aoc+xml"/>
+    <mime-type type="application/vnd.etsi.cug+xml"/>
+    <mime-type type="application/vnd.etsi.iptvcommand+xml"/>
+    <mime-type type="application/vnd.etsi.iptvdiscovery+xml"/>
+    <mime-type type="application/vnd.etsi.iptvprofile+xml"/>
+    <mime-type type="application/vnd.etsi.iptvsad-bc+xml"/>
+    <mime-type type="application/vnd.etsi.iptvsad-cod+xml"/>
+    <mime-type type="application/vnd.etsi.iptvsad-npvr+xml"/>
+    <mime-type type="application/vnd.etsi.iptvueprofile+xml"/>
+    <mime-type type="application/vnd.etsi.mcid+xml"/>
+    <mime-type type="application/vnd.etsi.sci+xml"/>
+    <mime-type type="application/vnd.etsi.simservs+xml"/>
+    <mime-type type="application/vnd.eudora.data"/>
+    <mime-type type="application/vnd.ezpix-album">
+        <glob pattern="*.ez2"/>
+    </mime-type>
+    <mime-type type="application/vnd.ezpix-package">
+        <glob pattern="*.ez3"/>
+    </mime-type>
+    <mime-type type="application/vnd.f-secure.mobile"/>
+    <mime-type type="application/vnd.fdf">
+        <acronym>FDF</acronym>
+        <_comment>Forms Data Format</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/Forms_Data_Format</tika:link>
+        <tika:link>http://www.adobe.com/devnet/acrobat/fdftoolkit.html</tika:link>
+        <tika:uti>com.adobe.fdf</tika:uti>
+        <magic priority="50">
+            <match value="%FDF-" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.fdf"/>
+    </mime-type>
+    <mime-type type="application/vnd.fdsn.mseed">
+        <glob pattern="*.mseed"/>
+    </mime-type>
+    <mime-type type="application/vnd.fdsn.seed">
+        <glob pattern="*.seed"/>
+        <glob pattern="*.dataless"/>
+    </mime-type>
+    <mime-type type="application/vnd.ffsns"/>
+    <mime-type type="application/vnd.fints"/>
+    <mime-type type="application/vnd.flographit">
+        <glob pattern="*.gph"/>
+    </mime-type>
+    <mime-type type="application/vnd.fluxtime.clip">
+        <glob pattern="*.ftc"/>
+    </mime-type>
+    <mime-type type="application/vnd.font-fontforge-sfd"/>
+    <mime-type type="application/vnd.framemaker">
+        <glob pattern="*.fm"/>
+        <glob pattern="*.frame"/>
+        <glob pattern="*.maker"/>
+        <glob pattern="*.book"/>
+    </mime-type>
+    <mime-type type="application/vnd.frogans.fnc">
+        <glob pattern="*.fnc"/>
+    </mime-type>
+    <mime-type type="application/vnd.frogans.ltf">
+        <glob pattern="*.ltf"/>
+    </mime-type>
+    <mime-type type="application/vnd.fsc.weblaunch">
+        <glob pattern="*.fsc"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujitsu.oasys">
+        <glob pattern="*.oas"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujitsu.oasys2">
+        <glob pattern="*.oa2"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujitsu.oasys3">
+        <glob pattern="*.oa3"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujitsu.oasysgp">
+        <glob pattern="*.fg5"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujitsu.oasysprs">
+        <glob pattern="*.bh2"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujixerox.art-ex"/>
+    <mime-type type="application/vnd.fujixerox.art4"/>
+    <mime-type type="application/vnd.fujixerox.hbpl"/>
+    <mime-type type="application/vnd.fujixerox.ddd">
+        <glob pattern="*.ddd"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujixerox.docuworks">
+        <glob pattern="*.xdw"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujixerox.docuworks.binder">
+        <glob pattern="*.xbd"/>
+    </mime-type>
+    <mime-type type="application/vnd.fut-misnet"/>
+    <mime-type type="application/vnd.fuzzysheet">
+        <glob pattern="*.fzs"/>
+    </mime-type>
+    <mime-type type="application/vnd.genomatix.tuxedo">
+        <glob pattern="*.txd"/>
+    </mime-type>
+    <mime-type type="application/vnd.geogebra.file">
+        <glob pattern="*.ggb"/>
+    </mime-type>
+    <mime-type type="application/vnd.geogebra.tool">
+        <glob pattern="*.ggt"/>
+    </mime-type>
+    <mime-type type="application/vnd.geometry-explorer">
+        <glob pattern="*.gex"/>
+        <glob pattern="*.gre"/>
+    </mime-type>
+    <mime-type type="application/vnd.gmx">
+        <glob pattern="*.gmx"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.google-earth.kml+xml">
+        <root-XML localName="kml"/>
+        <root-XML namespaceURI="http://www.opengis.net/kml/2.2" localName="kml"/>
+        <root-XML namespaceURI="http://earth.google.com/kml/2.0" localName="kml"/>
+        <root-XML namespaceURI="http://earth.google.com/kml/2.1" localName="kml"/>
+        <root-XML namespaceURI="http://earth.google.com/kml/2.2" localName="kml"/>
+        <acronym>KML</acronym>
+        <_comment>Keyhole Markup Language</_comment>
+        <glob pattern="*.kml"/>
+        <sub-class-of type="application/xml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.google-earth.kmz">
+        <sub-class-of type="application/zip"/>
+        <glob pattern="*.kmz"/>
+    </mime-type>
+    <mime-type type="application/vnd.grafeq">
+        <glob pattern="*.gqf"/>
+        <glob pattern="*.gqs"/>
+    </mime-type>
+    <mime-type type="application/vnd.gridmp"/>
+    <mime-type type="application/vnd.groove-account">
+        <glob pattern="*.gac"/>
+    </mime-type>
+    <mime-type type="application/vnd.groove-help">
+        <glob pattern="*.ghf"/>
+    </mime-type>
+    <mime-type type="application/vnd.groove-identity-message">
+        <glob pattern="*.gim"/>
+    </mime-type>
+    <mime-type type="application/vnd.groove-injector">
+        <glob pattern="*.grv"/>
+    </mime-type>
+    <mime-type type="application/vnd.groove-tool-message">
+        <glob pattern="*.gtm"/>
+    </mime-type>
+    <mime-type type="application/vnd.groove-tool-template">
+        <glob pattern="*.tpl"/>
+    </mime-type>
+    <mime-type type="application/vnd.groove-vcard">
+        <glob pattern="*.vcg"/>
+    </mime-type>
+    <mime-type type="application/vnd.handheld-entertainment+xml">
+        <glob pattern="*.zmm"/>
+    </mime-type>
+    <mime-type type="application/vnd.hbci">
+        <glob pattern="*.hbci"/>
+    </mime-type>
+    <mime-type type="application/vnd.hcl-bireports"/>
+    <mime-type type="application/vnd.hhe.lesson-player">
+        <glob pattern="*.les"/>
+    </mime-type>
+    <mime-type type="application/vnd.hp-hpgl">
+        <glob pattern="*.hpgl"/>
+    </mime-type>
+    <mime-type type="application/vnd.hp-hpid">
+        <glob pattern="*.hpid"/>
+    </mime-type>
+    <mime-type type="application/vnd.hp-hps">
+        <glob pattern="*.hps"/>
+    </mime-type>
+    <mime-type type="application/vnd.hp-jlyt">
+        <glob pattern="*.jlt"/>
+    </mime-type>
+    <mime-type type="application/vnd.hp-pcl">
+        <glob pattern="*.pcl"/>
+    </mime-type>
+    <mime-type type="application/vnd.hp-pclxl">
+        <glob pattern="*.pclxl"/>
+    </mime-type>
+    <mime-type type="application/vnd.httphone"/>
+    <mime-type type="application/vnd.hydrostatix.sof-data">
+        <glob pattern="*.sfd-hdstx"/>
+    </mime-type>
+    <mime-type type="application/vnd.hzn-3d-crossword">
+        <glob pattern="*.x3d"/>
+    </mime-type>
+    <mime-type type="application/vnd.ibm.afplinedata"/>
+    <mime-type type="application/vnd.ibm.electronic-media"/>
+    <mime-type type="application/vnd.ibm.minipay">
+        <glob pattern="*.mpy"/>
+    </mime-type>
+    <mime-type type="application/vnd.ibm.modcap">
+        <glob pattern="*.afp"/>
+        <glob pattern="*.listafp"/>
+        <glob pattern="*.list3820"/>
+    </mime-type>
+    <mime-type type="application/vnd.ibm.rights-management">
+        <glob pattern="*.irm"/>
+    </mime-type>
+    <mime-type type="application/vnd.ibm.secure-container">
+        <glob pattern="*.sc"/>
+    </mime-type>
+    <mime-type type="application/vnd.iccprofile">
+        <glob pattern="*.icc"/>
+        <glob pattern="*.icm"/>
+    </mime-type>
+    <mime-type type="application/vnd.igloader">
+        <glob pattern="*.igl"/>
+    </mime-type>
+    <mime-type type="application/vnd.immervision-ivp">
+        <glob pattern="*.ivp"/>
+    </mime-type>
+    <mime-type type="application/vnd.immervision-ivu">
+        <glob pattern="*.ivu"/>
+    </mime-type>
+    <mime-type type="application/vnd.informedcontrol.rms+xml"/>
+    <mime-type type="application/vnd.informix-visionary"/>
+    <mime-type type="application/vnd.intercon.formnet">
+        <glob pattern="*.xpw"/>
+        <glob pattern="*.xpx"/>
+    </mime-type>
+    <mime-type type="application/vnd.intertrust.digibox"/>
+    <mime-type type="application/vnd.intertrust.nncp"/>
+    <mime-type type="application/vnd.intu.qbo">
+        <glob pattern="*.qbo"/>
+    </mime-type>
+    <mime-type type="application/vnd.intu.qfx">
+        <glob pattern="*.qfx"/>
+    </mime-type>
+    <mime-type type="application/vnd.iptc.g2.conceptitem+xml"/>
+    <mime-type type="application/vnd.iptc.g2.knowledgeitem+xml"/>
+    <mime-type type="application/vnd.iptc.g2.newsitem+xml"/>
+    <mime-type type="application/vnd.iptc.g2.packageitem+xml"/>
+    <mime-type type="application/vnd.ipunplugged.rcprofile">
+        <glob pattern="*.rcprofile"/>
+    </mime-type>
+    <mime-type type="application/vnd.irepository.package+xml">
+        <glob pattern="*.irp"/>
+    </mime-type>
+    <mime-type type="application/vnd.is-xpr">
+        <glob pattern="*.xpr"/>
+    </mime-type>
+    <mime-type type="application/vnd.jam">
+        <glob pattern="*.jam"/>
+    </mime-type>
+    <mime-type type="application/vnd.japannet-directory-service"/>
+    <mime-type type="application/vnd.japannet-jpnstore-wakeup"/>
+    <mime-type type="application/vnd.japannet-payment-wakeup"/>
+    <mime-type type="application/vnd.japannet-registration"/>
+    <mime-type type="application/vnd.japannet-registration-wakeup"/>
+    <mime-type type="application/vnd.japannet-setstore-wakeup"/>
+    <mime-type type="application/vnd.japannet-verification"/>
+    <mime-type type="application/vnd.japannet-verification-wakeup"/>
+    <mime-type type="application/vnd.jcp.javame.midlet-rms">
+        <glob pattern="*.rms"/>
+    </mime-type>
+    <mime-type type="application/vnd.jisp">
+        <glob pattern="*.jisp"/>
+    </mime-type>
+    <mime-type type="application/vnd.joost.joda-archive">
+        <glob pattern="*.joda"/>
+    </mime-type>
+    <mime-type type="application/vnd.kahootz">
+        <glob pattern="*.ktz"/>
+        <glob pattern="*.ktr"/>
+    </mime-type>
+    <mime-type type="application/vnd.kde.karbon">
+        <glob pattern="*.karbon"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kchart">
+        <alias type="application/x-kchart"/>
+        <_comment>KChart File</_comment>
+        <glob pattern="*.chrt"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kformula">
+        <glob pattern="*.kfo"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kivio">
+        <glob pattern="*.flw"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kontour">
+        <glob pattern="*.kon"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kpresenter">
+        <alias type="application/x-kpresenter"/>
+        <_comment>KPresenter File</_comment>
+        <glob pattern="*.kpr"/>
+        <glob pattern="*.kpt"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kspread">
+        <alias type="application/x-kspread"/>
+        <_comment>KSpread File</_comment>
+        <glob pattern="*.ksp"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kword">
+        <alias type="application/x-kword"/>
+        <_comment>KWord File</_comment>
+        <glob pattern="*.kwd"/>
+        <glob pattern="*.kwt"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kenameaapp">
+        <glob pattern="*.htke"/>
+    </mime-type>
+    <mime-type type="application/vnd.kidspiration">
+        <glob pattern="*.kia"/>
+    </mime-type>
+    <mime-type type="application/vnd.kinar">
+        <glob pattern="*.kne"/>
+        <glob pattern="*.knp"/>
+    </mime-type>
+    <mime-type type="application/vnd.koan">
+        <alias type="application/x-koan"/>
+        <_comment>SSEYO Koan File</_comment>
+        <glob pattern="*.skp"/>
+        <glob pattern="*.skd"/>
+        <glob pattern="*.skt"/>
+        <glob pattern="*.skm"/>
+    </mime-type>
+    <mime-type type="application/vnd.kodak-descriptor">
+        <glob pattern="*.sse"/>
+    </mime-type>
+    <mime-type type="application/vnd.liberty-request+xml"/>
+    <mime-type type="application/vnd.llamagraphics.life-balance.desktop">
+        <glob pattern="*.lbd"/>
+    </mime-type>
+    <mime-type type="application/vnd.llamagraphics.life-balance.exchange+xml">
+        <glob pattern="*.lbe"/>
+    </mime-type>
+    <mime-type type="application/vnd.lotus-1-2-3">
+        <glob pattern="*.123"/>
+    </mime-type>
+    <mime-type type="application/vnd.lotus-approach">
+        <glob pattern="*.apr"/>
+    </mime-type>
+    <mime-type type="application/vnd.lotus-freelance">
+        <glob pattern="*.pre"/>
+    </mime-type>
+    <mime-type type="application/vnd.lotus-notes">
+        <glob pattern="*.nsf"/>
+    </mime-type>
+    <mime-type type="application/vnd.lotus-organizer">
+        <glob pattern="*.org"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.lotus-screencam">
+        <!-- <glob pattern="*.scm"/> - conflicts with text/x-scheme -->
+    </mime-type>
+
+    <mime-type type="application/vnd.lotus-wordpro">
+        <magic priority="50">
+            <match value="WordPro\0" type="string" offset="0" />
+            <match value="WordPro\r\373" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.lwp"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.macports.portpkg">
+        <glob pattern="*.portpkg"/>
+    </mime-type>
+    <mime-type type="application/vnd.marlin.drm.actiontoken+xml"/>
+    <mime-type type="application/vnd.marlin.drm.conftoken+xml"/>
+    <mime-type type="application/vnd.marlin.drm.license+xml"/>
+    <mime-type type="application/vnd.marlin.drm.mdcf"/>
+    <mime-type type="application/vnd.mcd">
+        <glob pattern="*.mcd"/>
+    </mime-type>
+    <mime-type type="application/vnd.medcalcdata">
+        <glob pattern="*.mc1"/>
+    </mime-type>
+    <mime-type type="application/vnd.mediastation.cdkey">
+        <glob pattern="*.cdkey"/>
+    </mime-type>
+    <mime-type type="application/vnd.meridian-slingshot"/>
+    <mime-type type="application/vnd.mfer">
+        <glob pattern="*.mwf"/>
+    </mime-type>
+    <mime-type type="application/vnd.mfmp">
+        <glob pattern="*.mfm"/>
+    </mime-type>
+    <mime-type type="application/vnd.micrografx.flo">
+        <glob pattern="*.flo"/>
+    </mime-type>
+    <mime-type type="application/vnd.micrografx.igx">
+        <glob pattern="*.igx"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.mif">
+        <_comment>FrameMaker Interchange Format</_comment>
+        <alias type="application/x-mif"/>
+        <alias type="application/x-frame"/>
+        <magic priority="50">
+            <match value="\&lt;MakerFile" type="string" offset="0" />
+            <match value="\&lt;MIFFile" type="string" offset="0" />
+            <match value="\&lt;MakerDictionary" type="string" offset="0" />
+            <match value="\&lt;MakerScreenFont" type="string" offset="0" />
+            <match value="\&lt;MML" type="string" offset="0" />
+            <match value="\&lt;Book" type="string" offset="0" />
+            <match value="\&lt;Maker" type="string" offset="0" />
+            <match value="\x3c\x4d\x49\x46\x46\x69\x6c\x65\x20" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.mif"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.mindjet.mindmanager">
+        <_comment>MindManager</_comment>
+        <sub-class-of type="application/zip"/>
+        <glob pattern="*.mmp"/>
+        <glob pattern="*.mmap"/>
+        <glob pattern="*.mmpt"/>
+        <glob pattern="*.mmat"/>
+        <glob pattern="*.mmmp"/>
+        <glob pattern="*.mmas"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.minisoft-hp3000-save"/>
+    <mime-type type="application/vnd.mitsubishi.misty-guard.trustweb"/>
+    <mime-type type="application/vnd.mobius.daf">
+        <glob pattern="*.daf"/>
+    </mime-type>
+    <mime-type type="application/vnd.mobius.dis">
+        <glob pattern="*.dis"/>
+    </mime-type>
+    <mime-type type="application/vnd.mobius.mbk">
+        <glob pattern="*.mbk"/>
+    </mime-type>
+    <mime-type type="application/vnd.mobius.mqy">
+        <glob pattern="*.mqy"/>
+    </mime-type>
+    <mime-type type="application/vnd.mobius.msl">
+        <glob pattern="*.msl"/>
+    </mime-type>
+    <mime-type type="application/vnd.mobius.plc">
+        <glob pattern="*.plc"/>
+    </mime-type>
+    <mime-type type="application/vnd.mobius.txf">
+        <glob pattern="*.txf"/>
+    </mime-type>
+    <mime-type type="application/vnd.mophun.application">
+        <glob pattern="*.mpn"/>
+    </mime-type>
+    <mime-type type="application/vnd.mophun.certificate">
+        <glob pattern="*.mpc"/>
+    </mime-type>
+    <mime-type type="application/vnd.motorola.flexsuite"/>
+    <mime-type type="application/vnd.motorola.flexsuite.adsi"/>
+    <mime-type type="application/vnd.motorola.flexsuite.fis"/>
+    <mime-type type="application/vnd.motorola.flexsuite.gotap"/>
+    <mime-type type="application/vnd.motorola.flexsuite.kmr"/>
+    <mime-type type="application/vnd.motorola.flexsuite.ttc"/>
+    <mime-type type="application/vnd.motorola.flexsuite.wem"/>
+    <mime-type type="application/vnd.motorola.iprm"/>
+    <mime-type type="application/vnd.mozilla.xul+xml">
+        <glob pattern="*.xul"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-artgalry">
+        <glob pattern="*.cil"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-asf"/>
+    <mime-type type="application/vnd.ms-cab-compressed">
+        <glob pattern="*.cab"/>
+    </mime-type>
+
+    <!-- http://www.iana.org/assignments/media-types/application/vnd.ms-excel -->
+    <mime-type type="application/vnd.ms-excel">
+        <!-- Use DefaultDetector / org.apache.tika.parser.microsoft.POIFSContainerDetector for more reliable detection of OLE2 documents -->
+        <alias type="application/msexcel" />
+        <_comment>Microsoft Excel Spreadsheet</_comment>
+        <magic priority="50">
+            <match value="Microsoft\ Excel\ 5.0\ Worksheet" type="string" offset="2080"/>
+            <match value="Foglio\ di\ lavoro\ Microsoft\ Exce" type="string" offset="2080"/>
+            <match value="Biff5" type="string" offset="2114"/>
+            <match value="Biff5" type="string" offset="2121"/>
+            <match value="\x09\x04\x06\x00\x00\x00\x10\x00" type="string" offset="0"/>
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="W\x00o\x00r\x00k\x00b\x00o\x00o\x00k" type="string" offset="1152:4096" />
+            </match>
+        </magic>
+        <glob pattern="*.xls"/>
+        <glob pattern="*.xlm"/>
+        <glob pattern="*.xla"/>
+        <glob pattern="*.xlc"/>
+        <glob pattern="*.xlt"/>
+        <glob pattern="*.xlw"/>
+        <glob pattern="*.xll"/>
+        <glob pattern="*.xld"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-excel.addin.macroenabled.12">
+        <_comment>Office Open XML Workbook Add-in (macro-enabled)</_comment>
+        <glob pattern="*.xlam"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-excel.sheet.macroenabled.12">
+        <_comment>Office Open XML Workbook (macro-enabled)</_comment>
+        <glob pattern="*.xlsm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-excel.sheet.binary.macroenabled.12">
+        <_comment>Microsoft Excel 2007 Binary Spreadsheet</_comment>
+        <glob pattern="*.xlsb"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-fontobject">
+        <glob pattern="*.eot"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-htmlhelp">
+        <glob pattern="*.chm"/>
+        <magic priority="50">
+            <match value="ITSF" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+    <mime-type type="application/vnd.ms-ims">
+        <glob pattern="*.ims"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-lrm">
+        <glob pattern="*.lrm"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-outlook">
+        <_comment>Microsoft Outlook Message</_comment>
+        <glob pattern="*.msg" />
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-outlook-pst">
+        <_comment>Outlook Personal Folders File Format</_comment>
+        <magic priority="50">
+            <match value="!BDN....SM" type="string" offset="0" mask="0xFFFFFFFF00000000FFFF"/>
+        </magic>
+        <glob pattern="*.pst"/>
+        <glob pattern="*.ost"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-pki.seccat">
+        <glob pattern="*.cat"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-pki.stl">
+        <glob pattern="*.stl"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-playready.initiator+xml"/>
+
+    <!-- http://www.iana.org/assignments/media-types/application/vnd.ms-powerpoint -->
+    <mime-type type="application/vnd.ms-powerpoint">
+        <!-- Use DefaultDetector / org.apache.tika.parser.microsoft.POIFSContainerDetector for more reliable detection of OLE2 documents -->
+        <alias type="application/mspowerpoint"/>
+        <_comment>Microsoft Powerpoint Presentation</_comment>
+        <magic priority="50">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="P\x00o\x00w\x00e\x00r\x00P\x00o\x00i\x00n\x00t\x00 D\x00o\x00c\x00u\x00m\x00e\x00n\x00t" type="string" offset="1152:4096" />
+            </match>
+        </magic>
+        <glob pattern="*.ppt"/>
+        <glob pattern="*.ppz"/>
+        <glob pattern="*.pps"/>
+        <glob pattern="*.pot"/>
+        <glob pattern="*.ppa"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-powerpoint.addin.macroenabled.12">
+        <_comment>Office Open XML Presentation Add-in (macro-enabled)</_comment>
+        <glob pattern="*.ppam"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-powerpoint.presentation.macroenabled.12">
+        <_comment>Office Open XML Presentation (macro-enabled)</_comment>
+        <glob pattern="*.pptm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-powerpoint.slide.macroenabled.12">
+        <glob pattern="*.sldm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-powerpoint.slideshow.macroenabled.12">
+        <_comment>Office Open XML Presentation Slideshow (macro-enabled)</_comment>
+        <glob pattern="*.ppsm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-powerpoint.template.macroenabled.12">
+        <glob pattern="*.potm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-project">
+        <glob pattern="*.mpp"/>
+        <glob pattern="*.mpt"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/x-project">
+        <glob pattern="*.mpx"/>
+        <magic priority="50">
+            <match value="MPX,Microsoft Project for Windows," type="string" offset="0"/>
+        </magic>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-tnef">
+        <alias type="application/ms-tnef" />
+        <magic priority="50">
+            <match value="0x223e9f78" type="little32" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-wmdrm.lic-chlg-req"/>
+    <mime-type type="application/vnd.ms-wmdrm.lic-resp"/>
+    <mime-type type="application/vnd.ms-wmdrm.meter-chlg-req"/>
+    <mime-type type="application/vnd.ms-wmdrm.meter-resp"/>
+
+    <mime-type type="application/vnd.ms-word.document.macroenabled.12">
+        <_comment>Office Open XML Document (macro-enabled)</_comment>
+        <glob pattern="*.docm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-word.template.macroenabled.12">
+        <_comment>Office Open XML Document Template (macro-enabled)</_comment>
+        <glob pattern="*.dotm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-works">
+        <magic priority="50">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="M\x00a\x00t\x00O\x00S\x00T" type="string" offset="1152:4096" />
+            </match>
+        </magic>
+        <glob pattern="*.wps"/>
+        <glob pattern="*.wks"/>
+        <glob pattern="*.wcm"/>
+        <glob pattern="*.wdb"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-wpl">
+        <glob pattern="*.wpl"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-xpsdocument">
+        <alias type="application/oxps"/>
+        <_comment>Open XML Paper Specification</_comment>
+        <glob pattern="*.xps"/>
+        <glob pattern="*.oxps"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+    <mime-type type="application/vnd.mseq">
+        <glob pattern="*.mseq"/>
+    </mime-type>
+    <mime-type type="application/vnd.msign"/>
+    <mime-type type="application/vnd.multiad.creator"/>
+    <mime-type type="application/vnd.multiad.creator.cif"/>
+    <mime-type type="application/vnd.music-niff"/>
+    <mime-type type="application/vnd.musician">
+        <glob pattern="*.mus"/>
+    </mime-type>
+    <mime-type type="application/vnd.muvee.style">
+        <glob pattern="*.msty"/>
+    </mime-type>
+    <mime-type type="application/vnd.ncd.control"/>
+    <mime-type type="application/vnd.ncd.reference"/>
+    <mime-type type="application/vnd.nervana"/>
+    <mime-type type="application/vnd.netfpx"/>
+    <mime-type type="application/vnd.neurolanguage.nlu">
+        <glob pattern="*.nlu"/>
+    </mime-type>
+    <mime-type type="application/vnd.noblenet-directory">
+        <glob pattern="*.nnd"/>
+    </mime-type>
+    <mime-type type="application/vnd.noblenet-sealer">
+        <glob pattern="*.nns"/>
+    </mime-type>
+    <mime-type type="application/vnd.noblenet-web">
+        <glob pattern="*.nnw"/>
+    </mime-type>
+    <mime-type type="application/vnd.nokia.catalogs"/>
+    <mime-type type="application/vnd.nokia.conml+wbxml"/>
+    <mime-type type="application/vnd.nokia.conml+xml"/>
+    <mime-type type="application/vnd.nokia.isds-radio-presets"/>
+    <mime-type type="application/vnd.nokia.iptv.config+xml"/>
+    <mime-type type="application/vnd.nokia.landmark+wbxml"/>
+    <mime-type type="application/vnd.nokia.landmark+xml"/>
+    <mime-type type="application/vnd.nokia.landmarkcollection+xml"/>
+    <mime-type type="application/vnd.nokia.n-gage.ac+xml"/>
+    <mime-type type="application/vnd.nokia.n-gage.data">
+        <glob pattern="*.ngdat"/>
+    </mime-type>
+    <mime-type type="application/vnd.nokia.n-gage.symbian.install">
+        <glob pattern="*.n-gage"/>
+    </mime-type>
+    <mime-type type="application/vnd.nokia.ncd"/>
+    <mime-type type="application/vnd.nokia.pcd+wbxml"/>
+    <mime-type type="application/vnd.nokia.pcd+xml"/>
+    <mime-type type="application/vnd.nokia.radio-preset">
+        <glob pattern="*.rpst"/>
+    </mime-type>
+    <mime-type type="application/vnd.nokia.radio-presets">
+        <glob pattern="*.rpss"/>
+    </mime-type>
+    <mime-type type="application/vnd.novadigm.edm">
+        <glob pattern="*.edm"/>
+    </mime-type>
+    <mime-type type="application/vnd.novadigm.edx">
+        <glob pattern="*.edx"/>
+    </mime-type>
+    <mime-type type="application/vnd.novadigm.ext">
+        <glob pattern="*.ext"/>
+    </mime-type>
+
+    <!-- =================================================================== -->
+    <!-- Open Document Format for Office Applications (OpenDocument) v1.0    -->
+    <!-- http://www.oasis-open.org/specs/index.php#opendocumentv1.0          -->
+    <!-- =================================================================== -->
+
+    <mime-type type="application/vnd.oasis.opendocument.chart">
+        <alias type="application/x-vnd.oasis.opendocument.chart"/>
+        <_comment>OpenDocument v1.0: Chart document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.chart"/>
+            </match>
+        </magic>
+        <glob pattern="*.odc"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.chart-template">
+        <alias type="application/x-vnd.oasis.opendocument.chart-template"/>
+        <_comment>OpenDocument v1.0: Chart document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.chart-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.otc"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.database">
+        <glob pattern="*.odb"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.formula">
+        <alias type="application/x-vnd.oasis.opendocument.formula"/>
+        <_comment>OpenDocument v1.0: Formula document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.formula" />
+            </match>
+        </magic>
+        <glob pattern="*.odf"/>
+        <sub-class-of type="application/zip"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.formula-template">
+        <alias type="application/x-vnd.oasis.opendocument.formula-template"/>
+        <_comment>OpenDocument v1.0: Formula document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.formula-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.odft"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.graphics">
+        <alias type="application/x-vnd.oasis.opendocument.graphics"/>
+        <_comment>OpenDocument v1.0: Graphics document (Drawing)</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.graphics"/>
+            </match>
+        </magic>
+        <glob pattern="*.odg"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.graphics-template">
+        <alias type="application/x-vnd.oasis.opendocument.graphics-template"/>
+        <_comment>OpenDocument v1.0: Graphics document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.graphics-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.otg"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.image">
+        <alias type="application/x-vnd.oasis.opendocument.image"/>
+        <_comment>OpenDocument v1.0: Image document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.image"/>
+            </match>
+        </magic>
+        <glob pattern="*.odi"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.image-template">
+        <alias type="application/x-vnd.oasis.opendocument.image-template"/>
+        <_comment>OpenDocument v1.0: Image document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.image-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.oti"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.presentation">
+        <alias type="application/x-vnd.oasis.opendocument.presentation"/>
+        <_comment>OpenDocument v1.0: Presentation document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.presentation"/>
+            </match>
+        </magic>
+        <glob pattern="*.odp"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.presentation-template">
+        <alias type="application/x-vnd.oasis.opendocument.presentation-template"/>
+        <_comment>OpenDocument v1.0: Presentation document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.presentation-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.otp"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.spreadsheet">
+        <alias type="application/x-vnd.oasis.opendocument.spreadsheet"/>
+        <_comment>OpenDocument v1.0: Spreadsheet document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.spreadsheet"/>
+            </match>
+        </magic>
+        <glob pattern="*.ods"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.spreadsheet-template">
+        <alias type="application/x-vnd.oasis.opendocument.spreadsheet-template"/>
+        <_comment>OpenDocument v1.0: Spreadsheet document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.spreadsheet-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.ots"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.text">
+        <alias type="application/x-vnd.oasis.opendocument.text"/>
+        <_comment>OpenDocument v1.0: Text document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.text"/>
+            </match>
+        </magic>
+        <glob pattern="*.odt"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.text-master">
+        <alias type="application/x-vnd.oasis.opendocument.text-master"/>
+        <_comment>OpenDocument v1.0: Global Text document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.text-master"/>
+            </match>
+        </magic>
+        <glob pattern="*.otm"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.text-template">
+        <alias type="application/x-vnd.oasis.opendocument.text-template"/>
+        <_comment>OpenDocument v1.0: Text document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.text-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.ott"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.text-web">
+        <alias type="application/x-vnd.oasis.opendocument.text-web"/>
+        <_comment>OpenDocument v1.0: Text document used as template for HTML documents</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.text-web"/>
+            </match>
+        </magic>
+        <glob pattern="*.oth"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.obn"/>
+    <mime-type type="application/vnd.olpc-sugar">
+        <glob pattern="*.xo"/>
+    </mime-type>
+    <mime-type type="application/vnd.oma-scws-config"/>
+    <mime-type type="application/vnd.oma-scws-http-request"/>
+    <mime-type type="application/vnd.oma-scws-http-response"/>
+    <mime-type type="application/vnd.oma.bcast.associated-procedure-parameter+xml"/>
+    <mime-type type="application/vnd.oma.bcast.drm-trigger+xml"/>
+    <mime-type type="application/vnd.oma.bcast.imd+xml"/>
+    <mime-type type="application/vnd.oma.bcast.ltkm"/>
+    <mime-type type="application/vnd.oma.bcast.notification+xml"/>
+    <mime-type type="application/vnd.oma.bcast.provisioningtrigger"/>
+    <mime-type type="application/vnd.oma.bcast.sgboot"/>
+    <mime-type type="application/vnd.oma.bcast.sgdd+xml"/>
+    <mime-type type="application/vnd.oma.bcast.sgdu"/>
+    <mime-type type="application/vnd.oma.bcast.simple-symbol-container"/>
+    <mime-type type="application/vnd.oma.bcast.smartcard-trigger+xml"/>
+    <mime-type type="application/vnd.oma.bcast.sprov+xml"/>
+    <mime-type type="application/vnd.oma.bcast.stkm"/>
+    <mime-type type="application/vnd.oma.dcd"/>
+    <mime-type type="application/vnd.oma.dcdc"/>
+    <mime-type type="application/vnd.oma.dd2+xml">
+        <glob pattern="*.dd2"/>
+    </mime-type>
+    <mime-type type="application/vnd.oma.drm.risd+xml"/>
+    <mime-type type="application/vnd.oma.group-usage-list+xml"/>
+    <mime-type type="application/vnd.oma.poc.detailed-progress-report+xml"/>
+    <mime-type type="application/vnd.oma.poc.final-report+xml"/>
+    <mime-type type="application/vnd.oma.poc.groups+xml"/>
+    <mime-type type="application/vnd.oma.poc.invocation-descriptor+xml"/>
+    <mime-type type="application/vnd.oma.poc.optimized-progress-report+xml"/>
+    <mime-type type="application/vnd.oma.xcap-directory+xml"/>
+    <mime-type type="application/vnd.omads-email+xml"/>
+    <mime-type type="application/vnd.omads-file+xml"/>
+    <mime-type type="application/vnd.omads-folder+xml"/>
+    <mime-type type="application/vnd.omaloc-supl-init"/>
+
+    <mime-type type="application/vnd.openofficeorg.extension">
+        <glob pattern="*.oxt"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.presentation">
+        <_comment>Office Open XML Presentation</_comment>
+        <glob pattern="*.pptx"/>
+        <glob pattern="*.thmx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slide">
+        <glob pattern="*.sldx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.template">
+        <_comment>Office Open XML Presentation Template</_comment>
+        <glob pattern="*.potx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slideshow">
+        <_comment>Office Open XML Presentation Slideshow</_comment>
+        <glob pattern="*.ppsx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
+        <_comment>Office Open XML Workbook</_comment>
+        <glob pattern="*.xlsx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.spreadsheetml.template">
+        <_comment>Office Open XML Workbook Template</_comment>
+        <glob pattern="*.xltx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-excel.template.macroenabled.12">
+        <_comment>Office Open XML Workbook Template (macro-enabled)</_comment>
+        <glob pattern="*.xltm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.document">
+        <_comment>Office Open XML Document</_comment>
+        <glob pattern="*.docx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.template">
+        <_comment>Office Open XML Document Template</_comment>
+        <glob pattern="*.dotx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.osa.netdeploy"/>
+    <mime-type type="application/vnd.osgi.bundle"/>
+    <mime-type type="application/vnd.osgi.dp">
+        <glob pattern="*.dp"/>
+    </mime-type>
+    <mime-type type="application/vnd.otps.ct-kip+xml"/>
+
+    <mime-type type="application/vnd.palm">
+        <!-- <glob pattern="*.pdb"/> - conflicts with chemical/x-pdb -->
+        <glob pattern="*.pqa"/>
+        <glob pattern="*.oprc"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.paos.xml"/>
+    <mime-type type="application/vnd.pg.format">
+        <glob pattern="*.str"/>
+    </mime-type>
+    <mime-type type="application/vnd.pg.osasli">
+        <glob pattern="*.ei6"/>
+    </mime-type>
+    <mime-type type="application/vnd.piaccess.application-licence"/>
+    <mime-type type="application/vnd.picsel">
+        <glob pattern="*.efif"/>
+    </mime-type>
+    <mime-type type="application/vnd.poc.group-advertisement+xml"/>
+    <mime-type type="application/vnd.pocketlearn">
+        <glob pattern="*.plf"/>
+    </mime-type>
+    <mime-type type="application/vnd.powerbuilder6">
+        <glob pattern="*.pbd"/>
+    </mime-type>
+    <mime-type type="application/vnd.powerbuilder6-s"/>
+    <mime-type type="application/vnd.powerbuilder7"/>
+    <mime-type type="application/vnd.powerbuilder7-s"/>
+    <mime-type type="application/vnd.powerbuilder75"/>
+    <mime-type type="application/vnd.powerbuilder75-s"/>
+    <mime-type type="application/vnd.preminet"/>
+    <mime-type type="application/vnd.previewsystems.box">
+        <glob pattern="*.box"/>
+    </mime-type>
+    <mime-type type="application/vnd.proteus.magazine">
+        <glob pattern="*.mgz"/>
+    </mime-type>
+    <mime-type type="application/vnd.publishare-delta-tree">
+        <glob pattern="*.qps"/>
+    </mime-type>
+    <mime-type type="application/vnd.pvi.ptid1">
+        <glob pattern="*.ptid"/>
+    </mime-type>
+    <mime-type type="application/vnd.pwg-multiplexed"/>
+    <mime-type type="application/vnd.pwg-xhtml-print+xml"/>
+    <mime-type type="application/vnd.qualcomm.brew-app-res"/>
+    <mime-type type="application/vnd.quark.quarkxpress">
+        <glob pattern="*.qxd"/>
+        <glob pattern="*.qxt"/>
+        <glob pattern="*.qwd"/>
+        <glob pattern="*.qwt"/>
+        <glob pattern="*.qxl"/>
+        <glob pattern="*.qxb"/>
+    </mime-type>
+    <mime-type type="application/vnd.rapid"/>
+    <mime-type type="application/vnd.recordare.musicxml">
+        <glob pattern="*.mxl"/>
+    </mime-type>
+    <mime-type type="application/vnd.recordare.musicxml+xml">
+        <glob pattern="*.musicxml"/>
+    </mime-type>
+    <mime-type type="application/vnd.renlearn.rlprint"/>
+    <mime-type type="application/vnd.rim.cod">
+        <glob pattern="*.cod"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.rn-realmedia">
+        <magic priority="50">
+            <match value=".RMF" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.rm"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.route66.link66+xml">
+        <glob pattern="*.link66"/>
+    </mime-type>
+    <mime-type type="application/vnd.ruckus.download"/>
+    <mime-type type="application/vnd.s3sms"/>
+    <mime-type type="application/vnd.sbm.cid"/>
+    <mime-type type="application/vnd.sbm.mid2"/>
+    <mime-type type="application/vnd.scribus"/>
+    <mime-type type="application/vnd.sealed.3df"/>
+    <mime-type type="application/vnd.sealed.csf"/>
+    <mime-type type="application/vnd.sealed.doc"/>
+    <mime-type type="application/vnd.sealed.eml"/>
+    <mime-type type="application/vnd.sealed.mht"/>
+    <mime-type type="application/vnd.sealed.net"/>
+    <mime-type type="application/vnd.sealed.ppt"/>
+    <mime-type type="application/vnd.sealed.tiff"/>
+    <mime-type type="application/vnd.sealed.xls"/>
+    <mime-type type="application/vnd.sealedmedia.softseal.html"/>
+    <mime-type type="application/vnd.sealedmedia.softseal.pdf"/>
+    <mime-type type="application/vnd.seemail">
+        <glob pattern="*.see"/>
+    </mime-type>
+    <mime-type type="application/vnd.sema">
+        <glob pattern="*.sema"/>
+    </mime-type>
+    <mime-type type="application/vnd.semd">
+        <glob pattern="*.semd"/>
+    </mime-type>
+    <mime-type type="application/vnd.semf">
+        <glob pattern="*.semf"/>
+    </mime-type>
+    <mime-type type="application/vnd.shana.informed.formdata">
+        <glob pattern="*.ifm"/>
+    </mime-type>
+    <mime-type type="application/vnd.shana.informed.formtemplate">
+        <glob pattern="*.itp"/>
+    </mime-type>
+    <mime-type type="application/vnd.shana.informed.interchange">
+        <glob pattern="*.iif"/>
+    </mime-type>
+    <mime-type type="application/vnd.shana.informed.package">
+        <glob pattern="*.ipk"/>
+    </mime-type>
+    <mime-type type="application/vnd.simtech-mindmapper">
+        <glob pattern="*.twd"/>
+        <glob pattern="*.twds"/>
+    </mime-type>
+    <mime-type type="application/vnd.smaf">
+        <glob pattern="*.mmf"/>
+    </mime-type>
+    <mime-type type="application/vnd.smart.teacher">
+        <glob pattern="*.teacher"/>
+    </mime-type>
+    <mime-type type="application/vnd.software602.filler.form+xml"/>
+    <mime-type type="application/vnd.software602.filler.form-xml-zip"/>
+    <mime-type type="application/vnd.solent.sdkm+xml">
+        <glob pattern="*.sdkm"/>
+        <glob pattern="*.sdkd"/>
+    </mime-type>
+    <mime-type type="application/vnd.spotfire.dxp">
+        <glob pattern="*.dxp"/>
+    </mime-type>
+    <mime-type type="application/vnd.spotfire.sfs">
+        <glob pattern="*.sfs"/>
+    </mime-type>
+    <mime-type type="application/vnd.sss-cod"/>
+    <mime-type type="application/vnd.sss-dtf"/>
+    <mime-type type="application/vnd.sss-ntf"/>
+
+    <mime-type type="application/vnd.stardivision.calc">
+        <sub-class-of type="application/x-tika-staroffice"/>
+        <magic priority="50">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="StarCalc" type="string" offset="2048:2207" />
+            </match>
+        </magic>
+        <glob pattern="*.sdc"/>
+    </mime-type>
+    <mime-type type="application/vnd.stardivision.draw">
+        <sub-class-of type="application/x-tika-staroffice"/>
+        <magic priority="50">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="StarDraw" type="string" offset="2048:2207" />
+            </match>
+        </magic>
+        <glob pattern="*.sda"/>
+    </mime-type>
+    <mime-type type="application/vnd.stardivision.impress">
+        <sub-class-of type="application/x-tika-staroffice"/>
+        <magic priority="50">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="StarImpress" type="string" offset="2048:2207" />
+            </match>
+        </magic>
+        <glob pattern="*.sdd"/>
+    </mime-type>
+    <mime-type type="application/vnd.stardivision.math">
+        <glob pattern="*.smf"/>
+    </mime-type>
+    <mime-type type="application/vnd.stardivision.writer">
+        <sub-class-of type="application/x-tika-staroffice"/>
+        <magic priority="50">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="StarWriter" type="string" offset="2048:2207" />
+            </match>
+        </magic>
+        <glob pattern="*.sdw"/>
+    </mime-type>
+    <mime-type type="application/x-staroffice-template">
+        <sub-class-of type="application/x-tika-staroffice"/>
+        <glob pattern="*.vor"/>
+    </mime-type>
+    <mime-type type="application/vnd.stardivision.writer-global">
+        <glob pattern="*.sgl"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.street-stream"/>
+    <mime-type type="application/vnd.sun.xml.calc">
+        <glob pattern="*.sxc"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.calc.template">
+        <glob pattern="*.stc"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.draw">
+        <glob pattern="*.sxd"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.draw.template">
+        <glob pattern="*.std"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.impress">
+        <glob pattern="*.sxi"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.impress.template">
+        <glob pattern="*.sti"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.math">
+        <glob pattern="*.sxm"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.sun.xml.writer">
+        <alias type="application/x-vnd.sun.xml.writer"/>
+        <_comment>OpenOffice v1.0: Writer Document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.sun.xml.writer"/>
+            </match>
+        </magic>
+        <glob pattern="*.sxw"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.sun.xml.writer.global">
+        <glob pattern="*.sxg"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.writer.template">
+        <glob pattern="*.stw"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.wadl+xml"/>
+    <mime-type type="application/vnd.sus-calendar">
+        <glob pattern="*.sus"/>
+        <glob pattern="*.susp"/>
+    </mime-type>
+    <mime-type type="application/vnd.svd">
+        <glob pattern="*.svd"/>
+    </mime-type>
+    <mime-type type="application/vnd.swiftview-ics"/>
+
+    <mime-type type="application/vnd.symbian.install">
+        <magic priority="50">
+            <match value="0x10000419" type="little32" offset="8" />
+        </magic>
+        <glob pattern="*.sis"/>
+        <glob pattern="*.sisx"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.syncml+xml">
+        <glob pattern="*.xsm"/>
+    </mime-type>
+    <mime-type type="application/vnd.syncml.dm+wbxml">
+        <glob pattern="*.bdm"/>
+    </mime-type>
+    <mime-type type="application/vnd.syncml.dm+xml">
+        <glob pattern="*.xdm"/>
+    </mime-type>
+    <mime-type type="application/vnd.syncml.dm.notification"/>
+    <mime-type type="application/vnd.syncml.ds.notification"/>
+    <mime-type type="application/vnd.tao.intent-module-archive">
+        <glob pattern="*.tao"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.tcpdump.pcap">
+        <_comment>TCPDump pcap packet capture</_comment>
+        <magic priority="50">
+            <match value="0xa1b2c3d4" type="big32" offset="0" />
+            <match value="0xd4c3b2a1" type="big32" offset="0" />
+        </magic>
+        <glob pattern="*.pcap"/>
+        <glob pattern="*.cap"/>
+        <glob pattern="*.dmp"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.tmobile-livetv">
+        <glob pattern="*.tmo"/>
+    </mime-type>
+    <mime-type type="application/vnd.trid.tpt">
+        <glob pattern="*.tpt"/>
+    </mime-type>
+    <mime-type type="application/vnd.triscape.mxs">
+        <glob pattern="*.mxs"/>
+    </mime-type>
+    <mime-type type="application/vnd.trueapp">
+        <glob pattern="*.tra"/>
+    </mime-type>
+    <mime-type type="application/vnd.truedoc"/>
+    <mime-type type="application/vnd.ufdl">
+        <glob pattern="*.ufd"/>
+        <glob pattern="*.ufdl"/>
+    </mime-type>
+    <mime-type type="application/vnd.uiq.theme">
+        <glob pattern="*.utz"/>
+    </mime-type>
+    <mime-type type="application/vnd.umajin">
+        <glob pattern="*.umj"/>
+    </mime-type>
+    <mime-type type="application/vnd.unity">
+        <glob pattern="*.unityweb"/>
+    </mime-type>
+    <mime-type type="application/vnd.uoml+xml">
+        <glob pattern="*.uoml"/>
+    </mime-type>
+    <mime-type type="application/vnd.uplanet.alert"/>
+    <mime-type type="application/vnd.uplanet.alert-wbxml"/>
+    <mime-type type="application/vnd.uplanet.bearer-choice"/>
+    <mime-type type="application/vnd.uplanet.bearer-choice-wbxml"/>
+    <mime-type type="application/vnd.uplanet.cacheop"/>
+    <mime-type type="application/vnd.uplanet.cacheop-wbxml"/>
+    <mime-type type="application/vnd.uplanet.channel"/>
+    <mime-type type="application/vnd.uplanet.channel-wbxml"/>
+    <mime-type type="application/vnd.uplanet.list"/>
+    <mime-type type="application/vnd.uplanet.list-wbxml"/>
+    <mime-type type="application/vnd.uplanet.listcmd"/>
+    <mime-type type="application/vnd.uplanet.listcmd-wbxml"/>
+    <mime-type type="application/vnd.uplanet.signal"/>
+    <mime-type type="application/vnd.vcx">
+        <glob pattern="*.vcx"/>
+    </mime-type>
+    <mime-type type="application/vnd.vd-study"/>
+    <mime-type type="application/vnd.vectorworks"/>
+    <mime-type type="application/vnd.vidsoft.vidconference"/>
+
+    <!-- http://www.iana.org/assignments/media-types/application/vnd.visio -->
+    <mime-type type="application/vnd.visio">
+        <_comment>Microsoft Visio Diagram</_comment>
+        <glob pattern="*.vsd"/>
+        <glob pattern="*.vst"/>
+        <glob pattern="*.vss"/>
+        <glob pattern="*.vsw"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.visionary">
+        <glob pattern="*.vis"/>
+    </mime-type>
+    <mime-type type="application/vnd.vividence.scriptfile"/>
+    <mime-type type="application/vnd.vsf">
+        <glob pattern="*.vsf"/>
+    </mime-type>
+    <mime-type type="application/vnd.wap.sic"/>
+    <mime-type type="application/vnd.wap.slc"/>
+
+    <mime-type type="application/vnd.wap.wbxml">
+        <glob pattern="*.wbxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.wap.wmlc">
+        <_comment>Compiled WML Document</_comment>
+        <glob pattern="*.wmlc"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.wap.wmlscriptc">
+        <_comment>Compiled WML Script</_comment>
+        <glob pattern="*.wmlsc"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.webturbo">
+        <glob pattern="*.wtb"/>
+    </mime-type>
+    <mime-type type="application/vnd.wfa.wsc"/>
+    <mime-type type="application/vnd.wmc"/>
+    <mime-type type="application/vnd.wmf.bootstrap"/>
+    <mime-type type="application/vnd.wordperfect">
+        <alias type="application/wordperfect"/>
+        <glob pattern="*.wpd"/>
+    </mime-type>
+    <mime-type type="application/vnd.wqd">
+        <glob pattern="*.wqd"/>
+    </mime-type>
+    <mime-type type="application/vnd.wrq-hp3000-labelled"/>
+    <mime-type type="application/vnd.wt.stf">
+        <glob pattern="*.stf"/>
+    </mime-type>
+    <mime-type type="application/vnd.wv.csp+wbxml"/>
+    <mime-type type="application/vnd.wv.csp+xml"/>
+    <mime-type type="application/vnd.wv.ssp+xml"/>
+    <mime-type type="application/vnd.xara">
+        <glob pattern="*.xar"/>
+    </mime-type>
+    <mime-type type="application/vnd.xfdl">
+        <glob pattern="*.xfdl"/>
+    </mime-type>
+    <mime-type type="application/vnd.xfdl.webform"/>
+    <mime-type type="application/vnd.xmi+xml"/>
+    <mime-type type="application/vnd.xmpie.cpkg"/>
+    <mime-type type="application/vnd.xmpie.dpkg"/>
+    <mime-type type="application/vnd.xmpie.plan"/>
+    <mime-type type="application/vnd.xmpie.ppkg"/>
+    <mime-type type="application/vnd.xmpie.xlim"/>
+    <mime-type type="application/vnd.yamaha.hv-dic">
+        <glob pattern="*.hvd"/>
+    </mime-type>
+    <mime-type type="application/vnd.yamaha.hv-script">
+        <glob pattern="*.hvs"/>
+    </mime-type>
+    <mime-type type="application/vnd.yamaha.hv-voice">
+        <glob pattern="*.hvp"/>
+    </mime-type>
+    <mime-type type="application/vnd.yamaha.openscoreformat">
+        <glob pattern="*.osf"/>
+    </mime-type>
+    <mime-type type="application/vnd.yamaha.openscoreformat.osfpvg+xml">
+        <glob pattern="*.osfpvg"/>
+    </mime-type>
+    <mime-type type="application/vnd.yamaha.smaf-audio">
+        <glob pattern="*.saf"/>
+    </mime-type>
+    <mime-type type="application/vnd.yamaha.smaf-phrase">
+        <glob pattern="*.spf"/>
+    </mime-type>
+    <mime-type type="application/vnd.yellowriver-custom-menu">
+        <glob pattern="*.cmp"/>
+    </mime-type>
+    <mime-type type="application/vnd.zul">
+        <glob pattern="*.zir"/>
+        <glob pattern="*.zirz"/>
+    </mime-type>
+    <mime-type type="application/vnd.zzazz.deck+xml">
+        <glob pattern="*.zaz"/>
+    </mime-type>
+    <mime-type type="application/voicexml+xml">
+        <glob pattern="*.vxml"/>
+    </mime-type>
+    <mime-type type="application/watcherinfo+xml"/>
+    <mime-type type="application/whoispp-query"/>
+    <mime-type type="application/whoispp-response"/>
+    <mime-type type="application/winhlp">
+        <glob pattern="*.hlp"/>
+    </mime-type>
+    <mime-type type="application/wita"/>
+    <mime-type type="application/wordperfect5.1"/>
+    <mime-type type="application/wsdl+xml">
+        <glob pattern="*.wsdl"/>
+    </mime-type>
+    <mime-type type="application/wspolicy+xml">
+        <glob pattern="*.wspolicy"/>
+    </mime-type>
+
+    <mime-type type="application/x-123">
+        <magic priority="50">
+            <match value="0x00001a00" type="big32" offset="0" />
+            <match value="0x00000200" type="big32" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-abiword">
+        <glob pattern="*.abw"/>
+    </mime-type>
+    <mime-type type="application/x-ace-compressed">
+        <glob pattern="*.ace"/>
+    </mime-type>
+
+    <mime-type type="application/x-axcrypt">
+        <_comment>AxCrypt</_comment>
+        <glob pattern="*.axx" />
+        <magic priority="60">
+            <!-- AxCrypt block header, skip length field, then Header of type Preamble -->
+            <match value="0xc0b9072e4f93f146a015792ca1d9e821" type="string" offset="0">
+                <match value="2" type="big32" offset="17" />
+            </match>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-adobe-indesign">
+        <acronym>INDD</acronym>
+        <_comment>Adobe InDesign document</_comment>
+        <glob pattern="*.indd"/>
+        <magic priority="50">
+            <match value="0x0606edf5d81d46e5bd31efe7fe74b71d" type="string" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-adobe-indesign-interchange">
+        <acronym>INX</acronym>
+        <_comment>Adobe InDesign Interchange format</_comment>
+        <magic priority="50">
+            <match value="&lt;?aid" type="string" offset="0:100"/>
+        </magic>
+        <glob pattern="*.inx"/>
+        <sub-class-of type="application/xml"/>
+    </mime-type>
+
+    <mime-type type="application/x-apple-diskimage">
+        <glob pattern="*.dmg"/>
+        <!-- <glob pattern="*.img"/> too generic -->
+        <!-- <glob pattern="*.smi"/> conflicts with SMIL -->
+    </mime-type>
+
+    <mime-type type="application/x-appleworks">
+        <glob pattern="*.cwk"/>
+    </mime-type>
+
+    <mime-type type="application/x-archive">
+        <alias type="application/x-unix-archive"/>
+        <magic priority="50">
+            <match value="=&lt;ar&gt;" type="string" offset="0"/>
+            <match value="!&lt;arch&gt;\n" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.ar"/>
+        <glob pattern="*.a"/>
+    </mime-type>
+
+    <mime-type type="application/x-arj">
+        <alias type="application/x-arj-compressed"/>
+        <magic priority="50">
+            <match value="0x60ea" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.arj"/>
+    </mime-type>
+
+    <mime-type type="application/x-authorware-bin">
+        <glob pattern="*.aab"/>
+        <glob pattern="*.x32"/>
+        <glob pattern="*.u32"/>
+        <glob pattern="*.vox"/>
+    </mime-type>
+    <mime-type type="application/x-authorware-map">
+        <glob pattern="*.aam"/>
+    </mime-type>
+    <mime-type type="application/x-authorware-seg">
+        <glob pattern="*.aas"/>
+    </mime-type>
+
+    <mime-type type="application/x-bcpio">
+        <glob pattern="*.bcpio"/>
+    </mime-type>
+
+    <mime-type type="application/x-berkeley-db">
+        <magic priority="50">
+            <match value="0x00061561" type="big32" offset="0"/>
+            <match value="0x00061561" type="host32" offset="12"/>
+            <match value="0x00061561" type="big32" offset="12"/>
+            <match value="0x00061561" type="little32" offset="12"/>
+            <match value="0x00053162" type="host32" offset="12"/>
+            <match value="0x00053162" type="big32" offset="12"/>
+            <match value="0x00053162" type="little32" offset="12"/>
+            <match value="0x00042253" type="host32" offset="12"/>
+            <match value="0x00042253" type="big32" offset="12"/>
+            <match value="0x00042253" type="little32" offset="12"/>
+            <match value="0x00040988" type="host32" offset="12"/>
+            <match value="0x00040988" type="little32" offset="12"/>
+            <match value="0x00040988" type="big32" offset="12"/>
+            <match value="0x00053162" type="host32" offset="0"/>
+            <match value="0x00053162" type="big32" offset="0"/>
+            <match value="0x00053162" type="little32" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-bibtex-text-file">
+        <magic priority="50">
+            <match value="%\ BibTeX\ `" type="string" offset="0"/>
+            <match value="%%%\ \ " type="string" offset="73"/>
+            <match value="%\ BibTeX\ standard\ bibliography\ " type="string" offset="0"/>
+            <match value="%%%\ \ @BibTeX-style-file{" type="string" offset="73"/>
+            <match value="@article{" type="string" offset="0"/>
+            <match value="@book{" type="string" offset="0"/>
+            <match value="@inbook{" type="string" offset="0"/>
+            <match value="@incollection{" type="string" offset="0"/>
+            <match value="@inproceedings{" type="string" offset="0"/>
+            <match value="@manual{" type="string" offset="0"/>
+            <match value="@misc{" type="string" offset="0"/>
+            <match value="@preamble{" type="string" offset="0"/>
+            <match value="@phdthesis{" type="string" offset="0"/>
+            <match value="@techreport{" type="string" offset="0"/>
+            <match value="@unpublished{" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.bib"/>
+        <glob pattern="*.bibtex"/>
+    </mime-type>
+
+    <mime-type type="application/x-bittorrent">
+        <magic priority="50">
+            <match value="d8:announce" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.torrent"/>
+    </mime-type>
+
+    <mime-type type="application/x-bplist">
+        <!-- The priority is 60, as .webarchive files often contain
+         (X)HTML content. The bplist magic must trump the XHTML
+         magics further within the file. This must also be
+         independent of the internal ordering of patterns within
+         MimeTypes -->
+        <magic priority="60">
+            <match value="bplist" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-bzip">
+        <magic priority="40">
+            <match value="BZh" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.bz"/>
+        <glob pattern="*.tbz"/>
+    </mime-type>
+
+    <mime-type type="application/x-bzip2">
+        <sub-class-of type="application/x-bzip"/>
+        <_comment>Bzip 2 UNIX Compressed File</_comment>
+        <magic priority="40">
+            <match value="\x42\x5a\x68\x39\x31" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.bz2"/>
+        <glob pattern="*.tbz2"/>
+        <glob pattern="*.boz"/>
+    </mime-type>
+
+    <mime-type type="application/x-cdlink">
+        <_comment>Virtual CD-ROM CD Image File</_comment>
+        <glob pattern="*.vcd"/>
+    </mime-type>
+
+    <mime-type type="application/x-chat">
+        <glob pattern="*.chat"/>
+    </mime-type>
+
+    <mime-type type="application/x-chess-pgn">
+        <glob pattern="*.pgn"/>
+    </mime-type>
+
+    <mime-type type="application/x-chrome-package">
+        <acronym>CRX</acronym>
+        <_comment>Chrome Extension Package</_comment>
+        <tika:link>https://developer.chrome.com/extensions/crx</tika:link>
+        <magic priority="50">
+            <match value="Cr24" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.crx"/>
+    </mime-type>
+
+    <mime-type type="application/x-compress">
+        <magic priority="50">
+            <match value="\037\235" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.z"/>
+    </mime-type>
+
+    <mime-type type="application/x-corelpresentations">
+        <glob pattern="*.shw"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/x-cpio">
+        <_comment>UNIX CPIO Archive</_comment>
+        <magic priority="50">
+            <match value="070707" type="little16" offset="0"/>
+            <match value="070707" type="big16" offset="0"/>
+            <match value="070707" type="string" offset="0"/>
+            <match value="070701" type="string" offset="0"/>
+            <match value="070702" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.cpio"/>
+    </mime-type>
+
+    <mime-type type="application/x-csh">
+        <glob pattern="*.csh"/>
+        <glob pattern="*.tcsh"/>
+    </mime-type>
+
+    <mime-type type="application/x-debian-package">
+        <sub-class-of type="application/x-archive"/>
+        <magic priority="60">
+            <match value="!&lt;arch&gt;\ndebian-binary" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.deb"/>
+        <glob pattern="*.udeb"/>
+    </mime-type>
+
+    <mime-type type="application/x-dex">
+        <acronym>DEX</acronym>
+        <_comment>Dalvik Executable Format</_comment>
+        <tika:link>http://source.android.com/devices/tech/dalvik/dex-format.html</tika:link>
+        <magic priority="50">
+            <match value="dex\n" type="string" offset="0">
+                <match value="\0" type="string" offset="7"/>
+            </match>
+        </magic>
+        <glob pattern="*.dex"/>
+    </mime-type>
+
+    <mime-type type="application/x-director">
+        <_comment>Shockwave Movie</_comment>
+        <glob pattern="*.dir"/>
+        <glob pattern="*.dcr"/>
+        <glob pattern="*.dxr"/>
+        <glob pattern="*.cst"/>
+        <glob pattern="*.cct"/>
+        <glob pattern="*.cxt"/>
+        <glob pattern="*.w3d"/>
+        <glob pattern="*.fgd"/>
+        <glob pattern="*.swa"/>
+    </mime-type>
+
+    <mime-type type="application/x-doom">
+        <glob pattern="*.wad"/>
+    </mime-type>
+    <mime-type type="application/x-dtbncx+xml">
+        <glob pattern="*.ncx"/>
+    </mime-type>
+    <mime-type type="application/x-dtbook+xml">
+        <glob pattern="*.dtb"/>
+    </mime-type>
+    <mime-type type="application/x-dtbresource+xml">
+        <glob pattern="*.res"/>
+    </mime-type>
+
+    <mime-type type="application/x-dvi">
+        <_comment>TeX Device Independent Document</_comment>
+        <magic priority="50">
+            <match value="\367\002" type="string" offset="0"/>
+            <match value="0x02f7" type="little16" offset="0"/>
+            <match value="\x1b\x20\x54\x65\x58\x20\x6f\x75\x74\x70\x75\x74\x20"
+                   type="string" offset="14"/>
+        </magic>
+        <glob pattern="*.dvi"/>
+    </mime-type>
+
+    <mime-type type="application/x-elc">
+        <_comment>Emacs Lisp bytecode</_comment>
+        <magic priority="50">
+            <!-- Emacs 18 -->
+            <match value="\012(" type="string" offset="0" />
+            <!-- Emacs 19 -->
+            <match value=";ELC\023\000\000\000" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.elc"/>
+    </mime-type>
+
+    <mime-type type="application/x-elf">
+        <magic priority="50">
+            <match value="\177ELF" type="string" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="message/x-emlx">
+        <magic priority="70">
+            <match value="\nRelay-Version:" type="string" offset="2:9"/>
+            <match value="\n#!\ rnews" type="string" offset="2:9"/>
+            <match value="\nN#!\ rnews" type="string" offset="2:9"/>
+            <match value="\nForward\ to" type="string" offset="2:9"/>
+            <match value="\nPipe\ to" type="string" offset="2:9"/>
+            <match value="\nReturn-Path:" type="string" offset="2:9"/>
+            <match value="\nFrom:" type="string" offset="2:9"/>
+            <match value="\nReceived:" type="string" offset="2:9"/>
+            <match value="\nMessage-ID:" type="string" offset="2:9"/>
+            <match value="\nDate:" type="string" offset="2:9"/>
+        </magic>
+        <glob pattern="*.emlx"/>
+    </mime-type>
+
+    <mime-type type="application/x-killustrator">
+        <_comment>KIllustrator File</_comment>
+        <glob pattern="*.kil"/>
+    </mime-type>
+
+    <mime-type type="application/x-object">
+        <sub-class-of type="application/x-elf"/>
+        <magic priority="50">
+            <match value="\177ELF" type="string" offset="0">
+                <match value="0x0100" type="string" offset="16"/>
+                <match value="0x0001" type="string" offset="16"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-executable">
+        <sub-class-of type="application/x-elf"/>
+        <magic priority="50">
+            <match value="\177ELF" type="string" offset="0">
+                <match value="0x0200" type="string" offset="16"/>
+                <match value="0x0002" type="string" offset="16"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-sharedlib">
+        <sub-class-of type="application/x-elf"/>
+        <magic priority="50">
+            <match value="\177ELF" type="string" offset="0">
+                <match value="0x0300" type="string" offset="16"/>
+                <match value="0x0003" type="string" offset="16"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-coredump">
+        <sub-class-of type="application/x-elf"/>
+        <magic priority="50">
+            <match value="\177ELF" type="string" offset="0">
+                <match value="0x0400" type="string" offset="16"/>
+                <match value="0x0004" type="string" offset="16"/>
+            </match>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-dosexec">
+        <_comment>DOS/Windows executable (EXE)</_comment>
+        <sub-class-of type="application/x-msdownload"/>
+        <glob pattern="*.exe"/>
+    </mime-type>
+
+    <mime-type type="application/x-emf">
+        <acronym>EMF</acronym>
+        <_comment>Extended Metafile</_comment>
+        <glob pattern="*.emf"/>
+        <magic priority="50">
+            <match value="0x01000000" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-filemaker">
+        <acronym>FP7</acronym>
+        <_comment>FileMaker Pro 7</_comment>
+        <magic priority="50">
+            <match value="0xC04842414D37" type="string" offset="14" >
+                <match value="0x4842414D323130314F43543939C102480750726F20372E30C0C0" type="string" offset="525" />
+            </match>
+        </magic>
+        <glob pattern="*.fp7" />
+    </mime-type>
+
+    <mime-type type="application/x-font-bdf">
+        <glob pattern="*.bdf"/>
+    </mime-type>
+    <mime-type type="application/x-font-dos"/>
+    <mime-type type="application/x-font-framemaker"/>
+    <mime-type type="application/x-font-ghostscript">
+        <glob pattern="*.gsf"/>
+    </mime-type>
+    <mime-type type="application/x-font-libgrx"/>
+    <mime-type type="application/x-font-linux-psf">
+        <glob pattern="*.psf"/>
+    </mime-type>
+
+    <mime-type type="application/x-font-otf">
+        <acronym>OTF</acronym>
+        <_comment>OpenType Font</_comment>
+        <glob pattern="*.otf"/>
+    </mime-type>
+
+    <mime-type type="application/x-font-pcf">
+        <glob pattern="*.pcf"/>
+    </mime-type>
+    <mime-type type="application/x-font-snf">
+        <glob pattern="*.snf"/>
+    </mime-type>
+    <mime-type type="application/x-font-speedo"/>
+    <mime-type type="application/x-font-sunos-news"/>
+
+    <mime-type type="application/x-font-ttf">
+        <acronym>TTF</acronym>
+        <_comment>TrueType Font</_comment>
+        <glob pattern="*.ttf"/>
+        <glob pattern="*.ttc"/>
+        <magic priority="40">
+            <match value="0x00010000" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-font-type1">
+        <glob pattern="*.pfa"/>
+        <glob pattern="*.pfb"/>
+        <magic priority="60">
+            <!-- Match for PFB, the binary format -->
+            <match value="\x80\x01\xFF\xFF\x00\x00%!PS-AdobeFont" type="string"
+                   mask="0xFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" offset="0"/>
+            <!-- Match for PFA, the text format" -->
+            <match value="%!PS-AdobeFont-1.0" type="string" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-font-adobe-metric">
+        <_comment>Adobe Font Metric</_comment>
+        <glob pattern="*.afm"/>
+        <glob pattern="*.acfm"/>
+        <glob pattern="*.amfm"/>
+        <magic priority="40">
+            <match value="StartFontMetrics" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-font-printer-metric">
+        <_comment>Printer Font Metric</_comment>
+        <glob pattern="*.pfm"/>
+        <magic priority="40">
+            <match value="0x0001FFFF0000436f707972" type="string" offset="0"
+                   mask="0xFFFF0000FFFFFFFFFFFFFF" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-font-vfont"/>
+
+    <mime-type type="application/x-foxmail">
+        <_comment>Foxmail Email File</_comment>
+        <magic>
+            <match value="0x1010101010101011111111111153" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-futuresplash">
+        <_comment>Macromedia FutureSplash File</_comment>
+        <glob pattern="*.spl"/>
+    </mime-type>
+
+    <mime-type type="application/x-gnucash">
+        <glob pattern="*.gnucash" />
+    </mime-type>
+
+    <mime-type type="application/x-gnumeric">
+        <alias type="application/x-Gnumeric-spreadsheet"/>
+        <magic priority="50">
+            <match value="=&lt;gmr:Workbook" type="string" offset="39" />
+        </magic>
+        <glob pattern="*.gnumeric"/>
+    </mime-type>
+
+    <mime-type type="application/x-gtar">
+        <_comment>GNU tar Compressed File Archive (GNU Tape Archive)</_comment>
+        <magic priority="50">
+            <!-- GNU tar archive -->
+            <match value="ustar  \0" type="string" offset="257" />
+        </magic>
+        <glob pattern="*.gtar"/>
+        <sub-class-of type="application/x-tar"/>
+    </mime-type>
+
+    <mime-type type="application/gzip">
+        <_comment>Gzip Compressed Archive</_comment>
+        <alias type="application/x-gzip"/>
+        <alias type="application/x-gunzip"/>
+        <alias type="application/gzip-compressed"/>
+        <alias type="application/gzipped"/>
+        <alias type="application/gzip-compressed"/>
+        <alias type="application/x-gzip-compressed"/>
+        <alias type="gzip/document"/>
+        <magic priority="45">
+            <match value="\037\213" type="string" offset="0" />
+            <match value="\x1f\x8b" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.tgz" />
+        <glob pattern="*.gz" />
+        <glob pattern="*-gz" />
+        <glob pattern="*.emz" />
+    </mime-type>
+
+    <mime-type type="application/x-hdf">
+        <_comment>Hierarchical Data Format File</_comment>
+        <magic priority="50">
+            <!-- HDF4 -->
+            <match value="0x0e031301" type="big32" offset="0"/>
+            <!-- HDF5 -->
+            <match value="\211HDF\r\n\032" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.hdf"/>
+        <glob pattern="*.he5"/>
+        <glob pattern="*.h5"/>
+    </mime-type>
+
+    <mime-type type="application/x-hwp">
+        <magic priority="50">
+            <!--
+        TIKA-330: Detection pattern based on signature strings from
+        the hwpfilter/source/hwpfile.cpp file in OpenOffice.org.
+      -->
+            <match value="HWP Document File V" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-ibooks+zip">
+        <sub-class-of type="application/epub+zip" />
+        <acronym>iBooks</acronym>
+        <_comment>Apple iBooks Author publication format</_comment>
+        <magic priority="50">
+            <match value="PK\003\004" type="string" offset="0">
+                <match value="mimetypeapplication/x-ibooks+zip" type="string" offset="30"/>
+            </match>
+        </magic>
+        <glob pattern="*.ibooks"/>
+    </mime-type>
+
+    <mime-type type="application/x-iso9660-image">
+        <acronym>ISO</acronym>
+        <_comment>ISO 9660 CD-ROM filesystem data</_comment>
+        <magic priority="50">
+            <match value="CD001" type="string" offset="32769"/>
+            <match value="CD001" type="string" offset="34817"/>
+            <match value="CD001" type="string" offset="36865"/>
+        </magic>
+        <glob pattern="*.iso"/>
+    </mime-type>
+
+    <mime-type type="application/x-itunes-ipa">
+        <sub-class-of type="application/zip"/>
+        <_comment>Apple iOS IPA AppStore file</_comment>
+        <glob pattern="*.ipa"/>
+    </mime-type>
+
+    <mime-type type="application/x-java-jnlp-file">
+        <glob pattern="*.jnlp"/>
+    </mime-type>
+
+    <mime-type type="application/x-java-pack200">
+        <glob pattern="*.pack"/>
+    </mime-type>
+
+    <mime-type type="application/x-kdelnk">
+        <magic priority="50">
+            <match value="[KDE\ Desktop\ Entry]" type="string" offset="0"/>
+            <match value="#\ KDE\ Config\ File" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-latex">
+        <_comment>LaTeX Source Document</_comment>
+        <magic priority="50">
+            <match value="%\ -*-latex-*-" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.latex"/>
+        <sub-class-of type="application/x-tex"/>
+    </mime-type>
+
+    <mime-type type="application/x-lha">
+        <magic priority="50">
+            <match value="-lzs-" type="string" offset="2"/>
+            <match value="-lh\40-" type="string" offset="2"/>
+            <match value="-lhd-" type="string" offset="2"/>
+            <match value="-lh2-" type="string" offset="2"/>
+            <match value="-lh3-" type="string" offset="2"/>
+            <match value="-lh4-" type="string" offset="2"/>
+            <match value="-lh5-" type="string" offset="2"/>
+            <match value="-lh6-" type="string" offset="2"/>
+            <match value="-lh7-" type="string" offset="2"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-lharc">
+        <magic priority="50">
+            <match value="-lh0-" type="string" offset="2"/>
+            <match value="-lh1-" type="string" offset="2"/>
+            <match value="-lz4-" type="string" offset="2"/>
+            <match value="-lz5-" type="string" offset="2"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-mobipocket-ebook">
+        <glob pattern="*.prc"/>
+        <glob pattern="*.mobi"/>
+    </mime-type>
+    <mime-type type="application/x-ms-application">
+        <glob pattern="*.application"/>
+    </mime-type>
+    <mime-type type="application/x-ms-wmd">
+        <glob pattern="*.wmd"/>
+    </mime-type>
+    <mime-type type="application/x-ms-wmz">
+        <sub-class-of type="application/x-gzip"/>
+        <glob pattern="*.wmz"/>
+    </mime-type>
+    <mime-type type="application/x-ms-xbap">
+        <glob pattern="*.xbap"/>
+    </mime-type>
+    <mime-type type="application/x-msaccess">
+        <glob pattern="*.mdb"/>
+        <magic priority="60">
+            <match value="0x000100005374616e" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-msbinder">
+        <glob pattern="*.obd"/>
+    </mime-type>
+    <mime-type type="application/x-mscardfile">
+        <glob pattern="*.crd"/>
+    </mime-type>
+    <mime-type type="application/x-msclip">
+        <glob pattern="*.clp"/>
+    </mime-type>
+
+    <mime-type type="application/x-msdownload">
+        <glob pattern="*.dll"/>
+        <glob pattern="*.com"/>
+        <glob pattern="*.bat"/>
+        <magic priority="50">
+            <match value="MZ" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-ms-installer">
+        <_comment>Microsoft Windows Installer</_comment>
+        <sub-class-of type="application/x-tika-msoffice"/>
+        <alias type="application/x-windows-installer"/>
+        <alias type="application/x-msi"/>
+        <glob pattern="*.msi"/>
+        <glob pattern="*.msp"/>
+        <glob pattern="*.mst"/>
+    </mime-type>
+
+    <mime-type type="application/x-msdownload;format=pe">
+        <sub-class-of type="application/x-msdownload"/>
+        <magic priority="55">
+            <!-- Technically the header offset is stored at 0x3c, and isn't a -->
+            <!-- constant, but it's almost always set to start at 0x80 or 0xf0 -->
+            <match value="PE\000\000" type="string" offset="128"/>
+            <match value="PE\000\000" type="string" offset="240"/>
+        </magic>
+    </mime-type>
+    <!-- the PE header should be PEx00x00 then a two byte machine type -->
+    <mime-type type="application/x-msdownload;format=pe32">
+        <sub-class-of type="application/x-msdownload;format=pe"/>
+        <magic priority="60">
+            <match value="PE\000\000" type="string" offset="128">
+                <match value="0x014c" type="little16" offset="132"/>
+            </match>
+            <match value="PE\000\000" type="string" offset="240">
+                <match value="0x014c" type="little16" offset="244"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-msdownload;format=pe64">
+        <sub-class-of type="application/x-msdownload;format=pe"/>
+        <magic priority="60">
+            <match value="PE\000\000" type="string" offset="128">
+                <match value="0x8664" type="little16" offset="132"/>
+            </match>
+            <match value="PE\000\000" type="string" offset="240">
+                <match value="0x8664" type="little16" offset="244"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-msdownload;format=pe-itanium">
+        <sub-class-of type="application/x-msdownload;format=pe"/>
+        <magic priority="60">
+            <match value="PE\000\000" type="string" offset="128">
+                <match value="0x0200" type="little16" offset="132"/>
+            </match>
+            <match value="PE\000\000" type="string" offset="240">
+                <match value="0x0200" type="little16" offset="244"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-msdownload;format=pe-armLE">
+        <sub-class-of type="application/x-msdownload;format=pe"/>
+        <magic priority="60">
+            <match value="pe\000\000" type="string" offset="128">
+                <match value="0x01c0" type="little16" offset="132"/>
+            </match>
+            <match value="pe\000\000" type="string" offset="240">
+                <match value="0x01c0" type="little16" offset="244"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-msdownload;format=pe-arm7">
+        <sub-class-of type="application/x-msdownload;format=pe"/>
+        <magic priority="60">
+            <match value="pe\000\000" type="string" offset="128">
+                <match value="0x01c4" type="little16" offset="132"/>
+            </match>
+            <match value="pe\000\000" type="string" offset="240">
+                <match value="0x01c4" type="little16" offset="244"/>
+            </match>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-msmediaview">
+        <glob pattern="*.mvb"/>
+        <glob pattern="*.m13"/>
+        <glob pattern="*.m14"/>
+    </mime-type>
+    <mime-type type="application/x-msmetafile">
+        <alias type="image/x-wmf"/>
+        <acronym>WMF</acronym>
+        <_comment>Windows Metafile</_comment>
+        <glob pattern="*.wmf"/>
+        <magic priority="50">
+            <match value="0xd7cdc69a0000" type="string" offset="0"/>
+            <match value="0x010009000003" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-msmoney">
+        <glob pattern="*.mny"/>
+        <magic priority="60">
+            <match value="0x000100004D534953414D204461746162617365" type="string" offset="0" />
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-mspublisher">
+        <glob pattern="*.pub"/>
+    </mime-type>
+    <mime-type type="application/x-msschedule">
+        <glob pattern="*.scd"/>
+    </mime-type>
+    <mime-type type="application/x-msterminal">
+        <glob pattern="*.trm"/>
+    </mime-type>
+    <mime-type type="application/x-mswrite">
+        <glob pattern="*.wri"/>
+    </mime-type>
+    <mime-type type="application/x-netcdf">
+        <glob pattern="*.nc"/>
+        <glob pattern="*.cdf"/>
+    </mime-type>
+    <mime-type type="application/x-pkcs12">
+        <glob pattern="*.p12"/>
+        <glob pattern="*.pfx"/>
+    </mime-type>
+    <mime-type type="application/x-pkcs7-certificates">
+        <glob pattern="*.p7b"/>
+        <glob pattern="*.spc"/>
+    </mime-type>
+    <mime-type type="application/x-pkcs7-certreqresp">
+        <glob pattern="*.p7r"/>
+    </mime-type>
+
+    <mime-type type="application/x-prt">
+        <glob pattern="*.prt"/>
+        <magic priority="50">
+            <match value="0M3C" type="string" offset="8" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-quattro-pro">
+        <glob pattern="*.qpw"/>
+        <glob pattern="*.wb1"/>
+        <glob pattern="*.wb2"/>
+        <glob pattern="*.wb3"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/x-rar-compressed">
+        <_comment>RAR archive</_comment>
+        <alias type="application/x-rar"/>
+        <magic priority="50">
+            <match value="Rar!" type="string" offset="0"/>
+            <match value="\x52\x61\x72\x21\x1a" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.rar"/>
+    </mime-type>
+
+    <mime-type type="application/x-roxio-toast">
+        <glob pattern="*.toast"/>
+        <sub-class-of type="application/x-iso9660-image"/>
+    </mime-type>
+
+    <mime-type type="application/x-rpm">
+        <_comment>RedHat Package Manager</_comment>
+        <glob pattern="*.rpm"/>
+        <magic priority="50">
+            <match value="\xed\xab\xee\xdb" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-sas">
+        <_comment>SAS Program</_comment>
+        <glob pattern="*.sas"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+    <mime-type type="application/x-sas-program-data">
+        <_comment>SAS Stored Program (DATA Step)</_comment>
+        <glob pattern="*.ss7"/>
+        <glob pattern="*.sas7bpgm"/>
+    </mime-type>
+    <mime-type type="application/x-sas-audit">
+        <_comment>SAS Audit</_comment>
+        <glob pattern="*.st7"/>
+        <glob pattern="*.sas7baud"/>
+    </mime-type>
+    <mime-type type="application/x-sas-data">
+        <_comment>SAS Data Set</_comment>
+        <glob pattern="*.sd7"/>
+        <glob pattern="*.sas7bdat"/>
+        <magic priority="40">
+            <match value="SAS FILE" type="string" offset="84" />
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-sas-view">
+        <_comment>SAS Data Set View</_comment>
+        <glob pattern="*.sv7"/>
+        <glob pattern="*.sas7bvew"/>
+    </mime-type>
+    <mime-type type="application/x-sas-data-index">
+        <_comment>SAS Data Set Index</_comment>
+        <glob pattern="*.si7"/>
+        <glob pattern="*.sas7bndx"/>
+    </mime-type>
+    <mime-type type="application/x-sas-catalog">
+        <_comment>SAS Catalog</_comment>
+        <glob pattern="*.sc7"/>
+        <glob pattern="*.sas7bcat"/>
+    </mime-type>
+    <mime-type type="application/x-sas-access">
+        <_comment>SAS Access Descriptor</_comment>
+        <glob pattern="*.sa7"/>
+        <glob pattern="*.sas7bacs"/>
+    </mime-type>
+    <mime-type type="application/x-sas-fdb">
+        <_comment>SAS FDB Consolidation Database File</_comment>
+        <glob pattern="*.sf7"/>
+        <glob pattern="*.sas7bfdb"/>
+    </mime-type>
+    <mime-type type="application/x-sas-mddb">
+        <_comment>SAS MDDB Multi-Dimensional Database File</_comment>
+        <glob pattern="*.sm7"/>
+        <glob pattern="*.sas7bmdb"/>
+    </mime-type>
+    <mime-type type="application/x-sas-dmdb">
+        <_comment>SAS DMDB Data Mining Database File</_comment>
+        <glob pattern="*.s7m"/>
+        <glob pattern="*.sas7bdmd"/>
+    </mime-type>
+    <mime-type type="application/x-sas-itemstor">
+        <_comment>SAS Item Store (ItemStor) File</_comment>
+        <glob pattern="*.sr7"/>
+        <glob pattern="*.sas7bitm"/>
+    </mime-type>
+    <mime-type type="application/x-sas-utility">
+        <_comment>SAS Utility</_comment>
+        <glob pattern="*.su7"/>
+        <glob pattern="*.sas7butl"/>
+    </mime-type>
+    <mime-type type="application/x-sas-putility">
+        <_comment>SAS Permanent Utility</_comment>
+        <glob pattern="*.sp7"/>
+        <glob pattern="*.sas7bput"/>
+    </mime-type>
+    <mime-type type="application/x-sas-transport">
+        <_comment>SAS Transport File</_comment>
+        <glob pattern="*.stx"/>
+    </mime-type>
+    <mime-type type="application/x-sas-backup">
+        <_comment>SAS Backup</_comment>
+        <glob pattern="*.sas7bbak"/>
+    </mime-type>
+
+    <mime-type type="application/x-sc">
+        <magic priority="50">
+            <match value="Spreadsheet" type="string" offset="38"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-sh">
+        <_comment>UNIX/LINUX Shell Script</_comment>
+        <magic priority="50">
+            <match value="#!/" type="string" offset="0"/>
+            <match value="#!\ /" type="string" offset="0"/>
+            <match value="#!\t/" type="string" offset="0"/>
+            <match value="eval &quot;exec" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.sh"/>
+        <glob pattern="*.bash"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="application/x-shar">
+        <glob pattern="*.shar"/>
+    </mime-type>
+
+    <mime-type type="application/x-shockwave-flash">
+        <acronym>Flash</acronym>
+        <_comment>Adobe Flash</_comment>
+        <magic priority="50">
+            <match value="FWS" type="string" offset="0"/> <!-- F = Uncompressed -->
+            <match value="CWS" type="string" offset="0"/> <!-- C = Compressed   -->
+        </magic>
+        <glob pattern="*.swf"/>
+    </mime-type>
+
+    <mime-type type="application/x-silverlight-app">
+        <glob pattern="*.xap"/>
+    </mime-type>
+
+    <mime-type type="application/x-stuffit">
+        <magic priority="50">
+            <match value="StuffIt" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.sit"/>
+    </mime-type>
+
+    <mime-type type="application/x-stuffitx">
+        <glob pattern="*.sitx"/>
+    </mime-type>
+    <mime-type type="application/x-sv4cpio">
+        <glob pattern="*.sv4cpio"/>
+    </mime-type>
+    <mime-type type="application/x-sv4crc">
+        <glob pattern="*.sv4crc"/>
+    </mime-type>
+
+    <mime-type type="application/x-tar">
+        <magic priority="40">
+            <!-- POSIX tar archive -->
+            <match value="ustar\0" type="string" offset="257" />
+        </magic>
+        <glob pattern="*.tar"/>
+    </mime-type>
+
+    <mime-type type="application/x-tex">
+        <_comment>TeX Source</_comment>
+        <alias type="text/x-tex"/>
+        <magic priority="50">
+            <match value="\\input" type="string" offset="0"/>
+            <match value="\\section" type="string" offset="0"/>
+            <match value="\\setlength" type="string" offset="0"/>
+            <match value="\\documentstyle" type="string" offset="0"/>
+            <match value="\\chapter" type="string" offset="0"/>
+            <match value="\\documentclass" type="string" offset="0"/>
+            <match value="\\relax" type="string" offset="0"/>
+            <match value="\\contentsline" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.tex"/>
+    </mime-type>
+
+    <mime-type type="application/x-tex-tfm">
+        <glob pattern="*.tfm"/>
+    </mime-type>
+
+    <mime-type type="application/x-texinfo">
+        <alias type="text/x-texinfo" />
+        <magic priority="50">
+            <match value="\\input\ texinfo" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.texinfo"/>
+        <glob pattern="*.texi"/>
+    </mime-type>
+
+    <!-- =================================================================== -->
+    <!-- Microsoft Office binary file formats                                -->
+    <!-- http://www.microsoft.com/interop/docs/OfficeBinaryFormats.mspx      -->
+    <!-- =================================================================== -->
+    <mime-type type="application/x-tika-msoffice">
+        <magic priority="40">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-tika-msoffice-embedded">
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+    <mime-type type="application/x-tika-msoffice-embedded;format=ole10_native">
+        <sub-class-of type="application/x-tika-msoffice-embedded"/>
+        <_comment>OLE10 Native Embedded Document</_comment>
+    </mime-type>
+    <mime-type type="application/x-tika-msoffice-embedded;format=comp_obj">
+        <sub-class-of type="application/x-tika-msoffice-embedded"/>
+        <_comment>CompObj OLE2 Embedded Document</_comment>
+    </mime-type>
+
+    <mime-type type="application/x-tika-msworks-spreadsheet">
+        <glob pattern="*.xlr"/>
+        <sub-class-of type="application/vnd.ms-excel"/>
+        <!-- this has to be highter than the Excel match -->
+        <magic priority="60">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="W\x00k\x00s\x00S\x00S\x00W\x00o\x00r\x00k\x00B\x00o\x00o\x00k" type="string" offset="1152:4096" />
+            </match>
+        </magic>
+    </mime-type>
+
+    <!-- =================================================================== -->
+    <!-- Office Open XML file formats                                        -->
+    <!-- http://www.ecma-international.org/publications/standards/Ecma-376.htm -->
+    <!-- =================================================================== -->
+    <mime-type type="application/x-tika-ooxml">
+        <sub-class-of type="application/zip"/>
+        <magic priority="50">
+            <match value="PK\003\004" type="string" offset="0">
+                <match value="[Content_Types].xml" type="string" offset="30"/>
+            </match>
+        </magic>
+    </mime-type>
+
+    <!-- Note - password protected OOXML files are actually stored in -->
+    <!--  an OLE2 (application/x-tika-msoffice) container -->
+    <mime-type type="application/x-tika-ooxml-protected">
+        <sub-class-of type="application/x-tika-ooxml"/>
+        <_comment>Password Protected OOXML File</_comment>
+    </mime-type>
+
+    <!-- Older StarOffice formats extend up the Microsoft OLE2 format -->
+    <mime-type type="application/x-tika-staroffice">
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/x-uc2-compressed">
+        <magic priority="50">
+            <match value="UC2\x1a" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.uc2"/>
+    </mime-type>
+    <mime-type type="application/x-ustar">
+        <glob pattern="*.ustar"/>
+    </mime-type>
+
+    <mime-type type="application/x-vmdk">
+        <acronym>VMDK</acronym>
+        <_comment>Virtual Disk Format</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/VMDK</tika:link>
+        <glob pattern="*.vmdk"/>
+    </mime-type>
+
+    <mime-type type="application/x-wais-source">
+        <glob pattern="*.src"/>
+    </mime-type>
+    <mime-type type="application/x-webarchive">
+        <sub-class-of type="application/x-bplist"/>
+        <glob pattern="*.webarchive"/>
+    </mime-type>
+    <mime-type type="application/x-x509-ca-cert">
+        <glob pattern="*.der"/>
+        <glob pattern="*.crt"/>
+    </mime-type>
+    <mime-type type="application/x-xfig">
+        <glob pattern="*.fig"/>
+    </mime-type>
+    <mime-type type="application/x-xpinstall">
+        <glob pattern="*.xpi"/>
+    </mime-type>
+
+    <mime-type type="application/x-xmind">
+        <_comment>XMind Pro</_comment>
+        <sub-class-of type="application/zip"/>
+        <glob pattern="*.xmind"/>
+        <!-- .xmap is also used, but that extension is more common elsewhere -->
+        <!-- <glob pattern="*.xmap"/> -->
+    </mime-type>
+
+    <mime-type type="application/x-xz">
+        <glob pattern="*.xz"/>
+        <magic priority="50">
+            <match value="\3757zXZ\000" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-zoo">
+        <magic priority="50">
+            <match value="0xfdc4a7dc" type="little32" offset="20"/>
+        </magic>
+        <glob pattern="*.zoo"/>
+    </mime-type>
+
+    <mime-type type="application/x400-bp"/>
+    <mime-type type="application/xcap-att+xml"/>
+    <mime-type type="application/xcap-caps+xml"/>
+    <mime-type type="application/xcap-el+xml"/>
+    <mime-type type="application/xcap-error+xml"/>
+    <mime-type type="application/xcap-ns+xml"/>
+    <mime-type type="application/xcon-conference-info-diff+xml"/>
+    <mime-type type="application/xcon-conference-info+xml"/>
+    <mime-type type="application/xenc+xml">
+        <glob pattern="*.xenc"/>
+    </mime-type>
+
+    <mime-type type="application/xhtml+xml">
+        <magic priority="50">
+            <match value="&lt;html xmlns=" type="string" offset="0:8192"/>
+        </magic>
+        <root-XML namespaceURI="http://www.w3.org/1999/xhtml" localName="html"/>
+        <glob pattern="*.xhtml"/>
+        <glob pattern="*.xht"/>
+    </mime-type>
+
+    <mime-type type="application/xhtml-voice+xml"/>
+
+    <mime-type type="application/xml">
+        <acronym>XML</acronym>
+        <_comment>Extensible Markup Language</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/Xml</tika:link>
+        <tika:uti>public.xml</tika:uti>
+        <alias type="text/xml"/>
+        <alias type="application/x-xml"/>
+        <magic priority="50">
+            <match value="&lt;?xml" type="string" offset="0"/>
+            <match value="&lt;?XML" type="string" offset="0"/>
+            <match value="&lt;!--" type="string" offset="0"/>
+            <!-- UTF-8 BOM -->
+            <match value="0xEFBBBF3C3F786D6C" type="string" offset="0"/>
+            <!-- UTF-16 LE/BE -->
+            <match value="0xFFFE3C003F0078006D006C00" type="string" offset="0"/>
+            <match value="0xFEFF003C003F0078006D006C" type="string" offset="0"/>
+            <!-- TODO: Add matches for the other possible XML encoding schemes -->
+        </magic>
+        <glob pattern="*.xml"/>
+        <glob pattern="*.xsl"/>
+        <glob pattern="*.xsd"/>
+        <sub-class-of type="text/plain" />
+    </mime-type>
+
+    <mime-type type="application/xml-dtd">
+        <_comment>XML Document Type Definition</_comment>
+        <sub-class-of type="text/plain"/>
+        <alias type="text/x-dtd"/>
+        <glob pattern="*.dtd"/>
+    </mime-type>
+
+    <mime-type type="application/xml-external-parsed-entity">
+        <alias type="text/xml-external-parsed-entity"/>
+    </mime-type>
+
+    <mime-type type="application/xmpp+xml"/>
+    <mime-type type="application/xop+xml">
+        <glob pattern="*.xop"/>
+    </mime-type>
+
+    <mime-type type="application/xslfo+xml">
+        <alias type="text/xsl"/>
+        <acronym>XSLFO</acronym>
+        <_comment>XSL Format</_comment>
+        <root-XML localName="root"
+                  namespaceURI="http://www.w3.org/1999/XSL/Format"/>
+        <glob pattern="*.xslfo"/>
+        <glob pattern="*.fo"/>
+    </mime-type>
+
+    <mime-type type="application/xslt+xml">
+        <alias type="text/xsl"/>
+        <acronym>XSLT</acronym>
+        <_comment>XSL Transformations</_comment>
+        <root-XML localName="stylesheet"
+                  namespaceURI="http://www.w3.org/1999/XSL/Transform"/>
+        <glob pattern="*.xslt"/>
+    </mime-type>
+
+    <mime-type type="application/xspf+xml">
+        <acronym>XSPF</acronym>
+        <_comment>XML Shareable Playlist Format</_comment>
+        <root-XML localName="playlist"
+                  namespaceURI="http://xspf.org/ns/0/"/>
+        <glob pattern="*.xspf"/>
+    </mime-type>
+
+    <mime-type type="application/xv+xml">
+        <glob pattern="*.mxml"/>
+        <glob pattern="*.xhvml"/>
+        <glob pattern="*.xvml"/>
+        <glob pattern="*.xvm"/>
+    </mime-type>
+
+    <mime-type type="application/zip">
+        <_comment>Compressed Archive File</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/ZIP_(file_format)</tika:link>
+        <tika:uti>com.pkware.zip-archive</tika:uti>
+        <alias type="application/x-zip-compressed"/>
+        <magic priority="50">
+            <match value="PK\003\004" type="string" offset="0"/>
+            <match value="PK\005\006" type="string" offset="0"/>
+            <match value="PK\x07\x08" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.zip"/>
+    </mime-type>
+
+    <mime-type type="application/x-7z-compressed">
+        <acronym>7zip</acronym>
+        <_comment>7-zip archive</_comment>
+        <magic priority="50">
+            <!-- Magic: '7', 'z', 0xBC, 0xAF, 0x27, 0x1C -->
+            <match value="7z" type="string" offset="0:1" >
+                <match value="0xBCAF271C" type="string" offset="2:5" />
+            </match>
+        </magic>
+        <glob pattern="*.7z" />
+    </mime-type>
+
+    <mime-type type="audio/32kadpcm"/>
+    <mime-type type="audio/3gpp"/>
+    <mime-type type="audio/3gpp2"/>
+    <mime-type type="audio/ac3"/>
+    <mime-type type="audio/adpcm">
+        <glob pattern="*.adp"/>
+    </mime-type>
+
+    <mime-type type="audio/amr">
+        <glob pattern="*.amr"/>
+        <magic priority="40">
+            <!-- Specific match for the original AMR format -->
+            <match value="#!AMR\n" type="string" offset="0"/>
+            <!-- General match for AMR subtypes we don't have entries for -->
+            <match value="#!AMR" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+    <mime-type type="audio/amr-wb">
+        <sub-class-of type="audio/amr"/>
+        <magic priority="50">
+            <match value="#!AMR-WB\n" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+    <mime-type type="audio/amr-wb+">
+        <sub-class-of type="audio/amr"/>
+        <!-- TIKA-1156 sample needed - might be "#!AMR-WB+\n" ? -->
+    </mime-type>
+
+    <mime-type type="audio/asc"/>
+
+    <mime-type type="audio/basic">
+        <_comment>uLaw/AU Audio File</_comment>
+        <magic priority="20">
+            <match value=".snd" type="string" offset="0">
+                <match value="1" type="big32" offset="12"/>
+                <match value="2" type="big32" offset="12"/>
+                <match value="3" type="big32" offset="12"/>
+                <match value="4" type="big32" offset="12"/>
+                <match value="5" type="big32" offset="12"/>
+                <match value="6" type="big32" offset="12"/>
+                <match value="7" type="big32" offset="12"/>
+            </match>
+            <match offset="0" type="string" value="\x2e\x73\x6e\x64\x00\x00\x00"/>
+        </magic>
+        <glob pattern="*.au"/>
+        <glob pattern="*.snd"/>
+    </mime-type>
+
+    <mime-type type="audio/bv16"/>
+    <mime-type type="audio/bv32"/>
+    <mime-type type="audio/clearmode"/>
+    <mime-type type="audio/cn"/>
+    <mime-type type="audio/dat12"/>
+    <mime-type type="audio/dls"/>
+    <mime-type type="audio/dsr-es201108"/>
+    <mime-type type="audio/dsr-es202050"/>
+    <mime-type type="audio/dsr-es202211"/>
+    <mime-type type="audio/dsr-es202212"/>
+    <mime-type type="audio/dvi4"/>
+    <mime-type type="audio/eac3"/>
+    <mime-type type="audio/evrc"/>
+    <mime-type type="audio/evrc-qcp"/>
+    <mime-type type="audio/evrc0"/>
+    <mime-type type="audio/evrc1"/>
+    <mime-type type="audio/evrcb"/>
+    <mime-type type="audio/evrcb0"/>
+    <mime-type type="audio/evrcb1"/>
+    <mime-type type="audio/evrcwb"/>
+    <mime-type type="audio/evrcwb0"/>
+    <mime-type type="audio/evrcwb1"/>
+    <mime-type type="audio/example"/>
+    <mime-type type="audio/g719"/>
+    <mime-type type="audio/g722"/>
+    <mime-type type="audio/g7221"/>
+    <mime-type type="audio/g723"/>
+    <mime-type type="audio/g726-16"/>
+    <mime-type type="audio/g726-24"/>
+    <mime-type type="audio/g726-32"/>
+    <mime-type type="audio/g726-40"/>
+    <mime-type type="audio/g728"/>
+    <mime-type type="audio/g729"/>
+    <mime-type type="audio/g7291"/>
+    <mime-type type="audio/g729d"/>
+    <mime-type type="audio/g729e"/>
+    <mime-type type="audio/gsm"/>
+    <mime-type type="audio/gsm-efr"/>
+    <mime-type type="audio/ilbc"/>
+    <mime-type type="audio/l16"/>
+    <mime-type type="audio/l20"/>
+    <mime-type type="audio/l24"/>
+    <mime-type type="audio/l8"/>
+    <mime-type type="audio/lpc"/>
+
+    <mime-type type="audio/midi">
+        <acronym>MIDI</acronym>
+        <_comment>Musical Instrument Digital Interface</_comment>
+        <magic priority ="20">
+            <match type="string" value="MThd" offset="0"/>
+        </magic>
+        <glob pattern="*.mid"/>
+        <glob pattern="*.midi"/>
+        <glob pattern="*.kar"/>
+        <glob pattern="*.rmi"/>
+    </mime-type>
+
+    <mime-type type="audio/mobile-xmf"/>
+    <mime-type type="audio/mp4">
+        <alias type="audio/x-m4a"/>
+        <alias type="audio/x-mp4a"/>
+        <magic priority="60">
+            <match value="ftypM4A " type="string" offset="4"/>
+            <match value="ftypM4B " type="string" offset="4"/>
+            <match value="ftypF4A " type="string" offset="4"/>
+            <match value="ftypF4B " type="string" offset="4"/>
+        </magic>
+        <glob pattern="*.mp4a"/>
+        <glob pattern="*.m4a"/>
+        <glob pattern="*.m4b"/>
+    </mime-type>
+    <mime-type type="audio/mp4a-latm"/>
+    <mime-type type="audio/mpa"/>
+    <mime-type type="audio/mpa-robust"/>
+
+    <mime-type type="audio/mpeg">
+        <alias type="audio/x-mpeg"/>
+        <acronym>MP3</acronym>
+        <_comment>MPEG-1 Audio Layer 3</_comment>
+        <magic priority="20">
+            <!-- http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html -->
+            <!-- Bit pattern for first two bytes: 11111111 111VVLLC    -->
+            <!-- VV = MPEG Audio Version ID; 10 = V2, 11 = V1          -->
+            <!-- LL = Layer description; 01 = L3, 10 = L2, 11 = L1     -->
+            <!-- C = Protection bit; 0 = CRC, 1 = no CRC               -->
+            <match value="0xfff2" type="string" offset="0"/> <!-- V2, L3, CRC -->
+            <match value="0xfff3" type="string" offset="0"/> <!-- V2, L3      -->
+            <match value="0xfff4" type="string" offset="0"/> <!-- V2, L2, CRC -->
+            <match value="0xfff5" type="string" offset="0"/> <!-- V2, L2      -->
+            <match value="0xfff6" type="string" offset="0"/> <!-- V2, L1, CRC -->
+            <match value="0xfff7" type="string" offset="0"/> <!-- V2, L1      -->
+            <match value="0xfffa" type="string" offset="0"/> <!-- V1, L3, CRC -->
+            <match value="0xfffb" type="string" offset="0"/> <!-- V1, L3      -->
+            <match value="0xfffc" type="string" offset="0"/> <!-- V1, L2, CRC -->
+            <match value="0xfffd" type="string" offset="0"/> <!-- V1, L2      -->
+            <!-- TIKA-417: This is the UTF-16 LE byte order mark! -->
+            <!-- match value="0xfffe" type="string" offset="0"/ --> <!-- V1, L1, CRC -->
+            <match value="0xffff" type="string" offset="0"/> <!-- V1, L1      -->
+            <match value="ID3" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.mpga"/>
+        <glob pattern="*.mp2"/>
+        <glob pattern="*.mp2a"/>
+        <glob pattern="*.mp3"/>
+        <glob pattern="*.m2a"/>
+        <glob pattern="*.m3a"/>
+    </mime-type>
+
+    <mime-type type="audio/mpeg4-generic"/>
+
+    <mime-type type="audio/ogg">
+        <_comment>Ogg Vorbis Audio</_comment>
+        <glob pattern="*.oga"/>
+        <sub-class-of type="application/ogg"/>
+    </mime-type>
+
+    <mime-type type="audio/vorbis">
+        <_comment>Ogg Vorbis Codec Compressed WAV File</_comment>
+        <alias type="application/x-ogg"/>
+        <magic priority="60">
+            <!-- For a single stream file -->
+            <match value="OggS\000.......................\001vorbis" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <glob pattern="*.ogg"/>
+        <sub-class-of type="audio/ogg"/>
+    </mime-type>
+
+    <mime-type type="audio/x-oggflac">
+        <_comment>Ogg Packaged Free Lossless Audio Codec</_comment>
+        <alias type="audio/x-ogg-flac"/>
+        <magic priority="60">
+            <!-- For a single stream file -->
+            <match value="OggS\000.......................FLAC" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="audio/ogg"/>
+    </mime-type>
+
+    <mime-type type="audio/x-oggpcm">
+        <_comment>Ogg Packaged Unompressed WAV File</_comment>
+        <alias type="audio/x-ogg-pcm"/>
+        <magic priority="60">
+            <!-- For a single stream file -->
+            <match value="OggS\000.......................PCM     " type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="audio/ogg"/>
+    </mime-type>
+
+    <mime-type type="audio/opus">
+        <_comment>Ogg Opus Codec Compressed WAV File</_comment>
+        <magic priority="60">
+            <!-- For a single stream file -->
+            <match value="OggS\000.......................OpusHead" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <glob pattern="*.opus"/>
+        <sub-class-of type="audio/ogg"/>
+    </mime-type>
+
+    <mime-type type="audio/speex">
+        <_comment>Ogg Speex Codec Compressed WAV File</_comment>
+        <alias type="application/x-speex"/>
+        <magic priority="60">
+            <!-- For a single stream file -->
+            <match value="OggS\000.......................Speex   " type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <glob pattern="*.spx"/>
+        <sub-class-of type="audio/ogg"/>
+    </mime-type>
+
+    <mime-type type="audio/parityfec"/>
+    <mime-type type="audio/pcma"/>
+    <mime-type type="audio/pcma-wb"/>
+    <mime-type type="audio/pcmu-wb"/>
+    <mime-type type="audio/pcmu"/>
+
+    <mime-type type="audio/prs.sid">
+        <magic priority="50">
+            <match value="PSID" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="audio/qcelp"/>
+    <mime-type type="audio/red"/>
+    <mime-type type="audio/rtp-enc-aescm128"/>
+    <mime-type type="audio/rtp-midi"/>
+    <mime-type type="audio/rtx"/>
+    <mime-type type="audio/smv"/>
+    <mime-type type="audio/smv0"/>
+    <mime-type type="audio/smv-qcp"/>
+    <mime-type type="audio/sp-midi"/>
+    <mime-type type="audio/t140c"/>
+    <mime-type type="audio/t38"/>
+    <mime-type type="audio/telephone-event"/>
+    <mime-type type="audio/tone"/>
+    <mime-type type="audio/ulpfec"/>
+    <mime-type type="audio/vdvi"/>
+    <mime-type type="audio/vmr-wb"/>
+    <mime-type type="audio/vnd.3gpp.iufp"/>
+    <mime-type type="audio/vnd.4sb"/>
+    <mime-type type="audio/vnd.audiokoz"/>
+    <mime-type type="audio/vnd.adobe.soundbooth">
+        <glob pattern="*.asnd"/>
+    </mime-type>
+    <mime-type type="audio/vnd.celp"/>
+    <mime-type type="audio/vnd.cisco.nse"/>
+    <mime-type type="audio/vnd.cmles.radio-events"/>
+    <mime-type type="audio/vnd.cns.anp1"/>
+    <mime-type type="audio/vnd.cns.inf1"/>
+    <mime-type type="audio/vnd.digital-winds">
+        <glob pattern="*.eol"/>
+    </mime-type>
+    <mime-type type="audio/vnd.dlna.adts"/>
+    <mime-type type="audio/vnd.dolby.heaac.1"/>
+    <mime-type type="audio/vnd.dolby.heaac.2"/>
+    <mime-type type="audio/vnd.dolby.mlp"/>
+    <mime-type type="audio/vnd.dolby.mps"/>
+    <mime-type type="audio/vnd.dolby.pl2"/>
+    <mime-type type="audio/vnd.dolby.pl2x"/>
+    <mime-type type="audio/vnd.dolby.pl2z"/>
+    <mime-type type="audio/vnd.dts">
+        <glob pattern="*.dts"/>
+    </mime-type>
+    <mime-type type="audio/vnd.dts.hd">
+        <glob pattern="*.dtshd"/>
+    </mime-type>
+    <mime-type type="audio/vnd.everad.plj"/>
+    <mime-type type="audio/vnd.hns.audio"/>
+    <mime-type type="audio/vnd.lucent.voice">
+        <glob pattern="*.lvp"/>
+    </mime-type>
+    <mime-type type="audio/vnd.ms-playready.media.pya">
+        <glob pattern="*.pya"/>
+    </mime-type>
+    <mime-type type="audio/vnd.nokia.mobile-xmf"/>
+    <mime-type type="audio/vnd.nortel.vbk"/>
+    <mime-type type="audio/vnd.nuera.ecelp4800">
+        <glob pattern="*.ecelp4800"/>
+    </mime-type>
+    <mime-type type="audio/vnd.nuera.ecelp7470">
+        <glob pattern="*.ecelp7470"/>
+    </mime-type>
+    <mime-type type="audio/vnd.nuera.ecelp9600">
+        <glob pattern="*.ecelp9600"/>
+    </mime-type>
+    <mime-type type="audio/vnd.octel.sbc"/>
+    <mime-type type="audio/vnd.qcelp"/>
+    <mime-type type="audio/vnd.rhetorex.32kadpcm"/>
+    <mime-type type="audio/vnd.sealedmedia.softseal.mpeg"/>
+    <mime-type type="audio/vnd.vmx.cvsd"/>
+    <mime-type type="audio/vorbis-config"/>
+    <mime-type type="audio/x-aac">
+        <glob pattern="*.aac"/>
+    </mime-type>
+
+    <mime-type type="audio/x-adbcm">
+        <magic priority="20">
+            <match value=".snd" type="string" offset="0">
+                <match value="23" type="big32" offset="12"/>
+            </match>
+        </magic>
+    </mime-type>
+
+    <mime-type type="audio/x-aiff">
+        <alias type="audio/aiff"/>
+        <acronym>AIFF</acronym>
+        <_comment>Audio Interchange File Format</_comment>
+        <magic priority="20">
+            <match value="FORM....AIFF" type="string" offset="0"
+                   mask="0xFFFFFFFF00000000FFFFFFFF"/>
+            <match value="FORM....AIFC" type="string" offset="0"
+                   mask="0xFFFFFFFF00000000FFFFFFFF"/>
+            <!-- Amiga IFF sound sample, somewhat like the more modern AIFF -->
+            <match value="FORM....8SVX" type="string" offset="0"
+                   mask="0xFFFFFFFF00000000FFFFFFFF"/>
+            <match offset="0" type="string" value="\x46\x4f\x52\x4d\x00"/>
+        </magic>
+        <glob pattern="*.aif"/>
+        <glob pattern="*.aiff"/>
+        <glob pattern="*.aifc"/>
+    </mime-type>
+
+    <mime-type type="audio/x-dec-basic">
+        <magic priority="20">
+            <match value="0x0064732E" type="big32" offset="0">
+                <match value="1" type="big32" offset="12"/>
+                <match value="2" type="big32" offset="12"/>
+                <match value="3" type="big32" offset="12"/>
+                <match value="4" type="big32" offset="12"/>
+                <match value="5" type="big32" offset="12"/>
+                <match value="6" type="big32" offset="12"/>
+                <match value="7" type="big32" offset="12"/>
+            </match>
+        </magic>
+    </mime-type>
+
+    <mime-type type="audio/x-dec-adbcm">
+        <magic priority="20">
+            <match value="0x0064732E" type="big32" offset="0">
+                <match value="23" type="big32" offset="12"/>
+            </match>
+        </magic>
+    </mime-type>
+
+    <mime-type type="audio/x-flac">
+        <acronym>FLAC</acronym>
+        <_comment>Free Lossless Audio Codec</_comment>
+        <magic priority="50">
+            <match value="fLaC" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.flac"/>
+    </mime-type>
+
+    <mime-type type="audio/x-mod">
+        <acronym>MOD</acronym>
+        <magic priority="50">
+            <match value="Extended\ Module:" type="string" offset="0"/>
+            <match value="BMOD2STM" type="string" offset="21"/>
+            <match value="M.K." type="string" offset="1080"/>
+            <match value="M!K!" type="string" offset="1080"/>
+            <match value="FLT4" type="string" offset="1080"/>
+            <match value="FLT8" type="string" offset="1080"/>
+            <match value="4CHN" type="string" offset="1080"/>
+            <match value="6CHN" type="string" offset="1080"/>
+            <match value="8CHN" type="string" offset="1080"/>
+            <match value="CD81" type="string" offset="1080"/>
+            <match value="OKTA" type="string" offset="1080"/>
+            <match value="16CN" type="string" offset="1080"/>
+            <match value="32CN" type="string" offset="1080"/>
+            <match value="IMPM" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.mod"/>
+    </mime-type>
+
+    <mime-type type="audio/x-mpegurl">
+        <_comment>MP3 Playlist File</_comment>
+        <magic priority="50">
+            <match offset="0" type="string" value="\x23\x45\x58\x54\x4d\x33\x55\x0d\x0a"/>
+        </magic>
+        <glob pattern="*.m3u"/>
+    </mime-type>
+
+    <mime-type type="audio/x-ms-wax">
+        <glob pattern="*.wax"/>
+    </mime-type>
+    <mime-type type="audio/x-ms-wma">
+        <sub-class-of type="video/x-ms-asf" />
+        <glob pattern="*.wma"/>
+        <magic priority="50">
+            <match value="Windows Media Audio" type="unicodeLE" offset="0:8192" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="audio/x-pn-realaudio">
+        <_comment>Real Audio</_comment>
+        <alias type="audio/x-realaudio" />
+        <magic priority="50">
+            <match value="0x2e7261fd" type="big32" offset="0"/>
+        </magic>
+        <glob pattern="*.ram"/>
+        <glob pattern="*.ra"/>
+    </mime-type>
+
+    <mime-type type="audio/x-pn-realaudio-plugin">
+        <_comment>RealMedia Player Plug-in</_comment>
+        <glob pattern="*.rmp"/>
+        <!-- <glob pattern="*.rpm"/> - conflicts with application/x-rpm -->
+    </mime-type>
+
+    <mime-type type="audio/x-wav">
+        <acronym>WAV</acronym>
+        <magic priority="20">
+            <match value="RIFF....WAVE" type="string" offset="0"
+                   mask="0xFFFFFFFF00000000FFFFFFFF"/>
+        </magic>
+        <glob pattern="*.wav"/>
+    </mime-type>
+
+    <mime-type type="chemical/x-cdx">
+        <magic priority="50">
+            <match value="VjCD0100" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.cdx"/>
+    </mime-type>
+    <mime-type type="chemical/x-cif">
+        <glob pattern="*.cif"/>
+    </mime-type>
+    <mime-type type="chemical/x-cmdf">
+        <glob pattern="*.cmdf"/>
+    </mime-type>
+    <mime-type type="chemical/x-cml">
+        <glob pattern="*.cml"/>
+    </mime-type>
+    <mime-type type="chemical/x-csml">
+        <glob pattern="*.csml"/>
+    </mime-type>
+
+    <mime-type type="chemical/x-pdb">
+        <_comment>Brookhaven Protein Databank File</_comment>
+        <glob pattern="*.pdb"/>
+    </mime-type>
+
+    <mime-type type="chemical/x-xyz">
+        <glob pattern="*.xyz"/>
+    </mime-type>
+
+    <mime-type type="image/x-ms-bmp">
+        <alias type="image/bmp"/>
+        <acronym>BMP</acronym>
+        <_comment>Windows bitmap</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/BMP_file_format</tika:link>
+        <tika:uti>com.microsoft.bmp</tika:uti>
+        <magic priority="50">
+            <match value="BM" type="string" offset="0">
+                <match value="0x0100" type="string" offset="26">
+                    <match value="0x0000" type="string" offset="28"/>
+                    <match value="0x0100" type="string" offset="28"/>
+                    <match value="0x0400" type="string" offset="28"/>
+                    <match value="0x0800" type="string" offset="28"/>
+                    <match value="0x1000" type="string" offset="28"/>
+                    <match value="0x1800" type="string" offset="28"/>
+                    <match value="0x2000" type="string" offset="28"/>
+                </match>
+            </match>
+        </magic>
+        <glob pattern="*.bmp"/>
+        <glob pattern="*.dib"/>
+    </mime-type>
+
+    <mime-type type="image/cgm">
+        <acronym>CGM</acronym>
+        <_comment>Computer Graphics Metafile</_comment>
+        <magic priority="50">
+            <match value="BEGMF" type="string" offset="0"/>
+            <match value="0x0020" mask="0xffe0" type="string" offset="0">
+                <match value="0x10220001" type="string" offset="2:64"/>
+                <match value="0x10220002" type="string" offset="2:64"/>
+                <match value="0x10220003" type="string" offset="2:64"/>
+                <match value="0x10220004" type="string" offset="2:64"/>
+            </match>
+        </magic>
+        <glob pattern="*.cgm"/>
+    </mime-type>
+
+    <mime-type type="image/example"/>
+
+    <mime-type type="image/fits">
+        <sub-class-of type="application/fits"/>
+    </mime-type>
+
+    <mime-type type="image/g3fax">
+        <glob pattern="*.g3"/>
+    </mime-type>
+
+    <mime-type type="image/gif">
+        <acronym>GIF</acronym>
+        <_comment>Graphics Interchange Format</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/Gif</tika:link>
+        <tika:uti>com.compuserve.gif</tika:uti>
+        <magic priority="50">
+            <match value="GIF87a" type="string" offset="0"/>
+            <match value="GIF89a" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.gif"/>
+    </mime-type>
+
+    <mime-type type="image/ief">
+        <glob pattern="*.ief"/>
+    </mime-type>
+
+    <mime-type type="image/jp2">
+        <sub-class-of type="image/x-jp2-container" />
+        <acronym>JP2</acronym>
+        <_comment>JPEG 2000 Part 1 (JP2)</_comment>
+        <magic priority="50">
+            <match value="0x0000000C6A5020200D0A870A" type="string" offset="0">
+                <match value="0x6a703220" type="string" offset="20"/>
+            </match>
+        </magic>
+        <glob pattern="*.jp2"/>
+    </mime-type>
+
+    <mime-type type="image/jpeg">
+        <acronym>JPEG</acronym>
+        <_comment>Joint Photographic Experts Group</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/Jpeg</tika:link>
+        <tika:uti>public.jpeg</tika:uti>
+        <magic priority="50">
+            <!-- FFD8 is the SOI (Start Of Image) marker.              -->
+            <!-- It is followed by another marker that starts with FF. -->
+            <match value="0xffd8ff" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.jpg"/>
+        <glob pattern="*.jpeg"/>
+        <glob pattern="*.jpe"/>
+        <glob pattern="*.jif"/>
+        <glob pattern="*.jfif"/>
+        <glob pattern="*.jfi"/>
+    </mime-type>
+
+    <mime-type type="image/jpm">
+        <alias type="video/jpm"/>
+        <sub-class-of type="image/x-jp2-container" />
+        <acronym>JP2</acronym>
+        <_comment>JPEG 2000 Part 6 (JPM)</_comment>
+        <magic priority="50">
+            <match value="0x0000000C6A5020200D0A870A" type="string" offset="0">
+                <match value="0x6a706d20" type="string" offset="20"/>
+            </match>
+        </magic>
+        <glob pattern="*.jpm"/>
+        <glob pattern="*.jpgm"/>
+    </mime-type>
+
+    <mime-type type="image/jpx">
+        <sub-class-of type="image/x-jp2-container" />
+        <acronym>JP2</acronym>
+        <_comment>JPEG 2000 Part 2 (JPX)</_comment>
+        <magic priority="50">
+            <match value="0x0000000C6A5020200D0A870A" type="string" offset="0">
+                <match value="0x6a707820" type="string" offset="20"/>
+            </match>
+        </magic>
+        <glob pattern="*.jpf"/>
+    </mime-type>
+
+    <mime-type type="image/naplps"/>
+
+    <mime-type type="image/nitf">
+        <alias type="image/ntf"/>
+        <magic priority="50">
+            <match value="NITF01.10" type="string" offset="0"/>
+            <match value="NITF02.000" type="string" offset="0"/>
+            <match value="NITF02.100" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.ntf"/>
+        <glob pattern="*.nitf"/>
+    </mime-type>
+
+    <mime-type type="image/png">
+        <acronym>PNG</acronym>
+        <_comment>Portable Network Graphics</_comment>
+        <magic priority="50">
+            <match value="\x89PNG\x0d\x0a\x1a\x0a" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.png"/>
+    </mime-type>
+
+    <mime-type type="image/prs.btif">
+        <glob pattern="*.btif"/>
+    </mime-type>
+    <mime-type type="image/prs.pti"/>
+
+    <mime-type type="image/svg+xml">
+        <sub-class-of type="application/xml"/>
+        <acronym>SVG</acronym>
+        <_comment>Scalable Vector Graphics</_comment>
+        <root-XML localName="svg" namespaceURI="http://www.w3.org/2000/svg"/>
+        <glob pattern="*.svg"/>
+        <glob pattern="*.svgz"/>
+    </mime-type>
+
+    <mime-type type="image/t38"/>
+
+    <mime-type type="image/tiff">
+        <acronym>TIFF</acronym>
+        <_comment>Tagged Image File Format</_comment>
+        <magic priority="50">
+            <!-- MM.* = Big endian (M=Motorola) and 0x002a in big endian    -->
+            <match value="MM\x00\x2a" type="string" offset="0"/>
+            <!-- II*. = Little endian (I=Intel) and 0x002a in little endian -->
+            <match value="II\x2a\x00" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.tiff"/>
+        <glob pattern="*.tif"/>
+    </mime-type>
+
+    <mime-type type="image/tiff-fx"/>
+
+    <mime-type type="image/vnd.adobe.photoshop">
+        <acronym>PSD</acronym>
+        <_comment>Photoshop Image</_comment>
+        <alias type="image/x-psd"/>
+        <alias type="application/photoshop"/>
+        <magic priority="50">
+            <!-- Version of 0x0001 is PSD -->
+            <match value="8BPS\x00\x01" type="string" offset="0"/>
+            <!-- Version of 0x0002 is PSB -->
+            <match value="8BPS\x00\x02" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.psd"/>
+    </mime-type>
+
+    <mime-type type="image/vnd.adobe.premiere">
+        <glob pattern="*.ppj"/>
+        <root-XML localName="PremiereData"/>
+        <sub-class-of type="application/xml"/>
+    </mime-type>
+
+    <mime-type type="image/vnd.cns.inf2"/>
+    <mime-type type="image/vnd.djvu">
+        <glob pattern="*.djvu"/>
+        <glob pattern="*.djv"/>
+    </mime-type>
+
+    <mime-type type="image/vnd.dwg">
+        <acronym>DWG</acronym>
+        <_comment>AutoCad Drawing</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/.dwg</tika:link>
+        <alias type="image/x-dwg"/>
+        <alias type="application/acad"/>
+        <alias type="application/x-acad"/>
+        <alias type="application/autocad_dwg"/>
+        <alias type="application/dwg"/>
+        <alias type="application/x-dwg"/>
+        <alias type="application/x-autocad"/>
+        <alias type="image/vnd.dwg"/>
+        <alias type="drawing/dwg"/>
+        <glob pattern="*.dwg"/>
+        <magic priority="50">
+            <match value="MC0.0" type="string" offset="0"/>
+            <match value="AC1.2" type="string" offset="0"/>
+            <match value="AC1.40" type="string" offset="0"/>
+            <match value="AC1.50" type="string" offset="0"/>
+            <match value="AC2.10" type="string" offset="0"/>
+            <match value="AC2.21" type="string" offset="0"/>
+            <match value="AC2.22" type="string" offset="0"/>
+            <!-- "AC" followed by four numbers -->
+            <match value="AC0000" type="string" offset="0"
+                   mask="0xFFFFF0F0F0F0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="image/vnd.dxf">
+        <acronym>DXF</acronym>
+        <_comment>AutoCAD DXF</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/AutoCAD_DXF</tika:link>
+        <glob pattern="*.dxf"/>
+    </mime-type>
+    <mime-type type="image/vnd.fastbidsheet">
+        <glob pattern="*.fbs"/>
+    </mime-type>
+    <mime-type type="image/vnd.fpx">
+        <glob pattern="*.fpx"/>
+    </mime-type>
+    <mime-type type="image/vnd.fst">
+        <glob pattern="*.fst"/>
+    </mime-type>
+    <mime-type type="image/vnd.fujixerox.edmics-mmr">
+        <glob pattern="*.mmr"/>
+    </mime-type>
+    <mime-type type="image/vnd.fujixerox.edmics-rlc">
+        <glob pattern="*.rlc"/>
+    </mime-type>
+    <mime-type type="image/vnd.globalgraphics.pgb"/>
+
+    <mime-type type="image/vnd.microsoft.icon">
+        <acronym>ICO</acronym>
+        <tika:link>http://en.wikipedia.org/wiki/.ico</tika:link>
+        <tika:uti>com.microsoft.ico</tika:uti>
+        <alias type="image/x-icon" />
+        <magic priority="50">
+            <match value="\102\101\050\000\000\000\056\000\000\000\000\000\000\000"
+                   type="string" offset="0"/>
+            <match value="\000\000\001\000" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.ico"/>
+    </mime-type>
+
+    <mime-type type="image/vnd.mix"/>
+    <mime-type type="image/vnd.ms-modi">
+        <glob pattern="*.mdi"/>
+        <_comment>Microsoft Document Imaging</_comment>
+        <magic priority="50">
+            <match value="0x45502A00" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="image/vnd.net-fpx">
+        <glob pattern="*.npx"/>
+    </mime-type>
+    <mime-type type="image/vnd.radiance"/>
+    <mime-type type="image/vnd.sealed.png"/>
+    <mime-type type="image/vnd.sealedmedia.softseal.gif"/>
+    <mime-type type="image/vnd.sealedmedia.softseal.jpg"/>
+    <mime-type type="image/vnd.svf"/>
+
+    <mime-type type="image/vnd.wap.wbmp">
+        <_comment>Wireless Bitmap File Format</_comment>
+        <glob pattern="*.wbmp"/>
+    </mime-type>
+
+    <mime-type type="image/vnd.xiff">
+        <glob pattern="*.xif"/>
+    </mime-type>
+    <mime-type type="image/x-cmu-raster">
+        <glob pattern="*.ras"/>
+    </mime-type>
+    <mime-type type="image/x-cmx">
+        <glob pattern="*.cmx"/>
+    </mime-type>
+
+    <mime-type type="image/x-freehand">
+        <_comment>FreeHand image</_comment>
+        <magic priority="50">
+            <match value="AGD2" type="string" offset="0"/>
+            <match value="AGD3" type="string" offset="0"/>
+            <match value="AGD4" type="string" offset="0"/>
+            <match value="FreeHand10" type="string" offset="0:24"/>
+            <match value="FreeHand11" type="string" offset="0:24"/>
+            <match value="FreeHand12" type="string" offset="0:24"/>
+        </magic>
+        <glob pattern="*.fh"/>
+        <glob pattern="*.fhc"/>
+        <glob pattern="*.fh4"/>
+        <glob pattern="*.fh40"/>
+        <glob pattern="*.fh5"/>
+        <glob pattern="*.fh50"/>
+        <glob pattern="*.fh7"/>
+        <glob pattern="*.fh8"/>
+        <glob pattern="*.fh9"/>
+        <glob pattern="*.fh10"/>
+        <glob pattern="*.fh11"/>
+        <glob pattern="*.fh12"/>
+        <glob pattern="*.ft7"/>
+        <glob pattern="*.ft8"/>
+        <glob pattern="*.ft9"/>
+        <glob pattern="*.ft10"/>
+        <glob pattern="*.ft11"/>
+        <glob pattern="*.ft12"/>
+    </mime-type>
+
+    <mime-type type="image/x-jp2-codestream">
+        <_comment>JPEG 2000 Codestream</_comment>
+        <magic priority="25">
+            <match value="0xff4fff51" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.j2c"/>
+    </mime-type>
+
+    <mime-type type="image/x-jp2-container">
+        <_comment>JPEG 2000 Container Format</_comment>
+        <magic priority="50">
+            <match value="0x0000000C6A5020200D0A870A" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="image/x-niff">
+        <_comment>Navy Interchange File Format</_comment>
+        <magic priority="50">
+            <match value="IIN1" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="image/x-pcx">
+        <glob pattern="*.pcx"/>
+    </mime-type>
+    <mime-type type="image/x-pict">
+        <_comment>Apple Macintosh QuickDraw/PICT Format</_comment>
+        <magic priority="50">
+            <match value="0x001102FF0C00" type="string" offset="522"/>
+        </magic>
+        <glob pattern="*.pic"/>
+        <glob pattern="*.pct"/>
+        <glob pattern="*.pict"/>
+    </mime-type>
+
+    <mime-type type="image/x-portable-anymap">
+        <acronym>PNM</acronym>
+        <_comment>Portable Any Map</_comment>
+        <glob pattern="*.pnm" />
+    </mime-type>
+
+    <mime-type type="image/x-portable-bitmap">
+        <sub-class-of type="image/x-portable-anymap"/>
+        <acronym>PBM</acronym>
+        <_comment>Portable Bit Map</_comment>
+        <magic priority="50">
+            <match value="P1" type="string" offset="0"/>
+            <match value="P4" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.pbm"/>
+    </mime-type>
+
+    <mime-type type="image/x-portable-graymap">
+        <sub-class-of type="image/x-portable-anymap"/>
+        <acronym>PGM</acronym>
+        <_comment>Portable Graymap Graphic</_comment>
+        <magic priority="50">
+            <match value="P2" type="string" offset="0"/>
+            <match value="P5" type="string" offset="0"/>
+            <match offset="0" type="string" value="\x50\x35\x0a"/>
+        </magic>
+        <glob pattern="*.pgm"/>
+    </mime-type>
+
+    <mime-type type="image/x-portable-pixmap">
+        <sub-class-of type="image/x-portable-anymap"/>
+        <acronym>PXM</acronym>
+        <_comment>UNIX Portable Bitmap Graphic</_comment>
+        <magic priority="50">
+            <match value="P3" type="string" offset="0"/>
+            <match value="P6" type="string" offset="0"/>
+            <match value="P7" type="string" offset="0"/>
+            <match offset="0" type="string" value="\x50\x34\x0a"/>
+        </magic>
+        <glob pattern="*.ppm"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-adobe">
+        <acronym>DNG</acronym>
+        <_comment>Adobe Digital Negative</_comment>
+        <glob pattern="*.dng"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-hasselblad">
+        <_comment>Hasselblad raw image</_comment>
+        <glob pattern="*.3fr"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-fuji">
+        <_comment>Fuji raw image</_comment>
+        <glob pattern="*.raf"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-canon">
+        <_comment>Canon raw image</_comment>
+        <glob pattern="*.crw"/>
+        <glob pattern="*.cr2"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-kodak">
+        <_comment>Kodak raw image</_comment>
+        <glob pattern="*.k25"/>
+        <glob pattern="*.kdc"/>
+        <glob pattern="*.dcs"/>
+        <glob pattern="*.drf"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-minolta">
+        <_comment>Minolta raw image</_comment>
+        <glob pattern="*.mrw"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-nikon">
+        <_comment>Nikon raw image</_comment>
+        <glob pattern="*.nef"/>
+        <glob pattern="*.nrw"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-olympus">
+        <_comment>Olympus raw image</_comment>
+        <glob pattern="*.orf"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-pentax">
+        <_comment>Pentax raw image</_comment>
+        <glob pattern="*.ptx"/>
+        <glob pattern="*.pef"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-sony">
+        <_comment>Sony raw image</_comment>
+        <glob pattern="*.arw"/>
+        <glob pattern="*.srf"/>
+        <glob pattern="*.sr2"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-sigma">
+        <_comment>Sigma raw image</_comment>
+        <glob pattern="*.x3f"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-epson">
+        <_comment>Epson raw image</_comment>
+        <glob pattern="*.erf"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-mamiya">
+        <_comment>Mamiya raw image</_comment>
+        <glob pattern="*.mef"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-leaf">
+        <_comment>Leaf raw image</_comment>
+        <glob pattern="*.mos"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-panasonic">
+        <_comment>Panasonic raw image</_comment>
+        <glob pattern="*.raw"/>
+        <glob pattern="*.rw2"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-phaseone">
+        <_comment>Phase One raw image</_comment>
+        <glob pattern="*.iiq"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-red">
+        <_comment>Red raw image</_comment>
+        <glob pattern="*.r3d"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-imacon">
+        <_comment>Imacon raw image</_comment>
+        <glob pattern="*.fff"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-logitech">
+        <_comment>Logitech raw image</_comment>
+        <glob pattern="*.pxn"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-casio">
+        <_comment>Casio raw image</_comment>
+        <glob pattern="*.bay"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-rawzor">
+        <_comment>Rawzor raw image</_comment>
+        <glob pattern="*.rwz"/>
+    </mime-type>
+
+    <mime-type type="image/x-rgb">
+        <_comment>Silicon Graphics RGB Bitmap</_comment>
+        <magic priority="50">
+            <match offset="0" type="string" value="\x01\xda\x01\x01\x00\x03"/>
+        </magic>
+        <glob pattern="*.rgb"/>
+    </mime-type>
+
+    <mime-type type="image/x-xbitmap">
+        <magic priority="50">
+            <match value="/* XPM" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.xbm"/>
+        <sub-class-of type="text/x-c"/>
+    </mime-type>
+
+    <mime-type type="image/x-xcf">
+        <_comment>GIMP Image File</_comment>
+        <alias type="image/xcf"/>
+        <magic priority="50">
+            <match type="string" value="gimp xcf " offset="0"/>
+        </magic>
+        <glob pattern="*.xcf"/>
+    </mime-type>
+
+    <mime-type type="image/x-xpixmap">
+        <glob pattern="*.xpm"/>
+    </mime-type>
+
+    <mime-type type="image/x-xwindowdump">
+        <_comment>X Windows Dump</_comment>
+        <glob pattern="*.xwd"/>
+    </mime-type>
+
+    <mime-type type="message/cpim"/>
+    <mime-type type="message/delivery-status"/>
+    <mime-type type="message/disposition-notification"/>
+    <mime-type type="message/example"/>
+    <mime-type type="message/external-body"/>
+    <mime-type type="message/global"/>
+    <mime-type type="message/global-delivery-status"/>
+    <mime-type type="message/global-disposition-notification"/>
+    <mime-type type="message/global-headers"/>
+    <mime-type type="message/http"/>
+    <mime-type type="message/imdn+xml"/>
+
+    <mime-type type="message/news">
+        <magic priority="50">
+            <match value="Path:" type="string" offset="0" />
+            <match value="Xref:" type="string" offset="0" />
+            <match value="Article" type="string" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="message/partial"/>
+
+    <mime-type type="message/rfc822">
+        <magic priority="50">
+            <match value="Relay-Version:" type="stringignorecase" offset="0"/>
+            <match value="#!\ rnews" type="string" offset="0"/>
+            <match value="N#!\ rnews" type="string" offset="0"/>
+            <match value="Forward\ to" type="string" offset="0"/>
+            <match value="Pipe\ to" type="string" offset="0"/>
+            <match value="Return-Path:" type="stringignorecase" offset="0"/>
+            <match value="From:" type="stringignorecase" offset="0"/>
+            <match value="Received:" type="stringignorecase" offset="0"/>
+            <match value="Message-ID:" type="stringignorecase" offset="0"/>
+            <match value="Date:" type="string" offset="0"/>
+            <match value="MIME-Version:" type="stringignorecase" offset="0"/>
+            <match value="X-Notes-Item:" type="string" offset="0">
+                <match value="Message-ID:" type="string" offset="0:8192"/>
+            </match>
+        </magic>
+        <glob pattern="*.eml"/>
+        <glob pattern="*.mime"/>
+        <glob pattern="*.mht"/>
+        <glob pattern="*.mhtml"/>
+    </mime-type>
+
+    <mime-type type="message/s-http"/>
+    <mime-type type="message/sip"/>
+    <mime-type type="message/sipfrag"/>
+    <mime-type type="message/tracking-status"/>
+    <mime-type type="message/vnd.si.simp"/>
+
+    <mime-type type="model/example"/>
+
+    <mime-type type="model/iges">
+        <_comment>Initial Graphics Exchange Specification Format</_comment>
+        <glob pattern="*.igs"/>
+        <glob pattern="*.iges"/>
+    </mime-type>
+
+    <mime-type type="model/mesh">
+        <glob pattern="*.msh"/>
+        <glob pattern="*.mesh"/>
+        <glob pattern="*.silo"/>
+    </mime-type>
+
+    <mime-type type="model/vnd.dwf">
+        <glob pattern="*.dwf"/>
+    </mime-type>
+    <mime-type type="model/vnd.dwfx+xps">
+        <_comment>AutoCAD Design Web Format</_comment>
+        <glob pattern="*.dwfx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="model/vnd.flatland.3dml"/>
+    <mime-type type="model/vnd.gdl">
+        <glob pattern="*.gdl"/>
+    </mime-type>
+    <mime-type type="model/vnd.gs-gdl"/>
+    <mime-type type="model/vnd.gs.gdl"/>
+    <mime-type type="model/vnd.gtw">
+        <glob pattern="*.gtw"/>
+    </mime-type>
+    <mime-type type="model/vnd.moml+xml"/>
+    <mime-type type="model/vnd.mts">
+        <glob pattern="*.mts"/>
+    </mime-type>
+    <mime-type type="model/vnd.parasolid.transmit.binary"/>
+    <mime-type type="model/vnd.parasolid.transmit.text"/>
+    <mime-type type="model/vnd.vtu">
+        <glob pattern="*.vtu"/>
+    </mime-type>
+
+    <mime-type type="model/vrml">
+        <glob pattern="*.wrl"/>
+        <glob pattern="*.vrml"/>
+    </mime-type>
+
+    <mime-type type="multipart/alternative"/>
+    <mime-type type="multipart/appledouble"/>
+    <mime-type type="multipart/byteranges"/>
+    <mime-type type="multipart/digest"/>
+    <mime-type type="multipart/encrypted"/>
+    <mime-type type="multipart/example"/>
+    <mime-type type="multipart/form-data"/>
+    <mime-type type="multipart/header-set"/>
+    <mime-type type="multipart/mixed"/>
+    <mime-type type="multipart/parallel"/>
+    <mime-type type="multipart/related"/>
+    <mime-type type="multipart/report"/>
+    <mime-type type="multipart/signed"/>
+    <mime-type type="multipart/voice-message"/>
+
+    <mime-type type="text/x-actionscript">
+        <_comment>ActionScript source code</_comment>
+        <glob pattern="*.as"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-ada">
+        <_comment>Ada source code</_comment>
+        <glob pattern="*.ada"/>
+        <glob pattern="*.adb"/>
+        <glob pattern="*.ads"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-applescript">
+        <_comment>AppleScript source code</_comment>
+        <glob pattern="*.applescript"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/asp">
+        <_comment>Active Server Page</_comment>
+        <glob pattern="*.asp"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/aspdotnet">
+        <_comment>ASP .NET</_comment>
+        <glob pattern="*.aspx"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-aspectj">
+        <_comment>AspectJ source code</_comment>
+        <glob pattern="*.aj"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-assembly">
+        <alias type="text/x-asm"/>
+        <_comment>Assembler source code</_comment>
+        <glob pattern="*.s"/>
+        <glob pattern="*.S"/>
+        <glob pattern="*.asm"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/calendar">
+        <glob pattern="*.ics"/>
+        <glob pattern="*.ifb"/>
+    </mime-type>
+
+    <mime-type type="text/css">
+        <_comment>Cascading Style Sheet</_comment>
+        <glob pattern="*.css"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/csv">
+        <glob pattern="*.csv"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/directory"/>
+    <mime-type type="text/dns"/>
+    <mime-type type="text/ecmascript"/>
+    <mime-type type="text/enriched"/>
+    <mime-type type="text/example"/>
+
+    <mime-type type="text/html">
+        <_comment>HyperText Markup Language</_comment>
+        <acronym>HTML</acronym>
+        <tika:uti>public.html</tika:uti>
+        <!-- TIKA-327: if you encounter tags in the HTML
+          with no declared namespace, it's not XHTML, it's just
+          bad HTML, unfortunately.
+     -->
+        <root-XML localName="html"/>
+        <root-XML localName="HTML"/>
+        <root-XML localName="link"/>
+        <root-XML localName="LINK"/>
+        <root-XML localName="body"/>
+        <root-XML localName="BODY"/>
+        <root-XML localName="p"/>
+        <root-XML localName="P"/>
+        <root-XML localName="script"/>
+        <root-XML localName="SCRIPT"/>
+        <root-XML localName="frameset"/>
+        <root-XML localName="FRAMESET"/>
+        <!-- The magic priority needs to be lower than that of -->
+        <!--  files which contain HTML within them, eg mime emails -->
+        <magic priority="40">
+            <match value="&lt;!DOCTYPE HTML" type="string" offset="0:64"/>
+            <match value="&lt;!doctype html" type="string" offset="0:64"/>
+            <match value="&lt;HEAD" type="string" offset="0:64"/>
+            <match value="&lt;head" type="string" offset="0:64"/>
+            <match value="&lt;TITLE" type="string" offset="0:64"/>
+            <match value="&lt;title" type="string" offset="0:64"/>
+            <!-- note on the offset value here: this can only be as big as
+           MimeTypes#getMinLength(). If you set the offset value to larger
+           than that size, the magic will only be compared to up to
+           MimeTypes#getMinLength() bytes.
+       -->
+            <match value="&lt;html" type="string" offset="0:8192"/>
+            <match value="&lt;HTML" type="string" offset="0:64"/>
+            <match value="&lt;BODY" type="string" offset="0"/>
+            <match value="&lt;body" type="string" offset="0"/>
+            <match value="&lt;DIV" type="string" offset="0"/>
+            <match value="&lt;div" type="string" offset="0"/>
+            <match value="&lt;TITLE" type="string" offset="0"/>
+            <match value="&lt;title" type="string" offset="0"/>
+            <match value="&lt;h1" type="string" offset="0"/>
+            <match value="&lt;H1" type="string" offset="0"/>
+            <match value="&lt;!doctype HTML" type="string" offset="0"/>
+            <match value="&lt;!DOCTYPE html" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.html"/>
+        <glob pattern="*.htm"/>
+    </mime-type>
+
+    <mime-type type="text/parityfec"/>
+
+    <mime-type type="text/plain">
+        <magic priority="20">
+            <match value="This is TeX," type="string" offset="0"/>
+            <match value="This is METAFONT," type="string" offset="0"/>
+            <match value="/*" type="string" offset="0"/>
+            <match value="//" type="string" offset="0"/>
+            <match value=";;" type="string" offset="0"/>
+            <!-- UTF-16BE BOM -->
+            <match value="0xfeff" type="string" offset="0"/>
+            <!-- UTF-16LE BOM -->
+            <match value="0xfffe" type="string" offset="0"/>
+            <!-- UTF-8 BOM -->
+            <match value="0xefbbbf" type="string" offset="0"/>
+        </magic>
+
+        <glob pattern="*.txt"/>
+        <glob pattern="*.text"/>
+        <glob pattern="*.conf"/>
+        <glob pattern="*.cfg"/>
+        <glob pattern="*.def"/>
+        <glob pattern="*.list"/>
+        <glob pattern="*.in"/>
+
+        <!-- TIKA-85: http://www.apache.org/dev/svn-eol-style.txt -->
+        <glob pattern="INSTALL"/>
+        <glob pattern="KEYS"/>
+        <glob pattern="Makefile"/>
+        <glob pattern="README"/>
+        <glob pattern="abs-linkmap"/>
+        <glob pattern="abs-menulinks"/>
+        <glob pattern="*.aart"/>
+        <glob pattern="*.ac"/>
+        <glob pattern="*.am"/>
+        <glob pattern="*.classpath"/>
+        <glob pattern="*.cmd"/>
+        <glob pattern="*.config"/>
+        <glob pattern="*.cwiki"/>
+        <glob pattern="*.data"/>
+        <glob pattern="*.dcl"/>
+        <glob pattern="*.egrm"/>
+        <glob pattern="*.ent"/>
+        <glob pattern="*.ft"/>
+        <glob pattern="*.fn"/>
+        <glob pattern="*.fv"/>
+        <glob pattern="*.grm"/>
+        <glob pattern="*.g"/>
+        <glob pattern=".htaccess"/>
+        <glob pattern="*.ihtml"/>
+        <glob pattern="*.jmx"/>
+        <glob pattern="*.junit"/>
+        <glob pattern="*.jx"/>
+        <glob pattern="*.manifest"/>
+        <glob pattern="*.m4"/>
+        <glob pattern="*.mf"/>
+        <glob pattern="*.MF"/>
+        <glob pattern="*.meta"/>
+        <glob pattern="*.n3"/>
+        <glob pattern="*.pen"/>
+        <glob pattern="*.pod"/>
+        <glob pattern="*.pom"/>
+        <glob pattern="*.project"/>
+        <glob pattern="*.properties"/>
+        <glob pattern="*.rng"/>
+        <glob pattern="*.rnx"/>
+        <glob pattern="*.roles"/>
+        <glob pattern="*.tld"/>
+        <glob pattern="*.types"/>
+        <glob pattern="*.vm"/>
+        <glob pattern="*.vsl"/>
+        <glob pattern="*.wsdd"/>
+        <glob pattern="*.xargs"/>
+        <glob pattern="*.xcat"/>
+        <glob pattern="*.xconf"/>
+        <glob pattern="*.xegrm"/>
+        <glob pattern="*.xgrm"/>
+        <glob pattern="*.xlex"/>
+        <glob pattern="*.xlog"/>
+        <glob pattern="*.xmap"/>
+        <glob pattern="*.xroles"/>
+        <glob pattern="*.xsamples"/>
+        <glob pattern="*.xsp"/>
+        <glob pattern="*.xweb"/>
+        <glob pattern="*.xwelcome"/>
+    </mime-type>
+
+    <mime-type type="text/prs.fallenstein.rst"/>
+    <mime-type type="text/prs.lines.tag">
+        <glob pattern="*.dsc"/>
+    </mime-type>
+    <mime-type type="text/red"/>
+    <mime-type type="text/rfc822-headers"/>
+    <mime-type type="text/richtext">
+        <glob pattern="*.rtx"/>
+    </mime-type>
+
+    <mime-type type="text/rtp-enc-aescm128"/>
+    <mime-type type="text/rtx"/>
+    <mime-type type="text/sgml">
+        <glob pattern="*.sgml"/>
+        <glob pattern="*.sgm"/>
+    </mime-type>
+    <mime-type type="text/t140"/>
+    <mime-type type="text/tab-separated-values">
+        <glob pattern="*.tsv"/>
+    </mime-type>
+
+    <mime-type type="text/troff">
+        <_comment>Roff/nroff/troff/groff Unformatted Manual Page (UNIX)</_comment>
+        <alias type="application/x-troff"/>
+        <alias type="application/x-troff-man"/>
+        <alias type="application/x-troff-me"/>
+        <alias type="application/x-troff-ms"/>
+        <magic priority="50">
+            <match value=".\\&quot;" type="string" offset="0"/>
+            <match value="'\\&quot;" type="string" offset="0"/>
+            <match value="'.\\&quot;" type="string" offset="0"/>
+            <match value="\\&quot;" type="string" offset="0"/>
+            <match value="'''" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.t"/>
+        <glob pattern="*.tr"/>
+        <glob pattern="*.roff"/>
+        <glob pattern="*.man"/>
+        <glob pattern="*.me"/>
+        <glob pattern="*.ms"/>
+    </mime-type>
+
+    <mime-type type="text/ulpfec"/>
+    <mime-type type="text/uri-list">
+        <glob pattern="*.uri"/>
+        <glob pattern="*.uris"/>
+        <glob pattern="*.urls"/>
+    </mime-type>
+    <mime-type type="text/vnd.abc"/>
+    <mime-type type="text/vnd.curl">
+        <glob pattern="*.curl"/>
+    </mime-type>
+    <mime-type type="text/vnd.curl.dcurl">
+        <glob pattern="*.dcurl"/>
+    </mime-type>
+    <mime-type type="text/vnd.curl.scurl">
+        <glob pattern="*.scurl"/>
+    </mime-type>
+    <mime-type type="text/vnd.curl.mcurl">
+        <glob pattern="*.mcurl"/>
+    </mime-type>
+    <mime-type type="text/vnd.dmclientscript"/>
+    <mime-type type="text/vnd.esmertec.theme-descriptor"/>
+    <mime-type type="text/vnd.fly">
+        <glob pattern="*.fly"/>
+    </mime-type>
+    <mime-type type="text/vnd.fmi.flexstor">
+        <glob pattern="*.flx"/>
+    </mime-type>
+    <mime-type type="text/vnd.graphviz">
+        <glob pattern="*.gv"/>
+    </mime-type>
+    <mime-type type="text/vnd.in3d.3dml">
+        <glob pattern="*.3dml"/>
+    </mime-type>
+    <mime-type type="text/vnd.in3d.spot">
+        <glob pattern="*.spot"/>
+    </mime-type>
+    <mime-type type="text/vnd.iptc.anpa">
+        <acronym>ANPA</acronym>
+        <_comment>American Newspaper Publishers Association Wire Feeds</_comment>
+        <glob pattern="*.anpa"/>
+        <magic priority="50">
+            <match value="\x16\x16\x01" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+    <mime-type type="text/vnd.iptc.newsml"/>
+    <mime-type type="text/vnd.iptc.nitf"/>
+    <mime-type type="text/vnd.latex-z"/>
+    <mime-type type="text/vnd.motorola.reflex"/>
+    <mime-type type="text/vnd.ms-mediapackage"/>
+    <mime-type type="text/vnd.net2phone.commcenter.command"/>
+    <mime-type type="text/vnd.si.uricatalogue"/>
+    <mime-type type="text/vnd.sun.j2me.app-descriptor">
+        <glob pattern="*.jad"/>
+    </mime-type>
+    <mime-type type="text/vnd.trolltech.linguist"/>
+    <mime-type type="text/vnd.wap.si"/>
+    <mime-type type="text/vnd.wap.sl"/>
+    <mime-type type="text/vnd.wap.wml">
+        <glob pattern="*.wml"/>
+    </mime-type>
+
+    <mime-type type="text/vnd.wap.wmlscript">
+        <_comment>WML Script</_comment>
+        <glob pattern="*.wmls"/>
+    </mime-type>
+
+    <mime-type type="text/x-awk">
+        <_comment>AWK script</_comment>
+        <magic priority="50">
+            <match value="#!/bin/gawk" type="string" offset="0"/>
+            <match value="#! /bin/gawk" type="string" offset="0"/>
+            <match value="#!/usr/bin/gawk" type="string" offset="0"/>
+            <match value="#! /usr/bin/gawk" type="string" offset="0"/>
+            <match value="#!/usr/local/bin/gawk" type="string" offset="0"/>
+            <match value="#! /usr/local/bin/gawk" type="string" offset="0"/>
+            <match value="#!/bin/awk" type="string" offset="0"/>
+            <match value="#! /bin/awk" type="string" offset="0"/>
+            <match value="#!/usr/bin/awk" type="string" offset="0"/>
+            <match value="#! /usr/bin/awk" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.awk"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-basic">
+        <_comment>Basic source code</_comment>
+        <glob pattern="*.bas"/>
+        <glob pattern="*.Bas"/>
+        <glob pattern="*.BAS"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-c++hdr">
+        <_comment>C++ source code header</_comment>
+        <glob pattern="*.hpp"/>
+        <glob pattern="*.hxx"/>
+        <glob pattern="*.hh"/>
+        <glob pattern="*.H"/>
+        <glob pattern="*.h++"/>
+        <glob pattern="*.hp"/>
+        <glob pattern="*.HPP"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-c++src">
+        <_comment>C++ source code</_comment>
+        <glob pattern="*.cpp"/>
+        <glob pattern="*.cxx"/>
+        <glob pattern="*.cc"/>
+        <glob pattern="*.C"/>
+        <glob pattern="*.c++"/>
+        <glob pattern="*.CPP"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-cgi">
+        <_comment>CGI script</_comment>
+        <glob pattern="*.cgi"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-chdr">
+        <_comment>C source code header</_comment>
+        <glob pattern="*.h"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-clojure">
+        <_comment>Clojure source code</_comment>
+        <glob pattern="*.clj"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-coffeescript">
+        <_comment>CoffeeScript source code</_comment>
+        <glob pattern="*.coffee"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-csrc">
+        <alias type="text/x-c"/>
+        <_comment>C source code</_comment>
+        <glob pattern="*.c"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-csharp">
+        <_comment>C# source code</_comment>
+        <glob pattern="*.cs"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-cobol">
+        <_comment>COBOL source code</_comment>
+        <glob pattern="*.cbl"/>
+        <glob pattern="*.Cbl"/>
+        <glob pattern="*.CBL"/>
+        <glob pattern="*.cob"/>
+        <glob pattern="*.Cob"/>
+        <glob pattern="*.COB"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-coldfusion">
+        <_comment>ColdFusion source code</_comment>
+        <glob pattern="*.cfm"/>
+        <glob pattern="*.cfml"/>
+        <glob pattern="*.cfc"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-common-lisp">
+        <_comment>Common Lisp source code</_comment>
+        <glob pattern="*.cl"/>
+        <glob pattern="*.jl"/>
+        <glob pattern="*.lisp"/>
+        <glob pattern="*.lsp"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-diff">
+        <magic priority="50">
+            <match value="diff\ " type="string" offset="0"/>
+            <match value="***\ " type="string" offset="0"/>
+            <match value="Only\ in\ " type="string" offset="0"/>
+            <match value="Common\ subdirectories:\ " type="string" offset="0"/>
+            <match value="Index:" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.diff"/>
+        <glob pattern="*.patch"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-eiffel">
+        <_comment>Eiffel source code</_comment>
+        <glob pattern="*.e"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-emacs-lisp">
+        <_comment>Emacs Lisp source code</_comment>
+        <glob pattern="*.el"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-erlang">
+        <_comment>Erlang source code</_comment>
+        <glob pattern="*.erl"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-expect">
+        <_comment>Expect Script</_comment>
+        <glob pattern="*.exp"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-forth">
+        <_comment>Forth source code</_comment>
+        <glob pattern="*.4th"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-fortran">
+        <_comment>Fortran source code</_comment>
+        <glob pattern="*.f"/>
+        <glob pattern="*.F"/>
+        <glob pattern="*.for"/>
+        <glob pattern="*.f77"/>
+        <glob pattern="*.f90"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-go">
+        <_comment>Go source code</_comment>
+        <glob pattern="*.go"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-groovy">
+        <_comment>Groovy source code</_comment>
+        <glob pattern="*.groovy"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-haskell">
+        <_comment>Haskell source code</_comment>
+        <glob pattern="*.hs"/>
+        <glob pattern="*.lhs"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-idl">
+        <_comment>Inteface Definition Language</_comment>
+        <glob pattern="*.idl"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-ini">
+        <_comment>Configuration file</_comment>
+        <glob pattern="*.ini"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-java-source">
+        <_comment>Java source code</_comment>
+        <alias type="text/x-java" />
+        <glob pattern="*.java"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-jsp">
+        <_comment>Java Server Page</_comment>
+        <alias type="application/x-httpd-jsp"/>
+        <sub-class-of type="text/plain"/>
+        <magic priority="50">
+            <match value="&lt;%@" type="string" offset="0"/>
+            <match value="&lt;%--" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.jsp"/>
+    </mime-type>
+
+    <mime-type type="text/x-less">
+        <_comment>LESS source code</_comment>
+        <glob pattern="*.less"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-lex">
+        <_comment>Lex/Flex source code</_comment>
+        <glob pattern="*.l"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-log">
+        <_comment>application log</_comment>
+        <glob pattern="*.log"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-lua">
+        <_comment>Lua source code</_comment>
+        <glob pattern="*.lua"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-ml">
+        <_comment>ML source code</_comment>
+        <glob pattern="*.ml"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-matlab">
+        <_comment>Matlab source code</_comment>
+        <magic priority="50">
+            <match value="function [" type="string" offset="0"/>
+        </magic>
+        <!-- <glob pattern="*.m"/> - conflicts with text/x-objcsrc -->
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="application/x-matlab-data">
+        <comment>MATLAB data file</comment>
+        <alias type="application/matlab-mat"/>
+        <magic priority="50">
+            <match value="MATLAB" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.mat"/>
+    </mime-type>
+
+    <mime-type type="text/x-modula">
+        <_comment>Modula source code</_comment>
+        <glob pattern="*.m3"/>
+        <glob pattern="*.i3"/>
+        <glob pattern="*.mg"/>
+        <glob pattern="*.ig"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-objcsrc">
+        <_comment>Objective-C source code</_comment>
+        <glob pattern="*.m"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-ocaml">
+        <_comment>Ocaml source code</_comment>
+        <glob pattern="*.ocaml"/>
+        <glob pattern="*.mli"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-pascal">
+        <_comment>Pascal source code</_comment>
+        <glob pattern="*.p"/>
+        <glob pattern="*.pp"/>
+        <glob pattern="*.pas"/>
+        <glob pattern="*.PAS"/>
+        <glob pattern="*.dpr"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-perl">
+        <_comment>Perl script</_comment>
+        <magic priority="50">
+            <match value="eval \&quot;exec /usr/local/bin/perl" type="string" offset="0"/>
+            <match value="#!/bin/perl" type="string" offset="0"/>
+            <match value="#!/bin/env perl" type="string" offset="0"/>
+            <match value="#!/usr/bin/perl" type="string" offset="0"/>
+            <match value="#!/usr/local/bin/perl" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.pl"/>
+        <glob pattern="*.pm"/>
+        <glob pattern="*.al"/>
+        <glob pattern="*.perl"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-php">
+        <_comment>PHP script</_comment>
+        <magic priority="50">
+            <match value="&lt;?php" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.php"/>
+        <glob pattern="*.php3"/>
+        <glob pattern="*.php4"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-prolog">
+        <_comment>Prolog source code</_comment>
+        <glob pattern="*.pro"/>
+        <!-- <glob pattern="*.pl"/> - conflicts with text/x-perl -->
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-python">
+        <_comment>Python script</_comment>
+        <magic priority="50">
+            <match value="#!/bin/python" type="string" offset="0"/>
+            <match value="#! /bin/python" type="string" offset="0"/>
+            <match value="eval &quot;exec /bin/python" type="string" offset="0"/>
+            <match value="#!/usr/bin/python" type="string" offset="0"/>
+            <match value="#! /usr/bin/python" type="string" offset="0"/>
+            <match value="eval &quot;exec /usr/bin/python" type="string" offset="0"/>
+            <match value="#!/usr/local/bin/python" type="string" offset="0"/>
+            <match value="#! /usr/local/bin/python" type="string" offset="0"/>
+            <match value="eval &quot;exec /usr/local/bin/python" type="string" offset="0"/>
+            <match value="/bin/env python" type="string" offset="1"/>
+        </magic>
+        <glob pattern="*.py"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-rst">
+        <_comment>reStructuredText source code</_comment>
+        <glob pattern="*.rest"/>
+        <glob pattern="*.rst"/>
+        <glob pattern="*.restx"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-rexx">
+        <_comment>Rexx source code</_comment>
+        <glob pattern="*.rexx"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-ruby">
+        <_comment>Ruby source code</_comment>
+        <glob pattern="*.rb"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-scala">
+        <_comment>Scala source code</_comment>
+        <glob pattern="*.scala"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-scheme">
+        <_comment>Scheme source code</_comment>
+        <glob pattern="*.scm"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-sed">
+        <_comment>Sed code</_comment>
+        <glob pattern="*.sed"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-sql">
+        <_comment>SQL code</_comment>
+        <glob pattern="*.sql"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-setext">
+        <glob pattern="*.etx"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-stsrc">
+        <_comment>Smalltalk source code</_comment>
+        <glob pattern="*.st"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-tcl">
+        <alias type="application/x-tcl"/>
+        <_comment>Tcl script</_comment>
+        <glob pattern="*.itk"/>
+        <glob pattern="*.tcl"/>
+        <glob pattern="*.tk"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-uuencode">
+        <glob pattern="*.uu"/>
+    </mime-type>
+
+    <mime-type type="text/x-vbasic">
+        <_comment>Visual basic source code</_comment>
+        <glob pattern="*.cls"/>
+        <glob pattern="*.Cls"/>
+        <glob pattern="*.CLS"/>
+        <glob pattern="*.frm"/>
+        <glob pattern="*.Frm"/>
+        <glob pattern="*.FRM"/>
+        <sub-class-of type="text/x-basic"/>
+    </mime-type>
+
+    <mime-type type="text/x-vbdotnet">
+        <_comment>VB.NET source code</_comment>
+        <glob pattern="*.vb"/>
+        <sub-class-of type="text/x-vbasic"/>
+    </mime-type>
+
+    <mime-type type="text/x-vbscript">
+        <_comment>VBScript source code</_comment>
+        <glob pattern="*.vbs"/>
+        <sub-class-of type="text/x-vbasic"/>
+    </mime-type>
+
+    <mime-type type="text/x-vcalendar">
+        <glob pattern="*.vcs"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-vcard">
+        <glob pattern="*.vcf"/>
+        <sub-class-of type="text/plain"/>
+        <magic priority="50">
+            <match value="BEGIN:VCARD" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="text/x-verilog">
+        <_comment>Verilog source code</_comment>
+        <glob pattern="*.v"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-vhdl">
+        <_comment>VHDL source code</_comment>
+        <glob pattern="*.vhd"/>
+        <glob pattern="*.vhdl"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-web-markdown">
+        <_comment>Markdown source code</_comment>
+        <glob pattern="*.md"/>
+        <glob pattern="*.mdtext"/>
+        <glob pattern="*.mkd"/>
+        <glob pattern="*.markdown"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-yacc">
+        <_comment>Yacc/Bison source code</_comment>
+        <glob pattern="*.y"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-yaml">
+        <_comment>YAML source code</_comment>
+        <glob pattern="*.yaml"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="video/3gpp">
+        <magic priority="60">
+            <match value="ftyp3ge6" type="string" offset="4"/>
+            <match value="ftyp3ge7" type="string" offset="4"/>
+            <match value="ftyp3gg6" type="string" offset="4"/>
+            <match value="ftyp3gp1" type="string" offset="4"/>
+            <match value="ftyp3gp2" type="string" offset="4"/>
+            <match value="ftyp3gp3" type="string" offset="4"/>
+            <match value="ftyp3gp4" type="string" offset="4"/>
+            <match value="ftyp3gp5" type="string" offset="4"/>
+            <match value="ftyp3gp6" type="string" offset="4"/>
+            <match value="ftyp3gs7" type="string" offset="4"/>
+        </magic>
+        <glob pattern="*.3gp"/>
+    </mime-type>
+    <mime-type type="video/3gpp-tt"/>
+    <mime-type type="video/3gpp2">
+        <magic priority="60">
+            <match value="ftyp3g2a" type="string" offset="4"/>
+            <match value="ftyp3g2b" type="string" offset="4"/>
+            <match value="ftyp3g2c" type="string" offset="4"/>
+        </magic>
+        <glob pattern="*.3g2"/>
+    </mime-type>
+    <mime-type type="video/bmpeg"/>
+    <mime-type type="video/bt656"/>
+    <mime-type type="video/celb"/>
+    <mime-type type="video/dv"/>
+    <mime-type type="video/example"/>
+    <mime-type type="video/h261">
+        <glob pattern="*.h261"/>
+    </mime-type>
+    <mime-type type="video/h263">
+        <glob pattern="*.h263"/>
+    </mime-type>
+    <mime-type type="video/h263-1998"/>
+    <mime-type type="video/h263-2000"/>
+    <mime-type type="video/h264">
+        <glob pattern="*.h264"/>
+    </mime-type>
+    <mime-type type="video/jpeg">
+        <glob pattern="*.jpgv"/>
+    </mime-type>
+    <mime-type type="video/jpeg2000"/>
+
+    <mime-type type="video/mj2">
+        <sub-class-of type="image/x-jp2-container" />
+        <acronym>MJ2</acronym>
+        <_comment>JPEG 2000 Part 3 (Motion JPEG, MJ2)</_comment>
+        <magic priority="50">
+            <match value="0x0000000C6A5020200D0A870A" type="string" offset="0">
+                <match value="0x6d6a7032" type="string" offset="20"/>
+            </match>
+        </magic>
+        <glob pattern="*.mj2"/>
+        <glob pattern="*.mjp2"/>
+    </mime-type>
+
+    <mime-type type="video/mp1s"/>
+    <mime-type type="video/mp2p"/>
+    <mime-type type="video/mp2t"/>
+
+    <mime-type type="video/mp4">
+        <magic priority="60">
+            <match value="ftypmp41" type="string" offset="4"/>
+            <match value="ftypmp42" type="string" offset="4"/>
+        </magic>
+        <glob pattern="*.mp4"/>
+        <glob pattern="*.mp4v"/>
+        <glob pattern="*.mpg4"/>
+        <sub-class-of type="video/quicktime" />
+    </mime-type>
+    <mime-type type="video/mp4v-es"/>
+
+    <mime-type type="video/mpeg">
+        <_comment>MPEG Movie Clip</_comment>
+        <magic priority="50">
+            <match value="\000\000\001\263" type="string" offset="0"/>
+            <match value="\000\000\001\272" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.mpeg"/>
+        <glob pattern="*.mpg"/>
+        <glob pattern="*.mpe"/>
+        <glob pattern="*.m1v"/>
+        <glob pattern="*.m2v"/>
+    </mime-type>
+
+    <mime-type type="video/mpeg4-generic"/>
+    <mime-type type="video/mpv"/>
+    <mime-type type="video/nv"/>
+
+    <mime-type type="video/ogg">
+        <_comment>Ogg Vorbis Video</_comment>
+        <glob pattern="*.ogv"/>
+        <sub-class-of type="application/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/daala">
+        <_comment>Ogg Daala Video</_comment>
+        <alias type="video/x-daala"/>
+        <magic priority="60">
+            <!-- Assumes Video stream comes before Audio, may not always -->
+            <match value="OggS\000.......................\x80daala" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/theora">
+        <_comment>Ogg Theora Video</_comment>
+        <alias type="video/x-theora"/>
+        <magic priority="60">
+            <!-- Assumes Video stream comes before Audio, may not always -->
+            <match value="OggS\000.......................\x80theora" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/x-dirac">
+        <_comment>Ogg Packaged Dirac Video</_comment>
+        <magic priority="60">
+            <match value="OggS\000.......................BBCD" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <glob pattern="*.drc"/>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/x-ogm">
+        <_comment>Ogg Packaged OGM Video</_comment>
+        <magic priority="60">
+            <!-- Assumes Video stream comes before Audio, may not always -->
+            <match value="OggS\000.......................video" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <glob pattern="*.ogm"/>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/x-ogguvs">
+        <_comment>Ogg Packaged Raw UVS Video</_comment>
+        <alias type="video/x-ogg-uvs"/>
+        <magic priority="60">
+            <match value="OggS\000.......................UVS " type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/x-oggyuv">
+        <_comment>Ogg Packaged Raw YUV Video</_comment>
+        <alias type="video/x-ogg-yuv"/>
+        <magic priority="60">
+            <match value="OggS\000.......................\001YUV" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/x-oggrgb">
+        <_comment>Ogg Packaged Raw RGB Video</_comment>
+        <alias type="video/x-ogg-rgb"/>
+        <magic priority="60">
+            <match value="OggS\000.......................\001RGB" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/parityfec"/>
+    <mime-type type="video/pointer"/>
+
+    <mime-type type="video/quicktime">
+        <magic priority="50">
+            <match value="moov" type="string" offset="4"/>
+            <match value="mdat" type="string" offset="4"/>
+            <!-- General match, specific ftypXXX ones present for subtypes -->
+            <match value="ftyp" type="string" offset="4"/>
+        </magic>
+        <glob pattern="*.qt"/>
+        <glob pattern="*.mov"/>
+    </mime-type>
+
+    <mime-type type="video/raw"/>
+    <mime-type type="video/rtp-enc-aescm128"/>
+    <mime-type type="video/rtx"/>
+    <mime-type type="video/smpte292m"/>
+    <mime-type type="video/ulpfec"/>
+    <mime-type type="video/vc1"/>
+    <mime-type type="video/vnd.cctv"/>
+    <mime-type type="video/vnd.dlna.mpeg-tts"/>
+    <mime-type type="video/vnd.fvt">
+        <glob pattern="*.fvt"/>
+    </mime-type>
+    <mime-type type="video/vnd.hns.video"/>
+    <mime-type type="video/vnd.iptvforum.1dparityfec-1010"/>
+    <mime-type type="video/vnd.iptvforum.1dparityfec-2005"/>
+    <mime-type type="video/vnd.iptvforum.2dparityfec-1010"/>
+    <mime-type type="video/vnd.iptvforum.2dparityfec-2005"/>
+    <mime-type type="video/vnd.iptvforum.ttsavc"/>
+    <mime-type type="video/vnd.iptvforum.ttsmpeg2"/>
+    <mime-type type="video/vnd.motorola.video"/>
+    <mime-type type="video/vnd.motorola.videop"/>
+    <mime-type type="video/vnd.mpegurl">
+        <glob pattern="*.mxu"/>
+        <glob pattern="*.m4u"/>
+    </mime-type>
+    <mime-type type="video/vnd.ms-playready.media.pyv">
+        <glob pattern="*.pyv"/>
+    </mime-type>
+    <mime-type type="video/vnd.nokia.interleaved-multimedia"/>
+    <mime-type type="video/vnd.nokia.videovoip"/>
+    <mime-type type="video/vnd.objectvideo"/>
+    <mime-type type="video/vnd.sealed.mpeg1"/>
+    <mime-type type="video/vnd.sealed.mpeg4"/>
+    <mime-type type="video/vnd.sealed.swf"/>
+    <mime-type type="video/vnd.sealedmedia.softseal.mov"/>
+    <mime-type type="video/vnd.vivo">
+        <glob pattern="*.viv"/>
+    </mime-type>
+    <mime-type type="video/x-f4v">
+        <glob pattern="*.f4v"/>
+    </mime-type>
+
+    <mime-type type="video/x-flc">
+        <glob pattern="*.flc"/>
+    </mime-type>
+
+    <mime-type type="video/x-fli">
+        <glob pattern="*.fli"/>
+    </mime-type>
+
+    <mime-type type="video/x-flv">
+        <magic priority="50">
+            <match value="FLV" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.flv"/>
+    </mime-type>
+
+    <mime-type type="video/x-jng">
+        <magic priority="50">
+            <match value="\x8bJNG" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.jng"/>
+    </mime-type>
+
+    <mime-type type="video/x-m4v">
+        <magic priority="60">
+            <match value="ftypM4V " type="string" offset="4"/>
+            <match value="ftypM4VH" type="string" offset="4"/>
+            <match value="ftypM4VP" type="string" offset="4"/>
+        </magic>
+        <glob pattern="*.m4v"/>
+        <sub-class-of type="video/mp4" />
+    </mime-type>
+
+    <mime-type type="video/x-mng">
+        <magic priority="50">
+            <match value="\x8aMNG" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.mng"/>
+    </mime-type>
+
+    <mime-type type="video/x-ms-asf">
+        <glob pattern="*.asf"/>
+        <glob pattern="*.asx"/>
+        <magic>
+            <match value="0x3026b275" type="big32" offset="0" />
+        </magic>
+    </mime-type>
+    <mime-type type="video/x-ms-wm">
+        <glob pattern="*.wm"/>
+    </mime-type>
+    <mime-type type="video/x-ms-wmv">
+        <sub-class-of type="video/x-ms-asf" />
+        <glob pattern="*.wmv"/>
+        <magic priority="60">
+            <match value="Windows Media Video" type="unicodeLE" offset="0:8192" />
+            <match value="VC-1 Advanced Profile" type="unicodeLE" offset="0:8192" />
+        </magic>
+    </mime-type>
+    <mime-type type="video/x-ms-wmx">
+        <glob pattern="*.wmx"/>
+    </mime-type>
+    <mime-type type="video/x-ms-wvx">
+        <glob pattern="*.wvx"/>
+    </mime-type>
+
+    <mime-type type="video/x-msvideo">
+        <_comment>Audio Video Interleave File</_comment>
+        <alias type="video/avi"/>
+        <alias type="video/msvideo"/>
+        <magic priority="50">
+            <match value="RIFF....AVI " type="string" offset="0"
+                   mask="0xFFFFFFFF00000000FFFFFFFF"/>
+            <match offset="8" type="string" value="\x41\x56\x49\x20"/>
+        </magic>
+        <glob pattern="*.avi"/>
+    </mime-type>
+
+    <mime-type type="video/x-sgi-movie">
+        <magic priority="50">
+            <match value="MOVI" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.movie"/>
+    </mime-type>
+
+    <mime-type type="application/x-matroska">
+        <_comment>Matroska Media Container</_comment>
+        <!-- Common magic across all Matroska varients -->
+        <!-- For full detection, we need a custom Detector, see TIKA-1180 -->
+        <magic priority="40">
+            <match value="0x1A45DFA3" type="string" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="video/x-matroska">
+        <sub-class-of type="application/x-matroska"/>
+        <glob pattern="*.mkv" />
+        <!-- Note: The magic value below isn't present in all MKV files -->
+        <magic priority="50">
+            <match value="0x1A45DFA3934282886D6174726F736B61" type="string" offset="0" />
+        </magic>
+    </mime-type>
+    <mime-type type="audio/x-matroska">
+        <sub-class-of type="application/x-matroska"/>
+        <glob pattern="*.mka" />
+    </mime-type>
+
+    <mime-type type="video/webm">
+        <sub-class-of type="application/x-matroska"/>
+        <glob pattern="*.webm" />
+    </mime-type>
+
+    <mime-type type="x-conference/x-cooltalk">
+        <_comment>Cooltalk Audio</_comment>
+        <glob pattern="*.ice"/>
+    </mime-type>
+
+    <mime-type type="application/x-fictionbook+xml">
+        <_comment>FictionBook document</_comment>
+        <sub-class-of type="application/xml"/>
+        <root-XML namespaceURI="http://www.gribuser.ru/xml/fictionbook/2.0" localName="FictionBook"/>
+        <glob pattern="*.fb2"/>
+    </mime-type>
+
+    <mime-type type="text/x-asciidoc">
+        <_comment>Asciidoc source code</_comment>
+        <glob pattern="*.asciidoc"/>
+        <glob pattern="*.adoc"/>
+        <glob pattern="*.ad"/>
+        <glob pattern="*.ad.txt"/>
+        <glob pattern="*.adoc.txt"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-d">
+        <_comment>D source code</_comment>
+        <glob pattern="*.d"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-haml">
+        <_comment>HAML source code</_comment>
+        <glob pattern="*.haml"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-haxe">
+        <_comment>Haxe source code</_comment>
+        <glob pattern="*.hx"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-rsrc">
+        <_comment>R source code</_comment>
+        <glob pattern="*.r"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="application/xquery">
+        <_comment>XQuery source code</_comment>
+        <glob pattern="*.xq"/>
+        <glob pattern="*.xquery"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+</mime-info>
\ No newline at end of file
diff --git a/0.8.1-rc1/metadata/src/site/resources/images/cas-metadata.jpg b/0.8.1-rc1/metadata/src/site/resources/images/cas-metadata.jpg
new file mode 100644
index 0000000..422c44a
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/site/resources/images/cas-metadata.jpg
Binary files differ
diff --git a/0.8.1-rc1/metadata/src/site/resources/images/cas-metadata.psd b/0.8.1-rc1/metadata/src/site/resources/images/cas-metadata.psd
new file mode 100644
index 0000000..299b164
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/site/resources/images/cas-metadata.psd
Binary files differ
diff --git a/0.8.1-rc1/metadata/src/site/resources/images/metadata.jpg b/0.8.1-rc1/metadata/src/site/resources/images/metadata.jpg
new file mode 100644
index 0000000..4310cf5
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/site/resources/images/metadata.jpg
Binary files differ
diff --git a/0.8.1-rc1/metadata/src/site/site.xml b/0.8.1-rc1/metadata/src/site/site.xml
new file mode 100644
index 0000000..7dd01f6
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/site/site.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<project name="cas-metadata">
+  <body>
+    <links>
+      <item name="OODT" href="../oodt-site/"/>
+    </links>
+
+    <menu ref="reports" inherit="bottom"/>
+    <menu name="Software Documentation">
+      <item name="Basic User's Guide" href="user/basic.html"/>
+      <item name="Advanced User's Guide" href="user/advanced.html"/>
+    </menu>
+  </body>
+</project>
\ No newline at end of file
diff --git a/0.8.1-rc1/metadata/src/site/xdoc/user/advanced.xml b/0.8.1-rc1/metadata/src/site/xdoc/user/advanced.xml
new file mode 100644
index 0000000..5ceeb2d
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/site/xdoc/user/advanced.xml
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+  <properties>
+    <title>CAS-Metadata Advanced User Guide</title>
+    <author email="woollard@jpl.nasa.gov">David Woollard</author>
+  </properties>
+
+  <body>
+    <section name="Introduction">
+    
+    <p>The purpose of this guide is to instruct the user in some advanced concepts 
+    within the CAS-Metadata project, including the ramifications of metadata
+    extraction with regard to repository search, type, checking, etc, and the use 
+    of mime-type detection. For basic topics, including the basics of metadata, how 
+    to write metadata extractors, and explanations of existing metadata extractors, 
+    see our <a href="../user/basic.html">Basic Guide.</a> In the rest of this guide, 
+    we will cover the following topics:</p>
+
+    <ul>
+      <li><a href="#search">Planning Metadata for Search</a></li>
+      <li><a href="#provenance">Planning Metadata for Provenance</a></li>
+      <li><a href="#mime">MIME-type Detection</a></li>
+    </ul>
+    
+    </section>
+  
+    <a name="search"/>
+    <section name="Planning Metadata for Search">
+    
+    <p>As discussed in the <a href="../user/basic.html">Basic Guide,</a> one of the
+    primary uses of metadata is search. When you consider search, remember that
+    neither the CAS-Metadata container nor the CAS-Filemgr are cognizant over
+    how people will search your data - you are.</p>
+    
+    <p>We recommend developing a data dictionary as a "best practice." The 
+    <a href="http://portal.acm.org/citation.cfm?id=541721">IBM Dictionary of 
+    Computing</a> describes a data dictionary as a "centralized repository of 
+    information about data such as meaning, relationships to other data, origin, 
+    usage, and format." This is a highly-related concept to ontology.</p>
+    
+    <p>The attributes of and relationships between products in your system will
+    not only help you to develop appropriate product types but also the metadata
+    you will need to extract from products to establish both these attributes and
+    relationships.</p> 
+    
+    <p>In the next subsections, we will discuss specific aspects of metadata 
+    extraction that impact downstream search.</p>
+    
+    <subsection name="Missing Elements">
+    
+    <p>Because metadata extraction is a separate activity from extraction (as 
+    discussed in the <a href="../user/basic.html">Basic Guide</a>), it is possible
+    that there is a miss-match between the metadata elements extracted by an 
+    extractor and the metadata elements that the CAS-Filemgr associated with 
+    a product type. CAS-Filemgr, therefore, only ingests the <i>intersection</i>
+    of the metadata extracted from the product and the metadata associated with
+    the product in CAS-Filemgr configuration. This means that missing elements
+    are possible.</p>
+    
+    </subsection>
+    
+    <subsection name="String-based Comparison">
+    <p>Metadata values are stored as strings in CAS-Metadata. While there are a 
+    number of good reasons for this, it is a design point that has a number of 
+    important ramifications for search. Specifically, all metadata elements should
+    be comparable. Of course strings are comparable, but without some forethought, a
+    string-based comparison can act differently than would a type-based comparison.</p>
+    
+    <p>This is where standards come into play. For various types, there are standard
+    string-based representations that ensure comparisons that behave identically to how
+    a type-based comparison would work. There is currently no plan to enforce these 
+    standards (and, depending on the particular type, the application domain, etc., 
+    there might be multiple competing standards - e.g., TAI vs. UTC formatted Time 
+    strings).</p>
+    
+    <p>Some example string representation standards by type:</p>
+    
+    <p><strong>Date-Time</strong></p>
+    
+    <p>With time, consistency is key. There are multiple formats, such as 
+    <a href="http://tycho.usno.navy.mil/mjd.html">Julian Day Numbers</a>, or UTC. 
+    Additionally, there are different time standards such as 
+    <a href="http://www.w3.org/TR/NOTE-datetime">UTC</a>, local time, and 
+    <a href="http://www.bipm.org/en/scientific/tai/">TAI</a>. One also needs to be 
+    aware of leap second observance and local time conventions such as daylight savings 
+    time, depending on representation and standard selection.</p>
+    
+    <p>Additionally, it is important to remember that inter-product consistency can be 
+    just as important as intra-product consistency because there are many downstream 
+    use cases of the search features of CAS-Filemgr and other CAS components that 
+    involve cross-product comparisons.</p>
+    
+    <p><strong>Integers</strong></p>
+    
+    <p>Integers can be easily represented as comparable strings, but you must remember
+    to pad correctly. The string "1" is greater than "01234", but "0001" is less than 
+    "01234."</p>
+    
+    <p>Like Date-Time, appropriate numerical representation is the responsibility
+    of the metadata extractor, though we have built some additionally support for 
+    representational transformations during the ingest process of the CAS-Filemgr.</p>
+        
+    <p>More on Padding..</p>    
+        
+    <p><strong>Floating Point Numbers</strong></p>    
+    
+    <p>The most prevalent of Floating point representations is 
+    <a href="http://ieeexplore.ieee.org/servlet/opac?punumber=4610933">IEEE 754-2008.</a>
+    This is a convenient representation because, amongst other reasons, it is the 
+    representation that Java uses so if you use Java to develop an extractor, you can 
+    use the <code>floatToIntBits(float value)</code> method of the <code>Float</code> 
+    class. Remember that, like Integers, you will need padding.</p>  
+    
+    <p><strong>Blobs, URLs, and Character Sets</strong></p>    
+    
+    <p>Remember that text encoding is important. Depending on the catalog extension 
+    point used by the CAS-Filemgr, metadata values might not be formatting correctly
+    for storage. For example, if a metadata object containing a blob of text is ingested
+    into a CAS-Filemgr instance that is configured to run with a DataStore extension 
+    backed by an Oracle DBMS, then UTF8 encoding is important.</p>
+        
+        
+    </subsection>
+    </section>
+    
+    <a name="provenance"/>
+    <section name="Planning Metadata for Provenance">
+    <p>Coming Soon...</p>
+    </section>
+    
+    <a name="mime"/>
+    <section name="MIME-type Detection">
+    
+    <p>Coming Soon...</p>
+    
+    </section>
+    <section name="Conclusion">
+      <p>This is intended to a living document discussing advanced topics within the 
+      CAS-Metadata project, though it is not comprehensive. In our 
+      <a href="../user/basic.html">Basic Guide,</a> we cover more topics regarding 
+      basic topics within CAS-Metadata.</p>
+    </section>
+    
+  </body>
+</document>
\ No newline at end of file
diff --git a/0.8.1-rc1/metadata/src/site/xdoc/user/basic.xml b/0.8.1-rc1/metadata/src/site/xdoc/user/basic.xml
new file mode 100644
index 0000000..175076a
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/site/xdoc/user/basic.xml
@@ -0,0 +1,486 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+  <properties>
+    <title>CAS-Metadata Basic User Guide</title>
+    <author email="woollard@jpl.nasa.gov">David Woollard</author>
+  </properties>
+
+  <body>
+    <section name="Introduction">
+    
+    <p>The purpose of this guide is to instruct the user in the basic concepts 
+    behind the CAS-Metadata project, including the basics of metadata, how to write 
+    metadata extractors, and explanations of existing metadata extractors. In 
+    addition to this guide, some of these concepts are also covered in our
+    CAS-File Manager <a href="../../filemgr/user/">User Guide</a>
+    and in our CAS-Curator <a href="../../curator/user/basic.html">
+    Basic User Guide</a>. For advanced topics, including extracting techniques to allow
+    for type-based matching, see our <a href="../user/advanced.html">Advanced Guide.</a>
+    In the rest of this guide, we will cover the following topics:</p>
+
+    <ul>
+      <li><a href="#basics">Metadata Basics</a></li>
+      <li><a href="#extractors">Metadata Extractors</a></li>
+      <li><a href="#existing">Existing Implementations</a></li>
+      <li><a href="#filemgr">Relationship to CAS-Filemgr</a></li>
+    </ul>
+    </section>
+  
+    <a name="basics"/>
+    <section name="Metadata Basics">
+    
+    <p>Metadata is <i>data about data</i>. Simply put, metadata is information about data
+    that aids the user in finding what they are looking for and clarifying what they are 
+    looking at. There are many examples of metadata standards, including 
+    <a href="http://dublincore.org/">Dublin Core</a> and ISO 
+    <a href="http://metadata-stds.org/">Standards.</a></p>
+    
+    <p>Examples of metadata include filename, URL, data producer, start and stop datetime 
+    for temporal files, bounding polygons for geo-referenced data, etc. In the CAS-Metadata
+    project, and in all of OODT, Metadata Objects are considered a container for 
+    product-related metadata. Interfaces for the <code>Metadata</code> Object are shown 
+    below:</p>
+    
+<source><![CDATA[    
+public class Metadata {
+
+    public Metadata() {...}
+
+    public Metadata(InputStream is) throws Exception {...}
+
+    public void addMetadata(Hashtable metadata) {...}
+
+    public void addMetadata(Hashtable metadata, boolean replace) {...}
+
+    public void replaceMetadata(Hashtable metadata) {...}
+
+    public void addMetadata(String key, String value) {...}
+    
+    public void addMetadata(String key, List values) {...}
+
+    public void replaceMetadata(String key, List values) {...}
+
+    public void replaceMetadata(String key, String value) {...}
+
+    public Object removeMetadata(String key) {...}
+
+    public List getAllMetadata(String key) {...}
+
+    public String getMetadata(String key) {...}
+
+    public Hashtable getHashtable() {...}
+
+    public boolean containsKey(String key) {...}
+
+    public boolean isMultiValued(String key) {...}
+    
+    public boolean equals(Object obj) {....}
+
+    public Document toXML() throws Exception {...}
+
+    private void parse(Document document) throws Exception {...}
+}    
+]]></source>    
+    
+    <p>The CAS-Metadata <code>Metadata</code> object is a key-multivalue container.
+    Users can add metadata elements to the <code>Metadata</code> Object via 
+    InputStream, HashTable Object, key with an array of values, and a simple
+    key and signal value interface. All keys and values are represented as Strings. 
+    See our <a href="../user/advanced.html">Advanced Guide</a> for more information
+    about the ramification of this design decision during type-based metadata search
+    and comparison.</p>  
+    
+    <p>In addition to the accessor and modifier methods that work with simple Strings,
+    the <code>Metadata</code> Object can work with XML Documents. An example of 
+    metadata in the XML format is given below:</p>
+    <!-- FIXME: change namespace URI? -->
+    <source><![CDATA[<cas:metadata xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+  <keyval>
+    <key>ProductType</key>
+    <val>MP3</val>
+  </keyval>
+  <keyval>
+    <key>Filename</key>
+    <val>blue_suede_shoes.mp3</val>
+  </keyval>
+  <keyval>
+    <key>Artist</key>
+    <val>The Beatles</val>
+  </keyval>
+  <keyval>
+    <key>Album</key>
+    <val>Revolver</val>
+  </keyval>
+  <keyval>
+    <key>SongName</key>
+    <val>Blue Suede Shoes</val>
+  </keyval>
+</cas:metadata>]]></source>
+    
+	<p>The above metadata example has been extracted from an MP3 file. There are a
+    number of metadata elements, including the Artist, Album, and SongName, as well 
+    as the product type (in this case, 'MP3'), and the name of the mp3 file. In 
+    addition, metadata elements can be multivalued. In this case, the 
+    <code>&lt;keyval&gt;</code> element can have multiple <code>&lt;val&gt;</code>
+    child elements.</p> 
+    </section>
+    
+    
+    <a name="extractors"/>
+    <section  name="Metadata Extractors">
+    <p>The role of a metadata extractor is extract metadata from one or more product 
+    <i>types</i>. In order to extract metadata, the extractor must understand the product 
+    type format, parse the product, and return metadata to be associated with the
+    product. CAS-Curator, for example, uses metadata extractors to generate metadata for 
+    products in its staging area, both as a preview to the curator, and also during the 
+    course of data ingestion.</p> 
+    
+    
+    <subsection name="Java API">
+    
+    <p>The CAS-Metadata project contains an interface class, 
+    <code>org.apache.oodt.cas.metadata.MetExtractor</code>. This API consists of
+    two primary methods (with multiple method signatures each). This API can be seen 
+    below:</p>
+    
+<source><![CDATA[public interface MetExtractor {
+
+    public Metadata extractMetadata(File f) 
+            throws MetExtractionException;
+
+    public Metadata extractMetadata(String filePath)
+            throws MetExtractionException;
+
+    public Metadata extractMetadata(URL fileUrl) 
+            throws MetExtractionException;
+
+    public Metadata extractMetadata(File f, File 
+            configFile) throws MetExtractionException;
+
+    public Metadata extractMetadata(File f, String 
+            configFilePath) throws MetExtractionException;
+
+    public Metadata extractMetadata(File f, 
+            MetExtractorConfig config) 
+            throws MetExtractionException;
+
+    public Metadata extractMetadata(URL fileUrl, 
+            MetExtractorConfig config) 
+            throws MetExtractionException;
+            
+    public void setConfigFile(File f) 
+            throws MetExtractionException;
+
+    public void setConfigFile(String filePath) 
+            throws MetExtractionException;
+
+    public void setConfigFile(MetExtractorConfig config);
+}]]></source>
+    
+    <p>In order to implement a new extractor, a developer may implement the
+    <code>MetExtractor</code> interface, or develop a metadata extractor 
+    that adheres to this interface in the development language of choice.</p>
+    
+    </subsection>
+    </section>
+    
+    <a name="existing"/>
+    <section name="Existing Implementations">
+      
+    <p>The CAS-Metadata project contains a number of existing metadata 
+    extractor implementations that the develop can directly leverage.</p>  
+    
+    <subsection name="External Metadata Extractor">
+    
+    <p>There are many situations in which developers are interested in using
+    a metadata extractor that is not written in Java. Perhaps there is an 
+    existing extractor written in a different programming language the source 
+    of which you do not have access, or perhaps there are functional or 
+    non-functional requirements that make a different language more 
+    appropriate.</p>
+      
+    <p>We have developed the <code>ExternMetExtractor</code> as part of the
+    CAS Metadata project to address this issue. The <code>ExternMetExtractor</code> 
+    uses a configuration file to specify the extractor working directory, the path 
+    to the executable, and any commandline arguments. This configuration file
+    is specified below:</p>  
+       
+<source><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<cas:externextractor xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+  <exec workingDir="">
+    <extractorBinPath envReplace="true">[PWD]/extractor</extractorBinPath>
+      <args>
+         <arg isDataFile="true"/>
+         <arg isPath="true">/usr/local/etc/testExtractor.config</arg>
+      </args>
+   </exec>
+</cas:externextractor>]]></source>
+    
+    <p>There are a number of important elements to the external metadata extractor 
+    configuration file, including working directory (the <code>workingDir</code>
+    attribute on the <code>exec</code> tag), the path the the executable extractor
+    (the value of the <code>extractorBinPath</code> tag), and any arguments required
+    by the extractor (values of the <code>args</code> tags).</p>
+    
+    <p>The working directory (the directory in which the metadata file is to be 
+    generated), is assumed to be the directory in which the extractor is run. This 
+    is signaled by a null value.</p>
+    
+    <p>Command-line arguments are delivered to the external extractor in the order 
+    they are listed in the configuration file. In order words,</p>
+
+<source><![CDATA[
+  <args>
+    <arg>arg1</arg>
+    <arg>arg2</arg>
+    <arg>arg3</arg>
+  </args>
+]]></source>    
+    
+     <p>would be passed to the extractor as <code>arg1 arg2 arg3</code>.</p>
+     
+     <p>Additionally, there are a number of specializations of the 
+     <code>arg</code> tag that can be set with tag attributes. Specifically:</p>
+     
+     <ul>
+       <li><code>isDataFile="true"</code> - This attribute passes the full path to 
+       the product from which metadata is to be extracted as the argument.</li>
+       <li><code>isPath="true"</code> - This attribute passes the argument encoded
+       as a properly formed path (no char-set replacement, etc).</li>
+       <li><code>envReplace="true"</code> - This attribute replaces any part of
+       the value of the argument that is inside brackets (<code>[</code> and 
+       <code>]</code>) with the environment variable matching the text inside the 
+       brackets, if such an enviroment variable exists.</li>
+     </ul>
+     
+     <p>For an example of the use of this type of metadata extractor, we our 
+     CAS-Curator <a href="../../curator/user/basic.html">
+     Basic User Guide</a>.</p>
+     
+     </subsection>
+     <subsection name="The Filename Token Metadata Extractor">
+     
+     <p>In many cases, products that are to be ingested are named with metadata
+     that should be extracted from the product name and cataloged upon ingest. For
+     this type of situation, we have developed the 
+     <code>FilenameTokenMetExtractor</code>. This extractor uses a configuration
+     file that specifies, for each metadata element, the index of the start 
+     position in the name for this metadata and its character length.</p>
+     
+     <p>Below is an example configuration file used by the 
+     <code>FilenameTokenMetExtractor</code>. It assumes a product name formatted 
+     as follows:</p>
+     
+     <p><code>MissionName_Date_StartOrbitNumber_StopOrbitNumber.txt</code></p>
+     
+ <source><![CDATA[
+  <input>
+    <group name="SubstringOffsetGroup">
+      <vector name="MissionName">
+        <element>1</element>
+        <element>11</element>      
+      </vector>
+      <vector name="Date">
+        <element>13</element>
+        <element>4</element>
+      </vector>
+      <vector name="StartOrbitNumber">
+        <element>18</element>
+        <element>16</element>
+      </vector>
+      <vector name="StopOrbitNumber">
+        <element>35</element>
+        <element>15</element>
+      </vector>
+   </group>
+    
+    <group name="CommonMetadata">
+        <scalar name="DataVersion">1.0</scalar>
+        <scalar name="CollectionName">Test</scalar>
+        <scalar name="DataProvider">OODT</scalar>
+    </group>
+</input>
+]]></source> 
+     
+     <p>In this configuration, the <code>FilenameTokenMetExtractor</code> will 
+     produce four metadata elements from the product name: <i>MissionName</i>,
+     <i>Date</i>, <i>StartOrbitNumber</i>, and <i>StopOrbitNumber</i>. The first 
+     element of each of these groups is the start index (this assumes 1-indexed
+     strings). The second element is the substring length.</p>
+     
+     <p>Additionally, this configuration specifies that metadata for all products
+     additionally contain three comment metadata elements that are static: 
+     <i>DataVersion</i>, <i>CollectionName</i>, and <i>DataProvider</i>.</p>
+     
+     </subsection>
+
+     <subsection name="Product Type Pattern Metadata Extractor">
+     <p>The <code>ProdTypePatternMetExtractor</code> can also be used to extract
+     metadata from the filename.  Unlike the <code>FilenameTokenMetExtractor</code>,
+     metadata elements do not have to be fixed-offset and fixed-length.  Instead,
+     metadata elements are represented by regular expressions.  These elements are
+     used in filename templates that, when matched, dynamically determine the
+     ProductType of the file.</p>
+
+     <p>Below is an example of a <code>product-type-patterns.xml</code> configuration
+     file used by the <code>ProdTypePatternMetExtractor:</code></p>
+
+<source><![CDATA[
+<config>
+  <!-- <element> MUST be defined before <product-type> so their patterns can be resolved -->
+  <!-- name MUST be an element defined in elements.xml (also only upper and lower case alpha chars) -->
+  <!-- regexp MUST be valid input to java.util.regex.Pattern.compile() -->
+  <element name="ISBN" regexp="[0-9]{10}"/>
+  <element name="Page" regexp="[0-9]*"/>
+
+  <!-- name MUST be a ProductType name defined in product-types.xml -->
+  <!-- metadata elements inside brackets MUST be mapped to the ProductType,
+       as defined in product-type-element-map.xml -->
+  <product-type name="Book" template="book-[ISBN].txt"/>
+  <product-type name="BookPage" template="page-[ISBN]-[Page].txt"/>
+</config>
+]]></source>
+
+     <p>This file defines a regular expression for the "ISBN" metadata element, in this case, a 10-digit number. Also, the
+     "Page" metadata element is defined as a sequence of 0 or more digits.
+     <p/>
+     Next, the file defines a filename pattern for the "Book" product type. The pattern is compiled into a regular
+     expression, substituting the previously defined regexes as capture groups. For example, "book-[ISBN].txt" compiles to
+     "book-([0-9]{10}).txt", and the ISBN met element is assigned to capture group 1. When the filename matches this
+     pattern, 2 metadata assignments occur: (1) the ISBN met element is set to the matched regex group, and (2) the
+     ProductType met element is set to "Book".
+     <p/>
+     Similarly, the second pattern sets ISBN, Page, and ProductType for files matching "page-([0-9]{10})-([0-9]*).txt".
+     <p/>
+     This achieves several things:
+     <ol>
+         <li>assigning met elements based on regular expressions</li>
+         <li>assigning product type based on easy-to-understand pattern with met elements clearly indicated</li>
+         <li>reuse of met element regular expressions</li>
+     </ol>
+     <p>See the <a href="../apidocs/org/apache/oodt/cas/metadata/extractors/ProdTypePatternMetExtractor.html">JavaDoc</a>
+     for more detailed information about using the <code>ProdTypePatternMetExtractor</code></p>
+     </p>
+     </subsection>
+
+     <subsection name="Metadata Reader Extractor">
+     
+     <p>The <code>MetReaderExtractor</code>, part of the OODT CAS-Metadata project,
+     assumes that a metadata file with then nameing convention "&lt;Product Name&gt;.met"
+     is present in the same directory as the product. This extractor further 
+     assumes that the metadata is in the format specified in this document.</p>
+     
+     </subsection>
+     <subsection name="Copy And Rewrite Extractor">
+     
+     <p>The <code>CopyAndRewriteExtractor</code> is a metadata extractor, that,
+     like the <code>MetReaderExtractor</code>, assumes that a metadata file exists
+     for the product from which metadata is to be extracted. This extractor reads 
+     in the original metadata file and replaces particular metadata values in that 
+     metadata file.</p>
+     
+     <p>The <code>CopyAndRewriteExtractor</code> takes in a configuration file that 
+     is a java properties object with the following properties defined:</p>
+
+     <ul>
+       <li>numRewriteFields - The number of fields to rewrite within the original
+       metadata file.</li>
+       <li>rewriteFieldN - The name(s) of the fields to rewrite in the original 
+       metadata file.</li>
+       <li>orig.met.file.path - The original path to the metadata file from which 
+       to draw the original metadata fields.</li>
+	   <li>fieldN.pattern - The string specification that details which fields to
+	   replace and to use in building the new field value.</li>
+	 </ul>
+     
+     <p> An example of the configuration file is given below:</p>
+     
+<source><![CDATA[     
+numRewriteFields=2
+rewriteField1=ProductType
+rewriteField2=FileLocation
+orig.met.file.path=./src/resources/examples/samplemet.xml
+ProductType.pattern=NewProductType[ProductType]
+FileLocation.pattern=/new/loc/[FileLocation]    
+]]></source>
+
+     <p>In ths example configuration, two metadata elements will be rewritten, 
+     <i>ProductType</i> and <i>FileLocation</i>. The original metadata file is 
+     located on at <code>./src/resources/examples/samplemet.xml</code>. The 
+     Product Type will be rewritten as NewProductType&lt;original ProductType 
+     value&gt;. The File location will now be set to 
+     <code>/new/location./src/resources/examples/samplemet.xml</code>.</p>
+     
+     </subsection>
+    </section>
+    
+    <a name="filemgr"/>
+    <section name="Relationship to CAS-Filemgr">
+    
+    <p>The most common use-case of CAS-Metadata is to capture the output of a metadata
+    extractor for use in the CAS-Filemgr's ingestion process.</p>
+    
+    <p><img src="../images/metadata.jpg"/></p>
+    
+    <p>In the above diagram, a metadata object is producted by an extractor. The 
+    product and its associated metadata are both ingested into the CAS-Filemgr.
+    The metadata will go into the Filemgr's metadata catalog and the product will
+    go to the archive.</p>
+    
+    <p>Because metadata extractors and the CAS-Filemgr are not tightly-coupled,
+    there are a number of implicit design assumptions that effect how you design
+    metadata extractors in this use-case. For example, CAS-Filemgr differentiates 
+    between products based on product <i>type</i>. File type and product type are 
+    not necessarily identical, so you should write extractors to to produce 
+    metadata specific to product types (See the <a href="../user/advanced.html">
+    Advanced Guide</a> for information on mime-type detection).</p>
+    
+    <p>Along the same lines, remember that there is no mechanism to enforce the 
+    metadata extracted for a particular product type be ingested into the 
+    Filemgr's catalog. The command-line ingest client for the CAS-Filemgr is given 
+    below (note that the command-line interface and the API are equivelent):</p>
+
+<source><![CDATA[        
+filemgr-client --url <url to xml rpc service> --operation \
+--ingestProduct --productName <name> --productStructure <Hierarchical|Flat> 
+--productTypeName <name of product type> --metadataFile <file> \
+[--clienTransfer --dataTransfer <java class name of data transfer factory>] \
+--refs <ref1>...<refn>
+]]></source>    
+    
+    <p>In the above interface, the important feature to note is that the user
+    supplies not only the product, but also the metadata file (or Metadata 
+    Object in the case of the API), the Product Name, Structure and Type
+    <i>on ingest</i>. Since each of these pieces of information is independant, 
+    it is the user's responsibility to maintain consistancy of the product type 
+    metadata between the extraction process and the ingest process.</p>
+    
+    </section>
+    
+    <section name="Conclusion">
+      <p>This is intended to be a basic guide to users of the CAS-Metadata project. We
+      have purposely omitted the discussion of metadata stardards, though we strongly
+      encourage you to investigate the role of standards and ontology in your 
+      particular application. In our <a href="../user/advanced.html">Advanced Guide</a>,
+      we cover more topics regarding the nuences of metadata extraction, including 
+      the impact of String-based representation on metadata element comparisons.</p>
+    </section>
+    
+  </body>
+</document>
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/MetadataTestCase.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/MetadataTestCase.java
new file mode 100644
index 0000000..792a250
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/MetadataTestCase.java
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.metadata;
+
+// JDK Input/output
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+// Junit Testing framework
+import junit.framework.TestCase;
+
+/**
+ * Base test case for metadata tests.  Provides access to test data files.
+ *
+ * @author Kelly
+ */
+public class MetadataTestCase extends TestCase {
+    /**
+     * Construct a metadata test case.
+     *
+     * @param name Case name.
+     */
+    public MetadataTestCase(String name) {
+        super(name);
+    }
+
+    /**
+     * Augment set up of a test case by creating a play directory where we can temporarily
+     * keep our test data files.
+     *
+     * @throws Exception If any errors occur in directory setup, or if superclass setUp throws it.
+     */
+    public void setUp() throws Exception {
+        super.setUp();                                                                      // Set up the framework test harness
+        tmpDir = File.createTempFile("metadata", ".tests");                                 // Get a temporary file
+        if (!tmpDir.delete())                                                               // File?! We don't want no stinkin' file
+            throw new IOException("Cannot delete temporary file " + tmpDir);                
+        if (!tmpDir.mkdirs())                                                               // Directory is what we want
+            throw new IOException("Cannot create temporary directory " + tmpDir);
+        //tmpDir.deleteOnExit();
+    }
+
+    /**
+     * Augment tear down of a test case by cleaning up our play directory.
+     *
+     * @throws Exception if any errors occur in directory deletion, or if superclass tearDown throws it.
+     */
+    public void tearDown() throws Exception {
+        String[] entries = tmpDir.list();                                                   // Get contents of our play area
+        for (int i = 0; i < entries.length; ++i) {                                          // Step through each one
+            File entry = new File(tmpDir, entries[i]);                                      // Make a file out of it
+            if (!entry.delete())                                                            // Nuke it if possible ...
+                throw new IOException("Cannot delete temporary file " + entry);             // Or if not ...
+        }
+        if (!tmpDir.delete())                                                               // Nuke the play area
+            throw new IOException("Cannot delete temporary directory " + tmpDir);           // Or if not ...
+        super.tearDown();                                                                   // Tear down the test harness
+    }
+    
+    /**
+     * Get a named test data file.  This will yield a test data file using the standard Java resource mechanism
+     * (ie, fetching out of a jar, from the class path, etc.) and stick it in a temporary file, since the
+     * metadata API works with files it can both name and use, not just streams of file data.
+     *
+     * @param name Name of the test data file to retrieve.
+     * @return A {@link java.io.File} containing the named test dat.
+     * @throws IOException If an I/O error occurs.
+     */
+    public File getTestDataFile(String name) throws IOException {
+        InputStream in = MetadataTestCase.class.getResourceAsStream(name);                  // Not found? Try resource stream
+        if (in == null)                                                                     // Still not found?  Bummer.
+            throw new IllegalArgumentException("Unknown test data file `" + name + "`; not found in resource path");
+        File fn = new File(tmpDir, name);                                                   // What the tests want: Files.
+        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fn));      // Copy data to it
+        in = new BufferedInputStream(in);                                                   // Buffer for efficiency
+        byte[] buf = new byte[512];                                                         // Classic disk page size
+        for (;;) {                                                                          // For ever
+            int c = in.read(buf);                                                           // Read into our buffer
+            if (c == -1) break;                                                             // EOF? Done.
+            out.write(buf, 0, c);                                                           // Not EOF? Copy out.
+        }
+        in.close();
+        out.close();
+        return fn;
+    }
+
+    /** Play area */
+    private File tmpDir;
+}
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/TestMetadata.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/TestMetadata.java
new file mode 100644
index 0000000..9918a48
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/TestMetadata.java
@@ -0,0 +1,168 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.cas.metadata;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+import java.util.Hashtable;
+
+/**
+ * Test Case Suite for the Metadata class.
+ * 
+ * @author mattmann
+ * @author bfoster
+ * 
+ */
+public class TestMetadata extends TestCase {
+
+  private Metadata metadata = null;
+
+  /**
+   * <p>
+   * Default Constructor
+   * </p>
+   */
+  public TestMetadata() {
+    super();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#setUp()
+   */
+  protected void setUp() throws Exception {
+    metadata = new Metadata();
+  }
+
+  public void testAddMany() {
+    List counting = new Vector();
+    counting.add("1");
+    counting.add("2");
+    counting.add("3");
+    metadata.addMetadata("ManyTest", counting);
+
+    assertNotNull(metadata.getAllMetadata("ManyTest"));
+    assertEquals(3, metadata.getAllMetadata("ManyTest").size());
+
+    // test ordering
+    assertEquals("1", (String) metadata.getAllMetadata("ManyTest").get(0));
+    assertEquals("2", (String) metadata.getAllMetadata("ManyTest").get(1));
+    assertEquals("3", (String) metadata.getAllMetadata("ManyTest").get(2));
+  }
+
+  public void testAddHashtable() {
+    Hashtable testHash = new Hashtable();
+    testHash.put("key1", "val1");
+    testHash.put("key2", "val2");
+
+    metadata = new Metadata();
+    metadata.addMetadata("key3", "val3");
+    metadata.addMetadata(testHash);
+
+    assertNotNull(metadata.getMetadata("key1"));
+    assertNotNull(metadata.getMetadata("key2"));
+
+    assertEquals("val1", metadata.getMetadata("key1"));
+    assertEquals("val2", metadata.getMetadata("key2"));
+
+    assertNotNull(metadata.getMetadata("key3"));
+    assertEquals("val3", metadata.getMetadata("key3"));
+  }
+
+  public void testReplace() {
+    Hashtable testHash = new Hashtable();
+    testHash.put("key1", "val1");
+    testHash.put("key2", "val2");
+
+    metadata = new Metadata();
+    metadata.addMetadata("blah", "blah2");
+
+    assertNotNull(metadata.getMetadata("blah"));
+    assertNull(metadata.getMetadata("key1"));
+    assertNull(metadata.getMetadata("key2"));
+
+    metadata.replaceMetadata(testHash);
+
+    assertNull(metadata.getMetadata("blah"));
+    assertNotNull(metadata.getMetadata("key1"));
+    assertNotNull(metadata.getMetadata("key2"));
+
+    assertEquals("val1", metadata.getMetadata("key1"));
+    assertEquals("val2", metadata.getMetadata("key2"));
+
+    metadata.replaceMetadata("key1", "val2");
+    metadata.replaceMetadata("key2", "val1");
+
+    assertEquals("val2", metadata.getMetadata("key1"));
+    assertEquals("val1", metadata.getMetadata("key2"));
+
+    List twoValues = new Vector();
+    twoValues.add("firstVal");
+    twoValues.add("secondVal");
+
+    metadata.replaceMetadata("key1", twoValues);
+    assertNotNull(metadata.getMetadata("key1"));
+    assertEquals(2, metadata.getAllMetadata("key1").size());
+
+    assertEquals("firstVal", (String) metadata.getAllMetadata("key1").get(0));
+    assertEquals("secondVal", (String) metadata.getAllMetadata("key1").get(1));
+
+  }
+  
+  public void testGetAllKeysWithName() {
+    Metadata m1 = new Metadata();
+    m1.addMetadata("Group1/key1", "val1");
+    m1.addMetadata("Group1/key2", "val2");
+    m1.addMetadata("Group2/key2", "val3");
+    m1.addMetadata("Group2/key2/key3", "val3");
+    m1.addMetadata("Group1/sub1/key2", "val3");
+    m1.addMetadata("Group1/sub2/key2/key3", "val3");
+    List<String> keys = m1.getAllKeysWithName("key2");
+    assertEquals(keys.size(), 3);
+    assertEquals(keys.get(0), "Group2/key2");
+    assertEquals(keys.get(1), "Group1/sub1/key2");
+    assertEquals(keys.get(2), "Group1/key2");
+    keys = m1.getAllKeysWithName("key1");
+    assertEquals(keys.size(), 1);
+    assertEquals(keys.get(0), "Group1/key1");
+  }
+
+  public void testEquals() {
+    Metadata m1 = new Metadata();
+    m1.addMetadata("key1", "val1");
+    m1.addMetadata("key2", "val2");
+    m1.addMetadata("key2", "val3");
+
+    Metadata m2 = new Metadata();
+    m2.addMetadata("key1", "val1");
+    m2.addMetadata("key2", "val2");
+    m2.addMetadata("key2", "val3");
+
+    assertEquals(m1, m2);
+    assertEquals(m2, m1);
+
+    m2.removeMetadata("key1");
+
+    assertFalse(m1.equals(m2));
+    assertFalse(m2.equals(m1));
+  }
+
+}
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/TestSerializableMetadata.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/TestSerializableMetadata.java
new file mode 100644
index 0000000..0fbb832
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/TestSerializableMetadata.java
@@ -0,0 +1,203 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.cas.metadata;
+
+import org.apache.oodt.commons.xml.XMLUtils;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import junit.framework.TestCase;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ *
+ *
+ * Test class for SerializableMetadata.
+ *
+ * @author bfoster
+ * @author mattmann
+ *
+ */
+public class TestSerializableMetadata extends TestCase {
+
+  private final String[] encodings = new String[] { "UTF-8", "iso-8859-1",
+      "windows-1252", "UTF-16", "US-ASCII" };
+
+  public TestSerializableMetadata() {
+    super();
+  }
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+  }
+
+  public void testSerialization() throws Exception {
+    for (int i = 0; i < encodings.length; i++) {
+      String encoding = encodings[i];
+      boolean useCDATA = false;
+      for (int j = 0; j < 2; j++, useCDATA = true) {
+        SerializableMetadata sm = new SerializableMetadata(encoding, useCDATA);
+        sm.addMetadata("key1", "val1");
+        sm.addMetadata("key2", "val2");
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(out);
+        oos.writeObject(sm);
+        oos.flush();
+
+        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
+            out.toByteArray()));
+        SerializableMetadata sm2 = (SerializableMetadata) ois.readObject();
+        oos.close();
+        ois.close();
+
+        assertNotNull(sm2);
+        assertNotNull(sm2.getHashtable());
+        assertEquals(2, sm2.getHashtable().size());
+        assertNotNull(sm2.getMetadata("key1"));
+        assertEquals("val1", sm2.getMetadata("key1"));
+        assertNotNull(sm2.getMetadata("key2"));
+        assertEquals("val2", sm2.getMetadata("key2"));
+        assertNotNull(sm2.getEncoding());
+        assertEquals(encoding, sm2.getEncoding());
+        assertEquals(useCDATA, sm2.isUsingCDATA());
+      }
+    }
+  }
+
+  public void testXmlStreaming() throws Exception {
+    for (int i = 0; i < encodings.length; i++) {
+      String encoding = encodings[i];
+      boolean useCDATA = false;
+      for (int j = 0; j < 2; j++, useCDATA = true) {
+        SerializableMetadata metadata1 = new SerializableMetadata(encoding,
+            useCDATA);
+        metadata1.addMetadata("Name1", "Value1");
+        metadata1.addMetadata("Name2", "Value/2");
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        metadata1.writeMetadataToXmlStream(out);
+
+        SerializableMetadata metadata2 = new SerializableMetadata(encoding,
+            useCDATA);
+        metadata2.loadMetadataFromXmlStream(new ByteArrayInputStream(out
+            .toByteArray()));
+        out.close();
+
+        assertNotNull(metadata2);
+        assertNotNull(metadata2.getHashtable());
+        assertEquals(2, metadata2.getHashtable().size());
+        assertNotNull(metadata2.getMetadata("Name1"));
+        assertEquals("Value1", metadata2.getMetadata("Name1"));
+        assertNotNull(metadata2.getMetadata("Name2"));
+        assertEquals("Value/2", metadata2.getMetadata("Name2"));
+      }
+    }
+  }
+
+  public void testMetadataConversion() throws Exception {
+    for (int i = 0; i < encodings.length; i++) {
+      String encoding = encodings[i];
+      Metadata m = new Metadata();
+      m.addMetadata("key1", "val1");
+      m.addMetadata("key2", "val2");
+
+      SerializableMetadata sm = new SerializableMetadata(m, encoding, false);
+      Metadata mConv = sm.getMetadata();
+
+      assertNotNull(mConv);
+      assertNotNull(mConv.getHashtable());
+      assertEquals(2, mConv.getHashtable().size());
+      assertNotNull(mConv.getMetadata("key1"));
+      assertEquals("val1", mConv.getMetadata("key1"));
+      assertNotNull(mConv.getMetadata("key2"));
+      assertEquals("val2", mConv.getMetadata("key2"));
+    }
+  }
+
+  public void testWriteRead() {
+    SerializableMetadata metadata = new SerializableMetadata();
+    metadata.addMetadata("Name1", "Value1");
+    metadata.addMetadata("Name2", "Value2");
+
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+    try {
+      XMLUtils.writeXmlToStream(metadata.toXML(), out);
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+
+    SerializableMetadata metadata2 = null;
+    try {
+      metadata2 = new SerializableMetadata(new ByteArrayInputStream(out
+          .toByteArray()));
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+
+    assertNotNull(metadata2);
+    assertNotNull(metadata2.getHashtable());
+
+    assertEquals(2, metadata2.getHashtable().size());
+    assertNotNull(metadata2.getMetadata("Name1"));
+    assertEquals("Value1", metadata2.getMetadata("Name1"));
+    assertNotNull(metadata2.getMetadata("Name2"));
+    assertEquals("Value2", metadata2.getMetadata("Name2"));
+  }
+
+  public void testNamespace() throws Exception {
+    SerializableMetadata metadata = new SerializableMetadata();
+    metadata.addMetadata("Name1", "Value1");
+    metadata.addMetadata("Name2", "Value2");
+
+    // write xml DOM to string
+    ByteArrayOutputStream array = new ByteArrayOutputStream();
+    metadata.writeMetadataToXmlStream(array);
+
+    // read string into new xml DOM
+    DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
+    f.setNamespaceAware(true);
+    Document doc = f.newDocumentBuilder().parse(new ByteArrayInputStream(array.toByteArray()));
+
+    final String NS = "http://oodt.jpl.nasa.gov/1.0/cas";
+    final String PREFIX = "cas";
+
+    // compare namespaces in DOM before and after the write/read operation
+    Element before = metadata.toXML().getDocumentElement();
+    String nsBefore = before.getNamespaceURI();
+    String preBefore = before.getPrefix();
+    assertEquals(NS, nsBefore);
+    assertEquals(PREFIX, preBefore);
+
+    Element after = doc.getDocumentElement();
+    String nsAfter = after.getNamespaceURI();
+    String preAfter = after.getPrefix();
+    assertEquals(NS, nsAfter);
+    assertEquals(PREFIX, preAfter);
+  }
+
+}
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestAbstractSAXConfigReader.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestAbstractSAXConfigReader.java
new file mode 100644
index 0000000..3d98ad0
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestAbstractSAXConfigReader.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.metadata.extractors;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestAbstractSAXConfigReader {
+
+    private AbstractSAXConfigReader configReader;
+    private File configFile;
+
+    private List<String> uris = new ArrayList<String>();
+    private List<String> localNames = new ArrayList<String>();
+    private List<String> qNames = new ArrayList<String>();
+    private List<Integer> attributes = new ArrayList<Integer>();
+
+    @Before
+    public void setup() throws Exception {
+        URL url = getClass().getResource("/product-type-patterns.xml");
+        configFile = new File(url.toURI());
+        configReader = new AbstractSAXConfigReader() {
+            @Override
+            public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
+                uris.add(uri);
+                localNames.add(localName);
+                qNames.add(qName);
+                attributes.add(attrs.getLength());
+            }
+        };
+    }
+
+    @After
+    public void teardown() {
+        uris.clear();
+        localNames.clear();
+        qNames.clear();
+        attributes.clear();
+    }
+
+    @Test
+    public void testParseConfigFile() throws Exception {
+        configReader.parseConfigFile(configFile);
+
+        assertEquals(5, uris.size());
+        for (String uri : uris)
+            assertEquals("", uri);
+
+        assertEquals(5, localNames.size());
+        for (String local : localNames)
+            assertEquals("", local);
+
+        assertEquals(5, qNames.size());
+        assertEquals("config", qNames.get(0));
+        assertEquals("element", qNames.get(1));
+        assertEquals("element", qNames.get(2));
+        assertEquals("product-type", qNames.get(3));
+        assertEquals("product-type", qNames.get(4));
+
+        assertEquals(5, attributes.size());
+
+        assertEquals(0, (int)attributes.get(0));
+        assertEquals(2, (int)attributes.get(1));
+        assertEquals(2, (int)attributes.get(2));
+        assertEquals(2, (int)attributes.get(3));
+        assertEquals(2, (int)attributes.get(4));
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestCopyAndRewriteExtractor.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestCopyAndRewriteExtractor.java
new file mode 100644
index 0000000..5c69f30
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestCopyAndRewriteExtractor.java
@@ -0,0 +1,159 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.MetadataTestCase;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.Properties;
+
+/**
+ * Tests the CopyAndRewriteExtractor.
+ */
+public class TestCopyAndRewriteExtractor extends MetadataTestCase {
+
+  private CopyAndRewriteExtractor extractor;
+
+  private static final String FILENAME = "Filename";
+
+  private static final String FILE_LOCATION = "FileLocation";
+
+  private static final String PRODUCT_TYPE = "ProductType";
+
+  private static final String expectedProductType = "NewProductTypeGenericFile";
+  
+  private static final String expectedFilename = "testfile.txt";
+
+  private String expectedFileLocation;
+  
+  private File confFile;
+  
+  private File sampleMetFile;
+  
+  private File extractFile;
+  
+  public TestCopyAndRewriteExtractor(String name) {
+    super(name);
+  }
+  
+  
+
+  public void testExtractMetadata() {
+    Metadata met = null;
+
+    try {
+      met = extractor.extractMetadata(this.extractFile.getCanonicalPath());
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(met);
+    assertNotNull(met.getHashtable());
+    assertNotNull(met.getHashtable().keySet());
+    assertEquals(3, met.getHashtable().keySet().size());
+    assertTrue(met.containsKey(FILENAME));
+    assertEquals(expectedFilename, met.getMetadata(FILENAME));
+    assertTrue(met.containsKey(PRODUCT_TYPE));
+    assertEquals(expectedProductType, met.getMetadata(PRODUCT_TYPE));
+    assertTrue(met.containsKey(FILE_LOCATION));
+    assertEquals("The expected file location: [" + expectedFileLocation
+        + "] does not match " + "the obtained file location: ["
+        + met.getMetadata(FILE_LOCATION) + "]", expectedFileLocation, met
+        .getMetadata(FILE_LOCATION));
+  }
+
+  public void testReplaceOrigMetFilePath() {
+    Metadata met = null;
+
+    try {
+      met = extractor.extractMetadata(this.extractFile.getCanonicalPath());
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(met);
+  }
+
+
+
+  /* (non-Javadoc)
+   * @see junit.framework.TestCase#setUp()
+   */
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    String confFilename = "/copyandrewrite.test.conf";
+    String sampleMetFilename = "/samplemet.xml";
+    String extractFilename = "/testfile.txt";
+    String origMetFilePath = "orig.met.file.path";
+    
+    // get all the needed files staged
+    this.sampleMetFile = super.getTestDataFile(sampleMetFilename);
+    this.extractFile = super.getTestDataFile(extractFilename);
+    
+    
+    // this is a java properties file
+    this.confFile = super.getTestDataFile(confFilename);
+    
+    // we need to compute and override orig.met.file.path
+    Properties confProps = new Properties();
+    confProps.load(new FileInputStream(confFile));
+    confProps.setProperty(origMetFilePath, sampleMetFile.getAbsolutePath());
+    confProps.store(new FileOutputStream(confFile), null);
+    
+
+    try {
+      this.expectedFileLocation = "/new/loc/"
+          + this.extractFile.getParentFile().getCanonicalPath();
+    } catch (Exception ignore) {
+    }
+    
+    
+    CopyAndRewriteConfig config = new CopyAndRewriteConfig();
+    try {
+      config.load(new FileInputStream(this.confFile));
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    this.extractor = new CopyAndRewriteExtractor();
+    this.extractor.setConfigFile(config);
+    
+  }
+
+
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.metadata.MetadataTestCase#tearDown()
+   */
+  @Override
+  public void tearDown() throws Exception {
+    super.tearDown();
+    if(this.confFile != null) this.confFile = null;
+    if(this.sampleMetFile != null) this.sampleMetFile = null;
+    if(this.extractFile != null) this.extractFile = null;
+    this.expectedFileLocation = null;
+  }
+  
+  
+}
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestDataSourceMetExtractor.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestDataSourceMetExtractor.java
new file mode 100644
index 0000000..ee090f1
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestDataSourceMetExtractor.java
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.metadata.extractors;
+
+// JUnit static imports
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
+
+// JDK imports
+import java.io.File;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+
+// JAVAX imports
+import javax.sql.DataSource;
+
+// OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+
+// JUnit imports
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+// Mockito imports
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Test class for {@link DataSourceMetExtractor}.
+ * 
+ * @author bfoster@apache.org (Brian Foster)
+ */
+@RunWith(JUnit4.class)
+public class TestDataSourceMetExtractor {
+
+  private static final String DB_COL_NAME_1 = "NAME";
+  private static final String DB_COL_VALUE_1 = "SomeName";
+  private static final String DB_COL_NAME_2 = "SIZE";
+  private static final String DB_COL_VALUE_2 = "20";
+
+  @Mock private DataSource dataSource;
+  @Mock private Connection conn;
+  @Mock private Statement statement;
+  @Mock private ResultSet rs;
+  @Mock private ResultSetMetaData rsMet;
+
+  private DataSourceMetExtractor extractor;
+
+  @Before
+  public void setUp() throws Exception {
+    MockitoAnnotations.initMocks(this);
+
+    when(dataSource.getConnection()).thenReturn(conn);
+    when(conn.createStatement()).thenReturn(statement);
+    when(statement.executeQuery(Mockito.<String>any())).thenReturn(rs);
+    when(rs.getMetaData()).thenReturn(rsMet);
+    when(rs.next()).thenReturn(true);
+    when(rs.getString(1)).thenReturn(DB_COL_VALUE_1);
+    when(rs.getString(2)).thenReturn(DB_COL_VALUE_2);
+    when(rsMet.getColumnCount()).thenReturn(2);
+    when(rsMet.getColumnName(1)).thenReturn(DB_COL_NAME_1);
+    when(rsMet.getColumnName(2)).thenReturn(DB_COL_NAME_2);
+
+    extractor = new DataSourceMetExtractor();
+  }
+ 
+  @Test
+  public void testGetKey() {
+    assertThat(extractor.getKey(new File("Test.csv")), is("Test"));
+    assertThat(extractor.getKey(new File("123_sdfwegd_g334g.dat")), is("123_sdfwegd_g334g"));
+    assertThat(extractor.getKey(new File("123qweJDKJF-3")), is("123qweJDKJF-3"));
+  }
+
+  @Test
+  public void testGetMetadata() throws MetExtractionException {
+    Metadata metadata = extractor.getMetadata(
+        dataSource, "select * from SomeTable where key = '%s'", "SomeKey");
+
+    assertThat(metadata.getAllKeys().size(), is(2));
+    assertThat(metadata.getMetadata(DB_COL_NAME_1), is(DB_COL_VALUE_1));
+    assertThat(metadata.getMetadata(DB_COL_NAME_2), is(DB_COL_VALUE_2));
+  }
+}
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestExternMetExtractor.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestExternMetExtractor.java
new file mode 100644
index 0000000..9be4f07
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestExternMetExtractor.java
@@ -0,0 +1,156 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//OODT imports
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.MetadataTestCase;
+import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.exec.ExecHelper;
+
+//JDK imports
+import java.io.File;
+import java.net.URLEncoder;
+
+/**
+ * 
+ * Test Suite for the {@link ExternMetExtractor} 
+ *          .
+ */
+public class TestExternMetExtractor extends MetadataTestCase {
+
+  private ExternMetExtractor extractor;
+
+  private static final String FILENAME = "Filename";
+
+  private static final String FILE_LOCATION = "FileLocation";
+
+  private static final String PRODUCT_TYPE = "ProductType";
+
+  private static final String expectedFilename = "/testfile.txt";
+
+  private static final String expectedProductType = "GenericFile";
+  
+  private File extractFile;
+  
+  private File confFile;
+  
+  private File metFile;
+  
+  private String expectedFileLocation;
+  
+  public TestExternMetExtractor(String name){
+    super(name);
+  }
+
+  public void testExtractor() {
+
+    Metadata met = null;
+
+    try {
+      met = extractor.extractMetadata(this.extractFile, this.confFile);
+    } catch (MetExtractionException e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(met);
+    assertTrue(this.metFile.exists());
+    assertTrue(met.containsKey(FILENAME));
+    assertTrue(met.containsKey(FILE_LOCATION));
+    assertTrue(met.containsKey(PRODUCT_TYPE));
+
+    assertEquals(expectedFilename.substring(1), met.getMetadata(FILENAME));
+    assertEquals("Expected: ["+this.expectedFileLocation+"]; Actual: ["+met.getMetadata(FILE_LOCATION)+"]", this.expectedFileLocation, met.getMetadata(FILE_LOCATION));
+    assertEquals(expectedProductType, met.getMetadata(PRODUCT_TYPE));
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.metadata.MetadataTestCase#tearDown()
+   */
+  public void tearDown() throws Exception {
+    super.tearDown();
+    if (this.metFile != null && this.metFile.exists()) {
+      this.metFile.delete();
+      this.metFile = null;
+    }
+    
+    if(this.confFile != null) this.confFile = null;
+    if(this.extractFile != null) this.extractFile = null;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.metadata.MetadataTestCase#setUp()
+   */
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    String configFilename = "/extern-config.xml";
+    String extractFilename = "/testfile.txt";
+    String extractorFilename = "/testExtractor";
+    String sampleMetFilename = "/samplemet.xml";
+    
+    this.confFile = super.getTestDataFile(configFilename);
+    this.extractFile = super.getTestDataFile(extractFilename);
+    this.metFile = new File(this.extractFile.getCanonicalPath()+".met");
+    this.expectedFileLocation = this.extractFile.getParent();
+    
+    File extractorFile = super.getTestDataFile(extractorFilename);
+    
+    // make it executable
+    // yes this is ghetto
+    String chmodCmd = "chmod +x "+extractorFile.getAbsolutePath();
+    ExecHelper.execUsingShell(chmodCmd);
+    
+    // replace the FileLocation met field in the sample met file
+    // with the actual file location of the extractFile
+    File sampleMetFile = super.getTestDataFile(sampleMetFilename);
+    String sampleMetFileContents = FileUtils.readFileToString(sampleMetFile);
+    String extractFileLocKey = "[EXTRACT_FILE_LOC]";
+    sampleMetFileContents = sampleMetFileContents.replace(extractFileLocKey, URLEncoder.encode(extractFile.getParent(), "UTF-8"));
+    FileUtils.writeStringToFile(sampleMetFile, sampleMetFileContents, "UTF-8");
+    
+    // replace the path to the sample met file inside of testExtractor
+    String extractorFileContents = FileUtils.readFileToString(extractorFile);
+    String sampleMetFilePathKey = "<TEST_SAMPLE_MET_PATH>";
+    extractorFileContents = extractorFileContents.replace(sampleMetFilePathKey, sampleMetFile.getAbsolutePath());
+    FileUtils.writeStringToFile(extractorFile, extractorFileContents);
+    
+    // replace path in confFile named TEST_PATH
+    String testPathKey = "TEST_PATH";
+    String confFileContents = FileUtils.readFileToString(this.confFile);
+    Metadata replaceMet = new Metadata();
+    replaceMet.addMetadata(testPathKey, extractorFile.getParent());
+    confFileContents = PathUtils.replaceEnvVariables(confFileContents, replaceMet);
+    FileUtils.writeStringToFile(this.confFile, confFileContents);
+    
+
+    try {
+      extractor = new ExternMetExtractor();
+    } catch (InstantiationException e) {
+      fail(e.getMessage());
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestExternMetExtractorConfigReader.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestExternMetExtractorConfigReader.java
new file mode 100644
index 0000000..b4b7240
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestExternMetExtractorConfigReader.java
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+// Metadata imports
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.MetadataTestCase;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//JDK imports
+import java.io.File;
+
+//Junit imports
+
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Test suite for the {@link ExternConfigReader}
+ * </p>.
+ */
+public class TestExternMetExtractorConfigReader extends MetadataTestCase {
+    /**
+     * Construct a TestExternMetExtractorConfigReader instance.
+     *
+     * @param name Case name.
+     */
+    public TestExternMetExtractorConfigReader(String name) {
+        super(name);
+    }
+    
+    private static final String configFilePath = "/extern-config.xml";
+
+    private static final String expectedBinPathEnding = "/testExtractor";
+
+    private static final String arg1 = ExternMetExtractorMetKeys.DATA_FILE_PLACE_HOLDER;
+
+    private static final String arg2 = ExternMetExtractorMetKeys.MET_FILE_PLACE_HOLDER;
+    
+    private static final String arg3 = "-Dtrue=always";
+
+    private static final String arg4 = "foo";
+
+    private static final String arg5 = "bar";
+
+    private static final String arg5ending = "/test\\ boo";
+    
+    private File confFile;
+
+    public void testReadConfig() {
+        ExternalMetExtractorConfig config = null;
+        try {
+            config = (ExternalMetExtractorConfig) new ExternConfigReader().parseConfigFile(this.confFile);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(config);
+        assertNotNull(config.getWorkingDirPath());
+        assertEquals("", config.getWorkingDirPath());
+        assertTrue(config.getExtractorBinPath().endsWith(expectedBinPathEnding));
+        assertTrue(config.getExtractorBinPath().indexOf("[") == -1);
+        assertTrue(config.getExtractorBinPath().indexOf("]") == -1);
+        assertNotNull(config.getArgList());
+        assertEquals(6, config.getArgList().length);
+        assertEquals(arg1, config.getArgList()[0]);
+        assertEquals(arg2, config.getArgList()[1]);
+        assertEquals(arg3, config.getArgList()[2]);
+        assertEquals(arg4, config.getArgList()[3]);
+        assertEquals(arg5, config.getArgList()[4]);
+        assertTrue(config.getArgList()[5].endsWith(arg5ending));
+
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.metadata.MetadataTestCase#setUp()
+     */
+    @Override
+    public void setUp() throws Exception {
+      super.setUp();
+      this.confFile = getTestDataFile(configFilePath);
+      
+      // replace path in confFile named TEST_PATH
+      String testPathKey = "TEST_PATH";
+      String confFileContents = FileUtils.readFileToString(this.confFile);
+      Metadata replaceMet = new Metadata();
+      replaceMet.addMetadata(testPathKey, this.confFile.getParent());
+      confFileContents = PathUtils.replaceEnvVariables(confFileContents, replaceMet);
+      FileUtils.writeStringToFile(this.confFile, confFileContents);
+    }
+}
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestMetReader.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestMetReader.java
new file mode 100644
index 0000000..dd944a3
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestMetReader.java
@@ -0,0 +1,110 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.extractors;
+
+//JDK imports
+import java.io.File;
+import java.net.URLEncoder;
+
+//OODT imports
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.cas.metadata.MetExtractor; //for javadoc
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.MetadataTestCase;
+
+/**
+ * 
+ * Test case for the {@link MetReaderExtractor} {@link MetExtractor}
+ */
+public class TestMetReader extends MetadataTestCase {
+
+    private MetReaderExtractor extractor;
+
+    private static final String expectedProductType = "GenericFile";
+
+    private static final String expectedFilename = "testfile.txt";
+
+    private static final String FILENAME = "Filename";
+
+    private static final String FILE_LOCATION = "FileLocation";
+
+    private static final String PRODUCT_TYPE = "ProductType";
+    
+    private String expectedFileLocation;
+    
+    private File extractFile;
+    
+    public TestMetReader(String name) {
+      super(name);
+    }
+
+    public void testExtractMetadata() {
+        Metadata met = null;
+
+        try {
+            met = extractor.extractMetadata(this.extractFile.getCanonicalPath());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(met);
+        assertNotNull(met.getHashtable());
+        assertNotNull(met.getHashtable().keySet());
+        assertEquals(3, met.getHashtable().keySet().size());
+        assertTrue(met.containsKey(FILENAME));
+        assertEquals(met.getMetadata(FILENAME), expectedFilename);
+        assertTrue(met.containsKey(FILE_LOCATION));
+        assertEquals(met.getMetadata(FILE_LOCATION), expectedFileLocation);
+        assertTrue(met.containsKey(PRODUCT_TYPE));
+        assertEquals(met.getMetadata(PRODUCT_TYPE), expectedProductType);
+
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.metadata.MetadataTestCase#setUp()
+     */
+    @Override
+    public void setUp() throws Exception {
+      super.setUp();
+      String extractFilename = "/testfile2.txt";
+      String sampleMetFilename = "/testfile2.txt.met";
+      this.extractFile = super.getTestDataFile(extractFilename);
+      this.expectedFileLocation = this.extractFile.getParent();
+      
+      // replace the FileLocation met field in the sample met file
+      // with the actual file location of the extractFile
+      File sampleMetFile = super.getTestDataFile(sampleMetFilename);
+      String sampleMetFileContents = FileUtils.readFileToString(sampleMetFile);
+      String extractFileLocKey = "[EXTRACT_FILE_LOC]";
+      sampleMetFileContents = sampleMetFileContents.replace(extractFileLocKey, URLEncoder.encode(extractFile.getParent(), "UTF-8"));
+      FileUtils.writeStringToFile(sampleMetFile, sampleMetFileContents, "UTF-8");
+
+      this.extractor = new MetReaderExtractor();
+
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.metadata.MetadataTestCase#tearDown()
+     */
+    @Override
+    public void tearDown() throws Exception {
+      super.tearDown();
+    }
+
+}
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestProdTypePatternMetExtractor.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestProdTypePatternMetExtractor.java
new file mode 100644
index 0000000..9f4049c
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/extractors/TestProdTypePatternMetExtractor.java
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.metadata.extractors;
+
+import com.google.common.io.Files;
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.net.URL;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestProdTypePatternMetExtractor {
+
+    private ProdTypePatternMetExtractor extractor;
+    private File configFile;
+    private File configFile2;
+
+    private File tmpDir;
+    private File book1;
+    private File book2;
+    private File page1;
+    private File page2;
+    private File page1a;
+    private File page2a;
+
+    @Before
+    public void setup() throws Exception {
+        URL url = getClass().getResource("/product-type-patterns.xml");
+        configFile = new File(url.toURI());
+        extractor = new ProdTypePatternMetExtractor();
+        extractor.setConfigFile(configFile);
+
+        tmpDir = Files.createTempDir();
+        book1 = new File(tmpDir, "book-1234567890.txt");
+        book2 = new File(tmpDir, "book-0987654321.txt");
+        page1 = new File(tmpDir, "page-1234567890-111.txt");
+        page2 = new File(tmpDir, "page-0987654321-222.txt");
+        Files.touch(book1);
+        Files.touch(book2);
+        Files.touch(page1);
+        Files.touch(page2);
+
+        url = getClass().getResource("/product-type-patterns-2.xml");
+        configFile2 = new File(url.toURI());
+        page1a = new File(tmpDir, "page-111-1234567890.txt");
+        page2a = new File(tmpDir, "page-222-0987654321.txt");
+        Files.touch(page1a);
+        Files.touch(page2a);
+    }
+
+    @After
+    public void teardown() {
+        FileUtils.deleteQuietly(tmpDir);
+    }
+
+    @Test
+    public void testExtractMetadata() throws Exception {
+        Metadata met = extractor.extractMetadata(book1);
+        assertEquals(2, met.getAllKeys().size());
+        assertEquals("Book", met.getMetadata("ProductType"));
+        assertEquals("1234567890", met.getMetadata("ISBN"));
+
+        met = extractor.extractMetadata(book2);
+        assertEquals(2, met.getAllKeys().size());
+        assertEquals("Book", met.getMetadata("ProductType"));
+        assertEquals("0987654321", met.getMetadata("ISBN"));
+
+        met = extractor.extractMetadata(page1);
+        assertEquals(3, met.getAllKeys().size());
+        assertEquals("BookPage", met.getMetadata("ProductType"));
+        assertEquals("1234567890", met.getMetadata("ISBN"));
+        assertEquals("111", met.getMetadata("Page"));
+
+        met = extractor.extractMetadata(page2);
+        assertEquals(3, met.getAllKeys().size());
+        assertEquals("BookPage", met.getMetadata("ProductType"));
+        assertEquals("0987654321", met.getMetadata("ISBN"));
+        assertEquals("222", met.getMetadata("Page"));
+    }
+
+    @Test
+    public void testNewConfigFile() throws Exception {
+        // make sure that duplicate met entries do not exist when re-parsing a new config file
+        Metadata met = extractor.extractMetadata(book1, configFile);
+        assertEquals(2, met.getAllKeys().size());
+        assertEquals(1, met.getAllMetadata("ProductType").size());
+        assertEquals(1, met.getAllMetadata("ISBN").size());
+
+        met = extractor.extractMetadata(book2, configFile);
+        assertEquals(2, met.getAllKeys().size());
+        assertEquals(1, met.getAllMetadata("ProductType").size());
+        assertEquals(1, met.getAllMetadata("ISBN").size());
+
+        met = extractor.extractMetadata(page1, configFile);
+        assertEquals(3, met.getAllKeys().size());
+        assertEquals(1, met.getAllMetadata("ProductType").size());
+        assertEquals(1, met.getAllMetadata("ISBN").size());
+        assertEquals(1, met.getAllMetadata("Page").size());
+
+        met = extractor.extractMetadata(page2, configFile);
+        assertEquals(3, met.getAllKeys().size());
+        assertEquals(1, met.getAllMetadata("ProductType").size());
+        assertEquals(1, met.getAllMetadata("ISBN").size());
+        assertEquals(1, met.getAllMetadata("Page").size());
+    }
+
+    @Test
+    public void testElementDeclarationOrder() throws Exception {
+        // the relative order of element declarations shouldn't matter
+        extractor.setConfigFile(configFile2);
+
+        Metadata met = extractor.extractMetadata(book1);
+        assertEquals(2, met.getAllKeys().size());
+        assertEquals("Book", met.getMetadata("ProductType"));
+        assertEquals("1234567890", met.getMetadata("ISBN"));
+
+        met = extractor.extractMetadata(book2);
+        assertEquals(2, met.getAllKeys().size());
+        assertEquals("Book", met.getMetadata("ProductType"));
+        assertEquals("0987654321", met.getMetadata("ISBN"));
+
+        met = extractor.extractMetadata(page1a);
+        assertEquals(3, met.getAllKeys().size());
+        assertEquals("BookPage", met.getMetadata("ProductType"));
+        assertEquals("1234567890", met.getMetadata("ISBN"));
+        assertEquals("111", met.getMetadata("Page"));
+
+        met = extractor.extractMetadata(page2a);
+        assertEquals(3, met.getAllKeys().size());
+        assertEquals("BookPage", met.getMetadata("ProductType"));
+        assertEquals("0987654321", met.getMetadata("ISBN"));
+        assertEquals("222", met.getMetadata("Page"));
+    }
+}
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/filenaming/TestPathUtilsNamingConvention.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/filenaming/TestPathUtilsNamingConvention.java
new file mode 100644
index 0000000..ed47b36
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/filenaming/TestPathUtilsNamingConvention.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.metadata.filenaming;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.util.UUID;
+
+//Apache imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.exceptions.NamingConventionException;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link PathUtilsNamingConvention}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestPathUtilsNamingConvention extends TestCase {
+
+   public void testRename() throws IOException, NamingConventionException {
+      File tmpFile = File.createTempFile("bogus", "bogus");
+      File tmpDir = new File(tmpFile.getParentFile(),
+            UUID.randomUUID().toString());
+      if (!tmpDir.mkdirs()) {
+         throw new IOException("Failed to create temp directory");
+      }
+      tmpFile.delete();
+      File testFile = new File(tmpDir, "TestProduct.txt");
+      Metadata m = new Metadata();
+      m.replaceMetadata("NewName", "NewProduct.txt");
+
+      // Test failure.
+      PathUtilsNamingConvention nc = new PathUtilsNamingConvention();
+      nc.setNamingConv("[NewName]");
+      try {
+         nc.rename(testFile, m);
+         fail("Should have thrown IOException");
+      } catch (NamingConventionException e) { /* expect throw */ }
+
+      // Test success.
+      FileUtils.touch(testFile);
+      File newFile = nc.rename(testFile, m);
+      assertTrue(newFile.exists());
+      assertEquals("NewProduct.txt", newFile.getName());
+      assertFalse(testFile.exists());
+
+      FileUtils.forceDelete(tmpDir);
+   }
+}
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/preconditions/TestPreCondEvalUtils.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/preconditions/TestPreCondEvalUtils.java
new file mode 100644
index 0000000..edd859f
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/preconditions/TestPreCondEvalUtils.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.preconditions;
+
+// Metadata Imports
+import org.apache.oodt.cas.metadata.MetadataTestCase;
+
+//JDK imports
+import java.io.File;
+import java.util.LinkedList;
+
+//Spring imports
+import org.junit.Before;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+//Junit imports
+
+
+/**
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test suite for the {@link PreCondEvalUtils} class
+ * </p>.
+ */
+public class TestPreCondEvalUtils extends MetadataTestCase {
+
+    LinkedList<String> preconditions;
+    
+    private PreCondEvalUtils evalUtils;
+
+    public TestPreCondEvalUtils(String name) {
+        super(name);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        this.preconditions = new LinkedList<String>();
+        this.preconditions.add("CheckThatDataFileSizeIsGreaterThanZero");
+        this.preconditions.add("CheckThatDataFileExists");
+        this.preconditions.add("CheckDataFileMimeType");
+        File preCondFile = getTestDataFile("/met_extr_preconditions.xml");
+        this.evalUtils = new PreCondEvalUtils(new FileSystemXmlApplicationContext("file:" + preCondFile.getAbsolutePath()));
+    }
+
+    public void testEval() throws Throwable {
+        // Test file is also the config file we used, neat!
+        File prodFile = getTestDataFile("/met_extr_preconditions.xml");
+        assertTrue(this.evalUtils.eval(this.preconditions, prodFile));
+    }
+}
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/util/TestMimeTypeUtils.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/util/TestMimeTypeUtils.java
new file mode 100644
index 0000000..e49991b
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/util/TestMimeTypeUtils.java
@@ -0,0 +1,33 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.cas.metadata.util;
+
+import junit.framework.TestCase;
+
+public class TestMimeTypeUtils extends TestCase {
+
+	public void testMimeTypes() {
+		MimeTypeUtils mtUtils = new MimeTypeUtils();
+		assertEquals("application/xml", mtUtils.getMimeType("file.xml"));
+		assertEquals("text/plain", mtUtils.getMimeType("file.txt"));
+		assertEquals("application/pdf", mtUtils.getMimeType("file.pdf"));
+		assertEquals("application/xhtml+xml", mtUtils.getMimeType("file.xhtml"));
+		assertEquals("application/xml", mtUtils.getSuperTypeForMimeType(mtUtils.getMimeType("file.xhtml")));
+		assertEquals("test/example", mtUtils.getMimeType("file.testexample"));
+	}
+	
+}
diff --git a/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/util/TestPathUtils.java b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/util/TestPathUtils.java
new file mode 100644
index 0000000..9ce7225
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/org/apache/oodt/cas/metadata/util/TestPathUtils.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.metadata.util;
+
+//JDK imports
+import java.util.Calendar;
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Test Case Suite for the PathUtils class.
+ * </p>
+ * 
+ */
+public class TestPathUtils extends TestCase {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testReplaceEnvVariables() {
+        this.singleValueTest();
+        this.multiValueTest();
+    }
+    
+    public void testDoDynamicReplacement() throws Exception {
+
+        System.out.println("Timezone is :" + Calendar.getInstance().getTimeZone().getID());
+
+        assertEquals("2008-01-20T16:30:28.000-000033", PathUtils
+            .doDynamicReplacement("[UTC_TO_TAI(2008-01-20T16:29:55.000Z)]"));
+        assertEquals("475000201.000",
+            PathUtils.doDynamicReplacement(
+                "[DATE_TO_SECS([UTC_TO_TAI(2008-01-20T16:29:55.000Z)], TAI_FORMAT, 1993-01-01)]"));
+        assertEquals("2010-01-01", PathUtils.doDynamicReplacement("[DATE_ADD(2009-12-31, yyyy-MM-dd, 1, day)]"));
+    }
+
+    private void singleValueTest() {
+        String key = "KEY";
+        String pathString = "[" + key + "]";
+        Metadata m = generateTestMetadata(key, 1);
+        assertEquals(getCorrectOutput(m, key, true), PathUtils
+                .replaceEnvVariables(pathString, m, true));
+        assertEquals(getCorrectOutput(m, key, false), PathUtils
+                .replaceEnvVariables(pathString, m, false));
+        assertEquals(PathUtils.replaceEnvVariables(pathString, m), PathUtils
+                .replaceEnvVariables(pathString, m, false));
+        assertEquals(PathUtils.replaceEnvVariables(pathString, m), PathUtils
+                .replaceEnvVariables(pathString, m, true));
+        assertEquals(PathUtils.replaceEnvVariables(pathString, m, false),
+                PathUtils.replaceEnvVariables(pathString, m, true));
+    }
+
+    private void multiValueTest() {
+        String key = "KEY";
+        String pathString = "[" + key + "]";
+        Metadata m = generateTestMetadata(key, 5);
+        assertEquals(getCorrectOutput(m, key, true), PathUtils
+                .replaceEnvVariables(pathString, m, true));
+        assertEquals(getCorrectOutput(m, key, false), PathUtils
+                .replaceEnvVariables(pathString, m, false));
+        assertEquals(PathUtils.replaceEnvVariables(pathString, m), PathUtils
+                .replaceEnvVariables(pathString, m, false));
+        assertFalse(PathUtils.replaceEnvVariables(pathString, m).equals(
+                PathUtils.replaceEnvVariables(pathString, m, true)));
+        assertFalse(PathUtils.replaceEnvVariables(pathString, m, false).equals(
+                PathUtils.replaceEnvVariables(pathString, m, true)));
+    }
+
+    private static Metadata generateTestMetadata(String key,
+            int numOfValueFields) {
+        Metadata m = new Metadata();
+        StringBuffer outputValue = new StringBuffer("");
+        Vector valList = new Vector();
+        for (int i = 0; i < numOfValueFields; i++)
+            valList.add("val" + i);
+        m.addMetadata(key, valList);
+        return m;
+    }
+
+    private static String getCorrectOutput(Metadata m, String key,
+            boolean expand) {
+        List valList = m.getAllMetadata(key);
+        String var = (String) valList.get(0);
+        if (expand)
+            for (int j = 1; j < valList.size(); j++)
+                var += PathUtils.DELIMITER + (String) valList.get(j);
+        return var;
+    }
+   
+}
diff --git a/0.8.1-rc1/metadata/src/test/resources/copyandrewrite.test.conf b/0.8.1-rc1/metadata/src/test/resources/copyandrewrite.test.conf
new file mode 100644
index 0000000..4eb8348
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/resources/copyandrewrite.test.conf
@@ -0,0 +1,5 @@
+numRewriteFields=2
+rewriteField1=ProductType
+rewriteField2=FileLocation
+ProductType.pattern=NewProductType[ProductType]
+FileLocation.pattern=/new/loc/[FileLocation]
diff --git a/0.8.1-rc1/metadata/src/test/resources/extern-config.xml b/0.8.1-rc1/metadata/src/test/resources/extern-config.xml
new file mode 100644
index 0000000..6ae5184
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/resources/extern-config.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.txt 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.
+-->
+<!-- FIXME: change namespace URI? -->
+<cas:externextractor xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+
+	<!--  
+	    workingDir: specifies the directory that the external command line met extractor will
+	    be run in. 
+	    
+	    if workingDir is not specified, and if the external command line met extractor honors
+	    the workingDir contract (generating .met file in directory that it is called from), then 
+	    the .met file will be generated in /path/to/file's parent directory. Otherwise, if the
+	    external command let met extractor doesn't honor working dir, then all bets
+	    are off.
+	-->
+	<exec workingDir="">
+		<!--  this path can be absolute or relative -->
+		<!--  you can optionally specify envReplace tag (=true) 
+		      to turn on environment variable replacement
+		-->
+		<extractorBinPath>[TEST_PATH]/testExtractor</extractorBinPath>
+
+		<!--  make sure to use character entities if there are any weird
+			parameters here that would screw up the XML.
+			
+			args come after providing the file to this met extractor. So, in other
+			words, we assume that extractorBinPath &gt;file&lt; &lt;args...&gt;
+			
+			where the first parameter is always the file to extract metadata from,
+			and the remaining parameters are optional to provide to the underlying
+			met extractor.
+		-->
+		<args>
+			<arg isDataFile="true"/>
+			<arg isMetFile="true"/>
+			<arg>-Dtrue=always</arg>
+			<arg>foo</arg>
+			<arg>bar</arg>
+			<!--  you can optionally specify that you would like environment 
+			      variable replacement on a particular argument
+			      
+			      You can also optionally specify that the argument is a path
+			      and that you would like it to be treated as such using the
+			      isPath="true". If not specified, the path is treated as if
+			      isPath was specified as "false", and String.replaceAll("\\s", "\\\\ ")
+			      is not called. If called, all white spaces are replaced from the path
+			      (using the above regex), and replaced with the literal string
+			      "\ ".
+			-->
+			<arg envReplace="true" isPath="true">[HOME]/test boo</arg>
+		</args>
+	</exec>
+
+</cas:externextractor>
\ No newline at end of file
diff --git a/0.8.1-rc1/metadata/src/test/resources/met_extr_preconditions.xml b/0.8.1-rc1/metadata/src/test/resources/met_extr_preconditions.xml
new file mode 100644
index 0000000..82847e5
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/resources/met_extr_preconditions.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+    
+
+    <!-- Precondition Comparators -->
+    <bean id="PreconditionComparator" lazy-init="true" abstract="true" class="org.apache.oodt.cas.metadata.preconditions.PreConditionComparator"/>
+    
+    
+    <bean id="CheckThatDataFileSizeIsGreaterThanZero" lazy-init="true" parent="PreconditionComparator" class="org.apache.oodt.cas.metadata.preconditions.FileSizeComparator">
+        <property name="description" value="Check if the current data file size is greater than zero"/>        
+        <property name="compareItem">
+            <value type="java.lang.Long">0</value>
+        </property>
+        <property name="type" value="greater_than"/>
+    </bean>
+    
+    <bean id="CheckThatDataFileExists" lazy-init="true" parent="PreconditionComparator" class="org.apache.oodt.cas.metadata.preconditions.ExistanceCheckComparator">
+        <property name="description" value="Check if the current data file exists"/>        
+        <property name="compareItem">
+            <value type="java.lang.Boolean">true</value>
+        </property>
+        <property name="type" value="equal_to"/>    
+    </bean>
+
+    <bean id="CheckDataFileMimeType" lazy-init="true" parent="PreconditionComparator" class="org.apache.oodt.cas.metadata.preconditions.MimeTypeComparator">
+        <property name="description" value="Check that data file mime type matches the specified mime type"/>        
+        <property name="compareItem">
+            <value type="java.lang.String">application/xml</value>
+        </property>
+        <property name="type" value="equal_to"/>   
+        <property name="mimeTypeRepo" value="./src/testdata/tika-mimetypes.xml"/>
+        <property name="useMagic" value="true"/> 
+    </bean>
+
+</beans>
\ No newline at end of file
diff --git a/0.8.1-rc1/metadata/src/test/resources/product-type-patterns-2.xml b/0.8.1-rc1/metadata/src/test/resources/product-type-patterns-2.xml
new file mode 100644
index 0000000..0eb67a0
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/resources/product-type-patterns-2.xml
@@ -0,0 +1,12 @@
+<config>
+    <!-- <element> MUST be defined before <product-type> so their patterns can be resolved -->
+    <!-- name MUST be an element defined in elements.xml (also only upper and lower case alpha chars) -->
+    <!-- regexp MUST be valid input to java.util.regex.Pattern.compile() -->
+    <element name="ISBN" regexp="[0-9]{10}"/>
+    <element name="Page" regexp="[0-9]*"/>
+
+    <!-- name MUST be a ProductType name defined in product-types.xml -->
+    <!-- metadata elements inside brackets MUST be mapped to the ProductType, as defined in product-type-element-map.xml -->
+    <product-type name="Book" template="book-[ISBN].txt"/>
+    <product-type name="BookPage" template="page-[Page]-[ISBN].txt"/>
+</config>
diff --git a/0.8.1-rc1/metadata/src/test/resources/product-type-patterns.xml b/0.8.1-rc1/metadata/src/test/resources/product-type-patterns.xml
new file mode 100644
index 0000000..ceedf81
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/resources/product-type-patterns.xml
@@ -0,0 +1,12 @@
+<config>
+    <!-- <element> MUST be defined before <product-type> so their patterns can be resolved -->
+    <!-- name MUST be an element defined in elements.xml (also only upper and lower case alpha chars) -->
+    <!-- regexp MUST be valid input to java.util.regex.Pattern.compile() -->
+    <element name="ISBN" regexp="[0-9]{10}"/>
+    <element name="Page" regexp="[0-9]*"/>
+
+    <!-- name MUST be a ProductType name defined in product-types.xml -->
+    <!-- metadata elements inside brackets MUST be mapped to the ProductType, as defined in product-type-element-map.xml -->
+    <product-type name="Book" template="book-[ISBN].txt"/>
+    <product-type name="BookPage" template="page-[ISBN]-[Page].txt"/>
+</config>
diff --git a/0.8.1-rc1/metadata/src/test/resources/samplemet.xml b/0.8.1-rc1/metadata/src/test/resources/samplemet.xml
new file mode 100644
index 0000000..b8e009b
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/resources/samplemet.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- FIXME: change namespace URI? -->
+<cas:metadata xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+ <keyval>
+   <key>Filename</key>
+   <val>testfile.txt</val>
+ </keyval>
+ <keyval>
+   <key>FileLocation</key>
+   <val>[EXTRACT_FILE_LOC]</val>
+ </keyval>
+ <keyval>
+   <key>ProductType</key>
+   <val>GenericFile</val>
+ </keyval>
+</cas:metadata>
diff --git a/0.8.1-rc1/metadata/src/test/resources/testExtractor b/0.8.1-rc1/metadata/src/test/resources/testExtractor
new file mode 100755
index 0000000..fc5ab36
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/resources/testExtractor
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+export PROD_FILE=$1
+export MET_FILE=$2
+
+set PROD_FILE
+set MET_FILE
+
+#echo "PWD IS $PWD and CWD is $CWD"
+#echo "product file: $PROD_FILE, met file: $MET_FILE"
+
+export PROD_DIR=`dirname $PROD_FILE`
+set PROD_DIR
+export MET_DIR=`dirname $MET_FILE`
+set PROD_DIR
+
+
+if [ $PROD_DIR = $MET_DIR ]; then
+	# just copy the sample metadata
+	cp <TEST_SAMPLE_MET_PATH> $MET_FILE
+fi
diff --git a/0.8.1-rc1/metadata/src/test/resources/testfile.txt b/0.8.1-rc1/metadata/src/test/resources/testfile.txt
new file mode 100644
index 0000000..6de7b8c
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/resources/testfile.txt
@@ -0,0 +1 @@
+This is a test file.
diff --git a/0.8.1-rc1/metadata/src/test/resources/testfile2.txt b/0.8.1-rc1/metadata/src/test/resources/testfile2.txt
new file mode 100644
index 0000000..6de7b8c
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/resources/testfile2.txt
@@ -0,0 +1 @@
+This is a test file.
diff --git a/0.8.1-rc1/metadata/src/test/resources/testfile2.txt.met b/0.8.1-rc1/metadata/src/test/resources/testfile2.txt.met
new file mode 100644
index 0000000..b8e009b
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/resources/testfile2.txt.met
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- FIXME: change namespace URI? -->
+<cas:metadata xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+ <keyval>
+   <key>Filename</key>
+   <val>testfile.txt</val>
+ </keyval>
+ <keyval>
+   <key>FileLocation</key>
+   <val>[EXTRACT_FILE_LOC]</val>
+ </keyval>
+ <keyval>
+   <key>ProductType</key>
+   <val>GenericFile</val>
+ </keyval>
+</cas:metadata>
diff --git a/0.8.1-rc1/metadata/src/test/resources/tika-mimetypes.xml b/0.8.1-rc1/metadata/src/test/resources/tika-mimetypes.xml
new file mode 100644
index 0000000..9935b5c
--- /dev/null
+++ b/0.8.1-rc1/metadata/src/test/resources/tika-mimetypes.xml
@@ -0,0 +1,5928 @@
+<?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.
+-->
+<!--
+  Description: This xml file defines the valid mime types used by Tika.
+  The mime type data within this file is based on information from various
+  sources like Apache Nutch, Apache HTTP Server, the file(1) command, etc.
+
+  Notes:
+   * Tika supports a wider range of match types than Freedesktop does
+   * Glob patterns must be unique, if there's a clash assign to the most
+     popular format
+   * The main mime type should be the canonical one, use aliases for any
+     other widely used forms
+   * Where there's a hierarchy in the types, list it via a parent
+   * Highly specific magic matches get a high priority
+   * General magic matches which could trigger a false-positive need
+     a low one
+   * The priority for containers normally need to be higher than for
+     the things they contain, so they don't accidently get detected
+     as what's in them
+   * For logic too complex to be expressed in a magic match, do the best
+     you can here, then provide a Custom Detector for the rest
+-->
+<mime-info>
+
+    <mime-type type="test/example">
+        <glob pattern="*.testexample"/>
+    </mime-type>
+    <mime-type type="application/activemessage"/>
+    <mime-type type="application/andrew-inset">
+        <glob pattern="*.ez"/>
+    </mime-type>
+    <mime-type type="application/applefile"/>
+    <mime-type type="application/applixware">
+        <glob pattern="*.aw"/>
+    </mime-type>
+
+    <mime-type type="application/atom+xml">
+        <root-XML localName="feed" namespaceURI="http://purl.org/atom/ns#"/>
+        <root-XML localName="feed" namespaceURI="http://www.w3.org/2005/Atom"/>
+        <glob pattern="*.atom"/>
+    </mime-type>
+
+    <mime-type type="application/atomcat+xml">
+        <glob pattern="*.atomcat"/>
+    </mime-type>
+    <mime-type type="application/atomicmail"/>
+    <mime-type type="application/atomsvc+xml">
+        <glob pattern="*.atomsvc"/>
+    </mime-type>
+    <mime-type type="application/auth-policy+xml"/>
+    <mime-type type="application/batch-smtp"/>
+    <mime-type type="application/beep+xml"/>
+
+    <mime-type type="application/bizagi-modeler">
+        <_comment>BizAgi Process Modeler</_comment>
+        <sub-class-of type="application/zip"/>
+        <glob pattern="*.bpm"/>
+    </mime-type>
+
+    <mime-type type="application/cals-1840"/>
+    <mime-type type="application/ccxml+xml">
+        <glob pattern="*.ccxml"/>
+    </mime-type>
+    <mime-type type="application/cea-2018+xml"/>
+    <mime-type type="application/cellml+xml"/>
+    <mime-type type="application/cnrp+xml"/>
+    <mime-type type="application/commonground"/>
+    <mime-type type="application/conference-info+xml"/>
+    <mime-type type="application/cpl+xml"/>
+    <mime-type type="application/csta+xml"/>
+    <mime-type type="application/cstadata+xml"/>
+    <mime-type type="application/cu-seeme">
+        <glob pattern="*.cu"/>
+    </mime-type>
+    <mime-type type="application/cybercash"/>
+    <mime-type type="application/davmount+xml">
+        <glob pattern="*.davmount"/>
+    </mime-type>
+    <mime-type type="application/dca-rft"/>
+    <mime-type type="application/dec-dx"/>
+    <mime-type type="application/dialog-info+xml"/>
+    <mime-type type="application/dicom"/>
+
+    <mime-type type="application/dita+xml">
+        <sub-class-of type="application/xml"/>
+        <_comment>Darwin Information Typing Architecture</_comment>
+    </mime-type>
+
+    <mime-type type="application/dita+xml;format=map">
+        <sub-class-of type="application/dita+xml"/>
+        <_comment>DITA Map</_comment>
+        <root-XML localName="map"/>
+        <root-XML localName="map" namespaceURI="http://docs.oasis-open.org/namespace"/>
+        <glob pattern="*.ditamap"/>
+    </mime-type>
+    <mime-type type="application/dita+xml;format=topic">
+        <sub-class-of type="application/dita+xml"/>
+        <_comment>DITA Topic</_comment>
+        <root-XML localName="topic"/>
+        <root-XML localName="topic" namespaceURI="http://docs.oasis-open.org/namespace"/>
+        <!-- Topic is the default, Task and Concept are specialisations -->
+        <glob pattern="*.dita"/>
+    </mime-type>
+    <mime-type type="application/dita+xml;format=task">
+        <sub-class-of type="application/dita+xml;format=task"/>
+        <_comment>DITA Task Topic</_comment>
+        <root-XML localName="task"/>
+        <root-XML localName="task" namespaceURI="http://docs.oasis-open.org/namespace"/>
+    </mime-type>
+    <mime-type type="application/dita+xml;format=concept">
+        <sub-class-of type="application/dita+xml;format=topic"/>
+        <_comment>DITA Concept Topic</_comment>
+        <root-XML localName="concept"/>
+        <root-XML localName="concept" namespaceURI="http://docs.oasis-open.org/namespace"/>
+    </mime-type>
+    <mime-type type="application/dita+xml;format=val">
+        <sub-class-of type="application/dita+xml"/>
+        <_comment>DITA Conditional Processing Profile</_comment>
+        <root-XML localName="val"/>
+        <root-XML localName="val" namespaceURI="http://docs.oasis-open.org/namespace"/>
+        <glob pattern="*.ditaval"/>
+    </mime-type>
+
+    <mime-type type="application/dns"/>
+    <mime-type type="application/dvcs"/>
+    <mime-type type="application/ecmascript">
+        <glob pattern="*.ecma"/>
+    </mime-type>
+    <mime-type type="application/edi-consent"/>
+    <mime-type type="application/edi-x12"/>
+    <mime-type type="application/edifact"/>
+    <mime-type type="application/emma+xml">
+        <glob pattern="*.emma"/>
+    </mime-type>
+    <mime-type type="application/epp+xml"/>
+
+    <mime-type type="application/epub+zip">
+        <acronym>EPUB</acronym>
+        <_comment>Electronic Publication</_comment>
+        <magic priority="50">
+            <match value="PK\003\004" type="string" offset="0">
+                <match value="mimetypeapplication/epub+zip" type="string" offset="30"/>
+            </match>
+        </magic>
+        <glob pattern="*.epub"/>
+    </mime-type>
+
+    <mime-type type="application/eshop"/>
+    <mime-type type="application/example"/>
+    <mime-type type="application/fastinfoset"/>
+    <mime-type type="application/fastsoap"/>
+
+    <mime-type type="application/fits">
+        <acronym>FITS</acronym>
+        <_comment>Flexible Image Transport System</_comment>
+        <tika:link>http://www.digitalpreservation.gov/formats/fdd/fdd000317.shtml</tika:link>
+        <magic priority="50">
+            <match value="SIMPLE  =                    T" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.fits"/>
+        <glob pattern="*.fit"/>
+        <glob pattern="*.fts"/>
+    </mime-type>
+
+    <mime-type type="application/font-tdpfr">
+        <glob pattern="*.pfr"/>
+    </mime-type>
+    <mime-type type="application/h224"/>
+    <mime-type type="application/http"/>
+    <mime-type type="application/hyperstudio">
+        <glob pattern="*.stk"/>
+    </mime-type>
+    <mime-type type="application/ibe-key-request+xml"/>
+    <mime-type type="application/ibe-pkg-reply+xml"/>
+    <mime-type type="application/ibe-pp-data"/>
+    <mime-type type="application/iges"/>
+
+    <mime-type type="application/illustrator">
+        <acronym>AI</acronym>
+        <_comment>Adobe Illustrator Artwork</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/Adobe_Illustrator_Artwork</tika:link>
+        <glob pattern="*.ai"/>]
+        <sub-class-of type="application/postscript"/>
+    </mime-type>
+
+    <mime-type type="application/im-iscomposing+xml"/>
+    <mime-type type="application/index"/>
+    <mime-type type="application/index.cmd"/>
+    <mime-type type="application/index.obj"/>
+    <mime-type type="application/index.response"/>
+    <mime-type type="application/index.vnd"/>
+    <mime-type type="application/iotp"/>
+    <mime-type type="application/ipp"/>
+    <mime-type type="application/isup"/>
+
+    <mime-type type="application/java-archive">
+        <_comment>Java Archive</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/.jar</tika:link>
+        <tika:uti>com.sun.java-archive</tika:uti>
+        <sub-class-of type="application/zip"/>
+        <glob pattern="*.jar"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.android.package-archive">
+        <sub-class-of type="application/java-archive"/>
+        <glob pattern="*.apk"/>
+    </mime-type>
+    <mime-type type="application/x-tika-java-enterprise-archive">
+        <sub-class-of type="application/java-archive"/>
+        <glob pattern="*.ear"/>
+    </mime-type>
+    <mime-type type="application/x-tika-java-web-archive">
+        <sub-class-of type="application/java-archive"/>
+        <glob pattern="*.war"/>
+    </mime-type>
+
+    <mime-type type="application/x-tika-unix-dump"/>
+
+    <mime-type type="application/java-serialized-object">
+        <glob pattern="*.ser"/>
+    </mime-type>
+
+    <mime-type type="application/javascript">
+        <alias type="application/x-javascript"/>
+        <alias type="text/javascript"/>
+        <sub-class-of type="text/plain"/>
+        <_comment>JavaScript Source Code</_comment>
+        <glob pattern="*.js"/>
+    </mime-type>
+
+    <mime-type type="application/json">
+        <sub-class-of type="application/javascript"/>
+        <glob pattern="*.json"/>
+    </mime-type>
+
+    <mime-type type="application/java-vm">
+        <_comment>Java Class File</_comment>
+        <alias type="application/x-java-vm"/>
+        <alias type="application/x-java"/>
+        <magic priority="40">
+            <match value="0xcafebabe" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.class"/>
+    </mime-type>
+
+    <mime-type type="application/x-java-jnilib">
+        <_comment>Java Native Library for OSX</_comment>
+        <magic priority="50">
+            <match value="0xcafebabe" type="string" offset="0">
+                <match value="0xfeedface" type="string" offset="4096"/>
+                <match value="0xfeedfacf" type="string" offset="4096"/>
+                <match value="0xcefaedfe" type="string" offset="4096"/>
+                <match value="0xcffaedfe" type="string" offset="4096"/>
+            </match>
+        </magic>
+        <glob pattern="*.jnilib"/>
+    </mime-type>
+
+    <mime-type type="application/kpml-request+xml"/>
+    <mime-type type="application/kpml-response+xml"/>
+    <mime-type type="application/lost+xml">
+        <glob pattern="*.lostxml"/>
+    </mime-type>
+
+    <mime-type type="application/mac-binhex40">
+        <alias type="application/mac-binhex"/>
+        <alias type="application/binhex"/>
+        <magic priority="50">
+            <match value="must\ be\ converted\ with\ BinHex" type="string" offset="11"/>
+        </magic>
+        <glob pattern="*.hqx"/>
+    </mime-type>
+
+    <mime-type type="application/mac-compactpro">
+        <glob pattern="*.cpt"/>
+    </mime-type>
+
+    <mime-type type="application/macwriteii"/>
+    <mime-type type="application/marc">
+        <glob pattern="*.mrc"/>
+    </mime-type>
+    <mime-type type="application/mathematica">
+        <glob pattern="*.ma"/>
+        <glob pattern="*.nb"/>
+        <glob pattern="*.mb"/>
+    </mime-type>
+    <mime-type type="application/mathml+xml">
+        <glob pattern="*.mathml"/>
+    </mime-type>
+    <mime-type type="application/mbms-associated-procedure-description+xml"/>
+    <mime-type type="application/mbms-deregister+xml"/>
+    <mime-type type="application/mbms-envelope+xml"/>
+    <mime-type type="application/mbms-msk+xml"/>
+    <mime-type type="application/mbms-msk-response+xml"/>
+    <mime-type type="application/mbms-protection-description+xml"/>
+    <mime-type type="application/mbms-reception-report+xml"/>
+    <mime-type type="application/mbms-register+xml"/>
+    <mime-type type="application/mbms-register-response+xml"/>
+    <mime-type type="application/mbms-user-service-description+xml"/>
+    <mime-type type="application/mbox">
+        <sub-class-of type="text/plain"/>
+        <glob pattern="*.mbox"/>
+    </mime-type>
+    <mime-type type="application/media_control+xml"/>
+    <mime-type type="application/mediaservercontrol+xml">
+        <glob pattern="*.mscml"/>
+    </mime-type>
+    <mime-type type="application/mikey"/>
+    <mime-type type="application/moss-keys"/>
+    <mime-type type="application/moss-signature"/>
+    <mime-type type="application/mosskey-data"/>
+    <mime-type type="application/mosskey-request"/>
+    <mime-type type="application/mp4">
+        <glob pattern="*.mp4s"/>
+    </mime-type>
+    <mime-type type="application/mpeg4-generic"/>
+    <mime-type type="application/mpeg4-iod"/>
+    <mime-type type="application/mpeg4-iod-xmt"/>
+
+    <!-- http://www.iana.org/assignments/media-types/application/msword -->
+    <mime-type type="application/msword">
+        <!-- Use DefaultDetector / org.apache.tika.parser.microsoft.POIFSContainerDetector for more reliable detection of OLE2 documents -->
+        <alias type="application/vnd.ms-word"/>
+        <_comment>Microsoft Word Document</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/.doc</tika:link>
+        <tika:uti>com.microsoft.word.doc</tika:uti>
+        <magic priority="50">
+            <match value="Microsoft\ Word\ 6.0\ Document" type="string" offset="2080"/>
+            <match value="Documento\ Microsoft\ Word\ 6" type="string" offset="2080"/>
+            <match value="MSWordDoc" type="string" offset="2112"/>
+            <match value="0x31be0000" type="big32" offset="0"/>
+            <match value="PO^Q`" type="string" offset="0"/>
+            <match value="\376\067\0\043" type="string" offset="0"/>
+            <match value="\333\245-\0\0\0" type="string" offset="0"/>
+            <match value="\224\246\056" type="string" offset="0"/>
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="W\x00o\x00r\x00d\x00D\x00o\x00c\x00u\x00m\x00e\x00n\x00t" type="string" offset="1152:4096" />
+            </match>
+        </magic>
+        <glob pattern="*.doc"/>
+        <glob pattern="*.dot"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/msword2">
+        <!-- Pre-OLE2, not a subtype of application/x-tika-msoffice -->
+        <_comment>Microsoft Word 2 Document</_comment>
+        <magic priority="50">
+            <match value="0x9ba5" type="string" />
+            <match value="0xdba5" type="string" />
+        </magic>
+    </mime-type>
+    <mime-type type="application/msword5">
+        <!-- Pre-OLE2, not a subtype of application/x-tika-msoffice -->
+        <_comment>Microsoft Word 5 Document</_comment>
+        <magic priority="50">
+            <match value="0xfe37" type="string" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/mxf">
+        <glob pattern="*.mxf"/>
+    </mime-type>
+    <mime-type type="application/nasdata"/>
+    <mime-type type="application/news-checkgroups"/>
+    <mime-type type="application/news-groupinfo"/>
+    <mime-type type="application/news-transmission"/>
+    <mime-type type="application/nss"/>
+    <mime-type type="application/ocsp-request"/>
+    <mime-type type="application/ocsp-response"/>
+
+    <mime-type type="application/octet-stream">
+        <magic priority="50">
+            <match value="#\ This\ is\ a\ shell\ archive" type="string" offset="10"/>
+            <match value="\037\036" type="string" offset="0"/>
+            <match value="017437" type="host16" offset="0"/>
+            <match value="0x1fff" type="host16" offset="0"/>
+            <match value="\377\037" type="string" offset="0"/>
+            <match value="0145405" type="host16" offset="0"/>
+        </magic>
+        <glob pattern="*.bin"/>
+        <glob pattern="*.dms"/>
+        <glob pattern="*.lha"/>
+        <glob pattern="*.lrf"/>
+        <glob pattern="*.lzh"/>
+        <glob pattern="*.so"/>
+        <glob pattern="*.dist"/>
+        <glob pattern="*.distz"/>
+        <glob pattern="*.pkg"/>
+        <glob pattern="*.bpk"/>
+        <glob pattern="*.dump"/>
+        <glob pattern="*.elc"/>
+        <glob pattern="*.deploy"/>
+    </mime-type>
+
+    <mime-type type="application/oda">
+        <glob pattern="*.oda"/>
+    </mime-type>
+    <mime-type type="application/oebps-package+xml">
+        <glob pattern="*.opf"/>
+    </mime-type>
+
+    <mime-type type="application/ogg">
+        <alias type="application/x-ogg"/>
+        <magic priority="50">
+            <match value="OggS" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.ogx"/>
+    </mime-type>
+    <mime-type type="application/kate">
+        <sub-class-of type="application/ogg"/>
+    </mime-type>
+
+    <mime-type type="application/onenote">
+        <glob pattern="*.onetoc"/>
+        <glob pattern="*.onetoc2"/>
+        <glob pattern="*.onetmp"/>
+        <glob pattern="*.onepkg"/>
+    </mime-type>
+    <mime-type type="application/parityfec"/>
+    <mime-type type="application/patch-ops-error+xml">
+        <glob pattern="*.xer"/>
+    </mime-type>
+
+    <mime-type type="application/pdf">
+        <alias type="application/x-pdf"/>
+        <acronym>PDF</acronym>
+        <_comment>Portable Document Format</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/PDF</tika:link>
+        <tika:link>http://www.adobe.com/devnet/pdf/pdf_reference_archive.html</tika:link>
+        <tika:uti>com.adobe.pdf</tika:uti>
+        <magic priority="50">
+            <match value="%PDF-" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.pdf"/>
+    </mime-type>
+
+    <mime-type type="application/pgp-encrypted">
+        <alias type="application/pgp"/>
+        <glob pattern="*.pgp"/>
+    </mime-type>
+
+    <mime-type type="application/pgp-keys"/>
+
+    <mime-type type="application/pgp-signature">
+        <glob pattern="*.asc"/>
+        <glob pattern="*.sig"/>
+    </mime-type>
+
+    <mime-type type="application/pics-rules">
+        <glob pattern="*.prf"/>
+    </mime-type>
+    <mime-type type="application/pidf+xml"/>
+    <mime-type type="application/pidf-diff+xml"/>
+    <mime-type type="application/pkcs10">
+        <glob pattern="*.p10"/>
+    </mime-type>
+
+    <mime-type type="application/pkcs7-mime">
+        <glob pattern="*.p7m"/>
+        <glob pattern="*.p7c"/>
+    </mime-type>
+
+    <mime-type type="application/pkcs7-signature">
+        <glob pattern="*.p7s"/>
+        <magic priority="50">
+            <match value="-----BEGIN PKCS7" type="string" offset="0"/>
+            <match value="0x3082FFFF06092a864886f70d0107FFa0" type="string"
+                   mask="0xFFFF0000FFFFFFFFFFFFFFFFFFFF00FF" offset="0"/>
+            <match value="0x308006092a864886f70d0107FFa0" type="string"
+                   mask="0xFFFFFFFFFFFFFFFFFFFFFFFF00FF" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/pkix-cert">
+        <glob pattern="*.cer"/>
+    </mime-type>
+    <mime-type type="application/pkix-crl">
+        <glob pattern="*.crl"/>
+    </mime-type>
+    <mime-type type="application/pkix-pkipath">
+        <glob pattern="*.pkipath"/>
+    </mime-type>
+    <mime-type type="application/pkixcmp">
+        <glob pattern="*.pki"/>
+    </mime-type>
+    <mime-type type="application/pls+xml">
+        <glob pattern="*.pls"/>
+    </mime-type>
+    <mime-type type="application/poc-settings+xml"/>
+
+    <mime-type type="application/postscript">
+        <_comment>PostScript</_comment>
+        <magic priority="50">
+            <match value="%!" type="string" offset="0" />
+            <match value="\004%!" type="string" offset="0" />
+            <!-- Windows format EPS -->
+            <match value="0xc5d0d3c6" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.ps"/>
+        <glob pattern="*.eps"/>
+        <glob pattern="*.epsf"/>
+        <glob pattern="*.epsi"/>
+    </mime-type>
+
+    <mime-type type="application/prs.alvestrand.titrax-sheet"/>
+    <mime-type type="application/prs.cww">
+        <glob pattern="*.cww"/>
+    </mime-type>
+    <mime-type type="application/prs.nprend"/>
+    <mime-type type="application/prs.plucker"/>
+    <mime-type type="application/qsig"/>
+
+    <mime-type type="application/rdf+xml">
+        <root-XML localName="RDF"/>
+        <root-XML localName="RDF" namespaceURI="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
+        <sub-class-of type="application/xml"/>
+        <acronym>RDF/XML</acronym>
+        <_comment>XML syntax for RDF graphs</_comment>
+        <glob pattern="*.rdf"/>
+        <glob pattern="*.owl"/>
+        <glob pattern="^rdf$" isregex="true"/>
+        <glob pattern="^owl$" isregex="true"/>
+        <glob pattern="*.xmp"/>
+    </mime-type>
+
+    <mime-type type="application/reginfo+xml">
+        <glob pattern="*.rif"/>
+    </mime-type>
+    <mime-type type="application/relax-ng-compact-syntax">
+        <sub-class-of type="text/plain"/>
+        <glob pattern="*.rnc"/>
+    </mime-type>
+    <mime-type type="application/remote-printing"/>
+    <mime-type type="application/resource-lists+xml">
+        <glob pattern="*.rl"/>
+    </mime-type>
+    <mime-type type="application/resource-lists-diff+xml">
+        <glob pattern="*.rld"/>
+    </mime-type>
+    <mime-type type="application/riscos"/>
+    <mime-type type="application/rlmi+xml"/>
+    <mime-type type="application/rls-services+xml">
+        <glob pattern="*.rs"/>
+    </mime-type>
+    <mime-type type="application/rsd+xml">
+        <glob pattern="*.rsd"/>
+    </mime-type>
+
+    <mime-type type="application/rss+xml">
+        <alias type="text/rss"/>
+        <root-XML localName="rss"/>
+        <root-XML namespaceURI="http://purl.org/rss/1.0/"/>
+        <glob pattern="*.rss"/>
+    </mime-type>
+
+    <mime-type type="application/rtf">
+        <_comment>Rich Text Format File</_comment>
+        <alias type="text/rtf"/>
+        <magic priority="50">
+            <match value="{\\rtf" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.rtf"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="application/rtx"/>
+    <mime-type type="application/samlassertion+xml"/>
+    <mime-type type="application/samlmetadata+xml"/>
+    <mime-type type="application/sbml+xml">
+        <glob pattern="*.sbml"/>
+    </mime-type>
+    <mime-type type="application/scvp-cv-request">
+        <glob pattern="*.scq"/>
+    </mime-type>
+    <mime-type type="application/scvp-cv-response">
+        <glob pattern="*.scs"/>
+    </mime-type>
+    <mime-type type="application/scvp-vp-request">
+        <glob pattern="*.spq"/>
+    </mime-type>
+    <mime-type type="application/scvp-vp-response">
+        <glob pattern="*.spp"/>
+    </mime-type>
+    <mime-type type="application/sdp">
+        <glob pattern="*.sdp"/>
+    </mime-type>
+    <mime-type type="application/set-payment"/>
+    <mime-type type="application/set-payment-initiation">
+        <glob pattern="*.setpay"/>
+    </mime-type>
+    <mime-type type="application/set-registration"/>
+    <mime-type type="application/set-registration-initiation">
+        <glob pattern="*.setreg"/>
+    </mime-type>
+    <mime-type type="application/sgml"/>
+    <mime-type type="application/sgml-open-catalog"/>
+    <mime-type type="application/shf+xml">
+        <glob pattern="*.shf"/>
+    </mime-type>
+    <mime-type type="application/sieve"/>
+    <mime-type type="application/simple-filter+xml"/>
+    <mime-type type="application/simple-message-summary"/>
+    <mime-type type="application/simplesymbolcontainer"/>
+    <mime-type type="application/slate"/>
+
+    <mime-type type="application/smil+xml">
+        <alias type="application/smil"/>
+        <_comment>SMIL Multimedia</_comment>
+        <glob pattern="*.smi"/>
+        <glob pattern="*.smil"/>
+        <glob pattern="*.sml"/>
+    </mime-type>
+
+    <mime-type type="application/soap+fastinfoset"/>
+    <mime-type type="application/soap+xml"/>
+
+    <mime-type type="application/sldworks">
+        <_comment>SolidWorks CAD program</_comment>
+        <glob pattern="*.sldprt" />
+        <glob pattern="*.sldasm" />
+        <glob pattern="*.slddrw" />
+        <sub-class-of type="application/x-tika-msoffice" />
+    </mime-type>
+
+    <mime-type type="application/sparql-query">
+        <glob pattern="*.rq"/>
+    </mime-type>
+    <mime-type type="application/sparql-results+xml">
+        <glob pattern="*.srx"/>
+    </mime-type>
+    <mime-type type="application/spirits-event+xml"/>
+    <mime-type type="application/srgs">
+        <glob pattern="*.gram"/>
+    </mime-type>
+    <mime-type type="application/srgs+xml">
+        <glob pattern="*.grxml"/>
+    </mime-type>
+    <mime-type type="application/ssml+xml">
+        <glob pattern="*.ssml"/>
+    </mime-type>
+    <mime-type type="application/timestamp-query"/>
+    <mime-type type="application/timestamp-reply"/>
+    <mime-type type="application/tve-trigger"/>
+    <mime-type type="application/ulpfec"/>
+    <mime-type type="application/vemmi"/>
+    <mime-type type="application/vividence.scriptfile"/>
+    <mime-type type="application/vnd.3gpp.bsf+xml"/>
+    <mime-type type="application/vnd.3gpp.pic-bw-large">
+        <glob pattern="*.plb"/>
+    </mime-type>
+    <mime-type type="application/vnd.3gpp.pic-bw-small">
+        <glob pattern="*.psb"/>
+    </mime-type>
+    <mime-type type="application/vnd.3gpp.pic-bw-var">
+        <glob pattern="*.pvb"/>
+    </mime-type>
+    <mime-type type="application/vnd.3gpp.sms"/>
+    <mime-type type="application/vnd.3gpp2.bcmcsinfo+xml"/>
+    <mime-type type="application/vnd.3gpp2.sms"/>
+    <mime-type type="application/vnd.3gpp2.tcap">
+        <glob pattern="*.tcap"/>
+    </mime-type>
+    <mime-type type="application/vnd.3m.post-it-notes">
+        <glob pattern="*.pwn"/>
+    </mime-type>
+    <mime-type type="application/vnd.accpac.simply.aso">
+        <glob pattern="*.aso"/>
+    </mime-type>
+    <mime-type type="application/vnd.accpac.simply.imp">
+        <glob pattern="*.imp"/>
+    </mime-type>
+    <mime-type type="application/vnd.acucobol">
+        <glob pattern="*.acu"/>
+    </mime-type>
+    <mime-type type="application/vnd.acucorp">
+        <glob pattern="*.atc"/>
+        <glob pattern="*.acutc"/>
+    </mime-type>
+    <mime-type type="application/vnd.adobe.air-application-installer-package+zip">
+        <glob pattern="*.air"/>
+    </mime-type>
+    <mime-type type="application/vnd.adobe.aftereffects.project">
+        <glob pattern="*.aep"/>
+    </mime-type>
+    <mime-type type="application/vnd.adobe.aftereffects.template">
+        <glob pattern="*.aet"/>
+    </mime-type>
+    <mime-type type="application/vnd.adobe.xdp+xml">
+        <glob pattern="*.xdp"/>
+    </mime-type>
+    <mime-type type="application/vnd.adobe.xfdf">
+        <glob pattern="*.xfdf"/>
+    </mime-type>
+    <mime-type type="application/vnd.aether.imp"/>
+    <mime-type type="application/vnd.airzip.filesecure.azf">
+        <glob pattern="*.azf"/>
+    </mime-type>
+    <mime-type type="application/vnd.airzip.filesecure.azs">
+        <glob pattern="*.azs"/>
+    </mime-type>
+    <mime-type type="application/vnd.amazon.ebook">
+        <glob pattern="*.azw"/>
+    </mime-type>
+    <mime-type type="application/vnd.americandynamics.acc">
+        <glob pattern="*.acc"/>
+    </mime-type>
+    <mime-type type="application/vnd.amiga.ami">
+        <glob pattern="*.ami"/>
+    </mime-type>
+    <mime-type type="application/vnd.anser-web-certificate-issue-initiation">
+        <glob pattern="*.cii"/>
+    </mime-type>
+    <mime-type type="application/vnd.anser-web-funds-transfer-initiation">
+        <glob pattern="*.fti"/>
+    </mime-type>
+    <mime-type type="application/vnd.antix.game-component">
+        <glob pattern="*.atx"/>
+    </mime-type>
+    <mime-type type="application/vnd.apple.installer+xml">
+        <glob pattern="*.mpkg"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.apple.iwork">
+        <sub-class-of type="application/zip"/>
+    </mime-type>
+    <mime-type type="application/vnd.apple.keynote">
+        <root-XML localName="presentation" namespaceURI="http://developer.apple.com/namespaces/keynote2" />
+        <sub-class-of type="application/vnd.apple.iwork" />
+        <glob pattern="*.key"/>
+    </mime-type>
+    <mime-type type="application/vnd.apple.pages">
+        <root-XML localName="document" namespaceURI="http://developer.apple.com/namespaces/sl" />
+        <sub-class-of type="application/vnd.apple.iwork" />
+        <glob pattern="*.pages"/>
+    </mime-type>
+    <mime-type type="application/vnd.apple.numbers">
+        <root-XML localName="document" namespaceURI="http://developer.apple.com/namespaces/ls" />
+        <sub-class-of type="application/vnd.apple.iwork" />
+        <glob pattern="*.numbers"/>
+    </mime-type>
+    <mime-type type="application/x-tika-iworks-protected">
+        <sub-class-of type="application/vnd.apple.iwork" />
+        <_comment>Password Protected iWorks File</_comment>
+    </mime-type>
+
+    <mime-type type="application/vnd.arastra.swi">
+        <glob pattern="*.swi"/>
+    </mime-type>
+    <mime-type type="application/vnd.audiograph"/>
+    <mime-type type="application/vnd.autopackage"/>
+    <mime-type type="application/vnd.avistar+xml"/>
+    <mime-type type="application/vnd.blueice.multipass">
+        <glob pattern="*.mpm"/>
+    </mime-type>
+    <mime-type type="application/vnd.bluetooth.ep.oob"/>
+    <mime-type type="application/vnd.bmi">
+        <glob pattern="*.bmi"/>
+    </mime-type>
+    <mime-type type="application/vnd.businessobjects">
+        <glob pattern="*.rep"/>
+    </mime-type>
+    <mime-type type="application/vnd.cab-jscript"/>
+    <mime-type type="application/vnd.canon-cpdl"/>
+    <mime-type type="application/vnd.canon-lips"/>
+    <mime-type type="application/vnd.cendio.thinlinc.clientconf"/>
+    <mime-type type="application/vnd.chemdraw+xml">
+        <glob pattern="*.cdxml"/>
+    </mime-type>
+    <mime-type type="application/vnd.chipnuts.karaoke-mmd">
+        <glob pattern="*.mmd"/>
+    </mime-type>
+    <mime-type type="application/vnd.cinderella">
+        <glob pattern="*.cdy"/>
+    </mime-type>
+    <mime-type type="application/vnd.cirpack.isdn-ext"/>
+    <mime-type type="application/vnd.claymore">
+        <glob pattern="*.cla"/>
+    </mime-type>
+    <mime-type type="application/vnd.clonk.c4group">
+        <glob pattern="*.c4g"/>
+        <glob pattern="*.c4d"/>
+        <glob pattern="*.c4f"/>
+        <glob pattern="*.c4p"/>
+        <glob pattern="*.c4u"/>
+    </mime-type>
+    <mime-type type="application/vnd.commerce-battelle"/>
+    <mime-type type="application/vnd.commonspace">
+        <glob pattern="*.csp"/>
+    </mime-type>
+    <mime-type type="application/vnd.contact.cmsg">
+        <glob pattern="*.cdbcmsg"/>
+    </mime-type>
+    <mime-type type="application/vnd.cosmocaller">
+        <glob pattern="*.cmc"/>
+    </mime-type>
+    <mime-type type="application/vnd.crick.clicker">
+        <glob pattern="*.clkx"/>
+    </mime-type>
+    <mime-type type="application/vnd.crick.clicker.keyboard">
+        <glob pattern="*.clkk"/>
+    </mime-type>
+    <mime-type type="application/vnd.crick.clicker.palette">
+        <glob pattern="*.clkp"/>
+    </mime-type>
+    <mime-type type="application/vnd.crick.clicker.template">
+        <glob pattern="*.clkt"/>
+    </mime-type>
+    <mime-type type="application/vnd.crick.clicker.wordbank">
+        <glob pattern="*.clkw"/>
+    </mime-type>
+    <mime-type type="application/vnd.criticaltools.wbs+xml">
+        <glob pattern="*.wbs"/>
+    </mime-type>
+    <mime-type type="application/vnd.ctc-posml">
+        <glob pattern="*.pml"/>
+    </mime-type>
+    <mime-type type="application/vnd.ctct.ws+xml"/>
+    <mime-type type="application/vnd.cups-pdf"/>
+    <mime-type type="application/vnd.cups-postscript"/>
+    <mime-type type="application/vnd.cups-ppd">
+        <glob pattern="*.ppd"/>
+    </mime-type>
+    <mime-type type="application/vnd.cups-raster"/>
+    <mime-type type="application/vnd.cups-raw"/>
+    <mime-type type="application/vnd.curl.car">
+        <glob pattern="*.car"/>
+    </mime-type>
+    <mime-type type="application/vnd.curl.pcurl">
+        <glob pattern="*.pcurl"/>
+    </mime-type>
+    <mime-type type="application/vnd.cybank"/>
+    <mime-type type="application/vnd.data-vision.rdz">
+        <glob pattern="*.rdz"/>
+    </mime-type>
+    <mime-type type="application/vnd.denovo.fcselayout-link">
+        <glob pattern="*.fe_launch"/>
+    </mime-type>
+    <mime-type type="application/vnd.dir-bi.plate-dl-nosuffix"/>
+    <mime-type type="application/vnd.dna">
+        <glob pattern="*.dna"/>
+    </mime-type>
+    <mime-type type="application/vnd.dolby.mlp">
+        <glob pattern="*.mlp"/>
+    </mime-type>
+    <mime-type type="application/vnd.dolby.mobile.1"/>
+    <mime-type type="application/vnd.dolby.mobile.2"/>
+    <mime-type type="application/vnd.dpgraph">
+        <glob pattern="*.dpg"/>
+    </mime-type>
+    <mime-type type="application/vnd.dreamfactory">
+        <glob pattern="*.dfac"/>
+    </mime-type>
+    <mime-type type="application/vnd.dvb.esgcontainer"/>
+    <mime-type type="application/vnd.dvb.ipdcdftnotifaccess"/>
+    <mime-type type="application/vnd.dvb.ipdcesgaccess"/>
+    <mime-type type="application/vnd.dvb.ipdcroaming"/>
+    <mime-type type="application/vnd.dvb.iptv.alfec-base"/>
+    <mime-type type="application/vnd.dvb.iptv.alfec-enhancement"/>
+    <mime-type type="application/vnd.dvb.notif-aggregate-root+xml"/>
+    <mime-type type="application/vnd.dvb.notif-container+xml"/>
+    <mime-type type="application/vnd.dvb.notif-generic+xml"/>
+    <mime-type type="application/vnd.dvb.notif-ia-msglist+xml"/>
+    <mime-type type="application/vnd.dvb.notif-ia-registration-request+xml"/>
+    <mime-type type="application/vnd.dvb.notif-ia-registration-response+xml"/>
+    <mime-type type="application/vnd.dvb.notif-init+xml"/>
+    <mime-type type="application/vnd.dxr"/>
+    <mime-type type="application/vnd.dynageo">
+        <glob pattern="*.geo"/>
+    </mime-type>
+    <mime-type type="application/vnd.ecdis-update"/>
+    <mime-type type="application/vnd.ecowin.chart">
+        <glob pattern="*.mag"/>
+    </mime-type>
+    <mime-type type="application/vnd.ecowin.filerequest"/>
+    <mime-type type="application/vnd.ecowin.fileupdate"/>
+    <mime-type type="application/vnd.ecowin.series"/>
+    <mime-type type="application/vnd.ecowin.seriesrequest"/>
+    <mime-type type="application/vnd.ecowin.seriesupdate"/>
+    <mime-type type="application/vnd.emclient.accessrequest+xml"/>
+    <mime-type type="application/vnd.enliven">
+        <glob pattern="*.nml"/>
+    </mime-type>
+    <mime-type type="application/vnd.epson.esf">
+        <glob pattern="*.esf"/>
+    </mime-type>
+    <mime-type type="application/vnd.epson.msf">
+        <glob pattern="*.msf"/>
+    </mime-type>
+    <mime-type type="application/vnd.epson.quickanime">
+        <glob pattern="*.qam"/>
+    </mime-type>
+    <mime-type type="application/vnd.epson.salt">
+        <glob pattern="*.slt"/>
+    </mime-type>
+    <mime-type type="application/vnd.epson.ssf">
+        <glob pattern="*.ssf"/>
+    </mime-type>
+    <mime-type type="application/vnd.ericsson.quickcall"/>
+    <mime-type type="application/vnd.eszigno3+xml">
+        <glob pattern="*.es3"/>
+        <glob pattern="*.et3"/>
+    </mime-type>
+    <mime-type type="application/vnd.etsi.aoc+xml"/>
+    <mime-type type="application/vnd.etsi.cug+xml"/>
+    <mime-type type="application/vnd.etsi.iptvcommand+xml"/>
+    <mime-type type="application/vnd.etsi.iptvdiscovery+xml"/>
+    <mime-type type="application/vnd.etsi.iptvprofile+xml"/>
+    <mime-type type="application/vnd.etsi.iptvsad-bc+xml"/>
+    <mime-type type="application/vnd.etsi.iptvsad-cod+xml"/>
+    <mime-type type="application/vnd.etsi.iptvsad-npvr+xml"/>
+    <mime-type type="application/vnd.etsi.iptvueprofile+xml"/>
+    <mime-type type="application/vnd.etsi.mcid+xml"/>
+    <mime-type type="application/vnd.etsi.sci+xml"/>
+    <mime-type type="application/vnd.etsi.simservs+xml"/>
+    <mime-type type="application/vnd.eudora.data"/>
+    <mime-type type="application/vnd.ezpix-album">
+        <glob pattern="*.ez2"/>
+    </mime-type>
+    <mime-type type="application/vnd.ezpix-package">
+        <glob pattern="*.ez3"/>
+    </mime-type>
+    <mime-type type="application/vnd.f-secure.mobile"/>
+    <mime-type type="application/vnd.fdf">
+        <acronym>FDF</acronym>
+        <_comment>Forms Data Format</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/Forms_Data_Format</tika:link>
+        <tika:link>http://www.adobe.com/devnet/acrobat/fdftoolkit.html</tika:link>
+        <tika:uti>com.adobe.fdf</tika:uti>
+        <magic priority="50">
+            <match value="%FDF-" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.fdf"/>
+    </mime-type>
+    <mime-type type="application/vnd.fdsn.mseed">
+        <glob pattern="*.mseed"/>
+    </mime-type>
+    <mime-type type="application/vnd.fdsn.seed">
+        <glob pattern="*.seed"/>
+        <glob pattern="*.dataless"/>
+    </mime-type>
+    <mime-type type="application/vnd.ffsns"/>
+    <mime-type type="application/vnd.fints"/>
+    <mime-type type="application/vnd.flographit">
+        <glob pattern="*.gph"/>
+    </mime-type>
+    <mime-type type="application/vnd.fluxtime.clip">
+        <glob pattern="*.ftc"/>
+    </mime-type>
+    <mime-type type="application/vnd.font-fontforge-sfd"/>
+    <mime-type type="application/vnd.framemaker">
+        <glob pattern="*.fm"/>
+        <glob pattern="*.frame"/>
+        <glob pattern="*.maker"/>
+        <glob pattern="*.book"/>
+    </mime-type>
+    <mime-type type="application/vnd.frogans.fnc">
+        <glob pattern="*.fnc"/>
+    </mime-type>
+    <mime-type type="application/vnd.frogans.ltf">
+        <glob pattern="*.ltf"/>
+    </mime-type>
+    <mime-type type="application/vnd.fsc.weblaunch">
+        <glob pattern="*.fsc"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujitsu.oasys">
+        <glob pattern="*.oas"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujitsu.oasys2">
+        <glob pattern="*.oa2"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujitsu.oasys3">
+        <glob pattern="*.oa3"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujitsu.oasysgp">
+        <glob pattern="*.fg5"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujitsu.oasysprs">
+        <glob pattern="*.bh2"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujixerox.art-ex"/>
+    <mime-type type="application/vnd.fujixerox.art4"/>
+    <mime-type type="application/vnd.fujixerox.hbpl"/>
+    <mime-type type="application/vnd.fujixerox.ddd">
+        <glob pattern="*.ddd"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujixerox.docuworks">
+        <glob pattern="*.xdw"/>
+    </mime-type>
+    <mime-type type="application/vnd.fujixerox.docuworks.binder">
+        <glob pattern="*.xbd"/>
+    </mime-type>
+    <mime-type type="application/vnd.fut-misnet"/>
+    <mime-type type="application/vnd.fuzzysheet">
+        <glob pattern="*.fzs"/>
+    </mime-type>
+    <mime-type type="application/vnd.genomatix.tuxedo">
+        <glob pattern="*.txd"/>
+    </mime-type>
+    <mime-type type="application/vnd.geogebra.file">
+        <glob pattern="*.ggb"/>
+    </mime-type>
+    <mime-type type="application/vnd.geogebra.tool">
+        <glob pattern="*.ggt"/>
+    </mime-type>
+    <mime-type type="application/vnd.geometry-explorer">
+        <glob pattern="*.gex"/>
+        <glob pattern="*.gre"/>
+    </mime-type>
+    <mime-type type="application/vnd.gmx">
+        <glob pattern="*.gmx"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.google-earth.kml+xml">
+        <root-XML localName="kml"/>
+        <root-XML namespaceURI="http://www.opengis.net/kml/2.2" localName="kml"/>
+        <root-XML namespaceURI="http://earth.google.com/kml/2.0" localName="kml"/>
+        <root-XML namespaceURI="http://earth.google.com/kml/2.1" localName="kml"/>
+        <root-XML namespaceURI="http://earth.google.com/kml/2.2" localName="kml"/>
+        <acronym>KML</acronym>
+        <_comment>Keyhole Markup Language</_comment>
+        <glob pattern="*.kml"/>
+        <sub-class-of type="application/xml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.google-earth.kmz">
+        <sub-class-of type="application/zip"/>
+        <glob pattern="*.kmz"/>
+    </mime-type>
+    <mime-type type="application/vnd.grafeq">
+        <glob pattern="*.gqf"/>
+        <glob pattern="*.gqs"/>
+    </mime-type>
+    <mime-type type="application/vnd.gridmp"/>
+    <mime-type type="application/vnd.groove-account">
+        <glob pattern="*.gac"/>
+    </mime-type>
+    <mime-type type="application/vnd.groove-help">
+        <glob pattern="*.ghf"/>
+    </mime-type>
+    <mime-type type="application/vnd.groove-identity-message">
+        <glob pattern="*.gim"/>
+    </mime-type>
+    <mime-type type="application/vnd.groove-injector">
+        <glob pattern="*.grv"/>
+    </mime-type>
+    <mime-type type="application/vnd.groove-tool-message">
+        <glob pattern="*.gtm"/>
+    </mime-type>
+    <mime-type type="application/vnd.groove-tool-template">
+        <glob pattern="*.tpl"/>
+    </mime-type>
+    <mime-type type="application/vnd.groove-vcard">
+        <glob pattern="*.vcg"/>
+    </mime-type>
+    <mime-type type="application/vnd.handheld-entertainment+xml">
+        <glob pattern="*.zmm"/>
+    </mime-type>
+    <mime-type type="application/vnd.hbci">
+        <glob pattern="*.hbci"/>
+    </mime-type>
+    <mime-type type="application/vnd.hcl-bireports"/>
+    <mime-type type="application/vnd.hhe.lesson-player">
+        <glob pattern="*.les"/>
+    </mime-type>
+    <mime-type type="application/vnd.hp-hpgl">
+        <glob pattern="*.hpgl"/>
+    </mime-type>
+    <mime-type type="application/vnd.hp-hpid">
+        <glob pattern="*.hpid"/>
+    </mime-type>
+    <mime-type type="application/vnd.hp-hps">
+        <glob pattern="*.hps"/>
+    </mime-type>
+    <mime-type type="application/vnd.hp-jlyt">
+        <glob pattern="*.jlt"/>
+    </mime-type>
+    <mime-type type="application/vnd.hp-pcl">
+        <glob pattern="*.pcl"/>
+    </mime-type>
+    <mime-type type="application/vnd.hp-pclxl">
+        <glob pattern="*.pclxl"/>
+    </mime-type>
+    <mime-type type="application/vnd.httphone"/>
+    <mime-type type="application/vnd.hydrostatix.sof-data">
+        <glob pattern="*.sfd-hdstx"/>
+    </mime-type>
+    <mime-type type="application/vnd.hzn-3d-crossword">
+        <glob pattern="*.x3d"/>
+    </mime-type>
+    <mime-type type="application/vnd.ibm.afplinedata"/>
+    <mime-type type="application/vnd.ibm.electronic-media"/>
+    <mime-type type="application/vnd.ibm.minipay">
+        <glob pattern="*.mpy"/>
+    </mime-type>
+    <mime-type type="application/vnd.ibm.modcap">
+        <glob pattern="*.afp"/>
+        <glob pattern="*.listafp"/>
+        <glob pattern="*.list3820"/>
+    </mime-type>
+    <mime-type type="application/vnd.ibm.rights-management">
+        <glob pattern="*.irm"/>
+    </mime-type>
+    <mime-type type="application/vnd.ibm.secure-container">
+        <glob pattern="*.sc"/>
+    </mime-type>
+    <mime-type type="application/vnd.iccprofile">
+        <glob pattern="*.icc"/>
+        <glob pattern="*.icm"/>
+    </mime-type>
+    <mime-type type="application/vnd.igloader">
+        <glob pattern="*.igl"/>
+    </mime-type>
+    <mime-type type="application/vnd.immervision-ivp">
+        <glob pattern="*.ivp"/>
+    </mime-type>
+    <mime-type type="application/vnd.immervision-ivu">
+        <glob pattern="*.ivu"/>
+    </mime-type>
+    <mime-type type="application/vnd.informedcontrol.rms+xml"/>
+    <mime-type type="application/vnd.informix-visionary"/>
+    <mime-type type="application/vnd.intercon.formnet">
+        <glob pattern="*.xpw"/>
+        <glob pattern="*.xpx"/>
+    </mime-type>
+    <mime-type type="application/vnd.intertrust.digibox"/>
+    <mime-type type="application/vnd.intertrust.nncp"/>
+    <mime-type type="application/vnd.intu.qbo">
+        <glob pattern="*.qbo"/>
+    </mime-type>
+    <mime-type type="application/vnd.intu.qfx">
+        <glob pattern="*.qfx"/>
+    </mime-type>
+    <mime-type type="application/vnd.iptc.g2.conceptitem+xml"/>
+    <mime-type type="application/vnd.iptc.g2.knowledgeitem+xml"/>
+    <mime-type type="application/vnd.iptc.g2.newsitem+xml"/>
+    <mime-type type="application/vnd.iptc.g2.packageitem+xml"/>
+    <mime-type type="application/vnd.ipunplugged.rcprofile">
+        <glob pattern="*.rcprofile"/>
+    </mime-type>
+    <mime-type type="application/vnd.irepository.package+xml">
+        <glob pattern="*.irp"/>
+    </mime-type>
+    <mime-type type="application/vnd.is-xpr">
+        <glob pattern="*.xpr"/>
+    </mime-type>
+    <mime-type type="application/vnd.jam">
+        <glob pattern="*.jam"/>
+    </mime-type>
+    <mime-type type="application/vnd.japannet-directory-service"/>
+    <mime-type type="application/vnd.japannet-jpnstore-wakeup"/>
+    <mime-type type="application/vnd.japannet-payment-wakeup"/>
+    <mime-type type="application/vnd.japannet-registration"/>
+    <mime-type type="application/vnd.japannet-registration-wakeup"/>
+    <mime-type type="application/vnd.japannet-setstore-wakeup"/>
+    <mime-type type="application/vnd.japannet-verification"/>
+    <mime-type type="application/vnd.japannet-verification-wakeup"/>
+    <mime-type type="application/vnd.jcp.javame.midlet-rms">
+        <glob pattern="*.rms"/>
+    </mime-type>
+    <mime-type type="application/vnd.jisp">
+        <glob pattern="*.jisp"/>
+    </mime-type>
+    <mime-type type="application/vnd.joost.joda-archive">
+        <glob pattern="*.joda"/>
+    </mime-type>
+    <mime-type type="application/vnd.kahootz">
+        <glob pattern="*.ktz"/>
+        <glob pattern="*.ktr"/>
+    </mime-type>
+    <mime-type type="application/vnd.kde.karbon">
+        <glob pattern="*.karbon"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kchart">
+        <alias type="application/x-kchart"/>
+        <_comment>KChart File</_comment>
+        <glob pattern="*.chrt"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kformula">
+        <glob pattern="*.kfo"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kivio">
+        <glob pattern="*.flw"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kontour">
+        <glob pattern="*.kon"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kpresenter">
+        <alias type="application/x-kpresenter"/>
+        <_comment>KPresenter File</_comment>
+        <glob pattern="*.kpr"/>
+        <glob pattern="*.kpt"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kspread">
+        <alias type="application/x-kspread"/>
+        <_comment>KSpread File</_comment>
+        <glob pattern="*.ksp"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kde.kword">
+        <alias type="application/x-kword"/>
+        <_comment>KWord File</_comment>
+        <glob pattern="*.kwd"/>
+        <glob pattern="*.kwt"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.kenameaapp">
+        <glob pattern="*.htke"/>
+    </mime-type>
+    <mime-type type="application/vnd.kidspiration">
+        <glob pattern="*.kia"/>
+    </mime-type>
+    <mime-type type="application/vnd.kinar">
+        <glob pattern="*.kne"/>
+        <glob pattern="*.knp"/>
+    </mime-type>
+    <mime-type type="application/vnd.koan">
+        <alias type="application/x-koan"/>
+        <_comment>SSEYO Koan File</_comment>
+        <glob pattern="*.skp"/>
+        <glob pattern="*.skd"/>
+        <glob pattern="*.skt"/>
+        <glob pattern="*.skm"/>
+    </mime-type>
+    <mime-type type="application/vnd.kodak-descriptor">
+        <glob pattern="*.sse"/>
+    </mime-type>
+    <mime-type type="application/vnd.liberty-request+xml"/>
+    <mime-type type="application/vnd.llamagraphics.life-balance.desktop">
+        <glob pattern="*.lbd"/>
+    </mime-type>
+    <mime-type type="application/vnd.llamagraphics.life-balance.exchange+xml">
+        <glob pattern="*.lbe"/>
+    </mime-type>
+    <mime-type type="application/vnd.lotus-1-2-3">
+        <glob pattern="*.123"/>
+    </mime-type>
+    <mime-type type="application/vnd.lotus-approach">
+        <glob pattern="*.apr"/>
+    </mime-type>
+    <mime-type type="application/vnd.lotus-freelance">
+        <glob pattern="*.pre"/>
+    </mime-type>
+    <mime-type type="application/vnd.lotus-notes">
+        <glob pattern="*.nsf"/>
+    </mime-type>
+    <mime-type type="application/vnd.lotus-organizer">
+        <glob pattern="*.org"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.lotus-screencam">
+        <!-- <glob pattern="*.scm"/> - conflicts with text/x-scheme -->
+    </mime-type>
+
+    <mime-type type="application/vnd.lotus-wordpro">
+        <magic priority="50">
+            <match value="WordPro\0" type="string" offset="0" />
+            <match value="WordPro\r\373" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.lwp"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.macports.portpkg">
+        <glob pattern="*.portpkg"/>
+    </mime-type>
+    <mime-type type="application/vnd.marlin.drm.actiontoken+xml"/>
+    <mime-type type="application/vnd.marlin.drm.conftoken+xml"/>
+    <mime-type type="application/vnd.marlin.drm.license+xml"/>
+    <mime-type type="application/vnd.marlin.drm.mdcf"/>
+    <mime-type type="application/vnd.mcd">
+        <glob pattern="*.mcd"/>
+    </mime-type>
+    <mime-type type="application/vnd.medcalcdata">
+        <glob pattern="*.mc1"/>
+    </mime-type>
+    <mime-type type="application/vnd.mediastation.cdkey">
+        <glob pattern="*.cdkey"/>
+    </mime-type>
+    <mime-type type="application/vnd.meridian-slingshot"/>
+    <mime-type type="application/vnd.mfer">
+        <glob pattern="*.mwf"/>
+    </mime-type>
+    <mime-type type="application/vnd.mfmp">
+        <glob pattern="*.mfm"/>
+    </mime-type>
+    <mime-type type="application/vnd.micrografx.flo">
+        <glob pattern="*.flo"/>
+    </mime-type>
+    <mime-type type="application/vnd.micrografx.igx">
+        <glob pattern="*.igx"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.mif">
+        <_comment>FrameMaker Interchange Format</_comment>
+        <alias type="application/x-mif"/>
+        <alias type="application/x-frame"/>
+        <magic priority="50">
+            <match value="\&lt;MakerFile" type="string" offset="0" />
+            <match value="\&lt;MIFFile" type="string" offset="0" />
+            <match value="\&lt;MakerDictionary" type="string" offset="0" />
+            <match value="\&lt;MakerScreenFont" type="string" offset="0" />
+            <match value="\&lt;MML" type="string" offset="0" />
+            <match value="\&lt;Book" type="string" offset="0" />
+            <match value="\&lt;Maker" type="string" offset="0" />
+            <match value="\x3c\x4d\x49\x46\x46\x69\x6c\x65\x20" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.mif"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.mindjet.mindmanager">
+        <_comment>MindManager</_comment>
+        <sub-class-of type="application/zip"/>
+        <glob pattern="*.mmp"/>
+        <glob pattern="*.mmap"/>
+        <glob pattern="*.mmpt"/>
+        <glob pattern="*.mmat"/>
+        <glob pattern="*.mmmp"/>
+        <glob pattern="*.mmas"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.minisoft-hp3000-save"/>
+    <mime-type type="application/vnd.mitsubishi.misty-guard.trustweb"/>
+    <mime-type type="application/vnd.mobius.daf">
+        <glob pattern="*.daf"/>
+    </mime-type>
+    <mime-type type="application/vnd.mobius.dis">
+        <glob pattern="*.dis"/>
+    </mime-type>
+    <mime-type type="application/vnd.mobius.mbk">
+        <glob pattern="*.mbk"/>
+    </mime-type>
+    <mime-type type="application/vnd.mobius.mqy">
+        <glob pattern="*.mqy"/>
+    </mime-type>
+    <mime-type type="application/vnd.mobius.msl">
+        <glob pattern="*.msl"/>
+    </mime-type>
+    <mime-type type="application/vnd.mobius.plc">
+        <glob pattern="*.plc"/>
+    </mime-type>
+    <mime-type type="application/vnd.mobius.txf">
+        <glob pattern="*.txf"/>
+    </mime-type>
+    <mime-type type="application/vnd.mophun.application">
+        <glob pattern="*.mpn"/>
+    </mime-type>
+    <mime-type type="application/vnd.mophun.certificate">
+        <glob pattern="*.mpc"/>
+    </mime-type>
+    <mime-type type="application/vnd.motorola.flexsuite"/>
+    <mime-type type="application/vnd.motorola.flexsuite.adsi"/>
+    <mime-type type="application/vnd.motorola.flexsuite.fis"/>
+    <mime-type type="application/vnd.motorola.flexsuite.gotap"/>
+    <mime-type type="application/vnd.motorola.flexsuite.kmr"/>
+    <mime-type type="application/vnd.motorola.flexsuite.ttc"/>
+    <mime-type type="application/vnd.motorola.flexsuite.wem"/>
+    <mime-type type="application/vnd.motorola.iprm"/>
+    <mime-type type="application/vnd.mozilla.xul+xml">
+        <glob pattern="*.xul"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-artgalry">
+        <glob pattern="*.cil"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-asf"/>
+    <mime-type type="application/vnd.ms-cab-compressed">
+        <glob pattern="*.cab"/>
+    </mime-type>
+
+    <!-- http://www.iana.org/assignments/media-types/application/vnd.ms-excel -->
+    <mime-type type="application/vnd.ms-excel">
+        <!-- Use DefaultDetector / org.apache.tika.parser.microsoft.POIFSContainerDetector for more reliable detection of OLE2 documents -->
+        <alias type="application/msexcel" />
+        <_comment>Microsoft Excel Spreadsheet</_comment>
+        <magic priority="50">
+            <match value="Microsoft\ Excel\ 5.0\ Worksheet" type="string" offset="2080"/>
+            <match value="Foglio\ di\ lavoro\ Microsoft\ Exce" type="string" offset="2080"/>
+            <match value="Biff5" type="string" offset="2114"/>
+            <match value="Biff5" type="string" offset="2121"/>
+            <match value="\x09\x04\x06\x00\x00\x00\x10\x00" type="string" offset="0"/>
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="W\x00o\x00r\x00k\x00b\x00o\x00o\x00k" type="string" offset="1152:4096" />
+            </match>
+        </magic>
+        <glob pattern="*.xls"/>
+        <glob pattern="*.xlm"/>
+        <glob pattern="*.xla"/>
+        <glob pattern="*.xlc"/>
+        <glob pattern="*.xlt"/>
+        <glob pattern="*.xlw"/>
+        <glob pattern="*.xll"/>
+        <glob pattern="*.xld"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-excel.addin.macroenabled.12">
+        <_comment>Office Open XML Workbook Add-in (macro-enabled)</_comment>
+        <glob pattern="*.xlam"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-excel.sheet.macroenabled.12">
+        <_comment>Office Open XML Workbook (macro-enabled)</_comment>
+        <glob pattern="*.xlsm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-excel.sheet.binary.macroenabled.12">
+        <_comment>Microsoft Excel 2007 Binary Spreadsheet</_comment>
+        <glob pattern="*.xlsb"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-fontobject">
+        <glob pattern="*.eot"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-htmlhelp">
+        <glob pattern="*.chm"/>
+        <magic priority="50">
+            <match value="ITSF" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+    <mime-type type="application/vnd.ms-ims">
+        <glob pattern="*.ims"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-lrm">
+        <glob pattern="*.lrm"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-outlook">
+        <_comment>Microsoft Outlook Message</_comment>
+        <glob pattern="*.msg" />
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-outlook-pst">
+        <_comment>Outlook Personal Folders File Format</_comment>
+        <magic priority="50">
+            <match value="!BDN....SM" type="string" offset="0" mask="0xFFFFFFFF00000000FFFF"/>
+        </magic>
+        <glob pattern="*.pst"/>
+        <glob pattern="*.ost"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-pki.seccat">
+        <glob pattern="*.cat"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-pki.stl">
+        <glob pattern="*.stl"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-playready.initiator+xml"/>
+
+    <!-- http://www.iana.org/assignments/media-types/application/vnd.ms-powerpoint -->
+    <mime-type type="application/vnd.ms-powerpoint">
+        <!-- Use DefaultDetector / org.apache.tika.parser.microsoft.POIFSContainerDetector for more reliable detection of OLE2 documents -->
+        <alias type="application/mspowerpoint"/>
+        <_comment>Microsoft Powerpoint Presentation</_comment>
+        <magic priority="50">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="P\x00o\x00w\x00e\x00r\x00P\x00o\x00i\x00n\x00t\x00 D\x00o\x00c\x00u\x00m\x00e\x00n\x00t" type="string" offset="1152:4096" />
+            </match>
+        </magic>
+        <glob pattern="*.ppt"/>
+        <glob pattern="*.ppz"/>
+        <glob pattern="*.pps"/>
+        <glob pattern="*.pot"/>
+        <glob pattern="*.ppa"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-powerpoint.addin.macroenabled.12">
+        <_comment>Office Open XML Presentation Add-in (macro-enabled)</_comment>
+        <glob pattern="*.ppam"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-powerpoint.presentation.macroenabled.12">
+        <_comment>Office Open XML Presentation (macro-enabled)</_comment>
+        <glob pattern="*.pptm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-powerpoint.slide.macroenabled.12">
+        <glob pattern="*.sldm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-powerpoint.slideshow.macroenabled.12">
+        <_comment>Office Open XML Presentation Slideshow (macro-enabled)</_comment>
+        <glob pattern="*.ppsm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-powerpoint.template.macroenabled.12">
+        <glob pattern="*.potm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-project">
+        <glob pattern="*.mpp"/>
+        <glob pattern="*.mpt"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/x-project">
+        <glob pattern="*.mpx"/>
+        <magic priority="50">
+            <match value="MPX,Microsoft Project for Windows," type="string" offset="0"/>
+        </magic>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-tnef">
+        <alias type="application/ms-tnef" />
+        <magic priority="50">
+            <match value="0x223e9f78" type="little32" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-wmdrm.lic-chlg-req"/>
+    <mime-type type="application/vnd.ms-wmdrm.lic-resp"/>
+    <mime-type type="application/vnd.ms-wmdrm.meter-chlg-req"/>
+    <mime-type type="application/vnd.ms-wmdrm.meter-resp"/>
+
+    <mime-type type="application/vnd.ms-word.document.macroenabled.12">
+        <_comment>Office Open XML Document (macro-enabled)</_comment>
+        <glob pattern="*.docm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-word.template.macroenabled.12">
+        <_comment>Office Open XML Document Template (macro-enabled)</_comment>
+        <glob pattern="*.dotm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-works">
+        <magic priority="50">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="M\x00a\x00t\x00O\x00S\x00T" type="string" offset="1152:4096" />
+            </match>
+        </magic>
+        <glob pattern="*.wps"/>
+        <glob pattern="*.wks"/>
+        <glob pattern="*.wcm"/>
+        <glob pattern="*.wdb"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-wpl">
+        <glob pattern="*.wpl"/>
+    </mime-type>
+    <mime-type type="application/vnd.ms-xpsdocument">
+        <alias type="application/oxps"/>
+        <_comment>Open XML Paper Specification</_comment>
+        <glob pattern="*.xps"/>
+        <glob pattern="*.oxps"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+    <mime-type type="application/vnd.mseq">
+        <glob pattern="*.mseq"/>
+    </mime-type>
+    <mime-type type="application/vnd.msign"/>
+    <mime-type type="application/vnd.multiad.creator"/>
+    <mime-type type="application/vnd.multiad.creator.cif"/>
+    <mime-type type="application/vnd.music-niff"/>
+    <mime-type type="application/vnd.musician">
+        <glob pattern="*.mus"/>
+    </mime-type>
+    <mime-type type="application/vnd.muvee.style">
+        <glob pattern="*.msty"/>
+    </mime-type>
+    <mime-type type="application/vnd.ncd.control"/>
+    <mime-type type="application/vnd.ncd.reference"/>
+    <mime-type type="application/vnd.nervana"/>
+    <mime-type type="application/vnd.netfpx"/>
+    <mime-type type="application/vnd.neurolanguage.nlu">
+        <glob pattern="*.nlu"/>
+    </mime-type>
+    <mime-type type="application/vnd.noblenet-directory">
+        <glob pattern="*.nnd"/>
+    </mime-type>
+    <mime-type type="application/vnd.noblenet-sealer">
+        <glob pattern="*.nns"/>
+    </mime-type>
+    <mime-type type="application/vnd.noblenet-web">
+        <glob pattern="*.nnw"/>
+    </mime-type>
+    <mime-type type="application/vnd.nokia.catalogs"/>
+    <mime-type type="application/vnd.nokia.conml+wbxml"/>
+    <mime-type type="application/vnd.nokia.conml+xml"/>
+    <mime-type type="application/vnd.nokia.isds-radio-presets"/>
+    <mime-type type="application/vnd.nokia.iptv.config+xml"/>
+    <mime-type type="application/vnd.nokia.landmark+wbxml"/>
+    <mime-type type="application/vnd.nokia.landmark+xml"/>
+    <mime-type type="application/vnd.nokia.landmarkcollection+xml"/>
+    <mime-type type="application/vnd.nokia.n-gage.ac+xml"/>
+    <mime-type type="application/vnd.nokia.n-gage.data">
+        <glob pattern="*.ngdat"/>
+    </mime-type>
+    <mime-type type="application/vnd.nokia.n-gage.symbian.install">
+        <glob pattern="*.n-gage"/>
+    </mime-type>
+    <mime-type type="application/vnd.nokia.ncd"/>
+    <mime-type type="application/vnd.nokia.pcd+wbxml"/>
+    <mime-type type="application/vnd.nokia.pcd+xml"/>
+    <mime-type type="application/vnd.nokia.radio-preset">
+        <glob pattern="*.rpst"/>
+    </mime-type>
+    <mime-type type="application/vnd.nokia.radio-presets">
+        <glob pattern="*.rpss"/>
+    </mime-type>
+    <mime-type type="application/vnd.novadigm.edm">
+        <glob pattern="*.edm"/>
+    </mime-type>
+    <mime-type type="application/vnd.novadigm.edx">
+        <glob pattern="*.edx"/>
+    </mime-type>
+    <mime-type type="application/vnd.novadigm.ext">
+        <glob pattern="*.ext"/>
+    </mime-type>
+
+    <!-- =================================================================== -->
+    <!-- Open Document Format for Office Applications (OpenDocument) v1.0    -->
+    <!-- http://www.oasis-open.org/specs/index.php#opendocumentv1.0          -->
+    <!-- =================================================================== -->
+
+    <mime-type type="application/vnd.oasis.opendocument.chart">
+        <alias type="application/x-vnd.oasis.opendocument.chart"/>
+        <_comment>OpenDocument v1.0: Chart document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.chart"/>
+            </match>
+        </magic>
+        <glob pattern="*.odc"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.chart-template">
+        <alias type="application/x-vnd.oasis.opendocument.chart-template"/>
+        <_comment>OpenDocument v1.0: Chart document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.chart-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.otc"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.database">
+        <glob pattern="*.odb"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.formula">
+        <alias type="application/x-vnd.oasis.opendocument.formula"/>
+        <_comment>OpenDocument v1.0: Formula document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.formula" />
+            </match>
+        </magic>
+        <glob pattern="*.odf"/>
+        <sub-class-of type="application/zip"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.formula-template">
+        <alias type="application/x-vnd.oasis.opendocument.formula-template"/>
+        <_comment>OpenDocument v1.0: Formula document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.formula-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.odft"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.graphics">
+        <alias type="application/x-vnd.oasis.opendocument.graphics"/>
+        <_comment>OpenDocument v1.0: Graphics document (Drawing)</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.graphics"/>
+            </match>
+        </magic>
+        <glob pattern="*.odg"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.graphics-template">
+        <alias type="application/x-vnd.oasis.opendocument.graphics-template"/>
+        <_comment>OpenDocument v1.0: Graphics document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.graphics-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.otg"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.image">
+        <alias type="application/x-vnd.oasis.opendocument.image"/>
+        <_comment>OpenDocument v1.0: Image document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.image"/>
+            </match>
+        </magic>
+        <glob pattern="*.odi"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.image-template">
+        <alias type="application/x-vnd.oasis.opendocument.image-template"/>
+        <_comment>OpenDocument v1.0: Image document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.image-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.oti"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.presentation">
+        <alias type="application/x-vnd.oasis.opendocument.presentation"/>
+        <_comment>OpenDocument v1.0: Presentation document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.presentation"/>
+            </match>
+        </magic>
+        <glob pattern="*.odp"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.presentation-template">
+        <alias type="application/x-vnd.oasis.opendocument.presentation-template"/>
+        <_comment>OpenDocument v1.0: Presentation document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.presentation-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.otp"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.spreadsheet">
+        <alias type="application/x-vnd.oasis.opendocument.spreadsheet"/>
+        <_comment>OpenDocument v1.0: Spreadsheet document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.spreadsheet"/>
+            </match>
+        </magic>
+        <glob pattern="*.ods"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.spreadsheet-template">
+        <alias type="application/x-vnd.oasis.opendocument.spreadsheet-template"/>
+        <_comment>OpenDocument v1.0: Spreadsheet document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.spreadsheet-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.ots"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.text">
+        <alias type="application/x-vnd.oasis.opendocument.text"/>
+        <_comment>OpenDocument v1.0: Text document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.text"/>
+            </match>
+        </magic>
+        <glob pattern="*.odt"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.text-master">
+        <alias type="application/x-vnd.oasis.opendocument.text-master"/>
+        <_comment>OpenDocument v1.0: Global Text document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.text-master"/>
+            </match>
+        </magic>
+        <glob pattern="*.otm"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.text-template">
+        <alias type="application/x-vnd.oasis.opendocument.text-template"/>
+        <_comment>OpenDocument v1.0: Text document used as template</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.text-template"/>
+            </match>
+        </magic>
+        <glob pattern="*.ott"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.oasis.opendocument.text-web">
+        <alias type="application/x-vnd.oasis.opendocument.text-web"/>
+        <_comment>OpenDocument v1.0: Text document used as template for HTML documents</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.oasis.opendocument.text-web"/>
+            </match>
+        </magic>
+        <glob pattern="*.oth"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.obn"/>
+    <mime-type type="application/vnd.olpc-sugar">
+        <glob pattern="*.xo"/>
+    </mime-type>
+    <mime-type type="application/vnd.oma-scws-config"/>
+    <mime-type type="application/vnd.oma-scws-http-request"/>
+    <mime-type type="application/vnd.oma-scws-http-response"/>
+    <mime-type type="application/vnd.oma.bcast.associated-procedure-parameter+xml"/>
+    <mime-type type="application/vnd.oma.bcast.drm-trigger+xml"/>
+    <mime-type type="application/vnd.oma.bcast.imd+xml"/>
+    <mime-type type="application/vnd.oma.bcast.ltkm"/>
+    <mime-type type="application/vnd.oma.bcast.notification+xml"/>
+    <mime-type type="application/vnd.oma.bcast.provisioningtrigger"/>
+    <mime-type type="application/vnd.oma.bcast.sgboot"/>
+    <mime-type type="application/vnd.oma.bcast.sgdd+xml"/>
+    <mime-type type="application/vnd.oma.bcast.sgdu"/>
+    <mime-type type="application/vnd.oma.bcast.simple-symbol-container"/>
+    <mime-type type="application/vnd.oma.bcast.smartcard-trigger+xml"/>
+    <mime-type type="application/vnd.oma.bcast.sprov+xml"/>
+    <mime-type type="application/vnd.oma.bcast.stkm"/>
+    <mime-type type="application/vnd.oma.dcd"/>
+    <mime-type type="application/vnd.oma.dcdc"/>
+    <mime-type type="application/vnd.oma.dd2+xml">
+        <glob pattern="*.dd2"/>
+    </mime-type>
+    <mime-type type="application/vnd.oma.drm.risd+xml"/>
+    <mime-type type="application/vnd.oma.group-usage-list+xml"/>
+    <mime-type type="application/vnd.oma.poc.detailed-progress-report+xml"/>
+    <mime-type type="application/vnd.oma.poc.final-report+xml"/>
+    <mime-type type="application/vnd.oma.poc.groups+xml"/>
+    <mime-type type="application/vnd.oma.poc.invocation-descriptor+xml"/>
+    <mime-type type="application/vnd.oma.poc.optimized-progress-report+xml"/>
+    <mime-type type="application/vnd.oma.xcap-directory+xml"/>
+    <mime-type type="application/vnd.omads-email+xml"/>
+    <mime-type type="application/vnd.omads-file+xml"/>
+    <mime-type type="application/vnd.omads-folder+xml"/>
+    <mime-type type="application/vnd.omaloc-supl-init"/>
+
+    <mime-type type="application/vnd.openofficeorg.extension">
+        <glob pattern="*.oxt"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.presentation">
+        <_comment>Office Open XML Presentation</_comment>
+        <glob pattern="*.pptx"/>
+        <glob pattern="*.thmx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slide">
+        <glob pattern="*.sldx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.template">
+        <_comment>Office Open XML Presentation Template</_comment>
+        <glob pattern="*.potx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slideshow">
+        <_comment>Office Open XML Presentation Slideshow</_comment>
+        <glob pattern="*.ppsx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
+        <_comment>Office Open XML Workbook</_comment>
+        <glob pattern="*.xlsx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.spreadsheetml.template">
+        <_comment>Office Open XML Workbook Template</_comment>
+        <glob pattern="*.xltx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.ms-excel.template.macroenabled.12">
+        <_comment>Office Open XML Workbook Template (macro-enabled)</_comment>
+        <glob pattern="*.xltm"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.document">
+        <_comment>Office Open XML Document</_comment>
+        <glob pattern="*.docx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.template">
+        <_comment>Office Open XML Document Template</_comment>
+        <glob pattern="*.dotx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.osa.netdeploy"/>
+    <mime-type type="application/vnd.osgi.bundle"/>
+    <mime-type type="application/vnd.osgi.dp">
+        <glob pattern="*.dp"/>
+    </mime-type>
+    <mime-type type="application/vnd.otps.ct-kip+xml"/>
+
+    <mime-type type="application/vnd.palm">
+        <!-- <glob pattern="*.pdb"/> - conflicts with chemical/x-pdb -->
+        <glob pattern="*.pqa"/>
+        <glob pattern="*.oprc"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.paos.xml"/>
+    <mime-type type="application/vnd.pg.format">
+        <glob pattern="*.str"/>
+    </mime-type>
+    <mime-type type="application/vnd.pg.osasli">
+        <glob pattern="*.ei6"/>
+    </mime-type>
+    <mime-type type="application/vnd.piaccess.application-licence"/>
+    <mime-type type="application/vnd.picsel">
+        <glob pattern="*.efif"/>
+    </mime-type>
+    <mime-type type="application/vnd.poc.group-advertisement+xml"/>
+    <mime-type type="application/vnd.pocketlearn">
+        <glob pattern="*.plf"/>
+    </mime-type>
+    <mime-type type="application/vnd.powerbuilder6">
+        <glob pattern="*.pbd"/>
+    </mime-type>
+    <mime-type type="application/vnd.powerbuilder6-s"/>
+    <mime-type type="application/vnd.powerbuilder7"/>
+    <mime-type type="application/vnd.powerbuilder7-s"/>
+    <mime-type type="application/vnd.powerbuilder75"/>
+    <mime-type type="application/vnd.powerbuilder75-s"/>
+    <mime-type type="application/vnd.preminet"/>
+    <mime-type type="application/vnd.previewsystems.box">
+        <glob pattern="*.box"/>
+    </mime-type>
+    <mime-type type="application/vnd.proteus.magazine">
+        <glob pattern="*.mgz"/>
+    </mime-type>
+    <mime-type type="application/vnd.publishare-delta-tree">
+        <glob pattern="*.qps"/>
+    </mime-type>
+    <mime-type type="application/vnd.pvi.ptid1">
+        <glob pattern="*.ptid"/>
+    </mime-type>
+    <mime-type type="application/vnd.pwg-multiplexed"/>
+    <mime-type type="application/vnd.pwg-xhtml-print+xml"/>
+    <mime-type type="application/vnd.qualcomm.brew-app-res"/>
+    <mime-type type="application/vnd.quark.quarkxpress">
+        <glob pattern="*.qxd"/>
+        <glob pattern="*.qxt"/>
+        <glob pattern="*.qwd"/>
+        <glob pattern="*.qwt"/>
+        <glob pattern="*.qxl"/>
+        <glob pattern="*.qxb"/>
+    </mime-type>
+    <mime-type type="application/vnd.rapid"/>
+    <mime-type type="application/vnd.recordare.musicxml">
+        <glob pattern="*.mxl"/>
+    </mime-type>
+    <mime-type type="application/vnd.recordare.musicxml+xml">
+        <glob pattern="*.musicxml"/>
+    </mime-type>
+    <mime-type type="application/vnd.renlearn.rlprint"/>
+    <mime-type type="application/vnd.rim.cod">
+        <glob pattern="*.cod"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.rn-realmedia">
+        <magic priority="50">
+            <match value=".RMF" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.rm"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.route66.link66+xml">
+        <glob pattern="*.link66"/>
+    </mime-type>
+    <mime-type type="application/vnd.ruckus.download"/>
+    <mime-type type="application/vnd.s3sms"/>
+    <mime-type type="application/vnd.sbm.cid"/>
+    <mime-type type="application/vnd.sbm.mid2"/>
+    <mime-type type="application/vnd.scribus"/>
+    <mime-type type="application/vnd.sealed.3df"/>
+    <mime-type type="application/vnd.sealed.csf"/>
+    <mime-type type="application/vnd.sealed.doc"/>
+    <mime-type type="application/vnd.sealed.eml"/>
+    <mime-type type="application/vnd.sealed.mht"/>
+    <mime-type type="application/vnd.sealed.net"/>
+    <mime-type type="application/vnd.sealed.ppt"/>
+    <mime-type type="application/vnd.sealed.tiff"/>
+    <mime-type type="application/vnd.sealed.xls"/>
+    <mime-type type="application/vnd.sealedmedia.softseal.html"/>
+    <mime-type type="application/vnd.sealedmedia.softseal.pdf"/>
+    <mime-type type="application/vnd.seemail">
+        <glob pattern="*.see"/>
+    </mime-type>
+    <mime-type type="application/vnd.sema">
+        <glob pattern="*.sema"/>
+    </mime-type>
+    <mime-type type="application/vnd.semd">
+        <glob pattern="*.semd"/>
+    </mime-type>
+    <mime-type type="application/vnd.semf">
+        <glob pattern="*.semf"/>
+    </mime-type>
+    <mime-type type="application/vnd.shana.informed.formdata">
+        <glob pattern="*.ifm"/>
+    </mime-type>
+    <mime-type type="application/vnd.shana.informed.formtemplate">
+        <glob pattern="*.itp"/>
+    </mime-type>
+    <mime-type type="application/vnd.shana.informed.interchange">
+        <glob pattern="*.iif"/>
+    </mime-type>
+    <mime-type type="application/vnd.shana.informed.package">
+        <glob pattern="*.ipk"/>
+    </mime-type>
+    <mime-type type="application/vnd.simtech-mindmapper">
+        <glob pattern="*.twd"/>
+        <glob pattern="*.twds"/>
+    </mime-type>
+    <mime-type type="application/vnd.smaf">
+        <glob pattern="*.mmf"/>
+    </mime-type>
+    <mime-type type="application/vnd.smart.teacher">
+        <glob pattern="*.teacher"/>
+    </mime-type>
+    <mime-type type="application/vnd.software602.filler.form+xml"/>
+    <mime-type type="application/vnd.software602.filler.form-xml-zip"/>
+    <mime-type type="application/vnd.solent.sdkm+xml">
+        <glob pattern="*.sdkm"/>
+        <glob pattern="*.sdkd"/>
+    </mime-type>
+    <mime-type type="application/vnd.spotfire.dxp">
+        <glob pattern="*.dxp"/>
+    </mime-type>
+    <mime-type type="application/vnd.spotfire.sfs">
+        <glob pattern="*.sfs"/>
+    </mime-type>
+    <mime-type type="application/vnd.sss-cod"/>
+    <mime-type type="application/vnd.sss-dtf"/>
+    <mime-type type="application/vnd.sss-ntf"/>
+
+    <mime-type type="application/vnd.stardivision.calc">
+        <sub-class-of type="application/x-tika-staroffice"/>
+        <magic priority="50">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="StarCalc" type="string" offset="2048:2207" />
+            </match>
+        </magic>
+        <glob pattern="*.sdc"/>
+    </mime-type>
+    <mime-type type="application/vnd.stardivision.draw">
+        <sub-class-of type="application/x-tika-staroffice"/>
+        <magic priority="50">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="StarDraw" type="string" offset="2048:2207" />
+            </match>
+        </magic>
+        <glob pattern="*.sda"/>
+    </mime-type>
+    <mime-type type="application/vnd.stardivision.impress">
+        <sub-class-of type="application/x-tika-staroffice"/>
+        <magic priority="50">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="StarImpress" type="string" offset="2048:2207" />
+            </match>
+        </magic>
+        <glob pattern="*.sdd"/>
+    </mime-type>
+    <mime-type type="application/vnd.stardivision.math">
+        <glob pattern="*.smf"/>
+    </mime-type>
+    <mime-type type="application/vnd.stardivision.writer">
+        <sub-class-of type="application/x-tika-staroffice"/>
+        <magic priority="50">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="StarWriter" type="string" offset="2048:2207" />
+            </match>
+        </magic>
+        <glob pattern="*.sdw"/>
+    </mime-type>
+    <mime-type type="application/x-staroffice-template">
+        <sub-class-of type="application/x-tika-staroffice"/>
+        <glob pattern="*.vor"/>
+    </mime-type>
+    <mime-type type="application/vnd.stardivision.writer-global">
+        <glob pattern="*.sgl"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.street-stream"/>
+    <mime-type type="application/vnd.sun.xml.calc">
+        <glob pattern="*.sxc"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.calc.template">
+        <glob pattern="*.stc"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.draw">
+        <glob pattern="*.sxd"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.draw.template">
+        <glob pattern="*.std"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.impress">
+        <glob pattern="*.sxi"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.impress.template">
+        <glob pattern="*.sti"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.math">
+        <glob pattern="*.sxm"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.sun.xml.writer">
+        <alias type="application/x-vnd.sun.xml.writer"/>
+        <_comment>OpenOffice v1.0: Writer Document</_comment>
+        <magic>
+            <match type="string" offset="0" value="PK">
+                <match type="string" offset="30"
+                       value="mimetypeapplication/vnd.sun.xml.writer"/>
+            </match>
+        </magic>
+        <glob pattern="*.sxw"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.sun.xml.writer.global">
+        <glob pattern="*.sxg"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.xml.writer.template">
+        <glob pattern="*.stw"/>
+    </mime-type>
+    <mime-type type="application/vnd.sun.wadl+xml"/>
+    <mime-type type="application/vnd.sus-calendar">
+        <glob pattern="*.sus"/>
+        <glob pattern="*.susp"/>
+    </mime-type>
+    <mime-type type="application/vnd.svd">
+        <glob pattern="*.svd"/>
+    </mime-type>
+    <mime-type type="application/vnd.swiftview-ics"/>
+
+    <mime-type type="application/vnd.symbian.install">
+        <magic priority="50">
+            <match value="0x10000419" type="little32" offset="8" />
+        </magic>
+        <glob pattern="*.sis"/>
+        <glob pattern="*.sisx"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.syncml+xml">
+        <glob pattern="*.xsm"/>
+    </mime-type>
+    <mime-type type="application/vnd.syncml.dm+wbxml">
+        <glob pattern="*.bdm"/>
+    </mime-type>
+    <mime-type type="application/vnd.syncml.dm+xml">
+        <glob pattern="*.xdm"/>
+    </mime-type>
+    <mime-type type="application/vnd.syncml.dm.notification"/>
+    <mime-type type="application/vnd.syncml.ds.notification"/>
+    <mime-type type="application/vnd.tao.intent-module-archive">
+        <glob pattern="*.tao"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.tcpdump.pcap">
+        <_comment>TCPDump pcap packet capture</_comment>
+        <magic priority="50">
+            <match value="0xa1b2c3d4" type="big32" offset="0" />
+            <match value="0xd4c3b2a1" type="big32" offset="0" />
+        </magic>
+        <glob pattern="*.pcap"/>
+        <glob pattern="*.cap"/>
+        <glob pattern="*.dmp"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.tmobile-livetv">
+        <glob pattern="*.tmo"/>
+    </mime-type>
+    <mime-type type="application/vnd.trid.tpt">
+        <glob pattern="*.tpt"/>
+    </mime-type>
+    <mime-type type="application/vnd.triscape.mxs">
+        <glob pattern="*.mxs"/>
+    </mime-type>
+    <mime-type type="application/vnd.trueapp">
+        <glob pattern="*.tra"/>
+    </mime-type>
+    <mime-type type="application/vnd.truedoc"/>
+    <mime-type type="application/vnd.ufdl">
+        <glob pattern="*.ufd"/>
+        <glob pattern="*.ufdl"/>
+    </mime-type>
+    <mime-type type="application/vnd.uiq.theme">
+        <glob pattern="*.utz"/>
+    </mime-type>
+    <mime-type type="application/vnd.umajin">
+        <glob pattern="*.umj"/>
+    </mime-type>
+    <mime-type type="application/vnd.unity">
+        <glob pattern="*.unityweb"/>
+    </mime-type>
+    <mime-type type="application/vnd.uoml+xml">
+        <glob pattern="*.uoml"/>
+    </mime-type>
+    <mime-type type="application/vnd.uplanet.alert"/>
+    <mime-type type="application/vnd.uplanet.alert-wbxml"/>
+    <mime-type type="application/vnd.uplanet.bearer-choice"/>
+    <mime-type type="application/vnd.uplanet.bearer-choice-wbxml"/>
+    <mime-type type="application/vnd.uplanet.cacheop"/>
+    <mime-type type="application/vnd.uplanet.cacheop-wbxml"/>
+    <mime-type type="application/vnd.uplanet.channel"/>
+    <mime-type type="application/vnd.uplanet.channel-wbxml"/>
+    <mime-type type="application/vnd.uplanet.list"/>
+    <mime-type type="application/vnd.uplanet.list-wbxml"/>
+    <mime-type type="application/vnd.uplanet.listcmd"/>
+    <mime-type type="application/vnd.uplanet.listcmd-wbxml"/>
+    <mime-type type="application/vnd.uplanet.signal"/>
+    <mime-type type="application/vnd.vcx">
+        <glob pattern="*.vcx"/>
+    </mime-type>
+    <mime-type type="application/vnd.vd-study"/>
+    <mime-type type="application/vnd.vectorworks"/>
+    <mime-type type="application/vnd.vidsoft.vidconference"/>
+
+    <!-- http://www.iana.org/assignments/media-types/application/vnd.visio -->
+    <mime-type type="application/vnd.visio">
+        <_comment>Microsoft Visio Diagram</_comment>
+        <glob pattern="*.vsd"/>
+        <glob pattern="*.vst"/>
+        <glob pattern="*.vss"/>
+        <glob pattern="*.vsw"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.visionary">
+        <glob pattern="*.vis"/>
+    </mime-type>
+    <mime-type type="application/vnd.vividence.scriptfile"/>
+    <mime-type type="application/vnd.vsf">
+        <glob pattern="*.vsf"/>
+    </mime-type>
+    <mime-type type="application/vnd.wap.sic"/>
+    <mime-type type="application/vnd.wap.slc"/>
+
+    <mime-type type="application/vnd.wap.wbxml">
+        <glob pattern="*.wbxml"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.wap.wmlc">
+        <_comment>Compiled WML Document</_comment>
+        <glob pattern="*.wmlc"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.wap.wmlscriptc">
+        <_comment>Compiled WML Script</_comment>
+        <glob pattern="*.wmlsc"/>
+    </mime-type>
+
+    <mime-type type="application/vnd.webturbo">
+        <glob pattern="*.wtb"/>
+    </mime-type>
+    <mime-type type="application/vnd.wfa.wsc"/>
+    <mime-type type="application/vnd.wmc"/>
+    <mime-type type="application/vnd.wmf.bootstrap"/>
+    <mime-type type="application/vnd.wordperfect">
+        <alias type="application/wordperfect"/>
+        <glob pattern="*.wpd"/>
+    </mime-type>
+    <mime-type type="application/vnd.wqd">
+        <glob pattern="*.wqd"/>
+    </mime-type>
+    <mime-type type="application/vnd.wrq-hp3000-labelled"/>
+    <mime-type type="application/vnd.wt.stf">
+        <glob pattern="*.stf"/>
+    </mime-type>
+    <mime-type type="application/vnd.wv.csp+wbxml"/>
+    <mime-type type="application/vnd.wv.csp+xml"/>
+    <mime-type type="application/vnd.wv.ssp+xml"/>
+    <mime-type type="application/vnd.xara">
+        <glob pattern="*.xar"/>
+    </mime-type>
+    <mime-type type="application/vnd.xfdl">
+        <glob pattern="*.xfdl"/>
+    </mime-type>
+    <mime-type type="application/vnd.xfdl.webform"/>
+    <mime-type type="application/vnd.xmi+xml"/>
+    <mime-type type="application/vnd.xmpie.cpkg"/>
+    <mime-type type="application/vnd.xmpie.dpkg"/>
+    <mime-type type="application/vnd.xmpie.plan"/>
+    <mime-type type="application/vnd.xmpie.ppkg"/>
+    <mime-type type="application/vnd.xmpie.xlim"/>
+    <mime-type type="application/vnd.yamaha.hv-dic">
+        <glob pattern="*.hvd"/>
+    </mime-type>
+    <mime-type type="application/vnd.yamaha.hv-script">
+        <glob pattern="*.hvs"/>
+    </mime-type>
+    <mime-type type="application/vnd.yamaha.hv-voice">
+        <glob pattern="*.hvp"/>
+    </mime-type>
+    <mime-type type="application/vnd.yamaha.openscoreformat">
+        <glob pattern="*.osf"/>
+    </mime-type>
+    <mime-type type="application/vnd.yamaha.openscoreformat.osfpvg+xml">
+        <glob pattern="*.osfpvg"/>
+    </mime-type>
+    <mime-type type="application/vnd.yamaha.smaf-audio">
+        <glob pattern="*.saf"/>
+    </mime-type>
+    <mime-type type="application/vnd.yamaha.smaf-phrase">
+        <glob pattern="*.spf"/>
+    </mime-type>
+    <mime-type type="application/vnd.yellowriver-custom-menu">
+        <glob pattern="*.cmp"/>
+    </mime-type>
+    <mime-type type="application/vnd.zul">
+        <glob pattern="*.zir"/>
+        <glob pattern="*.zirz"/>
+    </mime-type>
+    <mime-type type="application/vnd.zzazz.deck+xml">
+        <glob pattern="*.zaz"/>
+    </mime-type>
+    <mime-type type="application/voicexml+xml">
+        <glob pattern="*.vxml"/>
+    </mime-type>
+    <mime-type type="application/watcherinfo+xml"/>
+    <mime-type type="application/whoispp-query"/>
+    <mime-type type="application/whoispp-response"/>
+    <mime-type type="application/winhlp">
+        <glob pattern="*.hlp"/>
+    </mime-type>
+    <mime-type type="application/wita"/>
+    <mime-type type="application/wordperfect5.1"/>
+    <mime-type type="application/wsdl+xml">
+        <glob pattern="*.wsdl"/>
+    </mime-type>
+    <mime-type type="application/wspolicy+xml">
+        <glob pattern="*.wspolicy"/>
+    </mime-type>
+
+    <mime-type type="application/x-123">
+        <magic priority="50">
+            <match value="0x00001a00" type="big32" offset="0" />
+            <match value="0x00000200" type="big32" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-abiword">
+        <glob pattern="*.abw"/>
+    </mime-type>
+    <mime-type type="application/x-ace-compressed">
+        <glob pattern="*.ace"/>
+    </mime-type>
+
+    <mime-type type="application/x-axcrypt">
+        <_comment>AxCrypt</_comment>
+        <glob pattern="*.axx" />
+        <magic priority="60">
+            <!-- AxCrypt block header, skip length field, then Header of type Preamble -->
+            <match value="0xc0b9072e4f93f146a015792ca1d9e821" type="string" offset="0">
+                <match value="2" type="big32" offset="17" />
+            </match>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-adobe-indesign">
+        <acronym>INDD</acronym>
+        <_comment>Adobe InDesign document</_comment>
+        <glob pattern="*.indd"/>
+        <magic priority="50">
+            <match value="0x0606edf5d81d46e5bd31efe7fe74b71d" type="string" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-adobe-indesign-interchange">
+        <acronym>INX</acronym>
+        <_comment>Adobe InDesign Interchange format</_comment>
+        <magic priority="50">
+            <match value="&lt;?aid" type="string" offset="0:100"/>
+        </magic>
+        <glob pattern="*.inx"/>
+        <sub-class-of type="application/xml"/>
+    </mime-type>
+
+    <mime-type type="application/x-apple-diskimage">
+        <glob pattern="*.dmg"/>
+        <!-- <glob pattern="*.img"/> too generic -->
+        <!-- <glob pattern="*.smi"/> conflicts with SMIL -->
+    </mime-type>
+
+    <mime-type type="application/x-appleworks">
+        <glob pattern="*.cwk"/>
+    </mime-type>
+
+    <mime-type type="application/x-archive">
+        <alias type="application/x-unix-archive"/>
+        <magic priority="50">
+            <match value="=&lt;ar&gt;" type="string" offset="0"/>
+            <match value="!&lt;arch&gt;\n" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.ar"/>
+        <glob pattern="*.a"/>
+    </mime-type>
+
+    <mime-type type="application/x-arj">
+        <alias type="application/x-arj-compressed"/>
+        <magic priority="50">
+            <match value="0x60ea" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.arj"/>
+    </mime-type>
+
+    <mime-type type="application/x-authorware-bin">
+        <glob pattern="*.aab"/>
+        <glob pattern="*.x32"/>
+        <glob pattern="*.u32"/>
+        <glob pattern="*.vox"/>
+    </mime-type>
+    <mime-type type="application/x-authorware-map">
+        <glob pattern="*.aam"/>
+    </mime-type>
+    <mime-type type="application/x-authorware-seg">
+        <glob pattern="*.aas"/>
+    </mime-type>
+
+    <mime-type type="application/x-bcpio">
+        <glob pattern="*.bcpio"/>
+    </mime-type>
+
+    <mime-type type="application/x-berkeley-db">
+        <magic priority="50">
+            <match value="0x00061561" type="big32" offset="0"/>
+            <match value="0x00061561" type="host32" offset="12"/>
+            <match value="0x00061561" type="big32" offset="12"/>
+            <match value="0x00061561" type="little32" offset="12"/>
+            <match value="0x00053162" type="host32" offset="12"/>
+            <match value="0x00053162" type="big32" offset="12"/>
+            <match value="0x00053162" type="little32" offset="12"/>
+            <match value="0x00042253" type="host32" offset="12"/>
+            <match value="0x00042253" type="big32" offset="12"/>
+            <match value="0x00042253" type="little32" offset="12"/>
+            <match value="0x00040988" type="host32" offset="12"/>
+            <match value="0x00040988" type="little32" offset="12"/>
+            <match value="0x00040988" type="big32" offset="12"/>
+            <match value="0x00053162" type="host32" offset="0"/>
+            <match value="0x00053162" type="big32" offset="0"/>
+            <match value="0x00053162" type="little32" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-bibtex-text-file">
+        <magic priority="50">
+            <match value="%\ BibTeX\ `" type="string" offset="0"/>
+            <match value="%%%\ \ " type="string" offset="73"/>
+            <match value="%\ BibTeX\ standard\ bibliography\ " type="string" offset="0"/>
+            <match value="%%%\ \ @BibTeX-style-file{" type="string" offset="73"/>
+            <match value="@article{" type="string" offset="0"/>
+            <match value="@book{" type="string" offset="0"/>
+            <match value="@inbook{" type="string" offset="0"/>
+            <match value="@incollection{" type="string" offset="0"/>
+            <match value="@inproceedings{" type="string" offset="0"/>
+            <match value="@manual{" type="string" offset="0"/>
+            <match value="@misc{" type="string" offset="0"/>
+            <match value="@preamble{" type="string" offset="0"/>
+            <match value="@phdthesis{" type="string" offset="0"/>
+            <match value="@techreport{" type="string" offset="0"/>
+            <match value="@unpublished{" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.bib"/>
+        <glob pattern="*.bibtex"/>
+    </mime-type>
+
+    <mime-type type="application/x-bittorrent">
+        <magic priority="50">
+            <match value="d8:announce" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.torrent"/>
+    </mime-type>
+
+    <mime-type type="application/x-bplist">
+        <!-- The priority is 60, as .webarchive files often contain
+         (X)HTML content. The bplist magic must trump the XHTML
+         magics further within the file. This must also be
+         independent of the internal ordering of patterns within
+         MimeTypes -->
+        <magic priority="60">
+            <match value="bplist" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-bzip">
+        <magic priority="40">
+            <match value="BZh" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.bz"/>
+        <glob pattern="*.tbz"/>
+    </mime-type>
+
+    <mime-type type="application/x-bzip2">
+        <sub-class-of type="application/x-bzip"/>
+        <_comment>Bzip 2 UNIX Compressed File</_comment>
+        <magic priority="40">
+            <match value="\x42\x5a\x68\x39\x31" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.bz2"/>
+        <glob pattern="*.tbz2"/>
+        <glob pattern="*.boz"/>
+    </mime-type>
+
+    <mime-type type="application/x-cdlink">
+        <_comment>Virtual CD-ROM CD Image File</_comment>
+        <glob pattern="*.vcd"/>
+    </mime-type>
+
+    <mime-type type="application/x-chat">
+        <glob pattern="*.chat"/>
+    </mime-type>
+
+    <mime-type type="application/x-chess-pgn">
+        <glob pattern="*.pgn"/>
+    </mime-type>
+
+    <mime-type type="application/x-chrome-package">
+        <acronym>CRX</acronym>
+        <_comment>Chrome Extension Package</_comment>
+        <tika:link>https://developer.chrome.com/extensions/crx</tika:link>
+        <magic priority="50">
+            <match value="Cr24" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.crx"/>
+    </mime-type>
+
+    <mime-type type="application/x-compress">
+        <magic priority="50">
+            <match value="\037\235" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.z"/>
+    </mime-type>
+
+    <mime-type type="application/x-corelpresentations">
+        <glob pattern="*.shw"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/x-cpio">
+        <_comment>UNIX CPIO Archive</_comment>
+        <magic priority="50">
+            <match value="070707" type="little16" offset="0"/>
+            <match value="070707" type="big16" offset="0"/>
+            <match value="070707" type="string" offset="0"/>
+            <match value="070701" type="string" offset="0"/>
+            <match value="070702" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.cpio"/>
+    </mime-type>
+
+    <mime-type type="application/x-csh">
+        <glob pattern="*.csh"/>
+        <glob pattern="*.tcsh"/>
+    </mime-type>
+
+    <mime-type type="application/x-debian-package">
+        <sub-class-of type="application/x-archive"/>
+        <magic priority="60">
+            <match value="!&lt;arch&gt;\ndebian-binary" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.deb"/>
+        <glob pattern="*.udeb"/>
+    </mime-type>
+
+    <mime-type type="application/x-dex">
+        <acronym>DEX</acronym>
+        <_comment>Dalvik Executable Format</_comment>
+        <tika:link>http://source.android.com/devices/tech/dalvik/dex-format.html</tika:link>
+        <magic priority="50">
+            <match value="dex\n" type="string" offset="0">
+                <match value="\0" type="string" offset="7"/>
+            </match>
+        </magic>
+        <glob pattern="*.dex"/>
+    </mime-type>
+
+    <mime-type type="application/x-director">
+        <_comment>Shockwave Movie</_comment>
+        <glob pattern="*.dir"/>
+        <glob pattern="*.dcr"/>
+        <glob pattern="*.dxr"/>
+        <glob pattern="*.cst"/>
+        <glob pattern="*.cct"/>
+        <glob pattern="*.cxt"/>
+        <glob pattern="*.w3d"/>
+        <glob pattern="*.fgd"/>
+        <glob pattern="*.swa"/>
+    </mime-type>
+
+    <mime-type type="application/x-doom">
+        <glob pattern="*.wad"/>
+    </mime-type>
+    <mime-type type="application/x-dtbncx+xml">
+        <glob pattern="*.ncx"/>
+    </mime-type>
+    <mime-type type="application/x-dtbook+xml">
+        <glob pattern="*.dtb"/>
+    </mime-type>
+    <mime-type type="application/x-dtbresource+xml">
+        <glob pattern="*.res"/>
+    </mime-type>
+
+    <mime-type type="application/x-dvi">
+        <_comment>TeX Device Independent Document</_comment>
+        <magic priority="50">
+            <match value="\367\002" type="string" offset="0"/>
+            <match value="0x02f7" type="little16" offset="0"/>
+            <match value="\x1b\x20\x54\x65\x58\x20\x6f\x75\x74\x70\x75\x74\x20"
+                   type="string" offset="14"/>
+        </magic>
+        <glob pattern="*.dvi"/>
+    </mime-type>
+
+    <mime-type type="application/x-elc">
+        <_comment>Emacs Lisp bytecode</_comment>
+        <magic priority="50">
+            <!-- Emacs 18 -->
+            <match value="\012(" type="string" offset="0" />
+            <!-- Emacs 19 -->
+            <match value=";ELC\023\000\000\000" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.elc"/>
+    </mime-type>
+
+    <mime-type type="application/x-elf">
+        <magic priority="50">
+            <match value="\177ELF" type="string" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="message/x-emlx">
+        <magic priority="70">
+            <match value="\nRelay-Version:" type="string" offset="2:9"/>
+            <match value="\n#!\ rnews" type="string" offset="2:9"/>
+            <match value="\nN#!\ rnews" type="string" offset="2:9"/>
+            <match value="\nForward\ to" type="string" offset="2:9"/>
+            <match value="\nPipe\ to" type="string" offset="2:9"/>
+            <match value="\nReturn-Path:" type="string" offset="2:9"/>
+            <match value="\nFrom:" type="string" offset="2:9"/>
+            <match value="\nReceived:" type="string" offset="2:9"/>
+            <match value="\nMessage-ID:" type="string" offset="2:9"/>
+            <match value="\nDate:" type="string" offset="2:9"/>
+        </magic>
+        <glob pattern="*.emlx"/>
+    </mime-type>
+
+    <mime-type type="application/x-killustrator">
+        <_comment>KIllustrator File</_comment>
+        <glob pattern="*.kil"/>
+    </mime-type>
+
+    <mime-type type="application/x-object">
+        <sub-class-of type="application/x-elf"/>
+        <magic priority="50">
+            <match value="\177ELF" type="string" offset="0">
+                <match value="0x0100" type="string" offset="16"/>
+                <match value="0x0001" type="string" offset="16"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-executable">
+        <sub-class-of type="application/x-elf"/>
+        <magic priority="50">
+            <match value="\177ELF" type="string" offset="0">
+                <match value="0x0200" type="string" offset="16"/>
+                <match value="0x0002" type="string" offset="16"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-sharedlib">
+        <sub-class-of type="application/x-elf"/>
+        <magic priority="50">
+            <match value="\177ELF" type="string" offset="0">
+                <match value="0x0300" type="string" offset="16"/>
+                <match value="0x0003" type="string" offset="16"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-coredump">
+        <sub-class-of type="application/x-elf"/>
+        <magic priority="50">
+            <match value="\177ELF" type="string" offset="0">
+                <match value="0x0400" type="string" offset="16"/>
+                <match value="0x0004" type="string" offset="16"/>
+            </match>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-dosexec">
+        <_comment>DOS/Windows executable (EXE)</_comment>
+        <sub-class-of type="application/x-msdownload"/>
+        <glob pattern="*.exe"/>
+    </mime-type>
+
+    <mime-type type="application/x-emf">
+        <acronym>EMF</acronym>
+        <_comment>Extended Metafile</_comment>
+        <glob pattern="*.emf"/>
+        <magic priority="50">
+            <match value="0x01000000" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-filemaker">
+        <acronym>FP7</acronym>
+        <_comment>FileMaker Pro 7</_comment>
+        <magic priority="50">
+            <match value="0xC04842414D37" type="string" offset="14" >
+                <match value="0x4842414D323130314F43543939C102480750726F20372E30C0C0" type="string" offset="525" />
+            </match>
+        </magic>
+        <glob pattern="*.fp7" />
+    </mime-type>
+
+    <mime-type type="application/x-font-bdf">
+        <glob pattern="*.bdf"/>
+    </mime-type>
+    <mime-type type="application/x-font-dos"/>
+    <mime-type type="application/x-font-framemaker"/>
+    <mime-type type="application/x-font-ghostscript">
+        <glob pattern="*.gsf"/>
+    </mime-type>
+    <mime-type type="application/x-font-libgrx"/>
+    <mime-type type="application/x-font-linux-psf">
+        <glob pattern="*.psf"/>
+    </mime-type>
+
+    <mime-type type="application/x-font-otf">
+        <acronym>OTF</acronym>
+        <_comment>OpenType Font</_comment>
+        <glob pattern="*.otf"/>
+    </mime-type>
+
+    <mime-type type="application/x-font-pcf">
+        <glob pattern="*.pcf"/>
+    </mime-type>
+    <mime-type type="application/x-font-snf">
+        <glob pattern="*.snf"/>
+    </mime-type>
+    <mime-type type="application/x-font-speedo"/>
+    <mime-type type="application/x-font-sunos-news"/>
+
+    <mime-type type="application/x-font-ttf">
+        <acronym>TTF</acronym>
+        <_comment>TrueType Font</_comment>
+        <glob pattern="*.ttf"/>
+        <glob pattern="*.ttc"/>
+        <magic priority="40">
+            <match value="0x00010000" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-font-type1">
+        <glob pattern="*.pfa"/>
+        <glob pattern="*.pfb"/>
+        <magic priority="60">
+            <!-- Match for PFB, the binary format -->
+            <match value="\x80\x01\xFF\xFF\x00\x00%!PS-AdobeFont" type="string"
+                   mask="0xFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" offset="0"/>
+            <!-- Match for PFA, the text format" -->
+            <match value="%!PS-AdobeFont-1.0" type="string" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-font-adobe-metric">
+        <_comment>Adobe Font Metric</_comment>
+        <glob pattern="*.afm"/>
+        <glob pattern="*.acfm"/>
+        <glob pattern="*.amfm"/>
+        <magic priority="40">
+            <match value="StartFontMetrics" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-font-printer-metric">
+        <_comment>Printer Font Metric</_comment>
+        <glob pattern="*.pfm"/>
+        <magic priority="40">
+            <match value="0x0001FFFF0000436f707972" type="string" offset="0"
+                   mask="0xFFFF0000FFFFFFFFFFFFFF" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-font-vfont"/>
+
+    <mime-type type="application/x-foxmail">
+        <_comment>Foxmail Email File</_comment>
+        <magic>
+            <match value="0x1010101010101011111111111153" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-futuresplash">
+        <_comment>Macromedia FutureSplash File</_comment>
+        <glob pattern="*.spl"/>
+    </mime-type>
+
+    <mime-type type="application/x-gnucash">
+        <glob pattern="*.gnucash" />
+    </mime-type>
+
+    <mime-type type="application/x-gnumeric">
+        <alias type="application/x-Gnumeric-spreadsheet"/>
+        <magic priority="50">
+            <match value="=&lt;gmr:Workbook" type="string" offset="39" />
+        </magic>
+        <glob pattern="*.gnumeric"/>
+    </mime-type>
+
+    <mime-type type="application/x-gtar">
+        <_comment>GNU tar Compressed File Archive (GNU Tape Archive)</_comment>
+        <magic priority="50">
+            <!-- GNU tar archive -->
+            <match value="ustar  \0" type="string" offset="257" />
+        </magic>
+        <glob pattern="*.gtar"/>
+        <sub-class-of type="application/x-tar"/>
+    </mime-type>
+
+    <mime-type type="application/gzip">
+        <_comment>Gzip Compressed Archive</_comment>
+        <alias type="application/x-gzip"/>
+        <alias type="application/x-gunzip"/>
+        <alias type="application/gzip-compressed"/>
+        <alias type="application/gzipped"/>
+        <alias type="application/gzip-compressed"/>
+        <alias type="application/x-gzip-compressed"/>
+        <alias type="gzip/document"/>
+        <magic priority="45">
+            <match value="\037\213" type="string" offset="0" />
+            <match value="\x1f\x8b" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.tgz" />
+        <glob pattern="*.gz" />
+        <glob pattern="*-gz" />
+        <glob pattern="*.emz" />
+    </mime-type>
+
+    <mime-type type="application/x-hdf">
+        <_comment>Hierarchical Data Format File</_comment>
+        <magic priority="50">
+            <!-- HDF4 -->
+            <match value="0x0e031301" type="big32" offset="0"/>
+            <!-- HDF5 -->
+            <match value="\211HDF\r\n\032" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.hdf"/>
+        <glob pattern="*.he5"/>
+        <glob pattern="*.h5"/>
+    </mime-type>
+
+    <mime-type type="application/x-hwp">
+        <magic priority="50">
+            <!--
+        TIKA-330: Detection pattern based on signature strings from
+        the hwpfilter/source/hwpfile.cpp file in OpenOffice.org.
+      -->
+            <match value="HWP Document File V" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-ibooks+zip">
+        <sub-class-of type="application/epub+zip" />
+        <acronym>iBooks</acronym>
+        <_comment>Apple iBooks Author publication format</_comment>
+        <magic priority="50">
+            <match value="PK\003\004" type="string" offset="0">
+                <match value="mimetypeapplication/x-ibooks+zip" type="string" offset="30"/>
+            </match>
+        </magic>
+        <glob pattern="*.ibooks"/>
+    </mime-type>
+
+    <mime-type type="application/x-iso9660-image">
+        <acronym>ISO</acronym>
+        <_comment>ISO 9660 CD-ROM filesystem data</_comment>
+        <magic priority="50">
+            <match value="CD001" type="string" offset="32769"/>
+            <match value="CD001" type="string" offset="34817"/>
+            <match value="CD001" type="string" offset="36865"/>
+        </magic>
+        <glob pattern="*.iso"/>
+    </mime-type>
+
+    <mime-type type="application/x-itunes-ipa">
+        <sub-class-of type="application/zip"/>
+        <_comment>Apple iOS IPA AppStore file</_comment>
+        <glob pattern="*.ipa"/>
+    </mime-type>
+
+    <mime-type type="application/x-java-jnlp-file">
+        <glob pattern="*.jnlp"/>
+    </mime-type>
+
+    <mime-type type="application/x-java-pack200">
+        <glob pattern="*.pack"/>
+    </mime-type>
+
+    <mime-type type="application/x-kdelnk">
+        <magic priority="50">
+            <match value="[KDE\ Desktop\ Entry]" type="string" offset="0"/>
+            <match value="#\ KDE\ Config\ File" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-latex">
+        <_comment>LaTeX Source Document</_comment>
+        <magic priority="50">
+            <match value="%\ -*-latex-*-" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.latex"/>
+        <sub-class-of type="application/x-tex"/>
+    </mime-type>
+
+    <mime-type type="application/x-lha">
+        <magic priority="50">
+            <match value="-lzs-" type="string" offset="2"/>
+            <match value="-lh\40-" type="string" offset="2"/>
+            <match value="-lhd-" type="string" offset="2"/>
+            <match value="-lh2-" type="string" offset="2"/>
+            <match value="-lh3-" type="string" offset="2"/>
+            <match value="-lh4-" type="string" offset="2"/>
+            <match value="-lh5-" type="string" offset="2"/>
+            <match value="-lh6-" type="string" offset="2"/>
+            <match value="-lh7-" type="string" offset="2"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-lharc">
+        <magic priority="50">
+            <match value="-lh0-" type="string" offset="2"/>
+            <match value="-lh1-" type="string" offset="2"/>
+            <match value="-lz4-" type="string" offset="2"/>
+            <match value="-lz5-" type="string" offset="2"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-mobipocket-ebook">
+        <glob pattern="*.prc"/>
+        <glob pattern="*.mobi"/>
+    </mime-type>
+    <mime-type type="application/x-ms-application">
+        <glob pattern="*.application"/>
+    </mime-type>
+    <mime-type type="application/x-ms-wmd">
+        <glob pattern="*.wmd"/>
+    </mime-type>
+    <mime-type type="application/x-ms-wmz">
+        <sub-class-of type="application/x-gzip"/>
+        <glob pattern="*.wmz"/>
+    </mime-type>
+    <mime-type type="application/x-ms-xbap">
+        <glob pattern="*.xbap"/>
+    </mime-type>
+    <mime-type type="application/x-msaccess">
+        <glob pattern="*.mdb"/>
+        <magic priority="60">
+            <match value="0x000100005374616e" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-msbinder">
+        <glob pattern="*.obd"/>
+    </mime-type>
+    <mime-type type="application/x-mscardfile">
+        <glob pattern="*.crd"/>
+    </mime-type>
+    <mime-type type="application/x-msclip">
+        <glob pattern="*.clp"/>
+    </mime-type>
+
+    <mime-type type="application/x-msdownload">
+        <glob pattern="*.dll"/>
+        <glob pattern="*.com"/>
+        <glob pattern="*.bat"/>
+        <magic priority="50">
+            <match value="MZ" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-ms-installer">
+        <_comment>Microsoft Windows Installer</_comment>
+        <sub-class-of type="application/x-tika-msoffice"/>
+        <alias type="application/x-windows-installer"/>
+        <alias type="application/x-msi"/>
+        <glob pattern="*.msi"/>
+        <glob pattern="*.msp"/>
+        <glob pattern="*.mst"/>
+    </mime-type>
+
+    <mime-type type="application/x-msdownload;format=pe">
+        <sub-class-of type="application/x-msdownload"/>
+        <magic priority="55">
+            <!-- Technically the header offset is stored at 0x3c, and isn't a -->
+            <!-- constant, but it's almost always set to start at 0x80 or 0xf0 -->
+            <match value="PE\000\000" type="string" offset="128"/>
+            <match value="PE\000\000" type="string" offset="240"/>
+        </magic>
+    </mime-type>
+    <!-- the PE header should be PEx00x00 then a two byte machine type -->
+    <mime-type type="application/x-msdownload;format=pe32">
+        <sub-class-of type="application/x-msdownload;format=pe"/>
+        <magic priority="60">
+            <match value="PE\000\000" type="string" offset="128">
+                <match value="0x014c" type="little16" offset="132"/>
+            </match>
+            <match value="PE\000\000" type="string" offset="240">
+                <match value="0x014c" type="little16" offset="244"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-msdownload;format=pe64">
+        <sub-class-of type="application/x-msdownload;format=pe"/>
+        <magic priority="60">
+            <match value="PE\000\000" type="string" offset="128">
+                <match value="0x8664" type="little16" offset="132"/>
+            </match>
+            <match value="PE\000\000" type="string" offset="240">
+                <match value="0x8664" type="little16" offset="244"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-msdownload;format=pe-itanium">
+        <sub-class-of type="application/x-msdownload;format=pe"/>
+        <magic priority="60">
+            <match value="PE\000\000" type="string" offset="128">
+                <match value="0x0200" type="little16" offset="132"/>
+            </match>
+            <match value="PE\000\000" type="string" offset="240">
+                <match value="0x0200" type="little16" offset="244"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-msdownload;format=pe-armLE">
+        <sub-class-of type="application/x-msdownload;format=pe"/>
+        <magic priority="60">
+            <match value="pe\000\000" type="string" offset="128">
+                <match value="0x01c0" type="little16" offset="132"/>
+            </match>
+            <match value="pe\000\000" type="string" offset="240">
+                <match value="0x01c0" type="little16" offset="244"/>
+            </match>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-msdownload;format=pe-arm7">
+        <sub-class-of type="application/x-msdownload;format=pe"/>
+        <magic priority="60">
+            <match value="pe\000\000" type="string" offset="128">
+                <match value="0x01c4" type="little16" offset="132"/>
+            </match>
+            <match value="pe\000\000" type="string" offset="240">
+                <match value="0x01c4" type="little16" offset="244"/>
+            </match>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-msmediaview">
+        <glob pattern="*.mvb"/>
+        <glob pattern="*.m13"/>
+        <glob pattern="*.m14"/>
+    </mime-type>
+    <mime-type type="application/x-msmetafile">
+        <alias type="image/x-wmf"/>
+        <acronym>WMF</acronym>
+        <_comment>Windows Metafile</_comment>
+        <glob pattern="*.wmf"/>
+        <magic priority="50">
+            <match value="0xd7cdc69a0000" type="string" offset="0"/>
+            <match value="0x010009000003" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-msmoney">
+        <glob pattern="*.mny"/>
+        <magic priority="60">
+            <match value="0x000100004D534953414D204461746162617365" type="string" offset="0" />
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-mspublisher">
+        <glob pattern="*.pub"/>
+    </mime-type>
+    <mime-type type="application/x-msschedule">
+        <glob pattern="*.scd"/>
+    </mime-type>
+    <mime-type type="application/x-msterminal">
+        <glob pattern="*.trm"/>
+    </mime-type>
+    <mime-type type="application/x-mswrite">
+        <glob pattern="*.wri"/>
+    </mime-type>
+    <mime-type type="application/x-netcdf">
+        <glob pattern="*.nc"/>
+        <glob pattern="*.cdf"/>
+    </mime-type>
+    <mime-type type="application/x-pkcs12">
+        <glob pattern="*.p12"/>
+        <glob pattern="*.pfx"/>
+    </mime-type>
+    <mime-type type="application/x-pkcs7-certificates">
+        <glob pattern="*.p7b"/>
+        <glob pattern="*.spc"/>
+    </mime-type>
+    <mime-type type="application/x-pkcs7-certreqresp">
+        <glob pattern="*.p7r"/>
+    </mime-type>
+
+    <mime-type type="application/x-prt">
+        <glob pattern="*.prt"/>
+        <magic priority="50">
+            <match value="0M3C" type="string" offset="8" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-quattro-pro">
+        <glob pattern="*.qpw"/>
+        <glob pattern="*.wb1"/>
+        <glob pattern="*.wb2"/>
+        <glob pattern="*.wb3"/>
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/x-rar-compressed">
+        <_comment>RAR archive</_comment>
+        <alias type="application/x-rar"/>
+        <magic priority="50">
+            <match value="Rar!" type="string" offset="0"/>
+            <match value="\x52\x61\x72\x21\x1a" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.rar"/>
+    </mime-type>
+
+    <mime-type type="application/x-roxio-toast">
+        <glob pattern="*.toast"/>
+        <sub-class-of type="application/x-iso9660-image"/>
+    </mime-type>
+
+    <mime-type type="application/x-rpm">
+        <_comment>RedHat Package Manager</_comment>
+        <glob pattern="*.rpm"/>
+        <magic priority="50">
+            <match value="\xed\xab\xee\xdb" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-sas">
+        <_comment>SAS Program</_comment>
+        <glob pattern="*.sas"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+    <mime-type type="application/x-sas-program-data">
+        <_comment>SAS Stored Program (DATA Step)</_comment>
+        <glob pattern="*.ss7"/>
+        <glob pattern="*.sas7bpgm"/>
+    </mime-type>
+    <mime-type type="application/x-sas-audit">
+        <_comment>SAS Audit</_comment>
+        <glob pattern="*.st7"/>
+        <glob pattern="*.sas7baud"/>
+    </mime-type>
+    <mime-type type="application/x-sas-data">
+        <_comment>SAS Data Set</_comment>
+        <glob pattern="*.sd7"/>
+        <glob pattern="*.sas7bdat"/>
+        <magic priority="40">
+            <match value="SAS FILE" type="string" offset="84" />
+        </magic>
+    </mime-type>
+    <mime-type type="application/x-sas-view">
+        <_comment>SAS Data Set View</_comment>
+        <glob pattern="*.sv7"/>
+        <glob pattern="*.sas7bvew"/>
+    </mime-type>
+    <mime-type type="application/x-sas-data-index">
+        <_comment>SAS Data Set Index</_comment>
+        <glob pattern="*.si7"/>
+        <glob pattern="*.sas7bndx"/>
+    </mime-type>
+    <mime-type type="application/x-sas-catalog">
+        <_comment>SAS Catalog</_comment>
+        <glob pattern="*.sc7"/>
+        <glob pattern="*.sas7bcat"/>
+    </mime-type>
+    <mime-type type="application/x-sas-access">
+        <_comment>SAS Access Descriptor</_comment>
+        <glob pattern="*.sa7"/>
+        <glob pattern="*.sas7bacs"/>
+    </mime-type>
+    <mime-type type="application/x-sas-fdb">
+        <_comment>SAS FDB Consolidation Database File</_comment>
+        <glob pattern="*.sf7"/>
+        <glob pattern="*.sas7bfdb"/>
+    </mime-type>
+    <mime-type type="application/x-sas-mddb">
+        <_comment>SAS MDDB Multi-Dimensional Database File</_comment>
+        <glob pattern="*.sm7"/>
+        <glob pattern="*.sas7bmdb"/>
+    </mime-type>
+    <mime-type type="application/x-sas-dmdb">
+        <_comment>SAS DMDB Data Mining Database File</_comment>
+        <glob pattern="*.s7m"/>
+        <glob pattern="*.sas7bdmd"/>
+    </mime-type>
+    <mime-type type="application/x-sas-itemstor">
+        <_comment>SAS Item Store (ItemStor) File</_comment>
+        <glob pattern="*.sr7"/>
+        <glob pattern="*.sas7bitm"/>
+    </mime-type>
+    <mime-type type="application/x-sas-utility">
+        <_comment>SAS Utility</_comment>
+        <glob pattern="*.su7"/>
+        <glob pattern="*.sas7butl"/>
+    </mime-type>
+    <mime-type type="application/x-sas-putility">
+        <_comment>SAS Permanent Utility</_comment>
+        <glob pattern="*.sp7"/>
+        <glob pattern="*.sas7bput"/>
+    </mime-type>
+    <mime-type type="application/x-sas-transport">
+        <_comment>SAS Transport File</_comment>
+        <glob pattern="*.stx"/>
+    </mime-type>
+    <mime-type type="application/x-sas-backup">
+        <_comment>SAS Backup</_comment>
+        <glob pattern="*.sas7bbak"/>
+    </mime-type>
+
+    <mime-type type="application/x-sc">
+        <magic priority="50">
+            <match value="Spreadsheet" type="string" offset="38"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-sh">
+        <_comment>UNIX/LINUX Shell Script</_comment>
+        <magic priority="50">
+            <match value="#!/" type="string" offset="0"/>
+            <match value="#!\ /" type="string" offset="0"/>
+            <match value="#!\t/" type="string" offset="0"/>
+            <match value="eval &quot;exec" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.sh"/>
+        <glob pattern="*.bash"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="application/x-shar">
+        <glob pattern="*.shar"/>
+    </mime-type>
+
+    <mime-type type="application/x-shockwave-flash">
+        <acronym>Flash</acronym>
+        <_comment>Adobe Flash</_comment>
+        <magic priority="50">
+            <match value="FWS" type="string" offset="0"/> <!-- F = Uncompressed -->
+            <match value="CWS" type="string" offset="0"/> <!-- C = Compressed   -->
+        </magic>
+        <glob pattern="*.swf"/>
+    </mime-type>
+
+    <mime-type type="application/x-silverlight-app">
+        <glob pattern="*.xap"/>
+    </mime-type>
+
+    <mime-type type="application/x-stuffit">
+        <magic priority="50">
+            <match value="StuffIt" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.sit"/>
+    </mime-type>
+
+    <mime-type type="application/x-stuffitx">
+        <glob pattern="*.sitx"/>
+    </mime-type>
+    <mime-type type="application/x-sv4cpio">
+        <glob pattern="*.sv4cpio"/>
+    </mime-type>
+    <mime-type type="application/x-sv4crc">
+        <glob pattern="*.sv4crc"/>
+    </mime-type>
+
+    <mime-type type="application/x-tar">
+        <magic priority="40">
+            <!-- POSIX tar archive -->
+            <match value="ustar\0" type="string" offset="257" />
+        </magic>
+        <glob pattern="*.tar"/>
+    </mime-type>
+
+    <mime-type type="application/x-tex">
+        <_comment>TeX Source</_comment>
+        <alias type="text/x-tex"/>
+        <magic priority="50">
+            <match value="\\input" type="string" offset="0"/>
+            <match value="\\section" type="string" offset="0"/>
+            <match value="\\setlength" type="string" offset="0"/>
+            <match value="\\documentstyle" type="string" offset="0"/>
+            <match value="\\chapter" type="string" offset="0"/>
+            <match value="\\documentclass" type="string" offset="0"/>
+            <match value="\\relax" type="string" offset="0"/>
+            <match value="\\contentsline" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.tex"/>
+    </mime-type>
+
+    <mime-type type="application/x-tex-tfm">
+        <glob pattern="*.tfm"/>
+    </mime-type>
+
+    <mime-type type="application/x-texinfo">
+        <alias type="text/x-texinfo" />
+        <magic priority="50">
+            <match value="\\input\ texinfo" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.texinfo"/>
+        <glob pattern="*.texi"/>
+    </mime-type>
+
+    <!-- =================================================================== -->
+    <!-- Microsoft Office binary file formats                                -->
+    <!-- http://www.microsoft.com/interop/docs/OfficeBinaryFormats.mspx      -->
+    <!-- =================================================================== -->
+    <mime-type type="application/x-tika-msoffice">
+        <magic priority="40">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-tika-msoffice-embedded">
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+    <mime-type type="application/x-tika-msoffice-embedded;format=ole10_native">
+        <sub-class-of type="application/x-tika-msoffice-embedded"/>
+        <_comment>OLE10 Native Embedded Document</_comment>
+    </mime-type>
+    <mime-type type="application/x-tika-msoffice-embedded;format=comp_obj">
+        <sub-class-of type="application/x-tika-msoffice-embedded"/>
+        <_comment>CompObj OLE2 Embedded Document</_comment>
+    </mime-type>
+
+    <mime-type type="application/x-tika-msworks-spreadsheet">
+        <glob pattern="*.xlr"/>
+        <sub-class-of type="application/vnd.ms-excel"/>
+        <!-- this has to be highter than the Excel match -->
+        <magic priority="60">
+            <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+                <match value="W\x00k\x00s\x00S\x00S\x00W\x00o\x00r\x00k\x00B\x00o\x00o\x00k" type="string" offset="1152:4096" />
+            </match>
+        </magic>
+    </mime-type>
+
+    <!-- =================================================================== -->
+    <!-- Office Open XML file formats                                        -->
+    <!-- http://www.ecma-international.org/publications/standards/Ecma-376.htm -->
+    <!-- =================================================================== -->
+    <mime-type type="application/x-tika-ooxml">
+        <sub-class-of type="application/zip"/>
+        <magic priority="50">
+            <match value="PK\003\004" type="string" offset="0">
+                <match value="[Content_Types].xml" type="string" offset="30"/>
+            </match>
+        </magic>
+    </mime-type>
+
+    <!-- Note - password protected OOXML files are actually stored in -->
+    <!--  an OLE2 (application/x-tika-msoffice) container -->
+    <mime-type type="application/x-tika-ooxml-protected">
+        <sub-class-of type="application/x-tika-ooxml"/>
+        <_comment>Password Protected OOXML File</_comment>
+    </mime-type>
+
+    <!-- Older StarOffice formats extend up the Microsoft OLE2 format -->
+    <mime-type type="application/x-tika-staroffice">
+        <sub-class-of type="application/x-tika-msoffice"/>
+    </mime-type>
+
+    <mime-type type="application/x-uc2-compressed">
+        <magic priority="50">
+            <match value="UC2\x1a" type="string" offset="0" />
+        </magic>
+        <glob pattern="*.uc2"/>
+    </mime-type>
+    <mime-type type="application/x-ustar">
+        <glob pattern="*.ustar"/>
+    </mime-type>
+
+    <mime-type type="application/x-vmdk">
+        <acronym>VMDK</acronym>
+        <_comment>Virtual Disk Format</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/VMDK</tika:link>
+        <glob pattern="*.vmdk"/>
+    </mime-type>
+
+    <mime-type type="application/x-wais-source">
+        <glob pattern="*.src"/>
+    </mime-type>
+    <mime-type type="application/x-webarchive">
+        <sub-class-of type="application/x-bplist"/>
+        <glob pattern="*.webarchive"/>
+    </mime-type>
+    <mime-type type="application/x-x509-ca-cert">
+        <glob pattern="*.der"/>
+        <glob pattern="*.crt"/>
+    </mime-type>
+    <mime-type type="application/x-xfig">
+        <glob pattern="*.fig"/>
+    </mime-type>
+    <mime-type type="application/x-xpinstall">
+        <glob pattern="*.xpi"/>
+    </mime-type>
+
+    <mime-type type="application/x-xmind">
+        <_comment>XMind Pro</_comment>
+        <sub-class-of type="application/zip"/>
+        <glob pattern="*.xmind"/>
+        <!-- .xmap is also used, but that extension is more common elsewhere -->
+        <!-- <glob pattern="*.xmap"/> -->
+    </mime-type>
+
+    <mime-type type="application/x-xz">
+        <glob pattern="*.xz"/>
+        <magic priority="50">
+            <match value="\3757zXZ\000" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="application/x-zoo">
+        <magic priority="50">
+            <match value="0xfdc4a7dc" type="little32" offset="20"/>
+        </magic>
+        <glob pattern="*.zoo"/>
+    </mime-type>
+
+    <mime-type type="application/x400-bp"/>
+    <mime-type type="application/xcap-att+xml"/>
+    <mime-type type="application/xcap-caps+xml"/>
+    <mime-type type="application/xcap-el+xml"/>
+    <mime-type type="application/xcap-error+xml"/>
+    <mime-type type="application/xcap-ns+xml"/>
+    <mime-type type="application/xcon-conference-info-diff+xml"/>
+    <mime-type type="application/xcon-conference-info+xml"/>
+    <mime-type type="application/xenc+xml">
+        <glob pattern="*.xenc"/>
+    </mime-type>
+
+    <mime-type type="application/xhtml+xml">
+        <magic priority="50">
+            <match value="&lt;html xmlns=" type="string" offset="0:8192"/>
+        </magic>
+        <root-XML namespaceURI="http://www.w3.org/1999/xhtml" localName="html"/>
+        <glob pattern="*.xhtml"/>
+        <glob pattern="*.xht"/>
+    </mime-type>
+
+    <mime-type type="application/xhtml-voice+xml"/>
+
+    <mime-type type="application/xml">
+        <acronym>XML</acronym>
+        <_comment>Extensible Markup Language</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/Xml</tika:link>
+        <tika:uti>public.xml</tika:uti>
+        <alias type="text/xml"/>
+        <alias type="application/x-xml"/>
+        <magic priority="50">
+            <match value="&lt;?xml" type="string" offset="0"/>
+            <match value="&lt;?XML" type="string" offset="0"/>
+            <match value="&lt;!--" type="string" offset="0"/>
+            <!-- UTF-8 BOM -->
+            <match value="0xEFBBBF3C3F786D6C" type="string" offset="0"/>
+            <!-- UTF-16 LE/BE -->
+            <match value="0xFFFE3C003F0078006D006C00" type="string" offset="0"/>
+            <match value="0xFEFF003C003F0078006D006C" type="string" offset="0"/>
+            <!-- TODO: Add matches for the other possible XML encoding schemes -->
+        </magic>
+        <glob pattern="*.xml"/>
+        <glob pattern="*.xsl"/>
+        <glob pattern="*.xsd"/>
+        <sub-class-of type="text/plain" />
+    </mime-type>
+
+    <mime-type type="application/xml-dtd">
+        <_comment>XML Document Type Definition</_comment>
+        <sub-class-of type="text/plain"/>
+        <alias type="text/x-dtd"/>
+        <glob pattern="*.dtd"/>
+    </mime-type>
+
+    <mime-type type="application/xml-external-parsed-entity">
+        <alias type="text/xml-external-parsed-entity"/>
+    </mime-type>
+
+    <mime-type type="application/xmpp+xml"/>
+    <mime-type type="application/xop+xml">
+        <glob pattern="*.xop"/>
+    </mime-type>
+
+    <mime-type type="application/xslfo+xml">
+        <alias type="text/xsl"/>
+        <acronym>XSLFO</acronym>
+        <_comment>XSL Format</_comment>
+        <root-XML localName="root"
+                  namespaceURI="http://www.w3.org/1999/XSL/Format"/>
+        <glob pattern="*.xslfo"/>
+        <glob pattern="*.fo"/>
+    </mime-type>
+
+    <mime-type type="application/xslt+xml">
+        <alias type="text/xsl"/>
+        <acronym>XSLT</acronym>
+        <_comment>XSL Transformations</_comment>
+        <root-XML localName="stylesheet"
+                  namespaceURI="http://www.w3.org/1999/XSL/Transform"/>
+        <glob pattern="*.xslt"/>
+    </mime-type>
+
+    <mime-type type="application/xspf+xml">
+        <acronym>XSPF</acronym>
+        <_comment>XML Shareable Playlist Format</_comment>
+        <root-XML localName="playlist"
+                  namespaceURI="http://xspf.org/ns/0/"/>
+        <glob pattern="*.xspf"/>
+    </mime-type>
+
+    <mime-type type="application/xv+xml">
+        <glob pattern="*.mxml"/>
+        <glob pattern="*.xhvml"/>
+        <glob pattern="*.xvml"/>
+        <glob pattern="*.xvm"/>
+    </mime-type>
+
+    <mime-type type="application/zip">
+        <_comment>Compressed Archive File</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/ZIP_(file_format)</tika:link>
+        <tika:uti>com.pkware.zip-archive</tika:uti>
+        <alias type="application/x-zip-compressed"/>
+        <magic priority="50">
+            <match value="PK\003\004" type="string" offset="0"/>
+            <match value="PK\005\006" type="string" offset="0"/>
+            <match value="PK\x07\x08" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.zip"/>
+    </mime-type>
+
+    <mime-type type="application/x-7z-compressed">
+        <acronym>7zip</acronym>
+        <_comment>7-zip archive</_comment>
+        <magic priority="50">
+            <!-- Magic: '7', 'z', 0xBC, 0xAF, 0x27, 0x1C -->
+            <match value="7z" type="string" offset="0:1" >
+                <match value="0xBCAF271C" type="string" offset="2:5" />
+            </match>
+        </magic>
+        <glob pattern="*.7z" />
+    </mime-type>
+
+    <mime-type type="audio/32kadpcm"/>
+    <mime-type type="audio/3gpp"/>
+    <mime-type type="audio/3gpp2"/>
+    <mime-type type="audio/ac3"/>
+    <mime-type type="audio/adpcm">
+        <glob pattern="*.adp"/>
+    </mime-type>
+
+    <mime-type type="audio/amr">
+        <glob pattern="*.amr"/>
+        <magic priority="40">
+            <!-- Specific match for the original AMR format -->
+            <match value="#!AMR\n" type="string" offset="0"/>
+            <!-- General match for AMR subtypes we don't have entries for -->
+            <match value="#!AMR" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+    <mime-type type="audio/amr-wb">
+        <sub-class-of type="audio/amr"/>
+        <magic priority="50">
+            <match value="#!AMR-WB\n" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+    <mime-type type="audio/amr-wb+">
+        <sub-class-of type="audio/amr"/>
+        <!-- TIKA-1156 sample needed - might be "#!AMR-WB+\n" ? -->
+    </mime-type>
+
+    <mime-type type="audio/asc"/>
+
+    <mime-type type="audio/basic">
+        <_comment>uLaw/AU Audio File</_comment>
+        <magic priority="20">
+            <match value=".snd" type="string" offset="0">
+                <match value="1" type="big32" offset="12"/>
+                <match value="2" type="big32" offset="12"/>
+                <match value="3" type="big32" offset="12"/>
+                <match value="4" type="big32" offset="12"/>
+                <match value="5" type="big32" offset="12"/>
+                <match value="6" type="big32" offset="12"/>
+                <match value="7" type="big32" offset="12"/>
+            </match>
+            <match offset="0" type="string" value="\x2e\x73\x6e\x64\x00\x00\x00"/>
+        </magic>
+        <glob pattern="*.au"/>
+        <glob pattern="*.snd"/>
+    </mime-type>
+
+    <mime-type type="audio/bv16"/>
+    <mime-type type="audio/bv32"/>
+    <mime-type type="audio/clearmode"/>
+    <mime-type type="audio/cn"/>
+    <mime-type type="audio/dat12"/>
+    <mime-type type="audio/dls"/>
+    <mime-type type="audio/dsr-es201108"/>
+    <mime-type type="audio/dsr-es202050"/>
+    <mime-type type="audio/dsr-es202211"/>
+    <mime-type type="audio/dsr-es202212"/>
+    <mime-type type="audio/dvi4"/>
+    <mime-type type="audio/eac3"/>
+    <mime-type type="audio/evrc"/>
+    <mime-type type="audio/evrc-qcp"/>
+    <mime-type type="audio/evrc0"/>
+    <mime-type type="audio/evrc1"/>
+    <mime-type type="audio/evrcb"/>
+    <mime-type type="audio/evrcb0"/>
+    <mime-type type="audio/evrcb1"/>
+    <mime-type type="audio/evrcwb"/>
+    <mime-type type="audio/evrcwb0"/>
+    <mime-type type="audio/evrcwb1"/>
+    <mime-type type="audio/example"/>
+    <mime-type type="audio/g719"/>
+    <mime-type type="audio/g722"/>
+    <mime-type type="audio/g7221"/>
+    <mime-type type="audio/g723"/>
+    <mime-type type="audio/g726-16"/>
+    <mime-type type="audio/g726-24"/>
+    <mime-type type="audio/g726-32"/>
+    <mime-type type="audio/g726-40"/>
+    <mime-type type="audio/g728"/>
+    <mime-type type="audio/g729"/>
+    <mime-type type="audio/g7291"/>
+    <mime-type type="audio/g729d"/>
+    <mime-type type="audio/g729e"/>
+    <mime-type type="audio/gsm"/>
+    <mime-type type="audio/gsm-efr"/>
+    <mime-type type="audio/ilbc"/>
+    <mime-type type="audio/l16"/>
+    <mime-type type="audio/l20"/>
+    <mime-type type="audio/l24"/>
+    <mime-type type="audio/l8"/>
+    <mime-type type="audio/lpc"/>
+
+    <mime-type type="audio/midi">
+        <acronym>MIDI</acronym>
+        <_comment>Musical Instrument Digital Interface</_comment>
+        <magic priority ="20">
+            <match type="string" value="MThd" offset="0"/>
+        </magic>
+        <glob pattern="*.mid"/>
+        <glob pattern="*.midi"/>
+        <glob pattern="*.kar"/>
+        <glob pattern="*.rmi"/>
+    </mime-type>
+
+    <mime-type type="audio/mobile-xmf"/>
+    <mime-type type="audio/mp4">
+        <alias type="audio/x-m4a"/>
+        <alias type="audio/x-mp4a"/>
+        <magic priority="60">
+            <match value="ftypM4A " type="string" offset="4"/>
+            <match value="ftypM4B " type="string" offset="4"/>
+            <match value="ftypF4A " type="string" offset="4"/>
+            <match value="ftypF4B " type="string" offset="4"/>
+        </magic>
+        <glob pattern="*.mp4a"/>
+        <glob pattern="*.m4a"/>
+        <glob pattern="*.m4b"/>
+    </mime-type>
+    <mime-type type="audio/mp4a-latm"/>
+    <mime-type type="audio/mpa"/>
+    <mime-type type="audio/mpa-robust"/>
+
+    <mime-type type="audio/mpeg">
+        <alias type="audio/x-mpeg"/>
+        <acronym>MP3</acronym>
+        <_comment>MPEG-1 Audio Layer 3</_comment>
+        <magic priority="20">
+            <!-- http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html -->
+            <!-- Bit pattern for first two bytes: 11111111 111VVLLC    -->
+            <!-- VV = MPEG Audio Version ID; 10 = V2, 11 = V1          -->
+            <!-- LL = Layer description; 01 = L3, 10 = L2, 11 = L1     -->
+            <!-- C = Protection bit; 0 = CRC, 1 = no CRC               -->
+            <match value="0xfff2" type="string" offset="0"/> <!-- V2, L3, CRC -->
+            <match value="0xfff3" type="string" offset="0"/> <!-- V2, L3      -->
+            <match value="0xfff4" type="string" offset="0"/> <!-- V2, L2, CRC -->
+            <match value="0xfff5" type="string" offset="0"/> <!-- V2, L2      -->
+            <match value="0xfff6" type="string" offset="0"/> <!-- V2, L1, CRC -->
+            <match value="0xfff7" type="string" offset="0"/> <!-- V2, L1      -->
+            <match value="0xfffa" type="string" offset="0"/> <!-- V1, L3, CRC -->
+            <match value="0xfffb" type="string" offset="0"/> <!-- V1, L3      -->
+            <match value="0xfffc" type="string" offset="0"/> <!-- V1, L2, CRC -->
+            <match value="0xfffd" type="string" offset="0"/> <!-- V1, L2      -->
+            <!-- TIKA-417: This is the UTF-16 LE byte order mark! -->
+            <!-- match value="0xfffe" type="string" offset="0"/ --> <!-- V1, L1, CRC -->
+            <match value="0xffff" type="string" offset="0"/> <!-- V1, L1      -->
+            <match value="ID3" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.mpga"/>
+        <glob pattern="*.mp2"/>
+        <glob pattern="*.mp2a"/>
+        <glob pattern="*.mp3"/>
+        <glob pattern="*.m2a"/>
+        <glob pattern="*.m3a"/>
+    </mime-type>
+
+    <mime-type type="audio/mpeg4-generic"/>
+
+    <mime-type type="audio/ogg">
+        <_comment>Ogg Vorbis Audio</_comment>
+        <glob pattern="*.oga"/>
+        <sub-class-of type="application/ogg"/>
+    </mime-type>
+
+    <mime-type type="audio/vorbis">
+        <_comment>Ogg Vorbis Codec Compressed WAV File</_comment>
+        <alias type="application/x-ogg"/>
+        <magic priority="60">
+            <!-- For a single stream file -->
+            <match value="OggS\000.......................\001vorbis" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <glob pattern="*.ogg"/>
+        <sub-class-of type="audio/ogg"/>
+    </mime-type>
+
+    <mime-type type="audio/x-oggflac">
+        <_comment>Ogg Packaged Free Lossless Audio Codec</_comment>
+        <alias type="audio/x-ogg-flac"/>
+        <magic priority="60">
+            <!-- For a single stream file -->
+            <match value="OggS\000.......................FLAC" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="audio/ogg"/>
+    </mime-type>
+
+    <mime-type type="audio/x-oggpcm">
+        <_comment>Ogg Packaged Unompressed WAV File</_comment>
+        <alias type="audio/x-ogg-pcm"/>
+        <magic priority="60">
+            <!-- For a single stream file -->
+            <match value="OggS\000.......................PCM     " type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="audio/ogg"/>
+    </mime-type>
+
+    <mime-type type="audio/opus">
+        <_comment>Ogg Opus Codec Compressed WAV File</_comment>
+        <magic priority="60">
+            <!-- For a single stream file -->
+            <match value="OggS\000.......................OpusHead" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <glob pattern="*.opus"/>
+        <sub-class-of type="audio/ogg"/>
+    </mime-type>
+
+    <mime-type type="audio/speex">
+        <_comment>Ogg Speex Codec Compressed WAV File</_comment>
+        <alias type="application/x-speex"/>
+        <magic priority="60">
+            <!-- For a single stream file -->
+            <match value="OggS\000.......................Speex   " type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <glob pattern="*.spx"/>
+        <sub-class-of type="audio/ogg"/>
+    </mime-type>
+
+    <mime-type type="audio/parityfec"/>
+    <mime-type type="audio/pcma"/>
+    <mime-type type="audio/pcma-wb"/>
+    <mime-type type="audio/pcmu-wb"/>
+    <mime-type type="audio/pcmu"/>
+
+    <mime-type type="audio/prs.sid">
+        <magic priority="50">
+            <match value="PSID" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="audio/qcelp"/>
+    <mime-type type="audio/red"/>
+    <mime-type type="audio/rtp-enc-aescm128"/>
+    <mime-type type="audio/rtp-midi"/>
+    <mime-type type="audio/rtx"/>
+    <mime-type type="audio/smv"/>
+    <mime-type type="audio/smv0"/>
+    <mime-type type="audio/smv-qcp"/>
+    <mime-type type="audio/sp-midi"/>
+    <mime-type type="audio/t140c"/>
+    <mime-type type="audio/t38"/>
+    <mime-type type="audio/telephone-event"/>
+    <mime-type type="audio/tone"/>
+    <mime-type type="audio/ulpfec"/>
+    <mime-type type="audio/vdvi"/>
+    <mime-type type="audio/vmr-wb"/>
+    <mime-type type="audio/vnd.3gpp.iufp"/>
+    <mime-type type="audio/vnd.4sb"/>
+    <mime-type type="audio/vnd.audiokoz"/>
+    <mime-type type="audio/vnd.adobe.soundbooth">
+        <glob pattern="*.asnd"/>
+    </mime-type>
+    <mime-type type="audio/vnd.celp"/>
+    <mime-type type="audio/vnd.cisco.nse"/>
+    <mime-type type="audio/vnd.cmles.radio-events"/>
+    <mime-type type="audio/vnd.cns.anp1"/>
+    <mime-type type="audio/vnd.cns.inf1"/>
+    <mime-type type="audio/vnd.digital-winds">
+        <glob pattern="*.eol"/>
+    </mime-type>
+    <mime-type type="audio/vnd.dlna.adts"/>
+    <mime-type type="audio/vnd.dolby.heaac.1"/>
+    <mime-type type="audio/vnd.dolby.heaac.2"/>
+    <mime-type type="audio/vnd.dolby.mlp"/>
+    <mime-type type="audio/vnd.dolby.mps"/>
+    <mime-type type="audio/vnd.dolby.pl2"/>
+    <mime-type type="audio/vnd.dolby.pl2x"/>
+    <mime-type type="audio/vnd.dolby.pl2z"/>
+    <mime-type type="audio/vnd.dts">
+        <glob pattern="*.dts"/>
+    </mime-type>
+    <mime-type type="audio/vnd.dts.hd">
+        <glob pattern="*.dtshd"/>
+    </mime-type>
+    <mime-type type="audio/vnd.everad.plj"/>
+    <mime-type type="audio/vnd.hns.audio"/>
+    <mime-type type="audio/vnd.lucent.voice">
+        <glob pattern="*.lvp"/>
+    </mime-type>
+    <mime-type type="audio/vnd.ms-playready.media.pya">
+        <glob pattern="*.pya"/>
+    </mime-type>
+    <mime-type type="audio/vnd.nokia.mobile-xmf"/>
+    <mime-type type="audio/vnd.nortel.vbk"/>
+    <mime-type type="audio/vnd.nuera.ecelp4800">
+        <glob pattern="*.ecelp4800"/>
+    </mime-type>
+    <mime-type type="audio/vnd.nuera.ecelp7470">
+        <glob pattern="*.ecelp7470"/>
+    </mime-type>
+    <mime-type type="audio/vnd.nuera.ecelp9600">
+        <glob pattern="*.ecelp9600"/>
+    </mime-type>
+    <mime-type type="audio/vnd.octel.sbc"/>
+    <mime-type type="audio/vnd.qcelp"/>
+    <mime-type type="audio/vnd.rhetorex.32kadpcm"/>
+    <mime-type type="audio/vnd.sealedmedia.softseal.mpeg"/>
+    <mime-type type="audio/vnd.vmx.cvsd"/>
+    <mime-type type="audio/vorbis-config"/>
+    <mime-type type="audio/x-aac">
+        <glob pattern="*.aac"/>
+    </mime-type>
+
+    <mime-type type="audio/x-adbcm">
+        <magic priority="20">
+            <match value=".snd" type="string" offset="0">
+                <match value="23" type="big32" offset="12"/>
+            </match>
+        </magic>
+    </mime-type>
+
+    <mime-type type="audio/x-aiff">
+        <alias type="audio/aiff"/>
+        <acronym>AIFF</acronym>
+        <_comment>Audio Interchange File Format</_comment>
+        <magic priority="20">
+            <match value="FORM....AIFF" type="string" offset="0"
+                   mask="0xFFFFFFFF00000000FFFFFFFF"/>
+            <match value="FORM....AIFC" type="string" offset="0"
+                   mask="0xFFFFFFFF00000000FFFFFFFF"/>
+            <!-- Amiga IFF sound sample, somewhat like the more modern AIFF -->
+            <match value="FORM....8SVX" type="string" offset="0"
+                   mask="0xFFFFFFFF00000000FFFFFFFF"/>
+            <match offset="0" type="string" value="\x46\x4f\x52\x4d\x00"/>
+        </magic>
+        <glob pattern="*.aif"/>
+        <glob pattern="*.aiff"/>
+        <glob pattern="*.aifc"/>
+    </mime-type>
+
+    <mime-type type="audio/x-dec-basic">
+        <magic priority="20">
+            <match value="0x0064732E" type="big32" offset="0">
+                <match value="1" type="big32" offset="12"/>
+                <match value="2" type="big32" offset="12"/>
+                <match value="3" type="big32" offset="12"/>
+                <match value="4" type="big32" offset="12"/>
+                <match value="5" type="big32" offset="12"/>
+                <match value="6" type="big32" offset="12"/>
+                <match value="7" type="big32" offset="12"/>
+            </match>
+        </magic>
+    </mime-type>
+
+    <mime-type type="audio/x-dec-adbcm">
+        <magic priority="20">
+            <match value="0x0064732E" type="big32" offset="0">
+                <match value="23" type="big32" offset="12"/>
+            </match>
+        </magic>
+    </mime-type>
+
+    <mime-type type="audio/x-flac">
+        <acronym>FLAC</acronym>
+        <_comment>Free Lossless Audio Codec</_comment>
+        <magic priority="50">
+            <match value="fLaC" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.flac"/>
+    </mime-type>
+
+    <mime-type type="audio/x-mod">
+        <acronym>MOD</acronym>
+        <magic priority="50">
+            <match value="Extended\ Module:" type="string" offset="0"/>
+            <match value="BMOD2STM" type="string" offset="21"/>
+            <match value="M.K." type="string" offset="1080"/>
+            <match value="M!K!" type="string" offset="1080"/>
+            <match value="FLT4" type="string" offset="1080"/>
+            <match value="FLT8" type="string" offset="1080"/>
+            <match value="4CHN" type="string" offset="1080"/>
+            <match value="6CHN" type="string" offset="1080"/>
+            <match value="8CHN" type="string" offset="1080"/>
+            <match value="CD81" type="string" offset="1080"/>
+            <match value="OKTA" type="string" offset="1080"/>
+            <match value="16CN" type="string" offset="1080"/>
+            <match value="32CN" type="string" offset="1080"/>
+            <match value="IMPM" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.mod"/>
+    </mime-type>
+
+    <mime-type type="audio/x-mpegurl">
+        <_comment>MP3 Playlist File</_comment>
+        <magic priority="50">
+            <match offset="0" type="string" value="\x23\x45\x58\x54\x4d\x33\x55\x0d\x0a"/>
+        </magic>
+        <glob pattern="*.m3u"/>
+    </mime-type>
+
+    <mime-type type="audio/x-ms-wax">
+        <glob pattern="*.wax"/>
+    </mime-type>
+    <mime-type type="audio/x-ms-wma">
+        <sub-class-of type="video/x-ms-asf" />
+        <glob pattern="*.wma"/>
+        <magic priority="50">
+            <match value="Windows Media Audio" type="unicodeLE" offset="0:8192" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="audio/x-pn-realaudio">
+        <_comment>Real Audio</_comment>
+        <alias type="audio/x-realaudio" />
+        <magic priority="50">
+            <match value="0x2e7261fd" type="big32" offset="0"/>
+        </magic>
+        <glob pattern="*.ram"/>
+        <glob pattern="*.ra"/>
+    </mime-type>
+
+    <mime-type type="audio/x-pn-realaudio-plugin">
+        <_comment>RealMedia Player Plug-in</_comment>
+        <glob pattern="*.rmp"/>
+        <!-- <glob pattern="*.rpm"/> - conflicts with application/x-rpm -->
+    </mime-type>
+
+    <mime-type type="audio/x-wav">
+        <acronym>WAV</acronym>
+        <magic priority="20">
+            <match value="RIFF....WAVE" type="string" offset="0"
+                   mask="0xFFFFFFFF00000000FFFFFFFF"/>
+        </magic>
+        <glob pattern="*.wav"/>
+    </mime-type>
+
+    <mime-type type="chemical/x-cdx">
+        <magic priority="50">
+            <match value="VjCD0100" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.cdx"/>
+    </mime-type>
+    <mime-type type="chemical/x-cif">
+        <glob pattern="*.cif"/>
+    </mime-type>
+    <mime-type type="chemical/x-cmdf">
+        <glob pattern="*.cmdf"/>
+    </mime-type>
+    <mime-type type="chemical/x-cml">
+        <glob pattern="*.cml"/>
+    </mime-type>
+    <mime-type type="chemical/x-csml">
+        <glob pattern="*.csml"/>
+    </mime-type>
+
+    <mime-type type="chemical/x-pdb">
+        <_comment>Brookhaven Protein Databank File</_comment>
+        <glob pattern="*.pdb"/>
+    </mime-type>
+
+    <mime-type type="chemical/x-xyz">
+        <glob pattern="*.xyz"/>
+    </mime-type>
+
+    <mime-type type="image/x-ms-bmp">
+        <alias type="image/bmp"/>
+        <acronym>BMP</acronym>
+        <_comment>Windows bitmap</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/BMP_file_format</tika:link>
+        <tika:uti>com.microsoft.bmp</tika:uti>
+        <magic priority="50">
+            <match value="BM" type="string" offset="0">
+                <match value="0x0100" type="string" offset="26">
+                    <match value="0x0000" type="string" offset="28"/>
+                    <match value="0x0100" type="string" offset="28"/>
+                    <match value="0x0400" type="string" offset="28"/>
+                    <match value="0x0800" type="string" offset="28"/>
+                    <match value="0x1000" type="string" offset="28"/>
+                    <match value="0x1800" type="string" offset="28"/>
+                    <match value="0x2000" type="string" offset="28"/>
+                </match>
+            </match>
+        </magic>
+        <glob pattern="*.bmp"/>
+        <glob pattern="*.dib"/>
+    </mime-type>
+
+    <mime-type type="image/cgm">
+        <acronym>CGM</acronym>
+        <_comment>Computer Graphics Metafile</_comment>
+        <magic priority="50">
+            <match value="BEGMF" type="string" offset="0"/>
+            <match value="0x0020" mask="0xffe0" type="string" offset="0">
+                <match value="0x10220001" type="string" offset="2:64"/>
+                <match value="0x10220002" type="string" offset="2:64"/>
+                <match value="0x10220003" type="string" offset="2:64"/>
+                <match value="0x10220004" type="string" offset="2:64"/>
+            </match>
+        </magic>
+        <glob pattern="*.cgm"/>
+    </mime-type>
+
+    <mime-type type="image/example"/>
+
+    <mime-type type="image/fits">
+        <sub-class-of type="application/fits"/>
+    </mime-type>
+
+    <mime-type type="image/g3fax">
+        <glob pattern="*.g3"/>
+    </mime-type>
+
+    <mime-type type="image/gif">
+        <acronym>GIF</acronym>
+        <_comment>Graphics Interchange Format</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/Gif</tika:link>
+        <tika:uti>com.compuserve.gif</tika:uti>
+        <magic priority="50">
+            <match value="GIF87a" type="string" offset="0"/>
+            <match value="GIF89a" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.gif"/>
+    </mime-type>
+
+    <mime-type type="image/ief">
+        <glob pattern="*.ief"/>
+    </mime-type>
+
+    <mime-type type="image/jp2">
+        <sub-class-of type="image/x-jp2-container" />
+        <acronym>JP2</acronym>
+        <_comment>JPEG 2000 Part 1 (JP2)</_comment>
+        <magic priority="50">
+            <match value="0x0000000C6A5020200D0A870A" type="string" offset="0">
+                <match value="0x6a703220" type="string" offset="20"/>
+            </match>
+        </magic>
+        <glob pattern="*.jp2"/>
+    </mime-type>
+
+    <mime-type type="image/jpeg">
+        <acronym>JPEG</acronym>
+        <_comment>Joint Photographic Experts Group</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/Jpeg</tika:link>
+        <tika:uti>public.jpeg</tika:uti>
+        <magic priority="50">
+            <!-- FFD8 is the SOI (Start Of Image) marker.              -->
+            <!-- It is followed by another marker that starts with FF. -->
+            <match value="0xffd8ff" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.jpg"/>
+        <glob pattern="*.jpeg"/>
+        <glob pattern="*.jpe"/>
+        <glob pattern="*.jif"/>
+        <glob pattern="*.jfif"/>
+        <glob pattern="*.jfi"/>
+    </mime-type>
+
+    <mime-type type="image/jpm">
+        <alias type="video/jpm"/>
+        <sub-class-of type="image/x-jp2-container" />
+        <acronym>JP2</acronym>
+        <_comment>JPEG 2000 Part 6 (JPM)</_comment>
+        <magic priority="50">
+            <match value="0x0000000C6A5020200D0A870A" type="string" offset="0">
+                <match value="0x6a706d20" type="string" offset="20"/>
+            </match>
+        </magic>
+        <glob pattern="*.jpm"/>
+        <glob pattern="*.jpgm"/>
+    </mime-type>
+
+    <mime-type type="image/jpx">
+        <sub-class-of type="image/x-jp2-container" />
+        <acronym>JP2</acronym>
+        <_comment>JPEG 2000 Part 2 (JPX)</_comment>
+        <magic priority="50">
+            <match value="0x0000000C6A5020200D0A870A" type="string" offset="0">
+                <match value="0x6a707820" type="string" offset="20"/>
+            </match>
+        </magic>
+        <glob pattern="*.jpf"/>
+    </mime-type>
+
+    <mime-type type="image/naplps"/>
+
+    <mime-type type="image/nitf">
+        <alias type="image/ntf"/>
+        <magic priority="50">
+            <match value="NITF01.10" type="string" offset="0"/>
+            <match value="NITF02.000" type="string" offset="0"/>
+            <match value="NITF02.100" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.ntf"/>
+        <glob pattern="*.nitf"/>
+    </mime-type>
+
+    <mime-type type="image/png">
+        <acronym>PNG</acronym>
+        <_comment>Portable Network Graphics</_comment>
+        <magic priority="50">
+            <match value="\x89PNG\x0d\x0a\x1a\x0a" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.png"/>
+    </mime-type>
+
+    <mime-type type="image/prs.btif">
+        <glob pattern="*.btif"/>
+    </mime-type>
+    <mime-type type="image/prs.pti"/>
+
+    <mime-type type="image/svg+xml">
+        <sub-class-of type="application/xml"/>
+        <acronym>SVG</acronym>
+        <_comment>Scalable Vector Graphics</_comment>
+        <root-XML localName="svg" namespaceURI="http://www.w3.org/2000/svg"/>
+        <glob pattern="*.svg"/>
+        <glob pattern="*.svgz"/>
+    </mime-type>
+
+    <mime-type type="image/t38"/>
+
+    <mime-type type="image/tiff">
+        <acronym>TIFF</acronym>
+        <_comment>Tagged Image File Format</_comment>
+        <magic priority="50">
+            <!-- MM.* = Big endian (M=Motorola) and 0x002a in big endian    -->
+            <match value="MM\x00\x2a" type="string" offset="0"/>
+            <!-- II*. = Little endian (I=Intel) and 0x002a in little endian -->
+            <match value="II\x2a\x00" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.tiff"/>
+        <glob pattern="*.tif"/>
+    </mime-type>
+
+    <mime-type type="image/tiff-fx"/>
+
+    <mime-type type="image/vnd.adobe.photoshop">
+        <acronym>PSD</acronym>
+        <_comment>Photoshop Image</_comment>
+        <alias type="image/x-psd"/>
+        <alias type="application/photoshop"/>
+        <magic priority="50">
+            <!-- Version of 0x0001 is PSD -->
+            <match value="8BPS\x00\x01" type="string" offset="0"/>
+            <!-- Version of 0x0002 is PSB -->
+            <match value="8BPS\x00\x02" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.psd"/>
+    </mime-type>
+
+    <mime-type type="image/vnd.adobe.premiere">
+        <glob pattern="*.ppj"/>
+        <root-XML localName="PremiereData"/>
+        <sub-class-of type="application/xml"/>
+    </mime-type>
+
+    <mime-type type="image/vnd.cns.inf2"/>
+    <mime-type type="image/vnd.djvu">
+        <glob pattern="*.djvu"/>
+        <glob pattern="*.djv"/>
+    </mime-type>
+
+    <mime-type type="image/vnd.dwg">
+        <acronym>DWG</acronym>
+        <_comment>AutoCad Drawing</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/.dwg</tika:link>
+        <alias type="image/x-dwg"/>
+        <alias type="application/acad"/>
+        <alias type="application/x-acad"/>
+        <alias type="application/autocad_dwg"/>
+        <alias type="application/dwg"/>
+        <alias type="application/x-dwg"/>
+        <alias type="application/x-autocad"/>
+        <alias type="image/vnd.dwg"/>
+        <alias type="drawing/dwg"/>
+        <glob pattern="*.dwg"/>
+        <magic priority="50">
+            <match value="MC0.0" type="string" offset="0"/>
+            <match value="AC1.2" type="string" offset="0"/>
+            <match value="AC1.40" type="string" offset="0"/>
+            <match value="AC1.50" type="string" offset="0"/>
+            <match value="AC2.10" type="string" offset="0"/>
+            <match value="AC2.21" type="string" offset="0"/>
+            <match value="AC2.22" type="string" offset="0"/>
+            <!-- "AC" followed by four numbers -->
+            <match value="AC0000" type="string" offset="0"
+                   mask="0xFFFFF0F0F0F0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="image/vnd.dxf">
+        <acronym>DXF</acronym>
+        <_comment>AutoCAD DXF</_comment>
+        <tika:link>http://en.wikipedia.org/wiki/AutoCAD_DXF</tika:link>
+        <glob pattern="*.dxf"/>
+    </mime-type>
+    <mime-type type="image/vnd.fastbidsheet">
+        <glob pattern="*.fbs"/>
+    </mime-type>
+    <mime-type type="image/vnd.fpx">
+        <glob pattern="*.fpx"/>
+    </mime-type>
+    <mime-type type="image/vnd.fst">
+        <glob pattern="*.fst"/>
+    </mime-type>
+    <mime-type type="image/vnd.fujixerox.edmics-mmr">
+        <glob pattern="*.mmr"/>
+    </mime-type>
+    <mime-type type="image/vnd.fujixerox.edmics-rlc">
+        <glob pattern="*.rlc"/>
+    </mime-type>
+    <mime-type type="image/vnd.globalgraphics.pgb"/>
+
+    <mime-type type="image/vnd.microsoft.icon">
+        <acronym>ICO</acronym>
+        <tika:link>http://en.wikipedia.org/wiki/.ico</tika:link>
+        <tika:uti>com.microsoft.ico</tika:uti>
+        <alias type="image/x-icon" />
+        <magic priority="50">
+            <match value="\102\101\050\000\000\000\056\000\000\000\000\000\000\000"
+                   type="string" offset="0"/>
+            <match value="\000\000\001\000" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.ico"/>
+    </mime-type>
+
+    <mime-type type="image/vnd.mix"/>
+    <mime-type type="image/vnd.ms-modi">
+        <glob pattern="*.mdi"/>
+        <_comment>Microsoft Document Imaging</_comment>
+        <magic priority="50">
+            <match value="0x45502A00" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="image/vnd.net-fpx">
+        <glob pattern="*.npx"/>
+    </mime-type>
+    <mime-type type="image/vnd.radiance"/>
+    <mime-type type="image/vnd.sealed.png"/>
+    <mime-type type="image/vnd.sealedmedia.softseal.gif"/>
+    <mime-type type="image/vnd.sealedmedia.softseal.jpg"/>
+    <mime-type type="image/vnd.svf"/>
+
+    <mime-type type="image/vnd.wap.wbmp">
+        <_comment>Wireless Bitmap File Format</_comment>
+        <glob pattern="*.wbmp"/>
+    </mime-type>
+
+    <mime-type type="image/vnd.xiff">
+        <glob pattern="*.xif"/>
+    </mime-type>
+    <mime-type type="image/x-cmu-raster">
+        <glob pattern="*.ras"/>
+    </mime-type>
+    <mime-type type="image/x-cmx">
+        <glob pattern="*.cmx"/>
+    </mime-type>
+
+    <mime-type type="image/x-freehand">
+        <_comment>FreeHand image</_comment>
+        <magic priority="50">
+            <match value="AGD2" type="string" offset="0"/>
+            <match value="AGD3" type="string" offset="0"/>
+            <match value="AGD4" type="string" offset="0"/>
+            <match value="FreeHand10" type="string" offset="0:24"/>
+            <match value="FreeHand11" type="string" offset="0:24"/>
+            <match value="FreeHand12" type="string" offset="0:24"/>
+        </magic>
+        <glob pattern="*.fh"/>
+        <glob pattern="*.fhc"/>
+        <glob pattern="*.fh4"/>
+        <glob pattern="*.fh40"/>
+        <glob pattern="*.fh5"/>
+        <glob pattern="*.fh50"/>
+        <glob pattern="*.fh7"/>
+        <glob pattern="*.fh8"/>
+        <glob pattern="*.fh9"/>
+        <glob pattern="*.fh10"/>
+        <glob pattern="*.fh11"/>
+        <glob pattern="*.fh12"/>
+        <glob pattern="*.ft7"/>
+        <glob pattern="*.ft8"/>
+        <glob pattern="*.ft9"/>
+        <glob pattern="*.ft10"/>
+        <glob pattern="*.ft11"/>
+        <glob pattern="*.ft12"/>
+    </mime-type>
+
+    <mime-type type="image/x-jp2-codestream">
+        <_comment>JPEG 2000 Codestream</_comment>
+        <magic priority="25">
+            <match value="0xff4fff51" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.j2c"/>
+    </mime-type>
+
+    <mime-type type="image/x-jp2-container">
+        <_comment>JPEG 2000 Container Format</_comment>
+        <magic priority="50">
+            <match value="0x0000000C6A5020200D0A870A" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="image/x-niff">
+        <_comment>Navy Interchange File Format</_comment>
+        <magic priority="50">
+            <match value="IIN1" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="image/x-pcx">
+        <glob pattern="*.pcx"/>
+    </mime-type>
+    <mime-type type="image/x-pict">
+        <_comment>Apple Macintosh QuickDraw/PICT Format</_comment>
+        <magic priority="50">
+            <match value="0x001102FF0C00" type="string" offset="522"/>
+        </magic>
+        <glob pattern="*.pic"/>
+        <glob pattern="*.pct"/>
+        <glob pattern="*.pict"/>
+    </mime-type>
+
+    <mime-type type="image/x-portable-anymap">
+        <acronym>PNM</acronym>
+        <_comment>Portable Any Map</_comment>
+        <glob pattern="*.pnm" />
+    </mime-type>
+
+    <mime-type type="image/x-portable-bitmap">
+        <sub-class-of type="image/x-portable-anymap"/>
+        <acronym>PBM</acronym>
+        <_comment>Portable Bit Map</_comment>
+        <magic priority="50">
+            <match value="P1" type="string" offset="0"/>
+            <match value="P4" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.pbm"/>
+    </mime-type>
+
+    <mime-type type="image/x-portable-graymap">
+        <sub-class-of type="image/x-portable-anymap"/>
+        <acronym>PGM</acronym>
+        <_comment>Portable Graymap Graphic</_comment>
+        <magic priority="50">
+            <match value="P2" type="string" offset="0"/>
+            <match value="P5" type="string" offset="0"/>
+            <match offset="0" type="string" value="\x50\x35\x0a"/>
+        </magic>
+        <glob pattern="*.pgm"/>
+    </mime-type>
+
+    <mime-type type="image/x-portable-pixmap">
+        <sub-class-of type="image/x-portable-anymap"/>
+        <acronym>PXM</acronym>
+        <_comment>UNIX Portable Bitmap Graphic</_comment>
+        <magic priority="50">
+            <match value="P3" type="string" offset="0"/>
+            <match value="P6" type="string" offset="0"/>
+            <match value="P7" type="string" offset="0"/>
+            <match offset="0" type="string" value="\x50\x34\x0a"/>
+        </magic>
+        <glob pattern="*.ppm"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-adobe">
+        <acronym>DNG</acronym>
+        <_comment>Adobe Digital Negative</_comment>
+        <glob pattern="*.dng"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-hasselblad">
+        <_comment>Hasselblad raw image</_comment>
+        <glob pattern="*.3fr"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-fuji">
+        <_comment>Fuji raw image</_comment>
+        <glob pattern="*.raf"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-canon">
+        <_comment>Canon raw image</_comment>
+        <glob pattern="*.crw"/>
+        <glob pattern="*.cr2"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-kodak">
+        <_comment>Kodak raw image</_comment>
+        <glob pattern="*.k25"/>
+        <glob pattern="*.kdc"/>
+        <glob pattern="*.dcs"/>
+        <glob pattern="*.drf"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-minolta">
+        <_comment>Minolta raw image</_comment>
+        <glob pattern="*.mrw"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-nikon">
+        <_comment>Nikon raw image</_comment>
+        <glob pattern="*.nef"/>
+        <glob pattern="*.nrw"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-olympus">
+        <_comment>Olympus raw image</_comment>
+        <glob pattern="*.orf"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-pentax">
+        <_comment>Pentax raw image</_comment>
+        <glob pattern="*.ptx"/>
+        <glob pattern="*.pef"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-sony">
+        <_comment>Sony raw image</_comment>
+        <glob pattern="*.arw"/>
+        <glob pattern="*.srf"/>
+        <glob pattern="*.sr2"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-sigma">
+        <_comment>Sigma raw image</_comment>
+        <glob pattern="*.x3f"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-epson">
+        <_comment>Epson raw image</_comment>
+        <glob pattern="*.erf"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-mamiya">
+        <_comment>Mamiya raw image</_comment>
+        <glob pattern="*.mef"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-leaf">
+        <_comment>Leaf raw image</_comment>
+        <glob pattern="*.mos"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-panasonic">
+        <_comment>Panasonic raw image</_comment>
+        <glob pattern="*.raw"/>
+        <glob pattern="*.rw2"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-phaseone">
+        <_comment>Phase One raw image</_comment>
+        <glob pattern="*.iiq"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-red">
+        <_comment>Red raw image</_comment>
+        <glob pattern="*.r3d"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-imacon">
+        <_comment>Imacon raw image</_comment>
+        <glob pattern="*.fff"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-logitech">
+        <_comment>Logitech raw image</_comment>
+        <glob pattern="*.pxn"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-casio">
+        <_comment>Casio raw image</_comment>
+        <glob pattern="*.bay"/>
+    </mime-type>
+
+    <mime-type type="image/x-raw-rawzor">
+        <_comment>Rawzor raw image</_comment>
+        <glob pattern="*.rwz"/>
+    </mime-type>
+
+    <mime-type type="image/x-rgb">
+        <_comment>Silicon Graphics RGB Bitmap</_comment>
+        <magic priority="50">
+            <match offset="0" type="string" value="\x01\xda\x01\x01\x00\x03"/>
+        </magic>
+        <glob pattern="*.rgb"/>
+    </mime-type>
+
+    <mime-type type="image/x-xbitmap">
+        <magic priority="50">
+            <match value="/* XPM" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.xbm"/>
+        <sub-class-of type="text/x-c"/>
+    </mime-type>
+
+    <mime-type type="image/x-xcf">
+        <_comment>GIMP Image File</_comment>
+        <alias type="image/xcf"/>
+        <magic priority="50">
+            <match type="string" value="gimp xcf " offset="0"/>
+        </magic>
+        <glob pattern="*.xcf"/>
+    </mime-type>
+
+    <mime-type type="image/x-xpixmap">
+        <glob pattern="*.xpm"/>
+    </mime-type>
+
+    <mime-type type="image/x-xwindowdump">
+        <_comment>X Windows Dump</_comment>
+        <glob pattern="*.xwd"/>
+    </mime-type>
+
+    <mime-type type="message/cpim"/>
+    <mime-type type="message/delivery-status"/>
+    <mime-type type="message/disposition-notification"/>
+    <mime-type type="message/example"/>
+    <mime-type type="message/external-body"/>
+    <mime-type type="message/global"/>
+    <mime-type type="message/global-delivery-status"/>
+    <mime-type type="message/global-disposition-notification"/>
+    <mime-type type="message/global-headers"/>
+    <mime-type type="message/http"/>
+    <mime-type type="message/imdn+xml"/>
+
+    <mime-type type="message/news">
+        <magic priority="50">
+            <match value="Path:" type="string" offset="0" />
+            <match value="Xref:" type="string" offset="0" />
+            <match value="Article" type="string" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="message/partial"/>
+
+    <mime-type type="message/rfc822">
+        <magic priority="50">
+            <match value="Relay-Version:" type="stringignorecase" offset="0"/>
+            <match value="#!\ rnews" type="string" offset="0"/>
+            <match value="N#!\ rnews" type="string" offset="0"/>
+            <match value="Forward\ to" type="string" offset="0"/>
+            <match value="Pipe\ to" type="string" offset="0"/>
+            <match value="Return-Path:" type="stringignorecase" offset="0"/>
+            <match value="From:" type="stringignorecase" offset="0"/>
+            <match value="Received:" type="stringignorecase" offset="0"/>
+            <match value="Message-ID:" type="stringignorecase" offset="0"/>
+            <match value="Date:" type="string" offset="0"/>
+            <match value="MIME-Version:" type="stringignorecase" offset="0"/>
+            <match value="X-Notes-Item:" type="string" offset="0">
+                <match value="Message-ID:" type="string" offset="0:8192"/>
+            </match>
+        </magic>
+        <glob pattern="*.eml"/>
+        <glob pattern="*.mime"/>
+        <glob pattern="*.mht"/>
+        <glob pattern="*.mhtml"/>
+    </mime-type>
+
+    <mime-type type="message/s-http"/>
+    <mime-type type="message/sip"/>
+    <mime-type type="message/sipfrag"/>
+    <mime-type type="message/tracking-status"/>
+    <mime-type type="message/vnd.si.simp"/>
+
+    <mime-type type="model/example"/>
+
+    <mime-type type="model/iges">
+        <_comment>Initial Graphics Exchange Specification Format</_comment>
+        <glob pattern="*.igs"/>
+        <glob pattern="*.iges"/>
+    </mime-type>
+
+    <mime-type type="model/mesh">
+        <glob pattern="*.msh"/>
+        <glob pattern="*.mesh"/>
+        <glob pattern="*.silo"/>
+    </mime-type>
+
+    <mime-type type="model/vnd.dwf">
+        <glob pattern="*.dwf"/>
+    </mime-type>
+    <mime-type type="model/vnd.dwfx+xps">
+        <_comment>AutoCAD Design Web Format</_comment>
+        <glob pattern="*.dwfx"/>
+        <sub-class-of type="application/x-tika-ooxml"/>
+    </mime-type>
+
+    <mime-type type="model/vnd.flatland.3dml"/>
+    <mime-type type="model/vnd.gdl">
+        <glob pattern="*.gdl"/>
+    </mime-type>
+    <mime-type type="model/vnd.gs-gdl"/>
+    <mime-type type="model/vnd.gs.gdl"/>
+    <mime-type type="model/vnd.gtw">
+        <glob pattern="*.gtw"/>
+    </mime-type>
+    <mime-type type="model/vnd.moml+xml"/>
+    <mime-type type="model/vnd.mts">
+        <glob pattern="*.mts"/>
+    </mime-type>
+    <mime-type type="model/vnd.parasolid.transmit.binary"/>
+    <mime-type type="model/vnd.parasolid.transmit.text"/>
+    <mime-type type="model/vnd.vtu">
+        <glob pattern="*.vtu"/>
+    </mime-type>
+
+    <mime-type type="model/vrml">
+        <glob pattern="*.wrl"/>
+        <glob pattern="*.vrml"/>
+    </mime-type>
+
+    <mime-type type="multipart/alternative"/>
+    <mime-type type="multipart/appledouble"/>
+    <mime-type type="multipart/byteranges"/>
+    <mime-type type="multipart/digest"/>
+    <mime-type type="multipart/encrypted"/>
+    <mime-type type="multipart/example"/>
+    <mime-type type="multipart/form-data"/>
+    <mime-type type="multipart/header-set"/>
+    <mime-type type="multipart/mixed"/>
+    <mime-type type="multipart/parallel"/>
+    <mime-type type="multipart/related"/>
+    <mime-type type="multipart/report"/>
+    <mime-type type="multipart/signed"/>
+    <mime-type type="multipart/voice-message"/>
+
+    <mime-type type="text/x-actionscript">
+        <_comment>ActionScript source code</_comment>
+        <glob pattern="*.as"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-ada">
+        <_comment>Ada source code</_comment>
+        <glob pattern="*.ada"/>
+        <glob pattern="*.adb"/>
+        <glob pattern="*.ads"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-applescript">
+        <_comment>AppleScript source code</_comment>
+        <glob pattern="*.applescript"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/asp">
+        <_comment>Active Server Page</_comment>
+        <glob pattern="*.asp"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/aspdotnet">
+        <_comment>ASP .NET</_comment>
+        <glob pattern="*.aspx"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-aspectj">
+        <_comment>AspectJ source code</_comment>
+        <glob pattern="*.aj"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-assembly">
+        <alias type="text/x-asm"/>
+        <_comment>Assembler source code</_comment>
+        <glob pattern="*.s"/>
+        <glob pattern="*.S"/>
+        <glob pattern="*.asm"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/calendar">
+        <glob pattern="*.ics"/>
+        <glob pattern="*.ifb"/>
+    </mime-type>
+
+    <mime-type type="text/css">
+        <_comment>Cascading Style Sheet</_comment>
+        <glob pattern="*.css"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/csv">
+        <glob pattern="*.csv"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/directory"/>
+    <mime-type type="text/dns"/>
+    <mime-type type="text/ecmascript"/>
+    <mime-type type="text/enriched"/>
+    <mime-type type="text/example"/>
+
+    <mime-type type="text/html">
+        <_comment>HyperText Markup Language</_comment>
+        <acronym>HTML</acronym>
+        <tika:uti>public.html</tika:uti>
+        <!-- TIKA-327: if you encounter tags in the HTML
+          with no declared namespace, it's not XHTML, it's just
+          bad HTML, unfortunately.
+     -->
+        <root-XML localName="html"/>
+        <root-XML localName="HTML"/>
+        <root-XML localName="link"/>
+        <root-XML localName="LINK"/>
+        <root-XML localName="body"/>
+        <root-XML localName="BODY"/>
+        <root-XML localName="p"/>
+        <root-XML localName="P"/>
+        <root-XML localName="script"/>
+        <root-XML localName="SCRIPT"/>
+        <root-XML localName="frameset"/>
+        <root-XML localName="FRAMESET"/>
+        <!-- The magic priority needs to be lower than that of -->
+        <!--  files which contain HTML within them, eg mime emails -->
+        <magic priority="40">
+            <match value="&lt;!DOCTYPE HTML" type="string" offset="0:64"/>
+            <match value="&lt;!doctype html" type="string" offset="0:64"/>
+            <match value="&lt;HEAD" type="string" offset="0:64"/>
+            <match value="&lt;head" type="string" offset="0:64"/>
+            <match value="&lt;TITLE" type="string" offset="0:64"/>
+            <match value="&lt;title" type="string" offset="0:64"/>
+            <!-- note on the offset value here: this can only be as big as
+           MimeTypes#getMinLength(). If you set the offset value to larger
+           than that size, the magic will only be compared to up to
+           MimeTypes#getMinLength() bytes.
+       -->
+            <match value="&lt;html" type="string" offset="0:8192"/>
+            <match value="&lt;HTML" type="string" offset="0:64"/>
+            <match value="&lt;BODY" type="string" offset="0"/>
+            <match value="&lt;body" type="string" offset="0"/>
+            <match value="&lt;DIV" type="string" offset="0"/>
+            <match value="&lt;div" type="string" offset="0"/>
+            <match value="&lt;TITLE" type="string" offset="0"/>
+            <match value="&lt;title" type="string" offset="0"/>
+            <match value="&lt;h1" type="string" offset="0"/>
+            <match value="&lt;H1" type="string" offset="0"/>
+            <match value="&lt;!doctype HTML" type="string" offset="0"/>
+            <match value="&lt;!DOCTYPE html" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.html"/>
+        <glob pattern="*.htm"/>
+    </mime-type>
+
+    <mime-type type="text/parityfec"/>
+
+    <mime-type type="text/plain">
+        <magic priority="20">
+            <match value="This is TeX," type="string" offset="0"/>
+            <match value="This is METAFONT," type="string" offset="0"/>
+            <match value="/*" type="string" offset="0"/>
+            <match value="//" type="string" offset="0"/>
+            <match value=";;" type="string" offset="0"/>
+            <!-- UTF-16BE BOM -->
+            <match value="0xfeff" type="string" offset="0"/>
+            <!-- UTF-16LE BOM -->
+            <match value="0xfffe" type="string" offset="0"/>
+            <!-- UTF-8 BOM -->
+            <match value="0xefbbbf" type="string" offset="0"/>
+        </magic>
+
+        <glob pattern="*.txt"/>
+        <glob pattern="*.text"/>
+        <glob pattern="*.conf"/>
+        <glob pattern="*.cfg"/>
+        <glob pattern="*.def"/>
+        <glob pattern="*.list"/>
+        <glob pattern="*.in"/>
+
+        <!-- TIKA-85: http://www.apache.org/dev/svn-eol-style.txt -->
+        <glob pattern="INSTALL"/>
+        <glob pattern="KEYS"/>
+        <glob pattern="Makefile"/>
+        <glob pattern="README"/>
+        <glob pattern="abs-linkmap"/>
+        <glob pattern="abs-menulinks"/>
+        <glob pattern="*.aart"/>
+        <glob pattern="*.ac"/>
+        <glob pattern="*.am"/>
+        <glob pattern="*.classpath"/>
+        <glob pattern="*.cmd"/>
+        <glob pattern="*.config"/>
+        <glob pattern="*.cwiki"/>
+        <glob pattern="*.data"/>
+        <glob pattern="*.dcl"/>
+        <glob pattern="*.egrm"/>
+        <glob pattern="*.ent"/>
+        <glob pattern="*.ft"/>
+        <glob pattern="*.fn"/>
+        <glob pattern="*.fv"/>
+        <glob pattern="*.grm"/>
+        <glob pattern="*.g"/>
+        <glob pattern=".htaccess"/>
+        <glob pattern="*.ihtml"/>
+        <glob pattern="*.jmx"/>
+        <glob pattern="*.junit"/>
+        <glob pattern="*.jx"/>
+        <glob pattern="*.manifest"/>
+        <glob pattern="*.m4"/>
+        <glob pattern="*.mf"/>
+        <glob pattern="*.MF"/>
+        <glob pattern="*.meta"/>
+        <glob pattern="*.n3"/>
+        <glob pattern="*.pen"/>
+        <glob pattern="*.pod"/>
+        <glob pattern="*.pom"/>
+        <glob pattern="*.project"/>
+        <glob pattern="*.properties"/>
+        <glob pattern="*.rng"/>
+        <glob pattern="*.rnx"/>
+        <glob pattern="*.roles"/>
+        <glob pattern="*.tld"/>
+        <glob pattern="*.types"/>
+        <glob pattern="*.vm"/>
+        <glob pattern="*.vsl"/>
+        <glob pattern="*.wsdd"/>
+        <glob pattern="*.xargs"/>
+        <glob pattern="*.xcat"/>
+        <glob pattern="*.xconf"/>
+        <glob pattern="*.xegrm"/>
+        <glob pattern="*.xgrm"/>
+        <glob pattern="*.xlex"/>
+        <glob pattern="*.xlog"/>
+        <glob pattern="*.xmap"/>
+        <glob pattern="*.xroles"/>
+        <glob pattern="*.xsamples"/>
+        <glob pattern="*.xsp"/>
+        <glob pattern="*.xweb"/>
+        <glob pattern="*.xwelcome"/>
+    </mime-type>
+
+    <mime-type type="text/prs.fallenstein.rst"/>
+    <mime-type type="text/prs.lines.tag">
+        <glob pattern="*.dsc"/>
+    </mime-type>
+    <mime-type type="text/red"/>
+    <mime-type type="text/rfc822-headers"/>
+    <mime-type type="text/richtext">
+        <glob pattern="*.rtx"/>
+    </mime-type>
+
+    <mime-type type="text/rtp-enc-aescm128"/>
+    <mime-type type="text/rtx"/>
+    <mime-type type="text/sgml">
+        <glob pattern="*.sgml"/>
+        <glob pattern="*.sgm"/>
+    </mime-type>
+    <mime-type type="text/t140"/>
+    <mime-type type="text/tab-separated-values">
+        <glob pattern="*.tsv"/>
+    </mime-type>
+
+    <mime-type type="text/troff">
+        <_comment>Roff/nroff/troff/groff Unformatted Manual Page (UNIX)</_comment>
+        <alias type="application/x-troff"/>
+        <alias type="application/x-troff-man"/>
+        <alias type="application/x-troff-me"/>
+        <alias type="application/x-troff-ms"/>
+        <magic priority="50">
+            <match value=".\\&quot;" type="string" offset="0"/>
+            <match value="'\\&quot;" type="string" offset="0"/>
+            <match value="'.\\&quot;" type="string" offset="0"/>
+            <match value="\\&quot;" type="string" offset="0"/>
+            <match value="'''" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.t"/>
+        <glob pattern="*.tr"/>
+        <glob pattern="*.roff"/>
+        <glob pattern="*.man"/>
+        <glob pattern="*.me"/>
+        <glob pattern="*.ms"/>
+    </mime-type>
+
+    <mime-type type="text/ulpfec"/>
+    <mime-type type="text/uri-list">
+        <glob pattern="*.uri"/>
+        <glob pattern="*.uris"/>
+        <glob pattern="*.urls"/>
+    </mime-type>
+    <mime-type type="text/vnd.abc"/>
+    <mime-type type="text/vnd.curl">
+        <glob pattern="*.curl"/>
+    </mime-type>
+    <mime-type type="text/vnd.curl.dcurl">
+        <glob pattern="*.dcurl"/>
+    </mime-type>
+    <mime-type type="text/vnd.curl.scurl">
+        <glob pattern="*.scurl"/>
+    </mime-type>
+    <mime-type type="text/vnd.curl.mcurl">
+        <glob pattern="*.mcurl"/>
+    </mime-type>
+    <mime-type type="text/vnd.dmclientscript"/>
+    <mime-type type="text/vnd.esmertec.theme-descriptor"/>
+    <mime-type type="text/vnd.fly">
+        <glob pattern="*.fly"/>
+    </mime-type>
+    <mime-type type="text/vnd.fmi.flexstor">
+        <glob pattern="*.flx"/>
+    </mime-type>
+    <mime-type type="text/vnd.graphviz">
+        <glob pattern="*.gv"/>
+    </mime-type>
+    <mime-type type="text/vnd.in3d.3dml">
+        <glob pattern="*.3dml"/>
+    </mime-type>
+    <mime-type type="text/vnd.in3d.spot">
+        <glob pattern="*.spot"/>
+    </mime-type>
+    <mime-type type="text/vnd.iptc.anpa">
+        <acronym>ANPA</acronym>
+        <_comment>American Newspaper Publishers Association Wire Feeds</_comment>
+        <glob pattern="*.anpa"/>
+        <magic priority="50">
+            <match value="\x16\x16\x01" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+    <mime-type type="text/vnd.iptc.newsml"/>
+    <mime-type type="text/vnd.iptc.nitf"/>
+    <mime-type type="text/vnd.latex-z"/>
+    <mime-type type="text/vnd.motorola.reflex"/>
+    <mime-type type="text/vnd.ms-mediapackage"/>
+    <mime-type type="text/vnd.net2phone.commcenter.command"/>
+    <mime-type type="text/vnd.si.uricatalogue"/>
+    <mime-type type="text/vnd.sun.j2me.app-descriptor">
+        <glob pattern="*.jad"/>
+    </mime-type>
+    <mime-type type="text/vnd.trolltech.linguist"/>
+    <mime-type type="text/vnd.wap.si"/>
+    <mime-type type="text/vnd.wap.sl"/>
+    <mime-type type="text/vnd.wap.wml">
+        <glob pattern="*.wml"/>
+    </mime-type>
+
+    <mime-type type="text/vnd.wap.wmlscript">
+        <_comment>WML Script</_comment>
+        <glob pattern="*.wmls"/>
+    </mime-type>
+
+    <mime-type type="text/x-awk">
+        <_comment>AWK script</_comment>
+        <magic priority="50">
+            <match value="#!/bin/gawk" type="string" offset="0"/>
+            <match value="#! /bin/gawk" type="string" offset="0"/>
+            <match value="#!/usr/bin/gawk" type="string" offset="0"/>
+            <match value="#! /usr/bin/gawk" type="string" offset="0"/>
+            <match value="#!/usr/local/bin/gawk" type="string" offset="0"/>
+            <match value="#! /usr/local/bin/gawk" type="string" offset="0"/>
+            <match value="#!/bin/awk" type="string" offset="0"/>
+            <match value="#! /bin/awk" type="string" offset="0"/>
+            <match value="#!/usr/bin/awk" type="string" offset="0"/>
+            <match value="#! /usr/bin/awk" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.awk"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-basic">
+        <_comment>Basic source code</_comment>
+        <glob pattern="*.bas"/>
+        <glob pattern="*.Bas"/>
+        <glob pattern="*.BAS"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-c++hdr">
+        <_comment>C++ source code header</_comment>
+        <glob pattern="*.hpp"/>
+        <glob pattern="*.hxx"/>
+        <glob pattern="*.hh"/>
+        <glob pattern="*.H"/>
+        <glob pattern="*.h++"/>
+        <glob pattern="*.hp"/>
+        <glob pattern="*.HPP"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-c++src">
+        <_comment>C++ source code</_comment>
+        <glob pattern="*.cpp"/>
+        <glob pattern="*.cxx"/>
+        <glob pattern="*.cc"/>
+        <glob pattern="*.C"/>
+        <glob pattern="*.c++"/>
+        <glob pattern="*.CPP"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-cgi">
+        <_comment>CGI script</_comment>
+        <glob pattern="*.cgi"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-chdr">
+        <_comment>C source code header</_comment>
+        <glob pattern="*.h"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-clojure">
+        <_comment>Clojure source code</_comment>
+        <glob pattern="*.clj"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-coffeescript">
+        <_comment>CoffeeScript source code</_comment>
+        <glob pattern="*.coffee"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-csrc">
+        <alias type="text/x-c"/>
+        <_comment>C source code</_comment>
+        <glob pattern="*.c"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-csharp">
+        <_comment>C# source code</_comment>
+        <glob pattern="*.cs"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-cobol">
+        <_comment>COBOL source code</_comment>
+        <glob pattern="*.cbl"/>
+        <glob pattern="*.Cbl"/>
+        <glob pattern="*.CBL"/>
+        <glob pattern="*.cob"/>
+        <glob pattern="*.Cob"/>
+        <glob pattern="*.COB"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-coldfusion">
+        <_comment>ColdFusion source code</_comment>
+        <glob pattern="*.cfm"/>
+        <glob pattern="*.cfml"/>
+        <glob pattern="*.cfc"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-common-lisp">
+        <_comment>Common Lisp source code</_comment>
+        <glob pattern="*.cl"/>
+        <glob pattern="*.jl"/>
+        <glob pattern="*.lisp"/>
+        <glob pattern="*.lsp"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-diff">
+        <magic priority="50">
+            <match value="diff\ " type="string" offset="0"/>
+            <match value="***\ " type="string" offset="0"/>
+            <match value="Only\ in\ " type="string" offset="0"/>
+            <match value="Common\ subdirectories:\ " type="string" offset="0"/>
+            <match value="Index:" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.diff"/>
+        <glob pattern="*.patch"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-eiffel">
+        <_comment>Eiffel source code</_comment>
+        <glob pattern="*.e"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-emacs-lisp">
+        <_comment>Emacs Lisp source code</_comment>
+        <glob pattern="*.el"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-erlang">
+        <_comment>Erlang source code</_comment>
+        <glob pattern="*.erl"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-expect">
+        <_comment>Expect Script</_comment>
+        <glob pattern="*.exp"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-forth">
+        <_comment>Forth source code</_comment>
+        <glob pattern="*.4th"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-fortran">
+        <_comment>Fortran source code</_comment>
+        <glob pattern="*.f"/>
+        <glob pattern="*.F"/>
+        <glob pattern="*.for"/>
+        <glob pattern="*.f77"/>
+        <glob pattern="*.f90"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-go">
+        <_comment>Go source code</_comment>
+        <glob pattern="*.go"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-groovy">
+        <_comment>Groovy source code</_comment>
+        <glob pattern="*.groovy"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-haskell">
+        <_comment>Haskell source code</_comment>
+        <glob pattern="*.hs"/>
+        <glob pattern="*.lhs"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-idl">
+        <_comment>Inteface Definition Language</_comment>
+        <glob pattern="*.idl"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-ini">
+        <_comment>Configuration file</_comment>
+        <glob pattern="*.ini"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-java-source">
+        <_comment>Java source code</_comment>
+        <alias type="text/x-java" />
+        <glob pattern="*.java"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-jsp">
+        <_comment>Java Server Page</_comment>
+        <alias type="application/x-httpd-jsp"/>
+        <sub-class-of type="text/plain"/>
+        <magic priority="50">
+            <match value="&lt;%@" type="string" offset="0"/>
+            <match value="&lt;%--" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.jsp"/>
+    </mime-type>
+
+    <mime-type type="text/x-less">
+        <_comment>LESS source code</_comment>
+        <glob pattern="*.less"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-lex">
+        <_comment>Lex/Flex source code</_comment>
+        <glob pattern="*.l"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-log">
+        <_comment>application log</_comment>
+        <glob pattern="*.log"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-lua">
+        <_comment>Lua source code</_comment>
+        <glob pattern="*.lua"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-ml">
+        <_comment>ML source code</_comment>
+        <glob pattern="*.ml"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-matlab">
+        <_comment>Matlab source code</_comment>
+        <magic priority="50">
+            <match value="function [" type="string" offset="0"/>
+        </magic>
+        <!-- <glob pattern="*.m"/> - conflicts with text/x-objcsrc -->
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="application/x-matlab-data">
+        <comment>MATLAB data file</comment>
+        <alias type="application/matlab-mat"/>
+        <magic priority="50">
+            <match value="MATLAB" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.mat"/>
+    </mime-type>
+
+    <mime-type type="text/x-modula">
+        <_comment>Modula source code</_comment>
+        <glob pattern="*.m3"/>
+        <glob pattern="*.i3"/>
+        <glob pattern="*.mg"/>
+        <glob pattern="*.ig"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-objcsrc">
+        <_comment>Objective-C source code</_comment>
+        <glob pattern="*.m"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-ocaml">
+        <_comment>Ocaml source code</_comment>
+        <glob pattern="*.ocaml"/>
+        <glob pattern="*.mli"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-pascal">
+        <_comment>Pascal source code</_comment>
+        <glob pattern="*.p"/>
+        <glob pattern="*.pp"/>
+        <glob pattern="*.pas"/>
+        <glob pattern="*.PAS"/>
+        <glob pattern="*.dpr"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-perl">
+        <_comment>Perl script</_comment>
+        <magic priority="50">
+            <match value="eval \&quot;exec /usr/local/bin/perl" type="string" offset="0"/>
+            <match value="#!/bin/perl" type="string" offset="0"/>
+            <match value="#!/bin/env perl" type="string" offset="0"/>
+            <match value="#!/usr/bin/perl" type="string" offset="0"/>
+            <match value="#!/usr/local/bin/perl" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.pl"/>
+        <glob pattern="*.pm"/>
+        <glob pattern="*.al"/>
+        <glob pattern="*.perl"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-php">
+        <_comment>PHP script</_comment>
+        <magic priority="50">
+            <match value="&lt;?php" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.php"/>
+        <glob pattern="*.php3"/>
+        <glob pattern="*.php4"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-prolog">
+        <_comment>Prolog source code</_comment>
+        <glob pattern="*.pro"/>
+        <!-- <glob pattern="*.pl"/> - conflicts with text/x-perl -->
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-python">
+        <_comment>Python script</_comment>
+        <magic priority="50">
+            <match value="#!/bin/python" type="string" offset="0"/>
+            <match value="#! /bin/python" type="string" offset="0"/>
+            <match value="eval &quot;exec /bin/python" type="string" offset="0"/>
+            <match value="#!/usr/bin/python" type="string" offset="0"/>
+            <match value="#! /usr/bin/python" type="string" offset="0"/>
+            <match value="eval &quot;exec /usr/bin/python" type="string" offset="0"/>
+            <match value="#!/usr/local/bin/python" type="string" offset="0"/>
+            <match value="#! /usr/local/bin/python" type="string" offset="0"/>
+            <match value="eval &quot;exec /usr/local/bin/python" type="string" offset="0"/>
+            <match value="/bin/env python" type="string" offset="1"/>
+        </magic>
+        <glob pattern="*.py"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-rst">
+        <_comment>reStructuredText source code</_comment>
+        <glob pattern="*.rest"/>
+        <glob pattern="*.rst"/>
+        <glob pattern="*.restx"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-rexx">
+        <_comment>Rexx source code</_comment>
+        <glob pattern="*.rexx"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-ruby">
+        <_comment>Ruby source code</_comment>
+        <glob pattern="*.rb"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-scala">
+        <_comment>Scala source code</_comment>
+        <glob pattern="*.scala"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-scheme">
+        <_comment>Scheme source code</_comment>
+        <glob pattern="*.scm"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-sed">
+        <_comment>Sed code</_comment>
+        <glob pattern="*.sed"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-sql">
+        <_comment>SQL code</_comment>
+        <glob pattern="*.sql"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-setext">
+        <glob pattern="*.etx"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-stsrc">
+        <_comment>Smalltalk source code</_comment>
+        <glob pattern="*.st"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-tcl">
+        <alias type="application/x-tcl"/>
+        <_comment>Tcl script</_comment>
+        <glob pattern="*.itk"/>
+        <glob pattern="*.tcl"/>
+        <glob pattern="*.tk"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-uuencode">
+        <glob pattern="*.uu"/>
+    </mime-type>
+
+    <mime-type type="text/x-vbasic">
+        <_comment>Visual basic source code</_comment>
+        <glob pattern="*.cls"/>
+        <glob pattern="*.Cls"/>
+        <glob pattern="*.CLS"/>
+        <glob pattern="*.frm"/>
+        <glob pattern="*.Frm"/>
+        <glob pattern="*.FRM"/>
+        <sub-class-of type="text/x-basic"/>
+    </mime-type>
+
+    <mime-type type="text/x-vbdotnet">
+        <_comment>VB.NET source code</_comment>
+        <glob pattern="*.vb"/>
+        <sub-class-of type="text/x-vbasic"/>
+    </mime-type>
+
+    <mime-type type="text/x-vbscript">
+        <_comment>VBScript source code</_comment>
+        <glob pattern="*.vbs"/>
+        <sub-class-of type="text/x-vbasic"/>
+    </mime-type>
+
+    <mime-type type="text/x-vcalendar">
+        <glob pattern="*.vcs"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-vcard">
+        <glob pattern="*.vcf"/>
+        <sub-class-of type="text/plain"/>
+        <magic priority="50">
+            <match value="BEGIN:VCARD" type="string" offset="0"/>
+        </magic>
+    </mime-type>
+
+    <mime-type type="text/x-verilog">
+        <_comment>Verilog source code</_comment>
+        <glob pattern="*.v"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-vhdl">
+        <_comment>VHDL source code</_comment>
+        <glob pattern="*.vhd"/>
+        <glob pattern="*.vhdl"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-web-markdown">
+        <_comment>Markdown source code</_comment>
+        <glob pattern="*.md"/>
+        <glob pattern="*.mdtext"/>
+        <glob pattern="*.mkd"/>
+        <glob pattern="*.markdown"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-yacc">
+        <_comment>Yacc/Bison source code</_comment>
+        <glob pattern="*.y"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-yaml">
+        <_comment>YAML source code</_comment>
+        <glob pattern="*.yaml"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="video/3gpp">
+        <magic priority="60">
+            <match value="ftyp3ge6" type="string" offset="4"/>
+            <match value="ftyp3ge7" type="string" offset="4"/>
+            <match value="ftyp3gg6" type="string" offset="4"/>
+            <match value="ftyp3gp1" type="string" offset="4"/>
+            <match value="ftyp3gp2" type="string" offset="4"/>
+            <match value="ftyp3gp3" type="string" offset="4"/>
+            <match value="ftyp3gp4" type="string" offset="4"/>
+            <match value="ftyp3gp5" type="string" offset="4"/>
+            <match value="ftyp3gp6" type="string" offset="4"/>
+            <match value="ftyp3gs7" type="string" offset="4"/>
+        </magic>
+        <glob pattern="*.3gp"/>
+    </mime-type>
+    <mime-type type="video/3gpp-tt"/>
+    <mime-type type="video/3gpp2">
+        <magic priority="60">
+            <match value="ftyp3g2a" type="string" offset="4"/>
+            <match value="ftyp3g2b" type="string" offset="4"/>
+            <match value="ftyp3g2c" type="string" offset="4"/>
+        </magic>
+        <glob pattern="*.3g2"/>
+    </mime-type>
+    <mime-type type="video/bmpeg"/>
+    <mime-type type="video/bt656"/>
+    <mime-type type="video/celb"/>
+    <mime-type type="video/dv"/>
+    <mime-type type="video/example"/>
+    <mime-type type="video/h261">
+        <glob pattern="*.h261"/>
+    </mime-type>
+    <mime-type type="video/h263">
+        <glob pattern="*.h263"/>
+    </mime-type>
+    <mime-type type="video/h263-1998"/>
+    <mime-type type="video/h263-2000"/>
+    <mime-type type="video/h264">
+        <glob pattern="*.h264"/>
+    </mime-type>
+    <mime-type type="video/jpeg">
+        <glob pattern="*.jpgv"/>
+    </mime-type>
+    <mime-type type="video/jpeg2000"/>
+
+    <mime-type type="video/mj2">
+        <sub-class-of type="image/x-jp2-container" />
+        <acronym>MJ2</acronym>
+        <_comment>JPEG 2000 Part 3 (Motion JPEG, MJ2)</_comment>
+        <magic priority="50">
+            <match value="0x0000000C6A5020200D0A870A" type="string" offset="0">
+                <match value="0x6d6a7032" type="string" offset="20"/>
+            </match>
+        </magic>
+        <glob pattern="*.mj2"/>
+        <glob pattern="*.mjp2"/>
+    </mime-type>
+
+    <mime-type type="video/mp1s"/>
+    <mime-type type="video/mp2p"/>
+    <mime-type type="video/mp2t"/>
+
+    <mime-type type="video/mp4">
+        <magic priority="60">
+            <match value="ftypmp41" type="string" offset="4"/>
+            <match value="ftypmp42" type="string" offset="4"/>
+        </magic>
+        <glob pattern="*.mp4"/>
+        <glob pattern="*.mp4v"/>
+        <glob pattern="*.mpg4"/>
+        <sub-class-of type="video/quicktime" />
+    </mime-type>
+    <mime-type type="video/mp4v-es"/>
+
+    <mime-type type="video/mpeg">
+        <_comment>MPEG Movie Clip</_comment>
+        <magic priority="50">
+            <match value="\000\000\001\263" type="string" offset="0"/>
+            <match value="\000\000\001\272" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.mpeg"/>
+        <glob pattern="*.mpg"/>
+        <glob pattern="*.mpe"/>
+        <glob pattern="*.m1v"/>
+        <glob pattern="*.m2v"/>
+    </mime-type>
+
+    <mime-type type="video/mpeg4-generic"/>
+    <mime-type type="video/mpv"/>
+    <mime-type type="video/nv"/>
+
+    <mime-type type="video/ogg">
+        <_comment>Ogg Vorbis Video</_comment>
+        <glob pattern="*.ogv"/>
+        <sub-class-of type="application/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/daala">
+        <_comment>Ogg Daala Video</_comment>
+        <alias type="video/x-daala"/>
+        <magic priority="60">
+            <!-- Assumes Video stream comes before Audio, may not always -->
+            <match value="OggS\000.......................\x80daala" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/theora">
+        <_comment>Ogg Theora Video</_comment>
+        <alias type="video/x-theora"/>
+        <magic priority="60">
+            <!-- Assumes Video stream comes before Audio, may not always -->
+            <match value="OggS\000.......................\x80theora" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/x-dirac">
+        <_comment>Ogg Packaged Dirac Video</_comment>
+        <magic priority="60">
+            <match value="OggS\000.......................BBCD" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <glob pattern="*.drc"/>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/x-ogm">
+        <_comment>Ogg Packaged OGM Video</_comment>
+        <magic priority="60">
+            <!-- Assumes Video stream comes before Audio, may not always -->
+            <match value="OggS\000.......................video" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <glob pattern="*.ogm"/>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/x-ogguvs">
+        <_comment>Ogg Packaged Raw UVS Video</_comment>
+        <alias type="video/x-ogg-uvs"/>
+        <magic priority="60">
+            <match value="OggS\000.......................UVS " type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/x-oggyuv">
+        <_comment>Ogg Packaged Raw YUV Video</_comment>
+        <alias type="video/x-ogg-yuv"/>
+        <magic priority="60">
+            <match value="OggS\000.......................\001YUV" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/x-oggrgb">
+        <_comment>Ogg Packaged Raw RGB Video</_comment>
+        <alias type="video/x-ogg-rgb"/>
+        <magic priority="60">
+            <match value="OggS\000.......................\001RGB" type="string"
+                   mask="0xFFFFFFFF00000000000000000000000000000000000000000000000000FFFFFFFF"
+                   offset="0"/>
+        </magic>
+        <sub-class-of type="video/ogg"/>
+    </mime-type>
+
+    <mime-type type="video/parityfec"/>
+    <mime-type type="video/pointer"/>
+
+    <mime-type type="video/quicktime">
+        <magic priority="50">
+            <match value="moov" type="string" offset="4"/>
+            <match value="mdat" type="string" offset="4"/>
+            <!-- General match, specific ftypXXX ones present for subtypes -->
+            <match value="ftyp" type="string" offset="4"/>
+        </magic>
+        <glob pattern="*.qt"/>
+        <glob pattern="*.mov"/>
+    </mime-type>
+
+    <mime-type type="video/raw"/>
+    <mime-type type="video/rtp-enc-aescm128"/>
+    <mime-type type="video/rtx"/>
+    <mime-type type="video/smpte292m"/>
+    <mime-type type="video/ulpfec"/>
+    <mime-type type="video/vc1"/>
+    <mime-type type="video/vnd.cctv"/>
+    <mime-type type="video/vnd.dlna.mpeg-tts"/>
+    <mime-type type="video/vnd.fvt">
+        <glob pattern="*.fvt"/>
+    </mime-type>
+    <mime-type type="video/vnd.hns.video"/>
+    <mime-type type="video/vnd.iptvforum.1dparityfec-1010"/>
+    <mime-type type="video/vnd.iptvforum.1dparityfec-2005"/>
+    <mime-type type="video/vnd.iptvforum.2dparityfec-1010"/>
+    <mime-type type="video/vnd.iptvforum.2dparityfec-2005"/>
+    <mime-type type="video/vnd.iptvforum.ttsavc"/>
+    <mime-type type="video/vnd.iptvforum.ttsmpeg2"/>
+    <mime-type type="video/vnd.motorola.video"/>
+    <mime-type type="video/vnd.motorola.videop"/>
+    <mime-type type="video/vnd.mpegurl">
+        <glob pattern="*.mxu"/>
+        <glob pattern="*.m4u"/>
+    </mime-type>
+    <mime-type type="video/vnd.ms-playready.media.pyv">
+        <glob pattern="*.pyv"/>
+    </mime-type>
+    <mime-type type="video/vnd.nokia.interleaved-multimedia"/>
+    <mime-type type="video/vnd.nokia.videovoip"/>
+    <mime-type type="video/vnd.objectvideo"/>
+    <mime-type type="video/vnd.sealed.mpeg1"/>
+    <mime-type type="video/vnd.sealed.mpeg4"/>
+    <mime-type type="video/vnd.sealed.swf"/>
+    <mime-type type="video/vnd.sealedmedia.softseal.mov"/>
+    <mime-type type="video/vnd.vivo">
+        <glob pattern="*.viv"/>
+    </mime-type>
+    <mime-type type="video/x-f4v">
+        <glob pattern="*.f4v"/>
+    </mime-type>
+
+    <mime-type type="video/x-flc">
+        <glob pattern="*.flc"/>
+    </mime-type>
+
+    <mime-type type="video/x-fli">
+        <glob pattern="*.fli"/>
+    </mime-type>
+
+    <mime-type type="video/x-flv">
+        <magic priority="50">
+            <match value="FLV" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.flv"/>
+    </mime-type>
+
+    <mime-type type="video/x-jng">
+        <magic priority="50">
+            <match value="\x8bJNG" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.jng"/>
+    </mime-type>
+
+    <mime-type type="video/x-m4v">
+        <magic priority="60">
+            <match value="ftypM4V " type="string" offset="4"/>
+            <match value="ftypM4VH" type="string" offset="4"/>
+            <match value="ftypM4VP" type="string" offset="4"/>
+        </magic>
+        <glob pattern="*.m4v"/>
+        <sub-class-of type="video/mp4" />
+    </mime-type>
+
+    <mime-type type="video/x-mng">
+        <magic priority="50">
+            <match value="\x8aMNG" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.mng"/>
+    </mime-type>
+
+    <mime-type type="video/x-ms-asf">
+        <glob pattern="*.asf"/>
+        <glob pattern="*.asx"/>
+        <magic>
+            <match value="0x3026b275" type="big32" offset="0" />
+        </magic>
+    </mime-type>
+    <mime-type type="video/x-ms-wm">
+        <glob pattern="*.wm"/>
+    </mime-type>
+    <mime-type type="video/x-ms-wmv">
+        <sub-class-of type="video/x-ms-asf" />
+        <glob pattern="*.wmv"/>
+        <magic priority="60">
+            <match value="Windows Media Video" type="unicodeLE" offset="0:8192" />
+            <match value="VC-1 Advanced Profile" type="unicodeLE" offset="0:8192" />
+        </magic>
+    </mime-type>
+    <mime-type type="video/x-ms-wmx">
+        <glob pattern="*.wmx"/>
+    </mime-type>
+    <mime-type type="video/x-ms-wvx">
+        <glob pattern="*.wvx"/>
+    </mime-type>
+
+    <mime-type type="video/x-msvideo">
+        <_comment>Audio Video Interleave File</_comment>
+        <alias type="video/avi"/>
+        <alias type="video/msvideo"/>
+        <magic priority="50">
+            <match value="RIFF....AVI " type="string" offset="0"
+                   mask="0xFFFFFFFF00000000FFFFFFFF"/>
+            <match offset="8" type="string" value="\x41\x56\x49\x20"/>
+        </magic>
+        <glob pattern="*.avi"/>
+    </mime-type>
+
+    <mime-type type="video/x-sgi-movie">
+        <magic priority="50">
+            <match value="MOVI" type="string" offset="0"/>
+        </magic>
+        <glob pattern="*.movie"/>
+    </mime-type>
+
+    <mime-type type="application/x-matroska">
+        <_comment>Matroska Media Container</_comment>
+        <!-- Common magic across all Matroska varients -->
+        <!-- For full detection, we need a custom Detector, see TIKA-1180 -->
+        <magic priority="40">
+            <match value="0x1A45DFA3" type="string" offset="0" />
+        </magic>
+    </mime-type>
+
+    <mime-type type="video/x-matroska">
+        <sub-class-of type="application/x-matroska"/>
+        <glob pattern="*.mkv" />
+        <!-- Note: The magic value below isn't present in all MKV files -->
+        <magic priority="50">
+            <match value="0x1A45DFA3934282886D6174726F736B61" type="string" offset="0" />
+        </magic>
+    </mime-type>
+    <mime-type type="audio/x-matroska">
+        <sub-class-of type="application/x-matroska"/>
+        <glob pattern="*.mka" />
+    </mime-type>
+
+    <mime-type type="video/webm">
+        <sub-class-of type="application/x-matroska"/>
+        <glob pattern="*.webm" />
+    </mime-type>
+
+    <mime-type type="x-conference/x-cooltalk">
+        <_comment>Cooltalk Audio</_comment>
+        <glob pattern="*.ice"/>
+    </mime-type>
+
+    <mime-type type="application/x-fictionbook+xml">
+        <_comment>FictionBook document</_comment>
+        <sub-class-of type="application/xml"/>
+        <root-XML namespaceURI="http://www.gribuser.ru/xml/fictionbook/2.0" localName="FictionBook"/>
+        <glob pattern="*.fb2"/>
+    </mime-type>
+
+    <mime-type type="text/x-asciidoc">
+        <_comment>Asciidoc source code</_comment>
+        <glob pattern="*.asciidoc"/>
+        <glob pattern="*.adoc"/>
+        <glob pattern="*.ad"/>
+        <glob pattern="*.ad.txt"/>
+        <glob pattern="*.adoc.txt"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-d">
+        <_comment>D source code</_comment>
+        <glob pattern="*.d"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-haml">
+        <_comment>HAML source code</_comment>
+        <glob pattern="*.haml"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-haxe">
+        <_comment>Haxe source code</_comment>
+        <glob pattern="*.hx"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="text/x-rsrc">
+        <_comment>R source code</_comment>
+        <glob pattern="*.r"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+    <mime-type type="application/xquery">
+        <_comment>XQuery source code</_comment>
+        <glob pattern="*.xq"/>
+        <glob pattern="*.xquery"/>
+        <sub-class-of type="text/plain"/>
+    </mime-type>
+
+</mime-info>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/opsui/pom.xml b/0.8.1-rc1/mvn/archetypes/opsui/pom.xml
new file mode 100644
index 0000000..ec0fafe
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/opsui/pom.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../../../core</relativePath>
+  </parent>
+  <artifactId>opsui-archetype</artifactId>
+  <packaging>maven-archetype</packaging>
+
+  <name>OODT :: Archetypes :: OpsUI</name>
+
+  <build>
+    <extensions>
+      <extension>
+        <groupId>org.apache.maven.archetype</groupId>
+        <artifactId>archetype-packaging</artifactId>
+        <version>2.0-alpha-5</version>
+      </extension>
+    </extensions>
+
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <artifactId>maven-archetype-plugin</artifactId>
+          <version>2.0-alpha-5</version>
+          <extensions>true</extensions>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/opsui/src/main/resources/META-INF/maven/archetype-metadata.xml b/0.8.1-rc1/mvn/archetypes/opsui/src/main/resources/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..d6275a6
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/opsui/src/main/resources/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="opsui"
+    xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <fileSets>
+    <fileSet filtered="true" encoding="UTF-8">
+      <directory>src/main/webapp</directory>
+      <includes>
+        <include>**/*.xml</include>
+      </includes>
+    </fileSet>
+  </fileSets>
+</archetype-descriptor>
diff --git a/0.8.1-rc1/mvn/archetypes/opsui/src/main/resources/archetype-resources/pom.xml b/0.8.1-rc1/mvn/archetypes/opsui/src/main/resources/archetype-resources/pom.xml
new file mode 100644
index 0000000..e3cc3a6
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/opsui/src/main/resources/archetype-resources/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+--><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>${groupId}</groupId>

+  <artifactId>${artifactId}</artifactId>

+  <packaging>war</packaging>

+  <version>${version}</version>

+  <name>Ops UI</name>

+

+  <build>

+    <sourceDirectory>src/main/java</sourceDirectory>

+    <testSourceDirectory>src/test</testSourceDirectory>

+    <outputDirectory>target/classes</outputDirectory>

+

+    <resources>

+      <resource>

+        <directory>src/main/resources</directory>

+      </resource>

+      <resource>

+        <directory>src/main/java</directory>

+        <includes>

+          <include>**</include>

+        </includes>

+        <excludes>

+          <exclude>**/*.java</exclude>

+        </excludes>

+      </resource>

+    </resources>

+

+    <plugins>

+      <plugin>

+        <groupId>org.apache.maven.plugins</groupId>

+        <artifactId>maven-war-plugin</artifactId>

+        <version>2.1.1</version>

+        <configuration>

+          <overlays>

+            <overlay>

+              <groupId>org.apache.oodt</groupId>

+              <artifactId>pcs-opsui</artifactId>

+            </overlay>

+          </overlays>

+        </configuration>

+      </plugin>

+    </plugins>

+  </build>

+

+  <dependencies>

+    <dependency>

+      <groupId>org.apache.oodt</groupId>

+      <artifactId>pcs-opsui</artifactId>

+      <version>0.4-SNAPSHOT</version>

+      <type>war</type>

+    </dependency>

+  </dependencies>

+

+</project>

diff --git a/0.8.1-rc1/mvn/archetypes/opsui/src/main/resources/archetype-resources/src/main/webapp/META-INF/context.xml b/0.8.1-rc1/mvn/archetypes/opsui/src/main/resources/archetype-resources/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..36c8768
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/opsui/src/main/resources/archetype-resources/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,52 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<Context path="/opsui">
+		
+	<Parameter name="filemgr.url"
+	    value="[FILEMGR_URL]"/>		
+		
+	<Parameter name="workflow.url"
+	    value="[WORKFLOW_URL]"/>
+
+	<Parameter name="resmgr.url"
+	    value="[RESMGR_URL]"/>
+
+	<Parameter name="org.apache.oodt.pcs.opsui.workflow.lifecycleFilePath"
+	    value="[WORKFLOW_HOME]/policy/workflow-lifecycle.xml"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.opsui.winst.statuses"
+	    value="QUEUED, RSUBMIT, BUILDING CONFIG FILE, PGE EXEC, CRAWLING, STAGING INPUT, FINISHED, STARTED, PAUSED"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.opsui.winst.metFields.filePath"
+	    value="[WORKFLOW_HOME]/policy/workflow-instance-met.xml"/>   
+	    
+	<Parameter name="org.apache.oodt.pcs.health.crawler.conf.filePath"
+	    value="[PCS_HOME]/aux/pcs/pcs-crawlers.xml"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.health.workflow.statuses.filePath"
+	    value="[PCS_HOME]/aux/pcs/pcs-workflow-statuses.xml"/>	    
+	 
+	<Parameter name="ganglia.url" value="[GANGLIA_URL]"/>
+	<Parameter name="contact.email" value="user@oodt.apache.org"/>
+	
+	<Parameter name="opsui.skin" value=""/>
+	<Parameter name="opsui.homepage" value="org.apache.oodt.pcs.opsui.HomePage"/>   
+</Context>
diff --git a/0.8.1-rc1/mvn/archetypes/opsui/src/test/resources/projects/basic/archetype.properties b/0.8.1-rc1/mvn/archetypes/opsui/src/test/resources/projects/basic/archetype.properties
new file mode 100644
index 0000000..3d9406b
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/opsui/src/test/resources/projects/basic/archetype.properties
@@ -0,0 +1,19 @@
+#Tue Nov 08 21:23:35 PST 2011
+# 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.
+
+version=0.1-SNAPSHOT
+groupId=archetype.it
+artifactId=basic
diff --git a/0.8.1-rc1/mvn/archetypes/opsui/src/test/resources/projects/basic/goal.txt b/0.8.1-rc1/mvn/archetypes/opsui/src/test/resources/projects/basic/goal.txt
new file mode 100644
index 0000000..bd1c7e4
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/opsui/src/test/resources/projects/basic/goal.txt
@@ -0,0 +1,16 @@
+<!--
+ 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.
+-->
diff --git a/0.8.1-rc1/mvn/archetypes/pom.xml b/0.8.1-rc1/mvn/archetypes/pom.xml
new file mode 100644
index 0000000..788627a
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/pom.xml
@@ -0,0 +1,38 @@
+<?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.
+-->
+<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>
+
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../../core</relativePath>
+  </parent>
+
+  <artifactId>archetypes</artifactId>
+  <name>OODT :: Archetypes</name>
+  <description>Ways to quickly get started with some of OODT's components</description>
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>opsui</module>
+    <module>radix</module>
+  </modules>
+
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/pom.xml
new file mode 100644
index 0000000..719b429
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/pom.xml
@@ -0,0 +1,51 @@
+<?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.
+-->
+<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>
+  
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../../../core</relativePath>
+  </parent>
+  <artifactId>radix-archetype</artifactId>
+  <packaging>maven-archetype</packaging>
+
+  <name>OODT :: Archetypes :: RADiX</name>
+
+  <build>
+    <extensions>
+      <extension>
+        <groupId>org.apache.maven.archetype</groupId>
+        <artifactId>archetype-packaging</artifactId>
+        <version>2.0-alpha-5</version>
+      </extension>
+    </extensions>
+
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <artifactId>maven-archetype-plugin</artifactId>
+          <version>2.0-alpha-5</version>
+          <extensions>true</extensions>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/META-INF/maven/archetype-metadata.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..02bbba3
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,144 @@
+<?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.
+-->
+<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="radix-dms"
+    xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <requiredProperties>
+    <requiredProperty key="oodt">
+      <defaultValue>0.7-SNAPSHOT</defaultValue>
+    </requiredProperty>
+  </requiredProperties>
+  <fileSets>
+    <fileSet filtered="true" packaged="false">
+      <directory></directory>
+      <includes>
+        <include>README.txt</include>
+      </includes>
+    </fileSet>
+  </fileSets>
+  <modules>
+    <module id="extensions" dir="extensions" name="extensions">
+      <fileSets>
+        <fileSet>
+          <directory></directory>
+          <includes/>
+        </fileSet>
+      </fileSets>
+    </module>
+    <module id="resmgr" dir="resmgr" name="resmgr">
+      <fileSets>
+        <fileSet>
+          <directory></directory>
+          <includes/>
+        </fileSet>
+      </fileSets>
+    </module>
+    <module id="pcs" dir="pcs" name="pcs">
+      <fileSets>
+        <fileSet>
+          <directory></directory>
+          <includes/>
+        </fileSet>
+      </fileSets>
+    </module>
+    <module id="filemgr" dir="filemgr" name="filemgr">
+      <fileSets>
+        <fileSet>
+          <directory></directory>
+          <includes/>
+        </fileSet>
+      </fileSets>
+    </module>
+    <module id="workflow" dir="workflow" name="workflow">
+      <fileSets>
+        <fileSet>
+          <directory></directory>
+          <includes/>
+        </fileSet>
+      </fileSets>
+    </module>
+    <module id="pge" dir="pge" name="pge">
+      <fileSets>
+        <fileSet>
+          <directory></directory>
+          <includes/>
+        </fileSet>
+      </fileSets>
+    </module>
+    <module id="crawler" dir="crawler" name="crawler">
+      <fileSets>
+        <fileSet>
+          <directory></directory>
+          <includes/>
+        </fileSet>
+      </fileSets>
+    </module>
+    <module id="solr" dir="solr" name="solr">
+      <fileSets>
+        <fileSet>
+          <directory></directory>
+          <includes/>
+        </fileSet>
+      </fileSets>
+    </module>    
+    <module id="distribution" dir="distribution" name="distribution">
+      <fileSets>
+        <fileSet>
+          <directory></directory>
+          <includes/>
+        </fileSet>
+      </fileSets>
+    </module>
+    <module id="webapps" dir="webapps" name="webapps">
+      <modules>
+        <module id="opsui" dir="opsui" name="opsui">
+          <fileSets>
+            <fileSet>
+              <directory></directory>
+              <includes/>
+            </fileSet>
+          </fileSets>
+        </module>
+        <module id="pcs-services" dir="pcs-services" name="pcs-services">
+          <fileSets>
+            <fileSet>
+              <directory></directory>
+              <includes/>
+            </fileSet>
+          </fileSets>
+        </module>
+        <module id="fmprod" dir="fmprod" name="fmprod">
+          <fileSets>
+            <fileSet>
+              <directory></directory>
+              <includes/>
+            </fileSet>
+          </fileSets>
+        </module>
+        <module id="solr-webapp" dir="solr-webapp" name="solr-webapp">
+          <fileSets>
+            <fileSet>
+              <directory></directory>
+              <includes/>
+            </fileSet>
+          </fileSets>
+        </module>        
+      </modules>
+    </module>
+  </modules>
+</archetype-descriptor>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/README.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/README.txt
new file mode 100644
index 0000000..64ca256
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/README.txt
@@ -0,0 +1,53 @@
+# 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.
+
+######################################################################################
+#     OODT RADiX README
+#
+#     Description:
+#       	This project is meant as template to support faster
+#       data system deployment. Configurable OODT deployments
+#       are possible using Maven profiles (see below).
+#       
+#       OODT version 0.7-SNAPSHOT 
+######################################################################################
+
+REQUIREMENTS:
+* Java Development Kit (JDK) 1.6+
+* JAVA_HOME set 
+  see: http://docs.oracle.com/cd/E19182-01/820-7851/inst_cli_jdk_javahome_t/index.html
+* (Snapshot releases only) OODT source tree installed. 
+  see: http://oodt.apache.org/components/maven/filemgr/user/basic.html
+
+INSTALLATION:
+  # build oodt
+  $ mvn clean package <OPTIONAL PROFILES> # see optional build profiles below
+
+  # deploy oodt
+  $ tar zxf distribution/target/${PROJECT_ARTIFACT_ID}-distribution-*-bin.tar.gz -C /my/deployment/directory/oodt
+  
+  ---
+  NOTE: For other build configurations, add the following arguments:
+  (default)           : bin, crawler, data, extensions,
+                        filemgr (Lucene), logs, pcs, resmgr,
+                        tomcat, workflow, pge
+
+  -Pfm-solr-catalog   : default components, filemgr (Solr),
+                        solr, tomcat/webapps/solr
+
+RUN:
+  $ cd /my/deployment/directory/oodt
+  $ cd bin
+  $ ./oodt start
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/pom.xml
new file mode 100644
index 0000000..8a033d6
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/pom.xml
@@ -0,0 +1,83 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>${groupId}</groupId>
+    <artifactId>${rootArtifactId}</artifactId>
+    <version>${version}</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+  <name>Crawler (Apache OODT)</name>
+  <artifactId>${rootArtifactId}-${artifactId}</artifactId>
+  <packaging>jar</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-2</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/assembly/assembly.xml</descriptor>
+          </descriptors>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>${groupId}</groupId>
+      <artifactId>${rootArtifactId}-extensions</artifactId>
+      <version>${project.parent.version}</version>
+      <type>jar</type>
+      <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.oodt</groupId>
+          <artifactId>cas-filemgr</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-crawler</artifactId>
+      <version>${oodt.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/assembly/assembly.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..996112f
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/assembly/assembly.xml
@@ -0,0 +1,75 @@
+<!--
+ 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.
+-->
+<assembly>
+  <id>bin</id>
+  <formats>
+    <format>tar.gz</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <baseDirectory>crawler</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/bin</directory>
+      <outputDirectory>crawler/bin</outputDirectory>
+      <includes/>
+      <fileMode>755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/logs</directory>
+      <outputDirectory>crawler/logs</outputDirectory>
+      <includes>
+        <include>REMOVE.log</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/etc</directory>
+      <outputDirectory>crawler/etc</outputDirectory>
+      <includes>
+        <include>**.properties</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/policy</directory>
+      <outputDirectory>crawler/policy</outputDirectory>
+      <includes/>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>crawler/lib</outputDirectory>
+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>
+      <unpackOptions/>
+    </dependencySet>
+  </dependencySets>
+</assembly>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/bin/crawlctl b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/bin/crawlctl
new file mode 100755
index 0000000..ac99407
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/bin/crawlctl
@@ -0,0 +1,18 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+##########################################################################
+
+java -Djava.util.logging.config.file=../etc/logging.properties -Djava.ext.dirs=../lib org.apache.oodt.cas.crawl.daemon.CrawlDaemonController $@
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/bin/crawler_launcher b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/bin/crawler_launcher
new file mode 100755
index 0000000..4198615
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/bin/crawler_launcher
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+# 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.
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false
+os400=false
+darwin=false
+case "`uname`" in
+CYGWIN*) cygwin=true;;
+OS400*) os400=true;;
+Darwin*) darwin=true;;
+esac
+
+# resolve links - $0 may be a softlink
+PRG="$0"
+
+while [ -h "$PRG" ]; do
+  ls=`ls -ld "$PRG"`
+  link=`expr "$ls" : '.*-> \(.*\)$'`
+  if expr "$link" : '/.*' > /dev/null; then
+    PRG="$link"
+  else
+    PRG=`dirname "$PRG"`/"$link"
+  fi
+done
+
+# Get standard environment variables
+PRGDIR=`dirname "$PRG"`
+
+# Only set OODT_HOME if not already set
+[ -z "$OODT_HOME" ] && OODT_HOME=`cd "$PRGDIR/../.." ; pwd`
+
+# Get OODT environment set up
+if [ -r "$OODT_HOME"/bin/env.sh ]; then
+  . "$OODT_HOME"/bin/env.sh
+fi
+
+# Only set CRAWLER_HOME if not already set
+if [ -z "$CRAWLER_HOME" ]; then
+  CRAWLER_HOME="$OODT_HOME"/crawler
+  export CRAWLER_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$JRE_HOME" ] && JRE_HOME=`cygpath --unix "$JRE_HOME"`
+  [ -n "$OODT_HOME" ] && OODT_HOME=`cygpath --unix "$OODT_HOME"`
+  [ -n "$CRAWLER_HOME" ] && CRAWLER_HOME=`cygpath --unix "$CRAWLER_HOME"`
+  [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# In case this script was run from somewhere else cd to this directory
+cd "$CRAWLER_HOME"/bin
+
+"$_RUNJAVA" $JAVA_OPTS $OODT_OPTS \
+   -Djava.ext.dirs="$CRAWLER_HOME"/lib \
+   -Djava.util.logging.config.file="$CRAWLER_HOME"/etc/logging.properties \
+   -Dorg.apache.oodt.cas.crawl.bean.repo=file:"$CRAWLER_HOME"/policy/crawler-config.xml \
+   -Dorg.apache.oodt.cas.cli.action.spring.config=file:"$CRAWLER_HOME"/policy/cmd-line-actions.xml \
+   -Dorg.apache.oodt.cas.cli.option.spring.config=file:"$CRAWLER_HOME"/policy/cmd-line-options.xml \
+    org.apache.oodt.cas.crawl.CrawlerLauncher "$@"
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/etc/logging.properties b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/etc/logging.properties
new file mode 100644
index 0000000..c77a851
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/etc/logging.properties
@@ -0,0 +1,63 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.FileHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = ../logs/cas_crawler%g.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 5
+java.util.logging.FileHandler.append = true
+java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging level for the subsystems
+
+org.apache.oodt.cas.crawl.level = ALL
+
+org.apache.oodt.cas.crawl.action.level = ALL
+
+org.apache.oodt.cas.crawl.typedetection.level = ALL
+
+org.apache.oodt.cas.crawl.util.level = ALL
+
+org.apache.oodt.cas.crawl.config.level = ALL
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = INFO
+httpclient.wire.header.level = INFO
+httpclient.wire.level = INFO
+
+org.springframework.beans.level = SEVERE
+org.springframework.core.level = SEVERE
+org.springframework.level = SEVERE
+org.springframework.beans.factory.level = SEVERE
+org.springframework.beans.factory.config.level = SEVERE
+org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.level = SEVERE
+org.apache.oodt.cas.crawl.util.CasPropertyPlaceholderConfigurer.level = SEVERE
+sun.net.level = SEVERE
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/logs/REMOVE.log b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/logs/REMOVE.log
new file mode 100644
index 0000000..9215491
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/logs/REMOVE.log
@@ -0,0 +1,18 @@
+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.
+
+
+You can remove this file. It was only included to ensure that the log directory for this
+distribution was created on assembly.
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/action-beans.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/action-beans.xml
new file mode 100644
index 0000000..78d2c2d
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/action-beans.xml
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+    <bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor" />
+    <bean class="org.apache.oodt.cas.crawl.util.CasPropertyPlaceholderConfigurer">
+
+        <!-- Allow for system-level properties to override all properties below -->
+        <property name="systemPropertiesMode" value="2" />
+
+        <!-- Default Properties -->
+        <property name="properties">
+            <props>
+                <prop key="crawler.failure.dir">[FAILURE_DIR]</prop>
+                <prop key="crawler.backup.dir">[BACKUP_DIR]</prop>
+                <prop key="crawler.workflowmgr.url">[WORKFLOW_URL]</prop>
+                <prop key="crawler.filemgr.url">[FILEMGR_URL]</prop>
+                <prop key="crawler.client.transferer">org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory</prop>
+                <prop key="crawler.met.file.ext">met</prop>
+                <prop key="crawler.pushpull.met.file.ext">[PUSHPULL_MET_FILE_EXT]</prop>
+                <prop key="crawler.anc.file.ext">anc</prop>
+                <prop key="crawler.anc.file.suffix"></prop>
+                <prop key="notification.mail.host"></prop>
+                <prop key="notification.sender"></prop>
+                <prop key="notification.success.subject"></prop>
+                <prop key="notification.success.message"></prop>
+                <prop key="notification.success.recipients"></prop>
+            </props>
+        </property>
+
+        <!-- File Properties - overrides default properties -->
+        <!-- property name="location" value="/org/apache/oodt/cas/crawl/crawler.properties" 
+            / -->
+    </bean>
+
+    <!-- DELETE Actions -->
+    <bean id="DeleteDataFile" lazy-init="true" class="org.apache.oodt.cas.crawl.action.DeleteFile">
+        <property name="description" value="Deletes the current data file" />
+        <property name="phases">
+            <list>
+                <value type="java.lang.String">postIngestSuccess</value>
+            </list>
+        </property>
+    </bean>
+
+    <bean id="DeleteMetadataFile" lazy-init="true" class="org.apache.oodt.cas.crawl.action.DeleteFile">
+        <property name="description" value="Deletes the metadata file for the current data file" />
+        <property name="fileExtension" value="${crawler.met.file.ext}" />
+        <property name="phases">
+            <list>
+                <value type="java.lang.String">postIngestSuccess</value>
+            </list>
+        </property>
+    </bean>
+
+    <bean id="DeletePushpullMetFile" lazy-init="true" class="org.apache.oodt.cas.crawl.action.DeleteFile">
+        <property name="description" value="Deletes the push-pull metadata file for the current data file" />
+        <property name="fileExtension" value="${crawler.pushpull.met.file.ext}" />
+        <property name="phases">
+            <list>
+                <value type="java.lang.String">postIngestSuccess</value>
+            </list>
+        </property>
+    </bean>
+
+    <!-- MOVE to FAILURE_DIR Actions -->
+    <bean id="MoveDataFileToFailureDir" lazy-init="true" class="org.apache.oodt.cas.crawl.action.MoveFile">
+        <property name="description" value="Moves the current data file to failure directory" />
+        <property name="toDir" value="${crawler.failure.dir}" />
+        <property name="createToDir" value="true" />
+        <property name="phases">
+            <list>
+                <value type="java.lang.String">postIngestFailure</value>
+            </list>
+        </property>
+    </bean>
+
+    <bean id="MoveMetadataFileToFailureDir" lazy-init="true" class="org.apache.oodt.cas.crawl.action.MoveFile">
+        <property name="description" value="Moves the metadata file for the current data file to failure directory" />
+        <property name="fileExtension" value="${crawler.met.file.ext}" />
+        <property name="toDir" value="${crawler.failure.dir}" />
+        <property name="createToDir" value="true" />
+        <property name="phases">
+            <list>
+                <value type="java.lang.String">postIngestFailure</value>
+            </list>
+        </property>
+    </bean>
+
+    <bean id="MovePushpullMetFileToFailureDir" lazy-init="true" class="org.apache.oodt.cas.crawl.action.MoveFile">
+        <property name="description" value="Moves the push-pull metadata file for the current data file to failure directory" />
+        <property name="createToDir" value="true" />
+        <property name="fileExtension" value="${crawler.pushpull.met.file.ext}" />
+        <property name="toDir" value="${crawler.failure.dir}" />
+        <property name="phases">
+            <list>
+                <value type="java.lang.String">postIngestFailure</value>
+            </list>
+        </property>
+    </bean>
+
+    <!-- MOVE to BACKUP_DIR Actions -->
+    <bean id="MovePushpullMetFileToBackupDir" lazy-init="true" class="org.apache.oodt.cas.crawl.action.MoveFile">
+        <property name="description" value="Moves the push-pull metadata file for the current data file to success directory" />
+        <property name="fileExtension" value="${crawler.pushpull.met.file.ext}" />
+        <property name="toDir" value="${crawler.backup.dir}" />
+        <property name="createToDir" value="true" />
+        <property name="phases">
+            <list>
+                <value type="java.lang.String">postIngestSuccess</value>
+            </list>
+        </property>
+    </bean>
+
+    <bean id="MoveMetadataFileToBackupDir" lazy-init="true" class="org.apache.oodt.cas.crawl.action.MoveFile">
+        <property name="description" value="Moves the metadata file for the current data file to success directory" />
+        <property name="fileExtension" value="${crawler.met.file.ext}" />
+        <property name="toDir" value="${crawler.backup.dir}" />
+        <property name="createToDir" value="true" />
+        <property name="phases">
+            <list>
+                <value type="java.lang.String">postIngestSuccess</value>
+            </list>
+        </property>
+    </bean>
+
+    <!-- Workflow Manager Actions -->
+    <bean id="TriggerPostIngestWorkflow" lazy-init="true" class="org.apache.oodt.cas.crawl.action.WorkflowMgrStatusUpdate">
+        <property name="description" value="Triggers workflow event with the name [ProductType]Ingest" />
+        <property name="ingestSuffix" value="Ingest" />
+        <property name="workflowMgrUrl" value="${crawler.workflowmgr.url}" />
+        <property name="phases">
+            <list>
+                <value type="java.lang.String">postIngestSuccess</value>
+            </list>
+        </property>
+    </bean>
+
+    <!-- File Manager Actions -->
+    <bean id="Unique" lazy-init="true" class="org.apache.oodt.cas.crawl.action.FilemgrUniquenessChecker">
+        <property name="description" value="Checks the filemgr against the PRODUCT_NAME for the current data file to make sure it has not yet been ingested" />
+        <property name="filemgrUrl" value="${crawler.filemgr.url}" />
+        <property name="phases">
+            <list>
+                <value type="java.lang.String">preIngest</value>
+            </list>
+        </property>
+    </bean>
+
+    <bean id="IngestAncillaryFile" lazy-init="true" class="org.apache.oodt.cas.crawl.action.IngestAncillary">
+        <property name="description" value="This will ingest an associated file along with the current file being ingested by the crawler." />
+        <property name="fileManagerUrl" value="${crawler.filemgr.url}" />
+        <property name="fileExtension" value="${crawler.anc.file.ext}" />
+        <property name="fileSuffix" value="${crawler.anc.file.suffix}" />
+        <property name="keepExistingExtension">
+            <value type="java.lang.Boolean">false</value>
+        </property>
+        <property name="dataTransferService" value="${crawler.client.transferer}" />
+        <property name="relatedKey" value="CAS.ProductId" />
+        <property name="copyKeys">
+            <list>
+                <value type="java.lang.String">MetKey1</value>
+            </list>
+        </property>
+        <property name="productType" value="GenericFile" />
+        <property name="failMissingFile">
+            <value type="java.lang.Boolean">true</value>
+        </property>
+        <property name="phases">
+            <list>
+                <value type="java.lang.String">preIngest</value>
+            </list>
+        </property>
+    </bean>
+
+    <!-- Existence Check Actions -->
+    <bean id="CheckMetFileExists" lazy-init="true" class="org.apache.oodt.cas.crawl.action.ExternAction">
+        <property name="description" value="Checks if metadata file was created -- make sure check-exists.sh is on your PATH" />
+        <property name="executeCommand" value="./check-exists.sh [Filename].met" />
+        <property name="phases">
+            <list>
+                <value type="java.lang.String">preIngest</value>
+            </list>
+        </property>
+    </bean>
+
+    <!-- Email Actions -->
+    <bean id="SendNotification" lazy-init="true" class="org.apache.oodt.cas.crawl.action.EmailNotification">
+        <property name="description" value="This will send an email that indicates the submission to the catalog was successful." />
+        <property name="mailHost" value="${notification.mail.host}" />
+        <property name="sender" value="${notification.sender}" />
+        <property name="subject" value="${notification.success.subject}" />
+        <property name="message" value="${notification.success.message}" />
+        <property name="recipients" value="${notification.success.recipients}" />
+        <property name="ignoreInvalidAddresses">
+            <value type="java.lang.Boolean">true</value>
+        </property>
+        <property name="phases">
+            <list>
+                <value type="java.lang.String">postIngestSuccess</value>
+            </list>
+        </property>
+    </bean>
+</beans>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/cmd-line-actions.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/cmd-line-actions.xml
new file mode 100644
index 0000000..e3bd9e6
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/cmd-line-actions.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean id="launchStdCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.cli.action.CrawlerLauncherCliAction">
+    <property name="description" value="Triggers StdProductCrawler" />
+    <property name="crawlerId" value="StdProductCrawler" />
+  </bean>
+
+  <bean id="launchMetCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.cli.action.CrawlerLauncherCliAction">
+    <property name="description" value="Triggers MetExtractorProductCrawler" />
+    <property name="crawlerId" value="MetExtractorProductCrawler" />
+  </bean>
+
+  <bean id="launchAutoCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.cli.action.CrawlerLauncherCliAction">
+    <property name="description" value="Triggers AutoDetectProductCrawler" />
+    <property name="crawlerId" value="AutoDetectProductCrawler" />
+  </bean>
+</beans>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/cmd-line-options.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/cmd-line-options.xml
new file mode 100644
index 0000000..e6b6811
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/cmd-line-options.xml
@@ -0,0 +1,913 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean id="operation" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="op" />
+    <property name="longOption" value="operation" />
+    <property name="description" value="Declare that you wish to present an operation" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="true" />
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="launchStdCrawler" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="launchMetCrawler" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="launchAutoCrawler" p:required="false" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- launchStdCrawler Options -->
+  <bean id="launchStdCrawler" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="stdPC" />
+    <property name="longOption" value="launchStdCrawler" />
+    <property name="description" value="Triggers StdProductCrawler" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>launchStdCrawler</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchStdCrawler" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- launchMetCrawler Options -->
+  <bean id="launchMetCrawler" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="metPC" />
+    <property name="longOption" value="launchMetCrawler" />
+    <property name="description" value="Triggers MetExtractorProductCrawler" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>launchMetCrawler</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchMetCrawler" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- launchAutoCrawler Options -->
+  <bean id="launchAutoCrawler" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="autoPC" />
+    <property name="longOption" value="launchAutoCrawler" />
+    <property name="description" value="Triggers AutoDetectProductCrawler" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>launchAutoCrawler</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchAutoCrawler" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+    <bean id="printSupportedCrawlerActions" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="psca" />
+        <property name="longOption" value="printSupportedCrawlerActions" />
+        <property name="description" value="Prints a list and description of all supported CrawlerActions" />
+        <property name="hasArgs" value="false" />
+        <property name="required" value="false" />
+        <property name="performAndQuit" value="true" />
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerActionInfoHandler">
+                <property name="applicationContext">
+                    <bean class="org.springframework.context.support.FileSystemXmlApplicationContext">
+                        <constructor-arg value="../policy/action-beans.xml" />
+                    </bean>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+    <bean id="printSupportedPreconditions" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="psp" />
+        <property name="longOption" value="printSupportedPreconditions" />
+        <property name="description" value="Prints a list and description of all supported Preconditions" />
+        <property name="hasArgs" value="false" />
+        <property name="required" value="false" />
+        <property name="performAndQuit" value="true" />
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.PreconditionInfoHandler">
+                <property name="applicationContext">
+                    <bean class="org.springframework.context.support.FileSystemXmlApplicationContext">
+                        <constructor-arg value="../policy/precondition-beans.xml" />
+                    </bean>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+    <bean id="filemgrUrl" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="fm" />
+        <property name="longOption" value="filemgrUrl" />
+        <property name="description" value="File Manager URL" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="url" />
+        <property name="required" value="true" />
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>StdProductCrawler.filemgrUrl</value>
+                        <value>MetExtractorProductCrawler.filemgrUrl</value>
+                        <value>AutoDetectProductCrawler.filemgrUrl</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+        <property name="validators">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+                    <property name="allowedArgs">
+                        <list>
+                            <value>http://.*:\d*</value>
+                        </list>
+                    </property>
+                </bean>
+            </list>
+        </property>
+    </bean>
+
+    <bean id="failureDir" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="fd" />
+        <property name="longOption" value="failureDir" />
+        <property name="description" value="Directory where files will be moved on failure" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="directory" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+      </list>
+    </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>MoveMetadataFileToFailureDir.toDir</value>
+                        <value>MovePushpullMetFileToFailureDir.toDir</value>
+                        <value>MoveDataFileToFailureDir.toDir</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+        <property name="validators">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+            </list>
+        </property>
+    </bean>
+
+    <bean id="successDir" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="sd" />
+        <property name="longOption" value="successDir" />
+        <property name="description" value="Directory where files will be moved on success" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="directory" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>MovePushpullMetFileToBackupDir.toDir</value>
+                        <value>MoveMetadataFileToBackupDir.toDir</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+        <property name="validators">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+            </list>
+        </property>
+    </bean>
+
+    <bean id="workflowMgrUrl" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="wm" />
+        <property name="longOption" value="workflowMgrUrl" />
+        <property name="description" value="Workflow Manager URL" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="url" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>UpdateWorkflowStatusToIngest.workflowMgrUrl</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+        <property name="validators">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+                    <property name="allowedArgs">
+                        <list>
+                            <value>http://.*:\d*</value>
+                        </list>
+                    </property>
+                </bean>
+            </list>
+        </property>
+    </bean>
+
+    <bean id="clientTransferer" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="ct" />
+        <property name="longOption" value="clientTransferer" />
+        <property name="description" value="File Manager data transferer factory class" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="class" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>StdProductCrawler.clientTransferer</value>
+                        <value>MetExtractorProductCrawler.clientTransferer</value>
+                        <value>AutoDetectProductCrawler.clientTransferer</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+        <property name="validators">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.validator.ClassExistsCmdLineOptionValidator" />
+            </list>
+        </property>
+    </bean>
+
+    <bean id="requiredMetadata" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="rqm" />
+        <property name="longOption" value="requiredMetadata" />
+        <property name="type" value="java.util.List" />
+        <property name="description" value="Metadata required for ingest to take place" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="metadata_elements" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>StdProductCrawler.requiredMetadata</value>
+                        <value>MetExtractorProductCrawler.requiredMetadata</value>
+                        <value>AutoDetectProductCrawler.requiredMetadata</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+    <bean id="actionIds" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="ais" />
+        <property name="longOption" value="actionIds" />
+        <property name="type" value="java.util.List" />
+        <property name="description" value="CrawlerActions that should be performed" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="CrawlerAction ids" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>StdProductCrawler.actionIds</value>
+                        <value>MetExtractorProductCrawler.actionIds</value>
+                        <value>AutoDetectProductCrawler.actionIds</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+    <bean id="preCondIds" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="pids" />
+        <property name="longOption" value="preCondIds" />
+        <property name="type" value="java.util.List" />
+        <property name="description" value="PreConditionComparator ids that must pass before any metadata extraction will run" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="PreConditionComparator ids" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>MetExtractorProductCrawler.preCondIds</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+  <bean id="namingConventionId" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="ncid" />
+    <property name="longOption" value="namingConventionId" />
+    <property name="description" value="ID of the NamingConvention to use to rename products before ingest" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="NamingConvention ID" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>MetExtractorProductCrawler.namingConventionId</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+    <bean id="noRecur" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="nr" />
+        <property name="longOption" value="noRecur" />
+        <property name="description" value="Turns off recursive crawling - will only process files in productPath directory" />
+        <property name="type" value="boolean" />
+        <property name="hasArgs" value="false" />
+                <property name="staticArgs">
+            <list>
+                <value>true</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>StdProductCrawler.noRecur</value>
+                        <value>MetExtractorProductCrawler.noRecur</value>
+                        <value>AutoDetectProductCrawler.noRecur</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+    <bean id="crawlForDirs" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="cfd" />
+        <property name="longOption" value="crawlForDirs" />
+        <property name="description" value="Will crawl for directories instead of files" />
+        <property name="type" value="boolean" />
+        <property name="hasArgs" value="false" />
+                <property name="staticArgs">
+            <list>
+                <value>true</value>
+            </list>
+        </property>
+        <property name="required" value="false" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>StdProductCrawler.crawlForDirs</value>
+                        <value>MetExtractorProductCrawler.crawlForDirs</value>
+                        <value>AutoDetectProductCrawler.crawlForDirs</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+    <bean id="skipIngest" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="si" />
+        <property name="longOption" value="skipIngest" />
+        <property name="description" value="Will skip ingest to file manager and any post ingest actions" />
+        <property name="type" value="boolean" />
+        <property name="hasArgs" value="false" />
+                <property name="staticArgs">
+            <list>
+                <value>true</value>
+            </list>
+        </property>
+        <property name="required" value="false" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>StdProductCrawler.skipIngest</value>
+                        <value>MetExtractorProductCrawler.skipIngest</value>
+                        <value>AutoDetectProductCrawler.skipIngest</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+    <bean id="daemonPort" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="dp" />
+        <property name="longOption" value="daemonPort" />
+        <property name="type" value="int" />
+        <property name="description" value="Cause crawler to become a daemon with a XML-RPC webserver started on the given port number" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="portNum" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>StdProductCrawler.daemonPort</value>
+                        <value>MetExtractorProductCrawler.daemonPort</value>
+                        <value>AutoDetectProductCrawler.daemonPort</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+        <property name="validators">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+                    <property name="allowedArgs">
+                        <list>
+                            <value>\d*</value>
+                        </list>
+                    </property>
+                </bean>
+            </list>
+        </property>
+    </bean>
+
+    <bean id="daemonWait" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="dw" />
+        <property name="longOption" value="daemonWait" />
+        <property name="type" value="int" />
+        <property name="description" value="Cause crawler to become a daemon and sleep for given number of seconds between crawls" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="seconds" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>StdProductCrawler.daemonWait</value>
+                        <value>MetExtractorProductCrawler.daemonWait</value>
+                        <value>AutoDetectProductCrawler.daemonWait</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+        <property name="validators">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.validator.ArgRegExpCmdLineOptionValidator">
+                    <property name="allowedArgs">
+                        <list>
+                            <value>\d*</value>
+                        </list>
+                    </property>
+                </bean>
+            </list>
+        </property>
+    </bean>
+
+    <bean id="productPath" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="pp" />
+        <property name="longOption" value="productPath" />
+        <property name="description" value="Root directory to crawl" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="directory" />
+        <property name="required" value="true" />
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>StdProductCrawler.productPath</value>
+                        <value>MetExtractorProductCrawler.productPath</value>
+                        <value>AutoDetectProductCrawler.productPath</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+        <property name="validators">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+            </list>
+        </property>
+    </bean>
+
+    <bean id="metFileExtension" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="mfx" />
+        <property name="longOption" value="metFileExtension" />
+        <property name="description" value="The file extension of existing and to be created PCS metadata files" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="file extension" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchStdCrawler" p:relation="REQUIRED" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>StdProductCrawler.metFileExtension</value>
+                        <value>DeleteMetadataFile.fileExtension</value>
+                        <value>MoveMetadataFileToBackupDir.fileExtension</value>
+                        <value>MoveMetadataFileToFailureDir.fileExtension</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+    <bean id="metExtractor" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="mx" />
+        <property name="longOption" value="metExtractor" />
+        <property name="description" value="Metadata extractor class to use" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="class" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="REQUIRED" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>MetExtractorProductCrawler.metExtractor</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+        <property name="validators">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.validator.ClassExistsCmdLineOptionValidator" />
+            </list>
+        </property>
+    </bean>
+
+    <bean id="metExtractorConfig" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="mxc" />
+        <property name="longOption" value="metExtractorConfig" />
+        <property name="description" value="Config file for metadata extractor" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="file" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="REQUIRED" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>MetExtractorProductCrawler.metExtractorConfig</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+        <property name="validators">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+            </list>
+        </property>
+    </bean>
+
+    <bean id="mimeExtractorRepo" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="mxr" />
+        <property name="longOption" value="mimeExtractorRepo" />
+        <property name="description" value="Mime-type to metadata extractor mapping xml file" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="file" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchAutoCrawler" p:relation="REQUIRED" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>AutoDetectProductCrawler.mimeExtractorRepo</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+        <property name="validators">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.validator.FileExistCmdLineOptionValidator" />
+            </list>
+        </property>
+    </bean>
+
+    <bean id="pushpullMetFileExtension" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="ppmfx" />
+        <property name="longOption" value="pushpullMetFileExtension" />
+        <property name="description" value="File extension of push-pull metadata files" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="file extension" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchStdCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchMetCrawler" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="launchAutoCrawler" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+                <property name="properties">
+                    <list>
+                        <value>DeletePushpullMetFile.fileExtension</value>
+                        <value>MovePushpullMetFileToBackupDir.fileExtension</value>
+                        <value>MovePushpullMetFileToFailureDir.fileExtension</value>
+                        <value>CheckThatPushPullMetFileExists.fileExtension</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+  <bean id="notification" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="n" />
+    <property name="longOption" value="notification" />
+    <property name="description" value="Declare that your want email notification" />
+    <property name="hasArgs" value="false" />
+    <property name="required" value="false" />
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="mailHost" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="sender" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="subject" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="message" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="recipients" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="ignoreInvalidAddresses" p:required="false" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="mailHost" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="mh" />
+    <property name="longOption" value="mailHost" />
+    <property name="description" value="Email Host" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="host" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>SendNotification.emailHost</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="sender" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="sdr" />
+    <property name="longOption" value="sender" />
+    <property name="description" value="Email sender" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="email address" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>SendNotification.sender</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="subject" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="sub" />
+    <property name="longOption" value="subject" />
+    <property name="description" value="Email subject" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="email subject" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>SendNotification.subject</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="message" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="msg" />
+    <property name="longOption" value="message" />
+    <property name="description" value="Email message body" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="email message" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>SendNotification.message</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="recipients" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="rcpts" />
+    <property name="longOption" value="recipients" />
+    <property name="description" value="List of recipient emails" />
+    <property name="type" value="java.util.List" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="email addresses" />
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>SendNotification.recipients</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="ignoreInvalidAddresses" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="iias" />
+    <property name="longOption" value="ignoreInvalidAddresses" />
+    <property name="description" value="If invalid addresses should just be ignored" />
+    <property name="type" value="boolean" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+    <list>
+        <value>true</value>
+    </list>
+    </property>
+    <property name="required" value="false" />
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.crawl.cli.option.handler.CrawlerBeansPropHandler">
+        <property name="properties">
+          <list>
+            <value>SendNotification.ignoreInvalidAddresses</value>
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+</beans>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/crawler-beans.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/crawler-beans.xml
new file mode 100644
index 0000000..a30077f
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/crawler-beans.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">   
+
+    <bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor"/>    
+    
+    <!-- Product Crawlers -->
+    
+    <bean id="StdProductCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.StdProductCrawler">
+        <description>Ingests data files based on existing metadata files</description>
+    </bean>
+    
+    <bean id="MetExtractorProductCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.MetExtractorProductCrawler">
+        <description>Ingests data files after generating a metadat file for it with a given metadata extractor</description>
+    </bean>
+    
+    <bean id="AutoDetectProductCrawler" lazy-init="true" class="org.apache.oodt.cas.crawl.AutoDetectProductCrawler">
+        <description>Ingests data files based on existing metadata files choosing metadata extractors based on mimetypes given in specified mimetype xml file</description>
+    </bean>
+    
+</beans>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/crawler-config.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/crawler-config.xml
new file mode 100755
index 0000000..091b7e0
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/crawler-config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+    <bean class="org.apache.oodt.cas.crawl.util.CasPropertyOverrideConfigurer" />
+
+    <import resource="crawler-beans.xml"/>
+    <import resource="action-beans.xml"/>
+    <import resource="precondition-beans.xml"/>
+    <import resource="naming-beans.xml" />
+
+</beans>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/naming-beans.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/naming-beans.xml
new file mode 100644
index 0000000..38dda48
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/naming-beans.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean id="ExampleNamingConv" class="org.apache.oodt.cas.metadata.filenaming.PathUtilsNamingConvention">
+    <property name="namingConv" value="[ProductType].[NominalDate].txt" />
+  </bean>
+</beans>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/precondition-beans.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/precondition-beans.xml
new file mode 100644
index 0000000..4ba46fa
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/crawler/src/main/resources/policy/precondition-beans.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+    <bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor" />
+  <bean class="org.apache.oodt.cas.crawl.util.CasPropertyPlaceholderConfigurer">
+
+    <!-- Allow for system-level properties to override all properties below -->
+    <property name="systemPropertiesMode" value="2" />
+
+    <!-- Default Properties -->
+    <property name="properties">
+      <props>
+        <prop key="crawler.pushpull.met.file.ext">[PUSHPULL_MET_FILE_EXT]</prop>
+      </props>
+    </property>
+  </bean>
+
+    <!-- Precondition Comparators -->
+    <bean id="CheckThatPushPullMetFileExists" lazy-init="true" class="org.apache.oodt.cas.metadata.preconditions.ExistanceCheckComparator">
+    <property name="fileExtension" value="${crawler.pushpull.met.file.ext}" />
+        <property name="description" value="Checks if the push-pull metadata file exists for the current data file" />
+        <property name="compareItem">
+            <value type="java.lang.Boolean">true</value>
+        </property>
+        <property name="type" value="equal_to" />
+    </bean>
+
+    <bean id="CheckThatDataFileSizeIsGreaterThanZero" lazy-init="true" class="org.apache.oodt.cas.metadata.preconditions.FileSizeComparator">
+        <property name="description" value="Check if the current data file size is greater than zero" />
+        <property name="compareItem">
+            <value type="java.lang.Long">0</value>
+        </property>
+        <property name="type" value="greater_than" />
+    </bean>
+
+    <bean id="AprioriUniquessCheckWithFilemgr" lazy-init="true" class="org.apache.oodt.cas.crawl.comparator.FilemgrUniquenessCheckComparator">
+        <property name="description" value="Checks where the current data file existing in the filemgr based on its FILENAME" />
+        <property name="compareItem">
+            <value type="java.lang.Boolean">false</value>
+        </property>
+        <property name="type" value="equal_to" />
+    </bean>
+</beans>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/pom.xml
new file mode 100644
index 0000000..d2de984
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/pom.xml
@@ -0,0 +1,343 @@
+<?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.
+-->
+<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>
+   <parent>
+      <groupId>${groupId}</groupId>
+      <artifactId>${rootArtifactId}</artifactId>
+      <version>${version}</version>
+      <relativePath>../pom.xml</relativePath>
+   </parent>
+   <artifactId>${rootArtifactId}-${artifactId}</artifactId>
+   <name>Distribution (RADiX Distro of OODT)</name>
+   <packaging>pom</packaging>
+   <properties>
+      <tomcat.version>5.5.23</tomcat.version>
+   </properties>
+   <profiles>
+      <profile>
+         <id>default</id>
+         <activation>
+            <activeByDefault>true</activeByDefault>
+         </activation>
+         <dependencies>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-filemgr</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-crawler</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-workflow</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-pge</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-pcs</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-resmgr</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-extensions</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-opsui</artifactId>
+               <version>${project.parent.version}</version>
+               <type>war</type>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-pcs-services</artifactId>
+               <version>${project.parent.version}</version>
+               <type>war</type>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-fmprod</artifactId>
+               <version>${project.parent.version}</version>
+               <type>war</type>
+            </dependency>
+         </dependencies>
+         <build>
+            <plugins>
+               <plugin>
+                  <groupId>org.apache.maven.plugins</groupId>
+                  <artifactId>maven-dependency-plugin</artifactId>
+                  <version>2.3</version>
+                  <executions>
+                     <execution>
+                        <id>unpack-tomcat</id>
+                        <phase>process-sources</phase>
+                        <goals>
+                           <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                           <artifactItems>
+                              <artifactItem>
+                                 <groupId>tomcat</groupId>
+                                 <artifactId>apache-tomcat</artifactId>
+                                 <version>${tomcat.version}</version>
+                                 <type>zip</type>
+                                 <overWrite>false</overWrite>
+                                 <outputDirectory>${project.build.directory}/</outputDirectory>
+                              </artifactItem>
+                              <artifactItem>
+                                 <groupId>${groupId}</groupId>
+                                 <artifactId>${parent.artifactId}-opsui</artifactId>
+                                 <type>war</type>
+                                 <overWrite>false</overWrite>
+                                 <outputDirectory>${project.build.directory}/apache-tomcat-${tomcat.version}/webapps/opsui</outputDirectory>
+                              </artifactItem>
+                              <artifactItem>
+                                 <groupId>${groupId}</groupId>
+                                 <artifactId>${parent.artifactId}-pcs-services</artifactId>
+                                 <type>war</type>
+                                 <overWrite>false</overWrite>
+                                 <outputDirectory>${project.build.directory}/apache-tomcat-${tomcat.version}/webapps/pcs</outputDirectory>
+                              </artifactItem>
+                              <artifactItem>
+                                 <groupId>${groupId}</groupId>
+                                 <artifactId>${parent.artifactId}-fmprod</artifactId>
+                                 <type>war</type>
+                                 <overWrite>false</overWrite>
+                                 <outputDirectory>${project.build.directory}/apache-tomcat-${tomcat.version}/webapps/fmprod</outputDirectory>
+                              </artifactItem>
+                           </artifactItems>
+                        </configuration>
+                     </execution>
+                  </executions>
+               </plugin>
+               <plugin>
+                  <groupId>org.apache.maven.plugins</groupId>
+                  <artifactId>maven-assembly-plugin</artifactId>
+                  <version>2.2</version>
+                  <configuration>
+                     <descriptors>
+                        <descriptor>src/main/assembly/assembly.xml</descriptor>
+                     </descriptors>
+                  </configuration>
+                  <executions>
+                     <execution>
+                        <phase>package</phase>
+                        <goals>
+                           <goal>single</goal>
+                        </goals>
+                     </execution>
+                  </executions>
+               </plugin>
+            </plugins>
+         </build>
+      </profile>
+      <profile>
+         <id>fm-solr-catalog</id>
+         <activation/>
+         <dependencies>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-filemgr</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-crawler</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-workflow</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-pge</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-pcs</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-resmgr</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-extensions</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-solr</artifactId>
+               <version>${project.parent.version}</version>
+               <type>tar.gz</type>
+               <classifier>bin</classifier>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-opsui</artifactId>
+               <version>${project.parent.version}</version>
+               <type>war</type>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-pcs-services</artifactId>
+               <version>${project.parent.version}</version>
+               <type>war</type>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-fmprod</artifactId>
+               <version>${project.parent.version}</version>
+               <type>war</type>
+            </dependency>
+            <dependency>
+               <groupId>${groupId}</groupId>
+               <artifactId>${rootArtifactId}-solr-webapp</artifactId>
+               <version>${project.parent.version}</version>
+               <type>war</type>
+            </dependency>
+         </dependencies>
+         <build>
+            <plugins>
+               <plugin>
+                  <groupId>org.apache.maven.plugins</groupId>
+                  <artifactId>maven-dependency-plugin</artifactId>
+                  <version>2.3</version>
+                  <executions>
+                     <execution>
+                        <id>unpack-tomcat</id>
+                        <phase>process-sources</phase>
+                        <goals>
+                           <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                           <artifactItems>
+                              <artifactItem>
+                                 <groupId>tomcat</groupId>
+                                 <artifactId>apache-tomcat</artifactId>
+                                 <version>${tomcat.version}</version>
+                                 <type>zip</type>
+                                 <overWrite>false</overWrite>
+                                 <outputDirectory>${project.build.directory}/</outputDirectory>
+                              </artifactItem>
+                              <artifactItem>
+                                 <groupId>${groupId}</groupId>
+                                 <artifactId>${parent.artifactId}-opsui</artifactId>
+                                 <type>war</type>
+                                 <overWrite>false</overWrite>
+                                 <outputDirectory>${project.build.directory}/apache-tomcat-${tomcat.version}/webapps/opsui</outputDirectory>
+                              </artifactItem>
+                              <artifactItem>
+                                 <groupId>${groupId}</groupId>
+                                 <artifactId>${parent.artifactId}-pcs-services</artifactId>
+                                 <type>war</type>
+                                 <overWrite>false</overWrite>
+                                 <outputDirectory>${project.build.directory}/apache-tomcat-${tomcat.version}/webapps/pcs</outputDirectory>
+                              </artifactItem>
+                              <artifactItem>
+                                 <groupId>${groupId}</groupId>
+                                 <artifactId>${parent.artifactId}-fmprod</artifactId>
+                                 <type>war</type>
+                                 <overWrite>false</overWrite>
+                                 <outputDirectory>${project.build.directory}/apache-tomcat-${tomcat.version}/webapps/fmprod</outputDirectory>
+                              </artifactItem>
+                              <artifactItem>
+                                 <groupId>${groupId}</groupId>
+                                 <artifactId>${parent.artifactId}-solr-webapp</artifactId>
+                                 <type>war</type>
+                                 <overWrite>false</overWrite>
+                                 <outputDirectory>${project.build.directory}/apache-tomcat-${tomcat.version}/webapps/solr</outputDirectory>
+                              </artifactItem>
+                           </artifactItems>
+                        </configuration>
+                     </execution>
+                  </executions>
+               </plugin>
+               <plugin>
+                  <groupId>org.apache.maven.plugins</groupId>
+                  <artifactId>maven-assembly-plugin</artifactId>
+                  <version>2.2</version>
+                  <configuration>
+                     <descriptors>
+                        <descriptor>src/main/assembly/assembly.xml</descriptor>
+                     </descriptors>
+                  </configuration>
+                  <executions>
+                     <execution>
+                        <phase>package</phase>
+                        <goals>
+                           <goal>single</goal>
+                        </goals>
+                     </execution>
+                  </executions>
+               </plugin>
+            </plugins>
+         </build>
+      </profile>
+   </profiles>
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/assembly/assembly.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..9d915df
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/assembly/assembly.xml
@@ -0,0 +1,109 @@
+<!--
+ 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.
+-->
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+  <id>bin</id>
+  <formats>
+    <format>tar.gz</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/bin</directory>
+      <outputDirectory>bin</outputDirectory>
+      <includes/>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>logs</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>data</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>data/archive</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>data/staging</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>data/work</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>data/met</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>data/failure</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>${project.build.directory}/apache-tomcat-${tomcat.version}</directory>
+      <outputDirectory>tomcat</outputDirectory>
+      <excludes>
+        <exclude>**/webapps/docs/**</exclude>
+        <exclude>**/webapps/examples/**</exclude>
+        <exclude>**/webapps/host-manager/**</exclude>
+        <exclude>**/webapps/manager/**</exclude>
+        <exclude>**/webapps/servlets-examples/**</exclude>
+        <exclude>**/webapps/jsp-examples/**</exclude>
+        <exclude>**/webapps/webdav/**</exclude>
+      </excludes>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>.</outputDirectory>
+      <unpack>true</unpack>
+      <useProjectArtifact>false</useProjectArtifact>
+      <useTransitiveDependencies>false</useTransitiveDependencies>
+      <excludes>
+        <exclude>${groupId}:${parent.artifactId}-opsui</exclude>
+        <exclude>${groupId}:${parent.artifactId}-pcs-services</exclude>
+        <exclude>${groupId}:${parent.artifactId}-fmprod</exclude>
+        <exclude>${groupId}:${parent.artifactId}-solr-webapp</exclude>
+      </excludes>
+    </dependencySet>
+  </dependencySets>
+</assembly>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/resources/bin/env.sh b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/resources/bin/env.sh
new file mode 100755
index 0000000..f51f0ca
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/resources/bin/env.sh
@@ -0,0 +1,205 @@
+#!/bin/sh
+
+# 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.
+
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false
+os400=false
+darwin=false
+case "`uname`" in
+CYGWIN*) cygwin=true;;
+OS400*) os400=true;;
+Darwin*) darwin=true;;
+esac
+
+# resolve links - $0 may be a softlink
+PRG="$0"
+
+while [ -h "$PRG" ]; do
+  ls=`ls -ld "$PRG"`
+  link=`expr "$ls" : '.*-> \(.*\)$'`
+  if expr "$link" : '/.*' > /dev/null; then
+    PRG="$link"
+  else
+    PRG=`dirname "$PRG"`/"$link"
+  fi
+done
+
+# Get standard environment variables
+PRGDIR=`dirname "$PRG"`
+
+# Only set OODT_HOME if not already set
+[ -z "$OODT_HOME" ] && OODT_HOME=`cd "$PRGDIR/.." ; pwd`
+
+export OODT_HOME
+
+# Ensure that any user defined CLASSPATH variables are not used on startup,
+# but allow them to be specified in setenv.sh, in rare case when it is needed.
+CLASSPATH=
+
+if [ -r "$OODT_BASE"/bin/setenv.sh ]; then
+  . "$OODT_BASE"/bin/setenv.sh
+elif [ -r "$OODT_HOME"/bin/setenv.sh ]; then
+  . "$OODT_HOME"/bin/setenv.sh
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$JRE_HOME" ] && JRE_HOME=`cygpath --unix "$JRE_HOME"`
+  [ -n "$OODT_HOME" ] && OODT_HOME=`cygpath --unix "$OODT_HOME"`
+  [ -n "$OODT_BASE" ] && OODT_BASE=`cygpath --unix "$OODT_BASE"`
+  [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# Get standard Java environment variables
+if $os400; then
+  # -r will Only work on the os400 if the files are:
+  # 1. owned by the user
+  # 2. owned by the PRIMARY group of the user
+  # this will not work if the user belongs in secondary groups
+  BASEDIR="$OODT_HOME"
+  . "$OODT_HOME"/bin/setclasspath.sh
+else
+  if [ -r "$OODT_HOME"/bin/setclasspath.sh ]; then
+    BASEDIR="$OODT_HOME"
+    . "$OODT_HOME"/bin/setclasspath.sh
+  else
+    echo "Cannot find $OODT_HOME/bin/setclasspath.sh"
+    echo "This file is needed to run this program"
+    exit 1
+  fi
+fi
+
+if [ -z "$OODT_BASE" ]; then
+  OODT_BASE="$OODT_HOME"
+  export OODT_BASE
+fi
+
+if [ -z "$OODT_OUT" ] ; then
+  OODT_OUT="$OODT_BASE"/logs/oodt.out
+  export OODT_OUT
+fi
+
+if [ -z "$FILEMGR_HOME" ]; then
+  FILEMGR_HOME="$OODT_HOME"/filemgr
+  export FILEMGR_HOME
+fi
+
+if [ -z "$WORKFLOW_HOME" ]; then
+  WORKFLOW_HOME="$OODT_HOME"/workflow
+  export WORKFLOW_HOME
+fi
+
+if [ -z "$RESMGR_HOME" ]; then
+  RESMGR_HOME="$OODT_HOME"/resmgr
+  export RESMGR_HOME
+fi
+
+if [ -z "$PCS_HOME" ]; then
+  PCS_HOME="$OODT_HOME"/pcs
+  export PCS_HOME
+fi
+
+if [ -z "$CRAWLER_HOME" ]; then
+  CRAWLER_HOME="$OODT_HOME"/crawler
+  export CRAWLER_HOME
+fi
+
+if [ -z "$PGE_ROOT" ]; then
+  PGE_ROOT="$OODT_HOME"/pge
+  export PGE_ROOT
+fi
+
+if [ -z "$SOLR_HOME" ]; then
+  SOLR_HOME="$OODT_HOME"/solr
+  export SOLR_HOME
+fi
+
+if [ -z "$OODT_TMPDIR" ]; then
+  # Define the java.io.tmpdir to use for OODT
+  OODT_TMPDIR="$OODT_BASE"/temp
+  export OODT_TMPDIR
+fi
+
+if [ -z "$FILEMGR_PORT" ]; then
+  FILEMGR_PORT=9000
+  export FILEMGR_PORT
+fi
+
+if [ -z "$CRAWLER_PORT" ]; then
+  CRAWLER_PORT=9020
+  export CRAWLER_PORT
+fi 
+
+if [ -z "$WORKFLOW_PORT" ]; then
+  WORKFLOW_PORT=9001
+  export WORKFLOW_PORT
+fi
+
+if [ -z "$RESMGR_PORT" ]; then
+  RESMGR_PORT=9002
+  export RESMGR_PORT
+fi
+
+if [ -z "$TOMCAT_PORT" ]; then
+  TOMCAT_PORT=8080
+  export TOMCAT_PORT
+fi
+
+if [ -z "$OODT_SERVICES_HOST" ]; then
+  OODT_SERVICES_HOST=localhost
+  export OODT_SERVICES_HOST
+fi
+
+if [ -z "$FILEMGR_URL" ]; then
+  FILEMGR_URL=http://"$OODT_SERVICES_HOST":"$FILEMGR_PORT"
+  export FILEMGR_URL
+fi
+
+if [ -z "$WORKFLOW_URL" ]; then
+  WORKFLOW_URL=http://"$OODT_SERVICES_HOST":"$WORKFLOW_PORT"
+  export WORKFLOW_URL
+fi
+
+if [ -z "$RESMGR_URL" ]; then
+  RESMGR_URL=http://"$OODT_SERVICES_HOST":"$RESMGR_PORT"
+  export RESMGR_URL
+fi
+
+if [ -z "$CRAWLER_URL" ]; then
+  CRAWLER_URL=http://"$OODT_SERVICES_HOST":"$CRAWLER_PORT"
+  export CRAWLER_URL
+fi
+
+
+# When no TTY is available, don't output to console
+have_tty=0
+if [ "`tty`" != "not a tty" ]; then
+    have_tty=1
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  JAVA_HOME=`cygpath --absolute --windows "$JAVA_HOME"`
+  JRE_HOME=`cygpath --absolute --windows "$JRE_HOME"`
+  OODT_HOME=`cygpath --absolute --windows "$OODT_HOME"`
+  OODT_BASE=`cygpath --absolute --windows "$OODT_BASE"`
+  OODT_TMPDIR=`cygpath --absolute --windows "$OODT_TMPDIR"`
+  CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+  JAVA_ENDORSED_DIRS=`cygpath --path --windows "$JAVA_ENDORSED_DIRS"`
+fi
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/resources/bin/oodt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/resources/bin/oodt
new file mode 100755
index 0000000..6648bc7
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/resources/bin/oodt
@@ -0,0 +1,168 @@
+#!/usr/bin/env bash
+
+# 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.
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false
+os400=false
+darwin=false
+case "`uname`" in
+CYGWIN*) cygwin=true;;
+OS400*) os400=true;;
+Darwin*) darwin=true;;
+esac
+
+# resolve links - $0 may be a softlink
+PRG="$0"
+
+while [ -h "$PRG" ]; do
+  ls=`ls -ld "$PRG"`
+  link=`expr "$ls" : '.*-> \(.*\)$'`
+  if expr "$link" : '/.*' > /dev/null; then
+    PRG="$link"
+  else
+    PRG=`dirname "$PRG"`/"$link"
+  fi
+done
+
+# Get standard environment variables
+PRGDIR=`dirname "$PRG"`
+
+# Only set OODT_HOME if not already set
+[ -z "$OODT_HOME" ] && OODT_HOME=`cd "$PRGDIR/.." ; pwd`
+
+# Get OODT environment set up
+if [ -r "$OODT_HOME"/bin/env.sh ]; then
+  . "$OODT_HOME"/bin/env.sh
+fi
+
+# Only output this if we have a TTY
+if [ $have_tty -eq 1 ]; then
+  echo "Using OODT_BASE:   $OODT_BASE"
+  echo "Using OODT_HOME:   $OODT_HOME"
+  echo "Using OODT_TMPDIR: $OODT_TMPDIR"
+  if [ "$1" = "debug" ] ; then
+    echo "Using JAVA_HOME:       $JAVA_HOME"
+  else
+    echo "Using JRE_HOME:        $JRE_HOME"
+  fi
+  echo "Using CLASSPATH:       $CLASSPATH"
+fi
+
+WORKFLOW_EXEC=wmgr
+RESMGR_EXEC=resmgr
+FILEMGR_EXEC=filemgr
+TOMCAT_EXEC=catalina.sh
+
+# Check that target executable exists
+if [ ! -x "$FILEMGR_HOME"/bin/"$FILEMGR_EXEC" ]; then
+  echo "Cannot find $FILEMGR_HOME/bin/$FILEMGR_EXEC"
+  echo "This file is needed to run this program"
+  exit 1
+fi
+
+# Check that target executable exists
+if [ ! -x "$WORKFLOW_HOME"/bin/"$WORKFLOW_EXEC" ]; then
+  echo "Cannot find $WORKFLOW_HOME/bin/$WORKFLOW_EXEC"
+  echo "This file is needed to run this program"
+  exit 1
+fi
+
+# Check that target executable exists
+if [ ! -x "$RESMGR_HOME"/bin/"$RESMGR_EXEC" ]; then
+  echo "Cannot find $RESMGR_HOME/bin/$RESMGR_EXEC"
+  echo "This file is needed to run this program"
+  exit 1
+fi
+
+# Check that target executable exists
+if [ ! -x "$OODT_BASE"/tomcat/bin/"$TOMCAT_EXEC" ]; then
+  echo "Cannot find $OODT_BASE/tomcat/bin/$TOMCAT_EXEC"
+  echo "This file is needed to run this program"
+  exit 1
+fi
+
+if [ "$1" = "start" ]; then
+  exec "$FILEMGR_HOME"/bin/"$FILEMGR_EXEC" start "$@" >> "$OODT_OUT" 2>&1  &
+  exec "$WORKFLOW_HOME"/bin/"$WORKFLOW_EXEC" start "$@" >> "$OODT_OUT" 2>&1  &
+  exec "$RESMGR_HOME"/bin/"$RESMGR_EXEC" start "$@" >> "$OODT_OUT" 2>&1  &  
+  exec "$OODT_BASE"/tomcat/bin/"$TOMCAT_EXEC" start "$@" >> "$OODT_OUT" 2>&1 &
+  sleep 0.2s
+# Print confirmation messages to the end user
+# FileManager
+# check if the PID file exists:
+  if [ ! -e "../filemgr/run/cas.filemgr.pid" ] 
+  then
+    # no pid file was created by the process, it must have failed.
+    echo -e 'Starting OODT File Manager [' $'\e[31m' 'Failed' $'\e[00m' ']'
+
+  else
+    # pid file exists, check if the associated process is running.
+    if kill -0 `cat ../filemgr/run/cas.filemgr.pid` > /dev/null 2>&1;
+    then
+        echo -e 'Starting OODT File Manager [' $'\e[32m' 'Successful' $'\e[00m' ']'
+    else
+        echo -e 'Starting OODT File Manager [' $'\e[31m' 'Failed' $'\e[00m' ']'
+    fi
+  fi
+
+# ResourceManager
+# check if the PID file exists:
+  if [ ! -e "../resmgr/run/cas.resmgr.pid" ]
+  then
+    # no pid file was created by the process, it must have failed.
+    echo -e 'Starting OODT Resource Manager [' $'\e[31m' 'Failed' $'\e[00m' ']'
+
+  else
+    # pid file exists, check if the associated process is running.
+    if kill -0 `cat ../resmgr/run/cas.resmgr.pid` > /dev/null 2>&1;
+    then
+        echo -e 'Starting OODT Resource Manager [' $'\e[32m' 'Successful' $'\e[00m' ']'
+    else
+        echo -e 'Starting OODT Resource Manager [' $'\e[31m' 'Failed' $'\e[00m' ']'
+    fi
+  fi
+
+
+# WorkflowManager
+# check if the PID file exists:
+  if [ ! -e "../workflow/run/cas.workflow.pid" ]
+  then
+    # no pid file was created by the process, it must have failed.
+    echo -e 'Starting OODT Workflow Manager [' $'\e[31m' 'Failed' $'\e[00m' ']'
+
+  else
+    # pid file exists, check if the associated process is running.
+    if kill -0 `cat ../workflow/run/cas.workflow.pid` > /dev/null 2>&1;
+    then
+        echo -e 'Starting OODT Workflow Manager [' $'\e[32m' 'Successful' $'\e[00m' ']'
+    else
+        echo -e 'Starting OODT Workflow Manager [' $'\e[31m' 'Failed' $'\e[00m' ']'
+    fi
+  fi
+elif [ "$1" = "stop" ]; then
+  exec "$FILEMGR_HOME"/bin/"$FILEMGR_EXEC" stop "$@" >> "$OODT_OUT" 2>&1  &
+  exec "$WORKFLOW_HOME"/bin/"$WORKFLOW_EXEC" stop "$@" >> "$OODT_OUT" 2>&1 &
+  exec "$RESMGR_HOME"/bin/"$RESMGR_EXEC" stop "$@" >> "$OODT_OUT" 2>&1 &
+  exec "$OODT_BASE"/tomcat/bin/"$TOMCAT_EXEC" stop "$@" >> "$OODT_OUT" 2>&1 &
+else
+  echo "Usage: oodt.sh ( commands ... )"
+  echo "commands:"
+  echo "  start             Start OODT in a separate window"
+  echo "  stop              Stop OODT, waiting up to 5 seconds for the process to end"
+#  echo "  version           What version of OODT are you running?"
+  exit 1
+fi
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/resources/bin/setclasspath.sh b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/resources/bin/setclasspath.sh
new file mode 100644
index 0000000..90e5f0e
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/resources/bin/setclasspath.sh
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+# 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.
+
+# -----------------------------------------------------------------------------
+#  Set CLASSPATH and Java options
+#
+#  $Id$
+# -----------------------------------------------------------------------------
+
+# Make sure prerequisite environment variables are set
+if [ -z "$JAVA_HOME" -a -z "$JRE_HOME" ]; then
+  if $darwin; then
+    if [ -d "/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home" ]; then
+      export JAVA_HOME="/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home"
+    fi
+  else
+    JAVA_PATH=`which java 2>/dev/null`
+    if [ "x$JAVA_PATH" != "x" ]; then
+      JAVA_PATH=`dirname $JAVA_PATH 2>/dev/null`
+      JRE_HOME=`dirname $JAVA_PATH 2>/dev/null`
+    fi
+    if [ "x$JRE_HOME" = "x" ]; then
+      # XXX: Should we try other locations?
+      if [ -x /usr/bin/java ]; then
+        JRE_HOME=/usr
+      fi
+    fi
+  fi
+  if [ -z "$JAVA_HOME" -a -z "$JRE_HOME" ]; then
+    echo "Neither the JAVA_HOME nor the JRE_HOME environment variable is defined"
+    echo "At least one of these environment variable is needed to run this program"
+    exit 1
+  fi
+fi
+if [ -z "$JAVA_HOME" -a "$1" = "debug" ]; then
+  echo "JAVA_HOME should point to a JDK in order to run in debug mode."
+  exit 1
+fi
+if [ -z "$JRE_HOME" ]; then
+  JRE_HOME="$JAVA_HOME"
+fi
+
+# If we're running under jdb, we need a full jdk.
+if [ "$1" = "debug" ] ; then
+  if [ "$os400" = "true" ]; then
+    if [ ! -x "$JAVA_HOME"/bin/java -o ! -x "$JAVA_HOME"/bin/javac ]; then
+      echo "The JAVA_HOME environment variable is not defined correctly"
+      echo "This environment variable is needed to run this program"
+      echo "NB: JAVA_HOME should point to a JDK not a JRE"
+      exit 1
+    fi
+  else
+    if [ ! -x "$JAVA_HOME"/bin/java -o ! -x "$JAVA_HOME"/bin/jdb -o ! -x "$JAVA_HOME"/bin/javac ]; then
+      echo "The JAVA_HOME environment variable is not defined correctly"
+      echo "This environment variable is needed to run this program"
+      echo "NB: JAVA_HOME should point to a JDK not a JRE"
+      exit 1
+    fi
+  fi
+fi
+if [ -z "$BASEDIR" ]; then
+  echo "The BASEDIR environment variable is not defined"
+  echo "This environment variable is needed to run this program"
+  exit 1
+fi
+if [ ! -x "$BASEDIR"/bin/setclasspath.sh ]; then
+  if $os400; then
+    # -x will Only work on the os400 if the files are:
+    # 1. owned by the user
+    # 2. owned by the PRIMARY group of the user
+    # this will not work if the user belongs in secondary groups
+    eval
+  else
+    echo "The BASEDIR environment variable is not defined correctly"
+    echo "This environment variable is needed to run this program"
+    exit 1
+  fi
+fi
+
+# Don't override the endorsed dir if the user has set it previously
+if [ -z "$JAVA_ENDORSED_DIRS" ]; then
+  # Set the default -Djava.endorsed.dirs argument
+  JAVA_ENDORSED_DIRS="$BASEDIR"/endorsed
+fi
+
+# OSX hack to CLASSPATH
+JIKESPATH=
+if [ `uname -s` = "Darwin" ]; then
+  OSXHACK="/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Classes"
+  if [ -d "$OSXHACK" ]; then
+    for i in "$OSXHACK"/*.jar; do
+      JIKESPATH="$JIKESPATH":"$i"
+    done
+  fi
+fi
+
+# Set standard commands for invoking Java.
+_RUNJAVA="$JRE_HOME"/bin/java
+if [ "$os400" != "true" ]; then
+  _RUNJDB="$JAVA_HOME"/bin/jdb
+fi
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/resources/bin/setenv.sh b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/resources/bin/setenv.sh
new file mode 100644
index 0000000..5e6dbbf
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/distribution/src/main/resources/bin/setenv.sh
@@ -0,0 +1,13 @@
+########  setenv.sh ########
+#
+# Set project specific configuration in setenv.sh
+#
+# Example:
+# 		- Change filemgr URL to http://locatlhost:1234
+#			FILEMGR_URL=http://locatlhost:1234
+#
+#		- Set custom job directory
+#			PROJECT_JOB_DIR=/usr/local/project/data/jobs
+#
+############################
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/extensions/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/extensions/pom.xml
new file mode 100644
index 0000000..97526c7
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/extensions/pom.xml
@@ -0,0 +1,81 @@
+<?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.

+-->

+<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>

+  <parent>

+    <groupId>${groupId}</groupId>

+    <artifactId>${rootArtifactId}</artifactId>

+    <version>${version}</version>

+    <relativePath>../pom.xml</relativePath>

+  </parent>

+  <artifactId>${rootArtifactId}-${artifactId}</artifactId>

+  <packaging>jar</packaging>

+  <name>Extensions</name>

+  <description>Library of classes that are reused across subcomponents.</description>

+

+  <build>

+    <plugins>

+      <plugin>

+        <groupId>org.apache.maven.plugins</groupId>

+        <artifactId>maven-assembly-plugin</artifactId>

+        <version>2.2-beta-2</version>

+        <configuration>

+          <descriptors>

+            <descriptor>src/main/assembly/assembly.xml</descriptor>

+          </descriptors>

+        </configuration>

+        <executions>

+          <execution>

+            <id>dist-assembly</id>

+            <phase>package</phase>

+            <goals>

+              <goal>single</goal>

+            </goals>

+          </execution>

+        </executions>

+      </plugin>

+    </plugins>

+  </build>

+

+  <dependencies>

+    <dependency>

+      <groupId>org.apache.oodt</groupId>

+      <artifactId>cas-metadata</artifactId>

+      <version>${oodt.version}</version>

+    </dependency>

+    <dependency>

+      <groupId>org.apache.oodt</groupId>

+      <artifactId>cas-filemgr</artifactId>

+      <version>${oodt.version}</version>

+    </dependency>

+    <dependency>

+      <groupId>org.apache.oodt</groupId>

+      <artifactId>pcs-core</artifactId>

+      <version>${oodt.version}</version>

+    </dependency>

+    <dependency>

+      <groupId>junit</groupId>

+      <artifactId>junit</artifactId>

+      <version>3.8.2</version>

+    </dependency>

+  </dependencies>

+

+</project>

diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/extensions/src/main/assembly/assembly.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/extensions/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..b02cde6
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/extensions/src/main/assembly/assembly.xml
@@ -0,0 +1,72 @@
+<!--
+ 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.
+-->
+<assembly>
+  <id>bin</id>
+  <formats>
+    <format>tar.gz</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <baseDirectory>extensions</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/extractor/bin</directory>
+      <outputDirectory>extensions/extractor/bin</outputDirectory>
+      <includes/>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/logs</directory>
+      <outputDirectory>extensions/logs</outputDirectory>
+      <includes>
+        <include>REMOVE.log</include>
+      </includes>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/extractor/etc</directory>
+      <outputDirectory>extensions/extractor/etc</outputDirectory>
+      <includes/>
+      <fileMode>664</fileMode>
+      <directoryMode>775</directoryMode>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>extensions/lib</outputDirectory>
+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>
+      <unpackOptions/>
+    </dependencySet>
+  </dependencySets>
+</assembly>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/extensions/src/main/resources/logs/REMOVE.log b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/extensions/src/main/resources/logs/REMOVE.log
new file mode 100644
index 0000000..9215491
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/extensions/src/main/resources/logs/REMOVE.log
@@ -0,0 +1,18 @@
+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.
+
+
+You can remove this file. It was only included to ensure that the log directory for this
+distribution was created on assembly.
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/pom.xml
new file mode 100644
index 0000000..d0216db
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/pom.xml
@@ -0,0 +1,116 @@
+<?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.
+-->
+<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>
+   <parent>
+      <groupId>${groupId}</groupId>
+      <artifactId>${rootArtifactId}</artifactId>
+      <version>${version}</version>
+      <relativePath>../pom.xml</relativePath>
+   </parent>
+   <name>File Manager (Apache OODT)</name>
+   <artifactId>${rootArtifactId}-${artifactId}</artifactId>
+   <packaging>jar</packaging>
+   <profiles>
+      <profile>
+         <id>default</id>
+         <activation>
+            <activeByDefault>true</activeByDefault>
+         </activation>
+         <build>
+            <plugins>
+               <plugin>
+                  <groupId>org.apache.maven.plugins</groupId>
+                  <artifactId>maven-assembly-plugin</artifactId>
+                  <version>2.2-beta-2</version>
+                  <configuration>
+                     <descriptors>
+                        <descriptor>src/main/assembly/assembly.xml</descriptor>
+                     </descriptors>
+                  </configuration>
+                  <executions>
+                     <execution>
+                        <id>dist-assembly</id>
+                        <phase>package</phase>
+                        <goals>
+                           <goal>single</goal>
+                        </goals>
+                     </execution>
+                  </executions>
+               </plugin>
+            </plugins>
+         </build>
+      </profile>
+      <profile>
+         <id>fm-solr-catalog</id>
+         <activation/>
+         <build>
+            <plugins>
+               <plugin>
+                  <groupId>org.apache.maven.plugins</groupId>
+                  <artifactId>maven-assembly-plugin</artifactId>
+                  <version>2.2-beta-2</version>
+                  <configuration>
+                     <descriptors>
+                        <descriptor>src/main/assembly/assembly.fm-solr-catalog.xml</descriptor>
+                     </descriptors>
+                  </configuration>
+                  <executions>
+                     <execution>
+                        <id>dist-assembly</id>
+                        <phase>package</phase>
+                        <goals>
+                           <goal>single</goal>
+                        </goals>
+                     </execution>
+                  </executions>
+               </plugin>
+            </plugins>
+         </build>
+      </profile>
+   </profiles>
+   <dependencies>
+      <dependency>
+         <groupId>${groupId}</groupId>
+         <artifactId>${rootArtifactId}-extensions</artifactId>
+         <version>${project.parent.version}</version>
+         <type>jar</type>
+         <scope>runtime</scope>
+         <exclusions>
+            <exclusion>
+               <groupId>org.apache.oodt</groupId>
+               <artifactId>cas-filemgr</artifactId>
+            </exclusion>
+         </exclusions>
+      </dependency>
+      <dependency>
+         <groupId>org.apache.oodt</groupId>
+         <artifactId>cas-filemgr</artifactId>
+         <version>${oodt.version}</version>
+      </dependency>
+      <dependency>
+         <groupId>junit</groupId>
+         <artifactId>junit</artifactId>
+         <version>3.8.2</version>
+         <scope>test</scope>
+      </dependency>
+   </dependencies>
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/assembly/assembly.fm-solr-catalog.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/assembly/assembly.fm-solr-catalog.xml
new file mode 100644
index 0000000..030c84c
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/assembly/assembly.fm-solr-catalog.xml
@@ -0,0 +1,100 @@
+<!--
+ 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.
+-->
+<assembly>
+  <id>bin</id>
+  <formats>
+    <format>tar.gz</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <baseDirectory>filemgr</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/bin</directory>
+      <outputDirectory>filemgr/bin</outputDirectory>
+      <includes/>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>filemgr/logs</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>filemgr/run</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/etc</directory>
+      <outputDirectory>filemgr/etc</outputDirectory>
+      <includes>
+        <include>**.xml</include>
+      </includes>
+      <excludes>
+        <exclude>filemgr.properties</exclude>
+      </excludes>
+      <fileMode>664</fileMode>
+      <directoryMode>775</directoryMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/policy</directory>
+      <outputDirectory>filemgr/policy</outputDirectory>
+      <includes>
+        <include>**/**.xml</include>
+      </includes>
+      <fileMode>664</fileMode>
+      <directoryMode>775</directoryMode>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>
+  </fileSets>
+    <files>
+      <file>
+        <source>${basedir}/src/main/resources/etc/filemgr.fm-solr-catalog.properties</source>
+        <outputDirectory>filemgr/etc</outputDirectory>
+        <destName>filemgr.properties</destName>
+      </file>
+    </files>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>filemgr/lib</outputDirectory>
+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>
+      <unpackOptions/>
+    </dependencySet>
+  </dependencySets>
+</assembly>
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/assembly/assembly.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..bfe8831
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/assembly/assembly.xml
@@ -0,0 +1,91 @@
+<!--
+ 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.
+-->
+<assembly>
+  <id>bin</id>
+  <formats>
+    <format>tar.gz</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <baseDirectory>filemgr</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/bin</directory>
+      <outputDirectory>filemgr/bin</outputDirectory>
+      <includes/>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>filemgr/logs</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>filemgr/run</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/etc</directory>
+      <outputDirectory>filemgr/etc</outputDirectory>
+      <includes>
+        <include>filemgr.properties</include>
+        <include>**.xml</include>
+      </includes>
+      <fileMode>664</fileMode>
+      <directoryMode>775</directoryMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/policy</directory>
+      <outputDirectory>filemgr/policy</outputDirectory>
+      <includes>
+        <include>**/**.xml</include>
+      </includes>
+      <fileMode>664</fileMode>
+      <directoryMode>775</directoryMode>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>filemgr/lib</outputDirectory>
+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>
+      <unpackOptions/>
+    </dependencySet>
+  </dependencySets>
+</assembly>
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/bin/filemgr b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/bin/filemgr
new file mode 100644
index 0000000..867b77c
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/bin/filemgr
@@ -0,0 +1,168 @@
+#!/bin/sh
+
+# 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.
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false
+os400=false
+darwin=false
+case "`uname`" in
+CYGWIN*) cygwin=true;;
+OS400*) os400=true;;
+Darwin*) darwin=true;;
+esac
+
+# resolve links - $0 may be a softlink
+PRG="$0"
+
+while [ -h "$PRG" ]; do
+  ls=`ls -ld "$PRG"`
+  link=`expr "$ls" : '.*-> \(.*\)$'`
+  if expr "$link" : '/.*' > /dev/null; then
+    PRG="$link"
+  else
+    PRG=`dirname "$PRG"`/"$link"
+  fi
+done
+
+# Get standard environment variables
+PRGDIR=`dirname "$PRG"`
+
+# Only set OODT_HOME if not already set
+[ -z "$OODT_HOME" ] && OODT_HOME=`cd "$PRGDIR/../.." ; pwd`
+
+# Get OODT environment set up
+if [ -r "$OODT_HOME"/bin/env.sh ]; then
+  . "$OODT_HOME"/bin/env.sh
+fi
+
+# Only set FILEMGR_HOME if not already set
+if [ -z "$FILEMGR_HOME" ]; then
+  FILEMGR_HOME="$OODT_HOME"/filemgr
+  export FILEMGR_HOME
+fi
+
+if [ -z "$FILEMGR_PID" ]; then
+  FILEMGR_PID="$FILEMGR_HOME"/run/cas.filemgr.pid
+fi 
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$JRE_HOME" ] && JRE_HOME=`cygpath --unix "$JRE_HOME"`
+  [ -n "$OODT_HOME" ] && OODT_HOME=`cygpath --unix "$OODT_HOME"`
+  [ -n "$FILEMGR_HOME" ] && FILEMGR_HOME=`cygpath --unix "$FILEMGR_HOME"`
+  [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+if [ "$1" = "start" ]; then
+  if [ ! -z "$FILEMGR_PID" ]; then
+    if [ -f "$FILEMGR_PID" ]; then
+      echo "PID file ($FILEMGR_PID) found. Is File Manager still running? Start aborted."
+      exit 1
+    fi
+  fi
+
+  # Move to bin directory in case this is called from some other directory. 
+  # This is to keep relative paths correct.
+  cd "$FILEMGR_HOME"/bin
+  
+  "$_RUNJAVA" $JAVA_OPTS $OODT_OPTS \
+    -Djava.ext.dirs="$FILEMGR_HOME"/lib \
+    -Djava.util.logging.config.file="$FILEMGR_HOME"/etc/logging.properties \
+    -Dorg.apache.oodt.cas.filemgr.properties="$FILEMGR_HOME"/etc/filemgr.properties \
+    -Djava.io.tmpdir="$OODT_TMPDIR" \
+    org.apache.oodt.cas.filemgr.system.XmlRpcFileManager \
+    --portNum $FILEMGR_PORT 2>&1 &
+
+  if [ ! -z "$FILEMGR_PID" ]; then
+    echo $! > $FILEMGR_PID
+  fi
+
+  if [ $have_tty -eq 1 ]; then
+    echo "File Manager started PID file ($FILEMGR_PID)."
+  fi
+
+elif [ "$1" = "stop" ]; then
+
+  shift
+
+  SLEEP=5
+  if [ ! -z "$1" ]; then
+    echo $1 | grep "[^0-9]" > /dev/null 2>&1
+    if [ $? -eq 1 ]; then
+      SLEEP=$1
+      shift
+    fi
+  fi
+
+  FORCE=0
+  if [ "$1" = "-force" ]; then
+    shift
+    FORCE=1
+  fi
+
+  if [ ! -z "$FILEMGR_PID" ]; then
+    if [ -f "$FILEMGR_PID" ]; then
+      kill `cat $FILEMGR_PID` >/dev/null 2>&1
+      if [ $? -eq 1 ]; then
+        echo "ID file ($FILEMGR_PID) found with PID `cat $FILEMGR_PID` but no matching process was found. Removed $FILEMGR_PID, now FileManager can be started."
+        `rm $FILEMGR_PID`
+        exit 1
+      fi
+    else
+      echo "\$FILEMGR_PID was set ($FILEMGR_PID) but the specified file does not exist. Is File Manager running? Stop aborted."
+      exit 1
+    fi
+  fi
+
+  if [ ! -z "$FILEMGR_PID" ]; then
+    if [ -f "$FILEMGR_PID" ]; then
+      while [ $SLEEP -ge 0 ]; do
+        kill -0 `cat $FILEMGR_PID` >/dev/null 2>&1
+        if [ $? -eq 1 ]; then
+          rm $FILEMGR_PID
+          break
+        fi
+        if [ $SLEEP -gt 0 ]; then
+          sleep 1
+        fi
+        if [ $SLEEP -eq 0 ]; then
+          if [ $FORCE -eq 0 ]; then
+            echo "File Manager did not stop in time. PID file was not removed."
+          fi
+        fi
+        SLEEP=`expr $SLEEP - 1 `
+      done
+    fi
+  fi
+
+  if [ $FORCE -eq 1 ]; then
+    if [ -z "$FILEMGR_PID" ]; then
+      echo "Kill failed: \$FILEMGR_PID not set"
+    else
+      if [ -f "$FILEMGR_PID" ]; then
+        echo "Killing: `cat $FILEMGR_PID`"
+        kill -9 `cat $FILEMGR_PID`
+        rm $FILEMGR_PID
+      fi
+    fi
+  fi
+
+else
+  echo "Usage: filemgr {start|stop|status}"
+  exit 1
+fi
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/bin/filemgr-client b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/bin/filemgr-client
new file mode 100644
index 0000000..e30ebd2
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/bin/filemgr-client
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+# 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.
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false
+os400=false
+darwin=false
+case "`uname`" in
+CYGWIN*) cygwin=true;;
+OS400*) os400=true;;
+Darwin*) darwin=true;;
+esac
+
+# resolve links - $0 may be a softlink
+PRG="$0"
+
+while [ -h "$PRG" ]; do
+  ls=`ls -ld "$PRG"`
+  link=`expr "$ls" : '.*-> \(.*\)$'`
+  if expr "$link" : '/.*' > /dev/null; then
+    PRG="$link"
+  else
+    PRG=`dirname "$PRG"`/"$link"
+  fi
+done
+
+# Get standard environment variables
+PRGDIR=`dirname "$PRG"`
+
+# Only set OODT_HOME if not already set
+[ -z "$OODT_HOME" ] && OODT_HOME=`cd "$PRGDIR/../.." ; pwd`
+
+# Get OODT environment set up
+if [ -r "$OODT_HOME"/bin/env.sh ]; then
+  . "$OODT_HOME"/bin/env.sh
+fi
+
+# Only set FILEMGR_HOME if not already set
+if [ -z "$FILEMGR_HOME" ]; then
+  FILEMGR_HOME="$OODT_HOME"/filemgr
+  export FILEMGR_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$JRE_HOME" ] && JRE_HOME=`cygpath --unix "$JRE_HOME"`
+  [ -n "$OODT_HOME" ] && OODT_HOME=`cygpath --unix "$OODT_HOME"`
+  [ -n "$FILEMGR_HOME" ] && FILEMGR_HOME=`cygpath --unix "$FILEMGR_HOME"`
+  [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# Move to bin directory in case this is called from some other directory.
+# This is to keep relative paths correct.
+cd "$FILEMGR_HOME"/bin
+
+"$_RUNJAVA" $JAVA_OPTS $OODT_OPTS \
+  -Djava.ext.dirs="$FILEMGR_HOME"/lib \
+  -Dorg.apache.oodt.cas.filemgr.properties="$FILEMGR_HOME"/etc/filemgr.properties \
+  -Djava.util.logging.config.file="$FILEMGR_HOME"/etc/logging.properties \
+  -Dorg.apache.oodt.cas.cli.action.spring.config=file:"$FILEMGR_HOME"/policy/cmd-line-actions.xml \
+  -Dorg.apache.oodt.cas.cli.option.spring.config=file:"$FILEMGR_HOME"/policy/cmd-line-options.xml \
+  org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient "$@"
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/bin/query-tool b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/bin/query-tool
new file mode 100644
index 0000000..ce02792
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/bin/query-tool
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+# 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.
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false
+os400=false
+darwin=false
+case "`uname`" in
+CYGWIN*) cygwin=true;;
+OS400*) os400=true;;
+Darwin*) darwin=true;;
+esac
+
+# resolve links - $0 may be a softlink
+PRG="$0"
+
+while [ -h "$PRG" ]; do
+  ls=`ls -ld "$PRG"`
+  link=`expr "$ls" : '.*-> \(.*\)$'`
+  if expr "$link" : '/.*' > /dev/null; then
+    PRG="$link"
+  else
+    PRG=`dirname "$PRG"`/"$link"
+  fi
+done
+
+# Get standard environment variables
+PRGDIR=`dirname "$PRG"`
+
+# Only set OODT_HOME if not already set
+[ -z "$OODT_HOME" ] && OODT_HOME=`cd "$PRGDIR/../.." ; pwd`
+
+# Get OODT environment set up
+if [ -r "$OODT_HOME"/bin/env.sh ]; then
+  . "$OODT_HOME"/bin/env.sh
+fi
+
+# Only set FILEMGR_HOME if not already set
+if [ -z "$FILEMGR_HOME" ]; then
+  FILEMGR_HOME="$OODT_HOME"/filemgr
+  export FILEMGR_HOME
+fi
+
+if [ -z "$FILEMGR_PID" ]; then
+  FILEMGR_PID="$FILEMGR_HOME"/run/cas.filemgr.pid
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$JRE_HOME" ] && JRE_HOME=`cygpath --unix "$JRE_HOME"`
+  [ -n "$OODT_HOME" ] && OODT_HOME=`cygpath --unix "$OODT_HOME"`
+  [ -n "$OODT_BASE" ] && OODT_BASE=`cygpath --unix "$OODT_BASE"`
+  [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# Move to bin directory in case this is called from some other directory.
+# This is to keep relative paths correct.
+cd "$FILEMGR_HOME"/bin
+
+"$_RUNJAVA" $JAVA_OPTS $OODT_OPTS \
+  -Djava.endorsed.dirs=../lib \
+  org.apache.oodt.cas.filemgr.tools.QueryTool "$@"
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/etc/filemgr.fm-solr-catalog.properties b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/etc/filemgr.fm-solr-catalog.properties
new file mode 100644
index 0000000..543ea34
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/etc/filemgr.fm-solr-catalog.properties
@@ -0,0 +1,113 @@
+# 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.
+
+# Configuration properties for the File Manager
+
+# repository factory
+filemgr.repository.factory=org.apache.oodt.cas.filemgr.repository.XMLRepositoryManagerFactory
+
+# Solr catalog factory
+filemgr.catalog.factory=org.apache.oodt.cas.filemgr.catalog.solr.SolrCatalogFactory
+org.apache.oodt.cas.filemgr.catalog.solr.url=http://localhost:8080/solr/oodt-fm
+
+# data transfer factory
+filemgr.datatransfer.factory=org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory
+
+# validation layer factory
+filemgr.validationLayer.factory=org.apache.oodt.cas.filemgr.validation.XMLValidationLayerFactory
+
+# xml rpc client configuration
+org.apache.oodt.cas.filemgr.system.xmlrpc.connectionTimeout.minutes=20
+org.apache.oodt.cas.filemgr.system.xmlrpc.requestTimeout.minutes=60
+#org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retries=0
+#org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retry.interval.seconds=3
+
+# mapped data source catalog configuration
+#org.apache.oodt.cas.filemgr.catalog.mappeddatasource.mapFile=/path/to/ops.catalog.typemap.properties
+
+# lucene catalog configuration
+org.apache.oodt.cas.filemgr.catalog.lucene.idxPath=[OODT_HOME]/data/catalog
+org.apache.oodt.cas.filemgr.catalog.lucene.pageSize=20
+org.apache.oodt.cas.filemgr.catalog.lucene.commitLockTimeout.seconds=60
+org.apache.oodt.cas.filemgr.catalog.lucene.writeLockTimeout.seconds=60
+org.apache.oodt.cas.filemgr.catalog.lucene.mergeFactor=20
+
+# XML repository manager configuration
+org.apache.oodt.cas.filemgr.repositorymgr.dirs=file:[FILEMGR_HOME]/policy/oodt
+
+# XML validation layer configuration
+org.apache.oodt.cas.filemgr.validation.dirs=file:[FILEMGR_HOME]/policy/oodt
+
+# remote data transfer configuration
+org.apache.oodt.cas.filemgr.datatransfer.remote.chunkSize=1024
+
+# location of Mime-Type repository
+org.apache.oodt.cas.filemgr.mime.type.repository=[FILEMGR_HOME]/etc/mime-types.xml
+
+
+############ data source configuration ##################################
+#
+# These 3 blocks of config properties can be used to setup a catalog,
+# repository manager, and validation layer based on a RDBMS such as
+# Oracle, MySQL, PostgreSQL, or any others that support a jdbc connection.
+# Just un-comment the following blocks of properties and configure as
+# needed.
+#
+#########################################################################
+
+# datasource catalog config
+#org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.url=some_jdbc_url
+#org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.user=user
+#org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.pass=pass
+#org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.driver=driver.class.name
+#org.apache.oodt.cas.filemgr.catalog.datasource.quoteFields=false
+#org.apache.oodt.cas.filemgr.catalog.datasource.pageSize=20
+#org.apache.oodt.cas.filemgr.catalog.datasource.cacheUpdateMinutes=5
+
+# data source repository manager configuration
+#org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.url=some_jdbc_url
+#org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.user=user
+#org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.pass=pass
+#org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.driver=driver.class.name
+
+# data source validation layer configuration
+#org.apache.oodt.cas.filemgr.validation.datasource.jdbc.url=some_jdbc_url
+#org.apache.oodt.cas.filemgr.validation.datasource.jdbc.user=user
+#org.apache.oodt.cas.filemgr.validation.datasource.jdbc.pass=pass
+#org.apache.oodt.cas.filemgr.validation.datasource.jdbc.driver=driver.class.name
+#org.apache.oodt.cas.filemgr.validation.datasource.quoteFields=false
+
+
+# tells the file manager system layer to include product instance metadata
+# NOTE: here are the expected field mappings
+#
+# product.getProductId() -> ProductId
+# product.getProductName() -> ProductName
+# product.getProductStructure() -> ProductStructure
+# product.getTransferStatus() -> ProductTransferStatus
+# product.getRootRef() -> ProductRootReference
+
+# for the references returned by product.getProductReferences() the following
+# metadata fields will be added (order will be maintained, such that data store
+# ref at index 0 will map to orig ref at index 0, etc.)
+#
+# ProductDataStoreReferences (list of all data store references:
+# note already translated into path, not URI)
+# ProductOrigReferences (list of all orig references:
+# note already translated into path, not URI)
+# ProductMimeType (list of all references' mime-types)
+# ProductFileSize (list of all references' file sizes)
+
+org.apache.oodt.cas.filemgr.metadata.expandProduct=false
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/etc/filemgr.properties b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/etc/filemgr.properties
new file mode 100644
index 0000000..acbfe57
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/etc/filemgr.properties
@@ -0,0 +1,112 @@
+# 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.
+
+# Configuration properties for the File Manager
+
+# repository factory
+filemgr.repository.factory=org.apache.oodt.cas.filemgr.repository.XMLRepositoryManagerFactory
+
+# Lucene catalog factory
+filemgr.catalog.factory=org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory
+
+# data transfer factory
+filemgr.datatransfer.factory=org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory
+
+# validation layer factory
+filemgr.validationLayer.factory=org.apache.oodt.cas.filemgr.validation.XMLValidationLayerFactory
+
+# xml rpc client configuration
+org.apache.oodt.cas.filemgr.system.xmlrpc.connectionTimeout.minutes=20
+org.apache.oodt.cas.filemgr.system.xmlrpc.requestTimeout.minutes=60
+#org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retries=0
+#org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retry.interval.seconds=3
+
+# mapped data source catalog configuration
+#org.apache.oodt.cas.filemgr.catalog.mappeddatasource.mapFile=/path/to/ops.catalog.typemap.properties
+
+# lucene catalog configuration
+org.apache.oodt.cas.filemgr.catalog.lucene.idxPath=[OODT_HOME]/data/catalog
+org.apache.oodt.cas.filemgr.catalog.lucene.pageSize=20
+org.apache.oodt.cas.filemgr.catalog.lucene.commitLockTimeout.seconds=60
+org.apache.oodt.cas.filemgr.catalog.lucene.writeLockTimeout.seconds=60
+org.apache.oodt.cas.filemgr.catalog.lucene.mergeFactor=20
+
+# XML repository manager configuration
+org.apache.oodt.cas.filemgr.repositorymgr.dirs=file:[FILEMGR_HOME]/policy/oodt
+
+# XML validation layer configuration
+org.apache.oodt.cas.filemgr.validation.dirs=file:[FILEMGR_HOME]/policy/oodt
+
+# remote data transfer configuration
+org.apache.oodt.cas.filemgr.datatransfer.remote.chunkSize=1024
+
+# location of Mime-Type repository
+org.apache.oodt.cas.filemgr.mime.type.repository=[FILEMGR_HOME]/etc/mime-types.xml
+
+
+############ data source configuration ##################################
+#
+# These 3 blocks of config properties can be used to setup a catalog,
+# repository manager, and validation layer based on a RDBMS such as
+# Oracle, MySQL, PostgreSQL, or any others that support a jdbc connection.
+# Just un-comment the following blocks of properties and configure as
+# needed.
+#
+#########################################################################
+
+# datasource catalog config
+#org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.url=some_jdbc_url
+#org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.user=user
+#org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.pass=pass
+#org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.driver=driver.class.name
+#org.apache.oodt.cas.filemgr.catalog.datasource.quoteFields=false
+#org.apache.oodt.cas.filemgr.catalog.datasource.pageSize=20
+#org.apache.oodt.cas.filemgr.catalog.datasource.cacheUpdateMinutes=5
+
+# data source repository manager configuration
+#org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.url=some_jdbc_url
+#org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.user=user
+#org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.pass=pass
+#org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.driver=driver.class.name
+
+# data source validation layer configuration
+#org.apache.oodt.cas.filemgr.validation.datasource.jdbc.url=some_jdbc_url
+#org.apache.oodt.cas.filemgr.validation.datasource.jdbc.user=user
+#org.apache.oodt.cas.filemgr.validation.datasource.jdbc.pass=pass
+#org.apache.oodt.cas.filemgr.validation.datasource.jdbc.driver=driver.class.name
+#org.apache.oodt.cas.filemgr.validation.datasource.quoteFields=false
+
+
+# tells the file manager system layer to include product instance metadata
+# NOTE: here are the expected field mappings
+#
+# product.getProductId() -> ProductId
+# product.getProductName() -> ProductName
+# product.getProductStructure() -> ProductStructure
+# product.getTransferStatus() -> ProductTransferStatus
+# product.getRootRef() -> ProductRootReference
+
+# for the references returned by product.getProductReferences() the following
+# metadata fields will be added (order will be maintained, such that data store
+# ref at index 0 will map to orig ref at index 0, etc.)
+#
+# ProductDataStoreReferences (list of all data store references:
+# note already translated into path, not URI)
+# ProductOrigReferences (list of all orig references:
+# note already translated into path, not URI)
+# ProductMimeType (list of all references' mime-types)
+# ProductFileSize (list of all references' file sizes)
+
+org.apache.oodt.cas.filemgr.metadata.expandProduct=false
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/etc/logging.properties b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/etc/logging.properties
new file mode 100644
index 0000000..4b1dcc1
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/etc/logging.properties
@@ -0,0 +1,64 @@
+# 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.
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.FileHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = ../logs/cas_filemgr%g.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 5
+java.util.logging.FileHandler.append = true
+java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging level for the subsystems
+
+# catalog subsystem
+org.apache.oodt.cas.filemgr.catalog.level = INFO
+
+# repository subsystem
+org.apache.oodt.cas.filemgr.repository.level = FINE
+
+# system subsystem
+org.apache.oodt.cas.filemgr.system.level = INFO
+
+# versioning subsystem
+org.apache.oodt.cas.filemgr.versioning.level = INFO
+
+# data transfer subsystem
+org.apache.oodt.cas.filemgr.datatransfer.level = FINE
+
+# util
+org.apache.oodt.cas.filemgr.util.level = INFO
+
+# validation
+org.apache.oodt.cas.filemgr.validation.level = INFO
+
+# control the underlying commons-httpclient transport layer for xmlrpc
+org.apache.commons.httpclient.level = INFO
+httpclient.wire.header.level = INFO
+httpclient.wire.level = INFO
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/etc/mime-types.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/etc/mime-types.xml
new file mode 100644
index 0000000..6b678be
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/etc/mime-types.xml
@@ -0,0 +1,4119 @@
+<?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.
+-->
+<!--
+  Description: This xml file defines the valid mime types used by Tika.
+  The mime type data within this file is based on information from various
+  sources like Apache Nutch, Apache HTTP Server, the file(1) command, etc.
+-->
+<mime-info>
+
+  <mime-type type="application/activemessage"/>
+  <mime-type type="application/andrew-inset">
+    <glob pattern="*.ez"/>
+  </mime-type>
+  <mime-type type="application/applefile"/>
+  <mime-type type="application/applixware">
+    <glob pattern="*.aw"/>
+  </mime-type>
+
+  <mime-type type="application/atom+xml">
+    <root-XML localName="feed" namespaceURI="http://purl.org/atom/ns#"/>
+    <glob pattern="*.atom"/>
+  </mime-type>
+
+  <mime-type type="application/atomcat+xml">
+    <glob pattern="*.atomcat"/>
+  </mime-type>
+  <mime-type type="application/atomicmail"/>
+  <mime-type type="application/atomsvc+xml">
+    <glob pattern="*.atomsvc"/>
+  </mime-type>
+  <mime-type type="application/auth-policy+xml"/>
+  <mime-type type="application/batch-smtp"/>
+  <mime-type type="application/beep+xml"/>
+  <mime-type type="application/cals-1840"/>
+  <mime-type type="application/ccxml+xml">
+    <glob pattern="*.ccxml"/>
+  </mime-type>
+  <mime-type type="application/cea-2018+xml"/>
+  <mime-type type="application/cellml+xml"/>
+  <mime-type type="application/cnrp+xml"/>
+  <mime-type type="application/commonground"/>
+  <mime-type type="application/conference-info+xml"/>
+  <mime-type type="application/cpl+xml"/>
+  <mime-type type="application/csta+xml"/>
+  <mime-type type="application/cstadata+xml"/>
+  <mime-type type="application/cu-seeme">
+    <glob pattern="*.cu"/>
+  </mime-type>
+  <mime-type type="application/cybercash"/>
+  <mime-type type="application/davmount+xml">
+    <glob pattern="*.davmount"/>
+  </mime-type>
+  <mime-type type="application/dca-rft"/>
+  <mime-type type="application/dec-dx"/>
+  <mime-type type="application/dialog-info+xml"/>
+  <mime-type type="application/dicom"/>
+  <mime-type type="application/dns"/>
+  <mime-type type="application/dvcs"/>
+  <mime-type type="application/ecmascript">
+    <glob pattern="*.ecma"/>
+  </mime-type>
+  <mime-type type="application/edi-consent"/>
+  <mime-type type="application/edi-x12"/>
+  <mime-type type="application/edifact"/>
+  <mime-type type="application/emma+xml">
+    <glob pattern="*.emma"/>
+  </mime-type>
+  <mime-type type="application/epp+xml"/>
+
+  <mime-type type="application/epub+zip">
+    <acronym>EPUB</acronym>
+    <_comment>Electronic Publication</_comment>
+    <magic priority="50">
+      <match value="PK\003\004" type="string" offset="0">
+        <match value="mimetypeapplication/epub+zip" type="string" offset="30"/>
+      </match>
+    </magic>
+    <glob pattern="*.epub"/>
+  </mime-type>
+
+  <mime-type type="application/eshop"/>
+  <mime-type type="application/example"/>
+  <mime-type type="application/fastinfoset"/>
+  <mime-type type="application/fastsoap"/>
+  <mime-type type="application/fits"/>
+  <mime-type type="application/font-tdpfr">
+    <glob pattern="*.pfr"/>
+  </mime-type>
+  <mime-type type="application/h224"/>
+  <mime-type type="application/http"/>
+  <mime-type type="application/hyperstudio">
+    <glob pattern="*.stk"/>
+  </mime-type>
+  <mime-type type="application/ibe-key-request+xml"/>
+  <mime-type type="application/ibe-pkg-reply+xml"/>
+  <mime-type type="application/ibe-pp-data"/>
+  <mime-type type="application/iges"/>
+  <mime-type type="application/im-iscomposing+xml"/>
+  <mime-type type="application/index"/>
+  <mime-type type="application/index.cmd"/>
+  <mime-type type="application/index.obj"/>
+  <mime-type type="application/index.response"/>
+  <mime-type type="application/index.vnd"/>
+  <mime-type type="application/iotp"/>
+  <mime-type type="application/ipp"/>
+  <mime-type type="application/isup"/>
+
+  <mime-type type="application/java-archive">
+    <sub-class-of type="application/zip"/>
+    <glob pattern="*.jar"/>
+  </mime-type>
+
+  <mime-type type="application/java-serialized-object">
+    <glob pattern="*.ser"/>
+  </mime-type>
+
+  <mime-type type="application/javascript">
+    <sub-class-of type="text/plain"/>
+    <glob pattern="*.js"/>
+  </mime-type>
+
+  <mime-type type="application/json">
+    <sub-class-of type="application/javascript"/>
+    <glob pattern="*.json"/>
+  </mime-type>
+
+  <mime-type type="application/java-vm">
+    <magic priority="40">
+      <match value="0xcafebabe" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.class"/>
+  </mime-type>
+
+  <mime-type type="application/kpml-request+xml"/>
+  <mime-type type="application/kpml-response+xml"/>
+  <mime-type type="application/lost+xml">
+    <glob pattern="*.lostxml"/>
+  </mime-type>
+
+  <mime-type type="application/mac-binhex40">
+    <alias type="application/mac-binhex"/>
+    <alias type="application/binhex"/>
+    <magic priority="50">
+      <match value="must\ be\ converted\ with\ BinHex" type="string" offset="11"/>
+    </magic>
+    <glob pattern="*.hqx"/>
+  </mime-type>
+
+  <mime-type type="application/mac-compactpro">
+    <glob pattern="*.cpt"/>
+  </mime-type>
+
+  <mime-type type="application/macwriteii"/>
+  <mime-type type="application/marc">
+    <glob pattern="*.mrc"/>
+  </mime-type>
+  <mime-type type="application/mathematica">
+    <glob pattern="*.ma"/>
+    <glob pattern="*.nb"/>
+    <glob pattern="*.mb"/>
+  </mime-type>
+  <mime-type type="application/mathml+xml">
+    <glob pattern="*.mathml"/>
+  </mime-type>
+  <mime-type type="application/mbms-associated-procedure-description+xml"/>
+  <mime-type type="application/mbms-deregister+xml"/>
+  <mime-type type="application/mbms-envelope+xml"/>
+  <mime-type type="application/mbms-msk+xml"/>
+  <mime-type type="application/mbms-msk-response+xml"/>
+  <mime-type type="application/mbms-protection-description+xml"/>
+  <mime-type type="application/mbms-reception-report+xml"/>
+  <mime-type type="application/mbms-register+xml"/>
+  <mime-type type="application/mbms-register-response+xml"/>
+  <mime-type type="application/mbms-user-service-description+xml"/>
+  <mime-type type="application/mbox">
+    <sub-class-of type="text/plain"/>
+    <glob pattern="*.mbox"/>
+  </mime-type>
+  <mime-type type="application/media_control+xml"/>
+  <mime-type type="application/mediaservercontrol+xml">
+    <glob pattern="*.mscml"/>
+  </mime-type>
+  <mime-type type="application/mikey"/>
+  <mime-type type="application/moss-keys"/>
+  <mime-type type="application/moss-signature"/>
+  <mime-type type="application/mosskey-data"/>
+  <mime-type type="application/mosskey-request"/>
+  <mime-type type="application/mp4">
+    <glob pattern="*.mp4s"/>
+  </mime-type>
+  <mime-type type="application/mpeg4-generic"/>
+  <mime-type type="application/mpeg4-iod"/>
+  <mime-type type="application/mpeg4-iod-xmt"/>
+
+  <!-- http://www.iana.org/assignments/media-types/application/msword -->
+  <mime-type type="application/msword">
+    <!-- Use org.apache.tika.detect.ContainerAwareDetector for more reliable detection of OLE2 documents -->
+    <alias type="application/vnd.ms-word"/>
+    <_comment>Microsoft Word Document</_comment>
+    <magic priority="50">
+      <match value="Microsoft\ Word\ 6.0\ Document" type="string" offset="2080"/>
+      <match value="Documento\ Microsoft\ Word\ 6" type="string" offset="2080"/>
+      <match value="MSWordDoc" type="string" offset="2112"/>
+      <match value="0x31be0000" type="big32" offset="0"/>
+      <match value="PO^Q`" type="string" offset="0"/>
+      <match value="\376\067\0\043" type="string" offset="0"/>
+      <match value="\333\245-\0\0\0" type="string" offset="0"/>
+      <match value="\354\245\301" type="string" offset="512"/>
+      <match value="\320\317\021\340\241\261\032\341" type="string" offset="0"/>
+      <match value="\224\246\056" type="string" offset="0"/>
+      <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+         <match value="W\x00o\x00r\x00d\x00D\x00o\x00c\x00u\x00m\x00e\x00n\x00t" type="string" offset="1152:4096" />
+      </match>
+    </magic>
+    <glob pattern="*.doc"/>
+    <glob pattern="*.dot"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/mxf">
+    <glob pattern="*.mxf"/>
+  </mime-type>
+  <mime-type type="application/nasdata"/>
+  <mime-type type="application/news-checkgroups"/>
+  <mime-type type="application/news-groupinfo"/>
+  <mime-type type="application/news-transmission"/>
+  <mime-type type="application/nss"/>
+  <mime-type type="application/ocsp-request"/>
+  <mime-type type="application/ocsp-response"/>
+
+  <mime-type type="application/octet-stream">
+    <magic priority="50">
+      <match value="#\ This\ is\ a\ shell\ archive" type="string" offset="10"/>
+      <match value="\037\036" type="string" offset="0"/>
+      <match value="017437" type="host16" offset="0"/>
+      <match value="0x1fff" type="host16" offset="0"/>
+      <match value="\377\037" type="string" offset="0"/>
+      <match value="0145405" type="host16" offset="0"/>
+    </magic>
+    <glob pattern="*.bin"/>
+    <glob pattern="*.dms"/>
+    <glob pattern="*.lha"/>
+    <glob pattern="*.lrf"/>
+    <glob pattern="*.lzh"/>
+    <glob pattern="*.so"/>
+    <glob pattern="*.iso"/>
+    <glob pattern="*.dmg"/>
+    <glob pattern="*.dist"/>
+    <glob pattern="*.distz"/>
+    <glob pattern="*.pkg"/>
+    <glob pattern="*.bpk"/>
+    <glob pattern="*.dump"/>
+    <glob pattern="*.elc"/>
+    <glob pattern="*.deploy"/>
+  </mime-type>
+
+  <mime-type type="application/oda">
+    <glob pattern="*.oda"/>
+  </mime-type>
+  <mime-type type="application/oebps-package+xml">
+    <glob pattern="*.opf"/>
+  </mime-type>
+
+  <mime-type type="application/ogg">
+    <alias type="application/x-ogg"/>
+    <magic priority="50">
+      <match value="OggS" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.ogx"/>
+  </mime-type>
+
+  <mime-type type="application/onenote">
+    <glob pattern="*.onetoc"/>
+    <glob pattern="*.onetoc2"/>
+    <glob pattern="*.onetmp"/>
+    <glob pattern="*.onepkg"/>
+  </mime-type>
+  <mime-type type="application/parityfec"/>
+  <mime-type type="application/patch-ops-error+xml">
+    <glob pattern="*.xer"/>
+  </mime-type>
+
+  <mime-type type="application/pdf">
+    <alias type="application/x-pdf"/>
+    <acronym>PDF</acronym>
+    <_comment>Portable Document Format</_comment>
+    <magic priority="50">
+      <match value="%PDF-" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.pdf"/>
+  </mime-type>
+
+  <mime-type type="application/pgp-encrypted">
+    <glob pattern="*.pgp"/>
+  </mime-type>
+  <mime-type type="application/pgp-keys"/>
+  <mime-type type="application/pgp-signature">
+    <glob pattern="*.asc"/>
+    <glob pattern="*.sig"/>
+  </mime-type>
+  <mime-type type="application/pics-rules">
+    <glob pattern="*.prf"/>
+  </mime-type>
+  <mime-type type="application/pidf+xml"/>
+  <mime-type type="application/pidf-diff+xml"/>
+  <mime-type type="application/pkcs10">
+    <glob pattern="*.p10"/>
+  </mime-type>
+  <mime-type type="application/pkcs7-mime">
+    <glob pattern="*.p7m"/>
+    <glob pattern="*.p7c"/>
+  </mime-type>
+  <mime-type type="application/pkcs7-signature">
+    <glob pattern="*.p7s"/>
+  </mime-type>
+  <mime-type type="application/pkix-cert">
+    <glob pattern="*.cer"/>
+  </mime-type>
+  <mime-type type="application/pkix-crl">
+    <glob pattern="*.crl"/>
+  </mime-type>
+  <mime-type type="application/pkix-pkipath">
+    <glob pattern="*.pkipath"/>
+  </mime-type>
+  <mime-type type="application/pkixcmp">
+    <glob pattern="*.pki"/>
+  </mime-type>
+  <mime-type type="application/pls+xml">
+    <glob pattern="*.pls"/>
+  </mime-type>
+  <mime-type type="application/poc-settings+xml"/>
+
+  <mime-type type="application/postscript">
+    <_comment>PostScript</_comment>
+    <magic priority="50">
+      <match value="%!" type="string" offset="0" />
+      <match value="\004%!" type="string" offset="0" />
+      <!-- Windows format EPS -->
+      <match value="0xc5d0d3c6" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.ai"/>
+    <glob pattern="*.ps"/>
+    <glob pattern="*.eps"/>
+    <glob pattern="*.epsf"/>
+    <glob pattern="*.epsi"/>
+  </mime-type>
+
+  <mime-type type="application/prs.alvestrand.titrax-sheet"/>
+  <mime-type type="application/prs.cww">
+    <glob pattern="*.cww"/>
+  </mime-type>
+  <mime-type type="application/prs.nprend"/>
+  <mime-type type="application/prs.plucker"/>
+  <mime-type type="application/qsig"/>
+
+  <mime-type type="application/rdf+xml">
+    <root-XML localName="RDF"/>
+    <root-XML localName="RDF" namespaceURI="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
+    <sub-class-of type="application/xml"/>
+    <acronym>RDF/XML</acronym>
+    <_comment>XML syntax for RDF graphs</_comment>
+    <glob pattern="*.rdf"/>
+    <glob pattern="*.owl"/>
+    <glob pattern="^rdf$" isregex="true"/>
+    <glob pattern="^owl$" isregex="true"/>
+  </mime-type>
+
+  <mime-type type="application/reginfo+xml">
+    <glob pattern="*.rif"/>
+  </mime-type>
+  <mime-type type="application/relax-ng-compact-syntax">
+    <sub-class-of type="text/plain"/>
+    <glob pattern="*.rnc"/>
+  </mime-type>
+  <mime-type type="application/remote-printing"/>
+  <mime-type type="application/resource-lists+xml">
+    <glob pattern="*.rl"/>
+  </mime-type>
+  <mime-type type="application/resource-lists-diff+xml">
+    <glob pattern="*.rld"/>
+  </mime-type>
+  <mime-type type="application/riscos"/>
+  <mime-type type="application/rlmi+xml"/>
+  <mime-type type="application/rls-services+xml">
+    <glob pattern="*.rs"/>
+  </mime-type>
+  <mime-type type="application/rsd+xml">
+    <glob pattern="*.rsd"/>
+  </mime-type>
+
+  <mime-type type="application/rss+xml">
+    <alias type="text/rss"/>
+    <root-XML localName="rss"/>
+    <root-XML namespaceURI="http://purl.org/rss/1.0/"/>
+    <glob pattern="*.rss"/>
+  </mime-type>
+
+  <mime-type type="application/rtf">
+    <alias type="text/rtf"/>
+    <magic priority="50">
+      <match value="{\\rtf" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.rtf"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="application/rtx"/>
+  <mime-type type="application/samlassertion+xml"/>
+  <mime-type type="application/samlmetadata+xml"/>
+  <mime-type type="application/sbml+xml">
+    <glob pattern="*.sbml"/>
+  </mime-type>
+  <mime-type type="application/scvp-cv-request">
+    <glob pattern="*.scq"/>
+  </mime-type>
+  <mime-type type="application/scvp-cv-response">
+    <glob pattern="*.scs"/>
+  </mime-type>
+  <mime-type type="application/scvp-vp-request">
+    <glob pattern="*.spq"/>
+  </mime-type>
+  <mime-type type="application/scvp-vp-response">
+    <glob pattern="*.spp"/>
+  </mime-type>
+  <mime-type type="application/sdp">
+    <glob pattern="*.sdp"/>
+  </mime-type>
+  <mime-type type="application/set-payment"/>
+  <mime-type type="application/set-payment-initiation">
+    <glob pattern="*.setpay"/>
+  </mime-type>
+  <mime-type type="application/set-registration"/>
+  <mime-type type="application/set-registration-initiation">
+    <glob pattern="*.setreg"/>
+  </mime-type>
+  <mime-type type="application/sgml"/>
+  <mime-type type="application/sgml-open-catalog"/>
+  <mime-type type="application/shf+xml">
+    <glob pattern="*.shf"/>
+  </mime-type>
+  <mime-type type="application/sieve"/>
+  <mime-type type="application/simple-filter+xml"/>
+  <mime-type type="application/simple-message-summary"/>
+  <mime-type type="application/simplesymbolcontainer"/>
+  <mime-type type="application/slate"/>
+  <mime-type type="application/smil"/>
+  <mime-type type="application/smil+xml">
+    <glob pattern="*.smi"/>
+    <glob pattern="*.smil"/>
+  </mime-type>
+  <mime-type type="application/soap+fastinfoset"/>
+  <mime-type type="application/soap+xml"/>
+  <mime-type type="application/sparql-query">
+    <glob pattern="*.rq"/>
+  </mime-type>
+  <mime-type type="application/sparql-results+xml">
+    <glob pattern="*.srx"/>
+  </mime-type>
+  <mime-type type="application/spirits-event+xml"/>
+  <mime-type type="application/srgs">
+    <glob pattern="*.gram"/>
+  </mime-type>
+  <mime-type type="application/srgs+xml">
+    <glob pattern="*.grxml"/>
+  </mime-type>
+  <mime-type type="application/ssml+xml">
+    <glob pattern="*.ssml"/>
+  </mime-type>
+  <mime-type type="application/timestamp-query"/>
+  <mime-type type="application/timestamp-reply"/>
+  <mime-type type="application/tve-trigger"/>
+  <mime-type type="application/ulpfec"/>
+  <mime-type type="application/vemmi"/>
+  <mime-type type="application/vividence.scriptfile"/>
+  <mime-type type="application/vnd.3gpp.bsf+xml"/>
+  <mime-type type="application/vnd.3gpp.pic-bw-large">
+    <glob pattern="*.plb"/>
+  </mime-type>
+  <mime-type type="application/vnd.3gpp.pic-bw-small">
+    <glob pattern="*.psb"/>
+  </mime-type>
+  <mime-type type="application/vnd.3gpp.pic-bw-var">
+    <glob pattern="*.pvb"/>
+  </mime-type>
+  <mime-type type="application/vnd.3gpp.sms"/>
+  <mime-type type="application/vnd.3gpp2.bcmcsinfo+xml"/>
+  <mime-type type="application/vnd.3gpp2.sms"/>
+  <mime-type type="application/vnd.3gpp2.tcap">
+    <glob pattern="*.tcap"/>
+  </mime-type>
+  <mime-type type="application/vnd.3m.post-it-notes">
+    <glob pattern="*.pwn"/>
+  </mime-type>
+  <mime-type type="application/vnd.accpac.simply.aso">
+    <glob pattern="*.aso"/>
+  </mime-type>
+  <mime-type type="application/vnd.accpac.simply.imp">
+    <glob pattern="*.imp"/>
+  </mime-type>
+  <mime-type type="application/vnd.acucobol">
+    <glob pattern="*.acu"/>
+  </mime-type>
+  <mime-type type="application/vnd.acucorp">
+    <glob pattern="*.atc"/>
+    <glob pattern="*.acutc"/>
+  </mime-type>
+  <mime-type type="application/vnd.adobe.air-application-installer-package+zip">
+    <glob pattern="*.air"/>
+  </mime-type>
+  <mime-type type="application/vnd.adobe.xdp+xml">
+    <glob pattern="*.xdp"/>
+  </mime-type>
+  <mime-type type="application/vnd.adobe.xfdf">
+    <glob pattern="*.xfdf"/>
+  </mime-type>
+  <mime-type type="application/vnd.aether.imp"/>
+  <mime-type type="application/vnd.airzip.filesecure.azf">
+    <glob pattern="*.azf"/>
+  </mime-type>
+  <mime-type type="application/vnd.airzip.filesecure.azs">
+    <glob pattern="*.azs"/>
+  </mime-type>
+  <mime-type type="application/vnd.amazon.ebook">
+    <glob pattern="*.azw"/>
+  </mime-type>
+  <mime-type type="application/vnd.americandynamics.acc">
+    <glob pattern="*.acc"/>
+  </mime-type>
+  <mime-type type="application/vnd.amiga.ami">
+    <glob pattern="*.ami"/>
+  </mime-type>
+  <mime-type type="application/vnd.android.package-archive">
+    <glob pattern="*.apk"/>
+  </mime-type>
+  <mime-type type="application/vnd.anser-web-certificate-issue-initiation">
+    <glob pattern="*.cii"/>
+  </mime-type>
+  <mime-type type="application/vnd.anser-web-funds-transfer-initiation">
+    <glob pattern="*.fti"/>
+  </mime-type>
+  <mime-type type="application/vnd.antix.game-component">
+    <glob pattern="*.atx"/>
+  </mime-type>
+  <mime-type type="application/vnd.apple.installer+xml">
+    <glob pattern="*.mpkg"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.apple.iwork">
+    <sub-class-of type="application/zip"/>
+    <glob pattern="*.key"/>
+    <glob pattern="*.pages"/>
+    <glob pattern="*.numbers"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.apple.keynote">
+    <root-XML localName="presentation" namespaceURI="http://developer.apple.com/namespaces/keynote2" />
+  </mime-type>
+  <mime-type type="application/vnd.apple.pages">
+    <root-XML localName="document" namespaceURI="http://developer.apple.com/namespaces/sl" />
+  </mime-type>
+  <mime-type type="application/vnd.apple.numbers">
+    <root-XML localName="document" namespaceURI="http://developer.apple.com/namespaces/ls" />
+  </mime-type>
+  <mime-type type="application/vnd.arastra.swi">
+    <glob pattern="*.swi"/>
+  </mime-type>
+  <mime-type type="application/vnd.audiograph">
+    <glob pattern="*.aep"/>
+  </mime-type>
+  <mime-type type="application/vnd.autopackage"/>
+  <mime-type type="application/vnd.avistar+xml"/>
+  <mime-type type="application/vnd.blueice.multipass">
+    <glob pattern="*.mpm"/>
+  </mime-type>
+  <mime-type type="application/vnd.bluetooth.ep.oob"/>
+  <mime-type type="application/vnd.bmi">
+    <glob pattern="*.bmi"/>
+  </mime-type>
+  <mime-type type="application/vnd.businessobjects">
+    <glob pattern="*.rep"/>
+  </mime-type>
+  <mime-type type="application/vnd.cab-jscript"/>
+  <mime-type type="application/vnd.canon-cpdl"/>
+  <mime-type type="application/vnd.canon-lips"/>
+  <mime-type type="application/vnd.cendio.thinlinc.clientconf"/>
+  <mime-type type="application/vnd.chemdraw+xml">
+    <glob pattern="*.cdxml"/>
+  </mime-type>
+  <mime-type type="application/vnd.chipnuts.karaoke-mmd">
+    <glob pattern="*.mmd"/>
+  </mime-type>
+  <mime-type type="application/vnd.cinderella">
+    <glob pattern="*.cdy"/>
+  </mime-type>
+  <mime-type type="application/vnd.cirpack.isdn-ext"/>
+  <mime-type type="application/vnd.claymore">
+    <glob pattern="*.cla"/>
+  </mime-type>
+  <mime-type type="application/vnd.clonk.c4group">
+    <glob pattern="*.c4g"/>
+    <glob pattern="*.c4d"/>
+    <glob pattern="*.c4f"/>
+    <glob pattern="*.c4p"/>
+    <glob pattern="*.c4u"/>
+  </mime-type>
+  <mime-type type="application/vnd.commerce-battelle"/>
+  <mime-type type="application/vnd.commonspace">
+    <glob pattern="*.csp"/>
+  </mime-type>
+  <mime-type type="application/vnd.contact.cmsg">
+    <glob pattern="*.cdbcmsg"/>
+  </mime-type>
+  <mime-type type="application/vnd.cosmocaller">
+    <glob pattern="*.cmc"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker">
+    <glob pattern="*.clkx"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker.keyboard">
+    <glob pattern="*.clkk"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker.palette">
+    <glob pattern="*.clkp"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker.template">
+    <glob pattern="*.clkt"/>
+  </mime-type>
+  <mime-type type="application/vnd.crick.clicker.wordbank">
+    <glob pattern="*.clkw"/>
+  </mime-type>
+  <mime-type type="application/vnd.criticaltools.wbs+xml">
+    <glob pattern="*.wbs"/>
+  </mime-type>
+  <mime-type type="application/vnd.ctc-posml">
+    <glob pattern="*.pml"/>
+  </mime-type>
+  <mime-type type="application/vnd.ctct.ws+xml"/>
+  <mime-type type="application/vnd.cups-pdf"/>
+  <mime-type type="application/vnd.cups-postscript"/>
+  <mime-type type="application/vnd.cups-ppd">
+    <glob pattern="*.ppd"/>
+  </mime-type>
+  <mime-type type="application/vnd.cups-raster"/>
+  <mime-type type="application/vnd.cups-raw"/>
+  <mime-type type="application/vnd.curl.car">
+    <glob pattern="*.car"/>
+  </mime-type>
+  <mime-type type="application/vnd.curl.pcurl">
+    <glob pattern="*.pcurl"/>
+  </mime-type>
+  <mime-type type="application/vnd.cybank"/>
+  <mime-type type="application/vnd.data-vision.rdz">
+    <glob pattern="*.rdz"/>
+  </mime-type>
+  <mime-type type="application/vnd.denovo.fcselayout-link">
+    <glob pattern="*.fe_launch"/>
+  </mime-type>
+  <mime-type type="application/vnd.dir-bi.plate-dl-nosuffix"/>
+  <mime-type type="application/vnd.dna">
+    <glob pattern="*.dna"/>
+  </mime-type>
+  <mime-type type="application/vnd.dolby.mlp">
+    <glob pattern="*.mlp"/>
+  </mime-type>
+  <mime-type type="application/vnd.dolby.mobile.1"/>
+  <mime-type type="application/vnd.dolby.mobile.2"/>
+  <mime-type type="application/vnd.dpgraph">
+    <glob pattern="*.dpg"/>
+  </mime-type>
+  <mime-type type="application/vnd.dreamfactory">
+    <glob pattern="*.dfac"/>
+  </mime-type>
+  <mime-type type="application/vnd.dvb.esgcontainer"/>
+  <mime-type type="application/vnd.dvb.ipdcdftnotifaccess"/>
+  <mime-type type="application/vnd.dvb.ipdcesgaccess"/>
+  <mime-type type="application/vnd.dvb.ipdcroaming"/>
+  <mime-type type="application/vnd.dvb.iptv.alfec-base"/>
+  <mime-type type="application/vnd.dvb.iptv.alfec-enhancement"/>
+  <mime-type type="application/vnd.dvb.notif-aggregate-root+xml"/>
+  <mime-type type="application/vnd.dvb.notif-container+xml"/>
+  <mime-type type="application/vnd.dvb.notif-generic+xml"/>
+  <mime-type type="application/vnd.dvb.notif-ia-msglist+xml"/>
+  <mime-type type="application/vnd.dvb.notif-ia-registration-request+xml"/>
+  <mime-type type="application/vnd.dvb.notif-ia-registration-response+xml"/>
+  <mime-type type="application/vnd.dvb.notif-init+xml"/>
+  <mime-type type="application/vnd.dxr"/>
+  <mime-type type="application/vnd.dynageo">
+    <glob pattern="*.geo"/>
+  </mime-type>
+  <mime-type type="application/vnd.ecdis-update"/>
+  <mime-type type="application/vnd.ecowin.chart">
+    <glob pattern="*.mag"/>
+  </mime-type>
+  <mime-type type="application/vnd.ecowin.filerequest"/>
+  <mime-type type="application/vnd.ecowin.fileupdate"/>
+  <mime-type type="application/vnd.ecowin.series"/>
+  <mime-type type="application/vnd.ecowin.seriesrequest"/>
+  <mime-type type="application/vnd.ecowin.seriesupdate"/>
+  <mime-type type="application/vnd.emclient.accessrequest+xml"/>
+  <mime-type type="application/vnd.enliven">
+    <glob pattern="*.nml"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.esf">
+    <glob pattern="*.esf"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.msf">
+    <glob pattern="*.msf"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.quickanime">
+    <glob pattern="*.qam"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.salt">
+    <glob pattern="*.slt"/>
+  </mime-type>
+  <mime-type type="application/vnd.epson.ssf">
+    <glob pattern="*.ssf"/>
+  </mime-type>
+  <mime-type type="application/vnd.ericsson.quickcall"/>
+  <mime-type type="application/vnd.eszigno3+xml">
+    <glob pattern="*.es3"/>
+    <glob pattern="*.et3"/>
+  </mime-type>
+  <mime-type type="application/vnd.etsi.aoc+xml"/>
+  <mime-type type="application/vnd.etsi.cug+xml"/>
+  <mime-type type="application/vnd.etsi.iptvcommand+xml"/>
+  <mime-type type="application/vnd.etsi.iptvdiscovery+xml"/>
+  <mime-type type="application/vnd.etsi.iptvprofile+xml"/>
+  <mime-type type="application/vnd.etsi.iptvsad-bc+xml"/>
+  <mime-type type="application/vnd.etsi.iptvsad-cod+xml"/>
+  <mime-type type="application/vnd.etsi.iptvsad-npvr+xml"/>
+  <mime-type type="application/vnd.etsi.iptvueprofile+xml"/>
+  <mime-type type="application/vnd.etsi.mcid+xml"/>
+  <mime-type type="application/vnd.etsi.sci+xml"/>
+  <mime-type type="application/vnd.etsi.simservs+xml"/>
+  <mime-type type="application/vnd.eudora.data"/>
+  <mime-type type="application/vnd.ezpix-album">
+    <glob pattern="*.ez2"/>
+  </mime-type>
+  <mime-type type="application/vnd.ezpix-package">
+    <glob pattern="*.ez3"/>
+  </mime-type>
+  <mime-type type="application/vnd.f-secure.mobile"/>
+  <mime-type type="application/vnd.fdf">
+    <glob pattern="*.fdf"/>
+  </mime-type>
+  <mime-type type="application/vnd.fdsn.mseed">
+    <glob pattern="*.mseed"/>
+  </mime-type>
+  <mime-type type="application/vnd.fdsn.seed">
+    <glob pattern="*.seed"/>
+    <glob pattern="*.dataless"/>
+  </mime-type>
+  <mime-type type="application/vnd.ffsns"/>
+  <mime-type type="application/vnd.fints"/>
+  <mime-type type="application/vnd.flographit">
+    <glob pattern="*.gph"/>
+  </mime-type>
+  <mime-type type="application/vnd.fluxtime.clip">
+    <glob pattern="*.ftc"/>
+  </mime-type>
+  <mime-type type="application/vnd.font-fontforge-sfd"/>
+  <mime-type type="application/vnd.framemaker">
+    <glob pattern="*.fm"/>
+    <glob pattern="*.frame"/>
+    <glob pattern="*.maker"/>
+    <glob pattern="*.book"/>
+  </mime-type>
+  <mime-type type="application/vnd.frogans.fnc">
+    <glob pattern="*.fnc"/>
+  </mime-type>
+  <mime-type type="application/vnd.frogans.ltf">
+    <glob pattern="*.ltf"/>
+  </mime-type>
+  <mime-type type="application/vnd.fsc.weblaunch">
+    <glob pattern="*.fsc"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasys">
+    <glob pattern="*.oas"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasys2">
+    <glob pattern="*.oa2"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasys3">
+    <glob pattern="*.oa3"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasysgp">
+    <glob pattern="*.fg5"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujitsu.oasysprs">
+    <glob pattern="*.bh2"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujixerox.art-ex"/>
+  <mime-type type="application/vnd.fujixerox.art4"/>
+  <mime-type type="application/vnd.fujixerox.hbpl"/>
+  <mime-type type="application/vnd.fujixerox.ddd">
+    <glob pattern="*.ddd"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujixerox.docuworks">
+    <glob pattern="*.xdw"/>
+  </mime-type>
+  <mime-type type="application/vnd.fujixerox.docuworks.binder">
+    <glob pattern="*.xbd"/>
+  </mime-type>
+  <mime-type type="application/vnd.fut-misnet"/>
+  <mime-type type="application/vnd.fuzzysheet">
+    <glob pattern="*.fzs"/>
+  </mime-type>
+  <mime-type type="application/vnd.genomatix.tuxedo">
+    <glob pattern="*.txd"/>
+  </mime-type>
+  <mime-type type="application/vnd.geogebra.file">
+    <glob pattern="*.ggb"/>
+  </mime-type>
+  <mime-type type="application/vnd.geogebra.tool">
+    <glob pattern="*.ggt"/>
+  </mime-type>
+  <mime-type type="application/vnd.geometry-explorer">
+    <glob pattern="*.gex"/>
+    <glob pattern="*.gre"/>
+  </mime-type>
+  <mime-type type="application/vnd.gmx">
+    <glob pattern="*.gmx"/>
+  </mime-type>
+  <mime-type type="application/vnd.google-earth.kml+xml">
+    <glob pattern="*.kml"/>
+  </mime-type>
+  <mime-type type="application/vnd.google-earth.kmz">
+    <glob pattern="*.kmz"/>
+  </mime-type>
+  <mime-type type="application/vnd.grafeq">
+    <glob pattern="*.gqf"/>
+    <glob pattern="*.gqs"/>
+  </mime-type>
+  <mime-type type="application/vnd.gridmp"/>
+  <mime-type type="application/vnd.groove-account">
+    <glob pattern="*.gac"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-help">
+    <glob pattern="*.ghf"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-identity-message">
+    <glob pattern="*.gim"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-injector">
+    <glob pattern="*.grv"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-tool-message">
+    <glob pattern="*.gtm"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-tool-template">
+    <glob pattern="*.tpl"/>
+  </mime-type>
+  <mime-type type="application/vnd.groove-vcard">
+    <glob pattern="*.vcg"/>
+  </mime-type>
+  <mime-type type="application/vnd.handheld-entertainment+xml">
+    <glob pattern="*.zmm"/>
+  </mime-type>
+  <mime-type type="application/vnd.hbci">
+    <glob pattern="*.hbci"/>
+  </mime-type>
+  <mime-type type="application/vnd.hcl-bireports"/>
+  <mime-type type="application/vnd.hhe.lesson-player">
+    <glob pattern="*.les"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-hpgl">
+    <glob pattern="*.hpgl"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-hpid">
+    <glob pattern="*.hpid"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-hps">
+    <glob pattern="*.hps"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-jlyt">
+    <glob pattern="*.jlt"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-pcl">
+    <glob pattern="*.pcl"/>
+  </mime-type>
+  <mime-type type="application/vnd.hp-pclxl">
+    <glob pattern="*.pclxl"/>
+  </mime-type>
+  <mime-type type="application/vnd.httphone"/>
+  <mime-type type="application/vnd.hydrostatix.sof-data">
+    <glob pattern="*.sfd-hdstx"/>
+  </mime-type>
+  <mime-type type="application/vnd.hzn-3d-crossword">
+    <glob pattern="*.x3d"/>
+  </mime-type>
+  <mime-type type="application/vnd.ibm.afplinedata"/>
+  <mime-type type="application/vnd.ibm.electronic-media"/>
+  <mime-type type="application/vnd.ibm.minipay">
+    <glob pattern="*.mpy"/>
+  </mime-type>
+  <mime-type type="application/vnd.ibm.modcap">
+    <glob pattern="*.afp"/>
+    <glob pattern="*.listafp"/>
+    <glob pattern="*.list3820"/>
+  </mime-type>
+  <mime-type type="application/vnd.ibm.rights-management">
+    <glob pattern="*.irm"/>
+  </mime-type>
+  <mime-type type="application/vnd.ibm.secure-container">
+    <glob pattern="*.sc"/>
+  </mime-type>
+  <mime-type type="application/vnd.iccprofile">
+    <glob pattern="*.icc"/>
+    <glob pattern="*.icm"/>
+  </mime-type>
+  <mime-type type="application/vnd.igloader">
+    <glob pattern="*.igl"/>
+  </mime-type>
+  <mime-type type="application/vnd.immervision-ivp">
+    <glob pattern="*.ivp"/>
+  </mime-type>
+  <mime-type type="application/vnd.immervision-ivu">
+    <glob pattern="*.ivu"/>
+  </mime-type>
+  <mime-type type="application/vnd.informedcontrol.rms+xml"/>
+  <mime-type type="application/vnd.informix-visionary"/>
+  <mime-type type="application/vnd.intercon.formnet">
+    <glob pattern="*.xpw"/>
+    <glob pattern="*.xpx"/>
+  </mime-type>
+  <mime-type type="application/vnd.intertrust.digibox"/>
+  <mime-type type="application/vnd.intertrust.nncp"/>
+  <mime-type type="application/vnd.intu.qbo">
+    <glob pattern="*.qbo"/>
+  </mime-type>
+  <mime-type type="application/vnd.intu.qfx">
+    <glob pattern="*.qfx"/>
+  </mime-type>
+  <mime-type type="application/vnd.iptc.g2.conceptitem+xml"/>
+  <mime-type type="application/vnd.iptc.g2.knowledgeitem+xml"/>
+  <mime-type type="application/vnd.iptc.g2.newsitem+xml"/>
+  <mime-type type="application/vnd.iptc.g2.packageitem+xml"/>
+  <mime-type type="application/vnd.ipunplugged.rcprofile">
+    <glob pattern="*.rcprofile"/>
+  </mime-type>
+  <mime-type type="application/vnd.irepository.package+xml">
+    <glob pattern="*.irp"/>
+  </mime-type>
+  <mime-type type="application/vnd.is-xpr">
+    <glob pattern="*.xpr"/>
+  </mime-type>
+  <mime-type type="application/vnd.jam">
+    <glob pattern="*.jam"/>
+  </mime-type>
+  <mime-type type="application/vnd.japannet-directory-service"/>
+  <mime-type type="application/vnd.japannet-jpnstore-wakeup"/>
+  <mime-type type="application/vnd.japannet-payment-wakeup"/>
+  <mime-type type="application/vnd.japannet-registration"/>
+  <mime-type type="application/vnd.japannet-registration-wakeup"/>
+  <mime-type type="application/vnd.japannet-setstore-wakeup"/>
+  <mime-type type="application/vnd.japannet-verification"/>
+  <mime-type type="application/vnd.japannet-verification-wakeup"/>
+  <mime-type type="application/vnd.jcp.javame.midlet-rms">
+    <glob pattern="*.rms"/>
+  </mime-type>
+  <mime-type type="application/vnd.jisp">
+    <glob pattern="*.jisp"/>
+  </mime-type>
+  <mime-type type="application/vnd.joost.joda-archive">
+    <glob pattern="*.joda"/>
+  </mime-type>
+  <mime-type type="application/vnd.kahootz">
+    <glob pattern="*.ktz"/>
+    <glob pattern="*.ktr"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.karbon">
+    <glob pattern="*.karbon"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kchart">
+    <glob pattern="*.chrt"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kformula">
+    <glob pattern="*.kfo"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kivio">
+    <glob pattern="*.flw"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kontour">
+    <glob pattern="*.kon"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kpresenter">
+    <glob pattern="*.kpr"/>
+    <glob pattern="*.kpt"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kspread">
+    <glob pattern="*.ksp"/>
+  </mime-type>
+  <mime-type type="application/vnd.kde.kword">
+    <glob pattern="*.kwd"/>
+    <glob pattern="*.kwt"/>
+  </mime-type>
+  <mime-type type="application/vnd.kenameaapp">
+    <glob pattern="*.htke"/>
+  </mime-type>
+  <mime-type type="application/vnd.kidspiration">
+    <glob pattern="*.kia"/>
+  </mime-type>
+  <mime-type type="application/vnd.kinar">
+    <glob pattern="*.kne"/>
+    <glob pattern="*.knp"/>
+  </mime-type>
+  <mime-type type="application/vnd.koan">
+    <alias type="application/x-koan"/>
+    <_comment>SSEYO Koan File</_comment>
+    <glob pattern="*.skp"/>
+    <glob pattern="*.skd"/>
+    <glob pattern="*.skt"/>
+    <glob pattern="*.skm"/>
+  </mime-type>
+  <mime-type type="application/vnd.kodak-descriptor">
+    <glob pattern="*.sse"/>
+  </mime-type>
+  <mime-type type="application/vnd.liberty-request+xml"/>
+  <mime-type type="application/vnd.llamagraphics.life-balance.desktop">
+    <glob pattern="*.lbd"/>
+  </mime-type>
+  <mime-type type="application/vnd.llamagraphics.life-balance.exchange+xml">
+    <glob pattern="*.lbe"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-1-2-3">
+    <glob pattern="*.123"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-approach">
+    <glob pattern="*.apr"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-freelance">
+    <glob pattern="*.pre"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-notes">
+    <glob pattern="*.nsf"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-organizer">
+    <glob pattern="*.org"/>
+  </mime-type>
+  <mime-type type="application/vnd.lotus-screencam">
+    <glob pattern="*.scm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.lotus-wordpro">
+    <magic priority="50">
+      <match value="WordPro\0" type="string" offset="0" />
+      <match value="WordPro\r\373" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.lwp"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.macports.portpkg">
+    <glob pattern="*.portpkg"/>
+  </mime-type>
+  <mime-type type="application/vnd.marlin.drm.actiontoken+xml"/>
+  <mime-type type="application/vnd.marlin.drm.conftoken+xml"/>
+  <mime-type type="application/vnd.marlin.drm.license+xml"/>
+  <mime-type type="application/vnd.marlin.drm.mdcf"/>
+  <mime-type type="application/vnd.mcd">
+    <glob pattern="*.mcd"/>
+  </mime-type>
+  <mime-type type="application/vnd.medcalcdata">
+    <glob pattern="*.mc1"/>
+  </mime-type>
+  <mime-type type="application/vnd.mediastation.cdkey">
+    <glob pattern="*.cdkey"/>
+  </mime-type>
+  <mime-type type="application/vnd.meridian-slingshot"/>
+  <mime-type type="application/vnd.mfer">
+    <glob pattern="*.mwf"/>
+  </mime-type>
+  <mime-type type="application/vnd.mfmp">
+    <glob pattern="*.mfm"/>
+  </mime-type>
+  <mime-type type="application/vnd.micrografx.flo">
+    <glob pattern="*.flo"/>
+  </mime-type>
+  <mime-type type="application/vnd.micrografx.igx">
+    <glob pattern="*.igx"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.mif">
+    <_comment>FrameMaker MIF document</_comment>
+    <alias type="application/x-mif"/>
+    <alias type="application/x-frame"/>
+    <magic priority="50">
+      <match value="\&lt;MakerFile" type="string" offset="0" />
+      <match value="\&lt;MIFFile" type="string" offset="0" />
+      <match value="\&lt;MakerDictionary" type="string" offset="0" />
+      <match value="\&lt;MakerScreenFont" type="string" offset="0" />
+      <match value="\&lt;MML" type="string" offset="0" />
+      <match value="\&lt;Book" type="string" offset="0" />
+      <match value="\&lt;Maker" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.mif"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.minisoft-hp3000-save"/>
+  <mime-type type="application/vnd.mitsubishi.misty-guard.trustweb"/>
+  <mime-type type="application/vnd.mobius.daf">
+    <glob pattern="*.daf"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.dis">
+    <glob pattern="*.dis"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.mbk">
+    <glob pattern="*.mbk"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.mqy">
+    <glob pattern="*.mqy"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.msl">
+    <glob pattern="*.msl"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.plc">
+    <glob pattern="*.plc"/>
+  </mime-type>
+  <mime-type type="application/vnd.mobius.txf">
+    <glob pattern="*.txf"/>
+  </mime-type>
+  <mime-type type="application/vnd.mophun.application">
+    <glob pattern="*.mpn"/>
+  </mime-type>
+  <mime-type type="application/vnd.mophun.certificate">
+    <glob pattern="*.mpc"/>
+  </mime-type>
+  <mime-type type="application/vnd.motorola.flexsuite"/>
+  <mime-type type="application/vnd.motorola.flexsuite.adsi"/>
+  <mime-type type="application/vnd.motorola.flexsuite.fis"/>
+  <mime-type type="application/vnd.motorola.flexsuite.gotap"/>
+  <mime-type type="application/vnd.motorola.flexsuite.kmr"/>
+  <mime-type type="application/vnd.motorola.flexsuite.ttc"/>
+  <mime-type type="application/vnd.motorola.flexsuite.wem"/>
+  <mime-type type="application/vnd.motorola.iprm"/>
+  <mime-type type="application/vnd.mozilla.xul+xml">
+    <glob pattern="*.xul"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-artgalry">
+    <glob pattern="*.cil"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-asf"/>
+  <mime-type type="application/vnd.ms-cab-compressed">
+    <glob pattern="*.cab"/>
+  </mime-type>
+
+  <!-- http://www.iana.org/assignments/media-types/application/vnd.ms-excel -->
+  <mime-type type="application/vnd.ms-excel">
+    <!-- Use org.apache.tika.detect.ContainerAwareDetector for more reliable detection of OLE2 documents -->
+    <alias type="application/msexcel" />
+    <_comment>Microsoft Excel Spreadsheet</_comment>
+    <magic priority="50">
+      <match value="Microsoft\ Excel\ 5.0\ Worksheet" type="string" offset="2080"/>
+      <match value="Foglio\ di\ lavoro\ Microsoft\ Exce" type="string" offset="2080"/>
+      <match value="Biff5" type="string" offset="2114"/>
+      <match value="Biff5" type="string" offset="2121"/>
+      <match value="\x09\x04\x06\x00\x00\x00\x10\x00" type="string" offset="0"/>
+      <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+         <match value="W\x00o\x00r\x00k\x00b\x00o\x00o\x00k" type="string" offset="1152:4096" />
+      </match>
+    </magic>
+    <glob pattern="*.xls"/>
+    <glob pattern="*.xlm"/>
+    <glob pattern="*.xla"/>
+    <glob pattern="*.xlc"/>
+    <glob pattern="*.xlt"/>
+    <glob pattern="*.xlw"/>
+    <glob pattern="*.xll"/>
+    <glob pattern="*.xld"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.addin.macroenabled.12">
+    <_comment>Office Open XML Workbook Add-in (macro-enabled)</_comment>
+    <glob pattern="*.xlam"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.sheet.macroenabled.12">
+    <_comment>Office Open XML Workbook (macro-enabled)</_comment>
+    <glob pattern="*.xlsm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.sheet.binary.macroenabled.12">
+    <_comment>Microsoft Excel 2007 Binary Spreadsheet</_comment>
+    <glob pattern="*.xlsb"/>
+    <sub-class-of type="application/vnd.ms-excel"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.template.macroenabled.12">
+    <glob pattern="*.xltm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-fontobject">
+    <glob pattern="*.eot"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-htmlhelp">
+    <glob pattern="*.chm"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-ims">
+    <glob pattern="*.ims"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-lrm">
+    <glob pattern="*.lrm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-outlook">
+    <_comment>Microsoft Outlook Message</_comment>
+    <glob pattern="*.msg" />
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-pki.seccat">
+    <glob pattern="*.cat"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-pki.stl">
+    <glob pattern="*.stl"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-playready.initiator+xml"/>
+
+  <!-- http://www.iana.org/assignments/media-types/application/vnd.ms-powerpoint -->
+  <mime-type type="application/vnd.ms-powerpoint">
+    <!-- Use org.apache.tika.detect.ContainerAwareDetector for more reliable detection of OLE2 documents -->
+    <alias type="application/mspowerpoint"/>
+    <_comment>Microsoft Powerpoint Presentation</_comment>
+    <magic priority="50">
+      <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8">
+         <match value="P\x00o\x00w\x00e\x00r\x00P\x00o\x00i\x00n\x00t\x00 D\x00o\x00c\x00u\x00m\x00e\x00n\x00t" type="string" offset="1152:4096" />
+      </match>
+    </magic>
+    <glob pattern="*.ppz"/>
+    <glob pattern="*.ppt"/>
+    <glob pattern="*.pps"/>
+    <glob pattern="*.pot"/>
+    <glob pattern="*.ppa"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.addin.macroenabled.12">
+    <_comment>Office Open XML Presentation Add-in (macro-enabled)</_comment>
+    <glob pattern="*.ppam"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.presentation.macroenabled.12">
+    <_comment>Office Open XML Presentation (macro-enabled)</_comment>
+    <glob pattern="*.pptm"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.slide.macroenabled.12">
+    <glob pattern="*.sldm"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.slideshow.macroenabled.12">
+    <_comment>Office Open XML Presentation Slideshow (macro-enabled)</_comment>
+    <glob pattern="*.ppsm"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-powerpoint.template.macroenabled.12">
+    <glob pattern="*.potm"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-project">
+    <glob pattern="*.mpp"/>
+    <glob pattern="*.mpt"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-tnef">
+    <alias type="application/ms-tnef" />
+    <magic priority="50">
+      <match value="0x223e9f78" type="little16" offset="0" />
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-wmdrm.lic-chlg-req"/>
+  <mime-type type="application/vnd.ms-wmdrm.lic-resp"/>
+  <mime-type type="application/vnd.ms-wmdrm.meter-chlg-req"/>
+  <mime-type type="application/vnd.ms-wmdrm.meter-resp"/>
+
+  <mime-type type="application/vnd.ms-word.document.macroenabled.12">
+    <_comment>Office Open XML Document (macro-enabled)</_comment>
+    <glob pattern="*.docm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-word.template.macroenabled.12">
+    <_comment>Office Open XML Document Template (macro-enabled)</_comment>
+    <glob pattern="*.dotm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-works">
+    <glob pattern="*.wps"/>
+    <glob pattern="*.wks"/>
+    <glob pattern="*.wcm"/>
+    <glob pattern="*.wdb"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-wpl">
+    <glob pattern="*.wpl"/>
+  </mime-type>
+  <mime-type type="application/vnd.ms-xpsdocument">
+    <glob pattern="*.xps"/>
+  </mime-type>
+  <mime-type type="application/vnd.mseq">
+    <glob pattern="*.mseq"/>
+  </mime-type>
+  <mime-type type="application/vnd.msign"/>
+  <mime-type type="application/vnd.multiad.creator"/>
+  <mime-type type="application/vnd.multiad.creator.cif"/>
+  <mime-type type="application/vnd.music-niff"/>
+  <mime-type type="application/vnd.musician">
+    <glob pattern="*.mus"/>
+  </mime-type>
+  <mime-type type="application/vnd.muvee.style">
+    <glob pattern="*.msty"/>
+  </mime-type>
+  <mime-type type="application/vnd.ncd.control"/>
+  <mime-type type="application/vnd.ncd.reference"/>
+  <mime-type type="application/vnd.nervana"/>
+  <mime-type type="application/vnd.netfpx"/>
+  <mime-type type="application/vnd.neurolanguage.nlu">
+    <glob pattern="*.nlu"/>
+  </mime-type>
+  <mime-type type="application/vnd.noblenet-directory">
+    <glob pattern="*.nnd"/>
+  </mime-type>
+  <mime-type type="application/vnd.noblenet-sealer">
+    <glob pattern="*.nns"/>
+  </mime-type>
+  <mime-type type="application/vnd.noblenet-web">
+    <glob pattern="*.nnw"/>
+  </mime-type>
+  <mime-type type="application/vnd.nokia.catalogs"/>
+  <mime-type type="application/vnd.nokia.conml+wbxml"/>
+  <mime-type type="application/vnd.nokia.conml+xml"/>
+  <mime-type type="application/vnd.nokia.isds-radio-presets"/>
+  <mime-type type="application/vnd.nokia.iptv.config+xml"/>
+  <mime-type type="application/vnd.nokia.landmark+wbxml"/>
+  <mime-type type="application/vnd.nokia.landmark+xml"/>
+  <mime-type type="application/vnd.nokia.landmarkcollection+xml"/>
+  <mime-type type="application/vnd.nokia.n-gage.ac+xml"/>
+  <mime-type type="application/vnd.nokia.n-gage.data">
+    <glob pattern="*.ngdat"/>
+  </mime-type>
+  <mime-type type="application/vnd.nokia.n-gage.symbian.install">
+    <glob pattern="*.n-gage"/>
+  </mime-type>
+  <mime-type type="application/vnd.nokia.ncd"/>
+  <mime-type type="application/vnd.nokia.pcd+wbxml"/>
+  <mime-type type="application/vnd.nokia.pcd+xml"/>
+  <mime-type type="application/vnd.nokia.radio-preset">
+    <glob pattern="*.rpst"/>
+  </mime-type>
+  <mime-type type="application/vnd.nokia.radio-presets">
+    <glob pattern="*.rpss"/>
+  </mime-type>
+  <mime-type type="application/vnd.novadigm.edm">
+    <glob pattern="*.edm"/>
+  </mime-type>
+  <mime-type type="application/vnd.novadigm.edx">
+    <glob pattern="*.edx"/>
+  </mime-type>
+  <mime-type type="application/vnd.novadigm.ext">
+    <glob pattern="*.ext"/>
+  </mime-type>
+
+  <!-- =================================================================== -->
+  <!-- Open Document Format for Office Applications (OpenDocument) v1.0 -->
+  <!-- http://www.oasis-open.org/specs/index.php#opendocumentv1.0 -->
+  <!-- =================================================================== -->
+
+  <mime-type type="application/vnd.oasis.opendocument.chart">
+    <alias type="application/x-vnd.oasis.opendocument.chart"/>
+    <_comment>OpenDocument v1.0: Chart document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.chart"/>
+      </match>
+    </magic>
+    <glob pattern="*.odc"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.chart-template">
+    <alias type="application/x-vnd.oasis.opendocument.chart-template"/>
+    <_comment>OpenDocument v1.0: Chart document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.chart-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.otc"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.database">
+    <glob pattern="*.odb"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.formula">
+    <alias type="application/x-vnd.oasis.opendocument.formula"/>
+    <_comment>OpenDocument v1.0: Formula document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.formula" />
+      </match>
+    </magic>
+    <glob pattern="*.odf"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.formula-template">
+    <alias type="application/x-vnd.oasis.opendocument.formula-template"/>
+    <_comment>OpenDocument v1.0: Formula document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.formula-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.odft"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.graphics">
+    <alias type="application/x-vnd.oasis.opendocument.graphics"/>
+    <_comment>OpenDocument v1.0: Graphics document (Drawing)</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.graphics"/>
+      </match>
+    </magic>
+    <glob pattern="*.odg"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.graphics-template">
+    <alias type="application/x-vnd.oasis.opendocument.graphics-template"/>
+    <_comment>OpenDocument v1.0: Graphics document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.graphics-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.otg"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.image">
+    <alias type="application/x-vnd.oasis.opendocument.image"/>
+    <_comment>OpenDocument v1.0: Image document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.image"/>
+      </match>
+    </magic>
+    <glob pattern="*.odi"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.image-template">
+    <alias type="application/x-vnd.oasis.opendocument.image-template"/>
+    <_comment>OpenDocument v1.0: Image document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.image-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.oti"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.presentation">
+    <alias type="application/x-vnd.oasis.opendocument.presentation"/>
+    <_comment>OpenDocument v1.0: Presentation document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.presentation"/>
+      </match>
+    </magic>
+    <glob pattern="*.odp"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.presentation-template">
+    <alias type="application/x-vnd.oasis.opendocument.presentation-template"/>
+    <_comment>OpenDocument v1.0: Presentation document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+              value="mimetypeapplication/vnd.oasis.opendocument.presentation-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.otp"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.spreadsheet">
+    <alias type="application/x-vnd.oasis.opendocument.spreadsheet"/>
+    <_comment>OpenDocument v1.0: Spreadsheet document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.spreadsheet"/>
+      </match>
+    </magic>
+    <glob pattern="*.ods"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.spreadsheet-template">
+    <alias type="application/x-vnd.oasis.opendocument.spreadsheet-template"/>
+    <_comment>OpenDocument v1.0: Spreadsheet document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.spreadsheet-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.ots"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.text">
+    <alias type="application/x-vnd.oasis.opendocument.text"/>
+    <_comment>OpenDocument v1.0: Text document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.text"/>
+      </match>
+    </magic>
+    <glob pattern="*.odt"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.text-master">
+    <alias type="application/x-vnd.oasis.opendocument.text-master"/>
+    <_comment>OpenDocument v1.0: Global Text document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+               value="mimetypeapplication/vnd.oasis.opendocument.text-master"/>
+      </match>
+    </magic>
+    <glob pattern="*.otm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.text-template">
+    <alias type="application/x-vnd.oasis.opendocument.text-template"/>
+    <_comment>OpenDocument v1.0: Text document used as template</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+              value="mimetypeapplication/vnd.oasis.opendocument.text-template"/>
+      </match>
+    </magic>
+    <glob pattern="*.ott"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.oasis.opendocument.text-web">
+    <alias type="application/x-vnd.oasis.opendocument.text-web"/>
+    <_comment>OpenDocument v1.0: Text document used as template for HTML documents</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+              value="mimetypeapplication/vnd.oasis.opendocument.text-web"/>
+      </match>
+    </magic>
+    <glob pattern="*.oth"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.obn"/>
+  <mime-type type="application/vnd.olpc-sugar">
+    <glob pattern="*.xo"/>
+  </mime-type>
+  <mime-type type="application/vnd.oma-scws-config"/>
+  <mime-type type="application/vnd.oma-scws-http-request"/>
+  <mime-type type="application/vnd.oma-scws-http-response"/>
+  <mime-type type="application/vnd.oma.bcast.associated-procedure-parameter+xml"/>
+  <mime-type type="application/vnd.oma.bcast.drm-trigger+xml"/>
+  <mime-type type="application/vnd.oma.bcast.imd+xml"/>
+  <mime-type type="application/vnd.oma.bcast.ltkm"/>
+  <mime-type type="application/vnd.oma.bcast.notification+xml"/>
+  <mime-type type="application/vnd.oma.bcast.provisioningtrigger"/>
+  <mime-type type="application/vnd.oma.bcast.sgboot"/>
+  <mime-type type="application/vnd.oma.bcast.sgdd+xml"/>
+  <mime-type type="application/vnd.oma.bcast.sgdu"/>
+  <mime-type type="application/vnd.oma.bcast.simple-symbol-container"/>
+  <mime-type type="application/vnd.oma.bcast.smartcard-trigger+xml"/>
+  <mime-type type="application/vnd.oma.bcast.sprov+xml"/>
+  <mime-type type="application/vnd.oma.bcast.stkm"/>
+  <mime-type type="application/vnd.oma.dcd"/>
+  <mime-type type="application/vnd.oma.dcdc"/>
+  <mime-type type="application/vnd.oma.dd2+xml">
+    <glob pattern="*.dd2"/>
+  </mime-type>
+  <mime-type type="application/vnd.oma.drm.risd+xml"/>
+  <mime-type type="application/vnd.oma.group-usage-list+xml"/>
+  <mime-type type="application/vnd.oma.poc.detailed-progress-report+xml"/>
+  <mime-type type="application/vnd.oma.poc.final-report+xml"/>
+  <mime-type type="application/vnd.oma.poc.groups+xml"/>
+  <mime-type type="application/vnd.oma.poc.invocation-descriptor+xml"/>
+  <mime-type type="application/vnd.oma.poc.optimized-progress-report+xml"/>
+  <mime-type type="application/vnd.oma.xcap-directory+xml"/>
+  <mime-type type="application/vnd.omads-email+xml"/>
+  <mime-type type="application/vnd.omads-file+xml"/>
+  <mime-type type="application/vnd.omads-folder+xml"/>
+  <mime-type type="application/vnd.omaloc-supl-init"/>
+
+  <mime-type type="application/vnd.openofficeorg.extension">
+    <glob pattern="*.oxt"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.presentation">
+    <_comment>Office Open XML Presentation</_comment>
+    <glob pattern="*.pptx"/>
+    <glob pattern="*.thmx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slide">
+    <glob pattern="*.sldx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slideshow">
+    <glob pattern="*.ppsx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.template">
+    <_comment>Office Open XML Presentation Template</_comment>
+    <glob pattern="*.potx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.presentationml.slideshow">
+    <_comment>Office Open XML Presentation Slideshow</_comment>
+    <glob pattern="*.ppsx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
+    <_comment>Office Open XML Workbook</_comment>
+    <glob pattern="*.xlsx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.spreadsheetml.template">
+    <_comment>Office Open XML Workbook Template</_comment>
+    <glob pattern="*.xltx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.ms-excel.template.macroenabled.12">
+    <_comment>Office Open XML Workbook Template (macro-enabled)</_comment>
+    <glob pattern="*.xltm"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.document">
+    <_comment>Office Open XML Document</_comment>
+    <glob pattern="*.docx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.template">
+    <_comment>Office Open XML Document Template</_comment>
+    <glob pattern="*.dotx"/>
+    <sub-class-of type="application/x-tika-ooxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.osa.netdeploy"/>
+  <mime-type type="application/vnd.osgi.bundle"/>
+  <mime-type type="application/vnd.osgi.dp">
+    <glob pattern="*.dp"/>
+  </mime-type>
+  <mime-type type="application/vnd.otps.ct-kip+xml"/>
+  <mime-type type="application/vnd.palm">
+    <glob pattern="*.pdb"/>
+    <glob pattern="*.pqa"/>
+    <glob pattern="*.oprc"/>
+  </mime-type>
+  <mime-type type="application/vnd.paos.xml"/>
+  <mime-type type="application/vnd.pg.format">
+    <glob pattern="*.str"/>
+  </mime-type>
+  <mime-type type="application/vnd.pg.osasli">
+    <glob pattern="*.ei6"/>
+  </mime-type>
+  <mime-type type="application/vnd.piaccess.application-licence"/>
+  <mime-type type="application/vnd.picsel">
+    <glob pattern="*.efif"/>
+  </mime-type>
+  <mime-type type="application/vnd.poc.group-advertisement+xml"/>
+  <mime-type type="application/vnd.pocketlearn">
+    <glob pattern="*.plf"/>
+  </mime-type>
+  <mime-type type="application/vnd.powerbuilder6">
+    <glob pattern="*.pbd"/>
+  </mime-type>
+  <mime-type type="application/vnd.powerbuilder6-s"/>
+  <mime-type type="application/vnd.powerbuilder7"/>
+  <mime-type type="application/vnd.powerbuilder7-s"/>
+  <mime-type type="application/vnd.powerbuilder75"/>
+  <mime-type type="application/vnd.powerbuilder75-s"/>
+  <mime-type type="application/vnd.preminet"/>
+  <mime-type type="application/vnd.previewsystems.box">
+    <glob pattern="*.box"/>
+  </mime-type>
+  <mime-type type="application/vnd.proteus.magazine">
+    <glob pattern="*.mgz"/>
+  </mime-type>
+  <mime-type type="application/vnd.publishare-delta-tree">
+    <glob pattern="*.qps"/>
+  </mime-type>
+  <mime-type type="application/vnd.pvi.ptid1">
+    <glob pattern="*.ptid"/>
+  </mime-type>
+  <mime-type type="application/vnd.pwg-multiplexed"/>
+  <mime-type type="application/vnd.pwg-xhtml-print+xml"/>
+  <mime-type type="application/vnd.qualcomm.brew-app-res"/>
+  <mime-type type="application/vnd.quark.quarkxpress">
+    <glob pattern="*.qxd"/>
+    <glob pattern="*.qxt"/>
+    <glob pattern="*.qwd"/>
+    <glob pattern="*.qwt"/>
+    <glob pattern="*.qxl"/>
+    <glob pattern="*.qxb"/>
+  </mime-type>
+  <mime-type type="application/vnd.rapid"/>
+  <mime-type type="application/vnd.recordare.musicxml">
+    <glob pattern="*.mxl"/>
+  </mime-type>
+  <mime-type type="application/vnd.recordare.musicxml+xml">
+    <glob pattern="*.musicxml"/>
+  </mime-type>
+  <mime-type type="application/vnd.renlearn.rlprint"/>
+  <mime-type type="application/vnd.rim.cod">
+    <glob pattern="*.cod"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.rn-realmedia">
+    <magic priority="50">
+      <match value=".RMF" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.rm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.route66.link66+xml">
+    <glob pattern="*.link66"/>
+  </mime-type>
+  <mime-type type="application/vnd.ruckus.download"/>
+  <mime-type type="application/vnd.s3sms"/>
+  <mime-type type="application/vnd.sbm.cid"/>
+  <mime-type type="application/vnd.sbm.mid2"/>
+  <mime-type type="application/vnd.scribus"/>
+  <mime-type type="application/vnd.sealed.3df"/>
+  <mime-type type="application/vnd.sealed.csf"/>
+  <mime-type type="application/vnd.sealed.doc"/>
+  <mime-type type="application/vnd.sealed.eml"/>
+  <mime-type type="application/vnd.sealed.mht"/>
+  <mime-type type="application/vnd.sealed.net"/>
+  <mime-type type="application/vnd.sealed.ppt"/>
+  <mime-type type="application/vnd.sealed.tiff"/>
+  <mime-type type="application/vnd.sealed.xls"/>
+  <mime-type type="application/vnd.sealedmedia.softseal.html"/>
+  <mime-type type="application/vnd.sealedmedia.softseal.pdf"/>
+  <mime-type type="application/vnd.seemail">
+    <glob pattern="*.see"/>
+  </mime-type>
+  <mime-type type="application/vnd.sema">
+    <glob pattern="*.sema"/>
+  </mime-type>
+  <mime-type type="application/vnd.semd">
+    <glob pattern="*.semd"/>
+  </mime-type>
+  <mime-type type="application/vnd.semf">
+    <glob pattern="*.semf"/>
+  </mime-type>
+  <mime-type type="application/vnd.shana.informed.formdata">
+    <glob pattern="*.ifm"/>
+  </mime-type>
+  <mime-type type="application/vnd.shana.informed.formtemplate">
+    <glob pattern="*.itp"/>
+  </mime-type>
+  <mime-type type="application/vnd.shana.informed.interchange">
+    <glob pattern="*.iif"/>
+  </mime-type>
+  <mime-type type="application/vnd.shana.informed.package">
+    <glob pattern="*.ipk"/>
+  </mime-type>
+  <mime-type type="application/vnd.simtech-mindmapper">
+    <glob pattern="*.twd"/>
+    <glob pattern="*.twds"/>
+  </mime-type>
+  <mime-type type="application/vnd.smaf">
+    <glob pattern="*.mmf"/>
+  </mime-type>
+  <mime-type type="application/vnd.smart.teacher">
+    <glob pattern="*.teacher"/>
+  </mime-type>
+  <mime-type type="application/vnd.software602.filler.form+xml"/>
+  <mime-type type="application/vnd.software602.filler.form-xml-zip"/>
+  <mime-type type="application/vnd.solent.sdkm+xml">
+    <glob pattern="*.sdkm"/>
+    <glob pattern="*.sdkd"/>
+  </mime-type>
+  <mime-type type="application/vnd.spotfire.dxp">
+    <glob pattern="*.dxp"/>
+  </mime-type>
+  <mime-type type="application/vnd.spotfire.sfs">
+    <glob pattern="*.sfs"/>
+  </mime-type>
+  <mime-type type="application/vnd.sss-cod"/>
+  <mime-type type="application/vnd.sss-dtf"/>
+  <mime-type type="application/vnd.sss-ntf"/>
+  <mime-type type="application/vnd.stardivision.calc">
+    <glob pattern="*.sdc"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.draw">
+    <glob pattern="*.sda"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.impress">
+    <glob pattern="*.sdd"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.math">
+    <glob pattern="*.smf"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.writer">
+    <glob pattern="*.sdw"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.writer">
+    <glob pattern="*.vor"/>
+  </mime-type>
+  <mime-type type="application/vnd.stardivision.writer-global">
+    <glob pattern="*.sgl"/>
+  </mime-type>
+  <mime-type type="application/vnd.street-stream"/>
+  <mime-type type="application/vnd.sun.xml.calc">
+    <glob pattern="*.sxc"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.calc.template">
+    <glob pattern="*.stc"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.draw">
+    <glob pattern="*.sxd"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.draw.template">
+    <glob pattern="*.std"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.impress">
+    <glob pattern="*.sxi"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.impress.template">
+    <glob pattern="*.sti"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.math">
+    <glob pattern="*.sxm"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.sun.xml.writer">
+    <alias type="application/x-vnd.sun.xml.writer"/>
+    <_comment>OpenOffice v1.0: Writer Document</_comment>
+    <magic>
+      <match type="string" offset="0" value="PK">
+        <match type="string" offset="30"
+          value="mimetypeapplication/vnd.sun.xml.writer"/>
+      </match>
+    </magic>
+    <glob pattern="*.sxw"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.sun.xml.writer.global">
+    <glob pattern="*.sxg"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.xml.writer.template">
+    <glob pattern="*.stw"/>
+  </mime-type>
+  <mime-type type="application/vnd.sun.wadl+xml"/>
+  <mime-type type="application/vnd.sus-calendar">
+    <glob pattern="*.sus"/>
+    <glob pattern="*.susp"/>
+  </mime-type>
+  <mime-type type="application/vnd.svd">
+    <glob pattern="*.svd"/>
+  </mime-type>
+  <mime-type type="application/vnd.swiftview-ics"/>
+
+  <mime-type type="application/vnd.symbian.install">
+    <magic priority="50">
+      <match value="0x10000419" type="little32" offset="8" />
+    </magic>
+    <glob pattern="*.sis"/>
+    <glob pattern="*.sisx"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.syncml+xml">
+    <glob pattern="*.xsm"/>
+  </mime-type>
+  <mime-type type="application/vnd.syncml.dm+wbxml">
+    <glob pattern="*.bdm"/>
+  </mime-type>
+  <mime-type type="application/vnd.syncml.dm+xml">
+    <glob pattern="*.xdm"/>
+  </mime-type>
+  <mime-type type="application/vnd.syncml.dm.notification"/>
+  <mime-type type="application/vnd.syncml.ds.notification"/>
+  <mime-type type="application/vnd.tao.intent-module-archive">
+    <glob pattern="*.tao"/>
+  </mime-type>
+  <mime-type type="application/vnd.tmobile-livetv">
+    <glob pattern="*.tmo"/>
+  </mime-type>
+  <mime-type type="application/vnd.trid.tpt">
+    <glob pattern="*.tpt"/>
+  </mime-type>
+  <mime-type type="application/vnd.triscape.mxs">
+    <glob pattern="*.mxs"/>
+  </mime-type>
+  <mime-type type="application/vnd.trueapp">
+    <glob pattern="*.tra"/>
+  </mime-type>
+  <mime-type type="application/vnd.truedoc"/>
+  <mime-type type="application/vnd.ufdl">
+    <glob pattern="*.ufd"/>
+    <glob pattern="*.ufdl"/>
+  </mime-type>
+  <mime-type type="application/vnd.uiq.theme">
+    <glob pattern="*.utz"/>
+  </mime-type>
+  <mime-type type="application/vnd.umajin">
+    <glob pattern="*.umj"/>
+  </mime-type>
+  <mime-type type="application/vnd.unity">
+    <glob pattern="*.unityweb"/>
+  </mime-type>
+  <mime-type type="application/vnd.uoml+xml">
+    <glob pattern="*.uoml"/>
+  </mime-type>
+  <mime-type type="application/vnd.uplanet.alert"/>
+  <mime-type type="application/vnd.uplanet.alert-wbxml"/>
+  <mime-type type="application/vnd.uplanet.bearer-choice"/>
+  <mime-type type="application/vnd.uplanet.bearer-choice-wbxml"/>
+  <mime-type type="application/vnd.uplanet.cacheop"/>
+  <mime-type type="application/vnd.uplanet.cacheop-wbxml"/>
+  <mime-type type="application/vnd.uplanet.channel"/>
+  <mime-type type="application/vnd.uplanet.channel-wbxml"/>
+  <mime-type type="application/vnd.uplanet.list"/>
+  <mime-type type="application/vnd.uplanet.list-wbxml"/>
+  <mime-type type="application/vnd.uplanet.listcmd"/>
+  <mime-type type="application/vnd.uplanet.listcmd-wbxml"/>
+  <mime-type type="application/vnd.uplanet.signal"/>
+  <mime-type type="application/vnd.vcx">
+    <glob pattern="*.vcx"/>
+  </mime-type>
+  <mime-type type="application/vnd.vd-study"/>
+  <mime-type type="application/vnd.vectorworks"/>
+  <mime-type type="application/vnd.vidsoft.vidconference"/>
+
+  <!-- http://www.iana.org/assignments/media-types/application/vnd.visio -->
+  <mime-type type="application/vnd.visio">
+    <_comment>Microsoft Visio Diagram</_comment>
+    <glob pattern="*.vsd"/>
+    <glob pattern="*.vst"/>
+    <glob pattern="*.vss"/>
+    <glob pattern="*.vsw"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.visionary">
+    <glob pattern="*.vis"/>
+  </mime-type>
+  <mime-type type="application/vnd.vividence.scriptfile"/>
+  <mime-type type="application/vnd.vsf">
+    <glob pattern="*.vsf"/>
+  </mime-type>
+  <mime-type type="application/vnd.wap.sic"/>
+  <mime-type type="application/vnd.wap.slc"/>
+
+  <mime-type type="application/vnd.wap.wbxml">
+    <glob pattern="*.wbxml"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.wap.wmlc">
+    <_comment>Compiled WML Document</_comment>
+    <glob pattern="*.wmlc"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.wap.wmlscriptc">
+    <_comment>Compiled WML Script</_comment>
+    <glob pattern="*.wmlsc"/>
+  </mime-type>
+
+  <mime-type type="application/vnd.webturbo">
+    <glob pattern="*.wtb"/>
+  </mime-type>
+  <mime-type type="application/vnd.wfa.wsc"/>
+  <mime-type type="application/vnd.wmc"/>
+  <mime-type type="application/vnd.wmf.bootstrap"/>
+  <mime-type type="application/vnd.wordperfect">
+    <glob pattern="*.wpd"/>
+  </mime-type>
+  <mime-type type="application/vnd.wqd">
+    <glob pattern="*.wqd"/>
+  </mime-type>
+  <mime-type type="application/vnd.wrq-hp3000-labelled"/>
+  <mime-type type="application/vnd.wt.stf">
+    <glob pattern="*.stf"/>
+  </mime-type>
+  <mime-type type="application/vnd.wv.csp+wbxml"/>
+  <mime-type type="application/vnd.wv.csp+xml"/>
+  <mime-type type="application/vnd.wv.ssp+xml"/>
+  <mime-type type="application/vnd.xara">
+    <glob pattern="*.xar"/>
+  </mime-type>
+  <mime-type type="application/vnd.xfdl">
+    <glob pattern="*.xfdl"/>
+  </mime-type>
+  <mime-type type="application/vnd.xfdl.webform"/>
+  <mime-type type="application/vnd.xmi+xml"/>
+  <mime-type type="application/vnd.xmpie.cpkg"/>
+  <mime-type type="application/vnd.xmpie.dpkg"/>
+  <mime-type type="application/vnd.xmpie.plan"/>
+  <mime-type type="application/vnd.xmpie.ppkg"/>
+  <mime-type type="application/vnd.xmpie.xlim"/>
+  <mime-type type="application/vnd.yamaha.hv-dic">
+    <glob pattern="*.hvd"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.hv-script">
+    <glob pattern="*.hvs"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.hv-voice">
+    <glob pattern="*.hvp"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.openscoreformat">
+    <glob pattern="*.osf"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.openscoreformat.osfpvg+xml">
+    <glob pattern="*.osfpvg"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.smaf-audio">
+    <glob pattern="*.saf"/>
+  </mime-type>
+  <mime-type type="application/vnd.yamaha.smaf-phrase">
+    <glob pattern="*.spf"/>
+  </mime-type>
+  <mime-type type="application/vnd.yellowriver-custom-menu">
+    <glob pattern="*.cmp"/>
+  </mime-type>
+  <mime-type type="application/vnd.zul">
+    <glob pattern="*.zir"/>
+    <glob pattern="*.zirz"/>
+  </mime-type>
+  <mime-type type="application/vnd.zzazz.deck+xml">
+    <glob pattern="*.zaz"/>
+  </mime-type>
+  <mime-type type="application/voicexml+xml">
+    <glob pattern="*.vxml"/>
+  </mime-type>
+  <mime-type type="application/watcherinfo+xml"/>
+  <mime-type type="application/whoispp-query"/>
+  <mime-type type="application/whoispp-response"/>
+  <mime-type type="application/winhlp">
+    <glob pattern="*.hlp"/>
+  </mime-type>
+  <mime-type type="application/wita"/>
+  <mime-type type="application/wordperfect5.1"/>
+  <mime-type type="application/wsdl+xml">
+    <glob pattern="*.wsdl"/>
+  </mime-type>
+  <mime-type type="application/wspolicy+xml">
+    <glob pattern="*.wspolicy"/>
+  </mime-type>
+
+  <mime-type type="application/x-123">
+    <magic priority="50">
+      <match value="0x00001a00" type="big32" offset="0" />
+      <match value="0x00000200" type="big32" offset="0" />
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-abiword">
+    <glob pattern="*.abw"/>
+  </mime-type>
+  <mime-type type="application/x-ace-compressed">
+    <glob pattern="*.ace"/>
+  </mime-type>
+
+  <mime-type type="application/x-adobe-indesign">
+    <acronym>INDD</acronym>
+    <_comment>Adobe InDesign document</_comment>
+    <glob pattern="*.indd"/>
+  </mime-type>
+
+  <mime-type type="application/x-adobe-indesign-interchange">
+    <acronym>INX</acronym>
+    <_comment>Adobe InDesign Interchange format</_comment>
+    <magic priority="50">
+      <match value="&lt;?aid" type="string" offset="0:100"/>
+    </magic>
+    <glob pattern="*.inx"/>
+    <sub-class-of type="application/xml"/>
+  </mime-type>
+
+  <mime-type type="application/x-archive">
+    <magic priority="50">
+      <match value="=&lt;ar&gt;" type="string" offset="0"/>
+      <match value="=!&lt;arch&gt;" type="string" offset="0"/>
+    </magic>
+    <glob patter="*.ar"/>
+  </mime-type>
+
+  <mime-type type="application/x-authorware-bin">
+    <glob pattern="*.aab"/>
+    <glob pattern="*.x32"/>
+    <glob pattern="*.u32"/>
+    <glob pattern="*.vox"/>
+  </mime-type>
+  <mime-type type="application/x-authorware-map">
+    <glob pattern="*.aam"/>
+  </mime-type>
+  <mime-type type="application/x-authorware-seg">
+    <glob pattern="*.aas"/>
+  </mime-type>
+  <mime-type type="application/x-bcpio">
+    <glob pattern="*.bcpio"/>
+  </mime-type>
+
+  <mime-type type="application/x-berkeley-db">
+    <magic priority="50">
+      <match value="0x00061561" type="big32" offset="0"/>
+      <match value="0x00061561" type="host32" offset="12"/>
+      <match value="0x00061561" type="big32" offset="12"/>
+      <match value="0x00061561" type="little32" offset="12"/>
+      <match value="0x00053162" type="host32" offset="12"/>
+      <match value="0x00053162" type="big32" offset="12"/>
+      <match value="0x00053162" type="little32" offset="12"/>
+      <match value="0x00042253" type="host32" offset="12"/>
+      <match value="0x00042253" type="big32" offset="12"/>
+      <match value="0x00042253" type="little32" offset="12"/>
+      <match value="0x00040988" type="host32" offset="12"/>
+      <match value="0x00040988" type="little32" offset="12"/>
+      <match value="0x00040988" type="big32" offset="12"/>
+      <match value="0x00053162" type="host32" offset="0"/>
+      <match value="0x00053162" type="big32" offset="0"/>
+      <match value="0x00053162" type="little32" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-bibtex-text-file">
+    <magic priority="50">
+      <match value="%\ BibTeX\ `" type="string" offset="0"/>
+      <match value="%%%\ \ " type="string" offset="73"/>
+      <match value="%\ BibTeX\ standard\ bibliography\ " type="string" offset="0"/>
+      <match value="%%%\ \ @BibTeX-style-file{" type="string" offset="73"/>
+      <match value="@article{" type="string" offset="0"/>
+      <match value="@book{" type="string" offset="0"/>
+      <match value="@inbook{" type="string" offset="0"/>
+      <match value="@incollection{" type="string" offset="0"/>
+      <match value="@inproceedings{" type="string" offset="0"/>
+      <match value="@manual{" type="string" offset="0"/>
+      <match value="@misc{" type="string" offset="0"/>
+      <match value="@preamble{" type="string" offset="0"/>
+      <match value="@phdthesis{" type="string" offset="0"/>
+      <match value="@techreport{" type="string" offset="0"/>
+      <match value="@unpublished{" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.bib"/>
+    <glob pattern="*.bibtex"/>
+  </mime-type>
+
+  <mime-type type="application/x-bittorrent">
+    <magic priority="50">
+      <match value="d8:announce" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.torrent"/>
+  </mime-type>
+
+  <mime-type type="application/x-bzip">
+    <magic priority="40">
+      <match value="BZh" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.bz"/>
+    <glob pattern="*.tbz"/>
+  </mime-type>
+
+  <mime-type type="application/x-bzip2">
+    <glob pattern="*.bz2"/>
+    <glob pattern="*.tbz2"/>
+    <glob pattern="*.boz"/>
+    <sub-class-of type="application/x-bzip"/>
+  </mime-type>
+
+  <mime-type type="application/x-cdlink">
+    <_comment>Virtual CD-ROM CD Image File</_comment>
+    <glob pattern="*.vcd"/>
+  </mime-type>
+
+  <mime-type type="application/x-chat">
+    <glob pattern="*.chat"/>
+  </mime-type>
+  <mime-type type="application/x-chess-pgn">
+    <glob pattern="*.pgn"/>
+  </mime-type>
+
+  <mime-type type="application/x-compress">
+    <magic priority="50">
+      <match value="\037\235" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.z"/>
+  </mime-type>
+
+  <mime-type type="application/x-corelpresentations">
+    <glob pattern="*.shw"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+  
+  <mime-type type="application/x-cpio">
+    <magic priority="50">
+      <match value="070707" type="little16" offset="0"/>
+      <match value="070707" type="big16" offset="0"/>
+      <match value="070707" type="string" offset="0"/>
+      <match value="070701" type="string" offset="0"/>
+      <match value="070702" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.cpio"/>
+  </mime-type>
+
+  <mime-type type="application/x-csh">
+    <glob pattern="*.csh"/>
+  </mime-type>
+
+  <mime-type type="application/x-debian-package">
+    <glob pattern="*.deb"/>
+    <glob pattern="*.udeb"/>
+  </mime-type>
+
+  <mime-type type="application/x-director">
+    <_comment>Shockwave Movie</_comment>
+    <glob pattern="*.dir"/>
+    <glob pattern="*.dcr"/>
+    <glob pattern="*.dxr"/>
+    <glob pattern="*.cst"/>
+    <glob pattern="*.cct"/>
+    <glob pattern="*.cxt"/>
+    <glob pattern="*.w3d"/>
+    <glob pattern="*.fgd"/>
+    <glob pattern="*.swa"/>
+  </mime-type>
+
+  <mime-type type="application/x-doom">
+    <glob pattern="*.wad"/>
+  </mime-type>
+  <mime-type type="application/x-dtbncx+xml">
+    <glob pattern="*.ncx"/>
+  </mime-type>
+  <mime-type type="application/x-dtbook+xml">
+    <glob pattern="*.dtb"/>
+  </mime-type>
+  <mime-type type="application/x-dtbresource+xml">
+    <glob pattern="*.res"/>
+  </mime-type>
+
+  <mime-type type="application/x-dvi">
+    <magic priority="50">
+      <match value="\367\002" type="string" offset="0"/>
+      <match value="0x02f7" type="little16" offset="0"/>
+    </magic>
+    <glob pattern="*.dvi"/>
+  </mime-type>
+
+  <mime-type type="application/x-elc">
+    <_comment>Emacs Lisp bytecode</_comment>
+    <magic priority="50">
+      <!-- Emacs 18 -->
+      <match value="\012(" type="string" offset="0" />
+      <!-- Emacs 19 -->
+      <match value=";ELC\023\000\000\000" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.elc"/>
+  </mime-type>
+
+  <mime-type type="application/x-font-bdf">
+    <glob pattern="*.bdf"/>
+  </mime-type>
+  <mime-type type="application/x-font-dos"/>
+  <mime-type type="application/x-font-framemaker"/>
+  <mime-type type="application/x-font-ghostscript">
+    <glob pattern="*.gsf"/>
+  </mime-type>
+  <mime-type type="application/x-font-libgrx"/>
+  <mime-type type="application/x-font-linux-psf">
+    <glob pattern="*.psf"/>
+  </mime-type>
+
+  <mime-type type="application/x-font-otf">
+    <acronym>OTF</acronym>
+    <_comment>OpenType Font</_comment>
+    <glob pattern="*.otf"/>
+  </mime-type>
+
+  <mime-type type="application/x-font-pcf">
+    <glob pattern="*.pcf"/>
+  </mime-type>
+  <mime-type type="application/x-font-snf">
+    <glob pattern="*.snf"/>
+  </mime-type>
+  <mime-type type="application/x-font-speedo"/>
+  <mime-type type="application/x-font-sunos-news"/>
+
+  <mime-type type="application/x-font-ttf">
+    <acronym>TTF</acronym>
+    <_comment>TrueType Font</_comment>
+    <glob pattern="*.ttf"/>
+    <glob pattern="*.ttc"/>
+    <magic priority="40">
+      <match value="0x00010000" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-font-type1">
+    <glob pattern="*.pfa"/>
+    <glob pattern="*.pfb"/>
+    <glob pattern="*.pfm"/>
+    <glob pattern="*.afm"/>
+  </mime-type>
+  <mime-type type="application/x-font-vfont"/>
+
+  <mime-type type="application/x-futuresplash">
+    <_comment>Macromedia FutureSplash File</_comment>
+    <glob pattern="*.spl"/>
+  </mime-type>
+
+  <mime-type type="application/x-gnucash">
+    <glob pattern="*.gnucash" />
+  </mime-type>
+
+  <mime-type type="application/x-gnumeric">
+    <alias type="application/x-Gnumeric-spreadsheet"/>
+    <magic priority="50">
+      <match value="=&lt;gmr:Workbook" type="string" offset="39" />
+    </magic>
+    <glob pattern="*.gnumeric"/>
+  </mime-type>
+
+  <mime-type type="application/x-gtar">
+    <magic priority="40">
+      <!-- GNU tar archive -->
+      <match value="ustar \0" type="string" offset="257" />
+    </magic>
+    <glob pattern="*.gtar"/>
+    <sub-class-of type="application/x-tar"/>
+  </mime-type>
+
+  <mime-type type="application/x-gzip">
+    <magic priority="40">
+      <match value="\037\213" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.tgz" />
+    <glob pattern="*.gz" />
+    <glob pattern="*-gz" />
+    <glob pattern="*.emz" />
+  </mime-type>
+
+  <mime-type type="application/x-hdf">
+    <magic priority="50">
+      <match value="0x0e031301" type="big32" offset="0"/>
+      <match value="\211HDF\r\n\032" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.hdf"/>
+    <glob pattern="*.he5"/>
+  </mime-type>
+
+  <mime-type type="application/x-hwp">
+    <magic priority="50">
+      <!--
+        TIKA-330: Detection pattern based on signature strings from
+        the hwpfilter/source/hwpfile.cpp file in OpenOffice.org.
+      -->
+      <match value="HWP Document File V" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-iso9660-image">
+    <magic priority="50">
+      <match value="CD001" type="string" offset="37633"/>
+    </magic>
+    <glob pattern="*.iso" />
+  </mime-type>
+
+  <mime-type type="application/x-java-jnlp-file">
+    <glob pattern="*.jnlp"/>
+  </mime-type>
+
+  <mime-type type="application/x-kdelnk">
+    <magic priority="50">
+      <match value="[KDE\ Desktop\ Entry]" type="string" offset="0"/>
+      <match value="#\ KDE\ Config\ File" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-latex">
+    <_comment>LaTeX Source Document</_comment>
+    <magic priority="50">
+      <match value="%\ -*-latex-*-" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.latex"/>
+  </mime-type>
+
+  <mime-type type="application/x-lha">
+    <magic priority="50">
+      <match value="-lzs-" type="string" offset="2"/>
+      <match value="-lh\40-" type="string" offset="2"/>
+      <match value="-lhd-" type="string" offset="2"/>
+      <match value="-lh2-" type="string" offset="2"/>
+      <match value="-lh3-" type="string" offset="2"/>
+      <match value="-lh4-" type="string" offset="2"/>
+      <match value="-lh5-" type="string" offset="2"/>
+      <match value="-lh6-" type="string" offset="2"/>
+      <match value="-lh7-" type="string" offset="2"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-lharc">
+    <magic priority="50">
+      <match value="-lh0-" type="string" offset="2"/>
+      <match value="-lh1-" type="string" offset="2"/>
+      <match value="-lz4-" type="string" offset="2"/>
+      <match value="-lz5-" type="string" offset="2"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-mobipocket-ebook">
+    <glob pattern="*.prc"/>
+    <glob pattern="*.mobi"/>
+  </mime-type>
+  <mime-type type="application/x-ms-application">
+    <glob pattern="*.application"/>
+  </mime-type>
+  <mime-type type="application/x-ms-wmd">
+    <glob pattern="*.wmd"/>
+  </mime-type>
+  <mime-type type="application/x-ms-wmz">
+    <sub-class-of type="application/x-gzip"/>
+    <glob pattern="*.wmz"/>
+  </mime-type>
+  <mime-type type="application/x-ms-xbap">
+    <glob pattern="*.xbap"/>
+  </mime-type>
+  <mime-type type="application/x-msaccess">
+    <glob pattern="*.mdb"/>
+  </mime-type>
+  <mime-type type="application/x-msbinder">
+    <glob pattern="*.obd"/>
+  </mime-type>
+  <mime-type type="application/x-mscardfile">
+    <glob pattern="*.crd"/>
+  </mime-type>
+  <mime-type type="application/x-msclip">
+    <glob pattern="*.clp"/>
+  </mime-type>
+  <mime-type type="application/x-msdownload">
+    <glob pattern="*.exe"/>
+    <glob pattern="*.dll"/>
+    <glob pattern="*.com"/>
+    <glob pattern="*.bat"/>
+    <glob pattern="*.msi"/>
+  </mime-type>
+  <mime-type type="application/x-msmediaview">
+    <glob pattern="*.mvb"/>
+    <glob pattern="*.m13"/>
+    <glob pattern="*.m14"/>
+  </mime-type>
+  <mime-type type="application/x-msmetafile">
+    <alias type="image/x-emf"/>
+    <alias type="image/x-wmf"/>
+    <acronym>WMF</acronym>
+    <_comment>Windows Metafile</_comment>
+    <glob pattern="*.wmf"/>
+    <glob pattern="*.emf"/>
+  </mime-type>
+  <mime-type type="application/x-msmoney">
+    <glob pattern="*.mny"/>
+  </mime-type>
+  <mime-type type="application/x-mspublisher">
+    <glob pattern="*.pub"/>
+  </mime-type>
+  <mime-type type="application/x-msschedule">
+    <glob pattern="*.scd"/>
+  </mime-type>
+  <mime-type type="application/x-msterminal">
+    <glob pattern="*.trm"/>
+  </mime-type>
+  <mime-type type="application/x-mswrite">
+    <glob pattern="*.wri"/>
+  </mime-type>
+  <mime-type type="application/x-netcdf">
+    <glob pattern="*.nc"/>
+    <glob pattern="*.cdf"/>
+  </mime-type>
+  <mime-type type="application/x-pkcs12">
+    <glob pattern="*.p12"/>
+    <glob pattern="*.pfx"/>
+  </mime-type>
+  <mime-type type="application/x-pkcs7-certificates">
+    <glob pattern="*.p7b"/>
+    <glob pattern="*.spc"/>
+  </mime-type>
+  <mime-type type="application/x-pkcs7-certreqresp">
+    <glob pattern="*.p7r"/>
+  </mime-type>
+
+  <mime-type type="application/x-quattro-pro">
+    <glob pattern="*.qpw"/>
+    <glob pattern="*.wb1"/>
+    <glob pattern="*.wb2"/>
+    <glob pattern="*.wb3"/>
+    <sub-class-of type="application/x-tika-msoffice"/>
+  </mime-type>
+  
+  <mime-type type="application/x-rar-compressed">
+    <alias type="application/x-rar"/>
+    <magic priority="50">
+      <match value="Rar!" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.rar"/>
+  </mime-type>
+
+  <mime-type type="application/x-rpm">
+    <glob pattern="*.rpm"/>
+  </mime-type>
+
+  <mime-type type="application/x-sc">
+    <magic priority="50">
+      <match value="Spreadsheet" type="string" offset="38"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-sh">
+    <magic priority="50">
+      <match value="#!/" type="string" offset="0"/>
+      <match value="#!\ /" type="string" offset="0"/>
+      <match value="#!\t/" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.sh"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="application/x-shar">
+    <glob pattern="*.shar"/>
+  </mime-type>
+
+  <mime-type type="application/x-shockwave-flash">
+    <acronym>Flash</acronym>
+    <_comment>Adobe Flash</_comment>
+    <magic priority="50">
+      <match value="FWS" type="string" offset="0"/> <!-- F = Uncompressed -->
+      <match value="CWS" type="string" offset="0"/> <!-- C = Compressed -->
+    </magic>
+    <glob pattern="*.swf"/>
+  </mime-type>
+
+  <mime-type type="application/x-silverlight-app">
+    <glob pattern="*.xap"/>
+  </mime-type>
+
+  <mime-type type="application/x-stuffit">
+    <magic priority="50">
+      <match value="StuffIt" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.sit"/>
+  </mime-type>
+
+  <mime-type type="application/x-stuffitx">
+    <glob pattern="*.sitx"/>
+  </mime-type>
+  <mime-type type="application/x-sv4cpio">
+    <glob pattern="*.sv4cpio"/>
+  </mime-type>
+  <mime-type type="application/x-sv4crc">
+    <glob pattern="*.sv4crc"/>
+  </mime-type>
+
+  <mime-type type="application/x-tar">
+    <magic priority="40">
+      <!-- POSIX tar archive -->
+      <match value="ustar\0" type="string" offset="257" />
+    </magic>
+    <glob pattern="*.tar"/>
+  </mime-type>
+
+  <mime-type type="application/x-tcl">
+    <alias type="text/x-tcl"/>
+    <glob pattern="*.tcl"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="application/x-tex">
+    <alias type="text/x-tex"/>
+    <magic priority="50">
+      <match value="\\input" type="string" offset="0"/>
+      <match value="\\section" type="string" offset="0"/>
+      <match value="\\setlength" type="string" offset="0"/>
+      <match value="\\documentstyle" type="string" offset="0"/>
+      <match value="\\chapter" type="string" offset="0"/>
+      <match value="\\documentclass" type="string" offset="0"/>
+      <match value="\\relax" type="string" offset="0"/>
+      <match value="\\contentsline" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.tex"/>
+  </mime-type>
+
+  <mime-type type="application/x-tex-tfm">
+    <glob pattern="*.tfm"/>
+  </mime-type>
+
+  <mime-type type="application/x-texinfo">
+    <alias type="text/x-texinfo" />
+    <magic priority="50">
+      <match value="\\input\ texinfo" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.texinfo"/>
+    <glob pattern="*.texi"/>
+  </mime-type>
+
+  <!-- =================================================================== -->
+  <!-- Microsoft Office binary file formats -->
+  <!-- http://www.microsoft.com/interop/docs/OfficeBinaryFormats.mspx -->
+  <!-- =================================================================== -->
+  <mime-type type="application/x-tika-msoffice">
+    <magic>
+      <match value="0xd0cf11e0a1b11ae1" type="string" offset="0:8"/>
+    </magic>
+  </mime-type>
+
+  <!-- =================================================================== -->
+  <!-- Office Open XML file formats -->
+  <!-- http://www.ecma-international.org/publications/standards/Ecma-376.htm -->
+  <!-- =================================================================== -->
+  <mime-type type="application/x-tika-ooxml">
+    <sub-class-of type="application/zip"/>
+    <magic priority="50">
+      <match value="PK\003\004" type="string" offset="0">
+        <match value="[Content_Types].xml" type="string" offset="30"/>
+      </match>
+    </magic>
+  </mime-type>
+
+  <mime-type type="application/x-ustar">
+    <glob pattern="*.ustar"/>
+  </mime-type>
+  <mime-type type="application/x-wais-source">
+    <glob pattern="*.src"/>
+  </mime-type>
+  <mime-type type="application/x-x509-ca-cert">
+    <glob pattern="*.der"/>
+    <glob pattern="*.crt"/>
+  </mime-type>
+  <mime-type type="application/x-xfig">
+    <glob pattern="*.fig"/>
+  </mime-type>
+  <mime-type type="application/x-xpinstall">
+    <glob pattern="*.xpi"/>
+  </mime-type>
+
+  <mime-type type="application/x-zoo">
+    <magic priority="50">
+      <match value="0xfdc4a7dc" type="little32" offset="20"/>
+    </magic>
+    <glob pattern="*.zoo"/>
+  </mime-type>
+
+  <mime-type type="application/x400-bp"/>
+  <mime-type type="application/xcap-att+xml"/>
+  <mime-type type="application/xcap-caps+xml"/>
+  <mime-type type="application/xcap-el+xml"/>
+  <mime-type type="application/xcap-error+xml"/>
+  <mime-type type="application/xcap-ns+xml"/>
+  <mime-type type="application/xcon-conference-info-diff+xml"/>
+  <mime-type type="application/xcon-conference-info+xml"/>
+  <mime-type type="application/xenc+xml">
+    <glob pattern="*.xenc"/>
+  </mime-type>
+
+  <mime-type type="application/xhtml+xml">
+    <magic priority="50">
+      <match value="&lt;html xmlns=" type="string" offset="0:8192"/>
+    </magic>
+    <root-XML namespaceURI="http://www.w3.org/1999/xhtml" localName="html"/>
+    <glob pattern="*.xhtml"/>
+    <glob pattern="*.xht"/>
+  </mime-type>
+
+  <mime-type type="application/xhtml-voice+xml"/>
+
+  <mime-type type="application/xml">
+    <alias type="text/xml"/>
+    <magic priority="50">
+      <match value="&lt;?xml" type="string" offset="0"/>
+      <match value="&lt;?XML" type="string" offset="0"/>
+      <match value="&lt;!--" type="string" offset="0"/>
+      <match value="0xFFFE3C003F0078006D006C00" type="string" offset="0"/>
+      <match value="0xFEFF003C003F0078006D006C" type="string" offset="0"/>
+      <!-- TODO: Add matches for the other possible XML encoding schemes -->
+    </magic>
+    <glob pattern="*.xml"/>
+    <glob pattern="*.xsl"/>
+    <glob pattern="*.xsd"/>
+    <sub-class-of type="text/plain" />
+  </mime-type>
+
+  <mime-type type="application/xml-dtd">
+    <sub-class-of type="text/plain"/>
+    <glob pattern="*.dtd"/>
+  </mime-type>
+  <mime-type type="application/xml-external-parsed-entity"/>
+  <mime-type type="application/xmpp+xml"/>
+  <mime-type type="application/xop+xml">
+    <glob pattern="*.xop"/>
+  </mime-type>
+
+  <mime-type type="application/xslt+xml">
+    <alias type="text/xsl"/>
+    <acronym>XSLT</acronym>
+    <_comment>XSL Transformations</_comment>
+    <root-XML localName="stylesheet"
+              namespaceURI="http://www.w3.org/1999/XSL/Transform"/>
+    <glob pattern="*.xslt"/>
+  </mime-type>
+
+  <mime-type type="application/xspf+xml">
+    <glob pattern="*.xspf"/>
+  </mime-type>
+  <mime-type type="application/xv+xml">
+    <glob pattern="*.mxml"/>
+    <glob pattern="*.xhvml"/>
+    <glob pattern="*.xvml"/>
+    <glob pattern="*.xvm"/>
+  </mime-type>
+
+  <mime-type type="application/zip">
+    <alias type="application/x-zip-compressed"/>
+    <magic priority="40">
+      <match value="PK\003\004" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.zip"/>
+  </mime-type>
+
+  <mime-type type="audio/32kadpcm"/>
+  <mime-type type="audio/3gpp"/>
+  <mime-type type="audio/3gpp2"/>
+  <mime-type type="audio/ac3"/>
+  <mime-type type="audio/adpcm">
+    <glob pattern="*.adp"/>
+  </mime-type>
+  <mime-type type="audio/amr"/>
+  <mime-type type="audio/amr-wb"/>
+  <mime-type type="audio/amr-wb+"/>
+  <mime-type type="audio/asc"/>
+
+  <mime-type type="audio/basic">
+    <magic priority="20">
+      <match value=".snd" type="string" offset="0">
+        <match value="1" type="big32" offset="12"/>
+        <match value="2" type="big32" offset="12"/>
+        <match value="3" type="big32" offset="12"/>
+        <match value="4" type="big32" offset="12"/>
+        <match value="5" type="big32" offset="12"/>
+        <match value="6" type="big32" offset="12"/>
+        <match value="7" type="big32" offset="12"/>
+      </match>
+    </magic>
+    <glob pattern="*.au"/>
+    <glob pattern="*.snd"/>
+  </mime-type>
+
+  <mime-type type="audio/bv16"/>
+  <mime-type type="audio/bv32"/>
+  <mime-type type="audio/clearmode"/>
+  <mime-type type="audio/cn"/>
+  <mime-type type="audio/dat12"/>
+  <mime-type type="audio/dls"/>
+  <mime-type type="audio/dsr-es201108"/>
+  <mime-type type="audio/dsr-es202050"/>
+  <mime-type type="audio/dsr-es202211"/>
+  <mime-type type="audio/dsr-es202212"/>
+  <mime-type type="audio/dvi4"/>
+  <mime-type type="audio/eac3"/>
+  <mime-type type="audio/evrc"/>
+  <mime-type type="audio/evrc-qcp"/>
+  <mime-type type="audio/evrc0"/>
+  <mime-type type="audio/evrc1"/>
+  <mime-type type="audio/evrcb"/>
+  <mime-type type="audio/evrcb0"/>
+  <mime-type type="audio/evrcb1"/>
+  <mime-type type="audio/evrcwb"/>
+  <mime-type type="audio/evrcwb0"/>
+  <mime-type type="audio/evrcwb1"/>
+  <mime-type type="audio/example"/>
+  <mime-type type="audio/g719"/>
+  <mime-type type="audio/g722"/>
+  <mime-type type="audio/g7221"/>
+  <mime-type type="audio/g723"/>
+  <mime-type type="audio/g726-16"/>
+  <mime-type type="audio/g726-24"/>
+  <mime-type type="audio/g726-32"/>
+  <mime-type type="audio/g726-40"/>
+  <mime-type type="audio/g728"/>
+  <mime-type type="audio/g729"/>
+  <mime-type type="audio/g7291"/>
+  <mime-type type="audio/g729d"/>
+  <mime-type type="audio/g729e"/>
+  <mime-type type="audio/gsm"/>
+  <mime-type type="audio/gsm-efr"/>
+  <mime-type type="audio/ilbc"/>
+  <mime-type type="audio/l16"/>
+  <mime-type type="audio/l20"/>
+  <mime-type type="audio/l24"/>
+  <mime-type type="audio/l8"/>
+  <mime-type type="audio/lpc"/>
+
+  <mime-type type="audio/midi">
+    <acronym>MIDI</acronym>
+    <_comment>Musical Instrument Digital Interface</_comment>
+    <magic priority ="20">
+      <match type="string" value="MThd" offset="0"/>
+    </magic>
+    <glob pattern="*.mid"/>
+    <glob pattern="*.midi"/>
+    <glob pattern="*.kar"/>
+    <glob pattern="*.rmi"/>
+  </mime-type>
+
+  <mime-type type="audio/mobile-xmf"/>
+  <mime-type type="audio/mp4">
+    <alias type="audio/x-mp4a"/>
+    <glob pattern="*.mp4a"/>
+  </mime-type>
+  <mime-type type="audio/mp4a-latm"/>
+  <mime-type type="audio/mpa"/>
+  <mime-type type="audio/mpa-robust"/>
+
+  <mime-type type="audio/mpeg">
+    <acronym>MP3</acronym>
+    <_comment>MPEG-1 Audio Layer 3</_comment>
+    <magic priority="20">
+      <!-- http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html -->
+      <!-- Bit pattern for first two bytes: 11111111 111VVLLC -->
+      <!-- VV = MPEG Audio Version ID; 10 = V2, 11 = V1 -->
+      <!-- LL = Layer description; 01 = L3, 10 = L2, 11 = L1 -->
+      <!-- C = Protection bit; 0 = CRC, 1 = no CRC -->
+      <match value="0xfff2" type="string" offset="0"/> <!-- V2, L3, CRC -->
+      <match value="0xfff3" type="string" offset="0"/> <!-- V2, L3 -->
+      <match value="0xfff4" type="string" offset="0"/> <!-- V2, L2, CRC -->
+      <match value="0xfff5" type="string" offset="0"/> <!-- V2, L2 -->
+      <match value="0xfff6" type="string" offset="0"/> <!-- V2, L1, CRC -->
+      <match value="0xfff7" type="string" offset="0"/> <!-- V2, L1 -->
+      <match value="0xfffa" type="string" offset="0"/> <!-- V1, L3, CRC -->
+      <match value="0xfffb" type="string" offset="0"/> <!-- V1, L3 -->
+      <match value="0xfffc" type="string" offset="0"/> <!-- V1, L2, CRC -->
+      <match value="0xfffd" type="string" offset="0"/> <!-- V1, L2 -->
+      <!-- TIKA-417: This is the UTF-16 LE byte order mark! -->
+      <!-- match value="0xfffe" type="string" offset="0"/ --> <!-- V1, L1, CRC -->
+      <match value="0xffff" type="string" offset="0"/> <!-- V1, L1 -->
+      <match value="ID3" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.mpga"/>
+    <glob pattern="*.mp2"/>
+    <glob pattern="*.mp2a"/>
+    <glob pattern="*.mp3"/>
+    <glob pattern="*.m2a"/>
+    <glob pattern="*.m3a"/>
+  </mime-type>
+
+  <mime-type type="audio/mpeg4-generic"/>
+
+  <mime-type type="audio/ogg">
+    <glob pattern="*.oga"/>
+    <glob pattern="*.ogg"/>
+    <glob pattern="*.spx"/>
+    <sub-class-of type="application/ogg"/>
+  </mime-type>
+
+  <mime-type type="audio/parityfec"/>
+  <mime-type type="audio/pcma"/>
+  <mime-type type="audio/pcma-wb"/>
+  <mime-type type="audio/pcmu-wb"/>
+  <mime-type type="audio/pcmu"/>
+
+  <mime-type type="audio/prs.sid">
+    <magic priority="50">
+      <match value="PSID" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="audio/qcelp"/>
+  <mime-type type="audio/red"/>
+  <mime-type type="audio/rtp-enc-aescm128"/>
+  <mime-type type="audio/rtp-midi"/>
+  <mime-type type="audio/rtx"/>
+  <mime-type type="audio/smv"/>
+  <mime-type type="audio/smv0"/>
+  <mime-type type="audio/smv-qcp"/>
+  <mime-type type="audio/sp-midi"/>
+  <mime-type type="audio/t140c"/>
+  <mime-type type="audio/t38"/>
+  <mime-type type="audio/telephone-event"/>
+  <mime-type type="audio/tone"/>
+  <mime-type type="audio/ulpfec"/>
+  <mime-type type="audio/vdvi"/>
+  <mime-type type="audio/vmr-wb"/>
+  <mime-type type="audio/vnd.3gpp.iufp"/>
+  <mime-type type="audio/vnd.4sb"/>
+  <mime-type type="audio/vnd.audiokoz"/>
+  <mime-type type="audio/vnd.celp"/>
+  <mime-type type="audio/vnd.cisco.nse"/>
+  <mime-type type="audio/vnd.cmles.radio-events"/>
+  <mime-type type="audio/vnd.cns.anp1"/>
+  <mime-type type="audio/vnd.cns.inf1"/>
+  <mime-type type="audio/vnd.digital-winds">
+    <glob pattern="*.eol"/>
+  </mime-type>
+  <mime-type type="audio/vnd.dlna.adts"/>
+  <mime-type type="audio/vnd.dolby.heaac.1"/>
+  <mime-type type="audio/vnd.dolby.heaac.2"/>
+  <mime-type type="audio/vnd.dolby.mlp"/>
+  <mime-type type="audio/vnd.dolby.mps"/>
+  <mime-type type="audio/vnd.dolby.pl2"/>
+  <mime-type type="audio/vnd.dolby.pl2x"/>
+  <mime-type type="audio/vnd.dolby.pl2z"/>
+  <mime-type type="audio/vnd.dts">
+    <glob pattern="*.dts"/>
+  </mime-type>
+  <mime-type type="audio/vnd.dts.hd">
+    <glob pattern="*.dtshd"/>
+  </mime-type>
+  <mime-type type="audio/vnd.everad.plj"/>
+  <mime-type type="audio/vnd.hns.audio"/>
+  <mime-type type="audio/vnd.lucent.voice">
+    <glob pattern="*.lvp"/>
+  </mime-type>
+  <mime-type type="audio/vnd.ms-playready.media.pya">
+    <glob pattern="*.pya"/>
+  </mime-type>
+  <mime-type type="audio/vnd.nokia.mobile-xmf"/>
+  <mime-type type="audio/vnd.nortel.vbk"/>
+  <mime-type type="audio/vnd.nuera.ecelp4800">
+    <glob pattern="*.ecelp4800"/>
+  </mime-type>
+  <mime-type type="audio/vnd.nuera.ecelp7470">
+    <glob pattern="*.ecelp7470"/>
+  </mime-type>
+  <mime-type type="audio/vnd.nuera.ecelp9600">
+    <glob pattern="*.ecelp9600"/>
+  </mime-type>
+  <mime-type type="audio/vnd.octel.sbc"/>
+  <mime-type type="audio/vnd.qcelp"/>
+  <mime-type type="audio/vnd.rhetorex.32kadpcm"/>
+  <mime-type type="audio/vnd.sealedmedia.softseal.mpeg"/>
+  <mime-type type="audio/vnd.vmx.cvsd"/>
+  <mime-type type="audio/vorbis"/>
+  <mime-type type="audio/vorbis-config"/>
+  <mime-type type="audio/x-aac">
+    <glob pattern="*.aac"/>
+  </mime-type>
+
+  <mime-type type="audio/x-adbcm">
+    <magic priority="20">
+      <match value=".snd" type="string" offset="0">
+        <match value="23" type="big32" offset="12"/>
+      </match>
+    </magic>
+  </mime-type>
+
+  <mime-type type="audio/x-aiff">
+    <alias type="audio/aiff"/>
+    <acronym>AIFF</acronym>
+    <_comment>Audio Interchange File Format</_comment>
+    <magic priority="20">
+      <match value="FORM....AIFF" type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+      <match value="FORM....AIFC" type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+      <!-- Amiga IFF sound sample, somewhat like the more modern AIFF -->
+      <match value="FORM....8SVX" type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+    </magic>
+    <glob pattern="*.aif"/>
+    <glob pattern="*.aiff"/>
+    <glob pattern="*.aifc"/>
+  </mime-type>
+
+  <mime-type type="audio/x-dec-basic">
+    <magic priority="20">
+      <match value="0x0064732E" type="big32" offset="0">
+        <match value="1" type="big32" offset="12"/>
+        <match value="2" type="big32" offset="12"/>
+        <match value="3" type="big32" offset="12"/>
+        <match value="4" type="big32" offset="12"/>
+        <match value="5" type="big32" offset="12"/>
+        <match value="6" type="big32" offset="12"/>
+        <match value="7" type="big32" offset="12"/>
+      </match>
+    </magic>
+  </mime-type>
+
+  <mime-type type="audio/x-dec-adbcm">
+    <magic priority="20">
+      <match value="0x0064732E" type="big32" offset="0">
+        <match value="23" type="big32" offset="12"/>
+      </match>
+    </magic>
+  </mime-type>
+
+  <mime-type type="audio/x-flac">
+    <acronym>FLAC</acronym>
+    <_comment>Free Lossless Audio Codec</_comment>
+    <magic priority="50">
+      <match value="fLaC" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.flac"/>
+  </mime-type>
+
+  <mime-type type="audio/x-mod">
+    <acronym>MOD</acronym>
+    <magic priority="50">
+      <match value="Extended\ Module:" type="string" offset="0"/>
+      <match value="BMOD2STM" type="string" offset="21"/>
+      <match value="M.K." type="string" offset="1080"/>
+      <match value="M!K!" type="string" offset="1080"/>
+      <match value="FLT4" type="string" offset="1080"/>
+      <match value="FLT8" type="string" offset="1080"/>
+      <match value="4CHN" type="string" offset="1080"/>
+      <match value="6CHN" type="string" offset="1080"/>
+      <match value="8CHN" type="string" offset="1080"/>
+      <match value="CD81" type="string" offset="1080"/>
+      <match value="OKTA" type="string" offset="1080"/>
+      <match value="16CN" type="string" offset="1080"/>
+      <match value="32CN" type="string" offset="1080"/>
+      <match value="IMPM" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.mod"/>
+  </mime-type>
+
+  <mime-type type="audio/x-mpegurl">
+    <glob pattern="*.m3u"/>
+  </mime-type>
+  <mime-type type="audio/x-ms-wax">
+    <glob pattern="*.wax"/>
+  </mime-type>
+  <mime-type type="audio/x-ms-wma">
+    <glob pattern="*.wma"/>
+  </mime-type>
+
+  <mime-type type="audio/x-pn-realaudio">
+    <_comment>Real Audio</_comment>
+    <alias type="audio/x-realaudio" />
+    <magic priority="50">
+      <match value="0x2e7261fd" type="big32" offset="0"/>
+    </magic>
+    <glob pattern="*.ram"/>
+    <glob pattern="*.ra"/>
+  </mime-type>
+
+  <mime-type type="audio/x-pn-realaudio-plugin">
+    <glob pattern="*.rmp"/>
+  </mime-type>
+
+  <mime-type type="audio/x-wav">
+    <acronym>WAV</acronym>
+    <magic priority="20">
+      <match value="RIFF....WAVE" type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+    </magic>
+    <glob pattern="*.wav"/>
+  </mime-type>
+
+  <mime-type type="chemical/x-cdx">
+    <glob pattern="*.cdx"/>
+  </mime-type>
+  <mime-type type="chemical/x-cif">
+    <glob pattern="*.cif"/>
+  </mime-type>
+  <mime-type type="chemical/x-cmdf">
+    <glob pattern="*.cmdf"/>
+  </mime-type>
+  <mime-type type="chemical/x-cml">
+    <glob pattern="*.cml"/>
+  </mime-type>
+  <mime-type type="chemical/x-csml">
+    <glob pattern="*.csml"/>
+  </mime-type>
+  <mime-type type="chemical/x-pdb"/>
+  <mime-type type="chemical/x-xyz">
+    <glob pattern="*.xyz"/>
+  </mime-type>
+
+  <mime-type type="image/bmp">
+    <alias type="image/x-ms-bmp"/>
+    <acronym>BMP</acronym>
+    <_comment>Windows bitmap</_comment>
+    <magic priority="50">
+      <match value="BM" type="string" offset="0" />
+    </magic>
+    <glob pattern="*.bmp"/>
+    <glob pattern="*.dib"/>
+  </mime-type>
+
+  <mime-type type="image/cgm">
+    <acronym>CGM</acronym>
+    <_comment>Computer Graphics Metafile</_comment>
+    <magic priority="50">
+      <match value="BEGMF" type="string" offset="0"/>
+      <match value="0x0020" mask="0xffe0" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.cgm"/>
+  </mime-type>
+
+  <mime-type type="image/example"/>
+  <mime-type type="image/fits"/>
+  <mime-type type="image/g3fax">
+    <glob pattern="*.g3"/>
+  </mime-type>
+
+  <mime-type type="image/gif">
+    <acronym>GIF</acronym>
+    <_comment>Graphics Interchange Format</_comment>
+    <magic priority="50">
+      <match value="GIF87a" type="string" offset="0"/>
+      <match value="GIF89a" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.gif"/>
+  </mime-type>
+
+  <mime-type type="image/ief">
+    <glob pattern="*.ief"/>
+  </mime-type>
+  <mime-type type="image/jp2"/>
+
+  <mime-type type="image/jpeg">
+    <acronym>JPEG</acronym>
+    <_comment>Joint Photographic Experts Group</_comment>
+    <magic priority="50">
+      <!-- FFD8 is the SOI (Start Of Image) marker. -->
+      <!-- It is followed by another marker that starts with FF. -->
+      <match value="0xffd8ff" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.jpg"/>
+    <glob pattern="*.jpeg"/>
+    <glob pattern="*.jpe"/>
+    <glob pattern="*.jif"/>
+    <glob pattern="*.jfif"/>
+    <glob pattern="*.jfi"/>
+  </mime-type>
+
+  <mime-type type="image/jpm"/>
+  <mime-type type="image/jpx"/>
+  <mime-type type="image/naplps"/>
+
+  <mime-type type="image/png">
+    <acronym>PNG</acronym>
+    <_comment>Portable Network Graphics</_comment>
+    <magic priority="50">
+      <match value="\x89PNG\x0d\x0a\x1a\x0a" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.png"/>
+  </mime-type>
+
+  <mime-type type="image/prs.btif">
+    <glob pattern="*.btif"/>
+  </mime-type>
+  <mime-type type="image/prs.pti"/>
+
+  <mime-type type="image/svg+xml">
+    <sub-class-of type="application/xml"/>
+    <acronym>SVG</acronym>
+    <_comment>Scalable Vector Graphics</_comment>
+    <root-XML localName="svg" namespaceURI="http://www.w3.org/2000/svg"/>
+    <glob pattern="*.svg"/>
+    <glob pattern="*.svgz"/>
+  </mime-type>
+
+  <mime-type type="image/t38"/>
+
+  <mime-type type="image/tiff">
+    <acronym>TIFF</acronym>
+    <_comment>Tagged Image File Format</_comment>
+    <magic priority="50">
+      <!-- MM.* = Big endian (M=Motorola) and 0x002a in big endian -->
+      <match value="MM\x00\x2a" type="string" offset="0"/>
+      <!-- II*. = Little endian (I=Intel) and 0x002a in little endian -->
+      <match value="II\x2a\x00" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.tiff"/>
+    <glob pattern="*.tif"/>
+  </mime-type>
+
+  <mime-type type="image/tiff-fx"/>
+
+  <mime-type type="image/vnd.adobe.photoshop">
+    <alias type="image/x-psd"/>
+    <glob pattern="*.psd"/>
+  </mime-type>
+
+  <mime-type type="image/vnd.cns.inf2"/>
+  <mime-type type="image/vnd.djvu">
+    <glob pattern="*.djvu"/>
+    <glob pattern="*.djv"/>
+  </mime-type>
+
+  <mime-type type="image/vnd.dwg">
+    <acronym>DWG</acronym>
+    <_comment>AutoCad Drawing</_comment>
+    <alias type="image/x-dwg"/>
+    <alias type="application/acad"/>
+    <alias type="application/x-acad"/>
+    <alias type="application/autocad_dwg"/>
+    <alias type="application/dwg"/>
+    <alias type="application/x-dwg"/>
+    <alias type="application/x-autocad"/>
+    <glob pattern="*.dwg"/>
+    <magic priority="50">
+      <!-- "AC" followed by four numbers -->
+      <match value="AC0000" type="string" offset="0"
+             mask="0xFFFFF0F0F0F0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="image/vnd.dxf">
+    <glob pattern="*.dxf"/>
+  </mime-type>
+  <mime-type type="image/vnd.fastbidsheet">
+    <glob pattern="*.fbs"/>
+  </mime-type>
+  <mime-type type="image/vnd.fpx">
+    <glob pattern="*.fpx"/>
+  </mime-type>
+  <mime-type type="image/vnd.fst">
+    <glob pattern="*.fst"/>
+  </mime-type>
+  <mime-type type="image/vnd.fujixerox.edmics-mmr">
+    <glob pattern="*.mmr"/>
+  </mime-type>
+  <mime-type type="image/vnd.fujixerox.edmics-rlc">
+    <glob pattern="*.rlc"/>
+  </mime-type>
+  <mime-type type="image/vnd.globalgraphics.pgb"/>
+  <mime-type type="image/vnd.microsoft.icon"/>
+  <mime-type type="image/vnd.mix"/>
+  <mime-type type="image/vnd.ms-modi">
+    <glob pattern="*.mdi"/>
+  </mime-type>
+  <mime-type type="image/vnd.net-fpx">
+    <glob pattern="*.npx"/>
+  </mime-type>
+  <mime-type type="image/vnd.radiance"/>
+  <mime-type type="image/vnd.sealed.png"/>
+  <mime-type type="image/vnd.sealedmedia.softseal.gif"/>
+  <mime-type type="image/vnd.sealedmedia.softseal.jpg"/>
+  <mime-type type="image/vnd.svf"/>
+
+  <mime-type type="image/vnd.wap.wbmp">
+    <_comment>Wireless Bitmap File Format</_comment>
+    <glob pattern="*.wbmp"/>
+  </mime-type>
+
+  <mime-type type="image/vnd.xiff">
+    <glob pattern="*.xif"/>
+  </mime-type>
+  <mime-type type="image/x-cmu-raster">
+    <glob pattern="*.ras"/>
+  </mime-type>
+  <mime-type type="image/x-cmx">
+    <glob pattern="*.cmx"/>
+  </mime-type>
+  <mime-type type="image/x-freehand">
+    <glob pattern="*.fh"/>
+    <glob pattern="*.fhc"/>
+    <glob pattern="*.fh4"/>
+    <glob pattern="*.fh5"/>
+    <glob pattern="*.fh7"/>
+  </mime-type>
+
+  <mime-type type="image/x-icon">
+    <magic priority="50">
+      <match value="\102\101\050\000\000\000\056\000\000\000\000\000\000\000"
+             type="string" offset="0"/>
+      <match value="\000\000\001\000" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.ico"/>
+  </mime-type>
+
+  <mime-type type="image/x-niff">
+    <_comment>Navy Interchange File Format</_comment>
+    <magic priority="50">
+      <match value="IIN1" type="string" offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="image/x-pcx">
+    <glob pattern="*.pcx"/>
+  </mime-type>
+  <mime-type type="image/x-pict">
+    <glob pattern="*.pic"/>
+    <glob pattern="*.pct"/>
+  </mime-type>
+
+  <mime-type type="image/x-portable-anymap">
+    <acronym>PNM</acronym>
+    <_comment>Portable Any Map</_comment>
+    <glob pattern="*.pnm" />
+  </mime-type>
+
+  <mime-type type="image/x-portable-bitmap">
+    <sub-class-of type="image/x-portable-anymap"/>
+    <acronym>PBM</acronym>
+    <_comment>Portable Bit Map</_comment>
+    <magic priority="50">
+      <match value="P1" type="string" offset="0"/>
+      <match value="P4" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.pbm"/>
+  </mime-type>
+
+  <mime-type type="image/x-portable-graymap">
+    <sub-class-of type="image/x-portable-anymap"/>
+    <acronym>PGM</acronym>
+    <_comment>Portable Gray Map</_comment>
+    <magic priority="50">
+      <match value="P2" type="string" offset="0"/>
+      <match value="P5" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.pgm"/>
+  </mime-type>
+
+  <mime-type type="image/x-portable-pixmap">
+    <sub-class-of type="image/x-portable-anymap"/>
+    <acronym>PXM</acronym>
+    <_comment>Portable Pixel Map</_comment>
+    <magic priority="50">
+      <match value="P3" type="string" offset="0"/>
+      <match value="P6" type="string" offset="0"/>
+      <match value="P7" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.ppm"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-adobe">
+    <acronym>DNG</acronym>
+    <_comment>Adobe Digital Negative</_comment>
+    <glob pattern="*.dng"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-hasselblad">
+    <_comment>Hasselblad raw image</_comment>
+    <glob pattern="*.3fr"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-fuji">
+    <_comment>Fuji raw image</_comment>
+    <glob pattern="*.raf"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-canon">
+    <_comment>Canon raw image</_comment>
+    <glob pattern="*.crw"/>
+    <glob pattern="*.cr2"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-kodak">
+    <_comment>Kodak raw image</_comment>
+    <glob pattern="*.k25"/>
+    <glob pattern="*.kdc"/>
+    <glob pattern="*.dcs"/>
+    <glob pattern="*.drf"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-minolta">
+    <_comment>Minolta raw image</_comment>
+    <glob pattern="*.mrw"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-nikon">
+    <_comment>Nikon raw image</_comment>
+    <glob pattern="*.nef"/>
+    <glob pattern="*.nrw"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-olympus">
+    <_comment>Olympus raw image</_comment>
+    <glob pattern="*.orf"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-pentax">
+    <_comment>Pentax raw image</_comment>
+    <glob pattern="*.ptx"/>
+    <glob pattern="*.pef"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-sony">
+    <_comment>Sony raw image</_comment>
+    <glob pattern="*.arw"/>
+    <glob pattern="*.srf"/>
+    <glob pattern="*.sr2"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-sigma">
+    <_comment>Sigma raw image</_comment>
+    <glob pattern="*.x3f"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-epson">
+    <_comment>Epson raw image</_comment>
+    <glob pattern="*.erf"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-mamiya">
+    <_comment>Mamiya raw image</_comment>
+    <glob pattern="*.mef"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-leaf">
+    <_comment>Leaf raw image</_comment>
+    <glob pattern="*.mos"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-panasonic">
+    <_comment>Panasonic raw image</_comment>
+    <glob pattern="*.raw"/>
+    <glob pattern="*.rw2"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-phaseone">
+    <_comment>Phase One raw image</_comment>
+    <glob pattern="*.cap"/>
+    <glob pattern="*.iiq"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-red">
+    <_comment>Red raw image</_comment>
+    <glob pattern="*.r3d"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-imacon">
+    <_comment>Imacon raw image</_comment>
+    <glob pattern="*.fff"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-logitech">
+    <_comment>Logitech raw image</_comment>
+    <glob pattern="*.pxn"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-casio">
+    <_comment>Casio raw image</_comment>
+    <glob pattern="*.bay"/>
+  </mime-type>
+
+  <mime-type type="image/x-raw-rawzor">
+    <_comment>Rawzor raw image</_comment>
+    <glob pattern="*.rwz"/>
+  </mime-type>
+
+  <mime-type type="image/x-rgb">
+    <glob pattern="*.rgb"/>
+  </mime-type>
+
+  <mime-type type="image/x-xbitmap">
+    <magic priority="50">
+      <match value="/* XPM" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.xbm"/>
+    <sub-class-of type="text/x-c"/>
+  </mime-type>
+
+  <mime-type type="image/x-xcf">
+    <alias type="image/xcf"/>
+    <magic priority="50">
+      <match type="string" value="gimp xcf " offset="0"/>
+    </magic>
+  </mime-type>
+
+  <mime-type type="image/x-xpixmap">
+    <glob pattern="*.xpm"/>
+  </mime-type>
+  <mime-type type="image/x-xwindowdump">
+    <glob pattern="*.xwd"/>
+  </mime-type>
+
+  <mime-type type="message/cpim"/>
+  <mime-type type="message/delivery-status"/>
+  <mime-type type="message/disposition-notification"/>
+  <mime-type type="message/example"/>
+  <mime-type type="message/external-body"/>
+  <mime-type type="message/global"/>
+  <mime-type type="message/global-delivery-status"/>
+  <mime-type type="message/global-disposition-notification"/>
+  <mime-type type="message/global-headers"/>
+  <mime-type type="message/http"/>
+  <mime-type type="message/imdn+xml"/>
+
+  <mime-type type="message/news">
+    <magic priority="50">
+      <match value="Path:" type="string" offset="0" />
+      <match value="Xref:" type="string" offset="0" />
+      <match value="Article" type="string" offset="0" />
+    </magic>
+  </mime-type>
+
+  <mime-type type="message/partial"/>
+
+  <mime-type type="message/rfc822">
+    <magic priority="50">
+      <match value="Relay-Version:" type="string" offset="0"/>
+      <match value="#!\ rnews" type="string" offset="0"/>
+      <match value="N#!\ rnews" type="string" offset="0"/>
+      <match value="Forward\ to" type="string" offset="0"/>
+      <match value="Pipe\ to" type="string" offset="0"/>
+      <match value="Return-Path:" type="string" offset="0"/>
+      <match value="From:" type="string" offset="0"/>
+      <match value="Received:" type="string" offset="0"/>
+      <match type="string" value="Message-ID:" offset="0"/>
+      <match type="string" value="Date:" offset="0"/>
+    </magic>
+    <glob pattern="*.eml"/>
+    <glob pattern="*.mime"/>
+  </mime-type>
+
+  <mime-type type="message/s-http"/>
+  <mime-type type="message/sip"/>
+  <mime-type type="message/sipfrag"/>
+  <mime-type type="message/tracking-status"/>
+  <mime-type type="message/vnd.si.simp"/>
+
+  <mime-type type="model/example"/>
+
+  <mime-type type="model/iges">
+    <_comment>Initial Graphics Exchange Specification Format</_comment>
+    <glob pattern="*.igs"/>
+    <glob pattern="*.iges"/>
+  </mime-type>
+
+  <mime-type type="model/mesh">
+    <glob pattern="*.msh"/>
+    <glob pattern="*.mesh"/>
+    <glob pattern="*.silo"/>
+  </mime-type>
+
+  <mime-type type="model/vnd.dwf">
+    <glob pattern="*.dwf"/>
+  </mime-type>
+  <mime-type type="model/vnd.flatland.3dml"/>
+  <mime-type type="model/vnd.gdl">
+    <glob pattern="*.gdl"/>
+  </mime-type>
+  <mime-type type="model/vnd.gs-gdl"/>
+  <mime-type type="model/vnd.gs.gdl"/>
+  <mime-type type="model/vnd.gtw">
+    <glob pattern="*.gtw"/>
+  </mime-type>
+  <mime-type type="model/vnd.moml+xml"/>
+  <mime-type type="model/vnd.mts">
+    <glob pattern="*.mts"/>
+  </mime-type>
+  <mime-type type="model/vnd.parasolid.transmit.binary"/>
+  <mime-type type="model/vnd.parasolid.transmit.text"/>
+  <mime-type type="model/vnd.vtu">
+    <glob pattern="*.vtu"/>
+  </mime-type>
+
+  <mime-type type="model/vrml">
+    <glob pattern="*.wrl"/>
+    <glob pattern="*.vrml"/>
+  </mime-type>
+
+  <mime-type type="multipart/alternative"/>
+  <mime-type type="multipart/appledouble"/>
+  <mime-type type="multipart/byteranges"/>
+  <mime-type type="multipart/digest"/>
+  <mime-type type="multipart/encrypted"/>
+  <mime-type type="multipart/example"/>
+  <mime-type type="multipart/form-data"/>
+  <mime-type type="multipart/header-set"/>
+  <mime-type type="multipart/mixed"/>
+  <mime-type type="multipart/parallel"/>
+  <mime-type type="multipart/related"/>
+  <mime-type type="multipart/report"/>
+  <mime-type type="multipart/signed"/>
+  <mime-type type="multipart/voice-message"/>
+  <mime-type type="text/calendar">
+    <glob pattern="*.ics"/>
+    <glob pattern="*.ifb"/>
+  </mime-type>
+
+  <mime-type type="text/css">
+    <_comment>Cascading Style Sheet</_comment>
+    <glob pattern="*.css"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="text/csv">
+    <glob pattern="*.csv"/>
+  </mime-type>
+  <mime-type type="text/directory"/>
+  <mime-type type="text/dns"/>
+  <mime-type type="text/ecmascript"/>
+  <mime-type type="text/enriched"/>
+  <mime-type type="text/example"/>
+
+  <mime-type type="text/html">
+     <!-- TIKA-327: if you encounter tags in the HTML
+          with no declared namespace, it's not XHTML, it's just
+          bad HTML, unfortunately.
+     -->
+    <root-XML localName="html"/>
+    <root-XML localName="HTML"/>
+    <root-XML localName="link"/>
+    <root-XML localName="LINK"/>
+    <root-XML localName="body"/>
+    <root-XML localName="BODY"/>
+    <root-XML localName="p"/>
+    <root-XML localName="P"/>
+    <root-XML localName="script"/>
+    <root-XML localName="SCRIPT"/>
+    <root-XML localName="frameset"/>
+    <root-XML localName="FRAMESET"/>
+    <magic priority="50">
+      <match value="&lt;!DOCTYPE HTML" type="string" offset="0:64"/>
+      <match value="&lt;!doctype html" type="string" offset="0:64"/>
+      <match value="&lt;HEAD" type="string" offset="0:64"/>
+      <match value="&lt;head" type="string" offset="0:64"/>
+      <match value="&lt;TITLE" type="string" offset="0:64"/>
+      <match value="&lt;title" type="string" offset="0:64"/>
+      <!-- note on the offset value here: this can only be as big as
+           MimeTypes#getMinLength(). If you set the offset value to larger
+           than that size, the magic will only be compared to up to
+           MimeTypes#getMinLength() bytes.
+       -->
+      <match value="&lt;html" type="string" offset="0:8192"/>
+      <match value="&lt;HTML" type="string" offset="0:64"/>
+      <match value="&lt;BODY" type="string" offset="0"/>
+      <match value="&lt;body" type="string" offset="0"/>
+      <match value="&lt;TITLE" type="string" offset="0"/>
+      <match value="&lt;title" type="string" offset="0"/>
+      <match value="&lt;h1" type="string" offset="0"/>
+      <match value="&lt;H1" type="string" offset="0"/>
+      <match value="&lt;!doctype HTML" type="string" offset="0"/>
+      <match value="&lt;!DOCTYPE html" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.html"/>
+    <glob pattern="*.htm"/>
+  </mime-type>
+
+  <mime-type type="text/javascript"/>
+  <mime-type type="text/parityfec"/>
+
+  <mime-type type="text/plain">
+    <magic priority="20">
+      <match value="This is TeX," type="string" offset="0"/>
+      <match value="This is METAFONT," type="string" offset="0"/>
+      <match value="/*" type="string" offset="0"/>
+      <match value="//" type="string" offset="0"/>
+      <match value=";;" type="string" offset="0"/>
+      <!-- UTF-16BE BOM -->
+      <match value="0xfeff" type="string" offset="0"/>
+      <!-- UTF-16LE BOM -->
+      <match value="0xfffe" type="string" offset="0"/>
+      <!-- UTF-8 BOM -->
+      <match value="0xefbbbf" type="string" offset="0"/>
+    </magic>
+
+    <glob pattern="*.txt"/>
+    <glob pattern="*.text"/>
+    <glob pattern="*.conf"/>
+    <glob pattern="*.def"/>
+    <glob pattern="*.list"/>
+    <glob pattern="*.log"/>
+    <glob pattern="*.in"/>
+
+    <!-- TIKA-85: http://www.apache.org/dev/svn-eol-style.txt -->
+    <glob pattern="INSTALL"/>
+    <glob pattern="KEYS"/>
+    <glob pattern="Makefile"/>
+    <glob pattern="README"/>
+    <glob pattern="abs-linkmap"/>
+    <glob pattern="abs-menulinks"/>
+    <glob pattern="*.aart"/>
+    <glob pattern="*.ac"/>
+    <glob pattern="*.am"/>
+    <glob pattern="*.cgi"/>
+    <glob pattern="*.classpath"/>
+    <glob pattern="*.cmd"/>
+    <glob pattern="*.config"/>
+    <glob pattern="*.cwiki"/>
+    <glob pattern="*.data"/>
+    <glob pattern="*.dcl"/>
+    <glob pattern="*.egrm"/>
+    <glob pattern="*.ent"/>
+    <glob pattern="*.ft"/>
+    <glob pattern="*.fn"/>
+    <glob pattern="*.fv"/>
+    <glob pattern="*.grm"/>
+    <glob pattern="*.g"/>
+    <glob pattern=".htaccess"/>
+    <glob pattern="*.ihtml"/>
+    <glob pattern="*.jmx"/>
+    <glob pattern="*.jsp"/>
+    <glob pattern="*.junit"/>
+    <glob pattern="*.jx"/>
+    <glob pattern="*.manifest"/>
+    <glob pattern="*.m4"/>
+    <glob pattern="*.mf"/>
+    <glob pattern="*.MF"/>
+    <glob pattern="*.meta"/>
+    <glob pattern="*.n3"/>
+    <glob pattern="*.pen"/>
+    <glob pattern="*.pl"/>
+    <glob pattern="*.pm"/>
+    <glob pattern="*.pod"/>
+    <glob pattern="*.pom"/>
+    <glob pattern="*.project"/>
+    <glob pattern="*.properties"/>
+    <glob pattern="*.py"/>
+    <glob pattern="*.rb"/>
+    <glob pattern="*.rng"/>
+    <glob pattern="*.rnx"/>
+    <glob pattern="*.roles"/>
+    <glob pattern="*.sql"/>
+    <glob pattern="*.tld"/>
+    <glob pattern="*.types"/>
+    <glob pattern="*.vm"/>
+    <glob pattern="*.vsl"/>
+    <glob pattern="*.wsdd"/>
+    <glob pattern="*.xargs"/>
+    <glob pattern="*.xcat"/>
+    <glob pattern="*.xconf"/>
+    <glob pattern="*.xegrm"/>
+    <glob pattern="*.xgrm"/>
+    <glob pattern="*.xlex"/>
+    <glob pattern="*.xlog"/>
+    <glob pattern="*.xmap"/>
+    <glob pattern="*.xroles"/>
+    <glob pattern="*.xsamples"/>
+    <glob pattern="*.xsp"/>
+    <glob pattern="*.xweb"/>
+    <glob pattern="*.xwelcome"/>
+  </mime-type>
+
+  <mime-type type="text/prs.fallenstein.rst"/>
+  <mime-type type="text/prs.lines.tag">
+    <glob pattern="*.dsc"/>
+  </mime-type>
+  <mime-type type="text/red"/>
+  <mime-type type="text/rfc822-headers"/>
+  <mime-type type="text/richtext">
+    <glob pattern="*.rtx"/>
+  </mime-type>
+  <mime-type type="text/rtf"/>
+  <mime-type type="text/rtp-enc-aescm128"/>
+  <mime-type type="text/rtx"/>
+  <mime-type type="text/sgml">
+    <glob pattern="*.sgml"/>
+    <glob pattern="*.sgm"/>
+  </mime-type>
+  <mime-type type="text/t140"/>
+  <mime-type type="text/tab-separated-values">
+    <glob pattern="*.tsv"/>
+  </mime-type>
+
+  <mime-type type="text/troff">
+    <alias type="application/x-troff"/>
+    <alias type="application/x-troff-man"/>
+    <alias type="application/x-troff-me"/>
+    <alias type="application/x-troff-ms"/>
+    <magic priority="50">
+      <match value=".\\&quot;" type="string" offset="0"/>
+      <match value="'\\&quot;" type="string" offset="0"/>
+      <match value="'.\\&quot;" type="string" offset="0"/>
+      <match value="\\&quot;" type="string" offset="0"/>
+      <match value="'''" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.t"/>
+    <glob pattern="*.tr"/>
+    <glob pattern="*.roff"/>
+    <glob pattern="*.man"/>
+    <glob pattern="*.me"/>
+    <glob pattern="*.ms"/>
+  </mime-type>
+
+  <mime-type type="text/ulpfec"/>
+  <mime-type type="text/uri-list">
+    <glob pattern="*.uri"/>
+    <glob pattern="*.uris"/>
+    <glob pattern="*.urls"/>
+  </mime-type>
+  <mime-type type="text/vnd.abc"/>
+  <mime-type type="text/vnd.curl">
+    <glob pattern="*.curl"/>
+  </mime-type>
+  <mime-type type="text/vnd.curl.dcurl">
+    <glob pattern="*.dcurl"/>
+  </mime-type>
+  <mime-type type="text/vnd.curl.scurl">
+    <glob pattern="*.scurl"/>
+  </mime-type>
+  <mime-type type="text/vnd.curl.mcurl">
+    <glob pattern="*.mcurl"/>
+  </mime-type>
+  <mime-type type="text/vnd.dmclientscript"/>
+  <mime-type type="text/vnd.esmertec.theme-descriptor"/>
+  <mime-type type="text/vnd.fly">
+    <glob pattern="*.fly"/>
+  </mime-type>
+  <mime-type type="text/vnd.fmi.flexstor">
+    <glob pattern="*.flx"/>
+  </mime-type>
+  <mime-type type="text/vnd.graphviz">
+    <glob pattern="*.gv"/>
+  </mime-type>
+  <mime-type type="text/vnd.in3d.3dml">
+    <glob pattern="*.3dml"/>
+  </mime-type>
+  <mime-type type="text/vnd.in3d.spot">
+    <glob pattern="*.spot"/>
+  </mime-type>
+  <mime-type type="text/vnd.iptc.newsml"/>
+  <mime-type type="text/vnd.iptc.nitf"/>
+  <mime-type type="text/vnd.latex-z"/>
+  <mime-type type="text/vnd.motorola.reflex"/>
+  <mime-type type="text/vnd.ms-mediapackage"/>
+  <mime-type type="text/vnd.net2phone.commcenter.command"/>
+  <mime-type type="text/vnd.si.uricatalogue"/>
+  <mime-type type="text/vnd.sun.j2me.app-descriptor">
+    <glob pattern="*.jad"/>
+  </mime-type>
+  <mime-type type="text/vnd.trolltech.linguist"/>
+  <mime-type type="text/vnd.wap.si"/>
+  <mime-type type="text/vnd.wap.sl"/>
+  <mime-type type="text/vnd.wap.wml">
+    <glob pattern="*.wml"/>
+  </mime-type>
+
+  <mime-type type="text/vnd.wap.wmlscript">
+    <_comment>WML Script</_comment>
+    <glob pattern="*.wmls"/>
+  </mime-type>
+
+  <mime-type type="text/x-asm">
+    <glob pattern="*.s"/>
+    <glob pattern="*.asm"/>
+  </mime-type>
+
+  <mime-type type="text/x-c">
+    <glob pattern="*.c"/>
+    <glob pattern="*.cc"/>
+    <glob pattern="*.cxx"/>
+    <glob pattern="*.cpp"/>
+    <glob pattern="*.h"/>
+    <glob pattern="*.hh"/>
+    <glob pattern="*.dic"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="text/x-diff">
+    <magic priority="50">
+      <match value="diff\ " type="string" offset="0"/>
+      <match value="***\ " type="string" offset="0"/>
+      <match value="Only\ in\ " type="string" offset="0"/>
+      <match value="Common\ subdirectories:\ " type="string" offset="0"/>
+      <match value="Index:" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.diff"/>
+    <glob pattern="*.patch"/>
+  </mime-type>
+
+  <mime-type type="text/x-fortran">
+    <glob pattern="*.f"/>
+    <glob pattern="*.for"/>
+    <glob pattern="*.f77"/>
+    <glob pattern="*.f90"/>
+  </mime-type>
+  <mime-type type="text/x-pascal">
+    <glob pattern="*.p"/>
+    <glob pattern="*.pas"/>
+  </mime-type>
+
+  <mime-type type="text/x-java-source">
+    <glob pattern="*.java"/>
+    <sub-class-of type="text/plain"/>
+  </mime-type>
+
+  <mime-type type="text/x-setext">
+    <glob pattern="*.etx"/>
+  </mime-type>
+
+  <mime-type type="text/x-uuencode">
+    <glob pattern="*.uu"/>
+  </mime-type>
+  <mime-type type="text/x-vcalendar">
+    <glob pattern="*.vcs"/>
+  </mime-type>
+  <mime-type type="text/x-vcard">
+    <glob pattern="*.vcf"/>
+  </mime-type>
+  <mime-type type="text/xml"/>
+  <mime-type type="text/xml-external-parsed-entity"/>
+  <mime-type type="video/3gpp">
+    <glob pattern="*.3gp"/>
+  </mime-type>
+  <mime-type type="video/3gpp-tt"/>
+  <mime-type type="video/3gpp2">
+    <glob pattern="*.3g2"/>
+  </mime-type>
+  <mime-type type="video/bmpeg"/>
+  <mime-type type="video/bt656"/>
+  <mime-type type="video/celb"/>
+  <mime-type type="video/dv"/>
+  <mime-type type="video/example"/>
+  <mime-type type="video/h261">
+    <glob pattern="*.h261"/>
+  </mime-type>
+  <mime-type type="video/h263">
+    <glob pattern="*.h263"/>
+  </mime-type>
+  <mime-type type="video/h263-1998"/>
+  <mime-type type="video/h263-2000"/>
+  <mime-type type="video/h264">
+    <glob pattern="*.h264"/>
+  </mime-type>
+  <mime-type type="video/jpeg">
+    <glob pattern="*.jpgv"/>
+  </mime-type>
+  <mime-type type="video/jpeg2000"/>
+  <mime-type type="video/jpm">
+    <glob pattern="*.jpm"/>
+    <glob pattern="*.jpgm"/>
+  </mime-type>
+  <mime-type type="video/mj2">
+    <glob pattern="*.mj2"/>
+    <glob pattern="*.mjp2"/>
+  </mime-type>
+  <mime-type type="video/mp1s"/>
+  <mime-type type="video/mp2p"/>
+  <mime-type type="video/mp2t"/>
+  <mime-type type="video/mp4">
+    <glob pattern="*.mp4"/>
+    <glob pattern="*.mp4v"/>
+    <glob pattern="*.mpg4"/>
+  </mime-type>
+  <mime-type type="video/mp4v-es"/>
+
+  <mime-type type="video/mpeg">
+    <magic priority="50">
+      <match value="\000\000\001\263" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.mpeg"/>
+    <glob pattern="*.mpg"/>
+    <glob pattern="*.mpe"/>
+    <glob pattern="*.m1v"/>
+    <glob pattern="*.m2v"/>
+  </mime-type>
+
+  <mime-type type="video/vnd.mpegurl">
+    <glob pattern="*.mxu"/>
+  </mime-type>
+
+  <mime-type type="video/mpeg4-generic"/>
+  <mime-type type="video/mpv"/>
+  <mime-type type="video/nv"/>
+
+  <mime-type type="video/ogg">
+    <glob pattern="*.ogv"/>
+    <sub-class-of type="application/ogg"/>
+  </mime-type>
+
+  <mime-type type="video/parityfec"/>
+  <mime-type type="video/pointer"/>
+
+  <mime-type type="video/quicktime">
+    <magic priority="50">
+      <match value="moov" type="string" offset="4"/>
+      <match value="mdat" type="string" offset="4"/>
+      <match value="ftyp" type="string" offset="4"/>
+    </magic>
+    <glob pattern="*.qt"/>
+    <glob pattern="*.mov"/>
+  </mime-type>
+
+  <mime-type type="video/raw"/>
+  <mime-type type="video/rtp-enc-aescm128"/>
+  <mime-type type="video/rtx"/>
+  <mime-type type="video/smpte292m"/>
+  <mime-type type="video/ulpfec"/>
+  <mime-type type="video/vc1"/>
+  <mime-type type="video/vnd.cctv"/>
+  <mime-type type="video/vnd.dlna.mpeg-tts"/>
+  <mime-type type="video/vnd.fvt">
+    <glob pattern="*.fvt"/>
+  </mime-type>
+  <mime-type type="video/vnd.hns.video"/>
+  <mime-type type="video/vnd.iptvforum.1dparityfec-1010"/>
+  <mime-type type="video/vnd.iptvforum.1dparityfec-2005"/>
+  <mime-type type="video/vnd.iptvforum.2dparityfec-1010"/>
+  <mime-type type="video/vnd.iptvforum.2dparityfec-2005"/>
+  <mime-type type="video/vnd.iptvforum.ttsavc"/>
+  <mime-type type="video/vnd.iptvforum.ttsmpeg2"/>
+  <mime-type type="video/vnd.motorola.video"/>
+  <mime-type type="video/vnd.motorola.videop"/>
+  <mime-type type="video/vnd.mpegurl">
+    <glob pattern="*.mxu"/>
+    <glob pattern="*.m4u"/>
+  </mime-type>
+  <mime-type type="video/vnd.ms-playready.media.pyv">
+    <glob pattern="*.pyv"/>
+  </mime-type>
+  <mime-type type="video/vnd.nokia.interleaved-multimedia"/>
+  <mime-type type="video/vnd.nokia.videovoip"/>
+  <mime-type type="video/vnd.objectvideo"/>
+  <mime-type type="video/vnd.sealed.mpeg1"/>
+  <mime-type type="video/vnd.sealed.mpeg4"/>
+  <mime-type type="video/vnd.sealed.swf"/>
+  <mime-type type="video/vnd.sealedmedia.softseal.mov"/>
+  <mime-type type="video/vnd.vivo">
+    <glob pattern="*.viv"/>
+  </mime-type>
+  <mime-type type="video/x-f4v">
+    <glob pattern="*.f4v"/>
+  </mime-type>
+
+  <mime-type type="video/x-flc">
+    <glob pattern="*.flc"/>
+  </mime-type>
+
+  <mime-type type="video/x-fli">
+    <glob pattern="*.fli"/>
+  </mime-type>
+
+  <mime-type type="video/x-flv">
+    <magic priority="50">
+      <match value="FLV" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.flv"/>
+  </mime-type>
+
+  <mime-type type="video/x-jng">
+    <magic priority="50">
+      <match value="\x8bJNG" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.jng"/>
+  </mime-type>
+
+  <mime-type type="video/x-m4v">
+    <glob pattern="*.m4v"/>
+  </mime-type>
+
+  <mime-type type="video/x-mng">
+    <magic priority="50">
+      <match value="\x8aMNG" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.mng"/>
+  </mime-type>
+
+  <mime-type type="video/x-ms-asf">
+    <glob pattern="*.asf"/>
+    <glob pattern="*.asx"/>
+  </mime-type>
+  <mime-type type="video/x-ms-wm">
+    <glob pattern="*.wm"/>
+  </mime-type>
+  <mime-type type="video/x-ms-wmv">
+    <glob pattern="*.wmv"/>
+  </mime-type>
+  <mime-type type="video/x-ms-wmx">
+    <glob pattern="*.wmx"/>
+  </mime-type>
+  <mime-type type="video/x-ms-wvx">
+    <glob pattern="*.wvx"/>
+  </mime-type>
+
+  <mime-type type="video/x-msvideo">
+    <alias type="video/avi"/>
+    <alias type="video/msvideo"/>
+    <magic priority="50">
+      <match value="RIFF....AVI " type="string" offset="0"
+             mask="0xFFFFFFFF00000000FFFFFFFF"/>
+    </magic>
+    <glob pattern="*.avi"/>
+  </mime-type>
+
+  <mime-type type="video/x-sgi-movie">
+    <magic priority="50">
+      <match value="MOVI" type="string" offset="0"/>
+    </magic>
+    <glob pattern="*.movie"/>
+  </mime-type>
+
+  <mime-type type="x-conference/x-cooltalk">
+    <_comment>Cooltalk Audio</_comment>
+    <glob pattern="*.ice"/>
+  </mime-type>
+
+</mime-info>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/logs/REMOVE.log b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/logs/REMOVE.log
new file mode 100644
index 0000000..eecee37
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/logs/REMOVE.log
@@ -0,0 +1,20 @@
+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.
+
+
+You can remove this file. It was only included to ensure that the log directory for this
+distribution was created on assembly.
+
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/cmd-line-actions.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/cmd-line-actions.xml
new file mode 100644
index 0000000..cf66c9d
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/cmd-line-actions.xml
@@ -0,0 +1,123 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+    <bean id="addProductType" class="org.apache.oodt.cas.filemgr.cli.action.AddProductTypeCliAction">
+        <property name="description" value="Adds a ProductType to list of supported ProductTypes" />
+    </bean>
+  <bean id="deleteProductByName" class="org.apache.oodt.cas.filemgr.cli.action.DeleteProductByNameCliAction">
+    <property name="description" value="Delete Product by name" />
+  </bean>
+  <bean id="deleteProductById" class="org.apache.oodt.cas.filemgr.cli.action.DeleteProductByIdCliAction">
+    <property name="description" value="Delete Product by ID" />
+  </bean>
+  <bean id="dumpMetadata" class="org.apache.oodt.cas.filemgr.cli.action.DumpMetadataCliAction">
+    <property name="description" value="Dumps Product Metadata out to XML" />
+  </bean>
+    <bean id="getCurrentTransfer" class="org.apache.oodt.cas.filemgr.cli.action.GetCurrentTransferCliAction">
+    <property name="description" value="Gets the status of the current Product file transfer" />
+  </bean>
+  <bean id="getCurrentTransfers" class="org.apache.oodt.cas.filemgr.cli.action.GetCurrentTransfersCliAction">
+    <property name="description" value="Gets the status of the current Product file transfers" />
+  </bean>
+  <bean id="getFilePercentTransferred" class="org.apache.oodt.cas.filemgr.cli.action.GetFilePercentTransferredCliAction">
+    <property name="description" value="Gets the percent amount transferred of given file" />
+  </bean>
+  <bean id="getFirstPage" class="org.apache.oodt.cas.filemgr.cli.action.GetFirstPageCliAction">
+    <property name="description" value="Gets first page of Products of given ProductType" />
+  </bean>
+  <bean id="getLastPage" class="org.apache.oodt.cas.filemgr.cli.action.GetLastPageCliAction">
+    <property name="description" value="Gets last page of Products of given ProductType" />
+  </bean>
+  <bean id="getNextPage" class="org.apache.oodt.cas.filemgr.cli.action.GetNextPageCliAction">
+    <property name="description" value="Gets next page of Products of given ProductType" />
+  </bean>
+  <bean id="getNumProducts" class="org.apache.oodt.cas.filemgr.cli.action.GetNumProductsCliAction">
+    <property name="description" value="Gets number of Products ingested for a given ProductType" />
+  </bean>
+  <bean id="getPrevPage" class="org.apache.oodt.cas.filemgr.cli.action.GetPrevPageCliAction">
+    <property name="description" value="Gets prev page of Products of given ProductType" />
+  </bean>
+  <bean id="getProductByName" class="org.apache.oodt.cas.filemgr.cli.action.GetProductByNameCliAction">
+    <property name="description" value="Get Product info by name" />
+  </bean>
+  <bean id="getProductById" class="org.apache.oodt.cas.filemgr.cli.action.GetProductByIdCliAction">
+    <property name="description" value="Gets Product info by ID" />
+  </bean>
+  <bean id="getProductPercentTransferred" class="org.apache.oodt.cas.filemgr.cli.action.GetProductPercentTransferredCliAction">
+    <property name="description" value="Gets percent amount transferred of a Products data files" />
+  </bean>
+  <bean id="getProductTypeByName" class="org.apache.oodt.cas.filemgr.cli.action.GetProductTypeByNameCliAction">
+    <property name="description" value="Gets a ProductType by its name" />
+  </bean>
+  <bean id="hasProduct" class="org.apache.oodt.cas.filemgr.cli.action.HasProductCliAction">
+    <property name="description" value="Checks if Product with given name has been ingested" />
+  </bean>
+  <bean id="ingestProduct" class="org.apache.oodt.cas.filemgr.cli.action.IngestProductCliAction">
+    <property name="description" value="Ingests a Product" />
+  </bean>
+  <bean id="luceneQuery" class="org.apache.oodt.cas.filemgr.cli.action.LuceneQueryCliAction">
+    <property name="description" value="Queries by parsing an Lucene-like query into a FileManager Query" />
+  </bean>
+  <bean id="retrieveFilesById" class="org.apache.oodt.cas.filemgr.cli.action.RetrieveFilesCliAction">
+    <property name="description" value="Retrieve a Product's files by Product ID" />
+  </bean>
+  <bean id="retrieveFilesByName" class="org.apache.oodt.cas.filemgr.cli.action.RetrieveFilesCliAction">
+    <property name="description" value="Retrieve a Product's files by Product name" />
+  </bean>
+  <bean id="sqlQuery" class="org.apache.oodt.cas.filemgr.cli.action.SqlQueryCliAction">
+    <property name="description" value="Queries by parsing an SQL-like query into a FileManager Query" />
+    <property name="detailedDescription">
+      <value>
+ This supports sending queries to the FileManager in form of
+  SELECT [Elements] FROM [ProductTypes] WHERE [where-clause], where:
+   - [Elements]: is a comma separated list of Element names; may also be * which
+    represents all Elements
+   - [ProductTypes]: is a comma separated list of ProductType names; may also
+    be * which represents all ProductTypes
+   - [where-clause]: is an optional Element name filter supporting the following:
+      * AND and OR boolean operators
+      * () grouping of queries
+      * element-name == 'element-value'
+      * element-name &#60; 'element-value'
+      * element-name &#62; 'element-value'
+      * element-name &#60;= 'element-value'
+      * element-name &#62;= 'element-value'"
+
+ An additional post-query FilterAlgor can also be specified where you specify
+  which Metadata fields which should be used as each Product's StartDateTime,
+  EndDateTime, and Priority values
+      </value>
+    </property>
+    <property name="examples">
+      <value>
+ (Assume you have a ProductType, GenericFile, which supports the
+    Elements: Filename, NominalDate, Group, and DataVersion)
+  $ ./filemgr-client -u http://localhost:9000 -op -sql
+    -q "SELECT Filename FROM GenericFile WHERE (NominalDate == '2011-20-10' OR
+      NominalDate == '2011-20-11') AND Group == 'Test' AND DataVersion > '1.0'"
+ (Returns all Products in FileManager -- use with care)
+  $ ./filemgr-client -u http://localhost:9000 -op -sql -q "SELECT * FROM *"
+      </value>
+    </property>
+  </bean>
+</beans>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/cmd-line-options.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/cmd-line-options.xml
new file mode 100644
index 0000000..227def2
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/cmd-line-options.xml
@@ -0,0 +1,1175 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+    <bean id="url" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="u" />
+        <property name="longOption" value="url" />
+        <property name="description" value="File Manager URL" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="url" />
+        <property name="required" value="true" />
+        <property name="handler">
+            <bean
+                class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+                <property name="propertyNames">
+                    <list>
+                        <value>org.apache.oodt.cas.filemgr.url</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+    <bean id="operation" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+        <property name="shortOption" value="op" />
+        <property name="longOption" value="operation" />
+        <property name="description"
+            value="Declare that you wish to present an operation" />
+        <property name="hasArgs" value="false" />
+        <property name="required" value="true" />
+        <property name="subOptions">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="addProductType" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="deleteProductById" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="deleteProductByName" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="ingestProduct" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="hasProduct" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getProductTypeByName" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getNumProducts" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getFirstPage" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getNextPage" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getPrevPage" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getLastPage" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getCurrentTransfer" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getCurrentTransfers" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getProductById" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getProductByName" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getProductPctTransferred" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getFilePctTransferred" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="sqlQuery" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="dumpMetadata" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="luceneQuery" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="retrieveFilesById" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="retrieveFilesByName" p:required="false" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- AddProductType Options -->
+    <bean id="addProductType" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="addPT" />
+        <property name="longOption" value="addProductType" />
+        <property name="description" value="Triggers addProductType Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>addProductType</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="addProductType" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+  <bean id="typeName" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="tn" />
+    <property name="longOption" value="typeName" />
+    <property name="description" value="ProductType name" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="product-type-name" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="addProductType" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="addProductType" p:methodName="setProductTypeName" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="typeDesc" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="td" />
+    <property name="longOption" value="typeDesc" />
+    <property name="description" value="ProductType description" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="description" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="addProductType" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="addProductType" p:methodName="setProductTypeDescription" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="repository" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="repo" />
+    <property name="longOption" value="repository" />
+    <property name="description" value="ProductType repository" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-path" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="addProductType" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="addProductType" p:methodName="setFileRepositoryPath" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="versionClass" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="vc" />
+    <property name="longOption" value="versionClass" />
+    <property name="description" value="ProductType versioner class" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="addProductType" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="addProductType" p:methodName="setVersioner" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <!-- IngestProduct Options -->
+  <bean id="ingestProduct" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="ingest" />
+    <property name="longOption" value="ingestProduct" />
+    <property name="description" value="Triggers ingestProduct Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>ingestProduct</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="productStructure" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="ps" />
+    <property name="longOption" value="productStructure" />
+    <property name="description" value="Hierarchical | Flat" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="structure-type" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="ingestProduct" p:methodName="setProductStructure" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="metadataFile" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="mf" />
+    <property name="longOption" value="metadataFile" />
+    <property name="description" value="Metadata XML file path or URL" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-path-or-url" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="clientTransfer" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="ct" />
+    <property name="longOption" value="clientTransfer" />
+    <property name="description" value="User client transferer" />
+    <property name="hasArgs" value="false" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="dataTransfer" p:required="true" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="dataTransfer" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="dt" />
+    <property name="longOption" value="dataTransfer" />
+    <property name="description" value="DataTransferer factory class" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="ingestProduct" p:methodName="setDataTransferer" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="refs" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="rs" />
+    <property name="longOption" value="refs" />
+    <property name="description" value="Data file path or URL" />
+    <property name="type" value="java.util.List" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-path-or-url" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="ingestProduct" p:methodName="setReferences" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <!-- HasProduct Options -->
+  <bean id="hasProduct" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="product" />
+    <property name="longOption" value="hasProduct" />
+    <property name="description" value="Triggers hasProduct Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>hasProduct</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="hasProduct" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetProductTypeByName Options -->
+  <bean id="getProductTypeByName" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="ptbyn" />
+    <property name="longOption" value="getProductTypeByName" />
+    <property name="description" value="Triggers getProductTypeByName Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getProductTypeByName</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductTypeByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetNumProducts Options -->
+  <bean id="getNumProducts" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="num" />
+    <property name="longOption" value="getNumProducts" />
+    <property name="description" value="Triggers getNumProducts Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getNumProducts</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNumProducts" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetFirstPage Options -->
+  <bean id="getFirstPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="page1" />
+    <property name="longOption" value="getFirstPage" />
+    <property name="description" value="Triggers getFirstPage Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getFirstPage</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getFirstPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetNextPage Options -->
+  <bean id="getNextPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="next" />
+    <property name="longOption" value="getNextPage" />
+    <property name="description" value="Triggers getNextPage Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getNextPage</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNextPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetPrevPage Options -->
+  <bean id="getPrevPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="prev" />
+    <property name="longOption" value="getPrevPage" />
+    <property name="description" value="Triggers getPrevPage Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getPrevPage</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getPrevPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetLastPage Options -->
+  <bean id="getLastPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="last" />
+    <property name="longOption" value="getLastPage" />
+    <property name="description" value="Triggers getLastPage Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getLastPage</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getLastPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetCurrentTransfer Options -->
+  <bean id="getCurrentTransfer" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="curTran" />
+    <property name="longOption" value="getCurrentTransfer" />
+    <property name="description" value="Triggers getCurrentTransfer Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getCurrentTransfer</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getCurrentTransfer" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetCurrentTransfers Options -->
+  <bean id="getCurrentTransfers" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="curTrans" />
+    <property name="longOption" value="getCurrentTransfers" />
+    <property name="description" value="Triggers getCurrentTransfers Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getCurrentTransfers</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getCurrentTransfers" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetProductPercentTransferred Options -->
+  <bean id="getProductPctTransferred" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="pctTrans" />
+    <property name="longOption" value="getProductPctTransferred" />
+    <property name="description" value="Triggers getProductPercentTransferred Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getProductPercentTransferred</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductPercentTransferred" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetFilePercentTransferred Options -->
+  <bean id="getFilePctTransferred" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="filePctTrans" />
+    <property name="longOption" value="getFilePctTransferred" />
+    <property name="description" value="Triggers getFilePercentTransferred Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getFilePercentTransferred</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getFilePercentTransferred" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="origRef" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="or" />
+    <property name="longOption" value="origRef" />
+    <property name="description" value="Original reference" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-path-or-url" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getFilePercentTransferred" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <!-- SqlQuery Options -->
+  <bean id="sqlQuery" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="sql" />
+    <property name="longOption" value="sqlQuery" />
+    <property name="description" value="Triggers sqlQuery Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>sqlQuery</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+
+
+  <!-- GetProductById Options -->
+  <bean id="getProductById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="pbyid" />
+    <property name="longOption" value="getProductById" />
+    <property name="description" value="Triggers getProductById Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getProductById</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductById" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- GetProductByName Options -->
+  <bean id="getProductByName" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="pbyn" />
+    <property name="longOption" value="getProductByName" />
+    <property name="description" value="Triggers getProductByName Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getProductByName</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- DeleteProductById Options -->
+  <bean id="deleteProductById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="dbyid" />
+    <property name="longOption" value="deleteProductById" />
+    <property name="description" value="Triggers deleteProductById Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>deleteProductById</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="deleteProductById" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- DeleteProductByName Options -->
+  <bean id="deleteProductByName" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="dbyn" />
+    <property name="longOption" value="deleteProductByName" />
+    <property name="description" value="Triggers deleteProductByName Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>deleteProductByName</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="deleteProductByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <!-- DumpMetadata Options -->
+  <bean id="dumpMetadata" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="dmet" />
+    <property name="longOption" value="dumpMetadata" />
+    <property name="description" value="Triggers dumpMetadata Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>dumpMetadata</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="dumpMetadata" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="outputDir" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="out" />
+    <property name="longOption" value="outputDir" />
+    <property name="description" value="Output directory" />
+    <property name="type" value="java.io.File" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="file-dir" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="dumpMetadata" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <!-- LuceneQuery Options -->
+  <bean id="luceneQuery" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="lucene" />
+    <property name="longOption" value="luceneQuery" />
+    <property name="description" value="Triggers luceneQuery Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>luceneQuery</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="reducedProductTypes" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="pts" />
+    <property name="longOption" value="reducedProductTypes" />
+    <property name="description" value="Limit query ProductTypes queried against" />
+    <property name="type" value="java.util.List" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="list-of-product-types" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="reducedMetadataKeys" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="metKeys" />
+    <property name="longOption" value="reducedMetadataKeys" />
+    <property name="description" value="Limit Elements returned by query" />
+    <property name="type" value="java.util.List" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="list-of-elements" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <!-- retrieveFiles Options -->
+  <bean id="retrieveFilesById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="rfbyid" />
+    <property name="longOption" value="retrieveFilesById" />
+    <property name="description" value="Triggers retrieveFilesById Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>retrieveFilesById</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesById" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="retrieveFilesByName" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="rfbyn" />
+    <property name="longOption" value="retrieveFilesByName" />
+    <property name="description" value="Triggers retrieveFilesByName Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>retrieveFilesByName</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="transferer" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="trans" />
+    <property name="longOption" value="transferer" />
+    <property name="description" value="Factory for creating DataTransfer which will perform the file transfer(s)" />
+    <property name="type" value="org.apache.oodt.cas.filemgr.datatransfer.DataTransferFactory" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="transfer factory class" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesById" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="retrieveFilesById" p:methodName="setDataTransferFactory" />
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="retrieveFilesByName" p:methodName="setDataTransferFactory" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+  <bean id="destination" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="dest" />
+    <property name="longOption" value="destination" />
+    <property name="description" value="Directory to transfer Product file to" />
+    <property name="type" value="java.io.File" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="directory" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesById" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+    <!-- Options used for multiple Actions -->
+  <bean id="productId" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="pid" />
+    <property name="longOption" value="productId" />
+    <property name="description" value="Product ID" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="product-id" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductPercentTransferred" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductById" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="deleteProductById" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="dumpMetadata" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesById" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+    
+  <bean id="productName" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="pn" />
+    <property name="longOption" value="productName" />
+    <property name="description" value="Product name" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="product-name" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="hasProduct" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductByName" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="deleteProductByName" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="retrieveFilesByName" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="productTypeName" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="ptn" />
+    <property name="longOption" value="productTypeName" />
+    <property name="description" value="ProductType name" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="product-type-name" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="ingestProduct" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductTypeByName" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNumProducts" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getFirstPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNextPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getPrevPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getLastPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getProductPercentTransferred" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+  
+  <bean id="currentPageNum" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="curPage" />
+    <property name="longOption" value="currentPageNum" />
+    <property name="description" value="Current Page Number" />
+    <property name="type" value="int" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="page-number" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getNextPage" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getPrevPage" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="query" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="q" />
+    <property name="longOption" value="query" />
+    <property name="description" value="File Manager query" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="query" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="sortBy" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="sb" />
+    <property name="longOption" value="sortBy" />
+    <property name="description" value="Metadata field to sort query results by" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="metadata field" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="outputFormat" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="of" />
+    <property name="longOption" value="outputFormat" />
+    <property name="description" value="Output format string (i.e. Filename = $Filename)" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="output-format-string" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="delimiter" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="dlmtr" />
+    <property name="longOption" value="delimiter" />
+    <property name="description" value="String to use the separate query results" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="delimiter-string" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="filter" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+    <property name="shortOption" value="f" />
+    <property name="longOption" value="filter" />
+    <property name="description" value="Query filter" />
+    <property name="hasArgs" value="false" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="subOptions">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="algor" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="converter" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="startDateTimeMetKey" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="endDateTimeMetKey" p:required="true" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="priorityMetKey" p:required="true" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="algor" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="algor" />
+    <property name="longOption" value="algor" />
+    <property name="description" value="FilterAlgor class" />
+    <property name="type" value="org.apache.oodt.cas.filemgr.structs.query.filter.FilterAlgor" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+  
+  <bean id="converter" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="conv" />
+    <property name="longOption" value="converter" />
+    <property name="description" value="VersionConverter class" />
+    <property name="type" value="org.apache.oodt.cas.filemgr.structs.query.conv.VersionConverter" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="classpath" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+
+  <bean id="startDateTimeMetKey" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="sdtMetKey" />
+    <property name="longOption" value="startDateTimeMetKey" />
+    <property name="description" value="Start date time metadata key" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="metadata-key" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+  
+  <bean id="endDateTimeMetKey" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="edtMetKey" />
+    <property name="longOption" value="endDateTimeMetKey" />
+    <property name="description" value="End date time metadata key" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="metadata-key" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+  
+  <bean id="priorityMetKey" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+      p:isSubOption="true">
+    <property name="shortOption" value="prMetKey" />
+    <property name="longOption" value="priorityMetKey" />
+    <property name="description" value="Priority metadata key" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="metadata-key" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="sqlQuery" p:relation="OPTIONAL" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="luceneQuery" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+</beans>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/oodt/elements.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/oodt/elements.xml
new file mode 100644
index 0000000..d56c44b
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/oodt/elements.xml
@@ -0,0 +1,77 @@
+<?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.
+-->
+<cas:elements xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<element id="urn:oodt:ProductId" name="CAS.ProductId">
+<dcElement>Identifier</dcElement>
+        <!--
+You can optionally specify a 'trim' tag to identify whether
+or not you want newlines trimmed from the element description. To
+turn off trimming (now done by default), include the following with your
+description definition: trim="false"
+-->
+<description>
+A Product's unique identifier within the CAS namespace.
+</description>
+</element>
+<element id="urn:oodt:ProductName" name="CAS.ProductName">
+<dcElement>Title</dcElement>
+<description>
+A Product's name within the CAS namespace.
+</description>
+</element>
+<element id="urn:oodt:ProductReceivedTime"
+name="CAS.ProductReceivedTime">
+<dcElement />
+<description>
+The ISO 8601 formatted time that the Product was received.
+</description>
+</element>
+<element id="urn:oodt:Filename" name="Filename">
+<description>
+The names of the files that represent this product.
+</description>
+<dcElement />
+</element>
+<element id="urn:oodt:FileLocation" name="FileLocation">
+<description>
+The locations of the files that represent this product.
+</description>
+<dcElement />
+</element>
+<element id="urn:oodt:ProductType" name="ProductType">
+<description>
+Type of product, as specified by, e.g., a data bible.
+</description>
+<dcElement />
+</element>
+<element id="urn:oodt:ProductStructure" name="ProductStructure">
+<description>
+Whether or not a product is Flat (e.g., a set of independent
+files), or hierarchical, e.g., a dir structure.
+</description>
+<dcElement />
+</element>
+<element id="urn:oodt:MimeType" name="MimeType">
+<description>The IETF mime type of this product.</description>
+<dcElement />
+</element>
+<element id="urn:test:DataVersion" name="DataVersion">
+<description>The version of the data product</description>
+<dcElement />
+</element>
+</cas:elements>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/oodt/product-type-element-map.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/oodt/product-type-element-map.xml
new file mode 100644
index 0000000..418c0d9
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/oodt/product-type-element-map.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<cas:producttypemap xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+ <!-- can set the "parent" attribute on types below to allow inheritance
+of elements between the types
+-->
+   <type id="urn:oodt:GenericFile">
+       <element id="urn:oodt:ProductReceivedTime"/>
+       <element id="urn:oodt:ProductName"/>
+       <element id="urn:oodt:ProductId"/>
+       <element id="urn:oodt:ProductType"/>
+       <element id="urn:oodt:ProductStructure"/>
+       <element id="urn:oodt:Filename"/>
+       <element id="urn:oodt:FileLocation"/>
+       <element id="urn:oodt:MimeType"/>
+       <element id="urn:test:DataVersion"/>
+  </type>
+</cas:producttypemap>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/oodt/product-types.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/oodt/product-types.xml
new file mode 100644
index 0000000..2d40847
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/filemgr/src/main/resources/policy/oodt/product-types.xml
@@ -0,0 +1,53 @@
+<?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.
+-->
+<cas:producttypes xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+  <type id="urn:oodt:GenericFile" name="GenericFile">
+    <repository path="file://[OODT_HOME]/data/archive"/>
+    <versioner class="org.apache.oodt.cas.filemgr.versioning.BasicVersioner"/>
+    <!--
+You can optionally specify a 'trim' tag to identify whether
+or not you want newlines trimmed from the product type description. To
+turn off trimming (now done by default), include the following attribute with your
+description definition: trim="false"
+-->
+    <description>The default product type for any kind of file.</description>
+    <metExtractors>
+      <extractor
+        class="org.apache.oodt.cas.filemgr.metadata.extractors.CoreMetExtractor">
+        <configuration>
+          <!-- you can optionally include the envReplace tag to turn on/off environment var replacement -->
+          <property name="nsAware" value="true" />
+          <property name="elementNs" value="CAS" />
+          <property name="elements"
+            value="ProductReceivedTime,ProductName,ProductId" />
+        </configuration>
+      </extractor>
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.MimeTypeExtractor" />
+      <extractor class="org.apache.oodt.cas.filemgr.metadata.extractors.examples.FinalFileLocationExtractor">
+        <configuration>
+          <!-- this property specifies whether you want the FILE_LOCATION field
+computed by this extractor to replace any other FILE_LOCATION met
+attribute.
+-->
+           <property name="replace" value="true"/>
+        </configuration>
+      </extractor>
+    </metExtractors>
+    <metadata/>
+  </type>
+</cas:producttypes>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/pom.xml
new file mode 100644
index 0000000..4e99cb9
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/pom.xml
@@ -0,0 +1,84 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>${groupId}</groupId>
+    <artifactId>${rootArtifactId}</artifactId>
+    <version>${version}</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+  <name>PCS Config (Apache OODT)</name>
+  <artifactId>${rootArtifactId}-${artifactId}</artifactId>
+  <packaging>jar</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-2</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/assembly/assembly.xml</descriptor>
+          </descriptors>
+        </configuration>
+        <executions>
+          <execution>
+            <id>dist-assembly</id>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>${groupId}</groupId>
+      <artifactId>${rootArtifactId}-extensions</artifactId>
+      <version>${project.parent.version}</version>
+      <type>jar</type>
+      <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.oodt</groupId>
+          <artifactId>cas-filemgr</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>pcs-core</artifactId>
+      <version>${oodt.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/assembly/assembly.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..5bd2d0a
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/assembly/assembly.xml
@@ -0,0 +1,91 @@
+<!--
+ 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.
+-->
+<assembly>
+  <id>bin</id>
+  <formats>
+    <format>tar.gz</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <baseDirectory>pcs</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/bin</directory>
+      <outputDirectory>pcs/bin</outputDirectory>
+      <includes/>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>pcs/logs</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>pcs/run</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/etc</directory>
+      <outputDirectory>pcs/etc</outputDirectory>
+      <includes>
+        <include>**.properties</include>
+        <include>**.xml</include>
+      </includes>
+      <fileMode>664</fileMode>
+      <directoryMode>775</directoryMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/policy</directory>
+      <outputDirectory>pcs/policy</outputDirectory>
+      <includes>
+        <include>**/**.xml</include>
+      </includes>
+      <fileMode>664</fileMode>
+      <directoryMode>775</directoryMode>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>pcs/lib</outputDirectory>
+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>
+      <unpackOptions/>
+    </dependencySet>
+  </dependencySets>
+</assembly>
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/bin/pcs_ll b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/bin/pcs_ll
new file mode 100755
index 0000000..28bbd1d
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/bin/pcs_ll
@@ -0,0 +1,47 @@
+#!/bin/tcsh
+# 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.
+# 
+#
+# Tool:  Long lister
+# Purpose:  Provide metadata information for all files in a directory.  
+# Interface:  Command-line.  If no arguments provided, assume the current 
+# directory.  Arguments can be a directory or a filename specification 
+# with wildcards.
+# Output:  Text to standard out.  One line per file.  Fields of line 
+# (tab-separated):
+#    Filename
+#    Test Tag(s)
+#    Test Counter(s)
+#    Subtest tag(s)
+#    DataStartTime
+#    DataEndTime
+#  
+# Note this behavior can be overriden by specifications in the pcs-ll-conf.xml 
+# file.
+#
+# Sample usage: ./pcs_ll
+
+
+set ORIG_DIR = `pwd`
+set DIR = `dirname $0`
+cd $DIR
+set DIR_PATH = `pwd`
+cd $ORIG_DIR
+
+java -Djava.util.logging.config.file=$DIR_PATH/../etc/logging.properties \
+    -Djava.ext.dirs=$DIR_PATH/../lib:$DIR_PATH/../../filemgr/lib:$DIR_PATH/../../workflow/lib \
+	org.apache.oodt.pcs.tools.PCSLongLister \
+	$FILEMGR_URL $DIR_PATH/../policy/pcs-ll-conf.xml $argv[2-$#argv]
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/bin/pcs_stat b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/bin/pcs_stat
new file mode 100755
index 0000000..0ae3a1d
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/bin/pcs_stat
@@ -0,0 +1,78 @@
+#!/bin/tcsh
+# 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.
+# 
+#
+# A tool to provide a report of the health of the PCS.
+# Example report:
+#
+# --------------------------------------
+# PCS Health Monitor Report
+# Generated on: 2007-07-12T10:56:23.000Z
+# 
+# Service Status:
+# 
+# File Manager:            [http://vostok:9000]: UP
+# Workflow Manager:  [http://vostok:9001]: DOWN
+# Resource Manager: [http://vostok:9002]: UP
+# > batch stub:   [http://compute-0-9:2001]: UP
+# > batch stub: [http://compute-0-10:2001]: UP
+#
+# Crawlers:
+# CPTOverview: [http://flatiron:9030]:         UP
+# CPTHeliostat:  [http://flatiron:9031]:         DOWN
+#  
+# PCS Health:
+# 
+# Files:
+# --------
+# last product ingested: oco_L1aRad01wdk_90233_070604010005.hdf at 2007-06-04T10:00:00.000Z
+#
+# Jobs:
+# --------
+# 10 tasks QUEUED
+# 9  tasks CRAWLING
+# 1  tasks PGE EXEC
+# 
+# Ingest:
+# --------
+# CPTOverview:
+# 
+# number of crawls: 10
+# average crawl time (ms): 50
+# 
+# CPTHeliostat:
+# 
+# number of crawls: 56
+# average crawl time (ms): 10
+# --------------------------------------
+# 
+# Sample usage: ./pcs_stat
+
+set ORIG_DIR = `pwd`
+set DIR = `dirname $0`
+cd $DIR
+set DIR_PATH = `pwd`
+cd $ORIG_DIR
+
+java -Djava.util.logging.config.file=$DIR_PATH/../etc/logging.properties \
+    -Djava.ext.dirs=$DIR_PATH/../lib:$DIR_PATH/../../filemgr/lib:$DIR_PATH/../workflow/lib:$DIR_PATH/../../resmgr/lib \
+    -Dorg.apache.oodt.cas.filemgr.properties=$DIR_PATH/../../filemgr/etc/filemgr.properties \
+	org.apache.oodt.pcs.tools.PCSHealthMonitor \
+	$FILEMGR_URL \
+	$WORKFLOW_URL \
+	$RESMGR_URL \
+	$DIR_PATH/../policy/pcs-crawlers.xml \
+	$DIR_PATH/../policy/pcs-workflow-statuses.xml
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/bin/pcs_trace b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/bin/pcs_trace
new file mode 100755
index 0000000..225db73d
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/bin/pcs_trace
@@ -0,0 +1,40 @@
+#!/bin/tcsh
+# 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.
+# 
+#
+# PCS Trace utility to discover product information including lineage
+# upstream and downstream, metadata, pipeline information and the like
+#
+# Sample usage: ./pcs_trace oco_L033Sun01Sun_91601_070922054839.pkt
+
+
+set DIR = `dirname $0`
+cd $DIR
+set DIR_PATH = `pwd`
+
+if ( $#argv != 1 ) then
+	echo "Usage: $0 <product>"
+	exit 1
+else
+	java -Djava.ext.dirs=$DIR_PATH/../lib:$DIR_PATH/../../filemgr/lib:$DIR_PATH/../../workflow/lib \
+    -Djava.util.logging.config.file=$DIR_PATH/../etc/logging.properties \
+    -Dorg.apache.oodt.cas.filemgr.properties=$DIR_PATH/../../filemgr/etc/filemgr.properties \
+	org.apache.oodt.pcs.tools.PCSTrace \
+	--fm $FILEMGR_URL \
+	--wm $WORKFLOW_URL \
+	--product $1 \
+	--enableNonCat
+endif
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/etc/logging.properties b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/etc/logging.properties
new file mode 100644
index 0000000..47ddde4
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/etc/logging.properties
@@ -0,0 +1,48 @@
+# 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.
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates one handlers
+handlers = java.util.logging.ConsoleHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging levels
+org.apache.oodt.pcs.level = SEVERE
+org.apache.oodt.pcs.util.level = SEVERE
+org.apache.oodt.pcs.tools.level = SEVERE
+
+# set logging levels for FM interface
+org.apache.oodt.cas.filemgr.system.level = SEVERE
+org.apache.oodt.cas.pge.util.level = OFF
+
+# set logging levels for WM interface
+org.apache.oodt.cas.workflow.system.level = OFF
+org.apache.oodt.cas.workflow.instrepo.level = OFF
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = OFF
+httpclient.wire.header.level = OFF
+httpclient.wire.level = OFF
+sun.net.www.protocol.http.level = OFF
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/policy/pcs-crawlers.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/policy/pcs-crawlers.xml
new file mode 100644
index 0000000..d1bfee2
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/policy/pcs-crawlers.xml
@@ -0,0 +1,50 @@
+<?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.
+
+Author: Chris Mattmann
+
+This file defines what ingest crawlers are being used by the PCS.
+This file is used in the PCSHealthMonitor tool.
+-->
+<input>
+
+    <!-- 
+      Here are global properties for the 
+      crawler. These properties are environment 
+      variable replaced.
+      
+      The only current property is:
+      
+      Hostname: the default hostname that the crawler 
+      daemons are operating on.
+     -->
+	<group name="CrawlProperties">
+		<scalar name="Hostname">localhost</scalar>
+	</group>
+
+    <!-- Here is a set of scalars where 
+         the scalar:
+         
+         name: the name of the crawler to monitor status for.
+         value: the port number that the crawler daemon to 
+         monitor is running on.
+     -->
+	<group name="CrawlerInfo">
+	    <scalar name="Crawler1">9020</scalar>
+	</group>
+
+</input>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/policy/pcs-ll-conf.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/policy/pcs-ll-conf.xml
new file mode 100644
index 0000000..d03d7ea
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/policy/pcs-ll-conf.xml
@@ -0,0 +1,96 @@
+<?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.
+
+Author: Chris Mattmann
+
+This file configures the PCS long lister, defining what product types
+to exclude from the listing, what field names to include as listing 
+columns, and which of those field names are collection tags that group 
+products together.
+-->
+<input>
+
+  <!-- 
+    Defines metadata fields per product to show as 
+    columns in the long listing. The scalar name 
+    attribute is the product met field name, and 
+    the value for the scalar is the name that the 
+    long lister displays while listing. The vector of 
+    ordered met keys is the display order in the listing.
+   -->
+  <group name="MetFieldColumns">
+    <vector name="OrderedMetKeys">
+      <element>Filename</element>
+      <element>TestTag</element>
+      <element>SubTestTag</element>
+      <element>TestCounter</element>
+      <element>StartDateTime</element>
+      <element>EndDateTime</element>
+    </vector>
+  
+    <scalar name="Filename">Filename</scalar>
+    <scalar name="TestTag">Test Tag(s)</scalar>
+    <scalar name="SubTestTag">Subtest tag(s)</scalar>
+    <scalar name="TestCounter">Test Counter(s)</scalar>
+    <scalar name="StartDateTime">DataStartTime</scalar>
+    <scalar name="EndDateTime">DataEndTime</scalar>
+  </group>
+  
+  <!-- 
+    Lets the long lister know which fields are 
+    collection fields: that is, fields that group 
+    products together. These fields will be used, along 
+    with the InputFiles met field, to find descendant 
+    files with matching collection field values.
+   -->
+  <group name="CollectionFields">
+    <vector name="FieldNames">
+      <element>TestTag</element>
+      <element>SubTestTag</element>
+      <element>TestCounter</element>
+    </vector>
+  </group>
+  
+  <!-- 
+    If you don't expect all the product types to be 
+    listable, you can set an exclude list. This is 
+    useful when e.g., some product types are so massive 
+    you would never do a long listing on them because 
+    the descendant query would take a long time.  
+   -->
+  <group name="ExcludedProductTypeList">
+   <vector name="ProductTypes">
+    <element>FTSSpectrum</element>
+    <element>FTSRunlog</element>
+    <element>FTSSunrun</element>
+    <element>PrimaryLog</element>
+    <element>MonitorLog</element>
+    <element>OCOTrendXML</element>
+    <element>SavesetDir</element>
+    <element>FTSIgramDir</element>
+    <element>SavesetInfoDir</element>
+    <element>CPTHeliostat</element>
+    <element>CPTMotor</element>
+    <element>CPTPhotodiode</element>
+    <element>CPTWavemeter</element>
+    <element>CPTETL</element>
+    <element>CPTStep</element>
+    <element>CPTCollimator</element>
+   </vector>
+  </group>
+
+</input>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/policy/pcs-workflow-statuses.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/policy/pcs-workflow-statuses.xml
new file mode 100644
index 0000000..c9402e3
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pcs/src/main/resources/policy/pcs-workflow-statuses.xml
@@ -0,0 +1,42 @@
+<?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.
+ 
+Author: Chris Mattmann
+
+This file defines the workflow statuses that we care about
+in the PCS Health Monitor tool.
+-->
+<input>
+
+    <!--  this information defines the 
+    valid workflow states that we want to 
+    check job status for.
+     -->
+	<group name="WorkflowStatesGroup">
+		<vector name="States">
+		 <element>QUEUED</element>
+		 <element>RSUBMIT</element>
+		 <element>BUILDING CONFIG FILE</element>
+		 <element>PGE EXEC</element>
+		 <element>CRAWLING</element>
+		 <element>STAGING INPUT</element>
+		 <element>FINISHED</element>
+		 <element>STARTED</element>
+		 <element>PAUSED</element>
+		</vector>
+	</group>
+</input>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pge/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pge/pom.xml
new file mode 100644
index 0000000..b1410cd
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pge/pom.xml
@@ -0,0 +1,98 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>${groupId}</groupId>
+    <artifactId>${rootArtifactId}</artifactId>
+    <version>${version}</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+  <name>PGE (Apache OODT)</name>
+  <artifactId>${rootArtifactId}-pge</artifactId>
+  <packaging>jar</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-2</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/assembly/assembly.xml</descriptor>
+          </descriptors>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+ 
+  <dependencies>
+    <dependency>
+      <groupId>${groupId}</groupId>
+      <artifactId>${rootArtifactId}-extensions</artifactId>
+      <version>${project.parent.version}</version>
+      <type>jar</type>
+      <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.oodt</groupId>
+          <artifactId>cas-filemgr</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-workflow</artifactId>
+      <version>${oodt.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-pge</artifactId>
+      <version>${oodt.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.oodt</groupId>
+          <artifactId>cas-filemgr</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.oodt</groupId>
+          <artifactId>cas-crawler</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pge/src/main/assembly/assembly.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pge/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..b5afa1b
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pge/src/main/assembly/assembly.xml
@@ -0,0 +1,61 @@
+<!--
+ 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.
+-->
+<assembly>
+  <id>bin</id>
+  <formats>
+    <format>tar.gz</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <baseDirectory>pge</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/bin</directory>
+      <outputDirectory>pge/bin</outputDirectory>
+      <includes/>
+      <fileMode>755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/policy</directory>
+      <outputDirectory>pge/policy</outputDirectory>
+      <includes/>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>pge/lib</outputDirectory>
+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>
+      <unpackOptions/>
+    </dependencySet>
+  </dependencySets>
+</assembly>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pge/src/main/resources/bin/example-script.sh b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pge/src/main/resources/bin/example-script.sh
new file mode 100755
index 0000000..23bf47c
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pge/src/main/resources/bin/example-script.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+echo "Hello World"
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pge/src/main/resources/policy/example-pge-config.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pge/src/main/resources/policy/example-pge-config.xml
new file mode 100644
index 0000000..7f836bd
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pge/src/main/resources/policy/example-pge-config.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<pgeConfig>
+
+  <!-- How to run the PGE -->
+  <exe dir="[JobDir]" shell="/bin/bash">
+    <cmd>[PGE_ROOT]/bin/example-script.sh > /tmp/HelloWorldPGE-[ProductionDateTime].output.txt</cmd>
+  </exe>
+
+  <!-- Files to ingest -->
+  <output>
+  </output>
+
+  <!-- Custom metadata to add to output files -->
+  <customMetadata>
+    <!-- helpful keys -->
+    <metadata key="LessThan" val="&#x3C;"/>
+    <metadata key="LessThanOrEqualTo" val="[LessThan]="/>
+    <metadata key="GreaterThan" val="&#x3E;"/>
+    <metadata key="GreaterThanOrEqualTo" val="[GreaterThan]="/>
+    <metadata key="Exclamation" val="&#33;"/>
+    <metadata key="Ampersand" val="&#38;"/>
+    <metadata key="NotEqualTo" val="[Ampersand]="/>
+    <metadata key="LogicalAnd" val="[Ampersand][Ampersand]"/>
+    <metadata key="CshPipeToStdOutAndError" val="[GreaterThan][Ampersand][Exclamation]"/>
+
+    <metadata key="ProductionDateTime" val="[DATE.UTC]"/>
+  </customMetadata>
+
+</pgeConfig>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pom.xml
new file mode 100644
index 0000000..3e53b01
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/pom.xml
@@ -0,0 +1,129 @@
+<?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.

+-->

+<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>${groupId}</groupId>

+  <artifactId>${artifactId}</artifactId>

+  <name>Data Management System</name>

+  <packaging>pom</packaging>

+  <description>Data Management System Powered by Apache OODT delivered via RADiX</description>

+  <version>${version}</version>

+

+  <properties>

+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

+    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

+    <oodt.version>${oodt}</oodt.version>

+    <oodt.pge.version>${oodt}</oodt.pge.version>

+   <!-- Maven plugin dependencies -->

+    <maven-compiler-plugin.version>3.2</maven-compiler-plugin.version>

+    <maven-surefire-plugin.version>2.17</maven-surefire-plugin.version>

+    <maven-jar-plugin.version>2.5</maven-jar-plugin.version>

+    <maven-javadoc-plugin.version>2.10.1</maven-javadoc-plugin.version>

+    <maven-eclipse-plugin.version>2.9</maven-eclipse-plugin.version>

+  </properties>

+

+  <repositories>

+    <repository>

+      <id>maven2</id>

+      <name>Java Sun Maven2 Repository</name>

+      <url>http://download.java.net/maven/2</url>

+      <layout>default</layout>

+    </repository>

+    <repository>

+      <id>apache.snapshots</id>

+      <name>Apache Snapshots</name>

+      <url>http://repository.apache.org/snapshots/</url>

+      <releases>

+        <enabled>false</enabled>

+      </releases>

+    </repository>

+  </repositories>

+

+  <distributionManagement>

+  <!-- use the following if you're not using a snapshot version. -->

+    <repository>

+      <id>repo</id>

+      <name>Repository Name</name>

+      <url>scp://host/path/to/repo</url>

+    </repository>

+    <!-- use the following if you ARE using a snapshot version. -->

+    <snapshotRepository>

+      <id>repo</id>

+      <name>Repository Name</name>

+      <url>scp://host/path/to/repo</url>

+    </snapshotRepository>

+  </distributionManagement>

+

+  <build>

+    <sourceDirectory>${basedir}/src/main/java</sourceDirectory>

+    <testSourceDirectory>${basedir}/src/test</testSourceDirectory>

+    <plugins>

+      <plugin>

+        <artifactId>maven-compiler-plugin</artifactId>

+        <version>${maven-compiler-plugin.version}</version>

+        <configuration>

+          <source>1.6</source>

+          <target>1.6</target>

+        </configuration>

+      </plugin>

+      <plugin>

+        <artifactId>maven-jar-plugin</artifactId>

+        <version>${maven-jar-plugin.version}</version>

+        <configuration>

+          <archive>

+            <index>true</index>

+          </archive>

+        </configuration>

+      </plugin>

+      <plugin>

+        <artifactId>maven-eclipse-plugin</artifactId>

+        <version>${maven-eclipse-plugin.version}</version>

+      </plugin>

+      <plugin>

+        <artifactId>maven-surefire-plugin</artifactId>

+        <version>${maven-surefire-plugin.version}</version>

+        <configuration>

+          <includes>

+            <include>**/*Test*.java</include>

+          </includes>

+        </configuration>

+      </plugin>

+      <plugin>

+        <artifactId>maven-javadoc-plugin</artifactId>

+        <version>${maven-javadoc-plugin.version}</version>

+        <configuration>

+          <outputEncoding>UTF-8</outputEncoding>

+          <charset>UTF-8</charset>

+          <docencoding>UTF-8</docencoding>

+          <encoding>UTF-8</encoding>

+        </configuration>

+        <executions>

+          <execution>

+            <id>attach-javadocs</id>

+            <phase>package</phase>

+            <goals>

+              <goal>javadoc</goal>

+            </goals>

+          </execution>

+        </executions>

+      </plugin>

+    </plugins>

+  </build>

+

+</project>

diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/pom.xml
new file mode 100644
index 0000000..e044feb
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/pom.xml
@@ -0,0 +1,99 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>${groupId}</groupId>
+    <artifactId>${rootArtifactId}</artifactId>
+    <version>${version}</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+  <name>Resource Manager (Apache OODT)</name>
+  <artifactId>${rootArtifactId}-${artifactId}</artifactId>
+  <packaging>jar</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-2</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/assembly/assembly.xml</descriptor>
+          </descriptors>
+        </configuration>
+        <executions>
+          <execution>
+            <id>dist-assembly</id>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>${groupId}</groupId>
+      <artifactId>${rootArtifactId}-extensions</artifactId>
+      <version>${project.parent.version}</version>
+      <type>jar</type>
+      <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.oodt</groupId>
+          <artifactId>cas-filemgr</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-resource</artifactId>
+      <version>${oodt.version}</version>
+    </dependency>
+       <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-pge</artifactId>
+      <version>${oodt.pge.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.oodt</groupId>
+          <artifactId>cas-filemgr</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.oodt</groupId>
+          <artifactId>cas-crawler</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency> 
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/assembly/assembly.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..c95f8f9
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/assembly/assembly.xml
@@ -0,0 +1,91 @@
+<!--
+ 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.
+-->
+<assembly>
+  <id>bin</id>
+  <formats>
+    <format>tar.gz</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <baseDirectory>resmgr</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/bin</directory>
+      <outputDirectory>resmgr/bin</outputDirectory>
+      <includes/>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>resmgr/logs</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>resmgr/run</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/etc</directory>
+      <outputDirectory>resmgr/etc</outputDirectory>
+      <includes>
+        <include>**.properties</include>
+        <include>**.xml</include>
+      </includes>
+      <fileMode>664</fileMode>
+      <directoryMode>775</directoryMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/policy</directory>
+      <outputDirectory>resmgr/policy</outputDirectory>
+      <includes>
+        <include>**/**.xml</include>
+      </includes>
+      <fileMode>664</fileMode>
+      <directoryMode>775</directoryMode>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>resmgr/lib</outputDirectory>
+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>
+      <unpackOptions/>
+    </dependencySet>
+  </dependencySets>
+</assembly>
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/bin/batch_stub b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/bin/batch_stub
new file mode 100755
index 0000000..a499e2f
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/bin/batch_stub
@@ -0,0 +1,31 @@
+#!/bin/tcsh
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+# $Id$ 
+#
+
+set DIR = `dirname $0`
+cd $DIR
+set DIR_PATH = `pwd`
+
+if ( $#argv != 1 ) then
+        echo "Usage: $0 <port>"
+        exit 1
+else
+        java -Djava.ext.dirs=../lib \
+        org.apache.oodt.cas.resource.system.extern.XmlRpcBatchStub \
+        --portNum $1&
+endif
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/bin/remote b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/bin/remote
new file mode 100755
index 0000000..d946357
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/bin/remote
@@ -0,0 +1,37 @@
+#!/bin/bash
+#
+# Script to run a command on all nodes specified in a nodes.xml config file
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+# $Id$
+
+E_NO_ARGS=65
+
+if [ $# -eq 0 ]
+then
+  echo "Usage: remote /path/to/nodes.xml command..."
+  exit $E_NO_ARGS
+fi 
+
+NODES=$(awk '/<node/ {print substr($3, 12,length($3)-12)}' $1)
+shift 
+for NODE in $NODES
+do
+  ssh $NODE $"${@// /\\ }" 2>&1 | sed "s/^/$NODE: /" &
+done
+
+exit 0 
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/bin/resmgr b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/bin/resmgr
new file mode 100755
index 0000000..7bd9db7
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/bin/resmgr
@@ -0,0 +1,173 @@
+#!/bin/sh
+#
+# init script for XmlRpcResourceManager
+#
+# chkconfig: 345 88 22
+# description: CAS Resource Manager
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+# $Id$
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false
+os400=false
+darwin=false
+case "`uname`" in
+CYGWIN*) cygwin=true;;
+OS400*) os400=true;;
+Darwin*) darwin=true;;
+esac
+
+# resolve links - $0 may be a softlink
+PRG="$0"
+
+while [ -h "$PRG" ]; do
+  ls=`ls -ld "$PRG"`
+  link=`expr "$ls" : '.*-> \(.*\)$'`
+  if expr "$link" : '/.*' > /dev/null; then
+    PRG="$link"
+  else
+    PRG=`dirname "$PRG"`/"$link"
+  fi
+done
+
+# Get standard environment variables
+PRGDIR=`dirname "$PRG"`
+
+# Only set OODT_HOME if not already set
+[ -z "$OODT_HOME" ] && OODT_HOME=`cd "$PRGDIR/../.." ; pwd`
+
+# Get OODT environment set up
+if [ -r "$OODT_HOME"/bin/env.sh ]; then
+  . "$OODT_HOME"/bin/env.sh
+fi
+
+# Only set RESMGR_HOME if not already set
+if [ -z "$RESMGR_HOME" ]; then
+  RESMGR_HOME="$OODT_HOME"/resmgr
+  export RESMGR_HOME
+fi
+
+if [ -z "$RESMGR_PID" ]; then
+  RESMGR_PID="$RESMGR_HOME"/run/cas.resmgr.pid
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$JRE_HOME" ] && JRE_HOME=`cygpath --unix "$JRE_HOME"`
+  [ -n "$OODT_HOME" ] && OODT_HOME=`cygpath --unix "$OODT_HOME"`
+  [ -n "$RESMGR_HOME" ] && RESMGR_HOME=`cygpath --unix "$RESMGR_HOME"`
+  [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+if [ "$1" = "start" ]; then
+  if [ ! -z "$RESMGR_PID" ]; then
+    if [ -f "$RESMGR_PID" ]; then
+      echo "PID file ($RESMGR_PID) found. Is Resource Manager still running? Start aborted."
+      exit 1
+    fi
+  fi
+
+  # In case this script was run from somewhere else cd to this directory
+  cd "$RESMGR_HOME"/bin
+
+  "$_RUNJAVA" $JAVA_OPTS $OODT_OPTS \
+    -Djava.ext.dirs="$RESMGR_HOME"/lib \
+    -Djava.util.logging.config.file="$RESMGR_HOME"/etc/logging.properties \
+    -Dorg.apache.oodt.cas.resource.properties="$RESMGR_HOME"/etc/resource.properties \
+    -Djava.io.tmpdir="$OODT_TMPDIR" \
+    org.apache.oodt.cas.resource.system.XmlRpcResourceManager \
+    --portNum "$RESMGR_PORT" 2>&1 &
+
+  if [ ! -z "$RESMGR_PID" ]; then
+    echo $! > $RESMGR_PID
+  fi
+
+  if [ $have_tty -eq 1 ]; then
+    echo "Resource Manager started PID file ($RESMGR_PID)."
+  fi
+
+elif [ "$1" = "stop" ]; then
+
+  shift
+
+  SLEEP=5
+  if [ ! -z "$1" ]; then
+    echo $1 | grep "[^0-9]" > /dev/null 2>&1
+    if [ $? -eq 1 ]; then
+      SLEEP=$1
+      shift
+    fi
+  fi
+
+  FORCE=0
+  if [ "$1" = "-force" ]; then
+    shift
+    FORCE=1
+  fi
+
+  if [ ! -z "$RESMGR_PID" ]; then
+    if [ -f "$RESMGR_PID" ]; then
+      kill `cat $RESMGR_PID` >/dev/null 2>&1
+      if [ $? -eq 1 ]; then
+        echo "PID file ($RESMGR_PID) found but no matching process was found. Stop aborted."
+        exit 1
+      fi
+    else
+      echo "\$RESMGR_PID was set ($RESMGR_PID) but the specified file does not exist. Is Resource Manager running? Stop aborted."
+      exit 1
+    fi
+  fi
+
+  if [ ! -z "$RESMGR_PID" ]; then
+    if [ -f "$RESMGR_PID" ]; then
+      while [ $SLEEP -ge 0 ]; do
+        kill -0 `cat $RESMGR_PID` >/dev/null 2>&1
+        if [ $? -eq 1 ]; then
+          rm $RESMGR_PID
+          break
+        fi
+        if [ $SLEEP -gt 0 ]; then
+          sleep 1
+        fi
+        if [ $SLEEP -eq 0 ]; then
+          if [ $FORCE -eq 0 ]; then
+            echo "Resource Manager did not stop in time. PID file was not removed."
+          fi
+        fi
+        SLEEP=`expr $SLEEP - 1 `
+      done
+    fi
+  fi
+
+  if [ $FORCE -eq 1 ]; then
+    if [ -z "$RESMGR_PID" ]; then
+      echo "Kill failed: \$RESMGR_PID not set"
+    else
+      if [ -f "$RESMGR_PID" ]; then
+        echo "Killing: `cat $RESMGR_PID`"
+        kill -9 `cat $RESMGR_PID`
+        rm $RESMGR_PID
+      fi
+    fi
+  fi
+
+else
+  echo "Usage: resmgr {start|stop}"
+  exit 1
+fi
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/bin/resmgr-client b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/bin/resmgr-client
new file mode 100755
index 0000000..e7dbd3d
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/bin/resmgr-client
@@ -0,0 +1,34 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+# $Id$
+
+
+if [ -z $JAVA_HOME ] ; then
+	JAVA_HOME=/path/to/java/home
+else
+	JAVA_HOME=${JAVA_HOME}
+fi
+
+export JAVA_HOME
+
+$JAVA_HOME/bin/java \
+        -Djava.ext.dirs=../lib \
+        -Dorg.apache.oodt.cas.resource.properties=../etc/resource.properties \
+        -Djava.util.logging.config.file=../etc/logging.properties \
+        -Dorg.apache.oodt.cas.cli.action.spring.config=../policy/cmd-line-actions.xml \
+        -Dorg.apache.oodt.cas.cli.option.spring.config=../policy/cmd-line-options.xml \
+        org.apache.oodt.cas.resource.system.XmlRpcResourceManagerClient $*
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/etc/logging.properties b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/etc/logging.properties
new file mode 100644
index 0000000..8785c8b
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/etc/logging.properties
@@ -0,0 +1,67 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.FileHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = ../logs/cas_resource%g.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 5
+java.util.logging.FileHandler.append = true
+java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging level for the subsystems
+
+# batchmgr subsystem
+org.apache.oodt.cas.resource.batchmgr.level = INFO
+
+# monitor subsystem
+org.apache.oodt.cas.resource.monitor.level = INFO
+
+# jobqueue subsystem
+org.apache.oodt.cas.resource.jobqueue.level = INFO
+
+# scheduler subsystem
+org.apache.oodt.cas.resource.scheduler.level = INFO
+
+# system subsystem
+org.apache.oodt.cas.resource.system.level = FINE
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = INFO
+httpclient.wire.header.level = INFO
+httpclient.wire.level = INFO
+
+# spring framework logging
+org.springframework.beans.level = SEVERE
+org.springframework.core.level = SEVERE
+org.springframework.level = SEVERE
+org.springframework.beans.factory.level = SEVERE
+org.springframework.beans.factory.config.level = SEVERE
+org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.level = SEVERE
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/etc/resource.properties b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/etc/resource.properties
new file mode 100644
index 0000000..5520c7b
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/etc/resource.properties
@@ -0,0 +1,61 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+#
+# Properties required to configure the Resource Manager
+
+# resource batchmgr factory
+resource.batchmgr.factory = org.apache.oodt.cas.resource.batchmgr.XmlRpcBatchMgrFactory
+
+# resource monitor factory
+resource.monitor.factory = org.apache.oodt.cas.resource.monitor.AssignmentMonitorFactory
+
+# resource scheduler factory
+resource.scheduler.factory = org.apache.oodt.cas.resource.scheduler.LRUSchedulerFactory
+
+# resource jobqueue factory
+resource.jobqueue.factory = org.apache.oodt.cas.resource.jobqueue.JobStackJobQueueFactory
+
+# resource job repository factory
+resource.jobrepo.factory = org.apache.oodt.cas.resource.jobrepo.MemoryJobRepositoryFactory
+
+# node repository factory
+org.apache.oodt.cas.resource.nodes.repo.factory = org.apache.oodt.cas.resource.noderepo.XmlNodeRepositoryFactory
+
+# queue repository factory
+org.apache.oodt.cas.resource.queues.repo.factory = org.apache.oodt.cas.resource.queuerepo.XmlQueueRepositoryFactory
+
+# JobStack JobQueue config properties
+org.apache.oodt.cas.resource.jobqueue.jobstack.maxstacksize=1000
+
+# XML LRUScheduler config properties
+org.apache.oodt.cas.resource.scheduler.wait.seconds=20
+
+# XML-RPC configuration props
+org.apache.oodt.cas.resource.system.xmlrpc.requestTimeout.minutes=20
+org.apache.oodt.cas.resource.system.xmlrpc.connectionTimeout.minutes=60
+
+# XStream JobRepo configuration props
+org.apache.oodt.cas.resource.jobrepo.xstream.working.dir=[HOME]/job-repo
+org.apache.oodt.cas.resource.jobrepo.xstream.max.history=4000
+
+# XML Node Repository config properties
+org.apache.oodt.cas.resource.nodes.dirs=file://[RESMGR_HOME]/policy
+
+# XML Queue Repository config properties
+org.apache.oodt.cas.resource.nodetoqueues.dirs=file://[RESMGR_HOME]/policy
+
+
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/cmd-line-actions.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/cmd-line-actions.xml
new file mode 100644
index 0000000..04919e9
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/cmd-line-actions.xml
@@ -0,0 +1,92 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+	<bean id="addNode"
+		class="org.apache.oodt.cas.resource.cli.action.AddNodeCliAction">
+		<property name="description" value="Adds a ResourceNode" />
+	</bean>
+	<bean id="addNodeToQueue"
+		class="org.apache.oodt.cas.resource.cli.action.AddNodeToQueueCliAction">
+		<property name="description" value="Adds a ResourceNode to a Queue" />
+	</bean>
+	<bean id="addQueue"
+		class="org.apache.oodt.cas.resource.cli.action.AddQueueCliAction">
+		<property name="description" value="Adds a queue" />
+	</bean>
+	<bean id="getExecNode"
+		class="org.apache.oodt.cas.resource.cli.action.GetExecNodeCliAction">
+		<property name="description" value="Get execution node for a job" />
+	</bean>
+	<bean id="getJobInfo"
+		class="org.apache.oodt.cas.resource.cli.action.GetJobInfoCliAction">
+		<property name="description" value="Gets information about a job" />
+	</bean>
+	<bean id="getNodeById"
+		class="org.apache.oodt.cas.resource.cli.action.GetNodeByIdCliAction">
+		<property name="description" value="Gets information about a node" />
+	</bean>
+	<bean id="getNodeLoad"
+		class="org.apache.oodt.cas.resource.cli.action.GetNodeLoadCliAction">
+		<property name="description" value="Gets the current job load of a node" />
+	</bean>
+	<bean id="getNodes"
+		class="org.apache.oodt.cas.resource.cli.action.GetNodesCliAction">
+		<property name="description" value="Gets a list of managed nodes" />
+	</bean>
+	<bean id="getNodesInQueue"
+		class="org.apache.oodt.cas.resource.cli.action.GetNodesInQueueCliAction">
+		<property name="description"
+			value="Gets list of nodes which belong to given queue" />
+	</bean>
+	<bean id="getQueues"
+		class="org.apache.oodt.cas.resource.cli.action.GetQueuesCliAction">
+		<property name="description" value="Gets list of queues" />
+	</bean>
+	<bean id="getQueuesWithNode"
+		class="org.apache.oodt.cas.resource.cli.action.GetQueuesWithNodeCliAction">
+		<property name="description" value="Gets list of queues which contain given node" />
+	</bean>
+	<bean id="kill" class="org.apache.oodt.cas.resource.cli.action.KillCliAction">
+		<property name="description" value="Kills a job" />
+	</bean>
+	<bean id="removeNode"
+		class="org.apache.oodt.cas.resource.cli.action.RemoveNodeCliAction">
+		<property name="description" value="Removes given node from managed nodes" />
+	</bean>
+	<bean id="removeNodeFromQueue"
+		class="org.apache.oodt.cas.resource.cli.action.RemoveNodeFromQueueCliAction">
+		<property name="description" value="Removes given node from given queue" />
+	</bean>
+	<bean id="removeQueue"
+		class="org.apache.oodt.cas.resource.cli.action.RemoveQueueCliAction">
+		<property name="description" value="Removes a queue" />
+	</bean>
+	<bean id="setNodeCapacity"
+		class="org.apache.oodt.cas.resource.cli.action.SetNodeCapacityCliAction">
+		<property name="description" value="Changes a nodes capacity" />
+	</bean>
+	<bean id="submitJob"
+		class="org.apache.oodt.cas.resource.cli.action.SubmitJobCliAction">
+		<property name="description" value="Submits a job for execution" />
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/cmd-line-options.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/cmd-line-options.xml
new file mode 100644
index 0000000..a7a1fde
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/cmd-line-options.xml
@@ -0,0 +1,601 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+	<bean id="url" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="u" />
+		<property name="longOption" value="url" />
+		<property name="description" value="Resource Manager URL" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="url" />
+		<property name="required" value="true" />
+		<property name="handler">
+			<bean
+				class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+				<property name="propertyNames">
+					<list>
+						<value>org.apache.oodt.cas.resource.url</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="operation" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+		<property name="shortOption" value="op" />
+		<property name="longOption" value="operation" />
+		<property name="description"
+			value="Declare that you wish to present an operation" />
+		<property name="hasArgs" value="false" />
+		<property name="required" value="true" />
+		<property name="subOptions">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getNodeById" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getNodes" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getQueues" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="addNode" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="removeNode" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="setNodeCapacity" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getExecNode" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="addQueue" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="removeQueue" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="addNodeToQueue" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getNodesInQueue" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getQueuesWithNode" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="removeNodeFromQueue" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getNodeLoad" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="submitJob" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getJobInfo" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="kill" p:required="false" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetNodeById Options -->
+	<bean id="getNodeById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="nbyid" />
+		<property name="longOption" value="getNodeById" />
+		<property name="description" value="Triggers getNodeById Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getNodeById</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodeById" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetNodes Options -->
+	<bean id="getNodes" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="nodes" />
+		<property name="longOption" value="getNodes" />
+		<property name="description" value="Triggers getNodes Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getNodes</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodes" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetQueues Options -->
+	<bean id="getQueues" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="queues" />
+		<property name="longOption" value="getQueues" />
+		<property name="description" value="Triggers getQueues Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getQueues</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getQueues" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- AddNode Options -->
+	<bean id="addNode" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="an" />
+		<property name="longOption" value="addNode" />
+		<property name="description" value="Triggers addNode Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>addNode</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNode" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="ipAddr" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="addr" />
+		<property name="longOption" value="ipAddr" />
+		<property name="description" value="Node IP Address" />
+		<property name="type" value="java.net.URL" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="ip-addr" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNode" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+				<property name="applyToActions">
+					<list>
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="addNode" p:methodName="setNodeUrl" />
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<!-- RemoveNode Options -->
+	<bean id="removeNode" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="rn" />
+		<property name="longOption" value="removeNode" />
+		<property name="description" value="Triggers removeNode Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>removeNode</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeNode" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- SetNodeCapacity Options -->
+	<bean id="setNodeCapacity" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="sncap" />
+		<property name="longOption" value="setNodeCapacity" />
+		<property name="description" value="Triggers setNodeCapacity Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>setNodeCapacity</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="setNodeCapacity" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+  <!-- SetNodeCapacity Options -->
+  <bean id="getExecNode" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="exeNode" />
+    <property name="longOption" value="getExecNode" />
+    <property name="description" value="Triggers getExecNode Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getExecNode</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getExecNode" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+	<!-- AddQueue Options -->
+	<bean id="addQueue" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="aq" />
+		<property name="longOption" value="addQueue" />
+		<property name="description" value="Triggers addQueue Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>addQueue</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addQueue" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- RemoveQueue Options -->
+	<bean id="removeQueue" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="rq" />
+		<property name="longOption" value="removeQueue" />
+		<property name="description" value="Triggers removeQueue Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>removeQueue</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeQueue" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- AddNodeToQueue Options -->
+	<bean id="addNodeToQueue" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="antq" />
+		<property name="longOption" value="addNodeToQueue" />
+		<property name="description" value="Triggers addNodeToQueue Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>addNodeToQueue</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNodeToQueue" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetNodesInQueue Options -->
+	<bean id="getNodesInQueue" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="ninq" />
+		<property name="longOption" value="getNodesInQueue" />
+		<property name="description" value="Triggers getNodesInQueue Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getNodesInQueue</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodesInQueue" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetQueuesWithNode Options -->
+	<bean id="getQueuesWithNode" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="qwn" />
+		<property name="longOption" value="getQueuesWithNode" />
+		<property name="description" value="Triggers getQueuesWithNode Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getQueuesWithNode</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getQueuesWithNode" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- RemoveNodeFromQueue Options -->
+	<bean id="removeNodeFromQueue" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="rnfq" />
+		<property name="longOption" value="removeNodeFromQueue" />
+		<property name="description" value="Triggers removeNodeFromQueue Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>removeNodeFromQueue</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeNodeFromQueue" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetNodeLoad Options -->
+	<bean id="getNodeLoad" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="load" />
+		<property name="longOption" value="getNodeLoad" />
+		<property name="description" value="Triggers getNodeLoad Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getNodeLoad</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodeLoad" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- SubmitJob Options -->
+	<bean id="submitJob" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="submit" />
+		<property name="longOption" value="submitJob" />
+		<property name="description" value="Triggers submitJob Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>submitJob</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="submitJob" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="def" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="d" />
+		<property name="longOption" value="def" />
+		<property name="description" value="Job Definition File" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="xml-file" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="submitJob" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+				<property name="applyToActions">
+					<list>
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="submitJob" p:methodName="setJobDefinitionFile" />
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+  <bean id="nodeUrl" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="nu" />
+    <property name="longOption" value="nodeUrl" />
+    <property name="description" value="Node URL" />
+    <property name="type" value="java.net.URL" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="url" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="submitJob" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="submitJob" p:methodName="setUrl" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+	<!-- GetJobInfo Options -->
+	<bean id="getJobInfo" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="info" />
+		<property name="longOption" value="getJobInfo" />
+		<property name="description" value="Triggers getJobInfo Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getJobInfo</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getJobInfo" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- Kill Options -->
+	<bean id="kill" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="k" />
+		<property name="longOption" value="kill" />
+		<property name="description" value="Triggers kill Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>kill</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="kill" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- Options used for multiple Actions -->
+	<bean id="nodeId" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="nid" />
+		<property name="longOption" value="nodeId" />
+		<property name="description" value="Node ID" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="node-id" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodeById" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNode" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeNode" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="setNodeCapacity" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNodeToQueue" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getQueuesWithNode" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeNodeFromQueue" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodeLoad" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+		</property>
+	</bean>
+
+	<bean id="capacity" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="cap" />
+		<property name="longOption" value="capacity" />
+		<property name="description" value="Node Capacity" />
+		<property name="type" value="int" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="capacity" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNode" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="setNodeCapacity" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+		</property>
+	</bean>
+
+	<bean id="queueName" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="qn" />
+		<property name="longOption" value="queueName" />
+		<property name="description" value="Queue name" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="queue-name" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addQueue" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeQueue" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNodeToQueue" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodesInQueue" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeNodeFromQueue" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+		</property>
+	</bean>
+
+  <bean id="jobId" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="jid" />
+    <property name="longOption" value="jobId" />
+    <property name="description" value="Job ID" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="job-id" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getJobInfo" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getExecNode" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="kill" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+</beans>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/jobs/exJob.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/jobs/exJob.xml
new file mode 100644
index 0000000..bbe0def
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/jobs/exJob.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<cas:job xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" id="abcd"
+	name="TestJob">
+	<instanceClass
+		name="org.apache.oodt.cas.resource.examples.HelloWorldJob" />
+	<inputClass
+		name="org.apache.oodt.cas.resource.structs.NameValueJobInput">
+		<properties>
+			<property name="user.name" value="Homer!" />
+		</properties>
+	</inputClass>
+	<queue>quick</queue>
+	<load>1</load>
+</cas:job>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/jobs/exLongJob.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/jobs/exLongJob.xml
new file mode 100644
index 0000000..3cbeb29
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/jobs/exLongJob.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<cas:job xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" id="abcd"
+	name="TestJob">
+	<instanceClass
+		name="org.apache.oodt.cas.resource.examples.LongJob" />
+	<inputClass
+		name="org.apache.oodt.cas.resource.structs.NameValueJobInput">
+		<properties>
+			<property name="wait" value="60" />
+		</properties>
+	</inputClass>
+	<queue>quick</queue>
+	<load>1</load>
+</cas:job>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/node-to-queue-mapping.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/node-to-queue-mapping.xml
new file mode 100644
index 0000000..73b0eba
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/node-to-queue-mapping.xml
@@ -0,0 +1,26 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<cas:node-to-queue-mapping xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<node id="localhost">
+		<queues>
+			<queue name="high"/>
+			<queue name="quick"/>
+			<queue name="long"/>
+		</queues>
+	</node>	
+</cas:node-to-queue-mapping>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/nodes.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/nodes.xml
new file mode 100644
index 0000000..d3d415d
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/resmgr/src/main/resources/policy/nodes.xml
@@ -0,0 +1,23 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<cas:resourcenodes xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<node nodeId="localhost" ip="http://localhost:2001" capacity="8"/>
+	<!-- EnvReplace Example 
+	<node nodeId="somehost" ip="http://somehost:[BATCH_STUB_PORT]" capacity="8" envReplace="true"/>
+	-->
+</cas:resourcenodes>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/pom.xml
new file mode 100644
index 0000000..c9798de
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/pom.xml
@@ -0,0 +1,58 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>${groupId}</groupId>
+    <artifactId>${rootArtifactId}</artifactId>
+    <version>${version}</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+  <name>Solr Catalog (Apache Solr)</name>
+  <artifactId>${rootArtifactId}-${artifactId}</artifactId>
+  <packaging>jar</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-2</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/assembly/assembly.xml</descriptor>
+          </descriptors>
+        </configuration>
+        <executions>
+          <execution>
+            <id>dist-assembly</id>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies/>
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/assembly/assembly.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..0ef24b3
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/assembly/assembly.xml
@@ -0,0 +1,47 @@
+<assembly>
+  <id>bin</id>
+  <formats>
+    <format>tar.gz</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <baseDirectory>solr</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>solr</outputDirectory>
+      <includes>
+        <include>*.*</include>
+      </includes>
+      <fileMode>660</fileMode>
+      <directoryMode>775</directoryMode>
+    </fileSet>    
+    <fileSet>
+      <directory>${basedir}/src/main/resources/bin</directory>
+      <outputDirectory>solr/bin</outputDirectory>
+      <includes>
+        <include>**.*</include>
+      </includes>
+      <fileMode>775</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/oodt-fm</directory>
+      <outputDirectory>solr/oodt-fm</outputDirectory>
+      <includes>
+        <include>**/**.*</include>
+      </includes>
+      <fileMode>660</fileMode>
+      <directoryMode>775</directoryMode>
+    </fileSet>
+  </fileSets>
+</assembly>
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/README.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/README.txt
new file mode 100644
index 0000000..64d7c41
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/README.txt
@@ -0,0 +1,63 @@
+# 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.
+
+
+Example Solr Home Directory
+=============================
+
+This directory is provided as an example of what a "Solr Home" directory
+should look like.
+
+It's not strictly necessary that you copy all of the files in this
+directory when setting up a new instance of Solr, but it is recommended.
+
+
+Basic Directory Structure
+-------------------------
+
+The Solr Home directory typically contains the following...
+
+* solr.xml *
+
+This is the primary configuration file Solr looks for when starting.
+This file specifies the list of "SolrCores" it should load, and high 
+level configuration options that should be used for all SolrCores.
+
+Please see the comments in ./solr.xml for more details.
+
+If no solr.xml file is found, then Solr assumes that there should be
+a single SolrCore named "collection1" and that the "Instance Directory" 
+for collection1 should be the same as the Solr Home Directory.
+
+* Individual SolrCore Instance Directories *
+
+Although solr.xml can be configured to look for SolrCore Instance Directories 
+in any path, simple sub-directories of the Solr Home Dir using relative paths 
+are common for many installations.  In this directory you can see the 
+"./collection1" Instance Directory.
+
+* A Shared 'lib' Directory *
+
+Although solr.xml can be configured with an optional "sharedLib" attribute 
+that can point to any path, it is common to use a "./lib" sub-directory of the 
+Solr Home Directory.
+
+* ZooKeeper Files *
+
+When using SolrCloud using the embedded ZooKeeper option for Solr, it is 
+common to have a "zoo.cfg" file and "zoo_data" directories in the Solr Home 
+Directory.  Please see the SolrCloud wiki page for more details...
+
+https://wiki.apache.org/solr/SolrCloud
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/README.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/README.txt
new file mode 100644
index 0000000..337d55b
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/README.txt
@@ -0,0 +1,50 @@
+# 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.
+
+
+Example SolrCore Instance Directory
+=============================
+
+This directory is provided as an example of what an "Instance Directory"
+should look like for a SolrCore
+
+It's not strictly necessary that you copy all of the files in this
+directory when setting up a new SolrCores, but it is recommended.
+
+
+Basic Directory Structure
+-------------------------
+
+The Solr Home directory typically contains the following sub-directories...
+
+   conf/
+        This directory is mandatory and must contain your solrconfig.xml
+        and schema.xml.  Any other optional configuration files would also 
+        be kept here.
+
+   data/
+        This directory is the default location where Solr will keep your
+        index, and is used by the replication scripts for dealing with
+        snapshots.  You can override this location in the 
+        conf/solrconfig.xml.  Solr will create this directory if it does not 
+        already exist.
+
+   lib/
+        This directory is optional.  If it exists, Solr will load any Jars
+        found in this directory and use them to resolve any "plugins"
+        specified in your solrconfig.xml or schema.xml (ie: Analyzers,
+        Request Handlers, etc...).  Alternatively you can use the <lib>
+        syntax in conf/solrconfig.xml to direct Solr to your plugins.  See 
+        the example conf/solrconfig.xml file for details.
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/admin-extra.html b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/admin-extra.html
new file mode 100644
index 0000000..fecab20
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/admin-extra.html
@@ -0,0 +1,24 @@
+<!--
+ 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.
+-->
+
+<!-- The content of this page will be statically included into the top-
+right box of the cores overview page. Uncomment this as an example to 
+see there the content will show up.
+
+<img src="img/ico/construction.png"> This line will appear at the top-
+right box on collection1's Overview
+-->
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/admin-extra.menu-bottom.html b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/admin-extra.menu-bottom.html
new file mode 100644
index 0000000..3359a46
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/admin-extra.menu-bottom.html
@@ -0,0 +1,25 @@
+<!--
+ 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.
+-->
+
+<!-- admin-extra.menu-bottom.html -->
+<!--
+<li>
+  <a href="#" style="background-image: url(img/ico/construction.png);">
+    LAST ITEM
+  </a>
+</li>
+-->
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/admin-extra.menu-top.html b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/admin-extra.menu-top.html
new file mode 100644
index 0000000..0886cee
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/admin-extra.menu-top.html
@@ -0,0 +1,25 @@
+<!--
+ 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.
+-->
+
+<!-- admin-extra.menu-top.html -->
+<!--
+<li>
+  <a href="#" style="background-image: url(img/ico/construction.png);">
+    FIRST ITEM
+  </a>
+</li>
+-->
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/clustering/carrot2/kmeans-attributes.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/clustering/carrot2/kmeans-attributes.xml
new file mode 100644
index 0000000..d802465
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/clustering/carrot2/kmeans-attributes.xml
@@ -0,0 +1,19 @@
+<!-- 
+  Default configuration for the bisecting k-means clustering algorithm.
+  
+  This file can be loaded (and saved) by Carrot2 Workbench.
+  http://project.carrot2.org/download.html
+-->
+<attribute-sets default="attributes">
+    <attribute-set id="attributes">
+      <value-set>
+        <label>attributes</label>
+          <attribute key="MultilingualClustering.defaultLanguage">
+            <value type="org.carrot2.core.LanguageCode" value="ENGLISH"/>
+          </attribute>
+          <attribute key="MultilingualClustering.languageAggregationStrategy">
+            <value type="org.carrot2.text.clustering.MultilingualClustering$LanguageAggregationStrategy" value="FLATTEN_MAJOR_LANGUAGE"/>
+          </attribute>
+      </value-set>
+  </attribute-set>
+</attribute-sets>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/clustering/carrot2/lingo-attributes.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/clustering/carrot2/lingo-attributes.xml
new file mode 100644
index 0000000..4bf1360
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/clustering/carrot2/lingo-attributes.xml
@@ -0,0 +1,24 @@
+<!-- 
+  Default configuration for the Lingo clustering algorithm.
+
+  This file can be loaded (and saved) by Carrot2 Workbench.
+  http://project.carrot2.org/download.html
+-->
+<attribute-sets default="attributes">
+    <attribute-set id="attributes">
+      <value-set>
+        <label>attributes</label>
+          <!-- 
+          The language to assume for clustered documents.
+          For a list of allowed values, see: 
+          http://download.carrot2.org/stable/manual/#section.attribute.lingo.MultilingualClustering.defaultLanguage
+          -->
+          <attribute key="MultilingualClustering.defaultLanguage">
+            <value type="org.carrot2.core.LanguageCode" value="ENGLISH"/>
+          </attribute>
+          <attribute key="LingoClusteringAlgorithm.desiredClusterCountBase">
+            <value type="java.lang.Integer" value="20"/>
+          </attribute>
+      </value-set>
+  </attribute-set>
+</attribute-sets>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/clustering/carrot2/stc-attributes.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/clustering/carrot2/stc-attributes.xml
new file mode 100644
index 0000000..c1bf110
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/clustering/carrot2/stc-attributes.xml
@@ -0,0 +1,19 @@
+<!-- 
+  Default configuration for the STC clustering algorithm.
+
+  This file can be loaded (and saved) by Carrot2 Workbench.
+  http://project.carrot2.org/download.html
+-->
+<attribute-sets default="attributes">
+    <attribute-set id="attributes">
+      <value-set>
+        <label>attributes</label>
+          <attribute key="MultilingualClustering.defaultLanguage">
+            <value type="org.carrot2.core.LanguageCode" value="ENGLISH"/>
+          </attribute>
+          <attribute key="MultilingualClustering.languageAggregationStrategy">
+            <value type="org.carrot2.text.clustering.MultilingualClustering$LanguageAggregationStrategy" value="FLATTEN_MAJOR_LANGUAGE"/>
+          </attribute>
+      </value-set>
+  </attribute-set>
+</attribute-sets>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/currency.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/currency.xml
new file mode 100644
index 0000000..3a9c58a
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/currency.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" ?>
+<!--
+ 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.
+-->
+
+<!-- Example exchange rates file for CurrencyField type named "currency" in example schema -->
+
+<currencyConfig version="1.0">
+  <rates>
+    <!-- Updated from http://www.exchangerate.com/ at 2011-09-27 -->
+    <rate from="USD" to="ARS" rate="4.333871" comment="ARGENTINA Peso" />
+    <rate from="USD" to="AUD" rate="1.025768" comment="AUSTRALIA Dollar" />
+    <rate from="USD" to="EUR" rate="0.743676" comment="European Euro" />
+    <rate from="USD" to="BRL" rate="1.881093" comment="BRAZIL Real" />
+    <rate from="USD" to="CAD" rate="1.030815" comment="CANADA Dollar" />
+    <rate from="USD" to="CLP" rate="519.0996" comment="CHILE Peso" />
+    <rate from="USD" to="CNY" rate="6.387310" comment="CHINA Yuan" />
+    <rate from="USD" to="CZK" rate="18.47134" comment="CZECH REP. Koruna" />
+    <rate from="USD" to="DKK" rate="5.515436" comment="DENMARK Krone" />
+    <rate from="USD" to="HKD" rate="7.801922" comment="HONG KONG Dollar" />
+    <rate from="USD" to="HUF" rate="215.6169" comment="HUNGARY Forint" />
+    <rate from="USD" to="ISK" rate="118.1280" comment="ICELAND Krona" />
+    <rate from="USD" to="INR" rate="49.49088" comment="INDIA Rupee" />
+    <rate from="USD" to="XDR" rate="0.641358" comment="INTNL MON. FUND SDR" />
+    <rate from="USD" to="ILS" rate="3.709739" comment="ISRAEL Sheqel" />
+    <rate from="USD" to="JPY" rate="76.32419" comment="JAPAN Yen" />
+    <rate from="USD" to="KRW" rate="1169.173" comment="KOREA (SOUTH) Won" />
+    <rate from="USD" to="KWD" rate="0.275142" comment="KUWAIT Dinar" />
+    <rate from="USD" to="MXN" rate="13.85895" comment="MEXICO Peso" />
+    <rate from="USD" to="NZD" rate="1.285159" comment="NEW ZEALAND Dollar" />
+    <rate from="USD" to="NOK" rate="5.859035" comment="NORWAY Krone" />
+    <rate from="USD" to="PKR" rate="87.57007" comment="PAKISTAN Rupee" />
+    <rate from="USD" to="PEN" rate="2.730683" comment="PERU Sol" />
+    <rate from="USD" to="PHP" rate="43.62039" comment="PHILIPPINES Peso" />
+    <rate from="USD" to="PLN" rate="3.310139" comment="POLAND Zloty" />
+    <rate from="USD" to="RON" rate="3.100932" comment="ROMANIA Leu" />
+    <rate from="USD" to="RUB" rate="32.14663" comment="RUSSIA Ruble" />
+    <rate from="USD" to="SAR" rate="3.750465" comment="SAUDI ARABIA Riyal" />
+    <rate from="USD" to="SGD" rate="1.299352" comment="SINGAPORE Dollar" />
+    <rate from="USD" to="ZAR" rate="8.329761" comment="SOUTH AFRICA Rand" />
+    <rate from="USD" to="SEK" rate="6.883442" comment="SWEDEN Krona" />
+    <rate from="USD" to="CHF" rate="0.906035" comment="SWITZERLAND Franc" />
+    <rate from="USD" to="TWD" rate="30.40283" comment="TAIWAN Dollar" />
+    <rate from="USD" to="THB" rate="30.89487" comment="THAILAND Baht" />
+    <rate from="USD" to="AED" rate="3.672955" comment="U.A.E. Dirham" />
+    <rate from="USD" to="UAH" rate="7.988582" comment="UKRAINE Hryvnia" />
+    <rate from="USD" to="GBP" rate="0.647910" comment="UNITED KINGDOM Pound" />
+    
+    <!-- Cross-rates for some common currencies -->
+    <rate from="EUR" to="GBP" rate="0.869914" />  
+    <rate from="EUR" to="NOK" rate="7.800095" />  
+    <rate from="GBP" to="NOK" rate="8.966508" />  
+  </rates>
+</currencyConfig>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/elevate.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/elevate.xml
new file mode 100644
index 0000000..25d5ceb
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/elevate.xml
@@ -0,0 +1,38 @@
+<?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.
+-->
+
+<!-- If this file is found in the config directory, it will only be
+     loaded once at startup.  If it is found in Solr's data
+     directory, it will be re-loaded every commit.
+
+   See http://wiki.apache.org/solr/QueryElevationComponent for more info
+
+-->
+<elevate>
+ <query text="foo bar">
+  <doc id="1" />
+  <doc id="2" />
+  <doc id="3" />
+ </query>
+ 
+ <query text="ipod">
+   <doc id="MA147LL/A" />  <!-- put the actual ipod at the top -->
+   <doc id="IW-02" exclude="true" /> <!-- exclude this cable -->
+ </query>
+ 
+</elevate>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/contractions_ca.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/contractions_ca.txt
new file mode 100644
index 0000000..307a85f
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/contractions_ca.txt
@@ -0,0 +1,8 @@
+# Set of Catalan contractions for ElisionFilter
+# TODO: load this as a resource from the analyzer and sync it in build.xml
+d
+l
+m
+n
+s
+t
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/contractions_fr.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/contractions_fr.txt
new file mode 100644
index 0000000..f1bba51
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/contractions_fr.txt
@@ -0,0 +1,15 @@
+# Set of French contractions for ElisionFilter
+# TODO: load this as a resource from the analyzer and sync it in build.xml
+l
+m
+t
+qu
+n
+s
+j
+d
+c
+jusqu
+quoiqu
+lorsqu
+puisqu
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/contractions_ga.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/contractions_ga.txt
new file mode 100644
index 0000000..9ebe7fa
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/contractions_ga.txt
@@ -0,0 +1,5 @@
+# Set of Irish contractions for ElisionFilter
+# TODO: load this as a resource from the analyzer and sync it in build.xml
+d
+m
+b
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/contractions_it.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/contractions_it.txt
new file mode 100644
index 0000000..cac0409
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/contractions_it.txt
@@ -0,0 +1,23 @@
+# Set of Italian contractions for ElisionFilter
+# TODO: load this as a resource from the analyzer and sync it in build.xml
+c
+l 
+all 
+dall 
+dell 
+nell 
+sull 
+coll 
+pell 
+gl 
+agl 
+dagl 
+degl 
+negl 
+sugl 
+un 
+m 
+t 
+s 
+v 
+d
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/hyphenations_ga.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/hyphenations_ga.txt
new file mode 100644
index 0000000..4d2642c
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/hyphenations_ga.txt
@@ -0,0 +1,5 @@
+# Set of Irish hyphenations for StopFilter
+# TODO: load this as a resource from the analyzer and sync it in build.xml
+h
+n
+t
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stemdict_nl.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stemdict_nl.txt
new file mode 100644
index 0000000..4410729
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stemdict_nl.txt
@@ -0,0 +1,6 @@
+# Set of overrides for the dutch stemmer
+# TODO: load this as a resource from the analyzer and sync it in build.xml
+fiets	fiets
+bromfiets	bromfiets
+ei	eier
+kind	kinder
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stoptags_ja.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stoptags_ja.txt
new file mode 100644
index 0000000..71b7508
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stoptags_ja.txt
@@ -0,0 +1,420 @@
+#
+# This file defines a Japanese stoptag set for JapanesePartOfSpeechStopFilter.
+#
+# Any token with a part-of-speech tag that exactly matches those defined in this
+# file are removed from the token stream.
+#
+# Set your own stoptags by uncommenting the lines below.  Note that comments are
+# not allowed on the same line as a stoptag.  See LUCENE-3745 for frequency lists,
+# etc. that can be useful for building you own stoptag set.
+#
+# The entire possible tagset is provided below for convenience.
+#
+#####
+#  noun: unclassified nouns
+#名詞
+#
+#  noun-common: Common nouns or nouns where the sub-classification is undefined
+#名詞-一般
+#
+#  noun-proper: Proper nouns where the sub-classification is undefined 
+#名詞-固有名詞
+#
+#  noun-proper-misc: miscellaneous proper nouns
+#名詞-固有名詞-一般
+#
+#  noun-proper-person: Personal names where the sub-classification is undefined
+#名詞-固有名詞-人名
+#
+#  noun-proper-person-misc: names that cannot be divided into surname and 
+#  given name; foreign names; names where the surname or given name is unknown.
+#  e.g. お市の方
+#名詞-固有名詞-人名-一般
+#
+#  noun-proper-person-surname: Mainly Japanese surnames.
+#  e.g. 山田
+#名詞-固有名詞-人名-姓
+#
+#  noun-proper-person-given_name: Mainly Japanese given names.
+#  e.g. 太郎
+#名詞-固有名詞-人名-名
+#
+#  noun-proper-organization: Names representing organizations.
+#  e.g. 通産省, NHK
+#名詞-固有名詞-組織
+#
+#  noun-proper-place: Place names where the sub-classification is undefined
+#名詞-固有名詞-地域
+#
+#  noun-proper-place-misc: Place names excluding countries.
+#  e.g. アジア, バルセロナ, 京都
+#名詞-固有名詞-地域-一般
+#
+#  noun-proper-place-country: Country names. 
+#  e.g. 日本, オーストラリア
+#名詞-固有名詞-地域-国
+#
+#  noun-pronoun: Pronouns where the sub-classification is undefined
+#名詞-代名詞
+#
+#  noun-pronoun-misc: miscellaneous pronouns: 
+#  e.g. それ, ここ, あいつ, あなた, あちこち, いくつ, どこか, なに, みなさん, みんな, わたくし, われわれ
+#名詞-代名詞-一般
+#
+#  noun-pronoun-contraction: Spoken language contraction made by combining a 
+#  pronoun and the particle 'wa'.
+#  e.g. ありゃ, こりゃ, こりゃあ, そりゃ, そりゃあ 
+#名詞-代名詞-縮約
+#
+#  noun-adverbial: Temporal nouns such as names of days or months that behave 
+#  like adverbs. Nouns that represent amount or ratios and can be used adverbially,
+#  e.g. 金曜, 一月, 午後, 少量
+#名詞-副詞可能
+#
+#  noun-verbal: Nouns that take arguments with case and can appear followed by 
+#  'suru' and related verbs (する, できる, なさる, くださる)
+#  e.g. インプット, 愛着, 悪化, 悪戦苦闘, 一安心, 下取り
+#名詞-サ変接続
+#
+#  noun-adjective-base: The base form of adjectives, words that appear before な ("na")
+#  e.g. 健康, 安易, 駄目, だめ
+#名詞-形容動詞語幹
+#
+#  noun-numeric: Arabic numbers, Chinese numerals, and counters like 何 (回), 数.
+#  e.g. 0, 1, 2, 何, 数, 幾
+#名詞-数
+#
+#  noun-affix: noun affixes where the sub-classification is undefined
+#名詞-非自立
+#
+#  noun-affix-misc: Of adnominalizers, the case-marker の ("no"), and words that 
+#  attach to the base form of inflectional words, words that cannot be classified 
+#  into any of the other categories below. This category includes indefinite nouns.
+#  e.g. あかつき, 暁, かい, 甲斐, 気, きらい, 嫌い, くせ, 癖, こと, 事, ごと, 毎, しだい, 次第, 
+#       順, せい, 所為, ついで, 序で, つもり, 積もり, 点, どころ, の, はず, 筈, はずみ, 弾み, 
+#       拍子, ふう, ふり, 振り, ほう, 方, 旨, もの, 物, 者, ゆえ, 故, ゆえん, 所以, わけ, 訳,
+#       わり, 割り, 割, ん-口語/, もん-口語/
+#名詞-非自立-一般
+#
+#  noun-affix-adverbial: noun affixes that that can behave as adverbs.
+#  e.g. あいだ, 間, あげく, 挙げ句, あと, 後, 余り, 以外, 以降, 以後, 以上, 以前, 一方, うえ, 
+#       上, うち, 内, おり, 折り, かぎり, 限り, きり, っきり, 結果, ころ, 頃, さい, 際, 最中, さなか, 
+#       最中, じたい, 自体, たび, 度, ため, 為, つど, 都度, とおり, 通り, とき, 時, ところ, 所, 
+#       とたん, 途端, なか, 中, のち, 後, ばあい, 場合, 日, ぶん, 分, ほか, 他, まえ, 前, まま, 
+#       儘, 侭, みぎり, 矢先
+#名詞-非自立-副詞可能
+#
+#  noun-affix-aux: noun affixes treated as 助動詞 ("auxiliary verb") in school grammars 
+#  with the stem よう(だ) ("you(da)").
+#  e.g.  よう, やう, 様 (よう)
+#名詞-非自立-助動詞語幹
+#  
+#  noun-affix-adjective-base: noun affixes that can connect to the indeclinable
+#  connection form な (aux "da").
+#  e.g. みたい, ふう
+#名詞-非自立-形容動詞語幹
+#
+#  noun-special: special nouns where the sub-classification is undefined.
+#名詞-特殊
+#
+#  noun-special-aux: The そうだ ("souda") stem form that is used for reporting news, is 
+#  treated as 助動詞 ("auxiliary verb") in school grammars, and attach to the base 
+#  form of inflectional words.
+#  e.g. そう
+#名詞-特殊-助動詞語幹
+#
+#  noun-suffix: noun suffixes where the sub-classification is undefined.
+#名詞-接尾
+#
+#  noun-suffix-misc: Of the nouns or stem forms of other parts of speech that connect 
+#  to ガル or タイ and can combine into compound nouns, words that cannot be classified into
+#  any of the other categories below. In general, this category is more inclusive than 
+#  接尾語 ("suffix") and is usually the last element in a compound noun.
+#  e.g. おき, かた, 方, 甲斐 (がい), がかり, ぎみ, 気味, ぐるみ, (~した) さ, 次第, 済 (ず) み,
+#       よう, (でき)っこ, 感, 観, 性, 学, 類, 面, 用
+#名詞-接尾-一般
+#
+#  noun-suffix-person: Suffixes that form nouns and attach to person names more often
+#  than other nouns.
+#  e.g. 君, 様, 著
+#名詞-接尾-人名
+#
+#  noun-suffix-place: Suffixes that form nouns and attach to place names more often 
+#  than other nouns.
+#  e.g. 町, 市, 県
+#名詞-接尾-地域
+#
+#  noun-suffix-verbal: Of the suffixes that attach to nouns and form nouns, those that 
+#  can appear before スル ("suru").
+#  e.g. 化, 視, 分け, 入り, 落ち, 買い
+#名詞-接尾-サ変接続
+#
+#  noun-suffix-aux: The stem form of そうだ (様態) that is used to indicate conditions, 
+#  is treated as 助動詞 ("auxiliary verb") in school grammars, and attach to the 
+#  conjunctive form of inflectional words.
+#  e.g. そう
+#名詞-接尾-助動詞語幹
+#
+#  noun-suffix-adjective-base: Suffixes that attach to other nouns or the conjunctive 
+#  form of inflectional words and appear before the copula だ ("da").
+#  e.g. 的, げ, がち
+#名詞-接尾-形容動詞語幹
+#
+#  noun-suffix-adverbial: Suffixes that attach to other nouns and can behave as adverbs.
+#  e.g. 後 (ご), 以後, 以降, 以前, 前後, 中, 末, 上, 時 (じ)
+#名詞-接尾-副詞可能
+#
+#  noun-suffix-classifier: Suffixes that attach to numbers and form nouns. This category 
+#  is more inclusive than 助数詞 ("classifier") and includes common nouns that attach 
+#  to numbers.
+#  e.g. 個, つ, 本, 冊, パーセント, cm, kg, カ月, か国, 区画, 時間, 時半
+#名詞-接尾-助数詞
+#
+#  noun-suffix-special: Special suffixes that mainly attach to inflecting words.
+#  e.g. (楽し) さ, (考え) 方
+#名詞-接尾-特殊
+#
+#  noun-suffix-conjunctive: Nouns that behave like conjunctions and join two words 
+#  together.
+#  e.g. (日本) 対 (アメリカ), 対 (アメリカ), (3) 対 (5), (女優) 兼 (主婦)
+#名詞-接続詞的
+#
+#  noun-verbal_aux: Nouns that attach to the conjunctive particle て ("te") and are 
+#  semantically verb-like.
+#  e.g. ごらん, ご覧, 御覧, 頂戴
+#名詞-動詞非自立的
+#
+#  noun-quotation: text that cannot be segmented into words, proverbs, Chinese poetry, 
+#  dialects, English, etc. Currently, the only entry for 名詞 引用文字列 ("noun quotation") 
+#  is いわく ("iwaku").
+#名詞-引用文字列
+#
+#  noun-nai_adjective: Words that appear before the auxiliary verb ない ("nai") and
+#  behave like an adjective.
+#  e.g. 申し訳, 仕方, とんでも, 違い
+#名詞-ナイ形容詞語幹
+#
+#####
+#  prefix: unclassified prefixes
+#接頭詞
+#
+#  prefix-nominal: Prefixes that attach to nouns (including adjective stem forms) 
+#  excluding numerical expressions.
+#  e.g. お (水), 某 (氏), 同 (社), 故 (~氏), 高 (品質), お (見事), ご (立派)
+#接頭詞-名詞接続
+#
+#  prefix-verbal: Prefixes that attach to the imperative form of a verb or a verb
+#  in conjunctive form followed by なる/なさる/くださる.
+#  e.g. お (読みなさい), お (座り)
+#接頭詞-動詞接続
+#
+#  prefix-adjectival: Prefixes that attach to adjectives.
+#  e.g. お (寒いですねえ), バカ (でかい)
+#接頭詞-形容詞接続
+#
+#  prefix-numerical: Prefixes that attach to numerical expressions.
+#  e.g. 約, およそ, 毎時
+#接頭詞-数接続
+#
+#####
+#  verb: unclassified verbs
+#動詞
+#
+#  verb-main:
+#動詞-自立
+#
+#  verb-auxiliary:
+#動詞-非自立
+#
+#  verb-suffix:
+#動詞-接尾
+#
+#####
+#  adjective: unclassified adjectives
+#形容詞
+#
+#  adjective-main:
+#形容詞-自立
+#
+#  adjective-auxiliary:
+#形容詞-非自立
+#
+#  adjective-suffix:
+#形容詞-接尾
+#
+#####
+#  adverb: unclassified adverbs
+#副詞
+#
+#  adverb-misc: Words that can be segmented into one unit and where adnominal 
+#  modification is not possible.
+#  e.g. あいかわらず, 多分
+#副詞-一般
+#
+#  adverb-particle_conjunction: Adverbs that can be followed by の, は, に, 
+#  な, する, だ, etc.
+#  e.g. こんなに, そんなに, あんなに, なにか, なんでも
+#副詞-助詞類接続
+#
+#####
+#  adnominal: Words that only have noun-modifying forms.
+#  e.g. この, その, あの, どの, いわゆる, なんらかの, 何らかの, いろんな, こういう, そういう, ああいう, 
+#       どういう, こんな, そんな, あんな, どんな, 大きな, 小さな, おかしな, ほんの, たいした, 
+#       「(, も) さる (ことながら)」, 微々たる, 堂々たる, 単なる, いかなる, 我が」「同じ, 亡き
+#連体詞
+#
+#####
+#  conjunction: Conjunctions that can occur independently.
+#  e.g. が, けれども, そして, じゃあ, それどころか
+接続詞
+#
+#####
+#  particle: unclassified particles.
+助詞
+#
+#  particle-case: case particles where the subclassification is undefined.
+助詞-格助詞
+#
+#  particle-case-misc: Case particles.
+#  e.g. から, が, で, と, に, へ, より, を, の, にて
+助詞-格助詞-一般
+#
+#  particle-case-quote: the "to" that appears after nouns, a person’s speech, 
+#  quotation marks, expressions of decisions from a meeting, reasons, judgements,
+#  conjectures, etc.
+#  e.g. ( だ) と (述べた.), ( である) と (して執行猶予...)
+助詞-格助詞-引用
+#
+#  particle-case-compound: Compounds of particles and verbs that mainly behave 
+#  like case particles.
+#  e.g. という, といった, とかいう, として, とともに, と共に, でもって, にあたって, に当たって, に当って,
+#       にあたり, に当たり, に当り, に当たる, にあたる, において, に於いて,に於て, における, に於ける, 
+#       にかけ, にかけて, にかんし, に関し, にかんして, に関して, にかんする, に関する, に際し, 
+#       に際して, にしたがい, に従い, に従う, にしたがって, に従って, にたいし, に対し, にたいして, 
+#       に対して, にたいする, に対する, について, につき, につけ, につけて, につれ, につれて, にとって,
+#       にとり, にまつわる, によって, に依って, に因って, により, に依り, に因り, による, に依る, に因る, 
+#       にわたって, にわたる, をもって, を以って, を通じ, を通じて, を通して, をめぐって, をめぐり, をめぐる,
+#       って-口語/, ちゅう-関西弁「という」/, (何) ていう (人)-口語/, っていう-口語/, といふ, とかいふ
+助詞-格助詞-連語
+#
+#  particle-conjunctive:
+#  e.g. から, からには, が, けれど, けれども, けど, し, つつ, て, で, と, ところが, どころか, とも, ども, 
+#       ながら, なり, ので, のに, ば, ものの, や ( した), やいなや, (ころん) じゃ(いけない)-口語/, 
+#       (行っ) ちゃ(いけない)-口語/, (言っ) たって (しかたがない)-口語/, (それがなく)ったって (平気)-口語/
+助詞-接続助詞
+#
+#  particle-dependency:
+#  e.g. こそ, さえ, しか, すら, は, も, ぞ
+助詞-係助詞
+#
+#  particle-adverbial:
+#  e.g. がてら, かも, くらい, 位, ぐらい, しも, (学校) じゃ(これが流行っている)-口語/, 
+#       (それ)じゃあ (よくない)-口語/, ずつ, (私) なぞ, など, (私) なり (に), (先生) なんか (大嫌い)-口語/,
+#       (私) なんぞ, (先生) なんて (大嫌い)-口語/, のみ, だけ, (私) だって-口語/, だに, 
+#       (彼)ったら-口語/, (お茶) でも (いかが), 等 (とう), (今後) とも, ばかり, ばっか-口語/, ばっかり-口語/,
+#       ほど, 程, まで, 迄, (誰) も (が)([助詞-格助詞] および [助詞-係助詞] の前に位置する「も」)
+助詞-副助詞
+#
+#  particle-interjective: particles with interjective grammatical roles.
+#  e.g. (松島) や
+助詞-間投助詞
+#
+#  particle-coordinate:
+#  e.g. と, たり, だの, だり, とか, なり, や, やら
+助詞-並立助詞
+#
+#  particle-final:
+#  e.g. かい, かしら, さ, ぜ, (だ)っけ-口語/, (とまってる) で-方言/, な, ナ, なあ-口語/, ぞ, ね, ネ, 
+#       ねぇ-口語/, ねえ-口語/, ねん-方言/, の, のう-口語/, や, よ, ヨ, よぉ-口語/, わ, わい-口語/
+助詞-終助詞
+#
+#  particle-adverbial/conjunctive/final: The particle "ka" when unknown whether it is 
+#  adverbial, conjunctive, or sentence final. For example:
+#       (a) 「A か B か」. Ex:「(国内で運用する) か,(海外で運用する) か (.)」
+#       (b) Inside an adverb phrase. Ex:「(幸いという) か (, 死者はいなかった.)」
+#           「(祈りが届いたせい) か (, 試験に合格した.)」
+#       (c) 「かのように」. Ex:「(何もなかった) か (のように振る舞った.)」
+#  e.g. か
+助詞-副助詞/並立助詞/終助詞
+#
+#  particle-adnominalizer: The "no" that attaches to nouns and modifies 
+#  non-inflectional words.
+助詞-連体化
+#
+#  particle-adnominalizer: The "ni" and "to" that appear following nouns and adverbs 
+#  that are giongo, giseigo, or gitaigo.
+#  e.g. に, と
+助詞-副詞化
+#
+#  particle-special: A particle that does not fit into one of the above classifications. 
+#  This includes particles that are used in Tanka, Haiku, and other poetry.
+#  e.g. かな, けむ, ( しただろう) に, (あんた) にゃ(わからん), (俺) ん (家)
+助詞-特殊
+#
+#####
+#  auxiliary-verb:
+助動詞
+#
+#####
+#  interjection: Greetings and other exclamations.
+#  e.g. おはよう, おはようございます, こんにちは, こんばんは, ありがとう, どうもありがとう, ありがとうございます, 
+#       いただきます, ごちそうさま, さよなら, さようなら, はい, いいえ, ごめん, ごめんなさい
+#感動詞
+#
+#####
+#  symbol: unclassified Symbols.
+記号
+#
+#  symbol-misc: A general symbol not in one of the categories below.
+#  e.g. [○◎@$〒→+]
+記号-一般
+#
+#  symbol-comma: Commas
+#  e.g. [,、]
+記号-読点
+#
+#  symbol-period: Periods and full stops.
+#  e.g. [..。]
+記号-句点
+#
+#  symbol-space: Full-width whitespace.
+記号-空白
+#
+#  symbol-open_bracket:
+#  e.g. [({‘“『【]
+記号-括弧開
+#
+#  symbol-close_bracket:
+#  e.g. [)}’”』」】]
+記号-括弧閉
+#
+#  symbol-alphabetic:
+#記号-アルファベット
+#
+#####
+#  other: unclassified other
+#その他
+#
+#  other-interjection: Words that are hard to classify as noun-suffixes or 
+#  sentence-final particles.
+#  e.g. (だ)ァ
+その他-間投
+#
+#####
+#  filler: Aizuchi that occurs during a conversation or sounds inserted as filler.
+#  e.g. あの, うんと, えと
+フィラー
+#
+#####
+#  non-verbal: non-verbal sound.
+非言語音
+#
+#####
+#  fragment:
+#語断片
+#
+#####
+#  unknown: unknown part of speech.
+#未知語
+#
+##### End of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ar.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ar.txt
new file mode 100644
index 0000000..046829d
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ar.txt
@@ -0,0 +1,125 @@
+# This file was created by Jacques Savoy and is distributed under the BSD license.
+# See http://members.unine.ch/jacques.savoy/clef/index.html.
+# Also see http://www.opensource.org/licenses/bsd-license.html
+# Cleaned on October 11, 2009 (not normalized, so use before normalization)
+# This means that when modifying this list, you might need to add some 
+# redundant entries, for example containing forms with both أ and ا
+من
+ومن
+منها
+منه
+في
+وفي
+فيها
+فيه


+ثم
+او
+أو

+بها
+به


+اى
+اي
+أي
+أى
+لا
+ولا
+الا
+ألا
+إلا
+لكن
+ما
+وما
+كما
+فما
+عن
+مع
+اذا
+إذا
+ان
+أن
+إن
+انها
+أنها
+إنها
+انه
+أنه
+إنه
+بان
+بأن
+فان
+فأن
+وان
+وأن
+وإن
+التى
+التي
+الذى
+الذي
+الذين
+الى
+الي
+إلى
+إلي
+على
+عليها
+عليه
+اما
+أما
+إما
+ايضا
+أيضا
+كل
+وكل
+لم
+ولم
+لن
+ولن
+هى
+هي
+هو
+وهى
+وهي
+وهو
+فهى
+فهي
+فهو
+انت
+أنت
+لك
+لها
+له
+هذه
+هذا
+تلك
+ذلك
+هناك
+كانت
+كان
+يكون
+تكون
+وكانت
+وكان
+غير
+بعض
+قد
+نحو
+بين
+بينما
+منذ
+ضمن
+حيث
+الان
+الآن
+خلال
+بعد
+قبل
+حتى
+عند
+عندما
+لدى
+جميع
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_bg.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_bg.txt
new file mode 100644
index 0000000..1ae4ba2
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_bg.txt
@@ -0,0 +1,193 @@
+# This file was created by Jacques Savoy and is distributed under the BSD license.
+# See http://members.unine.ch/jacques.savoy/clef/index.html.
+# Also see http://www.opensource.org/licenses/bsd-license.html

+аз
+ако
+ала
+бе
+без
+беше
+би
+бил
+била
+били
+било
+близо
+бъдат
+бъде
+бяха

+вас
+ваш
+ваша
+вероятно
+вече
+взема
+ви
+вие
+винаги
+все
+всеки
+всички
+всичко
+всяка
+във
+въпреки
+върху

+ги
+главно
+го

+да
+дали
+до
+докато
+докога
+дори
+досега
+доста

+едва
+един
+ето
+за
+зад
+заедно
+заради
+засега
+затова
+защо
+защото

+из
+или
+им
+има
+имат
+иска

+каза
+как
+каква
+какво
+както
+какъв
+като
+кога
+когато
+което
+които
+кой
+който
+колко
+която
+къде
+където
+към
+ли

+ме
+между
+мен
+ми
+мнозина
+мога
+могат
+може
+моля
+момента
+му

+на
+над
+назад
+най
+направи
+напред
+например
+нас
+не
+него
+нея
+ни
+ние
+никой
+нито
+но
+някои
+някой
+няма
+обаче
+около
+освен
+особено
+от
+отгоре
+отново
+още
+пак
+по
+повече
+повечето
+под
+поне
+поради
+после
+почти
+прави
+пред
+преди
+през
+при
+пък
+първо

+са
+само
+се
+сега
+си
+скоро
+след
+сме
+според
+сред
+срещу
+сте
+съм
+със
+също

+тази
+така
+такива
+такъв
+там
+твой
+те
+тези
+ти
+тн
+то
+това
+тогава
+този
+той
+толкова
+точно
+трябва
+тук
+тъй
+тя
+тях

+харесва

+че
+често
+чрез
+ще
+щом

diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ca.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ca.txt
new file mode 100644
index 0000000..3da65de
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ca.txt
@@ -0,0 +1,220 @@
+# Catalan stopwords from http://github.com/vcl/cue.language (Apache 2 Licensed)
+a
+abans
+ací
+ah
+així
+això
+al
+als
+aleshores
+algun
+alguna
+algunes
+alguns
+alhora
+allà
+allí
+allò
+altra
+altre
+altres
+amb
+ambdós
+ambdues
+apa
+aquell
+aquella
+aquelles
+aquells
+aquest
+aquesta
+aquestes
+aquests
+aquí
+baix
+cada
+cadascú
+cadascuna
+cadascunes
+cadascuns
+com
+contra
+d'un
+d'una
+d'unes
+d'uns
+dalt
+de
+del
+dels
+des
+després
+dins
+dintre
+donat
+doncs
+durant
+e
+eh
+el
+els
+em
+en
+encara
+ens
+entre
+érem
+eren
+éreu
+es
+és
+esta
+està
+estàvem
+estaven
+estàveu
+esteu
+et
+etc
+ets
+fins
+fora
+gairebé
+ha
+han
+has
+havia
+he
+hem
+heu
+hi 
+ho
+i
+igual
+iguals
+ja
+l'hi
+la
+les
+li
+li'n
+llavors
+m'he
+ma
+mal
+malgrat
+mateix
+mateixa
+mateixes
+mateixos
+me
+mentre
+més
+meu
+meus
+meva
+meves
+molt
+molta
+moltes
+molts
+mon
+mons
+n'he
+n'hi
+ne
+ni
+no
+nogensmenys
+només
+nosaltres
+nostra
+nostre
+nostres
+o
+oh
+oi
+on
+pas
+pel
+pels
+per
+però
+perquè
+poc 
+poca
+pocs
+poques
+potser
+propi
+qual
+quals
+quan
+quant 
+que
+què
+quelcom
+qui
+quin
+quina
+quines
+quins
+s'ha
+s'han
+sa
+semblant
+semblants
+ses
+seu 
+seus
+seva
+seva
+seves
+si
+sobre
+sobretot
+sóc
+solament
+sols
+son 
+són
+sons 
+sota
+sou
+t'ha
+t'han
+t'he
+ta
+tal
+també
+tampoc
+tan
+tant
+tanta
+tantes
+teu
+teus
+teva
+teves
+ton
+tons
+tot
+tota
+totes
+tots
+un
+una
+unes
+uns
+us
+va
+vaig
+vam
+van
+vas
+veu
+vosaltres
+vostra
+vostre
+vostres
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ckb.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ckb.txt
new file mode 100644
index 0000000..87abf11
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ckb.txt
@@ -0,0 +1,136 @@
+# set of kurdish stopwords
+# note these have been normalized with our scheme (e represented with U+06D5, etc)
+# constructed from:
+# * Fig 5 of "Building A Test Collection For Sorani Kurdish" (Esmaili et al)
+# * "Sorani Kurdish: A Reference Grammar with selected readings" (Thackston)
+# * Corpus-based analysis of 77M word Sorani collection: wikipedia, news, blogs, etc
+
+# and

+# which
+کە
+# of

+# made/did
+کرد
+# that/which
+ئەوەی
+# on/head
+سەر
+# two
+دوو
+# also
+هەروەها
+# from/that
+لەو
+# makes/does
+دەکات
+# some
+چەند
+# every
+هەر
+
+# demonstratives
+# that
+ئەو
+# this
+ئەم
+
+# personal pronouns
+# I
+من
+# we
+ئێمە
+# you
+تۆ
+# you
+ئێوە
+# he/she/it
+ئەو
+# they
+ئەوان
+
+# prepositions
+# to/with/by
+بە
+پێ
+# without
+بەبێ
+# along with/while/during
+بەدەم
+# in the opinion of
+بەلای
+# according to
+بەپێی
+# before
+بەرلە
+# in the direction of
+بەرەوی
+# in front of/toward
+بەرەوە
+# before/in the face of
+بەردەم
+# without
+بێ
+# except for
+بێجگە
+# for
+بۆ
+# on/in
+دە
+تێ
+# with
+دەگەڵ
+# after
+دوای
+# except for/aside from
+جگە
+# in/from
+لە
+لێ
+# in front of/before/because of
+لەبەر
+# between/among
+لەبەینی
+# concerning/about
+لەبابەت
+# concerning
+لەبارەی
+# instead of
+لەباتی
+# beside
+لەبن
+# instead of
+لەبرێتی
+# behind
+لەدەم
+# with/together with
+لەگەڵ
+# by
+لەلایەن
+# within
+لەناو
+# between/among
+لەنێو
+# for the sake of
+لەپێناوی
+# with respect to
+لەرەوی
+# by means of/for
+لەرێ
+# for the sake of
+لەرێگا
+# on/on top of/according to
+لەسەر
+# under
+لەژێر
+# between/among
+ناو
+# between/among
+نێوان
+# after
+پاش
+# before
+پێش
+# like
+وەک
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_cz.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_cz.txt
new file mode 100644
index 0000000..53c6097
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_cz.txt
@@ -0,0 +1,172 @@
+a
+s
+k
+o
+i
+u
+v
+z
+dnes
+cz
+tímto
+budeš
+budem
+byli
+jseš
+můj
+svým
+ta
+tomto
+tohle
+tuto
+tyto
+jej
+zda
+proč
+máte
+tato
+kam
+tohoto
+kdo
+kteří
+mi
+nám
+tom
+tomuto
+mít
+nic
+proto
+kterou
+byla
+toho
+protože
+asi
+ho
+naši
+napište
+re
+což
+tím
+takže
+svých
+její
+svými
+jste
+aj
+tu
+tedy
+teto
+bylo
+kde
+ke
+pravé
+ji
+nad
+nejsou
+či
+pod
+téma
+mezi
+přes
+ty
+pak
+vám
+ani
+když
+však
+neg
+jsem
+tento
+článku
+články
+aby
+jsme
+před
+pta
+jejich
+byl
+ještě
+až
+bez
+také
+pouze
+první
+vaše
+která
+nás
+nový
+tipy
+pokud
+může
+strana
+jeho
+své
+jiné
+zprávy
+nové
+není
+vás
+jen
+podle
+zde
+už
+být
+více
+bude
+již
+než
+který
+by
+které
+co
+nebo
+ten
+tak
+má
+při
+od
+po
+jsou
+jak
+další
+ale
+si
+se
+ve
+to
+jako
+za
+zpět
+ze
+do
+pro
+je
+na
+atd
+atp
+jakmile
+přičemž
+já
+on
+ona
+ono
+oni
+ony
+my
+vy
+jí
+ji
+mě
+mne
+jemu
+tomu
+těm
+těmu
+němu
+němuž
+jehož
+jíž
+jelikož
+jež
+jakož
+načež
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_da.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_da.txt
new file mode 100644
index 0000000..42e6145
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_da.txt
@@ -0,0 +1,110 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/danish/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A Danish stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+ | This is a ranked list (commonest to rarest) of stopwords derived from
+ | a large text sample.
+
+
+og           | and
+i            | in
+jeg          | I
+det          | that (dem. pronoun)/it (pers. pronoun)
+at           | that (in front of a sentence)/to (with infinitive)
+en           | a/an
+den          | it (pers. pronoun)/that (dem. pronoun)
+til          | to/at/for/until/against/by/of/into, more
+er           | present tense of "to be"
+som          | who, as
+på           | on/upon/in/on/at/to/after/of/with/for, on
+de           | they
+med          | with/by/in, along
+han          | he
+af           | of/by/from/off/for/in/with/on, off
+for          | at/for/to/from/by/of/ago, in front/before, because
+ikke         | not
+der          | who/which, there/those
+var          | past tense of "to be"
+mig          | me/myself
+sig          | oneself/himself/herself/itself/themselves
+men          | but
+et           | a/an/one, one (number), someone/somebody/one
+har          | present tense of "to have"
+om           | round/about/for/in/a, about/around/down, if
+vi           | we
+min          | my
+havde        | past tense of "to have"
+ham          | him
+hun          | she
+nu           | now
+over         | over/above/across/by/beyond/past/on/about, over/past
+da           | then, when/as/since
+fra          | from/off/since, off, since
+du           | you
+ud           | out
+sin          | his/her/its/one's
+dem          | them
+os           | us/ourselves
+op           | up
+man          | you/one
+hans         | his
+hvor         | where
+eller        | or
+hvad         | what
+skal         | must/shall etc.
+selv         | myself/youself/herself/ourselves etc., even
+her          | here
+alle         | all/everyone/everybody etc.
+vil          | will (verb)
+blev         | past tense of "to stay/to remain/to get/to become"
+kunne        | could
+ind          | in
+når          | when
+være         | present tense of "to be"
+dog          | however/yet/after all
+noget        | something
+ville        | would
+jo           | you know/you see (adv), yes
+deres        | their/theirs
+efter        | after/behind/according to/for/by/from, later/afterwards
+ned          | down
+skulle       | should
+denne        | this
+end          | than
+dette        | this
+mit          | my/mine
+også         | also
+under        | under/beneath/below/during, below/underneath
+have         | have
+dig          | you
+anden        | other
+hende        | her
+mine         | my
+alt          | everything
+meget        | much/very, plenty of
+sit          | his, her, its, one's
+sine         | his, her, its, one's
+vor          | our
+mod          | against
+disse        | these
+hvis         | if
+din          | your/yours
+nogle        | some
+hos          | by/at
+blive        | be/become
+mange        | many
+ad           | by/through
+bliver       | present tense of "to be/to become"
+hendes       | her/hers
+været        | be
+thi          | for (conj)
+jer          | you
+sådan        | such, like this/like that
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_de.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_de.txt
new file mode 100644
index 0000000..86525e7
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_de.txt
@@ -0,0 +1,294 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/german/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A German stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+ | The number of forms in this list is reduced significantly by passing it
+ | through the German stemmer.
+
+
+aber           |  but
+
+alle           |  all
+allem
+allen
+aller
+alles
+
+als            |  than, as
+also           |  so
+am             |  an + dem
+an             |  at
+
+ander          |  other
+andere
+anderem
+anderen
+anderer
+anderes
+anderm
+andern
+anderr
+anders
+
+auch           |  also
+auf            |  on
+aus            |  out of
+bei            |  by
+bin            |  am
+bis            |  until
+bist           |  art
+da             |  there
+damit          |  with it
+dann           |  then
+
+der            |  the
+den
+des
+dem
+die
+das
+
+daß            |  that
+
+derselbe       |  the same
+derselben
+denselben
+desselben
+demselben
+dieselbe
+dieselben
+dasselbe
+
+dazu           |  to that
+
+dein           |  thy
+deine
+deinem
+deinen
+deiner
+deines
+
+denn           |  because
+
+derer          |  of those
+dessen         |  of him
+
+dich           |  thee
+dir            |  to thee
+du             |  thou
+
+dies           |  this
+diese
+diesem
+diesen
+dieser
+dieses
+
+
+doch           |  (several meanings)
+dort           |  (over) there
+
+
+durch          |  through
+
+ein            |  a
+eine
+einem
+einen
+einer
+eines
+
+einig          |  some
+einige
+einigem
+einigen
+einiger
+einiges
+
+einmal         |  once
+
+er             |  he
+ihn            |  him
+ihm            |  to him
+
+es             |  it
+etwas          |  something
+
+euer           |  your
+eure
+eurem
+euren
+eurer
+eures
+
+für            |  for
+gegen          |  towards
+gewesen        |  p.p. of sein
+hab            |  have
+habe           |  have
+haben          |  have
+hat            |  has
+hatte          |  had
+hatten         |  had
+hier           |  here
+hin            |  there
+hinter         |  behind
+
+ich            |  I
+mich           |  me
+mir            |  to me
+
+
+ihr            |  you, to her
+ihre
+ihrem
+ihren
+ihrer
+ihres
+euch           |  to you
+
+im             |  in + dem
+in             |  in
+indem          |  while
+ins            |  in + das
+ist            |  is
+
+jede           |  each, every
+jedem
+jeden
+jeder
+jedes
+
+jene           |  that
+jenem
+jenen
+jener
+jenes
+
+jetzt          |  now
+kann           |  can
+
+kein           |  no
+keine
+keinem
+keinen
+keiner
+keines
+
+können         |  can
+könnte         |  could
+machen         |  do
+man            |  one
+
+manche         |  some, many a
+manchem
+manchen
+mancher
+manches
+
+mein           |  my
+meine
+meinem
+meinen
+meiner
+meines
+
+mit            |  with
+muss           |  must
+musste         |  had to
+nach           |  to(wards)
+nicht          |  not
+nichts         |  nothing
+noch           |  still, yet
+nun            |  now
+nur            |  only
+ob             |  whether
+oder           |  or
+ohne           |  without
+sehr           |  very
+
+sein           |  his
+seine
+seinem
+seinen
+seiner
+seines
+
+selbst         |  self
+sich           |  herself
+
+sie            |  they, she
+ihnen          |  to them
+
+sind           |  are
+so             |  so
+
+solche         |  such
+solchem
+solchen
+solcher
+solches
+
+soll           |  shall
+sollte         |  should
+sondern        |  but
+sonst          |  else
+über           |  over
+um             |  about, around
+und            |  and
+
+uns            |  us
+unse
+unsem
+unsen
+unser
+unses
+
+unter          |  under
+viel           |  much
+vom            |  von + dem
+von            |  from
+vor            |  before
+während        |  while
+war            |  was
+waren          |  were
+warst          |  wast
+was            |  what
+weg            |  away, off
+weil           |  because
+weiter         |  further
+
+welche         |  which
+welchem
+welchen
+welcher
+welches
+
+wenn           |  when
+werde          |  will
+werden         |  will
+wie            |  how
+wieder         |  again
+will           |  want
+wir            |  we
+wird           |  will
+wirst          |  willst
+wo             |  where
+wollen         |  want
+wollte         |  wanted
+würde          |  would
+würden         |  would
+zu             |  to
+zum            |  zu + dem
+zur            |  zu + der
+zwar           |  indeed
+zwischen       |  between
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_el.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_el.txt
new file mode 100644
index 0000000..232681f
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_el.txt
@@ -0,0 +1,78 @@
+# Lucene Greek Stopwords list
+# Note: by default this file is used after GreekLowerCaseFilter,
+# so when modifying this file use 'σ' instead of 'ς' 
+ο

+το
+οι
+τα
+του
+τησ
+των
+τον
+την
+και 
+κι

+ειμαι
+εισαι
+ειναι
+ειμαστε
+ειστε
+στο
+στον
+στη
+στην
+μα
+αλλα
+απο
+για
+προσ
+με
+σε
+ωσ
+παρα
+αντι
+κατα
+μετα
+θα
+να
+δε
+δεν
+μη
+μην
+επι
+ενω
+εαν
+αν
+τοτε
+που
+πωσ
+ποιοσ
+ποια
+ποιο
+ποιοι
+ποιεσ
+ποιων
+ποιουσ
+αυτοσ
+αυτη
+αυτο
+αυτοι
+αυτων
+αυτουσ
+αυτεσ
+αυτα
+εκεινοσ
+εκεινη
+εκεινο
+εκεινοι
+εκεινεσ
+εκεινα
+εκεινων
+εκεινουσ
+οπωσ
+ομωσ
+ισωσ
+οσο
+οτι
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_en.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_en.txt
new file mode 100644
index 0000000..2c164c0
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_en.txt
@@ -0,0 +1,54 @@
+# 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.
+
+# a couple of test stopwords to test that the words are really being
+# configured from this file:
+stopworda
+stopwordb
+
+# Standard english stop words taken from Lucene's StopAnalyzer
+a
+an
+and
+are
+as
+at
+be
+but
+by
+for
+if
+in
+into
+is
+it
+no
+not
+of
+on
+or
+such
+that
+the
+their
+then
+there
+these
+they
+this
+to
+was
+will
+with
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_es.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_es.txt
new file mode 100644
index 0000000..487d78c
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_es.txt
@@ -0,0 +1,356 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/spanish/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A Spanish stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+
+ | The following is a ranked list (commonest to rarest) of stopwords
+ | deriving from a large sample of text.
+
+ | Extra words have been added at the end.
+
+de             |  from, of
+la             |  the, her
+que            |  who, that
+el             |  the
+en             |  in
+y              |  and
+a              |  to
+los            |  the, them
+del            |  de + el
+se             |  himself, from him etc
+las            |  the, them
+por            |  for, by, etc
+un             |  a
+para           |  for
+con            |  with
+no             |  no
+una            |  a
+su             |  his, her
+al             |  a + el
+  | es         from SER
+lo             |  him
+como           |  how
+más            |  more
+pero           |  pero
+sus            |  su plural
+le             |  to him, her
+ya             |  already
+o              |  or
+  | fue        from SER
+este           |  this
+  | ha         from HABER
+sí             |  himself etc
+porque         |  because
+esta           |  this
+  | son        from SER
+entre          |  between
+  | está     from ESTAR
+cuando         |  when
+muy            |  very
+sin            |  without
+sobre          |  on
+  | ser        from SER
+  | tiene      from TENER
+también        |  also
+me             |  me
+hasta          |  until
+hay            |  there is/are
+donde          |  where
+  | han        from HABER
+quien          |  whom, that
+  | están      from ESTAR
+  | estado     from ESTAR
+desde          |  from
+todo           |  all
+nos            |  us
+durante        |  during
+  | estados    from ESTAR
+todos          |  all
+uno            |  a
+les            |  to them
+ni             |  nor
+contra         |  against
+otros          |  other
+  | fueron     from SER
+ese            |  that
+eso            |  that
+  | había      from HABER
+ante           |  before
+ellos          |  they
+e              |  and (variant of y)
+esto           |  this
+mí             |  me
+antes          |  before
+algunos        |  some
+qué            |  what?
+unos           |  a
+yo             |  I
+otro           |  other
+otras          |  other
+otra           |  other
+él             |  he
+tanto          |  so much, many
+esa            |  that
+estos          |  these
+mucho          |  much, many
+quienes        |  who
+nada           |  nothing
+muchos         |  many
+cual           |  who
+  | sea        from SER
+poco           |  few
+ella           |  she
+estar          |  to be
+  | haber      from HABER
+estas          |  these
+  | estaba     from ESTAR
+  | estamos    from ESTAR
+algunas        |  some
+algo           |  something
+nosotros       |  we
+
+      | other forms
+
+mi             |  me
+mis            |  mi plural
+tú             |  thou
+te             |  thee
+ti             |  thee
+tu             |  thy
+tus            |  tu plural
+ellas          |  they
+nosotras       |  we
+vosotros       |  you
+vosotras       |  you
+os             |  you
+mío            |  mine
+mía            |
+míos           |
+mías           |
+tuyo           |  thine
+tuya           |
+tuyos          |
+tuyas          |
+suyo           |  his, hers, theirs
+suya           |
+suyos          |
+suyas          |
+nuestro        |  ours
+nuestra        |
+nuestros       |
+nuestras       |
+vuestro        |  yours
+vuestra        |
+vuestros       |
+vuestras       |
+esos           |  those
+esas           |  those
+
+               | forms of estar, to be (not including the infinitive):
+estoy
+estás
+está
+estamos
+estáis
+están
+esté
+estés
+estemos
+estéis
+estén
+estaré
+estarás
+estará
+estaremos
+estaréis
+estarán
+estaría
+estarías
+estaríamos
+estaríais
+estarían
+estaba
+estabas
+estábamos
+estabais
+estaban
+estuve
+estuviste
+estuvo
+estuvimos
+estuvisteis
+estuvieron
+estuviera
+estuvieras
+estuviéramos
+estuvierais
+estuvieran
+estuviese
+estuvieses
+estuviésemos
+estuvieseis
+estuviesen
+estando
+estado
+estada
+estados
+estadas
+estad
+
+               | forms of haber, to have (not including the infinitive):
+he
+has
+ha
+hemos
+habéis
+han
+haya
+hayas
+hayamos
+hayáis
+hayan
+habré
+habrás
+habrá
+habremos
+habréis
+habrán
+habría
+habrías
+habríamos
+habríais
+habrían
+había
+habías
+habíamos
+habíais
+habían
+hube
+hubiste
+hubo
+hubimos
+hubisteis
+hubieron
+hubiera
+hubieras
+hubiéramos
+hubierais
+hubieran
+hubiese
+hubieses
+hubiésemos
+hubieseis
+hubiesen
+habiendo
+habido
+habida
+habidos
+habidas
+
+               | forms of ser, to be (not including the infinitive):
+soy
+eres
+es
+somos
+sois
+son
+sea
+seas
+seamos
+seáis
+sean
+seré
+serás
+será
+seremos
+seréis
+serán
+sería
+serías
+seríamos
+seríais
+serían
+era
+eras
+éramos
+erais
+eran
+fui
+fuiste
+fue
+fuimos
+fuisteis
+fueron
+fuera
+fueras
+fuéramos
+fuerais
+fueran
+fuese
+fueses
+fuésemos
+fueseis
+fuesen
+siendo
+sido
+  |  sed also means 'thirst'
+
+               | forms of tener, to have (not including the infinitive):
+tengo
+tienes
+tiene
+tenemos
+tenéis
+tienen
+tenga
+tengas
+tengamos
+tengáis
+tengan
+tendré
+tendrás
+tendrá
+tendremos
+tendréis
+tendrán
+tendría
+tendrías
+tendríamos
+tendríais
+tendrían
+tenía
+tenías
+teníamos
+teníais
+tenían
+tuve
+tuviste
+tuvo
+tuvimos
+tuvisteis
+tuvieron
+tuviera
+tuvieras
+tuviéramos
+tuvierais
+tuvieran
+tuviese
+tuvieses
+tuviésemos
+tuvieseis
+tuviesen
+teniendo
+tenido
+tenida
+tenidos
+tenidas
+tened
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_eu.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_eu.txt
new file mode 100644
index 0000000..25f1db9
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_eu.txt
@@ -0,0 +1,99 @@
+# example set of basque stopwords
+al
+anitz
+arabera
+asko
+baina
+bat
+batean
+batek
+bati
+batzuei
+batzuek
+batzuetan
+batzuk
+bera
+beraiek
+berau
+berauek
+bere
+berori
+beroriek
+beste
+bezala
+da
+dago
+dira
+ditu
+du
+dute
+edo
+egin
+ere
+eta
+eurak
+ez
+gainera
+gu
+gutxi
+guzti
+haiei
+haiek
+haietan
+hainbeste
+hala
+han
+handik
+hango
+hara
+hari
+hark
+hartan
+hau
+hauei
+hauek
+hauetan
+hemen
+hemendik
+hemengo
+hi
+hona
+honek
+honela
+honetan
+honi
+hor
+hori
+horiei
+horiek
+horietan
+horko
+horra
+horrek
+horrela
+horretan
+horri
+hortik
+hura
+izan
+ni
+noiz
+nola
+non
+nondik
+nongo
+nor
+nora
+ze
+zein
+zen
+zenbait
+zenbat
+zer
+zergatik
+ziren
+zituen
+zu
+zuek
+zuen
+zuten
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_fa.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_fa.txt
new file mode 100644
index 0000000..723641c
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_fa.txt
@@ -0,0 +1,313 @@
+# This file was created by Jacques Savoy and is distributed under the BSD license.
+# See http://members.unine.ch/jacques.savoy/clef/index.html.
+# Also see http://www.opensource.org/licenses/bsd-license.html
+# Note: by default this file is used after normalization, so when adding entries
+# to this file, use the arabic 'ي' instead of 'ی'
+انان
+نداشته
+سراسر
+خياه
+ايشان
+وي
+تاكنون
+بيشتري
+دوم
+پس
+ناشي
+وگو
+يا
+داشتند
+سپس
+هنگام
+هرگز
+پنج
+نشان
+امسال
+ديگر
+گروهي
+شدند
+چطور
+ده

+دو
+نخستين
+ولي
+چرا
+چه
+وسط

+كدام
+قابل
+يك
+رفت
+هفت
+همچنين
+در
+هزار
+بله
+بلي
+شايد
+اما
+شناسي
+گرفته
+دهد
+داشته
+دانست
+داشتن
+خواهيم
+ميليارد
+وقتيكه
+امد
+خواهد
+جز
+اورده
+شده
+بلكه
+خدمات
+شدن
+برخي
+نبود
+بسياري
+جلوگيري
+حق
+كردند
+نوعي
+بعري
+نكرده
+نظير
+نبايد
+بوده
+بودن
+داد
+اورد
+هست
+جايي
+شود
+دنبال
+داده
+بايد
+سابق
+هيچ
+همان
+انجا
+كمتر
+كجاست
+گردد
+كسي
+تر
+مردم
+تان
+دادن
+بودند
+سري
+جدا
+ندارند
+مگر
+يكديگر
+دارد
+دهند
+بنابراين
+هنگامي
+سمت
+جا
+انچه
+خود
+دادند
+زياد
+دارند
+اثر
+بدون
+بهترين
+بيشتر
+البته
+به
+براساس
+بيرون
+كرد
+بعضي
+گرفت
+توي
+اي
+ميليون
+او
+جريان
+تول
+بر
+مانند
+برابر
+باشيم
+مدتي
+گويند
+اكنون
+تا
+تنها
+جديد
+چند
+بي
+نشده
+كردن
+كردم
+گويد
+كرده
+كنيم
+نمي
+نزد
+روي
+قصد
+فقط
+بالاي
+ديگران
+اين
+ديروز
+توسط
+سوم
+ايم
+دانند
+سوي
+استفاده
+شما
+كنار
+داريم
+ساخته
+طور
+امده
+رفته
+نخست
+بيست
+نزديك
+طي
+كنيد
+از
+انها
+تمامي
+داشت
+يكي
+طريق
+اش
+چيست
+روب
+نمايد
+گفت
+چندين
+چيزي
+تواند
+ام
+ايا
+با
+ان
+ايد
+ترين
+اينكه
+ديگري
+راه
+هايي
+بروز
+همچنان
+پاعين
+كس
+حدود
+مختلف
+مقابل
+چيز
+گيرد
+ندارد
+ضد
+همچون
+سازي
+شان
+مورد
+باره
+مرسي
+خويش
+برخوردار
+چون
+خارج
+شش
+هنوز
+تحت
+ضمن
+هستيم
+گفته
+فكر
+بسيار
+پيش
+براي
+روزهاي
+انكه
+نخواهد
+بالا
+كل
+وقتي
+كي
+چنين
+كه
+گيري
+نيست
+است
+كجا
+كند
+نيز
+يابد
+بندي
+حتي
+توانند
+عقب
+خواست
+كنند
+بين
+تمام
+همه
+ما
+باشند
+مثل
+شد
+اري
+باشد
+اره
+طبق
+بعد
+اگر
+صورت
+غير
+جاي
+بيش
+ريزي
+اند
+زيرا
+چگونه
+بار
+لطفا
+مي
+درباره
+من
+ديده
+همين
+گذاري
+برداري
+علت
+گذاشته
+هم
+فوق
+نه
+ها
+شوند
+اباد
+همواره
+هر
+اول
+خواهند
+چهار
+نام
+امروز
+مان
+هاي
+قبل
+كنم
+سعي
+تازه
+را
+هستند
+زير
+جلوي
+عنوان
+بود
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_fi.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_fi.txt
new file mode 100644
index 0000000..4372c9a
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_fi.txt
@@ -0,0 +1,97 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/finnish/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+ 
+| forms of BE
+
+olla
+olen
+olet
+on
+olemme
+olette
+ovat
+ole        | negative form
+
+oli
+olisi
+olisit
+olisin
+olisimme
+olisitte
+olisivat
+olit
+olin
+olimme
+olitte
+olivat
+ollut
+olleet
+
+en         | negation
+et
+ei
+emme
+ette
+eivät
+
+|Nom   Gen    Acc    Part   Iness   Elat    Illat  Adess   Ablat   Allat   Ess    Trans
+minä   minun  minut  minua  minussa minusta minuun minulla minulta minulle               | I
+sinä   sinun  sinut  sinua  sinussa sinusta sinuun sinulla sinulta sinulle               | you
+hän    hänen  hänet  häntä  hänessä hänestä häneen hänellä häneltä hänelle               | he she
+me     meidän meidät meitä  meissä  meistä  meihin meillä  meiltä  meille                | we
+te     teidän teidät teitä  teissä  teistä  teihin teillä  teiltä  teille                | you
+he     heidän heidät heitä  heissä  heistä  heihin heillä  heiltä  heille                | they
+
+tämä   tämän         tätä   tässä   tästä   tähän  tallä   tältä   tälle   tänä   täksi  | this
+tuo    tuon          tuotä  tuossa  tuosta  tuohon tuolla  tuolta  tuolle  tuona  tuoksi | that
+se     sen           sitä   siinä   siitä   siihen sillä   siltä   sille   sinä   siksi  | it
+nämä   näiden        näitä  näissä  näistä  näihin näillä  näiltä  näille  näinä  näiksi | these
+nuo    noiden        noita  noissa  noista  noihin noilla  noilta  noille  noina  noiksi | those
+ne     niiden        niitä  niissä  niistä  niihin niillä  niiltä  niille  niinä  niiksi | they
+
+kuka   kenen kenet   ketä   kenessä kenestä keneen kenellä keneltä kenelle kenenä keneksi| who
+ketkä  keiden ketkä  keitä  keissä  keistä  keihin keillä  keiltä  keille  keinä  keiksi | (pl)
+mikä   minkä minkä   mitä   missä   mistä   mihin  millä   miltä   mille   minä   miksi  | which what
+mitkä                                                                                    | (pl)
+
+joka   jonka         jota   jossa   josta   johon  jolla   jolta   jolle   jona   joksi  | who which
+jotka  joiden        joita  joissa  joista  joihin joilla  joilta  joille  joina  joiksi | (pl)
+
+| conjunctions
+
+että   | that
+ja     | and
+jos    | if
+koska  | because
+kuin   | than
+mutta  | but
+niin   | so
+sekä   | and
+sillä  | for
+tai    | or
+vaan   | but
+vai    | or
+vaikka | although
+
+
+| prepositions
+
+kanssa  | with
+mukaan  | according to
+noin    | about
+poikki  | across
+yli     | over, across
+
+| other
+
+kun    | when
+niin   | so
+nyt    | now
+itse   | self
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_fr.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_fr.txt
new file mode 100644
index 0000000..749abae
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_fr.txt
@@ -0,0 +1,186 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/french/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A French stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+au             |  a + le
+aux            |  a + les
+avec           |  with
+ce             |  this
+ces            |  these
+dans           |  with
+de             |  of
+des            |  de + les
+du             |  de + le
+elle           |  she
+en             |  `of them' etc
+et             |  and
+eux            |  them
+il             |  he
+je             |  I
+la             |  the
+le             |  the
+leur           |  their
+lui            |  him
+ma             |  my (fem)
+mais           |  but
+me             |  me
+même           |  same; as in moi-même (myself) etc
+mes            |  me (pl)
+moi            |  me
+mon            |  my (masc)
+ne             |  not
+nos            |  our (pl)
+notre          |  our
+nous           |  we
+on             |  one
+ou             |  where
+par            |  by
+pas            |  not
+pour           |  for
+qu             |  que before vowel
+que            |  that
+qui            |  who
+sa             |  his, her (fem)
+se             |  oneself
+ses            |  his (pl)
+son            |  his, her (masc)
+sur            |  on
+ta             |  thy (fem)
+te             |  thee
+tes            |  thy (pl)
+toi            |  thee
+ton            |  thy (masc)
+tu             |  thou
+un             |  a
+une            |  a
+vos            |  your (pl)
+votre          |  your
+vous           |  you
+
+               |  single letter forms
+
+c              |  c'
+d              |  d'
+j              |  j'
+l              |  l'
+à              |  to, at
+m              |  m'
+n              |  n'
+s              |  s'
+t              |  t'
+y              |  there
+
+               | forms of être (not including the infinitive):
+été
+étée
+étées
+étés
+étant
+suis
+es
+est
+sommes
+êtes
+sont
+serai
+seras
+sera
+serons
+serez
+seront
+serais
+serait
+serions
+seriez
+seraient
+étais
+était
+étions
+étiez
+étaient
+fus
+fut
+fûmes
+fûtes
+furent
+sois
+soit
+soyons
+soyez
+soient
+fusse
+fusses
+fût
+fussions
+fussiez
+fussent
+
+               | forms of avoir (not including the infinitive):
+ayant
+eu
+eue
+eues
+eus
+ai
+as
+avons
+avez
+ont
+aurai
+auras
+aura
+aurons
+aurez
+auront
+aurais
+aurait
+aurions
+auriez
+auraient
+avais
+avait
+avions
+aviez
+avaient
+eut
+eûmes
+eûtes
+eurent
+aie
+aies
+ait
+ayons
+ayez
+aient
+eusse
+eusses
+eût
+eussions
+eussiez
+eussent
+
+               | Later additions (from Jean-Christophe Deschamps)
+ceci           |  this
+cela           |  that
+celà           |  that
+cet            |  this
+cette          |  this
+ici            |  here
+ils            |  they
+les            |  the (pl)
+leurs          |  their (pl)
+quel           |  which
+quels          |  which
+quelle         |  which
+quelles        |  which
+sans           |  without
+soi            |  oneself
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ga.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ga.txt
new file mode 100644
index 0000000..9ff88d7
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ga.txt
@@ -0,0 +1,110 @@
+
+a
+ach
+ag
+agus
+an
+aon
+ar
+arna
+as
+b'
+ba
+beirt
+bhúr
+caoga
+ceathair
+ceathrar
+chomh
+chtó
+chuig
+chun
+cois
+céad
+cúig
+cúigear
+d'
+daichead
+dar
+de
+deich
+deichniúr
+den
+dhá
+do
+don
+dtí
+dá
+dár
+dó
+faoi
+faoin
+faoina
+faoinár
+fara
+fiche
+gach
+gan
+go
+gur
+haon
+hocht
+i
+iad
+idir
+in
+ina
+ins
+inár
+is
+le
+leis
+lena
+lenár
+m'
+mar
+mo
+mé
+na
+nach
+naoi
+naonúr
+ná
+ní
+níor
+nó
+nócha
+ocht
+ochtar
+os
+roimh
+sa
+seacht
+seachtar
+seachtó
+seasca
+seisear
+siad
+sibh
+sinn
+sna
+sé
+sí
+tar
+thar
+thú
+triúr
+trí
+trína
+trínár
+tríocha
+tú
+um
+ár

+éis


+ón
+óna
+ónár
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_gl.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_gl.txt
new file mode 100644
index 0000000..d8760b1
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_gl.txt
@@ -0,0 +1,161 @@
+# galican stopwords
+a
+aínda
+alí
+aquel
+aquela
+aquelas
+aqueles
+aquilo
+aquí
+ao
+aos
+as
+así

+ben
+cando
+che
+co
+coa
+comigo
+con
+connosco
+contigo
+convosco
+coas
+cos
+cun
+cuns
+cunha
+cunhas
+da
+dalgunha
+dalgunhas
+dalgún
+dalgúns
+das
+de
+del
+dela
+delas
+deles
+desde
+deste
+do
+dos
+dun
+duns
+dunha
+dunhas
+e
+el
+ela
+elas
+eles
+en
+era
+eran
+esa
+esas
+ese
+eses
+esta
+estar
+estaba
+está
+están
+este
+estes
+estiven
+estou
+eu

+facer
+foi
+foron
+fun
+había
+hai
+iso
+isto
+la
+las
+lle
+lles
+lo
+los
+mais
+me
+meu
+meus
+min
+miña
+miñas
+moi
+na
+nas
+neste
+nin
+no
+non
+nos
+nosa
+nosas
+noso
+nosos
+nós
+nun
+nunha
+nuns
+nunhas
+o
+os
+ou

+ós
+para
+pero
+pode
+pois
+pola
+polas
+polo
+polos
+por
+que
+se
+senón
+ser
+seu
+seus
+sexa
+sido
+sobre
+súa
+súas
+tamén
+tan
+te
+ten
+teñen
+teño
+ter
+teu
+teus
+ti
+tido
+tiña
+tiven
+túa
+túas
+un
+unha
+unhas
+uns
+vos
+vosa
+vosas
+voso
+vosos
+vós
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_hi.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_hi.txt
new file mode 100644
index 0000000..86286bb
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_hi.txt
@@ -0,0 +1,235 @@
+# Also see http://www.opensource.org/licenses/bsd-license.html
+# See http://members.unine.ch/jacques.savoy/clef/index.html.
+# This file was created by Jacques Savoy and is distributed under the BSD license.
+# Note: by default this file also contains forms normalized by HindiNormalizer 
+# for spelling variation (see section below), such that it can be used whether or 
+# not you enable that feature. When adding additional entries to this list,
+# please add the normalized form as well. 
+अंदर
+अत
+अपना
+अपनी
+अपने
+अभी
+आदि
+आप
+इत्यादि
+इन 
+इनका
+इन्हीं
+इन्हें
+इन्हों
+इस
+इसका
+इसकी
+इसके
+इसमें
+इसी
+इसे
+उन
+उनका
+उनकी
+उनके
+उनको
+उन्हीं
+उन्हें
+उन्हों
+उस
+उसके
+उसी
+उसे
+एक
+एवं
+एस
+ऐसे
+और
+कई
+कर
+करता
+करते
+करना
+करने
+करें
+कहते
+कहा
+का
+काफ़ी
+कि
+कितना
+किन्हें
+किन्हों
+किया
+किर
+किस
+किसी
+किसे
+की
+कुछ
+कुल
+के
+को
+कोई
+कौन
+कौनसा
+गया
+घर
+जब
+जहाँ
+जा
+जितना
+जिन
+जिन्हें
+जिन्हों
+जिस
+जिसे
+जीधर
+जैसा
+जैसे
+जो
+तक
+तब
+तरह
+तिन
+तिन्हें
+तिन्हों
+तिस
+तिसे
+तो
+था
+थी
+थे
+दबारा
+दिया
+दुसरा
+दूसरे
+दो
+द्वारा
+न
+नहीं
+ना
+निहायत
+नीचे
+ने
+पर
+पर  
+पहले
+पूरा
+पे
+फिर
+बनी
+बही
+बहुत
+बाद
+बाला
+बिलकुल
+भी
+भीतर
+मगर
+मानो
+मे
+में
+यदि
+यह
+यहाँ
+यही
+या
+यिह 
+ये
+रखें
+रहा
+रहे
+ऱ्वासा
+लिए
+लिये
+लेकिन
+व
+वर्ग
+वह
+वह 
+वहाँ
+वहीं
+वाले
+वुह 
+वे
+वग़ैरह
+संग
+सकता
+सकते
+सबसे
+सभी
+साथ
+साबुत
+साभ
+सारा
+से
+सो
+ही
+हुआ
+हुई
+हुए
+है
+हैं
+हो
+होता
+होती
+होते
+होना
+होने
+# additional normalized forms of the above
+अपनि
+जेसे
+होति
+सभि
+तिंहों
+इंहों
+दवारा
+इसि
+किंहें
+थि
+उंहों
+ओर
+जिंहें
+वहिं
+अभि
+बनि
+हि
+उंहिं
+उंहें
+हें
+वगेरह
+एसे
+रवासा
+कोन
+निचे
+काफि
+उसि
+पुरा
+भितर
+हे
+बहि
+वहां
+कोइ
+यहां
+जिंहों
+तिंहें
+किसि
+कइ
+यहि
+इंहिं
+जिधर
+इंहें
+अदि
+इतयादि
+हुइ
+कोनसा
+इसकि
+दुसरे
+जहां
+अप
+किंहों
+उनकि
+भि
+वरग
+हुअ
+जेसा
+नहिं
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_hu.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_hu.txt
new file mode 100644
index 0000000..37526da
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_hu.txt
@@ -0,0 +1,211 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/hungarian/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+ 
+| Hungarian stop word list
+| prepared by Anna Tordai
+
+a
+ahogy
+ahol
+aki
+akik
+akkor
+alatt
+által
+általában
+amely
+amelyek
+amelyekben
+amelyeket
+amelyet
+amelynek
+ami
+amit
+amolyan
+amíg
+amikor
+át
+abban
+ahhoz
+annak
+arra
+arról
+az
+azok
+azon
+azt
+azzal
+azért
+aztán
+azután
+azonban
+bár
+be
+belül
+benne
+cikk
+cikkek
+cikkeket
+csak
+de
+e
+eddig
+egész
+egy
+egyes
+egyetlen
+egyéb
+egyik
+egyre
+ekkor
+el
+elég
+ellen
+elő
+először
+előtt
+első
+én
+éppen
+ebben
+ehhez
+emilyen
+ennek
+erre
+ez
+ezt
+ezek
+ezen
+ezzel
+ezért
+és
+fel
+felé
+hanem
+hiszen
+hogy
+hogyan
+igen
+így
+illetve
+ill.
+ill
+ilyen
+ilyenkor
+ison
+ismét
+itt
+jó
+jól
+jobban
+kell
+kellett
+keresztül
+keressünk
+ki
+kívül
+között
+közül
+legalább
+lehet
+lehetett
+legyen
+lenne
+lenni
+lesz
+lett
+maga
+magát
+majd
+majd
+már
+más
+másik
+meg
+még
+mellett
+mert
+mely
+melyek
+mi
+mit
+míg
+miért
+milyen
+mikor
+minden
+mindent
+mindenki
+mindig
+mint
+mintha
+mivel
+most
+nagy
+nagyobb
+nagyon
+ne
+néha
+nekem
+neki
+nem
+néhány
+nélkül
+nincs
+olyan
+ott
+össze

+ők
+őket
+pedig
+persze
+rá
+s
+saját
+sem
+semmi
+sok
+sokat
+sokkal
+számára
+szemben
+szerint
+szinte
+talán
+tehát
+teljes
+tovább
+továbbá
+több
+úgy
+ugyanis
+új
+újabb
+újra
+után
+utána
+utolsó
+vagy
+vagyis
+valaki
+valami
+valamint
+való
+vagyok
+van
+vannak
+volt
+voltam
+voltak
+voltunk
+vissza
+vele
+viszont
+volna
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_hy.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_hy.txt
new file mode 100644
index 0000000..60c1c50
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_hy.txt
@@ -0,0 +1,46 @@
+# example set of Armenian stopwords.
+այդ
+այլ
+այն
+այս
+դու
+դուք
+եմ
+են
+ենք
+ես
+եք

+էի
+էին
+էինք
+էիր
+էիք
+էր
+ըստ


+ին
+իսկ
+իր
+կամ
+համար
+հետ
+հետո
+մենք
+մեջ
+մի

+նա
+նաև
+նրա
+նրանք
+որ
+որը
+որոնք
+որպես
+ու
+ում
+պիտի
+վրա

diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_id.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_id.txt
new file mode 100644
index 0000000..4617f83
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_id.txt
@@ -0,0 +1,359 @@
+# from appendix D of: A Study of Stemming Effects on Information
+# Retrieval in Bahasa Indonesia
+ada
+adanya
+adalah
+adapun
+agak
+agaknya
+agar
+akan
+akankah
+akhirnya
+aku
+akulah
+amat
+amatlah
+anda
+andalah
+antar
+diantaranya
+antara
+antaranya
+diantara
+apa
+apaan
+mengapa
+apabila
+apakah
+apalagi
+apatah
+atau
+ataukah
+ataupun
+bagai
+bagaikan
+sebagai
+sebagainya
+bagaimana
+bagaimanapun
+sebagaimana
+bagaimanakah
+bagi
+bahkan
+bahwa
+bahwasanya
+sebaliknya
+banyak
+sebanyak
+beberapa
+seberapa
+begini
+beginian
+beginikah
+beginilah
+sebegini
+begitu
+begitukah
+begitulah
+begitupun
+sebegitu
+belum
+belumlah
+sebelum
+sebelumnya
+sebenarnya
+berapa
+berapakah
+berapalah
+berapapun
+betulkah
+sebetulnya
+biasa
+biasanya
+bila
+bilakah
+bisa
+bisakah
+sebisanya
+boleh
+bolehkah
+bolehlah
+buat
+bukan
+bukankah
+bukanlah
+bukannya
+cuma
+percuma
+dahulu
+dalam
+dan
+dapat
+dari
+daripada
+dekat
+demi
+demikian
+demikianlah
+sedemikian
+dengan
+depan
+di
+dia
+dialah
+dini
+diri
+dirinya
+terdiri
+dong
+dulu
+enggak
+enggaknya
+entah
+entahlah
+terhadap
+terhadapnya
+hal
+hampir
+hanya
+hanyalah
+harus
+haruslah
+harusnya
+seharusnya
+hendak
+hendaklah
+hendaknya
+hingga
+sehingga
+ia
+ialah
+ibarat
+ingin
+inginkah
+inginkan
+ini
+inikah
+inilah
+itu
+itukah
+itulah
+jangan
+jangankan
+janganlah
+jika
+jikalau
+juga
+justru
+kala
+kalau
+kalaulah
+kalaupun
+kalian
+kami
+kamilah
+kamu
+kamulah
+kan
+kapan
+kapankah
+kapanpun
+dikarenakan
+karena
+karenanya
+ke
+kecil
+kemudian
+kenapa
+kepada
+kepadanya
+ketika
+seketika
+khususnya
+kini
+kinilah
+kiranya
+sekiranya
+kita
+kitalah
+kok
+lagi
+lagian
+selagi
+lah
+lain
+lainnya
+melainkan
+selaku
+lalu
+melalui
+terlalu
+lama
+lamanya
+selama
+selama
+selamanya
+lebih
+terlebih
+bermacam
+macam
+semacam
+maka
+makanya
+makin
+malah
+malahan
+mampu
+mampukah
+mana
+manakala
+manalagi
+masih
+masihkah
+semasih
+masing
+mau
+maupun
+semaunya
+memang
+mereka
+merekalah
+meski
+meskipun
+semula
+mungkin
+mungkinkah
+nah
+namun
+nanti
+nantinya
+nyaris
+oleh
+olehnya
+seorang
+seseorang
+pada
+padanya
+padahal
+paling
+sepanjang
+pantas
+sepantasnya
+sepantasnyalah
+para
+pasti
+pastilah
+per
+pernah
+pula
+pun
+merupakan
+rupanya
+serupa
+saat
+saatnya
+sesaat
+saja
+sajalah
+saling
+bersama
+sama
+sesama
+sambil
+sampai
+sana
+sangat
+sangatlah
+saya
+sayalah
+se
+sebab
+sebabnya
+sebuah
+tersebut
+tersebutlah
+sedang
+sedangkan
+sedikit
+sedikitnya
+segala
+segalanya
+segera
+sesegera
+sejak
+sejenak
+sekali
+sekalian
+sekalipun
+sesekali
+sekaligus
+sekarang
+sekarang
+sekitar
+sekitarnya
+sela
+selain
+selalu
+seluruh
+seluruhnya
+semakin
+sementara
+sempat
+semua
+semuanya
+sendiri
+sendirinya
+seolah
+seperti
+sepertinya
+sering
+seringnya
+serta
+siapa
+siapakah
+siapapun
+disini
+disinilah
+sini
+sinilah
+sesuatu
+sesuatunya
+suatu
+sesudah
+sesudahnya
+sudah
+sudahkah
+sudahlah
+supaya
+tadi
+tadinya
+tak
+tanpa
+setelah
+telah
+tentang
+tentu
+tentulah
+tentunya
+tertentu
+seterusnya
+tapi
+tetapi
+setiap
+tiap
+setidaknya
+tidak
+tidakkah
+tidaklah
+toh
+waduh
+wah
+wahai
+sewaktu
+walau
+walaupun
+wong
+yaitu
+yakni
+yang
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_it.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_it.txt
new file mode 100644
index 0000000..1219cc7
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_it.txt
@@ -0,0 +1,303 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/italian/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | An Italian stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+ad             |  a (to) before vowel
+al             |  a + il
+allo           |  a + lo
+ai             |  a + i
+agli           |  a + gli
+all            |  a + l'
+agl            |  a + gl'
+alla           |  a + la
+alle           |  a + le
+con            |  with
+col            |  con + il
+coi            |  con + i (forms collo, cogli etc are now very rare)
+da             |  from
+dal            |  da + il
+dallo          |  da + lo
+dai            |  da + i
+dagli          |  da + gli
+dall           |  da + l'
+dagl           |  da + gll'
+dalla          |  da + la
+dalle          |  da + le
+di             |  of
+del            |  di + il
+dello          |  di + lo
+dei            |  di + i
+degli          |  di + gli
+dell           |  di + l'
+degl           |  di + gl'
+della          |  di + la
+delle          |  di + le
+in             |  in
+nel            |  in + el
+nello          |  in + lo
+nei            |  in + i
+negli          |  in + gli
+nell           |  in + l'
+negl           |  in + gl'
+nella          |  in + la
+nelle          |  in + le
+su             |  on
+sul            |  su + il
+sullo          |  su + lo
+sui            |  su + i
+sugli          |  su + gli
+sull           |  su + l'
+sugl           |  su + gl'
+sulla          |  su + la
+sulle          |  su + le
+per            |  through, by
+tra            |  among
+contro         |  against
+io             |  I
+tu             |  thou
+lui            |  he
+lei            |  she
+noi            |  we
+voi            |  you
+loro           |  they
+mio            |  my
+mia            |
+miei           |
+mie            |
+tuo            |
+tua            |
+tuoi           |  thy
+tue            |
+suo            |
+sua            |
+suoi           |  his, her
+sue            |
+nostro         |  our
+nostra         |
+nostri         |
+nostre         |
+vostro         |  your
+vostra         |
+vostri         |
+vostre         |
+mi             |  me
+ti             |  thee
+ci             |  us, there
+vi             |  you, there
+lo             |  him, the
+la             |  her, the
+li             |  them
+le             |  them, the
+gli            |  to him, the
+ne             |  from there etc
+il             |  the
+un             |  a
+uno            |  a
+una            |  a
+ma             |  but
+ed             |  and
+se             |  if
+perché         |  why, because
+anche          |  also
+come           |  how
+dov            |  where (as dov')
+dove           |  where
+che            |  who, that
+chi            |  who
+cui            |  whom
+non            |  not
+più            |  more
+quale          |  who, that
+quanto         |  how much
+quanti         |
+quanta         |
+quante         |
+quello         |  that
+quelli         |
+quella         |
+quelle         |
+questo         |  this
+questi         |
+questa         |
+queste         |
+si             |  yes
+tutto          |  all
+tutti          |  all
+
+               |  single letter forms:
+
+a              |  at
+c              |  as c' for ce or ci
+e              |  and
+i              |  the
+l              |  as l'
+o              |  or
+
+               | forms of avere, to have (not including the infinitive):
+
+ho
+hai
+ha
+abbiamo
+avete
+hanno
+abbia
+abbiate
+abbiano
+avrò
+avrai
+avrà
+avremo
+avrete
+avranno
+avrei
+avresti
+avrebbe
+avremmo
+avreste
+avrebbero
+avevo
+avevi
+aveva
+avevamo
+avevate
+avevano
+ebbi
+avesti
+ebbe
+avemmo
+aveste
+ebbero
+avessi
+avesse
+avessimo
+avessero
+avendo
+avuto
+avuta
+avuti
+avute
+
+               | forms of essere, to be (not including the infinitive):
+sono
+sei

+siamo
+siete
+sia
+siate
+siano
+sarò
+sarai
+sarà
+saremo
+sarete
+saranno
+sarei
+saresti
+sarebbe
+saremmo
+sareste
+sarebbero
+ero
+eri
+era
+eravamo
+eravate
+erano
+fui
+fosti
+fu
+fummo
+foste
+furono
+fossi
+fosse
+fossimo
+fossero
+essendo
+
+               | forms of fare, to do (not including the infinitive, fa, fat-):
+faccio
+fai
+facciamo
+fanno
+faccia
+facciate
+facciano
+farò
+farai
+farà
+faremo
+farete
+faranno
+farei
+faresti
+farebbe
+faremmo
+fareste
+farebbero
+facevo
+facevi
+faceva
+facevamo
+facevate
+facevano
+feci
+facesti
+fece
+facemmo
+faceste
+fecero
+facessi
+facesse
+facessimo
+facessero
+facendo
+
+               | forms of stare, to be (not including the infinitive):
+sto
+stai
+sta
+stiamo
+stanno
+stia
+stiate
+stiano
+starò
+starai
+starà
+staremo
+starete
+staranno
+starei
+staresti
+starebbe
+staremmo
+stareste
+starebbero
+stavo
+stavi
+stava
+stavamo
+stavate
+stavano
+stetti
+stesti
+stette
+stemmo
+steste
+stettero
+stessi
+stesse
+stessimo
+stessero
+stando
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ja.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ja.txt
new file mode 100644
index 0000000..d4321be
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ja.txt
@@ -0,0 +1,127 @@
+#
+# This file defines a stopword set for Japanese.
+#
+# This set is made up of hand-picked frequent terms from segmented Japanese Wikipedia.
+# Punctuation characters and frequent kanji have mostly been left out.  See LUCENE-3745
+# for frequency lists, etc. that can be useful for making your own set (if desired)
+#
+# Note that there is an overlap between these stopwords and the terms stopped when used
+# in combination with the JapanesePartOfSpeechStopFilter.  When editing this file, note
+# that comments are not allowed on the same line as stopwords.
+#
+# Also note that stopping is done in a case-insensitive manner.  Change your StopFilter
+# configuration if you need case-sensitive stopping.  Lastly, note that stopping is done
+# using the same character width as the entries in this file.  Since this StopFilter is
+# normally done after a CJKWidthFilter in your chain, you would usually want your romaji
+# entries to be in half-width and your kana entries to be in full-width.
+#
+の
+に
+は
+を
+た
+が
+で
+て
+と
+し
+れ
+さ
+ある
+いる
+も
+する
+から
+な
+こと
+として
+い
+や
+れる
+など
+なっ
+ない
+この
+ため
+その
+あっ
+よう
+また
+もの
+という
+あり
+まで
+られ
+なる
+へ
+か
+だ
+これ
+によって
+により
+おり
+より
+による
+ず
+なり
+られる
+において
+ば
+なかっ
+なく
+しかし
+について
+せ
+だっ
+その後
+できる
+それ
+う
+ので
+なお
+のみ
+でき
+き
+つ
+における
+および
+いう
+さらに
+でも
+ら
+たり
+その他
+に関する
+たち
+ます
+ん
+なら
+に対して
+特に
+せる
+及び
+これら
+とき
+では
+にて
+ほか
+ながら
+うち
+そして
+とともに
+ただし
+かつて
+それぞれ
+または
+お
+ほど
+ものの
+に対する
+ほとんど
+と共に
+といった
+です
+とも
+ところ
+ここ
+##### End of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_lv.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_lv.txt
new file mode 100644
index 0000000..e21a23c
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_lv.txt
@@ -0,0 +1,172 @@
+# Set of Latvian stopwords from A Stemming Algorithm for Latvian, Karlis Kreslins
+# the original list of over 800 forms was refined: 
+#   pronouns, adverbs, interjections were removed
+# 
+# prepositions
+aiz
+ap
+ar
+apakš
+ārpus
+augšpus
+bez
+caur
+dēļ
+gar
+iekš
+iz
+kopš
+labad
+lejpus
+līdz
+no
+otrpus
+pa
+par
+pār
+pēc
+pie
+pirms
+pret
+priekš
+starp
+šaipus
+uz
+viņpus
+virs
+virspus
+zem
+apakšpus
+# Conjunctions
+un
+bet
+jo
+ja
+ka
+lai
+tomēr
+tikko
+turpretī
+arī
+kaut
+gan
+tādēļ
+tā
+ne
+tikvien
+vien
+kā
+ir
+te
+vai
+kamēr
+# Particles
+ar
+diezin
+droši
+diemžēl
+nebūt
+ik
+it
+taču
+nu
+pat
+tiklab
+iekšpus
+nedz
+tik
+nevis
+turpretim
+jeb
+iekam
+iekām
+iekāms
+kolīdz
+līdzko
+tiklīdz
+jebšu
+tālab
+tāpēc
+nekā
+itin
+jā
+jau
+jel
+nē
+nezin
+tad
+tikai
+vis
+tak
+iekams
+vien
+# modal verbs
+būt  
+biju 
+biji
+bija
+bijām
+bijāt
+esmu
+esi
+esam
+esat 
+būšu     
+būsi
+būs
+būsim
+būsiet
+tikt
+tiku
+tiki
+tika
+tikām
+tikāt
+tieku
+tiec
+tiek
+tiekam
+tiekat
+tikšu
+tiks
+tiksim
+tiksiet
+tapt
+tapi
+tapāt
+topat
+tapšu
+tapsi
+taps
+tapsim
+tapsiet
+kļūt
+kļuvu
+kļuvi
+kļuva
+kļuvām
+kļuvāt
+kļūstu
+kļūsti
+kļūst
+kļūstam
+kļūstat
+kļūšu
+kļūsi
+kļūs
+kļūsim
+kļūsiet
+# verbs
+varēt
+varēju
+varējām
+varēšu
+varēsim
+var
+varēji
+varējāt
+varēsi
+varēsiet
+varat
+varēja
+varēs
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_nl.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_nl.txt
new file mode 100644
index 0000000..47a2aea
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_nl.txt
@@ -0,0 +1,119 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/dutch/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A Dutch stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+ | This is a ranked list (commonest to rarest) of stopwords derived from
+ | a large sample of Dutch text.
+
+ | Dutch stop words frequently exhibit homonym clashes. These are indicated
+ | clearly below.
+
+de             |  the
+en             |  and
+van            |  of, from
+ik             |  I, the ego
+te             |  (1) chez, at etc, (2) to, (3) too
+dat            |  that, which
+die            |  that, those, who, which
+in             |  in, inside
+een            |  a, an, one
+hij            |  he
+het            |  the, it
+niet           |  not, nothing, naught
+zijn           |  (1) to be, being, (2) his, one's, its
+is             |  is
+was            |  (1) was, past tense of all persons sing. of 'zijn' (to be) (2) wax, (3) the washing, (4) rise of river
+op             |  on, upon, at, in, up, used up
+aan            |  on, upon, to (as dative)
+met            |  with, by
+als            |  like, such as, when
+voor           |  (1) before, in front of, (2) furrow
+had            |  had, past tense all persons sing. of 'hebben' (have)
+er             |  there
+maar           |  but, only
+om             |  round, about, for etc
+hem            |  him
+dan            |  then
+zou            |  should/would, past tense all persons sing. of 'zullen'
+of             |  or, whether, if
+wat            |  what, something, anything
+mijn           |  possessive and noun 'mine'
+men            |  people, 'one'
+dit            |  this
+zo             |  so, thus, in this way
+door           |  through by
+over           |  over, across
+ze             |  she, her, they, them
+zich           |  oneself
+bij            |  (1) a bee, (2) by, near, at
+ook            |  also, too
+tot            |  till, until
+je             |  you
+mij            |  me
+uit            |  out of, from
+der            |  Old Dutch form of 'van der' still found in surnames
+daar           |  (1) there, (2) because
+haar           |  (1) her, their, them, (2) hair
+naar           |  (1) unpleasant, unwell etc, (2) towards, (3) as
+heb            |  present first person sing. of 'to have'
+hoe            |  how, why
+heeft          |  present third person sing. of 'to have'
+hebben         |  'to have' and various parts thereof
+deze           |  this
+u              |  you
+want           |  (1) for, (2) mitten, (3) rigging
+nog            |  yet, still
+zal            |  'shall', first and third person sing. of verb 'zullen' (will)
+me             |  me
+zij            |  she, they
+nu             |  now
+ge             |  'thou', still used in Belgium and south Netherlands
+geen           |  none
+omdat          |  because
+iets           |  something, somewhat
+worden         |  to become, grow, get
+toch           |  yet, still
+al             |  all, every, each
+waren          |  (1) 'were' (2) to wander, (3) wares, (3)
+veel           |  much, many
+meer           |  (1) more, (2) lake
+doen           |  to do, to make
+toen           |  then, when
+moet           |  noun 'spot/mote' and present form of 'to must'
+ben            |  (1) am, (2) 'are' in interrogative second person singular of 'to be'
+zonder         |  without
+kan            |  noun 'can' and present form of 'to be able'
+hun            |  their, them
+dus            |  so, consequently
+alles          |  all, everything, anything
+onder          |  under, beneath
+ja             |  yes, of course
+eens           |  once, one day
+hier           |  here
+wie            |  who
+werd           |  imperfect third person sing. of 'become'
+altijd         |  always
+doch           |  yet, but etc
+wordt          |  present third person sing. of 'become'
+wezen          |  (1) to be, (2) 'been' as in 'been fishing', (3) orphans
+kunnen         |  to be able
+ons            |  us/our
+zelf           |  self
+tegen          |  against, towards, at
+na             |  after, near
+reeds          |  already
+wil            |  (1) present tense of 'want', (2) 'will', noun, (3) fender
+kon            |  could; past tense of 'to be able'
+niets          |  nothing
+uw             |  your
+iemand         |  somebody
+geweest        |  been; past participle of 'be'
+andere         |  other
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_no.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_no.txt
new file mode 100644
index 0000000..a7a2c28
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_no.txt
@@ -0,0 +1,194 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/norwegian/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A Norwegian stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+ | This stop word list is for the dominant bokmål dialect. Words unique
+ | to nynorsk are marked *.
+
+ | Revised by Jan Bruusgaard <Jan.Bruusgaard@ssb.no>, Jan 2005
+
+og             | and
+i              | in
+jeg            | I
+det            | it/this/that
+at             | to (w. inf.)
+en             | a/an
+et             | a/an
+den            | it/this/that
+til            | to
+er             | is/am/are
+som            | who/that
+på             | on
+de             | they / you(formal)
+med            | with
+han            | he
+av             | of
+ikke           | not
+ikkje          | not *
+der            | there
+så             | so
+var            | was/were
+meg            | me
+seg            | you
+men            | but
+ett            | one
+har            | have
+om             | about
+vi             | we
+min            | my
+mitt           | my
+ha             | have
+hadde          | had
+hun            | she
+nå             | now
+over           | over
+da             | when/as
+ved            | by/know
+fra            | from
+du             | you
+ut             | out
+sin            | your
+dem            | them
+oss            | us
+opp            | up
+man            | you/one
+kan            | can
+hans           | his
+hvor           | where
+eller          | or
+hva            | what
+skal           | shall/must
+selv           | self (reflective)
+sjøl           | self (reflective)
+her            | here
+alle           | all
+vil            | will
+bli            | become
+ble            | became
+blei           | became *
+blitt          | have become
+kunne          | could
+inn            | in
+når            | when
+være           | be
+kom            | come
+noen           | some
+noe            | some
+ville          | would
+dere           | you
+som            | who/which/that
+deres          | their/theirs
+kun            | only/just
+ja             | yes
+etter          | after
+ned            | down
+skulle         | should
+denne          | this
+for            | for/because
+deg            | you
+si             | hers/his
+sine           | hers/his
+sitt           | hers/his
+mot            | against
+å              | to
+meget          | much
+hvorfor        | why
+dette          | this
+disse          | these/those
+uten           | without
+hvordan        | how
+ingen          | none
+din            | your
+ditt           | your
+blir           | become
+samme          | same
+hvilken        | which
+hvilke         | which (plural)
+sånn           | such a
+inni           | inside/within
+mellom         | between
+vår            | our
+hver           | each
+hvem           | who
+vors           | us/ours
+hvis           | whose
+både           | both
+bare           | only/just
+enn            | than
+fordi          | as/because
+før            | before
+mange          | many
+også           | also
+slik           | just
+vært           | been
+være           | to be
+båe            | both *
+begge          | both
+siden          | since
+dykk           | your *
+dykkar         | yours *
+dei            | they *
+deira          | them *
+deires         | theirs *
+deim           | them *
+di             | your (fem.) *
+då             | as/when *
+eg             | I *
+ein            | a/an *
+eit            | a/an *
+eitt           | a/an *
+elles          | or *
+honom          | he *
+hjå            | at *
+ho             | she *
+hoe            | she *
+henne          | her
+hennar         | her/hers
+hennes         | hers
+hoss           | how *
+hossen         | how *
+ikkje          | not *
+ingi           | noone *
+inkje          | noone *
+korleis        | how *
+korso          | how *
+kva            | what/which *
+kvar           | where *
+kvarhelst      | where *
+kven           | who/whom *
+kvi            | why *
+kvifor         | why *
+me             | we *
+medan          | while *
+mi             | my *
+mine           | my *
+mykje          | much *
+no             | now *
+nokon          | some (masc./neut.) *
+noka           | some (fem.) *
+nokor          | some *
+noko           | some *
+nokre          | some *
+si             | his/hers *
+sia            | since *
+sidan          | since *
+so             | so *
+somt           | some *
+somme          | some *
+um             | about*
+upp            | up *
+vere           | be *
+vore           | was *
+verte          | become *
+vort           | become *
+varte          | became *
+vart           | became *
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_pt.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_pt.txt
new file mode 100644
index 0000000..acfeb01
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_pt.txt
@@ -0,0 +1,253 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/portuguese/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A Portuguese stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+
+ | The following is a ranked list (commonest to rarest) of stopwords
+ | deriving from a large sample of text.
+
+ | Extra words have been added at the end.
+
+de             |  of, from
+a              |  the; to, at; her
+o              |  the; him
+que            |  who, that
+e              |  and
+do             |  de + o
+da             |  de + a
+em             |  in
+um             |  a
+para           |  for
+  | é          from SER
+com            |  with
+não            |  not, no
+uma            |  a
+os             |  the; them
+no             |  em + o
+se             |  himself etc
+na             |  em + a
+por            |  for
+mais           |  more
+as             |  the; them
+dos            |  de + os
+como           |  as, like
+mas            |  but
+  | foi        from SER
+ao             |  a + o
+ele            |  he
+das            |  de + as
+  | tem        from TER
+à              |  a + a
+seu            |  his
+sua            |  her
+ou             |  or
+  | ser        from SER
+quando         |  when
+muito          |  much
+  | há         from HAV
+nos            |  em + os; us
+já             |  already, now
+  | está       from EST
+eu             |  I
+também         |  also
+só             |  only, just
+pelo           |  per + o
+pela           |  per + a
+até            |  up to
+isso           |  that
+ela            |  he
+entre          |  between
+  | era        from SER
+depois         |  after
+sem            |  without
+mesmo          |  same
+aos            |  a + os
+  | ter        from TER
+seus           |  his
+quem           |  whom
+nas            |  em + as
+me             |  me
+esse           |  that
+eles           |  they
+  | estão      from EST
+você           |  you
+  | tinha      from TER
+  | foram      from SER
+essa           |  that
+num            |  em + um
+nem            |  nor
+suas           |  her
+meu            |  my
+às             |  a + as
+minha          |  my
+  | têm        from TER
+numa           |  em + uma
+pelos          |  per + os
+elas           |  they
+  | havia      from HAV
+  | seja       from SER
+qual           |  which
+  | será       from SER
+nós            |  we
+  | tenho      from TER
+lhe            |  to him, her
+deles          |  of them
+essas          |  those
+esses          |  those
+pelas          |  per + as
+este           |  this
+  | fosse      from SER
+dele           |  of him
+
+ | other words. There are many contractions such as naquele = em+aquele,
+ | mo = me+o, but they are rare.
+ | Indefinite article plural forms are also rare.
+
+tu             |  thou
+te             |  thee
+vocês          |  you (plural)
+vos            |  you
+lhes           |  to them
+meus           |  my
+minhas
+teu            |  thy
+tua
+teus
+tuas
+nosso          | our
+nossa
+nossos
+nossas
+
+dela           |  of her
+delas          |  of them
+
+esta           |  this
+estes          |  these
+estas          |  these
+aquele         |  that
+aquela         |  that
+aqueles        |  those
+aquelas        |  those
+isto           |  this
+aquilo         |  that
+
+               | forms of estar, to be (not including the infinitive):
+estou
+está
+estamos
+estão
+estive
+esteve
+estivemos
+estiveram
+estava
+estávamos
+estavam
+estivera
+estivéramos
+esteja
+estejamos
+estejam
+estivesse
+estivéssemos
+estivessem
+estiver
+estivermos
+estiverem
+
+               | forms of haver, to have (not including the infinitive):
+hei
+há
+havemos
+hão
+houve
+houvemos
+houveram
+houvera
+houvéramos
+haja
+hajamos
+hajam
+houvesse
+houvéssemos
+houvessem
+houver
+houvermos
+houverem
+houverei
+houverá
+houveremos
+houverão
+houveria
+houveríamos
+houveriam
+
+               | forms of ser, to be (not including the infinitive):
+sou
+somos
+são
+era
+éramos
+eram
+fui
+foi
+fomos
+foram
+fora
+fôramos
+seja
+sejamos
+sejam
+fosse
+fôssemos
+fossem
+for
+formos
+forem
+serei
+será
+seremos
+serão
+seria
+seríamos
+seriam
+
+               | forms of ter, to have (not including the infinitive):
+tenho
+tem
+temos
+tém
+tinha
+tínhamos
+tinham
+tive
+teve
+tivemos
+tiveram
+tivera
+tivéramos
+tenha
+tenhamos
+tenham
+tivesse
+tivéssemos
+tivessem
+tiver
+tivermos
+tiverem
+terei
+terá
+teremos
+terão
+teria
+teríamos
+teriam
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ro.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ro.txt
new file mode 100644
index 0000000..4fdee90
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ro.txt
@@ -0,0 +1,233 @@
+# This file was created by Jacques Savoy and is distributed under the BSD license.
+# See http://members.unine.ch/jacques.savoy/clef/index.html.
+# Also see http://www.opensource.org/licenses/bsd-license.html
+acea
+aceasta
+această
+aceea
+acei
+aceia
+acel
+acela
+acele
+acelea
+acest
+acesta
+aceste
+acestea
+aceşti
+aceştia
+acolo
+acum
+ai
+aia
+aibă
+aici
+al
+ăla
+ale
+alea
+ălea
+altceva
+altcineva
+am
+ar
+are
+aş
+aşadar
+asemenea
+asta
+ăsta
+astăzi
+astea
+ăstea
+ăştia
+asupra
+aţi
+au
+avea
+avem
+aveţi
+azi
+bine
+bucur
+bună
+ca
+că
+căci
+când
+care
+cărei
+căror
+cărui
+cât
+câte
+câţi
+către
+câtva
+ce
+cel
+ceva
+chiar
+cînd
+cine
+cineva
+cît
+cîte
+cîţi
+cîtva
+contra
+cu
+cum
+cumva
+curând
+curînd
+da
+dă
+dacă
+dar
+datorită
+de
+deci
+deja
+deoarece
+departe
+deşi
+din
+dinaintea
+dintr
+dintre
+drept
+după
+ea
+ei
+el
+ele
+eram
+este
+eşti
+eu
+face
+fără
+fi
+fie
+fiecare
+fii
+fim
+fiţi
+iar
+ieri
+îi
+îl
+îmi
+împotriva
+în 
+înainte
+înaintea
+încât
+încît
+încotro
+între
+întrucât
+întrucît
+îţi
+la
+lângă
+le
+li
+lîngă
+lor
+lui
+mă
+mâine
+mea
+mei
+mele
+mereu
+meu
+mi
+mine
+mult
+multă
+mulţi
+ne
+nicăieri
+nici
+nimeni
+nişte
+noastră
+noastre
+noi
+noştri
+nostru
+nu
+ori
+oricând
+oricare
+oricât
+orice
+oricînd
+oricine
+oricît
+oricum
+oriunde
+până
+pe
+pentru
+peste
+pînă
+poate
+pot
+prea
+prima
+primul
+prin
+printr
+sa
+să
+săi
+sale
+sau
+său
+se
+şi
+sînt
+sîntem
+sînteţi
+spre
+sub
+sunt
+suntem
+sunteţi
+ta
+tăi
+tale
+tău
+te
+ţi
+ţie
+tine
+toată
+toate
+tot
+toţi
+totuşi
+tu
+un
+una
+unde
+undeva
+unei
+unele
+uneori
+unor
+vă
+vi
+voastră
+voastre
+voi
+voştri
+vostru
+vouă
+vreo
+vreun
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ru.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ru.txt
new file mode 100644
index 0000000..5527140
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_ru.txt
@@ -0,0 +1,243 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/russian/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | a russian stop word list. comments begin with vertical bar. each stop
+ | word is at the start of a line.
+
+ | this is a ranked list (commonest to rarest) of stopwords derived from
+ | a large text sample.
+
+ | letter `ё' is translated to `е'.
+
+и              | and
+в              | in/into
+во             | alternative form
+не             | not
+что            | what/that
+он             | he
+на             | on/onto
+я              | i
+с              | from
+со             | alternative form
+как            | how
+а              | milder form of `no' (but)
+то             | conjunction and form of `that'
+все            | all
+она            | she
+так            | so, thus
+его            | him
+но             | but
+да             | yes/and
+ты             | thou
+к              | towards, by
+у              | around, chez
+же             | intensifier particle
+вы             | you
+за             | beyond, behind
+бы             | conditional/subj. particle
+по             | up to, along
+только         | only
+ее             | her
+мне            | to me
+было           | it was
+вот            | here is/are, particle
+от             | away from
+меня           | me
+еще            | still, yet, more
+нет            | no, there isnt/arent
+о              | about
+из             | out of
+ему            | to him
+теперь         | now
+когда          | when
+даже           | even
+ну             | so, well
+вдруг          | suddenly
+ли             | interrogative particle
+если           | if
+уже            | already, but homonym of `narrower'
+или            | or
+ни             | neither
+быть           | to be
+был            | he was
+него           | prepositional form of его
+до             | up to
+вас            | you accusative
+нибудь         | indef. suffix preceded by hyphen
+опять          | again
+уж             | already, but homonym of `adder'
+вам            | to you
+сказал         | he said
+ведь           | particle `after all'
+там            | there
+потом          | then
+себя           | oneself
+ничего         | nothing
+ей             | to her
+может          | usually with `быть' as `maybe'
+они            | they
+тут            | here
+где            | where
+есть           | there is/are
+надо           | got to, must
+ней            | prepositional form of  ей
+для            | for
+мы             | we
+тебя           | thee
+их             | them, their
+чем            | than
+была           | she was
+сам            | self
+чтоб           | in order to
+без            | without
+будто          | as if
+человек        | man, person, one
+чего           | genitive form of `what'
+раз            | once
+тоже           | also
+себе           | to oneself
+под            | beneath
+жизнь          | life
+будет          | will be
+ж              | short form of intensifer particle `же'
+тогда          | then
+кто            | who
+этот           | this
+говорил        | was saying
+того           | genitive form of `that'
+потому         | for that reason
+этого          | genitive form of `this'
+какой          | which
+совсем         | altogether
+ним            | prepositional form of `его', `они'
+здесь          | here
+этом           | prepositional form of `этот'
+один           | one
+почти          | almost
+мой            | my
+тем            | instrumental/dative plural of `тот', `то'
+чтобы          | full form of `in order that'
+нее            | her (acc.)
+кажется        | it seems
+сейчас         | now
+были           | they were
+куда           | where to
+зачем          | why
+сказать        | to say
+всех           | all (acc., gen. preposn. plural)
+никогда        | never
+сегодня        | today
+можно          | possible, one can
+при            | by
+наконец        | finally
+два            | two
+об             | alternative form of `о', about
+другой         | another
+хоть           | even
+после          | after
+над            | above
+больше         | more
+тот            | that one (masc.)
+через          | across, in
+эти            | these
+нас            | us
+про            | about
+всего          | in all, only, of all
+них            | prepositional form of `они' (they)
+какая          | which, feminine
+много          | lots
+разве          | interrogative particle
+сказала        | she said
+три            | three
+эту            | this, acc. fem. sing.
+моя            | my, feminine
+впрочем        | moreover, besides
+хорошо         | good
+свою           | ones own, acc. fem. sing.
+этой           | oblique form of `эта', fem. `this'
+перед          | in front of
+иногда         | sometimes
+лучше          | better
+чуть           | a little
+том            | preposn. form of `that one'
+нельзя         | one must not
+такой          | such a one
+им             | to them
+более          | more
+всегда         | always
+конечно        | of course
+всю            | acc. fem. sing of `all'
+между          | between
+
+
+  | b: some paradigms
+  |
+  | personal pronouns
+  |
+  | я  меня  мне  мной  [мною]
+  | ты  тебя  тебе  тобой  [тобою]
+  | он  его  ему  им  [него, нему, ним]
+  | она  ее  эи  ею  [нее, нэи, нею]
+  | оно  его  ему  им  [него, нему, ним]
+  |
+  | мы  нас  нам  нами
+  | вы  вас  вам  вами
+  | они  их  им  ими  [них, ним, ними]
+  |
+  |   себя  себе  собой   [собою]
+  |
+  | demonstrative pronouns: этот (this), тот (that)
+  |
+  | этот  эта  это  эти
+  | этого  эты  это  эти
+  | этого  этой  этого  этих
+  | этому  этой  этому  этим
+  | этим  этой  этим  [этою]  этими
+  | этом  этой  этом  этих
+  |
+  | тот  та  то  те
+  | того  ту  то  те
+  | того  той  того  тех
+  | тому  той  тому  тем
+  | тем  той  тем  [тою]  теми
+  | том  той  том  тех
+  |
+  | determinative pronouns
+  |
+  | (a) весь (all)
+  |
+  | весь  вся  все  все
+  | всего  всю  все  все
+  | всего  всей  всего  всех
+  | всему  всей  всему  всем
+  | всем  всей  всем  [всею]  всеми
+  | всем  всей  всем  всех
+  |
+  | (b) сам (himself etc)
+  |
+  | сам  сама  само  сами
+  | самого саму  само  самих
+  | самого самой самого  самих
+  | самому самой самому  самим
+  | самим  самой  самим  [самою]  самими
+  | самом самой самом  самих
+  |
+  | stems of verbs `to be', `to have', `to do' and modal
+  |
+  | быть  бы  буд  быв  есть  суть
+  | име
+  | дел
+  | мог   мож  мочь
+  | уме
+  | хоч  хот
+  | долж
+  | можн
+  | нужн
+  | нельзя
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_sv.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_sv.txt
new file mode 100644
index 0000000..096f87f
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_sv.txt
@@ -0,0 +1,133 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/swedish/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A Swedish stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+ | This is a ranked list (commonest to rarest) of stopwords derived from
+ | a large text sample.
+
+ | Swedish stop words occasionally exhibit homonym clashes. For example
+ |  så = so, but also seed. These are indicated clearly below.
+
+och            | and
+det            | it, this/that
+att            | to (with infinitive)
+i              | in, at
+en             | a
+jag            | I
+hon            | she
+som            | who, that
+han            | he
+på             | on
+den            | it, this/that
+med            | with
+var            | where, each
+sig            | him(self) etc
+för            | for
+så             | so (also: seed)
+till           | to
+är             | is
+men            | but
+ett            | a
+om             | if; around, about
+hade           | had
+de             | they, these/those
+av             | of
+icke           | not, no
+mig            | me
+du             | you
+henne          | her
+då             | then, when
+sin            | his
+nu             | now
+har            | have
+inte           | inte någon = no one
+hans           | his
+honom          | him
+skulle         | 'sake'
+hennes         | her
+där            | there
+min            | my
+man            | one (pronoun)
+ej             | nor
+vid            | at, by, on (also: vast)
+kunde          | could
+något          | some etc
+från           | from, off
+ut             | out
+när            | when
+efter          | after, behind
+upp            | up
+vi             | we
+dem            | them
+vara           | be
+vad            | what
+över           | over
+än             | than
+dig            | you
+kan            | can
+sina           | his
+här            | here
+ha             | have
+mot            | towards
+alla           | all
+under          | under (also: wonder)
+någon          | some etc
+eller          | or (else)
+allt           | all
+mycket         | much
+sedan          | since
+ju             | why
+denna          | this/that
+själv          | myself, yourself etc
+detta          | this/that
+åt             | to
+utan           | without
+varit          | was
+hur            | how
+ingen          | no
+mitt           | my
+ni             | you
+bli            | to be, become
+blev           | from bli
+oss            | us
+din            | thy
+dessa          | these/those
+några          | some etc
+deras          | their
+blir           | from bli
+mina           | my
+samma          | (the) same
+vilken         | who, that
+er             | you, your
+sådan          | such a
+vår            | our
+blivit         | from bli
+dess           | its
+inom           | within
+mellan         | between
+sådant         | such a
+varför         | why
+varje          | each
+vilka          | who, that
+ditt           | thy
+vem            | who
+vilket         | who, that
+sitta          | his
+sådana         | such a
+vart           | each
+dina           | thy
+vars           | whose
+vårt           | our
+våra           | our
+ert            | your
+era            | your
+vilkas         | whose
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_th.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_th.txt
new file mode 100644
index 0000000..07f0fab
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_th.txt
@@ -0,0 +1,119 @@
+# Thai stopwords from:
+# "Opinion Detection in Thai Political News Columns
+# Based on Subjectivity Analysis"
+# Khampol Sukhum, Supot Nitsuwat, and Choochart Haruechaiyasak
+ไว้
+ไม่
+ไป
+ได้
+ให้
+ใน
+โดย
+แห่ง
+แล้ว
+และ
+แรก
+แบบ
+แต่
+เอง
+เห็น
+เลย
+เริ่ม
+เรา
+เมื่อ
+เพื่อ
+เพราะ
+เป็นการ
+เป็น
+เปิดเผย
+เปิด
+เนื่องจาก
+เดียวกัน
+เดียว
+เช่น
+เฉพาะ
+เคย
+เข้า
+เขา
+อีก
+อาจ
+อะไร
+ออก
+อย่าง
+อยู่
+อยาก
+หาก
+หลาย
+หลังจาก
+หลัง
+หรือ
+หนึ่ง
+ส่วน
+ส่ง
+สุด
+สําหรับ
+ว่า
+วัน
+ลง
+ร่วม
+ราย
+รับ
+ระหว่าง
+รวม
+ยัง
+มี
+มาก
+มา
+พร้อม
+พบ
+ผ่าน
+ผล
+บาง
+น่า
+นี้
+นํา
+นั้น
+นัก
+นอกจาก
+ทุก
+ที่สุด
+ที่
+ทําให้
+ทํา
+ทาง
+ทั้งนี้
+ทั้ง
+ถ้า
+ถูก
+ถึง
+ต้อง
+ต่างๆ
+ต่าง
+ต่อ
+ตาม
+ตั้งแต่
+ตั้ง
+ด้าน
+ด้วย
+ดัง
+ซึ่ง
+ช่วง
+จึง
+จาก
+จัด
+จะ
+คือ
+ความ
+ครั้ง
+คง
+ขึ้น
+ของ
+ขอ
+ขณะ
+ก่อน
+ก็
+การ
+กับ
+กัน
+กว่า
+กล่าว
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_tr.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_tr.txt
new file mode 100644
index 0000000..84d9408
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/stopwords_tr.txt
@@ -0,0 +1,212 @@
+# Turkish stopwords from LUCENE-559
+# merged with the list from "Information Retrieval on Turkish Texts"
+#   (http://www.users.muohio.edu/canf/papers/JASIST2008offPrint.pdf)
+acaba
+altmış
+altı
+ama
+ancak
+arada
+aslında
+ayrıca
+bana
+bazı
+belki
+ben
+benden
+beni
+benim
+beri
+beş
+bile
+bin
+bir
+birçok
+biri
+birkaç
+birkez
+birşey
+birşeyi
+biz
+bize
+bizden
+bizi
+bizim
+böyle
+böylece
+bu
+buna
+bunda
+bundan
+bunlar
+bunları
+bunların
+bunu
+bunun
+burada
+çok
+çünkü
+da
+daha
+dahi
+de
+defa
+değil
+diğer
+diye
+doksan
+dokuz
+dolayı
+dolayısıyla
+dört
+edecek
+eden
+ederek
+edilecek
+ediliyor
+edilmesi
+ediyor
+eğer
+elli
+en
+etmesi
+etti
+ettiği
+ettiğini
+gibi
+göre
+halen
+hangi
+hatta
+hem
+henüz
+hep
+hepsi
+her
+herhangi
+herkesin
+hiç
+hiçbir
+için
+iki
+ile
+ilgili
+ise
+işte
+itibaren
+itibariyle
+kadar
+karşın
+katrilyon
+kendi
+kendilerine
+kendini
+kendisi
+kendisine
+kendisini
+kez
+ki
+kim
+kimden
+kime
+kimi
+kimse
+kırk
+milyar
+milyon
+mu
+mü
+mı
+nasıl
+ne
+neden
+nedenle
+nerde
+nerede
+nereye
+niye
+niçin
+o
+olan
+olarak
+oldu
+olduğu
+olduğunu
+olduklarını
+olmadı
+olmadığı
+olmak
+olması
+olmayan
+olmaz
+olsa
+olsun
+olup
+olur
+olursa
+oluyor
+on
+ona
+ondan
+onlar
+onlardan
+onları
+onların
+onu
+onun
+otuz
+oysa
+öyle
+pek
+rağmen
+sadece
+sanki
+sekiz
+seksen
+sen
+senden
+seni
+senin
+siz
+sizden
+sizi
+sizin
+şey
+şeyden
+şeyi
+şeyler
+şöyle
+şu
+şuna
+şunda
+şundan
+şunları
+şunu
+tarafından
+trilyon
+tüm
+üç
+üzere
+var
+vardı
+ve
+veya
+ya
+yani
+yapacak
+yapılan
+yapılması
+yapıyor
+yapmak
+yaptı
+yaptığı
+yaptığını
+yaptıkları
+yedi
+yerine
+yetmiş
+yine
+yirmi
+yoksa
+yüz
+zaten
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/userdict_ja.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/userdict_ja.txt
new file mode 100644
index 0000000..6f0368e
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/lang/userdict_ja.txt
@@ -0,0 +1,29 @@
+#
+# This is a sample user dictionary for Kuromoji (JapaneseTokenizer)
+#
+# Add entries to this file in order to override the statistical model in terms
+# of segmentation, readings and part-of-speech tags.  Notice that entries do
+# not have weights since they are always used when found.  This is by-design
+# in order to maximize ease-of-use.
+#
+# Entries are defined using the following CSV format:
+#  <text>,<token 1> ... <token n>,<reading 1> ... <reading n>,<part-of-speech tag>
+#
+# Notice that a single half-width space separates tokens and readings, and
+# that the number tokens and readings must match exactly.
+#
+# Also notice that multiple entries with the same <text> is undefined.
+#
+# Whitespace only lines are ignored.  Comments are not allowed on entry lines.
+#
+
+# Custom segmentation for kanji compounds
+日本経済新聞,日本 経済 新聞,ニホン ケイザイ シンブン,カスタム名詞
+関西国際空港,関西 国際 空港,カンサイ コクサイ クウコウ,カスタム名詞
+
+# Custom segmentation for compound katakana
+トートバッグ,トート バッグ,トート バッグ,かずカナ名詞
+ショルダーバッグ,ショルダー バッグ,ショルダー バッグ,かずカナ名詞
+
+# Custom reading for former sumo wrestler
+朝青龍,朝青龍,アサショウリュウ,カスタム人名
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/mapping-FoldToASCII.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/mapping-FoldToASCII.txt
new file mode 100644
index 0000000..9a84b6e
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/mapping-FoldToASCII.txt
@@ -0,0 +1,3813 @@
+# 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.
+
+
+# This map converts alphabetic, numeric, and symbolic Unicode characters
+# which are not in the first 127 ASCII characters (the "Basic Latin" Unicode
+# block) into their ASCII equivalents, if one exists.
+#
+# Characters from the following Unicode blocks are converted; however, only
+# those characters with reasonable ASCII alternatives are converted:
+#
+# - C1 Controls and Latin-1 Supplement: http://www.unicode.org/charts/PDF/U0080.pdf
+# - Latin Extended-A: http://www.unicode.org/charts/PDF/U0100.pdf
+# - Latin Extended-B: http://www.unicode.org/charts/PDF/U0180.pdf
+# - Latin Extended Additional: http://www.unicode.org/charts/PDF/U1E00.pdf
+# - Latin Extended-C: http://www.unicode.org/charts/PDF/U2C60.pdf
+# - Latin Extended-D: http://www.unicode.org/charts/PDF/UA720.pdf
+# - IPA Extensions: http://www.unicode.org/charts/PDF/U0250.pdf
+# - Phonetic Extensions: http://www.unicode.org/charts/PDF/U1D00.pdf
+# - Phonetic Extensions Supplement: http://www.unicode.org/charts/PDF/U1D80.pdf
+# - General Punctuation: http://www.unicode.org/charts/PDF/U2000.pdf
+# - Superscripts and Subscripts: http://www.unicode.org/charts/PDF/U2070.pdf
+# - Enclosed Alphanumerics: http://www.unicode.org/charts/PDF/U2460.pdf
+# - Dingbats: http://www.unicode.org/charts/PDF/U2700.pdf
+# - Supplemental Punctuation: http://www.unicode.org/charts/PDF/U2E00.pdf
+# - Alphabetic Presentation Forms: http://www.unicode.org/charts/PDF/UFB00.pdf
+# - Halfwidth and Fullwidth Forms: http://www.unicode.org/charts/PDF/UFF00.pdf
+#  
+# See: http://en.wikipedia.org/wiki/Latin_characters_in_Unicode
+#
+# The set of character conversions supported by this map is a superset of
+# those supported by the map represented by mapping-ISOLatin1Accent.txt.
+#
+# See the bottom of this file for the Perl script used to generate the contents
+# of this file (without this header) from ASCIIFoldingFilter.java.
+
+
+# Syntax:
+#   "source" => "target"
+#     "source".length() > 0 (source cannot be empty.)
+#     "target".length() >= 0 (target can be empty.)
+
+
+# À  [LATIN CAPITAL LETTER A WITH GRAVE]
+"\u00C0" => "A"
+
+# Á  [LATIN CAPITAL LETTER A WITH ACUTE]
+"\u00C1" => "A"
+
+# Â  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX]
+"\u00C2" => "A"
+
+# Ã  [LATIN CAPITAL LETTER A WITH TILDE]
+"\u00C3" => "A"
+
+# Ä  [LATIN CAPITAL LETTER A WITH DIAERESIS]
+"\u00C4" => "A"
+
+# Å  [LATIN CAPITAL LETTER A WITH RING ABOVE]
+"\u00C5" => "A"
+
+# Ā  [LATIN CAPITAL LETTER A WITH MACRON]
+"\u0100" => "A"
+
+# Ă  [LATIN CAPITAL LETTER A WITH BREVE]
+"\u0102" => "A"
+
+# Ą  [LATIN CAPITAL LETTER A WITH OGONEK]
+"\u0104" => "A"
+
+# Ə  http://en.wikipedia.org/wiki/Schwa  [LATIN CAPITAL LETTER SCHWA]
+"\u018F" => "A"
+
+# Ǎ  [LATIN CAPITAL LETTER A WITH CARON]
+"\u01CD" => "A"
+
+# Ǟ  [LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON]
+"\u01DE" => "A"
+
+# Ǡ  [LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON]
+"\u01E0" => "A"
+
+# Ǻ  [LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE]
+"\u01FA" => "A"
+
+# Ȁ  [LATIN CAPITAL LETTER A WITH DOUBLE GRAVE]
+"\u0200" => "A"
+
+# Ȃ  [LATIN CAPITAL LETTER A WITH INVERTED BREVE]
+"\u0202" => "A"
+
+# Ȧ  [LATIN CAPITAL LETTER A WITH DOT ABOVE]
+"\u0226" => "A"
+
+# Ⱥ  [LATIN CAPITAL LETTER A WITH STROKE]
+"\u023A" => "A"
+
+# ᴀ  [LATIN LETTER SMALL CAPITAL A]
+"\u1D00" => "A"
+
+# Ḁ  [LATIN CAPITAL LETTER A WITH RING BELOW]
+"\u1E00" => "A"
+
+# Ạ  [LATIN CAPITAL LETTER A WITH DOT BELOW]
+"\u1EA0" => "A"
+
+# Ả  [LATIN CAPITAL LETTER A WITH HOOK ABOVE]
+"\u1EA2" => "A"
+
+# Ấ  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE]
+"\u1EA4" => "A"
+
+# Ầ  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE]
+"\u1EA6" => "A"
+
+# Ẩ  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE]
+"\u1EA8" => "A"
+
+# Ẫ  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE]
+"\u1EAA" => "A"
+
+# Ậ  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW]
+"\u1EAC" => "A"
+
+# Ắ  [LATIN CAPITAL LETTER A WITH BREVE AND ACUTE]
+"\u1EAE" => "A"
+
+# Ằ  [LATIN CAPITAL LETTER A WITH BREVE AND GRAVE]
+"\u1EB0" => "A"
+
+# Ẳ  [LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE]
+"\u1EB2" => "A"
+
+# Ẵ  [LATIN CAPITAL LETTER A WITH BREVE AND TILDE]
+"\u1EB4" => "A"
+
+# Ặ  [LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW]
+"\u1EB6" => "A"
+
+# Ⓐ  [CIRCLED LATIN CAPITAL LETTER A]
+"\u24B6" => "A"
+
+# A  [FULLWIDTH LATIN CAPITAL LETTER A]
+"\uFF21" => "A"
+
+# à  [LATIN SMALL LETTER A WITH GRAVE]
+"\u00E0" => "a"
+
+# á  [LATIN SMALL LETTER A WITH ACUTE]
+"\u00E1" => "a"
+
+# â  [LATIN SMALL LETTER A WITH CIRCUMFLEX]
+"\u00E2" => "a"
+
+# ã  [LATIN SMALL LETTER A WITH TILDE]
+"\u00E3" => "a"
+
+# ä  [LATIN SMALL LETTER A WITH DIAERESIS]
+"\u00E4" => "a"
+
+# å  [LATIN SMALL LETTER A WITH RING ABOVE]
+"\u00E5" => "a"
+
+# ā  [LATIN SMALL LETTER A WITH MACRON]
+"\u0101" => "a"
+
+# ă  [LATIN SMALL LETTER A WITH BREVE]
+"\u0103" => "a"
+
+# ą  [LATIN SMALL LETTER A WITH OGONEK]
+"\u0105" => "a"
+
+# ǎ  [LATIN SMALL LETTER A WITH CARON]
+"\u01CE" => "a"
+
+# ǟ  [LATIN SMALL LETTER A WITH DIAERESIS AND MACRON]
+"\u01DF" => "a"
+
+# ǡ  [LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON]
+"\u01E1" => "a"
+
+# ǻ  [LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE]
+"\u01FB" => "a"
+
+# ȁ  [LATIN SMALL LETTER A WITH DOUBLE GRAVE]
+"\u0201" => "a"
+
+# ȃ  [LATIN SMALL LETTER A WITH INVERTED BREVE]
+"\u0203" => "a"
+
+# ȧ  [LATIN SMALL LETTER A WITH DOT ABOVE]
+"\u0227" => "a"
+
+# ɐ  [LATIN SMALL LETTER TURNED A]
+"\u0250" => "a"
+
+# ə  [LATIN SMALL LETTER SCHWA]
+"\u0259" => "a"
+
+# ɚ  [LATIN SMALL LETTER SCHWA WITH HOOK]
+"\u025A" => "a"
+
+# ᶏ  [LATIN SMALL LETTER A WITH RETROFLEX HOOK]
+"\u1D8F" => "a"
+
+# ᶕ  [LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK]
+"\u1D95" => "a"
+
+# ạ  [LATIN SMALL LETTER A WITH RING BELOW]
+"\u1E01" => "a"
+
+# ả  [LATIN SMALL LETTER A WITH RIGHT HALF RING]
+"\u1E9A" => "a"
+
+# ạ  [LATIN SMALL LETTER A WITH DOT BELOW]
+"\u1EA1" => "a"
+
+# ả  [LATIN SMALL LETTER A WITH HOOK ABOVE]
+"\u1EA3" => "a"
+
+# ấ  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE]
+"\u1EA5" => "a"
+
+# ầ  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE]
+"\u1EA7" => "a"
+
+# ẩ  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE]
+"\u1EA9" => "a"
+
+# ẫ  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE]
+"\u1EAB" => "a"
+
+# ậ  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW]
+"\u1EAD" => "a"
+
+# ắ  [LATIN SMALL LETTER A WITH BREVE AND ACUTE]
+"\u1EAF" => "a"
+
+# ằ  [LATIN SMALL LETTER A WITH BREVE AND GRAVE]
+"\u1EB1" => "a"
+
+# ẳ  [LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE]
+"\u1EB3" => "a"
+
+# ẵ  [LATIN SMALL LETTER A WITH BREVE AND TILDE]
+"\u1EB5" => "a"
+
+# ặ  [LATIN SMALL LETTER A WITH BREVE AND DOT BELOW]
+"\u1EB7" => "a"
+
+# ₐ  [LATIN SUBSCRIPT SMALL LETTER A]
+"\u2090" => "a"
+
+# ₔ  [LATIN SUBSCRIPT SMALL LETTER SCHWA]
+"\u2094" => "a"
+
+# ⓐ  [CIRCLED LATIN SMALL LETTER A]
+"\u24D0" => "a"
+
+# ⱥ  [LATIN SMALL LETTER A WITH STROKE]
+"\u2C65" => "a"
+
+# Ɐ  [LATIN CAPITAL LETTER TURNED A]
+"\u2C6F" => "a"
+
+# a  [FULLWIDTH LATIN SMALL LETTER A]
+"\uFF41" => "a"
+
+# Ꜳ  [LATIN CAPITAL LETTER AA]
+"\uA732" => "AA"
+
+# Æ  [LATIN CAPITAL LETTER AE]
+"\u00C6" => "AE"
+
+# Ǣ  [LATIN CAPITAL LETTER AE WITH MACRON]
+"\u01E2" => "AE"
+
+# Ǽ  [LATIN CAPITAL LETTER AE WITH ACUTE]
+"\u01FC" => "AE"
+
+# ᴁ  [LATIN LETTER SMALL CAPITAL AE]
+"\u1D01" => "AE"
+
+# Ꜵ  [LATIN CAPITAL LETTER AO]
+"\uA734" => "AO"
+
+# Ꜷ  [LATIN CAPITAL LETTER AU]
+"\uA736" => "AU"
+
+# Ꜹ  [LATIN CAPITAL LETTER AV]
+"\uA738" => "AV"
+
+# Ꜻ  [LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR]
+"\uA73A" => "AV"
+
+# Ꜽ  [LATIN CAPITAL LETTER AY]
+"\uA73C" => "AY"
+
+# ⒜  [PARENTHESIZED LATIN SMALL LETTER A]
+"\u249C" => "(a)"
+
+# ꜳ  [LATIN SMALL LETTER AA]
+"\uA733" => "aa"
+
+# æ  [LATIN SMALL LETTER AE]
+"\u00E6" => "ae"
+
+# ǣ  [LATIN SMALL LETTER AE WITH MACRON]
+"\u01E3" => "ae"
+
+# ǽ  [LATIN SMALL LETTER AE WITH ACUTE]
+"\u01FD" => "ae"
+
+# ᴂ  [LATIN SMALL LETTER TURNED AE]
+"\u1D02" => "ae"
+
+# ꜵ  [LATIN SMALL LETTER AO]
+"\uA735" => "ao"
+
+# ꜷ  [LATIN SMALL LETTER AU]
+"\uA737" => "au"
+
+# ꜹ  [LATIN SMALL LETTER AV]
+"\uA739" => "av"
+
+# ꜻ  [LATIN SMALL LETTER AV WITH HORIZONTAL BAR]
+"\uA73B" => "av"
+
+# ꜽ  [LATIN SMALL LETTER AY]
+"\uA73D" => "ay"
+
+# Ɓ  [LATIN CAPITAL LETTER B WITH HOOK]
+"\u0181" => "B"
+
+# Ƃ  [LATIN CAPITAL LETTER B WITH TOPBAR]
+"\u0182" => "B"
+
+# Ƀ  [LATIN CAPITAL LETTER B WITH STROKE]
+"\u0243" => "B"
+
+# ʙ  [LATIN LETTER SMALL CAPITAL B]
+"\u0299" => "B"
+
+# ᴃ  [LATIN LETTER SMALL CAPITAL BARRED B]
+"\u1D03" => "B"
+
+# Ḃ  [LATIN CAPITAL LETTER B WITH DOT ABOVE]
+"\u1E02" => "B"
+
+# Ḅ  [LATIN CAPITAL LETTER B WITH DOT BELOW]
+"\u1E04" => "B"
+
+# Ḇ  [LATIN CAPITAL LETTER B WITH LINE BELOW]
+"\u1E06" => "B"
+
+# Ⓑ  [CIRCLED LATIN CAPITAL LETTER B]
+"\u24B7" => "B"
+
+# B  [FULLWIDTH LATIN CAPITAL LETTER B]
+"\uFF22" => "B"
+
+# ƀ  [LATIN SMALL LETTER B WITH STROKE]
+"\u0180" => "b"
+
+# ƃ  [LATIN SMALL LETTER B WITH TOPBAR]
+"\u0183" => "b"
+
+# ɓ  [LATIN SMALL LETTER B WITH HOOK]
+"\u0253" => "b"
+
+# ᵬ  [LATIN SMALL LETTER B WITH MIDDLE TILDE]
+"\u1D6C" => "b"
+
+# ᶀ  [LATIN SMALL LETTER B WITH PALATAL HOOK]
+"\u1D80" => "b"
+
+# ḃ  [LATIN SMALL LETTER B WITH DOT ABOVE]
+"\u1E03" => "b"
+
+# ḅ  [LATIN SMALL LETTER B WITH DOT BELOW]
+"\u1E05" => "b"
+
+# ḇ  [LATIN SMALL LETTER B WITH LINE BELOW]
+"\u1E07" => "b"
+
+# ⓑ  [CIRCLED LATIN SMALL LETTER B]
+"\u24D1" => "b"
+
+# b  [FULLWIDTH LATIN SMALL LETTER B]
+"\uFF42" => "b"
+
+# ⒝  [PARENTHESIZED LATIN SMALL LETTER B]
+"\u249D" => "(b)"
+
+# Ç  [LATIN CAPITAL LETTER C WITH CEDILLA]
+"\u00C7" => "C"
+
+# Ć  [LATIN CAPITAL LETTER C WITH ACUTE]
+"\u0106" => "C"
+
+# Ĉ  [LATIN CAPITAL LETTER C WITH CIRCUMFLEX]
+"\u0108" => "C"
+
+# Ċ  [LATIN CAPITAL LETTER C WITH DOT ABOVE]
+"\u010A" => "C"
+
+# Č  [LATIN CAPITAL LETTER C WITH CARON]
+"\u010C" => "C"
+
+# Ƈ  [LATIN CAPITAL LETTER C WITH HOOK]
+"\u0187" => "C"
+
+# Ȼ  [LATIN CAPITAL LETTER C WITH STROKE]
+"\u023B" => "C"
+
+# ʗ  [LATIN LETTER STRETCHED C]
+"\u0297" => "C"
+
+# ᴄ  [LATIN LETTER SMALL CAPITAL C]
+"\u1D04" => "C"
+
+# Ḉ  [LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE]
+"\u1E08" => "C"
+
+# Ⓒ  [CIRCLED LATIN CAPITAL LETTER C]
+"\u24B8" => "C"
+
+# C  [FULLWIDTH LATIN CAPITAL LETTER C]
+"\uFF23" => "C"
+
+# ç  [LATIN SMALL LETTER C WITH CEDILLA]
+"\u00E7" => "c"
+
+# ć  [LATIN SMALL LETTER C WITH ACUTE]
+"\u0107" => "c"
+
+# ĉ  [LATIN SMALL LETTER C WITH CIRCUMFLEX]
+"\u0109" => "c"
+
+# ċ  [LATIN SMALL LETTER C WITH DOT ABOVE]
+"\u010B" => "c"
+
+# č  [LATIN SMALL LETTER C WITH CARON]
+"\u010D" => "c"
+
+# ƈ  [LATIN SMALL LETTER C WITH HOOK]
+"\u0188" => "c"
+
+# ȼ  [LATIN SMALL LETTER C WITH STROKE]
+"\u023C" => "c"
+
+# ɕ  [LATIN SMALL LETTER C WITH CURL]
+"\u0255" => "c"
+
+# ḉ  [LATIN SMALL LETTER C WITH CEDILLA AND ACUTE]
+"\u1E09" => "c"
+
+# ↄ  [LATIN SMALL LETTER REVERSED C]
+"\u2184" => "c"
+
+# ⓒ  [CIRCLED LATIN SMALL LETTER C]
+"\u24D2" => "c"
+
+# Ꜿ  [LATIN CAPITAL LETTER REVERSED C WITH DOT]
+"\uA73E" => "c"
+
+# ꜿ  [LATIN SMALL LETTER REVERSED C WITH DOT]
+"\uA73F" => "c"
+
+# c  [FULLWIDTH LATIN SMALL LETTER C]
+"\uFF43" => "c"
+
+# ⒞  [PARENTHESIZED LATIN SMALL LETTER C]
+"\u249E" => "(c)"
+
+# Ð  [LATIN CAPITAL LETTER ETH]
+"\u00D0" => "D"
+
+# Ď  [LATIN CAPITAL LETTER D WITH CARON]
+"\u010E" => "D"
+
+# Đ  [LATIN CAPITAL LETTER D WITH STROKE]
+"\u0110" => "D"
+
+# Ɖ  [LATIN CAPITAL LETTER AFRICAN D]
+"\u0189" => "D"
+
+# Ɗ  [LATIN CAPITAL LETTER D WITH HOOK]
+"\u018A" => "D"
+
+# Ƌ  [LATIN CAPITAL LETTER D WITH TOPBAR]
+"\u018B" => "D"
+
+# ᴅ  [LATIN LETTER SMALL CAPITAL D]
+"\u1D05" => "D"
+
+# ᴆ  [LATIN LETTER SMALL CAPITAL ETH]
+"\u1D06" => "D"
+
+# Ḋ  [LATIN CAPITAL LETTER D WITH DOT ABOVE]
+"\u1E0A" => "D"
+
+# Ḍ  [LATIN CAPITAL LETTER D WITH DOT BELOW]
+"\u1E0C" => "D"
+
+# Ḏ  [LATIN CAPITAL LETTER D WITH LINE BELOW]
+"\u1E0E" => "D"
+
+# Ḑ  [LATIN CAPITAL LETTER D WITH CEDILLA]
+"\u1E10" => "D"
+
+# Ḓ  [LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW]
+"\u1E12" => "D"
+
+# Ⓓ  [CIRCLED LATIN CAPITAL LETTER D]
+"\u24B9" => "D"
+
+# Ꝺ  [LATIN CAPITAL LETTER INSULAR D]
+"\uA779" => "D"
+
+# D  [FULLWIDTH LATIN CAPITAL LETTER D]
+"\uFF24" => "D"
+
+# ð  [LATIN SMALL LETTER ETH]
+"\u00F0" => "d"
+
+# ď  [LATIN SMALL LETTER D WITH CARON]
+"\u010F" => "d"
+
+# đ  [LATIN SMALL LETTER D WITH STROKE]
+"\u0111" => "d"
+
+# ƌ  [LATIN SMALL LETTER D WITH TOPBAR]
+"\u018C" => "d"
+
+# ȡ  [LATIN SMALL LETTER D WITH CURL]
+"\u0221" => "d"
+
+# ɖ  [LATIN SMALL LETTER D WITH TAIL]
+"\u0256" => "d"
+
+# ɗ  [LATIN SMALL LETTER D WITH HOOK]
+"\u0257" => "d"
+
+# ᵭ  [LATIN SMALL LETTER D WITH MIDDLE TILDE]
+"\u1D6D" => "d"
+
+# ᶁ  [LATIN SMALL LETTER D WITH PALATAL HOOK]
+"\u1D81" => "d"
+
+# ᶑ  [LATIN SMALL LETTER D WITH HOOK AND TAIL]
+"\u1D91" => "d"
+
+# ḋ  [LATIN SMALL LETTER D WITH DOT ABOVE]
+"\u1E0B" => "d"
+
+# ḍ  [LATIN SMALL LETTER D WITH DOT BELOW]
+"\u1E0D" => "d"
+
+# ḏ  [LATIN SMALL LETTER D WITH LINE BELOW]
+"\u1E0F" => "d"
+
+# ḑ  [LATIN SMALL LETTER D WITH CEDILLA]
+"\u1E11" => "d"
+
+# ḓ  [LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW]
+"\u1E13" => "d"
+
+# ⓓ  [CIRCLED LATIN SMALL LETTER D]
+"\u24D3" => "d"
+
+# ꝺ  [LATIN SMALL LETTER INSULAR D]
+"\uA77A" => "d"
+
+# d  [FULLWIDTH LATIN SMALL LETTER D]
+"\uFF44" => "d"
+
+# DŽ  [LATIN CAPITAL LETTER DZ WITH CARON]
+"\u01C4" => "DZ"
+
+# DZ  [LATIN CAPITAL LETTER DZ]
+"\u01F1" => "DZ"
+
+# Dž  [LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON]
+"\u01C5" => "Dz"
+
+# Dz  [LATIN CAPITAL LETTER D WITH SMALL LETTER Z]
+"\u01F2" => "Dz"
+
+# ⒟  [PARENTHESIZED LATIN SMALL LETTER D]
+"\u249F" => "(d)"
+
+# ȸ  [LATIN SMALL LETTER DB DIGRAPH]
+"\u0238" => "db"
+
+# dž  [LATIN SMALL LETTER DZ WITH CARON]
+"\u01C6" => "dz"
+
+# dz  [LATIN SMALL LETTER DZ]
+"\u01F3" => "dz"
+
+# ʣ  [LATIN SMALL LETTER DZ DIGRAPH]
+"\u02A3" => "dz"
+
+# ʥ  [LATIN SMALL LETTER DZ DIGRAPH WITH CURL]
+"\u02A5" => "dz"
+
+# È  [LATIN CAPITAL LETTER E WITH GRAVE]
+"\u00C8" => "E"
+
+# É  [LATIN CAPITAL LETTER E WITH ACUTE]
+"\u00C9" => "E"
+
+# Ê  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX]
+"\u00CA" => "E"
+
+# Ë  [LATIN CAPITAL LETTER E WITH DIAERESIS]
+"\u00CB" => "E"
+
+# Ē  [LATIN CAPITAL LETTER E WITH MACRON]
+"\u0112" => "E"
+
+# Ĕ  [LATIN CAPITAL LETTER E WITH BREVE]
+"\u0114" => "E"
+
+# Ė  [LATIN CAPITAL LETTER E WITH DOT ABOVE]
+"\u0116" => "E"
+
+# Ę  [LATIN CAPITAL LETTER E WITH OGONEK]
+"\u0118" => "E"
+
+# Ě  [LATIN CAPITAL LETTER E WITH CARON]
+"\u011A" => "E"
+
+# Ǝ  [LATIN CAPITAL LETTER REVERSED E]
+"\u018E" => "E"
+
+# Ɛ  [LATIN CAPITAL LETTER OPEN E]
+"\u0190" => "E"
+
+# Ȅ  [LATIN CAPITAL LETTER E WITH DOUBLE GRAVE]
+"\u0204" => "E"
+
+# Ȇ  [LATIN CAPITAL LETTER E WITH INVERTED BREVE]
+"\u0206" => "E"
+
+# Ȩ  [LATIN CAPITAL LETTER E WITH CEDILLA]
+"\u0228" => "E"
+
+# Ɇ  [LATIN CAPITAL LETTER E WITH STROKE]
+"\u0246" => "E"
+
+# ᴇ  [LATIN LETTER SMALL CAPITAL E]
+"\u1D07" => "E"
+
+# Ḕ  [LATIN CAPITAL LETTER E WITH MACRON AND GRAVE]
+"\u1E14" => "E"
+
+# Ḗ  [LATIN CAPITAL LETTER E WITH MACRON AND ACUTE]
+"\u1E16" => "E"
+
+# Ḙ  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW]
+"\u1E18" => "E"
+
+# Ḛ  [LATIN CAPITAL LETTER E WITH TILDE BELOW]
+"\u1E1A" => "E"
+
+# Ḝ  [LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE]
+"\u1E1C" => "E"
+
+# Ẹ  [LATIN CAPITAL LETTER E WITH DOT BELOW]
+"\u1EB8" => "E"
+
+# Ẻ  [LATIN CAPITAL LETTER E WITH HOOK ABOVE]
+"\u1EBA" => "E"
+
+# Ẽ  [LATIN CAPITAL LETTER E WITH TILDE]
+"\u1EBC" => "E"
+
+# Ế  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE]
+"\u1EBE" => "E"
+
+# Ề  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE]
+"\u1EC0" => "E"
+
+# Ể  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE]
+"\u1EC2" => "E"
+
+# Ễ  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE]
+"\u1EC4" => "E"
+
+# Ệ  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW]
+"\u1EC6" => "E"
+
+# Ⓔ  [CIRCLED LATIN CAPITAL LETTER E]
+"\u24BA" => "E"
+
+# ⱻ  [LATIN LETTER SMALL CAPITAL TURNED E]
+"\u2C7B" => "E"
+
+# E  [FULLWIDTH LATIN CAPITAL LETTER E]
+"\uFF25" => "E"
+
+# è  [LATIN SMALL LETTER E WITH GRAVE]
+"\u00E8" => "e"
+
+# é  [LATIN SMALL LETTER E WITH ACUTE]
+"\u00E9" => "e"
+
+# ê  [LATIN SMALL LETTER E WITH CIRCUMFLEX]
+"\u00EA" => "e"
+
+# ë  [LATIN SMALL LETTER E WITH DIAERESIS]
+"\u00EB" => "e"
+
+# ē  [LATIN SMALL LETTER E WITH MACRON]
+"\u0113" => "e"
+
+# ĕ  [LATIN SMALL LETTER E WITH BREVE]
+"\u0115" => "e"
+
+# ė  [LATIN SMALL LETTER E WITH DOT ABOVE]
+"\u0117" => "e"
+
+# ę  [LATIN SMALL LETTER E WITH OGONEK]
+"\u0119" => "e"
+
+# ě  [LATIN SMALL LETTER E WITH CARON]
+"\u011B" => "e"
+
+# ǝ  [LATIN SMALL LETTER TURNED E]
+"\u01DD" => "e"
+
+# ȅ  [LATIN SMALL LETTER E WITH DOUBLE GRAVE]
+"\u0205" => "e"
+
+# ȇ  [LATIN SMALL LETTER E WITH INVERTED BREVE]
+"\u0207" => "e"
+
+# ȩ  [LATIN SMALL LETTER E WITH CEDILLA]
+"\u0229" => "e"
+
+# ɇ  [LATIN SMALL LETTER E WITH STROKE]
+"\u0247" => "e"
+
+# ɘ  [LATIN SMALL LETTER REVERSED E]
+"\u0258" => "e"
+
+# ɛ  [LATIN SMALL LETTER OPEN E]
+"\u025B" => "e"
+
+# ɜ  [LATIN SMALL LETTER REVERSED OPEN E]
+"\u025C" => "e"
+
+# ɝ  [LATIN SMALL LETTER REVERSED OPEN E WITH HOOK]
+"\u025D" => "e"
+
+# ɞ  [LATIN SMALL LETTER CLOSED REVERSED OPEN E]
+"\u025E" => "e"
+
+# ʚ  [LATIN SMALL LETTER CLOSED OPEN E]
+"\u029A" => "e"
+
+# ᴈ  [LATIN SMALL LETTER TURNED OPEN E]
+"\u1D08" => "e"
+
+# ᶒ  [LATIN SMALL LETTER E WITH RETROFLEX HOOK]
+"\u1D92" => "e"
+
+# ᶓ  [LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK]
+"\u1D93" => "e"
+
+# ᶔ  [LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK]
+"\u1D94" => "e"
+
+# ḕ  [LATIN SMALL LETTER E WITH MACRON AND GRAVE]
+"\u1E15" => "e"
+
+# ḗ  [LATIN SMALL LETTER E WITH MACRON AND ACUTE]
+"\u1E17" => "e"
+
+# ḙ  [LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW]
+"\u1E19" => "e"
+
+# ḛ  [LATIN SMALL LETTER E WITH TILDE BELOW]
+"\u1E1B" => "e"
+
+# ḝ  [LATIN SMALL LETTER E WITH CEDILLA AND BREVE]
+"\u1E1D" => "e"
+
+# ẹ  [LATIN SMALL LETTER E WITH DOT BELOW]
+"\u1EB9" => "e"
+
+# ẻ  [LATIN SMALL LETTER E WITH HOOK ABOVE]
+"\u1EBB" => "e"
+
+# ẽ  [LATIN SMALL LETTER E WITH TILDE]
+"\u1EBD" => "e"
+
+# ế  [LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE]
+"\u1EBF" => "e"
+
+# ề  [LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE]
+"\u1EC1" => "e"
+
+# ể  [LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE]
+"\u1EC3" => "e"
+
+# ễ  [LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE]
+"\u1EC5" => "e"
+
+# ệ  [LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW]
+"\u1EC7" => "e"
+
+# ₑ  [LATIN SUBSCRIPT SMALL LETTER E]
+"\u2091" => "e"
+
+# ⓔ  [CIRCLED LATIN SMALL LETTER E]
+"\u24D4" => "e"
+
+# ⱸ  [LATIN SMALL LETTER E WITH NOTCH]
+"\u2C78" => "e"
+
+# e  [FULLWIDTH LATIN SMALL LETTER E]
+"\uFF45" => "e"
+
+# ⒠  [PARENTHESIZED LATIN SMALL LETTER E]
+"\u24A0" => "(e)"
+
+# Ƒ  [LATIN CAPITAL LETTER F WITH HOOK]
+"\u0191" => "F"
+
+# Ḟ  [LATIN CAPITAL LETTER F WITH DOT ABOVE]
+"\u1E1E" => "F"
+
+# Ⓕ  [CIRCLED LATIN CAPITAL LETTER F]
+"\u24BB" => "F"
+
+# ꜰ  [LATIN LETTER SMALL CAPITAL F]
+"\uA730" => "F"
+
+# Ꝼ  [LATIN CAPITAL LETTER INSULAR F]
+"\uA77B" => "F"
+
+# ꟻ  [LATIN EPIGRAPHIC LETTER REVERSED F]
+"\uA7FB" => "F"
+
+# F  [FULLWIDTH LATIN CAPITAL LETTER F]
+"\uFF26" => "F"
+
+# ƒ  [LATIN SMALL LETTER F WITH HOOK]
+"\u0192" => "f"
+
+# ᵮ  [LATIN SMALL LETTER F WITH MIDDLE TILDE]
+"\u1D6E" => "f"
+
+# ᶂ  [LATIN SMALL LETTER F WITH PALATAL HOOK]
+"\u1D82" => "f"
+
+# ḟ  [LATIN SMALL LETTER F WITH DOT ABOVE]
+"\u1E1F" => "f"
+
+# ẛ  [LATIN SMALL LETTER LONG S WITH DOT ABOVE]
+"\u1E9B" => "f"
+
+# ⓕ  [CIRCLED LATIN SMALL LETTER F]
+"\u24D5" => "f"
+
+# ꝼ  [LATIN SMALL LETTER INSULAR F]
+"\uA77C" => "f"
+
+# f  [FULLWIDTH LATIN SMALL LETTER F]
+"\uFF46" => "f"
+
+# ⒡  [PARENTHESIZED LATIN SMALL LETTER F]
+"\u24A1" => "(f)"
+
+# ff  [LATIN SMALL LIGATURE FF]
+"\uFB00" => "ff"
+
+# ffi  [LATIN SMALL LIGATURE FFI]
+"\uFB03" => "ffi"
+
+# ffl  [LATIN SMALL LIGATURE FFL]
+"\uFB04" => "ffl"
+
+# fi  [LATIN SMALL LIGATURE FI]
+"\uFB01" => "fi"
+
+# fl  [LATIN SMALL LIGATURE FL]
+"\uFB02" => "fl"
+
+# Ĝ  [LATIN CAPITAL LETTER G WITH CIRCUMFLEX]
+"\u011C" => "G"
+
+# Ğ  [LATIN CAPITAL LETTER G WITH BREVE]
+"\u011E" => "G"
+
+# Ġ  [LATIN CAPITAL LETTER G WITH DOT ABOVE]
+"\u0120" => "G"
+
+# Ģ  [LATIN CAPITAL LETTER G WITH CEDILLA]
+"\u0122" => "G"
+
+# Ɠ  [LATIN CAPITAL LETTER G WITH HOOK]
+"\u0193" => "G"
+
+# Ǥ  [LATIN CAPITAL LETTER G WITH STROKE]
+"\u01E4" => "G"
+
+# ǥ  [LATIN SMALL LETTER G WITH STROKE]
+"\u01E5" => "G"
+
+# Ǧ  [LATIN CAPITAL LETTER G WITH CARON]
+"\u01E6" => "G"
+
+# ǧ  [LATIN SMALL LETTER G WITH CARON]
+"\u01E7" => "G"
+
+# Ǵ  [LATIN CAPITAL LETTER G WITH ACUTE]
+"\u01F4" => "G"
+
+# ɢ  [LATIN LETTER SMALL CAPITAL G]
+"\u0262" => "G"
+
+# ʛ  [LATIN LETTER SMALL CAPITAL G WITH HOOK]
+"\u029B" => "G"
+
+# Ḡ  [LATIN CAPITAL LETTER G WITH MACRON]
+"\u1E20" => "G"
+
+# Ⓖ  [CIRCLED LATIN CAPITAL LETTER G]
+"\u24BC" => "G"
+
+# Ᵹ  [LATIN CAPITAL LETTER INSULAR G]
+"\uA77D" => "G"
+
+# Ꝿ  [LATIN CAPITAL LETTER TURNED INSULAR G]
+"\uA77E" => "G"
+
+# G  [FULLWIDTH LATIN CAPITAL LETTER G]
+"\uFF27" => "G"
+
+# ĝ  [LATIN SMALL LETTER G WITH CIRCUMFLEX]
+"\u011D" => "g"
+
+# ğ  [LATIN SMALL LETTER G WITH BREVE]
+"\u011F" => "g"
+
+# ġ  [LATIN SMALL LETTER G WITH DOT ABOVE]
+"\u0121" => "g"
+
+# ģ  [LATIN SMALL LETTER G WITH CEDILLA]
+"\u0123" => "g"
+
+# ǵ  [LATIN SMALL LETTER G WITH ACUTE]
+"\u01F5" => "g"
+
+# ɠ  [LATIN SMALL LETTER G WITH HOOK]
+"\u0260" => "g"
+
+# ɡ  [LATIN SMALL LETTER SCRIPT G]
+"\u0261" => "g"
+
+# ᵷ  [LATIN SMALL LETTER TURNED G]
+"\u1D77" => "g"
+
+# ᵹ  [LATIN SMALL LETTER INSULAR G]
+"\u1D79" => "g"
+
+# ᶃ  [LATIN SMALL LETTER G WITH PALATAL HOOK]
+"\u1D83" => "g"
+
+# ḡ  [LATIN SMALL LETTER G WITH MACRON]
+"\u1E21" => "g"
+
+# ⓖ  [CIRCLED LATIN SMALL LETTER G]
+"\u24D6" => "g"
+
+# ꝿ  [LATIN SMALL LETTER TURNED INSULAR G]
+"\uA77F" => "g"
+
+# g  [FULLWIDTH LATIN SMALL LETTER G]
+"\uFF47" => "g"
+
+# ⒢  [PARENTHESIZED LATIN SMALL LETTER G]
+"\u24A2" => "(g)"
+
+# Ĥ  [LATIN CAPITAL LETTER H WITH CIRCUMFLEX]
+"\u0124" => "H"
+
+# Ħ  [LATIN CAPITAL LETTER H WITH STROKE]
+"\u0126" => "H"
+
+# Ȟ  [LATIN CAPITAL LETTER H WITH CARON]
+"\u021E" => "H"
+
+# ʜ  [LATIN LETTER SMALL CAPITAL H]
+"\u029C" => "H"
+
+# Ḣ  [LATIN CAPITAL LETTER H WITH DOT ABOVE]
+"\u1E22" => "H"
+
+# Ḥ  [LATIN CAPITAL LETTER H WITH DOT BELOW]
+"\u1E24" => "H"
+
+# Ḧ  [LATIN CAPITAL LETTER H WITH DIAERESIS]
+"\u1E26" => "H"
+
+# Ḩ  [LATIN CAPITAL LETTER H WITH CEDILLA]
+"\u1E28" => "H"
+
+# Ḫ  [LATIN CAPITAL LETTER H WITH BREVE BELOW]
+"\u1E2A" => "H"
+
+# Ⓗ  [CIRCLED LATIN CAPITAL LETTER H]
+"\u24BD" => "H"
+
+# Ⱨ  [LATIN CAPITAL LETTER H WITH DESCENDER]
+"\u2C67" => "H"
+
+# Ⱶ  [LATIN CAPITAL LETTER HALF H]
+"\u2C75" => "H"
+
+# H  [FULLWIDTH LATIN CAPITAL LETTER H]
+"\uFF28" => "H"
+
+# ĥ  [LATIN SMALL LETTER H WITH CIRCUMFLEX]
+"\u0125" => "h"
+
+# ħ  [LATIN SMALL LETTER H WITH STROKE]
+"\u0127" => "h"
+
+# ȟ  [LATIN SMALL LETTER H WITH CARON]
+"\u021F" => "h"
+
+# ɥ  [LATIN SMALL LETTER TURNED H]
+"\u0265" => "h"
+
+# ɦ  [LATIN SMALL LETTER H WITH HOOK]
+"\u0266" => "h"
+
+# ʮ  [LATIN SMALL LETTER TURNED H WITH FISHHOOK]
+"\u02AE" => "h"
+
+# ʯ  [LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL]
+"\u02AF" => "h"
+
+# ḣ  [LATIN SMALL LETTER H WITH DOT ABOVE]
+"\u1E23" => "h"
+
+# ḥ  [LATIN SMALL LETTER H WITH DOT BELOW]
+"\u1E25" => "h"
+
+# ḧ  [LATIN SMALL LETTER H WITH DIAERESIS]
+"\u1E27" => "h"
+
+# ḩ  [LATIN SMALL LETTER H WITH CEDILLA]
+"\u1E29" => "h"
+
+# ḫ  [LATIN SMALL LETTER H WITH BREVE BELOW]
+"\u1E2B" => "h"
+
+# ẖ  [LATIN SMALL LETTER H WITH LINE BELOW]
+"\u1E96" => "h"
+
+# ⓗ  [CIRCLED LATIN SMALL LETTER H]
+"\u24D7" => "h"
+
+# ⱨ  [LATIN SMALL LETTER H WITH DESCENDER]
+"\u2C68" => "h"
+
+# ⱶ  [LATIN SMALL LETTER HALF H]
+"\u2C76" => "h"
+
+# h  [FULLWIDTH LATIN SMALL LETTER H]
+"\uFF48" => "h"
+
+# Ƕ  http://en.wikipedia.org/wiki/Hwair  [LATIN CAPITAL LETTER HWAIR]
+"\u01F6" => "HV"
+
+# ⒣  [PARENTHESIZED LATIN SMALL LETTER H]
+"\u24A3" => "(h)"
+
+# ƕ  [LATIN SMALL LETTER HV]
+"\u0195" => "hv"
+
+# Ì  [LATIN CAPITAL LETTER I WITH GRAVE]
+"\u00CC" => "I"
+
+# Í  [LATIN CAPITAL LETTER I WITH ACUTE]
+"\u00CD" => "I"
+
+# Î  [LATIN CAPITAL LETTER I WITH CIRCUMFLEX]
+"\u00CE" => "I"
+
+# Ï  [LATIN CAPITAL LETTER I WITH DIAERESIS]
+"\u00CF" => "I"
+
+# Ĩ  [LATIN CAPITAL LETTER I WITH TILDE]
+"\u0128" => "I"
+
+# Ī  [LATIN CAPITAL LETTER I WITH MACRON]
+"\u012A" => "I"
+
+# Ĭ  [LATIN CAPITAL LETTER I WITH BREVE]
+"\u012C" => "I"
+
+# Į  [LATIN CAPITAL LETTER I WITH OGONEK]
+"\u012E" => "I"
+
+# İ  [LATIN CAPITAL LETTER I WITH DOT ABOVE]
+"\u0130" => "I"
+
+# Ɩ  [LATIN CAPITAL LETTER IOTA]
+"\u0196" => "I"
+
+# Ɨ  [LATIN CAPITAL LETTER I WITH STROKE]
+"\u0197" => "I"
+
+# Ǐ  [LATIN CAPITAL LETTER I WITH CARON]
+"\u01CF" => "I"
+
+# Ȉ  [LATIN CAPITAL LETTER I WITH DOUBLE GRAVE]
+"\u0208" => "I"
+
+# Ȋ  [LATIN CAPITAL LETTER I WITH INVERTED BREVE]
+"\u020A" => "I"
+
+# ɪ  [LATIN LETTER SMALL CAPITAL I]
+"\u026A" => "I"
+
+# ᵻ  [LATIN SMALL CAPITAL LETTER I WITH STROKE]
+"\u1D7B" => "I"
+
+# Ḭ  [LATIN CAPITAL LETTER I WITH TILDE BELOW]
+"\u1E2C" => "I"
+
+# Ḯ  [LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE]
+"\u1E2E" => "I"
+
+# Ỉ  [LATIN CAPITAL LETTER I WITH HOOK ABOVE]
+"\u1EC8" => "I"
+
+# Ị  [LATIN CAPITAL LETTER I WITH DOT BELOW]
+"\u1ECA" => "I"
+
+# Ⓘ  [CIRCLED LATIN CAPITAL LETTER I]
+"\u24BE" => "I"
+
+# ꟾ  [LATIN EPIGRAPHIC LETTER I LONGA]
+"\uA7FE" => "I"
+
+# I  [FULLWIDTH LATIN CAPITAL LETTER I]
+"\uFF29" => "I"
+
+# ì  [LATIN SMALL LETTER I WITH GRAVE]
+"\u00EC" => "i"
+
+# í  [LATIN SMALL LETTER I WITH ACUTE]
+"\u00ED" => "i"
+
+# î  [LATIN SMALL LETTER I WITH CIRCUMFLEX]
+"\u00EE" => "i"
+
+# ï  [LATIN SMALL LETTER I WITH DIAERESIS]
+"\u00EF" => "i"
+
+# ĩ  [LATIN SMALL LETTER I WITH TILDE]
+"\u0129" => "i"
+
+# ī  [LATIN SMALL LETTER I WITH MACRON]
+"\u012B" => "i"
+
+# ĭ  [LATIN SMALL LETTER I WITH BREVE]
+"\u012D" => "i"
+
+# į  [LATIN SMALL LETTER I WITH OGONEK]
+"\u012F" => "i"
+
+# ı  [LATIN SMALL LETTER DOTLESS I]
+"\u0131" => "i"
+
+# ǐ  [LATIN SMALL LETTER I WITH CARON]
+"\u01D0" => "i"
+
+# ȉ  [LATIN SMALL LETTER I WITH DOUBLE GRAVE]
+"\u0209" => "i"
+
+# ȋ  [LATIN SMALL LETTER I WITH INVERTED BREVE]
+"\u020B" => "i"
+
+# ɨ  [LATIN SMALL LETTER I WITH STROKE]
+"\u0268" => "i"
+
+# ᴉ  [LATIN SMALL LETTER TURNED I]
+"\u1D09" => "i"
+
+# ᵢ  [LATIN SUBSCRIPT SMALL LETTER I]
+"\u1D62" => "i"
+
+# ᵼ  [LATIN SMALL LETTER IOTA WITH STROKE]
+"\u1D7C" => "i"
+
+# ᶖ  [LATIN SMALL LETTER I WITH RETROFLEX HOOK]
+"\u1D96" => "i"
+
+# ḭ  [LATIN SMALL LETTER I WITH TILDE BELOW]
+"\u1E2D" => "i"
+
+# ḯ  [LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE]
+"\u1E2F" => "i"
+
+# ỉ  [LATIN SMALL LETTER I WITH HOOK ABOVE]
+"\u1EC9" => "i"
+
+# ị  [LATIN SMALL LETTER I WITH DOT BELOW]
+"\u1ECB" => "i"
+
+# ⁱ  [SUPERSCRIPT LATIN SMALL LETTER I]
+"\u2071" => "i"
+
+# ⓘ  [CIRCLED LATIN SMALL LETTER I]
+"\u24D8" => "i"
+
+# i  [FULLWIDTH LATIN SMALL LETTER I]
+"\uFF49" => "i"
+
+# IJ  [LATIN CAPITAL LIGATURE IJ]
+"\u0132" => "IJ"
+
+# ⒤  [PARENTHESIZED LATIN SMALL LETTER I]
+"\u24A4" => "(i)"
+
+# ij  [LATIN SMALL LIGATURE IJ]
+"\u0133" => "ij"
+
+# Ĵ  [LATIN CAPITAL LETTER J WITH CIRCUMFLEX]
+"\u0134" => "J"
+
+# Ɉ  [LATIN CAPITAL LETTER J WITH STROKE]
+"\u0248" => "J"
+
+# ᴊ  [LATIN LETTER SMALL CAPITAL J]
+"\u1D0A" => "J"
+
+# Ⓙ  [CIRCLED LATIN CAPITAL LETTER J]
+"\u24BF" => "J"
+
+# J  [FULLWIDTH LATIN CAPITAL LETTER J]
+"\uFF2A" => "J"
+
+# ĵ  [LATIN SMALL LETTER J WITH CIRCUMFLEX]
+"\u0135" => "j"
+
+# ǰ  [LATIN SMALL LETTER J WITH CARON]
+"\u01F0" => "j"
+
+# ȷ  [LATIN SMALL LETTER DOTLESS J]
+"\u0237" => "j"
+
+# ɉ  [LATIN SMALL LETTER J WITH STROKE]
+"\u0249" => "j"
+
+# ɟ  [LATIN SMALL LETTER DOTLESS J WITH STROKE]
+"\u025F" => "j"
+
+# ʄ  [LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK]
+"\u0284" => "j"
+
+# ʝ  [LATIN SMALL LETTER J WITH CROSSED-TAIL]
+"\u029D" => "j"
+
+# ⓙ  [CIRCLED LATIN SMALL LETTER J]
+"\u24D9" => "j"
+
+# ⱼ  [LATIN SUBSCRIPT SMALL LETTER J]
+"\u2C7C" => "j"
+
+# j  [FULLWIDTH LATIN SMALL LETTER J]
+"\uFF4A" => "j"
+
+# ⒥  [PARENTHESIZED LATIN SMALL LETTER J]
+"\u24A5" => "(j)"
+
+# Ķ  [LATIN CAPITAL LETTER K WITH CEDILLA]
+"\u0136" => "K"
+
+# Ƙ  [LATIN CAPITAL LETTER K WITH HOOK]
+"\u0198" => "K"
+
+# Ǩ  [LATIN CAPITAL LETTER K WITH CARON]
+"\u01E8" => "K"
+
+# ᴋ  [LATIN LETTER SMALL CAPITAL K]
+"\u1D0B" => "K"
+
+# Ḱ  [LATIN CAPITAL LETTER K WITH ACUTE]
+"\u1E30" => "K"
+
+# Ḳ  [LATIN CAPITAL LETTER K WITH DOT BELOW]
+"\u1E32" => "K"
+
+# Ḵ  [LATIN CAPITAL LETTER K WITH LINE BELOW]
+"\u1E34" => "K"
+
+# Ⓚ  [CIRCLED LATIN CAPITAL LETTER K]
+"\u24C0" => "K"
+
+# Ⱪ  [LATIN CAPITAL LETTER K WITH DESCENDER]
+"\u2C69" => "K"
+
+# Ꝁ  [LATIN CAPITAL LETTER K WITH STROKE]
+"\uA740" => "K"
+
+# Ꝃ  [LATIN CAPITAL LETTER K WITH DIAGONAL STROKE]
+"\uA742" => "K"
+
+# Ꝅ  [LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE]
+"\uA744" => "K"
+
+# K  [FULLWIDTH LATIN CAPITAL LETTER K]
+"\uFF2B" => "K"
+
+# ķ  [LATIN SMALL LETTER K WITH CEDILLA]
+"\u0137" => "k"
+
+# ƙ  [LATIN SMALL LETTER K WITH HOOK]
+"\u0199" => "k"
+
+# ǩ  [LATIN SMALL LETTER K WITH CARON]
+"\u01E9" => "k"
+
+# ʞ  [LATIN SMALL LETTER TURNED K]
+"\u029E" => "k"
+
+# ᶄ  [LATIN SMALL LETTER K WITH PALATAL HOOK]
+"\u1D84" => "k"
+
+# ḱ  [LATIN SMALL LETTER K WITH ACUTE]
+"\u1E31" => "k"
+
+# ḳ  [LATIN SMALL LETTER K WITH DOT BELOW]
+"\u1E33" => "k"
+
+# ḵ  [LATIN SMALL LETTER K WITH LINE BELOW]
+"\u1E35" => "k"
+
+# ⓚ  [CIRCLED LATIN SMALL LETTER K]
+"\u24DA" => "k"
+
+# ⱪ  [LATIN SMALL LETTER K WITH DESCENDER]
+"\u2C6A" => "k"
+
+# ꝁ  [LATIN SMALL LETTER K WITH STROKE]
+"\uA741" => "k"
+
+# ꝃ  [LATIN SMALL LETTER K WITH DIAGONAL STROKE]
+"\uA743" => "k"
+
+# ꝅ  [LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE]
+"\uA745" => "k"
+
+# k  [FULLWIDTH LATIN SMALL LETTER K]
+"\uFF4B" => "k"
+
+# ⒦  [PARENTHESIZED LATIN SMALL LETTER K]
+"\u24A6" => "(k)"
+
+# Ĺ  [LATIN CAPITAL LETTER L WITH ACUTE]
+"\u0139" => "L"
+
+# Ļ  [LATIN CAPITAL LETTER L WITH CEDILLA]
+"\u013B" => "L"
+
+# Ľ  [LATIN CAPITAL LETTER L WITH CARON]
+"\u013D" => "L"
+
+# Ŀ  [LATIN CAPITAL LETTER L WITH MIDDLE DOT]
+"\u013F" => "L"
+
+# Ł  [LATIN CAPITAL LETTER L WITH STROKE]
+"\u0141" => "L"
+
+# Ƚ  [LATIN CAPITAL LETTER L WITH BAR]
+"\u023D" => "L"
+
+# ʟ  [LATIN LETTER SMALL CAPITAL L]
+"\u029F" => "L"
+
+# ᴌ  [LATIN LETTER SMALL CAPITAL L WITH STROKE]
+"\u1D0C" => "L"
+
+# Ḷ  [LATIN CAPITAL LETTER L WITH DOT BELOW]
+"\u1E36" => "L"
+
+# Ḹ  [LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON]
+"\u1E38" => "L"
+
+# Ḻ  [LATIN CAPITAL LETTER L WITH LINE BELOW]
+"\u1E3A" => "L"
+
+# Ḽ  [LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW]
+"\u1E3C" => "L"
+
+# Ⓛ  [CIRCLED LATIN CAPITAL LETTER L]
+"\u24C1" => "L"
+
+# Ⱡ  [LATIN CAPITAL LETTER L WITH DOUBLE BAR]
+"\u2C60" => "L"
+
+# Ɫ  [LATIN CAPITAL LETTER L WITH MIDDLE TILDE]
+"\u2C62" => "L"
+
+# Ꝇ  [LATIN CAPITAL LETTER BROKEN L]
+"\uA746" => "L"
+
+# Ꝉ  [LATIN CAPITAL LETTER L WITH HIGH STROKE]
+"\uA748" => "L"
+
+# Ꞁ  [LATIN CAPITAL LETTER TURNED L]
+"\uA780" => "L"
+
+# L  [FULLWIDTH LATIN CAPITAL LETTER L]
+"\uFF2C" => "L"
+
+# ĺ  [LATIN SMALL LETTER L WITH ACUTE]
+"\u013A" => "l"
+
+# ļ  [LATIN SMALL LETTER L WITH CEDILLA]
+"\u013C" => "l"
+
+# ľ  [LATIN SMALL LETTER L WITH CARON]
+"\u013E" => "l"
+
+# ŀ  [LATIN SMALL LETTER L WITH MIDDLE DOT]
+"\u0140" => "l"
+
+# ł  [LATIN SMALL LETTER L WITH STROKE]
+"\u0142" => "l"
+
+# ƚ  [LATIN SMALL LETTER L WITH BAR]
+"\u019A" => "l"
+
+# ȴ  [LATIN SMALL LETTER L WITH CURL]
+"\u0234" => "l"
+
+# ɫ  [LATIN SMALL LETTER L WITH MIDDLE TILDE]
+"\u026B" => "l"
+
+# ɬ  [LATIN SMALL LETTER L WITH BELT]
+"\u026C" => "l"
+
+# ɭ  [LATIN SMALL LETTER L WITH RETROFLEX HOOK]
+"\u026D" => "l"
+
+# ᶅ  [LATIN SMALL LETTER L WITH PALATAL HOOK]
+"\u1D85" => "l"
+
+# ḷ  [LATIN SMALL LETTER L WITH DOT BELOW]
+"\u1E37" => "l"
+
+# ḹ  [LATIN SMALL LETTER L WITH DOT BELOW AND MACRON]
+"\u1E39" => "l"
+
+# ḻ  [LATIN SMALL LETTER L WITH LINE BELOW]
+"\u1E3B" => "l"
+
+# ḽ  [LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW]
+"\u1E3D" => "l"
+
+# ⓛ  [CIRCLED LATIN SMALL LETTER L]
+"\u24DB" => "l"
+
+# ⱡ  [LATIN SMALL LETTER L WITH DOUBLE BAR]
+"\u2C61" => "l"
+
+# ꝇ  [LATIN SMALL LETTER BROKEN L]
+"\uA747" => "l"
+
+# ꝉ  [LATIN SMALL LETTER L WITH HIGH STROKE]
+"\uA749" => "l"
+
+# ꞁ  [LATIN SMALL LETTER TURNED L]
+"\uA781" => "l"
+
+# l  [FULLWIDTH LATIN SMALL LETTER L]
+"\uFF4C" => "l"
+
+# LJ  [LATIN CAPITAL LETTER LJ]
+"\u01C7" => "LJ"
+
+# Ỻ  [LATIN CAPITAL LETTER MIDDLE-WELSH LL]
+"\u1EFA" => "LL"
+
+# Lj  [LATIN CAPITAL LETTER L WITH SMALL LETTER J]
+"\u01C8" => "Lj"
+
+# ⒧  [PARENTHESIZED LATIN SMALL LETTER L]
+"\u24A7" => "(l)"
+
+# lj  [LATIN SMALL LETTER LJ]
+"\u01C9" => "lj"
+
+# ỻ  [LATIN SMALL LETTER MIDDLE-WELSH LL]
+"\u1EFB" => "ll"
+
+# ʪ  [LATIN SMALL LETTER LS DIGRAPH]
+"\u02AA" => "ls"
+
+# ʫ  [LATIN SMALL LETTER LZ DIGRAPH]
+"\u02AB" => "lz"
+
+# Ɯ  [LATIN CAPITAL LETTER TURNED M]
+"\u019C" => "M"
+
+# ᴍ  [LATIN LETTER SMALL CAPITAL M]
+"\u1D0D" => "M"
+
+# Ḿ  [LATIN CAPITAL LETTER M WITH ACUTE]
+"\u1E3E" => "M"
+
+# Ṁ  [LATIN CAPITAL LETTER M WITH DOT ABOVE]
+"\u1E40" => "M"
+
+# Ṃ  [LATIN CAPITAL LETTER M WITH DOT BELOW]
+"\u1E42" => "M"
+
+# Ⓜ  [CIRCLED LATIN CAPITAL LETTER M]
+"\u24C2" => "M"
+
+# Ɱ  [LATIN CAPITAL LETTER M WITH HOOK]
+"\u2C6E" => "M"
+
+# ꟽ  [LATIN EPIGRAPHIC LETTER INVERTED M]
+"\uA7FD" => "M"
+
+# ꟿ  [LATIN EPIGRAPHIC LETTER ARCHAIC M]
+"\uA7FF" => "M"
+
+# M  [FULLWIDTH LATIN CAPITAL LETTER M]
+"\uFF2D" => "M"
+
+# ɯ  [LATIN SMALL LETTER TURNED M]
+"\u026F" => "m"
+
+# ɰ  [LATIN SMALL LETTER TURNED M WITH LONG LEG]
+"\u0270" => "m"
+
+# ɱ  [LATIN SMALL LETTER M WITH HOOK]
+"\u0271" => "m"
+
+# ᵯ  [LATIN SMALL LETTER M WITH MIDDLE TILDE]
+"\u1D6F" => "m"
+
+# ᶆ  [LATIN SMALL LETTER M WITH PALATAL HOOK]
+"\u1D86" => "m"
+
+# ḿ  [LATIN SMALL LETTER M WITH ACUTE]
+"\u1E3F" => "m"
+
+# ṁ  [LATIN SMALL LETTER M WITH DOT ABOVE]
+"\u1E41" => "m"
+
+# ṃ  [LATIN SMALL LETTER M WITH DOT BELOW]
+"\u1E43" => "m"
+
+# ⓜ  [CIRCLED LATIN SMALL LETTER M]
+"\u24DC" => "m"
+
+# m  [FULLWIDTH LATIN SMALL LETTER M]
+"\uFF4D" => "m"
+
+# ⒨  [PARENTHESIZED LATIN SMALL LETTER M]
+"\u24A8" => "(m)"
+
+# Ñ  [LATIN CAPITAL LETTER N WITH TILDE]
+"\u00D1" => "N"
+
+# Ń  [LATIN CAPITAL LETTER N WITH ACUTE]
+"\u0143" => "N"
+
+# Ņ  [LATIN CAPITAL LETTER N WITH CEDILLA]
+"\u0145" => "N"
+
+# Ň  [LATIN CAPITAL LETTER N WITH CARON]
+"\u0147" => "N"
+
+# Ŋ  http://en.wikipedia.org/wiki/Eng_(letter)  [LATIN CAPITAL LETTER ENG]
+"\u014A" => "N"
+
+# Ɲ  [LATIN CAPITAL LETTER N WITH LEFT HOOK]
+"\u019D" => "N"
+
+# Ǹ  [LATIN CAPITAL LETTER N WITH GRAVE]
+"\u01F8" => "N"
+
+# Ƞ  [LATIN CAPITAL LETTER N WITH LONG RIGHT LEG]
+"\u0220" => "N"
+
+# ɴ  [LATIN LETTER SMALL CAPITAL N]
+"\u0274" => "N"
+
+# ᴎ  [LATIN LETTER SMALL CAPITAL REVERSED N]
+"\u1D0E" => "N"
+
+# Ṅ  [LATIN CAPITAL LETTER N WITH DOT ABOVE]
+"\u1E44" => "N"
+
+# Ṇ  [LATIN CAPITAL LETTER N WITH DOT BELOW]
+"\u1E46" => "N"
+
+# Ṉ  [LATIN CAPITAL LETTER N WITH LINE BELOW]
+"\u1E48" => "N"
+
+# Ṋ  [LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW]
+"\u1E4A" => "N"
+
+# Ⓝ  [CIRCLED LATIN CAPITAL LETTER N]
+"\u24C3" => "N"
+
+# N  [FULLWIDTH LATIN CAPITAL LETTER N]
+"\uFF2E" => "N"
+
+# ñ  [LATIN SMALL LETTER N WITH TILDE]
+"\u00F1" => "n"
+
+# ń  [LATIN SMALL LETTER N WITH ACUTE]
+"\u0144" => "n"
+
+# ņ  [LATIN SMALL LETTER N WITH CEDILLA]
+"\u0146" => "n"
+
+# ň  [LATIN SMALL LETTER N WITH CARON]
+"\u0148" => "n"
+
+# ʼn  [LATIN SMALL LETTER N PRECEDED BY APOSTROPHE]
+"\u0149" => "n"
+
+# ŋ  http://en.wikipedia.org/wiki/Eng_(letter)  [LATIN SMALL LETTER ENG]
+"\u014B" => "n"
+
+# ƞ  [LATIN SMALL LETTER N WITH LONG RIGHT LEG]
+"\u019E" => "n"
+
+# ǹ  [LATIN SMALL LETTER N WITH GRAVE]
+"\u01F9" => "n"
+
+# ȵ  [LATIN SMALL LETTER N WITH CURL]
+"\u0235" => "n"
+
+# ɲ  [LATIN SMALL LETTER N WITH LEFT HOOK]
+"\u0272" => "n"
+
+# ɳ  [LATIN SMALL LETTER N WITH RETROFLEX HOOK]
+"\u0273" => "n"
+
+# ᵰ  [LATIN SMALL LETTER N WITH MIDDLE TILDE]
+"\u1D70" => "n"
+
+# ᶇ  [LATIN SMALL LETTER N WITH PALATAL HOOK]
+"\u1D87" => "n"
+
+# ṅ  [LATIN SMALL LETTER N WITH DOT ABOVE]
+"\u1E45" => "n"
+
+# ṇ  [LATIN SMALL LETTER N WITH DOT BELOW]
+"\u1E47" => "n"
+
+# ṉ  [LATIN SMALL LETTER N WITH LINE BELOW]
+"\u1E49" => "n"
+
+# ṋ  [LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW]
+"\u1E4B" => "n"
+
+# ⁿ  [SUPERSCRIPT LATIN SMALL LETTER N]
+"\u207F" => "n"
+
+# ⓝ  [CIRCLED LATIN SMALL LETTER N]
+"\u24DD" => "n"
+
+# n  [FULLWIDTH LATIN SMALL LETTER N]
+"\uFF4E" => "n"
+
+# NJ  [LATIN CAPITAL LETTER NJ]
+"\u01CA" => "NJ"
+
+# Nj  [LATIN CAPITAL LETTER N WITH SMALL LETTER J]
+"\u01CB" => "Nj"
+
+# ⒩  [PARENTHESIZED LATIN SMALL LETTER N]
+"\u24A9" => "(n)"
+
+# nj  [LATIN SMALL LETTER NJ]
+"\u01CC" => "nj"
+
+# Ò  [LATIN CAPITAL LETTER O WITH GRAVE]
+"\u00D2" => "O"
+
+# Ó  [LATIN CAPITAL LETTER O WITH ACUTE]
+"\u00D3" => "O"
+
+# Ô  [LATIN CAPITAL LETTER O WITH CIRCUMFLEX]
+"\u00D4" => "O"
+
+# Õ  [LATIN CAPITAL LETTER O WITH TILDE]
+"\u00D5" => "O"
+
+# Ö  [LATIN CAPITAL LETTER O WITH DIAERESIS]
+"\u00D6" => "O"
+
+# Ø  [LATIN CAPITAL LETTER O WITH STROKE]
+"\u00D8" => "O"
+
+# Ō  [LATIN CAPITAL LETTER O WITH MACRON]
+"\u014C" => "O"
+
+# Ŏ  [LATIN CAPITAL LETTER O WITH BREVE]
+"\u014E" => "O"
+
+# Ő  [LATIN CAPITAL LETTER O WITH DOUBLE ACUTE]
+"\u0150" => "O"
+
+# Ɔ  [LATIN CAPITAL LETTER OPEN O]
+"\u0186" => "O"
+
+# Ɵ  [LATIN CAPITAL LETTER O WITH MIDDLE TILDE]
+"\u019F" => "O"
+
+# Ơ  [LATIN CAPITAL LETTER O WITH HORN]
+"\u01A0" => "O"
+
+# Ǒ  [LATIN CAPITAL LETTER O WITH CARON]
+"\u01D1" => "O"
+
+# Ǫ  [LATIN CAPITAL LETTER O WITH OGONEK]
+"\u01EA" => "O"
+
+# Ǭ  [LATIN CAPITAL LETTER O WITH OGONEK AND MACRON]
+"\u01EC" => "O"
+
+# Ǿ  [LATIN CAPITAL LETTER O WITH STROKE AND ACUTE]
+"\u01FE" => "O"
+
+# Ȍ  [LATIN CAPITAL LETTER O WITH DOUBLE GRAVE]
+"\u020C" => "O"
+
+# Ȏ  [LATIN CAPITAL LETTER O WITH INVERTED BREVE]
+"\u020E" => "O"
+
+# Ȫ  [LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON]
+"\u022A" => "O"
+
+# Ȭ  [LATIN CAPITAL LETTER O WITH TILDE AND MACRON]
+"\u022C" => "O"
+
+# Ȯ  [LATIN CAPITAL LETTER O WITH DOT ABOVE]
+"\u022E" => "O"
+
+# Ȱ  [LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON]
+"\u0230" => "O"
+
+# ᴏ  [LATIN LETTER SMALL CAPITAL O]
+"\u1D0F" => "O"
+
+# ᴐ  [LATIN LETTER SMALL CAPITAL OPEN O]
+"\u1D10" => "O"
+
+# Ṍ  [LATIN CAPITAL LETTER O WITH TILDE AND ACUTE]
+"\u1E4C" => "O"
+
+# Ṏ  [LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS]
+"\u1E4E" => "O"
+
+# Ṑ  [LATIN CAPITAL LETTER O WITH MACRON AND GRAVE]
+"\u1E50" => "O"
+
+# Ṓ  [LATIN CAPITAL LETTER O WITH MACRON AND ACUTE]
+"\u1E52" => "O"
+
+# Ọ  [LATIN CAPITAL LETTER O WITH DOT BELOW]
+"\u1ECC" => "O"
+
+# Ỏ  [LATIN CAPITAL LETTER O WITH HOOK ABOVE]
+"\u1ECE" => "O"
+
+# Ố  [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE]
+"\u1ED0" => "O"
+
+# Ồ  [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE]
+"\u1ED2" => "O"
+
+# Ổ  [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE]
+"\u1ED4" => "O"
+
+# Ỗ  [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE]
+"\u1ED6" => "O"
+
+# Ộ  [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW]
+"\u1ED8" => "O"
+
+# Ớ  [LATIN CAPITAL LETTER O WITH HORN AND ACUTE]
+"\u1EDA" => "O"
+
+# Ờ  [LATIN CAPITAL LETTER O WITH HORN AND GRAVE]
+"\u1EDC" => "O"
+
+# Ở  [LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE]
+"\u1EDE" => "O"
+
+# Ỡ  [LATIN CAPITAL LETTER O WITH HORN AND TILDE]
+"\u1EE0" => "O"
+
+# Ợ  [LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW]
+"\u1EE2" => "O"
+
+# Ⓞ  [CIRCLED LATIN CAPITAL LETTER O]
+"\u24C4" => "O"
+
+# Ꝋ  [LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY]
+"\uA74A" => "O"
+
+# Ꝍ  [LATIN CAPITAL LETTER O WITH LOOP]
+"\uA74C" => "O"
+
+# O  [FULLWIDTH LATIN CAPITAL LETTER O]
+"\uFF2F" => "O"
+
+# ò  [LATIN SMALL LETTER O WITH GRAVE]
+"\u00F2" => "o"
+
+# ó  [LATIN SMALL LETTER O WITH ACUTE]
+"\u00F3" => "o"
+
+# ô  [LATIN SMALL LETTER O WITH CIRCUMFLEX]
+"\u00F4" => "o"
+
+# õ  [LATIN SMALL LETTER O WITH TILDE]
+"\u00F5" => "o"
+
+# ö  [LATIN SMALL LETTER O WITH DIAERESIS]
+"\u00F6" => "o"
+
+# ø  [LATIN SMALL LETTER O WITH STROKE]
+"\u00F8" => "o"
+
+# ō  [LATIN SMALL LETTER O WITH MACRON]
+"\u014D" => "o"
+
+# ŏ  [LATIN SMALL LETTER O WITH BREVE]
+"\u014F" => "o"
+
+# ő  [LATIN SMALL LETTER O WITH DOUBLE ACUTE]
+"\u0151" => "o"
+
+# ơ  [LATIN SMALL LETTER O WITH HORN]
+"\u01A1" => "o"
+
+# ǒ  [LATIN SMALL LETTER O WITH CARON]
+"\u01D2" => "o"
+
+# ǫ  [LATIN SMALL LETTER O WITH OGONEK]
+"\u01EB" => "o"
+
+# ǭ  [LATIN SMALL LETTER O WITH OGONEK AND MACRON]
+"\u01ED" => "o"
+
+# ǿ  [LATIN SMALL LETTER O WITH STROKE AND ACUTE]
+"\u01FF" => "o"
+
+# ȍ  [LATIN SMALL LETTER O WITH DOUBLE GRAVE]
+"\u020D" => "o"
+
+# ȏ  [LATIN SMALL LETTER O WITH INVERTED BREVE]
+"\u020F" => "o"
+
+# ȫ  [LATIN SMALL LETTER O WITH DIAERESIS AND MACRON]
+"\u022B" => "o"
+
+# ȭ  [LATIN SMALL LETTER O WITH TILDE AND MACRON]
+"\u022D" => "o"
+
+# ȯ  [LATIN SMALL LETTER O WITH DOT ABOVE]
+"\u022F" => "o"
+
+# ȱ  [LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON]
+"\u0231" => "o"
+
+# ɔ  [LATIN SMALL LETTER OPEN O]
+"\u0254" => "o"
+
+# ɵ  [LATIN SMALL LETTER BARRED O]
+"\u0275" => "o"
+
+# ᴖ  [LATIN SMALL LETTER TOP HALF O]
+"\u1D16" => "o"
+
+# ᴗ  [LATIN SMALL LETTER BOTTOM HALF O]
+"\u1D17" => "o"
+
+# ᶗ  [LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK]
+"\u1D97" => "o"
+
+# ṍ  [LATIN SMALL LETTER O WITH TILDE AND ACUTE]
+"\u1E4D" => "o"
+
+# ṏ  [LATIN SMALL LETTER O WITH TILDE AND DIAERESIS]
+"\u1E4F" => "o"
+
+# ṑ  [LATIN SMALL LETTER O WITH MACRON AND GRAVE]
+"\u1E51" => "o"
+
+# ṓ  [LATIN SMALL LETTER O WITH MACRON AND ACUTE]
+"\u1E53" => "o"
+
+# ọ  [LATIN SMALL LETTER O WITH DOT BELOW]
+"\u1ECD" => "o"
+
+# ỏ  [LATIN SMALL LETTER O WITH HOOK ABOVE]
+"\u1ECF" => "o"
+
+# ố  [LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE]
+"\u1ED1" => "o"
+
+# ồ  [LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE]
+"\u1ED3" => "o"
+
+# ổ  [LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE]
+"\u1ED5" => "o"
+
+# ỗ  [LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE]
+"\u1ED7" => "o"
+
+# ộ  [LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW]
+"\u1ED9" => "o"
+
+# ớ  [LATIN SMALL LETTER O WITH HORN AND ACUTE]
+"\u1EDB" => "o"
+
+# ờ  [LATIN SMALL LETTER O WITH HORN AND GRAVE]
+"\u1EDD" => "o"
+
+# ở  [LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE]
+"\u1EDF" => "o"
+
+# ỡ  [LATIN SMALL LETTER O WITH HORN AND TILDE]
+"\u1EE1" => "o"
+
+# ợ  [LATIN SMALL LETTER O WITH HORN AND DOT BELOW]
+"\u1EE3" => "o"
+
+# ₒ  [LATIN SUBSCRIPT SMALL LETTER O]
+"\u2092" => "o"
+
+# ⓞ  [CIRCLED LATIN SMALL LETTER O]
+"\u24DE" => "o"
+
+# ⱺ  [LATIN SMALL LETTER O WITH LOW RING INSIDE]
+"\u2C7A" => "o"
+
+# ꝋ  [LATIN SMALL LETTER O WITH LONG STROKE OVERLAY]
+"\uA74B" => "o"
+
+# ꝍ  [LATIN SMALL LETTER O WITH LOOP]
+"\uA74D" => "o"
+
+# o  [FULLWIDTH LATIN SMALL LETTER O]
+"\uFF4F" => "o"
+
+# Π [LATIN CAPITAL LIGATURE OE]
+"\u0152" => "OE"
+
+# ɶ  [LATIN LETTER SMALL CAPITAL OE]
+"\u0276" => "OE"
+
+# Ꝏ  [LATIN CAPITAL LETTER OO]
+"\uA74E" => "OO"
+
+# Ȣ  http://en.wikipedia.org/wiki/OU  [LATIN CAPITAL LETTER OU]
+"\u0222" => "OU"
+
+# ᴕ  [LATIN LETTER SMALL CAPITAL OU]
+"\u1D15" => "OU"
+
+# ⒪  [PARENTHESIZED LATIN SMALL LETTER O]
+"\u24AA" => "(o)"
+
+# œ  [LATIN SMALL LIGATURE OE]
+"\u0153" => "oe"
+
+# ᴔ  [LATIN SMALL LETTER TURNED OE]
+"\u1D14" => "oe"
+
+# ꝏ  [LATIN SMALL LETTER OO]
+"\uA74F" => "oo"
+
+# ȣ  http://en.wikipedia.org/wiki/OU  [LATIN SMALL LETTER OU]
+"\u0223" => "ou"
+
+# Ƥ  [LATIN CAPITAL LETTER P WITH HOOK]
+"\u01A4" => "P"
+
+# ᴘ  [LATIN LETTER SMALL CAPITAL P]
+"\u1D18" => "P"
+
+# Ṕ  [LATIN CAPITAL LETTER P WITH ACUTE]
+"\u1E54" => "P"
+
+# Ṗ  [LATIN CAPITAL LETTER P WITH DOT ABOVE]
+"\u1E56" => "P"
+
+# Ⓟ  [CIRCLED LATIN CAPITAL LETTER P]
+"\u24C5" => "P"
+
+# Ᵽ  [LATIN CAPITAL LETTER P WITH STROKE]
+"\u2C63" => "P"
+
+# Ꝑ  [LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER]
+"\uA750" => "P"
+
+# Ꝓ  [LATIN CAPITAL LETTER P WITH FLOURISH]
+"\uA752" => "P"
+
+# Ꝕ  [LATIN CAPITAL LETTER P WITH SQUIRREL TAIL]
+"\uA754" => "P"
+
+# P  [FULLWIDTH LATIN CAPITAL LETTER P]
+"\uFF30" => "P"
+
+# ƥ  [LATIN SMALL LETTER P WITH HOOK]
+"\u01A5" => "p"
+
+# ᵱ  [LATIN SMALL LETTER P WITH MIDDLE TILDE]
+"\u1D71" => "p"
+
+# ᵽ  [LATIN SMALL LETTER P WITH STROKE]
+"\u1D7D" => "p"
+
+# ᶈ  [LATIN SMALL LETTER P WITH PALATAL HOOK]
+"\u1D88" => "p"
+
+# ṕ  [LATIN SMALL LETTER P WITH ACUTE]
+"\u1E55" => "p"
+
+# ṗ  [LATIN SMALL LETTER P WITH DOT ABOVE]
+"\u1E57" => "p"
+
+# ⓟ  [CIRCLED LATIN SMALL LETTER P]
+"\u24DF" => "p"
+
+# ꝑ  [LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER]
+"\uA751" => "p"
+
+# ꝓ  [LATIN SMALL LETTER P WITH FLOURISH]
+"\uA753" => "p"
+
+# ꝕ  [LATIN SMALL LETTER P WITH SQUIRREL TAIL]
+"\uA755" => "p"
+
+# ꟼ  [LATIN EPIGRAPHIC LETTER REVERSED P]
+"\uA7FC" => "p"
+
+# p  [FULLWIDTH LATIN SMALL LETTER P]
+"\uFF50" => "p"
+
+# ⒫  [PARENTHESIZED LATIN SMALL LETTER P]
+"\u24AB" => "(p)"
+
+# Ɋ  [LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL]
+"\u024A" => "Q"
+
+# Ⓠ  [CIRCLED LATIN CAPITAL LETTER Q]
+"\u24C6" => "Q"
+
+# Ꝗ  [LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER]
+"\uA756" => "Q"
+
+# Ꝙ  [LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE]
+"\uA758" => "Q"
+
+# Q  [FULLWIDTH LATIN CAPITAL LETTER Q]
+"\uFF31" => "Q"
+
+# ĸ  http://en.wikipedia.org/wiki/Kra_(letter)  [LATIN SMALL LETTER KRA]
+"\u0138" => "q"
+
+# ɋ  [LATIN SMALL LETTER Q WITH HOOK TAIL]
+"\u024B" => "q"
+
+# ʠ  [LATIN SMALL LETTER Q WITH HOOK]
+"\u02A0" => "q"
+
+# ⓠ  [CIRCLED LATIN SMALL LETTER Q]
+"\u24E0" => "q"
+
+# ꝗ  [LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER]
+"\uA757" => "q"
+
+# ꝙ  [LATIN SMALL LETTER Q WITH DIAGONAL STROKE]
+"\uA759" => "q"
+
+# q  [FULLWIDTH LATIN SMALL LETTER Q]
+"\uFF51" => "q"
+
+# ⒬  [PARENTHESIZED LATIN SMALL LETTER Q]
+"\u24AC" => "(q)"
+
+# ȹ  [LATIN SMALL LETTER QP DIGRAPH]
+"\u0239" => "qp"
+
+# Ŕ  [LATIN CAPITAL LETTER R WITH ACUTE]
+"\u0154" => "R"
+
+# Ŗ  [LATIN CAPITAL LETTER R WITH CEDILLA]
+"\u0156" => "R"
+
+# Ř  [LATIN CAPITAL LETTER R WITH CARON]
+"\u0158" => "R"
+
+# Ȓ  [LATIN CAPITAL LETTER R WITH DOUBLE GRAVE]
+"\u0210" => "R"
+
+# Ȓ  [LATIN CAPITAL LETTER R WITH INVERTED BREVE]
+"\u0212" => "R"
+
+# Ɍ  [LATIN CAPITAL LETTER R WITH STROKE]
+"\u024C" => "R"
+
+# ʀ  [LATIN LETTER SMALL CAPITAL R]
+"\u0280" => "R"
+
+# ʁ  [LATIN LETTER SMALL CAPITAL INVERTED R]
+"\u0281" => "R"
+
+# ᴙ  [LATIN LETTER SMALL CAPITAL REVERSED R]
+"\u1D19" => "R"
+
+# ᴚ  [LATIN LETTER SMALL CAPITAL TURNED R]
+"\u1D1A" => "R"
+
+# Ṙ  [LATIN CAPITAL LETTER R WITH DOT ABOVE]
+"\u1E58" => "R"
+
+# Ṛ  [LATIN CAPITAL LETTER R WITH DOT BELOW]
+"\u1E5A" => "R"
+
+# Ṝ  [LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON]
+"\u1E5C" => "R"
+
+# Ṟ  [LATIN CAPITAL LETTER R WITH LINE BELOW]
+"\u1E5E" => "R"
+
+# Ⓡ  [CIRCLED LATIN CAPITAL LETTER R]
+"\u24C7" => "R"
+
+# Ɽ  [LATIN CAPITAL LETTER R WITH TAIL]
+"\u2C64" => "R"
+
+# Ꝛ  [LATIN CAPITAL LETTER R ROTUNDA]
+"\uA75A" => "R"
+
+# Ꞃ  [LATIN CAPITAL LETTER INSULAR R]
+"\uA782" => "R"
+
+# R  [FULLWIDTH LATIN CAPITAL LETTER R]
+"\uFF32" => "R"
+
+# ŕ  [LATIN SMALL LETTER R WITH ACUTE]
+"\u0155" => "r"
+
+# ŗ  [LATIN SMALL LETTER R WITH CEDILLA]
+"\u0157" => "r"
+
+# ř  [LATIN SMALL LETTER R WITH CARON]
+"\u0159" => "r"
+
+# ȑ  [LATIN SMALL LETTER R WITH DOUBLE GRAVE]
+"\u0211" => "r"
+
+# ȓ  [LATIN SMALL LETTER R WITH INVERTED BREVE]
+"\u0213" => "r"
+
+# ɍ  [LATIN SMALL LETTER R WITH STROKE]
+"\u024D" => "r"
+
+# ɼ  [LATIN SMALL LETTER R WITH LONG LEG]
+"\u027C" => "r"
+
+# ɽ  [LATIN SMALL LETTER R WITH TAIL]
+"\u027D" => "r"
+
+# ɾ  [LATIN SMALL LETTER R WITH FISHHOOK]
+"\u027E" => "r"
+
+# ɿ  [LATIN SMALL LETTER REVERSED R WITH FISHHOOK]
+"\u027F" => "r"
+
+# ᵣ  [LATIN SUBSCRIPT SMALL LETTER R]
+"\u1D63" => "r"
+
+# ᵲ  [LATIN SMALL LETTER R WITH MIDDLE TILDE]
+"\u1D72" => "r"
+
+# ᵳ  [LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE]
+"\u1D73" => "r"
+
+# ᶉ  [LATIN SMALL LETTER R WITH PALATAL HOOK]
+"\u1D89" => "r"
+
+# ṙ  [LATIN SMALL LETTER R WITH DOT ABOVE]
+"\u1E59" => "r"
+
+# ṛ  [LATIN SMALL LETTER R WITH DOT BELOW]
+"\u1E5B" => "r"
+
+# ṝ  [LATIN SMALL LETTER R WITH DOT BELOW AND MACRON]
+"\u1E5D" => "r"
+
+# ṟ  [LATIN SMALL LETTER R WITH LINE BELOW]
+"\u1E5F" => "r"
+
+# ⓡ  [CIRCLED LATIN SMALL LETTER R]
+"\u24E1" => "r"
+
+# ꝛ  [LATIN SMALL LETTER R ROTUNDA]
+"\uA75B" => "r"
+
+# ꞃ  [LATIN SMALL LETTER INSULAR R]
+"\uA783" => "r"
+
+# r  [FULLWIDTH LATIN SMALL LETTER R]
+"\uFF52" => "r"
+
+# ⒭  [PARENTHESIZED LATIN SMALL LETTER R]
+"\u24AD" => "(r)"
+
+# Ś  [LATIN CAPITAL LETTER S WITH ACUTE]
+"\u015A" => "S"
+
+# Ŝ  [LATIN CAPITAL LETTER S WITH CIRCUMFLEX]
+"\u015C" => "S"
+
+# Ş  [LATIN CAPITAL LETTER S WITH CEDILLA]
+"\u015E" => "S"
+
+# Š  [LATIN CAPITAL LETTER S WITH CARON]
+"\u0160" => "S"
+
+# Ș  [LATIN CAPITAL LETTER S WITH COMMA BELOW]
+"\u0218" => "S"
+
+# Ṡ  [LATIN CAPITAL LETTER S WITH DOT ABOVE]
+"\u1E60" => "S"
+
+# Ṣ  [LATIN CAPITAL LETTER S WITH DOT BELOW]
+"\u1E62" => "S"
+
+# Ṥ  [LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE]
+"\u1E64" => "S"
+
+# Ṧ  [LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE]
+"\u1E66" => "S"
+
+# Ṩ  [LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE]
+"\u1E68" => "S"
+
+# Ⓢ  [CIRCLED LATIN CAPITAL LETTER S]
+"\u24C8" => "S"
+
+# ꜱ  [LATIN LETTER SMALL CAPITAL S]
+"\uA731" => "S"
+
+# ꞅ  [LATIN SMALL LETTER INSULAR S]
+"\uA785" => "S"
+
+# S  [FULLWIDTH LATIN CAPITAL LETTER S]
+"\uFF33" => "S"
+
+# ś  [LATIN SMALL LETTER S WITH ACUTE]
+"\u015B" => "s"
+
+# ŝ  [LATIN SMALL LETTER S WITH CIRCUMFLEX]
+"\u015D" => "s"
+
+# ş  [LATIN SMALL LETTER S WITH CEDILLA]
+"\u015F" => "s"
+
+# š  [LATIN SMALL LETTER S WITH CARON]
+"\u0161" => "s"
+
+# ſ  http://en.wikipedia.org/wiki/Long_S  [LATIN SMALL LETTER LONG S]
+"\u017F" => "s"
+
+# ș  [LATIN SMALL LETTER S WITH COMMA BELOW]
+"\u0219" => "s"
+
+# ȿ  [LATIN SMALL LETTER S WITH SWASH TAIL]
+"\u023F" => "s"
+
+# ʂ  [LATIN SMALL LETTER S WITH HOOK]
+"\u0282" => "s"
+
+# ᵴ  [LATIN SMALL LETTER S WITH MIDDLE TILDE]
+"\u1D74" => "s"
+
+# ᶊ  [LATIN SMALL LETTER S WITH PALATAL HOOK]
+"\u1D8A" => "s"
+
+# ṡ  [LATIN SMALL LETTER S WITH DOT ABOVE]
+"\u1E61" => "s"
+
+# ṣ  [LATIN SMALL LETTER S WITH DOT BELOW]
+"\u1E63" => "s"
+
+# ṥ  [LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE]
+"\u1E65" => "s"
+
+# ṧ  [LATIN SMALL LETTER S WITH CARON AND DOT ABOVE]
+"\u1E67" => "s"
+
+# ṩ  [LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE]
+"\u1E69" => "s"
+
+# ẜ  [LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE]
+"\u1E9C" => "s"
+
+# ẝ  [LATIN SMALL LETTER LONG S WITH HIGH STROKE]
+"\u1E9D" => "s"
+
+# ⓢ  [CIRCLED LATIN SMALL LETTER S]
+"\u24E2" => "s"
+
+# Ꞅ  [LATIN CAPITAL LETTER INSULAR S]
+"\uA784" => "s"
+
+# s  [FULLWIDTH LATIN SMALL LETTER S]
+"\uFF53" => "s"
+
+# ẞ  [LATIN CAPITAL LETTER SHARP S]
+"\u1E9E" => "SS"
+
+# ⒮  [PARENTHESIZED LATIN SMALL LETTER S]
+"\u24AE" => "(s)"
+
+# ß  [LATIN SMALL LETTER SHARP S]
+"\u00DF" => "ss"
+
+# st  [LATIN SMALL LIGATURE ST]
+"\uFB06" => "st"
+
+# Ţ  [LATIN CAPITAL LETTER T WITH CEDILLA]
+"\u0162" => "T"
+
+# Ť  [LATIN CAPITAL LETTER T WITH CARON]
+"\u0164" => "T"
+
+# Ŧ  [LATIN CAPITAL LETTER T WITH STROKE]
+"\u0166" => "T"
+
+# Ƭ  [LATIN CAPITAL LETTER T WITH HOOK]
+"\u01AC" => "T"
+
+# Ʈ  [LATIN CAPITAL LETTER T WITH RETROFLEX HOOK]
+"\u01AE" => "T"
+
+# Ț  [LATIN CAPITAL LETTER T WITH COMMA BELOW]
+"\u021A" => "T"
+
+# Ⱦ  [LATIN CAPITAL LETTER T WITH DIAGONAL STROKE]
+"\u023E" => "T"
+
+# ᴛ  [LATIN LETTER SMALL CAPITAL T]
+"\u1D1B" => "T"
+
+# Ṫ  [LATIN CAPITAL LETTER T WITH DOT ABOVE]
+"\u1E6A" => "T"
+
+# Ṭ  [LATIN CAPITAL LETTER T WITH DOT BELOW]
+"\u1E6C" => "T"
+
+# Ṯ  [LATIN CAPITAL LETTER T WITH LINE BELOW]
+"\u1E6E" => "T"
+
+# Ṱ  [LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW]
+"\u1E70" => "T"
+
+# Ⓣ  [CIRCLED LATIN CAPITAL LETTER T]
+"\u24C9" => "T"
+
+# Ꞇ  [LATIN CAPITAL LETTER INSULAR T]
+"\uA786" => "T"
+
+# T  [FULLWIDTH LATIN CAPITAL LETTER T]
+"\uFF34" => "T"
+
+# ţ  [LATIN SMALL LETTER T WITH CEDILLA]
+"\u0163" => "t"
+
+# ť  [LATIN SMALL LETTER T WITH CARON]
+"\u0165" => "t"
+
+# ŧ  [LATIN SMALL LETTER T WITH STROKE]
+"\u0167" => "t"
+
+# ƫ  [LATIN SMALL LETTER T WITH PALATAL HOOK]
+"\u01AB" => "t"
+
+# ƭ  [LATIN SMALL LETTER T WITH HOOK]
+"\u01AD" => "t"
+
+# ț  [LATIN SMALL LETTER T WITH COMMA BELOW]
+"\u021B" => "t"
+
+# ȶ  [LATIN SMALL LETTER T WITH CURL]
+"\u0236" => "t"
+
+# ʇ  [LATIN SMALL LETTER TURNED T]
+"\u0287" => "t"
+
+# ʈ  [LATIN SMALL LETTER T WITH RETROFLEX HOOK]
+"\u0288" => "t"
+
+# ᵵ  [LATIN SMALL LETTER T WITH MIDDLE TILDE]
+"\u1D75" => "t"
+
+# ṫ  [LATIN SMALL LETTER T WITH DOT ABOVE]
+"\u1E6B" => "t"
+
+# ṭ  [LATIN SMALL LETTER T WITH DOT BELOW]
+"\u1E6D" => "t"
+
+# ṯ  [LATIN SMALL LETTER T WITH LINE BELOW]
+"\u1E6F" => "t"
+
+# ṱ  [LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW]
+"\u1E71" => "t"
+
+# ẗ  [LATIN SMALL LETTER T WITH DIAERESIS]
+"\u1E97" => "t"
+
+# ⓣ  [CIRCLED LATIN SMALL LETTER T]
+"\u24E3" => "t"
+
+# ⱦ  [LATIN SMALL LETTER T WITH DIAGONAL STROKE]
+"\u2C66" => "t"
+
+# t  [FULLWIDTH LATIN SMALL LETTER T]
+"\uFF54" => "t"
+
+# Þ  [LATIN CAPITAL LETTER THORN]
+"\u00DE" => "TH"
+
+# Ꝧ  [LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER]
+"\uA766" => "TH"
+
+# Ꜩ  [LATIN CAPITAL LETTER TZ]
+"\uA728" => "TZ"
+
+# ⒯  [PARENTHESIZED LATIN SMALL LETTER T]
+"\u24AF" => "(t)"
+
+# ʨ  [LATIN SMALL LETTER TC DIGRAPH WITH CURL]
+"\u02A8" => "tc"
+
+# þ  [LATIN SMALL LETTER THORN]
+"\u00FE" => "th"
+
+# ᵺ  [LATIN SMALL LETTER TH WITH STRIKETHROUGH]
+"\u1D7A" => "th"
+
+# ꝧ  [LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER]
+"\uA767" => "th"
+
+# ʦ  [LATIN SMALL LETTER TS DIGRAPH]
+"\u02A6" => "ts"
+
+# ꜩ  [LATIN SMALL LETTER TZ]
+"\uA729" => "tz"
+
+# Ù  [LATIN CAPITAL LETTER U WITH GRAVE]
+"\u00D9" => "U"
+
+# Ú  [LATIN CAPITAL LETTER U WITH ACUTE]
+"\u00DA" => "U"
+
+# Û  [LATIN CAPITAL LETTER U WITH CIRCUMFLEX]
+"\u00DB" => "U"
+
+# Ü  [LATIN CAPITAL LETTER U WITH DIAERESIS]
+"\u00DC" => "U"
+
+# Ũ  [LATIN CAPITAL LETTER U WITH TILDE]
+"\u0168" => "U"
+
+# Ū  [LATIN CAPITAL LETTER U WITH MACRON]
+"\u016A" => "U"
+
+# Ŭ  [LATIN CAPITAL LETTER U WITH BREVE]
+"\u016C" => "U"
+
+# Ů  [LATIN CAPITAL LETTER U WITH RING ABOVE]
+"\u016E" => "U"
+
+# Ű  [LATIN CAPITAL LETTER U WITH DOUBLE ACUTE]
+"\u0170" => "U"
+
+# Ų  [LATIN CAPITAL LETTER U WITH OGONEK]
+"\u0172" => "U"
+
+# Ư  [LATIN CAPITAL LETTER U WITH HORN]
+"\u01AF" => "U"
+
+# Ǔ  [LATIN CAPITAL LETTER U WITH CARON]
+"\u01D3" => "U"
+
+# Ǖ  [LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON]
+"\u01D5" => "U"
+
+# Ǘ  [LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE]
+"\u01D7" => "U"
+
+# Ǚ  [LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON]
+"\u01D9" => "U"
+
+# Ǜ  [LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE]
+"\u01DB" => "U"
+
+# Ȕ  [LATIN CAPITAL LETTER U WITH DOUBLE GRAVE]
+"\u0214" => "U"
+
+# Ȗ  [LATIN CAPITAL LETTER U WITH INVERTED BREVE]
+"\u0216" => "U"
+
+# Ʉ  [LATIN CAPITAL LETTER U BAR]
+"\u0244" => "U"
+
+# ᴜ  [LATIN LETTER SMALL CAPITAL U]
+"\u1D1C" => "U"
+
+# ᵾ  [LATIN SMALL CAPITAL LETTER U WITH STROKE]
+"\u1D7E" => "U"
+
+# Ṳ  [LATIN CAPITAL LETTER U WITH DIAERESIS BELOW]
+"\u1E72" => "U"
+
+# Ṵ  [LATIN CAPITAL LETTER U WITH TILDE BELOW]
+"\u1E74" => "U"
+
+# Ṷ  [LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW]
+"\u1E76" => "U"
+
+# Ṹ  [LATIN CAPITAL LETTER U WITH TILDE AND ACUTE]
+"\u1E78" => "U"
+
+# Ṻ  [LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS]
+"\u1E7A" => "U"
+
+# Ụ  [LATIN CAPITAL LETTER U WITH DOT BELOW]
+"\u1EE4" => "U"
+
+# Ủ  [LATIN CAPITAL LETTER U WITH HOOK ABOVE]
+"\u1EE6" => "U"
+
+# Ứ  [LATIN CAPITAL LETTER U WITH HORN AND ACUTE]
+"\u1EE8" => "U"
+
+# Ừ  [LATIN CAPITAL LETTER U WITH HORN AND GRAVE]
+"\u1EEA" => "U"
+
+# Ử  [LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE]
+"\u1EEC" => "U"
+
+# Ữ  [LATIN CAPITAL LETTER U WITH HORN AND TILDE]
+"\u1EEE" => "U"
+
+# Ự  [LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW]
+"\u1EF0" => "U"
+
+# Ⓤ  [CIRCLED LATIN CAPITAL LETTER U]
+"\u24CA" => "U"
+
+# U  [FULLWIDTH LATIN CAPITAL LETTER U]
+"\uFF35" => "U"
+
+# ù  [LATIN SMALL LETTER U WITH GRAVE]
+"\u00F9" => "u"
+
+# ú  [LATIN SMALL LETTER U WITH ACUTE]
+"\u00FA" => "u"
+
+# û  [LATIN SMALL LETTER U WITH CIRCUMFLEX]
+"\u00FB" => "u"
+
+# ü  [LATIN SMALL LETTER U WITH DIAERESIS]
+"\u00FC" => "u"
+
+# ũ  [LATIN SMALL LETTER U WITH TILDE]
+"\u0169" => "u"
+
+# ū  [LATIN SMALL LETTER U WITH MACRON]
+"\u016B" => "u"
+
+# ŭ  [LATIN SMALL LETTER U WITH BREVE]
+"\u016D" => "u"
+
+# ů  [LATIN SMALL LETTER U WITH RING ABOVE]
+"\u016F" => "u"
+
+# ű  [LATIN SMALL LETTER U WITH DOUBLE ACUTE]
+"\u0171" => "u"
+
+# ų  [LATIN SMALL LETTER U WITH OGONEK]
+"\u0173" => "u"
+
+# ư  [LATIN SMALL LETTER U WITH HORN]
+"\u01B0" => "u"
+
+# ǔ  [LATIN SMALL LETTER U WITH CARON]
+"\u01D4" => "u"
+
+# ǖ  [LATIN SMALL LETTER U WITH DIAERESIS AND MACRON]
+"\u01D6" => "u"
+
+# ǘ  [LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE]
+"\u01D8" => "u"
+
+# ǚ  [LATIN SMALL LETTER U WITH DIAERESIS AND CARON]
+"\u01DA" => "u"
+
+# ǜ  [LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE]
+"\u01DC" => "u"
+
+# ȕ  [LATIN SMALL LETTER U WITH DOUBLE GRAVE]
+"\u0215" => "u"
+
+# ȗ  [LATIN SMALL LETTER U WITH INVERTED BREVE]
+"\u0217" => "u"
+
+# ʉ  [LATIN SMALL LETTER U BAR]
+"\u0289" => "u"
+
+# ᵤ  [LATIN SUBSCRIPT SMALL LETTER U]
+"\u1D64" => "u"
+
+# ᶙ  [LATIN SMALL LETTER U WITH RETROFLEX HOOK]
+"\u1D99" => "u"
+
+# ṳ  [LATIN SMALL LETTER U WITH DIAERESIS BELOW]
+"\u1E73" => "u"
+
+# ṵ  [LATIN SMALL LETTER U WITH TILDE BELOW]
+"\u1E75" => "u"
+
+# ṷ  [LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW]
+"\u1E77" => "u"
+
+# ṹ  [LATIN SMALL LETTER U WITH TILDE AND ACUTE]
+"\u1E79" => "u"
+
+# ṻ  [LATIN SMALL LETTER U WITH MACRON AND DIAERESIS]
+"\u1E7B" => "u"
+
+# ụ  [LATIN SMALL LETTER U WITH DOT BELOW]
+"\u1EE5" => "u"
+
+# ủ  [LATIN SMALL LETTER U WITH HOOK ABOVE]
+"\u1EE7" => "u"
+
+# ứ  [LATIN SMALL LETTER U WITH HORN AND ACUTE]
+"\u1EE9" => "u"
+
+# ừ  [LATIN SMALL LETTER U WITH HORN AND GRAVE]
+"\u1EEB" => "u"
+
+# ử  [LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE]
+"\u1EED" => "u"
+
+# ữ  [LATIN SMALL LETTER U WITH HORN AND TILDE]
+"\u1EEF" => "u"
+
+# ự  [LATIN SMALL LETTER U WITH HORN AND DOT BELOW]
+"\u1EF1" => "u"
+
+# ⓤ  [CIRCLED LATIN SMALL LETTER U]
+"\u24E4" => "u"
+
+# u  [FULLWIDTH LATIN SMALL LETTER U]
+"\uFF55" => "u"
+
+# ⒰  [PARENTHESIZED LATIN SMALL LETTER U]
+"\u24B0" => "(u)"
+
+# ᵫ  [LATIN SMALL LETTER UE]
+"\u1D6B" => "ue"
+
+# Ʋ  [LATIN CAPITAL LETTER V WITH HOOK]
+"\u01B2" => "V"
+
+# Ʌ  [LATIN CAPITAL LETTER TURNED V]
+"\u0245" => "V"
+
+# ᴠ  [LATIN LETTER SMALL CAPITAL V]
+"\u1D20" => "V"
+
+# Ṽ  [LATIN CAPITAL LETTER V WITH TILDE]
+"\u1E7C" => "V"
+
+# Ṿ  [LATIN CAPITAL LETTER V WITH DOT BELOW]
+"\u1E7E" => "V"
+
+# Ỽ  [LATIN CAPITAL LETTER MIDDLE-WELSH V]
+"\u1EFC" => "V"
+
+# Ⓥ  [CIRCLED LATIN CAPITAL LETTER V]
+"\u24CB" => "V"
+
+# Ꝟ  [LATIN CAPITAL LETTER V WITH DIAGONAL STROKE]
+"\uA75E" => "V"
+
+# Ꝩ  [LATIN CAPITAL LETTER VEND]
+"\uA768" => "V"
+
+# V  [FULLWIDTH LATIN CAPITAL LETTER V]
+"\uFF36" => "V"
+
+# ʋ  [LATIN SMALL LETTER V WITH HOOK]
+"\u028B" => "v"
+
+# ʌ  [LATIN SMALL LETTER TURNED V]
+"\u028C" => "v"
+
+# ᵥ  [LATIN SUBSCRIPT SMALL LETTER V]
+"\u1D65" => "v"
+
+# ᶌ  [LATIN SMALL LETTER V WITH PALATAL HOOK]
+"\u1D8C" => "v"
+
+# ṽ  [LATIN SMALL LETTER V WITH TILDE]
+"\u1E7D" => "v"
+
+# ṿ  [LATIN SMALL LETTER V WITH DOT BELOW]
+"\u1E7F" => "v"
+
+# ⓥ  [CIRCLED LATIN SMALL LETTER V]
+"\u24E5" => "v"
+
+# ⱱ  [LATIN SMALL LETTER V WITH RIGHT HOOK]
+"\u2C71" => "v"
+
+# ⱴ  [LATIN SMALL LETTER V WITH CURL]
+"\u2C74" => "v"
+
+# ꝟ  [LATIN SMALL LETTER V WITH DIAGONAL STROKE]
+"\uA75F" => "v"
+
+# v  [FULLWIDTH LATIN SMALL LETTER V]
+"\uFF56" => "v"
+
+# Ꝡ  [LATIN CAPITAL LETTER VY]
+"\uA760" => "VY"
+
+# ⒱  [PARENTHESIZED LATIN SMALL LETTER V]
+"\u24B1" => "(v)"
+
+# ꝡ  [LATIN SMALL LETTER VY]
+"\uA761" => "vy"
+
+# Ŵ  [LATIN CAPITAL LETTER W WITH CIRCUMFLEX]
+"\u0174" => "W"
+
+# Ƿ  http://en.wikipedia.org/wiki/Wynn  [LATIN CAPITAL LETTER WYNN]
+"\u01F7" => "W"
+
+# ᴡ  [LATIN LETTER SMALL CAPITAL W]
+"\u1D21" => "W"
+
+# Ẁ  [LATIN CAPITAL LETTER W WITH GRAVE]
+"\u1E80" => "W"
+
+# Ẃ  [LATIN CAPITAL LETTER W WITH ACUTE]
+"\u1E82" => "W"
+
+# Ẅ  [LATIN CAPITAL LETTER W WITH DIAERESIS]
+"\u1E84" => "W"
+
+# Ẇ  [LATIN CAPITAL LETTER W WITH DOT ABOVE]
+"\u1E86" => "W"
+
+# Ẉ  [LATIN CAPITAL LETTER W WITH DOT BELOW]
+"\u1E88" => "W"
+
+# Ⓦ  [CIRCLED LATIN CAPITAL LETTER W]
+"\u24CC" => "W"
+
+# Ⱳ  [LATIN CAPITAL LETTER W WITH HOOK]
+"\u2C72" => "W"
+
+# W  [FULLWIDTH LATIN CAPITAL LETTER W]
+"\uFF37" => "W"
+
+# ŵ  [LATIN SMALL LETTER W WITH CIRCUMFLEX]
+"\u0175" => "w"
+
+# ƿ  http://en.wikipedia.org/wiki/Wynn  [LATIN LETTER WYNN]
+"\u01BF" => "w"
+
+# ʍ  [LATIN SMALL LETTER TURNED W]
+"\u028D" => "w"
+
+# ẁ  [LATIN SMALL LETTER W WITH GRAVE]
+"\u1E81" => "w"
+
+# ẃ  [LATIN SMALL LETTER W WITH ACUTE]
+"\u1E83" => "w"
+
+# ẅ  [LATIN SMALL LETTER W WITH DIAERESIS]
+"\u1E85" => "w"
+
+# ẇ  [LATIN SMALL LETTER W WITH DOT ABOVE]
+"\u1E87" => "w"
+
+# ẉ  [LATIN SMALL LETTER W WITH DOT BELOW]
+"\u1E89" => "w"
+
+# ẘ  [LATIN SMALL LETTER W WITH RING ABOVE]
+"\u1E98" => "w"
+
+# ⓦ  [CIRCLED LATIN SMALL LETTER W]
+"\u24E6" => "w"
+
+# ⱳ  [LATIN SMALL LETTER W WITH HOOK]
+"\u2C73" => "w"
+
+# w  [FULLWIDTH LATIN SMALL LETTER W]
+"\uFF57" => "w"
+
+# ⒲  [PARENTHESIZED LATIN SMALL LETTER W]
+"\u24B2" => "(w)"
+
+# Ẋ  [LATIN CAPITAL LETTER X WITH DOT ABOVE]
+"\u1E8A" => "X"
+
+# Ẍ  [LATIN CAPITAL LETTER X WITH DIAERESIS]
+"\u1E8C" => "X"
+
+# Ⓧ  [CIRCLED LATIN CAPITAL LETTER X]
+"\u24CD" => "X"
+
+# X  [FULLWIDTH LATIN CAPITAL LETTER X]
+"\uFF38" => "X"
+
+# ᶍ  [LATIN SMALL LETTER X WITH PALATAL HOOK]
+"\u1D8D" => "x"
+
+# ẋ  [LATIN SMALL LETTER X WITH DOT ABOVE]
+"\u1E8B" => "x"
+
+# ẍ  [LATIN SMALL LETTER X WITH DIAERESIS]
+"\u1E8D" => "x"
+
+# ₓ  [LATIN SUBSCRIPT SMALL LETTER X]
+"\u2093" => "x"
+
+# ⓧ  [CIRCLED LATIN SMALL LETTER X]
+"\u24E7" => "x"
+
+# x  [FULLWIDTH LATIN SMALL LETTER X]
+"\uFF58" => "x"
+
+# ⒳  [PARENTHESIZED LATIN SMALL LETTER X]
+"\u24B3" => "(x)"
+
+# Ý  [LATIN CAPITAL LETTER Y WITH ACUTE]
+"\u00DD" => "Y"
+
+# Ŷ  [LATIN CAPITAL LETTER Y WITH CIRCUMFLEX]
+"\u0176" => "Y"
+
+# Ÿ  [LATIN CAPITAL LETTER Y WITH DIAERESIS]
+"\u0178" => "Y"
+
+# Ƴ  [LATIN CAPITAL LETTER Y WITH HOOK]
+"\u01B3" => "Y"
+
+# Ȳ  [LATIN CAPITAL LETTER Y WITH MACRON]
+"\u0232" => "Y"
+
+# Ɏ  [LATIN CAPITAL LETTER Y WITH STROKE]
+"\u024E" => "Y"
+
+# ʏ  [LATIN LETTER SMALL CAPITAL Y]
+"\u028F" => "Y"
+
+# Ẏ  [LATIN CAPITAL LETTER Y WITH DOT ABOVE]
+"\u1E8E" => "Y"
+
+# Ỳ  [LATIN CAPITAL LETTER Y WITH GRAVE]
+"\u1EF2" => "Y"
+
+# Ỵ  [LATIN CAPITAL LETTER Y WITH DOT BELOW]
+"\u1EF4" => "Y"
+
+# Ỷ  [LATIN CAPITAL LETTER Y WITH HOOK ABOVE]
+"\u1EF6" => "Y"
+
+# Ỹ  [LATIN CAPITAL LETTER Y WITH TILDE]
+"\u1EF8" => "Y"
+
+# Ỿ  [LATIN CAPITAL LETTER Y WITH LOOP]
+"\u1EFE" => "Y"
+
+# Ⓨ  [CIRCLED LATIN CAPITAL LETTER Y]
+"\u24CE" => "Y"
+
+# Y  [FULLWIDTH LATIN CAPITAL LETTER Y]
+"\uFF39" => "Y"
+
+# ý  [LATIN SMALL LETTER Y WITH ACUTE]
+"\u00FD" => "y"
+
+# ÿ  [LATIN SMALL LETTER Y WITH DIAERESIS]
+"\u00FF" => "y"
+
+# ŷ  [LATIN SMALL LETTER Y WITH CIRCUMFLEX]
+"\u0177" => "y"
+
+# ƴ  [LATIN SMALL LETTER Y WITH HOOK]
+"\u01B4" => "y"
+
+# ȳ  [LATIN SMALL LETTER Y WITH MACRON]
+"\u0233" => "y"
+
+# ɏ  [LATIN SMALL LETTER Y WITH STROKE]
+"\u024F" => "y"
+
+# ʎ  [LATIN SMALL LETTER TURNED Y]
+"\u028E" => "y"
+
+# ẏ  [LATIN SMALL LETTER Y WITH DOT ABOVE]
+"\u1E8F" => "y"
+
+# ẙ  [LATIN SMALL LETTER Y WITH RING ABOVE]
+"\u1E99" => "y"
+
+# ỳ  [LATIN SMALL LETTER Y WITH GRAVE]
+"\u1EF3" => "y"
+
+# ỵ  [LATIN SMALL LETTER Y WITH DOT BELOW]
+"\u1EF5" => "y"
+
+# ỷ  [LATIN SMALL LETTER Y WITH HOOK ABOVE]
+"\u1EF7" => "y"
+
+# ỹ  [LATIN SMALL LETTER Y WITH TILDE]
+"\u1EF9" => "y"
+
+# ỿ  [LATIN SMALL LETTER Y WITH LOOP]
+"\u1EFF" => "y"
+
+# ⓨ  [CIRCLED LATIN SMALL LETTER Y]
+"\u24E8" => "y"
+
+# y  [FULLWIDTH LATIN SMALL LETTER Y]
+"\uFF59" => "y"
+
+# ⒴  [PARENTHESIZED LATIN SMALL LETTER Y]
+"\u24B4" => "(y)"
+
+# Ź  [LATIN CAPITAL LETTER Z WITH ACUTE]
+"\u0179" => "Z"
+
+# Ż  [LATIN CAPITAL LETTER Z WITH DOT ABOVE]
+"\u017B" => "Z"
+
+# Ž  [LATIN CAPITAL LETTER Z WITH CARON]
+"\u017D" => "Z"
+
+# Ƶ  [LATIN CAPITAL LETTER Z WITH STROKE]
+"\u01B5" => "Z"
+
+# Ȝ  http://en.wikipedia.org/wiki/Yogh  [LATIN CAPITAL LETTER YOGH]
+"\u021C" => "Z"
+
+# Ȥ  [LATIN CAPITAL LETTER Z WITH HOOK]
+"\u0224" => "Z"
+
+# ᴢ  [LATIN LETTER SMALL CAPITAL Z]
+"\u1D22" => "Z"
+
+# Ẑ  [LATIN CAPITAL LETTER Z WITH CIRCUMFLEX]
+"\u1E90" => "Z"
+
+# Ẓ  [LATIN CAPITAL LETTER Z WITH DOT BELOW]
+"\u1E92" => "Z"
+
+# Ẕ  [LATIN CAPITAL LETTER Z WITH LINE BELOW]
+"\u1E94" => "Z"
+
+# Ⓩ  [CIRCLED LATIN CAPITAL LETTER Z]
+"\u24CF" => "Z"
+
+# Ⱬ  [LATIN CAPITAL LETTER Z WITH DESCENDER]
+"\u2C6B" => "Z"
+
+# Ꝣ  [LATIN CAPITAL LETTER VISIGOTHIC Z]
+"\uA762" => "Z"
+
+# Z  [FULLWIDTH LATIN CAPITAL LETTER Z]
+"\uFF3A" => "Z"
+
+# ź  [LATIN SMALL LETTER Z WITH ACUTE]
+"\u017A" => "z"
+
+# ż  [LATIN SMALL LETTER Z WITH DOT ABOVE]
+"\u017C" => "z"
+
+# ž  [LATIN SMALL LETTER Z WITH CARON]
+"\u017E" => "z"
+
+# ƶ  [LATIN SMALL LETTER Z WITH STROKE]
+"\u01B6" => "z"
+
+# ȝ  http://en.wikipedia.org/wiki/Yogh  [LATIN SMALL LETTER YOGH]
+"\u021D" => "z"
+
+# ȥ  [LATIN SMALL LETTER Z WITH HOOK]
+"\u0225" => "z"
+
+# ɀ  [LATIN SMALL LETTER Z WITH SWASH TAIL]
+"\u0240" => "z"
+
+# ʐ  [LATIN SMALL LETTER Z WITH RETROFLEX HOOK]
+"\u0290" => "z"
+
+# ʑ  [LATIN SMALL LETTER Z WITH CURL]
+"\u0291" => "z"
+
+# ᵶ  [LATIN SMALL LETTER Z WITH MIDDLE TILDE]
+"\u1D76" => "z"
+
+# ᶎ  [LATIN SMALL LETTER Z WITH PALATAL HOOK]
+"\u1D8E" => "z"
+
+# ẑ  [LATIN SMALL LETTER Z WITH CIRCUMFLEX]
+"\u1E91" => "z"
+
+# ẓ  [LATIN SMALL LETTER Z WITH DOT BELOW]
+"\u1E93" => "z"
+
+# ẕ  [LATIN SMALL LETTER Z WITH LINE BELOW]
+"\u1E95" => "z"
+
+# ⓩ  [CIRCLED LATIN SMALL LETTER Z]
+"\u24E9" => "z"
+
+# ⱬ  [LATIN SMALL LETTER Z WITH DESCENDER]
+"\u2C6C" => "z"
+
+# ꝣ  [LATIN SMALL LETTER VISIGOTHIC Z]
+"\uA763" => "z"
+
+# z  [FULLWIDTH LATIN SMALL LETTER Z]
+"\uFF5A" => "z"
+
+# ⒵  [PARENTHESIZED LATIN SMALL LETTER Z]
+"\u24B5" => "(z)"
+
+# ⁰  [SUPERSCRIPT ZERO]
+"\u2070" => "0"
+
+# ₀  [SUBSCRIPT ZERO]
+"\u2080" => "0"
+
+# ⓪  [CIRCLED DIGIT ZERO]
+"\u24EA" => "0"
+
+# ⓿  [NEGATIVE CIRCLED DIGIT ZERO]
+"\u24FF" => "0"
+
+# 0  [FULLWIDTH DIGIT ZERO]
+"\uFF10" => "0"
+
+# ¹  [SUPERSCRIPT ONE]
+"\u00B9" => "1"
+
+# ₁  [SUBSCRIPT ONE]
+"\u2081" => "1"
+
+# ①  [CIRCLED DIGIT ONE]
+"\u2460" => "1"
+
+# ⓵  [DOUBLE CIRCLED DIGIT ONE]
+"\u24F5" => "1"
+
+# ❶  [DINGBAT NEGATIVE CIRCLED DIGIT ONE]
+"\u2776" => "1"
+
+# ➀  [DINGBAT CIRCLED SANS-SERIF DIGIT ONE]
+"\u2780" => "1"
+
+# ➊  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE]
+"\u278A" => "1"
+
+# 1  [FULLWIDTH DIGIT ONE]
+"\uFF11" => "1"
+
+# ⒈  [DIGIT ONE FULL STOP]
+"\u2488" => "1."
+
+# ⑴  [PARENTHESIZED DIGIT ONE]
+"\u2474" => "(1)"
+
+# ²  [SUPERSCRIPT TWO]
+"\u00B2" => "2"
+
+# ₂  [SUBSCRIPT TWO]
+"\u2082" => "2"
+
+# ②  [CIRCLED DIGIT TWO]
+"\u2461" => "2"
+
+# ⓶  [DOUBLE CIRCLED DIGIT TWO]
+"\u24F6" => "2"
+
+# ❷  [DINGBAT NEGATIVE CIRCLED DIGIT TWO]
+"\u2777" => "2"
+
+# ➁  [DINGBAT CIRCLED SANS-SERIF DIGIT TWO]
+"\u2781" => "2"
+
+# ➋  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO]
+"\u278B" => "2"
+
+# 2  [FULLWIDTH DIGIT TWO]
+"\uFF12" => "2"
+
+# ⒉  [DIGIT TWO FULL STOP]
+"\u2489" => "2."
+
+# ⑵  [PARENTHESIZED DIGIT TWO]
+"\u2475" => "(2)"
+
+# ³  [SUPERSCRIPT THREE]
+"\u00B3" => "3"
+
+# ₃  [SUBSCRIPT THREE]
+"\u2083" => "3"
+
+# ③  [CIRCLED DIGIT THREE]
+"\u2462" => "3"
+
+# ⓷  [DOUBLE CIRCLED DIGIT THREE]
+"\u24F7" => "3"
+
+# ❸  [DINGBAT NEGATIVE CIRCLED DIGIT THREE]
+"\u2778" => "3"
+
+# ➂  [DINGBAT CIRCLED SANS-SERIF DIGIT THREE]
+"\u2782" => "3"
+
+# ➌  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE]
+"\u278C" => "3"
+
+# 3  [FULLWIDTH DIGIT THREE]
+"\uFF13" => "3"
+
+# ⒊  [DIGIT THREE FULL STOP]
+"\u248A" => "3."
+
+# ⑶  [PARENTHESIZED DIGIT THREE]
+"\u2476" => "(3)"
+
+# ⁴  [SUPERSCRIPT FOUR]
+"\u2074" => "4"
+
+# ₄  [SUBSCRIPT FOUR]
+"\u2084" => "4"
+
+# ④  [CIRCLED DIGIT FOUR]
+"\u2463" => "4"
+
+# ⓸  [DOUBLE CIRCLED DIGIT FOUR]
+"\u24F8" => "4"
+
+# ❹  [DINGBAT NEGATIVE CIRCLED DIGIT FOUR]
+"\u2779" => "4"
+
+# ➃  [DINGBAT CIRCLED SANS-SERIF DIGIT FOUR]
+"\u2783" => "4"
+
+# ➍  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR]
+"\u278D" => "4"
+
+# 4  [FULLWIDTH DIGIT FOUR]
+"\uFF14" => "4"
+
+# ⒋  [DIGIT FOUR FULL STOP]
+"\u248B" => "4."
+
+# ⑷  [PARENTHESIZED DIGIT FOUR]
+"\u2477" => "(4)"
+
+# ⁵  [SUPERSCRIPT FIVE]
+"\u2075" => "5"
+
+# ₅  [SUBSCRIPT FIVE]
+"\u2085" => "5"
+
+# ⑤  [CIRCLED DIGIT FIVE]
+"\u2464" => "5"
+
+# ⓹  [DOUBLE CIRCLED DIGIT FIVE]
+"\u24F9" => "5"
+
+# ❺  [DINGBAT NEGATIVE CIRCLED DIGIT FIVE]
+"\u277A" => "5"
+
+# ➄  [DINGBAT CIRCLED SANS-SERIF DIGIT FIVE]
+"\u2784" => "5"
+
+# ➎  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE]
+"\u278E" => "5"
+
+# 5  [FULLWIDTH DIGIT FIVE]
+"\uFF15" => "5"
+
+# ⒌  [DIGIT FIVE FULL STOP]
+"\u248C" => "5."
+
+# ⑸  [PARENTHESIZED DIGIT FIVE]
+"\u2478" => "(5)"
+
+# ⁶  [SUPERSCRIPT SIX]
+"\u2076" => "6"
+
+# ₆  [SUBSCRIPT SIX]
+"\u2086" => "6"
+
+# ⑥  [CIRCLED DIGIT SIX]
+"\u2465" => "6"
+
+# ⓺  [DOUBLE CIRCLED DIGIT SIX]
+"\u24FA" => "6"
+
+# ❻  [DINGBAT NEGATIVE CIRCLED DIGIT SIX]
+"\u277B" => "6"
+
+# ➅  [DINGBAT CIRCLED SANS-SERIF DIGIT SIX]
+"\u2785" => "6"
+
+# ➏  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX]
+"\u278F" => "6"
+
+# 6  [FULLWIDTH DIGIT SIX]
+"\uFF16" => "6"
+
+# ⒍  [DIGIT SIX FULL STOP]
+"\u248D" => "6."
+
+# ⑹  [PARENTHESIZED DIGIT SIX]
+"\u2479" => "(6)"
+
+# ⁷  [SUPERSCRIPT SEVEN]
+"\u2077" => "7"
+
+# ₇  [SUBSCRIPT SEVEN]
+"\u2087" => "7"
+
+# ⑦  [CIRCLED DIGIT SEVEN]
+"\u2466" => "7"
+
+# ⓻  [DOUBLE CIRCLED DIGIT SEVEN]
+"\u24FB" => "7"
+
+# ❼  [DINGBAT NEGATIVE CIRCLED DIGIT SEVEN]
+"\u277C" => "7"
+
+# ➆  [DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN]
+"\u2786" => "7"
+
+# ➐  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN]
+"\u2790" => "7"
+
+# 7  [FULLWIDTH DIGIT SEVEN]
+"\uFF17" => "7"
+
+# ⒎  [DIGIT SEVEN FULL STOP]
+"\u248E" => "7."
+
+# ⑺  [PARENTHESIZED DIGIT SEVEN]
+"\u247A" => "(7)"
+
+# ⁸  [SUPERSCRIPT EIGHT]
+"\u2078" => "8"
+
+# ₈  [SUBSCRIPT EIGHT]
+"\u2088" => "8"
+
+# ⑧  [CIRCLED DIGIT EIGHT]
+"\u2467" => "8"
+
+# ⓼  [DOUBLE CIRCLED DIGIT EIGHT]
+"\u24FC" => "8"
+
+# ❽  [DINGBAT NEGATIVE CIRCLED DIGIT EIGHT]
+"\u277D" => "8"
+
+# ➇  [DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT]
+"\u2787" => "8"
+
+# ➑  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT]
+"\u2791" => "8"
+
+# 8  [FULLWIDTH DIGIT EIGHT]
+"\uFF18" => "8"
+
+# ⒏  [DIGIT EIGHT FULL STOP]
+"\u248F" => "8."
+
+# ⑻  [PARENTHESIZED DIGIT EIGHT]
+"\u247B" => "(8)"
+
+# ⁹  [SUPERSCRIPT NINE]
+"\u2079" => "9"
+
+# ₉  [SUBSCRIPT NINE]
+"\u2089" => "9"
+
+# ⑨  [CIRCLED DIGIT NINE]
+"\u2468" => "9"
+
+# ⓽  [DOUBLE CIRCLED DIGIT NINE]
+"\u24FD" => "9"
+
+# ❾  [DINGBAT NEGATIVE CIRCLED DIGIT NINE]
+"\u277E" => "9"
+
+# ➈  [DINGBAT CIRCLED SANS-SERIF DIGIT NINE]
+"\u2788" => "9"
+
+# ➒  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE]
+"\u2792" => "9"
+
+# 9  [FULLWIDTH DIGIT NINE]
+"\uFF19" => "9"
+
+# ⒐  [DIGIT NINE FULL STOP]
+"\u2490" => "9."
+
+# ⑼  [PARENTHESIZED DIGIT NINE]
+"\u247C" => "(9)"
+
+# ⑩  [CIRCLED NUMBER TEN]
+"\u2469" => "10"
+
+# ⓾  [DOUBLE CIRCLED NUMBER TEN]
+"\u24FE" => "10"
+
+# ❿  [DINGBAT NEGATIVE CIRCLED NUMBER TEN]
+"\u277F" => "10"
+
+# ➉  [DINGBAT CIRCLED SANS-SERIF NUMBER TEN]
+"\u2789" => "10"
+
+# ➓  [DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN]
+"\u2793" => "10"
+
+# ⒑  [NUMBER TEN FULL STOP]
+"\u2491" => "10."
+
+# ⑽  [PARENTHESIZED NUMBER TEN]
+"\u247D" => "(10)"
+
+# ⑪  [CIRCLED NUMBER ELEVEN]
+"\u246A" => "11"
+
+# ⓫  [NEGATIVE CIRCLED NUMBER ELEVEN]
+"\u24EB" => "11"
+
+# ⒒  [NUMBER ELEVEN FULL STOP]
+"\u2492" => "11."
+
+# ⑾  [PARENTHESIZED NUMBER ELEVEN]
+"\u247E" => "(11)"
+
+# ⑫  [CIRCLED NUMBER TWELVE]
+"\u246B" => "12"
+
+# ⓬  [NEGATIVE CIRCLED NUMBER TWELVE]
+"\u24EC" => "12"
+
+# ⒓  [NUMBER TWELVE FULL STOP]
+"\u2493" => "12."
+
+# ⑿  [PARENTHESIZED NUMBER TWELVE]
+"\u247F" => "(12)"
+
+# ⑬  [CIRCLED NUMBER THIRTEEN]
+"\u246C" => "13"
+
+# ⓭  [NEGATIVE CIRCLED NUMBER THIRTEEN]
+"\u24ED" => "13"
+
+# ⒔  [NUMBER THIRTEEN FULL STOP]
+"\u2494" => "13."
+
+# ⒀  [PARENTHESIZED NUMBER THIRTEEN]
+"\u2480" => "(13)"
+
+# ⑭  [CIRCLED NUMBER FOURTEEN]
+"\u246D" => "14"
+
+# ⓮  [NEGATIVE CIRCLED NUMBER FOURTEEN]
+"\u24EE" => "14"
+
+# ⒕  [NUMBER FOURTEEN FULL STOP]
+"\u2495" => "14."
+
+# ⒁  [PARENTHESIZED NUMBER FOURTEEN]
+"\u2481" => "(14)"
+
+# ⑮  [CIRCLED NUMBER FIFTEEN]
+"\u246E" => "15"
+
+# ⓯  [NEGATIVE CIRCLED NUMBER FIFTEEN]
+"\u24EF" => "15"
+
+# ⒖  [NUMBER FIFTEEN FULL STOP]
+"\u2496" => "15."
+
+# ⒂  [PARENTHESIZED NUMBER FIFTEEN]
+"\u2482" => "(15)"
+
+# ⑯  [CIRCLED NUMBER SIXTEEN]
+"\u246F" => "16"
+
+# ⓰  [NEGATIVE CIRCLED NUMBER SIXTEEN]
+"\u24F0" => "16"
+
+# ⒗  [NUMBER SIXTEEN FULL STOP]
+"\u2497" => "16."
+
+# ⒃  [PARENTHESIZED NUMBER SIXTEEN]
+"\u2483" => "(16)"
+
+# ⑰  [CIRCLED NUMBER SEVENTEEN]
+"\u2470" => "17"
+
+# ⓱  [NEGATIVE CIRCLED NUMBER SEVENTEEN]
+"\u24F1" => "17"
+
+# ⒘  [NUMBER SEVENTEEN FULL STOP]
+"\u2498" => "17."
+
+# ⒄  [PARENTHESIZED NUMBER SEVENTEEN]
+"\u2484" => "(17)"
+
+# ⑱  [CIRCLED NUMBER EIGHTEEN]
+"\u2471" => "18"
+
+# ⓲  [NEGATIVE CIRCLED NUMBER EIGHTEEN]
+"\u24F2" => "18"
+
+# ⒙  [NUMBER EIGHTEEN FULL STOP]
+"\u2499" => "18."
+
+# ⒅  [PARENTHESIZED NUMBER EIGHTEEN]
+"\u2485" => "(18)"
+
+# ⑲  [CIRCLED NUMBER NINETEEN]
+"\u2472" => "19"
+
+# ⓳  [NEGATIVE CIRCLED NUMBER NINETEEN]
+"\u24F3" => "19"
+
+# ⒚  [NUMBER NINETEEN FULL STOP]
+"\u249A" => "19."
+
+# ⒆  [PARENTHESIZED NUMBER NINETEEN]
+"\u2486" => "(19)"
+
+# ⑳  [CIRCLED NUMBER TWENTY]
+"\u2473" => "20"
+
+# ⓴  [NEGATIVE CIRCLED NUMBER TWENTY]
+"\u24F4" => "20"
+
+# ⒛  [NUMBER TWENTY FULL STOP]
+"\u249B" => "20."
+
+# ⒇  [PARENTHESIZED NUMBER TWENTY]
+"\u2487" => "(20)"
+
+# «  [LEFT-POINTING DOUBLE ANGLE QUOTATION MARK]
+"\u00AB" => "\""
+
+# »  [RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK]
+"\u00BB" => "\""
+
+# “  [LEFT DOUBLE QUOTATION MARK]
+"\u201C" => "\""
+
+# ”  [RIGHT DOUBLE QUOTATION MARK]
+"\u201D" => "\""
+
+# „  [DOUBLE LOW-9 QUOTATION MARK]
+"\u201E" => "\""
+
+# ″  [DOUBLE PRIME]
+"\u2033" => "\""
+
+# ‶  [REVERSED DOUBLE PRIME]
+"\u2036" => "\""
+
+# ❝  [HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT]
+"\u275D" => "\""
+
+# ❞  [HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT]
+"\u275E" => "\""
+
+# ❮  [HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT]
+"\u276E" => "\""
+
+# ❯  [HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT]
+"\u276F" => "\""
+
+# "  [FULLWIDTH QUOTATION MARK]
+"\uFF02" => "\""
+
+# ‘  [LEFT SINGLE QUOTATION MARK]
+"\u2018" => "\'"
+
+# ’  [RIGHT SINGLE QUOTATION MARK]
+"\u2019" => "\'"
+
+# ‚  [SINGLE LOW-9 QUOTATION MARK]
+"\u201A" => "\'"
+
+# ‛  [SINGLE HIGH-REVERSED-9 QUOTATION MARK]
+"\u201B" => "\'"
+
+# ′  [PRIME]
+"\u2032" => "\'"
+
+# ‵  [REVERSED PRIME]
+"\u2035" => "\'"
+
+# ‹  [SINGLE LEFT-POINTING ANGLE QUOTATION MARK]
+"\u2039" => "\'"
+
+# ›  [SINGLE RIGHT-POINTING ANGLE QUOTATION MARK]
+"\u203A" => "\'"
+
+# ❛  [HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT]
+"\u275B" => "\'"
+
+# ❜  [HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT]
+"\u275C" => "\'"
+
+# '  [FULLWIDTH APOSTROPHE]
+"\uFF07" => "\'"
+
+# ‐  [HYPHEN]
+"\u2010" => "-"
+
+# ‑  [NON-BREAKING HYPHEN]
+"\u2011" => "-"
+
+# ‒  [FIGURE DASH]
+"\u2012" => "-"
+
+# –  [EN DASH]
+"\u2013" => "-"
+
+# —  [EM DASH]
+"\u2014" => "-"
+
+# ⁻  [SUPERSCRIPT MINUS]
+"\u207B" => "-"
+
+# ₋  [SUBSCRIPT MINUS]
+"\u208B" => "-"
+
+# -  [FULLWIDTH HYPHEN-MINUS]
+"\uFF0D" => "-"
+
+# ⁅  [LEFT SQUARE BRACKET WITH QUILL]
+"\u2045" => "["
+
+# ❲  [LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT]
+"\u2772" => "["
+
+# [  [FULLWIDTH LEFT SQUARE BRACKET]
+"\uFF3B" => "["
+
+# ⁆  [RIGHT SQUARE BRACKET WITH QUILL]
+"\u2046" => "]"
+
+# ❳  [LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT]
+"\u2773" => "]"
+
+# ]  [FULLWIDTH RIGHT SQUARE BRACKET]
+"\uFF3D" => "]"
+
+# ⁽  [SUPERSCRIPT LEFT PARENTHESIS]
+"\u207D" => "("
+
+# ₍  [SUBSCRIPT LEFT PARENTHESIS]
+"\u208D" => "("
+
+# ❨  [MEDIUM LEFT PARENTHESIS ORNAMENT]
+"\u2768" => "("
+
+# ❪  [MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT]
+"\u276A" => "("
+
+# (  [FULLWIDTH LEFT PARENTHESIS]
+"\uFF08" => "("
+
+# ⸨  [LEFT DOUBLE PARENTHESIS]
+"\u2E28" => "(("
+
+# ⁾  [SUPERSCRIPT RIGHT PARENTHESIS]
+"\u207E" => ")"
+
+# ₎  [SUBSCRIPT RIGHT PARENTHESIS]
+"\u208E" => ")"
+
+# ❩  [MEDIUM RIGHT PARENTHESIS ORNAMENT]
+"\u2769" => ")"
+
+# ❫  [MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT]
+"\u276B" => ")"
+
+# )  [FULLWIDTH RIGHT PARENTHESIS]
+"\uFF09" => ")"
+
+# ⸩  [RIGHT DOUBLE PARENTHESIS]
+"\u2E29" => "))"
+
+# ❬  [MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT]
+"\u276C" => "<"
+
+# ❰  [HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT]
+"\u2770" => "<"
+
+# <  [FULLWIDTH LESS-THAN SIGN]
+"\uFF1C" => "<"
+
+# ❭  [MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT]
+"\u276D" => ">"
+
+# ❱  [HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT]
+"\u2771" => ">"
+
+# >  [FULLWIDTH GREATER-THAN SIGN]
+"\uFF1E" => ">"
+
+# ❴  [MEDIUM LEFT CURLY BRACKET ORNAMENT]
+"\u2774" => "{"
+
+# {  [FULLWIDTH LEFT CURLY BRACKET]
+"\uFF5B" => "{"
+
+# ❵  [MEDIUM RIGHT CURLY BRACKET ORNAMENT]
+"\u2775" => "}"
+
+# }  [FULLWIDTH RIGHT CURLY BRACKET]
+"\uFF5D" => "}"
+
+# ⁺  [SUPERSCRIPT PLUS SIGN]
+"\u207A" => "+"
+
+# ₊  [SUBSCRIPT PLUS SIGN]
+"\u208A" => "+"
+
+# +  [FULLWIDTH PLUS SIGN]
+"\uFF0B" => "+"
+
+# ⁼  [SUPERSCRIPT EQUALS SIGN]
+"\u207C" => "="
+
+# ₌  [SUBSCRIPT EQUALS SIGN]
+"\u208C" => "="
+
+# =  [FULLWIDTH EQUALS SIGN]
+"\uFF1D" => "="
+
+# !  [FULLWIDTH EXCLAMATION MARK]
+"\uFF01" => "!"
+
+# ‼  [DOUBLE EXCLAMATION MARK]
+"\u203C" => "!!"
+
+# ⁉  [EXCLAMATION QUESTION MARK]
+"\u2049" => "!?"
+
+# #  [FULLWIDTH NUMBER SIGN]
+"\uFF03" => "#"
+
+# $  [FULLWIDTH DOLLAR SIGN]
+"\uFF04" => "$"
+
+# ⁒  [COMMERCIAL MINUS SIGN]
+"\u2052" => "%"
+
+# %  [FULLWIDTH PERCENT SIGN]
+"\uFF05" => "%"
+
+# &  [FULLWIDTH AMPERSAND]
+"\uFF06" => "&"
+
+# ⁎  [LOW ASTERISK]
+"\u204E" => "*"
+
+# *  [FULLWIDTH ASTERISK]
+"\uFF0A" => "*"
+
+# ,  [FULLWIDTH COMMA]
+"\uFF0C" => ","
+
+# .  [FULLWIDTH FULL STOP]
+"\uFF0E" => "."
+
+# ⁄  [FRACTION SLASH]
+"\u2044" => "/"
+
+# /  [FULLWIDTH SOLIDUS]
+"\uFF0F" => "/"
+
+# :  [FULLWIDTH COLON]
+"\uFF1A" => ":"
+
+# ⁏  [REVERSED SEMICOLON]
+"\u204F" => ";"
+
+# ;  [FULLWIDTH SEMICOLON]
+"\uFF1B" => ";"
+
+# ?  [FULLWIDTH QUESTION MARK]
+"\uFF1F" => "?"
+
+# ⁇  [DOUBLE QUESTION MARK]
+"\u2047" => "??"
+
+# ⁈  [QUESTION EXCLAMATION MARK]
+"\u2048" => "?!"
+
+# @  [FULLWIDTH COMMERCIAL AT]
+"\uFF20" => "@"
+
+# \  [FULLWIDTH REVERSE SOLIDUS]
+"\uFF3C" => "\\"
+
+# ‸  [CARET]
+"\u2038" => "^"
+
+# ^  [FULLWIDTH CIRCUMFLEX ACCENT]
+"\uFF3E" => "^"
+
+# _  [FULLWIDTH LOW LINE]
+"\uFF3F" => "_"
+
+# ⁓  [SWUNG DASH]
+"\u2053" => "~"
+
+# ~  [FULLWIDTH TILDE]
+"\uFF5E" => "~"
+
+################################################################
+# Below is the Perl script used to generate the above mappings #
+# from ASCIIFoldingFilter.java:                                #
+################################################################
+#
+# #!/usr/bin/perl
+#
+# use warnings;
+# use strict;
+# 
+# my @source_chars = ();
+# my @source_char_descriptions = ();
+# my $target = '';
+# 
+# while (<>) {
+#   if (/case\s+'(\\u[A-F0-9]+)':\s*\/\/\s*(.*)/i) {
+#     push @source_chars, $1;
+#	  push @source_char_descriptions, $2;
+#	  next;
+#   }
+#   if (/output\[[^\]]+\]\s*=\s*'(\\'|\\\\|.)'/) {
+#     $target .= $1;
+#     next;
+#   }
+#   if (/break;/) {
+#     $target = "\\\"" if ($target eq '"');
+#     for my $source_char_num (0..$#source_chars) {
+#	    print "# $source_char_descriptions[$source_char_num]\n";
+#	    print "\"$source_chars[$source_char_num]\" => \"$target\"\n\n";
+#	  }
+#	  @source_chars = ();
+#	  @source_char_descriptions = ();
+#	  $target = '';
+#   }
+# }
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/mapping-ISOLatin1Accent.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/mapping-ISOLatin1Accent.txt
new file mode 100644
index 0000000..ede7742
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/mapping-ISOLatin1Accent.txt
@@ -0,0 +1,246 @@
+# 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.
+
+# Syntax:
+#   "source" => "target"
+#     "source".length() > 0 (source cannot be empty.)
+#     "target".length() >= 0 (target can be empty.)
+
+# example:
+#   "À" => "A"
+#   "\u00C0" => "A"
+#   "\u00C0" => "\u0041"
+#   "ß" => "ss"
+#   "\t" => " "
+#   "\n" => ""
+
+# À => A
+"\u00C0" => "A"
+
+# Á => A
+"\u00C1" => "A"
+
+# Â => A
+"\u00C2" => "A"
+
+# Ã => A
+"\u00C3" => "A"
+
+# Ä => A
+"\u00C4" => "A"
+
+# Å => A
+"\u00C5" => "A"
+
+# Æ => AE
+"\u00C6" => "AE"
+
+# Ç => C
+"\u00C7" => "C"
+
+# È => E
+"\u00C8" => "E"
+
+# É => E
+"\u00C9" => "E"
+
+# Ê => E
+"\u00CA" => "E"
+
+# Ë => E
+"\u00CB" => "E"
+
+# Ì => I
+"\u00CC" => "I"
+
+# Í => I
+"\u00CD" => "I"
+
+# Î => I
+"\u00CE" => "I"
+
+# Ï => I
+"\u00CF" => "I"
+
+# IJ => IJ
+"\u0132" => "IJ"
+
+# Ð => D
+"\u00D0" => "D"
+
+# Ñ => N
+"\u00D1" => "N"
+
+# Ò => O
+"\u00D2" => "O"
+
+# Ó => O
+"\u00D3" => "O"
+
+# Ô => O
+"\u00D4" => "O"
+
+# Õ => O
+"\u00D5" => "O"
+
+# Ö => O
+"\u00D6" => "O"
+
+# Ø => O
+"\u00D8" => "O"
+
+# Π=> OE
+"\u0152" => "OE"
+
+# Þ
+"\u00DE" => "TH"
+
+# Ù => U
+"\u00D9" => "U"
+
+# Ú => U
+"\u00DA" => "U"
+
+# Û => U
+"\u00DB" => "U"
+
+# Ü => U
+"\u00DC" => "U"
+
+# Ý => Y
+"\u00DD" => "Y"
+
+# Ÿ => Y
+"\u0178" => "Y"
+
+# à => a
+"\u00E0" => "a"
+
+# á => a
+"\u00E1" => "a"
+
+# â => a
+"\u00E2" => "a"
+
+# ã => a
+"\u00E3" => "a"
+
+# ä => a
+"\u00E4" => "a"
+
+# å => a
+"\u00E5" => "a"
+
+# æ => ae
+"\u00E6" => "ae"
+
+# ç => c
+"\u00E7" => "c"
+
+# è => e
+"\u00E8" => "e"
+
+# é => e
+"\u00E9" => "e"
+
+# ê => e
+"\u00EA" => "e"
+
+# ë => e
+"\u00EB" => "e"
+
+# ì => i
+"\u00EC" => "i"
+
+# í => i
+"\u00ED" => "i"
+
+# î => i
+"\u00EE" => "i"
+
+# ï => i
+"\u00EF" => "i"
+
+# ij => ij
+"\u0133" => "ij"
+
+# ð => d
+"\u00F0" => "d"
+
+# ñ => n
+"\u00F1" => "n"
+
+# ò => o
+"\u00F2" => "o"
+
+# ó => o
+"\u00F3" => "o"
+
+# ô => o
+"\u00F4" => "o"
+
+# õ => o
+"\u00F5" => "o"
+
+# ö => o
+"\u00F6" => "o"
+
+# ø => o
+"\u00F8" => "o"
+
+# œ => oe
+"\u0153" => "oe"
+
+# ß => ss
+"\u00DF" => "ss"
+
+# þ => th
+"\u00FE" => "th"
+
+# ù => u
+"\u00F9" => "u"
+
+# ú => u
+"\u00FA" => "u"
+
+# û => u
+"\u00FB" => "u"
+
+# ü => u
+"\u00FC" => "u"
+
+# ý => y
+"\u00FD" => "y"
+
+# ÿ => y
+"\u00FF" => "y"
+
+# ff => ff
+"\uFB00" => "ff"
+
+# fi => fi
+"\uFB01" => "fi"
+
+# fl => fl
+"\uFB02" => "fl"
+
+# ffi => ffi
+"\uFB03" => "ffi"
+
+# ffl => ffl
+"\uFB04" => "ffl"
+
+# ſt => ft
+"\uFB05" => "ft"
+
+# st => st
+"\uFB06" => "st"
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/protwords.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/protwords.txt
new file mode 100644
index 0000000..1dfc0ab
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/protwords.txt
@@ -0,0 +1,21 @@
+# 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.
+
+#-----------------------------------------------------------------------
+# Use a protected word file to protect against the stemmer reducing two
+# unrelated words to the same base word.
+
+# Some non-words that normally won't be encountered,
+# just to test that they won't be stemmed.
+dontstems
+zwhacky
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/schema.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/schema.xml
new file mode 100644
index 0000000..d2a6975
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/schema.xml
@@ -0,0 +1,1025 @@
+<?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.
+-->
+
+<!--  
+ This is the Solr schema file. This file should be named "schema.xml" and
+ should be in the conf directory under the solr home
+ (i.e. ./solr/conf/schema.xml by default) 
+ or located where the classloader for the Solr webapp can find it.
+
+ This example schema is the recommended starting point for users.
+ It should be kept correct and concise, usable out-of-the-box.
+
+ For more information, on how to customize this file, please see
+ http://wiki.apache.org/solr/SchemaXml
+
+ PERFORMANCE NOTE: this schema includes many optional features and should not
+ be used for benchmarking.  To improve performance one could
+  - set stored="false" for all fields possible (esp large fields) when you
+    only need to search on the field but don't need to return the original
+    value.
+  - set indexed="false" if you don't need to search on the field, but only
+    return the field as a result of searching on other indexed fields.
+  - remove all unneeded copyField statements
+  - for best index size and searching performance, set "index" to false
+    for all general text fields, use copyField to copy them to the
+    catchall "text" field, and use that for searching.
+  - For maximum indexing performance, use the StreamingUpdateSolrServer
+    java client.
+  - Remember to run the JVM in server mode, and use a higher logging level
+    that avoids logging every request
+-->
+
+<schema name="Default Solr File Manager schema" version="1.5">
+  <!-- attribute "name" is the name of this schema and is only used for display purposes.
+       version="x.y" is Solr's version number for the schema syntax and 
+       semantics.  It should not normally be changed by applications.
+
+       1.0: multiValued attribute did not exist, all fields are multiValued 
+            by nature
+       1.1: multiValued attribute introduced, false by default 
+       1.2: omitTermFreqAndPositions attribute introduced, true by default 
+            except for text fields.
+       1.3: removed optional field compress feature
+       1.4: autoGeneratePhraseQueries attribute introduced to drive QueryParser
+            behavior when a single string produces multiple tokens.  Defaults 
+            to off for version >= 1.4
+       1.5: omitNorms defaults to true for primitive field types 
+            (int, float, boolean, string...)
+     -->
+
+ <fields>
+   <!-- Valid attributes for fields:
+     name: mandatory - the name for the field
+     type: mandatory - the name of a field type from the 
+       <types> fieldType section
+     indexed: true if this field should be indexed (searchable or sortable)
+     stored: true if this field should be retrievable
+     docValues: true if this field should have doc values. Doc values are
+       useful for faceting, grouping, sorting and function queries. Although not
+       required, doc values will make the index faster to load, more
+       NRT-friendly and more memory-efficient. They however come with some
+       limitations: they are currently only supported by StrField, UUIDField
+       and all Trie*Fields, and depending on the field type, they might
+       require the field to be single-valued, be required or have a default
+       value (check the documentation of the field type you're interested in
+       for more information)
+     multiValued: true if this field may contain multiple values per document
+     omitNorms: (expert) set to true to omit the norms associated with
+       this field (this disables length normalization and index-time
+       boosting for the field, and saves some memory).  Only full-text
+       fields or fields that need an index-time boost need norms.
+       Norms are omitted for primitive (non-analyzed) types by default.
+     termVectors: [false] set to true to store the term vector for a
+       given field.
+       When using MoreLikeThis, fields used for similarity should be
+       stored for best performance.
+     termPositions: Store position information with the term vector.  
+       This will increase storage costs.
+     termOffsets: Store offset information with the term vector. This 
+       will increase storage costs.
+     required: The field is required.  It will throw an error if the
+       value does not exist
+     default: a value that should be used if no value is specified
+       when adding a document.
+   -->
+
+   <!-- field names should consist of alphanumeric or underscore characters only and
+      not start with a digit.  This is not currently strictly enforced,
+      but other field names will not have first class support from all components
+      and back compatibility is not guaranteed.  Names with both leading and
+      trailing underscores (e.g. _version_) are reserved.
+   -->
+        
+     
+   <!-- Solr unique document identifier -->
+   <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> 
+
+   <!-- core CAS product attributes -->
+   <field name="CAS.ProductId" type="string" indexed="true" stored="true" required="true" multiValued="false" />
+   <field name="CAS.ProductName" type="string" indexed="true" stored="true" required="true" multiValued="false" />
+   <field name="CAS.ProductTypeName" type="string" indexed="true" stored="true" required="true" multiValued="false" />
+   <field name="CAS.ProductTypeId" type="string" indexed="true" stored="true" required="true" multiValued="false" />
+   <field name="CAS.ProductReceivedTime" type="date" indexed="true" stored="true" required="false" multiValued="false" />
+   <field name="CAS.ProductStructure" type="string" indexed="true" stored="true" required="false" multiValued="false" />
+   <field name="CAS.ProductTransferStatus" type="string" indexed="true" stored="true" required="false" multiValued="false" />
+
+   <field name="CAS.RootReferenceOriginal" type="string" indexed="true" stored="true" required="false" multiValued="true" />
+   <field name="CAS.RootReferenceDatastore" type="string" indexed="true" stored="true" required="false" multiValued="true" />
+   <field name="CAS.RootReferenceFileSize" type="long" indexed="true" stored="true" required="false" multiValued="true" />
+   <field name="CAS.RootReferenceMimeType" type="string" indexed="true" stored="true" required="false" multiValued="true" />
+
+   <field name="CAS.ReferenceOriginal" type="string" indexed="true" stored="true" required="false" multiValued="true" />
+   <field name="CAS.ReferenceDatastore" type="string" indexed="true" stored="true" required="false" multiValued="true" />
+   <field name="CAS.ReferenceFileSize" type="long" indexed="true" stored="true" required="false" multiValued="true" />
+   <field name="CAS.ReferenceMimeType" type="string" indexed="true" stored="true" required="false" multiValued="true" />
+
+   <!-- all unspecified fields ending in 'Date' or 'Time' are interpreted as single-value dates  -->
+   <field name="*Date" type="date" indexed="true" stored="true" required="false" multiValued="false" />
+   <field name="*Time" type="date" indexed="true" stored="true" required="false" multiValued="false" />
+
+   <!-- all other fields are indexed and stored as-is and can have multiple values -->
+   <dynamicField name="*" type="string" indexed="true" stored="true" omitNorms="true" multiValued="true" />
+
+   <!-- catch-all text fields for full free-text query -->
+   <copyField source="*" dest="text" />
+   <copyField source="*" dest="text_rev" />
+
+   <!-- Main body of document extracted by SolrCell.
+        NOTE: This field is not indexed by default, since it is also copied to "text"
+        using copyField below. This is to save space. Use this field for returning and
+        highlighting document content. Use the "text" field to search the content. -->
+   <field name="content" type="text_general" indexed="false" stored="true" multiValued="true"/>
+
+   <!-- catchall field, containing all other searchable text fields (implemented
+        via copyField further on in this schema  -->
+   <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
+
+   <!-- catchall text field that indexes tokens both normally and in reverse for efficient
+        leading wildcard queries. -->
+   <field name="text_rev" type="text_general_rev" indexed="true" stored="false" multiValued="true"/>
+
+   <!-- IMPORTANT: needed by Solr 4.X and above -->
+   <field name="_version_" type="long" indexed="true" stored="true"/>
+
+   <!-- uncomment the following to ignore any fields that don't already match an existing 
+        field name or dynamic field, rather than reporting them as an error. 
+        alternately, change the type="ignored" to some other type e.g. "text" if you want 
+        unknown fields indexed and/or stored by default --> 
+   <!--dynamicField name="*" type="ignored" multiValued="true" /-->
+   
+ </fields>
+
+
+ <!-- Field to use to determine and enforce document uniqueness. 
+      Unless this field is marked with required="false", it will be a required field
+   -->
+ <uniqueKey>id</uniqueKey>
+
+ <!-- DEPRECATED: The defaultSearchField is consulted by various query parsers when
+  parsing a query string that isn't explicit about the field.  Machine (non-user)
+  generated queries are best made explicit, or they can use the "df" request parameter
+  which takes precedence over this.
+  Note: Un-commenting defaultSearchField will be insufficient if your request handler
+  in solrconfig.xml defines "df", which takes precedence. That would need to be removed.
+ <defaultSearchField>text</defaultSearchField> -->
+
+ <!-- DEPRECATED: The defaultOperator (AND|OR) is consulted by various query parsers
+  when parsing a query string to determine if a clause of the query should be marked as
+  required or optional, assuming the clause isn't already marked by some operator.
+  The default is OR, which is generally assumed so it is not a good idea to change it
+  globally here.  The "q.op" request parameter takes precedence over this.
+ <solrQueryParser defaultOperator="OR"/> -->
+ 
+  <types>
+    <!-- field type definitions. The "name" attribute is
+       just a label to be used by field definitions.  The "class"
+       attribute and any other attributes determine the real
+       behavior of the fieldType.
+         Class names starting with "solr" refer to java classes in a
+       standard package such as org.apache.solr.analysis
+    -->
+
+    <!-- The StrField type is not analyzed, but indexed/stored verbatim.
+       It supports doc values but in that case the field needs to be
+       single-valued and either required or have a default value.
+      -->
+    <fieldType name="string" class="solr.StrField" sortMissingLast="true" />
+
+    <!-- boolean type: "true" or "false" -->
+    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
+
+    <!-- sortMissingLast and sortMissingFirst attributes are optional attributes are
+         currently supported on types that are sorted internally as strings
+         and on numeric types.
+	     This includes "string","boolean", and, as of 3.5 (and 4.x),
+	     int, float, long, date, double, including the "Trie" variants.
+       - If sortMissingLast="true", then a sort on this field will cause documents
+         without the field to come after documents with the field,
+         regardless of the requested sort order (asc or desc).
+       - If sortMissingFirst="true", then a sort on this field will cause documents
+         without the field to come before documents with the field,
+         regardless of the requested sort order.
+       - If sortMissingLast="false" and sortMissingFirst="false" (the default),
+         then default lucene sorting will be used which places docs without the
+         field first in an ascending sort and last in a descending sort.
+    -->    
+
+    <!--
+      Default numeric field types. For faster range queries, consider the tint/tfloat/tlong/tdouble types.
+
+      These fields support doc values, but they require the field to be
+      single-valued and either be required or have a default value.
+    -->
+    <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
+
+    <!--
+     Numeric field types that index each value at various levels of precision
+     to accelerate range queries when the number of values between the range
+     endpoints is large. See the javadoc for NumericRangeQuery for internal
+     implementation details.
+
+     Smaller precisionStep values (specified in bits) will lead to more tokens
+     indexed per value, slightly larger index size, and faster range queries.
+     A precisionStep of 0 disables indexing at different precision levels.
+    -->
+    <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
+    <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
+    <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
+    <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
+
+    <!-- The format for this date field is of the form 1995-12-31T23:59:59Z, and
+         is a more restricted form of the canonical representation of dateTime
+         http://www.w3.org/TR/xmlschema-2/#dateTime    
+         The trailing "Z" designates UTC time and is mandatory.
+         Optional fractional seconds are allowed: 1995-12-31T23:59:59.999Z
+         All other components are mandatory.
+
+         Expressions can also be used to denote calculations that should be
+         performed relative to "NOW" to determine the value, ie...
+
+               NOW/HOUR
+                  ... Round to the start of the current hour
+               NOW-1DAY
+                  ... Exactly 1 day prior to now
+               NOW/DAY+6MONTHS+3DAYS
+                  ... 6 months and 3 days in the future from the start of
+                      the current day
+                      
+         Consult the DateField javadocs for more information.
+
+         Note: For faster range queries, consider the tdate type
+      -->
+    <fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/>
+
+    <!-- A Trie based date field for faster date range queries and date faceting. -->
+    <fieldType name="tdate" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="0"/>
+
+
+    <!--Binary data type. The data should be sent/retrieved in as Base64 encoded Strings -->
+    <fieldtype name="binary" class="solr.BinaryField"/>
+
+    <!--
+      Note:
+      These should only be used for compatibility with existing indexes (created with lucene or older Solr versions).
+      Use Trie based fields instead. As of Solr 3.5 and 4.x, Trie based fields support sortMissingFirst/Last
+      
+      Plain numeric field types that store and index the text
+      value verbatim (and hence don't correctly support range queries, since the
+      lexicographic ordering isn't equal to the numeric ordering)
+    -->
+    <fieldType name="pint" class="solr.IntField"/>
+    <fieldType name="plong" class="solr.LongField"/>
+    <fieldType name="pfloat" class="solr.FloatField"/>
+    <fieldType name="pdouble" class="solr.DoubleField"/>
+    <fieldType name="pdate" class="solr.DateField" sortMissingLast="true"/>
+
+    <!-- The "RandomSortField" is not used to store or search any
+         data.  You can declare fields of this type it in your schema
+         to generate pseudo-random orderings of your docs for sorting 
+         or function purposes.  The ordering is generated based on the field
+         name and the version of the index. As long as the index version
+         remains unchanged, and the same field name is reused,
+         the ordering of the docs will be consistent.  
+         If you want different psuedo-random orderings of documents,
+         for the same version of the index, use a dynamicField and
+         change the field name in the request.
+     -->
+    <fieldType name="random" class="solr.RandomSortField" indexed="true" />
+
+    <!-- solr.TextField allows the specification of custom text analyzers
+         specified as a tokenizer and a list of token filters. Different
+         analyzers may be specified for indexing and querying.
+
+         The optional positionIncrementGap puts space between multiple fields of
+         this type on the same document, with the purpose of preventing false phrase
+         matching across fields.
+
+         For more info on customizing your analyzer chain, please see
+         http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters
+     -->
+
+    <!-- One can also specify an existing Analyzer class that has a
+         default constructor via the class attribute on the analyzer element.
+         Example:
+    <fieldType name="text_greek" class="solr.TextField">
+      <analyzer class="org.apache.lucene.analysis.el.GreekAnalyzer"/>
+    </fieldType>
+    -->
+
+    <!-- A text field that only splits on whitespace for exact matching of words -->
+    <fieldType name="text_ws" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A general text field that has reasonable, generic
+         cross-language defaults: it tokenizes with StandardTokenizer,
+	 removes stop words from case-insensitive "stopwords.txt"
+	 (empty by default), and down cases.  At query time only, it
+	 also applies synonyms. -->
+    <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A text field with defaults appropriate for English: it
+         tokenizes with StandardTokenizer, removes English stop words
+         (lang/stopwords_en.txt), down cases, protects words from protwords.txt, and
+         finally applies Porter's stemming.  The query time analyzer
+         also applies synonyms from synonyms.txt. -->
+    <fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        -->
+        <!-- Case insensitive stop word removal.
+          add enablePositionIncrements=true in both the index and query
+          analyzers to leave a 'gap' for more accurate phrase queries.
+        -->
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="lang/stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.LowerCaseFilterFactory"/>
+	<filter class="solr.EnglishPossessiveFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+	<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+	-->
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="lang/stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.LowerCaseFilterFactory"/>
+	<filter class="solr.EnglishPossessiveFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+	<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+	-->
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A text field with defaults appropriate for English, plus
+	 aggressive word-splitting and autophrase features enabled.
+	 This field is just like text_en, except it adds
+	 WordDelimiterFilter to enable splitting and matching of
+	 words on case-change, alpha numeric boundaries, and
+	 non-alphanumeric chars.  This means certain compound word
+	 cases will work, for example query "wi fi" will match
+	 document "WiFi" or "wi-fi".
+        -->
+    <fieldType name="text_en_splitting" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
+      <analyzer type="index">
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        -->
+        <!-- Case insensitive stop word removal.
+          add enablePositionIncrements=true in both the index and query
+          analyzers to leave a 'gap' for more accurate phrase queries.
+        -->
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="lang/stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="lang/stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Less flexible matching, but less false matches.  Probably not ideal for product names,
+         but may be good for SKUs.  Can insert dashes in the wrong place and still match. -->
+    <fieldType name="text_en_splitting_tight" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt"/>
+        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="0" generateNumberParts="0" catenateWords="1" catenateNumbers="1" catenateAll="0"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+        <!-- this filter can remove any duplicate tokens that appear at the same position - sometimes
+             possible with WordDelimiterFilter in conjuncton with stemming. -->
+        <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Just like text_general except it reverses the characters of
+	 each token, to enable more efficient leading wildcard queries. -->
+    <fieldType name="text_general_rev" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.ReversedWildcardFilterFactory" withOriginal="true"
+           maxPosAsterisk="3" maxPosQuestion="2" maxFractionAsterisk="0.33"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- charFilter + WhitespaceTokenizer  -->
+    <!--
+    <fieldType name="text_char_norm" class="solr.TextField" positionIncrementGap="100" >
+      <analyzer>
+        <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ISOLatin1Accent.txt"/>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+      </analyzer>
+    </fieldType>
+    -->
+
+    <!-- This is an example of using the KeywordTokenizer along
+         With various TokenFilterFactories to produce a sortable field
+         that does not include some properties of the source text
+      -->
+    <fieldType name="alphaOnlySort" class="solr.TextField" sortMissingLast="true" omitNorms="true">
+      <analyzer>
+        <!-- KeywordTokenizer does no actual tokenizing, so the entire
+             input string is preserved as a single token
+          -->
+        <tokenizer class="solr.KeywordTokenizerFactory"/>
+        <!-- The LowerCase TokenFilter does what you expect, which can be
+             when you want your sorting to be case insensitive
+          -->
+        <filter class="solr.LowerCaseFilterFactory" />
+        <!-- The TrimFilter removes any leading or trailing whitespace -->
+        <filter class="solr.TrimFilterFactory" />
+        <!-- The PatternReplaceFilter gives you the flexibility to use
+             Java Regular expression to replace any sequence of characters
+             matching a pattern with an arbitrary replacement string, 
+             which may include back references to portions of the original
+             string matched by the pattern.
+             
+             See the Java Regular Expression documentation for more
+             information on pattern and replacement string syntax.
+             
+             http://java.sun.com/j2se/1.6.0/docs/api/java/util/regex/package-summary.html
+          -->
+        <filter class="solr.PatternReplaceFilterFactory"
+                pattern="([^a-z])" replacement="" replace="all"
+        />
+      </analyzer>
+    </fieldType>
+    
+    <fieldtype name="phonetic" stored="false" indexed="true" class="solr.TextField" >
+      <analyzer>
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.DoubleMetaphoneFilterFactory" inject="false"/>
+      </analyzer>
+    </fieldtype>
+
+    <fieldtype name="payloads" stored="false" indexed="true" class="solr.TextField" >
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <!--
+        The DelimitedPayloadTokenFilter can put payloads on tokens... for example,
+        a token of "foo|1.4"  would be indexed as "foo" with a payload of 1.4f
+        Attributes of the DelimitedPayloadTokenFilterFactory : 
+         "delimiter" - a one character delimiter. Default is | (pipe)
+	 "encoder" - how to encode the following value into a playload
+	    float -> org.apache.lucene.analysis.payloads.FloatEncoder,
+	    integer -> o.a.l.a.p.IntegerEncoder
+	    identity -> o.a.l.a.p.IdentityEncoder
+            Fully Qualified class name implementing PayloadEncoder, Encoder must have a no arg constructor.
+         -->
+        <filter class="solr.DelimitedPayloadTokenFilterFactory" encoder="float"/>
+      </analyzer>
+    </fieldtype>
+
+    <!-- lowercases the entire field value, keeping it as a single token.  -->
+    <fieldType name="lowercase" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.KeywordTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory" />
+      </analyzer>
+    </fieldType>
+
+    <!-- 
+      Example of using PathHierarchyTokenizerFactory at index time, so
+      queries for paths match documents at that path, or in descendent paths
+    -->
+    <fieldType name="descendent_path" class="solr.TextField">
+      <analyzer type="index">
+	<tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" />
+      </analyzer>
+      <analyzer type="query">
+	<tokenizer class="solr.KeywordTokenizerFactory" />
+      </analyzer>
+    </fieldType>
+    <!-- 
+      Example of using PathHierarchyTokenizerFactory at query time, so
+      queries for paths match documents at that path, or in ancestor paths
+    -->
+    <fieldType name="ancestor_path" class="solr.TextField">
+      <analyzer type="index">
+	<tokenizer class="solr.KeywordTokenizerFactory" />
+      </analyzer>
+      <analyzer type="query">
+	<tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" />
+      </analyzer>
+    </fieldType>
+
+    <!-- since fields of this type are by default not stored or indexed,
+         any data added to them will be ignored outright.  --> 
+    <fieldtype name="ignored" stored="false" indexed="false" multiValued="true" class="solr.StrField" />
+
+    <!-- This point type indexes the coordinates as separate fields (subFields)
+      If subFieldType is defined, it references a type, and a dynamic field
+      definition is created matching *___<typename>.  Alternately, if 
+      subFieldSuffix is defined, that is used to create the subFields.
+      Example: if subFieldType="double", then the coordinates would be
+        indexed in fields myloc_0___double,myloc_1___double.
+      Example: if subFieldSuffix="_d" then the coordinates would be indexed
+        in fields myloc_0_d,myloc_1_d
+      The subFields are an implementation detail of the fieldType, and end
+      users normally should not need to know about them.
+     -->
+    <fieldType name="point" class="solr.PointType" dimension="2" subFieldSuffix="_d"/>
+
+    <!-- A specialized field for geospatial search. If indexed, this fieldType must not be multivalued. -->
+    <fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
+
+    <!-- An alternative geospatial field type new to Solr 4.  It supports multiValued and polygon shapes.
+      For more information about this and other Spatial fields new to Solr 4, see:
+      http://wiki.apache.org/solr/SolrAdaptersForLuceneSpatial4
+    -->
+    <fieldType name="location_rpt" class="solr.SpatialRecursivePrefixTreeFieldType"
+        geo="true" distErrPct="0.025" maxDistErr="0.000009" units="degrees" />
+
+   <!-- Money/currency field type. See http://wiki.apache.org/solr/MoneyFieldType
+        Parameters:
+          defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
+          precisionStep:   Specifies the precisionStep for the TrieLong field used for the amount
+          providerClass:   Lets you plug in other exchange provider backend:
+                           solr.FileExchangeRateProvider is the default and takes one parameter:
+                             currencyConfig: name of an xml file holding exchange rates
+                           solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
+                             ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
+                             refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
+   -->
+    <fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
+             
+
+
+   <!-- some examples for different languages (generally ordered by ISO code) -->
+
+    <!-- Arabic -->
+    <fieldType name="text_ar" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- for any non-arabic -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ar.txt" enablePositionIncrements="true"/>
+        <!-- normalizes ﻯ to ﻱ, etc -->
+        <filter class="solr.ArabicNormalizationFilterFactory"/>
+        <filter class="solr.ArabicStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Bulgarian -->
+    <fieldType name="text_bg" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/> 
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_bg.txt" enablePositionIncrements="true"/>
+        <filter class="solr.BulgarianStemFilterFactory"/>       
+      </analyzer>
+    </fieldType>
+    
+    <!-- Catalan -->
+    <fieldType name="text_ca" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- removes l', etc -->
+        <filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_ca.txt"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ca.txt" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Catalan"/>       
+      </analyzer>
+    </fieldType>
+    
+    <!-- CJK bigram (see text_ja for a Japanese configuration using morphological analysis) -->
+    <fieldType name="text_cjk" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- normalize width before bigram, as e.g. half-width dakuten combine  -->
+        <filter class="solr.CJKWidthFilterFactory"/>
+        <!-- for any non-CJK -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.CJKBigramFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Czech -->
+    <fieldType name="text_cz" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_cz.txt" enablePositionIncrements="true"/>
+        <filter class="solr.CzechStemFilterFactory"/>       
+      </analyzer>
+    </fieldType>
+    
+    <!-- Danish -->
+    <fieldType name="text_da" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_da.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Danish"/>       
+      </analyzer>
+    </fieldType>
+    
+    <!-- German -->
+    <fieldType name="text_de" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_de.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.GermanNormalizationFilterFactory"/>
+        <filter class="solr.GermanLightStemFilterFactory"/>
+        <!-- less aggressive: <filter class="solr.GermanMinimalStemFilterFactory"/> -->
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="German2"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Greek -->
+    <fieldType name="text_el" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- greek specific lowercase for sigma -->
+        <filter class="solr.GreekLowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="false" words="lang/stopwords_el.txt" enablePositionIncrements="true"/>
+        <filter class="solr.GreekStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Spanish -->
+    <fieldType name="text_es" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_es.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SpanishLightStemFilterFactory"/>
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="Spanish"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Basque -->
+    <fieldType name="text_eu" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_eu.txt" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Basque"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Persian -->
+    <fieldType name="text_fa" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <!-- for ZWNJ -->
+        <charFilter class="solr.PersianCharFilterFactory"/>
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.ArabicNormalizationFilterFactory"/>
+        <filter class="solr.PersianNormalizationFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_fa.txt" enablePositionIncrements="true"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Finnish -->
+    <fieldType name="text_fi" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_fi.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Finnish"/>
+        <!-- less aggressive: <filter class="solr.FinnishLightStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- French -->
+    <fieldType name="text_fr" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- removes l', etc -->
+        <filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_fr.txt"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_fr.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.FrenchLightStemFilterFactory"/>
+        <!-- less aggressive: <filter class="solr.FrenchMinimalStemFilterFactory"/> -->
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="French"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Irish -->
+    <fieldType name="text_ga" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- removes d', etc -->
+        <filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_ga.txt"/>
+        <!-- removes n-, etc. position increments is intentionally false! -->
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/hyphenations_ga.txt" enablePositionIncrements="false"/>
+        <filter class="solr.IrishLowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ga.txt" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Irish"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Galician -->
+    <fieldType name="text_gl" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_gl.txt" enablePositionIncrements="true"/>
+        <filter class="solr.GalicianStemFilterFactory"/>
+        <!-- less aggressive: <filter class="solr.GalicianMinimalStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Hindi -->
+    <fieldType name="text_hi" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <!-- normalizes unicode representation -->
+        <filter class="solr.IndicNormalizationFilterFactory"/>
+        <!-- normalizes variation in spelling -->
+        <filter class="solr.HindiNormalizationFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_hi.txt" enablePositionIncrements="true"/>
+        <filter class="solr.HindiStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Hungarian -->
+    <fieldType name="text_hu" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_hu.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Hungarian"/>
+        <!-- less aggressive: <filter class="solr.HungarianLightStemFilterFactory"/> -->   
+      </analyzer>
+    </fieldType>
+    
+    <!-- Armenian -->
+    <fieldType name="text_hy" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_hy.txt" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Armenian"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Indonesian -->
+    <fieldType name="text_id" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_id.txt" enablePositionIncrements="true"/>
+        <!-- for a less aggressive approach (only inflectional suffixes), set stemDerivational to false -->
+        <filter class="solr.IndonesianStemFilterFactory" stemDerivational="true"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Italian -->
+    <fieldType name="text_it" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- removes l', etc -->
+        <filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_it.txt"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_it.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.ItalianLightStemFilterFactory"/>
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="Italian"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Japanese using morphological analysis (see text_cjk for a configuration using bigramming)
+
+         NOTE: If you want to optimize search for precision, use default operator AND in your query
+         parser config with <solrQueryParser defaultOperator="AND"/> further down in this file.  Use 
+         OR if you would like to optimize for recall (default).
+    -->
+    <fieldType name="text_ja" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false">
+      <analyzer>
+      <!-- Kuromoji Japanese morphological analyzer/tokenizer (JapaneseTokenizer)
+
+           Kuromoji has a search mode (default) that does segmentation useful for search.  A heuristic
+           is used to segment compounds into its parts and the compound itself is kept as synonym.
+
+           Valid values for attribute mode are:
+              normal: regular segmentation
+              search: segmentation useful for search with synonyms compounds (default)
+            extended: same as search mode, but unigrams unknown words (experimental)
+
+           For some applications it might be good to use search mode for indexing and normal mode for
+           queries to reduce recall and prevent parts of compounds from being matched and highlighted.
+           Use <analyzer type="index"> and <analyzer type="query"> for this and mode normal in query.
+
+           Kuromoji also has a convenient user dictionary feature that allows overriding the statistical
+           model with your own entries for segmentation, part-of-speech tags and readings without a need
+           to specify weights.  Notice that user dictionaries have not been subject to extensive testing.
+
+           User dictionary attributes are:
+                     userDictionary: user dictionary filename
+             userDictionaryEncoding: user dictionary encoding (default is UTF-8)
+
+           See lang/userdict_ja.txt for a sample user dictionary file.
+
+           Punctuation characters are discarded by default.  Use discardPunctuation="false" to keep them.
+
+           See http://wiki.apache.org/solr/JapaneseLanguageSupport for more on Japanese language support.
+        -->
+        <tokenizer class="solr.JapaneseTokenizerFactory" mode="search"/>
+        <!--<tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>-->
+        <!-- Reduces inflected verbs and adjectives to their base/dictionary forms (辞書形) -->
+        <filter class="solr.JapaneseBaseFormFilterFactory"/>
+        <!-- Removes tokens with certain part-of-speech tags -->
+        <filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt" enablePositionIncrements="true"/>
+        <!-- Normalizes full-width romaji to half-width and half-width kana to full-width (Unicode NFKC subset) -->
+        <filter class="solr.CJKWidthFilterFactory"/>
+        <!-- Removes common tokens typically not useful for search, but have a negative effect on ranking -->
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt" enablePositionIncrements="true" />
+        <!-- Normalizes common katakana spelling variations by removing any last long sound character (U+30FC) -->
+        <filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
+        <!-- Lower-cases romaji characters -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Latvian -->
+    <fieldType name="text_lv" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_lv.txt" enablePositionIncrements="true"/>
+        <filter class="solr.LatvianStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Dutch -->
+    <fieldType name="text_nl" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_nl.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.StemmerOverrideFilterFactory" dictionary="lang/stemdict_nl.txt" ignoreCase="false"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Dutch"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Norwegian -->
+    <fieldType name="text_no" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_no.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Norwegian"/>
+        <!-- less aggressive: <filter class="solr.NorwegianLightStemFilterFactory"/> -->
+        <!-- singular/plural: <filter class="solr.NorwegianMinimalStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Portuguese -->
+    <fieldType name="text_pt" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_pt.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.PortugueseLightStemFilterFactory"/>
+        <!-- less aggressive: <filter class="solr.PortugueseMinimalStemFilterFactory"/> -->
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="Portuguese"/> -->
+        <!-- most aggressive: <filter class="solr.PortugueseStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Romanian -->
+    <fieldType name="text_ro" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ro.txt" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Romanian"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Russian -->
+    <fieldType name="text_ru" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ru.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Russian"/>
+        <!-- less aggressive: <filter class="solr.RussianLightStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Swedish -->
+    <fieldType name="text_sv" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_sv.txt" format="snowball" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Swedish"/>
+        <!-- less aggressive: <filter class="solr.SwedishLightStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Thai -->
+    <fieldType name="text_th" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.ThaiWordFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_th.txt" enablePositionIncrements="true"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Turkish -->
+    <fieldType name="text_tr" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.TurkishLowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="false" words="lang/stopwords_tr.txt" enablePositionIncrements="true"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Turkish"/>
+      </analyzer>
+    </fieldType>
+
+ </types>
+  
+  <!-- Similarity is the scoring routine for each document vs. a query.
+       A custom Similarity or SimilarityFactory may be specified here, but 
+       the default is fine for most applications.  
+       For more info: http://wiki.apache.org/solr/SchemaXml#Similarity
+    -->
+  <!--
+     <similarity class="com.example.solr.CustomSimilarityFactory">
+       <str name="paramkey">param value</str>
+     </similarity>
+    -->
+
+</schema>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/scripts.conf b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/scripts.conf
new file mode 100644
index 0000000..f58b262
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/scripts.conf
@@ -0,0 +1,24 @@
+# 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.
+
+user=
+solr_hostname=localhost
+solr_port=8983
+rsyncd_port=18983
+data_dir=
+webapp_name=solr
+master_host=
+master_data_dir=
+master_status_dir=
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/solrconfig.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/solrconfig.xml
new file mode 100644
index 0000000..f02039f
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/solrconfig.xml
@@ -0,0 +1,1873 @@
+<?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.
+-->
+
+<!-- 
+     For more details about configurations options that may appear in
+     this file, see http://wiki.apache.org/solr/SolrConfigXml. 
+-->
+<config>
+  <!-- In all configuration below, a prefix of "solr." for class names
+       is an alias that causes solr to search appropriate packages,
+       including org.apache.solr.(search|update|request|core|analysis)
+
+       You may also specify a fully qualified Java classname if you
+       have your own custom plugins.
+    -->
+
+  <!-- Controls what version of Lucene various components of Solr
+       adhere to.  Generally, you want to use the latest version to
+       get all bug fixes and improvements. It is highly recommended
+       that you fully re-index after changing this setting as it can
+       affect both how text is indexed and queried.
+  -->
+  <luceneMatchVersion>4.7</luceneMatchVersion>
+
+  <!-- <lib/> directives can be used to instruct Solr to load an Jars
+       identified and use them to resolve any "plugins" specified in
+       your solrconfig.xml or schema.xml (ie: Analyzers, Request
+       Handlers, etc...).
+
+       All directories and paths are resolved relative to the
+       instanceDir.
+
+       Please note that <lib/> directives are processed in the order
+       that they appear in your solrconfig.xml file, and are "stacked" 
+       on top of each other when building a ClassLoader - so if you have 
+       plugin jars with dependencies on other jars, the "lower level" 
+       dependency jars should be loaded first.
+
+       If a "./lib" directory exists in your instanceDir, all files
+       found in it are included as if you had used the following
+       syntax...
+       
+              <lib dir="./lib" />
+    -->
+
+  <!-- A 'dir' option by itself adds any files found in the directory 
+       to the classpath, this is useful for including all jars in a
+       directory.
+
+       When a 'regex' is specified in addition to a 'dir', only the
+       files in that directory which completely match the regex
+       (anchored on both ends) will be included.
+
+       If a 'dir' option (with or without a regex) is used and nothing
+       is found that matches, a warning will be logged.
+
+       The examples below can be used to load some solr-contribs along 
+       with their external dependencies.
+    -->
+  <lib dir="../../../contrib/extraction/lib" regex=".*\.jar" />
+  <lib dir="../../../dist/" regex="solr-cell-\d.*\.jar" />
+
+  <lib dir="../../../contrib/clustering/lib/" regex=".*\.jar" />
+  <lib dir="../../../dist/" regex="solr-clustering-\d.*\.jar" />
+
+  <lib dir="../../../contrib/langid/lib/" regex=".*\.jar" />
+  <lib dir="../../../dist/" regex="solr-langid-\d.*\.jar" />
+
+  <lib dir="../../../contrib/velocity/lib" regex=".*\.jar" />
+  <lib dir="../../../dist/" regex="solr-velocity-\d.*\.jar" />
+
+  <!-- an exact 'path' can be used instead of a 'dir' to specify a 
+       specific jar file.  This will cause a serious error to be logged 
+       if it can't be loaded.
+    -->
+  <!--
+     <lib path="../a-jar-that-does-not-exist.jar" /> 
+  -->
+  
+  <!-- Data Directory
+
+       Used to specify an alternate directory to hold all index data
+       other than the default ./data under the Solr home.  If
+       replication is in use, this should match the replication
+       configuration.
+    -->
+  <dataDir>${solr.data.dir:}</dataDir>
+
+
+  <!-- The DirectoryFactory to use for indexes.
+       
+       solr.StandardDirectoryFactory is filesystem
+       based and tries to pick the best implementation for the current
+       JVM and platform.  solr.NRTCachingDirectoryFactory, the default,
+       wraps solr.StandardDirectoryFactory and caches small files in memory
+       for better NRT performance.
+
+       One can force a particular implementation via solr.MMapDirectoryFactory,
+       solr.NIOFSDirectoryFactory, or solr.SimpleFSDirectoryFactory.
+
+       solr.RAMDirectoryFactory is memory based, not
+       persistent, and doesn't work with replication.
+    -->
+  <directoryFactory name="DirectoryFactory" 
+                    class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}">
+    
+         
+    <!-- These will be used if you are using the solr.HdfsDirectoryFactory,
+         otherwise they will be ignored. If you don't plan on using hdfs,
+         you can safely remove this section. -->      
+    <!-- The root directory that collection data should be written to. -->     
+    <str name="solr.hdfs.home">${solr.hdfs.home:}</str>
+    <!-- The hadoop configuration files to use for the hdfs client. -->    
+    <str name="solr.hdfs.confdir">${solr.hdfs.confdir:}</str>
+    <!-- Enable/Disable the hdfs cache. -->    
+    <str name="solr.hdfs.blockcache.enabled">${solr.hdfs.blockcache.enabled:true}</str>
+    
+  </directoryFactory> 
+
+  <!-- The CodecFactory for defining the format of the inverted index.
+       The default implementation is SchemaCodecFactory, which is the official Lucene
+       index format, but hooks into the schema to provide per-field customization of
+       the postings lists and per-document values in the fieldType element
+       (postingsFormat/docValuesFormat). Note that most of the alternative implementations
+       are experimental, so if you choose to customize the index format, its a good
+       idea to convert back to the official format e.g. via IndexWriter.addIndexes(IndexReader)
+       before upgrading to a newer version to avoid unnecessary reindexing.
+  -->
+  <codecFactory class="solr.SchemaCodecFactory"/>
+
+  <!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>:
+  
+       <schemaFactory class="ManagedIndexSchemaFactory">
+         <bool name="mutable">true</bool>
+         <str name="managedSchemaResourceName">managed-schema</str>
+       </schemaFactory>
+       
+       When ManagedIndexSchemaFactory is specified, Solr will load the schema from
+       he resource named in 'managedSchemaResourceName', rather than from schema.xml.
+       Note that the managed schema resource CANNOT be named schema.xml.  If the managed
+       schema does not exist, Solr will create it after reading schema.xml, then rename
+       'schema.xml' to 'schema.xml.bak'. 
+       
+       Do NOT hand edit the managed schema - external modifications will be ignored and
+       overwritten as a result of schema modification REST API calls.
+
+       When ManagedIndexSchemaFactory is specified with mutable = true, schema
+       modification REST API calls will be allowed; otherwise, error responses will be
+       sent back for these requests. 
+  -->
+  <schemaFactory class="ClassicIndexSchemaFactory"/>
+
+  <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+       Index Config - These settings control low-level behavior of indexing
+       Most example settings here show the default value, but are commented
+       out, to more easily see where customizations have been made.
+       
+       Note: This replaces <indexDefaults> and <mainIndex> from older versions
+       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+  <indexConfig>
+    <!-- maxFieldLength was removed in 4.0. To get similar behavior, include a 
+         LimitTokenCountFilterFactory in your fieldType definition. E.g. 
+     <filter class="solr.LimitTokenCountFilterFactory" maxTokenCount="10000"/>
+    -->
+    <!-- Maximum time to wait for a write lock (ms) for an IndexWriter. Default: 1000 -->
+    <!-- <writeLockTimeout>1000</writeLockTimeout>  -->
+
+    <!-- The maximum number of simultaneous threads that may be
+         indexing documents at once in IndexWriter; if more than this
+         many threads arrive they will wait for others to finish.
+         Default in Solr/Lucene is 8. -->
+    <!-- <maxIndexingThreads>8</maxIndexingThreads>  -->
+
+    <!-- Expert: Enabling compound file will use less files for the index, 
+         using fewer file descriptors on the expense of performance decrease. 
+         Default in Lucene is "true". Default in Solr is "false" (since 3.6) -->
+    <!-- <useCompoundFile>false</useCompoundFile> -->
+
+    <!-- ramBufferSizeMB sets the amount of RAM that may be used by Lucene
+         indexing for buffering added documents and deletions before they are
+         flushed to the Directory.
+         maxBufferedDocs sets a limit on the number of documents buffered
+         before flushing.
+         If both ramBufferSizeMB and maxBufferedDocs is set, then
+         Lucene will flush based on whichever limit is hit first.
+         The default is 100 MB.  -->
+    <!-- <ramBufferSizeMB>100</ramBufferSizeMB> -->
+    <!-- <maxBufferedDocs>1000</maxBufferedDocs> -->
+
+    <!-- Expert: Merge Policy 
+         The Merge Policy in Lucene controls how merging of segments is done.
+         The default since Solr/Lucene 3.3 is TieredMergePolicy.
+         The default since Lucene 2.3 was the LogByteSizeMergePolicy,
+         Even older versions of Lucene used LogDocMergePolicy.
+      -->
+    <!--
+        <mergePolicy class="org.apache.lucene.index.TieredMergePolicy">
+          <int name="maxMergeAtOnce">10</int>
+          <int name="segmentsPerTier">10</int>
+        </mergePolicy>
+      -->
+       
+    <!-- Merge Factor
+         The merge factor controls how many segments will get merged at a time.
+         For TieredMergePolicy, mergeFactor is a convenience parameter which
+         will set both MaxMergeAtOnce and SegmentsPerTier at once.
+         For LogByteSizeMergePolicy, mergeFactor decides how many new segments
+         will be allowed before they are merged into one.
+         Default is 10 for both merge policies.
+      -->
+    <!-- 
+    <mergeFactor>10</mergeFactor>
+      -->
+
+    <!-- Expert: Merge Scheduler
+         The Merge Scheduler in Lucene controls how merges are
+         performed.  The ConcurrentMergeScheduler (Lucene 2.3 default)
+         can perform merges in the background using separate threads.
+         The SerialMergeScheduler (Lucene 2.2 default) does not.
+     -->
+    <!-- 
+       <mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/>
+       -->
+
+    <!-- LockFactory 
+
+         This option specifies which Lucene LockFactory implementation
+         to use.
+      
+         single = SingleInstanceLockFactory - suggested for a
+                  read-only index or when there is no possibility of
+                  another process trying to modify the index.
+         native = NativeFSLockFactory - uses OS native file locking.
+                  Do not use when multiple solr webapps in the same
+                  JVM are attempting to share a single index.
+         simple = SimpleFSLockFactory  - uses a plain file for locking
+
+         Defaults: 'native' is default for Solr3.6 and later, otherwise
+                   'simple' is the default
+
+         More details on the nuances of each LockFactory...
+         http://wiki.apache.org/lucene-java/AvailableLockFactories
+    -->
+    <lockType>${solr.lock.type:native}</lockType>
+
+    <!-- Unlock On Startup
+
+         If true, unlock any held write or commit locks on startup.
+         This defeats the locking mechanism that allows multiple
+         processes to safely access a lucene index, and should be used
+         with care. Default is "false".
+
+         This is not needed if lock type is 'single'
+     -->
+    <!--
+    <unlockOnStartup>false</unlockOnStartup>
+      -->
+    
+    <!-- Expert: Controls how often Lucene loads terms into memory
+         Default is 128 and is likely good for most everyone.
+      -->
+    <!-- <termIndexInterval>128</termIndexInterval> -->
+
+    <!-- If true, IndexReaders will be opened/reopened from the IndexWriter
+         instead of from the Directory. Hosts in a master/slave setup
+         should have this set to false while those in a SolrCloud
+         cluster need to be set to true. Default: true
+      -->
+    <!-- 
+    <nrtMode>true</nrtMode>
+      -->
+
+    <!-- Commit Deletion Policy
+         Custom deletion policies can be specified here. The class must
+         implement org.apache.lucene.index.IndexDeletionPolicy.
+
+         The default Solr IndexDeletionPolicy implementation supports
+         deleting index commit points on number of commits, age of
+         commit point and optimized status.
+         
+         The latest commit point should always be preserved regardless
+         of the criteria.
+    -->
+    <!-- 
+    <deletionPolicy class="solr.SolrDeletionPolicy">
+    -->
+      <!-- The number of commit points to be kept -->
+      <!-- <str name="maxCommitsToKeep">1</str> -->
+      <!-- The number of optimized commit points to be kept -->
+      <!-- <str name="maxOptimizedCommitsToKeep">0</str> -->
+      <!--
+          Delete all commit points once they have reached the given age.
+          Supports DateMathParser syntax e.g.
+        -->
+      <!--
+         <str name="maxCommitAge">30MINUTES</str>
+         <str name="maxCommitAge">1DAY</str>
+      -->
+    <!-- 
+    </deletionPolicy>
+    -->
+
+    <!-- Lucene Infostream
+       
+         To aid in advanced debugging, Lucene provides an "InfoStream"
+         of detailed information when indexing.
+
+         Setting the value to true will instruct the underlying Lucene
+         IndexWriter to write its info stream to solr's log. By default,
+         this is enabled here, and controlled through log4j.properties.
+      -->
+     <infoStream>true</infoStream>
+  </indexConfig>
+
+
+  <!-- JMX
+       
+       This example enables JMX if and only if an existing MBeanServer
+       is found, use this if you want to configure JMX through JVM
+       parameters. Remove this to disable exposing Solr configuration
+       and statistics to JMX.
+
+       For more details see http://wiki.apache.org/solr/SolrJmx
+    -->
+  <jmx />
+  <!-- If you want to connect to a particular server, specify the
+       agentId 
+    -->
+  <!-- <jmx agentId="myAgent" /> -->
+  <!-- If you want to start a new MBeanServer, specify the serviceUrl -->
+  <!-- <jmx serviceUrl="service:jmx:rmi:///jndi/rmi://localhost:9999/solr"/>
+    -->
+
+  <!-- The default high-performance update handler -->
+  <updateHandler class="solr.DirectUpdateHandler2">
+
+    <!-- Enables a transaction log, used for real-time get, durability, and
+         and solr cloud replica recovery.  The log can grow as big as
+         uncommitted changes to the index, so use of a hard autoCommit
+         is recommended (see below).
+         "dir" - the target directory for transaction logs, defaults to the
+                solr data directory.  --> 
+    <updateLog>
+      <str name="dir">${solr.ulog.dir:}</str>
+    </updateLog>
+ 
+    <!-- AutoCommit
+
+         Perform a hard commit automatically under certain conditions.
+         Instead of enabling autoCommit, consider using "commitWithin"
+         when adding documents. 
+
+         http://wiki.apache.org/solr/UpdateXmlMessages
+
+         maxDocs - Maximum number of documents to add since the last
+                   commit before automatically triggering a new commit.
+
+         maxTime - Maximum amount of time in ms that is allowed to pass
+                   since a document was added before automatically
+                   triggering a new commit. 
+         openSearcher - if false, the commit causes recent index changes
+           to be flushed to stable storage, but does not cause a new
+           searcher to be opened to make those changes visible.
+
+         If the updateLog is enabled, then it's highly recommended to
+         have some sort of hard autoCommit to limit the log size.
+      -->
+     <autoCommit> 
+       <maxTime>${solr.autoCommit.maxTime:15000}</maxTime> 
+       <openSearcher>false</openSearcher> 
+     </autoCommit>
+
+    <!-- softAutoCommit is like autoCommit except it causes a
+         'soft' commit which only ensures that changes are visible
+         but does not ensure that data is synced to disk.  This is
+         faster and more near-realtime friendly than a hard commit.
+      -->
+
+     <autoSoftCommit> 
+       <maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime> 
+     </autoSoftCommit>
+
+    <!-- Update Related Event Listeners
+         
+         Various IndexWriter related events can trigger Listeners to
+         take actions.
+
+         postCommit - fired after every commit or optimize command
+         postOptimize - fired after every optimize command
+      -->
+    <!-- The RunExecutableListener executes an external command from a
+         hook such as postCommit or postOptimize.
+         
+         exe - the name of the executable to run
+         dir - dir to use as the current working directory. (default=".")
+         wait - the calling thread waits until the executable returns. 
+                (default="true")
+         args - the arguments to pass to the program.  (default is none)
+         env - environment variables to set.  (default is none)
+      -->
+    <!-- This example shows how RunExecutableListener could be used
+         with the script based replication...
+         http://wiki.apache.org/solr/CollectionDistribution
+      -->
+    <!--
+       <listener event="postCommit" class="solr.RunExecutableListener">
+         <str name="exe">solr/bin/snapshooter</str>
+         <str name="dir">.</str>
+         <bool name="wait">true</bool>
+         <arr name="args"> <str>arg1</str> <str>arg2</str> </arr>
+         <arr name="env"> <str>MYVAR=val1</str> </arr>
+       </listener>
+      -->
+
+  </updateHandler>
+  
+  <!-- IndexReaderFactory
+
+       Use the following format to specify a custom IndexReaderFactory,
+       which allows for alternate IndexReader implementations.
+
+       ** Experimental Feature **
+
+       Please note - Using a custom IndexReaderFactory may prevent
+       certain other features from working. The API to
+       IndexReaderFactory may change without warning or may even be
+       removed from future releases if the problems cannot be
+       resolved.
+
+
+       ** Features that may not work with custom IndexReaderFactory **
+
+       The ReplicationHandler assumes a disk-resident index. Using a
+       custom IndexReader implementation may cause incompatibility
+       with ReplicationHandler and may cause replication to not work
+       correctly. See SOLR-1366 for details.
+
+    -->
+  <!--
+  <indexReaderFactory name="IndexReaderFactory" class="package.class">
+    <str name="someArg">Some Value</str>
+  </indexReaderFactory >
+  -->
+  <!-- By explicitly declaring the Factory, the termIndexDivisor can
+       be specified.
+    -->
+  <!--
+     <indexReaderFactory name="IndexReaderFactory" 
+                         class="solr.StandardIndexReaderFactory">
+       <int name="setTermIndexDivisor">12</int>
+     </indexReaderFactory >
+    -->
+
+  <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+       Query section - these settings control query time things like caches
+       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+  <query>
+    <!-- Max Boolean Clauses
+
+         Maximum number of clauses in each BooleanQuery,  an exception
+         is thrown if exceeded.
+
+         ** WARNING **
+         
+         This option actually modifies a global Lucene property that
+         will affect all SolrCores.  If multiple solrconfig.xml files
+         disagree on this property, the value at any given moment will
+         be based on the last SolrCore to be initialized.
+         
+      -->
+    <maxBooleanClauses>1024</maxBooleanClauses>
+
+
+    <!-- Solr Internal Query Caches
+
+         There are two implementations of cache available for Solr,
+         LRUCache, based on a synchronized LinkedHashMap, and
+         FastLRUCache, based on a ConcurrentHashMap.  
+
+         FastLRUCache has faster gets and slower puts in single
+         threaded operation and thus is generally faster than LRUCache
+         when the hit ratio of the cache is high (> 75%), and may be
+         faster under other scenarios on multi-cpu systems.
+    -->
+
+    <!-- Filter Cache
+
+         Cache used by SolrIndexSearcher for filters (DocSets),
+         unordered sets of *all* documents that match a query.  When a
+         new searcher is opened, its caches may be prepopulated or
+         "autowarmed" using data from caches in the old searcher.
+         autowarmCount is the number of items to prepopulate.  For
+         LRUCache, the autowarmed items will be the most recently
+         accessed items.
+
+         Parameters:
+           class - the SolrCache implementation LRUCache or
+               (LRUCache or FastLRUCache)
+           size - the maximum number of entries in the cache
+           initialSize - the initial capacity (number of entries) of
+               the cache.  (see java.util.HashMap)
+           autowarmCount - the number of entries to prepopulate from
+               and old cache.  
+      -->
+    <filterCache class="solr.FastLRUCache"
+                 size="512"
+                 initialSize="512"
+                 autowarmCount="0"/>
+
+    <!-- Query Result Cache
+         
+         Caches results of searches - ordered lists of document ids
+         (DocList) based on a query, a sort, and the range of documents requested.  
+      -->
+    <queryResultCache class="solr.LRUCache"
+                     size="512"
+                     initialSize="512"
+                     autowarmCount="0"/>
+   
+    <!-- Document Cache
+
+         Caches Lucene Document objects (the stored fields for each
+         document).  Since Lucene internal document ids are transient,
+         this cache will not be autowarmed.  
+      -->
+    <documentCache class="solr.LRUCache"
+                   size="512"
+                   initialSize="512"
+                   autowarmCount="0"/>
+    
+    <!-- custom cache currently used by block join --> 
+    <cache name="perSegFilter"
+      class="solr.search.LRUCache"
+      size="10"
+      initialSize="0"
+      autowarmCount="10"
+      regenerator="solr.NoOpRegenerator" />
+
+    <!-- Field Value Cache
+         
+         Cache used to hold field values that are quickly accessible
+         by document id.  The fieldValueCache is created by default
+         even if not configured here.
+      -->
+    <!--
+       <fieldValueCache class="solr.FastLRUCache"
+                        size="512"
+                        autowarmCount="128"
+                        showItems="32" />
+      -->
+
+    <!-- Custom Cache
+
+         Example of a generic cache.  These caches may be accessed by
+         name through SolrIndexSearcher.getCache(),cacheLookup(), and
+         cacheInsert().  The purpose is to enable easy caching of
+         user/application level data.  The regenerator argument should
+         be specified as an implementation of solr.CacheRegenerator 
+         if autowarming is desired.  
+      -->
+    <!--
+       <cache name="myUserCache"
+              class="solr.LRUCache"
+              size="4096"
+              initialSize="1024"
+              autowarmCount="1024"
+              regenerator="com.mycompany.MyRegenerator"
+              />
+      -->
+
+
+    <!-- Lazy Field Loading
+
+         If true, stored fields that are not requested will be loaded
+         lazily.  This can result in a significant speed improvement
+         if the usual case is to not load all stored fields,
+         especially if the skipped fields are large compressed text
+         fields.
+    -->
+    <enableLazyFieldLoading>true</enableLazyFieldLoading>
+
+   <!-- Use Filter For Sorted Query
+
+        A possible optimization that attempts to use a filter to
+        satisfy a search.  If the requested sort does not include
+        score, then the filterCache will be checked for a filter
+        matching the query. If found, the filter will be used as the
+        source of document ids, and then the sort will be applied to
+        that.
+
+        For most situations, this will not be useful unless you
+        frequently get the same search repeatedly with different sort
+        options, and none of them ever use "score"
+     -->
+   <!--
+      <useFilterForSortedQuery>true</useFilterForSortedQuery>
+     -->
+
+   <!-- Result Window Size
+
+        An optimization for use with the queryResultCache.  When a search
+        is requested, a superset of the requested number of document ids
+        are collected.  For example, if a search for a particular query
+        requests matching documents 10 through 19, and queryWindowSize is 50,
+        then documents 0 through 49 will be collected and cached.  Any further
+        requests in that range can be satisfied via the cache.  
+     -->
+   <queryResultWindowSize>20</queryResultWindowSize>
+
+   <!-- Maximum number of documents to cache for any entry in the
+        queryResultCache. 
+     -->
+   <queryResultMaxDocsCached>200</queryResultMaxDocsCached>
+
+   <!-- Query Related Event Listeners
+
+        Various IndexSearcher related events can trigger Listeners to
+        take actions.
+
+        newSearcher - fired whenever a new searcher is being prepared
+        and there is a current searcher handling requests (aka
+        registered).  It can be used to prime certain caches to
+        prevent long request times for certain requests.
+
+        firstSearcher - fired whenever a new searcher is being
+        prepared but there is no current registered searcher to handle
+        requests or to gain autowarming data from.
+
+        
+     -->
+    <!-- QuerySenderListener takes an array of NamedList and executes a
+         local query request for each NamedList in sequence. 
+      -->
+    <listener event="newSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <!--
+           <lst><str name="q">solr</str><str name="sort">price asc</str></lst>
+           <lst><str name="q">rocks</str><str name="sort">weight asc</str></lst>
+          -->
+      </arr>
+    </listener>
+    <listener event="firstSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <lst>
+          <str name="q">static firstSearcher warming in solrconfig.xml</str>
+        </lst>
+      </arr>
+    </listener>
+
+    <!-- Use Cold Searcher
+
+         If a search request comes in and there is no current
+         registered searcher, then immediately register the still
+         warming searcher and use it.  If "false" then all requests
+         will block until the first searcher is done warming.
+      -->
+    <useColdSearcher>false</useColdSearcher>
+
+    <!-- Max Warming Searchers
+         
+         Maximum number of searchers that may be warming in the
+         background concurrently.  An error is returned if this limit
+         is exceeded.
+
+         Recommend values of 1-2 for read-only slaves, higher for
+         masters w/o cache warming.
+      -->
+    <maxWarmingSearchers>2</maxWarmingSearchers>
+
+  </query>
+
+
+  <!-- Request Dispatcher
+
+       This section contains instructions for how the SolrDispatchFilter
+       should behave when processing requests for this SolrCore.
+
+       handleSelect is a legacy option that affects the behavior of requests
+       such as /select?qt=XXX
+
+       handleSelect="true" will cause the SolrDispatchFilter to process
+       the request and dispatch the query to a handler specified by the 
+       "qt" param, assuming "/select" isn't already registered.
+
+       handleSelect="false" will cause the SolrDispatchFilter to
+       ignore "/select" requests, resulting in a 404 unless a handler
+       is explicitly registered with the name "/select"
+
+       handleSelect="true" is not recommended for new users, but is the default
+       for backwards compatibility
+    -->
+  <requestDispatcher handleSelect="false" >
+    <!-- Request Parsing
+
+         These settings indicate how Solr Requests may be parsed, and
+         what restrictions may be placed on the ContentStreams from
+         those requests
+
+         enableRemoteStreaming - enables use of the stream.file
+         and stream.url parameters for specifying remote streams.
+
+         multipartUploadLimitInKB - specifies the max size (in KiB) of
+         Multipart File Uploads that Solr will allow in a Request.
+         
+         formdataUploadLimitInKB - specifies the max size (in KiB) of
+         form data (application/x-www-form-urlencoded) sent via
+         POST. You can use POST to pass request parameters not
+         fitting into the URL.
+         
+         addHttpRequestToContext - if set to true, it will instruct
+         the requestParsers to include the original HttpServletRequest
+         object in the context map of the SolrQueryRequest under the 
+         key "httpRequest". It will not be used by any of the existing
+         Solr components, but may be useful when developing custom 
+         plugins.
+         
+         *** WARNING ***
+         The settings below authorize Solr to fetch remote files, You
+         should make sure your system has some authentication before
+         using enableRemoteStreaming="true"
+
+      --> 
+    <requestParsers enableRemoteStreaming="true" 
+                    multipartUploadLimitInKB="2048000"
+                    formdataUploadLimitInKB="2048"
+                    addHttpRequestToContext="false"/>
+
+    <!-- HTTP Caching
+
+         Set HTTP caching related parameters (for proxy caches and clients).
+
+         The options below instruct Solr not to output any HTTP Caching
+         related headers
+      -->
+    <httpCaching never304="true" />
+    <!-- If you include a <cacheControl> directive, it will be used to
+         generate a Cache-Control header (as well as an Expires header
+         if the value contains "max-age=")
+         
+         By default, no Cache-Control header is generated.
+         
+         You can use the <cacheControl> option even if you have set
+         never304="true"
+      -->
+    <!--
+       <httpCaching never304="true" >
+         <cacheControl>max-age=30, public</cacheControl> 
+       </httpCaching>
+      -->
+    <!-- To enable Solr to respond with automatically generated HTTP
+         Caching headers, and to response to Cache Validation requests
+         correctly, set the value of never304="false"
+         
+         This will cause Solr to generate Last-Modified and ETag
+         headers based on the properties of the Index.
+
+         The following options can also be specified to affect the
+         values of these headers...
+
+         lastModFrom - the default value is "openTime" which means the
+         Last-Modified value (and validation against If-Modified-Since
+         requests) will all be relative to when the current Searcher
+         was opened.  You can change it to lastModFrom="dirLastMod" if
+         you want the value to exactly correspond to when the physical
+         index was last modified.
+
+         etagSeed="..." is an option you can change to force the ETag
+         header (and validation against If-None-Match requests) to be
+         different even if the index has not changed (ie: when making
+         significant changes to your config file)
+
+         (lastModifiedFrom and etagSeed are both ignored if you use
+         the never304="true" option)
+      -->
+    <!--
+       <httpCaching lastModifiedFrom="openTime"
+                    etagSeed="Solr">
+         <cacheControl>max-age=30, public</cacheControl> 
+       </httpCaching>
+      -->
+  </requestDispatcher>
+
+  <!-- Request Handlers 
+
+       http://wiki.apache.org/solr/SolrRequestHandler
+
+       Incoming queries will be dispatched to a specific handler by name
+       based on the path specified in the request.
+
+       Legacy behavior: If the request path uses "/select" but no Request
+       Handler has that name, and if handleSelect="true" has been specified in
+       the requestDispatcher, then the Request Handler is dispatched based on
+       the qt parameter.  Handlers without a leading '/' are accessed this way
+       like so: http://host/app/[core/]select?qt=name  If no qt is
+       given, then the requestHandler that declares default="true" will be
+       used or the one named "standard".
+
+       If a Request Handler is declared with startup="lazy", then it will
+       not be initialized until the first request that uses it.
+
+    -->
+  <!-- SearchHandler
+
+       http://wiki.apache.org/solr/SearchHandler
+
+       For processing Search Queries, the primary Request Handler
+       provided with Solr is "SearchHandler" It delegates to a sequent
+       of SearchComponents (see below) and supports distributed
+       queries across multiple shards
+    -->
+  <requestHandler name="/select" class="solr.SearchHandler">
+    <!-- default values for query parameters can be specified, these
+         will be overridden by parameters in the request
+      -->
+     <lst name="defaults">
+       <str name="echoParams">explicit</str>
+       <int name="rows">10</int>
+       <str name="df">text</str>
+     </lst>
+    <!-- In addition to defaults, "appends" params can be specified
+         to identify values which should be appended to the list of
+         multi-val params from the query (or the existing "defaults").
+      -->
+    <!-- In this example, the param "fq=instock:true" would be appended to
+         any query time fq params the user may specify, as a mechanism for
+         partitioning the index, independent of any user selected filtering
+         that may also be desired (perhaps as a result of faceted searching).
+
+         NOTE: there is *absolutely* nothing a client can do to prevent these
+         "appends" values from being used, so don't use this mechanism
+         unless you are sure you always want it.
+      -->
+    <!--
+       <lst name="appends">
+         <str name="fq">inStock:true</str>
+       </lst>
+      -->
+    <!-- "invariants" are a way of letting the Solr maintainer lock down
+         the options available to Solr clients.  Any params values
+         specified here are used regardless of what values may be specified
+         in either the query, the "defaults", or the "appends" params.
+
+         In this example, the facet.field and facet.query params would
+         be fixed, limiting the facets clients can use.  Faceting is
+         not turned on by default - but if the client does specify
+         facet=true in the request, these are the only facets they
+         will be able to see counts for; regardless of what other
+         facet.field or facet.query params they may specify.
+
+         NOTE: there is *absolutely* nothing a client can do to prevent these
+         "invariants" values from being used, so don't use this mechanism
+         unless you are sure you always want it.
+      -->
+    <!--
+       <lst name="invariants">
+         <str name="facet.field">cat</str>
+         <str name="facet.field">manu_exact</str>
+         <str name="facet.query">price:[* TO 500]</str>
+         <str name="facet.query">price:[500 TO *]</str>
+       </lst>
+      -->
+    <!-- If the default list of SearchComponents is not desired, that
+         list can either be overridden completely, or components can be
+         prepended or appended to the default list.  (see below)
+      -->
+    <!--
+       <arr name="components">
+         <str>nameOfCustomComponent1</str>
+         <str>nameOfCustomComponent2</str>
+       </arr>
+      -->
+    </requestHandler>
+
+  <!-- A request handler that returns indented JSON by default -->
+  <requestHandler name="/query" class="solr.SearchHandler">
+     <lst name="defaults">
+       <str name="echoParams">explicit</str>
+       <str name="wt">json</str>
+       <str name="indent">true</str>
+       <str name="df">text</str>
+     </lst>
+  </requestHandler>
+
+
+  <!-- realtime get handler, guaranteed to return the latest stored fields of
+       any document, without the need to commit or open a new searcher.  The
+       current implementation relies on the updateLog feature being enabled.
+
+       ** WARNING **
+       Do NOT disable the realtime get handler at /get if you are using
+       SolrCloud otherwise any leader election will cause a full sync in ALL
+       replicas for the shard in question. Similarly, a replica recovery will
+       also always fetch the complete index from the leader because a partial
+       sync will not be possible in the absence of this handler.
+  -->
+  <requestHandler name="/get" class="solr.RealTimeGetHandler">
+     <lst name="defaults">
+       <str name="omitHeader">true</str>
+       <str name="wt">json</str>
+       <str name="indent">true</str>
+     </lst>
+  </requestHandler>
+
+ 
+  <!-- A Robust Example 
+       
+       This example SearchHandler declaration shows off usage of the
+       SearchHandler with many defaults declared
+
+       Note that multiple instances of the same Request Handler
+       (SearchHandler) can be registered multiple times with different
+       names (and different init parameters)
+    -->
+  <requestHandler name="/browse" class="solr.SearchHandler">
+     <lst name="defaults">
+       <str name="echoParams">explicit</str>
+
+       <!-- VelocityResponseWriter settings -->
+       <str name="wt">velocity</str>
+       <str name="v.template">browse</str>
+       <str name="v.layout">layout</str>
+       <str name="title">Solritas</str>
+
+       <!-- Query settings -->
+       <str name="defType">edismax</str>
+       <str name="qf">
+          text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
+          title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0
+       </str>
+       <str name="df">text</str>
+       <str name="mm">100%</str>
+       <str name="q.alt">*:*</str>
+       <str name="rows">10</str>
+       <str name="fl">*,score</str>
+
+       <str name="mlt.qf">
+         text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
+         title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0
+       </str>
+       <str name="mlt.fl">text,features,name,sku,id,manu,cat,title,description,keywords,author,resourcename</str>
+       <int name="mlt.count">3</int>
+
+       <!-- Faceting defaults -->
+       <str name="facet">on</str>
+       <str name="facet.field">cat</str>
+       <str name="facet.field">manu_exact</str>
+       <str name="facet.field">content_type</str>
+       <str name="facet.field">author_s</str>
+       <str name="facet.query">ipod</str>
+       <str name="facet.query">GB</str>
+       <str name="facet.mincount">1</str>
+       <str name="facet.pivot">cat,inStock</str>
+       <str name="facet.range.other">after</str>
+       <str name="facet.range">price</str>
+       <int name="f.price.facet.range.start">0</int>
+       <int name="f.price.facet.range.end">600</int>
+       <int name="f.price.facet.range.gap">50</int>
+       <str name="facet.range">popularity</str>
+       <int name="f.popularity.facet.range.start">0</int>
+       <int name="f.popularity.facet.range.end">10</int>
+       <int name="f.popularity.facet.range.gap">3</int>
+       <str name="facet.range">manufacturedate_dt</str>
+       <str name="f.manufacturedate_dt.facet.range.start">NOW/YEAR-10YEARS</str>
+       <str name="f.manufacturedate_dt.facet.range.end">NOW</str>
+       <str name="f.manufacturedate_dt.facet.range.gap">+1YEAR</str>
+       <str name="f.manufacturedate_dt.facet.range.other">before</str>
+       <str name="f.manufacturedate_dt.facet.range.other">after</str>
+
+       <!-- Highlighting defaults -->
+       <str name="hl">on</str>
+       <str name="hl.fl">content features title name</str>
+       <str name="hl.encoder">html</str>
+       <str name="hl.simple.pre">&lt;b&gt;</str>
+       <str name="hl.simple.post">&lt;/b&gt;</str>
+       <str name="f.title.hl.fragsize">0</str>
+       <str name="f.title.hl.alternateField">title</str>
+       <str name="f.name.hl.fragsize">0</str>
+       <str name="f.name.hl.alternateField">name</str>
+       <str name="f.content.hl.snippets">3</str>
+       <str name="f.content.hl.fragsize">200</str>
+       <str name="f.content.hl.alternateField">content</str>
+       <str name="f.content.hl.maxAlternateFieldLength">750</str>
+
+       <!-- Spell checking defaults -->
+       <str name="spellcheck">on</str>
+       <str name="spellcheck.extendedResults">false</str>       
+       <str name="spellcheck.count">5</str>
+       <str name="spellcheck.alternativeTermCount">2</str>
+       <str name="spellcheck.maxResultsForSuggest">5</str>       
+       <str name="spellcheck.collate">true</str>
+       <str name="spellcheck.collateExtendedResults">true</str>  
+       <str name="spellcheck.maxCollationTries">5</str>
+       <str name="spellcheck.maxCollations">3</str>           
+     </lst>
+
+     <!-- append spellchecking to our list of components -->
+     <arr name="last-components">
+       <str>spellcheck</str>
+     </arr>
+  </requestHandler>
+
+
+  <!-- Update Request Handler.  
+       
+       http://wiki.apache.org/solr/UpdateXmlMessages
+
+       The canonical Request Handler for Modifying the Index through
+       commands specified using XML, JSON, CSV, or JAVABIN
+
+       Note: Since solr1.1 requestHandlers requires a valid content
+       type header if posted in the body. For example, curl now
+       requires: -H 'Content-type:text/xml; charset=utf-8'
+       
+       To override the request content type and force a specific 
+       Content-type, use the request parameter: 
+         ?update.contentType=text/csv
+       
+       This handler will pick a response format to match the input
+       if the 'wt' parameter is not explicit
+    -->
+  <requestHandler name="/update" class="solr.UpdateRequestHandler">
+    <!-- See below for information on defining 
+         updateRequestProcessorChains that can be used by name 
+         on each Update Request
+      -->
+    <!--
+       <lst name="defaults">
+         <str name="update.chain">dedupe</str>
+       </lst>
+       -->
+  </requestHandler>
+
+  <!-- for back compat with clients using /update/json and /update/csv -->  
+  <requestHandler name="/update/json" class="solr.UpdateRequestHandler">
+        <lst name="defaults">
+         <str name="stream.contentType">application/json</str>
+       </lst>
+  </requestHandler>
+  <requestHandler name="/update/csv" class="solr.UpdateRequestHandler">
+        <lst name="defaults">
+         <str name="stream.contentType">application/csv</str>
+       </lst>
+  </requestHandler>
+
+  <!-- Solr Cell Update Request Handler
+
+       http://wiki.apache.org/solr/ExtractingRequestHandler 
+
+    -->
+  <requestHandler name="/update/extract" 
+                  startup="lazy"
+                  class="solr.extraction.ExtractingRequestHandler" >
+    <lst name="defaults">
+      <str name="lowernames">true</str>
+      <str name="uprefix">ignored_</str>
+
+      <!-- capture link hrefs but ignore div attributes -->
+      <str name="captureAttr">true</str>
+      <str name="fmap.a">links</str>
+      <str name="fmap.div">ignored_</str>
+    </lst>
+  </requestHandler>
+
+
+  <!-- Field Analysis Request Handler
+
+       RequestHandler that provides much the same functionality as
+       analysis.jsp. Provides the ability to specify multiple field
+       types and field names in the same request and outputs
+       index-time and query-time analysis for each of them.
+
+       Request parameters are:
+       analysis.fieldname - field name whose analyzers are to be used
+
+       analysis.fieldtype - field type whose analyzers are to be used
+       analysis.fieldvalue - text for index-time analysis
+       q (or analysis.q) - text for query time analysis
+       analysis.showmatch (true|false) - When set to true and when
+           query analysis is performed, the produced tokens of the
+           field value analysis will be marked as "matched" for every
+           token that is produces by the query analysis
+   -->
+  <requestHandler name="/analysis/field" 
+                  startup="lazy"
+                  class="solr.FieldAnalysisRequestHandler" />
+
+
+  <!-- Document Analysis Handler
+
+       http://wiki.apache.org/solr/AnalysisRequestHandler
+
+       An analysis handler that provides a breakdown of the analysis
+       process of provided documents. This handler expects a (single)
+       content stream with the following format:
+
+       <docs>
+         <doc>
+           <field name="id">1</field>
+           <field name="name">The Name</field>
+           <field name="text">The Text Value</field>
+         </doc>
+         <doc>...</doc>
+         <doc>...</doc>
+         ...
+       </docs>
+
+    Note: Each document must contain a field which serves as the
+    unique key. This key is used in the returned response to associate
+    an analysis breakdown to the analyzed document.
+
+    Like the FieldAnalysisRequestHandler, this handler also supports
+    query analysis by sending either an "analysis.query" or "q"
+    request parameter that holds the query text to be analyzed. It
+    also supports the "analysis.showmatch" parameter which when set to
+    true, all field tokens that match the query tokens will be marked
+    as a "match". 
+  -->
+  <requestHandler name="/analysis/document" 
+                  class="solr.DocumentAnalysisRequestHandler" 
+                  startup="lazy" />
+
+  <!-- Admin Handlers
+
+       Admin Handlers - This will register all the standard admin
+       RequestHandlers.  
+    -->
+  <requestHandler name="/admin/" 
+                  class="solr.admin.AdminHandlers" />
+  <!-- This single handler is equivalent to the following... -->
+  <!--
+     <requestHandler name="/admin/luke"       class="solr.admin.LukeRequestHandler" />
+     <requestHandler name="/admin/system"     class="solr.admin.SystemInfoHandler" />
+     <requestHandler name="/admin/plugins"    class="solr.admin.PluginInfoHandler" />
+     <requestHandler name="/admin/threads"    class="solr.admin.ThreadDumpHandler" />
+     <requestHandler name="/admin/properties" class="solr.admin.PropertiesRequestHandler" />
+     <requestHandler name="/admin/file"       class="solr.admin.ShowFileRequestHandler" >
+    -->
+  <!-- If you wish to hide files under ${solr.home}/conf, explicitly
+       register the ShowFileRequestHandler using the definition below. 
+       NOTE: The glob pattern ('*') is the only pattern supported at present, *.xml will
+             not exclude all files ending in '.xml'. Use it to exclude _all_ updates
+    -->
+  <!--
+     <requestHandler name="/admin/file" 
+                     class="solr.admin.ShowFileRequestHandler" >
+       <lst name="invariants">
+         <str name="hidden">synonyms.txt</str> 
+         <str name="hidden">anotherfile.txt</str> 
+         <str name="hidden">*</str> 
+       </lst>
+     </requestHandler>
+    -->
+
+  <!--
+    Enabling this request handler (which is NOT a default part of the admin handler) will allow the Solr UI to edit
+    all the config files. This is intended for secure/development use ONLY! Leaving available and publically
+    accessible is a security vulnerability and should be done with extreme caution!
+  -->
+  <!-- ping/healthcheck -->
+  <requestHandler name="/admin/ping" class="solr.PingRequestHandler">
+    <lst name="invariants">
+      <str name="q">solrpingquery</str>
+    </lst>
+    <lst name="defaults">
+      <str name="echoParams">all</str>
+    </lst>
+    <!-- An optional feature of the PingRequestHandler is to configure the 
+         handler with a "healthcheckFile" which can be used to enable/disable 
+         the PingRequestHandler.
+         relative paths are resolved against the data dir 
+      -->
+    <!-- <str name="healthcheckFile">server-enabled.txt</str> -->
+  </requestHandler>
+
+  <!-- Echo the request contents back to the client -->
+  <requestHandler name="/debug/dump" class="solr.DumpRequestHandler" >
+    <lst name="defaults">
+     <str name="echoParams">explicit</str> 
+     <str name="echoHandler">true</str>
+    </lst>
+  </requestHandler>
+  
+  <!-- Solr Replication
+
+       The SolrReplicationHandler supports replicating indexes from a
+       "master" used for indexing and "slaves" used for queries.
+
+       http://wiki.apache.org/solr/SolrReplication 
+
+       It is also necessary for SolrCloud to function (in Cloud mode, the
+       replication handler is used to bulk transfer segments when nodes 
+       are added or need to recover).
+
+       https://wiki.apache.org/solr/SolrCloud/
+    -->
+  <requestHandler name="/replication" class="solr.ReplicationHandler" > 
+    <!--
+       To enable simple master/slave replication, uncomment one of the 
+       sections below, depending on whether this solr instance should be
+       the "master" or a "slave".  If this instance is a "slave" you will 
+       also need to fill in the masterUrl to point to a real machine.
+    -->
+    <!--
+       <lst name="master">
+         <str name="replicateAfter">commit</str>
+         <str name="replicateAfter">startup</str>
+         <str name="confFiles">schema.xml,stopwords.txt</str>
+       </lst>
+    -->
+    <!--
+       <lst name="slave">
+         <str name="masterUrl">http://your-master-hostname:8983/solr</str>
+         <str name="pollInterval">00:00:60</str>
+       </lst>
+    -->
+  </requestHandler>
+
+  <!-- Search Components
+
+       Search components are registered to SolrCore and used by 
+       instances of SearchHandler (which can access them by name)
+       
+       By default, the following components are available:
+       
+       <searchComponent name="query"     class="solr.QueryComponent" />
+       <searchComponent name="facet"     class="solr.FacetComponent" />
+       <searchComponent name="mlt"       class="solr.MoreLikeThisComponent" />
+       <searchComponent name="highlight" class="solr.HighlightComponent" />
+       <searchComponent name="stats"     class="solr.StatsComponent" />
+       <searchComponent name="debug"     class="solr.DebugComponent" />
+   
+       Default configuration in a requestHandler would look like:
+
+       <arr name="components">
+         <str>query</str>
+         <str>facet</str>
+         <str>mlt</str>
+         <str>highlight</str>
+         <str>stats</str>
+         <str>debug</str>
+       </arr>
+
+       If you register a searchComponent to one of the standard names, 
+       that will be used instead of the default.
+
+       To insert components before or after the 'standard' components, use:
+    
+       <arr name="first-components">
+         <str>myFirstComponentName</str>
+       </arr>
+    
+       <arr name="last-components">
+         <str>myLastComponentName</str>
+       </arr>
+
+       NOTE: The component registered with the name "debug" will
+       always be executed after the "last-components" 
+       
+     -->
+  
+   <!-- Spell Check
+
+        The spell check component can return a list of alternative spelling
+        suggestions.  
+
+        http://wiki.apache.org/solr/SpellCheckComponent
+     -->
+  <searchComponent name="spellcheck" class="solr.SpellCheckComponent">
+
+    <str name="queryAnalyzerFieldType">text_general</str>
+
+    <!-- Multiple "Spell Checkers" can be declared and used by this
+         component
+      -->
+
+    <!-- a spellchecker built from a field of the main index -->
+    <lst name="spellchecker">
+      <str name="name">default</str>
+      <str name="field">text</str>
+      <str name="classname">solr.DirectSolrSpellChecker</str>
+      <!-- the spellcheck distance measure used, the default is the internal levenshtein -->
+      <str name="distanceMeasure">internal</str>
+      <!-- minimum accuracy needed to be considered a valid spellcheck suggestion -->
+      <float name="accuracy">0.5</float>
+      <!-- the maximum #edits we consider when enumerating terms: can be 1 or 2 -->
+      <int name="maxEdits">2</int>
+      <!-- the minimum shared prefix when enumerating terms -->
+      <int name="minPrefix">1</int>
+      <!-- maximum number of inspections per result. -->
+      <int name="maxInspections">5</int>
+      <!-- minimum length of a query term to be considered for correction -->
+      <int name="minQueryLength">4</int>
+      <!-- maximum threshold of documents a query term can appear to be considered for correction -->
+      <float name="maxQueryFrequency">0.01</float>
+      <!-- uncomment this to require suggestions to occur in 1% of the documents
+      	<float name="thresholdTokenFrequency">.01</float>
+      -->
+    </lst>
+    
+    <!-- a spellchecker that can break or combine words.  See "/spell" handler below for usage -->
+    <lst name="spellchecker">
+      <str name="name">wordbreak</str>
+      <str name="classname">solr.WordBreakSolrSpellChecker</str>      
+      <str name="field">name</str>
+      <str name="combineWords">true</str>
+      <str name="breakWords">true</str>
+      <int name="maxChanges">10</int>
+    </lst>
+
+    <!-- a spellchecker that uses a different distance measure -->
+    <!--
+       <lst name="spellchecker">
+         <str name="name">jarowinkler</str>
+         <str name="field">spell</str>
+         <str name="classname">solr.DirectSolrSpellChecker</str>
+         <str name="distanceMeasure">
+           org.apache.lucene.search.spell.JaroWinklerDistance
+         </str>
+       </lst>
+     -->
+
+    <!-- a spellchecker that use an alternate comparator 
+
+         comparatorClass be one of:
+          1. score (default)
+          2. freq (Frequency first, then score)
+          3. A fully qualified class name
+      -->
+    <!--
+       <lst name="spellchecker">
+         <str name="name">freq</str>
+         <str name="field">lowerfilt</str>
+         <str name="classname">solr.DirectSolrSpellChecker</str>
+         <str name="comparatorClass">freq</str>
+      -->
+
+    <!-- A spellchecker that reads the list of words from a file -->
+    <!--
+       <lst name="spellchecker">
+         <str name="classname">solr.FileBasedSpellChecker</str>
+         <str name="name">file</str>
+         <str name="sourceLocation">spellings.txt</str>
+         <str name="characterEncoding">UTF-8</str>
+         <str name="spellcheckIndexDir">spellcheckerFile</str>
+       </lst>
+      -->
+  </searchComponent>
+  
+  <!-- A request handler for demonstrating the spellcheck component.  
+
+       NOTE: This is purely as an example.  The whole purpose of the
+       SpellCheckComponent is to hook it into the request handler that
+       handles your normal user queries so that a separate request is
+       not needed to get suggestions.
+
+       IN OTHER WORDS, THERE IS REALLY GOOD CHANCE THE SETUP BELOW IS
+       NOT WHAT YOU WANT FOR YOUR PRODUCTION SYSTEM!
+       
+       See http://wiki.apache.org/solr/SpellCheckComponent for details
+       on the request parameters.
+    -->
+  <requestHandler name="/spell" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <str name="df">text</str>
+      <!-- Solr will use suggestions from both the 'default' spellchecker
+           and from the 'wordbreak' spellchecker and combine them.
+           collations (re-written queries) can include a combination of
+           corrections from both spellcheckers -->
+      <str name="spellcheck.dictionary">default</str>
+      <str name="spellcheck.dictionary">wordbreak</str>
+      <str name="spellcheck">on</str>
+      <str name="spellcheck.extendedResults">true</str>       
+      <str name="spellcheck.count">10</str>
+      <str name="spellcheck.alternativeTermCount">5</str>
+      <str name="spellcheck.maxResultsForSuggest">5</str>       
+      <str name="spellcheck.collate">true</str>
+      <str name="spellcheck.collateExtendedResults">true</str>  
+      <str name="spellcheck.maxCollationTries">10</str>
+      <str name="spellcheck.maxCollations">5</str>         
+    </lst>
+    <arr name="last-components">
+      <str>spellcheck</str>
+    </arr>
+  </requestHandler>
+
+  <searchComponent name="suggest" class="solr.SuggestComponent">
+  	<lst name="suggester">
+      <str name="name">mySuggester</str>
+      <str name="lookupImpl">FuzzyLookupFactory</str>      <!-- org.apache.solr.spelling.suggest.fst -->
+      <str name="dictionaryImpl">DocumentDictionaryFactory</str>     <!-- org.apache.solr.spelling.suggest.HighFrequencyDictionaryFactory --> 
+      <str name="field">cat</str>
+      <str name="weightField">price</str>
+      <str name="suggestAnalyzerFieldType">string</str>
+    </lst>
+  </searchComponent>
+
+  <requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <str name="suggest">true</str>
+      <str name="suggest.count">10</str>
+    </lst>
+    <arr name="components">
+      <str>suggest</str>
+    </arr>
+  </requestHandler>
+  <!-- Term Vector Component
+
+       http://wiki.apache.org/solr/TermVectorComponent
+    -->
+  <searchComponent name="tvComponent" class="solr.TermVectorComponent"/>
+
+  <!-- A request handler for demonstrating the term vector component
+
+       This is purely as an example.
+
+       In reality you will likely want to add the component to your 
+       already specified request handlers. 
+    -->
+  <requestHandler name="/tvrh" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <str name="df">text</str>
+      <bool name="tv">true</bool>
+    </lst>
+    <arr name="last-components">
+      <str>tvComponent</str>
+    </arr>
+  </requestHandler>
+
+  <!-- Clustering Component
+
+       You'll need to set the solr.clustering.enabled system property
+       when running solr to run with clustering enabled:
+
+            java -Dsolr.clustering.enabled=true -jar start.jar
+
+       http://wiki.apache.org/solr/ClusteringComponent
+       http://carrot2.github.io/solr-integration-strategies/
+    -->
+  <searchComponent name="clustering"
+                   enable="${solr.clustering.enabled:false}"
+                   class="solr.clustering.ClusteringComponent" >
+    <lst name="engine">
+      <str name="name">lingo</str>
+
+      <!-- Class name of a clustering algorithm compatible with the Carrot2 framework.
+
+           Currently available open source algorithms are:
+           * org.carrot2.clustering.lingo.LingoClusteringAlgorithm
+           * org.carrot2.clustering.stc.STCClusteringAlgorithm
+           * org.carrot2.clustering.kmeans.BisectingKMeansClusteringAlgorithm
+
+           See http://project.carrot2.org/algorithms.html for more information.
+
+           A commercial algorithm Lingo3G (needs to be installed separately) is defined as:
+           * com.carrotsearch.lingo3g.Lingo3GClusteringAlgorithm
+        -->
+      <str name="carrot.algorithm">org.carrot2.clustering.lingo.LingoClusteringAlgorithm</str>
+
+      <!-- Override location of the clustering algorithm's resources 
+           (attribute definitions and lexical resources).
+
+           A directory from which to load algorithm-specific stop words,
+           stop labels and attribute definition XMLs. 
+
+           For an overview of Carrot2 lexical resources, see:
+           http://download.carrot2.org/head/manual/#chapter.lexical-resources
+
+           For an overview of Lingo3G lexical resources, see:
+           http://download.carrotsearch.com/lingo3g/manual/#chapter.lexical-resources
+       -->
+      <str name="carrot.resourcesDir">clustering/carrot2</str>
+    </lst>
+
+    <!-- An example definition for the STC clustering algorithm. -->
+    <lst name="engine">
+      <str name="name">stc</str>
+      <str name="carrot.algorithm">org.carrot2.clustering.stc.STCClusteringAlgorithm</str>
+    </lst>
+
+    <!-- An example definition for the bisecting kmeans clustering algorithm. -->
+    <lst name="engine">
+      <str name="name">kmeans</str>
+      <str name="carrot.algorithm">org.carrot2.clustering.kmeans.BisectingKMeansClusteringAlgorithm</str>
+    </lst>
+  </searchComponent>
+
+  <!-- A request handler for demonstrating the clustering component
+
+       This is purely as an example.
+
+       In reality you will likely want to add the component to your 
+       already specified request handlers. 
+    -->
+  <requestHandler name="/clustering"
+                  startup="lazy"
+                  enable="${solr.clustering.enabled:false}"
+                  class="solr.SearchHandler">
+    <lst name="defaults">
+      <bool name="clustering">true</bool>
+      <bool name="clustering.results">true</bool>
+      <!-- Field name with the logical "title" of a each document (optional) -->
+      <str name="carrot.title">name</str>
+      <!-- Field name with the logical "URL" of a each document (optional) -->
+      <str name="carrot.url">id</str>
+      <!-- Field name with the logical "content" of a each document (optional) -->
+      <str name="carrot.snippet">features</str>
+      <!-- Apply highlighter to the title/ content and use this for clustering. -->
+      <bool name="carrot.produceSummary">true</bool>
+      <!-- the maximum number of labels per cluster -->
+      <!--<int name="carrot.numDescriptions">5</int>-->
+      <!-- produce sub clusters -->
+      <bool name="carrot.outputSubClusters">false</bool>
+
+      <!-- Configure the remaining request handler parameters. -->
+      <str name="defType">edismax</str>
+      <str name="qf">
+        text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
+      </str>
+      <str name="q.alt">*:*</str>
+      <str name="rows">10</str>
+      <str name="fl">*,score</str>
+    </lst>
+    <arr name="last-components">
+      <str>clustering</str>
+    </arr>
+  </requestHandler>
+  
+  <!-- Terms Component
+
+       http://wiki.apache.org/solr/TermsComponent
+
+       A component to return terms and document frequency of those
+       terms
+    -->
+  <searchComponent name="terms" class="solr.TermsComponent"/>
+
+  <!-- A request handler for demonstrating the terms component -->
+  <requestHandler name="/terms" class="solr.SearchHandler" startup="lazy">
+     <lst name="defaults">
+      <bool name="terms">true</bool>
+      <bool name="distrib">false</bool>
+    </lst>     
+    <arr name="components">
+      <str>terms</str>
+    </arr>
+  </requestHandler>
+
+
+  <!-- Query Elevation Component
+
+       http://wiki.apache.org/solr/QueryElevationComponent
+
+       a search component that enables you to configure the top
+       results for a given query regardless of the normal lucene
+       scoring.
+    -->
+  <searchComponent name="elevator" class="solr.QueryElevationComponent" >
+    <!-- pick a fieldType to analyze queries -->
+    <str name="queryFieldType">string</str>
+    <str name="config-file">elevate.xml</str>
+  </searchComponent>
+
+  <!-- A request handler for demonstrating the elevator component -->
+  <requestHandler name="/elevate" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+      <str name="df">text</str>
+    </lst>
+    <arr name="last-components">
+      <str>elevator</str>
+    </arr>
+  </requestHandler>
+
+  <!-- Highlighting Component
+
+       http://wiki.apache.org/solr/HighlightingParameters
+    -->
+  <searchComponent class="solr.HighlightComponent" name="highlight">
+    <highlighting>
+      <!-- Configure the standard fragmenter -->
+      <!-- This could most likely be commented out in the "default" case -->
+      <fragmenter name="gap" 
+                  default="true"
+                  class="solr.highlight.GapFragmenter">
+        <lst name="defaults">
+          <int name="hl.fragsize">100</int>
+        </lst>
+      </fragmenter>
+
+      <!-- A regular-expression-based fragmenter 
+           (for sentence extraction) 
+        -->
+      <fragmenter name="regex" 
+                  class="solr.highlight.RegexFragmenter">
+        <lst name="defaults">
+          <!-- slightly smaller fragsizes work better because of slop -->
+          <int name="hl.fragsize">70</int>
+          <!-- allow 50% slop on fragment sizes -->
+          <float name="hl.regex.slop">0.5</float>
+          <!-- a basic sentence pattern -->
+          <str name="hl.regex.pattern">[-\w ,/\n\&quot;&apos;]{20,200}</str>
+        </lst>
+      </fragmenter>
+
+      <!-- Configure the standard formatter -->
+      <formatter name="html" 
+                 default="true"
+                 class="solr.highlight.HtmlFormatter">
+        <lst name="defaults">
+          <str name="hl.simple.pre"><![CDATA[<em>]]></str>
+          <str name="hl.simple.post"><![CDATA[</em>]]></str>
+        </lst>
+      </formatter>
+
+      <!-- Configure the standard encoder -->
+      <encoder name="html" 
+               class="solr.highlight.HtmlEncoder" />
+
+      <!-- Configure the standard fragListBuilder -->
+      <fragListBuilder name="simple" 
+                       class="solr.highlight.SimpleFragListBuilder"/>
+      
+      <!-- Configure the single fragListBuilder -->
+      <fragListBuilder name="single" 
+                       class="solr.highlight.SingleFragListBuilder"/>
+      
+      <!-- Configure the weighted fragListBuilder -->
+      <fragListBuilder name="weighted" 
+                       default="true"
+                       class="solr.highlight.WeightedFragListBuilder"/>
+      
+      <!-- default tag FragmentsBuilder -->
+      <fragmentsBuilder name="default" 
+                        default="true"
+                        class="solr.highlight.ScoreOrderFragmentsBuilder">
+        <!-- 
+        <lst name="defaults">
+          <str name="hl.multiValuedSeparatorChar">/</str>
+        </lst>
+        -->
+      </fragmentsBuilder>
+
+      <!-- multi-colored tag FragmentsBuilder -->
+      <fragmentsBuilder name="colored" 
+                        class="solr.highlight.ScoreOrderFragmentsBuilder">
+        <lst name="defaults">
+          <str name="hl.tag.pre"><![CDATA[
+               <b style="background:yellow">,<b style="background:lawgreen">,
+               <b style="background:aquamarine">,<b style="background:magenta">,
+               <b style="background:palegreen">,<b style="background:coral">,
+               <b style="background:wheat">,<b style="background:khaki">,
+               <b style="background:lime">,<b style="background:deepskyblue">]]></str>
+          <str name="hl.tag.post"><![CDATA[</b>]]></str>
+        </lst>
+      </fragmentsBuilder>
+      
+      <boundaryScanner name="default" 
+                       default="true"
+                       class="solr.highlight.SimpleBoundaryScanner">
+        <lst name="defaults">
+          <str name="hl.bs.maxScan">10</str>
+          <str name="hl.bs.chars">.,!? &#9;&#10;&#13;</str>
+        </lst>
+      </boundaryScanner>
+      
+      <boundaryScanner name="breakIterator" 
+                       class="solr.highlight.BreakIteratorBoundaryScanner">
+        <lst name="defaults">
+          <!-- type should be one of CHARACTER, WORD(default), LINE and SENTENCE -->
+          <str name="hl.bs.type">WORD</str>
+          <!-- language and country are used when constructing Locale object.  -->
+          <!-- And the Locale object will be used when getting instance of BreakIterator -->
+          <str name="hl.bs.language">en</str>
+          <str name="hl.bs.country">US</str>
+        </lst>
+      </boundaryScanner>
+    </highlighting>
+  </searchComponent>
+
+  <!-- Update Processors
+
+       Chains of Update Processor Factories for dealing with Update
+       Requests can be declared, and then used by name in Update
+       Request Processors
+
+       http://wiki.apache.org/solr/UpdateRequestProcessor
+
+    --> 
+  <!-- Deduplication
+
+       An example dedup update processor that creates the "id" field
+       on the fly based on the hash code of some other fields.  This
+       example has overwriteDupes set to false since we are using the
+       id field as the signatureField and Solr will maintain
+       uniqueness based on that anyway.  
+       
+    -->
+  <!--
+     <updateRequestProcessorChain name="dedupe">
+       <processor class="solr.processor.SignatureUpdateProcessorFactory">
+         <bool name="enabled">true</bool>
+         <str name="signatureField">id</str>
+         <bool name="overwriteDupes">false</bool>
+         <str name="fields">name,features,cat</str>
+         <str name="signatureClass">solr.processor.Lookup3Signature</str>
+       </processor>
+       <processor class="solr.LogUpdateProcessorFactory" />
+       <processor class="solr.RunUpdateProcessorFactory" />
+     </updateRequestProcessorChain>
+    -->
+  
+  <!-- Language identification
+
+       This example update chain identifies the language of the incoming
+       documents using the langid contrib. The detected language is
+       written to field language_s. No field name mapping is done.
+       The fields used for detection are text, title, subject and description,
+       making this example suitable for detecting languages form full-text
+       rich documents injected via ExtractingRequestHandler.
+       See more about langId at http://wiki.apache.org/solr/LanguageDetection
+    -->
+    <!--
+     <updateRequestProcessorChain name="langid">
+       <processor class="org.apache.solr.update.processor.TikaLanguageIdentifierUpdateProcessorFactory">
+         <str name="langid.fl">text,title,subject,description</str>
+         <str name="langid.langField">language_s</str>
+         <str name="langid.fallback">en</str>
+       </processor>
+       <processor class="solr.LogUpdateProcessorFactory" />
+       <processor class="solr.RunUpdateProcessorFactory" />
+     </updateRequestProcessorChain>
+    -->
+
+  <!-- Script update processor
+
+    This example hooks in an update processor implemented using JavaScript.
+
+    See more about the script update processor at http://wiki.apache.org/solr/ScriptUpdateProcessor
+  -->
+  <!--
+    <updateRequestProcessorChain name="script">
+      <processor class="solr.StatelessScriptUpdateProcessorFactory">
+        <str name="script">update-script.js</str>
+        <lst name="params">
+          <str name="config_param">example config parameter</str>
+        </lst>
+      </processor>
+      <processor class="solr.RunUpdateProcessorFactory" />
+    </updateRequestProcessorChain>
+  -->
+ 
+  <!-- Response Writers
+
+       http://wiki.apache.org/solr/QueryResponseWriter
+
+       Request responses will be written using the writer specified by
+       the 'wt' request parameter matching the name of a registered
+       writer.
+
+       The "default" writer is the default and will be used if 'wt' is
+       not specified in the request.
+    -->
+  <!-- The following response writers are implicitly configured unless
+       overridden...
+    -->
+  <!--
+     <queryResponseWriter name="xml" 
+                          default="true"
+                          class="solr.XMLResponseWriter" />
+     <queryResponseWriter name="json" class="solr.JSONResponseWriter"/>
+     <queryResponseWriter name="python" class="solr.PythonResponseWriter"/>
+     <queryResponseWriter name="ruby" class="solr.RubyResponseWriter"/>
+     <queryResponseWriter name="php" class="solr.PHPResponseWriter"/>
+     <queryResponseWriter name="phps" class="solr.PHPSerializedResponseWriter"/>
+     <queryResponseWriter name="csv" class="solr.CSVResponseWriter"/>
+     <queryResponseWriter name="schema.xml" class="solr.SchemaXmlResponseWriter"/>
+    -->
+
+  <queryResponseWriter name="json" class="solr.JSONResponseWriter">
+     <!-- For the purposes of the tutorial, JSON responses are written as
+      plain text so that they are easy to read in *any* browser.
+      If you expect a MIME type of "application/json" just remove this override.
+     -->
+    <str name="content-type">text/plain; charset=UTF-8</str>
+  </queryResponseWriter>
+  
+  <!--
+     Custom response writers can be declared as needed...
+    -->
+    <queryResponseWriter name="velocity" class="solr.VelocityResponseWriter" startup="lazy"/>
+  
+
+  <!-- XSLT response writer transforms the XML output by any xslt file found
+       in Solr's conf/xslt directory.  Changes to xslt files are checked for
+       every xsltCacheLifetimeSeconds.  
+    -->
+  <queryResponseWriter name="xslt" class="solr.XSLTResponseWriter">
+    <int name="xsltCacheLifetimeSeconds">5</int>
+  </queryResponseWriter>
+
+  <!-- Query Parsers
+
+       http://wiki.apache.org/solr/SolrQuerySyntax
+
+       Multiple QParserPlugins can be registered by name, and then
+       used in either the "defType" param for the QueryComponent (used
+       by SearchHandler) or in LocalParams
+    -->
+  <!-- example of registering a query parser -->
+  <!--
+     <queryParser name="myparser" class="com.mycompany.MyQParserPlugin"/>
+    -->
+
+  <!-- Function Parsers
+
+       http://wiki.apache.org/solr/FunctionQuery
+
+       Multiple ValueSourceParsers can be registered by name, and then
+       used as function names when using the "func" QParser.
+    -->
+  <!-- example of registering a custom function parser  -->
+  <!--
+     <valueSourceParser name="myfunc" 
+                        class="com.mycompany.MyValueSourceParser" />
+    -->
+    
+  
+  <!-- Document Transformers
+       http://wiki.apache.org/solr/DocTransformers
+    -->
+  <!--
+     Could be something like:
+     <transformer name="db" class="com.mycompany.LoadFromDatabaseTransformer" >
+       <int name="connection">jdbc://....</int>
+     </transformer>
+     
+     To add a constant value to all docs, use:
+     <transformer name="mytrans2" class="org.apache.solr.response.transform.ValueAugmenterFactory" >
+       <int name="value">5</int>
+     </transformer>
+     
+     If you want the user to still be able to change it with _value:something_ use this:
+     <transformer name="mytrans3" class="org.apache.solr.response.transform.ValueAugmenterFactory" >
+       <double name="defaultValue">5</double>
+     </transformer>
+
+      If you are using the QueryElevationComponent, you may wish to mark documents that get boosted.  The
+      EditorialMarkerFactory will do exactly that:
+     <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
+    -->
+    
+
+  <!-- Legacy config for the admin interface -->
+  <admin>
+    <defaultQuery>*:*</defaultQuery>
+  </admin>
+
+</config>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/spellings.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/spellings.txt
new file mode 100644
index 0000000..d7ede6f
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/spellings.txt
@@ -0,0 +1,2 @@
+pizza
+history
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/stopwords.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/stopwords.txt
new file mode 100644
index 0000000..ae1e83e
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/stopwords.txt
@@ -0,0 +1,14 @@
+# 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.
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/synonyms.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/synonyms.txt
new file mode 100644
index 0000000..7f72128
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/synonyms.txt
@@ -0,0 +1,29 @@
+# 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.
+
+#-----------------------------------------------------------------------
+#some test synonym mappings unlikely to appear in real input text
+aaafoo => aaabar
+bbbfoo => bbbfoo bbbbar
+cccfoo => cccbar cccbaz
+fooaaa,baraaa,bazaaa
+
+# Some synonym groups specific to this example
+GB,gib,gigabyte,gigabytes
+MB,mib,megabyte,megabytes
+Television, Televisions, TV, TVs
+#notice we use "gib" instead of "GiB" so any WordDelimiterFilter coming
+#after us won't split it into two words.
+
+# Synonym mappings can be used for spelling correction too
+pixima => pixma
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/update-script.js b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/update-script.js
new file mode 100644
index 0000000..49b07f9
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/update-script.js
@@ -0,0 +1,53 @@
+/*
+  This is a basic skeleton JavaScript update processor.
+
+  In order for this to be executed, it must be properly wired into solrconfig.xml; by default it is commented out in
+  the example solrconfig.xml and must be uncommented to be enabled.
+
+  See http://wiki.apache.org/solr/ScriptUpdateProcessor for more details.
+*/
+
+function processAdd(cmd) {
+
+  doc = cmd.solrDoc;  // org.apache.solr.common.SolrInputDocument
+  id = doc.getFieldValue("id");
+  logger.info("update-script#processAdd: id=" + id);
+
+// Set a field value:
+//  doc.setField("foo_s", "whatever");
+
+// Get a configuration parameter:
+//  config_param = params.get('config_param');  // "params" only exists if processor configured with <lst name="params">
+
+// Get a request parameter:
+// some_param = req.getParams().get("some_param")
+
+// Add a field of field names that match a pattern:
+//   - Potentially useful to determine the fields/attributes represented in a result set, via faceting on field_name_ss
+//  field_names = doc.getFieldNames().toArray();
+//  for(i=0; i < field_names.length; i++) {
+//    field_name = field_names[i];
+//    if (/attr_.*/.test(field_name)) { doc.addField("attribute_ss", field_names[i]); }
+//  }
+
+}
+
+function processDelete(cmd) {
+  // no-op
+}
+
+function processMergeIndexes(cmd) {
+  // no-op
+}
+
+function processCommit(cmd) {
+  // no-op
+}
+
+function processRollback(cmd) {
+  // no-op
+}
+
+function finish() {
+  // no-op
+}
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/README.txt b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/README.txt
new file mode 100644
index 0000000..5d560ba
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/README.txt
@@ -0,0 +1,101 @@
+Introduction
+------------
+Solr Search Velocity Templates
+
+A quick demo of using Solr using http://wiki.apache.org/solr/VelocityResponseWriter
+
+You typically access these templates via:
+	http://localhost:8983/solr/collection1/browse
+
+It's called "browse" because you can click around with your mouse
+without needing to type any search terms.  And of course it
+also works as a standard search app as well.
+
+Known Limitations
+-----------------
+* The /browse and the VelocityResponseWriter component
+  serve content directly from Solr, which usually requires
+  Solr's HTTP API to be exposed.  Advanced users could
+  potentially access other parts of Solr directly.
+* There are some hard coded fields in these templates.
+  Since these templates live under conf, they should be
+  considered part of the overall configuration, and
+  must be coordinated with schema.xml and solrconfig.xml
+
+Velocity Info
+-------------
+Java-based template language.
+
+It's nice in this context because change to the templates
+are immediately visible in browser on the next visit.
+
+Links:
+	http://velocity.apache.org
+	http://wiki.apache.org/velocity/
+	http://velocity.apache.org/engine/releases/velocity-1.7/user-guide.html
+
+
+File List
+---------
+
+System and Misc:
+  VM_global_library.vm    - Macros used other templates,
+                            exact filename is important for Velocity to see it
+  error.vm                - shows errors, if any
+  debug.vm                - includes toggle links for "explain" and "all fields"
+                            activated by debug link in footer.vm
+  README.txt              - this file
+
+Overall Page Composition:
+  browse.vm               - Main entry point into templates
+  layout.vm               - overall HTML page layout
+  head.vm                 - elements in the <head> section of the HTML document
+  header.vm               - top section of page visible to users
+  footer.vm               - bottom section of page visible to users,
+                            includes debug and help links
+  main.css                - CSS style for overall pages
+                            see also jquery.autocomplete.css
+
+Query Form and Options:
+  query_form.vm           - renders query form
+  query_group.vm          - group by fields
+                            e.g.: Manufacturer or Poplularity
+  query_spatial.vm        - select box for location based Geospacial search
+
+Spelling Suggestions:
+  did_you_mean.vm         - hyperlinked spelling suggestions in results
+  suggest.vm              - dynamic spelling suggestions
+                            as you type in the search form
+  jquery.autocomplete.js  - supporting files for dynamic suggestions
+  jquery.autocomplete.css - Most CSS is defined in main.css
+
+
+Search Results, General:
+  (see also browse.vm)
+  tabs.vm                 - provides navigation to advanced search options
+  pagination_top.vm       - paging and staticis at top of results
+  pagination_bottom.vm    - paging and staticis at bottom of results
+  results_list.vm
+  hit.vm                  - called for each matching doc,
+                            decides which template to use
+  hit_grouped.vm          - display results grouped by field values
+  product_doc.vm          - display a Product
+  join_doc.vm             - display a joined document
+  richtext_doc.vm         - display a complex/misc. document
+  hit_plain.vm            - basic display of all fields,
+                            edit results_list.vm to enable this
+
+
+Search Results, Facets & Clusters:
+  facets.vm               - calls the 4 facet and 1 cluster template
+  facet_fields.vm         - display facets based on field values
+                            e.g.: fields specified by &facet.field=
+  facet_queries.vm        - display facets based on specific facet queries
+                            e.g.: facets specified by &facet.query=
+  facet_ranges.vm         - display facets based on ranges
+                            e.g.: ranges specified by &facet.range=
+  facet_pivot.vm          - display pivot based facets
+                            e.g.: facets specified by &facet.pivot=
+  cluster.vm              - if clustering is available
+                            then call cluster_results.vm
+  cluster_results.vm      - actual rendering of clusters
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/VM_global_library.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/VM_global_library.vm
new file mode 100644
index 0000000..5dda07c
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/VM_global_library.vm
@@ -0,0 +1,175 @@
+#**
+ *  Global macros used by other templates.
+ *  This file must be named VM_global_library.vm
+ *  in order for Velocity to find it.
+ *#
+
+#macro(param $key)$request.params.get($key)#end
+
+#macro(url_root)/solr#end
+
+## TODO: s/url_for_solr/url_for_core/ and s/url_root/url_for_solr/
+#macro(core_name)$request.core.name#end
+#macro(url_for_solr)#{url_root}#if($request.core.name != "")/$request.core.name#end#end
+#macro(url_for_home)#url_for_solr/browse#end
+
+#macro(q)&q=$!{esc.url($params.get('q'))}#end
+
+#macro(fqs $p)#foreach($fq in $p)#if($velocityCount>1)&#{end}fq=$esc.url($fq)#end#end
+
+#macro(debug)#if($request.params.get('debugQuery'))&debugQuery=true#end#end
+
+#macro(boostPrice)#if($request.params.get('bf') == 'price')&bf=price#end#end        
+
+#macro(annotate)#if($request.params.get('annotateBrowse'))&annotateBrowse=true#end#end
+
+#macro(annTitle $msg)#if($annotate == true)title="$msg"#end#end
+
+#macro(spatial)#if($request.params.get('sfield'))&sfield=store#end#if($request.params.get('pt'))&pt=$request.params.get('pt')#end#if($request.params.get('d'))&d=$request.params.get('d')#end#end
+
+#macro(qOpts)#set($queryOpts = $request.params.get("queryOpts"))#if($queryOpts && $queryOpts != "")&queryOpts=$queryOpts#end#end
+
+#macro(group)#if($request.params.getBool("group") == true)&group=true#end#if($request.params.get("group.field"))#foreach($grp in $request.params.getParams('group.field'))&group.field=$grp#end#end#end
+
+#macro(sort $p)#if($p)#foreach($s in $p)&sort=$esc.url($s)#end#end#end
+
+#macro(lensNoQ)?#if($request.params.getParams('fq') and $list.size($request.params.getParams('fq')) > 0)&#fqs($request.params.getParams('fq'))#end#sort($request.params.getParams('sort'))#debug#boostPrice#annotate#spatial#qOpts#group#end
+#macro(lens)#lensNoQ#q#end
+        
+
+#macro(url_for_lens)#{url_for_home}#lens#end
+
+#macro(url_for_start $start)#url_for_home#lens&start=$start#end
+
+#macro(url_for_filters $p)#url_for_home?#q#boostPrice#spatial#qOpts#if($list.size($p) > 0)&#fqs($p)#end#debug#end
+
+#macro(url_for_nested_facet_query $field)#url_for_home#lens&fq=$esc.url($field)#end
+
+## TODO: convert to use {!raw f=$field}$value (with escaping of course)
+#macro(url_for_facet_filter $field $value)#url_for_home#lens&fq=$esc.url($field):%22$esc.url($value)%22#end
+
+#macro(url_for_facet_date_filter $field $value)#url_for_home#lens&fq=$esc.url($field):$esc.url($value)#end
+
+#macro(url_for_facet_range_filter $field $value)#url_for_home#lens&fq=$esc.url($field):$esc.url($value)#end
+
+
+#macro(link_to_previous_page $text)
+  #if($page.current_page_number > 1)
+    #set($prev_start = $page.start - $page.results_per_page)
+    <a class="prev-page" href="#url_for_start($prev_start)">$text</a>
+  #end
+#end
+
+#macro(link_to_next_page $text)
+  #if($page.current_page_number < $page.page_count)
+    #set($next_start = $page.start + $page.results_per_page)
+    <a class="next-page" href="#url_for_start($next_start)">$text</a>
+  #end
+#end
+
+#macro(link_to_page $page_number $text)
+  #if($page_number == $page.current_page_number)
+    $text
+  #else
+    #if($page_number <= $page.page_count)
+      #set($page_start = $page_number * $page.results_per_page - $page.results_per_page)
+      <a class="page" href="#url_for_start($page_start)">$text</a>
+    #end
+  #end
+#end
+
+#macro(display_facet_query $field, $display, $fieldName)
+  #if($field.size() > 0)
+  <span class="facet-field">$display</span>
+    <ul>
+    #foreach ($facet in $field)
+      #if ($facet.value > 0)
+        #set($facetURL = "#url_for_nested_facet_query($facet.key)")
+        #if ($facetURL != '')
+          <li><a href="$facetURL">$facet.key</a> ($facet.value)</li>
+        #end
+      #end
+    #end
+    </ul>
+  #end      
+#end
+
+
+#macro(display_facet_range $field, $display, $fieldName, $start, $end, $gap, $before, $after)
+  <span class="facet-field">$display</span>
+    <ul>
+    #if($before && $before != "")
+      #set($value = "[* TO " + "#format_value($start)" + "}")
+      #set($facetURL = "#url_for_facet_range_filter($fieldName, $value)")
+      <li><a href="$facetURL">Less than #format_value($start)</a> ($before)</li>
+    #end
+    #foreach ($facet in $field)
+      #set($rangeEnd = "#range_get_to_value($facet.key, $gap)")
+      #set($value = "[" + $facet.key + " TO " + $rangeEnd + "}")
+      #set($facetURL = "#url_for_facet_range_filter($fieldName, $value)")
+      #if ($facetURL != '')
+        <li><a href="$facetURL">$facet.key - #format_value($rangeEnd)</a> ($facet.value)</li>
+      #end
+    #end
+    #if($end && $end != "" && $after > 0)
+      #set($value = "[" + "#format_value($end)" + " TO *}")
+      #set($facetURL = "#url_for_facet_range_filter($fieldName, $value)")
+      <li><a href="$facetURL">More than #format_value($end)</a> ($after)</li>
+    #end
+    </ul>
+#end
+
+## $pivots is a list of facet_pivot
+#macro(display_facet_pivot $pivots, $display)
+  #if($pivots.size() > 0)
+  <span class="facet-field">$display</span>
+    <ul>
+      #foreach ($pivot in $pivots)
+        #foreach ($entry in $pivot.value)
+          <a href="#url_for_facet_filter($entry.field, $entry.value)">$entry.field::$entry.value</a> ($entry.count)
+          <ul>
+            #foreach($nest in $entry.pivot)
+              <a href="#url_for_facet_filter($entry.field, $entry.value)&fq=$esc.url($nest.field):%22$esc.url($nest.value)%22">$nest.field::$nest.value</a> ($nest.count)
+            #end
+          </ul>
+        #end
+      #end
+    </ul>
+  #end
+#end
+
+#macro(field $f)
+  #if($response.response.highlighting.get($docId).get($f).get(0))
+    #set($pad = "")
+    #foreach($v in $response.response.highlighting.get($docId).get($f))
+$pad$v##
+      #set($pad = " ... ")
+    #end
+  #else
+    #foreach($v in $doc.getFieldValues($f))
+$v##
+    #end
+  #end
+#end  
+
+#macro(utc_date $theDate)
+$date.format("yyyy-MM-dd'T'HH:mm:ss'Z'",$theDate,$date.getLocale(),$date.getTimeZone().getTimeZone("UTC"))##
+#end
+
+#macro(format_value $val)
+#if(${val.class.name} == "java.util.Date")
+#utc_date($val)##
+#else
+$val##
+#end
+#end
+
+#macro(range_get_to_value $inval, $gapval)
+#if(${gapval.class.name} == "java.lang.String")
+$inval$gapval##
+#elseif(${gapval.class.name} == "java.lang.Float" || ${inval.class.name} == "java.lang.Float")
+$math.toDouble($math.add($inval,$gapval))##
+#else
+$math.add($inval,$gapval)##
+#end
+#end
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/browse.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/browse.vm
new file mode 100644
index 0000000..10ecaeb
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/browse.vm
@@ -0,0 +1,33 @@
+#**
+ *  Main entry point into the /browse templates
+ *#
+
+#set($searcher = $request.searcher)
+#set($params = $request.params)
+#set($clusters = $response.response.clusters)
+#set($mltResults = $response.response.get("moreLikeThis"))
+#set($annotate = $params.get("annotateBrowse"))
+#parse('query_form.vm')
+#parse('did_you_mean.vm')
+
+<div class="navigators">
+  #parse("facets.vm")
+</div>
+
+<div class="pagination">
+  #parse("pagination_top.vm")
+</div>
+
+## Show Error Message, if any
+<div class="error">
+  #parse("error.vm")
+</div>
+
+## Render Results, actual matching docs
+<div class="results">
+  #parse("results_list.vm")
+</div>
+
+<div class="pagination">
+  #parse("pagination_bottom.vm")
+</div>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/cluster.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/cluster.vm
new file mode 100644
index 0000000..bfe2f3b
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/cluster.vm
@@ -0,0 +1,19 @@
+#**
+ *  Check if Clustering is Enabled and then
+ *  call cluster_results.vm
+ *#
+
+<h2 #annTitle("Clusters generated by Carrot2 using the /clustering RequestHandler")>
+  Clusters
+</h2>
+
+## Div tag has placeholder text by default
+<div id="clusters">
+  Run Solr with java -Dsolr.clustering.enabled=true -jar start.jar to see clustered search results.
+</div>
+
+## Replace the div content *if* Carrot^2 is available
+<script type="text/javascript">
+  $('#clusters').load("#url_for_solr/clustering#lens",
+    {'wt':'velocity', 'v.template':"cluster_results"});
+</script>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/cluster_results.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/cluster_results.vm
new file mode 100644
index 0000000..204480d
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/cluster_results.vm
@@ -0,0 +1,31 @@
+#**
+ *  Actual rendering of Clusters
+ *#
+
+## For each cluster
+#foreach ($clusters in $response.response.clusters)
+
+  #set($labels = $clusters.get('labels'))
+  #set($docs = $clusters.get('docs'))
+
+  ## This Cluster's Heading
+  <h3>
+    #foreach ($label in $labels)
+      ## Keep the following line together to prevent
+      ## a space appearing before each comma
+      $label#if( $foreach.hasNext ),#end
+    #end
+  </h3>
+
+  ## This Cluster's Documents
+  <ol>
+    ## For each doc in this cluster
+    #foreach ($cluDoc in $docs)
+      <li>
+        <a href="#url_for_home?q=id:$cluDoc">
+          $cluDoc</a>
+      </li>
+    #end
+  </ol>
+
+#end   ## end for each Cluster
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/debug.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/debug.vm
new file mode 100644
index 0000000..8f6d232
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/debug.vm
@@ -0,0 +1,28 @@
+#**
+ *  Show Debugging Information, if enabled
+ *#
+
+#if( $params.getBool("debugQuery",false) )
+  <a href="#" onclick='jQuery(this).siblings("pre").toggle(); return false;'>
+    toggle explain</a>
+
+  <pre style="display:none">
+    $response.getExplainMap().get($doc.getFirstValue('id'))
+  </pre>
+
+  <a href="#" onclick='jQuery(this).siblings("pre2").toggle(); return false;'>
+    toggle all fields</a>
+
+  <pre2 style="display:none">
+    #foreach($fieldname in $doc.fieldNames)
+      <br>
+        <span class="field-name">$fieldname :</span>
+        <span>
+          #foreach($value in $doc.getFieldValues($fieldname))
+            $esc.html($value)
+          #end
+        </span>
+      </br>
+    #end
+  </pre2>
+#end
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/did_you_mean.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/did_you_mean.vm
new file mode 100644
index 0000000..b8faaa5
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/did_you_mean.vm
@@ -0,0 +1,9 @@
+#**
+ *  Hyperlinked spelling suggestions in results list
+ *#
+
+#set($dym = $response.response.spellcheck.suggestions.collation.collationQuery)
+#if($dym)
+  Did you mean
+  <a href="#{url_for_home}#{lensNoQ}&q=$esc.url($dym)">$esc.html($dym)</a>?
+#end
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/error.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/error.vm
new file mode 100644
index 0000000..80b5819
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/error.vm
@@ -0,0 +1,11 @@
+#**
+ *  Show Error Message, if any
+ *#
+
+## Show Error Message, if any
+## Usually rendered inside div class=error
+
+#if( $response.response.error.code )
+  <h1>ERROR $response.response.error.code</h1>
+  $response.response.error.msg
+#end
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facet_fields.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facet_fields.vm
new file mode 100644
index 0000000..d9db659
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facet_fields.vm
@@ -0,0 +1,23 @@
+#**
+ *  Display facets based on field values
+ *  e.g.: fields specified by &facet.field=
+ *#
+
+#if($response.facetFields)
+  <h2 #annTitle("Facets generated by adding &facet.field= to the request")>
+    Field Facets
+  </h2>
+  #foreach($field in $response.facetFields)
+    ## Hide facets without value
+    #if($field.values.size() > 0)
+      <span class="facet-field">$field.name</span>
+      <ul>
+        #foreach($facet in $field.values)
+          <li>
+            <a href="#url_for_facet_filter($field.name, $facet.name)">$facet.name</a> ($facet.count)
+          </li>
+        #end
+      </ul>
+    #end  ## end if > 0
+  #end    ## end for each facet field
+#end      ## end if response has facet fields
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facet_pivot.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facet_pivot.vm
new file mode 100644
index 0000000..7aa50da
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facet_pivot.vm
@@ -0,0 +1,12 @@
+#**
+ *  Display Pivot-Based Facets
+ *  e.g.: facets specified by &facet.pivot=
+ *#
+
+<h2 #annTitle("Facets generated by adding &facet.pivot= to the request")>
+  Pivot Facets
+</h2>
+
+#set($pivot = $response.response.facet_counts.facet_pivot)
+
+#display_facet_pivot($pivot, "")
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facet_queries.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facet_queries.vm
new file mode 100644
index 0000000..37489c7
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facet_queries.vm
@@ -0,0 +1,12 @@
+#**
+ *  Display facets based on specific facet queries
+ *  e.g.: facets specified by &facet.query=
+ *#
+
+#set($field = $response.response.facet_counts.facet_queries)
+
+<h2 #annTitle("Facets generated by adding &facet.query= to the request")>
+  Query Facets
+</h2>
+
+#display_facet_query($field, "", "")
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facet_ranges.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facet_ranges.vm
new file mode 100644
index 0000000..a61084b
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facet_ranges.vm
@@ -0,0 +1,23 @@
+#**
+ *  Display facets based on ranges of values, AKA "Bukets"
+ *  e.g.: ranges specified by &facet.range=
+ *#
+
+<h2 #annTitle("Facets generated by adding &facet.range= to the request")>
+  Range Facets
+</h2>
+
+#foreach ($field in $response.response.facet_counts.facet_ranges)
+  ## Hide facets without value
+  #if($field.value.counts.size() > 0)
+	#set($name = $field.key)
+	#set($display = $name)
+	#set($f = $field.value.counts)
+	#set($start = $field.value.start)
+	#set($end = $field.value.end)
+	#set($gap = $field.value.gap)
+	#set($before = $field.value.before)
+	#set($after = $field.value.after)
+	#display_facet_range($f, $display, $name, $start, $end, $gap, $before, $after)
+  #end  ## end if has any values
+#end    ## end for each facet range
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facets.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facets.vm
new file mode 100644
index 0000000..55d40c9
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/facets.vm
@@ -0,0 +1,10 @@
+#**
+ *  Overall Facet display block
+ *  Invokes the 4 facet and 1 cluster template
+ *#
+
+#parse('facet_fields.vm')
+#parse('facet_queries.vm')
+#parse('facet_ranges.vm')
+#parse('facet_pivot.vm')
+#parse('cluster.vm')
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/footer.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/footer.vm
new file mode 100644
index 0000000..0604c34
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/footer.vm
@@ -0,0 +1,43 @@
+#**
+ *  Render the bottom section of the page visible to users
+ *#
+
+<hr/>
+<div>
+  <span>Options:</span>
+
+  #if($request.params.get('debugQuery'))
+    <a href="#url_for_home?#q#if($list.size($request.params.getParams('fq')) > 0)&#fqs($request.params.getParams('fq'))#end">
+      disable debug</a>
+  #else
+    <a href="#url_for_lens&debugQuery=true&fl=*,score">
+      enable debug</a>
+  #end
+  -
+  #if($annotate)
+    <a href="#url_for_home?#q#if($list.size($request.params.getParams('fq')) > 0)&#fqs($request.params.getParams('fq'))#end#boostPrice">
+      disable annotation</a>
+  #else
+    <a href="#url_for_lens&annotateBrowse=true">
+      enable annotation</a>
+  #end
+  -
+  <a #annTitle("Click to switch to an XML response: &wt=xml") href="#url_for_lens&wt=xml#if($request.params.get('debugQuery'))&debugQuery=true#end">
+    XML results</a>
+
+</div>
+
+<div>
+  Generated by <a href="http://wiki.apache.org/solr/VelocityResponseWriter">VelocityResponseWriter</a>
+</div>
+<div>
+  <span>Documentation: </span>
+  <a href="http://lucene.apache.org/solr">Solr Home Page</a>, <a href="http://wiki.apache.org/solr">
+    Solr Wiki</a>
+  </div>
+<div>
+  Disclaimer:
+  The locations displayed in this demonstration are purely fictional.
+  It is more than likely that no store with the items listed actually
+  exists at that location!
+</div>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/head.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/head.vm
new file mode 100644
index 0000000..d1f6ee6
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/head.vm
@@ -0,0 +1,35 @@
+#**
+ *  Provide elements for the <head> section of the HTML document
+ *#
+
+  ## An example of using an arbitrary request parameter
+  <title>#param('title')</title>
+  <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
+
+  <script type="text/javascript" src="#{url_root}/js/lib/jquery-1.7.2.min.js"></script>
+  <link rel="stylesheet" type="text/css" href="#{url_for_solr}/admin/file?file=/velocity/main.css&contentType=text/css"/>
+  <link rel="stylesheet" href="#{url_for_solr}/admin/file?file=/velocity/jquery.autocomplete.css&contentType=text/css" type="text/css" />
+  <script type="text/javascript" src="#{url_for_solr}/admin/file?file=/velocity/jquery.autocomplete.js&contentType=text/javascript"></script>
+
+
+    <script>
+    $(document).ready(function(){
+      $("\#q").autocomplete('#{url_for_solr}/terms', {  ## backslash escaped #q as that is a macro defined in VM_global_library.vm
+           extraParams:{
+             'terms.prefix': function() { return $("\#q").val();},
+             'terms.sort': 'count',
+             'terms.fl': 'name',
+             'wt': 'velocity',
+             'v.template': 'suggest'
+           }
+         }
+      ).keydown(function(e){
+        if (e.keyCode === 13){
+          $("#query-form").trigger('submit');
+        }
+      });
+
+      // http://localhost:8983/solr/collection1/terms?terms.fl=name&terms.prefix=i&terms.sort=count&wt=velocity&v.template=suggest
+    });
+
+    </script>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/header.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/header.vm
new file mode 100644
index 0000000..6866047
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/header.vm
@@ -0,0 +1,7 @@
+#**
+ *  Render the top section of the page visible to users
+ *#
+
+<div id="head">
+  <span ><a href="#url_for_home#if($request.params.get('debugQuery'))?debugQuery=true#end"><img src="#{url_root}/img/solr.png" id="logo"/></a></span>
+</div>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/hit.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/hit.vm
new file mode 100644
index 0000000..a9c11f4
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/hit.vm
@@ -0,0 +1,25 @@
+#**
+ *  Called for each matching document but then
+ *  calls one of product_doc, join_doc or richtext_doc
+ *  depending on which fields the doc has
+ *#
+
+#set($docId = $doc.getFieldValue('id'))
+
+<div class="result-document">
+
+  ## Has a "name" field ?
+  #if($doc.getFieldValue('name'))
+    #parse("product_doc.vm")
+
+  ## Has a "compName_s" field ?
+  #elseif($doc.getFieldValue('compName_s'))
+    #parse("join_doc.vm")
+
+  ## Fallback to richtext_doc
+  #else
+    #parse("richtext_doc.vm")
+
+  #end
+
+</div>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/hit_grouped.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/hit_grouped.vm
new file mode 100644
index 0000000..5297f1e
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/hit_grouped.vm
@@ -0,0 +1,43 @@
+#**
+ *  Display grouped results
+ *#
+
+<div class="result-document">
+
+  <div class="result-title">
+    <b>$grouping.key</b>
+  </div>
+
+  <div>
+    Total Matches in Group: $grouping.value.matches
+  </div>
+
+  <div>  ## list of groups
+
+    #foreach ($group in $grouping.value.groups)
+      <div class="group-value">
+        #if($group.groupValue)$group.groupValue#{else}<i>No group</i>#end
+        <span #annTitle("The count of the number of documents in this group")>
+          ($group.doclist.numFound)
+        </span>
+      </div>
+
+      <div class="group-doclist"
+        #annTitle("Contains the top scoring documents in the group")
+      >
+        #foreach ($doc in $group.doclist)
+          #set($docId = $doc.getFieldValue('id'))
+          #if($doc.getFieldValue('name'))
+            #parse("product_doc.vm")
+          #elseif($doc.getFieldValue('compName_s'))
+            #parse("join_doc.vm")
+          #else
+            #parse("richtext_doc.vm")
+          #end
+        #end
+      </div>
+
+    #end  ## end of foreach group in grouping.value.groups
+  </div>  ## div tag for entire list of groups
+
+</div>  ## end of div class=result-document
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/hit_plain.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/hit_plain.vm
new file mode 100644
index 0000000..193439b
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/hit_plain.vm
@@ -0,0 +1,25 @@
+#**
+ *  An extremely plain / debug version of hit.vm
+ *#
+
+<table>
+  ## For each field
+  #foreach( $fieldName in $doc.fieldNames )
+    ## For each value
+    #foreach( $value in $doc.getFieldValues($fieldName) )
+      <tr>
+        ## Field Name
+        <th align="right" valign="top">
+          #if( $foreach.count == 1 )
+            $fieldName:
+          #end
+        </th>
+        ## Field Value(s)
+        <td align="left" valign="top">
+          $esc.html($value) <br/>
+        </td>
+      </tr>
+    #end     ## end for each value
+  #end       ## end for each field
+</table>
+<hr/>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/join_doc.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/join_doc.vm
new file mode 100644
index 0000000..9956012
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/join_doc.vm
@@ -0,0 +1,20 @@
+#**
+ *  Display documents that are joined to other documents
+ *#
+
+<div class="result-title">
+  <b>#field('compName_s')</b>
+</div>
+
+<div>
+  Id: #field('id')
+  (company-details document for
+    <a href="http://wiki.apache.org/solr/Join" target="_new">join</a>
+  )
+</div>
+
+<div>
+  Address: #field('address_s')
+</div>
+
+#parse('debug.vm')
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/jquery.autocomplete.css b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/jquery.autocomplete.css
new file mode 100644
index 0000000..91b6228
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/jquery.autocomplete.css
@@ -0,0 +1,48 @@
+.ac_results {
+	padding: 0px;
+	border: 1px solid black;
+	background-color: white;
+	overflow: hidden;
+	z-index: 99999;
+}
+
+.ac_results ul {
+	width: 100%;
+	list-style-position: outside;
+	list-style: none;
+	padding: 0;
+	margin: 0;
+}
+
+.ac_results li {
+	margin: 0px;
+	padding: 2px 5px;
+	cursor: default;
+	display: block;
+	/* 
+	if width will be 100% horizontal scrollbar will apear 
+	when scroll mode will be used
+	*/
+	/*width: 100%;*/
+	font: menu;
+	font-size: 12px;
+	/* 
+	it is very important, if line-height not setted or setted 
+	in relative units scroll will be broken in firefox
+	*/
+	line-height: 16px;
+	overflow: hidden;
+}
+
+.ac_loading {
+	background: white url('indicator.gif') right center no-repeat;
+}
+
+.ac_odd {
+	background-color: #eee;
+}
+
+.ac_over {
+	background-color: #0A246A;
+	color: white;
+}
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/jquery.autocomplete.js b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/jquery.autocomplete.js
new file mode 100644
index 0000000..09bb376
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/jquery.autocomplete.js
@@ -0,0 +1,763 @@
+/*
+ * Autocomplete - jQuery plugin 1.1pre
+ *
+ * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id: jquery.autocomplete.js 5785 2008-07-12 10:37:33Z joern.zaefferer $
+ *
+ */
+
+;(function($) {
+	
+$.fn.extend({
+	autocomplete: function(urlOrData, options) {
+		var isUrl = typeof urlOrData == "string";
+		options = $.extend({}, $.Autocompleter.defaults, {
+			url: isUrl ? urlOrData : null,
+			data: isUrl ? null : urlOrData,
+			delay: isUrl ? $.Autocompleter.defaults.delay : 10,
+			max: options && !options.scroll ? 10 : 150
+		}, options);
+		
+		// if highlight is set to false, replace it with a do-nothing function
+		options.highlight = options.highlight || function(value) { return value; };
+		
+		// if the formatMatch option is not specified, then use formatItem for backwards compatibility
+		options.formatMatch = options.formatMatch || options.formatItem;
+		
+		return this.each(function() {
+			new $.Autocompleter(this, options);
+		});
+	},
+	result: function(handler) {
+		return this.bind("result", handler);
+	},
+	search: function(handler) {
+		return this.trigger("search", [handler]);
+	},
+	flushCache: function() {
+		return this.trigger("flushCache");
+	},
+	setOptions: function(options){
+		return this.trigger("setOptions", [options]);
+	},
+	unautocomplete: function() {
+		return this.trigger("unautocomplete");
+	}
+});
+
+$.Autocompleter = function(input, options) {
+
+	var KEY = {
+		UP: 38,
+		DOWN: 40,
+		DEL: 46,
+		TAB: 9,
+		RETURN: 13,
+		ESC: 27,
+		COMMA: 188,
+		PAGEUP: 33,
+		PAGEDOWN: 34,
+		BACKSPACE: 8
+	};
+
+	// Create $ object for input element
+	var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass);
+
+	var timeout;
+	var previousValue = "";
+	var cache = $.Autocompleter.Cache(options);
+	var hasFocus = 0;
+	var lastKeyPressCode;
+	var config = {
+		mouseDownOnSelect: false
+	};
+	var select = $.Autocompleter.Select(options, input, selectCurrent, config);
+	
+	var blockSubmit;
+	
+	// prevent form submit in opera when selecting with return key
+	$.browser.opera && $(input.form).bind("submit.autocomplete", function() {
+		if (blockSubmit) {
+			blockSubmit = false;
+			return false;
+		}
+	});
+	
+	// only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
+	$input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
+		// track last key pressed
+		lastKeyPressCode = event.keyCode;
+		switch(event.keyCode) {
+		
+			case KEY.UP:
+				event.preventDefault();
+				if ( select.visible() ) {
+					select.prev();
+				} else {
+					onChange(0, true);
+				}
+				break;
+				
+			case KEY.DOWN:
+				event.preventDefault();
+				if ( select.visible() ) {
+					select.next();
+				} else {
+					onChange(0, true);
+				}
+				break;
+				
+			case KEY.PAGEUP:
+				event.preventDefault();
+				if ( select.visible() ) {
+					select.pageUp();
+				} else {
+					onChange(0, true);
+				}
+				break;
+				
+			case KEY.PAGEDOWN:
+				event.preventDefault();
+				if ( select.visible() ) {
+					select.pageDown();
+				} else {
+					onChange(0, true);
+				}
+				break;
+			
+			// matches also semicolon
+			case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
+			case KEY.TAB:
+			case KEY.RETURN:
+				if( selectCurrent() ) {
+					// stop default to prevent a form submit, Opera needs special handling
+					event.preventDefault();
+					blockSubmit = true;
+					return false;
+				}
+				break;
+				
+			case KEY.ESC:
+				select.hide();
+				break;
+				
+			default:
+				clearTimeout(timeout);
+				timeout = setTimeout(onChange, options.delay);
+				break;
+		}
+	}).focus(function(){
+		// track whether the field has focus, we shouldn't process any
+		// results if the field no longer has focus
+		hasFocus++;
+	}).blur(function() {
+		hasFocus = 0;
+		if (!config.mouseDownOnSelect) {
+			hideResults();
+		}
+	}).click(function() {
+		// show select when clicking in a focused field
+		if ( hasFocus++ > 1 && !select.visible() ) {
+			onChange(0, true);
+		}
+	}).bind("search", function() {
+		// TODO why not just specifying both arguments?
+		var fn = (arguments.length > 1) ? arguments[1] : null;
+		function findValueCallback(q, data) {
+			var result;
+			if( data && data.length ) {
+				for (var i=0; i < data.length; i++) {
+					if( data[i].result.toLowerCase() == q.toLowerCase() ) {
+						result = data[i];
+						break;
+					}
+				}
+			}
+			if( typeof fn == "function" ) fn(result);
+			else $input.trigger("result", result && [result.data, result.value]);
+		}
+		$.each(trimWords($input.val()), function(i, value) {
+			request(value, findValueCallback, findValueCallback);
+		});
+	}).bind("flushCache", function() {
+		cache.flush();
+	}).bind("setOptions", function() {
+		$.extend(options, arguments[1]);
+		// if we've updated the data, repopulate
+		if ( "data" in arguments[1] )
+			cache.populate();
+	}).bind("unautocomplete", function() {
+		select.unbind();
+		$input.unbind();
+		$(input.form).unbind(".autocomplete");
+	});
+	
+	
+	function selectCurrent() {
+		var selected = select.selected();
+		if( !selected )
+			return false;
+		
+		var v = selected.result;
+		previousValue = v;
+		
+		if ( options.multiple ) {
+			var words = trimWords($input.val());
+			if ( words.length > 1 ) {
+				v = words.slice(0, words.length - 1).join( options.multipleSeparator ) + options.multipleSeparator + v;
+			}
+			v += options.multipleSeparator;
+		}
+		
+		$input.val(v);
+		hideResultsNow();
+		$input.trigger("result", [selected.data, selected.value]);
+		return true;
+	}
+	
+	function onChange(crap, skipPrevCheck) {
+		if( lastKeyPressCode == KEY.DEL ) {
+			select.hide();
+			return;
+		}
+		
+		var currentValue = $input.val();
+		
+		if ( !skipPrevCheck && currentValue == previousValue )
+			return;
+		
+		previousValue = currentValue;
+		
+		currentValue = lastWord(currentValue);
+		if ( currentValue.length >= options.minChars) {
+			$input.addClass(options.loadingClass);
+			if (!options.matchCase)
+				currentValue = currentValue.toLowerCase();
+			request(currentValue, receiveData, hideResultsNow);
+		} else {
+			stopLoading();
+			select.hide();
+		}
+	};
+	
+	function trimWords(value) {
+		if ( !value ) {
+			return [""];
+		}
+		var words = value.split( options.multipleSeparator );
+		var result = [];
+		$.each(words, function(i, value) {
+			if ( $.trim(value) )
+				result[i] = $.trim(value);
+		});
+		return result;
+	}
+	
+	function lastWord(value) {
+		if ( !options.multiple )
+			return value;
+		var words = trimWords(value);
+		return words[words.length - 1];
+	}
+	
+	// fills in the input box w/the first match (assumed to be the best match)
+	// q: the term entered
+	// sValue: the first matching result
+	function autoFill(q, sValue){
+		// autofill in the complete box w/the first match as long as the user hasn't entered in more data
+		// if the last user key pressed was backspace, don't autofill
+		if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) {
+			// fill in the value (keep the case the user has typed)
+			$input.val($input.val() + sValue.substring(lastWord(previousValue).length));
+			// select the portion of the value not typed by the user (so the next character will erase)
+			$.Autocompleter.Selection(input, previousValue.length, previousValue.length + sValue.length);
+		}
+	};
+
+	function hideResults() {
+		clearTimeout(timeout);
+		timeout = setTimeout(hideResultsNow, 200);
+	};
+
+	function hideResultsNow() {
+		var wasVisible = select.visible();
+		select.hide();
+		clearTimeout(timeout);
+		stopLoading();
+		if (options.mustMatch) {
+			// call search and run callback
+			$input.search(
+				function (result){
+					// if no value found, clear the input box
+					if( !result ) {
+						if (options.multiple) {
+							var words = trimWords($input.val()).slice(0, -1);
+							$input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") );
+						}
+						else
+							$input.val( "" );
+					}
+				}
+			);
+		}
+		if (wasVisible)
+			// position cursor at end of input field
+			$.Autocompleter.Selection(input, input.value.length, input.value.length);
+	};
+
+	function receiveData(q, data) {
+		if ( data && data.length && hasFocus ) {
+			stopLoading();
+			select.display(data, q);
+			autoFill(q, data[0].value);
+			select.show();
+		} else {
+			hideResultsNow();
+		}
+	};
+
+	function request(term, success, failure) {
+		if (!options.matchCase)
+			term = term.toLowerCase();
+		var data = cache.load(term);
+		data = null; // Avoid buggy cache and go to Solr every time 
+		// recieve the cached data
+		if (data && data.length) {
+			success(term, data);
+		// if an AJAX url has been supplied, try loading the data now
+		} else if( (typeof options.url == "string") && (options.url.length > 0) ){
+			
+			var extraParams = {
+				timestamp: +new Date()
+			};
+			$.each(options.extraParams, function(key, param) {
+				extraParams[key] = typeof param == "function" ? param() : param;
+			});
+			
+			$.ajax({
+				// try to leverage ajaxQueue plugin to abort previous requests
+				mode: "abort",
+				// limit abortion to this input
+				port: "autocomplete" + input.name,
+				dataType: options.dataType,
+				url: options.url,
+				data: $.extend({
+					q: lastWord(term),
+					limit: options.max
+				}, extraParams),
+				success: function(data) {
+					var parsed = options.parse && options.parse(data) || parse(data);
+					cache.add(term, parsed);
+					success(term, parsed);
+				}
+			});
+		} else {
+			// if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match
+			select.emptyList();
+			failure(term);
+		}
+	};
+	
+	function parse(data) {
+		var parsed = [];
+		var rows = data.split("\n");
+		for (var i=0; i < rows.length; i++) {
+			var row = $.trim(rows[i]);
+			if (row) {
+				row = row.split("|");
+				parsed[parsed.length] = {
+					data: row,
+					value: row[0],
+					result: options.formatResult && options.formatResult(row, row[0]) || row[0]
+				};
+			}
+		}
+		return parsed;
+	};
+
+	function stopLoading() {
+		$input.removeClass(options.loadingClass);
+	};
+
+};
+
+$.Autocompleter.defaults = {
+	inputClass: "ac_input",
+	resultsClass: "ac_results",
+	loadingClass: "ac_loading",
+	minChars: 1,
+	delay: 400,
+	matchCase: false,
+	matchSubset: true,
+	matchContains: false,
+	cacheLength: 10,
+	max: 100,
+	mustMatch: false,
+	extraParams: {},
+	selectFirst: false,
+	formatItem: function(row) { return row[0]; },
+	formatMatch: null,
+	autoFill: false,
+	width: 0,
+	multiple: false,
+	multipleSeparator: ", ",
+	highlight: function(value, term) {
+		return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
+	},
+    scroll: true,
+    scrollHeight: 180
+};
+
+$.Autocompleter.Cache = function(options) {
+
+	var data = {};
+	var length = 0;
+	
+	function matchSubset(s, sub) {
+		if (!options.matchCase) 
+			s = s.toLowerCase();
+		var i = s.indexOf(sub);
+		if (options.matchContains == "word"){
+			i = s.toLowerCase().search("\\b" + sub.toLowerCase());
+		}
+		if (i == -1) return false;
+		return i == 0 || options.matchContains;
+	};
+	
+	function add(q, value) {
+		if (length > options.cacheLength){
+			flush();
+		}
+		if (!data[q]){ 
+			length++;
+		}
+		data[q] = value;
+	}
+	
+	function populate(){
+		if( !options.data ) return false;
+		// track the matches
+		var stMatchSets = {},
+			nullData = 0;
+
+		// no url was specified, we need to adjust the cache length to make sure it fits the local data store
+		if( !options.url ) options.cacheLength = 1;
+		
+		// track all options for minChars = 0
+		stMatchSets[""] = [];
+		
+		// loop through the array and create a lookup structure
+		for ( var i = 0, ol = options.data.length; i < ol; i++ ) {
+			var rawValue = options.data[i];
+			// if rawValue is a string, make an array otherwise just reference the array
+			rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue;
+			
+			var value = options.formatMatch(rawValue, i+1, options.data.length);
+			if ( value === false )
+				continue;
+				
+			var firstChar = value.charAt(0).toLowerCase();
+			// if no lookup array for this character exists, look it up now
+			if( !stMatchSets[firstChar] ) 
+				stMatchSets[firstChar] = [];
+
+			// if the match is a string
+			var row = {
+				value: value,
+				data: rawValue,
+				result: options.formatResult && options.formatResult(rawValue) || value
+			};
+			
+			// push the current match into the set list
+			stMatchSets[firstChar].push(row);
+
+			// keep track of minChars zero items
+			if ( nullData++ < options.max ) {
+				stMatchSets[""].push(row);
+			}
+		};
+
+		// add the data items to the cache
+		$.each(stMatchSets, function(i, value) {
+			// increase the cache size
+			options.cacheLength++;
+			// add to the cache
+			add(i, value);
+		});
+	}
+	
+	// populate any existing data
+	setTimeout(populate, 25);
+	
+	function flush(){
+		data = {};
+		length = 0;
+	}
+	
+	return {
+		flush: flush,
+		add: add,
+		populate: populate,
+		load: function(q) {
+			if (!options.cacheLength || !length)
+				return null;
+			/* 
+			 * if dealing w/local data and matchContains than we must make sure
+			 * to loop through all the data collections looking for matches
+			 */
+			if( !options.url && options.matchContains ){
+				// track all matches
+				var csub = [];
+				// loop through all the data grids for matches
+				for( var k in data ){
+					// don't search through the stMatchSets[""] (minChars: 0) cache
+					// this prevents duplicates
+					if( k.length > 0 ){
+						var c = data[k];
+						$.each(c, function(i, x) {
+							// if we've got a match, add it to the array
+							if (matchSubset(x.value, q)) {
+								csub.push(x);
+							}
+						});
+					}
+				}				
+				return csub;
+			} else 
+			// if the exact item exists, use it
+			if (data[q]){
+				return data[q];
+			} else
+			if (options.matchSubset) {
+				for (var i = q.length - 1; i >= options.minChars; i--) {
+					var c = data[q.substr(0, i)];
+					if (c) {
+						var csub = [];
+						$.each(c, function(i, x) {
+							if (matchSubset(x.value, q)) {
+								csub[csub.length] = x;
+							}
+						});
+						return csub;
+					}
+				}
+			}
+			return null;
+		}
+	};
+};
+
+$.Autocompleter.Select = function (options, input, select, config) {
+	var CLASSES = {
+		ACTIVE: "ac_over"
+	};
+	
+	var listItems,
+		active = -1,
+		data,
+		term = "",
+		needsInit = true,
+		element,
+		list;
+	
+	// Create results
+	function init() {
+		if (!needsInit)
+			return;
+		element = $("<div/>")
+		.hide()
+		.addClass(options.resultsClass)
+		.css("position", "absolute")
+		.appendTo(document.body);
+	
+		list = $("<ul/>").appendTo(element).mouseover( function(event) {
+			if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') {
+	            active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event));
+			    $(target(event)).addClass(CLASSES.ACTIVE);            
+	        }
+		}).click(function(event) {
+			$(target(event)).addClass(CLASSES.ACTIVE);
+			select();
+			// TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus
+			input.focus();
+			return false;
+		}).mousedown(function() {
+			config.mouseDownOnSelect = true;
+		}).mouseup(function() {
+			config.mouseDownOnSelect = false;
+		});
+		
+		if( options.width > 0 )
+			element.css("width", options.width);
+			
+		needsInit = false;
+	} 
+	
+	function target(event) {
+		var element = event.target;
+		while(element && element.tagName != "LI")
+			element = element.parentNode;
+		// more fun with IE, sometimes event.target is empty, just ignore it then
+		if(!element)
+			return [];
+		return element;
+	}
+
+	function moveSelect(step) {
+		listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE);
+		movePosition(step);
+        var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE);
+        if(options.scroll) {
+            var offset = 0;
+            listItems.slice(0, active).each(function() {
+				offset += this.offsetHeight;
+			});
+            if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) {
+                list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight());
+            } else if(offset < list.scrollTop()) {
+                list.scrollTop(offset);
+            }
+        }
+	};
+	
+	function movePosition(step) {
+		active += step;
+		if (active < 0) {
+			active = listItems.size() - 1;
+		} else if (active >= listItems.size()) {
+			active = 0;
+		}
+	}
+	
+	function limitNumberOfItems(available) {
+		return options.max && options.max < available
+			? options.max
+			: available;
+	}
+	
+	function fillList() {
+		list.empty();
+		var max = limitNumberOfItems(data.length);
+		for (var i=0; i < max; i++) {
+			if (!data[i])
+				continue;
+			var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term);
+			if ( formatted === false )
+				continue;
+			var li = $("<li/>").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
+			$.data(li, "ac_data", data[i]);
+		}
+		listItems = list.find("li");
+		if ( options.selectFirst ) {
+			listItems.slice(0, 1).addClass(CLASSES.ACTIVE);
+			active = 0;
+		}
+		// apply bgiframe if available
+		if ( $.fn.bgiframe )
+			list.bgiframe();
+	}
+	
+	return {
+		display: function(d, q) {
+			init();
+			data = d;
+			term = q;
+			fillList();
+		},
+		next: function() {
+			moveSelect(1);
+		},
+		prev: function() {
+			moveSelect(-1);
+		},
+		pageUp: function() {
+			if (active != 0 && active - 8 < 0) {
+				moveSelect( -active );
+			} else {
+				moveSelect(-8);
+			}
+		},
+		pageDown: function() {
+			if (active != listItems.size() - 1 && active + 8 > listItems.size()) {
+				moveSelect( listItems.size() - 1 - active );
+			} else {
+				moveSelect(8);
+			}
+		},
+		hide: function() {
+			element && element.hide();
+			listItems && listItems.removeClass(CLASSES.ACTIVE);
+			active = -1;
+		},
+		visible : function() {
+			return element && element.is(":visible");
+		},
+		current: function() {
+			return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]);
+		},
+		show: function() {
+			var offset = $(input).offset();
+			element.css({
+				width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(),
+				top: offset.top + input.offsetHeight,
+				left: offset.left
+			}).show();
+            if(options.scroll) {
+                list.scrollTop(0);
+                list.css({
+					maxHeight: options.scrollHeight,
+					overflow: 'auto'
+				});
+				
+                if($.browser.msie && typeof document.body.style.maxHeight === "undefined") {
+					var listHeight = 0;
+					listItems.each(function() {
+						listHeight += this.offsetHeight;
+					});
+					var scrollbarsVisible = listHeight > options.scrollHeight;
+                    list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight );
+					if (!scrollbarsVisible) {
+						// IE doesn't recalculate width when scrollbar disappears
+						listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) );
+					}
+                }
+                
+            }
+		},
+		selected: function() {
+			var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);
+			return selected && selected.length && $.data(selected[0], "ac_data");
+		},
+		emptyList: function (){
+			list && list.empty();
+		},
+		unbind: function() {
+			element && element.remove();
+		}
+	};
+};
+
+$.Autocompleter.Selection = function(field, start, end) {
+	if( field.createTextRange ){
+		var selRange = field.createTextRange();
+		selRange.collapse(true);
+		selRange.moveStart("character", start);
+		selRange.moveEnd("character", end);
+		selRange.select();
+	} else if( field.setSelectionRange ){
+		field.setSelectionRange(start, end);
+	} else {
+		if( field.selectionStart ){
+			field.selectionStart = start;
+			field.selectionEnd = end;
+		}
+	}
+	field.focus();
+};
+
+})(jQuery);
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/layout.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/layout.vm
new file mode 100644
index 0000000..50f4c1b
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/layout.vm
@@ -0,0 +1,24 @@
+#**
+ *  Overall HTML page layout
+ *#
+
+<html>
+<head>
+  #parse("head.vm")
+</head>
+  <body>
+    <div id="admin"><a href="#url_root/#/#core_name">Solr Admin</a></div>
+    <div id="header">
+      #parse("header.vm")
+    </div>
+    <div id="tabs">
+      #parse("tabs.vm")
+    </div>
+    <div id="content">
+      $content
+    </div>
+    <div id="footer">
+      #parse("footer.vm")
+    </div>
+  </body>
+</html>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/main.css b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/main.css
new file mode 100644
index 0000000..0aed533
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/main.css
@@ -0,0 +1,230 @@
+#admin{
+  text-align: right;
+  vertical-align: top; 
+}
+
+#head{
+  width: 100%;
+}
+.array-field {
+  border: 2px solid #474747;
+  background: #FFE9D8;
+  padding: 5px;
+  margin: 5px;
+}
+
+.array-field-list li {
+  list-style: circle;
+  margin-left: 20px;
+}
+
+.parsed_query_header {
+  font-family: Helvetica, Arial, sans-serif;
+  font-size: 10pt;
+  font-weight: bold;
+}
+
+.parsed_query {
+  font-family: Courier, Courier New, monospaced;
+  font-size: 10pt;
+  font-weight: normal;
+}
+
+body {
+  font-family: Helvetica, Arial, sans-serif;
+  font-size: 10pt;
+}
+
+a {
+  color: #43a4b1;
+}
+
+.navigators {
+  float: left;
+  margin: 5px;
+  margin-top: 0px;
+  width: 185px;
+  padding: 5px;
+  top: -20px;
+  position: relative;  
+}
+
+.tabs-bar {
+  padding: 5px;
+  width: 100%;
+  border: 1px solid;
+  border-width: 0px 0px 1px 0px;
+}
+.tab {
+  font-weight: bold;
+  padding: 5px;
+  margin: 0px 5px;
+  border: 1px solid;
+  background-color: #dddddd;
+  border-top-left-radius: 4px;
+  border-top-right-radius: 4px;
+}
+.tab:hover {
+  background: #FEC293;
+}
+.tab.selected {
+  background-color: #ffffff;
+  border-bottom: 1px solid #ffffff;
+}
+
+.navigators h2 {
+  background: #FEC293;
+  padding: 2px 5px;
+}
+
+.navigators ul {
+  list-style: none;
+  margin: 0;
+  margin-bottom: 5px;
+  margin-top: 5px;
+  padding-left: 10px;
+}
+
+.navigators ul li {
+  color: #999;
+  padding: 2px;
+}
+
+
+
+.facet-field {
+  font-weight: bold;
+}
+
+.highlight {
+  color: white;
+  background-color: gray;
+  border: 1px black solid;
+}
+
+.highlight-box {
+  margin-left: 15px;
+}
+
+.field-name {
+  font-weight: bold;
+}
+
+.highlighted-facet-field {
+  background: white;
+}
+
+.constraints {
+  margin-top: 10px;
+}
+
+#query-form{
+  width: 80%;
+}
+
+
+
+.query-box, .constraints {
+  padding: 5px;
+  margin: 5px;
+  font-weight: normal;
+  font-size: 24px;
+  letter-spacing: 0.08em;
+}
+
+.query-box #q {
+  margin-left: 8px;
+  width: 60%;
+  height: 50px;
+  border: 1px solid #999;
+  font-size: 1em;
+  padding: 0.4em;
+}
+
+.query-box {
+  
+}
+
+.query-boost {
+  
+  top: 10px;
+  left: 50px;
+  position: relative;
+  font-size: 0.8em;
+}
+
+.query-box .inputs{
+  left: 180px;
+  position: relative;
+  
+}
+
+#logo {
+  margin: 10px;
+  border-style: none;
+}
+
+.pagination {
+  padding-left: 33%;
+  background: #eee;
+  margin: 5px;
+  margin-left: 210px;
+  padding-top: 5px;
+  padding-bottom: 5px;
+}
+
+.result-document {
+  border: 1px solid #999;
+  padding: 5px;
+  margin: 5px;
+  margin-left: 210px;
+  margin-bottom: 15px;
+}
+
+.result-document div{
+  padding: 5px;
+}
+
+.result-title{
+  width:60%;
+}
+
+.result-body{
+  background: #ddd;
+}
+
+.mlt{
+  
+}
+
+.map{
+  float: right;
+  position: relative;
+  top: -25px;  
+}
+
+.result-document:nth-child(2n+1) {
+  background-color: #eee;
+}
+
+
+.selected-facet-field {
+  font-weight: bold;
+}
+
+li.show {
+  list-style: disc;
+}
+
+.group-value{
+  font-weight: bold;
+}
+
+.error {
+  color: white;
+  background-color: red;
+  left: 210px;
+  width:80%;
+  position: relative;
+
+}
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/mime_type_lists.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/mime_type_lists.vm
new file mode 100644
index 0000000..1468bbd
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/mime_type_lists.vm
@@ -0,0 +1,68 @@
+#**
+ *  Define some Mime-Types, short and long form
+ *#
+
+## MimeType to extension map for detecting file type
+## and showing proper icon
+## List of types match the icons in /solr/img/filetypes
+
+## Short MimeType Names
+## Was called $supportedtypes
+#set($supportedMimeTypes = "7z;ai;aiff;asc;audio;bin;bz2;c;cfc;cfm;chm;class;conf;cpp;cs;css;csv;deb;divx;doc;dot;eml;enc;file;gif;gz;hlp;htm;html;image;iso;jar;java;jpeg;jpg;js;lua;m;mm;mov;mp3;mpg;odc;odf;odg;odi;odp;ods;odt;ogg;pdf;pgp;php;pl;png;ppt;ps;py;ram;rar;rb;rm;rpm;rtf;sig;sql;swf;sxc;sxd;sxi;sxw;tar;tex;tgz;txt;vcf;video;vsd;wav;wma;wmv;xls;xml;xpi;xvid;zip")
+
+## Long Form: map MimeType headers to our Short names
+## Was called $extMap
+#set( $mimeExtensionsMap = {
+   "application/x-7z-compressed": "7z",
+   "application/postscript": "ai",
+   "application/pgp-signature": "asc",
+   "application/octet-stream": "bin",
+   "application/x-bzip2": "bz2",
+   "text/x-c": "c",
+   "application/vnd.ms-htmlhelp": "chm",
+   "application/java-vm": "class",
+   "text/css": "css",
+   "text/csv": "csv",
+   "application/x-debian-package": "deb",
+   "application/msword": "doc",
+   "message/rfc822": "eml",
+   "image/gif": "gif",
+   "application/winhlp": "hlp",
+   "text/html": "html",
+   "application/java-archive": "jar",
+   "text/x-java-source": "java",
+   "image/jpeg": "jpeg",
+   "application/javascript": "js",
+   "application/vnd.oasis.opendocument.chart": "odc",
+   "application/vnd.oasis.opendocument.formula": "odf",
+   "application/vnd.oasis.opendocument.graphics": "odg",
+   "application/vnd.oasis.opendocument.image": "odi",
+   "application/vnd.oasis.opendocument.presentation": "odp",
+   "application/vnd.oasis.opendocument.spreadsheet": "ods",
+   "application/vnd.oasis.opendocument.text": "odt",
+   "application/pdf": "pdf",
+   "application/pgp-encrypted": "pgp",
+   "image/png": "png",
+   "application/vnd.ms-powerpoint": "ppt",
+   "audio/x-pn-realaudio": "ram",
+   "application/x-rar-compressed": "rar",
+   "application/vnd.rn-realmedia": "rm",
+   "application/rtf": "rtf",
+   "application/x-shockwave-flash": "swf",
+   "application/vnd.sun.xml.calc": "sxc",
+   "application/vnd.sun.xml.draw": "sxd",
+   "application/vnd.sun.xml.impress": "sxi",
+   "application/vnd.sun.xml.writer": "sxw",
+   "application/x-tar": "tar",
+   "application/x-tex": "tex",
+   "text/plain": "txt",
+   "text/x-vcard": "vcf",
+   "application/vnd.visio": "vsd",
+   "audio/x-wav": "wav",
+   "audio/x-ms-wma": "wma",
+   "video/x-ms-wmv": "wmv",
+   "application/vnd.ms-excel": "xls",
+   "application/xml": "xml",
+   "application/x-xpinstall": "xpi",
+   "application/zip": "zip"
+})
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/pagination_bottom.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/pagination_bottom.vm
new file mode 100644
index 0000000..71b8bdf
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/pagination_bottom.vm
@@ -0,0 +1,22 @@
+#**
+ *  Paging and Statistics at bottom of results
+ *#
+
+## Usually rendered in pagination div tag
+
+#if($response.response.get('grouped'))
+  ## pass
+#else
+
+  #link_to_previous_page("previous")
+
+  <span class="results-found">$page.results_found</span>
+  results found.
+
+  Page <span class="page-num">$page.current_page_number</span>
+    of <span class="page-count">$page.page_count</span>
+
+  #link_to_next_page("next")
+
+#end
+<br/>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/pagination_top.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/pagination_top.vm
new file mode 100644
index 0000000..e0ac8ac
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/pagination_top.vm
@@ -0,0 +1,29 @@
+#**
+ *  Paging and Statistics at top of results
+ *#
+
+## Usually rendered in pagination div tag
+
+## Grouped Results / Not Paginated
+#if($response.response.get('grouped'))
+
+  <span>
+    <span class="results-found">
+      $response.response.get('grouped').size() group(s)
+    </span>
+    found in ${response.responseHeader.QTime} ms
+  </span>
+
+## Regular Results / Use Paging Links if needed
+#else
+
+  <span>
+    <span class="results-found">$page.results_found</span>
+    results found in
+    ${response.responseHeader.QTime} ms
+  </span>
+
+  Page <span class="page-num">$page.current_page_number</span>
+    of <span class="page-count">$page.page_count</span>
+
+#end   ## end else non-grouped results, normal pagination
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/product_doc.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/product_doc.vm
new file mode 100644
index 0000000..c878d8c
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/product_doc.vm
@@ -0,0 +1,32 @@
+#**
+ *  Render a hit representing a Product
+ *  assumed to have a field called "name"
+ *#
+
+<div class="result-title"><b>#field('name')</b><span class="mlt">   #if($params.getBool('mlt', false) == false)<a href="#lensNoQ&q=id:$docId&mlt=true">More Like This</a>#end</span></div>
+##do we have a physical store for this product
+#set($store = $doc.getFieldValue('store'))
+#if($store)<div class="map"><img src="http://maps.google.com/maps/api/staticmap?&zoom=12&size=150x80&maptype=roadmap&markers=$doc.getFieldValue('store')&sensor=false" /><div><small><a target="_map" href="http://maps.google.com/?q=$store&amp;source=embed">Larger Map</a></small></div></div>#end
+<div>Id: #field('id')</div>
+<div>Price: #field('price_c')</div>
+<div>Features: #field('features')</div>
+<div>In Stock: #field('inStock')</div>
+<div class="mlt">
+  #set($mlt = $mltResults.get($docId))
+  #set($mltOn = $params.getBool('mlt'))
+  #if($mltOn == true)<div class="field-name">Similar Items</div>#end
+  #if ($mltOn && $mlt && $mlt.size() > 0)
+  <ul>
+    #foreach($mltHit in $mlt)
+      #set($mltId = $mltHit.getFieldValue('id'))
+      <li><div><a href="#url_for_home?q=id:$mltId">$mltId</a></div><div><span class="field-name">Name:</span> $mltHit.getFieldValue('name')</div>
+        <div><span class="field-name">Price:</span> $!number.currency($mltHit.getFieldValue('price')) <span class="field-name">In Stock:</span> $mltHit.getFieldValue('inStock')</div>
+
+      </li>
+    #end
+  </ul>
+  #elseif($mltOn && $mlt.size() == 0)
+    <div>No Similar Items Found</div>
+  #end
+</div>
+#parse('debug.vm')
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/query.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/query.vm
new file mode 100644
index 0000000..ddbab3f
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/query.vm
@@ -0,0 +1,42 @@
+<div class="query-box">
+  <form id="query-form" action="#{url_for_home}" method="GET">
+    <div class="inputs">
+      <span #annTitle("Add the query using the &q= parameter")>Find: <input type="text" id="q" name="q" value="$!esc.html($params.get('q'))"/> <input type="submit" id="querySubmit"/> <input type="reset"/></span>
+      <div class="query-boost"><span #annTitle("Add the boost function &bf=price to the query")><input type="checkbox" name="bf" value="price" #if($request.params.get('bf') == 'price')checked="true"#end>Boost by Price</input></span>
+      #parse("querySpatial.vm")
+      #parse("queryGroup.vm")
+      </div>
+  </div>
+
+    #if($request.params.get('debugQuery'))
+      <input type="hidden" name="debugQuery" value="true"/>
+    #end
+    #if($annotate == true)
+      <input type="hidden" name="annotateBrowse" value="true"/>
+    #end
+    #foreach($fq in $request.params.getParams('fq'))
+      #if ($fq != "{!bbox}")
+        <input type="hidden" name="fq" id="allFQs" value="$esc.html($fq)"/>
+      #end
+    #end
+    <div class="constraints" #annTitle("Lists out the &fq filters.  Click to remove.")>
+      #foreach($fq in $params.getParams('fq'))
+        #set($previous_fq_count=$velocityCount - 1)
+        #if($fq != '')
+        &gt; <a style="{text-decoration: line-through;}" href="#url_for_filters($request.params.getParams('fq').subList(0,$previous_fq_count))">$fq</a>
+        #end
+      #end
+    </div>
+    <div class="parsed_query_header">
+     #if($request.params.get('debugQuery'))
+        <a href="#" onclick='jQuery(this).siblings("div").toggle(); return false;'>toggle parsed query</a>
+        <div class="parsed_query" style="display:none">$response.response.debug.parsedquery</div>
+      #end
+      #set($queryOpts = $request.params.get("queryOpts"))
+      #if($queryOpts && $queryOpts != "")
+        <input type="hidden" name="queryOpts" value="$queryOpts"/>
+      #end
+    </div>
+  </form>
+
+</div>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/query_form.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/query_form.vm
new file mode 100644
index 0000000..70a0af2
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/query_form.vm
@@ -0,0 +1,64 @@
+#**
+ *  Renders the main query form
+ *#
+
+<div class="query-box">
+  <form id="query-form" action="#{url_for_home}" method="GET">
+
+    <div class="inputs">
+      <span #annTitle("Add the query using the &q= parameter")>
+        Find:
+        <input type="text" id="q" name="q" value="$!esc.html($params.get('q'))"/>
+        <input type="submit" id="querySubmit"/>
+        <input type="reset"/>
+      </span>
+      <div class="query-boost">
+        <span #annTitle("Add the boost function &bf=price to the query")>
+          <input type="checkbox" name="bf" value="price"
+            #if($request.params.get('bf') == 'price')checked="true"#end
+          >
+            Boost by Price
+          </input>
+        </span>
+      #parse("query_spatial.vm")
+      #parse("query_group.vm")
+      </div>
+  </div>
+
+    #if($request.params.get('debugQuery'))
+      <input type="hidden" name="debugQuery" value="true"/>
+    #end
+    #if($annotate == true)
+      <input type="hidden" name="annotateBrowse" value="true"/>
+    #end
+    #foreach($fq in $request.params.getParams('fq'))
+      #if ($fq != "{!bbox}")
+        <input type="hidden" name="fq" id="allFQs" value="$esc.html($fq)"/>
+      #end
+    #end
+
+    <div class="constraints" #annTitle("Lists out the &fq filters.  Click to remove.")>
+      #foreach($fq in $params.getParams('fq'))
+        #set($previous_fq_count=$velocityCount - 1)
+        #if($fq != '')
+          &gt;
+          <a style="{text-decoration: line-through;}"
+            href="#url_for_filters($request.params.getParams('fq').subList(0,$previous_fq_count))"
+          >$fq</a>
+        #end
+      #end
+    </div>
+
+    <div class="parsed_query_header">
+      #if($request.params.get('debugQuery'))
+        <a href="#" onclick='jQuery(this).siblings("div").toggle(); return false;'>toggle parsed query</a>
+        <div class="parsed_query" style="display:none">$response.response.debug.parsedquery</div>
+      #end
+      #set($queryOpts = $request.params.get("queryOpts"))
+      #if($queryOpts && $queryOpts != "")
+        <input type="hidden" name="queryOpts" value="$queryOpts"/>
+      #end
+    </div>
+
+  </form>
+</div>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/query_group.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/query_group.vm
new file mode 100644
index 0000000..42e5457
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/query_group.vm
@@ -0,0 +1,43 @@
+#**
+ *  Query settings for grouping by fields,
+ *  e.g.: Manufacturer or Popularity
+ *#
+
+#set($queryOpts = $params.get("queryOpts"))
+
+#if($queryOpts == "group")
+  <div>
+    #set($groupF = $request.params.get('group.field'))
+
+    <label #annTitle("Add the &group.field parameter. Multiselect is supported")>
+      Group By:
+      <select id="group" name="group.field" multiple="true">
+        ## TODO: Handle multiple selects correctly
+        ## TODO: fix empty / "No Group" selection
+
+        <option value=""
+          #if($groupF == '')selected="true"#end
+        >
+          No Group
+        </option>
+
+        <option value="manu_exact"
+          #if($groupF == 'manu_exact')selected="true"#end
+        >
+          Manufacturer
+        </option>
+
+        <option value="popularity"
+          #if($groupF == 'popularity')selected="true"#end
+        >
+          Popularity
+        </option>
+
+      </select>
+    </label>  
+
+    <input type="hidden" name="group" value="true"/>
+
+  </div>
+
+#end
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/query_spatial.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/query_spatial.vm
new file mode 100644
index 0000000..2bc2044
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/query_spatial.vm
@@ -0,0 +1,75 @@
+#**
+ *  Query logic for selecting location / Geospatial search
+ *#
+
+#set($queryOpts = $params.get("queryOpts"))
+
+#if($queryOpts == "spatial")
+
+  <div>
+
+    #set($loc = $request.params.get('pt'))
+    ## Normalize first trip through to "none" because
+    ## an empty string generates an error message later on
+    #if( ! $loc )
+      #set( $loc = "none" )
+    #end
+
+    #set($dist = $request.params.get('d', "10"))
+
+    ## Cities for The Select List
+    #set( $cities = {
+      "none": "No Filter",
+      "45.17614,-93.87341": "Buffalo, MN",
+      "37.7752,-100.0232": "Dodge City, KS",
+      "35.0752,-97.032": "Oklahoma City, OK",
+      "37.7752,-122.4232": "San Francisco CA"
+    })
+
+    <label #annTitle("Add the &pt parameter")>
+      Location Filter:
+      <select id="pt" name="pt">
+
+        ## Generate <option> tag for each city
+        #foreach( $city_lon_lat in $cities.keySet() )
+          #set( $city_name = $cities.get($city_lon_lat) )
+          <option value="$city_lon_lat"
+            #if($loc == $city_lon_lat)selected="true"#end
+          >
+            $city_name
+          </option>
+        #end
+
+      </select>
+
+    </label>
+
+    <span #annTitle("Add the &d parameter")>
+      Distance (KM):
+      <input id="d" name="d" type="text" size="6"
+        value="#if($dist != '')${dist}#{else}10#end"  ## TODO: isn't the default of 10 above sufficient?  no if/else needed?
+      />
+    </span>
+
+    <input type="hidden" name="sfield" value="store"/>
+    <input type="hidden" id="spatialFQ" name="fq" value=""/>
+    <input type="hidden" name="queryOpts" value="spatial"/>        
+
+  </div>
+
+  <script type="text/javascript">
+    $('#query-form').submit(function() {
+      if ($("#pt").val() != "none") {
+        $("#spatialFQ").val("{!bbox}");
+      }
+      $fqs = $("#allFQs").val();
+      $fqs = $fqs.replace("{!bbox}", "");
+      if ($fqs == ''){
+        $("#allFQs").remove();
+      }
+      $("#allFQs").val($fqs);
+      return true;
+    });
+  </script>
+
+#end
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/results_list.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/results_list.vm
new file mode 100644
index 0000000..f73532b
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/results_list.vm
@@ -0,0 +1,22 @@
+#**
+ *  Render the main Results List
+ *#
+
+## Usually displayed inside <div class="results">
+
+#if($response.response.get('grouped'))
+
+  #foreach($grouping in $response.response.get('grouped'))
+    #parse("hit_grouped.vm")
+  #end
+
+#else
+
+  #foreach($doc in $response.results)
+    #parse("hit.vm")
+    ## Can get an extremely simple view of the doc
+    ## which might be nicer for debugging
+    ##parse("hit_plain.vm")
+  #end
+
+#end
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/richtext_doc.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/richtext_doc.vm
new file mode 100644
index 0000000..9e8d6cb
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/richtext_doc.vm
@@ -0,0 +1,153 @@
+#**
+ *  Render a complex document in the results list
+ *#
+
+## Load Mime-Type List and Mapping
+#parse('mime_type_lists.vm')
+## Sets:
+## * supportedMimeTypes, AKA supportedtypes
+## * mimeExtensionsMap, AKA extMap
+
+## Title
+#if($doc.getFieldValue('title'))
+  #set($title = $esc.html($doc.getFirstValue('title')))
+#else
+  #set($title = "["+$doc.getFieldValue('id')+"]")
+#end
+
+## URL
+#if($doc.getFieldValue('url'))
+  #set($url = $doc.getFieldValue('url'))
+#elseif($doc.getFieldValue('resourcename'))
+  #set($url = "file:///$doc.getFieldValue('resourcename')")
+#else
+  #set($url = "$doc.getFieldValue('id')")
+#end
+
+## Sort out Mime-Type
+#set($ct = $list.get($doc.getFirstValue('content_type').split(";"),0))
+#set($filename = $doc.getFieldValue('resourcename'))
+#set($filetype = false)
+#set($filetype = $mimeExtensionsMap.get($ct))
+
+## TODO: falling back to file extension is convenient,
+## except when you don't have an icon for that extension
+## example "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
+## document with a .docx extension.
+## It'd be nice to fall back to an "unknown" or the existing "file" type
+## We sort of do this below, but only if the filename has no extension
+## (anything after the last dot).
+
+#if(!$filetype)
+  #set($filetype = $filename.substring($filename.lastIndexOf(".")).substring(1))
+#end
+
+## #if(!$filetype)
+##   #set($filetype = "file")
+## #end
+## #if(!$supportedMimeTypes.contains($filetype))
+##   #set($filetype = "file")
+## #end
+
+## Row 1: Icon and Title and mlt link
+<div class="result-title">
+  ## Icon
+  ## Small file type icons from http://www.splitbrain.org/projects/file_icons (public domain)
+  <img src="#{url_root}/img/filetypes/${filetype}.png" align="center">
+
+  ## Title, hyperlinked
+  <a href="${url}" target="_blank">
+    <b>$title</b></a>
+
+  ## Link for MLT / More Like This / Find Similar
+  <span class="mlt">
+    #if($params.getBool('mlt', false) == false)
+      <a href="#lensNoQ&q=id:%22$docId%22&mlt=true">
+        More Like This</a>
+    #end
+  </span>
+
+</div>
+
+## Row 2?: ID / URL
+<div>
+  Id: #field('id')
+</div>
+
+## Resource Name
+<div>
+  #if($doc.getFieldValue('resourcename'))
+    Resource name: $filename 
+  #elseif($url)
+    URL: $url
+  #end
+  #if($ct)
+    ($ct)
+  #end
+</div>
+
+## Author
+#if($doc.getFieldValue('author'))
+  <div>
+    Author: #field('author')
+  </div>
+#end
+
+## Last_Modified Date
+#if($doc.getFieldValue('last_modified'))
+  <div>
+    last-modified:
+    #field('last_modified')
+  </div>
+#end
+
+## Main content of doc
+<div class="result-body">
+  #field('content')
+</div>
+
+## Display Similar Documents / MLT = More Like This
+<div class="mlt">
+  #set($mlt = $mltResults.get($docId))
+  #set($mltOn = $params.getBool('mlt'))
+  #if($mltOn == true)
+    <div class="field-name">
+      Similar Items
+    </div>
+  #end
+  ## If has MLT enabled An Entries to show
+  #if ($mltOn && $mlt && $mlt.size() > 0)
+    <ul>
+      #foreach($mltHit in $mlt)
+        #set($mltId = $mltHit.getFieldValue('id'))
+        <li>
+          <div>
+            <a href="#url_for_home?q=id:$mltId">
+              $mltId</a>
+          </div>
+          <div>
+            <span class="field-name">
+              Title:
+            </span>
+            $mltHit.getFieldValue('title')
+          </div>
+          <div>
+            <span class="field-name">
+              Author:
+            </span>
+            $mltHit.getFieldValue('author')
+            <span class="field-name">
+              Description:
+            </span>
+            $mltHit.getFieldValue('description')
+          </div>
+        </li>
+      #end    ## end for each mltHit in $mlt
+    </ul>
+  ## Else MLT Enabled but no mlt results for this query
+  #elseif($mltOn && $mlt.size() == 0)
+    <div>No Similar Items Found</div>
+  #end
+</div>  ## div class=mlt
+
+#parse('debug.vm')
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/suggest.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/suggest.vm
new file mode 100644
index 0000000..dae6b83
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/suggest.vm
@@ -0,0 +1,8 @@
+#**
+ *  Provides cynamic spelling suggestions
+ *  as you type in the search form
+ *#
+
+#foreach($t in $response.response.terms.name)
+  $t.key
+#end
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/tabs.vm b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/tabs.vm
new file mode 100644
index 0000000..da19cbc
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/velocity/tabs.vm
@@ -0,0 +1,50 @@
+#**
+ *  Provides navigation/access to Advanced search options
+ *  Usually displayed near the top of the page
+ *#
+
+##TODO: Make some nice tabs here
+
+#set($queryOpts = $params.get("queryOpts"))
+
+<div class="tabs-bar" #annTitle("Click the link to demonstrate various Solr capabilities")>
+
+  <span>Type of Search:</span>
+
+  ##queryOpts=$queryOpts
+
+  ## return to Simple Search
+  ##set( $selected = ($queryOpts && $queryOpts != "") )
+  #set( $selected = ! $queryOpts )
+  <span class="tab #if($selected)selected#end">
+    #if($selected)
+      Simple
+    #else
+      <a href="#url_for_home/?#debug#annotate">
+        Simple</a>
+    #end
+  </span>
+
+  ## GEO-Spatial / Location Based
+  #set( $selected = ($queryOpts == "spatial") )
+  <span class="tab #if($selected)selected#end">
+    #if($selected)
+      Spatial
+    #else
+      <a href="#url_for_home?&queryOpts=spatial#debug#annotate">
+        Spatial</a>
+    #end
+  </span>
+
+  ## Group By Field
+  #set( $selected = ($queryOpts == "group") )
+  <span class="tab #if($selected)selected#end">
+    #if($selected)
+      Group By
+    #else
+      <a href="#url_for_home?#debug#annotate&queryOpts=group&group=true&group.field=manu_exact">
+        Group By</a>
+    #end
+  </span>
+
+</div>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/example.xsl b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/example.xsl
new file mode 100644
index 0000000..b899270
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/example.xsl
@@ -0,0 +1,132 @@
+<?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.
+ -->
+
+<!-- 
+  Simple transform of Solr query results to HTML
+ -->
+<xsl:stylesheet version='1.0'
+    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
+>
+
+  <xsl:output media-type="text/html" encoding="UTF-8"/> 
+  
+  <xsl:variable name="title" select="concat('Solr search results (',response/result/@numFound,' documents)')"/>
+  
+  <xsl:template match='/'>
+    <html>
+      <head>
+        <title><xsl:value-of select="$title"/></title>
+        <xsl:call-template name="css"/>
+      </head>
+      <body>
+        <h1><xsl:value-of select="$title"/></h1>
+        <div class="note">
+          This has been formatted by the sample "example.xsl" transform -
+          use your own XSLT to get a nicer page
+        </div>
+        <xsl:apply-templates select="response/result/doc"/>
+      </body>
+    </html>
+  </xsl:template>
+  
+  <xsl:template match="doc">
+    <xsl:variable name="pos" select="position()"/>
+    <div class="doc">
+      <table width="100%">
+        <xsl:apply-templates>
+          <xsl:with-param name="pos"><xsl:value-of select="$pos"/></xsl:with-param>
+        </xsl:apply-templates>
+      </table>
+    </div>
+  </xsl:template>
+
+  <xsl:template match="doc/*[@name='score']" priority="100">
+    <xsl:param name="pos"></xsl:param>
+    <tr>
+      <td class="name">
+        <xsl:value-of select="@name"/>
+      </td>
+      <td class="value">
+        <xsl:value-of select="."/>
+
+        <xsl:if test="boolean(//lst[@name='explain'])">
+          <xsl:element name="a">
+            <!-- can't allow whitespace here -->
+            <xsl:attribute name="href">javascript:toggle("<xsl:value-of select="concat('exp-',$pos)" />");</xsl:attribute>?</xsl:element>
+          <br/>
+          <xsl:element name="div">
+            <xsl:attribute name="class">exp</xsl:attribute>
+            <xsl:attribute name="id">
+              <xsl:value-of select="concat('exp-',$pos)" />
+            </xsl:attribute>
+            <xsl:value-of select="//lst[@name='explain']/str[position()=$pos]"/>
+          </xsl:element>
+        </xsl:if>
+      </td>
+    </tr>
+  </xsl:template>
+
+  <xsl:template match="doc/arr" priority="100">
+    <tr>
+      <td class="name">
+        <xsl:value-of select="@name"/>
+      </td>
+      <td class="value">
+        <ul>
+        <xsl:for-each select="*">
+          <li><xsl:value-of select="."/></li>
+        </xsl:for-each>
+        </ul>
+      </td>
+    </tr>
+  </xsl:template>
+
+
+  <xsl:template match="doc/*">
+    <tr>
+      <td class="name">
+        <xsl:value-of select="@name"/>
+      </td>
+      <td class="value">
+        <xsl:value-of select="."/>
+      </td>
+    </tr>
+  </xsl:template>
+
+  <xsl:template match="*"/>
+  
+  <xsl:template name="css">
+    <script>
+      function toggle(id) {
+        var obj = document.getElementById(id);
+        obj.style.display = (obj.style.display != 'block') ? 'block' : 'none';
+      }
+    </script>
+    <style type="text/css">
+      body { font-family: "Lucida Grande", sans-serif }
+      td.name { font-style: italic; font-size:80%; }
+      td { vertical-align: top; }
+      ul { margin: 0px; margin-left: 1em; padding: 0px; }
+      .note { font-size:80%; }
+      .doc { margin-top: 1em; border-top: solid grey 1px; }
+      .exp { display: none; font-family: monospace; white-space: pre; }
+    </style>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/example_atom.xsl b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/example_atom.xsl
new file mode 100644
index 0000000..b6c2315
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/example_atom.xsl
@@ -0,0 +1,67 @@
+<?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.
+ -->
+
+<!-- 
+  Simple transform of Solr query results to Atom
+ -->
+
+<xsl:stylesheet version='1.0'
+    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
+
+  <xsl:output
+       method="xml"
+       encoding="utf-8"
+       media-type="application/xml"
+  />
+
+  <xsl:template match='/'>
+    <xsl:variable name="query" select="response/lst[@name='responseHeader']/lst[@name='params']/str[@name='q']"/>
+    <feed xmlns="http://www.w3.org/2005/Atom">
+      <title>Example Solr Atom 1.0 Feed</title>
+      <subtitle>
+       This has been formatted by the sample "example_atom.xsl" transform -
+       use your own XSLT to get a nicer Atom feed.
+      </subtitle>
+      <author>
+        <name>Apache Solr</name>
+        <email>solr-user@lucene.apache.org</email>
+      </author>
+      <link rel="self" type="application/atom+xml" 
+            href="http://localhost:8983/solr/q={$query}&amp;wt=xslt&amp;tr=atom.xsl"/>
+      <updated>
+        <xsl:value-of select="response/result/doc[position()=1]/date[@name='timestamp']"/>
+      </updated>
+      <id>tag:localhost,2007:example</id>
+      <xsl:apply-templates select="response/result/doc"/>
+    </feed>
+  </xsl:template>
+    
+  <!-- search results xslt -->
+  <xsl:template match="doc">
+    <xsl:variable name="id" select="str[@name='id']"/>
+    <entry>
+      <title><xsl:value-of select="str[@name='name']"/></title>
+      <link href="http://localhost:8983/solr/select?q={$id}"/>
+      <id>tag:localhost,2007:<xsl:value-of select="$id"/></id>
+      <summary><xsl:value-of select="arr[@name='features']"/></summary>
+      <updated><xsl:value-of select="date[@name='timestamp']"/></updated>
+    </entry>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/example_rss.xsl b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/example_rss.xsl
new file mode 100644
index 0000000..2857f11
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/example_rss.xsl
@@ -0,0 +1,66 @@
+<?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.
+ -->
+
+<!-- 
+  Simple transform of Solr query results to RSS
+ -->
+
+<xsl:stylesheet version='1.0'
+    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
+
+  <xsl:output
+       method="xml"
+       encoding="utf-8"
+       media-type="application/xml"
+  />
+  <xsl:template match='/'>
+    <rss version="2.0">
+       <channel>
+	 <title>Example Solr RSS 2.0 Feed</title>
+         <link>http://localhost:8983/solr</link>
+         <description>
+          This has been formatted by the sample "example_rss.xsl" transform -
+          use your own XSLT to get a nicer RSS feed.
+         </description>
+         <language>en-us</language>
+         <docs>http://localhost:8983/solr</docs>
+         <xsl:apply-templates select="response/result/doc"/>
+       </channel>
+    </rss>
+  </xsl:template>
+  
+  <!-- search results xslt -->
+  <xsl:template match="doc">
+    <xsl:variable name="id" select="str[@name='id']"/>
+    <xsl:variable name="timestamp" select="date[@name='timestamp']"/>
+    <item>
+      <title><xsl:value-of select="str[@name='name']"/></title>
+      <link>
+        http://localhost:8983/solr/select?q=id:<xsl:value-of select="$id"/>
+      </link>
+      <description>
+        <xsl:value-of select="arr[@name='features']"/>
+      </description>
+      <pubDate><xsl:value-of select="$timestamp"/></pubDate>
+      <guid>
+        http://localhost:8983/solr/select?q=id:<xsl:value-of select="$id"/>
+      </guid>
+    </item>
+  </xsl:template>
+</xsl:stylesheet>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/luke.xsl b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/luke.xsl
new file mode 100644
index 0000000..8553f3c
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/luke.xsl
@@ -0,0 +1,337 @@
+<?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.
+-->
+
+
+<!-- 
+  Display the luke request handler with graphs
+ -->
+<xsl:stylesheet
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns="http://www.w3.org/1999/xhtml"
+    version="1.0"
+    >
+    <xsl:output
+        method="html"
+        encoding="UTF-8"
+        media-type="text/html"
+        doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+        doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+    />
+
+    <xsl:variable name="title">Solr Luke Request Handler Response</xsl:variable>
+
+    <xsl:template match="/">
+        <html xmlns="http://www.w3.org/1999/xhtml">
+            <head>
+                <link rel="stylesheet" type="text/css" href="solr-admin.css"/>
+                <link rel="icon" href="favicon.ico" type="image/ico"/>
+                <link rel="shortcut icon" href="favicon.ico" type="image/ico"/>
+                <title>
+                    <xsl:value-of select="$title"/>
+                </title>
+                <xsl:call-template name="css"/>
+
+            </head>
+            <body>
+                <h1>
+                    <xsl:value-of select="$title"/>
+                </h1>
+                <div class="doc">
+                    <ul>
+                        <xsl:if test="response/lst[@name='index']">
+                            <li>
+                                <a href="#index">Index Statistics</a>
+                            </li>
+                        </xsl:if>
+                        <xsl:if test="response/lst[@name='fields']">
+                            <li>
+                                <a href="#fields">Field Statistics</a>
+                                <ul>
+                                    <xsl:for-each select="response/lst[@name='fields']/lst">
+                                        <li>
+                                            <a href="#{@name}">
+                                                <xsl:value-of select="@name"/>
+                                            </a>
+                                        </li>
+                                    </xsl:for-each>
+                                </ul>
+                            </li>
+                        </xsl:if>
+                        <xsl:if test="response/lst[@name='doc']">
+                            <li>
+                                <a href="#doc">Document statistics</a>
+                            </li>
+                        </xsl:if>
+                    </ul>
+                </div>
+                <xsl:if test="response/lst[@name='index']">
+                    <h2><a name="index"/>Index Statistics</h2>
+                    <xsl:apply-templates select="response/lst[@name='index']"/>
+                </xsl:if>
+                <xsl:if test="response/lst[@name='fields']">
+                    <h2><a name="fields"/>Field Statistics</h2>
+                    <xsl:apply-templates select="response/lst[@name='fields']"/>
+                </xsl:if>
+                <xsl:if test="response/lst[@name='doc']">
+                    <h2><a name="doc"/>Document statistics</h2>
+                    <xsl:apply-templates select="response/lst[@name='doc']"/>
+                </xsl:if>
+            </body>
+        </html>
+    </xsl:template>
+
+    <xsl:template match="lst">
+        <xsl:if test="parent::lst">
+            <tr>
+                <td colspan="2">
+                    <div class="doc">
+                        <xsl:call-template name="list"/>
+                    </div>
+                </td>
+            </tr>
+        </xsl:if>
+        <xsl:if test="not(parent::lst)">
+            <div class="doc">
+                <xsl:call-template name="list"/>
+            </div>
+        </xsl:if>
+    </xsl:template>
+
+    <xsl:template name="list">
+        <xsl:if test="count(child::*)>0">
+            <table>
+                <thead>
+                    <tr>
+                        <th colspan="2">
+                            <p>
+                                <a name="{@name}"/>
+                            </p>
+                            <xsl:value-of select="@name"/>
+                        </th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <xsl:choose>
+                        <xsl:when
+                            test="@name='histogram'">
+                            <tr>
+                                <td colspan="2">
+                                    <xsl:call-template name="histogram"/>
+                                </td>
+                            </tr>
+                        </xsl:when>
+                        <xsl:otherwise>
+                            <xsl:apply-templates/>
+                        </xsl:otherwise>
+                    </xsl:choose>
+                </tbody>
+            </table>
+        </xsl:if>
+    </xsl:template>
+
+    <xsl:template name="histogram">
+        <div class="doc">
+            <xsl:call-template name="barchart">
+                <xsl:with-param name="max_bar_width">50</xsl:with-param>
+                <xsl:with-param name="iwidth">800</xsl:with-param>
+                <xsl:with-param name="iheight">160</xsl:with-param>
+                <xsl:with-param name="fill">blue</xsl:with-param>
+            </xsl:call-template>
+        </div>
+    </xsl:template>
+
+    <xsl:template name="barchart">
+        <xsl:param name="max_bar_width"/>
+        <xsl:param name="iwidth"/>
+        <xsl:param name="iheight"/>
+        <xsl:param name="fill"/>
+        <xsl:variable name="max">
+            <xsl:for-each select="int">
+                <xsl:sort data-type="number" order="descending"/>
+                <xsl:if test="position()=1">
+                    <xsl:value-of select="."/>
+                </xsl:if>
+            </xsl:for-each>
+        </xsl:variable>
+        <xsl:variable name="bars">
+           <xsl:value-of select="count(int)"/>
+        </xsl:variable>
+        <xsl:variable name="bar_width">
+           <xsl:choose>
+             <xsl:when test="$max_bar_width &lt; ($iwidth div $bars)">
+               <xsl:value-of select="$max_bar_width"/>
+             </xsl:when>
+             <xsl:otherwise>
+               <xsl:value-of select="$iwidth div $bars"/>
+             </xsl:otherwise>
+           </xsl:choose>
+        </xsl:variable>
+        <table class="histogram">
+           <tbody>
+              <tr>
+                <xsl:for-each select="int">
+                   <td>
+                 <xsl:value-of select="."/>
+                 <div class="histogram">
+                  <xsl:attribute name="style">background-color: <xsl:value-of select="$fill"/>; width: <xsl:value-of select="$bar_width"/>px; height: <xsl:value-of select="($iheight*number(.)) div $max"/>px;</xsl:attribute>
+                 </div>
+                   </td> 
+                </xsl:for-each>
+              </tr>
+              <tr>
+                <xsl:for-each select="int">
+                   <td>
+                       <xsl:value-of select="@name"/>
+                   </td>
+                </xsl:for-each>
+              </tr>
+           </tbody>
+        </table>
+    </xsl:template>
+
+    <xsl:template name="keyvalue">
+        <xsl:choose>
+            <xsl:when test="@name">
+                <tr>
+                    <td class="name">
+                        <xsl:value-of select="@name"/>
+                    </td>
+                    <td class="value">
+                        <xsl:value-of select="."/>
+                    </td>
+                </tr>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:value-of select="."/>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template match="int|bool|long|float|double|uuid|date">
+        <xsl:call-template name="keyvalue"/>
+    </xsl:template>
+
+    <xsl:template match="arr">
+        <tr>
+            <td class="name">
+                <xsl:value-of select="@name"/>
+            </td>
+            <td class="value">
+                <ul>
+                    <xsl:for-each select="child::*">
+                        <li>
+                            <xsl:apply-templates/>
+                        </li>
+                    </xsl:for-each>
+                </ul>
+            </td>
+        </tr>
+    </xsl:template>
+
+    <xsl:template match="str">
+        <xsl:choose>
+            <xsl:when test="@name='schema' or @name='index' or @name='flags'">
+                <xsl:call-template name="schema"/>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:call-template name="keyvalue"/>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="schema">
+        <tr>
+            <td class="name">
+                <xsl:value-of select="@name"/>
+            </td>
+            <td class="value">
+                <xsl:if test="contains(.,'unstored')">
+                    <xsl:value-of select="."/>
+                </xsl:if>
+                <xsl:if test="not(contains(.,'unstored'))">
+                    <xsl:call-template name="infochar2string">
+                        <xsl:with-param name="charList">
+                            <xsl:value-of select="."/>
+                        </xsl:with-param>
+                    </xsl:call-template>
+                </xsl:if>
+            </td>
+        </tr>
+    </xsl:template>
+
+    <xsl:template name="infochar2string">
+        <xsl:param name="i">1</xsl:param>
+        <xsl:param name="charList"/>
+
+        <xsl:variable name="char">
+            <xsl:value-of select="substring($charList,$i,1)"/>
+        </xsl:variable>
+        <xsl:choose>
+            <xsl:when test="$char='I'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='I']"/> - </xsl:when>
+            <xsl:when test="$char='T'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='T']"/> - </xsl:when>
+            <xsl:when test="$char='S'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='S']"/> - </xsl:when>
+            <xsl:when test="$char='M'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='M']"/> - </xsl:when>
+            <xsl:when test="$char='V'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='V']"/> - </xsl:when>
+            <xsl:when test="$char='o'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='o']"/> - </xsl:when>
+            <xsl:when test="$char='p'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='p']"/> - </xsl:when>
+            <xsl:when test="$char='O'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='O']"/> - </xsl:when>
+            <xsl:when test="$char='L'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='L']"/> - </xsl:when>
+            <xsl:when test="$char='B'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='B']"/> - </xsl:when>
+            <xsl:when test="$char='C'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='C']"/> - </xsl:when>
+            <xsl:when test="$char='f'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='f']"/> - </xsl:when>
+            <xsl:when test="$char='l'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='l']"/> -
+            </xsl:when>
+        </xsl:choose>
+
+        <xsl:if test="not($i>=string-length($charList))">
+            <xsl:call-template name="infochar2string">
+                <xsl:with-param name="i">
+                    <xsl:value-of select="$i+1"/>
+                </xsl:with-param>
+                <xsl:with-param name="charList">
+                    <xsl:value-of select="$charList"/>
+                </xsl:with-param>
+            </xsl:call-template>
+        </xsl:if>
+    </xsl:template>
+    <xsl:template name="css">
+        <style type="text/css">
+            <![CDATA[
+            td.name {font-style: italic; font-size:80%; }
+            .doc { margin: 0.5em; border: solid grey 1px; }
+            .exp { display: none; font-family: monospace; white-space: pre; }
+            div.histogram { background: none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;}
+            table.histogram { width: auto; vertical-align: bottom; }
+            table.histogram td, table.histogram th { text-align: center; vertical-align: bottom; border-bottom: 1px solid #ff9933; width: auto; }
+            ]]>
+        </style>
+    </xsl:template>
+</xsl:stylesheet>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/updateXml.xsl b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/updateXml.xsl
new file mode 100644
index 0000000..daf1344
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/conf/xslt/updateXml.xsl
@@ -0,0 +1,70 @@
+<!-- 
+ * 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.
+ -->
+
+<!--
+  Simple transform of Solr query response into Solr Update XML compliant XML.
+  When used in the xslt response writer you will get UpdaateXML as output.
+  But you can also store a query response XML to disk and feed this XML to
+  the XSLTUpdateRequestHandler to index the content. Provided as example only.
+  See http://wiki.apache.org/solr/XsltUpdateRequestHandler for more info
+ -->
+<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
+  <xsl:output media-type="text/xml" method="xml" indent="yes"/>
+
+  <xsl:template match='/'>
+    <add>
+        <xsl:apply-templates select="response/result/doc"/>
+    </add>
+  </xsl:template>
+  
+  <!-- Ignore score (makes no sense to index) -->
+  <xsl:template match="doc/*[@name='score']" priority="100">
+  </xsl:template>
+
+  <xsl:template match="doc">
+    <xsl:variable name="pos" select="position()"/>
+    <doc>
+        <xsl:apply-templates>
+          <xsl:with-param name="pos"><xsl:value-of select="$pos"/></xsl:with-param>
+        </xsl:apply-templates>
+    </doc>
+  </xsl:template>
+
+  <!-- Flatten arrays to duplicate field lines -->
+  <xsl:template match="doc/arr" priority="100">
+      <xsl:variable name="fn" select="@name"/>
+      
+      <xsl:for-each select="*">
+		<xsl:element name="field">
+		    <xsl:attribute name="name"><xsl:value-of select="$fn"/></xsl:attribute>
+	        <xsl:value-of select="."/>
+		</xsl:element>
+      </xsl:for-each>
+  </xsl:template>
+
+
+  <xsl:template match="doc/*">
+      <xsl:variable name="fn" select="@name"/>
+
+	<xsl:element name="field">
+	    <xsl:attribute name="name"><xsl:value-of select="$fn"/></xsl:attribute>
+        <xsl:value-of select="."/>
+	</xsl:element>
+  </xsl:template>
+
+  <xsl:template match="*"/>
+</xsl:stylesheet>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/core.properties b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/core.properties
new file mode 100644
index 0000000..21e2bf4
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/oodt-fm/core.properties
@@ -0,0 +1 @@
+name=oodt-fm
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/solr.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/solr.xml
new file mode 100644
index 0000000..94d60b6
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/solr.xml
@@ -0,0 +1,45 @@
+<?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.
+-->
+
+<!--
+   This is an example of a simple "solr.xml" file for configuring one or 
+   more Solr Cores, as well as allowing Cores to be added, removed, and 
+   reloaded via HTTP requests.
+
+   More information about options available in this configuration file, 
+   and Solr Core administration can be found online:
+   http://wiki.apache.org/solr/CoreAdmin
+-->
+
+<solr>
+
+  <solrcloud>
+    <str name="host">${host:}</str>
+    <int name="hostPort">${jetty.port:8983}</int>
+    <str name="hostContext">${hostContext:solr}</str>
+    <int name="zkClientTimeout">${zkClientTimeout:30000}</int>
+    <bool name="genericCoreNodeNames">${genericCoreNodeNames:true}</bool>
+  </solrcloud>
+
+  <shardHandlerFactory name="shardHandlerFactory"
+    class="HttpShardHandlerFactory">
+    <int name="socketTimeout">${socketTimeout:0}</int>
+    <int name="connTimeout">${connTimeout:0}</int>
+  </shardHandlerFactory>
+
+</solr>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/zoo.cfg b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/zoo.cfg
new file mode 100644
index 0000000..aea4518
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/solr/src/main/resources/zoo.cfg
@@ -0,0 +1,17 @@
+# The number of milliseconds of each tick
+tickTime=2000
+# The number of ticks that the initial
+# synchronization phase can take
+initLimit=10
+# The number of ticks that can pass between
+# sending a request and getting an acknowledgement
+syncLimit=5
+
+# the directory where the snapshot is stored.
+# dataDir=/opt/zookeeper/data
+# NOTE: Solr defaults the dataDir to <solrHome>/zoo_data
+
+# the port at which the clients will connect
+# clientPort=2181
+# NOTE: Solr sets this based on zkRun / zkHost params
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/fmprod/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/fmprod/pom.xml
new file mode 100644
index 0000000..a43102f
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/fmprod/pom.xml
@@ -0,0 +1,79 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>${groupId}</groupId>
+    <artifactId>${rootArtifactId}</artifactId>
+    <version>${version}</version>
+    <relativePath>../../pom.xml</relativePath>
+  </parent>
+  <name>Filemanager Product Services (Apache OODT)</name>
+  <artifactId>${rootArtifactId}-${artifactId}</artifactId>
+  <packaging>war</packaging>
+
+  <build>
+    <sourceDirectory>src/main/java</sourceDirectory>
+    <testSourceDirectory>src/test</testSourceDirectory>
+    <outputDirectory>target/classes</outputDirectory>
+
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+      <resource>
+        <directory>src/main/java</directory>
+        <includes>
+          <include>**</include>
+        </includes>
+        <excludes>
+          <exclude>**/*.java</exclude>
+        </excludes>
+      </resource>
+    </resources>
+
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-war-plugin</artifactId>
+        <version>2.1.1</version>
+        <configuration>
+          <overlays>
+            <overlay>
+              <groupId>org.apache.oodt</groupId>
+              <artifactId>cas-product</artifactId>
+            </overlay>
+          </overlays>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-product</artifactId>
+      <version>${oodt.version}</version>
+      <type>war</type>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/fmprod/src/main/resources/rdfconf.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/fmprod/src/main/resources/rdfconf.xml
new file mode 100644
index 0000000..e648a1c
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/fmprod/src/main/resources/rdfconf.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+	
+	Author: Chris A. Mattmann
+	Description: Refactored the definition of the relevant CAS RDF
+	web service configuration parameters into this file. See tag specific
+	documentation below for information on how to use the file to configure
+	the CAS RDF web service.
+ 
+-->
+<!-- FIXME: adjust namespace URI? -->
+<cas:rdfconf xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+ <!-- 
+   Here you can add as many &quot;ns&quot; tags as desired. Each 
+   ns should include <b>both</b> a name attribute and a value attribute, 
+   where name,value are the xmlns name and value, e.g., xmlns:&lt;name&gt;=&quot;value&quot;
+  -->
+ <namespaces>
+   <ns name="cas" value="urn:oodt:"/>
+   <ns name="rdf" value="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
+   
+   <!-- an example included from EDRN -->
+   <ns name="edrn" value="urn:edrn:"/>
+   <ns name="x" value="http://edrn.nci.nih.gov/rdf/schema.rdf#"/>
+ </namespaces>
+ 
+ <!--  optionally specify CAS met keys to be renamed in the output RDF. Each key tag
+       must include a <b>from</b> and a <b>to</b> attribute, renaming the original CAS
+       product met key &quot;from&quot; to the new RDF output key &quot;to&quot;
+  -->
+ <rewrite>
+   <key from="SiteId" to="site"/>
+   <key from="SiteName" to="site"/>
+   <key from="ProtocolId" to="protocol"/> 
+   <key from="OrganId" to="organ"/>
+   <key from="OrganSite" to="organ"/>
+   <key from="ProtocolName" to="protocol"/>
+ </rewrite>
+ 
+ <!-- 
+   Placing key tags in this file declares that the source CAS product met keys
+   are in fact resource link identifiers, and should be output as such in the 
+   RDF. Required parameters for each key tag are: name, identifying the source
+   CAS product met key, and link, identifying the start of the resource link to
+   be used in the rdf:resource output tag, e.g., 
+   &lt;x:protocol rdf:resource=&quot;&lt;link&gt;/&lt;key value&gt;&quot;&gt;
+  -->
+ <resourcelinks>
+   <key name="SiteId" link="http://edrn.nci.nih.gov/data/sites/"/>
+   <key name="SiteName" link="http://edrn.nci.nih.gov/data/sites/"/>
+   <key name="ProtocolId" link="http://edrn.nci.nih.gov/data/protocols/"/>
+   <key name="ProtocolName" link="http://edrn.nci.nih.gov/data/protocols/"/>
+   <key name="OrganId" link="http://edrn.nci.nih.gov/data/body-systems/"/>
+   <key name="OrganSite" link="http://edrn.nci.nih.gov/data/body-systems/"/>
+ </resourcelinks>
+ 
+ <!-- 
+      associates CAS product met specific keys to previously declared namespaces. Each key
+      tag should contain a name attribute whose value is valid CAS product met key, and each 
+      ns attribute on each key tag should be a previously declared namespace from the namespaces
+      tag.
+      
+   
+      You <b>must</b> declare a default ns in the default attribute in the keynsmap tag. This
+      ns will be used if no key ns is declared in the nsmap.
+  -->
+ <keynsmap default="edrn">
+   <key name="CAS.ProductId" ns="cas"/>
+   <key name="CAS.ProductName" ns="cas"/>
+   <key name="CAS.ProductReceivedTime" ns="cas"/>
+   <key name="FileLocation" ns="cas"/>
+   <key name="Filename" ns="cas"/>
+   <key name="ProductType" ns="cas"/>  
+   <key name="DataVersion" ns="cas"/>
+   <key name="MimeType" ns="cas"/> 
+   
+   <!--  EDRN example -->
+   <key name="SiteId" ns="x"/>
+   <key name="SiteName" ns="x"/>
+   <key name="ProtocolName" ns="x"/>
+   <key name="ProtocolId" ns="x"/>
+   <key name="OrganId" ns="x"/>
+   <key name="OrganSite" ns="x"/>
+ </keynsmap>
+ 
+ <!-- 
+      associates CAS product type names to previously declared namespaces. Each type
+      tag should contain a name attribute whose value is valid CAS product type, and each 
+      ns attribute on each key tag should be a previously declared namespace from the namespaces
+      tag.
+ 
+      You <b>must</b> declare a default ns in the default attribute in the typesnsmap tag. This
+      ns will be used if no type ns is declared in the nsmap. 
+  -->
+ <typesnsmap default="edrn">
+   <type name="GenericFile" ns="cas"/>
+ </typesnsmap>
+</cas:rdfconf>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/fmprod/src/main/resources/rssconf.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/fmprod/src/main/resources/rssconf.xml
new file mode 100644
index 0000000..5e69e0a
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/fmprod/src/main/resources/rssconf.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+	
+	Author: Chris A. Mattmann
+	Description: This file configures the CAS RSS web service. The
+	main aspects of this file are the ability to recast a product's 
+	metadata as relevant RSS compatiable tags.
+-->
+<!-- FIXME: adjust namespace URI? -->
+<cas:rssconf xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+  <!-- 
+    An option "channelLink" attribute may be set on the above outer tag to 
+    set the channel's link attribute.
+    
+    Metadata available for replacement in this attribute is:
+    
+    BaseUrl: the base URL for the CAS web service layer.
+    ProductTypeId: the id passed to the RSS channel via the id param
+    ProductType: the channel product type name passed via the channel param
+    TopN: the topn param, if passed.
+   -->
+  
+  <!-- 
+    Each &lt;tag&gt; tag defines 2 attributes:
+    
+    name (required) - the RSS output tag name
+    source (optional) - the field name from the CAS product's metadata and its
+    associated value.
+    
+    Each &lt;tag&gt; has a set of &lt;attribute&gt; tags, which define XML attributes
+    on the RSS output tags. Each &lt;attribute&gt; has the following attributes:
+    
+    name (required) - the RSS output tag attribute name
+    value (required) - the RSS output tag attribute value. By default these values are
+    run through PathUtils#replaceEnvVariables which replaces met keys using the standard
+    CAS met replacement strategy.
+   -->
+    
+    <!-- 
+    
+    If you want to turn your CAS File Manager into a Podcast feeder for iTunes, uncomment
+    the below tag block. You'll need to modify your web.xml for this webapp and change
+    the default name of the /data service to /data.mp3. Then you're set!
+    
+    <tag name="enclosure">
+      <attribute name="url" value="http://localhost:8080/fmprod/data.mp3?productID=[CAS.ProductId]"/>
+      <attribute name="length" value="[FileSize]"/>
+      <attribute name="type" value="audio/mpeg"/>
+    </tag>
+    
+    -->
+
+    <!-- 
+    
+    If you want to turn your CAS File Manager into a GeoRSS 
+    simple service (see http://georss.org/simple), add the 
+    following block, assuming that you have indexed met fields 
+    named Latitude and Longitude for your product (update as 
+    appropriate otherwise).
+    
+    <tag name="georss:point" source="[Latitude] [Longitude]"/>
+    -->
+    
+    <tag name="cas:source" source="[ProductType]"/>
+    <tag name="source" source="[ProductType]"/>
+
+</cas:rssconf>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/fmprod/src/main/webapp/META-INF/context.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/fmprod/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..b09d597
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/fmprod/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,29 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+
+<Context path="/fmprod" debug="5"
+  reloadable="true" crossContext="true">
+
+  <Valve className="org.apache.catalina.valves.AccessLogValve"
+    prefix="fmprod_access_log." suffix=".txt" pattern="common" />
+
+  <Parameter name="filemgr.url" value="[FILEMGR_URL]" override="false" />
+  <Parameter name="filemgr.rdfconf.file" value="[FMPROD_HOME]/rdfconf.xml" override="false"/>
+  <Parameter name="filemgr.rssconf.file" value="[FMPROD_HOME]/rssconf.xml" override="false"/>
+  <Parameter name="filemgr.working.dir" value="/tmp" override="false" />
+
+</Context>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/opsui/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/opsui/pom.xml
new file mode 100644
index 0000000..3551e16
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/opsui/pom.xml
@@ -0,0 +1,79 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>${groupId}</groupId>
+    <artifactId>${rootArtifactId}</artifactId>
+    <version>${version}</version>
+    <relativePath>../../pom.xml</relativePath>
+  </parent>
+  <name>PCS Ops Interface (Apache OODT)</name>
+  <artifactId>${rootArtifactId}-${artifactId}</artifactId>
+  <packaging>war</packaging>
+
+  <build>
+    <sourceDirectory>src/main/java</sourceDirectory>
+    <testSourceDirectory>src/test</testSourceDirectory>
+    <outputDirectory>target/classes</outputDirectory>
+
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+      <resource>
+        <directory>src/main/java</directory>
+        <includes>
+          <include>**</include>
+        </includes>
+        <excludes>
+          <exclude>**/*.java</exclude>
+        </excludes>
+      </resource>
+    </resources>
+
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-war-plugin</artifactId>
+        <version>2.1.1</version>
+        <configuration>
+          <overlays>
+            <overlay>
+              <groupId>org.apache.oodt</groupId>
+              <artifactId>pcs-opsui</artifactId>
+            </overlay>
+          </overlays>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>pcs-opsui</artifactId>
+      <version>${oodt.version}</version>
+      <type>war</type>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/opsui/src/main/webapp/META-INF/context.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/opsui/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..12b4197
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/opsui/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,64 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<Context path="/opsui">
+		
+	<Parameter name="filemgr.url"
+	    value="[FILEMGR_URL]"/>		
+		
+	<Parameter name="workflow.url"
+	    value="[WORKFLOW_URL]"/>
+
+	<Parameter name="resmgr.url"
+	    value="[RESMGR_URL]"/>
+
+	<Parameter name="org.apache.oodt.pcs.opsui.workflow.lifecycleFilePath"
+	    value="[WORKFLOW_HOME]/policy/workflow-lifecycle.xml"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.opsui.winst.statuses"
+	    value="QUEUED, RSUBMIT, BUILDING CONFIG FILE, PGE EXEC, CRAWLING, STAGING INPUT, FINISHED, STARTED, PAUSED"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.opsui.winst.metFields.filePath"
+	    value="[WORKFLOW_HOME]/policy/workflow-instance-met.xml"/>   
+	    
+	<Parameter name="org.apache.oodt.pcs.health.crawler.conf.filePath"
+	    value="[PCS_HOME]/policy/pcs-crawlers.xml"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.health.workflow.statuses.filePath"
+	    value="[PCS_HOME]/policy/pcs-workflow-statuses.xml"/>	    
+	 
+	<Parameter name="ganglia.url" value="[GANGLIA_URL]"/>
+	<Parameter name="contact.email" value="user@oodt.apache.org"/>
+
+    <Parameter name="org.apache.oodt.pcs.trace.excludeList"
+               value=""/>   
+    <Parameter name="org.apache.oodt.pcs.trace.enableNotCat"
+               value="true"/>
+               	
+        <!-- OPSUI SKINNING
+                Directions: Set the 'opsui.skin' property's value attribute. 
+                Supported skins:
+                        ""           => No skin
+                        "cleanwhite" => Clean, white background OODT base skin
+                        "navyblue"   => Darker, blue background OODT base skin
+                        "classic"    => The original, OCO (Orbiting Carbon Observatory) skin for OPSUI
+                OR add your own!
+        -->
+        <Parameter name="opsui.skin" value="cleanwhite"/>
+        <Parameter name="opsui.homepage" value="org.apache.oodt.pcs.opsui.HomePage"/>
+
+</Context>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/opsui/src/main/webapp/WEB-INF/web.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/opsui/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..51ce823
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/opsui/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ 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.
+-->
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+     version="2.4">
+
+    <display-name>opsui</display-name>
+
+     <!--  
+          There are three means to configure Wickets configuration mode and they are
+          tested in the order given. 
+          1) A system property: -Dwicket.configuration
+          2) servlet specific <init-param>
+          3) context specific <context-param>
+          The value might be either "development" (reloading when templates change)
+          or "deployment". If no configuration is found, "development" is the default.
+    -->
+
+    <filter>
+        <filter-name>wicket.browser</filter-name>
+        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
+        <init-param>
+            <param-name>applicationClassName</param-name>
+            <param-value>org.apache.oodt.pcs.opsui.OpsuiApp</param-value>
+        </init-param>
+    </filter>
+
+ <filter-mapping>
+  <filter-name>wicket.browser</filter-name>
+    <url-pattern>/*</url-pattern>
+ </filter-mapping>
+ 
+  <context-param>
+    <param-name>filemgr.working.dir</param-name>
+    <param-value>/tmp</param-value>
+  </context-param>
+
+  <servlet>
+    <servlet-name>DataDeliveryServlet</servlet-name>
+    <servlet-class>org.apache.oodt.cas.product.data.DataDeliveryServlet</servlet-class>
+  </servlet>
+  <servlet>
+    <servlet-name>DatasetDeliveryServlet</servlet-name>
+    <servlet-class>org.apache.oodt.cas.product.data.DatasetDeliveryServlet</servlet-class>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>DataDeliveryServlet</servlet-name>
+    <url-pattern>/data</url-pattern>
+  </servlet-mapping>
+  
+  <servlet-mapping>
+    <servlet-name>DatasetDeliveryServlet</servlet-name>
+    <url-pattern>/dataset</url-pattern>
+  </servlet-mapping>  
+ 
+
+
+</web-app>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/pcs-services/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/pcs-services/pom.xml
new file mode 100644
index 0000000..be0da7d
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/pcs-services/pom.xml
@@ -0,0 +1,79 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>${groupId}</groupId>
+    <artifactId>${rootArtifactId}</artifactId>
+    <version>${version}</version>
+    <relativePath>../../pom.xml</relativePath>
+  </parent>
+  <name>PCS Services (Apache OODT)</name>
+  <artifactId>${rootArtifactId}-${artifactId}</artifactId>
+  <packaging>war</packaging>
+
+  <build>
+    <sourceDirectory>src/main/java</sourceDirectory>
+    <testSourceDirectory>src/test</testSourceDirectory>
+    <outputDirectory>target/classes</outputDirectory>
+
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+      <resource>
+        <directory>src/main/java</directory>
+        <includes>
+          <include>**</include>
+        </includes>
+        <excludes>
+          <exclude>**/*.java</exclude>
+        </excludes>
+      </resource>
+    </resources>
+
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-war-plugin</artifactId>
+        <version>2.1.1</version>
+        <configuration>
+          <overlays>
+            <overlay>
+              <groupId>org.apache.oodt</groupId>
+              <artifactId>pcs-services</artifactId>
+            </overlay>
+          </overlays>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>pcs-services</artifactId>
+      <version>${oodt.version}</version>
+      <type>war</type>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/pcs-services/src/main/webapp/META-INF/context.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/pcs-services/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..1619db4
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/pcs-services/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,44 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<Context path="/pcs">
+		
+	<Parameter name="org.apache.oodt.cas.fm.url"
+	    value="[FILEMGR_URL]"/>
+
+	<Parameter name="org.apache.oodt.cas.wm.url"
+	    value="[WORKFLOW_URL]"/>
+
+	<Parameter name="org.apache.oodt.cas.rm.url"
+	    value="[RESMGR_URL]"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.ll.conf.filePath"
+	    value="[PCS_HOME]/aux/pcs/pcs-ll-conf.xmnl"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.health.crawler.conf.filePath"
+	    value="[PCS_HOME]/aux/pcs/pcs-crawlers.xml"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.health.workflow.statuses.filePath"
+	    value="[PCS_HOME]/aux/pcs/pcs-workflow-statuses.xml"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.trace.enableNonCat"
+	    value="true"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.trace.productTypeExcludeList"
+	    value="TypeName1,TypeName2"/>
+
+</Context>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/pom.xml
new file mode 100644
index 0000000..fc2ddf3
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/pom.xml
@@ -0,0 +1,30 @@
+<?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.

+-->

+<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>

+  <parent>

+    <groupId>${groupId}</groupId>

+    <artifactId>${rootArtifactId}</artifactId>

+    <version>${version}</version>

+    <relativePath>../pom.xml</relativePath>

+  </parent>

+  <name>Web Applications (Apache OODT)</name>

+  <packaging>pom</packaging>

+  <artifactId>${rootArtifactId}-${artifactId}</artifactId>

+

+</project>

diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/solr-webapp/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/solr-webapp/pom.xml
new file mode 100644
index 0000000..da9477f
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/solr-webapp/pom.xml
@@ -0,0 +1,106 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>${groupId}</groupId>
+    <artifactId>${rootArtifactId}</artifactId>
+    <version>${version}</version>
+    <relativePath>../../pom.xml</relativePath>
+  </parent>
+  <name>Solr Webapp (Apache Solr)</name>
+  <artifactId>${rootArtifactId}-${artifactId}</artifactId>
+  <packaging>war</packaging>
+
+  <build>
+    <sourceDirectory>src/main/java</sourceDirectory>
+    <testSourceDirectory>src/test</testSourceDirectory>
+    <outputDirectory>target/classes</outputDirectory>
+
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+      <resource>
+        <directory>src/main/java</directory>
+        <includes>
+          <include>**</include>
+        </includes>
+        <excludes>
+          <exclude>**/*.java</exclude>
+        </excludes>
+      </resource>
+    </resources>
+
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-war-plugin</artifactId>
+        <version>2.1.1</version>
+        <configuration>
+          <overlays>
+            <overlay>
+              <groupId>org.apache.solr</groupId>
+              <artifactId>solr</artifactId>
+            </overlay>
+          </overlays>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.solr</groupId>
+      <artifactId>solr</artifactId>
+      <version>4.7.0</version>
+      <type>war</type>
+    </dependency>
+    
+	<dependency>
+		<groupId>org.slf4j</groupId>
+		<artifactId>slf4j-api</artifactId>
+		<version>1.6.6</version>
+	</dependency>
+	<dependency>
+		<groupId>org.slf4j</groupId>
+		<artifactId>jcl-over-slf4j</artifactId>
+		<version>1.6.6</version>
+	</dependency>
+	<dependency>
+		<groupId>org.slf4j</groupId>
+		<artifactId>jul-to-slf4j</artifactId>
+		<version>1.6.6</version>
+	</dependency>
+	<dependency>
+		<groupId>org.slf4j</groupId>
+		<artifactId>slf4j-log4j12</artifactId>
+		<version>1.6.6</version>
+	</dependency>
+	<dependency>
+		<groupId>log4j</groupId>
+		<artifactId>log4j</artifactId>
+		<version>1.2.16</version>
+	</dependency>
+	
+  </dependencies>
+
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/solr-webapp/src/main/webapp/META-INF/context.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/solr-webapp/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..8eb28e4
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/solr-webapp/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Context path="/solr">
+  <Parameter name="solr/home" value="../solr"/>
+</Context> 
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/solr-webapp/src/main/webapp/WEB-INF/lib/log4j.properties b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/solr-webapp/src/main/webapp/WEB-INF/lib/log4j.properties
new file mode 100644
index 0000000..f33fa71
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/solr-webapp/src/main/webapp/WEB-INF/lib/log4j.properties
@@ -0,0 +1,24 @@
+#  Logging level
+solr.log=logs/
+log4j.rootLogger=INFO, file, CONSOLE
+
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%-4r [%t] %-5p %c %x \u2013 %m%n
+
+#- size rotation with log cleanup.
+log4j.appender.file=org.apache.log4j.RollingFileAppender
+log4j.appender.file.MaxFileSize=4MB
+log4j.appender.file.MaxBackupIndex=9
+
+#- File to log to and log format
+log4j.appender.file.File=${solr.log}/solr.log
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%-5p - %d{yyyy-MM-dd HH:mm:ss.SSS}; %C; %m\n
+
+log4j.logger.org.apache.zookeeper=WARN
+log4j.logger.org.apache.hadoop=WARN
+
+# set to INFO to enable infostream log messages
+log4j.logger.org.apache.solr.update.LoggingInfoStream=OFF
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/solr-webapp/src/main/webapp/WEB-INF/web.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/solr-webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100755
index 0000000..6330fe9
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/webapps/solr-webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,181 @@
+<?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.
+-->
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+         version="2.5"
+         metadata-complete="true"
+>
+
+
+  <!-- Uncomment if you are trying to use a Resin version before 3.0.19.
+    Their XML implementation isn't entirely compatible with Xerces.
+    Below are the implementations to use with Sun's JVM.
+  <system-property javax.xml.xpath.XPathFactory=
+             "com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl"/>
+  <system-property javax.xml.parsers.DocumentBuilderFactory=
+             "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl"/>
+  <system-property javax.xml.parsers.SAXParserFactory=
+             "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"/>
+   -->
+
+  <!-- People who want to hardcode their "Solr Home" directly into the
+       WAR File can set the JNDI property here...
+   -->
+  
+    <env-entry>
+       <env-entry-name>solr/home</env-entry-name>
+       <env-entry-value>../solr</env-entry-value>
+       <env-entry-type>java.lang.String</env-entry-type>
+    </env-entry>
+   
+   
+  <!-- Any path (name) registered in solrconfig.xml will be sent to that filter -->
+  <filter>
+    <filter-name>SolrRequestFilter</filter-name>
+    <filter-class>org.apache.solr.servlet.SolrDispatchFilter</filter-class>
+    <!-- If you are wiring Solr into a larger web application which controls
+         the web context root, you will probably want to mount Solr under
+         a path prefix (app.war with /app/solr mounted into it, for example).
+         You will need to put this prefix in front of the SolrDispatchFilter
+         url-pattern mapping too (/solr/*), and also on any paths for
+         legacy Solr servlet mappings you may be using.
+         For the Admin UI to work properly in a path-prefixed configuration,
+         the admin folder containing the resources needs to be under the app context root
+         named to match the path-prefix.  For example:
+
+            .war
+               xxx
+                 js
+                   main.js
+    -->
+    <!--
+    <init-param>
+      <param-name>path-prefix</param-name>
+      <param-value>/xxx</param-value>
+    </init-param>
+    -->
+  </filter>
+
+  <filter-mapping>
+    <!--
+      NOTE: When using multicore, /admin JSP URLs with a core specified
+      such as /solr/coreName/admin/stats.jsp get forwarded by a
+      RequestDispatcher to /solr/admin/stats.jsp with the specified core
+      put into request scope keyed as "org.apache.solr.SolrCore".
+
+      It is unnecessary, and potentially problematic, to have the SolrDispatchFilter
+      configured to also filter on forwards.  Do not configure
+      this dispatcher as <dispatcher>FORWARD</dispatcher>.
+    -->
+    <filter-name>SolrRequestFilter</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+
+  <servlet>
+    <servlet-name>Zookeeper</servlet-name>
+    <servlet-class>org.apache.solr.servlet.ZookeeperInfoServlet</servlet-class>
+  </servlet>
+  
+  <servlet>
+    <servlet-name>LoadAdminUI</servlet-name>
+    <servlet-class>org.apache.solr.servlet.LoadAdminUiServlet</servlet-class>
+  </servlet>
+  
+  <!-- Remove in Solr 5.0 -->
+  <!-- This sends SC_MOVED_PERMANENTLY (301) for resources that changed in 4.0 -->
+  <servlet>
+    <servlet-name>RedirectOldAdminUI</servlet-name>
+    <servlet-class>org.apache.solr.servlet.RedirectServlet</servlet-class>
+    <init-param>
+      <param-name>destination</param-name>
+      <param-value>${context}/#/</param-value>
+    </init-param>
+  </servlet>
+  
+  <servlet>
+    <servlet-name>RedirectOldZookeeper</servlet-name>
+    <servlet-class>org.apache.solr.servlet.RedirectServlet</servlet-class>
+    <init-param>
+      <param-name>destination</param-name>
+      <param-value>${context}/zookeeper</param-value>
+    </init-param>
+  </servlet>
+  
+  <servlet>
+    <servlet-name>RedirectLogging</servlet-name>
+    <servlet-class>org.apache.solr.servlet.RedirectServlet</servlet-class>
+    <init-param>
+      <param-name>destination</param-name>
+      <param-value>${context}/#/~logging</param-value>
+    </init-param>
+  </servlet>
+
+  <servlet>
+    <servlet-name>SolrRestApi</servlet-name>
+    <servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
+    <init-param>
+      <param-name>org.restlet.application</param-name>
+      <param-value>org.apache.solr.rest.SolrRestApi</param-value>
+    </init-param>
+  </servlet>
+  
+  <servlet-mapping>
+    <servlet-name>RedirectOldAdminUI</servlet-name>
+    <url-pattern>/admin/</url-pattern>
+  </servlet-mapping>
+  <servlet-mapping>
+    <servlet-name>RedirectOldAdminUI</servlet-name>
+    <url-pattern>/admin</url-pattern>
+  </servlet-mapping>
+  <servlet-mapping>
+    <servlet-name>RedirectOldZookeeper</servlet-name>
+    <url-pattern>/zookeeper.jsp</url-pattern>
+  </servlet-mapping>
+  <servlet-mapping>
+    <servlet-name>RedirectLogging</servlet-name>
+    <url-pattern>/logging</url-pattern>
+  </servlet-mapping>
+
+  <!-- Servlet Mapping -->
+  <servlet-mapping>
+    <servlet-name>Zookeeper</servlet-name>
+    <url-pattern>/zookeeper</url-pattern>
+  </servlet-mapping>
+  
+  <servlet-mapping>
+    <servlet-name>LoadAdminUI</servlet-name>
+    <url-pattern>/admin.html</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>SolrRestApi</servlet-name>
+    <url-pattern>/schema/*</url-pattern>
+  </servlet-mapping>
+  
+  <mime-mapping>
+    <extension>.xsl</extension>
+    <!-- per http://www.w3.org/TR/2006/PR-xslt20-20061121/ -->
+    <mime-type>application/xslt+xml</mime-type>
+  </mime-mapping>
+
+  <welcome-file-list>
+    <welcome-file>admin.html</welcome-file>
+  </welcome-file-list>
+
+</web-app>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/pom.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/pom.xml
new file mode 100644
index 0000000..d7670a4
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/pom.xml
@@ -0,0 +1,98 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>${groupId}</groupId>
+    <artifactId>${rootArtifactId}</artifactId>
+    <version>${version}</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+  <name>Workflow Manager (Apache OODT)</name>
+  <artifactId>${rootArtifactId}-workflow</artifactId>
+  <packaging>jar</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-2</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/assembly/assembly.xml</descriptor>
+          </descriptors>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+ 
+  <dependencies>
+    <dependency>
+      <groupId>${groupId}</groupId>
+      <artifactId>${rootArtifactId}-extensions</artifactId>
+      <version>${project.parent.version}</version>
+      <type>jar</type>
+      <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.oodt</groupId>
+          <artifactId>cas-filemgr</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-workflow</artifactId>
+      <version>${oodt.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-pge</artifactId>
+      <version>${oodt.pge.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.oodt</groupId>
+          <artifactId>cas-filemgr</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.oodt</groupId>
+          <artifactId>cas-crawler</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/assembly/assembly.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..bee3039
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/assembly/assembly.xml
@@ -0,0 +1,80 @@
+<!--
+ 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.
+-->
+<assembly>
+  <id>bin</id>
+  <formats>
+    <format>tar.gz</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <baseDirectory>workflow</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/bin</directory>
+      <outputDirectory>workflow/bin</outputDirectory>
+      <includes/>
+      <fileMode>755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>workflow/logs</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>workflow/run</outputDirectory>
+      <excludes>
+        <exclude>**/*</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/etc</directory>
+      <outputDirectory>workflow/etc</outputDirectory>
+      <includes/>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/policy</directory>
+      <outputDirectory>workflow/policy</outputDirectory>
+      <includes/>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>workflow/lib</outputDirectory>
+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>
+      <unpackOptions/>
+    </dependencySet>
+  </dependencySets>
+</assembly>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/bin/wmgr b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/bin/wmgr
new file mode 100644
index 0000000..854216c
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/bin/wmgr
@@ -0,0 +1,168 @@
+#!/bin/sh
+
+# 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.
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false
+os400=false
+darwin=false
+case "`uname`" in
+CYGWIN*) cygwin=true;;
+OS400*) os400=true;;
+Darwin*) darwin=true;;
+esac
+
+# resolve links - $0 may be a softlink
+PRG="$0"
+
+while [ -h "$PRG" ]; do
+  ls=`ls -ld "$PRG"`
+  link=`expr "$ls" : '.*-> \(.*\)$'`
+  if expr "$link" : '/.*' > /dev/null; then
+    PRG="$link"
+  else
+    PRG=`dirname "$PRG"`/"$link"
+  fi
+done
+
+# Get standard environment variables
+PRGDIR=`dirname "$PRG"`
+
+# Only set OODT_HOME if not already set
+[ -z "$OODT_HOME" ] && OODT_HOME=`cd "$PRGDIR/../.." ; pwd`
+
+# Get OODT environment set up
+if [ -r "$OODT_HOME"/bin/env.sh ]; then
+  . "$OODT_HOME"/bin/env.sh
+fi
+
+# Only set WORKFLOW_HOME if not already set
+if [ -z "$WORKFLOW_HOME" ]; then
+  WORKFLOW_HOME="$OODT_HOME"/workflow
+  export WORKFLOW_HOME
+fi
+
+if [ -z "$WORKFLOW_PID" ]; then
+  WORKFLOW_PID="$WORKFLOW_HOME"/run/cas.workflow.pid
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$JRE_HOME" ] && JRE_HOME=`cygpath --unix "$JRE_HOME"`
+  [ -n "$OODT_HOME" ] && OODT_HOME=`cygpath --unix "$OODT_HOME"`
+  [ -n "$WORKFLOW_HOME" ] && WORKFLOW_HOME=`cygpath --unix "$WORKFLOW_HOME"`
+  [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+if [ "$1" = "start" ]; then
+  if [ ! -z "$WORKFLOW_PID" ]; then
+    if [ -f "$WORKFLOW_PID" ]; then
+      echo "PID file ($WORKFLOW_PID) found. Is Workflow Manager still running? Start aborted."
+      exit 1
+    fi
+  fi
+
+  # In case this script was run from somewhere else cd to this directory
+  cd "$WORKFLOW_HOME"/bin
+
+  "$_RUNJAVA" $JAVA_OPTS $OODT_OPTS \
+    -Djava.ext.dirs="$WORKFLOW_HOME"/lib \
+    -Djava.util.logging.config.file="$WORKFLOW_HOME"/etc/logging.properties \
+    -Dorg.apache.oodt.cas.workflow.properties="$WORKFLOW_HOME"/etc/workflow.properties \
+    -Djava.io.tmpdir="$OODT_TMPDIR" \
+    -Dorg.apache.oodt.cas.pge.task.metkeys.legacyMode="true" \
+    -Dorg.apache.oodt.cas.pge.task.status.legacyMode="true" \
+    org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManager \
+    --portNum "$WORKFLOW_PORT" 2>&1 &
+
+  if [ ! -z "$WORKFLOW_PID" ]; then
+    echo $! > $WORKFLOW_PID
+  fi
+
+  if [ $have_tty -eq 1 ]; then
+    echo "Workflow Manager started PID file ($WORKFLOW_PID)."
+  fi
+
+elif [ "$1" = "stop" ]; then
+
+  shift
+
+  SLEEP=5
+  if [ ! -z "$1" ]; then
+    echo $1 | grep "[^0-9]" > /dev/null 2>&1
+    if [ $? -eq 1 ]; then
+      SLEEP=$1
+      shift
+    fi
+  fi
+
+  FORCE=0
+  if [ "$1" = "-force" ]; then
+    shift
+    FORCE=1
+  fi
+
+  if [ ! -z "$WORKFLOW_PID" ]; then
+    if [ -f "$WORKFLOW_PID" ]; then
+      kill `cat $WORKFLOW_PID` >/dev/null 2>&1
+      if [ $? -eq 1 ]; then
+        echo "PID file ($WORKFLOW_PID) found but no matching process was found. Stop aborted."
+        exit 1
+      fi
+    else
+      echo "\$WORKFLOW_PID was set ($WORKFLOW_PID) but the specified file does not exist. Is Workflow Manager running? Stop aborted."
+      exit 1
+    fi
+  fi
+
+  if [ ! -z "$WORKFLOW_PID" ]; then
+    if [ -f "$WORKFLOW_PID" ]; then
+      while [ $SLEEP -ge 0 ]; do
+        kill -0 `cat $WORKFLOW_PID` >/dev/null 2>&1
+        if [ $? -eq 1 ]; then
+          rm $WORKFLOW_PID
+          break
+        fi
+        if [ $SLEEP -gt 0 ]; then
+          sleep 1
+        fi
+        if [ $SLEEP -eq 0 ]; then
+          if [ $FORCE -eq 0 ]; then
+            echo "Workflow Manager did not stop in time. PID file was not removed."
+          fi
+        fi
+        SLEEP=`expr $SLEEP - 1 `
+      done
+    fi
+  fi
+
+  if [ $FORCE -eq 1 ]; then
+    if [ -z "$WORKFLOW_PID" ]; then
+      echo "Kill failed: \$WORKFLOW_PID not set"
+    else
+      if [ -f "$WORKFLOW_PID" ]; then
+        echo "Killing: `cat $WORKFLOW_PID`"
+        kill -9 `cat $WORKFLOW_PID`
+        rm $WORKFLOW_PID
+      fi
+    fi
+  fi
+
+else
+  echo "Usage: wmgr {start|stop}"
+  exit 1
+fi
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/bin/wmgr-client b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/bin/wmgr-client
new file mode 100644
index 0000000..63f18b2
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/bin/wmgr-client
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+# 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.
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false
+os400=false
+darwin=false
+case "`uname`" in
+CYGWIN*) cygwin=true;;
+OS400*) os400=true;;
+Darwin*) darwin=true;;
+esac
+
+# resolve links - $0 may be a softlink
+PRG="$0"
+
+while [ -h "$PRG" ]; do
+  ls=`ls -ld "$PRG"`
+  link=`expr "$ls" : '.*-> \(.*\)$'`
+  if expr "$link" : '/.*' > /dev/null; then
+    PRG="$link"
+  else
+    PRG=`dirname "$PRG"`/"$link"
+  fi
+done
+
+# Get standard environment variables
+PRGDIR=`dirname "$PRG"`
+
+# Only set OODT_HOME if not already set
+[ -z "$OODT_HOME" ] && OODT_HOME=`cd "$PRGDIR/../.." ; pwd`
+
+# Get OODT environment set up
+if [ -r "$OODT_HOME"/bin/env.sh ]; then
+  . "$OODT_HOME"/bin/env.sh
+fi
+
+# Only set WORKFLOW_HOME if not already set
+if [ -z "$WORKFLOW_HOME" ]; then
+  WORKFLOW_HOME="$OODT_HOME"/workflow
+  export WORKFLOW_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$JRE_HOME" ] && JRE_HOME=`cygpath --unix "$JRE_HOME"`
+  [ -n "$OODT_HOME" ] && OODT_HOME=`cygpath --unix "$OODT_HOME"`
+  [ -n "$WORKFLOW_HOME" ] && WORKFLOW_HOME=`cygpath --unix "$WORKFLOW_HOME"`
+  [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# In case this script was run from somewhere else cd to this directory
+cd "$WORKFLOW_HOME"/bin
+
+"$_RUNJAVA" $JAVA_OPTS $OODT_OPTS \
+  -Djava.ext.dirs="$WORKFLOW_HOME"/lib \
+  -Djava.util.logging.config.file="$WORKFLOW_HOME"/etc/logging.properties \
+  -Dorg.apache.oodt.cas.cli.action.spring.config=file:"$WORKFLOW_HOME"/policy/cmd-line-actions.xml \
+  -Dorg.apache.oodt.cas.cli.option.spring.config=file:"$WORKFLOW_HOME"/policy/cmd-line-options.xml \
+  org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient "$@"
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/bin/wmkill b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/bin/wmkill
new file mode 100755
index 0000000..4cec22d
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/bin/wmkill
@@ -0,0 +1,31 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.  
+
+export ORIG_DIR=`pwd`
+export DIR=`dirname $0`
+cd $DIR
+export DIR_PATH=`pwd`
+cd $ORIG_DIR
+
+if [ "$#" -ne 1 ]; then
+    echo "Usage: $0 <workflow instance id>"
+    exit 1
+else
+    pushd $DIR_PATH
+    ./wmgr-client --url http://localhost:9001 --operation --stopWorkflowInst --id $1
+    popd
+fi
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/bin/wmkillallbystatus b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/bin/wmkillallbystatus
new file mode 100755
index 0000000..d0df9df
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/bin/wmkillallbystatus
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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. 
+
+export ORIG_DIR=`pwd`
+export DIR=`dirname $0`
+cd $DIR
+export DIR_PATH=`pwd`
+cd $ORIG_DIR
+
+if [ "$#" -ne 1 ]; then
+    echo "Usage: $0 <status, e.g., QUEUED, RSUBMIT, etc.>"
+    exit 1
+else
+    pushd $DIR_PATH
+    for id in `./wmgr-client --url http://localhost:9001 --operation --getFirstPage --status $1 | awk '{print $2}' | cut -f 2 -d = | cut -f 1 -d ,` 
+        do
+            echo "Killing workflow with ID $id"
+            ./wmkill $id
+    done
+    popd
+fi
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/etc/logging.properties b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/etc/logging.properties
new file mode 100644
index 0000000..d3467dd
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/etc/logging.properties
@@ -0,0 +1,68 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.FileHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = ../logs/cas_workflow%g.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 5
+java.util.logging.FileHandler.append = true
+java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging level for the subsystems
+
+# data structures subsystem
+org.apache.oodt.cas.workflow.structs.level = INFO
+
+# engine subsystem
+org.apache.oodt.cas.workflow.engine.level = INFO
+
+# instance repository subsystem
+org.apache.oodt.cas.workflow.instrepo.level = INFO
+
+# repository subsystem
+org.apache.oodt.cas.workflow.repository.level = INFO
+
+# system subsystem
+org.apache.oodt.cas.workflow.system.level = FINE
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = INFO
+httpclient.wire.header.level = INFO
+httpclient.wire.level = INFO
+sun.net.level = OFF
+sun.net.www.level = OFF
+
+# spring framework logging
+org.springframework.beans.level = SEVERE
+org.springframework.core.level = SEVERE
+org.springframework.level = SEVERE
+org.springframework.beans.factory.level = SEVERE
+org.springframework.beans.factory.config.level = SEVERE
+org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.level = SEVERE
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/etc/workflow.properties b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/etc/workflow.properties
new file mode 100644
index 0000000..dbb0dba
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/etc/workflow.properties
@@ -0,0 +1,70 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+# Properties required to configure the Workflow Manager
+
+# workflow repository factory
+workflow.repo.factory = org.apache.oodt.cas.workflow.repository.XMLWorkflowRepositoryFactory
+
+# workflow engine factory
+workflow.engine.factory = org.apache.oodt.cas.workflow.engine.ThreadPoolWorkflowEngineFactory
+
+# workflow instance repository factory
+workflow.engine.instanceRep.factory = org.apache.oodt.cas.workflow.instrepo.LuceneWorkflowInstanceRepositoryFactory
+
+# thread pool workflow engine properties
+org.apache.oodt.cas.workflow.engine.queueSize=
+org.apache.oodt.cas.workflow.engine.maxPoolSize=
+org.apache.oodt.cas.workflow.engine.minPoolSize=6
+org.apache.oodt.cas.workflow.engine.threadKeepAlive.minutes=5
+org.apache.oodt.cas.workflow.engine.unlimitedQueue=true
+org.apache.oodt.cas.workflow.engine.preConditionWaitTime=10
+
+# set this if you want the workflow manager to submit jobs through the resource mgr
+org.apache.oodt.cas.workflow.engine.resourcemgr.url=http://localhost:9002
+
+# if you use the resource mgr submission, you can specify how many seconds the 
+# workflow manager should wait inbetween checking to see if a job is complete
+org.apache.oodt.cas.workflow.engine.resourcemgr.pollingWaitTime=10
+
+# workflow instance repository general properties
+# default page size to page through WorkflowInstances with
+org.apache.oodt.cas.workflow.instanceRep.pageSize=20
+
+# lucene workflow instance repository properties
+org.apache.oodt.cas.workflow.instanceRep.lucene.idxPath=[OODT_HOME]/data/workflow
+
+# data source workflow instance repository properties
+# org.apache.oodt.cas.workflow.instanceRep.datasource.jdbc.url=jdbc:url
+# org.apache.oodt.cas.workflow.instanceRep.datasource.jdbc.user=user
+# org.apache.oodt.cas.workflow.instanceRep.datasource.jdbc.pass=pass
+# org.apache.oodt.cas.workflow.instanceRep.datasource.jdbc.driver=your.jdbc.Driver
+# org.apache.oodt.cas.workflow.instanceRep.datasource.quoteFields=false
+
+# XML workflow repository properties
+org.apache.oodt.cas.workflow.repo.dirs=file://[WORKFLOW_HOME]/policy
+
+# wengine-style packaged workflow repo properties
+#org.apache.oodt.cas.workflow.wengine.packagedRepo.dir.path = /path/to/wengine/workflow/files
+
+# data source workflow repository properties
+# org.apache.oodt.cas.workflow.repo.datasource.jdbc.url=jdbc:url
+# org.apache.oodt.cas.workflow.repo.datasource.jdbc.user=user
+# org.apache.oodt.cas.workflow.repo.datasource.jdbc.pass=pass
+# org.apache.oodt.cas.workflow.repo.datasource.jdbc.driver=your.jdbc.Driver
+
+# Spring command line option and action store properties
+org.apache.oodt.cas.cli.action.spring.config=src/main/resources/cmd-line-actions.xml
+org.apache.oodt.cas.cli.option.spring.config=src/main/resources/cmd-line-options.xml
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/logs/REMOVE.log b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/logs/REMOVE.log
new file mode 100644
index 0000000..fa3ce73
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/logs/REMOVE.log
@@ -0,0 +1,19 @@
+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.
+
+
+You can remove this file. It was only included to ensure that the log directory for this
+distribution was created on assembly.
+
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/cmd-line-actions.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/cmd-line-actions.xml
new file mode 100644
index 0000000..693212e
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/cmd-line-actions.xml
@@ -0,0 +1,85 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+    <bean id="sendEvent" class="org.apache.oodt.cas.workflow.cli.action.SendEventCliAction">
+        <property name="description" value="Triggers an event" />
+    </bean>
+    <bean id="dynWorkflow" class="org.apache.oodt.cas.workflow.cli.action.DynWorkflowCliAction">
+    <property name="description" value="Creates a workflow using the given tasks and then executes it" />
+  </bean>
+  <bean id="getWorkflowInsts" class="org.apache.oodt.cas.workflow.cli.action.GetWorkflowInstsCliAction">
+    <property name="description" value="List all workflow instances" />
+  </bean>
+  <bean id="getWorkflows" class="org.apache.oodt.cas.workflow.cli.action.GetWorkflowsCliAction">
+    <property name="description" value="List all workflow models" />
+  </bean>
+  <bean id="getTaskById" class="org.apache.oodt.cas.workflow.cli.action.GetTaskByIdCliAction">
+    <property name="description" value="Gets task information for task with given ID" />
+  </bean>
+  <bean id="getConditionById" class="org.apache.oodt.cas.workflow.cli.action.GetConditionByIdCliAction">
+    <property name="description" value="Gets condition information for condition with given ID" />
+  </bean>
+  <bean id="getWorkflowById" class="org.apache.oodt.cas.workflow.cli.action.GetWorkflowByIdCliAction">
+    <property name="description" value="Gets workflow information for workflow with given ID" />
+  </bean>
+  <bean id="getWorkflowsByEvent" class="org.apache.oodt.cas.workflow.cli.action.GetWorkflowsByEventCliAction">
+    <property name="description" value="List workflow information for workflows with attached to event" />
+  </bean>
+  <bean id="getRegisteredEvents" class="org.apache.oodt.cas.workflow.cli.action.GetRegisteredEventsCliAction">
+    <property name="description" value="List registered events" />
+  </bean>
+  <bean id="getWorkflowInst" class="org.apache.oodt.cas.workflow.cli.action.GetWorkflowInstCliAction">
+    <property name="description" value="Gets workflow instance by instance ID" />
+  </bean>
+  <bean id="getWallClockTime" class="org.apache.oodt.cas.workflow.cli.action.GetWallClockTimeCliAction">
+    <property name="description" value="Gets wall clock time for workflow instance" />
+  </bean>
+  <bean id="getTaskWallClockTime" class="org.apache.oodt.cas.workflow.cli.action.GetTaskWallClockTimeCliAction">
+    <property name="description" value="Gets wall clock time for workflow instance's current task" />
+  </bean>
+  <bean id="stopWorkflowInst" class="org.apache.oodt.cas.workflow.cli.action.StopWorkflowInstCliAction">
+    <property name="description" value="Stops a workflow instance" />
+  </bean>
+  <bean id="pauseWorkflowInst" class="org.apache.oodt.cas.workflow.cli.action.PauseWorkflowInstCliAction">
+    <property name="description" value="Pauses a workflow instance" />
+  </bean>
+  <bean id="resumeWorkflowInst" class="org.apache.oodt.cas.workflow.cli.action.ResumeWorkflowInstCliAction">
+    <property name="description" value="Resumes a paused workflow instance" />
+  </bean>
+  <bean id="getFirstPage" class="org.apache.oodt.cas.workflow.cli.action.GetFirstPageCliAction">
+    <property name="description" value="Gets first page of workflows" />
+  </bean>
+  <bean id="getNextPage" class="org.apache.oodt.cas.workflow.cli.action.GetNextPageCliAction">
+    <property name="description" value="Gets next page of workflows" />
+  </bean>
+  <bean id="getPrevPage" class="org.apache.oodt.cas.workflow.cli.action.GetPrevPageCliAction">
+    <property name="description" value="Gets prev page of workflows" />
+  </bean>
+  <bean id="getLastPage" class="org.apache.oodt.cas.workflow.cli.action.GetLastPageCliAction">
+    <property name="description" value="Gets last page of workflows" />
+  </bean>
+  <bean id="getWorkflowInstMet" class="org.apache.oodt.cas.workflow.cli.action.GetWorkflowInstMetCliAction">
+    <property name="description" value="Gets workflow instance metadata" />
+  </bean>
+
+</beans>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/cmd-line-options.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/cmd-line-options.xml
new file mode 100644
index 0000000..83efd4b
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/cmd-line-options.xml
@@ -0,0 +1,683 @@
+<?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. Author: 
+    bfoster (Brian Foster) -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+    <bean id="url" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="u" />
+        <property name="longOption" value="url" />
+        <property name="description" value="Workflow Manager URL" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="url" />
+        <property name="required" value="true" />
+        <property name="handler">
+            <bean
+                class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+                <property name="propertyNames">
+                    <list>
+                        <value>org.apache.oodt.cas.workflow.url</value>
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+    <bean id="operation" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+        <property name="shortOption" value="op" />
+        <property name="longOption" value="operation" />
+        <property name="description"
+            value="Declare that you wish to present an operation" />
+        <property name="hasArgs" value="false" />
+        <property name="required" value="true" />
+        <property name="subOptions">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="sendEvent" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="dynWorkflow" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getWorkflowInsts" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getWorkflows" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getTaskById" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getConditionById" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getWorkflowById" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getWorkflowsByEvent" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getRegisteredEvents" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getWorkflowInst" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getWallClockTime" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getTaskWallClockTime" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="stopWorkflowInst" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="pauseWorkflowInst" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="resumeWorkflowInst" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getFirstPage" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getNextPage" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getPrevPage" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getLastPage" p:required="false" />
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="getWorkflowInstMet" p:required="false" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- SendEvent Options -->
+    <bean id="sendEvent" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="se" />
+        <property name="longOption" value="sendEvent" />
+        <property name="description" value="Triggers sendEvent Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>sendEvent</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="sendEvent" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- DynWorkflow Options -->
+    <bean id="dynWorkflow" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="dw" />
+        <property name="longOption" value="dynWorkflow" />
+        <property name="description" value="Triggers dynWorkflow Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>dynWorkflow</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="dynWorkflow" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <bean id="taskIds" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="tids" />
+        <property name="longOption" value="taskIds" />
+        <property name="description" value="List of workflow task ids" />
+        <property name="type" value="java.util.List" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="task-ids" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="dynWorkflow" p:relation="REQUIRED" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+        </property>
+    </bean>
+
+    <!-- GetWorkflowInsts Options -->
+    <bean id="getWorkflowInsts" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="winsts" />
+        <property name="longOption" value="getWorkflowInsts" />
+        <property name="description" value="Triggers GetWorkflowInsts Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getWorkflowInsts</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="GetWorkflowInsts" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetWorkflows Options -->
+    <bean id="getWorkflows" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="wflows" />
+        <property name="longOption" value="getWorkflows" />
+        <property name="description" value="Triggers getWorkflows Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getWorkflows</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getWorkflows" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetTaskById Options -->
+    <bean id="getTaskById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="tbyid" />
+        <property name="longOption" value="getTaskById" />
+        <property name="description" value="Triggers getTaskById Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getTaskById</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getTaskById" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetTaskById Options -->
+    <bean id="getConditionById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="cbyid" />
+        <property name="longOption" value="getConditionById" />
+        <property name="description" value="Triggers getConditionById Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getConditionById</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getConditionById" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetWorkflowById Options -->
+    <bean id="getWorkflowById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="wbyid" />
+        <property name="longOption" value="getWorkflowById" />
+        <property name="description" value="Triggers getWorkflowById Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getWorkflowById</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getWorkflowById" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetWorkflowsByEvent Options -->
+    <bean id="getWorkflowsByEvent" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="wbye" />
+        <property name="longOption" value="getWorkflowsByEvent" />
+        <property name="description" value="Triggers getWorkflowsByEvent Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getWorkflowsByEvent</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getWorkflowsByEvent" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetRegisteredEvents Options -->
+    <bean id="getRegisteredEvents" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="events" />
+        <property name="longOption" value="getRegisteredEvents" />
+        <property name="description" value="Triggers getRegisteredEvents Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getRegisteredEvents</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getRegisteredEvents" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetWorkflowInst Options -->
+    <bean id="getWorkflowInst" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="inst" />
+        <property name="longOption" value="getWorkflowInst" />
+        <property name="description" value="Triggers getWorkflowInst Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getWorkflowInst</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getWorkflowInst" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetWallClockTime Options -->
+    <bean id="getWallClockTime" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="time" />
+        <property name="longOption" value="getWallClockTime" />
+        <property name="description" value="Triggers getWallClockTime Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getWallClockTime</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getWallClockTime" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetTaskWallClockTime Options -->
+    <bean id="getTaskWallClockTime" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="ttime" />
+        <property name="longOption" value="getTaskWallClockTime" />
+        <property name="description" value="Triggers getTaskWallClockTime Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getTaskWallClockTime</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getTaskWallClockTime" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- StopWorkflowInst Options -->
+    <bean id="stopWorkflowInst" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="stop" />
+        <property name="longOption" value="stopWorkflowInst" />
+        <property name="description" value="Triggers stopWorkflowInst Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>stopWorkflowInst</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="stopWorkflowInst" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- PauseWorkflowInst Options -->
+    <bean id="pauseWorkflowInst" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="pause" />
+        <property name="longOption" value="pauseWorkflowInst" />
+        <property name="description" value="Triggers pauseWorkflowInst Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>pauseWorkflowInst</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="pauseWorkflowInst" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- ResumeWorkflowInst Options -->
+    <bean id="resumeWorkflowInst" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="resume" />
+        <property name="longOption" value="resumeWorkflowInst" />
+        <property name="description" value="Triggers resumeWorkflowInst Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>resumeWorkflowInst</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="resumeWorkflowInst" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetFirstPage Options -->
+    <bean id="getFirstPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="page1" />
+        <property name="longOption" value="getFirstPage" />
+        <property name="description" value="Triggers getFirstPage Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getFirstPage</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getFirstPage" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetNextPage Options -->
+    <bean id="getNextPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="next" />
+        <property name="longOption" value="getNextPage" />
+        <property name="description" value="Triggers getNextPage Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getNextPage</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getNextPage" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetPrevPage Options -->
+    <bean id="getPrevPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="prev" />
+        <property name="longOption" value="getPrevPage" />
+        <property name="description" value="Triggers getPrevPage Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getPrevPage</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getPrevPage" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetLastPage Options -->
+    <bean id="getLastPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="last" />
+        <property name="longOption" value="getLastPage" />
+        <property name="description" value="Triggers getLastPage Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getLastPage</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getLastPage" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- GetWorkflowInstMet Options -->
+    <bean id="getWorkflowInstMet" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="getMet" />
+        <property name="longOption" value="getWorkflowInstMet" />
+        <property name="description" value="Triggers getWorkflowInstMet Action" />
+        <property name="hasArgs" value="false" />
+        <property name="staticArgs">
+            <list>
+                <value>getWorkflowInstMet</value>
+            </list>
+        </property>
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getWorkflowInstMet" p:relation="REQUIRED" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- Options used for multiple Actions -->
+    <bean id="eventName" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="en" />
+        <property name="longOption" value="eventName" />
+        <property name="description" value="Name of the Event to trigger" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="event-name" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="sendEvent" p:relation="REQUIRED" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getWorkflowsByEvent" p:relation="REQUIRED" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+        </property>
+    </bean>
+
+    <bean id="metaData" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+        <property name="shortOption" value="m" />
+        <property name="longOption" value="metaData" />
+        <property name="description" value="Declare that you wish to present metadata" />
+        <property name="hasArgs" value="false" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="sendEvent" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="dynMetadata" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="subOptions">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+                    p:option-ref="key" p:required="true" />
+            </list>
+        </property>
+    </bean>
+
+    <bean id="key" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+        p:isSubOption="true">
+        <property name="shortOption" value="k" />
+        <property name="longOption" value="key" />
+        <property name="description" value="Workflow Metadata: key val val..." />
+        <property name="type" value="java.util.List" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="key-vals" />
+        <property name="repeating" value="true" />
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+                <property name="applyToActions">
+                    <list>
+                        <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+                            p:actionName="sendEvent" p:methodName="addMetadata" />
+                        <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+                            p:actionName="dynWorkflow" p:methodName="addMetadata" />
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+    <bean id="id" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="id" />
+        <property name="longOption" value="id" />
+        <property name="description" value="ID" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="id" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getTaskById" p:relation="REQUIRED" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getConditionById" p:relation="REQUIRED" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getWorkflowById" p:relation="REQUIRED" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getWorkflowInst" p:relation="REQUIRED" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getWallClockTime" p:relation="REQUIRED" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getTaskWallClockTime" p:relation="REQUIRED" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="stopWorkflowInst" p:relation="REQUIRED" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="pauseWorkflowInst" p:relation="REQUIRED" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="resumeWorkflowInst" p:relation="REQUIRED" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getWorkflowInstMet" p:relation="REQUIRED" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+                <property name="applyToActions">
+                    <list>
+                        <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+                            p:actionName="getTaskById" p:methodName="setTaskId"
+                            p:argDescription="task-id" />
+                        <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+                            p:actionName="getConditionById" p:methodName="setConditionId"
+                            p:argDescription="condition-id" />
+                        <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+                            p:actionName="getWorkflowById" p:methodName="setWorkflowId"
+                            p:argDescription="workflow-id" />
+                        <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+                            p:actionName="getWorkflowInst" p:methodName="setInstanceId"
+                            p:argDescription="instance-id" />
+                        <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+                            p:actionName="getWallClockTime" p:methodName="setInstanceId"
+                            p:argDescription="instance-id" />
+                        <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+                            p:actionName="getTaskWallClockTime" p:methodName="setInstanceId"
+                            p:argDescription="instance-id" />
+                        <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+                            p:actionName="stopWorkflowInst" p:methodName="setInstanceId"
+                            p:argDescription="instance-id" />
+                        <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+                            p:actionName="pauseWorkflowInst" p:methodName="setInstanceId"
+                            p:argDescription="instance-id" />
+                        <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+                            p:actionName="resumeWorkflowInst" p:methodName="setInstanceId"
+                            p:argDescription="instance-id" />
+                        <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+                            p:actionName="getWorkflowInstMet" p:methodName="setInstanceId"
+                            p:argDescription="instance-id" />
+                    </list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+    <bean id="status" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="s" />
+        <property name="longOption" value="status" />
+        <property name="description" value="Workflow status" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="status" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getFirstPage" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getNextPage" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getPrevPage" p:relation="OPTIONAL" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getLastPage" p:relation="OPTIONAL" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+        </property>
+    </bean>
+
+    <bean id="pageNum" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+        <property name="shortOption" value="p" />
+        <property name="longOption" value="pageNum" />
+        <property name="description" value="Page Number" />
+        <property name="type" value="int" />
+        <property name="hasArgs" value="true" />
+        <property name="argsDescription" value="page" />
+        <property name="requirementRules">
+            <list>
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getNextPage" p:relation="REQUIRED" />
+                <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+                    p:actionName="getPrevPage" p:relation="REQUIRED" />
+            </list>
+        </property>
+        <property name="handler">
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+        </property>
+    </bean>
+</beans>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/conditions.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/conditions.xml
new file mode 100644
index 0000000..3375fc5
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/conditions.xml
@@ -0,0 +1,21 @@
+<!--
+  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.
+-->
+<cas:conditions xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<!--
+  TODO: Add some examples
+-->
+</cas:conditions>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/events.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/events.xml
new file mode 100644
index 0000000..84a02ae
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/events.xml
@@ -0,0 +1,21 @@
+<!--
+  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.
+-->
+<cas:workflowevents xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<!--
+  TODO: Add some examples
+-->
+</cas:workflowevents>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/tasks.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/tasks.xml
new file mode 100644
index 0000000..86aa67e
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/tasks.xml
@@ -0,0 +1,21 @@
+<!--
+  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.
+-->
+<cas:tasks xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<!--
+  TODO: Add some examples
+-->
+</cas:tasks>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/workflow-instance-met.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/workflow-instance-met.xml
new file mode 100644
index 0000000..2905a46
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/workflow-instance-met.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<!-- FIXME: Change namespace URI? -->
+<cas:winstfields xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<default>
+  <field name="WorkflowInstId"/>
+  <field name="TaskId"/>
+  <field name="ProcessingNode"/>
+</default>
+<workflow id="urn:oodt:testWorkflow">
+  <field name="WorkflowInstId"/>
+</workflow>
+<workflow id="urn:oodt:testMetErrorWorkflow">
+  <field name="numSeconds"/>
+  <field name="WorkflowInstId"/>
+  <field name="ProcessingNode"/>
+</workflow>
+<!--
+  TODO: Add some documentation
+-->
+</cas:winstfields>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/workflow-lifecycle.xml b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/workflow-lifecycle.xml
new file mode 100644
index 0000000..ccba643
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/archetype-resources/workflow/src/main/resources/policy/workflow-lifecycle.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<!-- FIXME: Change namespace URI? -->
+<cas:workflowlifecycles xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<default>
+  <stage name="error">
+    <status>METMISS</status>
+    <status>ERROR</status>
+  </stage>
+  <stage name="setup">
+    <status>QUEUED</status>
+    <status>CREATED</status>
+  </stage>
+  <stage name="precond_check">
+    <status>PAUSED</status>  
+  </stage>
+  <stage name="workflow_start">
+    <status>RSUBMIT</status>
+    <status>STARTED</status>
+  </stage>
+  <stage name="pge_setup_build_config_file">
+    <status>BUILDING CONFIG FILE</status>
+  </stage>
+  <stage name="pge_staging_input">
+    <status>STAGING INPUT</status>
+  </stage>
+  <stage name="pge_exec">
+    <status>PGE EXEC</status>
+  </stage>
+  <stage name="pcs_crawl">
+    <status>CRAWLING</status>
+  </stage>
+  <stage name="completion">
+    <status>FINISHED</status>
+  </stage>
+</default>
+
+<!-- 
+  Lifecycles can also be specified at the 
+  Workflow Id level, by starting with a 
+  <lifecycle name="" workflowId="some_id">
+    
+    declaration, and then using the stage
+    and status tags appropriately as shown
+    above
+    
+  </lifecycle>
+ -->
+</cas:workflowlifecycles>
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/bin/radix b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/bin/radix
new file mode 100755
index 0000000..52e295a
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/main/resources/bin/radix
@@ -0,0 +1,19 @@
+# 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.
+
+mvn archetype:generate -DarchetypeGroupId=org.apache.oodt \
+    -DarchetypeArtifactId=radix-archetype -DarchetypeVersion=0.8 \
+    -Doodt=0.8 -DgroupId=com.mycompany \
+    -DartifactId=oodt -Dversion=0.1
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/test/resources/projects/basic/archetype.properties b/0.8.1-rc1/mvn/archetypes/radix/src/test/resources/projects/basic/archetype.properties
new file mode 100644
index 0000000..995df71
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/test/resources/projects/basic/archetype.properties
@@ -0,0 +1,20 @@
+#Mon May 16 11:55:26 PDT 2011
+# 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.
+
+version=0.1-SNAPSHOT
+groupId=archetype.it
+artifactId=basic
+oodt=0.7-SNAPSHOT
diff --git a/0.8.1-rc1/mvn/archetypes/radix/src/test/resources/projects/basic/goal.txt b/0.8.1-rc1/mvn/archetypes/radix/src/test/resources/projects/basic/goal.txt
new file mode 100644
index 0000000..bd1c7e4
--- /dev/null
+++ b/0.8.1-rc1/mvn/archetypes/radix/src/test/resources/projects/basic/goal.txt
@@ -0,0 +1,16 @@
+<!--
+ 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.
+-->
diff --git a/0.8.1-rc1/mvn/plugins/cas-install/maven-cas-install-plugin.iml b/0.8.1-rc1/mvn/plugins/cas-install/maven-cas-install-plugin.iml
new file mode 100644
index 0000000..cca8c95
--- /dev/null
+++ b/0.8.1-rc1/mvn/plugins/cas-install/maven-cas-install-plugin.iml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
+    <output url="file://$MODULE_DIR$/target/classes" />
+    <output-test url="file://$MODULE_DIR$/target/test-classes" />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+      <excludeFolder url="file://$MODULE_DIR$/target" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: xml-apis:xml-apis:2.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.tika:tika-core:1.6" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.maven:maven-plugin-api:2.0" level="project" />
+    <orderEntry type="module" module-name="cas-metadata" />
+    <orderEntry type="module" module-name="oodt-commons" />
+    <orderEntry type="library" name="Maven: commons-dbcp:commons-dbcp:1.2.1" level="project" />
+    <orderEntry type="library" name="Maven: xml-apis:xml-apis:1.0.b2" level="project" />
+    <orderEntry type="library" name="Maven: commons-collections:commons-collections:2.1" level="project" />
+    <orderEntry type="library" name="Maven: commons-pool:commons-pool:1.2" level="project" />
+    <orderEntry type="library" name="Maven: xmlrpc:xmlrpc:2.0.1" level="project" />
+    <orderEntry type="library" name="Maven: xerces:xercesImpl:2.9.1" level="project" />
+    <orderEntry type="module" module-name="pcs-input" />
+    <orderEntry type="library" name="Maven: commons-lang:commons-lang:2.3" level="project" />
+    <orderEntry type="library" name="Maven: commons-logging:commons-logging:1.0.3" level="project" />
+    <orderEntry type="library" name="Maven: commons-codec:commons-codec:1.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.tika:tika-core:1.7" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-core:2.5.4" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-hibernate3:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: aopalliance:aopalliance:1.0" level="project" />
+    <orderEntry type="library" name="Maven: org.hibernate:hibernate:3.2.5.ga" level="project" />
+    <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache:1.2.3" level="project" />
+    <orderEntry type="library" name="Maven: asm:asm-attrs:1.5.3" level="project" />
+    <orderEntry type="library" name="Maven: dom4j:dom4j:1.6.1" level="project" />
+    <orderEntry type="library" name="Maven: antlr:antlr:2.7.6" level="project" />
+    <orderEntry type="library" name="Maven: cglib:cglib:2.1_3" level="project" />
+    <orderEntry type="library" name="Maven: asm:asm:1.5.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-beans:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-context:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-dao:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: com.google.guava:guava:10.0.1" level="project" />
+    <orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: junit:junit:3.8.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.ant:ant:1.7.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.ant:ant-launcher:1.7.0" level="project" />
+    <orderEntry type="library" name="Maven: commons-io:commons-io:1.4" level="project" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/0.8.1-rc1/mvn/plugins/cas-install/pom.xml b/0.8.1-rc1/mvn/plugins/cas-install/pom.xml
new file mode 100644
index 0000000..ebae4ed
--- /dev/null
+++ b/0.8.1-rc1/mvn/plugins/cas-install/pom.xml
@@ -0,0 +1,95 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../../../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>maven-cas-install-plugin</artifactId>
+  <packaging>maven-plugin</packaging>
+  <name>CAS Installer Maven Mojo</name>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>2.0</version>
+    </dependency>
+   <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-metadata</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.ant</groupId>
+      <artifactId>ant</artifactId>
+      <version>1.7.0</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <scope>compile</scope>
+   </dependency>
+  </dependencies>
+  <build>
+  	<pluginManagement>
+  		<plugins>
+  			<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+  			<plugin>
+  				<groupId>org.eclipse.m2e</groupId>
+  				<artifactId>lifecycle-mapping</artifactId>
+  				<version>1.0.0</version>
+  				<configuration>
+  					<lifecycleMappingMetadata>
+  						<pluginExecutions>
+  							<pluginExecution>
+  								<pluginExecutionFilter>
+  									<groupId>
+  										org.apache.maven.plugins
+  									</groupId>
+  									<artifactId>
+  										maven-plugin-plugin
+  									</artifactId>
+  									<versionRange>
+  										[3.3,)
+  									</versionRange>
+  									<goals>
+  										<goal>descriptor</goal>
+  									</goals>
+  								</pluginExecutionFilter>
+  								<action>
+  									<ignore />
+  								</action>
+  							</pluginExecution>
+  						</pluginExecutions>
+  					</lifecycleMappingMetadata>
+  				</configuration>
+  			</plugin>
+  		</plugins>
+  	</pluginManagement>
+  </build>
+</project>
diff --git a/0.8.1-rc1/mvn/plugins/cas-install/src/main/java/org/apache/oodt/cas/install/AntDecorator.java b/0.8.1-rc1/mvn/plugins/cas-install/src/main/java/org/apache/oodt/cas/install/AntDecorator.java
new file mode 100644
index 0000000..8c0b0b6
--- /dev/null
+++ b/0.8.1-rc1/mvn/plugins/cas-install/src/main/java/org/apache/oodt/cas/install/AntDecorator.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.install;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+
+//ANT imports
+import org.apache.commons.io.FileUtils;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Target;
+import org.apache.tools.ant.taskdefs.Chmod;
+import org.apache.tools.ant.taskdefs.Delete;
+import org.apache.tools.ant.taskdefs.Untar;
+import org.apache.tools.ant.taskdefs.Untar.UntarCompressionMethod;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A decorator wrapping <a href="http://ant.apache.org/">Apache Ant</a> core
+ * tasks
+ * </p>.
+ */
+public final class AntDecorator {
+    
+    public static void chmodFile(File file, String perms){
+        Chmoder chmod = new Chmoder();
+        chmod.setFile(file);
+        chmod.setPerm(perms);
+        chmod.execute();
+    }
+
+    public static void deleteAllFilesAndDir(File startDir) {
+        Deleter delete = new Deleter();
+        delete.setDir(startDir);
+        delete.setIncludeEmptyDirs(true);
+        delete.setVerbose(true);
+        delete.setFollowSymlinks(true);
+        delete.execute();
+    }
+
+    public static void untarFile(File tarFile, File destDir) throws IOException {
+        Untarer untar = new Untarer();
+        Untar.UntarCompressionMethod compMethod = new UntarCompressionMethod();
+        compMethod.setValue("gzip");
+        untar.setCompression(compMethod);
+        untar.setDest(destDir);
+        untar.setSrc(tarFile);
+        untar.execute();
+
+        // now that the work is done, use file utils to
+        // move everything out of destDir/tarFileNoExt
+        // into destDir
+        // then delete destDir/tarFileNoExt
+        String wrongInstallDir = destDir.getCanonicalPath() + File.separator
+                + getFileNameNoExt(tarFile.getName());
+        FileUtils.copyDirectory(new File(wrongInstallDir), destDir, true);
+
+        // grrr java IO, love it
+        // because it sucks, we have to CHMOD everything in destDir/bin
+        File binDir = new File(destDir.getCanonicalPath() + File.separator
+                + "bin");
+        Chmoder chmod = new Chmoder();
+        chmod.setDir(binDir);
+        chmod.setPerm("ugo+rx");
+        chmod.setIncludes("*");
+        chmod.execute();
+
+        deleteAllFilesAndDir(new File(wrongInstallDir));
+
+    }
+
+    final static class Untarer extends Untar {
+        public Untarer() {
+            project = new Project();
+            project.init();
+            taskType = "untar";
+            taskName = "untar";
+            target = new Target();
+        }
+
+    }
+
+    final static class Deleter extends Delete {
+        public Deleter() {
+            project = new Project();
+            project.init();
+            taskType = "delete";
+            taskName = "delete";
+            target = new Target();
+        }
+
+    }
+
+    final static class Chmoder extends Chmod {
+        public Chmoder() {
+            project = new Project();
+            project.init();
+            taskType = "chmod";
+            taskName = "chmod";
+            target = new Target();
+        }
+    }
+
+    private static String getFileNameNoExt(String filename) {
+        return filename.substring(0, filename.indexOf(".tar"));
+    }
+
+}
diff --git a/0.8.1-rc1/mvn/plugins/cas-install/src/main/java/org/apache/oodt/cas/install/CASInstallDirMetKeys.java b/0.8.1-rc1/mvn/plugins/cas-install/src/main/java/org/apache/oodt/cas/install/CASInstallDirMetKeys.java
new file mode 100644
index 0000000..806eafe
--- /dev/null
+++ b/0.8.1-rc1/mvn/plugins/cas-install/src/main/java/org/apache/oodt/cas/install/CASInstallDirMetKeys.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.install;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Met keys for the {@link CASInstallDistMojo}
+ * </p>.
+ */
+public interface CASInstallDirMetKeys {
+
+    public static final String POLICY_DIR_NAME = "policy";
+
+    public static final String CONFIG_DIR_NAME = "etc";
+    
+    public static final String LIB_DIR_NAME = "lib";
+    
+    public static final String BIN_DIR_NAME = "bin";
+
+    public static final String[] FM_CONFIG_FILES = { "filemgr.properties",
+            "logging.properties" };
+
+}
diff --git a/0.8.1-rc1/mvn/plugins/cas-install/src/main/java/org/apache/oodt/cas/install/CASInstallDistMojo.java b/0.8.1-rc1/mvn/plugins/cas-install/src/main/java/org/apache/oodt/cas/install/CASInstallDistMojo.java
new file mode 100644
index 0000000..150a312
--- /dev/null
+++ b/0.8.1-rc1/mvn/plugins/cas-install/src/main/java/org/apache/oodt/cas/install/CASInstallDistMojo.java
@@ -0,0 +1,317 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.install;
+
+//APACHE imports
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+//JDK imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+import java.io.File;
+import java.io.IOException;
+
+//OODT imports
+import static org.apache.oodt.cas.install.CASInstallDirMetKeys.*;
+
+/**
+ * Goal that unpackages a .tar.gz distribution of a CAS distro and installs it,
+ * overriding configuration files and installing custom policy files, as
+ * specified.
+ * 
+ * @goal install
+ */
+public class CASInstallDistMojo extends AbstractMojo {
+
+    /**
+     * Location of the CAS distribution to install, e.g.,
+     * /path/to/cas-filemgr-{version}.tar.gz.
+     * 
+     * @parameter
+     * @required
+     */
+    private File casDistributionFile;
+
+    /**
+     * Location of policy directories each containing XML-based CAS policy files
+     * (e.g., <code>product-types.xml</code>,
+     * <code>product-type-element-map.xml</code>, and
+     * <code>elements.xml</code> for the CAS) that will be installed into the
+     * {@link #casInstallationDir}/policy directory.
+     * 
+     * @parameter
+     * 
+     */
+    private File[] customPolicyDirs;
+
+    /**
+     * Location of a directory containing a custom CAS configuration, e.g., a
+     * filemgr.properties and/or a logging.properties file for filemgr that will
+     * be copied into the {@link #casInstallationDir}/etc directory.
+     * 
+     * @parameter
+     */
+    private File customConfigurationDir;
+
+    /**
+     * The directory to which the plugin will install the CAS. Defaults to
+     * /usr/local/${project.artifactId}-${project.version}, if not specified.
+     * 
+     * @parameter expression='/usr/local/${project.artifactId}-${project.version}'
+     */
+    private File casInstallationDir;
+
+    /**
+     * Location of custom jar files that you want to include in the
+     * {@link #casInstallationDir}/lib directory.
+     * 
+     * @parameter
+     */
+    private File[] customLibs;
+
+    /**
+     * Files to do dynamic {@link PathUtils#replaceEnvVariables(String)} on.
+     * 
+     * @parameter
+     */
+    private EnvReplacer[] envVarReplaceFiles;
+
+    /**
+     * Script files to potentially overwrite and customize functionality for the
+     * CAS bin scripts.
+     * 
+     * @parameter
+     */
+    private File[] customBinScripts;
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.maven.plugin.Mojo#execute()
+     */
+    public void execute() throws MojoExecutionException, MojoFailureException {
+
+        if (casDistributionFile == null
+                || (casDistributionFile != null && !casDistributionFile
+                        .exists())) {
+            throw new MojoExecutionException("the CAS distribution: ["
+                    + casDistributionFile + "] does not exist!");
+        }
+
+        // remove cas installation libs directory and its contents if custom libs specified.
+        // this is to prevent legacy jars from polluting the cas installation libs directory
+        if (customLibs != null && customLibs.length > 0) {
+
+            File libDir = null;
+            
+            // get the lib dir
+            try {
+                libDir = new File(casInstallationDir.getCanonicalPath()
+                        + File.separator + LIB_DIR_NAME);
+
+            } catch (IOException e) {
+                getLog().warn(
+                        "Unable to detect lib dir: IO exception: "
+                                + e.getMessage());
+            }
+
+            // delete the lib dir
+            if (libDir != null) {
+
+                getLog().warn(
+                		"removing pre-existing CAS libraries directory ["
+                		+libDir.getAbsolutePath()+"] since custom CAS libraries have been specified");
+                
+                try {
+					FileUtils.deleteDirectory(libDir);
+				} catch (IOException e) {
+	                getLog().warn(
+	                        "Unable to delete lib dir ["+libDir.getAbsolutePath()+"]: "
+	                                + e.getMessage());
+				}    
+            }         
+        }
+        
+        getLog().info(
+                "unpackaging distro: [" + casDistributionFile + "] to: ["
+                        + casInstallationDir + "]");
+        try {
+            AntDecorator.untarFile(casDistributionFile, casInstallationDir);
+        } catch (IOException e) {
+            throw new MojoExecutionException(
+                    "an IO exception occured while untarring the CAS distribution: Message: "
+                            + e.getMessage());
+        }
+
+        if (customPolicyDirs != null && customPolicyDirs.length > 0) {
+            getLog().info(
+                    "installing [" + customPolicyDirs.length
+                            + "] custom policy dirs");
+
+            // remove the default policy
+            File policyDir = null;
+            try {
+                policyDir = new File(casInstallationDir.getCanonicalPath()
+                        + File.separator + POLICY_DIR_NAME);
+                AntDecorator.deleteAllFilesAndDir(policyDir);
+            } catch (IOException e) {
+                getLog().warn(
+                        "IO exception when removing default policy from: ["
+                                + policyDir + "]: Message: " + e.getMessage());
+            }
+
+            for (int i = 0; i < customPolicyDirs.length; i++) {
+                getLog().info(
+                        "Installing: [" + customPolicyDirs[i] + "] to: ["
+                                + policyDir + "]");
+
+                if (customPolicyDirs[i].exists()) {
+                    try {
+                        FileUtils.copyDirectoryToDirectory(customPolicyDirs[i],
+                                policyDir);
+                    } catch (IOException e) {
+                        getLog().warn(
+                                "error copying custom policy dir: ["
+                                        + customPolicyDirs[i]
+                                        + "] to policy dir: [" + policyDir
+                                        + "]");
+                    }
+                }
+
+            }
+
+        }
+
+        if (customConfigurationDir != null && customConfigurationDir.exists()) {
+
+            try {
+                File configDir = new File(casInstallationDir.getCanonicalPath()
+                        + File.separator + CONFIG_DIR_NAME);
+
+                // remove default config
+                AntDecorator.deleteAllFilesAndDir(configDir);
+
+                configDir.mkdir();
+
+                // install custom config
+                FileUtils
+                        .copyDirectory(customConfigurationDir, configDir, true);
+
+            } catch (IOException e) {
+                getLog().warn(
+                        "Unable to detect configuration dir: IO exception: "
+                                + e.getMessage());
+            }
+
+        }
+
+        if (customLibs != null && customLibs.length > 0) {
+            getLog().info(
+                    "installing [" + customLibs.length
+                            + "] custom CAS libraries");
+
+            File libDir = null;
+            // get the lib dir
+            try {
+                libDir = new File(casInstallationDir.getCanonicalPath()
+                        + File.separator + LIB_DIR_NAME);
+
+            } catch (IOException e) {
+                getLog().warn(
+                        "Unable to detect lib dir: IO exception: "
+                                + e.getMessage());
+            }
+
+            for (int i = 0; i < customLibs.length; i++) {
+                getLog().info(
+                        "installing [" + customLibs[i] + "] to "
+                                + libDir.getAbsolutePath() + "]");
+                try {
+                    FileUtils.copyFileToDirectory(customLibs[i], libDir);
+                } catch (IOException e) {
+                    getLog().warn(
+                            "IOException installing [" + customLibs[i]
+                                    + "] to " + libDir.getAbsolutePath()
+                                    + "]: Message: " + e.getMessage());
+                }
+            }
+        }
+
+        if (envVarReplaceFiles != null && envVarReplaceFiles.length > 0) {
+            getLog().info(
+                    "Replacing env vars on [" + envVarReplaceFiles.length
+                            + "] files");
+
+            for (int i = 0; i < envVarReplaceFiles.length; i++) {
+                try {
+                    envVarReplaceFiles[i].doEnvReplace();
+                } catch (IOException e) {
+                    getLog().warn(
+                            "IOException while doing env replacement on: ["
+                                    + envVarReplaceFiles[i].getFilepath()
+                                    + "]: Message: " + e.getMessage());
+                }
+            }
+        }
+
+        if (customBinScripts != null && customBinScripts.length > 0) {
+            getLog().info(
+                    "installing [" + customBinScripts.length
+                            + "] custom bin scripts");
+
+            File binDir = null;
+
+            try {
+                binDir = new File(casInstallationDir.getCanonicalPath()
+                        + File.separator + BIN_DIR_NAME);
+            } catch (IOException e) {
+                getLog().warn(
+                        "Unable to detect bin dir: IO exception: Message: "
+                                + e.getMessage());
+            }
+
+            for (int i = 0; i < customBinScripts.length; i++) {
+                getLog().info(
+                        "installing [" + customBinScripts[i] + "] to ["
+                                + binDir + "]");
+                try {
+                    FileUtils.copyFileToDirectory(customBinScripts[i], binDir);
+                    // now chmod it with exec perms
+                    String custBinScriptFullPath = binDir + File.separator
+                            + customBinScripts[i].getName();
+
+                    getLog().info("fixing perms on ["+custBinScriptFullPath+"]");
+                    AntDecorator.chmodFile(new File(custBinScriptFullPath),
+                            "ugo+rx");
+                } catch (IOException e) {
+                    getLog().warn(
+                            "unable to install [" + customBinScripts[i]
+                                    + "] to [" + binDir
+                                    + "]: IO exception: Message: "
+                                    + e.getMessage());
+                }
+            }
+        }
+
+    }
+
+}
diff --git a/0.8.1-rc1/mvn/plugins/cas-install/src/main/java/org/apache/oodt/cas/install/EnvReplacer.java b/0.8.1-rc1/mvn/plugins/cas-install/src/main/java/org/apache/oodt/cas/install/EnvReplacer.java
new file mode 100644
index 0000000..b4ebc9f
--- /dev/null
+++ b/0.8.1-rc1/mvn/plugins/cas-install/src/main/java/org/apache/oodt/cas/install/EnvReplacer.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.install;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+
+//APACHE imports
+import org.apache.commons.io.FileUtils;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Does {@link PathUtils#replaceEnvVariables(String)} on the given
+ * {@link #filepath} by reading the {@link File} into a String using
+ * {@link FileUtils#readFileToString(File)} and then doing
+ * {@link PathUtils#replaceEnvVariables(String)} on that String.
+ * </p>.
+ */
+public class EnvReplacer {
+
+    private File filepath;
+
+    public void doEnvReplace() throws IOException {
+        if (this.filepath != null && this.filepath.exists()
+                && this.filepath.canWrite()) {
+
+            String existingFileStr = FileUtils.readFileToString(this.filepath);
+            String envReplacedFileStr = PathUtils
+                    .replaceEnvVariables(existingFileStr);
+            FileUtils.writeStringToFile(this.filepath, envReplacedFileStr);
+
+        }
+
+    }
+
+    /**
+     * @return the filepath
+     */
+    public File getFilepath() {
+        return filepath;
+    }
+
+    /**
+     * @param filepath
+     *            the filepath to set
+     */
+    public void setFilepath(File filepath) {
+        this.filepath = filepath;
+    }
+}
diff --git a/0.8.1-rc1/opendapps/pom.xml b/0.8.1-rc1/opendapps/pom.xml
new file mode 100644
index 0000000..201bcc8
--- /dev/null
+++ b/0.8.1-rc1/opendapps/pom.xml
@@ -0,0 +1,77 @@
+<?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.
+-->
+<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>
+  <artifactId>opendapps</artifactId>
+  <name>Apache OODT Configurable OPeNDAP Profile Server</name>
+  <description>A generic, configurable Apache OODT profile server
+  implementation that easily connects to OPeNDAP data sources. Connections 
+  are configured via an XML configuration file, providing information on how 
+  to extract and translate datasets from OPeNDAP and THREDDS into OODT profiles.
+  </description> 
+  <scm>
+   	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/opendapps</connection>
+   	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/opendapps</developerConnection>
+   	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/opendapps</url>
+  </scm>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <configuration>
+          <descriptorRefs>
+            <descriptorRef>jar-with-dependencies</descriptorRef>
+          </descriptorRefs>
+        </configuration>
+        <!-- enable creation of single jar to use this module stand alone -->
+        <executions>
+          <execution>
+            <id>make-assembly</id> <!-- this is used for inheritance merges -->
+            <phase>package</phase> <!-- bind to the packaging phase -->
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+   <dependency>
+     <groupId>edu.ucar</groupId>
+     <artifactId>netcdf</artifactId>
+     <version>4.2</version>
+   </dependency>
+   <dependency>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-profile</artifactId>
+    <version>${project.parent.version}</version>
+   </dependency>
+   <dependency>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-xmlquery</artifactId>
+    <version>${project.parent.version}</version>
+   </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/DapNames.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/DapNames.java
new file mode 100644
index 0000000..1d08a4d
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/DapNames.java
@@ -0,0 +1,39 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps;
+
+//OPeNDAP imports
+import opendap.dap.DAS;
+
+/**
+ * 
+ * A set of named constants for extracting information from OPeNDAP {@link DAS}
+ * profiles.
+ * 
+ */
+public interface DapNames {
+
+  public static final String ACTUAL_RANGE = "actual_range";
+
+  public static final String UNITS = "units";
+
+  public static final String START = "start";
+
+  public static final String END = "end";
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/DatasetCrawler.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/DatasetCrawler.java
new file mode 100644
index 0000000..32f8e83
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/DatasetCrawler.java
@@ -0,0 +1,129 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps;
+
+//JDK imports
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.opendapps.config.OpendapConfig;
+import org.apache.oodt.opendapps.extractors.MetadataExtractor;
+import org.apache.oodt.opendapps.extractors.ThreddsMetadataExtractor;
+
+import thredds.catalog.InvAccess;
+import thredds.catalog.InvCatalogRef;
+import thredds.catalog.InvDataset;
+import thredds.catalog.InvService;
+import thredds.catalog.ServiceType;
+import thredds.catalog.crawl.CatalogCrawler;
+
+/**
+ * Crawls a catalog and returns all the datasets and their references.
+ * 
+ */
+public class DatasetCrawler implements CatalogCrawler.Listener {
+
+  private static Logger LOG = Logger.getLogger(DatasetCrawler.class.getName());
+
+  private List<String> urls = new Vector<String>();
+
+  private Map<String, Metadata> datasetMet;
+
+  private String datasetURL = null;
+  
+  private OpendapConfig conf = null;
+
+  public DatasetCrawler(String datasetURL, OpendapConfig conf) {
+    this.datasetURL = datasetURL.endsWith("/") ? datasetURL : datasetURL + "/";
+    this.datasetMet = new HashMap<String, Metadata>();
+    this.conf = conf;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * thredds.catalog.crawl.CatalogCrawler.Listener#getCatalogRef(thredds.catalog
+   * .InvCatalogRef, java.lang.Object)
+   */
+  public boolean getCatalogRef(InvCatalogRef dd, Object context) {
+    return true;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * thredds.catalog.crawl.CatalogCrawler.Listener#getDataset(thredds.catalog
+   * .InvDataset, java.lang.Object)
+   */
+  public void getDataset(InvDataset dd, Object context) {
+  	String url = this.datasetURL + dd.getCatalogUrl().split("#")[1];
+    String id = dd.getID();    
+    LOG.log(Level.FINE, url + " is the computed access URL for this dataset");
+    // look for an OpenDAP access URL, only extract metadata if it is found
+    List<InvAccess> datasets = dd.getAccess();
+    if (dd.getAccess() != null && dd.getAccess().size() > 0) {
+      Iterator<InvAccess> sets = datasets.iterator();
+      while (sets.hasNext()) {
+        InvAccess single = sets.next();
+        InvService service = single.getService();
+        // note: select the OpenDAP access URL based on THREDDS service type
+        if (service.getServiceType()==ServiceType.OPENDAP) {
+          LOG.log(Level.FINE, "Found OpenDAP access URL: "+ single.getUrlPath());
+          String opendapurl = this.datasetURL + single.getUrlPath();
+          // extract metadata from THREDDS catalog
+          MetadataExtractor extractor = new ThreddsMetadataExtractor(dd);
+          Metadata met = new Metadata();
+          extractor.extract(met, conf);
+          // index metadata by opendap access URL
+          this.datasetMet.put(opendapurl, met);
+          this.urls.add(opendapurl);
+          break;
+        }
+      }
+    }
+  }
+
+  /**
+   * Gets the set of String {@link URL}s crawled.
+   * 
+   * @return A {@link List} of {@link String} representations of {@link URL}s.
+   */
+  public List<String> getURLs() {
+    return this.urls;
+  }
+
+  /**
+   * Returns the exracted THREDDS {@link InvDataset} metadata. The dataset
+   * metadata is mapped to the unique THREDDS dataset URL.
+   * 
+   * @return the exracted THREDDS {@link InvDataset} metadata.
+   */
+  public Map<String, Metadata> getDatasetMet() {
+    return this.datasetMet;
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/DatasetExtractor.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/DatasetExtractor.java
new file mode 100644
index 0000000..6e666bb
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/DatasetExtractor.java
@@ -0,0 +1,178 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps;
+
+//JDK imports
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.opendapps.config.OpendapConfig;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+//NetCDF-Java imports
+import thredds.catalog.crawl.CatalogCrawler;
+import ucar.nc2.util.CancelTask;
+import opendap.dap.DConnect;
+import opendap.dap.DataDDS;
+
+/**
+ * 
+ * This class takes in a query and the main catalog url and returns a list of
+ * relevant dataset urls
+ * 
+ */
+public class DatasetExtractor {
+
+  private static Logger LOG = Logger
+      .getLogger(DatasetExtractor.class.getName());
+
+  public static final String FINDALL = "PFunction=findall";
+
+  public static final String FINDSOME = "PFunction=findsome";
+
+  public static final String FINDQUERY = "PFunction=findquery";
+
+  private String q;
+
+  private String mainCatalogURL;
+
+  private String datasetURL;
+
+  private List<String> allUrls;
+
+  private Map<String, Metadata> datasetMet;
+  
+  private OpendapConfig conf;
+
+  public DatasetExtractor(XMLQuery q, String mainCatalogURL, String datasetURL, OpendapConfig conf) {
+    this.q = q.getKwdQueryString().trim();
+    this.mainCatalogURL = mainCatalogURL;
+    this.datasetURL = datasetURL;
+    this.conf = conf;
+    this.initExtraction();
+  }
+
+  public List<String> getDapUrls() {
+    List<String> urls = null;
+
+    if (this.q.contains(FINDALL))
+      urls = this.allUrls;
+    else if (this.q.contains(FINDSOME))
+      urls = this.getFindSome();
+    else if (this.q.contains(FINDQUERY))
+      urls = this.getFindQuery();
+
+    return urls;
+  }
+
+  public Metadata getDatasetMet(String opendapUrl){
+    return this.datasetMet.get(opendapUrl);
+  }
+
+  private void initExtraction() {
+    DatasetCrawler listener = new DatasetCrawler(this.datasetURL, this.conf);
+    CancelTask ignore = new CancelTask() {
+      public boolean isCancel() {
+        return false;
+      }
+
+      public void setError(String msg) {
+        LOG.log(Level.WARNING, msg);
+      }
+
+    };
+
+    LOG.log(Level.FINE, "catalogURL: " + this.mainCatalogURL);
+    // Note: look for all datasets, that have either a urlPath="" attribute, or a <access> subelement
+    CatalogCrawler crawler = new CatalogCrawler(CatalogCrawler.USE_ALL, false, listener);
+    crawler.crawl(this.mainCatalogURL, ignore, System.out, this);
+    this.allUrls = listener.getURLs();
+    this.datasetMet = listener.getDatasetMet();
+  }
+
+  private List<String> getFindQuery() {
+    LOG.log(Level.FINE, "PFunction: findquery selected: orig query: [" + this.q
+        + "]");
+    String queryExpression = "";
+    Pattern parameterPattern = Pattern.compile("PParameter=\"(.+?)\"");
+    Matcher urlsMatch = parameterPattern.matcher(this.q);
+    while (urlsMatch.find()) {
+      queryExpression = urlsMatch.group(1);
+    }
+
+    List<String> datasetUrls = new Vector<String>();
+
+    for (String datasetUrl : this.allUrls) {
+      DConnect dConn = null;
+      try {
+        dConn = new DConnect(datasetUrl, true);
+      } catch (FileNotFoundException e) {
+        e.printStackTrace();
+        LOG.log(Level.WARNING, datasetUrl
+            + " is neither a valid URL nor a filename.");
+      }
+      try {
+        DataDDS dds = dConn.getData(queryExpression, null);
+
+        if (dds != null) {
+          datasetUrls.add(datasetUrl);
+        }
+      } catch (Exception e) {
+        e.printStackTrace();
+        LOG.log(Level.SEVERE, " Some DAP2Exception or not a validate DDS", e);
+      }
+    }
+
+    return datasetUrls;
+
+  }
+
+  private List<String> getFindSome() {
+    LOG.log(Level.FINE, "PFunction: findsome selected");
+    String urlsString = "";
+    Pattern parameterPattern = Pattern.compile("PParameter=\"(.+?)\"");
+    Matcher urlsMatch = parameterPattern.matcher(this.q);
+    while (urlsMatch.find()) {
+      urlsString = urlsMatch.group(1);
+    }
+
+    LOG.log(Level.FINE, "PParameter: [" + urlsString
+        + "] parsed from original string query: [" + this.q + "]");
+
+    List<String> openDapUrls = new ArrayList<String>();
+
+    StringTokenizer tokens = new StringTokenizer(urlsString, ",");
+    while (tokens.hasMoreTokens()) {
+      openDapUrls.add(tokens.nextToken());
+    }
+
+    LOG.log(Level.FINE, "OPeNDAP urls: [" + openDapUrls + "]");
+    return openDapUrls;
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/OpendapProfileElementExtractor.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/OpendapProfileElementExtractor.java
new file mode 100644
index 0000000..fa6420b
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/OpendapProfileElementExtractor.java
@@ -0,0 +1,168 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.opendapps;
+
+//JDK imports
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OPeNDAP/THREDDS imports
+import opendap.dap.Attribute;
+import opendap.dap.AttributeTable;
+import opendap.dap.DAS;
+import opendap.dap.NoSuchAttributeException;
+
+//OODT imports
+import org.apache.oodt.opendapps.config.OpendapConfig;
+import org.apache.oodt.profile.EnumeratedProfileElement;
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileElement;
+import org.apache.oodt.profile.RangedProfileElement;
+
+import static org.apache.oodt.opendapps.DapNames.*;
+
+/**
+ * 
+ * 
+ * This class is used to set custom functionality for scraping data into
+ * different types of objects. The class looks at the {@link OpendapConfig} and
+ * then tries to stuff what's in each &lt;var&gt; into
+ * {@link RangedProfileElement} or {@link EnumeratedProfileElement}. The class
+ * is designed with extensibility in mind in case new {@link ProfileElement}
+ * types are created in the future.
+ * 
+ */
+public class OpendapProfileElementExtractor {
+
+  private static final Logger LOG = Logger
+      .getLogger(OpendapProfileElementExtractor.class.getName());
+
+  private OpendapConfig conf;
+
+  public OpendapProfileElementExtractor(OpendapConfig conf) {
+    this.conf = conf;
+  }
+
+  public RangedProfileElement extractRangedProfileElement(String elemName, String varname,
+      Profile profile, DAS das) throws NoSuchAttributeException {
+    RangedProfileElement elem = new RangedProfileElement(profile);
+    elem.setName(elemName);
+    AttributeTable attTable = null;
+    try {
+      attTable = das.getAttributeTable(varname);
+      
+      // make variable names case insensitive
+      if(attTable == null) attTable = das.getAttributeTable(varname.toLowerCase());
+      if(attTable == null) attTable = das.getAttributeTable(varname.toUpperCase());
+      if(attTable == null) throw new NoSuchAttributeException("Att table for ["+varname+"] is null!");
+    } catch (NoSuchAttributeException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Error extracting attribute table for element: ["
+          + elemName + "]: Message: " + e.getMessage());
+      throw e;
+
+    }
+
+    Enumeration attributeNames = attTable.getNames();
+
+    while (attributeNames.hasMoreElements()) {
+      String attrName = (String) attributeNames.nextElement();
+      Attribute attr = attTable.getAttribute(attrName);
+     
+      if (!attr.isContainer()) {
+      	 Enumeration attrValues = null;
+        
+        	try {
+            attrValues = attr.getValues();
+          } catch (NoSuchAttributeException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Attempt to resolve attribute: [" + attrName
+                + "] failed: Message: " + e.getMessage());
+            continue;
+         }
+  
+        while (attrValues.hasMoreElements()) {
+          String attrValue = (String) attrValues.nextElement();
+          if (attrName.equals(ACTUAL_RANGE)) {
+            elem.setMinValue(attrValue);
+            if (attrValues.hasMoreElements()) {
+              elem.setMaxValue((String) attrValues.nextElement());
+            }
+          } else if (attrName.equals(UNITS)) {
+            elem.setUnit(attrValue);
+          } else if (attrName.equals(START)) {
+            elem.setMinValue(attrValue);
+          } else if (attrName.equals(END)) {
+            elem.setMaxValue(attrValue);
+          }
+        }
+      }
+      
+    } // not a container attribute
+    
+    return elem;
+  }
+
+  public EnumeratedProfileElement extractEnumeratedProfileElement(String elemName, String varname,
+      Profile profile, DAS das)
+      throws NoSuchAttributeException {
+    EnumeratedProfileElement elem = new EnumeratedProfileElement(profile);
+    elem.setName(elemName);
+
+    AttributeTable attTable = null;
+    try {
+      attTable = das.getAttributeTable(elemName);
+    } catch (NoSuchAttributeException e) {
+      LOG.log(Level.WARNING, "Error extracting attribute table for element: ["
+          + elemName + "]: Message: " + e.getMessage());
+      throw e;
+
+    }
+
+    Enumeration attributeNames = attTable.getNames();
+    while (attributeNames.hasMoreElements()) {
+      String attrName = (String) attributeNames.nextElement();
+      Attribute attr = attTable.getAttribute(attrName);
+      Enumeration attrValues = null;
+      try {
+        attrValues = attr.getValues();
+      } catch (NoSuchAttributeException e) {
+        LOG.log(Level.WARNING, "Attempt to resolve attribute: [" + attrName
+            + "] failed: Message: " + e.getMessage());
+        continue;
+      }
+
+      while (attrValues.hasMoreElements()) {
+        String attrValue = (String) attrValues.nextElement();
+        if (attrName.equals(ACTUAL_RANGE)) {
+          String[] vals = attrValue.split(" ");
+          elem.getValues().addAll(Arrays.asList(vals));
+        } else if (attrName.equals(UNITS)) {
+          elem.setUnit(attrValue);
+        } else {
+          elem.getValues().add(attrValue);
+        }
+      }
+
+    }
+
+    return elem;
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/OpendapProfileHandler.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/OpendapProfileHandler.java
new file mode 100644
index 0000000..5870fef
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/OpendapProfileHandler.java
@@ -0,0 +1,186 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps;
+
+//JDK imports
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import opendap.dap.DConnect;
+
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.opendapps.config.DapRoot;
+import org.apache.oodt.opendapps.config.OpendapConfig;
+import org.apache.oodt.opendapps.config.OpendapConfigReader;
+import org.apache.oodt.opendapps.extractors.DasMetadataExtractor;
+import org.apache.oodt.opendapps.extractors.MetadataExtractor;
+import org.apache.oodt.opendapps.extractors.NcmlMetadataExtractor;
+import org.apache.oodt.opendapps.extractors.ThreddsMetadataExtractor;
+import org.apache.oodt.opendapps.util.ProfileUtils;
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileException;
+import org.apache.oodt.profile.handlers.ProfileHandler;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+/**
+ * 
+ * 
+ * A generic reusable OODT {@link ProfileHandler} for use in extracting metadata
+ * from OPeNDAP and THREDDS-accessible datasets.
+ * 
+ */
+public class OpendapProfileHandler implements ProfileHandler {
+
+  private static final String PROFILE_HANDLER_ID = "OODT OPeNDAP Profile Handler";
+
+  private static Logger LOG = Logger.getLogger(OpendapProfileHandler.class
+      .getName());
+
+  private OpendapConfig conf;
+
+  public OpendapProfileHandler(){
+  }
+
+  /**
+   * Implementation of interface method
+   */
+  public List<Profile> findProfiles(XMLQuery xmlQuery) throws ProfileException {
+    String configFileLoc = null;
+    String q = xmlQuery.getKwdQueryString();
+    if (q.contains("ConfigUrl=")){
+    	Pattern parameterPattern = Pattern.compile("ConfigUrl=(.+?)( .*)?$");
+    	Matcher fileMatch = parameterPattern.matcher(q);
+    	while (fileMatch.find()) {
+    		configFileLoc = fileMatch.group(1);
+    	}
+    } else {
+    	configFileLoc = System.getProperty("org.apache.oodt.opendap.config.filePath");
+    }
+    
+    if (configFileLoc.isEmpty()){
+    	throw new ProfileException(
+    		"Configuration file not found. Please specify in System property opendap.config.filePath or as URL parameter ConfigUrl");
+    } else {
+    	try {
+    		this.conf = OpendapConfigReader.read(configFileLoc);
+    	} catch (FileNotFoundException e) {
+    		throw new ProfileException("FileNotFoundException: File not found!");
+    	} catch (MalformedURLException e) {
+    		throw new ProfileException("MalformedURLException: please fix file URL");
+    	}
+    }
+    
+    List<Profile> profiles = new Vector<Profile>();
+    List<DapRoot> roots = this.conf.getRoots();
+	  
+    // loop over THREDDS catalogs
+    for (DapRoot root : roots) {
+    	LOG.log(Level.INFO,"Parsing DapRoot="+root.getDatasetUrl());
+
+      DatasetExtractor d = new DatasetExtractor(xmlQuery, root.getCatalogUrl()
+          .toExternalForm(), root.getDatasetUrl().toExternalForm(), conf);
+      if (d.getDapUrls() != null) {
+        for (String opendapUrl : d.getDapUrls()) {
+        	
+          // wrap the profile generation in try-catch to avoid stopping the whole harvesting process in case an exception is thrown
+          try {
+
+          	LOG.log(Level.FINE,"Connecting to opendapurl="+opendapUrl);
+  
+            Profile profile = new Profile();
+            DConnect dConn = null;
+            try {
+              dConn = new DConnect(opendapUrl, true);
+            } catch (FileNotFoundException e) {
+              LOG.log(Level.WARNING, "Opendap URL not found: [" + opendapUrl
+                  + "]: Message: " + e.getMessage());
+              throw new ProfileException("Opendap URL not found: [" + opendapUrl
+                  + "]: Message: " + e.getMessage());
+            }
+
+            // retrieve already extracted THREDDS metadata
+            Metadata datasetMet = d.getDatasetMet(opendapUrl);
+            
+            // extract DAS metadata
+            MetadataExtractor dasExtractor = new DasMetadataExtractor(dConn);
+            dasExtractor.extract(datasetMet, conf);
+            
+            // extract NcML metadata, if available
+           if (datasetMet.containsKey(ThreddsMetadataExtractor.SERVICE_TYPE_NCML)) {
+            	// retrieve URL of NcML document, previously stored
+            	final String ncmlUrl = datasetMet.getMetadata(ThreddsMetadataExtractor.SERVICE_TYPE_NCML);
+            	MetadataExtractor ncmlExtractor = new NcmlMetadataExtractor(ncmlUrl);
+            	ncmlExtractor.extract(datasetMet, conf);
+            }
+            
+            // debug: write out all metadata entries
+            for (String key : datasetMet.getAllKeys()) {
+          	  LOG.log(Level.FINER, "Metadata key="+key+" value="+datasetMet.getMetadata(key));
+            }
+         
+            // <resAttributes>
+            profile.setResourceAttributes(ProfileUtils.getResourceAttributes(
+                this.conf, opendapUrl, dConn, datasetMet));
+            
+            // <profAttributes>
+            profile.setProfileAttributes(ProfileUtils
+                .getProfileAttributes(this.conf, datasetMet));
+            // <profElement>
+            profile.getProfileElements().putAll(
+                ProfileUtils.getProfileElements(this.conf, dConn, datasetMet, profile));
+            profiles.add(profile);
+            LOG.log(Level.FINE, "Added profile id="+profile.getProfileAttributes().getID());
+            
+            
+          } catch(Exception e) {
+          	// in case of exception, don't harvest this dataset, but keep going
+          	LOG.log(Level.WARNING,"Error while building profile for opendapurl="+opendapUrl); 
+          	LOG.log(Level.WARNING,e.getMessage());
+          }
+
+        }
+      }
+    }
+    return profiles;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.profile.handlers.ProfileHandler#get(java.lang.String)
+   */
+  public Profile get(String id) throws ProfileException {
+    throw new ProfileException("method not implemented yet!");
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.profile.handlers.ProfileHandler#getID()
+   */
+  public String getID() {
+    return PROFILE_HANDLER_ID;
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/Profiler.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/Profiler.java
new file mode 100644
index 0000000..ae85684
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/Profiler.java
@@ -0,0 +1,156 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.opendapps;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.opendapps.util.ProfileChecker;
+import org.apache.oodt.opendapps.util.ProfileSerializer;
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.handlers.ProfileHandler;
+import org.apache.oodt.xmlquery.XMLQuery;
+import org.xml.sax.SAXException;
+
+/**
+ * Command line class to drive the creation of OODT profiles from THREDDS
+ * catalogs with OpenDAP endpoints.
+ * <p/>
+ * This class reads the list of THREDDS catalog URLs from the given opendapps
+ * configuration file, parses the catalogs, and it writes the OODT profiles (one
+ * for each THREDDS dataset) in the file "profiles.xml" in the specified
+ * directory, or in the local execution directory if none is specified.
+ * <p/>
+ * Usage: java -classpath [path to opendapps-version-jar-with-dependencies.jar]
+ * org.apache.oodt.opendapps.Profiler [config_file_location]
+ * [optional_output_dir]
+ * <p/>
+ * Usage example: java -classpath
+ * ./target/opendapps-0.4-SNAPSHOT-jar-with-dependencies.jar
+ * org.apache.oodt.opendapps.Profiler /home/users/testuser/opendap.config.xml
+ * /tmp
+ * 
+ * @author Luca Cinquini
+ * 
+ */
+public class Profiler {
+
+  private static Logger LOG = Logger.getLogger(Profiler.class.getName());
+  
+  /**
+   * Optional directory to serialize the profiles to.
+   */
+  private File outputDir;
+
+  /**
+   * Command line invocation method.
+   * 
+   * @param args
+   */
+  public static void main(String[] args) throws Exception {
+
+    // parse command line input
+    if (args.length != 1 && args.length != 2) {
+      usage();
+    }
+    File configFile = new File(args[0]);
+    Profiler profiler = new Profiler();
+    if (args.length == 2) {
+      profiler.setOutputDir( new File(args[1]) );
+    }
+    
+    // run profiler
+    profiler.makeProfiles(configFile);
+    
+  }
+  
+  /**
+   * No argument constructor.
+   */
+  public Profiler() {}
+  
+  /**
+   * Setter method for output directory.
+   * @param outputDir
+   */
+  public void setOutputDir(File outputDir) {
+		this.outputDir = outputDir;
+	}
+
+	/**
+   * Method to generate OODT profiles according to the specifications contained in a configuration file.
+   * 
+   * @param configFile 
+   * @return
+   */
+  public List<Profile> makeProfiles(final File configFile) throws Exception {
+
+    // parse THREDDS catalogs, create OODT profiles
+    ProfileHandler profileHandler = new OpendapProfileHandler();
+    XMLQuery xmlQuery = Profiler.buildXMLQuery(configFile);
+    @SuppressWarnings(value = "unchecked")
+    final List<Profile> profiles = profileHandler.findProfiles(xmlQuery);
+    
+    // check profiles
+    for (final Profile profile : profiles) {
+    	final StringBuilder sb = new StringBuilder();
+    	boolean ok = ProfileChecker.check(profile, sb);
+    	// print out the profile summary for quick review by the publisher
+    	System.out.println(sb.toString());
+    	if (!ok) {
+    		LOG.log(Level.SEVERE, "ERROR: invalid profile:"+profile.getResourceAttributes().getIdentifier());
+    	} 	
+    }
+
+    // serialize profiles to XML
+    String xml = ProfileSerializer.toXML(profiles);
+    LOG.log(Level.FINE, xml);
+
+    // write XML to disk
+    if (outputDir != null) {
+      final File file = new File(outputDir, "profiles.xml");
+      FileUtils.writeStringToFile(file, xml);
+    }
+
+    return profiles;
+    
+  }
+
+  private static XMLQuery buildXMLQuery(final File file) throws SAXException {
+
+    final String query = "<query><queryKWQString>"
+        + "PFunction=findall?ConfigUrl=" + file.getAbsolutePath()
+        + "</queryKWQString></query>";
+    final XMLQuery xmlQuery = new XMLQuery(query);
+    return xmlQuery;
+
+  }
+
+  private final static void usage() {
+    System.out
+        .println("Usage: java -classpath [path to opendapps-version-jar-with-dependencies.jar] org.apache.oodt.opendapps.Profiler <config file location> [<output_dir>]");
+    System.out
+        .println("Example: java -classpath ./target/opendapps-0.4-SNAPSHOT-jar-with-dependencies.jar org.apache.oodt.opendapps.Profiler /home/users/testuser/opendap.config.xml /tmp");
+    System.exit(-1);
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/ConstantSpec.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/ConstantSpec.java
new file mode 100644
index 0000000..06c3fe4
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/ConstantSpec.java
@@ -0,0 +1,91 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps.config;
+
+//APACHE imports
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileAttributes;
+import org.apache.oodt.profile.ResourceAttributes;
+
+/**
+ * 
+ * A specification of a constant field to flow through into either the generated
+ * {@link Profile}s {@link ProfileAttributes} section or its
+ * {@link ResourceAttributes} section. Part of the {@link OpendapConfig}.
+ * 
+ */
+public class ConstantSpec {
+
+  private String type;
+
+  private String name;
+
+  private String value;
+
+  public ConstantSpec() {
+    this.type = null;
+    this.name = null;
+    this.value = null;
+  }
+
+  /**
+   * @return the type
+   */
+  public String getType() {
+    return type;
+  }
+
+  /**
+   * @param type
+   *          the type to set
+   */
+  public void setType(String type) {
+    this.type = type;
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return the value
+   */
+  public String getValue() {
+    return value;
+  }
+
+  /**
+   * @param value
+   *          the value to set
+   */
+  public void setValue(String value) {
+    this.value = value;
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/DapRoot.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/DapRoot.java
new file mode 100644
index 0000000..2784368
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/DapRoot.java
@@ -0,0 +1,88 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps.config;
+
+//JDK imports
+import java.net.URL;
+
+/**
+ * 
+ * A set of root {@link URL} information for OPeNDAP/THREDDS catalogs to crawl
+ * and obtain dataset metadata from.
+ * 
+ */
+public class DapRoot {
+
+  private URL datasetUrl;
+
+  private URL catalogUrl;
+
+  private String filter;
+
+  public DapRoot() {
+    this.datasetUrl = null;
+    this.catalogUrl = null;
+    this.filter = null;
+  }
+
+  /**
+   * @return the datasetUrl
+   */
+  public URL getDatasetUrl() {
+    return datasetUrl;
+  }
+
+  /**
+   * @param datasetUrl
+   *          the datasetUrl to set
+   */
+  public void setDatasetUrl(URL datasetUrl) {
+    this.datasetUrl = datasetUrl;
+  }
+
+  /**
+   * @return the catalogUrl
+   */
+  public URL getCatalogUrl() {
+    return catalogUrl;
+  }
+
+  /**
+   * @param catalogUrl
+   *          the catalogUrl to set
+   */
+  public void setCatalogUrl(URL catalogUrl) {
+    this.catalogUrl = catalogUrl;
+  }
+
+  /**
+   * @return the filter
+   */
+  public String getFilter() {
+    return filter;
+  }
+
+  /**
+   * @param filter
+   *          the filter to set
+   */
+  public void setFilter(String filter) {
+    this.filter = filter;
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/DatasetMetElem.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/DatasetMetElem.java
new file mode 100644
index 0000000..7afbdb9
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/DatasetMetElem.java
@@ -0,0 +1,70 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps.config;
+
+//APACHE imports
+import org.apache.oodt.profile.EnumeratedProfileElement;
+
+/**
+ * 
+ * Specification for the {@link OpendapConfig} that specifies what THREDDS
+ * dataset met to use to create {@link EnumeratedProfileElement}s from.
+ * 
+ */
+public class DatasetMetElem {
+
+  private String profileElementName;
+
+  private String value;
+
+  public DatasetMetElem() {
+    this.profileElementName = null;
+    this.value = null;
+  }
+
+  /**
+   * @return the profileElementName
+   */
+  public String getProfileElementName() {
+    return profileElementName;
+  }
+
+  /**
+   * @param profileElementName
+   *          the profileElementName to set
+   */
+  public void setProfileElementName(String profileElementName) {
+    this.profileElementName = profileElementName;
+  }
+
+  /**
+   * @return the value
+   */
+  public String getValue() {
+    return value;
+  }
+
+  /**
+   * @param value
+   *          the value to set
+   */
+  public void setValue(String value) {
+    this.value = value;
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/OpendapConfig.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/OpendapConfig.java
new file mode 100644
index 0000000..7d9dacb
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/OpendapConfig.java
@@ -0,0 +1,128 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps.config;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * 
+ * The configuration object for the {@link OpendapProfileHandler}.
+ * 
+ */
+public class OpendapConfig {
+
+  private List<DapRoot> roots;
+
+  private List<RewriteSpec> rewriteSpecs;
+
+  private List<ConstantSpec> constSpecs;
+
+  private List<DatasetMetElem> datasetMetSpecs;
+  
+  private ProcessingInstructions processingInstructions;
+
+  public OpendapConfig() {
+    this.roots = new Vector<DapRoot>();
+    this.rewriteSpecs = new Vector<RewriteSpec>();
+    this.constSpecs = new Vector<ConstantSpec>();
+    this.datasetMetSpecs = new Vector<DatasetMetElem>();
+    this.processingInstructions = new ProcessingInstructions();
+  }
+
+  /**
+   * @return the roots
+   */
+  public List<DapRoot> getRoots() {
+    return roots;
+  }
+
+  /**
+   * @param roots
+   *          the roots to set
+   */
+  public void setRoots(List<DapRoot> roots) {
+    this.roots = roots;
+  }
+
+  /**
+   * @return the rewriteSpecs
+   */
+  public List<RewriteSpec> getRewriteSpecs() {
+    return rewriteSpecs;
+  }
+
+  /**
+   * @param rewriteSpecs
+   *          the rewriteSpecs to set
+   */
+  public void setRewriteSpecs(List<RewriteSpec> rewriteSpecs) {
+    this.rewriteSpecs = rewriteSpecs;
+  }
+
+  /**
+   * @return the constSpecs
+   */
+  public List<ConstantSpec> getConstSpecs() {
+    return constSpecs;
+  }
+
+  /**
+   * @param constSpecs
+   *          the constSpecs to set
+   */
+  public void setConstSpecs(List<ConstantSpec> constSpecs) {
+    this.constSpecs = constSpecs;
+  }
+
+  /**
+   * @return the datasetMetSpecs
+   */
+  public List<DatasetMetElem> getDatasetMetSpecs() {
+    return datasetMetSpecs;
+  }
+
+  /**
+   * @param datasetMetSpecs
+   *          the datasetMetSpecs to set
+   */
+  public void setDatasetMetSpecs(List<DatasetMetElem> datasetMetSpecs) {
+    this.datasetMetSpecs = datasetMetSpecs;
+  }
+  
+  /**
+   * Returns all processing instructions.
+   * 
+   * @return the processingInstructions
+   */
+  public ProcessingInstructions getProcessingInstructions() {
+  	return this.processingInstructions;
+  }
+  
+  /**
+   * Adds a processing instruction.
+   * 
+   * @param key
+   * @param value
+   */
+  public void addProcessingInstruction(String key, String value) {
+  	this.processingInstructions.addInstruction(key, value);
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/OpendapConfigMetKeys.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/OpendapConfigMetKeys.java
new file mode 100644
index 0000000..6be8298
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/OpendapConfigMetKeys.java
@@ -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.
+ */
+
+package org.apache.oodt.opendapps.config;
+
+/**
+ * 
+ * A set of metadata keys for reading the {@link OpendapConfig}.
+ * 
+ */
+public interface OpendapConfigMetKeys {
+
+  public static final String RES_ATTR_SPEC_TYPE = "resAttr";
+
+  public static final String PROF_ATTR_SPEC_TYPE = "profAttr";
+
+  public static final String PROF_ELEM_SPEC_TYPE = "profElem";
+
+  public static final String ENUM_ELEMENT_TYPE = "EnumeratedProfileElement";
+
+  public static final String RANGED_ELEMENT_TYPE = "RangedProfileElement";
+
+  public static final String DAP_ROOT_TAG = "root";
+
+  public static final String DATASET_URL_ATTR = "datasetURL";
+
+  public static final String CATALOG_URL_ATTR = "catalogURL";
+
+  public static final String FILTER_ATTR = "filter";
+
+  public static final String REWRITE_ROOT_TAG = "rewrite";
+
+  public static final String REWRITE_VAR_TAG = "var";
+
+  public static final String REWRITE_VAR_NAME_ATTR = "name";
+
+  public static final String REWRITE_VAR_RENAME_ATTR = "rename";
+
+  public static final String REWRITE_VAR_TYPE_ATTR = "type";
+
+  public static final String CONSTANT_ROOT_TAG = "constants";
+
+  public static final String CONSTANT_TAG = "const";
+
+  public static final String CONSTANT_NAME_ATTR = "name";
+
+  public static final String CONSTANT_TYPE_ATTR = "type";
+
+  public static final String CONSTANT_VALUE_ATTR = "value";
+  
+  public static final String DATASET_MET_ROOT_TAG = "datasetMetadata";
+  
+  public static final String DATASET_MET_ELEM_TAG = "elem";
+  
+  public static final String DATASET_MET_NAME_ATTR = "name";
+  
+  public static final String DATASET_MET_VALUE_ATTR = "value";
+  
+  public static final String RES_LOCATION_ATTR = "resLocation";
+  
+  public static final String PROCESSING_INSTRUCTIONS_TAG = "processingInstructions";
+  
+  public static final String PROCESSING_INSTRUCTION_TAG = "processingInstruction";
+  
+  public static final String PROCESSING_INSTRUCTION_NAME_ATTR = "name";
+  
+  public static final String PROCESSING_INSTRUCTION_VALUE_ATTR = "value";
+  
+  public static final String EXCLUDE_VARIABLES_ATTR = "excludeVariables";
+  
+  public static final String DATETIME_FORMAT_ATTR = "datetimeFormat";
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/OpendapConfigReader.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/OpendapConfigReader.java
new file mode 100644
index 0000000..4137805
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/OpendapConfigReader.java
@@ -0,0 +1,133 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps.config;
+
+// OODT imports
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.CATALOG_URL_ATTR;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.CONSTANT_NAME_ATTR;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.CONSTANT_ROOT_TAG;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.CONSTANT_TAG;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.CONSTANT_TYPE_ATTR;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.CONSTANT_VALUE_ATTR;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.DAP_ROOT_TAG;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.DATASET_MET_ELEM_TAG;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.DATASET_MET_NAME_ATTR;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.DATASET_MET_ROOT_TAG;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.DATASET_MET_VALUE_ATTR;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.DATASET_URL_ATTR;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.FILTER_ATTR;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.PROCESSING_INSTRUCTIONS_TAG;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.PROCESSING_INSTRUCTION_NAME_ATTR;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.PROCESSING_INSTRUCTION_TAG;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.PROCESSING_INSTRUCTION_VALUE_ATTR;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.REWRITE_ROOT_TAG;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.REWRITE_VAR_NAME_ATTR;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.REWRITE_VAR_RENAME_ATTR;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.REWRITE_VAR_TAG;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.REWRITE_VAR_TYPE_ATTR;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * 
+ * Reads the {@link OpendapConfig} from a provided file and returns it.
+ * 
+ */
+public class OpendapConfigReader {
+
+  public static OpendapConfig read(String confFilePath)
+      throws FileNotFoundException, MalformedURLException {
+    OpendapConfig conf = new OpendapConfig();
+    Document doc = XMLUtils.getDocumentRoot(new FileInputStream(new File(
+        confFilePath)));
+    Element rootElem = doc.getDocumentElement();
+
+    NodeList dapRootNodeList = rootElem.getElementsByTagName(DAP_ROOT_TAG);
+    for (int i = 0; i < dapRootNodeList.getLength(); i++) {
+      Element dapRootElem = (Element) dapRootNodeList.item(i);
+      DapRoot root = new DapRoot();
+      root.setCatalogUrl(new URL(dapRootElem.getAttribute(CATALOG_URL_ATTR)));
+      root.setDatasetUrl(new URL(dapRootElem.getAttribute(DATASET_URL_ATTR)));
+      root.setFilter(dapRootElem.getAttribute(FILTER_ATTR));
+      conf.getRoots().add(root);
+    }
+
+    Element rewriteRootElem = XMLUtils.getFirstElement(REWRITE_ROOT_TAG,
+        rootElem);
+    NodeList rewriteNodeList = rewriteRootElem
+        .getElementsByTagName(REWRITE_VAR_TAG);
+    for (int i = 0; i < rewriteNodeList.getLength(); i++) {
+      Element rewriteElem = (Element) rewriteNodeList.item(i);
+      RewriteSpec spec = new RewriteSpec();
+      spec.setOrigName(rewriteElem.getAttribute(REWRITE_VAR_NAME_ATTR));
+      spec.setRename(rewriteElem.getAttribute(REWRITE_VAR_RENAME_ATTR));
+      spec.setElementType(rewriteElem.getAttribute(REWRITE_VAR_TYPE_ATTR));
+      conf.getRewriteSpecs().add(spec);
+    }
+
+    Element datasetMetRootElem = XMLUtils.getFirstElement(DATASET_MET_ROOT_TAG,
+        rootElem);
+    NodeList datasetMetElemNodeList = datasetMetRootElem
+        .getElementsByTagName(DATASET_MET_ELEM_TAG);
+    for (int i = 0; i < datasetMetElemNodeList.getLength(); i++) {
+      Element datasetMetElem = (Element) datasetMetElemNodeList.item(i);
+      DatasetMetElem datasetMetSpec = new DatasetMetElem();
+      datasetMetSpec.setProfileElementName(datasetMetElem
+          .getAttribute(DATASET_MET_NAME_ATTR));
+      datasetMetSpec.setValue(datasetMetElem
+          .getAttribute(DATASET_MET_VALUE_ATTR));
+      conf.getDatasetMetSpecs().add(datasetMetSpec);
+    }
+
+    Element constRootElem = XMLUtils.getFirstElement(CONSTANT_ROOT_TAG,
+        rootElem);
+    NodeList constNodeList = constRootElem.getElementsByTagName(CONSTANT_TAG);
+    for (int i = 0; i < constNodeList.getLength(); i++) {
+      Element constElem = (Element) constNodeList.item(i);
+      ConstantSpec constSpec = new ConstantSpec();
+      constSpec.setName(constElem.getAttribute(CONSTANT_NAME_ATTR));
+      constSpec.setType(constElem.getAttribute(CONSTANT_TYPE_ATTR));
+      constSpec.setValue(constElem
+          .getAttribute(CONSTANT_VALUE_ATTR));
+      conf.getConstSpecs().add(constSpec);
+    }
+    
+    Element processingInstructionsElem = XMLUtils.getFirstElement(PROCESSING_INSTRUCTIONS_TAG, rootElem);
+    if (processingInstructionsElem!=null) {
+    	NodeList instNodeList = processingInstructionsElem.getElementsByTagName(PROCESSING_INSTRUCTION_TAG);
+    	for (int i = 0; i < instNodeList.getLength(); i++) {
+    		Element instElem = (Element) instNodeList.item(i);
+    		conf.addProcessingInstruction(instElem.getAttribute(PROCESSING_INSTRUCTION_NAME_ATTR), 
+    				                          instElem.getAttribute(PROCESSING_INSTRUCTION_VALUE_ATTR) );
+    	}
+    }
+
+    return conf;
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/OpendapProfileMetKeys.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/OpendapProfileMetKeys.java
new file mode 100644
index 0000000..d060b57
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/OpendapProfileMetKeys.java
@@ -0,0 +1,36 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.opendapps.config;
+
+/**
+ * Interface containing names for the metadata keys written to an OpenDAP profile document.
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public interface OpendapProfileMetKeys {
+	
+	 public static final String VARIABLES = "Variables";
+	 
+	 public static final String COORDINATES = "Coordinates";
+	 
+	 public static final String VARIABLES_LONG_NAMES = "Variable Long Names";
+	 
+	 public static final String CF_STANDARD_NAMES = "CF Standard Names";
+	 
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/ProcessingInstructions.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/ProcessingInstructions.java
new file mode 100644
index 0000000..08ad5e6
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/ProcessingInstructions.java
@@ -0,0 +1,102 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.opendapps.config;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.springframework.util.StringUtils;
+
+/**
+ * Class that holds special configuration instructions for generating an Opendap profile.
+ * Instructions are stored as (name, values) pairs: each named instruction can have multiple values.
+ * An instructions may be specified in the Opendap XML configuration file as a single element with comma-separated values,
+ * or as multiple elements with the same name (and one or more values each).
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public class ProcessingInstructions {
+	
+	/**
+	 * Local storage for processing instructions.
+	 * Note that the order of the XML elements is not preserved (on purpose).
+	 */
+	private final Map<String, Set<String>> instructions = new HashMap<String, Set<String>>();
+	
+	/**
+	 * Returns all values for a named instruction,
+	 * or an empty set if the instruction was not specified.
+	 * @param key
+	 * @return
+	 */
+	public Set<String> getInstructionValues(String key) {
+		if (instructions.containsKey(key)) {
+			return Collections.unmodifiableSet( instructions.get(key) );
+		} else {
+			return Collections.unmodifiableSet( new HashSet<String>() );
+		}
+	}
+	
+	/**
+	 * If an instruction contains a single value, it is returned.
+	 * If the instruction has no values or multiple values, returns null instead.
+	 * @param key
+	 * @return
+	 */
+	public String getInstructionValue(String key) {
+		if (instructions.get(key)!=null &&  instructions.get(key).size()==1) {
+			for (String value : instructions.get(key)) {
+				return value;
+			}
+		}
+		return null;
+	}
+	
+	/**
+	 * Returns all instructions.
+	 * @return
+	 */
+	public Map<String, Set<String>> getInstructions() {
+		return Collections.unmodifiableMap(instructions);
+	}
+	
+	/**
+	 * Method to add a value to a named instruction.
+	 * Value can be a comma separated list of values.
+	 * Leading and trailing spaces for each value are removed.
+	 * @param key
+	 * @param value
+	 */
+	public void addInstruction(String key, String value) {
+		if (StringUtils.hasText(key)) {
+			if (!instructions.containsKey(key)) {
+				instructions.put(key, new HashSet<String>());
+			}
+			String[] vals = value.split(",");
+			for (String val : vals) {
+				if (StringUtils.hasText(val)) {
+					instructions.get(key).add(val.trim());
+				}
+			}
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/RewriteSpec.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/RewriteSpec.java
new file mode 100644
index 0000000..fd8a0fe
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/config/RewriteSpec.java
@@ -0,0 +1,86 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps.config;
+
+/**
+ * 
+ * A specification for rewriting OPeNDAP element names and tags from their
+ * original OPeNDAP/THREDDS names into OODT profile elements, and their names
+ * and types. Part of the {@link OpendapConfig}.
+ * 
+ */
+public class RewriteSpec {
+
+  private String origName;
+
+  private String rename;
+
+  private String elementType;
+
+  public RewriteSpec() {
+    this.origName = null;
+    this.rename = null;
+    this.elementType = null;
+  }
+
+  /**
+   * @return the origName
+   */
+  public String getOrigName() {
+    return origName;
+  }
+
+  /**
+   * @param origName
+   *          the origName to set
+   */
+  public void setOrigName(String origName) {
+    this.origName = origName;
+  }
+
+  /**
+   * @return the rename
+   */
+  public String getRename() {
+    return rename;
+  }
+
+  /**
+   * @param rename
+   *          the rename to set
+   */
+  public void setRename(String rename) {
+    this.rename = rename;
+  }
+
+  /**
+   * @return the elementType
+   */
+  public String getElementType() {
+    return elementType;
+  }
+
+  /**
+   * @param elementType
+   *          the elementType to set
+   */
+  public void setElementType(String elementType) {
+    this.elementType = elementType;
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/extractors/DasMetadataExtractor.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/extractors/DasMetadataExtractor.java
new file mode 100644
index 0000000..635b15f
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/extractors/DasMetadataExtractor.java
@@ -0,0 +1,190 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps.extractors;
+
+//JDK imports
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+//OPENDAP imports
+import opendap.dap.Attribute;
+import opendap.dap.AttributeTable;
+import opendap.dap.DAS;
+import opendap.dap.DConnect;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.opendapps.config.OpendapConfig;
+import org.apache.oodt.opendapps.config.OpendapConfigMetKeys;
+import org.apache.oodt.opendapps.config.OpendapProfileMetKeys;
+import org.apache.oodt.opendapps.config.ProcessingInstructions;
+import org.apache.oodt.opendapps.util.ProfileUtils;
+import org.springframework.util.StringUtils;
+
+/**
+ * Implementation of {@link MetadataExtractor} to extract metadata from an
+ * OpenDAP DAS source. Currently this class only extracts metadata from the
+ * NetCDF global attributes of type String, disregarding all others.
+ * 
+ * @author Luca Cinquini
+ * 
+ */
+public class DasMetadataExtractor implements MetadataExtractor {
+
+  // constants from NetCDF metadata convention
+  public static final String NC_GLOBAL = "NC_GLOBAL";
+  public static final String LONG_NAME = "long_name";
+  public static final String STANDARD_NAME = "standard_name";
+
+  // NetCDF data types
+  public static final int INT32_TYPE = 6;
+  public static final int INT64_TYPE = 7;
+  public static final int FLOAT32_TYPE = 8;
+  public static final int FLOAT64_TYPE = 9;
+  public static final int STRING_TYPE = 10;
+  
+  // output format for all global attributes interpreted as dates
+  private final static String OUTPUT_DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+  private final static DateFormat outputDatetimeFormat = new SimpleDateFormat(OUTPUT_DATETIME_FORMAT);
+
+  private static Logger LOG = Logger.getLogger(DasMetadataExtractor.class
+      .getName());
+
+  /**
+   * The DAS stream which is the metadata source.
+   */
+  private final DConnect dConn;
+
+  public DasMetadataExtractor(DConnect dConn) {
+    this.dConn = dConn;
+  }
+
+  /**
+	 * The main metadata extraction method.
+	 * 
+	 * @param metadata
+	 *          : the metadata target, specifically the CAS metadata container.
+	 */
+	public void extract(Metadata metadata, OpendapConfig config) {
+	
+	  LOG.log(Level.INFO, "Parsing DAS metadata from: " + dConn.URL());
+	  
+	  // list of excluded variables
+	  Set<String> excludedVariables 
+	  	= config.getProcessingInstructions().getInstructionValues(OpendapConfigMetKeys.EXCLUDE_VARIABLES_ATTR);
+	
+	  try {
+	    DAS das = dConn.getDAS();
+	    @SuppressWarnings("unchecked")
+	    Enumeration<String> names = das.getNames();
+	    while (names.hasMoreElements()) {
+	      String attName = names.nextElement();
+	      LOG.log(Level.FINE, "Extracting DAS attribute: " + attName);
+	      AttributeTable at = das.getAttributeTable(attName);
+	      Enumeration<String> e = at.getNames();
+	      
+	      // NetCDF global attributes
+	      // store attribute name, all values for ALL attributes (strings and numerics)
+	      ProcessingInstructions processingInstructions = config.getProcessingInstructions();
+	      if (attName.equals(NC_GLOBAL)) {
+	      	while (e.hasMoreElements()) {
+	      		String key = e.nextElement();
+	      		Attribute att = at.getAttribute(key);
+	      		// convert all DAS attribute names to lower case
+	      		String lkey = key.toLowerCase();
+	      		
+	      		// look for global attribute name in date/time configuration specification
+	      		String dateTimeFormatKey = OpendapConfigMetKeys.DATETIME_FORMAT_ATTR + ":" + lkey;
+	      		String dateTimeFormatValue = processingInstructions.getInstructionValue(dateTimeFormatKey);
+	      		// add this attribute as properly formatted date/time
+	      		if (StringUtils.hasText(dateTimeFormatValue)) {
+	      			DateFormat inFormat = new SimpleDateFormat(dateTimeFormatValue);
+	      			Enumeration<String> edt = att.getValues();
+	      			while (edt.hasMoreElements()) {
+	      				String value = edt.nextElement();
+	      				try {
+  	      				Date date = inFormat.parse(value);
+  	      				ProfileUtils.addIfNotNull(metadata, lkey, outputDatetimeFormat.format(date));
+	      				} catch(ParseException pe) {
+	      					LOG.log(Level.WARNING, 
+	      							    "Error parsing date/time from DAS attribute: "+key+" value="+value+" error="+pe.getMessage());
+	      				}
+	      			}
+	      		// add this global attribute as string
+	      		} else {
+	      			ProfileUtils.addIfNotExisting(metadata, lkey, att.getValues());
+	      		}
+	      	}
+	        
+	      // NetCDF coordinates
+	      } else {
+	      	
+	      	if (   attName.equalsIgnoreCase("lat") || attName.equalsIgnoreCase("latitude")
+	      			|| attName.equalsIgnoreCase("lon") || attName.equalsIgnoreCase("longitude")
+	      			|| attName.equalsIgnoreCase("time")
+	      			|| attName.equalsIgnoreCase("alt") || attName.equalsIgnoreCase("altitude")
+	      			|| attName.equalsIgnoreCase("lev") || attName.equalsIgnoreCase("level")
+	      			|| attName.equalsIgnoreCase("depth")
+	      			) {
+	      		
+	      		if (!excludedVariables.contains(attName)) {
+	      			// store coordinate name
+	      			ProfileUtils.addIfNotNull(metadata, OpendapProfileMetKeys.COORDINATES, attName);
+	      		}
+	        	
+	      	} else if (attName.toLowerCase().startsWith("time_") || attName.toLowerCase().endsWith("_time")) {
+	      		
+	      		// ignore for now - it's not a coordinate neither a variable you would want to search on
+	      		
+	        // NetCDF variables
+	      	} else {
+	      		
+	      		if (!excludedVariables.contains(attName)) {
+	          	// store variable name
+	          	ProfileUtils.addIfNotNull(metadata, OpendapProfileMetKeys.VARIABLES, attName);
+	          	// store "standard_name", "long_name"
+	          	while (e.hasMoreElements()) {
+	          		String key = e.nextElement();
+	          		Attribute att = at.getAttribute(key);
+	          		if (key.equalsIgnoreCase(STANDARD_NAME)) {
+	          			ProfileUtils.addIfNotNull(metadata, OpendapProfileMetKeys.CF_STANDARD_NAMES, att.getValueAt(0));
+	          		} else if (key.equalsIgnoreCase(LONG_NAME)) {
+	          			ProfileUtils.addIfNotNull(metadata, OpendapProfileMetKeys.VARIABLES_LONG_NAMES, att.getValueAt(0));
+	          		}       		
+	          	}	
+	      		}
+	        	
+	      	}
+	      }
+	
+	    }
+	    
+	  } catch (Exception e) {
+	    LOG.log(Level.WARNING, "Error parsing DAS metadata: " + e.getMessage());
+	  }
+	
+	}
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/extractors/MetadataExtractor.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/extractors/MetadataExtractor.java
new file mode 100644
index 0000000..1cf9805
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/extractors/MetadataExtractor.java
@@ -0,0 +1,43 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps.extractors;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.opendapps.config.OpendapConfig;
+
+/**
+ * Interface for extracting metadata from a generic web accessible resource into
+ * a CAS metadata container. Each implementation class must be responsible for
+ * instantiating and accessing the specific metadata source as appropriate.
+ * 
+ * @author Luca Cinquini
+ * 
+ */
+public interface MetadataExtractor {
+
+  /**
+   * Method to (further) populate the metadata container. 
+   * Any extracted metadata is added to the current metadata content.
+   * 
+   * @param metadata
+   * @param config
+   */
+  void extract(Metadata metadata, OpendapConfig config);
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/extractors/NcmlMetadataExtractor.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/extractors/NcmlMetadataExtractor.java
new file mode 100644
index 0000000..9b40330
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/extractors/NcmlMetadataExtractor.java
@@ -0,0 +1,55 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps.extractors;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.opendapps.config.OpendapConfig;
+
+/**
+ * Implementation of {@link MetadataExtractor} that parses an NcML XML document.
+ * Currently this class is simply a stub that doesn't do anything.
+ * 
+ * @author Luca Cinquini
+ * 
+ */
+public class NcmlMetadataExtractor implements MetadataExtractor {
+
+  private final String ncmlUrl;
+
+  private static Logger LOG = Logger.getLogger(NcmlMetadataExtractor.class
+      .getName());
+
+  public NcmlMetadataExtractor(String ncmlUrl) {
+    this.ncmlUrl = ncmlUrl;
+  }
+
+  /**
+   * Stub implementation of interface method.
+   */
+  public void extract(Metadata metadata, OpendapConfig config) {
+
+    LOG.log(Level.FINE, "Parsing NcML metadata from: " + ncmlUrl);
+
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/extractors/ThreddsMetadataExtractor.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/extractors/ThreddsMetadataExtractor.java
new file mode 100644
index 0000000..74cba96
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/extractors/ThreddsMetadataExtractor.java
@@ -0,0 +1,325 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps.extractors;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.UUID;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.opendapps.config.OpendapConfig;
+import org.apache.oodt.opendapps.util.ProfileUtils;
+
+
+//Spring imports
+import org.springframework.util.StringUtils;
+
+//THREDDS imports
+import thredds.catalog.InvAccess;
+import thredds.catalog.InvDataset;
+import thredds.catalog.InvDocumentation;
+import thredds.catalog.InvProperty;
+import thredds.catalog.ServiceType;
+import thredds.catalog.ThreddsMetadata.Contributor;
+import thredds.catalog.ThreddsMetadata.GeospatialCoverage;
+import thredds.catalog.ThreddsMetadata.Range;
+import thredds.catalog.ThreddsMetadata.Source;
+import thredds.catalog.ThreddsMetadata.Vocab;
+import ucar.nc2.units.DateType;
+import ucar.unidata.geoloc.LatLonRect;
+
+/**
+ * Implementation of {@link MetadataExtractor} that extracts metadata from a
+ * Thredds dataset.
+ * 
+ * @author Luca Cinquini
+ * 
+ */
+public class ThreddsMetadataExtractor implements MetadataExtractor {
+
+  private static Logger LOG = Logger.getLogger(ThreddsMetadataExtractor.class
+      .getName());
+
+  // constant missing for 4.2 version of NetCDF library
+  public final static String SERVICE_TYPE_NCML = "NCML";
+  
+  /**
+   * The source of metadata to be extracted.
+   */
+  private final InvDataset dataset;
+
+  public ThreddsMetadataExtractor(final InvDataset dataset) {
+    this.dataset = dataset;
+  }
+
+  public void extract(Metadata met, OpendapConfig config) {
+
+    LOG.log(Level.INFO, "Crawling catalog URL=" + dataset.getCatalogUrl()
+        + " dataset ID=" + dataset.getID());
+
+    ProfileUtils.addIfNotNull(met, "Authority", dataset.getAuthority());
+    ProfileUtils.addIfNotNull(met, "CatalogUrl", dataset.getCatalogUrl());
+    try {
+    	ProfileUtils.addIfNotNull(met, "Host", (new URL(dataset.getCatalogUrl())).getHost() );
+    } catch(MalformedURLException e) {
+    	LOG.log(Level.WARNING, e.getMessage());
+    }
+    ProfileUtils.addIfNotNull(met, "DatasetFullName", dataset.getFullName());
+    if (dataset.getContributors() != null) {
+      for (Contributor contributor : dataset.getContributors()) {
+        ProfileUtils.addIfNotNull(met, "Contributor", contributor.getName());
+      }
+    }
+
+    if (dataset.getCreators() != null) {
+      for (Source source : dataset.getCreators()) {
+        ProfileUtils.addIfNotNull(met, "Creator", source.getName());
+      }
+    }
+
+    if (dataset.getDataFormatType() != null) {
+      ProfileUtils.addIfNotNull(met, "DataFormatType", dataset
+          .getDataFormatType().toString());
+    }
+
+    if (dataset.getDataType() != null) {
+      ProfileUtils.addIfNotNull(met, "DataType", dataset.getDataType()
+          .toString());
+    }
+
+    if (dataset.getDates() != null) {
+      for (DateType dateType : dataset.getDates()) {
+        String dateString = null;
+        try {
+          dateString = ProfileUtils.toISO8601(dateType.getDate());
+        } catch (Exception e) {
+          LOG.log(Level.WARNING,
+              "Error converting date: [" + dateType.getDate() + "]: Message: "
+                  + e.getMessage());
+        }
+        ProfileUtils.addIfNotNull(met, "Dates", dateString);
+      }
+    }
+
+    if (dataset.getDocumentation() != null) {
+      for (InvDocumentation doc : dataset.getDocumentation()) {
+      	// textual documentation
+      	if (StringUtils.hasText(doc.getInlineContent())) {
+      		if (StringUtils.hasText(doc.getType())) {
+      			// use specific documentation type, when available
+      			ProfileUtils.addIfNotNull(met, doc.getType(), doc.getInlineContent());
+      		} else {
+      			// otherwise use generic "Documentation" tag
+      			ProfileUtils.addIfNotNull(met, "Documentation", doc.getInlineContent());
+      		}
+      	}
+      	// hyperlinked documentation
+      	if (StringUtils.hasText(doc.getXlinkHref())) {
+      		String tuple = this.encodeXlinkTuple(doc.getXlinkHref(), doc.getXlinkTitle(), doc.getType());
+      		ProfileUtils.addIfNotNull(met, "Xlink", tuple);
+      	}
+      	
+      }
+    }
+
+    ProfileUtils.addIfNotNull(met, "FullName", dataset.getFullName());
+    GeospatialCoverage geoCoverage = dataset.getGeospatialCoverage();
+    
+    if (geoCoverage != null) {
+    	
+      LatLonRect bbox = geoCoverage.getBoundingBox();
+      if (bbox != null) {
+        ProfileUtils.addIfNotNull(met, "SouthwestBC", bbox.getLowerLeftPoint()
+            .toString());
+        ProfileUtils.addIfNotNull(met, "NorthwestBC", bbox.getUpperLeftPoint()
+            .toString());
+        ProfileUtils.addIfNotNull(met, "NortheastBC", bbox.getUpperRightPoint()
+            .toString());
+        ProfileUtils.addIfNotNull(met, "SoutheastBC", bbox.getLowerRightPoint()
+            .toString());
+      }
+      
+      // try north south, east west
+      if (geoCoverage.getNorthSouthRange() != null) {        	
+        Range nsRange = geoCoverage.getNorthSouthRange();
+        ProfileUtils.addIfNotNull(met, "NorthSouthRangeStart",
+            String.valueOf(nsRange.getStart()));
+        ProfileUtils.addIfNotNull(met, "NorthSouthRangeResolution",
+            String.valueOf(nsRange.getResolution()));
+        ProfileUtils.addIfNotNull(met, "NorthSouthRangeSize",
+            String.valueOf(nsRange.getSize()));
+        ProfileUtils.addIfNotNull(met, "NorthSouthRangeUnits",
+            nsRange.getUnits());
+        ProfileUtils.addIfNotNull(met, "NorthSouthRangeStop",
+            String.valueOf(nsRange.getStart()+nsRange.getSize()));
+      }
+
+      if (geoCoverage.getEastWestRange() != null) {
+        Range nsRange = geoCoverage.getEastWestRange();
+        ProfileUtils.addIfNotNull(met, "EastWestRangeStart",
+            String.valueOf(nsRange.getStart()));
+        ProfileUtils.addIfNotNull(met, "EastWestRangeResolution",
+            String.valueOf(nsRange.getResolution()));
+        ProfileUtils.addIfNotNull(met, "EastWestRangeSize",
+            String.valueOf(nsRange.getSize()));
+        ProfileUtils.addIfNotNull(met, "EastWestRangeUnits",
+            nsRange.getUnits());
+        ProfileUtils.addIfNotNull(met, "EastWestRangeStop",
+            String.valueOf(nsRange.getStart()+nsRange.getSize()));
+      }      
+
+      ProfileUtils.addIfNotNull(met, "GeospatialCoverageLatitudeResolution",
+          String.valueOf(dataset.getGeospatialCoverage().getLatResolution()));
+      ProfileUtils.addIfNotNull(met, "GeospatialCoverageLongitudeResolution",
+          String.valueOf(dataset.getGeospatialCoverage().getLonResolution()));
+      
+      // add geo-spatial coverage alternative form
+      ProfileUtils.addIfNotNull(met, "GeospatialCoverageLatSouth", String.valueOf(dataset.getGeospatialCoverage().getLatSouth()));
+      ProfileUtils.addIfNotNull(met, "GeospatialCoverageLatNorth", String.valueOf(dataset.getGeospatialCoverage().getLatNorth()));   
+      ProfileUtils.addIfNotNull(met, "GeospatialCoverageLonWest", String.valueOf(dataset.getGeospatialCoverage().getLonWest()));
+      ProfileUtils.addIfNotNull(met, "GeospatialCoverageLonEast", String.valueOf(dataset.getGeospatialCoverage().getLonEast()));
+      
+      if (dataset.getGeospatialCoverage().getNames() != null) {
+        for (Vocab gName : dataset.getGeospatialCoverage().getNames()) {
+          ProfileUtils.addIfNotNull(met, "GeospatialCoverage", gName.getText());
+        }
+      }
+
+    }
+
+    ProfileUtils.addIfNotNull(met, "History", dataset.getHistory());
+    if (dataset.getKeywords() != null) {
+      for (Vocab vocab : dataset.getKeywords()) {
+        ProfileUtils.addIfNotNull(met, "Keywords", vocab.getText());
+      }
+    }
+    ProfileUtils.addIfNotNull(met, "Name", dataset.getName());
+    ProfileUtils.addIfNotNull(met, "Processing", dataset.getProcessing());
+    if (dataset.getProjects() != null) {
+      for (Vocab vocab : dataset.getProjects()) {
+        ProfileUtils.addIfNotNull(met, "Projects", vocab.getText());
+      }
+    }
+
+    if (dataset.getProperties() != null) {
+      for (InvProperty prop : dataset.getProperties()) {
+        ProfileUtils.addIfNotNull(met, prop.getName(), prop.getValue());
+      }
+    }
+
+    if (dataset.getPublishers() != null) {
+      for (Source source : dataset.getPublishers()) {
+      	// Note: use "Publisher" (singular) as from the OODT profile specification
+        ProfileUtils.addIfNotNull(met, "Publisher", source.getName());
+      }
+    }
+
+    ProfileUtils.addIfNotNull(met, "RestrictAccess",
+        dataset.getRestrictAccess());
+    if (dataset.getTimeCoverage() != null) {
+      String startDateTimeStr = null, endDateTimeStr = null;
+      try {
+        startDateTimeStr = ProfileUtils.toISO8601(dataset.getTimeCoverage()
+            .getStart().getDate());
+        endDateTimeStr = ProfileUtils.toISO8601(dataset.getTimeCoverage()
+            .getEnd().getDate());
+      } catch (Exception e) {
+        LOG.log(
+            Level.WARNING,
+            "Error converting start/end date time strings: Message: "
+                + e.getMessage());
+      }
+
+      ProfileUtils.addIfNotNull(met, "StartDateTime", startDateTimeStr);
+      ProfileUtils.addIfNotNull(met, "EndDateTime", endDateTimeStr);
+    }
+
+    if (dataset.getTimeCoverage() != null
+        && dataset.getTimeCoverage().getResolution() != null) {
+      ProfileUtils.addIfNotNull(met, "TimeCoverageResolution", dataset
+          .getTimeCoverage().getResolution().getText());
+    }
+    // dataset unique ID
+    ProfileUtils.addIfNotNull(met, "UniqueID", dataset.getUniqueID());
+
+    // dataset ID is typically not null
+    ProfileUtils.addIfNotNull(met, "ID", dataset.getID());
+
+    // generate a UUID for each dataset, to be used as profile ID
+    ProfileUtils.addIfNotNull(met, "UUID", UUID.randomUUID().toString());
+
+    // store access services - only the OpenDAP endpoint for now
+    for (InvAccess access : dataset.getAccess()) {    	
+      String url = access.getStandardUri().toString();
+    	String type = access.getService().getServiceType().toString();
+    	String name = access.getService().getName();
+    	
+    	// add opendap access URL
+    	if (type.equalsIgnoreCase(ServiceType.OPENDAP.toString())) {
+    		// store opendap URL
+    		ProfileUtils.addIfNotNull(met,"OpendapUrl",url);
+    	  // note: special processing of opendap endpoints since URL in thredds catalog is unusable without a suffix
+    		ProfileUtils.addIfNotNull(met,"Access", this.encodeAccessTuple(url+".html", ProfileUtils.MIME_TYPE_OPENDAP_HTML, type));
+    	} 
+    }
+    // add TREDDS XML catalog URL
+    String url = dataset.getCatalogUrl(); // catalog_url.xml#dataset_id
+    ProfileUtils.addIfNotNull(met,"Access", this.encodeAccessTuple(url, ProfileUtils.MIME_TYPE_THREDDS, "Catalog/XML"));
+    ProfileUtils.addIfNotNull(met,"Access", this.encodeAccessTuple(url.replaceAll("\\.xml", ".html"), ProfileUtils.MIME_TYPE_HTML, "Catalog/HTML"));
+
+  }
+  
+	/**
+	 * Utility method that joins the parts of an xlink tuple (href, title, type) with a delimiting character.
+	 * @param href : the xlink URL, must be not null
+	 * @param title : the xlink title, may be null
+	 * @param type : the xlink type, may be null
+	 * @return
+	 */
+	private String encodeXlinkTuple(final String href, final String title, final String type) {
+	    final StringBuilder tuple = new StringBuilder();
+      tuple.append(href)
+           .append(ProfileUtils.CHAR)
+           .append(StringUtils.hasText(title) ? title : "Reference" )
+           .append(ProfileUtils.CHAR)
+           .append(StringUtils.hasText(type) ? type : "HTML" );
+      return tuple.toString();
+	}
+	
+	/**
+	 * Utility method that joins the part of A THREDDS access point (url, service type, service name) with a delimiting character
+	 * @param url : the access URL
+	 * @param type : the service type, mapped to a mime type
+	 * @param name : the service name
+	 * @return
+	 */
+	private String encodeAccessTuple(final String url, final String type, final String name) {
+    final StringBuilder tuple = new StringBuilder();
+    tuple.append(url)
+         .append(ProfileUtils.CHAR)
+         .append(StringUtils.hasText(type) ? type : "")
+         .append(ProfileUtils.CHAR)
+         .append(StringUtils.hasText(name) ? name : "");
+    return tuple.toString();
+	}
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/util/OpendapURLEvaluator.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/util/OpendapURLEvaluator.java
new file mode 100644
index 0000000..eeec45c
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/util/OpendapURLEvaluator.java
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps.util;
+
+//JDK imports
+import java.io.IOException;
+
+import org.apache.oodt.opendapps.DatasetExtractor;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+/**
+ * 
+ * Evaluates the resultant OPeNDAP URLs returned from a THREDDS catalog by the
+ * {@link DatasetExtractor}.
+ * 
+ */
+public class OpendapURLEvaluator {
+
+  public static void main(String[] args) throws IOException {
+    String datasetUrl = args[0];
+    String catalogUrl = args[1];
+
+    DatasetExtractor gen = new DatasetExtractor(getQuery(), catalogUrl,
+        datasetUrl, null);
+    System.out.println(gen.getDapUrls());
+  }
+
+  private static XMLQuery getQuery() {
+    return new XMLQuery("PFunction=findall", "cmdline", "cmdline", null, null,
+        null, null, null, XMLQuery.DEFAULT_MAX_RESULTS, true);
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/util/ProfileChecker.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/util/ProfileChecker.java
new file mode 100644
index 0000000..34d2b4d
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/util/ProfileChecker.java
@@ -0,0 +1,174 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.opendapps.util;
+
+// JDK imports
+import java.util.List;
+
+// OODT imports
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileElement;
+
+// Spring imports
+import org.springframework.util.StringUtils;
+
+/**
+ * Utility class that checks an OODT Profile versus a list of required/optional elements,
+ * and provides a validation summary for quick inspection by the publisher.
+ * 
+ * @author Luca Cinquini
+ *
+ */
+public class ProfileChecker {
+	
+	// list of mandatory profile elements
+	private final static String[] mandatoryProfileElements = new String[] {  };
+	
+	// list of optional profile elements
+	private final static String[] optionalProfileElements = new String[] { "mission_name", "sensor", "institute",
+		                                                                     "variable", "cf_standard_name", "variable_long_name",
+		                                                                     "spatial_coverage",
+		                                                                     "north_degrees", "east_degrees", "south_degrees", "west_degrees",
+		                                                                     "datetime_start", "datetime_stop" };
+		
+	/**
+	 * Main method to check an OODT profile.
+	 * 
+	 * @param profile : the OODT profile that needs validation.
+	 * @param sb : buffer to write the output to.
+	 * @return : true if the profile is valid, false otherwise.
+	 */
+	public static boolean check(final Profile profile, final StringBuilder sb) {
+		
+		// profile passes by default
+		boolean ok = true;
+		sb.append("\nChecking profile="+profile.getProfileAttributes().getID());
+		
+		ok = ok && checkResourceAttribute("Identifier", profile.getResourceAttributes().getIdentifier(), true, sb);
+		
+		ok = ok && checkResourceAttribute("Title", profile.getResourceAttributes().getTitle(), true, sb);
+		
+		ok = ok && checkResourceAttribute("Description", profile.getResourceAttributes().getDescription(), false, sb);
+		
+		ok = ok && checkResourceAttribute("Location of type "+ProfileUtils.MIME_TYPE_OPENDAP_HTML, 
+				             selectResourceLocationByMimeType(profile.getResourceAttributes().getResLocations(), ProfileUtils.MIME_TYPE_OPENDAP_HTML), 
+				             true, sb);
+		
+		ok = ok && checkResourceAttribute("Location of type "+ProfileUtils.MIME_TYPE_THREDDS, 
+        selectResourceLocationByMimeType(profile.getResourceAttributes().getResLocations(), ProfileUtils.MIME_TYPE_THREDDS), 
+        true, sb);
+		
+		ok = ok && checkResourceAttribute("Location of type "+ProfileUtils.MIME_TYPE_HTML, 
+        selectResourceLocationByMimeType(profile.getResourceAttributes().getResLocations(), ProfileUtils.MIME_TYPE_HTML), 
+        true, sb);
+		
+		ok = ok && checkResourceAttribute("Location of type "+ProfileUtils.MIME_TYPE_GIS, 
+        selectResourceLocationByMimeType(profile.getResourceAttributes().getResLocations(), ProfileUtils.MIME_TYPE_GIS), 
+        true, sb);
+		
+		for (String name : mandatoryProfileElements) {
+			ok = ok && checkProfileElement(profile, name, true, sb);
+		}
+		for (String name : optionalProfileElements) {
+			ok = ok && checkProfileElement(profile, name, false, sb);
+		}
+		
+		return ok;
+	}
+	
+	/**
+	 * Method to check that a profile Resource Attribute has a valid value.
+	 * 
+	 * @param name
+	 * @param value
+	 * @param mandatory
+	 * @param sb
+	 * @return
+	 */
+	private static boolean checkResourceAttribute(String name, String value, boolean mandatory, StringBuilder sb) {
+		sb.append("\n\tResource Attribute '" + name + "' = ");
+		if (!StringUtils.hasText(value) || value.equalsIgnoreCase("null")) {
+				if (mandatory) return false; // bad value
+		} else {
+			sb.append(value);
+		}
+		return true;
+	}
+	
+	/**
+	 * Method to check that the profile contains at least one valid value for of a specific element name.
+	 * 
+	 * @param profile
+	 * @param name
+	 * @param mandatory
+	 * @param sb
+	 * @return
+	 */
+	private static boolean checkProfileElement(Profile profile, String name, boolean mandatory, StringBuilder sb) {
+		
+		sb.append("\n\tProfile Element '" + name + "' = ");
+	  // profile element is valid by default
+		boolean ok = true; 
+	
+		if (profile.getProfileElements().containsKey(name)) {
+				ProfileElement profElement = (ProfileElement)profile.getProfileElements().get(name);
+			
+  			// profile element found
+  			List<String> values = profElement.getValues();
+  			if (values.size()>0) {
+  				boolean first = true;
+  				for (String value : values) {
+  					if (!StringUtils.hasText(value) || value.equalsIgnoreCase("null")) {
+  						if (mandatory) ok = false; // invalid value for this profile element
+  					} else {
+  						if (!first) sb.append(", ");
+  						sb.append(value);
+  						first = false;
+  					}
+  				}
+  			} else {
+  				if (mandatory) ok = false; // no values found for this profile element
+  			}
+		
+		} else {
+			if (mandatory) ok = false; // no profile element found
+		}
+		
+		return ok;
+		
+	}
+	
+	/**
+	 * Method to select the resource location of a specific mime type, if found.
+	 * 
+	 * @param resLocations
+	 * @param mimeType
+	 * @return
+	 */
+	private static String selectResourceLocationByMimeType(List<String> resLocations, String mimeType) {
+		
+		for (String resLocation : resLocations) {
+			String[] parts = resLocation.split("\\|"); // regular expression of ProfileUtils.CHAR
+			if (parts[1].equals(mimeType)) return parts[0];
+		}
+		
+		// resource location not found
+		return null;
+		
+	}
+
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/util/ProfileSerializer.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/util/ProfileSerializer.java
new file mode 100644
index 0000000..55c47da
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/util/ProfileSerializer.java
@@ -0,0 +1,109 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.opendapps.util;
+
+//JDK imports
+import java.io.StringWriter;
+import java.util.List;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+//OODT imports
+import org.apache.oodt.profile.Profile;
+
+/**
+ * Utility class to serialize a list of profiles to an XML document.
+ * <p/>
+ * Based on functionality already contained in the OODT grid ProfileQueryServlet
+ * class, but separated as a stand alone utility to reduce dependencies.
+ * 
+ * @author Luca Cinquini
+ * 
+ */
+public class ProfileSerializer {
+
+  /**
+   * Function to serialize a list of {@link Profile}s to XML.
+   * 
+   * @param profiles
+   * @return
+   * @throws TransformerException
+   */
+  public static String toXML(final List<Profile> profiles)
+      throws TransformerException {
+
+    final StringWriter writer = new StringWriter();
+    writer.append("<?xml version='1.0' encoding='UTF-8'?>");
+    writer.append("<!DOCTYPE profiles PUBLIC '" + Profile.PROFILES_DTD_FPI
+        + "' '" + Profile.PROFILES_DTD_URL + "'>");
+    writer.append("<profiles>");
+
+    final Transformer transformer = createTransformer();
+    final Document doc = Profile.createProfileDocument();
+    for (final Profile profile : profiles) {
+
+      Node profileNode = profile.toXML(doc);
+      DOMSource source = new DOMSource(profileNode);
+      StreamResult result = new StreamResult(writer);
+      transformer.transform(source, result);
+
+    }
+
+    writer.append("</profiles>");
+
+    return writer.toString();
+
+  }
+
+  /**
+   * Create a transformer, properly configured for XML text serialization.
+   * 
+   * @return a <code>Transformer</code> value.
+   * @throws TransformerException
+   *           if an error occurs.
+   */
+  private static Transformer createTransformer() throws TransformerException {
+
+    Transformer transformer;
+    synchronized (TRANSFORMER_FACTORY) {
+      transformer = TRANSFORMER_FACTORY.newTransformer();
+    }
+
+    transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+    transformer.setOutputProperty(OutputKeys.VERSION, "1.0");
+    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+    transformer.setOutputProperty(OutputKeys.STANDALONE, "no");
+    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+    transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml");
+    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount",
+        "4");
+
+    return transformer;
+  }
+
+  /** Sole transformer factory this class will ever need. */
+  private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory
+      .newInstance();
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/util/ProfileUtils.java b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/util/ProfileUtils.java
new file mode 100644
index 0000000..07950ed
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/java/org/apache/oodt/opendapps/util/ProfileUtils.java
@@ -0,0 +1,427 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.opendapps.util;
+
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.ENUM_ELEMENT_TYPE;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.PROF_ATTR_SPEC_TYPE;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.PROF_ELEM_SPEC_TYPE;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.RANGED_ELEMENT_TYPE;
+import static org.apache.oodt.opendapps.config.OpendapConfigMetKeys.RES_ATTR_SPEC_TYPE;
+
+//JDK imports
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OPENDAP imports
+import opendap.dap.BaseType;
+import opendap.dap.DArray;
+import opendap.dap.DConnect;
+import opendap.dap.DDS;
+import opendap.dap.DGrid;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.opendapps.OpendapProfileElementExtractor;
+import org.apache.oodt.opendapps.config.ConstantSpec;
+import org.apache.oodt.opendapps.config.DatasetMetElem;
+import org.apache.oodt.opendapps.config.OpendapConfig;
+import org.apache.oodt.opendapps.config.RewriteSpec;
+import org.apache.oodt.profile.EnumeratedProfileElement;
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileAttributes;
+import org.apache.oodt.profile.ProfileElement;
+import org.apache.oodt.profile.ResourceAttributes;
+import org.springframework.util.StringUtils;
+
+/**
+ * 
+ * Static methods for unraveling and generating {@link ProfileElement}s,
+ * {@link ProfileAttributes} and {@link ResourceAttributes} for a
+ * {@link Profile}, derived from a set of OPeNDAP dataset information and an
+ * {@link OpendapConfig}.
+ * 
+ * 
+ */
+public class ProfileUtils {
+	
+	static {
+		// Note: must override the CAS PathUtils delimiter otherwise every sentence is split at the ',' as different metadata fields.
+		// The delimiter must be a character that is not commonly used in the metadata values, 
+		// and that it does not a special regular expression character.
+		// Cannot use '#' as it is used in URL anchors, such as THREDDS urls.
+		// Cannot user '?', '&' as they are used in URL query strings.
+		// Cannot use '|' as it is used as multi-part separators in encoding of metadata fields.
+		PathUtils.DELIMITER = "~";
+	}
+	
+  // character separating multiple parts of the same metadata field,
+  // when more than one piece of information needs to be stored in one field
+  public final static String CHAR = "|";
+  
+  // HTTP mime types
+  public final static String MIME_TYPE_THREDDS = "application/xml+thredds";   
+  public final static String MIME_TYPE_NETCDF = "application/netcdf";
+  public final static String MIME_TYPE_GRIDFTP = "application/gridftp";
+  public final static String MIME_TYPE_FTP = "application/ftp";
+  public final static String MIME_TYPE_LAS = "application/las";   
+  public final static String MIME_TYPE_HTML = "text/html";
+  public final static String MIME_TYPE_GOOGLE_EARTH = "application/vnd.google-earth.kmz";
+  public final static String MIME_TYPE_HDF = "application/x-hdf";
+  public final static String MIME_TYPE_OPENDAP = "application/opendap";
+  public final static String MIME_TYPE_OPENDAP_DODS = "application/opendap-dods";
+  public final static String MIME_TYPE_OPENDAP_DAS = "application/opendap-das";
+  public final static String MIME_TYPE_OPENDAP_DDS = "application/opendap-dds";
+  public final static String MIME_TYPE_OPENDAP_HTML = "application/opendap-html";
+  public final static String MIME_TYPE_RSS = "application/rss+xml";
+  public final static String MIME_TYPE_GIS = "application/gis";
+
+
+  private static final Logger LOG = Logger.getLogger(ProfileUtils.class
+      .getName());
+
+  public static ResourceAttributes getResourceAttributes(OpendapConfig conf,
+      String opendapUrl, DConnect dConn, Metadata datasetMet) {
+    ResourceAttributes resAttr = new ResourceAttributes();
+    for (ConstantSpec spec : conf.getConstSpecs()) {
+      if (spec.getType().equals(RES_ATTR_SPEC_TYPE)) {
+        try {        	
+        	      	        	
+        	// first process expanded '[@...]' instructions
+        	List<String> values = multipleEnvVariablesReplacement(spec.getValue(), datasetMet);
+        	
+        	// then process standard '[...]' instructions
+        	for (String value : values) {
+          	String _value = PathUtils.replaceEnvVariables(value, datasetMet, true);          		        		
+        		if (StringUtils.hasText(_value)) {
+        			setResourceAttributes(resAttr, spec.getName(), _value);
+        		}
+        		
+        	}
+ 
+        } catch (Exception e) {
+          e.printStackTrace();
+          LOG.log(Level.WARNING, "Error setting field: [" + spec.getName()
+              + "] in resource attributes: Message: " + e.getMessage());
+        }
+      }
+    }
+
+
+    return resAttr;
+  }
+  
+  /**
+   * Utility method to process environment replacement instructions of the form '[@key]'
+   * resulting in as many output values as there are values for the environment variable 'key'.
+   * Note that currently only one such pattern '[@key']' can be processed.
+   * 
+   * @param value
+   * @param metadata
+   * @return
+   */
+  private static List<String> multipleEnvVariablesReplacement(String value, Metadata metadata) {
+  	
+  	List<String> newValues = new ArrayList<String>();
+
+  	// regexp matching found > replace values
+  	int start = value.indexOf("[@");
+  	if (start>=0) {
+  		
+  			int end = value.indexOf("]",start+2);
+  			// remove '[@',']' to obtain environment variable key
+  			String envKey = value.substring(start+2,end);
+    		List<String> envValues = metadata.getAllMetadata(envKey);
+    		if (envValues!=null) {
+      		for (String envValue : envValues) {
+      			// create new metadata value for this environment replacement
+      			String newValue = value.replaceAll("\\[@"+envKey+"\\]", envValue);
+      			newValues.add(newValue);
+      		}
+  		}
+  		
+    // regexp matching not found > return original value
+  	} else {
+  		newValues.add(value);
+  	}
+  	
+  	return newValues;
+  	
+  }
+
+  public static ProfileAttributes getProfileAttributes(OpendapConfig conf, Metadata datasetMet) {
+    ProfileAttributes profAttr = new ProfileAttributes();
+    for (ConstantSpec spec : conf.getConstSpecs()) {
+      if (spec.getType().equals(PROF_ATTR_SPEC_TYPE)) {
+        setProfileAttributesProperty(profAttr, spec.getName(), PathUtils
+            .replaceEnvVariables(spec.getValue(), datasetMet, true));
+      }
+    }
+
+    return profAttr;
+
+  }
+
+  public static Map<String, ProfileElement> getProfileElements(
+      OpendapConfig conf, DConnect dConn, Metadata datasetMet, Profile profile) throws Exception {
+  	
+    OpendapProfileElementExtractor pe = new OpendapProfileElementExtractor(conf);
+    Map<String, ProfileElement> profElements = new HashMap<String, ProfileElement>();
+
+    // extracts all variables defined in DDS
+    try {
+      	
+    		DDS dds = dConn.getDDS();
+      	      	
+      	// loop over all variables found
+      	Enumeration variables = dds.getVariables();
+      	while (variables.hasMoreElements()) {
+      		
+      		BaseType variable = (BaseType)variables.nextElement();
+      		String varName = variable.getName();
+      		if (variable instanceof DArray) {
+      			LOG.log(Level.FINE, "Extracting Darray variable: "+varName);
+      		} else if (variable instanceof DGrid) {
+      			LOG.log(Level.FINE, "Extracting Dgrid variable: "+varName);
+      		}     		
+
+      		RewriteSpec spec = getProfileElementSpec(varName, conf);
+      		if (spec!=null) {
+      			// use configuration to set variable re-name and type
+      			String peName = spec.getRename() != null && !spec.getRename().equals("") ? spec.getRename() : spec.getOrigName();
+            if (spec.getElementType().equals(RANGED_ELEMENT_TYPE)) {
+              profElements.put(peName, pe.extractRangedProfileElement(peName, spec.getOrigName(), profile, dConn.getDAS()));
+            } else if (spec.getElementType().equals(ENUM_ELEMENT_TYPE)) {
+              profElements.put(peName, pe.extractEnumeratedProfileElement(peName, spec.getOrigName(), profile, dConn.getDAS()));
+            }
+      		} else {
+      			// if not explicitly configured, assume variable if of RANGED_ELEMENT_TYPE
+      			profElements.put(varName, pe.extractRangedProfileElement(varName, varName, profile, dConn.getDAS()));
+      		}
+      		
+      	}
+      	
+    } catch(Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Error extracting metadata from DDS ("+dConn.URL()+") :"  +e.getMessage());
+      // rethrow the exception so that this dataset is not harvested
+      throw e;
+    }
+
+    // add profile elements from <datasetMetadata> specification
+    if (datasetMet != null) {
+      for (DatasetMetElem datasetSpec : conf.getDatasetMetSpecs()) {
+      	// retrieve values from metadata container
+        List<String> values = datasetMet.getAllMetadata(datasetSpec.getValue());
+      	addValuesToEnumeratedProfileElement(datasetSpec.getProfileElementName(), values, profile, profElements);
+      }
+    }
+    
+    // add profile elements from <constants> specification
+    for (ConstantSpec spec : conf.getConstSpecs()) {
+      if (spec.getType().equals(PROF_ELEM_SPEC_TYPE)) {
+      	// retrieve value from XML configuration file, replace with value from metadata container if required,
+      	// split according to delimiter
+        String replaceVal = PathUtils.replaceEnvVariables(spec.getValue(), datasetMet);
+        List<String> values = Arrays.asList(replaceVal.split(PathUtils.DELIMITER));
+      	addValuesToEnumeratedProfileElement(spec.getName(), values, profile, profElements);
+      }
+    }
+
+    return profElements;
+
+  }
+  
+  /**
+   * Method to add one or more values to an EnumeratedProfileElement, creating the element if not existing already.
+   * The supplied values are added only if valid.
+   */
+  private static void addValuesToEnumeratedProfileElement(final String name, final List<String> values, Profile profile, Map<String, ProfileElement> profElements) {
+  	
+  	// try retrieve existing profile element
+  	ProfileElement epe = profElements.get(name);
+  	// or create a new one if not found
+  	if (epe==null) {
+  		 epe = new EnumeratedProfileElement(profile);
+  	   epe.setName(name);
+  	} 
+  	if (values!=null) {
+      for (String value : values) {
+      	if (StringUtils.hasText(value) && !value.equalsIgnoreCase("null")) {
+      		epe.getValues().add(value);
+      	}
+      }
+  	}
+    // only save profile elements with one or more values
+    if (epe.getValues().size()>0) profElements.put(name, epe);
+  	
+  }
+
+  private static void setProfileAttributesProperty(ProfileAttributes attr,
+      String propName, String value) {
+    if (propName.equals("profId")) {
+      attr.setID(value);
+    } else if (propName.equals("profVersion")) {
+      attr.setVersion(value);
+    } else if (propName.equals("profType")) {
+      attr.setType(value);
+    } else if (propName.equals("profStatusId")) {
+      attr.setStatusID(value);
+    } else if (propName.equals("profSecurityType")) {
+      attr.setSecurityType(value);
+    } else if (propName.equals("profParentId")) {
+      attr.setParent(value);
+    } else if (propName.equals("profRegAuthority")) {
+      attr.setRegAuthority(value);
+    } else if (propName.equals("profChildId")) {
+      attr.getChildren().addAll(Arrays.asList(value.split(PathUtils.DELIMITER)));
+    } else if (propName.equals("profRevisionNote")) {
+      attr.getRevisionNotes().addAll(Arrays.asList(value.split(PathUtils.DELIMITER)));
+    }
+
+  }
+
+  private static void setResourceAttributes(ResourceAttributes resAttr,
+      String propName, String value) {
+    if (StringUtils.hasText(value) && !value.equalsIgnoreCase("null")) {
+      if (propName.equals("Identifier")) {
+        resAttr.setIdentifier(value);
+      } else if (propName.equals("Title")) {
+        resAttr.setTitle(value);
+      } else if (propName.equals("Format")) {
+        resAttr.getFormats().addAll( parseValues(value) );
+      } else if (propName.equals("Description")) {
+        resAttr.setDescription(value);
+      } else if (propName.equals("Creator")) {
+        resAttr.getCreators().addAll( parseValues(value) );
+      } else if (propName.equals("Subject")) {
+        resAttr.getSubjects().addAll( parseValues(value) );
+      } else if (propName.equals("Publisher")) {
+        resAttr.getPublishers().addAll( parseValues(value) );
+      } else if (propName.equals("Contributor")) {
+        resAttr.getContributors().addAll( parseValues(value) );
+      } else if (propName.equals("Date")) {
+        resAttr.getDates().addAll( parseValues(value) );
+      } else if (propName.equals("Type")) {
+        resAttr.getTypes().addAll( parseValues(value) );
+      } else if (propName.equals("Source")) {
+        resAttr.getSources().addAll( parseValues(value) );
+      } else if (propName.equals("Language")) {
+        resAttr.getLanguages().addAll( parseValues(value) );
+      } else if (propName.equals("Relation")) {
+        resAttr.getRelations().addAll( parseValues(value) );
+      } else if (propName.equals("Coverage")) {
+        resAttr.getCoverages().addAll( parseValues(value) );
+      } else if (propName.equals("Rights")) {
+        resAttr.getRights().addAll( parseValues(value) );
+      } else if (propName.equals("resContext")) {
+        resAttr.getResContexts().addAll( parseValues(value) );
+      } else if (propName.equals("resAggregation")) {
+        resAttr.setResAggregation(value);
+      } else if (propName.equals("resClass")) {
+        resAttr.setResClass(value);
+      } else if (propName.equals("resLocation")) {
+        resAttr.getResLocations().addAll( parseValues(value) );
+      }
+    }
+  }
+  
+  /**
+   * Utility method to discover the rewrite specification for a named variable, if available.
+   * @param name
+   * @param conf
+   */
+  private static RewriteSpec getProfileElementSpec(String origName, OpendapConfig conf) {
+  	for (RewriteSpec spec : conf.getRewriteSpecs()) {
+  		if (spec.getOrigName().equals(origName)) {
+  			return spec;
+  		}
+  	}
+  	return null;
+  }
+  
+  /**
+   * Utility method to split a metadata field value according to the known delimiter.
+   * @param value
+   * @return
+   */
+  public static List<String> parseValues(String value) {
+  	List<String> values = new ArrayList<String>();
+  	for (String val : value.split(PathUtils.DELIMITER)) {
+  		if (StringUtils.hasText(val) && !val.equalsIgnoreCase("null")) {
+  			values.add(val);
+  		}
+  	}
+  	
+  	return values;
+  }
+  
+  /**
+   * Method to add a (name,value) pair to the metadata container if the value is not null or empty,
+   * and doesn't exist already.
+   * @param met
+   * @param field
+   * @param value
+   */
+  public static void addIfNotNull(Metadata met, String key, String value) {
+  	// do not add a null value
+  	if (StringUtils.hasText(value) && !value.equalsIgnoreCase("null")) {
+  		// do not add the same value twice for the same metadata key
+  		if (!met.containsKey(key) || !met.getAllMetadata(key).contains(value)) {
+  			met.addMetadata(key, value);
+  		}
+    }
+  }
+  
+	/**
+	 * Method to add multiple (key, value) pairs to the metadata container if not existing already.
+	 * @param met
+	 * @param field
+	 * @param value
+	 */
+	public static void addIfNotExisting(Metadata metadata, String key, Enumeration<String> values) {
+		if (StringUtils.hasText(key) && !metadata.containsKey(key)) {
+			while (values.hasMoreElements()) {
+				String value = values.nextElement();
+				if (StringUtils.hasText(value) && !value.equalsIgnoreCase("null")) {
+					metadata.addMetadata(key,value);
+				}
+			}
+		}
+	}
+  
+  // inspired from ASLv2 code at:
+  // http://www.java2s.com/Code/Java/Data-Type/ISO8601dateparsingutility.htm
+  public static String toISO8601(Date date) {
+    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+    TimeZone tz = TimeZone.getTimeZone("UTC");
+    df.setTimeZone(tz);
+    String output = df.format(date);
+    return output;
+  }
+
+}
diff --git a/0.8.1-rc1/opendapps/src/main/resources/logging.properties b/0.8.1-rc1/opendapps/src/main/resources/logging.properties
new file mode 100644
index 0000000..663006a
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/resources/logging.properties
@@ -0,0 +1,35 @@
+#  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.
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+org.apache.oodt.opendapps.level = INFO
+org.apache.oodt.opendapps.util.level = INFO
+org.apache.oodt.opendapps.config.level = INFO
+
+# Tone down the Sun log messages
+sun.net.www.level=SEVERE
\ No newline at end of file
diff --git a/0.8.1-rc1/opendapps/src/main/resources/opendap.config.xml b/0.8.1-rc1/opendapps/src/main/resources/opendap.config.xml
new file mode 100644
index 0000000..a338130
--- /dev/null
+++ b/0.8.1-rc1/opendapps/src/main/resources/opendap.config.xml
@@ -0,0 +1,192 @@
+<!-- 
+ 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.
+ 
+Description: This file defines a set of information used by an OODT Profile Server 
+to extract and deliver back OODT Profile metadata from an underlying OPeNDAP/THREDDS 
+accessible data source. This configuration file builds on prior work that was only 
+configurable in Java code, but is now configurable via this file.
+
+-->
+<oodt:opendap xmlns:oodt="http://oodt.apache.org/1.0" id="urn:oodt:opendap:psid" name="OPeNDAP Handler">
+
+    <!-- 
+       A set of THREDDS catalog roots to derive datasets from. Must specify at least one root.
+       
+       datasetURL - the original URL to the THREDDS dataset.
+       catalogURL - the original URL to the THREDDS catalog.xml file used to obtain dataset metadata 
+                    and information from.
+       filter (optional) - defines an optional dataset filter for inclusion/exclusion.
+    
+     -->
+    <root datasetURL="http://thredds1.pfeg.noaa.gov/thredds/dodsC/" catalogURL="http://thredds1.pfeg.noaa.gov/thredds/Satellite/aggregsatMW/chla/catalog.xml" filter=".*" />
+    <root datasetURL="http://thredds1.pfeg.noaa.gov/thredds/dodsC/" catalogURL="http://thredds1.pfeg.noaa.gov/thredds/Satellite/aggregsatMH/chla/catalog.xml" filter=".*" />
+    <root datasetURL="http://thredds1.pfeg.noaa.gov/thredds/dodsC/" catalogURL="http://thredds1.pfeg.noaa.gov/thredds/Satellite/aggregsatSW/chla/catalog.xml" filter=".*" />
+    <root datasetURL="http://thredds1.pfeg.noaa.gov/thredds/dodsC/" catalogURL="http://thredds1.pfeg.noaa.gov/thredds/Satellite/aggregsatSA/chla/catalog.xml" filter=".*" />
+    <root datasetURL="http://thredds1.pfeg.noaa.gov/thredds/dodsC/" catalogURL="http://thredds1.pfeg.noaa.gov/thredds/Satellite/aggregsatAG/tanm/catalog.xml" filter=".*" />
+    <root datasetURL="http://thredds1.pfeg.noaa.gov/thredds/dodsC/" catalogURL="http://thredds1.pfeg.noaa.gov/thredds/Satellite/aggregsatAA/ssta/catalog.xml" filter=".*" />
+    <root datasetURL="http://thredds1.pfeg.noaa.gov/thredds/dodsC/" catalogURL="http://thredds1.pfeg.noaa.gov/thredds/Satellite/aggregsatMH/sstd/catalog.xml" filter=".*" />
+	
+	
+	<!-- 
+	   A set of specifications for how to rewrite the names of underlying OPeNDAP/THREDDS dataset variables 
+	   into profile elements within the generated OODT profile. These information are used only to transform 
+	   OPeNDAP variables into OODT profile elements. If an OPeNDAP element part of a dataset is not specified 
+	   in this rewrite block, the variable not be extracted.
+	   
+	   name: The original name of the OPeNDAP variable.
+	   rename (optional): What to rename the variable to in the OODT Profile Elements section.
+	   type: Either EnumeratedProfileElement or RangedProfileElement. EnumeratedProfileElement indicates this is 
+	   a variable with a select vocabulary of choices, with multiple values to specify those choices. RangedProfileElement 
+	   indicates this is an OPeNDAP variable with a specified min/max value.
+	
+	 -->
+	<rewrite>
+		<var name="altitude" type="RangedProfileElement"/>
+		<var name="lat" rename="latitude" type="RangedProfileElement"/>
+		<var name="lon" rename="longitude" type="RangedProfileElement"/>
+		<var name="time" type="RangedProfileElement"/>		
+	</rewrite>
+	
+	
+	<!-- 
+	  THREDDS Dataset metadata that you want to flow into the Profile 
+	  Elements portion of the profile. Each specified dataset metadata 
+	  will be turned into an EnumeratedProfileElement with 1 or more values.
+	  
+	  name: The name of the profile element.
+	  value: The dataset metadata element to extract the metadata from. The 
+	  extracted metadata is shoved into the generated EnumeratedProfileElement's
+	  value set.	
+	 -->
+	<datasetMetadata>
+	
+	   <!-- variable names -->
+	   <elem name="variable" value="Variables"/>
+	   <elem name="cf_standard_name" value="CF Standard Names"/>
+	   <elem name="variable_long_name" value="Variable Long Names"/>
+	   
+	   	<!-- geospatial coverage -->
+		<elem name="south_deegrees" value="GeospatialCoverageLatSouth"/>
+		<elem name="north_deegrees" value="GeospatialCoverageLatNorth"/>
+		<elem name="west_deegrees" value="GeospatialCoverageLonWest"/>
+		<elem name="east_deegrees" value="GeospatialCoverageLonEast"/>
+		<elem name="spatial_coverage" value="GeospatialCoverage"/>
+		<elem name="latitude_resolution" value="GeospatialCoverageLatitudeResolution"/>
+	    <elem name="longitude_resolution" value="GeospatialCoverageLongitudeResolution"/>
+	
+		<!-- temporal coverage -->
+		<elem name="datetime_start" value="StartDateTime"/>
+	   	<elem name="datetime_stop" value="EndDateTime"/>
+	    <elem name="temporal_resolution" value="TimeCoverageResolution"/>
+
+	</datasetMetadata>
+	
+	<!-- 
+	    A set of constant metadata to plumb through into the profile, either in the 
+	    profileAttributes section or the resourceAttributes section. The type parameter
+	    indicates the section name, and the rest of the attributes are fairly evident from there.
+	    Note: the value tag can use CAS/OODT based environment variable replacement, by specifying 
+	    values within the '[' and ']' delimiters, e.g., [PROFILE_REG_AUTHORITY].
+	    
+	    type: either profAttr, resAttr, or profElem to indicate what section in the profile the information 
+	    should be part of. If profElem is selected, then an EnumeratedProfileElement with the provided 
+	    values will be created and added to the profile.
+	    name: the name of the profileAttribute or resourceAttribute field.
+	    value: the value to be set.
+	    
+	    
+	    profAttr can be any of:
+	      profId
+	      profVersion
+	      profType
+	      profStatusId
+	      profSecurityType
+	      profParentId
+	      profRegAuthority
+	      profChildId
+	      profRevisionNote
+
+        resAttr can be any of:	
+          Identifier
+          Title
+          Description
+          Creator
+          Subject
+          Publisher
+          Contributor
+          Date
+          Type
+          Source
+          Language
+          Relation
+          Coverage
+          Rights
+          resContext
+          resAggregation
+          resClass
+          resLocation              
+	 -->
+	<constants>
+	
+	    <!-- profile attributes -->
+	    <const type="profAttr" name="profType" value="CMDS Ocean Dataset Profile"/>
+	    <const type="profAttr" name="profStatusId" value="active"/>
+	    <const type="profAttr" name="profRegAuthority" value="NASA Coastal Marine Data Discovery Service (CMDS)" />
+	    <const type="profAttr" name="profId" value="[UUID]"/>
+	    <const type="profAttr" name="profVersion" value="1.0"/>
+	    	    
+	    <!-- resource attributes -->
+	    <const type="resAttr" name="Identifier" value="[ID]|[Host]" />
+        <const type="resAttr" name="Title" value="[FullName]" />
+        <const type="resAttr" name="Description" value="[Summary]" />
+        <const type="resAttr" name="resLocation" value="[Access]"/>
+        <const type="resAttr" name="Rights" value="[Rights]" />       
+        <const type="resAttr" name="Relation" value="[Xlink]"/>
+		<const type="resAttr" name="Publisher" value="[Publisher]" />
+		<const type="resAttr" name="Creator" value="[Creator]" />
+		<const type="resAttr" name="Type" value="[DataType]"/>
+		<const type="resAttr" name="Format" value="[DataFormatType]"/>
+		<!-- dynamic keywords harvested from data -->
+		<const type="resAttr" name="Subject" value="[Keywords]" />
+		<!-- static keywords to supplement keywords harvested from data -->
+		<const type="resAttr" name="Subject" value="Coastal Marine Data" />
+		<const type="resAttr" name="Subject" value="Oceans" />
+		<const type="resAttr" name="Subject" value="Climate Change" />
+		<!-- OODT resource parameters -->
+		<const type="resAttr" name="resClass" value="data.dataSet" />
+		<const type="resAttr" name="resContext" value="Oceanography"/>
+		<const type="resAttr" name="resAggregation" value="dataSet"/>
+		
+		<!-- profile elements from DAS/NC_GLOBAL section -->
+		<const type="profElem" name="mission_name" value="[satellite]"/>
+		<const type="profElem" name="sensor" value="[sensor]"/>
+		<const type="profElem" name="source" value="[source]"/>
+		<const type="profElem" name="project" value="[project]"/>
+		<const type="profElem" name="processing_level" value="[processing_level]"/>
+		<!-- constant values -->
+		<const type="profElem" name="spatial_coverage" value="Global"/>
+		<const type="profElem" name="institute" value="NOAA CoastWatch"/>
+		
+		<!-- constants required by ESGF harvesting process -->
+		<const type="profElem" name="master_id" value="[ID]|[Host]"/>
+		<const type="profElem" name="type" value="Dataset"/>
+		<const type="profElem" name="data_node" value="[Host]"/>
+		<const type="profElem" name="index_node" value="cmds-esg.jpl.nasa.gov"/>
+		
+		
+	</constants>
+
+</oodt:opendap>
\ No newline at end of file
diff --git a/0.8.1-rc1/pcs/core/pom.xml b/0.8.1-rc1/pcs/core/pom.xml
new file mode 100644
index 0000000..9973bee
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/pom.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+  <artifactId>pcs-core</artifactId>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../../core/pom.xml</relativePath>
+  </parent>
+  <name>Process Control System Core Package</name>
+  <packaging>jar</packaging>
+  <description>The Process Control System's core system framework. PCS is an agglomeration of 
+  CAS services and components needed to build a science data system.
+  </description>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-2</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/assembly/assembly.xml</descriptor>
+          </descriptors>
+          <archive>
+            <manifest>
+              <mainClass>org.apache.oodt.pcs.tools.PCSHealthMonitor</mainClass>
+            </manifest>
+          </archive>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>    
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-commons</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>pcs-input</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-metadata</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-workflow</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>    
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-resource</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-filemgr</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-crawler</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>xmlrpc</groupId>
+      <artifactId>xmlrpc</artifactId>
+      <version>2.0.1</version>
+    </dependency>    
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/pcs/core/src/main/assembly/assembly.xml b/0.8.1-rc1/pcs/core/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..250c44d
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/assembly/assembly.xml
@@ -0,0 +1,72 @@
+<!-- 
+/*
+ * 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.
+ */
+
+$Id$
+-->

+<assembly>

+  <id>dist</id>

+  <formats>

+    <format>tar.gz</format>
+    <format>zip</format>

+  </formats>
+  <includeBaseDirectory>true</includeBaseDirectory>
+  <baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>

+  <fileSets>

+    <fileSet>

+      <directory>${basedir}</directory>

+      <outputDirectory>.</outputDirectory>

+      <includes>

+        <include>LICENSE.txt</include>

+        <include>CHANGES.txt</include>

+      </includes>

+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/bin</directory>
+      <outputDirectory>scripts</outputDirectory>
+      <includes/>
+      <fileMode>755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>logs</outputDirectory>
+      <includes>
+        <include>REMOVE.log</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>aux/pcs</outputDirectory>
+      <includes>
+        <include>pcs-crawlers.xml</include>
+        <include>pcs-workflow-statuses.xml</include>
+        <include>pcs-ll-conf.xml</include>
+        <include>pcs.logging.properties</include>
+      </includes>
+    </fileSet>

+  </fileSets>

+  <dependencySets>

+    <dependencySet>

+      <outputDirectory>lib</outputDirectory>

+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>

+      <unpackOptions/>

+    </dependencySet>

+  </dependencySets>

+</assembly>

diff --git a/0.8.1-rc1/pcs/core/src/main/bin/pcs_ll b/0.8.1-rc1/pcs/core/src/main/bin/pcs_ll
new file mode 100755
index 0000000..1108667
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/bin/pcs_ll
@@ -0,0 +1,47 @@
+#!/bin/tcsh
+# 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.
+# 
+#
+# Tool:  Long lister
+# Purpose:  Provide metadata information for all files in a directory.  
+# Interface:  Command-line.  If no arguments provided, assume the current 
+# directory.  Arguments can be a directory or a filename specification 
+# with wildcards.
+# Output:  Text to standard out.  One line per file.  Fields of line 
+# (tab-separated):
+#    Filename
+#    Test Tag(s)
+#    Test Counter(s)
+#    Subtest tag(s)
+#    DataStartTime
+#    DataEndTime
+#  
+# Note this behavior can be overriden by specifications in the pcs-ll-conf.xml 
+# file.
+#
+# Sample usage: ./pcs_ll
+
+
+set ORIG_DIR = `pwd`
+set DIR = `dirname $0`
+cd $DIR
+set DIR_PATH = `pwd`
+cd $ORIG_DIR
+
+java -Djava.util.logging.config.file=$DIR_PATH/../aux/pcs/pcs.logging.properties \
+    -Djava.ext.dirs=$DIR_PATH/../lib:$DIR_PATH/../filemgr/lib:$DIR_PATH/../workflow/lib \
+	org.apache.oodt.pcs.tools.PCSLongLister \
+	$FILEMGR_URL $DIR_PATH/../aux/pcs/pcs-ll-conf.xml $argv[2-$#argv]
diff --git a/0.8.1-rc1/pcs/core/src/main/bin/pcs_stat b/0.8.1-rc1/pcs/core/src/main/bin/pcs_stat
new file mode 100755
index 0000000..fe5cde1
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/bin/pcs_stat
@@ -0,0 +1,78 @@
+#!/bin/tcsh
+# 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.
+# 
+#
+# A tool to provide a report of the health of the PCS.
+# Example report:
+#
+# --------------------------------------
+# PCS Health Monitor Report
+# Generated on: 2007-07-12T10:56:23.000Z
+# 
+# Service Status:
+# 
+# File Manager:            [http://vostok:9000]: UP
+# Workflow Manager:  [http://vostok:9001]: DOWN
+# Resource Manager: [http://vostok:9002]: UP
+# > batch stub:   [http://compute-0-9:2001]: UP
+# > batch stub: [http://compute-0-10:2001]: UP
+#
+# Crawlers:
+# CPTOverview: [http://flatiron:9030]:         UP
+# CPTHeliostat:  [http://flatiron:9031]:         DOWN
+#  
+# PCS Health:
+# 
+# Files:
+# --------
+# last product ingested: oco_L1aRad01wdk_90233_070604010005.hdf at 2007-06-04T10:00:00.000Z
+#
+# Jobs:
+# --------
+# 10 tasks QUEUED
+# 9  tasks CRAWLING
+# 1  tasks PGE EXEC
+# 
+# Ingest:
+# --------
+# CPTOverview:
+# 
+# number of crawls: 10
+# average crawl time (ms): 50
+# 
+# CPTHeliostat:
+# 
+# number of crawls: 56
+# average crawl time (ms): 10
+# --------------------------------------
+# 
+# Sample usage: ./pcs_stat
+
+set ORIG_DIR = `pwd`
+set DIR = `dirname $0`
+cd $DIR
+set DIR_PATH = `pwd`
+cd $ORIG_DIR
+
+java -Djava.util.logging.config.file=$DIR_PATH/../aux/pcs/pcs.logging.properties \
+    -Djava.ext.dirs=$DIR_PATH/../lib:$DIR_PATH/../filemgr/lib:$DIR_PATH/../workflow/lib:../resmgr/lib \
+    -Dorg.apache.oodt.cas.filemgr.properties=$DIR_PATH/../filemgr/etc/filemgr.properties \
+	org.apache.oodt.pcs.tools.PCSHealthMonitor \
+	$FILEMGR_URL \
+	$WORKFLOW_URL \
+	$RESMGR_URL \
+	$DIR_PATH/../aux/pcs/pcs-crawlers.xml \
+	$DIR_PATH/../aux/pcs/pcs-workflow-statuses.xml
diff --git a/0.8.1-rc1/pcs/core/src/main/bin/pcs_trace b/0.8.1-rc1/pcs/core/src/main/bin/pcs_trace
new file mode 100755
index 0000000..9f0eb01
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/bin/pcs_trace
@@ -0,0 +1,40 @@
+#!/bin/tcsh
+# 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.
+# 
+#
+# PCS Trace utility to discover product information including lineage
+# upstream and downstream, metadata, pipeline information and the like
+#
+# Sample usage: ./pcs_trace oco_L033Sun01Sun_91601_070922054839.pkt
+
+
+set DIR = `dirname $0`
+cd $DIR
+set DIR_PATH = `pwd`
+
+if ( $#argv != 1 ) then
+	echo "Usage: $0 <product>"
+	exit 1
+else
+	java -Djava.ext.dirs=$DIR_PATH/../lib:$DIR_PATH/../filemgr/lib:$DIR_PATH/../workflow/lib \
+    -Djava.util.logging.config.file=$DIR_PATH/../aux/pcs/pcs.logging.properties \
+    -Dorg.apache.oodt.cas.filemgr.properties=$DIR_PATH/../filemgr/etc/filemgr.properties \
+	org.apache.oodt.pcs.tools.PCSTrace \
+	--fm $FILEMGR_URL \
+	--wm $WORKFLOW_URL \
+	--product $1 \
+	--enableNonCat
+endif
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlInfo.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlInfo.java
new file mode 100644
index 0000000..c4be09d
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlInfo.java
@@ -0,0 +1,84 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.health;
+
+/**
+ * Information about a crawler: its <code>crawlerName</code> and
+ * <code>crawlerPort</code>.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class CrawlInfo {
+
+  private String crawlerName;
+
+  private String crawlerPort;
+
+  /**
+   * Default Constructor.
+   * 
+   */
+  public CrawlInfo() {
+
+  }
+
+  /**
+   * Constructs a new CrawlInfo with the specified parameters.
+   * 
+   * @param name
+   *          The name of the Crawler.
+   * @param port
+   *          The port that the Crawler was running on.
+   */
+  public CrawlInfo(String name, String port) {
+    this.crawlerName = name;
+    this.crawlerPort = port;
+  }
+
+  /**
+   * @return the crawlerName
+   */
+  public String getCrawlerName() {
+    return crawlerName;
+  }
+
+  /**
+   * @param crawlerName
+   *          the crawlerName to set
+   */
+  public void setCrawlerName(String crawlerName) {
+    this.crawlerName = crawlerName;
+  }
+
+  /**
+   * @return the crawlerPort
+   */
+  public String getCrawlerPort() {
+    return crawlerPort;
+  }
+
+  /**
+   * @param crawlerPort
+   *          the crawlerPort to set
+   */
+  public void setCrawlerPort(String crawlerPort) {
+    this.crawlerPort = crawlerPort;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlPropertiesFile.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlPropertiesFile.java
new file mode 100644
index 0000000..3b6bfa4
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlPropertiesFile.java
@@ -0,0 +1,94 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.health;
+
+//OODT imports
+import org.apache.oodt.pcs.input.PGEConfigurationFile;
+import org.apache.oodt.pcs.input.PGEGroup;
+import org.apache.oodt.pcs.input.PGEConfigFileReader;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//JDK imports
+import java.io.FileInputStream;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+/**
+ * 
+ * Properties used by the {@link PCSHealthMonitor} tool to determine
+ * {@link ProductCrawler} status.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class CrawlPropertiesFile implements CrawlerPropertiesMetKeys {
+
+  private PGEConfigurationFile file;
+
+  /**
+   * Constructs a new CrawlPropertiesFile.
+   * 
+   * @param filePath
+   *          The path to the CrawlPropertiesFile to load.
+   * @throws InstantiationException
+   *           If there is some error reading the file.
+   */
+  public CrawlPropertiesFile(String filePath) throws InstantiationException {
+    try {
+      this.file = new PGEConfigFileReader().read(new FileInputStream(filePath));
+    } catch (Exception e) {
+      throw new InstantiationException(e.getMessage());
+    }
+  }
+
+  /**
+   * 
+   * @return A {@link List} of {@link CrawlInfo} objects describing a Crawler.
+   */
+  public List getCrawlers() {
+    PGEGroup crawlInfo = (PGEGroup) this.file.getPgeSpecificGroups().get(
+        CRAWLER_INFO_GROUP);
+
+    Map scalars = crawlInfo.getScalars();
+    List crawlers = new Vector(scalars.keySet().size());
+    for (Iterator i = scalars.keySet().iterator(); i.hasNext();) {
+      String crawlerName = (String) i.next();
+      String crawlerPort = crawlInfo.getScalar(crawlerName).getValue();
+      CrawlInfo info = new CrawlInfo(crawlerName, crawlerPort);
+      crawlers.add(info);
+    }
+
+    return crawlers;
+  }
+
+  /**
+   * 
+   * @return The String hostname that the Crawlers run on. This is used by the
+   *         {@link PCSHealthMonitor} tool to communicate with the Crawlers and
+   *         to check their status.
+   */
+  public String getCrawlHost() {
+    String crawlHost = ((PGEGroup) this.file.getPgeSpecificGroups().get(
+        CRAWLER_PROPERTIES_GROUP)).getScalar(CRAWLER_HOST_NAME).getValue();
+    crawlHost = PathUtils.replaceEnvVariables(crawlHost);
+    return crawlHost;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlerHealth.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlerHealth.java
new file mode 100644
index 0000000..d782e5f
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlerHealth.java
@@ -0,0 +1,110 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.health;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.daemon.CrawlDaemon; //for javadoc
+
+/**
+ * 
+ * Health of a PCS Crawler in terms of the number of crawls performed, and
+ * average crawl time provided by a {@link CrawlDaemon}
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class CrawlerHealth {
+
+  private String crawlerName;
+
+  private int numCrawls;
+
+  private double avgCrawlTime;
+
+  /**
+   * Default Constructor.
+   * 
+   */
+  public CrawlerHealth() {
+
+  }
+
+  /**
+   * Constructs a new CrawlerHealth with the given parameters.
+   * 
+   * @param crawlerName
+   *          Name of the Crawler.
+   * @param numCrawls
+   *          The number of crawls performed.
+   * @param avgCrawlTime
+   *          The average time (in seconds) that a Crawler spends during each
+   *          crawl.
+   */
+  public CrawlerHealth(String crawlerName, int numCrawls, double avgCrawlTime) {
+    this.crawlerName = crawlerName;
+    this.numCrawls = numCrawls;
+    this.avgCrawlTime = avgCrawlTime;
+  }
+
+  /**
+   * @return the avgCrawlTime
+   */
+  public double getAvgCrawlTime() {
+    return avgCrawlTime;
+  }
+
+  /**
+   * @param avgCrawlTime
+   *          the avgCrawlTime to set
+   */
+  public void setAvgCrawlTime(double avgCrawlTime) {
+    this.avgCrawlTime = avgCrawlTime;
+  }
+
+  /**
+   * @return the crawlerName
+   */
+  public String getCrawlerName() {
+    return crawlerName;
+  }
+
+  /**
+   * @param crawlerName
+   *          the crawlerName to set
+   */
+  public void setCrawlerName(String crawlerName) {
+    this.crawlerName = crawlerName;
+  }
+
+  /**
+   * @return the numCrawls
+   */
+  public int getNumCrawls() {
+    return numCrawls;
+  }
+
+  /**
+   * @param numCrawls
+   *          the numCrawls to set
+   */
+  public void setNumCrawls(int numCrawls) {
+    this.numCrawls = numCrawls;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlerPropertiesMetKeys.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlerPropertiesMetKeys.java
new file mode 100644
index 0000000..411dd8d
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlerPropertiesMetKeys.java
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.health;
+
+/**
+ * 
+ * Met keys read from the {@link CrawlPropertiesFile}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public interface CrawlerPropertiesMetKeys {
+
+  public static final String CRAWLER_INFO_GROUP = "CrawlerInfo";
+
+  public static final String CRAWLER_PROPERTIES_GROUP = "CrawlProperties";
+
+  public static final String CRAWLER_HOST_NAME = "Hostname";
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlerStatus.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlerStatus.java
new file mode 100644
index 0000000..53604df
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/CrawlerStatus.java
@@ -0,0 +1,105 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.health;
+
+/**
+ * Provides status about a Crawler to the {@link PCSHealthMonitor}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class CrawlerStatus {
+
+    private CrawlInfo info;
+
+    private String status;
+
+    private String crawlHost;
+
+    /**
+     * Default Constructor.
+     * 
+     */
+    public CrawlerStatus() {
+
+    }
+
+    /**
+     * Constructs a new CrawlerStatus with the given parameters.
+     * 
+     * @param info
+     *            The {@link CrawlerInfo} describing this Crawler.
+     * @param status
+     *            One of {@link PCSHealthMonitorMetKeys#STATUS_UP} , or
+     *            {@link PCSHealthMonitorMetKeys#STATUS_DOWN}.
+     * 
+     * @param crawlHost
+     *            The host that the Crawler is running on.
+     */
+    public CrawlerStatus(CrawlInfo info, String status, String crawlHost) {
+        this.info = info;
+        this.status = status;
+        this.crawlHost = crawlHost;
+    }
+
+    /**
+     * @return the info
+     */
+    public CrawlInfo getInfo() {
+        return info;
+    }
+
+    /**
+     * @param info
+     *            the info to set
+     */
+    public void setInfo(CrawlInfo info) {
+        this.info = info;
+    }
+
+    /**
+     * @return the status
+     */
+    public String getStatus() {
+        return status;
+    }
+
+    /**
+     * @param status
+     *            the status to set
+     */
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    /**
+     * @return the crawlHost
+     */
+    public String getCrawlHost() {
+        return crawlHost;
+    }
+
+    /**
+     * @param crawlHost
+     *            the crawlHost to set
+     */
+    public void setCrawlHost(String crawlHost) {
+        this.crawlHost = crawlHost;
+    }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/JobHealthStatus.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/JobHealthStatus.java
new file mode 100644
index 0000000..0bd3677
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/JobHealthStatus.java
@@ -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.
+ */
+
+package org.apache.oodt.pcs.health;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance; //for javadoc
+import org.apache.oodt.cas.workflow.structs.WorkflowStatus; //for javadoc
+
+/**
+ * 
+ * A container representing Job health status in the PCS
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class JobHealthStatus {
+
+  private String status;
+
+  private int numPipelines;
+
+  public JobHealthStatus() {
+
+  }
+
+  /**
+   * Constructs a JobHealthStatus with the given parameters.
+   * 
+   * @param status
+   *          The Job status, one of {@link WorkflowStatus#STARTED}, or any of
+   *          the other WorkflowStatus keys.
+   * 
+   * @param numPipelines
+   *          The number of {@link WorkflowInstance}s with the given
+   *          {@link WorkflowStatus}.
+   */
+  public JobHealthStatus(String status, int numPipelines) {
+    this.status = status;
+    this.numPipelines = numPipelines;
+  }
+
+  /**
+   * @return the numPipelines
+   */
+  public int getNumPipelines() {
+    return numPipelines;
+  }
+
+  /**
+   * @param numPipelines
+   *          the numPipelines to set
+   */
+  public void setNumPipelines(int numPipelines) {
+    this.numPipelines = numPipelines;
+  }
+
+  /**
+   * @return the status
+   */
+  public String getStatus() {
+    return status;
+  }
+
+  /**
+   * @param status
+   *          the status to set
+   */
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/PCSDaemonStatus.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/PCSDaemonStatus.java
new file mode 100644
index 0000000..777d48e
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/PCSDaemonStatus.java
@@ -0,0 +1,107 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.pcs.health;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A simple data structure to capture the status of a PCS daemon (either the
+ * File Manager, the Workflow Manager, or the Resource Manager)
+ * </p>.
+ */
+public class PCSDaemonStatus {
+
+    private String daemonName;
+
+    private String urlStr;
+
+    private String status;
+
+    /**
+     * Default Constructor.
+     * 
+     */
+    public PCSDaemonStatus() {
+    }
+
+    /**
+     * Constructs a new PCSDaemonStatus with the default parameters.
+     * 
+     * @param daemonName
+     *            The name of the PCS Daemon.
+     * @param urlStr
+     *            A Stirng representation of a {@link URL} that this daemon runs
+     *            on.
+     * @param status
+     *            One of {@link PCSHealthMonitorMetKeys#STATUS_UP} , or
+     *            {@link PCSHealthMonitorMetKeys#STATUS_DOWN}.
+     */
+    public PCSDaemonStatus(String daemonName, String urlStr, String status) {
+        super();
+        this.daemonName = daemonName;
+        this.urlStr = urlStr;
+        this.status = status;
+    }
+
+    /**
+     * @return the daemonName
+     */
+    public String getDaemonName() {
+        return daemonName;
+    }
+
+    /**
+     * @param daemonName
+     *            the daemonName to set
+     */
+    public void setDaemonName(String daemonName) {
+        this.daemonName = daemonName;
+    }
+
+    /**
+     * @return the status
+     */
+    public String getStatus() {
+        return status;
+    }
+
+    /**
+     * @param status
+     *            the status to set
+     */
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    /**
+     * @return the urlStr
+     */
+    public String getUrlStr() {
+        return urlStr;
+    }
+
+    /**
+     * @param urlStr
+     *            the urlStr to set
+     */
+    public void setUrlStr(String urlStr) {
+        this.urlStr = urlStr;
+    }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/PCSHealthMonitorMetKeys.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/PCSHealthMonitorMetKeys.java
new file mode 100644
index 0000000..c28feb5
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/PCSHealthMonitorMetKeys.java
@@ -0,0 +1,52 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.health;
+
+/**
+ * Met keys for the {@link PCSHealthMonitor} tool
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public interface PCSHealthMonitorMetKeys {
+
+  public static final String HEADER_AND_FOOTER = "--------------------------------------";
+
+  public static final String SECTION_SEPARATOR = "--------";
+
+  public static final String REPORT_BANNER = "PCS Health Monitor Report";
+
+  public static final String FILE_MANAGER_DAEMON_NAME = "File Manager";
+
+  public static final String WORKFLOW_MANAGER_DAEMON_NAME = "Workflow Manager";
+
+  public static final String RESOURCE_MANAGER_DAEMON_NAME = "Resource Manager";
+
+  public static final String BATCH_STUB_DAEMON_NAME = "batch stub";
+
+  public static final String STATUS_UP = "UP";
+
+  public static final String STATUS_DOWN = "DOWN";
+
+  public static final int TOP_N_PRODUCTS = 20;
+
+  public static final int CRAWLER_DOWN_INT = -1;
+
+  public static final double CRAWLER_DOWN_DOUBLE = -1.0;
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/PCSHealthMonitorReport.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/PCSHealthMonitorReport.java
new file mode 100644
index 0000000..bcf58d8
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/PCSHealthMonitorReport.java
@@ -0,0 +1,252 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.health;
+
+//OODT imports
+import org.apache.oodt.commons.date.DateUtils;
+import org.apache.oodt.pcs.tools.PCSHealthMonitor;
+import org.apache.oodt.cas.filemgr.structs.Product; //for javadoc
+import org.apache.oodt.cas.resource.system.extern.XmlRpcBatchStub; //for javadoc
+
+//JDK imports
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 
+ * The output generated from running the {@link PCSHealthMonitor#getReport()}
+ * method.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class PCSHealthMonitorReport {
+
+  private Date generationDate;
+
+  private PCSDaemonStatus fmStatus;
+
+  private PCSDaemonStatus wmStatus;
+
+  private PCSDaemonStatus rmStatus;
+
+  private List batchStubStatus;
+
+  private List crawlerStatus;
+
+  private List latestProductsIngested;
+
+  private List jobHealthStatus;
+
+  private List crawlerHealthStatus;
+
+  /**
+   * Default Constructor.
+   * 
+   */
+  public PCSHealthMonitorReport() {
+
+  }
+
+  /**
+   * Constructs a new PCSHealthMonitorReport with the given parameters.
+   * 
+   * @param generationDate
+   *          The {@link Date} that this report was generated.
+   * @param fmStatus
+   *          The {@link PCSDaemonStatus} for the File Manager.
+   * @param wmStatus
+   *          The {@link PCSDaemonStatus} for the Workflow Manager.
+   * @param rmStatus
+   *          THe {@link PCSDaemonStatus} for the Resource Manager.
+   * @param batchStubStatus
+   *          A {@lik List} of {@link PCSDaemonStatus}es for each
+   *          {@link XmlRpcBatchStub}.
+   * @param crawlerStatus
+   *          A {@link List} of {@link CrawlerStatus}es.
+   * @param latestProductsIngested
+   *          A {@link List} of the top N {@link Product}s that have been
+   *          ingested.
+   * @param jobHealthStatus
+   *          A {@link List} of {@link JobHealthStatus}es.
+   * @param crawlerHealthStatus
+   *          A {@link List} of {@link CrawlerHealth}s.
+   */
+  public PCSHealthMonitorReport(Date generationDate, PCSDaemonStatus fmStatus,
+      PCSDaemonStatus wmStatus, PCSDaemonStatus rmStatus, List batchStubStatus,
+      List crawlerStatus, List latestProductsIngested, List jobHealthStatus,
+      List crawlerHealthStatus) {
+    super();
+    this.generationDate = generationDate;
+    this.fmStatus = fmStatus;
+    this.wmStatus = wmStatus;
+    this.rmStatus = rmStatus;
+    this.batchStubStatus = batchStubStatus;
+    this.crawlerStatus = crawlerStatus;
+    this.latestProductsIngested = latestProductsIngested;
+    this.jobHealthStatus = jobHealthStatus;
+    this.crawlerHealthStatus = crawlerHealthStatus;
+  }
+
+  /**
+   * @return the batchStubStatus
+   */
+  public List getBatchStubStatus() {
+    return batchStubStatus;
+  }
+
+  /**
+   * @param batchStubStatus
+   *          the batchStubStatus to set
+   */
+  public void setBatchStubStatus(List batchStubStatus) {
+    this.batchStubStatus = batchStubStatus;
+  }
+
+  /**
+   * @return the crawlerHealthStatus
+   */
+  public List getCrawlerHealthStatus() {
+    return crawlerHealthStatus;
+  }
+
+  /**
+   * @param crawlerHealthStatus
+   *          the crawlerHealthStatus to set
+   */
+  public void setCrawlerHealthStatus(List crawlerHealthStatus) {
+    this.crawlerHealthStatus = crawlerHealthStatus;
+  }
+
+  /**
+   * @return the crawlerStatus
+   */
+  public List getCrawlerStatus() {
+    return crawlerStatus;
+  }
+
+  /**
+   * @param crawlerStatus
+   *          the crawlerStatus to set
+   */
+  public void setCrawlerStatus(List crawlerStatus) {
+    this.crawlerStatus = crawlerStatus;
+  }
+
+  /**
+   * @return the fmStatus
+   */
+  public PCSDaemonStatus getFmStatus() {
+    return fmStatus;
+  }
+
+  /**
+   * @param fmStatus
+   *          the fmStatus to set
+   */
+  public void setFmStatus(PCSDaemonStatus fmStatus) {
+    this.fmStatus = fmStatus;
+  }
+
+  /**
+   * @return the generationDate
+   */
+  public Date getGenerationDate() {
+    return generationDate;
+  }
+
+  /**
+   * @param generationDate
+   *          the generationDate to set
+   */
+  public void setGenerationDate(Date generationDate) {
+    this.generationDate = generationDate;
+  }
+
+  /**
+   * @return the jobHealthStatus
+   */
+  public List getJobHealthStatus() {
+    return jobHealthStatus;
+  }
+
+  /**
+   * @param jobHealthStatus
+   *          the jobHealthStatus to set
+   */
+  public void setJobHealthStatus(List jobHealthStatus) {
+    this.jobHealthStatus = jobHealthStatus;
+  }
+
+  /**
+   * @return the latestProductsIngested
+   */
+  public List getLatestProductsIngested() {
+    return latestProductsIngested;
+  }
+
+  /**
+   * @param latestProductsIngested
+   *          the latestProductsIngested to set
+   */
+  public void setLatestProductsIngested(List latestProductsIngested) {
+    this.latestProductsIngested = latestProductsIngested;
+  }
+
+  /**
+   * @return the rmStatus
+   */
+  public PCSDaemonStatus getRmStatus() {
+    return rmStatus;
+  }
+
+  /**
+   * @param rmStatus
+   *          the rmStatus to set
+   */
+  public void setRmStatus(PCSDaemonStatus rmStatus) {
+    this.rmStatus = rmStatus;
+  }
+
+  /**
+   * @return the wmStatus
+   */
+  public PCSDaemonStatus getWmStatus() {
+    return wmStatus;
+  }
+
+  /**
+   * @param wmStatus
+   *          the wmStatus to set
+   */
+  public void setWmStatus(PCSDaemonStatus wmStatus) {
+    this.wmStatus = wmStatus;
+  }
+
+  /**
+   * 
+   * @return This report's {@link #generationDate} in ISO 8601 String format.
+   */
+  public String getCreateDateIsoFormat() {
+    Calendar cal = Calendar.getInstance();
+    cal.setTime(this.generationDate);
+    return DateUtils.toString(cal);
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/WorkflowStatesFile.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/WorkflowStatesFile.java
new file mode 100644
index 0000000..180f3f6
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/WorkflowStatesFile.java
@@ -0,0 +1,69 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.health;
+
+//OODT imports
+import org.apache.oodt.pcs.input.PGEConfigurationFile;
+import org.apache.oodt.pcs.input.PGEGroup;
+import org.apache.oodt.pcs.input.PGEConfigFileReader;
+
+//JDK imports
+import java.io.FileInputStream;
+import java.util.List;
+
+/**
+ * 
+ * A file that manages the {@link Workflow} states that the
+ * {@link PCSHealthMonitor} tool will look up when obtaining status in the PCS.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class WorkflowStatesFile implements WorkflowStatesMetKeys {
+
+  private PGEConfigurationFile file;
+
+  /**
+   * Constructs a new WorkflowStatesFile with the specified parameters.
+   * 
+   * @param filePath
+   *          The {@link File} path to the WorkflowStatesFile.
+   * 
+   * @throws InstantiationException
+   *           If there is any error reading and parsing the WorkflowStates
+   *           file.
+   */
+  public WorkflowStatesFile(String filePath) throws InstantiationException {
+    try {
+      this.file = new PGEConfigFileReader().read(new FileInputStream(filePath));
+    } catch (Exception e) {
+      throw new InstantiationException(e.getMessage());
+    }
+  }
+
+  /**
+   * 
+   * @return The {@link List} of String Workflow States defined in the Workflow
+   *         States file.
+   */
+  public List getStates() {
+    return ((PGEGroup) this.file.getPgeSpecificGroups().get(
+        WORKFLOW_STATES_GROUP)).getVector(WORKFLOW_STATES_VECTOR).getElements();
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/WorkflowStatesMetKeys.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/WorkflowStatesMetKeys.java
new file mode 100644
index 0000000..e4c1e55
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/health/WorkflowStatesMetKeys.java
@@ -0,0 +1,33 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.health;
+
+/**
+ * 
+ * Met keys for the {@link WorkflowStatesFile}
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public interface WorkflowStatesMetKeys {
+
+  public static final String WORKFLOW_STATES_GROUP = "WorkflowStatesGroup";
+
+  public static final String WORKFLOW_STATES_VECTOR = "States";
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/listing/ListingConf.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/listing/ListingConf.java
new file mode 100644
index 0000000..01394e7
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/listing/ListingConf.java
@@ -0,0 +1,133 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.listing;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.util.Collections;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.pcs.input.PGEConfigFileException;
+import org.apache.oodt.pcs.input.PGEConfigFileReader;
+import org.apache.oodt.pcs.input.PGEConfigurationFile;
+import org.apache.oodt.pcs.tools.PCSLongLister; //for javadoc
+import static org.apache.oodt.pcs.listing.ListingConfKeys.*;
+
+/**
+ * 
+ * The configuration for the {@link PCSLongLister}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ListingConf {
+
+  private PGEConfigurationFile conf;
+
+  /**
+   * Constructs a new ListingConf with the given {@link File}.
+   * 
+   * @param file
+   *          The configuration file.
+   * @throws FileNotFoundException
+   *           If the config file cannot be found.
+   * @throws InstantiationException
+   *           If there is some error reading the config file.
+   */
+  public ListingConf(File file) throws FileNotFoundException,
+      InstantiationException {
+    try {
+      this.conf = new PGEConfigFileReader().read(new FileInputStream(file));
+    } catch (FileNotFoundException e) {
+      throw e;
+    } catch (PGEConfigFileException e) {
+      throw new InstantiationException(e.getMessage());
+    } finally {
+      if (this.conf == null)
+        throw new InstantiationException("Configuration is null!");
+    }
+  }
+
+  /**
+   * Returns the set of excluded product types.
+   * 
+   * @return The set of excluded product types.
+   */
+  public List<String> getExcludedTypes() {
+    if (this.conf.getPgeSpecificGroups().get(EXCLUDED_PRODUCT_TYPE_GROUP) == null) {
+      return Collections.EMPTY_LIST;
+    }
+
+    return (List<String>) (List<?>) this.conf.getPgeSpecificGroups().get(
+        EXCLUDED_PRODUCT_TYPE_GROUP).getVector(EXCLUDED_VECTOR).getElements();
+
+  }
+
+  /**
+   * Gets the set of Header column met key names for the long lister.
+   * 
+   * @return The set of Header column met key names for the long lister.
+   */
+  public List<String> getHeaderColKeys() {
+    if (this.conf.getPgeSpecificGroups().get(MET_FIELD_COLS_GROUP) == null) {
+      return Collections.EMPTY_LIST;
+    }
+
+    return (List<String>) (List<?>) this.conf.getPgeSpecificGroups().get(
+        MET_FIELD_COLS_GROUP).getVector(MET_FIELDS_ORDER_VECTOR).getElements();
+  }
+
+  /**
+   * Returns the display name for a particular header col key.
+   * 
+   * @param headerColKey
+   *          The header col met key to look up the display name for.
+   * @return The header col met key's display name.
+   */
+  public String getHeaderColDisplayName(String headerColKey) {
+    if (this.conf.getPgeSpecificGroups().get(MET_FIELD_COLS_GROUP) == null) {
+      return "";
+    }
+
+    return this.conf.getPgeSpecificGroups().get(MET_FIELD_COLS_GROUP)
+        .getScalar(headerColKey).getValue();
+  }
+
+  /**
+   * Tester method to determine if an output field is a collection field, and
+   * needs special handling.
+   * 
+   * @param colName
+   *          The field name to check.
+   * @return True if it's a collection field, false if not, or if the collection
+   *         fields group doesn't exist in the conf.
+   */
+  public boolean isCollectionField(String colName) {
+    if (this.conf.getPgeSpecificGroups().get(COLLECTION_FIELDS_GROUP) == null) {
+      return false;
+    }
+
+    return this.conf.getPgeSpecificGroups().get(COLLECTION_FIELDS_GROUP)
+        .getVector(COLLECTION_FIELDS_NAMES).getElements().contains(colName);
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/listing/ListingConfKeys.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/listing/ListingConfKeys.java
new file mode 100644
index 0000000..114052d
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/listing/ListingConfKeys.java
@@ -0,0 +1,42 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.listing;
+
+/**
+ * 
+ * Met keys required to read the {@link ListingConf}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface ListingConfKeys {
+
+  public static final String MET_FIELD_COLS_GROUP = "MetFieldColumns";
+  
+  public static final String MET_FIELDS_ORDER_VECTOR = "OrderedMetKeys";
+
+  public static final String COLLECTION_FIELDS_GROUP = "CollectionFields";
+
+  public static final String COLLECTION_FIELDS_NAMES = "FieldNames";
+
+  public static final String EXCLUDED_PRODUCT_TYPE_GROUP = "ExcludedProductTypeList";
+
+  public static final String EXCLUDED_VECTOR = "ProductTypes";
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/metadata/PCSConfigMetadata.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/metadata/PCSConfigMetadata.java
new file mode 100644
index 0000000..9e4f894
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/metadata/PCSConfigMetadata.java
@@ -0,0 +1,79 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.metadata;
+
+/**
+ * 
+ * A set of Met Keys for the Task Metadata required by the PCS.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public interface PCSConfigMetadata {
+
+  public static final String PGE_TASK_TYPE = "PCS_PGETaskType";
+
+  public static final String NUM_JAVA_EXT_DIRS = "PCS_NumJavaExtDirs";
+
+  // use this key like: JAVA_EXT_DIR+"1", or JAVA_EXT_DIR+"2"
+  public static final String JAVA_EXT_DIR = "PCS_JavaExtDir";
+
+  public static final String JAVA_MAIN_CLASS = "PCS_JavaMainClass";
+
+  public static final String FILE_MANAGER_URL = "PCS_FileManagerUrl";
+
+  public static final String SCF_FILE_MANAGER_URL = "SCF_FileManagerUrl";
+
+  public static final String WORKFLOW_MANAGER_URL = "PCS_WorkflowManagerUrl";
+
+  public static final String PGE_CONFIG_FILE_PROPERTY_ADDER_CLASS = "PCS_PGEConfigPropertyAdderClass";
+
+  public static final String CLIENT_TRANSFER_SERVICE_FACTORY = "PCS_ClientTransferServiceFactory";
+
+  public static final String CRAWLER_CLEANUP = "PCS_CrawlerCleanup";
+
+  public static final String CRAWLER_CRAWLDIRS = "PCS_CrawlerCrawlForDirs";
+
+  public static final String CONFIG_FILE_SCHEMA_PATH = "PCS_ConfigFileSchemaPath";
+
+  public static final String PGE_CONFIG_FILE_NAME = "PCS_PGEConfigFileName";
+
+  public static final String PGE_LOG_FILE_NAME = "PCS_PGELogFileName";
+
+  public static final String PGE_TYPE_GDS_ADAPTOR = "GDSAdaptor";
+
+  public static final String PGE_TYPE_GDS_PGE = "GDSPge";
+
+  public static final String UNKNOWN = "UNKNOWN";
+
+  public static final String WORKFLOW_MGR_URL = "WorkflowManagerUrl";
+
+  public static final String WORKFLOW_INST_ID = "WorkflowInstId";
+
+  public static final String MAX_ALLOWABLE_GAP_MINUTES = "PCS_MaxAllowableTimeGapMinutes";
+
+  /* PGE task statuses */
+  public static final String STAGING_INPUT = "STAGING INPUT";
+
+  public static final String CONF_FILE_BUILD = "BUILDING CONFIG FILE";
+
+  public static final String RUNNING_PGE = "PGE EXEC";
+
+  public static final String CRAWLING = "CRAWLING";
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/metadata/PCSMetadata.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/metadata/PCSMetadata.java
new file mode 100644
index 0000000..7f107b2
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/metadata/PCSMetadata.java
@@ -0,0 +1,78 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.metadata;
+
+/**
+ * 
+ * A Collection of Metadata field names for PCS.
+ * 
+ */
+public interface PCSMetadata {
+
+  /* Met Fields */
+  public static final String APPLICATION_SUCCESS_FLAG = "ApplicationSuccessFlag";
+
+  public static final String ON_DISK = "OnDisk";
+
+  public static final String TAPE_LOCATION = "TapeLocation";
+
+  public static final String PRODUCTION_LOCATION = "ProductionLocation";
+
+  public static final String PRODUCTION_LOCATION_CODE = "ProductionLocationCode";
+
+  public static final String DATA_VERSION = "DataVersion";
+
+  public static final String DATA_PROVIDER = "DataProvider";
+
+  public static final String COLLECTION_LABEL = "CollectionLabel";
+
+  public static final String COMMENTS = "Comments";
+
+  public static final String EXECUTABLE_PATHNAMES = "ExecutablePathnames";
+
+  public static final String EXECUTABLE_VERSIONS = "ExecutableVersions";
+
+  public static final String PROCESSING_LEVEL = "ProcessingLevel";
+
+  public static final String JOB_ID = "JobId";
+
+  public static final String TASK_ID = "TaskId";
+
+  public static final String PRODUCTION_DATE_TIME = "ProductionDateTime";
+
+  public static final String INPUT_FILES = "InputFiles";
+
+  public static final String PGE_NAME = "PGEName";
+
+  public static final String OUTPUT_FILES = "OutputFiles";
+  
+  public static final String TEST_TAG = "TestTag";
+
+  public static final String SUB_TEST_TAG = "SubTestTag";
+
+  public static final String TEST_LOCATION = "TestLocation";
+
+  public static final String TEST_COUNTER = "TestCounter";
+
+  public static final String TEST_DATE = "TestDate";
+  
+  public static final String START_DATE_TIME = "StartDateTime";
+
+  public static final String END_DATE_TIME = "EndDateTime";
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/pedigree/Pedigree.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/pedigree/Pedigree.java
new file mode 100644
index 0000000..0bae718
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/pedigree/Pedigree.java
@@ -0,0 +1,230 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.pedigree;
+
+//OODT imports
+import org.apache.oodt.pcs.metadata.PCSMetadata;
+import org.apache.oodt.pcs.metadata.PCSConfigMetadata;
+import org.apache.oodt.pcs.query.FilenameQuery;
+import org.apache.oodt.pcs.query.InputFilesQuery;
+import org.apache.oodt.pcs.query.JobIdQuery;
+import org.apache.oodt.pcs.util.FileManagerUtils;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JDK imports
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
+
+/**
+ * 
+ * A class to provide pedigre tracking for PCS {@link Product}s.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class Pedigree implements PCSMetadata, PCSConfigMetadata {
+
+  /* our file manager interface */
+  private FileManagerUtils fm;
+
+  /* should we include not cataloged products in the pedigree? */
+  private boolean listNotCataloged = false;
+
+  /* are there any product types that we should exclude from the pedigree? */
+  private List prodTypeExcludeList;
+
+  /**
+   * 
+   * Constructs a new Pedigree object that will connect to the file manager at
+   * the given {@link URL} specified by the <code>fmUrlStr</code> string
+   * parameter.
+   * 
+   * @param fmUrlStr
+   *          The String {@link URL} of the file manager to connect to.
+   * @param listNotCat
+   *          Whether or not we should include non-cataloged products in the
+   *          pedigree.
+   * @param excludeList
+   *          A {@link List} of String {@link ProductType} names that should be
+   *          excluded from the Pedigree.
+   */
+  public Pedigree(String fmUrlStr, boolean listNotCat, List excludeList) {
+    this(new FileManagerUtils(FileManagerUtils.safeGetUrlFromString(fmUrlStr)),
+        listNotCat, excludeList);
+
+  }
+
+  /**
+   * 
+   * Constructs a new Pedigree object that will connect to the file manager
+   * specified by the {@link FileManagerUtils} object passed in.
+   * 
+   * @param fm
+   *          The PCS interface to the File Manager.
+   * @param listNotCat
+   *          Whether or not we should include non-cataloged products in the
+   *          pedigree.
+   * @param excludeList
+   *          A {@link List} of String {@link ProductType} names that should be
+   *          excluded from the Pedigree.
+   */
+  public Pedigree(FileManagerUtils fm, boolean listNotCat, List excludeList) {
+    this.fm = fm;
+    this.listNotCataloged = listNotCat;
+    this.prodTypeExcludeList = excludeList;
+  }
+
+  /**
+   * Performs a full pedigree of the specified {@link Product} <code>orig</code>
+   * . If <code>upstream</code> is set to true, an upstream pedigree is
+   * performed, otherwise, a downstream pedigree is performed.
+   * 
+   * @param orig
+   *          The {@link Product} to perform a pedigree of.
+   * @param upstream
+   *          Whether or not we should do an upstream (true) or downstream
+   *          (false) pedigree.
+   * @return A {@link PedigreeTree} containing the Pedigree of a given product.
+   */
+  public PedigreeTree doPedigree(Product orig, boolean upstream) {
+    List pedProds = null;
+    PedigreeTreeNode origRoot = PedigreeTreeNode
+        .getPedigreeTreeNodeFromProduct(orig, null);
+
+    // System.out.println("Doing pedigree: upstream: ["+upstream+"]");
+    Stack roots = new Stack();
+    roots.add(origRoot);
+
+    do {
+
+      PedigreeTreeNode currRoot = (PedigreeTreeNode) roots.pop();
+      /*
+       * System.out.println("Examining root: ["+currRoot.getNodeProduct().
+       * getProductName()+"]");
+       */
+
+      if (upstream) {
+        pedProds = getUpstreamPedigreedProducts(currRoot.getNodeProduct());
+      } else {
+        pedProds = getDownstreamPedigreedProducts(currRoot.getNodeProduct());
+      }
+
+      if (pedProds != null && pedProds.size() > 0) {
+        for (Iterator i = pedProds.iterator(); i.hasNext();) {
+          Product p = (Product) i.next();
+          if (p.getProductName().equals(
+              currRoot.getNodeProduct().getProductName())) {
+            // don't allow for the same pedigreed product to be
+            // added to the list
+            continue;
+          }
+          PedigreeTreeNode prodNode = PedigreeTreeNode
+              .getPedigreeTreeNodeFromProduct(p, currRoot);
+          roots.add(prodNode);
+        }
+      } else {
+        // System.out.println("Pedigree products is null or size 0");
+      }
+
+    } while (!roots.empty());
+
+    return new PedigreeTree(origRoot);
+  }
+
+  /**
+   * Returns the most direct ancestors (a {@link List} of {@link Product}s)
+   * upstream from the given {@link Product} named <code>orig</code>.
+   * 
+   * @param orig
+   *          The {@link Product} to get direct upstream relatives of.
+   * @return A {@link List} of {@link Product}s directly upstream from the given
+   *         {@link Product}.
+   */
+  public List getUpstreamPedigreedProducts(Product orig) {
+    if (orig == null
+        || (orig != null && orig.getProductType() == null)
+        || (orig != null && orig.getProductType() != null 
+            && orig.getProductType().getName() == null)
+        || (orig != null && orig.getProductType() != null
+            && orig.getProductType().getName() != null && 
+            orig.getProductType().getName().equals(UNKNOWN))) {
+      return new Vector();
+    }
+    Metadata pMet = fm.safeGetMetadata(orig);
+    return getProducts(pMet.getAllMetadata(INPUT_FILES));
+
+  }
+
+  /**
+   * Returns the most direct ancestors (a {@link List} of {@link Product}s)
+   * downstream from the given {@link Product} named <code>orig</code>.
+   * 
+   * @param orig
+   *          The {@link Product} to get direct downstream relatives of.
+   * @return A {@link List} of {@link Product}s directly downstream from the
+   *         given {@link Product}.
+   */
+  public List getDownstreamPedigreedProducts(Product orig) {
+    return fm.queryAllTypes(new InputFilesQuery(orig.getProductName(), fm)
+        .buildQuery(), this.prodTypeExcludeList);
+  }
+
+  /**
+   * Gets all associated {@link Product}s with the provided
+   * {@link WorkflowInstance} identified by its ID (the <code>wInstId</code>
+   * string parameter).
+   * 
+   * @param wInstId
+   *          The ID of the {@link WorkflowInstance} to look up the
+   *          {@link Product}s for.
+   * @return A {@link List} of {@link Product}s associated with the provided
+   *         Workflow Instance ID.
+   */
+  public List getWorkflowInstProds(String wInstId) {
+    return fm.queryAllTypes(new JobIdQuery(wInstId, fm).buildQuery(),
+        this.prodTypeExcludeList);
+  }
+
+  private List getProducts(List prodNames) {
+    if (prodNames == null || (prodNames != null && prodNames.size() == 0)) {
+      return new Vector();
+    }
+
+    List prods = new Vector(prodNames.size());
+
+    for (Iterator i = prodNames.iterator(); i.hasNext();) {
+      String prodName = (String) i.next();
+      List prodList = fm.queryAllTypes(new FilenameQuery(prodName, fm)
+          .buildQuery(), this.prodTypeExcludeList);
+      if (prodList != null && prodList.size() > 0) {
+        prods.add((Product) prodList.get(0));
+      } else {
+        if (this.listNotCataloged) {
+          // create a new product and add it
+          prods.add(Product.getDefaultFlatProduct(prodName, UNKNOWN));
+        }
+      }
+    }
+
+    return prods;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/pedigree/PedigreeTree.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/pedigree/PedigreeTree.java
new file mode 100644
index 0000000..0498d27
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/pedigree/PedigreeTree.java
@@ -0,0 +1,107 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.pedigree;
+
+/**
+ * 
+ * A data structure representing an upstream and downstream 
+ * pedigree for a particular {@link Product}. That is: what files 
+ * went into producing this {@link Product}, and in what files 
+ * was this {@link Product} included?
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PedigreeTree {
+
+    private PedigreeTreeNode root;
+
+    public PedigreeTree(PedigreeTreeNode root) {
+        this.root = root;
+    }
+
+    public int getNumLevels() {
+        if (root != null) {
+            return traverse(root, 0) + 1;
+        } else
+            return 0;
+    }
+
+    public PedigreeTreeNode getRoot() {
+        return root;
+    }
+
+    public void setRoot(PedigreeTreeNode root) {
+        this.root = root;
+    }
+
+    /**
+     * Tree:
+     *            -------->[N3]
+     *          ---->[N2]
+     *            -------->[N5]
+     *   [N1]---
+     *          ---->[N4]
+     *    
+     * 
+     * 
+     * @param node
+     * @param level
+     * @return
+     */
+    private int traverse(PedigreeTreeNode node, int level) {
+        int maxLevel = level;
+        if (node.getNumChildren() > 0) {
+            for (int i = 0; i < node.getNumChildren(); i++) {
+                int lvl = traverse(node.getChildAt(i), level + 1);
+                if (lvl > maxLevel) {
+                    maxLevel = lvl;
+                }
+            }
+        }
+
+        return maxLevel;
+    }
+
+    public void traverseAndPrint(PedigreeTreeNode node, int level) {
+        System.out.println(getTabStr(level)
+                + node.getNodeProduct().getProductName());
+        if (node.getNumChildren() > 0) {
+            for (int i = 0; i < node.getNumChildren(); i++) {
+                traverseAndPrint(node.getChildAt(i), level + 1);
+
+            }
+        }
+    }
+
+    private String getTabStr(int num) {
+        StringBuffer tabStrBuf = new StringBuffer();
+        for (int i = 0; i < num; i++) {
+            tabStrBuf.append("\t");
+        }
+
+        return tabStrBuf.toString();
+    }
+    
+    public void printPedigreeTree() {
+        PedigreeTreeNode root = getRoot();
+        traverseAndPrint(root, 0);
+    }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/pedigree/PedigreeTreeNode.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/pedigree/PedigreeTreeNode.java
new file mode 100644
index 0000000..481671d
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/pedigree/PedigreeTreeNode.java
@@ -0,0 +1,92 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.pedigree;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * 
+ * A node in the {@link PedigreeTree}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class PedigreeTreeNode {
+
+  private Product prod;
+
+  private List children;
+
+  private PedigreeTreeNode parent;
+
+  public PedigreeTreeNode(PedigreeTreeNode parent) {
+    this(parent, null);
+  }
+
+  public PedigreeTreeNode(PedigreeTreeNode parent, Product prod) {
+    this(parent, new Vector(), prod);
+  }
+
+  public PedigreeTreeNode(PedigreeTreeNode parent, List children, Product prod) {
+    this.parent = parent;
+    if (this.parent != null) {
+      this.parent.addChild(this);
+    }
+    this.children = children;
+    this.prod = prod;
+  }
+
+  public void setParent(PedigreeTreeNode parent) {
+    this.parent = parent;
+  }
+
+  public void addChild(PedigreeTreeNode child) {
+    this.children.add(child);
+  }
+
+  public int getNumChildren() {
+    if (this.children == null)
+      return 0;
+    return this.children.size();
+  }
+
+  public PedigreeTreeNode getChildAt(int idx) {
+    return (PedigreeTreeNode) this.children.get(idx);
+  }
+
+  public Product getNodeProduct() {
+    return this.prod;
+  }
+
+  public void setNodeProduct(Product prod) {
+    this.prod = prod;
+  }
+
+  public static PedigreeTreeNode getPedigreeTreeNodeFromProduct(Product p,
+      PedigreeTreeNode parent) {
+    PedigreeTreeNode node = new PedigreeTreeNode(parent);
+    node.setNodeProduct(p);
+    return node;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/AbstractPCSQuery.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/AbstractPCSQuery.java
new file mode 100644
index 0000000..1f384ea
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/AbstractPCSQuery.java
@@ -0,0 +1,61 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.query;
+
+//OODT imports
+import org.apache.oodt.pcs.util.FileManagerUtils;
+import org.apache.oodt.cas.filemgr.structs.Element;
+
+/**
+ * Abstract functionality for PCS queries.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public abstract class AbstractPCSQuery implements PCSQuery {
+
+  /* interface to the file manager so we can look up elem defs */
+  protected FileManagerUtils fm = null;
+
+  /**
+   * Constructs a new AbstractOCOQuery using the given {@link FileManagerUtils}
+   * file manager interface.
+   * 
+   * @param fm
+   *          The interface to the File Manager.
+   */
+  protected AbstractPCSQuery(FileManagerUtils fm) {
+    this.fm = fm;
+  }
+
+  /**
+   * Wrapper method around {@link #fm.safeGetElementByName}.
+   * 
+   * @param elemName
+   *          The name of the metadata element to obtain the ID for.
+   * @return The String ID of the given <code>elemName</code>.
+   */
+  protected String getElemId(String elemName) {
+    Element elem = fm.safeGetElementByName(elemName);
+    if (elem == null)
+      return null;
+
+    return elem.getElementId();
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/FilenameQuery.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/FilenameQuery.java
new file mode 100644
index 0000000..723b220
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/FilenameQuery.java
@@ -0,0 +1,69 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.query;
+
+//OODT imports
+import org.apache.oodt.pcs.util.FileManagerUtils;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+
+/**
+ * 
+ * A query to the File Manager using the <code>Filename</code> product met field.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class FilenameQuery extends AbstractPCSQuery {
+
+  /* the product name that we're querying for */
+  private String fileName = null;
+
+  public FilenameQuery(String name, FileManagerUtils fm) {
+    super(fm);
+    this.fileName = name;
+  }
+
+  /**
+   * @return the fileName
+   */
+  public String getFileName() {
+    return fileName;
+  }
+
+  /**
+   * @param fileName
+   *          the fileName to set
+   */
+  public void setFileName(String fileName) {
+    this.fileName = fileName;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.pcs.query.PCSQuery#buildQuery()
+   */
+  public Query buildQuery() {
+    Query query = new Query();
+    TermQueryCriteria crit = new TermQueryCriteria(FILENAME, this.fileName);
+    query.addCriterion(crit);
+    return query;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/InputFilesQuery.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/InputFilesQuery.java
new file mode 100644
index 0000000..30bb461
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/InputFilesQuery.java
@@ -0,0 +1,58 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.query;
+
+//OODT imports
+import org.apache.oodt.pcs.metadata.PCSMetadata;
+import org.apache.oodt.pcs.util.FileManagerUtils;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+
+/**
+ * 
+ * A query to the File Manager using the <code>InputFiles</code> product met
+ * field
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+
+public class InputFilesQuery extends AbstractPCSQuery implements PCSMetadata {
+
+  private String origInputFile;
+
+  public InputFilesQuery(String origFile, FileManagerUtils fm) {
+    super(fm);
+    origInputFile = origFile;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.pcs.query.PCSQuery#buildQuery()
+   */
+  public Query buildQuery() {
+    Query query = new Query();
+    TermQueryCriteria crit = new TermQueryCriteria(INPUT_FILES,
+        this.origInputFile);
+
+    query.addCriterion(crit);
+    return query;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/JobIdQuery.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/JobIdQuery.java
new file mode 100644
index 0000000..c65d96e
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/JobIdQuery.java
@@ -0,0 +1,55 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.query;
+
+//OODT imports
+import org.apache.oodt.pcs.metadata.PCSMetadata;
+import org.apache.oodt.pcs.util.FileManagerUtils;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+
+/**
+ * 
+ * A query to the File Manager using the <code>JobId</code> product met field.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class JobIdQuery extends AbstractPCSQuery implements PCSMetadata {
+
+  private String jobId;
+
+  public JobIdQuery(String jobId, FileManagerUtils fm) {
+    super(fm);
+    this.jobId = jobId;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.pcs.query.PCSQuery#buildQuery()
+   */
+  public Query buildQuery() {
+    Query query = new Query();
+    TermQueryCriteria crit = new TermQueryCriteria(JOB_ID, this.jobId);
+
+    query.addCriterion(crit);
+    return query;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/OutputFilesQuery.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/OutputFilesQuery.java
new file mode 100644
index 0000000..b4ab27c
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/OutputFilesQuery.java
@@ -0,0 +1,56 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.pcs.query;
+
+//OODT imports
+import org.apache.oodt.pcs.metadata.PCSMetadata;
+import org.apache.oodt.pcs.util.FileManagerUtils;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+
+/**
+ * 
+ * A query to the File Manager using the <code>OutputFiles</code> product met
+ * field.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class OutputFilesQuery extends AbstractPCSQuery implements PCSMetadata {
+
+  private String origOutputFile;
+
+  public OutputFilesQuery(String file, FileManagerUtils fm) {
+    super(fm);
+    origOutputFile = file;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.pcs.query.PCSQuery#buildQuery()
+   */
+  public Query buildQuery() {
+    Query query = new Query();
+    TermQueryCriteria crit = new TermQueryCriteria(OUTPUT_FILES,
+        this.origOutputFile);
+
+    query.addCriterion(crit);
+    return query;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/PCSQuery.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/PCSQuery.java
new file mode 100644
index 0000000..78ef1b6
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/PCSQuery.java
@@ -0,0 +1,44 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.query;
+
+//OODT imports
+import org.apache.oodt.pcs.metadata.PCSMetadata;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Query;
+
+/**
+ * 
+ * Core interface for PCS queries (wrappers around file manager {@link Query}s
+ * that make them easier to construct).
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface PCSQuery extends PCSMetadata, CoreMetKeys {
+
+  /**
+   * Builds a filemgr compliant {@link Query} object from a concrete instance of
+   * the implementing class.
+   * 
+   * @return A filemgr compliant {@link Query} object.
+   */
+  public Query buildQuery();
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/ProductNameQuery.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/ProductNameQuery.java
new file mode 100644
index 0000000..f397d6d
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/ProductNameQuery.java
@@ -0,0 +1,57 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.query;
+
+//OODT imports
+import org.apache.oodt.pcs.metadata.PCSMetadata;
+import org.apache.oodt.pcs.util.FileManagerUtils;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+
+/**
+ * 
+ * A query to the File Manager using the <code>ProductName</code> product met
+ * field.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ProductNameQuery extends AbstractPCSQuery implements PCSMetadata {
+
+  private String prodName;
+
+  public ProductNameQuery(String prodName, FileManagerUtils fm) {
+    super(fm);
+    this.prodName = prodName;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.pcs.query.PCSQuery#buildQuery()
+   */
+  public Query buildQuery() {
+    Query query = new Query();
+    TermQueryCriteria crit = new TermQueryCriteria(PRODUCT_NAME, this.prodName);
+
+    query.addCriterion(crit);
+    return query;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/TemporalQuery.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/TemporalQuery.java
new file mode 100644
index 0000000..c6f546a
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/query/TemporalQuery.java
@@ -0,0 +1,72 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.query;
+
+//OODT imports
+import org.apache.oodt.pcs.util.FileManagerUtils;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria;
+
+/**
+ * 
+ * A query with a <code>StartDateTime</code> and an <code>EndDateTime</code>
+ * range that identifies a set of matching {@link Product}s.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class TemporalQuery extends AbstractPCSQuery {
+
+  private String startDateTime;
+
+  private String endDateTime;
+
+  private String temporalFld;
+
+  public TemporalQuery(FileManagerUtils fm, String startDateTime,
+      String endDateTime, String temporalFld) {
+    super(fm);
+    this.startDateTime = startDateTime;
+    this.endDateTime = endDateTime;
+    this.temporalFld = temporalFld;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.pcs.query.PCSQuery#buildQuery()
+   */
+  public Query buildQuery() {
+    Query query = new Query();
+    RangeQueryCriteria crit = new RangeQueryCriteria();
+    crit.setElementName(this.temporalFld);
+    crit.setInclusive(true);
+
+    if (this.startDateTime != null) {
+      crit.setStartValue(this.startDateTime);
+    }
+
+    if (this.endDateTime != null) {
+      crit.setEndValue(this.endDateTime);
+    }
+
+    query.addCriterion(crit);
+    return query;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/tools/PCSHealthMonitor.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/tools/PCSHealthMonitor.java
new file mode 100644
index 0000000..2d5ca1d
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/tools/PCSHealthMonitor.java
@@ -0,0 +1,649 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.tools;
+
+//JDK imports
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+//APACHE imports
+import org.apache.xmlrpc.XmlRpcClient;
+
+//OODT imports
+import org.apache.oodt.commons.date.DateUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.crawl.daemon.CrawlDaemonController;
+import org.apache.oodt.pcs.util.FileManagerUtils;
+import org.apache.oodt.pcs.util.ResourceManagerUtils;
+import org.apache.oodt.pcs.util.WorkflowManagerUtils;
+import org.apache.oodt.pcs.health.CrawlInfo;
+import org.apache.oodt.pcs.health.CrawlPropertiesFile;
+import org.apache.oodt.pcs.health.CrawlerHealth;
+import org.apache.oodt.pcs.health.CrawlerStatus;
+import org.apache.oodt.pcs.health.JobHealthStatus;
+import org.apache.oodt.pcs.health.PCSDaemonStatus;
+import org.apache.oodt.pcs.health.PCSHealthMonitorMetKeys;
+import org.apache.oodt.pcs.health.PCSHealthMonitorReport;
+import org.apache.oodt.pcs.health.WorkflowStatesFile;
+
+/**
+ * 
+ * A tool to monitor the health of the PCS.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public final class PCSHealthMonitor implements CoreMetKeys,
+    PCSHealthMonitorMetKeys {
+
+  private FileManagerUtils fm;
+
+  private WorkflowManagerUtils wm;
+
+  private ResourceManagerUtils rm;
+
+  private CrawlPropertiesFile crawlProps;
+
+  private WorkflowStatesFile statesFile;
+
+  public PCSHealthMonitor(String fmUrlStr, String wmUrlStr, String rmUrlStr,
+      String crawlPropFilePath, String statesFilePath)
+      throws InstantiationException {
+    this.fm = new FileManagerUtils(fmUrlStr);
+    this.wm = new WorkflowManagerUtils(wmUrlStr);
+    this.rm = new ResourceManagerUtils(rmUrlStr);
+    this.crawlProps = new CrawlPropertiesFile(crawlPropFilePath);
+    this.statesFile = new WorkflowStatesFile(statesFilePath);
+  }
+
+  public PCSHealthMonitorReport getReport() {
+    PCSHealthMonitorReport report = new PCSHealthMonitorReport();
+    report.setGenerationDate(new Date());
+    report.setFmStatus(getFileManagerStatus());
+    report.setWmStatus(getWorkflowManagerStatus());
+    report.setRmStatus(getResourceManagerStatus());
+    report.setBatchStubStatus(getBatchStubStatus());
+    report.setCrawlerStatus(getCrawlerStatus());
+    report.setLatestProductsIngested(getProductHealth());
+    report.setJobHealthStatus(getJobStatusHealth());
+    report.setCrawlerHealthStatus(getIngestHealth());
+
+    return report;
+  }
+
+  public void quickPrintMonitorToConsole() {
+    System.out.println(HEADER_AND_FOOTER);
+    System.out.println(REPORT_BANNER);
+    System.out.println("Generated on: "
+        + DateUtils.toString(Calendar.getInstance()));
+    System.out.println("");
+    System.out.println("Service Status:");
+    System.out.println("");
+
+    System.out.println(FILE_MANAGER_DAEMON_NAME
+        + getStrPadding(FILE_MANAGER_DAEMON_NAME, WORKFLOW_MANAGER_DAEMON_NAME)
+        + ":\t[" + this.fm.getFmUrl() + "]: " + printUp(getFmUp()));
+
+    System.out.println(WORKFLOW_MANAGER_DAEMON_NAME + ":\t["
+        + this.wm.getWmUrl() + "]: " + printUp(getWmUp()));
+
+    System.out.println(RESOURCE_MANAGER_DAEMON_NAME + ":\t["
+        + this.rm.getResmgrUrl() + "]: " + printUp(getRmUp()));
+
+    quickPrintBatchStubs();
+
+    System.out.println("");
+    System.out.println("Crawlers:");
+    quickPrintCrawlers();
+    System.out.println("");
+
+    System.out.println("PCS Health: ");
+    System.out.println("");
+    System.out.println("Files:");
+    System.out.println(SECTION_SEPARATOR);
+
+    quickPrintProductHealth();
+
+    System.out.println("");
+    System.out.println("Jobs:");
+    System.out.println(SECTION_SEPARATOR);
+
+    quickPrintJobStatusHealth();
+
+    System.out.println("");
+    System.out.println("Ingest:");
+    System.out.println(SECTION_SEPARATOR);
+
+    quickPrintIngestStatusHealth();
+
+    System.out.println(HEADER_AND_FOOTER);
+
+  }
+
+  public void printMonitorToConsole(PCSHealthMonitorReport report) {
+
+    System.out.println(HEADER_AND_FOOTER);
+    System.out.println(REPORT_BANNER);
+    System.out.println("Generated on: " + report.getCreateDateIsoFormat());
+    System.out.println("");
+    System.out.println("Service Status:");
+    System.out.println("");
+
+    System.out.println(report.getFmStatus().getDaemonName()
+        + getStrPadding(report.getFmStatus().getDaemonName(), report
+            .getWmStatus().getDaemonName()) + ":\t["
+        + report.getFmStatus().getUrlStr() + "]: "
+        + report.getFmStatus().getStatus());
+
+    System.out.println(report.getWmStatus().getDaemonName() + ":\t["
+        + report.getWmStatus().getUrlStr() + "]: "
+        + report.getWmStatus().getStatus());
+
+    System.out.println(report.getRmStatus().getDaemonName() + ":\t["
+        + report.getRmStatus().getUrlStr() + "]: "
+        + report.getRmStatus().getStatus());
+
+    printBatchStubs(report);
+
+    System.out.println("");
+    System.out.println("Crawlers:");
+    printCrawlers(report);
+    System.out.println("");
+
+    System.out.println("PCS Health: ");
+    System.out.println("");
+    System.out.println("Files:");
+    System.out.println(SECTION_SEPARATOR);
+
+    printProductHealth(report);
+
+    System.out.println("");
+    System.out.println("Jobs:");
+    System.out.println(SECTION_SEPARATOR);
+
+    printJobStatusHealth(report);
+
+    System.out.println("");
+    System.out.println("Ingest:");
+    System.out.println(SECTION_SEPARATOR);
+
+    printIngestStatusHealth(report);
+
+    System.out.println(HEADER_AND_FOOTER);
+
+  }
+
+  public static void main(String[] args) throws Exception {
+    String usage = "PCSHealthMonitor <fm url> <wm url> <rm url> <crawler xml file path> <workflow states xml file path>\n";
+    String fmUrlStr = null, wmUrlStr = null, rmUrlStr = null;
+    String crawlerXmlFilePath = null, workflowStateXmlPath = null;
+
+    if (args.length != 5) {
+      System.err.println(usage);
+      System.exit(1);
+    }
+
+    fmUrlStr = args[0];
+    wmUrlStr = args[1];
+    rmUrlStr = args[2];
+    crawlerXmlFilePath = args[3];
+    workflowStateXmlPath = args[4];
+
+    PCSHealthMonitor mon = new PCSHealthMonitor(fmUrlStr, wmUrlStr, rmUrlStr,
+        crawlerXmlFilePath, workflowStateXmlPath);
+    try {
+      mon.quickPrintMonitorToConsole();
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+
+  private PCSDaemonStatus getFileManagerStatus() {
+    PCSDaemonStatus fmStatus = new PCSDaemonStatus();
+
+    fmStatus.setDaemonName(FILE_MANAGER_DAEMON_NAME);
+    fmStatus.setStatus(printUp(getFmUp()));
+    fmStatus.setUrlStr(this.fm.getFmUrl().toString());
+
+    return fmStatus;
+  }
+
+  private PCSDaemonStatus getWorkflowManagerStatus() {
+    PCSDaemonStatus wmStatus = new PCSDaemonStatus();
+
+    wmStatus.setDaemonName(WORKFLOW_MANAGER_DAEMON_NAME);
+    wmStatus.setStatus(printUp(getWmUp()));
+    wmStatus.setUrlStr(this.wm.getWmUrl().toString());
+
+    return wmStatus;
+  }
+
+  private PCSDaemonStatus getResourceManagerStatus() {
+    PCSDaemonStatus rmStatus = new PCSDaemonStatus();
+
+    rmStatus.setDaemonName(RESOURCE_MANAGER_DAEMON_NAME);
+    rmStatus.setStatus(printUp(getRmUp()));
+    rmStatus.setUrlStr(this.rm.getResmgrUrl().toString());
+
+    return rmStatus;
+  }
+
+  private List getBatchStubStatus() {
+    List batchStubStatus = new Vector();
+
+    if (getRmUp()) {
+      // only print if the resource manager is up
+      List resNodes = rm.safeGetResourceNodes();
+
+      if (resNodes != null && resNodes.size() > 0) {
+        for (Iterator i = resNodes.iterator(); i.hasNext();) {
+          ResourceNode node = (ResourceNode) i.next();
+          PCSDaemonStatus batchStatus = new PCSDaemonStatus();
+          batchStatus.setDaemonName(BATCH_STUB_DAEMON_NAME);
+          batchStatus.setUrlStr(node.getIpAddr().toString());
+          batchStatus.setStatus(printUp(getBatchStubUp(node)));
+          batchStubStatus.add(batchStatus);
+        }
+      }
+    }
+
+    return batchStubStatus;
+  }
+
+  private List getCrawlerStatus() {
+    List crawlers = this.crawlProps.getCrawlers();
+    String crawlHost = this.crawlProps.getCrawlHost();
+    List statuses = new Vector();
+
+    if (crawlers != null && crawlers.size() > 0) {
+      Collections.sort(crawlers, new Comparator() {
+        public int compare(Object o1, Object o2) {
+          CrawlInfo c1 = (CrawlInfo) o1;
+          CrawlInfo c2 = (CrawlInfo) o2;
+
+          return c1.getCrawlerName().compareTo(c2.getCrawlerName());
+        }
+
+      });
+
+      for (Iterator i = crawlers.iterator(); i.hasNext();) {
+        CrawlInfo info = (CrawlInfo) i.next();
+        String crawlerUrlStr = "http://" + crawlHost + ":"
+            + info.getCrawlerPort();
+        CrawlerStatus status = new CrawlerStatus();
+        status.setInfo(info);
+        status.setStatus(printUp(getCrawlerUp(crawlerUrlStr)));
+        status.setCrawlHost(crawlHost);
+        statuses.add(status);
+      }
+    }
+
+    return statuses;
+
+  }
+
+  private List getProductHealth() {
+    if (getFmUp()) {
+      return this.fm.safeGetTopNProducts(TOP_N_PRODUCTS);
+    } else
+      return new Vector();
+  }
+
+  private List getJobStatusHealth() {
+    if (!getWmUp()) {
+      return new Vector();
+    }
+
+    List statuses = new Vector();
+    List states = this.statesFile.getStates();
+
+    if (states != null && states.size() > 0) {
+      for (Iterator i = states.iterator(); i.hasNext();) {
+        String state = (String) i.next();
+        int numPipelines = this.wm.safeGetNumWorkflowInstancesByStatus(state);
+        if (numPipelines == -1) {
+          numPipelines = 0;
+        }
+
+        JobHealthStatus jobStatus = new JobHealthStatus();
+        jobStatus.setStatus(state);
+        jobStatus.setNumPipelines(numPipelines);
+        statuses.add(jobStatus);
+      }
+    }
+
+    return statuses;
+  }
+
+  private List getIngestHealth() {
+    if (this.crawlProps.getCrawlers() == null) {
+      return new Vector();
+    }
+
+    List statuses = new Vector();
+
+    for (Iterator i = this.crawlProps.getCrawlers().iterator(); i.hasNext();) {
+      CrawlInfo info = (CrawlInfo) i.next();
+      String crawlUrlStr = "http://" + this.crawlProps.getCrawlHost() + ":"
+          + info.getCrawlerPort();
+      try {
+        CrawlDaemonController controller = new CrawlDaemonController(
+            crawlUrlStr);
+        CrawlerHealth health = new CrawlerHealth();
+        health.setCrawlerName(info.getCrawlerName());
+        health.setNumCrawls(controller.getNumCrawls());
+        health
+            .setAvgCrawlTime((double) (controller.getAverageCrawlTime() / 1000.0));
+        statuses.add(health);
+
+      } catch (Exception e) {
+        CrawlerHealth health = new CrawlerHealth();
+        health.setCrawlerName(info.getCrawlerName());
+        health.setNumCrawls(CRAWLER_DOWN_INT);
+        health.setAvgCrawlTime(CRAWLER_DOWN_DOUBLE);
+        statuses.add(health);
+      }
+
+    }
+
+    return statuses;
+  }
+
+  private void printIngestStatusHealth(PCSHealthMonitorReport report) {
+    if (report.getCrawlerHealthStatus() != null
+        && report.getCrawlerHealthStatus().size() > 0) {
+      for (Iterator i = report.getCrawlerHealthStatus().iterator(); i.hasNext();) {
+        CrawlerHealth health = (CrawlerHealth) i.next();
+        System.out.print(health.getCrawlerName() + ":");
+        if (health.getNumCrawls() == CRAWLER_DOWN_INT) {
+          System.out.println(" DOWN");
+        } else {
+          System.out.println("");
+          System.out.println("Number of Crawls: " + health.getNumCrawls());
+          System.out.println("Average Crawl Time (seconds): "
+              + health.getAvgCrawlTime());
+          System.out.println("");
+        }
+
+      }
+
+    }
+  }
+
+  private void printJobStatusHealth(PCSHealthMonitorReport report) {
+    if (report.getJobHealthStatus() != null
+        && report.getJobHealthStatus().size() > 0) {
+      for (Iterator i = report.getJobHealthStatus().iterator(); i.hasNext();) {
+        JobHealthStatus status = (JobHealthStatus) i.next();
+        System.out.println(status.getNumPipelines() + " pipelines "
+            + status.getStatus());
+      }
+    }
+  }
+
+  private void printProductHealth(PCSHealthMonitorReport report) {
+    if (report.getLatestProductsIngested() != null
+        && report.getLatestProductsIngested().size() > 0) {
+      System.out.println("Latest " + TOP_N_PRODUCTS + " products ingested:");
+      for (Iterator i = report.getLatestProductsIngested().iterator(); i
+          .hasNext();) {
+        Product p = (Product) i.next();
+        p.setProductType(fm.safeGetProductTypeById(p.getProductType()
+            .getProductTypeId()));
+        p.setProductReferences(fm.safeGetProductReferences(p));
+        Metadata prodMet = fm.safeGetMetadata(p);
+        System.out.println(fm.getFilePath(p) + " at: "
+            + prodMet.getMetadata("CAS." + PRODUCT_RECEVIED_TIME));
+      }
+
+    }
+  }
+
+  private void printBatchStubs(PCSHealthMonitorReport report) {
+    if (report.getBatchStubStatus() != null
+        && report.getBatchStubStatus().size() > 0) {
+      for (Iterator i = report.getBatchStubStatus().iterator(); i.hasNext();) {
+        PCSDaemonStatus batchStatus = (PCSDaemonStatus) i.next();
+        System.out.println("> " + batchStatus.getDaemonName() + ": ["
+            + batchStatus.getUrlStr() + "]: " + batchStatus.getStatus());
+      }
+
+    }
+  }
+
+  private void printCrawlers(PCSHealthMonitorReport report) {
+    if (report.getCrawlerStatus() != null
+        && report.getCrawlerStatus().size() > 0) {
+      List crawlers = this.crawlProps.getCrawlers();
+      String biggestString = getBiggestString(crawlers);
+
+      for (Iterator i = report.getCrawlerStatus().iterator(); i.hasNext();) {
+        CrawlerStatus status = (CrawlerStatus) i.next();
+        String crawlerUrlStr = "http://" + status.getCrawlHost() + ":"
+            + status.getInfo().getCrawlerPort();
+        System.out.println(getStrPadding(status.getInfo().getCrawlerName(),
+            biggestString)
+            + status.getInfo().getCrawlerName()
+            + ": ["
+            + crawlerUrlStr
+            + "]: "
+            + status.getStatus());
+      }
+
+    }
+
+  }
+
+  private void quickPrintCrawlers() {
+    List crawlers = this.crawlProps.getCrawlers();
+    String crawlHost = this.crawlProps.getCrawlHost();
+
+    if (crawlers != null && crawlers.size() > 0) {
+      Collections.sort(crawlers, new Comparator() {
+        public int compare(Object o1, Object o2) {
+          CrawlInfo c1 = (CrawlInfo) o1;
+          CrawlInfo c2 = (CrawlInfo) o2;
+
+          return c1.getCrawlerName().compareTo(c2.getCrawlerName());
+        }
+
+      });
+
+      String biggestString = getBiggestString(crawlers);
+      for (Iterator i = crawlers.iterator(); i.hasNext();) {
+        CrawlInfo info = (CrawlInfo) i.next();
+        String crawlerUrlStr = "http://" + crawlHost + ":"
+            + info.getCrawlerPort();
+        System.out.println(getStrPadding(info.getCrawlerName(), biggestString)
+            + info.getCrawlerName() + ": [" + crawlerUrlStr + "]: "
+            + printUp(getCrawlerUp(crawlerUrlStr)));
+      }
+    }
+
+  }
+
+  private void quickPrintBatchStubs() {
+    List resNodes = null;
+
+    if (getRmUp()) {
+      // only print if the resource manager is up
+      resNodes = rm.safeGetResourceNodes();
+
+      if (resNodes != null && resNodes.size() > 0) {
+        for (Iterator i = resNodes.iterator(); i.hasNext();) {
+          ResourceNode node = (ResourceNode) i.next();
+          System.out.println("> " + BATCH_STUB_DAEMON_NAME + ": ["
+              + node.getIpAddr() + "]: " + printUp(getBatchStubUp(node)));
+        }
+      }
+    }
+  }
+
+  private void quickPrintJobStatusHealth() {
+    if (!getWmUp()) {
+      return;
+    }
+
+    List states = this.statesFile.getStates();
+
+    if (states != null && states.size() > 0) {
+      for (Iterator i = states.iterator(); i.hasNext();) {
+        String state = (String) i.next();
+        int numPipelines = this.wm.safeGetNumWorkflowInstancesByStatus(state);
+        if (numPipelines == -1) {
+          numPipelines = 0;
+        }
+        System.out.println(numPipelines + " pipelines " + state);
+
+      }
+    }
+  }
+
+  private void quickPrintProductHealth() {
+    if (getFmUp()) {
+      System.out.println("Latest " + TOP_N_PRODUCTS + " products ingested:");
+
+      List prods = this.fm.safeGetTopNProducts(TOP_N_PRODUCTS);
+
+      if (prods != null && prods.size() > 0) {
+        for (Iterator i = prods.iterator(); i.hasNext();) {
+          Product p = (Product) i.next();
+          p.setProductType(fm.safeGetProductTypeById(p.getProductType()
+              .getProductTypeId()));
+          p.setProductReferences(fm.safeGetProductReferences(p));
+          Metadata prodMet = fm.safeGetMetadata(p);
+          System.out.println(fm.getFilePath(p) + " at: "
+              + prodMet.getMetadata("CAS." + PRODUCT_RECEVIED_TIME));
+        }
+      }
+
+    }
+  }
+
+  private void quickPrintIngestStatusHealth() {
+    if (this.crawlProps.getCrawlers() == null) {
+      return;
+    }
+
+    for (Iterator i = this.crawlProps.getCrawlers().iterator(); i.hasNext();) {
+      CrawlInfo info = (CrawlInfo) i.next();
+      String crawlUrlStr = "http://" + this.crawlProps.getCrawlHost() + ":"
+          + info.getCrawlerPort();
+      try {
+        CrawlDaemonController controller = new CrawlDaemonController(
+            crawlUrlStr);
+        System.out.println(info.getCrawlerName() + ":");
+        System.out.println("Number of Crawls: " + controller.getNumCrawls());
+        System.out.println("Average Crawl Time (seconds): "
+            + (double) (controller.getAverageCrawlTime() / 1000.0));
+        System.out.println("");
+
+      } catch (Exception e) {
+        System.out.println(info.getCrawlerName() + ": DOWN");
+      }
+
+    }
+  }
+
+  private String getBiggestString(List crawlInfos) {
+    int biggestStrSz = Integer.MIN_VALUE;
+    String biggestStr = null;
+
+    for (Iterator i = crawlInfos.iterator(); i.hasNext();) {
+      CrawlInfo info = (CrawlInfo) i.next();
+      String crawlInfoName = info.getCrawlerName();
+      if (crawlInfoName.length() > biggestStrSz) {
+        biggestStr = crawlInfoName;
+        biggestStrSz = biggestStr.length();
+      }
+    }
+
+    return biggestStr;
+  }
+
+  private String getStrPadding(String initString, String compareString) {
+    int sizeInitStr = initString.length();
+    int sizeCompareStr = compareString.length();
+
+    int diff = Math.abs(sizeInitStr - sizeCompareStr);
+    StringBuffer buf = new StringBuffer();
+    for (int i = 0; i < diff; i++) {
+      buf.append(" ");
+    }
+
+    return buf.toString();
+  }
+
+  private boolean getBatchStubUp(ResourceNode node) {
+    XmlRpcClient client = new XmlRpcClient(node.getIpAddr());
+    Vector argList = new Vector();
+
+    try {
+      return ((Boolean) client.execute("batchstub.isAlive", argList))
+          .booleanValue();
+    } catch (Exception e) {
+      return false;
+    }
+  }
+
+  private boolean getCrawlerUp(String crawlUrlStr) {
+    CrawlDaemonController controller = null;
+
+    try {
+      controller = new CrawlDaemonController(crawlUrlStr);
+      return controller.isRunning();
+    } catch (Exception e) {
+      return false;
+    }
+  }
+
+  private boolean getFmUp() {
+    return fm.getFmgrClient() != null ? fm.getFmgrClient().isAlive() : false;
+  }
+
+  private boolean getWmUp() {
+    try {
+      wm.getClient().getRegisteredEvents();
+      return true;
+    } catch (Exception e) {
+      return false;
+    }
+  }
+
+  private boolean getRmUp() {
+    try {
+      rm.getClient().getNodes();
+      return true;
+    } catch (Exception e) {
+      return false;
+    }
+  }
+
+  private String printUp(boolean upFlag) {
+    return upFlag ? STATUS_UP : STATUS_DOWN;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/tools/PCSLongLister.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/tools/PCSLongLister.java
new file mode 100644
index 0000000..74eabd2
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/tools/PCSLongLister.java
@@ -0,0 +1,208 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.tools;
+
+//OODT imports
+import org.apache.oodt.pcs.listing.ListingConf;
+import org.apache.oodt.pcs.metadata.PCSMetadata;
+import org.apache.oodt.pcs.query.InputFilesQuery;
+import org.apache.oodt.pcs.util.FileManagerUtils;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JDK imports
+import java.io.File;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
+
+/**
+ * 
+ * The PCS Long Lister tool: mimics UNIX-ls and looks up descendant metadata for
+ * fields like TestTag, SubTestTag, TestCounter. Also displays Filename,
+ * StartDateTime, and EndDateTime for each listed file, and any of its met keys
+ * configured in the <code>pcs-ll-conf.xml</code> file.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PCSLongLister implements PCSMetadata, CoreMetKeys {
+
+  private FileManagerUtils fm;
+
+  private ListingConf conf;
+
+  public PCSLongLister(String fmUrlStr, String confFile)
+      throws InstantiationException {
+    fm = new FileManagerUtils(fmUrlStr);
+    try {
+      this.conf = new ListingConf(new File(confFile));
+    } catch (Exception e) {
+      throw new InstantiationException(e.getMessage());
+    }
+  }
+
+  public void doList(List prodNames) {
+    if (prodNames != null && prodNames.size() > 0) {
+      System.out.println(getToolHeader());
+      for (Iterator i = prodNames.iterator(); i.hasNext();) {
+        String prodName = (String) i.next();
+        // check to see if the product name has a "/" in it
+        // (this is true in the case of someone using */* from
+        // a shell): if it does, we'll consider the prodName a
+        // path, and we'll clean it using new File(prodName).getName()
+        if (prodName.indexOf("/") != -1) {
+          // clean the prodName
+          prodName = new File(prodName).getName();
+        }
+
+        Product prod = fm.safeGetProductByName(prodName);
+        if (prod == null) {
+          // product not cataloged
+          System.out.println(prodName + "\tNot Cataloged!");
+          continue;
+        }
+        Metadata met = fm.safeGetMetadata(prod);
+        outputListingLine(met, prodName);
+      }
+    }
+
+  }
+
+  public static void main(String[] args) throws Exception {
+    String usage = "PCSLongLister <conf file> <fmurl> [files]";
+    List fileList;
+
+    if (args.length < 2) {
+      System.err.println(usage);
+      System.exit(1);
+    }
+
+    if (args.length == 2) {
+      // assume they gave us the current dir "."
+      // get a list of files from there
+      fileList = Arrays.asList(new File(".").list());
+    } else if (args.length == 3 && new File(args[2]).isDirectory()) {
+      fileList = Arrays.asList(new File(args[2]).list());
+    } else {
+      // it's going to be a list of files anyways
+      // so just treat the whole argList as a list of file names
+      List argList = Arrays.asList(args);
+      fileList = argList.subList(2, argList.size());
+    }
+
+    PCSLongLister lister = new PCSLongLister(args[0], args[1]);
+    lister.doList(fileList);
+
+  }
+
+  private String getToolHeader() {
+    StringBuffer header = new StringBuffer();
+    for (String colName : this.conf.getHeaderColKeys()) {
+      header.append(this.conf.getHeaderColDisplayName(colName));
+      header.append("\t");
+    }
+    return header.toString();
+  }
+
+  private void outputListingLine(Metadata met, String prodName) {
+    StringBuffer output = new StringBuffer();
+    for (String colNameKey : this.conf.getHeaderColKeys()) {
+      if (!this.conf.isCollectionField(colNameKey)) {
+        output.append(met.getMetadata(colNameKey));
+        output.append("\t");
+      } else {
+        output.append(outputOrBlank(getAllProductsByTag(met, prodName,
+            colNameKey)));
+        output.append("\t");
+      }
+    }
+    System.out.println(output.toString());
+  }
+
+  private static String outputOrBlank(List items) {
+    if (items == null || (items != null && items.size() == 0)) {
+      return "N/A";
+    }
+
+    StringBuffer buf = new StringBuffer();
+    for (Iterator i = items.iterator(); i.hasNext();) {
+      String item = (String) i.next();
+      buf.append(item);
+      buf.append(",");
+    }
+
+    buf.deleteCharAt(buf.length() - 1);
+    return buf.toString();
+  }
+
+  private List getAllProductsByTag(Metadata met, String productName,
+      String tagType) {
+    if (met.containsKey(tagType)) {
+      return met.getAllMetadata(tagType);
+    }
+
+    // assume now that there are no test tags
+    // so what we want to do is to query the file catalog
+    // for InputFiles:productName and then keep doing this until
+    // we get an answer that has test tags: for each test tag (once
+    // they are found), we'll collect them in a list
+    List tags = new Vector();
+    boolean foundTag = false;
+    Stack descendants = new Stack();
+    descendants.push(productName);
+
+    while (!descendants.empty() && !foundTag) {
+      String prodName = (String) descendants.pop();
+      List products = fm.queryAllTypes(new InputFilesQuery(prodName, fm)
+          .buildQuery(), this.conf.getExcludedTypes());
+
+      // iterate over all the products
+      // get each set of metadata
+      // if you find one tag, then set foundTag = true, and we
+      // break
+      if (products != null && products.size() > 0) {
+        for (Iterator i = products.iterator(); i.hasNext();) {
+          Product prod = (Product) i.next();
+          Metadata prodMet = fm.safeGetMetadata(prod);
+
+          if (prodMet.containsKey(tagType)) {
+            // got one, done
+            if (!foundTag)
+              foundTag = true;
+            if (!tags.contains(prodMet.getMetadata(tagType))) {
+              tags.add(prodMet.getMetadata(tagType));
+            }
+          }
+        }
+
+        if (!foundTag) {
+          // continue the search
+          descendants.addAll(FileManagerUtils.toProductNameList(products));
+        }
+      }
+    }
+
+    return tags;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/tools/PCSTrace.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/tools/PCSTrace.java
new file mode 100644
index 0000000..76425c1
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/tools/PCSTrace.java
@@ -0,0 +1,251 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.tools;
+
+//JDK imports
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.pcs.metadata.PCSConfigMetadata;
+import org.apache.oodt.pcs.metadata.PCSMetadata;
+import org.apache.oodt.pcs.pedigree.Pedigree;
+import org.apache.oodt.pcs.pedigree.PedigreeTree;
+import org.apache.oodt.pcs.util.FileManagerUtils;
+import org.apache.oodt.pcs.util.WorkflowManagerUtils;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+
+/**
+ * 
+ * A program to trace the history of a particular PCS product.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public final class PCSTrace implements PCSMetadata, PCSConfigMetadata {
+
+  /* our interface to the file manager */
+  private FileManagerUtils fm;
+
+  /* our interface to the workflow manager */
+  private WorkflowManagerUtils wm;
+
+  /* whether or not we should list non-cataloged products in pedigree */
+  private boolean listNotCataloged = false;
+
+  /* exclude list */
+  private List excludeTypeList;
+
+  private static final String REPORT_LINE_SEPARATOR = "-------------------------------------------------- ";
+
+  public PCSTrace(URL wmgrUrl, URL fmUrl) {
+    fm = new FileManagerUtils(fmUrl);
+    wm = new WorkflowManagerUtils(wmgrUrl);
+  }
+
+  public PCSTrace(String wmgrUrlStr, String fmUrlStr) {
+    this(FileManagerUtils.safeGetUrlFromString(wmgrUrlStr), FileManagerUtils
+        .safeGetUrlFromString(fmUrlStr));
+  }
+
+  /**
+   * @param excludeTypeList
+   *          the excludeTypeList to set
+   */
+  public void setExcludeTypeList(List excludeTypeList) {
+    this.excludeTypeList = excludeTypeList;
+  }
+
+  /**
+   * @return the excludeTypeList
+   */
+  public List getExcludeTypeList() {
+    return excludeTypeList;
+  }
+
+  /**
+   * Outputs a trace report in the following format:
+   * 
+   * Product Name: <i>oco_L1aRad09088_0939838838.hdf</i>
+   * -------------------------------------------------- Location:
+   * /preflt/jpl/Rad/9088/l1a/oco_L1aRad09088_0939838838.hdf
+   * 
+   * Metadata:
+   * 
+   * &lt;Met Field Name&gt; =&gt; &lt;Met Field Value&gt; &lt;Met Field
+   * Name2&gt; =&gt; &lt;Met Field Value2&gt;
+   * 
+   * --------------------------------------------------- Generated from
+   * workflows:
+   * 
+   * CPT Pipeline: ID: [99299-add99-92983-9d9d9-0099d] State: FINISHED
+   * Associated products:
+   * 
+   * oco_RawL017_93983993938.pkt oco_RawL032_93939388383.pkt
+   * oco_RawL033_93838383838.pkt oco_RawL034_93938378585.pkt
+   * 
+   * --------------------------------------------------- Full lineage:
+   * 
+   * Upstream: CPTOverview_98383388d.txt=&gt;oco_RawL017_93983993938.pkt=&gt;
+   * oco_RawL032_93939388383
+   * .pkt=&gt;oco_RawL033_93838383838.pkt=&gt;oco_RawL034_93938378585.pkt
+   * 
+   * Downstream: oco_L1BRad_19889_983838383.hdf
+   * ---------------------------------------------------
+   * 
+   * 
+   * @param productName
+   *          The name of the product to trace lineage for.
+   */
+  public void doTrace(String productName) {
+
+    Product prod = fm.safeGetProductByName(productName);
+
+    Pedigree pedigree = new Pedigree(fm, this.listNotCataloged,
+        this.excludeTypeList);
+
+    System.out.println("");
+    System.out.println(REPORT_LINE_SEPARATOR);
+    System.out.println("Product: " + prod.getProductName());
+    System.out.println(REPORT_LINE_SEPARATOR);
+
+    prod.setProductReferences(fm.safeGetProductReferences(prod));
+    System.out.println("Location: " + fm.getFilePath(prod));
+    System.out.println(REPORT_LINE_SEPARATOR);
+    System.out.println("Metadata: ");
+    Metadata met = fm.safeGetMetadata(prod);
+    if (met != null && met.getHashtable() != null
+        && met.getHashtable().keySet().size() > 0) {
+      for (Iterator i = met.getHashtable().keySet().iterator(); i.hasNext();) {
+        String key = (String) i.next();
+        List vals = met.getAllMetadata(key);
+        System.out.println(key + "=>" + vals);
+      }
+    }
+
+    System.out.println(REPORT_LINE_SEPARATOR);
+    System.out.println("Generated from workflow:");
+    System.out.println("");
+    WorkflowInstance inst = null;
+
+    try {
+      inst = getWorkflowInstanceById(wm.safeGetWorkflowInstances(), met
+          .getMetadata(JOB_ID));
+
+      System.out.println(inst.getWorkflow().getName() + ": ID: ["
+          + inst.getId() + "]");
+      System.out.println("Status: " + inst.getStatus());
+      List wInstProds = pedigree.getWorkflowInstProds(inst.getId());
+      if (wInstProds != null && wInstProds.size() > 0) {
+        System.out.println("Associated products:");
+        System.out.println("");
+        for (Iterator i = wInstProds.iterator(); i.hasNext();) {
+          Product wInstProd = (Product) i.next();
+          System.out.println(wInstProd.getProductName());
+        }
+      }
+    } catch (Exception e) {
+      System.out.println("Unable to obtain workflow instance for product!");
+    }
+
+    System.out.println(REPORT_LINE_SEPARATOR);
+    System.out.println("Full lineage:");
+    System.out.println("");
+    System.out.println("Downstream:");
+
+    PedigreeTree downstreamLineageTree = pedigree.doPedigree(prod, false);
+    downstreamLineageTree.printPedigreeTree();
+
+    System.out.println("");
+    System.out.println("Upstream:");
+    PedigreeTree upstreamLineageTree = pedigree.doPedigree(prod, true);
+    upstreamLineageTree.printPedigreeTree();
+
+  }
+
+  public void enableNonCatalogProductsInPed() {
+    this.listNotCataloged = true;
+  }
+
+  /**
+   * 
+   * @param args
+   * @throws Exception
+   */
+  public static void main(String[] args) throws Exception {
+    String productName = null;
+    String workflowUrlStr = null, filemgrUrlStr = null;
+    boolean enableNotCat = false;
+    List exList = null;
+
+    String usage = "PCSTrace --fm <url> --wm <url> --product <name> "
+        + " [--enableNonCat] [--exclude <type name 1>,<type name 2>...,<type name n>]\n";
+
+    for (int i = 0; i < args.length; i++) {
+      if (args[i].equals("--fm")) {
+        filemgrUrlStr = args[++i];
+      } else if (args[i].equals("--wm")) {
+        workflowUrlStr = args[++i];
+      } else if (args[i].equals("--product")) {
+        productName = args[++i];
+      } else if (args[i].equals("--enableNonCat")) {
+        enableNotCat = true;
+      } else if (args[i].equals("--exclude")) {
+        String[] excludeTypes = args[++i].split(",");
+        exList = Arrays.asList(excludeTypes);
+      }
+
+    }
+
+    if (productName == null || workflowUrlStr == null || filemgrUrlStr == null) {
+      System.err.println(usage);
+      System.exit(1);
+    }
+
+    PCSTrace tracer = new PCSTrace(workflowUrlStr, filemgrUrlStr);
+    if (enableNotCat) {
+      tracer.enableNonCatalogProductsInPed();
+    }
+    if (exList != null) {
+      tracer.setExcludeTypeList(exList);
+    }
+    tracer.doTrace(productName);
+
+  }
+
+  private WorkflowInstance getWorkflowInstanceById(List insts, String id) {
+    if (insts == null) {
+      return null;
+    }
+
+    for (Iterator i = insts.iterator(); i.hasNext();) {
+      WorkflowInstance inst = (WorkflowInstance) i.next();
+      if (inst.getId().equals(id)) {
+        return inst;
+      }
+    }
+
+    return null;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/util/FileManagerUtils.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/util/FileManagerUtils.java
new file mode 100644
index 0000000..c19f819
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/util/FileManagerUtils.java
@@ -0,0 +1,454 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.util;
+
+//OODT imports
+import org.apache.oodt.pcs.metadata.PCSConfigMetadata;
+import org.apache.oodt.pcs.query.FilenameQuery;
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JDK imports
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * 
+ * A set of utility methods for use by the PCS in communicating with the File
+ * Manager.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class FileManagerUtils implements PCSConfigMetadata {
+  /* our log stream */
+  private static Logger LOG = Logger
+      .getLogger(FileManagerUtils.class.getName());
+
+  private XmlRpcFileManagerClient fmgrClient = null;
+
+  private URL fmUrl;
+
+  public FileManagerUtils(URL fileMgrUrl) {
+    try {
+      fmgrClient = new XmlRpcFileManagerClient(fileMgrUrl);
+    } catch (ConnectionException e) {
+      LOG.log(Level.SEVERE, "Unable to connect to file manager: ["
+          + fileMgrUrl.toString() + "]");
+      fmgrClient = null;
+    }
+
+    this.fmUrl = fileMgrUrl;
+  }
+
+  public FileManagerUtils(String fmUrlStr) {
+    this(safeGetUrlFromString(fmUrlStr));
+  }
+
+  public FileManagerUtils(XmlRpcFileManagerClient client) {
+    this.fmgrClient = client;
+  }
+
+  public List safeGetTopNProducts(int n) {
+    try {
+      return this.fmgrClient.getTopNProducts(n);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Exception obtaining top" + n
+          + " products: message: " + e.getMessage());
+      return null;
+    }
+  }
+
+  public Product getLatestProductByName(String prodName, String productTypeName) {
+    return getLatestProductByName(prodName,
+        safeGetProductTypeByName(productTypeName));
+  }
+
+  public Product getLatestProductByName(String prodName, ProductType type) {
+    return getLatestProduct(new FilenameQuery(prodName, this).buildQuery(),
+        type);
+  }
+
+  public Product getLatestProduct(Query query, String productTypeName) {
+    return getLatestProduct(query, safeGetProductTypeByName(productTypeName));
+  }
+
+  public List toProductTypeList(List typeNames) {
+    List typeList = new Vector();
+
+    if (typeNames != null && typeNames.size() > 0) {
+      for (Iterator i = typeNames.iterator(); i.hasNext();) {
+        String typeName = (String) i.next();
+        ProductType type = safeGetProductTypeByName(typeName);
+        if (type != null) {
+          typeList.add(type);
+        }
+      }
+    }
+
+    return typeList;
+  }
+
+  public List queryTypeList(Query query, List typeList) {
+    List products = new Vector();
+
+    if (typeList != null && typeList.size() > 0) {
+      for (Iterator i = typeList.iterator(); i.hasNext();) {
+        ProductType type = (ProductType) i.next();
+        List prods = safeIssueQuery(query, type);
+        if (prods != null && prods.size() > 0) {
+          products.addAll(prods);
+        }
+      }
+    }
+
+    return products;
+  }
+
+  public List queryAllTypes(Query query) {
+    return queryAllTypes(query, null);
+  }
+
+  public List<Product> querySpecifiedTypes(Query query, List<String> typeList) {
+    List<Product> products = new Vector<Product>();
+
+    for (String productTypeName : typeList) {
+      List<Product> prods = safeIssueQuery(query,
+          safeGetProductTypeByName(productTypeName));
+      if (prods != null && prods.size() > 0) {
+        products.addAll(prods);
+      }
+    }
+
+    return products;
+  }
+
+  public List queryAllTypes(Query query, List excludeTypeList) {
+    List productTypes = safeGetProductTypes();
+    List products = new Vector();
+
+    if (productTypes != null && productTypes.size() > 0) {
+      for (Iterator i = productTypes.iterator(); i.hasNext();) {
+        ProductType type = (ProductType) i.next();
+        if (excludeTypeList != null && excludeTypeList.contains(type.getName())) {
+          // System.out.println("Skipping: [" + type.getName() + "]");
+          continue;
+        }
+
+        List prods = safeIssueQuery(query, type);
+        if (prods != null && prods.size() > 0) {
+          products.addAll(prods);
+        }
+      }
+    }
+
+    return products;
+
+  }
+
+  public List queryAndReturnMetadata(Query query, ProductType type) {
+    List prods = safeIssueQuery(query, type);
+
+    if (prods == null || (prods != null && prods.size() == 0)) {
+      return new Vector();
+    }
+
+    List prodsMet = new Vector(prods.size());
+
+    for (Iterator i = prods.iterator(); i.hasNext();) {
+      Product p = (Product) i.next();
+      prodsMet.add(safeGetMetadata(p));
+    }
+
+    return prodsMet;
+  }
+
+  public List safeIssueQuery(Query query, ProductType type) {
+    List retProds = null;
+
+    try {
+      retProds = this.fmgrClient.query(query, type);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Exception issuing query: [" + query
+          + "] to file manager at: [" + this.fmgrClient.getFileManagerUrl()
+          + "]: Message: " + e.getMessage(), e);
+    }
+
+    return retProds;
+
+  }
+
+  public Element safeGetElementByName(String elemName) {
+    Element element = null;
+
+    try {
+      element = fmgrClient.getElementByName(elemName);
+    } catch (ValidationLayerException e) {
+      LOG.log(Level.WARNING,
+          "Exception obtaining element definition for element: [" + elemName
+              + "]: Message: " + e.getMessage());
+    }
+
+    return element;
+  }
+
+  public ProductType safeGetProductTypeByName(String productTypeName) {
+    ProductType type = null;
+
+    try {
+      type = fmgrClient.getProductTypeByName(productTypeName);
+    } catch (RepositoryManagerException e) {
+      LOG.log(Level.WARNING, "Exception obtaining product type definition"
+          + " for type: [" + productTypeName + "]: Message: " + e.getMessage());
+    }
+
+    return type;
+  }
+
+  public ProductType safeGetProductTypeById(String productTypeId) {
+    ProductType type = null;
+
+    try {
+      type = fmgrClient.getProductTypeById(productTypeId);
+    } catch (RepositoryManagerException e) {
+      LOG.log(Level.WARNING, "Exception obtaining product type definition"
+          + " for type: [" + productTypeId + "]: Message: " + e.getMessage());
+    }
+
+    return type;
+  }
+
+  public List safeGetProductReferences(Product product) {
+    List refs = null;
+
+    try {
+      refs = fmgrClient.getProductReferences(product);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Exception obtaining product references"
+          + "for product: [" + product.getProductName() + "]: Message: "
+          + e.getMessage());
+    }
+
+    return refs;
+  }
+
+  public Metadata safeGetMetadata(Product product) {
+    Metadata metadata = null;
+
+    try {
+      metadata = fmgrClient.getMetadata(product);
+    } catch (CatalogException e) {
+      LOG.log(Level.WARNING, "Unable to obtain metadata for product: ["
+          + product.getProductName() + "] " + "from File Manager at: ["
+          + fmgrClient.getFileManagerUrl() + "]: Message: " + e.getMessage());
+    }
+
+    return metadata;
+  }
+
+  public List safeGetProductTypes() {
+    List types = null;
+
+    try {
+      types = fmgrClient.getProductTypes();
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Unable to retrieve product types from filemgr: ["
+          + fmgrClient.getFileManagerUrl() + "]: reason: " + e.getMessage());
+    }
+
+    return types;
+  }
+
+  public Product getLatestProduct(Query query, ProductType type) {
+    List products = null;
+
+    try {
+      products = fmgrClient.query(query, type);
+      if (products != null && products.size() > 0) {
+        Product p = (Product) products.get(0);
+        p.setProductReferences(safeGetProductReferences(p));
+        return p;
+      }
+    } catch (Exception e) {
+      LOG.log(Level.SEVERE, "Unable to obtain products: query: [" + query
+          + "]: Message: " + e.getMessage(), e);
+    }
+
+    return null;
+
+  }
+
+  public Product safeGetProductByName(String prodName) {
+    Product p = null;
+
+    try {
+      p = this.fmgrClient.getProductByName(prodName);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Error obtaining product: [" + prodName
+          + "]: Message: " + e.getMessage(), e);
+    }
+
+    return p;
+  }
+
+  public String getFilePath(Product prod) {
+    if (prod.getProductReferences() == null) {
+      prod.setProductReferences(safeGetProductReferences(prod));
+    }
+
+    if (prod.getProductReferences() == null
+        || (prod.getProductReferences() != null && prod.getProductReferences()
+            .size() == 0)) {
+      return "N/A";
+    }
+
+    // get the first ref
+    Reference r = (Reference) prod.getProductReferences().get(0);
+    return safeGetFileFromUri(r.getDataStoreReference()).getAbsolutePath();
+  }
+
+  public static List toProductNameList(List productList) {
+    if (productList == null || (productList != null && productList.size() == 0)) {
+      return new Vector();
+    }
+
+    List prodNames = new Vector(productList.size());
+    for (Iterator i = productList.iterator(); i.hasNext();) {
+      Product p = (Product) i.next();
+      prodNames.add(p.getProductName());
+    }
+
+    return prodNames;
+  }
+
+  public static boolean check(String propName, String propValue,
+      Metadata metadata) {
+    if (propValue == null) {
+      LOG.log(Level.SEVERE, "PCS: " + propName + ": value: " + propValue);
+      metadata.replaceMetadata("ApplicationSuccess", "false");
+      return false;
+    } else {
+      return true;
+    }
+  }
+
+  public static URL safeGetUrlFromString(String urlStr) {
+    URL url = null;
+
+    try {
+      url = new URL(urlStr);
+    } catch (MalformedURLException e) {
+      LOG.log(Level.SEVERE, "PCS: Unable to generate url from url string: ["
+          + urlStr + "]: Message: " + e.getMessage());
+    }
+
+    return url;
+  }
+
+  public static File safeGetFileFromUri(String uri) {
+    File f = null;
+
+    try {
+      f = new File(new URI(uri));
+    } catch (URISyntaxException e) {
+      LOG.log(Level.WARNING,
+          "URI syntax exception obtaining file object from uri: [" + uri + "]");
+    }
+
+    return f;
+  }
+
+  /**
+   * @return the fmgrClient
+   */
+  public XmlRpcFileManagerClient getFmgrClient() {
+    return fmgrClient;
+  }
+
+  /**
+   * @param fmgrClient
+   *          the fmgrClient to set
+   */
+  public void setFmgrClient(XmlRpcFileManagerClient fmgrClient) {
+    this.fmgrClient = fmgrClient;
+    if (this.fmgrClient != null) {
+      this.fmUrl = this.fmgrClient.getFileManagerUrl();
+    }
+  }
+
+  /**
+   * 
+   * @return The {@link URL} to the File Manager that this FileManagerUtils
+   *         object connects to.
+   */
+  public URL getFmUrl() {
+    return this.fmUrl;
+  }
+
+  public static String getDirProductFilePath(Product p, String prodName) {
+    return FileManagerUtils.safeGetFileFromUri(
+        FileManagerUtils.getRootReference(prodName, p.getProductReferences())
+            .getOrigReference()).getAbsolutePath();
+  }
+
+  public static Reference getRootReference(String productName, List refs) {
+    Reference r = null;
+
+    for (Iterator i = refs.iterator(); i.hasNext();) {
+      Reference ref = (Reference) i.next();
+      if (isRootDir(ref, productName)) {
+        r = ref;
+      }
+    }
+
+    return r;
+  }
+
+  public static boolean isRootDir(Reference r, String prodName) {
+    if (!r.getOrigReference().endsWith("/")) {
+      return false;
+    } else {
+      String referenceURI = r.getOrigReference();
+      int lastFolderInPathStartIdx = referenceURI.substring(0,
+          referenceURI.length() - 1).lastIndexOf("/") + 1;
+      String lastFolderInPath = referenceURI.substring(
+          lastFolderInPathStartIdx, referenceURI.length() - 1);
+      return lastFolderInPath.startsWith(prodName);
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/util/ResourceManagerUtils.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/util/ResourceManagerUtils.java
new file mode 100644
index 0000000..e849eb7
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/util/ResourceManagerUtils.java
@@ -0,0 +1,113 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.util;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.resource.system.XmlRpcResourceManagerClient;
+
+/**
+ * A set of utility methods that can be used by PCS that need to
+ * communicate with the Resource Manager.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ResourceManagerUtils {
+
+  /* our resource manager client */
+  private XmlRpcResourceManagerClient client;
+
+  /* our log stream */
+  private static final Logger LOG = Logger.getLogger(ResourceManagerUtils.class
+      .getName());
+
+  private URL rmUrl;
+
+  public ResourceManagerUtils(String urlStr) {
+    this(safeGetUrlFromString(urlStr));
+  }
+
+  public ResourceManagerUtils(URL url) {
+    this.client = new XmlRpcResourceManagerClient(url);
+    this.rmUrl = url;
+
+  }
+
+  public ResourceManagerUtils(XmlRpcResourceManagerClient client) {
+    this.client = client;
+  }
+
+  /**
+   * @return the client
+   */
+  public XmlRpcResourceManagerClient getClient() {
+    return client;
+  }
+
+  /**
+   * @param client
+   *          the client to set
+   */
+  public void setClient(XmlRpcResourceManagerClient client) {
+    this.client = client;
+    if (this.client != null) {
+      this.rmUrl = this.client.getResMgrUrl();
+    }
+  }
+
+  public List safeGetResourceNodes() {
+    try {
+      return this.client.getNodes();
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to obtain resource nodes "
+          + "while communicating with resource manager at: ["
+          + this.client.getResMgrUrl() + "]");
+      return null;
+    }
+  }
+
+  /**
+   * 
+   * @return The {@link URL} for the Resource Manager that this
+   *         ResourceManagerUtils communicates with.
+   */
+  public URL getResmgrUrl() {
+    return this.rmUrl;
+  }
+
+  private static URL safeGetUrlFromString(String urlStr) {
+    URL url = null;
+
+    try {
+      url = new URL(urlStr);
+    } catch (MalformedURLException e) {
+      LOG.log(Level.SEVERE, "PCS: Unable to generate url from url string: ["
+          + urlStr + "]: Message: " + e.getMessage());
+    }
+
+    return url;
+  }
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/util/WorkflowManagerUtils.java b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/util/WorkflowManagerUtils.java
new file mode 100644
index 0000000..67db072
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/java/org/apache/oodt/pcs/util/WorkflowManagerUtils.java
@@ -0,0 +1,158 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.util;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+import org.apache.xmlrpc.XmlRpcClient;
+
+/**
+ * 
+ * A set of utility methods that can be used by PCS that need to communicate
+ * with the Workflow Manager.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class WorkflowManagerUtils {
+
+  /* our workflow manager client */
+  private XmlRpcWorkflowManagerClient client;
+
+  /* our log stream */
+  private static final Logger LOG = Logger.getLogger(WorkflowManagerUtils.class
+      .getName());
+
+  private URL wmUrl;
+
+  public WorkflowManagerUtils(String urlStr) {
+    this(safeGetUrlFromString(urlStr));
+  }
+
+  public WorkflowManagerUtils(URL url) {
+    this.client = new XmlRpcWorkflowManagerClient(url);
+    this.wmUrl = url;
+  }
+
+  public WorkflowManagerUtils(XmlRpcWorkflowManagerClient client) {
+    this.client = client;
+  }
+
+  public void updateWorkflowInstanceStatus(String wInstId, String status) {
+    try {
+      this.client.updateWorkflowInstanceStatus(wInstId, status);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+
+  }
+
+  public List<WorkflowInstance> safeGetWorkflowInstances() {
+    if (!isConnected())
+      return Collections.EMPTY_LIST;
+
+    try {
+      return this.client.getWorkflowInstances();
+    } catch (Throwable ignore) {
+      return Collections.EMPTY_LIST;
+    }
+  }
+
+  public boolean isConnected() {
+    try {
+      XmlRpcClient c = new XmlRpcClient(this.client.getWorkflowManagerUrl());
+      c.execute("workflowmgr.getWorkflowInstances", new Vector());
+      return true;
+    } catch (Exception ignore) {
+      return false;
+    }
+  }
+
+  public List safeGetWorkflowInstancesByStatus(String status) {
+    try {
+      return this.client.getWorkflowInstancesByStatus(status);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING,
+          "exception obtaining workflow instances by status: [" + status
+              + "]: message: " + e.getMessage());
+      return null;
+    }
+  }
+
+  public int safeGetNumWorkflowInstancesByStatus(String status) {
+    try {
+      return this.client.getNumWorkflowInstancesByStatus(status);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING,
+          "exception obtaining num workflow instances by status: [" + status
+              + "]: message: " + e.getMessage());
+      return -1;
+    }
+  }
+
+  /**
+   * @return the client
+   */
+  public XmlRpcWorkflowManagerClient getClient() {
+    return client;
+  }
+
+  /**
+   * @param client
+   *          the client to set
+   */
+  public void setClient(XmlRpcWorkflowManagerClient client) {
+    this.client = client;
+    if (this.client != null) {
+      this.wmUrl = this.client.getWorkflowManagerUrl();
+    }
+  }
+
+  private static URL safeGetUrlFromString(String urlStr) {
+    URL url = null;
+
+    try {
+      url = new URL(urlStr);
+    } catch (MalformedURLException e) {
+      LOG.log(Level.SEVERE, "PCS: Unable to generate url from url string: ["
+          + urlStr + "]: Message: " + e.getMessage());
+    }
+
+    return url;
+  }
+
+  /**
+   * 
+   * @return The {@link URL} pointer to the Workflow Manager that this
+   *         WorkflowManagerUtils communicates with.
+   */
+  public URL getWmUrl() {
+    return this.wmUrl;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/core/src/main/resources/pcs-crawlers.xml b/0.8.1-rc1/pcs/core/src/main/resources/pcs-crawlers.xml
new file mode 100644
index 0000000..d1bfee2
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/resources/pcs-crawlers.xml
@@ -0,0 +1,50 @@
+<?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.
+
+Author: Chris Mattmann
+
+This file defines what ingest crawlers are being used by the PCS.
+This file is used in the PCSHealthMonitor tool.
+-->
+<input>
+
+    <!-- 
+      Here are global properties for the 
+      crawler. These properties are environment 
+      variable replaced.
+      
+      The only current property is:
+      
+      Hostname: the default hostname that the crawler 
+      daemons are operating on.
+     -->
+	<group name="CrawlProperties">
+		<scalar name="Hostname">localhost</scalar>
+	</group>
+
+    <!-- Here is a set of scalars where 
+         the scalar:
+         
+         name: the name of the crawler to monitor status for.
+         value: the port number that the crawler daemon to 
+         monitor is running on.
+     -->
+	<group name="CrawlerInfo">
+	    <scalar name="Crawler1">9020</scalar>
+	</group>
+
+</input>
\ No newline at end of file
diff --git a/0.8.1-rc1/pcs/core/src/main/resources/pcs-ll-conf.xml b/0.8.1-rc1/pcs/core/src/main/resources/pcs-ll-conf.xml
new file mode 100644
index 0000000..d03d7ea
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/resources/pcs-ll-conf.xml
@@ -0,0 +1,96 @@
+<?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.
+
+Author: Chris Mattmann
+
+This file configures the PCS long lister, defining what product types
+to exclude from the listing, what field names to include as listing 
+columns, and which of those field names are collection tags that group 
+products together.
+-->
+<input>
+
+  <!-- 
+    Defines metadata fields per product to show as 
+    columns in the long listing. The scalar name 
+    attribute is the product met field name, and 
+    the value for the scalar is the name that the 
+    long lister displays while listing. The vector of 
+    ordered met keys is the display order in the listing.
+   -->
+  <group name="MetFieldColumns">
+    <vector name="OrderedMetKeys">
+      <element>Filename</element>
+      <element>TestTag</element>
+      <element>SubTestTag</element>
+      <element>TestCounter</element>
+      <element>StartDateTime</element>
+      <element>EndDateTime</element>
+    </vector>
+  
+    <scalar name="Filename">Filename</scalar>
+    <scalar name="TestTag">Test Tag(s)</scalar>
+    <scalar name="SubTestTag">Subtest tag(s)</scalar>
+    <scalar name="TestCounter">Test Counter(s)</scalar>
+    <scalar name="StartDateTime">DataStartTime</scalar>
+    <scalar name="EndDateTime">DataEndTime</scalar>
+  </group>
+  
+  <!-- 
+    Lets the long lister know which fields are 
+    collection fields: that is, fields that group 
+    products together. These fields will be used, along 
+    with the InputFiles met field, to find descendant 
+    files with matching collection field values.
+   -->
+  <group name="CollectionFields">
+    <vector name="FieldNames">
+      <element>TestTag</element>
+      <element>SubTestTag</element>
+      <element>TestCounter</element>
+    </vector>
+  </group>
+  
+  <!-- 
+    If you don't expect all the product types to be 
+    listable, you can set an exclude list. This is 
+    useful when e.g., some product types are so massive 
+    you would never do a long listing on them because 
+    the descendant query would take a long time.  
+   -->
+  <group name="ExcludedProductTypeList">
+   <vector name="ProductTypes">
+    <element>FTSSpectrum</element>
+    <element>FTSRunlog</element>
+    <element>FTSSunrun</element>
+    <element>PrimaryLog</element>
+    <element>MonitorLog</element>
+    <element>OCOTrendXML</element>
+    <element>SavesetDir</element>
+    <element>FTSIgramDir</element>
+    <element>SavesetInfoDir</element>
+    <element>CPTHeliostat</element>
+    <element>CPTMotor</element>
+    <element>CPTPhotodiode</element>
+    <element>CPTWavemeter</element>
+    <element>CPTETL</element>
+    <element>CPTStep</element>
+    <element>CPTCollimator</element>
+   </vector>
+  </group>
+
+</input>
\ No newline at end of file
diff --git a/0.8.1-rc1/pcs/core/src/main/resources/pcs-workflow-statuses.xml b/0.8.1-rc1/pcs/core/src/main/resources/pcs-workflow-statuses.xml
new file mode 100644
index 0000000..c9402e3
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/resources/pcs-workflow-statuses.xml
@@ -0,0 +1,42 @@
+<?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.
+ 
+Author: Chris Mattmann
+
+This file defines the workflow statuses that we care about
+in the PCS Health Monitor tool.
+-->
+<input>
+
+    <!--  this information defines the 
+    valid workflow states that we want to 
+    check job status for.
+     -->
+	<group name="WorkflowStatesGroup">
+		<vector name="States">
+		 <element>QUEUED</element>
+		 <element>RSUBMIT</element>
+		 <element>BUILDING CONFIG FILE</element>
+		 <element>PGE EXEC</element>
+		 <element>CRAWLING</element>
+		 <element>STAGING INPUT</element>
+		 <element>FINISHED</element>
+		 <element>STARTED</element>
+		 <element>PAUSED</element>
+		</vector>
+	</group>
+</input>
\ No newline at end of file
diff --git a/0.8.1-rc1/pcs/core/src/main/resources/pcs.logging.properties b/0.8.1-rc1/pcs/core/src/main/resources/pcs.logging.properties
new file mode 100644
index 0000000..47ddde4
--- /dev/null
+++ b/0.8.1-rc1/pcs/core/src/main/resources/pcs.logging.properties
@@ -0,0 +1,48 @@
+# 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.
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates one handlers
+handlers = java.util.logging.ConsoleHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging levels
+org.apache.oodt.pcs.level = SEVERE
+org.apache.oodt.pcs.util.level = SEVERE
+org.apache.oodt.pcs.tools.level = SEVERE
+
+# set logging levels for FM interface
+org.apache.oodt.cas.filemgr.system.level = SEVERE
+org.apache.oodt.cas.pge.util.level = OFF
+
+# set logging levels for WM interface
+org.apache.oodt.cas.workflow.system.level = OFF
+org.apache.oodt.cas.workflow.instrepo.level = OFF
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = OFF
+httpclient.wire.header.level = OFF
+httpclient.wire.level = OFF
+sun.net.www.protocol.http.level = OFF
+
diff --git a/0.8.1-rc1/pcs/input/pom.xml b/0.8.1-rc1/pcs/input/pom.xml
new file mode 100644
index 0000000..5de008d
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+  <artifactId>pcs-input</artifactId>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../../core/pom.xml</relativePath>
+  </parent>
+  <name>Process Control System Input Data Package</name>
+  <packaging>jar</packaging>
+  <description>The Process Control System's data handling package. This package contains data structures
+  and readers and writers to write an input file format similar to HDF, as represented in XML.
+  </description>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>2.4</version>
+        <configuration>
+          <forkMode>pertest</forkMode>
+          <useSystemClassLoader>false</useSystemClassLoader>
+          <systemProperties>
+            <property>
+              <name>javax.xml.transform.TransformerFactory</name>
+              <value>com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl</value>
+            </property>
+          </systemProperties>
+           <forkedProcessTimeoutInSeconds>0</forkedProcessTimeoutInSeconds>
+           <redirectTestOutputToFile>true</redirectTestOutputToFile>
+            <includes>
+              <include>**/*Test*.java</include>
+            </includes>
+        </configuration>
+      </plugin>  
+    </plugins>
+    <resources>
+      <resource>
+        <targetPath>org/apache/oodt/pcs/input</targetPath>
+        <directory>${basedir}/src/main/resources</directory>
+        <includes>
+          <include>pge-config-example.xml</include>
+        </includes>
+      </resource>
+    </resources>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-commons</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigFileException.java b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigFileException.java
new file mode 100644
index 0000000..c0136b0
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigFileException.java
@@ -0,0 +1,56 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+/**
+ * 
+ * <p>
+ * A PGEConfigFileException is thrown by the {@link PGEConfigFileReader} when
+ * there is some general error parsing the {@link PGEConfigurationFile}.
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PGEConfigFileException extends Exception {
+
+  /* needed for serializable interface */
+  private static final long serialVersionUID = 92938858585L;
+
+  /**
+   * <p>
+   * Constructs a new PGEConfigFileException.
+   * </p>
+   */
+  public PGEConfigFileException() {
+    super();
+  }
+
+  /**
+   * <p>
+   * Constructs a new PGEConfigFileException with the given <code>message</code>
+   * .
+   * </p>
+   * 
+   * @param message
+   *          The error message.
+   */
+  public PGEConfigFileException(String message) {
+    super(message);
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigFileKeys.java b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigFileKeys.java
new file mode 100644
index 0000000..1c0b4db
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigFileKeys.java
@@ -0,0 +1,59 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+/**
+ * 
+ * <p>
+ * Metadata keys used when building a {@link PGEConfigurationFile}
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public interface PGEConfigFileKeys {
+
+  public static final String RECORDED_AUX_INPUT_FILES_GROUP = "RecordedAuxiliaryInputFiles";
+
+  public static final String DYNAMIC_AUX_INPUT_FILES_GROUP = "DynamicAuxiliaryInputFiles";
+
+  public static final String INPUT_PRODUCT_FILES_GROUP = "InputProductFiles";
+
+  public static final String PRODUCT_PATH_GROUP = "ProductPathGroup";
+
+  public static final String PGE_NAME_GROUP = "PGENameGroup";
+
+  public static final String MODE_GROUP = "ModeGroup";
+
+  public static final String GEOMETRY_GROUP = "Geometry";
+
+  public static final String PRIMARY_EXECUTABLE_GROUP = "PrimaryExecutable";
+
+  public static final String SFIF_FILE_GROUP = "StaticFileIdentificationFiles";
+
+  public static final String JOB_IDENTIFICATION_GROUP = "JobIdentification";
+
+  public static final String SCF_IDENTIFICATION_GROUP = "SCFIdentification";
+
+  public static final String MONITOR_GROUP = "MonitorGroup";
+
+  public static final String MONITOR_LEVEL_GROUP = "MonitorLevel";
+
+  public static final String LOG_METADATA_GROUP = "LogMetadata";
+
+  public static final String COMMAND_LINE_PARAMETERS_GROUP = "CommandLineParameters";
+
+}
diff --git a/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigFileReader.java b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigFileReader.java
new file mode 100644
index 0000000..4759c9e
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigFileReader.java
@@ -0,0 +1,318 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+//JDK imports
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * 
+ * <p>
+ * A Reader for reading the constructs defined in a {@link PGEConfigurationFile}.
+ * The constructs are read and a new {@link PGEConfigurationFile} object is
+ * constructed and returned.
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PGEConfigFileReader {
+
+  /**
+   * <p>
+   * Default Constructor
+   * </p>
+   */
+  public PGEConfigFileReader() {
+  }
+
+  /**
+   * 
+   * <p>
+   * Reads the PGE Configuration file from the given <code>url</code>.
+   * </p>
+   * 
+   * @param url
+   *          The {@link URL} pointer to the pge configuration file.
+   * @return A new {@link PGEConfigurationFile} object, created from the
+   *         specified URL.
+   * @throws PGEConfigFileException
+   *           If there is an error reading the url.
+   */
+  public PGEConfigurationFile read(URL url) throws PGEConfigFileException {
+    PGEConfigurationFile configFile = null;
+
+    try {
+      configFile = read(url.openStream());
+    } catch (IOException e) {
+      throw new PGEConfigFileException("Unable to read PGE "
+          + "configuration file from url: " + url + ": Message: "
+          + e.getMessage());
+    }
+
+    return configFile;
+  }
+
+  /**
+   * 
+   * <p>
+   * Reads a PGEConfigurationFile from the specified <code>is</code>
+   * InputStream.
+   * </p>
+   * 
+   * @param is
+   *          The InputStream to read the PGEConfigurationFile from.
+   * @return A new {@link PGEConfigurationFile}, created from the specified
+   *         InputStream.
+   * @throws PGEConfigFileException
+   *           If any error occurs.
+   */
+  public PGEConfigurationFile read(InputStream is)
+      throws PGEConfigFileException {
+    PGEConfigurationFile configFile = null;
+
+    DocumentBuilderFactory factory = null;
+    DocumentBuilder parser = null;
+    Document document = null;
+
+    if (is == null) {
+      return null;
+    }
+
+    InputSource inputSource = new InputSource(is);
+
+    try {
+      factory = DocumentBuilderFactory.newInstance();
+      parser = factory.newDocumentBuilder();
+      document = parser.parse(inputSource);
+    } catch (Exception parseException) {
+      parseException.printStackTrace();
+      return null;
+    }
+
+    // okay, construct the PGEConfigurationFile now
+    configFile = new PGEConfigurationFile();
+
+    Element pgeConf = document.getDocumentElement();
+
+    NodeList pgeGroups = pgeConf.getElementsByTagName("group");
+
+    for (int i = 0; i < pgeGroups.getLength(); i++) {
+      // get the name of the group
+      Element group = (Element) pgeGroups.item(i);
+      String groupName = group.getAttribute("name");
+
+      if (groupName.equals("PGENameGroup")) {
+        addPGEName(configFile, group);
+      } else if (groupName.equals("InputProductFiles")) {
+        addInputProductFiles(configFile, group);
+      } else if (groupName.equals("StaticFileIdentificationFiles")) {
+        addSFIFFiles(configFile, group);
+      } else if (groupName.equals("DynamicAuxiliaryInputFiles")) {
+        addDynamicAuxInputFiles(configFile, group);
+      } else if (groupName.equals("RecordedAuxiliaryInputFiles")) {
+        addRecAuxInputFiles(configFile, group);
+      } else if (groupName.equals("ProductPathGroup")) {
+        addProductPath(configFile, group);
+      } else if (groupName.equals("MonitorGroup")) {
+        addMonitorGroup(configFile, group);
+      } else if (groupName.equals("MonitorLevel")) {
+        addMonitorLevels(configFile, group);
+      } else {
+        // pge specific groups, just add generic groups
+        addPGESpecificGroup(configFile, group);
+      }
+    }
+
+    return configFile;
+  }
+
+  private void addPGESpecificGroup(PGEConfigurationFile configFile,
+      Element group) throws PGEConfigFileException {
+
+    List scalars = PGEXMLFileUtils.getScalars(group);
+    List vectors = PGEXMLFileUtils.getVectors(group);
+    List matrixs = PGEXMLFileUtils.getMatrixs(group);
+
+    PGEGroup pgeGroup = new PGEGroup(group.getAttribute("name"));
+
+    for (Iterator i = scalars.iterator(); i.hasNext();) {
+      PGEScalar s = (PGEScalar) i.next();
+      pgeGroup.addScalar(s);
+    }
+
+    for (Iterator i = vectors.iterator(); i.hasNext();) {
+      PGEVector v = (PGEVector) i.next();
+      pgeGroup.addVector(v);
+    }
+
+    for (Iterator i = matrixs.iterator(); i.hasNext();) {
+      PGEMatrix m = (PGEMatrix) i.next();
+      pgeGroup.addMatrix(m);
+    }
+
+    configFile.getPgeSpecificGroups().put(pgeGroup.getName(), pgeGroup);
+
+  }
+
+  private void addMonitorLevels(PGEConfigurationFile configFile, Element group)
+      throws PGEConfigFileException {
+
+    List scalars = PGEXMLFileUtils.getScalars(group);
+
+    if (scalars != null && scalars.size() > 0) {
+      for (Iterator i = scalars.iterator(); i.hasNext();) {
+        PGEScalar scalar = (PGEScalar) i.next();
+        configFile.getMonitorLevelGroup().addScalar(scalar);
+      }
+    }
+
+  }
+
+  private void addMonitorGroup(PGEConfigurationFile configFile, Element group)
+      throws PGEConfigFileException {
+
+    List scalars = PGEXMLFileUtils.getScalars(group);
+
+    // the list should be not be null
+    if (scalars == null) {
+      throw new PGEConfigFileException(
+          "There is no monitor path or monitor filename format defined in the MonitorGroup!");
+    }
+
+    PGEScalar monPath = null, monFilenameFormat = null;
+
+    for (Iterator i = scalars.iterator(); i.hasNext();) {
+      PGEScalar scalar = (PGEScalar) i.next();
+
+      if (scalar.getName().equals("MonitorPath")) {
+        monPath = scalar;
+      } else if (scalar.getName().equals("MonitorFilenameFormat")) {
+        monFilenameFormat = scalar;
+      }
+    }
+
+    configFile.setMonitorPath(monPath);
+    configFile.setMonitorFilenameFormat(monFilenameFormat);
+
+  }
+
+  private void addProductPath(PGEConfigurationFile configFile, Element group)
+      throws PGEConfigFileException {
+    List scalars = PGEXMLFileUtils.getScalars(group);
+
+    // the list should be size 1
+    if (scalars == null || (scalars != null && scalars.size() != 1)) {
+      throw new PGEConfigFileException(
+          "There is no product path defined in the configuration file, or there is more than one scalar listed in the ProductPathGroup!");
+    }
+
+    PGEScalar scalar = (PGEScalar) scalars.get(0);
+
+    // the name of the product path should be ProductPath
+
+    if (!scalar.getName().equals("ProductPath")) {
+      throw new PGEConfigFileException(
+          "The product path should be defined as a scalar with the name \"ProductPath\"!");
+    }
+
+    configFile.setProductPath(scalar);
+  }
+
+  private void addPGEName(PGEConfigurationFile configFile, Element group)
+      throws PGEConfigFileException {
+
+    // get the scalars, there should be only one
+    List scalars = PGEXMLFileUtils.getScalars(group);
+
+    // the list should be size 1
+    if (scalars == null || (scalars != null && scalars.size() != 1)) {
+      throw new PGEConfigFileException(
+          "There is no PGEName defined in the configuration file, or there is more than one scalar listed in the PGENameGroup");
+    }
+
+    // the name of the scalar should be PGEName
+    PGEScalar scalar = (PGEScalar) scalars.get(0);
+
+    if (!scalar.getName().equals("PGEName")) {
+      throw new PGEConfigFileException(
+          "The name of the PGE should be defined as a scalar with the name \"PGEName\"!");
+    }
+
+    // okay, we're set, set the PGE Name
+    configFile.setPgeName(scalar);
+
+  }
+
+  private void addInputProductFiles(PGEConfigurationFile configFile,
+      Element group) throws PGEConfigFileException {
+    addScalarFilesToGroup(group, configFile.getInputProductFiles());
+    addVectorFilesToGroup(group, configFile.getInputProductFiles());
+  }
+
+  private void addSFIFFiles(PGEConfigurationFile configFile, Element group)
+      throws PGEConfigFileException {
+    addScalarFilesToGroup(group, configFile.getStaticFileIdentificationFiles());
+  }
+
+  private void addDynamicAuxInputFiles(PGEConfigurationFile configFile,
+      Element group) throws PGEConfigFileException {
+    addScalarFilesToGroup(group, configFile.getDynamicAuxiliaryInputFiles());
+  }
+
+  private void addRecAuxInputFiles(PGEConfigurationFile configFile,
+      Element group) throws PGEConfigFileException {
+    addScalarFilesToGroup(group, configFile.getRecordedAuxiliaryInputFiles());
+  }
+
+  private void addScalarFilesToGroup(Element group, PGEGroup pgeGroup)
+      throws PGEConfigFileException {
+    // get the scalars, and add them to the group
+    List scalars = PGEXMLFileUtils.getScalars(group);
+
+    if (scalars != null && scalars.size() > 0) {
+      for (Iterator i = scalars.iterator(); i.hasNext();) {
+        PGEScalar scalar = (PGEScalar) i.next();
+        pgeGroup.addScalar(scalar);
+      }
+    }
+  }
+
+  private void addVectorFilesToGroup(Element group, PGEGroup pgeGroup)
+      throws PGEConfigFileException {
+    // get the vectors, and add them to the group
+    List vectors = PGEXMLFileUtils.getVectors(group);
+
+    if (vectors != null && vectors.size() > 0) {
+      for (Iterator i = vectors.iterator(); i.hasNext();) {
+        PGEVector vector = (PGEVector) i.next();
+        pgeGroup.addVector(vector);
+      }
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigFileWriter.java b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigFileWriter.java
new file mode 100644
index 0000000..f989f46
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigFileWriter.java
@@ -0,0 +1,357 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JDK imports
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * <p>
+ * A Configuration File Writer for PGEs.
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public final class PGEConfigFileWriter implements PGEConfigFileKeys,
+    PGEDataParseKeys {
+
+  /* the PGE configuration file that we're writing */
+  private PGEConfigurationFile configFile = null;
+
+  /* our log stream */
+  private static Logger LOG = Logger.getLogger(PGEConfigFileWriter.class
+      .getName());
+
+  /*
+   * whether or not the values in the XML file should be URLEncoded: if true,
+   * the values will be encoded using UTF-8.
+   */
+  private boolean urlEncoding = false;
+
+  /* schema location for the PGE input.xsd file */
+  private String schemaLocation = null;
+
+  /**
+   * <p>
+   * Default Constructor
+   * </p>
+   * .
+   * 
+   * @param config
+   *          The ConfigurationFile that this writer is responsible for writing.
+   * 
+   */
+  public PGEConfigFileWriter(PGEConfigurationFile config) {
+    this.configFile = config;
+  }
+
+  /**
+   * <p>
+   * Writes the ConfigurationFile to the specified filePath.
+   * </p>
+   * 
+   * @param filePath
+   *          The filePath of the XML config file to write.
+   * @throws Exception
+   *           If any error occurs.
+   */
+  public void writeToXmlFile(String filePath) throws Exception {
+    XMLUtils.writeXmlFile(getConfigFileXml(), filePath);
+  }
+
+  /**
+   * 
+   * @return An XML DOM {@link Document} representation of the internal
+   *         PGEConfigurationFile.
+   * @throws Exception
+   *           If any error occurs.
+   */
+  public Document getConfigFileXml() throws Exception {
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    factory.setNamespaceAware(true);
+    Document document = null;
+
+    try {
+      DocumentBuilder builder = factory.newDocumentBuilder();
+      document = builder.newDocument();
+
+      Element root = (Element) document.createElement(PGE_INPUT_TAG_NAME);
+      root.setAttribute("xmlns:xsi",
+          "http://www.w3.org/2001/XMLSchema-instance");
+      root
+          .setAttribute(
+              "xsi:noNamespaceSchemaLocation",
+              (schemaLocation == null
+                  || (schemaLocation != null && schemaLocation.equals("")) ? "input.xsd"
+                  : schemaLocation));
+      document.appendChild(root);
+
+      if (configFile != null) {
+        // write the PGE Name group
+        if (configFile.getPgeName() != null) {
+          PGEGroup pgeNameGroup = new PGEGroup(PGE_NAME_GROUP);
+          pgeNameGroup.addScalar(configFile.getPgeName());
+          root.appendChild(getGroupElement(pgeNameGroup, document));
+        }
+
+        // write the input product files
+        root.appendChild(getGroupElement(configFile.getInputProductFiles(),
+            document));
+
+        // write the static file identification files
+        root.appendChild(getGroupElement(configFile
+            .getStaticFileIdentificationFiles(), document));
+
+        // write the dynamic auxilliary files
+        root.appendChild(getGroupElement(configFile
+            .getDynamicAuxiliaryInputFiles(), document));
+
+        // write the recorded auxilliary files
+        root.appendChild(getGroupElement(configFile
+            .getRecordedAuxiliaryInputFiles(), document));
+
+        // write the product path group
+        if (configFile.getProductPath() != null) {
+          PGEGroup productPathGroup = new PGEGroup(PRODUCT_PATH_GROUP);
+          productPathGroup.addScalar(configFile.getProductPath());
+          root.appendChild(getGroupElement(productPathGroup, document));
+        }
+
+        // write the monitor level group
+        root.appendChild(getGroupElement(configFile.getMonitorLevelGroup(),
+            document));
+
+        // write the monitor group
+        if (configFile.getMonitorFilenameFormat() != null
+            && configFile.getMonitorPath() != null) {
+          PGEGroup monitorGroup = new PGEGroup(MONITOR_GROUP);
+          monitorGroup.addScalar(configFile.getMonitorPath());
+          monitorGroup.addScalar(configFile.getMonitorFilenameFormat());
+          root.appendChild(getGroupElement(monitorGroup, document));
+        }
+
+        // write the pge specific groups
+        for (Iterator i = configFile.getPgeSpecificGroups().keySet().iterator(); i
+            .hasNext();) {
+          String pgeSpecificGroupName = (String) i.next();
+          PGEGroup pgeSpecificGroup = (PGEGroup) configFile
+              .getPgeSpecificGroups().get(pgeSpecificGroupName);
+
+          root.appendChild(getGroupElement(pgeSpecificGroup, document));
+        }
+
+      }
+
+      return document;
+
+    } catch (ParserConfigurationException pce) {
+      pce.printStackTrace();
+      LOG.log(Level.WARNING, "Error generating pge configuration file!: "
+          + pce.getMessage());
+      throw new Exception("Error generating pge configuration file!: "
+          + pce.getMessage());
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+
+  }
+
+  private Element getGroupElement(PGEGroup group, Document document)
+      throws Exception {
+    Element groupElem = document.createElement(GROUP_TAG_NAME);
+    groupElem.setAttribute(NAME_ATTR, group.getName());
+
+    if (group.getNumScalars() > 0) {
+      for (Iterator i = group.getScalars().keySet().iterator(); i.hasNext();) {
+        String scalarName = (String) i.next();
+        PGEScalar scalar = group.getScalar(scalarName);
+
+        Element scalarElem = document.createElement(SCALAR_TAG_NAME);
+        scalarElem.setAttribute(NAME_ATTR, scalar.getName());
+
+        if (scalar.getValue() == null) {
+          throw new Exception("Attempt to write null value for scalar: ["
+              + scalarName + "] to PGE config file!");
+        }
+
+        if (urlEncoding) {
+          try {
+            scalarElem.appendChild(document.createTextNode(URLEncoder.encode(
+                scalar.getValue(), "UTF-8")));
+          } catch (UnsupportedEncodingException e) {
+            LOG.log(Level.WARNING,
+                "Error creating text node for scalar element: "
+                    + scalar.getName() + " in pge group: " + group.getName()
+                    + " Message: " + e.getMessage());
+          }
+
+        } else {
+          scalarElem.appendChild(document.createTextNode(scalar.getValue()));
+        }
+
+        groupElem.appendChild(scalarElem);
+      }
+
+    }
+
+    if (group.getNumVectors() > 0) {
+      for (Iterator i = group.getVectors().keySet().iterator(); i.hasNext();) {
+        String vectorName = (String) i.next();
+        PGEVector vector = group.getVector(vectorName);
+
+        Element vectorElem = document.createElement(VECTOR_TAG_NAME);
+        vectorElem.setAttribute(NAME_ATTR, vector.getName());
+
+        for (Iterator j = vector.getElements().iterator(); j.hasNext();) {
+          String element = (String) j.next();
+
+          if (element == null) {
+            throw new Exception("Attempt to write null value for vector: ["
+                + vectorName + "] to PGE config file!");
+          }
+
+          Element elementElem = document.createElement(VECTOR_ELEMENT_TAG);
+          if (urlEncoding) {
+            try {
+              elementElem.appendChild(document.createTextNode(URLEncoder
+                  .encode(element, "UTF-8")));
+            } catch (UnsupportedEncodingException e) {
+              LOG.log(Level.WARNING,
+                  "Error creating text node for vector element: "
+                      + vector.getName() + " in pge group: " + group.getName()
+                      + " Message: " + e.getMessage());
+            }
+          } else {
+            elementElem.appendChild(document.createTextNode(element));
+          }
+
+          vectorElem.appendChild(elementElem);
+        }
+
+        groupElem.appendChild(vectorElem);
+      }
+    }
+
+    if (group.getNumMatrixs() > 0) {
+      for (Iterator i = group.getMatrixs().keySet().iterator(); i.hasNext();) {
+        String matrixName = (String) i.next();
+        PGEMatrix matrix = group.getMatrix(matrixName);
+
+        Element matrixElem = document.createElement(MATRIX_TAG_NAME);
+        matrixElem.setAttribute(NAME_ATTR, matrix.getName());
+
+        int rowNum = 0;
+        for (Iterator j = matrix.getRows().iterator(); j.hasNext();) {
+          List rowValues = (List) j.next();
+
+          Element rowElem = document.createElement(MATRIX_ROW_TAG);
+
+          int colNum = 0;
+          for (Iterator k = rowValues.iterator(); k.hasNext();) {
+            String colValue = (String) k.next();
+            Element colElem = document.createElement(MATRIX_COL_TAG);
+
+            if (colValue == null) {
+              throw new Exception("Attempt to write null value for matrix: ["
+                  + matrixName + "]: " + "(" + rowNum + "," + colNum + ")");
+            }
+
+            if (urlEncoding) {
+              try {
+                colElem.appendChild(document.createTextNode(URLEncoder.encode(
+                    colValue, "UTF-8")));
+              } catch (UnsupportedEncodingException e) {
+                LOG.log(Level.WARNING,
+                    "Error creating node for matrix element: "
+                        + matrix.getName() + " (" + rowNum + "," + colNum
+                        + ") in pge group: " + group.getName() + " Message: "
+                        + e.getMessage());
+              }
+
+            } else {
+              colElem.appendChild(document.createTextNode(colValue));
+            }
+
+            colNum++;
+          }
+
+          rowNum++;
+        }
+
+        groupElem.appendChild(matrixElem);
+      }
+    }
+
+    if (group.getNumGroups() > 0) {
+      for (Iterator i = group.getGroups().keySet().iterator(); i.hasNext();) {
+        String groupName = (String) i.next();
+        PGEGroup subgroup = group.getGroup(groupName);
+        Element subgroupElem = getGroupElement(subgroup, document);
+        groupElem.appendChild(subgroupElem);
+      }
+
+    }
+
+    return groupElem;
+
+  }
+
+  /**
+   * @return Returns the urlEncoding.
+   */
+  public boolean isUrlEncoding() {
+    return urlEncoding;
+  }
+
+  /**
+   * @param urlEncoding
+   *          The urlEncoding to set.
+   */
+  public void setUrlEncoding(boolean urlEncoding) {
+    this.urlEncoding = urlEncoding;
+  }
+
+  /**
+   * @return Returns the schemaLocation.
+   */
+  public String getSchemaLocation() {
+    return schemaLocation;
+  }
+
+  /**
+   * @param schemaLocation
+   *          The schemaLocation to set.
+   */
+  public void setSchemaLocation(String schemaLocation) {
+    this.schemaLocation = schemaLocation;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigurationFile.java b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigurationFile.java
new file mode 100644
index 0000000..b98bd0a
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEConfigurationFile.java
@@ -0,0 +1,235 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+//OCO imports
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 
+ * <p>
+ * A configuration file to record input similar to HDF format. The configuration
+ * file is a set of named {@link PGEGroup}s.
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PGEConfigurationFile implements PGEConfigFileKeys {
+
+  /* the name of the PGE that uses this configuration file */
+  private PGEScalar pgeName = null;
+
+  /* the list of data product files for tihs PGE */
+  private PGEGroup inputProductFiles = null;
+
+  /* the list of static file identification files */
+  private PGEGroup staticFileIdentificationFiles = null;
+
+  /* the list of ancillary files identified by the PCS */
+  private PGEGroup dynamicAuxiliaryInputFiles = null;
+
+  /*
+   * the list of ancillary files that are not used by the PGE directly, but are
+   * recorded in the AncillaryDataDescriptors metadata element
+   */
+  private PGEGroup recordedAuxiliaryInputFiles = null;
+
+  /* the location to put any output products */
+  private PGEScalar productPath = null;
+
+  /* the location to which to save monitor files */
+  private PGEScalar monitorPath = null;
+
+  /* the filename format of the monitor files */
+  private PGEScalar monitorFilenameFormat = null;
+
+  private PGEGroup monitorLevelGroup = null;
+
+  /* the pge specific groups in the configuration file */
+  private Map<String, PGEGroup> pgeSpecificGroups = null;
+
+  /**
+   * <p>
+   * Constructs a new PGEConfigurationFile with no groups.
+   * </p>
+   */
+  public PGEConfigurationFile() {
+    this.pgeSpecificGroups = new HashMap<String, PGEGroup>();
+    this.inputProductFiles = new PGEGroup(INPUT_PRODUCT_FILES_GROUP);
+    this.staticFileIdentificationFiles = new PGEGroup(SFIF_FILE_GROUP);
+    this.dynamicAuxiliaryInputFiles = new PGEGroup(
+        DYNAMIC_AUX_INPUT_FILES_GROUP);
+    this.recordedAuxiliaryInputFiles = new PGEGroup(
+        RECORDED_AUX_INPUT_FILES_GROUP);
+    this.monitorLevelGroup = new PGEGroup(MONITOR_LEVEL_GROUP);
+  }
+
+  /**
+   * @return the pgeName
+   */
+  public PGEScalar getPgeName() {
+    return pgeName;
+  }
+
+  /**
+   * @param pgeName
+   *          the pgeName to set
+   */
+  public void setPgeName(PGEScalar pgeName) {
+    this.pgeName = pgeName;
+  }
+
+  /**
+   * @return the inputProductFiles
+   */
+  public PGEGroup getInputProductFiles() {
+    return inputProductFiles;
+  }
+
+  /**
+   * @param inputProductFiles
+   *          the inputProductFiles to set
+   */
+  public void setInputProductFiles(PGEGroup inputProductFiles) {
+    this.inputProductFiles = inputProductFiles;
+  }
+
+  /**
+   * @return the staticFileIdentificationFiles
+   */
+  public PGEGroup getStaticFileIdentificationFiles() {
+    return staticFileIdentificationFiles;
+  }
+
+  /**
+   * @param staticFileIdentificationFiles
+   *          the staticFileIdentificationFiles to set
+   */
+  public void setStaticFileIdentificationFiles(
+      PGEGroup staticFileIdentificationFiles) {
+    this.staticFileIdentificationFiles = staticFileIdentificationFiles;
+  }
+
+  /**
+   * @return the dynamicAuxiliaryInputFiles
+   */
+  public PGEGroup getDynamicAuxiliaryInputFiles() {
+    return dynamicAuxiliaryInputFiles;
+  }
+
+  /**
+   * @param dynamicAuxiliaryInputFiles
+   *          the dynamicAuxiliaryInputFiles to set
+   */
+  public void setDynamicAuxiliaryInputFiles(PGEGroup dynamicAuxiliaryInputFiles) {
+    this.dynamicAuxiliaryInputFiles = dynamicAuxiliaryInputFiles;
+  }
+
+  /**
+   * @return the recordedAuxiliaryInputFiles
+   */
+  public PGEGroup getRecordedAuxiliaryInputFiles() {
+    return recordedAuxiliaryInputFiles;
+  }
+
+  /**
+   * @param recordedAuxiliaryInputFiles
+   *          the recordedAuxiliaryInputFiles to set
+   */
+  public void setRecordedAuxiliaryInputFiles(
+      PGEGroup recordedAuxiliaryInputFiles) {
+    this.recordedAuxiliaryInputFiles = recordedAuxiliaryInputFiles;
+  }
+
+  /**
+   * @return the productPath
+   */
+  public PGEScalar getProductPath() {
+    return productPath;
+  }
+
+  /**
+   * @param productPath
+   *          the productPath to set
+   */
+  public void setProductPath(PGEScalar productPath) {
+    this.productPath = productPath;
+  }
+
+  /**
+   * @return the monitorPath
+   */
+  public PGEScalar getMonitorPath() {
+    return monitorPath;
+  }
+
+  /**
+   * @param monitorPath
+   *          the monitorPath to set
+   */
+  public void setMonitorPath(PGEScalar monitorPath) {
+    this.monitorPath = monitorPath;
+  }
+
+  /**
+   * @return the monitorFilenameFormat
+   */
+  public PGEScalar getMonitorFilenameFormat() {
+    return monitorFilenameFormat;
+  }
+
+  /**
+   * @param monitorFilenameFormat
+   *          the monitorFilenameFormat to set
+   */
+  public void setMonitorFilenameFormat(PGEScalar monitorFilenameFormat) {
+    this.monitorFilenameFormat = monitorFilenameFormat;
+  }
+
+  /**
+   * @return the monitorLevelGroup
+   */
+  public PGEGroup getMonitorLevelGroup() {
+    return monitorLevelGroup;
+  }
+
+  /**
+   * @param monitorLevelGroup
+   *          the monitorLevelGroup to set
+   */
+  public void setMonitorLevelGroup(PGEGroup monitorLevelGroup) {
+    this.monitorLevelGroup = monitorLevelGroup;
+  }
+
+  /**
+   * @return the pgeSpecificGroups
+   */
+  public Map<String, PGEGroup> getPgeSpecificGroups() {
+    return pgeSpecificGroups;
+  }
+
+  /**
+   * @param pgeSpecificGroups
+   *          the pgeSpecificGroups to set
+   */
+  public void setPgeSpecificGroups(Map<String, PGEGroup> pgeSpecificGroups) {
+    this.pgeSpecificGroups = pgeSpecificGroups;
+  }
+  
+}
diff --git a/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEDataHandler.java b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEDataHandler.java
new file mode 100644
index 0000000..1915b6b
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEDataHandler.java
@@ -0,0 +1,253 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+//JDK imports
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * 
+ * <p>
+ * A SAX-based event handler to parse PGE data out of an underlying XML file.
+ * </p>
+ * 
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class PGEDataHandler extends DefaultHandler implements PGEDataParseKeys {
+
+  /* our log stream */
+  private static final Logger LOG = Logger.getLogger(PGEDataHandler.class
+      .getName());
+
+  /* scalars to be set as tags are encountered */
+  private Map scalars = new HashMap();
+
+  /* vectors to be set as tags are encountered */
+  private Map vectors = new HashMap();
+
+  /* matrices to be set as tags are encountered */
+  private Map matrices = new HashMap();
+
+  /* the status of the parse handler */
+  private int parseStatus = UNSET;
+
+  private boolean vecElement;
+
+  private boolean matrixElement;
+
+  private PGEScalar currentScalar = null;
+
+  private PGEVector currentVector = null;
+
+  private PGEMatrix currentMatrix = null;
+
+  private StringBuffer charBuf;
+
+  // needed for parsing matrix
+  private int currentRow = 0;
+
+  private int currentCol = 0;
+
+  public PGEDataHandler() {
+    vecElement = false;
+    matrixElement = false;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
+   * java.lang.String, java.lang.String, org.xml.sax.Attributes)
+   */
+  public void startElement(String uri, String localName, String qName,
+      Attributes attributes) throws SAXException {
+    if (notParsing()) {
+      // only care about if it's a scalar/vector or matrix
+      if (qName.equals(SCALAR_TAG_NAME)) {
+        parseStatus = PARSING_SCALAR;
+        currentScalar = new PGEScalar();
+        currentScalar.setName(attributes.getValue(NAME_ATTR));
+        charBuf = new StringBuffer();
+      } else if (qName.equals(VECTOR_TAG_NAME)) {
+        parseStatus = PARSING_VEC;
+        currentVector = new PGEVector();
+        currentVector.setName(attributes.getValue(NAME_ATTR));
+      } else if (qName.equals(MATRIX_TAG_NAME)) {
+        parseStatus = PARSING_MATRIX;
+        currentMatrix = new PGEMatrix(attributes.getValue(NAME_ATTR), Integer
+            .parseInt(attributes.getValue(ROWS_ATTR)), Integer
+            .parseInt(attributes.getValue(COLS_ATTR)));
+      }
+    } else if (isParsingScalar()) {
+      // shouldn't encountere another tag here
+      throw new SAXException("Parsing scalar: [" + this.currentScalar.getName()
+          + "]: Should not encounter another tag within");
+    } else if (isParsingVector()) {
+      if (qName.equals(VECTOR_ELEMENT_TAG)) {
+        vecElement = true;
+        charBuf = new StringBuffer();
+      }
+
+    } else if (isParsingMatrix()) {
+      if (qName.equals(MATRIX_COL_TAG)) {
+        matrixElement = true;
+        charBuf = new StringBuffer();
+      }
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String,
+   * java.lang.String, java.lang.String)
+   */
+  public void endElement(String uri, String localName, String qName)
+      throws SAXException {
+    if (qName.equals(SCALAR_TAG_NAME)) {
+      this.currentScalar.setValue(this.charBuf.toString());
+      this.scalars.put(this.currentScalar.getName(), this.currentScalar);
+      clearCharBuf();
+      parseStatus = UNSET;
+    } else if (qName.equals(VECTOR_ELEMENT_TAG)) {
+      this.currentVector.getElements().add(this.charBuf.toString());
+      clearCharBuf();
+      this.vecElement = false;
+    } else if (qName.equals(VECTOR_TAG_NAME)) {
+      // add the vector
+      if (this.currentVector != null) {
+        this.vectors.put(this.currentVector.getName(), this.currentVector);
+        parseStatus = UNSET;
+      }
+    } else if (qName.equals(MATRIX_TAG_NAME)) {
+      if (this.currentMatrix != null) {
+        this.matrices.put(this.currentMatrix.getName(), this.currentMatrix);
+
+        parseStatus = UNSET;
+        this.currentCol = 0;
+        this.currentRow = 0;
+      }
+    } else if (qName.equals(MATRIX_ROW_TAG)) {
+      this.currentRow++;
+      this.currentCol = 0;
+    } else if (qName.equals(MATRIX_COL_TAG)) {
+      this.currentMatrix.addValue(this.charBuf.toString(), this.currentRow,
+          this.currentCol);
+      this.currentCol++;
+      clearCharBuf();
+      this.matrixElement = false;
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
+   */
+  public void characters(char[] ch, int start, int length) throws SAXException {
+    /*
+     * String val = new String(ch, start, length).trim(); if(!val.equals("")){
+     * this.charBuf.append(val); }
+     */
+    if (isParsingScalar() || isParsingVectorElement()
+        || isParsingMatrixElement()) {
+      this.charBuf.append(ch, start, length);
+    }
+  }
+
+  /**
+   * @return the matrices
+   */
+  public Map getMatrices() {
+    return matrices;
+  }
+
+  /**
+   * @param matrices
+   *          the matrices to set
+   */
+  public void setMatrices(Map matrices) {
+    this.matrices = matrices;
+  }
+
+  /**
+   * @return the scalars
+   */
+  public Map getScalars() {
+    return scalars;
+  }
+
+  /**
+   * @param scalars
+   *          the scalars to set
+   */
+  public void setScalars(Map scalars) {
+    this.scalars = scalars;
+  }
+
+  /**
+   * @return the vectors
+   */
+  public Map getVectors() {
+    return vectors;
+  }
+
+  /**
+   * @param vectors
+   *          the vectors to set
+   */
+  public void setVectors(Map vectors) {
+    this.vectors = vectors;
+  }
+
+  public boolean isParsingScalar() {
+    return parseStatus == PARSING_SCALAR;
+  }
+
+  public boolean isParsingVector() {
+    return parseStatus == PARSING_VEC;
+  }
+
+  public boolean isParsingMatrix() {
+    return parseStatus == PARSING_MATRIX;
+  }
+
+  public boolean isParsingMatrixElement() {
+    return matrixElement;
+  }
+
+  public boolean isParsingVectorElement() {
+    return vecElement;
+  }
+
+  public boolean notParsing() {
+    return parseStatus == UNSET;
+  }
+
+  private void clearCharBuf() {
+    this.charBuf.setLength(0);
+    this.charBuf = null;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEDataParseKeys.java b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEDataParseKeys.java
new file mode 100644
index 0000000..795e063
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEDataParseKeys.java
@@ -0,0 +1,59 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+/**
+ * 
+ * <p>
+ * A collection of metadata keys relating to the {@link PGEDataHandler}
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface PGEDataParseKeys {
+
+  public static final int PARSING_VEC = -10;
+
+  public static final int PARSING_SCALAR = -20;
+
+  public static final int PARSING_MATRIX = -30;
+
+  public static final int UNSET = -1;
+
+  public static final String GROUP_TAG_NAME = "group";
+
+  public static final String SCALAR_TAG_NAME = "scalar";
+
+  public static final String VECTOR_TAG_NAME = "vector";
+
+  public static final String MATRIX_TAG_NAME = "matrix";
+
+  public static final String PGE_INPUT_TAG_NAME = "input";
+
+  public static final String VECTOR_ELEMENT_TAG = "element";
+
+  public static final String MATRIX_ROW_TAG = "tr";
+
+  public static final String MATRIX_COL_TAG = "td";
+
+  public static final String NAME_ATTR = "name";
+
+  public static final String ROWS_ATTR = "rows";
+
+  public static final String COLS_ATTR = "cols";
+}
diff --git a/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEGroup.java b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEGroup.java
new file mode 100644
index 0000000..b4cb93e
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEGroup.java
@@ -0,0 +1,211 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+//JDK imports
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>
+ * A PGEGroup is a named set of named {@link PGEVector}s, {@link PGEScalar}s and
+ * {@link PGEMatrix}s.
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PGEGroup {
+
+  /* the name of the PGEGroup */
+  private String name = null;
+
+  /* the HashMap of PGEScalars */
+  private Map<String, PGEScalar> scalars = null;
+
+  /* the HashMap of PGEVectors */
+  private Map<String, PGEVector> vectors = null;
+
+  /* the HashMap of PGEMatrixs */
+  private Map<String, PGEMatrix> matrixs = null;
+
+  /* the HashMap of PGEGroups */
+  private Map<String, PGEGroup> groups = null;
+
+  /**
+   * <p>
+   * Constructs a new PGEGroup with the given name
+   * </p>
+   */
+  public PGEGroup(String name) {
+    this.name = name;
+    this.scalars = new HashMap<String, PGEScalar>();
+    this.vectors = new HashMap<String, PGEVector>();
+    this.matrixs = new HashMap<String, PGEMatrix>();
+    this.groups = new HashMap<String, PGEGroup>();
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return the scalars
+   */
+  public Map<String, PGEScalar> getScalars() {
+    return scalars;
+  }
+
+  /**
+   * @param scalars
+   *          the scalars to set
+   */
+  public void setScalars(Map<String, PGEScalar> scalars) {
+    this.scalars = scalars;
+  }
+
+  /**
+   * @return the vectors
+   */
+  public Map<String, PGEVector> getVectors() {
+    return vectors;
+  }
+
+  /**
+   * @param vectors
+   *          the vectors to set
+   */
+  public void setVectors(Map<String, PGEVector> vectors) {
+    this.vectors = vectors;
+  }
+
+  /**
+   * @return the matrixs
+   */
+  public Map<String, PGEMatrix> getMatrixs() {
+    return matrixs;
+  }
+
+  /**
+   * @param matrixs
+   *          the matrixs to set
+   */
+  public void setMatrixs(Map<String, PGEMatrix> matrixs) {
+    this.matrixs = matrixs;
+  }
+
+  /**
+   * @return the groups
+   */
+  public Map<String, PGEGroup> getGroups() {
+    return groups;
+  }
+
+  /**
+   * @param groups
+   *          the groups to set
+   */
+  public void setGroups(Map<String, PGEGroup> groups) {
+    this.groups = groups;
+  }
+
+  public void addScalar(PGEScalar scalar) {
+    if (this.scalars != null && !this.scalars.containsKey(scalar.getName())) {
+      this.scalars.put(scalar.getName(), scalar);
+    }
+  }
+
+  public void addVector(PGEVector vector) {
+    if (this.vectors != null && !this.vectors.containsKey(vector.getName())) {
+      this.vectors.put(vector.getName(), vector);
+    }
+  }
+
+  public void addMatrix(PGEMatrix matrix) {
+    if (this.matrixs != null && !this.matrixs.containsKey(matrix.getName())) {
+      this.matrixs.put(matrix.getName(), matrix);
+    }
+  }
+
+  public PGEScalar getScalar(String name) {
+    if (this.scalars != null) {
+      return this.scalars.get(name);
+    } else
+      return null;
+  }
+
+  public PGEVector getVector(String name) {
+    if (this.vectors != null) {
+      return this.vectors.get(name);
+    } else
+      return null;
+  }
+
+  public PGEMatrix getMatrix(String name) {
+    if (this.matrixs != null) {
+      return this.matrixs.get(name);
+    } else
+      return null;
+  }
+
+  public PGEGroup getGroup(String name) {
+    if (this.groups != null) {
+      return this.groups.get(name);
+    } else
+      return null;
+  }
+
+  public int getNumScalars() {
+    if (this.scalars != null) {
+      return this.scalars.size();
+    } else
+      return 0;
+  }
+
+  public int getNumVectors() {
+    if (this.vectors != null) {
+      return this.vectors.size();
+    } else
+      return 0;
+  }
+
+  public int getNumMatrixs() {
+    if (this.matrixs != null) {
+      return this.matrixs.size();
+    } else
+      return 0;
+  }
+
+  public int getNumGroups() {
+    if (this.groups != null) {
+      return this.groups.size();
+    } else
+      return 0;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEMatrix.java b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEMatrix.java
new file mode 100644
index 0000000..1f6362b
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEMatrix.java
@@ -0,0 +1,133 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * 
+ * <p>
+ * A PGEMatrix is a set of rows and columns with values in each cell defined by
+ * a row number and column number.
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PGEMatrix {
+
+  private List<List<Object>> rows;
+
+  private int numCols;
+
+  private String name;
+
+  /**
+   * <p>
+   * Constructs a new PGEMatrix with no rows or columns.
+   * </p>
+   */
+  public PGEMatrix() {
+    this(null, 0, 0);
+  }
+
+  /**
+   * <p>
+   * Constructs a new PGEMatrix with the specified <code>numrows</code> and
+   * <code>numcols</code>.
+   * 
+   * @param numrows
+   *          The number of rows in the matrix.
+   * @param numcols
+   *          The number of columns for each row in the matrix.
+   */
+  public PGEMatrix(String name, int numrows, int numcols) {
+    super();
+    this.rows = new Vector<List<Object>>(numrows);
+    this.numCols = numcols;
+    this.name = name;
+
+    for (int i = 0; i < numrows; i++) {
+      List<Object> colVector = new Vector<Object>(numcols);
+      this.rows.add(i, colVector);
+    }
+  }
+
+  public void addValue(Object value, int row, int col) {
+    if ((row > this.rows.size() || row < 0) || (col > this.numCols || col < 0)) {
+      return;
+    }
+
+    ((List<Object>) this.rows.get(row)).add(col, value);
+  }
+
+  public Object getValue(int row, int col) {
+    if ((row > this.rows.size() || row < 0) || (col > this.numCols || col < 0)) {
+      return null;
+    }
+
+    return ((List<Object>) this.rows.get(row)).get(col);
+  }
+
+  /**
+   * @return Returns the rows.
+   */
+  public List<List<Object>> getRows() {
+    return this.rows;
+  }
+
+  /**
+   * @param rows
+   *          The rows to set.
+   */
+  public void setRows(List<List<Object>> rows) {
+    this.rows = rows;
+  }
+
+  /**
+   * @return Returns the name.
+   */
+  public String getName() {
+    return this.name;
+  }
+
+  /**
+   * @param name
+   *          The name to set.
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return Returns the numCols.
+   */
+  public int getNumCols() {
+    return this.numCols;
+  }
+
+  /**
+   * @param numCols
+   *          The numCols to set.
+   */
+  public void setNumCols(int numCols) {
+    this.numCols = numCols;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEScalar.java b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEScalar.java
new file mode 100644
index 0000000..124101a
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEScalar.java
@@ -0,0 +1,82 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+/**
+ * 
+ * <p>
+ * A PGE Scalar represents a named unit of information. In essence, it is a
+ * name/value pair.
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PGEScalar {
+
+  private String name;
+
+  private String value;
+
+  /**
+     * 
+     */
+  public PGEScalar() {
+    super();
+  }
+
+  /**
+   * @param name
+   * @param value
+   */
+  public PGEScalar(String name, String value) {
+    super();
+    this.name = name;
+    this.value = value;
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return the value
+   */
+  public String getValue() {
+    return value;
+  }
+
+  /**
+   * @param value
+   *          the value to set
+   */
+  public void setValue(String value) {
+    this.value = value;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEVector.java b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEVector.java
new file mode 100644
index 0000000..1497cfa
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEVector.java
@@ -0,0 +1,86 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * 
+ * <p>
+ * A PGEVector is a dynamic set of information, coupled with a name. The
+ * information may include number, or string data.
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PGEVector {
+
+  private String name;
+
+  private List<Object> elements;
+
+  /**
+   * @param name
+   * @param elements
+   */
+  public PGEVector(String name, List<Object> elements) {
+    super();
+    this.name = name;
+    this.elements = elements;
+  }
+
+  /**
+   * 
+   */
+  public PGEVector() {
+    this(null, new Vector<Object>());
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return the elements
+   */
+  public List<Object> getElements() {
+    return elements;
+  }
+
+  /**
+   * @param elements
+   *          the elements to set
+   */
+  public void setElements(List<Object> elements) {
+    this.elements = elements;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEXMLFileUtils.java b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEXMLFileUtils.java
new file mode 100644
index 0000000..ab2cdb1
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/java/org/apache/oodt/pcs/input/PGEXMLFileUtils.java
@@ -0,0 +1,365 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+//OODT imports
+import org.apache.oodt.commons.xml.DOMUtil;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * <p>
+ * Low-level reading API to get {@link PGEVector}s, {@link PGEScalar}s, and
+ * {@link PGEMatrix}s from underlying OCO XML files.
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public final class PGEXMLFileUtils {
+
+  /* our log stream */
+  private static final Logger LOG = Logger.getLogger(PGEXMLFileUtils.class
+      .getName());
+
+  public static Map getMatrixsAsMap(Element group)
+      throws PGEConfigFileException {
+    // get the nodelist for the matrixs
+    NodeList matrixs = group.getElementsByTagName("matrix");
+
+    // if it's null, return null
+    if (matrixs == null) {
+      return null;
+    }
+
+    Map matrixMap = new HashMap(matrixs.getLength());
+
+    // for each matrix in the list, create a PGEMatrix with the name
+    // attribute and the appropriate value
+
+    for (int i = 0; i < matrixs.getLength(); i++) {
+      Element matrix = (Element) matrixs.item(i);
+
+      // get the name of the matrix
+      String matrixName = matrix.getAttribute("name");
+
+      // get the number of cols
+      NodeList rowNodeList = matrix.getElementsByTagName("tr");
+
+      // there has to be at least one 1
+      if (rowNodeList == null
+          || (rowNodeList != null && rowNodeList.getLength() <= 0)) {
+        throw new PGEConfigFileException(
+            "there must be at least one row in a matrix!");
+      }
+
+      PGEMatrix pgeMatrix = new PGEMatrix();
+      pgeMatrix.setName(matrixName);
+
+      for (int j = 0; j < rowNodeList.getLength(); j++) {
+        Element rowElem = (Element) rowNodeList.item(j);
+
+        // get the number of cols
+        NodeList colNodeList = rowElem.getElementsByTagName("td");
+
+        // there must be at least one colum in each row
+        if (colNodeList == null
+            || (colNodeList != null && colNodeList.getLength() <= 0)) {
+          throw new PGEConfigFileException(
+              "there must be at least one column a matrix row!");
+        }
+
+        if (pgeMatrix.getNumCols() == 0) {
+          // then set it
+          pgeMatrix.setNumCols(colNodeList.getLength());
+        }
+
+        List colList = new Vector(colNodeList.getLength());
+
+        for (int k = 0; k < colNodeList.getLength(); k++) {
+          Element colElement = (Element) colNodeList.item(k);
+          colList.add(DOMUtil.getSimpleElementText(colElement));
+        }
+
+        pgeMatrix.getRows().add(colList);
+      }
+
+      matrixMap.put(pgeMatrix.getName(), pgeMatrix);
+    }
+    return matrixMap;
+  }
+
+  public static List getMatrixs(Element group) throws PGEConfigFileException {
+    // get the nodelist for the matrixs
+    NodeList matrixs = group.getElementsByTagName("matrix");
+
+    // if it's null, return null
+    if (matrixs == null) {
+      return null;
+    }
+
+    List matrixList = new Vector(matrixs.getLength());
+
+    // for each matrix in the list, create a PGEMatrix with the name
+    // attribute and the appropriate value
+
+    for (int i = 0; i < matrixs.getLength(); i++) {
+      Element matrix = (Element) matrixs.item(i);
+
+      // get the name of the matrix
+      String matrixName = matrix.getAttribute("name");
+
+      // get the number of cols
+      NodeList rowNodeList = matrix.getElementsByTagName("tr");
+
+      // there has to be at least one 1
+      if (rowNodeList == null
+          || (rowNodeList != null && rowNodeList.getLength() <= 0)) {
+        throw new PGEConfigFileException(
+            "there must be at least one row in a matrix!");
+      }
+
+      PGEMatrix pgeMatrix = new PGEMatrix();
+      pgeMatrix.setName(matrixName);
+
+      for (int j = 0; j < rowNodeList.getLength(); j++) {
+        Element rowElem = (Element) rowNodeList.item(j);
+
+        // get the number of cols
+        NodeList colNodeList = rowElem.getElementsByTagName("td");
+
+        // there must be at least one colum in each row
+        if (colNodeList == null
+            || (colNodeList != null && colNodeList.getLength() <= 0)) {
+          throw new PGEConfigFileException(
+              "there must be at least one column a matrix row!");
+        }
+
+        if (pgeMatrix.getNumCols() == 0) {
+          // then set it
+          pgeMatrix.setNumCols(colNodeList.getLength());
+        }
+
+        List colList = new Vector(colNodeList.getLength());
+
+        for (int k = 0; k < colNodeList.getLength(); k++) {
+          Element colElement = (Element) colNodeList.item(k);
+          colList.add(DOMUtil.getSimpleElementText(colElement));
+        }
+
+        pgeMatrix.getRows().add(colList);
+      }
+
+      matrixList.add(pgeMatrix);
+    }
+
+    return matrixList;
+  }
+
+  public static Map getScalarsAsMap(Element group)
+      throws PGEConfigFileException {
+    // get the nodelist for scalars
+    NodeList scalars = group.getElementsByTagName("scalar");
+
+    // if it's null, return null
+    if (scalars == null) {
+      return null;
+    }
+
+    Map scalarMap = new HashMap(scalars.getLength());
+
+    // for each scalar in the list, create a PGEScalar with the name
+    // attribute, and appropriate value
+    for (int i = 0; i < scalars.getLength(); i++) {
+      Element scalar = (Element) scalars.item(i);
+
+      // name of the scalar is in the name attribute
+      String scalarName = scalar.getAttribute("name");
+
+      // get the value of it
+      String scalarValue = DOMUtil.getSimpleElementText(scalar);
+
+      scalarMap.put(scalarName, new PGEScalar(scalarName, scalarValue));
+    }
+
+    return scalarMap;
+  }
+
+  public static List getScalars(Element group) throws PGEConfigFileException {
+    // get the nodelist for scalars
+    NodeList scalars = group.getElementsByTagName("scalar");
+
+    // if it's null, return null
+    if (scalars == null) {
+      return null;
+    }
+
+    List scalarList = new Vector(scalars.getLength());
+
+    // for each scalar in the list, create a PGEScalar with the name
+    // attribute, and appropriate value
+    for (int i = 0; i < scalars.getLength(); i++) {
+      Element scalar = (Element) scalars.item(i);
+
+      // name of the scalar is in the name attribute
+      String scalarName = scalar.getAttribute("name");
+
+      // get the value of it
+      String scalarValue = DOMUtil.getSimpleElementText(scalar);
+
+      scalarList.add(new PGEScalar(scalarName, scalarValue));
+    }
+
+    return scalarList;
+  }
+
+  public static Map getVectorsAsMap(Element group)
+      throws PGEConfigFileException {
+    // get the nodelist for scalars
+    NodeList vectors = group.getElementsByTagName("vector");
+
+    // if it's null, return null
+    if (vectors == null) {
+      return null;
+    }
+
+    Map vectorMap = new HashMap(vectors.getLength());
+
+    // for each vector in the list, create a PGEVector with the name
+    // attribute, and appropriate value
+    for (int i = 0; i < vectors.getLength(); i++) {
+      Element vector = (Element) vectors.item(i);
+
+      // name of the vector is in the name attribute
+      String vectorName = vector.getAttribute("name");
+
+      PGEVector vec = new PGEVector();
+      vec.setName(vectorName);
+
+      // get the nodelist of elements
+      NodeList vecElems = vector.getElementsByTagName("element");
+
+      if (vecElems == null || (vecElems != null && vecElems.getLength() <= 0)) {
+        throw new PGEConfigFileException(
+            "There must be at least one element in a PGEVector!");
+      }
+
+      List vecElemList = new Vector(vecElems.getLength());
+
+      for (int j = 0; j < vecElems.getLength(); j++) {
+        Element vecElem = (Element) vecElems.item(j);
+        vecElemList.add(DOMUtil.getSimpleElementText(vecElem));
+      }
+
+      vec.setElements(vecElemList);
+      vectorMap.put(vec.getName(), vec);
+    }
+
+    return vectorMap;
+  }
+
+  public static List getVectors(Element group) throws PGEConfigFileException {
+    // get the nodelist for scalars
+    NodeList vectors = group.getElementsByTagName("vector");
+
+    // if it's null, return null
+    if (vectors == null) {
+      return null;
+    }
+
+    List vectorList = new Vector(vectors.getLength());
+
+    // for each vector in the list, create a PGEVector with the name
+    // attribute, and appropriate value
+    for (int i = 0; i < vectors.getLength(); i++) {
+      Element vector = (Element) vectors.item(i);
+
+      // name of the vector is in the name attribute
+      String vectorName = vector.getAttribute("name");
+
+      PGEVector vec = new PGEVector();
+      vec.setName(vectorName);
+
+      // get the nodelist of elements
+      NodeList vecElems = vector.getElementsByTagName("element");
+
+      if (vecElems == null || (vecElems != null && vecElems.getLength() <= 0)) {
+        throw new PGEConfigFileException(
+            "There must be at least one element in a PGEVector!");
+      }
+
+      List vecElemList = new Vector(vecElems.getLength());
+
+      for (int j = 0; j < vecElems.getLength(); j++) {
+        Element vecElem = (Element) vecElems.item(j);
+        vecElemList.add(DOMUtil.getSimpleElementText(vecElem));
+      }
+
+      vec.setElements(vecElemList);
+      vectorList.add(vec);
+    }
+
+    return vectorList;
+  }
+
+  public static Document getDocumentRoot(String xmlFile) {
+    // open up the XML file
+    DocumentBuilderFactory factory = null;
+    DocumentBuilder parser = null;
+    Document document = null;
+    InputSource inputSource = null;
+
+    InputStream xmlInputStream = null;
+
+    try {
+      xmlInputStream = new File(xmlFile).toURL().openStream();
+    } catch (IOException e) {
+      LOG.log(Level.WARNING, "IOException when getting input stream from ["
+          + xmlFile + "]: returning null document root");
+      return null;
+    }
+
+    inputSource = new InputSource(xmlInputStream);
+
+    try {
+      factory = DocumentBuilderFactory.newInstance();
+      parser = factory.newDocumentBuilder();
+      document = parser.parse(inputSource);
+    } catch (Exception e) {
+      LOG.warning("Unable to parse xml file [" + xmlFile + "]." + "Reason is ["
+          + e + "]");
+      return null;
+    }
+
+    return document;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/input/src/main/resources/pge-config-example.xml b/0.8.1-rc1/pcs/input/src/main/resources/pge-config-example.xml
new file mode 100644
index 0000000..f0d693b
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/resources/pge-config-example.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<!-- Configuration file for running PGE Test -->
+<!-- Created by mattmann -->
+<!-- Created on November 11, 2005 at 09:22:00 -->
+<!-- GDS Build n.mm.pp -->
+<!-- Test name: testPGEConfigFileReader -->
+
+<input>
+   <group name="PGENameGroup">
+     <scalar name="PGEName">Test PGE</scalar>
+   </group>
+   
+   <group name="InputProductFiles">
+     <scalar name="VCID17Stream">/data/o04521/10/oco_10_200090503_o04521_p125_vcid17_mcf200901051234ops.hdf</scalar>
+     <scalar name="VCID32Stream">/data/o04521/10/oco_10_200090503_o04521_p125_vcid32_mcf200901051234ops.hdf</scalar>
+     <scalar name="VCID33Stream">/data/o04521/10/oco_10_200090503_o04521_p125_vcid33_mcf200901051234ops.hdf</scalar>
+     <scalar name="VCID34Stream">/data/o04521/10/oco_10_200090503_o04521_p125_vcid34_mcf200901051234ops.hdf</scalar>
+   </group>
+
+   <group name="StaticFileIdentificationFiles">
+     <scalar name="SFIF12Stream">/data/o04521/10/oco_10_200090503_o04521_p125_sfif12_mcf200901051234ops.hdf</scalar>
+     <scalar name="SFIF34Stream">/data/o04521/10/oco_10_200090503_o04521_p125_sfif34_mcf200901051234ops.hdf</scalar>
+   </group>
+   
+   <group name="DynamicAuxiliaryInputFiles">
+     <scalar name="AuxStream1">/data/o04521/10/oco_10_200090503_o04521_p125_aux1_mcf200901051234ops.aux</scalar>
+   </group>
+   
+   <group name="RecordedAuxiliaryInputFiles">
+      <scalar name="RecAuxStream1">/data/o04521/10/oco_10_200090503_o04521_p125_raux1_mcf200901051234ops.raux</scalar>
+   </group>
+   
+   <group name="ProductPathGroup">
+      <scalar name="ProductPath">/data</scalar>
+   </group>
+   
+   <group name="MonitorGroup">
+      <scalar name="MonitorPath">/data/monitor</scalar>
+      <scalar name="MonitorFilenameFormat">.monitor</scalar>
+   </group>
+
+   <group name="MonitorLevel">
+      <scalar name="MonIO">High</scalar>
+      <scalar name="MonAlg">Off</scalar>
+      <scalar name="MonControl">Med</scalar>
+   </group>
+   
+   <!--  PGE Specific Info -->
+   
+   <group name="MyPGEInfo">
+     <scalar name="TestScalar1">Scalar1</scalar>
+     <vector name="TestVector1">
+       <element>10</element>
+       <element>test string</element>
+       <element>55.5</element>
+       <element>/data/1/2/3/file.file</element>
+     </vector>
+     
+     <matrix name="TestMatrix1">
+       <tr>
+         <td>55</td>
+         <td>12</td>
+         <td>1</td>
+       </tr>
+        <tr>
+         <td>44</td>
+         <td>33</td>
+         <td>100</td>
+       </tr>    
+     </matrix>
+   </group>
+   
+   
+</input>
diff --git a/0.8.1-rc1/pcs/input/src/main/resources/pge-data-sax-example.xml b/0.8.1-rc1/pcs/input/src/main/resources/pge-data-sax-example.xml
new file mode 100644
index 0000000..f70d4c0
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/main/resources/pge-data-sax-example.xml
@@ -0,0 +1,271 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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 pgedata [
+
+<!--define the internal DTD-->
+  <!ELEMENT pgedata (scalar*,vector*,matrix*)>
+  <!ELEMENT matrix (tr+)>
+  <!ELEMENT tr (td+)>
+  <!ELEMENT td (#PCDATA)>
+  <!ELEMENT scalar (#PCDATA)>
+  <!ATTLIST scalar name CDATA ''>
+  <!ATTLIST matrix name CDATA ''>
+  <!ATTLIST matrix rows CDATA ''>
+  <!ATTLIST matrix cols CDATA ''>
+  <!ELEMENT vector (element*)>
+  <!ATTLIST vector name CDATA ''>
+  <!ELEMENT element (#PCDATA)>
+
+<!--close the DOCTYPE declaration-->
+]>
+
+<pgedata>
+<scalar name="foo">bar</scalar>
+<vector name="solar_degrad_stddev_pixel_strong_co2">
+<element>7.156829408322501e-18</element>
+<element>1.001230034697944e-17</element>
+<element>2.516345810183765e-18</element>
+<element>5.094596673550921e-18</element>
+<element>3.255014963930512e-18</element>
+<element>5.462772487746047e-18</element>
+<element>4.855160146533748e-18</element>
+<element>9.933721983075038e-18</element>
+<element>6.690502587946044e-18</element>
+<element>9.151933719744191e-18</element>
+<element>5.650032685446839e-07</element>
+<element>5.650032683079101e-07</element>
+<element>5.650032675464667e-07</element>
+<element>5.650032673675753e-07</element>
+<element>5.650032682784805e-07</element>
+<element>5.650032672186995e-07</element>
+<element>5.650032673387105e-07</element>
+<element>5.650032679108124e-07</element>
+<element>5.650032677826825e-07</element>
+<element>5.650032673930709e-07</element>
+<element>5.650032675232457e-07</element>
+<element>5.650032685245339e-07</element>
+<element>5.650032680052611e-07</element>
+<element>5.65003268542033e-07</element>
+<element>5.650032679906624e-07</element>
+<element>5.650032673606469e-07</element>
+<element>5.650032675613922e-07</element>
+<element>5.650032683106426e-07</element>
+<element>5.650032689379945e-07</element>
+<element>5.650032676014303e-07</element>
+<element>5.65003266960909e-07</element>
+<element>5.650032677139583e-07</element>
+<element>5.650032674960097e-07</element>
+<element>5.650032681530792e-07</element>
+<element>5.650032675200847e-07</element>
+<element>5.650032686111758e-07</element>
+<element>5.650032686858376e-07</element>
+<element>5.65003268010127e-07</element>
+<element>5.650032682342422e-07</element>
+<element>5.650032678880181e-07</element>
+<element>5.650032682061757e-07</element>
+<element>5.65003267883388e-07</element>
+<element>5.650032675152441e-07</element>
+<element>5.650032682394885e-07</element>
+<element>5.650032674941117e-07</element>
+<element>5.650032684140377e-07</element>
+<element>5.650032683660305e-07</element>
+<element>5.650032682050788e-07</element>
+<element>5.650032687935118e-07</element>
+<element>5.650032683845967e-07</element>
+<element>5.650032676294086e-07</element>
+<element>5.650032679809725e-07</element>
+<element>5.650032676793177e-07</element>
+<element>5.65003268781788e-07</element>
+<element>5.650032684167456e-07</element>
+<element>5.650032680698273e-07</element>
+<element>5.650032682093531e-07</element>
+<element>5.650032668567917e-07</element>
+<element>5.650032684921305e-07</element>
+<element>5.650032678442659e-07</element>
+<element>5.650032683200177e-07</element>
+<element>5.650032674059403e-07</element>
+<element>5.650032675556752e-07</element>
+<element>5.650032672721777e-07</element>
+<element>5.65003268435877e-07</element>
+<element>5.65003268168295e-07</element>
+<element>5.650032672004772e-07</element>
+<element>5.65003268343149e-07</element>
+<element>5.650032672935149e-07</element>
+<element>5.650032673435717e-07</element>
+<element>5.650032676094195e-07</element>
+<element>5.650032684139997e-07</element>
+<element>5.650032685593072e-07</element>
+<element>5.65003268364404e-07</element>
+<element>5.650032679422686e-07</element>
+<element>5.650032675656163e-07</element>
+<element>5.650032684983817e-07</element>
+<element>5.650032677526585e-07</element>
+<element>5.650032675956273e-07</element>
+<element>5.650032687894096e-07</element>
+<element>5.650032678559322e-07</element>
+<element>5.650032682914911e-07</element>
+<element>5.650032679964352e-07</element>
+<element>5.650032684764378e-07</element>
+<element>5.650032674968119e-07</element>
+<element>5.650032681637797e-07</element>
+<element>5.650032681947215e-07</element>
+<element>5.650032678251767e-07</element>
+<element>5.650032690991248e-07</element>
+<element>5.650032690235313e-07</element>
+<element>5.650032680351119e-07</element>
+<element>5.650032676168338e-07</element>
+<element>5.647772123356515e-07</element>
+<element>4.376496495071942e-07</element>
+<element>4.376496497473271e-07</element>
+<element>4.376496497611925e-07</element>
+<element>4.376496496419958e-07</element>
+<element>4.376496499490122e-07</element>
+<element>4.376496491453507e-07</element>
+<element>4.376496496199902e-07</element>
+<element>4.376496496313135e-07</element>
+<element>4.376496493560163e-07</element>
+<element>4.37649649415751e-07</element>
+<element>4.376496487438027e-07</element>
+<element>4.376496490231489e-07</element>
+<element>4.376496487693666e-07</element>
+<element>4.376496497192663e-07</element>
+<element>4.376496495310717e-07</element>
+<element>4.37649648937335e-07</element>
+<element>4.376496500508244e-07</element>
+<element>4.376496494235092e-07</element>
+<element>4.376496487765641e-07</element>
+<element>4.376496502573037e-07</element>
+<element>4.376496491797974e-07</element>
+<element>4.376496499778206e-07</element>
+<element>4.376496500770006e-07</element>
+<element>4.376496494665307e-07</element>
+<element>4.376496491597167e-07</element>
+<element>4.376496489798316e-07</element>
+<element>4.376496494860262e-07</element>
+<element>4.37649649797094e-07</element>
+<element>4.376496497130217e-07</element>
+<element>4.376496486902971e-07</element>
+<element>4.376496495729736e-07</element>
+<element>4.376496496595051e-07</element>
+<element>4.376496499103306e-07</element>
+<element>4.376496500715821e-07</element>
+<element>4.37649648393365e-07</element>
+<element>4.376496484669906e-07</element>
+<element>4.376496492303731e-07</element>
+<element>4.376496495606573e-07</element>
+<element>4.376496490041646e-07</element>
+<element>4.37649649320577e-07</element>
+<element>4.376496495126756e-07</element>
+<element>4.376496494133791e-07</element>
+<element>4.376496502085632e-07</element>
+<element>4.376496503500403e-07</element>
+<element>4.376496494589024e-07</element>
+<element>4.376496498368655e-07</element>
+<element>4.376496500551011e-07</element>
+<element>4.376496497645193e-07</element>
+<element>4.376496500291563e-07</element>
+<element>4.376496502373919e-07</element>
+<element>4.376496509054261e-07</element>
+<element>4.376496493571226e-07</element>
+<element>4.376496494287977e-07</element>
+<element>4.376496480356845e-07</element>
+<element>4.376496498622485e-07</element>
+<element>4.376496492795068e-07</element>
+<element>4.376496493635472e-07</element>
+<element>4.376496495742711e-07</element>
+<element>4.376496492800899e-07</element>
+<element>4.376496486776432e-07</element>
+<element>4.376496491663729e-07</element>
+<element>4.376496487538479e-07</element>
+<element>4.376496505841974e-07</element>
+<element>4.376496494712244e-07</element>
+<element>4.376496507553076e-07</element>
+<element>4.376496496479507e-07</element>
+<element>4.376496489174097e-07</element>
+<element>4.376496506213675e-07</element>
+<element>4.376496492764853e-07</element>
+<element>4.376496503826606e-07</element>
+<element>4.376496497457357e-07</element>
+<element>4.376496500068803e-07</element>
+<element>4.376496491424506e-07</element>
+<element>4.376496490184349e-07</element>
+<element>4.376496499516555e-07</element>
+<element>4.376496508092893e-07</element>
+<element>4.376496497149663e-07</element>
+<element>4.376496490162042e-07</element>
+<element>4.376496497150526e-07</element>
+<element>4.376496496328375e-07</element>
+<element>4.376496508772949e-07</element>
+<element>4.376496494788424e-07</element>
+<element>4.376496495435055e-07</element>
+<element>4.376496488787512e-07</element>
+<element>4.376496496375363e-07</element>
+<element>4.376496496740998e-07</element>
+<element>4.37649649215851e-07</element>
+<element>4.376496489065544e-07</element>
+<element>4.376496492788316e-07</element>
+<element>4.376496490897931e-07</element>
+<element>4.37649649440043e-07</element>
+<element>4.376496498238065e-07</element>
+<element>4.376496494226082e-07</element>
+<element>4.376496497567646e-07</element>
+<element>4.376496493141858e-07</element>
+<element>4.37649648813068e-07</element>
+<element>4.376496501462642e-07</element>
+<element>4.376496497298497e-07</element>
+<element>4.376496492198953e-07</element>
+<element>4.376496503621545e-07</element>
+<element>4.376496508834365e-07</element>
+<element>4.37649649716903e-07</element>
+<element>4.376496497673743e-07</element>
+<element>4.376496492369553e-07</element>
+<element>4.376496488408098e-07</element>
+<element>4.376496497061842e-07</element>
+<element>4.376496492088419e-07</element>
+<element>4.376496505378924e-07</element>
+<element>4.376496500324374e-07</element>
+<element>4.376496505858961e-07</element>
+<element>4.376496483579881e-07</element>
+<element>4.376496492047949e-07</element>
+<element>4.37649650283361e-07</element>
+<element>4.37649649931959e-07</element>
+<element>4.37649650345139e-07</element>
+<element>4.376496499007843e-07</element>
+<element>4.376496490379377e-07</element>
+<element>1.061115853951698e-17</element>
+<element>1.044441840201302e-17</element>
+<element>4.957385254465431e-18</element>
+<element>4.329574642053506e-18</element>
+<element>7.235238887322188e-18</element>
+<element>6.979433064230618e-18</element>
+<element>1.100843453633496e-17</element>
+<element>7.519914554272377e-18</element>
+<element>4.874490654891152e-18</element>
+<element>1.716558331680342e-18</element>
+</vector>
+<matrix name="foomatrix" rows="2" cols="2">
+ <tr>
+   <td>194</td>
+   <td>192</td>
+ </tr>
+ <tr>
+   <td>1</td>
+   <td>2.2</td>
+ </tr>
+</matrix>
+</pgedata>
diff --git a/0.8.1-rc1/pcs/input/src/test/org/apache/oodt/pcs/input/PGEConfigFileReaderTest.java b/0.8.1-rc1/pcs/input/src/test/org/apache/oodt/pcs/input/PGEConfigFileReaderTest.java
new file mode 100644
index 0000000..c3d41d4
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/test/org/apache/oodt/pcs/input/PGEConfigFileReaderTest.java
@@ -0,0 +1,168 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+//JDK imports
+import java.util.Iterator;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * <p>
+ * A TestCase to test the PGEConfigFileReader
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PGEConfigFileReaderTest extends TestCase {
+
+  private PGEConfigurationFile configFile = null;
+
+  protected void setUp() {
+    PGEConfigFileReader reader = new PGEConfigFileReader();
+
+    try {
+      configFile = reader.read(this.getClass().getResource(
+          "pge-config-example.xml"));
+    } catch (PGEConfigFileException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+  }
+
+  public void testPGEName() {
+    assertEquals("The PGE Name: " + configFile.getPgeName().getValue()
+        + " is not equal to TestPGE", "Test PGE", configFile.getPgeName()
+        .getValue());
+  }
+
+  public void testInputProductFiles() {
+    PGEGroup inputProductFiles = configFile.getInputProductFiles();
+
+    assertEquals("There is not 4 input product files!", 4, inputProductFiles
+        .getNumScalars());
+    assertEquals(
+        "The VCID17Stream does not have the correct value!",
+        "/data/o04521/10/oco_10_200090503_o04521_p125_vcid17_mcf200901051234ops.hdf",
+        inputProductFiles.getScalar("VCID17Stream").getValue());
+
+    assertEquals(
+        "The VCID34Stream does not have the correct value!",
+        "/data/o04521/10/oco_10_200090503_o04521_p125_vcid34_mcf200901051234ops.hdf",
+        inputProductFiles.getScalar("VCID34Stream").getValue());
+  }
+
+  public void testSFIFInputFiles() {
+    PGEGroup sfifFiles = configFile.getStaticFileIdentificationFiles();
+
+    assertEquals("There is not 2 sfif files!", 2, sfifFiles.getNumScalars());
+
+    assertEquals(
+        "The SFIF34Stream does not have the correct value!",
+        "/data/o04521/10/oco_10_200090503_o04521_p125_sfif34_mcf200901051234ops.hdf",
+        sfifFiles.getScalar("SFIF34Stream").getValue());
+  }
+
+  public void testDynamicAuxFiles() {
+    PGEGroup dynAuxFiles = configFile.getDynamicAuxiliaryInputFiles();
+
+    assertEquals("There is not 1 dynamic aux file!", 1, dynAuxFiles
+        .getNumScalars());
+
+    assertEquals(
+        "The AuxStream1 does not have the correct value!",
+        "/data/o04521/10/oco_10_200090503_o04521_p125_aux1_mcf200901051234ops.aux",
+        dynAuxFiles.getScalar("AuxStream1").getValue());
+  }
+
+  public void testRecordedAuxFiles() {
+    PGEGroup recAuxFiles = configFile.getRecordedAuxiliaryInputFiles();
+
+    assertEquals("There is not 1 recorded aux file!", 1, recAuxFiles
+        .getNumScalars());
+
+    assertEquals(
+        "The RecAuxStream1 does not have the correct value!",
+        "/data/o04521/10/oco_10_200090503_o04521_p125_raux1_mcf200901051234ops.raux",
+        recAuxFiles.getScalar("RecAuxStream1").getValue());
+  }
+
+  public void testProductPath() {
+    assertEquals("The product path: " + configFile.getProductPath().getValue()
+        + " is not equal to /data", "/data", configFile.getProductPath()
+        .getValue());
+  }
+
+  public void testMonitorPath() {
+    assertEquals("The monitor path: " + configFile.getMonitorPath().getValue()
+        + " is not equal to /data/monitor", "/data/monitor", configFile
+        .getMonitorPath().getValue());
+  }
+
+  public void testMonitorFilenameFormat() {
+    assertEquals("The monitor filename format: "
+        + configFile.getMonitorFilenameFormat().getValue()
+        + " is not equal to .monitor", ".monitor", configFile
+        .getMonitorFilenameFormat().getValue());
+  }
+
+  public void testMonitorLevels() {
+    assertEquals("The MonIO level was not set to High!", "High", configFile
+        .getMonitorLevelGroup().getScalar("MonIO").getValue());
+    assertEquals("The MonAlg level was not set to Off!", "Off", configFile
+        .getMonitorLevelGroup().getScalar("MonAlg").getValue());
+    assertEquals("The MonControl level was not set to Med!", "Med", configFile
+        .getMonitorLevelGroup().getScalar("MonControl").getValue());
+  }
+
+  public void testPGESpecificInfo() {
+
+    PGEGroup pgeSpecific = (PGEGroup) configFile.getPgeSpecificGroups().get(
+        "MyPGEInfo");
+
+    assertNotNull(pgeSpecific);
+
+    // test that the scalar is read
+    assertEquals("The test scalar 1 does not have a value of Scalar1",
+        "Scalar1", pgeSpecific.getScalar("TestScalar1").getValue());
+
+    // test that the vector is read
+    PGEVector testVec = pgeSpecific.getVector("TestVector1");
+
+    String testVal = "/data/1/2/3/file.file";
+    boolean hasValue = false;
+
+    for (Iterator i = testVec.getElements().iterator(); i.hasNext();) {
+      String elem = (String) i.next();
+      if (elem.equals(testVal)) {
+        hasValue = true;
+      }
+    }
+
+    assertTrue("The vector TestVector1 does not have the value " + testVal
+        + "!", hasValue);
+
+    // test that the matrix was read right
+    PGEMatrix testMatrix = pgeSpecific.getMatrix("TestMatrix1");
+
+    // row 1, col 0 should be 44
+    assertEquals("The matrix value isn't 44!", 44, Integer
+        .parseInt((String) testMatrix.getValue(1, 0)));
+  }
+}
diff --git a/0.8.1-rc1/pcs/input/src/test/org/apache/oodt/pcs/input/PGEConfigFileWriterTest.java b/0.8.1-rc1/pcs/input/src/test/org/apache/oodt/pcs/input/PGEConfigFileWriterTest.java
new file mode 100644
index 0000000..3b327a8
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/test/org/apache/oodt/pcs/input/PGEConfigFileWriterTest.java
@@ -0,0 +1,83 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JDK imports
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import org.w3c.dom.Document;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * <p>
+ * A Testcase for the PGEConfigFileWriter.
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PGEConfigFileWriterTest extends TestCase {
+
+  private PGEConfigurationFile configFile = null;
+
+  private PGEConfigFileWriter configFileWriter = null;
+
+  /**
+     * 
+     */
+  public PGEConfigFileWriterTest() {
+    configFile = new PGEConfigurationFile();
+    configFileWriter = new PGEConfigFileWriter(configFile);
+  }
+
+  public void testWriteRead() {
+    configFile.setPgeName(new PGEScalar("PGEName", "fts_sliceipp"));
+
+    Document configFileDoc = null;
+
+    try {
+      configFileDoc = configFileWriter.getConfigFileXml();
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    XMLUtils.writeXmlToStream(configFileDoc, out);
+
+    ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+    PGEConfigFileReader reader = new PGEConfigFileReader();
+
+    PGEConfigurationFile readConfigFile = null;
+
+    try {
+      readConfigFile = reader.read(in);
+    } catch (PGEConfigFileException e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(readConfigFile);
+    assertEquals("fts_sliceipp", readConfigFile.getPgeName().getValue());
+
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/input/src/test/org/apache/oodt/pcs/input/PGEDataHandlerTest.java b/0.8.1-rc1/pcs/input/src/test/org/apache/oodt/pcs/input/PGEDataHandlerTest.java
new file mode 100644
index 0000000..8304be0
--- /dev/null
+++ b/0.8.1-rc1/pcs/input/src/test/org/apache/oodt/pcs/input/PGEDataHandlerTest.java
@@ -0,0 +1,99 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.pcs.input;
+
+//JDK imports
+import java.io.File;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * <p>
+ * Test suite for the {@link PGEDataHandler}
+ * </p>
+ * .
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PGEDataHandlerTest extends TestCase {
+
+  private static final String testFilePath = "./src/main/resources/pge-data-sax-example.xml";
+
+  private static final String expectedVecValSixthElement = "5.462772487746047e-18";
+
+  public void testGetScalars() {
+    PGEDataHandler handler = new PGEDataHandler();
+    doParse(handler);
+    assertNotNull(handler.getScalars());
+    assertNotNull(handler.getScalars().keySet());
+    assertEquals(1, handler.getScalars().keySet().size());
+    assertTrue(handler.getScalars().containsKey("foo"));
+    assertNotNull(handler.getScalars().entrySet());
+    PGEScalar scalar = (PGEScalar) handler.getScalars().get("foo");
+    assertEquals("bar", scalar.getValue());
+
+  }
+
+  public void testGetMatrices() {
+    PGEDataHandler handler = new PGEDataHandler();
+    doParse(handler);
+    assertNotNull(handler.getMatrices());
+    assertNotNull(handler.getMatrices().keySet());
+    assertEquals(1, handler.getMatrices().keySet().size());
+    assertTrue(handler.getMatrices().containsKey("foomatrix"));
+    PGEMatrix matrix = (PGEMatrix) handler.getMatrices().get("foomatrix");
+    assertNotNull(matrix);
+    assertEquals(2, matrix.getNumCols());
+    assertEquals(2, matrix.getRows().size());
+    assertEquals("194", matrix.getValue(0, 0));
+    assertEquals("2.2", matrix.getValue(1, 1));
+  }
+
+  public void testGetVectors() {
+    PGEDataHandler handler = new PGEDataHandler();
+    doParse(handler);
+    assertNotNull(handler.getVectors());
+    assertNotNull(handler.getVectors().keySet());
+    assertEquals(1, handler.getVectors().keySet().size());
+    assertTrue(handler.getVectors().containsKey(
+        "solar_degrad_stddev_pixel_strong_co2"));
+    PGEVector vec = (PGEVector) handler.getVectors().get(
+        "solar_degrad_stddev_pixel_strong_co2");
+    assertNotNull(vec);
+    assertEquals(expectedVecValSixthElement, vec.getElements().get(5));
+
+  }
+
+  private void doParse(PGEDataHandler handler) {
+    SAXParserFactory factory = SAXParserFactory.newInstance();
+    try {
+      // Parse the input
+      SAXParser saxParser = factory.newSAXParser();
+      saxParser.parse(new File(testFilePath), handler);
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail("exception reading data out of: [" + testFilePath + "]: Message: "
+          + e.getMessage());
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/pom.xml b/0.8.1-rc1/pcs/opsui/pom.xml
new file mode 100755
index 0000000..9577bbb
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/pom.xml
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+	<artifactId>pcs-opsui</artifactId>
+	<packaging>war</packaging>
+	<parent>
+       <groupId>org.apache.oodt</groupId>
+       <artifactId>oodt-core</artifactId>
+       <version>0.8.1</version>
+       <relativePath>../../core/pom.xml</relativePath>
+    </parent>
+	<name>Process Control System Operator Interface Webapp</name>
+	<properties>
+		<wicket.version>1.4.17</wicket.version>
+		<jetty.version>6.1.25</jetty.version>
+		<slf4j.version>1.5.8</slf4j.version>
+		<log4j.version>1.2.14</log4j.version>
+	</properties>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.wicket</groupId>
+			<artifactId>wicket</artifactId>
+			<version>${wicket.version}</version>
+		</dependency>
+		<dependency>
+		    <groupId>org.apache.wicket</groupId>
+		    <artifactId>wicket-extensions</artifactId>
+		    <version>${wicket.version}</version>
+		</dependency>
+		<dependency>
+		  <groupId>org.apache.oodt</groupId>
+		  <artifactId>oodt-webapp-components</artifactId>
+		  <version>${project.parent.version}</version>
+		  <exclusions>
+		    <exclusion>
+		      <artifactId>cas-filemgr</artifactId>
+		      <groupId>org.apache.oodt</groupId>
+		    </exclusion>
+		    <exclusion>
+		      <artifactId>cas-workflow</artifactId>
+		      <groupId>org.apache.oodt</groupId>
+		    </exclusion>
+		  </exclusions>
+		</dependency>
+		<dependency>
+		   <groupId>org.apache.oodt</groupId>
+		   <artifactId>cas-filemgr</artifactId>
+		   <version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+		  <groupId>org.apache.oodt</groupId>
+		  <artifactId>cas-metadata</artifactId>
+		  <version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+		  <groupId>org.apache.oodt</groupId>
+		  <artifactId>cas-product</artifactId>
+		  <version>${project.parent.version}</version>
+		  <type>war</type>
+		</dependency>
+		<dependency>
+		  <groupId>org.apache.oodt</groupId>
+		  <artifactId>pcs-core</artifactId>
+		  <version>${project.parent.version}</version>
+		</dependency>
+
+		<!-- LOGGING DEPENDENCIES - LOG4J -->
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-log4j12</artifactId>
+			<version>${slf4j.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>1.2.14</version>
+		</dependency>
+
+		<!--  JUNIT DEPENDENCY FOR TESTING -->
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.8.1</version>
+			<scope>test</scope>
+		</dependency>
+
+		<!--  JETTY DEPENDENCIES FOR TESTING  -->
+		<dependency>
+			<groupId>org.mortbay.jetty</groupId>
+			<artifactId>jetty</artifactId>
+			<version>${jetty.version}</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.mortbay.jetty</groupId>
+			<artifactId>jetty-util</artifactId>
+			<version>${jetty.version}</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.mortbay.jetty</groupId>
+			<artifactId>jetty-management</artifactId>
+			<version>${jetty.version}</version>
+			<scope>provided</scope>
+		</dependency>
+	</dependencies>
+        <profiles>
+            <profile>
+                <id>audit</id>
+                <activation>
+                    <activeByDefault>false</activeByDefault>
+                </activation>
+                <build>
+                    <plugins>
+                        <plugin>
+                            <groupId>org.codehaus.mojo</groupId>
+                            <artifactId>rat-maven-plugin</artifactId>
+                            <executions>
+                                <execution>
+                                    <phase>verify</phase>
+                                    <goals>
+                                        <goal>check</goal>
+                                    </goals>
+                                </execution>
+                            </executions>
+                            <configuration>
+                                <numUnapprovedLicenses>1</numUnapprovedLicenses>
+                            </configuration>
+                        </plugin>
+                    </plugins>
+                </build>
+            </profile>
+        </profiles>
+	<build>
+		<resources>
+			<resource>
+				<filtering>false</filtering>
+				<directory>src/main/resources</directory>
+			</resource>
+			<resource>
+				<filtering>false</filtering>
+				<directory>src/main/java</directory>
+				<includes>
+					<include>**</include>
+				</includes>
+				<excludes>
+					<exclude>**/*.java</exclude>
+				</excludes>
+			</resource>
+		</resources>
+		<testResources>
+			<testResource>
+				<filtering>false</filtering>
+				<directory>src/test/java</directory>
+				<includes>
+					<include>**</include>
+				</includes>
+				<excludes>
+					<exclude>**/*.java</exclude>
+				</excludes>
+			</testResource>
+		</testResources>
+		<plugins>
+			<plugin>
+				<inherited>true</inherited>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.5</source>
+					<target>1.5</target>
+					<optimize>true</optimize>
+					<debug>true</debug>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+	</project>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage.css b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage.css
new file mode 100644
index 0000000..7ed928b
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage.css
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+#header {
+    width:100%;
+    height:80px;
+    border-bottom: solid 1px #2e3e4e;
+}
+
+#project_logo {
+    float:left;
+}
+
+#user_status {
+    float:right;
+    padding:10px;
+}
+
+#nav {
+    margin-top:10px;
+}
+
+#nav a {
+    color:#c0c0c0;
+    text-decoration:none;
+    border-right:solid 1px #456;
+    padding: 3px 20px;
+}
+#nav a.first {
+}
+#nav a.last {
+    border-right:none;
+}
+
+#footer{
+  position:fixed;
+  bottom:0px;
+  width:100%;
+  height:80px;
+  padding:5px 0px;
+  border-spacing:0px;
+  border-top:solid 1px #2e3e4e;
+  font-size:90%;
+  z-index:10000;
+}
+#footer p {
+  width:100%;
+  padding:5px 15px;
+  text-align:center;
+}
+
+#feedback {
+    margin:0px;
+    margin-top:-20px;
+    font-size:90%;
+}
+
+#powered,#feedback {
+  margin-left:-30px;
+}
+
+
+
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage.html
new file mode 100644
index 0000000..0055c54
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage.html
@@ -0,0 +1,125 @@
+<!--
+ 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.
+-->
+<html
+	xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<head>
+<title>Apache OODT PCS Operator Interface</title>
+<wicket:link>
+  <link type="text/css" rel="stylesheet" href="BasePage.css"/>
+  <script type="text/javascript" language="Javascript" src="jquery-1.7.min.js"></script>
+  <script type="text/javascript" language="Javascript" src="BasePage.js"></script>
+</wicket:link>
+<wicket:remove>
+  <script language="Javascript" type="text/javascript">
+   <!--
+
+   function menuSelected(cell) {
+		cell.css({'background-color':'#006699'});
+	}
+	function menuNotSelected(cell) {
+		cell.css({'background-color':'#666666'});	
+	}   
+   
+   function subMenuSelected(id) {
+		var x = document.getElementById(id).rows;
+		var y = x[0].cells;
+		y[0].innerHTML = "<img src='selleftcorner.gif'>";
+		y[1].bgColor = "#99CCFF";
+		y[2].innerHTML = "<img src='selrightcorner.gif'>";
+	}
+
+	function subMenuNotSelected(id) {
+		var x = document.getElementById(id).rows;
+		var y = x[0].cells;
+		y[0].innerHTML = "<img src='leftcorner.gif'>";
+		y[1].bgColor = "#cccccc";
+		y[2].innerHTML = "<img src='rightcorner.gif'>";
+	}     
+	
+	var interfaceimg = new Array();
+	function preloadimg() {
+		for (var i = 0; i < arguments.length; i++) {
+			interfaceimg[i] = new Image();
+			interfaceimg[i].src = arguments[i];
+		}
+	}
+
+	// Enter full URL to image tabs to preload below. Separate with comma:
+
+	preloadimg("rightcorner.gif", "leftcorner.gif",
+			"selrightcorner.gif", "selleftcorner.gif");	
+   //-->
+  </script>
+</wicket:remove>
+</head>
+<body>
+<div id="header">
+    <div id="project_logo">
+       <wicket:link>
+	     <img src="project_logo.png" alt="banner image" class="banner"/>
+       </wicket:link>
+    </div>
+    <div id="user_status">
+		<span>Apache OODT PCS Operator Interface</span>
+        <!--TODO: add Wicket logon widget here -->
+		<span id="logon_widget"/>
+    </div>
+</div>
+<div id="nav">
+        <a href="#" wicket:id="home_link" class="first">
+					  <span>
+					    Home
+					  </span>
+					</a>
+        <a href="#" wicket:id="fmbrowser_link" >
+					  <span>
+					    File Catalog Browse
+					  </span>
+					</a>
+        <a href="#" wicket:id="wmonitor_link" id="wmonitor_link" >
+					  <span>
+					    Workflow Monitor
+					  </span>
+					</a>
+        <a href="#" wicket:id="ganglia_link" >
+					  <span>
+					    Resource Monitor
+					  </span>
+					</a>
+        <a href="#" wicket:id="config_link">
+					  <span>
+					    Configuration
+					  </span>
+					</a>
+        <a href="#" wicket:id="pcsstatus_link" id="pcsstatus_link" class="last">
+					  <span>
+					    PCS Status
+					  </span>
+					</a>
+</div>
+
+<wicket:child/>
+
+<p>&nbsp;</p>
+<p>&nbsp;</p>
+
+<div id="footer">
+        <p id="powered">Powered by <a href="http://oodt.apache.org/">Apache OODT</a></p>
+        <p id="feedback"><a href="#" wicket:id="contact_link">Feedback</a></p>
+</div>
+</body>
+</html>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage.java
new file mode 100644
index 0000000..b7ffbd0
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage.java
@@ -0,0 +1,106 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.pcs.opsui;
+
+//Wicket imports
+import org.apache.oodt.pcs.opsui.config.ConfigPage;
+import org.apache.oodt.pcs.opsui.status.StatusPage;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.link.ExternalLink;
+import org.apache.wicket.markup.html.link.Link;
+
+/**
+ *
+ * Provides the controller for the OPSUI template.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class BasePage extends OPSUIWebPage {
+  
+  protected OpsuiApp app;
+  
+  public BasePage(PageParameters parameters){    
+    this.app = (OpsuiApp)getApplication();
+    add(new Link("home_link"){
+      /* (non-Javadoc)
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        setResponsePage(app.getHomePage());
+      }
+    });
+    
+    add(new Link("fmbrowser_link"){
+      /* (non-Javadoc)
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+       setResponsePage(TypesPage.class); 
+      }
+    });
+    
+    add(new Link("pcsstatus_link"){
+      
+    /* (non-Javadoc)
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        setResponsePage(StatusPage.class);
+        
+      }
+    });
+    
+    add(new Link("wmonitor_link"){
+       /* (non-Javadoc)
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        PageParameters params = new PageParameters();
+        params.add("status", "ALL");
+        params.add("pageNum", "1");
+        setResponsePage(WorkflowInstanceViewerPage.class, params);
+        
+      }
+    });
+    
+    add(new Link("config_link"){
+        /* (non-Javadoc)
+         * @see org.apache.wicket.markup.html.link.Link#onClick()
+         */
+        @Override
+        public void onClick() {
+          PageParameters params = new PageParameters();
+          params.add("tab", "File Manager");
+          setResponsePage(ConfigPage.class, params);  
+        }
+    });
+    
+    add(new ExternalLink("ganglia_link", app.getGangliaUrl()));
+    
+    add(new ExternalLink("contact_link", "mailto:"+((OpsuiApp)getApplication()).getEmailContactLink()));
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage.js b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage.js
new file mode 100644
index 0000000..5729ad7
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage.js
@@ -0,0 +1 @@
+// Apache OODT OPSUI JS
\ No newline at end of file
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_classic.css b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_classic.css
new file mode 100644
index 0000000..84f1d4c
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_classic.css
@@ -0,0 +1,222 @@
+/*
+ * 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.
+ */
+body{
+	background-color:#000000;
+	color:#000000;
+	margin-top: 0;
+	margin-left:0; 
+	margin-right:0; 
+	margin-bottom:0;
+	width:100%;
+	height:100%;
+}
+
+#opsui_header_tbl{
+  border:0px;
+  border-spacing:0px;
+  white-space:nowrap;
+  padding:0px;
+  width:100%;
+
+}
+
+#opsui_inner_header_tbl{
+  border:0px;
+  border-spacing:0px;
+  white-space:nowrap;
+  padding:0px;
+  width:100%;
+
+}
+
+#menu_inner_tbl{
+  padding:0px;
+  border-spacing:1px;
+  border:0px;
+  width:100%;
+  color:white; 
+}
+
+#menu_inner_tbl_home{
+  background-color:#666666;
+  height:23px;
+  width:20px;
+  text-align:center;
+}
+
+#menu_tbl_links{
+  padding:0px;
+  border-spacing:1px;
+  border:0px;
+  width:100%;
+  color:white; 
+}
+
+#menu_inner_tbl_links_fm{
+  background-color:#666666;
+  height:23px;
+  text-align:center;
+}
+
+#menu_inner_tbl_links_wm{
+  background-color:#666666;
+  height:23px;
+  text-align:center;
+}
+
+#menu_inner_tbl_links_rm{
+  background-color:#666666;
+  height:23px;
+  text-align:center;
+}
+
+#menu_inner_tbl_links_cfg{
+  background-color:#666666;
+  height:23px;
+  text-align:center;
+}
+
+#menu_inner_tbl_links_pcsstat{
+  background-color:#666666;
+  height:23px;
+  text-align:center;
+}
+
+#footer_tbl{
+  padding:4px;
+  border-spacing:0px;
+  width:730px;
+  border:0px;
+}
+
+.banner{
+  border:0px;
+  width:379px;
+  height:65px;  
+}
+
+.spacer{
+  width:730px;
+  height:2px;  
+}
+
+.tdspacer{
+  background-color:#666666;
+  height:23px;
+  width:20%;
+}
+
+.tight-noborder{
+  vertical-spacing:0px;
+  width:100%;
+  border:0px;
+}
+
+.white {
+  color:white;
+}
+
+.whitebg{
+	background-color:white;
+}
+
+.blackbg{
+	background-color:black;
+}
+
+.blackLink {
+  color:#000000;
+  line-height:18px;
+}
+
+.firstGovImg{
+  height:39px;
+  width:136px;
+  border:0px;
+}
+
+.nasaHomePageImg{
+  height:40px;
+  width:61px;
+  border:0px;
+}
+
+.feedback{
+  font-family:Arial, Helvetica, sans-serif;
+  font-size:2px;
+}
+
+a{
+	text-decoration:none;
+}
+
+a:hover{
+	text-decoration:underline;
+}
+
+#criteria_form_add_element_value{
+	font-weight:bold;
+}
+
+#product_table{
+	border:1px;
+	border-spacing:2px;
+	border: 1px solid #000000;
+	width:800px;
+}
+
+#product_table td{
+  border: 1px solid #000000;
+  margin: 0; 
+  padding: 2px;
+}
+
+#pagination_table{
+	border-spacing:3px;
+	width:100%;
+}
+
+#pagination_table_result_hdr{
+	width:100px;
+	white-space: nowrap;
+	font-weight:bold;
+}
+
+#cas_fm_browser_ptype_table{
+  padding:2px;
+  border-spacing:2px;
+  width:800px;
+  border: 1px solid #000000;
+}
+
+#cas_fm_browser_ptype_table td{
+  border: 1px solid #000000;
+  margin: 0; 
+  padding: 2px;
+}
+
+.workflow_status{
+   border-left: 1px;
+   padding-left: 1px;
+   border-right: 1px;
+   padding-right: 1px;
+   border-width: 1px;
+   border-top:0px;
+   border-bottom:0px;
+   border-style:solid;
+   border-color:black;	
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_classic.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_classic.html
new file mode 100644
index 0000000..b106536
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_classic.html
@@ -0,0 +1,351 @@
+<!--
+ 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.
+-->
+<html
+	xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<head>
+<title>Apache OODT PCS Operator Interface</title>
+<wicket:link>
+	<link type="text/css" rel="stylesheet" href="BasePage_classic.css" />
+	<script type="text/javascript" language="Javascript"
+		src="jquery-1.7.min.js"></script>
+	<script type="text/javascript" language="Javascript" src="BasePage_classic.js"></script>
+</wicket:link>
+<wicket:remove>
+	<script language="Javascript" type="text/javascript">
+	<!--
+		function menuSelected(cell) {
+			cell.css({
+				'background-color' : '#006699'
+			});
+		}
+		function menuNotSelected(cell) {
+			cell.css({
+				'background-color' : '#666666'
+			});
+		}
+
+		function subMenuSelected(id) {
+			var x = document.getElementById(id).rows;
+			var y = x[0].cells;
+			y[0].innerHTML = "<img src='selleftcorner.gif'>";
+			y[1].bgColor = "#99CCFF";
+			y[2].innerHTML = "<img src='selrightcorner.gif'>";
+		}
+
+		function subMenuNotSelected(id) {
+			var x = document.getElementById(id).rows;
+			var y = x[0].cells;
+			y[0].innerHTML = "<img src='leftcorner.gif'>";
+			y[1].bgColor = "#cccccc";
+			y[2].innerHTML = "<img src='rightcorner.gif'>";
+		}
+
+		var interfaceimg = new Array();
+		function preloadimg() {
+			for ( var i = 0; i < arguments.length; i++) {
+				interfaceimg[i] = new Image();
+				interfaceimg[i].src = arguments[i];
+			}
+		}
+
+		// Enter full URL to image tabs to preload below. Separate with comma:
+
+		preloadimg("rightcorner.gif", "leftcorner.gif", "selrightcorner.gif",
+				"selleftcorner.gif");
+	//-->
+	</script>
+</wicket:remove>
+</head>
+
+<map name="Map">
+	<area shape="rect" coords="91,36,272,54" href="http://www.caltech.edu/"
+		alt="Caltech" />
+	<area shape="circle" coords="61,34,24" href="http://www.nasa.gov"
+		alt="NASA" />
+	<area shape="rect" coords="91,11,278,35"
+		href="http://www.jpl.nasa.gov/"
+		alt="Daily Planet e-News for the JPL Community" />
+</map>
+
+<body>
+	<table border="0" cellspacing="0" cellpadding="0" align="center"
+		bgcolor="#FFFFFF" width="730">
+		<tr class="blackbg">
+			<td style="width: 10px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 10px; height: 1px;" />
+				</wicket:link></td>
+			<td style="width: 732px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 730px; height: 10px;">
+				</wicket:link></td>
+			<td style="width: 10px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 10px; height: 1px;" />
+				</wicket:link></td>
+		</tr>
+		<tr>
+			<td style="width:10px;"><wicket:link><img src="spacer.gif" alt="spacer" style="width:10px;height:1px;"/></wicket:link></td>
+			<td style="width:732px;"><wicket:link><img src="spacer.gif" alt="spacer" style="width:730px;height:10px;"/></wicket:link></td>
+			<td style="width:10px;"><wicket:link><img src="spacer.gif" alt="spacer" style="width:10px;height:1px;"/></wicket:link></td>
+		</tr>
+		<tr>
+			<td style="width:10px;"><wicket:link><img src="spacer.gif" alt="spacer" style="width:10px;height:1px;"/></wicket:link></td>
+			<td style="width:732px;vertical-align: top;">
+
+				<table id="opsui_header_tbl">
+					<tr>
+						<td>
+							<table id="opsui_inner_header_tbl">
+								<tr>
+									<td style="width: 379px; background-color: #ccccc;"><wicket:link>
+											<img src="nasa_logo.gif" alt="banner image" class="banner"
+												usemap="#Map" />
+										</wicket:link>
+									</td>
+									<td
+										style="height: 70px; width: 136px; background-color: #cccccc;"></td>
+									<td
+										style="width: 205px; background-color: #000669; text-align: center; vertical-align: middle;">
+										<!--TODO: add Wicket logon widget here --> <span
+										id="logon_widget" /> <span
+										style="font-size: 14px; color: white;">Welcome to the
+											Operator Interface Web site</span> <br /> <br />
+									</td>
+								</tr>
+							</table>
+						</td>
+					</tr>
+					<tr>
+						<td><wicket:link>
+								<img src="spacer.gif" alt="spacer" class="spacer" />
+							</wicket:link>
+						</td>
+					</tr>
+					<tr>
+						<td class="white">
+							<table id="menu_inner_tbl">
+								<tr>
+									<td id="menu_inner_tbl_home"
+										onMouseOver="menuSelected($(this))"
+										onMouseOut="menuNotSelected($(this))"><a href="#"
+										wicket:id="home_link" class="white">HOME</a>
+									</td>
+									<td class="tdspacer"></td>
+									<td class="tdspacer"></td>
+									<td class="tdspacer"></td>
+									<td class="tdspacer"></td>
+								</tr>
+							</table>
+						</td>
+					</tr>
+					<tr>
+						<td><wicket:link>
+								<img src="spacer.gif" alt="spacer" class="spacer"
+									style="height: 1px;" />
+							</wicket:link>
+						</td>
+					</tr>
+					<tr>
+						<td style="width: 100%"><wicket:link>
+								<img src="banner.jpg" class="tight-noborder" alt="Banner" />
+							</wicket:link>
+						</td>
+					</tr>
+					<tr>
+						<td class="white">
+							<table id="menu_tbl_links">
+								<tr>
+									<td id="menu_inner_tbl_links_fm"
+										onMouseOver="menuSelected($(this))"
+										onMouseOut="menuNotSelected($(this))"><a href="#"
+										wicket:id="fmbrowser_link" class="blackLink"> <span
+											style="color: white; font-weight: bold;"> File Catalog
+												Browse </span> </a>
+									</td>
+									<td id="menu_inner_tbl_links_wm"
+										onMouseOver="menuSelected($(this))"
+										onMouseOut="menuNotSelected($(this))"><a href="#"
+										wicket:id="wmonitor_link" id="wmonitor_link" class="blackLink">
+											<span style="color: white; font-weight: bold;">
+												Workflow Monitor </span> </a>
+									</td>
+									<td id="menu_inner_tbl_links_rm"
+										onMouseOver="menuSelected($(this))"
+										onMouseOut="menuNotSelected($(this))"><a href="#"
+										wicket:id="ganglia_link" class="blackLink"> <span
+											style="color: white; font-weight: bold;"> Resource
+												Monitor </span> </a>
+									</td>
+									<td id="menu_inner_tbl_links_cfg"
+										onMouseOver="menuSelected($(this))"
+										onMouseOut="menuNotSelected($(this))"><a href="#"
+										wicket:id="config_link" class="blackLink"> <span
+											style="color: white; font-weight: bold;">
+												Configuration </span> </a>
+									</td>
+									<td id="menu_inner_tbl_links_pcsstat"
+										onMouseOver="menuSelected($(this))"
+										onMouseOut="menuNotSelected($(this))"><a href="#"
+										wicket:id="pcsstatus_link" id="pcsstatus_link"
+										class="blackLink"> <span
+											style="color: white; font-weight: bold;"> PCS Status </span>
+									</a>
+									</td>
+								</tr>
+							</table>
+						</td>
+					</tr>
+					<tr>
+						<td><wicket:link>
+								<img src="spacer.gif" alt="spacer" class="spacer"
+									style="height: 1px;">
+							</wicket:link>
+						</td>
+					</tr>
+
+				</table>
+			</td>
+			<td style="width:10px;"><wicket:link><img src="spacer.gif" alt="spacer" style="width:10px;height:1px;"/></wicket:link>
+			</td>
+		</tr>
+
+		<tr>
+			<td style="width: 10px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 10px; height: 1px;" />
+				</wicket:link></td>
+			<td style="width: 732px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 730px; height: 10px;">
+				</wicket:link></td>
+			<td style="width: 10px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 10px; height: 1px;" />
+				</wicket:link></td>
+		</tr>
+		<tr>
+			<td style="width:10px;"><wicket:link><img src="spacer.gif" alt="spacer" style="width:10px;height:100px;"/></wicket:link></td>
+			<td style="vertical-align: top;width: 732px;">
+			  
+			  <wicket:child />
+			
+			
+			</td>
+			<td style="width:10px;">
+			  <wicket:link><img src="spacer.gif" alt="spacer" style="width:10px;height:300px;"/></wicket:link>
+			</td>
+		</tr>
+		<tr>
+			<td style="width: 10px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 10px; height: 1px;" />
+				</wicket:link></td>
+			<td style="width: 732px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 730px; height: 10px;">
+				</wicket:link></td>
+			<td style="width: 10px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 10px; height: 1px;" />
+				</wicket:link></td>
+		</tr>
+
+		<tr>
+			<td style="width: 10px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 10px; height: 1px;" />
+				</wicket:link></td>
+			<td style="width: 732px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 730px; height: 10px;">
+				</wicket:link></td>
+			<td style="width: 10px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 10px; height: 1px;" />
+				</wicket:link></td>
+		</tr>
+		<tr>
+			<td width="10"><wicket:link><img src="spacer.gif" alt="spacer" style="width:10px;height:1px;"/></wicket:link></td>
+
+			<td style="background-color:#cccccc;width:732px;">
+
+
+				<table id="footer_tbl">
+					<tr>
+						<td style="vertical-align: top; width: 160px;"><a
+							target="_blank" href="http://www.firstgov.gov/"> <wicket:link>
+									<img class="firstGovImg" src="footer_image1.gif" />
+								</wicket:link> </a>
+						</td>
+						<td style="width: 200px;"><a target="_blank"
+							href="http://www.jpl.nasa.gov/copyrights.cfm">+ JPL/Caltech
+								Privacy/Copyright </a>
+						</td>
+						<td style="width: 61px;"><a target="_blank"
+							href="http://www.nasa.gov/home/index.html"> <wicket:link>
+									<img class="nasaHomePageImg" alt="NASA Home Page"
+										src="footer_image2.gif" />
+								</wicket:link> </a>
+						</td>
+						<td style="width: 280px;"><span class="feedback">&nbsp;</span>
+							<a href="#" wicket:id="contact_link">Feedback</a>
+						</td>
+					</tr>
+				</table> <wicket:remove>
+					<div style="text-align: center">
+						<p>
+							Powered by <a href="http://oodt.apache.org/">Apache OODT</a>
+						</p>
+					</div>
+				</wicket:remove>
+			</td>
+			<td style="width:10px;"><wicket:link><img src="spacer.gif" alt="spacer" style="width:10px;height:8px;"/></wicket:link></td>
+		</tr>
+		<tr>
+			<td style="width: 10px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 10px; height: 1px;" />
+				</wicket:link></td>
+			<td style="width: 732px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 730px; height: 10px;">
+				</wicket:link></td>
+			<td style="width: 10px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 10px; height: 1px;" />
+				</wicket:link></td>
+		</tr>
+
+
+		<tr class="blackbg">
+			<td style="width: 10px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 10px; height: 1px;" />
+				</wicket:link></td>
+			<td style="width: 732px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 730px; height: 10px;">
+				</wicket:link></td>
+			<td style="width: 10px;"><wicket:link>
+					<img src="spacer.gif" alt="spacer"
+						style="width: 10px; height: 1px;" />
+				</wicket:link></td>
+		</tr>
+	</table>
+</body>
+</html>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_classic.js b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_classic.js
new file mode 100644
index 0000000..ce0e1c9
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_classic.js
@@ -0,0 +1,53 @@
+/*
+ *  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.
+ */
+function menuSelected(cell) {
+	cell.css({
+		'background-color' : '#006699'
+	});
+}
+function menuNotSelected(cell) {
+	cell.css({
+		'background-color' : '#666666'
+	});
+}
+
+function subMenuSelected(id) {
+	var x = document.getElementById(id).rows;
+	var y = x[0].cells;
+	y[0].innerHTML = "<img src='/images/selleftcorner.gif'>";
+	y[1].bgColor = "#99CCFF";
+	y[2].innerHTML = "<img src='/images/selrightcorner.gif'>";
+}
+
+function subMenuNotSelected(id) {
+	var x = document.getElementById(id).rows;
+	var y = x[0].cells;
+	y[0].innerHTML = "<img src='/images/leftcorner.gif'>";
+	y[1].bgColor = "#cccccc";
+	y[2].innerHTML = "<img src='/images/rightcorner.gif'>";
+}
+
+var interfaceimg = new Array();
+function preloadimg() {
+	for ( var i = 0; i < arguments.length; i++) {
+		interfaceimg[i] = new Image();
+		interfaceimg[i].src = arguments[i];
+	}
+}
+
+//preloadimg("/images/rightcorner.gif", "/images/leftcorner.gif", "/images/selrightcorner.gif",
+//		"/images/selleftcorner.gif");
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_cleanwhite.css b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_cleanwhite.css
new file mode 100644
index 0000000..3883e97
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_cleanwhite.css
@@ -0,0 +1,352 @@
+/*
+ * 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.
+ */
+/*
+ bg             #334455
+ borders-top    #2e3e4e
+ border-left    #304050
+ bg-text        #162636
+ link-text      #c0c0c0
+*/
+
+body {
+    background-color:#FFF;
+    margin:0px;
+    padding:0px;
+    font-family: verdana, arial,  sans-serif;
+    font-size: small;
+}
+
+#content {
+	padding: 10px;	
+}
+
+#header {
+    width:100%;
+    height:80px;
+    border-bottom: solid 1px #2e3e4e;
+}
+
+#project_logo {
+    float:left;
+}
+
+#user_status {
+    float:right;
+    padding:10px;
+    color:#162636;
+}
+
+#nav {
+    margin-top:10px;
+}
+
+#nav a {
+    color:#193678;
+    text-decoration:none;
+    font-weight: bolder;
+    border-right:solid 1px #456;
+    padding: 3px 20px;
+}
+#nav a.first {
+}
+#nav a.last {
+    border-right:none;
+}
+#nav a:hover {
+    color:#4965A6;
+}
+
+#footer{
+  position:fixed;
+  bottom:0px;
+  width:100%;
+  height:80px;
+  padding:5px 0px;
+  border-spacing:0px;
+  border-top:solid 1px #2e3e4e;
+  background-color: #EEE;
+  font-size:90%;
+  z-index:10000;
+}
+#footer a {
+  color:#193678;
+}
+
+#footer p {
+  width:100%;
+  padding:5px 15px;
+  text-align:center;
+}
+
+#feedback {
+    margin:0px;
+    margin-top:-20px;
+    font-size:90%;
+}
+
+#powered,#feedback {
+  margin-left:-30px;
+}
+
+
+a{
+	color: rgb(31, 31, 107);
+}
+
+a:hover{
+}
+
+a:visited {
+	color: purple;	
+}
+
+a img,  {
+    border:none;
+}
+
+/**
+ * HEADERS 
+**/
+h1, h2, h3, h4, h5 {
+    background-color:#193678;
+    color:#FFF;
+    border-top:solid 1px #DDD;
+    border-bottom:solid 1px #DDD;
+    padding:8px;
+}
+h1 {
+
+}
+
+h2 {
+
+}
+
+h3 {
+    
+}
+
+h4 {
+    background-color:transparent;
+    color: #444;
+    border-top:none;
+    margin:10px;
+}
+
+h5 {
+
+}
+
+/**
+ * TABLES
+**/
+table {
+	font-family: verdana,arial,sans-serif;
+	font-size:11px;
+	color:#333333;
+	border-width: 1px;
+	border-color: #304050;
+	border-collapse: collapse;
+}
+table th {
+	border-width: 1px;
+	padding: 8px;
+	border-style: solid;
+	border-color: #193678;
+	background-color: #193678;
+	color: #FFF;
+}
+table td {
+	border-width: 1px;
+	padding: 8px;
+	border-style: solid;
+	border-color: #304050;
+	background-color: #ffffff;
+}
+
+
+/**
+ * BREADCRUMBS
+ */
+div#breadcrumbs {
+    color:#777;
+    margin-left:20px;
+    margin-top:15px;
+}
+
+div#breadcrumbs a {
+
+}
+
+div#breadcrumbs span.divider {
+    padding:0px 5px;
+}
+
+
+
+
+
+
+/**
+ * FILE MANAGER: Types.css
+**/ 
+#cas_fm_browser_ptype_table{
+
+}
+
+#cas_fm_browser_ptype_table td{
+
+}
+
+/**
+ * FILE MANAGER: TypeBrowser.css
+**/ 
+
+#criteria_form_add_element_value{
+	font-weight:bold;
+}
+
+#product_table{
+
+}
+
+#product_table td{
+
+}
+
+#pagination_table{
+	border-spacing:3px;
+	width:100%;
+}
+
+#pagination_table_result_hdr{
+	width:100px;
+	white-space: nowrap;
+	font-weight:bold;
+}
+
+/**
+ * FILE MANAGER: ProductBrowser.css
+**/ 
+#met_table{
+
+}
+
+#met_elem_name{
+	
+}
+
+#met_values_table{
+
+}
+
+.nada{
+	
+}
+
+#ref_table{
+	
+}
+
+#ref_table_hdr{
+	
+}
+
+/**
+ * FILE MANAGER: ProductRefsBrowser.css
+**/ 
+ 
+.nada{
+	
+}
+
+#ref_table{
+	
+}
+
+#ref_table_hdr{
+	
+}
+
+/**
+ * FILE MANAGER: ProductPaginator.css
+**/ 
+#paginator-break{
+  border:2;
+  width:100%;
+}
+
+#container-div{
+  width:100%;
+}
+
+#paginator-table{
+  border-spacing:3;
+  width:100;
+}
+
+#paginator-table-header{
+  width:100%;
+  white-space:nowrap;
+  font-weight:bold;
+}
+
+
+#page_repeater{
+
+}
+
+a, a:hover, a:focus, a:active{
+	text-decoration: none;
+}
+
+.selected{
+  font-weight:bold;
+  color:red;
+}
+
+/**
+ * FILE MANAGER: MetadataBrowser.css
+**/ 
+
+#met_table{
+
+}
+
+#met_elem_name{
+	
+}
+
+#met_values_table{
+
+}
+
+.nada{
+	
+}
+
+/**
+ * WORKFLOW MANAGER: Workflow Instances 
+**/
+#instance_filter_header p {
+    padding-left:20px;
+}
+a.workflow_status {
+    border-right:solid 1px #ccc;
+    padding-left:15px;
+    padding-right:15px;
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_cleanwhite.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_cleanwhite.html
new file mode 100644
index 0000000..1b037f7
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_cleanwhite.html
@@ -0,0 +1,127 @@
+<!--
+ 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.
+-->
+<html
+	xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<head>
+<title>Apache OODT PCS Operator Interface</title>
+<wicket:link>
+  <link type="text/css" rel="stylesheet" href="BasePage.css"/>
+  <script type="text/javascript" language="Javascript" src="jquery-1.7.min.js"></script>
+  <script type="text/javascript" language="Javascript" src="BasePage.js"></script>
+</wicket:link>
+<wicket:remove>
+  <script language="Javascript" type="text/javascript">
+   <!--
+
+   function menuSelected(cell) {
+		cell.css({'background-color':'#006699'});
+	}
+	function menuNotSelected(cell) {
+		cell.css({'background-color':'#666666'});	
+	}   
+   
+   function subMenuSelected(id) {
+		var x = document.getElementById(id).rows;
+		var y = x[0].cells;
+		y[0].innerHTML = "<img src='selleftcorner.gif'>";
+		y[1].bgColor = "#99CCFF";
+		y[2].innerHTML = "<img src='selrightcorner.gif'>";
+	}
+
+	function subMenuNotSelected(id) {
+		var x = document.getElementById(id).rows;
+		var y = x[0].cells;
+		y[0].innerHTML = "<img src='leftcorner.gif'>";
+		y[1].bgColor = "#cccccc";
+		y[2].innerHTML = "<img src='rightcorner.gif'>";
+	}     
+	
+	var interfaceimg = new Array();
+	function preloadimg() {
+		for (var i = 0; i < arguments.length; i++) {
+			interfaceimg[i] = new Image();
+			interfaceimg[i].src = arguments[i];
+		}
+	}
+
+	// Enter full URL to image tabs to preload below. Separate with comma:
+
+	preloadimg("rightcorner.gif", "leftcorner.gif",
+			"selrightcorner.gif", "selleftcorner.gif");	
+   //-->
+  </script>
+</wicket:remove>
+</head>
+<body>
+<div id="content">
+<div id="header">
+    <div id="project_logo">
+       <wicket:link>
+	     <img src="project_logo.png" alt="banner image" class="banner"/>
+       </wicket:link>
+    </div>
+    <div id="user_status">
+		<span>Apache OODT PCS Operator Interface</span>
+        <!--TODO: add Wicket logon widget here -->
+		<span id="logon_widget"/>
+    </div>
+</div>
+<div id="nav">
+        <a href="#" wicket:id="home_link" class="first">
+					  <span>
+					    Home
+					  </span>
+					</a>
+        <a href="#" wicket:id="fmbrowser_link" >
+					  <span>
+					    File Catalog Browse
+					  </span>
+					</a>
+        <a href="#" wicket:id="wmonitor_link" id="wmonitor_link" >
+					  <span>
+					    Workflow Monitor
+					  </span>
+					</a>
+        <a href="#" wicket:id="ganglia_link" >
+					  <span>
+					    Resource Monitor
+					  </span>
+					</a>
+        <a href="#" wicket:id="config_link">
+					  <span>
+					    Configuration
+					  </span>
+					</a>
+        <a href="#" wicket:id="pcsstatus_link" id="pcsstatus_link" class="last">
+					  <span>
+					    PCS Status
+					  </span>
+					</a>
+</div>
+
+<wicket:child/>
+
+<p>&nbsp;</p>
+<p>&nbsp;</p>
+
+</div> <!--  end content block -->
+<div id="footer">
+        <p id="powered">Powered by <a href="http://oodt.apache.org/">Apache OODT</a></p>
+        <p id="feedback"><a href="#" wicket:id="contact_link">Feedback</a></p>
+</div>
+</body>
+</html>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_navyblue.css b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_navyblue.css
new file mode 100644
index 0000000..3b43dad
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/BasePage_navyblue.css
@@ -0,0 +1,350 @@
+/*
+ * 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.
+ */
+/*
+ bg             #334455
+ borders-top    #2e3e4e
+ border-left    #304050
+ bg-text        #162636
+ link-text      #c0c0c0
+*/
+
+body {
+    background-color:#345;
+    margin:0px;
+    padding:0px;
+    font-family: arial, verdana, sans-serif;
+}
+
+#header {
+    width:100%;
+    height:80px;
+    border-bottom: solid 1px #2e3e4e;
+}
+
+#project_logo {
+    float:left;
+}
+
+#user_status {
+    float:right;
+    padding:10px;
+    color:#162636;
+}
+
+#nav {
+    margin-top:10px;
+}
+
+#nav a {
+    color:#c0c0c0;
+    text-decoration:none;
+    border-right:solid 1px #456;
+    padding: 3px 20px;
+}
+#nav a.first {
+}
+#nav a.last {
+    border-right:none;
+}
+#nav a:hover {
+    text-decoration:underline;
+    color:#fff;
+    background-color:#2e3e4e;
+}
+
+#footer{
+  position:fixed;
+  bottom:0px;
+  width:100%;
+  height:80px;
+  padding:5px 0px;
+  border-spacing:0px;
+  border-top:solid 1px #2e3e4e;
+  color:#234;
+  background-color:#364656;
+  font-size:90%;
+  z-index:10000;
+}
+#footer a {
+  color:#aaa;
+}
+
+#footer p {
+  width:100%;
+  padding:5px 15px;
+  text-align:center;
+}
+
+#feedback {
+    margin:0px;
+    margin-top:-20px;
+    font-size:90%;
+}
+
+#powered,#feedback {
+  margin-left:-30px;
+}
+
+
+a{
+    color:#c0c0c0;
+	text-decoration:none;
+}
+
+a:hover{
+	text-decoration:underline;
+}
+
+a img,  {
+    border:none;
+}
+
+
+/**
+ * HEADERS 
+**/
+h1, h2, h3, h4, h5 {
+    background-color:#283848;
+    color:#eee;
+    border-top:solid 1px #2e3e4e;
+    border-bottom:solid 1px #233343;
+    padding:8px;
+}
+h1 {
+
+}
+
+h2 {
+
+}
+
+h3 {
+    
+}
+
+h4 {
+    background-color:transparent;
+    border-top:none;
+    margin:10px;
+}
+
+h5 {
+
+}
+
+/**
+ * TABLES
+**/
+table {
+  padding:2px;
+  width:100%;
+  border: none;
+}
+table tr {
+    
+}
+
+table tr th {
+
+}
+
+table tr td {
+    border-bottom:solid 1px #234;
+    border-right:solid 1px #234;
+    padding:5px;
+    color:#111;
+}
+
+table table td {
+    border-bottom:none;
+    border-right:none;
+}
+
+/**
+ * BREADCRUMBS
+ */
+div#breadcrumbs {
+    color:#777;
+    margin-left:20px;
+    margin-top:15px;
+}
+
+div#breadcrumbs a {
+
+}
+
+div#breadcrumbs span.divider {
+    padding:0px 5px;
+}
+
+
+
+
+
+
+/**
+ * FILE MANAGER: Types.css
+**/ 
+#cas_fm_browser_ptype_table{
+
+}
+
+#cas_fm_browser_ptype_table td{
+
+}
+
+/**
+ * FILE MANAGER: TypeBrowser.css
+**/ 
+
+#criteria_form_add_element_value{
+	font-weight:bold;
+}
+
+#product_table{
+
+}
+
+#product_table td{
+
+}
+
+#pagination_table{
+	border-spacing:3px;
+	width:100%;
+}
+
+#pagination_table_result_hdr{
+	width:100px;
+	white-space: nowrap;
+	font-weight:bold;
+}
+
+/**
+ * FILE MANAGER: ProductBrowser.css
+**/ 
+#met_table{
+
+}
+
+#met_elem_name{
+	
+}
+
+#met_values_table{
+
+}
+
+.nada{
+	
+}
+
+#ref_table{
+	
+}
+
+#ref_table_hdr{
+	
+}
+
+/**
+ * FILE MANAGER: ProductRefsBrowser.css
+**/ 
+ 
+.nada{
+	
+}
+
+#ref_table{
+	
+}
+
+#ref_table_hdr{
+	
+}
+
+/**
+ * FILE MANAGER: ProductPaginator.css
+**/ 
+#paginator-break{
+  border:2;
+  width:100%;
+}
+
+#container-div{
+  width:100%;
+}
+
+#paginator-table{
+  border-spacing:3;
+  width:100;
+}
+
+#paginator-table-header{
+  width:100%;
+  white-space:nowrap;
+  font-weight:bold;
+}
+
+
+#page_repeater{
+
+}
+
+a, a:hover, a:focus, a:active{
+	text-decoration: none;
+}
+
+.selected{
+  font-weight:bold;
+  color:red;
+}
+
+/**
+ * FILE MANAGER: MetadataBrowser.css
+**/ 
+
+#met_table{
+
+}
+
+#met_elem_name{
+	
+}
+
+#met_values_table{
+
+}
+
+.nada{
+	
+}
+
+/**
+ * WORKFLOW MANAGER: Workflow Instances 
+**/
+#instance_filter_header p {
+    padding-left:20px;
+}
+a.workflow_status {
+    border-right:solid 1px #ccc;
+    padding-left:15px;
+    padding-right:15px;
+}
+#workflow_model_tbl td.task_bubble {
+	background-color: #333 !important;	/* NOTE: This overrides oodt-webapp-components's CSS value */
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage.css b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage.css
new file mode 100644
index 0000000..0f32f07
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage.css
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+#splash {
+    position:absolute;
+    left:50%;
+    top:50%;
+    margin:-180px 0 0 -370px;
+    height:260px;    
+    width:730px;
+    z-index:0;
+}
+#splash_branding {
+    padding:5px;
+    width:315px;
+    height:200px;
+    padding:32px 50px 30px 0;
+    text-align:right;
+    float:left;
+}
+#splash_nav {
+    float:left;
+    height:200px;
+    width:315px;
+    padding: 30px 0 30px 45px;
+    border-left:solid 1px #304050;
+}
+#splash_nav a {
+    display:block;
+    padding:10px;
+}  
+
+
+.border {
+    border-top: solid 1px #234;
+}
+
+
+
+#footer{
+  position:absolute;
+  bottom:20px;
+  width:100%;
+  padding:10px 0px;
+  border-spacing:0px;
+  border-top:solid 1px #2e3e4e;
+  color:#234;
+  font-size:90%;
+}
+
+#footer p {
+  width:100%;
+  padding:5px 15px;
+  text-align:center;
+}
+
+#powered {
+  margin-left:-30px;
+}
+
+
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage.html
new file mode 100644
index 0000000..d07aa4f
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage.html
@@ -0,0 +1,72 @@
+<!--
+ 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.
+-->
+<html
+	xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<head>
+<title>Apache OODT PCS Operator Interface</title>
+<wicket:link>
+  <link type="text/css" rel="stylesheet" href="HomePage.css"/>
+</wicket:link>
+</head>
+<body>
+<div id="splash">
+    <div id="splash_branding">
+        <wicket:link>
+            <img src="splash.png" id="splash_logo"/>
+        </wicket:link>
+    </div>
+    <div id="splash_nav">
+        <a href="#" wicket:id="fmbrowser_link" >
+					  <span>
+					    File Catalog Browse
+					  </span>
+					</a>
+        <a href="#" wicket:id="wmonitor_link" id="wmonitor_link" >
+					  <span>
+					    Workflow Monitor
+					  </span>
+					</a>
+        <a href="#" wicket:id="ganglia_link" >
+					  <span>
+					    Resource Monitor
+					  </span>
+					</a>
+        <a href="#" wicket:id="config_link">
+					  <span>
+					    Configuration
+					  </span>
+					</a>
+        <a href="#" wicket:id="pcsstatus_link" id="pcsstatus_link">
+					  <span>
+					    PCS Status
+					  </span>
+					</a>
+    </div>
+</div>
+
+
+
+
+
+<div id="footer">
+        <p id="powered">Powered by <a href="http://oodt.apache.org/">Apache OODT</a></p>
+</div>
+
+
+</body>
+
+</html>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage.java
new file mode 100644
index 0000000..50bc200
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage.java
@@ -0,0 +1,94 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.pcs.opsui;
+
+//Wicket imports
+import org.apache.oodt.pcs.opsui.config.ConfigPage;
+import org.apache.oodt.pcs.opsui.status.StatusPage;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.link.ExternalLink;
+import org.apache.wicket.markup.html.link.Link;
+
+/**
+ *
+ * Main home page of the web app.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class HomePage extends OPSUIWebPage {
+
+  protected OpsuiApp app;
+  
+  public HomePage(PageParameters parameters){
+    this.app = (OpsuiApp)getApplication();
+    
+    add(new Link("fmbrowser_link"){
+      /* (non-Javadoc)
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+       setResponsePage(TypesPage.class); 
+      }
+    });
+    
+    add(new Link("pcsstatus_link"){
+      
+    /* (non-Javadoc)
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        setResponsePage(StatusPage.class);
+        
+      }
+    });
+    
+    add(new Link("wmonitor_link"){
+       /* (non-Javadoc)
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        PageParameters params = new PageParameters();
+        params.add("status", "ALL");
+        params.add("pageNum", "1");
+        setResponsePage(WorkflowInstanceViewerPage.class, params);
+        
+      }
+    });
+    
+    add(new ExternalLink("ganglia_link", app.getGangliaUrl()));
+    
+    add(new Link("config_link"){
+      /* (non-Javadoc)
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        PageParameters params = new PageParameters();
+        params.add("tab", "File Manager");
+        setResponsePage(ConfigPage.class, params);  
+      }
+  });    
+  }
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage_cleanwhite.css b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage_cleanwhite.css
new file mode 100644
index 0000000..1825c94
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage_cleanwhite.css
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+/*
+ bg             #334455
+ borders-top    #2e3e4e
+ border-left    #304050
+*/
+
+body {
+    background-color:#FFF;
+    margin:0px;
+    padding:0px;
+    font-family: verdana, arial,  sans-serif;
+}
+
+#splash {
+    position:absolute;
+    left:50%;
+    top:50%;
+    margin:-180px 0 0 -370px;
+    height:260px;    
+    width:800px;
+    z-index:0;
+}
+#splash_branding {
+    padding:5px;
+    width:315px;
+    height:200px;
+    padding:32px 50px 30px 0;
+    text-align:right;
+    float:left;
+}
+#splash_nav {
+    float:left;
+    height:200px;
+    width:315px;
+    padding: 30px 0 30px 45px;
+    border-left:solid 1px #304050;
+}
+#splash_nav a {
+    display:block;
+    padding:10px;
+    text-decoration: none;
+    color:#193678;
+    font-weight: bolder;
+}  
+#splash_nav a:hover {
+    color:#4965A6;
+    text-decoration: none;
+}
+
+
+.border {
+    border-top: solid 1px #234;
+}
+
+
+
+#footer{
+  position:absolute;
+  bottom:20px;
+  width:100%;
+  padding:10px 0px;
+  border-spacing:0px;
+  border-top:solid 1px #2e3e4e;
+  color:#234;
+  font-size:90%;
+}
+#footer a {
+  color:#193678;
+}
+
+#footer p {
+  width:100%;
+  padding:5px 15px;
+  text-align:center;
+}
+
+#powered {
+  margin-left:-30px;
+}
+
+
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage_navyblue.css b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage_navyblue.css
new file mode 100644
index 0000000..cdb22ac
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/HomePage_navyblue.css
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+/*
+ bg             #334455
+ borders-top    #2e3e4e
+ border-left    #304050
+*/
+
+body {
+    background-color:#345;
+    margin:0px;
+    padding:0px;
+    font-family: arial, verdana, sans-serif;
+}
+
+#splash {
+    position:absolute;
+    left:50%;
+    top:50%;
+    margin:-180px 0 0 -370px;
+    height:260px;    
+    width:730px;
+    z-index:0;
+}
+#splash_branding {
+    padding:5px;
+    width:315px;
+    height:200px;
+    padding:32px 50px 30px 0;
+    text-align:right;
+    float:left;
+}
+#splash_nav {
+    float:left;
+    height:200px;
+    width:315px;
+    padding: 30px 0 30px 45px;
+    border-left:solid 1px #304050;
+}
+#splash_nav a {
+    display:block;
+    padding:10px;
+    color:#c0c0c0;
+    text-decoration:none;
+}  
+#splash_nav a:hover {
+    text-decoration:underline;
+    color:#fff;
+}
+
+
+.border {
+    border-top: solid 1px #234;
+}
+
+
+
+#footer{
+  position:absolute;
+  bottom:20px;
+  width:100%;
+  padding:10px 0px;
+  border-spacing:0px;
+  border-top:solid 1px #2e3e4e;
+  color:#234;
+  font-size:90%;
+  background-color:#364656;
+}
+#footer a {
+  color:#aaa;
+}
+
+#footer p {
+  width:100%;
+  padding:5px 15px;
+  text-align:center;
+}
+
+#powered {
+  margin-left:-30px;
+}
+
+
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/OPSUIWebPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/OPSUIWebPage.java
new file mode 100644
index 0000000..a0559e2
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/OPSUIWebPage.java
@@ -0,0 +1,45 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.opsui;
+
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.protocol.http.WebResponse;
+
+/**
+*
+* Extension of WebPage for customized features
+*
+* @author riverma
+* @version $Revision$
+*
+*/
+public class OPSUIWebPage extends WebPage {
+
+	  /**
+	   * Necessary to alleviate 'Page expired' caching issue.
+	   * See: http://www.richardnichols.net/2010/03/apache-wicket-force-page-reload-to-fix-ajax-back/
+	   */
+	  @Override
+	  protected void configureResponse() {
+	      super.configureResponse();
+	      WebResponse response = getWebRequestCycle().getWebResponse();
+	      response.setHeader("Cache-Control", 
+	            "no-cache, max-age=0,must-revalidate, no-store");
+	  } 
+	
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/OpsuiApp.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/OpsuiApp.java
new file mode 100644
index 0000000..5ef2e80
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/OpsuiApp.java
@@ -0,0 +1,258 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.opsui;
+
+//OODT imports
+import java.io.Serializable;
+import java.util.List;
+import java.util.Vector;
+
+import javax.servlet.ServletContext;
+
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.webcomponents.filemgr.FMBrowserSession;
+import org.apache.oodt.cas.webcomponents.workflow.instance.WorkflowInstancesViewer;
+import org.apache.oodt.pcs.opsui.config.ConfigPage;
+import org.apache.oodt.pcs.opsui.status.StatusPage;
+import org.apache.oodt.pcs.webcomponents.trace.Trace;
+
+//Wicket imports
+import org.apache.wicket.Page;
+import org.apache.wicket.Request;
+import org.apache.wicket.ResourceReference;
+import org.apache.wicket.Response;
+import org.apache.wicket.Session;
+import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.request.target.coding.MixedParamUrlCodingStrategy;
+
+/**
+ * 
+ * The OPSUI application object.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class OpsuiApp extends WebApplication implements Serializable {
+
+  private static final long serialVersionUID = 1403288657369282259L;
+
+  public OpsuiApp() {
+    MixedParamUrlCodingStrategy types = new MixedParamUrlCodingStrategy(
+        "types", TypesPage.class, new String[] {});
+
+    MixedParamUrlCodingStrategy typeBrowser = new MixedParamUrlCodingStrategy(
+        "type", TypeBrowserPage.class, new String[] { "name", "pageNum" });
+
+    MixedParamUrlCodingStrategy prodBrowser = new MixedParamUrlCodingStrategy(
+        "product", ProductBrowserPage.class, new String[] { "id" });
+
+    MixedParamUrlCodingStrategy pcsStatus = new MixedParamUrlCodingStrategy(
+        "status", StatusPage.class, new String[] {});
+
+    MixedParamUrlCodingStrategy taskPageMount = new MixedParamUrlCodingStrategy(
+        "task", WorkflowTaskViewerPage.class, new String[] { "id" });
+    MixedParamUrlCodingStrategy condPageMount = new MixedParamUrlCodingStrategy(
+        "condition", WorkflowConditionViewerPage.class, new String[] { "id" });
+
+    MixedParamUrlCodingStrategy workflowPageMount = new MixedParamUrlCodingStrategy(
+        "workflow", WorkflowViewerPage.class, new String[] { "id" });
+
+    MixedParamUrlCodingStrategy workflowsPageMount = new MixedParamUrlCodingStrategy(
+        "workflows", WorkflowsViewerPage.class, new String[] {});
+
+    MixedParamUrlCodingStrategy workflowInstsPageMount = new MixedParamUrlCodingStrategy(
+        "instances", WorkflowInstanceViewerPage.class, new String[] { "status",
+            "pageNum" });
+    
+    MixedParamUrlCodingStrategy configPageMount = new MixedParamUrlCodingStrategy("config", 
+        ConfigPage.class, new String [] {"tab"});
+
+    mount(pcsStatus);
+    mount(types);
+    mount(typeBrowser);
+    mount(prodBrowser);
+    mount(taskPageMount);
+    mount(condPageMount);
+    mount(workflowPageMount);
+    mount(workflowsPageMount);
+    mount(workflowInstsPageMount);
+    mount(configPageMount);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.wicket.Application#getHomePage()
+   */
+  @Override
+  public Class<? extends Page> getHomePage() {
+    try {
+      return (Class<? extends Page>) Class.forName(getHomePageClass());
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      return HomePage.class;
+    }
+  }
+
+  public String getFmUrlStr() {
+    return PathUtils.replaceEnvVariables(getServletContext().getInitParameter(
+        "filemgr.url"));
+  }
+
+  public String getWmUrlStr() {
+    return PathUtils.replaceEnvVariables(getServletContext().getInitParameter(
+        "workflow.url"));
+  }
+
+  public String getRmUrlStr() {
+    return PathUtils.replaceEnvVariables(getServletContext().getInitParameter(
+        "resmgr.url"));
+  }
+
+  public String getEmailContactLink() {
+    return getServletContext().getInitParameter("contact.email");
+  }
+
+  public String getCrawlerConfFilePath() {
+    return PathUtils.replaceEnvVariables(getServletContext().getInitParameter(
+        "org.apache.oodt.pcs.health.crawler.conf.filePath"));
+  }
+
+  public String getStatesFilePath() {
+    return PathUtils.replaceEnvVariables(getServletContext().getInitParameter(
+        "org.apache.oodt.pcs.health.workflow.statuses.filePath"));
+  }
+
+  public String getWorkflowLifecycleFilePath() {
+    return PathUtils.replaceEnvVariables(getServletContext().getInitParameter(
+        "org.apache.oodt.pcs.opsui.workflow.lifecycleFilePath"));
+  }
+
+  public String getGangliaUrl() {
+    return PathUtils.replaceEnvVariables(getServletContext().getInitParameter(
+        "ganglia.url"));
+  }
+
+  public String getSkin() {
+    return getServletContext().getInitParameter("opsui.skin");
+  }
+
+  public String getHomePageClass() {
+    return getServletContext().getInitParameter("opsui.homepage");
+  }
+
+  public List<String> getWorkflowInstStatues() {
+    String[] statuses = getServletContext().getInitParameter(
+        "org.apache.oodt.pcs.opsui.winst.statuses").split(",");
+    List<String> statusList = new Vector<String>();
+    for (String status : statuses) {
+      statusList.add(status.trim());
+    }
+    statusList.add("ALL");
+    return statusList;
+  }
+
+  public String getWorkflowInstMetFieldsFilePath() {
+    return PathUtils.replaceEnvVariables(getServletContext().getInitParameter(
+        "org.apache.oodt.pcs.opsui.winst.metFields.filePath"));
+  }
+
+  public boolean isEnabledTraceNotCatProducts() {
+    return Boolean.valueOf(getServletContext().getInitParameter(
+        "org.apache.oodt.pcs.trace.enableNotCat"));
+  }
+
+  public List<String> getTraceExcludedProductTypeList() {
+    String[] types = getServletContext().getInitParameter(
+        "org.apache.oodt.pcs.trace.excludeList").split(",");
+    List<String> excludes = new Vector<String>();
+
+    for (String type : types) {
+      excludes.add(type);
+    }
+
+    return excludes;
+
+  }
+
+  public String getRootContext() {
+    return getServletContext().getServletContextName();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.wicket.protocol.http.WebApplication#newSession(org.apache.wicket
+   * .Request, org.apache.wicket.Response)
+   */
+  @Override
+  public Session newSession(Request request, Response response) {
+    FMBrowserSession session = new FMBrowserSession(request);
+    if (getSkin() != null) {
+      session.setStyle(getSkin());
+    }
+    return session;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.wicket.protocol.http.WebApplication#init()
+   */
+  @Override
+  protected void init() {
+    super.init();
+
+    mountSharedResource("/images/percentImage_back1.png",
+        new ResourceReference(WorkflowInstancesViewer.class,
+            "percentImage_back1.png").getSharedResourceKey());
+    mountSharedResource("/images/percentImage_back2.png",
+        new ResourceReference(WorkflowInstancesViewer.class,
+            "percentImage_back2.png").getSharedResourceKey());
+    mountSharedResource("/images/percentImage_back3.png",
+        new ResourceReference(WorkflowInstancesViewer.class,
+            "percentImage_back3.png").getSharedResourceKey());
+    mountSharedResource("/images/percentImage_back4.png",
+        new ResourceReference(WorkflowInstancesViewer.class,
+            "percentImage_back4.png").getSharedResourceKey());
+
+    mountSharedResource("/images/icon_arrow_up.gif", new ResourceReference(
+        StatusPage.class, "icon_arrow_up.gif").getSharedResourceKey());
+
+    mountSharedResource("/images/rightcorner.gif", new ResourceReference(
+        BasePage.class, "rightcorner.gif").getSharedResourceKey());
+    mountSharedResource("/images/leftcorner.gif", new ResourceReference(
+        BasePage.class, "leftcorner.gif").getSharedResourceKey());
+    mountSharedResource("/images/selrightcorner.gif", new ResourceReference(
+        BasePage.class, "selrightcorner.gif").getSharedResourceKey());
+    mountSharedResource("/images/selleftcorner.gif", new ResourceReference(
+        BasePage.class, "selleftcorner.gif").getSharedResourceKey());
+
+    mountSharedResource("/images/open.gif", new ResourceReference(Trace.class,
+        "open.gif").getSharedResourceKey());
+    mountSharedResource("/images/closed.gif", new ResourceReference(
+        Trace.class, "closed.gif").getSharedResourceKey());
+    
+    mountSharedResource("/images/tab_bottom.gif", new ResourceReference(ConfigPage.class, 
+        "tab_bottom.gif").getSharedResourceKey());
+
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductBrowserPage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductBrowserPage.html
new file mode 100644
index 0000000..660fd96
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductBrowserPage.html
@@ -0,0 +1,19 @@
+<!--
+ 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.
+-->
+<wicket:extend>
+ <div id="prod_browser_component" wicket:id="prod_browser_component"/>
+</wicket:extend>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductBrowserPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductBrowserPage.java
new file mode 100644
index 0000000..c1c26c4
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductBrowserPage.java
@@ -0,0 +1,45 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.pcs.opsui;
+
+//OODT imports
+import org.apache.oodt.pcs.opsui.pedigree.TraceableProductBrowser;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+
+/**
+ *
+ * Shows a product, its metadata, and its references, all 
+ * on a single page.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class ProductBrowserPage extends BasePage {
+
+  public ProductBrowserPage(PageParameters parameters){
+    super(parameters);
+    add(new TraceableProductBrowser("prod_browser_component", 
+        app.getFmUrlStr(),
+        parameters.getString("id"), app.isEnabledTraceNotCatProducts(), 
+        app.getTraceExcludedProductTypeList()));
+  }
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductMetBrowserPage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductMetBrowserPage.html
new file mode 100644
index 0000000..0b3f5a1
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductMetBrowserPage.html
@@ -0,0 +1,19 @@
+<!--
+ 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.
+-->
+<wicket:extend>
+  <div id="met_browser_component" wicket:id="met_browser_component"/>
+</wicket:extend>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductMetBrowserPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductMetBrowserPage.java
new file mode 100644
index 0000000..5e44209
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductMetBrowserPage.java
@@ -0,0 +1,43 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.pcs.opsui;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.filemgr.browser.metadata.MetadataBrowser;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+
+/**
+ *
+ * Show's a product's metadata.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class ProductMetBrowserPage extends BasePage {
+  
+  public ProductMetBrowserPage(PageParameters parameters){
+    super(parameters);
+    add(new MetadataBrowser("met_browser_component", app.getFmUrlStr(), 
+        parameters.getString("id")));
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductRefBrowserPage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductRefBrowserPage.html
new file mode 100644
index 0000000..9f58c0d
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductRefBrowserPage.html
@@ -0,0 +1,19 @@
+<!--
+ 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.
+-->
+<wicket:extend>
+  <div id="refs_component" wicket:id="refs_component"/>
+</wicket:extend>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductRefBrowserPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductRefBrowserPage.java
new file mode 100644
index 0000000..e96a463
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/ProductRefBrowserPage.java
@@ -0,0 +1,45 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.pcs.opsui;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.filemgr.browser.product.ProductRefsBrowser;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+
+/**
+ *
+ * Page that shows a Product's reference 
+ * information.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class ProductRefBrowserPage extends BasePage {
+  
+  public ProductRefBrowserPage(PageParameters parameters){
+    super(parameters);    
+    add(new ProductRefsBrowser("refs_component",
+        app.getFmUrlStr(),
+        parameters.getString("id")));
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/TypeBrowserPage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/TypeBrowserPage.html
new file mode 100644
index 0000000..9461f6c
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/TypeBrowserPage.html
@@ -0,0 +1,20 @@
+<!--
+ 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.
+-->
+<wicket:extend>
+
+ <div wicket:id="type_browser_component" id="type_browser_component"/>
+</wicket:extend>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/TypeBrowserPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/TypeBrowserPage.java
new file mode 100644
index 0000000..4e7972f
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/TypeBrowserPage.java
@@ -0,0 +1,46 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.pcs.opsui;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.filemgr.browser.types.TypeBrowser;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+
+/**
+ *
+ * The type browser page that shows a table including 
+ * all of the queried products for a given type and a 
+ * query selection form.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class TypeBrowserPage extends BasePage {
+
+  public TypeBrowserPage(PageParameters parameters){
+    super(parameters);
+    add(new TypeBrowser("type_browser_component", app.getFmUrlStr(),
+        parameters.getString("name"), parameters.getInt("pageNum", 1),        
+        TypeBrowserPage.class, ProductBrowserPage.class, ProductRefBrowserPage.class, 
+        ProductMetBrowserPage.class));
+  }
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/TypesPage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/TypesPage.html
new file mode 100644
index 0000000..5abc6bd
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/TypesPage.html
@@ -0,0 +1,19 @@
+<!--
+ 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.
+-->
+<wicket:extend>
+  <div id="types_component" wicket:id="types_component"/>
+</wicket:extend>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/TypesPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/TypesPage.java
new file mode 100644
index 0000000..98a4a61
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/TypesPage.java
@@ -0,0 +1,42 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.opsui;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.filemgr.browser.types.Types;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+
+/**
+ * 
+ * The types page that shows type names and bucket counts
+ * (that are clickable).
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TypesPage extends BasePage {
+
+  public TypesPage(PageParameters parameters) {
+    super(parameters);    
+    add(new Types("types_component",
+       app.getFmUrlStr(), TypeBrowserPage.class));
+  }
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowConditionViewerPage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowConditionViewerPage.html
new file mode 100755
index 0000000..3357acc
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowConditionViewerPage.html
@@ -0,0 +1,20 @@
+<!--
+ 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.
+-->
+<wicket:extend>
+<div id="breadcrumbs"><a href="#" wicket:id="crumb_home_link">Home</a>&nbsp;<span class="divider">/</span>&nbsp;Conditions&nbsp;<span class="divider">/</span>&nbsp;<span wicket:id="cond_id">urn:oodt:TestCondition</span></div>
+<div wicket:id="cond_viewer"/>
+</wicket:extend>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowConditionViewerPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowConditionViewerPage.java
new file mode 100644
index 0000000..3459875
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowConditionViewerPage.java
@@ -0,0 +1,47 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.opsui;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.workflow.conditions.WorkflowConditionViewer;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+
+/**
+ * 
+ * Page controller for the WorkflowConditionViewerPage.html file.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowConditionViewerPage extends WorkflowCrumbedPage {
+
+  /**
+   * @param parameters
+   */
+  public WorkflowConditionViewerPage(PageParameters parameters) {
+    super(parameters);
+    add(new WorkflowConditionViewer("cond_viewer", app.getWmUrlStr(),
+        parameters.getString("id")));
+    add(new Label("cond_id", parameters.getString("id")));
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowCrumbedPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowCrumbedPage.java
new file mode 100644
index 0000000..e0116a9
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowCrumbedPage.java
@@ -0,0 +1,55 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.pcs.opsui;
+
+//OODT imports
+import org.apache.oodt.pcs.opsui.status.StatusPage;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.link.Link;
+
+/**
+ *
+ * Adds a bread crumb link to the OPSUI app home, 
+ * the PCS status page.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class WorkflowCrumbedPage extends BasePage {
+
+  /**
+   * @param parameters
+   */
+  public WorkflowCrumbedPage(PageParameters parameters) {
+    super(parameters);
+    add(new Link("crumb_home_link"){
+      /* (non-Javadoc)
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        setResponsePage(StatusPage.class);        
+      }
+    });
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowInstanceViewerPage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowInstanceViewerPage.html
new file mode 100755
index 0000000..73afe46
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowInstanceViewerPage.html
@@ -0,0 +1,20 @@
+<!--
+ 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.
+-->
+<wicket:extend>
+<div id="breadcrumbs"><a href="#" wicket:id="crumb_home_link">Home</a>&nbsp;<span class="divider">/</span>&nbsp;Instances&nbsp;</div>
+<div wicket:id="instance_viewer"/>
+</wicket:extend>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowInstanceViewerPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowInstanceViewerPage.java
new file mode 100644
index 0000000..2e820ad
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowInstanceViewerPage.java
@@ -0,0 +1,51 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.pcs.opsui;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.workflow.instance.WorkflowInstancesViewer;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+
+/**
+ *
+ * Shows a set of workflow instances.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class WorkflowInstanceViewerPage extends WorkflowCrumbedPage {
+
+  /**
+   * @param parameters
+   */
+  public WorkflowInstanceViewerPage(PageParameters parameters) {
+    super(parameters);
+    OpsuiApp app = (OpsuiApp)getApplication();
+    add(new WorkflowInstancesViewer("instance_viewer", 
+        app.getWmUrlStr(), parameters.getString("status"), 
+        parameters.getInt("pageNum", 1), 
+        app.getWorkflowInstStatues(), app.getWorkflowLifecycleFilePath(), 
+        app.getWorkflowInstMetFieldsFilePath(), WorkflowViewerPage.class, 
+        WorkflowTaskViewerPage.class, WorkflowInstanceViewerPage.class));
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowTaskViewerPage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowTaskViewerPage.html
new file mode 100755
index 0000000..32277e8
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowTaskViewerPage.html
@@ -0,0 +1,21 @@
+<!--
+ 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.
+-->
+<wicket:extend>
+<div id="breadcrumbs"><a href="#" wicket:id="crumb_home_link">Home</a>&nbsp;<span class="divider">/</span>&nbsp;Tasks&nbsp;<span class="divider">/</span>&nbsp;<span wicket:id="task_id">urn:oodt:LongTask</span></div>
+<h3>Workflow Task Metadata:</h3>
+<div wicket:id="task_viewer" id="task_viewer"/>
+</wicket:extend>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowTaskViewerPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowTaskViewerPage.java
new file mode 100644
index 0000000..5ea0de1
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowTaskViewerPage.java
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.pcs.opsui;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.workflow.tasks.WorkflowTaskViewer;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+
+/**
+ *
+ * Controller for the TaskViewerPage.html.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class WorkflowTaskViewerPage extends WorkflowCrumbedPage {
+
+  /**
+   * @param parameters
+   */
+  public WorkflowTaskViewerPage(PageParameters parameters) {
+    super(parameters);
+    add(new WorkflowTaskViewer("task_viewer", app.getWmUrlStr(),
+        parameters.getString("id"), WorkflowConditionViewerPage.class));
+    add(new Label("task_id", parameters.getString("id")));
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowViewerPage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowViewerPage.html
new file mode 100755
index 0000000..0c5c21c
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowViewerPage.html
@@ -0,0 +1,21 @@
+<!--
+ 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.
+-->
+<wicket:extend>
+<div id="breadcrumbs"><a href="#" wicket:id="crumb_home_link">Home</a>&nbsp;<span class="divider">/</span>&nbsp;<a href="#" wicket:id="workflows_viewer_link">Workflows</a>&nbsp;<span class="divider">/</span>&nbsp;<span wicket:id="workflow_id">urn:oodt:LongWorkflow</span></div>
+<h3>Workflow Details:</h3>
+<div wicket:id="workflow_viewer" id="workflow_viewer"/>
+</wicket:extend>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowViewerPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowViewerPage.java
new file mode 100644
index 0000000..32876ca
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowViewerPage.java
@@ -0,0 +1,58 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.opsui;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.workflow.model.WorkflowViewer;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.Link;
+
+/**
+ * 
+ * Controller for the WorkflowViewerPage.html.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowViewerPage extends WorkflowCrumbedPage {
+
+  /**
+   * @param parameters
+   */
+  public WorkflowViewerPage(PageParameters parameters) {
+    super(parameters);
+    add(new WorkflowViewer("workflow_viewer", app.getWmUrlStr(),
+        parameters.getString("id"), WorkflowTaskViewerPage.class));
+    add(new Link("workflows_viewer_link"){
+        /* (non-Javadoc)
+         * @see org.apache.wicket.markup.html.link.Link#onClick()
+         */
+        @Override
+        public void onClick() {
+          setResponsePage(WorkflowsViewerPage.class);          
+        }
+    });
+    
+    add(new Label("workflow_id", parameters.getString("id")));
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowsViewerPage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowsViewerPage.html
new file mode 100755
index 0000000..45167fb
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowsViewerPage.html
@@ -0,0 +1,20 @@
+<!--
+ 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.
+-->
+<wicket:extend>
+<div id="breadcrumbs"><a href="#" wicket:id="crumb_home_link">Home</a>&nbsp;<span class="divider">/</span>&nbsp;Workflows&nbsp;</div>
+<div wicket:id="workflows_viewer" id="workflows_viewer"/>
+</wicket:extend>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowsViewerPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowsViewerPage.java
new file mode 100644
index 0000000..26f0de6
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/WorkflowsViewerPage.java
@@ -0,0 +1,47 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.pcs.opsui;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.workflow.model.WorkflowsViewer;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+
+/**
+ *
+ * Page controller for the WorkflowsViewerPage.html.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class WorkflowsViewerPage extends WorkflowCrumbedPage {
+
+  /**
+   * @param parameters
+   */
+  public WorkflowsViewerPage(PageParameters parameters) {
+    super(parameters);
+    add(new WorkflowsViewer("workflows_viewer", app.getWmUrlStr(),
+        WorkflowViewerPage.class));
+  
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/banner.jpg b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/banner.jpg
new file mode 100755
index 0000000..f0e8a1a
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/banner.jpg
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/ConfigPage.css b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/ConfigPage.css
new file mode 100644
index 0000000..ee7af16
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/ConfigPage.css
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+div.tabpanel div.tab-row ul {
+    height: 20px;
+    margin: 0;
+    padding-left: 10px;
+    background: url( ../../images/tab_bottom.gif ) repeat-x bottom;
+}
+
+div.tabpanel div.tab-row li {
+    margin: 0;
+    padding: 0;
+    display: inline;
+    list-style-type: none;
+}
+
+div.tabpanel div.tab-row a:link, div.tabpanel div.tab-row a:visited {
+    float: left;
+    background: #f3f3f3;
+    font-size: 12px;
+    line-height: 14px;
+    font-weight: bold;
+    padding: 2px 10px 2px 10px;
+    margin-right: 4px;
+    border: 1px solid #ccc;
+    text-decoration: none;
+    color: #666;
+}
+
+div.tabpanel div.tab-row li.selected a:link, div.tabpanel div.tab-row a:visited.active {
+    border-bottom: 1px solid #fff;
+    background: #fff;
+    color: #000;
+}
+
+div.tabpanel div.tab-row a:hover {
+    background: #fff;
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/ConfigPage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/ConfigPage.html
new file mode 100644
index 0000000..bcd9087
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/ConfigPage.html
@@ -0,0 +1,24 @@
+<!--
+ 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.
+-->
+<wicket:extend>
+<wicket:link>
+  <link rel="stylesheet" type="text/css" href="ConfigPage.css"/>
+</wicket:link>
+
+<p>&nbsp;</p>
+<div wicket:id="tabs" class="tabpanel">[tabbed panel will be here]</div>
+</wicket:extend>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/ConfigPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/ConfigPage.java
new file mode 100644
index 0000000..561ba8d
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/ConfigPage.java
@@ -0,0 +1,119 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.opsui.config;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.oodt.pcs.opsui.BasePage;
+import org.apache.oodt.pcs.opsui.config.filemgr.FileManagerConfigPage;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.apache.wicket.extensions.markup.html.tabs.TabbedPanel;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ConfigPage extends BasePage {
+
+  /**
+   * @param parameters
+   */
+  public ConfigPage(PageParameters parameters) {
+    super(parameters);
+
+    List<ITab> tabs = new Vector<ITab>();
+    tabs.add(new AbstractTab(new Model<String>("File Manager")) {
+      @Override
+      public Panel getPanel(String id) {
+        return new FileManagerConfigPage(id);
+      }
+    });
+
+    tabs.add(new AbstractTab(new Model<String>("Workflow Manager")) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see
+       * org.apache.wicket.extensions.markup.html.tabs.AbstractTab#getPanel(
+       * java.lang.String)
+       */
+      @Override
+      public Panel getPanel(String id) {
+        // TODO Auto-generated method stub
+        return null;
+      }
+    });
+
+    tabs.add(new AbstractTab(new Model<String>("Resource Manager")) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see
+       * org.apache.wicket.extensions.markup.html.tabs.AbstractTab#getPanel(
+       * java.lang.String)
+       */
+      @Override
+      public Panel getPanel(String arg0) {
+        // TODO Auto-generated method stub
+        return null;
+      }
+    });
+
+    tabs.add(new AbstractTab(new Model<String>("PGE Configuration")) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see
+       * org.apache.wicket.extensions.markup.html.tabs.AbstractTab#getPanel(
+       * java.lang.String)
+       */
+      @Override
+      public Panel getPanel(String arg0) {
+        // TODO Auto-generated method stub
+        return null;
+      }
+    });
+
+    TabbedPanel tabbedPanel = new TabbedPanel("tabs", tabs);
+    tabbedPanel.setSelectedTab(getTabIdx(tabs,
+        parameters.getString("tab", "File Manager")));
+
+    add(tabbedPanel);
+  }
+
+  private int getTabIdx(List<ITab> tabs, String tabName) {
+    for (int i = 0; i < tabs.size(); i++) {
+      ITab tab = tabs.get(i);
+      if (tab.getTitle().getObject().equals(tabName)) {
+        return i;
+      }
+    }
+
+    return -1;
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/filemgr/FileManagerConfigPage.css b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/filemgr/FileManagerConfigPage.css
new file mode 100644
index 0000000..518ee56
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/filemgr/FileManagerConfigPage.css
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+#fm_cfg_outer_shell{
+	width:100%;
+	height:570px;
+	border-spacing:0px;
+	border: 1px solid #000000;
+}
+
+#sixpadded{
+	width:100px;
+	border:1px solid #000000;
+	border-spacing:0px;
+	padding: 6px;
+}
+
+
+td.fcfg_header{
+	white-space:nowrap;
+	text-align:right;
+	font-weight:bold;
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/filemgr/FileManagerConfigPage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/filemgr/FileManagerConfigPage.html
new file mode 100644
index 0000000..43e819f
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/filemgr/FileManagerConfigPage.html
@@ -0,0 +1,104 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:link>
+  <link rel="stylesheet" type="text/css" href="FileManagerConfigPage.css"/>
+</wicket:link>
+<div id="form_shell">
+<p>&nbsp;</p>
+	<form>
+		<table id="fm_cfg_outer_shell">
+			<tr style="height:10%">
+				<td>
+					<table id="sixpadded">
+						<tr>
+							<td class="fcfg_header">Port Number:&nbsp;&nbsp;
+							</td>
+							<td style="text-align:left;"><input id="port_number" size="20"
+								maxlength="50" value="9000" />
+							</td>
+							<td colspan="2">&nbsp;</td>
+						</tr>
+						<tr>
+							<td class="fcfg_header">Transfer:
+							</td>
+							<td colspan="3">&nbsp;</td>
+						</tr>
+						<tr id="transfer_types">
+							<td>&nbsp;</td>
+							<td>&nbsp;&nbsp;<input type="radio" id="transfer_type" value="org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory">Local</input>
+							<wicket:remove>
+							   <input type="radio" id="transfer_type" value="org.apache.oodt.cas.filemgr.datatransfer.RemoteDataTransferFactory">Remote</input>
+							</wicket:remove>
+							</td>
+							<td colspan="2">&nbsp;</td>
+						</tr>
+						<tr>
+							<td colspan="2">&nbsp;</td>
+							<td class="fcfg_header">Chunk Size:
+							</td>
+							<td align="left"><input type="text" id="remote_chunk_size"
+								size="20" maxlength="50" value="" />
+							</td>
+						</tr>
+					</table></td>
+			</tr>
+			<tr style="height:25%">
+				<td>
+					<!-- include catalog jsp --></td>
+			</tr>
+			<tr style="height:25%;">
+				<td>
+					<!-- include Repository jsp --></td>
+			</tr>
+			<tr style="height:25%;">
+				<td>
+					<!-- include Validation jsp --></td>
+			</tr>
+			<tr style="height:10%;">
+				<td>
+					<table style="width:100%">
+						<tr>
+							<td colspan="2" class="fcfg_header"><b>XML-RPL Configuration:</b>
+							</td>
+						</tr>
+						<tr>
+							<td style="width:30%" class="fcfg_header">Connection Timeout:&nbsp;&nbsp;<input
+								type="text" id="connection_time_out" size="20" value="20" />
+							</td>
+							<td style="width:30%" class="fcfg_header">Request Timeout:&nbsp;&nbsp;<input
+								type="text" id="request_timeout" size="20" value="60" />
+							</td>
+						</tr>
+					</table>
+				</td>
+			</tr>
+			<tr style="height:5%;">
+				<td>
+					<table style="width:100%">
+						<tr>
+							<td align="right"><input
+								type="submit" id="save_fm_cfg" value="Save"/>
+							</td>
+						</tr>
+					</table>
+			    </td>
+			</tr>
+		</table>
+	</form>
+</div>
+</wicket:panel>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/filemgr/FileManagerConfigPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/filemgr/FileManagerConfigPage.java
new file mode 100644
index 0000000..01a6103
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/filemgr/FileManagerConfigPage.java
@@ -0,0 +1,43 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.pcs.opsui.config.filemgr;
+
+import org.apache.wicket.markup.html.panel.Panel;
+
+/**
+ *
+ * Describe your class here.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class FileManagerConfigPage extends Panel {
+
+  private static final long serialVersionUID = 145336240434428919L;
+
+  /**
+   * @param id
+   */
+  public FileManagerConfigPage(String id) {
+    super(id);
+  }
+
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/tab_bottom.gif b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/tab_bottom.gif
new file mode 100644
index 0000000..da70aaf
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/config/tab_bottom.gif
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/footer_image1.gif b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/footer_image1.gif
new file mode 100755
index 0000000..ac94b17
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/footer_image1.gif
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/footer_image2.gif b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/footer_image2.gif
new file mode 100755
index 0000000..66836c1
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/footer_image2.gif
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/jquery-1.7.min.js b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/jquery-1.7.min.js
new file mode 100644
index 0000000..3ca5e0f
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/jquery-1.7.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.7 jquery.com | jquery.org/license */
+(function(a,b){function cA(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cx(a){if(!cm[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cn||(cn=c.createElement("iframe"),cn.frameBorder=cn.width=cn.height=0),b.appendChild(cn);if(!co||!cn.createElement)co=(cn.contentWindow||cn.contentDocument).document,co.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),co.close();d=co.createElement(a),co.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cn)}cm[a]=e}return cm[a]}function cw(a,b){var c={};f.each(cs.concat.apply([],cs.slice(0,b)),function(){c[this]=a});return c}function cv(){ct=b}function cu(){setTimeout(cv,0);return ct=f.now()}function cl(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ck(){try{return new a.XMLHttpRequest}catch(b){}}function ce(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cd(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function cc(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bG.test(a)?d(a,e):cc(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)cc(a+"["+e+"]",b[e],c,d);else d(a,b)}function cb(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function ca(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bV,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=ca(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=ca(a,c,d,e,"*",g));return l}function b_(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bR),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bE(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bz:bA;if(d>0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bB(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function br(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bi,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bq(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bp(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bp)}function bp(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bo(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bn(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bm(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bl(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function X(a){var b=Y.split(" "),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function W(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(R.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(){return!0}function M(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function K(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(K,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z]|[0-9])/ig,x=/^-ms-/,y=function(a,b){return(b+"").toUpperCase()},z=d.userAgent,A,B,C,D=Object.prototype.toString,E=Object.prototype.hasOwnProperty,F=Array.prototype.push,G=Array.prototype.slice,H=String.prototype.trim,I=Array.prototype.indexOf,J={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7",length:0,size:function(){return this.length},toArray:function(){return G.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?F.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),B.add(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(G.apply(this,arguments),"slice",G.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:F,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;B.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!B){B=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",C,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",C),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&K()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return a!=null&&m.test(a)&&!isNaN(a)},type:function(a){return a==null?String(a):J[D.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!E.call(a,"constructor")&&!E.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||E.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(x,"ms-").replace(w,y)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:H?function(a){return a==null?"":H.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?F.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(I)return I.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=G.call(arguments,2),g=function(){return a.apply(c,f.concat(G.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){J["[object "+b+"]"]=b.toLowerCase()}),A=e.uaMatch(z),A.browser&&(e.browser[A.browser]=!0,e.browser.version=A.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?C=function(){c.removeEventListener("DOMContentLoaded",C,!1),e.ready()}:c.attachEvent&&(C=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",C),e.ready())}),typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return e});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){return i.done.apply(i,arguments).fail.apply(i,arguments)},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;a.setAttribute("className","t"),a.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/><nav></nav>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,unknownElems:!!a.getElementsByTagName("nav").length,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",enctype:!!c.createElement("form").enctype,submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.lastChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},m&&f.extend(p,{position:"absolute",left:"-999px",top:"-999px"});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;f(function(){var a,b,d,e,g,h,i=1,j="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",l="visibility:hidden;border:0;",n="style='"+j+"border:5px solid #000;padding:0;'",p="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>";m=c.getElementsByTagName("body")[0];!m||(a=c.createElement("div"),a.style.cssText=l+"width:0;height:0;position:static;top:0;margin-top:"+i+"px",m.insertBefore(a,m.firstChild),o=c.createElement("div"),o.style.cssText=j+l,o.innerHTML=p,a.appendChild(o),b=o.firstChild,d=b.firstChild,g=b.nextSibling.firstChild.firstChild,h={doesNotAddBorder:d.offsetTop!==5,doesAddBorderForTableAndCells:g.offsetTop===5},d.style.position="fixed",d.style.top="20px",h.fixedPosition=d.offsetTop===20||d.offsetTop===15,d.style.position=d.style.top="",b.style.overflow="hidden",b.style.position="relative",h.subtractsBorderForOverflowNotVisible=d.offsetTop===-5,h.doesNotIncludeMarginInBodyOffset=m.offsetTop!==i,m.removeChild(a),o=a=null,f.extend(k,h))}),o.innerHTML="",n.removeChild(o),o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[f.expando]:a[f.expando]&&f.expando,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[f.expando]=n=++f.uuid:n=f.expando),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[f.expando]:f.expando;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)?b=b:b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" "));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[f.expando]:a.removeAttribute?a.removeAttribute(f.expando):a[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];if(!arguments.length){if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}return b}e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!a||j===3||j===8||j===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g},removeAttr:function(a,b){var c,d,e,g,h=0;if(a.nodeType===1){d=(b||"").split(p),g=d.length;for(;h<g;h++)e=d[h].toLowerCase(),c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1)}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return b;h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/\.(.*)$/,A=/^(?:textarea|input|select)$/i,B=/\./g,C=/ /g,D=/[^\w\s.|`]/g,E=/^([^\.]*)?(?:\.(.+))?$/,F=/\bhover(\.\S+)?/,G=/^key/,H=/^(?:mouse|contextmenu)|click/,I=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,J=function(a){var b=I.exec(a);b&&
+(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},K=function(a,b){return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||a.id===b[2])&&(!b[3]||b[3].test(a.className))},L=function(a){return f.event.special.hover?a:a.replace(F,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=L(c).split(" ");for(k=0;k<c.length;k++){l=E.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,namespace:n.join(".")},p),g&&(o.quick=J(g),!o.quick&&f.expr.match.POS.test(g)&&(o.isPositional=!0)),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d){var e=f.hasData(a)&&f._data(a),g,h,i,j,k,l,m,n,o,p,q;if(!!e&&!!(m=e.events)){b=L(b||"").split(" ");for(g=0;g<b.length;g++){h=E.exec(b[g])||[],i=h[1],j=h[2];if(!i){j=j?"."+j:"";for(l in m)f.event.remove(a,l+j,c,d);return}n=f.event.special[i]||{},i=(d?n.delegateType:n.bindType)||i,p=m[i]||[],k=p.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;if(c||j||d||n.remove)for(l=0;l<p.length;l++){q=p[l];if(!c||c.guid===q.guid)if(!j||j.test(q.namespace))if(!d||d===q.selector||d==="**"&&q.selector)p.splice(l--,1),q.selector&&p.delegateCount--,n.remove&&n.remove.call(a,q)}else p.length=0;p.length===0&&k!==p.length&&((!n.teardown||n.teardown.call(a,j)===!1)&&f.removeEvent(a,i,e.handle),delete m[i])}f.isEmptyObject(m)&&(o=e.handle,o&&(o.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"",(g||!e)&&c.preventDefault();if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,n=null;for(m=e.parentNode;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length;l++){m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d);if(c.isPropagationStopped())break}c.type=h,c.isDefaultPrevented()||(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=(f.event.special[c.type]||{}).handle,j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click"))for(m=c.target;m!=this;m=m.parentNode||this){o={},q=[];for(k=0;k<e;k++)r=d[k],s=r.selector,t=o[s],r.isPositional?t=(t||(o[s]=f(s))).index(m)>=0:t===b&&(t=o[s]=r.quick?K(m,r.quick):f(m).is(s)),t&&q.push(r);q.length&&j.push({elem:m,matches:q})}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){p=j[k],c.currentTarget=p.elem;for(l=0;l<p.matches.length&&!c.isImmediatePropagationStopped();l++){r=p.matches[l];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=(i||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement wheelDelta".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},focus:{delegateType:"focusin",noBubble:!0},blur:{delegateType:"focusout",noBubble:!0},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?N:M):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=N;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=N;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=N,this.stopPropagation()},isDefaultPrevented:M,isPropagationStopped:M,isImmediatePropagationStopped:M},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]=f.event.special[b]={delegateType:b,bindType:b,handle:function(a){var b=this,c=a.relatedTarget,d=a.handleObj,e=d.selector,g,h;if(!c||d.origType===a.type||c!==b&&!f.contains(b,c))g=a.type,a.type=d.origType,h=d.handler.apply(this,arguments),a.type=g;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(A.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;A.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return A.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=M;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=M);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),G.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),H.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw"Syntax error, unrecognized expression: "+a};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var O=/Until$/,P=/^(?:parents|prevUntil|prevAll)/,Q=/,/,R=/^.[^:#\[\.,]*$/,S=Array.prototype.slice,T=f.expr.match.POS,U={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(W(this,a,!1),"not",a)},filter:function(a){return this.pushStack(W(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?T.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var Y="abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",Z=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,_=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,ba=/<([\w:]+)/,bb=/<tbody/i,bc=/<|&#?\w+;/,bd=/<(?:script|style)/i,be=/<(?:script|object|embed|option|style)/i,bf=new RegExp("<(?:"+Y.replace(" ","|")+")","i"),bg=/checked\s*(?:[^=]|=\s*.checked.)/i,bh=/\/(java|ecma)script/i,bi=/^\s*<!(?:\[CDATA\[|\-\-)/,bj={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bk=X(c);bj.optgroup=bj.option,bj.tbody=bj.tfoot=bj.colgroup=bj.caption=bj.thead,bj.th=bj.td,f.support.htmlSerialize||(bj._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after"
+,arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Z,""):null;if(typeof a=="string"&&!bd.test(a)&&(f.support.leadingWhitespace||!$.test(a))&&!bj[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(_,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bg.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bl(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,br)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!be.test(j)&&(f.support.checkClone||!bg.test(j))&&!f.support.unknownElems&&bf.test(j)&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bn(a,d),e=bo(a),g=bo(d);for(h=0;e[h];++h)g[h]&&bn(e[h],g[h])}if(b){bm(a,d);if(c){e=bo(a),g=bo(d);for(h=0;e[h];++h)bm(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!bc.test(k))k=b.createTextNode(k);else{k=k.replace(_,"<$1></$2>");var l=(ba.exec(k)||["",""])[1].toLowerCase(),m=bj[l]||bj._default,n=m[0],o=b.createElement("div");b===c?bk.appendChild(o):X(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=bb.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&$.test(k)&&o.insertBefore(b.createTextNode($.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bq(k[i]);else bq(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||bh.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bs=/alpha\([^)]*\)/i,bt=/opacity=([^)]*)/,bu=/([A-Z]|^ms)/g,bv=/^-?\d+(?:px)?$/i,bw=/^-?\d/,bx=/^([\-+])=([\-+.\de]+)/,by={position:"absolute",visibility:"hidden",display:"block"},bz=["Left","Right"],bA=["Top","Bottom"],bB,bC,bD;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bB(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bx.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bB)return bB(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bE(a,b,d);f.swap(a,by,function(){e=bE(a,b,d)});return e}},set:function(a,b){if(!bv.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bt.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bs,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bs.test(g)?g.replace(bs,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bB(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bC=function(a,c){var d,e,g;c=c.replace(bu,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bD=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bv.test(f)&&bw.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bB=bC||bD,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bF=/%20/g,bG=/\[\]$/,bH=/\r?\n/g,bI=/#.*$/,bJ=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bK=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bL=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bM=/^(?:GET|HEAD)$/,bN=/^\/\//,bO=/\?/,bP=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bQ=/^(?:select|textarea)/i,bR=/\s+/,bS=/([?&])_=[^&]*/,bT=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bU=f.fn.load,bV={},bW={},bX,bY,bZ=["*/"]+["*"];try{bX=e.href}catch(b$){bX=c.createElement("a"),bX.href="",bX=bX.href}bY=bT.exec(bX.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bU)return bU.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bP,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bQ.test(this.nodeName)||bK.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bH,"\r\n")}}):{name:b.name,value:c.replace(bH,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?cb(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),cb(a,b);return a},ajaxSettings:{url:bX,isLocal:bL.test(bY[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bZ},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:b_(bV),ajaxTransport:b_(bW),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cd(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=ce(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bJ.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bI,"").replace(bN,bY[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bR),d.crossDomain==null&&(r=bT.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bY[1]&&r[2]==bY[2]&&(r[3]||(r[1]==="http:"?80:443))==(bY[3]||(bY[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),ca(bV,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bM.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bO.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bS,"$1_="+x);d.url=y+(y===d.url?(bO.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bZ+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=ca(bW,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){s<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)cc(g,a[g],c,e);return d.join("&").replace(bF,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cf=f.now(),cg=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cf++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cg.test(b.url)||e&&cg.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cg,l),b.url===j&&(e&&(k=k.replace(cg,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ch=a.ActiveXObject?function(){for(var a in cj)cj[a](0,1)}:!1,ci=0,cj;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ck()||cl()}:ck,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ch&&delete cj[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++ci,ch&&(cj||(cj={},f(a).unload(ch)),cj[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cm={},cn,co,cp=/^(?:toggle|show|hide)$/,cq=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cr,cs=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],ct;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cw("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cx(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cw("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cw("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cx(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cp.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=cq.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cw("show",1),slideUp:cw("hide",1),slideToggle:cw("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=ct||cu(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cr&&(cr=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=ct||cu(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cr),cr=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now))}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cy=/^t(?:able|d|h)$/i,cz=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cA(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cy.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cz.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cz.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cA(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cA(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window);
\ No newline at end of file
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/leftcorner.gif b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/leftcorner.gif
new file mode 100755
index 0000000..57c779d
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/leftcorner.gif
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/nasa_logo.gif b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/nasa_logo.gif
new file mode 100755
index 0000000..ad93603
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/nasa_logo.gif
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/pedigree/TraceableProductBrowser.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/pedigree/TraceableProductBrowser.html
new file mode 100644
index 0000000..5781a61
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/pedigree/TraceableProductBrowser.html
@@ -0,0 +1,64 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:remove>
+  <link rel="stylesheet" type="text/css" href="ProductBrowser.css"/>
+</wicket:remove>
+
+<h3>Product: <span wicket:id="product_name">foo.txt</span></h3>
+<p><form wicket:id="trace_form"><input type="submit" value="Trace" wicket:id="trace_button" id="trace_button"/></form></p>
+<p>Percent Transferred: <span wicket:id="product_pct_transfer">100%</span></p>
+<a href="#References">Jump to References</a>
+                
+<h3>Metadata</h3>
+  <table id="met_table">
+    <tr wicket:id="met_elem">
+      <td wicket:id="met_elem_name" id="met_elem_name">CAS.ProductName</td>
+      <td>
+         <table id="met_values_table">
+          <tr wicket:id="met_values_list">
+             <td wicket:id="met_value">foo.txt</td>
+          </tr>
+         </table>
+      </td>
+     </tr>
+   </table>
+   
+   <h3 wicket:id="no_prod_met_display" class="nada">No Product Metadata!</h3>
+   <p>&nbsp;</p>
+   <p>&nbsp;</p>
+   <a name="References"></a>
+
+<h3>References</h3>
+  <table id="ref_table">
+    <tr id="ref_table_hdr">
+      <td>File Location</td>
+      <td>File Size</td>
+      <td>Percent Transferred</td>
+    </tr>
+    <tr wicket:id="ref_list">
+      <td><a wicket:id="ref_file_path_link" href="#"><span wicket:id="ref_file_path">/home/files/foo.txt/foo.txt</span></a></td>
+      <td wicket:id="ref_file_size">4028</td>
+      <td wicket:id="ref_pct_transferred">100%</td>
+    </tr>
+  </table>
+
+  <h3 wicket:id="no_prod_ref_display" class="nada">No Product References!</h3>
+  
+
+<span wicket:id="pedigree"/>
+</wicket:panel>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/pedigree/TraceableProductBrowser.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/pedigree/TraceableProductBrowser.java
new file mode 100644
index 0000000..3be7677
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/pedigree/TraceableProductBrowser.java
@@ -0,0 +1,154 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.opsui.pedigree;
+
+//JDK imports
+import java.io.File;
+import java.net.URI;
+import java.text.NumberFormat;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.apache.oodt.cas.webcomponents.filemgr.FileManagerConn;
+import org.apache.oodt.cas.webcomponents.filemgr.browser.product.ProductBrowser;
+import org.apache.oodt.pcs.opsui.OpsuiApp;
+import org.apache.oodt.pcs.webcomponents.trace.Trace;
+
+//Wicket imports
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Button;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.link.ExternalLink;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.model.util.ListModel;
+
+/**
+ * 
+ * Extends the existing {@link ProductBrowser} and adds a Web form and
+ * associated pedigree tree container to expose the {@link Trace} component.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TraceableProductBrowser extends ProductBrowser {
+
+  private static final long serialVersionUID = 5512878676145737818L;
+
+  private static final Logger LOG = Logger
+      .getLogger(TraceableProductBrowser.class.getName());
+
+  /**
+   * @param componentId
+   * @param fmUrlStr
+   * @param productId
+   */
+  public TraceableProductBrowser(String componentId, final String fmUrlStr,
+      final String productId, final boolean enableNotCat, final List<String> excludes) {
+    super(componentId, fmUrlStr, productId);
+    final FileManagerConn fm = new FileManagerConn(fmUrlStr);
+    final Product product = fm.safeGetProductById(productId);
+    final OpsuiApp app = (OpsuiApp)getApplication();
+
+    Form traceForm = new Form("trace_form");
+    traceForm.add(new Button("trace_button") {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see org.apache.wicket.markup.html.form.Button#onSubmit()
+       */
+      @Override
+      public void onSubmit() {
+        Trace tracer = new Trace("pedigree", fmUrlStr, enableNotCat, excludes,
+            product);
+        tracer.setVisible(true);
+        getParent().getParent().replace(tracer);
+        setVisible(false);
+      }
+
+    });
+    add(traceForm);
+    add(new WebMarkupContainer("pedigree").setVisible(false));
+
+    List<Reference> refs = fm.getProductReferences(product);
+    if (refs != null && refs.size() > 0) {
+      replace(new Label("no_prod_ref_display") {
+        /*
+         * (non-Javadoc)
+         * 
+         * @see org.apache.wicket.Component#isVisible()
+         */
+        @Override
+        public boolean isVisible() {
+          return false;
+        }
+      });
+
+      replace(new ListView<Reference>("ref_list", new ListModel<Reference>(refs)) {
+        /*
+         * (non-Javadoc)
+         * 
+         * @see
+         * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+         * .wicket.markup.html.list.ListItem)
+         */
+        @Override
+        protected void populateItem(ListItem<Reference> refItem) {
+          Reference r = refItem.getModelObject();
+          String filePath = null;
+          try {
+            filePath = new File(new URI(r.getDataStoreReference()))
+                .getAbsolutePath();
+          } catch (Exception ignore) {
+          }
+          
+          ExternalLink refLink = new ExternalLink("ref_file_path_link", 
+              "/" + app.getRootContext() + "/data?productID="+productId);
+          refLink.add(new Label("ref_file_path", filePath));
+          refItem.add(refLink);
+          refItem.add(new Label("ref_file_size",
+              String.valueOf(r.getFileSize())));
+          try {
+            refItem.add(new Label("ref_pct_transferred", NumberFormat
+                .getPercentInstance()
+                .format(fm.getFm().getRefPctTransferred(r))));
+          } catch (DataTransferException e) {
+            LOG.log(
+                Level.WARNING,
+                "Unable to determine product reference size: Reason: "
+                    + e.getMessage());
+            refItem.add(new Label("ref_pct_transferred", "N/A"));
+          }
+
+        }
+      });
+    } else {
+      replace(new Label("no_prod_ref_display", "No Product References!"));
+    }
+
+  }
+  
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/project_logo.png b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/project_logo.png
new file mode 100644
index 0000000..278a1e3
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/project_logo.png
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/project_logo_cleanwhite.png b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/project_logo_cleanwhite.png
new file mode 100644
index 0000000..278a1e3
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/project_logo_cleanwhite.png
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/project_logo_navyblue.png b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/project_logo_navyblue.png
new file mode 100644
index 0000000..d78091c
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/project_logo_navyblue.png
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/rightcorner.gif b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/rightcorner.gif
new file mode 100755
index 0000000..59772da
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/rightcorner.gif
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/selleftcorner.gif b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/selleftcorner.gif
new file mode 100755
index 0000000..48987bf
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/selleftcorner.gif
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/selrightcorner.gif b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/selrightcorner.gif
new file mode 100755
index 0000000..da79c1b
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/selrightcorner.gif
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/spacer.gif b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/spacer.gif
new file mode 100755
index 0000000..46a2cf0
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/spacer.gif
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/splash.png b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/splash.png
new file mode 100644
index 0000000..f1eb6dc
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/splash.png
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/splash_cleanwhite.png b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/splash_cleanwhite.png
new file mode 100644
index 0000000..f1eb6dc
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/splash_cleanwhite.png
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/splash_navyblue.png b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/splash_navyblue.png
new file mode 100644
index 0000000..91215a1
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/splash_navyblue.png
Binary files differ
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/status/StatusPage.css b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/status/StatusPage.css
new file mode 100644
index 0000000..23c852c
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/status/StatusPage.css
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+#widenoborder{
+  width:100%;
+  border:0px;
+}
+
+#fm_status{
+
+}
+
+#wm_status{
+
+}
+
+#rm_status{
+
+}
+
+#report_date{
+
+}
+
+.roundtable table{
+border-top: 2px solid #bbb8a9;
+border-bottom: 2px solid #bbb8a9;
+border-left: 2px solid #bbb8a9;
+border-right: 2px solid #bbb8a9;
+}
+
+.nowrap{
+  white-space:nowrap;
+}
+
+.heading{
+  font-size:14px;
+  font-weight:bold;
+}
+
+.avg_crawl_time{
+
+}
+
+.num_crawls{
+
+}
+
+.crawler_name{
+
+}
+
+.file_ingest_datetime{
+
+}
+
+.file_path{
+
+}
+
+.status_name{
+
+}
+
+.batch_stub_url{
+
+}
+
+.crawler_name_and_url{
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/status/StatusPage.html b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/status/StatusPage.html
new file mode 100644
index 0000000..3da31dd
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/status/StatusPage.html
@@ -0,0 +1,24 @@
+<!--
+ 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.
+-->
+<wicket:extend>
+<wicket:link>
+<link rel="stylesheet" type="text/css" href="StatusPage.css"/>
+</wicket:link>
+
+<div wicket:id="health_monitor" id="health_monitor"/>
+
+</wicket:extend>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/status/StatusPage.java b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/status/StatusPage.java
new file mode 100644
index 0000000..7bbd7ad
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/java/org/apache/oodt/pcs/opsui/status/StatusPage.java
@@ -0,0 +1,60 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.opsui.status;
+
+//OODT imports
+import org.apache.oodt.pcs.opsui.ProductBrowserPage;
+import org.apache.oodt.pcs.opsui.BasePage;
+import org.apache.oodt.pcs.opsui.OpsuiApp;
+import org.apache.oodt.pcs.opsui.WorkflowInstanceViewerPage;
+import org.apache.oodt.pcs.tools.PCSHealthMonitor;
+import org.apache.oodt.pcs.webcomponents.health.HealthMonitor;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+
+/**
+ * 
+ * A wicket controller for exposing the super awesome power of the
+ * {@link PCSHealthMonitor}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class StatusPage extends BasePage {
+
+  /**
+   * @param parameters
+   * @throws InstantiationException
+   */
+  public StatusPage(PageParameters parameters) throws InstantiationException {
+    super(parameters);
+
+    OpsuiApp app = (OpsuiApp) getApplication();
+    String fmUrlStr = app.getFmUrlStr();
+    String wmUrlStr = app.getWmUrlStr();
+    String rmUrlStr = app.getRmUrlStr();
+    String crawlerConfFilePath = app.getCrawlerConfFilePath();
+    String statesFilePath = app.getStatesFilePath();
+    add(new HealthMonitor("health_monitor", fmUrlStr, wmUrlStr, rmUrlStr,
+        crawlerConfFilePath, statesFilePath, ProductBrowserPage.class,
+        WorkflowInstanceViewerPage.class));
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/opsui/src/main/webapp/META-INF/context.xml b/0.8.1-rc1/pcs/opsui/src/main/webapp/META-INF/context.xml
new file mode 100755
index 0000000..2542fa2
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,68 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<Context path="/pcs-opsui">
+		
+	<Parameter name="filemgr.url"
+	    value="[FILEMGR_URL]"/>		
+	
+	<Parameter name="workflow.url"
+	    value="[WORKFLOW_URL]"/>
+
+	<Parameter name="resmgr.url"
+	    value="[RESMGR_URL]"/>
+
+	<Parameter name="org.apache.oodt.pcs.opsui.workflow.lifecycleFilePath"
+	    value="[WORKFLOW_HOME]/policy/wengine/wengine-lifecycle.xml"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.opsui.winst.statuses"
+	    value="Null, Loaded, Queued, Blocked, WaitingOnResources, PreConditionSuccess, ExecutionComplete, Unknown, Paused, PreConditionEval, Executing, PostConditionEval, ResultsSuccess, ResultsFailure, ResultsBail, Stopped, Off, Failure, Success"/>
+	
+	<!-- <Parameter name="org.apache.oodt.pcs.opsui.winst.statuses"
+	    value="QUEUED, RSUBMIT, BUILDING CONFIG FILE, PGE EXEC, CRAWLING, STAGING INPUT, FINISHED, STARTED, PAUSED"/>-->
+	    
+	<Parameter name="org.apache.oodt.pcs.opsui.winst.metFields.filePath"
+	    value="[WORKFLOW_HOME]/policy/workflow-instance-met.xml"/>   
+	    
+	<Parameter name="org.apache.oodt.pcs.health.crawler.conf.filePath"
+	    value="[PCS_HOME]/aux/pcs/pcs-crawlers.xml"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.health.workflow.statuses.filePath"
+	    value="[PCS_HOME]/aux/pcs/pcs-workflow-statuses.xml"/>	    
+	    
+	<Parameter name="org.apache.oodt.pcs.trace.excludeList"
+	    value=""/>
+	
+	<Parameter name="org.apache.oodt.pcs.trace.enableNotCat"
+	    value="true"/>
+	 
+	<Parameter name="ganglia.url" value="[GANGLIA_URL]"/>
+	<Parameter name="contact.email" value="user@oodt.apache.org"/>
+
+	<!-- OPSUI SKINNING
+		Directions: Set the 'opsui.skin' property's value attribute. 
+		Supported skins:
+			""           => No skin
+			"cleanwhite" => Clean, white background OODT base skin
+			"navyblue"   => Darker, blue background OODT base skin
+			"classic"    => The original, OCO (Orbiting Carbon Observatory) skin for OPSUI
+		OR add your own!
+	-->
+	<Parameter name="opsui.skin" value="cleanwhite"/>
+	<Parameter name="opsui.homepage" value="org.apache.oodt.pcs.opsui.HomePage"/>
+	    
+</Context>
diff --git a/0.8.1-rc1/pcs/opsui/src/main/webapp/WEB-INF/web.xml b/0.8.1-rc1/pcs/opsui/src/main/webapp/WEB-INF/web.xml
new file mode 100755
index 0000000..12c3743
--- /dev/null
+++ b/0.8.1-rc1/pcs/opsui/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ 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.
+-->
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+	 version="2.4">
+
+	<display-name>pcs-opsui</display-name>
+
+	 <!--  
+	      There are three means to configure Wickets configuration mode and they are
+	      tested in the order given. 
+	      1) A system property: -Dwicket.configuration
+	      2) servlet specific <init-param>
+	      3) context specific <context-param>
+	      The value might be either "development" (reloading when templates change)
+	      or "deployment". If no configuration is found, "development" is the default.
+	-->
+
+	<filter>
+		<filter-name>wicket.browser</filter-name>
+ 		<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
+		<init-param>
+			<param-name>applicationClassName</param-name>
+			<param-value>org.apache.oodt.pcs.opsui.OpsuiApp</param-value>
+ 		</init-param>
+ 	</filter>
+
+ <filter-mapping>
+  <filter-name>wicket.browser</filter-name>
+	<url-pattern>/*</url-pattern>
+ </filter-mapping>
+ 
+  <context-param>
+    <param-name>filemgr.working.dir</param-name>
+    <param-value>/tmp</param-value>
+  </context-param>
+
+  <servlet>
+    <servlet-name>DataDeliveryServlet</servlet-name>
+    <servlet-class>org.apache.oodt.cas.product.data.DataDeliveryServlet</servlet-class>
+  </servlet>
+  <servlet>
+    <servlet-name>DatasetDeliveryServlet</servlet-name>
+    <servlet-class>org.apache.oodt.cas.product.data.DatasetDeliveryServlet</servlet-class>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>DataDeliveryServlet</servlet-name>
+    <url-pattern>/data</url-pattern>
+  </servlet-mapping>
+  
+  <servlet-mapping>
+    <servlet-name>DatasetDeliveryServlet</servlet-name>
+    <url-pattern>/dataset</url-pattern>
+  </servlet-mapping>  
+ 
+
+
+</web-app>
diff --git a/0.8.1-rc1/pcs/services/pom.xml b/0.8.1-rc1/pcs/services/pom.xml
new file mode 100644
index 0000000..99a83c0
--- /dev/null
+++ b/0.8.1-rc1/pcs/services/pom.xml
@@ -0,0 +1,57 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../../core/pom.xml</relativePath>
+  </parent>
+  <groupId>org.apache.oodt</groupId>
+  <artifactId>pcs-services</artifactId>
+  <packaging>war</packaging>
+  <name>OODT Process Control System JAX-RS service layer</name>
+  <description>A web application for exposing services form the underlying 
+  OODT Process Control System via the JAX-RS specification.</description>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>pcs-core</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>net.sf.json-lib</groupId>
+      <artifactId>json-lib</artifactId>
+      <version>2.3</version>
+      <classifier>jdk15</classifier>
+    </dependency>
+    <dependency>
+       <groupId>servletapi</groupId>
+       <artifactId>servletapi</artifactId>
+       <version>2.4</version>
+       <scope>provided</scope>
+    </dependency>
+   <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+      <version>2.3.1</version>
+   </dependency>
+  </dependencies>
+
+</project>
diff --git a/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/HealthResource.java b/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/HealthResource.java
new file mode 100644
index 0000000..cb43eef
--- /dev/null
+++ b/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/HealthResource.java
@@ -0,0 +1,388 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.services;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//JAX-RS imports
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+//JSON imports
+import net.sf.json.JSONObject;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.pcs.health.CrawlerHealth;
+import org.apache.oodt.pcs.health.CrawlerStatus;
+import org.apache.oodt.pcs.health.JobHealthStatus;
+import org.apache.oodt.pcs.health.PCSDaemonStatus;
+import org.apache.oodt.pcs.health.PCSHealthMonitorMetKeys;
+import org.apache.oodt.pcs.health.PCSHealthMonitorReport;
+import org.apache.oodt.pcs.tools.PCSHealthMonitor;
+import org.apache.oodt.pcs.util.FileManagerUtils;
+
+/**
+ * 
+ * The JAX-RS resource exposing the {@link PCSHealthMonitor}.
+ * 
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+@Path("health")
+public class HealthResource extends PCSService {
+
+  private static final long serialVersionUID = -7768836001459227323L;
+
+  private static final Logger LOG = Logger.getLogger(HealthResource.class
+      .getName());
+
+  private PCSHealthMonitor mon;
+
+  public HealthResource() throws MalformedURLException, InstantiationException {
+    super();
+    mon = new PCSHealthMonitor(PCSService.conf.getFmUrl().toString(),
+        PCSService.conf.getWmUrl().toString(), PCSService.conf.getRmUrl()
+            .toString(), PCSService.conf.getCrawlerConfigFilePath(),
+        PCSService.conf.getWorkflowStatusesFilePath());
+  }
+
+  @GET
+  @Path("report")
+  @Produces("text/plain")
+  public String healthReport() {
+    PCSHealthMonitorReport report = mon.getReport();
+    Map<String, Object> output = new HashMap<String, Object>();
+    output.put("generated", report.getCreateDateIsoFormat());
+    output.put("daemonStatus", this.encodeDaemonOutput(report));
+    output.put("crawlerStatus", this.encodeCrawlerHealthReportOutput(report));
+    output.put("latestFiles", this.encodeLatestFilesOutput(report));
+    output.put("jobHealth", this.encodeJobHealthStatusList(report));
+    output.put("ingestHealth", this.encodeIngestHealthList(report));
+    return this.encodeReportAsJson(output);
+  }
+
+  @GET
+  @Path("report/ingest")
+  @Produces("text/plain")
+  public String ingestReport() {
+    PCSHealthMonitorReport report = mon.getReport();
+    Map<String, Object> output = new HashMap<String, Object>();
+    output.put("generated", report.getCreateDateIsoFormat());
+    output.put("ingestHealth", this.encodeIngestHealthList(report));
+    return this.encodeReportAsJson(output);
+  }
+
+  @GET
+  @Path("report/ingest/{cname}")
+  @Produces("text/plain")
+  public String ingestReportByName(@PathParam("cname") String crawlerName) {
+    PCSHealthMonitorReport report = mon.getReport();
+    Map<String, Object> output = new HashMap<String, Object>();
+    output.put("generated", report.getCreateDateIsoFormat());
+    output.put("ingestHealth", this
+        .encodeIngestHealthList(report, crawlerName));
+    return this.encodeReportAsJson(output);
+  }
+
+  @GET
+  @Path("report/jobs")
+  @Produces("text/plain")
+  public String jobsReport() {
+    PCSHealthMonitorReport report = mon.getReport();
+    Map<String, Object> output = new HashMap<String, Object>();
+    output.put("generated", report.getCreateDateIsoFormat());
+    output.put("jobHealth", this.encodeJobHealthStatusList(report));
+    return this.encodeReportAsJson(output);
+  }
+
+  @GET
+  @Path("report/jobs/{state}")
+  @Produces("text/plain")
+  public String jobsReportByState(@PathParam("state") String jobState) {
+    PCSHealthMonitorReport report = mon.getReport();
+    Map<String, Object> output = new HashMap<String, Object>();
+    output.put("generated", report.getCreateDateIsoFormat());
+    output.put("jobHealth", this.encodeJobHealthStatusList(report, jobState));
+    return this.encodeReportAsJson(output);
+  }
+
+  @GET
+  @Path("report/daemon")
+  @Produces("text/plain")
+  public String daemonReport() {
+    PCSHealthMonitorReport report = mon.getReport();
+    Map<String, Object> output = new HashMap<String, Object>();
+    output.put("generated", report.getCreateDateIsoFormat());
+    output.put("daemonStatus", this.encodeDaemonOutput(report));
+    return this.encodeReportAsJson(output);
+  }
+
+  @GET
+  @Path("report/daemon/{dname}")
+  @Produces("text/plain")
+  public String daemonReportByName(@PathParam("dname") String daemonName) {
+    PCSHealthMonitorReport report = mon.getReport();
+    Map<String, Object> output = new HashMap<String, Object>();
+    output.put("generated", report.getCreateDateIsoFormat());
+    output.put("daemonStatus", this.encodeDaemonOutput(report, daemonName));
+    return this.encodeReportAsJson(output);
+
+  }
+
+  @GET
+  @Path("report/crawlers")
+  @Produces("text/plain")
+  public String crawlerHealthReport() {
+    PCSHealthMonitorReport report = mon.getReport();
+    Map<String, Object> output = new HashMap<String, Object>();
+    output.put("generated", report.getCreateDateIsoFormat());
+    output.put("crawlerStatus", this.encodeCrawlerHealthReportOutput(report));
+    return this.encodeReportAsJson(output);
+  }
+
+  @GET
+  @Path("report/crawlers/{cname}")
+  @Produces("text/plain")
+  public String getCrawlerHealthReportByName(
+      @PathParam("cname") String crawlerName) {
+    PCSHealthMonitorReport report = mon.getReport();
+    Map<String, Object> output = new HashMap<String, Object>();
+    output.put("generated", report.getCreateDateIsoFormat());
+    output.put("crawlerStatus", this.encodeCrawlerHealthReportOutput(report,
+        crawlerName));
+    return this.encodeReportAsJson(output);
+  }
+
+  @GET
+  @Path("report/latestfiles")
+  @Produces("text/plain")
+  public String getLatestIngestedFiles() {
+    PCSHealthMonitorReport report = mon.getReport();
+    Map<String, Object> output = new HashMap<String, Object>();
+    output.put("generated", report.getCreateDateIsoFormat());
+    output.put("latestFiles", this.encodeLatestFilesOutput(report));
+    return this.encodeReportAsJson(output);
+  }
+
+  private String encodeReportAsJson(Map<String, Object> reportHash) {
+    JSONObject response = new JSONObject();
+    response.put("report", reportHash);
+    return response.toString();
+  }
+
+  private Map<String, Object> encodeCrawlerHealth(CrawlerHealth health) {
+    Map<String, Object> output = new HashMap<String, Object>();
+    output.put("crawler", health.getCrawlerName());
+    output.put("avgCrawlTime", health.getAvgCrawlTime());
+    output.put("numCrawls", health.getNumCrawls());
+    return output;
+  }
+
+  private Map<String, Object> encodeJobStatus(JobHealthStatus status) {
+    Map<String, Object> output = new HashMap<String, Object>();
+    output.put("state", status.getStatus());
+    output.put("numJobs", status.getNumPipelines());
+    return output;
+  }
+
+  private void encodeLatestFile(List<Object> latestFilesOutput, Product p)
+      throws MalformedURLException {
+    FileManagerUtils fm = new FileManagerUtils(PCSService.conf.getFmUrl());
+    p.setProductType(fm.safeGetProductTypeById(p.getProductType()
+        .getProductTypeId()));
+    p.setProductReferences(fm.safeGetProductReferences(p));
+    Metadata prodMet = fm.safeGetMetadata(p);
+    if (prodMet == null)
+      prodMet = new Metadata();
+    Map<String, Object> fileOutput = new HashMap<String, Object>();
+    fileOutput.put("filepath", fm.getFilePath(p));
+    fileOutput.put("receivedTime", prodMet.getMetadata("CAS."
+        + CoreMetKeys.PRODUCT_RECEVIED_TIME) != null ? prodMet
+        .getMetadata("CAS." + CoreMetKeys.PRODUCT_RECEVIED_TIME) : "UNKNOWN");
+    latestFilesOutput.add(fileOutput);
+  }
+
+  private Map<String, String> encodeCrawlerStatus(CrawlerStatus status) {
+    Map<String, String> output = new HashMap<String, String>();
+    output.put("crawlerName", status.getInfo().getCrawlerName());
+    output.put("crawlerPort", status.getInfo().getCrawlerPort());
+    output.put("url", status.getCrawlHost());
+    output.put("status", status.getStatus());
+    return output;
+  }
+
+  private List<Object> encodeIngestHealthList(PCSHealthMonitorReport report,
+      String... crawlerName) {
+    List<Object> crawlerHealthList = new Vector<Object>();
+    if (crawlerName.length > 0) {
+      boolean found = false;
+      for (CrawlerHealth ch : (List<CrawlerHealth>) (List<?>) report
+          .getCrawlerHealthStatus()) {
+        if (ch.getCrawlerName().equals(crawlerName[0])) {
+          crawlerHealthList.add(this.encodeCrawlerHealth(ch));
+          found = true;
+          break;
+        }
+      }
+      if (!found)
+        throw new ResourceNotFoundException(
+            "No ingest crawler found with name: [" + crawlerName[0] + "]");
+    } else {
+      for (CrawlerHealth ch : (List<CrawlerHealth>) (List<?>) report
+          .getCrawlerHealthStatus()) {
+        crawlerHealthList.add(this.encodeCrawlerHealth(ch));
+      }
+    }
+    return crawlerHealthList;
+  }
+
+  private List<Object> encodeJobHealthStatusList(PCSHealthMonitorReport report,
+      String... jobState) {
+    List<Object> jobStatusList = new Vector<Object>();
+    if (jobState.length > 0) {
+      boolean found = false;
+      for (JobHealthStatus js : (List<JobHealthStatus>) (List<?>) report
+          .getJobHealthStatus()) {
+        if (js.getStatus().equals(jobState[0])) {
+          jobStatusList.add(this.encodeJobStatus(js));
+          found = true;
+          break;
+        }
+      }
+      if (!found)
+        throw new ResourceNotFoundException(
+            "Unable to find any jobs with associated state: [" + jobState[0]
+                + "]");
+    } else {
+      for (JobHealthStatus js : (List<JobHealthStatus>) (List<?>) report
+          .getJobHealthStatus()) {
+        jobStatusList.add(this.encodeJobStatus(js));
+      }
+    }
+    return jobStatusList;
+  }
+
+  private Map<String, Object> encodeLatestFilesOutput(
+      PCSHealthMonitorReport report) {
+    Map<String, Object> latestFilesOutput = new HashMap<String, Object>();
+    latestFilesOutput.put("topN", PCSHealthMonitor.TOP_N_PRODUCTS);
+    List<Object> latestFilesList = new Vector<Object>();
+    for (Product prod : (List<Product>) (List<?>) report
+        .getLatestProductsIngested()) {
+      try {
+        this.encodeLatestFile(latestFilesList, prod);
+      } catch (MalformedURLException e) {
+        LOG.log(Level.WARNING, "Unable to encode latest file: ["
+            + prod.getProductName() + "]: error: Message: " + e.getMessage());
+      }
+    }
+    latestFilesOutput.put("files", latestFilesList);
+    return latestFilesOutput;
+  }
+
+  private List<Object> encodeCrawlerHealthReportOutput(
+      PCSHealthMonitorReport report, String... crawlerName) {
+    List<Object> crawlerOutput = new Vector<Object>();
+    if (crawlerName.length > 0) {
+      boolean found = false;
+      for (CrawlerStatus cs : (List<CrawlerStatus>) (List<?>) report
+          .getCrawlerStatus()) {
+        if (cs.getInfo().getCrawlerName().equals(crawlerName[0])) {
+          crawlerOutput.add(this.encodeCrawlerStatus(cs));
+          found = true;
+          break;
+        }
+      }
+      if (!found)
+        throw new ResourceNotFoundException(
+            "Unable to find any crawlers with name: [" + crawlerName[0] + "]");
+    } else {
+      for (CrawlerStatus cs : (List<CrawlerStatus>) (List<?>) report
+          .getCrawlerStatus()) {
+        crawlerOutput.add(this.encodeCrawlerStatus(cs));
+      }
+    }
+
+    return crawlerOutput;
+  }
+
+  private Map<String, Object> encodeDaemonOutput(PCSHealthMonitorReport report,
+      String... daemonName) {
+    Map<String, Object> daemonOutput = new HashMap<String, Object>();
+    if (daemonName.length > 0) {
+      if (daemonName[0].equals("fm")) {
+        daemonOutput.put("fm", this.encodeDaemonStatus(report.getFmStatus()));
+      } else if (daemonName[0].equals("wm")) {
+        daemonOutput.put("wm", this.encodeDaemonStatus(report.getWmStatus()));
+      } else if (daemonName[0].equals("rm")) {
+        daemonOutput.put("rm", this.encodeDaemonStatus(report.getRmStatus()));
+      } else if (daemonName[0].equals("stubs")) {
+        if (report.getRmStatus().getStatus().equals(
+            PCSHealthMonitorMetKeys.STATUS_UP)) {
+          // print out the batch stubs
+          List<Object> stubs = new Vector<Object>();
+          for (PCSDaemonStatus bStatus : (List<PCSDaemonStatus>) (List<?>) report
+              .getBatchStubStatus()) {
+            stubs.add(this.encodeDaemonStatus(bStatus));
+          }
+          daemonOutput.put("stubs", stubs);
+        } else
+          throw new ResourceNotFoundException(
+              "Resource Manager not running so no batch stubs to check.");
+      } else
+        throw new ResourceNotFoundException("Daemon not found");
+    } else {
+      daemonOutput.put("fm", this.encodeDaemonStatus(report.getFmStatus()));
+      daemonOutput.put("wm", this.encodeDaemonStatus(report.getWmStatus()));
+      daemonOutput.put("rm", this.encodeDaemonStatus(report.getRmStatus()));
+      if (report.getRmStatus().getStatus().equals(
+          PCSHealthMonitorMetKeys.STATUS_UP)) {
+        // print out the batch stubs
+        List<Object> stubs = new Vector<Object>();
+        for (PCSDaemonStatus bStatus : (List<PCSDaemonStatus>) (List<?>) report
+            .getBatchStubStatus()) {
+          stubs.add(this.encodeDaemonStatus(bStatus));
+        }
+        daemonOutput.put("stubs", stubs);
+      }
+    }
+    return daemonOutput;
+  }
+
+  private Map<String, String> encodeDaemonStatus(PCSDaemonStatus status) {
+    Map<String, String> output = new HashMap<String, String>();
+    output.put("daemon", status.getDaemonName());
+    output.put("url", status.getUrlStr());
+    output.put("status", status.getStatus());
+    return output;
+  }
+}
diff --git a/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/PCSService.java b/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/PCSService.java
new file mode 100644
index 0000000..2e6e24d
--- /dev/null
+++ b/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/PCSService.java
@@ -0,0 +1,75 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.services;
+
+//JDK imports
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+
+//JAX-RS imports
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+//OODT imports
+import org.apache.oodt.pcs.services.config.PCSServiceConfig;
+
+
+/**
+ *
+ * Base class for PCS JAX-RS services. Loads up 
+ * the {@link PCSServiceConfig} and makes it available
+ * statically to downstream descendants.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class PCSService extends HttpServlet {
+
+  protected static final long serialVersionUID = 6256089700429938496L;
+  
+  protected static PCSServiceConfig conf;
+  
+
+  /* (non-Javadoc)
+   * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
+   */
+  @Override
+  public void init(ServletConfig config) throws ServletException {
+    super.init(config);
+    conf = new PCSServiceConfig(config);
+  }
+  
+
+  protected class ResourceNotFoundException extends WebApplicationException {
+
+    public ResourceNotFoundException() {
+      super(Response.status(Status.NOT_FOUND).type(MediaType.TEXT_PLAIN)
+          .build());
+    }
+
+    public ResourceNotFoundException(String msg) {
+      super(Response.status(Status.NOT_FOUND).entity(msg).type(
+          MediaType.TEXT_PLAIN).build());
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/PedigreeResource.java b/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/PedigreeResource.java
new file mode 100644
index 0000000..b8b3eb0
--- /dev/null
+++ b/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/PedigreeResource.java
@@ -0,0 +1,123 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.services;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+//JAX-RS imports
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+//JSON imports
+import net.sf.json.JSONObject;
+
+//OODT imports
+import org.apache.oodt.pcs.pedigree.Pedigree;
+import org.apache.oodt.pcs.pedigree.PedigreeTree;
+import org.apache.oodt.pcs.pedigree.PedigreeTreeNode;
+import org.apache.oodt.pcs.util.FileManagerUtils;
+
+/**
+ * 
+ * Exposes the {@link Pedigree} API of the PCS to provide an upstream and
+ * downstream lineage of a particular OODT {@link Product} using JAX-RS.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+@Path("pedigree")
+public class PedigreeResource extends PCSService {
+
+  private static final long serialVersionUID = 4851623546718112205L;
+
+  private Pedigree trace;
+
+  private FileManagerUtils fm;
+
+  public PedigreeResource() throws MalformedURLException {
+    this.fm = new FileManagerUtils(PCSService.conf.getFmUrl());
+    this.trace = new Pedigree(this.fm, PCSService.conf
+        .isTraceNotCatalogedFiles(), Arrays.asList(PCSService.conf
+        .getTraceProductTypeExcludeList().split(",")));
+  }
+
+  @GET
+  @Path("report/{filename}")
+  @Produces("text/plain")
+  public String generatePedigree(@PathParam("filename") String filename) {
+    PedigreeTree upstreamTree = this.trace.doPedigree(this.fm
+        .safeGetProductByName(filename), true);
+    PedigreeTree downstreamTree = this.trace.doPedigree(this.fm
+        .safeGetProductByName(filename), false);
+    return this.encodePedigreeAsJson(upstreamTree, downstreamTree);
+  }
+
+  @GET
+  @Path("report/{filename}/upstream")
+  @Produces("text/plain")
+  public String generateUpstreamPedigree(@PathParam("filename") String filename) {
+    PedigreeTree upstreamTree = this.trace.doPedigree(this.fm
+        .safeGetProductByName(filename), true);
+    return this.encodePedigreeAsJson(upstreamTree, null);
+  }
+
+  @GET
+  @Path("report/{filename}/downstream")
+  @Produces("text/plain")
+  public String generateDownstreamPedigree(
+      @PathParam("filename") String filename) {
+    PedigreeTree downstreamTree = this.trace.doPedigree(this.fm
+        .safeGetProductByName(filename), false);
+    return this.encodePedigreeAsJson(null, downstreamTree);
+  }
+
+  private String encodePedigreeAsJson(PedigreeTree up, PedigreeTree down) {
+    Map<String, Object> output = new HashMap<String, Object>();
+    if (up != null)
+      output.put("upstream", this.encodePedigreeTreeAsJson(up.getRoot()));
+    if (down != null)
+      output.put("downstream", this.encodePedigreeTreeAsJson(down.getRoot()));
+    JSONObject json = new JSONObject();
+    json.put("pedigree", output);
+    return json.toString();
+  }
+
+  private Object encodePedigreeTreeAsJson(PedigreeTreeNode node) {
+    if (node.getNumChildren() > 0) {
+      Map<String, Object> map = new HashMap<String, Object>();
+      List<Object> list = new Vector<Object>();
+      for (int i = 0; i < node.getNumChildren(); i++) {
+        list.add(this
+            .encodePedigreeTreeAsJson(node.getChildAt(i)));
+      }
+      map.put(node.getNodeProduct().getProductName(), list);
+      return map;
+    } else {
+      return node.getNodeProduct().getProductName();
+    }
+  }
+}
diff --git a/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/config/PCSServiceConfMetKeys.java b/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/config/PCSServiceConfMetKeys.java
new file mode 100644
index 0000000..167cdd3
--- /dev/null
+++ b/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/config/PCSServiceConfMetKeys.java
@@ -0,0 +1,46 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.services.config;
+
+/**
+ * 
+ * Config file met keys for the PCS services <code>context.xml</code> file.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface PCSServiceConfMetKeys {
+
+  public static final String FM_URL = "org.apache.oodt.cas.fm.url";
+
+  public static final String WM_URL = "org.apache.oodt.cas.wm.url";
+
+  public static final String RM_URL = "org.apache.oodt.cas.rm.url";
+
+  public static final String PCS_LL_CONF_FILE_PATH = "org.apache.oodt.pcs.ll.conf.filePath";
+
+  public static final String PCS_HEALTH_CRAWLER_CONF_PATH = "org.apache.oodt.pcs.health.crawler.conf.filePath";
+
+  public static final String PCS_HEALTH_WORKFLOW_STATUS_PATH = "org.apache.oodt.pcs.health.workflow.statuses.filePath";
+
+  public static final String PCS_TRACE_ENABLE_NON_CAT = "org.apache.oodt.pcs.trace.enableNonCat";
+  
+  public static final String PCS_TRACE_PTYPE_EXCLUDE_LIST = "org.apache.oodt.pcs.trace.productTypeExcludeList";
+
+}
diff --git a/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/config/PCSServiceConfig.java b/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/config/PCSServiceConfig.java
new file mode 100644
index 0000000..463f471
--- /dev/null
+++ b/0.8.1-rc1/pcs/services/src/main/java/org/apache/oodt/pcs/services/config/PCSServiceConfig.java
@@ -0,0 +1,128 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.services.config;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.servlet.ServletConfig;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+/**
+ * 
+ * The configuration class for the PCS JAX RS services.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PCSServiceConfig implements PCSServiceConfMetKeys {
+
+  private Map<String, String> parameters;
+
+  private static final Logger LOG = Logger.getLogger(PCSServiceConfig.class
+      .getName());
+
+  public PCSServiceConfig(ServletConfig config) {
+    this.parameters = new HashMap<String, String>();
+    this.readContextParams(config);
+  }
+
+  /**
+   * @return the fmUrl
+   * @throws MalformedURLException
+   */
+  public URL getFmUrl() throws MalformedURLException {
+    return new URL(PathUtils.replaceEnvVariables(this.parameters.get(FM_URL)));
+  }
+
+  /**
+   * @return the wmUrl
+   * @throws MalformedURLException
+   */
+  public URL getWmUrl() throws MalformedURLException {
+    return new URL(PathUtils.replaceEnvVariables(this.parameters.get(WM_URL)));
+  }
+
+  /**
+   * @return the rmUrl
+   * @throws MalformedURLException
+   */
+  public URL getRmUrl() throws MalformedURLException {
+    return new URL(PathUtils.replaceEnvVariables(this.parameters.get(RM_URL)));
+  }
+
+  /**
+   * @return the listingConfFilePath
+   */
+  public String getListingConfFilePath() {
+    return PathUtils.replaceEnvVariables(this.parameters
+        .get(PCS_LL_CONF_FILE_PATH));
+  }
+
+  /**
+   * @return the crawlerConfigFilePath
+   */
+  public String getCrawlerConfigFilePath() {
+    return PathUtils.replaceEnvVariables(this.parameters
+        .get(PCS_HEALTH_CRAWLER_CONF_PATH));
+  }
+
+  /**
+   * @return the workflowStatusesFilePath
+   */
+  public String getWorkflowStatusesFilePath() {
+    return PathUtils.replaceEnvVariables(this.parameters
+        .get(PCS_HEALTH_WORKFLOW_STATUS_PATH));
+  }
+
+  /**
+   * @return the traceNotCatalogedFiles
+   */
+  public boolean isTraceNotCatalogedFiles() {
+    return Boolean.valueOf(this.parameters.get(PCS_TRACE_ENABLE_NON_CAT));
+  }
+  
+  /**
+   * @return The comma-separated list of product types to exclude from
+   * pedigree tracking.
+   */
+  public String getTraceProductTypeExcludeList(){
+    return PathUtils.replaceEnvVariables(this.parameters.get(PCS_TRACE_PTYPE_EXCLUDE_LIST));
+  }
+
+  @SuppressWarnings("unchecked")
+  private void readContextParams(ServletConfig config) {
+    for (Enumeration<String> paramNames = config.getServletContext()
+        .getInitParameterNames(); paramNames.hasMoreElements();) {
+      String paramName = paramNames.nextElement();
+      this.parameters.put(paramName, config.getServletContext()
+          .getInitParameter(paramName));
+    }
+
+    LOG.log(Level.INFO, "Init Parameters: " + this.parameters);
+  }
+
+}
diff --git a/0.8.1-rc1/pcs/services/src/main/webapp/META-INF/context.xml b/0.8.1-rc1/pcs/services/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..6f1781b
--- /dev/null
+++ b/0.8.1-rc1/pcs/services/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,44 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<Context path="/pcs" docBase="/path/to/pcs-services-X.Y.war">
+		
+	<Parameter name="org.apache.oodt.cas.fm.url"
+	    value="[FILEMGR_URL]"/>
+
+	<Parameter name="org.apache.oodt.cas.wm.url"
+	    value="[WORKFLOW_URL]"/>
+
+	<Parameter name="org.apache.oodt.cas.rm.url"
+	    value="[RESMGR_URL]"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.ll.conf.filePath"
+	    value="[PCS_HOME]/aux/pcs/pcs-ll-conf.xmnl"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.health.crawler.conf.filePath"
+	    value="[PCS_HOME]/aux/pcs/pcs-crawlers.xml"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.health.workflow.statuses.filePath"
+	    value="[PCS_HOME]/aux/pcs/pcs-workflow-statuses.xml"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.trace.enableNonCat"
+	    value="true"/>
+	    
+	<Parameter name="org.apache.oodt.pcs.trace.productTypeExcludeList"
+	    value="TypeName1,TypeName2"/>
+
+</Context>
diff --git a/0.8.1-rc1/pcs/services/src/main/webapp/WEB-INF/web.xml b/0.8.1-rc1/pcs/services/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..01b15e1
--- /dev/null
+++ b/0.8.1-rc1/pcs/services/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<web-app id="PCS" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" 
+     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+	<display-name>PCS</display-name>
+	<servlet>
+	 <servlet-name>CXFServlet</servlet-name>
+	 <servlet-class>
+	   org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet
+	 </servlet-class>
+	 <init-param>
+	  <param-name>jaxrs.serviceClasses</param-name>
+	  <param-value>
+	    org.apache.oodt.pcs.services.HealthResource
+	    org.apache.oodt.pcs.services.PedigreeResource
+	  </param-value>
+	 </init-param>
+	<load-on-startup>1</load-on-startup>
+	</servlet>
+   <servlet>
+        <display-name>PCS Service</display-name>
+        <servlet-name>PCS Service</servlet-name>
+        <servlet-class>org.apache.oodt.pcs.services.PCSService</servlet-class>
+        <load-on-startup>1</load-on-startup>
+    </servlet>	
+	<servlet-mapping>
+		<servlet-name>CXFServlet</servlet-name>
+		<url-pattern>/services/*</url-pattern>
+	</servlet-mapping>
+</web-app>
diff --git a/0.8.1-rc1/pge/pom.xml b/0.8.1-rc1/pge/pom.xml
new file mode 100644
index 0000000..958ba35
--- /dev/null
+++ b/0.8.1-rc1/pge/pom.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>cas-pge</artifactId>
+  <name>CAS PGE Adaptor Framework</name>
+  <description>Allows data processing jobs not written in conformance with the
+        PCS PGE interface to be run within the PCS.</description>
+ <build>
+    <testSourceDirectory>${basedir}/src/test/java</testSourceDirectory> 
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-2</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/assembly/assembly.xml</descriptor>
+          </descriptors>
+          <archive>
+            <manifest>
+              <mainClass>org.apache.oodt.cas.pge.PGETask</mainClass>
+            </manifest>
+          </archive>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin> 
+    </plugins>
+ </build>
+  <profiles>
+    <profile>
+      <id>audit</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>rat-maven-plugin</artifactId>
+            <configuration>
+              <excludes>
+                <exclude>**/resources/examples/**</exclude>
+              </excludes>
+              <numUnapprovedLicenses>2</numUnapprovedLicenses>
+            </configuration>
+            <executions>
+              <execution>
+                <phase>verify</phase>
+                <goals>
+                  <goal>check</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>   
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-metadata</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-commons</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>    
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-filemgr</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-workflow</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-crawler</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-core</artifactId>
+      <version>2.5.4</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-beans</artifactId>
+      <version>2.5.4</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+      <version>2.5.4</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>10.0.1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <version>2.6</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.velocity</groupId>
+      <artifactId>velocity</artifactId>
+      <version>1.7</version>
+    </dependency>    
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+      <version>3.2.1</version>
+    </dependency>    
+    <dependency>
+      <groupId>net.sf.saxon</groupId>
+      <artifactId>saxon-dom</artifactId>
+      <version>8.7</version>      
+	  </dependency>
+		<dependency>
+			<groupId>org.easymock</groupId>
+			<artifactId>easymock</artifactId>
+			<version>3.1</version>
+			<scope>test</scope>
+		</dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/pge/src/main/assembly/assembly.xml b/0.8.1-rc1/pge/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..623841c
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/assembly/assembly.xml
@@ -0,0 +1,77 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<assembly>
+  <id>dist</id>
+  <formats>
+    <format>tar.gz</format>
+    <format>zip</format>
+  </formats>
+  <includeBaseDirectory>true</includeBaseDirectory>
+  <baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/bin</directory>
+      <outputDirectory>bin</outputDirectory>
+      <includes/>
+      <fileMode>755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>etc</outputDirectory>
+      <includes>
+        <include>logging.properties</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>logs</outputDirectory>
+      <includes>
+        <include>REMOVE.log</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/examples</directory>
+      <outputDirectory>etc/examples</outputDirectory>
+      <excludes/>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>lib</outputDirectory>
+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>
+      <unpackOptions/>
+    </dependencySet>
+  </dependencySets>
+</assembly>
diff --git a/0.8.1-rc1/pge/src/main/bin/pgetask b/0.8.1-rc1/pge/src/main/bin/pgetask
new file mode 100755
index 0000000..23aae63
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/bin/pgetask
@@ -0,0 +1,22 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+$JAVA_HOME/bin/java -Djava.ext.dirs=../lib \
+        -Djava.util.logging.config.file=../etc/logging.properties \
+        -Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl \
+        org.apache.oodt.cas.pge.PGETask --metadata ../etc/examples/WorkflowMgrInput/pcs-pge-dyn-metadata.met \
+        --config ../etc/examples/WorkflowMgrInput/pcs-pge-task-workflow.properties \
+        --instanceClass org.apache.oodt.cas.pge.StdPGETaskInstance
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/ConfigFilePropertyAdder.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/ConfigFilePropertyAdder.java
new file mode 100644
index 0000000..2170925
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/ConfigFilePropertyAdder.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pge;
+
+//OODT imports
+import org.apache.oodt.cas.pge.metadata.PgeMetadata;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * An interface for adding dynamic properties to the {@link Metadata} based on
+ * metadata supplied. This interface is used by the PGETask to dynamically add
+ * PGE-specific properties that aren't general to all PGEs.
+ * </p>
+ * 
+ */
+public interface ConfigFilePropertyAdder {
+
+    public void addConfigProperties(PgeMetadata metadata, Object... objs);
+
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/PGETask.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/PGETask.java
new file mode 100644
index 0000000..0ef8a63
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/PGETask.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge;
+
+//JDK static imports
+import static org.apache.oodt.cas.pge.util.GenericPgeObjectFactory.createPGETaskInstance;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.exceptions.WorkflowTaskInstanceException;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+
+/**
+ * Runs a {@link PGETaskInstance} given {@link Metadata} and a
+ * {@link WorkflowTaskConfiguration}.
+ *
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public class PGETask {
+
+    private static final Logger LOGGER = Logger.getLogger(PGETask.class.getName());
+
+    private Metadata metadata;
+
+    private WorkflowTaskConfiguration wftConfig;
+
+    public PGETask(Metadata metadata, WorkflowTaskConfiguration wftConfig) {
+        this.metadata = metadata;
+        this.wftConfig = wftConfig;
+    }
+
+    public void run(String pgeTaskInstanceClasspath)
+            throws InstantiationException, IllegalAccessException,
+            ClassNotFoundException, WorkflowTaskInstanceException {
+        PGETaskInstance pgeTaskInst = createPGETaskInstance(
+                pgeTaskInstanceClasspath, LOGGER);
+        pgeTaskInst.run(this.metadata, this.wftConfig);
+    }
+
+    public static void main(String[] args) throws Exception {
+        String metadataFilePath = null, configPropertiesPath = null;
+        String pgeTaskInstanceClasspath = null;
+        String usage = "PGETask --instanceClass <PGETaskInstance> "
+                + "--metadata </path/to/metadata/file> "
+                + "--config </path/to/task/config/file>\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--metadata")) {
+                metadataFilePath = args[++i];
+            } else if (args[i].equals("--config")) {
+                configPropertiesPath = args[++i];
+            } else if (args[i].equals("--instanceClass")) {
+                pgeTaskInstanceClasspath = args[++i];
+            }
+        }
+
+        if (metadataFilePath == null || configPropertiesPath == null) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        SerializableMetadata sm = new SerializableMetadata("UTF-8", false);
+        sm.loadMetadataFromXmlStream(new File(metadataFilePath).toURL()
+                .openStream());
+        WorkflowTaskConfiguration config = new WorkflowTaskConfiguration();
+        config.getProperties().load(
+                new File(configPropertiesPath).toURL().openStream());
+
+        PGETask task = new PGETask(sm, config);
+        task.run(pgeTaskInstanceClasspath);
+    }
+
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/PGETaskInstance.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/PGETaskInstance.java
new file mode 100644
index 0000000..1c583c6
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/PGETaskInstance.java
@@ -0,0 +1,597 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge;
+
+//OODT static imports
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.ACTION_IDS;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.ATTEMPT_INGEST_ALL;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.CRAWLER_CONFIG_FILE;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.CRAWLER_CRAWL_FOR_DIRS;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.CRAWLER_RECUR;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.DUMP_METADATA;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.FILE_STAGER;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.INGEST_CLIENT_TRANSFER_SERVICE_FACTORY;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.INGEST_FILE_MANAGER_URL;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.LOG_FILENAME_PATTERN;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.MET_FILE_EXT;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.NAME;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.MIME_EXTRACTOR_REPO;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.PGE_CONFIG_BUILDER;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.PGE_RUNTIME;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.PROPERTY_ADDERS;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.REQUIRED_METADATA;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.WORKFLOW_MANAGER_URL;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskStatus.CONF_FILE_BUILD;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskStatus.CRAWLING;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskStatus.RUNNING_PGE;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskStatus.STAGING_INPUT;
+import static org.apache.oodt.cas.pge.util.GenericPgeObjectFactory.createConfigFilePropertyAdder;
+import static org.apache.oodt.cas.pge.util.GenericPgeObjectFactory.createFileStager;
+import static org.apache.oodt.cas.pge.util.GenericPgeObjectFactory.createPgeConfigBuilder;
+import static org.apache.oodt.cas.pge.util.GenericPgeObjectFactory.createSciPgeConfigFileWriter;
+
+//JDK imports
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.FileHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.SimpleFormatter;
+import java.util.regex.Pattern;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.AutoDetectProductCrawler;
+import org.apache.oodt.cas.crawl.ProductCrawler;
+import org.apache.oodt.cas.crawl.StdProductCrawler;
+import org.apache.oodt.cas.crawl.status.IngestStatus;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.metadata.filenaming.PathUtilsNamingConvention;
+import org.apache.oodt.cas.pge.config.DynamicConfigFile;
+import org.apache.oodt.cas.pge.config.OutputDir;
+import org.apache.oodt.cas.pge.config.PgeConfig;
+import org.apache.oodt.cas.pge.config.RegExprOutputFiles;
+import org.apache.oodt.cas.pge.config.XmlFilePgeConfigBuilder;
+import org.apache.oodt.cas.pge.metadata.PgeMetadata;
+import org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys;
+import org.apache.oodt.cas.pge.staging.FileManagerFileStager;
+import org.apache.oodt.cas.pge.staging.FileStager;
+import org.apache.oodt.cas.pge.writers.PcsMetFileWriter;
+import org.apache.oodt.cas.pge.writers.SciPgeConfigFileWriter;
+import org.apache.oodt.cas.workflow.metadata.CoreMetKeys;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.structs.exceptions.WorkflowTaskInstanceException;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+import org.apache.oodt.cas.workflow.util.ScriptFile;
+import org.apache.oodt.commons.exec.ExecUtils;
+
+//Spring imports
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+//Google imports
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+
+/**
+ * Runs a CAS-style Product Generation Executive based on the PCS Wrapper
+ * Architecture from mattmann et al. on OCO.
+ *
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public class PGETaskInstance implements WorkflowTaskInstance {
+
+   protected Logger logger = Logger.getLogger(PGETaskInstance.class.getName());
+   protected XmlRpcWorkflowManagerClient wm;
+   protected String workflowInstId;
+   protected PgeMetadata pgeMetadata;
+   protected PgeConfig pgeConfig;
+
+   protected PGETaskInstance() {}
+
+   @Override
+   public void run(Metadata metadata, WorkflowTaskConfiguration config)
+         throws WorkflowTaskInstanceException {
+      try {
+         // Initialize CAS-PGE.
+         pgeMetadata = createPgeMetadata(metadata, config);
+         pgeConfig = createPgeConfig();
+         runPropertyAdders();
+         wm = createWorkflowManagerClient();
+         workflowInstId = getWorkflowInstanceId();
+         logger = createLogger(); // use workflow ID specific logger from now on 
+
+         // Write out PgeMetadata.
+         dumpMetadataIfRequested();
+
+         // Setup the PGE.
+         createExeDir();
+         createOuputDirsIfRequested();
+         updateStatus(CONF_FILE_BUILD.getWorkflowStatusName());
+         createDynamicConfigFiles();
+         updateStatus(STAGING_INPUT.getWorkflowStatusName());
+         stageFiles();
+
+         // Run the PGE.
+         runPge();
+
+         // Ingest products.
+         runIngestCrawler(createProductCrawler());
+
+         // Commit dynamic metadata.
+         updateDynamicMetadata();
+      } catch (Exception e) {
+         logger.log(Level.SEVERE, "PGETask FAILED!!! : " + e.getMessage(), e);
+         throw new WorkflowTaskInstanceException("PGETask FAILED!!! : "
+               + e.getMessage(), e);
+      }
+   }
+
+   protected void updateStatus(String status) throws Exception {
+      logger.info("Updating status to workflow as [" + status + "]");
+      if (!wm.updateWorkflowInstanceStatus(workflowInstId, status)) {
+         throw new Exception(
+               "Failed to update workflow status : client returned false");
+      }
+   }
+
+   protected Logger createLogger() throws Exception {
+      File logDir = new File(pgeConfig.getExeDir(), "logs");
+      if (!(logDir.exists() || logDir.mkdirs())) {
+         throw new Exception("mkdirs for logs directory return false");
+      }
+
+      Logger logger = Logger.getLogger(PGETaskInstance.class.getName()
+            + "." + workflowInstId);
+      FileHandler handler = new FileHandler(
+            new File(logDir, createLogFileName()).getAbsolutePath());
+      handler.setEncoding("UTF-8");
+      handler.setFormatter(new SimpleFormatter());
+      logger.addHandler(handler);
+      return logger;
+   }
+
+   protected String createLogFileName() throws Exception {
+      String filenamePattern = pgeMetadata.getMetadata(LOG_FILENAME_PATTERN);
+      if (filenamePattern != null) {
+         return filenamePattern;
+      } else {
+         return pgeMetadata.getMetadata(NAME) + "." + System.currentTimeMillis()
+            + ".log";
+      }
+   }
+
+   protected PgeMetadata createPgeMetadata(Metadata dynMetadata,
+         WorkflowTaskConfiguration config) throws Exception {
+      logger.info("Converting workflow configuration to static metadata...");
+      Metadata staticMetadata = new Metadata();
+      for (Object objKey : config.getProperties().keySet()) {
+         String key = (String) objKey;
+         PgeTaskMetKeys metKey = PgeTaskMetKeys.getByName(key);
+         if (metKey != null && metKey.isVector()) {
+            List<String> values = Lists.newArrayList(
+                  Splitter.on(",").trimResults()
+                  .omitEmptyStrings()
+                  .split(config.getProperty(key)));
+            logger.finest("Adding static metadata: key = [" + key
+                  + "] value = " + values);
+            staticMetadata.addMetadata(key, values);
+         } else {
+            String value = config.getProperty(key);
+            logger.finest("Adding static metadata: key = [" + key
+                  + "] value = [" + value + "]");
+            staticMetadata.addMetadata(key, value);
+         }
+      }
+      logger.info("Loading workflow context metadata...");
+      for (String key : dynMetadata.getAllKeys()) {
+         logger.finest(
+               "Adding dynamic metadata: key = [" + key + "] value = "
+                     + dynMetadata.getAllMetadata(key));
+      }
+      return new PgeMetadata(staticMetadata, dynMetadata);
+   }
+
+   protected PgeConfig createPgeConfig() throws Exception {
+      logger.info("Create PgeConfig...");
+      String pgeConfigBuilderClass = pgeMetadata
+            .getMetadata(PGE_CONFIG_BUILDER);
+      if (pgeConfigBuilderClass != null) {
+         logger.info("Using PgeConfigBuilder: " + pgeConfigBuilderClass);
+         return createPgeConfigBuilder(pgeConfigBuilderClass, logger)
+               .build(pgeMetadata);
+      } else {
+         logger.info("Using default PgeConfigBuilder: "
+               + XmlFilePgeConfigBuilder.class.getCanonicalName());
+         return new XmlFilePgeConfigBuilder().build(pgeMetadata);
+      }
+   }
+
+   protected void runPropertyAdders() throws Exception {
+      try {
+         logger.info("Loading/Running property adders...");
+         List<String> propertyAdders = pgeMetadata
+               .getAllMetadata(PROPERTY_ADDERS);
+         if (propertyAdders != null) {
+            for (String propertyAdder : propertyAdders) {
+               runPropertyAdder(loadPropertyAdder(propertyAdder));
+            }
+         } else {
+            logger.info("No property adders specified");
+         }
+      } catch (Exception e) {
+         throw new Exception("Failed to instanciate/run Property Adders : "
+               + e.getMessage(), e);
+      }
+   }
+
+   protected ConfigFilePropertyAdder loadPropertyAdder(
+         String propertyAdderClasspath) throws Exception {
+      logger.fine("Loading property adder: " + propertyAdderClasspath);
+      return createConfigFilePropertyAdder(propertyAdderClasspath, logger);
+   }
+
+   protected void runPropertyAdder(ConfigFilePropertyAdder propAdder)
+         throws Exception {
+      logger.info("Running property adder: "
+            + propAdder.getClass().getCanonicalName());
+      propAdder.addConfigProperties(pgeMetadata,
+            pgeConfig.getPropertyAdderCustomArgs());
+   }
+
+   protected XmlRpcWorkflowManagerClient createWorkflowManagerClient()
+         throws Exception {
+      String url = pgeMetadata.getMetadata(WORKFLOW_MANAGER_URL);
+      logger.info("Creating WorkflowManager client for url [" + url + "]");
+      Validate.notNull(url, "Must specify " + WORKFLOW_MANAGER_URL);
+      return new XmlRpcWorkflowManagerClient(new URL(url));
+   }
+
+   protected String getWorkflowInstanceId() throws Exception {
+      String instanceId = pgeMetadata.getMetadata(CoreMetKeys.WORKFLOW_INST_ID);
+      logger.info("Workflow instanceId is [" + instanceId + "]");
+      Validate.notNull(instanceId, "Must specify "
+            + CoreMetKeys.WORKFLOW_INST_ID);
+      return instanceId;
+   }
+
+   protected void dumpMetadataIfRequested() throws Exception {
+      if (Boolean.parseBoolean(pgeMetadata
+            .getMetadata(DUMP_METADATA))) {
+         new SerializableMetadata(pgeMetadata.asMetadata())
+               .writeMetadataToXmlStream(new FileOutputStream(
+                     getDumpMetadataPath()));
+      }
+   }
+
+   protected String getDumpMetadataPath() throws Exception {
+      return new File(pgeConfig.getExeDir()).getAbsolutePath() + "/"
+            + getDumpMetadataName();
+   }
+
+   protected String getDumpMetadataName() throws Exception {
+      return "pgetask-metadata.xml";
+   }
+
+   protected void createExeDir() throws Exception {
+      logger.info("Creating PGE execution working directory: ["
+            + pgeConfig.getExeDir() + "]");
+      File executionDir = new File(pgeConfig.getExeDir());
+      if (!(executionDir.exists() || executionDir.mkdirs())) {
+         throw new Exception("mkdirs returned false for creating ["
+               + pgeConfig.getExeDir() + "]");
+      }
+   }
+
+   protected void createOuputDirsIfRequested() throws Exception {
+      for (OutputDir outputDir : pgeConfig.getOuputDirs()) {
+         if (outputDir.isCreateBeforeExe()) {
+            logger.info("Creating PGE file ouput directory: ["
+                  + outputDir.getPath() + "]");
+            File dir = new File(outputDir.getPath());
+            if (!(dir.exists() || dir.mkdirs())) {
+               throw new Exception("mkdir returned false for creating ["
+                     + outputDir.getPath() + "]");
+            }
+         }
+      }
+   }
+
+   protected void stageFiles() throws Exception {
+      if (pgeConfig.getFileStagingInfo() != null) {
+         FileStager fileStager = getFileStager();
+         logger.info("Starting file staging...");
+         fileStager.stageFiles(
+               pgeConfig.getFileStagingInfo(), pgeMetadata, logger);
+      } else {
+         logger.info("No files to stage.");
+      }
+   }
+
+   protected FileStager getFileStager() throws Exception {
+      String fileStagerClass = pgeMetadata.getMetadata(FILE_STAGER);
+      if (fileStagerClass != null) {
+         logger.info("Loading FileStager [" + fileStagerClass + "]");
+         return createFileStager(fileStagerClass, logger);
+      } else {
+         logger.info("Using default FileStager ["
+               + FileManagerFileStager.class.getCanonicalName() + "]");
+         return new FileManagerFileStager();
+      }
+   }
+
+   protected void createDynamicConfigFiles() throws Exception {
+      logger.info("Starting creation of sci pge config files...");
+      for (DynamicConfigFile dynamicConfigFile : pgeConfig
+            .getDynamicConfigFiles()) {
+         createDynamicConfigFile(dynamicConfigFile);
+      }
+      logger.info("Successfully wrote all sci pge config files!");
+   }
+
+   protected void createDynamicConfigFile(DynamicConfigFile dynamicConfigFile)
+         throws Exception {
+      Validate.notNull(dynamicConfigFile, "dynamicConfigFile cannot be null");
+      logger.fine("Starting creation of sci pge config file ["
+            + dynamicConfigFile.getFilePath() + "]...");
+
+      // Create parent directory if it doesn't exist.
+      File parentDir = new File(dynamicConfigFile.getFilePath())
+            .getParentFile();
+      if (!(parentDir.exists() || parentDir.mkdirs())) {
+         throw new Exception("Failed to create directory where sci pge config file ["
+               + dynamicConfigFile.getFilePath() + "] was to be written");
+      }
+
+      // Load writer and write file.
+      logger.fine("Loading writer class for sci pge config file ["
+            + dynamicConfigFile.getFilePath() + "]...");
+      SciPgeConfigFileWriter writer = createSciPgeConfigFileWriter(
+            dynamicConfigFile.getWriterClass(), logger);
+      logger.fine("Loaded writer [" + writer.getClass().getCanonicalName()
+            + "] for sci pge config file [" + dynamicConfigFile.getFilePath()
+            + "]...");
+      logger.info("Writing sci pge config file [" + dynamicConfigFile.getFilePath()
+                  + "]...");
+      File configFile = writer.createConfigFile(dynamicConfigFile.getFilePath(),
+            pgeMetadata.asMetadata(), logger, dynamicConfigFile.getArgs());
+      if (!configFile.exists()) {
+         throw new Exception("Writer failed to create config file ["
+               + configFile + "], exists returned false");
+      }
+   }
+
+   protected ScriptFile buildPgeRunScript() {
+      logger.fine("Creating PGE run script for shell [" + pgeConfig.getShellType()
+                  + "] with contents " + pgeConfig.getExeCmds());
+      ScriptFile sf = new ScriptFile(pgeConfig.getShellType());
+      sf.setCommands(pgeConfig.getExeCmds());
+      return sf;
+   }
+
+   protected File getScriptPath() {
+      File script = new File(pgeConfig.getExeDir(), getPgeScriptName());
+      logger.fine("Script file with be written to [" + script + "]");
+      return script;
+   }
+
+   protected String getPgeScriptName() {
+      String pgeScriptName = "sciPgeExeScript_" + pgeMetadata.getMetadata(NAME);
+      logger.fine("Generated script file name [" + pgeScriptName + "]");
+      return pgeScriptName;
+   }
+
+   protected void runPge() throws Exception {
+      ScriptFile sf = null;
+      try {
+         long startTime = System.currentTimeMillis();
+         logger.info("PGE start time [" + new Date(startTime) + "]");
+
+         // create script to run
+         sf = buildPgeRunScript();
+         sf.writeScriptFile(getScriptPath().getAbsolutePath());
+
+         // run script and evaluate whether success or failure
+         updateStatus(RUNNING_PGE.getWorkflowStatusName());
+         logger.info("Starting execution of PGE...");
+         if (!wasPgeSuccessful(ExecUtils.callProgram(
+               pgeConfig.getShellType() + " " + getScriptPath(), logger,
+               new File(pgeConfig.getExeDir()).getAbsoluteFile()))) {
+            throw new RuntimeException("Pge didn't finish successfully");
+         } else {
+            logger.info(
+                  "Successfully completed running: '" + sf.getCommands() + "'");
+         }
+
+         long endTime = System.currentTimeMillis();
+         logger.info("PGE end time [" + new Date(startTime) + "]");
+
+         long runTime = endTime - startTime;
+         logger.info("PGE runtime in millis [" + runTime + "]");
+
+         pgeMetadata.replaceMetadata(PGE_RUNTIME, Long.toString(runTime));
+
+      } catch (Exception e) {
+         throw new Exception("Exception when executing PGE commands '"
+               + (sf != null ? sf.getCommands() : "NULL") + "' : "
+               + e.getMessage(), e);
+      }
+   }
+
+   protected boolean wasPgeSuccessful(int returnCode) {
+      return returnCode == 0;
+   }
+   
+   protected void processOutput() throws FileNotFoundException, IOException {
+     for (final OutputDir outputDir : this.pgeConfig.getOuputDirs()) {
+         File[] createdFiles = new File(outputDir.getPath()).listFiles();
+         for (File createdFile : createdFiles) {
+             Metadata outputMetadata = new Metadata();
+             for (RegExprOutputFiles regExprFiles : outputDir
+                     .getRegExprOutputFiles()) {
+                 if (Pattern.matches(regExprFiles.getRegExp(), createdFile
+                         .getName())) {
+                     try {
+                         PcsMetFileWriter writer = (PcsMetFileWriter) Class
+                                 .forName(regExprFiles.getConverterClass())
+                                 .newInstance();
+                         outputMetadata.replaceMetadata(this.getMetadataForFile(
+                 (regExprFiles.getRenamingConv() != null) 
+               ? createdFile = this.renameFile(createdFile, regExprFiles.getRenamingConv())
+               : createdFile, writer, regExprFiles.getArgs()));
+                     } catch (Exception e) {
+                         logger.severe(
+                                 "Failed to create metadata file for '"
+                                         + createdFile + "' : "
+                                         + e.getMessage());
+                     }
+                 }
+             }
+             if (outputMetadata.getAllKeys().size() > 0)
+               this.writeFromMetadata(outputMetadata, createdFile.getAbsolutePath() 
+                   + "." + this.pgeMetadata.getMetadata(MET_FILE_EXT));
+         }
+     }
+ }
+
+	protected File renameFile(File file, PathUtilsNamingConvention renamingConv)
+			throws Exception {
+		Metadata curMetadata = this.pgeMetadata.asMetadata();
+		curMetadata.replaceMetadata(renamingConv.getTmpReplaceMet());
+		return renamingConv.rename(file, curMetadata);
+	}
+
+	protected Metadata getMetadataForFile(File sciPgeCreatedDataFile,
+			PcsMetFileWriter writer, Object[] args) throws Exception {
+		return writer.getMetadataForFile(sciPgeCreatedDataFile,
+				this.pgeMetadata, args);
+	}
+
+	protected void writeFromMetadata(Metadata metadata, String toMetFilePath)
+			throws FileNotFoundException, IOException {
+		new SerializableMetadata(metadata, "UTF-8", false)
+				.writeMetadataToXmlStream(new FileOutputStream(toMetFilePath));
+	}
+
+	protected ProductCrawler createProductCrawler() throws Exception {
+     /* create a ProductCrawler based on whether or not the output dir specifies a MIME_EXTRACTOR_REPO */
+      logger.info("Configuring ProductCrawler...");
+      ProductCrawler crawler = null;
+      if (pgeMetadata.getMetadata(MIME_EXTRACTOR_REPO) != null && 
+    		  !pgeMetadata.getMetadata(MIME_EXTRACTOR_REPO).equals("")){
+          crawler = new AutoDetectProductCrawler();
+          ((AutoDetectProductCrawler)crawler).
+            setMimeExtractorRepo(pgeMetadata.getMetadata(MIME_EXTRACTOR_REPO));    	  
+      }
+      else{
+    	  crawler = new StdProductCrawler();
+      }
+
+      crawler.setClientTransferer(pgeMetadata
+            .getMetadata(INGEST_CLIENT_TRANSFER_SERVICE_FACTORY));
+      crawler.setFilemgrUrl(pgeMetadata.getMetadata(INGEST_FILE_MANAGER_URL));
+      String crawlerConfigFile = pgeMetadata.getMetadata(CRAWLER_CONFIG_FILE);
+      if (!Strings.isNullOrEmpty(crawlerConfigFile)) {
+         crawler.setApplicationContext(
+               new FileSystemXmlApplicationContext(crawlerConfigFile));
+         List<String> actionIds = pgeMetadata.getAllMetadata(ACTION_IDS);
+         if (actionIds != null) {
+            crawler.setActionIds(actionIds);
+         }
+      }
+      crawler.setRequiredMetadata(pgeMetadata.getAllMetadata(REQUIRED_METADATA));
+      crawler.setCrawlForDirs(Boolean.parseBoolean(pgeMetadata
+            .getMetadata(CRAWLER_CRAWL_FOR_DIRS)));
+      crawler.setNoRecur(!Boolean.parseBoolean(
+            pgeMetadata.getMetadata(CRAWLER_RECUR)));
+      logger.fine(
+            "Passing Workflow Metadata to CAS-Crawler as global metadata . . .");
+      crawler.setGlobalMetadata(pgeMetadata.asMetadata(PgeMetadata.Type.DYNAMIC));
+      logger.fine("Created ProductCrawler ["
+            + crawler.getClass().getCanonicalName() + "]");
+      return crawler;
+   }
+
+   protected void runIngestCrawler(ProductCrawler crawler) throws Exception {
+      // Determine if we need to create Metadata files
+	   if (crawler instanceof StdProductCrawler){
+		   this.processOutput();
+	   }
+	   
+	   // Determine directories to crawl.
+      List<File> crawlDirs = new LinkedList<File>();
+      for (OutputDir outputDir : pgeConfig.getOuputDirs()) {
+         crawlDirs.add(new File(outputDir.getPath()));
+      }
+
+      // Start crawlin...
+      updateStatus(CRAWLING.getWorkflowStatusName());
+      boolean attemptIngestAll = Boolean.parseBoolean(pgeMetadata
+            .getMetadata(ATTEMPT_INGEST_ALL));
+      for (File crawlDir : crawlDirs) {
+         logger.info("Crawling for products in [" + crawlDir + "]");
+         crawler.crawl(crawlDir);
+         if (!attemptIngestAll) {
+            verifyIngests(crawler);
+         }
+      }
+      if (attemptIngestAll) {
+         verifyIngests(crawler);
+      }
+   }
+
+   protected void verifyIngests(ProductCrawler crawler) throws Exception {
+      logger.info("Verifying ingests successful...");
+      boolean ingestsSuccess = true;
+      String exceptionMsg = "";
+      for (IngestStatus status : crawler.getIngestStatus()) {
+         if (status.getResult().equals(IngestStatus.Result.FAILURE)) {
+            exceptionMsg += (exceptionMsg.equals("") ? "" : " : ")
+                  + "Failed to ingest product [file='"
+                  + status.getProduct().getAbsolutePath() + "',result='"
+                  + status.getResult() + "',msg='" + status.getMessage() + "']";
+            ingestsSuccess = false;
+         } else if (!status.getResult().equals(IngestStatus.Result.SUCCESS)) {
+            logger.warning("Product was not ingested [file='"
+                  + status.getProduct().getAbsolutePath() + "',result='"
+                  + status.getResult() + "',msg='" + status.getMessage() + "']");
+         }
+      }
+      if (!ingestsSuccess) {
+         throw new Exception(exceptionMsg);
+      } else {
+         logger.info("Ingests were successful");
+      }
+   }
+
+   protected void updateDynamicMetadata() throws Exception {
+      pgeMetadata.commitMarkedDynamicMetadataKeys();
+      wm.updateMetadataForWorkflow(workflowInstId,
+            pgeMetadata.asMetadata(PgeMetadata.Type.DYNAMIC));
+   }
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/StdPGETaskInstance.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/StdPGETaskInstance.java
new file mode 100644
index 0000000..cef4031
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/StdPGETaskInstance.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pge;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The Standard implementation of the {@link PGETaskInstance}. Doesn't override
+ * any of the default functionality
+ * </p>.
+ */
+public class StdPGETaskInstance extends PGETaskInstance {
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/WinPGETaskInstance.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/WinPGETaskInstance.java
new file mode 100644
index 0000000..89f4beb
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/WinPGETaskInstance.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pge;
+
+import org.apache.oodt.cas.workflow.util.CygwinScriptFile;
+import org.apache.oodt.cas.workflow.util.ScriptFile;
+
+/**
+ * Runs a CAS-style Product Generation Executive based on the PCS Wrapper
+ * Architecture from mattmann et al. on OCO specifically on a Windows Cygwin-running
+ * machine
+ *
+ * @author riverma (Rishi Verma)
+ */
+public class WinPGETaskInstance extends PGETaskInstance {
+
+	  /**
+	   * Override buildPgeRunScript method to call a windows specific script file
+	   */
+	  @Override
+	  protected ScriptFile buildPgeRunScript() {
+		  CygwinScriptFile sf = new CygwinScriptFile(this.pgeConfig.getShellType());
+	      sf.setCommands(this.pgeConfig.getExeCmds());
+	   
+	      return sf;
+	  }	
+	
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/DynamicConfigFile.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/DynamicConfigFile.java
new file mode 100644
index 0000000..e0a2df7
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/DynamicConfigFile.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pge.config;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A dynamic representation of a SciPgeConfigFile
+ * </p>.
+ */
+public class DynamicConfigFile {
+
+    private String filePath, writerClass;
+
+    private Object[] args;
+
+    public DynamicConfigFile(String filePath, String writerClass, Object[] args) {
+        this.filePath = filePath;
+        this.writerClass = writerClass;
+        this.args = args;
+    }
+
+    public void setFilePath(String filePath) {
+        this.filePath = filePath;
+    }
+
+    public String getFilePath() {
+        return this.filePath;
+    }
+
+    public void setWriterClass(String writerClass) {
+        this.writerClass = writerClass;
+    }
+
+    public String getWriterClass() {
+        return this.writerClass;
+    }
+
+    public void setArgs(Object[] args) {
+        this.args = args;
+    }
+
+    public Object[] getArgs() {
+        return this.args;
+    }
+
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/FileStagingInfo.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/FileStagingInfo.java
new file mode 100644
index 0000000..e43f0bc
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/FileStagingInfo.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.config;
+
+//JDK imports
+import java.util.List;
+import java.util.Set;
+
+//Google imports
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * Configuration information about which files should be staged and where.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class FileStagingInfo {
+
+   private final String stagingDir;
+   private final boolean forceStaging;
+   private final Set<String> filePaths;
+   private final Set<String> productIds;
+
+   public FileStagingInfo(String stagingDir) {
+      this(stagingDir, false);
+   }
+
+   public FileStagingInfo(String stagingDir, boolean forceStaging) {
+      this.stagingDir = stagingDir;
+      this.forceStaging = forceStaging;
+      filePaths = Sets.newHashSet();
+      productIds = Sets.newHashSet();
+   }
+
+   public void addFilePath(String filePath) {
+      filePaths.add(filePath);
+   }
+
+   public void addFilePaths(List<String> filePaths) {
+      this.filePaths.addAll(filePaths);
+   }
+
+   public List<String> getFilePaths() {
+      return Lists.newArrayList(filePaths);
+   }
+
+   public void addProductId(String productId) {
+      productIds.add(productId);
+   }
+
+   public void addProductIds(List<String> productIds) {
+      productIds.addAll(productIds);
+   }
+
+   public List<String> getProductIds() {
+      return Lists.newArrayList(productIds);
+   }
+
+   public String getStagingDir() {
+      return stagingDir;
+   }
+
+   public boolean isForceStaging() {
+      return forceStaging;
+   }
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/OutputDir.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/OutputDir.java
new file mode 100644
index 0000000..ec7ed4e
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/OutputDir.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.config;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+/**
+ * An output directory where PGE will create files.
+ * 
+ * @author bfoster
+ * @version $Revision$
+ */
+public class OutputDir {
+
+   private String path;
+   private boolean createBeforeExe;
+   private List<RegExprOutputFiles> regExprOutputFilesList;
+
+   public OutputDir() {
+	  this(null, false);
+   }
+
+   public OutputDir(String path, boolean createBeforeExe) {
+      setPath(path);
+      setCreateBeforeExe(createBeforeExe);
+      this.regExprOutputFilesList = new Vector<RegExprOutputFiles>();
+
+   }
+
+   public void setPath(String path) {
+      Validate.notNull(path, "path cannot be null");
+      this.path = path;
+   }
+      
+   public String getPath() {
+      return path;
+   }
+
+   public void setCreateBeforeExe(boolean createBeforeExe) {
+      this.createBeforeExe = createBeforeExe;
+   }
+
+   public boolean isCreateBeforeExe() {
+      return createBeforeExe;
+   }
+   
+   public void addRegExprOutputFiles(RegExprOutputFiles regExprOutputFiles) {
+     this.regExprOutputFilesList.add(regExprOutputFiles);
+   } 
+
+   public List<RegExprOutputFiles> getRegExprOutputFiles() {
+     return this.regExprOutputFilesList;
+ }
+
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/PgeConfig.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/PgeConfig.java
new file mode 100644
index 0000000..52a97f2
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/PgeConfig.java
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.config;
+
+//JDK imports
+import java.util.List;
+
+//Google imports
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+
+/** 
+ * Configuration file for CAS-PGE.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class PgeConfig {
+
+    private List<DynamicConfigFile> dynamicConfigFiles;
+    private List<OutputDir> outputDirs;
+    private Object[] propertyAdderCustomArgs;
+    private String exeDir;
+    private String shellType;
+    private List<String> exeCmds;
+    private FileStagingInfo fileStagingInfo;
+
+    public PgeConfig() {
+        shellType = "sh";
+        outputDirs = Lists.newArrayList();
+        dynamicConfigFiles = Lists.newArrayList();
+        exeCmds = Lists.newArrayList();
+    }
+
+    public void addDynamicConfigFile(DynamicConfigFile dynamicConfigFile) {
+        dynamicConfigFiles.add(dynamicConfigFile);
+    }
+
+    public List<DynamicConfigFile> getDynamicConfigFiles() {
+        return dynamicConfigFiles;
+    }
+
+    public void addOuputDirAndExpressions(OutputDir outputDir) {
+        outputDirs.add(outputDir);
+    }
+
+    public List<OutputDir> getOuputDirs() {
+        return outputDirs;
+    }
+
+    public void setExeDir(String exeDir) {
+        this.exeDir = exeDir;
+    }
+
+    public String getExeDir() {
+        return exeDir;
+    }
+
+    public void setShellType(String shellType) {
+        if (!Strings.isNullOrEmpty(shellType)) {
+            this.shellType = shellType;
+        }
+    }
+
+    public String getShellType() {
+        return shellType;
+    }
+
+    public void setExeCmds(List<String> exeCmds) {
+        this.exeCmds = exeCmds;
+    }
+
+    public List<String> getExeCmds() {
+        return exeCmds;
+    }
+
+    public void setPropertyAdderCustomArgs(Object[] args) {
+        propertyAdderCustomArgs = args;
+    }
+
+    public Object[] getPropertyAdderCustomArgs() {
+        return propertyAdderCustomArgs != null ? propertyAdderCustomArgs
+                : new Object[0];
+    }
+
+    public void setFileStagingInfo(FileStagingInfo fileStagingInfo) {
+       this.fileStagingInfo = fileStagingInfo;
+    }
+
+    public FileStagingInfo getFileStagingInfo() {
+       return fileStagingInfo;
+    }
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/PgeConfigBuilder.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/PgeConfigBuilder.java
new file mode 100644
index 0000000..0bde153
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/PgeConfigBuilder.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.config;
+
+//OODT imports
+import org.apache.oodt.cas.pge.metadata.PgeMetadata;
+
+/**
+ * Interface for building a {@link PgeConfig}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public interface PgeConfigBuilder {
+
+    public PgeConfig build(PgeMetadata pgeMetadata) throws Exception;
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/PgeConfigMetKeys.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/PgeConfigMetKeys.java
new file mode 100644
index 0000000..fe91029
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/PgeConfigMetKeys.java
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.config;
+
+/**
+ * Met Keys used when reading a {@link PgeConfig} XML file.
+ *
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public interface PgeConfigMetKeys {
+
+    public static final String IMPORT_TAG = "import";
+
+    public static final String NAMESPACE_ATTR = "namespace";
+
+    public static final String FILE_ATTR = "file";
+
+    public static final String CUSTOM_METADATA_TAG = "customMetadata";
+
+    public static final String METADATA_TAG = "metadata";
+
+    public static final String KEYREF_ATTR = "key-ref";
+
+    public static final String KEY_GEN_ATTR = "key-gen";
+
+    public static final String KEY_ATTR = "key";
+
+    public static final String VAL_ATTR = "val";
+
+    public static final String ENV_REPLACE_ATTR = "envReplace";
+
+    public static final String ENV_REPLACE_NO_RECUR_ATTR = "envReplace-NoRecur";
+
+    public static final String SPLIT_ATTR = "split";
+
+    public static final String WORKFLOW_MET_ATTR = "workflowMet";
+
+    public static final String DYN_INPUT_FILES_TAG = "dynInputFiles";
+
+    public static final String FILE_TAG = "file";
+
+    public static final String PATH_ATTR = "path";
+
+    public static final String WRITER_CLASS_ATTR = "writerClass";
+
+    public static final String ARGS_ATTR = "args";
+
+    public static final String EXE_TAG = "exe";
+
+    public static final String DIR_ATTR = "dir";
+
+    public static final String SHELL_TYPE_ATTR = "shellType";
+
+    public static final String CMD_TAG = "cmd";
+
+    public static final String OUTPUT_TAG = "output";
+
+    public static final String DIR_TAG = "dir";
+
+    public static final String CREATE_BEFORE_EXEC_ATTR = "createBeforeExe";
+    
+    public static final String FILES_TAG = "files";
+
+    public static final String REGEX_ATTR = "regExp";
+
+    public static final String NAME_ATTR = "name";
+
+    public static final String MET_FILE_WRITER_CLASS_ATTR = "metFileWriterClass";
+
+    public static final String RENAMING_CONV_TAG = "renamingConv";
+
+    public static final String NAMING_EXPR_ATTR = "namingExpr";    
+
+    public static final String FILE_STAGING_TAG = "fileStaging";
+
+    public static final String STAGE_FILES_TAG = "stageFiles";
+
+    public static final String METADATA_KEY_ATTR = "metadataKey";
+
+    public static final String FORCE_ATTR = "force";
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/RegExprOutputFiles.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/RegExprOutputFiles.java
new file mode 100644
index 0000000..8000695
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/RegExprOutputFiles.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pge.config;
+
+import org.apache.oodt.cas.metadata.filenaming.PathUtilsNamingConvention;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A regular expression class to define what OutputFiles
+ * to identify after running a PGE
+ * </p>.
+ */
+public class RegExprOutputFiles {
+
+    private String regExp;
+
+    private String converterClass;
+
+    private Object[] args;
+
+    private PathUtilsNamingConvention renamingConv;
+    
+    public RegExprOutputFiles(String regExp, String converterClass, 
+    		PathUtilsNamingConvention renamingConv, Object[] args) {
+        this.regExp = regExp;
+        this.converterClass = converterClass;
+        this.renamingConv = renamingConv;
+        this.args = args;
+    }
+    
+    public PathUtilsNamingConvention getRenamingConv() {
+    	return this.renamingConv;
+    }
+
+    public String getRegExp() {
+        return this.regExp;
+    }
+
+    public String getConverterClass() {
+        return this.converterClass;
+    }
+
+    public Object[] getArgs() {
+        return this.args;
+    }
+
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/XmlFilePgeConfigBuilder.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/XmlFilePgeConfigBuilder.java
new file mode 100644
index 0000000..cd518e3
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/config/XmlFilePgeConfigBuilder.java
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.config;
+
+//OODT static imports
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.CONFIG_FILE_PATH;
+import static org.apache.oodt.cas.pge.util.XmlHelper.fillIn;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getCustomMetadataElement;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getDir;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getDynamicConfigFiles;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getExeCmds;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getFileStaging;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getImports;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getMetadataElements;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getMetadataKey;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getMetadataKeyRef;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getMetadataValues;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getOuputDirs;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getOutput;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getRootElement;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getShellType;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getStageFilesMetKeys;
+import static org.apache.oodt.cas.pge.util.XmlHelper.isForceStage;
+import static org.apache.oodt.cas.pge.util.XmlHelper.isWorkflowMetKey;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.pge.metadata.PgeMetadata;
+import org.apache.oodt.cas.pge.util.Pair;
+import org.apache.oodt.cas.pge.util.XmlHelper;
+
+//DOM imports
+import org.w3c.dom.Element;
+
+import com.google.common.collect.Lists;
+
+/**
+ * An implementation of the {@link PgeConfigBuilder} that reads an XML file
+ * representation of the {@link PgeConfig}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class XmlFilePgeConfigBuilder implements PgeConfigBuilder {
+
+   private final List<String> missingMetadataKeys;
+
+   public XmlFilePgeConfigBuilder() {
+      missingMetadataKeys = Lists.newArrayList();
+   }
+
+   @Override
+   public PgeConfig build(PgeMetadata pgeMetadata) throws IOException {
+      try {
+         missingMetadataKeys.clear();
+
+         PgeConfig pgeConfig = new PgeConfig();
+         String configFile = fillIn(pgeMetadata.getMetadata(CONFIG_FILE_PATH),
+               pgeMetadata.asMetadata());
+         if (configFile == null) {
+            throw new Exception("Must specify metadata field '"
+                  + CONFIG_FILE_PATH + "'");
+         }
+         pgeMetadata.replaceMetadata(loadConfigFile(configFile, pgeConfig,
+               pgeMetadata));
+         return pgeConfig;
+      } catch (Exception e) {
+         throw new IOException("Failed to build PgeConfig : " + e.getMessage(),
+               e);
+      }
+   }
+
+   private PgeMetadata loadConfigFile(String configFile, PgeConfig pgeConfig,
+         PgeMetadata parentPgeMetadata) throws Exception {
+      PgeMetadata pgeMetadata = new PgeMetadata(parentPgeMetadata);
+      Element root = getRootElement(configFile);
+
+      // Read in imports
+      List<Pair<String, String>> imports = getImports(root, pgeMetadata.asMetadata());
+      for (Pair<String, String> imp : imports) {
+         String namespace = imp.getFirst();
+         String file = imp.getSecond();
+
+         // If relative path, then make path relative to configFile.
+         if (!file.startsWith(File.separator)) {
+            file = new File(configFile).getParent() + File.separator + file;
+         }
+
+         // Add metadata generated from import.
+         if (namespace != null) {
+            pgeMetadata.replaceMetadata(
+                  loadConfigFile(file, pgeConfig, parentPgeMetadata),
+                  namespace);
+         } else {
+            pgeMetadata.replaceMetadata(loadConfigFile(file, pgeConfig,
+                  parentPgeMetadata));
+         }
+      }
+
+      // load custom metadata
+      loadCustomMetadata(root, pgeMetadata);
+      Metadata metadata = pgeMetadata.asMetadata();
+
+      // load dynamic config file info
+      for (DynamicConfigFile dcf : getDynamicConfigFiles(root, metadata)) {
+         pgeConfig.addDynamicConfigFile(dcf);
+      }
+
+      // load file staging info.
+      loadFileStagingInfo(root, pgeConfig, pgeMetadata);
+
+      // load exe info
+      Element exeElem = XmlHelper.getExe(root);
+      if (exeElem != null) {
+         pgeConfig.setExeDir(getDir(exeElem, metadata));
+         pgeConfig.setShellType(getShellType(exeElem, metadata));
+         pgeConfig.setExeCmds(getExeCmds(exeElem, metadata));
+      }
+
+      // load output dirs
+      Element outputElem = getOutput(root);
+      if (outputElem != null) {
+         for (OutputDir outputDir : getOuputDirs(outputElem, metadata)) {
+            pgeConfig.addOuputDirAndExpressions(outputDir);
+         }
+      }
+
+      return pgeMetadata;
+   }
+
+   private void loadCustomMetadata(Element root, PgeMetadata pgeMetadata)
+         throws MalformedURLException, Exception {
+
+      // Check if there is a 'customMetadata' elem and load it.
+      Element customMetadataElem = getCustomMetadataElement(root);
+      if (customMetadataElem == null) {
+         return;
+      }
+
+      // Iterate through metadata elements.
+      for (Element metElem : getMetadataElements(customMetadataElem)) {
+         Metadata curMetadata = pgeMetadata.asMetadata();
+
+         // Load supported metadata element attributes.
+         String key = getMetadataKey(metElem, curMetadata);
+         List<String> values = getMetadataValues(metElem, curMetadata);
+         String keyRef = getMetadataKeyRef(metElem, curMetadata);
+
+         // Check that either val or key-ref is given.
+         if (!values.isEmpty() && keyRef != null) {
+            throw new Exception(
+                  "Cannot specify both values and keyref for metadata key '"
+                        + key + "'");
+
+            // If val is given then set metadata with key and val.
+         } else if (!values.isEmpty()) {
+            pgeMetadata.replaceMetadata(key, values);
+
+            // Otherwise key-ref was given, so set the link.
+         } else {
+            pgeMetadata.linkKey(key, keyRef);
+         }
+
+         // Check if current key should be marked as workflow metadata.
+         if (isWorkflowMetKey(metElem, curMetadata)) {
+            pgeMetadata.markAsDynamicMetadataKey(key);
+         }
+      }
+   }
+
+   private void loadFileStagingInfo(Element root, PgeConfig pgeConfig,
+         PgeMetadata pgeMetadata) throws Exception {
+      Metadata metadata = pgeMetadata.asMetadata();
+      Element fileStagingElem = getFileStaging(root);
+
+      // Check if there is file staging info specified.
+      if (fileStagingElem != null) {
+         FileStagingInfo fileStagingInfo = new FileStagingInfo(getDir(
+               fileStagingElem, metadata), isForceStage(fileStagingElem,
+               metadata));
+
+         // Iterate through list of metadata keys which have list of files as
+         // their values which should be staged.
+         for (String metKey : getStageFilesMetKeys(fileStagingElem, metadata)) {
+            List<String> files = metadata.getAllMetadata(metKey);
+            fileStagingInfo.addFilePaths(files);
+
+            // Generate paths which the files will be staged to.
+            List<String> newPaths = Lists.newArrayList();
+            for (String file : files) {
+               File fileHandle = new File(file);
+               if (fileStagingInfo.isForceStaging() || !fileHandle.exists()) {
+                  newPaths.add(fileStagingInfo.getStagingDir() + File.separator
+                        + fileHandle.getName());
+               } else {
+                  newPaths.add(file);
+               }
+            }
+
+            // Update metadata key with what will be the new paths of the files.
+            pgeMetadata.replaceMetadata(metKey, newPaths);
+         }
+
+         // Add staging info to PgeConfig.
+         pgeConfig.setFileStagingInfo(fileStagingInfo);
+      }
+   }
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/metadata/PgeMetadata.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/metadata/PgeMetadata.java
new file mode 100644
index 0000000..a56c8c4
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/metadata/PgeMetadata.java
@@ -0,0 +1,489 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.metadata;
+
+//JDK imports
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import java.util.Vector;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+
+//Google imports
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+/**
+ * A wrapper class to act as a facade interface to all the different
+ * {@link Metadata} sources given to a PGE.
+ * 
+ * NOTE: 2 ways to update DYNAMIC metadata: 1) Create a key link to a DYNAMIC metadata
+ * key, then change the value of the key link or 2) add metadata then mark the
+ * key as dynamic and commit it.
+ * 
+ * @author bfoster (Brian Foster)
+ * @author mattmann (Chris Mattmann)
+ */
+public class PgeMetadata {
+
+   public enum Type {
+      STATIC, DYNAMIC, LOCAL;
+   }
+   public static final List<Type> DEFAULT_COMBINE_ORDER = Lists
+         .newArrayList(Type.LOCAL, Type.DYNAMIC, Type.STATIC);
+   
+   public static final List<Type> DEFAULT_QUERY_ORDER = Lists
+		   .newArrayList(Type.STATIC, Type.DYNAMIC, Type.LOCAL);
+
+   private final Metadata staticMetadata;
+   private final Metadata dynamicMetadata;
+   private final Metadata localMetadata;
+
+   private final Map<String, String> keyLinkMap;
+   private final Set<String> markedAsDynamicMetKeys;
+
+   public PgeMetadata() {
+      keyLinkMap = Maps.newHashMap();
+      markedAsDynamicMetKeys = Sets.newHashSet();
+      staticMetadata = new Metadata();
+      dynamicMetadata = new Metadata();
+      localMetadata = new Metadata();
+   }
+
+   public PgeMetadata(PgeMetadata pgeMetadata) {
+      this();
+
+      Validate.notNull(pgeMetadata, "pgeMetadata cannot be null");
+
+      replaceMetadata(pgeMetadata);
+   }
+
+   public PgeMetadata(Metadata staticMetadata, Metadata dynamicMetadata) {
+      this();
+
+      Validate.notNull(staticMetadata, "staticMetadata cannot be null");
+      Validate.notNull(dynamicMetadata, "dynamicMetadata cannot be null");
+
+      this.staticMetadata.replaceMetadata(staticMetadata);
+      this.dynamicMetadata.replaceMetadata(dynamicMetadata);
+   }
+
+   /**
+    * Replaces or creates this {@link PgeMetadata}'s metadata with given
+    * {@link PgeMetadata}'s metadata. Also adds in the list of given
+    * {@link PgeMetadata}'s LOCAL metadata marked for promotion DYNAMIC
+    * metadata and list of key links.
+    * 
+    * @param pgeMetadata
+    *           A {@link PgeMetadata} whose metadata and key links will be added
+    *           to this {@link PgeMetadata}'s metadata and key links.
+    */
+   public void replaceMetadata(PgeMetadata pgeMetadata) {
+      Validate.notNull(pgeMetadata, "pgeMetadata cannot be null");
+
+      staticMetadata.replaceMetadata(pgeMetadata.staticMetadata);
+      dynamicMetadata.replaceMetadata(pgeMetadata.dynamicMetadata);
+      localMetadata.replaceMetadata(pgeMetadata.localMetadata);
+
+      keyLinkMap.putAll(pgeMetadata.keyLinkMap);
+      markedAsDynamicMetKeys.addAll(pgeMetadata.markedAsDynamicMetKeys);
+   }
+
+   /**
+    * Replaces or creates this {@link PgeMetadata}'s metadata with given
+    * {@link PgeMetadata}'s metadata. The provided "group" will be used to
+    * namespace the given {@link PgeMetadata}'s LOCAL metadata when add to this
+    * {@link PgeMetadata}'s LOCAL metadata. It will also namespace given
+    * {@link PgeMetadata}'s key links before adding then to this
+    * {@link PgeMetadata}'s key links. Also add in the list of given
+    * {@link PgeMetadata}'s LOCAL metadata marked for promotion DYNAMIC
+    * metadata.
+    * 
+    * @param pgeMetadata
+    *           A {@link PgeMetadata} whose metadata and key links will be added
+    *           to this {@link PgeMetadata}'s metadata and key links.
+    * @param group
+    *           The namespace which will be used to namespace given
+    *           {@link PgeMetadata}'s LOCAL metadata and key links before being
+    *           added to this {@link PgeMetadata}'s LOCAL metadata and key
+    *           links.
+    */
+   public void replaceMetadata(PgeMetadata pgeMetadata, String group) {
+      Validate.notNull(pgeMetadata, "pgeMetadata cannot be null");
+      Validate.notNull(group, "group cannot be null");
+
+      staticMetadata.replaceMetadata(pgeMetadata.staticMetadata);
+      dynamicMetadata.replaceMetadata(pgeMetadata.dynamicMetadata);
+      localMetadata.replaceMetadata(group, pgeMetadata.localMetadata);
+
+      // Namespace link keys that point to either importing
+      // metadata's local key or link key.
+      for (String keyLink : pgeMetadata.keyLinkMap.keySet()) {
+         String key = pgeMetadata.keyLinkMap.get(keyLink);
+         // Check if key is was local key or a link key
+         if (pgeMetadata.localMetadata.containsKey(key)
+               || pgeMetadata.keyLinkMap.containsKey(key)) {
+            key = group + "/" + key;
+         }
+         linkKey(group + "/" + keyLink, key);
+      }
+
+      // Namespace workflow keys that point to either importing
+      // metadata's local key or link key.
+      for (String key : pgeMetadata.markedAsDynamicMetKeys) {
+         if (pgeMetadata.localMetadata.containsKey(key)
+               || pgeMetadata.keyLinkMap.containsKey(key)) {
+            key = group + "/" + key;
+         }
+         markAsDynamicMetadataKey(key);
+      }
+   }
+
+   /**
+    * Use to mark LOCAL keys which should be moved into DYNAMIC metadata when
+    * {@link #commitMarkedDynamicMetadataKeys(String...)} is invoked. If no 
+    * args are specified then all LOCAL metadata is marked for move to
+    * DYNAMIC metadata.
+    * 
+    * @param keys
+    *           Keys to mark as to be made DYNAMIC, otherwise if no keys then
+    *           all LOCAL metadata keys are mark for move to DYNAMIC.
+    */
+   public void markAsDynamicMetadataKey(String... keys) {
+      List<String> markedKeys = Lists.newArrayList(keys);
+      if (markedKeys.isEmpty()) {
+         markedKeys.addAll(localMetadata.getAllKeys());
+      }
+      markedAsDynamicMetKeys.addAll(markedKeys);
+   }
+
+   /**
+    * Use to commit marked LOCAL keys to DYNAMIC keys. Specify a list of keys
+    * only if you want to limit the keys which get committed, otherwise all
+    * marked keys will be moved into DYNAMIC metadata.
+    * 
+    * @param keys
+    *           The list of marked LOCAL metadata keys which should be moved
+    *           into DYNAMIC metadata. If no keys are specified then all marked
+    *           keys are moved.
+    */
+   public void commitMarkedDynamicMetadataKeys(String... keys) {
+      Set<String> commitKeys = Sets.newHashSet(keys);
+      if (commitKeys.isEmpty()) {
+         commitKeys.addAll(markedAsDynamicMetKeys);
+      } else {
+         commitKeys.retainAll(markedAsDynamicMetKeys);
+      }
+      for (String key : commitKeys) {
+         dynamicMetadata.replaceMetadata(key,
+               localMetadata.getAllMetadata(resolveKey(key)));
+         localMetadata.removeMetadata(key);
+         markedAsDynamicMetKeys.remove(key);
+      }
+   }
+
+   @VisibleForTesting
+   protected Set<String> getMarkedAsDynamicMetadataKeys() {
+      return Collections.unmodifiableSet(markedAsDynamicMetKeys);
+   }
+
+   /**
+    * Create a key which is a link to another key, such that if you get the
+    * metadata values for the created link it will return the current metadata
+    * values of the key it was linked to. NOTE: if the key's metadata values
+    * change, then the metadata values for the link key will also be the changed
+    * values. If you want to create a key which holds the current value of a
+    * key, then create a new metadata key.
+    * 
+    * @param keyLink
+    *           The name of the link key you wish to create.
+    * @param key
+    *           The key you which to link to (may also be a key link)
+    */
+   public void linkKey(String keyLink, String key) {
+      Validate.notNull(keyLink, "keyLink cannot be null");
+      Validate.notNull(key, "key cannot be null");
+
+      localMetadata.removeMetadata(keyLink);
+      keyLinkMap.put(keyLink, key);
+   }
+
+   /**
+    * Removes a key link reference. The key which the key link was linked to
+    * remains unchanged.
+    * 
+    * @param keyLink
+    *           The key link which you wish to destroy.
+    */
+   public void unlinkKey(String keyLink) {
+      Validate.notNull(keyLink, "keyLink cannot be null");
+
+      keyLinkMap.remove(keyLink);
+   }
+
+   /**
+    * Check if the given key name is a key link.
+    * 
+    * @param key
+    *           The key name in question.
+    * @return True is the given key name is a key link, false if key name is an
+    *         actual key.
+    */
+   public boolean isLink(String key) {
+      Validate.notNull(key, "key cannot be null");
+
+      return keyLinkMap.containsKey(key);
+   }
+
+   /**
+    * Find the actual key whose value will be returned for the given key. If the
+    * given key is a key (not a key link) then the given key will just be
+    * returned, otherwise it will trace through key link mapping to find the key
+    * which the given key link points to.
+    * 
+    * @param key
+    *           The name of a key or key link.
+    * @return The key whose value will be returned for the given key or key
+    *         link.
+    */
+   public String resolveKey(String key) {
+      Validate.notNull(key, "key cannot be null");
+
+      while (keyLinkMap.containsKey(key)) {
+         key = keyLinkMap.get(key);
+      }
+      return key;
+   }
+
+   /**
+    * Determines the path by which the given key (if it is a key link) links to
+    * the key whose value it will return. If the given key is a key link and
+    * points to a key then the returning {@link List} will be of size 1 and will
+    * contain just that key. However, if the given key is a key link which
+    * points to another key link then the returning {@link List} will be greater
+    * than 1 (will depend on how many key links are connected before they actual
+    * point to a key. If the given key is a key, then the returning {@link List}
+    * will be empty.
+    * 
+    * @param key
+    *           The path to the key whose value will be returned for the give
+    *           key.
+    * @return A key path {@link List}.
+    */
+   public List<String> getReferenceKeyPath(String key) {
+      Validate.notNull(key, "key cannot be null");
+
+      List<String> keyPath = Lists.newArrayList();
+      while (keyLinkMap.containsKey(key))
+         keyPath.add(key = keyLinkMap.get(key));
+      return keyPath;
+   }
+
+   public void replaceMetadata(PgeTaskMetKeys key, String value) {
+      Validate.notNull(key, "key cannot be null");
+
+      replaceMetadata(key.getName(), value);
+   }
+
+   /**
+    * Replace the given key's value with the given value. If the given key is a
+    * key link, then it will update the value of the key it is linked to if that
+    * key is DYNAMIC or LOCAL. If given key is a key link and it links to a
+    * STATIC key, then a new LOCAL key will be create.
+    * 
+    * @param key
+    *           The key or key link for whose value should be replaced.
+    * @param value
+    *           The value to give the given key. Will replace any existing value
+    *           or will be the value of a newly created LOCAL key.
+    */
+   public void replaceMetadata(String key, String value) {
+      Validate.notNull(key, "key cannot be null");
+      Validate.notNull(value, "value cannot be null");
+
+      String resolveKey = resolveKey(key);
+      // If key is a key link which points to a DYNAMIC key then update the
+      // DYNAMIC key's value.
+      if (keyLinkMap.containsKey(key)
+            && dynamicMetadata.containsKey(resolveKey)) {
+         dynamicMetadata.replaceMetadata(resolveKey, value);
+      } else {
+         localMetadata.replaceMetadata(resolveKey, value);
+      }
+   }
+
+   /**
+    * Replace all key values with the given key values in the provided
+    * {@link Metadata}. If the key does not exist it will be created.
+    * 
+    * @param metadata
+    *           {@link Metadata} to replace or create.
+    */
+   public void replaceMetadata(Metadata metadata) {
+      Validate.notNull(metadata, "metadata cannot be null");
+
+      for (String key : metadata.getAllKeys()) {
+         replaceMetadata(key, metadata.getAllMetadata(key));
+      }
+   }
+
+   public void replaceMetadata(PgeTaskMetKeys key, List<String> values) {
+      Validate.notNull(key, "key cannot be null");
+
+      replaceMetadata(key.getName(), values);
+   }
+
+   /**
+    * Replace the given key's values with the given values. If the given key is
+    * a key link, then it will update the values of the key it is linked to if
+    * that key is DYNAMIC or LOCAL. If given key is a key link and it links to a
+    * STATIC key, then a new LOCAL key will be create.
+    * 
+    * @param key
+    *           The key or key link for whose values should be replaced.
+    * @param values
+    *           The values to give the given key. Will replace any existing
+    *           values or will be the values of a newly created LOCAL key.
+    */
+   public void replaceMetadata(String key, List<String> values) {
+      Validate.notNull(key, "key cannot be null");
+      Validate.notNull(values, "values cannot be null");
+
+      String resolveKey = resolveKey(key);
+      if (keyLinkMap.containsKey(key) && dynamicMetadata.containsKey(resolveKey)) {
+         dynamicMetadata.replaceMetadata(resolveKey, values);
+      } else {
+         localMetadata.replaceMetadata(resolveKey, values);
+      }
+   }
+
+   /**
+    * Combines STATIC, DYNAMIC, and LOCAL metadata into one metadata object. You
+    * can restrict which metadata you want combined and change the order in
+    * which combining takes place by specifying Type arguments in the order you
+    * which precedence to be observed. For example, if you perform the
+    * following: pgeMetadata.asMetadata(LOCAL, STATIC) then only LOCAL and
+    * STATIC metadata will be combined and LOCAL metadata will trump STATIC
+    * metadata if they both contain the same key. If no arguments are specified
+    * then DEFAULT_COMBINE_ORDER is used.
+    * 
+    * @param types
+    *           The Type hierarchy you which to use when metadata is combined,
+    *           if no args then DEFAULT_COMBINE_ORDER is used.
+    * @return Combined metadata.
+    */
+   public Metadata asMetadata(Type... types) {
+      List<Type> combineOrder = Lists.newArrayList(types);
+      if (combineOrder.isEmpty()) {
+         combineOrder.addAll(DEFAULT_COMBINE_ORDER);
+      }
+
+      Metadata combinedMetadata = new Metadata();
+      for (Type type : combineOrder) {
+         switch (type) {
+            case DYNAMIC:
+               combinedMetadata.replaceMetadata(dynamicMetadata);
+               break;
+            case STATIC:
+               combinedMetadata.replaceMetadata(staticMetadata);
+               break;
+            case LOCAL:
+               combinedMetadata.replaceMetadata(localMetadata);
+               for (String key : keyLinkMap.keySet()) {
+                  List<String> values = getAllMetadata(key);
+                  if (values != null) {
+                     combinedMetadata.replaceMetadata(key, values);
+                  }
+               }
+               break;
+         }
+      }
+      return combinedMetadata;
+   }
+
+   public List<String> getAllMetadata(PgeTaskMetKeys key, Type... types) {
+      return getAllMetadata(key.getName(), types);
+   }
+
+   /**
+    * Get metadata values for given key. If Types are specified then it provides
+    * the precedence order in which to search for the key. If no Type args are
+    * specified then DEFAULT_QUERY_ORDER will be used. For example if
+    * you pass in Type args: STATIC, LOCAL then STATIC metadata will first be
+    * checked for the key and if it contains it, then it will return the found
+    * value, otherwise it will then check LOCAL metadata for the key and if it
+    * finds the value it will return it, otherwise null.
+    * 
+    * @param key
+    *           The key for whose metadata values should be returned.
+    * @param types
+    *           The type hierarchy which should be used, if no Types specified
+    *           DEFAULT_QUERY_ORDER will be used.
+    * @return Metadata values for given key.
+    */
+   public List<String> getAllMetadata(String key, Type... types) {
+      List<Type> queryOrder = Lists.newArrayList(types);
+      if (queryOrder.isEmpty()) {
+         queryOrder.addAll(DEFAULT_QUERY_ORDER);
+      }
+
+      String useKey = resolveKey(key);
+      for (Type type : queryOrder) {
+         switch (type) {
+            case DYNAMIC:
+               if (dynamicMetadata.containsKey(useKey)) {
+                  return dynamicMetadata.getAllMetadata(useKey);
+               }
+               break;
+            case STATIC:
+               if (staticMetadata.containsKey(useKey)) {
+                  return staticMetadata.getAllMetadata(useKey);
+               }
+               break;
+            case LOCAL:
+               if (localMetadata.containsKey(useKey)) {
+                  return localMetadata.getAllMetadata(useKey);
+               }
+               break;
+         }
+      }
+      return new Vector<String>();
+   }
+
+   public String getMetadata(PgeTaskMetKeys key, Type... types) {
+      return getMetadata(key.getName(), types);
+   }
+
+   /**
+    * Returns the first value returned by {@link #getAllMetadata(String, Type...)}, if it returns
+    * null then this method will also return null.
+    */
+   public String getMetadata(String key, Type... types) {
+      List<String> values = getAllMetadata(key, types);
+      return values != null && values.size() > 0 ? values.get(0) : null;
+   }
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/metadata/PgeTaskMetKeys.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/metadata/PgeTaskMetKeys.java
new file mode 100644
index 0000000..00f0b54
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/metadata/PgeTaskMetKeys.java
@@ -0,0 +1,204 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.metadata;
+
+//Google imports
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * PGETaskInstance Reserved Metadata keys.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public enum PgeTaskMetKeys {
+
+   /**
+    * PGE Name used to create the execution script file name and name the Java Logger.
+    */
+   NAME(
+         "PGETask/Name",
+         "PGETask_Name"),
+   /**
+    * Path to CAS-PGE's configuration file.
+    */
+   CONFIG_FILE_PATH(
+         "PGETask/ConfigFilePath",
+         "PGETask_ConfigFilePath"),
+   /**
+    * CAS-PGE's ConfigBuilder classpath.
+    */
+   PGE_CONFIG_BUILDER(
+         "PGETask/PgeConfigBuilder",
+         "PGETask_PgeConfigBuilder"),
+   /**
+    * The java logger {@link FileHandler} pattern (only for filename though).
+    */
+   LOG_FILENAME_PATTERN(
+         "PGETask/LogFilenamePattern",
+         "PGETask_LogFilenamePattern"),
+   /**
+    * List of {@link ConfigFilePropertyAdder}s classpaths to be run.
+    */
+   PROPERTY_ADDERS(
+         "PGETask/PropertyAdders",
+         "PGETask_PropertyAdderClasspath",
+         true),
+   /**
+    * {@link FileStager}s classpath.
+    */
+   FILE_STAGER(
+         "PGETask/FileStager",
+         "PGETask_FileStager"),
+   /**
+    * List of {@link ConfigFilePropertyAdder}s classpaths to be run.
+    */
+   DUMP_METADATA(
+         "PGETask/DumpMetadata",
+         "PGETask_DumpMetadata"),
+   /**
+    * Set by CAS-PGE to the number of milliseconds it took CAS-PGE to run.
+    */
+   PGE_RUNTIME(
+         "PGETask/Runtime",
+         "PGETask_Runtime"),
+   /**
+    * CAS Workflow Manager URL to which CAS-PGE should update it's status
+    * and metadata.
+    */
+   WORKFLOW_MANAGER_URL(
+         "PGETask/WorkflowManagerUrl",
+         "PCS_WorkflowManagerUrl"),
+   /**
+    * CAS File Manager URL used for queries.
+    */
+   QUERY_FILE_MANAGER_URL(
+         "PGETask/Query/FileManagerUrl",
+         "PCS_FileManagerUrl"),
+   /**
+    * CAS File Manager URL used for product ingestion.
+    */
+   INGEST_FILE_MANAGER_URL(
+         "PGETask/Ingest/FileManagerUrl",
+         "PCS_FileManagerUrl"),
+   /**
+    * The {@link DataTransferFactory} used for product staging.
+    */
+   QUERY_CLIENT_TRANSFER_SERVICE_FACTORY(
+         "PGETask/Query/ClientTransferServiceFactory",
+         "PCS_ClientTransferServiceFactory"),
+   /**
+    * The {@link DataTransferFactory} used for product ingestion.
+    */
+   INGEST_CLIENT_TRANSFER_SERVICE_FACTORY(
+         "PGETask/Ingest/ClientTransferServiceFactory",
+         "PCS_ClientTransferServiceFactory"),
+   /**
+    * Path to Crawler Spring XML config file.
+    */
+   CRAWLER_CONFIG_FILE(
+         "PGETask/Ingest/CrawlerConfigFile",
+         "PCS_ActionRepoFile"),
+   /**
+    * The IDs of the {@link CrawlerAction}s in the {@link #ACTION_REPO_FILE} to run.
+    */
+   ACTION_IDS(
+         "PGETask/Ingest/ActionsIds",
+         "PCS_ActionsIds",
+         true),
+   /**
+    * If set to true the crawler will crawl for directories instead of files.
+    */
+   CRAWLER_CRAWL_FOR_DIRS(
+         "PGETask/Ingest/CrawlerCrawlForDirs",
+         "PCS_CrawlerCrawlForDirs"),
+   /**
+    * If set to true the crawler will perform a deep crawl for files.
+    */
+   CRAWLER_RECUR(
+         "PGETask/Ingest/CrawlerRecur",
+         "PCS_CrawlerRecur"),
+   /**
+    * Path to AutoDetectProductCrawler's MimeExtractorRepo XML config.
+    */
+   MIME_EXTRACTOR_REPO(
+         "PGETask/Ingest/MimeExtractorRepo",
+         "PGETask_MimeExtractorRepo"),
+   /**
+    * List of metadata keys required for Product ingest.
+    */
+   REQUIRED_METADATA(
+         "PGETask/Ingest/RequiredMetadata",
+         "PCS_RequiredMetadata",
+         true),
+   /**
+    * If set to true then will attempt to ingest all Product's even if one
+    * fails. If false, will bail ingest after first failed Product ingest.
+    */
+   ATTEMPT_INGEST_ALL(
+         "PGETask/Ingest/AttemptIngestAll",
+         "PGETask_AttemptIngestAll"),
+   
+   /**
+    * Identifies the metadata file name extension to use when CAS-PGE 
+    * is running in legacy mode and generating metadata files for the 
+    * StdProductCrawler. If not set, will default in CAS-PGE to .met.
+    * Note, there is no new version of this property, it only exists in
+    * legacy mode, but an attempt is made to provide a new path style/grouped
+    * version of the key for forward compat.
+    */
+   MET_FILE_EXT("PGETask/Ingest/MetFileExtension", 
+                "PCS_MetFileExtension");
+
+
+   public static final String USE_LEGACY_PROPERTY = "org.apache.oodt.cas.pge.task.metkeys.legacyMode";
+
+   @VisibleForTesting String name;
+   @VisibleForTesting String legacyName;
+   private boolean isVector;
+
+   PgeTaskMetKeys(String name, String legacyName) {
+      this(name, legacyName, false);
+   }
+
+   PgeTaskMetKeys(String name, String legacyName, boolean isVector) {
+      this.name = name;
+      this.legacyName = legacyName;
+      this.isVector = isVector;
+   }
+
+   public String getName() {
+      return Boolean.getBoolean(USE_LEGACY_PROPERTY) ? legacyName : name;
+   }
+
+   public boolean isVector() {
+      return isVector;
+   }
+
+   public static PgeTaskMetKeys getByName(String name) {
+      for (PgeTaskMetKeys key : values()) {
+         if (key.getName().equals(name)) {
+            return key;
+         }
+      }
+      return null;
+   }
+
+   @Override
+   public String toString() {
+      return getName();
+   }
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/metadata/PgeTaskStatus.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/metadata/PgeTaskStatus.java
new file mode 100644
index 0000000..e2af575
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/metadata/PgeTaskStatus.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.metadata;
+
+//Google imports
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Workflow Statuses for {@link PGETaskInstance}.
+ *
+ * @author bfoster (Brian Foster)
+ * @author mattmann (Chris Mattmann)
+ */
+public enum PgeTaskStatus {
+	
+	/**
+	 * The PGE is staging its input to the job working directory.
+	 */
+   STAGING_INPUT("PGETask_Staging_Input", "STAGING INPUT"),
+   
+   /**
+    * The PGE is building its internal configuration file.
+    */
+   CONF_FILE_BUILD("PGETask_Building_Config_File", "BUILDING CONFIG FILE"),
+   
+   /**
+    * The PGE is executing.
+    */
+   RUNNING_PGE("PGETask_Running", "PGE EXEC"),
+   
+   /**
+    * The ingest crawler has been created, either a StdProductCrawler
+    * or if {@link PgeTaskMetKeys#MIME_EXTRACTOR_REPO} has been specified
+    * an AutoDetectProductCrawler.
+    */
+   CRAWLING("PGETask_Crawling", "CRAWLING");
+
+   public static final String USE_LEGACY_STATUS_PROPERTY = "org.apache.oodt.cas.pge.task.status.legacyMode";
+   
+   @VisibleForTesting private String workflowStatusName;
+   @VisibleForTesting private String legacyName;
+
+   PgeTaskStatus(String workflowStatusName, String legacyName) {
+      this.workflowStatusName = workflowStatusName;
+      this.legacyName = legacyName;
+   }
+
+   public String getWorkflowStatusName() {
+      return Boolean.getBoolean(USE_LEGACY_STATUS_PROPERTY) ? this.legacyName:this.workflowStatusName;
+   }
+   
+   @Override
+   public String toString() {
+      return getWorkflowStatusName();
+   }
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/query/conv/DateVersionConverter.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/query/conv/DateVersionConverter.java
new file mode 100644
index 0000000..dbbc3a9
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/query/conv/DateVersionConverter.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pge.query.conv;
+
+//OODT imports
+import org.apache.oodt.commons.date.DateUtils;
+import org.apache.oodt.cas.filemgr.structs.query.conv.VersionConverter;
+
+//JDK imports
+import java.text.ParseException;
+import java.util.Calendar;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ */
+public class DateVersionConverter implements VersionConverter {
+
+    public double convertToPriority(String version) throws ParseException {
+        Calendar cal = DateUtils.toCalendar(version,
+                DateUtils.FormatType.UTC_FORMAT);
+        return (cal.get(Calendar.YEAR) * 10000)
+                + ((cal.get(Calendar.MONTH) + 1) * 100)
+                + (cal.get(Calendar.DAY_OF_MONTH));
+    }
+
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/staging/FileManagerFileStager.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/staging/FileManagerFileStager.java
new file mode 100644
index 0000000..a97c0fb
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/staging/FileManagerFileStager.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.staging;
+
+//OODT static imports
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.QUERY_CLIENT_TRANSFER_SERVICE_FACTORY;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.QUERY_FILE_MANAGER_URL;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.datatransfer.DataTransfer;
+import org.apache.oodt.cas.filemgr.datatransfer.RemoteDataTransferFactory;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.util.GenericFileManagerObjectFactory;
+import org.apache.oodt.cas.pge.metadata.PgeMetadata;
+
+//Google imports
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+
+//JDK imports
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A {@link FileStager} which uses a FileManager {@link DataTransferer}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class FileManagerFileStager extends FileStager {
+
+   @Override
+   public void stageFile(URI stageFile, File destDir,
+         PgeMetadata pgeMetadata, Logger logger) throws Exception {
+      DataTransfer dataTransferer = createDataTransfer(pgeMetadata, logger);
+      logger.log(Level.INFO, "Using DataTransfer ["
+               + dataTransferer.getClass().getCanonicalName() + "]");
+      setFileManagerUrl(dataTransferer, pgeMetadata, logger);
+      dataTransferer.retrieveProduct(createProduct(stageFile), destDir);
+   }
+
+   @VisibleForTesting
+   static DataTransfer createDataTransfer(PgeMetadata pgeMetadata,
+         Logger logger) throws InstantiationException {
+      if (pgeMetadata.getMetadata(QUERY_CLIENT_TRANSFER_SERVICE_FACTORY) != null) {
+         return GenericFileManagerObjectFactory
+               .getDataTransferServiceFromFactory(pgeMetadata
+                     .getMetadata(QUERY_CLIENT_TRANSFER_SERVICE_FACTORY));
+      } else {
+         logger.log(Level.INFO, "Using default DataTransferer");
+         return new RemoteDataTransferFactory().createDataTransfer();
+      }
+   }
+
+   @VisibleForTesting
+   static void setFileManagerUrl(DataTransfer dataTransferer,
+         PgeMetadata pgeMetadata, Logger logger) throws MalformedURLException {
+      String filemgrUrl = pgeMetadata.getMetadata(QUERY_FILE_MANAGER_URL);
+      if (filemgrUrl != null) {
+         dataTransferer.setFileManagerUrl(new URL(filemgrUrl));
+      } else {
+         logger.log(Level.WARNING, "Metadata field [" + QUERY_FILE_MANAGER_URL
+               + "] was not set, if DataTranferer requires filemgr server,"
+               + " your transfers will fail");
+      }
+   }
+
+   @VisibleForTesting
+   static Product createProduct(URI path) {
+      Product product = new Product();
+      Reference reference = new Reference();
+      reference.setDataStoreReference(path.toString());
+      product.setProductReferences(Lists.newArrayList(reference));
+      return product;
+   }
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/staging/FileStager.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/staging/FileStager.java
new file mode 100644
index 0000000..19b22a0
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/staging/FileStager.java
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.staging;
+
+//OODT static imports
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.QUERY_FILE_MANAGER_URL;
+
+//JDK imports
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.commons.lang.Validate;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.pge.config.FileStagingInfo;
+import org.apache.oodt.cas.pge.metadata.PgeMetadata;
+
+//Google imports
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+
+/**
+ * Responsible for transferring Product files to a directory accessible by
+ * by CAS-PGE.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public abstract class FileStager {
+
+   public void stageFiles(FileStagingInfo fileStagingInfo,
+         PgeMetadata pgeMetadata, Logger logger) throws Exception {
+      logger.log(Level.INFO, "Creating staging directory ["
+            + fileStagingInfo.getStagingDir() + "]");
+      new File(fileStagingInfo.getStagingDir()).mkdirs();
+      for (String file : fileStagingInfo.getFilePaths()) {
+         File fileHandle = new File(file);
+         if (fileStagingInfo.isForceStaging() || !fileHandle.exists()) {
+            logger.log(Level.INFO, "Staging file [" + file
+                  + "] to directory ["
+                  + fileStagingInfo.getStagingDir() + "]");
+            stageFile(asURI(file), new File(fileStagingInfo.getStagingDir()),
+                  pgeMetadata, logger);
+         }
+      }
+      if (!fileStagingInfo.getProductIds().isEmpty()) {
+         XmlRpcFileManagerClient fmClient = createFileManagerClient(pgeMetadata);
+         for (String productId : fileStagingInfo.getProductIds()) {
+            logger.log(Level.INFO, "Staging product [" + productId
+                  + "] to directory ["
+                  + fileStagingInfo.getStagingDir() + "]");
+            for (URI uri : getProductReferences(productId, fmClient)) {
+               logger.log(Level.INFO, "Staging product [" + productId
+                     + "] reference [" + uri
+                     + "] to directory ["
+                     + fileStagingInfo.getStagingDir() + "]");
+               stageFile(uri, new File(fileStagingInfo.getStagingDir()),
+                     pgeMetadata, logger);
+            }
+         }
+      }
+   }
+
+   @VisibleForTesting
+   static XmlRpcFileManagerClient createFileManagerClient(PgeMetadata pgeMetadata)
+         throws Exception {
+      String filemgrUrl = pgeMetadata.getMetadata(QUERY_FILE_MANAGER_URL);
+      if (filemgrUrl == null) {
+         throw new Exception("Must specify [" + QUERY_FILE_MANAGER_URL
+               + "] if you want to stage product IDs");
+      }
+      return new XmlRpcFileManagerClient(new URL(filemgrUrl));
+   }
+
+   @VisibleForTesting
+   static List<URI> getProductReferences(
+         String productId, XmlRpcFileManagerClient fmClient)
+         throws URISyntaxException, CatalogException {
+      List<URI> files = Lists.newArrayList();
+      Product product = new Product();
+      product.setProductId(productId);
+      List<Reference> refs = fmClient.getProductReferences(product);
+      for (Reference ref : refs) {
+         files.add(new URI(ref.getDataStoreReference()));
+      }
+      return files;
+   }
+
+   @VisibleForTesting
+   static URI asURI(String path) throws URISyntaxException {
+      Validate.notNull(path, "path must not be null");
+
+      URI uri = URI.create(path);
+      if (uri.getScheme() == null) {
+         uri = URI.create("file://" + new File(path).getAbsolutePath());
+      }
+      return uri;
+   }
+
+   protected abstract void stageFile(URI stageFile, File destDir,
+         PgeMetadata pgeMetadata, Logger logger) throws Exception;
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/util/GenericPgeObjectFactory.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/util/GenericPgeObjectFactory.java
new file mode 100644
index 0000000..50359e0
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/util/GenericPgeObjectFactory.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.util;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+//OODT imports
+import org.apache.oodt.cas.pge.ConfigFilePropertyAdder;
+import org.apache.oodt.cas.pge.PGETaskInstance;
+import org.apache.oodt.cas.pge.config.PgeConfigBuilder;
+import org.apache.oodt.cas.pge.staging.FileStager;
+import org.apache.oodt.cas.pge.writers.DynamicConfigFileWriter;
+import org.apache.oodt.cas.pge.writers.SciPgeConfigFileWriter;
+
+/**
+ * Factory for creating {@link Object}s.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class GenericPgeObjectFactory {
+
+   private GenericPgeObjectFactory() {}
+
+   public static PGETaskInstance createPGETaskInstance(
+         String clazz, Logger logger) {
+      try {
+         return (PGETaskInstance) Class.forName(clazz).newInstance();
+      } catch (Exception e) {
+         logger.log(Level.SEVERE, "Failed to create PGETaskInstance ["
+               + clazz + "] : " + e.getMessage(), e);
+         return null;
+      }
+   }
+
+   public static PgeConfigBuilder createPgeConfigBuilder(
+         String clazz, Logger logger) {
+      try {
+         return (PgeConfigBuilder) Class.forName(clazz).newInstance();
+      } catch (Exception e) {
+         logger.log(Level.SEVERE, "Failed to create PgeConfigBuilder ["
+               + clazz + "] : " + e.getMessage(), e);
+         return null;
+      }
+   }
+
+   public static ConfigFilePropertyAdder createConfigFilePropertyAdder(
+         String clazz, Logger logger) {
+      try {
+         return (ConfigFilePropertyAdder) Class.forName(clazz).newInstance();
+      } catch (Exception e) {
+         logger.log(Level.SEVERE, "Failed to create ConfigFilePropertyAdder ["
+               + clazz + "] : " + e.getMessage(), e);
+         return null;
+      }
+   }
+
+   public static FileStager createFileStager(
+         String clazz, Logger logger) {
+      try {
+         return (FileStager) Class.forName(clazz).newInstance();
+      } catch (Exception e) {
+         logger.log(Level.SEVERE, "Failed to create FileStager ["
+               + clazz + "] : " + e.getMessage(), e);
+         return null;
+      }
+   }
+
+   public static SciPgeConfigFileWriter createSciPgeConfigFileWriter(
+         String clazz, Logger logger) {
+      try {
+         return (SciPgeConfigFileWriter) Class.forName(clazz).newInstance();
+      } catch (Exception e) {
+         logger.log(Level.SEVERE, "Failed to create SciPgeConfigFileWriter ["
+               + clazz + "] : " + e.getMessage(), e);
+         return null;
+      }
+   }
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/util/Pair.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/util/Pair.java
new file mode 100644
index 0000000..cd2c3d4
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/util/Pair.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.util;
+
+/**
+ * Wrapper class around 2 objects.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class Pair<Type1, Type2> {
+
+   private final Type1 first;
+   private final Type2 second;
+
+   public Pair(Type1 first, Type2 second) {
+      this.first = first;
+      this.second = second;
+   }
+
+   public Type1 getFirst() {
+      return first;
+   }
+
+   public Type2 getSecond() {
+      return second;
+   }
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/util/XmlHelper.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/util/XmlHelper.java
new file mode 100644
index 0000000..eb52905
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/util/XmlHelper.java
@@ -0,0 +1,504 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.util;
+
+//OODT static imports
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.ARGS_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.CMD_TAG;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.CREATE_BEFORE_EXEC_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.CUSTOM_METADATA_TAG;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.DIR_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.DIR_TAG;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.DYN_INPUT_FILES_TAG;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.ENV_REPLACE_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.ENV_REPLACE_NO_RECUR_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.EXE_TAG;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.FILE_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.FILE_STAGING_TAG;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.FILE_TAG;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.FILES_TAG;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.FORCE_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.IMPORT_TAG;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.KEYREF_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.KEY_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.KEY_GEN_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.METADATA_KEY_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.METADATA_TAG;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.MET_FILE_WRITER_CLASS_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.NAME_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.NAMING_EXPR_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.NAMESPACE_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.OUTPUT_TAG;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.PATH_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.RENAMING_CONV_TAG;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.REGEX_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.SHELL_TYPE_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.SPLIT_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.STAGE_FILES_TAG;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.VAL_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.WORKFLOW_MET_ATTR;
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.WRITER_CLASS_ATTR;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.QUERY_FILE_MANAGER_URL;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.filemgr.util.QueryUtils;
+import org.apache.oodt.cas.filemgr.util.SqlParser;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.filenaming.PathUtilsNamingConvention;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.pge.config.DynamicConfigFile;
+import org.apache.oodt.cas.pge.config.OutputDir;
+import org.apache.oodt.cas.pge.config.RegExprOutputFiles;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//DOM imports
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+//Google imports
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+
+/**
+ * Help class with method for parsing XMLFilePgeConfigBuilder config XML file.
+ * 
+ * @author bfoster (Brian Foster)
+ * @author mattmann (Chris Mattmann)
+ */
+public class XmlHelper {
+
+	private XmlHelper() {
+	}
+
+	public static Element getRootElement(String xmlFilePath)
+			throws FileNotFoundException {
+		return XMLUtils.getDocumentRoot(
+				new FileInputStream(new File(xmlFilePath)))
+				.getDocumentElement();
+	}
+
+	public static List<Pair<String, String>> getImports(Element elem,
+			Metadata metadata) throws Exception {
+		List<Pair<String, String>> imports = Lists.newArrayList();
+		NodeList nodeList = elem.getElementsByTagName(IMPORT_TAG);
+		for (int i = 0; i < nodeList.getLength(); i++) {
+			Element importElem = (Element) nodeList.item(i);
+			String namespace = getNamespace(importElem, metadata);
+			String file = getFile(importElem, metadata);
+			imports.add(new Pair<String, String>(namespace, file));
+		}
+		return imports;
+	}
+
+	public static String getNamespace(Element elem, Metadata metadata)
+			throws Exception {
+		String namespace = elem.getAttribute(NAMESPACE_ATTR);
+		if (!Strings.isNullOrEmpty(namespace)) {
+			return fillIn(namespace, metadata, false);
+		} else {
+			return null;
+		}
+	}
+
+	public static String getFile(Element elem, Metadata metadata)
+			throws Exception {
+		String file = elem.getAttribute(FILE_ATTR);
+		if (!Strings.isNullOrEmpty(file)) {
+			return fillIn(file, metadata, false);
+		} else {
+			return null;
+		}
+	}
+
+	public static Element getCustomMetadataElement(Element root)
+			throws Exception {
+		NodeList nodes = root.getElementsByTagName(CUSTOM_METADATA_TAG);
+		if (nodes.getLength() == 0) {
+			return null;
+		} else if (nodes.getLength() == 1) {
+			return (Element) nodes.item(0);
+		} else {
+			throw new Exception("Found more than one '" + CUSTOM_METADATA_TAG
+					+ "' element");
+		}
+	}
+
+	public static List<Element> getMetadataElements(Element customMetadataElem) {
+		NodeList metElemsNodeList = customMetadataElem
+				.getElementsByTagName(METADATA_TAG);
+		List<Element> metElems = Lists.newArrayList();
+		for (int i = 0; i < metElemsNodeList.getLength(); i++) {
+			metElems.add((Element) metElemsNodeList.item(i));
+		}
+		return metElems;
+	}
+
+	public static String getMetadataKey(Element metElem, Metadata metadata)
+			throws Exception {
+		String key = metElem.getAttribute(KEY_ATTR);
+
+		// no key attr, so check for key_gen attr.
+		if (Strings.isNullOrEmpty(key)) {
+			key = fillIn(metElem.getAttribute(KEY_GEN_ATTR), metadata);
+		}
+
+		// if still no key value, then fail.
+		if (Strings.isNullOrEmpty(key)) {
+			throw new Exception("Must specify either metadata attr '"
+					+ KEY_ATTR + "' or '" + KEY_GEN_ATTR + "'");
+		}
+
+		// else success!
+		return key;
+	}
+
+	public static boolean isEnvReplaceNoRecur(Element elem, Metadata metadata)
+			throws Exception {
+		String isEnvReplaceNoRecur = elem
+				.getAttribute(ENV_REPLACE_NO_RECUR_ATTR);
+		if (Strings.isNullOrEmpty(isEnvReplaceNoRecur)) {
+			return false;
+		} else {
+			return isEnvReplaceNoRecur.trim().toLowerCase().equals("true");
+		}
+	}
+
+	public static boolean isEnvReplace(Element elem, Metadata metadata)
+			throws Exception {
+		String isEnvReplace = elem.getAttribute(ENV_REPLACE_ATTR);
+		if (Strings.isNullOrEmpty(isEnvReplace)) {
+			return true;
+		} else {
+			return !isEnvReplace.trim().toLowerCase().equals("false");
+		}
+	}
+
+	public static boolean isMultiValue(Element elem, Metadata metadata)
+			throws Exception {
+		return Boolean.parseBoolean(fillIn(elem.getAttribute(SPLIT_ATTR),
+				metadata));
+	}
+
+	public static List<String> getMetadataValues(Element elem, Metadata metadata)
+			throws Exception {
+		List<String> values = Lists.newArrayList();
+
+		// Read val attr.
+		String value = elem.getAttribute(VAL_ATTR);
+
+		// Check if val tag was not specified see if value was given as element
+		// text.
+		if (Strings.isNullOrEmpty(value)) {
+			value = elem.getTextContent();
+		}
+
+		// If value was found.
+		if (!Strings.isNullOrEmpty(value)) {
+
+			// Is multi-value so split up value.
+			if (isMultiValue(elem, metadata)) {
+				for (String v : Splitter.on(",").split(value)) {
+
+					// Check for envReplace and perform met replacement on value
+					// if set.
+					if (isEnvReplaceNoRecur(elem, metadata)) {
+						values.add(fillIn(v, metadata, false));
+					} else if (isEnvReplace(elem, metadata)) {
+						values.add(fillIn(v, metadata));
+					}
+				}
+
+				// Is scalar
+			} else {
+
+				// Check for envReplace and perform met replacement on value if
+				// set.
+				if (isEnvReplaceNoRecur(elem, metadata)) {
+					value = fillIn(value, metadata, false);
+				} else if (isEnvReplace(elem, metadata)) {
+					value = fillIn(value, metadata);
+				}
+				values.add(value);
+			}
+
+		}
+		return values;
+	}
+
+	public static String getMetadataKeyRef(Element elem, Metadata metadata)
+			throws Exception {
+		String keyRef = elem.getAttribute(KEYREF_ATTR);
+		if (!Strings.isNullOrEmpty(keyRef)) {
+
+			// Check for envReplace and perform met replacement on value if set.
+			if (isEnvReplaceNoRecur(elem, metadata)) {
+				keyRef = fillIn(keyRef, metadata, false);
+			} else if (isEnvReplace(elem, metadata)) {
+				keyRef = fillIn(keyRef, metadata);
+			}
+
+			return keyRef;
+		} else {
+			return null;
+		}
+	}
+
+	public static boolean isWorkflowMetKey(Element elem, Metadata metadata)
+			throws Exception {
+		return Boolean.parseBoolean(fillIn(
+				elem.getAttribute(WORKFLOW_MET_ATTR), metadata, false));
+	}
+
+	public static String getPath(Element elem, Metadata metadata)
+			throws Exception {
+		return fillIn(elem.getAttribute(PATH_ATTR), metadata, false);
+	}
+
+	public static String getWriter(Element elem, Metadata metadata)
+			throws Exception {
+		return fillIn(elem.getAttribute(WRITER_CLASS_ATTR), metadata, false);
+	}
+
+	public static List<String> getArgs(Element elem, Metadata metadata)
+			throws Exception {
+		List<String> args = Lists.newArrayList();
+		for (String arg : Splitter.on(",").split(elem.getAttribute(ARGS_ATTR))) {
+			args.add(fillIn(arg, metadata, false));
+		}
+		if (args.size() == 1 && Strings.isNullOrEmpty(args.get(0))) {
+			return Lists.newArrayList();
+		} else {
+			return args;
+		}
+	}
+
+	public static List<DynamicConfigFile> getDynamicConfigFiles(Element elem,
+			Metadata metadata) throws Exception {
+		List<DynamicConfigFile> dynamicConfigFiles = Lists.newArrayList();
+		NodeList nodeList = elem.getElementsByTagName(DYN_INPUT_FILES_TAG);
+
+		// Check if dynInput element exists.
+		if (nodeList.getLength() > 0) {
+			Element dynamicConfigFilesElem = (Element) nodeList.item(0);
+			nodeList = dynamicConfigFilesElem.getElementsByTagName(FILE_TAG);
+
+			// Load each dynamic input file information.
+			for (int i = 0; i < nodeList.getLength(); i++) {
+				Element fileElem = (Element) nodeList.item(i);
+				String path = getPath(fileElem, metadata);
+				String writer = getWriter(fileElem, metadata);
+				List<String> args = getArgs(fileElem, metadata);
+				dynamicConfigFiles.add(new DynamicConfigFile(path, writer, args
+						.toArray(new String[0])));
+			}
+		}
+		return dynamicConfigFiles;
+	}
+
+	public static Element getExe(Element elem) throws Exception {
+		NodeList nodeList = elem.getElementsByTagName(EXE_TAG);
+		if (nodeList.getLength() > 1) {
+			throw new Exception("Can only specify '" + EXE_TAG + "' once!");
+		} else if (nodeList.getLength() == 1) {
+			return (Element) nodeList.item(0);
+		} else {
+			return null;
+		}
+	}
+
+	public static String getDir(Element elem, Metadata metadata)
+			throws MalformedURLException, Exception {
+		return fillIn(elem.getAttribute(DIR_ATTR), metadata);
+	}
+
+	public static String getShellType(Element elem, Metadata metadata)
+			throws MalformedURLException, Exception {
+		return fillIn(elem.getAttribute(SHELL_TYPE_ATTR), metadata);
+	}
+
+	public static List<String> getExeCmds(Element elem, Metadata metadata)
+			throws MalformedURLException, DOMException, Exception {
+		List<String> exeCmds = Lists.newArrayList();
+		NodeList nodeList = elem.getElementsByTagName(CMD_TAG);
+		for (int i = 0; i < nodeList.getLength(); i++) {
+			Element cmdElem = (Element) nodeList.item(i);
+			String exeCmd = cmdElem.getTextContent();
+			if (isEnvReplaceNoRecur(cmdElem, metadata)) {
+				exeCmd = fillIn(exeCmd, metadata, false);
+			} else if (isEnvReplace(cmdElem, metadata)) {
+				exeCmd = fillIn(exeCmd, metadata);
+			}
+			exeCmds.add(exeCmd);
+		}
+		return exeCmds;
+	}
+
+	public static Element getFileStaging(Element elem) throws Exception {
+		NodeList nodeList = elem.getElementsByTagName(FILE_STAGING_TAG);
+		if (nodeList.getLength() > 1) {
+			throw new Exception("Can only specify '" + FILE_STAGING_TAG
+					+ "' once!");
+		} else if (nodeList.getLength() == 1) {
+			return (Element) nodeList.item(0);
+		} else {
+			return null;
+		}
+	}
+
+	public static boolean isForceStage(Element elem, Metadata metadata)
+			throws Exception {
+		return Boolean.parseBoolean(fillIn(elem.getAttribute(FORCE_ATTR),
+				metadata));
+	}
+
+	public static String getFileStagingMetadataKey(Element elem,
+			Metadata metadata) throws Exception {
+		return fillIn(elem.getAttribute(METADATA_KEY_ATTR), metadata);
+	}
+
+	public static List<String> getStageFilesMetKeys(Element elem,
+			Metadata metadata) throws Exception {
+		List<String> metKeys = Lists.newArrayList();
+		NodeList nodeList = elem.getElementsByTagName(STAGE_FILES_TAG);
+		for (int i = 0; i < nodeList.getLength(); i++) {
+			Element stageFilesElem = (Element) nodeList.item(i);
+			metKeys.add(getFileStagingMetadataKey(stageFilesElem, metadata));
+		}
+		return metKeys;
+	}
+
+	public static Element getOutput(Element elem) throws Exception {
+		NodeList nodeList = elem.getElementsByTagName(OUTPUT_TAG);
+		if (nodeList.getLength() > 1) {
+			throw new Exception("Can only specify '" + OUTPUT_TAG + "' once!");
+		} else if (nodeList.getLength() == 1) {
+			return (Element) nodeList.item(0);
+		} else {
+			return null;
+		}
+	}
+
+	public static boolean isCreateBeforeExe(Element elem, Metadata metadata)
+			throws Exception {
+		return Boolean.parseBoolean(fillIn(
+				elem.getAttribute(CREATE_BEFORE_EXEC_ATTR), metadata));
+	}
+
+	public static List<OutputDir> getOuputDirs(Element elem, Metadata metadata)
+			throws Exception {
+		List<OutputDir> outputDirs = Lists.newArrayList();
+		NodeList nodeList = elem.getElementsByTagName(DIR_TAG);
+		for (int i = 0; i < nodeList.getLength(); i++) {
+			Element outputDirElem = (Element) nodeList.item(i);
+			String path = getPath(outputDirElem, metadata);
+			boolean createBeforeExe = isCreateBeforeExe(outputDirElem, metadata);
+			OutputDir outputDir = new OutputDir(path, createBeforeExe);
+			getRegExpOutputFiles(outputDirElem, metadata, outputDir);
+			outputDirs.add(outputDir);
+		}
+		return outputDirs;
+
+	}
+
+	public static void getRegExpOutputFiles(Element elem, Metadata metadata,
+			OutputDir outputDir) throws Exception {
+		NodeList fileList = elem.getElementsByTagName(FILES_TAG);
+		for (int j = 0; j < fileList.getLength(); j++) {
+			Element fileElement = (Element) fileList.item(j);
+			String outputFile = fileElement.getAttribute(REGEX_ATTR);
+			if (outputFile.equals("")){
+				outputFile = fillIn(fileElement.getAttribute(NAME_ATTR),
+						metadata);
+			}
+			PathUtilsNamingConvention renamingConvention = null;
+			NodeList renamingConvNodes = fileElement
+					.getElementsByTagName(RENAMING_CONV_TAG);
+
+			if (renamingConvNodes.getLength() > 0) {
+				Element renamingElement = (Element) renamingConvNodes.item(0);
+				String namingExpr = renamingElement
+						.getAttribute(NAMING_EXPR_ATTR);
+				if (renamingElement.getAttribute(ENV_REPLACE_ATTR)
+						.toLowerCase().equals("true")){
+					namingExpr = fillIn(namingExpr, metadata, false);
+				}
+				else if (!renamingElement.getAttribute(ENV_REPLACE_ATTR)
+						.toLowerCase().equals("false")){
+					namingExpr = fillIn(namingExpr, metadata);
+				}
+				renamingConvention = new PathUtilsNamingConvention();
+				renamingConvention.setNamingConv(namingExpr);
+				NodeList metadataNodes = renamingElement
+						.getElementsByTagName(METADATA_TAG);
+				for (int k = 0; k < metadataNodes.getLength(); k++) {
+					renamingConvention.addTmpReplaceMet(((Element) metadataNodes
+							.item(k)).getAttribute(KEY_ATTR), Arrays
+							.asList(((Element) metadataNodes.item(k))
+									.getAttribute(VAL_ATTR).split(",")));
+				}
+			}
+
+			outputDir
+					.addRegExprOutputFiles(new RegExprOutputFiles(outputFile,
+							fillIn(fileElement
+									.getAttribute(MET_FILE_WRITER_CLASS_ATTR),
+									metadata), renamingConvention, (Object[]) fillIn(
+									fileElement.getAttribute(ARGS_ATTR),
+									metadata).split(",")));
+		}
+
+	}
+
+	public static String fillIn(String value, Metadata inputMetadata)
+			throws Exception {
+		return fillIn(value, inputMetadata, true);
+	}
+
+	public static String fillIn(String value, Metadata inputMetadata,
+			boolean envReplaceRecur) throws Exception {
+		try {
+			while ((value = PathUtils
+					.doDynamicReplacement(value, inputMetadata)).contains("[")
+					&& envReplaceRecur)
+				;
+			if (value.toUpperCase().matches(
+					"^\\s*SQL\\s*\\(.*\\)\\s*\\{.*\\}\\s*$"))
+				value = QueryUtils
+						.getQueryResultsAsString(new XmlRpcFileManagerClient(
+								new URL(inputMetadata
+										.getMetadata(QUERY_FILE_MANAGER_URL
+												.getName())))
+								.complexQuery(SqlParser
+										.parseSqlQueryMethod(value)));
+			return value;
+		} catch (Exception e) {
+			throw new Exception("Failed to parse value: " + value, e);
+		}
+	}
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/CsvConfigFileWriter.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/CsvConfigFileWriter.java
new file mode 100644
index 0000000..f21f251
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/CsvConfigFileWriter.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.writers;
+
+//Google static imports
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+//JDK imports
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.List;
+import java.util.logging.Logger;
+
+//Google imports
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * CSV {@link SciPgeConfigFileWriter} which takes a comma separted list of
+ * {@link String}s as the first index of the args and generates a CSV file from
+ * the metadata fields listed. For example, if the list of {@link String}s given
+ * is:
+ *
+ * <pre>
+ *    InputFiles,IsText
+ * </pre>
+ *
+ * And:
+ *
+ * <pre>
+ *    InputFiles=File1.txt,File2.dat,File3.xml
+ *    IsText=true,false,true
+ * </pre>
+ *
+ * Then the CSV file create will look like:
+ *
+ * <pre>
+ *    InputFiles,IsText
+ *    File1.text,true
+ *    File2.dat,false
+ *    File3.xml,true
+ * </pre>
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class CsvConfigFileWriter extends DynamicConfigFileWriter {
+
+   private static final int HEADER_INDEX = 0;
+   private static final int DELIM_INDEX = 0;
+
+   private static final String DEFAULT_DELIM = ",";
+
+   @Override
+   public File generateFile(String filePath, Metadata metadata, Logger logger,
+         Object... customArgs) throws Exception {
+      checkArgument(customArgs.length > 0,
+            CsvConfigFileWriter.class.getCanonicalName()
+                  + " has no args specified");
+      List<String> header = checkNotNull(
+            Lists.newArrayList(Splitter.on(",").split(
+                  (String) customArgs[HEADER_INDEX])),
+            "Must specify CSV header in args at index = '" + HEADER_INDEX + "'");
+      String delim = DEFAULT_DELIM;
+      if (customArgs.length > DELIM_INDEX) {
+         delim = (String) customArgs[DELIM_INDEX];
+      }
+
+      return writeCsvFile(filePath, header, generateRows(header, metadata),
+            delim);
+   }
+
+   @VisibleForTesting
+   protected List<List<String>> generateRows(List<String> header,
+         Metadata meatadata) {
+      List<List<String>> rows = Lists.newArrayList();
+      int index = 0;
+      TOP: while (true) {
+         for (String columnName : header) {
+            List<String> values = meatadata.getAllMetadata(columnName);
+            if (values.size() <= index) {
+               break TOP;
+            }
+            List<String> row = rows.get(index);
+            if (row == null) {
+               row = Lists.newArrayList();
+            }
+            row.add(values.get(index));
+            rows.set(index, row);
+         }
+      }
+      return rows;
+   }
+
+   @VisibleForTesting
+   protected File writeCsvFile(String file, List<String> header,
+         List<List<String>> rows, String delim) throws IOException {
+      File outputFile = new File(file);
+      PrintStream ps = null;
+      try {
+         ps = new PrintStream(new FileOutputStream(outputFile));
+         ps.println(Joiner.on(delim).join(header));
+         for (List<String> row : rows) {
+            ps.println(Joiner.on(delim).join(row));
+         }
+         return outputFile;
+      } catch (Exception e) {
+         throw new IOException("Failed to write CSV file '" + file + "' : "
+               + e.getMessage(), e);
+      } finally {
+         try {
+            ps.close();
+         } catch (Exception ignore) {
+         }
+      }
+   }
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/DynamicConfigFileWriter.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/DynamicConfigFileWriter.java
new file mode 100644
index 0000000..b174375
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/DynamicConfigFileWriter.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.writers;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * Abstract interface for generating PGE config input files defining the input
+ * necessary to run the underlying PGE.
+ * 
+ * @author bfoster (Brian Foster)
+ * @author mattmann (Chris Mattmann)
+ */
+public abstract class DynamicConfigFileWriter implements SciPgeConfigFileWriter {
+
+	private static final Logger logger = Logger
+			.getLogger(DynamicConfigFileWriter.class.getName());
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.apache.oodt.cas.pge.writers.SciPgeConfigFileWriter#createConfigFile
+	 * (java.lang.String, org.apache.oodt.cas.metadata.Metadata,
+	 * java.lang.Object[])
+	 */
+	@Override
+	public File createConfigFile(String sciPgeConfigFilePath,
+			Metadata inputMetadata, Object... customArgs) throws IOException {
+		try {
+			return this.generateFile(sciPgeConfigFilePath, inputMetadata,
+					logger, customArgs);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new IOException(e);
+		}
+	}
+
+	/**
+	 * Generates a config file for CAS-PGE to use as PGE input with the given
+	 * default logger.
+	 * 
+	 * @param filePath
+	 *            The name of the config file to generate.
+	 * @param metadata
+	 *            Input CAS-PGE metadata.
+	 * @param logger
+	 *            The logger to write any status information to.
+	 * @param args
+	 *            Any custom parameters needed for the writer to write the input
+	 *            config file.
+	 * @return The newly generated CAS-PGE input config file.
+	 * @throws Exception
+	 *             If any error occurs.
+	 */
+	public abstract File generateFile(String filePath, Metadata metadata,
+			Logger logger, Object... args) throws Exception;
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/ExternExtractorMetWriter.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/ExternExtractorMetWriter.java
new file mode 100644
index 0000000..4c9c61e
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/ExternExtractorMetWriter.java
@@ -0,0 +1,49 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.pge.writers;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.extractors.ExternConfigReader;
+import org.apache.oodt.cas.metadata.extractors.ExternMetExtractor;
+import org.apache.oodt.cas.pge.writers.PcsMetFileWriter;
+
+/**
+ * 
+ * Wraps the OODT CAS {@link ExternMetExtractor} and exposes it as a CAS-PGE
+ * {@link PcsMetFileWriter}.
+ * 
+ */
+public class ExternExtractorMetWriter extends PcsMetFileWriter {
+
+  @Override
+  protected Metadata getSciPgeSpecificMetadata(File sciPgeConfigFilePath,
+      Metadata inputMetadata, Object... customArgs) throws Exception {
+    ExternMetExtractor extractor = new ExternMetExtractor();
+    extractor.setConfigFile(new ExternConfigReader().parseConfigFile(new File(
+        (String) customArgs[0])));
+    Metadata m = new Metadata();
+    m.addMetadata(extractor.extractMetadata(sciPgeConfigFilePath)
+        .getHashtable(), true);
+    return m;
+  }
+
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/FilenameExtractorWriter.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/FilenameExtractorWriter.java
new file mode 100644
index 0000000..5cae64f
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/FilenameExtractorWriter.java
@@ -0,0 +1,55 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.pge.writers;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.extractors.FilenameTokenMetExtractor;
+import org.apache.oodt.cas.pge.writers.PcsMetFileWriter;
+
+/**
+ * 
+ * Wrap CAS-Metadata's {@link FilenameTokenMetExtractor} as a CAS-PGE
+ * {@link PcsMetFileWriter}. First arg passed in is the config file full path.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class FilenameExtractorWriter extends PcsMetFileWriter {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.pge.writers.PcsMetFileWriter#getSciPgeSpecificMetadata
+   * (java.io.File, org.apache.oodt.cas.metadata.Metadata, java.lang.Object[])
+   */
+  @Override
+  protected Metadata getSciPgeSpecificMetadata(File generatedFile,
+      Metadata workflowMet, Object... args) throws Exception {
+    String metConfFilePath = String.valueOf(args[0]);
+    FilenameTokenMetExtractor extractor = new FilenameTokenMetExtractor();
+    extractor.setConfigFile(metConfFilePath);
+    return extractor.extractMetadata(generatedFile);
+  }
+
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/MetadataKeyReplacerTemplateWriter.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/MetadataKeyReplacerTemplateWriter.java
new file mode 100644
index 0000000..775445a
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/MetadataKeyReplacerTemplateWriter.java
@@ -0,0 +1,80 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.pge.writers;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+import java.util.logging.Logger;
+
+//APACHE imports
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * Simple template based replacement writer, replaces $variables inside of a
+ * text file template with information computed by Apache OODT (e.g., from
+ * environment variables, from input workflow or file metadata, derived
+ * metadata, etc etc.)
+ * 
+ * Multi-valued metadata keys are expanded to joined strings delimited by the
+ * 2nd varargs argument to
+ * {@link #createConfigFile(String, Metadata, Object...)}. The 1st varargs
+ * argument to {@link #createConfigFile(String, Metadata, Object...)} is the
+ * template file to use as a basis.
+ * 
+ */
+public class MetadataKeyReplacerTemplateWriter extends
+    DynamicConfigFileWriter {
+
+  private static final String DEFAULT_SEPARATOR = ",";
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.pge.writers.DynamicConfigFileWriter#generateFile(java
+   * .lang.String, org.apache.oodt.cas.metadata.Metadata,
+   * java.util.logging.Logger, java.lang.Object[])
+   */
+  @Override
+  public File generateFile(String filePath, Metadata metadata, Logger logger,
+      Object... args) throws Exception {
+    String templateFile = (String) args[0];
+    String processedTemplate = FileUtils
+        .readFileToString(new File(templateFile));
+    String separator = args.length == 2 ? (String) args[1] : DEFAULT_SEPARATOR;
+
+    for (String key : metadata.getAllKeys()) {
+      String replaceVal = null;
+      if (metadata.isMultiValued(key)) {
+        List<String> values = metadata.getAllMetadata(key);
+        replaceVal = StringUtils.join(values, separator);
+      } else
+        replaceVal = metadata.getMetadata(key);
+      processedTemplate = processedTemplate.replaceAll("\\$" + key, replaceVal);
+    }
+
+    File configFile = new File(filePath);
+    FileUtils.writeStringToFile(configFile, processedTemplate);
+    return configFile;
+  }
+
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/PcsMetFileWriter.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/PcsMetFileWriter.java
new file mode 100644
index 0000000..60256e3
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/PcsMetFileWriter.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pge.writers;
+
+//OODT imports
+import org.apache.oodt.cas.pge.metadata.PgeMetadata;
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//OODT imports
+import java.io.File;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Writes a PCS metadata file for the give data file
+ * </p>.
+ */
+public abstract class PcsMetFileWriter {
+
+	public static final String FILE_SIZE = "FileSize";
+	
+    public Metadata getMetadataForFile(File sciPgeCreatedDataFile,
+            PgeMetadata pgeMetadata, Object... customArgs) throws Exception {
+        try {
+            Metadata inputMetadata = pgeMetadata.asMetadata();
+
+            inputMetadata.replaceMetadata(CoreMetKeys.FILENAME,
+                    sciPgeCreatedDataFile.getName());
+            inputMetadata.replaceMetadata(CoreMetKeys.FILE_LOCATION,
+                    sciPgeCreatedDataFile.getParentFile().getAbsolutePath());
+            inputMetadata.replaceMetadata(FILE_SIZE, Long.toString(new File(
+					inputMetadata.getMetadata(CoreMetKeys.FILE_LOCATION),
+					inputMetadata.getMetadata(CoreMetKeys.FILENAME)).length()));
+            
+            return this.getSciPgeSpecificMetadata(
+                    sciPgeCreatedDataFile, inputMetadata, customArgs);
+        } catch (Exception e) {
+            throw new Exception("Failed to create PCS metadata file for '"
+                    + sciPgeCreatedDataFile + "' : " + e.getMessage(), e);
+        }
+    }
+
+    protected abstract Metadata getSciPgeSpecificMetadata(
+            File sciPgeCreatedDataFile, Metadata inputMetadata,
+            Object... customArgs) throws Exception;
+
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/SciPgeConfigFileWriter.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/SciPgeConfigFileWriter.java
new file mode 100644
index 0000000..cbaf55e
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/SciPgeConfigFileWriter.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pge.writers;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Abstract interface for generating PGE config input files defining the input
+ * necessary to run the underlying PGE
+ * </p>.
+ */
+public interface SciPgeConfigFileWriter {
+
+    /**
+     * 
+     * @param sciPgeConfigFilePath
+     * @param inputMetadata
+     * @param customArgs
+     * @return
+     * @throws IOException
+     */
+    public File createConfigFile(String sciPgeConfigFilePath,
+            Metadata inputMetadata, Object... customArgs) throws IOException;
+
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/TextConfigFileWriter.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/TextConfigFileWriter.java
new file mode 100644
index 0000000..161b21b
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/TextConfigFileWriter.java
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.writers;
+
+//Google static imports
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+//OODT static imports
+import static org.apache.oodt.cas.pge.util.XmlHelper.fillIn;
+
+//JDK imports
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.logging.Logger;
+
+//Google imports
+import com.google.common.annotations.VisibleForTesting;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * Text {@link SciPgeConfigFileWriter} which takes a template with envReplace
+ * metadata that gets dynamically filled out and written to a file.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TextConfigFileWriter extends DynamicConfigFileWriter {
+
+   private static final int TEMPLATE_INDEX = 0;
+
+   @Override
+   public File generateFile(String filePath, Metadata metadata, Logger logger,
+         Object... customArgs) throws Exception {
+      checkArgument(customArgs.length > 0,
+            TextConfigFileWriter.class.getCanonicalName()
+                  + " has no args specified");
+      String template = checkNotNull((String) customArgs[TEMPLATE_INDEX],
+            "Must specify Text file template in args at index = '"
+                  + TEMPLATE_INDEX + "'");
+
+      try {
+         return writeTextFile(filePath, fillIn(template, metadata));
+      } catch (Exception e) {
+         throw new IOException(e);
+      }
+   }
+
+   @VisibleForTesting
+   protected File writeTextFile(String file, String text) throws IOException {
+      File outputFile = new File(file);
+      PrintStream ps = null;
+      try {
+         ps = new PrintStream(new FileOutputStream(outputFile));
+         ps.println(text);
+         return outputFile;
+      } catch (Exception e) {
+         throw new IOException("Failed to write text file '" + file + "' : "
+               + e.getMessage(), e);
+      } finally {
+         try {
+            ps.close();
+         } catch (Exception ignore) {
+         }
+      }
+   }
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/VelocityConfigFileWriter.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/VelocityConfigFileWriter.java
new file mode 100644
index 0000000..9aa4526
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/VelocityConfigFileWriter.java
@@ -0,0 +1,79 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.pge.writers;
+
+//JDK imports
+import java.io.File;
+import java.io.StringWriter;
+import java.util.logging.Logger;
+
+//APACHE imports
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+
+/**
+ * 
+ * A PGE input file writer based on Apache Velocity and Paul Ramirez's need to
+ * make my code better.
+ * 
+ * First var args parameter to
+ * {@link #createConfigFile(String, Metadata, Object...)} is the template
+ * directory full path. Second var args parameter to
+ * {@link #createConfigFile(String, Metadata, Object...)} is the template file
+ * name.
+ * 
+ */
+public class VelocityConfigFileWriter extends DynamicConfigFileWriter {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.pge.writers.DynamicConfigFileWriter#generateFile(java
+   * .lang.String, org.apache.oodt.cas.metadata.Metadata,
+   * java.util.logging.Logger, java.lang.Object[])
+   */
+  @Override
+  public File generateFile(String filePath, Metadata metadata, Logger logger,
+      Object... args) throws Exception {
+    File configFile = new File(filePath);
+    VelocityMetadata velocityMetadata = new VelocityMetadata(metadata);
+    // Velocity requires you to set a path of where to look for
+    // templates. This path defaults to . if not set.
+    int slashIndex = ((String) args[0]).lastIndexOf('/');
+    String templatePath = ((String) args[0]).substring(0, slashIndex);
+    Velocity.setProperty("file.resource.loader.path", templatePath);
+    // Initialize Velocity and set context up
+    Velocity.init();
+    VelocityContext context = new VelocityContext();
+    context.put("metadata", velocityMetadata);
+    context.put("env", System.getenv());
+    // Load template from templatePath
+    String templateName = ((String) args[0]).substring(slashIndex);
+    Template template = Velocity.getTemplate(templateName);
+    // Fill out template and write to file
+    StringWriter sw = new StringWriter();
+    template.merge(context, sw);
+    FileUtils.writeStringToFile(configFile, sw.toString());
+    return configFile;
+  }
+
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/VelocityMetadata.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/VelocityMetadata.java
new file mode 100644
index 0000000..0997316
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/VelocityMetadata.java
@@ -0,0 +1,49 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.pge.writers;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * Wrapper around CAS {@link Metadata} object to provide Velocity template
+ * semantics, e.g., a {@link #get(String)} method that allows for
+ * ${metadata.author} (the '.' is a call that Velocity then makes from the
+ * template to the {@link #get(String)} method in the class.
+ * 
+ * @author pramirez
+ * 
+ */
+public class VelocityMetadata extends Metadata {
+  private Metadata _metadata = null;
+
+  public VelocityMetadata(Metadata metadata) {
+    this._metadata = metadata;
+  }
+
+  public String get(String key) {
+    return _metadata.getMetadata(key);
+  }
+
+  public List<String> getValues(String key) {
+    return (List<String>) _metadata.getAllMetadata(key);
+  }
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/metlist/MetadataListPcsMetFileWriter.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/metlist/MetadataListPcsMetFileWriter.java
new file mode 100644
index 0000000..019e4cd
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/metlist/MetadataListPcsMetFileWriter.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pge.writers.metlist;
+
+//JDK imports
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Arrays;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.cas.pge.writers.PcsMetFileWriter;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A {@link PcsMetFileWriter} that generates PCS met files based on a MetList
+ * XML document
+ * </p>.
+ */
+public class MetadataListPcsMetFileWriter extends PcsMetFileWriter {
+
+    @Override
+    protected Metadata getSciPgeSpecificMetadata(File sciPgeCreatedDataFile,
+            Metadata inputMetadata, Object... customArgs) throws Exception {
+        Metadata metadata = new Metadata();
+        for (Object arg : customArgs) {
+            Element root = XMLUtils.getDocumentRoot(
+                    new FileInputStream(new File((String) arg)))
+                    .getDocumentElement();
+            NodeList metadataNodeList = root.getElementsByTagName(METADATA_TAG);
+            for (int i = 0; i < metadataNodeList.getLength(); i++) {
+                Element metadataElement = (Element) metadataNodeList.item(i);
+                String key = metadataElement.getAttribute(KEY_ATTR);
+                if (key.equals(""))
+                	key = PathUtils.doDynamicReplacement(metadataElement.getAttribute(KEY_GEN_ATTR), inputMetadata);
+                String val = metadataElement.getAttribute(VAL_ATTR);
+            	if (val.equals("")) 
+            		val = metadataElement.getTextContent();
+                if (val != null && !val.equals("")) {
+                    if (!metadataElement.getAttribute(ENV_REPLACE_ATTR).toLowerCase().equals("false"))
+                        val = PathUtils.doDynamicReplacement(val, inputMetadata);
+                    String[] vals = null;
+                    if (metadataElement.getAttribute(SPLIT_ATTR).toLowerCase().equals("false")) {
+                        vals = new String[] { val };
+                    } else {
+                        String delimiter = metadataElement.getAttribute("delimiter");
+                        if (delimiter == null || delimiter.equals(""))
+                            delimiter = ",";
+                        vals = (val + delimiter).split(delimiter);
+                    }
+                    metadata.replaceMetadata(key, Arrays.asList(vals));
+                    inputMetadata.replaceMetadata(key, Arrays.asList(vals));
+                } else if (inputMetadata.getMetadata(key) != null
+                        && !inputMetadata.getMetadata(key).equals("")) {
+                    metadata.replaceMetadata(key, inputMetadata
+                            .getAllMetadata(key));
+                }
+            }
+        }
+        return metadata;
+    }
+
+}
diff --git a/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/xslt/XslTransformWriter.java b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/xslt/XslTransformWriter.java
new file mode 100644
index 0000000..9c783cb
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/java/org/apache/oodt/cas/pge/writers/xslt/XslTransformWriter.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pge.writers.xslt;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+import javax.xml.transform.Result;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.dom.DOMSource;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.pge.writers.SciPgeConfigFileWriter;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * XSL Transformation class which writes Science PGE config files based from the
+ * XML format of SerializableMetadata
+ * </p>.
+ */
+public class XslTransformWriter implements SciPgeConfigFileWriter {
+
+    public File createConfigFile(String sciPgeConfigFilePath,
+            Metadata inputMetadata, Object... customArgs) throws IOException {
+        try {
+            File sciPgeConfigFile = new File(sciPgeConfigFilePath);
+
+            String xsltFilePath = (String) customArgs[0];
+            Source xsltSource = new StreamSource(new File(xsltFilePath));
+            Result result = new StreamResult(sciPgeConfigFile);
+
+            TransformerFactory transFact = TransformerFactory.newInstance();
+            Transformer trans = transFact.newTransformer(xsltSource);
+            boolean useCDATA = customArgs.length > 1 ? ((String) customArgs[1])
+                    .toLowerCase().equals("true") : false;
+            Source xmlSource = new DOMSource((new SerializableMetadata(
+                    inputMetadata,
+                    trans.getOutputProperty(OutputKeys.ENCODING), useCDATA))
+                    .toXML());
+
+            trans.setOutputProperty(OutputKeys.INDENT, "yes");
+            trans.transform(xmlSource, result);
+
+            return sciPgeConfigFile;
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new IOException("Failed to create science PGE config file '"
+                    + sciPgeConfigFilePath + "' : " + e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/pge/src/main/resources/CAS-PGE_learn_by_example.docx b/0.8.1-rc1/pge/src/main/resources/CAS-PGE_learn_by_example.docx
new file mode 100644
index 0000000..473098c
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/CAS-PGE_learn_by_example.docx
Binary files differ
diff --git a/0.8.1-rc1/pge/src/main/resources/REMOVE.log b/0.8.1-rc1/pge/src/main/resources/REMOVE.log
new file mode 100644
index 0000000..cb27d16
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/REMOVE.log
@@ -0,0 +1,18 @@
+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.
+
+
+You can remove this file. It was only included to ensure that the log directory for this
+distribution was created on assembly.
diff --git a/0.8.1-rc1/pge/src/main/resources/examples/Crawler/action-beans.properties b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/action-beans.properties
new file mode 100644
index 0000000..2f89fbf
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/action-beans.properties
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more contributor
+# license agreements.  See the NOTICE.txt 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.
+
+crawler.failure.dir=/path/to/failure/dir
+crawler.backup.dir=/path/to/backup/dir
+crawler.workflowmgr.url=http://localhost:9001
+crawler.filemgr.url=http://localhost:9000
+crawler.met.file.ext=met
diff --git a/0.8.1-rc1/pge/src/main/resources/examples/Crawler/action-beans.xml b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/action-beans.xml
new file mode 100644
index 0000000..ced0ce8
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/action-beans.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor" />
+	<bean class="org.apache.oodt.cas.crawl.util.CasPropertyPlaceholderConfigurer">
+
+		<!-- Allow for system-level properties to override all properties below -->
+		<property name="systemPropertiesMode" value="2" />
+
+    <property name="location" value="src/main/resources/examples/Crawler/action-beans.properties" /> 
+	</bean>
+
+	<!-- DELETE Actions -->
+	<bean id="DeleteDataFile" lazy-init="true" class="org.apache.oodt.cas.crawl.action.DeleteFile">
+		<property name="description" value="Deletes the current data file" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestSuccess</value>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="DeleteMetadataFile" lazy-init="true" class="org.apache.oodt.cas.crawl.action.DeleteFile">
+		<property name="description" value="Deletes the metadata file for the current data file" />
+		<property name="fileExtension" value="${crawler.met.file.ext}" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestSuccess</value>
+			</list>
+		</property>
+	</bean>
+
+	<!-- MOVE to FAILURE_DIR Actions -->
+	<bean id="MoveDataFileToFailureDir" lazy-init="true" class="org.apache.oodt.cas.crawl.action.MoveFile">
+		<property name="description" value="Moves the current data file to failure directory" />
+		<property name="toDir" value="${crawler.failure.dir}" />
+		<property name="createToDir" value="true" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestFailure</value>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="MoveMetadataFileToFailureDir" lazy-init="true" class="org.apache.oodt.cas.crawl.action.MoveFile">
+		<property name="description" value="Moves the metadata file for the current data file to failure directory" />
+		<property name="fileExtension" value="${crawler.met.file.ext}" />
+		<property name="toDir" value="${crawler.failure.dir}" />
+		<property name="createToDir" value="true" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestFailure</value>
+			</list>
+		</property>
+	</bean>
+
+	<!-- MOVE to BACKUP_DIR Actions -->
+	<bean id="MoveMetadataFileToBackupDir" lazy-init="true" class="org.apache.oodt.cas.crawl.action.MoveFile">
+		<property name="description" value="Moves the metadata file for the current data file to success directory" />
+		<property name="fileExtension" value="${crawler.met.file.ext}" />
+		<property name="toDir" value="${crawler.backup.dir}" />
+		<property name="createToDir" value="true" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestSuccess</value>
+			</list>
+		</property>
+	</bean>
+
+	<!-- Workflow Manager Actions -->
+	<bean id="TriggerPostIngestWorkflow" lazy-init="true" class="org.apache.oodt.cas.crawl.action.WorkflowMgrStatusUpdate">
+		<property name="description" value="Triggers workflow event with the name [ProductType]Ingest" />
+		<property name="ingestSuffix" value="Ingest" />
+		<property name="workflowMgrUrl" value="${crawler.workflowmgr.url}" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">postIngestSuccess</value>
+			</list>
+		</property>
+	</bean>
+
+	<!-- File Manager Actions -->
+	<bean id="Unique" lazy-init="true" class="org.apache.oodt.cas.crawl.action.FilemgrUniquenessChecker">
+		<property name="description" value="Checks the filemgr against the PRODUCT_NAME for the current data file to make sure it has not yet been ingested" />
+		<property name="filemgrUrl" value="${crawler.filemgr.url}" />
+		<property name="phases">
+			<list>
+				<value type="java.lang.String">preIngest</value>
+			</list>
+		</property>
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/pge/src/main/resources/examples/Crawler/crawler-config.xml b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/crawler-config.xml
new file mode 100755
index 0000000..2727386
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/crawler-config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean class="org.apache.oodt.cas.crawl.util.CasPropertyOverrideConfigurer" />
+
+	<import resource="action-beans.xml" />
+	<import resource="precondition-beans.xml" />
+  <import resource="naming-beans.xml" />
+
+</beans>
diff --git a/0.8.1-rc1/pge/src/main/resources/examples/Crawler/filename.extractor.config.xml b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/filename.extractor.config.xml
new file mode 100644
index 0000000..6513e9d
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/filename.extractor.config.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<input>
+
+   <group name="TokenNameListGroup">
+     <scalar name="Delimeter">_</scalar>
+     <vector name="TokenMetKeys">
+    
+     <!-- 
+     [sourcename]_[tablename]_[productiondatetime].[ext]
+     
+     ex file name: datasource_tablename_20101129122700.txt
+     -->
+       <element>SourceName</element>
+       <element>TableName</element>
+       <element>ProductionDateTime</element>
+     </vector>
+  
+   </group>
+
+
+    <group name="SubstringOffsetGroup">
+     <!--  the indices for the substring met key selection -->
+     <!--  the first element is the starting index in the string -->
+     <!--  NOTE: this assumes 1-indexed strings (and is internally converted to
+           0-indexed.
+      -->
+     <!--  the second element is the length -->
+     
+     <!--  MissionName_Date_StartOrbitNumber_StopOrbitNumber.txt -->
+     
+      <vector name="MissionName">
+        <element>1</element>
+        <element>11</element>      
+      </vector>
+      
+      <vector name="Date">
+        <element>13</element>
+        <element>4</element>
+      </vector>
+      
+      <vector name="StartOrbitNumber">
+        <element>18</element>
+        <element>16</element>
+      </vector>
+      
+      <vector name="StopOrbitNumber">
+        <element>35</element>
+        <element>15</element>
+      </vector>
+      
+   </group>
+   
+   <group name="ProductionDateTimeGroup">
+     <scalar name="DateTimeFormat">yyyyMMddHHmmss</scalar>
+   </group>   
+    
+    <group name="CommonMetadata">
+       <!--  can now use environment variable replacement in any of the values for 
+             scalars or vectors, just use CAS bracket style [ENV VAR NAME]
+         
+             Also can use vector to indicate multiple values for a particular met field.
+        -->
+        <scalar name="DataVersion">1.0</scalar>
+        <scalar name="CollectionName">Products extracted by the OODT Filename Met Extractor</scalar>
+        <scalar name="DataProvider">OODT</scalar>
+    </group>
+</input>
diff --git a/0.8.1-rc1/pge/src/main/resources/examples/Crawler/mime-extractor-map.xml b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/mime-extractor-map.xml
new file mode 100644
index 0000000..e445f46
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/mime-extractor-map.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<cas:mimetypemap xmlns:cas="http://oodt.jpl.nassa.gov/1.0/cas" magic="false"
+    mimeRepo="mime-types.xml">
+
+  <!-- This will be the default extractor used if product doesn't match any
+    of the mime-types defined in mime-types.xml file (this element is optional) -->
+  <default>
+    <!-- you can put a default NamingConvention here too.
+    <namingConvention id="PDFNamingConv" />
+    -->
+    <!-- You can add multiple extractors here if there are more than one,
+      however extractor is optional, so below extractor can be removed -->
+    <extractor class="org.apache.oodt.cas.metadata.extractors.MetReaderExtractor" />
+  </default>
+
+  <mime type="all/products">
+    <extractor class="org.apache.oodt.cas.metadata.extractors.MetReaderExtractor" />
+  </mime>
+
+  <!-- Example type where PGE generates a metadata file for the product, but
+    the product also needs additional metadata extraction from it... in the
+    mime-types.xml file txt/product has super type all/products, which means
+    that for any product that is a txt/product then all/products extractors
+    will be first be run on it (which, in this case, is just one extractor
+    which reads in the existing metadata file) followed by txt/product
+    extractors which is a filename based extractor. -->
+  <mime type="txt/product">
+    <extractor class="org.apache.oodt.cas.metadata.extractors.FilenameTokenMetExtractor">
+      <config file="filename.extractor.config.xml" />
+    </extractor>
+  </mime>
+
+  <!-- This is an example of a type where only one extractor is run on
+    product, this is because pdf/product only specifies one extractor and
+    in mime-types.xml file pdf/product has no super type. -->
+  <mime type="pdf/product">
+    <namingConvention id="PDFNamingConv" />
+    <extractor class="org.apache.oodt.cas.metadata.extractors.FilenameTokenMetExtractor">
+      <config file="filename.extractor.config.xml" />
+    </extractor>
+  </mime>
+
+  <!-- This is an example of a type where two extractors get run... this case
+    is an alternative way of handling txt/product... txt/product will run
+    the same 2 extractors which this type will run but for different reasons...
+    doc/product doesn't have any super type, it instead defines both extractors
+    directly to itself. -->
+  <mime type="doc/product">
+    <extractor class="org.apache.oodt.cas.metadata.extractors.MetReaderExtractor" />
+    <extractor class="org.apache.oodt.cas.metadata.extractors.FilenameTokenMetExtractor">
+      <config file="filename.extractor.config.xml" />
+    </extractor>
+  </mime>
+</cas:mimetypemap>
diff --git a/0.8.1-rc1/pge/src/main/resources/examples/Crawler/mime-types.xml b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/mime-types.xml
new file mode 100644
index 0000000..c6c0d50
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/mime-types.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<mime-info>
+	
+	<mime-type type="all/prouducts" />
+
+  <mime-type type="txt/product">
+    <sub-class-of type="all/prouducts" />
+    <glob pattern=".*\.txt" isregex="true" />
+  </mime-type>
+
+  <mime-type type="pdf/product">
+    <glob pattern=".*\.pdf" isregex="true" />
+  </mime-type>
+
+  <mime-type type="doc/product">
+    <glob pattern=".*\.doc" isregex="true" />
+  </mime-type>
+</mime-info>
diff --git a/0.8.1-rc1/pge/src/main/resources/examples/Crawler/naming-beans.xml b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/naming-beans.xml
new file mode 100644
index 0000000..3cd14ad
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/naming-beans.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean id="PDFNamingConv" class="org.apache.oodt.cas.metadata.filenaming.PathUtilsNamingConvention">
+    <property name="namingConv" value="[ProductType].[NominalDate].pdf" />
+  </bean>
+</beans>
diff --git a/0.8.1-rc1/pge/src/main/resources/examples/Crawler/precondition-beans.xml b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/precondition-beans.xml
new file mode 100644
index 0000000..68d7083
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/examples/Crawler/precondition-beans.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor" />
+
+	<!-- Precondition Comparators -->
+	<bean id="CheckThatDataFileSizeIsGreaterThanZero" lazy-init="true" class="org.apache.oodt.cas.metadata.preconditions.FileSizeComparator">
+		<property name="description" value="Check if the current data file size is greater than zero" />
+		<property name="compareItem">
+			<value type="java.lang.Long">0</value>
+		</property>
+		<property name="type" value="greater_than" />
+	</bean>
+
+	<bean id="AprioriUniquessCheckWithFilemgr" lazy-init="true" class="org.apache.oodt.cas.crawl.comparator.FilemgrUniquenessCheckComparator">
+		<property name="description" value="Checks where the current data file existing in the filemgr based on its FILENAME" />
+		<property name="compareItem">
+			<value type="java.lang.Boolean">false</value>
+		</property>
+		<property name="type" value="equal_to" />
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/pge/src/main/resources/examples/PgeConfigFiles/pge-config.xml b/0.8.1-rc1/pge/src/main/resources/examples/PgeConfigFiles/pge-config.xml
new file mode 100755
index 0000000..eef1a8d
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/examples/PgeConfigFiles/pge-config.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+
+TODO(bfoster): Make this a working example.
+-->
+<pgeConfig>
+    
+    <import namespace="optional-NS" file="absolute-or-relative-to-this-file-another-pgeConfig-import-file-path"/>
+    
+    <!-- input file for science PGE that need to be created  -->
+    <dynInputFiles>
+        
+        <!-- one or more of these -->
+        <file path="path-with-name-to-create" writerClass="class-path-to-SciPgeConfigFileWriter" args="zero-or-more-args-comma-segregated"/>
+        
+    </dynInputFiles>
+    
+    <!-- how to run science PGE -->
+    <exe dir="set-working-dir-for-script" shellType="script-type">
+        
+        <!-- one or more of these -->
+        <cmd>line-in-script-file</cmd>
+        
+    </exe>
+    
+    <!-- files to ingest -->
+    <output>
+
+        <!-- one or more of these -->
+        <!-- if a dir path is specified WITHOUT specifying an associated 
+             set of files tags, along with the regExp and metFileWriterClass
+             and args required to produce metadata CAS-PGE will REQUIRE that 
+             you provide (as part of the tasks.xml definition for this task:
+             
+             PGETask/Ingest/MimeExtractorRepo - Path to AutoDetectProductCrawler's 
+                                                MimeExtractorRepo XML config
+                                                
+             And an AutoDetectProductCrawler will be created in lieu of the 
+             StdProductCrawler. In addition you will not see the extracted
+             metadata produced as .met files in the job working directory for
+             these CAS-PGE jobs as the extracted metadata won't be serialized.
+         -->
+        <dir path="path-to-an-output-dir" createBeforeExe="true-or-false" />
+        
+        <dir path="path-to-an-output-dir" createBeforeExe="true-or-false">
+          <!-- back compatability re-introduced in OODT-667
+            by specifying one or more files you cause CAS-PGE to generate a StdProductCrawler,
+            to crawl generated metadata files derived from calling the metFileWriterClass implementation
+            on files matching Java RegEx or file name (exact match) in path-to-an-output-dir. Met files are serialized and stored in the job
+            directory where the CAS-PGE job ran, and are then ingested into the file manager along
+            with the origin data file.
+            
+           -->
+          <files regExp="java-regex" 
+                 name="file-name"
+                 metFileWriterClass="org.apache.oodt.cas.pge.writers.PcsMetFileWriter.subclass" 
+                 args="zero-or-more-args-comma-segregated">
+                 
+             <!-- 
+               A convention for renaming the files as they are processed on output.
+               By default uses the PathUtilsNamingConvention.
+              -->
+             <renamingConv namingExpr="/[SomePathUtils]/[Metadata]" envReplace="true">
+               <metadata key="some-key" val="some-val"/>
+               <metadata key="some-other-key" val="zero-or-more-vals-comma-segregated"/>                 
+             </renamingConv>      
+          </files>
+        </dir>
+
+    </output>
+    
+    <!-- metadata keys you want to set -->
+    <customMetadata>
+        
+        <!-- one or more of these -->
+        <metadata key="name-of-metadata-field" val="metadata-value"/>
+        
+    </customMetadata>
+    
+</pgeConfig>
diff --git a/0.8.1-rc1/pge/src/main/resources/examples/WorkflowMgrInput/pcs-pge-dyn-metadata.met b/0.8.1-rc1/pge/src/main/resources/examples/WorkflowMgrInput/pcs-pge-dyn-metadata.met
new file mode 100644
index 0000000..8ac10f9
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/examples/WorkflowMgrInput/pcs-pge-dyn-metadata.met
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<cas:metadata xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<!--  this dyn metadata should come from the workflow/process manager -->
+ <keyval>
+   <key>TaskId</key>
+   <val>1</val>
+ </keyval>
+ <keyval>
+   <key>JobId</key>
+   <val>1929</val>
+ </keyval>
+ <keyval>
+   <key>ProcessingNode</key>
+   <val>compute-0-13</val>
+ </keyval>
+ 
+ <!--  this dynamic metadata is the actual input to the task -->
+ <keyval>
+   <key>SiteName</key>
+   <val>parkfalls</val>
+ </keyval>
+ <keyval>
+   <key>InstrumentId</key>
+   <val>ifs1</val>
+ </keyval>
+ <keyval>
+   <key>LocalDay</key>
+   <val>050506</val>
+ </keyval>
+ <keyval>
+   <key>ProductType</key>
+   <val>IASI_CalSub</val>
+ </keyval>
+  
+</cas:metadata>
\ No newline at end of file
diff --git a/0.8.1-rc1/pge/src/main/resources/examples/WorkflowMgrInput/pcs-pge-task-workflow.properties b/0.8.1-rc1/pge/src/main/resources/examples/WorkflowMgrInput/pcs-pge-task-workflow.properties
new file mode 100755
index 0000000..0e9bd94
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/examples/WorkflowMgrInput/pcs-pge-task-workflow.properties
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+foobar=foo
diff --git a/0.8.1-rc1/pge/src/main/resources/examples/WorkflowTask/tasks.xml b/0.8.1-rc1/pge/src/main/resources/examples/WorkflowTask/tasks.xml
new file mode 100644
index 0000000..b0eab1f
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/examples/WorkflowTask/tasks.xml
@@ -0,0 +1,23 @@
+<!-- A sample CAS workflow task configuration with the basic set of 
+     CAS-PGE properties. You can find a full list of the properties
+     here:
+
+     http://svn.apache.org/repos/asf/oodt/trunk/pge/src/main/java/org/apache/oodt/cas/pge/metadata/PgeTaskMetKeys.java
+--> 
+<cas:workflowtasks xmlns:cas="http://oodt.apache.org/1.0/cas">
+<task id="urn:oodt:casPgeTask" name="CAS PGE" class="org.apache.oodt.cas.pge.StdPGETaskInstance">
+      <conditions/>
+      <configuration>
+         <property name="PGETask_Name" value="CAS PGE"/>
+         <property name="PGETask_ConfigFilePath" value="[PGE_ROOT]/policy/pge-config.xml" envReplace="true"/>
+         <property name="PGETask_DumpMetadata" value="true"/>
+         <property name="PCS_WorkflowManagerUrl" value="[WORKFLOW_URL]" envReplace="true" />
+         <property name="PCS_FileManagerUrl" value="[FILEMGR_URL]" envReplace="true"/>
+         <property name="PCS_MetFileExtension" value="met"/>
+         <property name="PCS_ClientTransferServiceFactory" value="org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory"/>
+         <property name="PCS_ActionRepoFile" value="file:[CRAWLER_HOME]/policy/crawler-config.xml" envReplace="true"/>
+      </configuration>
+      <requiredMetFields>
+      </requiredMetFields>
+</task>
+</cas:workflowtasks>
\ No newline at end of file
diff --git a/0.8.1-rc1/pge/src/main/resources/examples/XsltFiles/xslt_prop_eq_val.xml b/0.8.1-rc1/pge/src/main/resources/examples/XsltFiles/xslt_prop_eq_val.xml
new file mode 100644
index 0000000..0d3fc3c
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/examples/XsltFiles/xslt_prop_eq_val.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+
+    <xsl:output method="text"/>    
+
+    <xsl:variable name="delimiter"><xsl:text>,</xsl:text></xsl:variable>
+    <xsl:variable name="equalTo"><xsl:text>=</xsl:text></xsl:variable>    
+    <xsl:variable name="newline"><xsl:text>&#x0A;</xsl:text></xsl:variable>
+        
+    <xsl:template match="/">
+        <xsl:apply-templates/>
+    </xsl:template>
+
+    <xsl:template match="metadata/keyval">
+        <xsl:value-of select="key"/>
+        <xsl:value-of select="$equalTo"/>
+        <xsl:for-each select="val">
+            <xsl:value-of select="."/>
+            <xsl:if test="not(position() = last())">
+                <xsl:value-of select="$delimiter"/>
+            </xsl:if>
+        </xsl:for-each>
+        <xsl:value-of select="$newline"/>
+    </xsl:template>
+            
+</xsl:stylesheet>
diff --git a/0.8.1-rc1/pge/src/main/resources/fileconcatenator-pge.tar b/0.8.1-rc1/pge/src/main/resources/fileconcatenator-pge.tar
new file mode 100644
index 0000000..de384e5
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/fileconcatenator-pge.tar
@@ -0,0 +1,237 @@
+fileconcatenator-pge/000755 036164 000024 00000000000 11617101420 015601 5ustar00rvermastaff000000 000000 fileconcatenator-pge/.classpath000644 036164 000024 00000001273 11617055321 017577 0ustar00rvermastaff000000 000000 <?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
+fileconcatenator-pge/.project000644 036164 000024 00000001047 11617055320 017261 0ustar00rvermastaff000000 000000 <?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>fileconcatenator-pge</name>
+	<comment></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.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
+fileconcatenator-pge/.settings/000755 036164 000024 00000000000 11617101425 017524 5ustar00rvermastaff000000 000000 fileconcatenator-pge/pom.xml000644 036164 000024 00000001662 11617101305 017125 0ustar00rvermastaff000000 000000 <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.apache.oodt.pge</groupId>
+  <artifactId>fileconcatenator-pge</artifactId>
+  <version>1.0</version>
+  <name>FileConcatenatorPGE</name>
+  <description>Example file-concatenator project for learning about CAS-PGE</description>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.5</source>
+          <target>1.5</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+  	<dependency>
+  		<groupId>org.apache.oodt</groupId>
+  		<artifactId>cas-pge</artifactId>
+  		<version>0.3</version>
+  		<scope>compile</scope>
+  	</dependency>
+  </dependencies>
+</project>
+fileconcatenator-pge/src/000755 036164 000024 00000000000 11617054756 016413 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/000755 036164 000024 00000000000 11617054756 017337 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/test/000755 036164 000024 00000000000 11617054756 017372 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/test/java/000755 036164 000024 00000000000 11617054756 020313 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/test/resources/000755 036164 000024 00000000000 11617054756 021404 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/java/000755 036164 000024 00000000000 11617054756 020260 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/resources/000755 036164 000024 00000000000 11617054756 021351 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/resources/config/000755 036164 000024 00000000000 11617054756 022616 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/resources/extractors/000755 036164 000024 00000000000 11617054756 023547 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/resources/files/000755 036164 000024 00000000000 11617054756 022453 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/resources/files/concatenatingInputFile1.txt000644 036164 000024 00000001633 11617054756 027735 0ustar00rvermastaff000000 000000 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce quis nunc
+quam, vel laoreet libero. Pellentesque sit amet mauris ligula. Etiam sed
+metus vel elit feugiat accumsan at ac nisi. Cras a turpis scelerisque
+augue semper mollis. Proin rutrum sollicitudin est at scelerisque.
+Aenean ligula eros, luctus consequat gravida et, gravida in ligula. Nunc
+venenatis tellus in urna placerat accumsan. Ut vehicula adipiscing
+faucibus. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+Phasellus id diam sed nulla venenatis laoreet at nec elit. Suspendisse
+et mauris nec tortor vehicula aliquet. Cras ornare dignissim vestibulum.
+Vestibulum aliquet magna nec diam gravida gravida. Duis semper, erat in
+ultrices convallis, lorem enim laoreet magna, eget sagittis ligula nunc
+eu quam. Nunc ac tempus orci. Pellentesque semper eleifend suscipit. Nam
+est nisi, scelerisque sodales bibendum eget, porttitor fringilla metus. fileconcatenator-pge/src/main/resources/files/concatenatingInputFile2.txt000644 036164 000024 00000001453 11617054756 027736 0ustar00rvermastaff000000 000000 
+
+Aenean vel nulla ut nulla tempus venenatis in eget est. Curabitur
+tincidunt mattis dolor rutrum gravida. Nunc vel dui eu diam luctus
+dictum non vitae leo. Morbi et velit neque. Phasellus placerat augue eu
+nisi convallis adipiscing. Donec sagittis tristique tellus, ut aliquet
+quam pellentesque ut. Ut tortor nibh, ultrices in bibendum vitae, mollis
+a justo. Nulla fermentum, urna sed bibendum tempor, ipsum leo tincidunt
+tellus, ac lacinia purus justo ut nibh. Pellentesque gravida, metus
+lobortis convallis egestas, erat dui ullamcorper leo, vitae aliquet
+justo nunc ac justo. Vivamus dapibus, quam in eleifend aliquet, erat
+nulla molestie lectus, ut gravida nunc augue vitae nulla. Nam vulputate
+arcu ut ante pharetra a dictum nunc tincidunt. Nunc tortor quam,
+convallis vel lacinia ac, dignissim sed sem. 
+fileconcatenator-pge/src/main/resources/extractors/concatenatingfilename.extractor.config.xml000644 036164 000024 00000001037 11617077706 034066 0ustar00rvermastaff000000 000000 <?xml version="1.0" encoding="UTF-8"?>
+  <input>
+    <group name="SubstringOffsetGroup">
+      <vector name="ConcatenatingInputFileName">
+        <element>1</element>
+        <element>33</element>      
+      </vector>
+   </group>
+    
+    <group name="CommonMetadata">
+        <scalar name="DataVersion">1.0</scalar>
+        <scalar name="CollectionName">File Concatenator product</scalar>
+        <scalar name="DataProvider">OODT-PGE</scalar>
+        <scalar name="ProductType">FileConcatenatorProductType</scalar>
+    </group>
+    
+</input>fileconcatenator-pge/src/main/resources/extractors/metlistwriter/000755 036164 000024 00000000000 11617054756 026465 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/resources/extractors/metlistwriter/metout.xml000644 036164 000024 00000000235 11617054756 030524 0ustar00rvermastaff000000 000000 <?xml version="1.0" encoding="UTF-8"?>
+<metadataList>
+    
+    <!-- one or more of these -->
+    <metadata key="JobId" value="[JobId]"/>
+    
+</metadataList>fileconcatenator-pge/src/main/resources/config/PGEConfig.xml000644 036164 000024 00000004375 11617077701 025105 0ustar00rvermastaff000000 000000 <?xml version="1.0" encoding="UTF-8"?>
+<pgeConfig>
+
+        <!-- How to run the PGE -->
+        <exe dir="[JobDir]" shell="/bin/bash">
+          <!-- cd to PGE root -->
+          <cmd>cd [PGE_ROOT]/file_concatenator</cmd>
+              	<cmd>cp [InputFile1] [OutputFile]</cmd>
+              	<cmd>cat [InputFile2] >> [OutputFile]</cmd>
+        </exe>
+
+	    <!-- Files to ingest -->
+	    <output>
+        	<!-- one or more of these -->
+       	 	<dir path="[JobDir]" createBeforeExe="false">
+            
+            	<!-- one or more of these ** regExp or name can be used-->
+            	<files regExp=".*\.txt" metFileWriterClass="org.apache.oodt.pge.examples.fileconcatenator.writers.ConcactenatingFilenameExtractorWriter"  args="[PGE_ROOT]/file_concatenator/extractors/concatenatingfilename.extractor.config.xml"/>
+                <files regExp=".*\.txt" metFileWriterClass="org.apache.oodt.cas.pge.writers.metlist.MetadataListPcsMetFileWriter" args="[PGE_ROOT]/file_concatenator/extractors/metlistwriter/metout.xml"/>
+            </dir>
+        </output>
+
+        <!-- Custom metadata to add to output files -->
+        <customMetadata>
+                <!-- helpful keys -->
+                <metadata key="LessThan" val="&#x3C;"/>
+                <metadata key="LessThanOrEqualTo" val="[LessThan]="/>
+                <metadata key="GreaterThan" val="&#x3E;"/>
+                <metadata key="GreaterThanOrEqualTo" val="[GreaterThan]="/>
+                <metadata key="Exclamation" val="&#33;"/>
+                <metadata key="Ampersand" val="&#38;"/>
+                <metadata key="NotEqualTo" val="[Ampersand]="/>
+                <metadata key="LogicalAnd" val="[Ampersand][Ampersand]"/>
+                <metadata key="CshPipeToStdOutAndError" val="[GreaterThan][Ampersand][Exclamation]"/>
+
+				<metadata key="ProductionDateTime" val="[DATE.UTC]"/>
+				<metadata key="JobDir" val="[PGE_ROOT]/file_concatenator/output/jobs/job-[ProductionDateTime]"/>
+				<metadata key="InputFile1" val="[PGE_ROOT]/file_concatenator/files/concatenatingInputFile1.txt"/>
+				<metadata key="InputFile2" val="[PGE_ROOT]/file_concatenator/files/concatenatingInputFile2.txt"/>
+				<metadata key="OutputFile" val="[JobDir]/concatenatedOutputFile-[ProductionDateTime].txt"/>        
+      </customMetadata>
+
+</pgeConfig>
+fileconcatenator-pge/src/main/java/org/000755 036164 000024 00000000000 11617054756 021047 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/java/org/apache/000755 036164 000024 00000000000 11617054756 022270 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/java/org/apache/oodt/000755 036164 000024 00000000000 11617054756 023235 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/java/org/apache/oodt/pge/000755 036164 000024 00000000000 11617054756 024010 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/java/org/apache/oodt/pge/examples/000755 036164 000024 00000000000 11617054756 025626 5ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/java/org/apache/oodt/pge/examples/fileconcatenator/000755 036164 000024 00000000000 11617054756 031146 5ustar00rvermastaff000000 000000 src/main/java/org/apache/oodt/pge/examples/fileconcatenator/FileConcatenatorPGETask.java000644 036164 000024 00000002420 11617054756 036327 0ustar00rvermastaff000000 000000 fileconcatenator-pgepackage org.apache.oodt.pge.examples.fileconcatenator;
+
+import org.apache.oodt.cas.pge.PGETaskInstance;
+import org.apache.oodt.cas.pge.metadata.PgeTaskMetadataKeys;
+
+public class FileConcatenatorPGETask extends PGETaskInstance {
+	  
+	/* PGE task statuses */
+	  public static final String STAGING_INPUT = "STAGING INPUT";
+	  
+	  public static final String CONF_FILE_BUILD = "BUILDING CONFIG FILE";
+	  
+	  public static final String RUNNING_PGE = "PGE EXEC";
+	  
+	  public static final String CRAWLING = "CRAWLING";
+
+	  /* (non-Javadoc)
+	   * @see org.apache.oodt.cas.pge.PGETaskInstance#updateStatus(java.lang.String)
+	   */
+	  @Override
+	  protected void updateStatus(String status) {
+	     String proteoStatus = this.convertStatus(status);
+	     super.updateStatus(proteoStatus);
+	  }
+
+	  private String convertStatus(String casPgeStatus) {
+	    if (casPgeStatus.equals(PgeTaskMetadataKeys.CONF_FILE_BUILD)) {
+	        return CONF_FILE_BUILD;
+	    } else if (casPgeStatus.equals(PgeTaskMetadataKeys.STAGING_INPUT)) {
+	        return STAGING_INPUT;
+	    } else if (casPgeStatus.equals(PgeTaskMetadataKeys.CRAWLING)) {
+	        return CRAWLING;
+	    } else if (casPgeStatus.equals(PgeTaskMetadataKeys.RUNNING_PGE)) {
+	        return RUNNING_PGE;
+	    } else
+	        return casPgeStatus;
+	}
+	  
+}
+fileconcatenator-pge/src/main/java/org/apache/oodt/pge/examples/fileconcatenator/writers/000755 036164 000024 00000000000 11617054756 032645 5ustar00rvermastaff000000 000000 org/apache/oodt/pge/examples/fileconcatenator/writers/ConcactenatingFilenameExtractorWriter.java000600 036164 000024 00000002125 11617077213 043064 0ustar00rvermastaff000000 000000 fileconcatenator-pge/src/main/javapackage org.apache.oodt.pge.examples.fileconcatenator.writers;
+
+import java.io.File;
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.extractors.FilenameTokenMetExtractor;
+import org.apache.oodt.cas.pge.writers.PcsMetFileWriter;
+
+public class ConcactenatingFilenameExtractorWriter extends PcsMetFileWriter {
+
+	private static final Logger LOG = Logger.getLogger(ConcactenatingFilenameExtractorWriter.class
+		      .getName());	
+	
+	@Override
+	protected Metadata getSciPgeSpecificMetadata(File sciPgeCreatedDataFile,
+			Metadata inputMetadata, Object... customArgs) throws Exception {
+
+		Metadata met = new Metadata();
+		met.addMetadata(inputMetadata);
+		met.addMetadata("ProductType", "GenericFile");
+		
+	    String metConfFilePath = String.valueOf(customArgs[0]);
+	    LOG.info("metConfFilePath = ["+metConfFilePath+"]");
+	    FilenameTokenMetExtractor extractor = new FilenameTokenMetExtractor();
+	    extractor.setConfigFile(metConfFilePath);
+	    met.addMetadata(extractor.extractMetadata(sciPgeCreatedDataFile));
+	    
+		return met;
+	}
+
+}
+fileconcatenator-pge/.settings/org.eclipse.jdt.core.prefs000644 036164 000024 00000000414 11617055320 024507 0ustar00rvermastaff000000 000000 #Fri Aug 05 14:04:16 PDT 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
+fileconcatenator-pge/.settings/org.maven.ide.eclipse.prefs000644 036164 000024 00000000406 11617055300 024644 0ustar00rvermastaff000000 000000 #Fri Aug 05 14:04:00 PDT 2011
+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/0.8.1-rc1/pge/src/main/resources/logging.properties b/0.8.1-rc1/pge/src/main/resources/logging.properties
new file mode 100644
index 0000000..3d0b6e9
--- /dev/null
+++ b/0.8.1-rc1/pge/src/main/resources/logging.properties
@@ -0,0 +1,65 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.FileHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = ../logs/cas_pge%g.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 5
+java.util.logging.FileHandler.append = true
+java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging level for the subsystems
+
+# catalog subsystem
+org.apache.oodt.cas.filemgr.catalog.level = INFO
+
+# repository subsystem
+org.apache.oodt.cas.filemgr.repository.level = FINE
+
+# system subsystem
+org.apache.oodt.cas.filemgr.system.level = INFO
+
+# versioning subsystem
+org.apache.oodt.cas.filemgr.versioning.level = INFO
+
+# data transfer subsystem
+org.apache.oodt.cas.filemgr.datatransfer.level = FINE
+
+# util
+org.apache.oodt.cas.filemgr.util.level = INFO
+
+# validation
+org.apache.oodt.cas.filemgr.validation.level = INFO
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = INFO
+httpclient.wire.header.level = INFO
+httpclient.wire.level = INFO
+
diff --git a/0.8.1-rc1/pge/src/site/resources/images/cas-pge.jpg b/0.8.1-rc1/pge/src/site/resources/images/cas-pge.jpg
new file mode 100644
index 0000000..36f77c5
--- /dev/null
+++ b/0.8.1-rc1/pge/src/site/resources/images/cas-pge.jpg
Binary files differ
diff --git a/0.8.1-rc1/pge/src/site/resources/images/cas-pge.psd b/0.8.1-rc1/pge/src/site/resources/images/cas-pge.psd
new file mode 100644
index 0000000..b2a583e
--- /dev/null
+++ b/0.8.1-rc1/pge/src/site/resources/images/cas-pge.psd
Binary files differ
diff --git a/0.8.1-rc1/pge/src/site/resources/images/pge_instance_plugin_points.png b/0.8.1-rc1/pge/src/site/resources/images/pge_instance_plugin_points.png
new file mode 100644
index 0000000..fa3d3e7
--- /dev/null
+++ b/0.8.1-rc1/pge/src/site/resources/images/pge_instance_plugin_points.png
Binary files differ
diff --git a/0.8.1-rc1/pge/src/site/site.xml b/0.8.1-rc1/pge/src/site/site.xml
new file mode 100755
index 0000000..07338b5
--- /dev/null
+++ b/0.8.1-rc1/pge/src/site/site.xml
@@ -0,0 +1,30 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<project name="cas-pge">
+
+  <body>
+    <links>
+      <item name="OODT" href="../oodt-site/"/>
+    </links>
+
+    <menu ref="reports" inherit="bottom"/>
+    <menu name="Software Documentation">
+      <item name="Developer Guide" href="development/developer.html"/>
+    </menu>
+  </body>
+</project>
diff --git a/0.8.1-rc1/pge/src/site/xdoc/development/developer.xml b/0.8.1-rc1/pge/src/site/xdoc/development/developer.xml
new file mode 100644
index 0000000..28bd6c7
--- /dev/null
+++ b/0.8.1-rc1/pge/src/site/xdoc/development/developer.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS PGE Basic Developer Guide</title>
+      <author email="holenoter@me.com">Brian Foster</author>
+      <author email="rverma@jpl.nasa.gov">Rishi Verma</author>
+   </properties>
+
+   <body>
+   
+      <section name="Introduction">
+        <p>
+          This is the developer guide for the Apache OODT Catalog and Archive Service (CAS) 
+          Program Generation Executable (PGE) component, or CAS-PGE for short. This guide 
+          explains the CAS-PGE architecture as well as its tailorable extension 
+          points. 
+         
+        <p>The remainder of this guide is separated into the following sections:</p>
+       <ul>
+        <li><a href="#section1">Project Description</a></li>
+        <li><a href="#section2">Architecture</a></li>
+        <li><a href="#section3">Extension Points</a></li>
+      </ul>
+        </p>
+      </section>
+    
+      <a name="section1"/>
+      <section name="Project Description">
+        <p>In order to fully understand the CAS-PGE component, it is helpful to have a solid grasp
+        of the CAS Workflow component. If you need some background on CAS Workflow, please
+        see our <a href="../../workflow/development/developer.html">CAS Workflow Developer Guide</a>.
+        With CAS Workflow in mind, it is often the case that CAS Workflow is used as part of a data 
+        processing system - where 
+        workflows are responsible for controlling the run order of different Product Generation 
+        Executables (PGEs). In circumstances like this, CAS-PGE can help wrap a PGE as part of a
+        CAS Workflow. One can think of a PGE as a piece of code, which given a set of inputs, 
+        generates output files. Thus, CAS-PGE is designed to help accomplish the most common actions 
+        required to run PGEs: ie. finding their input files, executing the PGE, and saving their output files. 
+        CAS-PGE performs some of these actions by interacting with a second CAS component as well: 
+        CAS File Manager.  The CAS File Manager can be part of this type of workflow-based data processing 
+        system, which manages data files, and can support metadata-filtering queries across those
+        files to allow for fast retrieval. In other words, CAS File Manger complements CAS-PGE by 
+        supporting file cataloging for files involved in PGE operations. </p>
+        <p>In summary, CAS-PGE's role is to provide tools for 
+        encapsulating PGEs; however, it also seeks to leverage and make the use of other CAS 
+        components to support the aforementioned goal.</p> 
+      </section>    
+      
+      <a name="section2"/>
+      <section name="Architecture">
+      <p>[TBD]</p>
+      </section>
+      
+      <a name="section3"/>
+      <section name="Extension Points">
+	  <p>PGEs usually need a method by which information is given to them on how
+		to run, what to run with (i.e. input files), and where to place the
+		output files as well as what to name them. CAS-PGE accomplishes this, and other tasks,
+		by making use of customizable extension points.
+	 </p>
+	 <p>The following is a description of the most common extension points</p>
+	 <ul>
+	   <li><b>SciPgeConfigFileWriter</b> - writes configuration files for describing how a 
+	   PGE will run, with which input files it will run with, and where the output will be placed</li>
+	   <li><b>PcsMetFileWriter</b> - controls which metadata should be sent to the CAS File 
+	   Manager (with each output file) for ingestion</li>
+	   <li><b>PGETaskInstance</b> - an extensible module which performs the most generic 
+	   and common actions required by typical PGEs. This module makes getting started with a
+	   default PGE configuration simple.</li>
+	   <li><b>PgeConfigBuilder</b> - builds a PgeConfig object, which has the ability to
+	   control how a CAS-PGE will run</li>
+	   </ul>
+	   
+	   <p>The relationship between these extension-points and other CAS-PGE components 
+	   is described in the below figure. </p>
+	   
+	   <p><img src="../images/pge_instance_plugin_points.png" 
+        alt="Extension Points"/></p>    
+	   
+	   <subsection name="Runtime Execution">
+	   <p>
+	   In terms of runtime execution, CAS-PGE makes use of two mediums to configure how a 
+	   PGE will run: metadata and a 
+	   PgeConfig object. Using these two pieces of information, CAS-PGE can configure how 
+	   many configuration files it should generate, which SciPgeConfigFileWriter(s) to use to create 
+	   these configuration files, which output files need which PcsMetFileWriter to generate their
+		metadata for CAS File Manager ingestion, how to run the PGE, which CAS File
+		Manager to talk to, etc.  For the first medium (metadata), there is a set of reserved metadata
+		fields that CAS-PGE expects, which affects the way CAS-PGE runs (i.e. which CAS
+		File Manager to ingest to).  For the second medium (PgeConfig), the PgeConfigBuilder builds up a 
+		PgeConfig object, which can also control how CAS-PGE runs. 
+      </p>
+      </subsection>
+      </section>
+      
+    
+   </body>
+</document>
\ No newline at end of file
diff --git a/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/MockConfigFilePropertyAdder.java b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/MockConfigFilePropertyAdder.java
new file mode 100644
index 0000000..a6f083b
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/MockConfigFilePropertyAdder.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge;
+
+//OODT imports
+import org.apache.oodt.cas.pge.metadata.PgeMetadata;
+
+/**
+ * Mock implementation of {@link ConfigFilePropertyAdder}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class MockConfigFilePropertyAdder implements ConfigFilePropertyAdder {
+
+   public static final String RUN_COUNTER = "MockConfigFilePropertyAdder/RunCounter";
+
+   public void addConfigProperties(PgeMetadata metadata, Object... objs) {
+      String key = (String) objs[0];
+      String value = (String) objs[1];
+      metadata.replaceMetadata(key, value);
+      String runCounter = metadata.getMetadata(RUN_COUNTER);
+      if (runCounter == null) {
+         metadata.replaceMetadata(RUN_COUNTER, "1");
+      } else {
+         metadata.replaceMetadata(RUN_COUNTER, Integer.toString(Integer.parseInt(runCounter) + 1));
+      }
+   }
+}
diff --git a/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/TestPGETaskInstance.java b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/TestPGETaskInstance.java
new file mode 100644
index 0000000..501428b
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/TestPGETaskInstance.java
@@ -0,0 +1,593 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge;
+
+//OODT static imports
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.ACTION_IDS;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.ATTEMPT_INGEST_ALL;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.CONFIG_FILE_PATH;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.CRAWLER_CONFIG_FILE;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.CRAWLER_CRAWL_FOR_DIRS;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.CRAWLER_RECUR;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.DUMP_METADATA;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.INGEST_CLIENT_TRANSFER_SERVICE_FACTORY;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.INGEST_FILE_MANAGER_URL;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.MIME_EXTRACTOR_REPO;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.NAME;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.PGE_CONFIG_BUILDER;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.PROPERTY_ADDERS;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.REQUIRED_METADATA;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.WORKFLOW_MANAGER_URL;
+import static org.apache.oodt.cas.pge.metadata.PgeTaskStatus.CRAWLING;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+//JDK imports
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.UUID;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+//Apache imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.crawl.AutoDetectProductCrawler;
+import org.apache.oodt.cas.crawl.ProductCrawler;
+import org.apache.oodt.cas.crawl.action.CrawlerAction;
+import org.apache.oodt.cas.crawl.action.MoveFile;
+import org.apache.oodt.cas.crawl.status.IngestStatus;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.pge.config.DynamicConfigFile;
+import org.apache.oodt.cas.pge.config.MockPgeConfigBuilder;
+import org.apache.oodt.cas.pge.config.OutputDir;
+import org.apache.oodt.cas.pge.config.PgeConfig;
+import org.apache.oodt.cas.pge.metadata.PgeMetadata;
+import org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys;
+import org.apache.oodt.cas.pge.metadata.PgeTaskStatus;
+import org.apache.oodt.cas.pge.writers.MockDynamicConfigFileWriter;
+import org.apache.oodt.cas.workflow.metadata.CoreMetKeys;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+
+//Google imports
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+/**
+ * Test class for {@link PGETaskInstance}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestPGETaskInstance extends TestCase {
+
+   private final List<File> tmpDirs = Lists.newArrayList();
+
+   @Override
+   public void tearDown() throws Exception {
+      for (File tmpDir : tmpDirs) {
+         FileUtils.forceDelete(tmpDir);
+      }
+      tmpDirs.clear();
+   }
+
+   public void testLoadPropertyAdders() throws Exception {
+      PGETaskInstance pgeTask = createTestInstance();
+      ConfigFilePropertyAdder propAdder = pgeTask
+            .loadPropertyAdder(MockConfigFilePropertyAdder.class
+                  .getCanonicalName());
+      assertNotNull(propAdder);
+      assertTrue(propAdder instanceof MockConfigFilePropertyAdder);
+   }
+
+   public void testRunPropertyAdders() throws Exception {
+      PGETaskInstance pgeTask = createTestInstance();
+      pgeTask.pgeMetadata.replaceMetadata(PROPERTY_ADDERS,
+            MockConfigFilePropertyAdder.class.getCanonicalName());
+      pgeTask.pgeConfig.setPropertyAdderCustomArgs(new Object[] { "key",
+            "value" });
+      pgeTask.runPropertyAdders();
+      assertEquals("value", pgeTask.pgeMetadata.getMetadata("key"));
+
+      pgeTask.pgeMetadata.replaceMetadata(
+            MockConfigFilePropertyAdder.RUN_COUNTER, "0");
+      pgeTask.pgeMetadata.replaceMetadata(PROPERTY_ADDERS, Lists.newArrayList(
+            MockConfigFilePropertyAdder.class.getCanonicalName(),
+            MockConfigFilePropertyAdder.class.getCanonicalName()));
+      pgeTask.runPropertyAdders();
+      assertEquals("value", pgeTask.pgeMetadata.getMetadata("key"));
+      assertEquals("2",
+            pgeTask.pgeMetadata
+                  .getMetadata(MockConfigFilePropertyAdder.RUN_COUNTER));
+
+      pgeTask.pgeMetadata.replaceMetadata(
+            MockConfigFilePropertyAdder.RUN_COUNTER, "0");
+      System.setProperty(PgeTaskMetKeys.USE_LEGACY_PROPERTY, "true");
+      pgeTask.pgeMetadata.replaceMetadata(PROPERTY_ADDERS.getName(),
+            MockConfigFilePropertyAdder.class.getCanonicalName());
+      pgeTask.runPropertyAdders();
+      assertEquals("value", pgeTask.pgeMetadata.getMetadata("key"));
+      assertEquals("1",
+            pgeTask.pgeMetadata
+                  .getMetadata(MockConfigFilePropertyAdder.RUN_COUNTER));
+      System.getProperties().remove(PgeTaskMetKeys.USE_LEGACY_PROPERTY);
+   }
+
+   public void testCreatePgeMetadata() throws Exception {
+      final String PGE_NAME = "PGE_Test";
+      final String PGE_REQUIRED_METADATA = "Filename, FileLocation ";
+      final String PROP_ADDERS = "some.prop.adder.classpath,some.other.classpath";
+      PGETaskInstance pgeTask = createTestInstance();
+      Metadata dynMet = new Metadata();
+      WorkflowTaskConfiguration config = new WorkflowTaskConfiguration();
+      config.addConfigProperty(NAME.getName(), PGE_NAME);
+      config.addConfigProperty(REQUIRED_METADATA.getName(),
+            PGE_REQUIRED_METADATA);
+      config.addConfigProperty(PROPERTY_ADDERS.getName(), PROP_ADDERS);
+
+      PgeMetadata pgeMet = pgeTask.createPgeMetadata(dynMet, config);
+      assertEquals(1, pgeMet.getAllMetadata(NAME).size());
+      assertEquals(PGE_NAME, pgeMet.getAllMetadata(NAME).get(0));
+      assertEquals(2, pgeMet.getAllMetadata(REQUIRED_METADATA).size());
+      assertTrue(pgeMet.getAllMetadata(REQUIRED_METADATA).contains("Filename"));
+      assertTrue(pgeMet.getAllMetadata(REQUIRED_METADATA).contains(
+            "FileLocation"));
+      assertEquals(2, pgeMet.getAllMetadata(PROPERTY_ADDERS).size());
+      assertTrue(pgeMet.getAllMetadata(PROPERTY_ADDERS).contains(
+            "some.prop.adder.classpath"));
+      assertTrue(pgeMet.getAllMetadata(PROPERTY_ADDERS).contains(
+            "some.other.classpath"));
+
+      // Verify still works when only one property adder is specified.
+      pgeTask = createTestInstance();
+      config = new WorkflowTaskConfiguration();
+      config.addConfigProperty(PgeTaskMetKeys.PROPERTY_ADDERS.getName(),
+            "one.prop.adder.only");
+
+      pgeMet = pgeTask.createPgeMetadata(dynMet, config);
+      assertEquals(1, pgeMet.getAllMetadata(PROPERTY_ADDERS).size());
+      assertEquals("one.prop.adder.only", pgeMet
+            .getAllMetadata(PROPERTY_ADDERS).get(0));
+   }
+
+   @SuppressWarnings("unchecked") // FileUtils.readLines cast to List<String>
+   public void testLogger() throws Exception {
+      PGETaskInstance pgeTask1 = createTestInstance();
+      PGETaskInstance pgeTask2 = createTestInstance();
+
+      pgeTask1.logger.log(Level.INFO, "pge1 message1");
+      pgeTask1.logger.log(Level.INFO, "pge1 message2");
+      pgeTask2.logger.log(Level.SEVERE, "pge2 message1");
+      pgeTask1.logger.log(Level.INFO, "pge1 message3");
+
+      for (Handler handler : pgeTask1.logger.getHandlers()) {
+         handler.flush();
+      }
+      for (Handler handler : pgeTask2.logger.getHandlers()) {
+         handler.flush();
+      }
+      File logDir = new File(pgeTask1.pgeConfig.getExeDir() + "/logs");
+      assertTrue(logDir.exists());
+      List<String> messages = FileUtils.readLines(logDir.listFiles(
+         new FileFilter() {
+            @Override
+            public boolean accept(File pathname) {
+               return pathname.getName().endsWith(".log");
+            }
+         })[0], "UTF-8");
+      assertEquals(Level.INFO.getLocalizedName() + ": pge1 message1", messages.get(1));
+      assertEquals(Level.INFO.getLocalizedName() + ": pge1 message2", messages.get(3));
+      assertEquals(Level.INFO.getLocalizedName() + ": pge1 message3", messages.get(5));
+      logDir = new File(pgeTask2.pgeConfig.getExeDir() + "/logs");
+      assertTrue(logDir.exists());
+      messages = FileUtils.readLines(logDir.listFiles(
+         new FileFilter() {
+            @Override
+            public boolean accept(File pathname) {
+               return pathname.getName().endsWith(".log");
+            }
+         })[0], "UTF-8");
+      assertEquals(Level.SEVERE.getLocalizedName() + ": pge2 message1", messages.get(1));
+   }
+
+   public void testUpdateStatus() throws Exception {
+      final Map<String, String> args = Maps.newHashMap();
+      PGETaskInstance pgeTask = createTestInstance();
+      pgeTask.wm = new XmlRpcWorkflowManagerClient(null) {
+         @Override
+         public boolean updateWorkflowInstanceStatus(String instanceId,
+               String status) {
+            args.put("InstanceId", instanceId);
+            args.put("Status", status);
+            return true;
+         }
+      };
+      String instanceId = "Test ID";
+      String status = PgeTaskStatus.CRAWLING.getWorkflowStatusName();
+      pgeTask.workflowInstId = instanceId;
+      pgeTask.updateStatus(status);
+      assertEquals(instanceId, args.get("InstanceId"));
+      assertEquals(status, args.get("Status"));
+   }
+
+   public void testCreatePgeConfig() throws Exception {
+      final String KEY = "TestKey";
+      final String VALUE = "TestValue";
+      File pgeConfigFile = new File(createTmpDir(), "pgeConfig.xml");
+      FileUtils.writeLines(pgeConfigFile, "UTF-8",
+            Lists.newArrayList(
+               "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
+               "<pgeConfig>",
+               "   <customMetadata>",
+               "      <metadata key=\"" + KEY + "\" val=\"" + VALUE
+               		+ "\"/>",
+               "   </customMetadata>",
+               "</pgeConfig>"));
+      PGETaskInstance pgeTask = createTestInstance();
+      pgeTask.pgeMetadata.replaceMetadata(CONFIG_FILE_PATH,
+            pgeConfigFile.getAbsolutePath());
+      PgeConfig pgeConfig = pgeTask.createPgeConfig();
+      assertNotNull(pgeConfig);
+      assertEquals(VALUE, pgeTask.pgeMetadata.getMetadata(KEY));
+
+      pgeTask = createTestInstance();
+      pgeTask.pgeMetadata.replaceMetadata(PGE_CONFIG_BUILDER,
+            MockPgeConfigBuilder.class.getCanonicalName());
+      pgeConfig = pgeTask.createPgeConfig();
+      assertEquals(MockPgeConfigBuilder.MOCK_EXE_DIR, pgeConfig.getExeDir());
+   }
+
+   public void testCreateWorkflowManagerClient() throws Exception {
+      PGETaskInstance pgeTask = createTestInstance();
+      pgeTask.pgeMetadata.replaceMetadata(WORKFLOW_MANAGER_URL,
+            "http://localhost:8888");
+      XmlRpcWorkflowManagerClient wmClient =
+         pgeTask.createWorkflowManagerClient();
+      assertNotNull(wmClient);
+   }
+
+   public void testGetWorkflowInstanceId() throws Exception {
+      String workflowInstId = "12345";
+      PGETaskInstance pgeTask = createTestInstance();
+      pgeTask.pgeMetadata.replaceMetadata(CoreMetKeys.WORKFLOW_INST_ID,
+            workflowInstId);
+      assertEquals(workflowInstId, pgeTask.getWorkflowInstanceId());
+   }
+
+   public void testCreateExeDir() throws Exception {
+      PGETaskInstance pgeTask = createTestInstance();
+      File exeDir = new File(pgeTask.pgeConfig.getExeDir());
+      FileUtils.deleteDirectory(exeDir);
+      assertFalse(exeDir.exists());
+      pgeTask.createExeDir();
+      assertTrue(exeDir.exists());
+   }
+
+   public void testCreateOuputDirsIfRequested() throws Exception {
+      PGETaskInstance pgeTask = createTestInstance();
+      File outputDir1 = createTmpDir();
+      FileUtils.forceDelete(outputDir1);
+      File outputDir2 = createTmpDir();
+      FileUtils.forceDelete(outputDir2);
+      File outputDir3 = new File("/some/file/path");
+      assertFalse(outputDir1.exists());
+      assertFalse(outputDir2.exists());
+      assertFalse(outputDir3.exists());
+      pgeTask.pgeConfig.addOuputDirAndExpressions(new OutputDir(outputDir1
+            .getAbsolutePath(), true));
+      pgeTask.pgeConfig.addOuputDirAndExpressions(new OutputDir(outputDir2
+            .getAbsolutePath(), true));
+      pgeTask.pgeConfig.addOuputDirAndExpressions(new OutputDir(outputDir3
+            .getAbsolutePath(), false));
+      pgeTask.createOuputDirsIfRequested();
+      assertTrue(outputDir1.exists());
+      assertTrue(outputDir2.exists());
+      assertFalse(outputDir3.exists());
+   }
+
+   public void testCreateDynamicConfigFile() throws Exception {
+      File tmpDir = createTmpDir();
+      FileUtils.forceDelete(tmpDir);
+      assertFalse(tmpDir.exists());
+      PGETaskInstance pgeTask = createTestInstance();
+      File dynamicConfigFile = new File(tmpDir, "DynamicConfig.xml");
+      assertFalse(dynamicConfigFile.exists());
+      pgeTask.createDynamicConfigFile(new DynamicConfigFile(dynamicConfigFile.getAbsolutePath(),
+            MockDynamicConfigFileWriter.class.getCanonicalName(),
+            new Object[] {}));
+      assertTrue(dynamicConfigFile.exists());
+   }
+
+   public void testDumpMetadataIfRequested() throws Exception {
+      PGETaskInstance pgeTask = createTestInstance();
+      File dumpMetFile = new File(pgeTask.getDumpMetadataPath());
+      pgeTask.dumpMetadataIfRequested();
+      assertFalse(dumpMetFile.exists());
+      pgeTask.pgeMetadata.replaceMetadata(DUMP_METADATA, "true");
+      pgeTask.dumpMetadataIfRequested();
+      assertTrue(dumpMetFile.exists());
+      @SuppressWarnings("unchecked")
+      List<String> dumpedMet = FileUtils.readLines(dumpMetFile, "UTF-8");
+      assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
+            dumpedMet.get(0));
+      assertEquals(
+            "<cas:metadata xmlns:cas=\"http://oodt.jpl.nasa.gov/1.0/cas\">",
+            dumpedMet.get(1));
+      assertEquals("   <keyval type=\"vector\">", dumpedMet.get(2));
+      assertEquals("      <key>PGETask%2FName</key>", dumpedMet.get(3));
+      assertEquals("      <val>" + pgeTask.pgeMetadata.getMetadata(NAME)
+            + "</val>", dumpedMet.get(4));
+      assertEquals("   </keyval>", dumpedMet.get(5));
+      assertEquals("   <keyval type=\"vector\">", dumpedMet.get(6));
+      assertEquals("      <key>PGETask%2FDumpMetadata</key>", dumpedMet.get(7));
+      assertEquals(
+            "      <val>" + pgeTask.pgeMetadata.getMetadata(DUMP_METADATA)
+                  + "</val>", dumpedMet.get(8));
+      assertEquals("   </keyval>", dumpedMet.get(9));
+      assertEquals("</cas:metadata>", dumpedMet.get(10));
+   }
+
+   public void testCreateProductCrawler() throws Exception {
+      PGETaskInstance pgeTask = createTestInstance();
+      pgeTask.pgeMetadata.replaceMetadata(MIME_EXTRACTOR_REPO,
+            "src/main/resources/examples/Crawler/mime-extractor-map.xml");
+      pgeTask.pgeMetadata.replaceMetadata(
+            INGEST_CLIENT_TRANSFER_SERVICE_FACTORY,
+            "org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory");
+      pgeTask.pgeMetadata.replaceMetadata(INGEST_FILE_MANAGER_URL,
+            "http://localhost:9000");
+      pgeTask.pgeMetadata.replaceMetadata(CRAWLER_CONFIG_FILE,
+            "src/main/resources/examples/Crawler/crawler-config.xml");
+      pgeTask.pgeMetadata.replaceMetadata(ACTION_IDS,
+            Lists.newArrayList("DeleteDataFile", "MoveMetadataFileToFailureDir"));
+      pgeTask.pgeMetadata.replaceMetadata(REQUIRED_METADATA,
+            Lists.newArrayList("Owners"));
+      pgeTask.pgeMetadata.replaceMetadata(CRAWLER_CRAWL_FOR_DIRS,
+            Boolean.toString(false));
+      pgeTask.pgeMetadata.replaceMetadata(CRAWLER_RECUR,
+            Boolean.toString(true));
+
+      ProductCrawler pc = pgeTask.createProductCrawler();
+      assertEquals(
+            "org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory",
+            pc.getClientTransferer());
+      assertEquals("http://localhost:9000", pc.getFilemgrUrl());
+      assertEquals(
+            Sets.newHashSet("DeleteDataFile", "MoveMetadataFileToFailureDir"),
+            Sets.newHashSet(pc.getActionIds()));
+      CrawlerAction action = (CrawlerAction) pc.getApplicationContext().getBean("DeleteDataFile");
+      assertNotNull(action);
+      MoveFile moveFileAction = (MoveFile) pc.getApplicationContext().getBean("MoveMetadataFileToFailureDir");
+      Properties properties = new Properties();
+      properties.load(new FileInputStream(new File(
+            "src/main/resources/examples/Crawler/action-beans.properties")));
+      assertEquals(properties.get("crawler.failure.dir"),
+            moveFileAction.getToDir());
+      assertTrue(pc.getRequiredMetadata().contains("Owners"));
+      assertFalse(pc.isCrawlForDirs());
+      assertFalse(pc.isNoRecur());
+   }
+
+   public void testRunIngestCrawler() throws Exception {
+      // Case: UpdateStatus Success, VerifyIngest Success,
+      PGETaskInstance pgeTask = createTestInstance();
+      pgeTask.pgeConfig.addOuputDirAndExpressions(new OutputDir("/tmp/dir1", true));
+      pgeTask.pgeConfig.addOuputDirAndExpressions(new OutputDir("/tmp/dir2", true));
+      pgeTask.pgeMetadata.replaceMetadata(ATTEMPT_INGEST_ALL, Boolean.toString(true));
+      pgeTask.workflowInstId = "WorkflowInstanceId";
+
+      pgeTask.wm = createMock(XmlRpcWorkflowManagerClient.class);
+      expect(pgeTask.wm.updateWorkflowInstanceStatus(pgeTask.workflowInstId,
+            CRAWLING.getWorkflowStatusName())).andReturn(true);
+      replay(pgeTask.wm);
+
+      AutoDetectProductCrawler pc = createMock(AutoDetectProductCrawler.class);
+      pc.crawl(new File("/tmp/dir1"));
+      pc.crawl(new File("/tmp/dir2"));
+      expect(pc.getIngestStatus()).andReturn(Collections.<IngestStatus>emptyList());
+      replay(pc);
+
+      pgeTask.runIngestCrawler(pc);
+
+      verify(pgeTask.wm);
+      verify(pc);
+
+      // Case: UpdateStatus Fail
+      pgeTask.wm = createMock(XmlRpcWorkflowManagerClient.class);
+      expect(pgeTask.wm.updateWorkflowInstanceStatus(pgeTask.workflowInstId,
+            CRAWLING.getWorkflowStatusName())).andReturn(false);
+      replay(pgeTask.wm);
+
+      pc = createMock(AutoDetectProductCrawler.class);
+      replay(pc);
+
+      try {
+         pgeTask.runIngestCrawler(pc);
+         fail("Should have thrown");
+      } catch (Exception e) { /* expect throw */ }
+
+      verify(pgeTask.wm);
+      verify(pc);
+
+      // Case: UpdateStatus Success, VerifyIngest Fail
+      pgeTask.wm = createMock(XmlRpcWorkflowManagerClient.class);
+      expect(pgeTask.wm.updateWorkflowInstanceStatus(pgeTask.workflowInstId,
+            CRAWLING.getWorkflowStatusName())).andReturn(true);
+      replay(pgeTask.wm);
+
+      pc = createMock(AutoDetectProductCrawler.class);
+      pc.crawl(new File("/tmp/dir1"));
+      pc.crawl(new File("/tmp/dir2"));
+      IngestStatus failedIngestStatus = new IngestStatus() {
+         @Override
+         public String getMessage() {
+            return "Ingest Failure";
+         }
+         @Override
+         public File getProduct() {
+            return new File("/tmp/dir1");
+         }
+         @Override
+         public Result getResult() {
+            return Result.FAILURE;
+         }
+      };
+      expect(pc.getIngestStatus()).andReturn(
+            Lists.newArrayList(failedIngestStatus));
+      replay(pc);
+
+      try {
+         pgeTask.runIngestCrawler(pc);
+         fail("Should have thrown");
+      } catch (Exception e) { /* expect throw */ }
+
+      verify(pgeTask.wm);
+      verify(pc);
+   }
+
+   public void testVerifyIngests() throws Exception {
+      PGETaskInstance pgeTask = createTestInstance();
+
+      // Test case failure.
+      AutoDetectProductCrawler pc = createMock(AutoDetectProductCrawler.class);
+      IngestStatus failedIngestStatus = new IngestStatus() {
+         @Override
+         public String getMessage() {
+            return "Ingest Failure";
+         }
+         @Override
+         public File getProduct() {
+            return new File("/tmp/dir1");
+         }
+         @Override
+         public Result getResult() {
+            return Result.FAILURE;
+         }
+      };
+      expect(pc.getIngestStatus()).andReturn(
+            Lists.newArrayList(failedIngestStatus));
+      replay(pc);
+
+      try {
+         pgeTask.verifyIngests(pc);
+         fail("Should have thrown");
+      } catch (Exception e) { /* expect throw */ }
+
+      verify(pc);
+
+      // Test case warn failure of precondition, but success overall.
+      pc = createMock(AutoDetectProductCrawler.class);
+      IngestStatus precondsFailIngestStatus = new IngestStatus() {
+         @Override
+         public String getMessage() {
+            return "Preconditions failed";
+         }
+         @Override
+         public File getProduct() {
+            return new File("/tmp/dir1");
+         }
+         @Override
+         public Result getResult() {
+            return Result.PRECONDS_FAILED;
+         }
+      };
+      expect(pc.getIngestStatus()).andReturn(
+            Lists.newArrayList(precondsFailIngestStatus));
+      replay(pc);
+
+      pgeTask.logger = createMock(Logger.class);
+      pgeTask.logger.info("Verifying ingests successful...");
+      pgeTask.logger.warning(
+            "Product was not ingested [file='/tmp/dir1',result='PRECONDS_FAILED',msg='Preconditions failed']");
+      pgeTask.logger.info("Ingests were successful");
+      replay(pgeTask.logger);
+
+      pgeTask.verifyIngests(pc);
+
+      verify(pc);
+      verify(pgeTask.logger);
+
+      // Test case success.
+      pc = createMock(AutoDetectProductCrawler.class);
+      IngestStatus successIngestStatus = new IngestStatus() {
+         @Override
+         public String getMessage() {
+            return "Ingest Success";
+         }
+         @Override
+         public File getProduct() {
+            return new File("/tmp/dir1");
+         }
+         @Override
+         public Result getResult() {
+            return Result.SUCCESS;
+         }
+      };
+      expect(pc.getIngestStatus()).andReturn(
+            Lists.newArrayList(successIngestStatus));
+      replay(pc);
+
+      pgeTask.logger = createMock(Logger.class);
+      pgeTask.logger.info("Verifying ingests successful...");
+      pgeTask.logger.info("Ingests were successful");
+      replay(pgeTask.logger);
+
+      pgeTask.verifyIngests(pc);
+
+      verify(pc);
+      verify(pgeTask.logger);
+   }
+
+   private PGETaskInstance createTestInstance() throws Exception {
+      return createTestInstance(UUID.randomUUID().toString());
+   }
+
+   private PGETaskInstance createTestInstance(String workflowInstId)
+         throws Exception {
+      PGETaskInstance pgeTask = new PGETaskInstance();
+      pgeTask.workflowInstId = workflowInstId;
+      pgeTask.pgeMetadata = new PgeMetadata();
+      pgeTask.pgeMetadata.replaceMetadata(NAME, "TestPGE");
+      pgeTask.pgeConfig = new PgeConfig();
+      File exeDir = new File(createTmpDir(), workflowInstId);
+      pgeTask.pgeConfig.setExeDir(exeDir.getAbsolutePath());
+      pgeTask.logger = pgeTask.createLogger();
+      return pgeTask;
+   }
+
+   private File createTmpDir() throws Exception {
+      File tmpFile = File.createTempFile("bogus", "bogus");
+      File tmpDir = new File(tmpFile.getParentFile(), UUID.randomUUID().toString());
+      tmpFile.delete();
+      tmpDir.mkdirs();
+      tmpDirs.add(tmpDir);
+      return tmpDir;
+   }
+}
diff --git a/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/config/MockPgeConfigBuilder.java b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/config/MockPgeConfigBuilder.java
new file mode 100644
index 0000000..fc66db2
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/config/MockPgeConfigBuilder.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.config;
+
+//OODT imports
+import org.apache.oodt.cas.pge.metadata.PgeMetadata;
+
+/**
+ * Mock implementation of {@link PgeConfigBuilder}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class MockPgeConfigBuilder implements PgeConfigBuilder {
+
+   public static final String MOCK_EXE_DIR = "/mock/exe/dir";
+
+   public PgeConfig build(PgeMetadata pgeMetadata) throws Exception {
+      PgeConfig pgeConfig = new PgeConfig();
+      pgeConfig.setExeDir(MOCK_EXE_DIR);
+      return pgeConfig;
+   }
+}
diff --git a/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/config/TestXmlFilePgeConfigBuilder.java b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/config/TestXmlFilePgeConfigBuilder.java
new file mode 100644
index 0000000..58cd1f8
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/config/TestXmlFilePgeConfigBuilder.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.config;
+
+//OODT static imports
+import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.CONFIG_FILE_PATH;
+
+//JDK imports
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//OODT imports
+import org.apache.oodt.cas.pge.metadata.PgeMetadata;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link XmlFilePgeConfigBuilder}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestXmlFilePgeConfigBuilder extends TestCase {
+
+   public static final String CONFIG_FILE = "src/test/resources/pge-config.xml";
+
+   public void testBuild() throws IOException {
+      XmlFilePgeConfigBuilder builder = new XmlFilePgeConfigBuilder();
+      PgeMetadata pgeMetadata = new PgeMetadata();
+      pgeMetadata.replaceMetadata(CONFIG_FILE_PATH, CONFIG_FILE);
+      pgeMetadata.replaceMetadata("INPUT_FILE_1", "src/test/resources/data-file-1.txt");
+      pgeMetadata.replaceMetadata("INPUT_FILE_2", "src/test/resources/data-file-2.txt");
+      pgeMetadata.replaceMetadata("WORKING_DIR", "/tmp");
+      pgeMetadata.markAsDynamicMetadataKey();
+      pgeMetadata.commitMarkedDynamicMetadataKeys();
+      PgeConfig pgeConfig = builder.build(pgeMetadata);
+
+      // Verify metadata checks out.
+      assertEquals(40, pgeMetadata.asMetadata().getAllKeys().size());
+      assertEquals(CONFIG_FILE, pgeMetadata.getMetadata(CONFIG_FILE_PATH));
+      assertEquals("src/test/resources/data-file-1.txt", pgeMetadata.getMetadata("INPUT_FILE_1"));
+      assertEquals("src/test/resources/data-file-2.txt", pgeMetadata.getMetadata("INPUT_FILE_2"));
+      assertEquals("/tmp", pgeMetadata.getMetadata("WORKING_DIR"));
+      assertEquals(">", pgeMetadata.getMetadata("commons/GreaterThan"));
+      assertEquals("<", pgeMetadata.getMetadata("commons/LessThan"));
+      assertEquals("&", pgeMetadata.getMetadata("commons/Ampersand"));
+      assertEquals("'", pgeMetadata.getMetadata("commons/Apostrophe"));
+      assertEquals("\"", pgeMetadata.getMetadata("commons/QuotationMark"));
+      assertEquals("org.apache.oodt.cas.pge.writers.TextConfigFileWriter", pgeMetadata.getMetadata("writers/TextWriter"));
+      assertEquals("org.apache.oodt.cas.pge.writers.CsvConfigFileWriter", pgeMetadata.getMetadata("writers/CsvWriter"));
+      assertEquals("Simple", pgeMetadata.getMetadata("GREETING_ENUM"));
+      assertEquals("true", pgeMetadata.getMetadata("FORCE_STAGING"));
+      assertEquals("Custom", pgeMetadata.getMetadata("CUSTOM_GREETING_ENUM"));
+      assertEquals("<Custom Greeting Here>", pgeMetadata.getMetadata("CUSTOM_GREETING_ENUM_VALUE"));
+      assertEquals("/tmp", pgeMetadata.getMetadata("WorkingDir"));
+      assertEquals("Simple", pgeMetadata.getMetadata("GreetingEnum"));
+      assertEquals("Custom", pgeMetadata.getMetadata("CustomGreetingEnum"));
+      assertEquals("<Custom Greeting Here>", pgeMetadata.getMetadata("CustomGreetingEnumValue"));
+      assertEquals("src/test/resources/data-file-1.txt", pgeMetadata.getMetadata("InputFile1"));
+      assertEquals("src/test/resources/data-file-2.txt", pgeMetadata.getMetadata("InputFile2"));
+      assertEquals("true", pgeMetadata.getMetadata("ForceStaging"));
+      assertEquals(Lists.newArrayList("/tmp/staging/data-file-1.txt", "/tmp/staging/data-file-2.txt"), pgeMetadata.getAllMetadata("InputFiles"));
+      assertEquals("/tmp/config", pgeMetadata.getMetadata("ConfigDir"));
+      assertEquals("/tmp/output", pgeMetadata.getMetadata("OutputDir"));
+      assertEquals("/tmp/staging", pgeMetadata.getMetadata("StagingDir"));
+      assertEquals("dyn-input.txt", pgeMetadata.getMetadata("DynInput/Text/Name"));
+      assertEquals("dyn-input.csv", pgeMetadata.getMetadata("DynInput/CSV/Name"));
+      assertEquals("/tmp/config/dyn-input.txt", pgeMetadata.getMetadata("TextInputFile"));
+      assertEquals("/tmp/config/dyn-input.csv", pgeMetadata.getMetadata("CsvInputFile"));
+      assertEquals("PgeOutput.txt", pgeMetadata.getMetadata("OutputFileName"));
+      assertEquals("\n      [Greeting],\n      This is a template for text file [TextInputFile].\n      This template was written at: [DATE.UTC].\n      [Signature]\n    ", pgeMetadata.getMetadata("TextFileTemplate"));
+      assertEquals("Hello", pgeMetadata.getMetadata("SimpleGreeting"));
+      assertEquals("Hi", pgeMetadata.getMetadata("CasualGreeting"));
+      assertEquals("<Custom Greeting Here>", pgeMetadata.getMetadata("CustomGreeting"));
+      assertEquals("Hello", pgeMetadata.getMetadata("Greating"));
+      assertEquals("-bfost", pgeMetadata.getMetadata("Signature"));
+      assertEquals(Lists.newArrayList("File1.txt","File2.dat","File3.xml"), pgeMetadata.getAllMetadata("AuxInputFiles"));
+      assertEquals(Lists.newArrayList("true","false","true"), pgeMetadata.getAllMetadata("IsText"));
+      assertEquals(Lists.newArrayList("AuxInputFiles","IsText"), pgeMetadata.getAllMetadata("CsvHeader"));
+
+      // Verify pgeconfig checks out.
+      List<DynamicConfigFile> dynConfigFiles = pgeConfig.getDynamicConfigFiles();
+      assertEquals(2, dynConfigFiles.size());
+      assertEquals("org.apache.oodt.cas.pge.writers.TextConfigFileWriter", dynConfigFiles.get(0).getWriterClass());
+      assertEquals("/tmp/config/dyn-input.txt", dynConfigFiles.get(0).getFilePath());
+      assertEquals(Lists.newArrayList("\n      [Greeting],\n      This is a template for text file [TextInputFile].\n      This template was written at: [DATE.UTC].\n      [Signature]\n    "), Arrays.asList(dynConfigFiles.get(0).getArgs()));
+      assertEquals("org.apache.oodt.cas.pge.writers.CsvConfigFileWriter", dynConfigFiles.get(1).getWriterClass());
+      assertEquals("/tmp/config/dyn-input.csv", dynConfigFiles.get(1).getFilePath());
+      assertEquals(Lists.newArrayList("AuxInputFiles,IsText"), Arrays.asList(dynConfigFiles.get(1).getArgs()));
+
+      assertEquals(5, pgeConfig.getExeCmds().size());
+      assertEquals("echo /tmp/config/dyn-input.txt > PgeOutput.txt", pgeConfig.getExeCmds().get(0));
+      assertEquals("echo /tmp/config/dyn-input.csv >> PgeOutput.txt", pgeConfig.getExeCmds().get(1));
+      assertEquals("if ( ! -e src/test/resources/data-file-1.txt || ! -e src/test/resources/data-file-2.txt ) then", pgeConfig.getExeCmds().get(2));
+      assertEquals("  exit 1", pgeConfig.getExeCmds().get(3));
+      assertEquals("endif", pgeConfig.getExeCmds().get(4));
+      assertEquals("/tmp", pgeConfig.getExeDir());
+      assertEquals("csh", pgeConfig.getShellType());
+
+      FileStagingInfo fileStagingInfo = pgeConfig.getFileStagingInfo();
+      assertEquals(Lists.newArrayList("src/test/resources/data-file-2.txt", "src/test/resources/data-file-1.txt"), fileStagingInfo.getFilePaths());
+      assertEquals("/tmp/staging", fileStagingInfo.getStagingDir());
+      assertEquals(true, fileStagingInfo.isForceStaging());
+
+      List<OutputDir> outputDirs = pgeConfig.getOuputDirs();
+      assertEquals(1, outputDirs.size());
+      assertEquals(true, outputDirs.get(0).isCreateBeforeExe());
+      assertEquals("/tmp/output", outputDirs.get(0).getPath());
+   }
+}
diff --git a/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/metadata/TestPgeMetadata.java b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/metadata/TestPgeMetadata.java
new file mode 100644
index 0000000..0cb2a59
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/metadata/TestPgeMetadata.java
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.metadata;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.pge.metadata.PgeMetadata.Type;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link PgeMetadata}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestPgeMetadata extends TestCase {
+
+   public void testReplacePgeMetadata() {
+      Metadata staticMetadata = new Metadata();
+      staticMetadata.addMetadata("key1", "staticValue1");
+      staticMetadata.addMetadata("key2", "staticValue2");
+      staticMetadata.addMetadata("key3", "staticValue3");
+
+      Metadata dynamicMetadata = new Metadata();
+      dynamicMetadata.addMetadata("key2", "dynValue2");
+
+      PgeMetadata pgeMet = new PgeMetadata(staticMetadata, dynamicMetadata);
+      PgeMetadata pgeMet2 = new PgeMetadata(staticMetadata, dynamicMetadata);
+      pgeMet2.replaceMetadata("key4", "localValue4");
+      pgeMet2.linkKey("keyLink1", "key1");
+      pgeMet2.markAsDynamicMetadataKey("key4");
+      pgeMet.replaceMetadata(pgeMet2, "test");
+
+      assertEquals("staticValue1", pgeMet.getMetadata("key1"));
+      assertEquals("staticValue2", pgeMet.getMetadata("key2"));
+      assertEquals("staticValue2",
+            pgeMet.getMetadata("key2", PgeMetadata.Type.STATIC));
+      assertEquals("staticValue3", pgeMet.getMetadata("key3"));
+      assertNull(pgeMet.getMetadata("key4"));
+
+      assertNull(pgeMet.getMetadata("test/key1"));
+      assertNull(pgeMet.getMetadata("test/key2"));
+      assertNull(pgeMet.getMetadata("test/key2", PgeMetadata.Type.STATIC));
+      assertNull(pgeMet.getMetadata("test/key3"));
+      assertEquals("localValue4", pgeMet.getMetadata("test/key4"));
+
+      assertNull(pgeMet.getMetadata("keyLink1"));
+      assertEquals(pgeMet.getMetadata("key1"),
+            pgeMet.getMetadata("test/keyLink1"));
+      assertEquals(1, pgeMet.getMarkedAsDynamicMetadataKeys().size());
+      assertEquals("test/key4", pgeMet.getMarkedAsDynamicMetadataKeys()
+            .iterator().next());
+   }
+
+   public void testChangingDynamicMetadata() {
+      PgeMetadata pgeMet = new PgeMetadata();
+
+      assertTrue(pgeMet.asMetadata(Type.DYNAMIC).getAllKeys().isEmpty());
+      pgeMet.replaceMetadata("key1", "value1");
+      assertTrue(pgeMet.asMetadata(Type.DYNAMIC).getAllKeys().isEmpty());
+      pgeMet.markAsDynamicMetadataKey();
+      assertTrue(pgeMet.asMetadata(Type.DYNAMIC).getAllKeys().isEmpty());
+      pgeMet.commitMarkedDynamicMetadataKeys();
+      assertEquals(1, pgeMet.asMetadata(Type.DYNAMIC).getAllKeys().size());
+      assertEquals("value1", pgeMet.asMetadata(Type.DYNAMIC)
+            .getMetadata("key1"));
+
+      pgeMet = new PgeMetadata();
+
+      assertTrue(pgeMet.asMetadata(Type.DYNAMIC).getAllKeys().isEmpty());
+      pgeMet.replaceMetadata("key1", "value1");
+      assertTrue(pgeMet.asMetadata(Type.DYNAMIC).getAllKeys().isEmpty());
+      pgeMet.markAsDynamicMetadataKey("key1");
+      assertTrue(pgeMet.asMetadata(Type.DYNAMIC).getAllKeys().isEmpty());
+      pgeMet.commitMarkedDynamicMetadataKeys("key1");
+      assertEquals(1, pgeMet.asMetadata(Type.DYNAMIC).getAllKeys().size());
+      assertEquals("value1", pgeMet.asMetadata(Type.DYNAMIC)
+            .getMetadata("key1"));
+
+      pgeMet.linkKey("keyLink1", "key1");
+      pgeMet.replaceMetadata("keyLink1", "newValue");
+      assertEquals("newValue",
+            pgeMet.asMetadata(Type.DYNAMIC).getMetadata("key1"));
+   }
+
+   public void testLinking() {
+      PgeMetadata pgeMet = new PgeMetadata();
+
+      pgeMet.replaceMetadata("key1", "value1");
+      pgeMet.linkKey("keyLink1", "key1");
+      pgeMet.linkKey("keyLink2", "keyLink1");
+      pgeMet.linkKey("keyLink3", "keyLink1");
+
+      assertEquals("value1", pgeMet.getMetadata("key1"));
+      assertEquals("value1", pgeMet.getMetadata("keyLink1"));
+      assertEquals("value1", pgeMet.getMetadata("keyLink2"));
+      assertEquals("value1", pgeMet.getMetadata("keyLink3"));
+
+      pgeMet.replaceMetadata("keyLink3", "newValue");
+
+      assertEquals("newValue", pgeMet.getMetadata("key1"));
+      assertEquals("newValue", pgeMet.getMetadata("keyLink1"));
+      assertEquals("newValue", pgeMet.getMetadata("keyLink2"));
+      assertEquals("newValue", pgeMet.getMetadata("keyLink3"));
+
+      assertEquals(Lists.newArrayList("keyLink1", "key1"),
+            pgeMet.getReferenceKeyPath("keyLink2"));
+      assertEquals(Lists.newArrayList("keyLink1", "key1"),
+            pgeMet.getReferenceKeyPath("keyLink3"));
+
+      pgeMet.replaceMetadata("key1", "value1");
+
+      assertEquals("value1", pgeMet.getMetadata("key1"));
+      assertEquals("value1", pgeMet.getMetadata("keyLink1"));
+      assertEquals("value1", pgeMet.getMetadata("keyLink2"));
+      assertEquals("value1", pgeMet.getMetadata("keyLink3"));
+
+      pgeMet.unlinkKey("keyLink1");
+
+      assertEquals("value1", pgeMet.getMetadata("key1"));
+      assertNull(pgeMet.getMetadata("keyLink1"));
+      assertNull(pgeMet.getMetadata("keyLink2"));
+      assertNull(pgeMet.getMetadata("keyLink3"));
+
+      pgeMet.linkKey("keyLink1", "key1");
+
+      assertEquals("value1", pgeMet.getMetadata("key1"));
+      assertEquals("value1", pgeMet.getMetadata("keyLink1"));
+      assertEquals("value1", pgeMet.getMetadata("keyLink2"));
+      assertEquals("value1", pgeMet.getMetadata("keyLink3"));
+
+      assertEquals("key1", pgeMet.resolveKey("key1"));
+      assertEquals("key1", pgeMet.resolveKey("keyLink1"));
+      assertEquals("key1", pgeMet.resolveKey("keyLink2"));
+      assertEquals("key1", pgeMet.resolveKey("keyLink3"));
+      assertEquals("keyLink4", pgeMet.resolveKey("keyLink4"));
+   }
+}
diff --git a/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/metadata/TestPgeTaskMetKeys.java b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/metadata/TestPgeTaskMetKeys.java
new file mode 100644
index 0000000..30ce77f
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/metadata/TestPgeTaskMetKeys.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.metadata;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link PgeTaskMetKeys}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestPgeTaskMetKeys extends TestCase {
+
+   public void testLegacyMode() {
+      assertEquals(PgeTaskMetKeys.NAME.getName(), PgeTaskMetKeys.NAME.name);
+      System.setProperty(PgeTaskMetKeys.USE_LEGACY_PROPERTY, "true");
+      assertEquals(PgeTaskMetKeys.NAME.getName(), PgeTaskMetKeys.NAME.legacyName);
+   }
+
+   public void testIsVector() {
+      assertFalse(PgeTaskMetKeys.NAME.isVector());
+      assertFalse(PgeTaskMetKeys.getByName(
+            PgeTaskMetKeys.NAME.getName()).isVector());
+      assertTrue(PgeTaskMetKeys.PROPERTY_ADDERS.isVector());
+      assertTrue(PgeTaskMetKeys.getByName(
+            PgeTaskMetKeys.PROPERTY_ADDERS.getName()).isVector());
+      assertNull(PgeTaskMetKeys.getByName("BOGUS/BOGUS/BOGUS"));
+   }
+}
diff --git a/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/staging/TestFileStager.java b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/staging/TestFileStager.java
new file mode 100644
index 0000000..13a7c18
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/staging/TestFileStager.java
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.staging;
+
+//EasyMock static imports
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reportMatcher;
+import static org.easymock.EasyMock.verify;
+
+//JDK imports
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManager;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.pge.metadata.PgeMetadata;
+import org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys;
+
+//EasyMock imports
+import org.easymock.IArgumentMatcher;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link FileStager}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestFileStager extends TestCase {
+
+   public void testCreateFileManagerClient() throws Exception {
+      // Test throws case.
+      PgeMetadata pgeMetadata = createStrictMock(PgeMetadata.class);
+      expect(pgeMetadata.getMetadata(PgeTaskMetKeys.QUERY_FILE_MANAGER_URL))
+            .andReturn(null);
+      replay(pgeMetadata);
+
+      try {
+         FileStager.createFileManagerClient(pgeMetadata);
+         fail("Should have thrown Exception");
+      } catch (Exception e) { /* expect throw */
+      }
+      verify(pgeMetadata);
+
+      // Test success case.
+      System.setProperty("filemgr.catalog.factory", "");
+      System.setProperty("filemgr.repository.factory", "");
+      int port = 9876;
+      XmlRpcFileManager filemgr = new XmlRpcFileManager(port);
+      String filemgrUrl = "http://localhost:" + port;
+      pgeMetadata = createStrictMock(PgeMetadata.class);
+      expect(pgeMetadata.getMetadata(PgeTaskMetKeys.QUERY_FILE_MANAGER_URL))
+            .andReturn(filemgrUrl);
+      replay(pgeMetadata);
+
+      assertEquals(filemgrUrl, FileStager.createFileManagerClient(pgeMetadata)
+            .getFileManagerUrl().toString());
+      verify(pgeMetadata);
+      filemgr.shutdown();
+   }
+
+   public void testGetProductReferences() throws CatalogException,
+         URISyntaxException {
+      String productId = "12345";
+
+      String uri1 = "file:///path/to/file1";
+      String uri2 = "file:///path/to/file2";
+      Reference ref1 = new Reference();
+      ref1.setDataStoreReference(uri1);
+      Reference ref2 = new Reference();
+      ref2.setDataStoreReference(uri2);
+
+      XmlRpcFileManagerClient fmClient = createStrictMock(XmlRpcFileManagerClient.class);
+      expect(fmClient.getProductReferences(ProductIdMatcher.eqProductId(productId))).andReturn(
+            Lists.newArrayList(ref1, ref2));
+      replay(fmClient);
+
+      List<URI> uris = FileStager.getProductReferences(productId, fmClient);
+      assertEquals(2, uris.size());
+      assertTrue(uris.contains(new URI("file:///path/to/file1")));
+      assertTrue(uris.contains(new URI("file:///path/to/file2")));
+
+      verify(fmClient);
+   }
+
+   public void testAsURI() throws URISyntaxException {
+      String absoluteHttpUri = "http://somewhere.com/path/to/data.dat";
+      String absoluteFileUri = "file:///path/to/data.dat";
+      String relativePath = "path/to/data.dat";
+      String absolutePath = "/path/to/data.dat";
+
+      assertEquals("http://somewhere.com/path/to/data.dat",
+            FileStager.asURI(absoluteHttpUri).toString());
+      assertEquals("file:///path/to/data.dat", FileStager
+            .asURI(absoluteFileUri).toString());
+      assertEquals("file://" + new File("").getAbsolutePath()
+            + "/path/to/data.dat", FileStager.asURI(relativePath).toString());
+      assertEquals("file:///path/to/data.dat", FileStager.asURI(absolutePath)
+            .toString());
+   }
+
+   public static class ProductIdMatcher implements IArgumentMatcher {
+
+      private String productId;
+
+      public ProductIdMatcher(String productId) {
+         this.productId = productId;
+      }
+
+      @Override
+      public void appendTo(StringBuffer buffer) {
+         buffer.append("eqProduct(");
+         buffer.append(Product.class.getName());
+         buffer.append(" with product id [");
+         buffer.append(productId + "])");
+      }
+
+      @Override
+      public boolean matches(Object obj) {
+         if (obj instanceof Product) {
+            return productId.equals(((Product) obj).getProductId());
+         }
+         return false;
+      }
+
+      public static Product eqProductId(String productId) {
+         reportMatcher(new ProductIdMatcher(productId));
+         return null;
+      }
+   }
+   
+}
diff --git a/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/util/TestXmlHelper.java b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/util/TestXmlHelper.java
new file mode 100644
index 0000000..bee37b6
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/util/TestXmlHelper.java
@@ -0,0 +1,70 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.cas.pge.util;
+
+import static org.apache.oodt.cas.pge.config.PgeConfigMetKeys.IMPORT_TAG;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getFile;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getImports;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getNamespace;
+import static org.apache.oodt.cas.pge.util.XmlHelper.getRootElement;
+
+import java.io.FileNotFoundException;
+import java.util.List;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import org.apache.oodt.cas.metadata.Metadata;
+
+import junit.framework.TestCase;
+
+public class TestXmlHelper extends TestCase {
+
+   private static final String BLANK_PGE_CONFIG = "src/test/resources/blank-pge-config.xml";
+   private static final String IMPORTS_ONLY_PGE_CONFIG = "src/test/resources/imports-only-pge-config.xml";
+
+   // Tests that only root node is required.
+   public void testLoadBlankXmlFile() throws FileNotFoundException {
+      Element elem = getRootElement(BLANK_PGE_CONFIG);
+      assertNotNull(elem);
+      assertEquals(1, elem.getChildNodes().getLength());
+      assertEquals("#text", elem.getChildNodes().item(0).getNodeName());
+      assertEquals("", elem.getChildNodes().item(0).getNodeValue().trim());
+   }
+
+   public void testGetImports() throws Exception {
+      Element elem = getRootElement(IMPORTS_ONLY_PGE_CONFIG);
+      Metadata metadata = new Metadata();
+      List<Pair<String, String>> imports = getImports(elem, metadata);
+      assertEquals(2, imports.size());
+      assertEquals("blank", imports.get(0).getFirst());
+      assertEquals("blank-pge-config.xml", imports.get(0).getSecond());
+      assertEquals(null, imports.get(1).getFirst());
+      assertEquals("pge-config.xml", imports.get(1).getSecond());
+   }
+
+   public void testGetNamespace() throws Exception {
+      Element elem = getRootElement(IMPORTS_ONLY_PGE_CONFIG);
+      Metadata metadata = new Metadata();
+
+      NodeList importTags = elem.getElementsByTagName(IMPORT_TAG);
+      assertEquals("blank", getNamespace((Element) importTags.item(0), metadata));
+      assertEquals("blank-pge-config.xml", getFile((Element) importTags.item(0), metadata));
+      assertNull(getNamespace((Element) importTags.item(1), metadata));
+      assertEquals("pge-config.xml", getFile((Element) importTags.item(1), metadata));
+   }
+}
diff --git a/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/util/UtilsTest.java b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/util/UtilsTest.java
new file mode 100644
index 0000000..b22e4eb
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/util/UtilsTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.pge.util;
+
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.QueryFormulationException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+
+import java.net.MalformedURLException;
+
+import junit.framework.TestCase;
+
+public class UtilsTest extends TestCase {
+
+	protected void setUp() throws Exception {
+	}
+
+	protected void tearDown() throws Exception {
+	}
+
+	public void testEvalSQL() throws MalformedURLException, ConnectionException, CatalogException, RepositoryManagerException, QueryFormulationException {
+		//Utils.evalSQL("SQL { SELECT Filename FROM IASI_L1C WHERE DataVersion >= '23.4' AND DataVersion <= '24.4' AND DataVersion != '24.0' OR Filename != 'SomeName' }");
+	}
+
+}
diff --git a/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/writers/MetadataKeyReplacementTemplateWriterTest.java b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/writers/MetadataKeyReplacementTemplateWriterTest.java
new file mode 100644
index 0000000..2ecc558
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/writers/MetadataKeyReplacementTemplateWriterTest.java
@@ -0,0 +1,77 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.pge.writers;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test harness for the MetadataKeyReplacementWriter.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class MetadataKeyReplacementTemplateWriterTest extends TestCase {
+
+  private static final Logger LOG = Logger
+      .getLogger(MetadataKeyReplacementTemplateWriterTest.class.getName());
+
+  private static final String expected = "Welcome to ApacheCon Paul and Chris! You are a member of the following projects OODT,Tika,SIS,Gora.";
+
+  public void testGenerateTemplate() throws IOException {
+    MetadataKeyReplacerTemplateWriter writer = new MetadataKeyReplacerTemplateWriter();
+    String templateSourcePath = "./src/test/resources/metkeyreplace.template";
+    String outPath = File.createTempFile("foo", "bar").getParentFile()
+        .getAbsolutePath();
+    if (!outPath.endsWith("/"))
+      outPath += "/";
+
+    outPath += "generated.template";
+
+    Metadata met = new Metadata();
+    met.addMetadata("Person1", "Paul");
+    met.addMetadata("Person2", "Chris");
+    met.addMetadata("Projects", "OODT");
+    met.addMetadata("Projects", "Tika");
+    met.addMetadata("Projects", "SIS");
+    met.addMetadata("Projects", "Gora");
+
+    try {
+      writer.generateFile(outPath, met, LOG, templateSourcePath);
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+
+    assertTrue(new File(outPath).exists());
+    String fileString = FileUtils.readFileToString(new File(outPath));
+    assertNotNull(fileString);
+    assertEquals(expected, fileString);
+  }
+}
diff --git a/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/writers/MockDynamicConfigFileWriter.java b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/writers/MockDynamicConfigFileWriter.java
new file mode 100644
index 0000000..6e9fab6
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/writers/MockDynamicConfigFileWriter.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pge.writers;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+//Apache imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * Mock implementation of {@link DynamicConfigFileWriter}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class MockDynamicConfigFileWriter extends DynamicConfigFileWriter {
+
+   @Override
+   public File generateFile(String filePath, Metadata metadata, Logger logger,
+         Object... customArgs) throws IOException {
+      File configFile = new File(filePath);
+      configFile.getParentFile().mkdirs();
+      FileUtils.touch(configFile);
+      return configFile;
+   }
+}
diff --git a/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/writers/VelocityConfigFileWriterTest.java b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/writers/VelocityConfigFileWriterTest.java
new file mode 100644
index 0000000..c434e79
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/java/org/apache/oodt/cas/pge/writers/VelocityConfigFileWriterTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.pge.writers;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.logging.Logger;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.pge.writers.VelocityConfigFileWriter;
+import org.apache.oodt.cas.pge.writers.VelocityMetadata;
+
+import junit.framework.TestCase;
+
+public class VelocityConfigFileWriterTest extends TestCase {
+
+  private static final Logger LOG = Logger
+      .getLogger(VelocityConfigFileWriterTest.class.getName());
+
+  public void testCreateConfigFile() throws IOException {
+    URL url = this.getClass().getResource("/test-config.vm");
+    VelocityConfigFileWriter vcfw = new VelocityConfigFileWriter();
+    VelocityMetadata metadata = new VelocityMetadata(new Metadata());
+    metadata.addMetadata("name", "Chris");
+    metadata.addMetadata("name", "Paul");
+    metadata.addMetadata("conference", "ApacheCon");
+    File config = File.createTempFile("config", ".out");
+    try {
+      vcfw.generateFile(config.toString(), metadata, LOG, url.getFile());
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+    String output = FileUtils.readFileToString(config);
+    assertEquals(System.getenv().get("USER") + " Welcomes to ApacheCon Chris Paul!", output);
+    config.delete();
+  }
+
+}
diff --git a/0.8.1-rc1/pge/src/test/resources/blank-pge-config.xml b/0.8.1-rc1/pge/src/test/resources/blank-pge-config.xml
new file mode 100755
index 0000000..7039755
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/resources/blank-pge-config.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<!--
+Empty PgeConfig file for testing purposes.
+-->
+<pgeConfig>    
+</pgeConfig>
diff --git a/0.8.1-rc1/pge/src/test/resources/common-metadata-pge-config.xml b/0.8.1-rc1/pge/src/test/resources/common-metadata-pge-config.xml
new file mode 100755
index 0000000..972567f
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/resources/common-metadata-pge-config.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<!-- 
+  Only customMetadata other PgeConfig XML file for testing purposes.
+-->
+<pgeConfig>
+
+	<customMetadata>
+		<metadata key="GreaterThan" val="&gt;" />
+		<metadata key="LessThan" val="&lt;" />
+    <metadata key="Ampersand" val="&amp;" />
+    <metadata key="Apostrophe" val="&apos;" />
+    <metadata key="QuotationMark" val="&quot;" />		
+	</customMetadata>
+
+</pgeConfig>
diff --git a/0.8.1-rc1/pge/src/test/resources/custom-metadata-only-pge-config.xml b/0.8.1-rc1/pge/src/test/resources/custom-metadata-only-pge-config.xml
new file mode 100755
index 0000000..a7a7e67
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/resources/custom-metadata-only-pge-config.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<!-- 
+  Only customMetadata other PgeConfig XML file for testing purposes.
+-->
+<pgeConfig>
+
+	<customMetadata>
+		<metadata key="" val="" />
+		<metadata key="" key-ref="" />
+		<metadata key-gen="" val="" />
+	</customMetadata>
+
+</pgeConfig>
diff --git a/0.8.1-rc1/pge/src/test/resources/data-file-1.txt b/0.8.1-rc1/pge/src/test/resources/data-file-1.txt
new file mode 100644
index 0000000..68e17c6
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/resources/data-file-1.txt
@@ -0,0 +1,16 @@
+# 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.
+
+This is a test data file 1
diff --git a/0.8.1-rc1/pge/src/test/resources/data-file-2.txt b/0.8.1-rc1/pge/src/test/resources/data-file-2.txt
new file mode 100644
index 0000000..c6aa5d4
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/resources/data-file-2.txt
@@ -0,0 +1,16 @@
+# 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.
+
+This is a test data file 2
diff --git a/0.8.1-rc1/pge/src/test/resources/dyn-input-writers-pge-config.xml b/0.8.1-rc1/pge/src/test/resources/dyn-input-writers-pge-config.xml
new file mode 100755
index 0000000..b8a1c31
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/resources/dyn-input-writers-pge-config.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<pgeConfig>
+
+	<customMetadata>
+	  <metadata key="TextWriter" val="org.apache.oodt.cas.pge.writers.TextConfigFileWriter" />
+	  <metadata key="CsvWriter" val="org.apache.oodt.cas.pge.writers.CsvConfigFileWriter" />
+	</customMetadata>
+
+</pgeConfig>
diff --git a/0.8.1-rc1/pge/src/test/resources/imports-only-pge-config.xml b/0.8.1-rc1/pge/src/test/resources/imports-only-pge-config.xml
new file mode 100755
index 0000000..167f25c
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/resources/imports-only-pge-config.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<!--
+Only imports other PgeConfig XML file for testing purposes.
+-->
+<pgeConfig>
+    
+    <import namespace="blank" file="blank-pge-config.xml"/>
+    <import file="pge-config.xml"/>
+
+</pgeConfig>
diff --git a/0.8.1-rc1/pge/src/test/resources/metkeyreplace.template b/0.8.1-rc1/pge/src/test/resources/metkeyreplace.template
new file mode 100644
index 0000000..af8648c
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/resources/metkeyreplace.template
@@ -0,0 +1 @@
+Welcome to ApacheCon $Person1 and $Person2! You are a member of the following projects $Projects.
\ No newline at end of file
diff --git a/0.8.1-rc1/pge/src/test/resources/pge-config.xml b/0.8.1-rc1/pge/src/test/resources/pge-config.xml
new file mode 100755
index 0000000..5e4f121
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/resources/pge-config.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+
+TODO(bfoster): Make this a working example.
+-->
+<pgeConfig>
+
+  <import namespace="commons" file="common-metadata-pge-config.xml" />
+  <import namespace="writers" file="dyn-input-writers-pge-config.xml" />
+
+	<dynInputFiles>
+		<file path="[TextInputFile]" writerClass="[writers/TextWriter]" args="[TextFileTemplate]" />
+    <file path="[CsvInputFile]" writerClass="[writers/CsvWriter]" args="[CsvHeader]" />
+	</dynInputFiles>
+
+  <fileStaging dir="[StagingDir]" force="[ForceStaging]">
+    <stageFiles metadataKey="InputFiles" />
+  </fileStaging>
+
+	<exe dir="[WorkingDir]" shellType="csh">
+		<cmd>echo [TextInputFile] [commons/GreaterThan] [OutputFileName]</cmd>
+    <cmd>echo [CsvInputFile] [commons/GreaterThan][commons/GreaterThan] [OutputFileName]</cmd>
+    <cmd>if ( ! -e [InputFile1] || ! -e [InputFile2] ) then</cmd>
+    <cmd>  exit 1</cmd>
+    <cmd>endif</cmd>
+	</exe>
+
+	<output>
+		<dir path="[OutputDir]" createBeforeExe="true"/>
+	</output>
+
+	<customMetadata>
+    <!-- Defaults -->
+    <metadata key="GREETING_ENUM" val="Simple" />
+    <metadata key="FORCE_STAGING" val="true" />
+    <metadata key="CUSTOM_GREETING_ENUM" val="Custom" />
+    <metadata key="CUSTOM_GREETING_ENUM_VALUE" val="[commons/LessThan]Custom Greeting Here[commons/GreaterThan]" />
+    
+	  <!-- Remap externally set metadata so if name changes easy to update config file -->
+	  <metadata key="WorkingDir" key-ref="WORKING_DIR" />
+    <metadata key="GreetingEnum" key-ref="GREETING_ENUM" />
+    <metadata key="CustomGreetingEnum" key-ref="CUSTOM_GREETING_ENUM" />
+    <metadata key="CustomGreetingEnumValue" key-ref="CUSTOM_GREETING_ENUM_VALUE" />
+    <metadata key="InputFile1" key-ref="INPUT_FILE_1" />
+    <metadata key="InputFile2" key-ref="INPUT_FILE_2" />
+    <metadata key="ForceStaging" key-ref="FORCE_STAGING" />
+
+    <!-- Input Files -->
+    <metadata key="InputFiles" val="[InputFile1],[InputFile2]" split="true" />
+    
+    <!-- Working sub-directories -->
+    <metadata key="ConfigDir" val="[WorkingDir]/config" />
+    <metadata key="OutputDir" val="[WorkingDir]/output" />
+    <metadata key="StagingDir" val="[WorkingDir]/staging" />
+
+    <!-- Dynamically generated PGE input config files -->
+    <metadata key="DynInput/Text/Name" val="dyn-input.txt" />
+    <metadata key="DynInput/CSV/Name" val="dyn-input.csv" />
+    <metadata key="TextInputFile" val="[ConfigDir]/[DynInput/Text/Name]" />
+    <metadata key="CsvInputFile" val="[ConfigDir]/[DynInput/CSV/Name]" />
+
+    <!-- Output file names -->
+    <metadata key="OutputFileName" val="PgeOutput.txt" />
+
+    <!-- Text input file template metadata -->
+    <metadata key="TextFileTemplate" envReplace="false">
+      [Greeting],
+      This is a template for text file [TextInputFile].
+      This template was written at: [DATE.UTC].
+      [Signature]
+    </metadata>
+    <metadata key="SimpleGreeting" val="Hello" />
+    <metadata key="CasualGreeting" val="Hi" />    
+    <metadata key-gen="[CustomGreetingEnum]Greeting" val="[CustomGreetingEnumValue]" />
+    <metadata key="Greating" key-ref="[GreetingEnum]Greeting" />
+    <metadata key="Signature" val="-bfost" />
+
+    <!-- CSV input file metadata -->
+    <metadata key="AuxInputFiles" val="File1.txt,File2.dat,File3.xml" split="true" />
+    <metadata key="IsText" val="true,false,true" split="true" />
+    <metadata key="CsvHeader" val="AuxInputFiles,IsText" split="true" />
+	</customMetadata>
+
+</pgeConfig>
diff --git a/0.8.1-rc1/pge/src/test/resources/test-config.vm b/0.8.1-rc1/pge/src/test/resources/test-config.vm
new file mode 100644
index 0000000..59ddc42
--- /dev/null
+++ b/0.8.1-rc1/pge/src/test/resources/test-config.vm
@@ -0,0 +1 @@
+$env.USER Welcomes to $metadata.conference#foreach($name in $metadata.getValues('name')) $name#end!
\ No newline at end of file
diff --git a/0.8.1-rc1/pom.xml b/0.8.1-rc1/pom.xml
new file mode 100644
index 0000000..971856b
--- /dev/null
+++ b/0.8.1-rc1/pom.xml
@@ -0,0 +1,106 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+    <parent>
+        <groupId>org.apache.oodt</groupId>
+        <artifactId>oodt-core</artifactId>
+        <version>0.8.1</version>
+        <relativePath>core/pom.xml</relativePath>
+    </parent>
+
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt</artifactId>
+    <name>Apache OODT</name>
+    <packaging>pom</packaging>
+    <description>
+        Apache OODT is middleware for metadata.
+    </description>
+
+    <scm>
+        <connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1</developerConnection>
+        <url>http://svn.apache.org/viewvc/oodt/tags/0.8.1</url>
+    </scm>
+
+    <modules>
+        <module>core</module>
+        <module>commons</module>
+        <module>cli</module>
+        <module>pcs/input</module>
+        <module>metadata</module>
+        <module>protocol/api</module>
+        <module>protocol/ftp</module>
+        <module>protocol/http</module>
+        <module>protocol/imaps</module>
+        <module>protocol/sftp</module>
+        <module>xmlquery</module>
+        <module>sso</module>
+        <module>filemgr</module>
+        <module>catalog</module> 
+        <module>workflow</module>
+        <module>crawler</module>
+        <module>resource</module>
+        <module>curator</module>
+        <module>pge</module>
+        <module>mvn/plugins/cas-install</module>
+        <module>mvn/archetypes</module>
+        <module>pushpull</module>
+        <module>product</module>
+        <module>profile</module>
+        <module>grid</module>
+        <module>xmlps</module>
+        <module>opendapps</module>
+        <module>webapp/components</module>
+        <module>webapp/fmbrowser</module>
+        <module>webapp/fmprod</module>
+        <module>webapp/wmonitor</module>
+        <module>app/fmbrowser</module>
+        <module>app/weditor</module>
+        <module>pcs/core</module>
+        <module>pcs/opsui</module>
+        <module>pcs/services</module>
+    </modules>
+    <profiles>
+        <profile>
+            <id>audit</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>rat-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>check</goal>
+                                </goals>
+                            </execution>
+                            </executions>
+                            <configuration>
+                                <numUnapprovedLicenses>11</numUnapprovedLicenses>
+                            </configuration>
+                        </plugin>
+                    </plugins>
+                </build>
+            </profile>
+        </profiles>
+</project>
diff --git a/0.8.1-rc1/product/pom.xml b/0.8.1-rc1/product/pom.xml
new file mode 100644
index 0000000..3432328
--- /dev/null
+++ b/0.8.1-rc1/product/pom.xml
@@ -0,0 +1,124 @@
+<?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.
+-->
+<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>
+    <parent>
+        <groupId>org.apache.oodt</groupId>
+        <artifactId>oodt-core</artifactId>
+        <version>0.8.1</version>
+        <relativePath>../core/pom.xml</relativePath>
+    </parent>
+    <artifactId>oodt-product</artifactId>
+    <name>Product Service</name>
+    <description>
+        The Product Service provides access to data products.  Products can be
+        scientific datasets, images, documents, or anything with an electronic
+        representation.  The Product Service accepts standard query expressions (see
+        the Query Expression component) and returns zero or more matching products.
+        In addition, the product service can transform products from proprietary
+        formats and into Internet standard formats or run other transformations, all
+        without impacting local stores or operations.
+    </description>
+    <scm>
+   		<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/product</connection>
+   		<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/product</developerConnection>
+   		<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/product</url>
+    </scm>
+    <build>
+        <resources>
+            <resource>
+                <targetPath>org/apache/oodt/product</targetPath>
+                <directory>${basedir}/src/main/conf</directory>
+                <includes>
+                    <include>displayableTypes.xml</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <profiles>
+        <profile>
+            <id>audit</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>rat-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>check</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.oodt</groupId>
+            <artifactId>oodt-commons</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>1.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tika</groupId>
+            <artifactId>tika-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.oodt</groupId>
+            <artifactId>oodt-xmlquery</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+	    <dependency>
+	       <groupId>javax.servlet</groupId>
+	       <artifactId>servlet-api</artifactId>
+	       <version>2.4</version>
+	       <scope>provided</scope>
+	    </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>3.8.2</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/0.8.1-rc1/product/src/main/conf/displayableTypes.xml b/0.8.1-rc1/product/src/main/conf/displayableTypes.xml
new file mode 100644
index 0000000..aca9ad0
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/conf/displayableTypes.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

+<!--

+  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 displayableTypes [

+  <!ELEMENT displayableTypes (type*)>

+  <!ELEMENT type (#PCDATA)>

+]>

+<displayableTypes>

+  <type>text/plain</type>

+  <type>text/richtext</type>

+  <type>text/enriched</type>

+  <type>text/tab-separated-values</type>

+  <type>text/html</type>

+  <type>text/xml</type>

+  <type>text/rtf</type>

+  <type>message/rfc822</type>

+  <type>message/partial</type>

+  <type>message/external-body</type>

+  <type>message/news</type>

+  <type>message/http</type>

+  <type>message/delivery-status</type>

+  <type>message/disposition-notification</type>

+  <type>message/s-http</type>

+  <type>application/rtf</type>

+  <type>application/pdf</type>

+  <type>image/jpeg</type>

+  <type>image/gif</type>

+  <type>image/tiff</type>

+  <type>image/png</type>

+  <type>audio/basic</type>

+  <type>audio/32kadpcm</type>

+  <type>audio/mpeg</type>

+  <type>video/mpeg</type>

+  <type>video/quicktime</type>

+  <type>model/vrml</type>

+</displayableTypes>

diff --git a/0.8.1-rc1/product/src/main/conf/ofsn-ps.xml b/0.8.1-rc1/product/src/main/conf/ofsn-ps.xml
new file mode 100644
index 0000000..01939dd
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/conf/ofsn-ps.xml
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  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.
+-->
+<!--  
+Configures a new OODT OFSN style product server. This is a product server
+of the form:
+
+http://host/webgrid/prod?OFSN=/some/ofsn+AND+RT=sometype
+
+OFSN is an online file specification name, as defined by the PDS standards.
+RT is a transformation identifier, identifying a remote transformation to be applied
+at the given OFSN path.
+
+More more information on the OFSN style product servers, see the PDS original here:
+
+http://oodt/pds-client/guide/product
+   
+Required attributes:
+   id: defines a unique URN/id for this product server instance
+   name: defines a human readable name for this product server instance
+   productRoot: defines the root path in which the OFSN product server should start looking for 
+   paths based on a given OFSN
+
+FIXME: Change XML namespace URI for oodt prefix?
+-->
+<oodt:ofsn xmlns:oodt="http://oodt.jpl.nasa.gov/xml/namespaces/oodt/1.0"
+      id="urn:oodt:prod:ofsn"
+      name="OODT OFSN Style Product Handler"
+      productRoot="/some/path"
+      >
+      
+  <!--  defines a new OFSN handler. There are 2 valid types:
+     
+     listing: this type generates a list of files given an OFSN. The list will 
+     be returned and formatted in XML for easy parsing.
+     
+     get: this type returns the bits of the requested ofsn, after performing some
+     type of transformation on them.
+     
+     Required attributes:
+     
+     name: gives the handler type a identifiable name. This should be a valid RT name for use in the OODT
+     product server query, e.g., if you want the dir list non-recursive listing handler to be called on 
+     RT=DIRLIST1, then set name to "DIRLIST1", as below.
+     
+     type: either listing, or get, depending on the desired handler type.
+     
+     class: defines a class that implements either the org.apache.oodt.product.handlers.ofsn.OFSNListHandler
+     interface (for "listing" handlers), or the org.apache.oodt.product.handlers.ofsn.OFSNGetHandler (for
+     "get" handlers). Note that this class must be on the classpath in order for it to be referenced in
+     this configuration.
+  
+   -->
+   
+   <!-- 
+     Optionally, each handler can have its own configuration, specified on the form of
+       &lt;property name=&quot;some name&quot; value=&quot;some value&quot;/&gt;
+       
+       where some name is the name of the configuration property and some value is the
+       value of the configuration property.
+       
+       Optional properties (for GET handlers):
+       
+       property name: mimeType
+       property value: the desired MIME type (also referred to as content-type) a handler should return
+       content as (eg. "text/plain"). More formally, any value of the form 
+       "type/subtype(; parameter=...)*" as defined in RFC 2045.
+    -->
+    
+        
+   <!-- 
+   The DIRLIST1 type is identical to DIRLIST but does not recursively
+   descend into subdirectories.
+   -->
+  <handler name="DIRLIST1" type="listing" 
+       class="org.apache.oodt.product.handlers.ofsn.DirListNonRecursiveHandler"/>
+       
+       
+  <!-- 
+    The DIRLIST type returns an XML file with directory names (and only
+    directory names) and total size of files in each directory starting in
+    the requested directory and traversing into the subdirectories. 
+   -->
+  <handler name="DIRLIST" type="listing"
+       class="org.apache.oodt.product.handlers.ofsn.DirListRecursiveHandler"/>
+    
+
+  <!-- 
+    The DIRFILELIST1 is identical to DIRFILELIST except that it does not
+    recurse into subdirectories.
+   -->
+  <handler name="DIRFILELIST1" type="listing"
+       class="org.apache.oodt.product.handlers.ofsn.FileListNonRecursiveHandler"/>
+
+  <!-- 
+    The DIRFILELIST returns an XML document containing all of the filenames
+    (and only the files, not directories) and their sizes, recursing into
+    subdirectories.  
+   -->          
+  <handler name="DIRFILELIST" type="listing"
+       class="org.apache.oodt.product.handlers.ofsn.FileListRecursiveHandler"/>
+
+  <!-- 
+    The  RAW_SIZE  generates an XML document telling the size of the raw file that 
+    would be returned by the corresponding RAW type.  
+   -->     
+  <handler name="RAW_SIZE" type="listing"
+       class="org.apache.oodt.product.handlers.ofsn.RawSizeListHandler">
+     
+     <!-- 
+       Required attributes:
+          isSizeCmd: this value should be set to true in this handler to ensure that
+          only the size is printed in the OFSN doc.
+      -->
+     <property name="isSizeCmd" value="true"/>
+  </handler>
+
+   <!-- 
+    The FILELIST type returns an XML file naming the requested file and also
+    giving its size.   
+   -->
+  <handler name="FILE_LIST" type="listing"
+       class="org.apache.oodt.product.handlers.ofsn.SingleFileListHandler"/>
+    
+ 
+  <!-- 
+    The FILELISTZIP is similar to FILELIST except that it tells what the size
+    of the requested file would be if compressed into a ZIP archive.  
+  -->   
+  <handler name="FILE_LIST_ZIP" type="listing"
+       class="org.apache.oodt.product.handlers.ofsn.SingleZipFileListHandler">
+       
+       <!-- 
+        Optional attributes:
+          cacheDirRoot: defines the cache dir that the product server should use when asked to create temporary
+          files, e.g., by a listing or get handler. By default, if not specified, it defaults to /tmp
+       
+        -->
+       <property name="cacheDirRoot" value="/tmp"/>       
+  </handler>
+
+  <!-- 
+    The RAW type merely returns the requested file without any modification 
+    (MIME type application/octet-stream ). 
+  -->  
+  <handler name="RAW" type="get"
+       class="org.apache.oodt.product.handlers.ofsn.StdOFSNGetHandler"/>       
+       
+  
+  <!--  
+    The MD5 type returns an MD5 hash of the file bytes generated on the server side.
+   -->
+   
+   <handler name="MD5" type="get"
+       class="org.apache.oodt.product.handlers.ofsn.MD5GetHandler">
+       
+       <property name="mimeType" value="text/plain"/>
+       
+   </handler>
+
+
+  <!--  
+    The URL type returns a URL listing pointing to files within an OFSN
+    
+    (Optional) Use the below properties to customize the constructed URL returned:
+        1. prodServerHostname: the product server hostname
+        2. prodServerPort: the product server's port
+        3. prodServerContextRoot: the name of the product server webapp
+        4. productRoot: the root directory of the product server - identical
+                        to the root directory at the top of this XML file
+        5. returnType: the desired return type. i.e. RAW, MD5, etc.
+   -->
+  <handler name="URL" type="get"
+       class="org.apache.oodt.product.handlers.ofsn.URLGetHandler">
+       
+       <!-- the below values are the default if nothing specified
+       <property name="prodServerHostname" value="localhost"/>
+       <property name="prodServerPort" value="8080"/>
+       <property name="prodServerContextRoot" value="web-grid"/>
+       <property name="productRoot" value="/some/path"/>
+       <property name="returnType" value="RAW"/>
+       -->
+  	   
+       <property name="mimeType" value="text/plain"/>
+  	   
+  </handler>
+</oodt:ofsn>
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/LargeProductQueryHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/LargeProductQueryHandler.java
new file mode 100644
index 0000000..6c0eadd
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/LargeProductQueryHandler.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product;
+
+import org.apache.oodt.xmlquery.XMLQuery;
+
+/**
+ * Handle requests for products that are too large to fit in an {@link
+ * org.apache.oodt.xmlquery.XMLQuery} object.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+public interface LargeProductQueryHandler extends QueryHandler {
+	/**
+	 * Retrieve a chunk of a product.
+	 *
+	 * The product is identified by a string ID.  The query handler should return a
+	 * binary chunk of the product using the given offset and length.  If the ID isn't
+	 * recognized, it should return null.  It should throw an exception if retrieval
+	 * fails for some reason.
+	 *
+	 * @param id Product ID.
+	 * @param offset Where in the product to get a chunk of it.
+	 * @param length How much of the product to get.
+	 * @return A chunk, or null if the <var>id</var> is unknown.
+	 * @throws ProductException if an error occurs.
+	 */
+	byte[] retrieveChunk(String id, long offset, int length) throws ProductException;
+
+	/**
+	 * Close off a product.
+	 *
+	 * This method indicates that the product is no longer required and its resources
+	 * can be freed by the query handler.  If the ID is unknown, no untoward action is
+	 * required.  It should throw an exception if there is an error during the
+	 * resource release (such as an {@link java.io.IOException} when closing a file.
+	 *
+	 * @param id Product ID.
+	 * @throws ProductException if an error occurs.
+	 */
+	void close(String id) throws ProductException;
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/QueryHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/QueryHandler.java
new file mode 100644
index 0000000..6addbce
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/QueryHandler.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product;
+
+import org.apache.oodt.xmlquery.XMLQuery;
+
+/**
+ * Handler for queries in a product service.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+public interface QueryHandler {
+	/**
+	 * Run a query.
+	 *
+	 * @param q The query.
+	 * @return The response.
+	 * @throws ProductException if an error occurs.
+	 */
+	XMLQuery query(XMLQuery q) throws ProductException;
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/AbstractCrawlLister.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/AbstractCrawlLister.java
new file mode 100644
index 0000000..649dcbd
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/AbstractCrawlLister.java
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.io.File;
+import java.io.FileFilter;
+import java.util.List;
+import java.util.Properties;
+import java.util.Stack;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.product.ProductException;
+
+/**
+ * 
+ * An abstract {@link OFSNListHandler} for generating file lists based on two
+ * simple flags: recurse, and crawlForDirs, indicating to crawl for directories
+ * rather than files.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public abstract class AbstractCrawlLister implements OFSNListHandler {
+
+  protected final static Logger LOG = Logger
+      .getLogger(AbstractCrawlLister.class.getName());
+
+  protected static final FileFilter FILE_FILTER = new FileFilter() {
+    public boolean accept(File pathname) {
+      if (pathname.isFile()) {
+        return true;
+      } else
+        return false;
+    }
+  };
+
+  protected static final FileFilter DIR_FILTER = new FileFilter() {
+    public boolean accept(File pathname) {
+      if (pathname.isDirectory()) {
+        return true;
+      } else
+        return false;
+    }
+  };
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.OFSNListHandler#configure(java.
+   * util.Properties)
+   */
+  public abstract void configure(Properties conf);
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.OFSNListHandler#getListing(java
+   * .lang.String)
+   */
+  public abstract File[] getListing(String ofsn) throws ProductException;
+
+  protected File[] crawlFiles(File dirRoot, boolean recur,
+      boolean crawlForDirs) {
+    if (dirRoot == null || ((dirRoot != null && !dirRoot.exists())))
+      throw new IllegalArgumentException("dir root: [" + dirRoot
+          + "] is null or non existant!");
+
+    List<File> fileList = new Vector<File>();
+
+    // start crawling
+    Stack<File> stack = new Stack<File>();
+    stack.push(dirRoot.isDirectory() ? dirRoot : dirRoot.getParentFile());
+    while (!stack.isEmpty()) {
+      File dir = (File) stack.pop();
+      LOG.log(Level.INFO, "OFSN: Crawling " + dir);
+
+      File[] productFiles = null;
+      if (crawlForDirs) {
+        productFiles = dir.listFiles(DIR_FILTER);
+      } else {
+        productFiles = dir.listFiles(FILE_FILTER);
+      }
+
+      for (int j = 0; j < productFiles.length; j++) {
+        fileList.add(productFiles[j]);
+      }
+
+      if (recur) {
+        File[] subdirs = dir.listFiles(DIR_FILTER);
+        if (subdirs != null)
+          for (int j = 0; j < subdirs.length; j++)
+            stack.push(subdirs[j]);
+      }
+    }
+
+    return fileList.toArray(new File[fileList.size()]);
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/DirListNonRecursiveHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/DirListNonRecursiveHandler.java
new file mode 100644
index 0000000..afabb4f
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/DirListNonRecursiveHandler.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.io.File;
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.product.ProductException;
+
+/**
+ * 
+ * Generates a directory listing, without recursing into the OFSN path.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class DirListNonRecursiveHandler extends AbstractCrawlLister {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.OFSNListHandler#getListing(java
+   * .lang.String)
+   */
+  public File[] getListing(String ofsn) throws ProductException {
+     return crawlFiles(new File(ofsn), false, true);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.OFSNListHandler#configure(java.
+   * util.Properties)
+   */
+  public void configure(Properties conf) {
+     // no properties defined yet
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/DirListRecursiveHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/DirListRecursiveHandler.java
new file mode 100644
index 0000000..00dd4ec
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/DirListRecursiveHandler.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.io.File;
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.product.ProductException;
+
+/**
+ * 
+ * Generates a directory listing, recursing into the OFSN path.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class DirListRecursiveHandler extends AbstractCrawlLister {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.AbstractCrawlLister#configure(java
+   * .util.Properties)
+   */
+  @Override
+  public void configure(Properties conf) {
+    // no properties yet
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.AbstractCrawlLister#getListing(
+   * java.lang.String)
+   */
+  @Override
+  public File[] getListing(String ofsn) throws ProductException {
+    return crawlFiles(new File(ofsn), true, true);
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/FileListNonRecursiveHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/FileListNonRecursiveHandler.java
new file mode 100644
index 0000000..2d8cfea
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/FileListNonRecursiveHandler.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.io.File;
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.product.ProductException;
+
+/**
+ *
+ * A non recursive file listing from a given OFSN.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class FileListNonRecursiveHandler extends AbstractCrawlLister {
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.product.handlers.ofsn.OFSNListHandler#configure(java.util.Properties)
+   */
+  @Override
+  public void configure(Properties conf) {
+    // TODO Auto-generated method stub
+    // nothing yet
+
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.product.handlers.ofsn.OFSNListHandler#getListing(java.lang.String)
+   */
+  @Override
+  public File[] getListing(String ofsn) throws ProductException {
+    return crawlFiles(new File(ofsn), false, false);
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/FileListRecursiveHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/FileListRecursiveHandler.java
new file mode 100644
index 0000000..5543494
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/FileListRecursiveHandler.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.io.File;
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.product.ProductException;
+
+/**
+ *
+ * A recursive file listing from the provided ofsn.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class FileListRecursiveHandler extends AbstractCrawlLister {
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.product.handlers.ofsn.AbstractCrawlLister#configure(java.util.Properties)
+   */
+  @Override
+  public void configure(Properties conf) {
+    // TODO Auto-generated method stub
+    // nothing yet
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.product.handlers.ofsn.AbstractCrawlLister#getListing(java.lang.String)
+   */
+  @Override
+  public File[] getListing(String ofsn) throws ProductException {
+    return crawlFiles(new File(ofsn), true, false);
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/MD5GetHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/MD5GetHandler.java
new file mode 100644
index 0000000..595e3de
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/MD5GetHandler.java
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Properties;
+
+//APACHE imports
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.product.ProductException;
+
+/**
+ * 
+ * A {@link OFSNGetHandler} to perform an MD5 for a file on the server side.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class MD5GetHandler implements OFSNGetHandler {
+
+  private MessageDigest md = null;
+
+  public MD5GetHandler() throws InstantiationException {
+    try {
+      this.md = MessageDigest.getInstance("MD5");
+    } catch (NoSuchAlgorithmException e) {
+      e.printStackTrace();
+      throw new InstantiationException(e.getMessage());
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.OFSNListHandler#configure(java.
+   * util.Properties)
+   */
+  public void configure(Properties conf) {
+    // TODO Auto-generated method stub
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.OFSNGetHandler#retrieveChunk(java
+   * .lang.String, long, int)
+   */
+  public byte[] retrieveChunk(String filepath, long offset, int length)
+      throws ProductException {
+    try {
+      String hash = this.hashData(FileUtils.readFileToByteArray(new File(
+          filepath)));
+      byte[] retBytes = new byte[length];
+      byte[] hashBytes = hash.getBytes();      
+      ByteArrayInputStream is = new ByteArrayInputStream(hashBytes);
+      is.skip(offset);
+      is.read(retBytes, 0, length);
+      return retBytes;
+    } catch (IOException e) {
+      e.printStackTrace();
+      throw new ProductException("Error reading bytes from file: [" + filepath
+          + "] MD5: Message: " + e.getMessage());
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.OFSNGetHandler#sizeOf(java.lang
+   * .String)
+   */
+  public long sizeOf(String filepath) {
+    try {
+      String hash = this.hashData(FileUtils.readFileToByteArray(new File(
+          filepath)));
+      return hash.getBytes().length;
+    } catch (IOException e) {
+      e.printStackTrace();
+      return -1;
+    }
+  }
+
+  /**
+   * Use this method ot generate a test MD5 of a provide {@link File} specified
+   * in args[0].
+   * 
+   * @param args
+   *          Only need to specify 1 arg, the full path to the {@link File} to
+   *          MD5.
+   * @throws Exception
+   *           If any error occurs.
+   */
+  public static void main(String[] args) throws Exception {
+    if (args.length != 1) {
+      System.err.println("MD5GetHandler <file>");
+      System.exit(1);
+    }
+
+    String filepath = args[0];
+    String hashString = new MD5GetHandler().hashData(FileUtils
+        .readFileToByteArray(new File(filepath)));
+    System.out.println(hashString);
+  }
+
+  private String hashData(byte[] dataToHash) {
+    this.md.update(dataToHash, 0, dataToHash.length);
+    byte[] hash = this.md.digest();
+    return new String(Hex.encodeHex(hash));
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandler.java
new file mode 100644
index 0000000..1ffd1f7
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandler.java
@@ -0,0 +1,265 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//APACHE imports
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.mime.MimeTypesFactory;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.product.handlers.ofsn.metadata.OFSNMetKeys;
+import org.apache.oodt.product.handlers.ofsn.metadata.OFSNXMLConfigMetKeys;
+import org.apache.oodt.product.handlers.ofsn.metadata.OFSNXMLMetKeys;
+import org.apache.oodt.product.handlers.ofsn.metadata.XMLQueryMetKeys;
+import org.apache.oodt.product.handlers.ofsn.util.OFSNObjectFactory;
+import org.apache.oodt.product.handlers.ofsn.util.OFSNUtils;
+import org.apache.oodt.product.LargeProductQueryHandler;
+import org.apache.oodt.product.ProductException;
+import org.apache.oodt.xmlquery.LargeResult;
+import org.apache.oodt.xmlquery.Result;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+/**
+ * 
+ * An extensible implementation of the PDS-inspired Online File Specification
+ * Name (OFSN) style product server. See the ofsn-ps.xml file for a detailed
+ * specification of the configuration and motivation behind this product
+ * handler.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class OFSNFileHandler implements LargeProductQueryHandler,
+    XMLQueryMetKeys, OFSNXMLMetKeys, OFSNMetKeys, OFSNXMLConfigMetKeys {
+
+  private static final Logger LOG = Logger.getLogger(OFSNFileHandler.class
+      .getName());
+
+  private static final String CMD_SEPARATOR = ";";
+
+  // by default return dir size on listing commands
+  private boolean computeDirSize = true;
+  
+  // by default return file size on listing commands
+  private boolean computeFileSize = true;
+
+  private OFSNFileHandlerConfiguration conf;
+
+  private static Map<String, Object> HANDLER_CACHE;
+
+  public OFSNFileHandler() throws InstantiationException {
+    // init conf here
+    String xmlConfigFilePath = System.getProperty(OFSN_XML_CONF_FILE_KEY);
+    this.computeDirSize = Boolean.getBoolean(OFSN_COMPUTE_DIR_SIZE);
+    this.computeFileSize = Boolean.getBoolean(OFSN_COMPUTE_FILE_SIZE);
+
+
+    if (xmlConfigFilePath == null) {
+      throw new InstantiationException(
+          "Must define xml configuration file path via property : ["
+              + OFSN_XML_CONF_FILE_KEY + "]");
+    }
+
+    try {
+      this.conf = OFSNFileHandlerConfigurationReader
+          .getConfig(xmlConfigFilePath);
+    } catch (FileNotFoundException e) {
+      throw new InstantiationException("xml configuration file: ["
+          + xmlConfigFilePath + "] not found!");
+    }
+
+    if (this.conf.getProductRoot() == null) {
+      throw new InstantiationException(
+          "Must define: [productRoot] attribute in XML configuration!");
+    }
+
+    // used to cache handlers -- map of RT type to Get/List handler instance
+    HANDLER_CACHE = new HashMap<String, Object>();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.product.QueryHandler#query(org.apache.oodt.xmlquery.XMLQuery)
+   */
+  public XMLQuery query(XMLQuery xmlQuery) throws ProductException {
+    String ofsn = OFSNUtils.extractFieldFromQuery(xmlQuery, OFSN);
+    String cmd = OFSNUtils.extractFieldFromQuery(xmlQuery, RETURN_TYPE);
+    validate(ofsn, cmd);
+    String cmdId = ofsn + CMD_SEPARATOR + cmd;
+    OFSNHandlerConfig cfg = this.conf.getHandlerConfig(cmd);
+    validateHandlerConfig(cfg, cmd);
+
+    String realPath = this.conf.getProductRoot() + ofsn;
+
+    if (isListingCmd(cmd)) {
+      ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+      OFSNListHandler handler = getListHandler(cmd, cfg.getClassName());
+      File[] fileList = handler.getListing(realPath);
+      generateOFSNXml(fileList, cfg, outStream);
+      xmlQuery.getResults().add(
+          new Result(cmdId, XML_MIME_TYPE, null, cmdId, Collections.EMPTY_LIST,
+              outStream.toString()));
+    } else if (isGetCmd(cmd)) {
+      OFSNGetHandler handler = getGetHandler(cmd, cfg.getClassName());
+      String rtAndPath = cmd + CMD_SEPARATOR + realPath;
+      String mimeType;
+      
+      // check for and use mimetype conf property if available
+      if (cfg.getHandlerConf().containsKey(PROPERTY_MIMETYPE_ATTR)) {
+    	  MediaType mediaType = MediaType.parse(cfg.getHandlerConf()
+    			  .getProperty(PROPERTY_MIMETYPE_ATTR));
+    	  if (mediaType == null) {
+    		  LOG.log(Level.WARNING, "MIME type ["
+    				  +cfg.getHandlerConf().getProperty(PROPERTY_MIMETYPE_ATTR)+"] specified "
+    				  +"for handler ["+cfg.getClassName()+"] invalid. Defaulting to MIME type ["
+    				  +MediaType.OCTET_STREAM.toString()+"]");
+    		  mediaType = MediaType.OCTET_STREAM;
+    	  }
+    	  mimeType = mediaType.toString();
+      } else { // use default mimetype of product on disk
+          try {
+              mimeType = MimeTypesFactory.create().getMimeType(new File(realPath)).getName();
+          } catch (Exception e) {
+              mimeType = null;
+          }
+      }
+      
+      xmlQuery.getResults().add(
+          new LargeResult(/* id */rtAndPath,/* mimeType */ mimeType, /* profileID */null, 
+        		  /* resourceID */new File(realPath).getName(), Collections.EMPTY_LIST, 
+        		  handler.sizeOf(realPath)));
+    } else {
+      throw new ProductException("return type: [" + cmd + "] is unsupported!");
+    }
+
+    return xmlQuery;
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.product.LargeProductQueryHandler#close(java.lang.String)
+   */
+  public void close(String id) throws ProductException {
+    // nothing to do
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.LargeProductQueryHandler#retrieveChunk(java.lang.String,
+   * long, int)
+   */
+  public byte[] retrieveChunk(String id, long offset, int length)
+      throws ProductException {
+    // unmarshall the return type and path
+    String[] rtTypeAndPathArr = id.split(CMD_SEPARATOR);
+    String rtType = rtTypeAndPathArr[0];
+    String filepath = rtTypeAndPathArr[1];
+
+    OFSNGetHandler handler = getGetHandler(rtType, this.conf
+        .getHandlerClass(rtType));
+    
+    return handler.retrieveChunk(filepath, offset, length);
+  }
+
+  private void generateOFSNXml(File[] mlsFileList, OFSNHandlerConfig cfg,
+      OutputStream outStream) {
+    XMLUtils.writeXmlToStream(OFSNUtils.getOFSNDoc(Arrays.asList(mlsFileList),
+        cfg, this.conf.getProductRoot(), this.computeDirSize, this.computeFileSize),
+        outStream);
+  }
+
+  private void validate(String ofsn, String cmd) throws ProductException {
+    if (ofsn == null || cmd == null || (ofsn != null && ofsn.equals(""))
+        || (cmd != null && cmd.equals(""))) {
+      throw new ProductException("must specify OFSN and RT parameters!");
+    } else if (!OFSNUtils.validateOFSN(ofsn)) {
+      throw new ProductException("OFSN is invalid");
+    }
+  }
+
+  private void validateHandlerConfig(OFSNHandlerConfig cfg, String cmd)
+      throws ProductException {
+    if (cfg == null) {
+      throw new ProductException("Unrecognized command: [" + cmd + "]!");
+    }
+  }
+
+  private OFSNListHandler getListHandler(String rtType, String className) {
+    if (HANDLER_CACHE.containsKey(rtType)) {
+      return (OFSNListHandler) HANDLER_CACHE.get(rtType);
+    } else {
+      OFSNListHandler handler = OFSNObjectFactory.getListHandler(className);
+      LOG.log(Level.INFO, "Getting handler config for RT: ["+rtType+"]");
+      handler.configure(this.conf.getHandlerConfig(rtType).getHandlerConf());
+      HANDLER_CACHE.put(rtType, handler);
+      return handler;
+    }
+  }
+
+  private OFSNGetHandler getGetHandler(String rtType, String className) {
+    if (HANDLER_CACHE.containsKey(rtType)) {
+      return (OFSNGetHandler) HANDLER_CACHE.get(rtType);
+    } else {
+      OFSNGetHandler handler = OFSNObjectFactory.getGetHandler(className);
+      handler.configure(this.conf.getHandlerConfig(rtType).getHandlerConf());
+      HANDLER_CACHE.put(rtType, handler);
+      return handler;
+    }
+  }
+
+  private boolean isListingCmd(String cmd) throws ProductException {
+    OFSNHandlerConfig cfg = this.conf.getHandlerConfig(cmd);
+    if (cfg == null) {
+      throw new ProductException("Unrecognized command: [" + cmd + "]!");
+    }
+
+    if (cfg.getType().equals(LISTING_CMD)) {
+      return true;
+    } else
+      return false;
+  }
+
+  private boolean isGetCmd(String cmd) throws ProductException {
+    OFSNHandlerConfig cfg = this.conf.getHandlerConfig(cmd);
+
+    if (cfg.getType().equals(GET_CMD)) {
+      return true;
+    } else
+      return false;
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandlerConfiguration.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandlerConfiguration.java
new file mode 100644
index 0000000..e663f56
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandlerConfiguration.java
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 
+ * The OFSN product handler's configuration object.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class OFSNFileHandlerConfiguration {
+
+  protected Map<String, OFSNHandlerConfig> handlerTable;
+
+  private String productRoot;
+
+  private String id;
+
+  private String name;
+
+  public OFSNFileHandlerConfiguration(String productRoot, String id, String name) {
+    this.handlerTable = new HashMap<String, OFSNHandlerConfig>();
+    this.productRoot = productRoot;
+    this.id = id;
+    this.name = name;
+    cleanse(this.productRoot);
+  }
+
+  public OFSNFileHandlerConfiguration() {
+    this(null, null, null);
+  }
+
+  public String getHandlerType(String handlerName) {
+    if (this.handlerTable.containsKey(handlerName)) {
+      return this.handlerTable.get(handlerName).getType();
+    } else
+      return null;
+  }
+
+  public String getHandlerClass(String handlerName) {
+    if (this.handlerTable.containsKey(handlerName)) {
+      return this.handlerTable.get(handlerName).getClassName();
+    } else
+      return null;
+  }
+
+  public List<OFSNHandlerConfig> getHandlerConfigs() {
+    return Arrays.asList(this.handlerTable.values().toArray(
+        new OFSNHandlerConfig[this.handlerTable.size()]));
+  }
+
+  public OFSNHandlerConfig getHandlerConfig(String handlerName) {
+    return this.handlerTable.get(handlerName);
+  }
+
+  /**
+   * @return the productRoot
+   */
+  public String getProductRoot() {
+    return productRoot;
+  }
+
+  /**
+   * @param productRoot
+   *          the productRoot to set
+   */
+  public void setProductRoot(String productRoot) {
+    this.productRoot = productRoot;
+    cleanse(this.productRoot);
+  }
+
+  /**
+   * @return the id
+   */
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * @param id
+   *          the id to set
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  private void cleanse(String path) {
+    if (path != null && !path.endsWith("/")) {
+      path += "/";
+    }
+  }
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandlerConfigurationReader.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandlerConfigurationReader.java
new file mode 100644
index 0000000..feeb738
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNFileHandlerConfigurationReader.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.util.Properties;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.product.handlers.ofsn.metadata.OFSNXMLConfigMetKeys;
+
+/**
+ * 
+ * Reads an XML file representation of the {@link OFSNFileHandlerConfiguration}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public final class OFSNFileHandlerConfigurationReader implements
+    OFSNXMLConfigMetKeys {
+
+  public static OFSNFileHandlerConfiguration getConfig(String filePath)
+      throws FileNotFoundException {
+    OFSNFileHandlerConfiguration config = new OFSNFileHandlerConfiguration();
+
+    Document configDoc = XMLUtils.getDocumentRoot(new FileInputStream(new File(
+        filePath)));
+    Element configElem = configDoc.getDocumentElement();
+    config.setId(configElem.getAttribute(OFSN_CFG_ID_ATTR));
+    config.setName(configElem.getAttribute(OFSN_CFG_NAME_ATTR));
+    config.setProductRoot(configElem.getAttribute(OFSN_PRODUCT_ROOT_ATTR));
+    addHandlers(configElem, config);
+    return config;
+  }
+
+  private static void addHandlers(Element configRootElem,
+      OFSNFileHandlerConfiguration config) {
+    NodeList handlerNodes = configRootElem.getElementsByTagName(HANDLER_TAG);
+    for (int i = 0; i < handlerNodes.getLength(); i++) {
+      OFSNHandlerConfig cfg = getHandlerConfig((Element) handlerNodes.item(i));
+      config.handlerTable.put(cfg.getName(), cfg);
+    }
+  }
+
+  private static OFSNHandlerConfig getHandlerConfig(Element handlerNodeElem) {
+    OFSNHandlerConfig cfg = new OFSNHandlerConfig();
+    cfg.setClassName(handlerNodeElem.getAttribute(HANDLER_CLASSNAME_ATTR));
+    cfg.setName(handlerNodeElem.getAttribute(HANDLER_NAME_ATTR));
+    cfg.setType(handlerNodeElem.getAttribute(HANDLER_TYPE_ATTR));
+    cfg.setHandlerConf(readConfig(handlerNodeElem));
+    return cfg;
+  }
+
+  private static Properties readConfig(Element handlerNodeElem) {
+    Properties config = new Properties();
+    NodeList propertyNodes = handlerNodeElem.getElementsByTagName(PROPERTY_TAG);
+
+    if (propertyNodes != null && propertyNodes.getLength() > 0) {
+      for (int j = 0; j < propertyNodes.getLength(); j++) {
+        Element propertyElem = (Element) propertyNodes.item(j);
+        String propertyName = propertyElem.getAttribute(PROPERTY_NAME_ATTR);
+        String propertyValue = propertyElem.getAttribute(PROPERTY_VALUE_ATTR);
+
+        config.setProperty(propertyName, propertyValue);
+      }
+    }
+
+    return config;
+  }
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNGetHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNGetHandler.java
new file mode 100644
index 0000000..5638a21
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNGetHandler.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.product.ProductException;
+
+/**
+ * 
+ * The default OFSN handler for getting remote data.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface OFSNGetHandler {
+
+  /**
+   * Retrieves a chunk of data from the remote file.
+   * 
+   * @param filepath
+   *          The path to the remote file.
+   * @param offset
+   *          The offset in the remote data to retrieve.
+   * @param length
+   *          The length of data to read
+   * @return The byte[] data, read, or null otherwise.
+   * @throws ProductException
+   *           If any error occurs.
+   */
+  public byte[] retrieveChunk(String filepath, long offset, int length)
+      throws ProductException;
+
+  /**
+   * Returns the size of the remote data, which may be the entire file in
+   * question, or some subset/transformation on it.
+   * 
+   * @param filepath
+   *          The remote file in question.
+   * @return The size of the remote file, potentially after a remote
+   *         transformation has occured.
+   */
+  public long sizeOf(String filepath);
+
+  /**
+   * Configures this handler with the provided configuration stored in a
+   * {@link Properties} object.
+   * 
+   * @param conf
+   *          The configuration for this list handler.
+   */
+  public void configure(Properties conf);
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNHandlerConfig.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNHandlerConfig.java
new file mode 100644
index 0000000..8c8aa18
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNHandlerConfig.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.util.Properties;
+
+/**
+ * 
+ * A configuration element in the XML config file for the OFSN handler.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class OFSNHandlerConfig {
+
+  private String className;
+
+  private String type;
+
+  private String name;
+  
+  private Properties handlerConf;
+
+  /**
+   * @param className
+   * @param type
+   * @param name
+   */
+  public OFSNHandlerConfig(String className, String type, String name) {
+    super();
+    this.className = className;
+    this.type = type;
+    this.name = name;
+    this.handlerConf = new Properties();
+  }
+
+  /**
+   * 
+   */
+  public OFSNHandlerConfig() {
+    super();
+  }
+
+  /**
+   * @return the className
+   */
+  public String getClassName() {
+    return className;
+  }
+
+  /**
+   * @param className
+   *          the className to set
+   */
+  public void setClassName(String className) {
+    this.className = className;
+  }
+
+  /**
+   * @return the type
+   */
+  public String getType() {
+    return type;
+  }
+
+  /**
+   * @param type
+   *          the type to set
+   */
+  public void setType(String type) {
+    this.type = type;
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return the handlerConf
+   */
+  public Properties getHandlerConf() {
+    return handlerConf;
+  }
+
+  /**
+   * @param handlerConf the handlerConf to set
+   */
+  public void setHandlerConf(Properties handlerConf) {
+    this.handlerConf = handlerConf;
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNListHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNListHandler.java
new file mode 100644
index 0000000..72c24d3
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/OFSNListHandler.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.io.File;
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.product.ProductException;
+
+/**
+ * <p>
+ * Classes that implement this interface define how to return file listings on a
+ * remote server from an <code>ofsn</code>.
+ * </p>
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface OFSNListHandler {
+
+  /**
+   * Handlers that implement this method take an <code>O</code>nline
+   * <code>F</code>ile <code>S</code>pecification <code>N</code>ame and return
+   * back a listing of files on the remote server.
+   * 
+   * @param ofsn
+   *          The OFSN path to list files from.
+   * @return An array of {@link File} objects.
+   * @throws ProductException
+   *           If any error occurs performing the listing on the server side.
+   */
+  public File[] getListing(String ofsn) throws ProductException;
+
+  /**
+   * Configures this handler with the provided configuration stored in a
+   * {@link Properties} object.
+   * 
+   * @param conf
+   *          The configuration for this list handler.
+   */
+  public void configure(Properties conf);
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/RawSizeListHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/RawSizeListHandler.java
new file mode 100644
index 0000000..883e1b5
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/RawSizeListHandler.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.io.File;
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.product.ProductException;
+
+/**
+ *
+ * Handles a listing request for the raw size of a file. This listing
+ * returns a single file or directory, which will then have its size
+ * computed.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class RawSizeListHandler implements OFSNListHandler {
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.product.handlers.ofsn.OFSNListHandler#configure(java.util.Properties)
+   */
+  public void configure(Properties conf) {
+    // TODO Auto-generated method stub
+    // nothing yet
+
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.product.handlers.ofsn.OFSNListHandler#getListing(java.lang.String)
+   */
+  public File[] getListing(String ofsn) throws ProductException {
+    if (!new File(ofsn).exists()) {
+          throw new ProductException("file: [" + ofsn
+                  + "] does not exist!");
+      }
+      return new File[] { new File(ofsn) };
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/SingleFileListHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/SingleFileListHandler.java
new file mode 100644
index 0000000..45d559c
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/SingleFileListHandler.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.io.File;
+import java.util.Properties;
+
+import org.apache.oodt.product.ProductException;
+
+/**
+ * 
+ * Returns a single remote file listing of the given ofsn.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class SingleFileListHandler implements OFSNListHandler {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.OFSNListHandler#configure(java.
+   * util.Properties)
+   */
+  public void configure(Properties conf) {
+    // TODO Auto-generated method stub
+    // nothing yet
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.OFSNListHandler#getListing(java
+   * .lang.String)
+   */
+  public File[] getListing(String ofsn) throws ProductException {
+    if (!new File(ofsn).exists()) {
+      throw new ProductException("file: [" + ofsn + "] does not exist!");
+    }
+    return new File[] { new File(ofsn) };
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/SingleZipFileListHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/SingleZipFileListHandler.java
new file mode 100644
index 0000000..748a534
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/SingleZipFileListHandler.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//OODT imports
+import org.apache.oodt.product.handlers.ofsn.util.OFSNUtils;
+import org.apache.oodt.product.ProductException;
+
+//JDK imports
+import java.io.File;
+import java.util.Properties;
+
+
+/**
+ * 
+ * Generates a listing of the size of a remote file identified by its OFSN as a
+ * zip would be.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class SingleZipFileListHandler implements OFSNListHandler {
+
+  private String cacheRoot;
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.OFSNListHandler#configure(java.
+   * util.Properties)
+   */
+  public void configure(Properties conf) {
+    // TODO Auto-generated method stub
+
+    this.cacheRoot = conf.getProperty("cacheDirRoot");
+
+    if (this.cacheRoot == null) {
+      this.cacheRoot = "/tmp";
+    }
+
+    if (!this.cacheRoot.endsWith("/")) {
+      this.cacheRoot += "/";
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.OFSNListHandler#getListing(java
+   * .lang.String)
+   */
+  public File[] getListing(String ofsn) throws ProductException {
+    if (!new File(ofsn).exists()) {
+      throw new ProductException("file: [" + ofsn + "] does not exist!");
+    }
+
+    String zipFilePath = this.cacheRoot + new File(ofsn).getName() + ".zip";
+    File zipFile = OFSNUtils.buildZipFile(zipFilePath, new File[] { new File(
+        ofsn) });
+    return new File[] { zipFile };
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/StdOFSNGetHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/StdOFSNGetHandler.java
new file mode 100644
index 0000000..2a56cf1
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/StdOFSNGetHandler.java
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.product.ProductException;
+
+/**
+ * 
+ * Standard way of retrieving a file without performing 
+ * any transformation on it.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class StdOFSNGetHandler implements OFSNGetHandler {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.OFSNGetHandler#retrieveChunk(java
+   * .lang.String, long, int)
+   */
+  public byte[] retrieveChunk(String filepath, long offset, int length)
+      throws ProductException {
+    InputStream in = null;
+    byte[] buf = null;
+
+    try {
+      in = new FileInputStream(new File(filepath));
+
+      buf = new byte[length];
+      int numRead;
+      long numSkipped;
+      numSkipped = in.skip(offset);
+      if (numSkipped != offset) {
+        throw new ProductException("Was not able to skip: [" + offset
+            + "] bytes into product: num actually skipped: [" + numSkipped
+            + "]");
+      }
+
+      numRead = in.read(buf, 0, length);
+
+      if (numRead != length) {
+        throw new ProductException("Was not able to read: [" + length
+            + "] bytes from product: num actually read: [" + numRead + "]");
+      }
+    } catch (IOException e) {
+      e.printStackTrace();
+      throw new ProductException("IO exception retrieving chunk of product: ["
+          + filepath + "]: Message: " + e.getMessage());
+    } finally {
+      if (in != null) {
+        try {
+          in.close();
+        } catch (Exception ignore) {
+        }
+
+        in = null;
+      }
+    }
+
+    return buf;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.product.handlers.ofsn.OFSNGetHandler#sizeOf(java.lang
+   * .String)
+   */
+  public long sizeOf(String filepath) {
+     return new File(filepath).length();
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.product.handlers.ofsn.OFSNGetHandler#configure(java.util.Properties)
+   */
+  public void configure(Properties conf) {
+    // no properties to configure    
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/URLGetHandler.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/URLGetHandler.java
new file mode 100644
index 0000000..f5e5dab
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/URLGetHandler.java
@@ -0,0 +1,252 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn;
+
+//JDK imports
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.product.ProductException;
+import org.apache.oodt.product.handlers.ofsn.AbstractCrawlLister;
+import org.apache.oodt.product.handlers.ofsn.OFSNGetHandler;
+
+/**
+  * A {@link OFSNGetHandler} for returning a URL listing pointing to files within an OFSN
+ * 
+ * NOTE: Configuration parameters for this class include:
+ * 1. Server hostname
+ * 2. Server port
+ * 3. Webapp context-root
+ * 4. Path to product-root
+ * 5. Return type desired for URLs
+ * 
+ * @author rverma
+ * @version $Revision$
+ *
+ */
+public class URLGetHandler extends AbstractCrawlLister implements OFSNGetHandler {
+
+	Logger LOG = Logger.getLogger(URLGetHandler.class.getName());
+	
+	// Constants
+	private static final String PROD_SERVER_HOSTNAME = "prodServerHostname";
+	private static final String PROD_SERVER_PORT = "prodServerPort";
+	private static final String PROD_SERVER_CONTEXT = "prodServerContextRoot";
+	private static final String PRODUCT_ROOT = "productRoot";
+	private static final String RETURN_TYPE = "returnType";
+	
+	protected static final String DEFAULT_RETURN_VALUE="";
+	protected static final String DEFAULT_PROD_SERVER_HOSTNAME = "localhost";
+	protected static final String DEFAULT_PROD_SERVER_PORT = "8080";
+	protected static final String DEFAULT_PROD_SERVER_CONTEXT = "web-grid";
+	protected static final String DEFAULT_PRODUCT_ROOT = "/some/path";
+	protected static final String DEFAULT_RETURN_TYPE = "RAW";
+	
+	// Instance
+	private String prodServerHostname = new String();
+	private String prodServerPort = new String();
+	private String prodServerContext = new String();
+	private String productRoot = new String();	
+	private String returnType = new String();
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.apache.oodt.product.handlers.ofsn.AbstractCrawlLister#configure(java.util.Properties)
+	 */
+	public void configure(Properties prop) {
+		
+		if (prop != null) {
+			if (prop.getProperty(PROD_SERVER_HOSTNAME) != null)
+				this.prodServerHostname = prop.getProperty(PROD_SERVER_HOSTNAME);
+			else { 
+				LOG.warning("Configuration property ["+PROD_SERVER_HOSTNAME+"] not specified, using default");
+				this.prodServerHostname = DEFAULT_PROD_SERVER_HOSTNAME;
+			}
+			LOG.info("Property ["+PROD_SERVER_HOSTNAME+"] set with value ["+this.prodServerHostname+"]");
+			
+			if (prop.getProperty(PROD_SERVER_PORT) != null)
+				this.prodServerPort = prop.getProperty(PROD_SERVER_PORT);
+			else { 
+				LOG.warning("Configuration property ["+PROD_SERVER_PORT+"] not specified, using default");
+				this.prodServerPort = DEFAULT_PROD_SERVER_PORT;
+			}
+			LOG.info("Property ["+PROD_SERVER_PORT+"] set with value ["+this.prodServerPort+"]");
+			
+			if (prop.getProperty(PROD_SERVER_CONTEXT) != null)
+				this.prodServerContext = prop.getProperty(PROD_SERVER_CONTEXT);		
+			else { 
+				LOG.warning("Configuration property ["+PROD_SERVER_CONTEXT+"] not specified, using default");
+				this.prodServerContext = DEFAULT_PROD_SERVER_CONTEXT;
+			}
+			LOG.info("Property ["+PROD_SERVER_CONTEXT+"] set with value ["+this.prodServerContext+"]");
+			
+			if (prop.getProperty(PRODUCT_ROOT) != null)
+				this.productRoot = prop.getProperty(PRODUCT_ROOT);		
+			else { 
+				LOG.warning("Configuration property ["+PRODUCT_ROOT+"] not specified, using default");
+				this.productRoot = DEFAULT_PRODUCT_ROOT;
+			}
+			LOG.info("Property ["+PRODUCT_ROOT+"] set with value ["+this.productRoot+"]");
+			
+			if (prop.getProperty(RETURN_TYPE) != null)
+				this.returnType = prop.getProperty(RETURN_TYPE);
+			else { 
+				LOG.warning("Configuration property ["+RETURN_TYPE+"] not specified, using default");
+				this.returnType = DEFAULT_RETURN_TYPE;
+			}
+			LOG.info("Property ["+RETURN_TYPE+"] set with value ["+this.returnType+"]");
+			
+		} else {
+			LOG.warning("Configuration properties could not be loaded");
+		}
+		
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.apache.oodt.product.handlers.ofsn.OFSNGetHandler#retrieveChunk(java.lang.String, long, int)
+	 */
+	public byte[] retrieveChunk(String filepath, long offset, int length)
+			throws ProductException {
+	  
+		LOG.info("Retrieving chunk of URL listing for path: ["+filepath+"] at offset "
+	    			+ offset+" for "+length+" bytes");
+
+		String urlListing = DEFAULT_RETURN_VALUE;
+		try {
+			urlListing = getURLListing(filepath);
+		} catch (ProductException e) {
+			LOG.warning("Unable to obtain byte chunk ("+offset+" - "+(offset+length)+") " 
+					+ "for filepath listing ["+filepath+"]");
+			LOG.warning(e.getMessage());
+		} catch (IllegalArgumentException e) {
+			LOG.warning("Unable to obtain byte chunk ("+offset+" - "+(offset+length)+") " 
+					+ "for filepath listing ["+filepath+"]");
+			LOG.warning(e.getMessage());
+		}
+		
+        // Convert listing to bytes
+        byte[] retBytes = new byte[length];
+        byte[] metBytes = urlListing.getBytes();      
+        ByteArrayInputStream is = new ByteArrayInputStream(metBytes);
+        is.skip(offset);
+        is.read(retBytes, 0, length);
+        
+        return retBytes;
+	}
+
+	/**
+	 * Returns a new-line separated list of URLs for all files located under the given filepath
+	 * 
+	 * @param filePath the absolute path to a root-directory to get a product listing for
+	 * @return a string containing a new-line separated list of URLs
+	 * @throws ProductException
+	 */
+	private String getURLListing(String filePath) throws ProductException, 
+			IllegalArgumentException {     
+		
+		// crawl and collect all files (including within subdirs) under filepath
+		File[] fileListing = getListing(filePath);
+		 
+		// convert each crawled file's path into an OFSN download link
+		StringBuilder stringBuilder = new StringBuilder();
+		for (int i=0; i < fileListing.length; i++) {
+			File file = (File) fileListing[i];
+			stringBuilder.append(buildOFSNURL(file).toString());
+			stringBuilder.append("\n");
+		}
+		
+    	return stringBuilder.toString();
+	}
+	
+	/**
+	 * Returns a URL object representing the URL associated with this particular product file.
+	 * 
+	 * The URL is defined to have items such as: hostname, server port, server context root,
+	 * and return type configured based upon a product server configuration file
+	 * 
+	 * @param file the product file
+	 * @return a URL
+	 */
+	private URL buildOFSNURL(File file) {
+		URL url = null;
+		
+		String fileRelativePath = file.getAbsolutePath().substring(this.productRoot.length());
+		
+		// construct a URL for the file, optionally using a port if available
+		String ofsnPath;
+		if (this.prodServerPort != null) {
+			if (!this.prodServerPort.isEmpty()) {
+				ofsnPath = "http://" + this.prodServerHostname 
+				+ ":" + this.prodServerPort + "/" + this.prodServerContext 
+				+ "/prod?q=OFSN=" + fileRelativePath + "+AND+RT%3D" + this.returnType;
+			} else {
+				ofsnPath = "http://" + this.prodServerHostname 
+				+ "/" + this.prodServerContext + "/prod?q=OFSN=" + fileRelativePath 
+				+ "+AND+RT%3D" + this.returnType;
+			}
+		} else {
+			ofsnPath = "http://" + this.prodServerHostname 
+			+ "/" + this.prodServerContext + "/prod?q=OFSN=" + fileRelativePath 
+			+ "+AND+RT%3D" + this.returnType;
+		}
+		
+		try {
+			url = new URL(ofsnPath);
+		} catch (MalformedURLException e) {
+			LOG.warning(e.getMessage());
+		}
+		
+		return url;
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.apache.oodt.product.handlers.ofsn.OFSNGetHandler#sizeOf(java.lang.String)
+	 */
+	public long sizeOf(String filepath) {
+		String urlListing = DEFAULT_RETURN_VALUE;
+		try {
+			urlListing = getURLListing(filepath);
+		} catch (ProductException e) {
+			LOG.warning("Unable to obtain size information for filepath listing ["+filepath+"]");
+			LOG.warning(e.getMessage());
+		} catch (IllegalArgumentException e) {
+			LOG.warning("Unable to obtain size information for filepath listing ["+filepath+"]");
+			LOG.warning(e.getMessage());
+		}
+		
+		return urlListing.getBytes().length;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.apache.oodt.product.handlers.ofsn.AbstractCrawlLister#getListing(java.lang.String)
+	 */
+	public File[] getListing(String filePath) throws ProductException, 
+			IllegalArgumentException {
+		return crawlFiles(new File(filePath), true, false);
+	} 
+
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNMetKeys.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNMetKeys.java
new file mode 100644
index 0000000..91be3f8
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNMetKeys.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn.metadata;
+
+/**
+ * Met keys for use in OFSN handler definition.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface OFSNMetKeys {
+
+  public static final String LISTING_CMD = "listing";
+
+  public static final String GET_CMD = "get";
+  
+  public static final String OFSN_XML_CONF_FILE_KEY = "org.apache.oodt.product.handlers.ofsn.xmlConfigFilePath";
+  
+  public static final String OFSN_COMPUTE_DIR_SIZE = "org.apache.oodt.product.handlers.ofsn.computeDirSize";
+  
+  public static final String OFSN_COMPUTE_FILE_SIZE = "org.apache.oodt.product.handlers.ofsn.computeFileSize";
+
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNXMLConfigMetKeys.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNXMLConfigMetKeys.java
new file mode 100644
index 0000000..065ced4
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNXMLConfigMetKeys.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn.metadata;
+
+// OODT imports
+import org.apache.oodt.product.handlers.ofsn.OFSNFileHandlerConfigurationReader; //javadoc
+
+/**
+ * 
+ * Met Keys for the {@link OFSNFileHandlerConfigurationReader}
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface OFSNXMLConfigMetKeys {
+
+  public static final String OFSN_CFG_ID_ATTR = "id";
+
+  public static final String OFSN_CFG_NAME_ATTR = "name";
+
+  public static final String OFSN_PRODUCT_ROOT_ATTR = "productRoot";
+
+  public static final String HANDLER_TAG = "handler";
+
+  public static final String HANDLER_CLASSNAME_ATTR = "class";
+
+  public static final String HANDLER_NAME_ATTR = "name";
+
+  public static final String HANDLER_TYPE_ATTR = "type";
+
+  public static final String PROPERTY_TAG = "property";
+
+  public static final String PROPERTY_NAME_ATTR = "name";
+
+  public static final String PROPERTY_VALUE_ATTR = "value";
+  
+  /* optional handler property attributes supported by all handlers */
+  public static final String PROPERTY_MIMETYPE_ATTR = "mimeType"; 
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNXMLMetKeys.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNXMLMetKeys.java
new file mode 100644
index 0000000..a694c97
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OFSNXMLMetKeys.java
@@ -0,0 +1,43 @@
+
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn.metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public interface OFSNXMLMetKeys {
+    
+    public static final String DIR_RESULT_TAG = "dirResult";
+    
+    public static final String DIR_ENTRY_TAG = "dirEntry";
+    
+    public static final String OFSN_TAG = "OFSN";
+    
+    public static final String FILE_SIZE_TAG = "fileSize";
+    
+    public static final String XML_MIME_TYPE = "text/xml";
+    
+    // FIXME: change namespace URI?
+    public static final String DIR_LISTING_NS = "http://oodt.jpl.nasa.gov/xml/namespaces/dirlist/1.0";
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OODTMetKeys.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OODTMetKeys.java
new file mode 100644
index 0000000..777faf5
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/OODTMetKeys.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn.metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public interface OODTMetKeys {
+    
+    public static final String XMLQUERY_QUERYELEM_ROLE_ELEM = "elemName";
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/XMLQueryMetKeys.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/XMLQueryMetKeys.java
new file mode 100644
index 0000000..ff55105
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/metadata/XMLQueryMetKeys.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn.metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public interface XMLQueryMetKeys {
+    
+    public static final String OFSN = "OFSN";
+    
+    public static final String RETURN_TYPE = "RT";
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/util/OFSNObjectFactory.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/util/OFSNObjectFactory.java
new file mode 100644
index 0000000..da7e029
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/util/OFSNObjectFactory.java
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn.util;
+
+//OODT imports
+import org.apache.oodt.product.handlers.ofsn.OFSNGetHandler;
+import org.apache.oodt.product.handlers.ofsn.OFSNListHandler;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * 
+ * The Object factory to use in the OFSN product server.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public final class OFSNObjectFactory {
+
+  private static final Logger LOG = Logger.getLogger(OFSNObjectFactory.class
+      .getName());
+
+  /**
+   * <p>
+   * Constructs a new {@link OFSNListHandler} from the specified
+   * <code>className</code>.
+   * </p>
+   * 
+   * @param className
+   *          The class name of the OFSNListHandler object to create.
+   * @return A newly constructed {@link OFSNListHandler} object.
+   */
+  public static OFSNListHandler getListHandler(String className) {
+    try {
+      Class<OFSNListHandler> listHandler = (Class<OFSNListHandler>) Class
+          .forName(className);
+      return listHandler.newInstance();
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading list handler class " + className
+              + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading list handler class " + className
+              + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading list handler class " + className
+              + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+
+  /**
+   * <p>
+   * Constructs a new {@link OFSNGetHandler} from the specified
+   * <code>className</code>.
+   * </p>
+   * 
+   * @param className
+   *          The class name of the OFSNGetHandler object to create.
+   * @return A newly constructed {@link OFSNGetHandler} object.
+   */
+  public static OFSNGetHandler getGetHandler(String className) {
+    try {
+      Class<OFSNGetHandler> getHandler = (Class<OFSNGetHandler>) Class
+          .forName(className);
+      return getHandler.newInstance();
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading get handler class " + className
+              + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading get handler class " + className
+              + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading get handler class " + className
+              + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/util/OFSNUtils.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/util/OFSNUtils.java
new file mode 100644
index 0000000..fbf335f
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/product/handlers/ofsn/util/OFSNUtils.java
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn.util;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.product.handlers.ofsn.OFSNHandlerConfig;
+import org.apache.oodt.product.handlers.ofsn.metadata.OFSNMetKeys;
+import org.apache.oodt.product.handlers.ofsn.metadata.OFSNXMLMetKeys;
+import org.apache.oodt.product.handlers.ofsn.metadata.OODTMetKeys;
+import org.apache.oodt.xmlquery.QueryElement;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+//APACHE imports
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+
+/**
+ * 
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public final class OFSNUtils implements OODTMetKeys, OFSNXMLMetKeys,
+    OFSNMetKeys {
+
+  public static String extractFieldFromQuery(XMLQuery query, String name) {
+    for (Iterator<QueryElement> i = query.getWhereElementSet().iterator(); i
+        .hasNext();) {
+      QueryElement element = i.next();
+      if (element.getRole().equals(XMLQUERY_QUERYELEM_ROLE_ELEM)
+          && element.getValue().equalsIgnoreCase(name)) {
+        // get the next element and ensure that it is a LITERAL, and
+        // return that
+        QueryElement litElement = i.next();
+        return litElement.getValue();
+      }
+    }
+
+    return null;
+  }
+
+  public static Document getOFSNDoc(List<File> fileList, OFSNHandlerConfig cfg,
+      String productRoot, boolean showDirSize, boolean showFileSize) {
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    factory.setNamespaceAware(true);
+    Document document = null;
+
+    try {
+      DocumentBuilder builder = factory.newDocumentBuilder();
+      document = builder.newDocument();
+
+      Element root = (Element) document.createElement(DIR_RESULT_TAG);
+      XMLUtils.addAttribute(document, root, "xmlns", DIR_LISTING_NS);
+      document.appendChild(root);
+
+      for (File file : fileList) {
+        Element dirEntryElem = XMLUtils.addNode(document, root, DIR_ENTRY_TAG);
+        String ofsn = toOFSN(file.getAbsolutePath(), productRoot);
+        //This ensures that we get ofsn names with unix style separators.
+        //On a Windows machine, the product server would return '\'
+        //separators.
+        String unixStyleOFSN = FilenameUtils.separatorsToUnix(ofsn);
+        if (cfg.getType().equals(LISTING_CMD)) {
+          if (!Boolean.valueOf(cfg.getHandlerConf().getProperty("isSizeCmd"))) {
+            XMLUtils.addNode(document, dirEntryElem, OFSN_TAG, unixStyleOFSN);
+          }
+        }
+
+        long size = Long.MIN_VALUE;
+
+        if (file.isDirectory()) {
+          if (showDirSize) {
+            size = FileUtils.sizeOfDirectory(file);
+          }
+        } else {
+          if (showFileSize) {
+            size = file.length();
+          }
+        }
+
+        if (size != Long.MIN_VALUE) {
+          XMLUtils.addNode(document, dirEntryElem, FILE_SIZE_TAG, String
+              .valueOf(size));
+        }
+      }
+
+      return document;
+    } catch (ParserConfigurationException e) {
+      e.printStackTrace();
+      return null;
+    }
+
+  }
+
+  public static String relativeize(String path, String productRoot) {
+    return productRoot + (path.startsWith("/") ? path.substring(1) : path);
+  }
+
+  public static File buildZipFile(String zipFileFullPath, File[] files) {
+    // Create a buffer for reading the files
+    byte[] buf = new byte[1024];
+    ZipOutputStream out = null;
+
+    try {
+      // Create the ZIP file
+      out = new ZipOutputStream(new FileOutputStream(zipFileFullPath));
+
+      for (File file : files) {
+        FileInputStream in = new FileInputStream(file);
+
+        // Add ZIP entry to output stream.
+        out.putNextEntry(new ZipEntry(file.getName()));
+
+        // Transfer bytes from the file to the ZIP file
+        int len;
+        while ((len = in.read(buf)) > 0) {
+          out.write(buf, 0, len);
+        }
+
+        // Complete the entry
+        out.closeEntry();
+        in.close();
+      }
+    } catch (IOException e) {
+      e.printStackTrace();
+    } finally {
+      if (out != null) {
+        try {
+          out.close();
+        } catch (Exception ignore) {
+        }
+
+        out = null;
+      }
+    }
+
+    return new File(zipFileFullPath);
+
+  }
+
+  public static boolean validateOFSN(String ofsn) {
+      if (ofsn == null) {
+          return false;
+      } else {
+          return !ofsn.equals("") && !ofsn.matches(".*\\.\\..*");
+      }
+  }
+  
+  private static String toOFSN(String absolutePath, String productRootPath) {
+    if (absolutePath.startsWith(productRootPath)) {
+      return absolutePath.substring(productRootPath.length());
+    } else {
+      // must have been a *.zip file, generated in some cache dir
+      // just return the file name
+      return new File(absolutePath).getName();
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/xmlquery/ChunkedProductInputStream.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/xmlquery/ChunkedProductInputStream.java
new file mode 100644
index 0000000..8988f8d
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/xmlquery/ChunkedProductInputStream.java
@@ -0,0 +1,204 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import org.apache.oodt.product.ProductException;
+import org.apache.oodt.product.Retriever;
+
+/**
+ * Streamer for chunked products.
+ *
+ * This streamer starts a background thread to repeatedly read chunks of a product into a
+ * bounded buffer.  Reads read from chunks in the buffer.
+ *
+ * @author Kelly
+ * @version $Revision: 1.5 $
+ */
+final class ChunkedProductInputStream extends InputStream {
+	/**
+	 * Creates a new <code>ChunkedProductInputStream</code> instance.
+	 *
+	 * @param id Product ID.
+	 * @param retriever Retriever to use.
+	 * @param size How big the product is.
+	 */
+	ChunkedProductInputStream(String id, Retriever retriever, long size) {
+		this.id = id;							       // Save product ID
+		this.size = size;						       // Save size
+		this.retriever = retriever;					       // And the retriever used to get chunks
+		open = true;							       // Start out open
+		eof = false;                                                           // And not yet reached EOF, even if size=0
+	}
+
+
+	/**
+	 * Read a single byte.
+	 *
+	 * This method reads from a chunk stored in the bounded buffer.  It may block if
+	 * there are no more blocks in the buffer.
+	 *
+	 * @return Byte, or -1 if at end of file.
+	 * @throws IOException if an error occurs.
+	 */
+	public int read() throws IOException {
+		checkOpen();                                                           // Make sure the stream's open
+		if (eof) throw new IOException("End of file");			       // Already reached EOF?  You lose.
+		fetchBlock();							       // Get a block.
+		if (eof) return -1;						       // No more blocks?  Signal EOF.
+		return block[blockIndex++];					       // Yield next byte (promoted) from block.
+	}
+
+	/**
+	 * Read into an array.
+	 *
+	 * This method reads from a chunk stored in the bounded buffer.  It may block if
+	 * there are no more blocks in the buffer.
+	 *
+	 * @param b a <code>byte[]</code> value.
+	 * @param offset Where in <var>b</var> to save read bytes.
+	 * @param length How many bytes to try to read.
+	 * @return Number of bytes actually read, or -1 at end of file.
+	 * @throws IOException if an error occurs.
+	 */
+	public int read(byte[] b, int offset, int length) throws IOException {
+		checkOpen();							       // Check if open
+		if (offset < 0 || offset > b.length || length < 0 || (offset + length) > b.length || (offset + length) < 0)
+			throw new IllegalArgumentException("Illegal offset=" + offset + "/length=" + length
+				+ " for byte array of length " + b.length);
+		else if (length == 0)						       // Want zero?
+			return 0;						       // Then you get zero
+		if (eof) throw new IOException("End of file");			       // Already reached EOF?  You lose.
+		fetchBlock();							       // Get a block.
+		if (eof) return -1;						       // No more blocks?  Signal EOF.
+		int amount = Math.min(length, block.length - blockIndex);	       // Return requested amount or whatever's left
+		System.arraycopy(block, blockIndex, b, offset, amount);		       // Transfer
+		blockIndex += amount;						       // Advance
+		return amount;							       // Done
+	}
+
+	/**
+	 * Fetch another block.
+	 *
+	 * @throws IOException if an error occurs.
+	 */
+	private void fetchBlock() throws IOException {
+		if (block == null || blockIndex == block.length) try {		       // No block, or current block exhausted?
+			if (productIndex == size) {				       // No more blocks left to get?
+				block = null;					       // Drop current block
+				eof = true;					       // Signal EOF
+			} else {						       // Otherwise there are more blocks
+				int x=(int)Math.min(BLOCK_SIZE, size - productIndex);  // Can only fetch so much
+				block = retriever.retrieveChunk(id, productIndex, x);  // Get x's worth of data
+				blockIndex = 0;					       // Start at block's beginning
+				productIndex += block.length;			       // Advance product index by block size
+			}
+		} catch (ProductException ex) {
+			throw new IOException(ex.getMessage());
+		}
+	}
+
+	/**
+	 * Return number of bytes currently available.
+	 *
+	 * If we have a block, the amount of available bytes is whatever's in the block.
+	 * Otherwise we don't know how many bytes, and we could block, so say zero are available.
+	 *
+	 * @return an <code>int</code> value.
+	 * @throws IOException if an error occurs.
+	 */
+	public int available() throws IOException {
+		checkOpen();							       // Open?
+		return block == null? 0 : block.length - blockIndex;		       // If no current block, you can only get 0
+	}
+
+	public void close() throws IOException {
+		checkOpen();							       // Open?
+		try {
+			retriever.close(id);					       // Tell retriever we're done
+			open = false;						       // Flag it
+		} catch (ProductException ex) {
+			throw new IOException(ex.getMessage());
+		}
+	}
+
+	/**
+	 * Mark is not supported.
+	 *
+	 * @param limit Unused parameter.
+	 */
+	public void mark(int limit) {
+		throw new UnsupportedOperationException("Mark not supported");
+	}
+
+	/**
+	 * Reset is not supported.
+	 */
+	public void reset() {
+		throw new UnsupportedOperationException("Reset not supported");
+	}
+
+	/**
+	 * Mark/reset operations are not supported.
+	 *
+	 * @return False.
+	 */
+	public boolean markSuppoted() {
+		return false;
+	}
+	
+	/**
+	 * Throw an exception if the stream's closed.
+	 *
+	 * @throws IOException if the stream's closed.
+	 */
+	private final void checkOpen() throws IOException {
+		if (open) return;
+		throw new IOException("Stream closed");
+	}
+
+	/** Product ID. */
+	private String id;
+
+	/** What can retrieve the product. */
+	private Retriever retriever;
+
+	/** How big the product is. */
+	private long size;
+
+	/** Current block or null if there's no current block. */
+	private byte[] block;
+
+	/** From where in <code>block</code> to read. */
+	private int blockIndex;
+
+	/** From where in the product to read the next block. */
+	private long productIndex = 0L;
+
+	/** True if we got to the end of file. */
+	private boolean eof;
+	
+	/** Is the stream open? */
+	private boolean open;
+
+	/** Size of chunks. */
+	private static final int BLOCK_SIZE = Integer.getInteger("org.apache.oodt.xmlquery.blockSize", 4096).intValue();
+}
diff --git a/0.8.1-rc1/product/src/main/java/org/apache/oodt/xmlquery/LargeResult.java b/0.8.1-rc1/product/src/main/java/org/apache/oodt/xmlquery/LargeResult.java
new file mode 100644
index 0000000..efc6102
--- /dev/null
+++ b/0.8.1-rc1/product/src/main/java/org/apache/oodt/xmlquery/LargeResult.java
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.util.List;
+import java.util.StringTokenizer;
+import org.apache.oodt.product.Retriever;
+import java.io.InputStream;
+import java.io.IOException;
+
+// FIXME: change MIME type application/vnd.jpl.large-product?
+
+/**
+ * A <em>large</em> result is a result for <em>large</em> products.
+ *
+ * What is large?  Some might say large is something that exceeds most other things of
+ * like kind in bulk, capacity, quantity, superficial dimensions, or number of constituent
+ * units.  Large might be big, great, capacious, extensive.  Large might be opposed to
+ * small; as, a large horse; a large house or room; a large lake or pool; a large jug or
+ * spoon; a large vineyard; a large army; a large city.  Some might say that particularly
+ * if they're named Webster.
+ *
+ * @author Kelly
+ * @version $Revision: 1.2 $
+ */
+public class LargeResult extends Result {
+	/**
+	 * Creates a new <code>LargeResult</code> instance.
+	 *
+	 * @param result a <code>Result</code> value.
+	 */
+	public LargeResult(Result result) {
+		super(result.getID(), "application/vnd.jpl.large-product", result.getProfileID(), result.getResourceID(),
+			result.getHeaders(), transformMimeType(result));
+		StringTokenizer st = new StringTokenizer((String) value);
+		st.nextToken();
+		this.size = Long.parseLong(st.nextToken());
+	}
+
+	/**
+	 * Creates a new <code>LargeResult</code> instance.
+	 *
+	 * @param id Result ID.
+	 * @param mimeType MIME type.
+	 * @param profileID Profile ID.
+	 * @param resourceID Resource ID.
+	 * @param headers Headers.
+	 * @param size Size of the product.
+	 */
+	public LargeResult(String id, String mimeType, String profileID, String resourceID, List headers, long size) {
+		super(id, "application/vnd.jpl.large-product", profileID, resourceID, headers, mimeType + " " + size);
+		this.size = size;
+	}
+
+	/**
+	 * Get the size of the product.
+	 *
+	 * @return Its size.
+	 */
+	public final long getSize() {
+		return size;
+	}
+
+	public final String getMimeType() {
+		return new StringTokenizer((String) value).nextToken();
+	}
+
+	/**
+	 * Return the result's value.
+	 *
+	 * @return a String.
+	 * @deprecated This method always treats its value as if it were a String.  Worse,
+	 * for very large results, it cannot contain the entire result in memory.  Use
+	 * {@link #getInputStream} instead to perform stream processing on result data.
+	 */
+	public final Object getValue() {
+		Object value = null;
+		InputStream in = null;
+		try {
+			if (size > Integer.MAX_VALUE)
+				throw new IllegalStateException("Cannot use getValue() for this product, result is too large; "
+					+ "use LargeResult.getInputStream instead");
+			int sizeToRead = (int) size;
+			byte[] buf = new byte[sizeToRead];
+			int index = 0;
+			int num;
+			in = getInputStream();
+			while ((num = in.read(buf, index, sizeToRead)) != -1) {
+				index += num;
+				sizeToRead -= num;
+				if (sizeToRead == 0) break;
+			}
+
+			// OK, this sucks.  Sucks sucks sucks.  Look, getValue is not to
+			// be used anyway.  It sucks.  But dammit, there's some annoying
+			// code over in EDRN which is using it when they should be using
+			// getInputStream.  Basically, if you call this, you're a hoser.
+			// And if you call it and you're not expecting a String, you're a
+			// loser/hoser.  DEPRECATED!
+			value = new String(buf);
+
+		} catch (IOException ex) {
+			throw new IllegalStateException("Unexpected IOException: " + ex.getMessage());
+		} finally {
+			if (in != null) try {
+				in.close();
+			} catch (IOException ignore) {}
+		}
+		return value;
+	}
+
+	/** Size of the product. */
+	private long size;
+
+	/**
+	 * Get an input stream that streams the result from the product server.
+	 *
+	 * @return an <code>InputStream</code> value.
+	 * @throws IOException if an error occurs.
+	 */
+	public InputStream getInputStream() throws IOException {
+		return new ChunkedProductInputStream(id, retriever, size);
+	}
+
+	/**
+	 * Given an existing <code>Result</code> yield its MIME type.
+	 *
+	 * The existing <code>Result</code> might be a <code>LargeResult</code>, in which
+	 * case the real MIME type is hidden in the value.  Otherwise, it's directly in
+	 * the object.
+	 *
+	 * @param result a <code>Result</code> value.
+	 * @return The MIME type.
+	 */
+	private static String transformMimeType(Result result) {
+		if ("application/vnd.jpl.large-product".equals(result.mimeType))
+			return (String) result.value;
+		else
+			return result.mimeType + " 0";
+	}
+
+	/** Serial version unique ID. */
+	static final long serialVersionUID = -969838775595705444L;
+}
diff --git a/0.8.1-rc1/product/src/site/resources/images/delegation.png b/0.8.1-rc1/product/src/site/resources/images/delegation.png
new file mode 100644
index 0000000..aea86e3
--- /dev/null
+++ b/0.8.1-rc1/product/src/site/resources/images/delegation.png
Binary files differ
diff --git a/0.8.1-rc1/product/src/site/resources/images/delegation.psd b/0.8.1-rc1/product/src/site/resources/images/delegation.psd
new file mode 100644
index 0000000..9b74dca
--- /dev/null
+++ b/0.8.1-rc1/product/src/site/resources/images/delegation.psd
Binary files differ
diff --git a/0.8.1-rc1/product/src/site/resources/images/grid-product.jpg b/0.8.1-rc1/product/src/site/resources/images/grid-product.jpg
new file mode 100644
index 0000000..7b1126e
--- /dev/null
+++ b/0.8.1-rc1/product/src/site/resources/images/grid-product.jpg
Binary files differ
diff --git a/0.8.1-rc1/product/src/site/site.xml b/0.8.1-rc1/product/src/site/site.xml
new file mode 100644
index 0000000..0b2c94c
--- /dev/null
+++ b/0.8.1-rc1/product/src/site/site.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<project name="Product Service">
+
+  <body>
+    <links>
+      <item name="OODT" href="../oodt-site/"/>
+      <item name="Grid" href="../grid/"/>
+    </links>
+
+    <menu ref="reports" inherit="bottom"/>
+    <menu name="User's Guide">
+      <item name="Tutorials" href="tutorials/"/>
+      <item name="Product Servlet" href="servlet/"/>
+    </menu>
+  </body>
+</project>
diff --git a/0.8.1-rc1/product/src/site/xdoc/servlet/index.xml b/0.8.1-rc1/product/src/site/xdoc/servlet/index.xml
new file mode 100644
index 0000000..22f9bd5
--- /dev/null
+++ b/0.8.1-rc1/product/src/site/xdoc/servlet/index.xml
@@ -0,0 +1,243 @@
+<?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.
+-->
+<document>
+  <properties>
+    <title>Using the Product Servlet</title>
+    <author email="kelly@apache.org">Sean Kelly</author>
+  </properties>
+
+  <body>
+    <section name="Using the Product Servlet">
+      <p>The query servlet is nice for general purpose queries, but for
+	those who just want to retrieve products, it's a bit annoying to
+	have to process all that XML and do base-64 conversions.  Is there
+	a simpler way?  Absolutely.  The product servlet deals with just
+	products, and delivers them in their appropriate form direct over
+	HTTP.
+      </p>
+    </section>
+    <section name="Requirements">
+
+      <p>The product servlet provides HTTP access to products, so
+	naturally, you'll need to use a language or system that supports
+	HTTP client access to HTTP servers.  Where can you find such a
+	system?  Your handy-dandy web browser is one!  Most programming
+	languages also have HTTP APIs either built-in or freely available.
+      </p>
+
+      <p>You also need to know</p>
+
+      <ul>
+	<li>The URL of the product servlet that has access to the
+	  product server you want to query.</li>
+	<li>The object name of the product server you want to
+	  access.</li>
+	<li>The keyword query expression that can be understood by the
+	  product server.</li>
+      </ul>
+    </section>
+    <section name="Making a Query">
+
+      <p>The product servlet accepts either <code>GET</code> or
+	<code>POST</code> requests of URL-encoded form data.  In
+	response, it delivers a matching product (if any can be found)
+	in the format appropriate to the product's MIME type.  You can
+	also request a specific MIME type.  If there's no matching
+	product, you get HTTP error 404 (not found).
+      </p>
+
+      <p>The parameters that the servlet expects are:</p>
+
+      <table border="0" cellpadding="3" cellspacing="0">
+
+	<thead>
+	  <tr>
+	    <th>Parameter Name</th>
+	    <th>Obligation</th>
+	    <th>Meaning</th>
+	  </tr>
+	</thead>
+
+	<tbody>
+	  <tr>
+	    <td><code>object</code></td>
+	    <td>Once</td>
+	    <td>Names the product server to receive the query.  This
+	      parameter must be specified exactly once and takes the form
+	      <code>urn:eda:<var>proto</var>:<var>name</var></code>, such
+	      as <code>urn:eda:rmi:PDS.Atmos.Product</code> for the
+	      RMI-accessed Atmoshpheres node of the Planetary Data System.
+	    </td>
+
+	  </tr>
+
+	  <tr>
+	    <td><code>keywordQuery</code></td>
+	    <td>Once</td>
+	    <td>Lists the keyword query expression to pass to the
+	      product server, such as <code>PatientID = 19928</code> or
+	      <code>ONLINE_FILE_SPECIFICATION_NAME =
+		data/images/mars.jpg</code>.
+	    </td>
+
+	  </tr>
+
+	  <tr>
+	    <td><code>id</code></td>
+	    <td>None or Once</td>
+	    <td>Optional parameter that identifies a single product to
+	      retrieve if more than one product match.  A product server
+	      may return multiple matching products.  By default, the
+	      product servlet returns the first matching product only.  By
+	      specifying the <code>id</code> parameter, you can select a
+	      specific product when more than one match.  (In practice,
+	      not a single product server <em>to date</em> has ever
+	      returned more than one match.)
+	    </td>
+
+	  </tr>
+
+	  <tr>
+	    <td><code>mimeType</code></td>
+	    <td>Zero to Many</td>
+	    <td>Optional parameter that lists acceptable MIME types for
+	      the product (see below).
+	    </td>
+
+	  </tr>
+
+	</tbody>
+      </table>
+    </section>
+    <section name="MIME Types">
+
+      <p>Many product servers are capable of conversion of products from
+	a system-specific storage medium into an Internet-standard
+	interoperable format.  Internet-standard MIME types are what
+	drives this mechanism.  The product servlet can take a list of
+	specific MIME types and pass them to the product server for
+	consideration in retrieving your products.
+      </p>
+
+      <p>MIME type conversions are like <em>suggestions</em> to product
+	servers.  Product servers are not obligated to honor all
+	conversions, and indeed you may well receive 404 (not found) for a
+	conversion that makes no sense to a particular product server
+	(such as an audio clip to <code>text/html</code>).
+      </p>
+
+      <p>The <code>mimeType</code> parameter is what drives this
+	mechanism.  By specifying one or more <code>mimeType</code>
+	parameters in your <code>GET</code> or <code>POST</code> request,
+	you list the preferred MIME types in which you would like the
+	product delivered.  Furthermore, you can use wildcards to further
+	enable a product server to satisfy you.  The ordering of the
+	parameters is significant.
+      </p>
+
+      <p>Here are some examples.  Suppose the request URI part of the
+	URL contained:</p>
+
+      <pre>...mimeType=text/rtf&amp;mimeType=text/*...</pre>
+
+      <p>This specifies two MIME types:</p>
+
+      <ol>
+	<li><code>text/rtf</code>, the Rich Text Format, is the
+	  preferred format for delivering products.
+	</li>
+
+	<li><code>text/*</code> means any text type.  Any text is better
+	  than no text if for some reason the product server can't give a
+	  Rich Text Format product.
+	</li>
+      </ol>
+
+      <p>Here's another example:</p>
+
+      <pre>...mimeType=image/png&amp;mimeType=image/jpeg...</pre>
+
+      <p>This indicates that you'd like a Portable Network Graphic
+	format image, if possible, but will settle for a JPEG-JFIF format
+	image.  No other image format (especially not the proprietary and
+	ancient GIF format) is acceptable.  Adding an additional
+	<code>&amp;mimeType=image/*</code> would mean any image format
+	would be fine.  Adding <code>&amp;mimeType=*/*</code> means
+	<em>any format</em> would be acceptable, be it audio, video, text,
+	image, or otherwise.
+      </p>
+
+      <p>If there are <em>no</em> <code>mimeType</code> parameters, then
+	the product servlet uses a default list containing just
+	<code>*/*</code>, meaning any type is fine.
+      </p>
+    </section>
+    <section name="Example">
+
+      <p>To retrieve an image of Mars from the PDS product server at the
+	Imaging Node, in PNG format if possible and any image format
+	otherwise, try the following:
+      </p>
+
+      <p><code><a
+	    href="http://starbrite.jpl.nasa.gov/prod?mimeType=image/png&amp;mimeType=image/*&amp;object=urn:eda:rmi:PDS.Img.Product&amp;keywordQuery=ONLINE_FILE_SPECIFICATION_NAME+%3D+thumbnail/mgs-m-moc-na_wa-2-sdp-l0-v1.0/mgsc_1082/m09063/m0906352.imq.jpg">http://starbrite.jpl.nasa.gov/prod?<br/>mimeType=image/png&amp;<br/>mimeType=image/*&amp;<br/>object=urn:eda:rmi:PDS.Img.Product&amp;<br/>keywordQuery=OFSN+%3D+thumbnail/mgs-m-moc-na_wa-2-sdp-l0-v1.0/mgsc_1082/m09063/m0906352.imq.jpg</a></code></p>
+
+      <p>This URL contains linebreaks for readability only.  Let's take
+	this URL apart to see what's going on:
+      </p>
+
+      <ul>
+	<li>The URL to the product servlet in this case is
+	  <code>http://starbrite.jpl.nasa.gov/prod</code>.  Often the URL
+	  will take this form, or may be
+	  <code>http://<var>hostname</var>/servlet/jpl.oodt.servlets.ProductServlet</code>.
+	  Most people prefer the shorter form.
+	</li>
+
+	<li>The question mark <code>?</code> separates the request URI
+	  from its parameters.
+	</li>
+
+	<li>The first parameter, <code>mimeType=image/png</code>, says
+	  that Portable Network Graphics images are preferred.
+	</li>
+
+	<li>The second parameter, <code>mimeType=image/*</code>, says
+	  that if the product server can't convert to or other provide
+	  Portable Network Graphics format images, then <em>any image
+	    format</em> is acceptable.
+	</li>
+
+	<li>The third parameter,
+	  <code>object=urn:eda:rmi:PDS.Img.Product</code>, identifies the
+	  product server.
+	</li>
+
+	<li>The fourth parameter, <code>keywordQuery=...</code> names
+	  the query expression.  In this case, it's <code>OFSN =
+	    thumbnail/mgs-m-moc-na_wa-2-sdp-l0-v1.0/mgsc_1082/m09063/m0906352.imq.jpg</code>.
+	</li>
+      </ul>
+
+      <p>The response to this URL's GET request is a JPEG-JFIF image
+	(sorry, PNG's not yet available from the PDS Image Node)
+	containing a picture of some planetary surface.  Neat, huh?
+      </p>
+    </section>
+  </body>
+</document>
diff --git a/0.8.1-rc1/product/src/site/xdoc/tutorials/index.xml b/0.8.1-rc1/product/src/site/xdoc/tutorials/index.xml
new file mode 100755
index 0000000..e130ea9
--- /dev/null
+++ b/0.8.1-rc1/product/src/site/xdoc/tutorials/index.xml
@@ -0,0 +1,36 @@
+<?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.

+-->

+<document>

+  <properties>

+    <title>Product Service Tutorials</title>

+    <author email="Sean.Kelly@jpl.nasa.gov">Sean Kelly</author>

+  </properties>

+

+  <body>

+    <section name="Product Service Tutorials">

+      <p>The following tutorials are available:</p>

+      <ul>

+	<li><a href="./ps">Your First Product Service</a></li>

+	<li><a href="./qh">Developing a Query Handler</a></li>

+	<li><a href="./lh">Serving Large Products</a></li>

+      </ul>

+    </section>

+  </body>

+</document>

+

+

diff --git a/0.8.1-rc1/product/src/site/xdoc/tutorials/lh/index.xml b/0.8.1-rc1/product/src/site/xdoc/tutorials/lh/index.xml
new file mode 100755
index 0000000..cb3de01
--- /dev/null
+++ b/0.8.1-rc1/product/src/site/xdoc/tutorials/lh/index.xml
@@ -0,0 +1,718 @@
+<?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.

+-->

+<document>

+  <properties>

+    <title>Serving Large Products</title>

+    <author email="Sean.Kelly@jpl.nasa.gov">Sean Kelly</author>

+  </properties>

+

+  <body>

+    <section name="Serving Large Products">

+      <p>In the <a href="../qh/">last tutorial</a>, we created a query

+	handler and "installed" it in a product server.  We could

+	query it for products (mathematical constants) using the

+	XMLQuery's postfix boolean stacks.  The handler would return

+	results by embedding them in the returned XMLQuery.  Now we'll

+	return larger products that live outside of the XMLQuery.

+      </p>

+    </section>

+

+    <section name="What's Large?">

+      <p>There's a <a

+	  href="http://www.worldslargestthings.com/california/clam.htm">giant

+	  clam</a> at Pismo Beach, a <a

+	  href="http://www.worldslargestthings.com/kansas/cawkercity.htm">giant

+	  ball of twine</a> in Kansas, and for those who drive SUVs, a

+	  <a

+	  href="http://www.worldslargestthings.com/missouri/gaspump.htm">giant

+	  gas pump</a>.  For the OODT framework, large is similarly hard to define.

+      </p>

+

+      <p>One of the original architects of the OODT framework thought

+	that putting a products result in with the query meant that

+	you'd never lose the separation between product and the query

+	that generated it.  I'm not sure I see the value in that, but

+	regardless, it posed a practical challenge: an

+	<code>XMLQuery</code> object in memory with one or two large

+	results in it will exhaust the Java virtual machine's available

+	memory.

+      </p>

+

+      <p>It's even worse in when the XMLQuery is expressed as a

+	textual XML document.  In this case, a binary product must be

+	encoded in a text format (we use <a

+	href="ftp://ftp.rfc-editor.org/in-notes/rfc2045.txt">Base64</a>),

+	making the XMLQuery in XML format even larger than as a Java

+	object.  Moreover, those XML documents must be parsed at some

+	time to reconstitute them as Java objects.  We use a DOM-based

+	parser, which holds the entire document in memory.  Naturally,

+	things tend to explode at this rate.

+      </p>

+

+      <p>There is a way out of the quagmire, though.  Instead of

+	writing a <code>QueryHandler</code>, write a

+	<code>LargeProductQueryHandler</code>.  A

+	<code>QueryHandler</code> puts <code>Result</code> objects

+	into the <code>XMLQuery</code> which hold the entire product.

+	A <code>LargeProductQueryHandler</code> puts

+	<code>LargeResult</code> objects which hold <em>a reference to

+	the product</em>.

+      </p>

+    </section>

+

+    <section name="Large Handlers and Large Results">

+      <p>The OODT framework provides an extension to the

+	<code>QueryHandler</code> interface called

+	<code>jpl.eda.product.LargeProductQueryHandler</code>.  This

+	interface adds two methods that you must implement:

+      </p>

+

+      <ul>

+	<li><code>retrieveChunk</code>.  This method returns a byte

+	  array representing a chunk of the product.  The OODT

+	  framework calls this method repeatedly to gather chunks of

+	  the product for the product client.  It takes a <em>product

+	  ID</em> (a string) that identifies which product is being

+	  retrieved.  It also takes an byte offset into the product

+	  data and a size of the byte chunk to return.  You return the

+	  matching chunk.

+	</li>

+

+	<li><code>close</code>.  This method is called by the OODT

+	  framework to tell the query handler it's done getting a

+	  product.  It takes a <em>product ID</em> that tells which

+	  product is no longer being retrieved.  You use this method

+	  to perform any cleanup necessary.

+	</li>

+      </ul>

+	  

+      <p>Because it extends the <code>QueryHandler</code> interface,

+	you still have to implement the <code>query</code> method.

+	However, as a <code>LargeProductQueryHandler</code>, you can

+	add <code>LargeResult</code> objects to the

+	<code>XMLQuery</code> passed in.  <code>LargeResult</code>s

+	identify the <em>product ID</em> (string) that the OODT

+	framework will later use when it calls

+	<code>retrieveChunk</code> and <code>close</code>.

+      </p>

+

+      <p>For example, suppose you're serving large images by

+	generating them from various other data sources:

+      </p>

+

+      <ol>

+	<li>The <code>query</code> method would examine the user's

+	  query, consult the various data sources, and generate the

+	  image, storing it in a temporary file.  It would also assign

+	  a string <em>product ID</em> to this file, use that product

+	  ID in a <code>LargeResult</code> object, add the

+	  <code>LargeResult</code> to the <code>XMLQuery</code>, and

+	  return the modified <code>XMLQuery</code>.

+	</li>

+

+	<li>Shortly afterward, the OODT framework will repeatedly call

+	  the <code>retrieveChunk</code> method.  This method would

+	  check the <em>product ID</em> passed in and locate the

+	  corresponding temporary file generated earlier by the

+	  <code>query</code> method.  It would index into the file by

+	  the offset requested by the framework, read the number of

+	  bytes requested by the framework, package that up into a

+	  byte array, and return it.  Eventually, the OODT framework

+	  will have read the entire product this way.

+	</li>

+

+	<li>Lastly, the OODT framework will call the

+	  <code>close</code> method.  This method would check the

+	  <em>product ID</em> and locate and delete the temporary

+	  file.

+	</li>

+      </ol>

+

+      <p>To put this into practice, let's create a

+	<code>LargeProductQueryHandler</code> that serves files out of

+	the product server's filesystem.

+      </p>

+    </section>

+

+    <section name="Writing the Handler">

+      <p>We'll develop a <code>FileHandler</code> that will serve

+	files out of the product server's filesystem.  Providing

+	filesystem access through the OODT framework in this way is

+	probably not a very good idea (after all, product clients

+	could request copies of sensitive files), but for a

+	demonstration it'll do.

+      </p>

+

+      <p>Because files can be quite large, we'll use a

+	<code>LargeProductQueryHandler</code>.  It will serve queries

+	of the form

+      </p>

+

+      <p><code>file = <var>path</var></code></p>

+

+      <p>where <var>path</var> is the full path of the file the user

+	wants.  The handler will add <code>LargeResult</code>s to the

+	XMLQuery, and the <em>product ID</em> will just simply be the

+	<var>path</var> of the requested file.  The

+	<code>retrieveChunk</code> method will open the file with the

+	given product ID (which is just the path to the file) and

+	return a block of data out of it.  The <code>close</code>

+	method won't need to do anything, since we're not creating

+	temporary files or making network conncetions or anything;

+	there's just nothing to clean up.

+      </p>

+

+      <subsection name="Getting the Path">

+	<p>First, let's create a utility method that takes the

+	  <code>XMLQuery</code> and returns a <code>java.io.File</code>

+	  that matches the requested file.  Because the query takes the form

+	</p>

+

+	<p><code>file = <var>path</var></code></p>

+

+	<p>there should be three <code>QueryElement</code>s on the "where" stack:</p>

+

+	<ol>

+	  <li>The zeroth (topmost) has role = <code>elemName</code>

+	    and value = <code>file</code>.

+	  </li>

+	  <li>The first (middle) has role = <code>LITERAL</code> and

+	    value = the <var>path</var> of the file the user wants.

+	  </li>

+	  <li>The last (bottom) has role = <code>RELOP</code> and

+	    value = <code>EQ</code>.

+	  </li>

+	</ol>

+

+	<p>We'll reject any other query by returning <code>null</code>

+	  from this method.  Further, if the file named by the

+	  <var>path</var> doesn't exist, or if it's not a file (for

+	  example, it's a directory or a socket), we'll return <code>null</code>.

+	</p>

+

+	<p>Here's the start of our <code>FileHandler.java</code>:</p>

+

+	<source>import java.io.File;

+import java.util.List;

+import jpl.eda.product.LargeProductQueryHandler;

+import jpl.eda.xmlquery.QueryElement;

+import jpl.eda.xmlquery.XMLQuery;

+public class FileHandler

+  implements LargeProductQueryHandler {

+  private static File getFile(XMLQuery q) {

+    List stack = q.getWhereElementSet();

+    if (stack.size() != 3) return null;

+    QueryElement e = (QueryElement) stack.get(0);

+    if (!"elemName".equals(e.getRole())

+      || !"file".equals(e.getValue()))

+      return null;

+    e = (QueryElement) stack.get(2);

+    if (!"RELOP".equals(e.getRole())

+      || !"EQ".equals(e.getValue()))

+      return null;

+    e = (QueryElement) stack.get(1);   	    

+    if (!"LITERAL".equals(e.getRole()))

+      return null;

+    File file = new File(e.getValue());

+    if (!file.isFile()) return null;

+    return file;

+  }

+}</source>

+      </subsection>

+      <subsection name="Checking the MIME Type">

+	<p>Recall that the user can say what MIME types of products

+	  are acceptable by specifying the preference list in the

+	  XMLQuery.  This lets a product server that serves, say,

+	  video clips, convert them to <code>video/mpeg</code>

+	  (MPEG-2), <code>video/mpeg4-generic</code> (MPEG-4),

+	  <code>video/quicktime</code> (Apple Quicktime), or some

+	  other format, in order to better serve its clients.

+	</p>

+

+	<p>Since our product server just serves <em>files of any

+	    format</em>, we won't really bother with the list of

+	    acceptable MIME types.  After all, the

+	    <code>/etc/passwd</code> file <em>could</em> be a JPEG

+	    image on some systems.  (Yes, we could go through the

+	    extra step of determining the MIME type of a file by

+	    looking at its extension or its contents, but this is an

+	    OODT tutorial, not a something-else-tutorial!)

+	</p>

+

+	<p>However, we will honor the user's wishes by labeling the

+	  result's MIME type based on what the user specifies in the

+	  acceptable MIME type list.  So, if the product client says

+	  that <code>image/jpeg</code> is acceptable and the file is

+	  <code>/etc/passwd</code>, we'll call

+	  <code>/etc/passwd</code> a JPEG image.  However, we won't

+	  try to read the client's mind: if the user wants

+	  <code>image/*</code>, then we'll just say it's a binary

+	  file, <code>application/octet-stream</code>.

+	</p>

+

+	<p>Here's the code:</p>

+

+	<source>import java.util.Iterator;

+...

+public class FileHandler

+  implements LargeProductQueryHandler {

+  ...

+  private static String getMimeType(XMLQuery q) {

+    for (Iterator i = q.getMimeAccept().iterator();

+      i.hasNext();) {

+      String t = (String) i.next();

+      if (t.indexOf('*') == -1) return t;

+    }

+    return "application/octet-stream";

+  }

+}</source>

+      </subsection>

+

+      <subsection name="Inserting the Result">

+	<p>Once we've got the file that the user wants and the MIME

+	  type to call it, all we have to do is insert the

+	  <code>LargeResult</code>.  Remember that it's the

+	  <code>LargeResult</code> that tells the OODT framework what

+	  the <em>product ID</em> is for later

+	  <code>retrieveChunk</code> and <code>close</code> calls.

+	  The <em>product ID</em> is passed as the first argument to

+	  the <code>LargeResult</code> constructor.

+	</p>

+

+	<p>We'll write a utility method to insert the <code>LargeResult</code>:</p>

+

+	<source>import java.io.IOException;

+import java.util.Collections;

+import jpl.eda.xmlquery.LargeResult;

+...

+public class FileHandler

+  implements LargeProductQueryHandler {

+  ...

+  private static void insert(File file, String type,

+    XMLQuery q) throws IOException {

+    String id = file.getCanonicalPath();

+    long size = file.length();

+    LargeResult lr = new LargeResult(id, type,

+      /*profileID*/null, /*resourceID*/null,

+      /*headers*/Collections.EMPTY_LIST, size);

+    q.getResults().add(lr);

+  }

+}</source>

+

+      </subsection>

+

+      <subsection name='Handling the Query'>

+	<p>With our three utility methods in hand, writing the

+	  required <code>query</code> method is a piece of cake.  Here

+	  it is:

+	</p>

+

+	<source>import jpl.eda.product.ProductException;

+...

+public class FileHandler

+  implements LargeProductQueryHandler {

+  ...

+  public XMLQuery query(XMLQuery q)

+    throws ProductException {

+    try {

+      File file = getFile(q);

+      if (file == null) return q;

+      String type = getMimeType(q);

+      insert(file, type, q);

+      return q;

+    } catch (IOException ex) {

+      throw new ProductException(ex);

+    }

+  }

+}</source>

+

+	<p>The <code>query</code> method as defined by the

+	  <code>QueryHandler</code> interface (and extended into the

+	  <code>LargeProductQueryHandler</code> interface) is allowed

+	  to throw only one kind of checked exception:

+	  <code>ProductException</code>.  So, in case the

+	  <code>insert</code> method throws an

+	  <code>IOException</code>, we transform it into a

+	  <code>ProductException</code>.

+	</p>

+

+	<p>Now there are just two more required methods to implement,

+	  <code>retrieveChunk</code> and <code>close</code>.

+	</p>

+      </subsection>

+

+      <subsection name='Blowing Chunks'>

+	<p>The OODT framework repeatedly calls handler's

+	  <code>retrieveChunk</code> method to get chunks of the

+	  product, evenutally getting the entire product (unless the

+	  product client decides to abort the transfer).  For our file

+	  handler, retrieve chunk just has to

+	</p>

+	<ol>

+	  <li>Make sure the file specified by the <em>product ID</em>

+	    still exists (after all, it could be deleted at any time,

+	    even before the first <code>retrieveChunk</code> got

+	    called).

+	  </li>

+	  <li>Open the file.</li>

+	  <li>Skip into the file by the requested offset.</li>

+	  <li>Read the requested number of bytes out of the file.</li>

+	  <li>Return those bytes.</li>

+	  <li>Close the file.</li>

+	</ol>

+

+	<p>We'll write a quick little <code>skip</code> method to skip

+	  into a file's input stream:

+	</p>

+

+	<source>private static void skip(long offset,

+  InputStream in) throws IOException {

+  while (offset > 0)

+    offset -= in.skip(offset);

+}</source>

+

+	<p>And here's another little utility method to read a

+	  specified number of bytes out of a file's input stream:

+	</p>

+

+	<source>private static byte[] read(int length,

+  InputStream in) throws IOException {

+  byte[] buf = new byte[length];

+  int numRead;

+  int index = 0;

+  int toRead = length;

+  while (toRead > 0) {

+    numRead = in.read(buf, index, toRead);

+    index += numRead;

+    toRead -= numRead;

+  }

+  return buf;

+}</source>

+

+	<p>(By now, you're probably wondering why we just didn't use

+	  <code>java.io.RandomAccessFile</code>; I'm wondering that

+	  too!)</p>

+

+	<p>Finally, we can implement the required

+	  <code>retrieveChunk</code> method:

+	</p>

+

+	<source>import java.io.BufferedInputStream;

+import java.io.FileInputStream;

+...

+public class FileHandler

+  implements LargeProductQueryHandler {

+  ...

+  public byte[] retrieveChunk(String id, long offset,

+    int length) throws ProductException {

+    BufferedInputStream in = null;

+    try {

+      File f = new File(id);

+      if (!f.isFile()) throw new ProductException(id

+        + " isn't a file (anymore?)");

+      in = new BufferedInputStream(new FileInputStream(f));

+      skip(offset, in);

+      byte[] buf = read(length, in);

+      return buf;

+    } catch (IOException ex) {

+      throw new ProductException(ex);

+    } finally {

+      if (in != null) try {

+        in.close();

+      } catch (IOException ignore) {}

+    }

+  }

+}</source>

+

+      </subsection>

+

+      <subsection name='Closing Up'>

+	<p>Because the OODT framework has no idea what data sources a

+	  <code>LargeProductQueryHandler</code> will eventually

+	  consult, what temporary files it may need to clean up, what

+	  network sockets it might need to shut down, and so forth, it

+	  needs some way to indicate to a query handler that's it's

+	  done calling <code>retrieveChunk</code> for a certain

+	  <em>product ID</em>.  The <code>close</code> method does this.

+	</p>

+

+	<p>In our example, <code>close</code> doesn't need to do

+	  anything, but we are obligated to implement it:

+	</p>

+

+	<source>...

+public class FileHandler

+  implements LargeProductQueryHandler {

+  ...

+  public void close(String id) {}

+}</source>

+      </subsection>

+

+      <subsection name='Complete Source Code'>

+	<p>Here's the complete source file, <code>FileHandler.java</code>:</p>

+	<source>import java.io.BufferedInputStream;

+import java.io.File;

+import java.io.FileInputStream;

+import java.io.InputStream;

+import java.io.IOException;

+import java.util.Collections;

+import java.util.Iterator;

+import java.util.List;

+import jpl.eda.product.LargeProductQueryHandler;

+import jpl.eda.product.ProductException;

+import jpl.eda.xmlquery.LargeResult;

+import jpl.eda.xmlquery.QueryElement;

+import jpl.eda.xmlquery.XMLQuery;

+

+public class FileHandler

+  implements LargeProductQueryHandler {

+  private static File getFile(XMLQuery q) {

+    List stack = q.getWhereElementSet();

+    if (stack.size() != 3) return null;

+    QueryElement e = (QueryElement) stack.get(0);

+    if (!"elemName".equals(e.getRole())

+      || !"file".equals(e.getValue()))

+      return null;

+    e = (QueryElement) stack.get(2);

+    if (!"RELOP".equals(e.getRole())

+      || !"EQ".equals(e.getValue()))

+      return null;

+    e = (QueryElement) stack.get(1);   	    

+    if (!"LITERAL".equals(e.getRole()))

+      return null;

+    File file = new File(e.getValue());

+    if (!file.isFile()) return null;

+    return file;

+  }

+  private static String getMimeType(XMLQuery q) {

+    for (Iterator i = q.getMimeAccept().iterator();

+      i.hasNext();) {

+      String t = (String) i.next();

+      if (t.indexOf('*') == -1) return t;

+    }

+    return "application/octet-stream";

+  }

+  private static void insert(File file, String type,

+    XMLQuery q) throws IOException {

+    String id = file.getCanonicalPath();

+    long size = file.length();

+    LargeResult lr = new LargeResult(id, type,

+      /*profileID*/null, /*resourceID*/null,

+      /*headers*/Collections.EMPTY_LIST, size);

+    q.getResults().add(lr);

+  }

+  public XMLQuery query(XMLQuery q)

+    throws ProductException {

+    try {

+      File file = getFile(q);

+      if (file == null) return q;

+      String type = getMimeType(q);

+      insert(file, type, q);

+      return q;

+    } catch (IOException ex) {

+      throw new ProductException(ex);

+    }

+  }

+  private static void skip(long offset,

+    InputStream in) throws IOException {

+    while (offset > 0)

+      offset -= in.skip(offset);

+  }

+  private static byte[] read(int length,

+    InputStream in) throws IOException {

+    byte[] buf = new byte[length];

+    int numRead;

+    int index = 0;

+    int toRead = length;

+    while (toRead > 0) {

+      numRead = in.read(buf, index, toRead);

+      index += numRead;

+      toRead -= numRead;

+    }

+    return buf;

+  }

+  public byte[] retrieveChunk(String id, long offset,

+    int length) throws ProductException {

+    BufferedInputStream in = null;

+    try {

+      File f = new File(id);

+      if (!f.isFile()) throw new ProductException(id

+        + " isn't a file (anymore?)");

+      in = new BufferedInputStream(new FileInputStream(f));

+      skip(offset, in);

+      byte[] buf = read(length, in);

+      return buf;

+    } catch (IOException ex) {

+      throw new ProductException(ex);

+    } finally {

+      if (in != null) try {

+        in.close();

+      } catch (IOException ignore) {}

+    }

+  }

+  public void close(String id) {}

+}</source>

+      </subsection>

+    </section>

+

+    <section name='Compiling the Code'>

+      <p>We'll compile this code using the J2SDK command-line tools,

+	but if you're more comfortable with some kind of Integrated

+	Development Environment (IDE), adjust as necessary.

+      </p>

+

+      <p>Let's go back again to the <code>$PS_HOME</code> directory we

+	made earlier; create the file

+	<code>$PS_HOME/src/FileHandler.java</code> with the contents

+	shown above.  Then, compile and update the jar file as follows:

+      </p>

+

+      <source>% <b>javac -extdirs lib \

+  -d classes src/FileHandler.java</b>

+% <b>ls -l classes</b>

+total 8

+-rw-r--r--  1 kelly  kelly  2524 25 Feb 15:46 ConstantHandler.class

+-rw-r--r--  1 kelly  kelly  3163 26 Feb 16:15 FileHandler.class

+% <b>jar -uf lib/my-handlers.jar \

+  -C classes FileHandler.class</b>

+% <b>jar -tf lib/my-handlers.jar</b>

+META-INF/

+META-INF/MANIFEST.MF

+ConstantHandler.class

+FileHandler.class</source>

+

+      <p>We've now got a jar with the <code>ConstantHandler</code>

+	from the <a href="../qh/">last tutorial</a> and our new

+	<code>FileHandler</code>.

+      </p>

+    </section>

+

+    <section name='Specifying and Running the New Query Handler'>

+      <p>The <code>$PS_HOME/bin/ps</code> script already has a system

+	property specifying the <code>ConstantHandler</code>, so we

+	just need to add the <code>FileHandler</code> to that list.

+      </p>

+

+      <p>First, stop the product server by hitting CTRL+C (or your

+	interrupt key) in the window in which it's currently running.

+	Then, modify the <code>$PS_HOME/bin/ps</code> script to read

+	as follows:

+      </p>

+

+      <source>#!/bin/sh

+exec java -Djava.ext.dirs=$PS_HOME/lib \

+    -Dhandlers=ConstantHandler,FileHandler \

+    jpl.eda.ExecServer \

+    jpl.eda.product.rmi.ProductServiceImpl \

+    urn:eda:rmi:MyProductService</source>

+

+      <p>Then start the server by running

+	<code>$PS_HOME/bin/ps</code>.  If all goes well, the product

+	server will be ready to answer queries again, this time

+	passing each incoming <code>XMLQuery</code> to <em>two</em>

+	different query handlers.

+      </p>

+

+      <p>Edit the <code>$PS_HOME/bin/pc</code> script once more to

+	make sure the <code>-out</code> and not the <code>-xml</code>

+	command-line argument is being used.  Let's try querying for a

+	file:

+      </p>

+

+      <source>% <b>$PS_HOME/bin/pc "file = /etc/passwd"</b>

+nobody:*:-2:-2:Unprivileged User:/:/usr/bin/false

+root:*:0:0:System Administrator:/var/root:/bin/sh

+daemon:*:1:1:System Services:/var/root:/usr/bin/false

+...</source>

+

+      <p>If you like, you can change the <code>-out</code> to

+	<code>-xml</code> again and examine the XML version.  This

+	time, the product data isn't in the XMLQuery object.

+      </p>

+    </section>

+

+    <section name="What's the Difference?">

+      <p>On the client side, the interface to get product results in

+	<code>LargeResult</code>s versus regular <code>Result</code>s

+	is identical.  The client calls <code>getInputStream</code> to

+	get a binary stream to read the product data.

+      </p>

+

+      <p>There is a speed penalty for large results.  What

+	<code>Result.getInputStream</code> returns is an input stream

+	to product data already contained in the XMLQuery.  It's a

+	stream to a buffer already in the client's address space, so

+	it's nice and fast.

+      </p>

+

+      <p><code>LargeResult</code> overrides the

+	<code>getInputStream</code> method to instead return an input

+	stream that repeatedly makes calls back to the product

+	server's <code>retrieveChunk</code> method.  Since the product

+	is <em>not</em> already in the local address space of the

+	client, getting large products is a bit slower.  To

+	compensate, the input stream actually starts a background

+	thread to start retrieving chunks of the product ahead of the

+	product client, up to a certain point (we don't want to run

+	out of memory again).

+      </p>

+

+      <p>On the server side, the difference is in programming

+	complexity.  Creating a <code>LargeProductQueryHandler</code>

+	requires implementing three methods instead of just one.  You

+	may have to clean up temporary files, close network ports, or

+	do other cleanup.  You may even have to guard against clients

+	that present specially-crafted product IDs that try to

+	circumvent access controls to products.

+      </p>

+

+      <p><code>LargeResult</code>s are more general, and will work for

+	any size product, from zero bytes on up.  And you can even mix

+	and match: a <code>LargeProductQueryHandler</code> can add

+	regular <code>Result</code>s to an XMLQuery as well as

+	<code>LargeResult</code>s.  You might program some logic that,

+	under a certain threshold, to return regular

+	<code>Result</code>s for small sized products, and

+	<code>LargeResult</code>s for anything bigger than small.

+      </p>

+    </section>

+

+    <section name='Conclusion'>

+      <p>In this tutorial, we implemented a

+	<code>LargeProductQueryHandler</code> that served large

+	products.  In this case, large could mean zero bytes (empty

+	products) up to gargantuan numbers of bytes.  This handler

+	queried for files in the product server's filesystem, which is

+	a bit insecure so you might want to terminate the product

+	server as soon as possible.  We also learned that what the

+	advantages and disadvantages were between regular product

+	results and large product results, and that

+	<code>LargeProductQueryHandler</code>s can use

+	<code>LargeResult</code> objects in addition to regular

+	<code>Result</code> objects.

+      </p>

+

+      <p>If you've also completed the <a href="../ps">Your First

+	  Product Service</a> tutorial and the <a

+	  href="../qh/">Developing a Query Handler</a> tutorial, you

+	are now a master of the OODT Product Service.

+	Congratulations!

+      </p>

+    </section>

+  </body>

+</document>

diff --git a/0.8.1-rc1/product/src/site/xdoc/tutorials/ps/index.xml b/0.8.1-rc1/product/src/site/xdoc/tutorials/ps/index.xml
new file mode 100755
index 0000000..91bfc00
--- /dev/null
+++ b/0.8.1-rc1/product/src/site/xdoc/tutorials/ps/index.xml
@@ -0,0 +1,481 @@
+<?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.

+-->

+<document>

+  <properties>

+    <title>Your First Product Service</title>

+    <author email="Sean.Kelly@jpl.nasa.gov">Sean Kelly</author>

+  </properties>

+

+  <body>

+    <section name="Your First Product Service">

+      <p>This tutorial introduces starting a basic product server.

+	This product server will be capable of accepting queries, but

+	will not actually respond with any data.  By completing this

+	tutorial, you'll have a working product server in which you

+	can install more complex logic to actually handle product

+	requests.

+      </p>

+    </section>

+

+    <section name="The Product Service">

+      <p>The OODT Product Service is a remotely accessible software

+	component that enables you to retrieve products, which can be

+	any kind of data.  In OODT, a <em>product client</em> passes a

+	<em>query</em> into a known product server.  The product

+	server delegates that query to its installed <em>query

+	handlers</em>; each one gets a chance at satisfying the query

+	with requested data.  Query handlers are the interfaces between

+	the generic OODT framework and your system-specific data

+	stores.  They have the job of understanding the passed in

+	query, finding or even synthesizing the matching product,

+	applying conversions to Internet-standard formats, and

+	returning results.  The product service then collects all the

+	matching products from the query handlers and returns them to

+	the product client.

+      </p>

+

+      <p>To deploy a product server, you need to come up with query

+	handlers that interface to your site- or discipline-specific

+	data stores.  Then, start a product server and inform it of

+	what query handlers to use.

+      </p>

+

+      <subsection name="Delegation Model">

+	<p>The OODT product service <em>delegates</em> incoming

+	  queries to zero or more query handlers.  In the case of zero

+	  query handlers, the product service always replies to every

+	  query with "zero matches."  Otherwise, the query handlers

+	  get a chance to satisfy the query, and may or may not add

+	  matching products to the result.

+	</p>

+

+	<p>The following class diagram demonstrates this delegation model:</p>

+

+	<img src="../../images/delegation.png" alt="Delegation Class Diagram" />

+

+	<p>Here, a product client calls a server to process a query

+	  for products. The server delegates to query handlers, which

+	  are Java objects that implement the

+	  <code>QueryHandler</code> interface.  Two query handlers in

+	  this diagram, <code>MyHandler</code> and

+	  <code>MyOtherHandler</code> can both try to satisfy the

+	  query by adding matching products to the total result.  They

+	  can each add more than one matching product, just one, or

+	  none at all.  The server then returns the matches, if any,

+	  to the client.

+	</p>

+      </subsection>

+

+      <subsection name="Large Products">

+	<p>In OODT, a query contains its matching products.  When a

+	  client passes a query to a product server, the query object

+	  returns to the client <em>with matching products embedded in

+	    it</em>.  This can, however, make query objects too large to

+	  be comfortably passed around a network of OODT services (query

+	  objects must reside completely in memory).  In this case, a

+	  special extension of a <code>QueryHandler</code>, a

+	  <code>LargeProductQueryHandler</code>, can instead place a

+	  <em>reference</em> to the product data in the query.

+	</p>

+	<p>To product clients, the difference is invisible: the

+	  product data is still accessed from the query object the

+	  same way.  As a developer of product services, though, you

+	  may need to decide which kind of query handler to make:

+	  regular or large.

+	</p>

+      </subsection>

+

+      <subsection name="Communicating with a Product Service">

+	<p>The product service is a remotely accessible object.

+	  Therefore, product clients access it with a remote object

+	  access protocol.  Currently, OODT supports RMI and CORBA.  You

+	  can also access product services with HTTP; in this case, a

+	  proxy object provides the HTTP interface while internally it

+	  accesses a product service with RMI or CORBA.

+	</p>

+

+	<p>For this tutorial, we'll use RMI because it's enormously

+	  less complex than CORBA.

+	</p>

+      </subsection>

+    </section>

+

+    <section name="Making the Staging Area">

+      <p>To start a product service, we'll create a directory

+	structure that will hold software components (jar files) as

+	well as scripts that will simplify the usually over-long Java

+	command lines.  (Note that these examples are for Mac OS X,

+	Linux, or other Unix-like systems.  Windows users will have to

+	adapt.)

+      </p>

+

+      <p>Let's start by making a directory hierarchy for our product

+	service called <code>ps</code> (this example uses a C-style

+	shell <code>csh</code>, if you're using <code>bash</code> or

+	another style shell, substitute the appropriate commands).

+      </p>

+

+      <source>% <b>mkdir ps</b>

+% <b>cd ps</b>

+% <b>setenv PS_HOME `pwd`</b>

+% <b>mkdir bin lib</b>

+% <b>ls -RF $PS_HOME</b>

+bin/    lib/

+

+/Users/kelly/tmp/ps/bin:

+

+/Users/kelly/tmp/ps/lib:</source>

+

+      <p>Note that we're using an environment variable

+	<code>PS_HOME</code> to contain the path of the directory

+	we're using to hold everything.  We'll use this environment

+	variable as we develop the scripts to launch the product service.

+      </p>

+    </section>

+

+    <section name="The RMI Registry">

+      <p>Since we're using Remote Method Invocation (RMI) for this

+	tutorial, we'll need to start an RMI Registry.  An RMI

+	Registry serves as a catalog that maps between named objects,

+	such as your product server, to the appropriate network

+	address and port where the object can be located.  Your

+	product client will use the RMI registry to locate the product

+	server so it can connect to the product server and communicate with it.

+      </p>

+

+      <subsection name="Collecting the RMI Registry Components">

+	<p>To start an RMI Registry, you'll need the following components:</p>

+

+	<ul>

+	  <li><a href="/edm-commons/">EDM Common Components</a>.

+	    These are common utilities used by every OODT

+	    service.</li> <li><a href="/grid-product/">Grid Product

+	    Service</a>.  This is the product service, product client,

+	    query handler interface, and related classes.</li> <li><a

+	    href="/rmi-registry/">OODT RMI Registry</a>.  This is the

+	    actual RMI registry.</li>

+	</ul>

+

+	<p>Download each component's binary distribution, unpack each

+	  one, and take collect the jar files into the

+	  <code>lib</code> directory.  For example:

+	</p>

+

+	<source>% <b>cp /tmp/edm-commons-2.2.5/*.jar $PS_HOME/lib</b>

+% <b>cp /tmp/grid-product-3.0.3/*.jar $PS_HOME/lib</b>

+% <b>cp /tmp/rmi-registry-1.0.0/*.jar $PS_HOME/lib</b>

+% <b>ls -l $PS_HOME/lib</b>

+total 312

+-rw-r--r--  1 kelly  kelly  149503 24 Feb 14:06 edm-commons-2.2.5.jar

+-rw-r--r--  1 kelly  kelly  120844 24 Feb 14:07 grid-product-3.0.3.jar

+-rw-r--r--  1 kelly  kelly    8055 24 Feb 14:07 rmi-registry-1.0.0.jar</source>

+      </subsection>

+

+      <subsection name="Writing the RMI Script">

+	<p>To keep from having to type long Java command lines, we'll

+	  create a simple shell script that will start the RMI

+	  registry.  We'll call it <code>rmi-reg</code> and stick it

+	  in the <code>bin</code> directory.

+	</p>

+

+	<p>Here's the <code>rmi-reg</code> script:</p>

+	<source>#!/bin/sh

+exec java -Djava.ext.dirs=$PS_HOME/lib \

+    gov.nasa.jpl.oodt.rmi.RMIRegistry</source>

+

+	<p>This script tells the Java virtual machine to find

+	  extension jars in the directory <code>$PS_HOME/lib</code>.  It

+	  then says that the main class to execute is

+	  <code>gov.nasa.jpl.oodt.rmi.RMIRegistry</code>.

+	</p>

+

+	<p>Go ahead and make this script executable and start the RMI

+	  Registry. In another window (with the appropriate setting of

+	  <code>PS_HOME</code>), run

+	  <code>$PS_HOME/bin/rmi-reg</code>.  You should see output

+	  similar to the following:

+	</p>

+

+	<source>% <b>chmod 755 $PS_HOME/bin/rmi-reg</b>

+% <b>$PS_HOME/bin/rmi-reg</b>

+Thu Feb 24 14:10:25 CST 2005: no objects registered</source>

+

+	<p>The RMI Registry is now running.  Every two minutes it will

+	  display an update of all registered objects.  Naturally, we

+	  don't have any product service running right now, so it will

+	  say <code>no objects registered</code>.  Go ahead and ignore

+	  this window for now.  It's time to start our product server.

+	</p>

+      </subsection>

+    </section>

+

+    <section name="The Product Server">

+      <p>With an RMI Registry in place, we're ready to start our

+	product server.  As with the RMI Registry, we'll need the

+	software components and to make a script to launch it.

+      </p>

+

+      <subsection name="Collecting the Product Server Components">

+	<p>We already have two of the components needed to start the

+	  product server, <code>edm-commons</code> and

+	  <code>grid-product</code>.  We need two more:

+	</p>

+

+	<ul>

+	  <li><a href="/edm-query/">EDM Query Expression</a>.  This

+	  component encapsulates the implementation of an OODT query

+	  and also contains some product retrieval utilities.</li>

+	  <li><a href="http://ws.apache.org/xmlrpc">Apache

+	  XML-RPC</a>.  This is used internally by OODT services.

+	  Download version 1.1, not a later version!  If you prefer,

+	  you can <a

+	  href="http://ibiblio.org/maven/xmlrpc/jars/xmlrpc-1.1.jar">fetch

+	  the jar file directly</a>.</li>

+	</ul>

+

+	<p>As before, put these jars into the

+	  <code>$PS_HOME/lib</code> directory:

+	</p>

+

+	<source>% <b>ls -l $PS_HOME/lib</b>

+total 376

+-rw-r--r--  1 kelly  kelly  149503 24 Feb 14:06 edm-commons-2.2.5.jar

+-rw-r--r--  1 kelly  kelly   43879 24 Feb 14:35 edm-query-2.0.2.jar

+-rw-r--r--  1 kelly  kelly  120844 24 Feb 14:07 grid-product-3.0.3.jar

+-rw-r--r--  1 kelly  kelly    8055 24 Feb 14:07 rmi-registry-1.0.0.jar

+-rw-r--r--  1 kelly  kelly   53978 24 Feb 14:35 xmlrpc-1.1.jar</source>

+      </subsection>

+

+      <subsection name="Writing the Product Server Script">

+	<p>To launch the product server, we'll create a script called

+	  <code>ps</code> in the <code>$PS_HOME/bin</code> directory.

+	  Here's its contents:

+	</p>

+

+	<source>#!/bin/sh

+exec java -Djava.ext.dirs=$PS_HOME/lib \

+    jpl.eda.ExecServer \

+    jpl.eda.product.rmi.ProductServiceImpl \

+    urn:eda:rmi:MyProductService</source>

+

+	<p>Like with the RMI server, this tells Java where to find

+	  extension jars (<code>$PS_HOME/lib</code>).  The main class

+	  is <code>jpl.eda.ExecServer</code>, this is a framework

+	  class from <code>edm-commons</code> that provides basic

+	  start-up functions for a variety of services.  In this case,

+	  the service is

+	  <code>jpl.eda.product.rmi.ProductServiceImpl</code>; this is

+	  the name of the class that provides the RMI version of the

+	  OODT product service.  We then pass in one final

+	  command-line argument,

+	  <code>urn:eda:rmi:MyProductService</code>.  This names the product service.

+	</p>

+      </subsection>

+

+      <subsection name="What's in a Name?">

+	<p>The product service registers itself using a name provided

+	  on the command-line, in this case,

+	  <code>urn:eda:rmi:MyProductService</code>.  Let's take apart

+	  the name and see how it works.

+	</p>

+

+	<p>If you're familiar with web standards, you can see that the

+	  name is a Uniform Resource Name (URN), since it starts with

+	  <code>urn:</code>.  The OODT Framework uses URNs to identify

+	  services and other objects.  The <code>eda:</code> tells

+	  that the name is part of the Enterprise Data Architecture

+	  (EDA) namespace.  (EDA was the name of a project related to

+	  OODT that was merged with OODT.  For now, just always use

+	  <code>eda:</code> in your URNs.)

+	</p>

+	

+	<p>Next comes <code>rmi:</code>.  This is a special flag for

+	  the OODT services that tells that we're using a name of an

+	  RMI-accessible object.  The OODT framework will know to use

+	  an RMI Registry to register the server. 

+	</p>

+

+	<p>Finally is <code>MyProductService</code>.  This is the

+	  actual name used in the RMI Registry.  You can call your

+	  product service anything you want.  For example, suppose you

+	  have three product servers; one in the US, one in Canada,

+	  and one in Australia.  You might name them:

+	</p>

+

+	<ul>

+	  <li><code>urn:eda:rmi:US</code></li>

+	  <li><code>urn:eda:rmi:Canada</code></li>

+	  <li><code>urn:eda:rmi:Australia</code></li>

+	</ul>

+

+	<p>Or you might prefer to use ISO country codes.  Or you might

+	  name them according to the kinds of products they serve,

+	  such as <code>urn:eda:rmi:Biomarkers</code> or

+	  <code>urn:eda:rmi:BusniessForecasts</code>.

+	</p>

+

+	<p>The RMI Registry will happily re-assign a name if one's

+	  already in use, so when deploying your own product servers,

+	  be sure to give each one a unique name.

+	</p>

+      </subsection>

+

+      <subsection name="Launching the Product Server">

+	<p>Make the <code>ps</code> script executable and start the

+	  product server at this time.  Do this in a separate window

+	  with the appropriate setting of <code>PS_HOME</code>:

+	</p>

+

+	<source>% <b>chmod 755 $PS_HOME/bin/ps</b>

+% <b>$PS_HOME/bin/ps</b>

+Object context ready; delegating to: [jpl.eda.object.jndi.RMIContext@94257f]</source>

+

+	<p>The product service is now running and ready to accept

+	  product queries.  Since we didn't tell it what query

+	  handlers to use, it will always respond with zero matching

+	  products.  That may not be interesting, but it's a good test

+	  to see if we can at least launch a product server.  Now,

+	  let's launch a product client and query it.

+	</p>

+      </subsection>

+    </section>

+

+    <section name="Querying the Product Server">

+      <p>To query the product server, we use a product client.  The

+	Java class <code>jpl.eda.product.ProductClient</code> provides

+	the API for your own programs to query for and retrieve

+	products.  But it's also an executable class, so we can run it

+	from the command-line in order to test our product server.

+	However, let's again make a script to make invoking it a bit

+	easier.

+      </p>

+

+      <p>We'll call the script <code>pc</code> for "product client,"

+	and it will take a single command line argument, which will be

+	the <em>query expression</em> to pass into the product server.

+	Query expressions define the constraints on the kinds of

+	products we want to achieve.  Since the product server we've

+	set up will always respond with zero products, though, we can

+	pass in any syntactically valid query expression.

+      </p>

+

+      <p>Here's the script:</p>

+

+      <source>#!/bin/sh

+if [ $# -ne 1 ]; then

+   echo "Usage: `basename $0` &lt;query-expression&gt;" 1>&amp;2

+   exit 1

+fi

+

+exec java -Djava.ext.dirs=$PS_HOME/lib \

+     jpl.eda.product.ProductClient \

+     -out \

+     urn:eda:rmi:MyProductService \

+     "$1"</source>

+

+

+      <p>This script checks to make sure there's exactly one

+	command-line argument, the query expression.  If there isn't,

+	it prints a helpful usage message to the standard error

+	stream, as is Unix tradition.  Otherwise, it will execute the

+	<code>jpl.eda.product.ProductClient</code> class with Java.

+	When executed, this class expects three command-line arguments:

+      </p>

+

+      <ol>

+	<li><code>-out</code> or <code>-xml</code>.  OODT uses XML to

+	  represent the query that it passes to and receives back from

+	  a product server.  With <code>-out</code>, the product

+	  client will write to the standard output the raw product

+	  data.  With <code>-xml</code>, you'll instead see the XML

+	  representation of the query (with any embedded matching

+	  products) instead.

+	</li>

+

+	<li>The name of the product service to contact.  In this case,

+	  we're using the one we started earlier, registered under the

+	  name <code>urn:eda:rmi:MyProductService</code>.

+	</li>

+

+	<li>The query expression.</li>

+      </ol>

+

+      <p>Now we can make this script executable and run it:</p>

+

+      <source>% <b>chmod 755 $PS_HOME/bin/pc</b>

+<b>$PS_HOME/bin/pc "x = 3"</b>

+Object context ready; delegating to: [jpl.eda.object.jndi.RMIContext@c79809]

+No matching results</source>

+

+      <p>Although not terribly exciting, this is good news.  Here's

+	what happened:

+      </p>

+

+      <ol>

+	<li>The product client created a query object (of class

+	  <code>jpl.eda.xmlquery.XMLQuery</code> from the

+	  <code>edm-query</code> component) out of the string query

+	  <code>x = 3</code>.

+	</li>

+

+	<li>It asked the RMI Registry to tell it where (network

+	  address) it could find the product service named

+	  <code>MyProductService</code>.

+	</li>

+

+	<li>After getting the response back from the RMI Registry, it

+	  then contacted the product service over a network connection

+	  (even if to the same local system) and asked it to handle

+	  the query, passing the query object.

+	</li>

+

+	<li>The product service, having no query handlers to which to

+	  delegate, merely returned the query object unmodified over

+	  the network connection.

+	</li>

+

+	<li>The product client, having no product to write to the

+	  standard output (as indicated by the <code>-out</code>

+	  argument), wrote the diagnostic message <code>No matching

+	  results</code>.

+	</li>

+      </ol>

+

+      <p>You can make this example slightly more interesting by

+	changing the <code>-out</code> in the <code>pc</code> script

+	to <code>-xml</code>.  Now, when you run it, you'll see an XML

+	document describing the query.  One of the pertinent sections

+	to note is:

+      </p>

+

+      <source>...&lt;queryResultSet/&gt;...</source>

+

+      <p>This empty XML element means that there were no results.</p>

+    </section>

+

+    <section name="Conclusion">

+      <p>By following this tutorial, you've started both an RMI

+	Registry and a basic product server.  You've queried that

+	product server to insure that you can communicate with it.  In

+	later tutorials, you'll build on this product server by adding

+	a query handler to it and returning actual product data.

+      </p>

+    </section>

+

+  </body>

+</document>

diff --git a/0.8.1-rc1/product/src/site/xdoc/tutorials/qh/index.xml b/0.8.1-rc1/product/src/site/xdoc/tutorials/qh/index.xml
new file mode 100755
index 0000000..c684ad7
--- /dev/null
+++ b/0.8.1-rc1/product/src/site/xdoc/tutorials/qh/index.xml
@@ -0,0 +1,704 @@
+<?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.

+-->

+<document>

+  <properties>

+    <title>Developing a Query Handler</title>

+    <author email="Sean.Kelly@jpl.nasa.gov">Sean Kelly</author>

+  </properties>

+

+  <body>

+    <section name="Developing a Query Handler">

+      <p>In the <a href="../ps/">last tutorial</a>, we started a

+	product server.  But this wasn't a very useful product server;

+	it could answer queries but always respond with no results.

+	That's because it had no query handlers.  Query handlers have

+	the responsibility of actually handling product queries.  In

+	this tutorial, we'll develop a query handler, install it into

+	our product server, and query it to see if it works.

+      </p>

+

+      <p>To do this tutorial, you'll need mastery of two things:</p>

+      <ul>

+	<li>Using the <code>XMLQuery</code> class.  Follow the <a

+	    href="/edm-query/tutorial/">query expression tutorail</a>

+	    now if you're not familiar with it.

+	</li>

+

+	<li>Running and querying a product server.  Follow the <a

+	    href="../ps/">Your First Product Server</a> tutorial to

+	    get your product server up and running.  In this tutorial,

+	    we'll build on that product server, so it's especially

+	    important to have it in good shape.

+	</li>

+      </ul>

+    </section>

+

+    <section name="Serving Up Constants">

+      <p>Product servers delegate to query handlers.  It's the job of

+	query handlers to interpret incoming queries (expressed as

+	<code>XMLQuery</code> objects), search for, retrieve, convert,

+	or synthesize matching product results, adorn the

+	<code>XMLQuery</code> object with <code>Result</code> objects,

+	and return the modified query.  At that point the OODT

+	framework takes over again and tries other installed query

+	handlers, eventually returning the completed

+	<code>XMLQuery</code> back to the product client that made the

+	query in the first place.

+      </p>

+

+      <p>We'll make a query handler that serves mathematical

+	constants.  Have you ever been in a position where you needed,

+	say, the value of the third Flajolet number or perhaps

+	Zeta(9)?  No?  Well, just pretend for now you did.  What we'll

+	do is develop a query handler for a product server that will

+	serve values of various mathematical constants.

+      </p>

+

+      <p>The approach we'll take has three simple steps:</p>

+

+      <ol>

+	<li>Get some handy constants.</li>

+	<li>Define the query expression.</li>

+	<li>Write a query handler.  The query handler will:

+	  <ol>

+	    <li>Examine the query expression to see if it's a request

+	      for a constant, and if so, what constant is

+	      requested.

+	    </li>

+	    <li>Examine the query's list of acceptable MIME types.</li>

+	    <li>If both check out, look up the desired constant's value.</li>

+	    <li>If found, add it as a <code>Result</code> in the <code>XMLQuery</code>.</li>

+	  </ol>

+	</li>

+      </ol>

+    </section>

+

+    <section name="Writing the Code">

+      <p>In this section, we'll build up the query handler source code

+	in pieces, examining each piece thoroughly.  We'll then

+	present the entire source file.

+      </p>

+

+      <subsection name='Gathering Handy Constants'>

+	<p>The wonderful world of science and mathematics is replete

+	  with useful constant values.  For this example, let's just pick three:

+	</p>

+

+	<ul>

+	  <li><var>pi</var> = 3.14159265...</li>

+	  <li><var>e</var> = 2.7182818285...</li>

+	  <li><var>gamma</var> = 0.577215664...</li>

+	</ul>

+

+	<p>In Java code, we can set up those values as a

+	  <code>Map</code> in a static field.  Thus we start forming our

+	  source file, <code>ConstantHandler.java</code>:

+	</p>

+

+	<source>import java.util.HashMap;

+import java.util.Map;

+import jpl.eda.product.QueryHandler;

+public class ConstantHandler

+  implements QueryHandler {

+  private static final Map CONSTANTS = new HashMap();

+  static {

+    CONSTANTS.put("pi",    "3.14159265...");

+    CONSTANTS.put("e",     "2.7182818285...");

+    CONSTANTS.put("gamma", "0.577215664...");

+  }

+}</source>

+

+	<p>As you can see, we're storing both the constant name and its

+	  value as <code>java.lang.String</code> objects.

+	</p>

+      </subsection>

+

+      <subsection name='Defining the Query Expression'>

+	<p>Recall that the <code>XMLQuery</code> class can use parsed

+	  queries (where it generates postfix boolean stacks) or

+	  unparsed ones.  While unparsed ones are easier, we'll go with

+	  parsed ones to demonstrate how on the server-side you deal

+	  with those postfix stacks.

+	</p>

+

+	<p>Using the XMLQuery's expression language, we'll look for

+	  queries of the form:</p>

+	

+	<p><code>constant = <var>name</var></code></p>

+

+	<p>where <var>name</var> is the name of a constant.  That will

+	  form a postfix "where" stack with exactly three

+	  <code>QueryElement</code> objects on it:

+	</p>

+

+	<ol>

+	  <li>The first (top) <code>QueryElement</code> will have role =

+	    <code>elemName</code> and value = <code>constant</code>.

+	  </li>

+

+	  <li>The second (middle) <code>QueryElement</code> will have

+	    role = <code>LITERAL</code> and a value equal to the

+	    constant <var>name</var>.

+	  </li>

+

+	  <li>The third (bottom) <code>QueryElement</code> will have

+	    role = <code>RELOP</code> and value = <code>EQ</code>.

+	  </li>

+	</ol>

+

+	<p>If we get any other kind of stack, we'll reject it and return

+	  no matching results.  That's reasonable behavior; after all, a

+	  query for <code>donutsEaten &gt; 5 AND RETURN =

+	    episodeNumber</code> may be handled by a

+	  <code>SimpsonsEpisodeQueryHandler</code> that's <em>also</em>

+	  installed in the same product server.

+	</p>

+

+	<p>We'll define a utility method, <code>getConstantName</code>,

+	  that will take the <code>XMLQuery</code>, check for the

+	  postfix "where" stack as described, and return the matching

+	  constant <var>name</var>.  If it gets a stack whose structure

+	  doesn't match, it will return <code>null</code>.  We'll add

+	  this method to our <code>ConstantHandler.java</code> file:

+	</p>

+

+	<source>import java.util.List;

+import jpl.eda.xmlquery.XMLQuery;

+import jpl.eda.xmlquery.QueryElement;

+...

+public class ConstantHandler

+  implements QueryHandler {

+  ...

+  private static String getConstantName(XMLQuery q) {

+    List stack = q.getWhereElementSet();

+    if (stack.size() != 3) return null;

+    QueryElement e = (QueryElement) stack.get(0);

+    if (!"elemName".equals(e.getRole())

+      || !"constant".equals(e.getValue()))

+      return null;

+    e = (QueryElement) stack.get(2);

+    if (!"RELOP".equals(e.getRole())

+      || !"EQ".equals(e.getValue()))

+      return null;

+    e = (QueryElement) stack.get(1);

+    if (!"LITERAL".equals(e.getRole()))

+	return null;

+    return e.getValue();

+  }

+}</source>

+

+	<p>Here, we first check to make sure there's exactly three

+	  elements, returning null if not.  There's no need to go further.

+	</p>

+

+	<p>Assuming there's three elements, the code then checks the

+	  topmost element.  For an expression <code>constant =

+	    <var>name</var></code>, the topmost element will have role

+	  <code>elemName</code> and value <code>constant</code>.  If

+	  neither condition is true, we return null right away.  No need

+	  to check further.

+	</p>

+

+	<p>If the topmost element checks out, we then check the

+	  bottommost element.  For <code>constant =

+	    <var>name</var></code>, the bottom element is generated from

+	  the equals sign.  It will have role <code>RELOP</code>

+	  (relational operator) and value <code>EQ</code>, meaning

+	  "equals".

+	</p>

+

+	<p>If it checks out, all we have to do is check the middle

+	  element.  The infix expression <code>constant =

+	    <var>name</var></code> generates a postfix middle element of

+	  <var>name</var> as the value, with a role of

+	  <code>LITERAL</code>.  We make sure it's <code>LITERAL</code>.

+	  If not, we're done; it's not a valid expression for our query

+	  handler.

+	</p>

+

+	<p>But if so, then the value of that query element is the name

+	  of the desired constant.  So we return it, regardless of what

+	  it is.

+	</p>

+      </subsection>

+

+      <subsection name='Checking for Acceptable MIME Types'>

+	<p>Since all of our mathematical constants are strings, we'll

+	  say that the result MIME type of our products is

+	  <code>text/plain</code>.  That means that any incoming

+	  <code>XMLQuery</code> must include any of the following MIME types:

+	</p>

+	<ol>

+	  <li><code>text/plain</code></li>

+	  <li><code>text/*</code></li>

+	  <li><code>*/*</code></li>

+	</ol>

+	<p>All of these match <code>text/plain</code>, which is the only

+	  product type we're capable of serving.  (In your own product

+	  servers, you might have more complex logic; for example, you

+	  could write code to draw the numbers into an image file if the

+	  requested type is <code>image/jpeg</code> ... but I wouldn't

+	  want to.)

+	</p>

+	<p>To support this in our query handler, we'll write another

+	  utility method.  It'll be called

+	  <code>isAcceptableType</code>, and it will take the

+	  <code>XMLQuery</code> and examine it to see what MIME types

+	  are acceptable to the caller.  If it finds any of the ones in

+	  the above list, it will return <code>true</code>, and the

+	  caller can continue to process the query.  If not, it will

+	  return <code>false</code>, and the query handler will stop

+	  processing and return the <code>XMLQuery</code> unadorned with

+	  any results.

+	</p>

+	<p>Here's the code:</p>

+

+	<source>import java.util.Iterator;

+...

+public class ConstantHandler

+  implements QueryHandler {

+  ...

+  private static boolean isAcceptableType(XMLQuery q) {

+    List mimes = q.getMimeAccept();

+    if (mimes.isEmpty()) return true;

+    for (Iterator i = mimes.iterator(); i.hasNext();) {

+      String type = (String) i.next();

+      if ("text/plain".equals(type)

+        || "text/*".equals(type)

+        || "*/*".equals(type)) return true;

+    }

+    return false;

+  }

+}</source>

+

+	<p>Here, we check if the list of acceptable MIME types is empty.

+	  An empty list is the same as saying <code>*/*</code>, so that

+	  automatically says we've got an acceptable type.  For a

+	  non-empty list, we go through each type one-by-one.  If it's

+	  any of the strings <code>text/plain</code>,

+	  <code>text/*</code>, or <code>*/*</code>, then that's an

+	  acceptable type.

+	</p>

+

+	<p>However, if we get through the entire list and we don't find

+	  any type that the user wants that we can provide, we return

+	  <code>false</code>.  The query handler will check for a

+	  <code>false</code> value and return early from handling the

+	  query, leaving the <code>XMLQuery</code> untouched.

+	</p>

+      </subsection>

+

+      <subsection name='Inserting the Result'>

+	<p>Assuming the query handler has found an acceptable MIME type,

+	  and has found a valid query and the name of the desired

+	  constant, it can lookup the constant in the

+	  <code>CONSTANTS</code> map.  And assuming it finds a matching

+	  constant in that map, it can insert the value as a

+	  <code>Result</code> object.

+	</p>

+

+	<p>To insert the constant's value, we'll develop yet another

+	  utility method, this time called <code>insert</code>.  This

+	  method will take the name of the constant, its value, and the

+	  <code>XMLQuery</code>.  It will add a <code>Result</code>

+	  object to the <code>XMLQuery</code>.  When the query handler

+	  returns this modified <code>XMLQuery</code> object, the

+	  framework will return it to the product client, which can then

+	  display the matching result.

+	</p>

+

+	<p><code>Result</code> objects can also have optional

+	  <code>Header</code> objects that serve as "column headings"

+	  for tabular like results.  Our result isn't tabular, it's just

+	  a single value, but we'll add a heading anyway just to

+	  demonstrate how it's done.  (You could argue that it's a

+	  one-by-one table, too!)  The header's name will be the same as

+	  the constant's name; the data type will be <code>real</code>

+	  and the units will be <code>none</code>.

+	</p>

+

+	<p>Here's the code:</p>

+

+	<source>import java.util.Collections;

+import jpl.eda.xmlquery.Header;

+import jpl.eda.xmlquery.Result;

+...

+public class ConstantHandler

+  implements QueryHandler {

+  ...

+  private static void insert(String name,

+    String value, XMLQuery q) {

+    Header h = new Header(name, "real", "none");

+    Result r = new Result(name, "text/plain",

+      /*profileID*/null, /*resourceID*/null,

+      Collections.singletonList(h),

+      value, /*classified*/false, Result.INFINITE);

+    q.getResults().add(r);

+  }

+}</source>

+

+	<p>In this method, we first create the header.  Then we create

+	  the result; the result's ID (which differentiates it from

+	  other results in the same <code>XMLQuery</code> is just the

+	  name of the constant.  Its MIME type is

+	  <code>text/plain</code>.  We set the profile ID and resource

+	  ID fields to <code>null</code>, as recommended back in the <a

+	    href="/edm-query/tutorial/">XMLQuery Tutorial</a>.  Then we

+	  add our sole header.  Then we add the mathematical constant's

+	  value.  Finally, this constant isn't classified, so we set the

+	  classified flag to <code>false</code>.  Also, these

+	  mathematical constants should be valid forever, so we set the

+	  validity period to <code>Result.INFINITE</code>, a special

+	  value that means a never-ending validity period.

+	</p>

+      </subsection>

+

+      <subsection name='Handling the Query'>

+	<p>With all of these utility methods in hand, it's easy to

+	  handle the query now.  The

+	  <code>jpl.eda.product.QueryHandler</code> interface

+	  specifies a single method that we must implement,

+	  <code>query</code>.  This method accepts an

+	  <code>XMLQuery</code> object and returns an

+	  <code>XMLQuery</code> object.  The returned one may or may

+	  not be adorned with matching results.

+	</p>

+

+	<p>Here's what we have to do:</p>

+	<ol>

+	  <li>Get the constant name with <code>getConstantName</code>.

+	    If we get <code>null</code>, it means the query's not of

+	    the form <code>constant = <var>name</var></code>, so we

+	    ignore it.

+	  </li>

+

+	  <li>See if the user's willing to accept a

+	    <code>text/plain</code> MIME type.  If not, we ignore this query.

+	  </li>

+

+	  <li>Find the constant in our <code>CONSTANTS</code> map.  If

+	    it's not there, we ignore this query.

+	  </li>

+

+	  <li>Insert the constant's value into the <code>XMLQuery</code>.</li>

+

+	  <li>Returned the modified <code>XMLQuery</code>.</li>

+	</ol>

+

+	<p>The source:</p>

+

+	<source>public class ConstantHandler

+  implements QueryHandler {

+  ...

+  public XMLQuery query(XMLQuery q) {

+    String name = getConstantName(q);

+    if (name == null) return q;

+    if (!isAcceptableType(q)) return q;

+    String value = (String) CONSTANTS.get(name);

+    if (value == null) return q;

+    insert(name, value, q);

+    return q;

+  }

+}</source>

+

+      </subsection>

+

+      <subsection name='Complete Source Code'>

+	<p>Here is the complete source file,

+	<code>ConstantHandler.java</code>:</p>

+

+	<source>import java.util.Collections;

+import java.util.HashMap;

+import java.util.Iterator;

+import java.util.List;

+import java.util.Map;

+import jpl.eda.product.QueryHandler;

+import jpl.eda.xmlquery.Header;

+import jpl.eda.xmlquery.Result;

+import jpl.eda.xmlquery.QueryElement;

+import jpl.eda.xmlquery.XMLQuery;

+

+public class ConstantHandler

+  implements QueryHandler {

+  private static final Map CONSTANTS = new HashMap();

+  static {

+    CONSTANTS.put("pi",    "3.14159265...");

+    CONSTANTS.put("e",     "2.7182818285...");

+    CONSTANTS.put("gamma", "0.577215664...");

+  }

+  private static String getConstantName(XMLQuery q) {

+    List stack = q.getWhereElementSet();

+    if (stack.size() != 3) return null;

+    QueryElement e = (QueryElement) stack.get(0);

+    if (!"elemName".equals(e.getRole())

+      || !"constant".equals(e.getValue()))

+      return null;

+    e = (QueryElement) stack.get(2);

+    if (!"RELOP".equals(e.getRole())

+      || !"EQ".equals(e.getValue()))

+      return null;

+    e = (QueryElement) stack.get(1);

+    if (!"LITERAL".equals(e.getRole()))

+	return null;

+    return e.getValue();

+  }

+  private static boolean isAcceptableType(XMLQuery q) {

+    List mimes = q.getMimeAccept();

+    if (mimes.isEmpty()) return true;

+    for (Iterator i = mimes.iterator(); i.hasNext();) {

+      String type = (String) i.next();

+      if ("text/plain".equals(type)

+        || "text/*".equals(type)

+        || "*/*".equals(type)) return true;

+    }

+    return false;

+  }

+  private static void insert(String name,

+    String value, XMLQuery q) {

+    Header h = new Header(name, "real", "none");

+    Result r = new Result(name, "text/plain",

+      /*profileID*/null, /*resourceID*/null,

+      Collections.singletonList(h),

+      value, /*classified*/false, Result.INFINITE);

+    q.getResults().add(r);

+  }

+  public XMLQuery query(XMLQuery q) {

+    String name = getConstantName(q);

+    if (name == null) return q;

+    if (!isAcceptableType(q)) return q;

+    String value = (String) CONSTANTS.get(name);

+    if (value == null) return q;

+    insert(name, value, q);

+    return q;

+  }

+}</source>

+

+	<p>How should you go about compiling this and installing it in

+	  a product server?  Read on!

+	</p>

+      </subsection>

+    </section>

+

+    <section name="Compiling the Code">

+      <p>We'll compile this code using the J2SDK command-line tools,

+	but if you're more comfortable with some kind of Integrated

+	Development Environment (IDE), adjust as necessary.

+      </p>

+

+      <p>First, let's go back to the <code>$PS_HOME</code> directory

+	we made earlier and make directories to hold both the source

+	code and classes that we'll compile from it:

+      </p>

+

+      <source>% <b>cd $PS_HOME</b>

+% <b>mkdir classes src</b></source>

+

+      <p>Then, create <code>$PS_HOME/src/ConstantHandler.java</code> using

+	your favorite text editor (or by cutting and pasting the source

+	from this page, or whatever).  Finally, compile the file as follows:

+      </p>

+

+      <source>% <b>javac -extdirs lib \

+  -d classes src/ConstantHandler.java</b>

+% ls -l classes

+total 4

+-rw-r--r--  1 kelly  kelly  2524 25 Feb 15:46 ConstantHandler.class</source>

+

+      <p>The <code>javac</code> command is the Java compiler.  The

+	<code>-extdirs lib</code> arguments tell the compiler where to

+	find extension jars.  In this case, the code references things

+	defined in edm-query-2.0.2.jar and grid-product-3.0.3.jar.

+	The <code>-d classes</code> tells where compiled classes

+	should go.

+      </p>

+

+      <p>Next, make a jar file that contains your compiled class:</p>

+

+      <source>% <b>jar -cf lib/my-handlers.jar \

+  -C classes ConstantHandler.class</b>

+% <b>jar -tf lib/my-handlers.jar</b>

+META-INF/

+META-INF/MANIFEST.MF

+ConstantHandler.class</source>

+

+      <p>We now have a new jar file of our own creation in the

+	<code>$PS_HOME/lib</code> directory; this means that the

+	product server will be able to find out new query handler.

+	All we have to do now is tell our product server about it.

+      </p>

+    </section>

+

+    <section name='Specfying the Query Handler'>

+      <p>Query handlers aren't really <em>installed</em> into product

+	servers.  What you do is tell the product server what query

+	handlers you want it to use by naming their classes.  The

+	product server will instantiate an object of each class and,

+	as queries come in, it will delegate queries to each

+	instantiated query handler.

+      </p>

+

+      <p>To tell a product server what query handlers to instantiate,

+	you specify a system property called <code>handlers</code>.

+	You set this property to a comma-separated list of class

+	names.  These should be fully-qualified class names (with

+	package prefixes, if you used packages when making your query

+	handlers), separated by commas.  In this tutorial, we made

+	just one query handler, and we didn't put it into a package,

+	so we'll just use <code>ConstantHandler</code>.

+      </p>

+

+      <p>First, stop any product server you have running now by

+	pressing CTRL+C (or whatever your interrupt key is) in the

+	window that was running the product server.  Next, modify the

+	<code>$PS_HOME/bin/ps</code> file so it reads as follows:

+      </p>

+

+      <source>#!/bin/sh

+exec java -Djava.ext.dirs=$PS_HOME/lib \

+    -Dhandlers=ConstantHandler \

+    jpl.eda.ExecServer \

+    jpl.eda.product.rmi.ProductServiceImpl \

+    urn:eda:rmi:MyProductService</source>

+

+      <p>We specified a system property on the command line using

+	Java's <code>-D</code> option.  This defines the system

+	property <code>handlers</code> as having the value

+	<code>ConstantHandler</code>.  Finally, start the product

+	server again by running <code>$PS_HOME/bin/ps</code>.

+      </p>

+    </section>

+

+    <section name='Querying for Constants'>

+      <p>Once again, edit the <code>$PS_HOME/bin/pc</code> script and

+	change <code>-xml</code> back to <code>-out</code> so that

+	instead of the XML output we'll see the raw product data.

+	Then run it and see what happens:

+      </p>

+

+      <source>% <b>$PS_HOME/bin/pc 'constant = pi'</b>

+3.14159265...% </source>

+

+      <p>Because the raw product data was the string

+	<code>3.14159265...</code> without any trailing newline, the

+	shell's prompt appeared right at the end of the product

+	result.  You might try piping the output of the above command

+	through a pager like <code>more</code> or <code>less</code> to

+	avoid this.

+      </p>

+

+      <p>Here's what happened when we ran this command:</p>

+

+      <ol>

+	<li>The product client created an <code>XMLQuery</code> object

+	  out of the string query <code>constant = pi</code>.

+	</li>

+

+	<li>It asked the RMI Registry to tell it where (network

+	  address) it could find the product service named

+	  <code>MyProductService</code>.

+	</li>

+

+	<li>After getting the response back from the RMI Registry, it

+	  then contacted the product service over a network connection

+	  (even if to the same local system) and asked it to handle

+	  the query, passing the query object.

+	</li>

+

+	<li>The product service had only one query handler, the

+	  <code>ConstantHandler</code>, to which to delegate, so it

+	  passed the XMLQuery to it.

+	</li>

+

+	<li>The <code>ConstantHandler</code>'s <code>query</code>

+	  method was called.  It checked if the query was the kind it

+	  wanted, extracted the desired mathematical constant's name,

+	  checked for an acceptable requested MIME type, looked up the

+	  constant's value, inserted it as a <code>Result</code> into

+	  the <code>XMLQuery</code>, and returned the modified query.

+	</li>

+

+	<li>The product service, seeing it had no other handlers to

+	  try, returned the modified <code>XMLQuery</code> to the

+	  product client over the network connection.

+	</li>

+

+	<li>The product client took the first <code>Result</code> out

+	  of the <code>XMLQuery</code>, called

+	  <code>Result.getInputStream</code>, and copied each byte of

+	  the result to the standard output.  This wrote

+	  <code>3.14159265...</code> to your window.

+	</li>

+      </ol>

+

+      <p>If you change the <code>$PS_HOME/bin/pc</code> script again

+	so that instead of <code>-out</code> it's <code>-xml</code>,

+	you'll again see the XMLQuery as an XML document.  The interesting part is the <code>&lt;queryResultSet&gt;</code>:

+      </p>

+

+      <source><![CDATA[<queryResultSet>

+  <resultElement classified="false" validity="-1">

+    <resultId>pi</resultId>

+    <resultMimeType>text/plain</resultMimeType>

+    <profId/>

+    <identifier/>

+    <resultHeader>

+      <headerElement>

+	<elemName>pi</elemName>

+	<elemType>real</elemType>

+	<elemUnit>none</elemUnit>

+      </headerElement>

+    </resultHeader>

+    <resultValue xml:space="preserve">3.14159265...</resultValue>

+  </resultElement>

+</queryResultSet>]]></source>

+

+      <p>I'll let you figure out how this maps to the

+	<code>Result</code> object we created in the code.  OK, so is

+	this really interesting?  Not really, except to note that the

+	actual result data, <code>3.1415265...</code>, appears in the

+	XML document.  In the OODT framework, we call this a "small"

+	result, because the product data was embedded in the XMLQuery

+	object.  Text data like <code>text/plain</code> products

+	appear just as text.  Binary data like <code>image/jpeg</code>

+	and <code>application/octet-stream</code> get base-64 encoded

+	into text.

+      </p>

+      <p>As you can guess, there's a point at which encoded data goes

+	from being nice and small and tidy to just too large to

+	contain in a single object.  In the OODT framework, we can use

+	a special query handler for such large products, but that's

+	another tutorial.

+      </p>

+    </section>

+

+    <section name='Conclusion'>

+      <p>In this tutorial, we learned how to write a complete query

+	handler for a product server, including handling of postfix

+	boolean "where" stacks, lists of acceptable MIME types, and

+	result headers.  We compiled the query handler, put it into a

+	jar file, and specified it to our product server.  And we

+	could even query it and get data back.

+      </p>

+

+      <p>Don't toss out this product server yet, though.  Another

+	tutorial will use it and cover the infamous

+	<code>LargeProductQueryHandler</code>.

+      </p>

+    </section>

+  </body>

+</document>

diff --git a/0.8.1-rc1/product/src/test/org/apache/oodt/product/handlers/ofsn/util/OFSNUtilsTest.java b/0.8.1-rc1/product/src/test/org/apache/oodt/product/handlers/ofsn/util/OFSNUtilsTest.java
new file mode 100644
index 0000000..31a4494
--- /dev/null
+++ b/0.8.1-rc1/product/src/test/org/apache/oodt/product/handlers/ofsn/util/OFSNUtilsTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product.handlers.ofsn.util;
+
+import junit.framework.TestCase;
+/*
+ * 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.
+ */
+
+import java.util.Collections;
+
+/**
+ * Unit test for {@link OFSNUtils}.
+ *
+ * @author riverma
+ */
+public class OFSNUtilsTest extends TestCase {
+    public OFSNUtilsTest(String id) {
+        super(id);
+    }
+
+    public void testValidateOFSN() {
+        
+        assertTrue(OFSNUtils.validateOFSN("/dataset/dir1"));
+        assertTrue(OFSNUtils.validateOFSN("/dataset/dir1/"));
+        assertTrue(OFSNUtils.validateOFSN("/dataset/dir1/file1.h5"));
+        assertFalse(OFSNUtils.validateOFSN("/dataset/../../../../../../etc/passwd"));
+        
+    }
+}
diff --git a/0.8.1-rc1/product/src/test/org/apache/oodt/xmlquery/ChunkedProductInputStreamTest.java b/0.8.1-rc1/product/src/test/org/apache/oodt/xmlquery/ChunkedProductInputStreamTest.java
new file mode 100644
index 0000000..9ab531a
--- /dev/null
+++ b/0.8.1-rc1/product/src/test/org/apache/oodt/xmlquery/ChunkedProductInputStreamTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.IOException;
+import java.util.Arrays;
+import org.apache.oodt.product.ProductException;
+import org.apache.oodt.product.Retriever;
+import junit.framework.TestCase;
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Unit test for <code>ChunkedProductInputStream</code>.
+ *
+ * @author Kelly
+ * @version $Revision: 1.5 $
+ */
+public class ChunkedProductInputStreamTest extends TestCase implements Retriever {
+	/**
+	 * Creates a new <code>ChunkedProductInputStreamTest</code> instance.
+	 *
+	 * @param id Case name.
+	 */
+	public ChunkedProductInputStreamTest(String id) {
+		super(id);
+	}
+
+	public void setUp() throws Exception {
+		super.setUp();
+		data = new byte[4096];
+		for (int i = 0; i < 4096; ++i)
+			data[i] = (byte) (i % 256);
+	}
+
+	/**
+	 * Test reading a single byte at a time.
+	 *
+	 * @throws IOException if an error occurs.
+	 */
+ 	public void testByteReading() throws IOException {
+ 		ChunkedProductInputStream in = new ChunkedProductInputStream("test", this, 4096);
+ 		for (int i = 0; i < 4096; ++i)
+ 			assertEquals(toByte(i % 256), toByte(in.read() & 0xff));
+ 		assertEquals(-1, in.read());
+ 		in.close();
+ 	}
+
+	public void testArrayReading() throws IOException {
+		ChunkedProductInputStream in = new ChunkedProductInputStream("test", this, 4096);
+		ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
+		byte[] buf = new byte[256];
+		int num;
+		while ((num = in.read(buf)) != -1)
+			out.write(buf, 0, num);
+		in.close();
+		out.close();
+		assertTrue(Arrays.equals(data, out.toByteArray()));
+	}
+
+	/**
+	 * Test reading and skipping by various amounts.
+	 *
+	 * @throws IOException if an error occurs.
+	 */
+	public void testReadingAndSkipping() throws IOException {
+		ChunkedProductInputStream in = new ChunkedProductInputStream("test", this, 4096);
+		
+		byte[] buf = new byte[4];							    // Byte number:
+		assertEquals(0, in.read());							    // 0
+		assertEquals(0, in.skip(0));							    // 0
+		assertEquals(4, in.read(buf));							    // 1, 2, 3, 4
+		assertEquals(toByte(1), buf[0]);
+		assertEquals(toByte(2), buf[1]);
+		assertEquals(toByte(3), buf[2]);
+		assertEquals(toByte(4), buf[3]);
+		assertEquals(toByte(5), toByte(in.read()));					    // 5
+		assertEquals(4, in.skip(4));							    // 6, 7, 8, 9
+		assertEquals(toByte(10), toByte(in.read()));					    // 10
+		assertEquals(1000, in.skip(1000));						    // 11, 12, ..., 1010
+		assertEquals(toByte(1011 % 256), toByte(in.read()));				    // 1011
+
+		buf = new byte[1000];
+		int toRead = 1000;
+		int index = 0;
+		while (toRead > 0) {								    // 1012, 1013, ..., 2011
+			int numRead = in.read(buf, index, toRead);
+			if (numRead == -1)
+				fail("Premature EOF");
+			toRead -= numRead;
+			index += numRead;
+		}
+		for (int i = 0; i < buf.length; ++i)
+			assertEquals(data[i + 1012], buf[i]);
+
+		assertEquals(2, in.read(buf, 1, 2));						    // 2012, 2013
+		assertEquals(toByte(1012 % 256), buf[0]);
+		assertEquals(toByte(2012 % 256), buf[1]);
+		assertEquals(toByte(2013 % 256), buf[2]);
+		assertEquals(toByte(1015 % 256), buf[3]);
+
+		assertEquals(2082, in.skip(2083));						    // 2014, 2015, ..., 4095
+		// Shouldn't we get the -1 read first, and THEN get an IOException on subsequent reads?
+		try {
+			assertEquals(-1, in.read());
+		} catch (IOException ignore) {}
+		in.close();
+	}
+
+	/**
+	 * Test reading into larger and larger arrays.
+	 *
+	 * @throws IOException if an error occurs.
+	 */
+	public void testWideningWindows() throws IOException {
+		// Scary; this test hangs on Windows.  We really should investigate why as
+		// it could bite us on the bum in the future.
+		if (System.getProperty("os.name", "unknown").indexOf("Windows") != -1) return;
+
+		byte[] read = new byte[4096];
+		for (int size = 1; size <= 4096; size *= 2) {
+			byte[] buf = new byte[size];
+			ChunkedProductInputStream in = new ChunkedProductInputStream("test", this, 4096);
+			ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
+			int num;
+			while ((num = in.read(buf)) != -1)
+				out.write(buf, 0, num);
+			in.close();
+			out.close();
+			assertTrue(Arrays.equals(data, out.toByteArray()));
+		}
+	}
+
+	public byte[] retrieveChunk(String id, long offset, int length) {
+		if (!id.equals("test"))
+			throw new IllegalArgumentException("Unknown id " + id);
+		if (offset < 0 || offset > 4096 || length < 0 ||
+			(offset + length) > 4096 || (offset + length) < 0)
+			throw new IllegalArgumentException("Bad offset and/or length");
+		
+		int index = (int) offset;
+		byte[] sub = new byte[length];
+		System.arraycopy(data, index, sub, 0, length);
+		return sub;
+	}
+
+	private static byte toByte(int b) {
+		return (byte) (b & 0xff);
+	}
+
+	public void close(String id) {}
+
+	/** Test data. */
+	private byte[] data;
+}
diff --git a/0.8.1-rc1/product/src/test/org/apache/oodt/xmlquery/LargeResultTest.java b/0.8.1-rc1/product/src/test/org/apache/oodt/xmlquery/LargeResultTest.java
new file mode 100644
index 0000000..ff3679b
--- /dev/null
+++ b/0.8.1-rc1/product/src/test/org/apache/oodt/xmlquery/LargeResultTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import junit.framework.TestCase;
+import java.util.Collections;
+
+/**
+ * Unit test for {@link LargeResult}.
+ *
+ * @author Kelly
+ * @version $Revision: 1.2 $
+ */
+public class LargeResultTest extends TestCase {
+	public LargeResultTest(String id) {
+		super(id);
+	}
+
+	public void testLargeResults() {
+		LargeResult lr1 = new LargeResult("1.2.3", "text/plain", "JPL.Profile", "JPL.Resource", Collections.EMPTY_LIST, 1);
+		assertEquals("1.2.3", lr1.getID());
+		assertEquals("text/plain", lr1.getMimeType());
+		assertEquals("JPL.Profile", lr1.getProfileID());
+		assertEquals("JPL.Resource", lr1.getResourceID());
+		assertEquals(1, lr1.getSize());
+		assertTrue(lr1.getHeaders().isEmpty());
+
+		Result r = new Result("2.3.4", "application/vnd.jpl.large-product", "JPL.Profile", "JPL.Resource",
+			Collections.EMPTY_LIST, "text/plain 2");
+		LargeResult lr2 = new LargeResult(r);
+		assertEquals("text/plain", lr2.getMimeType());
+		assertEquals(2, lr2.getSize());
+
+		LargeResult lr3 = new LargeResult(lr2);
+		assertEquals("text/plain", lr2.getMimeType());
+		assertEquals(2, lr3.getSize());
+	}
+}
diff --git a/0.8.1-rc1/profile/pom.xml b/0.8.1-rc1/profile/pom.xml
new file mode 100644
index 0000000..92bf1a3
--- /dev/null
+++ b/0.8.1-rc1/profile/pom.xml
@@ -0,0 +1,135 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>oodt-profile</artifactId>
+  <name>Profile Service</name>
+  <description>The Profile Service describes and locates resources using metadata
+    descriptions.  These descriptions, called profiles, tell of a
+    resource's inception, composition, and location using a mix of
+    Dublin Core and ISO-11179 metadata as well as URIs for locations.
+    The Profile Service catalogs metadata descriptions and provides
+    creating, updating, and querying capabilities.</description>
+  <scm>
+   	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/profile</connection>
+   	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/profile</developerConnection>
+   	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/profile</url>
+  </scm>
+  <build>
+    <resources>
+      <resource>
+        <directory>${basedir}/src/main/dtd</directory>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <forkMode>once</forkMode>
+          <excludes>
+            <exclude>org/apache/oodt/profile/ProfileElementTestCase.java</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>audit</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>rat-maven-plugin</artifactId>
+            <configuration>
+              <excludes>
+                <exclude>**/testdata/*</exclude>
+                <exclude>**/handlers/lightweight/package.html</exclude>
+              </excludes>
+            </configuration>
+            <executions>
+              <execution>
+                <phase>verify</phase>
+                <goals>
+                  <goal>check</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-commons</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-xmlquery</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-filemgr</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.hp.hpl.jena</groupId>
+      <artifactId>jena</artifactId>
+      <version>2.6.3</version>
+    </dependency>
+    <dependency>
+      <groupId>com.ibm.icu</groupId>
+      <artifactId>icu4j</artifactId>
+      <version>3.4.4</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+      <version>3.0-alpha1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <version>1.3</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.0.4</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/profile/src/main/dtd/prof.dtd b/0.8.1-rc1/profile/src/main/dtd/prof.dtd
new file mode 100644
index 0000000..ee8af94
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/dtd/prof.dtd
@@ -0,0 +1,86 @@
+<?xml 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.
+-->
+
+<!ELEMENT profiles
+  (profile*)>
+
+<!ELEMENT profile
+  (profAttributes,
+   resAttributes,
+   profElement*)>
+
+    <!ELEMENT profAttributes
+      (profId, profVersion?, profType,
+       profStatusId, profSecurityType?, profParentId?, profChildId*,
+       profRegAuthority?, profRevisionNote*)>
+
+    <!ELEMENT resAttributes
+      (Identifier, Title?, Format*, Description?, Creator*, Subject*,
+       Publisher*, Contributor*, Date*, Type*, Source*,
+       Language*, Relation*, Coverage*, Rights*,
+       resContext+, resAggregation?, resClass, resLocation*)>
+
+    <!ELEMENT profElement
+      (elemId?, elemName, elemDesc?, elemType?, elemUnit?, 
+       elemEnumFlag, (elemValue* | (elemMinValue, elemMaxValue)),
+       elemSynonym*,
+       elemObligation?, elemMaxOccurrence?, elemComment?)>
+
+    <!ELEMENT profId (#PCDATA)>
+    <!ELEMENT profVersion (#PCDATA)>
+    <!ELEMENT profType (#PCDATA)>
+    <!ELEMENT profParentId (#PCDATA)>
+    <!ELEMENT profChildId (#PCDATA)>
+    <!ELEMENT profStatusId (#PCDATA)>
+    <!ELEMENT profSecurityType (#PCDATA)>
+    <!ELEMENT profRegAuthority (#PCDATA)>
+    <!ELEMENT profRevisionNote (#PCDATA)>
+
+    <!ELEMENT Identifier (#PCDATA)>
+    <!ELEMENT Title (#PCDATA)>
+    <!ELEMENT Format (#PCDATA)>
+    <!ELEMENT Description (#PCDATA)>
+    <!ELEMENT Creator (#PCDATA)>
+    <!ELEMENT Subject (#PCDATA)>
+    <!ELEMENT Publisher (#PCDATA)>
+    <!ELEMENT Contributor (#PCDATA)>
+    <!ELEMENT Date (#PCDATA)>
+    <!ELEMENT Type (#PCDATA)>
+    <!ELEMENT Source (#PCDATA)>
+    <!ELEMENT Language (#PCDATA)>
+    <!ELEMENT Relation (#PCDATA)>
+    <!ELEMENT Coverage (#PCDATA)>
+    <!ELEMENT Rights (#PCDATA)>
+    <!ELEMENT resContext (#PCDATA)>
+    <!ELEMENT resAggregation (#PCDATA)>
+    <!ELEMENT resClass (#PCDATA)>
+    <!ELEMENT resLocation (#PCDATA)>
+
+    <!ELEMENT elemId (#PCDATA)>
+    <!ELEMENT elemName (#PCDATA)>
+    <!ELEMENT elemType (#PCDATA)>
+    <!ELEMENT elemEnumFlag (#PCDATA)>
+    <!ELEMENT elemDesc (#PCDATA)>
+    <!ELEMENT elemSynonym (#PCDATA)>
+    <!ELEMENT elemUnit (#PCDATA)>
+    <!ELEMENT elemValue (#PCDATA)>	
+    <!ELEMENT elemMinValue (#PCDATA)>	
+    <!ELEMENT elemMaxValue (#PCDATA)>	
+    <!ELEMENT elemObligation (#PCDATA)>
+    <!ELEMENT elemMaxOccurrence (#PCDATA)>
+    <!ELEMENT elemComment (#PCDATA)>
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/DefaultFactory.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/DefaultFactory.java
new file mode 100644
index 0000000..33bbe3e
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/DefaultFactory.java
@@ -0,0 +1,56 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.profile;
+
+import java.util.List;
+import org.w3c.dom.Element;
+
+/**
+ * Default factory for profile objects.
+ *
+ * This factory creates the typical profile objects {@link RangedProfileElement}, {@link
+ * UnspecifiedProfileElement}, {@link EnumeratedProfileElement}, {@link Profile}, {@link
+ * ProfileAttributes}, and {@link ResourceAttributes}.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+class DefaultFactory implements ObjectFactory {
+	public RangedProfileElement createRangedProfileElement(Profile profile, String name, String id, String desc, String type,
+		String unit, List synonyms, boolean obligation, int maxOccurrence, String comments, String min, String max) {
+		return new RangedProfileElement(profile, name, id, desc, type, unit, synonyms, obligation, maxOccurrence,
+			comments, min, max);
+	}
+	public UnspecifiedProfileElement createUnspecifiedProfileElement(Profile profile, String name, String id, String desc,
+		String type, String unit, List synonyms, boolean obligation, int maxOccurrence, String comments) {
+		return new UnspecifiedProfileElement(profile, name, id, desc, type, unit, synonyms, obligation, maxOccurrence,
+			comments);
+	}
+	public EnumeratedProfileElement createEnumeratedProfileElement(Profile profile, String name, String id, String desc,
+		String type, String unit, List synonyms, boolean obligation, int maxOccurrence, String comments, List values) {
+		return new EnumeratedProfileElement(profile, name, id, desc, type, unit, synonyms, obligation, maxOccurrence,
+			comments, values);
+	}
+	public Profile createProfile(Element node) {
+		return new Profile(node, this);
+	}
+	public ProfileAttributes createProfileAttributes(Element node) {
+		return new ProfileAttributes(node);
+	}
+	public ResourceAttributes createResourceAttributes(Profile profile, Element node) {
+		return new ResourceAttributes(profile, node);
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/EnumeratedProfileElement.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/EnumeratedProfileElement.java
new file mode 100644
index 0000000..7e084c1
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/EnumeratedProfileElement.java
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.oodt.commons.util.XML;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.Resource;
+import java.net.URI;
+import java.util.Iterator;
+import org.w3c.dom.Element;
+
+/**
+ * Enumerated profile element.
+ *
+ * Objects of this class are elements of a profile that have several enumerated values.
+ *
+ * @author Kelly
+ */
+public class EnumeratedProfileElement extends ProfileElement {
+	/**
+	 * Create blank profile element belonging to the given profile.
+	 */
+	public EnumeratedProfileElement(Profile profile) {
+		super(profile);
+  values = new ArrayList();
+	}
+
+	/**
+	 * Create a profile element from constituent attributes.
+	 *
+	 * @param profile Profile to which this element belongs.
+	 * @param name Required name of the element.
+	 * @param id ID of the element.
+	 * @param desc Long description of the element.
+	 * @param type Data type of the element.
+	 * @param unit Units.
+	 * @param synonyms Collection of element IDs ({@link String}) that are synonyms for this element.
+	 * @param obligation True if this is a required element
+	 * @param maxOccurrence Maximum number of occurrences of this element.
+	 * @param comment Any comments about this element.
+	 * @param values Valid values.
+	 */
+	public EnumeratedProfileElement(Profile profile, String name, String id, String desc, String type, String unit,
+		List synonyms, boolean obligation, int maxOccurrence, String comment, List values) {
+		super(profile, name, id, desc, type, unit, synonyms, obligation, maxOccurrence, comment);
+		if (values.contains(null))
+			throw new IllegalArgumentException("Null item in 'values' not allowed for enumerated profile elements");
+		this.values = values;
+	}
+
+	protected boolean isEnumerated() {
+		return true;
+	}
+
+	protected void addValues(Node node) throws DOMException {
+		if (values == null) return;
+		for (Iterator i = values.iterator(); i.hasNext();) {
+			Element e = node.getOwnerDocument().createElement("elemValue");
+			e.appendChild(node.getOwnerDocument().createCDATASection((String) i.next()));
+			node.appendChild(e);
+		}
+	}
+
+	public String getMinValue() {
+		return "";
+	}
+
+	public String getMaxValue() {
+		return "";
+	}
+
+	public List getValues() {
+		return values;
+	}
+
+	protected void addElementSpecificProperties(Model model, Resource element, ProfileAttributes profAttr, URI uri) {
+		Utility.addProperty(model, element, Utility.edmValue, values, profAttr, uri);
+	}
+
+	/** Valid values. */
+	protected List values;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ObjectFactory.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ObjectFactory.java
new file mode 100755
index 0000000..e2b7a4d
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ObjectFactory.java
@@ -0,0 +1,109 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.profile;
+
+import java.util.List;
+import org.w3c.dom.Element;
+
+/**
+ * Factory to create profile-related objects.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+public interface ObjectFactory {
+	/**
+	 * Create a ranged profile element.
+	 *
+	 * @param profile a <code>Profile</code> value.
+	 * @param name a <code>String</code> value.
+	 * @param id a <code>String</code> value.
+	 * @param desc a <code>String</code> value.
+	 * @param type a <code>String</code> value.
+	 * @param unit a <code>String</code> value.
+	 * @param synonyms a <code>List</code> value.
+	 * @param obligation a <code>boolean</code> value.
+	 * @param maxOccurrence an <code>int</code> value.
+	 * @param comments a <code>String</code> value.
+	 * @param min a <code>double</code> value.
+	 * @param max a <code>double</code> value.
+	 * @return a <code>RangedProfileElement</code> value.
+	 */
+	RangedProfileElement createRangedProfileElement(Profile profile, String name, String id, String desc, String type,
+		String unit, List synonyms, boolean obligation, int maxOccurrence, String comments, String min, String max);
+
+	/**
+	 * Create a profile element with unspecified values.
+	 *
+	 * @param profile a <code>Profile</code> value.
+	 * @param name a <code>String</code> value.
+	 * @param id a <code>String</code> value.
+	 * @param desc a <code>String</code> value.
+	 * @param type a <code>String</code> value.
+	 * @param unit a <code>String</code> value.
+	 * @param synonyms a <code>List</code> value.
+	 * @param obligation a <code>boolean</code> value.
+	 * @param maxOccurrence an <code>int</code> value.
+	 * @param comments a <code>String</code> value.
+	 * @return an <code>UnspecifiedProfileElement</code> value.
+	 */
+	UnspecifiedProfileElement createUnspecifiedProfileElement(Profile profile, String name, String id, String desc, String type,
+		String unit, List synonyms, boolean obligation, int maxOccurrence, String comments);
+
+	/**
+	 * Create a profile element with enumerated values.
+	 *
+	 * @param profile a <code>Profile</code> value.
+	 * @param name a <code>String</code> value.
+	 * @param id a <code>String</code> value.
+	 * @param desc a <code>String</code> value.
+	 * @param type a <code>String</code> value.
+	 * @param unit a <code>String</code> value.
+	 * @param synonyms a <code>List</code> value.
+	 * @param obligation a <code>boolean</code> value.
+	 * @param maxOccurrence an <code>int</code> value.
+	 * @param comments a <code>String</code> value.
+	 * @param values a <code>List</code> value.
+	 * @return an <code>Enumerated</code> value.
+	 */
+	EnumeratedProfileElement createEnumeratedProfileElement(Profile profile, String name, String id, String desc, String type,
+		String unit, List synonyms, boolean obligation, int maxOccurrence, String comments, List values);
+
+	/**
+	 * Create a profile from a DOM node.
+	 *
+	 * @param node an <code>Element</code> value.
+	 * @return a <code>Profile</code> value.
+	 */
+	Profile createProfile(Element node);
+
+	/**
+	 * Create profile attributes from a DOM node.
+	 *
+	 * @param node an <code>Element</code> value.
+	 * @return a <code>ProfileAttributes</code> value.
+	 */
+	ProfileAttributes createProfileAttributes(Element node);
+
+	/**
+	 * Create resource attributes from a DOM node.
+	 *
+	 * @param profile Owning profile.
+	 * @param node an <code>Element</code> value.
+	 * @return a <code>ResourceAttributes</code> value.
+	 */
+	ResourceAttributes createResourceAttributes(Profile profile, Element node);
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/Profile.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/Profile.java
new file mode 100644
index 0000000..6d5406e
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/Profile.java
@@ -0,0 +1,391 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+import com.hp.hpl.jena.rdf.model.Property;
+import com.hp.hpl.jena.rdf.model.Resource;
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.apache.oodt.commons.Configuration;
+import org.apache.oodt.commons.util.Documentable;
+import org.apache.oodt.commons.util.XML;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.OutputStreamWriter;
+
+/**
+ * A profile.
+ *
+ * Objects of this class are profiles.  Profiles are metadata descriptions of resources.
+ *
+ * @author Kelly
+ */
+public class Profile implements Serializable, Cloneable, Comparable, Documentable {
+        /** Serial version unique ID. */
+        static final long serialVersionUID = -3936851809184360591L;
+
+	/** The formal public identifier of the profiles DTD. */
+	public static final String PROFILES_DTD_FPI = "-//JPL//DTD Profile 1.1//EN";
+
+	/** The system identifier of the profiles DTD. */
+	public static String PROFILES_DTD_URL = "http://oodt.jpl.nasa.gov/grid-profile/dtd/prof.dtd";
+
+	/**
+	 * Create a list of profiles by deserializing data from the given XML element.
+	 *
+	 * @param root Either a &lt;profiles&gt; or a &lt;profile&gt; element.
+	 * @param factory Factory for creation of profile-related objects.
+	 * @return A list of profiles.
+	 */
+	public static List createProfiles(Element root, ObjectFactory factory) {
+		List profiles = new ArrayList();
+		if ("profile".equals(root.getNodeName()))
+			// The root is a <profile>, so add the single profile to the list.
+			profiles.add(factory.createProfile((Element) root));
+		else if ("profiles".equals(root.getNodeName())) {
+			// The root is a <profiles>, so add each <profile> to the list.
+			NodeList children = root.getChildNodes();
+			for (int i = 0; i < children.getLength(); ++i) {
+				Node node = children.item(i);
+				if ("profile".equals(node.getNodeName()))
+					profiles.add(factory.createProfile((Element) node));
+			}
+		} else throw new IllegalArgumentException("Expected a <profiles> or <profile> top level element but got "
+			+ root.getNodeName());
+		return profiles;
+	}
+
+
+	/**
+	 * Create a list of profiles by deserializing data from the given XML element.
+	 *
+	 * This method uses the default factory that yields objects of this package,
+	 * namely {@link Profile}, {@link ProfileAttributes}, {@link ResourceAttributes},
+	 * and {@link ProfileElement} and its subclasses.
+	 *
+	 * @param root Either a &lt;profiles&gt; or a &lt;profile&gt; element.
+	 * @return A list of profiles.
+	 */
+	public static List createProfiles(Element root) {
+		return createProfiles(root, new DefaultFactory());
+	}
+
+	/**
+	 * Create a blank profile.
+	 */
+	public Profile() {
+		profAttr = new ProfileAttributes();
+		resAttr = new ResourceAttributes(this);
+	}
+
+	/**
+	 * Create a profile from an XML document.
+	 *
+	 * @param string The XML document (as a string).
+	 * @throws SAXException If the <var>string</var> can't be parsed.
+	 */
+	public Profile(String string) throws SAXException {
+		this(XML.parse(string).getDocumentElement(), new DefaultFactory());
+	}
+
+	/**
+	 * Create a profile from an XML document.
+	 *
+	 * @param string The XML document (as a string).
+	 * @param factory Object factory to use.
+	 * @throws SAXException If the <var>string</var> can't be parsed.
+	 */
+	public Profile(String string, ObjectFactory factory) throws SAXException {
+		this(XML.parse(string).getDocumentElement(), factory);
+	}
+
+	/**
+	 * Creates a new <code>Profile</code> instance.
+	 *
+	 * @param root a <code>Node</code> value.
+	 */
+	public Profile(Node root) {
+		this(root, new DefaultFactory());
+	}
+
+	/**
+	 * Create a profile from an XML document.
+	 *
+	 * @param root The &lt;profile&gt; element.
+	 */
+	public Profile(Node root, ObjectFactory factory) {
+		if (!root.getNodeName().equals("profile"))
+			throw new IllegalArgumentException("Construct a Profile from a <profile> element, not a <"
+				+ root.getNodeName() + ">");
+		NodeList children = root.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node node = children.item(i);
+			if ("profAttributes".equals(node.getNodeName()))
+				profAttr = factory.createProfileAttributes((Element) node);
+			else if ("resAttributes".equals(node.getNodeName()))
+				resAttr = factory.createResourceAttributes(this, (Element) node);
+			else if ("profElement".equals(node.getNodeName())) {
+				ProfileElement element = ProfileElement.createProfileElement((Element) node, this, factory);
+				elements.put(element.getName(), element);
+			}
+		}
+	}
+
+	/**
+	 * Create a profile from its attributes.
+	 *
+	 * @param profAttr Profile attributes.
+	 * @param resAttr Resource attributes.
+	 */
+	public Profile(ProfileAttributes profAttr, ResourceAttributes resAttr) {
+		this.profAttr = profAttr;
+		this.resAttr = resAttr;
+		if (this.resAttr != null) this.resAttr.profile = this;
+	}
+
+	public int hashCode() {
+		return profAttr.hashCode();
+	}
+
+	public boolean equals(Object rhs) {
+		if (rhs == this) return true;
+		if (rhs == null || !(rhs instanceof Profile)) return false;
+		Profile obj = (Profile) rhs;
+		return profAttr.equals(obj.profAttr);
+	}
+
+	public int compareTo(Object rhs) {
+		Profile obj = (Profile) rhs;
+		return profAttr.compareTo(obj.profAttr);
+	}
+
+	public String toString() {
+		Document doc = createProfileDocument();
+		doc.removeChild(doc.getDocumentElement());
+		doc.appendChild(toXML(doc));
+		return XML.serialize(doc);
+	}
+
+	public Object clone() {
+		Object clone = null;
+		try {
+			clone = super.clone();
+		} catch (CloneNotSupportedException cantHappen) {}
+		return clone;
+	}
+
+	/**
+	 * Get the profile attributes.
+	 *
+	 * @return The profile attributes.
+	 */
+	public ProfileAttributes getProfileAttributes() {
+		return profAttr;
+	}
+
+	/**
+	 * Get the resource attributes.
+	 *
+	 * @return The resource attributes.
+	 */
+	public ResourceAttributes getResourceAttributes() {
+		return resAttr;
+	}
+
+	/**
+	 * Set this profile's profile attributes.
+	 *
+	 * @param profAttr a <code>ProfileAttributes</code> value.
+	 */
+	public void setProfileAttributes(ProfileAttributes profAttr) {
+		this.profAttr = profAttr;
+	}
+
+	/**
+	 * Set this profile's resource attributes.
+	 *
+	 * @param resAttr a <code>ResourceAttributes</code> value.
+	 */
+	public void setResourceAttributes(ResourceAttributes resAttr) {
+		this.resAttr = resAttr;
+	}
+
+	/**
+	 * Get the profile elements.
+	 *
+	 * The profile elements are a mapping from the element name ({@link
+	 * java.lang.String}) to {@link ProfileElement}.
+	 *
+	 * @return The profile elements.
+	 */
+	public Map getProfileElements() {
+		return elements;
+	}
+
+	public URI getURI() {
+		return resAttr.getURI();
+	}
+
+	/**
+	 * Add this profile as an RDF resource description to an RDF model.
+	 *
+	 * This creates a description of the resource that this profile describes, as well
+	 * as additional resources for the reified statements about the profile itself,
+	 * and adds them all to the given model.
+	 *
+	 * @param model Model to which to add the profile and its related descriptions.
+	 */
+	public void addToModel(Model model) {
+		Resource resource = model.createResource(getURI().toString());
+		resAttr.addToModel(model, resource, profAttr);
+		for (Iterator i = elements.values().iterator(); i.hasNext();) {
+			ProfileElement e = (ProfileElement) i.next();
+			e.addToModel(model, resource, profAttr);
+		}
+	}
+
+	/**
+	 * Serialize this profile as an XML node.
+	 *
+	 * @param doc The document that will own this node.
+	 * @return The XML element &lt;profile&gt; representing these attributes.
+	 * @throws DOMException If an error occurs creating the XML nodes.
+	 */
+	public Node toXML(Document doc) throws DOMException {
+		return toXML(doc, /*withElements*/true);
+	}
+
+	/**
+	 * Serialize this profile as an XML node but without any elements.
+	 *
+	 * @param doc The document that will own this node.
+	 * @return The XML element &lt;profile&gt; representing these attributes.
+	 * @throws DOMException If an error occurs creating the XML nodes.
+	 */
+	public Node toXMLWithoutElements(Document doc) throws DOMException {
+		return toXML(doc, /*withElements*/false);
+	}
+
+	/**
+	 * Serialize this profile as an XML node.
+	 *
+	 * @param doc The document that will own this node.
+	 * @param withElements Include the profile elements?
+	 * @return The XML element &lt;profile&gt; representing these attributes.
+	 * @throws DOMException If an error occurs creating the XML nodes.
+	 */
+	private Node toXML(Document doc, boolean withElements) throws DOMException {
+		Element profile = doc.createElement("profile");
+		profile.appendChild(profAttr.toXML(doc));
+		profile.appendChild(resAttr.toXML(doc));
+		if (withElements) for (Iterator i = elements.values().iterator(); i.hasNext();)
+			profile.appendChild(((ProfileElement) i.next()).toXML(doc));
+		return profile;
+	}
+
+	/**
+	 * Create a &lt;profiles&gt; document using the profiles DTD.
+	 *
+	 * @return A &lt;profiles&gt; document with the profiles DTD.
+	 */
+	public static Document createProfilesDocument() {
+		return createDocument("profiles");
+	}
+
+	/**
+	 * Create a &lt;profile&gt; document using the profiles DTD.
+	 *
+	 * @return A &lt;profile&gt; document with the profiles DTD.
+	 */
+	public static Document createProfileDocument() {
+		return createDocument("profile");
+	}
+
+	/**
+	 * Create a document using the profiles DTD with the given root element.
+	 *
+	 * @param root Name of the root element.
+	 * @return The document with the appropriate document type declaration.
+	 */
+	static Document createDocument(String root) {
+		DocumentType docType = XML.getDOMImplementation().createDocumentType(root, PROFILES_DTD_FPI, PROFILES_DTD_URL);
+		Document doc = XML.getDOMImplementation().createDocument(/*namespaceURI*/null, root, docType);
+		return doc;
+	}
+
+	/** My profile attributes. */
+	protected ProfileAttributes profAttr;
+
+	/** My resource attributes. */
+	protected ResourceAttributes resAttr;
+
+	/** My elements.
+	 *
+	 * This mapping is from element name (a {@link String}) to {@link ProfileElement}.
+	 */
+	protected Map elements = new HashMap();
+
+	/**
+	 * Try to parse an XML profile in a file in its XML vocabulary.  If successful,
+	 * you get the profile as RDF document (in XML format) to the standard output
+	 * after it's been digested by the profile class.  If not, then you get an
+	 * exception.
+	 *
+	 * @param argv Command-line arguments, of which there should be one, the name of XML file containing the profile to parse
+	 * @throws Throwable if an error occurs.
+	 */
+	public static void main(String[] argv) throws Throwable {
+		if (argv.length != 1) {
+			System.err.println("Usage: <profile.xml>");
+			System.exit(1);
+		}
+		StringBuffer b = new StringBuffer();
+		BufferedReader reader = new BufferedReader(new FileReader(argv[0]));
+		char[] buf = new char[512];
+		int num;
+		while ((num = reader.read(buf)) != -1)
+			b.append(buf, 0, num);
+		reader.close();
+		Profile p = new Profile(b.toString());
+
+		Model model = ModelFactory.createDefaultModel();
+		p.addToModel(model);
+		OutputStreamWriter writer = new OutputStreamWriter(System.out);
+		model.write(writer);
+		writer.close();
+		System.exit(0);
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileAttributes.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileAttributes.java
new file mode 100644
index 0000000..b892110
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileAttributes.java
@@ -0,0 +1,346 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.oodt.commons.util.Documentable;
+import org.apache.oodt.commons.util.XML;
+import org.apache.oodt.commons.Configuration;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import java.io.IOException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.SAXException;
+
+/**
+ * Profile attributes.
+ *
+ * Objects of this class are attributes of profiles.
+ *
+ * @author Kelly
+ */
+public class ProfileAttributes implements Serializable, Cloneable, Comparable, Documentable {
+	/**
+	 * Create blank profile attributes.
+	 */
+	public ProfileAttributes() {
+		id = "UNKNOWN";
+		type = "UNKNOWN";
+		statusID = "UNKNOWN";
+		children = new ArrayList();
+		revisionNotes = new ArrayList();
+	}
+
+	/**
+	 * Create profile attributes from an XML document.
+	 *
+	 * @param root The &lt;profAttributes&gt; element.
+	 */
+	public ProfileAttributes(Node root) {
+		children = new ArrayList();
+		revisionNotes = new ArrayList();
+		NodeList childNodes = root.getChildNodes();
+		for (int i = 0; i < childNodes.getLength(); ++i) {
+			Node node = childNodes.item(i);
+			if ("profId".equals(node.getNodeName()))
+				id = XML.unwrappedText(node);
+			else if ("profVersion".equals(node.getNodeName()))
+				version = XML.unwrappedText(node);
+			else if ("profType".equals(node.getNodeName()))
+				type = XML.unwrappedText(node);
+			else if ("profStatusId".equals(node.getNodeName()))
+				statusID = XML.unwrappedText(node);
+			else if ("profSecurityType".equals(node.getNodeName()))
+				securityType = XML.unwrappedText(node);
+			else if ("profParentId".equals(node.getNodeName()))
+				parent = XML.unwrappedText(node);
+			else if ("profChildId".equals(node.getNodeName()))
+				children.add(XML.unwrappedText(node));
+			else if ("profRegAuthority".equals(node.getNodeName()))
+				regAuthority = XML.unwrappedText(node);
+			else if ("profRevisionNote".equals(node.getNodeName()))
+				revisionNotes.add(XML.unwrappedText(node));
+		}
+	}
+
+	/**
+	 * Create profile attributes from constituent attributes.
+	 *
+	 * @param id The profile ID.
+	 * @param version Version.
+	 * @param type Type of the profile.
+	 * @param statusID Status ID.
+	 * @param securityType Security type.
+	 * @param parent Parent profile IDs.
+	 * @param children Zero or more {@link String} child profile IDs.
+	 * @param regAuthority Registration authority.
+	 * @param revisionNotes Zero or more {@link String} revision notes.
+	 */
+	public ProfileAttributes(String id, String version, String type, String statusID, String securityType, String parent,
+		List children, String regAuthority, List revisionNotes) {
+		this.id = id;
+		this.version = version;
+		this.type = type;
+		this.statusID = statusID;
+		this.securityType = securityType;
+		this.parent = parent;
+		this.children = children;
+		this.regAuthority = regAuthority;
+		this.revisionNotes = revisionNotes;
+	}
+
+	public int hashCode() {
+		return id.hashCode();
+	}
+
+	public boolean equals(Object rhs) {
+		if (rhs == this) return true;
+		if (rhs == null || !(rhs instanceof ProfileAttributes)) return false;
+		return ((ProfileAttributes) rhs).id.equals(id);
+	}
+
+	public int compareTo(Object rhs) {
+		ProfileAttributes obj = (ProfileAttributes) rhs;
+		return id.compareTo(obj.id);
+	}
+
+	public String toString() {
+		return getClass().getName() + "[id=" + id + "]";
+	}
+
+	public Object clone() {
+		Object clone = null;
+		try {
+			clone = super.clone();
+		} catch (CloneNotSupportedException cantHappen) {}
+		return clone;
+	}
+
+	/**
+	 * Get the ID.
+	 *
+	 * @return The ID.
+	 */
+	public String getID() {
+		return id;
+	}
+
+	/**
+	 * Get the version.
+	 *
+	 * @return The version.
+	 */
+	public String getVersion() {
+		return version;
+	}
+
+	/**
+	 * Get the type.
+	 *
+	 * @return The type of the profile.
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/**
+	 * Get the status ID.
+	 *
+	 * @return The status ID.
+	 */
+	public String getStatusID() {
+		return statusID;
+	}
+
+	/**
+	 * Get the security type.
+	 *
+	 * @return The security type.
+	 */
+	public String getSecurityType() {
+		return securityType;
+	}
+
+	/**
+	 * Get the parent of this profile.
+	 *
+	 * @return The parent profile's ID.
+	 */
+	public String getParent() {
+		return parent;
+	}
+
+	/**
+	 * Get the children of this profile.
+	 *
+	 * @return A list of {@link String} IDs of its children.
+	 */
+	public List getChildren() {
+		return children;
+	}
+
+	/**
+	 * Get the registration authority of this profile.
+	 *
+	 * @return Its registration authority.
+	 */
+	public String getRegAuthority() {
+		return regAuthority;
+	}
+
+	/**
+	 * Get the revision notes of this profile.
+	 *
+	 * @return A list of {@link String} revision notes.
+	 */
+	public List getRevisionNotes() {
+		return revisionNotes;
+	}
+
+	/**
+	 * 
+	 * Set the Parent
+	 * 
+	 * @param theParent The Parent String.
+	 */
+	public void setParent(String theParent){
+		parent = theParent;
+	}
+
+	/**
+	 * Set the ID.
+	 *
+	 * @param id The ID.
+	 */
+	public void setID(String id) {
+		this.id = id;
+	}
+
+	/**
+	 * Set the version.
+	 *
+	 * @param version The version.
+	 */
+	public void setVersion(String version) {
+		this.version = version;
+	}
+
+	/**
+	 * Set the type.
+	 *
+	 * @param type The type of the profile.
+	 */
+	public void setType(String type) {
+		this.type = type;
+	}
+
+	/**
+	 * Set the status ID.
+	 *
+	 * @param statusID The status ID.
+	 */
+	public void setStatusID(String statusID) {
+		this.statusID = statusID;
+	}
+
+	/**
+	 * Set the security type.
+	 *
+	 * @param securityType The security type.
+	 */
+	public void setSecurityType(String securityType) {
+		this.securityType = securityType;
+	}
+
+	/**
+	 * Set the registration authority of this profile.
+	 *
+	 * @param regAuthority Its registration authority.
+	 */
+	public void setRegAuthority(String regAuthority) {
+		this.regAuthority = regAuthority;
+	}
+
+	/**
+	 * Serialize this attributes as an XML node.
+	 *
+	 * @param doc The document that will own this node.
+	 * @return The XML element &lt;profAttributes&gt; representing these attributes.
+	 * @throws DOMException If an error occurs creating the XML nodes.
+	 */
+	public Node toXML(Document doc) throws DOMException {
+		Element root = doc.createElement("profAttributes");
+		XML.add(root, "profId", id);
+		XML.addNonNull(root, "profVersion", version);
+		XML.addNonNull(root, "profType", type);
+		XML.addNonNull(root, "profStatusId", statusID);
+		XML.addNonNull(root, "profSecurityType", securityType);
+		XML.addNonNull(root, "profParentId", parent);
+		XML.add(root, "profChildId", children);
+		XML.addNonNull(root, "profRegAuthority", regAuthority);
+		XML.add(root, "profRevisionNote", revisionNotes);
+		return root;
+	}
+
+	/** Unique identifier, required. */
+	protected String id;
+
+	/** Version, optional. */
+	protected String version;
+
+	/** Type, required. */
+	protected String type;
+
+	/** Status ID, required. */
+	protected String statusID;
+
+	/** Type of security to apply, optional. */
+	protected String securityType;
+
+	/** Parent profile ID, optional. */
+	protected String parent;
+
+	/** List of zero or more children profile IDs ({@link String}s). */
+	protected List children;
+
+	/** Registration authority, optional. */
+	protected String regAuthority;
+
+	/** Revision notes, zero or more {@link String}s. */
+	protected List revisionNotes;
+
+        /** Serial version unique ID. */
+        static final long serialVersionUID = 6140264312462080058L;
+
+	/**
+	 * Create a &lt;profAttributes&gt; document using the profiles DTD.
+	 *
+	 * @return A &lt;profAttributs&gt; document with the profiles DTD.
+	 */
+	public static Document createProfAttributesDocument() {
+		return Profile.createDocument("profAttributes");
+	}
+
+
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileElement.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileElement.java
new file mode 100644
index 0000000..4add025
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileElement.java
@@ -0,0 +1,568 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.Resource;
+import java.io.Serializable;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import org.apache.oodt.commons.util.Documentable;
+import org.apache.oodt.commons.util.XML;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Profile element.
+ *
+ * Objects of this class are elements that describe the composition of a resource.
+ *
+ * @author Kelly
+ */
+public abstract class ProfileElement implements Serializable, Cloneable, Comparable, Documentable {
+	/**
+	 * Create a profile element from the given XML node.
+	 *
+	 * @param root The &lt;profElement&gt; node.
+	 * @param profile To what profile the element belongs.
+	 * @return A profile element.
+	 */
+	public static ProfileElement createProfileElement(Element root, Profile profile, ObjectFactory factory) {
+		String name = null;
+		String id = null;
+		String desc = null;
+		String type = null;
+		String unit = null;
+		List synonyms = new ArrayList();
+		boolean obligation = false;
+		int maxOccurrence = 0;
+		String comments = null;
+		boolean ranged = false;
+		NodeList children = root.getChildNodes();
+		String min = "0.0", max = "0.0";
+		boolean gotMin = false;
+		boolean gotMax = false;
+		List values = new ArrayList();
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node node = children.item(i);
+			if ("elemId".equals(node.getNodeName()))
+				id = XML.unwrappedText(node);
+			else if ("elemName".equals(node.getNodeName()))
+				name = XML.unwrappedText(node);
+			else if ("elemDesc".equals(node.getNodeName()))
+				desc = XML.unwrappedText(node);
+			else if ("elemType".equals(node.getNodeName()))
+				type = XML.unwrappedText(node);
+			else if ("elemUnit".equals(node.getNodeName()))
+				unit = XML.unwrappedText(node);
+			else if ("elemEnumFlag".equals(node.getNodeName()))
+				ranged = "F".equals(XML.unwrappedText(node));
+			else if ("elemSynonym".equals(node.getNodeName()))
+				synonyms.add(XML.unwrappedText(node));
+			else if ("elemObligation".equals(node.getNodeName())) {
+				String value = XML.unwrappedText(node);
+				obligation = "Required".equals(value) || "T".equals(value);
+			} else if ("elemMaxOccurrence".equals(node.getNodeName()))
+				try {
+					maxOccurrence = Integer.parseInt(XML.unwrappedText(node));
+				} catch (NumberFormatException ignore) {}
+			else if ("elemComment".equals(node.getNodeName()))
+				comments = XML.unwrappedText(node);
+			else if ("elemValue".equals(node.getNodeName())) {
+				values.add(text(node));
+			} else if ("elemMinValue".equals(node.getNodeName()))
+				try {
+					min = XML.unwrappedText(node);
+					gotMin = true;
+				} catch (NumberFormatException ignore) {}
+			else if ("elemMaxValue".equals(node.getNodeName()))
+				try {
+					max = XML.unwrappedText(node);
+					gotMax = true;
+				} catch (NumberFormatException ignore) {}
+		}
+		if (ranged) {
+			if (gotMin && gotMax) {
+				return factory.createRangedProfileElement(profile, name, id, desc, type, unit, synonyms, obligation,
+					maxOccurrence, comments, min, max);
+			}
+			return factory.createUnspecifiedProfileElement(profile, name, id, desc, type, unit, synonyms, obligation,
+				maxOccurrence, comments);
+		} else
+			return factory.createEnumeratedProfileElement(profile, name, id, desc, type, unit, synonyms, obligation,
+				maxOccurrence, comments, values);
+	}
+
+	/**
+	 * Create blank profile attributes belonging to the given profile.
+	 */
+	protected ProfileElement(Profile profile) {
+		this.profile = profile;
+		synonyms = new ArrayList();
+	}
+
+	/**
+	 * Create a profile element from constituent attributes.
+	 *
+	 * @param profile Profile to which this element belongs.
+	 * @param name Required name of the element.
+	 * @param id ID of the element.
+	 * @param desc Long description of the element.
+	 * @param type Data type of the element.
+	 * @param unit Units.
+	 * @param synonyms Collection of element IDs ({@link String}) that are synonyms for this element.
+	 * @param obligation True if this is a required element
+	 * @param maxOccurrence Maximum number of occurrences of this element.
+	 * @param comments Any comments about this element.
+	 */
+	protected ProfileElement(Profile profile, String name, String id, String desc, String type, String unit, List synonyms,
+		boolean obligation, int maxOccurrence, String comments) {
+		this.profile = profile;
+		this.name = name;
+		this.id = id;
+		this.desc = desc;
+		this.type = type;
+		this.unit = unit;
+		this.synonyms = synonyms;
+		this.obligation = obligation;
+		this.maxOccurrence = maxOccurrence;
+		this.comments = comments;
+	}
+
+	public int hashCode() {
+		return name.hashCode();
+	}
+
+	public boolean equals(Object rhs) {
+		if (rhs == this) return true;
+		if (rhs == null || !(rhs instanceof ProfileElement)) return false;
+		ProfileElement obj = (ProfileElement) rhs;
+		return profile.equals(obj.profile) && name.equals(obj.name);
+	}
+
+	public String toString() {
+		return getClass().getName() + "[profile=" + profile.toString() + ",name=" + name + "]";
+	}
+
+	public Object clone() {
+		Object obj = null;
+		try {
+			obj = super.clone();
+		} catch (CloneNotSupportedException cantHappen) {}
+		return obj;
+	}
+
+	public int compareTo(Object rhs) {
+		ProfileElement obj = (ProfileElement) rhs;
+		if (profile.compareTo(obj.profile) < 0)
+			return -1;
+		if (profile.compareTo(obj.profile) == 0)
+			return name.compareTo(obj.name);
+		return 1;
+	}
+
+	/**
+	 * Get the profile to whom I belong.
+	 *
+	 * @return The owning profile.
+	 */
+	public Profile getProfile() {
+		return profile;
+	}
+
+	/**
+	 * Get my name.
+	 *
+	 * @return My name.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Get my element ID.
+	 *
+	 * @return My ID.
+	 */
+	public String getID() {
+		return id;
+	}
+
+	/**
+	 * Get my long description.
+	 *
+	 * @return My long description.
+	 */
+	public String getDescription() {
+		return desc;
+	}
+
+	/**
+	 * Get my type.
+	 *
+	 * @return My type.
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/**
+	 * Get my unit.
+	 *
+	 * @return My unit.
+	 */
+	public String getUnit() {
+		return unit;
+	}
+
+	/**
+	 * Get my synonyms.
+	 *
+	 * @return A list of synonyms.
+	 */
+	public List getSynonyms() {
+		return synonyms;
+	}
+
+	/**
+	 * Am I obligatory?
+	 *
+	 * @return True if I am, false otherwise.
+	 */
+	public boolean isObligatory() {
+		return obligation;
+	}
+
+	/**
+	 * Get how many times I can occur.
+	 *
+	 * @return How many times I can occur.
+	 */
+	public int getMaxOccurrence() {
+		return maxOccurrence;
+	}
+
+	/**
+	 * Get any comments about me.
+	 *
+	 * @return Any comments.
+	 */
+	public String getComments() {
+		return comments;
+	}
+
+	/**
+	 * Set the profile to whom I belong.
+	 *
+	 * @param profile The owning profile.
+	 */
+	public void setProfile(Profile profile) {
+		this.profile = profile;
+	}
+
+	/**
+	 * Set my name.
+	 *
+	 * @param name My name.
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * Set my element ID.
+	 *
+	 * @param id My ID.
+	 */
+	public void setID(String id) {
+		this.id = id;
+	}
+
+	/**
+	 * Set my long description.
+	 *
+	 * @param desc My long description.
+	 */
+	public void setDescription(String desc) {
+		this.desc = desc;
+	}
+
+	/**
+	 * Set my type.
+	 *
+	 * @param type My type.
+	 */
+	public void setType(String type) {
+		this.type = type;
+	}
+
+	/**
+	 * Set my unit.
+	 *
+	 * @param unit My unit.
+	 */
+	public void setUnit(String unit) {
+		this.unit = unit;
+	}
+
+	/**
+	 * Set whether I'm obligatory.
+	 *
+	 * @param obligatory True if I am, false otherwise.
+	 */
+	public void setObligation(boolean obligatory) {
+		this.obligation = obligatory;
+	}
+
+	/**
+	 * Set how many times I can occur.
+	 *
+	 * @param occurrence How many times I can occur.
+	 */
+	public void setMaxOccurrence(int occurrence) {
+		this.maxOccurrence = occurrence;
+	}
+
+	/**
+	 * Set any comments about me.
+	 *
+	 * @param comments Any comments.
+	 */
+	public void setComments(String comments) {
+		this.comments = comments;
+	}
+
+	/**
+	 * Get my minimum value.
+	 *
+	 * @return My minimum value.
+	 */
+	public abstract String getMinValue();
+
+	/**
+	 * Get my maximum value.
+	 *
+	 * @return My maximum value.
+	 */
+	public abstract String getMaxValue();
+
+	/**
+	 * Get legal values.
+	 *
+	 * @return List of legal values (as {@link String}s).
+	 */
+	public abstract List getValues();
+
+	/**
+	 * Serialize this element as an XML node.
+	 *
+	 * @param doc The document that will own this node.
+	 * @return The XML element &lt;resAttributes&gt; representing these attributes.
+	 * @throws DOMException If an error occurs creating the XML nodes.
+	 */
+	public Node toXML(Document doc) throws DOMException {
+		return toXML(doc, /*withValues*/true);
+	}
+
+	/**
+	 * Serialize this element as an XML node without any values.
+	 *
+	 * @param doc The document that will own this node.
+	 * @return The XML element &lt;resAttributes&gt; representing these attributes.
+	 * @throws DOMException If an error occurs creating the XML nodes.
+	 */
+	public Node toXMLWithoutValues(Document doc) throws DOMException {
+		return toXML(doc, /*withValues*/false);
+	}
+
+	/**
+	 * Serialize this element.
+	 *
+	 * @param doc The document that will own this node.
+	 * @param withValues If true, serialize the values as well.
+	 * @return The XML element &lt;profElement&gt; representing this element.
+	 * @throws DOMException If an error occurs creating the XML nodes.
+	 */
+	private Node toXML(Document doc, boolean withValues) throws DOMException {
+		Element profElement = doc.createElement("profElement");
+		XML.addNonNull(profElement, "elemId", id);
+		XML.addNonNull(profElement, "elemName", name);
+		XML.addNonNull(profElement, "elemDesc", desc);
+		XML.addNonNull(profElement, "elemType", type);
+		XML.addNonNull(profElement, "elemUnit", unit);
+		XML.add(profElement, "elemEnumFlag", isEnumerated()? "T" : "F");
+		if (withValues) addValues(profElement);
+		XML.add(profElement, "elemSynonym", synonyms);
+		if (isObligatory())
+			XML.add(profElement, "elemObligation","Required");
+		if (getMaxOccurrence() >= 0)
+			XML.add(profElement, "elemMaxOccurrence", String.valueOf(getMaxOccurrence()));
+		XML.add(profElement, "elemComment", comments);
+		return profElement;
+	}
+
+	/**
+	 * Tell if this element is of the enumerated kind.
+	 *
+	 * @return a <code>boolean</code> value.
+	 */
+	protected abstract boolean isEnumerated();
+
+	/**
+	 * Add the values of this element to the given node.
+	 *
+	 * @param node The node to add to.
+	 * @throws DOMException If an error occurs creating the XML nodes.
+	 */
+	protected abstract void addValues(Node node) throws DOMException;
+
+	/**
+	 * Add this element to an RDF model including this element's profile.
+	 *
+	 * @param model The model to which we're being added.
+	 * @param resource The profile as an RDF resource description.
+	 * @param profAttr The profile's attributes.
+	 */
+	void addToModel(Model model, Resource resource, ProfileAttributes profAttr) {
+		URI profileURI = profile.getURI();
+		URI myURI = URI.create(profileURI.toString() + "#" + name);
+
+		Resource element = model.createResource(myURI.toString());
+		Utility.addProperty(model, resource, Utility.edmElement, element, profAttr, myURI);
+
+		String obStr = obligation? "Required" : "Optional";
+		String occurStr = String.valueOf(maxOccurrence);
+
+		Utility.addProperty(model, element, Utility.edmElemID,        id,       profAttr, myURI);
+		Utility.addProperty(model, element, Utility.edmDescription,   desc,     profAttr, myURI);
+		Utility.addProperty(model, element, Utility.edmElemType,      type,     profAttr, myURI);
+		Utility.addProperty(model, element, Utility.edmUnit,          unit,     profAttr, myURI);
+		Utility.addProperty(model, element, Utility.edmSynonym,       synonyms, profAttr, myURI);
+		Utility.addProperty(model, element, Utility.edmObligation,    obStr,    profAttr, myURI);
+		Utility.addProperty(model, element, Utility.edmMaxOccurrence, occurStr, profAttr, myURI);
+		Utility.addProperty(model, element, Utility.edmComment,       comments, profAttr, myURI);
+
+		addElementSpecificProperties(model, element, profAttr, myURI);
+	}
+
+	/**
+	 * Add the statements specific to this kind of profile element to an RDF model.
+	 *
+	 * @param model The model.
+	 * @param element This element, as an RDF resource.
+	 * @param profAttr The attributes of the element's profile.
+	 */
+	protected abstract void addElementSpecificProperties(Model model, Resource element, ProfileAttributes profAttr, URI uri);
+
+	/** My profile. */
+	protected Profile profile;
+
+	/** My required name. */
+	protected String name;
+
+	/** My optional id. */
+	protected String id;
+
+	/** My optional description. */
+	protected String desc;
+
+	/** My optional type. */
+	protected String type;
+
+	/** My optional unit. */
+	protected String unit;
+
+	/** My synonyms. */
+	protected List synonyms;
+
+	/** My obligation. */
+	protected boolean obligation;
+
+	/** My maxOccurrence. */
+	protected int maxOccurrence;
+
+	/** My optional comments. */
+	protected String comments;
+
+	/**
+	 * Create a &lt;profElement&gt; document using the profiles DTD.
+	 *
+	 * @return A &lt;profElement&gt; document with the profiles DTD.
+	 */
+	public static Document createProfElementDocument() {
+		return Profile.createDocument("profElement");
+	}
+
+	/**
+	 * Given a set of profile elements, return a set of profiles that own those elements.
+	 *
+	 * @param elements Profile elements.
+	 * @return Profiles that own those elements.
+	 */
+	public static Set profiles(Set elements) {
+		Set rc = new HashSet();
+		for (Iterator i = elements.iterator(); i.hasNext();) {
+			ProfileElement element = (ProfileElement) i.next();
+			rc.add(element.getProfile());
+		}
+		return rc;
+	}
+
+	/**
+	 * Given a set of profiles and of profile elements, return those elements that
+	 * are owned by any of the given profiles.
+	 *
+	 * @param profiles Profiles.
+	 * @param elements Profile elements.
+	 * @return Members of <var>elements</var> that are owned by members of <var>profiles</var>.
+	 */
+	public static Set elements(Set profiles, Set elements) {
+		Set rc = new HashSet();
+		for (Iterator i = elements.iterator(); i.hasNext();) {
+			ProfileElement element = (ProfileElement) i.next();
+			if (profiles.contains(element.getProfile()))
+				rc.add(element);
+		}
+		return rc;
+	}
+
+	static String text(Node node) {
+		StringBuffer b = new StringBuffer();
+	        text0(b, node);
+		return b.toString();
+	}
+
+	static void text0(StringBuffer b, Node node) {
+		if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.CDATA_SECTION_NODE) {
+			b.append(node.getNodeValue());
+			return;
+		}
+		NodeList children = node.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i)
+			text0(b, children.item(i));
+	}
+}
+
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileException.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileException.java
new file mode 100644
index 0000000..8124e6b
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileException.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+/**
+ * A profile-related exception.
+ *
+ * @author Kelly
+ */
+public class ProfileException extends Exception {
+	/**
+	 * Create a profile exception with no detail message.
+	 */
+	public ProfileException() {}
+
+	/**
+	 * Create a profile exception with the given detail message.
+	 */
+	public ProfileException(String message) {
+		super(message);
+	}
+
+	/**
+	 * Create a chained profile exception.
+	 *
+	 * @param cause Causing exception.
+	 */
+	public ProfileException(Throwable cause) {
+		super(cause);
+	}
+
+	/**
+	 * Creates a chained profile exception with detail message.
+	 *
+	 * @param msg Detail message.
+	 * @param cause Causing exception.
+	 */
+	public ProfileException(String msg, Throwable cause) {
+		super(msg, cause);
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileSAXException.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileSAXException.java
new file mode 100644
index 0000000..62a40f6
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileSAXException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import org.xml.sax.SAXException;
+
+/**
+ * An XML-related SAX exception from a profile server.
+ *
+ * @author Kelly
+ */
+public class ProfileSAXException extends ProfileException {
+	/**
+	 * Create a profile SAX exception.
+	 *
+	 * @param cause The SAX exception that caused this profile exception.
+	 */
+	public ProfileSAXException(SAXException cause) {
+		super(cause);
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileSQLException.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileSQLException.java
new file mode 100644
index 0000000..0ae7b95
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ProfileSQLException.java
@@ -0,0 +1,34 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.profile;
+
+import java.sql.SQLException;
+
+/**
+ * A database-related SQL exception from a profile server.
+ *
+ * @author Kelly
+ */
+public class ProfileSQLException extends ProfileException {
+	/**
+	 * Create a profile SQL exception.
+	 *
+	 * @param cause The SQL exception that caused this profile exception.
+	 */
+	public ProfileSQLException(SQLException cause) {
+		super(cause);
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/RangedProfileElement.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/RangedProfileElement.java
new file mode 100644
index 0000000..496709c
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/RangedProfileElement.java
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+import org.apache.oodt.commons.util.XML;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.Resource;
+import java.net.URI;
+
+/**
+ * Ranged profile element.
+ *
+ * Objects of this class are elements of a profile that represent a range of values.
+ *
+ * @author Kelly
+ */
+public class RangedProfileElement extends ProfileElement {
+	/**
+	 * Create blank profile attributes belonging to the given profile.
+	 */
+	public RangedProfileElement(Profile profile) {
+		super(profile);
+		min = "";
+		max = "";
+	}
+
+	/**
+	 * Create a profile element from constituent attributes.
+	 *
+	 * @param profile Profile to which this element belongs.
+	 * @param name Required name of the element.
+	 * @param id ID of the element.
+	 * @param desc Long description of the element.
+	 * @param type Data type of the element.
+	 * @param unit Units.
+	 * @param synonyms Collection of element IDs ({@link String}) that are synonyms for this element.
+	 * @param obligation True if this is a required element
+	 * @param maxOccurrence Maximum number of occurrences of this element.
+	 * @param comment Any comments about this element.
+	 * @param min Minimum value.
+	 * @param max Maximum value.
+	 */
+	public RangedProfileElement(Profile profile, String name, String id, String desc, String type, String unit, List synonyms,
+		boolean obligation, int maxOccurrence, String comment, String min, String max) {
+		super(profile, name, id, desc, type, unit, synonyms, obligation, maxOccurrence, comment);
+		this.min = min;
+		this.max = max;
+	}
+
+	protected boolean isEnumerated() {
+		return false;
+	}
+	
+	public void setMinValue(String min){
+		this.min = min;
+		
+	}
+	
+	public void setMaxValue(String max){
+		this.max = max;
+		
+	}
+
+	protected void addValues(Node node) throws DOMException {
+		XML.add(node, "elemMinValue", min);
+		XML.add(node, "elemMaxValue", max);
+	}
+
+	public String getMinValue() {
+		return String.valueOf(min);
+	}
+
+	public String getMaxValue() {
+		return String.valueOf(max);
+	}
+
+	public List getValues() {
+		return Collections.EMPTY_LIST;
+	}
+
+	protected void addElementSpecificProperties(Model model, Resource element, ProfileAttributes profAttr, URI uri) {
+		Utility.addProperty(model, element, Utility.edmMinValue, min, profAttr, uri);
+		Utility.addProperty(model, element, Utility.edmMaxValue, max, profAttr, uri);
+	}
+
+	/** Minimum value. */
+	protected String min;
+
+	/** Maximum value. */
+	protected String max;
+
+        /** Serial version unique ID. */
+        static final long serialVersionUID = -5697102597443089753L;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ResourceAttributes.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ResourceAttributes.java
new file mode 100644
index 0000000..d1e8f2e
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/ResourceAttributes.java
@@ -0,0 +1,594 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.Property;
+import com.hp.hpl.jena.rdf.model.Resource;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.oodt.commons.Configuration;
+import org.apache.oodt.xmlquery.Result;
+import org.apache.oodt.commons.util.Documentable;
+import org.apache.oodt.commons.util.XML;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import java.net.URI;
+
+/**
+ * Resource attribuets.
+ *
+ * Objects of this class are resource attributes of profiles.
+ *
+ * @author Kelly
+ */
+public class ResourceAttributes implements Serializable, Cloneable, Comparable, Documentable {
+	/**
+	 * Create blank profile attributes.
+	 */
+	public ResourceAttributes() {
+		this(/*profile*/null);
+	}
+
+	/**
+	 * Create blank profile attributes belonging to a certain profile.
+	 *
+	 * @param profile Owning profile.
+	 */
+	public ResourceAttributes(Profile profile) {
+		this.profile = profile;
+		identifier = "UNKNOWN";
+
+		// Other attributes are optional according to prof.dtd.
+		initializeLists();
+	}
+
+	/**
+	 * Create resource attributes from an XML document.
+	 *
+	 * @param profile Owning profile.
+	 * @param root The &lt;resAttributes&gt; element.
+	 */
+	public ResourceAttributes(Profile profile, Node root) {
+		this.profile = profile;
+		initializeLists();
+		NodeList children = root.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node node = children.item(i);
+			if ("Identifier".equals(node.getNodeName()))
+				identifier = XML.unwrappedText(node);
+			else if ("Title".equals(node.getNodeName()))
+				title = XML.unwrappedText(node);
+			else if ("Format".equals(node.getNodeName()))
+				formats.add(XML.unwrappedText(node));
+			else if ("Description".equals(node.getNodeName()))
+				description = XML.unwrappedText(node);
+			else if ("Creator".equals(node.getNodeName()))
+				creators.add(XML.unwrappedText(node));
+			else if ("Subject".equals(node.getNodeName()))
+				subjects.add(XML.unwrappedText(node));
+			else if ("Publisher".equals(node.getNodeName()))
+				publishers.add(XML.unwrappedText(node));
+			else if ("Contributor".equals(node.getNodeName()))
+				contributors.add(XML.unwrappedText(node));
+			else if ("Date".equals(node.getNodeName()))
+				dates.add(XML.unwrappedText(node));
+			else if ("Type".equals(node.getNodeName()))
+				types.add(XML.unwrappedText(node));
+			else if ("Source".equals(node.getNodeName()))
+				sources.add(XML.unwrappedText(node));
+			else if ("Language".equals(node.getNodeName()))
+				languages.add(XML.unwrappedText(node));
+			else if ("Relation".equals(node.getNodeName()))
+				relations.add(XML.unwrappedText(node));
+			else if ("Coverage".equals(node.getNodeName()))
+				coverages.add(XML.unwrappedText(node));
+			else if ("Rights".equals(node.getNodeName()))
+				rights.add(XML.unwrappedText(node));
+			else if ("resContext".equals(node.getNodeName()))
+				contexts.add(XML.unwrappedText(node));
+			else if ("resAggregation".equals(node.getNodeName()))
+				aggregation = XML.unwrappedText(node);
+			else if ("resClass".equals(node.getNodeName()))
+				clazz = XML.unwrappedText(node);
+			else if ("resLocation".equals(node.getNodeName()))
+				locations.add(XML.unwrappedText(node));
+		}
+	}
+
+	/**
+	 * Create resource attributes from constituent attributes.
+	 *
+	 * According to the Dublin Core, these attributes may be multivalued, but we force
+	 * the identifier, title, and description to be singly values in the DTD, so it is
+	 * here, too.  Unless otherwise specified, these are all collections of {@link
+	 * String}.
+	 *
+	 * @param profile Owning profile.
+	 * @param identifier The unique identifier.
+	 * @param title Title of the resource.
+	 * @param formats Format of the resource.
+	 * @param description Description of the resource.
+	 * @param creators Who/what created the resource.
+	 * @param subjects Subject matter covered by the resource.
+	 * @param publishers Who/what published the resrouce.
+	 * @param contributors Who/what contributed to the resource.
+	 * @param dates When the resource was created (collection of {@link java.util.Date}.
+	 * @param types Type of the resource.
+	 * @param sources Source of the resource.
+	 * @param languages Language in which the resource is written.
+	 * @param relations Relationships to the resource.
+	 * @param coverages Coverage of the resource.
+	 * @param rights Rights of the resource.
+	 * @param contexts Context of the resource.
+	 * @param aggregation Aggregation of the resource.
+	 * @param clazz Class of the resource.
+	 * @param locations Location of the resource.
+	 */
+	public ResourceAttributes(Profile profile, String identifier, String title, List formats, String description,
+		List creators, List subjects, List publishers, List contributors, List dates, List types, List sources,
+		List languages, List relations, List coverages, List rights, List contexts, String aggregation, String clazz,
+		List locations) {
+		this.profile = profile;
+		this.identifier = identifier;
+		this.title = title;
+		this.formats = formats;
+		this.description = description;
+		this.creators = creators;
+		this.subjects = subjects;
+		this.publishers = publishers;
+		this.contributors = contributors;
+		this.dates = dates;
+		this.types = types;
+		this.sources = sources;
+		this.languages = languages;
+		this.relations = relations;
+		this.coverages = coverages;
+		this.rights = rights;
+		this.contexts = contexts;
+		this.aggregation = aggregation;
+		this.clazz = clazz;
+		this.locations = locations;
+	}
+
+	public int hashCode() {
+		return identifier.hashCode();
+	}
+
+	public boolean equals(Object rhs) {
+		if (rhs == this) return true;
+		if (rhs == null || !(rhs instanceof ResourceAttributes)) return false;
+		return ((ResourceAttributes) rhs).identifier.equals(identifier);
+	}
+
+	public int compareTo(Object rhs) {
+		ResourceAttributes obj = (ResourceAttributes) rhs;
+		return identifier.compareTo(obj.identifier);
+	}
+
+	public String toString() {
+		return getClass().getName() + "[identifer=" + identifier + "]";
+	}
+
+	public Object clone() {
+		Object clone = null;
+		try {
+			clone = super.clone();
+		} catch (CloneNotSupportedException cantHappen) {}
+		return clone;
+	}
+
+	/**
+	 * Add resource attribute statements to the profile description in an RDF model.
+	 *
+	 * @param model Model to which the profile belongs.
+	 * @param resource Resource description of the profile.
+	 * @param profAttr Profile's attributes.
+	 */
+	void addToModel(Model model, Resource resource, ProfileAttributes profAttr) {
+		URI myURI = getURI();
+
+		Utility.addProperty(model, resource, Utility.dcTitle,        title,        profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.dcFormat,       formats,      profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.dcDescription,  description,  profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.dcCreator,      creators,     profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.dcSubject,      subjects,     profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.dcPublisher,    publishers,   profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.dcContributor,  contributors, profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.dcDate,         dates,        profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.dcType,         types,        profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.dcSource,       sources,      profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.dcLanguage,     languages,    profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.dcRelation,     relations,    profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.dcRights,       rights,       profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.edmContext,     contexts,     profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.edmAggregation, aggregation,  profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.edmClass,       clazz,        profAttr, myURI);
+		Utility.addProperty(model, resource, Utility.edmLocation,    locations,    profAttr, myURI);
+	}
+
+	public URI getURI() {
+		String identification;
+		if (identifier == null || identifier.length() == 0) {
+			if (locations.isEmpty())
+				identification = null;
+			else
+				identification = (String) locations.get(0);
+		} else
+			identification = identifier;
+
+		return identification == null? UNKNOWN_URI : URI.create(identification);
+	}
+
+	/**
+	 * Get the identifier.
+	 *
+	 * @return The identifier.
+	 */
+	public String getIdentifier() {
+		return identifier;
+	}
+
+	/**
+	 * Set the identifier.
+	 *
+	 * @param identifier The identifier.
+	 */
+	public void setIdentifier(String identifier) {
+		this.identifier = identifier;
+	}
+
+	/**
+	 * Get the title.
+	 *
+	 * @return The title.
+	 */
+	public String getTitle() {
+		return title;
+	}
+
+	/**
+	 * Set the title.
+         *
+         * @param title The title.
+         */
+        public void setTitle(String title) {
+                this.title = title;
+        }
+
+
+	/**
+	 * Get the formats.
+	 *
+	 * @return The formats.
+	 */
+	public List getFormats() {
+		return formats;
+	}
+
+	/**
+	 * Set the description.
+	 *
+	 * @param description The new description.
+	 */
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	/**
+	 * Get the description.
+	 *
+	 * @return The description.
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Get the creators.
+	 *
+	 * @return The creators.
+	 */
+	public List getCreators() {
+		return creators;
+	}
+
+	/**
+	 * Get the subjects.
+	 *
+	 * @return The subjects.
+	 */
+	public List getSubjects() {
+		return subjects;
+	}
+
+	/**
+	 * Get the publishers.
+	 *
+	 * @return The publishers.
+	 */
+	public List getPublishers() {
+		return publishers;
+	}
+
+	/**
+	 * Get the contributors.
+	 *
+	 * @return The contributors.
+	 */
+	public List getContributors() {
+		return contributors;
+	}
+
+	/**
+	 * Get the dates.
+	 *
+	 * @return The dates.
+	 */
+	public List getDates() {
+		return dates;
+	}
+
+	/**
+	 * Get the types.
+	 *
+	 * @return The types.
+	 */
+	public List getTypes() {
+		return types;
+	}
+
+	/**
+	 * Get the sources.
+	 *
+	 * @return The sources.
+	 */
+	public List getSources() {
+		return sources;
+	}
+
+	/**
+	 * Get the languages.
+	 *
+	 * @return The languages.
+	 */
+	public List getLanguages() {
+		return languages;
+	}
+
+	/**
+	 * Get the relations.
+	 *
+	 * @return The relations.
+	 */
+	public List getRelations() {
+		return relations;
+	}
+
+	/**
+	 * Get the coverages.
+	 *
+	 * @return The coverages.
+	 */
+	public List getCoverages() {
+		return coverages;
+	}
+
+	/**
+	 * Get the rights.
+	 *
+	 * @return The rights.
+	 */
+	public List getRights() {
+		return rights;
+	}
+
+	/**
+	 * Get the contexts.
+	 *
+	 * @return The contexts, a list of {@link String}s.
+	 */
+	public List getResContexts() {
+		return contexts;
+	}
+
+
+	/**
+	 * Get the aggregation.
+	 *
+	 * @return The aggregation.
+	 */
+	public String getResAggregation() {
+		return aggregation;
+	}
+
+	/**
+	 * Set the aggregation.
+	 *
+	 * @param aggregation The aggregation.
+	 */
+	public void setResAggregation(String aggregation) {
+		this.aggregation = aggregation;
+	}
+
+	/**
+	 * Get the class.
+	 *
+	 * @return The class.
+	 */
+	public String getResClass() {
+		return clazz;
+	}
+
+	/**
+	 * Set the class.
+	 *
+	 * @param clazz The class.
+	 */
+	public void setResClass(String clazz) {
+		this.clazz = clazz;
+	}
+
+	/**
+	 * Get the locations.
+	 *
+	 * @return Locations, a list of {@link String}s.
+	 */
+	public List getResLocations() {
+		return locations;
+	}
+
+
+	/**
+	 * Initialize all the various {@link java.util.List} fields.
+	 */
+	protected void initializeLists() {
+		formats = new ArrayList();
+		creators = new ArrayList();
+		subjects = new ArrayList();
+		publishers = new ArrayList();
+		contributors = new ArrayList();
+		dates = new ArrayList();
+		types = new ArrayList();
+		sources = new ArrayList();
+		languages = new ArrayList();
+		relations = new ArrayList();
+		coverages = new ArrayList();
+		rights = new ArrayList();
+		contexts = new ArrayList();
+		locations = new ArrayList();
+	}
+
+	/** Profile I describe. */
+	protected Profile profile;
+
+	/** Identifer. */
+	protected String identifier;
+
+	/** Titles. */
+	protected String title;
+
+	/** Formats. */
+	protected List formats;
+
+	/** Descriptions. */
+	protected String description;
+
+	/** Creators. */
+	protected List creators;
+
+	/** Subjects. */
+	protected List subjects;
+
+	/** Publishers. */
+	protected List publishers;
+
+	/** Contributors. */
+	protected List contributors;
+
+	/** Dates. */
+	protected List dates;
+
+	/** Types. */
+	protected List types;
+
+	/** Sources. */
+	protected List sources;
+
+	/** Languages. */
+	protected List languages;
+
+	/** Relations. */
+	protected List relations;
+
+	/** Coverages. */
+	protected List coverages;
+
+	/** Rights. */
+	protected List rights;
+
+	/** Contexts, one or more list of {@link String}s. */
+	protected List contexts;
+
+	/** Aggregation. */
+	protected String aggregation;
+
+	/** Clazz. */
+	protected String clazz;
+
+	/** Locations, zero or more {@link String}s. */
+	protected List locations;
+
+	/**
+	 * Serialize this attributes as an XML node.
+	 *
+	 * @param doc The document that will own this node.
+	 * @return The XML element &lt;resAttributes&gt; representing these attributes.
+	 * @throws DOMException If an error occurs creating the XML nodes.
+	 */
+	public Node toXML(Document doc) throws DOMException {
+		Element root = doc.createElement("resAttributes");
+		XML.add(root, "Identifier", identifier);
+		XML.addNonNull(root, "Title", title);
+		XML.add(root, "Format", formats);
+		XML.addNonNull(root, "Description", description);
+		XML.add(root, "Creator", creators);
+		XML.add(root, "Subject", subjects);
+		XML.add(root, "Publisher", publishers);
+		XML.add(root, "Contributor", contributors);
+		XML.add(root, "Date", dates);
+		XML.add(root, "Type", types);
+		XML.add(root, "Source", sources);
+		XML.add(root, "Language", languages);
+		XML.add(root, "Relation", relations);
+		XML.add(root, "Coverage", coverages);
+		XML.add(root, "Rights", rights);
+		List contexts = new ArrayList(this.contexts);
+		if (contexts.isEmpty()) contexts.add("UNKNOWN");
+		XML.add(root, "resContext", contexts);
+		XML.addNonNull(root, "resAggregation", aggregation);
+		if(clazz==null) clazz="UNKNOWN";
+		XML.addNonNull(root, "resClass", clazz);
+		XML.add(root, "resLocation", locations);
+
+		return root;
+	}
+
+	/**
+	 * Create a &lt;resAttributes&gt; document using the profiles DTD.
+	 *
+	 * @return A &lt;resAttributs&gt; document with the profiles DTD.
+	 */
+	public static Document createResAttributesDocument() {
+		return Profile.createDocument("resAttributes");
+	}
+
+	/** URI of a profile whose URI is unknown. */
+	private static final URI UNKNOWN_URI = URI.create("urn:eda:profile:UNKNOWN");
+
+        /** Serial version unique ID. */
+        static final long serialVersionUID = -4251763559607642607L;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/UnspecifiedProfileElement.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/UnspecifiedProfileElement.java
new file mode 100644
index 0000000..0ce1885
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/UnspecifiedProfileElement.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+import org.w3c.dom.Node;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.Resource;
+import java.net.URI;
+
+/**
+ * A profile element with unspecified values.
+
+ * This is a profile element that is not enumerated (it doesn't have listed values, and so
+ * <code>&lt;elemEnumFlag&gt;</code> is false), nor does it have minimum or maximum
+ * values.  As such, it always matches any query in which it's involved in an expression.
+ *
+ * @author Kelly
+ */
+public class UnspecifiedProfileElement extends ProfileElement implements Serializable, Cloneable {
+	/**
+	 * Creates a profile element.
+	 *
+	 * @param profile a <code>Profile</code> value.
+	 */
+	public UnspecifiedProfileElement(Profile profile) {
+		super(profile);
+	}
+
+	/**
+	 * Create a profile element from constituent attributes.
+	 *
+	 * @param profile Profile to which this element belongs.
+	 * @param name Required name of the element.
+	 * @param id ID of the element.
+	 * @param desc Long description of the element.
+	 * @param type Data type of the element.
+	 * @param unit Units.
+	 * @param synonyms Collection of element IDs ({@link String}) that are synonyms for this element.
+	 * @param obligation True if this is a required element
+	 * @param maxOccurrence Maximum number of occurrences of this element.
+	 * @param comment Any comments about this element.
+	 */
+	public UnspecifiedProfileElement(Profile profile, String name, String id, String desc, String type, String unit,
+		List synonyms, boolean obligation, int maxOccurrence, String comment) {
+		super(profile, name, id, desc, type, unit, synonyms, obligation, maxOccurrence, comment);
+	}
+
+	public List getValues() {
+		return Collections.EMPTY_LIST;
+	}
+
+	public String getMinValue() {
+		return "";
+	}
+
+	public String getMaxValue() {
+		return "";
+	}
+
+	protected boolean isEnumerated() {
+		return false;
+	}
+
+	protected void addValues(Node node) {}
+
+	protected void addElementSpecificProperties(Model model, Resource element, ProfileAttributes profAttr, URI uri) {}
+
+        /** Serial version unique ID. */
+        static final long serialVersionUID = -3717582969125927629L;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/Utility.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/Utility.java
new file mode 100644
index 0000000..f51eb7a
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/Utility.java
@@ -0,0 +1,240 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.profile;
+
+import org.apache.oodt.commons.Configuration;
+import java.io.IOException;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+import com.hp.hpl.jena.rdf.model.Resource;
+import com.hp.hpl.jena.rdf.model.Property;
+import java.util.Iterator;
+import java.util.Collection;
+import com.hp.hpl.jena.rdf.model.Bag;
+import com.hp.hpl.jena.rdf.model.Seq;
+import java.util.List;
+import java.net.URI;
+
+/**
+ * Profile utilities.
+ *
+ * Utility methods for profiles.
+ *
+ * @author Kelly
+ */
+class Utility {
+	/**
+	 * Don't call because this is a utiliy class.
+	 */
+	private Utility() {
+		throw new IllegalStateException("Utility class");
+	}
+
+	static void addProperty(Model model, Resource resource, Property property, Object value, ProfileAttributes profAttr,
+		URI uri) {
+
+		if (value == null || value.toString().length() == 0) return;
+
+		Object obj;
+		if (value instanceof Collection) {
+			Collection collection = (Collection) value;
+			if (collection.isEmpty()) return;
+			Bag bag = model.createBag(uri + "_" + property.getLocalName() + "_bag");
+			for (Iterator i = collection.iterator(); i.hasNext();)
+				bag.add(i.next());
+			resource.addProperty(property, bag);
+			obj = bag;
+		} else {
+			resource.addProperty(property, value.toString());
+			obj = value;
+		}
+
+		Resource reification = model.createResource(uri + "_" + property.getLocalName() + "_reification");
+
+		reification.addProperty(rdfSubject, resource);
+		reification.addProperty(rdfPredicate, property);
+		reification.addProperty(rdfObject, obj.toString());
+		reification.addProperty(rdfType, rdfStatement);
+
+		addPotentiallyNullReifiedStatement(reification, edmID, profAttr.getVersion());
+		addPotentiallyNullReifiedStatement(reification, edmVersion, profAttr.getVersion());
+		addPotentiallyNullReifiedStatement(reification, edmType, profAttr.getType());
+		addPotentiallyNullReifiedStatement(reification, edmStatus, profAttr.getStatusID());
+		addPotentiallyNullReifiedStatement(reification, edmSecurity, profAttr.getSecurityType());
+		addPotentiallyNullReifiedStatement(reification, edmParent, profAttr.getParent());
+		addPotentiallyNullReifiedStatement(reification, edmRegAuth, profAttr.getRegAuthority());
+
+		List children = profAttr.getChildren();
+		if (!children.isEmpty()) {
+			Bag bag = model.createBag(uri + "_" + property.getLocalName() + "_childrenBag");
+			for (Iterator i = children.iterator(); i.hasNext();)
+				bag.add(i.next());
+			reification.addProperty(edmChild, bag);
+		}
+
+		List revNotes = profAttr.getRevisionNotes();
+		if (!revNotes.isEmpty()) {
+			Seq seq = model.createSeq(uri + "_" + property.getLocalName() + "_revNotesSeq");
+			for (Iterator i = revNotes.iterator(); i.hasNext();)
+				seq.add(i.next());
+			reification.addProperty(edmRevNote, seq);
+		}
+	}
+
+	private static void addPotentiallyNullReifiedStatement(Resource reification, Property property, Object value) {
+		if (value == null || value.toString().length() == 0) return;
+		reification.addProperty(property, value.toString());
+	}
+
+
+	/** Dublin core's title */
+	static Property dcTitle;
+	static Property dcSubject;
+	static Property dcDescription;
+	static Property dcPublisher;
+	static Property dcContributor;
+	static Property dcCreator;
+	static Property dcDate;
+	static Property dcType;
+	static Property dcFormat;
+	static Property dcSource;
+	static Property dcLanguage;
+	static Property dcRelation;
+	static Property dcCoverage;
+	static Property dcRights;
+
+	/** A resource that is an RDF statement. */
+	static Resource rdfStatement;
+
+	/** A property that is an RDF subject of a statement. */
+	static Property rdfSubject;
+
+	/** A property that is an RDF predicate of a statement. */
+	static Property rdfPredicate;
+
+	/** A property that is an object of a statement. */
+	static Property rdfObject;
+
+	/** A property that names the type of an RDF resource. */
+	static Property rdfType;
+
+	private static final String RDF_SYNTAX_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+
+	private static final String DC_NS = "http://purl.org/dc/elements/1.1/";
+
+	private static Property edmID;
+	private static Property edmVersion;
+	private static Property edmType;
+	private static Property edmStatus;
+	private static Property edmSecurity;
+	private static Property edmParent;
+	private static Property edmChild;
+	private static Property edmRegAuth;
+	private static Property edmRevNote;
+
+	static Property edmElement;
+	static Property edmContext;
+	static Property edmAggregation;
+	static Property edmClass;
+	static Property edmLocation;
+	static Property edmElemID;
+	static Property edmDescription;
+	static Property edmElemType;
+	static Property edmUnit;
+	static Property edmSynonym;
+	static Property edmObligation;
+	static Property edmMaxOccurrence;
+	static Property edmComment;
+	static Property edmMinValue;
+	static Property edmMaxValue;
+	static Property edmValue;
+
+	/**
+	 * Initialize this class.
+	 */
+	static {
+		try {
+			Configuration config = Configuration.getConfiguration();
+			String profNS = System.getProperty("jpl.rdf.ns", "http://oodt.jpl.nasa.gov/grid-profile/rdfs/prof.rdf");
+			Model model = ModelFactory.createDefaultModel();
+
+			rdfStatement     = model.createResource(RDF_SYNTAX_NS + "Statement");
+
+			rdfSubject       = model.createProperty(RDF_SYNTAX_NS, "subject");
+			rdfPredicate     = model.createProperty(RDF_SYNTAX_NS, "predicate");
+			rdfObject        = model.createProperty(RDF_SYNTAX_NS, "object");
+			rdfType          = model.createProperty(RDF_SYNTAX_NS, "type");
+
+			dcTitle          = model.createProperty(DC_NS, "title");
+			dcCreator        = model.createProperty(DC_NS, "creator");
+			dcSubject        = model.createProperty(DC_NS, "subject");
+			dcDescription    = model.createProperty(DC_NS, "description");
+			dcPublisher      = model.createProperty(DC_NS, "publisher");
+			dcContributor    = model.createProperty(DC_NS, "contributor");
+			dcDate           = model.createProperty(DC_NS, "date");
+			dcType           = model.createProperty(DC_NS, "type");
+			dcFormat         = model.createProperty(DC_NS, "format");
+			dcSource         = model.createProperty(DC_NS, "source");
+			dcLanguage       = model.createProperty(DC_NS, "language");
+			dcRelation       = model.createProperty(DC_NS, "relation");
+			dcCoverage       = model.createProperty(DC_NS, "coverage");
+			dcRights         = model.createProperty(DC_NS, "rights");
+
+			edmID            = model.createProperty(profNS, "id");
+			edmVersion       = model.createProperty(profNS, "version");
+			edmType          = model.createProperty(profNS, "type");
+			edmStatus        = model.createProperty(profNS, "status");
+			edmSecurity      = model.createProperty(profNS, "security");
+			edmParent        = model.createProperty(profNS, "parent");
+			edmChild         = model.createProperty(profNS, "child");
+			edmRegAuth       = model.createProperty(profNS, "regAuth");
+			edmRevNote       = model.createProperty(profNS, "revNote");
+			edmElement       = model.createProperty(profNS, "element");
+			edmContext       = model.createProperty(profNS, "context");
+			edmClass         = model.createProperty(profNS, "class");
+			edmAggregation   = model.createProperty(profNS, "aggregation");
+			edmLocation      = model.createProperty(profNS, "location");
+
+			edmElemID        = model.createProperty(profNS, "edmElemID");
+			edmDescription   = model.createProperty(profNS, "edmDescription");
+			edmElemType      = model.createProperty(profNS, "edmElemType");
+			edmUnit          = model.createProperty(profNS, "edmUnit");
+			edmSynonym       = model.createProperty(profNS, "edmSynonym");
+			edmObligation    = model.createProperty(profNS, "edmObligation");
+			edmMaxOccurrence = model.createProperty(profNS, "edmMaxOccurrence");
+			edmComment       = model.createProperty(profNS, "edmComment");
+			edmMinValue      = model.createProperty(profNS, "edmMinValue");
+			edmMaxValue      = model.createProperty(profNS, "edmMaxValue");
+			edmValue         = model.createProperty(profNS, "edmValue");
+
+		} catch (IOException ex) {
+			System.err.println("Fatal I/O error prevents reading of configuration: " + ex.getMessage());
+			System.exit(1);
+		} catch (SAXParseException ex) {
+			System.err.println("Fatal error parsing file (public ID \"" + ex.getPublicId() + "\", system ID \""
+				+ ex.getSystemId() + "\"), line " + ex.getLineNumber() + " column " + ex.getColumnNumber()
+				+ ": " + ex.getMessage());
+			System.exit(1);
+		} catch (SAXException ex) {
+			System.err.println("Fatal SAX exception: " + ex.getMessage() + (ex.getException() == null? ""
+				: " (embedded exception " + ex.getException().getClass().getName() + ": "
+				+ ex.getException().getMessage() + ")"));
+			System.exit(1);
+		}
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/activity/ConnectedToServer.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/activity/ConnectedToServer.java
new file mode 100644
index 0000000..3b0fa6a
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/activity/ConnectedToServer.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.activity;
+
+import org.apache.oodt.commons.activity.Incident;
+
+public class ConnectedToServer extends Incident {
+   /** Serial version unique ID */
+   static final long serialVersionUID = 11593677192131322L;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/activity/ProfileClientConstructed.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/activity/ProfileClientConstructed.java
new file mode 100644
index 0000000..52a00fc
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/activity/ProfileClientConstructed.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.activity;
+
+import org.apache.oodt.commons.activity.Incident;
+
+public class ProfileClientConstructed extends Incident {
+   /** Serial version unique ID. */
+   static final long serialVersionUID = 6229028649808262392L;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/activity/QueriedHandlers.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/activity/QueriedHandlers.java
new file mode 100644
index 0000000..d155a17
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/activity/QueriedHandlers.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.activity;
+
+import org.apache.oodt.commons.activity.Incident;
+
+public class QueriedHandlers extends Incident {
+   /** Serial version unique ID. */
+   static final long serialVersionUID = -3845963004602982264L;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/activity/ReceivedQuery.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/activity/ReceivedQuery.java
new file mode 100644
index 0000000..a2bd723
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/activity/ReceivedQuery.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.activity;
+
+import org.apache.oodt.commons.activity.Incident;
+
+public class ReceivedQuery extends Incident {
+   /** Serial version unique ID. */
+   static final long serialVersionUID = 3646406525260246714L;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/LeafListener.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/LeafListener.java
new file mode 100755
index 0000000..9bb6670
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/LeafListener.java
@@ -0,0 +1,315 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.profile.gui;
+
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import javax.swing.JOptionPane;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+
+
+import java.util.Iterator;
+
+import org.apache.oodt.profile.ProfileElement;
+import org.apache.oodt.profile.EnumeratedProfileElement;
+import org.apache.oodt.profile.Profile;
+
+
+
+public class LeafListener extends MouseAdapter{
+	  profileTree tree;
+	  
+	  public LeafListener(profileTree jtr){
+
+	    tree = jtr;
+
+	  }
+
+	  private boolean isValidMultiTerm(String t){
+	  	if(t==null){return false;}
+	  	
+	  	if(t.equals("Children")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Revision Notes")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Contexts")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Contributors")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Coverages")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Creators")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Dates")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Formats")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Languages")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Resource Locations")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Publishers")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Relations")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Rights")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Sources")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Subjects")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Types")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Profile Elements")){
+	  		return true;
+	  	}
+	  	else if(t.equals("Synonyms")){
+	  		return true;
+	  	}
+
+	  	return false;
+	    
+	  }
+	  
+	  public DefaultMutableTreeNode generateNewProfileElementTree(String peName){
+	  	 DefaultMutableTreeNode peRoot = null;
+	  	 
+	  	 ProfileElement theProfileElement = new EnumeratedProfileElement(new Profile());
+          
+	    	
+	    	peRoot = new DefaultMutableTreeNode(peName);
+	    	DefaultMutableTreeNode theCommentsRoot = new DefaultMutableTreeNode("Comments");
+	    	DefaultMutableTreeNode theComments = new DefaultMutableTreeNode(theProfileElement.getComments());
+	    	
+	    	theCommentsRoot.add(theComments);
+	    	
+	    	DefaultMutableTreeNode theDesc = new DefaultMutableTreeNode(theProfileElement.getDescription());
+	    	DefaultMutableTreeNode theDescRoot = new DefaultMutableTreeNode("Description");
+	    	
+	    	theDescRoot.add(theDesc);
+	    	
+	    	
+	    	
+	    	DefaultMutableTreeNode theID = new DefaultMutableTreeNode(theProfileElement.getID());
+	    	DefaultMutableTreeNode theIDRoot = new DefaultMutableTreeNode("ID");
+	    	
+	    	theIDRoot.add(theID);
+	    	
+	    	DefaultMutableTreeNode theMO = new DefaultMutableTreeNode(new Integer(theProfileElement.getMaxOccurrence()).toString());
+	    	DefaultMutableTreeNode theMORoot = new DefaultMutableTreeNode("Max Occurence");
+	    	theMORoot.add(theMO);
+	    	
+	    	DefaultMutableTreeNode theSynonyms = new DefaultMutableTreeNode("Synonyms");
+	    	
+	    	for(Iterator i2 = theProfileElement.getSynonyms().iterator(); i2.hasNext(); ){
+	    		String theSynonym = (String)i2.next();
+	    		DefaultMutableTreeNode sNode = new DefaultMutableTreeNode(theSynonym);
+	    		theSynonyms.add(sNode);
+	    	}
+	
+	    	DefaultMutableTreeNode theType = new DefaultMutableTreeNode(theProfileElement.getType());
+	    	DefaultMutableTreeNode theTypeRoot = new DefaultMutableTreeNode("Type");
+	    	theTypeRoot.add(theType);
+	    	
+	    	
+	    	DefaultMutableTreeNode theUnit = new DefaultMutableTreeNode(theProfileElement.getUnit());
+	    	DefaultMutableTreeNode theUnitRoot = new DefaultMutableTreeNode("Unit");
+	    	theUnitRoot.add(theUnit);
+    	
+    	peRoot.add(theCommentsRoot);
+    	peRoot.add(theDescRoot);
+    	peRoot.add(theIDRoot);
+    	peRoot.add(theMORoot);
+    	peRoot.add(theSynonyms);
+    	peRoot.add(theTypeRoot);
+    	peRoot.add(theUnitRoot);
+    	
+    	
+	  	 return peRoot;
+	  	
+	  }
+
+	  protected void menuItem2ActionPerformed(ActionEvent evt,DefaultMutableTreeNode theTreeNode,DefaultTreeModel theModel){
+	  	//System.out.println("Adding child");
+	  	
+	  	//only add child if it's one of the things that should have children
+	  	String treeNodeName = (String)theTreeNode.getUserObject();
+	  	
+	  	if(isValidMultiTerm(treeNodeName)){
+	  		return; //only edit non multi-term fields
+	  	}
+	
+	  	
+	  	String newNodeName = (String)JOptionPane.showInputDialog(null,"Edit","Enter New Node Value", JOptionPane.PLAIN_MESSAGE,null,null,"New Value");
+	  	
+	  	if(newNodeName == null){return; } //they didn't specify name or hit cancel
+	  	theTreeNode.setUserObject(newNodeName);
+	  	theModel.reload();
+	  }
+	  
+	  
+	  protected void menuItem1ActionPerformed(ActionEvent evt,DefaultMutableTreeNode theTreeNode,DefaultTreeModel theModel){
+	  	//System.out.println("Adding child");
+	  	
+	  	//only add child if it's one of the things that should have children
+	  	String treeNodeName = (String)theTreeNode.getUserObject();
+	  	
+	  	if(!isValidMultiTerm(treeNodeName)){
+	  		return;
+	  	}
+	
+	  	DefaultMutableTreeNode theAddNode = null;
+	  	String childNodeName = (String)JOptionPane.showInputDialog(null,"Add","Enter Node Name", JOptionPane.PLAIN_MESSAGE,null,null,"Child Value");
+	  	
+	  	if(childNodeName == null){return; } //they didn't specify name or hit cancel
+	  	
+	  	if(treeNodeName.equals("Profile Elements")){
+	  		theAddNode = generateNewProfileElementTree(childNodeName);
+	  	}
+	  	else{
+	  		theAddNode = new DefaultMutableTreeNode(childNodeName);
+	  	}
+	  	
+	  	 
+           	
+	  	theTreeNode.add(theAddNode);
+	  	theModel.reload();
+	  }
+	  
+	  
+	  public void mousePressed(MouseEvent e) {
+
+	  	//System.out.println("In Mouse Pressed event ");
+	    int selectedRow = tree.getRowForLocation(e.getX(), e.getY());
+	    TreePath selectedPath = tree.getPathForLocation(e.getX(), e.getY());
+	    
+	    if(selectedRow != -1) {
+	       DefaultMutableTreeNode tn               //get end of current path
+	        = (DefaultMutableTreeNode)(selectedPath.getLastPathComponent());
+	      // if (tn.isLeaf()){ //we need leaf only
+	         //write your required process for tn here
+	         //for instance: popupMenu.show( ..... );
+	         //below is a dummy process
+	         //String str = (String)(tn.getUserObject());
+	        // System.out.println(str);
+	       	
+	       	JMenuItem menuItem1 = new JMenuItem("Add");
+	       	JMenuItem menuItem2 = new JMenuItem("Edit");
+	       	
+	       	menuItem2.addActionListener(new TreeNodeActionListener(tn,this,(DefaultTreeModel)tree.getModel(),"EDIT"));
+	       	menuItem1.addActionListener(new TreeNodeActionListener(tn,this,(DefaultTreeModel)tree.getModel(),"ADD"));       	
+	       	JPopupMenu popup = new JPopupMenu();
+	       	popup.add(menuItem1);
+	       	popup.add(menuItem2);
+	       	
+	       	if(e.isPopupTrigger()){
+	       		popup.show(tree,e.getX(),e.getY());
+	       	}
+	       	else{
+	       		//System.out.println("Wasn't popup trigger!");
+	       	}
+
+	       //}
+	    }
+	  }
+	  
+	  public void mouseReleased(MouseEvent e) {
+
+	  	//System.out.println("In Mouse Pressed event ");
+	    int selectedRow = tree.getRowForLocation(e.getX(), e.getY());
+	    TreePath selectedPath = tree.getPathForLocation(e.getX(), e.getY());
+	    
+	    if(selectedRow != -1) {
+	       DefaultMutableTreeNode tn               //get end of current path
+	        = (DefaultMutableTreeNode)(selectedPath.getLastPathComponent());
+	      // if (tn.isLeaf()){ //we need leaf only
+	         //write your required process for tn here
+	         //for instance: popupMenu.show( ..... );
+	         //below is a dummy process
+	         //String str = (String)(tn.getUserObject());
+	        // System.out.println(str);
+	       	
+	       	
+	       	JMenuItem menuItem1 = new JMenuItem("Add");
+	       	JMenuItem menuItem2 = new JMenuItem("Edit");
+	       	
+	       	menuItem2.addActionListener(new TreeNodeActionListener(tn,this,(DefaultTreeModel)tree.getModel(),"EDIT"));
+	       	menuItem1.addActionListener(new TreeNodeActionListener(tn,this,(DefaultTreeModel)tree.getModel(),"ADD"));  
+	       	JPopupMenu popup = new JPopupMenu();
+	       	popup.add(menuItem1);
+	       	popup.add(menuItem2);
+	       	
+	       	if(e.isPopupTrigger()){
+	       		popup.show(tree,e.getX(),e.getY());
+	       	}
+	       	else{
+	       		//System.out.println("Wasn't popup trigger!");
+	       	}
+
+	       //}
+	    }
+	  }
+	  
+	  public class TreeNodeActionListener implements ActionListener{
+	  	 private DefaultMutableTreeNode myTreeNode = null;
+	  	 private DefaultTreeModel myTreeModel = null;
+	  	 private LeafListener theLeafListener=null;
+	  	 private String type=null;
+	  	 
+	  	  public TreeNodeActionListener(DefaultMutableTreeNode t,LeafListener l,DefaultTreeModel tm,String theType){
+	  	  	myTreeNode = t;
+	  	  	theLeafListener = l;
+	  	  	myTreeModel = tm;
+	  	  	type = theType;
+	  	  }
+	  	  
+			public void actionPerformed(ActionEvent evt) {
+				//System.out.println("Caught click");
+				if(type.equals("ADD")){
+					theLeafListener.menuItem1ActionPerformed(evt,myTreeNode,myTreeModel);				
+				}
+				else if(type.equals("EDIT")){
+					theLeafListener.menuItem2ActionPerformed(evt,myTreeNode,myTreeModel);
+				}
+			}
+	  	  
+	  }
+	  
+	}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/ProfileBuilderGUI.form b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/ProfileBuilderGUI.form
new file mode 100755
index 0000000..c0b9ff0
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/ProfileBuilderGUI.form
@@ -0,0 +1,435 @@
+<?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.

+-->

+<Form style="Swing" ide="eclipse" builder="jigloo" laf="com.sun.java.swing.plaf.windows.WindowsLookAndFeel" version="2.7.2">

+<ExtraComponents>

+		<Component class="javax.swing.JMenuBar" name="jMenuBar1">

+			<Constraints>

+				<LayoutConstraint/>

+			</Constraints>

+			<Layout class="Box">

+				<Property name="axis" value="null"/>

+			</Layout>

+			<Events>

+			</Events>

+			<Properties>

+				<Property name="bounds" type="Rectangle">

+					<Rectangle value="[0, 0, 675, 21]"/>

+				</Property>

+			</Properties>

+			<SubComponents>

+				<Component class="javax.swing.JMenu" name="jMenu3">

+					<Constraints>

+						<LayoutConstraint/>

+					</Constraints>

+					<Layout class="Absolute">

+					</Layout>

+					<Events>

+					</Events>

+					<Properties>

+						<Property name="text" type="String" value="File"/>

+						<Property name="visible" type="boolean" value="true"/>

+					</Properties>

+					<SubComponents>

+						<Component class="javax.swing.JMenuItem" name="newFileMenuItem">

+							<Constraints>

+								<LayoutConstraint/>

+							</Constraints>

+							<Layout class="Absolute">

+							</Layout>

+							<Events>

+								<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" handler="newFileMenuItemActionPerformed"/>

+							</Events>

+							<Properties>

+								<Property name="text" type="String" value="New Profile"/>

+								<Property name="visible" type="boolean" value="true"/>

+								<Property name="preferredSize" type="Dimension">

+									<Dimension value="[28, 16]"/>

+								</Property>

+								<Property name="bounds" type="Rectangle">

+									<Rectangle value="[5, 5, 28, 16]"/>

+								</Property>

+							</Properties>

+						</Component>

+						<Component class="javax.swing.JMenuItem" name="openFileMenuItem">

+							<Constraints>

+								<LayoutConstraint/>

+							</Constraints>

+							<Layout class="Absolute">

+							</Layout>

+							<Events>

+								<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" handler="openFileMenuItemActionPerformed"/>

+							</Events>

+							<Properties>

+								<Property name="text" type="String" value="Open Profile"/>

+								<Property name="visible" type="boolean" value="true"/>

+								<Property name="bounds" type="Rectangle">

+									<Rectangle value="[5, 5, 60, 30]"/>

+								</Property>

+							</Properties>

+						</Component>

+						<Component class="javax.swing.JMenuItem" name="saveMenuItem">

+							<Constraints>

+								<LayoutConstraint/>

+							</Constraints>

+							<Layout class="Absolute">

+							</Layout>

+							<Events>

+								<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" handler="saveMenuItemActionPerformed"/>

+							</Events>

+							<Properties>

+								<Property name="text" type="String" value="Save Profile"/>

+								<Property name="visible" type="boolean" value="true"/>

+								<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>

+								<Property name="bounds" type="Rectangle">

+									<Rectangle value="[5, 5, 60, 30]"/>

+								</Property>

+							</Properties>

+						</Component>

+						<Component class="javax.swing.JMenuItem" name="closeFileMenuItem">

+							<Constraints>

+								<LayoutConstraint/>

+							</Constraints>

+							<Layout class="Absolute">

+							</Layout>

+							<Events>

+							</Events>

+							<Properties>

+								<Property name="text" type="String" value="Close"/>

+								<Property name="visible" type="boolean" value="true"/>

+								<Property name="bounds" type="Rectangle">

+									<Rectangle value="[5, 5, 60, 30]"/>

+								</Property>

+							</Properties>

+						</Component>

+						<Component class="javax.swing.JSeparator" name="jSeparator2">

+							<Constraints>

+								<LayoutConstraint/>

+							</Constraints>

+							<Layout class="Absolute">

+							</Layout>

+							<Events>

+							</Events>

+							<Properties>

+								<Property name="visible" type="boolean" value="true"/>

+								<Property name="bounds" type="Rectangle">

+									<Rectangle value="[5, 5, 60, 30]"/>

+								</Property>

+							</Properties>

+						</Component>

+						<Component class="javax.swing.JMenuItem" name="exitMenuItem">

+							<Constraints>

+								<LayoutConstraint/>

+							</Constraints>

+							<Layout class="Absolute">

+							</Layout>

+							<Events>

+								<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" handler="exitMenuItemActionPerformed"/>

+							</Events>

+							<Properties>

+								<Property name="text" type="String" value="Exit"/>

+								<Property name="visible" type="boolean" value="true"/>

+								<Property name="bounds" type="Rectangle">

+									<Rectangle value="[5, 5, 60, 30]"/>

+								</Property>

+							</Properties>

+						</Component>

+					</SubComponents>

+				</Component>

+				<Component class="javax.swing.JMenu" name="jMenu4">

+					<Constraints>

+						<LayoutConstraint/>

+					</Constraints>

+					<Layout class="Absolute">

+					</Layout>

+					<Events>

+					</Events>

+					<Properties>

+						<Property name="text" type="String" value="Edit"/>

+						<Property name="visible" type="boolean" value="true"/>

+					</Properties>

+					<SubComponents>

+						<Component class="javax.swing.JMenuItem" name="cutMenuItem">

+							<Constraints>

+								<LayoutConstraint/>

+							</Constraints>

+							<Layout class="Absolute">

+							</Layout>

+							<Events>

+							</Events>

+							<Properties>

+								<Property name="text" type="String" value="Cut"/>

+								<Property name="visible" type="boolean" value="true"/>

+								<Property name="preferredSize" type="Dimension">

+									<Dimension value="[27, 16]"/>

+								</Property>

+								<Property name="bounds" type="Rectangle">

+									<Rectangle value="[5, 5, 27, 16]"/>

+								</Property>

+							</Properties>

+						</Component>

+						<Component class="javax.swing.JMenuItem" name="copyMenuItem">

+							<Constraints>

+								<LayoutConstraint/>

+							</Constraints>

+							<Layout class="Absolute">

+							</Layout>

+							<Events>

+							</Events>

+							<Properties>

+								<Property name="text" type="String" value="Copy"/>

+								<Property name="visible" type="boolean" value="true"/>

+								<Property name="bounds" type="Rectangle">

+									<Rectangle value="[5, 5, 60, 30]"/>

+								</Property>

+							</Properties>

+						</Component>

+						<Component class="javax.swing.JMenuItem" name="pasteMenuItem">

+							<Constraints>

+								<LayoutConstraint/>

+							</Constraints>

+							<Layout class="Absolute">

+							</Layout>

+							<Events>

+							</Events>

+							<Properties>

+								<Property name="text" type="String" value="Paste"/>

+								<Property name="visible" type="boolean" value="true"/>

+								<Property name="bounds" type="Rectangle">

+									<Rectangle value="[5, 5, 60, 30]"/>

+								</Property>

+							</Properties>

+						</Component>

+						<Component class="javax.swing.JSeparator" name="jSeparator1">

+							<Constraints>

+								<LayoutConstraint/>

+							</Constraints>

+							<Layout class="Absolute">

+							</Layout>

+							<Events>

+							</Events>

+							<Properties>

+								<Property name="visible" type="boolean" value="true"/>

+								<Property name="bounds" type="Rectangle">

+									<Rectangle value="[5, 5, 60, 30]"/>

+								</Property>

+							</Properties>

+						</Component>

+						<Component class="javax.swing.JMenuItem" name="deleteMenuItem">

+							<Constraints>

+								<LayoutConstraint/>

+							</Constraints>

+							<Layout class="Absolute">

+							</Layout>

+							<Events>

+							</Events>

+							<Properties>

+								<Property name="text" type="String" value="Delete"/>

+								<Property name="visible" type="boolean" value="true"/>

+								<Property name="bounds" type="Rectangle">

+									<Rectangle value="[5, 5, 60, 30]"/>

+								</Property>

+							</Properties>

+						</Component>

+					</SubComponents>

+				</Component>

+				<Component class="javax.swing.JMenu" name="jMenu5">

+					<Constraints>

+						<LayoutConstraint/>

+					</Constraints>

+					<Layout class="Absolute">

+					</Layout>

+					<Events>

+					</Events>

+					<Properties>

+						<Property name="text" type="String" value="Help"/>

+						<Property name="visible" type="boolean" value="true"/>

+					</Properties>

+					<SubComponents>

+						<Component class="javax.swing.JMenuItem" name="helpMenuItem">

+							<Constraints>

+								<LayoutConstraint/>

+							</Constraints>

+							<Layout class="Absolute">

+							</Layout>

+							<Events>

+							</Events>

+							<Properties>

+								<Property name="text" type="String" value="Help"/>

+								<Property name="visible" type="boolean" value="true"/>

+								<Property name="preferredSize" type="Dimension">

+									<Dimension value="[31, 16]"/>

+								</Property>

+								<Property name="bounds" type="Rectangle">

+									<Rectangle value="[5, 5, 31, 16]"/>

+								</Property>

+							</Properties>

+						</Component>

+					</SubComponents>

+				</Component>

+			</SubComponents>

+		</Component></ExtraComponents>

+<NonVisualComponents>

+		<Component class="java.lang.Object" name="object1">

+			<Constraints>

+				<LayoutConstraint/>

+			</Constraints>

+			<Properties>

+			</Properties>

+		</Component></NonVisualComponents>

+	<Component class="javax.swing.JFrame" name="ProfileBuilderGUI">

+		<Constraints>

+			<LayoutConstraint/>

+		</Constraints>

+		<Layout class="Border">

+			<Property name="hgap" type="int" value="0"/>

+			<Property name="vgap" type="int" value="0"/>

+		</Layout>

+		<Events>

+		</Events>

+		<Properties>

+			<Property name="title" type="String" value="OODT Profile Builder"/>

+			<Property name="size" type="Dimension">

+				<Dimension value="[675, 360]"/>

+			</Property>

+			<Property name="bounds" type="Rectangle">

+				<Rectangle value="[0, 0, 675, 360]"/>

+			</Property>

+		</Properties>

+		<SubComponents>

+			<Component class="javax.swing.JPanel" name="jPanel1">

+				<Constraints>

+					<Constraint direction="Center"/>

+					<LayoutConstraint>

+						<Property name="direction" type="String" value="Center"/>

+					</LayoutConstraint>

+				</Constraints>

+				<Layout class="Border">

+					<Property name="hgap" type="int" value="0"/>

+					<Property name="vgap" type="int" value="0"/>

+				</Layout>

+				<Events>

+				</Events>

+				<Properties>

+					<Property name="bounds" type="Rectangle">

+						<Rectangle value="[0, 0, 675, 316]"/>

+					</Property>

+				</Properties>

+				<SubComponents>

+					<Component class="javax.swing.JScrollPane" name="jPanel2">

+						<Constraints>

+							<Constraint direction="West"/>

+							<LayoutConstraint>

+								<Property name="direction" type="String" value="West"/>

+							</LayoutConstraint>

+						</Constraints>

+						<Events>

+						</Events>

+						<Properties>

+							<Property name="preferredSize" type="Dimension">

+								<Dimension value="[231, 339]"/>

+							</Property>

+							<Property name="autoscrolls" type="boolean" value="true"/>

+							<Property name="bounds" type="Rectangle">

+								<Rectangle value="[0, 0, 231, 316]"/>

+							</Property>

+						</Properties>

+						<SubComponents>

+							<Component class="jpl.eda.profile.gui.profileTree" name="jTree1">

+								<Constraints>

+									<LayoutConstraint/>

+								</Constraints>

+								<Events>

+								</Events>

+								<Properties>

+									<Property name="editable" type="boolean" value="true"/>

+									<Property name="preferredSize" type="Dimension">

+										<Dimension value="[426, 800]"/>

+									</Property>

+									<Property name="autoscrolls" type="boolean" value="true"/>

+									<Property name="maximumSize" type="Dimension">

+										<Dimension value="[426, 800]"/>

+									</Property>

+									<Property name="opaque" type="boolean" value="true"/>

+									<Property name="size" type="Dimension">

+										<Dimension value="[426, 800]"/>

+									</Property>

+									<Property name="bounds" type="Rectangle">

+										<Rectangle value="[0, 0, 426, 800]"/>

+									</Property>

+								</Properties>

+							</Component>

+						</SubComponents>

+					</Component>

+					<Component class="javax.swing.JScrollPane" name="jPanel3">

+						<Constraints>

+							<Constraint direction="East"/>

+							<LayoutConstraint>

+								<Property name="direction" type="String" value="East"/>

+							</LayoutConstraint>

+						</Constraints>

+						<Events>

+						</Events>

+						<Properties>

+							<Property name="preferredSize" type="Dimension">

+								<Dimension value="[444, 339]"/>

+							</Property>

+							<Property name="autoscrolls" type="boolean" value="true"/>

+							<Property name="bounds" type="Rectangle">

+								<Rectangle value="[231, 0, 444, 316]"/>

+							</Property>

+						</Properties>

+						<SubComponents>

+							<Component class="javax.swing.JEditorPane" name="jEditorPane1">

+								<Constraints>

+									<LayoutConstraint/>

+								</Constraints>

+								<Events>

+								</Events>

+								<Properties>

+									<Property name="text" type="String" value=""/>

+									<Property name="editable" type="boolean" value="false"/>

+									<Property name="preferredSize" type="Dimension">

+										<Dimension value="[414, 320]"/>

+									</Property>

+									<Property name="autoscrolls" type="boolean" value="true"/>

+									<Property name="bounds" type="Rectangle">

+										<Rectangle value="[0, 0, 442, 314]"/>

+									</Property>

+								</Properties>

+							</Component>

+						</SubComponents>

+					</Component>

+				</SubComponents>

+			</Component>

+			<Component class="javax.swing.JButton" name="jButton1">

+				<Constraints>

+					<Constraint direction="South"/>

+					<LayoutConstraint>

+						<Property name="direction" type="String" value="South"/>

+					</LayoutConstraint>

+				</Constraints>

+				<Events>

+					<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" handler="jButton1ActionPerformed"/>

+				</Events>

+				<Properties>

+					<Property name="text" type="String" value="Show XML"/>

+				</Properties>

+			</Component>

+		</SubComponents>

+	</Component>

+</Form>

diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/ProfileBuilderGUI.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/ProfileBuilderGUI.java
new file mode 100755
index 0000000..25fd02f
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/ProfileBuilderGUI.java
@@ -0,0 +1,991 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.profile.gui;
+
+import javax.swing.JSeparator;
+import javax.swing.JMenuItem;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JPanel;
+import javax.swing.JEditorPane;
+import javax.swing.JScrollPane;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.BorderLayout;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreeModel;
+import javax.swing.JFileChooser;
+
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileElement;
+import org.apache.oodt.profile.RangedProfileElement;
+import org.apache.oodt.profile.gui.profileTree;
+
+import org.apache.oodt.profile.gui.pstructs.ProfilePrinter;
+
+
+import java.util.Iterator;
+import java.util.Enumeration;
+import java.util.List;
+
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import javax.swing.JButton;
+import org.xml.sax.SAXException;
+
+/**
+* This code was generated using CloudGarden's Jigloo
+* SWT/Swing GUI Builder, which is free for non-commercial
+* use. If Jigloo is being used commercially (ie, by a
+* for-profit company or business) then you should purchase
+* a license - please visit www.cloudgarden.com for details.
+*/
+public class ProfileBuilderGUI extends javax.swing.JFrame {
+	private JButton jButton1;
+	private JEditorPane jEditorPane1;
+	private JScrollPane jPanel3;
+	private profileTree jTree1;
+	private JScrollPane jPanel2;
+	private JPanel jPanel1;
+	private JMenuItem helpMenuItem;
+	private JMenu jMenu5;
+	private JMenuItem deleteMenuItem;
+	private JSeparator jSeparator1;
+	private JMenuItem pasteMenuItem;
+	private JMenuItem copyMenuItem;
+	private JMenuItem cutMenuItem;
+	private JMenu jMenu4;
+	private JMenuItem exitMenuItem;
+	private JSeparator jSeparator2;
+	private JMenuItem closeFileMenuItem;
+	private JMenuItem saveMenuItem;
+	private JMenuItem openFileMenuItem;
+	private JMenuItem newFileMenuItem;
+	private JMenu jMenu3;
+	private JMenuBar jMenuBar1;
+	
+	private Profile createdProfile=null;
+	
+
+	public ProfileBuilderGUI() {
+		initGUI();
+	}
+
+	/**
+	* Initializes the GUI.
+	* Auto-generated code - any changes you make will disappear.
+	*/
+	public void initGUI(){
+		try {
+			preInitGUI();
+	
+			try {
+				javax.swing.UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
+			} catch(Exception e) {
+				e.printStackTrace();
+			}
+			jPanel1 = new JPanel();
+			jPanel2 = new JScrollPane();
+			jTree1 = new profileTree();
+			jPanel3 = new JScrollPane();
+			jEditorPane1 = new JEditorPane();
+			jButton1 = new JButton();
+	
+			BorderLayout thisLayout = new BorderLayout();
+			this.getContentPane().setLayout(thisLayout);
+			thisLayout.setHgap(0);
+			thisLayout.setVgap(0);
+			this.setTitle("OODT Profile Builder");
+			this.setSize(new java.awt.Dimension(682,387));
+	
+			BorderLayout jPanel1Layout = new BorderLayout();
+			jPanel1.setLayout(jPanel1Layout);
+			jPanel1Layout.setHgap(0);
+			jPanel1Layout.setVgap(0);
+			this.getContentPane().add(jPanel1, BorderLayout.CENTER);
+	
+			jPanel2.setPreferredSize(new java.awt.Dimension(231,339));
+			jPanel2.setAutoscrolls(true);
+			jPanel1.add(jPanel2, BorderLayout.WEST);
+	
+			jTree1.setEditable(true);
+			jTree1.setPreferredSize(new java.awt.Dimension(426,800));
+			jTree1.setAutoscrolls(true);
+			jTree1.setMaximumSize(new java.awt.Dimension(426,800));
+			jTree1.setOpaque(true);
+			jTree1.setSize(new java.awt.Dimension(426,800));
+			jPanel2.add(jTree1);
+			jPanel2.setViewportView(jTree1);
+	
+			jPanel3.setPreferredSize(new java.awt.Dimension(444,339));
+			jPanel3.setAutoscrolls(true);
+			jPanel1.add(jPanel3, BorderLayout.EAST);
+	
+			jEditorPane1.setEditable(false);
+			jEditorPane1.setPreferredSize(new java.awt.Dimension(414,320));
+			jEditorPane1.setAutoscrolls(true);
+			jPanel3.add(jEditorPane1);
+			jPanel3.setViewportView(jEditorPane1);
+	
+			jButton1.setText("Show XML");
+			this.getContentPane().add(jButton1, BorderLayout.SOUTH);
+			jButton1.addActionListener( new ActionListener() {
+				public void actionPerformed(ActionEvent evt) {
+					jButton1ActionPerformed(evt);
+				}
+			});
+			jMenuBar1 = new JMenuBar();
+			jMenu3 = new JMenu();
+			newFileMenuItem = new JMenuItem();
+			openFileMenuItem = new JMenuItem();
+			saveMenuItem = new JMenuItem();
+			closeFileMenuItem = new JMenuItem();
+			jSeparator2 = new JSeparator();
+			exitMenuItem = new JMenuItem();
+			jMenu4 = new JMenu();
+			cutMenuItem = new JMenuItem();
+			copyMenuItem = new JMenuItem();
+			pasteMenuItem = new JMenuItem();
+			jSeparator1 = new JSeparator();
+			deleteMenuItem = new JMenuItem();
+			jMenu5 = new JMenu();
+			helpMenuItem = new JMenuItem();
+	
+			setJMenuBar(jMenuBar1);
+	
+			jMenu3.setText("File");
+			jMenu3.setVisible(true);
+			jMenuBar1.add(jMenu3);
+	
+			newFileMenuItem.setText("New Profile");
+			newFileMenuItem.setVisible(true);
+			newFileMenuItem.setPreferredSize(new java.awt.Dimension(28,16));
+			newFileMenuItem.setBounds(new java.awt.Rectangle(5,5,28,16));
+			jMenu3.add(newFileMenuItem);
+			newFileMenuItem.addActionListener( new ActionListener() {
+				public void actionPerformed(ActionEvent evt) {
+					newFileMenuItemActionPerformed(evt);
+				}
+			});
+	
+			openFileMenuItem.setText("Open Profile");
+			openFileMenuItem.setVisible(true);
+			openFileMenuItem.setBounds(new java.awt.Rectangle(5,5,60,30));
+			jMenu3.add(openFileMenuItem);
+			openFileMenuItem.addActionListener( new ActionListener() {
+				public void actionPerformed(ActionEvent evt) {
+					openFileMenuItemActionPerformed(evt);
+				}
+			});
+	
+			saveMenuItem.setText("Save Profile");
+			saveMenuItem.setVisible(true);
+			saveMenuItem.setVerifyInputWhenFocusTarget(false);
+			saveMenuItem.setBounds(new java.awt.Rectangle(5,5,60,30));
+			jMenu3.add(saveMenuItem);
+			saveMenuItem.addActionListener( new ActionListener() {
+				public void actionPerformed(ActionEvent evt) {
+					saveMenuItemActionPerformed(evt);
+				}
+			});
+	
+			closeFileMenuItem.setText("Close");
+			closeFileMenuItem.setVisible(true);
+			closeFileMenuItem.setBounds(new java.awt.Rectangle(5,5,60,30));
+			jMenu3.add(closeFileMenuItem);
+	
+			jSeparator2.setVisible(true);
+			jSeparator2.setBounds(new java.awt.Rectangle(5,5,60,30));
+			jMenu3.add(jSeparator2);
+	
+			exitMenuItem.setText("Exit");
+			exitMenuItem.setVisible(true);
+			exitMenuItem.setBounds(new java.awt.Rectangle(5,5,60,30));
+			jMenu3.add(exitMenuItem);
+			exitMenuItem.addActionListener( new ActionListener() {
+				public void actionPerformed(ActionEvent evt) {
+					exitMenuItemActionPerformed(evt);
+				}
+			});
+	
+			jMenu4.setText("Edit");
+			jMenu4.setVisible(true);
+			jMenuBar1.add(jMenu4);
+	
+			cutMenuItem.setText("Cut");
+			cutMenuItem.setVisible(true);
+			cutMenuItem.setPreferredSize(new java.awt.Dimension(27,16));
+			cutMenuItem.setBounds(new java.awt.Rectangle(5,5,27,16));
+			jMenu4.add(cutMenuItem);
+	
+			copyMenuItem.setText("Copy");
+			copyMenuItem.setVisible(true);
+			copyMenuItem.setBounds(new java.awt.Rectangle(5,5,60,30));
+			jMenu4.add(copyMenuItem);
+	
+			pasteMenuItem.setText("Paste");
+			pasteMenuItem.setVisible(true);
+			pasteMenuItem.setBounds(new java.awt.Rectangle(5,5,60,30));
+			jMenu4.add(pasteMenuItem);
+	
+			jSeparator1.setVisible(true);
+			jSeparator1.setBounds(new java.awt.Rectangle(5,5,60,30));
+			jMenu4.add(jSeparator1);
+	
+			deleteMenuItem.setText("Delete");
+			deleteMenuItem.setVisible(true);
+			deleteMenuItem.setBounds(new java.awt.Rectangle(5,5,60,30));
+			jMenu4.add(deleteMenuItem);
+	
+			jMenu5.setText("Help");
+			jMenu5.setVisible(true);
+			jMenuBar1.add(jMenu5);
+	
+			helpMenuItem.setText("Help");
+			helpMenuItem.setVisible(true);
+			helpMenuItem.setPreferredSize(new java.awt.Dimension(31,16));
+			helpMenuItem.setBounds(new java.awt.Rectangle(5,5,31,16));
+			jMenu5.add(helpMenuItem);
+	
+			postInitGUI();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+	/** Add your pre-init code in here 	*/
+	public void preInitGUI(){
+	}
+
+	/** Add your post-init code in here 	*/
+	public void postInitGUI(){
+	}
+
+	/** Auto-generated main method */
+	public static void main(String[] args){
+		//showGUI();
+		showMainGUI();
+	}
+
+	public static void showMainGUI(){
+		try {
+			ProfileBuilderGUI inst = new ProfileBuilderGUI();
+			inst.setVisible(true);
+			inst.getJTree1().addMouseListener(new LeafListener(inst.getJTree1()));
+		    inst.getJTree1().setExpandsSelectedPaths(true);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+
+
+	
+	
+	
+	/**
+	* This static method creates a new instance of this class and shows
+	* it inside a new JFrame, (unless it is already a JFrame).
+	*
+	* It is a convenience method for showing the GUI, but it can be
+	* copied and used as a basis for your own code.	*
+	* It is auto-generated code - the body of this method will be
+	* re-generated after any changes are made to the GUI.
+	* However, if you delete this method it will not be re-created.	*/
+	public static void showGUI(){
+		try {
+			ProfileBuilderGUI inst = new ProfileBuilderGUI();
+			inst.setVisible(true);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+/**
+* Auto-generated method
+*/public JPanel getJPanel1(){
+return jPanel1;	}
+/**
+* Auto-generated method
+*/public JScrollPane getJPanel2(){
+return jPanel2;	}
+/**
+* Auto-generated method
+*/public profileTree getJTree1(){
+return jTree1;	}
+
+public void setJTree1(profileTree jt){
+	jTree1 = jt;
+	repaint();
+}
+/**
+* Auto-generated method
+*/public JScrollPane getJPanel3(){
+return jPanel3;	}
+/**
+* Auto-generated method
+*/public JEditorPane getJEditorPane1(){
+return jEditorPane1;	}
+
+
+
+	/** Auto-generated event handler method */
+	protected void newFileMenuItemActionPerformed(ActionEvent evt){
+		//TODO add your handler code here
+		
+			createdProfile = new Profile();
+			jEditorPane1.setText(new ProfilePrinter(createdProfile,"http://oodt.jpl.nasa.gov/dtd/prof.dtd").toXMLString());
+			
+			getJTree1().setModel(generateModelFromProfile(createdProfile));
+			//getJTree1().addMouseListener(new LeafListener(getJTree1()));
+	}
+
+	/** Auto-generated event handler method */
+	protected void exitMenuItemActionPerformed(ActionEvent evt){
+		//TODO add your handler code here
+		System.exit(1);
+	}
+	
+	private void addElementsFromTreeNode(TreeNode t, List multiValueElem){
+		for(Enumeration i = t.children(); i.hasMoreElements(); ){
+            DefaultMutableTreeNode theNode = (DefaultMutableTreeNode)i.nextElement();
+            
+            String theStr = (String)theNode.getUserObject();
+            multiValueElem.add(theStr);    
+		}
+	}
+	
+	
+	
+	private Profile generateProfileFromModel(TreeModel dtm){
+		
+		Profile p = new Profile();
+		DefaultMutableTreeNode theProfileRoot = (DefaultMutableTreeNode)dtm.getRoot();
+		
+		//get the profile attributes
+		//children List
+		//id String
+		//parent String
+		//regAuthority String
+		//revisionNotes List
+		//securityType String
+		//statusID String
+		//type String
+		//version String
+		TreeNode theProfAttrRoot = theProfileRoot.getChildAt(0);
+
+		TreeNode theProfAttr_Children = theProfAttrRoot.getChildAt(0);
+		addElementsFromTreeNode(theProfAttr_Children,p.getProfileAttributes().getChildren());
+
+		TreeNode theProfAttr_IDRoot = theProfAttrRoot.getChildAt(1);
+		DefaultMutableTreeNode theProfAttr_ID = (DefaultMutableTreeNode)theProfAttr_IDRoot.getChildAt(0);
+		p.getProfileAttributes().setID((String)theProfAttr_ID.getUserObject());
+		
+		TreeNode theProfAttr_ParentRoot = theProfAttrRoot.getChildAt(2);
+		DefaultMutableTreeNode theProfAttr_Parent = (DefaultMutableTreeNode)theProfAttr_ParentRoot.getChildAt(0);
+		p.getProfileAttributes().setParent((String)theProfAttr_Parent.getUserObject());
+		
+		
+		TreeNode theProfAttr_RegAuthorityRoot = theProfAttrRoot.getChildAt(3);
+		DefaultMutableTreeNode theProfAttr_RegAuthority = (DefaultMutableTreeNode)theProfAttr_RegAuthorityRoot.getChildAt(0);
+		p.getProfileAttributes().setRegAuthority((String)theProfAttr_RegAuthority.getUserObject());
+		
+		TreeNode theProfAttr_revNotes = theProfAttrRoot.getChildAt(4);
+		addElementsFromTreeNode(theProfAttr_revNotes,p.getProfileAttributes().getRevisionNotes());
+
+		TreeNode theProfAttr_SecurityTypeRoot = theProfAttrRoot.getChildAt(5);
+		DefaultMutableTreeNode theProfAttr_SecurityType = (DefaultMutableTreeNode)theProfAttr_SecurityTypeRoot.getChildAt(0);
+		p.getProfileAttributes().setSecurityType((String)theProfAttr_SecurityType.getUserObject());
+		
+		TreeNode theProfAttr_StatusIDRoot = theProfAttrRoot.getChildAt(6);
+		DefaultMutableTreeNode theProfAttr_StatusID = (DefaultMutableTreeNode)theProfAttr_StatusIDRoot.getChildAt(0);
+		p.getProfileAttributes().setStatusID((String)theProfAttr_StatusID.getUserObject());
+		
+		TreeNode theProfAttr_TypeRoot = theProfAttrRoot.getChildAt(7);
+		DefaultMutableTreeNode theProfAttr_Type = (DefaultMutableTreeNode)theProfAttr_TypeRoot.getChildAt(0);
+		p.getProfileAttributes().setType((String)theProfAttr_Type.getUserObject());
+		
+		TreeNode theProfAttr_VersionRoot = theProfAttrRoot.getChildAt(8);
+		DefaultMutableTreeNode theProfAttr_Version = (DefaultMutableTreeNode)theProfAttr_VersionRoot.getChildAt(0);
+		p.getProfileAttributes().setVersion((String)theProfAttr_Version.getUserObject());
+				
+
+		//resource attributes
+		//aggregation - string
+		//class - string
+		//contexts - list
+		//contributors - list
+		//coverages - list
+		//creators - list
+		//dates - list
+		//description - string
+		//formats - list
+		//identifier - string
+		//languages - list
+		//locations - list
+		//publishers - list
+		//relations - list
+		//rights - list
+		//sources - list
+		//subjects - list
+		//title - string
+		//types - list
+		
+		TreeNode theResAttrRoot = theProfileRoot.getChildAt(1);
+		
+		TreeNode ra_aggRoot=theResAttrRoot.getChildAt(0);
+		TreeNode ra_classRoot=theResAttrRoot.getChildAt(1);
+		TreeNode ra_contextRoot=theResAttrRoot.getChildAt(2);
+		TreeNode ra_contribRoot=theResAttrRoot.getChildAt(3);
+		TreeNode ra_coverageRoot=theResAttrRoot.getChildAt(4);
+		TreeNode ra_creatorRoot=theResAttrRoot.getChildAt(5);
+		TreeNode ra_datesRoot=theResAttrRoot.getChildAt(6);
+		TreeNode ra_descRoot=theResAttrRoot.getChildAt(7);
+		TreeNode ra_formatsRoot=theResAttrRoot.getChildAt(8);
+		TreeNode ra_identifierRoot=theResAttrRoot.getChildAt(9);
+		TreeNode ra_langRoot=theResAttrRoot.getChildAt(10);
+		TreeNode ra_locationRoot=theResAttrRoot.getChildAt(11);
+		TreeNode ra_publishersRoot=theResAttrRoot.getChildAt(12);
+		TreeNode ra_relationsRoot=theResAttrRoot.getChildAt(13);
+		TreeNode ra_rightsRoot=theResAttrRoot.getChildAt(14);
+		TreeNode ra_sourcesRoot=theResAttrRoot.getChildAt(15);
+		TreeNode ra_subjectsRoot=theResAttrRoot.getChildAt(16);
+		TreeNode ra_titleRoot=theResAttrRoot.getChildAt(17);
+		TreeNode ra_typesRoot=theResAttrRoot.getChildAt(18);
+		
+		DefaultMutableTreeNode ra_agg = (DefaultMutableTreeNode)ra_aggRoot.getChildAt(0);
+		DefaultMutableTreeNode ra_class = (DefaultMutableTreeNode)ra_classRoot.getChildAt(0);
+		
+		
+		p.getResourceAttributes().setResAggregation((String)ra_agg.getUserObject());
+		p.getResourceAttributes().setResClass((String)ra_class.getUserObject());
+		addElementsFromTreeNode(ra_contextRoot,p.getResourceAttributes().getResContexts());
+		addElementsFromTreeNode(ra_contribRoot,p.getResourceAttributes().getContributors());
+		addElementsFromTreeNode(ra_coverageRoot,p.getResourceAttributes().getCoverages());
+		addElementsFromTreeNode(ra_creatorRoot,p.getResourceAttributes().getCreators());
+		addElementsFromTreeNode(ra_datesRoot,p.getResourceAttributes().getDates());
+		
+		DefaultMutableTreeNode ra_desc = (DefaultMutableTreeNode)ra_descRoot.getChildAt(0);
+		DefaultMutableTreeNode ra_identifier = (DefaultMutableTreeNode)ra_identifierRoot.getChildAt(0);
+		
+		p.getResourceAttributes().setDescription((String)ra_desc.getUserObject());
+		p.getResourceAttributes().setIdentifier((String)ra_identifier.getUserObject());
+		
+		addElementsFromTreeNode(ra_formatsRoot,p.getResourceAttributes().getFormats());
+		addElementsFromTreeNode(ra_langRoot,p.getResourceAttributes().getLanguages());
+		addElementsFromTreeNode(ra_locationRoot,p.getResourceAttributes().getResLocations());
+		addElementsFromTreeNode(ra_publishersRoot,p.getResourceAttributes().getPublishers());
+		addElementsFromTreeNode(ra_relationsRoot,p.getResourceAttributes().getRelations());
+		addElementsFromTreeNode(ra_rightsRoot,p.getResourceAttributes().getRights());
+		addElementsFromTreeNode(ra_sourcesRoot,p.getResourceAttributes().getSources());
+		addElementsFromTreeNode(ra_subjectsRoot,p.getResourceAttributes().getSubjects());
+		addElementsFromTreeNode(ra_typesRoot,p.getResourceAttributes().getTypes());
+		
+		DefaultMutableTreeNode ra_title = (DefaultMutableTreeNode)ra_titleRoot.getChildAt(0);
+		p.getResourceAttributes().setTitle((String)ra_title.getUserObject());
+		
+		//handle profile elements here
+		TreeNode theProfElemRoot = theProfileRoot.getChildAt(2);
+		
+		for(Enumeration e = theProfElemRoot.children(); e.hasMoreElements(); ){
+			DefaultMutableTreeNode profElemN_Root = (DefaultMutableTreeNode)e.nextElement();
+			System.out.println("Got Profile Element "+(String)profElemN_Root.getUserObject());
+			ProfileElement profElem = makeProfileElementFromTreeNode(p,profElemN_Root);
+			
+			if(profElem != null){
+				System.out.println("Making profile element");
+				System.out.println(profElem.toString());
+				
+				p.getProfileElements().put((String)profElemN_Root.getUserObject(),profElem);
+			}
+			
+			
+		}
+		
+		
+		return p;
+	}
+	
+	private ProfileElement makeProfileElementFromTreeNode(Profile theProfile,DefaultMutableTreeNode tn){
+		
+		ProfileElement theProfileElement = new RangedProfileElement(theProfile);
+		
+		DefaultMutableTreeNode commentRoot = (DefaultMutableTreeNode)tn.getChildAt(0);
+		DefaultMutableTreeNode descRoot = (DefaultMutableTreeNode)tn.getChildAt(1);
+		DefaultMutableTreeNode idRoot = (DefaultMutableTreeNode)tn.getChildAt(2);
+		DefaultMutableTreeNode moRoot = (DefaultMutableTreeNode)tn.getChildAt(3);
+		DefaultMutableTreeNode synRoot = (DefaultMutableTreeNode)tn.getChildAt(4);
+		DefaultMutableTreeNode typeRoot = (DefaultMutableTreeNode)tn.getChildAt(5);
+		DefaultMutableTreeNode unitRoot = (DefaultMutableTreeNode)tn.getChildAt(6);
+		
+		DefaultMutableTreeNode pe_Comments = (DefaultMutableTreeNode)commentRoot.getChildAt(0);
+		DefaultMutableTreeNode pe_desc = (DefaultMutableTreeNode)descRoot.getChildAt(0);
+		DefaultMutableTreeNode pe_id = (DefaultMutableTreeNode)idRoot.getChildAt(0);
+		DefaultMutableTreeNode pe_mo = (DefaultMutableTreeNode)moRoot.getChildAt(0);
+		DefaultMutableTreeNode pe_type = (DefaultMutableTreeNode)typeRoot.getChildAt(0);
+		DefaultMutableTreeNode pe_unit = (DefaultMutableTreeNode)unitRoot.getChildAt(0);
+		
+		addElementsFromTreeNode(synRoot,theProfileElement.getSynonyms());
+		
+		theProfileElement.setName((String)tn.getUserObject());
+		theProfileElement.setComments((String)pe_Comments.getUserObject());
+		theProfileElement.setDescription((String)pe_desc.getUserObject());
+		theProfileElement.setID((String)pe_id.getUserObject());
+		theProfileElement.setMaxOccurrence(Integer.parseInt((String)pe_mo.getUserObject()));
+		theProfileElement.setType((String)pe_type.getUserObject());
+		theProfileElement.setUnit((String)pe_unit.getUserObject());
+		
+		return theProfileElement;
+		
+		//return new RangedProfileElement(new Profile());
+	}
+	
+	
+	
+	private DefaultTreeModel generateModelFromProfile(Profile p){
+		DefaultMutableTreeNode root = new DefaultMutableTreeNode("Profile");
+		DefaultMutableTreeNode resAttrRoot = new DefaultMutableTreeNode("Resource Attributes");
+		DefaultMutableTreeNode profAttrRoot = new DefaultMutableTreeNode("Profile Attributes");
+		DefaultMutableTreeNode profElemRoot = new DefaultMutableTreeNode("Profile Elements");
+		
+		//do the Profile Attributes here
+		//children List
+		//id String
+		//parent String
+		//regAuthority String
+		//revisionNotes List
+		//securityType String
+		//statusID String
+		//type String
+		//version String
+		
+		DefaultMutableTreeNode profAttr_children = new DefaultMutableTreeNode("Children");
+		
+		for(Iterator i = p.getProfileAttributes().getChildren().iterator(); i.hasNext(); ){
+			String theChild = (String)i.next();
+			
+			DefaultMutableTreeNode profAttr_childN = new DefaultMutableTreeNode(theChild);
+			profAttr_children.add(profAttr_childN);
+		}
+		
+		
+		DefaultMutableTreeNode profAttr_id = new DefaultMutableTreeNode("Id");
+		profAttr_id.add(new DefaultMutableTreeNode(p.getProfileAttributes().getID()));
+
+		DefaultMutableTreeNode profAttr_parent = new DefaultMutableTreeNode("Parent");
+		profAttr_parent.add(new DefaultMutableTreeNode(p.getProfileAttributes().getParent()));		
+
+		DefaultMutableTreeNode profAttr_regAuth = new DefaultMutableTreeNode("Registration Authority");
+		profAttr_regAuth.add(new DefaultMutableTreeNode(p.getProfileAttributes().getRegAuthority()));		
+		
+		DefaultMutableTreeNode profAttr_revNotes = new DefaultMutableTreeNode("Revision Notes");
+		
+		for(Iterator i = p.getProfileAttributes().getRevisionNotes().iterator(); i.hasNext(); ){
+			String revNoteString = (String)i.next();
+			
+			DefaultMutableTreeNode revNote_Child = new DefaultMutableTreeNode(revNoteString);
+			profAttr_revNotes.add(revNote_Child);
+		}
+
+		DefaultMutableTreeNode profAttr_securityType = new DefaultMutableTreeNode("Security Type");
+		profAttr_securityType.add(new DefaultMutableTreeNode(p.getProfileAttributes().getSecurityType()));		
+		
+		DefaultMutableTreeNode profAttr_statusID = new DefaultMutableTreeNode("Status ID");
+		profAttr_statusID.add(new DefaultMutableTreeNode(p.getProfileAttributes().getStatusID()));		
+		
+		DefaultMutableTreeNode profAttr_type = new DefaultMutableTreeNode("Type");
+		profAttr_type.add(new DefaultMutableTreeNode(p.getProfileAttributes().getType()));		
+		
+		DefaultMutableTreeNode profAttr_version = new DefaultMutableTreeNode("Version");
+		profAttr_version.add(new DefaultMutableTreeNode(p.getProfileAttributes().getVersion()));		
+		
+		profAttrRoot.add(profAttr_children);
+		profAttrRoot.add(profAttr_id);
+		profAttrRoot.add(profAttr_parent);
+		profAttrRoot.add(profAttr_regAuth);
+		profAttrRoot.add(profAttr_revNotes);
+		profAttrRoot.add(profAttr_securityType);
+		profAttrRoot.add(profAttr_statusID);
+		profAttrRoot.add(profAttr_type);
+		profAttrRoot.add(profAttr_version);
+		
+		//resource attributes
+		//aggregation - string
+		//class - string
+		//contexts - list
+		//contributors - list
+		//coverages - list
+		//creators - list
+		//dates - list
+		//description - string
+		//formats - list
+		//identifier - string
+		//languages - list
+		//locations - list
+		//publishers - list
+		//relations - list
+		//rights - list
+		//sources - list
+		//subjects - list
+		//title - string
+		//types - list
+		
+		DefaultMutableTreeNode resAttr_aggregation = new DefaultMutableTreeNode("Aggregation");
+		resAttr_aggregation.add(new DefaultMutableTreeNode(p.getResourceAttributes().getResAggregation()));		
+
+		DefaultMutableTreeNode resAttr_class = new DefaultMutableTreeNode("Class");
+		resAttr_class.add(new DefaultMutableTreeNode(p.getResourceAttributes().getResClass()));		
+		
+		
+		DefaultMutableTreeNode resAttr_contexts = new DefaultMutableTreeNode("Contexts");
+		
+		for(Iterator i = p.getResourceAttributes().getResContexts().iterator(); i.hasNext(); ){
+			String theContext = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_contextN = new DefaultMutableTreeNode(theContext);
+			resAttr_contexts.add(resAttr_contextN);
+		}
+
+		DefaultMutableTreeNode resAttr_contributors = new DefaultMutableTreeNode("Contributors");
+		
+		for(Iterator i = p.getResourceAttributes().getContributors().iterator(); i.hasNext(); ){
+			String theContributor = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_contribN = new DefaultMutableTreeNode(theContributor);
+			resAttr_contributors.add(resAttr_contribN);
+		}
+		
+		DefaultMutableTreeNode resAttr_coverages = new DefaultMutableTreeNode("Coverages");
+		
+		for(Iterator i = p.getResourceAttributes().getCoverages().iterator(); i.hasNext(); ){
+			String theCoverage = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_coverageN= new DefaultMutableTreeNode(theCoverage);
+			resAttr_coverages.add(resAttr_coverageN);
+		}
+		
+		DefaultMutableTreeNode resAttr_creators = new DefaultMutableTreeNode("Creators");
+		
+		for(Iterator i = p.getResourceAttributes().getCreators().iterator(); i.hasNext(); ){
+			String theCreator = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_creatorN = new DefaultMutableTreeNode(theCreator);
+			resAttr_creators.add(resAttr_creatorN);
+		}
+
+		DefaultMutableTreeNode resAttr_dates = new DefaultMutableTreeNode("Dates");
+		
+		for(Iterator i = p.getResourceAttributes().getDates().iterator(); i.hasNext(); ){
+			String theDate = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_dateN = new DefaultMutableTreeNode(theDate);
+			resAttr_dates.add(resAttr_dateN);
+		}
+	
+		DefaultMutableTreeNode resAttr_description = new DefaultMutableTreeNode("Description");
+		resAttr_description.add(new DefaultMutableTreeNode(p.getResourceAttributes().getDescription()));		
+
+		DefaultMutableTreeNode resAttr_formats = new DefaultMutableTreeNode("Formats");
+		
+		for(Iterator i = p.getResourceAttributes().getFormats().iterator(); i.hasNext(); ){
+			String theFormat = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_formatN = new DefaultMutableTreeNode(theFormat);
+			resAttr_formats.add(resAttr_formatN);
+		}
+		
+		DefaultMutableTreeNode resAttr_identifier = new DefaultMutableTreeNode("Identifier");
+		resAttr_identifier.add(new DefaultMutableTreeNode(p.getResourceAttributes().getIdentifier()));		
+
+		DefaultMutableTreeNode resAttr_languages = new DefaultMutableTreeNode("Languages");
+		
+		for(Iterator i = p.getResourceAttributes().getLanguages().iterator(); i.hasNext(); ){
+			String theLanguage = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_langN = new DefaultMutableTreeNode(theLanguage);
+			resAttr_languages.add(resAttr_langN);
+		}
+		
+		DefaultMutableTreeNode resAttr_locations = new DefaultMutableTreeNode("Resource Locations");
+		
+		for(Iterator i = p.getResourceAttributes().getResLocations().iterator(); i.hasNext(); ){
+			String theLoc = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_locN = new DefaultMutableTreeNode(theLoc);
+			resAttr_locations.add(resAttr_locN);
+		}
+
+		DefaultMutableTreeNode resAttr_publishers = new DefaultMutableTreeNode("Publishers");
+		
+		for(Iterator i = p.getResourceAttributes().getPublishers().iterator(); i.hasNext(); ){
+			String thePublisher = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_pubN = new DefaultMutableTreeNode(thePublisher);
+			resAttr_publishers.add(resAttr_pubN);
+		}
+		
+		DefaultMutableTreeNode resAttr_relations = new DefaultMutableTreeNode("Relations");
+		
+		for(Iterator i = p.getResourceAttributes().getRelations().iterator(); i.hasNext(); ){
+			String theRelation = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_relationN = new DefaultMutableTreeNode(theRelation);
+			resAttr_relations.add(resAttr_relationN);
+		}
+
+		
+		DefaultMutableTreeNode resAttr_rights = new DefaultMutableTreeNode("Rights");
+		
+		for(Iterator i = p.getResourceAttributes().getRights().iterator(); i.hasNext(); ){
+			String theRight = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_rightN = new DefaultMutableTreeNode(theRight);
+			resAttr_rights.add(resAttr_rightN);
+		}
+
+		DefaultMutableTreeNode resAttr_sources = new DefaultMutableTreeNode("Sources");
+		
+		for(Iterator i = p.getResourceAttributes().getSources().iterator(); i.hasNext(); ){
+			String theSource = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_sourceN = new DefaultMutableTreeNode(theSource);
+			resAttr_sources.add(resAttr_sourceN);
+		}
+
+		DefaultMutableTreeNode resAttr_subjects = new DefaultMutableTreeNode("Subjects");
+		
+		for(Iterator i = p.getResourceAttributes().getSubjects().iterator(); i.hasNext(); ){
+			String theSubject = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_subjectN = new DefaultMutableTreeNode(theSubject);
+			resAttr_subjects.add(resAttr_subjectN);
+		}
+
+		DefaultMutableTreeNode resAttr_title = new DefaultMutableTreeNode("Title");
+		resAttr_title.add(new DefaultMutableTreeNode(p.getResourceAttributes().getTitle()));		
+	
+		DefaultMutableTreeNode resAttr_types = new DefaultMutableTreeNode("Types");
+		
+		for(Iterator i = p.getResourceAttributes().getTypes().iterator(); i.hasNext(); ){
+			String theType = (String)i.next();
+			
+			DefaultMutableTreeNode resAttr_typeN = new DefaultMutableTreeNode(theType);
+			resAttr_types.add(resAttr_typeN);
+		}
+	
+
+		resAttrRoot.add(resAttr_aggregation);
+		resAttrRoot.add(resAttr_class);
+		resAttrRoot.add(resAttr_contexts);
+		resAttrRoot.add(resAttr_contributors);
+		resAttrRoot.add(resAttr_coverages);
+		resAttrRoot.add(resAttr_creators);
+		resAttrRoot.add(resAttr_dates);
+		resAttrRoot.add(resAttr_description);
+		resAttrRoot.add(resAttr_formats);
+		resAttrRoot.add(resAttr_identifier);
+		resAttrRoot.add(resAttr_languages);
+		resAttrRoot.add(resAttr_locations);
+		resAttrRoot.add(resAttr_publishers);
+		resAttrRoot.add(resAttr_relations);
+		resAttrRoot.add(resAttr_rights);
+		resAttrRoot.add(resAttr_sources);
+		resAttrRoot.add(resAttr_subjects);
+		resAttrRoot.add(resAttr_title);
+		resAttrRoot.add(resAttr_types);
+
+        for(Iterator i = p.getProfileElements().keySet().iterator(); i.hasNext(); ){
+        	String peKey = (String)i.next();
+        	
+        	ProfileElement theProfileElement = (ProfileElement)p.getProfileElements().get(peKey);
+        	DefaultMutableTreeNode thePENode = new DefaultMutableTreeNode(theProfileElement.getName());
+        	DefaultMutableTreeNode theCommentsRoot = new DefaultMutableTreeNode("Comments");
+        	DefaultMutableTreeNode theComments = new DefaultMutableTreeNode(theProfileElement.getComments());
+        	
+        	theCommentsRoot.add(theComments);
+        	
+        	DefaultMutableTreeNode theDesc = new DefaultMutableTreeNode(theProfileElement.getDescription());
+        	DefaultMutableTreeNode theDescRoot = new DefaultMutableTreeNode("Description");
+        	
+        	theDescRoot.add(theDesc);
+        	
+        	
+        	
+        	DefaultMutableTreeNode theID = new DefaultMutableTreeNode(theProfileElement.getID());
+        	DefaultMutableTreeNode theIDRoot = new DefaultMutableTreeNode("ID");
+        	
+        	theIDRoot.add(theID);
+        	
+        	DefaultMutableTreeNode theMO = new DefaultMutableTreeNode(new Integer(theProfileElement.getMaxOccurrence()).toString());
+        	DefaultMutableTreeNode theMORoot = new DefaultMutableTreeNode("Max Occurence");
+        	theMORoot.add(theMO);
+        	
+        	DefaultMutableTreeNode theSynonyms = new DefaultMutableTreeNode("Synonyms");
+        	
+        	for(Iterator i2 = theProfileElement.getSynonyms().iterator(); i2.hasNext(); ){
+        		String theSynonym = (String)i2.next();
+        		DefaultMutableTreeNode sNode = new DefaultMutableTreeNode(theSynonym);
+        		theSynonyms.add(sNode);
+        	}
+
+        	DefaultMutableTreeNode theType = new DefaultMutableTreeNode(theProfileElement.getType());
+        	DefaultMutableTreeNode theTypeRoot = new DefaultMutableTreeNode("Type");
+        	theTypeRoot.add(theType);
+        	
+        	
+        	DefaultMutableTreeNode theUnit = new DefaultMutableTreeNode(theProfileElement.getUnit());
+        	DefaultMutableTreeNode theUnitRoot = new DefaultMutableTreeNode("Unit");
+        	theUnitRoot.add(theUnit);
+        	
+        	thePENode.add(theCommentsRoot);
+        	thePENode.add(theDescRoot);
+        	thePENode.add(theIDRoot);
+        	thePENode.add(theMORoot);
+        	thePENode.add(theSynonyms);
+        	thePENode.add(theTypeRoot);
+        	thePENode.add(theUnitRoot);
+        	
+        	profElemRoot.add(thePENode);
+        }
+		
+		root.add(profAttrRoot);
+		root.add(resAttrRoot);
+		root.add(profElemRoot);
+		
+		return new DefaultTreeModel(root);		
+		
+		
+	}
+
+	/** Auto-generated event handler method */
+	protected void openFileMenuItemActionPerformed(ActionEvent evt){
+		//TODO add your handler code here
+		
+	    String filename = File.separator+"tmp";
+	    JFileChooser fc = new JFileChooser(new File(filename));
+	    
+	    // Show open dialog; this method does not return until the dialog is closed
+	    int decision = fc.showOpenDialog(this);
+	    
+	    if(decision != JFileChooser.APPROVE_OPTION){
+	    	return; 
+	    }
+	    
+	    File selFile = fc.getSelectedFile();
+	    
+	    //create a buffered reader, read it in, create a new profile from that file
+	    FileReader fr = null;
+	    
+	    try{
+	    	fr = new FileReader(selFile);
+	    }
+	    catch(FileNotFoundException fne){
+	    	fne.printStackTrace();
+	    	System.out.println(fne.getMessage());
+	    }
+	    
+	    char [] buf = new char[256];
+	    StringBuffer sb = new StringBuffer();
+	    
+	    int numRead = -1;
+	    
+	    try{
+		    while((numRead = fr.read(buf,0,256)) != -1){
+		      sb.append(buf,0,numRead);
+		      buf = new char[256];
+		    }
+	    }
+	    catch(IOException ioe){
+	    	ioe.printStackTrace();
+	    	System.out.println(ioe.getMessage());	    	
+	    }
+	    
+	    System.out.println("Read in "+sb.toString());
+	    try{
+	    	createdProfile = new Profile(sb.toString());        
+	    	jEditorPane1.setText(new ProfilePrinter(createdProfile,"http://oodt.jpl.nasa.gov/dtd/prof.dtd").toXMLString());
+			
+			getJTree1().setModel(generateModelFromProfile(createdProfile));
+			//getJTree1().addMouseListener(new LeafListener(getJTree1()));
+	    }catch(SAXException se){
+	    	se.printStackTrace();
+	    	System.out.println(se.getMessage());
+	    }
+
+	    
+	}
+
+	/** Auto-generated event handler method */
+	protected void jButton1ActionPerformed(ActionEvent evt){
+		//TODO add your handler code here
+		
+		//basically we want to set the createdProfile to be generated from the current tree model
+		//then we want to set the jeditor pane to have the createdProfileText
+		
+		createdProfile = generateProfileFromModel(getJTree1().getModel());
+		//jEditorPane1.setText(createdProfile.toString());
+		jEditorPane1.setText(new ProfilePrinter(createdProfile,"http://oodt.jpl.nasa.gov/dtd/prof.dtd").toXMLString());
+		
+	}
+
+	/** Auto-generated event handler method */
+	protected void saveMenuItemActionPerformed(ActionEvent evt){
+		//TODO add your handler code here
+	    
+		
+	    JFileChooser fc = new JFileChooser();
+	    int decision = fc.showSaveDialog(this);
+	    
+	    if(decision != JFileChooser.APPROVE_OPTION){
+	    	return; 
+	    }
+	    
+	    //first thing -- set the created profile to the current tree
+	    createdProfile = generateProfileFromModel(getJTree1().getModel());
+	    
+		File file = fc.getSelectedFile();
+        FileOutputStream fos = null;
+        
+        try{
+        	System.out.println("Trying to write to "+file.getAbsolutePath());
+        	fos = new FileOutputStream (file.getAbsolutePath());
+        	fos.write(new ProfilePrinter(createdProfile,"http://oodt.jpl.nasa.gov/dtd/prof.dtd").toXMLString().getBytes());
+        }
+        catch(FileNotFoundException fne){
+        	fne.printStackTrace();
+        	System.out.println(fne.getMessage());
+        }
+        catch(IOException ioe){
+        	ioe.printStackTrace();
+        	System.out.println(ioe.getMessage());
+        }
+        finally{
+        	try{
+        		fos.close();
+        	}catch(Exception ignore){
+        		//ignore
+        	}
+        }
+
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/profileTree.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/profileTree.java
new file mode 100755
index 0000000..3c9cf92
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/profileTree.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.profile.gui;
+
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+
+
+public class profileTree extends JTree{
+	
+	public profileTree(){
+		setEditable(true);
+		DefaultMutableTreeNode dtmRoot = new DefaultMutableTreeNode("Profile");
+		DefaultMutableTreeNode resAttrRoot = new DefaultMutableTreeNode("Resource Attributes");
+		DefaultMutableTreeNode profAttrRoot = new DefaultMutableTreeNode("Profile Attributes");
+		DefaultMutableTreeNode profElemRoot = new DefaultMutableTreeNode("Profile Elements");
+		dtmRoot.add(resAttrRoot);
+		dtmRoot.add(profAttrRoot);
+		dtmRoot.add(profElemRoot);
+		DefaultTreeModel theModel = new DefaultTreeModel(dtmRoot);
+		setModel(theModel);
+	}
+	
+	
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/pstructs/ProfileAttributesPrinter.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/pstructs/ProfileAttributesPrinter.java
new file mode 100755
index 0000000..01d57af
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/pstructs/ProfileAttributesPrinter.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+/*
+ * Created on Jun 25, 2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.apache.oodt.profile.gui.pstructs;
+
+
+import org.apache.oodt.profile.ProfileAttributes;
+import java.util.Iterator;
+
+/**
+ * @author mattmann
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+public class ProfileAttributesPrinter {
+	
+	private ProfileAttributes myProfAttributes=null;
+	/**
+	 * 
+	 */
+	public ProfileAttributesPrinter(ProfileAttributes pa) {
+		super();
+		// TODO Auto-generated constructor stub
+		myProfAttributes = pa;
+	}
+	
+	public String toXMLString(){
+		String rStr="";
+		
+		rStr+="<profAttributes>\n";
+		rStr+="\t<profId>"+myProfAttributes.getID()+"</profId>\n";
+		rStr+="\t<profType>"+myProfAttributes.getType()+"</profType>\n";
+		rStr+="\t<profVersion>"+myProfAttributes.getVersion()+"</profVersion>\n";
+		rStr+="\t<profStatusId>"+myProfAttributes.getStatusID()+"</profStatusId>\n";
+		rStr+="\t<profSecurityType>"+myProfAttributes.getSecurityType()+"</profSecurityType>\n";
+		rStr+="\t<profParentId>"+myProfAttributes.getParent()+"</profParentId>\n";
+		
+		for(Iterator i = myProfAttributes.getChildren().iterator(); i.hasNext(); ){
+			String theChild = (String)i.next();
+			rStr+="\t<profChildId>"+theChild+"</profChildId>\n";
+		}
+		
+		rStr+="\t<profRegAuthority>"+myProfAttributes.getRegAuthority()+"</profRegAuthority>\n";
+		
+		for(Iterator i = myProfAttributes.getRevisionNotes().iterator(); i.hasNext(); ){
+			String theNote = (String)i.next();
+			rStr+="\t<profRevisionNote>"+theNote+"</profRevisionNote>\n";
+		}
+		
+		rStr+="</profAttributes>\n\n";
+		
+
+		return rStr;
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/pstructs/ProfileElementPrinter.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/pstructs/ProfileElementPrinter.java
new file mode 100755
index 0000000..55e9896
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/pstructs/ProfileElementPrinter.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+/*
+ * Created on Jun 25, 2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.apache.oodt.profile.gui.pstructs;
+
+import org.apache.oodt.profile.ProfileElement;
+import java.util.Iterator;
+
+/**
+ * @author mattmann
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+public class ProfileElementPrinter {
+	private ProfileElement myProfileElement=null;
+	
+	/**
+	 * 
+	 */
+	public ProfileElementPrinter(ProfileElement pe) {
+		super();
+		// TODO Auto-generated constructor stub
+		myProfileElement = pe;
+	}
+	
+	public String toXMLString(){
+		String rStr="";
+		
+		  rStr+="<profElement>\n";
+		  rStr+="\t<elemName>"+myProfileElement.getName()+"</elemName>\n";
+		  rStr+="\t<elemMaxOccurrence>"+myProfileElement.getMaxOccurrence()+"</elemMaxOccurrence>\n";
+		  rStr+="\t<elemMaxValue>"+myProfileElement.getMaxValue()+"</elemMaxValue>\n";
+		  rStr+="\t<elemMinValue>"+myProfileElement.getMinValue()+"</elemMinValue>\n";
+		  
+		  for(Iterator i = myProfileElement.getValues().iterator(); i.hasNext(); ){
+		  	String theValue = (String)i.next();
+		  	rStr+="<elemValue>"+theValue+"</elemValue>\n";
+		  }
+		  rStr+="\t<elemComment>"+myProfileElement.getComments()+"</elemComment>\n";
+		  rStr+="</profElement>\n";
+		return rStr;
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/pstructs/ProfilePrinter.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/pstructs/ProfilePrinter.java
new file mode 100755
index 0000000..22f52a9
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/pstructs/ProfilePrinter.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+/*
+ * Created on Jun 25, 2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.apache.oodt.profile.gui.pstructs;
+
+
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileElement;
+import java.util.Iterator;
+
+
+/**
+ * @author mattmann
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+public class ProfilePrinter {
+	
+	private Profile myProfile=null;
+	private String dtdUrl=null;
+	
+	/**
+	 * Pretty printing class for a profile, using lightweight, string
+	 * concatenation classes and methods
+	 */
+	public ProfilePrinter(Profile p,String profDTDURL) {
+		super();
+		// TODO Auto-generated constructor stub
+		myProfile = p;
+		dtdUrl = profDTDURL;
+	}
+	
+	public String toXMLString(){
+		String rStr = "<?xml version=\"1.0\" ?>\n";
+		rStr+="<!DOCTYPE profile SYSTEM \""+dtdUrl+"\">\n\n";
+		rStr+="<profile>\n";
+
+		
+		ProfileAttributesPrinter pap = new ProfileAttributesPrinter(myProfile.getProfileAttributes());
+		rStr+=pap.toXMLString();
+		
+		
+		ResourceAttributesPrinter rap = new ResourceAttributesPrinter(myProfile.getResourceAttributes());
+		rStr+=rap.toXMLString();
+
+		
+		for(Iterator i = myProfile.getProfileElements().keySet().iterator(); i.hasNext(); ){
+			String profElemName = (String)i.next();
+			
+			ProfileElement pe = (ProfileElement)myProfile.getProfileElements().get(profElemName);
+			ProfileElementPrinter pPrinter = new ProfileElementPrinter(pe);
+			rStr+=pPrinter.toXMLString();
+		}
+		
+		rStr+="</profile>\n";
+		
+		return rStr;
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/pstructs/ResourceAttributesPrinter.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/pstructs/ResourceAttributesPrinter.java
new file mode 100755
index 0000000..0bc1a90
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/gui/pstructs/ResourceAttributesPrinter.java
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+/*
+ * Created on Jun 18, 2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.apache.oodt.profile.gui.pstructs;
+
+import org.apache.oodt.profile.ResourceAttributes;
+import java.util.Iterator;
+
+/**
+ * @author mattmann
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+public class ResourceAttributesPrinter {
+	
+	private ResourceAttributes resAttr=null;
+	
+	/**
+	 * <p>Constructs a new Resource Attributes printer from a {@link ResourceAttributes}
+	 * object.</p>
+	 */
+	public ResourceAttributesPrinter(ResourceAttributes r) {
+		super();
+		// TODO Auto-generated constructor stub
+		resAttr = r;
+		
+	}
+	
+	public void setResourceAttributes(ResourceAttributes r){resAttr=r;}
+	public ResourceAttributes getResourceAttributes(){return resAttr;}
+	
+	public String toXMLString(){
+		String rStr="";
+		
+		   rStr+="<resAttributes>\n";
+		   
+		   rStr+="\t<Identifier>"+resAttr.getIdentifier()+"</Identifier>\n";
+		   rStr+="\t<Title>"+resAttr.getTitle()+"</Title>\n";
+		   rStr+="\t<resClass>"+resAttr.getResClass()+"</resClass>\n";
+		   rStr+="\t<resAggregation>"+resAttr.getResAggregation()+"</resAggregation>\n";
+
+		   for(Iterator i = resAttr.getRights().iterator(); i.hasNext(); ){
+		   	String theRight = (String)i.next();
+		   	rStr+="\t<Right>"+theRight+"</Right>\n";
+		   }
+		   
+		   for(Iterator i = resAttr.getSources().iterator(); i.hasNext(); ){
+		   	String theSource = (String)i.next();
+		   	rStr+="\t<Source>"+theSource+"</Source>\n";
+		   }
+		   
+		   for(Iterator i = resAttr.getSubjects().iterator(); i.hasNext(); ){
+		   	String theSubject = (String)i.next();
+		   	rStr+="\t<Subject>"+theSubject+"</Subject>\n";
+		   }
+		   
+		   for(Iterator i = resAttr.getFormats().iterator(); i.hasNext(); ){
+		   	String theFormat = (String)i.next();
+		   	rStr+="\t<Format>"+theFormat+"</Format>\n";
+		   }
+		   
+		   for(Iterator i = resAttr.getCreators().iterator(); i.hasNext(); ){
+		   	String theCreator = (String)i.next();
+		   	rStr+="\t<Creator>"+theCreator+"</Creator>\n";
+		   }
+		   
+		   for(Iterator i = resAttr.getPublishers().iterator(); i.hasNext(); ){
+		   	String thePublisher = (String)i.next();
+		   	rStr+="\t<Publisher>"+thePublisher+"</Publisher>\n";
+		   }
+		   
+		   for(Iterator i = resAttr.getTypes().iterator(); i.hasNext(); ){
+		   	String theType = (String)i.next();
+		   	rStr+="\t<Type>"+theType+"</Type>\n";
+		   }
+		   
+		   for(Iterator i = resAttr.getResContexts().iterator(); i.hasNext(); ){
+		   	String theContext = (String)i.next();
+		   	rStr+="\t<resContext>"+theContext+"</resContext>\n";
+		   }
+		   
+		   for(Iterator i = resAttr.getResLocations().iterator(); i.hasNext(); ){
+		   	String theLocation = (String)i.next();
+		   	rStr+="\t<resLocation>"+theLocation+"</resLocation>\n";
+		   }
+		   
+		   for(Iterator i = resAttr.getContributors().iterator(); i.hasNext(); ){
+		   	String theContributor = (String)i.next();
+		   	rStr+="\t<Contributor>"+theContributor+"</Contributor>\n";
+		   }
+		   
+		   for(Iterator i = resAttr.getCoverages().iterator(); i.hasNext(); ){
+		   	String theCoverage = (String)i.next();
+		   	rStr+="\t<Coverage>"+theCoverage+"</Coverage>\n";
+		   }
+		   
+		   for(Iterator i = resAttr.getLanguages().iterator(); i.hasNext(); ){
+		   	String theLang = (String)i.next();
+		   	rStr+="\t<Language>"+theLang+"</Language>\n";
+		   }
+		   
+		   for(Iterator i = resAttr.getRelations().iterator(); i.hasNext(); ){
+		   	String theRelation = (String)i.next();
+		   	rStr+="\t<Relation>"+theRelation+"</Relation>\n";
+		   }
+		   
+		   rStr+="</resAttributes>\n";
+		   
+		return rStr;
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/DatabaseProfileManager.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/DatabaseProfileManager.java
new file mode 100755
index 0000000..73eb294
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/DatabaseProfileManager.java
@@ -0,0 +1,283 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.profile.handlers;
+
+import java.io.*;
+import java.net.MalformedURLException;
+import java.sql.*;
+import java.util.*;
+import org.apache.oodt.commons.Configuration;
+import org.apache.oodt.commons.util.DOMParser;
+import org.apache.oodt.commons.util.*;
+import org.apache.oodt.xmlquery.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+import org.apache.oodt.profile.*;
+
+/**********************************************************************************
+**
+** DatabaseProfileManager.java
+**
+** @author Dan Crichton
+** 
+** date: 11/10/2000
+**
+** description: Map a profile into/out of a relational database
+**
+***********************************************************************************/
+
+public abstract class DatabaseProfileManager implements ProfileManager
+{
+	/** Add an element to the given node in an XML document.
+	 *
+	 * @param node To what node to add a new element.
+	 * @param name What the new element should be named.
+	 * @param value What string value the element should contain; if null, then don't add the element.
+	 * @throws DOMException If an error occurs.
+	 */
+	private static void add(Node node, String name, String value) throws DOMException {
+		if (value == null) return;
+		XML.add(node, name, value.trim());
+	}
+
+	/** Dump profiles in the database.
+	 *
+	 * This returns a list containing the contents of the profiles.
+	 *
+	 * @return The profiles in the database, as a list.
+	 * @throws ProfileException If an error occurs.
+	 */
+	public abstract List getProfiles(Connection conn) throws ProfileException;
+
+    	Connection conn;
+   	Properties props;
+
+
+    	/**********************************************************************
+    	 **
+    	 ** DatabaseProfileManager
+     	 **
+    	 **
+    	***********************************************************************/	
+
+    	public DatabaseProfileManager(Properties props) throws SQLException, Exception {
+		this(props, openConnection(props));
+    	}
+
+    	public DatabaseProfileManager (Properties props, Connection conn) 
+    	{
+		this.conn = conn;
+		this.props = props;
+    	}
+
+
+    	/**********************************************************************
+    	**
+    	** findProfiles
+    	**
+    	**  Returns a list of matching profiles
+    	**
+    	***********************************************************************/	
+    	public List findProfiles(XMLQuery query) throws DOMException, ProfileException 
+    	{
+		try
+		{
+			return(findProfiles(conn, query));
+		}
+		catch (Exception e)
+		{
+			throw new ProfileException (e.getMessage());
+		}
+    	}
+
+    	public abstract List findProfiles(Connection conn, XMLQuery query) throws DOMException, ProfileException;
+
+
+	public void add(Profile profile) throws ProfileException {
+
+		try
+		{
+			add(conn, profile);
+			conn.commit();
+		}
+		catch (SQLException e)
+		{
+			throw new ProfileSQLException (e);
+		}
+	}
+	public abstract void add(Connection conn, Profile profile) throws ProfileException ;
+	
+
+	public void addAll(Collection collection) throws ProfileException
+	{
+		try
+                {
+                        addAll(conn, collection);
+                        conn.commit();
+                }
+		catch (Exception e)
+                {	
+			try {
+				conn.rollback();
+			}catch (SQLException se) {
+				throw new ProfileSQLException(se);
+			}			
+                        throw new ProfileException(e.getMessage());
+                }
+	}
+
+	public abstract void addAll(Connection conn,Collection collection) throws ProfileException;
+
+	public abstract void clear(Connection conn) throws ProfileException ;
+
+	public void clear() throws ProfileException 
+	{
+		// Create database connection
+
+		try
+		{
+			clear(conn);
+			conn.commit();
+		}
+		catch (SQLException e)
+		{
+			throw new ProfileSQLException (e);
+		}
+	}
+	public boolean contains(Profile profile) throws ProfileException {
+		throw new UnsupportedOperationException("Not yet implemented");
+	}
+	public boolean containsAll(Collection collection) throws ProfileException {
+		throw new UnsupportedOperationException("Not yet implemented");
+	}
+
+	public abstract Profile get(Connection conn, String profID) throws ProfileException;
+
+	public Profile get(String profId) throws ProfileException {
+		// Create database connection
+
+		try
+		{ 
+			return(get(conn, profId));
+		}
+		catch (ProfileException e)
+		{
+			throw e;
+		}
+	}
+
+	public Collection getAll() throws ProfileException {
+		throw new UnsupportedOperationException("Not yet implemented");
+	}
+	public boolean isEmpty() throws ProfileException {
+		throw new UnsupportedOperationException("Not yet implemented");
+	}
+	public Iterator iterator() throws ProfileException {
+		throw new UnsupportedOperationException("Not yet implemented");
+	}
+
+	public abstract boolean remove(Connection conn, String profId, String version)
+		 throws ProfileException;
+
+	public abstract boolean remove(Connection conn, String profId) throws ProfileException;
+
+
+	public boolean remove(String profId, String version) throws ProfileException 
+	{
+		// Create database connection
+
+		try
+		{
+			boolean status = remove(conn, profId, version);
+			conn.commit();
+			return(status);
+		}
+		catch (SQLException e)
+		{
+			throw new ProfileSQLException (e);
+		}
+	}
+
+	public boolean remove(String profId) throws ProfileException {
+		// Create database connection
+
+		try
+		{
+			boolean status = remove(conn, profId);
+			conn.commit();
+			return(status);
+		}
+		catch (SQLException e)
+		{
+			throw new ProfileSQLException (e);
+		}
+	}
+
+	public int size() throws ProfileException {
+		try
+		{
+			return(size(conn));
+		}
+		catch (ProfileException e)
+		{
+			throw e;
+		}
+
+	}
+
+	public abstract int size(Connection conn) throws ProfileException ;
+
+	public void replace(Profile profile) throws ProfileException {
+		// Create database connection
+
+		try
+		{
+			replace(conn, profile);
+			conn.commit();
+		}
+		catch (Exception e)
+		{
+			throw new ProfileException(e.getMessage());
+		}
+	}
+	public abstract void replace(Connection conn, Profile profile) throws ProfileException ;
+
+	protected  static Connection openConnection(Properties props) throws SQLException, ProfileException
+	{
+		// load JDBC driver
+		String driver = props.getProperty("org.apache.oodt.util.JDBC_DB.driver","oracle.jdbc.driver.OracleDriver");
+		try {
+                        System.err.println("Attempting to load class " + driver);
+                        Class.forName(driver);
+                        System.err.println("Loaded " + driver);
+                } catch (ClassNotFoundException e) {
+                        throw new ProfileException("Can't load JDBC driver \"" + driver + "\": " +e.getMessage());
+                }       
+
+		// get connection
+		String url = props.getProperty("org.apache.oodt.util.JDBC_DB.url", "jdbc:oracle:@");
+		String database = props.getProperty("org.apache.oodt.util.JDBC_DB.database");
+		if(database != null) url += database;
+
+                Connection conn = DriverManager.getConnection(url,
+                        		props.getProperty("org.apache.oodt.util.JDBC_DB.user"),
+                        		props.getProperty("org.apache.oodt.util.JDBC_DB.password"));
+
+		conn.setAutoCommit(false);
+		return conn;
+       }
+}
+
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/ProfileHandler.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/ProfileHandler.java
new file mode 100644
index 0000000..f66ae3e
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/ProfileHandler.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileException;
+import org.apache.oodt.xmlquery.XMLQuery;
+import org.w3c.dom.Document;
+
+/**
+ * Interface of a profile handler.
+ *
+ * A profile handler can search for profiles or retrieve a single profile by its ID.
+ *
+ * @author Kelly
+ * @version $Revision: 1.2 $
+ */
+public interface ProfileHandler {
+	/**
+	 * Find a set of profiles that match the given <var>query</var>.
+	 *
+	 * This method searchs the profiles provided by this profile service provider
+	 * based on criteria in the <var>query</var>.  It returns an XML document
+	 * describing the profiles and profile elements that match.
+	 *
+	 * @param query Search criteria.
+	 * @return List of matching {@link Profile} objects.
+	 * @throws ProfileException If any other error occurs.
+	 */
+	List findProfiles(XMLQuery query) throws ProfileException;
+
+	/**
+	 * Get a profile.
+	 *
+	 * @param profID ID of the profile to get.
+	 * @return The profile with the given <var>profID</var>, or null if it's not found.
+	 * @throws ProfileException If any error occurs.
+	 */
+	Profile get(String profID) throws ProfileException;
+	
+	/**
+	 * Get my ID.
+	 *
+	 * @return A string that identifies this profile handler in some way.
+	 */
+	String getID();
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/ProfileManager.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/ProfileManager.java
new file mode 100755
index 0000000..f7d17c8
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/ProfileManager.java
@@ -0,0 +1,150 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements.  See the NOTICE.txt 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.
+
+package org.apache.oodt.profile.handlers;
+
+import java.util.Collection;
+import java.util.Iterator;
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileException;
+import org.apache.oodt.xmlquery.XMLQuery;
+import org.w3c.dom.Document;
+
+/**
+ * Interface of a profile manager.
+ *
+ * A profile manager can manage profiles by adding, removing, and manipulating them---in
+ * addition to searching them.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+public interface ProfileManager extends ProfileHandler {
+	/**
+	 * Add a profile into the set of profiles managed by this profile server.
+	 *
+	 * @param profile The profile to add or replace.
+	 * @throws ProfileException If any error occurs.
+	 */
+	void add(Profile profile) throws ProfileException;
+
+	/**
+	 * Add all of the profiles in the given collection to the set managed by this
+	 * server.
+	 *
+	 * Any profiles that already exist (as identified by their profile IDs) are replaced.
+	 *
+	 * @param collection Collection of {@link Profile}s to add.
+	 * @throws ProfileException If any error occurs.
+	 */
+	void addAll(Collection collection) throws ProfileException;
+
+	/**
+	 * Clear all profiles.
+	 *
+	 * This irrevocably removes all profiles from the server, leaving it with none.
+	 *
+	 * @throws ProfileException If any error occurs.
+	 */
+	void clear() throws ProfileException;
+
+	/**
+	 * Tell if the given profile is managed by this server.
+	 *
+	 * @param profile The profile to check.
+	 * @return True if <var>profile</var> is present in the server, false otherwise.
+	 * @throws ProfileException If any error occurs.
+	 */
+	boolean contains(Profile profile) throws ProfileException;
+
+	/**
+	 * Tell if the given collection of profiles are managed by this server.
+	 *
+	 * @param collection The collection of {@link Profile}s to check.
+	 * @return True if every {@link Profile} in <var>collection</var> are present in
+	 * the server, false otherwise.
+	 * @throws ProfileException If any error occurs.
+	 */
+	boolean containsAll(Collection collection) throws ProfileException;
+
+	/**
+	 * Get all profiles.
+	 *
+	 * @return  A collection of profiles
+	 * @throws ProfileException If any error occurs.
+	 */
+	Collection getAll() throws ProfileException;
+
+	/**
+	 * Tell if the set of profiles managed by this server is empty.
+	 *
+	 * @return True if there are no profiles in this server.
+	 * @throws ProfileException If any error occurs.
+	 */
+	boolean isEmpty() throws ProfileException;
+
+	/**
+	 * Iterate over the available profiles.
+	 *
+	 * Each call to <code>next</code> yields a copy of the next {@link Profile} object
+	 * managed by this server.  Updates to profile objects are not backed by the
+	 * server; make your updates and then call {@link #add}.
+	 *
+	 * @return An iterator over {@link Profile}s.
+	 * @throws ProfileException If any error occurs.
+	 */
+	Iterator iterator() throws ProfileException;
+
+	/**
+	 * Remove the profile with the given ID.
+	 *
+	 * This removes forever the given profile from the set of profiles managed by this
+	 * server.
+	 *
+	 * @param profID What profile to remove.
+	 * @param version What version of the the profile identified by <var>profID</var> to remove.
+	 * @return True if thie profile was actually present and removed; false if it wasn't present.
+	 * @throws ProfileException If any error occurs.
+	 */
+	boolean remove(String profID, String version) throws ProfileException;
+
+	/**
+	 * Remove the profile with the given ID.
+	 *
+	 * This removes forever the given profile from the set of profiles managed by this
+	 * server.
+	 *
+	 * @param profID ID of profile to remove.
+	 * @return True if thie profile was actually present and removed; false if it wasn't present.
+	 * @throws ProfileException If any error occurs.
+	 */
+	boolean remove(String profID) throws ProfileException;
+
+	/**
+	 * Get the size of the set of profiles managed by this server.
+	 *
+	 * @return The number of available profiles.
+	 * @throws ProfileException If any error occurs.
+	 */
+	int size() throws ProfileException;
+
+	/**
+	 * Replace a profile into the set of profiles managed by this profile server.
+	 *
+	 * @param profile The profile to add or replace.
+	 * @throws ProfileException If any error occurs.
+	 */
+	void replace(Profile profile) throws ProfileException;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/cas/CASProfileHandler.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/cas/CASProfileHandler.java
new file mode 100644
index 0000000..1a3c4d5
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/cas/CASProfileHandler.java
@@ -0,0 +1,300 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.cas;
+
+//CAS imports
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.profile.handlers.cas.util.ProfileUtils;
+
+//JDK imports
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileException;
+import org.apache.oodt.profile.handlers.ProfileHandler;
+import org.apache.oodt.xmlquery.QueryElement;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An OODT {@link ProfileHandler} that queries a backend OODT File Management
+ * component, and converts {@link Product}s and their {@link Metadata} into
+ * OODT {@link Profile}s.
+ * </p>
+ */
+public class CASProfileHandler implements ProfileHandler {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(CASProfileHandler.class
+            .getName());
+
+    /* our filemgr client */
+    private XmlRpcFileManagerClient fmClient = null;
+
+    /* the base URL to the data delivery servlet for products */
+    /* AKA our "web-ified" product server */
+    private String dataDelivBaseUrlStr = null;
+
+    /* product type filter: a list of product types to query across */
+    private List productTypeFilter = null;
+
+    public CASProfileHandler() throws InstantiationException {
+        // need to read in the system property
+        // telling us which filemgr to communicate with
+
+        String filemgrUrlStr = System.getProperty(
+                "org.apache.oodt.cas.profile.fmUrl", "http://localhost:9000");
+
+        try {
+            fmClient = new XmlRpcFileManagerClient(new URL(filemgrUrlStr));
+        } catch (Exception e) {
+            throw new InstantiationException(
+                    "Error communicating with the filemgr: [" + filemgrUrlStr
+                            + "]: message: " + e.getMessage());
+        }
+
+        // read in data deliv base url
+        dataDelivBaseUrlStr = System.getProperty(
+                "org.apache.oodt.cas.profile.dataDelivBaseUrl",
+                "http://localhost:8080/filemgr/data");
+
+        productTypeFilter = buildFilter(System
+                .getProperty("org.apache.oodt.cas.profile.product.types"));
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.profile.handlers.ProfileHandler#findProfiles(org.apache.oodt.xmlquery.XMLQuery)
+     */
+    public List findProfiles(XMLQuery query) throws ProfileException {
+        List profs = new Vector();
+
+        if (productTypeFilter != null && productTypeFilter.size() > 0) {
+            for (Iterator i = productTypeFilter.iterator(); i.hasNext();) {
+                ProductType type = (ProductType) i.next();
+                Query cQuery = convertQuery(query);
+
+                profs.addAll(queryAndBuildProfiles(type, cQuery));
+            }
+        }
+
+        return profs;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.profile.handlers.ProfileHandler#get(java.lang.String)
+     */
+    public Profile get(String arg0) throws ProfileException {
+        throw new ProfileException("Method not implemented yet");
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.profile.handlers.ProfileHandler#getID()
+     */
+    public String getID() {
+        return "CAS Filemgr Profile Handler";
+    }
+
+    private List safeGetProductTypes() {
+        List types = null;
+
+        try {
+            types = fmClient.getProductTypes();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return types;
+    }
+
+    private List safeGetProducts(ProductType type) {
+        List products = null;
+
+        try {
+            products = fmClient.getProductsByProductType(type);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return products;
+    }
+
+    private ProductType safeGetProductTypeByName(String name) {
+        ProductType type = null;
+
+        try {
+            type = fmClient.getProductTypeByName(name);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return type;
+    }
+
+    private Metadata safeGetMetadata(Product p) {
+        Metadata met = null;
+
+        try {
+            met = fmClient.getMetadata(p);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return met;
+    }
+
+    private List safeGetProductReferences(Product p) {
+        List references = null;
+
+        try {
+            references = fmClient.getProductReferences(p);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return references;
+    }
+
+    private Element safeGetElementByName(String name) {
+        Element elem = null;
+
+        try {
+            elem = fmClient.getElementByName(name);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return elem;
+    }
+
+    private List buildFilter(String productTypeNames) {
+        List typeFilter = new Vector();
+        if (productTypeNames == null) {
+            typeFilter = safeGetProductTypes(); // just grab them all
+        } else {
+            // split the string on ","
+            String[] typeNames = productTypeNames.split(",");
+
+            if (typeNames != null) {
+                for (int i = 0; i < typeNames.length; i++) {
+                    ProductType type = safeGetProductTypeByName(typeNames[i]);
+                    typeFilter.add(type);
+                }
+            } else {
+                LOG.log(Level.WARNING,
+                        "Unable to parse comma delimited type string: ["
+                                + productTypeNames + "]: using all types");
+                typeFilter = safeGetProductTypes();
+            }
+        }
+
+        return typeFilter;
+    }
+
+    private Query convertQuery(XMLQuery xmlQuery) {
+        // here's the dumbed down algorithm
+        // iterate over the whereSet
+        // when you find a elemName, grab the next query element
+        // ensure it's a literal, if so, there's your term query
+
+        // that's all we'll support for now
+        Query query = new Query();
+
+        if (xmlQuery.getWhereElementSet() != null
+                && xmlQuery.getWhereElementSet().size() > 0) {
+            for (Iterator i = xmlQuery.getWhereElementSet().iterator(); i
+                    .hasNext();) {
+                QueryElement elem = (QueryElement) i.next();
+                if (elem.getRole().equals("elemName")) {
+                    String elemName = elem.getValue();
+
+                    // to get the elem value, we need to grab the next elem
+                    // ensure it's a literal, and then grab it
+                    QueryElement litElem = (QueryElement) i.next();
+                    if (!litElem.getRole().equals("LITERAL")) {
+                        LOG.log(Level.WARNING,
+                                "next element not literal: element: ["
+                                        + litElem + "]: malformed xml query!");
+                        break;
+                    }
+                    String elemValue = litElem.getValue();
+                    TermQueryCriteria crit = new TermQueryCriteria();
+                    crit.setElementName(elemName);
+                    crit.setValue(elemValue);
+                    query.addCriterion(crit);
+                }
+            }
+        }
+
+        return query;
+    }
+
+    private List queryAndBuildProfiles(ProductType type, Query query) {
+        List profiles = new Vector();
+
+        List products = null;
+
+        try {
+            products = fmClient.query(query, type);
+
+            if (products != null && products.size() > 0) {
+                for (Iterator i = products.iterator(); i.hasNext();) {
+                    Product p = (Product) i.next();
+                    p.setProductReferences(safeGetProductReferences(p));
+                    Metadata met = safeGetMetadata(p);
+                    try {
+                        profiles.add(ProfileUtils.buildProfile(p, met,
+                                dataDelivBaseUrlStr));
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+
+                }
+            }
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE,
+                    "Exception querying the file manager for products: Message: "
+                            + e.getMessage());
+        }
+
+        return profiles;
+
+    }
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/cas/util/ProfileUtils.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/cas/util/ProfileUtils.java
new file mode 100644
index 0000000..9338c73
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/cas/util/ProfileUtils.java
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.cas.util;
+
+//CAS imports
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//OODT imports
+import org.apache.oodt.profile.EnumeratedProfileElement;
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileAttributes;
+import org.apache.oodt.profile.ResourceAttributes;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A set of utility methods to aid in CAS Filemgr vocabulary conversion to OODT
+ * {@link Profile} vocabulary.
+ * </p>
+ */
+public final class ProfileUtils {
+
+  private static final String PROF_ID_PRE = "urn:oodt:profile:";
+
+  private static final String PROF_TYPE = "profile";
+
+  private ProfileUtils() throws InstantiationException {
+    throw new InstantiationException("Don't construct utility classes!");
+  }
+
+  /**
+   * Builds a {@link Profile} from the given {@link Product}, and its
+   * {@link Metadata}.
+   * 
+   * @param p
+   *          The given {@link Product}.
+   * @param met
+   *          The given {@link Metadata}.
+   * @param dataDelivBaseUrl
+   *          A string representation of a {@link URL} to the data delivery
+   *          service for this particular {@link Product}. This is used, in
+   *          combination with the {@link Product}'s ID, to populate the
+   *          {@link ResourceAttributes} <code>resLocation</code> field.
+   * @return An OODT {@link Profile} representation pointing at the given
+   *         {@link Product}.
+   */
+  public static Profile buildProfile(Product p, Metadata met,
+      String dataDelivBaseUrl) {
+
+    Profile prof = new Profile();
+
+    ProfileAttributes profAttrs = new ProfileAttributes();
+    profAttrs.setID(PROF_ID_PRE + p.getProductId());
+    profAttrs.setRegAuthority("CAS");
+    profAttrs.setType(PROF_TYPE);
+
+    prof.setProfileAttributes(profAttrs);
+
+    ResourceAttributes resAttrs = new ResourceAttributes();
+    resAttrs.setDescription(p.getProductType().getDescription());
+    resAttrs.setIdentifier(p.getProductId());
+    resAttrs.setResClass(p.getProductType().getName());
+    resAttrs.setTitle(p.getProductName());
+    resAttrs.getPublishers().add("CAS");
+    resAttrs.getResLocations().add(
+        dataDelivBaseUrl + "?productID=" + p.getProductId());
+
+    prof.setResourceAttributes(resAttrs);
+
+    // build up profile elements
+    for(Iterator i = met.getHashtable().keySet().iterator(); i.hasNext(); ){
+      String key = (String)i.next();
+      List vals = met.getAllMetadata(key);
+      
+      EnumeratedProfileElement elem = new EnumeratedProfileElement(prof);
+      System.out.println("Adding ["+key+"]=>"+vals);
+      elem.setName(key);
+      elem.getValues().addAll(vals);
+      prof.getProfileElements().put(key, elem);
+    }
+    
+    
+    return prof;
+
+  }
+
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/AndExpression.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/AndExpression.java
new file mode 100644
index 0000000..d64f2a7
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/AndExpression.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.Map;
+
+/**
+ * An "and" component of a where-expression.
+ *
+ * This component evaluates a result that's the intersection of the left and right
+ * expressions.
+ *
+ * @author Kelly
+ */
+class AndExpression implements WhereExpression {
+	/**
+	 * Construct an "and" where-expression.
+	 *
+	 * @param lhs Left-hand side
+	 * @param rhs Right-hand side.
+	 */
+	public AndExpression(WhereExpression lhs, WhereExpression rhs) {
+		this.lhs = lhs;
+		this.rhs = rhs;
+	}
+
+	public Result result(SearchableResourceAttributes resAttr, Map elements) {
+		return new Intersection(lhs.result(resAttr, elements), rhs.result(resAttr, elements));
+	}
+
+	public WhereExpression simplify() {
+		// Simplify the left and right sides, and keep this node.
+		lhs = lhs.simplify();
+		rhs = rhs.simplify();
+		return this;
+	}
+
+	public WhereExpression negate() {
+		return new OrExpression(lhs.negate(), rhs.negate());
+	}
+
+	public String toString() {
+		return "and[" + lhs + "," + rhs + "]";
+	}
+
+	/** Left-hand side of the expression. */
+	private WhereExpression lhs;
+
+	/** Right-hand side of the expression. */
+	private WhereExpression rhs;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/ConstantExpression.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/ConstantExpression.java
new file mode 100644
index 0000000..d441053
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/ConstantExpression.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.HashSet;
+import java.util.Map;
+
+/**
+ * A constant expression.
+ *
+ * This expression yields either all the elements (if it's a constant true) or none (if
+ * it's a constant false).
+ *
+ * @author Kelly
+ */
+class ConstantExpression implements WhereExpression {
+	/**
+	 * Construct a constant where-expression.
+	 *
+	 * @param value Truth value of this expression.
+	 */
+	public ConstantExpression(boolean value) {
+		this.value = value;
+	}
+
+	public Result result(SearchableResourceAttributes resAttr, Map elements) {
+		if (value)
+			return new MatchingResult(new HashSet(elements.values()));
+		else
+			return FalseResult.INSTANCE;
+	}
+
+	public WhereExpression simplify() {
+		// Can't get simpler than this.
+		return this;
+	}
+
+	public WhereExpression negate() {
+		return new ConstantExpression(!value);
+	}
+
+	public String toString() {
+		return "constant[" + value + "]";
+	}
+
+	/** Truth value. */
+	private boolean value;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/FalseResult.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/FalseResult.java
new file mode 100644
index 0000000..127de29
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/FalseResult.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.Set;
+import java.util.Collections;
+
+/**
+ * A constant false result.
+ *
+ * This result never contains any matching elements.
+ *
+ * <p>Don't create elements of this object.  Just use the {@link #INSTANCE} field, since
+ * only one is any program will ever need.
+ *
+ * @author Kelly
+ */
+class FalseResult implements Result {
+	/**
+	 * Construct a false result.
+	 */
+	private FalseResult() {}
+
+	/** The single false result any program will ever need. */
+	public static final FalseResult INSTANCE = new FalseResult();
+
+	public String toString() {
+		return "falseResult";
+	}
+
+	public Set matchingElements() {
+		return Collections.EMPTY_SET;
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/Intersection.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/Intersection.java
new file mode 100644
index 0000000..4ef52f4
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/Intersection.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.Set;
+import org.apache.oodt.profile.ProfileElement;
+
+/**
+ * Intersection of the two sets is the result.
+ *
+ * This result takes the intersection of two other results.
+ *
+ * @author Kelly
+ */
+class Intersection implements Result {
+	/**
+	 * Construct an intersection.
+	 *
+	 * @param lhs Left-hand side
+	 * @param rhs Right-hand side.
+	 */
+	public Intersection(Result lhs, Result rhs) {
+		this.lhs = lhs;
+		this.rhs = rhs;
+	}
+
+	public Set matchingElements() {
+		Set intersection = ProfileElement.profiles(lhs.matchingElements());
+		intersection.retainAll(ProfileElement.profiles(rhs.matchingElements()));
+		Set rc = ProfileElement.elements(intersection, lhs.matchingElements());
+		rc.addAll(ProfileElement.elements(intersection, rhs.matchingElements()));
+		return rc;
+	}
+
+	public String toString() {
+		return "intersection[" + lhs + "," + rhs + "]";
+	}
+
+	/** Left-hand side of the result. */
+	private Result lhs;
+
+	/** Right-hand side of the result. */
+	private Result rhs;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/LightweightProfileServer.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/LightweightProfileServer.java
new file mode 100644
index 0000000..29977ea
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/LightweightProfileServer.java
@@ -0,0 +1,298 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Stack;
+import org.apache.oodt.commons.Configuration;
+import org.apache.oodt.commons.ExecServerConfig;
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileException;
+import org.apache.oodt.profile.handlers.ProfileHandler;
+import org.apache.oodt.commons.util.DOMParser;
+import org.apache.oodt.commons.util.XML;
+import org.apache.oodt.xmlquery.QueryElement;
+import org.apache.oodt.xmlquery.XMLQuery;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * A lightweight profile server.
+ *
+ * A lightweight profile server is lightweight because it doesn't rely on any external
+ * database or other search/retrieval mechanism.
+ *
+ * @author Kelly
+ */
+final public class LightweightProfileServer implements ProfileHandler {
+	/**
+	 * Create a lightweight profile server using defaults.
+	 *
+	 * @throws IOException If an I/O error occurs.
+	 * @throws SAXException If an error occurs parsing the profile file.
+	 * @throws MalformedURLException If the default profile URL is malformed.
+	 */
+	public LightweightProfileServer() throws IOException, SAXException, MalformedURLException {
+		this(System.getProperties());
+	}
+
+	/**
+	 * Create a lightweight profile server using the given properties.
+	 *
+	 * The property we use is
+	 * <code>profiles.url</code>,
+	 * which is the URL of the file containing profile definitions that this server
+	 * will read and serve.
+	 *
+	 * @param props Properties.
+	 * @throws IOException If an I/O error occurs.
+	 * @throws SAXException If an error occurs parsing the profile file.
+	 * @throws MalformedURLException If the URL to the profile file is malformed.
+	 */
+	public LightweightProfileServer(Properties props) throws IOException, SAXException, MalformedURLException {
+		this(new URL(props.getProperty("org.apache.oodt.profile.handlers.LightweightProfileServer.profiles.url",
+                        props.getProperty("org.apache.oodt.profile.webServer.baseURL", "http://eda.jpl.nasa.gov")
+                        + "/profiles.xml")),
+			props.getProperty("org.apache.oodt.profile.handlers.LightweightProfileServer.id", "lightweight"));
+	}
+
+	/**
+	 * Create a lightweight profile server using the given URL.
+	 *
+	 * @param url URL of the file containing profile definitions that this server will read and serve.
+	 * @param id Identifier to report for when this handler is queried by name.
+	 * @throws IOException If an I/O error occurs.
+	 * @throws SAXException If an error occurs parsing the profile file.
+	 * @throws MalformedURLException If <var>url</var> is malformed.
+	 */
+	public LightweightProfileServer(URL url, String id) throws IOException, SAXException, MalformedURLException {
+		this.id = id;
+
+		// Get the list of profiles from the cache, if it's there.
+		profiles = (List) cache.get(url);
+		if (profiles != null) return;
+
+		// It wasn't in the cache, so create a parser to parse the file.  We only
+		// deal with correct files, so turn on validation and install an error
+		// handler that will throw an exception.
+		profiles = new ArrayList();
+		DOMParser parser = XML.createDOMParser();
+		parser.setErrorHandler(new ErrorHandler() {
+			public void error(SAXParseException ex) throws SAXParseException {
+				System.err.println("Parse error line " + ex.getLineNumber() + " column "
+					+ ex.getColumnNumber() + ": " + ex.getMessage());
+				throw ex;
+			}
+			public void warning(SAXParseException ex) {
+				System.err.println("Parse warning: " + ex.getMessage());
+			}
+			public void fatalError(SAXParseException ex) throws SAXParseException {
+				throw ex;
+			}
+		});
+
+		// Parse the file.
+		InputSource inputSource = new InputSource(url.toString());
+		parser.parse(inputSource);
+		Document doc = parser.getDocument();
+
+		// Normalize it and get the document element, and from that, create a list
+		// of profiles, and add it to the cache.
+		doc.normalize();
+		Element root = doc.getDocumentElement();
+		profiles = Profile.createProfiles(root, new SearchableObjectFactory());
+		cache.put(url, profiles);
+
+		System.err.println("LightweightProfileServer ready");
+	}
+
+	public List findProfiles(XMLQuery query) throws ProfileException {
+		// Compute the where-expression based on the query string, and start off
+		// with an empty set of results.
+		Set matchingProfiles = new HashSet();
+		WhereExpression whereExpression = createWhereExpression(query);
+
+		// Search each profile, and add the results of the search to the set of results.
+		for (Iterator i = profiles.iterator(); i.hasNext();) {
+			SearchableProfile profile = (SearchableProfile) i.next();
+
+			// Search the profile with the where-expression.
+			Result result = profile.search(whereExpression);
+
+			// If there are any matching elements, add the profile to the set.
+			if (!result.matchingElements().isEmpty())
+				matchingProfiles.add(profile);
+		}
+
+		// Convert from set to list.
+		return new ArrayList(matchingProfiles);
+	}
+
+	/**
+	 * Get a single profile matching the given ID.
+	 *
+	 * @param profID a {@link String} value.
+	 * @return a {@link Profile} value.
+	 */
+	public Profile get(String profID) {
+		if (profID == null) return null;
+		Profile rc = null;
+		for (Iterator i = profiles.iterator(); i.hasNext();) {
+			Profile p = (Profile) i.next();
+			if (p.getProfileAttributes().getID().equals(profID)) {
+				rc = p;
+				break;
+			}
+		}
+		return rc;
+	}
+
+	/**
+	 * Convert the XML query to a where expression.
+	 *
+	 * @param query The query to convert
+	 * @return The equivalent, simplified where expression.
+	 */
+	private static WhereExpression createWhereExpression(XMLQuery query) {
+		Stack stack = new Stack();
+		 
+		// Collect together the where- and from-sets, joined with an "and".
+		List allElements = new ArrayList(query.getWhereElementSet());
+		List fromElements = query.getFromElementSet();
+		if (!fromElements.isEmpty()) {
+			allElements.addAll(fromElements);
+			allElements.add(new QueryElement("LOGOP", "AND"));
+		}
+		
+		// For each item in the where-set
+		for (Iterator i = allElements.iterator(); i.hasNext();) {
+			QueryElement queryElement = (QueryElement) i.next();
+
+			// Get the keyword and its type.
+			String keyword = queryElement.getValue();
+			String type = queryElement.getRole();
+
+			if (type.equals("elemName")) {
+				// It's an element name, so push the element name.
+				stack.push(keyword);
+			} else if (type.equals("LITERAL")) {
+				// It's a literal value, so push the value.
+				stack.push(keyword);
+			} else if (type.equals("LOGOP")) {
+				// It's a logical operator.  Pop the operands off the
+				// stack and push the appropriate operator back on.
+				if (keyword.equals("AND")) {
+					stack.push(new AndExpression((WhereExpression) stack.pop(), (WhereExpression)stack.pop()));
+				} else if (keyword.equals("OR")) {
+					stack.push(new OrExpression((WhereExpression) stack.pop(), (WhereExpression)stack.pop()));
+				} else if (keyword.equals("NOT")) {
+					stack.push(new NotExpression((WhereExpression) stack.pop()));
+				} else throw new IllegalArgumentException("Illegal operator \"" + keyword + "\" in query");
+			} else if (type.equals("RELOP")) {
+				// It's a relational operator.  Pop the element name and
+				// literal value off the stack, and push the operator
+				// expression on with the given operator.
+				stack.push(new OperatorExpression((String) stack.pop(), (String) stack.pop(), keyword));
+			}
+		}
+
+		// If there's nothing on the stack, we're given nothing, so give back everything.
+		if (stack.size() == 0)
+			return new ConstantExpression(true);
+		else if (stack.size() > 1)
+			throw new IllegalStateException("Imbalanced expression in query");
+		
+		// Simplify/optimize the where-expression and return it.
+		return ((WhereExpression) stack.pop()).simplify();
+	}
+
+	/** {@inheritDoc} */
+	public String getID() {
+		return id;
+	}
+
+	/** Profiles I serve. */
+	private List profiles;
+
+	/**
+	 * Cache of profiles.
+	 *
+	 * This is a mapping from {@link java.net.URL} of the profile source to the {@link
+	 * List} of profiles.  We do this so we don't have to keep rereading and reparsing
+	 * the possibly huge profile file each time an object of this class is
+	 * instantiated.
+	 *
+	 * <p><em>Question:</em> Since when are multiple LightweightProfileServers being
+	 * constructed anyway?  There's just one per profile server process, and it's
+	 * using just the one file, so there should be no need for this cache.  Who added
+	 * this?  And if it were me, what was I smoking?
+	 */
+	private static Map cache = new HashMap();
+
+	/** My ID. */
+	private String id;
+
+	/**
+	 * Application execution entry point.
+	 *
+	 * This lets you try out a query to the Lightweight Profile server.
+	 *
+	 * @param argv Command-line arguments.
+	 * @throws Exception Should any error occur.
+	 */
+	public static void main(String[] argv) throws Exception {
+		if (argv.length == 0) {
+			System.err.println("Usage: <query>...");
+			System.exit(1);
+		}
+
+		// Create the profile
+		LightweightProfileServer lp = new LightweightProfileServer();
+
+		// Gather together the command-line arguments into a single long string.
+		StringBuffer b = new StringBuffer();
+		for (int i = 0; i < argv.length; ++i)
+			b.append(argv[i]).append(' ');
+
+		// Create the query object from the expression.
+		XMLQuery query = new XMLQuery(b.toString().trim(), /*id*/"cli1", /*title*/"CmdLine-1",
+			/*desc*/"This is a query entered on the command-line", /*ddId*/null, /*resultModeId*/null,
+			/*propType*/null, /*propLevels*/null, XMLQuery.DEFAULT_MAX_RESULTS);
+
+		// Display the results.
+		System.out.println(lp.findProfiles(query));
+
+		// All done.
+		System.exit(0);
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/MatchingResult.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/MatchingResult.java
new file mode 100644
index 0000000..c1d499f
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/MatchingResult.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.Collections;
+import java.util.Set;
+import org.apache.oodt.profile.ProfileElement;
+
+/**
+ * A matching result.
+ *
+ * This result matches profile elements.
+ *
+ * @author Kelly
+ */
+class MatchingResult implements Result {
+	/**
+	 * Construct a matching result.
+	 *
+	 * @param element The profile element that matches.
+	 */
+	public MatchingResult(ProfileElement element) {
+		this.elements = Collections.singleton(element);
+	}
+
+	/**
+	 * Construct a matching result.
+	 *
+	 * @param elements The profile elements that all match.
+	 */
+	public MatchingResult(Set elements) {
+		this.elements = elements;
+	}
+
+	public Set matchingElements() {
+		return elements;
+	}
+
+	public String toString() {
+		return "match[" + elements + "]";
+	}
+
+	/** The matching elements. */
+	private Set elements;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/NotExpression.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/NotExpression.java
new file mode 100644
index 0000000..b6929d7
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/NotExpression.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.Map;
+
+/**
+ * A "not" component of a where-expression.
+ *
+ * This expression component negates its given operand.
+ *
+ * @author Kelly
+ */
+class NotExpression implements WhereExpression {
+	/**
+	 * Construct a "not" where-expression.
+	 *
+	 * @param operand The operand.
+	 */
+	public NotExpression(WhereExpression operand) {
+		this.operand = operand;
+	}
+
+	public Result result(SearchableResourceAttributes resAttr, Map elements) {
+		throw new IllegalStateException("Not-nodes must be simplified out since they cannot yield results");
+	}
+
+	public WhereExpression simplify() {
+		// Negate my operand right now, then simplify it, and drop myself out.
+		return operand.negate().simplify();
+	}
+
+	public WhereExpression negate() {
+		return new NotExpression(operand.negate());
+	}
+
+	public String toString() {
+		return "not[" + operand + "]";
+	}
+
+	/** Expression to negate. */
+	private WhereExpression operand;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/OperatorExpression.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/OperatorExpression.java
new file mode 100644
index 0000000..c046019
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/OperatorExpression.java
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A operator component of a where-expression.
+ *
+ * This component applies an operator, like &lt;, =, &ge;, etc., to a element name and a
+ * literal value.
+ *
+ * @author Kelly
+ */
+class OperatorExpression implements WhereExpression {
+	/**
+	 * Construct an operator where-expression.
+	 *
+	 * @param value Value to which to compare.
+	 * @param name Name of element to match.
+	 * @param operator What operator to use
+	 */
+	public OperatorExpression(String value, String name, String operator) {
+		if (Arrays.binarySearch(VALID_OPERATORS, operator) < 0)
+			throw new IllegalArgumentException("Invalid operator \"" + operator + "\"");
+
+		this.name = name;
+		this.value = value;
+		this.operator = operator;
+	}
+
+	public Result result(SearchableResourceAttributes resAttr, Map elements) {
+		// Is it a "from" relation or a "where" relation?
+		if (FROM_TOKENS.contains(name)) {
+			// "From."  So let the resource attributes take care of it.
+			return resAttr.result(name, value, operator);
+		} else if (RESOURCE_ATTRIBUTES.contains(name)) {
+			// Resource attributes in "Where"
+			// let the resource attributes take care of it.
+			return resAttr.result(name, value, operator);
+		} else {
+			// "Where."  See if our keyword is present in the given set.
+			SearchableProfileElement element = (SearchableProfileElement) elements.get(name);
+
+			// Nope.  We can only give a false result.
+			if (element == null) return FalseResult.INSTANCE;
+
+			// Yep.  Ask the element to yield the result.
+			return element.result(value, operator);
+		}
+	}
+
+	public WhereExpression simplify() {
+		// Can't get simpler than this.
+		return this;
+	}
+
+	public WhereExpression negate() {
+		String negated;
+		if (operator.equals("EQ"))
+			negated = "NE";
+		else if (operator.equals("NE"))
+			negated = "EQ";
+		else if (operator.equals("LT"))
+			negated = "GE";
+		else if (operator.equals("GT"))
+			negated = "LE";
+		else if (operator.equals("LE"))
+			negated = "GT";
+		else if (operator.equals("LIKE"))
+			negated = "NE";
+		else if (operator.equals("NOTLIKE"))
+			negated = "EQ";
+		else
+			negated = "LT";
+		return new OperatorExpression(value, name, negated);
+	}
+
+	public String toString() {
+		return "operator[" + name + " " + operator + " " + value + "]";
+	}
+
+	/** Name of element to match. */
+	private String name;
+
+	/** Value to compare. */
+	private String value;
+
+	/** Operator to use. */
+	private String operator;
+
+	/**
+	 * Valid operators.
+	 *
+	 * <strong>KEEP THIS IN ORDER!</strong>  We binary search on them!
+	 */
+	private static final String[] VALID_OPERATORS = {
+		"EQ", "GE", "GT", "LE", "LIKE", "LT", "NE", "NOTLIKE"
+	};
+
+	/**
+	 * Relational operations performed on the "from" part of a query instead of the
+	 * "where" part.  These work off the resource attributes rather than the profile
+	 * elements.
+	 */
+	private static final Set FROM_TOKENS = new HashSet(Arrays.asList(org.apache.oodt.xmlquery.XMLQuery.FROM_TOKENS));
+
+	/**
+	 * Resource attributes that are parsed into WHERE part of the xmlquery
+	 */
+	private static final Set RESOURCE_ATTRIBUTES = new HashSet(Arrays.asList(
+		new String[]{
+		"Identifier", "Title", "Format", "Description", "Creator", 
+		"Subject", "Publisher", "Contributor", "Date", "Type", 
+		"Source", "Language", "Relation", "Coverage", "Rights", 
+		"resContext", "resClass", "resLocation" }));
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/OrExpression.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/OrExpression.java
new file mode 100644
index 0000000..31ab17f
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/OrExpression.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.Map;
+
+/**
+ * An "or" component of a where-expression.
+ *
+ * This component yields a result that's the union of the results of the left and right
+ * sides.
+ *
+ * @author Kelly
+ */
+class OrExpression implements WhereExpression {
+	/**
+	 * Construct an "or" where-expression.
+	 *
+	 * @param lhs Left-hand side
+	 * @param rhs Right-hand side.
+	 */
+	public OrExpression(WhereExpression lhs, WhereExpression rhs) {
+		this.lhs = lhs;
+		this.rhs = rhs;
+	}
+
+	public Result result(SearchableResourceAttributes resAttr, Map elements) {
+		return new Union(lhs.result(resAttr, elements), rhs.result(resAttr, elements));
+	}
+
+	public WhereExpression simplify() {
+		// Simplify the left and right sides, and keep this node.
+		lhs = lhs.simplify();
+		rhs = rhs.simplify();
+		return this;
+	}
+
+	public WhereExpression negate() {
+		return new AndExpression(lhs.negate(), rhs.negate());
+	}
+
+	public String toString() {
+		return "or[" + lhs + "," + rhs + "]";
+	}
+
+	/** Left-hand side of the expression. */
+	private WhereExpression lhs;
+
+	/** Right-hand side of the expression. */
+	private WhereExpression rhs;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/Result.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/Result.java
new file mode 100644
index 0000000..6c4ceb3
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/Result.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.Set;
+
+/**
+ * A result of a profile match.
+ *
+ * @author Kelly
+ */
+interface Result {
+	/**
+	 * Get the set of matching elements.
+	 *
+	 * If the set is empty, it means no elements matched.
+	 */
+	Set matchingElements();
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableEnumeratedProfileElement.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableEnumeratedProfileElement.java
new file mode 100644
index 0000000..3f99bce
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableEnumeratedProfileElement.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.rmi.RemoteException;
+import org.apache.oodt.xmlquery.XMLQuery;
+import org.apache.oodt.profile.EnumeratedProfileElement;
+import java.util.List;
+
+/**
+ * Searchable, enumerated, profile element.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+public class SearchableEnumeratedProfileElement extends EnumeratedProfileElement implements SearchableProfileElement {
+	public SearchableEnumeratedProfileElement(SearchableProfile profile, String name, String id, String desc, String type,
+		String unit, List synonyms, boolean obligation, int maxOccurrence, String comment, List values) {
+		super(profile, name, id, desc, type, unit, synonyms, obligation, maxOccurrence, comment, values);
+	}
+
+	public Result result(String value, String operator) {
+		Result rc = FalseResult.INSTANCE;
+		if (operator.equals("EQ") || operator.equals("LE") || operator.equals("GE") ||
+			operator.equals("LIKE")) {
+			if (values.contains(value))
+				rc = new MatchingResult(this);
+		} else if (operator.equals("NE") || operator.equals("NOTLIKE")) {
+			if (!values.contains(value))
+				rc = new MatchingResult(this);
+		}
+		return rc;
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableObjectFactory.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableObjectFactory.java
new file mode 100644
index 0000000..aed4e9a
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableObjectFactory.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.List;
+import org.apache.oodt.profile.EnumeratedProfileElement;
+import org.apache.oodt.profile.ObjectFactory;
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileAttributes;
+import org.apache.oodt.profile.RangedProfileElement;
+import org.apache.oodt.profile.ResourceAttributes;
+import org.apache.oodt.profile.UnspecifiedProfileElement;
+import org.w3c.dom.Element;
+
+/**
+ * Factory that yields searchable profile objects.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+class SearchableObjectFactory implements ObjectFactory {
+	public RangedProfileElement createRangedProfileElement(Profile profile, String name, String id, String desc, String type,
+		String unit, List synonyms, boolean obligation, int maxOccurrence, String comments, String min, String max) {
+		return new SearchableRangedProfileElement((SearchableProfile) profile, name, id, desc, type, unit, synonyms,
+			obligation, maxOccurrence, comments, min, max);
+	}
+	public UnspecifiedProfileElement createUnspecifiedProfileElement(Profile profile, String name, String id, String desc,
+		String type, String unit, List synonyms, boolean obligation, int maxOccurrence, String comments) {
+		return new SearchableUnspecifiedProfileElement((SearchableProfile) profile, name, id, desc, type, unit, synonyms,
+			obligation, maxOccurrence, comments);
+	}
+	public EnumeratedProfileElement createEnumeratedProfileElement(Profile profile, String name, String id, String desc,
+		String type, String unit, List synonyms, boolean obligation, int maxOccurrence, String comments, List values) {
+		return new SearchableEnumeratedProfileElement((SearchableProfile) profile, name, id, desc, type, unit, synonyms,
+			obligation, maxOccurrence, comments, values);
+	}
+	public Profile createProfile(Element node) {
+		return new SearchableProfile(node, this);
+	}
+	public ProfileAttributes createProfileAttributes(Element node) {
+		return new ProfileAttributes(node);
+	}
+	public ResourceAttributes createResourceAttributes(Profile profile, Element node) {
+		return new SearchableResourceAttributes((SearchableProfile) profile, node);
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableProfile.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableProfile.java
new file mode 100644
index 0000000..be9a108
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableProfile.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import org.apache.oodt.profile.ObjectFactory;
+import org.apache.oodt.profile.Profile;
+import org.w3c.dom.Element;
+
+/**
+ * A profile that can be searched.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+public class SearchableProfile extends Profile {
+	public SearchableProfile(Element node, ObjectFactory factory) {
+		super(node, factory);
+	}
+
+	/**
+	 * Search this profile.
+	 *
+	 * @param expression Statement of what to retrieve.
+	 */
+	public Result search(WhereExpression expression) {
+		return expression.result((SearchableResourceAttributes) resAttr, elements);
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableProfileElement.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableProfileElement.java
new file mode 100644
index 0000000..39a8093
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableProfileElement.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import org.apache.oodt.profile.ProfileElement;
+
+/**
+ * A profile element that can be searched.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+interface SearchableProfileElement {
+	/** Produce a search result.
+	 *
+	 * @param value The desired value.
+	 * @param operator What operator to use for comparison.
+	 * @return A search result.
+	 */
+	Result result(String value, String operator);
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableRangedProfileElement.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableRangedProfileElement.java
new file mode 100644
index 0000000..e8ae0f6
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableRangedProfileElement.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.List;
+import org.apache.oodt.profile.RangedProfileElement;
+
+/**
+ * Searchable profile element with a range of valid values.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+public class SearchableRangedProfileElement extends RangedProfileElement implements SearchableProfileElement {
+	public SearchableRangedProfileElement(SearchableProfile profile, String name, String id, String desc, String type,
+		String unit, List synonyms, boolean obligation, int maxOccurrence, String comment, String min, String max) {
+		super(profile, name, id, desc, type, unit, synonyms, obligation, maxOccurrence, comment, min, max);
+	}
+
+	public Result result(String value, String operator) {
+		Result rc = FalseResult.INSTANCE;
+		double numeric = Double.parseDouble(value);
+		if (operator.equals("EQ") || operator.equals("LIKE")) {
+			if (Double.parseDouble(min) <= numeric && numeric <= Double.parseDouble(max)) rc = new MatchingResult(this);
+		} else if (operator.equals("NE") || operator.equals("NOTLIKE")) {
+			if (numeric < Double.parseDouble(min) || numeric > Double.parseDouble(max)) rc = new MatchingResult(this);
+		} else if (operator.equals("LT")) {
+			if (numeric > Double.parseDouble(min)) rc = new MatchingResult(this);
+		} else if (operator.equals("GT")) {
+			if (numeric < Double.parseDouble(max)) rc = new MatchingResult(this);
+		} else if (operator.equals("LE")) {
+			if (numeric >= Double.parseDouble(min)) rc = new MatchingResult(this);
+		} else {
+			if (numeric <= Double.parseDouble(max)) rc = new MatchingResult(this);
+		}
+		return rc;
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableResourceAttributes.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableResourceAttributes.java
new file mode 100644
index 0000000..9ba2f98
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableResourceAttributes.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.oodt.profile.ResourceAttributes;
+import org.w3c.dom.Element;
+
+/**
+ * Resource attributes that can be searched.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+public class SearchableResourceAttributes extends ResourceAttributes {
+	public SearchableResourceAttributes(SearchableProfile profile, Element node) {
+		super(profile, node);
+	}
+
+	/**
+	 * Produce a search result.
+	 *
+	 * @param value Desired value.
+	 * @param operator What operator to use for comparison.
+	 * @return a <code>Result</code> value.
+	 */
+	public Result result(String name, String value, String operator) {
+		if ("Identifier".equals(name))
+			return computeResult(identifier, value, operator);
+		else if ("Title".equals(name))
+			return computeResult(title, value, operator);
+		else if ("Format".equals(name))
+			return computeResult(formats, value, operator);
+		else if ("Description".equals(name))
+			return computeResult(description, value, operator);
+		else if ("Creator".equals(name))
+			return computeResult(creators, value, operator);
+		else if ("Subject".equals(name))
+			return computeResult(subjects, value, operator);
+		else if ("Publisher".equals(name))
+			return computeResult(publishers, value, operator);
+		else if ("Contributor".equals(name))
+			return computeResult(contributors, value, operator);
+		else if ("Date".equals(name))
+			return computeResult(dates, value, operator);
+		else if ("Type".equals(name))
+			return computeResult(types, value, operator);
+		else if ("Source".equals(name))
+			return computeResult(sources, value, operator);
+		else if ("Language".equals(name))
+			return computeResult(languages, value, operator);
+		else if ("Relation".equals(name))
+			return computeResult(relations, value, operator);
+		else if ("Coverage".equals(name))
+			return computeResult(coverages, value, operator);
+		else if ("Rights".equals(name))
+			return computeResult(rights, value, operator);
+		else if ("resContext".equals(name))
+			return computeResult(contexts, value, operator);
+		else if ("resClass".equals(name))
+			return computeResult(clazz, value, operator);
+		else if ("resLocation".equals(name))
+			return computeResult(locations, value, operator);
+		else
+			throw new IllegalArgumentException("Unknown attribute \"" + name + "\"");
+	}
+
+	private Result computeResult(String a, String b, String op) {
+		int c = a.compareTo(b);
+		boolean t;
+		if ("EQ".equals(op) || "LIKE".equals(op))
+			t = c == 0;
+		else if ("GE".equals(op))
+			t = c >= 0;
+		else if ("GT".equals(op))
+			t = c > 0;
+		else if ("LE".equals(op))
+			t = c <= 0;
+		else if ("LT".equals(op))
+			t = c < 0;
+		else if ("NE".equals(op) || "NOTLIKE".equals(op))
+			t = c != 0;
+		else
+			throw new IllegalArgumentException("Unknown relational operator \"" + op + "\"");
+		if (t)
+			return new MatchingResult(new HashSet(profile.getProfileElements().values()));
+		else
+			return FalseResult.INSTANCE;
+	}
+
+	private Result computeResult(List a, String b, String op) {		
+		if (a == null || a.isEmpty()) return FalseResult.INSTANCE;
+
+		Result f = FalseResult.INSTANCE;
+		Result t = new MatchingResult(new HashSet(profile.getProfileElements().values()));
+		Result rc = f;
+		if ("EQ".equals(op) || "LIKE".equals(op))
+			if (a.contains(b)) rc = t;
+		else if ("NE".equals(op)  || "NOTLIKE".equals(op))
+			if (!a.contains(b)) rc = t;
+		else if ("LT".equals(op) || "GT".equals(op) || "LE".equals(op) || "GE".equals(op)) {
+			for (Iterator i = a.iterator(); i.hasNext();) {
+				String value = (String) i.next();
+				rc = computeResult(value, b, op);
+				if (rc != f) break;
+			}
+		} else throw new IllegalArgumentException("Unknown relational operator \"" + op + "\"");
+		return rc;
+	}
+
+
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableUnspecifiedProfileElement.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableUnspecifiedProfileElement.java
new file mode 100644
index 0000000..f480877
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/SearchableUnspecifiedProfileElement.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.List;
+import org.apache.oodt.profile.UnspecifiedProfileElement;
+
+/**
+ * Searchable profile element with unspecified values.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+public class SearchableUnspecifiedProfileElement extends UnspecifiedProfileElement implements SearchableProfileElement {
+	public SearchableUnspecifiedProfileElement(SearchableProfile profile, String name, String id, String desc, String type,
+		String unit, List synonyms, boolean obligation, int maxOccurrence, String comment) {
+		super(profile, name, id, desc, type, unit, synonyms, obligation, maxOccurrence, comment);
+	}
+
+	public Result result(String value, String operator) {
+		return new MatchingResult(this);
+	}
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/Union.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/Union.java
new file mode 100644
index 0000000..003670a
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/Union.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.Set;
+import org.apache.oodt.profile.ProfileElement;
+
+/**
+ * A union of matching elements.
+ *
+ * @author Kelly
+ */
+class Union implements Result {
+	/**
+	 * Construct a union.
+	 *
+	 * @param lhs Left-hand side
+	 * @param rhs Right-hand side.
+	 */
+	public Union(Result lhs, Result rhs) {
+		this.lhs = lhs;
+		this.rhs = rhs;
+	}
+
+	public Set matchingElements() {
+		Set union = ProfileElement.profiles(lhs.matchingElements());
+		union.addAll(ProfileElement.profiles(rhs.matchingElements()));
+		Set rc = ProfileElement.elements(union, lhs.matchingElements());
+		rc.addAll(ProfileElement.elements(union, rhs.matchingElements()));
+		return rc;
+	}
+
+	public String toString() {
+		return "union[" + lhs + "," + rhs + "]";
+	}
+
+	/** Left-hand side of the result. */
+	private Result lhs;
+
+	/** Right-hand side of the result. */
+	private Result rhs;
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/WhereExpression.java b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/WhereExpression.java
new file mode 100644
index 0000000..cf488a6
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/WhereExpression.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import java.util.Map;
+
+/**
+ * A where-expression.
+ *
+ * @author Kelly
+ */
+interface WhereExpression {
+	/**
+	 * Compute the result tree of this where expression based on the map of profile elements.
+	 *
+	 * @param resAttr Resource attributes to check.
+	 * @param elements Map from {@link String} element name to {@link ProfileElement}.
+	 * @return A result tree that when evaluated yields matching {@link ProfileElement}s.
+	 */
+	Result result(SearchableResourceAttributes resAttr, Map elements);
+
+	/**
+	 * Return a simplified version of this expression.
+	 *
+	 * Our result generation can't handle "NOT" expressions (like "not (blah < 3)")
+	 * since we can't do set inversion, so we simplify the expression by removing all
+	 * "NOT" nodes.
+	 *
+	 * @return An equivalent expression without negative nodes.
+	 */
+	WhereExpression simplify();
+
+	/**
+	 * Negate this expression.
+	 *
+	 * @return The negation of this expression.
+	 */
+	WhereExpression negate();
+}
diff --git a/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/package.html b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/package.html
new file mode 100644
index 0000000..aca2c2c
--- /dev/null
+++ b/0.8.1-rc1/profile/src/main/java/org/apache/oodt/profile/handlers/lightweight/package.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+  <head>
+    <title>Lightweight Profile Handler.
+    </title>
+  </head>
+  <body>
+    <p>Lightweight profile handler.  The lightweight profile handler
+      is lightweight because it doesn't rely on any external
+      search/retrieval mechanism.  It's 100% pure Java, baby.
+    </p>
+    <p>To use this handler, create an XML file that contains the
+      profiles you want to serve.  Set the system property
+      <code>profiles.url</code>
+      to the location of that file.  Fire 'er up.
+    </p>
+  </body>
+</html>
diff --git a/0.8.1-rc1/profile/src/site/resources/examples/src.jar b/0.8.1-rc1/profile/src/site/resources/examples/src.jar
new file mode 100644
index 0000000..3edbb96
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/resources/examples/src.jar
Binary files differ
diff --git a/0.8.1-rc1/profile/src/site/resources/images/class.png b/0.8.1-rc1/profile/src/site/resources/images/class.png
new file mode 100644
index 0000000..d8a7ab4
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/resources/images/class.png
Binary files differ
diff --git a/0.8.1-rc1/profile/src/site/resources/images/class.psd b/0.8.1-rc1/profile/src/site/resources/images/class.psd
new file mode 100644
index 0000000..3a20fd4
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/resources/images/class.psd
Binary files differ
diff --git a/0.8.1-rc1/profile/src/site/resources/images/delegation.png b/0.8.1-rc1/profile/src/site/resources/images/delegation.png
new file mode 100644
index 0000000..fd8d5cf
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/resources/images/delegation.png
Binary files differ
diff --git a/0.8.1-rc1/profile/src/site/resources/images/delegation.psd b/0.8.1-rc1/profile/src/site/resources/images/delegation.psd
new file mode 100644
index 0000000..02a2fd9
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/resources/images/delegation.psd
Binary files differ
diff --git a/0.8.1-rc1/profile/src/site/resources/images/grid-profile.jpg b/0.8.1-rc1/profile/src/site/resources/images/grid-profile.jpg
new file mode 100644
index 0000000..de71567
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/resources/images/grid-profile.jpg
Binary files differ
diff --git a/0.8.1-rc1/profile/src/site/resources/images/stack.png b/0.8.1-rc1/profile/src/site/resources/images/stack.png
new file mode 100644
index 0000000..10856a5
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/resources/images/stack.png
Binary files differ
diff --git a/0.8.1-rc1/profile/src/site/resources/images/stack.psd b/0.8.1-rc1/profile/src/site/resources/images/stack.psd
new file mode 100644
index 0000000..6d23e2d
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/resources/images/stack.psd
Binary files differ
diff --git a/0.8.1-rc1/profile/src/site/resources/images/tree.png b/0.8.1-rc1/profile/src/site/resources/images/tree.png
new file mode 100644
index 0000000..52cf31f
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/resources/images/tree.png
Binary files differ
diff --git a/0.8.1-rc1/profile/src/site/resources/images/tree.psd b/0.8.1-rc1/profile/src/site/resources/images/tree.psd
new file mode 100644
index 0000000..b51ce99
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/resources/images/tree.psd
Binary files differ
diff --git a/0.8.1-rc1/profile/src/site/site.xml b/0.8.1-rc1/profile/src/site/site.xml
new file mode 100644
index 0000000..3cfecdf
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/site.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+
+<project name="Profile Service">
+
+  <body>
+    <links>
+      <item name="OODT" href="../oodt-site/"/>
+      <item name="Grid" href="../grid/"/>
+    </links>
+
+    <menu ref="reports" inherit="bottom"/>
+    <menu name="User's Guide">
+      <item name="Information Captured" href="info/"/>
+      <item name="Querying Profiles" href="querying/"/>
+      <item name="Profile Repr." href="rep/"/>
+      <item name="Basic Handler" href="handler/"/>
+      <item name="Advanced Handler" href="adv/"/>
+    </menu>
+    
+  </body>
+</project>
diff --git a/0.8.1-rc1/profile/src/site/xdoc/adv/index.xml b/0.8.1-rc1/profile/src/site/xdoc/adv/index.xml
new file mode 100755
index 0000000..3c8b913
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/xdoc/adv/index.xml
@@ -0,0 +1,1072 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!--

+Licensed to the Apache Software Foundation (ASF) under one or more contributor

+license agreements.  See the NOTICE.txt 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.

+-->

+<document>

+  <properties>

+    <title>Developing a Real Profile Handler</title>

+    <author email="Sean.Kelly@jpl.nasa.gov">Sean Kelly</author>

+  </properties>

+  <!-- Wizzy Noise - Haiku -->

+  <body>

+    <section name="Developing a Real Profile Handler">

+      <p>In the <a href="../handler/">basic profile handler

+	  tutorial</a>, we developed a profile handler that answered

+	every query with a list of exactly zero profile objects.  It

+	also responded to requests to retrieve a profile by a

+	specific ID with <code>null</code>, meaning "not found by

+	this handler."  Useful, huh?  Not really.

+      </p>

+

+      <p>But it did get our profile server ready for <em>this</em>

+	tutorial, where we'll write a <em>real</em> profile handler

+	that analyzes incoming queries, consults a local "database",

+	constructs a set of matching profile results, and responds to

+	requests to profiles by ID.  Get some fresh coffee, because

+	this is going to be a tough one.

+      </p>

+

+      <p>And yes, you'll need to have gone through <em>all</em> of the

+	following before proceeding:

+      </p>

+

+      <ul>

+	<li><a href="../info/">Information Captured in a Profile</a></li>

+	<li><a href="../querying/">Querying Profiles</a></li>

+	<li><a href="../rep">Profile Representation</a></li>

+	<li><a href="../handler">Developing a Profile Handler</a></li>

+      </ul>

+    </section>

+

+    <section name="The Music Database">

+      <p>Let's say you've got an OODT <a href="/grid-product/">product

+	  server</a> already running that serves up your favorite

+	  music files.  All you have to do is pass in the URI to a

+	  track and it spits back the MP3 data which can run into your

+	  favorite media player.  You've set it up so your URIs are

+	  all unique for each track, and you just have to pass in an

+	  unparsed XMLQuery like <code>urn:sk:tr5B7E.mp3</code> and

+	  you get the matching data.

+      </p>

+

+      <p>But since you're not in the habit of memorizing hexadecimal

+	numbers inside of URIs, let's write a profile server who's job

+	it is to take queries for specific artists, genres, albums,

+	ratings, track titles, and so forth, and spit out the matching

+	profiles.  The profiles have a places for a URI (in the

+	<code>Identifier</code> field) that you can then pass to the

+	hypothetical product server to get the track data.  (In fact,

+	this is a common OODT pattern: profile query to do resource

+	location, product query to do resource retrieval.)  While

+	you're listening to the track, you can read all sorts of other

+	juicy metadata about it by examining the returned profile.

+      </p>

+

+      <subsection name="The Metadata">

+	<p>For this demonstration, we'll just focus on three kinds of

+	  metadata instead of going all-out, <a

+	    href="http://www.apple.com/itunes/">iTunes</a> style:

+	</p>

+

+	<ul>

+	  <li>Artist name</li>

+	  <li>Album name</li>

+	  <li>Track name</li>

+	</ul>

+

+	<p>Each profile will describe a single track.  The resource

+	  attributes will have:

+	</p>

+

+	<ul>

+	  <li>The URI of the track as the <code>Identifier</code>.</li>

+	  <li>The name of the track as the <code>Title</code>.</li>

+	  <li>The name of the artist as the <code>Creator</code>.</li>

+	</ul>

+

+	<p>In addition, we'll put in two profile elements:</p>

+

+	<ul>

+	  <li>The name of the album as an

+	    <code>EnumeratedProfileElement</code>.

+	  </li>

+	  <li>The name of the artist as an

+	    <code>EnumeratedProfileElement</code>.  Yes, this is

+	    redundant with the artist named as the <code>Creator</code>

+	    in the resource attributes; but one profile element by

+	    itself would get too lonely!</li>

+	</ul>

+      </subsection>

+

+      <subsection name="Query Style">

+	<p>Both product handlers and profile handlers get to choose

+	  whether they want unparsed query expressions in their

+	  XMLQuery objects or if they want parsed query expressions.

+	  Parsed query expressions generate the "where" boolean stack.

+	  While the product server that this profile server is meant

+	  to work with wants unparsed ones, we'll use parsed

+	  expressions for this profile handler.  Why?  Well, having a

+	  well-defined query language and a way to operate on it will

+	  save a little trouble from us having to generate a parser.

+	</p>

+

+	<p>The queries will use element names <code>artist</code>,

+	  <code>album</code>, and <code>track</code> only, to match

+	  what we'll save in our music database.  Here are a couple example queries:

+	</p>

+

+	<source>artist = Beatles AND album = Revolver

+track = 'Blue Suede Shoes'</source>

+      </subsection>

+    </section>

+

+    <section name="Developing the Handler">

+      <p>We'll develop the handler in parts, so we can discuss each

+	section, and then show the entire source file.

+      </p>

+

+      <subsection name='Making the "Database"'>

+	<p>Our music database will be nothing more than Java objects

+	  kept in memory.  We'll create separate objects of three

+	  classes:

+	</p>

+

+	<ul>

+	  <li><code>Artist</code>.  <code>Artist</code> objects represent

+	      people or groups who create music.  <code>Artist</code>s

+	      will have zero or more <code>Track</code>s.

+	  </li>

+	  <li><code>Album</code>.  <code>Album</code> objects are

+	    collections of <code>Track</code>s.

+	  </li>

+	  <li><code>Track</code>.  <code>Track</code> objects appear

+	    on one <code>Album</code> and are made by one

+	    <code>Artist</code>.  They have the URN necessary to pass

+	    to the hypothetical music product server in order to

+	    actually play music.

+	  </li>

+	</ul>

+

+	<p>A better music model would probably separate out artists

+	  and composers, account for remixes, compilation albums,

+	  re-issues, multiple renditions, and so forth, but this is

+	  government work, and it'll do.

+	</p>

+

+	<p>Here's class <code>Artist</code>:</p>

+

+	<source>class Artist {

+  public Artist(String name) {

+    this.name = name;

+    tracks = new ArrayList();

+  }

+  public String getName() {

+    return name;

+  }

+  public List getTracks() {

+    return tracks;

+  }

+  public int hashCode() {

+    return name.hashCode();

+  }

+  public boolean equals(Object obj) {

+    if (obj == this) return true;

+    if (!(obj instanceof Artist)) return false;

+    Artist rhs = (Artist) obj;

+    return name.equals(rhs.name);

+  }

+  private String name;

+  private List tracks;

+}</source>

+

+	<p>As you can see, <code>Artist</code>s have a name and a

+	  <code>List</code> of <code>Track</code>s they've made.  Now,

+	  here's class <code>Album</code>:

+	</p>

+

+	<source>class Album {

+  public Album(String name) {

+    this.name = name;

+    tracks = new ArrayList();

+  }

+  public String getName() {

+    return name;

+  }

+  public List getTracks() {

+    return tracks;

+  }

+  public int hashCode() {

+    return name.hashCode();

+  }

+  public boolean equals(Object obj) {

+    if (obj == this) return true;

+    if (!(obj instanceof Album)) return false;

+    Album rhs = (Album) obj;

+    return name.equals(rhs.name);

+  }

+  private String name;

+  private List tracks;

+}</source>

+

+	<p>As with <code>Artist</code>s, <code>Album</code>s (or

+	  should that be <em>Alba</em>?) have names and collections of

+	  <code>Track</code>s.  Finally, here's class <code>Track</code>:

+	</p>

+

+	<source>class Track {

+  public Track(String name, URI id, Artist artist,

+    Album album) {

+    this.name = name;

+    this.id = id;

+    this.artist = artist;

+    this.album = album;

+    artist.getTracks().add(this);

+    album.getTracks().add(this);

+  }

+  public String getName() { return name; }

+  public URI getID() { return id; }

+  public Artist getArtist() { return artist; }

+  public Album getAlbum() { return album; }

+  public int hashCode() {

+    return name.hashCode() ^ id.hashCode();

+  }

+  public boolean equals(Object obj) {

+    if (obj == this) return true;

+    if (!(obj instanceof Track)) return false;

+    Track rhs = (Track) obj;

+    return id.equals(rhs.id);

+  }

+  private String name;

+  private URI id;

+  private Artist artist;

+  private Album album;

+}</source>

+

+	<p>As you can see from the code, a track belongs to an

+	  <code>Artist</code> and to an <code>Album</code> and has a

+	  URI which you can use to get to the track's MP3 data.

+	  Finally, with these three "entity" classes in hand, we can

+	  create a music database:

+	</p>

+

+	<source>class DB {

+  public static Set ARTISTS = new HashSet();

+  public static Set ALBUMS = new HashSet();

+  public static Set TRACKS = new HashSet();

+  static {

+    Artist bach = new Artist("Bach");

+    Album brandenburg123

+      = new Album("Brandenburg Concerti 1, 2, 3");

+    Album brandenburg456

+      = new Album("Brandenburg Concerti 4, 5, 6");

+    Track brandenburg1

+      = new Track("Brandenburg Concerto #1",

+      URI.create("urn:sk:tr91BC.mp3"), bach,

+      brandenburg123);

+    Track brandenburg2

+      = new Track("Brandenburg Concerto #2",

+      URI.create("urn:sk:tr311E.mp3"), bach,

+      brandenburg123);

+    Track brandenburg3

+      = new Track("Brandenburg Concerto #3",

+      URI.create("urn:sk:trA981.mp3"), bach,

+      brandenburg123);

+    Track brandenburg4

+      = new Track("Brandenburg Concerto #4",

+      URI.create("urn:sk:tr233A.mp3"), bach,

+      brandenburg456);

+    Track brandenburg5

+      = new Track("Brandenburg Concerto #5",

+      URI.create("urn:sk:trA6E5.mp3"), bach,

+      brandenburg456);

+

+     Track brandenburg6

+      = new Track("Brandenburg Concerto #6",

+      URI.create("urn:sk:tr01E9.mp3"), bach,

+      brandenburg456);

+

+    Artist delerium = new Artist("Delerium");

+    Album semantic = new Album("Semantic Spaces");

+    Album poem = new Album("Poem");

+    Track flowers

+      = new Track("Flowers Become Screens",

+      URI.create("urn:sk:tr3A5E.mp3"), delerium,

+      semantic);

+    Track metaphor = new Track("Metaphor",

+      URI.create("urn:sk:tr0E13.mp3"), delerium,

+      semantic);

+    Track innocente = new Track("Innocente",

+      URI.create("urn:sk:tr004A.mp3"), delerium,

+      poem);

+    Track aria = new Track("Aria",

+      URI.create("urn:sk:tr004A.mp3"), delerium,

+      poem);

+

+    ARTISTS.add(bach);

+    ARTISTS.add(delerium);

+    ALBUMS.add(brandenburg123);

+    ALBUMS.add(brandenburg456);

+    ALBUMS.add(semantic);

+    ALBUMS.add(poem);

+    TRACKS.add(brandenburg1);

+    TRACKS.add(brandenburg2);

+    TRACKS.add(brandenburg3);

+    TRACKS.add(brandenburg4);

+    TRACKS.add(brandenburg5);

+    TRACKS.add(brandenburg6);

+    TRACKS.add(flowers);

+    TRACKS.add(metaphor);

+    TRACKS.add(innocente);

+    TRACKS.add(aria);

+  }

+}</source>

+

+	<p>(Please don't judge this limited collection as the breadth

+	  of my listening tastes.  It's actually much narrower now!)

+	  In this small database, we've got two artists, Bach and

+	  Delerium, with four albums: <i>Brandenburg Concerti 1, 2,

+	  3</i> and <i>4, 5, 6</i>; and <i>Semantic Spaces</i> and

+	  <i>Poem</i>.  And we've got 10 tracks: 3 belonging to one

+	  album, 3 belonging to another, 2 belonging to yet another,

+	  and the last 2 belonging to the last album.  Six are by

+	  Bach, and four by Delerium.  Each track has

+	</p>

+      </subsection>

+

+      <subsection name="Querying our Database">

+	<p>Recall that the <a href="/edm-query/">XMLQuery</a>'s query

+	  language uses triples of the form (element, relation,

+	  literal) like <code>album != Poem</code>.  The relations

+	  include =, !=, &lt;, &gt;, &lt;=, &gt;=, LIKE, and NOTLIKE.

+	  The triples are linked with AND, OR, and NOT.  For this

+	  tutorial, we'll do the = and != cases.  The rest you can

+	  fill in for your own edification.  Our approach will be to

+	  examine the postfix "where" boolean stack and convert it

+	  into an infix boolean expression tree.  We'll ask the tree

+	  to evaluate itself into a matching set of

+	  <code>Track</code>s.  Then all we have to do is descibe the

+	  matching <code>Track</code>s as <code>Profile</code>

+	  objects.

+	</p>

+

+	<p>Let's start by defining a node in our expression tree:</p>

+

+	<source>interface Expr {

+  Set evaluate();

+}</source>

+

+	<p>The <code>evaluate</code> method means "evaluate into a

+	  <code>Set</code> of matching <code>Track</code> objects."

+	  With this interface, we can then define classes that make up

+	  different flavors of tree nodes.  One of the easier ones is

+	  a constant tree node that either matches <em>every</em>

+	  track available (constant true) or <em>none</em> of them

+	  (constant false):

+	</p>

+

+	<source>class Constant implements Expr {

+  public Constant(boolean value) {

+    this.value = value;

+  }

+  public Set evaluate() {

+    return value? DB.TRACKS

+      : Collections.EMPTY_SET;

+  }

+  private boolean value;

+}</source>

+

+	<p>Next, let's do negation.  This takes the set complement of

+	  an existing tree node:

+	</p>

+

+	<source>class Not implements Expr {

+  public Not(Expr expr) {

+    this.expr = expr;

+  }

+  public Set evaluate() {

+    Set matches = expr.evaluate();

+    Set inverse = new HashSet();

+    for (Iterator i = DB.TRACKS.iterator();

+      i.hasNext();) {

+      Track t = (Track) i.next();

+      if (!matches.contains(t))

+        inverse.add(t);

+    }

+    return inverse;

+  }

+  private Expr expr;

+}</source>

+

+	<p>As you can see, this node is constructed with another tree

+	  node expression.  To evaluate this node, we evaluate the

+	  expression passed in.  Then we take its inverse by iterating

+	  through each track in the database and adding it to the

+	  matching set if it <em>doesn't</em> occur in the

+	  expression's matching set.

+	</p>

+

+	<p>The union tree node takes two expressions and adds the two

+	  sets of matching tracks together:

+	</p>

+

+	<source>class Or implements Expr {

+  public Or(Expr lhs, Expr rhs) {

+    this.lhs = lhs;

+    this.rhs = rhs;

+  }

+  public Set evaluate() {

+    Set left = lhs.evaluate();

+    Set right = rhs.evaluate();

+    left.addAll(right);

+    return left;

+  }

+  private Expr lhs;

+  private Expr rhs;

+}</source>

+

+	<p>The intersection tree node evaluates to <code>Track</code>s

+	  that occur only in both expressions' tracks:

+	</p>

+

+	<source>class And implements Expr {

+  public And(Expr lhs, Expr rhs) {

+    this.lhs = lhs;

+    this.rhs = rhs;

+  }

+  public Set evaluate() {

+    Set left = lhs.evaluate();

+    Set right = rhs.evaluate();

+    left.retainAll(right);

+    return left;

+  }

+  private Expr lhs;

+  private Expr rhs;

+}</source>

+

+	<p>With these nodes, we can cover the logical operators AND,

+	  OR, and NOT that appear in a postfix "where" stack, as well

+	  as an empty "where" stack, which, by convention, is meant to

+	  be a constant "true", matching all available resources.  Now

+	  we just have to handle triples (element, relation, literal).

+	  First up, comparisons against <code>Artist</code>s:

+	</p>

+

+	<source>class ArtistExpr implements Expr {

+  public ArtistExpr(String op, String value) {

+    this.op = op;

+    this.value = value;

+  }

+  public Set evaluate() {

+    Set tracks = new HashSet();

+    if ("EQ".equals(op)) {

+      for (Iterator i = DB.ARTISTS.iterator();

+        i.hasNext();) {

+        Artist a = (Artist) i.next();

+        if (a.getName().equals(value))

+          tracks.addAll(a.getTracks());

+      }

+    } else if ("NE".equals(op)) {

+      for (Iterator i = DB.ARTISTS.iterator();

+        i.hasNext();) {

+        Artist a = (Artist) i.next();

+        if (!a.getName().equals(value))

+          tracks.addAll(a.getTracks());

+      }

+    } else throw new

+      UnsupportedOperationException("NYI");

+    return tracks;

+  }

+  private String op;

+  private String value;

+}</source>

+

+	<p>For an expression like <code>artist = Bach</code> or

+	  <code>artist != Delerium</code> we use a expression node

+	  object of the above class.  When it's <code>EQ</code>, we

+	  iterate through all the artists in the database and, when

+	  the artist's name matches, add all of that artist's tracks

+	  to the set of matches.  When it's <code>NE</code>, we

+	  instead add all of the artists' tracks whose name

+	  <em>doesn't</em> match.  (The other relational operators,

+	  <code>LT</code>, <code>GT</code>, <code>LE</code>,

+	  <code>GE</code>, <code>LIKE</code>, and <code>NOTLIKE</code>

+	  currently throw an exception.  You're welcome to try to

+	  implement those.)

+	</p>

+

+	<p>The <code>AlbumExpr</code> expression node is quite similar:</p>

+

+	<source>class AlbumExpr implements Expr {

+  public AlbumExpr(String op, String value) {

+    this.op = op;

+    this.value = value;

+  }

+  public Set evaluate() {

+    Set tracks = new HashSet();

+    if ("EQ".equals(op)) {

+      for (Iterator i = DB.ALBUMS.iterator();

+        i.hasNext();) {

+        Album a = (Album) i.next();

+        if (a.getName().equals(value))

+          tracks.addAll(a.getTracks());

+      }

+    } else if ("NE".equals(op)) {

+      for (Iterator i = DB.ALBUMS.iterator();

+        i.hasNext();) {

+        Album a = (Album) i.next();

+        if (!a.getName().equals(value))

+          tracks.addAll(a.getTracks());

+      }

+    } else throw new

+      UnsupportedOperationException("NYI");

+    return tracks;

+  }

+  private String op;

+  private String value;

+}</source>

+

+	<p>(Another exercise for the reader: refactor out common code

+	  between these two classes.)  Finally, the

+	  <code>TrackExpr</code> node is for expressions like

+	  <code>track = Poem</code>:

+	</p>

+

+	<source>class TrackExpr implements Expr {

+  public TrackExpr(String op, String value) {

+    this.op = op;

+    this.value = value;

+  }

+  public Set evaluate() {

+    Set tracks = new HashSet();

+    if ("EQ".equals(op)) {

+      for (Iterator i = DB.TRACKS.iterator();

+        i.hasNext();) {

+        Track t = (Track) i.next();

+        if (t.getName().equals(value))

+          tracks.add(t);

+      }

+    } else if ("NE".equals(op)) {

+      for (Iterator i = DB.TRACKS.iterator();

+        i.hasNext();) {

+        Track t = (Track) i.next();

+        if (!t.getName().equals(value))

+          tracks.add(t);

+      }

+    } else throw new

+      UnsupportedOperationException("NYI");

+    return tracks;

+  }

+  private String op;

+  private String value;

+}</source>

+

+	<p>For <code>EQ</code>, we just iterate through every track in

+	  the database and add it to the set of matching tracks if the

+	  names match the name passed into the user's query.  For

+	  <code>NE</code>, we add them if their names <em>don't</em> match.

+	</p>

+

+	<p>That completes all the code for the expression tree.  Now

+	  we can start working on the class that implements the

+	  <code>ProfileHandler</code> interface,

+	  <code>MusicHandler</code>.  Here, we'll build that

+	  expression tree with the incoming <code>XMLQuery</code>,

+	  which provides its "where" element stack as a postfix

+	  boolean expression.  Here's the approach:

+	</p>

+

+	<ol>

+	  <li>Make a new, empty stack.</li>

+	  <li>For each element in the "where" stack:

+	    <ol>

+	      <li>If it's an element name (<code>artist</code>,

+		<code>album</code>, <code>track</code>), push the name

+		onto the stack.

+	      </li>

+	      <li>If it's a literal value (<code>Bach</code>,

+		<code>Poem</code>, etc.), push it onto the stack.

+	      </li>

+	      <li>If it's a relational operator (<code>EQ</code>, <code>NE</code>, etc.):

+		<ol>

+		  <li>Pop two values off.</li>

+		  <li>Push an <code>ArtistExpr</code>, <code>AlbumExpr</code>, or <code>TrackExpr</code>.</li>

+		</ol>

+	      </li>

+	      <li>It it's a logical operator:

+		<ul>

+		  <li>For <code>AND</code>, pop two values off and push an <code>And</code> node.</li>

+		  <li>For <code>OR</code>, pop two values off and push an <code>Or</code> node.</li>

+		  <li>For <code>NOT</code>, pop one value off and push a <code>Not</code> node.</li>

+		</ul>

+	      </li>

+	    </ol>

+	  </li>

+	</ol>

+	<p>In the end, there will be one element left on the stack, an

+	  <code>Expr</code> node representing the root of the

+	  expression tree.  Here's the method of

+	  <code>MusicHandler</code> that implements the algorithm:

+	</p>

+

+	<source>private static Expr transform(XMLQuery q) {

+  Stack stack = new Stack();

+  for (Iterator i = q.getWhereElementSet()

+    .iterator(); i.hasNext();) {

+    QueryElement e = (QueryElement) i.next();

+    String keyword = e.getValue();

+    String type = e.getRole();

+    if ("elemName".equals(type))

+	stack.push(keyword);

+    else if ("LITERAL".equals(type))

+	stack.push(keyword);

+    else if ("RELOP".equals(type))

+	addRelational(keyword, (String)stack.pop(),

+	  (String)stack.pop(), stack);

+    else if ("LOGOP".equals(type))

+	addLogical(keyword, stack);

+    else throw new

+	IllegalArgumentException("Unknown query "

+	  + type + " type");

+  }

+  if (stack.size() == 0)

+    return new Constant(true);

+  else if (stack.size() > 1)

+    throw new IllegalArgumentException("Unbalanced"

+      + " query");

+  else return (Expr) stack.pop();

+}</source>

+

+	<p>For relational and logical operators, this method defers to

+	  two other utility methods, which we'll see shortly.  After

+	  iterating through the entire "where" set, we check to see if

+	  there's an empty stack.  That's the case where the user

+	  passes in an empty expression, which by convention we'll

+	  take to mean they want everything.  Otherwise, there should

+	  be just one <code>Expr</code> node on the stack, the root of

+	  the expression tree.

+	</p>

+

+	<p>To handle adding a <code>RELOP</code>, we pop two values

+	  off, the element name (<code>artist</code>,

+	  <code>album</code>, or <code>track</code>), and the literal

+	  value the user wants (<code>Bach</code>, <code>Poem</code>,

+	  etc.), along with the operator and the stack:

+	</p>

+

+	<source>private static void addRelational(String op,

+  String value, String kind, Stack stack) {

+  if ("artist".equals(kind))

+    stack.push(new ArtistExpr(op, value));

+  else if ("album".equals(kind))

+    stack.push(new AlbumExpr(op, value));

+  else if ("track".equals(kind))

+    stack.push(new TrackExpr(op, value));

+  else throw new

+    IllegalArgumentException("Unknown profile"

+      + " element " + kind);

+}</source>

+

+	<p>This method then replaces the popped off values with the

+	  matching <code>Expr</code> class for artists, albums, or

+	  tracks.

+	</p>

+

+	<p>To handle adding a <code>LOGOP</code>, we pass the logical

+	  operator and the entire stack to this method:

+	</p>

+

+	<source>private static void addLogical(String op,

+  Stack stack) {

+  if ("AND".equals(op))

+    stack.push(new And((Expr)stack.pop(),

+      (Expr) stack.pop()));

+  else if ("OR".equals(op))

+    stack.push(new Or((Expr)stack.pop(),

+      (Expr) stack.pop()));

+  else if ("NOT".equals(op))

+    stack.push(new Not((Expr)stack.pop()));

+  else throw new

+    IllegalArgumentException("Illegal operator "

+      + op);

+}</source>

+

+	<p>With all this code in place we can generate the expression

+	  tree.  Let's look at an example.  Suppose when constructing the

+	  <code>XMLQuery</code>, the user passed in</p>

+

+	<source>artist = Bach and not album = Poem or track != Aria</source>

+

+	<p>The XMLQuery query language generates a postfix stack of

+	  <code>QueryElement</code> objects in the "where" list:

+	</p>

+

+	<img src="../images/stack.png" alt="Stack" />

+

+	<p>And we then create this tree:</p>

+

+	<img src="../images/tree.png" alt="Tree" />

+

+	<p>Calling the root's <code>evaluate</code> method then yields

+	  a <code>java.util.Set</code> of <code>Track</code> objects

+	  that match that expression.

+	</p>

+

+	<p>OK, we've got a set of <code>Track</code>s.  But what we

+	  want are a set of <em><code>Profile</code>s</em>.  The next

+	  step is to describe those tracks using the profile metadata

+	  model.

+	</p>

+      </subsection>

+

+      <subsection name="Describing Tracks">

+	<p>Query handlers serve up <code>List</code>s of

+	  <code>Profile</code> objects, where <code>Profile</code>s

+	  contain metadata descriptions of resources.  For this

+	  tutorial, the resources we're describing are music tracks,

+	  represented by instances of <code>Track</code> objects.

+	  When the handler's <code>findProfiles</code> and

+	  <code>get</code> methods are called by the OODT framework to

+	  service a request, all we have to do is find the matching

+	  <code>Track</code> (or <code>Track</code>s) and create

+	  matching <code>Profile</code>s.

+	</p>

+

+	<p>Recall that we're setting up the resource attributes of the

+	  profile so that

+	</p>

+	<ul>

+	  <li>The URI of the track appears in the <code>Identifier</code>.</li>

+	  <li>The name of the track appears in the <code>Title</code>.</li>

+	  <li>The name of the artist appears the <code>Creator</code>.</li>

+	</ul>

+

+	<p>In addition, we'll put in two profile elements:</p>

+

+	<ul>

+	  <li>The name of the album as an

+	    <code>EnumeratedProfileElement</code>.

+	  </li>

+	  <li>The name of the artist redundantly as an

+	    <code>EnumeratedProfileElement</code>.

+	  </li>

+	</ul>

+

+	<p>Now, let's create a utility method <code>describe</code>

+	  which takes a <code>java.util.Set</code> of matching

+	  <code>Track</code>s and yields a <code>java.util.List</code>

+	  of corresponding <code>Profile</code>s:

+	</p>

+

+	<source>private static List describe(Set tracks) {

+  List profiles = new ArrayList();

+  for (Iterator i = tracks.iterator();

+    i.hasNext();) {

+    Track t = (Track) i.next();

+    String id = t.getID().toString();

+    String trackName = t.getName();

+    String albumName = t.getAlbum().getName();

+    String artistName = t.getArtist().getName();

+    Profile p = createProfile(id, trackName,

+      albumName, artistName);

+    profiles.add(p);

+  }

+  return profiles;

+}</source>

+

+	<p>We build a list of <code>Profile</code>s by calling another

+	  method, <code>createProfile</code>.  It takes the track's

+	  URI, its name, the name of the album on which it appears,

+	  and the name of the artist who created it, and yields a

+	  <code>Profile</code>:

+	</p>

+

+	<source>private static Profile createProfile(String id,

+  String trackName, String albumName,

+  String artistName) {

+  Profile p = new Profile();

+  ProfileAttributes pa=new ProfileAttributes(id,

+    "1.0", "profile", "active", "unclassified",

+    /*parent*/null, /*children*/EL,

+    "1.3.6.1.4.1.7655", /*revNotes*/EL);

+  p.setProfileAttributes(pa);

+  ResourceAttributes ra=new ResourceAttributes(p,

+    id, trackName,

+    Collections.singletonList("audio/mpeg"),

+    /*desc*/null,

+    Collections.singletonList(artistName),

+    /*subjects*/EL, /*pubs*/EL, /*contrib*/EL,

+    /*dates*/EL, /*types*/EL, /*sources*/EL,

+    /*langs*/EL, /*relations*/EL, /*covs*/EL,

+    /*rights*/EL,

+    Collections.singletonList("SK.Music"),

+    "granule", "system.productServer",

+    Collections.singletonList("urn:eda:rmi:"

+      + "MyProductServer"));

+    p.setResourceAttributes(ra);

+    EnumeratedProfileElement artistElem =

+    new EnumeratedProfileElement(p, "artist",

+    "artist", "Name of the artist of a work",

+    "string", "name", /*syns*/EL, /*ob*/true,

+    /*maxOccur*/1, /*comment*/null,

+    Collections.singletonList(artistName));

+  p.getProfileElements().put("artist",

+    artistElem);

+  EnumeratedProfileElement albumElem =

+    new EnumeratedProfileElement(p, "album",

+    "album", "Name of album where track occurs",

+    "string", "name", /*syns*/EL, /*ob*/true,

+    /*maxOccur*/1, /*comment*/null,

+    Collections.singletonList(albumName));

+  p.getProfileElements().put("album",

+    albumElem);

+  return p;

+}</source>

+

+	<p>The profile attributes say that</p>

+	<ul>

+	  <li>The ID of the profile itself is the same as the track's URI.</li>

+	  <li>The version of the profile is 1.0.</li>

+	  <li>The type is "profile".</li>

+	  <li>It's currently active.</li>

+	  <li>It's not top-secret, it's "unclassified".</li>

+	  <li>It has no parent profile.</li>

+	  <li>It has no child profiles.</li>

+	  <li>The registration authority has OID 1.3.6.1.4.1.7655</li>

+	  <li>There are no revision notes.</li>

+	</ul>

+

+	<p>The resource attributes say that</p>

+	<ul>

+	  <li>The Identifier is the track's URI.</li> <li>The Title is

+	  the track's title.</li> <li>The sole Format in which the

+	  track is available is <code>audio/mpeg</code>.</li>

+	  <li>There's no description.</li> <li>The sole Creator is the

+	  name of the artist.</li> <li>There are no subject keywords,

+	  publishers, contributors, dates, types, sources, languages,

+	  relations, coverages, nor rights.</li>

+	  <li>The sole resource context is "Tutorial.Music".</li>

+	  <li>The resource's aggregation is "granule", meaning this profile is describing a single, discrete resource.</li>

+	  <li>The resource's class is "system.productServer", meaning you need to contact a product server at the resource location to retrieve the resource.</li>

+	  <li>The resource location is <code>urn:eda:rmi:MyProductServer</code>.</li>

+	</ul>

+

+	<p>Finally, the two profile elements tell (again) who the

+	  artist was and also on what album the track appears.

+	</p>

+

+	<p>What's with all the <code>EL</code>s?  It's just to save on typing:</p>

+

+	<source>private static final List EL

+  = Collections.EMPTY_LIST;</source>

+      </subsection>

+

+      <subsection name="Implementng the Interface">

+	<p>The <code>ProfileHandler</code> interface stipulates two

+	  methods, one for finding profiles given an

+	  <code>XMLQuery</code> and another for retrieving a single

+	  profile given its ID.  With all of these utility methods in

+	  place, these are both easy to write.  First, the

+	  <code>findProfiles</code> method:

+	</p>

+

+	<source>public List findProfiles(XMLQuery q) {

+  Expr expr = transform(q);

+  Set matches = expr.evaluate();

+  List profiles = describe(matches);

+  return profiles;

+}</source>

+

+	<p>The algorithm should be painfully obvious by now: transform

+	  the query to a tree, evaluate the tree into a set of

+	  matching tracks, and describe the tracks.

+	</p>

+

+	<p>The <code>get</code> method takes a profile's ID and

+	  returns the matching profile, or <code>null</code> if it's

+	  not found.  Since we're using the track's ID as the

+	  profile's ID as well, we can just iterate through our

+	  tracks, find the one with the matching ID, and

+	  <code>describe</code> it:

+	</p>

+

+	<source>public Profile get(String id) {

+  URI uri = URI.create(id);

+  for (Iterator i = DB.TRACKS.iterator();

+    i.hasNext();) {

+    Track t = (Track) i.next();

+    if (t.getID().equals(uri))

+      return createProfile(t.getID().toString(),

+        t.getName(), t.getAlbum().getName(),

+        t.getArtist().getName());

+  }

+  return null;

+}</source>

+

+      </subsection>

+

+      <subsection name="Complete Source Code">

+	<p>Don't feel like cutting and pasting all of those code

+	  fragments?  No problem.  All of the source files are

+	  available <a href="../examples/src.jar">in a jar</a>.

+	</p>

+      </subsection>

+    </section>

+

+    <section name="Compiling the Handler">

+      <p>As with the <a

+	  href="../handler/"><code>NullHandler</code></a>, we'll use the

+	J2SDK command-line tools.  And if you've gone through the <a

+	  href="../handler/"><code>NullHandler</code> tutorial</a>, you've

+	got all the dependent jars in place already.  Just put the

+	<code>MusicHandler.java</code> and all the related source files

+	under <code>$PS_HOME/src</code>, compile, and build the jar:

+      </p>

+

+      <source>% <b>ls src</b>

+Album.java         Expr.java

+AlbumExpr.java     MusicHandler.java

+And.java           Not.java

+Artist.java        NullHandler.java

+ArtistExpr.java    Or.java

+Constant.java      Track.java

+DB.java            TrackExpr.java

+% <b>javac -extdirs lib -d classes src/*.java</b>

+% <b>ls classes</b>

+Album.class         Expr.class

+AlbumExpr.class     MusicHandler.class

+And.class           Not.class

+Artist.class        NullHandler.class

+ArtistExpr.class    Or.class

+Constant.class      Track.class

+DB.class            TrackExpr.class

+% <b>cd classes</b>

+% <b>jar -uf ../lib/my-handler.jar *.class</b>

+% <b>cd ..</b>

+% <b>jar -tf lib/my-handler.jar</b>

+META-INF/

+META-INF/MANIFEST.MF

+NullHandler.class

+Album.class

+AlbumExpr.class

+And.class

+Artist.class

+ArtistExpr.class

+Constant.class

+DB.class

+Expr.class

+MusicHandler.class

+Not.class

+Or.class

+Track.class

+TrackExpr.class</source>

+

+      <p>We also need to update the <code>$PS_HOME/bin/ps</code>

+	script.  Currently, it's instantiating just the

+	<code>NullHandler</code>; we need it to instantiate the

+	<code>MusicHandler</code> too.  Stop any currently running

+	profile server by pressing CTRL+C (or whatever your interrupt

+	key is) in the window running the server.  Then edit the

+	script so it reads as follows:

+      </p>

+

+      <source>#!/bin/sh

+exec java -Djava.ext.dirs=$PS_HOME/lib \

+    -Dhandlers=NullHandler,MusicHandler \

+    jpl.eda.ExecServer \

+    jpl.eda.profile.rmi.ProfileServiceImpl \

+    urn:eda:rmi:MyProfileService</source>

+

+      <p>Now the profile server will delegate to <em>two</em>

+	handlers: the <code>NullHandler</code> and the

+	<code>MusicHandler</code>.  With more than one handler, the

+	OODT framework calls each one in turn and collects all of the

+	matching profiles together to return to the

+	<code>ProfileClient</code>.  (Of course, the

+	<code>NullHandler</code> never actually generates any matching

+	profiles.)

+      </p>

+    </section>

+

+    <section name="Querying the Profile Server">

+      <p>Start the profile server by running

+	<code>$PS_HOME/bin/ps</code> in one window (presumably the RMI

+	registry is still running in another window).  In yet another

+	window, we'll run our <code>$PS_HOME/bin/pc</code> script to

+	query the profile server:

+      </p>

+

+      <source>% <b>$PS_HOME/bin/pc 'artist = Delerium

+ AND album != Poem OR artist = Bach'</b><![CDATA[

+Object context ready; delegating to:

+[jpl.eda.object.jndi.RMIContext@dec8b3]

+[<?xml version="1.0" encoding="UTF-8"?>

+<profile><profAttributes><profId>urn:sk:tr91BC.mp3</profId>...]]></source>

+

+      <p>Whoa!  There's a huge load of XML!  In fact what the

+	<code>ProfileClient</code> is printing is a

+	<code>java.util.List</code> of profiles in XML format, each

+	separated by a comma, and the whole list in square brackets.

+	If you search this output carefully, though, you can pick out

+	the <code>&lt;Title&gt;</code> elements and see indeed that

+	we've got six matching tracks:

+      </p>

+

+      <ul>

+	<li>Brandenburg Concerto #1</li>

+	<li>Brandenburg Concerto #2</li>

+	<li>Brandenburg Concerto #3</li>

+	<li>Brandenburg Concerto #4</li>

+	<li>Brandenburg Concerto #5</li>

+	<li>Brandenburg Concerto #6</li>

+	<li>Flowers Become Screens</li>

+	<li>Metaphor</li>

+      </ul>

+

+      <p>Sure enough, this matches the XMLQuery query language

+	expression we passed in: There are tracks by Delerium but

+	<em>not</em> from the Poem album, and there are all the tracks

+	by Bach.

+      </p>

+    </section>

+

+    <section name='Conclusion'>

+      <p>In this long tutorial we developed a real profile handler

+	that answered queries by transforming them from postfix stacks

+	into expression trees and using those trees to query an

+	in-memory database made of Java objects.  We then described

+	matching data by creating <code>Profile</code>s.

+      </p>

+

+      <p>You might be thinking that this seems like a lot of work, and

+	there might be some easier ways to go.  You could use the

+	<code>LightweightProfileHandler</code> for resources that

+	never change, but only if you don't have too many of them and

+	don't mind managing potentially large XML documents.  You

+	could choose to use unparsed XMLQuery expressions and instead

+	make the user query in the same language as your data system,

+	obviating the need for complex expression trees.

+      </p>

+

+      <p>However, with the tools presented in this tutorial, you could

+	adapt the expression tree code to generating system-specific

+	queries, and describe those results with as much or as little

+	detail as necessary.

+      </p>

+

+      <p>Happy profiling!</p>

+    </section>

+  </body>

+</document>

diff --git a/0.8.1-rc1/profile/src/site/xdoc/handler/index.xml b/0.8.1-rc1/profile/src/site/xdoc/handler/index.xml
new file mode 100755
index 0000000..ba02b14
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/xdoc/handler/index.xml
@@ -0,0 +1,595 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!--

+Licensed to the Apache Software Foundation (ASF) under one or more contributor

+license agreements.  See the NOTICE.txt 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.

+-->

+<document>

+  <properties>

+    <title>Developing a Profile Handler</title>

+    <author email="Sean.Kelly@jpl.nasa.gov">Sean Kelly</author>

+  </properties>

+  <!-- Shift - Nexus Overload -->

+  <body>

+    <section name="Developing a Profile Handler">

+      <p>Profiles describe resources. But where do profiles come from?

+	From profile handlers. Profile handlers are interchangeable

+	components of a profile server that accept queries for

+	profiles and return matching profiles. Profile handlers take a

+	static or a dynamic collection of information and serve an

+	equivalent set of profiles. Developing a new profile handler

+	is as simple as writing a Java class that implements a

+	specific interface or two.

+      </p>

+

+      <p>If you're not already familiar with the <code>XMLQuery</code>

+	class, go ahead and <a href="/edm-query/tutorial/">take its

+	  tutorial now</a>.  We'll wait!

+      </p>

+    </section>

+

+    <section name="Introduction">

+      <p>Profile handlers handle queries for profiles.  They're the

+	interchangeable part of a profile server that you can develop

+	for special needs.  Profile servers delegate all incoming

+	requests to zero or more profile handlers, as shown in the

+	following class diagram:

+      </p>

+

+      <img src="../images/delegation.png" alt="Delegation model" />

+

+      <p>Developing, testing, and deploying a new profile handler

+	involves:

+      </p>

+      <ol>

+	<li>Creating a class that implements (however indirectly)

+	  the <code>jpl.eda.profile.handlers.ProfileHandler</code> interface.

+	</li>

+	<li>Creating a new process that runs either the RMI or

+	    CORBA <code>ProfileServiceImpl</code> class,

+	    specifying the name of your handler class.

+	</li>

+	<li>Starting the server and sending in queries.

+	</li>

+      </ol>

+      <p>This document describes each of these steps in detail.</p>

+    </section>

+

+    <section name="Writing the Handler Class">

+      <p>Writing the class that handles profile queries and delivers

+	profile results is easily the hardest part in developing a new

+	kind of profile server.  Profile servers' handlers can serve

+	profiles describing static resources, can synthesize profile

+	on the fly to describe resources, and can create profile

+	metadata for resources that change all the time.

+      </p>

+      

+      <p>Understanding the resources you're trying to describe with

+	profiles is the most important thing you can do before

+	beginning to write your profile handler:

+      </p>

+

+      <ul>

+	<li>Do you always have the same set of static resources?

+	  If so, you can write a static profile document to describe

+	  them and use the

+	  <code>LightweightProfileHandler</code>, thus

+	  avoiding having to write a new handler at all.

+	</li>

+	<li>Do you have resources that never change, but may add to or

+	  remove from that set?  If so, you can use the

+	  <code>OracleProfileImpl</code> handler which uses an Oracle

+	  database to store a set of profiles that you can update.

+	</li>

+	<li>Do you have resources that do change, or that come

+	  from a dynamic set of data?  If so, you'll have to write a

+	  handler.

+	</li>

+      </ul>

+

+      <subsection name="Choosing the Handler Interface to Implement">

+	<p>The OODT Framework provides two handler interfaces (one is

+	  an extension of the other):

+	</p>

+	<ul>

+	  <li><code>jpl.eda.profile.handlers.ProfileHandler</code>

+	      is the basic profile handler.  It defines methods for

+	    <em>handling</em> searches for profiles.

+	  </li>

+

+	  <li><code>jpl.eda.profile.handlers.ProfileManager</code> is an

+	    extension that not just <em>handles</em> profile queries

+	    but also <em>manages</em> the set of profiles maintained

+	    by the server, by providing methods for adding to,

+	    removing from, and updating the set of managed profiles.

+	  </li>

+	</ul>

+      

+	<p>For nearly all applications, the <code>ProfileHandler</code>

+	  interface is sufficient.  If you need to provide profile

+	  management capabilities, it still may be handy to start with

+	  the <code>ProfileHandler</code> interface, implement and test

+	  its methods, and <em>then</em> change to the

+	  <code>ProfileManager</code>.

+	</p>

+      </subsection>

+

+      <subsection name="The ProfileHandler Interface">

+	<p>The <code>ProfileHandler</code> interface is

+	  as follows:

+	</p>

+

+	<source>package jpl.eda.profile.handlers;

+

+import java.util.List;

+import jpl.eda.profile.Profile;

+import jpl.eda.profile.ProfileException;

+import jpl.eda.xmlquery.XMLQuery;

+

+public interface ProfileHandler {

+  List findProfiles(XMLQuery query) throws ProfileException;

+  Profile get(String profID) throws ProfileException;

+}</source>

+

+	<p>The two methods are described in detail below.</p>

+

+	<dl>

+	  <dt><code>findProfiles</code></dt>

+	  <dd>This method accepts a query in the form of an

+	    <code>XMLQuery</code> object and returns a

+	    Java <code>List</code> of

+	    <code>Profile</code> objects that match.  If

+	    there are no matches, this method must return an empty

+	    list.  If an error occurs, it should throw the

+	      <code>ProfileException</code>.

+

+	    <p>This is by far the most used and most important

+	      method, and really is the <i>raison

+	      d'etre</i> for profile servers.  It's

+	      what the OODT Framework uses to allow clients to ask

+	      your server for resources based on metadata .

+	    </p>

+	  </dd>

+	  <dt><code>get</code></dt>

+	  <dd>This method accepts the ID of a profile in the form

+	    of a Java <code>String</code> and returns

+	    either a <code>Profile</code> object with that

+	    ID or null if the ID is unknown.  This method enables a

+	    client to retrieve a profile using a priori knowledge of

+	    the profile's ID (perhaps from a previous search).

+	  </dd>

+	</dl>

+      </subsection>

+

+      <subsection name="The ProfileManager Interface">

+	<p>The <code>ProfileManager</code> interface

+	  builds on the <code>ProfileHandler</code>, and is

+	  listed below:

+	</p>

+	<source>package jpl.eda.profile.handlers;

+

+import java.util.Collection;

+import java.util.Iterator;

+import jpl.eda.profile.Profile;

+import jpl.eda.profile.ProfileException;

+import jpl.eda.xmlquery.XMLQuery;

+

+public interface ProfileManager extends ProfileHandler {

+  void add(Profile profile) throws ProfileException;

+  void addAll(Collection collection) throws ProfileException;

+  void clear() throws ProfileException;

+  boolean contains(Profile profile) throws ProfileException;

+  boolean containsAll(Collection collection) throws ProfileException;

+  Collection getAll() throws ProfileException;

+  boolean isEmpty() throws ProfileException;

+  Iterator iterator() throws ProfileException;

+  boolean remove(String profID, String version) throws ProfileException;

+  boolean remove(String profID) throws ProfileException;

+  int size() throws ProfileException;

+  void replace(Profile profile) throws ProfileException;

+}</source>

+

+	<p>If you choose to implement a profile manager, please see

+	  the API documentation for the

+	  <code>ProfileManager</code> class for the

+	  expectations of each method.

+	</p>

+      </subsection>

+    </section>

+

+    <section name="Our First Profile Handler">

+      <p>Although not terribly useful, a &#8220;null&#8221; profile

+	handler is a good example to start with because it is small and

+	will make sure your environment is in good working order before

+	proceeding to a real profile handler.

+      </p>

+      

+      <p>What's a &#8220;null&#8221; profile handler?  It's one that

+	serves no profiles.  That is, for any query with

+	<code>findProfiles</code> and any retrieval with

+	<code>get</code> it never returns any profiles.

+      </p>

+

+      <subsection name="Directory Layout">

+	<p>For these examples, we'll work on a kind of Unix system

+	  with a <code>csh</code> shell.  Other shell users or Windows

+	  users will need to adjust.  We'll also use the J2SDK

+	  command-line tools.  If you're using an Integrated

+	  Development Environment of some sort, please adjust

+	  accordingly.

+	</p>

+

+	<p>We'll create a "home" directory for our profile servers

+	  with subdirectories to hold specific components like source

+	  code, jar files, and scripts.  We'll call this home

+	  directory by an environment variable, <code>PS_HOME</code>

+	  (PS for Profile Server), so that scripts won't have to refer

+	  to things by relative paths:

+	</p>

+

+	<source>% <b>mkdir ps</b>

+% <b>cd ps</b>

+% <b>setenv PS_HOME `pwd`</b>

+% <b>mkdir bin classes lib src</b></source>

+      </subsection>

+

+      <subsection name="Source File">

+	<p>One of the easier parts is the source itself for the

+	  &#8216;null&#8217; profile handler.  Here it is:

+	</p>

+	<source>import java.util.Collections;

+import java.util.List;

+import jpl.eda.profile.Profile;

+import jpl.eda.profile.handlers.ProfileHandler;

+import jpl.eda.xmlquery.XMLQuery;

+

+public class NullHandler implements ProfileHandler {

+  public List findProfiles(XMLQuery query) {

+    return Collections.EMPTY_LIST;

+  }

+  public Profile get(String id) {

+    return null;

+  }

+}</source>

+

+	<p>Note that for every query, the

+	  <code>findProfiles</code> method returns an empty list

+	  (meaning that no profiles matched), and that for any retrieval

+	  the <code>get</code> method returns null, meaning that

+	  the handler believes there's no such profile.

+	</p>

+	<p>This class should be compiled into a file named

+	  <code>$PS_HOME/src/NullHandler.java</code>

+	  since it is a public class.

+	</p>

+

+	<p><em>Note:</em> Profile handler classes <em>must</em> be

+	  public <em>and</em> provide a no-arguments

+	  constructor.  You should retrieve any initialization

+	  settings through the System Properties or by other means

+	  specific to your profile handler.

+	</p>

+      </subsection>

+      

+      <subsection name="Compiling the Handler">

+	<p>Compiling this profile handler requires the following

+	  dependent components:

+	</p>

+

+	<ul>

+	  <li><a href="/grid-profile/">Profile Service</a>.  This

+	    defines the entire profile model, handler interfaces,

+	    servers, clients, and so forth.

+	  </li>

+	  <li><a href="/edm-query/">Query Expression</a>.  This

+	    defines the <code>XMLQuery</code> and related classes.

+	  </li>

+	</ul>

+

+	<p>Download the binary distributions of the above two packages

+	  and copy the jar file from each into the

+	  <code>$PS_HOME/lib</code> directory.  Then you can compile

+	  the <code>NullHandler.java</code> file.

+	</p>

+

+	<source>% <b>ls</b>

+bin   classes   lib    src

+% <b>ls -l lib</b>

+total 244

+-rw-r--r--  1 kelly  kelly   43879 28 Feb 07:05 edm-query-2.0.2.jar

+-rw-r--r--  1 kelly  kelly  201453 28 Feb 07:01 grid-profile-3.0.2.jar

+% <b>javac -extdirs lib -d classes src/NullHandler.java</b>

+% <b>ls -l classes</b>

+total 4

+-rw-r--r--  1 kelly  kelly  511 28 Feb 07:07 NullHandler.class

+% <b>jar -cf lib/my-handler.jar -C classes NullHandler.class</b>

+% <b>jar -tf lib/my-handler.jar</b>

+META-INF/

+META-INF/MANIFEST.MF

+NullHandler.class</source>

+

+	<p>We now have a new jar file, <code>my-handler.jar</code>

+	  which contains our &#8216;null&#8217; profile handler,

+	  compiled and ready to go.

+	</p>

+      </subsection>

+

+      <subsection name="Starting an RMI Registry">

+	<p>Clients access profile servers with an open-ended set of

+	  network protocols.  We currently have implementations for

+	  RMI and CORBA.  For this tutorial, we'll use RMI, since it's

+	  enormously less complex.  Clients of RMI systems first

+	  contact an RMI registry and look up a server object's

+	  network address.  The registry maintains mappings from a

+	  server object's name to its network address.  When servers

+	  start up, they register with the RMI registry so clients can

+	  later find them.

+	</p>

+

+	<p>To start an RMI Registry, you'll need the following components:</p>

+

+	<ul>

+	  <li><a href="/edm-commons/">EDM Common Components</a>.

+	    These are common utilities used by every OODT

+	    service.

+	  </li>

+	  <li><a href="/rmi-registry/">OODT RMI Registry</a>.  This is the

+	    actual RMI registry.</li>

+	</ul>

+

+	<p>Download each component's binary distribution, unpack each

+	  one, and take collect the jar files into the

+	  <code>lib</code> directory.  The RMI Registry will also need

+	  the <code>grid-profile</code> jar file, which we've already

+	  got.

+	</p>

+

+	<source>% <b>ls -l $PS_HOME/lib</b>

+total 404

+-rw-r--r--  1 kelly  kelly  149503 28 Feb 07:28 edm-commons-2.2.5.jar

+-rw-r--r--  1 kelly  kelly   43879 28 Feb 07:05 edm-query-2.0.2.jar

+-rw-r--r--  1 kelly  kelly  201453 28 Feb 07:01 grid-profile-3.0.2.jar

+-rw-r--r--  1 kelly  kelly     796 28 Feb 07:07 my-handler.jar

+-rw-r--r--  1 kelly  kelly    8055 28 Feb 07:28 rmi-registry-1.0.0.jar</source>

+

+	<p>Now all we need is a convenient script to start the RMI

+	  registry.  We'll call it <code>rmi-reg</code> and stick it

+	  in the <code>bin</code> directory.  Here's the

+	  <code>rmi-reg</code> script:</p>

+

+	<source>#!/bin/sh

+exec java -Djava.ext.dirs=$PS_HOME/lib \

+    gov.nasa.jpl.oodt.rmi.RMIRegistry</source>

+

+	<p>This script tells the Java virtual machine to find

+	  extension jars in the directory <code>$PS_HOME/lib</code>.  It

+	  then says that the main class to execute is

+	  <code>gov.nasa.jpl.oodt.rmi.RMIRegistry</code>.

+	</p>

+

+	<p>Go ahead and make this script executable and start the RMI

+	  Registry. In another window (with the appropriate setting of

+	  <code>PS_HOME</code>), run

+	  <code>$PS_HOME/bin/rmi-reg</code>.  You should see output

+	  similar to the following:

+	</p>

+

+	<source>% <b>chmod 755 $PS_HOME/bin/rmi-reg</b>

+% <b>$PS_HOME/bin/rmi-reg</b>

+Mon Feb 28 07:30:13 CST 2005: no objects registered</source>

+

+	<p>The RMI Registry is now running.  Every two minutes it will

+	  display an update of all registered objects.  Naturally, we

+	  don't have any profile service running right now, so it will

+	  say <code>no objects registered</code>.  Go ahead and ignore

+	  this window for now.  It's time to start our profile server.

+	</p>

+      </subsection>

+

+      <subsection name="Starting the Profile Server">

+	<p>With our handler compiled and our RMI registry running,

+	  we're ready to start our profile server.  As said before,

+	  profile servers delegate to zero or more profile handlers to

+	  actually handle all incoming requests.  You tell the profile

+	  server what handlers to instantiate by naming their classes

+	  in a system property.  That property is called

+	  <code>handlers</code>, and its value is a comma-separated

+	  list of fully qualified class names, including the package

+	  name prefixes.  Since our <code>NullHandler</code> is just

+	  in the default package, <code>NullHandler</code> <em>is</em>

+	  its fully-qualified class name.

+	</p>

+

+	<p>Profile server processes require the following components

+	  in addition to the ones we've downloaded so far:</p>

+

+	<ul>

+	  <li><a href="http://ws.apache.org/xmlrpc">Apache

+	      XML-RPC</a>.  This is used internally by OODT services.

+	    Download version 1.1, not a later version!  If you prefer,

+	    you can <a

+	      href="http://ibiblio.org/maven/xmlrpc/jars/xmlrpc-1.1.jar">fetch

+	      the jar file directly</a>.

+	  </li>

+

+	  <li><a href="http://jena.sourceforge.net/">Jena Semantic Web

+	      Framework for Java</a>.  This is used by the classes

+	      that represent profiles.  You'll need version 1.6.1 You

+	      can also <a

+	      href="http://oodt.jpl.nasa.gov/download/public/Jena/jars/jena-1.6.1.jar">fetch

+	      the jar file directly</a>.

+	  </li>

+	</ul>

+

+	<p>Copy these two other jars to the <code>$PS_HOME/lib</code>

+	  directory.  You should now have seven jars there:

+	</p>

+

+	<source>% <b>ls -l $PS_HOME/lib</b>

+total 1580

+-rw-r--r--  1 kelly  kelly   149503 28 Feb 07:28 edm-commons-2.2.5.jar

+-rw-r--r--  1 kelly  kelly    43879 28 Feb 07:05 edm-query-2.0.2.jar

+-rw-r--r--  1 kelly  kelly   201453 28 Feb 07:01 grid-profile-3.0.2.jar

+-rw-r--r--  1 kelly  kelly  1144107 28 Feb 09:23 jena-1.6.1.jar

+-rw-r--r--  1 kelly  kelly      796 28 Feb 07:07 my-handler.jar

+-rw-r--r--  1 kelly  kelly     8055 28 Feb 07:28 rmi-registry-1.0.0.jar

+-rw-r--r--  1 kelly  kelly    53978 28 Feb 09:20 xmlrpc-1.1.jar</source>

+

+	<p>Now, create a second shell script to make starting the

+	  profile server convenient and call it

+	  <code>$PS_HOME/bin/ps</code>.  It should look like this:

+	</p>

+

+	<source>#!/bin/sh

+exec java -Djava.ext.dirs=$PS_HOME/lib \

+    -Dhandlers=NullHandler \

+    jpl.eda.ExecServer \

+    jpl.eda.profile.rmi.ProfileServiceImpl \

+    urn:eda:rmi:MyProfileService</source>

+

+	<p>Make the script executable and start the profile server:</p>

+

+	<source>% <b>chmod 755 $PS_HOME/bin/ps</b>

+% <b>$PS_HOME/bin/ps</b>

+Object context ready; delegating to: [jpl.eda.object.jndi.RMIContext@dec8b3]</source>

+

+	<p>The profile server will start, check its

+	  <code>handlers</code> property, and create an object of each

+	  class named by it.  Then it'll register itself with the RMI

+	  registry and wait for requests to come in from profile clients.

+	</p>

+

+      </subsection>

+

+      <subsection name="What's in a Name?">

+	<p>The profile server registers itself using a name provided

+	  on the command-line, in this case,

+	  <code>urn:eda:rmi:MyProfileService</code>.  Let's take apart

+	  the name and see how it works.

+	</p>

+

+	<p>If you're familiar with web standards, you can see that the

+	  name is a Uniform Resource Name (URN), since it starts with

+	  <code>urn:</code>.  The OODT Framework uses URNs to identify

+	  services and other objects.  The <code>eda:</code> tells

+	  that the name is part of the Enterprise Data Architecture

+	  (EDA) namespace.  (EDA was the name of a project related to

+	  OODT that was merged with OODT.  For now, just always use

+	  <code>eda:</code> in your URNs.)

+	</p>

+	

+	<p>Next comes <code>rmi:</code>.  This is a special flag for

+	  the OODT services that tells that we're using a name of an

+	  RMI-accessible object.  The OODT framework will know to use

+	  an RMI registry to register the server. 

+	</p>

+

+	<p>Finally is <code>MyProfileService</code>.  This is the

+	  actual name used in the RMI registry.  You can call your

+	  profile server anything you want.  For example, suppose you

+	  have three profile servers; one in the US, one in Canada,

+	  and one in Australia.  You might name them:

+	</p>

+

+	<ul>

+	  <li><code>urn:eda:rmi:US</code></li>

+	  <li><code>urn:eda:rmi:Canada</code></li>

+	  <li><code>urn:eda:rmi:Australia</code></li>

+	</ul>

+

+	<p>Or you might prefer to use ISO country codes.  Or you might

+	  name them according to the kinds of profiles they serve,

+	  such as <code>urn:eda:rmi:BiomarkerMetadata</code> or

+	  <code>urn:eda:rmi:BusniessForecastMetadata</code>.

+	</p>

+

+	<p>The RMI registry will happily re-assign a name if one's

+	  already in use, so when deploying your own profile (and

+	  other) servers, be sure to give each one a unique name.

+	</p>

+      </subsection>

+

+      <subsection name="Querying the Profile Server">

+	<p>To query a profile server, you use the

+	  <code>ProfileClient</code> class.  It provides methods to

+	  contact a named profile server, performing the lookup in the

+	  RMI registry, contacting the profile server, and passing in

+	  queries and profile retrievals.  The

+	  <code>ProfileClient</code> class is also an

+	  <em>executable</em> class, making it perfect for testing a

+	  new profile server from the command-line.

+	</p>

+

+	<p>Still, we'll make a script, called

+	  <code>$PS_HOME/bin/pc</code> (for "profile client") to

+	  execute it, though, to save from having to type hugely long

+	  Java command-lines:

+	</p>

+

+	<source>#!/bin/sh

+if [ $# -ne 1 ]; then

+   echo "Usage: `basename $0` &lt;query-expression&gt;" 1&gt;&amp;2

+   exit 1

+fi

+exec java -Djava.ext.dirs=$PS_HOME/lib \

+     jpl.eda.profile.ProfileClient \

+     urn:eda:rmi:MyProfileService \

+     "$1"</source>

+

+	<p>Make this script executable and then run it:</p>

+

+	<source>% <b>chmod 755 $PS_HOME/bin/pc</b>

+% <b>$PS_HOME/bin/pc "temperature = 37"</b>

+Object context ready; delegating to: [jpl.eda.object.jndi.RMIContext@dec8b3]

+[]</source>

+

+	<p>Although it may not look spetacular, this is a success!

+	  The two square brackets, <code>[]</code>, indicates the list

+	  of matching profiles to our query expression,

+	  <code>temperature = 37</code>.  In this case, there were no

+	  matches, which is exactly what we wanted.

+	</p>

+      </subsection>

+    </section>

+

+    <section name="Conclusion">

+      <p>The Null Profile Server made sure our development

+	environment worked from end to end for creating, deploying, and

+	testing a profile handler.  Now you're ready to implement a real

+	profile handler:

+      </p>

+

+      <ul>

+	<li>Instead of returning an empty list, create a

+	    <code>Profile</code> object and return it as a

+	    singleton list.  See the API documentation for

+	    <code>Profile</code> as well as other articles

+	    for manipulating this class.

+	</li>

+	<li>Analyze the methods of the

+	  <code>XMLQuery</code> class to determine the

+	  query passed in from the user.  Use that information to

+	  synthesize the correct <code>Profile</code>

+	  object.  See the API documentation for class

+	  <code>XMLQuery</code> for more information.

+	</li>

+	<li>Connecting to an external data source (such as the

+	    local filesystem or a database), synthesize appropriate

+	  profiles in response to queries and profile retrieval with

+	  the <code>get</code> method.

+	</li>

+      </ul>

+    </section>

+  </body>

+</document>

diff --git a/0.8.1-rc1/profile/src/site/xdoc/info/index.xml b/0.8.1-rc1/profile/src/site/xdoc/info/index.xml
new file mode 100755
index 0000000..fe44c1f
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/xdoc/info/index.xml
@@ -0,0 +1,848 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!--

+Licensed to the Apache Software Foundation (ASF) under one or more contributor

+license agreements.  See the NOTICE.txt 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.

+-->

+<document>

+  <properties>

+    <title>Information Captured in a Profile</title>

+    <author email="Sean.Kelly@jpl.nasa.gov">Sean Kelly</author>

+  </properties>

+  <!-- Infected Mushroom - Deeply Disturbed -->

+  <body>

+    <section name="Information Captured in a Profile">

+

+      <p>A profile serves as a generic template for describing the

+	characteristics of a resource. The question posed to a profile

+	generally takes the form of, "Can you answer <var>X</var>?" or

+	"Do you know the location of <var>X</var>?" where <var>X</var>

+	is some resource being sought. The more fully a profile describes

+	a particular resource, the better the profile can be used to

+	determine if the resource has the information in <var>X</var>.

+      </p>

+

+    </section>

+

+    <section name="Information and Organization">

+      <p>Profile servers capture three kinds of information:</p>

+

+      <ul>

+	<li><b>Resource Attributes</b> <p>Resource attributes are

+	  metadata about the resource's <em>inception</em>.  These

+	  attributes include the creator of the resource, in what

+	  language it exists, when it was created, and so forth.

+	  These attributes are based on the work of the <a

+	  href="http://www.dmci.org/">Dublin Core Metadata Initiative</a>.

+	  </p>

+	</li>

+

+	<li><b>Profile Elements</b> <p>Profile elements are metadata

+	    about the resource's <em>composition</em>.  These tell you

+	    about the morphology of the resource, such as data types

+	    captured within in, minimum and maximum values, synonymous

+	    elements, and so forth.  These attributes are based on <a

+	    href="http://metadata-standards.org/11179/">ISO/IEC 11179

+	    standards</a>.

+	  </p>

+	</li>

+

+	<li><b>Profile Attributes</b> <p>Profile attributes are

+	    metadata about the <em>profile itself</em>, such as who

+	    made it, whether it's classified, revision notes, and so

+	    forth.  It also has a unique identifying <a

+	    href="http://www.alvestrand.no/objectid/index.html">Object

+	    Identifier (OID)</a>.

+	  </p>

+	</li>

+      </ul>

+

+      <p>The following class diagram shows the relationship between

+	the different parts of a profile:

+      </p>

+

+      <img src="../images/class.png" alt="Class diagram"/>

+

+      <p>While this diagram shows the Java field names and Java

+	classes, the relationship applies to profiles whether they

+	exist as Java objects, as RDF documents, or as XML documents

+	in the profile vocabulary.

+      </p>

+    </section>

+

+    <section name="Inception Metadata">

+      <p>Profiles, whether expressed in RDF or in their own XML

+	vocabulary, have a section for capturing information about the

+	resource's inception.  This includes information about when the

+	resource was created, who created it, in what language it

+	exists, and so forth.  Profiles use the element set recommended

+	by the Dublin Core Metadata Initiative (DCMI) set in order to

+	describe the inception of a resource, with some extensions.

+      </p>

+

+      <p>Collectively, these metadata are called the <i>resource

+	attributes</i> or <code>resAttributes</code> of the profile.

+	Every profile has one and only one set of

+	<code>resAttributes</code>.  The metadata elements within the

+	<code>resAttributes</code> are defined in this section.

+      </p>

+

+      <subsection name="Identifier">

+	<p>As defined by the DCMI, the <code>Identifier</code> of a

+	  resource is some unambiguous way to identify the resource.

+	  In the profile implementation, one and only one

+	  <code>Identifier</code> is <span

+	  class="emphasis"><em>required</em></span>.

+	</p>

+

+	<p>It's highly recommended that <code>Identifier</code>s and

+	  <code>resLocation</code>s (see below) be URIs, but there's

+	  no software enforcment for this <em>unless you convert a

+	  Java profile to RDF</em> with the <code>toRDF</code> method.

+	  Identifiers should be more like URNs, while resLocations

+	  should be more like URLs.

+	</p>

+      </subsection>

+      <subsection name="Title">

+	<p>The <code>Title</code> names the resource, and is the name by

+	  which the resource is formally known.  The <code>Title</code> is

+	  optional; if present, it may occur only once in a profile.

+	</p>

+      </subsection>

+      <subsection name="Format">

+	<p>The <code>Format</code> indicates the manifestation of the

+	  resource.  You can specify any number of <code>Format</code>s in

+	  a profile.

+	</p>

+      </subsection>

+      <subsection name="Description">

+	<p>The <code>Description</code> element contains a free text

+	  account of the content of the resource.  It's optional in a

+	  profile; if present, it may occur only once.

+	</p>

+      </subsection>

+      <subsection name="Creator">

+	<p>Zero or more <code>Creator</code>s may be specified in a

+	  profile.  <code>Creator</code>s contain the name of people or

+	  organizations that created the resource.

+	</p>

+      </subsection>

+      <subsection name="Subject">

+	<p>You can list zero or more <code>Subject</code>s in a profile.

+	  The purpose of the <code>Subject</code> elements is to contain a

+	  keywords that describe the resource, usually selected from a

+	  controlled vocabulary.

+	</p>

+      </subsection>

+      <subsection name="Publisher">

+	<p>Any number of <code>Publisher</code> elements may appear in a

+	  profile.  They contain the organization responsible for

+	  making the resource available.

+	</p>

+      </subsection>

+      <subsection name="Contributor">

+	<p>A <code>Contributor</code> is a person or organization

+	  providing auxilliary work towards the resource's creation.

+	  Any number of <code>Contributor</code>s may be listed in a

+	  profile.

+	</p>

+      </subsection>

+      <subsection name="Date">

+	<p><code>Date</code> elements indicate the times in history when

+	  the resource was created.  You can include any number of

+	  <code>Date</code>s in a profile, although typically you'll

+	  specify just one if you speciy any at all.

+	</p>

+      </subsection>

+      <subsection name="Type">

+	<p>The <code>Type</code> element indicates the nature of the

+	  content of the resource, such as "fiction" for a work of

+	  fiction or "image" for a dataset rendered graphically.  You

+	  can include any number of <code>Type</code>s in a profile.

+	</p>

+      </subsection>

+      <subsection name="Source">

+	<p>When a resource is derived others, the <code>Source</code>

+	  element should indicate the <code>Identifier</code>s of the

+	  referenced resources.  You can specify any number of

+	  <code>Source</code>s in a profile.

+	</p>

+      </subsection>

+      <subsection name="Language">

+	<p>For resources that contain natural language content, the

+	  <code>Language</code> element indicates the languages in use.

+	  You can specify this element any number of times in a

+	  profile.

+      	</p>

+      </subsection>

+      <subsection name="Relation">

+	<p>When a resource is related to others, you can specify the

+	  <code>Identifier</code>s of the related resources using zero or

+	  more <code>Relation</code> elements.

+      	</p>

+      </subsection>

+      <subsection name="Coverage">

+	<p>For resources that cover a space or time or jurisdiction,

+	  use the <code>Coverage</code> element to indicate such coverage.

+	  This element may be listed any number of times in a profile,

+	  and its content should come from a controlled vocabulary.

+	  For resources with specific coordinate systems, it's better

+	  to use profile elements, described below.

+      	</p>

+      </subsection>

+      <subsection name="Rights">

+	<p>Copyright, ownership, redistribution, use, and other legal

+	  issues may exist for a resource.  When that happens, use the

+	  <code>Rights</code> element to list the rights management

+	  information.  You can list zero or more <code>Rights</code>

+	  elements in a profile.

+	</p>

+	<p><em>Note:</em> The official name of element for is plural

+	  <code>Rights</code>; this is inconsistent with the other

+	  metadata elements, but is consistent with the DCMI.

+	</p>

+      </subsection>

+      <subsection name="resContext">

+	<p>The <code>resContext</code> element identifies the application

+	  environment or discipline within which the resource

+	  originates and is derived from a taxonomy of scientific

+	  disciplines.  This element is required in a profile and may

+	  occur multiple times.

+	</p>

+

+	<p>As an example, a <code>resContext</code> of

+	  <code>NASA.PDS.Geoscience</code> tells that the resource is

+	  associated with the Geoscience node of the Planetary Data

+	  System.

+	</p>

+      </subsection>

+      <subsection name="resAggregation">

+	<p>The <code>resAggregation</code> element indicates the

+	  aggregative structure of the resource.  It tells you what

+	  you'll get if you retrieve the resource: a granule, a

+	  dataset, or a collection of datasets.  The legal values of

+	  this optional elements are:

+	</p>

+

+	<ul>

+	  <li><code>granule</code>, meaning the resource is a single

+	    product

+	  </li>

+	  <li><code>dataSet</code>, meaning the resource is a set of

+	    products

+	  </li>

+	  

+	  <li><code>dataSetCollection</code>, meaning the resource is

+	    collection of datasets

+	  </li>

+	</ul>

+

+	<p>The <code>resAggregation</code> element is optional; however,

+	  if specified, it may appear in a profile only once.

+      	</p>

+      </subsection>

+      <subsection name="resClass">

+	<p>The <code>resClass</code> element identifies the kind of the

+	  resource within a taxonomy of resource types.  It's a

+	  <em>required</em> element that is used by the OODT Framework

+	  to determine how to treat the profile as well as the

+	  resource named by the profile.

+	</p>

+

+	<p>For example, a <code>resClass</code> of

+	  <code>system.productServer</code> indicates that the resource is

+	  an OODT product server.  A query that matches this profile

+	  means that if the same query were given to the identified

+	  product server, it would yield a result.  A

+	  <code>resClass</code> of <code>system.profileServer</code> means the

+	  resource is a profile server.  That means that while the

+	  current profile server may or may not provide a matching

+	  profile, another profile server might, forming an implicit

+	  digraph of profile servers.  Other valid <code>resClass</code>

+	  values include <code>data.granule</code>, <code>data.dataSet</code>,

+	  and <code>application.interface</code>.

+      	</p>

+      </subsection>

+

+      <subsection name="resLocation">

+	<p>Zero or more <code>resLocation</code> elements may appear in

+	  a profile.  They tell where the resource is located, easily

+	  the most important part of the profile.  Because this

+	  element may appear several times, all locations should be

+	  considered valid; the application may pick the one that's

+	  most convenient.  The <code>resLocation</code> may also appear zero

+	  times.  This means that the profile indicates solely that

+	  the resource existswhere is unknown.

+	</p>

+

+	<p>The interpretation of the resLocation is as a URI.  For

+	  example, a <code>resClass</code> of

+	  <code>system.productServer</code> or

+	  <code>system.profileServer</code> means that the

+	  <code>resLocation</code> indicates an URN to a software object

+	  name.  Querying that object will yield either the desired

+	  result (for product servers) or more matching profiles (for

+	  profile servers).  For a resClass of <code>data.granule</code>

+	  or <code>data.dataSet</code>, the <code>resLocation</code> is an URL

+	  to the granule or dataset.

+	</p>

+      </subsection>

+    </section>

+

+    <section name="Composition Metadata">

+      <p>The most interesting part of a profile is in the metadata

+	that describes the composition of the resource that the

+	profile profiles.  The composition metadata is what enables a

+	profile server to tell if a particular resource can answer a

+	query.

+      </p>

+

+      <p>The composition metadata is based on the data element

+	description standards in ISO/IEC standard 11179.  They are the

+	<i>profile elements</i> or <code>profElement</code>s of a profile.

+	Every profile may have zero or more <code>profElement</code>s, the

+	components of which are discussed in this section.

+      </p>

+

+      <subsection name="elemId">

+	<p>The <code>elemId</code> is an optional universally unique

+	  identifier applied to the element.

+      	</p>

+      </subsection>

+      <subsection name="elemName">

+	<p>The <code>elemName</code> is the <em>required</em> name of the

+	  profile element.  It serves as the title role of one of the

+	  components of the resource.

+      	</p>

+      </subsection>

+      <subsection name="elemDesc">

+	<p>The <code>elemDesc</code> is the description of the profile

+	  element.  Although the title may often be enough to identify

+	  the purpose of the profile element, the description should

+	  be used to provide any further, free-text information that

+	  may be of importance to analysts and profile administrators.

+	  The description is optional.

+      	</p>

+      </subsection>

+      <subsection name="elemType">

+	<p>The <code>elemType</code> indicates the type of data

+	  represented in the profile element, synonymous to the

+	  ISO/IEC 11179 <code>Datatype</code> attribute.  The permissible

+	  values are:

+	</p>

+

+	<ul>

+	  <li><code>boolean</code></li>

+	  <li><code>character</code></li>

+	  <li><code>date_time</code></li>

+	  <li><code>enumerated</code></li>

+	  <li><code>integer</code></li>

+	  <li><code>ordinal</code></li>

+	  <li><code>rational</code></li>

+	  <li><code>scaled</code></li>

+	  <li><code>real</code></li>

+	  <li><code>complex</code></li>

+	  <li><code>state</code></li>

+	  <li><code>void</code></li>

+	</ul>

+

+	<p>This element is optional within a profile element.  When

+	  it's not present, the profile element merely indicates that

+	  the resource's content possesses the attribute, but more is

+	  not known.

+      	</p>

+      </subsection>

+

+      <subsection name="elemUnit">

+	<p>The <code>elemUnit</code> indicates the units associated with

+	  the values of the data element. This element is synonymous

+	  to the ISO/IEC 11179 attribute <code>unit.of.quantity</code>.

+	  Values for this optional element should be selected from

+	  standardized tables of units.

+      	</p>

+      </subsection>

+

+      <subsection name="elemEnumFlag, elemValue, elemMinValue, and elemMaxValue">

+	<p>The <code>elemEnumFlag</code> tells how possible values of the

+	  profile element are specified.  It works with the

+	  <code>elemValue</code>, <code>elemMinValue</code>, and

+	  <code>elemMaxValue</code> elements:

+	</p>

+

+	<ul>

+	  <li>If the <code>elemEnumFlag</code>'s value is <code>T</code> and

+	    one or more <code>elemValue</code>s appear, then the values

+	    listed are the valid values of the element.

+	  </li>

+	  <li>If the value is <code>F</code>, then a closed range of

+	    values bounded by the profile's <code>elemMinValue</code> and

+	    <code>elemMaxValue</code> elements indicates the valid values.

+	  </li>

+	  <li>If the value is <code>T</code> but no <code>elemValue</code>s

+	    appear, then it means that any value is a valid

+	    value for the resource.

+	  </li>

+	</ul>

+

+      </subsection>

+

+      <subsection name="elemSynonym">

+	<p>Often, a characteristic of a resource will go by several

+	  names, especially between scientific disciplines.  What one

+	  person may call <i>latitude</i>, another may call <i>x

+	    coordinate</i>, for example.  By specifiyng synonyms for a

+	  profile element, you can assist in automatic correlation of

+	  results and cross-disciplinary discovery.

+	</p>

+

+	<p>The <code>elemSynonym</code> provides a way to do just that.

+	  Zero or more <code>elemSynonym</code>s may appear in a profile

+	  element.  The values of this element are names from data

+	  dictionaries other than the discipline data dictionary

+	  hosting the profile.

+      	</p>

+      </subsection>

+      <subsection name="elemObligation">

+	<p>The <code>elemObligation</code> tells whether the data element

+	  is required to always or sometimes be present. This element

+	  is synonymous to the ISO/IEC 11179 attribute

+	  <code>Obligation</code>, and is optional within a profile

+	  element.

+	</p>

+

+	<p>The legal values for this element are <code>Required</code> and

+	  <code>Optional</code>, with the obvious meanings.

+      	</p>

+      </subsection>

+      <subsection name="elemComment">

+	<p>The <code>elemComment</code> field provides a remark concerning

+	  the application of the data element.  This element is

+	  synonymous to the ISO/IEC 11179 attribute <code>Comment</code>,

+	  and is optional within a profile element.

+	</p>

+      </subsection>

+    </section>

+

+    <section name="Metadata about the Profile">

+      <p>For a profile server to manage a set of profiles, it's

+	necessary to have metadata contained within the profile that

+	describes the profile itself.  This metadata, collectively

+	called the profile attributes, or <code>profAttributes</code>,

+	serves that purpose.

+      </p>

+

+      <p>Most of the elements within the <code>profAttributes</code> are

+	optional.  This sections describes each of them.

+      </p>

+

+      <subsection name="profId">

+	<p>The <code>profId</code> serves to give a unique identifier to

+	  the profile.  It should be expressed as a URI, and often as

+	  an URN.

+      	</p>

+      </subsection>

+      <subsection name="profVersion">

+	<p>The <code>profVersion</code> identifies the version number of

+	  the profile.

+      	</p>

+      </subsection>

+      <subsection name="profType">

+	<p>The <code>profType</code> identifies the type of the profile.

+	  The type that typically appears here is <code>profile</code>,

+	  meaning the profile is a profile (obviously).

+	</p>

+

+	<p>Another type that can be here is <code>dataDict</code>, which

+	  indicates that the profile doesn't describe a resource, but

+	  instead is a data dictionary for other profiles.  Such a

+	  profile's composition elements name the expected profile

+	  elements and ranges of valid valuese that will appear in

+	  other profiles.  The <code>profDataDictId</code> element

+	  identifies the profile serving as its data dictionary.

+	</p>

+      </subsection>

+      <subsection name="profStatusId">

+	<p>The <code>profStatusId</code> identifies the state of the

+	  profile.  Profiles may be either <code>active</code> or

+	  <code>inactive</code>.  An inactive profile is likely maintained

+	  for historical or exemplary reasons but is otherwise not

+	  currently used for searches or resource descriptions.

+	</p>

+      </subsection>

+      <subsection name="profSecurityType">

+	<p>The <code>profSecurityType</code> identifies whether the

+	  information contained in the profile may be of a sensitive

+	  nature.  Any string is valid here as the current OODT

+	  software does not use this field.

+	</p>

+      </subsection>

+      <subsection name="profParentId">

+	<p>The <code>profParentId</code> optionally identifies the URI of

+	  the parent of this profile.  Profiles may be arranged

+	  hierarchically in a singly rooted tree in a forest.

+	</p>

+      </subsection>

+      <subsection name="profChildId">

+	<p>The <code>profChildId</code>

+	  identifies zero or more children (by duplicating the element) of

+	  this profile.

+	</p>

+      </subsection>

+      <subsection name="profRegAuthority">

+	<p>The <code>profRegAuthority</code>

+	  names the registration authority responsible for authoring and

+	  maintaining the profile.

+	</p>

+      </subsection>

+      <subsection name="profRevisionNote">

+	<p>The <code>profRevisionNote</code> appears zero or more times in

+	  the profile to describe changes made to it over time.  The

+	  notes are free form text, and each element is ordered from

+	  newest to oldest note.

+	</p>

+      </subsection>

+      <subsection name="profDataDictId">

+	<p>The <code>profDataDictId</code>

+	  identifies the profile providing a data dictionary to the

+	  current profile.

+	</p>

+      </subsection>

+    </section>

+

+    <section name="Describing Resources">

+      <p>Let's take a look at how profiles would describe resources by

+	looking at an example set of scientific data.  Suppose you

+	archive high temperature data for your weather service; this

+	data comes in the form of tables of latitude/longitude

+	locations and the high temperature recorded at each point.

+	Since you're archiving daily high temperatures, there's one

+	table per day, so each day's table is a discrete resource.

+	Let's say you've got just three days of data so far, though,

+	and it looks like this (to keep things simple).

+      </p>

+

+      <table>

+	<thead>

+	  <tr>

+	    <th>Day Number</th> 

+	    <th>Lat</th>

+	    <th>Lon</th>

+	    <th>High Temp</th>

+	  </tr>

+	</thead>

+	<tbody>

+	  <tr><td rowspan="3">1</td><td>104.1</td><td>39.2</td><td>26.5</td></tr>

+	  <tr><td>110.3</td><td>42.4</td><td>29.9</td></tr>

+	  <tr><td>121.5</td><td>45.6</td><td>23.3</td></tr>

+

+	  <tr><td rowspan="3">2</td><td>104.1</td><td>39.2</td><td>31.5</td></tr>

+	  <tr><td>110.3</td><td>42.4</td><td>30.9</td></tr>

+	  <tr><td>121.5</td><td>45.6</td><td>27.5</td></tr>

+

+	  <tr><td rowspan="3">2</td><td>104.1</td><td>39.2</td><td>20.8</td></tr>

+	  <tr><td>110.3</td><td>42.4</td><td>19.5</td></tr>

+	</tbody>

+      </table>

+

+      <p>(On day #3, vandals destroyed the weather sensor station at

+	(121.5, 45.6), so there are only two measurements that day.)

+      </p>

+

+      <p>To make profiles for each day's of data, let's gather some

+	data that will be common to all of them.  First, say the

+	weather service's OID is 2.6.1.9, and for all collected data

+	the weather service has reserved an OID 2.6.1.9.2, high

+	temperature measurements 2.6.1.9.2.1.  They choose to make a

+	URI for each dataset,

+	<code>urn:weather:data:highs:<var>day-number</var></code>

+	where <var>day-number</var> is the day number of the data.

+	The official creator for all this data will be "Weather

+	Service", under subject keywords "weather", "temperatures",

+	and "measurements".  They'll also make the data tables

+	accessible as web documents in MIME format

+	<code>text/tab-separated-values</code> at the address

+	<code>http://weather.gov/data/highs/<var>day-number</var>.txt</code>.

+      </p>

+

+      <p>Here, then, is the profile for the day 1:</p>

+

+      <source><![CDATA[<profile>

+  <profAttributes>

+    <profId>2.6.1.9.2.1.1</profId>

+    <profType>profile</profType>

+    <profStatusId>active</profStatusId>

+  </profAttributes>

+  <resAttributes>

+    <Identifier>urn:weather:data:highs:1</Identifier>

+    <Title>High Temperatures - Day 1</Title>

+    <Format>text/tab-separated-values</Format>

+    <Creator>Weather Service</Creator>

+    <Subject>weather</Subject>

+    <Subject>temperatures</Subject>

+    <Subject>measurements</Subject>

+    <resContext>NOAA.NWS.Data</resContext>

+    <resClass>data.granule</resClass>

+    <resLocation>http://weather.gov/data/highs/1.txt</resLocation>

+  </resAttributes>

+  <profElement>

+    <elemName>latitude</elemName>

+    <elemType>real</elemType>

+    <elemUnit>degree</elemUnit>

+    <elemEnumFlag>F</elemEnumFlag>

+    <elemMinValue>104.1</elemMinValue>

+    <elemMaxValue>121.5</elemMaxValue>

+  </profElement>

+  <profElement>

+    <elemName>longitude</elemName>

+    <elemType>real</elemType>

+    <elemUnit>degree</elemUnit>

+    <elemEnumFlag>F</elemEnumFlag>

+    <elemMinValue>39.2</elemMinValue>

+    <elemMaxValue>45.6</elemMaxValue>

+  </profElement>

+  <profElement>

+    <elemName>temperature</elemName>

+    <elemType>real</elemType>

+    <elemUnit>celsius</elemUnit>

+    <elemEnumFlag>F</elemEnumFlag>

+    <elemMinValue>23.3</elemMinValue>

+    <elemMaxValue>29.9</elemMaxValue>

+  </profElement>

+</profile>]]></source>

+

+      <p>Someone searching for a high temperature that exceeded 25

+	degrees, for example, would find this as a matching

+	resource, as the <code>elemMinValue</code> for

+	<code>temperature</code> is 23.3, and 25 is over that.

+      </p>

+

+      <p>Here are all three profiles in one document:</p>

+

+      <source><![CDATA[<profiles>

+  <profile>

+    <profAttributes>

+      <profId>2.6.1.9.2.1.1</profId>

+      <profType>profile</profType>

+      <profStatusId>active</profStatusId>

+    </profAttributes>

+    <resAttributes>

+      <Identifier>urn:weather:data:highs:1</Identifier>

+      <Title>High Temperatures - Day 1</Title>

+      <Format>text/tab-separated-values</Format>

+      <Creator>Weather Service</Creator>

+      <Subject>weather</Subject>

+      <Subject>temperatures</Subject>

+      <Subject>measurements</Subject>

+      <resContext>NOAA.NWS.Data</resContext>

+      <resClass>data.granule</resClass>

+      <resLocation>http://weather.gov/data/highs/1.txt</resLocation>

+    </resAttributes>

+    <profElement>

+      <elemName>latitude</elemName>

+      <elemType>real</elemType>

+      <elemUnit>degree</elemUnit>

+      <elemEnumFlag>F</elemEnumFlag>

+      <elemMinValue>104.1</elemMinValue>

+      <elemMaxValue>121.5</elemMaxValue>

+    </profElement>

+    <profElement>

+      <elemName>longitude</elemName>

+      <elemType>real</elemType>

+      <elemUnit>degree</elemUnit>

+      <elemEnumFlag>F</elemEnumFlag>

+      <elemMinValue>39.2</elemMinValue>

+      <elemMaxValue>45.6</elemMaxValue>

+    </profElement>

+    <profElement>

+      <elemName>temperature</elemName>

+      <elemType>real</elemType>

+      <elemUnit>celsius</elemUnit>

+      <elemEnumFlag>F</elemEnumFlag>

+      <elemMinValue>23.3</elemMinValue>

+      <elemMaxValue>29.9</elemMaxValue>

+    </profElement>

+  </profile>

+  <profile>

+    <profAttributes>

+      <profId>2.6.1.9.2.1.2</profId>

+      <profType>profile</profType>

+      <profStatusId>active</profStatusId>

+    </profAttributes>

+    <resAttributes>

+      <Identifier>urn:weather:data:highs:2</Identifier>

+      <Title>High Temperatures - Day 2</Title>

+      <Format>text/tab-separated-values</Format>

+      <Creator>Weather Service</Creator>

+      <Subject>weather</Subject>

+      <Subject>temperatures</Subject>

+      <Subject>measurements</Subject>

+      <resContext>NOAA.NWS.Data</resContext>

+      <resClass>data.granule</resClass>

+      <resLocation>http://weather.gov/data/highs/2.txt</resLocation>

+    </resAttributes>

+    <profElement>

+      <elemName>latitude</elemName>

+      <elemType>real</elemType>

+      <elemUnit>degree</elemUnit>

+      <elemEnumFlag>F</elemEnumFlag>

+      <elemMinValue>104.1</elemMinValue>

+      <elemMaxValue>121.5</elemMaxValue>

+    </profElement>

+    <profElement>

+      <elemName>longitude</elemName>

+      <elemType>real</elemType>

+      <elemUnit>degree</elemUnit>

+      <elemEnumFlag>F</elemEnumFlag>

+      <elemMinValue>39.2</elemMinValue>

+      <elemMaxValue>45.6</elemMaxValue>

+    </profElement>

+    <profElement>

+      <elemName>temperature</elemName>

+      <elemType>real</elemType>

+      <elemUnit>celsius</elemUnit>

+      <elemEnumFlag>F</elemEnumFlag>

+      <elemMinValue>27.5</elemMinValue>

+      <elemMaxValue>31.5</elemMaxValue>

+    </profElement>

+  </profile>

+  <profile>

+    <profAttributes>

+      <profId>2.6.1.9.2.1.3</profId>

+      <profType>profile</profType>

+      <profStatusId>active</profStatusId>

+    </profAttributes>

+    <resAttributes>

+      <Identifier>urn:weather:data:highs:3</Identifier>

+      <Title>High Temperatures - Day 3</Title>

+      <Format>text/tab-separated-values</Format>

+      <Creator>Weather Service</Creator>

+      <Subject>weather</Subject>

+      <Subject>temperatures</Subject>

+      <Subject>measurements</Subject>

+      <resContext>NOAA.NWS.Data</resContext>

+      <resClass>data.granule</resClass>

+      <resLocation>http://weather.gov/data/highs/3.txt</resLocation>

+    </resAttributes>

+    <profElement>

+      <elemName>latitude</elemName>

+      <elemType>real</elemType>

+      <elemUnit>degree</elemUnit>

+      <elemEnumFlag>F</elemEnumFlag>

+      <elemMinValue>104.1</elemMinValue>

+      <elemMaxValue>110.3</elemMaxValue>

+    </profElement>

+    <profElement>

+      <elemName>longitude</elemName>

+      <elemType>real</elemType>

+      <elemUnit>degree</elemUnit>

+      <elemEnumFlag>F</elemEnumFlag>

+      <elemMinValue>39.2</elemMinValue>

+      <elemMaxValue>42.4</elemMaxValue>

+    </profElement>

+    <profElement>

+      <elemName>temperature</elemName>

+      <elemType>real</elemType>

+      <elemUnit>celsius</elemUnit>

+      <elemEnumFlag>F</elemEnumFlag>

+      <elemMinValue>19.5</elemMinValue>

+      <elemMaxValue>20.8</elemMaxValue>

+    </profElement>

+  </profile>

+</profiles>]]></source>

+

+      <p>Given this set of profiles, a profile search for resources

+	with <code>latitude &gt; 120.0</code> would match profiles

+	for day 1 and 2, but not day 3.  Actual profile searches are

+	possible by taking the above document and loading it into

+	the <code>LightweightProfileHandler</code>, yet that becomes

+	impractical for many many profiles, as it holds all of the

+	profile objects in memory and "searches" them in place.

+	More likely, data such as these would be stored in a

+	relational database, and the matching profiles would be

+	generated on demand.

+      </p>

+

+      <p>Let's make one more profile, a profile that describes

+	<em>the entire collection</em>:

+      </p>

+

+      <source><![CDATA[

+  <profile>

+    <profAttributes>

+      <profId>2.6.1.9.2.1</profId>

+      <profType>profile</profType>

+      <profStatusId>active</profStatusId>

+    </profAttributes>

+    <resAttributes>

+      <Identifier>urn:weather:data:highs:index</Identifier>

+      <Title>High Temperatures</Title>

+      <Format>text/tab-separated-values</Format>

+      <Creator>Weather Service</Creator>

+      <Subject>weather</Subject>

+      <Subject>temperatures</Subject>

+      <Subject>measurements</Subject>

+      <resContext>NOAA.NWS.Data</resContext>

+      <resClass>system.profileServer</resClass>

+      <resLocation>urn:weather:data:highs:ProfileServer</resLocation>

+    </resAttributes>

+    <profElement>

+      <elemName>latitude</elemName>

+      <elemType>real</elemType>

+      <elemUnit>degree</elemUnit>

+      <elemEnumFlag>F</elemEnumFlag>

+      <elemMinValue>104.1</elemMinValue>

+      <elemMaxValue>121.5</elemMaxValue>

+    </profElement>

+    <profElement>

+      <elemName>longitude</elemName>

+      <elemType>real</elemType>

+      <elemUnit>degree</elemUnit>

+      <elemEnumFlag>F</elemEnumFlag>

+      <elemMinValue>19.5</elemMinValue>

+      <elemMaxValue>31.5</elemMaxValue>

+    </profElement>

+    <profElement>

+      <elemName>temperature</elemName>

+      <elemType>real</elemType>

+      <elemUnit>celsius</elemUnit>

+      <elemEnumFlag>F</elemEnumFlag>

+      <elemMinValue>19.5</elemMinValue>

+      <elemMaxValue>31.5</elemMaxValue>

+    </profElement>

+  </profile>]]></source>

+

+      <p>Note that in addition to several changes in the resource

+	attributes, we've also changed the profile elements to

+	cover the entire range of latitude, longitude, and

+	temperature in the entire data set.  So, for temperature,

+	the lowest high temperature for all three days was 19.5,

+	and the highest was 31.5.  Now, a profile search can for

+	temperatures greater than 30 will match the profile for

+	the whole collection, as well as the profile for day #2.

+      </p>

+

+      <p>In fact, the OODT framework supports automatic drill-down of

+	this kind.  The <a href="/grid-query/">Query Service</a>, upon

+	encountering a matching profile, checks to see if the

+	<code>resClass</code> is <code>system.profileServer</code>,

+	and if so, will pass the query to the profile server at the

+	<code>resLocation</code> in the matched profile.  It will

+	gather up all matching profiles and return them to the user.

+	In this way, it can follow a directed graph of linked profile

+	servers (automatically avoiding cycles), and gathering more

+	and more results.

+      </p>

+    </section>

+  </body>

+</document>

diff --git a/0.8.1-rc1/profile/src/site/xdoc/querying/index.xml b/0.8.1-rc1/profile/src/site/xdoc/querying/index.xml
new file mode 100755
index 0000000..855774a
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/xdoc/querying/index.xml
@@ -0,0 +1,203 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+  <properties>
+    <title>Querying Profile Elements</title>
+    <author email="Sean.Kelly@jpl.nasa.gov">Sean Kelly</author>
+  </properties>
+  <!-- Four Carry Nuts - Hexagon -->
+  <body>
+    <section name="Querying Profile Elements">
+
+      <p>As desribed in <a href="../info/">Information Captured in a
+	Profile</a>, profile elements describe the composition of a
+	resource using metadata descriptions taken from the <a
+	href="http://metadata-standards.org/11179/">ISO/IEC 11179
+	standards</a>.  The profile elements catalog lists of valid
+	values, minimum and maximum values, data types, and so forth.
+      </p>
+
+      <p>As you develop a profile handler to perform queries and
+	generate profiles, you'll encounter three cases when querying
+	profile elements or the data sources they describe:
+      </p>
+
+      <ul>
+	<li>Querying ranges of values</li>
+	<li>Querying enumerated values</li>
+	<li>Querying unspecified profile lements</li>
+      </ul>
+    </section>
+
+    <section name="Queries Against Ranges">
+      <p>Ranged profile elements are those that describe an attribute
+	of a resource's composition in terms of a continuous space of
+	valid values.  In the Java implementation, there's a subclass
+	of <code>ProfileElement</code> to represent such ranges:
+	<code>RangedProfileElement</code>.  In the XML representation,
+	the <code>&lt;elemEnumFlag&gt;</code> is <code>F</code> and
+	there are values listed for <code>&lt;elemMinValue&gt;</code>
+	and <code>&lt;elemMaxValue&gt;</code>.
+      </p>
+
+      <p>An example of a ranged profile element might be:</p>
+      <table>
+	<tbody>
+	  <tr><td>Name:</td><td>temperature</td></tr>
+	  <tr><td>Description:</td><td>Temperatures measured using
+	  oral, medical-use, alcohol-based thermometer.</td></tr>
+	  <tr><td>Type:</td><td>real</td></tr>
+	  <tr><td>Unit:</td><td>kelvin</td></tr>
+	  <tr><td>Enumeration flag:</td><td>false</td></tr>
+	  <tr><td>Min value:</td><td>282.31</td></tr>
+	  <tr><td>Max value:</td><td>301.45</td></tr>
+	</tbody>
+      </table>
+
+      <p>When you're generating a profile (or querying a similar
+	metadata model) with a ranged element, queries should match if
+	the sought value occurs within the given, inclusive range.  If
+	it's a negative query, then it should match if the sought
+	value <em>doesn't</em> occur within the range.
+      </p>
+
+      <p>Here's an example.  Suppose you have a ranged profile element
+	called <code>lumens</code> and its minimum value is 10 and its
+	maximum value is 20.  Here's a table that shows queries and
+	whether they match:
+      </p>
+
+      <table>
+	<thead>
+	  <tr><th>Query</th><th>Match?</th></tr>
+	</thead>
+	<tbody>
+	  <tr><td>lumens = 12</td><td>Yes, since 12 is between 10 and 20</td></tr>
+	  <tr><td>lumens = 45</td><td>No, since 45 is above 20</td></tr>
+	  <tr><td>lumens != 12</td><td>Yes, since there are <em>other values</em> in the range 10..20 that match, such as 13, 14, 12.1, etc.</td></tr>
+	  <tr><td>lumens != 45</td><td>Yes, since are an infinite number of values in the range 10..22 that are not 45</td></tr>
+	  <tr><td>lumens != 10</td><td>Yes</td></tr>
+	  <tr><td>lumens &lt; 45</td><td>Yes</td></tr>
+	  <tr><td>lumens &gt; 15</td><td>Yes</td></tr>
+	  <tr><td>lumens &gt; 35</td><td>No; the highest lumen value is 20</td></tr>
+	  <tr><td>lumens LIKE 12</td><td>Maybe</td></tr>
+	</tbody>
+      </table>
+
+      <p>The "LIKE" relational operator defined by the XMLQuery query
+	langauge was meant for string comparisons, yet there's nothing
+	in the software that prevents it from being presented for
+	ranged queries.  The choice of whether to match it is up to you.
+      </p>
+    </section>
+
+    <section name="Queries Against Enumerated Values">
+      <p>Enumerated profile elements are those that describe an
+	attribute of a resource's composition in terms of a discrete
+	list of valid values.  In the Java implementation, there's a
+	subclass of <code>ProfileElement</code> to represent such
+	ranges: <code>EnumeratedProfileElement</code>.  In the XML
+	representation, the <code>&lt;elemEnumFlag&gt;</code> is
+	<code>T</code> and there are one or more
+	<code>&lt;elemValue&gt;</code> elements.
+      </p>
+
+      <p>An example of an enumerated profile element might be:</p>
+      <table>
+	<tbody>
+	  <tr><td>Name:</td><td>zone</td></tr>
+	  <tr><td>Description:</td><td>City Planning Commission zoning code for permitted land use.</td></tr>
+	  <tr><td>Type:</td><td>string</td></tr>
+	  <tr><td>Unit:</td><td>code</td></tr>
+	  <tr><td>Enumeration flag:</td><td>true</td></tr>
+	  <tr><td>Value:</td><td>A</td></tr>
+	  <tr><td>Value:</td><td>B1</td></tr>
+	  <tr><td>Value:</td><td>B2</td></tr>
+	  <tr><td>Value:</td><td>B4</td></tr>
+	  <tr><td>Value:</td><td>C</td></tr>
+	  <tr><td>Value:</td><td>H</td></tr>
+	  <tr><td>Value:</td><td>PDD</td></tr>
+	  <tr><td>Value:</td><td>R2</td></tr>
+	  <tr><td>Value:</td><td>R3</td></tr>
+	  <tr><td>Value:</td><td>R4</td></tr>
+	  <tr><td>Value:</td><td>R5</td></tr>
+	</tbody>
+      </table>
+
+      <p>When you're generating a profile (or querying a similar
+	metadata model) with an enumerated element, queries should
+	match if the sought value appears as one of the listed
+	elements.
+      </p>
+
+      <p>Here's an example.  Suppose you have an profile element
+	called <code>planet</code> that has as valid values
+	<code>Mercury</code>, <code>Venus</code>, <code>Earth</code>,
+	and <code>Mars</code>.  Here's a table that shows queries and
+	whether they match:
+      </p>
+
+      <table>
+	<thead>
+	  <tr><th>Query</th><th>Match?</th></tr>
+	</thead>
+	<tbody>
+	  <tr><td>planet = Mercury</td><td>Yes</td></tr>
+	  <tr><td>planet = Jupiter</td><td>No</td></tr>
+	  <tr><td>planet != Mercury</td><td>Yes since Earth, Venus, and Mars are all not Mercury</td></tr>
+	  <tr><td>planet != Jupiter</td><td>Yes since there are 4 planets which are all not Jupiter</td></tr>
+	  <tr><td>planet &lt; Earth</td><td>Maybe</td></tr>
+	  <tr><td>planet LIKE %E%</td><td>Yes, since all four planets have an E in them (without regard to case)</td></tr>
+	  <tr><td>planet NOTLIKE %E%</td><td>No, since all four planets have an E in them</td></tr>
+	</tbody>
+      </table>
+
+      <p>Relational ordering is not specified by the profile model, so whether
+	a query like <code>planet &lt; Earth</code> matches is up to you.
+      </p>
+    </section>
+
+    <section name="Querying Against Unspecified Values">
+      <p>An unspecific profile element indicates only the
+	<em>presence</em> of an attribute in the composition of a
+	resource, and nothing else.  In the Java implementation,
+	there's a subclass of <code>ProfileElement</code> to represent
+	this, <code>UnspecifiedProfileElement</code>.  In the XML
+	representation, the <code>&lt;elemEnumFlag&gt;</code> is
+	<code>T</code> and there are zero
+	<code>&lt;elemValue&gt;</code> elements.
+      </p>
+
+      <p>Unspecified profile elements can be useful where you have
+	profiles not describing single resources, but entire
+	collections of resources.  For example, you may have ranged
+	profile elements called <code>temperature</code> for each
+	temperature resource.  But if there are a billion resources,
+	then determining the minimum and maximum temperature for the
+	profile of the entire collection might be painful, in which
+	case you can say that the collection has a
+	<code>temperature</code> attribute by using an unspecified
+	profile for the element for the collection.
+      </p>
+
+      <p>Queries against unspecified elements always match, regardless
+	what the query is.
+      </p>
+    </section>
+  </body>
+</document>
diff --git a/0.8.1-rc1/profile/src/site/xdoc/rep/index.xml b/0.8.1-rc1/profile/src/site/xdoc/rep/index.xml
new file mode 100755
index 0000000..11c5d3e
--- /dev/null
+++ b/0.8.1-rc1/profile/src/site/xdoc/rep/index.xml
@@ -0,0 +1,334 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!--

+Licensed to the Apache Software Foundation (ASF) under one or more contributor

+license agreements.  See the NOTICE.txt 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.

+-->

+<document>

+  <properties>

+    <title>Representation of Profiles</title>

+    <author email="Sean.Kelly@jpl.nasa.gov">Sean Kelly</author>

+  </properties>

+

+  <body>

+    <section name="Representation of Profiles">

+      <p>Within the OODT Framework, profiles are represented as RDF

+	documents, XML documents, or Java objects. The Java Profile

+	class can yield itself as an RDF or XML document, and you can

+	construct a Java Profile from an XML document that describes a

+	profile.

+      </p>

+    </section>

+

+    <section name="Introduction">

+      <p>No matter what their origin or whether they're to be short

+	lived, profiles have a physical representation at one time

+	within the OODT framework.  Typically, you'll use the Java class

+	<code>Profile</code> when working with Java, or the

+	RDF or XML document version when working in other environments.

+	The RDF representation uses the RDF XML structure and RDF schema

+	to describe profiles.  The XML document version uses an

+	OODT-specific XML vocabulary and DTD.

+      </p>

+

+      <p><em>For C/C++ Users:</em> There is not yet a C/C++ representation of a profile.

+	Use the RDF or XML representation.

+      </p>

+

+      <p><em>Note:</em>The RDF representation is currently a work-in-progress.

+      </p>

+

+      <p>If you're developing a new kind of profile server, you

+	should become familiar with the Java

+	<code>Profile</code> class.  If you're searching for

+	profiles, you can just use the RDF or XML representations.

+      </p>

+    </section>

+

+    <section name="XML Profiles">

+      <p>Profiles can be represented as XML documents that conform to

+	the OODT Profile Document Type Definition (DTD).  The Formal

+	Public Identifier of the OODT Profile DTD is <code>-//JPL//DTD

+	Profile 1.0//EN</code>.  The normative System Identifier is

+	<a>http://oodt.jpl.nasa.gov/grid-profile/dtd/prof.dtd</a>.

+      </p>

+

+      <p>Although you should refer to the normative System

+	Identifier for the latest reference version, see the following:

+      </p>

+

+      <source><![CDATA[<!ELEMENT profiles

+  (profile*)>

+

+<!ELEMENT profile

+  (profAttributes,

+   resAttributes,

+   profElement*)>

+

+    <!ELEMENT profAttributes

+      (profId, profVersion?, profType,

+       profStatusId, profSecurityType?, profParentId?, profChildId*,

+       profRegAuthority?, profRevisionNote*)>

+

+    <!ELEMENT resAttributes

+      (Identifier, Title?, Format*, Description?, Creator*, Subject*,

+       Publisher*, Contributor*, Date*, Type*, Source*,

+       Language*, Relation*, Coverage*, Rights*,

+       resContext+, resAggregation?, resClass, resLocation*)>

+

+    <!ELEMENT profElement

+      (elemId?, elemName, elemDesc?, elemType?, elemUnit?, 

+       elemEnumFlag, (elemValue* | (elemMinValue, elemMaxValue)),

+       elemSynonym*,

+       elemObligation?, elemMaxOccurrence?, elemComment?)>

+

+    <!ELEMENT profId (#PCDATA)>

+    <!ELEMENT profVersion (#PCDATA)>

+    <!ELEMENT profType (#PCDATA)>

+    <!ELEMENT profParentId (#PCDATA)>

+    <!ELEMENT profChildId (#PCDATA)>

+    <!ELEMENT profStatusId (#PCDATA)>

+    <!ELEMENT profSecurityType (#PCDATA)>

+    <!ELEMENT profRegAuthority (#PCDATA)>

+    <!ELEMENT profRevisionNote (#PCDATA)>

+

+    <!ELEMENT Identifier (#PCDATA)>

+    <!ELEMENT Title (#PCDATA)>

+    <!ELEMENT Format (#PCDATA)>

+    <!ELEMENT Description (#PCDATA)>

+    <!ELEMENT Creator (#PCDATA)>

+    <!ELEMENT Subject (#PCDATA)>

+    <!ELEMENT Publisher (#PCDATA)>

+    <!ELEMENT Contributor (#PCDATA)>

+    <!ELEMENT Date (#PCDATA)>

+    <!ELEMENT Type (#PCDATA)>

+    <!ELEMENT Source (#PCDATA)>

+    <!ELEMENT Language (#PCDATA)>

+    <!ELEMENT Relation (#PCDATA)>

+    <!ELEMENT Coverage (#PCDATA)>

+    <!ELEMENT Rights (#PCDATA)>

+    <!ELEMENT resContext (#PCDATA)>

+    <!ELEMENT resAggregation (#PCDATA)>

+    <!ELEMENT resClass (#PCDATA)>

+    <!ELEMENT resLocation (#PCDATA)>

+

+    <!ELEMENT elemId (#PCDATA)>

+    <!ELEMENT elemName (#PCDATA)>

+    <!ELEMENT elemType (#PCDATA)>

+    <!ELEMENT elemEnumFlag (#PCDATA)>

+    <!ELEMENT elemDesc (#PCDATA)>

+    <!ELEMENT elemSynonym (#PCDATA)>

+    <!ELEMENT elemUnit (#PCDATA)>

+    <!ELEMENT elemValue (#PCDATA)>	

+    <!ELEMENT elemMinValue (#PCDATA)>	

+    <!ELEMENT elemMaxValue (#PCDATA)>	

+    <!ELEMENT elemObligation (#PCDATA)>

+    <!ELEMENT elemMaxOccurrence (#PCDATA)>

+    <!ELEMENT elemComment (#PCDATA)>]]></source>

+

+

+      <subsection name="Collections of Profiles">

+	<p>As you can see from the above,an

+	  XML element, <code>profiles</code> is a

+	  container element to hold zero or more profiles.  Use this

+	  element where it's necessary to manipulate a collection of

+	  profiles without regard to order.

+	</p>

+      </subsection>

+    </section>

+

+    <section name="Java Representation of Profiles">

+      <p>The OODT source code includes a class

+	<code>jpl.eda.profile.Profile</code> for object

+	represenation of a profile.  You can construct a

+	<code>Profile</code> object from an RDF or XML

+	document or create a blank one to populate with metadata

+	later.

+      </p>

+      <p>To construct a new, blank profile, use the no-arguments

+	constructor.  To construct a profile from an RDF or XML

+	document, use the constructor accepting a Resource or a DOM

+	<code>Node</code>, respectively.  The DOM node

+	should be a <code>Element</code> representing the

+	<code>profile</code> element.

+	Alternatively, if your XML document exists as a string, call

+	the constructor taking a single string.

+      </p>

+

+      <subsection name="Accessing Profile Metadata">

+	<p>To access the metadata of a profile, call the methods to

+	  retrieve the profile attributes, the resource attributes, or

+	  the profile elements.

+	</p>

+

+	<subsection name="Accessing the Profile Attributes">

+	  <p>You retrieve the profile attributes by calling

+	    <code>getProfileAttributes</code> on a

+	    <code>Profile</code>.  This returns an

+	    <code>ProfileAttributes</code> object which provides

+	    methods to get and set the various attributes.  Setting a

+	    value sets it for the <code>Profile</code> to which

+	    the <code>ProfileAttributes</code> belongs.

+	  </p>

+	  

+	  <p>A value of <code>null</code> for an optional

+	    attribute means the value isn't set.

+	  </p>

+	</subsection>

+

+	<subsection name="Accessing the Resource Attributes">

+	  <p>You retrieve the resource attributes similarly as for

+	    profile attributes, calling

+	    <code>getResourceAttributes</code> to yield a

+	    <code>ResourceAttributes</code> object.

+	  </p>

+	  <p>The <code>ResourceAttributes</code> has

+	    methods to get and set various attributes.  Note that many

+	    of the attributes are multi-valued.  For example, the

+	    resource profiled will likely cover several subjects.  In

+	  this case, the "get" method,

+	  <code>getSubjects</code>, returns a

+	  <code>java.util.List</code> of

+	  <code>String</code>s.  There is no set method.

+	    Instead, you just manipulate the list to add and remove

+	    subjects.

+	  </p>

+

+	  <p><em>Note:</em> All of the "get" functions that return

+	    <code>List</code>s return lists of

+	    <code>String</code>s, except for

+	    <code>getDates</code>, which returns a list of

+	    <code>java.util.Date</code>s.

+	  </p>

+

+	  <p>For other attributes which are singly valued, there is

+	    both a set and get method.  For optional values, a value of

+	    <code>null</code> means the attribute isn't set.

+	  </p>

+	</subsection>

+

+	<subsection name="Accessing the Profile Elements">

+	  <p>The profile stores its profile elements in a

+	    <code>java.util.Map</code>, mapping the name of

+	    the profile element (as a <code>String</code>) to

+	    an object of class <code>ProfileElement</code>.

+	    To access this map, call the method

+	    <code>getProfileElements</code> on a

+	    <code>Profile</code>.  Because this method returns

+	    a reference to the <code>Profile</code>'s map, any

+	    updates to the map affect the profile immediately.

+	  </p>

+

+	  <p><em>Caution:</em> Never store anything but

+	    <code>String</code>s as keys and

+	    <code>ProfileElement</code>s (or objects of its

+	    subclasses) as values in a profile element map.  The

+	    software will not operate correctly if any other kind of

+	    object is stored.

+	  </p>

+

+	  <subsection name="Common Attributes of Profile Elements">

+	    <p>The class

+	      <code>jpl.eda.profile.ProfileElement</code>

+	      contains the common parts of every profile element, such

+	      as its required name, its optional description, and so

+	      forth.  Use the value <code>null</code> for any

+	      optional attribute that's unset.

+	    </p>

+	    <p>The <code>ProfileElement</code> stores its

+	      synonyms as a <code>java.util.List</code> of

+	      <code>String</code>s.  Manipulate the list

+	      directly to add or remove synonyms.

+	    </p>

+	    <p>The <code>ProfileElement</code> class is

+	      abstract.  To create new profile elements for a profile,

+	      you need to create objects of one of the concrete

+	      <code>ProfileElement</code> subclasses:

+	    </p>

+

+	    <ul>

+	      <li><code>EnumeratedProfileElement</code></li>

+	      <li><code>RangedProfileElement</code></li>

+	      <li><code>UnspecifiedProfileElement</code></li>

+	    </ul>

+

+	    <p>The following sections detail each kind of profile

+	      element.

+	    </p>

+	  </subsection>

+

+	  <subsection name="Elements with Enumerated Values">

+	    <p>For profile elements that maintain a specified list of

+	      valid values, use the

+	      <code>EnumeratedProfileElement</code> class.

+	      Objects of this class maintian a

+	      <code>java.util.List</code> of values.  You can

+	      pass in a list of values when constrcuting the object, or

+	      can call the <code>getValues</code> method and

+	      manipulate the list directly.

+	    </p>

+	    <p>Queries that arrive for an enumerated profile

+	      element must match one of the listed elements exactly

+	      unless it's a negative (not-equal-to) query.  For

+	      example, suppose we had an enumerated profile element

+	      <code>filter</code> with values

+	      <code>infrared</code>, <code>visible</code>,

+	      and <code>ultraviolet</code>.  A query asking for

+	      a filter equal to infrared should match, as well as a

+	      query asking for a filter greater than or equal to

+	      infrared.  A query asking for a filter not equal to

+	      infrared shouldn't match, while a query asking for a

+	      filter not equal to x-ray should match.

+	    </p>

+	  </subsection>

+

+	  <subsection name="Elements with a Range of Values">

+	    <p>You can represent profile elements that have a range

+	      of valid values with the

+	      <code>RangedProfileElement</code> class.

+	      Construct this class with the minimum and maximum values,

+	      which must be numeric.

+	    </p>

+	    <p>Use the <code>getMinValue</code> to get the

+	      minimum value and <code>getMaxValue</code> to

+	      get the maximum value.

+	    </p>

+	    <p>Querying a profile that uses a range of values

+	      considers the range as inclusive.  For example, suppose

+	      the ranged profile element

+	      <code>temperature</code> has a minimum value of 32

+	      and a maximum value of 212.  A query that requests

+	      temperatures less than 32 shouldn't match, but less than or

+	      equal to 32 should match.

+	    </p>

+	  </subsection>

+

+	  <subsection name="Elements with no Specified Values">

+	    <p>For profile elements that you always want to match a

+	      query without explicitly listing each valid value or a

+	      range of legal numeric values you can use the class

+	      <code>UnspecifiedProfileElement</code>.  This

+	      class identifies an element with no range or list of

+	      valid values.

+	    </p>

+	    <p>Queries that arrive at such an element will

+	      <span class="emphasis"><em>always</em></span> match, even if they're

+	      negative (not-equal-to) queries.

+	    </p>

+	  </subsection>

+	</subsection>

+      </subsection>

+    </section>

+  </body>

+</document>

diff --git a/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/EnumeratedProfileElementTest.java b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/EnumeratedProfileElementTest.java
new file mode 100644
index 0000000..c89a79d
--- /dev/null
+++ b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/EnumeratedProfileElementTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.xml.sax.SAXException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import org.apache.oodt.commons.io.NullOutputStream;
+import org.apache.oodt.commons.util.XML;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * Unit test the {@link EnumeratedProfileElement} class.
+ *
+ * @author Kelly
+ */ 
+public class EnumeratedProfileElementTest extends ProfileElementTestCase {
+	/**
+	 * Construct the test case for the {@link EnumeratedProfileElement} class.
+	 */
+	public EnumeratedProfileElementTest(String name) {
+		super(name);
+	}
+
+	protected ProfileElement createProfileElement() {
+		return new EnumeratedProfileElement(ProfileTest.TEST_PROFILE, "name", "id", "desc", "type", "unit",
+			/*synonyms*/ new ArrayList(), /*obligation*/false, /*maxOccurrence*/1, "comment", VALUES);
+	}
+
+	public void testIt() {
+		ProfileElement element = createProfileElement();
+		List values = element.getValues();
+		assertEquals(3, values.size());
+		assertEquals("1", values.get(0));
+		assertEquals("2", values.get(1));
+		assertEquals("3", values.get(2));
+	}
+
+	public void testNulls() {
+		try {
+			EnumeratedProfileElement element = new EnumeratedProfileElement(createProfileElement().getProfile(),
+				"test", "test", "test", "test", "test", Collections.EMPTY_LIST, /*obligation*/true, /*maxOccur*/1,
+				"comment", Collections.singletonList(null));
+			fail("Null values must not be allowed as values in enumerated elements.");
+		} catch (IllegalArgumentException good) {}
+	}
+
+	protected void checkEnumFlag(String text) {
+		assertEquals("T", text);
+	}
+
+	protected void checkValue(String text) {
+		assertTrue(VALUES.contains(text));
+	}
+
+	protected void checkMaxValue(String text) {
+		fail("Enumerated profile element shouldn't have a maximum value");
+	}
+
+	protected void checkMinValue(String text) {
+		fail("Enumerated profile element shouldn't have a minimum value");
+	}
+
+	/**
+	 * Test to see if spaces are preserved in XML generation and parsing.
+	 *
+	 * @throws SAXException if an error occurs.
+	 */
+	public void testSpacePreserving() throws SAXException {
+		Profile p = new Profile();
+		ProfileAttributes pa = new ProfileAttributes("1", "1", "profile", "active", "1", "1",
+			/*children*/Collections.EMPTY_LIST, "1", /*revNotes*/Collections.EMPTY_LIST);
+		p.setProfileAttributes(pa);
+		ResourceAttributes ra = new ResourceAttributes(p, "id", "title", /*formats*/Collections.EMPTY_LIST, "description",
+			/*creators*/Collections.EMPTY_LIST, /*subjects*/Collections.EMPTY_LIST, /*publishers*/Collections.EMPTY_LIST,
+			/*contributors*/Collections.EMPTY_LIST, /*dates*/Collections.EMPTY_LIST, /*types*/Collections.EMPTY_LIST,
+			/*sources*/Collections.EMPTY_LIST, /*languages*/Collections.EMPTY_LIST, /*relations*/Collections.EMPTY_LIST,
+			/*coverages*/Collections.EMPTY_LIST, /*rights*/Collections.EMPTY_LIST, Collections.singletonList("context"),
+			"granule", "grainy", Collections.singletonList("file:/dev/null"));
+		p.setResourceAttributes(ra);
+		EnumeratedProfileElement e = new EnumeratedProfileElement(p, "mode", "mode", "Mode", "string", "mode",
+			/*synonyms*/Collections.EMPTY_LIST, /*obligation*/false, /*maxOccurrence*/1, "No comment",
+			Collections.singletonList("The current\n mode setting\n  is set to indent\n\n   a\n\n"
+				+ "    number of increasing\n     times."));
+		p.getProfileElements().put("mode", e);
+
+		Profile q = new Profile(p.toString());
+		e = (EnumeratedProfileElement) q.getProfileElements().values().iterator().next();
+		assertEquals("The current\n mode setting\n  is set to indent\n\n   a\n\n"
+			+ "    number of increasing\n     times.", e.getValues().get(0));
+	}
+
+	public void testXMLSerialization() throws Exception {
+		Profile p = new Profile();
+		EnumeratedProfileElement e = new EnumeratedProfileElement(p);
+		Document doc = XML.createDocument();
+		Node root = e.toXML(doc);
+		TransformerFactory tf = TransformerFactory.newInstance();
+		Transformer t = tf.newTransformer();
+		DOMSource s = new DOMSource(root);
+		StreamResult r = new StreamResult(new NullOutputStream());
+		t.transform(s, r);
+	}
+
+	/** Enumerated values for the test element. */
+	private static final List VALUES = Arrays.asList(new String[]{"1", "2", "3"});
+}
diff --git a/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/ProfileAttributesTest.java b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/ProfileAttributesTest.java
new file mode 100644
index 0000000..223a86f
--- /dev/null
+++ b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/ProfileAttributesTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import org.apache.oodt.commons.io.NullOutputStream;
+import org.apache.oodt.commons.util.XML;
+import junit.framework.TestCase;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Unit test the {@link ProfileAttributes} class.
+ *
+ * @author Kelly
+ */ 
+public class ProfileAttributesTest extends TestCase {
+	/** Construct the test case for the {@link ProfileAttributes} class. */
+	public ProfileAttributesTest(String name) {
+		super(name);
+	}
+
+	public void testNoArgsCtor() {
+		ProfileAttributes blank = new ProfileAttributes();
+		assertEquals("UNKNOWN", blank.getID());
+		assertEquals(0, blank.getChildren().size());
+	}
+
+	public void testCtor() {
+		assertEquals("id", TEST_PROFILE_ATTRIBUTES.getID());
+		assertEquals("version", TEST_PROFILE_ATTRIBUTES.getVersion());
+		assertEquals("type", TEST_PROFILE_ATTRIBUTES.getType());
+		assertEquals("statusID", TEST_PROFILE_ATTRIBUTES.getStatusID());
+		assertEquals("securityType", TEST_PROFILE_ATTRIBUTES.getSecurityType());
+		assertEquals("parent", TEST_PROFILE_ATTRIBUTES.getParent());
+		assertEquals(2, TEST_PROFILE_ATTRIBUTES.getChildren().size());
+		assertEquals("child1", TEST_PROFILE_ATTRIBUTES.getChildren().get(0));
+		assertEquals("child2", TEST_PROFILE_ATTRIBUTES.getChildren().get(1));
+		assertEquals("regAuthority", TEST_PROFILE_ATTRIBUTES.getRegAuthority());
+		assertEquals(2, TEST_PROFILE_ATTRIBUTES.getRevisionNotes().size());
+		assertEquals("note1", TEST_PROFILE_ATTRIBUTES.getRevisionNotes().get(0));
+		assertEquals("note2", TEST_PROFILE_ATTRIBUTES.getRevisionNotes().get(1));
+	}		
+
+	public void testObjectMethods() {
+		ProfileAttributes q1 = new ProfileAttributes("1", "2", "3", "4", "5", "6", Collections.EMPTY_LIST, "7",
+			Collections.EMPTY_LIST);
+		ProfileAttributes q2 = new ProfileAttributes("1", "2", "3", "4", "5", "6", Collections.EMPTY_LIST, "7",
+			Collections.EMPTY_LIST);
+		ProfileAttributes q3 = new ProfileAttributes("2", "3", "4", "5", "6", "7", Collections.EMPTY_LIST, "8",
+			Collections.EMPTY_LIST);
+		assertEquals(q1, q1);
+		assertEquals(q1, q2);
+		assertTrue(!q1.equals(q3));
+		ProfileAttributes q4 = (ProfileAttributes) q3.clone();
+		assertEquals(q3, q4);
+		assertTrue(q3 != q4);
+	}
+
+	public void testSetters() {
+		ProfileAttributes q = (ProfileAttributes) TEST_PROFILE_ATTRIBUTES.clone();
+
+		assertEquals("id", q.getID());
+		q.setID("newId");
+		assertEquals("newId", q.getID());
+
+		assertEquals("version", q.getVersion());
+		q.setVersion("newVersion");
+		assertEquals("newVersion", q.getVersion());
+
+		assertEquals("type", q.getType());
+		q.setType("newType");
+		assertEquals("newType", q.getType());
+
+		assertEquals("statusID", q.getStatusID());
+		q.setStatusID("newStatusid");
+		assertEquals("newStatusid", q.getStatusID());
+
+		assertEquals("securityType", q.getSecurityType());
+		q.setSecurityType("newSecuritytype");
+		assertEquals("newSecuritytype", q.getSecurityType());
+
+		assertEquals("regAuthority", q.getRegAuthority());
+		q.setRegAuthority("newRegAuthority");
+		assertEquals("newRegAuthority", q.getRegAuthority());
+	}
+
+	public void testXML() throws Exception {
+		Document doc = XML.createDocument();
+		Node root = TEST_PROFILE_ATTRIBUTES.toXML(doc);
+		assertEquals("profAttributes", root.getNodeName());
+		NodeList children = root.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node child = children.item(i);
+			String name = child.getNodeName();
+			if ("profId".equals(name)) {
+				assertEquals("id", XML.text(child));
+			} else if ("profVersion".equals(name)) {
+				assertEquals("version", XML.text(child));
+			} else if ("profType".equals(name)) {
+				assertEquals("type", XML.text(child));
+			} else if ("profStatusId".equals(name)) {
+				assertEquals("statusID", XML.text(child));
+			} else if ("profSecurityType".equals(name)) {
+				assertEquals("securityType", XML.text(child));
+			} else if ("profParentId".equals(name)) {
+				assertEquals("parent", XML.text(child));
+			} else if ("profChildId".equals(name)) {
+				; // ignore, list serialization tested in XMLTest
+			} else if ("profRegAuthority".equals(name)) {
+				assertEquals("regAuthority", XML.text(child));
+			} else if ("profRevisionNote".equals(name)) {
+				; // ignore, list serialization tested in XMLTest
+			} else fail("Unknown node \"" + name + "\" in XML result");
+		}
+		ProfileAttributes p = new ProfileAttributes(root);
+		assertEquals(TEST_PROFILE_ATTRIBUTES, p);
+	}
+	
+	public void testXMLSerialization() throws Exception {
+		ProfileAttributes p = new ProfileAttributes();
+		Document doc = XML.createDocument();
+		Node root = p.toXML(doc);
+		TransformerFactory tf = TransformerFactory.newInstance();
+		Transformer t = tf.newTransformer();
+		DOMSource s = new DOMSource(root);
+		StreamResult r = new StreamResult(new NullOutputStream());
+		t.transform(s, r);
+	}
+
+	static final ProfileAttributes TEST_PROFILE_ATTRIBUTES;
+
+	static {
+		List parents = Collections.singletonList("parent");
+		List children = new ArrayList();
+		children.add("child1");
+		children.add("child2");
+		List revisionNotes = new ArrayList();
+		revisionNotes.add("note1");
+		revisionNotes.add("note2");
+		TEST_PROFILE_ATTRIBUTES = new ProfileAttributes("id", "version", "type", "statusID",
+			"securityType", "parent", children, "regAuthority", revisionNotes);
+	}
+}
diff --git a/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/ProfileElementTestCase.java b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/ProfileElementTestCase.java
new file mode 100644
index 0000000..617c69c
--- /dev/null
+++ b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/ProfileElementTestCase.java
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import junit.framework.TestCase;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.apache.oodt.commons.util.XML;
+
+/**
+ * Test case for profile elements.
+ *
+ * @author Kelly
+ */ 
+public abstract class ProfileElementTestCase extends TestCase {
+	/** Construct the test case for the {@link ProfileElement} superclass. */
+	public ProfileElementTestCase(String name) {
+		super(name);
+	}
+
+	/**
+	 * Create a profile element object to test.
+	 *
+	 * The element returned must have as its owning profile the
+	 * <code>ProfileTest.TEST_PROFILE</code>, be named "name", have "id" as its ID,
+	 * have "desc" as its description, must be of type "type", have "unit" units, have
+	 * no synonyms, not be obligatory, may occur once, and have "comment" as its
+	 * comment.
+	 *
+	 * @return A profile element.
+	 */
+	protected abstract ProfileElement createProfileElement();
+
+	/**
+	 * Check if the given enumeration flag is valid.
+	 *
+	 * This method merely asserts that it's valid for the profile element in question.
+	 *
+	 * @param text Text to check.
+	 */
+	protected abstract void checkEnumFlag(String text);
+
+	/**
+	 * Check that the given value is valid.
+	 *
+	 * This method merely asserts that it's valid for the profile element in question.
+	 *
+	 * @param text Text to check.
+	 */
+	protected abstract void checkValue(String text);
+
+	/**
+	 * Check that the given maximum value is valid.
+	 *
+	 * This method merely asserts that it's valid for the profile element in question.
+	 *
+	 * @param text Text to check.
+	 */
+	protected abstract void checkMaxValue(String text);
+
+	/**
+	 * Check that the given minimum value is valid.
+	 *
+	 * This method merely asserts that it's valid for the profile element in question.
+	 *
+	 * @param text Text to check.
+	 */
+	protected abstract void checkMinValue(String text);
+
+	public void testCharacteristics() {
+		ProfileElement element = createProfileElement();
+		assertEquals(ProfileTest.TEST_PROFILE, element.getProfile());
+
+		assertEquals("name", element.getName());
+		element.setName("newName");
+		assertEquals("newName", element.getName());
+
+		assertEquals("id", element.getID());
+		element.setID("newID");
+		assertEquals("newID", element.getID());
+
+		assertEquals("desc", element.getDescription());
+		element.setDescription("newDesc");
+		assertEquals("newDesc", element.getDescription());
+
+		assertEquals("type", element.getType());
+		element.setType("newType");
+		assertEquals("newType", element.getType());
+
+		assertEquals("unit", element.getUnit());
+		element.setUnit("newUnit");
+		assertEquals("newUnit", element.getUnit());
+
+		assertEquals(0, element.getSynonyms().size());
+		element.getSynonyms().add("synonym");
+		assertEquals(1, element.getSynonyms().size());
+		assertEquals("synonym", element.getSynonyms().get(0));
+
+		assertTrue(!element.isObligatory());
+		element.setObligation(true);
+		assertTrue(element.isObligatory());
+
+		assertEquals(1, element.getMaxOccurrence());
+		element.setMaxOccurrence(2);
+		assertEquals(2, element.getMaxOccurrence());
+
+		assertEquals("comment", element.getComments());
+		element.setComments("newComment");
+		assertEquals("newComment", element.getComments());
+	}
+
+	public void testObjectMethods() {
+		ProfileElement elem1 = createProfileElement();
+		ProfileElement elem2 = createProfileElement();
+		ProfileElement elem3 = createProfileElement();
+		elem3.setName("newName");
+		assertEquals(elem1, elem1);
+		assertEquals(elem1, elem2);
+		assertTrue(!elem1.equals(elem3));
+		ProfileElement elem4 = (ProfileElement) elem3.clone();
+		assertEquals(elem3, elem4);
+		assertTrue(elem3 != elem4);
+	}
+
+	public void testXML() {
+		ProfileElement element = createProfileElement();
+		Document doc = XML.createDocument();
+		Node root = element.toXML(doc);
+		assertEquals("profElement", root.getNodeName());
+		NodeList children = root.getChildNodes();
+		boolean foundName = false;
+		boolean foundEnumFlag = false;
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node child = children.item(i);
+			String name = child.getNodeName();
+			String text = ProfileElement.text(child);
+			if ("elemId".equals(name)) {
+				assertEquals("id", text);
+			} else if ("elemName".equals(name)) {
+				assertEquals("name", text);
+				foundName = true;
+			} else if ("elemDesc".equals(name)) {
+				assertEquals("desc", text);
+			} else if ("elemType".equals(name)) {
+				assertEquals("type", text);
+			} else if ("elemUnit".equals(name)) {
+				assertEquals("unit", text);
+			} else if ("elemEnumFlag".equals(name)) {
+				checkEnumFlag(text);
+				foundEnumFlag = true;
+			} else if ("elemValue".equals(name)) {
+				checkValue(text);
+			} else if ("elemMinValue".equals(name)) {
+				checkMinValue(text);
+			} else if ("elemMaxValue".equals(name)) {
+				checkMaxValue(text);
+			} else if ("elemSynonym".equals(name)) {
+				; // ignore
+			} else if ("elemObligation".equals(name)) {
+				assertEquals("Optional", text);
+			} else if ("elemMaxOccurrence".equals(name)) {
+				assertEquals("1", text);
+			} else if ("elemComment".equals(name)) {
+				assertEquals("comment", text);
+			} else fail("Unknown node <" + name + "> under <profElement>");
+		}
+		assertTrue("Required <elemName> missing", foundName);
+		assertTrue("Required <elemEnumFlag> missing", foundEnumFlag);
+	}
+}
diff --git a/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/ProfileTest.java b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/ProfileTest.java
new file mode 100644
index 0000000..a6eee4d
--- /dev/null
+++ b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/ProfileTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import org.apache.oodt.commons.util.XML;
+import org.w3c.dom.Document;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit test the Profile class.
+ *
+ * @author Kelly
+ */ 
+public class ProfileTest extends TestCase {
+	/** Construct the test case for the Profile class. */
+	public ProfileTest(String name) {
+		super(name);
+	}
+
+	protected void setUp() throws Exception {
+		super.setUp();
+		oldProfNS = System.getProperty("jpl.rdf.ns");
+		System.setProperty("jpl.rdf.ns", "http://enterprise.jpl.nasa.gov/rdfs/prof.rdf#");
+
+		StringBuffer buffer = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+		buffer.append("<!DOCTYPE profile PUBLIC \"").append(Profile.PROFILES_DTD_FPI).append("\" \"")
+			.append(Profile.PROFILES_DTD_URL).append("\">\n");
+		BufferedReader reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("test.xml")));
+		String line;
+		while ((line = reader.readLine()) != null) {
+			buffer.append(line);
+			buffer.append('\n');
+		}
+		reader.close();
+		Document doc = XML.parse(buffer.toString());
+		profile1 = new Profile(buffer.toString());
+		profile2 = new Profile(doc.getDocumentElement());
+	}
+
+	protected void tearDown() throws Exception {
+		if (oldProfNS != null)
+			System.setProperty("jpl.rdf.ns", oldProfNS);
+		else
+			System.getProperties().remove("jpl.rdf.ns");
+	}
+
+	public void testQueries() {
+		// We test both profile1 (built from a string) and profile2 (from an XML
+		// document node); they should yield the same results because they
+		// represent the same document.
+
+		// Test the getResourceAttribute method.
+		assertEquals("PDS_PROFILE_SERVER", profile1.getResourceAttributes().getIdentifier());
+		assertEquals("PDS_PROFILE_SERVER", profile2.getResourceAttributes().getIdentifier());
+		assertEquals("text/html", profile1.getResourceAttributes().getFormats().get(0));
+		assertEquals("text/html", profile2.getResourceAttributes().getFormats().get(0));
+
+		// Test the getProfileID method.
+		assertEquals("OODT_PDS_PROFILE_SERVER", profile1.getProfileAttributes().getID());
+		assertEquals("OODT_PDS_PROFILE_SERVER", profile2.getProfileAttributes().getID());
+
+		// Test the getProfileAttribute method
+		assertEquals("profile", profile1.getProfileAttributes().getType());
+		assertEquals("profile", profile2.getProfileAttributes().getType());
+		assertEquals("NULL", profile1.getProfileAttributes().getSecurityType());
+		assertEquals("NULL", profile2.getProfileAttributes().getSecurityType());
+
+		// Test the getProfileElementItem method.
+		Map elements1 = profile1.getProfileElements();
+		Map elements2 = profile2.getProfileElements();
+		assertEquals(3, elements1.size());
+		assertEquals(3, elements2.size());
+		assertTrue(elements1.containsKey("TEST"));
+		assertTrue(elements2.containsKey("TEST"));
+		assertTrue(!elements1.containsKey("does-not-exist"));
+		assertTrue(!elements2.containsKey("does-not-exist"));
+		ProfileElement element1 = (ProfileElement) elements1.get("TEST2");
+		ProfileElement element2 = (ProfileElement) elements2.get("TEST2");
+		assertEquals("Testing", element1.getType());
+		assertEquals("Testing", element2.getType());
+
+		// Test the toString and getProfileString methods ... NB: this test should
+		// actually check value, not just see if they're equal.
+		assertEquals(profile1.toString(), profile2.toString());
+
+		// Test some miscellaneous query methods
+		assertEquals("Planetary Data System (PDS) - Profile Server V1.0", profile1.getResourceAttributes().getTitle());
+		assertEquals("iiop://oodt.jpl.nasa.gov:10000/JPL.PDS.PROFILE", profile1.getResourceAttributes().getResLocations()
+			.get(0));
+		assertEquals("system.profileServer", profile1.getResourceAttributes().getResClass());
+		assertEquals("Planetary Data System (PDS) - Profile Server V1.0", profile2.getResourceAttributes().getTitle());
+		assertEquals("iiop://oodt.jpl.nasa.gov:10000/JPL.PDS.PROFILE", profile2.getResourceAttributes().getResLocations()
+			.get(0));
+		assertEquals("system.profileServer", profile2.getResourceAttributes().getResClass());
+	}
+
+	/** A test profile, built from a string. */
+	private Profile profile1;
+
+	/** Another test profile, built from an XML document node. */
+	private Profile profile2;
+
+	/** Previous value of the JPL RDF namespace in the system properties. */
+	private String oldProfNS;
+
+	/** Another (static) test profile, for use by other test cases. */
+	static Profile TEST_PROFILE = new Profile(org.apache.oodt.profile.ProfileAttributesTest.TEST_PROFILE_ATTRIBUTES,
+		org.apache.oodt.profile.ResourceAttributesTest.TEST_RESOURCE_ATTRIBUTES);
+}
diff --git a/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/RangedProfileElementTest.java b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/RangedProfileElementTest.java
new file mode 100644
index 0000000..e8ede4e
--- /dev/null
+++ b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/RangedProfileElementTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import java.util.ArrayList;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import org.apache.oodt.commons.io.NullOutputStream;
+import org.apache.oodt.commons.util.XML;
+import junit.framework.TestCase;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * Unit test the {@link RangedProfileElement} class.
+ *
+ * @author Kelly
+ */ 
+public class RangedProfileElementTest extends ProfileElementTestCase {
+	/** Construct the test case for the {@link RangedProfileElement} class. */
+	public RangedProfileElementTest(String name) {
+		super(name);
+	}
+
+	protected ProfileElement createProfileElement() {
+		return new RangedProfileElement(ProfileTest.TEST_PROFILE, "name", "id", "desc", "type", "unit",
+			/*synonyms*/ new ArrayList(), /*obligation*/false, /*maxOccurrence*/1, "comment", /*min*/"-100.0",
+			/*max*/"100.0");
+	}
+
+	public void testIt() {
+		ProfileElement element = createProfileElement();
+		assertEquals("100.0", element.getMaxValue());
+		assertEquals("-100.0", element.getMinValue());
+		assertEquals(0, element.getValues().size());
+	}
+	
+	public void testXMLSerialization() throws Exception {
+		Profile p = new Profile();
+		RangedProfileElement e = new RangedProfileElement(p);
+		Document doc = XML.createDocument();
+		Node root = e.toXML(doc);
+		TransformerFactory tf = TransformerFactory.newInstance();
+		Transformer t = tf.newTransformer();
+		DOMSource s = new DOMSource(root);
+		StreamResult r = new StreamResult(new NullOutputStream());
+		t.transform(s, r);
+	}
+
+	protected void checkEnumFlag(String text) {
+		assertEquals("F", text);
+	}
+
+	protected void checkValue(String text) {
+		fail("Ranged profile element shouldn't have an enumerated value");
+	}
+
+	protected void checkMaxValue(String text) {
+		assertEquals("100.0", text);
+	}
+
+	protected void checkMinValue(String text) {
+		assertEquals("-100.0", text);
+	}
+}
diff --git a/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/ResourceAttributesTest.java b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/ResourceAttributesTest.java
new file mode 100644
index 0000000..96faa54
--- /dev/null
+++ b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/ResourceAttributesTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import org.apache.oodt.commons.io.NullOutputStream;
+import org.apache.oodt.commons.util.XML;
+import junit.framework.TestCase;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Unit test the {@link ResourceAttributes} class.
+ *
+ * @author Kelly
+ */ 
+public class ResourceAttributesTest extends TestCase {
+	/** Construct the test case for the {@link ResourceAttributes} class. */
+	public ResourceAttributesTest(String name) {
+		super(name);
+	}
+
+	public void testNoArgsCtor() {
+		ResourceAttributes blank = new ResourceAttributes();
+		assertEquals("UNKNOWN", blank.getIdentifier());
+		assertEquals(0, blank.getFormats().size());
+		assertEquals(0, blank.getCreators().size());
+		assertEquals(0, blank.getSubjects().size());
+		assertEquals(0, blank.getPublishers().size());
+		assertEquals(0, blank.getContributors().size());
+		assertEquals(0, blank.getDates().size());
+		assertEquals(0, blank.getTypes().size());
+		assertEquals(0, blank.getSources().size());
+		assertEquals(0, blank.getLanguages().size());
+		assertEquals(0, blank.getRelations().size());
+		assertEquals(0, blank.getCoverages().size());
+		assertEquals(0, blank.getRights().size());
+		assertEquals(0, blank.getResContexts().size());
+		assertEquals(0, blank.getResLocations().size());
+	}
+
+	public void testObjectMethods() {
+		List contexts = new ArrayList();
+		contexts.add("context");
+		ResourceAttributes r1 = new ResourceAttributes(null, "1", "title", Collections.EMPTY_LIST, "desc",
+			Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST,
+			Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST,
+			Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST,
+			contexts, "aggregation", "class", Collections.EMPTY_LIST);
+		ResourceAttributes r2 = new ResourceAttributes(null, "1", "title", Collections.EMPTY_LIST, "desc",
+			Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST,
+			Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST,
+			Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST,
+			contexts, "aggregation", "class", Collections.EMPTY_LIST);
+		ResourceAttributes r3 = new ResourceAttributes(null, "2", "title2", Collections.EMPTY_LIST, "desc2",
+			Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST,
+			Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST,
+			Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST,
+			contexts, "aggregation2", "class2", Collections.EMPTY_LIST);
+		assertEquals(r1, r1);
+		assertEquals(r1, r2);
+		assertTrue(!r1.equals(r3));
+		ResourceAttributes r4 = (ResourceAttributes) r3.clone();
+		assertEquals(r3, r4);
+		assertTrue(r3 != r4);
+	}
+
+	public void testSetters() {
+		ResourceAttributes q = (ResourceAttributes) TEST_RESOURCE_ATTRIBUTES.clone();
+
+		assertEquals("identifier", q.getIdentifier());
+		q.setIdentifier("newIdentifier");
+		assertEquals("newIdentifier", q.getIdentifier());
+
+		assertEquals("aggregation", q.getResAggregation());
+		q.setResAggregation("newAggergation");
+		assertEquals("newAggergation", q.getResAggregation());
+
+		assertEquals("class", q.getResClass());
+		q.setResClass("newClass");
+		assertEquals("newClass", q.getResClass());
+	}
+
+	public void testXML() throws Exception {
+		Document doc = XML.createDocument();
+		Node root = TEST_RESOURCE_ATTRIBUTES.toXML(doc);
+		assertEquals("resAttributes", root.getNodeName());
+		NodeList children = root.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node child = children.item(i);
+			String name = child.getNodeName();
+			if ("Identifier".equals(name)) {
+				assertEquals("identifier", XML.text(child));
+			} else if ("Title".equals(name)) {
+				assertEquals("title", XML.text(child));
+			} else if ("Format".equals(name)) {
+				; // ignore
+			} else if ("Description".equals(name)) {
+				assertEquals("desc", XML.text(child));
+			} else if ("Creator".equals(name)) {
+				; // ignore
+			} else if ("Subject".equals(name)) {
+				; // ignore
+			} else if ("Publisher".equals(name)) {
+				; // ignore
+			} else if ("Contributor".equals(name)) {
+				; // ignore
+			} else if ("Date".equals(name)) {
+				; // ignore
+			} else if ("Type".equals(name)) {
+				; // ignore
+			} else if ("Source".equals(name)) {
+				; // ignore
+			} else if ("Language".equals(name)) {
+				; // ignore
+			} else if ("Coverage".equals(name)) {
+				; // ignore
+			} else if ("Rights".equals(name)) {
+				; // ignore
+			} else if ("resContext".equals(name)) {
+				assertEquals("context", XML.text(child));
+			} else if ("resAggregation".equals(name)) {
+				assertEquals("aggregation", XML.text(child));
+			} else if ("resClass".equals(name)) {
+				assertEquals("class", XML.text(child));
+			} else if ("resLocation".equals(name)) {
+				; // ignore
+			} else fail("Unknown node \"" + name + "\" in XML result");
+		}
+		ResourceAttributes q = new ResourceAttributes(null, root);
+		assertEquals(TEST_RESOURCE_ATTRIBUTES, q);
+	}
+	
+	public void testXMLSerialization() throws Exception {
+		Profile p = new Profile();
+		ResourceAttributes ra = new ResourceAttributes(p);
+		Document doc = XML.createDocument();
+		Node root = ra.toXML(doc);
+		TransformerFactory tf = TransformerFactory.newInstance();
+		Transformer t = tf.newTransformer();
+		DOMSource s = new DOMSource(root);
+		StreamResult r = new StreamResult(new NullOutputStream());
+		t.transform(s, r);
+	}
+	
+	static ResourceAttributes TEST_RESOURCE_ATTRIBUTES; {
+		List contexts = Collections.singletonList("context");
+		List locations = Collections.singletonList("location");
+		TEST_RESOURCE_ATTRIBUTES = new ResourceAttributes(null, "identifier", "title",
+			Collections.EMPTY_LIST, "desc", Collections.EMPTY_LIST, Collections.EMPTY_LIST,
+			Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST,
+			Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST,
+			Collections.EMPTY_LIST, contexts, "aggregation", "class", locations);
+	}
+}
diff --git a/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/handlers/lightweight/LightweightProfileServerTest.java b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/handlers/lightweight/LightweightProfileServerTest.java
new file mode 100644
index 0000000..ea54ecf
--- /dev/null
+++ b/0.8.1-rc1/profile/src/test/java/org/apache/oodt/profile/handlers/lightweight/LightweightProfileServerTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.profile.handlers.lightweight;
+
+import org.apache.oodt.profile.ProfileElement;
+import org.apache.oodt.profile.ProfileException;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit test the LightweightProfileServer class.
+ *
+ * @author Kelly
+ */ 
+public class LightweightProfileServerTest extends TestCase {
+	/** Construct the test case for the LightweightProfileServer class. */
+	public LightweightProfileServerTest(String name) {
+		super(name);
+	}
+
+	protected void setUp() throws Exception {
+	  URL url = getClass().getResource("lightweightTest.xml");
+		server = new LightweightProfileServer(url, "testing");
+	}
+	
+	/**
+	 * Test the getID method.
+	 */
+	public void testGetID() {
+		assertEquals("testing", server.getID());
+	}
+
+	/**
+	 * Test the searching methods.
+	 */
+	public void testSearching() {
+		try {
+			List profiles;
+
+			// Try a positive search.
+			profiles = doSearch("TEST > 2 AND TEST < 30");
+			assertEquals(1, profiles.size());
+			SearchableProfile profile = (SearchableProfile) profiles.get(0);
+			assertEquals("PROFILE1", profile.getProfileAttributes().getID());
+			Map elements = profile.getProfileElements();
+			assertEquals(3, elements.size());
+			ProfileElement element = (ProfileElement) elements.get("TEST");
+			assertNotNull(element);
+			assertEquals("3.14159", element.getID());
+
+			// Now a negative one.
+			profiles = doSearch("NONEXISTENT = 452712917824812123125100884");
+			assertEquals(0, profiles.size());
+
+			// Now one that has multiple elements from one profile
+			profiles = doSearch("TEST <= 14 AND TEST2 >= 10");
+			assertEquals(1, profiles.size());
+			profile = (SearchableProfile) profiles.get(0);
+			assertEquals("PROFILE1", profile.getProfileAttributes().getID());
+			elements = profile.getProfileElements();
+			assertEquals(3, elements.size());
+			assertTrue(elements.containsKey("TEST"));
+			assertTrue(elements.containsKey("TEST2"));
+
+			// And again, but with OR instead of AND
+			profiles = doSearch("TEST <= 14 OR TEST2 >= 10");
+			assertEquals(1, profiles.size());
+			profile = (SearchableProfile) profiles.get(0);
+			assertEquals("PROFILE1", profile.getProfileAttributes().getID());
+			elements = profile.getProfileElements();
+			assertEquals(3, elements.size());
+			assertTrue(elements.containsKey("TEST"));
+			assertTrue(elements.containsKey("TEST2"));
+
+			// And again, but with one of the elements being not found
+			profiles = doSearch("NONEXISTENT = 123456789 OR TEST2 <= 1000000");
+			assertEquals(1, profiles.size());
+			profile = (SearchableProfile) profiles.get(0);
+			assertEquals("PROFILE1", profile.getProfileAttributes().getID());
+			elements = profile.getProfileElements();
+			assertEquals(3, elements.size());
+			assertTrue(elements.containsKey("TEST2"));
+
+			// And again, but spanning profiles
+			profiles = doSearch("TEST2 = 48 OR TEST4 = 192");
+			assertEquals(2, profiles.size());
+			for (Iterator i = profiles.iterator(); i.hasNext();) {
+				profile = (SearchableProfile) i.next();
+				elements = profile.getProfileElements();
+				assertEquals(3, elements.size());
+				if (profile.getProfileAttributes().getID().equals("PROFILE1")) {
+					assertTrue(elements.containsKey("TEST2"));
+				} else if (profile.getProfileAttributes().getID().equals("PROFILE2")) {
+					assertTrue(elements.containsKey("TEST4"));
+				} else fail("Profile \"" + profile.getProfileAttributes().getID() + "\" matched, but shouldn't");
+			}
+
+			// And again, but with a query on the "from" part.
+			profiles = doSearch("( TEST2 = 48 OR TEST4 = 192 ) AND Creator = Alice");
+			assertEquals(1, profiles.size());
+			profile = (SearchableProfile) profiles.get(0);
+			assertEquals("PROFILE1", profile.getProfileAttributes().getID());
+
+			// And again, but on a nonenumerated element with no min/max values.
+			profiles = doSearch("TEST5 = GEEBA");
+			assertEquals(1, profiles.size());
+			profile = (SearchableProfile) profiles.get(0);
+			assertEquals("PROFILE2", profile.getProfileAttributes().getID());
+
+			// And again, but with "RETURN =" parts.
+			//fail("Not yet implemented");
+
+		} catch (ProfileException ex) {
+			fail("Profile server failed with excepton: " + ex.getMessage());
+		}
+	}
+
+	/**
+	 * Execute the given search.
+	 *
+	 * @param expr The search experssion.
+	 * @return List of matching profiles.
+	 * @throws ProfileException If the profile server fails.
+	 */
+	private List doSearch(String expr) throws ProfileException {
+		XMLQuery query = new XMLQuery(expr, "test1", "LightweightProfileServerTest",
+			"This query is to test the LightweightProfileServer", /*ddId*/null, /*resultModeId*/null,
+			/*propType*/null, /*propLevels*/null, XMLQuery.DEFAULT_MAX_RESULTS);
+		return server.findProfiles(query);
+	}
+		
+
+	/** The lightweight profile server being tested. */
+	private LightweightProfileServer server;
+}
diff --git a/0.8.1-rc1/profile/src/test/resources/org/apache/oodt/profile/handlers/lightweight/lightweightTest.xml b/0.8.1-rc1/profile/src/test/resources/org/apache/oodt/profile/handlers/lightweight/lightweightTest.xml
new file mode 100644
index 0000000..502081a
--- /dev/null
+++ b/0.8.1-rc1/profile/src/test/resources/org/apache/oodt/profile/handlers/lightweight/lightweightTest.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright 2000-2002 California Institute of Technology.  ALL RIGHTS
+RESERVED.  U.S. Government Sponsorship acknowledged.
+
+$Id: lightweightTest.xml,v 1.2 2004/06/14 16:13:02 kelly Exp $
+-->
+<!DOCTYPE profiles PUBLIC "-//JPL//DTD EDA Profile 1.1//EN" "http://oodt.jpl.nasa.gov/grid-profile/dtd/prof.dtd">
+<profiles>
+  <profile>
+    <profAttributes>
+      <profId>PROFILE1</profId>
+      <profType>profile</profType>
+      <profStatusId>active</profStatusId>
+      <profSecurityType>NULL</profSecurityType>
+      <profRevisionNote>1.0</profRevisionNote>
+    </profAttributes>
+    <resAttributes>
+      <Identifier>TEST_PROFILE_1</Identifier>
+      <Title>Test profile number 1</Title>
+      <Format>text/html</Format>
+      <Creator>Alice</Creator>
+      <resContext>TEST</resContext>
+      <resAggregation>N/A</resAggregation>
+      <resClass>system.profileServer</resClass>
+      <resLocation>iiop://oodt.jpl.nasa.gov:10000/Test.Profile</resLocation>
+    </resAttributes>
+    <profElement>
+      <elemId>3.14159</elemId>
+      <elemName>TEST</elemName>
+      <elemDesc>This is a test element</elemDesc>
+      <elemType>Testing</elemType>
+      <elemUnit>fortnights-per-furlong</elemUnit>
+      <elemEnumFlag>F</elemEnumFlag>
+      <elemMinValue>0</elemMinValue>
+      <elemMaxValue>32</elemMaxValue>
+      <elemComment>Testing only.</elemComment>
+    </profElement>
+    <profElement>
+      <elemId>3.2</elemId>
+      <elemName>TEST2</elemName>
+      <elemDesc>This is another test element</elemDesc>
+      <elemType>Testing</elemType>
+      <elemUnit>fleas-per-tick</elemUnit>
+      <elemEnumFlag>F</elemEnumFlag>
+      <elemMinValue>32</elemMinValue>
+      <elemMaxValue>64</elemMaxValue>
+      <elemComment>More testing.</elemComment>
+    </profElement>
+    <profElement>
+      <elemId>3.5</elemId>
+      <elemName>TEST3</elemName>
+      <elemDesc>Yet another test element</elemDesc>
+      <elemType>Testing</elemType>
+      <elemEnumFlag>T</elemEnumFlag>
+      <elemValue>alpha</elemValue>
+      <elemValue>beta</elemValue>
+      <elemValue>gamma</elemValue>
+      <elemValue>delta</elemValue>
+      <elemComment>A bunch of greek letters, eh?</elemComment>
+    </profElement>
+  </profile>
+
+  <profile>
+    <profAttributes>
+      <profId>PROFILE2</profId>
+      <profType>profile</profType>
+      <profStatusId>active</profStatusId>
+      <profSecurityType>NULL</profSecurityType>
+      <profRevisionNote>1.0</profRevisionNote>
+    </profAttributes>
+    <resAttributes>
+      <Identifier>TEST_PROFILE_2</Identifier>
+      <Title>Test profile number 2</Title>
+      <Format>text/html</Format>
+      <Creator>Bill</Creator>
+      <resContext>TEST</resContext>
+      <resAggregation>N/A</resAggregation>
+      <resClass>system.profileServer</resClass>
+      <resLocation>iiop://oodt.jpl.nasa.gov:10000/Test.Profile</resLocation>
+    </resAttributes>
+    <profElement>
+      <elemId>3.5</elemId>
+      <elemName>TEST3</elemName>
+      <elemDesc>Yet another test element</elemDesc>
+      <elemType>Testing</elemType>
+      <elemEnumFlag>T</elemEnumFlag>
+      <elemValue>alpha</elemValue>
+      <elemValue>beta</elemValue>
+      <elemValue>gamma</elemValue>
+      <elemValue>delta</elemValue>
+      <elemComment>A bunch of greek letters, eh?</elemComment>
+    </profElement>
+    <profElement>
+      <elemId>3.6</elemId>
+      <elemName>TEST4</elemName>
+      <elemDesc>And still another test element</elemDesc>
+      <elemType>Testing</elemType>
+      <elemEnumFlag>F</elemEnumFlag>
+      <elemMinValue>128</elemMinValue>
+      <elemMaxValue>256</elemMaxValue>
+    </profElement>
+    <profElement>
+      <elemId>3.7</elemId>
+      <elemName>TEST5</elemName>
+      <elemDesc>This is a nonenumerated field with no min/max values, meaning it should always match.</elemDesc>
+      <elemType>char</elemType>
+      <elemEnumFlag>F</elemEnumFlag>
+    </profElement>
+  </profile>
+</profiles>
diff --git a/0.8.1-rc1/profile/src/test/resources/org/apache/oodt/profile/test.xml b/0.8.1-rc1/profile/src/test/resources/org/apache/oodt/profile/test.xml
new file mode 100644
index 0000000..69b41b3
--- /dev/null
+++ b/0.8.1-rc1/profile/src/test/resources/org/apache/oodt/profile/test.xml
@@ -0,0 +1,57 @@
+<!-- DO NOT put the XML processing instruction or DOCTYPE decl in this -->
+<!-- file!  They're added by the unit test automatically. -->
+<!-- Copyright 2000-2002 California Institute of Technology.  ALL -->
+<!-- RIGHTS RESERVED.  U.S. Government Sponsorship acknowledged. -->
+<!-- $Id: test.xml,v 1.1.1.1 2004/03/02 20:53:39 kelly Exp $ -->
+<profile>
+  <profAttributes>
+    <profId>OODT_PDS_PROFILE_SERVER</profId>
+    <profType>profile</profType>
+    <profStatusId>active</profStatusId>
+    <profSecurityType>NULL</profSecurityType>
+    <profRevisionNote>1999-09-30</profRevisionNote>
+  </profAttributes>
+  <resAttributes>
+    <Identifier>PDS_PROFILE_SERVER</Identifier>
+    <Title>Planetary Data System (PDS) - Profile Server V1.0</Title>
+    <Format>text/html</Format>
+    <resContext>PDS</resContext>
+    <resAggregation>N/A</resAggregation>
+    <resClass>system.profileServer</resClass>
+    <resLocation>iiop://oodt.jpl.nasa.gov:10000/JPL.PDS.PROFILE</resLocation>
+  </resAttributes>
+  <profElement>
+    <elemId>3.14159</elemId>
+    <elemName>TEST</elemName>
+    <elemDesc>This is a test element</elemDesc>
+    <elemType>Testing</elemType>
+    <elemUnit>fortnights-per-furlong</elemUnit>
+    <elemEnumFlag>F</elemEnumFlag>
+    <elemMinValue>0</elemMinValue>
+    <elemMaxValue>32</elemMaxValue>
+    <elemComment>Testing only.</elemComment>
+  </profElement>
+  <profElement>
+    <elemId>3.2</elemId>
+    <elemName>TEST2</elemName>
+    <elemDesc>This is another test element</elemDesc>
+    <elemType>Testing</elemType>
+    <elemUnit>fleas-per-tick</elemUnit>
+    <elemEnumFlag>F</elemEnumFlag>
+    <elemMinValue>32</elemMinValue>
+    <elemMaxValue>64</elemMaxValue>
+    <elemComment>More testing.</elemComment>
+  </profElement>
+  <profElement>
+    <elemId>3.5</elemId>
+    <elemName>TEST3</elemName>
+    <elemDesc>Yet another test element</elemDesc>
+    <elemType>Testing</elemType>
+    <elemEnumFlag>T</elemEnumFlag>
+    <elemValue>alpha</elemValue>
+    <elemValue>beta</elemValue>
+    <elemValue>gamma</elemValue>
+    <elemValue>delta</elemValue>
+    <elemComment>A bunch of greek letters, eh?</elemComment>
+  </profElement>
+</profile>
diff --git a/0.8.1-rc1/profile/src/test/resources/test.xml b/0.8.1-rc1/profile/src/test/resources/test.xml
new file mode 100644
index 0000000..69b41b3
--- /dev/null
+++ b/0.8.1-rc1/profile/src/test/resources/test.xml
@@ -0,0 +1,57 @@
+<!-- DO NOT put the XML processing instruction or DOCTYPE decl in this -->
+<!-- file!  They're added by the unit test automatically. -->
+<!-- Copyright 2000-2002 California Institute of Technology.  ALL -->
+<!-- RIGHTS RESERVED.  U.S. Government Sponsorship acknowledged. -->
+<!-- $Id: test.xml,v 1.1.1.1 2004/03/02 20:53:39 kelly Exp $ -->
+<profile>
+  <profAttributes>
+    <profId>OODT_PDS_PROFILE_SERVER</profId>
+    <profType>profile</profType>
+    <profStatusId>active</profStatusId>
+    <profSecurityType>NULL</profSecurityType>
+    <profRevisionNote>1999-09-30</profRevisionNote>
+  </profAttributes>
+  <resAttributes>
+    <Identifier>PDS_PROFILE_SERVER</Identifier>
+    <Title>Planetary Data System (PDS) - Profile Server V1.0</Title>
+    <Format>text/html</Format>
+    <resContext>PDS</resContext>
+    <resAggregation>N/A</resAggregation>
+    <resClass>system.profileServer</resClass>
+    <resLocation>iiop://oodt.jpl.nasa.gov:10000/JPL.PDS.PROFILE</resLocation>
+  </resAttributes>
+  <profElement>
+    <elemId>3.14159</elemId>
+    <elemName>TEST</elemName>
+    <elemDesc>This is a test element</elemDesc>
+    <elemType>Testing</elemType>
+    <elemUnit>fortnights-per-furlong</elemUnit>
+    <elemEnumFlag>F</elemEnumFlag>
+    <elemMinValue>0</elemMinValue>
+    <elemMaxValue>32</elemMaxValue>
+    <elemComment>Testing only.</elemComment>
+  </profElement>
+  <profElement>
+    <elemId>3.2</elemId>
+    <elemName>TEST2</elemName>
+    <elemDesc>This is another test element</elemDesc>
+    <elemType>Testing</elemType>
+    <elemUnit>fleas-per-tick</elemUnit>
+    <elemEnumFlag>F</elemEnumFlag>
+    <elemMinValue>32</elemMinValue>
+    <elemMaxValue>64</elemMaxValue>
+    <elemComment>More testing.</elemComment>
+  </profElement>
+  <profElement>
+    <elemId>3.5</elemId>
+    <elemName>TEST3</elemName>
+    <elemDesc>Yet another test element</elemDesc>
+    <elemType>Testing</elemType>
+    <elemEnumFlag>T</elemEnumFlag>
+    <elemValue>alpha</elemValue>
+    <elemValue>beta</elemValue>
+    <elemValue>gamma</elemValue>
+    <elemValue>delta</elemValue>
+    <elemComment>A bunch of greek letters, eh?</elemComment>
+  </profElement>
+</profile>
diff --git a/0.8.1-rc1/protocol/api/pom.xml b/0.8.1-rc1/protocol/api/pom.xml
new file mode 100644
index 0000000..3e852ad
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/pom.xml
@@ -0,0 +1,134 @@
+<?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. -->
+<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>
+	<parent>
+		<groupId>org.apache.oodt</groupId>
+		<artifactId>oodt-core</artifactId>
+		<version>0.8.1</version>
+		<relativePath>../../core/pom.xml</relativePath>
+	</parent>
+	<artifactId>cas-protocol-api</artifactId>
+	<name>CAS Protocol</name>
+	<profiles>
+		<profile>
+			<id>audit</id>
+			<activation>
+				<activeByDefault>false</activeByDefault>
+			</activation>
+			<build>
+				<plugins>
+					<plugin>
+						<groupId>org.codehaus.mojo</groupId>
+						<artifactId>rat-maven-plugin</artifactId>
+						<configuration>
+							<excludes>
+								<exclude>**/resources/examples/**/*</exclude>
+							</excludes>
+						</configuration>
+						<executions>
+							<execution>
+								<phase>verify</phase>
+								<goals>
+									<goal>check</goal>
+								</goals>
+							</execution>
+						</executions>
+					</plugin>
+				</plugins>
+			</build>
+		</profile>
+	</profiles>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<version>2.2-beta-2</version>
+				<configuration>
+					<descriptors>
+						<descriptor>src/main/assembly/assembly.xml</descriptor>
+					</descriptors>
+					<archive>
+						<manifest>
+							<mainClass>org.apache.oodt.cas.protocol.system.CLProtocolManager</mainClass>
+						</manifest>
+					</archive>
+				</configuration>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>single</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+    <resources>
+      <resource>
+        <targetPath>org/apache/oodt/cas/protocol</targetPath>
+        <directory>${basedir}/src/main/resources/policy</directory>
+        <includes>
+          <include>protocol-config.xml</include>
+        </includes>
+      </resource>
+    </resources>
+	</build>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>oodt-commons</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>cas-metadata</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-cli</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+		<dependency>
+			<groupId>commons-lang</groupId>
+			<artifactId>commons-lang</artifactId>
+			<version>2.3</version>
+		</dependency>
+		<dependency>
+			<groupId>xmlrpc</groupId>
+			<artifactId>xmlrpc</artifactId>
+			<version>2.0.1</version>
+		</dependency>
+		<dependency>
+			<groupId>com.thoughtworks.xstream</groupId>
+			<artifactId>xstream</artifactId>
+			<version>1.3.1</version>
+			<exclusions>
+				<exclusion>
+					<!-- xom is an optional dependency of xstream. Its also an Apache incompatible 
+						license -->
+					<groupId>xom</groupId>
+					<artifactId>xom</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.2</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+</project>
diff --git a/0.8.1-rc1/protocol/api/src/main/assembly/assembly.xml b/0.8.1-rc1/protocol/api/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..9af13fd
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/assembly/assembly.xml
@@ -0,0 +1,94 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<assembly>
+  <id>dist</id>
+  <formats>
+    <format>tar.gz</format>
+    <format>zip</format>
+  </formats>
+  <includeBaseDirectory>true</includeBaseDirectory>
+  <baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/bin</directory>
+      <outputDirectory>bin</outputDirectory>
+      <includes/>
+      <fileMode>755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>etc</outputDirectory>
+      <includes>
+        <include>*.properties</include>
+        <include>jssecacerts</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/examples</directory>
+      <outputDirectory>etc/examples</outputDirectory>
+      <excludes/>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>logs</outputDirectory>
+      <includes>
+        <include>REMOVE.log</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/policy</directory>
+      <outputDirectory>policy</outputDirectory>
+      <includes>
+        <include>cmd-line-actions.xml</include>
+        <include>cmd-line-options.xml</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+    <directory>${basedir}/src/main/java/org/apache/oodt/cas/protocol</directory>
+      <outputDirectory>policy</outputDirectory>
+      <includes>
+        <include>protocol-config.xml</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>lib</outputDirectory>
+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>
+      <unpackOptions/>
+    </dependencySet>
+  </dependencySets>
+</assembly>
+
diff --git a/0.8.1-rc1/protocol/api/src/main/bin/protocol b/0.8.1-rc1/protocol/api/src/main/bin/protocol
new file mode 100644
index 0000000..ff4cc20
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/bin/protocol
@@ -0,0 +1,29 @@
+#!/bin/csh
+
+# 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.
+
+set args
+
+if ( $#args > 0 ) then
+        set args = "$*"
+endif
+
+${JAVA_HOME}/bin/java \
+        -Djava.ext.dirs=../lib \
+        -Djava.util.logging.config.file=../etc/logging.properties \
+        -Dorg.apache.oodt.cas.cli.action.spring.config=../policy/cmd-line-actions.xml \
+        -Dorg.apache.oodt.cas.cli.option.spring.config=../policy/cmd-line-options.xml \
+        org.apache.oodt.cas.protocol.system.ProtocolCommandLine ${args}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/Protocol.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/Protocol.java
new file mode 100644
index 0000000..bbe05e2
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/Protocol.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.auth.Authentication;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+import org.apache.oodt.cas.protocol.util.ProtocolFileFilter;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+
+/**
+ * Interface for communication over different transfer protocols
+ * 
+ * @author bfoster
+ * @version $Revision$
+ */
+public interface Protocol {
+
+    public void connect(String host, Authentication authentication) throws ProtocolException;
+    
+    public void close() throws ProtocolException;
+
+    public boolean connected();
+    
+    public void cd(ProtocolFile file) throws ProtocolException;
+
+    public void cdRoot() throws ProtocolException;
+
+    public void cdHome() throws ProtocolException;
+
+    public void get(ProtocolFile fromFile, File toFile) throws ProtocolException;
+
+    public void put(File fromFile, ProtocolFile toFile) throws ProtocolException;
+    
+    public ProtocolFile pwd() throws ProtocolException;
+
+    public List<ProtocolFile> ls() throws ProtocolException;
+
+    public List<ProtocolFile> ls(ProtocolFileFilter filter) throws ProtocolException;
+
+    public void delete(ProtocolFile file) throws ProtocolException;
+
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/ProtocolFactory.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/ProtocolFactory.java
new file mode 100644
index 0000000..ed6153f
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/ProtocolFactory.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol;
+
+/**
+ * Factory for creating {@link Protocol}s
+ * 
+ * @author bfoster
+ * @version $Revision$
+ */
+public interface ProtocolFactory {
+
+    public Protocol newInstance();
+
+    public String getSchema();
+    
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/ProtocolFile.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/ProtocolFile.java
new file mode 100644
index 0000000..835dcc7
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/ProtocolFile.java
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol;
+
+//APACHE imports
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.Validate;
+
+/**
+ * A path representing a file/directory over some {@link Protocol}
+ * 
+ * @author bfoster
+ */
+public class ProtocolFile {
+
+	public static final String SEPARATOR = "/";
+	
+	private String path;
+	private boolean isDir;
+	private ProtocolFile parent;
+	
+	public ProtocolFile(String path, boolean isDir) {
+		this(null, path, isDir);
+	}
+	
+	public ProtocolFile(ProtocolFile parent, String path, boolean isDir) {
+		this.parent = parent;
+		this.isDir = isDir;
+		Validate.notNull(path, "ProtocolFile's path cannot be NULL");
+		this.path = path.length() > 0 && !path.equals(SEPARATOR) ? StringUtils
+				.chomp(path, SEPARATOR) : path;
+	}
+
+	/**
+	 * True is this path is a directory.
+	 * 
+	 * @return True if directory, false otherwise
+	 */
+	public boolean isDir() {
+		return isDir;
+	}
+
+	/**
+	 * Gets the {@link String} representation of this path.
+	 * 
+	 * @return The {@link String} representation of this path
+	 */
+	public String getPath() {
+		return path;
+	}
+
+	/**
+	 * Gets the name of this file this path represents (i.e. '/path/to/file' will
+	 * return 'file')
+	 * 
+	 * @return The name of the file this path represents
+	 */
+	public String getName() {
+		return path.substring(path.lastIndexOf(SEPARATOR) + 1);
+	}
+
+	/**
+	 * True if this path is a relative path (i.e. does not start with
+	 * {@link SEPARATOR}).
+	 * 
+	 * @return True is this a relative path, false otherwise
+	 */
+	public boolean isRelative() {
+		return !path.startsWith(SEPARATOR);
+	}
+
+	/**
+	 * Gets the parent {@link ProtocolFile} for this path.
+	 * 
+	 * @return The parent {@link ProtocolFile}
+	 */
+	public ProtocolFile getParent() {
+		if (parent != null) {
+			return parent;
+		} else {
+			int index = StringUtils.lastIndexOf(path, SEPARATOR);
+			return (index > 0) ? new ProtocolFile(StringUtils.substring(path, 0, index), true) : null;
+		}
+	}
+
+	/**
+	 * Get Absolute pathed {@link ProtocolFile} version of this {@link ProtocolFile}.
+	 * 
+	 * @return the absolute pathed version of this {@link ProtocolFile}
+	 */
+	public ProtocolFile getAbsoluteFile() {
+		if (this.isRelative()) {
+		  ProtocolFile parent = this.getParent();
+		  if (parent != null) {
+				return new ProtocolFile(StringUtils.chomp(parent.getAbsoluteFile().getPath(), SEPARATOR)
+						+ SEPARATOR + this.getPath(), this.isDir());
+			}
+		}
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public int hashCode() {
+		return this.getPath().hashCode();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean equals(Object path) {
+		if (path instanceof ProtocolFile) {
+			ProtocolFile p = (ProtocolFile) path;
+			return (p.getAbsoluteFile().getPath()
+					.equals(this.getAbsoluteFile().getPath()) && p.isDir() == this
+					.isDir());
+		}
+		return false;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String toString() {
+		return "{parent = '" + this.parent + "', path = '" + path + "', isDir = '" + isDir + "'}";
+	}
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/auth/Authentication.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/auth/Authentication.java
new file mode 100644
index 0000000..381e7ff
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/auth/Authentication.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.auth;
+
+/**
+ * Authentication interface for {@link Protocol} connections
+ * 
+ * @author bfoster
+ */
+public interface Authentication {
+
+	public String getUser();
+	
+	public String getPass();
+
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/auth/BasicAuthentication.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/auth/BasicAuthentication.java
new file mode 100644
index 0000000..27e4435
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/auth/BasicAuthentication.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.auth;
+
+import org.apache.commons.lang.Validate;
+
+/**
+ * Basic username and password {@link Authentication}
+ * 
+ * @author bfoster
+ * @version $Revision$
+ */
+public class BasicAuthentication implements Authentication {
+
+	private String user;
+	private String pass;
+	
+	public BasicAuthentication(String user, String pass) {
+		Validate.notNull(user, "NULL user not allowed");
+		Validate.notNull(pass, "NULL pass not allowed");
+		this.user = user;
+		this.pass = pass;
+	}
+	
+	public String getUser() {
+		return user;
+	}
+
+	public String getPass() {
+		return pass;
+	}
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/auth/NoAuthentication.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/auth/NoAuthentication.java
new file mode 100644
index 0000000..2f402d5
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/auth/NoAuthentication.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.auth;
+
+/**
+ * Use when {@link Protocol} requires no {@link Authentication} 
+ * 
+ * @author bfoster
+ */
+public class NoAuthentication implements Authentication {
+
+	public String getUser() {
+		return "";
+	}
+
+	public String getPass() {
+		return "";
+	}
+
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/BasicVerifyCliAction.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/BasicVerifyCliAction.java
new file mode 100644
index 0000000..113fa9e
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/BasicVerifyCliAction.java
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+import org.apache.oodt.cas.protocol.system.ProtocolManager;
+import org.apache.oodt.cas.protocol.verify.ProtocolVerifier;
+
+/**
+ * Action for determining whether a given {@link Protocol} or auto-determined
+ * {@link Protocol} via {@link ProtocolManager} can connect and pass
+ * verification of the given {@link Verifier} for given site.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class BasicVerifyCliAction extends ProtocolCliAction {
+
+   private ProtocolVerifier verifier;
+   private ProtocolFactory factory;
+
+   private boolean lastVerificationResult;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         if (factory != null) {
+            Protocol protocol = factory.newInstance();
+            if (lastVerificationResult = verifier.verify(protocol, getSite(),
+                  getAuthentication())) {
+               printer.println("Protocol '"
+                     + protocol.getClass().getCanonicalName()
+                     + "' PASSED verification!");
+            } else {
+               printer.println("Protocol '"
+                     + protocol.getClass().getCanonicalName()
+                     + "' FAILED verification!");
+            }
+         } else {
+            Protocol protocol = getProtocolManager().getProtocolBySite(
+                  getSite(), getAuthentication(), verifier);
+            if (lastVerificationResult = protocol != null) {
+               printer.println("Protocol '"
+                     + protocol.getClass().getCanonicalName()
+                     + "' PASSED verification!");
+            } else {
+               printer.println("No Protocol determined, FAILED verification!");
+            }
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to verify factory '"
+               + factory + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setVerifier(ProtocolVerifier verifier) {
+      this.verifier = verifier;
+   }
+
+   public void setProtocolFactory(ProtocolFactory factory) {
+      this.factory = factory;
+   }
+
+   protected boolean getLastVerificationResults() {
+      return lastVerificationResult;
+   }
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/CrossProtocolTransferCliAction.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/CrossProtocolTransferCliAction.java
new file mode 100644
index 0000000..84feeb8
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/CrossProtocolTransferCliAction.java
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.cli.action;
+
+//OODT imports
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.UUID;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.auth.Authentication;
+import org.apache.oodt.cas.protocol.auth.BasicAuthentication;
+import org.apache.oodt.cas.protocol.auth.NoAuthentication;
+import org.apache.oodt.cas.protocol.system.ProtocolManager;
+import org.apache.oodt.cas.protocol.verify.ProtocolVerifier;
+import org.apache.oodt.cas.protocol.verify.ProtocolVerifierFactory;
+
+/**
+ * {@link ProtocolAction} for transferring a file from one host to another
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class CrossProtocolTransferCliAction extends ProtocolCliAction {
+
+   private URI fromUri;
+   private URI toUri;
+   private ProtocolVerifierFactory verifierFactory;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         ProtocolVerifier verifier = null;
+         if (verifierFactory != null) {
+            verifier = verifierFactory.newInstance();
+         }
+
+         File localFile = createTempDownloadFile();
+         if (localFile == null) {
+            throw new Exception("Failed to create tempory local file");
+         }
+
+         ProtocolManager protocolManager = getProtocolManager();
+         Protocol fromProtocol = protocolManager.getProtocolBySite(fromUri,
+               getAuthentication(fromUri), verifier);
+         if (fromProtocol == null) {
+            throw new Exception("Failed to get protocol for 'from' URI '"
+                  + fromUri + "'");
+         }
+
+         Protocol toProtocol = protocolManager.getProtocolBySite(toUri,
+               getAuthentication(toUri), verifier);
+         if (toProtocol == null) {
+            throw new Exception("Failed to get protocol for 'to' URI '" + toUri
+                  + "'");
+         }
+
+         fromProtocol
+               .get(new ProtocolFile(fromUri.getPath(), false), localFile);
+         toProtocol.put(localFile, new ProtocolFile(toUri.getPath(), false));
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to transfer between 2 protocols : " + e.getMessage(), e);
+      }
+   }
+
+   public void setFromUri(String fromUri) throws URISyntaxException {
+      this.fromUri = new URI(fromUri);
+   }
+
+   public void setToUri(String toUri) throws URISyntaxException {
+      this.toUri = new URI(toUri);
+   }
+
+   public void setVerifierFactory(ProtocolVerifierFactory verifierFactory) {
+      this.verifierFactory = verifierFactory;
+   }
+
+   private File createTempDownloadFile() {
+      File bogusFile = null;
+      try {
+         bogusFile = File.createTempFile("bogus", "bogus");
+         File tmpDir = new File(bogusFile.getParentFile(), "ProtocolTransfer/"
+               + UUID.randomUUID().toString());
+         tmpDir.mkdirs();
+         return new File(tmpDir, "temp_file");
+      } catch (Exception e) {
+         return null;
+      } finally {
+         try {
+            bogusFile.delete();
+         } catch (Exception e) {
+         }
+      }
+   }
+
+   private Authentication getAuthentication(URI uri) {
+      if (uri.getUserInfo() != null) {
+         String[] userInfo = uri.getUserInfo().split("\\:");
+         return new BasicAuthentication(userInfo[0], userInfo[1]);
+      } else {
+         return new NoAuthentication();
+      }
+   }
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/DeleteEmptyDirectoriesCliAction.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/DeleteEmptyDirectoriesCliAction.java
new file mode 100644
index 0000000..664c8d7
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/DeleteEmptyDirectoriesCliAction.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.cli.action;
+
+// JDK imports
+import java.util.List;
+import java.util.regex.Pattern;
+
+
+
+// OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.verify.ProtocolVerifierFactory;
+
+/**
+ * {@link ProtocolAction} for deleting empty files from site.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class DeleteEmptyDirectoriesCliAction extends ProtocolCliAction {
+
+  private String directoryRegex = ".+";
+  private ProtocolVerifierFactory verifierFactory;
+
+  @Override
+  public void execute(ActionMessagePrinter printer) throws CmdLineActionException {
+    try {
+      Protocol protocol = getProtocolManager().getProtocolBySite(
+          getSite(), getAuthentication(), verifierFactory.newInstance());
+      List<ProtocolFile> files = protocol.ls();
+      for (ProtocolFile file : files) {
+        if (file.isDir() && Pattern.matches(directoryRegex, file.getName())) {
+          try {
+            protocol.delete(file);
+            printer.println("Success: " + file.getPath());
+          } catch (Exception e) {
+            printer.println("Failed: " + file.getPath());
+          }
+        }
+      }
+    } catch (Exception e) {
+      throw new CmdLineActionException("Failed to delete directories", e);
+    }
+  }
+
+  public void setDirectoryRegex(String directoryRegex) {
+    this.directoryRegex = directoryRegex;
+  }
+
+  public void setVerifierFactory(ProtocolVerifierFactory verifierFactory) {
+    this.verifierFactory = verifierFactory;
+  }
+}
+
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/DownloadCliAction.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/DownloadCliAction.java
new file mode 100644
index 0000000..7ed0b64
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/DownloadCliAction.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.cli.action;
+
+//JDK imports
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.system.ProtocolManager;
+
+/**
+ * A {@link ProtocolAction} which will downlaod a url
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class DownloadCliAction extends ProtocolCliAction {
+
+   protected URI uri;
+   protected String toDir;
+   protected Protocol usedProtocol;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         usedProtocol = createProtocol(getProtocolManager());
+         ProtocolFile fromFile = createProtocolFile();
+         String toFilename = fromFile.equals(ProtocolFile.SEPARATOR)
+               || fromFile.getName().isEmpty() ? uri.getHost() : fromFile
+               .getName();
+         File toFile = (toDir != null) ? new File(toDir, toFilename)
+               : new File(toFilename);
+         usedProtocol.get(fromFile, toFile.getAbsoluteFile());
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to download : "
+               + e.getMessage(), e);
+      }
+   }
+
+   public void setUrl(String urlString) throws URISyntaxException {
+      uri = new URI(urlString);
+   }
+
+   public void setToDir(String toDir) {
+      this.toDir = toDir;
+   }
+
+   protected Protocol getUsedProtocol() {
+      return usedProtocol;
+   }
+
+   protected ProtocolFile createProtocolFile() throws URISyntaxException {
+      return new ProtocolFile(uri.getPath(), false);
+   }
+
+   protected Protocol createProtocol(ProtocolManager protocolManager)
+         throws URISyntaxException {
+      return protocolManager.getProtocolBySite(
+            new URI(uri.getScheme(), uri.getHost(), null, null),
+            getAuthentication(), null);
+   }
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/GetSupportedFactoriesCliAction.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/GetSupportedFactoriesCliAction.java
new file mode 100644
index 0000000..9402949
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/GetSupportedFactoriesCliAction.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+
+/**
+ * {@link ProtocolAction} for get a list of supported {@link ProtocolFactory}s.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetSupportedFactoriesCliAction extends ProtocolCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         printer.println("Supported Factories:");
+         for (ProtocolFactory factory : getProtocolManager().getFactories()) {
+            System.out.println(" - " + factory.getClass().getCanonicalName());
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get supported factories : " + e.getMessage(), e);
+      }
+   }
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/ProtocolCliAction.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/ProtocolCliAction.java
new file mode 100644
index 0000000..39e8784
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/cli/action/ProtocolCliAction.java
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.cli.action;
+
+//JDK imports
+import java.net.URI;
+import java.net.URISyntaxException;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.protocol.auth.Authentication;
+import org.apache.oodt.cas.protocol.auth.BasicAuthentication;
+import org.apache.oodt.cas.protocol.auth.NoAuthentication;
+import org.apache.oodt.cas.protocol.config.SpringProtocolConfig;
+import org.apache.oodt.cas.protocol.system.ProtocolManager;
+
+/**
+ * Action used to perform some task via a {@link ProtocolManager}
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public abstract class ProtocolCliAction extends CmdLineAction {
+
+   private String user;
+   private String pass;
+   private String site;
+   private ProtocolManager protocolManager;
+
+   public void setUser(String user) {
+      this.user = user;
+   }
+
+   public void setPass(String pass) {
+      this.pass = pass;
+   }
+
+   public void setSite(String site) {
+      this.site = site;
+   }
+
+   public URI getSite() throws URISyntaxException {
+      return site != null ? new URI(site) : null;
+   }
+
+   public Authentication getAuthentication() {
+      if (user == null || pass == null) {
+         return new NoAuthentication();
+      } else {
+         return new BasicAuthentication(user, pass);
+      }
+   }
+
+   public void setProtocolManager(ProtocolManager protocolManager) {
+      this.protocolManager = protocolManager;
+   }
+
+   public ProtocolManager getProtocolManager() throws Exception {
+      if (protocolManager != null) {
+         return protocolManager;
+      }
+      String protocolConfig = PathUtils
+            .doDynamicReplacement(System
+                  .getProperty(
+                        "org.apache.oodt.cas.protocol.manager.config.file",
+                        "classpath:/org/apache/oodt/cas/protocol/protocol-config.xml"));
+      return protocolManager = new ProtocolManager(new SpringProtocolConfig(
+            protocolConfig));
+   }
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/config/ProtocolConfig.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/config/ProtocolConfig.java
new file mode 100644
index 0000000..2e2951c
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/config/ProtocolConfig.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.config;
+
+//JDK imports
+import java.net.URI;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+import org.apache.oodt.cas.protocol.system.ProtocolManager;
+
+/**
+ * Protocol configuration for configuring {@link ProtocolManager}.
+ *
+ * @author bfoster
+ */
+public interface ProtocolConfig {
+
+	public List<ProtocolFactory> getAllFactories();
+	
+	public List<ProtocolFactory> getFactoriesBySite(URI site);
+	
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/config/SpringProtocolConfig.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/config/SpringProtocolConfig.java
new file mode 100644
index 0000000..b658921
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/config/SpringProtocolConfig.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.config;
+
+//JDK imports
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+//Spring imports
+import org.apache.commons.lang.Validate;
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+/**
+ * Spring Framework base {@link ProtocolConfig} which loads {@link ProtocolFactory}s
+ * from a Spring xml bean file.
+ *
+ * @author bfoster
+ */
+public class SpringProtocolConfig implements ProtocolConfig {
+
+	protected Map<String, List<ProtocolFactory>> factoryMap;
+	
+	public SpringProtocolConfig(String configFile) {
+		Validate.notNull(configFile, "SpringProtocolConfig configFile cannnot be NULL");
+		factoryMap = new HashMap<String, List<ProtocolFactory>>();
+		loadFactories(new FileSystemXmlApplicationContext(configFile));
+	}
+	
+	private void loadFactories(FileSystemXmlApplicationContext appContext) {
+		Collection<ProtocolFactory> protocolFactories = appContext.getBeansOfType(ProtocolFactory.class).values();
+		for (ProtocolFactory factory : protocolFactories) {
+			List<ProtocolFactory> factories = factoryMap.get(factory.getSchema());
+			if (factories == null) {
+				factories = new ArrayList<ProtocolFactory>();
+			}
+			factories.add(factory);
+			factoryMap.put(factory.getSchema(), factories);
+		}
+	}
+	
+	public List<ProtocolFactory> getAllFactories() {
+		ArrayList<ProtocolFactory> factories = new ArrayList<ProtocolFactory>();
+		for (List<ProtocolFactory> groupOfFactories : factoryMap.values()) {
+			factories.addAll(groupOfFactories);
+		}
+		return factories;
+	}
+	
+	public List<ProtocolFactory> getFactoriesBySite(URI site) {
+		Validate.notNull(site, "URI site cannot be NULL");
+		List<ProtocolFactory> factories = factoryMap.get(site.getScheme());
+		if (factories == null) {
+			factories = new ArrayList<ProtocolFactory>();
+		}
+		return factories;
+	}
+
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/exceptions/ProtocolException.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/exceptions/ProtocolException.java
new file mode 100644
index 0000000..8ac2e99
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/exceptions/ProtocolException.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.exceptions;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ */
+public class ProtocolException extends Exception {
+
+	private static final long serialVersionUID = -8463387026167921360L;
+
+    public ProtocolException(String msg) {
+        super(msg);
+    }
+    
+    public ProtocolException(String msg, Throwable throwable) {
+        super(msg, throwable);
+    }
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/system/ProtocolCommandLine.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/system/ProtocolCommandLine.java
new file mode 100644
index 0000000..5f463d5
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/system/ProtocolCommandLine.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.system;
+
+//OODT imports
+import org.apache.oodt.cas.cli.CmdLineUtility;
+
+/**
+ * @author bfoster (Brian Foster)
+ */
+public class ProtocolCommandLine {
+
+	public static void main(String[] args) throws Exception {
+      CmdLineUtility cmdLineUtility = new CmdLineUtility();
+      cmdLineUtility.run(args);
+	}
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/system/ProtocolManager.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/system/ProtocolManager.java
new file mode 100644
index 0000000..f08e67d
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/system/ProtocolManager.java
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.system;
+
+//OODT imports
+import org.apache.commons.lang.Validate;
+import org.apache.oodt.cas.protocol.auth.Authentication;
+import org.apache.oodt.cas.protocol.config.ProtocolConfig;
+import org.apache.oodt.cas.protocol.verify.ProtocolVerifier;
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+
+//JDK imports
+import java.net.URI;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+/**
+ * A Manager responsible for managing site to {@link ProtocolFactory} mapping
+ *
+ * @author bfoster
+ */
+public class ProtocolManager {
+
+	private static final Logger LOG = Logger.getLogger(ProtocolManager.class.getName());
+	
+	private ProtocolConfig protocolConfig;
+	private Map<URI, ProtocolFactory> verifiedMap;
+	
+    public ProtocolManager(ProtocolConfig protocolConfig) {
+    	Validate.notNull(protocolConfig, "protocolConfig must not be NULL");
+    	this.protocolConfig = protocolConfig;
+    	verifiedMap = new HashMap<URI, ProtocolFactory>();
+    }
+    
+    public ProtocolConfig getConfig() {
+    	return protocolConfig;
+    }
+    
+    public List<ProtocolFactory> getFactories() {
+    	return protocolConfig.getAllFactories();
+    }
+    
+    /**
+     * Determines/creates the appropriate {@link Protocol} for the given site and {@link Authentication}.
+     * {@link ProtocolVerifier} is run and the first {@link Protocol} to pass its verification, will be
+     * returned already connected to the given site.  If a {@link Protocol} is returned once for a given
+     * site/Authentication combination, then it will be remember next time this method is called an
+     * {@link ProtocolVerifier} will not be run (assumed pass).
+     * 
+     * @param site The URI for which a {@link Protocol} will be created
+     * @param auth The connection {@link Authentication} to be used to connect to the given site
+     * @param verifier The {@link ProtocolVerifier} which any {@link Protocol} must pass to be returned 
+     * 			as the approved {@link Protocol} for the given site and {@link Authentication}; may be null,
+     * 			in which case as long as the {@link Protocol} can connect to the site it is considered a pass
+     * 			as will be returned
+     * @return A verified {@link Protocol} for the given site and {@link Authentication}, otherwise null if
+     * 	no {@link Protocol} could be determined.
+     */
+    public Protocol getProtocolBySite(URI site, Authentication auth, ProtocolVerifier verifier) {
+    	if (verifiedMap.containsKey(site)) {
+    		return verifiedMap.get(site).newInstance();
+    	} else {
+    		for (ProtocolFactory factory : protocolConfig.getFactoriesBySite(site)) {
+    			Protocol protocol = null;
+    			try {
+    				protocol = factory.newInstance();
+    				if (verifier == null || verifier.verify(protocol, site, auth)) {
+    					verifiedMap.put(site, factory);
+    					if (protocol.connected()) {
+    						protocol.close();
+    					}
+    					protocol.connect(site.getHost(), auth);
+    					return protocol;
+    				}
+    			} catch (Exception e) {
+					LOG.warning("Failed to create/verify protocol from factory '"
+							+ factory.getClass().getCanonicalName()
+							+ "' : "
+							+ e.getMessage());
+    			}
+    		}
+        	return null;
+    	}
+    }
+    
+    /**
+     * 
+     * @param site
+     * @param auth
+     * @param factory
+     * @throws IllegalArgumentException if any of the arguments are null
+     */
+    public void setProtocol(URI site, Authentication auth, ProtocolFactory factory) {
+    	Validate.notNull(site, "site must not be NULL");
+    	Validate.notNull(auth, "auth must not be NULL");
+    	Validate.notNull(factory, "factory must not be NULL");
+    	verifiedMap.put(site, factory);
+    }
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/util/ProtocolFileFilter.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/util/ProtocolFileFilter.java
new file mode 100644
index 0000000..70ed141
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/util/ProtocolFileFilter.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.util;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFile;
+
+/**
+ * Filter for filtering {@ProtocolFile}s.
+ * 
+ * @author bfoster
+ * @version $Revision$
+ */
+public interface ProtocolFileFilter {
+
+    public boolean accept(ProtocolFile file);
+
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/verify/BasicProtocolVerifier.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/verify/BasicProtocolVerifier.java
new file mode 100644
index 0000000..93df18c
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/verify/BasicProtocolVerifier.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.verify;
+
+//JDK imports
+import java.net.URI;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.auth.Authentication;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+
+/**
+ * {@link ProtocolVerifier} which performs basic verification of a given {@link Protocol} to
+ * a given site.  It check that {@link Protocol} can connect to the site, cd to a directory,
+ * cd back to HOME directory, and able to perform an ls and pwd.
+ * 
+ * @author bfoster
+ */
+public class BasicProtocolVerifier implements ProtocolVerifier {
+
+	private static final Logger LOG = Logger.getLogger(BasicProtocolVerifier.class.getName());
+	
+	private Map<URI, ProtocolFile> uriTestCdMap;
+	
+	public BasicProtocolVerifier(Map<URI, ProtocolFile> uriTestCdMap) {
+		this.uriTestCdMap = uriTestCdMap;
+	}
+
+	public boolean verify(Protocol protocol, URI site, Authentication auth) {
+        try {
+            LOG.log(Level.INFO, "Testing protocol "
+                    + protocol.getClass().getCanonicalName()
+                    + " . . . this may take a few minutes . . .");
+            
+            // Test connectivity
+            protocol.connect(site.getHost(), auth);
+            
+            // Test ls, cd, and pwd
+            protocol.cdHome();
+            ProtocolFile home = protocol.pwd();
+            protocol.ls();
+            if (uriTestCdMap.containsKey(site)) {
+            	protocol.cd(uriTestCdMap.get(site));
+            } else {
+            	protocol.cdHome();
+            }
+            protocol.cdHome();
+            
+            // Verify again at home directory
+            if (home == null || !home.equals(protocol.pwd()))
+                throw new ProtocolException(
+                        "Home directory not the same after cd");
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, "Protocol "
+                    + protocol.getClass().getCanonicalName()
+                    + " failed compatibility test : " + e.getMessage(), e);
+            return false;
+        } finally {
+        	try { protocol.close(); } catch (Exception e) {}
+        }
+        return true;
+    }
+
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/verify/BasicProtocolVerifierFactory.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/verify/BasicProtocolVerifierFactory.java
new file mode 100644
index 0000000..c7fa6ef
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/verify/BasicProtocolVerifierFactory.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.verify;
+
+//JDK imports
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFile;
+
+/**
+ * {@link ProtocolVerifierFactory} which creates {@link BasicProtocolVerifier}.
+ *
+ * @author bfoster
+ */
+public class BasicProtocolVerifierFactory implements ProtocolVerifierFactory {
+
+	private Map<URI, ProtocolFile> testCdMap;
+	
+	public ProtocolVerifier newInstance() {
+		if (testCdMap != null) {
+			return new BasicProtocolVerifier(testCdMap);
+		} else {
+			return new BasicProtocolVerifier(new HashMap<URI, ProtocolFile>());
+		}
+	}
+
+	public void setTestCdMap(Map<URI, ProtocolFile> testCdMap) {
+		this.testCdMap = testCdMap;
+	}
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/verify/ProtocolVerifier.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/verify/ProtocolVerifier.java
new file mode 100644
index 0000000..2f7d00b
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/verify/ProtocolVerifier.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.verify;
+
+//JDK imports
+import java.net.URI;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.auth.Authentication;
+
+/**
+ * Interface for verifying {@link Protocol}s can connect to sites.
+ * 
+ * @author bfoster
+ */
+public interface ProtocolVerifier {
+	
+    public boolean verify(Protocol protocol, URI site, Authentication auth);
+    
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/verify/ProtocolVerifierFactory.java b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/verify/ProtocolVerifierFactory.java
new file mode 100644
index 0000000..66a6db9
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/java/org/apache/oodt/cas/protocol/verify/ProtocolVerifierFactory.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.verify;
+
+/**
+ * Factory for creating {@link ProtocolVerifier}s
+ * 
+ * @author bfoster
+ */
+public interface ProtocolVerifierFactory {
+
+	public ProtocolVerifier newInstance();
+
+}
diff --git a/0.8.1-rc1/protocol/api/src/main/resources/policy/cmd-line-actions.xml b/0.8.1-rc1/protocol/api/src/main/resources/policy/cmd-line-actions.xml
new file mode 100644
index 0000000..90487bf
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/resources/policy/cmd-line-actions.xml
@@ -0,0 +1,42 @@
+<?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.
+-->
+<!-- 
+  Author: bfoster 
+  Description: ProtocolManager Configuration
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean id="Download" class="org.apache.oodt.cas.protocol.cli.action.DownloadCliAction">
+		<property name="description" value="Downloads a file" />
+	</bean>
+	<bean id="GetSupportedFactories" class="org.apache.oodt.cas.protocol.cli.action.GetSupportedFactoriesCliAction">
+		<property name="description" value="Prints out list of supported ProtocolFactory(s)" />
+	</bean>
+	<bean id="CrossProtocolTransfer" class="org.apache.oodt.cas.protocol.cli.action.CrossProtocolTransferCliAction">
+		<property name="description" value="Transfers a file across 2 different protocols" />
+		<property name="verifierFactory" ref="BasicVerifier" />
+	</bean>
+	<bean id="DeleteEmptyDirectories" class="org.apache.oodt.cas.protocol.cli.action.DeleteEmptyDirectoriesCliAction">
+		<property name="description" value="Deletes empty directories from a given site" />
+		<property name="verifierFactory" ref="BasicVerifier" />
+	</bean>
+
+	<bean id="BasicVerifier" class="org.apache.oodt.cas.protocol.verify.BasicProtocolVerifierFactory" />
+</beans>
diff --git a/0.8.1-rc1/protocol/api/src/main/resources/policy/cmd-line-options.xml b/0.8.1-rc1/protocol/api/src/main/resources/policy/cmd-line-options.xml
new file mode 100644
index 0000000..66eaa9c
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/resources/policy/cmd-line-options.xml
@@ -0,0 +1,166 @@
+<?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.
+-->
+<!-- Author: bfoster Description: ProtocolManager Configuration -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean id="user" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="u" />
+		<property name="longOption" value="user" />
+		<property name="description" value="Username for authentication" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="username" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="Download" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="Download" />
+          </list>
+        </property>
+      </bean>
+    </property>
+	</bean>
+
+	<bean id="pass" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="p" />
+		<property name="longOption" value="pass" />
+		<property name="description" value="Password for authentication" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="password" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="Download" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="Download" />
+          </list>
+        </property>
+      </bean>
+    </property>
+	</bean>
+
+	<bean id="url" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="url" />
+		<property name="longOption" value="url" />
+		<property name="description" value="URL to download" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="URL" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="Download" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="Download" />
+          </list>
+        </property>
+      </bean>
+    </property>
+	</bean>
+
+	<bean id="fromUrl" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="fu" />
+		<property name="longOption" value="fromUrl" />
+		<property name="description" value="URL to get file" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="URL" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="CrossProtocolTransfer" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="CrossProtocolTransfer" p:methodName="setFromUri" />
+          </list>
+        </property>
+      </bean>
+    </property>
+	</bean>
+
+	<bean id="toUrl" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="tu" />
+		<property name="longOption" value="toUrl" />
+		<property name="description" value="URL to send file" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="URL" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="CrossProtocolTransfer" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="CrossProtocolTransfer" p:methodName="setToUri" />
+          </list>
+        </property>
+      </bean>
+    </property>
+	</bean>
+
+	<bean id="directoriesRegex" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="dr" />
+		<property name="longOption" value="dirsRegex" />
+		<property name="description" value="Directory regex of directories to delete" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="URL" />
+	    <property name="requirementRules">
+	      <list>
+	        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+	          p:actionName="DeleteEmptyDirectories" p:relation="REQUIRED" />
+	      </list>
+	    </property>
+	    <property name="handler">
+	      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+	        <property name="applyToActions">
+	          <list>
+	            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+	              p:actionName="DeleteEmptyDirectories" p:methodName="setDirectoryRegex" />
+	          </list>
+	        </property>
+	      </bean>
+	    </property>
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/protocol/api/src/main/resources/policy/protocol-config.xml b/0.8.1-rc1/protocol/api/src/main/resources/policy/protocol-config.xml
new file mode 100644
index 0000000..0142004
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/main/resources/policy/protocol-config.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<!-- 
+	
+	Author: bfoster
+	Description: ProtocolManager Configuration
+	
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<import resource="classpath*:/org/apache/oodt/cas/protocol/**/*-protocol-config.xml"/>
+	
+</beans>
diff --git a/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/MockProtocol.java b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/MockProtocol.java
new file mode 100644
index 0000000..4677a77
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/MockProtocol.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol;
+
+//JDK imports
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.auth.Authentication;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+import org.apache.oodt.cas.protocol.util.ProtocolFileFilter;
+
+/**
+ * Mock {@link Protocol} for testing
+ * 
+ * @author bfoster
+ */
+public class MockProtocol implements Protocol {
+
+	private boolean connected;
+	private ProtocolFile cwd;
+	private String factoryId;
+	
+	private List<ProtocolFile> deletedFiles;
+	private List<ProtocolFile> putFiles;
+	private List<ProtocolFile> getFiles;
+	private int timesConnected;
+	
+	public MockProtocol(String factoryId) {
+		connected = false;
+		this.factoryId = factoryId;
+		deletedFiles = new ArrayList<ProtocolFile>();
+		putFiles = new ArrayList<ProtocolFile>();
+		getFiles = new ArrayList<ProtocolFile>();
+		timesConnected = 0;
+	}
+	
+	public String getFactoryId() {
+		return factoryId;
+	}
+	
+	public void connect(String host, Authentication authentication)
+			throws ProtocolException {
+		connected = true;
+		deletedFiles.clear();
+		putFiles.clear();
+		getFiles.clear();
+		timesConnected++;
+	}
+	
+	public int getTimesConnected() {
+		return timesConnected;
+	}
+
+	public void close() throws ProtocolException {
+		connected = false;
+	}
+
+	public boolean connected() {
+		return connected;
+	}
+
+	public void cd(ProtocolFile file) throws ProtocolException {
+		cwd = file;
+	}
+	
+	public void cdHome() throws ProtocolException {
+		cwd = new ProtocolFile("", true);
+	}
+	
+	public void cdRoot() throws ProtocolException {
+		cwd = new ProtocolFile("/", true);
+	}
+
+	public void get(ProtocolFile fromFile, File toFile)
+			throws ProtocolException {
+		getFiles.add(fromFile);
+	}
+
+	public List<ProtocolFile> getGetFiles() {
+		return getFiles;
+	}
+	
+	public void put(File fromFile, ProtocolFile toFile)
+			throws ProtocolException {
+		putFiles.add(toFile);
+	}
+	
+	public List<ProtocolFile> getPutFiles() {
+		return putFiles;
+	}
+
+	public ProtocolFile pwd() throws ProtocolException {
+		return cwd;
+	}
+
+	public List<ProtocolFile> ls() throws ProtocolException {
+		return Collections.emptyList();
+	}
+
+	public List<ProtocolFile> ls(ProtocolFileFilter filter) throws ProtocolException {
+		return Collections.emptyList();
+	}
+
+	public void delete(ProtocolFile file) throws ProtocolException {
+		deletedFiles.add(file);
+	}
+	
+	public List<ProtocolFile> getDeletedFiles() {
+		return deletedFiles;
+	}
+
+}
diff --git a/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/MockProtocolFactory.java b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/MockProtocolFactory.java
new file mode 100644
index 0000000..ee80362
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/MockProtocolFactory.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol;
+
+//OODT imports
+import org.apache.oodt.commons.spring.SpringSetIdInjectionType;
+
+/**
+ * Mock {@link ProtocolFactory} for testing
+ * 
+ * @author bfoster
+ */
+public class MockProtocolFactory implements ProtocolFactory, SpringSetIdInjectionType {
+
+	private String schema;
+	private String id;
+	
+	public MockProtocol newInstance() {
+		return new MockProtocol(id);
+	}
+
+	public String getSchema() {
+		return schema;
+	}
+	
+	public void setSchema(String schema) {
+		this.schema = schema;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+}
diff --git a/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/TestProtocolFile.java b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/TestProtocolFile.java
new file mode 100644
index 0000000..f0c472d
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/TestProtocolFile.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol;
+
+//JDK imports
+import java.io.File;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link ProtocolFile}
+ * 
+ * @author bfoster
+ */
+public class TestProtocolFile extends TestCase {
+
+	public void testInitialState() {
+		String filePath = ProtocolFile.SEPARATOR + "path" + ProtocolFile.SEPARATOR + "to" + ProtocolFile.SEPARATOR + "file";
+		ProtocolFile pFile = new ProtocolFile(filePath, false);
+		assertEquals(filePath, pFile.getPath());
+		assertEquals("file", pFile.getName());
+		assertFalse(pFile.isDir());
+		assertFalse(pFile.isRelative());
+		
+		// Test Parent file
+		String parentPath = ProtocolFile.SEPARATOR + "path" + ProtocolFile.SEPARATOR + "to";
+		assertEquals(parentPath, pFile.getParent().getPath());
+		assertEquals("to", pFile.getParent().getName());
+		assertTrue(pFile.getParent().isDir());
+		assertFalse(pFile.getParent().isRelative());
+	}
+	
+	public void testEquals() {
+		assertEquals(new ProtocolFile("/test/directory", true), new ProtocolFile(
+				new ProtocolFile("/test", true), "directory", true));
+		assertEquals(new ProtocolFile(new ProtocolFile("/", true), "repo", true), new ProtocolFile("/repo", true));
+		assertEquals(new ProtocolFile(new ProtocolFile("/", true), "", true), new ProtocolFile("/", true));
+	}
+}
diff --git a/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/auth/TestBasicAuthentication.java b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/auth/TestBasicAuthentication.java
new file mode 100644
index 0000000..149e583
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/auth/TestBasicAuthentication.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.auth;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link BasicAuthentication}
+ * 
+ * @author bfoster
+ */
+public class TestBasicAuthentication extends TestCase {
+
+	public void testInitialState() {
+		BasicAuthentication auth = new BasicAuthentication("user", "pass");
+		assertEquals("user", auth.getUser());
+		assertEquals("pass", auth.getPass());
+	}
+	
+	public void testNullCase() {
+		try {
+			new BasicAuthentication(null, "pass");
+			fail("Should have thrown IllegalArgumentException");
+		}catch (IllegalArgumentException e) {}
+		try {
+			new BasicAuthentication("user", null);
+			fail("Should have thrown IllegalArgumentException");
+		}catch (IllegalArgumentException e) {}
+		try {
+			new BasicAuthentication(null, null);
+			fail("Should have thrown IllegalArgumentException");
+		}catch (IllegalArgumentException e) {}
+	}
+}
diff --git a/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/auth/TestNoAuthentication.java b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/auth/TestNoAuthentication.java
new file mode 100644
index 0000000..51195e4
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/auth/TestNoAuthentication.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.auth;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link NoAuthentication}.
+ * 
+ * @author bfoster
+ */
+public class TestNoAuthentication extends TestCase {
+
+	public void testInitialState() {
+		NoAuthentication auth = new NoAuthentication();
+		assertEquals("", auth.getUser());
+		assertEquals("", auth.getPass());
+	}
+	
+}
diff --git a/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/cli/action/MockProtocolCliAction.java b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/cli/action/MockProtocolCliAction.java
new file mode 100644
index 0000000..351fc62
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/cli/action/MockProtocolCliAction.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * Mock class for {@ProtocolAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class MockProtocolCliAction extends ProtocolCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {      
+   }
+}
diff --git a/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/cli/action/TestBasicVerifyCliAction.java b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/cli/action/TestBasicVerifyCliAction.java
new file mode 100644
index 0000000..c46671f
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/cli/action/TestBasicVerifyCliAction.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.cli.action;
+
+//JDK imports
+import java.net.URI;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.auth.Authentication;
+import org.apache.oodt.cas.protocol.config.MockSpringProtocolConfig;
+import org.apache.oodt.cas.protocol.system.ProtocolManager;
+import org.apache.oodt.cas.protocol.verify.ProtocolVerifier;
+
+/**
+ * Test class for {@link BasicVerifyCliAction}
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestBasicVerifyCliAction extends TestCase {
+
+   public void testVerification() throws Exception {
+      BasicVerifyCliAction bva = new BasicVerifyCliAction();
+      bva.setSite("http://localhost");
+      bva.setVerifier(new ProtocolVerifier() {
+         public boolean verify(Protocol protocol, URI site,
+               Authentication auth) {
+            return auth != null && site.toString().equals("http://localhost");
+         }
+      });
+      bva.setProtocolManager(new ProtocolManager(new MockSpringProtocolConfig()));
+      bva.execute(new ActionMessagePrinter());
+      assertTrue(bva.getLastVerificationResults());
+   }
+}
diff --git a/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/cli/action/TestDownloadCliAction.java b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/cli/action/TestDownloadCliAction.java
new file mode 100644
index 0000000..21dae0e
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/cli/action/TestDownloadCliAction.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.cli.action;
+
+//JDK imports
+import java.net.URISyntaxException;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction.ActionMessagePrinter;
+import org.apache.oodt.cas.protocol.MockProtocol;
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.config.MockSpringProtocolConfig;
+import org.apache.oodt.cas.protocol.system.ProtocolManager;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link DownloadCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestDownloadCliAction extends TestCase {
+   
+   private ProtocolManager pm;
+   
+   @Override
+   public void setUp() {
+      pm = new ProtocolManager(new MockSpringProtocolConfig());
+   }
+   
+   public void testCreateProtocol() throws URISyntaxException {
+      DownloadCliAction da = new DownloadCliAction();
+      da.setUrl("http://localhost/some/file");
+      Protocol protocol = da.createProtocol(pm);
+      assertNotNull(protocol);
+      assertTrue(protocol instanceof MockProtocol);
+      assertEquals("http1", ((MockProtocol) protocol).getFactoryId());
+   }
+   
+   public void testCreateProtocolFile() throws URISyntaxException {
+      DownloadCliAction da = new DownloadCliAction();
+      da.setUrl("http://localhost/some/file");
+      ProtocolFile file = da.createProtocolFile();
+      assertNotNull(file);
+      assertEquals("/some/file", file.getPath());
+      assertFalse(file.isRelative());
+      assertFalse(file.isDir());
+   }
+   
+   public void testFileDownload() throws Exception {
+      DownloadCliAction da = new DownloadCliAction();
+      da.setUrl("http://localhost/some/file");
+      da.setProtocolManager(pm);
+      da.execute(new ActionMessagePrinter());
+      assertNotNull(da.getUsedProtocol());
+      assertTrue(da.getUsedProtocol() instanceof MockProtocol);
+      assertEquals(1, ((MockProtocol) da.getUsedProtocol()).getGetFiles().size());
+      assertEquals("/some/file", ((MockProtocol) da.getUsedProtocol()).getGetFiles().get(0).getPath());
+   }
+}
diff --git a/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/cli/action/TestProtocolCliAction.java b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/cli/action/TestProtocolCliAction.java
new file mode 100644
index 0000000..ab88c45
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/cli/action/TestProtocolCliAction.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.cli.action;
+
+//JDK imports
+import java.net.URISyntaxException;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link ProtocolCliAction}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class TestProtocolCliAction extends TestCase {
+
+   public void testInitialState() throws URISyntaxException {
+      MockProtocolCliAction action = new MockProtocolCliAction();
+      action.setUser("user");
+      action.setPass("pass");
+      action.setSite("http://some-site");
+      assertEquals("user", action.getAuthentication().getUser());
+      assertEquals("pass", action.getAuthentication().getPass());
+      assertEquals("http://some-site", action.getSite().toString());
+   }
+}
diff --git a/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/config/MockSpringProtocolConfig.java b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/config/MockSpringProtocolConfig.java
new file mode 100644
index 0000000..e4c7ceb
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/config/MockSpringProtocolConfig.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.config;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+
+/**
+ * Mock {@link SpringProtocolConfig}
+ * 
+ * @author bfoster
+ */
+public class MockSpringProtocolConfig extends SpringProtocolConfig {
+
+	private static final String CONFIG_FILE = "src/test/resources/test-protocol-config.xml";
+
+	public MockSpringProtocolConfig() {
+		super(CONFIG_FILE);
+	}
+
+	public String getConfigFile() {
+		return CONFIG_FILE;
+	}
+
+	public Map<String, List<ProtocolFactory>> getFactoryMap() {
+		return factoryMap;
+	}
+}
diff --git a/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/system/TestProtocolManager.java b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/system/TestProtocolManager.java
new file mode 100644
index 0000000..b6184ad
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/test/java/org/apache/oodt/cas/protocol/system/TestProtocolManager.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.system;
+
+//JDK imports
+import java.net.URI;
+import java.net.URISyntaxException;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.MockProtocol;
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.auth.Authentication;
+import org.apache.oodt.cas.protocol.auth.NoAuthentication;
+import org.apache.oodt.cas.protocol.config.MockSpringProtocolConfig;
+import org.apache.oodt.cas.protocol.verify.ProtocolVerifier;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link ProtocolManager}.
+ * 
+ * @author bfoster
+ */
+public class TestProtocolManager extends TestCase {
+	
+	private ProtocolManager protocolManager;
+	
+	@Override
+	public void setUp() {
+		protocolManager = new ProtocolManager(new MockSpringProtocolConfig());
+	}
+	
+	public void testInitialState() {
+		assertNotNull(protocolManager.getConfig());
+	}
+	
+	public void testProtocolFactoryMapping() throws URISyntaxException {
+		Protocol protocol = protocolManager.getProtocolBySite(new URI("ftp://localhost"), new NoAuthentication(), null);
+		assertNotNull(protocol);
+		assertTrue(protocol instanceof MockProtocol);
+		MockProtocol mockProtocol = (MockProtocol) protocol;
+		assertEquals("ftp1", mockProtocol.getFactoryId());
+		
+		//test that ftp1 was memorized and is returned again even though a Verifier was supplied this time that would return ftp3
+		protocol = protocolManager.getProtocolBySite(new URI("ftp://localhost"), new NoAuthentication(), new ProtocolVerifier() {
+			public boolean verify(Protocol protocol, URI site,
+					Authentication auth) {
+				if (protocol instanceof MockProtocol) {
+					MockProtocol mockProtocol = (MockProtocol) protocol;
+					return mockProtocol.getFactoryId().equals("ftp3");
+				} else {
+					return false;
+				}
+			}
+		});
+		assertNotNull(protocol);
+		assertTrue(protocol instanceof MockProtocol);
+		mockProtocol = (MockProtocol) protocol;
+		assertEquals("ftp1", mockProtocol.getFactoryId());
+
+	}
+	
+	public void testVerifier() throws URISyntaxException {
+		Protocol protocol = protocolManager.getProtocolBySite(new URI("ftp://localhost"), new NoAuthentication(), new ProtocolVerifier() {
+			public boolean verify(Protocol protocol, URI site,
+					Authentication auth) {
+				if (protocol instanceof MockProtocol) {
+					MockProtocol mockProtocol = (MockProtocol) protocol;
+					return mockProtocol.getFactoryId().equals("ftp3");
+				} else {
+					return false;
+				}
+			}
+		});
+		assertTrue(protocol instanceof MockProtocol);
+		MockProtocol mockProtocol = (MockProtocol) protocol;
+		assertEquals("ftp3", mockProtocol.getFactoryId());
+	}
+	
+}
diff --git a/0.8.1-rc1/protocol/api/src/test/resources/test-protocol-config.xml b/0.8.1-rc1/protocol/api/src/test/resources/test-protocol-config.xml
new file mode 100644
index 0000000..ef84b73
--- /dev/null
+++ b/0.8.1-rc1/protocol/api/src/test/resources/test-protocol-config.xml
@@ -0,0 +1,53 @@
+<?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.
+-->
+<!-- 
+	
+	Author: bfoster
+	Description: ProtocolManager Configuration
+	
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean class="org.apache.oodt.commons.spring.postprocessor.SetIdBeanPostProcessor"/>
+
+	<!-- list ProtocolFactories here -->
+	<bean id="ftp1" class="org.apache.oodt.cas.protocol.MockProtocolFactory">
+		<property name="schema" value="ftp"/>
+	</bean>
+	<bean id="ftp2" class="org.apache.oodt.cas.protocol.MockProtocolFactory">
+		<property name="schema" value="ftp"/>
+	</bean>
+	<bean id="ftp3" class="org.apache.oodt.cas.protocol.MockProtocolFactory">
+		<property name="schema" value="ftp"/>
+	</bean>
+	
+	<bean id="sftp1" class="org.apache.oodt.cas.protocol.MockProtocolFactory">
+		<property name="schema" value="sftp"/>
+	</bean>
+	<bean id="sftp2" class="org.apache.oodt.cas.protocol.MockProtocolFactory">
+		<property name="schema" value="sftp"/>
+	</bean>
+	
+	<bean id="http1" class="org.apache.oodt.cas.protocol.MockProtocolFactory">
+		<property name="schema" value="http"/>
+	</bean>
+	
+</beans>
diff --git a/0.8.1-rc1/protocol/ftp/pom.xml b/0.8.1-rc1/protocol/ftp/pom.xml
new file mode 100644
index 0000000..7238907
--- /dev/null
+++ b/0.8.1-rc1/protocol/ftp/pom.xml
@@ -0,0 +1,109 @@
+<?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. -->
+<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>
+	<parent>
+		<groupId>org.apache.oodt</groupId>
+		<artifactId>oodt-core</artifactId>
+		<version>0.8.1</version>
+		<relativePath>../../core/pom.xml</relativePath>
+	</parent>
+	<artifactId>cas-protocol-ftp</artifactId>
+	<name>CAS Protocol FTP Implementation</name>
+	<profiles>
+		<profile>
+			<id>audit</id>
+			<activation>
+				<activeByDefault>false</activeByDefault>
+			</activation>
+			<build>
+				<plugins>
+					<plugin>
+						<groupId>org.codehaus.mojo</groupId>
+						<artifactId>rat-maven-plugin</artifactId>
+						<configuration>
+							<excludes>
+								<exclude>**/resources/examples/**/*</exclude>
+							</excludes>
+						</configuration>
+						<executions>
+							<execution>
+								<phase>verify</phase>
+								<goals>
+									<goal>check</goal>
+								</goals>
+							</execution>
+						</executions>
+					</plugin>
+				</plugins>
+			</build>
+		</profile>
+	</profiles>
+  <build>
+    <resources>
+      <resource>
+        <targetPath>org/apache/oodt/cas/protocol/ftp</targetPath>
+        <directory>${basedir}/src/main/resources/policy</directory>
+        <includes>
+          <include>ftp-protocol-config.xml</include>
+        </includes>
+      </resource>
+    </resources>
+  </build>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>cas-protocol-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.jglobus</groupId>
+			<artifactId>JGlobus-GridFTP</artifactId>
+			<version>2.0.0</version>
+		</dependency>
+		<dependency>
+			<groupId>org.jglobus</groupId>
+			<artifactId>gss</artifactId>
+			<version>2.0.6</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-net</groupId>
+			<artifactId>commons-net</artifactId>
+			<version>1.4.0</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.ftpserver</groupId>
+			<artifactId>ftpserver-core</artifactId>
+			<version>1.0.5</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <version>1.5.2</version>
+      <scope>test</scope>
+    </dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.2</version>
+			<scope>test</scope>
+		</dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <version>1.9.5</version>
+            <scope>test</scope>
+        </dependency>
+	</dependencies>
+</project>
diff --git a/0.8.1-rc1/protocol/ftp/src/main/java/org/apache/oodt/cas/protocol/ftp/CogJGlobusFtpProtocol.java b/0.8.1-rc1/protocol/ftp/src/main/java/org/apache/oodt/cas/protocol/ftp/CogJGlobusFtpProtocol.java
new file mode 100644
index 0000000..36553cb
--- /dev/null
+++ b/0.8.1-rc1/protocol/ftp/src/main/java/org/apache/oodt/cas/protocol/ftp/CogJGlobusFtpProtocol.java
@@ -0,0 +1,229 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.ftp;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Vector;
+
+
+
+//Globus imports
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.auth.Authentication;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+import org.apache.oodt.cas.protocol.util.ProtocolFileFilter;
+import org.globus.ftp.FTPClient;
+import org.globus.ftp.FileInfo;
+import org.globus.ftp.HostPort;
+import org.globus.ftp.exception.ClientException;
+import org.globus.ftp.exception.ServerException;
+
+/**
+ * FTP implementation of a {@link Protocol}
+ * 
+ * @author bfoster
+ */
+public class CogJGlobusFtpProtocol implements Protocol {
+
+  private FTPClient ftp;
+  private boolean isConnected;
+  private int port;
+  private String homeDir;
+  
+  public CogJGlobusFtpProtocol() {
+  	this(21);
+  }
+  
+  public CogJGlobusFtpProtocol(int port) {
+  	this.port = port;
+  }
+  
+  public void cd(ProtocolFile file) throws ProtocolException {
+      try {
+          ftp.changeDir(file.getPath());
+      } catch (Exception e) {
+          throw new ProtocolException("Failed to cd to " + file + " : "
+                  + e.getMessage());
+      }
+  }
+  
+  public void cdRoot() throws ProtocolException {
+  	cd(new ProtocolFile(ProtocolFile.SEPARATOR, true));
+  }
+  
+  public void cdHome() throws ProtocolException {
+  	cd(new ProtocolFile(homeDir, true));
+  }
+
+  public void connect(String host, Authentication auth) throws ProtocolException {
+      try {
+          ftp = new FTPClient(host, port);
+      } catch (Exception e) {
+          throw new ProtocolException("Failed to connect to: " + host + " : "
+                  + e.getMessage(), e);
+      }
+      isConnected = true;
+
+      try {
+          ftp.authorize(auth.getUser(), auth.getPass());
+          ftp.setActive(ftp.setLocalPassive());
+          homeDir = ftp.getCurrentDir();
+      } catch (Exception e) {
+          throw new ProtocolException("Failed to login to: " + host + " : "
+                  + e.getMessage(), e);
+      }
+  }
+
+  public void close() throws ProtocolException {
+      try {
+          ftp.close();
+          isConnected = false;
+      } catch (Exception e) {
+          throw new ProtocolException("Error disconnecting from "
+                  + ftp.getHost() + " : " + e.getMessage());
+      }
+  }
+
+  public void get(ProtocolFile fromFile, File toFile)
+          throws ProtocolException {
+      try {
+          ftp.setActive(ftp.setLocalPassive());
+          ftp.get(fromFile.getPath(), toFile);
+      } catch (Exception e) {
+          throw new ProtocolException("Failed to download: " + fromFile.getName()
+                  + " : " + e.getMessage());
+      }
+  }
+  
+  public void put(File fromFile, ProtocolFile toFile) throws ProtocolException {
+	  try {
+		  ftp.put(fromFile, toFile.getPath(), false);
+	  }catch (Exception e) {
+		  throw new ProtocolException("Failed to put file '" + fromFile + "' : " + e.getMessage(), e);
+	  }
+  }
+
+    /**
+     * SetActive
+     * Sets the FTP Active Protocol
+     * Package protected so we can test the non FTP server parts of the codebase.
+     * @throws ProtocolException
+     */
+  protected void setActive() throws ProtocolException {
+      try {
+          ftp.setActive(ftp.setLocalPassive());
+      } catch (Exception e) {
+          throw new ProtocolException("Failed to set ftp active : "
+                  + e.getMessage());
+      }
+  }
+
+    /**
+     * ftpList
+     * Gets a file list from the FTP Server
+     * Package protected so we can test the non server portion of the code.
+     * @param filter
+     * @param modifier
+     * @return
+     */
+  protected Vector ftpList(String filter, String modifier) throws ProtocolException {
+      try {
+          return ftp.list(filter, modifier);
+      } catch (Exception e) {
+          throw new ProtocolException("Failed to get list of files : "
+                  + e.getMessage());
+      }
+
+  }
+  public List<ProtocolFile> ls() throws ProtocolException {
+      try {
+          setActive();
+          @SuppressWarnings("unchecked")
+          Vector<FileInfo> fileList = (Vector<FileInfo>) ftpList("*", null);
+          Vector<ProtocolFile> returnList = new Vector<ProtocolFile>();
+          for (FileInfo file : fileList) {
+              returnList.add(new ProtocolFile(this.pwd(), file.getName(), file.isDirectory()));
+          }
+          return returnList;
+      } catch (Exception e) {
+          throw new ProtocolException("Failed to get list of files : "
+                  + e.getMessage());
+      }
+  }
+  
+	public List<ProtocolFile> ls(ProtocolFileFilter filter) throws ProtocolException {
+    try {
+      ftp.setActive(ftp.setLocalPassive());
+      @SuppressWarnings("unchecked")
+      Vector<FileInfo> fileList = (Vector<FileInfo>) ftp.list("*", null);
+      Vector<ProtocolFile> returnList = new Vector<ProtocolFile>();
+      for (FileInfo file : fileList) {
+      	ProtocolFile pFile = new ProtocolFile(this.pwd(), file.getName(), file.isDirectory());
+      	if (filter.accept(pFile)) {
+      		returnList.add(pFile);
+      	}
+      }
+      return returnList;
+	  } catch (Exception e) {
+	      throw new ProtocolException("Failed to get list of files : "
+	              + e.getMessage());
+	  }
+  }
+
+    /**
+     * Returns the current Directory.
+     * Package protected so we can test the non ftp parts of the codebase.
+     * @return
+     * @throws ProtocolException
+     */
+  protected String getCurentDir() throws ProtocolException {
+      try {
+          return ftp.getCurrentDir();
+      } catch (Exception e) {
+          throw new ProtocolException("Failed to get current directory : "
+                  + e.getMessage());
+      }
+
+
+  }
+	
+  public ProtocolFile pwd() throws ProtocolException {
+      try {
+          return new ProtocolFile(getCurentDir(), true);
+      } catch (Exception e) {
+          throw new ProtocolException("Failed to pwd : " + e.getMessage());
+      }
+  }
+
+  public boolean connected() {
+      return isConnected;
+  }
+
+  public void delete(ProtocolFile file) throws ProtocolException {
+	  try {
+	  	ftp.deleteFile(file.getPath());
+		} catch (Exception e) {
+			throw new ProtocolException("Failed to download file '" 
+					+ file.getPath() + "' : " + e.getMessage(), e);
+		}
+  }
+
+}
diff --git a/0.8.1-rc1/protocol/ftp/src/main/java/org/apache/oodt/cas/protocol/ftp/CogJGlobusFtpProtocolFactory.java b/0.8.1-rc1/protocol/ftp/src/main/java/org/apache/oodt/cas/protocol/ftp/CogJGlobusFtpProtocolFactory.java
new file mode 100644
index 0000000..9b96981
--- /dev/null
+++ b/0.8.1-rc1/protocol/ftp/src/main/java/org/apache/oodt/cas/protocol/ftp/CogJGlobusFtpProtocolFactory.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.ftp;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+
+/**
+ * Factory for creating {@link CogJGlobusFtpProtocol}s
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class CogJGlobusFtpProtocolFactory implements ProtocolFactory {
+
+  public CogJGlobusFtpProtocol newInstance() {
+    return new CogJGlobusFtpProtocol();
+  }
+
+  public String getSchema() {
+	return "ftp";
+  }
+
+}
diff --git a/0.8.1-rc1/protocol/ftp/src/main/java/org/apache/oodt/cas/protocol/ftp/CommonsNetFtpProtocol.java b/0.8.1-rc1/protocol/ftp/src/main/java/org/apache/oodt/cas/protocol/ftp/CommonsNetFtpProtocol.java
new file mode 100644
index 0000000..fdc0f3c
--- /dev/null
+++ b/0.8.1-rc1/protocol/ftp/src/main/java/org/apache/oodt/cas/protocol/ftp/CommonsNetFtpProtocol.java
@@ -0,0 +1,244 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.ftp;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.LinkedList;
+import java.util.List;
+
+//APACHE imports
+import org.apache.commons.net.ftp.FTPClient;
+import org.apache.commons.net.ftp.FTPFile;
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.auth.Authentication;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+import org.apache.oodt.cas.protocol.util.ProtocolFileFilter;
+
+/**
+ * This class is responsible for FTP transfers. It is built as a wrapper around
+ * Apache's FTPClient class in order to connect it into the Crawler's Protocol
+ * infrastructure.
+ *
+ * @author bfoster
+ *
+ */
+public class CommonsNetFtpProtocol implements Protocol {
+
+	private final FTPClient ftp;
+	private String homeDir;
+
+	/**
+	 * Creates a new FtpClient
+	 */
+	public CommonsNetFtpProtocol() {
+		ftp = new FTPClient();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void connect(String host, Authentication auth)
+			throws ProtocolException {
+		// server cannot be null
+		if (host == null) {
+			throw new ProtocolException("Tried to connect to server == NULL");
+		}
+
+		try {
+			ftp.connect(host);
+			ftp.enterLocalPassiveMode();
+		} catch (Exception e) {
+			throw new ProtocolException("Failed to connect to server : "
+					+ e.getMessage());
+		}
+
+		try {
+			// try logging in
+			if (!ftp.login(auth.getUser(), auth.getPass())) {
+				throw new ProtocolException("Failed logging into host " + host
+						+ " as user " + auth.getUser());
+			}
+
+			// set file type to binary
+			ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
+
+			homeDir = ftp.printWorkingDirectory();
+		} catch (Exception e) {
+			// login failed
+			throw new ProtocolException("Exception thrown while logging into host "
+					+ host + " as user " + auth.getUser());
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public ProtocolFile pwd() throws ProtocolException {
+		try {
+			return new ProtocolFile(ftp.printWorkingDirectory(), true);
+		} catch (Exception e) {
+			throw new ProtocolException("Failed to pwd : " + e.getMessage());
+		}
+	}
+
+	public List<ProtocolFile> ls() throws ProtocolException {
+		try {
+			String path = this.pwd().getPath();
+			FTPFile[] files = ftp.listFiles();
+			List<ProtocolFile> returnFiles = new LinkedList<ProtocolFile>();
+			for (int i = 0; i < files.length; i++) {
+				FTPFile file = files[i];
+				if (file == null)
+					continue;
+				returnFiles.add(new ProtocolFile(path + "/" + file.getName(), file
+						.isDirectory()));
+			}
+			return returnFiles;
+		} catch (Exception e) {
+			throw new ProtocolException("Failed to get file list : " + e.getMessage());
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public List<ProtocolFile> ls(ProtocolFileFilter filter)
+			throws ProtocolException {
+		try {
+			FTPFile[] files = ftp.listFiles();
+			List<ProtocolFile> returnFiles = new LinkedList<ProtocolFile>();
+			for (int i = 0; i < files.length; i++) {
+				FTPFile file = files[i];
+				if (file == null)
+					continue;
+				String path = this.pwd().getPath();
+				ProtocolFile pFile = new ProtocolFile(path + "/" + file.getName(), file
+						.isDirectory());
+				if (filter.accept(pFile)) {
+					returnFiles.add(pFile);
+				}
+			}
+			return returnFiles;
+		} catch (Exception e) {
+			throw new ProtocolException("Failed to get file list : " + e.getMessage());
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void get(ProtocolFile fromFile, File toFile) throws ProtocolException {
+		// file or toLocalFile cannot be null
+		if (fromFile == null || toFile == null) {
+			throw new ProtocolException(
+					"Can't download file -> ProtocolFile == null || toLocalFile == null");
+		}
+
+		// download file
+		OutputStream os = null;
+		try {
+			os = new FileOutputStream(toFile);
+			if (!ftp.retrieveFile(fromFile.getName(), os)) {
+				throw new ProtocolException("Failed to download file "
+						+ fromFile.getName());
+			}
+		} catch (Exception e) {
+			// download failed
+			toFile.delete();
+			throw new ProtocolException("FAILED to download: " + fromFile.getName()
+					+ " : " + e.getMessage(), e);
+		} finally {
+			// close output stream
+			if (os != null)
+				try {
+					os.close();
+				} catch (Exception e) {
+					toFile.delete();
+					throw new ProtocolException("Failed to close outputstream : "
+							+ e.getMessage(), e);
+				}
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void put(File fromFile, ProtocolFile toFile) throws ProtocolException {
+		try {
+			ftp.storeFile(toFile.getPath(), new FileInputStream(fromFile));
+		} catch (Exception e) {
+			throw new ProtocolException("Failed to put file '" + fromFile + "' : "
+					+ e.getMessage(), e);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void cd(ProtocolFile file) throws ProtocolException {
+		try {
+			if (!ftp.changeWorkingDirectory(file.getPath()))
+				throw new Exception("Directory change method returned false");
+		} catch (Exception e) {
+			throw new ProtocolException("Failed to cd to " + file.getPath() + " : "
+					+ e.getMessage());
+		}
+	}
+
+	public void cdRoot() throws ProtocolException {
+		cd(new ProtocolFile(ProtocolFile.SEPARATOR, true));
+	}
+
+	public void cdHome() throws ProtocolException {
+		cd(new ProtocolFile(homeDir, true));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void close() throws ProtocolException {
+		try {
+			ftp.disconnect();
+		} catch (Exception e) {
+			throw new ProtocolException("Failed to disconnect from server");
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean connected() {
+		return ftp.isConnected();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void delete(ProtocolFile file) throws ProtocolException {
+		try {
+			ftp.deleteFile(file.getPath());
+		} catch (Exception e) {
+			throw new ProtocolException("Failed to delete file '" + file.getPath()
+					+ "' : " + e.getMessage(), e);
+		}
+	}
+}
diff --git a/0.8.1-rc1/protocol/ftp/src/main/java/org/apache/oodt/cas/protocol/ftp/CommonsNetFtpProtocolFactory.java b/0.8.1-rc1/protocol/ftp/src/main/java/org/apache/oodt/cas/protocol/ftp/CommonsNetFtpProtocolFactory.java
new file mode 100644
index 0000000..90cbd42
--- /dev/null
+++ b/0.8.1-rc1/protocol/ftp/src/main/java/org/apache/oodt/cas/protocol/ftp/CommonsNetFtpProtocolFactory.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.ftp;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+
+/**
+ * Constructs new {@link CommonsNetFtpProtocol}s.
+ * 
+ * @author bfoster
+ * @version $Revision$
+ */
+public class CommonsNetFtpProtocolFactory implements ProtocolFactory {
+
+  public CommonsNetFtpProtocol newInstance() {
+    return new CommonsNetFtpProtocol();
+  }
+
+  public String getSchema() {
+	return "ftp";
+  }
+
+}
diff --git a/0.8.1-rc1/protocol/ftp/src/main/resources/policy/ftp-protocol-config.xml b/0.8.1-rc1/protocol/ftp/src/main/resources/policy/ftp-protocol-config.xml
new file mode 100644
index 0000000..65b4ec4
--- /dev/null
+++ b/0.8.1-rc1/protocol/ftp/src/main/resources/policy/ftp-protocol-config.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<!-- 
+	
+	Author: bfoster
+	Description: ProtocolManager Configuration
+	
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean class="org.apache.oodt.cas.protocol.ftp.CogJGlobusFtpProtocolFactory"/>
+  <bean class="org.apache.oodt.cas.protocol.ftp.CommonsNetFtpProtocolFactory"/>
+	
+</beans>
diff --git a/0.8.1-rc1/protocol/ftp/src/test/java/org/apache/oodt/cas/protocol/ftp/TestCogJGlobusFtpProtocol.java b/0.8.1-rc1/protocol/ftp/src/test/java/org/apache/oodt/cas/protocol/ftp/TestCogJGlobusFtpProtocol.java
new file mode 100644
index 0000000..e69bf9e
--- /dev/null
+++ b/0.8.1-rc1/protocol/ftp/src/test/java/org/apache/oodt/cas/protocol/ftp/TestCogJGlobusFtpProtocol.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.ftp;
+
+//JUnit imports
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+
+//APACHE imports
+import org.apache.ftpserver.ConnectionConfigFactory;
+import org.apache.ftpserver.DataConnectionConfigurationFactory;
+import org.apache.ftpserver.FtpServer;
+import org.apache.ftpserver.FtpServerFactory;
+import org.apache.ftpserver.listener.ListenerFactory;
+import org.apache.ftpserver.usermanager.ClearTextPasswordEncryptor;
+import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.auth.BasicAuthentication;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+
+//JUnit imports
+import junit.framework.TestCase;
+import org.globus.ftp.FileInfo;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import static org.mockito.Mockito.spy;
+
+/**
+ * Test class for {@link CogJGlobusFtpProtocol}.
+ *
+ * @author bfoster
+ */
+public class TestCogJGlobusFtpProtocol extends TestCase {
+
+	private static final int PORT = 9000;
+	private FtpServer server;
+  private static final File USERS_FILE = new File("src/test/resources/users.properties");
+  
+	@Override
+	public void setUp() throws Exception {
+		assertTrue(USERS_FILE.getAbsolutePath() + " must exist",
+				USERS_FILE.exists());
+
+		FtpServerFactory serverFactory = new FtpServerFactory();
+
+		serverFactory.setConnectionConfig(new ConnectionConfigFactory()
+				.createConnectionConfig());
+
+		ListenerFactory listenerFactory = new ListenerFactory();
+
+		listenerFactory.setPort(PORT);
+
+		listenerFactory
+				.setDataConnectionConfiguration(new DataConnectionConfigurationFactory()
+						.createDataConnectionConfiguration());
+
+		serverFactory.addListener("default", listenerFactory.createListener());
+
+		PropertiesUserManagerFactory umFactory = new PropertiesUserManagerFactory();
+		umFactory.setPasswordEncryptor(new ClearTextPasswordEncryptor());
+		umFactory.setFile(USERS_FILE);
+
+		serverFactory.setUserManager(umFactory.createUserManager());
+
+		server = serverFactory.createServer();
+		//server.start();
+	}
+	
+	@Override
+	public void tearDown() {
+		server.stop();
+	}
+	
+	public void testLSandCDandPWD() throws ProtocolException {
+
+        CogJGlobusFtpProtocol ftpProtocol = spy(new CogJGlobusFtpProtocol(PORT));
+        BasicAuthentication auth = new BasicAuthentication("anonymous", "password");
+
+        /** Mocking server responses to prevent server failure **/
+
+        Mockito.doReturn("test/resources").when(ftpProtocol).getCurentDir();
+
+        Vector<FileInfo> vector = new Vector<FileInfo>();
+        FileInfo file = new FileInfo();
+        file.setName("users.properties");
+        byte b = 1;
+        file.setFileType(b);
+        vector.add(file);
+
+        Mockito.doAnswer(new Answer() {
+            public Object answer(InvocationOnMock invocation) {
+                return null;
+            }}).when(ftpProtocol).setActive();
+
+        Mockito.doReturn(vector).when(ftpProtocol).ftpList("*", null);
+
+        Mockito.doAnswer(new Answer() {
+            public Object answer(InvocationOnMock invocation) {
+                return null;
+            }}).when(ftpProtocol).connect("localhost", auth);
+
+        Mockito.doAnswer(new Answer() {
+            public Object answer(InvocationOnMock invocation) {
+                return null;
+            }}).when(ftpProtocol).cd(new ProtocolFile("test/resources", true));
+
+
+
+        ftpProtocol.connect("localhost", auth);
+
+
+		ftpProtocol.cd(new ProtocolFile("test/resources", true));
+
+		List<ProtocolFile> lsResults = ftpProtocol.ls();
+		assertTrue(lsResults.contains(new ProtocolFile(ftpProtocol.pwd(), "users.properties", false)));
+	}
+	
+}
diff --git a/0.8.1-rc1/protocol/ftp/src/test/resources/users.properties b/0.8.1-rc1/protocol/ftp/src/test/resources/users.properties
new file mode 100644
index 0000000..c4ace0b
--- /dev/null
+++ b/0.8.1-rc1/protocol/ftp/src/test/resources/users.properties
@@ -0,0 +1,26 @@
+# 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.
+
+ftpserver.user.anonymous.userpassword=
+ftpserver.user.anonymous.maxloginperip=2
+ftpserver.user.anonymous.uploadrate=4800
+ftpserver.user.anonymous.writepermission=false
+ftpserver.user.anonymous.maxloginnumber=20
+ftpserver.user.anonymous.enableflag=true
+ftpserver.user.anonymous.homedirectory=src
+ftpserver.user.anonymous.idletime=300
+ftpserver.user.anonymous.downloadrate=4800
diff --git a/0.8.1-rc1/protocol/http/pom.xml b/0.8.1-rc1/protocol/http/pom.xml
new file mode 100644
index 0000000..6419677
--- /dev/null
+++ b/0.8.1-rc1/protocol/http/pom.xml
@@ -0,0 +1,90 @@
+<?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. -->
+<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>
+	<parent>
+		<groupId>org.apache.oodt</groupId>
+		<artifactId>oodt-core</artifactId>
+		<version>0.8.1</version>
+		<relativePath>../../core/pom.xml</relativePath>
+	</parent>
+	<artifactId>cas-protocol-http</artifactId>
+	<name>CAS Protocol HTTP Implementation</name>
+	<profiles>
+		<profile>
+			<id>audit</id>
+			<activation>
+				<activeByDefault>false</activeByDefault>
+			</activation>
+			<build>
+				<plugins>
+					<plugin>
+						<groupId>org.codehaus.mojo</groupId>
+						<artifactId>rat-maven-plugin</artifactId>
+						<configuration>
+							<excludes>
+								<exclude>**/resources/examples/**/*</exclude>
+							</excludes>
+						</configuration>
+						<executions>
+							<execution>
+								<phase>verify</phase>
+								<goals>
+									<goal>check</goal>
+								</goals>
+							</execution>
+						</executions>
+					</plugin>
+				</plugins>
+			</build>
+		</profile>
+	</profiles>
+	<build>
+		<resources>
+			<resource>
+				<targetPath>org/apache/oodt/cas/protocol/http</targetPath>
+				<directory>${basedir}/src/main/resources/policy</directory>
+				<includes>
+					<include>http-protocol-config.xml</include>
+				</includes>
+			</resource>
+		</resources>
+	</build>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>cas-protocol-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-httpclient</groupId>
+			<artifactId>commons-httpclient</artifactId>
+			<version>3.0</version>
+		</dependency>
+		<dependency>
+			<groupId>nekohtml</groupId>
+			<artifactId>nekohtml</artifactId>
+			<version>1.9.6.2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.tika</groupId>
+			<artifactId>tika-parsers</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.2</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+</project>
diff --git a/0.8.1-rc1/protocol/http/src/main/java/org/apache/oodt/cas/protocol/http/HttpFile.java b/0.8.1-rc1/protocol/http/src/main/java/org/apache/oodt/cas/protocol/http/HttpFile.java
new file mode 100644
index 0000000..5e38940
--- /dev/null
+++ b/0.8.1-rc1/protocol/http/src/main/java/org/apache/oodt/cas/protocol/http/HttpFile.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.http;
+
+//OODT imports
+import org.apache.commons.lang.Validate;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+
+//JDK imports
+import java.net.URL;
+
+/**
+ * HTTP extension of {@link ProtocolFile}
+ * 
+ * @author bfoster
+ * @version $Revision$
+ */
+public class HttpFile extends ProtocolFile {
+
+	private static final long serialVersionUID = -7780059889413081800L;
+
+	private URL link;
+
+	public HttpFile(String virtualPath, boolean isDir, URL link) {
+		this(null, virtualPath, isDir, link);
+	}
+	
+	public HttpFile(HttpFile parent, String virtualPath, boolean isDir, URL link) {
+		super(parent, virtualPath, isDir);
+		Validate.notNull(link, "URL link must not be NULL");
+		this.link = link;
+	}
+
+	public URL getLink() {
+		return this.link;
+	}
+}
diff --git a/0.8.1-rc1/protocol/http/src/main/java/org/apache/oodt/cas/protocol/http/HttpProtocol.java b/0.8.1-rc1/protocol/http/src/main/java/org/apache/oodt/cas/protocol/http/HttpProtocol.java
new file mode 100644
index 0000000..24077c7
--- /dev/null
+++ b/0.8.1-rc1/protocol/http/src/main/java/org/apache/oodt/cas/protocol/http/HttpProtocol.java
@@ -0,0 +1,341 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.http;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.auth.Authentication;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+import org.apache.oodt.cas.protocol.http.util.HttpUtils;
+import org.apache.oodt.cas.protocol.util.ProtocolFileFilter;
+
+//JDK imports
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 
+ * Http Protocol communication class
+ * 
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class HttpProtocol implements Protocol {
+
+  private static Map<String, List<HttpFile>> linkChildren = new HashMap<String, List<HttpFile>>();
+
+  private HttpFile parentFile;
+  private HttpFile currentFile;
+  private boolean isConnected;
+  
+  public HttpProtocol() {
+    isConnected = false;
+  }
+
+  public void cd(ProtocolFile file) throws ProtocolException {
+    try {
+    	HttpFile httpFile = null;
+    	if (!(file instanceof HttpFile)) {
+    		URL link = HttpUtils.resolveUri(currentFile.getLink().toURI(), file.getPath()).toURL();
+  			httpFile = new HttpFile(link.getPath(), file.isDir(), link);
+      } else {
+        httpFile = (HttpFile) file;
+      }
+    	
+      if (!HttpUtils
+          .isDirectory(httpFile.getLink(), file.getPath()))
+        throw new ProtocolException(file
+            + " is not a directory (mime type must be text/html)");
+      this.currentFile = httpFile;
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to cd to " + file + " : "
+          + e.getMessage(), e);
+    }
+  }
+  
+  public void cdRoot() {
+  	currentFile = parentFile;
+  }
+  
+  public void cdHome() {
+  	cdRoot();
+  }
+
+  public void connect(String host, Authentication auth)
+      throws ProtocolException {
+    try {
+      URL url = new URL("http://" + host + "/");
+      url.openStream().close();
+      currentFile = parentFile = new HttpFile("/", true, url);
+      isConnected = true;
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to connect to http://" + host + " : "
+          + e.getMessage());
+    }
+  }
+
+  public void close() throws ProtocolException {
+    currentFile = parentFile = null;
+  }
+
+  public void get(ProtocolFile fromFile, File toFile)
+      throws ProtocolException {
+
+    OutputStream out = null;
+    InputStream in = null;
+    try {
+      out = new BufferedOutputStream(new FileOutputStream(toFile));
+      if (fromFile instanceof HttpFile) {
+    	  in = ((HttpFile) fromFile).getLink().openStream();
+      } else {
+    	  in = HttpUtils.resolveUri(currentFile.getLink().toURI(), fromFile.getPath()).toURL().openStream();
+      }
+
+      byte[] buffer = new byte[1024];
+      int numRead;
+      long numWritten = 0;
+      while ((numRead = in.read(buffer)) != -1) {
+        out.write(buffer, 0, numRead);
+        numWritten += numRead;
+      }
+      in.close();
+      out.close();
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to get file '" + fromFile + "' : "
+          + e.getMessage(), e);
+    } finally {
+      if (in != null)
+        try {
+          in.close();
+        } catch (Exception e) {
+          // log failure
+        }
+      if (out != null)
+        try {
+          out.close();
+        } catch (Exception e) {
+          // log failure
+        }
+    }
+  }
+  
+  public void put(File fromFile, ProtocolFile toFile) {
+	  //do nothing
+  }
+
+  public List<ProtocolFile> ls() throws ProtocolException {
+  	List<ProtocolFile> lsResults = new ArrayList<ProtocolFile>();
+  	for (HttpFile file : parseLink(currentFile)) {
+  		lsResults.add(file);
+  	}
+    return lsResults;
+  }
+
+	public List<ProtocolFile> ls(ProtocolFileFilter filter)
+			throws ProtocolException {
+  	List<ProtocolFile> lsResults = new ArrayList<ProtocolFile>();
+  	for (HttpFile file : parseLink(currentFile)) {
+  		if (filter.accept(file)) {
+  			lsResults.add(file);
+  		}
+  	}
+    return lsResults;
+	}
+	
+  public ProtocolFile pwd() throws ProtocolException {
+    try {
+      return currentFile;
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to get current working directory : "
+          + e.getMessage());
+    }
+  }
+
+  public boolean connected() {
+    return this.isConnected;
+  }
+
+  public List<HttpFile> parseLink(HttpFile file)
+      throws ProtocolException {
+    List<HttpFile> children = linkChildren.get(file.getLink()
+        .toString());
+    if (file.isDir() && children == null) {
+      try {
+
+        // Open link.
+        HttpURLConnection conn = HttpUtils.connect(file.getLink());
+
+        // If redirection took place, then change the ProtocolFile's URL.
+        if (HttpUtils.checkForRedirection(file.getLink(), conn.getURL())) {
+          file = new HttpFile(file, file.getPath(), file.isDir(), conn.getURL());
+        }
+
+        // Find links in URL.
+        children = new LinkedList<HttpFile>();
+        children.addAll(HttpUtils.findLinks(file));
+        
+        // Save children links found.
+        linkChildren.put(file.getLink().toString(), children);
+
+      } catch (Exception e) {
+        throw new ProtocolException("Failed to get children links for " + file
+            + " : " + e.getMessage(), e);
+      }
+    }
+    return children;
+  }
+
+//  public static String findLinkInATag(String aTag) {
+//    // find 'href' attribute
+//    String find = aTag.substring(aTag.indexOf("href") + 4);
+//    // USE STRICT FINDING FIRST
+//    // (['\"])\s*?[(http)(./)(..)/#].+?\\1
+//    // finds link between ' or ", which starts with one of
+//    // the following: http, ./, .., /, #
+//    // these starting possibilities can then be followed any
+//    // number of characters until the corresponding
+//    // ' or " is reached.
+//    String patternRegExp = "(['\"])\\s*?[\\(http\\)\\(\\./\\)\\(\\.\\.\\)/#].+?\\1";
+//    Pattern linkPattern = Pattern.compile(patternRegExp);
+//    Matcher linkMatch = linkPattern.matcher(find);
+//    if (linkMatch.find())
+//      find = find.substring(linkMatch.start() + 1, linkMatch.end() - 1);
+//    else {
+//      // RELAX FINDING SOME
+//      patternRegExp = "(['\"])\\s*?[^./].+?\\1";
+//      linkPattern = Pattern.compile(patternRegExp);
+//      linkMatch = linkPattern.matcher(find);
+//      if (linkMatch.find())
+//        find = find.substring(linkMatch.start() + 1, linkMatch.end() - 1);
+//      else {
+//        // EXTREMELY RELAX FINDING
+//        patternRegExp = "[^\"='/>\\s]+?[^\\s>\"']*?";
+//        linkPattern = Pattern.compile(patternRegExp);
+//        linkMatch = linkPattern.matcher(find);
+//        if (linkMatch.find())
+//          find = find.substring(linkMatch.start(), linkMatch.end());
+//        else {
+//          return null;
+//        }
+//      }
+//    }
+//    return find;
+//  }
+//
+//  public static String createLinkFromHref(HttpFile parent, String href) {
+//    if (!href.startsWith("http")) {
+//      String link = parent.getLink().toExternalForm();
+//      if (href.startsWith("..")) {
+//        int index = link.substring(0, link.lastIndexOf("/")).lastIndexOf("/");
+//        href = (index < 7) ? link + href.substring(2) : link.substring(0, link
+//            .substring(0, link.lastIndexOf("/")).lastIndexOf("/"))
+//            + href.substring(2);
+//      } else if (href.startsWith("./")) {
+//        int index = link.lastIndexOf("/");
+//        href = (index < 7) ? link + href.substring(1) : link
+//            .substring(0, index)
+//            + href.substring(1);
+//      } else if (href.startsWith("/")) {
+//        URL url = parent.getLink();
+//        href = url.getProtocol() + "://" + url.getHost() + href;
+//      } else {
+//        // find the last / in current link
+//        int index = link.lastIndexOf("/");
+//        // (index < 7) checks if in the current link, "/" only exists
+//        // in the protocol section of link (i.e. http://jpl.nasa.gov)
+//        href = (index < 7) ? link + "/" + href : link.substring(0, index) + "/"
+//            + href;
+//      }
+//    }
+//
+//    // remove "/" at end of link
+//    if (href.endsWith("/"))
+//      href = href.substring(0, href.length() - 1);
+//    href = href.trim();
+//
+//    return href;
+//  }
+//
+//  public ProtocolFile getProtocolFileFor(String path, boolean isDir)
+//      throws ProtocolException {
+//    try {
+//      StringTokenizer st = new StringTokenizer(path, "/ ");
+//      HttpFile curPath = this.parentFile;
+//      // System.out.println(parentPath);
+//      if (st.hasMoreTokens()) {
+//        do {
+//          String token = st.nextToken();
+//          List<HttpFile> children = this.parseLink(curPath);
+//          for (HttpFile pFile : children) {
+//            if (pFile.getName().equals(token)) {
+//              // System.out.println("token " + token + " " +
+//              // pFile);
+//              curPath = pFile;
+//              continue;
+//            }
+//          }
+//        } while (st.hasMoreTokens());
+//        if (curPath.equals(this.parentFile))
+//          return new HttpFile(path, isDir, new URL("http://"
+//                  + this.getSite().getHost() + path), curPath);
+//      }
+//      return curPath;
+//    } catch (Exception e) {
+//      throw new ProtocolException("Failed to get ProtocolPath for " + path);
+//    }
+//  }
+
+  public void delete(ProtocolFile file) {}
+
+//  private URL getSite() {
+//	return currentURL;  
+//  }
+  
+  public static void main(String[] args) throws Exception {
+    String urlString = null, downloadToDir = null;
+    for (int i = 0; i < args.length; i++) {
+      if (args[i].equals("--url"))
+        urlString = args[++i];
+      else if (args[i].equals("--downloadToDir"))
+        downloadToDir = args[++i];
+    }
+
+    if (urlString == null)
+      throw new Exception("Must specify a url to download: --url <url>");
+
+    URL url = new URL(urlString);
+    ProtocolFile urlFile = new HttpFile(url.getPath(), false, url);
+    File toFile = new File(downloadToDir, urlFile.getName());
+    toFile = toFile.getAbsoluteFile();
+    toFile.createNewFile();
+    new HttpProtocol().get(urlFile, toFile);
+  }
+
+}
diff --git a/0.8.1-rc1/protocol/http/src/main/java/org/apache/oodt/cas/protocol/http/HttpProtocolFactory.java b/0.8.1-rc1/protocol/http/src/main/java/org/apache/oodt/cas/protocol/http/HttpProtocolFactory.java
new file mode 100644
index 0000000..05b5bb3
--- /dev/null
+++ b/0.8.1-rc1/protocol/http/src/main/java/org/apache/oodt/cas/protocol/http/HttpProtocolFactory.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.http;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+
+/**
+ * Factory for creating {@link HttpProtocol}s
+ * 
+ * @author bfoster
+ * @version $Revision$
+ */
+public class HttpProtocolFactory implements ProtocolFactory {
+
+	public HttpProtocol newInstance() {
+		return new HttpProtocol();
+	}
+
+	public String getSchema() {
+		return "http";
+	}
+}
diff --git a/0.8.1-rc1/protocol/http/src/main/java/org/apache/oodt/cas/protocol/http/util/HttpUtils.java b/0.8.1-rc1/protocol/http/src/main/java/org/apache/oodt/cas/protocol/http/util/HttpUtils.java
new file mode 100644
index 0000000..a006598
--- /dev/null
+++ b/0.8.1-rc1/protocol/http/src/main/java/org/apache/oodt/cas/protocol/http/util/HttpUtils.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.http.util;
+
+//JDK imports
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+//APACHE imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.MimeTypeUtils;
+import org.apache.oodt.cas.protocol.http.HttpFile;
+
+/**
+ * Utility methods for HTTP Protocol related tasks.
+ *
+ * @author bfoster
+ */
+public class HttpUtils {
+
+  static final MimeTypeUtils MIME_TYPES = new MimeTypeUtils();
+  
+	// Pattern looking for <a href="(group-2)"/>(group-3)</a> . . . group-1 is for either " or '
+	static final Pattern XHTML_LINK_PATTERN = Pattern.compile("<\\s*a\\s+href\\s*=\\s*(['\"])(.+?)\\1\\s*>(.+?)<\\s*/\\s*a\\s*>"); 
+	static final Pattern LAZY_LINK_PATTERN = Pattern.compile("<\\s*a\\s+href\\s*=\\s*(['\"])(.+?)\\1\\s*/\\s*>"); 
+
+	private HttpUtils() {}
+	
+	/**
+	 * Resolves a path against given {@link URI} and creates the resolved {@link URI}.
+	 * (i.e. base = "http://localhost" ; path = "/path/to/file" ; resolved = "http://localhost/path/to/file")
+	 * Handles all cases: if base already has a path, if path is relative, if path is absolute.
+	 * 
+	 * @param base The base {@link URI} which the given path will be resolved against.
+	 * @param path The path to be resolved against the given {@link URI}
+	 * @return resolved {@link URI}. 
+	 * @throws URISyntaxException
+	 */
+	public static URI resolveUri(URI base, String path) throws URISyntaxException {
+		Validate.notNull(base, "base URI must not be NULL");
+		Validate.notNull(path, "resolve path must not be NULL");
+		if (path.startsWith("http://")) {
+			return new URI(path);
+		} else if (path.startsWith("/")) {
+			return new URI(base.getScheme() + "://" + base.getHost() + path);
+		} else {
+			if (base.toString().endsWith("/")) {
+				return new URI(base.toString() + path);
+			} else {
+				return new URI(base.toString() + "/" + path);				
+			}
+		}
+	}
+
+	public static HttpURLConnection connect(URL url) throws IOException {
+		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+		conn.connect();
+		conn.getResponseMessage();
+		return conn;
+	}
+
+  public static boolean checkForRedirection(URL beforeConnUrl, URL afterConnUrl) {
+    return !beforeConnUrl.toString().equals(afterConnUrl.toString());
+  }
+
+  public static String readUrl(HttpURLConnection conn) throws IOException {
+    // create URL source reader
+    Scanner scanner = new Scanner(conn.getInputStream());
+
+    // Read in link
+    StringBuffer sb = new StringBuffer("");
+    while (scanner.hasNext())
+      sb.append(scanner.nextLine());
+    
+    return sb.toString();
+  }
+
+	public static List<HttpFile> findLinks(HttpFile file) throws IOException, URISyntaxException {
+		Matcher matcher = XHTML_LINK_PATTERN.matcher(HttpUtils.readUrl(connect(file.getLink())));
+		List<HttpFile> httpFiles = new ArrayList<HttpFile>();
+		while (matcher.find()) {
+			String link = matcher.group(2).trim();
+			String virtualPath = matcher.group(3).trim();
+			URL url = resolveUri(file.getLink().toURI(), link).toURL();
+			httpFiles.add(new HttpFile(file, link, isDirectory(url, virtualPath), url));
+		}
+		matcher = LAZY_LINK_PATTERN.matcher(HttpUtils.readUrl(connect(file.getLink())));
+		while (matcher.find()) {
+			String link = matcher.group(2).trim();
+			URL url = resolveUri(file.getLink().toURI(), link).toURL();
+			httpFiles.add(new HttpFile(file, link, isDirectory(url, link), url));
+		}
+		return httpFiles;
+	}
+		
+	public static boolean isDirectory(URL url, String virtualPath) throws IOException {
+		try {
+			String mime = MIME_TYPES.autoResolveContentType(url.toString(),
+					MimeTypeUtils.readMagicHeader(url.openStream()));
+			return (mime.equals("text/html") && !virtualPath.endsWith(".html"));
+		} catch (Exception e) {
+			throw new IOException("URL does not exist '" + url + "'", e);
+		}
+	}
+}
diff --git a/0.8.1-rc1/protocol/http/src/main/resources/policy/http-protocol-config.xml b/0.8.1-rc1/protocol/http/src/main/resources/policy/http-protocol-config.xml
new file mode 100644
index 0000000..3b96e58
--- /dev/null
+++ b/0.8.1-rc1/protocol/http/src/main/resources/policy/http-protocol-config.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<!-- 
+	
+	Author: bfoster
+	Description: ProtocolManager Configuration
+	
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean class="org.apache.oodt.cas.protocol.http.HttpProtocolFactory"/>
+	
+</beans>
diff --git a/0.8.1-rc1/protocol/http/src/test/java/org/apache/oodt/cas/protocol/http/TestHttpFile.java b/0.8.1-rc1/protocol/http/src/test/java/org/apache/oodt/cas/protocol/http/TestHttpFile.java
new file mode 100644
index 0000000..c9b451a
--- /dev/null
+++ b/0.8.1-rc1/protocol/http/src/test/java/org/apache/oodt/cas/protocol/http/TestHttpFile.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.http;
+
+//JUnit imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link HttpFile}.
+ * 
+ * @author bfoster
+ */
+public class TestHttpFile extends TestCase {
+
+	public void testInitialState() throws MalformedURLException {
+		HttpFile parent = new HttpFile("/path/to", false, new URL("http://some-site"));
+		HttpFile file = new HttpFile(parent, "/path/to/file", false, new URL("http://some-site"));
+		assertNotNull(file.getLink());
+		assertEquals("http://some-site", file.getLink().toString());
+		assertFalse(file.isDir());
+		assertFalse(file.isRelative());
+		assertNotNull(file.getParent());
+		assertEquals(parent, file.getParent());
+	}
+	
+	public void testNullCase() throws MalformedURLException {
+		try {
+			 new HttpFile(null, false, new URL("http://some-site"));
+			fail("Should have thrown an IllegalArgumentException");
+		} catch (IllegalArgumentException e) {}
+		try {
+			 new HttpFile("/path/to/file", false, null);
+			fail("Should have thrown an IllegalArgumentException");
+		} catch (IllegalArgumentException e) {}
+	}
+}
diff --git a/0.8.1-rc1/protocol/http/src/test/java/org/apache/oodt/cas/protocol/http/TestHttpProtocol.java b/0.8.1-rc1/protocol/http/src/test/java/org/apache/oodt/cas/protocol/http/TestHttpProtocol.java
new file mode 100644
index 0000000..05a7c4f
--- /dev/null
+++ b/0.8.1-rc1/protocol/http/src/test/java/org/apache/oodt/cas/protocol/http/TestHttpProtocol.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.http;
+
+//JUnit imports
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import java.util.Scanner;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.auth.NoAuthentication;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+import org.apache.oodt.cas.protocol.http.util.HttpUtils;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link HttpProtocol}.
+ * 
+ * @author bfoster
+ */
+public class TestHttpProtocol extends TestCase {
+	
+	public void testConnection() throws InstantiationException, ProtocolException {
+		HttpProtocol httpProtocol = new HttpProtocol();
+		assertFalse(httpProtocol.connected());
+		httpProtocol.connect("svn.apache.org", new NoAuthentication());
+		assertTrue(httpProtocol.connected());
+	}
+	
+	public void testLSandCD() throws ProtocolException, InstantiationException {
+		HttpProtocol httpProtocol = new HttpProtocol();
+		httpProtocol.connect("svn.apache.org", new NoAuthentication());
+		assertTrue(httpProtocol.connected());
+		httpProtocol.cd(new ProtocolFile("repos/asf/oodt/trunk/protocol/http/src/main/java/org/apache/oodt/cas/protocol/http", true));
+		List<ProtocolFile> files = httpProtocol.ls();
+		boolean foundFile = false;
+		for (ProtocolFile file : files) {
+			if (file.getName().equals("HttpProtocol.java")) {
+				foundFile = true;
+				break;
+			}
+		}
+		assertTrue(foundFile);
+	}
+	
+	public void testPWD() throws ProtocolException {
+		HttpProtocol httpProtocol = new HttpProtocol();
+		httpProtocol.connect("svn.apache.org", new NoAuthentication());
+		assertTrue(httpProtocol.connected());
+		ProtocolFile gotoDir = new ProtocolFile(httpProtocol.pwd(),
+			"repos/asf/oodt/trunk/protocol/http/src/test/java/org/apache/oodt/cas/protocol/http", true);
+		httpProtocol.cd(gotoDir);
+		ProtocolFile currentDir = httpProtocol.pwd();
+		System.out.println(gotoDir.getAbsoluteFile());
+		System.out.println(currentDir.getAbsoluteFile());
+		assertEquals(gotoDir, currentDir);
+	}
+	
+	public void testGET() throws ProtocolException, IOException {
+		HttpProtocol httpProtocol = new HttpProtocol();
+		httpProtocol.connect("svn.apache.org", new NoAuthentication());
+		assertTrue(httpProtocol.connected());
+		httpProtocol.cd(new ProtocolFile("repos/asf/oodt/trunk/protocol/http/src/test/java/org/apache/oodt/cas"
+										 + "/protocol/http", true));
+		File bogus = File.createTempFile("bogus", "bogus");
+		File tmpDir = new File(bogus.getParentFile(), "TestHttpProtocol");
+		bogus.delete();
+		tmpDir.mkdirs();
+		File toFile = new File(tmpDir, "TestHttpProtocol.java");
+		httpProtocol.get(new ProtocolFile("TestHttpProtocol.java", false), toFile);
+		assertTrue(toFile.exists());
+		assertNotSame(0, toFile.length());
+		
+		String fileContent = "";
+		Scanner scanner = new Scanner(toFile);
+		while(scanner.hasNextLine()) {
+			fileContent += scanner.nextLine();
+		}
+		assertEquals(fileContent, HttpUtils.readUrl(HttpUtils.connect(new URL("http://svn.apache.org/repos/asf/oodt/"
+																			  + "trunk/protocol/http/src/test/java/org/"
+																			  + "apache/oodt/cas/protocol/http/"
+																			  + "TestHttpProtocol.java"))));
+		FileUtils.forceDelete(tmpDir);
+	}
+}
diff --git a/0.8.1-rc1/protocol/http/src/test/java/org/apache/oodt/cas/protocol/http/util/TestHttpUtils.java b/0.8.1-rc1/protocol/http/src/test/java/org/apache/oodt/cas/protocol/http/util/TestHttpUtils.java
new file mode 100644
index 0000000..67903ec
--- /dev/null
+++ b/0.8.1-rc1/protocol/http/src/test/java/org/apache/oodt/cas/protocol/http/util/TestHttpUtils.java
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.http.util;
+
+//JDK imports
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+import java.util.regex.Matcher;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.http.HttpFile;
+
+//JUnits imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link HttpUtils}.
+ *
+ * @author bfoster
+ */
+public class TestHttpUtils extends TestCase {
+	
+	private static final String APACHE_SVN_SITE = "http://svn.apache.org";
+	
+	private static final String PROTOCOL_HTTP_SVN_LOC = "/repos/asf/oodt/trunk/protocol/http";
+	private static final String PARENT_URL_OF_THIS_TEST = PROTOCOL_HTTP_SVN_LOC +
+														  "/src/test/java/org/apache/oodt/cas/protocol/http/util";
+	private static final String URL_OF_THIS_TEST = PARENT_URL_OF_THIS_TEST + "/TestHttpUtils.java";
+	
+	public void testResolveUri() throws URISyntaxException {
+		URI baseUri = new URI("http://localhost/base/directory/");
+		
+		// Test absolute resolve.
+		URI resolvedAbsoluteUri = HttpUtils.resolveUri(baseUri, "/path/to/file");
+		assertEquals("http://localhost/path/to/file", resolvedAbsoluteUri.toString());
+		
+		// Test relative resolve.
+		URI resolvedRelativeUri = HttpUtils.resolveUri(baseUri, "path/to/file");
+		assertEquals("http://localhost/base/directory/path/to/file", resolvedRelativeUri.toString());
+
+		// Test relative with base not ending in /
+		baseUri = new URI("http://localhost/base/directory");
+		assertEquals("http://localhost/base/directory/path/to/file", resolvedRelativeUri.toString());
+	}
+	
+	public void testConnectUrl() throws MalformedURLException, IOException {
+		HttpURLConnection conn = HttpUtils.connect(new URL(APACHE_SVN_SITE + URL_OF_THIS_TEST));
+		assertNotSame(0, conn.getDate());
+		String urlText = HttpUtils.readUrl(conn);
+		assertTrue(urlText.contains("public class TestHttpUtils extends TestCase {"));
+		conn.disconnect();
+	}
+	
+	public void testRedirector() throws MalformedURLException {
+		URL url = new URL("http://localhost:80");
+		URL redirectedURL = new URL("http://localhost:8080");
+		assertFalse(HttpUtils.checkForRedirection(url, url));
+		assertTrue(HttpUtils.checkForRedirection(url, redirectedURL));
+	}
+
+	public void testXhtmlLinkPattern() {
+		// SUCCESS cases
+		Matcher matcher = HttpUtils.XHTML_LINK_PATTERN.matcher("<a href=\"http://localhost\">localhost</a>");
+		assertTrue(matcher.find());
+		assertEquals("\"", matcher.group(1).trim());
+		assertEquals("http://localhost", matcher.group(2).trim());
+		assertEquals("localhost", matcher.group(3).trim());
+		
+		matcher = HttpUtils.XHTML_LINK_PATTERN.matcher("<a href='http://localhost'>localhost</a>");
+		assertTrue(matcher.find());
+		assertEquals("'", matcher.group(1).trim());
+		assertEquals("http://localhost", matcher.group(2).trim());
+		assertEquals("localhost", matcher.group(3).trim());
+		
+		matcher = HttpUtils.XHTML_LINK_PATTERN.matcher("< a href = \" http://localhost \" >  localhost < / a >");
+		assertTrue(matcher.find());
+		assertEquals("\"", matcher.group(1).trim());
+		assertEquals("http://localhost", matcher.group(2).trim());
+		assertEquals("localhost", matcher.group(3).trim());
+		
+		matcher = HttpUtils.XHTML_LINK_PATTERN.matcher("< a href = ' http://localhost ' >  localhost < / a >");
+		assertTrue(matcher.find());
+		assertEquals("'", matcher.group(1).trim());
+		assertEquals("http://localhost", matcher.group(2).trim());
+		assertEquals("localhost", matcher.group(3).trim());
+		
+		//Should not find case: open with " end with '
+		matcher = HttpUtils.XHTML_LINK_PATTERN.matcher("<a href=\"http://localhost\'>localhost</a>");
+		assertFalse(matcher.find());
+		
+		//Should not find case: open with ' end with "
+		matcher = HttpUtils.XHTML_LINK_PATTERN.matcher("<a href=\'http://localhost\">localhost</a>");
+		assertFalse(matcher.find());
+		
+		//Should not find case: lazy link pattern
+		matcher = HttpUtils.XHTML_LINK_PATTERN.matcher("<a href=\"http://localhost\"/>");
+		assertFalse(matcher.find());
+	}
+	
+	public void testLazyLinkPattern() {
+		Matcher matcher = HttpUtils.LAZY_LINK_PATTERN.matcher("<a href=\"http://localhost\"/>");
+		assertTrue(matcher.find());
+		assertEquals("\"", matcher.group(1).trim());
+		assertEquals("http://localhost", matcher.group(2).trim());
+		
+		matcher = HttpUtils.LAZY_LINK_PATTERN.matcher("<a href='http://localhost'/>");
+		assertTrue(matcher.find());
+		assertEquals("'", matcher.group(1).trim());
+		assertEquals("http://localhost", matcher.group(2).trim());
+		
+		matcher = HttpUtils.LAZY_LINK_PATTERN.matcher("< a href = \" http://localhost \" / >");
+		assertTrue(matcher.find());
+		assertEquals("\"", matcher.group(1).trim());
+		assertEquals("http://localhost", matcher.group(2).trim());
+		
+		matcher = HttpUtils.LAZY_LINK_PATTERN.matcher("< a href = ' http://localhost ' / >");
+		assertTrue(matcher.find());
+		assertEquals("'", matcher.group(1).trim());
+		assertEquals("http://localhost", matcher.group(2).trim());
+		
+		//Should not find case: open with " end with '
+		matcher = HttpUtils.LAZY_LINK_PATTERN.matcher("<a href=\"http://localhost\'/>");
+		assertFalse(matcher.find());
+		
+		//Should not find case: open with ' end with "
+		matcher = HttpUtils.LAZY_LINK_PATTERN.matcher("<a href=\'http://localhost\"/>");
+		assertFalse(matcher.find());
+		
+		//Should not find case: xhtml link pattern
+		matcher = HttpUtils.LAZY_LINK_PATTERN.matcher("<a href='http://localhost'>localhost</a>");
+		assertFalse(matcher.find());
+	}
+	
+	public void testFindLinks() throws MalformedURLException, IOException, URISyntaxException {
+		URL url = new URL(APACHE_SVN_SITE + PARENT_URL_OF_THIS_TEST);
+		HttpFile parent = new HttpFile(PARENT_URL_OF_THIS_TEST, true, url);
+		HttpURLConnection conn = HttpUtils.connect(url);
+		List<HttpFile> httpFiles = HttpUtils.findLinks(parent);
+		boolean foundThisTest = false;
+		for (HttpFile httpFile : httpFiles) {
+			if (httpFile.getName().equals("TestHttpUtils.java")) {
+				foundThisTest = true;
+				break;
+			}
+		}
+		assertTrue(foundThisTest);
+	}
+	
+	public void testIsDirectory() throws MalformedURLException, IOException {
+		assertTrue(HttpUtils.isDirectory(new URL(APACHE_SVN_SITE + PARENT_URL_OF_THIS_TEST), ""));
+		assertFalse(HttpUtils.isDirectory(new URL(APACHE_SVN_SITE + URL_OF_THIS_TEST), ""));
+		assertTrue(HttpUtils.isDirectory(new URL(APACHE_SVN_SITE), ""));
+	}
+}
diff --git a/0.8.1-rc1/protocol/imaps/pom.xml b/0.8.1-rc1/protocol/imaps/pom.xml
new file mode 100644
index 0000000..aadc040
--- /dev/null
+++ b/0.8.1-rc1/protocol/imaps/pom.xml
@@ -0,0 +1,101 @@
+<?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. -->
+<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>
+	<parent>
+		<groupId>org.apache.oodt</groupId>
+		<artifactId>oodt-core</artifactId>
+		<version>0.8.1</version>
+		<relativePath>../../core/pom.xml</relativePath>
+	</parent>
+	<artifactId>cas-protocol-imaps</artifactId>
+	<name>CAS Protocol IMAPS Implementation</name>
+	<profiles>
+		<profile>
+			<id>audit</id>
+			<activation>
+				<activeByDefault>false</activeByDefault>
+			</activation>
+			<build>
+				<plugins>
+					<plugin>
+						<groupId>org.codehaus.mojo</groupId>
+						<artifactId>rat-maven-plugin</artifactId>
+						<configuration>
+							<excludes>
+								<exclude>**/resources/examples/**/*</exclude>
+							</excludes>
+						</configuration>
+						<executions>
+							<execution>
+								<phase>verify</phase>
+								<goals>
+									<goal>check</goal>
+								</goals>
+							</execution>
+						</executions>
+					</plugin>
+				</plugins>
+			</build>
+		</profile>
+	</profiles>
+  <build>
+    <resources>
+      <resource>
+        <targetPath>org/apache/oodt/cas/protocol/imaps</targetPath>
+        <directory>${basedir}/src/main/resources/policy</directory>
+        <includes>
+          <include>imaps-protocol-config.xml</include>
+        </includes>
+      </resource>
+    </resources>
+  </build>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>cas-protocol-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.geronimo.javamail</groupId>
+			<artifactId>geronimo-javamail_1.4_mail</artifactId>
+			<version>1.8.1</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.geronimo.specs</groupId>
+			<artifactId>geronimo-activation_1.1_spec</artifactId>
+			<version>1.1</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.tika</groupId>
+			<artifactId>tika-parsers</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.icegreen</groupId>
+			<artifactId>greenmail</artifactId>
+			<version>1.3.1b</version>
+			<scope>test</scope>
+		</dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>1.3.1</version>
+        </dependency>
+        <dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.2</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+</project>
diff --git a/0.8.1-rc1/protocol/imaps/src/main/java/org/apache/oodt/cas/protocol/imaps/ImapsProtocol.java b/0.8.1-rc1/protocol/imaps/src/main/java/org/apache/oodt/cas/protocol/imaps/ImapsProtocol.java
new file mode 100644
index 0000000..723d2ae
--- /dev/null
+++ b/0.8.1-rc1/protocol/imaps/src/main/java/org/apache/oodt/cas/protocol/imaps/ImapsProtocol.java
@@ -0,0 +1,393 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.imaps;
+
+//JDK imports
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+//Javamail imports
+import javax.mail.Address;
+import javax.mail.Flags;
+import javax.mail.Folder;
+import javax.mail.Header;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.Part;
+import javax.mail.Session;
+import javax.mail.Store;
+import org.xml.sax.SAXException;
+
+//APACHE imports
+import org.apache.commons.codec.DecoderException;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.auth.Authentication;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+import org.apache.oodt.cas.protocol.util.ProtocolFileFilter;
+
+//TIKA imports
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.parser.html.HtmlParser;
+import org.apache.tika.sax.BodyContentHandler;
+import org.apache.tika.sax.TextContentHandler;
+
+/**
+ * IMAP Secure {@link Protocol} implementation
+ * 
+ * @author bfoster
+ * @version $Revision$
+ */
+public class ImapsProtocol implements Protocol {
+
+  static Store store;
+
+  static Folder currentFolder;
+  
+  static Folder homeFolder;
+  
+  static int port = 993;
+
+  static Session session;
+
+  static int openCalls = 0;
+
+  static int connectCalls = 0;
+  
+  public synchronized void cd(ProtocolFile file) throws ProtocolException {
+    try {
+      String remotePath = file.getPath();
+      if (remotePath.startsWith("/"))
+        remotePath = remotePath.substring(1);
+      if (remotePath.trim().equals(""))
+        homeFolder = currentFolder = store.getDefaultFolder();
+      else {
+        homeFolder = currentFolder = store.getFolder(remotePath);
+      }
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to change directory to '" 
+      		+ file + "' : " + e.getMessage(), e);
+    }
+  }
+
+  public synchronized void cdRoot() throws ProtocolException {
+    try {
+      cd(new ProtocolFile("/", true));
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to cd to root : " + e.getMessage(), e);
+    }
+  }
+  
+  public synchronized void cdHome() throws ProtocolException {
+    try {
+      cd(new ProtocolFile("", true));
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to cd to home : " + e.getMessage(), e);
+    }
+  }
+  
+  public synchronized void connect(String host, Authentication auth)
+      throws ProtocolException {
+    try {
+      if (store == null) {
+        store = (session = Session.getInstance(System.getProperties()))
+            .getStore("imaps");
+        store.connect(host, port, auth.getUser(), auth.getPass());
+        currentFolder = store.getDefaultFolder();
+      }
+      this.incrementConnections();
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to connected to IMAPS server " + host
+          + " with username " + auth.getUser() + " : " + e.getMessage(), e);
+    }
+  }
+
+  public synchronized void close() throws ProtocolException {
+    decrementConnections();
+    if (connectCalls <= 0) {
+      try {
+//        if (!currentFolder.isOpen()) {
+//          try {
+//            currentFolder.open(Folder.READ_WRITE);
+//          } catch (Exception e) {
+//            try {
+//              currentFolder.open(Folder.READ_ONLY);
+//            } catch (Exception e2) {
+//            }
+//          }
+//        }
+//        currentFolder.close(true);
+        store.close();
+      } catch (Exception e) {
+        throw new ProtocolException("Failed to close connection : " + e.getMessage(), e);
+      } finally {
+        store = null;
+      }
+    }
+  }
+
+  private synchronized void incrementConnections() {
+    connectCalls++;
+  }
+
+  private synchronized void decrementConnections() {
+    if (connectCalls > 0)
+      connectCalls--;
+  }
+
+  public synchronized void get(ProtocolFile fromFile, File toFile)
+      throws ProtocolException {
+    try {
+      openFolder(currentFolder);
+      Message[] messages = currentFolder.getMessages();
+      for (Message message : messages) {
+        if (this.getMessageName(message).equals(fromFile.getName())) {
+          writeMessageToLocalFile(message, toFile);
+          // message.setFlag(Flags.Flag.DELETED, true);
+          break;
+        }
+      }
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to download " + fromFile + " to "
+          + toFile + " : " + e.getMessage(), e);
+    } finally {
+      try {
+        closeFolder(currentFolder);
+      } catch (Exception e) {
+      }
+    }
+  }
+
+  public synchronized void put(File fromFile, ProtocolFile toFile) {
+	  //do nothing;
+  }
+  
+  private void writeMessageToLocalFile(Message message, File toLocalFile)
+      throws MessagingException, IOException, DecoderException, SAXException,
+      TikaException {
+    PrintStream ps = new PrintStream(new FileOutputStream(toLocalFile));
+
+    ps.print("From:");
+    Address[] senders = message.getFrom();
+    for (Address address : senders)
+      ps.print(" " + address.toString());
+
+    ps.print("\nTo:");
+		Set<Address> recipients = new LinkedHashSet<Address>(Arrays.asList(message
+				.getAllRecipients()));
+    for (Address address : recipients)
+      ps.print(" " + address.toString());
+
+    ps.println("\nSubject: " + message.getSubject());
+
+    ps.println("----- ~ Message ~ -----");
+    String content = this.getContentFromHTML(message);
+    if (content.equals(""))
+      content = this.getContentFromPlainText(message);
+    ps.println(content);
+
+    ps.close();
+  }
+
+  public synchronized boolean connected() {
+    return store.isConnected();
+  }
+
+  public List<ProtocolFile> ls() throws ProtocolException {
+    // if (changedDir) {
+    // System.out.println("Refreshed LS");
+    // currentFilesForCurrentFolder = new LinkedList<ProtocolFile>();
+    LinkedList<ProtocolFile> currentFilesForCurrentFolder = new LinkedList<ProtocolFile>();
+    try {
+      openFolder(currentFolder);
+      if (!currentFolder.getFullName().equals(
+          store.getDefaultFolder().getFullName())) {
+        Message[] messages = currentFolder.getMessages();
+        for (Message message : messages) {
+          currentFilesForCurrentFolder.add(new ProtocolFile(this.pwd().getPath()
+              + "/" + this.getMessageName(message), false));
+        }
+      }
+      // changedDir = false;
+    } catch (Exception e) {
+      if (!currentFolder.getFullName().equals(""))
+        throw new ProtocolException("Failed to ls : " + e.getMessage(), e);
+    } finally {
+      try {
+        closeFolder(currentFolder);
+      } catch (Exception e) {
+      }
+    }
+    // }
+    return currentFilesForCurrentFolder;
+  }
+
+	public List<ProtocolFile> ls(ProtocolFileFilter filter)
+			throws ProtocolException {
+    LinkedList<ProtocolFile> currentFilesForCurrentFolder = new LinkedList<ProtocolFile>();
+    try {
+      openFolder(currentFolder);
+      if (!currentFolder.getFullName().equals(
+          store.getDefaultFolder().getFullName())) {
+        Message[] messages = currentFolder.getMessages();
+        for (Message message : messages) {
+        	ProtocolFile pFile = new ProtocolFile(this.pwd().getPath()
+              + "/" + this.getMessageName(message), false);
+        	if (filter.accept(pFile)) {
+        		currentFilesForCurrentFolder.add(pFile);
+        	}
+        }
+      }
+    } catch (Exception e) {
+      if (!currentFolder.getFullName().equals(""))
+        throw new ProtocolException("Failed to ls : " + e.getMessage(), e);
+    } finally {
+      try {
+        closeFolder(currentFolder);
+      } catch (Exception e) {
+      }
+    }
+    return currentFilesForCurrentFolder;
+	}
+
+  public synchronized ProtocolFile pwd()
+      throws ProtocolException {
+    try {
+      String pwd = currentFolder.getFullName();
+      if (!pwd.equals("") && !pwd.startsWith("/"))
+        pwd = "/" + pwd;
+      return new ProtocolFile(pwd, true);
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to pwd : " + e.getMessage(), e);
+    }
+  }
+
+  private String getMessageName(Message msg) throws MessagingException {
+    Enumeration headers = msg.getAllHeaders();
+    while (headers.hasMoreElements()) {
+      Header header = (Header) headers.nextElement();
+      if (header.getName().toLowerCase().equals("message-id")) {
+        String stringHeader = header.getValue();
+        // System.out.println(stringHeader);
+        stringHeader = stringHeader.replace("<", "");
+        return stringHeader.substring(0, stringHeader.indexOf("@"));
+      }
+    }
+    return null;
+  }
+
+  private String getContentFromPlainText(Part p) throws MessagingException,
+      IOException, DecoderException {
+    StringBuffer content = new StringBuffer("");
+    if (p.isMimeType("text/plain")) {
+      content.append((String) p.getContent());
+    } else if (p.isMimeType("multipart/*")) {
+      Multipart mp = (Multipart) p.getContent();
+      int count = mp.getCount();
+      for (int i = 0; i < count; i++)
+        content.append(getContentFromPlainText(mp.getBodyPart(i)));
+    } else {
+      Object obj = p.getContent();
+      if (obj instanceof Part)
+        content.append(getContentFromPlainText((Part) p.getContent()));
+    }
+    return content.toString().replaceAll(" \\r\\n", "").replaceAll(" \\n", "");
+  }
+
+  private String getContentFromHTML(Part p) throws MessagingException,
+      IOException, DecoderException, SAXException, TikaException {
+    StringBuffer content = new StringBuffer("");
+    if (p.isMimeType("multipart/*")) {
+      Multipart mp = (Multipart) p.getContent();
+      int count = mp.getCount();
+      for (int i = 0; i < count; i++)
+        content.append(getContentFromHTML(mp.getBodyPart(i)));
+    } else if (p.isMimeType("text/html")) {
+      HtmlParser parser = new HtmlParser();
+      Metadata met = new Metadata();
+      TextContentHandler handler = new TextContentHandler(
+          new BodyContentHandler());
+      parser.parse(new ByteArrayInputStream(((String) p.getContent())
+          .getBytes()), handler, met);
+      content.append(handler.toString());
+    } else {
+      Object obj = p.getContent();
+      if (obj instanceof Part)
+        content.append(getContentFromHTML((Part) p.getContent()));
+    }
+    return content.toString();
+  }
+
+  private synchronized void openFolder(Folder folder) throws ProtocolException {
+    if (!folder.isOpen()) {
+      try {
+        folder.open(Folder.READ_WRITE);
+      } catch (Exception e) {
+        try {
+          folder.open(Folder.READ_ONLY);
+        } catch (Exception e2) {
+          throw new ProtocolException("Failed to open folder : "
+              + e.getMessage() + " : " + e2.getMessage());
+        }
+      }
+    }
+    openCalls++;
+  }
+
+  private synchronized void closeFolder(Folder folder) {
+    if (openCalls > 0)
+      openCalls--;
+
+    if (openCalls <= 0) {
+      try {
+        folder.close(true);
+      } catch (Exception e) {
+      }
+    }
+  }
+
+  public synchronized void delete(ProtocolFile file) throws ProtocolException {
+    try {
+      openFolder(currentFolder);
+      Message[] messages = currentFolder.getMessages();
+      for (Message message : messages) {
+        if (this.getMessageName(message).equals(file.getName())) {
+          message.setFlag(Flags.Flag.DELETED, true);
+          break;
+        }
+      }
+    } catch (Exception e) {
+    	throw new ProtocolException("Failed to delete file '" + file + "' : " + e.getMessage(), e);
+    } finally {
+      closeFolder(currentFolder);
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/protocol/imaps/src/main/java/org/apache/oodt/cas/protocol/imaps/ImapsProtocolFactory.java b/0.8.1-rc1/protocol/imaps/src/main/java/org/apache/oodt/cas/protocol/imaps/ImapsProtocolFactory.java
new file mode 100644
index 0000000..c2fda6a
--- /dev/null
+++ b/0.8.1-rc1/protocol/imaps/src/main/java/org/apache/oodt/cas/protocol/imaps/ImapsProtocolFactory.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.imaps;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+
+/**
+ * Factory for creating {@link ImapsProtocol}s.
+ * 
+ * @author bfoster
+ * @version $Revision$
+ */
+public class ImapsProtocolFactory implements ProtocolFactory {
+
+    private ImapsProtocol imapsClient;
+
+    public ImapsProtocol newInstance() {
+        if (this.imapsClient == null)
+            this.imapsClient = new ImapsProtocol();
+        return this.imapsClient;
+    }
+
+	public String getSchema() {
+		return "imaps";
+	}
+
+}
diff --git a/0.8.1-rc1/protocol/imaps/src/main/resources/policy/imaps-protocol-config.xml b/0.8.1-rc1/protocol/imaps/src/main/resources/policy/imaps-protocol-config.xml
new file mode 100644
index 0000000..da206b4
--- /dev/null
+++ b/0.8.1-rc1/protocol/imaps/src/main/resources/policy/imaps-protocol-config.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<!-- 
+	
+	Author: bfoster
+	Description: ProtocolManager Configuration
+	
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean class="org.apache.oodt.cas.protocol.imaps.ImapsProtocolFactory"/>
+	
+</beans>
diff --git a/0.8.1-rc1/protocol/imaps/src/test/java/org/apache/oodt/cas/protocol/imaps/TestImapsProtocol.java b/0.8.1-rc1/protocol/imaps/src/test/java/org/apache/oodt/cas/protocol/imaps/TestImapsProtocol.java
new file mode 100644
index 0000000..0c7501f
--- /dev/null
+++ b/0.8.1-rc1/protocol/imaps/src/test/java/org/apache/oodt/cas/protocol/imaps/TestImapsProtocol.java
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.imaps;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.auth.BasicAuthentication;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+
+//GreenMail imports
+import com.icegreen.greenmail.util.DummySSLSocketFactory;
+import com.icegreen.greenmail.util.GreenMail;
+import com.icegreen.greenmail.util.GreenMailUtil;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link ImapsProtocol}.
+ * 
+ * @author bfoster
+ */
+public class TestImapsProtocol extends TestCase {
+
+	private GreenMail gMail;
+	private ImapsProtocol imapsProtocol;
+	
+	@Override
+	public void setUp() {
+  	System.setProperty("mail.imaps.socketFactory.class", DummySSLSocketFactory.class.getCanonicalName());
+		System.setProperty("mail.imaps.socketFactory.fallback", "false");
+		gMail = new GreenMail();
+		gMail.setUser("bfoster@google.com", "password");
+		gMail.start();
+		ImapsProtocol.port = gMail.getImaps().getPort();
+		imapsProtocol = new ImapsProtocol();
+		try {
+			imapsProtocol.connect("localhost", new BasicAuthentication("bfoster@google.com", "password"));
+		} catch (ProtocolException e) {
+			fail("Failed to connect to GreenMail IMAPS server : " + e.getMessage());
+		}
+		assertEquals(1, ImapsProtocol.connectCalls);
+	}
+	
+	@Override
+	public void tearDown() {
+		gMail.stop();
+		try {
+			imapsProtocol.close();
+		} catch (Exception e) {}
+		assertEquals(0, ImapsProtocol.connectCalls);
+	}
+	
+	public void testCDAndPWD() throws ProtocolException {
+		assertEquals("", imapsProtocol.pwd().getPath());
+		imapsProtocol.cd(new ProtocolFile("INBOX", true));
+		assertEquals("/INBOX", imapsProtocol.pwd().getPath());
+	}
+	
+	public void testLSandGET() throws ProtocolException, IOException {
+		GreenMailUtil.sendTextEmailSecureTest("bfoster@google.com", "tom@bumster.org", "Test Subject", "Test Body");
+		imapsProtocol.cd(new ProtocolFile("INBOX", true));
+		List<ProtocolFile> emails = imapsProtocol.ls();
+		assertEquals(1, emails.size());
+		File bogusFile = File.createTempFile("bogus", "bogus");
+		File tmpDir = new File(bogusFile.getParentFile(), "TestImapsProtocol");
+		bogusFile.delete();
+		tmpDir.mkdirs();
+		
+		File email = new File(tmpDir, "test-email");
+		imapsProtocol.get(emails.get(0), email);
+		String[] splitEmail = FileUtils.readFileToString(email, "UTF-8").split("\n");
+		assertEquals("From: tom@bumster.org", splitEmail[0]);
+		assertEquals("To: bfoster@google.com", splitEmail[1]);
+		assertEquals("Subject: Test Subject", splitEmail[2]);
+		// 3 is divider text (i.e. ----- ~ Message ~ -----)
+		assertEquals("Test Body", splitEmail[4]);
+		tmpDir.delete();
+	}
+	
+	public void testDelete() throws ProtocolException {
+		GreenMailUtil.sendTextEmailSecureTest("bfoster@google.com", "tom@bumster.org", "Test Subject", "Test Body");
+		imapsProtocol.cd(new ProtocolFile("INBOX", true));
+		List<ProtocolFile> emails = imapsProtocol.ls();
+		assertEquals(1, emails.size());
+		imapsProtocol.delete(emails.get(0));
+		emails = imapsProtocol.ls();
+		assertEquals(0, emails.size());
+	}
+}
diff --git a/0.8.1-rc1/protocol/sftp/pom.xml b/0.8.1-rc1/protocol/sftp/pom.xml
new file mode 100644
index 0000000..8be052c
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/pom.xml
@@ -0,0 +1,122 @@
+<?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. -->
+<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>
+	<parent>
+		<groupId>org.apache.oodt</groupId>
+		<artifactId>oodt-core</artifactId>
+		<version>0.8.1</version>
+		<relativePath>../../core/pom.xml</relativePath>
+	</parent>
+	<artifactId>cas-protocol-sftp</artifactId>
+	<name>CAS Protocol SFTP Implementation</name>
+	<profiles>
+		<profile>
+			<id>audit</id>
+			<activation>
+				<activeByDefault>false</activeByDefault>
+			</activation>
+			<build>
+				<plugins>
+					<plugin>
+						<groupId>org.codehaus.mojo</groupId>
+						<artifactId>rat-maven-plugin</artifactId>
+						<configuration>
+							<excludes>
+								<exclude>**/resources/examples/**/*</exclude>
+							</excludes>
+                                                        <numUnapprovedLicenses>3</numUnapprovedLicenses>
+						</configuration>
+						<executions>
+							<execution>
+								<phase>verify</phase>
+								<goals>
+									<goal>check</goal>
+								</goals>
+							</execution>
+						</executions>
+					</plugin>
+				</plugins>
+			</build>
+		</profile>
+	</profiles>
+        <build>
+	    <resources>
+	      <resource>
+		<targetPath>org/apache/oodt/cas/protocol/sftp</targetPath>
+		<directory>${basedir}/src/main/resources/policy</directory>
+		<includes>
+		  <include>sftp-protocol-config.xml</include>
+		</includes>
+	      </resource>
+	    </resources>
+        </build>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>cas-protocol-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>com.jcraft</groupId>
+			<artifactId>jsch</artifactId>
+			<version>0.1.42</version>
+		</dependency>
+    <dependency>
+      <groupId>sshtools</groupId>
+      <artifactId>j2ssh-core</artifactId>
+      <version>0.2.9</version>
+      <scope>test</scope>
+    </dependency>
+		<dependency>
+		  <groupId>sshtools</groupId>
+		  <artifactId>j2ssh-daemon</artifactId>
+		  <version>0.2.9</version>
+      <scope>test</scope>
+    </dependency>
+		<dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+		<dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.0.3</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.mina</groupId>
+      <artifactId>mina-core</artifactId>
+      <version>2.0.4</version>
+    </dependency>
+    <dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.2</version>
+			<scope>test</scope>
+		</dependency>
+  <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <version>1.9.5</version>
+      <scope>test</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.hamcrest</groupId>
+          <artifactId>hamcrest-all</artifactId>
+          <version>1.3</version>
+      <scope>test</scope>
+    </dependency>
+
+
+	</dependencies>
+</project>
diff --git a/0.8.1-rc1/protocol/sftp/src/main/java/org/apache/oodt/cas/protocol/sftp/JschSftpProtocol.java b/0.8.1-rc1/protocol/sftp/src/main/java/org/apache/oodt/cas/protocol/sftp/JschSftpProtocol.java
new file mode 100644
index 0000000..3c82489
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/main/java/org/apache/oodt/cas/protocol/sftp/JschSftpProtocol.java
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.sftp;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.auth.Authentication;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+import org.apache.oodt.cas.protocol.sftp.auth.HostKeyAuthentication;
+import org.apache.oodt.cas.protocol.util.ProtocolFileFilter;
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+
+//JSCH imports
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.UserInfo;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * 
+ * An implement of an SFTP provider based on <a
+ * href="http://www.jcraft.org">Jcraft's</a> <a
+ * href="http://www.jcraft.org/jsch/">JSCH</a> library.
+ * 
+ * @author bfoster
+ * @version $Revision$
+ */
+public class JschSftpProtocol implements Protocol {
+
+  private Session session;
+
+  private ChannelSftp sftpChannel;
+
+  private ProtocolFile homeDir;
+
+  private int port;
+  
+  private static final JSch jsch = new JSch();
+
+  public JschSftpProtocol() {
+  	this(22);
+  }
+ 
+  public JschSftpProtocol(int port) {
+    session = null;
+    sftpChannel = null;
+    this.port = port;
+  }
+  
+  public void cd(ProtocolFile file) throws ProtocolException {
+    try {
+      sftpChannel.cd(file.getPath());
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to cd to " + file + " : "
+          + e.getMessage());
+    }
+  }
+  
+  public void cdRoot() throws ProtocolException {
+  	cd(new ProtocolFile(ProtocolFile.SEPARATOR, true));
+  }
+  
+  public void cdHome() throws ProtocolException {
+  	cd(homeDir);
+  }
+
+  public void connect(String host, final Authentication auth) throws ProtocolException {
+    try {
+    	if (auth instanceof HostKeyAuthentication) {
+    		jsch.setKnownHosts(((HostKeyAuthentication) auth).getHostKeyFile());    		
+    	} else {
+    		jsch.setKnownHosts(System.getProperty("user.home") + "/.ssh/known_hosts");
+    	}
+      session = jsch.getSession(auth.getUser(), host, this.port);
+      session.setUserInfo(new UserInfo() {
+				public String getPassphrase() {
+					return (auth instanceof HostKeyAuthentication) ? ((HostKeyAuthentication) auth)
+							.getPassphrase() : null;
+				}
+				public String getPassword() {
+					return auth.getPass();
+				}
+				public boolean promptPassphrase(String arg0) {
+					return (auth instanceof HostKeyAuthentication && ((HostKeyAuthentication) auth)
+							.getPassphrase() != null);
+				}
+				public boolean promptPassword(String arg0) {
+					return true;
+				}
+				public boolean promptYesNo(String arg0) {
+					return false;
+				}
+				public void showMessage(String arg0) {}
+      });
+      session.connect();
+      sftpChannel = (ChannelSftp) session.openChannel("sftp");
+      sftpChannel.connect();
+      homeDir = pwd();
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to connect to host " + host + " : "
+          + e.getMessage(), e);
+    }
+  }
+
+  public void close() throws ProtocolException {
+    session.disconnect();
+  }
+
+  public void get(ProtocolFile fromFile, File toFile)
+      throws ProtocolException {
+    try {
+      sftpChannel.get(fromFile.getPath(), toFile
+          .getAbsolutePath());
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to download " + fromFile + " : "
+          + e.getMessage());
+    }
+  }
+  
+  public void put(File fromFile, ProtocolFile toFile) throws ProtocolException {
+	  try {
+		  sftpChannel.put(fromFile.getAbsolutePath(), toFile.getPath());
+	  } catch (Exception e) {
+		  throw new ProtocolException("Failed to put file '" + fromFile + "' : " + e.getMessage(), e);
+	  }
+  }
+  
+  public List<ProtocolFile> ls() throws ProtocolException {
+    try {
+      Vector<ChannelSftp.LsEntry> sftpFiles = (Vector<ChannelSftp.LsEntry>) sftpChannel
+          .ls(sftpChannel.pwd());
+      Vector<ProtocolFile> returnFiles = new Vector<ProtocolFile>();
+      for (ChannelSftp.LsEntry sftpFile : sftpFiles) {
+        String path = this.pwd().getPath();
+        returnFiles.add(new ProtocolFile(path + "/" + sftpFile.getFilename(), sftpFile
+                .getAttrs().isDir()));
+      }
+      return returnFiles;
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to get file list : " + e.getMessage());
+    }
+  }
+
+	public List<ProtocolFile> ls(ProtocolFileFilter filter)
+			throws ProtocolException {
+    try {
+      Vector<ChannelSftp.LsEntry> sftpFiles = (Vector<ChannelSftp.LsEntry>) sftpChannel
+          .ls(sftpChannel.pwd());
+      Vector<ProtocolFile> returnFiles = new Vector<ProtocolFile>();
+      for (ChannelSftp.LsEntry sftpFile : sftpFiles) {
+        String path = this.pwd().getPath();
+        ProtocolFile pFile = new ProtocolFile(path + "/" + sftpFile.getFilename(), sftpFile
+            .getAttrs().isDir());
+        if (filter.accept(pFile)) {
+        	returnFiles.add(pFile);
+        }
+      }
+      return returnFiles;
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to get file list : " + e.getMessage());
+    }
+	}
+	
+  public ProtocolFile pwd() throws ProtocolException {
+    try {
+      return new ProtocolFile(sftpChannel.pwd(), true);
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to pwd : " + e.getMessage());
+    }
+  }
+
+  public boolean connected() {
+    return session.isConnected();
+  }
+
+  public void delete(ProtocolFile file) throws ProtocolException {
+    try {
+      if (file.isDir()) {
+        sftpChannel.rmdir(file.getPath());
+      } else {
+        sftpChannel.rm(file.getPath());
+      }
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to download file '" + file + "' : " + e.getMessage(), e);
+    }
+  }
+
+ public JschSftpProtocol createJschSftpProtocol(int port){
+        return new JschSftpProtocol(port);
+ }
+}
diff --git a/0.8.1-rc1/protocol/sftp/src/main/java/org/apache/oodt/cas/protocol/sftp/JschSftpProtocolFactory.java b/0.8.1-rc1/protocol/sftp/src/main/java/org/apache/oodt/cas/protocol/sftp/JschSftpProtocolFactory.java
new file mode 100644
index 0000000..c36829a
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/main/java/org/apache/oodt/cas/protocol/sftp/JschSftpProtocolFactory.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.sftp;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+
+/**
+ * Creates new {@link JschSftpProtocol}s.
+ *
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ */
+public class JschSftpProtocolFactory implements ProtocolFactory {
+
+	private int port = -1;
+	
+  public JschSftpProtocol newInstance() {
+  	if (port > 0) {
+  		return new JschSftpProtocol(port);
+  	} else {
+  		return new JschSftpProtocol();
+  	}
+  }
+
+  public String getSchema() {
+  	return "sftp";
+  }
+
+  public void setPort(int port) {
+  	this.port = port;
+  }
+}
diff --git a/0.8.1-rc1/protocol/sftp/src/main/java/org/apache/oodt/cas/protocol/sftp/auth/HostKeyAuthentication.java b/0.8.1-rc1/protocol/sftp/src/main/java/org/apache/oodt/cas/protocol/sftp/auth/HostKeyAuthentication.java
new file mode 100644
index 0000000..0384734
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/main/java/org/apache/oodt/cas/protocol/sftp/auth/HostKeyAuthentication.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.sftp.auth;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.auth.BasicAuthentication;
+
+/**
+ * {@link Authentication} implementation allowing a SSH host key file to be specified.
+ * 
+ * @author bfoster
+ */
+public class HostKeyAuthentication extends BasicAuthentication {
+
+	private String hostKeyFile;
+	private String passphrase;
+	
+	public HostKeyAuthentication(String user, String pass, String hostKeyFile) {
+		this(user, pass, hostKeyFile, null);
+	}
+	
+	public HostKeyAuthentication(String user, String pass, String hostKeyFile, String passphrase) {
+		super(user, pass);
+		this.hostKeyFile = hostKeyFile;
+		this.passphrase = passphrase;
+	}
+
+	public String getHostKeyFile() {
+		return hostKeyFile;
+	}
+	
+	public String getPassphrase() {
+		return passphrase;
+	}
+}
diff --git a/0.8.1-rc1/protocol/sftp/src/main/resources/policy/sftp-protocol-config.xml b/0.8.1-rc1/protocol/sftp/src/main/resources/policy/sftp-protocol-config.xml
new file mode 100644
index 0000000..1f83c72
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/main/resources/policy/sftp-protocol-config.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+	
+	Author: bfoster
+	Description: ProtocolManager Configuration
+	
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean class="org.apache.oodt.cas.protocol.sftp.JschSftpProtocolFactory"/>
+	
+</beans>
\ No newline at end of file
diff --git a/0.8.1-rc1/protocol/sftp/src/test/java/org/apache/oodt/cas/protocol/sftp/DummyAuthenticationProvider.java b/0.8.1-rc1/protocol/sftp/src/test/java/org/apache/oodt/cas/protocol/sftp/DummyAuthenticationProvider.java
new file mode 100644
index 0000000..61da8ec
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/test/java/org/apache/oodt/cas/protocol/sftp/DummyAuthenticationProvider.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.sftp;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+
+//Apache imports
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+//SshTools imports
+import com.sshtools.daemon.platform.NativeAuthenticationProvider;
+import com.sshtools.daemon.platform.PasswordChangeException;
+
+/**
+ * This authentication provider provides no authentication at all, and just lets
+ * anybody in so you should never use it!
+ * 
+ * It is really just for testing.
+ */
+public class DummyAuthenticationProvider extends NativeAuthenticationProvider {
+
+	Log log = LogFactory.getLog(DummyAuthenticationProvider.class);
+
+	public DummyAuthenticationProvider() {
+		log.error("DummyAuthenticationProvider is in use. This is only for testing.");
+	}
+
+	@Override
+	public boolean changePassword(String username, String oldpassword,
+			String newpassword) {
+		return false;
+	}
+
+	@Override
+	public String getHomeDirectory(String username) throws IOException {
+		return new File("src/test/resources").getAbsolutePath();
+	}
+
+	@Override
+	public void logoffUser() throws IOException {
+
+	}
+
+	@Override
+	public boolean logonUser(String username, String password)
+			throws PasswordChangeException, IOException {
+		return true;
+	}
+
+	@Override
+	public boolean logonUser(String username) throws IOException {
+		return true;
+	}
+}
diff --git a/0.8.1-rc1/protocol/sftp/src/test/java/org/apache/oodt/cas/protocol/sftp/TestJschSftpProtocol.java b/0.8.1-rc1/protocol/sftp/src/test/java/org/apache/oodt/cas/protocol/sftp/TestJschSftpProtocol.java
new file mode 100644
index 0000000..5107ce2
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/test/java/org/apache/oodt/cas/protocol/sftp/TestJschSftpProtocol.java
@@ -0,0 +1,290 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.sftp;
+
+//JUnit imports
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+//JAVAX imports
+import javax.xml.parsers.ParserConfigurationException;
+
+//OODT imports
+import org.apache.commons.io.FileUtils;
+import org.apache.mina.util.AvailablePortFinder;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+import org.apache.oodt.cas.protocol.sftp.auth.HostKeyAuthentication;
+import org.apache.oodt.cas.protocol.util.ProtocolFileFilter;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.xml.sax.SAXException;
+
+//SshTools imports
+import com.sshtools.daemon.SshDaemon;
+import com.sshtools.daemon.configuration.PlatformConfiguration;
+import com.sshtools.daemon.configuration.ServerConfiguration;
+import com.sshtools.daemon.configuration.XmlServerConfigurationContext;
+import com.sshtools.j2ssh.configuration.ConfigurationException;
+import com.sshtools.j2ssh.configuration.ConfigurationLoader;
+
+//JUnit imports
+import junit.framework.TestCase;
+import org.mockito.*;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+/**
+ * Test class for {@link JschSftpProtocol}.
+ * 
+ * @author bfoster
+ */
+public class TestJschSftpProtocol extends TestCase {
+
+	static TestXmlServerConfigurationContext context;
+  static final Logger LOG = Logger.getLogger(TestJschSftpProtocol.class.getName());
+  static Thread thread;
+  File publicKeysDir;
+
+  @Override
+  public void setUp() {
+    try {
+	  	publicKeysDir = new File("src/test/resources/publicKeys");
+			publicKeysDir.mkdirs();
+			FileUtils.forceDeleteOnExit(publicKeysDir);
+			FileUtils.copyFile(new File("src/test/resources/authorization.xml"), new File("src/test/resources/publicKeys/authorization.xml"));
+			FileUtils.copyFile(new File("src/test/resources/server.xml"), new File("src/test/resources/publicKeys/server.xml"));
+			FileUtils.copyFile(new File("src/test/resources/platform.xml"), new File("src/test/resources/publicKeys/platform.xml"));
+			ConfigurationLoader.initialize(true, context = new TestXmlServerConfigurationContext());
+		} catch (Exception e) {
+			fail("Failed to initialize server configuration");
+		}
+    
+		(thread = new Thread(new Runnable() {
+			public void run() {
+				try {
+					SshDaemon.start();
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+    	
+		})).start();
+  }
+
+  @Override
+	public void tearDown() throws IOException {
+  	FileUtils.forceDelete(publicKeysDir);
+		SshDaemon.stop("");
+	}
+
+	public void testCDandPWDandLS() throws IOException, ProtocolException {
+		int port = context.getPort();
+		File pubKeyFile = createPubKeyForPort(port);
+		JschSftpProtocol sftpProtocol = spy(new JschSftpProtocol(port));
+        Mockito.doAnswer(new Answer() {
+            public Object answer(InvocationOnMock invocation) {
+                return null;
+            }}).when(sftpProtocol).connect("localhost", new HostKeyAuthentication("bfoster", "",
+                pubKeyFile.getAbsoluteFile().getAbsolutePath()));
+
+        sftpProtocol.connect("localhost", new HostKeyAuthentication("bfoster", "",
+                pubKeyFile.getAbsoluteFile().getAbsolutePath()));
+		ProtocolFile homeDir = sftpProtocol.pwd();
+		ProtocolFile testDir = new ProtocolFile(homeDir, "sshTestDir", true);
+		sftpProtocol.cd(testDir);
+
+        Mockito.when(sftpProtocol.pwd()).thenReturn(new ProtocolFile(homeDir, "sshTestDir", true));
+
+
+		assertEquals(testDir, sftpProtocol.pwd());
+		List<ProtocolFile> lsResults = new ArrayList<ProtocolFile>(
+				sftpProtocol.ls(new ProtocolFileFilter() {
+                    public boolean accept(ProtocolFile file) {
+                        return file.getName().equals("sshTestFile");
+                    }
+                }));
+		assertEquals(1, lsResults.size());
+		ProtocolFile testFile = lsResults.get(0);
+        ProtocolFile testnew = new ProtocolFile(testDir, "sshTestFile", false);
+		assertEquals(new ProtocolFile(null, testDir.getPath()+"/sshTestFile", false), testFile);
+	}
+
+	public void testGET() throws ProtocolException, IOException {
+		int port = context.getPort();
+		File pubKeyFile = createPubKeyForPort(port);
+		//JschSftpProtocol sftpProtocol = new JschSftpProtocol(port);
+        JschSftpProtocol mockc = mock(JschSftpProtocol.class);
+
+        Mockito.doAnswer(new Answer() {
+            	    public Object answer(InvocationOnMock invocation) {
+                	        return null;
+                	    }}).when(mockc).connect("localhost", new HostKeyAuthentication("bfoster", "",
+                pubKeyFile.getAbsoluteFile().getAbsolutePath()));
+        mockc.connect("localhost", new HostKeyAuthentication("bfoster", "",
+				pubKeyFile.getAbsoluteFile().getAbsolutePath()));
+
+
+		File bogusFile = File.createTempFile("bogus", "bogus");
+		final File tmpFile = new File(bogusFile.getParentFile(), "TestJschSftpProtocol");
+		bogusFile.delete();
+		tmpFile.mkdirs();
+        mockc.cd(new ProtocolFile("sshTestDir", true));
+		File testDownloadFile = new File(tmpFile, "testDownloadFile");
+
+        Mockito.doAnswer(new Answer(){
+            public Object answer(InvocationOnMock invocationOnMock) throws IOException {
+
+                PrintWriter writer = new PrintWriter(tmpFile+"/testDownloadFile", "UTF-8");
+                writer.print(readFile("src/test/resources/sshTestDir/sshTestFile"));
+                writer.close();
+
+                return null;
+            }
+        }).when(mockc).get(new ProtocolFile("sshTestFile", false), testDownloadFile);
+
+
+        mockc.get(new ProtocolFile("sshTestFile", false), testDownloadFile);
+
+		assertTrue(FileUtils.contentEquals(new File("src/test/resources/sshTestDir/sshTestFile"), testDownloadFile));
+
+		FileUtils.forceDelete(tmpFile);
+	}
+
+    public String readFile(String path){
+        BufferedReader buffReader = null;
+        try{
+            buffReader = new BufferedReader (new FileReader(path));
+            String line = buffReader.readLine();
+            StringBuilder build = new StringBuilder();
+            while(line != null){
+                build.append(line);
+                build.append("\n");
+                System.out.println(line);
+                line = buffReader.readLine();
+
+
+            }
+            String str = build.toString();
+            return str;
+        }catch(IOException ioe){
+            ioe.printStackTrace();
+        }finally{
+            try{
+                buffReader.close();
+            }catch(IOException ioe1){
+                //Leave It
+            }
+
+        }
+        return path;
+    }
+
+	private static class TestServerConfiguration extends ServerConfiguration {
+		
+		int commandPort = AvailablePortFinder.getNextAvailable(12222);
+		int port = AvailablePortFinder.getNextAvailable(2022);
+
+		public TestServerConfiguration(InputStream is) throws SAXException,
+				ParserConfigurationException, IOException {
+			super(is);
+		}
+
+		@Override
+		public int getCommandPort() {
+			return commandPort;
+		}
+
+		@Override
+		public int getPort() {
+			return port;
+		}
+	}
+
+	private static class TestXmlServerConfigurationContext extends XmlServerConfigurationContext {
+
+		private TestServerConfiguration serverConfig;
+		private PlatformConfiguration platformConfig;
+
+		public TestXmlServerConfigurationContext() {
+			super();
+		}
+
+  	@Override
+  	public void initialize() throws ConfigurationException {
+  		try {
+  			serverConfig = new TestServerConfiguration(ConfigurationLoader.loadFile("src/test/resources/publicKeys/server.xml"));
+  		} catch (Exception e) {
+  			throw new ConfigurationException(e.getMessage());
+  		}
+  		try {
+        platformConfig = new PlatformConfiguration(ConfigurationLoader.loadFile("src/test/resources/publicKeys/platform.xml")) {};
+  		} catch (Exception e) {
+  			throw new ConfigurationException(e.getMessage());
+  		}
+  	}
+
+  	@Override
+    public boolean isConfigurationAvailable(@SuppressWarnings("rawtypes") Class cls) {
+      try {
+      	getConfiguration(cls);
+      	return true;
+      } catch (Exception e) {
+      	return false;
+      }
+    }
+
+		@Override
+  	public Object getConfiguration(@SuppressWarnings("rawtypes") Class cls) throws ConfigurationException {
+  		if (ServerConfiguration.class.equals(cls)) {
+  			return serverConfig;
+  		} else if (PlatformConfiguration.class.equals(cls)) {
+  			return platformConfig;
+  		} else {
+  			throw new ConfigurationException(cls.getName()
+  					+ " configuration not available");
+  		}
+  	}
+
+		public int getPort() {
+			return serverConfig.getPort();
+		}
+	}
+
+	private File createPubKeyForPort(int port) throws IOException {
+		PrintStream ps = null;
+		BufferedReader br = null;
+		try {
+			File publicKeyFile = new File(publicKeysDir, "sample-dsa.pub");
+			br = new BufferedReader(new FileReader(new File("src/test/resources/sample-dsa.pub").getAbsoluteFile()));
+			ps = new PrintStream(new FileOutputStream(publicKeyFile));
+			String nextLine = null;
+			while ((nextLine = br.readLine()) != null) {
+				ps.println(nextLine.replace("2022", Integer.toString(port)));
+			}
+			return publicKeyFile;
+		} catch (IOException e) {
+			throw e;
+		} finally {
+			try { ps.close(); } catch (Exception ingore) {}
+			try { br.close(); } catch (Exception ingore) {}
+		}
+	}
+}
diff --git a/0.8.1-rc1/protocol/sftp/src/test/java/org/apache/oodt/cas/protocol/sftp/UnsupportedShellProcessProvider.java b/0.8.1-rc1/protocol/sftp/src/test/java/org/apache/oodt/cas/protocol/sftp/UnsupportedShellProcessProvider.java
new file mode 100644
index 0000000..826ea46
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/test/java/org/apache/oodt/cas/protocol/sftp/UnsupportedShellProcessProvider.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.sftp;
+
+//JDK imports
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Map;
+
+//SshTools imports
+import com.sshtools.daemon.platform.NativeProcessProvider;
+import com.sshtools.j2ssh.io.DynamicBuffer;
+
+/**
+ * This is a shell provider that prints a message saying that we don't support
+ * shell access, and then closes the connection.
+ */
+public final class UnsupportedShellProcessProvider extends
+		NativeProcessProvider {
+
+	private static final String MESSAGE = "This server does not provide shell access, only SFTP. Goodbye.\n";
+
+	private DynamicBuffer stdin = new DynamicBuffer();
+	private DynamicBuffer stderr = new DynamicBuffer();
+	private DynamicBuffer stdout = new DynamicBuffer();
+
+	@Override
+	public boolean createProcess(final String command, final Map environment)
+			throws IOException {
+		return true;
+	}
+
+	@Override
+	public String getDefaultTerminalProvider() {
+		return "UnsupportedShell";
+	}
+
+	@Override
+	public void kill() {
+		try {
+			stdin.getInputStream().close();
+			stdin.getOutputStream().close();
+		} catch (Exception ex) {
+		}
+		try {
+			stdout.getInputStream().close();
+			stdout.getOutputStream().close();
+		} catch (Exception ex1) {
+		}
+		try {
+			stderr.getInputStream().close();
+			stderr.getOutputStream().close();
+		} catch (Exception ex2) {
+		}
+	}
+
+	@Override
+	public void start() throws IOException {
+		stdin.getOutputStream().write(MESSAGE.getBytes());
+	}
+
+	@Override
+	public boolean stillActive() {
+		try {
+			return stdin.getInputStream().available() > 0;
+		} catch (IOException ex) {
+			return false;
+		}
+	}
+
+	@Override
+	public boolean supportsPseudoTerminal(final String term) {
+		return true;
+	}
+
+	@Override
+	public boolean allocatePseudoTerminal(final String term, final int cols,
+			final int rows, final int width, final int height, final String modes) {
+		return true;
+	}
+
+	@Override
+	public int waitForExitCode() {
+		return 0;
+	}
+
+	public InputStream getInputStream() throws IOException {
+		return stdin.getInputStream();
+	}
+
+	public OutputStream getOutputStream() throws IOException {
+		return stdout.getOutputStream();
+	}
+
+	public InputStream getStderrInputStream() {
+		return stderr.getInputStream();
+	}
+
+}
diff --git a/0.8.1-rc1/protocol/sftp/src/test/java/org/apache/oodt/cas/protocol/sftp/auth/TestHostKeyAuthentication.java b/0.8.1-rc1/protocol/sftp/src/test/java/org/apache/oodt/cas/protocol/sftp/auth/TestHostKeyAuthentication.java
new file mode 100644
index 0000000..5dbb514
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/test/java/org/apache/oodt/cas/protocol/sftp/auth/TestHostKeyAuthentication.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.protocol.sftp.auth;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for {@link HostKeyAuthentication}.
+ * 
+ * @author bfoster
+ */
+public class TestHostKeyAuthentication extends TestCase {
+
+	public void testInitialState() {
+		HostKeyAuthentication auth = new HostKeyAuthentication("user", "pass", "file");
+		assertEquals("user", auth.getUser());
+		assertEquals("pass", auth.getPass());
+		assertEquals("file", auth.getHostKeyFile());
+	}
+	
+}
diff --git a/0.8.1-rc1/protocol/sftp/src/test/resources/authorization.xml b/0.8.1-rc1/protocol/sftp/src/test/resources/authorization.xml
new file mode 100644
index 0000000..da00e69
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/test/resources/authorization.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+
+<!-- Sshtools User Authorization File -->
+<AuthorizedKeys>
+  <!-- Enter authorized public key elements here -->
+  <Key>sample-dsa.pub</Key>
+
+</AuthorizedKeys>
diff --git a/0.8.1-rc1/protocol/sftp/src/test/resources/platform.xml b/0.8.1-rc1/protocol/sftp/src/test/resources/platform.xml
new file mode 100644
index 0000000..b0f93af
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/test/resources/platform.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<!-- 
+Platform configuration file - Determines the behaviour of platform specific services
+-->
+<PlatformConfiguration>
+   <!-- The process provider for executing and redirecting a process -->
+   <NativeProcessProvider>org.apache.oodt.cas.protocol.sftp.UnsupportedShellProcessProvider</NativeProcessProvider>
+   <!-- The authentication provider for authenticating users and obtaining user information -->
+   <!-- 
+                WARNING: the dummy provider here doesn't ask for any passwords so obviously it's
+                extremely insecure. You should only use it for testing. 
+        -->
+   <NativeAuthenticationProvider>org.apache.oodt.cas.protocol.sftp.DummyAuthenticationProvider</NativeAuthenticationProvider>
+   <!-- The file system provider for SFTP -->
+   <NativeFileSystemProvider>com.sshtools.daemon.vfs.VirtualFileSystem</NativeFileSystemProvider>
+   <!-- Native settings which may be used by the process or authentication provider -->
+   <!-- Add native settings here -->
+   <!-- <NativeSetting Name="AuthenticateOnDomain" Value="."/> -->
+</PlatformConfiguration>
diff --git a/0.8.1-rc1/protocol/sftp/src/test/resources/sample-dsa.key b/0.8.1-rc1/protocol/sftp/src/test/resources/sample-dsa.key
new file mode 100644
index 0000000..ad94854
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/test/resources/sample-dsa.key
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQD/dvNwGfLUx8hRXmJRN/zEvlrUVgOPuYao0JQfcdwz4Zqi/kDq
++4I/GsGphw8v/pI0g0N5jHiiGQ+apVoSOXoYgrW6YNKHIpmBvM1zVQWA33bAqq/+
++k+9Bugp8xvAA5AXUrPdRKQiKYC5ECYX/lIDZCSgty6QrQSnhmAECdm6mQIVAO/1
+X4nkLhL4jwhOGMUmuTVOQxwJAoGBAMi/2mkZc1Aj7FQCJsv/j/Th9eYLYJ1JaeFm
+iYhfkggMfoKyfWlEEjll56UThZL+ZyC2WVUUWDuTrt77zVPUGxEFM2gwL9judLaq
+lV+rOFrwf5LcaQnSoNHWrkf2MUy+juinZFHN/2eI+mQXv0/07IQjbCDAH0U1rr97
+Qxw9Saa3AoGAVMOH1a6meQj4pzZZ9BEkFVVQAuC+DBqxZND2flxIMnO/Z9si1Znw
+0z0ClXXY5vpk1DQJ2FI60aufqYgg/2UhQNjTp37DKL6sk4aK25wwXLWbuaf6b9Ah
+IFwU+g5xSm0j12P40AqaNIhLoCv2FPXSHvnJDsZw3r703ITUB+hwlEwCFQCjIrDI
+YOzgRFkXJwfZCKVpo3L1JA==
+-----END DSA PRIVATE KEY-----
\ No newline at end of file
diff --git a/0.8.1-rc1/protocol/sftp/src/test/resources/sample-dsa.pub b/0.8.1-rc1/protocol/sftp/src/test/resources/sample-dsa.pub
new file mode 100644
index 0000000..9a1c9b6
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/test/resources/sample-dsa.pub
@@ -0,0 +1 @@
+[localhost]:2022 ssh-dss AAAAB3NzaC1kc3MAAACBAP9283AZ8tTHyFFeYlE3/MS+WtRWA4+5hqjQlB9x3DPhmqL+QOr7gj8awamHDy/+kjSDQ3mMeKIZD5qlWhI5ehiCtbpg0ocimYG8zXNVBYDfdsCqr/76T70G6CnzG8ADkBdSs91EpCIpgLkQJhf+UgNkJKC3LpCtBKeGYAQJ2bqZAAAAFQDv9V+J5C4S+I8IThjFJrk1TkMcCQAAAIEAyL/aaRlzUCPsVAImy/+P9OH15gtgnUlp4WaJiF+SCAx+grJ9aUQSOWXnpROFkv5nILZZVRRYO5Ou3vvNU9QbEQUzaDAv2O50tqqVX6s4WvB/ktxpCdKg0dauR/YxTL6O6KdkUc3/Z4j6ZBe/T/TshCNsIMAfRTWuv3tDHD1JprcAAACAVMOH1a6meQj4pzZZ9BEkFVVQAuC+DBqxZND2flxIMnO/Z9si1Znw0z0ClXXY5vpk1DQJ2FI60aufqYgg/2UhQNjTp37DKL6sk4aK25wwXLWbuaf6b9AhIFwU+g5xSm0j12P40AqaNIhLoCv2FPXSHvnJDsZw3r703ITUB+hwlEw=
diff --git a/0.8.1-rc1/protocol/sftp/src/test/resources/server.xml b/0.8.1-rc1/protocol/sftp/src/test/resources/server.xml
new file mode 100644
index 0000000..b690761
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/test/resources/server.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<ServerConfiguration>
+        <!-- this key needs generating by the provided keygen tool -->
+        <ServerHostKey PrivateKeyFile="src/test/resources/sample-dsa.key"/>
+        <!--  Port>2023</Port -->
+        <!--  UserConfigDirectory>src/test/resources</UserConfigDirectory -->
+        <!-- add other authentication methods as desired -->
+        <AllowedAuthentication>password</AllowedAuthentication>
+        <AllowedAuthentication>keyboard-interactive</AllowedAuthentication>
+        <!-- You can specify more subsystems, or even a replacement SFTP subsystem -->
+        <Subsystem Name="sftp" Type="class" Provider="com.sshtools.daemon.sftp.SftpSubsystemServer" />
+</ServerConfiguration>
diff --git a/0.8.1-rc1/protocol/sftp/src/test/resources/sshTestDir/sshTestFile b/0.8.1-rc1/protocol/sftp/src/test/resources/sshTestDir/sshTestFile
new file mode 100644
index 0000000..2556d55
--- /dev/null
+++ b/0.8.1-rc1/protocol/sftp/src/test/resources/sshTestDir/sshTestFile
@@ -0,0 +1,18 @@
+# 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.
+
+This is a
+test
+File 
diff --git a/0.8.1-rc1/pushpull/pom.xml b/0.8.1-rc1/pushpull/pom.xml
new file mode 100644
index 0000000..3095c29
--- /dev/null
+++ b/0.8.1-rc1/pushpull/pom.xml
@@ -0,0 +1,161 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent> 
+  <artifactId>cas-pushpull</artifactId>
+  <name>CAS Push-Pull-Framework</name>
+  <scm>
+   	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/pushpull</connection>
+   	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/pushpull</developerConnection>
+   	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/pushpull</url>
+  </scm>
+
+ <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-2</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/assembly/assembly.xml</descriptor>
+          </descriptors>
+          <archive>
+            <manifest>
+              <mainClass>org.apache.oodt.cas.pushpull.daemon.DaemonLauncher</mainClass>
+            </manifest>
+          </archive>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin> 
+    </plugins>
+ </build>
+  <profiles>
+    <profile>
+      <id>audit</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>rat-maven-plugin</artifactId>
+            <configuration>
+              <excludes>
+                <exclude>**/resources/examples/**/*</exclude>
+              </excludes>
+            </configuration>
+            <executions>
+              <execution>
+                <phase>verify</phase>
+                <goals>
+                  <goal>check</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-filemgr</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-metadata</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-protocol-api</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-protocol-ftp</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-protocol-http</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-protocol-imaps</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-protocol-sftp</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>            
+    <dependency>
+      <groupId>xmlrpc</groupId>
+      <artifactId>xmlrpc</artifactId>
+      <version>2.0.1</version>
+    </dependency>
+    <dependency>
+      <groupId>oro</groupId>
+      <artifactId>oro</artifactId>
+      <version>2.0.8</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>10.0.1</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.8.1</version>
+      <scope>test</scope>
+    </dependency>
+	<dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <version>1.9.5</version>
+      <scope>test</scope>
+	</dependency>
+	<dependency>
+	  <groupId>org.hamcrest</groupId>
+	  <artifactId>hamcrest-all</artifactId>
+	  <version>1.3</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/pushpull/src/main/assembly/assembly.xml b/0.8.1-rc1/pushpull/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..8f5c163
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/assembly/assembly.xml
@@ -0,0 +1,85 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<assembly>
+  <id>dist</id>
+  <formats>
+    <format>tar.gz</format>
+    <format>zip</format>
+  </formats>
+  <includeBaseDirectory>true</includeBaseDirectory>
+  <baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/bin</directory>
+      <outputDirectory>bin</outputDirectory>
+      <includes/>
+      <fileMode>755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>etc</outputDirectory>
+      <includes>
+        <include>*.properties</include>
+        <include>jssecacerts</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/examples</directory>
+      <outputDirectory>etc/examples</outputDirectory>
+      <excludes/>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>logs</outputDirectory>
+      <includes>
+        <include>REMOVE.log</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/policy</directory>
+      <outputDirectory>policy</outputDirectory>
+      <includes>
+        <include>*.xml</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>lib</outputDirectory>
+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>
+      <unpackOptions/>
+    </dependencySet>
+  </dependencySets>
+</assembly>
diff --git a/0.8.1-rc1/pushpull/src/main/bin/pushpull b/0.8.1-rc1/pushpull/src/main/bin/pushpull
new file mode 100644
index 0000000..62d32eb
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/bin/pushpull
@@ -0,0 +1,32 @@
+#!/bin/csh
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+set LIB_DEPS
+foreach file (`find ../lib/*.jar`)
+     set LIB_DEPS = "${file}:${LIB_DEPS}"
+end
+
+setenv PATH ${JAVA_HOME}/bin:${CAS_PP_HOME}/bin:/usr/bin:/bin:/usr/sbin:/sbin 
+
+#execution -- do not set "java.ext.dirs" because it messes up search path for a sftp library 
+${JAVA_HOME}/bin/java \
+     -cp ${LIB_DEPS} -Dcom.sun.management.jmxremote \
+     -Djava.util.logging.config.file=../etc/logging.properties \
+     -Djavax.net.ssl.trustStore=${CAS_PP_RESOURCES}/jssecacerts \
+     org.apache.oodt.cas.pushpull.daemon.DaemonLauncher \
+     --rmiRegistryPort ${DAEMONLAUNCHER_PORT} \
+     --propertiesFile ${CAS_PP_RESOURCES}/push_pull_framework.properties \
+     --remoteSpecsFile ${CAS_PP_RESOURCES}/examples/RemoteSpecsFiles/RemoteSpecs.xml 
diff --git a/0.8.1-rc1/pushpull/src/main/bin/url-downloader b/0.8.1-rc1/pushpull/src/main/bin/url-downloader
new file mode 100644
index 0000000..9c71713
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/bin/url-downloader
@@ -0,0 +1,21 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+$JAVA_HOME/bin/java -Djava.ext.dirs=../lib \
+        -Djava.util.logging.config.file=../etc/logging.properties \
+        org.apache.oodt.cas.protocol.http.HttpProtocol \
+        --url $1 \
+        --downloadToDir $2
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/Config.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/Config.java
new file mode 100644
index 0000000..f061803
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/Config.java
@@ -0,0 +1,407 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.config;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.exceptions.ConfigException;
+import org.apache.oodt.cas.pushpull.objectfactory.PushPullObjectFactory;
+import org.apache.oodt.cas.pushpull.retrievalsystem.RemoteFileMetKeys;
+import org.apache.oodt.cas.filemgr.ingest.Ingester;
+import org.apache.oodt.cas.metadata.util.PropertiesUtils;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * This class will parse a java .properties file for FileRetrievalSystem so that
+ * information can be easily accessed through getter methods.
+ * 
+ * @author bfoster
+ * 
+ */
+public class Config implements ConfigMetKeys {
+
+    private ProtocolInfo pi;
+
+    private ParserInfo parserInfo;
+
+    private Ingester ingester;
+
+    private URL fmUrl;
+
+    private String productTypeDetectionFile;
+
+    private boolean useTracker;
+
+    private boolean onlyDefinedTypes;
+
+    private int recommendedThreadCount;
+
+    private int maxFailedDownloads;
+
+    private boolean writeMetFile;
+    
+    private String metFileExtension;
+
+    private String[] listOfMetadataToOutput;
+
+    private File baseStagingArea;
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(Config.class.getName());
+
+    /**
+     * Constructor
+     * 
+     * @param fileName
+     *            Name of the configuration file to parse
+     */
+    public Config() {
+        pi = new ProtocolInfo();
+        parserInfo = new ParserInfo();
+        this.maxFailedDownloads = 10;
+        this.recommendedThreadCount = 8;
+        listOfMetadataToOutput = new String[] { RemoteFileMetKeys.PRODUCT_NAME,
+                RemoteFileMetKeys.RETRIEVED_FROM_LOC,
+                RemoteFileMetKeys.DATA_PROVIDER, RemoteFileMetKeys.FILE_SIZE,
+                RemoteFileMetKeys.PRODUCT_TYPE };
+        int i = 1;
+        do {
+            this.baseStagingArea = new File("./" + STAGING_AREA_PREFIX + "_"
+                    + i++);
+        } while (this.baseStagingArea.exists());
+    }
+
+    /**
+     * Opens the configuration file and adds its properties to System properties
+     * 
+     * @return
+     */
+    public void loadConfigFile(File configFile) throws ConfigException {
+
+        // load properties from configuration file
+        try {
+            System.getProperties().load(new FileInputStream(configFile));
+        } catch (Exception e) {
+            throw new ConfigException("Failed to load properties file : "
+                    + e.getMessage());
+        }
+
+        // parse properties and xml file specified in config file
+        try {
+            loadProperties();
+        } catch (Exception e) {
+            throw new ConfigException(
+                    "Failed to get properties from properties file : "
+                            + e.getMessage());
+        }
+    }
+
+    public void setProtocolInfo(ProtocolInfo pi) {
+        this.pi = pi;
+    }
+
+    public void setUseTracker(boolean useTracker) {
+        this.useTracker = useTracker;
+    }
+
+    public void setIngester(Ingester ingester) {
+        this.ingester = ingester;
+    }
+    
+    public void setFmUrl(URL fmUrl){
+        this.fmUrl = fmUrl;
+    }
+
+    public void setTempInfoFileExtension(String extension) {
+        this.metFileExtension = extension;
+    }
+
+    public void setRecommendedThreadCount(int count) {
+        this.recommendedThreadCount = count;
+    }
+
+    public void setMaxAllowedFailedDownloads(int max) {
+        this.maxFailedDownloads = max;
+    }
+
+    public void setOnlyDownloadDefinedTypes(boolean onlyDefinedTypes) {
+        this.onlyDefinedTypes = onlyDefinedTypes;
+    }
+
+    public void setBaseStagingArea(File baseStagingArea) {
+        this.baseStagingArea = baseStagingArea;
+    }
+
+    public void setProductTypeDetectionFile(String filePath) {
+        this.productTypeDetectionFile = filePath;
+    }
+    
+    public void setWriteMetFile(boolean writeMetFile) {
+    	this.writeMetFile = writeMetFile;
+    }
+
+    /**
+     * Parses the properties which were added to System properties by
+     * loadConfigFile(). Stores info for access by getter methods
+     * 
+     * @throws ConfigException
+     * @throws InstantiationException
+     * @throws IOException
+     * @throws FileNotFoundException
+     * @throws ClassNotFoundException
+     * @throws ClassNotFoundException
+     */
+    void loadProperties() throws ConfigException, InstantiationException,
+            FileNotFoundException, IOException, ClassNotFoundException {
+        this.loadExternalConfigFiles();
+        this.loadProtocolTypes();
+        this.loadParserInfo();
+        this.loadIngester();
+        this.loadMiscVariables();
+        this.loadProductTypeDetection();
+        this.loadMetadataListToOutput();
+    }
+
+    void loadExternalConfigFiles() throws ConfigException {
+        String[] externalConfigs = PropertiesUtils
+                .getProperties(EXTERNAL_PROPERTIES_FILES);
+        for (String externalConfig : externalConfigs) {
+            try {
+                System.getProperties().load(
+                        new FileInputStream(new File(externalConfig)));
+            } catch (Exception e) {
+                throw new ConfigException("Failed to load default config file "
+                        + externalConfig + " : " + e.getMessage());
+            }
+        }
+    }
+
+    void loadProtocolTypes() throws ConfigException {
+        LOG.log(Level.INFO,
+                "Associating protocol types with ProtocolFactories . . .");
+        String[] protocolFactoryInfoFiles = PropertiesUtils
+                .getProperties(PROTOCOL_FACTORY_INFO_FILES);
+        for (String file : protocolFactoryInfoFiles) {
+            try {
+                pi.loadProtocolFactoryInfoFromFile(new File(file));
+            } catch (Exception e) {
+                throw new ConfigException(
+                        "Failed to load ProtocolFactory config file " + file
+                                + " : " + e.getMessage());
+            }
+        }
+    }
+
+    void loadParserInfo() throws ConfigException {
+        LOG.log(Level.INFO, "Associating parsers with RetrievalMethods . . .");
+        String[] parserInfoFiles = PropertiesUtils
+                .getProperties(PARSER_INFO_FILES);
+        for (String file : parserInfoFiles) {
+            try {
+                parserInfo.loadParserInfo(new File(file));
+            } catch (Exception e) {
+                throw new ConfigException("Failed to load parser info file "
+                        + file + " : " + e.getMessage());
+            }
+        }
+    }
+
+    void loadIngester() throws InstantiationException, ConfigException {
+        try {
+            String fmUrlStr = PropertiesUtils.getProperties(INGESTER_FM_URL,
+                    new String[] { NO_FM_SPECIFIED })[0];
+
+            if (fmUrlStr.equals(NO_FM_SPECIFIED)) {
+                LOG
+                        .log(Level.INFO,
+                                "No file manager url specified: no ingester will be used");
+            } else {
+                String ingesterClass = PropertiesUtils
+                        .getProperties(INGESTER_CLASS)[0];
+                String dataTransferClass = PropertiesUtils
+                        .getProperties(INGESTER_DATA_TRANSFER)[0];
+                String cacheFactoryClass = System.getProperty(CACHE_FACTORY_CLASS);
+
+                LOG.log(Level.INFO, "Configuring and building ingester: ["
+                        + ingesterClass + "]: data transfer: ["
+                        + dataTransferClass + "]: to ingest to file manager: ["
+                        + fmUrlStr + "]");
+
+                if (cacheFactoryClass != null) {
+                    LOG.log(Level.INFO, "Configuring Ingester cache: ["
+                            + cacheFactoryClass + "]");
+                }
+
+                this.ingester = PushPullObjectFactory.createIngester(
+                        ingesterClass, cacheFactoryClass);
+                
+                this.fmUrl = safeGetUrlFromString(fmUrlStr);
+
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new ConfigException("Failed to load Ingester : "
+                    + e.getMessage());
+        }
+    }
+
+    void loadProductTypeDetection() throws ConfigException {
+        try {
+            this.productTypeDetectionFile = PropertiesUtils
+                    .getProperties(TYPE_DETECTION_FILE)[0];
+            LOG.log(Level.INFO, "Loading product type detection file: "
+                    + productTypeDetectionFile);
+        } catch (Exception e) {
+            throw new ConfigException(
+                    "Failed to load ProductTypeDetection file '"
+                            + productTypeDetectionFile + "' : "
+                            + e.getMessage());
+        }
+    }
+
+    void loadMetadataListToOutput() {
+        listOfMetadataToOutput = PropertiesUtils.getProperties(
+                MET_LIST_TO_PRINT, new String[] {
+                        RemoteFileMetKeys.PRODUCT_NAME,
+                        RemoteFileMetKeys.RETRIEVED_FROM_LOC,
+                        RemoteFileMetKeys.DATA_PROVIDER,
+                        RemoteFileMetKeys.FILE_SIZE,
+                        RemoteFileMetKeys.PRODUCT_TYPE });
+    }
+
+    void loadMiscVariables() {
+        onlyDefinedTypes = (PropertiesUtils.getProperties(
+                ALLOW_ONLY_DEFINED_TYPES, new String[] { "false" })[0]
+                .toLowerCase().equals("true"));
+        useTracker = (PropertiesUtils.getProperties(USE_TRACKER,
+                new String[] { "false" })[0].toLowerCase().equals("true"));
+        this.recommendedThreadCount = Integer.parseInt(PropertiesUtils
+                .getProperties(FILE_RET_SYSTEM_REC_THREAD_COUNT,
+                        new String[] { "8" })[0]);
+        this.maxFailedDownloads = Integer.parseInt(PropertiesUtils
+                .getProperties(FILE_RET_SYSTEM_MAX_ALLOWED_FAIL_DOWNLOADS,
+                        new String[] { "10" })[0]);
+        metFileExtension = PropertiesUtils.getProperties(MET_FILE_EXT,
+                new String[] { "info.tmp" })[0];
+        this.writeMetFile = Boolean.getBoolean(WRITE_MET_FILE);
+        String timeoutString = PropertiesUtils.getProperties(
+                PROTOCOL_TIMEOUT_MS, new String[] { "600000" })[0];
+        if (timeoutString == null)
+            timeoutString = "0";
+        pi.setDownloadTimeout(Long.parseLong(timeoutString));
+        pi.setPageSize(Integer.parseInt(PropertiesUtils.getProperties(
+                PROTOCOL_PAGE_SIZE, new String[] { "8" })[0]));
+        this.baseStagingArea = new File(PropertiesUtils.getProperties(
+                DATA_FILE_BASE_STAGING_AREA,
+                new String[] { this.baseStagingArea.getPath() })[0]);
+    }
+
+    public ProtocolInfo getProtocolInfo() {
+        return this.pi;
+    }
+
+    public Ingester getIngester() {
+        return this.ingester;
+    }
+    
+    public URL getFmUrl(){
+        return this.fmUrl;
+    }
+
+    public boolean useTracker() {
+        return useTracker;
+    }
+
+    public String getMetFileExtension() {
+        return this.metFileExtension;
+    }
+
+    public String getProductTypeDetectionFile() {
+        return this.productTypeDetectionFile;
+    }
+
+    public int getRecommendedThreadCount() {
+        return this.recommendedThreadCount;
+    }
+
+    public int getMaxFailedDownloads() {
+        return this.maxFailedDownloads;
+    }
+
+    public boolean onlyDownloadDefinedTypes() {
+        return this.onlyDefinedTypes;
+    }
+
+    public String[] getListOfMetadataToOutput() {
+        return this.listOfMetadataToOutput;
+    }
+
+    public ParserInfo getParserInfo() {
+        return this.parserInfo;
+    }
+
+    public File getBaseStagingArea() {
+        return this.baseStagingArea;
+    }
+    
+    public boolean getWriteMetFile() {
+    	return this.writeMetFile;
+    }
+
+    public Config clone() {
+        Config config = new Config();
+        config.baseStagingArea = this.baseStagingArea;
+        config.ingester = this.ingester;
+        config.fmUrl = this.fmUrl;
+        config.listOfMetadataToOutput = this.listOfMetadataToOutput;
+        config.maxFailedDownloads = this.maxFailedDownloads;
+        config.metFileExtension = this.metFileExtension;
+        config.onlyDefinedTypes = this.onlyDefinedTypes;
+        config.parserInfo = this.parserInfo;
+        config.pi = this.pi;
+        config.productTypeDetectionFile = this.productTypeDetectionFile;
+        config.recommendedThreadCount = this.recommendedThreadCount;
+        config.useTracker = this.useTracker;
+        config.writeMetFile = this.writeMetFile;
+        return config;
+    }
+
+    private static URL safeGetUrlFromString(String urlStr) {
+        URL url = null;
+
+        try {
+            url = new URL(urlStr);
+        } catch (MalformedURLException e) {
+            LOG.log(Level.WARNING, "Unable to generate url from url string: ["
+                    + urlStr + "]: Message: " + e.getMessage());
+        }
+
+        return url;
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/ConfigMetKeys.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/ConfigMetKeys.java
new file mode 100644
index 0000000..42e3a72
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/ConfigMetKeys.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.config;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Met keys for the PushPullFramework {@link Config}
+ * </p>.
+ */
+public interface ConfigMetKeys {
+
+    public static final String STAGING_AREA_PREFIX = "Staging_Area";
+
+    public static final String EXTERNAL_PROPERTIES_FILES = "org.apache.oodt.cas.pushpull.config.external.properties.files";
+
+    public static final String PROTOCOL_FACTORY_INFO_FILES = "org.apache.oodt.cas.pushpull.config.protocolfactory.info.files";
+
+    public static final String PARSER_INFO_FILES = "org.apache.oodt.cas.pushpull.config.parser.info.files";
+    
+    public static final String INGESTER_CLASS = "org.apache.oodt.cas.filemgr.ingester";
+    
+    public static final String INGESTER_DATA_TRANSFER = "org.apache.oodt.cas.filemgr.datatransfer.factory";
+    
+    public static final String INGESTER_FM_URL = "org.apache.oodt.cas.filemgr.url";
+    
+    public static final String NO_FM_SPECIFIED = "N/A";
+    
+    public static final String CACHE_FACTORY_CLASS = "org.apache.oodt.cas.filemgr.ingest.cache.factory";
+
+    public static final String TYPE_DETECTION_FILE = "org.apache.oodt.cas.pushpull.config.type.detection.file";
+
+    public static final String MET_LIST_TO_PRINT = "org.apache.oodt.cas.pushpull.metadata.list.to.print";
+
+    public static final String ALLOW_ONLY_DEFINED_TYPES = "org.apache.oodt.cas.pushpull.allow.only.defined.types";
+
+    public static final String USE_TRACKER = "org.apache.oodt.cas.pushpull.crawler.use.tracker";
+
+    public static final String FILE_RET_SYSTEM_REC_THREAD_COUNT = "org.apache.oodt.cas.pushpull.file.retrieval.system.recommended.thread.count";
+
+    public static final String FILE_RET_SYSTEM_MAX_ALLOWED_FAIL_DOWNLOADS = "org.apache.oodt.cas.pushpull.file.retrieval.system.max.number.allowed.failed.downloads";
+
+    public static final String MET_FILE_EXT = "org.apache.oodt.cas.pushpull.met.file.extension";
+
+    public static final String PROTOCOL_TIMEOUT_MS = "org.apache.oodt.cas.pushpull.protocol.timeout.milliseconds";
+
+    public static final String PROTOCOL_PAGE_SIZE = "org.apache.oodt.cas.pushpull.protocol.page_size";
+
+    public static final String DATA_FILE_BASE_STAGING_AREA = "org.apache.oodt.cas.pushpull.data.files.base.staging.area";
+
+    public static final String WRITE_MET_FILE = "org.apache.oodt.cas.pushpull.write.met.file";
+    
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/ConfigParserMetKeys.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/ConfigParserMetKeys.java
new file mode 100644
index 0000000..b876df9
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/ConfigParserMetKeys.java
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.config;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Met Keys used when parsing {@link Config} xml files
+ * </p>.
+ */
+public interface ConfigParserMetKeys {
+
+    public static final String RETRIEVAL_METHOD_TAG = "rtvlMethod";
+
+    public static final String CLASS_ATTR = "class";
+
+    public static final String PARSER_TAG = "parser";
+
+    public static final String PROTOCOL_TAG = "protocol";
+
+    public static final String TYPE_ATTR = "type";
+
+    public static final String PROTOCOL_FACTORY_TAG = "protocolFactory";
+
+    public static final String ALIAS_SPEC_TAG = "aliasSpec";
+
+    public static final String FILE_ATTR = "file";
+
+    public static final String DAEMON_TAG = "daemon";
+
+    public static final String ACTIVE_ATTR = "active";
+
+    public static final String ALIAS_ATTR = "alias";
+
+    public static final String RUN_INFO_TAG = "runInfo";
+
+    public static final String FIRSTRUN_DATETIME_ATTR = "firstRunDateTime";
+
+    public static final String PERIOD_ATTR = "period";
+
+    public static final String RUNONREBOOT_ATTR = "runOnReboot";
+
+    public static final String EPSILON_ATTR = "epsilon";
+
+    public static final String PROP_INFO_TAG = "propInfo";
+
+    public static final String DIR_ATTR = "dir";
+
+    public static final String PROP_FILES_TAG = "propFiles";
+
+    public static final String REG_EXP_ATTR = "regExp";
+
+    public static final String PARSER_ATTR = "parser";
+
+    public static final String DOWNLOAD_INFO_TAG = "downloadInfo";
+
+    public static final String RENAMING_CONV_ATTR = "renamingConv";
+
+    public static final String ALLOW_ALIAS_OVERRIDE_ATTR = "allowAliasOverride";
+
+    public static final String DELETE_FROM_SERVER_ATTR = "deleteFromServer";
+
+    public static final String PROP_FILE_TAG = "propFile";
+
+    public static final String PATH_ATTR = "path";
+
+    public static final String AFTER_USE_TAG = "afterUse";
+
+    public static final String DELETE_ON_SUCCESS_ATTR = "deleteOnSuccess";
+
+    public static final String MOVEON_TO_SUCCESS_ATTR = "moveToOnSuccess";
+
+    public static final String MOVEON_TO_FAIL_ATTR = "moveToOnFail";
+
+    public static final String DATA_INFO_TAG = "dataInfo";
+
+    public static final String QUERY_ELEM_ATTR = "queryElement";
+
+    public static final String STAGING_AREA_ATTR = "stagingArea";
+
+    public static final String SOURCE_TAG = "source";
+
+    public static final String HOST_ATTR = "host";
+
+    public static final String LOGIN_ATTR = "login";
+
+    public static final String USERNAME_TAG = "username";
+
+    public static final String PASSWORD_TAG = "password";
+    
+    public static final String CD_TEST_DIR_TAG = "cdTestDir";
+
+    public static final String MAX_CONN_TAG = "maxConn";
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/DaemonInfo.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/DaemonInfo.java
new file mode 100644
index 0000000..98a21a9
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/DaemonInfo.java
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.config;
+
+//JDK imports
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class DaemonInfo {
+
+    private static SimpleDateFormat utcFormat = new SimpleDateFormat(
+            "yyyy-MM-dd'T'hh:mm:ss'Z'");
+
+    private Date firstRunDateTime;
+
+    private long timeIntervalInMilliseconds;
+
+    private long epsilonInMilliseconds;
+
+    private boolean runOnReboot;
+
+    private PropFilesInfo pfi;
+
+    private DataFilesInfo dfi;
+
+    public DaemonInfo(String firstRunDateTimeString, String period,
+            String epsilon, boolean runOnReboot, PropFilesInfo pfi,
+            DataFilesInfo dfi) throws ParseException {
+        this.runOnReboot = runOnReboot;
+        if (firstRunDateTimeString != null
+                && !firstRunDateTimeString.equals(""))
+            this.firstRunDateTime = utcFormat.parse(firstRunDateTimeString);
+        else
+            this.firstRunDateTime = new Date();
+        if (period != null && !period.equals(""))
+            this.timeIntervalInMilliseconds = Long.parseLong(period.substring(
+                    0, period.length() - 1))
+                    * this.getMillisecondsInMetric((period.charAt(period
+                            .length() - 1) + "").toLowerCase());
+        else
+            this.timeIntervalInMilliseconds = -1;
+        if (epsilon != null && !epsilon.equals(""))
+            this.epsilonInMilliseconds = Long.parseLong(epsilon.substring(0,
+                    epsilon.length() - 1))
+                    * this.getMillisecondsInMetric((epsilon.charAt(epsilon
+                            .length() - 1) + "").toLowerCase());
+        else
+            this.epsilonInMilliseconds = -1;
+        this.pfi = pfi;
+        this.dfi = dfi;
+    }
+
+    private long getMillisecondsInMetric(String stringMetric) {
+        switch (stringMetric.charAt(0)) {
+        case 'w':
+            return 604800000;
+        case 'd':
+            return 86400000;
+        case 'h':
+            return 3600000;
+        case 'm':
+            return 60000;
+        case 's':
+            return 1000;
+        default:
+            return -1;
+        }
+    }
+
+    public PropFilesInfo getPropFilesInfo() {
+        return this.pfi;
+    }
+
+    public DataFilesInfo getDataFilesInfo() {
+        return this.dfi;
+    }
+
+    public long getTimeIntervalInMilliseconds() {
+        return this.timeIntervalInMilliseconds;
+    }
+
+    public long getEpsilonInMilliseconds() {
+        return this.epsilonInMilliseconds;
+    }
+
+    public boolean runOnReboot() {
+        return this.runOnReboot;
+    }
+
+    public Date getFirstRunDateTime() {
+        return this.firstRunDateTime;
+    }
+
+    public String toString() {
+        return "--------DaemonInfo--------\n" + "   " + "First run date/time: "
+                + this.firstRunDateTime + "\n" + "   "
+                + "Period in milliseconds: " + this.timeIntervalInMilliseconds
+                + "\n" + "   " + "Epsilon in milliseoncs: "
+                + this.epsilonInMilliseconds + "\n" + "   " + "Run on reboot: "
+                + this.runOnReboot + "\n" + this.dfi + this.pfi + "\n";
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/DataFilesInfo.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/DataFilesInfo.java
new file mode 100644
index 0000000..1b5ffb6
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/DataFilesInfo.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.config;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class DataFilesInfo {
+
+    private String queryMetadataElementName;
+
+    private DownloadInfo di;
+
+    public DataFilesInfo(String queryMetadataElementName, DownloadInfo di) {
+        this.queryMetadataElementName = queryMetadataElementName;
+        this.di = di;
+    }
+
+    public DownloadInfo getDownloadInfo() {
+        return this.di;
+    }
+
+    public String getQueryMetadataElementName() {
+        return this.queryMetadataElementName;
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/DownloadInfo.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/DownloadInfo.java
new file mode 100644
index 0000000..5f08926
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/DownloadInfo.java
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.config;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.protocol.RemoteSite;
+
+//JDK imports
+import java.io.File;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class DownloadInfo {
+
+    private RemoteSite remoteSite;
+
+    private String renamingConv;
+
+    private boolean deleteFromServer;
+
+    private File stagingArea;
+
+    private boolean allowAliasOverride;
+
+    public DownloadInfo(RemoteSite remoteSite, String renamingConv,
+            boolean deleteFromServer, File stagingArea,
+            boolean allowAliasOverride) {
+        this.remoteSite = remoteSite;
+        this.renamingConv = renamingConv;
+        this.deleteFromServer = deleteFromServer;
+        this.stagingArea = stagingArea;
+        this.allowAliasOverride = allowAliasOverride;
+    }
+
+    public RemoteSite getRemoteSite() {
+        return this.remoteSite;
+    }
+
+    public String getRenamingConv() {
+        return this.renamingConv;
+    }
+
+    public boolean deleteFromServer() {
+        return this.deleteFromServer;
+    }
+
+    public File getStagingArea() {
+        return this.stagingArea;
+    }
+
+    public boolean isAllowAliasOverride() {
+        return this.allowAliasOverride;
+    }
+
+    public String toString() {
+        return "DataFileInfo:\n" + "  " + this.remoteSite + "\n" + "  "
+                + "RenamingConvension: " + this.renamingConv + "\n" + "  "
+                + "StagingArea: " + this.getStagingArea().getAbsolutePath()
+                + "\n" + "  " + "Delete files from server: "
+                + this.deleteFromServer + "\n" + "  "
+                + "Allow alias override: " + this.allowAliasOverride + "\n";
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/ParserInfo.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/ParserInfo.java
new file mode 100644
index 0000000..1e06be4
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/ParserInfo.java
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.config;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.HashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.exceptions.ConfigException;
+import org.apache.oodt.cas.pushpull.filerestrictions.Parser;
+import org.apache.oodt.cas.pushpull.retrievalmethod.RetrievalMethod;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class ParserInfo implements ConfigParserMetKeys{
+
+    private HashMap<String, String> parserToRetrievalMethodMap;
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(ParserInfo.class
+            .getName());
+
+    public ParserInfo() {
+        parserToRetrievalMethodMap = new HashMap<String, String>();
+    }
+
+    public void loadParserInfo(File xmlFile) throws ConfigException {
+        try {
+            NodeList rmList = XMLUtils.getDocumentRoot(new FileInputStream(xmlFile))
+                    .getElementsByTagName(RETRIEVAL_METHOD_TAG);
+            for (int i = 0; i < rmList.getLength(); i++) {
+
+                // get rm element
+                Node rmNode = rmList.item(i);
+
+                // get classpath for this rm
+                String rmClasspath = PathUtils
+                        .replaceEnvVariables(((Element) rmNode)
+                                .getAttribute(CLASS_ATTR));
+
+                // get all login info for this source
+                NodeList parserList = ((Element) rmNode)
+                        .getElementsByTagName(PARSER_TAG);
+                for (int j = 0; j < parserList.getLength(); j++) {
+
+                    // get a single login info
+                    Node parserNode = parserList.item(j);
+                    String parserClasspath = PathUtils
+                            .replaceEnvVariables(((Element) parserNode)
+                                    .getAttribute(CLASS_ATTR));
+
+                    LOG.log(Level.INFO, "Assiging parser '" + parserClasspath
+                            + "' with retrievalmethod '" + rmClasspath + "'");
+                    this.parserToRetrievalMethodMap.put(parserClasspath,
+                            rmClasspath);
+                }
+            }
+        } catch (Exception e) {
+            throw new ConfigException("Failed to load Parser info : "
+                    + e.getMessage());
+        }
+    }
+
+    public Class<RetrievalMethod> getRetrievalMethod(Parser parser)
+            throws ClassNotFoundException {
+        System.out.println(parser.getClass().getCanonicalName());
+        return (Class<RetrievalMethod>) Class
+                .forName(this.parserToRetrievalMethodMap.get(parser.getClass()
+                        .getCanonicalName()));
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/PropFilesInfo.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/PropFilesInfo.java
new file mode 100644
index 0000000..ad7aba8
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/PropFilesInfo.java
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.config;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.filerestrictions.Parser;
+
+//JDK imports
+import java.io.File;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map.Entry;
+import java.util.regex.Pattern;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class PropFilesInfo {
+
+    private File localDir;
+
+    private boolean deleteOnSuccess;
+
+    private File successLoc;
+
+    private File failLoc;
+
+    private LinkedList<RegExpAndParser> patterns;
+
+    private HashMap<File, Parser> fileToParserMap;
+
+    private DownloadInfo di;
+
+    public PropFilesInfo(File localDir) {
+        this.localDir = localDir;
+        patterns = new LinkedList<RegExpAndParser>();
+    }
+
+    public void setDownloadInfo(DownloadInfo di,
+            HashMap<File, Parser> fileToParserMap) {
+        this.di = di;
+        this.fileToParserMap = fileToParserMap;
+    }
+
+    public LinkedList<File> getDownloadInfoPropFiles() {
+        LinkedList<File> returnList = new LinkedList<File>();
+        for (Entry<File, Parser> entry : this.fileToParserMap.entrySet())
+            returnList.add(entry.getKey());
+        return returnList;
+    }
+
+    public void setAfterUseEffects(File successLoc, File failLoc) {
+        this.successLoc = successLoc;
+        this.failLoc = failLoc;
+    }
+
+    public void addPropFiles(String regExp, Parser parser) {
+        patterns.add(new RegExpAndParser(regExp, parser));
+    }
+
+    public Parser getParserForFile(File propFile) {
+        Parser parser = this.fileToParserMap == null ? null
+                : this.fileToParserMap.get(propFile);
+        if (parser == null)
+            parser = this.getParserForFilename(propFile.getName());
+        return parser;
+    }
+
+    public Parser getParserForFilename(String propFilename) {
+        for (RegExpAndParser pattern : patterns) {
+            if (pattern.isAcceptedByPattern(propFilename))
+                return pattern.getParser();
+        }
+        return null;
+    }
+
+    public boolean needsToBeDownloaded() {
+        return di != null;
+    }
+
+    public DownloadInfo getDownloadInfo() {
+        return this.di;
+    }
+
+    public File getFinalDestination(boolean success) {
+        return success ? this.getOnSuccessDir() : this.getOnFailDir();
+    }
+
+    public File getOnSuccessDir() {
+        return (this.successLoc == null) ? this.localDir : this.successLoc;
+    }
+
+    public File getOnFailDir() {
+        return (this.failLoc == null) ? this.localDir : this.failLoc;
+    }
+
+    public File getLocalDir() {
+        return this.localDir;
+    }
+
+    public void setDeleteOnSuccess(boolean deleteOnSuccess) {
+        this.deleteOnSuccess = deleteOnSuccess;
+    }
+
+    public boolean getDeleteOnSuccess() {
+      return deleteOnSuccess;
+    }
+
+    public String toString() {
+        return "PropFilesInfo\n" + "   " + "Local directory: " + this.localDir
+                + "\n" + "   " + "Patterns: " + this.patterns + "\n" + "   "
+                + "Delete on success: " + this.deleteOnSuccess + "\n" + "   "
+                + "Move to directory on success: " + this.successLoc + "\n"
+                + "   " + "Move to directory on fail: " + this.failLoc + "\n"
+                + "   " + this.di + "\n";
+    }
+
+    private class RegExpAndParser {
+        private String pattern;
+
+        private Parser parser;
+
+        public RegExpAndParser(String pattern, Parser parser) {
+            this.pattern = pattern;
+            this.parser = parser;
+        }
+
+        public boolean isAcceptedByPattern(String filename) {
+            return Pattern.matches(pattern, filename);
+        }
+
+        public Parser getParser() {
+            return this.parser;
+        }
+
+        public String getPattern() {
+            return this.pattern;
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/ProtocolInfo.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/ProtocolInfo.java
new file mode 100644
index 0000000..2972d0b
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/ProtocolInfo.java
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.config;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+import org.apache.oodt.cas.pushpull.exceptions.ConfigException;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class ProtocolInfo implements ConfigParserMetKeys {
+
+    private long timeout;
+
+    private int pgSize;
+
+    private static final int DEFAULT_PG_SIZE = 8;
+
+    private HashMap<String, LinkedList<Class<ProtocolFactory>>> protocolClassReference;
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(ProtocolInfo.class
+            .getName());
+
+    public ProtocolInfo() {
+        timeout = 0;
+        pgSize = DEFAULT_PG_SIZE;
+        protocolClassReference = new HashMap<String, LinkedList<Class<ProtocolFactory>>>();
+    }
+
+    public void loadProtocolFactoryInfoFromFile(File protocolFactoryInfo)
+            throws ConfigException {
+        try {
+            NodeList sourceList = XMLUtils.getDocumentRoot(new FileInputStream(protocolFactoryInfo))
+                    .getElementsByTagName(PROTOCOL_TAG);
+            for (int i = 0; i < sourceList.getLength(); i++) {
+
+                // get source element
+                Node sourceNode = sourceList.item(i);
+
+                // get host of this source
+                String type = PathUtils
+                        .replaceEnvVariables(((Element) sourceNode)
+                                .getAttribute(TYPE_ATTR));
+
+                // get all login info for this source
+                NodeList loginList = ((Element) sourceNode)
+                        .getElementsByTagName(PROTOCOL_FACTORY_TAG);
+                for (int j = 0; j < loginList.getLength(); j++) {
+
+                    // get a single login info
+                    Node loginNode = loginList.item(j);
+                    String protocolFactoryClass = PathUtils
+                            .replaceEnvVariables(((Element) loginNode)
+                                    .getAttribute(CLASS_ATTR));
+
+                    this.addClassForType(type, protocolFactoryClass);
+                }
+            }
+        } catch (Exception e) {
+            throw new ConfigException(
+                    "Failed to load ProtocolFactory info for protocol types : "
+                            + e.getMessage());
+        }
+    }
+
+    public void addClassForType(String type,
+            Class<ProtocolFactory> protocolFactoryClass) {
+        LinkedList<Class<ProtocolFactory>> protocolClasses;
+        if ((protocolClasses = protocolClassReference.get(type)) == null) {
+            protocolClasses = new LinkedList<Class<ProtocolFactory>>();
+            protocolClassReference.put(type.toLowerCase(), protocolClasses);
+        }
+        protocolClasses.add(protocolFactoryClass);
+        LOG.log(Level.INFO, "Assiging protocol '" + type.toLowerCase()
+                + "' with class '" + protocolFactoryClass + "'");
+    }
+
+    public void addClassForType(String type, String protocolFactoryClass)
+            throws ClassNotFoundException {
+        this.addClassForType(type, (Class<ProtocolFactory>) Class
+                .forName(protocolFactoryClass));
+    }
+
+    public void addClassForType(String type,
+            Class<ProtocolFactory>[] protocolFactoryClasses) {
+        for (Class<ProtocolFactory> clazz : protocolFactoryClasses) {
+            this.addClassForType(type, clazz);
+        }
+    }
+
+    public void addClassForType(String type, String[] protocolFactoryClasses)
+            throws ClassNotFoundException {
+        for (String clazz : protocolFactoryClasses) {
+            this.addClassForType(type, (Class<ProtocolFactory>) Class
+                    .forName(clazz));
+        }
+    }
+
+    public void setDownloadTimeout(long timeout) {
+        this.timeout = timeout;
+    }
+
+    public void setPageSize(int pgSize) {
+        if (pgSize != -1)
+            this.pgSize = pgSize;
+        else
+            this.pgSize = Integer.MAX_VALUE;
+    }
+
+    public LinkedList<Class<ProtocolFactory>> getProtocolClassesForProtocolType(
+            String type) {
+        return protocolClassReference.get(type.toLowerCase());
+    }
+
+    public long getDownloadTimeout() {
+        return timeout;
+    }
+
+    public int getPageSize() {
+        return pgSize;
+    }
+
+    public ProtocolInfo clone() {
+        ProtocolInfo pi = new ProtocolInfo();
+        pi.protocolClassReference = this.protocolClassReference;
+        pi.timeout = this.timeout;
+        pi.pgSize = this.pgSize;
+        return pi;
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/RemoteSpecs.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/RemoteSpecs.java
new file mode 100644
index 0000000..e0d5f0e
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/RemoteSpecs.java
@@ -0,0 +1,357 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pushpull.config;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.exceptions.ConfigException;
+import org.apache.oodt.cas.pushpull.filerestrictions.Parser;
+import org.apache.oodt.cas.pushpull.filerestrictions.renamingconventions.RenamingConvention;
+import org.apache.oodt.cas.pushpull.objectfactory.PushPullObjectFactory;
+import org.apache.oodt.cas.pushpull.protocol.RemoteSite;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.LinkedList;
+
+//DOM imports
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+//Google imports
+import com.google.common.base.Strings;
+
+/**
+ * Remote Site Crawling specifications.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class RemoteSpecs implements ConfigParserMetKeys {
+
+    LinkedList<Parser> parsers;
+
+    LinkedList<RenamingConvention> renamingConvs;
+
+    LinkedList<DaemonInfo> daemonInfoList;
+
+    SiteInfo siteInfo;
+
+    public RemoteSpecs() {
+        this.parsers = new LinkedList<Parser>();
+        this.renamingConvs = new LinkedList<RenamingConvention>();
+        daemonInfoList = new LinkedList<DaemonInfo>();
+        siteInfo = new SiteInfo();
+    }
+
+    public void loadRemoteSpecs(File remoteSpecsFile) throws ConfigException {
+        try {
+
+            Element root = XMLUtils.getDocumentRoot(
+                    new FileInputStream(remoteSpecsFile)).getDocumentElement();
+            NodeList aliasSpecList = root.getElementsByTagName(ALIAS_SPEC_TAG);
+            for (int i = 0; i < aliasSpecList.getLength(); i++) {
+                this.parseAndStoreLoginInfo(new File(PathUtils
+                        .replaceEnvVariables(((Element) aliasSpecList.item(i))
+                                .getAttribute(FILE_ATTR))));
+            }
+
+            // get DAEMON elements
+            NodeList daemonList = root.getElementsByTagName(DAEMON_TAG);
+            for (int i = 0; i < daemonList.getLength(); i++) {
+                Node daemonNode = daemonList.item(i);
+
+                // check if set to active (skip otherwise)
+                if (PathUtils.replaceEnvVariables(
+                        ((Element) daemonNode).getAttribute(ACTIVE_ATTR))
+                        .equals("no"))
+                    continue;
+
+                DaemonInfo di = null;
+
+                // get site alias
+                String siteAlias = PathUtils
+                        .replaceEnvVariables(((Element) daemonNode)
+                                .getAttribute(ALIAS_ATTR));
+                RemoteSite dataFilesRemoteSite = this.siteInfo
+                        .getSiteByAlias(siteAlias);
+                if (dataFilesRemoteSite == null)
+                    throw new ConfigException("Alias '" + siteAlias
+                            + "' in SiteInfo file '"
+                            + remoteSpecsFile.getAbsolutePath()
+                            + "' has not been defined");
+
+                // get RUNINFO element
+                NodeList runInfoList = ((Element) daemonNode)
+                        .getElementsByTagName(RUN_INFO_TAG);
+                String firstRunDateTimeString = null, period = null, epsilon = null;
+                boolean runOnReboot = false;
+                if (runInfoList.getLength() > 0) {
+                    Element runInfo = (Element) runInfoList.item(0);
+                    firstRunDateTimeString = runInfo
+                            .getAttribute(FIRSTRUN_DATETIME_ATTR);
+                    period = runInfo.getAttribute(PERIOD_ATTR);
+                    runOnReboot = (runInfo.getAttribute(RUNONREBOOT_ATTR)
+                            .toLowerCase().equals("yes")) ? true : false;
+                    epsilon = runInfo.getAttribute(EPSILON_ATTR);
+                    if (epsilon.equals(""))
+                        epsilon = "0s";
+                }
+
+                // get PROPINFO elements
+                NodeList propInfoList = ((Element) daemonNode)
+                        .getElementsByTagName(PROP_INFO_TAG);
+                LinkedList<PropFilesInfo> pfiList = new LinkedList<PropFilesInfo>();
+                PropFilesInfo pfi = null;
+                if (propInfoList.getLength() > 0) {
+                    Node propInfoNode = propInfoList.item(0);
+
+                    // get directory where the property files are
+                    File propertyFilesDir = new File(PathUtils
+                            .replaceEnvVariables(((Element) propInfoNode)
+                                    .getAttribute(DIR_ATTR)));
+
+                    pfi = new PropFilesInfo(propertyFilesDir);
+
+                    // get PROPFILES elements
+                    NodeList propFilesList = ((Element) propInfoNode)
+                            .getElementsByTagName(PROP_FILES_TAG);
+                    String propFilesRegExp = null;
+                    if (propFilesList.getLength() > 0) {
+                        for (int k = 0; k < propFilesList.getLength(); k++) {
+                            Node propFilesNode = propFilesList.item(k);
+                            propFilesRegExp = ((Element) propFilesNode)
+                                    .getAttribute(REG_EXP_ATTR);
+                            pfi
+                                    .addPropFiles(
+                                            propFilesRegExp,
+                                            PushPullObjectFactory
+                                                    .createNewInstance((Class<Parser>) Class
+                                                            .forName(PathUtils
+                                                                    .replaceEnvVariables(((Element) propFilesNode)
+                                                                            .getAttribute(PARSER_ATTR)))));
+                        }
+                    } else
+                        throw new ConfigException(
+                                "No propFiles element specified for deamon with alias '"
+                                        + siteAlias + "' in RemoteSpecs file '"
+                                        + remoteSpecsFile.getAbsolutePath()
+                                        + "'");
+
+                    // get DOWNLOADINFO element if given
+                    NodeList downloadInfoList = ((Element) propInfoNode)
+                            .getElementsByTagName(DOWNLOAD_INFO_TAG);
+                    if (downloadInfoList.getLength() > 0) {
+                        Node downloadInfo = downloadInfoList.item(0);
+                        String propFilesAlias = PathUtils
+                                .replaceEnvVariables(((Element) downloadInfo)
+                                        .getAttribute(ALIAS_ATTR));
+                        String propFilesRenamingConv = ((Element) downloadInfo)
+                                .getAttribute(RENAMING_CONV_ATTR);
+                        boolean allowAliasOverride = PathUtils
+                                .replaceEnvVariables(
+                                        ((Element) downloadInfo)
+                                                .getAttribute(ALLOW_ALIAS_OVERRIDE_ATTR))
+                                .equals("yes");
+                        boolean deleteFromServer = PathUtils
+                                .replaceEnvVariables(
+                                        ((Element) downloadInfo)
+                                                .getAttribute(DELETE_FROM_SERVER_ATTR))
+                                .equals("yes");
+                        RemoteSite propFilesRemoteSite = this.siteInfo
+                                .getSiteByAlias(propFilesAlias);
+                        if (propFilesRemoteSite == null)
+                            throw new ConfigException("Alias '"
+                                    + propFilesAlias
+                                    + "' in RemoteSpecs file '"
+                                    + remoteSpecsFile.getAbsolutePath()
+                                    + "' has not been defined");
+                        String regExp = ((Element) downloadInfo)
+                                .getAttribute(REG_EXP_ATTR);
+                        if (regExp.equals(""))
+                            regExp = propFilesRegExp;
+                        NodeList propsList = ((Element) propInfoNode)
+                                .getElementsByTagName(PROP_FILE_TAG);
+                        HashMap<File, Parser> propFileToParserMap = new HashMap<File, Parser>();
+                        for (int p = 0; p < propsList.getLength(); p++) {
+                            Element propElem = (Element) propsList.item(p);
+                            propFileToParserMap
+                                    .put(
+                                            new File(
+                                                    PathUtils
+                                                            .replaceEnvVariables(propElem
+                                                                    .getAttribute(PATH_ATTR))),
+                                            PushPullObjectFactory
+                                                    .createNewInstance((Class<Parser>) Class
+                                                            .forName(PathUtils
+                                                                    .replaceEnvVariables(propElem
+                                                                            .getAttribute(PARSER_ATTR)))));
+                        }
+                        pfi.setDownloadInfo(new DownloadInfo(
+                                propFilesRemoteSite, propFilesRenamingConv,
+                                deleteFromServer, propertyFilesDir,
+                                allowAliasOverride), propFileToParserMap);
+                    }
+
+                    // get AFTERUSE element
+                    NodeList afterUseList = ((Element) propInfoNode)
+                            .getElementsByTagName(AFTER_USE_TAG);
+                    if (afterUseList.getLength() > 0) {
+                        Element afterUse = (Element) afterUseList.item(0);
+                        File onSuccessDir = new File(PathUtils
+                                .replaceEnvVariables(afterUse
+                                        .getAttribute(MOVEON_TO_SUCCESS_ATTR)));
+                        File onFailDir = new File(PathUtils
+                                .replaceEnvVariables(afterUse
+                                        .getAttribute(MOVEON_TO_FAIL_ATTR)));
+                        pfi.setAfterUseEffects(onSuccessDir, onFailDir);
+                        boolean deleteOnSuccess = Boolean.parseBoolean(PathUtils
+                            .replaceEnvVariables(afterUse
+                                    .getAttribute(DELETE_ON_SUCCESS_ATTR)));
+                        pfi.setDeleteOnSuccess(deleteOnSuccess);
+                    }
+
+                } else
+                    throw new ConfigException(
+                            "No propInfo element specified for deamon with alias '"
+                                    + siteAlias + "' in RemoteSpecs file '"
+                                    + remoteSpecsFile.getAbsolutePath() + "'");
+
+                // get DATAINFO elements
+                NodeList dataInfoList = ((Element) daemonNode)
+                        .getElementsByTagName(DATA_INFO_TAG);
+                DataFilesInfo dfi = null;
+                if (dataInfoList.getLength() > 0) {
+                    Node dataInfo = dataInfoList.item(0);
+                    String queryElement = ((Element) dataInfo)
+                           .getAttribute(QUERY_ELEM_ATTR);
+                    if (Strings.isNullOrEmpty(queryElement)) {
+                       queryElement = null;
+                    } else {
+                       queryElement = PathUtils.replaceEnvVariables(queryElement);
+                    }
+                    String renamingConv = ((Element) dataInfo)
+                            .getAttribute(RENAMING_CONV_ATTR);
+                    if (Strings.isNullOrEmpty(renamingConv)) {
+                       renamingConv = null;
+                    }
+                    boolean allowAliasOverride = PathUtils.replaceEnvVariables(
+                            ((Element) dataInfo)
+                                    .getAttribute(ALLOW_ALIAS_OVERRIDE_ATTR))
+                            .equals("yes");
+                    File stagingArea = new File(PathUtils
+                            .replaceEnvVariables(((Element) dataInfo)
+                                    .getAttribute(STAGING_AREA_ATTR)));
+                    boolean deleteFromServer = PathUtils.replaceEnvVariables(
+                            ((Element) dataInfo)
+                                    .getAttribute(DELETE_FROM_SERVER_ATTR))
+                            .equals("yes");
+                    dfi = new DataFilesInfo(queryElement, new DownloadInfo(
+                            dataFilesRemoteSite, renamingConv,
+                            deleteFromServer, stagingArea, allowAliasOverride));
+                } else
+                    throw new ConfigException(
+                            "No dataInfo element specified for deamon with alias '"
+                                    + siteAlias + "' in RemoteSpecs file '"
+                                    + remoteSpecsFile.getAbsolutePath() + "'");
+
+                daemonInfoList.add(new DaemonInfo(firstRunDateTimeString,
+                        period, epsilon, runOnReboot, pfi, dfi));
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new ConfigException("Failed to load crawl elements : "
+                    + e.getMessage());
+        }
+    }
+
+    void parseAndStoreLoginInfo(File loginInfoFile) throws ConfigException {
+        try {
+            NodeList sourceList = XMLUtils.getDocumentRoot(new FileInputStream(loginInfoFile))
+                    .getElementsByTagName(SOURCE_TAG);
+            for (int i = 0; i < sourceList.getLength(); i++) {
+
+                // get source element
+                Node sourceNode = sourceList.item(i);
+
+                // get host of this source
+                String host = PathUtils
+                        .replaceEnvVariables(((Element) sourceNode)
+                                .getAttribute(HOST_ATTR));
+
+                // get all login info for this source
+                NodeList loginList = ((Element) sourceNode)
+                        .getElementsByTagName(LOGIN_ATTR);
+                for (int j = 0; j < loginList.getLength(); j++) {
+
+                    // get a single login info
+                    Node loginNode = loginList.item(j);
+                    String type = PathUtils
+                            .replaceEnvVariables(((Element) loginNode)
+                                    .getAttribute(TYPE_ATTR));
+                    String alias = PathUtils
+                            .replaceEnvVariables(((Element) loginNode)
+                                    .getAttribute(ALIAS_ATTR));
+                    String username = null, password = null, cdTestDir = null;
+                    int maxConnections = -1;
+
+                    // parse this login info
+                    NodeList loginInfo = loginNode.getChildNodes();
+                    for (int k = 0; k < loginInfo.getLength(); k++) {
+
+                        // get a single login info element
+                        Node node = loginInfo.item(k);
+
+                        // determine what element type it is
+                        if (node.getNodeName().equals(USERNAME_TAG)) {
+                            username = PathUtils.replaceEnvVariables(
+                                    XMLUtils.getSimpleElementText((Element) node, true));
+                        } else if (node.getNodeName().equals(PASSWORD_TAG)) {
+                            password = PathUtils.replaceEnvVariables(
+                                    XMLUtils.getSimpleElementText((Element) node, true));
+                        } else if (node.getNodeName().equals(CD_TEST_DIR_TAG)) {
+                            cdTestDir = PathUtils.replaceEnvVariables(
+                                    XMLUtils.getSimpleElementText((Element) node, true));
+                        } else if (node.getNodeName().equals(MAX_CONN_TAG)) {
+                            maxConnections = Integer.parseInt(PathUtils.replaceEnvVariables(
+                                    XMLUtils.getSimpleElementText((Element) node, true)));
+                        }
+                    }
+
+                    this.siteInfo.addSite(new RemoteSite(alias, new URL(type
+                            + "://" + host), username, password, cdTestDir, maxConnections));
+                }
+            }
+        } catch (Exception e) {
+            throw new ConfigException("Failed to load external source info : "
+                    + e.getMessage(), e);
+        }
+    }
+
+    public LinkedList<DaemonInfo> getDaemonInfoList() {
+        return this.daemonInfoList;
+    }
+
+    public SiteInfo getSiteInfo() {
+        return this.siteInfo;
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/SiteInfo.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/SiteInfo.java
new file mode 100644
index 0000000..487284b
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/config/SiteInfo.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.config;
+
+//JDK imports
+import java.net.URL;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.Map.Entry;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.protocol.RemoteSite;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class SiteInfo {
+
+    private HashMap<String, RemoteSite> aliasAndRemoteSite;
+
+    public SiteInfo() {
+        aliasAndRemoteSite = new HashMap<String, RemoteSite>();
+    }
+
+    public void addSite(RemoteSite rs) {
+        this.aliasAndRemoteSite.put(rs.getAlias(), rs);
+    }
+
+    public RemoteSite getSiteByAlias(String alias) {
+        return this.aliasAndRemoteSite.get(alias);
+    }
+
+    public LinkedList<RemoteSite> getPossibleRemoteSites(String alias, URL url,
+            String username, String password) {
+        LinkedList<RemoteSite> remoteSites = new LinkedList<RemoteSite>();
+        if (alias != null) {
+            RemoteSite rs = this.aliasAndRemoteSite.get(alias);
+            if (rs != null)
+                remoteSites.add(rs);
+            else if (url != null && username != null & password != null)
+                remoteSites.add(new RemoteSite(alias, url, username, password));
+        } else if (url != null) {
+            Set<Entry<String, RemoteSite>> set = this.aliasAndRemoteSite
+                    .entrySet();
+            for (Entry<String, RemoteSite> entry : set) {
+                RemoteSite rs = entry.getValue();
+                if (rs.getURL().equals(url)
+                        && (username == null || rs.getUsername().equals(
+                                username))
+                        && (password == null || rs.getPassword().equals(
+                                password)))
+                    remoteSites.add(rs);
+            }
+            if (remoteSites.size() == 0) {
+                if (url != null && username != null && password != null)
+                    remoteSites.add(new RemoteSite(url.toString(), url,
+                            username, password));
+            }
+        } else if (username != null) {
+            Set<Entry<String, RemoteSite>> set = this.aliasAndRemoteSite
+                    .entrySet();
+            for (Entry<String, RemoteSite> entry : set) {
+                RemoteSite rs = entry.getValue();
+                if (rs.getUsername().equals(username)
+                        && (password == null || rs.getPassword().equals(
+                                password)))
+                    remoteSites.add(rs);
+            }
+        } else if (password != null) {
+            Set<Entry<String, RemoteSite>> set = this.aliasAndRemoteSite
+                    .entrySet();
+            for (Entry<String, RemoteSite> entry : set) {
+                RemoteSite rs = entry.getValue();
+                if (rs.getPassword().equals(password))
+                    remoteSites.add(rs);
+            }
+        }
+        return remoteSites;
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/Daemon.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/Daemon.java
new file mode 100644
index 0000000..10f8f34
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/Daemon.java
@@ -0,0 +1,578 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.daemon;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.config.Config;
+import org.apache.oodt.cas.pushpull.config.DaemonInfo;
+import org.apache.oodt.cas.pushpull.config.SiteInfo;
+import org.apache.oodt.cas.pushpull.daemon.DaemonMBean;
+import org.apache.oodt.cas.pushpull.daemon.DaemonRmiInterface;
+import org.apache.oodt.cas.pushpull.protocol.RemoteSite;
+import org.apache.oodt.cas.pushpull.retrievalsystem.RetrievalSetup;
+
+//JDK imports
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.net.MalformedURLException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.Naming;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//JMX imports
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+/**
+ * Controls the execution times of the Crawler it is given. The Crawler is
+ * specified by the properties file passed in. A Crawler will be created per the
+ * properties file and executed at six hour intervals. This class can be
+ * controlled by CrawlDaemonController after is has been started up.
+ * 
+ * @author bfoster
+ */
+public class Daemon extends UnicastRemoteObject implements DaemonRmiInterface,
+        DaemonMBean {
+
+    private static final long serialVersionUID = 7660972939723142802L;
+
+    private DaemonListener daemonListener;
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(Daemon.class.getName());
+
+    /**
+     * Keeps track of whether the Crawler is running or not
+     */
+    private boolean isRunning;
+
+    /**
+     * If set to false the CrawlDaemon will terminate after the Crawler finishes
+     * crawling its current site.
+     */
+    private boolean keepRunning;
+
+    /**
+     * The time at which the Constructor is called
+     */
+    private long daemonCreationTime;
+
+    /**
+     * The total time during which the Crawl is actually running -- wait() time
+     * is not included.
+     */
+    private long daemonTotalRuntime;
+
+    /**
+     * Total number of times the Crawler has been run
+     */
+    private int numberOfCrawls;
+
+    private File propFilesDir;
+
+    private int daemonID;
+
+    private RetrievalSetup rs;
+
+    private Config config;
+
+    private DaemonInfo daemonInfo;
+
+    private MBeanServer mbs;
+
+    private int rmiRegPort;
+
+    /**
+     * Constructor
+     * 
+     * @throws RemoteException
+     * @throws RemoteException
+     * @throws InstantiationException
+     * @throws IOException
+     * @throws SecurityException
+     */
+    public Daemon(int rmiRegPort, int daemonID, Config config,
+            DaemonInfo daemonInfo, SiteInfo siteInfo) throws RemoteException,
+            InstantiationException {
+        super();
+
+        this.rmiRegPort = rmiRegPort;
+        this.daemonID = daemonID;
+        rs = new RetrievalSetup(config, siteInfo);
+        this.config = config;
+        this.daemonInfo = daemonInfo;
+
+        daemonCreationTime = System.currentTimeMillis();
+        daemonTotalRuntime = 0;
+        numberOfCrawls = 0;
+        isRunning = false;
+
+        try {
+            registerRMIServer();
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, "Failed to bind to RMI server : "
+                    + e.getMessage());
+        }
+
+        try {
+            // registry CrawlDaemon as MBean so it can be used with jconsole
+            mbs = ManagementFactory.getPlatformMBeanServer();
+            ObjectName name = new ObjectName(
+                    "org.apache.oodt.cas.pushpull.daemon:type=Daemon"
+                            + this.getDaemonID());
+            mbs.registerMBean(this, name);
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE,
+                    "Failed to register CrawlDaemon as a MBean Object : "
+                            + e.getMessage());
+        }
+    }
+
+    public String getName() {
+        return "Daemon" + this.getDaemonID();
+    }
+
+    private void registerRMIServer() throws RemoteException,
+            MalformedURLException, NotBoundException, AlreadyBoundException {
+        try {
+            Naming.bind("//localhost:" + this.rmiRegPort + "/daemon"
+                    + this.getDaemonID(), this);
+            LOG.log(Level.INFO, "Created Daemon ID = " + this.getDaemonID()
+                    + " on RMI registry port " + this.rmiRegPort);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RemoteException("Failed to bind Daemon with ID = "
+                    + this.getDaemonID() + " to RMI registry at port "
+                    + this.rmiRegPort);
+        }
+    }
+
+    public void registerDaemonListener(DaemonListener daemonListener) {
+        this.daemonListener = daemonListener;
+        this.daemonListener.wasRegisteredWith(this);
+    }
+
+    /**
+     * Loads and executes the Crawler specified by the properties file. It will
+     * crawl the URLs specified in the properties file in the sequence
+     * given--one at a time.
+     * 
+     * @param property
+     *            The system property whose value is the path to a java
+     *            .properties file that is be used to create the Crawler
+     * @throws DirStructException
+     */
+    public void startDaemon() {
+        new Thread(new Runnable() {
+
+            public void run() {
+
+                // check if Daemon should sleep first
+                long timeTilNextRun;
+                if ((timeTilNextRun = Daemon.this.calculateTimeTilNextRun()) != 0
+                        && !(Daemon.this.beforeToday(daemonInfo
+                                .getFirstRunDateTime()) && daemonInfo
+                                .runOnReboot()))
+                    sleep(timeTilNextRun);
+
+                for (keepRunning = true; keepRunning;) {
+                    long startTime = System.currentTimeMillis();
+
+                    // get permission to run
+                    Daemon.this.notifyDaemonListenerOfStart();
+                    if (!keepRunning) {
+                        Daemon.this.notifyDaemonListenerOfFinish();
+                        System.out.println("BREAKING OUT");
+                        break;
+                    }
+
+                    // run
+                    Daemon.this.isRunning = true;
+
+                    try {
+                        rs.retrieveFiles(daemonInfo.getPropFilesInfo(),
+                                daemonInfo.getDataFilesInfo());
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    } finally {
+                        numberOfCrawls++;
+                    }
+
+                    Daemon.this.isRunning = false;
+
+                    // calculate performance and sleep
+                    Daemon.this.notifyDaemonListenerOfFinish();
+                    Daemon.this.calculateAndStoreElapsedTime(startTime);
+                    if (Daemon.this.keepRunning
+                            && daemonInfo.getTimeIntervalInMilliseconds() >= 0) {
+                        sleep(Daemon.this.calculateTimeTilNextRun());
+                    } else {
+                        break;
+                    }
+                }
+                LOG.log(Level.INFO, "Daemon with ID = "
+                        + Daemon.this.getDaemonID() + " on RMI registry port "
+                        + Daemon.this.rmiRegPort + " is shutting down");
+                Daemon.this.unregister();
+            }
+        }).start();
+    }
+
+    private void unregister() {
+        try {
+            // unregister CrawlDaemon from RMI registry
+            Naming.unbind("//localhost:" + this.rmiRegPort + "/daemon"
+                    + this.getDaemonID());
+            this.mbs.unregisterMBean(new ObjectName(
+                    "org.apache.oodt.cas.pushpull.daemon:type=Daemon"
+                            + this.getDaemonID()));
+            UnicastRemoteObject.unexportObject(this, true);
+            this.daemonListener.wasUnregisteredWith(this);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public int getDaemonID() {
+        return Integer.parseInt(this.rmiRegPort + "" + this.daemonID);
+    }
+
+    private long calculateTimeTilNextRun() {
+        GregorianCalendar now = new GregorianCalendar();
+        GregorianCalendar gcStartDateTime = new GregorianCalendar();
+        gcStartDateTime.setTime(daemonInfo.getFirstRunDateTime());
+        long diff = now.getTimeInMillis() - gcStartDateTime.getTimeInMillis();
+        if (Math.abs(diff) <= daemonInfo.getEpsilonInMilliseconds())
+            return 0;
+        else if (diff < 0)
+            return gcStartDateTime.getTimeInMillis() - now.getTimeInMillis();
+        else if (daemonInfo.getTimeIntervalInMilliseconds() == 0) {
+            return 0;
+        } else {
+            int numOfPeriods = (int) (diff / daemonInfo
+                    .getTimeIntervalInMilliseconds());
+            long nextRunTime = gcStartDateTime.getTimeInMillis()
+                    + ((numOfPeriods + 1) * daemonInfo
+                            .getTimeIntervalInMilliseconds());
+            return nextRunTime - now.getTimeInMillis();
+        }
+    }
+
+    private boolean beforeToday(Date date) {
+        return date.before(new Date(System.currentTimeMillis()));
+    }
+
+    private void notifyDaemonListenerOfStart() {
+        if (this.daemonListener != null)
+            this.daemonListener.daemonStarting(this);
+    }
+
+    private void notifyDaemonListenerOfFinish() {
+        if (this.daemonListener != null)
+            this.daemonListener.daemonFinished(this);
+    }
+
+    private void sleep(long length) {
+        if (length > 0) {
+            LOG.log(Level.INFO, "Daemon with ID = " + this.getDaemonID()
+                    + " on RMI registry port " + this.rmiRegPort
+                    + " is going to sleep until "
+                    + new Date(System.currentTimeMillis() + length));
+            synchronized (this) {
+                try {
+                    wait(length);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+    }
+
+    private long calculateAndStoreElapsedTime(long startTime) {
+        long elapsedTime = System.currentTimeMillis() - startTime;
+        daemonTotalRuntime += elapsedTime;
+        return elapsedTime;
+    }
+
+    public synchronized void pauseDaemon() {
+        try {
+            LOG.log(Level.INFO, "Daemon with ID = " + this.getDaemonID()
+                    + " on RMI registry port " + this.rmiRegPort
+                    + " has been stopped");
+            this.wait(0);
+        } catch (Exception e) {
+        }
+        LOG.log(Level.INFO, "Daemon with ID = " + this.getDaemonID()
+                + " on RMI registry port " + this.rmiRegPort + " has resumed");
+    }
+
+    /**
+     * Wakes up the CrawlDaemon if it is sleeping
+     */
+    public synchronized void resume() {
+        notify();
+    }
+
+    /**
+     * Will terminate the CrawlDaemon. If its Crawler is crawling a site when
+     * this method is called, the terminate won't take place until after the
+     * Crawler has complete crawling that site.
+     */
+    public synchronized void quit() {
+        keepRunning = false;
+        resume();
+    }
+
+    /**
+     * Can be used to determine if Crawler is presently running
+     * 
+     * @return true if Crawler is runnning
+     * @uml.property name="isRunning"
+     */
+    public boolean isRunning() {
+        return isRunning;
+    }
+
+    /**
+     * Average runtime for the Crawler
+     * 
+     * @return average runtime for the Crawler
+     */
+    public long getAverageRunTime() {
+        return daemonTotalRuntime / numberOfCrawls;
+    }
+
+    /**
+     * Gets the total crawling time of the Crawler
+     * 
+     * @return Total crawling time of Crawler
+     */
+    public long getMillisCrawling() {
+        return daemonTotalRuntime;
+    }
+
+    /**
+     * Gets the time between the start of Crawler executions
+     * 
+     * @return Time interval between Crawler start times
+     */
+    public long getTimeInterval() {
+        return daemonInfo.getTimeIntervalInMilliseconds();
+    }
+
+    /**
+     * Gets the total number of times the Crawler has been run
+     * 
+     * @return The number of times Crawler has run
+     */
+    public int getNumCrawls() {
+        return numberOfCrawls;
+    }
+
+    public String[] downloadedFilesInStagingArea() {
+        return this.daemonInfo.getDataFilesInfo().getDownloadInfo()
+                .getStagingArea().list(new FilenameFilter() {
+                    public boolean accept(File dir, String name) {
+                        return !name.startsWith("Downloading_")
+                                && !(name.endsWith("info.tmp") || name
+                                        .endsWith("cas"));
+                    }
+                });
+    }
+
+    public String[] downloadingFilesInStagingArea() {
+        return this.daemonInfo.getDataFilesInfo().getDownloadInfo()
+                .getStagingArea().list(new FilenameFilter() {
+                    public boolean accept(File dir, String name) {
+                        return name.startsWith("Downloading_")
+                                && !(name.endsWith("info.tmp") || name
+                                        .endsWith("cas"));
+                    }
+                });
+    }
+
+    public int numberOfFilesDownloadingInStagingArea() {
+        return this.downloadingFilesInStagingArea().length;
+    }
+
+    public int numberOfFilesDownloadedInStagingArea() {
+        return this.downloadedFilesInStagingArea().length;
+    }
+
+    // ***************DaemonInfo******************
+    public long getTimeIntervalInMilliseconds() {
+        return this.daemonInfo.getTimeIntervalInMilliseconds();
+    }
+
+    public long getEpsilonInMilliseconds() {
+        return this.daemonInfo.getEpsilonInMilliseconds();
+    }
+
+    public boolean getRunOnReboot() {
+        return this.daemonInfo.runOnReboot();
+    }
+
+    public Date getFirstRunDateTime() {
+        return this.daemonInfo.getFirstRunDateTime();
+    }
+
+    // ***************DaemonInfo******************
+
+    // ***************DataFilesInfo*******************
+    public String getDataFilesRemoteSite() {
+        RemoteSite remoteSite = this.daemonInfo.getDataFilesInfo()
+                .getDownloadInfo().getRemoteSite();
+        return (remoteSite == null) ? "" : remoteSite.toString();
+    }
+
+    public String getDataFilesRenamingConv() {
+        return this.daemonInfo.getDataFilesInfo().getDownloadInfo()
+                .getRenamingConv();
+    }
+
+    public boolean getDeleteDataFilesFromServer() {
+        return this.daemonInfo.getDataFilesInfo().getDownloadInfo()
+                .deleteFromServer();
+    }
+
+    public String getQueryMetadataElementName() {
+        String element = this.daemonInfo.getDataFilesInfo()
+                .getQueryMetadataElementName();
+        if (element == null || element.equals(""))
+            element = "Filename";
+        return this.daemonInfo.getDataFilesInfo().getQueryMetadataElementName();
+    }
+
+    public File getDataFilesStagingArea() {
+        return this.daemonInfo.getDataFilesInfo().getDownloadInfo()
+                .getStagingArea();
+    }
+
+    public boolean getAllowAliasOverride() {
+        return this.daemonInfo.getDataFilesInfo().getDownloadInfo()
+                .isAllowAliasOverride();
+    }
+
+    // **************DataFilesInfo********************
+
+    // **************PropFilesInfo********************
+    public String getPropertyFilesRemoteSite() {
+        RemoteSite remoteSite = this.daemonInfo.getPropFilesInfo()
+                .getDownloadInfo().getRemoteSite();
+        return (remoteSite == null) ? "" : remoteSite.toString();
+    }
+
+    public String getPropertyFilesRenamingConv() {
+        return this.daemonInfo.getPropFilesInfo().getDownloadInfo()
+                .getRenamingConv();
+    }
+
+    public boolean getDeletePropertyFilesFromServer() {
+        return this.daemonInfo.getPropFilesInfo().getDownloadInfo()
+                .deleteFromServer();
+    }
+
+    public String getPropertyFilesOnSuccessDir() {
+        File successDir = this.daemonInfo.getPropFilesInfo().getOnSuccessDir();
+        return successDir == null ? "" : successDir.getAbsolutePath();
+    }
+
+    public String getPropertyFilesOnFailDir() {
+        File failDir = this.daemonInfo.getPropFilesInfo().getOnFailDir();
+        return failDir == null ? "" : failDir.getAbsolutePath();
+    }
+
+    public File getPropertyFilesLocalDir() {
+        return this.daemonInfo.getPropFilesInfo().getLocalDir();
+    }
+
+    // **************PropFilesInfo********************
+
+    /**
+     * Gets the time in milliseconds for when the CrawlDaemon constructor was
+     * invoked.
+     * 
+     * @return
+     * @uml.property name="daemonCreationTime"
+     */
+    public long getDaemonCreationTime() {
+        return daemonCreationTime;
+    }
+
+    public boolean getHasBeenToldToQuit() {
+        return !this.keepRunning;
+    }
+
+    public String toString() {
+        return this.getName();
+    }
+
+    /**
+     * Starts the program
+     * 
+     * @param args
+     *            Not Used
+     * @throws IOException
+     * @throws SecurityException
+     */
+    public static void main(String[] args) {
+        try {
+
+            int rmiPort = -1;
+            boolean waitForCrawlNotification = false;
+
+            for (int i = 0; i < args.length; ++i) {
+                if (args[i].equals("--rmiPort"))
+                    rmiPort = Integer.parseInt(args[++i]);
+                else if (args[i].equals("--waitForNotification"))
+                    waitForCrawlNotification = true;
+            }
+
+            LocateRegistry.createRegistry(rmiPort);
+
+            try {
+                // registry CrawlDaemon as MBean so it can be used with jconsole
+                MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+                ObjectName name = new ObjectName(
+                        "org.apache.oodt.cas.pushpull.daemon:type=Daemon");
+            } catch (Exception e) {
+                LOG.log(Level.SEVERE,
+                        "Failed to register CrawlDaemon as a MBean Object : "
+                                + e.getMessage());
+            }
+
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, "Failed to create CrawlDaemon : "
+                    + e.getMessage());
+        } finally {
+            // terminate the CrawlDaemon
+            LOG.log(Level.INFO, "Terminating CrawlDaemon");
+        }
+
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonController.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonController.java
new file mode 100644
index 0000000..f4bfcbb
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonController.java
@@ -0,0 +1,206 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.daemon;
+
+//JDK imports
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+
+/**
+ * @author bfoster
+ * 
+ * <p>
+ * After the CrawlDaemon has been started, this class can control the
+ * CrawlDaemon through webserver communication, thus it can be control from
+ * computers other than the one it is executing on. This class has control over
+ * pausing, resuming, and killing the CrawlDaemon process. It also has the
+ * ability of getting the status on several variables within the CrawlDaemon
+ * class. See CrawlDaemon for more info.
+ * </p>.
+ */
+public class DaemonController {
+
+    private DaemonRmiInterface daemon;
+
+    /**
+     * Constructor -- initializes the XmlRpcClient
+     * 
+     * @param crawlUrlStr
+     *            The URL location where the CrawlDaemon server is running
+     * @throws InstantiationException
+     */
+    public DaemonController(String rmiUrl) throws RemoteException {
+        try {
+            daemon = (DaemonRmiInterface) Naming.lookup(rmiUrl);
+            System.out.println(!daemon.getHasBeenToldToQuit());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Get the average time for each run of the Crawler controlled by the
+     * CrawlDaemons
+     * 
+     * @return Average runtime of Crawler
+     * @throws RemoteException
+     * @throws XmlRpcCommunicationException
+     *             Error communicating with server
+     */
+    public long getAverageRunTime() throws RemoteException {
+        return daemon.getAverageRunTime();
+    }
+
+    /**
+     * Gets the total milliseconds for which the Crawler in CrawlDaemon has been
+     * crawling since the CrawlDaemon was created.
+     * 
+     * @return The total milliseconds which the Crawler has been crawling
+     * @throws RemoteException
+     * @throws XmlRpcCommunicationException
+     *             Error communicating with server
+     */
+    public long getMillisCrawling() throws RemoteException {
+        return daemon.getMillisCrawling();
+    }
+
+    /**
+     * Gets the time between the start of each scheduled run.
+     * 
+     * @return The time between the start of each execution of the Crawler
+     *         controlled by the CrawlDaemon
+     * @throws RemoteException
+     * @throws XmlRpcCommunicationException
+     *             Error communicating with server
+     */
+    public long getWaitInterval() throws RemoteException {
+        return daemon.getTimeInterval();
+    }
+
+    /**
+     * Gets the numbers of times the Crawler has been run by the CrawlDaemon
+     * 
+     * @return The of times Crawler has executed
+     * @throws RemoteException
+     * @throws XmlRpcCommunicationException
+     *             Error communicating with server
+     */
+    public int getNumCrawls() throws RemoteException {
+        return daemon.getNumCrawls();
+    }
+
+    /**
+     * Used to determine if the Crawler in the CrawlDaemon is running
+     * 
+     * @return true is Crawler is running
+     * @throws RemoteException
+     * @throws XmlRpcCommunicationException
+     *             Error communicating with server
+     */
+    public boolean isRunning() throws RemoteException {
+        return daemon.isRunning();
+    }
+
+    /**
+     * Wakes the CrawlDaemon up and tells it to start crawling again. If stop()
+     * was called, this method will have the CrawlDaemon continue from where it
+     * left off. This method will also wake up the CrawlDaemon from its sleep
+     * between scheduled runs.
+     * 
+     * @throws RemoteException
+     * @throws XmlRpcCommunicationException
+     *             Error communicating with server
+     */
+    public void resume() throws RemoteException {
+        daemon.resume();
+    }
+
+    public void quit() throws RemoteException {
+        daemon.quit();
+    }
+
+    /**
+     * Gets the time in milliseconds of when the CrawlDaemon was created
+     * 
+     * @return The time the CrawlDaemon was created
+     * @throws RemoteException
+     * @throws XmlRpcCommunicationException
+     *             Error communicating with server
+     */
+    public long getDaemonCreationTime() throws RemoteException {
+        return daemon.getDaemonCreationTime();
+    }
+
+    /**
+     * Driver method -- starts the CrawlDaemonController
+     * 
+     * @param args
+     *            See documentation
+     * @throws Exception
+     *             On error! :)
+     */
+    public static void main(String[] args) throws Exception {
+        String avgCrawlOperation = "--getAverageRunTime\n";
+        String getMilisCrawlOperation = "--getMilisCrawling\n";
+        String getNumCrawlsOperation = "--getNumCrawls\n";
+        String getWaitIntervalOperation = "--getWaitInterval\n";
+        String isRunningOperation = "--isRunning\n";
+        String stopOperation = "--stop\n";
+        String usage = "CrawlController --url <url to xml rpc service> "
+                + "--operation [<operation> [params]]\n" + "operations:\n"
+                + avgCrawlOperation + getMilisCrawlOperation
+                + getNumCrawlsOperation + getWaitIntervalOperation
+                + isRunningOperation + stopOperation;
+        String operation = null, url = null;
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--operation")) {
+                operation = args[++i];
+            } else if (args[i].equals("--url")) {
+                url = args[++i];
+            }
+        }
+        if (operation == null) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        // create the controller
+        DaemonController controller = new DaemonController(url);
+        if (operation.equals("--getAverageRunTime")) {
+            double avgCrawlTime = controller.getAverageRunTime();
+            System.out.println("Average Crawl Time: [" + avgCrawlTime + "]");
+        } else if (operation.equals("--getMilisCrawling")) {
+            long crawlTime = controller.getMillisCrawling();
+            System.out.println("Total Crawl Time: [" + crawlTime
+                    + "] miliseconds");
+        } else if (operation.equals("--getNumCrawls")) {
+            int numCrawls = controller.getNumCrawls();
+            System.out.println("Num Crawls: [" + numCrawls + "]");
+        } else if (operation.equals("--getWaitInterval")) {
+            long waitInterval = controller.getWaitInterval();
+            System.out.println("Wait Interval: [" + waitInterval + "]");
+        } else if (operation.equals("--isRunning")) {
+            boolean running = controller.isRunning();
+            System.out.println(running ? "Yes" : "No");
+        } else
+            throw new IllegalArgumentException("Unknown Operation!");
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonLauncher.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonLauncher.java
new file mode 100644
index 0000000..6815ba7
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonLauncher.java
@@ -0,0 +1,191 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.daemon;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.config.Config;
+import org.apache.oodt.cas.pushpull.config.DaemonInfo;
+import org.apache.oodt.cas.pushpull.config.RemoteSpecs;
+
+//JDK imports
+import java.io.File;
+import java.lang.management.ManagementFactory;
+import java.rmi.registry.LocateRegistry;
+import java.util.LinkedList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//JMX imports
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class DaemonLauncher implements DaemonLauncherMBean {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(DaemonLauncher.class
+            .getName());
+
+    private Config config;
+
+    private RemoteSpecs rs;
+
+    private int rmiRegistryPort;
+
+    private int nextDaemonId;
+
+    private DaemonManager dm;
+
+    private LinkedList<Daemon> activeDaemonList;
+
+    private LinkedList<File> sitesFiles;
+
+    private File propertiesFile;
+
+    private MBeanServer mbs;
+
+    public DaemonLauncher(int rmiRegistryPort, File propertiesFile,
+            LinkedList<File> sitesFiles) {
+        this.rmiRegistryPort = rmiRegistryPort;
+        nextDaemonId = 0;
+        dm = new DaemonManager();
+        activeDaemonList = new LinkedList<Daemon>();
+        this.sitesFiles = sitesFiles;
+        this.propertiesFile = propertiesFile;
+        registerJMX();
+        this.configure();
+    }
+
+    private void registerJMX() {
+        try {
+            LocateRegistry.createRegistry(this.rmiRegistryPort);
+            mbs = ManagementFactory.getPlatformMBeanServer();
+            ObjectName name = new ObjectName(
+                    "org.apache.oodt.cas.pushpull.daemon:type=DaemonLauncher"
+                            + this.rmiRegistryPort);
+            mbs.registerMBean(this, name);
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE,
+                    "Failed to register DaemonLauncher as a MBean Object : "
+                            + e.getMessage());
+        }
+    }
+
+    private synchronized void configure() {
+        try {
+            LOG.log(Level.INFO, "Configuring DaemonLauncher. . .");
+            config = new Config();
+            config.loadConfigFile(propertiesFile);
+            rs = new RemoteSpecs();
+            for (File sitesFile : sitesFiles) {
+                LOG
+                        .log(Level.INFO, "Loading SiteInfo file '" + sitesFile
+                                + "'");
+                rs.loadRemoteSpecs(sitesFile);
+            }
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, "Failed to configure DaemonLauncher : "
+                    + e.getMessage());
+        }
+    }
+
+    public synchronized void launchDaemons() {
+        LOG.log(Level.INFO, "Launching Daemons . . .");
+        for (DaemonInfo daemonInfo : rs.getDaemonInfoList()) {
+            int curDaemonID = this.getNextDaemonId();
+            try {
+                Daemon daemon = new Daemon(this.rmiRegistryPort, curDaemonID,
+                        this.config, daemonInfo, rs.getSiteInfo());
+                LOG.log(Level.INFO, "Creating Daemon with ID = " + curDaemonID);
+                daemon.registerDaemonListener(dm);
+                daemon.startDaemon();
+                activeDaemonList.add(daemon);
+            } catch (Exception e) {
+                LOG.log(Level.SEVERE, "Failed to create Daemon with ID = "
+                        + curDaemonID + " : " + e.getMessage());
+            }
+        }
+    }
+
+    private synchronized int getNextDaemonId() {
+        while (this.dm.getUsedIDs().contains(++this.nextDaemonId))
+            ;
+        return this.nextDaemonId;
+    }
+
+    public void refreshDaemons() {
+        this.killAllDaemons();
+
+        LOG.log(Level.INFO, "Refreshing Daemons . . .");
+        this.configure();
+        launchDaemons();
+    }
+
+    public synchronized void killAllDaemons() {
+        LOG.log(Level.INFO, "Killing current Daemons . . .");
+        this.nextDaemonId = 0;
+        for (Daemon daemon : this.activeDaemonList) {
+            if (!daemon.getHasBeenToldToQuit())
+                daemon.quit();
+        }
+        activeDaemonList.clear();
+    }
+
+    public String[] viewDaemonWaitingList() {
+        return this.dm.getQueueList();
+    }
+
+    public synchronized void quit() {
+        this.killAllDaemons();
+        this.notify();
+    }
+
+    public static void main(String[] args) {
+
+        int rmiRegPort = -1;
+        File propertiesFile = null;
+        LinkedList<File> sitesFiles = new LinkedList<File>();
+
+        for (int i = 0; i < args.length; ++i) {
+            if (args[i].equals("--rmiRegistryPort"))
+                rmiRegPort = Integer.parseInt(args[++i]);
+            else if (args[i].equals("--propertiesFile"))
+                propertiesFile = new File(args[++i]);
+            else if (args[i].equals("--remoteSpecsFile"))
+                sitesFiles.add(new File(args[++i]));
+        }
+
+        DaemonLauncher daemonLauncher = new DaemonLauncher(rmiRegPort,
+                propertiesFile, sitesFiles);
+
+        daemonLauncher.launchDaemons();
+        synchronized (daemonLauncher) {
+            try {
+                daemonLauncher.wait();
+            } catch (Exception e) {
+            }
+        }
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonLauncherMBean.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonLauncherMBean.java
new file mode 100644
index 0000000..cfb637b
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonLauncherMBean.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.daemon;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public interface DaemonLauncherMBean {
+
+    public void killAllDaemons();
+
+    public void refreshDaemons();
+
+    public void quit();
+
+    public String[] viewDaemonWaitingList();
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonListener.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonListener.java
new file mode 100644
index 0000000..b90dfd0
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonListener.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.daemon;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public interface DaemonListener {
+
+    public void wasRegisteredWith(Daemon daemon);
+
+    public void wasUnregisteredWith(Daemon daemon);
+
+    public void daemonStarting(Daemon daemon);
+
+    public void daemonFinished(Daemon daemon);
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonMBean.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonMBean.java
new file mode 100644
index 0000000..646e6cb
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonMBean.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.daemon;
+
+//JDK imports
+import java.io.File;
+import java.util.Date;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public interface DaemonMBean {
+
+    /**
+     * Will terminate the CrawlDaemon. If its Crawler is crawling a site when
+     * this method is called, the terminate won't take place until after the
+     * Crawler has complete crawling that site.
+     * 
+     * @return
+     */
+    public void quit();
+
+    /**
+     * Can be used to determine if Crawler is presently running
+     * 
+     * @return true if Crawler is runnning
+     * @uml.property name="isRunning"
+     */
+    public boolean isRunning();
+
+    public boolean getHasBeenToldToQuit();
+
+    public long getTimeIntervalInMilliseconds();
+
+    public long getEpsilonInMilliseconds();
+
+    public boolean getRunOnReboot();
+
+    public Date getFirstRunDateTime();
+
+    public String[] downloadedFilesInStagingArea();
+
+    public String[] downloadingFilesInStagingArea();
+
+    public int numberOfFilesDownloadedInStagingArea();
+
+    public int numberOfFilesDownloadingInStagingArea();
+
+    public String getDataFilesRemoteSite();
+
+    public String getDataFilesRenamingConv();
+
+    public boolean getDeleteDataFilesFromServer();
+
+    public String getQueryMetadataElementName();
+
+    public File getDataFilesStagingArea();
+
+    public boolean getAllowAliasOverride();
+
+    public String getPropertyFilesRemoteSite();
+
+    public String getPropertyFilesRenamingConv();
+
+    public boolean getDeletePropertyFilesFromServer();
+
+    public String getPropertyFilesOnSuccessDir();
+
+    public String getPropertyFilesOnFailDir();
+
+    public File getPropertyFilesLocalDir();
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonManager.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonManager.java
new file mode 100644
index 0000000..33d9acf
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonManager.java
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.daemon;
+
+//JDK imports
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class DaemonManager implements DaemonListener {
+
+    private LinkedList<Daemon> waitingList;
+
+    private HashSet<Integer> usedIDs;
+
+    private Daemon runningDaemon;
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(DaemonManager.class
+            .getName());
+
+    public DaemonManager() {
+        waitingList = new LinkedList<Daemon>();
+        usedIDs = new HashSet<Integer>();
+        runningDaemon = null;
+    }
+
+    public synchronized boolean hasRunningDaemons() {
+        return this.waitingList.size() > 0 || this.runningDaemon != null;
+    }
+
+    public synchronized void clearWaitingList() {
+        this.waitingList.clear();
+    }
+
+    public synchronized void wasRegisteredWith(Daemon daemon) {
+        this.usedIDs.add(new Integer(daemon.getDaemonID()));
+    }
+
+    public synchronized void wasUnregisteredWith(Daemon daemon) {
+        this.usedIDs.remove(new Integer(daemon.getDaemonID()));
+    }
+
+    public void daemonStarting(Daemon daemon) {
+        if (!this.setAsRunning(daemon)) {
+            daemon.pauseDaemon();
+        }
+    }
+
+    public void daemonFinished(Daemon daemon) {
+        if (daemon.equals(this.runningDaemon))
+            this.startNextOnWaitingList();
+        else
+            this.waitingList.remove(daemon);
+    }
+
+    public synchronized HashSet<Integer> getUsedIDs() {
+        return this.usedIDs;
+    }
+
+    private synchronized boolean setAsRunning(Daemon daemon) {
+        if (runningDaemon == null) {
+            runningDaemon = daemon;
+            LOG.log(Level.INFO, "Daemon with ID = " + daemon.getDaemonID()
+                    + " was given permission to run");
+            return true;
+        } else {
+            LOG.log(Level.INFO, "Daemon with ID = " + daemon.getDaemonID()
+                    + " was added to the DaemonManager's waiting list");
+            waitingList.add(daemon);
+            return false;
+        }
+    }
+
+    private synchronized void startNextOnWaitingList() {
+        if (waitingList.size() > 0) {
+            runningDaemon = waitingList.removeFirst();
+            LOG.log(Level.INFO, "Daemon with ID = "
+                    + runningDaemon.getDaemonID()
+                    + " was given permission to run");
+            runningDaemon.resume();
+        } else {
+            runningDaemon = null;
+        }
+    }
+
+    public synchronized String[] getQueueList() {
+        String[] queue = new String[this.waitingList.size()];
+        int counter = 0;
+        for (Daemon daemon : this.waitingList) {
+            queue[counter++] = daemon.getName();
+        }
+        return queue;
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonRmiInterface.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonRmiInterface.java
new file mode 100644
index 0000000..45a5416
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/daemon/DaemonRmiInterface.java
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.daemon;
+
+//JDK imports
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public interface DaemonRmiInterface extends Remote {
+
+    /**
+     * Wakes up the CrawlDaemon if it is sleeping
+     * 
+     * @return Always true -- done because of XmlRpc communication
+     */
+    public void resume() throws RemoteException;
+
+    /**
+     * Will terminate the CrawlDaemon. If its Crawler is crawling a site when
+     * this method is called, the terminate won't take place until after the
+     * Crawler has complete crawling that site.
+     * 
+     * @return
+     */
+    public void quit() throws RemoteException;
+
+    /**
+     * Can be used to determine if Crawler is presently running
+     * 
+     * @return true if Crawler is runnning
+     * @uml.property name="isRunning"
+     */
+    public boolean isRunning() throws RemoteException;
+
+    /**
+     * Average runtime for the Crawler
+     * 
+     * @return average runtime for the Crawler
+     */
+    public long getAverageRunTime() throws RemoteException;
+
+    /**
+     * Gets the total crawling time of the Crawler
+     * 
+     * @return Total crawling time of Crawler
+     */
+    public long getMillisCrawling() throws RemoteException;
+
+    /**
+     * Gets the time between the start of Crawler executions
+     * 
+     * @return Time interval between Crawler start times
+     */
+    public long getTimeInterval() throws RemoteException;
+
+    /**
+     * Gets the total number of times the Crawler has been run
+     * 
+     * @return The number of times Crawler has run
+     */
+    public int getNumCrawls() throws RemoteException;
+
+    /**
+     * Gets the time in milliseconds for when the CrawlDaemon constructor was
+     * invoked.
+     * 
+     * @return
+     * @uml.property name="daemonCreationTime"
+     */
+    public long getDaemonCreationTime() throws RemoteException;
+
+    public boolean getHasBeenToldToQuit() throws RemoteException;
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/AlreadyInDatabaseException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/AlreadyInDatabaseException.java
new file mode 100644
index 0000000..988a2f5
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/AlreadyInDatabaseException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class AlreadyInDatabaseException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = 5268322663053758675L;
+
+    public AlreadyInDatabaseException() {
+        super();
+    }
+
+    public AlreadyInDatabaseException(String msg) {
+        super(msg);
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ConfigException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ConfigException.java
new file mode 100644
index 0000000..508444c
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ConfigException.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class ConfigException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = 2756721958068217752L;
+
+    public ConfigException() {
+        super();
+    }
+
+    public ConfigException(String message) {
+        super(message);
+    }
+
+    public ConfigException(String message, Throwable t) {
+      super(message, t);
+  }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/CrawlDaemonException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/CrawlDaemonException.java
new file mode 100644
index 0000000..245f81f
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/CrawlDaemonException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class CrawlDaemonException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = 4813134079371402218L;
+
+    public CrawlDaemonException() {
+        super();
+    }
+
+    public CrawlDaemonException(String message) {
+        super(message);
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/CrawlerException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/CrawlerException.java
new file mode 100644
index 0000000..96d3579
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/CrawlerException.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class CrawlerException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = 6812263687830031390L;
+
+    public CrawlerException() {
+        super();
+    }
+
+    public CrawlerException(String msg) {
+        super(msg);
+    }
+
+    public CrawlerException(String msg, Throwable t) {
+      super(msg, t);
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/FileRestrictionsException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/FileRestrictionsException.java
new file mode 100644
index 0000000..72beffa
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/FileRestrictionsException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class FileRestrictionsException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = 2429807743624154441L;
+
+    public FileRestrictionsException() {
+        super();
+    }
+
+    public FileRestrictionsException(String msg) {
+        super(msg);
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/MetExtractorException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/MetExtractorException.java
new file mode 100644
index 0000000..b85d48f
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/MetExtractorException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class MetExtractorException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = -5075869090098570091L;
+
+    public MetExtractorException() {
+        super();
+    }
+
+    public MetExtractorException(String msg) {
+        super(msg);
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/MethodException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/MethodException.java
new file mode 100644
index 0000000..bc7d933
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/MethodException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class MethodException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = -8717114929851891812L;
+
+    public MethodException() {
+        super();
+    }
+
+    public MethodException(String msg) {
+        super(msg);
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ParserException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ParserException.java
new file mode 100644
index 0000000..30df44a
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ParserException.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class ParserException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = 4654971837246731057L;
+
+    public ParserException() {
+        super();
+    }
+
+    public ParserException(String msg) {
+        super(msg);
+    }
+    
+    public ParserException(String msg, Throwable t) {
+      super(msg, t);
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ProtocolDeletionError.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ProtocolDeletionError.java
new file mode 100644
index 0000000..15eda47
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ProtocolDeletionError.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class ProtocolDeletionError extends ProtocolException {
+
+    private static final long serialVersionUID = 2209601187397273414L;
+
+    public ProtocolDeletionError() {
+        super();
+    }
+
+    public ProtocolDeletionError(String msg) {
+        super(msg);
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ProtocolException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ProtocolException.java
new file mode 100644
index 0000000..5d23fb6
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ProtocolException.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class ProtocolException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = -5585263924925230711L;
+
+    public ProtocolException() {
+        super();
+    }
+
+    public ProtocolException(String msg) {
+        super(msg);
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ProtocolFileException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ProtocolFileException.java
new file mode 100644
index 0000000..cc2b9ac
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ProtocolFileException.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class ProtocolFileException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = 5518075265972710679L;
+
+    public ProtocolFileException() {
+        super();
+    }
+
+    public ProtocolFileException(String msg) {
+        super(msg);
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/PushPullFrameworkException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/PushPullFrameworkException.java
new file mode 100644
index 0000000..511bea8
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/PushPullFrameworkException.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ *
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class PushPullFrameworkException extends Exception {
+
+    private static final long serialVersionUID = 1500358666243383567L;
+
+    public PushPullFrameworkException() {
+        super();
+    }
+
+    public PushPullFrameworkException(String msg) {
+        super(PushPullFrameworkException.addCallingClassToMsg(msg));
+    }
+
+    public PushPullFrameworkException(String msg, Throwable t) {
+       super(PushPullFrameworkException.addCallingClassToMsg(msg), t);
+    }
+
+    private static String addCallingClassToMsg(String msg) {
+        try {
+            Throwable stack = new Throwable();
+            stack.fillInStackTrace();
+            String[] splitName = stack.getStackTrace()[3].getClassName().split(
+                    "\\.");
+            return "[" + splitName[splitName.length - 1] + "] " + msg;
+        } catch (Exception e) {
+            return "[Unknown] " + msg;
+        }
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/RemoteConnectionException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/RemoteConnectionException.java
new file mode 100644
index 0000000..b9d5c5c
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/RemoteConnectionException.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ *
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class RemoteConnectionException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = -8694907817201161502L;
+
+    public RemoteConnectionException() {
+        super();
+    }
+
+    public RemoteConnectionException(String msg) {
+        super(msg);
+    }
+
+    public RemoteConnectionException(String msg, Throwable t) {
+       super(msg, t);
+   }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/RetrievalMethodException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/RetrievalMethodException.java
new file mode 100644
index 0000000..914ee15
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/RetrievalMethodException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class RetrievalMethodException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = 310484176199522L;
+
+    public RetrievalMethodException() {
+        super();
+    }
+
+    public RetrievalMethodException(String msg) {
+        super(msg);
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ThreadEvaluatorException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ThreadEvaluatorException.java
new file mode 100644
index 0000000..194230e
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ThreadEvaluatorException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class ThreadEvaluatorException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = 1974215121420264162L;
+
+    public ThreadEvaluatorException() {
+        super();
+    }
+
+    public ThreadEvaluatorException(String msg) {
+        super(msg);
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ToManyFailedDownloadsException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ToManyFailedDownloadsException.java
new file mode 100644
index 0000000..961cb4b
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/ToManyFailedDownloadsException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class ToManyFailedDownloadsException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = -5603700192543496505L;
+
+    public ToManyFailedDownloadsException() {
+        super();
+    }
+
+    public ToManyFailedDownloadsException(String msg) {
+        super(msg);
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/UndefinedTypeException.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/UndefinedTypeException.java
new file mode 100644
index 0000000..e853ee8
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/exceptions/UndefinedTypeException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class UndefinedTypeException extends PushPullFrameworkException {
+
+    private static final long serialVersionUID = -5217518860967878598L;
+
+    public UndefinedTypeException() {
+        super();
+    }
+
+    public UndefinedTypeException(String msg) {
+        super(msg);
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/GlobalVariables.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/GlobalVariables.java
new file mode 100644
index 0000000..5750550
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/GlobalVariables.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.expressions;
+
+//JDK imports
+import java.util.HashMap;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class GlobalVariables {
+
+    public static final HashMap<String, Variable> hashMap = new HashMap<String, Variable>();
+
+    private GlobalVariables() {
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/Method.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/Method.java
new file mode 100644
index 0000000..b536dc0
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/Method.java
@@ -0,0 +1,298 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.expressions;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.exceptions.MethodException;
+
+//JDK imports
+import java.util.LinkedList;
+import java.util.Stack;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class Method {
+
+    private String name;
+
+    private String infix;
+
+    private LinkedList<Variable> args;
+
+    private LinkedList<String> argNames;
+
+    private LinkedList<Integer> argTypes;
+
+    public final int INT = 0;
+
+    public final int STRING = 1;
+
+    public Method(String name) {
+        this.name = name;
+        args = new LinkedList<Variable>();
+        argNames = new LinkedList<String>();
+        argTypes = new LinkedList<Integer>();
+    }
+
+    public void addArgSignature(String name, int type) {
+        argNames.add(name);
+        argTypes.add(new Integer(type));
+    }
+
+    public boolean addArg(String name, String value) {
+        int nextLoc = args.size();
+        if (nextLoc >= 0) {
+            switch (argTypes.get(nextLoc).intValue()) {
+            case INT:
+                addArg(new Variable(null, new Integer(value)));
+                break;
+            case STRING:
+                addArg(new Variable(null, value));
+                break;
+            default:
+                return false;
+            }
+            return true;
+        } else
+            return false;
+    }
+
+    public void addArg(Variable v) {
+        args.addLast(v);
+    }
+
+    public void setBehavoir(String infix) {
+        this.infix = infix;
+    }
+
+    private LinkedList<ValidInput> convert(String infix) throws MethodException {
+        try {
+            LinkedList<ValidInput> output = new LinkedList<ValidInput>();
+            Stack<ValidInput> stack = new Stack<ValidInput>();
+            char[] infixArray = infix.toCharArray();
+            for (int i = 0; i < infixArray.length; i++) {
+                char c = infixArray[i];
+                // System.out.println("Next C = " + c);
+                switch (c) {
+                case '$':
+                    StringBuffer variable = new StringBuffer("");
+                    boolean globalVar = false;
+
+                    // skip $ by incr i and if true then variable is a global
+                    // variable and skip '{' by incr i again
+                    if (infixArray[++i] == '{') {
+                        globalVar = true;
+                        i++;
+                    }
+
+                    for (; i < infixArray.length; i++) {
+                        char ch = infixArray[i];
+                        // System.out.println("ch = " + ch);
+                        if ((ch <= 'Z' && ch >= 'A')
+                                || (ch <= 'z' && ch >= 'a')
+                                || (ch <= '9' && ch >= '0') || ch == '_')
+                            variable.append(ch);
+                        else
+                            break;
+                    }
+
+                    if (globalVar) {
+                        try {
+                            output.addLast(GlobalVariables.hashMap.get(variable
+                                    .toString()));
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                    } else {
+                        i--;
+                        output.addLast(args.get(argNames.indexOf(variable
+                                .toString())));
+                    }
+                    // System.out.println(output);
+                    break;
+                case '#':
+                    StringBuffer variableIntString = new StringBuffer("");
+                    int k = i + 1;
+                    for (; k < infixArray.length; k++) {
+                        char ch = infixArray[k];
+                        if (ch <= '9' && ch >= '0')
+                            variableIntString.append(ch);
+                        else
+                            break;
+                    }
+                    output.addLast(new Variable(null, new Integer(
+                            variableIntString.toString())));
+                    i = k - 1;
+                    break;
+                case '"':
+                    StringBuffer variableString = new StringBuffer("");
+                    int l = i + 1;
+                    for (; l < infixArray.length; l++) {
+                        char ch = infixArray[l];
+                        if (ch != '"')
+                            variableString.append(ch);
+                        else
+                            break;
+                    }
+                    output
+                            .addLast(new Variable(null, variableString
+                                    .toString()));
+                    i = l;
+                    break;
+                case '+':
+                case '-':
+                case '/':
+                case '*':
+                    // System.out.println("operators");
+                    while (!stack.empty()
+                            && hasHigherPrecedence(stack.peek().toString()
+                                    .charAt(0), c)) {
+                        output.addLast(stack.pop());
+                    }
+                    stack.push(new Operator(c + ""));
+                    // System.out.println("Stack: " + stack);
+                    break;
+                case ')':
+                    while (!stack.empty()) {
+                        ValidInput vi = stack.pop();
+                        if (vi.toString().charAt(0) == '(')
+                            break;
+                        output.addLast(vi);
+                    }
+                    break;
+                case '(':
+                    stack.push(new Punctuation(c + ""));
+                    break;
+
+                }
+            }
+            while (!stack.empty())
+                output.addLast(stack.pop());
+
+            return output;
+        } catch (Exception e) {
+            throw new MethodException("Failed to convert infix to postfix : "
+                    + e.getMessage());
+        }
+    }
+
+    public Object execute() throws MethodException {
+        try {
+            Stack<ValidInput> stack = new Stack<ValidInput>();
+            LinkedList<ValidInput> postfix = convert(infix);
+            for (ValidInput vi : postfix) {
+                if (vi instanceof Variable) {
+                    stack.push(vi);
+                } else if (vi instanceof Operator) {
+                    ValidInput first = stack.pop();
+                    ValidInput second = stack.pop();
+                    switch (vi.toString().charAt(0)) {
+                    case '+':
+                        if (((Variable) first).isString()
+                                || ((Variable) second).isString()) {
+                            String value = second.toString() + first.toString();
+                            stack.push(new Variable(null, value));
+                        } else if (((Variable) first).isInteger()
+                                && ((Variable) second).isInteger()) {
+                            Integer value = new Integer(((Integer) second
+                                    .getValue()).intValue()
+                                    + ((Integer) first.getValue()).intValue());
+                            stack.push(new Variable(null, value));
+                        } else {
+                            throw new MethodException(
+                                    "Invalid Concatination/Addition types. . .must be String or Integer");
+                        }
+                        break;
+                    case '-':
+                        if (((Variable) first).isInteger()
+                                && ((Variable) second).isInteger()) {
+                            Integer value = new Integer(((Integer) second
+                                    .getValue()).intValue()
+                                    - ((Integer) first.getValue()).intValue());
+                            stack.push(new Variable(null, value));
+                        } else {
+                            throw new MethodException(
+                                    "Invalid Subtraction types. . .must be Integer");
+                        }
+                        break;
+                    case '*':
+                        if (((Variable) first).isInteger()
+                                && ((Variable) second).isInteger()) {
+                            Integer value = new Integer(((Integer) second
+                                    .getValue()).intValue()
+                                    * ((Integer) first.getValue()).intValue());
+                            stack.push(new Variable(null, value));
+                        } else {
+                            throw new MethodException(
+                                    "Invalid Multiplication types. . .must be Integer");
+                        }
+                        break;
+                    case '/':
+                        if (((Variable) first).isInteger()
+                                && ((Variable) second).isInteger()
+                                && ((Integer) ((Variable) first).getValue())
+                                        .intValue() > 0) {
+                            Integer value = new Integer(((Integer) second
+                                    .getValue()).intValue()
+                                    / ((Integer) first.getValue()).intValue());
+                            stack.push(new Variable(null, value));
+                        } else {
+                            throw new MethodException(
+                                    "Invalid Division types. . .must be Integer and denominator must be greater than 0");
+                        }
+                        break;
+                    }
+                }
+            }
+            return stack.pop().getValue();
+        } catch (Exception e) {
+            throw new MethodException("Failed to execute method " + name
+                    + " : " + e.getMessage());
+        }
+    }
+
+    // does first have higher precedence than second
+    private boolean hasHigherPrecedence(char first, char second) {
+        switch (first) {
+        case '+':
+        case '-':
+            switch (second) {
+            case '+':
+            case '-':
+                return true;
+            }
+            return false;
+        case '*':
+        case '/':
+            return true;
+        }
+        return false;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/Operator.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/Operator.java
new file mode 100644
index 0000000..d6f16a9
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/Operator.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.expressions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class Operator implements ValidInput {
+
+    private String value;
+
+    public Operator(String value) {
+        this.value = value;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    public String toString() {
+        return value;
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/Punctuation.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/Punctuation.java
new file mode 100644
index 0000000..fb108ad
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/Punctuation.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.expressions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class Punctuation implements ValidInput {
+
+    private String value;
+
+    public Punctuation(String value) {
+        this.value = value;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    public String toString() {
+        return value;
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/ValidInput.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/ValidInput.java
new file mode 100644
index 0000000..50657fb
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/ValidInput.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.expressions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public interface ValidInput {
+
+    public Object getValue();
+
+    public String toString();
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/Variable.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/Variable.java
new file mode 100644
index 0000000..38828b9
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/expressions/Variable.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.expressions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class Variable implements ValidInput {
+
+    private String name;
+
+    private Object value;
+
+    private int fillSide;
+
+    private String fillString;
+
+    private int precision;
+
+    private int type;
+
+    public final int FILL_FRONT = 0;
+
+    public final int FILL_BACK = 1;
+
+    public final int TYPE_STRING = 2;
+
+    public final int TYPE_INTEGER = 3;
+
+    public Variable(String name) {
+        this(name, null);
+    }
+
+    public Variable(String name, Object value) {
+        this.name = name;
+        this.value = value;
+        fillSide = FILL_FRONT;
+        fillString = " ";
+        precision = -1;
+    }
+
+    public boolean isString() {
+        if (value instanceof String)
+            return true;
+        return false;
+    }
+
+    public boolean isInteger() {
+        if (value instanceof Integer)
+            return true;
+        return false;
+    }
+
+    public void setValue(Object value) {
+        this.value = value;
+        if (value instanceof String) {
+            type = TYPE_STRING;
+        } else if (value instanceof Integer) {
+            type = TYPE_INTEGER;
+        }
+    }
+
+    public void setPrecision(int precision) {
+        this.precision = precision;
+    }
+
+    public void setFillString(String fillString) {
+        this.fillString = fillString;
+    }
+
+    public void setFillSide(int fillSide) {
+        this.fillSide = fillSide;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    public int getPrecision() {
+        return precision;
+    }
+
+    public String getFillString() {
+        return fillString;
+    }
+
+    public int getFillSide() {
+        return fillSide;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String toString() {
+        String strValue = value.toString();
+        if (strValue.length() < this.precision) {
+            while (strValue.length() < this.precision) {
+                if (fillSide == FILL_FRONT) {
+                    strValue = fillString + strValue;
+                } else {
+                    strValue = strValue + fillString;
+                }
+            }
+        }
+        return strValue;
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/FileRestrictions.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/FileRestrictions.java
new file mode 100644
index 0000000..df84929
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/FileRestrictions.java
@@ -0,0 +1,521 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.filerestrictions;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.protocol.ProtocolPath;
+
+//JDK imports
+import java.io.InputStream;
+import java.util.LinkedList;
+
+
+/**
+ * This class allows the creation of restrictions for files and directories created below an actual directory which is passed
+ * into the constructor.  These restriction are loaded by passing a FileInputStream which contains a XML File
+ * into the {@link #loadRestrictions(InputStream)} method and can be tested against by using the {@link #isAllowed(VirtualFile)} method.
+ * 
+ * <pre>
+ * The XML file schema is:
+ *	{@literal <root>
+ *	   <variables>
+ *	      <variable name="variable-name">
+ *	         <type>INT-or-STRING</type>
+ *	         <value>variable-value</value>
+ *	         <precision>
+ *	            <locations>number-of-fill-locations</locations>
+ *	            <fill>fill-value</fill>
+ *	            <side>front-or-back</side>
+ *	         </precision>
+ *	      </variable>
+ *	      ...
+ *	      ...
+ *	   </variables>
+ *
+ *	   <methods>
+ *	      <method name="method-name">
+ *	         <args>
+ *	            <arg name="argument-name">
+ *	               <type>INT-or-STRING</type>
+ *	            </arg>
+ *	            ...
+ *	            ...
+ *	         </args>
+ *	         <action>method-behavior</action>
+ *	      </method>
+ *	      ...
+ *	      ...
+ *	   </methods>
+ *   
+ *	   <dirstruct name="root-directory-name">
+ *	      <nodirs/>
+ *	      <nofiles/>
+ *	      <file name="file-name"/>
+ *	      <dir name="directory-name">
+ *	         <nodirs/>
+ *	         <nofiles/>
+ *	         <file name="file-name"/>
+ *	         <dir name="directory-name">
+ *	            ...
+ *	            ...
+ *	         </dir>
+ *	      </dir>
+ *	      ...
+ *	      ...
+ *	   </dirstruct>
+ *	</root>}
+ * </pre>
+ *
+ * <i>{@literal <variables>}</i> and <i>{@literal <methods>}</i> can be created in this XML file so that they can be used in the <i>{@literal <dirstruct>}</i>
+ * portion of the XML file.  These <i>{@literal <variables>}</i> and <i>{@literal <methods>}</i> can be used inside the <i>{@literal <dir>}</i> and
+ * <i>{@literal <file>}</i> elements within the <i>{@literal <dirstruct>}</i> element to allow for varrying directory and file names beyond the capability
+ * of regular expressions (which are also allowed).  
+ * 
+ * <h2>VARIABLES (OPTIONAL):</h2>
+ * Let's start with describing the <i>{@literal <variables>}</i> portion of the XML file.  As many <i>{@literal <variable>}</i> elements as you would like
+ * can be specified inside the <i>{@literal <variables>}</i> tag.  The <i>{@literal <variable>}</i> element must have a parameter, 'name', which is the name
+ * of this <i>{@literal <variable>}</i>.  Every <i>{@literal <variable>}</i> is a global variable (that is, global in the scope of the XML file it is declared
+ * in -- it is not usable in other XML file, unless redeclared) so variable names are unique (however, are case sensitive) so thus a name can only
+ * be applied to one <i>{@literal <variable>}</i>.  Within the <i>{@literal <variable>}</i> element there are three possible sub-elements that can be included.
+ * <i>{@literal <type>}</i> and <i>{@literal <value>}</i> are required and <i>{@literal <precision>}</i> is optional.  <i>{@literal <type>}</i> can be either (and it must be
+ * in all UPPERCASE) INT or STRING (sorry, floating point numbers are not supported as of yet).  This specifies what type of value will be given in 
+ * <i>{@literal <value>}</i>.  This allows you to both use numerical values as either an integer or a string.  <i>{@literal <precision>}</i> can also be specified
+ * for each <i>{@literal <variable>}</i>.  This allows you to insure that an integer or string will take up a certain amount of space.  This is especially
+ * useful when dealing with dates.  For instance, say you had the following in your XML file: 
+ * 
+ * <pre>
+ *	{@literal <variable name="myVariable">
+ *	   <type>INT</type>
+ *	   <value>3</value>
+ *	</variable>}
+ * </pre>
+ *
+ * When myVariable was finally returned it would look like 3, however many times for dates you would like 03 returned.  You can specify this by adding
+ * precision to the following XML:
+ *
+ * <pre>
+ *	{@literal <variable name="myVariable">
+ *	   <type>INT</type>
+ *	   <value>3</value>
+ *	   <precision>
+ *	      <locations>2</locations>
+ *	      <fill>0</fill>
+ *	      <side>front</side>
+ *	   </precision>
+ *	</variable>}
+ * </pre>
+ *
+ * This insures that the number is always printed with 2 digits and if the number does not take up 2 digits worth of space a fill value 0 will be added
+ * to the front side of the integer, thus, in this example would give us 03.  Note: <i>{@literal <value>03</value>}</i> would NOT accomplish the same!!!!
+ * 
+ * <h2>METHODS (OPTIONAL):</h2>
+ * Next let's look at the <i>{@literal <methods>}</i> portion of the XML file.  <i>{@literal <method>}</i> elements must have a 'name' parameter, which is the name of the
+ * <i>{@literal <method>}</i>.  Every <i>{@literal <method>}</i> is also global in the same way as is every <i>{@literal <variable>}</i> and are also case-sensitive, thus method 
+ * names must be unique.  A <i>{@literal <method>}</i> element may contain an <i>{@literal <args>}</i> sub-element, however this is optional and only needed if the method
+ * is to take any arguments.  If an <i>{@literal <args>}</i> element is given, then it should contain at least one <i>{@literal <arg>}</i> element.  A <i>{@literal <method>}</i>
+ * may contain as many <i>{@literal <arg>}</i> elements as it needs.  What is being specified by a <i>{@literal <method>}</i> element is what would be known in java code 
+ * as the method signature.  Thus all we are going to specify is each argument's name and type.  Thus each <i>{@literal <arg>}</i> element must contain
+ * a 'name' parameter, which is the name of the argument and must contain a <i>{@literal <type>}</i> sub-element, so it is known how to treat the arguments when 
+ * the method is used within the <i>{@literal <dirstruct>}</i> section of the XML file.  Another sub-element, which is required, for the <i>{@literal <method>}</i>
+ * element is the <i>{@literal <action>}</i> element.  This element contains the behavior of the <i>{@literal <method>}</i>.  Before going into detail about what can be
+ * placed within the <i>{@literal <action>}</i> element let's first cover some syntax requirements for the XML file.
+ * 
+ * <h2>SYNTAX REQUIREMENTS:</h2>
+ * When a <i>{@literal <variable>}</i> is used it must be preceded by $ and inclosed in {} (e.g. ${myVariable}).<br>
+ * When a <i>{@literal <method>}</i> is used it must be preceded by % and end with () (e.g. %myMethod(), however if arguments are given then %myMethod(12,9)).<br>
+ * When a <i>{@literal <method>}</i> argument (<i>{@literal <arg>}</i> element) is used is must be preceded by $ (e.g. $myArg).<br>
+ * When a literal integer is used it must be preceded by # (e.g. #234).<br>
+ * When a literal string is used it must be inclosed in " (e.g. "my age is 56 -- no not really").<br>
+ *	
+ *	<p>NOTE: When passing arguments into methods the string and integer literal rules do not need to be followed because you have already defined what each
+ *	   argument type should be and they will be evaluated as such.</p>
+ *	<p>NOTE*: Also note that at present a <i>{@literal <variable>}</i> cannot be passed as an argument to the methods.  Just use the <i>{@literal <variable>}</i> where needed
+ *	   inside the <i>{@literal <action>}</i> element.  This feature should hopefully be added in a later release.</p>
+ *
+ * <h2>METHOD'S ACTION ELEMENT USAGE:</h2>
+ * The <i>{@literal <action>}</i> element will evaluate expressions that contain both integers and strings.  It obeys the rules of mathematical precedence and will
+ * also handle parentheses.  It also, like Java, still follows the order of precedence when strings are present.  That is, if you have the expression:<br>
+ * &nbsp&nbsp	<i>#2+#4+" years old, going on "+#2+#4</i><br>
+ * It would evaluate to:<br>
+ * &nbsp&nbsp	<i>6 years old, going on 24</i><br>
+ * You may use any <i>{@literal <variable>}</i> declared within the same XML file and may also use any argument (<i>{@literal <arg>}</i> element) declared within that 
+ * <i>{@literal <method>}</i>.  Also string and integer literals may be used.  Currently the only operators supported are +,-,*,/ (which are respectively:
+ * addition, subtraction, multiplication, and division).  Parentheses, (), and embedded parentheses, (()()), are also all allowed.
+ * 
+ * <h2>DIRSTRUCT:</h2>
+ * The final section of the XML file is the actual main purpose of the XML file.  This is the XML that controls which directories the crawler will be allowed
+ * to crawl and which files will be allowed.  The <i>{@literal <dirstruct>}</i> element requires a 'name' parameter which is the path to the root
+ * directory that is to be considered (that is, all other directories below the given directory are unimportant and will not be crawled).  You want your root
+ * directory path to stop at the first directory in which you are interested in more than one of its sub-directories or want file(s) inside it.
+ * For example, let say we want to crawl a remote site that has the following directory structure:
+ * 
+ * <pre>
+ *	-parent
+ *	   -child1
+ *	      -grandChild1
+ *	         -greatGrandChild1
+ *              -file1
+ *	         -greatGrandChild2
+ *	      -grandChild2
+ *	      -file1
+ *	   -child2 
+ *	      -file1
+ * 	   -child3
+ * 	      -file1
+ *	      -file2
+ * 	      -grandChild1
+ * 	         -file1
+ *	         -file2
+ * 	   -child4
+ * </pre>
+ * 
+ * Now, say, we only are interested in directories and files below the two shown 'grandChild1' directories.  This would mean that for our <i>{@literal <dirstruct>}</i>
+ * 'name' parameter we would put name="parent".  This is because we need access to both 'child1' and 'child3' subdirectories.  Now in order to avoid crawling
+ * 'child2' and 'child4' directories we have to specify <i>{@literal <dir>}</i> elements.  This would give us the following XML:
+ * 
+ * <pre>
+ * 	{@literal <dirstruct name="/parent">
+ *	   <dir name="child1"/>
+ *	   <dir name="child3"/>
+ *	</dirstruct>}
+ * </pre>
+ *
+ * This would restrict the directories allowed under 'parent' to only be directories with names either 'child1' or 'child3', all other directory names will
+ * be rejected.  However, more must be added to this example because we have not yet specified any restrictions on files allowed beneath 'parent',
+ * we have to add the <i>{@literal <nofiles/>}</i> element:
+ * 
+ * <pre>
+ *	{@literal <dirstruct name="/parent">}
+ *	   <i><b>{@literal <nofiles/>}</b></i>
+ *	   {@literal <dir name="child1"/>
+ *	   <dir name="child3"/>
+ *	</dirstruct>} 
+ * </pre>
+ *
+ * Now the only thing acceptable below parent is 'child1' and 'child3'.  We have to still further our restrictions under 'child1' and 'child3'.  Since under 
+ * 'child1' we only want 'grandChild1' we would have to make another <i>{@literal <dir>}</i> element and also add a <i>{@literal <nofiles/>}</i> element:
+ * 
+ * <pre>
+ *	{@literal <dirstruct name="/parent">
+ *	   <nofiles/>
+ *	   <dir name="child1">}
+ *	      <i><b>{@literal <nofiles/>
+ *	      <dir name="grandChild1"/>}</b></i>
+ *	   {@literal </dir>
+ *	   <dir name="child3"/>
+ *	</dirstruct>}  
+ * </pre>
+ * 
+ * We have to do the same also for 'child3', giving us:
+ * 
+ * <pre>
+ *	{@literal <dirstruct name="/parent">
+ *	   <nofiles/>
+ *	   <dir name="child1">
+ *	      <nofiles/>
+ *	      <dir name="grandChild1"/>
+ *	   </dir>
+ *	   <dir name="child3">}
+ *	      <i><b>{@literal <nofiles/>
+ *	      <dir name="grandChild1"/>}</b></i>
+ *	   {@literal </dir>
+ *	</dirstruct>}  
+ * </pre>
+ *
+ * From the example directory structure above, with this XML file specified, that directory structure would be limited to:
+ * 
+ * <pre>
+ *	-parent
+ *	   -child1
+ *	      -grandChild1
+ *	         -greatGrandChild1
+ *              -file1
+ *	         -greatGrandChild2
+ * 	   -child3
+ * 	      -grandChild1
+ * 	         -file1
+ *	         -file2
+ * </pre>
+ * 
+ * Say we now decide that we only want files below the two 'grandChild1' directories -- that is, no directories.  So we would change or XML by adding 
+ * in the <i>{@literal <nodir/>}</i> element:
+ * 
+ * <pre>
+ *	{@literal <dirstruct name="/parent">
+ *	   <nofiles/>
+ *	   <dir name="child1">
+ *	      <nofiles/>
+ *	      <dir name="grandChild1">}
+ *	          <i><b>{@literal <nodirs/>}</b></i>
+ *	      {@literal </dir>
+ *	   </dir>
+ *	   <dir name="child3">
+ *	      <nofiles/>
+ *	      <dir name="grandChild1">}
+ *	         <i><b>{@literal <nodirs/>}</b></i>
+ *	      {@literal </dir>
+ *	   </dir>
+ *	</dirstruct>}   
+ * </pre>
+ *
+ * Which now restricts our directory structure to:
+ * 
+ * <pre>
+ *	-parent
+ *	   -child1
+ *	      -grandChild1
+ * 	   -child3
+ * 	      -grandChild1
+ * 	         -file1
+ *	         -file2
+ * </pre>
+ * 
+ * Let's further specify now that we only want 'file1' in the '/parent/child3/grandChild1' directory.  This would change the XML to:
+ * 
+ * <pre>
+ *	{@literal <dirstruct name="/parent">
+ *	   <nofiles/>
+ *	   <dir name="child1">
+ *	      <nofiles/>
+ *	      <dir name="grandChild1">
+ *	          <nodirs/>
+ *	      </dir>
+ *	   </dir>
+ *	   <dir name="child3">
+ *	      <nofiles/>
+ *	      <dir name="grandChild1">
+ *	         <nodirs/>}
+ *	         <i><b>{@literal <file name="file1"/>}</b></i>
+ *	      {@literal </dir>
+ *	   </dir>
+ *	</dirstruct>}
+ * </pre>
+ *
+ * Our new allowed directory structure would now be:
+ * 
+ * <pre>
+ *	-parent
+ *	   -child1
+ *	      -grandChild1
+ * 	   -child3
+ * 	      -grandChild1
+ * 	         -file1
+ * </pre>
+ * 
+ *	NOTES:
+ * 	-You would not want to use the <i>{@literal <nofiles/>}</i> and <i>{@literal <file>}</i> elements in the same directory (same goes for the
+ * 	   <i>{@literal <nodirs/>}</i> and <i>{@literal <dir>}</i> elements) because you would be specifying that you don't want any files in that
+ * 	   directory, and then contradict yourself by specifying a <i>{@literal <file>}</i> element that is okay to have.  The <i>{@literal <file>}</i> 
+ *	   element states that no other file but the file I specified is allowed.  The only exception is if you have two or more <i>{@literal <file>}</i> 
+ *	   elements in the same directory -- this is allowed.  It follows the same rules as the <i>{@literal <dir>}</i> element in the example 
+ *	   given above where only 'child1' and 'child3' were allow.  The two don't cancel each other out. 
+ * 
+ * <h2>ADVANCED USAGES OF DIRSTRUCT:</h2>
+ * Regular expressions are allowed in the 'name' parameter of both <i>{@literal <dir>}</i> and <i>{@literal <file>}</i> elements.  Also any 
+ * <i>{@literal <method>}</i> or <i>{@literal <variable>}</i> element declared can be used within the 'name' parameter of both <i>{@literal <dir>}</i> 
+ * and <i>{@literal <file>}</i> elements.  There are also several predefined variables that can be used.
+ * 
+ * <h4>REGULAR EXPRESSIONS:</h4>
+ * The regular expressions are parsed by the <a href=http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html>Pattern</a> class 
+ * (See its documentation on rule for specifying regular expressions).  Here is an example use of a regular expression:
+ * 
+ * <pre>
+ *	{@literal <dirstruct name="/.../temp/test">
+ *	   <nofiles/>
+ *	   <dir name="\d{4}-\d{2}-\d{2}">
+ *	      <nodirs/>
+ *	   </dir>
+ *	</dirstruct>}
+ * </pre>
+ *
+ * This would restrict the directory files in directories below /.../temp/test to only directories whose names are dates of the
+ * format: YYYY-MM-DD.
+ * 
+ * <h4>PREDEFINED DATE VARIABLES:</h4>
+ * There are several predefined date variables than can be put as the <i>{@literal <value>}</i> of a <i>{@literal <variable>}</i> and then used.
+ * 
+ * These variables are:
+ * <pre>
+ * 	[DATE.DAY]	- day of today's date
+ * 	[DATE.MONTH]	- month of today's date
+ * 	[DATE.YEAR]	- year of today's date
+ * 	[DATE-N.DAY]	- the day of the date N days ago
+ * 	[DATE-N.MONTH]	- the month of the date N days ago
+ * 	[DATE-N.YEAR]	- the year of the date N days ago
+ * 	[DATE+N.DAY]	- the day of the date N days from now
+ * 	[DATE+N.MONTH]	- the month of the date N days from now
+ * 	[DATE+N.YEAR]	- the year of the date N days from now
+ * 
+ * 	-sorry, no DayOfYear implemented yet -- hopefully in a later release
+ * </pre>
+ * 
+ * Usage:
+ * <pre>
+ * 	{@literal <root>
+ * 	   <variables>
+ * 	      <variable name="todaysDay">
+ * 	         <type>INT</type>
+ * 	         <value>[DATE.DAY]</value>
+ *	         <precision>
+ *	            <locations>2</locations>
+ *	            <fill>0</fill>
+ *	            <side>front</side>
+ *	         </precision>
+ *	      </variable>
+ *	   </variabls>
+ *	   <dirstruct name="/path/to/parent/dir">
+ *	      <nofiles/>
+ *	      <dir name="MyFiles">
+ *	         <nodirs/>
+ *	         <file name="MyPaper_${todaysDay}"/>
+ *	      </dir>
+ *	   </dirstruct>
+ *	</root>}
+ *  </pre>
+ *  
+ *  This would allow only a file in /path/to/parent/dir/MyFiles which had the name which started with MyPaper_ and ended with the
+ *  day of the current day of the month.  For example, if to days date was 03/23/2005, then the file name allowed would be
+ *  MyPaper_23.
+ * 
+ * <h4>METHOD AND VARIABLE USAGE IN DIRSTRUCT:</h4>
+ * Here is an example of using <i>{@literal <variables>}</i> and <i>{@literal <methods>}</i>:
+ * 
+ * <pre>
+ *	{@literal <root>
+ *	   <variables>
+ *	      <variable name="DAY">
+ *	         <type>INT</type>
+ *	         <value>[DATE.DAY]</value>
+ *	         <precision>
+ *	            <locations>2</locations>
+ *	            <fill>0</fill>
+ *	            <side>front</side>
+ *	         </precision>
+ *	      </variable>
+ *	      <variable name="MONTH">
+ *	         <type>INT</type>
+ *	         <value>[DATE.MONTH]</value>
+ *	         <precision>
+ *	            <locations>2</locations>
+ *	            <fill>0</fill>
+ *	            <side>front</side>
+ *	         </precision>
+ *	      </variable>
+ *	      <variable name="YEAR">
+ *	         <type>INT</type>
+ *	         <value>[DATE.YEAR]</value>
+ *	      </variable>
+ *	   </variables>
+ *   
+ *	   <methods>
+ *	      <method name="ADD">
+ *	         <args>
+ *	            <arg name="1">
+ *	               <type>INT</type>
+ *	            </arg>
+ *	         </args>
+ *	         <action>"THE_YEAR_PLUS_"+$1+": "+(${YEAR}+$1)</action>
+ *	      </method>
+ *	      <method name="HOW_OLD_AM_I">
+ *	         <action>${YEAR}-#1984</action>
+ *	      </method>
+ *	      <method name="DATE">
+ *	         <action>${YEAR}+"-"+${MONTH}+"-"+${DAY}</action>
+ *	      </method>
+ *	   </methods>
+ *
+ *	   <dirstruct name="/path/to/parent/dir">
+ *	      <nofiles/>
+ *	      <dir name="AGE_%HOW_OLD_AM_I()"/>
+ *	      <dir name="DATE">
+ *	         <nodirs/>
+ *	         <file name="%ADD(5)"/>
+ *	      </dir>
+ *	   </dirstruct>
+ *	</root>}
+ * </pre>
+ *
+ * This would accept only the directories under /path/to/parent/dir which had the name (given today is 9/7/2007) 'AGE_23' or '2007-09-07'.
+ * This would allow any file or directory in under 'AGE_23', but would only allow a file with the name 'THE_YEAR_PLUS_5: 2012' in the 
+ * directory '2007-09-07'.
+ *  
+ * 
+ * @author bfoster
+ *
+ */
+public class FileRestrictions {
+
+    private FileRestrictions() throws InstantiationException{
+        throw new InstantiationException("Don't construct FileRestrictions!");
+    }
+
+    /**
+     * 
+     * @param path
+     * @return The initial cd directory which needs to be changed to (in order
+     *         to take care of possible auto-mounted directories)
+     */
+    public static boolean isAllowed(ProtocolPath path, VirtualFile root) {
+        return (isValidPath(path) && isAllowed(new VirtualFile(path
+                .getPathString(), path.isDirectory()), root));
+    }
+
+    public static boolean isAllowed(VirtualFile file, VirtualFile root) {
+        boolean vfDoesNotExist = false, lastFileIsDir = file.isDir();
+        VirtualFile vf = null;
+        while ((vf = root.getChildRecursive(file)) == null) {
+            vfDoesNotExist = true;
+            lastFileIsDir = file.isDir();
+            file = file.getParentFile();
+            if (file == null)
+                break;
+        }
+        return !(file == null || (vfDoesNotExist && ((lastFileIsDir && !vf
+                .allowNewDirs()) || (!lastFileIsDir && !vf.allowNewFiles()))));
+    }
+
+    private static boolean isValidPath(ProtocolPath path) {
+        if (path != null && !path.getFileName().equals(".")
+                && !path.getFileName().equals("..")) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public static LinkedList<String> toStringList(VirtualFile root) {
+        LinkedList<String> stringList = new LinkedList<String>();
+        stringList.addAll(toStringList(root.getChildren(), ""));
+        return stringList;
+    }
+
+    private static LinkedList<String> toStringList(
+            LinkedList<VirtualFile> children, String curPath) {
+        LinkedList<String> stringList = new LinkedList<String>();
+        for (VirtualFile child : children) {
+            String currentPath = curPath + "/" + child.getRegExp();
+            if (!child.isDir())
+                stringList.add(currentPath);
+            else
+                stringList
+                        .addAll(toStringList(child.getChildren(), currentPath));
+        }
+        return stringList;
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/Parser.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/Parser.java
new file mode 100644
index 0000000..20a8b9a
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/Parser.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.filerestrictions;
+
+//JDK imports
+import java.io.FileInputStream;
+
+
+import org.apache.oodt.cas.metadata.Metadata;
+//OODT imports
+import org.apache.oodt.cas.pushpull.exceptions.ParserException;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public interface Parser {
+
+    public VirtualFileStructure parse(FileInputStream inputFile, Metadata metadata)
+            throws ParserException;
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/VirtualFile.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/VirtualFile.java
new file mode 100644
index 0000000..68849e6
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/VirtualFile.java
@@ -0,0 +1,295 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.filerestrictions;
+
+//JDK imports
+import java.util.LinkedList;
+import java.util.StringTokenizer;
+import java.util.regex.Pattern;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class VirtualFile {
+
+    private String regExp;
+
+    private LinkedList<VirtualFile> children;
+
+    private VirtualFile parent;
+
+    private boolean noDirs;
+
+    private boolean noFiles;
+
+    private boolean isDir;
+
+    private boolean allowNewFiles;
+
+    private boolean allowNewDirs;
+
+    private VirtualFile(boolean isDir) {
+        this.isDir = isDir;
+        children = new LinkedList<VirtualFile>();
+        noDirs = noFiles = !isDir;
+        allowNewFiles = allowNewDirs = isDir;
+    }
+
+    public VirtualFile(String path, boolean isDir) {
+        this(isDir);
+
+        if (path != null) {
+            StringTokenizer st = new StringTokenizer(path, "/");
+
+            if (st.countTokens() > 1) {
+                VirtualFile vf = path.startsWith("/") ? VirtualFile
+                        .createRootDir()
+                        : new VirtualFile(st.nextToken(), true);
+                String curRegExp = st.nextToken();
+
+                while (st.hasMoreTokens()) {
+                    VirtualFile temp = new VirtualFile(curRegExp, true);
+                    vf.addChild(temp);
+                    vf = temp;
+                    curRegExp = st.nextToken();
+                }
+                this.regExp = curRegExp;
+                vf.addChild(this);
+            } else if (st.countTokens() > 0) {
+                this.regExp = st.nextToken();
+                if (path.startsWith("/"))
+                    VirtualFile.createRootDir().addChild(this);
+            } else {
+                this.copy(VirtualFile.createRootDir());
+            }
+        } else
+            this.copy(VirtualFile.createRootDir());
+    }
+
+    public VirtualFile(VirtualFile root, String path, boolean isDir) {
+        this(isDir);
+
+        if (path != null) {
+            StringTokenizer st = new StringTokenizer(path, "/");
+
+            if (st.countTokens() > 0) {
+                VirtualFile vf = root;
+                String curRegExp = st.nextToken();
+
+                while (st.hasMoreTokens()) {
+                    VirtualFile temp = new VirtualFile(curRegExp, true);
+                    vf.addChild(temp);
+                    vf = temp;
+                    curRegExp = st.nextToken();
+                }
+                this.regExp = curRegExp;
+                vf.addChild(this);
+            } else
+                this.copy(root);
+        } else
+            this.copy(root);
+    }
+
+    public static VirtualFile createRootDir() {
+        VirtualFile root = new VirtualFile(true);
+        root.regExp = "/";
+        return root;
+    }
+
+    public VirtualFile getRootDir() {
+        VirtualFile vf = this;
+        while (vf.getParentFile() != null)
+            vf = vf.getParentFile();
+        return vf;
+    }
+
+    public static VirtualFile mergeTwoFiles(VirtualFile vf1, VirtualFile vf2) {
+        if (vf1.isDir && vf1.isDir) {
+            VirtualFile newFile = VirtualFile.createRootDir();
+            newFile.children.addAll(vf1.children);
+            newFile.children.addAll(vf2.children);
+            return newFile;
+        } else
+            return null;
+    }
+
+    public void addChild(VirtualFile vf) {
+        if (this.isDir) {
+            VirtualFile existingChildWithSameName = this.getChild(vf.regExp,
+                    vf.isDir);
+            if (existingChildWithSameName == null) {
+                children.add(vf);
+                if (vf.isDir())
+                    allowNewDirs = false;
+                else
+                    allowNewFiles = false;
+                vf.parent = this;
+            } else {
+                vf.copy(existingChildWithSameName);
+            }
+        }
+    }
+
+    public LinkedList<VirtualFile> getChildren() {
+        return children;
+    }
+
+    public VirtualFile getChild(String regExp, boolean isDirectory) {
+        for (VirtualFile vf : children) {
+            // System.out.println("GETCHILD: " + regExp + " " + vf.regExp);
+            if ((regExp.equals(vf.regExp) || Pattern.matches(vf.regExp, regExp))
+                    && vf.isDir == isDirectory)
+                return vf;
+        }
+        return null;
+    }
+
+    public VirtualFile getChildRecursive(VirtualFile vf) {
+        return this.getChildRecursive(vf.getAbsolutePath(), vf.isDir);
+    }
+
+    public VirtualFile getChildRecursive(String path, boolean isDirectory) {
+        StringTokenizer st = new StringTokenizer(path, "/");
+        VirtualFile vf = this;
+        while (st.hasMoreTokens()) {
+            String curRegExp = st.nextToken();
+            if (st.hasMoreTokens()) {
+                if ((vf = vf.getChild(curRegExp, true)) == null)
+                    return null;
+            } else {
+                return vf.getChild(curRegExp, isDirectory);
+            }
+        }
+        return null;
+    }
+
+    public boolean hasChild(VirtualFile vf) {
+        if (children.contains(vf))
+            return true;
+        return false;
+    }
+
+    public String getAbsolutePath() {
+        if (regExp == null)
+            return null;
+        StringBuffer path = new StringBuffer(this.regExp);
+        VirtualFile parent = this.parent;
+        while (parent != null) {
+            path.insert(0, (parent.regExp != "/" ? parent.regExp : "") + "/");
+            parent = parent.parent;
+        }
+        return path.toString();
+    }
+
+    public VirtualFile getParentFile() {
+        return parent;
+    }
+
+    public String getRegExp() {
+        return regExp;
+    }
+
+    public void setNoDirs(boolean noDirs) {
+        if (this.isDir) {
+            if (noDirs)
+                allowNewDirs = false;
+            this.noDirs = noDirs;
+        }
+    }
+
+    public void setNoFiles(boolean noFiles) {
+        if (this.isDir) {
+            if (noFiles)
+                allowNewFiles = false;
+            this.noFiles = noFiles;
+        }
+    }
+
+    public boolean allowNewDirs() {
+        return allowNewDirs;
+    }
+
+    public boolean allowNewFiles() {
+        return allowNewFiles;
+    }
+
+    public boolean allowNoDirs() {
+        return noDirs;
+    }
+
+    public boolean allowNoFiles() {
+        return noFiles;
+    }
+
+    public boolean isDir() {
+        return isDir;
+    }
+
+    public void copy(VirtualFile vf) {
+        this.allowNewDirs = vf.allowNewDirs;
+        this.allowNewFiles = vf.allowNewFiles;
+        this.children = vf.children;
+        this.isDir = vf.isDir;
+        this.noDirs = vf.noDirs;
+        this.noFiles = vf.noFiles;
+        this.parent = vf.parent;
+        this.regExp = vf.regExp;
+    }
+
+    // TODO: make it compare against all variables
+    public boolean equals(Object obj) {
+        if (obj instanceof VirtualFile) {
+            VirtualFile compareFile = (VirtualFile) obj;
+            if (compareFile.getRegExp().equals(regExp)
+                    && compareFile.isDir() == this.isDir)
+                return true;
+        }
+        return false;
+    }
+
+    public String toString() {
+        StringBuffer sb = new StringBuffer(
+                "-<VirtualFile>\t : allowNewDirs/noDirs\t : allowNewFiles/noFiles\n------------\n");
+        LinkedList<VirtualFile> printFiles = new LinkedList<VirtualFile>();
+        printFiles.add(this);
+        sb.append(printVirtualFiles(printFiles, "-"));
+        return sb.toString();
+    }
+
+    private StringBuffer printVirtualFiles(LinkedList<VirtualFile> list,
+            String spacer) {
+        StringBuffer output = new StringBuffer("");
+        for (VirtualFile vf : list) {
+            output.append(spacer);
+            output.append(vf.getRegExp()
+                    + (vf.isDir && !vf.regExp.equals("/") ? "/" : "") + "\t : "
+                    + vf.allowNewDirs + "/" + vf.noDirs + "\t\t : "
+                    + vf.allowNewFiles + "/" + vf.noFiles + "\n");
+            output.append(printVirtualFiles(vf.getChildren(), " " + spacer));
+        }
+        return output;
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/VirtualFileStructure.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/VirtualFileStructure.java
new file mode 100644
index 0000000..cca4983
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/VirtualFileStructure.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.filerestrictions;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.protocol.RemoteSite;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class VirtualFileStructure {
+
+    private String pathToRoot;
+
+    private VirtualFile root;
+
+    private RemoteSite remoteSite;
+
+    public VirtualFileStructure(String pathToRoot, VirtualFile root) {
+        this.pathToRoot = pathToRoot;
+        this.root = root;
+    }
+
+    public VirtualFileStructure(RemoteSite remoteSite, String pathToRoot,
+            VirtualFile root) {
+        this(pathToRoot, root);
+        this.remoteSite = remoteSite;
+    }
+
+    public String getPathToRoot() {
+        return this.pathToRoot;
+    }
+
+    public VirtualFile getRootVirtualFile() {
+        return this.root;
+    }
+
+    public RemoteSite getRemoteSite() {
+        return this.remoteSite;
+    }
+
+    public boolean isRootBased() {
+        return this.pathToRoot.startsWith("/");
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/parsers/ClassNoaaEmailParser.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/parsers/ClassNoaaEmailParser.java
new file mode 100644
index 0000000..348cd24
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/parsers/ClassNoaaEmailParser.java
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.filerestrictions.parsers;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.pushpull.filerestrictions.Parser;
+import org.apache.oodt.cas.pushpull.filerestrictions.VirtualFile;
+import org.apache.oodt.cas.pushpull.filerestrictions.VirtualFileStructure;
+import org.apache.oodt.cas.pushpull.protocol.RemoteSite;
+import org.apache.oodt.cas.pushpull.exceptions.ParserException;
+
+
+//JDK imports
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.Scanner;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class ClassNoaaEmailParser implements Parser {
+
+    public ClassNoaaEmailParser() {}
+
+    public VirtualFileStructure parse(FileInputStream emailFile, Metadata metadata)
+            throws ParserException {
+        try {
+            VirtualFile root = VirtualFile.createRootDir();
+            Scanner s = new Scanner(emailFile);
+            StringBuffer sb = new StringBuffer("");
+            while (s.hasNextLine())
+                sb.append(s.nextLine() + "\n");
+
+            if (!validEmail(sb.toString()))
+                throw new ParserException(
+                        "Email not a IASI data processed notification email");
+
+            Pattern cdPattern = Pattern.compile("\\s*cd\\s{1,}.{1,}?(?:\\s|$)");
+            Matcher cdMatcher = cdPattern.matcher(sb);
+            Pattern getPattern = Pattern.compile("\\s*get\\s{1,}.{1,}?(?:\\s|$)");
+            Matcher getMatcher = getPattern.matcher(sb);
+            
+            VirtualFile vf = null;
+            while (cdMatcher.find() && getMatcher.find()) {
+                String cdCommand = sb.substring(cdMatcher.start(), cdMatcher.end());
+                String directory = cdCommand.trim().split(" ")[1];
+
+                vf = new VirtualFile(root, directory, true);
+                vf.setNoDirs(true);
+
+                String getCommand = sb.substring(getMatcher.start(), getMatcher.end());
+                String file = getCommand.trim().split(" ")[1];
+
+                if (file.endsWith("*")) {
+                    vf.addChild(new VirtualFile(file.substring(0,
+                            file.length() - 1), false));
+                    vf.addChild(new VirtualFile(file.substring(0,
+                            file.length() - 1)
+                            + ".sig", false));
+                } else {
+                    vf.addChild(new VirtualFile(file, false));
+                }
+            }
+
+            Pattern ftpPattern = Pattern.compile("\\sftp\\..*?\\s");
+            Matcher ftpMatcher = ftpPattern.matcher(sb);
+            RemoteSite remoteSite = null;
+            if (ftpMatcher.find()) {
+                String ftpSite = sb.substring(ftpMatcher.start(), ftpMatcher.end()).trim();
+                remoteSite = new RemoteSite(null, new URL("ftp://"
+                        + ftpSite), "anonymous", System
+                        .getenv("user.name")
+                        + "@jpl.nasa.gov");
+            }
+
+            return new VirtualFileStructure(remoteSite, "/", root);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new ParserException("Failed to parse IASI email : "
+                    + e.getMessage());
+        }
+    }
+
+    private boolean validEmail(String email) {
+        String[] containsStrings = (System.getProperties()
+                .getProperty("org.apache.oodt.cas.pushpull.filerestrictions.parsers.class.noaa.email.parser.contains.exprs")
+                + ",").split(",");
+        for (String containsString : containsStrings)
+            if (!email.contains(containsString))
+                return false;
+        return true;
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/parsers/DirStructXmlParser.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/parsers/DirStructXmlParser.java
new file mode 100644
index 0000000..63e5a6a
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/parsers/DirStructXmlParser.java
@@ -0,0 +1,348 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.filerestrictions.parsers;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.pushpull.filerestrictions.Parser;
+import org.apache.oodt.cas.pushpull.filerestrictions.VirtualFile;
+import org.apache.oodt.cas.pushpull.filerestrictions.VirtualFileStructure;
+import org.apache.oodt.cas.pushpull.exceptions.ParserException;
+import org.apache.oodt.cas.pushpull.expressions.GlobalVariables;
+import org.apache.oodt.cas.pushpull.expressions.Method;
+import org.apache.oodt.cas.pushpull.expressions.Variable;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+
+//JDK imports
+import java.io.FileInputStream;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class DirStructXmlParser implements Parser {
+
+    private static final Logger LOG = Logger.getLogger(DirStructXmlParser.class
+            .getName());
+    
+    private static final HashMap<String, Method> methodRepo = new HashMap<String, Method>();
+
+    public DirStructXmlParser() {}
+
+    public VirtualFileStructure parse(FileInputStream xmlFile, Metadata metadata)
+            throws ParserException {
+        try {
+            String initialCdDir = "/";
+            VirtualFile root = null;
+            NodeList list = (DocumentBuilderFactory.newInstance()
+                    .newDocumentBuilder().parse(new InputSource(xmlFile)))
+                    .getDocumentElement().getChildNodes();
+            VirtualFile currentFile = null;
+            for (int i = 0; i < list.getLength(); i++) {
+                Node node = list.item(i);
+                if (node.getNodeName().equals("dirstruct")) {
+
+                    // parse out starting path
+                    String startingPath = ((Element) node)
+                            .getAttribute("starting_path");
+                    if (startingPath != null) {
+                        root = (currentFile = new VirtualFile(
+                                initialCdDir = startingPath, true))
+                                .getRootDir();
+                        VirtualFile temp = currentFile.getParentFile();
+                        while (temp != null) {
+                            temp.setNoDirs(true);
+                            temp.setNoFiles(true);
+                            temp = temp.getParentFile();
+                        }
+                    } else {
+                        currentFile = root = VirtualFile.createRootDir();
+                    }
+
+                    // parse the directory structure
+                    parseDirstructXML(node.getChildNodes(), currentFile);
+
+                } else if (node.getNodeName().equals("variables")) {
+                    parseVariablesXML(node.getChildNodes());
+                } else if (node.getNodeName().equals("methods")) {
+                    parseMethodsXML(node.getChildNodes());
+                }
+            }
+            return new VirtualFileStructure(initialCdDir, root);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new ParserException("Failed to parse XML file : "
+                    + e.getMessage());
+        }
+    }
+
+    private void parseDirstructXML(NodeList list, VirtualFile currentLoadFile) {
+        for (int i = 0; i < list.getLength(); i++) {
+            Node dir = list.item(i);
+            if (dir.getNodeName().equals("dir")) {
+                String dirName = replaceVariablesAndMethods(((Element) dir)
+                        .getAttribute("name"));
+                currentLoadFile.addChild(new VirtualFile(dirName, true));
+                NodeList children;
+                if ((children = dir.getChildNodes()).getLength() > 0) {
+                    parseDirstructXML(children, currentLoadFile.getChild(
+                            dirName, true));
+                }
+            } else if (dir.getNodeName().equals("nodirs")) {
+                currentLoadFile.setNoDirs(true);
+            } else if (dir.getNodeName().equals("nofiles")) {
+                currentLoadFile.setNoFiles(true);
+            } else if (dir.getNodeName().equals("file")) {
+                VirtualFile vf = new VirtualFile(
+                        replaceVariablesAndMethods(((Element) dir)
+                                .getAttribute("name")), false);
+                vf.setNoDirs(true);
+                currentLoadFile.addChild(vf);
+            }
+        }
+    }
+
+    private String replaceVariablesAndMethods(String input) {
+        for (int i = 0; i < input.length(); i++) {
+            char c = input.charAt(i);
+            switch (c) {
+            case '$':
+                try {
+                    if (input.charAt(i + 1) == '{') {
+                        StringBuffer variable = new StringBuffer("");
+                        for (int j = i + 2; j < input.length(); j++) {
+                            char ch = input.charAt(j);
+                            if ((ch <= 'Z' && ch >= 'A')
+                                    || (ch <= 'z' && ch >= 'a')
+                                    || (ch <= '9' && ch >= '0') 
+                                    || ch == '_')
+                                variable.append(ch);
+                            else
+                                break;
+                        }
+                        Variable v = GlobalVariables.hashMap.get(variable
+                                .toString());
+                        if (v == null)
+                        	throw new Exception("No variable defined with name '" + variable.toString() + "'");
+                        input = input.replaceFirst("\\$\\{" + variable + "\\}", v.toString());
+                        i = i + v.toString().length();
+                    }
+                } catch (Exception e) {
+                	LOG.log(Level.WARNING, "Failed to replace variable in '" + input + " for i = '" + i + "' : " + e.getMessage(), e);
+                }
+                break;
+            case '%':
+                try {
+                    StringBuffer method = new StringBuffer("");
+                    int j = i + 1;
+                    for (; j < input.length(); j++) {
+                        char ch = input.substring(j, j + 1).charAt(0);
+                        if ((ch <= 'Z' && ch >= 'A')
+                                || (ch <= 'z' && ch >= 'a')
+                                || (ch <= '9' && ch >= '0') || ch == '_')
+                            method.append(ch);
+                        else
+                            break;
+                    }
+
+                    if (input.substring(j, j + 1).charAt(0) == '(') {
+                        Method m = methodRepo.get(method.toString());
+                        StringTokenizer st = new StringTokenizer(input
+                                .substring(j, input.substring(j).indexOf(")")
+                                        + j), "#\", ()");
+                        while (st.hasMoreTokens()) {
+                            String arg = st.nextToken();
+                            m.addArg(null, arg);
+                        }
+                        String returnValue = m.execute().toString();
+                        input = input.substring(0, i)
+                                + returnValue
+                                + input.substring(input.substring(i).indexOf(
+                                        ")")
+                                        + 1 + i);
+                        i = i + returnValue.length();
+                    } else {
+                        LOG.log(Level.SEVERE, "Invalid method signature in "
+                                + input + " near " + method);
+                        break;
+                    }
+                } catch (Exception e) {
+                }
+                break;
+            }
+        }
+        return input;
+    }
+
+    private void parseVariablesXML(NodeList list) throws DOMException, Exception {
+
+        // loop through all variable elements
+        for (int i = 0; i < list.getLength(); i++) {
+            Node node = list.item(i);
+
+            // parse variable element
+            if (node.getNodeName().equals("variable")) {
+                NodeList children = node.getChildNodes();
+
+                // create Variable Object
+                String variableName = ((Element) node).getAttribute("name");
+                Variable variable = new Variable(variableName);
+
+                // loop through to fill Variable
+                String type = null, value = null;
+                for (int j = 0; j < children.getLength(); j++) {
+                    Node child = children.item(j);
+
+                    // get the Variable's name
+                    if (child.getNodeName().equals("type")) {
+                        type = XMLUtils.getSimpleElementText((Element) child,
+                                true).toLowerCase();
+
+                        // get the Variable's value
+                    } else if (child.getNodeName().equals("value")) {
+                        value = PathUtils.doDynamicReplacement(XMLUtils
+                                .getSimpleElementText((Element) child, false));
+
+                        // get the Variable's value's precision infomation
+                    } else if (child.getNodeName().equals("precision")) {
+                        NodeList grandChildren = child.getChildNodes();
+                        for (int k = 0; k < grandChildren.getLength(); k++) {
+                            Node grandChild = grandChildren.item(k);
+                            // get the precision
+                            if (grandChild.getNodeName().equals("locations")) {
+                                variable.setPrecision(Integer.parseInt(XMLUtils
+                                        .getSimpleElementText((Element) grandChild, true)));
+                                // get the fill character to meet the precision
+                                // [optional]
+                            } else if (grandChild.getNodeName().equals("fill")) {
+                                variable.setFillString(
+                                    XMLUtils.getSimpleElementText((Element) grandChild, false));
+                                // get the side for which the fill character
+                                // will be applied [optional]
+                            } else if (grandChild.getNodeName().equals("side")) {
+                                variable.setFillSide(
+                                        (XMLUtils.getSimpleElementText((Element) grandChild, true)
+                                            .toLowerCase().equals("front")) 
+                                                ? variable.FILL_FRONT
+                                                : variable.FILL_BACK);
+                            }
+                        }
+                    }
+                }
+                // determine if variable is an Integer or a String
+                if (type.equals("int")) {
+                    variable.setValue(new Integer(value));
+                } else
+                    variable.setValue(value);
+
+                // store Variable in list of Variables
+                GlobalVariables.hashMap.put(variable.getName(), variable);
+            }
+        }
+    }
+
+    private void parseMethodsXML(NodeList list) {
+
+        // loop though all method elements
+        for (int i = 0; i < list.getLength(); i++) {
+            Node node = list.item(i);
+            // parse method element
+            if (node.getNodeName().equals("method")) {
+                NodeList children = node.getChildNodes();
+
+                // create Method Object
+                String methodName = ((Element) node).getAttribute("name");
+                Method method = new Method(methodName);
+
+                // loop through to fill Method Object
+                for (int j = 0; j < children.getLength(); j++) {
+                    Node child = children.item(j);
+
+                    // get the Method's behavoir
+                    if (child.getNodeName().equals("action")) {
+                        method.setBehavoir(XMLUtils.getSimpleElementText(
+                                (Element) child, false));
+
+                        // get the Method's arguments
+                    } else if (child.getNodeName().equals("args")) {
+                        String name, argType = null;
+                        NodeList grandChildren = child.getChildNodes();
+
+                        // loop for every arg element
+                        for (int k = 0; k < grandChildren.getLength(); k++) {
+                            Node grandChild = grandChildren.item(k);
+
+                            // parse arg element
+                            if (grandChild.getNodeName().equals("arg")) {
+                                name = ((Element) grandChild)
+                                        .getAttribute("name");
+
+                                // get arg element properties
+                                NodeList greatGrandChildren = grandChild
+                                        .getChildNodes();
+                                for (int l = 0; l < greatGrandChildren
+                                        .getLength(); l++) {
+                                    Node greatGrandChild = greatGrandChildren
+                                            .item(l);
+                                    if (greatGrandChild.getNodeName().equals(
+                                            "type")) {
+                                        argType = XMLUtils.getSimpleElementText(
+                                                (Element) greatGrandChild,
+                                                true);
+                                    }
+                                }
+
+                                // create argument signature in Method
+                                method
+                                        .addArgSignature(
+                                                name,
+                                                ((argType.toLowerCase()
+                                                        .equals("int")) ? method.INT
+                                                        : method.STRING));
+                            }
+                        }
+                    }
+                }
+
+                // store Method in list of Methods
+                methodRepo.put(method.getName(), method);
+            }
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/parsers/FileListParser.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/parsers/FileListParser.java
new file mode 100644
index 0000000..d540cf0
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/parsers/FileListParser.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.filerestrictions.parsers;
+
+//JDK imports
+import java.io.FileInputStream;
+import java.util.Scanner;
+
+
+import org.apache.oodt.cas.metadata.Metadata;
+//OODT imports
+import org.apache.oodt.cas.pushpull.exceptions.ParserException;
+import org.apache.oodt.cas.pushpull.filerestrictions.Parser;
+import org.apache.oodt.cas.pushpull.filerestrictions.VirtualFile;
+import org.apache.oodt.cas.pushpull.filerestrictions.VirtualFileStructure;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class FileListParser implements Parser {
+
+	public FileListParser() {}
+	
+    public VirtualFileStructure parse(FileInputStream inputFile, Metadata metadata)
+            throws ParserException {
+        Scanner scanner = new Scanner(inputFile);
+        VirtualFile root = VirtualFile.createRootDir();
+        String initialCdDir = "/";
+        if (scanner.hasNextLine()) {
+            initialCdDir = scanner.nextLine();
+            while (scanner.hasNextLine()) {
+                new VirtualFile(root, initialCdDir + "/" + scanner.nextLine(),
+                        false);
+            }
+        }
+        return new VirtualFileStructure(initialCdDir, root);
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/parsers/GenericEmailParser.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/parsers/GenericEmailParser.java
new file mode 100644
index 0000000..e9c6318
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/parsers/GenericEmailParser.java
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pushpull.filerestrictions.parsers;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.pushpull.filerestrictions.Parser;
+import org.apache.oodt.cas.pushpull.filerestrictions.VirtualFile;
+import org.apache.oodt.cas.pushpull.filerestrictions.VirtualFileStructure;
+import org.apache.oodt.cas.pushpull.exceptions.ParserException;
+
+//Google imports
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+//JDK imports
+import java.io.FileInputStream;
+import java.util.List;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A generic email parser which generates file paths to be downloaded by using a defined java
+ * Pattern. The pattern should specify pattern groups for file paths in the matching pattern.
+ * These groups will then be extracted and added to the file structure.
+ *
+ * @author bfoster@apache.org (Brian Foster)
+ */
+public class GenericEmailParser implements Parser {
+
+  private static final Logger log = Logger.getLogger(GenericEmailParser.class.getCanonicalName());
+
+  public static final String FILE_PATTERNS_PROPERTY_NAME =
+      "org.apache.oodt.cas.pushpull.generic.email.parser.file.pattern";
+  public static final String CHECK_FOR_PATTERN_PROPERTY_NAME =
+      "org.apache.oodt.cas.pushpull.generic.email.parser.check.for.pattern";
+  public static final String PATH_TO_ROOT_PROPERTY_NAME =
+      "org.apache.oodt.cas.pushpull.generic.email.parser.path.to.root";
+  public static final String METADATA_KEYS =
+      "org.apache.oodt.cas.pushpull.generic.email.parser.metadata.keys";
+  public static final String METADATA_KEY_PREFIX =
+      "org.apache.oodt.cas.pushpull.generic.email.parser.metadata.";      
+  
+  private final String filePattern;
+  private final String checkForPattern;
+  private final String pathToRoot;
+
+  public GenericEmailParser() {
+    filePattern = loadFilePattern();
+    checkForPattern = loadCheckForPattern();
+    pathToRoot = loadPathToRoot();
+  }
+ 
+  public GenericEmailParser(String filePattern, String checkForPattern, String pathToRoot) {
+    this.filePattern = filePattern;
+    this.checkForPattern = checkForPattern;
+    this.pathToRoot = Strings.nullToEmpty(pathToRoot);
+  }
+
+  @Override
+  public VirtualFileStructure parse(FileInputStream emailFile, Metadata metadata)
+      throws ParserException {
+    log.info("GenericEmailParser is parsing email: " + emailFile);
+
+    VirtualFile root = VirtualFile.createRootDir();
+
+    String emailText = readEmail(emailFile);
+    if (!isValidEmail(emailText)) {
+      throw new ParserException("Failed to find check for pattern in email: " + checkForPattern);
+    }
+    List<String> filePaths = generateFilePaths(emailText);
+    readMetadata(emailText, metadata);
+
+    for (String filePath : filePaths) {
+      new VirtualFile(root, pathToRoot + filePath, false);
+    }
+
+    return new VirtualFileStructure("/", root);
+  }
+
+  private String readEmail(FileInputStream emailFile) {
+    StringBuilder emailText = new StringBuilder("");
+    Scanner scanner = new Scanner(emailFile);
+    while (scanner.hasNextLine()) {
+      emailText.append(scanner.nextLine()).append("\n");
+    }
+    scanner.close();
+    return emailText.toString();
+  }
+
+  private List<String> generateFilePaths(String emailText) throws ParserException {
+    List<String> filePaths = Lists.newArrayList();
+    Pattern pattern = Pattern.compile(filePattern);
+    Matcher m = pattern.matcher(emailText);
+    if (m.find()) {
+      // Ignore index 0, as that is the matching string for pattern.
+      for (int i = 1; i <= m.groupCount(); i++) {
+        filePaths.add(m.group(i));          
+      }
+    }
+    return filePaths;
+  }
+
+  private void readMetadata(String emailText, Metadata metadata) {
+    Set<String> metadataKeys = loadMetadataKeys();
+    for (String metadataKey : metadataKeys) {
+      String metadataPattern = loadMetadataKey(metadataKey);
+      if (metadataPattern == null) {
+        log.log(Level.SEVERE, "Failed to load metadata pattern for key: " + metadataKey);
+      } else {
+        Pattern pattern = Pattern.compile(metadataPattern);
+        Matcher m = pattern.matcher(emailText);
+        if (m.find()) {
+          // Ignore index 0, as that is the matching string for pattern.
+          String metadatValue = m.group(1);
+          metadata.replaceMetadata(metadataKey, metadatValue);
+        }
+      }
+    }
+  }
+
+  private boolean isValidEmail(String emailText) {
+    Pattern pattern = Pattern.compile(checkForPattern);
+    Matcher m = pattern.matcher(emailText.replaceAll("\n", " "));
+    return m.find();
+  }
+  
+  private String loadFilePattern() {
+    return System.getProperty(FILE_PATTERNS_PROPERTY_NAME);
+  }
+  
+  private String loadCheckForPattern() {
+    return System.getProperty(CHECK_FOR_PATTERN_PROPERTY_NAME);    
+  }
+  
+  private String loadPathToRoot() {
+    return Strings.nullToEmpty(System.getProperty(PATH_TO_ROOT_PROPERTY_NAME));
+  }
+
+  private Set<String> loadMetadataKeys() {
+    return Sets.newHashSet(Splitter.on(",").omitEmptyStrings().split(
+        Strings.nullToEmpty(System.getProperty(METADATA_KEYS))));
+  }
+
+  private String loadMetadataKey(String key) {
+    return System.getProperty(METADATA_KEY_PREFIX + key);
+  }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/renamingconventions/RenamingConvention.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/renamingconventions/RenamingConvention.java
new file mode 100644
index 0000000..f2e0935
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/filerestrictions/renamingconventions/RenamingConvention.java
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.pushpull.filerestrictions.renamingconventions;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.pushpull.retrievalsystem.RemoteFile;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class RenamingConvention {
+	
+	private static Logger LOG = Logger.getLogger(RenamingConvention.class.getName());
+
+    private RenamingConvention() throws InstantiationException {
+        throw new InstantiationException("Don't construct RenamingConventions!");
+    }
+
+    /**
+     * Generates a unique file name for the given ProtocolFile
+     * 
+     * @param fileToGenNewNameFor
+     *            The file for which a unique name will be generated
+     * @return The unique file name (just the name).
+     */
+    public static String rename(RemoteFile fileToGenNewNameFor,
+            String renamingString) {
+    	try {
+    	    renamingString = grepReplace(renamingString, fileToGenNewNameFor);
+    	    renamingString = grepRemoveReplace(renamingString, fileToGenNewNameFor);
+	        renamingString = replace(renamingString, "[FILENAME]",
+	                fileToGenNewNameFor.getProtocolFile().getName());
+	        renamingString = replace(renamingString, "[PATH_NO_FILENAME]",
+	                getParentPath(fileToGenNewNameFor));
+	        renamingString = replace(renamingString, "[HOST]", fileToGenNewNameFor
+	                .getProtocolFile().getSite().getURL().getHost());
+	        renamingString = replace(renamingString, "[PARENT_FILENAME]",
+	                getParentFileName(fileToGenNewNameFor));
+	        renamingString = replace(renamingString, "[PARENT_PATH_NO_FILENAME]",
+	                getGrandParentPath(fileToGenNewNameFor));
+	        renamingString = replace(renamingString, "[URL]", fileToGenNewNameFor
+	                .getProtocolFile().getSite().getURL().toExternalForm());
+	        renamingString = replace(renamingString, "[IS_DIR]", String
+	                .valueOf(fileToGenNewNameFor.getProtocolFile().isDir()));
+	        renamingString = PathUtils.doDynamicReplacement(
+	            renamingString, fileToGenNewNameFor.getAllMetadata());
+    	}catch (Exception e) {
+    		LOG.log(Level.WARNING, "Failed to rename " + fileToGenNewNameFor 
+    				+ " : " + e.getMessage());
+    	}
+        return renamingString;
+    }
+
+    private static String grepReplace(String theString, RemoteFile fileToGenNewNameFor) {
+        Pattern grepPattern = Pattern.compile("\\[GREP\\(.*\\,.*\\)\\]");
+        Matcher grepMatcher = grepPattern.matcher(theString);
+        while (grepMatcher.find()) {
+            String origGrepString = theString.substring(grepMatcher.start(),
+                    grepMatcher.end()).trim();
+            String grepString = origGrepString.replace("[GREP('", "").replace(
+                    "')]", "").trim();
+            String[] grepStringSplit = grepString.split("','");
+            String pattern = grepStringSplit[0];
+            String string = rename(fileToGenNewNameFor, grepStringSplit[1]);
+            Pattern p = Pattern.compile(pattern);
+            Matcher m = p.matcher(string);
+            if (m.find()) {
+                theString = theString.replace(origGrepString, string.substring(
+                        m.start(), m.end()));
+            } else {
+                theString = theString.replace(origGrepString, "null");
+            }
+        }
+        return theString;
+    }
+
+    private static String grepRemoveReplace(String theString, RemoteFile fileToGenNewNameFor) {
+        Pattern grepPattern = Pattern.compile("\\[GREP_RM\\(.*,.*\\)\\]");
+        Matcher grepMatcher = grepPattern.matcher(theString);
+        while (grepMatcher.find()) {
+            String origGrepString = theString.substring(grepMatcher.start(),
+                    grepMatcher.end()).trim();
+            String grepString = origGrepString.replace("[GREP_RM('", "")
+                    .replace("')]", "").trim();
+            String[] grepStringSplit = grepString.split("','");
+            String pattern = grepStringSplit[0];
+            String string = rename(fileToGenNewNameFor, grepStringSplit[1]);
+            System.out.println("PAT_STR: " + pattern + " " + string);
+            Pattern p = Pattern.compile(pattern);
+            Matcher m = p.matcher(string);
+            if (m.find()) {
+                theString = theString.replace(origGrepString, string.replace(
+                        string.substring(m.start(), m.end()), ""));
+            } else {
+                theString = theString.replace(origGrepString, "null");
+            }
+        }
+        return theString;
+    }
+     
+    private static String replace(String theString,
+            String theValueToBeReplaced, String whatToReplaceWith) {
+        if (theValueToBeReplaced == null || theValueToBeReplaced.equals(""))
+            return theString;
+        if (whatToReplaceWith == null)
+            whatToReplaceWith = "";
+        return theString.replace(theValueToBeReplaced, whatToReplaceWith);
+    }
+
+    private static String getParentPath(RemoteFile fileToGenNewNameFor) {
+        String parentPath = "";
+        try {
+            parentPath = fileToGenNewNameFor.getProtocolFile().getParent().getPath();
+        } catch (Exception e) {
+        }
+        return parentPath;
+    }
+
+    private static String getParentFileName(RemoteFile fileToGenNewNameFor) {
+        String parentFileName = "";
+        try {
+            parentFileName = fileToGenNewNameFor.getProtocolFile().getParent().getName();
+        } catch (Exception e) {
+        }
+        return parentFileName;
+    }
+
+    private static String getGrandParentPath(RemoteFile fileToGenNewNameFor) {
+        String grandParentPath = "";
+        try {
+            grandParentPath = fileToGenNewNameFor.getProtocolFile().getParent()
+                    .getParent().getPath();
+        } catch (Exception e) {
+        }
+        return grandParentPath;
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/objectfactory/PushPullObjectFactory.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/objectfactory/PushPullObjectFactory.java
new file mode 100644
index 0000000..2e9d9af
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/objectfactory/PushPullObjectFactory.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.objectfactory;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.ingest.Cache;
+import org.apache.oodt.cas.filemgr.ingest.CacheFactory;
+import org.apache.oodt.cas.filemgr.ingest.Ingester;
+
+//JDK imports
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class PushPullObjectFactory {
+
+    private PushPullObjectFactory() throws InstantiationException {
+        throw new InstantiationException("Don't construct factory classes!");
+    }
+
+    public static <T> T createNewInstance(Class<T> clazz) throws InstantiationException {
+    	try {
+			return clazz.newInstance();
+		} catch (Exception e) {
+            throw new InstantiationException(
+                    "Failed to create new object : "
+                            + e.getMessage());
+		}
+    }
+    
+    public static Ingester createIngester(String ingesterClass,
+            String cacheFactoryClass) throws InstantiationException,
+            IllegalAccessException, ClassNotFoundException,
+            IllegalArgumentException, SecurityException,
+            InvocationTargetException, NoSuchMethodException {
+        String dataTransferFactory = System
+                .getProperty("org.apache.oodt.cas.filemgr.datatransfer.factory");
+        System.out.println("TRANSFER: " + dataTransferFactory);
+        if (cacheFactoryClass == null || cacheFactoryClass.equals("")) {
+            return (Ingester) Class.forName(ingesterClass).getConstructor(
+                    dataTransferFactory.getClass()).newInstance(
+                    dataTransferFactory);
+        } else {
+            Class<CacheFactory> cacheFactory = (Class<CacheFactory>) Class
+                    .forName(cacheFactoryClass);
+            Cache cache = cacheFactory.newInstance().createCache();
+            return (Ingester) Class.forName(ingesterClass).getConstructor(
+                    dataTransferFactory.getClass(), cache.getClass())
+                    .newInstance(dataTransferFactory, cache);
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/protocol/ProtocolHandler.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/protocol/ProtocolHandler.java
new file mode 100644
index 0000000..b1fcb83
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/protocol/ProtocolHandler.java
@@ -0,0 +1,588 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.pushpull.protocol;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFactory;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.pushpull.protocol.RemoteSiteFile;
+import org.apache.oodt.cas.pushpull.config.ProtocolInfo;
+import org.apache.oodt.cas.protocol.auth.BasicAuthentication;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+import org.apache.oodt.cas.protocol.util.ProtocolFileFilter;
+import org.apache.oodt.cas.pushpull.exceptions.RemoteConnectionException;
+
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * This class is responsible for creating the appropriate Protocol for the given
+ * RemoteSites. The boolean argument 'allowReuse' allows for one unique protocol
+ * for each URL. That is, if allowReuse is set to true, then if no Protocol has
+ * been created for the current site, the Protocol created will be saved and
+ * then returned for any later called with allowReuse equals true. This is to
+ * allow for the same Protocol object to be used by several classes. The
+ * Protocol class has been synchronized so this is thread-safe. If you set
+ * 'allowReuse' to false then a new Protocol object will be created and
+ * returned.<br>
+ * <br>
+ *
+ * @author bfoster
+ */
+public class ProtocolHandler {
+
+  private final HashMap<URL, ProtocolFactory> urlAndProtocolFactory;
+
+  private final HashMap<URL, Protocol> reuseProtocols;
+
+  private final HashMap<RemoteSiteFile, PagingInfo> pageInfos;
+
+  private final HashMap<RemoteSiteFile, List<RemoteSiteFile>> pathAndFileListMap;
+
+  private final ProtocolInfo pi;
+
+  private static final Logger LOG = Logger.getLogger(ProtocolHandler.class
+      .getName());
+
+  /**
+   * Creates a new ProtocolHandler for the given Config object
+   *
+   * @param config
+   *          The Config object that guides this ProtocolHandler in making class
+   *          instanciations
+   */
+  public ProtocolHandler(ProtocolInfo pi) {
+    this.pi = pi;
+    urlAndProtocolFactory = new HashMap<URL, ProtocolFactory>();
+    reuseProtocols = new HashMap<URL, Protocol>();
+    pageInfos = new HashMap<RemoteSiteFile, PagingInfo>();
+    pathAndFileListMap = new HashMap<RemoteSiteFile, List<RemoteSiteFile>>();
+  }
+
+  /**
+   * Returns the appropriate protocol for the given Path
+   *
+   * @param ProtocolPath
+   *          Used to determine the appropriate Protocol to be returned and the
+   *          path to navigate on if navigateToPathLoc is set to true.
+   * @param allowReuse
+   *          Set to true if you would like ProtocolHandler to take care of the
+   *          protocol returned (i.e. reuseable protocols may be returned by
+   *          this method again, if it is the appropriate protocol type for a
+   *          given Path. Also ProtocolHandler will take care of disconnecting
+   *          the reuseable protocols)
+   * @param navigateToPathLoc
+   *          If true, will navigate the to the end of the Path location
+   *          specified
+   * @return Protocol for the given Path
+   * @throws RemoteCommunicationException
+   *           If there is an error creating the protocol
+   */
+  public Protocol getAppropriateProtocol(RemoteSiteFile pFile,
+      boolean allowReuse, boolean navigateToPathLoc)
+      throws RemoteConnectionException {
+    try {
+      Protocol protocol = getAppropriateProtocol(pFile, allowReuse);
+      if (protocol != null && navigateToPathLoc) {
+        if (pFile.isDir())
+          this.cd(protocol, pFile);
+        else if (pFile.getParent() != null)
+          this.cd(protocol, new RemoteSiteFile(pFile.getParent(), pFile.getSite()));
+      }
+      return protocol;
+    } catch (Exception e) {
+      throw new RemoteConnectionException(
+          "Failed to get appropriate protocol for " + pFile + " : "
+              + e.getMessage(), e);
+    }
+  }
+
+  private Protocol getAppropriateProtocol(RemoteSiteFile pFile,
+      boolean allowReuse) throws ProtocolException, MalformedURLException {
+    return this.getAppropriateProtocolBySite(pFile.getSite(), allowReuse);
+  }
+
+  public Protocol getAppropriateProtocolBySite(RemoteSite remoteSite,
+      boolean allowReuse) throws ProtocolException {
+    Protocol protocol = null;
+    if ((allowReuse && ((protocol = reuseProtocols.get(remoteSite.getURL())) == null))
+        || !allowReuse) {
+      ProtocolFactory protocolFactory = this.urlAndProtocolFactory
+          .get(remoteSite.getURL());
+      if (protocolFactory == null) {
+        LinkedList<Class<ProtocolFactory>> protocolClasses = pi
+            .getProtocolClassesForProtocolType(remoteSite.getURL()
+                .getProtocol());
+        for (Class<ProtocolFactory> clazz : protocolClasses) {
+          try {
+            if ((protocol = (protocolFactory = clazz.newInstance())
+                .newInstance()) != null) {
+              if (!connect(protocol, remoteSite, true)) {
+                LOG.log(
+                    Level.WARNING,
+                    "ProtocolFactory "
+                        + protocolFactory.getClass().getCanonicalName()
+                        + " is not compatible with server at "
+                        + remoteSite.getURL());
+                protocol = null;
+              } else {
+                this.urlAndProtocolFactory.put(remoteSite.getURL(),
+                    protocolFactory);
+                break;
+              }
+            }
+          } catch (Exception e) {
+            LOG.log(Level.WARNING, "Failed to instanciate protocol " + clazz
+                + " for " + remoteSite.getURL());
+          }
+        }
+        if (protocol == null)
+          throw new ProtocolException("Failed to get appropriate protocol for "
+              + remoteSite);
+      } else {
+        connect(protocol = protocolFactory.newInstance(), remoteSite, false);
+      }
+      if (allowReuse)
+        this.reuseProtocols.put(remoteSite.getURL(), protocol);
+    }
+    return protocol;
+  }
+
+  public synchronized List<RemoteSiteFile> nextPage(RemoteSite site, Protocol protocol)
+      throws RemoteConnectionException, ProtocolException {
+    return nextPage(site, protocol, null);
+  }
+
+  /**
+   * @param protocol
+   * @return
+   * @throws RemoteConnectionException
+   * @throws ProtocolException
+   */
+  public synchronized List<RemoteSiteFile> nextPage(RemoteSite site, Protocol protocol,
+      ProtocolFileFilter filter) throws RemoteConnectionException,
+      ProtocolException {
+
+    PagingInfo pgInfo = this.getPagingInfo(this.pwd(site, protocol));
+    try {
+      System.out.println("PageSize: " + pi.getPageSize() + " PageLoc: "
+          + pgInfo.getPageLoc());
+      List<RemoteSiteFile> fileList = this.ls(site, protocol);
+      System.out.println("FileList size: " + fileList.size());
+
+      if (this.getDynamicFileList(site, protocol) == null
+          && !this.passesDynamicDetection(pgInfo, fileList)) {
+        LOG.log(
+            Level.SEVERE,
+            "Remote directory '"
+                + this.pwd(site, protocol)
+                + "' file list size has changed -- setting directory as dynamic and resetting page location");
+        this.putDynamicFileList(site, protocol, fileList);
+        pgInfo.updatePageInfo(0, fileList);
+      }
+
+      List<RemoteSiteFile> page = new LinkedList<RemoteSiteFile>();
+      int curLoc = pgInfo.getPageLoc();
+      for (; page.size() < pi.getPageSize() && curLoc < fileList.size(); curLoc++) {
+        if (filter == null || filter.accept(fileList.get(curLoc)))
+          page.add(fileList.get(curLoc));
+      }
+      pgInfo.updatePageInfo(curLoc, fileList);
+
+      return page;
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw new RemoteConnectionException(
+          "Failed getting next page for protocol " + protocol + "-- pgStart = "
+              + pgInfo.getPageLoc() + " pgSize = " + pi.getPageSize() + " : "
+              + e.getMessage());
+    }
+
+  }
+
+  private boolean passesDynamicDetection(PagingInfo pgInfo,
+      List<RemoteSiteFile> newLS) throws MalformedURLException,
+      ProtocolException {
+    if (pgInfo.getSizeOfLastLS() != -1
+        && (pgInfo.getSizeOfLastLS() != newLS.size() || (newLS.size() != 0
+            && pgInfo.getPageLoc() < newLS.size() && (newLS.get(pgInfo
+            .getPageLoc()) == null || !newLS.get(pgInfo.getPageLoc()).equals(
+            pgInfo.getRemoteSiteFileAtPageLoc()))))) {
+      return false;
+    } else {
+      return true;
+    }
+  }
+
+  public void download(Protocol protocol, RemoteSiteFile fromFile, File toFile,
+      boolean delete) throws RemoteConnectionException {
+
+    // rename file for download
+    File downloadFile = new File(
+        String.format("%s/Downloading_%s", toFile.getParent(), toFile.getName()));
+    toFile.renameTo(downloadFile);
+
+    LOG.log(Level.INFO, "Starting to download " + fromFile);
+    try {
+      // try to download the file
+      protocol.get(fromFile, downloadFile);
+
+      // rename file back to original name
+      if (!downloadFile.renameTo(toFile)) {
+        throw new IOException(
+            String.format("Failed to rename file %s to %s", downloadFile, toFile));
+      }
+
+      // delete file is specified
+      if (delete) {
+        if (!this.delete(protocol, fromFile))
+          LOG.log(Level.WARNING, "Failed to delete file '" + fromFile
+              + "' from server '" + fromFile.getSite() + "'");
+        else
+          LOG.log(Level.INFO, "Successfully deleted file '" + fromFile
+              + "' from server '" + fromFile.getSite() + "'");
+      }
+
+      LOG.log(Level.INFO, "Finished downloading " + fromFile + " to " + toFile);
+
+    } catch (Exception e) {
+      downloadFile.delete();
+      throw new RemoteConnectionException("Failed to download file " + fromFile
+          + " : " + e.getMessage(), e);
+    }
+  }
+
+  /**
+   * Connects the given Protocol to the given URL
+   *
+   * @param protocol
+   *          The Protocol that will be connected
+   * @param url
+   *          The server to which the Protocol will connect
+   * @throws RemoteConnectionException
+   *           If connection fails
+   * @throws RemoteLoginException
+   *           If login fails
+   */
+  public boolean connect(Protocol protocol, RemoteSite remoteSite, boolean test) {
+    for (int tries = 0; tries < 3; tries++) {
+
+      // wait for 5 secs before next retry
+      if (tries > 0) {
+        LOG.log(Level.INFO, "Will retry connecting to " + remoteSite
+            + " in 5 seconds");
+        synchronized (this) {
+          try {
+            System.out.print("Waiting");
+            for (int i = 0; i < 5; i++) {
+              System.out.print(" .");
+              wait(1000);
+            }
+            System.out.println();
+          } catch (Exception e) {
+          }
+        }
+      }
+
+      try {
+        // make sure protocol is disconnected
+        try {
+          protocol.close();
+        } catch (Exception e) {
+        }
+
+        // try connecting Protocol
+        protocol.connect(
+            remoteSite.getURL().getHost(),
+            new BasicAuthentication(remoteSite.getUsername(), remoteSite
+                .getPassword()));
+
+        // check connection
+        if (protocol.connected()
+            && (!test || isOkProtocol(protocol, remoteSite))) {
+          LOG.log(Level.INFO,
+              "Successfully connected to " + remoteSite.getURL()
+                  + " with protocol '" + protocol.getClass().getCanonicalName()
+                  + "' and username '" + remoteSite.getUsername() + "'");
+          return true;
+        } else
+          return false;
+
+      } catch (Exception e) {
+        LOG.log(Level.WARNING, "Error occurred while connecting to "
+            + remoteSite + " : " + e.getMessage(), e);
+      }
+
+    }
+    return false;
+  }
+
+  private boolean isOkProtocol(Protocol protocol, RemoteSite remoteSite) {
+    try {
+      LOG.log(Level.INFO, "Testing protocol "
+          + protocol.getClass().getCanonicalName()
+          + " . . . this may take a few minutes . . .");
+      // test ls, cd, and pwd
+      this.cdToHOME(protocol);
+      RemoteSiteFile home = this.pwd(remoteSite, protocol);
+      this.ls(remoteSite, protocol);
+      if (remoteSite.getCdTestDir() != null)
+        this.cd(protocol, new RemoteSiteFile(home, remoteSite.getCdTestDir(),
+            true, remoteSite));
+      else
+        this.cdToROOT(protocol);
+      this.cdToHOME(protocol);
+      if (home == null || !home.equals(this.pwd(remoteSite, protocol)))
+        throw new ProtocolException("Home directory not the same after cd");
+    } catch (Exception e) {
+      LOG.log(Level.SEVERE, "Protocol "
+          + protocol.getClass().getCanonicalName()
+          + " failed compatibility test : " + e.getMessage(), e);
+      return false;
+    }
+    return true;
+  }
+
+  public void cdToROOT(Protocol protocol) throws ProtocolException {
+    protocol.cdRoot();
+  }
+
+  public void cdToHOME(Protocol protocol) throws ProtocolException {
+    protocol.cdHome();
+  }
+
+  public boolean isProtocolConnected(Protocol protocol)
+      throws ProtocolException {
+    return protocol.connected();
+  }
+
+  public void cd(Protocol protocol, RemoteSiteFile file)
+      throws ProtocolException {
+    protocol.cd(file);
+  }
+
+  public RemoteSiteFile getProtocolFileFor(RemoteSite site, Protocol protocol, String file,
+      boolean isDir) throws ProtocolException {
+    return this.getProtocolFileByProtocol(site, protocol, file, isDir);
+  }
+
+  public synchronized boolean delete(Protocol protocol, RemoteSiteFile file)
+      throws MalformedURLException, ProtocolException {
+    try {
+      PagingInfo pgInfo = this.getPagingInfo(file.getRemoteParent());
+      List<RemoteSiteFile> fileList = this.ls(protocol, file.getRemoteParent());
+      int indexOfFile = fileList.indexOf(file);
+      if (indexOfFile != -1) {
+        protocol.delete(file);
+        fileList.remove(indexOfFile);
+        System.out.println("IndexOfFile: " + indexOfFile + " PageIndex: "
+            + pgInfo.getPageLoc());
+        if (indexOfFile < pgInfo.getPageLoc()
+            || indexOfFile == fileList.size() - 1)
+          pgInfo.updatePageInfo(pgInfo.getPageLoc() - 1, fileList);
+        else
+          pgInfo.updatePageInfo(pgInfo.getPageLoc(), fileList);
+        return true;
+      } else {
+        return false;
+      }
+    } catch (Exception e) {
+      LOG.log(Level.SEVERE, "Failed to delete file", e);
+      return false;
+    }
+  }
+
+  private synchronized void putPgInfo(PagingInfo pgInfo, RemoteSiteFile pFile) {
+    this.pageInfos.put(pFile, pgInfo);
+  }
+
+  private synchronized PagingInfo getPagingInfo(RemoteSiteFile pFile) {
+    PagingInfo pgInfo = this.pageInfos.get(pFile);
+    if (pgInfo == null)
+      this.putPgInfo(pgInfo = new PagingInfo(), pFile);
+    return pgInfo;
+  }
+
+  public RemoteSiteFile pwd(RemoteSite site, Protocol protocol) throws ProtocolException {
+    return new RemoteSiteFile(protocol.pwd(), site);
+  }
+
+  public List<RemoteSiteFile> ls(Protocol protocol, RemoteSiteFile dir)
+      throws ProtocolException {
+    List<RemoteSiteFile> fileList = this.getDynamicFileList(dir.getSite(), protocol);
+    if (fileList == null) {
+      protocol.cd(dir);
+      fileList = toRemoteSiteFiles(protocol.ls(), dir.getSite());
+    }
+    return fileList;
+  }
+
+  public List<RemoteSiteFile> ls(RemoteSite site, Protocol protocol) throws ProtocolException {
+    List<RemoteSiteFile> fileList = this.getDynamicFileList(site, protocol);
+    if (fileList == null)
+      fileList = toRemoteSiteFiles(protocol.ls(), site);
+    return fileList;
+  }
+
+  public List<RemoteSiteFile> ls(RemoteSite site, Protocol protocol, ProtocolFileFilter filter)
+      throws ProtocolException {
+    List<RemoteSiteFile> fileList = this.getDynamicFileList(site, protocol);
+    if (fileList == null)
+      fileList = toRemoteSiteFiles(protocol.ls(filter), site);
+    return fileList;
+  }
+
+  private synchronized List<RemoteSiteFile> getDynamicFileList(RemoteSite site, Protocol protocol)
+      throws ProtocolException {
+    return (List<RemoteSiteFile>) (List<?>) this.pathAndFileListMap.get(this
+        .pwd(site, protocol));
+  }
+
+  private synchronized void putDynamicFileList(RemoteSite site, Protocol protocol,
+      List<RemoteSiteFile> fileList) throws ProtocolException {
+    this.pathAndFileListMap.put(this.pwd(site, protocol), fileList);
+  }
+
+  public synchronized RemoteSiteFile getHomeDir(RemoteSite site, Protocol protocol) {
+    try {
+      protocol.cdHome();
+      return new RemoteSiteFile(protocol.pwd(), site);
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  public String getAbsPathFor(Protocol protocol, String path, boolean isDir) {
+    try {
+      protocol.cd(new ProtocolFile(path, isDir));
+      return protocol.pwd().getAbsoluteFile().getPath();
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  /**
+   * Disconnects and logs out the given Protocol
+   *
+   * @param protocol
+   *          The Protocol to be logout out and disconnected
+   * @throws RemoteConnectionException
+   */
+  public void disconnect(Protocol protocol) throws RemoteConnectionException {
+    try {
+      LOG.log(Level.INFO, "Disconnecting protocol " + protocol.getClass().getName());
+      protocol.close();
+    } catch (Exception e) {
+      throw new RemoteConnectionException("Error disconnecting " + protocol.getClass().getName()
+          + " : " + e.getMessage());
+    }
+  }
+
+  /**
+   * Disconnects all waiting Protocols and clears the waiting lists. Also clears
+   * the current Protocol
+   *
+   * @throws RemoteConnectionException
+   */
+  public void close() throws RemoteConnectionException {
+    Set<Entry<URL, Protocol>> entries = reuseProtocols.entrySet();
+    for (Entry<URL, Protocol> entry : entries) {
+      disconnect(entry.getValue());
+    }
+    this.reuseProtocols.clear();
+    this.urlAndProtocolFactory.clear();
+    this.pageInfos.clear();
+    this.pathAndFileListMap.clear();
+  }
+
+  private synchronized RemoteSiteFile getProtocolFileByProtocol(
+      RemoteSite site, Protocol protocol, String file, boolean isDir) throws ProtocolException {
+    try {
+      if (!file.startsWith("/")) {
+        protocol.cdHome();
+        file = protocol.pwd().getPath() + "/" + file;
+      }
+      return new RemoteSiteFile(file, isDir, site);
+    } catch (Exception e) {
+      throw new ProtocolException("Failed to create protocol for " + file
+          + " : " + e.getMessage());
+    }
+  }
+
+  private List<RemoteSiteFile> toRemoteSiteFiles(List<ProtocolFile> files, RemoteSite site) {
+    List<RemoteSiteFile> newFiles = new Vector<RemoteSiteFile>();
+    if (files != null) {
+      for (ProtocolFile file : files) {
+        newFiles.add(new RemoteSiteFile(file, site));
+      }
+    }
+    return newFiles;
+  }
+
+  class PagingInfo {
+
+    private int pageLoc;
+
+    private int sizeOfLastLS;
+
+    private RemoteSiteFile pFileAtPageLoc;
+
+    PagingInfo() {
+      this.pageLoc = 0;
+      this.sizeOfLastLS = -1;
+      this.pFileAtPageLoc = null;
+    }
+
+    synchronized void updatePageInfo(int newPageLoc, List<RemoteSiteFile> ls)
+        throws MalformedURLException, ProtocolException {
+      this.sizeOfLastLS = ls.size();
+      this.pageLoc = newPageLoc < 0 ? 0 : newPageLoc;
+      this.pFileAtPageLoc = (this.sizeOfLastLS > 0 && newPageLoc < ls.size()) ? ls
+          .get(newPageLoc) : null;
+    }
+
+    synchronized int getPageLoc() {
+      return this.pageLoc;
+    }
+
+    synchronized int getSizeOfLastLS() {
+      return this.sizeOfLastLS;
+    }
+
+    synchronized RemoteSiteFile getRemoteSiteFileAtPageLoc() {
+      return this.pFileAtPageLoc;
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/protocol/ProtocolPath.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/protocol/ProtocolPath.java
new file mode 100644
index 0000000..d2aaf8e
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/protocol/ProtocolPath.java
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.protocol;
+
+//JDK imports
+import java.io.Serializable;
+import java.net.MalformedURLException;
+
+/**
+ * This class wraps up a URL for a given path, and whether the path specified by
+ * the URL is a dirctory or not
+ * 
+ * @author bfoster
+ */
+public class ProtocolPath implements Serializable {
+
+    private static final long serialVersionUID = 807275248811949120L;
+
+    /**
+     * The string verion of the path in the URL
+     */
+    protected String path;
+
+    protected String remotePath;
+
+    protected boolean relativeToHOME;
+
+    /**
+     * Specifies whether this path is a path to a directory or file
+     */
+    protected boolean isDir;
+
+    public ProtocolPath() {
+        super();
+    }
+
+    public ProtocolPath(String path, boolean isDir) {
+        this.isDir = isDir;
+        this.path = this.checkForDelimiters(path);
+    }
+
+    protected String checkForDelimiters(String path) {
+        if (path.endsWith("/") && path.length() > 1)
+            path = path.substring(0, path.length() - 1);
+        relativeToHOME = !path.startsWith("/");
+        return path;
+    }
+
+    public boolean isRelativeToHOME() {
+        return relativeToHOME;
+    }
+
+    public String getPathString() {
+        return path;
+    }
+
+    /**
+     * Return the name of the file for which this path belongs
+     * 
+     * @return The Path file name.
+     */
+    public String getFileName() {
+        return path.substring(path.lastIndexOf("/") + 1);
+    }
+
+    /**
+     * Returns the path that is used when downloading the file
+     * 
+     * @return The downloading path
+     */
+    public String getDownloadPath() {
+        return (isDirectory()) ? path : path
+                .substring(0, path.lastIndexOf("/"))
+                + "/" + getDownloadFileName();
+    }
+
+    /**
+     * Returns the file name that is used when downloading the file
+     * 
+     * @return The name used during downloading.
+     */
+    public String getDownloadFileName() {
+        return "Downloading_" + getFileName();
+    }
+
+    /**
+     * Tells whether this path is a path to a directory or not
+     * 
+     * @return True if this Path is a directory
+     */
+    public boolean isDirectory() {
+        return isDir;
+    }
+
+    public boolean equals(Object path) {
+        if (path instanceof ProtocolPath) {
+            ProtocolPath p = (ProtocolPath) path;
+            return (p.getPathString().equals(this.getPathString()));
+        }
+        return false;
+    }
+
+    public String getParentDirPath() throws MalformedURLException {
+        if (path.length() <= 1)
+            return null;
+        return path.substring(0, path.lastIndexOf("/"));
+    }
+
+    public String toString() {
+        return (path + " isDir=" + this.isDir);
+    }
+
+    public ProtocolPath getParentPath() throws MalformedURLException {
+        return new ProtocolPath(path.substring(0, path.lastIndexOf("/")), true);
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/protocol/RemoteSite.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/protocol/RemoteSite.java
new file mode 100644
index 0000000..1edee22
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/protocol/RemoteSite.java
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.protocol;
+
+//JDK imports
+import java.net.URL;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class RemoteSite {
+    
+    private String alias, username, password, cdTestDir;
+    private int maxConnections;
+    private URL url;
+
+    public RemoteSite(String alias, URL url, String username, String password) {
+        this.alias = alias;
+        this.username = username;
+        this.password = password;
+        this.url = url;
+        this.maxConnections = -1;
+    }
+    
+    public RemoteSite(String alias, URL url, String username, String password, String cdTestDir) {
+        this(alias, url, username, password);
+        this.cdTestDir = cdTestDir;
+    }
+    
+    public RemoteSite(String alias, URL url, String username, String password, String cdTestDir, int maxConnections) {
+        this(alias, url, username, password, cdTestDir);
+        this.maxConnections = maxConnections;
+    }
+
+    public String getAlias() {
+        return this.alias;
+    }
+
+    public URL getURL() {
+        return this.url;
+    }
+
+    public String getUsername() {
+        return this.username;
+    }
+
+    public String getPassword() {
+        return this.password;
+    }
+    
+    public String getCdTestDir() {
+        return this.cdTestDir;
+    }
+
+    public int getMaxConnections() {
+    	return this.maxConnections;
+    }
+    
+    public void copy(RemoteSite rs) {
+        this.alias = rs.alias;
+        this.url = rs.url;
+        this.username = rs.username;
+        this.password = rs.password;
+        this.cdTestDir = rs.cdTestDir;
+        this.maxConnections = rs.maxConnections;
+    }
+
+    public boolean equals(Object obj) {
+        if (obj instanceof RemoteSite) {
+            RemoteSite rs = (RemoteSite) obj;
+            return (rs.alias.equals(this.alias) && rs.url.equals(this.url)
+                    && rs.username.equals(this.username) && rs.password
+                    .equals(this.password) && rs.maxConnections == this.maxConnections);
+        } else
+            return false;
+    }
+
+    public String toString() {
+        return "RemoteSite: alias = '" + this.alias + "'  url = '" + this.url
+                + "'  username = '" + this.username + "' cdTestDir = '" 
+                + this.cdTestDir + "' maxConnections = '" + this.maxConnections + "'";
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/protocol/RemoteSiteFile.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/protocol/RemoteSiteFile.java
new file mode 100644
index 0000000..89bfdbd
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/protocol/RemoteSiteFile.java
@@ -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.
+ */
+
+package org.apache.oodt.cas.pushpull.protocol;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFile;
+
+/**
+ *
+ * Extends {@link ProtocolFile} and links it to a {@link RemoteSite}.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class RemoteSiteFile extends ProtocolFile {
+
+  private RemoteSite site;
+
+  public RemoteSiteFile(ProtocolFile file, RemoteSite site){
+     this(file.getPath(), file.isDir(), site);
+  }
+
+  /**
+   * @param parent
+   * @param path
+   * @param isDir
+   * @param site
+   */
+  public RemoteSiteFile(ProtocolFile parent, String path, boolean isDir,
+      RemoteSite site) {
+    super(parent, path, isDir);
+    this.site = site;
+  }
+
+  /**
+   * @param path
+   * @param isDir
+   * @param site
+   */
+  public RemoteSiteFile(String path, boolean isDir, RemoteSite site) {
+    super(path, isDir);
+    this.site = site;
+  }
+
+  /**
+   * @return the site
+   */
+  public RemoteSite getSite() {
+    return site;
+  }
+
+  /**
+   * @param site
+   *          the site to set
+   */
+  public void setSite(RemoteSite site) {
+    this.site = site;
+  }
+
+  public RemoteSiteFile getRemoteParent() {
+    ProtocolFile parent = super.getParent();
+    return new RemoteSiteFile(parent.getPath(), parent.isDir(), this.site);
+  }
+
+  @Override
+public RemoteSiteFile getAbsoluteFile() {
+    ProtocolFile parent = super.getAbsoluteFile();
+    return new RemoteSiteFile(parent.getPath(), parent.isDir(), this.site);
+  }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalmethod/ListRetriever.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalmethod/ListRetriever.java
new file mode 100644
index 0000000..a2b4e78
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalmethod/ListRetriever.java
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.retrievalmethod;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.pushpull.config.DataFilesInfo;
+import org.apache.oodt.cas.pushpull.config.DownloadInfo;
+import org.apache.oodt.cas.pushpull.exceptions.AlreadyInDatabaseException;
+import org.apache.oodt.cas.pushpull.exceptions.RetrievalMethodException;
+import org.apache.oodt.cas.pushpull.exceptions.ToManyFailedDownloadsException;
+import org.apache.oodt.cas.pushpull.exceptions.UndefinedTypeException;
+import org.apache.oodt.cas.pushpull.filerestrictions.FileRestrictions;
+import org.apache.oodt.cas.pushpull.filerestrictions.Parser;
+import org.apache.oodt.cas.pushpull.filerestrictions.VirtualFileStructure;
+import org.apache.oodt.cas.pushpull.protocol.RemoteSite;
+import org.apache.oodt.cas.pushpull.retrievalsystem.DataFileToPropFileLinker;
+import org.apache.oodt.cas.pushpull.retrievalsystem.FileRetrievalSystem;
+
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.LinkedList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class ListRetriever implements RetrievalMethod {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(ListRetriever.class
+            .getName());
+
+    public void processPropFile(FileRetrievalSystem frs, Parser propFileParser,
+            File propFile, DataFilesInfo dfi, DataFileToPropFileLinker linker)
+            throws Exception {
+        RemoteSite remoteSite = null;
+
+        // parse property file
+        Metadata fileMetadata = new Metadata();
+        VirtualFileStructure vfs = propFileParser.parse(new FileInputStream(
+                propFile), fileMetadata);
+        DownloadInfo di = dfi.getDownloadInfo();
+        if (!di.isAllowAliasOverride()
+                || (remoteSite = vfs.getRemoteSite()) == null)
+            remoteSite = di.getRemoteSite();
+        LinkedList<String> fileList = FileRestrictions.toStringList(vfs
+                .getRootVirtualFile());
+
+        // download data files specified in property file
+        for (String file : fileList) {
+            try {
+                linker.addPropFileToDataFileLink(propFile, file);
+                if (!frs.addToDownloadQueue(remoteSite, file, di
+                        .getRenamingConv(), di.getStagingArea(), dfi
+                        .getQueryMetadataElementName(), di.deleteFromServer(), fileMetadata))
+                    linker.eraseLinks(propFile);
+            } catch (ToManyFailedDownloadsException e) {
+                throw new RetrievalMethodException(
+                        "Connection appears to be down. . .unusual number of download failures. . .stopping : "
+                                + e.getMessage());
+            } catch (CatalogException e) {
+                throw new RetrievalMethodException(
+                        "Failed to communicate with database : "
+                                + e.getMessage());
+            } catch (AlreadyInDatabaseException e) {
+                LOG.log(Level.WARNING, "Skipping file : " + e.getMessage());
+            } catch (UndefinedTypeException e) {
+                LOG.log(Level.WARNING, "Skipping file : " + e.getMessage());
+            } catch (Exception e) {
+                e.printStackTrace();
+                linker.markAsFailed(propFile, "Failed to download " + file
+                        + " from " + remoteSite + " : " + e.getMessage());
+                throw new Exception("Uknown error accured while downloading "
+                        + file + " from " + remoteSite + " -- bailing out : "
+                        + e.getMessage());
+            }
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalmethod/RemoteCrawler.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalmethod/RemoteCrawler.java
new file mode 100644
index 0000000..d5ca530
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalmethod/RemoteCrawler.java
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.retrievalmethod;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.pushpull.config.DataFilesInfo;
+import org.apache.oodt.cas.pushpull.config.DownloadInfo;
+import org.apache.oodt.cas.pushpull.exceptions.AlreadyInDatabaseException;
+import org.apache.oodt.cas.pushpull.exceptions.ProtocolFileException;
+import org.apache.oodt.cas.pushpull.exceptions.RetrievalMethodException;
+import org.apache.oodt.cas.pushpull.exceptions.ToManyFailedDownloadsException;
+import org.apache.oodt.cas.pushpull.exceptions.UndefinedTypeException;
+import org.apache.oodt.cas.pushpull.filerestrictions.FileRestrictions;
+import org.apache.oodt.cas.pushpull.filerestrictions.Parser;
+import org.apache.oodt.cas.pushpull.filerestrictions.VirtualFile;
+import org.apache.oodt.cas.pushpull.filerestrictions.VirtualFileStructure;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.protocol.util.ProtocolFileFilter;
+import org.apache.oodt.cas.pushpull.protocol.ProtocolPath;
+import org.apache.oodt.cas.pushpull.protocol.RemoteSite;
+import org.apache.oodt.cas.pushpull.protocol.RemoteSiteFile;
+import org.apache.oodt.cas.pushpull.retrievalsystem.DataFileToPropFileLinker;
+import org.apache.oodt.cas.pushpull.retrievalsystem.FileRetrievalSystem;
+
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.MalformedURLException;
+import java.util.List;
+import java.util.Stack;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class RemoteCrawler implements RetrievalMethod {
+
+    private static final Logger LOG = Logger.getLogger(RemoteCrawler.class
+            .getName());
+
+    /**
+     * Starts the crawler and creates a default DirStruct if null was supplied
+     * in constructor
+     *
+     * @throws MalformedURLException
+     * @throws ProtocolException
+     * @throws ProtocolFileException
+     */
+    @Override
+   public void processPropFile(FileRetrievalSystem frs, Parser propFileParser,
+            File propFile, DataFilesInfo dfi, DataFileToPropFileLinker linker)
+            throws Exception {
+        RemoteSite remoteSite;
+
+        // parse property file
+        Metadata fileMetadata = new Metadata();
+        VirtualFileStructure vfs = propFileParser.parse(new FileInputStream(
+                propFile), fileMetadata);
+
+        // determine RemoteSite
+        DownloadInfo di = dfi.getDownloadInfo();
+        if (!di.isAllowAliasOverride()
+                || (remoteSite = vfs.getRemoteSite()) == null)
+            remoteSite = di.getRemoteSite();
+
+        // modify vfs to be root based if HOME directory based
+        if (!vfs.isRootBased()) {
+            String homeDirPath = frs.getHomeDir(remoteSite).getPath();
+            VirtualFile root = new VirtualFile(homeDirPath, true);
+            root.addChild(vfs.getRootVirtualFile());
+            vfs = new VirtualFileStructure(homeDirPath + "/"
+                    + vfs.getPathToRoot(), root.getRootDir());
+            frs.changeToHOME(remoteSite);
+        }
+
+        // initialize variables
+        final String initialCdPath = vfs.getPathToRoot();
+        final VirtualFile vf = vfs.getRootVirtualFile();
+
+        // change to initial directory (takes care of Linux auto-mounting)
+        frs.changeToDir(initialCdPath, remoteSite);
+
+        // add starting directory to stack
+        Stack<RemoteSiteFile> files = new Stack<RemoteSiteFile>();
+        files.add(new RemoteSiteFile(frs.getCurrentFile(remoteSite), remoteSite));
+
+        // start crawling
+        while (!files.isEmpty()) {
+            RemoteSiteFile file = files.peek();
+            try {
+                // if directory, then add its children to the crawl list
+                if (file.isDir()) {
+
+                    // get next page worth of children
+                    List<RemoteSiteFile> children = frs.getNextPage(file,
+                            new ProtocolFileFilter() {
+                                @Override
+                              public boolean accept(ProtocolFile pFile) {
+                                    return FileRestrictions.isAllowed(new
+                                        ProtocolPath(pFile
+                                            .getPath(), pFile.isDir()), vf);
+                                }
+                            });
+
+                    // if directory had more children then add them
+                    if (children.size() > 0)
+                        files.addAll(children);
+                    // otherwise remove the directory from the crawl list
+                    else
+                        files.pop();
+
+                    // if file, then download it
+                } else {
+                    linker.addPropFileToDataFileLink(propFile, file);
+                    if (!frs.addToDownloadQueue(files.pop(), di
+                            .getRenamingConv(), di.getStagingArea(), dfi
+                            .getQueryMetadataElementName(), di
+                            .deleteFromServer(), fileMetadata))
+                        linker.eraseLinks(propFile);
+                }
+
+            } catch (ToManyFailedDownloadsException e) {
+                throw new RetrievalMethodException(
+                        "Connection appears to be down. . .unusual number of download failures. . .stopping : "
+                                + e.getMessage());
+            } catch (CatalogException e) {
+                throw new RetrievalMethodException(
+                        "Failed to communicate with database : "
+                                + e.getMessage());
+            } catch (AlreadyInDatabaseException e) {
+                LOG.log(Level.WARNING, "Skipping file : " + e.getMessage());
+            } catch (UndefinedTypeException e) {
+                LOG.log(Level.WARNING, "Skipping file : " + e.getMessage());
+            } catch (Exception e) {
+                linker.markAsFailed(propFile, e.getMessage());
+                throw new Exception("Uknown error accured while downloading "
+                        + file + " from " + remoteSite + " -- bailing out : "
+                        + e.getMessage(), e);
+            }
+        }
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalmethod/RetrievalMethod.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalmethod/RetrievalMethod.java
new file mode 100644
index 0000000..bd124a1
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalmethod/RetrievalMethod.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.retrievalmethod;
+
+//JDK imports
+import java.io.File;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.config.DataFilesInfo;
+import org.apache.oodt.cas.pushpull.filerestrictions.Parser;
+import org.apache.oodt.cas.pushpull.retrievalsystem.DataFileToPropFileLinker;
+import org.apache.oodt.cas.pushpull.retrievalsystem.FileRetrievalSystem;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public interface RetrievalMethod {
+
+    public void processPropFile(FileRetrievalSystem frs,
+            Parser propFileParser, File propFile, DataFilesInfo dfi,
+            DataFileToPropFileLinker linker) throws Exception;
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/DataFileToPropFileLinker.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/DataFileToPropFileLinker.java
new file mode 100644
index 0000000..b6b87bd
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/DataFileToPropFileLinker.java
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.retrievalsystem;
+
+//JDK imports
+import java.io.File;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map.Entry;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFile;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class DataFileToPropFileLinker implements DownloadListener {
+
+    private HashMap<String, File> protocolFilePathAndPropFileMap;
+
+    private HashMap<File, String> propFileToErrorsMap;
+
+    private LinkedList<ProtocolFile> downloadingDataFiles;
+
+    private LinkedList<ProtocolFile> failedDataFiles;
+
+    private LinkedList<ProtocolFile> successDataFiles;
+
+    public DataFileToPropFileLinker() {
+        this.protocolFilePathAndPropFileMap = new HashMap<String, File>();
+        this.propFileToErrorsMap = new HashMap<File, String>();
+        downloadingDataFiles = new LinkedList<ProtocolFile>();
+        failedDataFiles = new LinkedList<ProtocolFile>();
+        successDataFiles = new LinkedList<ProtocolFile>();
+    }
+
+    public synchronized void addPropFileToDataFileLink(File propFile,
+            ProtocolFile pFile) {
+        this.addPropFileToDataFileLink(propFile, pFile.getPath());
+    }
+
+    public synchronized void addPropFileToDataFileLink(File propFile,
+            String remoteDataFilePath) {
+        this.protocolFilePathAndPropFileMap.put(remoteDataFilePath, propFile);
+    }
+
+    public synchronized void markAsFailed(File propFile, String errorMsg) {
+        String errors = this.propFileToErrorsMap.get(propFile);
+        if (errors == null)
+            this.propFileToErrorsMap.put(propFile, errorMsg);
+        else
+            this.propFileToErrorsMap.put(propFile, errors + "," + errorMsg);
+    }
+
+    public synchronized void markAsFailed(ProtocolFile pFile, String errorMsg) {
+        this.markAsFailed(pFile.getPath(), errorMsg);
+    }
+
+    public synchronized void markAsFailed(String pFilePath, String errorMsg) {
+        File propFile = this.protocolFilePathAndPropFileMap.get(pFilePath);
+        if (propFile != null) {
+            String errors = this.propFileToErrorsMap.get(propFile);
+            if (errors == null)
+                this.propFileToErrorsMap.put(propFile, errorMsg);
+            else
+                this.propFileToErrorsMap.put(propFile, errors + "," + errorMsg);
+        }
+    }
+
+    public synchronized String getErrorsAndEraseLinks(File propFile) {
+        this.eraseLinks(propFile);
+        return this.getErrors(propFile);
+    }
+
+    public synchronized void eraseLinks(File propFile) {
+        LinkedList<String> keysToRemove = new LinkedList<String>();
+        for (Entry<String, File> entry : this.protocolFilePathAndPropFileMap
+                .entrySet())
+            if (entry.getValue().equals(propFile))
+                keysToRemove.add(entry.getKey());
+        for (String key : keysToRemove)
+            this.protocolFilePathAndPropFileMap.remove(key);
+    }
+
+    public synchronized String getErrors(File propFile) {
+        return this.propFileToErrorsMap.remove(propFile);
+    }
+
+    public synchronized String getStatusOf(File propFile) {
+        return "Status for " + propFile.getAbsolutePath() + ":" + " Errors: \n"
+                + "   " + this.propFileToErrorsMap.get(propFile) + "\n"
+                + " Data files specified which are currently downloading:\n"
+                + "   " + this.getDownloadingFilesLinkedToPropFile(propFile)
+                + "\n"
+                + " Data files specified which successfully downloaded:\n"
+                + "   "
+                + this.getSuccessfullyDownloadedFilesLinkedToPropFile(propFile)
+                + "\n" + " Data files specified which failed to download:\n"
+                + "   "
+                + this.getFailedToDownloadFilesLinkedToPropFile(propFile)
+                + "\n";
+    }
+
+    public synchronized LinkedList<ProtocolFile> getDownloadingFilesLinkedToPropFile(
+            File propFile) {
+        return this.getFilesLinkedToPropFileInList(propFile,
+                this.downloadingDataFiles);
+    }
+
+    public synchronized LinkedList<ProtocolFile> getSuccessfullyDownloadedFilesLinkedToPropFile(
+            File propFile) {
+        return this.getFilesLinkedToPropFileInList(propFile,
+                this.successDataFiles);
+    }
+
+    public synchronized LinkedList<ProtocolFile> getFailedToDownloadFilesLinkedToPropFile(
+            File propFile) {
+        return this.getFilesLinkedToPropFileInList(propFile,
+                this.failedDataFiles);
+    }
+
+    private LinkedList<ProtocolFile> getFilesLinkedToPropFileInList(
+            File propFile, LinkedList<ProtocolFile> list) {
+        LinkedList<ProtocolFile> returnList = new LinkedList<ProtocolFile>();
+        for (ProtocolFile pFile : list) {
+            if (this.protocolFilePathAndPropFileMap.get(pFile.getPath()) != null)
+                returnList.add(pFile);
+        }
+        return returnList;
+    }
+
+    public synchronized void downloadFailed(ProtocolFile file, String errorMsg) {
+        this.markAsFailed(file, "Failed to download '" + file
+                + "' -- Logged Error msg: " + errorMsg);
+        this.failedDataFiles.add(file);
+        this.downloadingDataFiles.remove(file);
+    }
+
+    public synchronized void downloadFinished(ProtocolFile file) {
+        this.successDataFiles.add(file);
+        this.downloadingDataFiles.remove(file);
+    }
+
+    public synchronized void downloadStarted(ProtocolFile file) {
+        this.downloadingDataFiles.add(file);
+    }
+
+    public synchronized void clear() {
+        this.propFileToErrorsMap.clear();
+        this.protocolFilePathAndPropFileMap.clear();
+        this.downloadingDataFiles.clear();
+        this.failedDataFiles.clear();
+        this.successDataFiles.clear();
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/DownloadListener.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/DownloadListener.java
new file mode 100644
index 0000000..985c22a
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/DownloadListener.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.retrievalsystem;
+
+//OODT imports
+import org.apache.oodt.cas.protocol.ProtocolFile;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public interface DownloadListener {
+
+    public void downloadStarted(ProtocolFile pFile);
+
+    public void downloadFinished(ProtocolFile pFile);
+
+    public void downloadFailed(ProtocolFile pFile, String errorMsg);
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/DownloadThreadEvaluator.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/DownloadThreadEvaluator.java
new file mode 100644
index 0000000..2fd093a
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/DownloadThreadEvaluator.java
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.retrievalsystem;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.exceptions.ThreadEvaluatorException;
+
+//JDK imports
+import java.io.File;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.Map.Entry;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class DownloadThreadEvaluator {
+
+    private HashMap<File, DownloadingFileInfo> fileAndDownloadingFileInfo;
+
+    private final int MAX_THREADS;
+
+    private int currentThreadCount;
+
+    private double[] downloadSpeedsForEachThread;
+
+    public DownloadThreadEvaluator(int maxThreads) {
+        this.MAX_THREADS = maxThreads;
+        downloadSpeedsForEachThread = new double[maxThreads + 1];
+        fileAndDownloadingFileInfo = new HashMap<File, DownloadingFileInfo>();
+        currentThreadCount = 0;
+    }
+
+    public synchronized void startTrackingDownloadRuntimeForFile(File file)
+            throws ThreadEvaluatorException {
+        long curTime = System.currentTimeMillis();
+        if (++this.currentThreadCount > this.MAX_THREADS)
+            throw new ThreadEvaluatorException(
+                    "Number of threads exceeds max allows threads");
+        updateThreadCounts(curTime);
+        fileAndDownloadingFileInfo.put(file, new DownloadingFileInfo(file,
+                curTime, this.currentThreadCount));
+    }
+
+    private void updateThreadCounts(long curTime) {
+        Set<Entry<File, DownloadingFileInfo>> entrySet = fileAndDownloadingFileInfo
+                .entrySet();
+        for (Entry<File, DownloadingFileInfo> entry : entrySet) {
+            entry.getValue()
+                    .updateThreadCount(curTime, this.currentThreadCount);
+        }
+    }
+
+    public synchronized void cancelRuntimeTracking(File file) {
+        fileAndDownloadingFileInfo.remove(file);
+        currentThreadCount--;
+        updateThreadCounts(System.currentTimeMillis());
+    }
+
+    public synchronized void fileDownloadComplete(File file)
+            throws ThreadEvaluatorException {
+        try {
+            long finishTime = System.currentTimeMillis();
+            DownloadingFileInfo dfi = fileAndDownloadingFileInfo.remove(file);
+            updateThreadCounts(finishTime);
+            LinkedList<TimeAndThreadCount> tatcList = dfi
+                    .getTimeAndThreadInfo();
+            long runtime = finishTime - dfi.getStartTimeInMillis();
+            double total = 0;
+            long nextTime;
+            for (int i = 0; i < tatcList.size(); i++) {
+                TimeAndThreadCount tatc = tatcList.get(i);
+                if (i + 1 >= tatcList.size())
+                    nextTime = finishTime;
+                else
+                    nextTime = tatcList.get(i + 1).getStartTimeInMillis();
+                long threadCountTime = nextTime - tatc.getStartTimeInMillis();
+                total += ((double) (tatc.getThreadCount() * threadCountTime))
+                        / (double) runtime;
+            }
+            int avgThreadCountForFile = (int) Math.rint(total);
+            System.out.println("Recorded avg: " + avgThreadCountForFile);
+
+            double downloadSpeed = (file.length() * avgThreadCountForFile)
+                    / calculateRuntime(dfi.getStartTimeInMillis());
+            double currentAvgSpeed = this.downloadSpeedsForEachThread[avgThreadCountForFile];
+            if (currentAvgSpeed == 0)
+                this.downloadSpeedsForEachThread[avgThreadCountForFile] = downloadSpeed;
+            else
+                this.downloadSpeedsForEachThread[avgThreadCountForFile] = (currentAvgSpeed + downloadSpeed) / 2;
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new ThreadEvaluatorException("Failed to register file "
+                    + file + " as downloaded : " + e.getMessage());
+        } finally {
+            currentThreadCount--;
+        }
+    }
+
+    long calculateRuntime(final long startTime) {
+        return System.currentTimeMillis() - startTime;
+    }
+
+    public synchronized int getRecommendedThreadCount() {
+
+        int curRecThreadCount = 1;
+        double curMaxSpeed = this.downloadSpeedsForEachThread[curRecThreadCount];
+        for (int i = 1; i < this.downloadSpeedsForEachThread.length; i++) {
+            double curSpeed = this.downloadSpeedsForEachThread[i];
+            if (curSpeed > curMaxSpeed) {
+                curMaxSpeed = curSpeed;
+                curRecThreadCount = i;
+            }
+        }
+
+        if (curRecThreadCount != this.MAX_THREADS
+                && this.downloadSpeedsForEachThread[curRecThreadCount + 1] == 0)
+            curRecThreadCount++;
+        else if (this.downloadSpeedsForEachThread[curRecThreadCount - 1] == 0)
+            curRecThreadCount--;
+
+        System.out.print("[ ");
+        for (double time : downloadSpeedsForEachThread)
+            System.out.print(time + " ");
+        System.out.println("]");
+
+        System.out.println("Recommended Threads: " + curRecThreadCount);
+
+        return curRecThreadCount;
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/DownloadingFileInfo.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/DownloadingFileInfo.java
new file mode 100644
index 0000000..555dbef
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/DownloadingFileInfo.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.retrievalsystem;
+
+//JDK imports
+import java.io.File;
+import java.util.LinkedList;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class DownloadingFileInfo {
+
+    private File downloadingFile;
+
+    private long startTimeInMillis;
+
+    private LinkedList<TimeAndThreadCount> timeAndThreadCountList;
+
+    public DownloadingFileInfo(File downloadingFile, long startTimeInMillis,
+            int currentThreadCount) {
+        timeAndThreadCountList = new LinkedList<TimeAndThreadCount>();
+        this.downloadingFile = downloadingFile;
+        this.startTimeInMillis = startTimeInMillis;
+        this.timeAndThreadCountList.add(new TimeAndThreadCount(
+                startTimeInMillis, currentThreadCount));
+    }
+
+    public void updateThreadCount(long timeInMillis, int threadCount) {
+        this.timeAndThreadCountList.add(new TimeAndThreadCount(timeInMillis,
+                threadCount));
+    }
+
+    public File getDownloadingFile() {
+        return this.downloadingFile;
+    }
+
+    public long getStartTimeInMillis() {
+        return this.startTimeInMillis;
+    }
+
+    public LinkedList<TimeAndThreadCount> getTimeAndThreadInfo() {
+        return this.timeAndThreadCountList;
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/FileRetrievalSystem.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/FileRetrievalSystem.java
new file mode 100644
index 0000000..23b7fca
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/FileRetrievalSystem.java
@@ -0,0 +1,958 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.retrievalsystem;
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.config.Config;
+import org.apache.oodt.cas.pushpull.config.SiteInfo;
+import org.apache.oodt.cas.pushpull.exceptions.AlreadyInDatabaseException;
+import org.apache.oodt.cas.pushpull.exceptions.CrawlerException;
+import org.apache.oodt.cas.pushpull.exceptions.ProtocolFileException;
+import org.apache.oodt.cas.pushpull.exceptions.RemoteConnectionException;
+import org.apache.oodt.cas.pushpull.exceptions.ThreadEvaluatorException;
+import org.apache.oodt.cas.pushpull.exceptions.ToManyFailedDownloadsException;
+import org.apache.oodt.cas.pushpull.exceptions.UndefinedTypeException;
+import org.apache.oodt.cas.pushpull.filerestrictions.renamingconventions.RenamingConvention;
+import org.apache.oodt.cas.protocol.exceptions.ProtocolException;
+import org.apache.oodt.cas.protocol.util.ProtocolFileFilter;
+import org.apache.oodt.cas.protocol.Protocol;
+import org.apache.oodt.cas.protocol.ProtocolFile;
+import org.apache.oodt.cas.pushpull.protocol.ProtocolHandler;
+import org.apache.oodt.cas.pushpull.protocol.RemoteSite;
+import org.apache.oodt.cas.pushpull.protocol.RemoteSiteFile;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.MimeTypeUtils;
+
+
+//JDK imports
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Vector;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+/**
+ * <pre>
+ *    Will crawl external directory structures and will download the files within these structures.
+ *
+ *    This class's settings are set using a java .properties file which can be read in and parsed by Config.java.
+ *    This .properties file should have the following properties set:
+ *
+ *   	{@literal #list of sites to crawl
+ *   	protocol.external.sources=&lt;path-to-xml-file&gt;
+ *
+ *   	#protocol types
+ *   	protocolfactory.types=&lt;list-of-protocols-separated-by-commas&gt; (e.g. ftp,http,https,sftp)
+ *
+ *   	#Protocol factories per types (must have one for each protocol mention in protocolfactory.types -- the property must be name
+ *    	# as such: protocolfactory.&lt;name-of-protocol-type&gt;
+ *   	protocolfactory.ftp=&lt;path-to-java-protocolfactory-class&gt; (e.g. org.apache.oodt.cas.protocol.ftp.FtpClientFactory)
+ *   	protocolfactory.http=&lt;path-to-java-protocolfactory-class&gt;
+ *   	protocolfactory.https=&lt;path-to-java-protocolfactory-class&gt;
+ *   	protocolfactory.sftp=&lt;path-to-java-protocolfactory-class&gt;
+ *
+ *   	#configuration to make java.net.URL accept unsupported protocols -- must exist just as shown
+ *   	java.protocol.handler.pkgs=org.apache.oodt.cas.url.handlers
+ *    }
+ *
+ *    In order to specify which external sites to crawl you must create a XML file which contains the
+ *    the site and necessary information needed to crawl the site, such as username and password.
+ *    protocol.external.sources must contain the path to this file so the crawl knows where to find it.
+ *    You can also train this class on how to crawl each given site.  This is also specified in an XML
+ *    file, whose path must be given in the first mentioned XML file which contians the username and password.
+ *
+ *    Then schema for the external sites XML file is as such:
+ *
+ *    	{@literal &lt;sources&gt;
+ *    	   &lt;source url=&quot;url-of-server&quot;&gt;
+ *    	      &lt;username&gt;username&lt;/username&gt;
+ *    	      &lt;password&gt;password&lt;/password&gt;
+ *    	      &lt;dirstruct&gt;path-to-xml-file&lt;/dirstruct&gt;
+ *    	      &lt;crawl&gt;yes-or-no&lt;/crawl&gt;
+ *    	   &lt;/source&gt;
+ *    	   ...
+ *    	   ...
+ *    	   ...
+ *    	&lt;/sources\&gt;}
+ *
+ *    You may specify as many sources as you would like by specifying multiple {@literal &lt;source&gt;} tags.
+ *    In the {@literal &lt;source&gt;} tag, the parameter 'url' must be specified.  This is the url of the server
+ *    you want the crawler to connect to.  It should be of the following format:
+ *    {@literal &lt;protocol&gt;://&lt;host&gt;} (e.g. sftp://remote.computer.gov)
+ *    If no username and password exist, then these elements can be omitted (they are optional).
+ *    For {@literal &lt;crawl&gt;} place yes or no here.  This is for convenience of being able to keep record of the
+ *    sites and their information in this XML file even if you decide that you no longer need to crawl it
+ *    anymore (just put {@literal &lt;crawl&gt;no&lt;/crawl&gt;} and the crawl will not crawl that site).
+ *    {@literal &lt;dirStruct&gt;} contains a path to another XML file which is documented in DirStruct.java javadoc.  This
+ *    element is optional.  If no {@literal &lt;dirStruct&gt;} is given, then every directory will be crawled on the site
+ *    and every encountered file will be downloaded.
+ * </pre>
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class FileRetrievalSystem {
+
+    /* our log stream */
+    private static final Logger LOG = Logger
+            .getLogger(FileRetrievalSystem.class.getName());
+
+    private final static int MAX_RETRIES = 3;
+
+    private LinkedList<ProtocolFile> failedDownloadList;
+
+    private HashSet<ProtocolFile> currentlyDownloading;
+
+    private int max_allowed_failed_downloads;
+
+    /**
+     * The max number of threads able to run at the same time
+     */
+    private int max_sessions;
+
+    private final int absMaxAllowedSessions = 50;
+
+    /**
+     * This is just for clarity purposes. . .I only create the amount of threads
+     * that I will allow to be used at any given moment
+     */
+    private final static int EXTRA_LAZY_SESSIONS_TIMEOUT = 10;
+
+    /**
+     * A list of created protocol sessions (devoted to grabbing files from the
+     * crawling directory structure) that are not presently in use.
+     */
+    private Vector<Protocol> avaliableSessions;
+
+    /**
+     * The number of sessions that have been created (should always be less than
+     * or equal to MAX_SESSIONS).
+     */
+    private int numberOfSessions;
+
+    /**
+     * The thread pool that is in charge of the sessions.
+     */
+    private ThreadPoolExecutor threadController;
+
+    /**
+     * Manages the Protocols and always ensures that the Crawler is using the
+     * appropriate protocol for any given server.
+     */
+    private ProtocolHandler protocolHandler;
+
+    /**
+     * max_sessions tracker
+     */
+    private DownloadThreadEvaluator dtEval;
+
+    private DownloadListener dListener;
+
+    private Config config;
+
+    private SiteInfo siteInfo;
+
+    private HashSet<File> stagingAreas;
+
+    private MimeTypeUtils mimeTypeDetection;
+
+    /**
+     * Creates a Crawler based on the URL, DirStruct, and Config objects passed
+     * in. If no DirStruct is needed then set it to null.
+     *
+     * @param url
+     *            The URL for which you want this Crawler to crawl
+     * @param dirStruct
+     *            The specified directory structure located at the host -- use
+     *            to train crawler (see DirStruct).
+     * @param config
+     *            The Configuration file that is passed to this objects
+     *            ProtocolHandler.
+     * @throws InstantiationException
+     * @throws DatabaseException
+     */
+    public FileRetrievalSystem(Config config, SiteInfo siteInfo)
+            throws InstantiationException {
+        try {
+            protocolHandler = new ProtocolHandler(config.getProtocolInfo());
+            this.config = config;
+            this.siteInfo = siteInfo;
+            mimeTypeDetection = new MimeTypeUtils(config
+                    .getProductTypeDetectionFile());
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new InstantiationException(
+                    "Failed to create FileRetrievalSystem : " + e.getMessage());
+        }
+    }
+
+    public void registerDownloadListener(DownloadListener dListener) {
+        this.dListener = dListener;
+    }
+
+    public void initialize() throws IOException {
+        try {
+            resetVariables();
+        } catch (Exception e) {
+            throw new IOException("Failed to initialize FileRetrievalSystem : "
+                    + e.getMessage());
+        }
+    }
+
+    /**
+     * Initializes variables that must be reset when more than one crawl is done
+     *
+     * @throws ThreadEvaluatorException
+     */
+    void resetVariables() throws ThreadEvaluatorException {
+        numberOfSessions = 0;
+        stagingAreas = new HashSet<File>();
+        avaliableSessions = new Vector<Protocol>();
+        currentlyDownloading = new HashSet<ProtocolFile>();
+        failedDownloadList = new LinkedList<ProtocolFile>();
+        max_allowed_failed_downloads = config.getMaxFailedDownloads();
+        max_sessions = config.getRecommendedThreadCount();
+        threadController = new ThreadPoolExecutor(this.max_sessions,
+                this.max_sessions, EXTRA_LAZY_SESSIONS_TIMEOUT,
+                TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
+        if (config.useTracker())
+            dtEval = new DownloadThreadEvaluator(this.absMaxAllowedSessions);
+    }
+
+    /**
+     * reset error flag
+     */
+    public void clearErrorFlag() {
+        max_allowed_failed_downloads += config.getMaxFailedDownloads();
+    }
+
+    public boolean isAlreadyInDatabase(RemoteFile rf) throws CatalogException {
+        return config.getIngester() != null ? config.getIngester().hasProduct(
+                config.getFmUrl(), rf.getMetadata(RemoteFile.PRODUCT_NAME))
+                : false;
+    }
+
+    public List<RemoteSiteFile> getNextPage(final RemoteSiteFile dir,
+            final ProtocolFileFilter filter) throws RemoteConnectionException {
+        for (int i = 0; i < 3; i++) {
+            try {
+                return protocolHandler.nextPage(dir.getSite(), protocolHandler
+                        .getAppropriateProtocol(dir, true, true),
+                        new ProtocolFileFilter() {
+                            @Override
+                           public boolean accept(ProtocolFile file) {
+                                return filter.accept(file)
+                                        && !FileRetrievalSystem.this
+                                                .isDownloading(file);
+                            }
+                        });
+            } catch (Exception e) {
+                LOG.log(Level.WARNING, "Retrying to get next page for " + dir
+                        + " because operation failed : " + e.getMessage(), e);
+            }
+        }
+        throw new RemoteConnectionException("Failed to get next page for "
+                + dir);
+    }
+
+    public void changeToRoot(RemoteSite remoteSite) throws ProtocolException,
+            MalformedURLException, org.apache.oodt.cas.protocol.exceptions.ProtocolException {
+        if (validate(remoteSite))
+            protocolHandler.cdToROOT(protocolHandler
+                    .getAppropriateProtocolBySite(remoteSite, true));
+        else
+            throw new ProtocolException("Not a valid remote site " + remoteSite);
+    }
+
+    public void changeToHOME(RemoteSite remoteSite) throws ProtocolException,
+            MalformedURLException {
+        if (validate(remoteSite))
+            protocolHandler.cdToHOME(protocolHandler
+                    .getAppropriateProtocolBySite(remoteSite, true));
+        else
+            throw new ProtocolException("Not a valid remote site " + remoteSite);
+    }
+
+    public void changeToDir(String dir, RemoteSite remoteSite)
+            throws MalformedURLException, ProtocolException {
+        if (validate(remoteSite))
+            this
+                    .changeToDir(protocolHandler.getProtocolFileFor(remoteSite,
+                            protocolHandler.getAppropriateProtocolBySite(
+                                    remoteSite, true), dir, true));
+        else
+            throw new ProtocolException("Not a valid remote site " + remoteSite);
+    }
+
+    public void changeToDir(RemoteSiteFile pFile) throws ProtocolException,
+            MalformedURLException {
+        RemoteSite remoteSite = pFile.getSite();
+        if (validate(remoteSite))
+            protocolHandler.cd(protocolHandler.getAppropriateProtocolBySite(
+                    remoteSite, true), pFile);
+        else
+            throw new ProtocolException("Not a valid remote site " + remoteSite);
+    }
+
+    public ProtocolFile getHomeDir(RemoteSite remoteSite)
+            throws ProtocolException {
+        if (validate(remoteSite))
+            return protocolHandler.getHomeDir(remoteSite, protocolHandler
+                    .getAppropriateProtocolBySite(remoteSite, true));
+        else
+            throw new ProtocolException("Not a valid remote site " + remoteSite);
+    }
+
+    public ProtocolFile getProtocolFile(RemoteSite remoteSite, String file,
+            boolean isDir) throws ProtocolException {
+        if (validate(remoteSite))
+            return protocolHandler.getProtocolFileFor(remoteSite, protocolHandler
+                    .getAppropriateProtocolBySite(remoteSite, true), file,
+                    isDir);
+        else
+            throw new ProtocolException("Not a valid remote site " + remoteSite);
+    }
+
+    public ProtocolFile getCurrentFile(RemoteSite remoteSite)
+            throws ProtocolFileException, ProtocolException,
+            MalformedURLException {
+        if (validate(remoteSite))
+            return protocolHandler.pwd(remoteSite, protocolHandler
+                    .getAppropriateProtocolBySite(remoteSite, true));
+        else
+            throw new ProtocolException("Not a valid remote site " + remoteSite);
+    }
+
+    // returns true if download was added to queue. . .false otherwise
+    public boolean addToDownloadQueue(RemoteSite remoteSite, String file,
+            String renamingString, File downloadToDir,
+            String uniqueMetadataElement, boolean deleteAfterDownload, Metadata fileMetadata)
+            throws ToManyFailedDownloadsException, RemoteConnectionException,
+            ProtocolFileException, ProtocolException,
+            AlreadyInDatabaseException, UndefinedTypeException,
+            CatalogException, IOException {
+        if (validate(remoteSite)) {
+            if (!file.startsWith("/"))
+                file = "/" + file;
+            return addToDownloadQueue(protocolHandler.getProtocolFileFor(remoteSite,
+                    protocolHandler.getAppropriateProtocolBySite(remoteSite,
+                            true), file, false), renamingString, downloadToDir,
+                    uniqueMetadataElement, deleteAfterDownload, fileMetadata);
+        } else
+            throw new ProtocolException("Not a valid remote site " + remoteSite);
+    }
+
+    public boolean validate(RemoteSite remoteSite) {
+        Preconditions.checkNotNull(remoteSite);
+        LinkedList<RemoteSite> remoteSites = this.siteInfo
+                .getPossibleRemoteSites(remoteSite.getAlias(), remoteSite
+                        .getURL(), remoteSite.getUsername(), remoteSite
+                        .getPassword());
+        if (remoteSites.size() == 1) {
+            RemoteSite rs = remoteSites.get(0);
+            remoteSite.copy(rs);
+            return true;
+        }
+        return false;
+    }
+
+    public void waitUntilAllCurrentDownloadsAreComplete()
+            throws ProtocolException {
+        synchronized (this) {
+            for (int i = 0; i < 180; i++) {
+                try {
+                    if (this.avaliableSessions.size() == this.numberOfSessions)
+                        return;
+                    else
+                        this.wait(5000);
+                } catch (Exception e) {
+                }
+            }
+            throw new ProtocolException(
+                    "Downloads appear to be hanging . . . aborting wait . . . waited for 15 minutes");
+        }
+    }
+
+  public boolean addToDownloadQueue(RemoteSiteFile file,
+                                    String renamingString,
+                                    File downloadToDir,
+                                    String uniqueMetadataElement,
+                                    boolean deleteAfterDownload,
+                                    Metadata fileMetadata) throws ToManyFailedDownloadsException,
+                                                                  RemoteConnectionException,
+                                                                  AlreadyInDatabaseException,
+                                                                  UndefinedTypeException,
+                                                                  CatalogException,
+                                                                  IOException {
+        if (this.failedDownloadList.size() > max_allowed_failed_downloads)
+            throw new ToManyFailedDownloadsException(
+                    "Number of failed downloads exceeds "
+                            + max_allowed_failed_downloads
+                            + " . . . blocking all downloads from being added to queue . . . "
+                            + "reset error flag in order to force allow downloads into queue");
+        if (this.isDownloading(file)) {
+            LOG.log(Level.WARNING, "Skipping file '" + file
+                    + "' because it is already on the download queue");
+            return false;
+        }
+
+        RemoteFile remoteFile = new RemoteFile(file);
+        remoteFile.addMetadata(fileMetadata);
+        remoteFile.addMetadata(RemoteFile.RENAMING_STRING, renamingString);
+        remoteFile.addMetadata(RemoteFile.DELETE_AFTER_DOWNLOAD,
+                deleteAfterDownload + "");
+
+        if (config.onlyDownloadDefinedTypes()) {
+           String mimeType = this.mimeTypeDetection.getMimeType(file.getName());
+           if (mimeType != null
+                   && !mimeType.equals("application/octet-stream")) {
+               remoteFile.addMetadata(RemoteFile.MIME_TYPE, mimeType);
+               remoteFile.addMetadata(RemoteFile.SUPER_TYPE, this.mimeTypeDetection
+                       .getSuperTypeForMimeType(mimeType));
+               String description = this.mimeTypeDetection
+                       .getDescriptionForMimeType(mimeType);
+               if (!Strings.isNullOrEmpty(description)) {
+                 if(description.indexOf("&") != -1){
+                   for (String field : description.split("\\&\\&")) {
+                     String[] keyval = field.split("\\=");
+                     remoteFile.addMetadata(keyval[0].trim(), keyval[1].trim());
+                   }
+                 } else{
+                   // it's the ProductType
+                   remoteFile.addMetadata(RemoteFile.PRODUCT_TYPE, description);
+                 }
+                 if (remoteFile.getMetadata(RemoteFile.UNIQUE_ELEMENT) != null) {
+                    uniqueMetadataElement = remoteFile.getMetadata(RemoteFile.UNIQUE_ELEMENT);
+                 }
+               }
+           } else {
+              throw new UndefinedTypeException("File '" + file
+                    + "' is not a defined type");
+           }
+        }
+
+        downloadToDir = new File(downloadToDir.isAbsolute() ? downloadToDir
+                .getAbsolutePath() : this.config.getBaseStagingArea() + "/"
+                + downloadToDir.getPath());
+        if (!this.isStagingAreaInitialized(downloadToDir))
+            this.initializeStagingArea(downloadToDir);
+
+        remoteFile.addMetadata(RemoteFile.DOWNLOAD_TO_DIR, downloadToDir.getAbsolutePath());
+
+    	if (remoteFile.getMetadata(RemoteFile.PRODUCT_NAME_GENERATOR) != null) {
+    		remoteFile.addMetadata(RemoteFile.PRODUCT_NAME, RenamingConvention.rename(remoteFile, remoteFile.getMetadata(RemoteFile.PRODUCT_NAME_GENERATOR)));
+    	}else {
+    		remoteFile.setUniqueMetadataElement(uniqueMetadataElement == null ? RemoteFile.FILENAME : uniqueMetadataElement);
+    	}
+
+        if (!isAlreadyInDatabase(remoteFile)) {
+
+            // get download location
+            File newFile = getSaveToLoc(remoteFile);
+
+            // add session to thread pool
+            if (!this.isInStagingArea(newFile)) {
+                for (int retries = 0;; retries++) {
+                    try {
+                        addSessionToThreadPool(
+                                getNextAvaliableSession(remoteFile
+                                        .getProtocolFile()), remoteFile,
+                                newFile);
+                        return true;
+                    } catch (Exception e) {
+                        if (retries < MAX_RETRIES) {
+                            LOG.log(Level.WARNING, "Failed to get session for "
+                                    + file + " . . . retrying in 5 secs");
+                            synchronized (this) {
+                                try {
+                                    wait(5000);
+                                } catch (Exception e1) {
+                                }
+                            }
+                        } else {
+                            this.failedDownloadList.add(file);
+                            throw new RemoteConnectionException(
+                                    "Failed to get session to download " + file
+                                            + " : " + e.getMessage(), e);
+                        }
+                    }
+                }
+            } else {
+                if (deleteAfterDownload) {
+                    try {
+                        protocolHandler
+                                .delete(protocolHandler.getAppropriateProtocol(
+                                        file, true, true), file);
+                    } catch (Exception e) {
+                        LOG.log(Level.SEVERE,
+                                "Failed to delete file from server : "
+                                        + e.getMessage());
+                    }
+                }
+                LOG.log(Level.WARNING, "Skipping file " + file
+                        + " because it is already in staging area");
+                return false;
+            }
+        } else
+            throw new AlreadyInDatabaseException("File " + file
+                    + " is already the database");
+    }
+
+    private boolean isStagingAreaInitialized(File stagingArea) {
+        return this.stagingAreas.contains(stagingArea);
+    }
+
+    private boolean isInStagingArea(final File findFile) {
+        return (findFile.exists() || new File(findFile.getParentFile(),
+                "Downloading_" + findFile.getName()).exists());
+    }
+
+    private void initializeStagingArea(File stagingArea) throws IOException {
+        LOG.log(Level.INFO, "Preparing staging area " + stagingArea);
+        if (stagingArea.exists()) {
+            File[] failedDownloads = stagingArea.listFiles(new FileFilter() {
+                @Override
+               public boolean accept(File pathname) {
+                    return pathname.getName().startsWith("Downloading_");
+                }
+            });
+            for (File file : failedDownloads) {
+                LOG.log(Level.INFO, "Removing failed download file "
+                        + file.getAbsolutePath());
+                file.delete();
+            }
+        } else {
+            LOG.log(Level.INFO, "Staging area " + stagingArea.getAbsolutePath()
+                    + " does not exist! -- trying to create it ");
+            if (!stagingArea.mkdirs())
+                throw new IOException("Failed to create staging area at "
+                        + stagingArea.getAbsolutePath());
+        }
+        this.stagingAreas.add(stagingArea);
+    }
+
+    File getSaveToLoc(RemoteFile remoteFile) {
+        String renamingString = remoteFile
+                .getMetadata(RemoteFile.RENAMING_STRING);
+        if (renamingString == null || renamingString.equals("")) {
+            return new File(remoteFile.getMetadata(RemoteFile.DOWNLOAD_TO_DIR)
+                    + "/" + remoteFile.getMetadata(RemoteFile.FILENAME));
+        } else {
+            File newFile = new File(remoteFile
+                    .getMetadata(RemoteFile.DOWNLOAD_TO_DIR)
+                    + "/"
+                    + RenamingConvention.rename(remoteFile, renamingString));
+            if (!newFile.getParentFile().equals(
+                    remoteFile.getMetadata(RemoteFile.DOWNLOAD_TO_DIR)))
+                newFile.getParentFile().mkdirs();
+            return newFile;
+        }
+    }
+
+    Protocol getNextAvaliableSession(RemoteSiteFile file) throws CrawlerException {
+        // wait for available session, then load it
+        Protocol session;
+        while ((session = getSession(file)) == null) {
+            try {
+                waitMainThread();
+            } catch (InterruptedException e1) {
+            }
+        }
+        return session;
+    }
+
+    /**
+     * Sleeps the crawling thread
+     *
+     * @throws InterruptedException
+     */
+    synchronized void waitMainThread() throws InterruptedException {
+        wait();
+    }
+
+    /**
+     * Wakes up the crawling thread
+     */
+    synchronized void wakeUpMainThread() {
+        notify();
+    }
+
+    /**
+     * Increments the number of downloading session
+     */
+    synchronized void incrementSessions() {
+        numberOfSessions++;
+    }
+
+    synchronized void decrementSessions() {
+        this.numberOfSessions--;
+    }
+
+    /**
+     * Gets an available downloading session Protocol. Returns null if none are
+     * available
+     *
+     * @param path
+     *            The session returned will be checked against the Path passed
+     *            in and if not presently connected to the Path's URL, it will
+     *            be disconnected from it's current server and connected to the
+     *            server specified by the Path.
+     * @return The found downloading session Protocol
+     * @throws RemoteCommunicationException
+     *             If downloading session Protocol has to be reconnected and
+     *             there is an error communicating with the server
+     */
+    synchronized Protocol getSession(RemoteSiteFile file) throws CrawlerException {
+        try {
+            Protocol session = null;
+			if (file.getSite().getMaxConnections() < 0
+					|| file.getSite().getMaxConnections() > this.getCurrentlyDownloadingFiles().size()) {
+	            if (avaliableSessions.size() > 0) {
+	                session = modifyAvailableSessionForPath(file);
+	            } else if (numberOfSessions < max_sessions) {
+	                session = createNewSessionForPath(file);
+	                incrementSessions();
+	            }
+            }
+            return session;
+        } catch (Exception e) {
+            throw new CrawlerException("Failed to get new session : "
+                    + e.getMessage(), e);
+        }
+    }
+
+    Protocol createNewSessionForPath(RemoteSiteFile file)
+            throws RemoteConnectionException {
+        return protocolHandler.getAppropriateProtocol(file, /* reuse */false, /* navigate */
+        true);
+    }
+
+    Protocol modifyAvailableSessionForPath(RemoteSiteFile file)
+            throws ProtocolException, RemoteConnectionException {
+        Protocol session = getAvailableSession();
+        if (!file.getSite().getURL().getHost().equals(
+                file.getSite().getURL().getHost())
+                || !protocolHandler.isProtocolConnected(session)) {
+            protocolHandler.disconnect(session);
+            session = protocolHandler.getAppropriateProtocol(file, /* reuse */
+            false, /* navigate */true);
+        } else {
+            try {
+                if (file.isDir())
+                    protocolHandler.cd(session, file);
+                else
+                    protocolHandler.cd(session,
+                          new RemoteSiteFile(file.getParent(), file.getSite()));
+            } catch (Exception e) {
+                e.printStackTrace();
+                try {
+                    protocolHandler.disconnect(session);
+                } catch (Exception exc) {
+                }
+                session = protocolHandler.getAppropriateProtocol(file, /* reuse */
+                false, /* navigate */true);
+            }
+        }
+        return session;
+    }
+
+    /**
+     * Puts a session in the available session list
+     *
+     * @param session
+     *            The Protocol session to be added to the available list
+     */
+    synchronized void addAvailableSession(Protocol session) {
+        avaliableSessions.add(session);
+    }
+
+    /**
+     * Removes a session from the available list and returns it
+     *
+     * @return An available downloading Protocol session
+     */
+    synchronized Protocol getAvailableSession() {
+        return avaliableSessions.remove(0);
+    }
+
+    synchronized int getNumberOfUsedSessions() {
+        return numberOfSessions - avaliableSessions.size();
+    }
+
+    /**
+     * Registers a downloading session with the threadpoolexecutor to begin
+     * downloading the specified ProtocolFile to the local File location
+     *
+     * @param session
+     *            The downloading Protocol session to be used to download the
+     *            ProtocolFile
+     * @param protocolFile
+     *            The file to be downloaded
+     * @param newFile
+     *            The location which the downloaded file will be stored
+     */
+    void addSessionToThreadPool(final Protocol session,
+            final RemoteFile remoteFile, final File newFile) {
+        this.addToDownloadingList(remoteFile.getProtocolFile());
+        threadController.execute(new Runnable() {
+            @Override
+            public void run() {
+                boolean successful = false;
+                int retries = 0;
+                Protocol curSession = session;
+
+                if (FileRetrievalSystem.this.dListener != null)
+                    FileRetrievalSystem.this.dListener
+                            .downloadStarted(remoteFile.getProtocolFile());
+
+                // try until successful or all retries have been used
+                do {
+                    try {
+                        // if thread tracker is to be used
+                        if (config.useTracker()) {
+                            dtEval.startTrackingDownloadRuntimeForFile(newFile);
+                            protocolHandler.download(curSession, remoteFile
+                                    .getProtocolFile(), newFile, remoteFile
+                                    .getMetadata(
+                                            RemoteFile.DELETE_AFTER_DOWNLOAD)
+                                    .equals("true"));
+                            dtEval.fileDownloadComplete(newFile);
+                            threadController
+                                    .setCorePoolSize(max_sessions = dtEval
+                                            .getRecommendedThreadCount());
+                            threadController.setMaximumPoolSize(max_sessions);
+                            // if static number of threads are to be used
+                        } else {
+                            protocolHandler.download(curSession, remoteFile
+                                    .getProtocolFile(), newFile, remoteFile
+                                    .getMetadata(
+                                            RemoteFile.DELETE_AFTER_DOWNLOAD)
+                                    .equals("true"));
+                        }
+
+                        successful = true;
+                        if (FileRetrievalSystem.this.dListener != null)
+                            FileRetrievalSystem.this.dListener
+                                    .downloadFinished(remoteFile
+                                            .getProtocolFile());
+
+                        remoteFile.addMetadata(RemoteFile.FILE_SIZE, newFile
+                                .length()
+                                + "");
+
+                        // try to create the metadata file
+                        if (config.getWriteMetFile()) {
+	                        try {
+	                        	LOG.log(Level.INFO, "Writing metadata file for '" + newFile + "'");
+	                            remoteFile.addMetadata(RemoteFile.FILE_SIZE,
+	                                    newFile.length() + "");
+	                            remoteFile.writeToPropEqValFile(newFile
+	                                    .getAbsolutePath()
+	                                    + "." + config.getMetFileExtension(),
+	                                    config.getListOfMetadataToOutput());
+	                        } catch (Exception e) {
+	                            LOG.log(Level.SEVERE,
+	                                    "Failed to create metadata file for "
+	                                            + remoteFile.getProtocolFile());
+	                        }
+                        }
+
+                    } catch (Exception e) {
+
+                        // if tracker is being used cancel tracking
+                        if (config.useTracker())
+                            dtEval.cancelRuntimeTracking(newFile);
+
+                        // delete any created file from staging area
+                        newFile.delete();
+                        new File(newFile.getAbsolutePath() + "."
+                                + config.getMetFileExtension()).delete();
+
+                        // check if a retry is still allowed
+                        if (++retries > MAX_RETRIES) {
+                            FileRetrievalSystem.this.failedDownloadList
+                                    .add(remoteFile.getProtocolFile());
+                            LOG.log(Level.SEVERE, "Failed to download "
+                                    + remoteFile.getProtocolFile() + " : "
+                                    + e.getMessage());
+                            if (FileRetrievalSystem.this.dListener != null)
+                                FileRetrievalSystem.this.dListener
+                                        .downloadFailed(remoteFile
+                                                .getProtocolFile(), e
+                                                .getMessage());
+                            break;
+                        } else if (FileRetrievalSystem.this.failedDownloadList
+                                .size() < max_allowed_failed_downloads) {
+                            // discard current session and recreate a new
+                            // session to try to download file with
+                            LOG.log(Level.WARNING, "Retrying to download file "
+                                    + remoteFile.getProtocolFile()
+                                    + " because download failed : "
+                                    + e.getMessage(), e);
+                            try {
+                                protocolHandler.disconnect(curSession);
+                            } catch (Exception exc) {
+                            }
+                            try {
+                                curSession = protocolHandler
+                                        .getAppropriateProtocol(remoteFile
+                                                .getProtocolFile(), false, true);
+                            } catch (Exception exc) {
+                                LOG.log(Level.SEVERE,
+                                        "Failed to reconnect protocol to retry download of file "
+                                                + remoteFile.getProtocolFile()
+                                                + " -- aborting retry : "
+                                                + e.getMessage(), e);
+                            }
+                        } else {
+                            LOG
+                                    .log(
+                                            Level.SEVERE,
+                                            "Terminating download tries for file "
+                                                    + remoteFile
+                                                            .getProtocolFile()
+                                                    + " do to too many previous download failures : "
+                                                    + e.getMessage(), e);
+                            if (FileRetrievalSystem.this.dListener != null)
+                                FileRetrievalSystem.this.dListener
+                                        .downloadFailed(remoteFile
+                                                .getProtocolFile(), e
+                                                .getMessage());
+                            break;
+                        }
+
+                    }
+                } while (!successful);
+
+                FileRetrievalSystem.this.removeFromDownloadingList(remoteFile
+                        .getProtocolFile());
+                determineSessionFate(curSession);
+            }
+        });
+    }
+
+    private synchronized void addToDownloadingList(ProtocolFile pFile) {
+        this.currentlyDownloading.add(pFile);
+    }
+
+    private synchronized void removeFromDownloadingList(ProtocolFile pFile) {
+        this.currentlyDownloading.remove(pFile);
+    }
+
+    public synchronized boolean isDownloading(ProtocolFile pFile) {
+        return this.currentlyDownloading.contains(pFile);
+    }
+
+    public synchronized LinkedList<ProtocolFile> getCurrentlyDownloadingFiles() {
+        LinkedList<ProtocolFile> list = new LinkedList<ProtocolFile>();
+        list.addAll(this.currentlyDownloading);
+        return list;
+    }
+
+    public LinkedList<ProtocolFile> getListOfFailedDownloads() {
+        return this.failedDownloadList;
+    }
+
+    public void clearFailedDownloadsList() {
+        this.failedDownloadList.clear();
+    }
+
+    synchronized void determineSessionFate(Protocol session) {
+        // determine whether thread should be keep or should be thrown away
+        if (numberOfSessions <= max_sessions) {
+            giveBackSession(session);
+        } else {
+            disposeOfSession(session);
+        }
+    }
+
+    void giveBackSession(Protocol session) {
+        addAvailableSession(session);
+        wakeUpMainThread();
+    }
+
+    void disposeOfSession(Protocol session) {
+        try {
+            protocolHandler.disconnect(session);
+        } catch (Exception e) {
+            // log failure
+        }
+        numberOfSessions--;
+    }
+
+    public void shutdown() {
+        try {
+            // close out threadpool
+            threadController.shutdown();
+            // give a max of 10 minutes to finish downloading any files
+            threadController.awaitTermination(600, TimeUnit.SECONDS);
+        } catch (Exception e) {
+            // log failure
+        }
+
+        try {
+            this.resetVariables();
+        } catch (Exception e) {
+
+        }
+
+        try {
+            closeSessions();
+        } catch (Exception e) {
+            // log failure!!!
+        }
+
+        try {
+            protocolHandler.close();
+        } catch (Exception e) {
+            // log failure!!!
+        }
+
+    }
+
+    /**
+     * Disconnects all downloading Protocol sessions in the avaiableSessions
+     * list. The ThreadPoolExecutor needs to be completely shutdown before this
+     * method should be called. Otherwise some Protocols might not be
+     * disconnected or left downloading.
+     *
+     * @return True if successful, false otherwise
+     * @throws RemoteConnectionException
+     */
+    public boolean closeSessions() throws RemoteConnectionException {
+        for (Protocol session : avaliableSessions) {
+            protocolHandler.disconnect(session);
+        }
+        // sessions.clear();
+        avaliableSessions.clear();
+        numberOfSessions = 0;
+        return true;
+    }
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/RemoteFile.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/RemoteFile.java
new file mode 100644
index 0000000..3847ba5
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/RemoteFile.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.retrievalsystem;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.pushpull.protocol.RemoteSiteFile;
+
+//JDK imports
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class RemoteFile implements RemoteFileMetKeys {
+
+    private Metadata metadata;
+
+    private RemoteSiteFile pFile;
+
+    public RemoteFile(RemoteSiteFile pFile) {
+        this.pFile = pFile;
+        this.metadata = new Metadata();
+        this.metadata.addMetadata(RETRIEVED_FROM_LOC, pFile.getPath());
+        this.metadata.addMetadata(FILENAME, pFile.getName());
+        this.metadata.addMetadata(DATA_PROVIDER, pFile.getSite().getURL().getHost());
+    }
+
+    public void setUniqueMetadataElement(String uniqueMetadataElement) {
+        this.metadata.addMetadata(PRODUCT_NAME, this
+                .getMetadata(uniqueMetadataElement));
+    }
+
+    public void addMetadata(String key, String value) {
+        this.metadata.addMetadata(key, value);
+    }
+
+    public void addMetadata(Metadata metadata) {
+        this.metadata.addMetadata(metadata);
+    }
+
+    public String getMetadata(String key) {
+        return this.metadata.getMetadata(key);
+    }
+
+    public Metadata getAllMetadata() {
+        return this.metadata;
+    }
+
+    public RemoteSiteFile getProtocolFile() {
+        return this.pFile;
+    }
+
+    public void writeToPropEqValFile(String filePath,
+            String[] metadataToWriteOut) throws IOException {
+        try {
+            SerializableMetadata sMetadata = new SerializableMetadata("UTF-8",
+                    false);
+            for (String metadataKey : metadataToWriteOut)
+                if (this.metadata.getMetadata(metadataKey) != null
+                        && !this.metadata.getMetadata(metadataKey).equals(""))
+                    sMetadata.addMetadata(metadataKey, this.metadata
+                            .getMetadata(metadataKey));
+            sMetadata.writeMetadataToXmlStream(new FileOutputStream(filePath));
+        } catch (Exception e) {
+            throw new IOException("Failed to write metadata file for "
+                    + this.pFile + " : " + e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/RemoteFileMetKeys.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/RemoteFileMetKeys.java
new file mode 100644
index 0000000..b63107d
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/RemoteFileMetKeys.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.retrievalsystem;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Met keys needed by the {@link RemoteFile}
+ * </p>.
+ */
+public interface RemoteFileMetKeys {
+
+    public static final String PRODUCT_NAME = "ProductName";
+
+    public static final String RETRIEVED_FROM_LOC = "RetrievedFromLoc";
+
+    public static final String FILENAME = "Filename";
+
+    public static final String DATA_PROVIDER = "DataProvider";
+
+    public static final String FILE_SIZE = "FileSize";
+
+    public static final String RENAMING_STRING = "RenamingString";
+
+    public static final String DOWNLOAD_TO_DIR = "DownloadToDir";
+
+    public static final String PRODUCT_TYPE = "ProductType";
+
+    public static final String MIME_TYPE = "MimeType";
+    
+    public static final String SUPER_TYPE = "SuperType";
+
+    public static final String DELETE_AFTER_DOWNLOAD = "DeleteAfterDownload";
+    
+    public static final String PRODUCT_NAME_GENERATOR = "ProductNameGenerator";
+    
+    public static final String UNIQUE_ELEMENT = "UniqueElement";
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/RetrievalSetup.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/RetrievalSetup.java
new file mode 100644
index 0000000..ae59506
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/RetrievalSetup.java
@@ -0,0 +1,277 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.retrievalsystem;
+
+//JDK imports
+import static org.apache.oodt.cas.metadata.util.PathUtils.doDynamicReplacement;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+//OODT imports
+import org.apache.oodt.cas.pushpull.config.Config;
+import org.apache.oodt.cas.pushpull.config.DataFilesInfo;
+import org.apache.oodt.cas.pushpull.config.SiteInfo;
+import org.apache.oodt.cas.pushpull.config.PropFilesInfo;
+import org.apache.oodt.cas.pushpull.config.ProtocolInfo;
+import org.apache.oodt.cas.pushpull.exceptions.ParserException;
+import org.apache.oodt.cas.pushpull.exceptions.RetrievalMethodException;
+import org.apache.oodt.cas.pushpull.filerestrictions.Parser;
+import org.apache.oodt.cas.pushpull.objectfactory.PushPullObjectFactory;
+import org.apache.oodt.cas.pushpull.retrievalmethod.RetrievalMethod;
+import org.apache.oodt.cas.pushpull.retrievalsystem.FileRetrievalSystem;
+import org.apache.oodt.commons.exec.ExecUtils;
+
+/**
+ *
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class RetrievalSetup {
+
+    private final Config config;
+
+    private final HashSet<File> alreadyProcessedPropFiles;
+
+    private final HashMap<Class<RetrievalMethod>, RetrievalMethod> classToRmMap;
+
+    private boolean downloadingProps;
+
+    private final SiteInfo siteInfo;
+
+    private final DataFileToPropFileLinker linker;
+
+    private final static Logger LOG = Logger.getLogger(RetrievalSetup.class
+            .getName());
+
+    public RetrievalSetup(Config config, SiteInfo siteInfo) {
+        this.downloadingProps = false;
+        this.config = config;
+        this.siteInfo = siteInfo;
+        alreadyProcessedPropFiles = new HashSet<File>();
+        classToRmMap = new HashMap<Class<RetrievalMethod>, RetrievalMethod>();
+        linker = new DataFileToPropFileLinker();
+    }
+
+    public void retrieveFiles(PropFilesInfo pfi, final DataFilesInfo dfi)
+            throws RetrievalMethodException {
+
+        FileRetrievalSystem dataFilesFRS = null;
+        try {
+            this.startPropFileDownload(pfi);
+
+            (dataFilesFRS = new FileRetrievalSystem(config, siteInfo))
+                    .initialize();
+            dataFilesFRS.registerDownloadListener(linker);
+
+            File[] propFiles = null;
+            while ((propFiles = getCurrentlyDownloadedPropFiles(pfi)).length > 0
+                    || downloadingProps) {
+                for (File propFile : propFiles) {
+                    try {
+                        Parser parser = pfi.getParserForFile(propFile);
+                        Class<RetrievalMethod> rmClass = config.getParserInfo()
+                                .getRetrievalMethod(parser);
+                        RetrievalMethod rm = null;
+                        if ((rm = this.classToRmMap.get(rmClass)) == null) {
+                            LOG.log(Level.INFO, "Creating '"
+                                    + rmClass.getCanonicalName()
+                                    + "' to download data files");
+                            rm = PushPullObjectFactory
+                                    .createNewInstance(rmClass);
+                            this.classToRmMap.put(rmClass, rm);
+                        }
+                        rm.processPropFile(dataFilesFRS, parser, propFile, dfi,
+                                linker);
+                    } catch (ParserException e) {
+                        LOG.log(Level.SEVERE, "Failed to parse property file "
+                                + propFile + " : " + e.getMessage(), e);
+                        linker.markAsFailed(propFile,
+                                "Failed to parse property file " + propFile
+                                        + " : " + e.getMessage());
+                    } catch (Exception e) {
+                        LOG.log(Level.SEVERE,
+                                "Failed to finish downloading per property files "
+                                        + propFile.getAbsolutePath() + " : "
+                                        + e.getMessage(), e);
+                        linker.markAsFailed(propFile,
+                                "Error while downloading per property file "
+                                        + propFile.getAbsolutePath() + " : "
+                                        + e.getMessage());
+                    }
+                }
+
+                dataFilesFRS.waitUntilAllCurrentDownloadsAreComplete();
+
+                for (File propFile : propFiles) {
+                    try {
+                        if (pfi.getLocalDir().equals(pfi.getOnSuccessDir())
+                                || pfi.getLocalDir().equals(pfi.getOnFailDir()))
+                            alreadyProcessedPropFiles.add(propFile);
+                        this.movePropsFileToFinalDestination(pfi, propFile,
+                                linker.getErrorsAndEraseLinks(propFile));
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        LOG.log(Level.SEVERE,
+                                "Error occurred while writing errors to error dir for file '"
+                                        + propFile + "' : " + e.getMessage());
+                    }
+                }
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            if (dataFilesFRS != null)
+                dataFilesFRS.shutdown();
+            alreadyProcessedPropFiles.clear();
+            linker.clear();
+        }
+    }
+
+    private void startPropFileDownload(final PropFilesInfo pfi)
+            throws IOException {
+        if (pfi.needsToBeDownloaded()) {
+            this.downloadingProps = true;
+            new Thread(new Runnable() {
+
+                @Override
+               public void run() {
+                    FileRetrievalSystem frs = null;
+                    try {
+                        (frs = new FileRetrievalSystem(
+                                RetrievalSetup.this
+                                        .createPropFilesConfig(config
+                                                .getProtocolInfo()), siteInfo))
+                                .initialize();
+
+                        LinkedList<File> propDirStructFiles = pfi
+                                .getDownloadInfoPropFiles();
+                        for (File dirStructFile : propDirStructFiles) {
+                            Parser parser = pfi.getParserForFile(dirStructFile);
+                            Class<RetrievalMethod> rmClass = config
+                                    .getParserInfo().getRetrievalMethod(parser);
+                            RetrievalMethod rm = null;
+                            if ((rm = RetrievalSetup.this.classToRmMap
+                                    .get(rmClass)) == null) {
+                                LOG.log(Level.INFO, "Creating '"
+                                        + rmClass.getCanonicalName()
+                                        + "' to download property files");
+                                rm = PushPullObjectFactory
+                                        .createNewInstance(rmClass);
+                                RetrievalSetup.this.classToRmMap.put(rmClass,
+                                        rm);
+                            }
+                            rm.processPropFile(frs, parser, dirStructFile,
+                                    new DataFilesInfo(null, pfi
+                                            .getDownloadInfo()), linker);
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    } finally {
+                        if (frs != null)
+                            frs.shutdown();
+                        RetrievalSetup.this.downloadingProps = false;
+                    }
+                }
+
+            }).start();
+
+            // give property file download a 5 sec head start
+            LOG
+                    .log(
+                            Level.INFO,
+                            "Waiting data download thread for 5 secs to give the property files download thread a head start");
+            synchronized (this) {
+                try {
+                    this.wait(5000);
+                } catch (Exception e) {
+                }
+            }
+        }
+    }
+
+    private File[] getCurrentlyDownloadedPropFiles(final PropFilesInfo pfi) {
+        File[] files = pfi.getLocalDir().listFiles(new FileFilter() {
+            @Override
+            public boolean accept(File pathname) {
+                return pfi.getParserForFile(pathname) != null
+                        && !(pathname.getName().startsWith("Downloading_")
+                                || pathname.getName().endsWith(
+                                        RetrievalSetup.this.config
+                                                .getMetFileExtension()) || alreadyProcessedPropFiles
+                                .contains(pathname));
+            }
+        });
+        return files == null ? new File[0] : files;
+    }
+
+    private Config createPropFilesConfig(ProtocolInfo pi) {
+        Config propConfig = this.config.clone();
+        ProtocolInfo propPI = pi.clone();
+        propPI.setPageSize(-1);
+        propConfig.setProtocolInfo(propPI);
+        propConfig.setUseTracker(false);
+        propConfig.setIngester(null);
+        propConfig.setOnlyDownloadDefinedTypes(false);
+        return propConfig;
+    }
+
+    private void movePropsFileToFinalDestination(PropFilesInfo pfi,
+            File dirstructFile, String errorMsgs) throws IOException {
+        File metFile = new File(
+            String.format("%s.%s", dirstructFile.getAbsolutePath(), config.getMetFileExtension()));
+        if (pfi.getDeleteOnSuccess() && errorMsgs == null) {
+            dirstructFile.delete();
+            metFile.delete();
+            return;
+        }
+        File moveToDir = pfi.getFinalDestination(errorMsgs == null);
+        moveToDir.mkdirs();
+        File newLoc = new File(moveToDir, dirstructFile.getName());
+        dirstructFile.renameTo(newLoc);
+        metFile.renameTo(new File(
+            String.format("%s.%s", newLoc.getAbsolutePath(), config.getMetFileExtension())));
+        if (errorMsgs != null) {
+            File errorFile = new File(newLoc.getParentFile(), dirstructFile
+                    .getName()
+                    + ".errors");
+            errorFile.createNewFile();
+            
+            PrintStream ps = new PrintStream(new FileOutputStream(errorFile));
+            ps.print(errorMsgs);
+            ps.println();
+            ps.close();
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/TimeAndThreadCount.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/TimeAndThreadCount.java
new file mode 100644
index 0000000..f8f3985
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/retrievalsystem/TimeAndThreadCount.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.retrievalsystem;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class TimeAndThreadCount {
+
+    private long startTimeInMillis;
+
+    private int threadCount;
+
+    public TimeAndThreadCount(long startTimeInMillis, int threadCount) {
+        this.startTimeInMillis = startTimeInMillis;
+        this.threadCount = threadCount;
+    }
+
+    public long getStartTimeInMillis() {
+        return this.startTimeInMillis;
+    }
+
+    public int getThreadCount() {
+        return this.threadCount;
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/url/handlers/imaps/Handler.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/url/handlers/imaps/Handler.java
new file mode 100644
index 0000000..c5ed8c2
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/url/handlers/imaps/Handler.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.url.handlers.imaps;
+
+//JDK imports
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class Handler extends URLStreamHandler {
+
+    @Override
+    protected URLConnection openConnection(URL url) throws IOException {
+        return new ImapsURLConnection(url);
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/url/handlers/imaps/ImapsURLConnection.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/url/handlers/imaps/ImapsURLConnection.java
new file mode 100644
index 0000000..6e1d792
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/url/handlers/imaps/ImapsURLConnection.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.url.handlers.imaps;
+
+//JDK imports
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class ImapsURLConnection extends URLConnection {
+
+    protected ImapsURLConnection(URL url) {
+        super(url);
+    }
+
+    @Override
+    public void connect() throws IOException {
+        // do nothing
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/url/handlers/sftp/Handler.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/url/handlers/sftp/Handler.java
new file mode 100644
index 0000000..e80a030
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/url/handlers/sftp/Handler.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.url.handlers.sftp;
+
+//JDK imports
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class Handler extends URLStreamHandler {
+
+    @Override
+    protected URLConnection openConnection(URL url) throws IOException {
+        return new SftpURLConnection(url);
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/url/handlers/sftp/SftpURLConnection.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/url/handlers/sftp/SftpURLConnection.java
new file mode 100644
index 0000000..ff63cdc
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/url/handlers/sftp/SftpURLConnection.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.url.handlers.sftp;
+
+//JDK imports
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public class SftpURLConnection extends URLConnection {
+
+    protected SftpURLConnection(URL url) {
+        super(url);
+    }
+
+    @Override
+    public void connect() throws IOException {
+        // do nothing!!!
+    }
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/util/ExpressionValidator.java b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/util/ExpressionValidator.java
new file mode 100644
index 0000000..ea3f49f
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/java/org/apache/oodt/cas/pushpull/util/ExpressionValidator.java
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.pushpull.util;
+
+//AWT Imports
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+//Swing Imports
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JFormattedTextField;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>Use to evaluate whether your regular expressions are 
+ * accepting the correct strings
+ * </p>.
+ */
+public class ExpressionValidator extends JPanel {
+
+	private static final long serialVersionUID = -2840589940304298547L;
+
+	private JLabel exprLabel;
+	private JLabel validateLabel;
+	private JLabel resultLabel;
+	
+	private JFormattedTextField exprField;
+	private JFormattedTextField validateField;
+	private JFormattedTextField resultField;
+
+	public ExpressionValidator() {
+		super(new BorderLayout());
+
+		exprLabel = new JLabel("Regular Expression: ");
+		validateLabel = new JLabel("Validate String: ");
+		resultLabel = new JLabel("Result: ");
+
+		exprField = new JFormattedTextField();
+		exprField.setColumns(60);
+
+		validateField = new JFormattedTextField();
+		validateField.setColumns(60);
+
+		resultField = new JFormattedTextField();
+		resultField.setColumns(60);
+		resultField.setEditable(false);
+		resultField.setForeground(Color.red);
+
+		exprLabel.setLabelFor(exprField);
+		validateLabel.setLabelFor(validateField);
+		resultLabel.setLabelFor(resultField);
+
+		JPanel labelPane = new JPanel(new GridLayout(0, 1));
+		labelPane.add(exprLabel);
+		labelPane.add(validateLabel);
+		labelPane.add(resultLabel);
+
+		JPanel fieldPane = new JPanel(new GridLayout(0, 1));
+		fieldPane.add(exprField);
+		fieldPane.add(validateField);
+		fieldPane.add(resultField);
+
+		JPanel buttonPane = new JPanel(new BorderLayout());
+		JButton validate = new JButton("Validate");
+		validate.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent event) {
+				try {
+					boolean value = ((String) validateField.getText()).matches((String) exprField.getText());
+					resultField.setText(value + "");
+				}catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		});
+		buttonPane.add(validate, BorderLayout.EAST);
+		
+		setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
+		add(labelPane, BorderLayout.WEST);
+		add(fieldPane, BorderLayout.CENTER);
+		add(buttonPane, BorderLayout.EAST);
+	}
+
+	public static void main(String[] args) {
+		SwingUtilities.invokeLater(new Runnable() {
+			public void run() {
+			    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
+				JFrame frame = new JFrame("Regular Expression Evaluator");
+				frame.setSize(dim.width / 2, dim.height / 2);
+			    frame.setLocation(dim.width / 3, dim.height / 3);
+				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+				frame.add(new ExpressionValidator());
+				frame.pack();
+				frame.setVisible(true);
+			}
+		});
+	}
+
+}
diff --git a/0.8.1-rc1/pushpull/src/main/resources/REMOVE.log b/0.8.1-rc1/pushpull/src/main/resources/REMOVE.log
new file mode 100644
index 0000000..cb27d16
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/REMOVE.log
@@ -0,0 +1,18 @@
+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.
+
+
+You can remove this file. It was only included to ensure that the log directory for this
+distribution was created on assembly.
diff --git a/0.8.1-rc1/pushpull/src/main/resources/default.properties b/0.8.1-rc1/pushpull/src/main/resources/default.properties
new file mode 100644
index 0000000..a50664d
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/default.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+#-------------------------------------------------------#
+#-----------------Protocol Defaults---------------------#
+#-------------------------------------------------------#
+
+#configuration to make java.net.URL accept unsupported protocols
+java.protocol.handler.pkgs=org.apache.oodt.cas.pushpull.url.handlers
diff --git a/0.8.1-rc1/pushpull/src/main/resources/documentation/Push-Pull-User-Manual_2008-02-12.doc b/0.8.1-rc1/pushpull/src/main/resources/documentation/Push-Pull-User-Manual_2008-02-12.doc
new file mode 100755
index 0000000..5fb5e28
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/documentation/Push-Pull-User-Manual_2008-02-12.doc
Binary files differ
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/ClassNoaaEmailParserFiles/IasiEmail b/0.8.1-rc1/pushpull/src/main/resources/examples/ClassNoaaEmailParserFiles/IasiEmail
new file mode 100644
index 0000000..7141348
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/ClassNoaaEmailParserFiles/IasiEmail
@@ -0,0 +1,129 @@
+
+
+             NOAA  COMPREHENSIVE LARGE ARRAY-DATA STEWARDSHIP SYSTEM
+
+                          A SERVICE OF:
+                   NOAA NATIONAL DATA CENTERS
+
+
+The CLASS has processed your order number A1040663.  The total size of 
+this order is 1246002618 bytes.
+
+
+Items are available for you in the anonymous FTP area. 
+You may obtain them as follows:
+
+   ftp ftp.class.noaa.gov   - Logon to CLASS system
+   anonymous          - login userid
+   user@internet      - enter your internet address as a password
+   binary             - changes transfer mode to binary
+   cd A1040663        - changes to correct directory
+   get 
+IASI_xxx_1C_M02_20070803000257Z_20070803000553Z_N_O_20070803013826Z__20070803014
+346
+                      - copies data; size is 60242714 bytes
+   get 
+IASI_xxx_1C_M02_20070802235953Z_20070803000257Z_N_O_20070803013555Z__20070803014
+041
+                      - copies data; size is 62970482 bytes
+   get 
+IASI_xxx_1C_M02_20070803000553Z_20070803000857Z_N_O_20070803014058Z__20070803014
+616
+                      - copies data; size is 62970482 bytes
+   get 
+IASI_xxx_1C_M02_20070803000857Z_20070803000953Z_N_O_20070803014332Z__20070803014
+646
+                      - copies data; size is 19326194 bytes
+   get 
+IASI_xxx_1C_M02_20070803001218Z_20070803001457Z_N_O_20070803014438Z__20070803014
+957
+                      - copies data; size is 54787178 bytes
+   get 
+IASI_xxx_1C_M02_20070803001458Z_20070803001753Z_N_O_20070803014619Z__20070803015
+222
+                      - copies data; size is 60242714 bytes
+   get 
+IASI_xxx_1C_M02_20070803001754Z_20070803002057Z_N_O_20070803014825Z__20070803015
+507
+                      - copies data; size is 62970482 bytes
+   get 
+IASI_xxx_1C_M02_20070803002058Z_20070803002353Z_N_O_20070803015110Z__20070803015
+742
+                      - copies data; size is 60242714 bytes
+   get 
+IASI_xxx_1C_M02_20070803002354Z_20070803002657Z_N_O_20070803015337Z__20070803020
+042
+                      - copies data; size is 62970482 bytes
+   get 
+IASI_xxx_1C_M02_20070803002658Z_20070803002953Z_N_O_20070803015605Z__20070803020
+202
+                      - copies data; size is 60242714 bytes
+   get 
+IASI_xxx_1C_M02_20070803002954Z_20070803003257Z_N_O_20070803021709Z__20070803022
+207
+                      - copies data; size is 62970482 bytes
+   get 
+IASI_xxx_1C_M02_20070803004458Z_20070803004753Z_N_O_20070803022947Z__20070803023
+437
+                      - copies data; size is 60242714 bytes
+   get 
+IASI_xxx_1C_M02_20070803003554Z_20070803003857Z_N_O_20070803022252Z__20070803022
+802
+                      - copies data; size is 62970482 bytes
+   get 
+IASI_xxx_1C_M02_20070803003858Z_20070803004153Z_N_O_20070803022515Z__20070803023
+102
+                      - copies data; size is 60242714 bytes
+   get 
+IASI_xxx_1C_M02_20070803004154Z_20070803004457Z_N_O_20070803022746Z__20070803023
+352
+                      - copies data; size is 62970482 bytes
+   get 
+IASI_xxx_1C_M02_20070803003258Z_20070803003553Z_N_O_20070803021943Z__20070803022
+507
+                      - copies data; size is 60242714 bytes
+   get 
+IASI_xxx_1C_M02_20070803005058Z_20070803005353Z_N_O_20070803023436Z__20070803024
+017
+                      - copies data; size is 60242714 bytes
+   get 
+IASI_xxx_1C_M02_20070803005354Z_20070803005657Z_N_O_20070803023700Z__20070803024
+132
+                      - copies data; size is 62970482 bytes
+   get 
+IASI_xxx_1C_M02_20070803005658Z_20070803005953Z_N_O_20070803023936Z__20070803024
+357
+                      - copies data; size is 60242714 bytes
+   get 
+IASI_xxx_1C_M02_20070803005954Z_20070803010257Z_N_O_20070803024159Z__20070803024
+657
+                      - copies data; size is 62970482 bytes
+   get 
+IASI_xxx_1C_M02_20070803004754Z_20070803005057Z_N_O_20070803023212Z__20070803023
+737
+                      - copies data; size is 62970482 bytes
+   bye  (or quit)     - to end ftp session.
+
+Alternatively, you can also pick up your data set via 
+ftp://ftp.class.noaa.gov/A1040663/
+                                                   or 
+http://www.class.noaa.gov/download/A1040663
+
+NOTE: You must pick up your data within 120 hours of this notice.
+
+
+
+
+Thank you.
+
+
+<< DO NOT reply to this e-mail as it is automatically generated. >>
+<< Please direct questions to the Help Desk: >>
+
+
+                   NOAA/CLASS User Assistance
+                   National Climatic Data Center
+                   151 Patton Avenue
+                   Asheville, NC 28801-5001
+
+                   Internet: info@class.noaa.gov
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/AIRABRAD.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/AIRABRAD.xml
new file mode 100644
index 0000000..d7b0491
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/AIRABRAD.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<root>
+    <dirstruct starting_path="/ftp/data/s4pa/Aqua_AIRS_Level1/AIRABRAD.005/2006">
+        <nofiles/>
+        <dir name="\d{3}">
+            <nodirs/>
+            <file name="AIRS\.2006\.\d{2}\.\d{2}\.\d{3}.L1B.AMSU_Rad\.v5\.0\.0\.0\.G\d{11}\.hdf(\.xml){0,1}"/>
+        </dir>
+    </dirstruct>
+</root>
\ No newline at end of file
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/AIRS3ST8.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/AIRS3ST8.xml
new file mode 100644
index 0000000..bae8cea
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/AIRS3ST8.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+<root>
+    <dirstruct starting_path="/data/s4pa/Aqua_AIRS_Level3/AIRS3ST8.005/2007">
+        <nodirs/>
+        <file name="AIRS\.2007.\d{2}.\d{2}.L3.RetStd_IR008\.v5\.0\.14\.0\.G\d{11}\.hdf(\.xml){0,1}"/>
+    </dirstruct>
+</root>
\ No newline at end of file
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/AIRS3STD.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/AIRS3STD.xml
new file mode 100644
index 0000000..8b45a34
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/AIRS3STD.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+<root>
+    <dirstruct starting_path="/data/s4pa/Aqua_AIRS_Level3/AIRS3STD.005/2007">
+        <nodirs/>
+        <file name="AIRS\.2007.\d{2}.\d{2}.L3.RetStd_IR001\.v5\.0\.14\.0\.G\d{11}\.hdf(\.xml){0,1}"/>
+    </dirstruct>
+</root>
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/CLASS_Email.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/CLASS_Email.xml
new file mode 100644
index 0000000..0c55af3
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/CLASS_Email.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<root>
+    <dirstruct starting_path="INBOX">
+        <nodirs/>
+    </dirstruct>
+</root>
\ No newline at end of file
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/CLASS_Text_Email.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/CLASS_Text_Email.xml
new file mode 100644
index 0000000..c4399c5
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/CLASS_Text_Email.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<root>
+    <dirstruct starting_path="/home/class/TextMail">
+        <dir name="\d{4}-\d{2}-\d{2}_\d{2}">
+            <dir name="class">
+                <nodirs/>
+            </dir>                
+        </dir>
+    </dirstruct>
+</root>
\ No newline at end of file
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/CloudSAT.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/CloudSAT.xml
new file mode 100644
index 0000000..c3477ae
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/CloudSAT.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+<root>
+    <dirstruct starting_path="2B-CWC-RO.R04/2007/304"/>
+</root>
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/GFS.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/GFS.xml
new file mode 100644
index 0000000..6ceea12
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/GFS.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<root>
+    <dirstruct starting_path="/pub/data/nccf/com/gfs/prod">
+        <nofiles/>
+        <dir name="gfs\.\d{8}((12)|(00))">
+            <nodirs/>
+            <file name="gfs\.t((00)|(12))z\.pgrb2f((03)|(06)|(09)|(12))"/>
+        </dir>
+    </dirstruct>
+</root>
+    
+    
+
+        
\ No newline at end of file
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/IASI.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/IASI.xml
new file mode 100644
index 0000000..d63e871
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/IASI.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<root>
+    <dirstruct starting_path="/misc/raid2/IASI/L1C/2007">
+        <nofiles/>
+    </dirstruct>
+</root>
\ No newline at end of file
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/IASI_2.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/IASI_2.xml
new file mode 100644
index 0000000..30bdbd8
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/IASI_2.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<root>
+    <dirstruct root_based="true" starting_path="/A6719183">
+        <nodirs/>
+    </dirstruct>
+</root>
\ No newline at end of file
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/IBIBLIO.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/IBIBLIO.xml
new file mode 100644
index 0000000..009e297
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/IBIBLIO.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<root>
+    <dirstruct starting_path="/mirrors/apache/">
+        <nofiles/>
+        <dir name="ant">
+            <nodirs/>
+        </dir>
+    </dirstruct>
+</root>
\ No newline at end of file
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/MODIS.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/MODIS.xml
new file mode 100644
index 0000000..12cf2d9
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/MODIS.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+<root>
+    <dirstruct starting_path="/MOTA/MCD43B1.005/2007.02.02">
+        <nodirs/>
+        <file name="MCD43B1\.A2007033\.h\d{2}v\d{2}\.005\.\d{13}\.hdf(\.xml){0,1}"/>
+    </dirstruct>
+</root>
\ No newline at end of file
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/RTG_SST.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/RTG_SST.xml
new file mode 100644
index 0000000..0dfbc5f
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/DirStructXmlParserFiles/RTG_SST.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<root>
+    <dirstruct starting_path="/pub/history/sst">
+        <nodirs/>
+        <file name="rtg_sst_grb_0\.5\.\d{8}"/>
+    </dirstruct>
+</root>
+        
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/ExternalSourcesFiles/ExternalSources.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/ExternalSourcesFiles/ExternalSources.xml
new file mode 100644
index 0000000..242b883
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/ExternalSourcesFiles/ExternalSources.xml
@@ -0,0 +1,75 @@
+<?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.
+-->
+<sources>
+    <source host="polar.ncep.noaa.gov">
+        <login type="ftp" alias="PolarNcepNoaaFtp">
+            <username>anonymous</username>
+            <password>user@host.com</password>
+        </login>
+    </source>    
+    <source host="ftp1.cloudsat.cira.colostate.edu">
+        <login type="ftp" alias="CloudSATFtp">
+            <username></username>
+            <password></password>
+            <cdTestDir>2B-CWC-RO.R04/2007/304</cdTestDir>
+            <maxConn>5</maxConn>
+        </login>
+    </source>
+    <source host="ftp.class.noaa.gov">
+        <login type="ftp" alias="ClassFtp">
+            <username>anonymous</username>
+            <password>user@host.com</password>
+        </login>
+    </source>
+    <source host="localhost">
+        <login type="file" alias="localhost">
+            <username>none</username>
+            <password>none</password>
+        </login>
+    </source>
+    <source host="ftpprd.ncep.noaa.gov">
+        <login type="ftp" alias="GfsFtp">
+            <username>anonymous</username>
+            <password>user@host.com</password>
+        </login>
+    </source>
+    <source host="e4ftl01u.ecs.nasa.gov">
+        <login type="ftp" alias="ModisFtp">
+            <username>anonymous</username>
+            <password>user@host.com</password>
+        </login>
+    </source>
+    <source host="airscal2u.ecs.nasa.gov">
+        <login type="ftp" alias="GdaacFtp">
+            <username>anonymous</username>
+            <password>user@host.com</password>
+        </login>
+    </source>
+    <source host="acdisc.gsfc.nasa.gov">
+        <login type="ftp" alias="AcdiscGsfcFtp">
+            <username>anonymous</username>
+            <password>user@host.com</password>
+        </login>
+    </source>
+    <source host="www.signal42.com">
+        <login type="http" alias="Signal42ApacheMirrorHttp">
+            <username>none</username>
+            <password>none</password>
+        </login>
+    </source>
+</sources>
\ No newline at end of file
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/FileListParserFiles/DownloadList.txt b/0.8.1-rc1/pushpull/src/main/resources/examples/FileListParserFiles/DownloadList.txt
new file mode 100644
index 0000000..9280931
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/FileListParserFiles/DownloadList.txt
@@ -0,0 +1,7 @@
+/misc/raid2/IASI/L1C/2007/06/30
+IASI_xxx_1C_M02_20070629235953Z_20070630000256Z_N_O_20070630013723Z__20070630014330
+IASI_xxx_1C_M02_20070630000257Z_20070630000552Z_N_O_20070630013952Z__20070630014640
+IASI_xxx_1C_M02_20070630000553Z_20070630000856Z_N_O_20070630014220Z__20070630014740
+IASI_xxx_1C_M02_20070630000857Z_20070630001152Z_N_O_20070630014452Z__20070630014944
+IASI_xxx_1C_M02_20070630001153Z_20070630001456Z_N_O_20070630014718Z__20070630015234
+IASI_xxx_1C_M02_20070630001753Z_20070630002056Z_N_O_20070630015228Z__20070630015909
diff --git "a/0.8.1-rc1/pushpull/src/main/resources/examples/ProcmailForwarding/\133dot\135forward" "b/0.8.1-rc1/pushpull/src/main/resources/examples/ProcmailForwarding/\133dot\135forward"
new file mode 100644
index 0000000..4f0d5bc
--- /dev/null
+++ "b/0.8.1-rc1/pushpull/src/main/resources/examples/ProcmailForwarding/\133dot\135forward"
@@ -0,0 +1 @@
+"|IFS=' '&&p=/usr/local/bin/procmail&&test -f $p&&exec $p -f-||exit 75#class"
\ No newline at end of file
diff --git "a/0.8.1-rc1/pushpull/src/main/resources/examples/ProcmailForwarding/\133dot\135procmail/general.rc" "b/0.8.1-rc1/pushpull/src/main/resources/examples/ProcmailForwarding/\133dot\135procmail/general.rc"
new file mode 100644
index 0000000..901cfd7
--- /dev/null
+++ "b/0.8.1-rc1/pushpull/src/main/resources/examples/ProcmailForwarding/\133dot\135procmail/general.rc"
@@ -0,0 +1,25 @@
+MONTHFOLDER= `date +%Y-%m-%d_%H `
+DUMMY= `test -d $MONTHFOLDER || mkdir -m g=rwx $MONTHFOLDER `
+
+CLASS_FOLDER= ${MONTHFOLDER}/class
+UNKNOWN_FOLDER= ${MONTHFOLDER}/unknown
+JPL_FOLDER= ${MONTHFOLDER}/jpl
+DUMMY= `test -d $CLASS_FOLDER || mkdir -m g=rwx $CLASS_FOLDER `
+DUMMY= `test -d $UNKNOWN_FOLDER || mkdir -m g=rwx $UNKNOWN_FOLDER `
+DUMMY= `test -d $JPL_FOLDER || mkdir -m g=rwx $JPL_FOLDER `
+
+:0 fw
+* 
+| formail -k -X From: -X Subject: 
+
+:0 :
+* ^From.*class\.noaa\.gov 
+${CLASS_FOLDER}
+
+:0 :
+* ^From.*jpl\.nasa\.gov
+${JPL_FOLDER}
+
+:0 :
+* 
+${UNKNOWN_FOLDER} 
diff --git "a/0.8.1-rc1/pushpull/src/main/resources/examples/ProcmailForwarding/\133dot\135procmailrc" "b/0.8.1-rc1/pushpull/src/main/resources/examples/ProcmailForwarding/\133dot\135procmailrc"
new file mode 100644
index 0000000..65524a1
--- /dev/null
+++ "b/0.8.1-rc1/pushpull/src/main/resources/examples/ProcmailForwarding/\133dot\135procmailrc"
@@ -0,0 +1,7 @@
+VERBOSE=off
+UMASK=007
+MAILDIR=$HOME/TextMail
+PMDIR=$HOME/.procmail
+DEFAULT=$MAILDIR
+LOGFILE=$PMDIR/log
+INCLUDERC=$PMDIR/general.rc
diff --git a/0.8.1-rc1/pushpull/src/main/resources/examples/RemoteSpecsFiles/RemoteSpecs.xml b/0.8.1-rc1/pushpull/src/main/resources/examples/RemoteSpecsFiles/RemoteSpecs.xml
new file mode 100644
index 0000000..bf4ed22
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/examples/RemoteSpecsFiles/RemoteSpecs.xml
@@ -0,0 +1,181 @@
+<?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.
+-->
+<remoteSpecs>
+    
+    <aliasSpecs>
+        <aliasSpec file="[CAS_PP_RESOURCES]/examples/ExternalSourcesFiles/ExternalSources.xml"/>
+    </aliasSpecs>
+
+    <daemons>
+        
+        <daemon alias="DewFtp" active="no">
+            <runInfo firstRunDateTime="2007-12-01T00:00:00Z" period="3m" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_RESOURCES]/examples/DirStructXmlParserFiles">
+                <propFiles regExp="IASI\.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+            </propInfo>
+            <dataInfo stagingArea="DewFtp" deleteFromServer="no"/>               
+        </daemon>
+        
+        <daemon alias="DewFtp" active="no">
+            <runInfo firstRunDateTime="2007-12-01T00:00:00Z" period="3m" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_TEMP_PROPS]/WeatherSftp">
+                <downloadInfo alias="WeatherSftp" remoteDir="junkTest"/>
+                <propFiles regExp="IASI\.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+            </propInfo>
+            <dataInfo stagingArea="DewFtp" deleteFromServer="no"/>
+        </daemon>
+        
+        <daemon alias="CalPolySftp" active="no">
+            <runInfo firstRunDateTime="2007-12-01T00:00:00Z" period="3m" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_RESOURCES]/examples/DirStructXmlParserFiles">
+                <propFiles regExp="CalPoly\.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+            </propInfo>
+            <dataInfo stagingArea="CalPolySftp" deleteFromServer="no"/>
+        </daemon>
+        
+        <daemon alias="WeatherSftp" active="no">
+            <runInfo firstRunDateTime="2007-12-01T00:00:00Z" period="3m" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_RESOURCES]/examples/DirStructXmlParserFiles">
+                <propFiles regExp="IASI\.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+            </propInfo>
+            <dataInfo stagingArea="WeatherSftp" deleteFromServer="no"/>            
+        </daemon>
+        
+        <daemon alias="WeatherSftp" active="no">
+            <runInfo firstRunDateTime="2007-12-01T00:00:00Z" period="3m" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_TEMP_PROPS]/WeatherSftp">
+                <downloadInfo alias="WeatherSftp" remoteDir="junkTest"/>
+                <propFiles regExp="IASI\.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+            </propInfo>
+            <dataInfo stagingArea="WeatherSftp" deleteFromServer="no" queryElement="RetrievedFromLoc"/>                
+        </daemon>
+        
+        <daemon alias="WeatherSftp" active="no">
+            <runInfo firstRunDateTime="2007-12-24T00:10:00Z" period="3m" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_RESOURCES]/examples/FileListParserFiles">
+                <propFiles regExp="DownloadList\.txt" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.FileListParser"/>
+            </propInfo>
+            <dataInfo stagingArea="WeatherSftp" deleteFromServer="no" queryElement="RetrievedFromLoc"/>
+        </daemon>
+        
+        <daemon alias="ClassFtp" active="no">
+            <runInfo firstRunDateTime="2007-12-01T00:00:00Z" period="3m" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_RESOURCES]/examples/DirStructXmlParserFiles">
+                <propFiles regExp="IASI_2.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+            </propInfo>
+            <dataInfo stagingArea="ClassFtp" deleteFromServer="no" queryElement="Filename"/>
+        </daemon>
+        
+        <daemon alias="ClassFtp" active="no">
+            <runInfo firstRunDateTime="2007-12-01T00:00:00Z" period="3m" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_RESOURCES]/examples/ClassNoaaEmailParserFiles">
+                <propFiles regExp="[^\.].*" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.ClassNoaaEmailParser"/>
+            </propInfo>
+            <dataInfo stagingArea="ClassFtp" deleteFromServer="no" queryElement="Filename"/>
+        </daemon>
+        
+        <daemon alias="ClassFtp" active="no">
+            <runInfo firstRunDateTime="2007-12-14T00:00:00Z" period="3m" epsilon="20s" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_TEMP_PROPS]/ClassFtp/Emails">
+                <downloadInfo alias="PeateImaps" deleteFromServer="yes" renamingConv="CLASS_[HOST]_[DATE.UTC]_[FILENAME].email">
+                    <propFile path="[CAS_PP_RESOURCES]/examples/DirStructXmlParserFiles/CLASS_Email.xml" 
+                        parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+                </downloadInfo>
+                <propFiles regExp=".*\.email" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.ClassNoaaEmailParser"/>
+                <afterUse moveToOnSuccess="[CAS_PP_TEMP_PROPS]/ClassFtp/ProcessedEmails" 
+                    moveToOnFail="[CAS_PP_TEMP_PROPS]/ClassFtp/FailedEmails"/>
+            </propInfo>
+            <dataInfo stagingArea="ClassFtp" deleteFromServer="no" allowAliasOverride="yes" 
+                queryElement="Filename" renamingConv="[GREP_RM('^L\d{1,}?\.','[FILENAME]')]"/>
+        </daemon>
+        
+        <daemon alias="ClassFtp" active="yes">
+            <runInfo firstRunDateTime="2007-12-14T00:00:00Z" period="3m" epsilon="20s" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_TEMP_PROPS]/ClassFtp/Emails">
+                <downloadInfo alias="localhost" deleteFromServer="yes" renamingConv="CLASS_[HOST]_[DATE.UTC]_[FILENAME].email">
+                    <propFile path="[CAS_PP_RESOURCES]/examples/DirStructXmlParserFiles/CLASS_Text_Email.xml" 
+                        parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+                </downloadInfo>
+                <propFiles regExp=".*\.email" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.ClassNoaaEmailParser"/>
+                <afterUse moveToOnSuccess="[CAS_PP_TEMP_PROPS]/ClassFtp/ProcessedEmails" 
+                    moveToOnFail="[CAS_PP_TEMP_PROPS]/ClassFtp/FailedEmails"/>
+            </propInfo>
+            <dataInfo stagingArea="ClassFtp" deleteFromServer="no" allowAliasOverride="yes" 
+                queryElement="Filename"/>
+        </daemon>
+        
+        <daemon alias="GfsFtp" active="no">
+            <runInfo firstRunDateTime="2007-11-27T00:00:00Z" period="3m" epsilon="20s" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_RESOURCES]/examples/DirStructXmlParserFiles">
+                <propFiles regExp="GFS\.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+            </propInfo>
+            <dataInfo stagingArea="GfsFtp" renamingConv="[PARENT_FILENAME]_[FILENAME]" queryElement="RetrievedFromLoc"/>
+        </daemon>
+        
+        <daemon alias="PolarNcepNoaaFtp" active="no">
+            <runInfo firstRunDateTime="2007-11-27T00:00:00Z" period="3m" epsilon="20s" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_RESOURCES]/examples/DirStructXmlParserFiles">
+                <propFiles regExp="RTG_SST\.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+            </propInfo>
+            <dataInfo stagingArea="RtgSstFtp" queryElement="Filename"/>
+        </daemon>
+
+        <daemon alias="ModisFtp" active="no">
+            <runInfo firstRunDateTime="2007-12-01T00:00:00Z" period="3m" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_RESOURCES]/examples/DirStructXmlParserFiles">
+                <propFiles regExp="MODIS\.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+            </propInfo>
+            <dataInfo stagingArea="ModisFtp" deleteFromServer="no" queryElement="RetrievedFromLoc"/>
+        </daemon>
+        
+        <daemon alias="GdaacFtp" active="no">
+            <runInfo firstRunDateTime="2007-12-01T00:00:00Z" period="3m" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_RESOURCES]/examples/DirStructXmlParserFiles">
+                <propFiles regExp="AIRABRAD\.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+            </propInfo>
+            <dataInfo stagingArea="GdaccFtp" deleteFromServer="no" queryElement="RetrievedFromLoc"/>
+        </daemon>
+        
+        <daemon alias="AcdiscGsfcFtp" active="no">
+            <runInfo firstRunDateTime="2007-12-01T00:00:00Z" period="3m" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_RESOURCES]/examples/DirStructXmlParserFiles">
+                <propFiles regExp="AIRS3STD\.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+                <propFiles regExp="AIRS3ST8\.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+            </propInfo>
+            <dataInfo stagingArea="AcdiscGsfcFtp" deleteFromServer="no" queryElement="RetrievedFromLoc"/>
+        </daemon>
+        
+        <daemon alias="Signal42ApacheMirrorHttp" active="no">
+            <runInfo firstRunDateTime="2007-12-01T00:00:00Z" period="3m" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_RESOURCES]/examples/DirStructXmlParserFiles">
+                <propFiles regExp="IBIBLIO\.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+            </propInfo>
+            <dataInfo stagingArea="Signal42ApacheMirrorHttp" deleteFromServer="no" queryElement="RetrievedFromLoc"/>
+        </daemon>
+        
+        <daemon alias="RimeSftp" active="no">
+            <runInfo firstRunDateTime="2008-02-19T00:00:00Z" period="3m" runOnReboot="yes"/>
+            <propInfo dir="[CAS_PP_RESOURCES]/examples/DirStructXmlParserFiles">
+                <propFiles regExp="RimeDIRSTRUCT.xml" parser="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+            </propInfo>
+            <dataInfo stagingArea="RimeSftp" renamingConv="[PATH_NO_FILENAME]/[FILENAME]" deleteFromServer="no" queryElement="RetrievedFromLoc"/>
+        </daemon>
+        
+    </daemons>
+    
+</remoteSpecs>
diff --git a/0.8.1-rc1/pushpull/src/main/resources/jssecacerts b/0.8.1-rc1/pushpull/src/main/resources/jssecacerts
new file mode 100644
index 0000000..7c8f621
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/jssecacerts
Binary files differ
diff --git a/0.8.1-rc1/pushpull/src/main/resources/logging.properties b/0.8.1-rc1/pushpull/src/main/resources/logging.properties
new file mode 100644
index 0000000..6af123f
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/logging.properties
@@ -0,0 +1,43 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.FileHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = ../logs/cas-pushpull%g.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 5
+java.util.logging.FileHandler.append = true
+java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
+
+java.lang.management.level = OFF
+java.rmi.registry.level = OFF
+javax.management.level = OFF
+javax.management.level = OFF
+sun.rmi.level = OFF
diff --git a/0.8.1-rc1/pushpull/src/main/resources/policy/ParserToRetrievalMethodMap.xml b/0.8.1-rc1/pushpull/src/main/resources/policy/ParserToRetrievalMethodMap.xml
new file mode 100644
index 0000000..537624c
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/policy/ParserToRetrievalMethodMap.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<rtvlMethods>
+    
+    <rtvlMethod class="org.apache.oodt.cas.pushpull.retrievalmethod.RemoteCrawler">
+        <parser class="org.apache.oodt.cas.pushpull.filerestrictions.parsers.DirStructXmlParser"/>
+    </rtvlMethod>
+    
+    <rtvlMethod class="org.apache.oodt.cas.pushpull.retrievalmethod.ListRetriever">
+        <parser class="org.apache.oodt.cas.pushpull.filerestrictions.parsers.FileListParser"/>
+        <parser class="org.apache.oodt.cas.pushpull.filerestrictions.parsers.ClassNoaaEmailParser"/>
+        <parser class="org.apache.oodt.cas.pushpull.filerestrictions.parsers.GenericEmailParser"/>
+    </rtvlMethod>
+    
+</rtvlMethods>
diff --git a/0.8.1-rc1/pushpull/src/main/resources/policy/ProtocolFactoryInfo.xml b/0.8.1-rc1/pushpull/src/main/resources/policy/ProtocolFactoryInfo.xml
new file mode 100644
index 0000000..d3c8c4e
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/policy/ProtocolFactoryInfo.xml
@@ -0,0 +1,45 @@
+<?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.
+-->
+<protocols>
+    
+    <protocol type="ftp">
+        <protocolFactory class="org.apache.oodt.cas.protocol.ftp.CogJGlobusFtpProtocolFactory"/>
+        <protocolFactory class="org.apache.oodt.cas.protocol.ftp.CommonsNetFtpProtocolFactory"/>
+    </protocol>
+    
+    <protocol type="http">
+        <protocolFactory class="org.apache.oodt.cas.protocol.http.HttpProtocolFactory"/>
+    </protocol>
+    
+    <protocol type="sftp">
+        <protocolFactory class="org.apache.oodt.cas.protocol.sftp.JschSftpProtocolFactory"/>
+    </protocol>
+    
+    <protocol type="imaps">
+        <protocolFactory class="org.apache.oodt.cas.protocol.imaps.ImapsProtocolFactory"/>
+    </protocol>
+    
+    <!--
+    Note: hasn't been implemented yet, see OODT-537 
+     
+    <protocol type="file">
+        <protocolFactory class="org.apache.oodt.cas.protocol.local.LocalProtocolFactory"/>    
+    </protocol>
+    -->
+    
+</protocols>
diff --git a/0.8.1-rc1/pushpull/src/main/resources/policy/mimetypes.xml b/0.8.1-rc1/pushpull/src/main/resources/policy/mimetypes.xml
new file mode 100644
index 0000000..36a5b98
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/policy/mimetypes.xml
@@ -0,0 +1,60 @@
+<?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.
+-->
+<mime-info>
+	
+	<mime-type type="product/pgp_signature">
+		<_comment><![CDATA[ProductNameGenerator=[GREP_RM('\.sig$','[FILENAME]')]]]></_comment>
+		<glob pattern="*.sig"/>
+	</mime-type>
+	
+	<mime-type type="metadata/cas_pushpull">
+		<glob pattern="*.info.tmp"/>
+	</mime-type>
+	
+	<mime-type type="metadata/cas_metadata">
+		<glob pattern="*.cas"/>
+		<glob pattern="*.met"/>
+	</mime-type>
+	
+	<mime-type type="product/iasi_xxx_1c">
+		<sub-class-of type="metop_a/noaa"/>
+		<_comment>ProductType=MOA_IASI_L1C</_comment>
+		<glob pattern="(?:L\d{1,}\.){0,1}IASI_xxx_1C_\w{3}_\w{15}_\w{15}_\w_\w_\w{15}__\w{14}" isregex="true"/>
+	</mime-type>
+	
+	<mime-type type="product/mhsx">
+		<sub-class-of type="metop_a/noaa"/>
+		<_comment>ProductType=MOA_MHS_L1B</_comment>
+		<glob pattern="(?:L\d{1,}\.){0,1}NSS\.MHSX\.\w{2}\.D\d{5}\.S\d{4}\.E\d{4}\.B\d{7}\.\w{2}" isregex="true"/>
+	</mime-type>
+	
+	<mime-type type="product/amsu_a">
+		<sub-class-of type="metop_a/noaa"/>
+		<_comment>ProductType=MOA_AMSUA_L1B</_comment>
+		<glob pattern="(?:L\d{1,}\.){0,1}NSS\.AMAX\.\w{2}\.D\d{5}\.S\d{4}\.E\d{4}\.B\d{7}\.\w{2}" isregex="true"/>
+	</mime-type>
+	
+	<mime-type type="product/rtg_sst">
+		<sub-class-of type="ncep/model"/>
+		<_comment><![CDATA[ProductType=RTG_SST && UniqueElement=RetrievedFromLoc]]></_comment>
+		<glob pattern="rtg_sst_grb_0\.5\.\d{8}" isregex="true"/>
+        <glob pattern="sst\.\d{8}_rtgssthr_grb_0\.5\.grib2" isregex="true"/>
+	</mime-type>
+	
+</mime-info>
+
diff --git a/0.8.1-rc1/pushpull/src/main/resources/push_pull_framework.properties b/0.8.1-rc1/pushpull/src/main/resources/push_pull_framework.properties
new file mode 100644
index 0000000..d1726ba
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/main/resources/push_pull_framework.properties
@@ -0,0 +1,106 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+# $Id: Configuration properties for the CAS Push-Pull-Framework$
+
+#---------------------------------------------------------------#
+#-------------------- Default Configurations -------------------#
+#---------------------------------------------------------------#
+
+#external configuration files
+org.apache.oodt.cas.pushpull.config.external.properties.files=[CAS_PP_HOME]/etc/default.properties
+
+
+#---------------------------------------------------------------#
+#-------------------- Default Ingester Properties --------------#
+#---------------------------------------------------------------#
+
+#ingester classpath
+org.apache.oodt.cas.filemgr.ingester=org.apache.oodt.cas.filemgr.ingest.StdIngester
+
+#ingester transferer
+org.apache.oodt.cas.filemgr.datatransfer.factory=org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory
+
+# ingester filemgr url
+org.apache.oodt.cas.filemgr.url=[FILEMGR_LOC]
+
+#---------------------------------------------------------------#
+#-------------------- Cached Ingester Properties  --------------#
+#---------------------------------------------------------------#
+org.apache.oodt.cas.filemgr.ingest.cache.factory=
+
+org.apache.oodt.cas.filemgr.ingest.cache.rangeQueryElementName=
+
+org.apache.oodt.cas.filemgr.ingest.cache.range.start=
+
+org.apache.oodt.cas.filemgr.ingest.cache.range.end=
+
+org.apache.oodt.cas.filemgr.ingest.cache.uniqueElementName=
+
+org.apache.oodt.cas.filemgr.ingest.cache.productType=
+
+
+#-------------------------------------------------------------#
+#---------------- Protocol Configurations --------------------#
+#-------------------------------------------------------------#
+
+#set the paging size (use -1 to turn paging off)
+org.apache.oodt.cas.pushpull.protocol.page_size=8
+
+#protocolfactory specification for protocol types
+org.apache.oodt.cas.pushpull.config.protocolfactory.info.files=[CAS_PP_HOME]/policy/ProtocolFactoryInfo.xml
+
+
+#-------------------------------------------------------------#
+#------------ FileRetrievalSystem Configurations -------------#
+#-------------------------------------------------------------#
+
+#parser to retrievalmethod map
+org.apache.oodt.cas.pushpull.config.parser.info.files=[CAS_PP_HOME]/policy/ParserToRetrievalMethodMap.xml
+
+#unique metadata element info
+org.apache.oodt.cas.pushpull.config.type.detection.file=[CAS_PP_HOME]/policy/mimetypes.xml
+
+#directory below which all data file will be downloaded to
+org.apache.oodt.cas.pushpull.data.files.base.staging.area=[CAS_PP_STAGING_AREA]
+
+#list of metadata values to print to metadata file
+org.apache.oodt.cas.pushpull.metadata.list.to.print=ProductName,RetrievedFromLoc,DataProvider,FileSize,RenamingString,ProductType,DownloadToDir,DeleteAfterDownload,SuperType
+
+#extension for temporary metadata file
+org.apache.oodt.cas.pushpull.write.met.file=true
+org.apache.oodt.cas.pushpull.met.file.extension=info.tmp
+
+#tracker varries the number of threads used to download files to find the optimized
+# number of threads in order to get the best download time
+org.apache.oodt.cas.pushpull.crawler.use.tracker=false
+
+#the recommended number of threads (will be the static number of 
+# threads used if the tracker is turned off)
+org.apache.oodt.cas.pushpull.file.retrieval.system.recommended.thread.count=30
+
+#the FileRetrievalSystem will stop accepting files for download once this number
+# of failed downloads is reached
+org.apache.oodt.cas.pushpull.file.retrieval.system.max.number.allowed.failed.downloads=10
+
+#if true, any file not defined in the file type detection file will not be downloaded
+org.apache.oodt.cas.pushpull.allow.only.defined.types=true
+
+org.apache.oodt.cas.pushpull.filerestrictions.parsers.class.noaa.email.parser.contains.exprs=CLASS\ has\ processed,anonymous
+
+org.apache.oodt.cas.pushpull.generic.email.parser.file.pattern=Wav File: ([^\\s]+)
+org.apache.oodt.cas.pushpull.generic.email.parser.check.for.pattern=Pattern to valid email has expected text
+org.apache.oodt.cas.pushpull.generic.email.parser.path.to.root=/some/root/path
+org.apache.oodt.cas.pushpull.generic.email.parser.metadata.keys=MasterInContactId
+org.apache.oodt.cas.pushpull.generic.email.parser.metadata.MasterInContactId=Master ContactID (\d+?)\n
diff --git a/0.8.1-rc1/pushpull/src/site/resources/images/cas-pushpull.jpg b/0.8.1-rc1/pushpull/src/site/resources/images/cas-pushpull.jpg
new file mode 100644
index 0000000..26e4345
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/site/resources/images/cas-pushpull.jpg
Binary files differ
diff --git a/0.8.1-rc1/pushpull/src/site/resources/images/cas-pushpull.psd b/0.8.1-rc1/pushpull/src/site/resources/images/cas-pushpull.psd
new file mode 100644
index 0000000..8aedbb3
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/site/resources/images/cas-pushpull.psd
Binary files differ
diff --git a/0.8.1-rc1/pushpull/src/site/resources/images/pp_extension_points.png b/0.8.1-rc1/pushpull/src/site/resources/images/pp_extension_points.png
new file mode 100644
index 0000000..b956b84
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/site/resources/images/pp_extension_points.png
Binary files differ
diff --git a/0.8.1-rc1/pushpull/src/site/resources/images/pp_object_model.png b/0.8.1-rc1/pushpull/src/site/resources/images/pp_object_model.png
new file mode 100644
index 0000000..fd25cd0
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/site/resources/images/pp_object_model.png
Binary files differ
diff --git a/0.8.1-rc1/pushpull/src/site/site.xml b/0.8.1-rc1/pushpull/src/site/site.xml
new file mode 100644
index 0000000..4e5af1f
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/site/site.xml
@@ -0,0 +1,32 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<project name="cas-pushpull">
+
+  <body>
+    <links>
+      <item name="OODT" href="../oodt-site/"/>
+    </links>
+
+    <menu ref="reports" inherit="bottom"/>
+    <menu name="Software Documentation">
+      <item name="Developer Guide" href="development/developer.html"/>
+      <item name="Basic User Guide" href="user/basic.html"/>
+      <item name="Advanced User Guide" href="user/advanced.html"/>
+    </menu>
+  </body>
+</project>
diff --git a/0.8.1-rc1/pushpull/src/site/xdoc/development/developer.xml b/0.8.1-rc1/pushpull/src/site/xdoc/development/developer.xml
new file mode 100644
index 0000000..49f522e
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/site/xdoc/development/developer.xml
@@ -0,0 +1,286 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS Push Pull Framework Developer Guide</title>
+      <author email="Brian.Foster@jpl.nasa.gov">Brian Foster</author>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+   </properties>
+
+   <body>
+   
+      <section name="Introduction">
+        <p>
+          This is the developer guide for the Apache OODT Catalog and Archive Service (CAS) 
+          Push Pull framework, or Push Pull for short. Primarily, this guide 
+          will explain the Push Pull architecture and interfaces, including its 
+          tailorable extension points. For information on installation, configuration,
+          and examples, please see our <a href="../user/basic.html">User Guides.</a>
+          
+          <p>The remainder of this guide is separated into the following sections:</p>
+      <ul>
+        <li><a href="#section1">Project Description</a></li>
+        <li><a href="#section2">Architecture</a></li>
+        <li><a href="#section3">Extension Points</a></li>
+        <li><a href="#section4">Current Extension Point Implementations</a></li>
+      </ul>
+          
+        </p>     
+      </section>
+      
+      <a name="section1"/>
+      <section name="Project Description">
+        <p>The Push Pull framework is responsible for downloading remote content (pull),
+        or accepting the delivery of remote content (push) to a local system staging area 
+        for use by the <a href="../../crawler">CAS Crawler Framework</a> to ingest into 
+        the <a href="../../filemgr">CAS File Manager</a>. The Push Pull framework is extensible 
+        and provides a fully tailorable Java-based API for the acquisition of remote content.</p> 
+      </section>
+      
+      <a name="section2"/>
+      <section name="Architecture">
+      
+        <p>In this section, we will describe the architecture of the Push Pull framework,
+        including its constituent components, object model, and key capabilities.</p>
+      
+        <subsection name="Components">
+        
+        <p>The major components of the Push Pull Framework are the Daemon Launcher, the Daemon, 
+        the Protocol Layer, and the File Retrieval System, to name a few.  The relationship between 
+        all of these components are shown in the diagram below:
+        </p>
+        
+        <p><img src="../images/pp_extension_points.png" alt="Push Pull Framework Architecture"/></p>
+        
+        <p>The Push Pull Framework provides a Daemon Launcher, responsible for creating new 
+        Daemon instances. Each Daemon has an associated Daemon Configuration, and has the 
+        ability to use a File Retrieval Setup extension point. This class is responsible for 
+        leveraging both a Protocol and a File Retrieval System to obtain ProtocolFiles, based on 
+        a File Restrictions Parser, that yields eventually a VirtualFileStructure (VFS) model. The 
+        VFS defines what files to accept and pull down from a remote site.
+        </p> 
+        
+        </subsection>
+        <subsection name="Object Model">
+        <p>The critical objects managed by the Push Pull Framework include:</p>
+        
+        <ul>
+          <li><strong>Protocol</strong> - A pluggable means of obtaining content over 
+          some file acquisition method, e.g., FTP, SCP, HTTP, etc.</li>
+          
+          <li><strong>Protocol File</strong> - Metadata information about a remote file, 
+          including its ProtocolPath.</li>
+          
+          <li><strong>Protocol Path</strong> - A pointer to a remote Product file's (or files') 
+          location, which can be used to derive metadata and determine where to place the file
+          in the local staging area built by the Push Pull Framework.</li>
+          
+          <li><strong>Remote Site</strong> - Descriptive information about a remote site, including 
+          the username/password combination, as well as a origin directory to start interrogating.</li>
+        </ul>
+
+        <p>Each Protocol delivers one or more Protocol Files. Each ProtocoFile is associated with a 
+        single RemoteSite, and each ProtocolFile is associated with a single ProtocolPath. These 
+        relationships are shown in the below figure.</p>
+        
+        <img src="../images/pp_object_model.png" alt="Push Pull Framework Object Model"/> 
+        </subsection> 
+      
+        <subsection name="Key Capabilities">
+        <p>The Push Pull Framework has been designed with a new of key capabilities in mind.
+        These capabilities include:</p>
+        
+        <p><strong>Flexibility</strong> - ability to plug in different Metadata Extractors, 
+        Data Protocols, Content Types, etc.</p>
+        
+        <p><strong>Support Push/Pull</strong> - Support of both &quot;Push&quot; and &quot;Pull&quot; 
+        style data transfers.</p>
+        
+        <p><strong>Extensibility</strong> - ability to add new, previously undiscovered Data Protocols, 
+        and &quot;plug&quot; them into the framework.</p>
+        
+        <p><strong>Java-based</strong> - Use of Java programming language and development kit for Multi-Platform 
+        deployment (using the Java Virtual Machine).</p>
+        
+        <p><strong>Fast Data-transfer</strong> - Support of Parallel File Transfers and Data Downloads.</p>
+        
+        <p><strong>Email-based Push</strong> - Support for Email-based Push Data Acceptance using IMAP, SMTP protocols.</p>
+        
+        <p><strong>Modeling of remote data sites</strong> - Ability to configure “Virtual” remote directories (based on Metadata 
+        such as Date/Time) to download files from.</p>
+        
+        <p><strong>Integration with other CAS components</strong> - Ability to &quot;plug-in&quot; to the CAS File Management 
+        and CAS Crawl Framework components for Data Ingestion.</p>         
+        </subsection>
+      </section>
+      
+      <a name="section3"/>
+      <section name="Extension Points">
+          <p>We have constructed the Push Pull Framework making use of the <i>factory 
+          method pattern</i> to provide multiple extension points for the Push Pull Framework. An 
+          extension point is an interface within the Push Pull Framework that can have many 
+          implementations. This is particularly useful when it comes to software 
+          component configuration because it allows different implementations of 
+          an existing interface to be selected at deployment time.</p> 
+          
+          <div class="info">The factory method pattern is a creational pattern common to
+          object oriented design. Each Push Pull Framework extension point involves the 
+          implementation of two interfaces: an <i>extension factory</i> and an 
+          <i>extension</i> implementation. At run-time, the Push Pull Framework loads a 
+          properties file specifies a factory class to use during extension point
+          instantiation. For example, the Push Pull Framework may communicate with a 
+          remote FTP site to obtain content, or it may use an IMAPS protocol plugin to 
+          accept email-push notifications of available files.
+          </div> 
+          
+          <p>Using extension points, it is fairly simple to support many different types 
+          of what are typically referred to as &quot;plug-in architectures&quot;. Each of the core 
+          extension points for the Push Pull Framework is described below:</p>
+          
+          <table>
+            <tr>
+              <td>Protocol</td>
+              <td>The Protocol extension point is the heart of the Push Pull framework, 
+              responsible for modeling remote sites, and for obtaining their content via 
+              different Retrieval Methods, using different File Restrictions Parsers.
+              </td>
+            </tr>
+            <tr>
+              <td>Retrieval Method</td>
+              <td>The Retrieval Method extension point is responsible for orchestrating 
+              download (pull) and acceptance (push) of remote content.
+              </td>
+            </tr>
+            <tr>
+              <td>File Restrictions Parser</td>
+              <td>The File Restrictions Parser extension point is responsible for defining 
+              how to accept or decline files encountered by a Retrieval Method, in essence 
+              modeling remote file and directory structures.
+              </td>
+            </tr>
+             <tr>
+              <td>System</td>
+              <td>The extension point that provides the external interface to the 
+              Push Pull Framework services. This includes the Daemon Launcher interface, 
+              as well as the associated Daemon interface, that 
+              is managed by with the Daemon Launcher.
+              </td>
+            </tr>          
+          
+          </table>
+       </section>
+       
+       <a name="section4"/>   
+       <section name="Current Extension Point Implementations">
+        
+         <p>There are at least two implementations of all of the aforementioned 
+         extension points for the Push Pull Framework. Each extension point implementation 
+         is detailed in this section.</p>
+
+         <subsection name="Protocol">
+            <ul>
+             <li><strong>Cog JGlobus FTP.</strong> An implementation of 
+             the Protocol extension point for FTP using 
+             <a href="http://dev.globus.org/wiki/CoG_jglobus">CoG jglobus</a>.
+             </li>
+             
+             <li><strong>Commons Net FTP.</strong> An implementation of the 
+             of the Protocol extension point for FTP using 
+             <a href="http://commons.apache.org/net/">Commons Net</a> FTP client.
+             </li>
+             
+             <li><strong>HTTP.</strong> An implementation of 
+             the Protocol extension point using Java's URL class, as well as 
+             <a href="http://tika.apche.org/">Apache Tika</a>'s HTMLParser.</li>
+             
+             <li><strong>IMAPS.</strong> An implementation of the 
+             Protocol extension point using IMAPS javax.mail classes from 
+             <a href="http://geronimo.apache.org">Apache Geronimo</a> and 
+             HTML parsing from <a href="http://tika.apache.org/">Apache Tika</a>.</li>
+
+             <li><strong>Local.</strong> An implementation of 
+             the Protocol extension point using Java NIO for local 
+             data acquisition.</li>
+             
+             <li><strong>SFTP.</strong> An implementation of the 
+             Protocol extension point using <a href="http://www.jcraft.org">JCraft</a>'s 
+             <a href="http://www.jcraft.org/jsch">JSch</a> library.</li>
+           </ul>
+         </subsection> 
+
+         <subsection name="Retrieval Method">
+            <ul>
+             <li><strong>Remote Crawler.</strong> An implementation of 
+             the Retrieval Method interface that uses an XML based set of 
+             policy files to determine which remote directories and files 
+             to crawl and obtain.</li>
+             
+             <li><strong>List Retriever.</strong> An implementation of the 
+             Retrieval Method interface that accepts a list of URLs that point 
+             to content to obtain.</li>
+           </ul>
+         </subsection> 
+
+         <subsection name="File Restrictions Parser">
+            <ul>
+             <li><strong>DirStructXml Parser.</strong> An implementation of 
+             the File Restrictions Parser interface that interprets an XML file 
+             specifying the remote directories and files to obtain.</li>
+             
+             <li><strong>FileList Parser.</strong> An implementation of the 
+             File Restrictions Parser interface that specifies an ASCII newline separated 
+             list of URLs pointing to remote directories and files to obtain.</li>
+
+             <li><strong>Class NOAA Email Parser.</strong> An implementation of the 
+             File Restrictions Parser interface that reads email files from NOAA's CLASS 
+             archive which specify lists of directory and file URLs to obtain.</li>
+           </ul>
+         </subsection>          
+         
+         
+         <subsection name="Daemon Launcher (Daemon client and Daemon server)">        
+             <ul>
+               <li><strong>Java RMI based server.</strong> An 
+               implementation of the external server interface for the Push Pull Framework that 
+               uses RMI as the transportation medium to launch Push Pull Daemons.</li>
+               
+               <li><strong>Push Pull Daemon.</strong> An 
+               implementation of the client interface for the Java RMI-based  
+               server that uses RMI as the transportation medium to manage and control the 
+               Push Pull services.</li>
+             </ul>
+         </subsection> 
+         
+      </section>
+      
+      <section name="Conclusion">
+      <p>The aim of this document is to provide information relevant to developers
+      about the CAS Push Pull Framework. Specifically, this document has described the 
+      Push Pull Framework's architecture, including its constituent components, object model and
+      key capabilities. Additionally, the this document provides an overview of the 
+      current implementations of the Push Pull Framework's extension points.</p> 
+      
+      <p>In the <a href="../user/basic.html">Basic User Guide</a> and 
+      <a href="../user/advanced.html">Advanced User Guide</a>, we will cover topics
+      like installation, configuration, and example uses as well as advanced topics
+      like scaling and other tips and tricks.</p> 
+      
+      </section>
+
+   </body>
+</document>
diff --git a/0.8.1-rc1/pushpull/src/site/xdoc/development/maven.xml b/0.8.1-rc1/pushpull/src/site/xdoc/development/maven.xml
new file mode 100755
index 0000000..d79f341
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/site/xdoc/development/maven.xml
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+  <properties>
+    <title>Using Maven</title>
+    <author email="woollard@jpl.nasa.gov">David Woollard</author>
+    <author email="sean.hardman@jpl.nasa.gov">Sean Hardman</author>
+  </properties>
+
+  <body>
+    <section name="Using Maven">
+      <p>OODT uses <a href="http://maven.apache.org/">Maven</a> for 
+      managing our build environment. Maven is an open source product from the 
+      <a href="http://www.apache.org/">Apache Software Foundation</a> that improves 
+      on <a href="http://ant.apache.org/">Ant</a> in the area of build management, 
+      which it turn was an improvement on Make. This document describes the use of 
+      Maven for Apache OODT build management.</p>
+    </section>
+    
+    <section name="Setup">
+      <p>Maven can be downloaded from the 
+      <a href="http://maven.apache.org/download.html">Maven Download</a> 
+      page. OODT is using version 2.0 and above. Maven was developed in Java so it 
+      will run on the popular platforms (e.g., Windows, Mac OSX, etc.). Beyond 
+      making sure the <i>mvn</i> executable is in your path, there is very little 
+      setup required.</p>
+
+      <p>Maven is based on the concept of a Project Object Model (POM) which is 
+      contained in the <i>pom.xml</i> file found at the root of each project. 
+      The POM allows Maven to manage a project's build, reporting and documentation. 
+      For OODT, much of the default information for managing the projects is 
+      contained in a parent POM, which is located in the <i>oodt-core</i> project. So, 
+      in order to build any of the other projects (e.g., cas-curator, cas-filemgr, 
+      etc.) the parent POM must be downloaded from the OODT Maven repository. The 
+      local <i>pom.xml</i> files for each of the projects have been configured to 
+      retrieve the parent POM automatically.</p>
+      
+      <p>Once Maven has been setup, the first step to building a project with Maven 
+      is to checkout a project's source code into the developer's work area. See the 
+      <a href="../development/subversion.html">Using Subversion</a> document for how to 
+      check out projects from the CM repository.</p>
+    </section>
+    
+    <section name="Project Structure">
+      <p>In order for default Maven functions to operate properly, there is a 
+      suggested project directory structure. The structure is as follows:</p>
+      
+      <source>
+/
+  src/             Source Code (everything)
+    main/            Program Source
+      assembly/        Package Descriptor
+      java/            Java Source
+      resources/       Scripts, Config File, etc.
+        ...
+    test/            Test Source
+      java/
+      resources/
+        ...
+    site/            Site Documentation
+      apt/             Docs in APT Format
+        index.apt
+        ...
+      xdoc/            Docs in XDOC Format
+        index.xml
+        ...
+      resources/
+        images/
+      site.xml         Menu Structure
+
+  target/          Build Results (binaries, docs and packages)
+    ...
+
+  LICENSE.txt
+  README.txt
+  pom.xml          Project Object Model (POM)
+      </source>
+    </section>
+    
+    <section name="Standard Commands">
+    <p>There are few standard commands that developers will use on a daily basis 
+    and they are related to building and cleaning a project.</p>
+    <subsection name="Build a Project">
+      <p>Build the project's libraries and executables with the following 
+      command:</p>
+      <source>
+mvn compile
+      </source>
+      <p>The above command will generate the artifacts in the <i>target/</i> 
+      directory.</p>      
+    </subsection>
+    <subsection name="Install a Project">
+      <p>Install the project's artifacts locally with the following command:</p>
+      <source>
+mvn install
+      </source>
+      <p>Prior to installation, the above command will compile the source code, 
+      if necessary, and execute the unit tests. The result of the above command 
+      is to install the generated artifacts (e.g. pom, jar, etc.) in the user's 
+      local Maven repository ($HOME/.m2/repository/). This is useful when the 
+      artifact is a dependency for another project but has yet to be deployed 
+      to the Maven repository.</p>
+    </subsection>
+    <subsection name="Package a Project">
+      <p>Create the project's distribution package with the following command:</p>
+      <source>
+mvn package
+      </source>
+      <p>Prior to package creation, the above command will compile the source 
+      code, if necessary, and execute the unit tests. The above command will 
+      create the package(s) in the target/ directory.</p>
+    </subsection>
+    <subsection name="Build a Project's Web Site">
+      <p>Build the project's web site with the following command:</p>
+      <source>
+mvn site
+      </source>
+      <p>The above command will generate the web site in the <i>target/site/</i>
+      directory. View the site by pointing your web browser at the 
+      <i>index.html</i> file within that directory.</p>
+    </subsection> 
+    <subsection name="Clean a Project">
+      <p>Clean out the project directory of generated artifacts with the 
+      following command:</p>
+      <source>
+mvn clean
+      </source>
+      <p>The above command will remove the <i>target/</i> directory and its 
+      contents.</p>
+    </subsection>
+    <subsection name="Useful Command Arguments">
+      <p>There a couple of useful arguments which can be appended to the 
+      commands above to limit the scope of the command.</p>
+      <p>In order to skip unit test execution, add the following argument:</p>
+      <source>
+mvn [command] -Dmaven.test.skip=true
+      </source>
+      <p>The above command is most useful with the <i>install</i>, 
+      <i>package</i> and <i>site</i> commands.</p>
+      <p>When a project has modules defined in the POM, the command can be 
+      performed against the top level of the project instead of the modules by 
+      adding the following argument:</p>
+      <source>
+mvn [command] --non-recursive
+      </source>
+    </subsection>
+    </section>
+    <section name="Acknowledgments">
+      <p>Much of the material in this Maven guide was originally authored 
+      by Sean Hardman under the sponsorship of NASA Jet Propulsion 
+      Laboratory's Planetary Data System. </p>
+    </section>
+    <section name="References">
+      <p>Here is a list of Maven resources:</p>
+      <ul>
+        <li><a href="http://maven.apache.org/guides/index.html">Online 
+        Documentation Index</a></li>
+      </ul>
+    </section>
+  </body>
+</document>
diff --git a/0.8.1-rc1/pushpull/src/site/xdoc/user/advanced.xml b/0.8.1-rc1/pushpull/src/site/xdoc/user/advanced.xml
new file mode 100644
index 0000000..ecd3ad4
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/site/xdoc/user/advanced.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS Push Pull User Guide</title>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+      <author email="woollard@jpl.nasa.gov">Dave Woollard</author>
+   </properties>
+
+   <body>
+      <div class="warning">This document is in the process of being reorganized as
+      part of our ongoing documentation effort. Please check back for updates.</div>  
+   
+      <section name="Introduction">
+      
+      <p>In the CAS Push Pull Framework Advanced User Guide, we will cover a number of 
+      advanced topics related to using the system, including situations
+      that have arisen in the authors' experiences. Basic
+      concepts, such as installation and configuration, can be found in the 
+      <a href="../user/basic.html">Basic User Guide</a>.</p>
+      
+      <p>The remainder of this guide is separated into the following sections:</p>
+      <ul>
+        <li><a href="#section1">TBD</a></li>
+      </ul>
+      
+      </section>
+      
+      <a name="section1"/>
+      <section name="TBD">
+      <p>Coming Soon...</p>
+      </section>
+      
+   </body>
+</document> 
diff --git a/0.8.1-rc1/pushpull/src/site/xdoc/user/basic.xml b/0.8.1-rc1/pushpull/src/site/xdoc/user/basic.xml
new file mode 100644
index 0000000..2aee3e5
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/site/xdoc/user/basic.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS Push Pull User Guide</title>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+      <author email="woollard@jpl.nasa.gov">Dave Woollard</author>
+   </properties>
+
+   <body>
+      <div class="warning">This document is in the process of being reorganized as
+      part of our ongoing documentation effort. Please check back for updates.</div>
+      
+      <section name="Introduction">
+      
+      <p>This document serves as a basic user's guide for the CAS Push Pull Framework
+      project. The goal of the document is to allow users to check out, build, and 
+      install a base version of the CAS Push Pull Framework as well as perform basic 
+      configuration tasks. For advanced topics, please see our 
+      <a href="../user/advanced.html">Advanced Guide.</a></p>
+      
+      <p>The remainder of this guide is separated into the following sections:</p>
+      <ul>
+        <li><a href="#section1">TBD</a></li>
+      </ul>
+      
+      </section>
+      
+      <a name="section1"/>
+      <section name="TBD">
+      <p>Coming Soon...</p>
+      </section>
+      
+   </body>
+</document> 
diff --git a/0.8.1-rc1/pushpull/src/site/xdoc/user/index.xml b/0.8.1-rc1/pushpull/src/site/xdoc/user/index.xml
new file mode 100644
index 0000000..6b3c916
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/site/xdoc/user/index.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS Push Pull Framework User Guide</title>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+      <author email="woollard@jpl.nasa.gov">Dave Woollard</author>
+   </properties>
+
+   <body>
+  
+      <div class="warning">This document is in the process of being reorganized as
+      part of our ongoing documentation effort. Please follow the links below to find
+      information that has previously been hosted on this page.</div>
+ 
+
+      <p>We are in the process of upgrading OODT documentation. In the near
+      future, we hope to provide information for developers regarding each 
+      component, including its purpose, structure, interfaces, and 
+      configuration points in a <a href="../development/developer.html">Developer
+      Guide.</a></p>
+      
+      <p>Information for users, including installation and basic configuration,
+      as well as example usage are provided in a 
+      <a href="../user/basic.html">Basic User Guide.</a> Advanced topics, like
+      look and feel, lessons-learned, and best practices are provided in an
+      <a href="../user/advanced.html">Advanced User Guide.</a></p>
+      
+      <p>Finally, we are planning to provide a number of case studies in the 
+      future, in which multi-component deployments are configured to handle
+      common data and computation management scenarios.</p> 
+
+   </body>
+</document> 
diff --git a/0.8.1-rc1/pushpull/src/test/org/apache/oodt/cas/pushpull/filerestrictions/parsers/GenericEmailParserTest.java b/0.8.1-rc1/pushpull/src/test/org/apache/oodt/cas/pushpull/filerestrictions/parsers/GenericEmailParserTest.java
new file mode 100644
index 0000000..e098c87
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/test/org/apache/oodt/cas/pushpull/filerestrictions/parsers/GenericEmailParserTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.pushpull.filerestrictions.parsers;
+
+// JUnit static imports
+import static org.junit.Assert.assertThat;
+
+
+// JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
+import java.util.List;
+
+
+import org.apache.oodt.cas.metadata.Metadata;
+// OODT imports
+import org.apache.oodt.cas.pushpull.exceptions.ParserException;
+import org.apache.oodt.cas.pushpull.filerestrictions.FileRestrictions;
+import org.apache.oodt.cas.pushpull.filerestrictions.VirtualFileStructure;
+
+// JUnit imports
+import org.hamcrest.Matchers;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Test class for {@link GenericEmailParser}.
+ *
+ * @author bfoster@apache.org (Brian Foster)
+ */
+@RunWith(JUnit4.class)
+public class GenericEmailParserTest {
+
+  private File emailFile;
+
+  @Before
+  public void setUp() throws URISyntaxException {
+    emailFile = new File(ClassLoader.getSystemResource("TestEmail.txt").toURI());
+  }
+
+  @Test
+  public void testGenericEmailParser() throws ParserException, FileNotFoundException {
+    GenericEmailParser parser = new GenericEmailParser(
+        "Wav File: ([^\\s]+)", "Dear Lousy Customer,", null);
+    VirtualFileStructure vfs = parser.parse(new FileInputStream(emailFile), new Metadata());
+    List<String> filePaths = FileRestrictions.toStringList(vfs.getRootVirtualFile());
+    assertThat(filePaths.size(), Matchers.is(1));
+    assertThat(filePaths.get(0), Matchers.is("/some/path/to/a/wav/file.wav"));
+  }
+
+  @Test (expected = ParserException.class)
+  public void testFailedValidEmailCheck() throws ParserException, FileNotFoundException {
+    GenericEmailParser parser = new GenericEmailParser(
+        "Wav File: ([^\\s]+)", "Phrase Not Found", null);
+    parser.parse(new FileInputStream(emailFile), new Metadata());
+  }
+}
diff --git a/0.8.1-rc1/pushpull/src/test/resources/TestEmail.txt b/0.8.1-rc1/pushpull/src/test/resources/TestEmail.txt
new file mode 100644
index 0000000..fd5a7fa
--- /dev/null
+++ b/0.8.1-rc1/pushpull/src/test/resources/TestEmail.txt
@@ -0,0 +1,16 @@
+
+Dear Lousy Customer,
+
+Your file is ready to download.
+
+File size: 12345
+
+Wav File: /some/path/to/a/wav/file.wav
+
+MDB Hash File: /some/path/to/a/md5/file.md5
+
+Thanks!
+Files-R-Us
+
+PS
+You only get this notification once so download now!!!!!
diff --git a/0.8.1-rc1/resource/pom.xml b/0.8.1-rc1/resource/pom.xml
new file mode 100644
index 0000000..c0c8159
--- /dev/null
+++ b/0.8.1-rc1/resource/pom.xml
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>cas-resource</artifactId>
+  <name>Catalog and Archive Resource Management Component</name>
+  <description>The resource management component of a Catalog and Archive Service. This component
+     provides job management, and management of the underlying software system hardware
+     and resources, such as disk space, computational resources, and shared identity.</description>
+  <scm>
+   	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/resource</connection>
+   	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/resource</developerConnection>
+   	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/resource</url>
+  </scm>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>2.4</version>
+        <configuration>
+          <forkMode>pertest</forkMode>
+          <useSystemClassLoader>false</useSystemClassLoader>
+          <systemProperties>
+             <property>
+               <name>java.util.logging.config.file</name>
+               <value>${basedir}/src/test/resources/test.logging.properties</value>
+              </property>
+           </systemProperties>
+           <forkedProcessTimeoutInSeconds>0</forkedProcessTimeoutInSeconds>
+           <redirectTestOutputToFile>true</redirectTestOutputToFile>
+            <includes>
+              <include>**/*Test*.java</include>
+            </includes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-2</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/assembly/assembly.xml</descriptor>
+          </descriptors>
+          <archive>
+            <manifest>
+              <mainClass>org.apache.oodt.cas.resource.system.XmlRpcResourceManagerClient</mainClass>
+            </manifest>
+          </archive>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.scala-lang</groupId>
+      <artifactId>scala-library</artifactId>
+      <version>2.10.3</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-core_2.10</artifactId>
+      <version>1.1.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-streaming_2.10</artifactId>
+      <version>1.1.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-client</artifactId>
+      <version>2.4.0</version>
+      <exclusions>
+        <exclusion>
+          <groupId>com.sun.jersey</groupId>
+          <artifactId>jersey-client</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.sun.jersey</groupId>
+          <artifactId>jersey-core</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.sun.jersey</groupId>
+          <artifactId>jersey-server</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.sun.jersey</groupId>
+          <artifactId>jersey-json</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.sun.jersey.contribs</groupId>
+          <artifactId>jersey-guice</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>com.sun.jersey</groupId>
+      <artifactId>jersey-client</artifactId>
+      <version>1.14</version>
+    </dependency>
+    <dependency>
+      <groupId>com.sun.jersey</groupId>
+      <artifactId>jersey-core</artifactId>
+      <version>1.14</version>
+    </dependency>
+    <dependency>
+      <groupId>com.sun.jersey</groupId>
+      <artifactId>jersey-server</artifactId>
+      <version>1.14</version>
+    </dependency>
+    <dependency>
+      <groupId>com.sun.jersey</groupId>
+      <artifactId>jersey-json</artifactId>
+      <version>1.14</version>
+    </dependency>
+    <dependency>
+      <groupId>com.sun.jersey.contribs</groupId>
+      <artifactId>jersey-guice</artifactId>
+      <version>1.14</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-metadata</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-cli</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.0.3</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+      <version>3.0</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <version>1.3</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-dbcp</groupId>
+      <artifactId>commons-dbcp</artifactId>
+      <version>1.2.1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+      <version>3.2.1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-pool</groupId>
+      <artifactId>commons-pool</artifactId>
+      <version>1.2</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+      <version>4.2.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.lucene</groupId>
+      <artifactId>lucene-core</artifactId>
+      <version>2.0.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.safehaus.jug</groupId>
+      <artifactId>jug</artifactId>
+      <version>2.0.0</version>
+      <classifier>asl</classifier>
+    </dependency>
+    <dependency>
+      <groupId>xmlrpc</groupId>
+      <artifactId>xmlrpc</artifactId>
+      <version>2.0.1</version>
+    </dependency>
+    <dependency>
+      <groupId>com.thoughtworks.xstream</groupId>
+      <artifactId>xstream</artifactId>
+      <version>1.3.1</version>
+      <exclusions>
+        <exclusion>
+          <!-- xom is an optional dependency of xstream. Its also an Apache incompatible license -->
+          <groupId>xom</groupId>
+          <artifactId>xom</artifactId>
+        </exclusion> 
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.mesos</groupId>
+      <artifactId>mesos</artifactId>
+      <version>0.21.0</version>
+      <classifier>shaded-protobuf</classifier>
+   </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/resource/src/main/assembly/assembly.xml b/0.8.1-rc1/resource/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..c753724
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/assembly/assembly.xml
@@ -0,0 +1,86 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<assembly>
+  <id>dist</id>
+  <formats>
+    <format>tar.gz</format>
+    <format>zip</format>
+  </formats>
+  <includeBaseDirectory>true</includeBaseDirectory>
+  <baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/bin</directory>
+      <outputDirectory>bin</outputDirectory>
+      <includes/>
+      <fileMode>755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>logs</outputDirectory>
+      <includes>
+        <include>REMOVE.log</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>etc</outputDirectory>
+      <includes>
+        <include>resource.properties</include>
+        <include>logging.properties</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>policy</outputDirectory>
+      <includes>
+        <include>cmd-line-actions.xml</include>
+        <include>cmd-line-options.xml</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/examples</directory>
+      <outputDirectory>policy</outputDirectory>
+      <excludes/>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>lib</outputDirectory>
+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>
+      <unpackOptions/>
+    </dependencySet>
+  </dependencySets>
+</assembly>
diff --git a/0.8.1-rc1/resource/src/main/bin/batch_stub b/0.8.1-rc1/resource/src/main/bin/batch_stub
new file mode 100644
index 0000000..aad77f2
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/bin/batch_stub
@@ -0,0 +1,33 @@
+#!/bin/tcsh
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+# $Id$ 
+#
+
+set DIR = `dirname $0`
+cd $DIR
+set DIR_PATH = `pwd`
+
+if ( $#argv != 1 ) then
+        echo "Usage: $0 <port>"
+        exit 1
+else
+        java -Djava.ext.dirs=../lib \
+        -Dorg.apache.oodt.cas.pge.task.metkeys.legacyMode="true" \
+	-Dorg.apache.oodt.cas.pge.task.status.legacyMode="true" \
+        org.apache.oodt.cas.resource.system.extern.XmlRpcBatchStub \
+        --portNum $1&
+endif
diff --git a/0.8.1-rc1/resource/src/main/bin/remote b/0.8.1-rc1/resource/src/main/bin/remote
new file mode 100644
index 0000000..d946357
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/bin/remote
@@ -0,0 +1,37 @@
+#!/bin/bash
+#
+# Script to run a command on all nodes specified in a nodes.xml config file
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+# $Id$
+
+E_NO_ARGS=65
+
+if [ $# -eq 0 ]
+then
+  echo "Usage: remote /path/to/nodes.xml command..."
+  exit $E_NO_ARGS
+fi 
+
+NODES=$(awk '/<node/ {print substr($3, 12,length($3)-12)}' $1)
+shift 
+for NODE in $NODES
+do
+  ssh $NODE $"${@// /\\ }" 2>&1 | sed "s/^/$NODE: /" &
+done
+
+exit 0 
diff --git a/0.8.1-rc1/resource/src/main/bin/resmgr b/0.8.1-rc1/resource/src/main/bin/resmgr
new file mode 100644
index 0000000..e122613
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/bin/resmgr
@@ -0,0 +1,73 @@
+#!/bin/sh
+#
+# init script for XmlRpcResourceManager
+#
+# chkconfig: 345 88 22
+# description: CAS Resource Manager
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+# $Id$
+
+[ -f /etc/sysconfig/java ] && . /etc/sysconfig/java
+#[ -f /etc/sysconfig/cas-filemgr] && . /etc/sysconfig/cas-filemgr
+
+SERVER_PORT=9002
+export SERVER_PORT
+if [ -z $JAVA_HOME ] ; then
+	JAVA_HOME=/path/to/java/home
+else
+	JAVA_HOME=${JAVA_HOME}
+fi
+
+export JAVA_HOME
+CAS_RESMGR_HOME=..
+export CAS_RESMGR_HOME
+RUN_HOME=${CAS_RESMGR_HOME}/../run
+export RUN_HOME
+CAS_RESMGR_PROPS=../etc/resource.properties
+export CAS_RESMGR_PROPS
+
+PATH=${JAVA_HOME}/bin:${CAS_RESMGR_HOME}/bin:/usr/bin:/bin:/usr/sbin:/sbin
+export PATH
+
+# See how we were called.
+case "$1" in
+  start)
+        echo -n "Starting cas resource manager: "
+        $JAVA_HOME/bin/java -Djava.ext.dirs=${CAS_RESMGR_HOME}/lib \
+        -Djava.util.logging.config.file=${CAS_RESMGR_HOME}/etc/logging.properties \
+        -Dorg.apache.oodt.cas.resource.properties=${CAS_RESMGR_PROPS} \
+        org.apache.oodt.cas.resource.system.XmlRpcResourceManager --portNum $SERVER_PORT &       
+        echo $! >${RUN_HOME}/cas.resmgr.pid 
+        echo "OK"
+        sleep 5
+        ;;
+  stop)
+        echo -n "Shutting down cas resource manager: "
+        kill `cat ${RUN_HOME}/cas.resmgr.pid`
+        echo "OK"
+        ;;
+  restart)
+        $0 stop
+        $0 start
+        ;;
+  *)
+        echo "Usage: $0 {start|stop|restart}"
+        exit 1
+esac
+
+exit 0
diff --git a/0.8.1-rc1/resource/src/main/bin/resmgr-client b/0.8.1-rc1/resource/src/main/bin/resmgr-client
new file mode 100644
index 0000000..e7dbd3d
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/bin/resmgr-client
@@ -0,0 +1,34 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+# $Id$
+
+
+if [ -z $JAVA_HOME ] ; then
+	JAVA_HOME=/path/to/java/home
+else
+	JAVA_HOME=${JAVA_HOME}
+fi
+
+export JAVA_HOME
+
+$JAVA_HOME/bin/java \
+        -Djava.ext.dirs=../lib \
+        -Dorg.apache.oodt.cas.resource.properties=../etc/resource.properties \
+        -Djava.util.logging.config.file=../etc/logging.properties \
+        -Dorg.apache.oodt.cas.cli.action.spring.config=../policy/cmd-line-actions.xml \
+        -Dorg.apache.oodt.cas.cli.option.spring.config=../policy/cmd-line-options.xml \
+        org.apache.oodt.cas.resource.system.XmlRpcResourceManagerClient $*
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/Batchmgr.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/Batchmgr.java
new file mode 100644
index 0000000..1232470
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/Batchmgr.java
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.batchmgr;
+
+//OODT imports
+import org.apache.oodt.cas.resource.jobrepo.JobRepository;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+
+//java imports
+import java.net.URL;
+
+/**
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * A batchmgr interface.
+ * </p>
+ * 
+ */
+public interface Batchmgr {
+
+    /**
+     * Executes a job remotely on the specified <code>remoteHost</code>.
+     * 
+     * @param job
+     *            The {@link JobSpec} to execute.
+     * @param remoteHost
+     *            A {@link URL} pointer to the remote host to execute the job
+     *            on.
+     * @return true if the job execution was successful, false otherwise.
+     * @throws JobExecutionException
+     *             If there is an exception executing the job on the remote
+     *             host.
+     */
+    public boolean executeRemotely(JobSpec job, ResourceNode resNode)
+            throws JobExecutionException;
+
+    /**
+     * Sets the {@link Monitor} to be used by this Batchmgr.
+     * 
+     * @param monitor
+     *            The {@link Monitor} to be used.
+     */
+    public void setMonitor(Monitor monitor);
+
+    /**
+     * Sets the {@link JobRepository} that this Batchmgr will use to persist
+     * {@link Job} information while {@link Job}s are executing.
+     * 
+     * @param repository
+     */
+    public void setJobRepository(JobRepository repository);
+    
+    
+    /**
+     * 
+     * @param jobId
+     * @param node
+     * @return
+     */
+    public boolean killJob(String jobId, ResourceNode node);
+    
+    
+    /**
+     * 
+     * @param jobId
+     * @return
+     */
+    public String getExecutionNode(String jobId);
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/BatchmgrFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/BatchmgrFactory.java
new file mode 100644
index 0000000..0f5a1f2
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/BatchmgrFactory.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.batchmgr;
+
+/**
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory class for creating implementations of the SimpleBatchmgr.
+ * </p>
+ * 
+ */
+public interface BatchmgrFactory {
+
+	/**
+	 * @return A new implementation of the {@link Batchmgr} interface.
+	 */
+	public Batchmgr createBatchmgr();
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/MesosBatchManager.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/MesosBatchManager.java
new file mode 100644
index 0000000..0f67f36
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/MesosBatchManager.java
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.batchmgr;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.mesos.Protos.Status;
+import org.apache.mesos.Protos.TaskID;
+import org.apache.mesos.SchedulerDriver;
+import org.apache.oodt.cas.resource.jobrepo.JobRepository;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+import org.apache.oodt.cas.resource.structs.exceptions.MesosFrameworkException;
+
+/**
+ * @author starchmd
+ * @version $Revision$
+ *
+ * A batch-manager used to execute and control jobs in a mesos-cluster.
+ */
+public class MesosBatchManager implements Batchmgr {
+
+    Map<String,TaskID> map = new HashMap<String,TaskID>();
+    SchedulerDriver driver;
+    JobRepository repo;
+    Monitor mon;
+
+    public MesosBatchManager() {
+    }
+    /**
+     * Required to set the driver used to run the job, so "kill"
+     * requests are mapped properly.
+     * @param driver
+     */
+    public void setDriver(SchedulerDriver driver)
+    {
+        this.driver = driver;
+    }
+    /**
+     * Register a new job with a batch manager.
+     * @param jobId - jobId in "resource" manager.
+     * @param task - mesos task.
+     */
+    public void registerExecutedJob(String jobId,TaskID task) {
+        map.put(jobId, task);
+    };
+
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#executeRemotely(org.apache.oodt.cas.resource.structs.JobSpec, org.apache.oodt.cas.resource.structs.ResourceNode)
+     */
+    @Override
+    public boolean executeRemotely(JobSpec job, ResourceNode resNode)
+            throws JobExecutionException {
+        throw new NotImplementedException("Execute remotely is not called when using mesos.");
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#setMonitor(org.apache.oodt.cas.resource.monitor.Monitor)
+     */
+    @Override
+    public void setMonitor(Monitor monitor) {
+        this.mon = monitor;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#setJobRepository(org.apache.oodt.cas.resource.jobrepo.JobRepository)
+     */
+    @Override
+    public void setJobRepository(JobRepository repository) {
+        this.repo = repository;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#killJob(java.lang.String, org.apache.oodt.cas.resource.structs.ResourceNode)
+     */
+    @Override
+    public boolean killJob(String jobId, ResourceNode node) {
+        TaskID id = (TaskID)map.get(jobId);
+        driver.killTask(id);
+        Status status = driver.killTask(id);
+        if (status != Status.DRIVER_RUNNING)
+            throw new MesosFrameworkException("Mesos Schedule Driver is dead: "+status.toString());
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#getExecutionNode(java.lang.String)
+     */
+    @Override
+    public String getExecutionNode(String jobId) {
+        // TODO Make this more meaningful.
+        return "All Your Jobs are belong to Mesos";
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/MesosBatchManagerFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/MesosBatchManagerFactory.java
new file mode 100644
index 0000000..e35b225
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/MesosBatchManagerFactory.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.batchmgr;
+
+
+
+/**
+ * @author starchmd
+ * @version $Revision$
+ *
+ * <p>
+ * A batchmgr factory.
+ * </p>
+ *
+ */
+
+public class MesosBatchManagerFactory implements BatchmgrFactory {
+
+    public MesosBatchManagerFactory(){
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.oodt.cas.resource.batchmgr.BatchmgrFactory#createBatchmgr()
+     */
+    public Batchmgr createBatchmgr() {
+        return new MesosBatchManager();
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/ResourceExecutor.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/ResourceExecutor.java
new file mode 100644
index 0000000..84e9fd6
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/ResourceExecutor.java
@@ -0,0 +1,175 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.batchmgr;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+import org.apache.mesos.Executor;
+import org.apache.mesos.ExecutorDriver;
+import org.apache.mesos.MesosExecutorDriver;
+import org.apache.mesos.Protos.ExecutorInfo;
+import org.apache.mesos.Protos.FrameworkInfo;
+import org.apache.mesos.Protos.SlaveInfo;
+import org.apache.mesos.Protos.Status;
+import org.apache.mesos.Protos.TaskID;
+import org.apache.mesos.Protos.TaskInfo;
+import org.apache.mesos.Protos.TaskState;
+import org.apache.mesos.Protos.TaskStatus;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.JobInstance;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.exceptions.JobInputException;
+import org.apache.oodt.cas.resource.util.GenericResourceManagerObjectFactory;
+import org.apache.oodt.cas.resource.util.MesosUtilities;
+
+/**
+ * @author starchmd
+ *
+ * This "Executor" is run by mesos to actually run the job.
+ */
+public class ResourceExecutor implements Executor {
+
+    PrintStream str = null;
+    String id = new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime())+" ";
+    public ResourceExecutor() {
+        try {
+            File tmp = new File("./executor-log.notalog");
+            //tmp.delete(); //With NIO then something must be caught
+            str = new PrintStream(new FileOutputStream(tmp));
+            str.println(id+"Starting up new<<<<<");
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Executor#disconnected(org.apache.mesos.ExecutorDriver)
+     */
+    @Override
+    public void disconnected(ExecutorDriver driver) {
+        str.println(id+"Disconnected!");
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Executor#error(org.apache.mesos.ExecutorDriver, java.lang.String)
+     */
+    @Override
+    public void error(ExecutorDriver driver, String error) {
+        str.println(id+"Error: "+error);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Executor#frameworkMessage(org.apache.mesos.ExecutorDriver, byte[])
+     */
+    @Override
+    public void frameworkMessage(ExecutorDriver arg0, byte[] arg1) {
+        str.println(id+"Message: "+new String(arg1));
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Executor#killTask(org.apache.mesos.ExecutorDriver, org.apache.mesos.Protos.TaskID)
+     */
+    @Override
+    public void killTask(ExecutorDriver arg0, TaskID arg1) {
+        str.println(id+"Kill");
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Executor#launchTask(org.apache.mesos.ExecutorDriver, org.apache.mesos.Protos.TaskInfo)
+     */
+    @Override
+    public void launchTask(final ExecutorDriver driver, final TaskInfo info) {
+        str.println(id+"Launch task!");
+        try {
+            JobSpec spec = MesosUtilities.byteStringToJobSpec(info.getData());
+            final JobInstance exec = GenericResourceManagerObjectFactory
+                    .getJobInstanceFromClassName(spec.getJob().getJobInstanceClassName());
+            final JobInput in = spec.getIn();
+            Thread tmp = new Thread(new Runnable(){
+                    public void run() {
+                        TaskStatus status = null;
+                        try {
+                            exec.execute(in);
+                            status = TaskStatus.newBuilder().setTaskId(info.getTaskId())
+                                    .setState(TaskState.TASK_FINISHED).build();
+                        } catch (JobInputException e) {
+                            e.printStackTrace();
+                            status = TaskStatus.newBuilder().setTaskId(info.getTaskId())
+                                    .setState(TaskState.TASK_FAILED).build();
+                        }
+                        driver.sendStatusUpdate(status);
+                    }
+            });
+            driver.sendStatusUpdate(TaskStatus.newBuilder().setTaskId(info.getTaskId())
+                  .setState(TaskState.TASK_STARTING).build());
+            tmp.start();
+        } catch (ClassNotFoundException e1) {
+            System.out.println("BAD DATA: ");
+            e1.printStackTrace();
+            driver.sendStatusUpdate(TaskStatus.newBuilder().setTaskId(info.getTaskId())
+                    .setState(TaskState.TASK_FAILED).build());
+        } catch (InstantiationException e2) {
+            System.out.println("BAD DATA: ");
+            e2.printStackTrace();
+            driver.sendStatusUpdate(TaskStatus.newBuilder().setTaskId(info.getTaskId())
+                    .setState(TaskState.TASK_FAILED).build());
+        } catch (IllegalAccessException e3) {
+            System.out.println("BAD DATA: ");
+            e3.printStackTrace();
+            driver.sendStatusUpdate(TaskStatus.newBuilder().setTaskId(info.getTaskId())
+                    .setState(TaskState.TASK_FAILED).build());
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Executor#registered(org.apache.mesos.ExecutorDriver, org.apache.mesos.Protos.ExecutorInfo, org.apache.mesos.Protos.FrameworkInfo, org.apache.mesos.Protos.SlaveInfo)
+     */
+    @Override
+    public void registered(ExecutorDriver arg0, ExecutorInfo arg1,
+            FrameworkInfo arg2, SlaveInfo arg3) {
+        System.out.println("Do-Wah-Do-Wah");
+        str.println(id+"Registered, Huzzah!");
+
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Executor#reregistered(org.apache.mesos.ExecutorDriver, org.apache.mesos.Protos.SlaveInfo)
+     */
+    @Override
+    public void reregistered(ExecutorDriver arg0, SlaveInfo arg1) {
+        System.out.println("Do-Wah-Do-Wah GO GO GO!!!!");
+        str.println(id+"Re-regged");
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Executor#shutdown(org.apache.mesos.ExecutorDriver)
+     */
+    @Override
+    public void shutdown(ExecutorDriver arg0) {
+        System.out.println("Down down down.");
+        str.println(id+"Shutdown");
+    }
+
+    public static void main(String[] args) throws Exception {
+        MesosExecutorDriver driver = new MesosExecutorDriver(new ResourceExecutor());
+        System.exit(driver.run() == Status.DRIVER_STOPPED ? 0 : 1);
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/XmlRpcBatchMgr.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/XmlRpcBatchMgr.java
new file mode 100644
index 0000000..75cbbe3
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/XmlRpcBatchMgr.java
@@ -0,0 +1,217 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.batchmgr;
+
+//OODT imports
+import org.apache.oodt.cas.resource.jobrepo.JobRepository;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.JobStatus;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+import org.apache.oodt.cas.resource.structs.exceptions.JobRepositoryException;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+
+//JDK imports
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * 
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * An XML-RPC interface to the batch manager.
+ * </p>
+ */
+public class XmlRpcBatchMgr implements Batchmgr {
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(XmlRpcBatchMgr.class
+            .getName());
+
+    private Monitor mon;
+
+    private JobRepository repo;
+
+    private Map nodeToJobMap;
+
+    private Map specToProxyMap;
+
+    public XmlRpcBatchMgr() {
+        nodeToJobMap = new HashMap();
+        specToProxyMap = new HashMap();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#executeRemotely(org.apache.oodt.cas.resource.structs.JobSpec,
+     *      java.net.URL)
+     */
+    public boolean executeRemotely(JobSpec jobSpec, ResourceNode resNode)
+            throws JobExecutionException {
+
+        XmlRpcBatchMgrProxy proxy = new XmlRpcBatchMgrProxy(jobSpec, resNode,
+                this);
+        if (!proxy.nodeAlive()) {
+            throw new JobExecutionException("Node: [" + resNode.getNodeId()
+                    + "] is down: Unable to execute job!");
+        }
+
+        synchronized (this.specToProxyMap) {
+            specToProxyMap.put(jobSpec.getJob().getId(), proxy);
+        }
+
+        synchronized (this.nodeToJobMap) {
+            this.nodeToJobMap
+                    .put(jobSpec.getJob().getId(), resNode.getNodeId());
+        }
+
+        proxy.start();
+
+        return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#setMonitor(org.apache.oodt.cas.resource.monitor.Monitor)
+     */
+    public void setMonitor(Monitor monitor) {
+        this.mon = monitor;
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#setJobRepository(org.apache.oodt.cas.resource.jobrepo.JobRepository)
+     */
+    public void setJobRepository(JobRepository repository) {
+        this.repo = repository;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#getExecutionNode(java.lang.String)
+     */
+    public String getExecutionNode(String jobId) {
+        return (String) nodeToJobMap.get(jobId);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#killJob(java.lang.String,
+     *      org.apache.oodt.cas.resource.structs.ResourceNode)
+     */
+    public boolean killJob(String jobId, ResourceNode node) {
+        JobSpec spec = null;
+        try {
+            spec = repo.getJobById(jobId);
+        } catch (Exception e) {
+            LOG.log(Level.WARNING, "Unable to get job by id: [" + jobId
+                    + "] to kill it: Message: " + e.getMessage());
+            return false;
+        }
+
+        XmlRpcBatchMgrProxy proxy = new XmlRpcBatchMgrProxy(spec, node, this);
+        return proxy.killJob();
+    }
+
+    protected void notifyMonitor(ResourceNode node, JobSpec jobSpec) {
+        Job job = jobSpec.getJob();
+        int reducedLoad = job.getLoadValue().intValue();
+        try {
+            mon.reduceLoad(node, reducedLoad);
+        } catch (MonitorException e) {
+        }
+    }
+
+    protected void jobSuccess(JobSpec spec) {
+        spec.getJob().setStatus(JobStatus.SUCCESS);
+        synchronized (this.nodeToJobMap) {
+            this.nodeToJobMap.remove(spec.getJob().getId());
+        }
+        synchronized (this.specToProxyMap) {
+            XmlRpcBatchMgrProxy proxy = (XmlRpcBatchMgrProxy) this.specToProxyMap
+                    .remove(spec.getJob().getId());
+            if (proxy != null) {
+                proxy = null;
+            }
+        }
+
+        try {
+            repo.updateJob(spec);
+        } catch (JobRepositoryException e) {
+            LOG.log(Level.WARNING, "Error set job completion status for job: ["
+                    + spec.getJob().getId() + "]: Message: " + e.getMessage());
+        }
+    }
+    
+    protected void jobFailure(JobSpec spec) {
+        spec.getJob().setStatus(JobStatus.FAILURE);
+        synchronized (this.nodeToJobMap) {
+            this.nodeToJobMap.remove(spec.getJob().getId());
+        }
+        synchronized (this.specToProxyMap) {
+            XmlRpcBatchMgrProxy proxy = (XmlRpcBatchMgrProxy) this.specToProxyMap
+                    .remove(spec.getJob().getId());
+            if (proxy != null) {
+                proxy = null;
+            }
+        }
+
+        try {
+            repo.updateJob(spec);
+        } catch (JobRepositoryException e) {
+            LOG.log(Level.WARNING, "Error set job completion status for job: ["
+                    + spec.getJob().getId() + "]: Message: " + e.getMessage());
+        }
+    }
+
+    protected void jobKilled(JobSpec spec) {
+        spec.getJob().setStatus(JobStatus.KILLED);
+        nodeToJobMap.remove(spec.getJob().getId());
+        try {
+            repo.updateJob(spec);
+        } catch (JobRepositoryException e) {
+            LOG.log(Level.WARNING, "Error setting job killed status for job: ["
+                    + spec.getJob().getId() + "]: Message: " + e.getMessage());
+        }
+    }
+
+    protected void jobExecuting(JobSpec spec) {
+        spec.getJob().setStatus(JobStatus.EXECUTED);
+        try {
+            repo.updateJob(spec);
+        } catch (JobRepositoryException e) {
+            LOG.log(Level.WARNING,
+                    "Error setting job execution status for job: ["
+                            + spec.getJob().getId() + "]: Message: "
+                            + e.getMessage());
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/XmlRpcBatchMgrFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/XmlRpcBatchMgrFactory.java
new file mode 100644
index 0000000..3a344ed
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/XmlRpcBatchMgrFactory.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.batchmgr;
+
+import org.apache.oodt.cas.resource.util.GenericResourceManagerObjectFactory;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+
+/**
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * A batchmgr factory.
+ * </p>
+ * 
+ */
+
+public class XmlRpcBatchMgrFactory implements BatchmgrFactory {
+
+	private Monitor mon = null;
+	
+	public XmlRpcBatchMgrFactory(){
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.apache.oodt.cas.resource.batchmgr.BatchmgrFactory#createBatchmgr()
+	 */
+	public Batchmgr createBatchmgr() {
+		return new XmlRpcBatchMgr();
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/XmlRpcBatchMgrProxy.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/XmlRpcBatchMgrProxy.java
new file mode 100644
index 0000000..4a4f2b2
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/batchmgr/XmlRpcBatchMgrProxy.java
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.batchmgr;
+
+//JDK imports
+import java.io.IOException;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.util.XmlRpcStructFactory;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+
+//APACHE imports
+import org.apache.xmlrpc.XmlRpcClient;
+import org.apache.xmlrpc.XmlRpcException;
+
+/**
+ * 
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * A {@link Runnable} proxy to an XmlRpcBatchStub that allows the call to the
+ * XmlRpcBatchStub to be asynchronous rather than synchronous. This allows a
+ * {@link Scheduler} that calls the {@link XmlRpcBatchMgr} to not be stuck
+ * waiting for each job to complete before scheduling the next {@link Job}
+ * </p>.
+ */
+public class XmlRpcBatchMgrProxy extends Thread implements Runnable {
+
+	private static final Logger LOG = Logger.getLogger(XmlRpcBatchMgrProxy.class.getName());
+	
+    private JobSpec jobSpec;
+
+    private ResourceNode remoteHost;
+
+    private XmlRpcClient client;
+
+    private XmlRpcBatchMgr parent;
+
+    public XmlRpcBatchMgrProxy(JobSpec jobSpec, ResourceNode remoteHost,
+            XmlRpcBatchMgr par) {
+        this.jobSpec = jobSpec;
+        this.remoteHost = remoteHost;
+        this.parent = par;
+    }
+
+    public boolean nodeAlive() {
+        client = new XmlRpcClient(remoteHost.getIpAddr());
+        Vector argList = new Vector();
+
+        boolean alive = false;
+
+        try {
+            alive = ((Boolean) client.execute("batchstub.isAlive", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            alive = false;
+        } catch (IOException e) {
+            alive = false;
+        }
+
+        return alive;
+
+    }
+
+    public boolean killJob() {
+        client = new XmlRpcClient(remoteHost.getIpAddr());
+        Vector argList = new Vector();
+        argList.add(XmlRpcStructFactory.getXmlRpcJob(jobSpec.getJob()));
+
+        boolean result = false;
+        try {
+            result = ((Boolean) client.execute("batchstub.killJob", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            result = false;
+        } catch (IOException e) {
+            e.printStackTrace();
+            result = false;
+        }
+
+        if (result) {
+            parent.jobKilled(jobSpec);
+        }
+
+        return result;
+    }
+
+    public void run() {
+        client = new XmlRpcClient(remoteHost.getIpAddr());
+        Vector argList = new Vector();
+        argList.add(XmlRpcStructFactory.getXmlRpcJob(jobSpec.getJob()));
+        argList.add(jobSpec.getIn().write());
+
+        boolean result = false;
+        try {
+            parent.jobExecuting(jobSpec);
+            result = ((Boolean) client
+                    .execute("batchstub.executeJob", argList)).booleanValue();
+            if (result)
+            	parent.jobSuccess(jobSpec);
+            else
+            	throw new Exception("batchstub.executeJob returned false");
+        } catch (Exception e) {
+        	LOG.log(Level.SEVERE, "Job execution failed for jobId '" + jobSpec.getJob().getId() + "' : " + e.getMessage(), e);
+            parent.jobFailure(jobSpec);
+        }finally {
+            parent.notifyMonitor(remoteHost, jobSpec);
+        }
+
+   }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/AddNodeCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/AddNodeCliAction.java
new file mode 100644
index 0000000..06f3c3e
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/AddNodeCliAction.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//JDK imports
+import java.net.URL;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+
+/**
+ * A {@link CmdLineAction} which adds a ResourceNode.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class AddNodeCliAction extends ResourceCliAction {
+
+   private String nodeId;
+   private URL nodeUrl;
+   private int capacity;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(nodeId, "Must specify nodeId");
+         Validate.notNull(nodeUrl, "Must specify nodeUrl");
+         Validate.notNull(capacity, "Must specify capacity");
+
+         getClient().addNode(new ResourceNode(nodeId, nodeUrl, capacity));
+         printer.println("Successfully added node!");
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to add node with nodeId '"
+               + nodeId + "', nodeUrl '" + nodeUrl + "', and capacity '"
+               + capacity + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setNodeId(String nodeId) {
+      this.nodeId = nodeId;
+   }
+
+   public void setNodeUrl(URL nodeUrl) {
+      this.nodeUrl = nodeUrl;
+   }
+
+   public void setCapacity(int capacity) {
+      this.capacity = capacity;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/AddNodeToQueueCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/AddNodeToQueueCliAction.java
new file mode 100644
index 0000000..ab61dda
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/AddNodeToQueueCliAction.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAcion} which adds a Node to a Queue.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class AddNodeToQueueCliAction extends ResourceCliAction {
+
+   private String queueName;
+   private String nodeId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(queueName, "Must specify queueName");
+         Validate.notNull(nodeId, "Must specify nodeId");
+
+         getClient().addNodeToQueue(nodeId, queueName);
+         printer.println("Successfully added node to queue!");
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get add node '" + nodeId
+               + "' to queue '" + queueName + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setQueueName(String queueName) {
+      this.queueName = queueName;
+   }
+
+   public void setNodeId(String nodeId) {
+      this.nodeId = nodeId;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/AddQueueCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/AddQueueCliAction.java
new file mode 100644
index 0000000..d15d825
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/AddQueueCliAction.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which adds a queue.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class AddQueueCliAction extends ResourceCliAction {
+
+   private String queueName;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(queueName, "Must specify queueName");
+
+         getClient().addQueue(queueName);
+         printer.println("Successfully added queue!");
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to add queue with name '"
+               + queueName + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setQueueName(String queueName) {
+      this.queueName = queueName;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetExecNodeCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetExecNodeCliAction.java
new file mode 100644
index 0000000..64dbfe2
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetExecNodeCliAction.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which get execution node for a job.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetExecNodeCliAction extends ResourceCliAction {
+
+   private String jobId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(jobId, "Must specify jobId");
+
+         String execNode = getClient().getExecutionNode(jobId);
+         printer.println("Executing node: " + execNode);
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get execution node for"
+               + " job '" + jobId + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setJobId(String jobId) {
+      this.jobId = jobId;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetJobInfoCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetJobInfoCliAction.java
new file mode 100644
index 0000000..a5cb480
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetJobInfoCliAction.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.JobStatus;
+
+/**
+ * A {@link CmdLineAction} which gets job info.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetJobInfoCliAction extends ResourceCliAction {
+
+   private String jobId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(jobId, "Must specify jobId");
+
+         Job jobInfo = getClient().getJobInfo(jobId);
+
+         printer.println("Job: [id=" + jobId + ", status="
+               + getReadableJobStatus(jobInfo.getStatus()) + ",name="
+               + jobInfo.getName() + ",queue=" + jobInfo.getQueueName()
+               + ",load=" + jobInfo.getLoadValue() + ",inputClass="
+               + jobInfo.getJobInputClassName() + ",instClass="
+               + jobInfo.getJobInstanceClassName() + "]");
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get job info for job '"
+               + jobId + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setJobId(String jobId) {
+      this.jobId = jobId;
+   }
+
+   private static String getReadableJobStatus(String status) {
+      if (status.equals(JobStatus.SUCCESS)) {
+         return "SUCCESS";
+      } else if (status.equals(JobStatus.FAILURE)) {
+         return "FAILURE";
+      } else if (status.equals(JobStatus.EXECUTED)) {
+         return "EXECUTED";
+      } else if (status.equals(JobStatus.QUEUED)) {
+         return "QUEUED";
+      } else if (status.equals(JobStatus.SCHEDULED)) {
+         return "SCHEDULED";
+      } else if (status.equals(JobStatus.KILLED)) {
+         return "KILLED";
+      } else
+         return null;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetNodeByIdCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetNodeByIdCliAction.java
new file mode 100644
index 0000000..1fae3a3
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetNodeByIdCliAction.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+
+/**
+ * A {@link CmdLineAction} which gets a ResourceNode by ID.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetNodeByIdCliAction extends ResourceCliAction {
+
+   private String nodeId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(nodeId, "Must specify nodeId");
+
+         ResourceNode node = getClient().getNodeById(nodeId);
+
+         if (node == null) {
+            throw new Exception("ResourceManager returned null ResourceNode"
+                  + " for nodeId '" + nodeId + "'");
+         }
+         printer.println("node: [id=" + node.getNodeId() + ",capacity="
+               + node.getCapacity() + ",url=" + node.getIpAddr() + "]");
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get node by id '" + nodeId
+               + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setNodeId(String nodeId) {
+      this.nodeId = nodeId;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetNodeLoadCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetNodeLoadCliAction.java
new file mode 100644
index 0000000..f0df4ce
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetNodeLoadCliAction.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which get load of given node.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetNodeLoadCliAction extends ResourceCliAction {
+
+   private String nodeId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(nodeId, "Must specify nodeId");
+
+         String result = getClient().getNodeLoad(nodeId);
+         printer.println("Load for node '" + nodeId + "': " + result);
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get node load for node '"
+               + nodeId + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setNodeId(String nodeId) {
+      this.nodeId = nodeId;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetNodesCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetNodesCliAction.java
new file mode 100644
index 0000000..122e09e
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetNodesCliAction.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+
+/**
+ * A {@link CmdLineAction} which get list of ResourceNodes.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetNodesCliAction extends ResourceCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         @SuppressWarnings("unchecked")
+         List<ResourceNode> nodes = getClient().getNodes();
+
+         if (nodes == null) {
+            throw new Exception("ResourceManager returned null nodes");
+         }
+         for (ResourceNode node : nodes) {
+            printer.println("node: [id=" + node.getNodeId() + ",capacity="
+                  + node.getCapacity() + ",url=" + node.getIpAddr() + "]");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get nodes : "
+               + e.getMessage(), e);
+      }
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetNodesInQueueCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetNodesInQueueCliAction.java
new file mode 100644
index 0000000..b42a0a4
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetNodesInQueueCliAction.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which gets the nodes in a queue.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetNodesInQueueCliAction extends ResourceCliAction {
+
+   private String queueName;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(queueName, "Must specify queueName");
+
+         List<String> nodeIds = getClient().getNodesInQueue(queueName);
+         printer.println("Nodes in Queue '" + queueName + "':");
+         for (String nodeId : nodeIds)
+            printer.println(" - " + nodeId);
+         printer.println();
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get nodes in queue '"
+               + queueName + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setQueueName(String queueName) {
+      this.queueName = queueName;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetQueuesCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetQueuesCliAction.java
new file mode 100644
index 0000000..f97b2be
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetQueuesCliAction.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which gets list of Node queues.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetQueuesCliAction extends ResourceCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         List<String> queueNames = getClient().getQueues();
+         printer.println("Queues:");
+         for (String queueName : queueNames)
+            printer.println(" - " + queueName);
+         printer.println();
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get queues : "
+               + e.getMessage(), e);
+      }
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetQueuesWithNodeCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetQueuesWithNodeCliAction.java
new file mode 100644
index 0000000..11b59a5
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/GetQueuesWithNodeCliAction.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which gets queues with given node id.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetQueuesWithNodeCliAction extends ResourceCliAction {
+
+   private String nodeId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(nodeId, "Must specify nodeId");
+
+         List<String> queueNames = getClient().getQueuesWithNode(nodeId);
+         printer.println("Queues with node '" + nodeId + "':");
+         for (String queueName : queueNames)
+            printer.println(" - " + queueName);
+         printer.println();
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get queues with node '"
+               + nodeId + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setNodeId(String nodeId) {
+      this.nodeId = nodeId;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/KillCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/KillCliAction.java
new file mode 100644
index 0000000..e4ce94c
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/KillCliAction.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which kills a job.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class KillCliAction extends ResourceCliAction {
+
+   private String jobId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(jobId, "Must specify jobId");
+
+         if (getClient().killJob(jobId)) {
+            printer.println("Job: [" + jobId + "] successfully killed.");
+         } else {
+            throw new Exception("Kill job returned false");
+         }
+
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to kill job '" + jobId
+               + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setJobId(String jobId) {
+      this.jobId = jobId;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/RemoveNodeCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/RemoveNodeCliAction.java
new file mode 100644
index 0000000..fb06eee
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/RemoveNodeCliAction.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which removes a node by id.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class RemoveNodeCliAction extends ResourceCliAction {
+
+   private String nodeId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(nodeId, "Must specify nodeId");
+
+         getClient().removeNode(nodeId);
+         printer.println("Successfully removed node!");
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to remove node with id '"
+               + nodeId + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setNodeId(String nodeId) {
+      this.nodeId = nodeId;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/RemoveNodeFromQueueCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/RemoveNodeFromQueueCliAction.java
new file mode 100644
index 0000000..b3d55e8
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/RemoveNodeFromQueueCliAction.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which removes a node from a queue.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class RemoveNodeFromQueueCliAction extends ResourceCliAction {
+
+   private String nodeId;
+   private String queueName;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(nodeId, "Must specify nodeId");
+         Validate.notNull(queueName, "Must specify queueName");
+
+         getClient().removeNodeFromQueue(nodeId, queueName);
+         printer.println("Successfully removed node from queue!");
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to remove node '"
+               + nodeId + "' from queue '" + queueName + "' : "
+               + e.getMessage(), e);
+      }
+   }
+
+   public void setNodeId(String nodeId) {
+      this.nodeId = nodeId;
+   }
+
+   public void setQueueName(String queueName) {
+      this.queueName = queueName;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/RemoveQueueCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/RemoveQueueCliAction.java
new file mode 100644
index 0000000..7ec63f8
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/RemoveQueueCliAction.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which removes a queue.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class RemoveQueueCliAction extends ResourceCliAction {
+
+   private String queueName;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull("Must specify queueName");
+
+         getClient().removeQueue(queueName);
+         printer.println("Successfully removed queue!");
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to remove queue with name '"
+               + queueName + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setQueueName(String queueName) {
+      this.queueName = queueName;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/ResourceCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/ResourceCliAction.java
new file mode 100644
index 0000000..5cbb360
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/ResourceCliAction.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.resource.system.XmlRpcResourceManagerClient;
+
+/**
+ * Base {@link CmdLineAction} for Workflow Manager.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public abstract class ResourceCliAction extends CmdLineAction {
+
+   private XmlRpcResourceManagerClient client;
+
+   public String getUrl() {
+      return System.getProperty("org.apache.oodt.cas.resource.url");
+   }
+
+   protected XmlRpcResourceManagerClient getClient()
+         throws MalformedURLException {
+      Validate.notNull(getUrl());
+
+      if (client != null) {
+         return client;
+      } else {
+         return new XmlRpcResourceManagerClient(new URL(getUrl()));
+      }
+   }
+
+   public void setClient(XmlRpcResourceManagerClient client) {
+      this.client = client;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/SetNodeCapacityCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/SetNodeCapacityCliAction.java
new file mode 100644
index 0000000..078c7c3
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/SetNodeCapacityCliAction.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which changes a node's capacity.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class SetNodeCapacityCliAction extends ResourceCliAction {
+
+   private String nodeId;
+   private int capacity;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(nodeId, "Must specify nodeId");
+         Validate.notNull(capacity, "Must specify capacity");
+
+         getClient().setNodeCapacity(nodeId, capacity);
+         printer.println("Successfully set node capacity!");
+      } catch (Exception e) {
+         throw new CmdLineActionException("", e);
+      }
+   }
+
+   public void setNodeId(String nodeId) {
+      this.nodeId = nodeId;
+   }
+
+   public void setCapacity(int capacity) {
+      this.capacity = capacity;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/SubmitJobCliAction.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/SubmitJobCliAction.java
new file mode 100644
index 0000000..8dae2d8
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/cli/action/SubmitJobCliAction.java
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli.action;
+
+//JDK imports
+import java.net.URL;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.util.JobBuilder;
+
+/**
+ * A {@link CmdLineAction} which submits a job.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class SubmitJobCliAction extends ResourceCliAction {
+
+   public String jobDefinitionFile;
+   public URL url;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Validate.notNull(jobDefinitionFile, "Must specify jobDefinitionFile");
+
+         JobSpec spec = JobBuilder.buildJobSpec(jobDefinitionFile);
+         if (url == null) {
+            printer.println("Successful submit job with jobId '"
+                  + getClient().submitJob(spec.getJob(), spec.getIn()) + "'");
+         } else {
+            if (getClient().submitJob(spec.getJob(), spec.getIn(), url)) {
+               printer.println("Successfully submitted job to url '"
+                     + url + "'");
+            } else {
+               throw new Exception("Job submit returned false");
+            }
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to submit job for job"
+               + " definition file '" + jobDefinitionFile + "' : "
+               + e.getMessage(), e);
+      }
+   }
+
+   public void setJobDefinitionFile(String jobDefinitionFile) {
+      this.jobDefinitionFile = jobDefinitionFile;
+   }
+
+   public void setUrl(URL url) {
+      this.url = url;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/HelloWorldJob.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/HelloWorldJob.java
new file mode 100644
index 0000000..b7b2317
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/HelloWorldJob.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.examples;
+
+//OODT imports
+import org.apache.oodt.cas.resource.metadata.JobMetadata;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.JobInstance;
+import org.apache.oodt.cas.resource.structs.NameValueJobInput;
+import org.apache.oodt.cas.resource.structs.exceptions.JobInputException;
+
+/**
+ * 
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * The classic programming example: the hello world job.
+ * </p>
+ */
+public class HelloWorldJob implements JobInstance, JobMetadata {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.structs.JobInstance#execute(org.apache.oodt.cas.resource.structs.JobInput)
+   */
+  public boolean execute(JobInput in) throws JobInputException {
+    if (!(in instanceof NameValueJobInput)) {
+      throw new JobInputException(
+          "Only know how to handle NameValueInput: unknown input type: ["
+              + in.getClass().getName() + "]");
+    }
+
+    NameValueJobInput input = (NameValueJobInput) in;
+
+    System.out.println("Hello world! How are you "
+        + input.getValue("user.name") + "!");
+    return true;
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/LongJob.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/LongJob.java
new file mode 100644
index 0000000..83bc6e0
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/LongJob.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.examples;
+
+//OODT imports
+import org.apache.oodt.cas.resource.metadata.JobMetadata;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.JobInstance;
+import org.apache.oodt.cas.resource.structs.NameValueJobInput;
+import org.apache.oodt.cas.resource.structs.exceptions.JobInputException;
+
+/**
+ * 
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * A Job that will take a variable amount of time to finish.
+ * </p>
+ */
+public class LongJob implements JobInstance, JobMetadata {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.resource.structs.JobInstance#execute(org.apache.oodt.cas.resource.structs.JobInput)
+     */
+    public boolean execute(JobInput in) throws JobInputException {
+        if (!(in instanceof NameValueJobInput)) {
+            throw new JobInputException(
+                    "Only know how to handle NameValueInput: unknown input type: ["
+                            + in.getClass().getName() + "]");
+        }
+
+        NameValueJobInput input = (NameValueJobInput) in;
+
+        int waitTime = 0;
+        waitTime = new Integer(input.getValue("wait")).intValue();
+
+        System.out.println("LongJob running for " + waitTime + " sec");
+
+        try {
+            Thread.sleep(waitTime * 1000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        System.out.println("LongJob finished.");
+
+        return true;
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/NoSparkFilePalindromeExample.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/NoSparkFilePalindromeExample.java
new file mode 100644
index 0000000..bf510fd
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/NoSparkFilePalindromeExample.java
@@ -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.
+ */
+
+
+package org.apache.oodt.cas.resource.examples;
+
+//JDK imports
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+//OODT imports
+import org.apache.oodt.cas.resource.metadata.JobMetadata;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.JobInstance;
+import org.apache.oodt.cas.resource.structs.NameValueJobInput;
+
+/**
+ *
+ * @author starchmd
+ * @version $Revision$
+ *
+ * <p>
+ * A job that searches the supplied file for palindromes.  Outputs timing information
+ * to another file for benchmarking purposes. References standard palindrom calculation.
+ *
+ * Uses non-spark processing for the computations.
+ * </p>
+ */
+public class NoSparkFilePalindromeExample implements JobInstance, JobMetadata {
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.oodt.cas.resource.structs.JobInstance#execute(org.apache.oodt.cas.resource.structs.JobInput)
+     */
+    public boolean execute(JobInput in) {
+        NameValueJobInput input = (NameValueJobInput) in;
+        PrintStream output = null;
+        BufferedReader br = null;
+        try {
+            //Setup output and timing
+            output = PalindromeUtils.getPrintStream(input.getValue("output"));
+            long count = 0;
+            final long start = System.currentTimeMillis();
+            //Read file and process
+            String file = input.getValue("file");
+            br = new BufferedReader(new FileReader(file));
+            String line;
+            while ((line = br.readLine()) != null) {
+                if (PalindromeUtils.isPalindrome(line))
+                    count++;
+            }
+            //Output timing and results
+            final long end = System.currentTimeMillis();
+            double timing = ((double)(end - start))/1000.0;
+            output.println("Found "+ count+" palindromes in "+timing+" seconds.");
+            br.close();
+        } catch (FileNotFoundException e) {
+            return false;
+        } catch (IOException e) {
+            return false;
+        } finally {
+            try {
+                br.close();
+                output.close();
+            } catch (Exception e) {}
+
+        }
+        return true;
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/PalindromeUtils.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/PalindromeUtils.java
new file mode 100644
index 0000000..127cf95
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/PalindromeUtils.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.examples;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+
+import org.apache.spark.api.java.function.Function;
+
+/**
+ * @author starchmd
+ *
+ * Tests if a line is a palindrome.
+ *
+ */
+public class PalindromeUtils {
+    /**
+     * Super simple palindrome test.
+     * @param line - line to test
+     * @return true if it is a palindrome, false otherwise.
+     */
+    public static boolean isPalindrome(String line) {
+        line = line.replaceAll("\\s","").toLowerCase();
+        return line.equals(new StringBuilder(line).reverse().toString());
+    }
+    /**
+     * Get a PrintStream for printing to give file
+     * @param file - file to open as PrintStream
+     * @return stream for file to print to.
+     * @throws FileNotFoundException
+     */
+    public static PrintStream getPrintStream(String file) throws FileNotFoundException {
+        return new PrintStream(new File(file));
+    }
+    /**
+     * Functor class for spark.  Really should do this in Scala....
+     * Note: serial id is disabled because this class has no instance variables.
+     * @author starchmd
+     */
+    @SuppressWarnings("serial")
+    static class FilterPalindrome implements Function<String, Boolean> {
+        public Boolean call(String s) { return isPalindrome(s); }
+      }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/SparkFilePalindromeExample.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/SparkFilePalindromeExample.java
new file mode 100644
index 0000000..79bdcb6
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/SparkFilePalindromeExample.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.examples;
+
+//JDK imports
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+//OODT imports
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.NameValueJobInput;
+import org.apache.oodt.cas.resource.structs.SparkInstance;
+import org.apache.oodt.cas.resource.structs.exceptions.JobInputException;
+import org.apache.spark.SparkContext;
+import org.apache.spark.api.java.JavaRDD;
+import org.apache.spark.api.java.JavaSparkContext;
+
+/**
+ *
+ * @author starchmd
+ * @version $Revision$
+ *
+ * <p>
+ * A job that searches the supplied file for palindromes.  Outputs timing information
+ * to another file for benchmarking purposes. References standard palindrom calculation.
+ *
+ * Uses spark processing for the computations.
+ * </p>
+ */
+public class SparkFilePalindromeExample implements SparkInstance {
+
+    JavaSparkContext sc;
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.oodt.cas.resource.structs.JobInstance#execute(org.apache.oodt.cas.resource.structs.JobInput)
+     */
+    public boolean execute(JobInput in) throws JobInputException {
+        NameValueJobInput input = (NameValueJobInput) in;
+        PrintStream output = null;
+        try {
+            //Setup output and timing
+            output = PalindromeUtils.getPrintStream(input.getValue("output"));
+            final long start = System.currentTimeMillis();
+            //Read file and process
+            JavaRDD<String> rdd = sc.textFile( input.getValue("file"));
+            JavaRDD<String> filtered = rdd.filter(new PalindromeUtils.FilterPalindrome());
+            long count = filtered.count();
+            //Output timing and results
+            final long end = System.currentTimeMillis();
+            double timing = ((double)(end - start))/1000.0;
+            output.println("Found "+ count+" palindromes in "+timing+" seconds.");
+        } catch (FileNotFoundException e) {
+            return false;
+        } finally {
+            try {
+                output.close();
+            } catch (Exception e) {}
+
+        }
+        return true;
+    }
+
+    @Override
+    public void setSparkContext(SparkContext context) {
+        this.sc = new JavaSparkContext(context);
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/StreamingPalindromeExample.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/StreamingPalindromeExample.java
new file mode 100644
index 0000000..a309697
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/StreamingPalindromeExample.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.examples;
+
+//JDK imports
+
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+//OODT imports
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.NameValueJobInput;
+import org.apache.oodt.cas.resource.structs.StreamingInstance;
+import org.apache.oodt.cas.resource.structs.exceptions.JobInputException;
+import org.apache.spark.SparkContext;
+import org.apache.spark.api.java.JavaRDD;
+import org.apache.spark.api.java.JavaSparkContext;
+import org.apache.spark.api.java.function.Function;
+import org.apache.spark.streaming.StreamingContext;
+import org.apache.spark.streaming.api.java.JavaDStream;
+import org.apache.spark.streaming.api.java.JavaReceiverInputDStream;
+import org.apache.spark.streaming.api.java.JavaStreamingContext;
+
+/**
+ *
+ * @author starchmd
+ * @version $Revision$
+ *
+ * <p>
+ * A job that searches the supplied file for palindromes.  Outputs timing information
+ * to another file for benchmarking purposes. References standard palindrom calculation.
+ *
+ * Uses spark processing for the computations.
+ * </p>
+ */
+public class StreamingPalindromeExample implements StreamingInstance {
+
+    JavaSparkContext sc;
+    JavaStreamingContext ssc;
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.oodt.cas.resource.structs.JobInstance#execute(org.apache.oodt.cas.resource.structs.JobInput)
+     */
+    //Will not serialize a class that has no members
+    @SuppressWarnings("serial")
+    public boolean execute(JobInput in) throws JobInputException {
+        NameValueJobInput input = (NameValueJobInput) in;
+        //Get time for watchdog
+        final int time = Integer.parseInt(input.getValue("time"));
+        try {
+            //Output to put data into
+            final PrintStream output = PalindromeUtils.getPrintStream(input.getValue("output"));
+            //Filter stream and count
+            JavaReceiverInputDStream<String> stream = ssc.socketTextStream(input.getValue("host"),Integer.parseInt(input.getValue("port")));
+            JavaDStream<String> filtered = stream.filter(new PalindromeUtils.FilterPalindrome());
+            final JavaDStream<Long> count = filtered.count();
+            //For each packet-ized count: output
+            count.foreachRDD(new Function<JavaRDD<Long>,Void>(){
+                @Override
+                public Void call(JavaRDD<Long> jrdd) throws Exception {
+                    synchronized(output)
+                    {
+                        Long[] collected = (Long[])jrdd.rdd().collect();
+                        for (Long item : collected)
+                        output.println("Found "+item.longValue()+ " palindromes.");
+                    }
+                    return null;
+                }});
+            ssc.start();
+            //Stop in <time> seconds
+            new Thread(new Runnable() {
+                public void run() {
+                    try {
+                        Thread.sleep(time);
+                    } catch (InterruptedException e) {
+                        //Don't cast this exception into the void
+                        Thread.currentThread().interrupt();
+                    } finally {
+                        ssc.stop();
+                        output.println("Stopping after "+time/1000+" seconds.");
+                    }
+                }
+            }).start();
+            //Wait for streaming to terminate
+            ssc.awaitTermination();
+        } catch (FileNotFoundException e) {
+            return false;
+        }
+        return true;
+    }
+    @Override
+    public void setStreamingContext(StreamingContext context) {
+        this.ssc = new JavaStreamingContext(context);
+    }
+    @Override
+    public void setSparkContext(SparkContext context) {
+        this.sc = new JavaSparkContext(context);
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/TestResmgr.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/TestResmgr.java
new file mode 100644
index 0000000..455ff07
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/examples/TestResmgr.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.examples;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.NameValueJobInput;
+import org.apache.oodt.cas.resource.system.XmlRpcResourceManagerClient;
+
+//JDK imports
+import java.net.URL;
+
+/**
+ * 
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * Tests the Job Submission capability of the Resource Manager
+ * </p>.
+ */
+public class TestResmgr {
+
+  public static void main(String[] Args) {
+
+    if (Args.length != 1) {
+      System.err.println("Specify a XmlRpcResourceManager Host");
+      System.exit(1);
+    }
+
+    try {
+      URL managerUrl = new URL(Args[0]);
+      XmlRpcResourceManagerClient client = new XmlRpcResourceManagerClient(
+          managerUrl);
+
+      Job hw1 = new Job("JobOne", "HelloWorldJob",
+          "org.apache.oodt.cas.resource.examples.HelloWorldJob",
+          "org.apache.oodt.cas.resource.structs.NameValueJobInput", "quick",
+          new Integer(1));
+      NameValueJobInput hw1Input = new NameValueJobInput();
+      hw1Input.setNameValuePair("user.name", "Dave");
+
+      client.submitJob(hw1, hw1Input);
+
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+
+  }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobqueue/JobQueue.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobqueue/JobQueue.java
new file mode 100644
index 0000000..370467b
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobqueue/JobQueue.java
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.jobqueue;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.resource.jobrepo.JobRepository;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.exceptions.JobQueueException;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An interface for persisting {@link JobSpec}s used by a
+ * {@link JobQueueController}.
+ * </p>.
+ */
+public interface JobQueue {
+
+  /**
+   * Persists a {@link JobSpec} to the queue.
+   * 
+   * @param spec
+   *          The {@link JobSpec} to persist.
+   * @return The ID of the JobSpec in the queue.
+   * @throws JobQueueException
+   *           If there is any error queueing the {@link JobSpec}.
+   */
+  public String addJob(JobSpec spec) throws JobQueueException;
+  
+  /**
+   * Re-adds a {@link JobSpec} to the back of the queue.
+   * 
+   * @param spec
+   *          The {@link JobSpec} to re-add.
+   * @throws JobQueueException
+   *           If there is any error requeueing the {@link JobSpec}.
+   */
+  public String requeueJob(JobSpec spec) throws JobQueueException;
+  
+  /**
+   * Gets an ordered {@link List} of queued {@link JobSpec}s.
+   * 
+   * @return An ordered {@link List} of queued {@link JobSpec}s.
+   * @throws JobQueueException
+   *           If there is any error obtaining the queued jobs.
+   */
+  public List getQueuedJobs() throws JobQueueException;
+
+  /**
+   * Purges all {@link JobSpec}s from the queue.
+   * 
+   * @throws JobQueueException
+   *           If there is any error purging all the {@link JobSpec}s.
+   */
+  public void purge() throws JobQueueException;
+
+  /**
+   * Returns a boolean value representing whether or not the queue is empty.
+   * 
+   * @return true, if the queue is empty, false otherwise.
+   */
+  public boolean isEmpty();
+
+  /**
+   * Gets the next {@link JobSpec} from the queue, and correspondingly removes
+   * it from persitance.
+   * 
+   * @return The next {@link JobSpec} from the queue.
+   * @throws JobQueueException
+   *           If there is any error getting the next {@link JobSpec}.
+   */
+  public JobSpec getNextJob() throws JobQueueException;
+  
+  
+  /**
+   * Gets the underlying {@link JobSpec} persistance layer
+   * used by this {@link JobQueue}.
+   * @return The underlying {@link JobRepository}.
+   */
+  public JobRepository getJobRepository();
+
+  /**
+   * Gets the number of jobs in queue
+   * @return Number of jobs in queue
+   */
+  public int getSize();
+  
+  /**
+   * Gets the max number of jobs allowed in
+   * queue at any given time
+   * @return Max number of jobs
+   */
+  public int getCapacity();
+  
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobqueue/JobQueueFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobqueue/JobQueueFactory.java
new file mode 100644
index 0000000..1c91d84
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobqueue/JobQueueFactory.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.jobqueue;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A factory for creating {@link JobQueue} services
+ * </p>.
+ */
+public interface JobQueueFactory {
+
+  /**
+   * Creates new {@link JobQueue} implementations.
+   * 
+   * @return New {@link JobQueue} implementations.
+   */
+  public JobQueue createQueue();
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobqueue/JobStack.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobqueue/JobStack.java
new file mode 100644
index 0000000..bc95c23
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobqueue/JobStack.java
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.jobqueue;
+
+//OODT imports
+import org.apache.oodt.cas.resource.jobrepo.JobRepository;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.JobStatus;
+import org.apache.oodt.cas.resource.structs.exceptions.JobQueueException;
+import org.apache.oodt.cas.resource.structs.exceptions.JobRepositoryException;
+
+//JAVA imports
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * 
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * The Job Stack for unallocatable Jobs.
+ * </p>
+ */
+public class JobStack implements JobQueue {
+  
+  /* our queue */
+  private Vector queue;
+
+  /* max queue size */
+  private int maxQueueSize;
+  
+  /* our job persistance layer */
+  private JobRepository repo;
+
+  /* our log stream */
+  private static final Logger LOG = Logger.getLogger(JobStack.class.getName());
+
+  public JobStack(int maxSize, JobRepository repo) {
+    queue = new Vector();
+    maxQueueSize = maxSize;
+    this.repo = repo;
+  }
+  
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.jobqueue.JobQueue#addJob(org.apache.oodt.cas.resource.structs.JobSpec)
+   */
+  public String addJob(JobSpec spec) throws JobQueueException {
+    String jobId = safeAddJob(spec);
+    if (queue.size() != maxQueueSize) {
+      LOG
+          .log(Level.INFO, "Added Job: [" + spec.getJob().getId()
+              + "] to queue");
+      queue.add(spec);
+      spec.getJob().setStatus(JobStatus.QUEUED);
+      safeUpdateJob(spec);
+      return jobId;
+    } else
+      throw new JobQueueException("Reached max queue size: [" + maxQueueSize
+          + "]: Unable to add job: [" + spec.getJob().getId() + "]");
+  }
+
+  /*
+   * (non-Javadoc)
+   * @see gov.nasa.jpl.oodt.cas.resource.jobqueue.JobQueue#requeueJob(gov.nasa.jpl.oodt.cas.resource.structs.JobSpec)
+   */
+  public String requeueJob(JobSpec spec) throws JobQueueException {
+	  try {
+	      queue.add(spec);
+	      spec.getJob().setStatus(JobStatus.QUEUED);
+	      safeUpdateJob(spec);
+	      return spec.getJob().getId();
+	  }catch (Exception e) {
+		  throw new JobQueueException("Failed to re-queue job '"
+                    + (spec != null ? spec.getJob().getId() : "null") + "' : "
+                    + e.getMessage(), e);
+	  }
+  }
+  
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.jobqueue.JobQueue#getQueuedJobs()
+   */
+  public List getQueuedJobs() throws JobQueueException {
+    return queue;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.jobqueue.JobQueue#purge()
+   */
+  public void purge() throws JobQueueException {
+    queue.removeAllElements();
+    //TODO: think about whether or not it makes
+    //sense to do something with the JobRepository
+    //here too
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.resource.jobqueue.JobQueue#isEmpty()
+   */
+  public boolean isEmpty() {
+    return queue.isEmpty();
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.resource.jobqueue.JobQueue#getNextJob()
+   */
+  public JobSpec getNextJob() throws JobQueueException {
+    JobSpec spec = (JobSpec)queue.remove(0);
+    // update its status since getNextJob is
+    // called by the scheduler when it is going
+    // to execute a job
+    spec.getJob().setStatus(JobStatus.SCHEDULED);
+    safeUpdateJob(spec);
+    return spec;
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.resource.jobqueue.JobQueue#getJobRepository()
+   */
+  public JobRepository getJobRepository() {
+    return repo;
+  }
+  
+  private void safeUpdateJob(JobSpec spec) {
+    try {
+      this.repo.updateJob(spec);
+    } catch (JobRepositoryException e) {
+      LOG.log(Level.WARNING, "Exception updating job: ["
+          + spec.getJob().getId() + "]: Message: " + e.getMessage());
+    }
+  }
+  
+  private String safeAddJob(JobSpec spec) {
+    try {
+      return this.repo.addJob(spec);
+    } catch (JobRepositoryException e) {
+      LOG
+          .log(Level.WARNING, "Exception adding job: Message: "
+              + e.getMessage());
+      return null;
+    }
+  }
+
+	public int getCapacity() {
+		return this.maxQueueSize;
+	}
+
+	public int getSize() {
+		return this.queue.size();
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobqueue/JobStackJobQueueFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobqueue/JobStackJobQueueFactory.java
new file mode 100644
index 0000000..e2205d3
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobqueue/JobStackJobQueueFactory.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.jobqueue;
+
+import org.apache.oodt.cas.resource.jobrepo.JobRepository;
+import org.apache.oodt.cas.resource.util.GenericResourceManagerObjectFactory;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A factory for creating {@link JobStack} {@link JobQueue}s.
+ * </p>.
+ */
+public class JobStackJobQueueFactory implements JobQueueFactory {
+
+  /* the maximum size of the jobqueue */
+  private int stackSize = -1;
+  
+  /* our job repository for persisting jobs */
+  private JobRepository repo;
+
+  public JobStackJobQueueFactory() {
+    String stackSizeStr = System
+        .getProperty("org.apache.oodt.cas.resource.jobqueue.jobstack.maxstacksize");
+
+    if (stackSizeStr != null) {
+      stackSize = Integer.parseInt(stackSizeStr);
+    }
+    
+    String jobRepoFactoryClassStr = System.getProperty(
+        "resource.jobrepo.factory",
+        "org.apache.oodt.cas.resource.jobrepo.MemoryJobRepositoryFactory");
+    this.repo = GenericResourceManagerObjectFactory
+        .getJobRepositoryFromServiceFactory(jobRepoFactoryClassStr);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.jobqueue.JobQueueFactory#createQueue()
+   */
+  public JobQueue createQueue() {
+    return new JobStack(stackSize, repo);
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/JobRepository.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/JobRepository.java
new file mode 100644
index 0000000..d08d074
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/JobRepository.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.jobrepo;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.exceptions.JobRepositoryException;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An interface for persisting {@link JobSpec}s
+ * </p>.
+ */
+public interface JobRepository {
+
+  public String addJob(JobSpec spec) throws JobRepositoryException;
+
+  public void updateJob(JobSpec spec) throws JobRepositoryException;
+
+  public void removeJob(JobSpec spec) throws JobRepositoryException;
+  
+  public JobSpec getJobById(String jobId) throws JobRepositoryException;
+
+  public String getStatus(JobSpec spec) throws JobRepositoryException;
+
+  public boolean jobFinished(JobSpec spec) throws JobRepositoryException;
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/JobRepositoryFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/JobRepositoryFactory.java
new file mode 100644
index 0000000..d76714a
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/JobRepositoryFactory.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.jobrepo;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory for creating {@link JobRepository}s
+ * </p>.
+ */
+public interface JobRepositoryFactory {
+
+  /**
+   * Creates new {@link JobRepository} implementations.
+   * 
+   * @return A new {@link JobRepository} implementation.
+   */
+  public JobRepository createRepository();
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/MemoryJobRepository.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/MemoryJobRepository.java
new file mode 100644
index 0000000..b9283e6
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/MemoryJobRepository.java
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.jobrepo;
+
+//JDK imports
+import java.util.Date;
+import java.util.HashMap;
+
+//OODT imports
+import org.apache.oodt.commons.util.DateConvert;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.JobStatus;
+import org.apache.oodt.cas.resource.structs.exceptions.JobRepositoryException;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * An implementation of a {@link JobRepository} that uses an internal
+ * {@link HashMap} for persisting its {@link JobSpec}s.
+ */
+public class MemoryJobRepository implements JobRepository {
+
+  /*
+   * our storage for {@link JobSpec}s. A map of job id to {@link JobSpec}.
+   */
+  private HashMap jobMap = null;
+
+  public MemoryJobRepository() {
+    jobMap = new HashMap();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.jobrepo.JobRepository#addJob(org.apache.oodt.cas.resource.structs.JobSpec)
+   */
+  public String addJob(JobSpec spec) throws JobRepositoryException {
+    // need to generate a JobId for this job
+    String jobId = DateConvert.isoFormat(new Date());
+
+    if (spec.getJob() != null) {
+      spec.getJob().setId(jobId);
+      jobMap.put(jobId, spec);
+      return jobId;
+    } else
+      throw new JobRepositoryException("Exception persisting job: job is null!");
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.jobrepo.JobRepository#getStatus(org.apache.oodt.cas.resource.structs.JobSpec)
+   */
+  public String getStatus(JobSpec spec) throws JobRepositoryException {
+    JobSpec persistedSpec = (JobSpec) jobMap.get(spec.getJob().getId());
+    return persistedSpec.getJob().getStatus();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.jobrepo.JobRepository#jobFinished(org.apache.oodt.cas.resource.structs.JobSpec)
+   */
+  public boolean jobFinished(JobSpec spec) throws JobRepositoryException {
+    JobSpec persistedSpec = (JobSpec) jobMap.get(spec.getJob().getId());
+    return persistedSpec.getJob().getStatus().equals(JobStatus.SUCCESS) 
+    	||  persistedSpec.getJob().getStatus().equals(JobStatus.FAILURE);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.jobrepo.JobRepository#removeJob(org.apache.oodt.cas.resource.structs.JobSpec)
+   */
+  public void removeJob(JobSpec spec) throws JobRepositoryException {
+    if (jobMap.remove(spec.getJob().getId()) == null) {
+      throw new JobRepositoryException("Attempt to remove a job: ["
+          + spec.getJob().getId() + "] that is not currently persisted");
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.jobrepo.JobRepository#updateJob(org.apache.oodt.cas.resource.structs.JobSpec)
+   */
+  public void updateJob(JobSpec spec) throws JobRepositoryException {
+    jobMap.put(spec.getJob().getId(), spec);
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.jobrepo.JobRepository#getJobById(java.lang.String)
+   */
+  public JobSpec getJobById(String jobId) throws JobRepositoryException {
+    return (JobSpec) jobMap.get(jobId);
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/MemoryJobRepositoryFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/MemoryJobRepositoryFactory.java
new file mode 100644
index 0000000..9d8b42e
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/MemoryJobRepositoryFactory.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.jobrepo;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>Creates new {@link MemoryJobRepository}s.s 
+ * </p>.
+ */
+public class MemoryJobRepositoryFactory implements JobRepositoryFactory {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.jobrepo.JobRepositoryFactory#createRepository()
+   */
+  public JobRepository createRepository() {
+    return new MemoryJobRepository();
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/XStreamJobRepository.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/XStreamJobRepository.java
new file mode 100644
index 0000000..a931bcb
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/XStreamJobRepository.java
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.jobrepo;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.Vector;
+
+//CommonsIO imports
+import org.apache.commons.io.FileUtils;
+
+//XStream imports
+import com.thoughtworks.xstream.XStream;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.JobStatus;
+import org.apache.oodt.cas.resource.structs.exceptions.JobRepositoryException;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * XStream based JobRepository
+ */
+public class XStreamJobRepository implements JobRepository {
+
+	private File workingDir;
+	private final int maxHistory;
+	private Map<String, String> jobMap;
+	private List<String> jobPrecedence;
+	
+	public XStreamJobRepository(File workingDir, int maxHistory) {
+		this.workingDir = workingDir;
+		this.maxHistory = Math.max(maxHistory == -1 ? Integer.MAX_VALUE : maxHistory, 1);
+		this.jobMap = Collections.synchronizedMap(new HashMap<String, String>());
+		this.jobPrecedence = new Vector<String>();
+	}
+	
+	public synchronized String addJob(JobSpec spec) throws JobRepositoryException {
+	    XStream xstream = new XStream();
+	    FileOutputStream os = null;
+		try {
+			if (this.jobMap.size() >= this.maxHistory)
+				FileUtils.forceDelete(new File(jobMap.remove(jobPrecedence.remove(0))));
+			
+			if (spec.getJob().getId() == null)
+			    spec.getJob().setId(UUID.randomUUID().toString());
+			else if (this.jobMap.containsKey(spec.getJob().getId()))
+				throw new JobRepositoryException("JobId '" + spec.getJob().getId() + "' already in use -- must pick unique JobId");
+			
+			File file = this.generateFilePath(spec.getJob().getId());
+			os = new FileOutputStream(file);
+		    xstream.toXML(spec, os);
+		    jobMap.put(spec.getJob().getId(), file.getAbsolutePath());
+		    jobPrecedence.add(spec.getJob().getId());
+			return spec.getJob().getId();
+		}catch (Exception e) {
+			throw new JobRepositoryException("Failed to add job spec to repo : " + e.getMessage(), e);
+		}finally {
+			try {
+				os.close();
+			}catch (Exception e) {}
+		}
+	}
+
+	public JobSpec getJobById(String jobId) throws JobRepositoryException {
+	    XStream xstream = new XStream();
+	    FileInputStream is = null;
+		try {
+			is = new FileInputStream(new File(this.jobMap.get(jobId)));
+		    return (JobSpec) xstream.fromXML(is);
+		}catch (Exception e) {
+			throw new JobRepositoryException("Failed to load job spec from repo by id '" + jobId + "' : " + e.getMessage(), e);
+		}finally {
+			try {
+				is.close();
+			}catch (Exception e) {}
+		}
+	}
+
+	public String getStatus(JobSpec spec) throws JobRepositoryException {
+		return this.getJobById(spec.getJob().getId()).getJob().getStatus();
+	}
+
+	public boolean jobFinished(JobSpec spec) throws JobRepositoryException {
+		String status = this.getStatus(spec);
+	    return status.equals(JobStatus.SUCCESS);
+	}
+
+	public synchronized void removeJob(JobSpec spec) throws JobRepositoryException {
+		try {
+			FileUtils.forceDelete(new File(this.jobMap.get(spec.getJob().getId())));
+		    jobMap.remove(spec.getJob().getId());
+		    jobPrecedence.remove(spec.getJob().getId());
+		}catch (Exception e) {
+			throw new JobRepositoryException("Failed to delete job '" + spec.getJob().getId() + "' : " + e.getMessage(), e);
+		}
+	}
+
+	public synchronized void updateJob(JobSpec spec) throws JobRepositoryException {
+	    XStream xstream = new XStream();
+	    FileOutputStream os = null;
+		try {
+			FileUtils.forceDelete(new File(this.jobMap.get(spec.getJob().getId())));
+			os = new FileOutputStream(new File(this.jobMap.get(spec.getJob().getId())));
+		    xstream.toXML(spec, os);
+		}catch (Exception e) {
+			throw new JobRepositoryException("Failed to add job spec to repo : " + e.getMessage(), e);
+		}finally {
+			try {
+				os.close();
+			}catch (Exception e) {}
+		}
+	}
+	
+	protected File generateFilePath(String jobId) {
+		return new File(workingDir, jobId + ".xstream");
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/XStreamJobRepositoryFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/XStreamJobRepositoryFactory.java
new file mode 100644
index 0000000..9e0288c
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/jobrepo/XStreamJobRepositoryFactory.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.jobrepo;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * Factory for creating XStream based JobRepository
+ */
+public class XStreamJobRepositoryFactory implements JobRepositoryFactory {
+
+	private static final Logger LOG = Logger.getLogger(XStreamJobRepositoryFactory.class.getName());
+	
+	public XStreamJobRepository createRepository() {
+		try {
+			String workingDirPropVal = System.getProperty("org.apache.oodt.cas.resource.jobrepo.xstream.working.dir");
+			if (workingDirPropVal == null)
+				return null;
+			else
+				workingDirPropVal = PathUtils.doDynamicReplacement(workingDirPropVal);
+			File working = new File(workingDirPropVal);
+			if (!working.exists())
+				working.mkdirs();
+			int maxHistory = Integer.parseInt(System.getProperty("org.apache.oodt.cas.resource.jobrepo.xstream.max.history", "-1"));
+			return new XStreamJobRepository(working, maxHistory);
+		}catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed to loaded XStreamJobRepository : " + e.getMessage(), e);
+			return null;
+		}
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/metadata/JobMetadata.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/metadata/JobMetadata.java
new file mode 100644
index 0000000..43f7b34
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/metadata/JobMetadata.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A set of metadata constants used by {@link Job}s in the resource manager.
+ * </p>
+ */
+public interface JobMetadata {
+
+	public static final String QUEUE_NAME = "QUEUE_NAME";
+
+	public static final String LOAD = "LOAD";
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/AssignmentMonitor.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/AssignmentMonitor.java
new file mode 100644
index 0000000..024a659
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/AssignmentMonitor.java
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor;
+
+//JDK imports
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+
+/**
+ * 
+ * @author woollard
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An implementation of the {@link Monitor} interface that loads its information
+ * about the underlying nodes from an XML file called <code>nodes.xml</code>.
+ * This implementation additionally uses an in-memory hash map to monitor the
+ * load on a given set of {@link ResourceNode}s.
+ * </p>
+ */
+public class AssignmentMonitor implements Monitor {
+	
+    /* our nodes map */
+    private static HashMap<String, ResourceNode> nodesMap;
+
+    /* our load map */
+    private static HashMap<String, Integer> loadMap;
+
+    public AssignmentMonitor(List<ResourceNode> nodes) {
+        nodesMap = new HashMap<String, ResourceNode>();
+        loadMap = new HashMap<String, Integer>();
+        
+        for (ResourceNode node : nodes) {
+            nodesMap.put(node.getNodeId(), node);
+            loadMap.put(node.getNodeId(), new Integer(0));
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see gov.nasa.jpl.oodt.cas.resource.monitor.Monitor#assignLoad(
+     *      gov.nasa.jpl.oodt.cas.resource.structs.ResourceNode, int)
+     */
+    @Override
+    public boolean assignLoad(ResourceNode node, int loadValue)
+            throws MonitorException {
+        int loadCap = node.getCapacity();
+        int curLoad = loadMap.get(node.getNodeId());
+
+        if (loadValue <= (loadCap - curLoad)) {
+            loadMap.remove(node.getNodeId());
+            loadMap.put(node.getNodeId(), new Integer(curLoad + loadValue));
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public boolean reduceLoad(ResourceNode node, int loadValue)
+            throws MonitorException {
+        int load = loadMap.get(node.getNodeId());
+        int newVal = load - loadValue;
+        if (newVal < 0)
+            newVal = 0; // should not happen but just in case
+        loadMap.remove(node.getNodeId());
+        loadMap.put(node.getNodeId(), new Integer(newVal));
+        return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see gov.nasa.jpl.oodt.cas.resource.monitor.Monitor#getLoad(gov.nasa.jpl.oodt.cas.resource.structs.ResourceNode)
+     */
+    public int getLoad(ResourceNode node) throws MonitorException {
+        ResourceNode resource = (ResourceNode) nodesMap.get(node.getNodeId());
+        int i = loadMap.get(node.getNodeId());
+        return (resource.getCapacity() - i);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see gov.nasa.jpl.oodt.cas.resource.monitor.Monitor#getNodes()
+     */
+    public List<ResourceNode> getNodes() throws MonitorException {
+        return new Vector<ResourceNode>(nodesMap.values());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see gov.nasa.jpl.oodt.cas.resource.monitor.Monitor#getNodeById(java.lang.String)
+     */
+    public ResourceNode getNodeById(String nodeId) throws MonitorException {
+        return (ResourceNode) nodesMap.get(nodeId);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see gov.nasa.jpl.oodt.cas.resource.monitor.Monitor#getNodeByURL(java.net.URL)
+     */
+    public ResourceNode getNodeByURL(URL ipAddr) throws MonitorException {
+        ResourceNode targetResource = null;
+        List<ResourceNode> nodes = this.getNodes();
+        for (int i = 0; i < nodes.size(); i++) {
+            if (((ResourceNode) nodes.get(i)).getIpAddr() == ipAddr) {
+                targetResource = (ResourceNode) nodes.get(i);
+                break;
+            }
+        }
+        return targetResource;
+    }
+
+    public void addNode(ResourceNode node) throws MonitorException {
+        nodesMap.put(node.getNodeId(), node);
+        if (!loadMap.containsKey(node.getNodeId()))
+            loadMap.put(node.getNodeId(), new Integer(0));
+    }
+
+    public void removeNodeById(String nodeId) throws MonitorException {
+        nodesMap.remove(nodeId);    
+        loadMap.remove(nodeId);
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/AssignmentMonitorFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/AssignmentMonitorFactory.java
new file mode 100644
index 0000000..ed87778
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/AssignmentMonitorFactory.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.monitor;
+
+//OODT imports
+import org.apache.oodt.cas.resource.noderepo.XmlNodeRepositoryFactory;
+import org.apache.oodt.cas.resource.util.GenericResourceManagerObjectFactory;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Creates implementations of {@link AssignmentMonitor}s.
+ * </p>
+ * 
+ */
+public class AssignmentMonitorFactory implements MonitorFactory {
+
+    private static final Logger LOG = Logger
+            .getLogger(AssignmentMonitorFactory.class.getName());
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * gov.nasa.jpl.oodt.cas.resource.monitor.MonitorFactory#createMonitor()
+     */
+    public AssignmentMonitor createMonitor() {
+        try {
+            String nodeRepoFactoryStr = System.getProperty(
+                    "gov.nasa.jpl.oodt.cas.resource.nodes.repo.factory",
+                    XmlNodeRepositoryFactory.class.getCanonicalName());
+            return new AssignmentMonitor(GenericResourceManagerObjectFactory
+                    .getNodeRepositoryFromFactory(nodeRepoFactoryStr)
+                    .loadNodes());
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, "Failed to create Assignment Monitor : "
+                    + e.getMessage(), e);
+            return null;
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/MesosMonitor.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/MesosMonitor.java
new file mode 100644
index 0000000..4a8b374
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/MesosMonitor.java
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.monitor;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+
+/**
+ * @author starchmd
+ * @version $Revision$
+ *
+ * A monitor to monitor the mesos-cluster jobs.
+ */
+public class MesosMonitor implements Monitor {
+
+    private static HashMap<String, ResourceNode> nodesMap = new HashMap<String, ResourceNode>();
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#getLoad(org.apache.oodt.cas.resource.structs.ResourceNode)
+     */
+    @Override
+    public int getLoad(ResourceNode node) throws MonitorException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#getNodes()
+     */
+    @Override
+    public List<ResourceNode> getNodes() throws MonitorException {
+        return new LinkedList<ResourceNode>(nodesMap.values());
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#getNodeById(java.lang.String)
+     */
+    @Override
+    public ResourceNode getNodeById(String nodeId) throws MonitorException {
+        return nodesMap.get(nodeId);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#getNodeByURL(java.net.URL)
+     */
+    @Override
+    public ResourceNode getNodeByURL(URL ipAddr) throws MonitorException {
+        for (ResourceNode node : nodesMap.values())
+            if (node.getIpAddr().equals(ipAddr))
+                return node;
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#reduceLoad(org.apache.oodt.cas.resource.structs.ResourceNode, int)
+     */
+    @Override
+    public boolean reduceLoad(ResourceNode node, int loadValue)
+            throws MonitorException {
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#assignLoad(org.apache.oodt.cas.resource.structs.ResourceNode, int)
+     */
+    @Override
+    public boolean assignLoad(ResourceNode node, int loadValue)
+            throws MonitorException {
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#addNode(org.apache.oodt.cas.resource.structs.ResourceNode)
+     */
+    @Override
+    public void addNode(ResourceNode node) throws MonitorException {
+        nodesMap.put(node.getNodeId(), node);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#removeNodeById(java.lang.String)
+     */
+    @Override
+    public void removeNodeById(String nodeId) throws MonitorException {
+        nodesMap.remove(nodeId);
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/MesosMonitorFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/MesosMonitorFactory.java
new file mode 100644
index 0000000..067ad8a
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/MesosMonitorFactory.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author starchmd
+ * @version $Revision$
+ *
+ * <p>
+ * Creates implementations of {@link MesosMonitor}s.
+ * </p>
+ *
+ */
+public class MesosMonitorFactory implements MonitorFactory {
+
+    private static final Logger LOG = Logger
+            .getLogger(MesosMonitorFactory.class.getName());
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * gov.nasa.jpl.oodt.cas.resource.monitor.MonitorFactory#createMonitor()
+     */
+    public MesosMonitor createMonitor() {
+        try {
+            return new MesosMonitor();
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, "Failed to create Mesos Monitor : " + e.getMessage(), e);
+            return null;
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/Monitor.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/Monitor.java
new file mode 100644
index 0000000..6c5fef2
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/Monitor.java
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.monitor;
+
+//JDK imports
+import java.util.List;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+
+/**
+ * 
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The Job Monitor interface.
+ * </p>
+ */
+public interface Monitor {
+
+ /**
+   * Gets the load on a resource node available to the resource manager.
+   * 
+   * @param node
+   *          The {@link ResourceNode} to obtain the load for.
+   * @return An integer respresentation of the load on a {@link ResourceNode}.
+   * @throws MonitorException
+   *           If there is any error obtaining the load.
+   */
+  public int getLoad(ResourceNode node) throws MonitorException;
+
+  /**
+   * 
+   * @return A {@link List} of the {@link ResourceNode}s known to the resource
+   *         manager.
+   * @throws MonitorException
+   *           If any error occurs getting the {@link List} of
+   *           {@link ResourceNode}s.
+   */
+  public List getNodes() throws MonitorException;
+  
+  
+  /**
+   * Gets the {@link ResourceNode} with the given <code>nodeId</code>.
+   * 
+   * @return The {@link ResourceNode} for the corresponding <code>nodeId</code>.
+   * @throws MonitorException
+   *           If any error occurs.
+   */
+  public ResourceNode getNodeById(String nodeId) throws MonitorException;
+
+  
+  /**
+   * Returns the {@link ResourceNode} with the given <code>ipAddr</code>.
+   * @param ipAddr The URL of the ResourceNode to return.
+   * @return The {@link ResourceNode} with the given ipAddr.
+   * @throws MonitorException If any error occurs.
+   */
+  public ResourceNode getNodeByURL(URL ipAddr) throws MonitorException;
+  
+  /**
+   * Reduces the load on a particular {@link ResourceNode} by the given
+   * <code>loadValue</code>.
+   * 
+   * @param node The {@link ResourceNode} to reduce the load on.
+   * @param loadValue The amount of reduction.
+   * @return True if successfully reduced, false otherwise.
+   * @throws MonitorException If any error occurs.
+   */
+  public boolean reduceLoad(ResourceNode node, int loadValue)
+  throws MonitorException;
+  
+  
+  /**
+   * 
+   * @param node
+   *          The {@link ResourceNode} to assign load to.
+   * @param loadValue
+   *          The integer load to assign to the given {@link ResourceNode}.
+   *          
+   * @return True if the Monitor was able to assign the load, false
+   * otherwise.
+   * @throws MonitorException
+   *           If any error occurs assigning the load.
+   */
+  public boolean assignLoad(ResourceNode node, int loadValue)
+      throws MonitorException;
+  
+	/**
+     * Adds a new {@link ResourceNode} for this {@link Monitor} to manage (if
+     * node already exist, then should perform update)
+     * 
+     * @param node
+     *            The new {@link ResourceNode} to manage
+     */
+    public void addNode(ResourceNode node) throws MonitorException;
+
+    /**
+     * Remove {@link ResourceNode} from this {@link Monitor}
+     * 
+     * @param nodeId
+     *            The id of the {@link ResourceNode} to remove
+     */
+    public void removeNodeById(String nodeId) throws MonitorException;
+	
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/MonitorFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/MonitorFactory.java
new file mode 100644
index 0000000..41f9792
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/MonitorFactory.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.monitor;
+
+/**
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * Creates new {@link Monitor} implementations.
+ * </p>
+ * 
+ */
+public interface MonitorFactory {
+
+	/**
+	 * @return A new implementation of the {@link Monitor} interface.
+	 */
+	public Monitor createMonitor();
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaAdapter.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaAdapter.java
new file mode 100644
index 0000000..64ea0b5
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaAdapter.java
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor.ganglia;
+
+//OODT imports
+import org.apache.oodt.cas.resource.monitor.ganglia.configuration.Cluster;
+import org.apache.oodt.cas.resource.monitor.ganglia.configuration.Host;
+import org.apache.oodt.cas.resource.monitor.ganglia.configuration.Metric;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+
+//JDK imports
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author rajith
+ * @author mattmann
+ * @version $Revision$
+ */
+public class GangliaAdapter {
+
+    private static final String ENCODING = "ISO-8859-1";
+
+    private String host;
+    
+    private int port;
+    
+    
+    public GangliaAdapter(String host, int port){
+       	this.host = host;
+       	this.port = port;
+    }
+
+    protected GangliaAdapter(){
+    	this(null, -9999);
+    }
+    
+    /**
+     * Get resource nodes' status.
+     * @return Map that contains status of resource nodes
+     * @throws org.apache.oodt.cas.resource.monitor.exceptions.MonitorException if an error occurred.
+     */
+    public Map<String, Map<String,String>> getResourceNodeStatus()
+            throws MonitorException {
+        List<Cluster> gridStatus = parseConfiguration(readXMLDump(this.host, this.port));
+        return filterNodes(gridStatus);
+    }
+    
+    /**
+     * 
+     * @return A string representation of the {@link #host}:{@link #port}
+     */
+    public String getUrlString(){
+    	return this.host+":"+this.port;
+    }
+
+    /**
+     * Filter out the nodes from the grid state ganglia configuration
+     * @param gridStatus Ganglia meta daemon parsed grid status
+     * @return resource node Map
+     */
+    private Map<String, Map<String,String>> filterNodes (List<Cluster> gridStatus){
+
+        Map<String, Map<String,String>> nodes = new HashMap<String, Map<String,String>>();
+        for (Cluster cluster : gridStatus) {
+            for (Host host : cluster.getHosts()) {
+                    Map<String, String> metrics = new HashMap<String, String>();
+                    for (Metric metric : host.getMetrics()) {
+                        metrics.put(metric.getName(), metric.getValue());
+                    }
+                    metrics.put(GangliaMetKeys.TN,host.getTn());
+                    metrics.put(GangliaMetKeys.TMAX, host.getTmax());
+                    metrics.put(GangliaMetKeys.IP, host.getIp());
+                    metrics.put(GangliaMetKeys.NAME, host.getName());
+                    nodes.put(host.getName(), metrics);
+            }
+        }
+        return nodes;
+    }
+
+    /**
+     * Get a XML dump from a ganglia meta daemon.
+     * @return A String that contains all the dump
+     * @throws org.apache.oodt.cas.resource.monitor.exceptions.MonitorException {@link org.apache.oodt.cas.resource.monitor.exceptions.MonitorException}
+     * if an error occurred during the read.
+     */
+    private String readXMLDump(String host, int port) throws MonitorException {
+        StringBuilder buffer = new StringBuilder();
+
+        try {
+            Socket s = new Socket(host, port);
+            BufferedReader reader =
+                    new BufferedReader(new InputStreamReader(s.getInputStream(), ENCODING));
+            String line = reader.readLine();
+            while (line != null) {
+                buffer.append(line);
+                line = reader.readLine();
+            }
+            reader.close();
+        } catch (UnknownHostException e) {
+            throw new MonitorException
+                    ("Unknown host: " + host + ":" + port + "-" + e.getMessage());
+        } catch (IOException e) {
+            throw new MonitorException
+                    ("Unable to get the monitoring report from the GMeta daemon: "
+                            + e.getMessage());
+        }
+        return buffer.toString().trim();
+    }
+
+    /**
+     * Parse a configuration from a XML output of a Ganglia meta daemon.
+     * @param buffer the XML buffer
+     * @return a Configuration
+     * @throws org.apache.oodt.cas.resource.monitor.exceptions.MonitorException {@link org.apache.oodt.cas.resource.monitor.exceptions.MonitorException} if an error occurred
+     */
+    private List<Cluster> parseConfiguration(String buffer)
+            throws MonitorException {
+        SAXParserFactory factory = SAXParserFactory.newInstance();
+        javax.xml.parsers.SAXParser parser;
+        GangliaXMLParser gangliaXMLParser;
+        try {
+            parser = factory.newSAXParser();
+            gangliaXMLParser = new GangliaXMLParser();
+            parser.parse(new InputSource(new StringReader(buffer)), gangliaXMLParser);
+
+        } catch (ParserConfigurationException e) {
+            throw new MonitorException("Error while parsing: " + e.getMessage());
+        } catch (SAXException e) {
+            throw new MonitorException("Error while parsing the XML: " + e.getMessage());
+        } catch (IOException e) {
+            throw new MonitorException("I/O error: " + e.getMessage());
+        }
+        return gangliaXMLParser.getGridConfiguration();
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaMetKeys.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaMetKeys.java
new file mode 100644
index 0000000..78a1bf3
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaMetKeys.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor.ganglia;
+
+/**
+ * @author rajith
+ * @version $Revision$
+ */
+public interface GangliaMetKeys {
+
+	/* XML specific keys */
+    public static final String CLUSTER = "CLUSTER";
+    public static final String HOST = "HOST";
+    public static final String METRIC = "METRIC";
+
+    public static final String NAME = "NAME";
+    public static final String VAL = "VAL";
+    public static final String TN = "TN";
+    public static final String TMAX = "TMAX";
+    public static final String DMAX = "DMAX";
+
+    /*Metric specific keys*/
+    public static final String TYPE = "TYPE";
+    public static final String UNITS = "UNITS";
+    public static final String SLOPE = "SLOPE";
+    public static final String SOURCE = "SOURCE";
+    public static final String EXTRA_ELEMENT = "EXTRA_ELEMENT";
+    public static final String GROUP = "GROUP";
+    public static final String DESC = "DESC";
+    public static final String TITLE = "TITLE";
+
+    /*Host specific keys*/
+    public static final String IP = "IP";
+    public static final String REPORTED = "REPORTED";
+    public static final String LOCATION = "LOCATION";
+    public static final String GMOND_STARTED = "GMOND_STARTED";
+
+    /*Cluster specific keys*/
+    public static final String LOCALTIME = "LOCALTIME";
+    public static final String OWNER = "OWNER";
+    public static final String LATLONG = "LATLONG";
+    public static final String URL = "URL";
+    
+    /*Ganglia metric keys*/
+    public static String LOAD_ONE = "load_one";
+    public static String LOAD_FIVE = "load_five";
+    public static String LOAD_FIFTEEN = "load_fifteen";
+    public static String CPU_NUM = "cpu_num";
+
+    /* Various needed keys */
+    public static int MAXIMUM_FRACTION_DIGITS = 3;
+
+
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaResourceMonitor.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaResourceMonitor.java
new file mode 100644
index 0000000..4a83d58
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaResourceMonitor.java
@@ -0,0 +1,274 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor.ganglia;
+
+//OODT imports
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.monitor.ganglia.loadcalc.LoadCalculator;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+import static org.apache.oodt.cas.resource.monitor.ganglia.GangliaMetKeys.NAME;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author rajith
+ * @author mattmann
+ * @version $Revision$
+ */
+public class GangliaResourceMonitor implements Monitor {
+
+	private static final Logger LOG = Logger
+			.getLogger(GangliaResourceMonitor.class.getName());
+	private LoadCalculator loadCalculator;
+	private Map<String, Integer> loadMap;
+	private Map<String, Map<String, String>> gmetaNodes;
+	private Map<String, GangliaAdapter> gmetaAdapters;
+	private static final int DEFAULT_PORT = 8649;
+
+	/**
+	 * Make a new GangliaResourceMonitor that reads information from a ganglia
+	 * meta daemon.
+	 * 
+	 * @param loadCalculator
+	 *            LoadCalculator
+	 *            {@link org.apache.oodt.cas.resource.monitor.ganglia.loadcalc.LoadCalculator}
+	 *            to calculate load
+	 * @param nodes
+	 *            resource nodes
+	 *            {@link org.apache.oodt.cas.resource.structs.ResourceNode} to
+	 *            be monitored.
+	 */
+	public GangliaResourceMonitor(LoadCalculator loadCalculator,
+			String gmetadHost, int gmetadPort) {
+		this.loadCalculator = loadCalculator;
+		this.loadMap = new HashMap<String, Integer>();
+		this.gmetaNodes = new HashMap<String, Map<String, String>>();
+		this.gmetaAdapters = new HashMap<String, GangliaAdapter>();
+		try {
+			this.initGmetaNodes(gmetadHost, gmetadPort);
+		} catch (Exception e) {
+			e.printStackTrace();
+			LOG.log(Level.WARNING,
+					"URL exception initializing gmetad nodes: [" + gmetadHost
+							+ ":" + gmetadPort + "]: Message: "
+							+ e.getMessage());
+		}
+
+	}
+
+	@Override
+	public int getLoad(ResourceNode node) throws MonitorException {
+		Map<String, String> nodeProperties = null;
+		String nodeId = node.getNodeId();
+		nodeProperties = this.locateNode(nodeId);
+		if (nodeProperties == null) {
+			throw new MonitorException(
+					"GangliaMonitor: not tracking requested node: [" + nodeId
+							+ "]");
+		}
+
+		// calculate load
+		double calcLoad = this.loadCalculator.calculateLoad(nodeProperties);
+		System.out.println(calcLoad);
+		int load = new Long(Math.round(calcLoad)).intValue();
+		System.out.println("LOAD is: "+load);
+		return load;
+	}
+
+	@Override
+	public boolean assignLoad(ResourceNode node, int loadValue)
+			throws MonitorException {
+		// technically this method should simply do nothing, since
+		// putting a job onto a node should cause Ganglia to detect
+		// for now we'll simply track what the current perceived load
+		// on a node is - we may want to factor this into the weighting
+		// in load calculator later
+		String nodeId = node.getNodeId();
+		if (loadMap.containsKey(nodeId)) {
+			int currLoad = loadMap.get(nodeId);
+			currLoad += loadValue;
+			loadMap.put(nodeId, currLoad);
+		} else {
+			loadMap.put(nodeId, loadValue);
+		}
+		return true;
+	}
+
+	@Override
+	public void addNode(ResourceNode node) {
+		this.addGmetadNode(node.getIpAddr().getHost(), node.getIpAddr()
+				.getPort());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void removeNodeById(String nodeId) {
+		this.removeGmetadNode(nodeId);
+	}
+
+	@Override
+	public List getNodes() throws MonitorException {
+		List<ResourceNode> nodes = new Vector<ResourceNode>();
+		if (this.gmetaAdapters != null) {
+			for (GangliaAdapter adapter : this.gmetaAdapters.values()) {
+				Map<String, Map<String, String>> aNodes = adapter
+						.getResourceNodeStatus();
+				for (Map<String, String> map : aNodes.values()) {
+					try {
+						nodes.add(this.nodeFromMap(map));
+					} catch (MalformedURLException e) {
+						e.printStackTrace();
+						throw new MonitorException(e.getMessage());
+					}
+				}
+			}
+		}
+
+		return nodes;
+	}
+
+	@Override
+	public ResourceNode getNodeById(String nodeId) throws MonitorException {
+		try {
+			return this.nodeFromMap(this.locateNode(nodeId));
+		} catch (MalformedURLException e) {
+			e.printStackTrace();
+			throw new MonitorException(e.getMessage());
+		}
+	}
+
+	@Override
+	public ResourceNode getNodeByURL(URL ipAddr) throws MonitorException {
+		if (this.gmetaAdapters != null) {
+			for (GangliaAdapter adapter : this.gmetaAdapters.values()) {
+				Map<String, Map<String, String>> aNodes = adapter
+						.getResourceNodeStatus();
+				for (String aNodeId : aNodes.keySet()) {
+					String host = ipAddr.getHost();
+					int port = ipAddr.getPort();
+					Map<String, String> nodeProps = aNodes.get(aNodeId);
+					if (aNodeId.equals(host)
+							&& nodeProps.get(DEFAULT_PORT).equals(
+									String.valueOf(port))) {
+						try {
+							return this.nodeFromMap(aNodes.get(aNodeId));
+						} catch (MalformedURLException e) {
+							e.printStackTrace();
+							throw new MonitorException(e.getMessage());
+						}
+					}
+				}
+			}
+		}
+
+		return null;
+	}
+
+	@Override
+	public boolean reduceLoad(ResourceNode node, int loadValue)
+			throws MonitorException {
+		String nodeId = node.getNodeId();
+		if (this.loadMap.containsKey(nodeId)) {
+			int currLoad = loadMap.get(nodeId);
+			currLoad = Math.min(0, currLoad - loadValue);
+			this.loadMap.put(nodeId, currLoad);
+		} else {
+			this.loadMap.put(nodeId, 0);
+		}
+		
+		return true;
+	}
+
+	private Map<String, String> locateNode(String nodeId) {
+		if (this.gmetaAdapters != null && this.gmetaAdapters.size() > 0) {
+			for (String nId : this.gmetaAdapters.keySet()) {
+				GangliaAdapter adapter = this.gmetaAdapters.get(nId);
+				try {
+					System.out.println("Querying gmetad: ["+adapter.getUrlString()+"]");
+					Map<String, Map<String, String>> nodeStatus = adapter
+							.getResourceNodeStatus();
+					System.out.println("Looking for nodeid: ["+nodeId+"]");
+					if (nodeStatus.containsKey(nodeId)) {
+						System.out.println("NODE met: "+nodeStatus.get(nodeId));
+						return nodeStatus.get(nodeId);
+					}
+				} catch (MonitorException e) {
+					LOG.log(Level.WARNING,
+							"MonitorException contacting Ganglia: ["
+									+ adapter.getUrlString() + "]");
+					e.printStackTrace();
+				}
+			}
+
+		}
+
+		return null;
+	}
+
+	private ResourceNode nodeFromMap(Map<String, String> map)
+			throws MalformedURLException {
+		if (map == null) return null;
+		ResourceNode node = new ResourceNode();
+		System.out.println("MAP IS "+map);
+		System.out.println("Setting hostname to "+map.get(NAME));
+		node.setId(map.get(NAME));
+		node.setIpAddr(new URL("http://" + map.get(NAME) + ":" + DEFAULT_PORT));
+		return node;
+	}
+
+	private void initGmetaNodes(String host, int port)
+			throws MalformedURLException {
+		this.addGmetadNode(host, port);
+	}
+
+	private GangliaAdapter createAdapter(Map<String, String> node) {
+		return new GangliaAdapter(node.get("host"), Integer.valueOf(node
+				.get("port")));
+	}
+
+	private void addGmetadNode(String host, int port) {
+		Map<String, String> rootNode = new HashMap<String, String>();
+		rootNode.put("host", host);
+		rootNode.put("port", String.valueOf(port));
+		this.gmetaNodes.put(host, rootNode);
+		this.gmetaAdapters.put(host, this.createAdapter(rootNode));
+	}
+
+	private void removeGmetadNode(String host) {
+		if (this.gmetaNodes.containsKey(host)
+				&& this.gmetaAdapters.containsKey(host)) {
+			LOG.log(Level.FINE,
+					"Removing gmetad node: ["
+							+ gmetaAdapters.get(host).getUrlString() + "]");
+			this.gmetaAdapters.remove(host);
+			this.gmetaNodes.remove(host);
+		}
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaResourceMonitorFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaResourceMonitorFactory.java
new file mode 100644
index 0000000..e87405b
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaResourceMonitorFactory.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor.ganglia;
+
+//JDK imports
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+
+//OODT imports
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.monitor.MonitorFactory;
+import org.apache.oodt.cas.resource.monitor.ganglia.loadcalc.LoadCalculator;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.util.GenericResourceManagerObjectFactory;
+
+/**
+ * @author rajith
+ * @version $Revision$
+ */
+public class GangliaResourceMonitorFactory implements MonitorFactory {
+
+	private static final Logger LOG = Logger
+			.getLogger(GangliaResourceMonitorFactory.class.getName());
+
+	@Override
+	public Monitor createMonitor() {
+		try {
+			String loadCalculatorFactoryStr = System
+					.getProperty("org.apache.oodt.cas.resource.monitor.loadcalc.factory");
+			String nodeRepoFactoryStr = System
+					.getProperty("org.apache.oodt.cas.resource.nodes.repo.factory");
+			
+			String gmetadHost = System
+                     .getProperty("org.apache.oodt.cas.resource.monitor.ganglia.gemtad.host.address");
+			
+			int gmetadPort = Integer.valueOf(System
+		                .getProperty("org.apache.oodt.cas.resource.monitor.ganglia.gemtad.host.port"));
+
+			LoadCalculator loadCalculator = GenericResourceManagerObjectFactory
+					.getLoadCalculatorFromServiceFactory(loadCalculatorFactoryStr);
+
+			return new GangliaResourceMonitor(loadCalculator, gmetadHost, gmetadPort);
+		} catch (Exception e) {
+			LOG.log(Level.SEVERE,
+					"Failed to create Resource Monitor : " + e.getMessage(), e);
+			return null;
+		}
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaXMLParser.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaXMLParser.java
new file mode 100644
index 0000000..f9de47a
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/GangliaXMLParser.java
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor.ganglia;
+
+import org.apache.oodt.cas.resource.monitor.ganglia.configuration.Cluster;
+import org.apache.oodt.cas.resource.monitor.ganglia.configuration.Host;
+import org.apache.oodt.cas.resource.monitor.ganglia.configuration.Metric;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author rajith
+ * @version $Revision$
+ *
+ * SAX parser to create a grid configuration from a XML stream.
+ * XML schema corresponds to a GMetad XML output.
+ */
+public class GangliaXMLParser extends DefaultHandler implements GangliaMetKeys {
+
+    private List<Cluster> grid;
+    private Cluster currentCluster;
+    private List<Host> currentClusterHosts;
+    private Host currentHost;
+    private List<Metric> currentHostMetrics;
+    private Metric currentMetric;
+    private HashMap<String, String> extraData;
+
+    /**
+     * {@inheritDoc}
+     */
+    public void endElement(String uri, String localName, String name) throws SAXException {
+        if (name.equals(METRIC)) {
+            this.currentMetric.setExtraData(extraData);
+            this.currentHostMetrics.add(currentMetric);
+
+        } else if (name.equals(HOST)) {
+            this.currentHost.setMetrics(currentHostMetrics);
+            this.currentClusterHosts.add(currentHost);
+
+        } else if (name.equals(CLUSTER)) {
+            this.currentCluster.setHosts(currentClusterHosts);
+            this.grid.add(currentCluster);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void startDocument() throws SAXException {
+        this.grid = new ArrayList<Cluster>();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void startElement(String uri, String localName, String name, Attributes atts) throws SAXException {
+        if (name.equals(METRIC)) {
+            this.currentMetric = new Metric(atts.getValue(NAME), atts.getValue(VAL), atts.getValue(TYPE),
+                    atts.getValue(UNITS), atts.getValue(TN), atts.getValue(TMAX), atts.getValue(DMAX),
+                    atts.getValue(SLOPE), atts.getValue(SOURCE));
+            this.extraData = new HashMap<String, String>();
+
+        } else if (name.equals(EXTRA_ELEMENT)) {
+            this.extraData.put(atts.getValue(NAME), atts.getValue(VAL));
+
+        } else if (name.equals(HOST)) {
+            this.currentHost = new Host(atts.getValue(NAME), atts.getValue(IP), atts.getValue(REPORTED),
+                    atts.getValue(TN), atts.getValue(TMAX), atts.getValue(DMAX), atts.getValue(LOCATION),
+                    atts.getValue(GMOND_STARTED));
+            this.currentHostMetrics = new ArrayList<Metric>();
+
+        } else if (name.equals(CLUSTER)) {
+            this.currentCluster = new Cluster(atts.getValue(NAME), atts.getValue(LOCALTIME), atts.getValue(OWNER),
+                    atts.getValue(LATLONG), atts.getValue(URL));
+            this.currentClusterHosts = new ArrayList<Host>();
+        }
+    }
+
+    /**
+     * Get the configuration after parsing the XML Stream.
+     *
+     * @return a grid configuration
+     */
+    public List<Cluster> getGridConfiguration() {
+        return this.grid;
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/configuration/Cluster.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/configuration/Cluster.java
new file mode 100644
index 0000000..5150392
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/configuration/Cluster.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor.ganglia.configuration;
+
+import java.util.List;
+
+/**
+ * @author rajith
+ * @version $Revision$
+ *
+ * Configuration element for the Ganglia cluster mapping. Contains hosts' status information
+ * of a particular cluster.
+ *
+ *  <CLUSTER NAME="" LOCALTIME="" OWNER="" LATLONG="" URL="">
+ *      <HOST NAME=....
+ *      ...
+ *      <HOST NAME=..
+ *  </CLUSTER>
+ */
+public class Cluster {
+
+    private String name;
+    private String localtime;
+    private String owner;
+    private String latLong;
+    private String url;
+    private List<Host> hosts;
+
+    public Cluster(String name, String localtime, String owner, String latLong, String url) {
+        this.name = name;
+        this.localtime = localtime;
+        this.owner = owner;
+        this.latLong = latLong;
+        this.url = url;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getOwner() {
+        return owner;
+    }
+
+    public String getLocaltime() {
+        return localtime;
+    }
+
+    public String getLatLong() {
+        return latLong;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public List<Host> getHosts() {
+        return hosts;
+    }
+
+    public void setHosts(List<Host> hosts) {
+        this.hosts = hosts;
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/configuration/Host.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/configuration/Host.java
new file mode 100644
index 0000000..509f202
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/configuration/Host.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor.ganglia.configuration;
+
+import java.util.List;
+
+/**
+ * @author rajith
+ * @version $Revision$
+ *
+ * Configuration element for the Ganglia host mapping. Consists with Metrics information
+ * of a particular host
+ *
+ *  <HOST NAME="" IP="" REPORTED="" TN="" TMAX="" DMAX="" LOCATION="" GMOND_STARTED="">
+ *      <METRIC NAME="" VAL="" TYPE="" UNITS="" TN="" TMAX="" DMAX="" SLOPE="" SOURCE="">
+ *      ............
+ *      <METRIC NAME=....
+ *  </HOST>
+ */
+public class Host {
+
+    private String name;
+    private String ip;
+    private String reported;
+    private String tn;
+    private String tmax;
+    private String dmax;
+    private String location;
+    private String gmondstarted;
+    private List<Metric> metrics;
+
+    public Host(String name, String ip, String reported, String tn, String tmax,
+                String dmax, String location, String gmondstarted) {
+        this.name = name;
+        this.ip = ip;
+        this.reported = reported;
+        this.tn = tn;
+        this.tmax = tmax;
+        this.dmax = dmax;
+        this.location = location;
+        this.gmondstarted = gmondstarted;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getIp() {
+        return ip;
+    }
+
+    public String getReported() {
+        return reported;
+    }
+
+    public String getTn() {
+        return tn;
+    }
+
+    public String getTmax() {
+        return tmax;
+    }
+
+    public String getDmax() {
+        return dmax;
+    }
+
+    public String getLocation() {
+        return location;
+    }
+
+    public String getGmondstarted() {
+        return gmondstarted;
+    }
+
+    public List<Metric> getMetrics() {
+        return metrics;
+    }
+
+    public void setMetrics(List<Metric> metrics) {
+        this.metrics = metrics;
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/configuration/Metric.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/configuration/Metric.java
new file mode 100644
index 0000000..3fcbcee
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/configuration/Metric.java
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor.ganglia.configuration;
+
+import java.util.HashMap;
+
+/**
+ * @author rajith
+ * @version $Revision$
+ *
+ * Configuration element for the Ganglia Metric mapping.
+ *
+ *  <METRIC NAME="" VAL="" TYPE="" UNITS="" TN="" TMAX="" DMAX="" SLOPE="" SOURCE="">
+ *      <EXTRA_DATA>
+ *          <EXTRA_ELEMENT NAME="" VAL=""/>
+ *          <EXTRA_ELEMENT NAME="" VAL=""/>
+ *          ........
+ *      </EXTRA_DATA>
+ *  </METRIC>
+ */
+public class Metric {
+
+    private String name;
+    private String value;
+    private String type;
+    private String units;
+    private String tn;
+    private String tmax;
+    private String dmax;
+    private String slope;
+    private String source;
+    private HashMap<String, String> extraData;
+
+    public Metric(String name, String value, String valueType, String units,
+                  String tn, String tmax, String dmax, String slope, String source) {
+        this.name = name;
+        this.value = value;
+        this.type = valueType;
+        this.units = units;
+        this.tn = tn;
+        this.tmax = tmax;
+        this.dmax = dmax;
+        this.slope = slope;
+        this.source = source;
+    }
+
+
+    public String getName() {
+        return name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getUnits() {
+        return units;
+    }
+
+    public String getTn() {
+        return tn;
+    }
+
+    public String getTmax() {
+        return tmax;
+    }
+
+    public String getDmax() {
+        return dmax;
+    }
+
+    public String getSlope() {
+        return slope;
+    }
+
+    public String getSource() {
+        return source;
+    }
+
+    public HashMap<String, String> getExtraData() {
+        return extraData;
+    }
+
+    public void setExtraData(HashMap<String, String> extraData) {
+        this.extraData = extraData;
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/loadcalc/LoadCalculator.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/loadcalc/LoadCalculator.java
new file mode 100644
index 0000000..730757a
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/loadcalc/LoadCalculator.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor.ganglia.loadcalc;
+
+//JDK imports
+import java.util.Map;
+
+/**
+ * @author rajith
+ * @author mattmann
+ * @version $Revision$
+ */
+public interface LoadCalculator {
+
+    /**
+     * Calculate the load and normalize it within the given node's capacity
+     * @param metrics status metrics of the resource node
+     * @return An integer representation of the load within 0 and node's capacity
+     */
+    public double calculateLoad(Map<String, String> metrics);
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/loadcalc/LoadCalculatorFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/loadcalc/LoadCalculatorFactory.java
new file mode 100644
index 0000000..cbe816a
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/loadcalc/LoadCalculatorFactory.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor.ganglia.loadcalc;
+
+/**
+ * @author rajith
+ * @version $Revision$
+ */
+public interface LoadCalculatorFactory {
+
+    /**
+     * @return A new implementation of the {@link LoadCalculator} interface.
+     */
+    public LoadCalculator createLoadCalculator();
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/loadcalc/WeightedAverageLoadCalc.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/loadcalc/WeightedAverageLoadCalc.java
new file mode 100644
index 0000000..31e264f
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/loadcalc/WeightedAverageLoadCalc.java
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor.ganglia.loadcalc;
+
+//JDK imports
+import java.text.NumberFormat;
+import java.util.Map;
+
+//OODT imports
+import static org.apache.oodt.cas.resource.monitor.ganglia.GangliaMetKeys.MAXIMUM_FRACTION_DIGITS;
+import static org.apache.oodt.cas.resource.monitor.ganglia.GangliaMetKeys.TN;
+import static org.apache.oodt.cas.resource.monitor.ganglia.GangliaMetKeys.TMAX;
+import static org.apache.oodt.cas.resource.monitor.ganglia.GangliaMetKeys.CPU_NUM;
+import static org.apache.oodt.cas.resource.monitor.ganglia.GangliaMetKeys.LOAD_ONE;
+import static org.apache.oodt.cas.resource.monitor.ganglia.GangliaMetKeys.LOAD_FIVE;
+import static org.apache.oodt.cas.resource.monitor.ganglia.GangliaMetKeys.LOAD_FIFTEEN;
+
+/**
+ * @author rajith
+ * @author mattmann
+ * @version $Revision$
+ */
+public class WeightedAverageLoadCalc implements LoadCalculator {
+
+    private double loadOneWeight;
+    private double loadFiveWeight;
+    private double loadFifteenWeight;
+
+    /* to format the load value*/
+    private NumberFormat numberFormat;
+
+    /**
+     * Make a new WeightedAverageLoadCalc {@link LoadCalculator}
+     * @param loadOneWeight weight for the load_one
+     * @param loadFiveWeight weight for the load_five
+     * @param loadFifteenWeight weight for the load_fifteen
+     */
+    public WeightedAverageLoadCalc (double loadOneWeight, double loadFiveWeight, double loadFifteenWeight){
+        this.loadOneWeight = loadOneWeight;
+        this.loadFiveWeight = loadFiveWeight;
+        this.loadFifteenWeight = loadFifteenWeight;
+
+        numberFormat = NumberFormat.getNumberInstance();
+        numberFormat.setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS);
+    }
+    /**
+     * {@inheritDoc}
+     *
+     * load is calculated as follows
+     * weightedLoadOne = loadOneWeight * minimum of (numOfCPUs, ((loadOne/numOfCPUs) * numOfCPUs))
+     *
+     * load = (weightedLoadOne + weightedLoadFive + weightedLoadFifteen) /
+     *           (loadOneWeight + loadFiveWeight + loadFifteenWeight)
+     */
+    @Override
+    public double calculateLoad(Map<String, String> nodeMetrics) {
+        double tn = Double.valueOf(nodeMetrics.get(TN));
+        double tmax = Double.valueOf(nodeMetrics.get(TMAX));
+        double numCpus = Double.valueOf(nodeMetrics.get(CPU_NUM));
+
+        if(tn > (4 * tmax)){
+           return numCpus; //if the node is offline assign the node's capacity as the load
+        }
+        else {
+            double weightedLoadOne = loadOneWeight * Math.min(numCpus,
+                    ((Double.valueOf(nodeMetrics.get(LOAD_ONE)) /
+                            Double.valueOf(nodeMetrics.get(CPU_NUM))) * numCpus));
+            double weightedLoadFive = loadFiveWeight * Math.min(numCpus,
+                    ((Double.valueOf(nodeMetrics.get(LOAD_FIVE)) /
+                            Double.valueOf(nodeMetrics.get(CPU_NUM)))* numCpus));
+            double weightedLoadFifteen = loadFifteenWeight * Math.min(numCpus,
+                    ((Double.valueOf(nodeMetrics.get(LOAD_FIFTEEN)) /
+                            Double.valueOf(nodeMetrics.get(CPU_NUM)))* numCpus));
+
+            double weightedLoadAverage = (weightedLoadOne + weightedLoadFive + weightedLoadFifteen) /
+                    (loadOneWeight + loadFiveWeight + loadFifteenWeight);
+            
+            System.out.println("Weighted load one: ["+weightedLoadOne+"]: weighted load five: ["+weightedLoadFive+"] weighted load fifteen: ["+weightedLoadFifteen+"]");
+            return Double.valueOf(numberFormat.format(weightedLoadAverage));
+        }
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/loadcalc/WeightedAverageLoadCalcFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/loadcalc/WeightedAverageLoadCalcFactory.java
new file mode 100644
index 0000000..051382c
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/ganglia/loadcalc/WeightedAverageLoadCalcFactory.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor.ganglia.loadcalc;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author rajith
+ * @version $Revision$
+ */
+public class WeightedAverageLoadCalcFactory implements LoadCalculatorFactory {
+
+    private static final Logger LOG = Logger.getLogger(WeightedAverageLoadCalcFactory.class.getName());
+
+    /**
+     *
+     * {@inheritDoc}
+     */
+    @Override
+    public LoadCalculator createLoadCalculator() {
+        try {
+            int loadOneWeight = Integer.parseInt(
+                    System.getProperty("org.apache.oodt.cas.resource.monitor.loadcalc.weight.loadone"));
+            int loadFiveWeight = Integer.parseInt(
+                    System.getProperty("org.apache.oodt.cas.resource.monitor.loadcalc.weight.loadfive"));
+            int loadFifteenWeight = Integer.parseInt(
+                    System.getProperty("org.apache.oodt.cas.resource.monitor.loadcalc.weight.loadfifteen"));
+            return new WeightedAverageLoadCalc(loadOneWeight, loadFiveWeight, loadFifteenWeight);
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, "Failed to create Load Calculator : " + e.getMessage(), e);
+            return null;
+        }
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/utils/MockGmetad.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/utils/MockGmetad.java
new file mode 100644
index 0000000..8c655e1
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/monitor/utils/MockGmetad.java
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor.utils;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+/**
+ * @author rajith
+ * @author mattmann
+ * @version $Revision$
+ *
+ * Ganglia meta daemon mock server
+ */
+public class MockGmetad implements Runnable {
+
+    private int socket;
+    private File fakeXMLDump;
+    private boolean testFinished;
+
+    public MockGmetad(int socket, String filePath){
+        this.socket = socket;
+        this.fakeXMLDump = new File(filePath);
+        this.testFinished = false;
+    }
+
+    public void stop(){
+        testFinished = true;
+    }
+
+    @Override
+    public void run() {
+        try {
+            ServerSocket serverSocket = new ServerSocket(socket);
+            FileInputStream fis = null;
+            OutputStream os = null;
+
+
+            while (!testFinished) {
+                Socket sock = serverSocket.accept();
+                try {
+                    byte[] xmlByteArray = new byte[1024];
+                    fis = new FileInputStream(fakeXMLDump);
+                    os = sock.getOutputStream();
+
+                    int count;
+                    while ((count = fis.read(xmlByteArray)) >= 0) {
+                        os.write(xmlByteArray, 0, count);
+                    }
+                    os.flush();
+                } finally {
+                    assert fis != null;
+                    fis.close();
+                    assert os != null;
+                    os.close();
+                    sock.close();
+                }
+            }
+        } catch (FileNotFoundException ignored) {
+            //Exception ignored
+        } catch (IOException ignored) {
+            //Exception ignored
+        }
+
+    }
+    
+    public static void main(String [] args) throws Exception{
+    	String xmlPath = null;
+    	int serverPort = -1;
+    	final String usage = "java MockGmetad <xml path> <port>\n";
+    	
+    	if (args.length != 2){
+    		System.err.println(usage);
+    		System.exit(1);
+    	}
+    	
+    	xmlPath = args[0];
+    	serverPort = Integer.valueOf(args[1]);
+    	
+    	MockGmetad gmetad = new MockGmetad(serverPort, xmlPath);
+    	ThreadLocal<MockGmetad> mockGmetad = new ThreadLocal<MockGmetad>();
+    	mockGmetad.set(gmetad);
+    	Thread mockGmetadServer = new Thread(mockGmetad.get());
+        mockGmetadServer.start();
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/BackendManager.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/BackendManager.java
new file mode 100644
index 0000000..8b7d296
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/BackendManager.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.mux;
+
+import java.util.List;
+
+import org.apache.oodt.cas.resource.batchmgr.Batchmgr;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.scheduler.Scheduler;
+import org.apache.oodt.cas.resource.structs.exceptions.QueueManagerException;
+
+/**
+ * Interface for the backend manager
+ *
+ * @author starchmd
+ */
+public interface BackendManager {
+
+    /**
+     * Add in a backend set to this manager.
+     * @param queue - queue that maps to the given monitor, batchmgr, and scheduler
+     * @param monitor - monitor used for this set
+     * @param batchmgr - batch manager for this set
+     * @param scheduler - scheduler for this set
+     */
+    public void addSet(String queue,Monitor monitor, Batchmgr batchmgr, Scheduler scheduler);
+    /**
+     * Return monitor for the given queue.
+     * @param queue - queue to check
+     * @return montior
+     * @throws QueueManagerException when queue does not exist
+     */
+    public Monitor getMonitor(String queue) throws QueueManagerException;
+    /**
+     * Return batch manager for the given queue.
+     * @param queue - queue to check
+     * @return batchmgr
+     * @throws QueueManagerException when queue does not exist
+     */
+    public Batchmgr getBatchmgr(String queue) throws QueueManagerException;
+    /**
+     * Return scheduler for the given queue.
+     * @param queue - queue to check
+     * @return scheduler
+     * @throws QueueManagerException when queue does not exist
+     */
+    public Scheduler getScheduler(String queue) throws QueueManagerException;
+    /**
+     * Return a list of all monitors.
+     * @return list of all monitors
+     */
+    public List<Monitor> getMonitors();
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/BackendRepository.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/BackendRepository.java
new file mode 100644
index 0000000..d759713
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/BackendRepository.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.mux;
+
+import org.apache.oodt.cas.resource.structs.exceptions.RepositoryException;
+
+/**
+ * Interface to handle loading of the configuration for which queues are associated 
+ * with which backend. i.e. read BackendManager configuration.
+ *
+ * @author starchmd
+ */
+public interface BackendRepository {
+    /**
+     * Load the backend.
+     * @return BackendManager all set up and ready to go.
+     */
+    public BackendManager load() throws RepositoryException;
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/BackendRepositoryFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/BackendRepositoryFactory.java
new file mode 100644
index 0000000..6850683
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/BackendRepositoryFactory.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.mux;
+
+/**
+ *
+ * @author starchmd
+ * @version $Revision$
+ *
+ * <p>
+ * The Backend Manager Repository Factory interface.
+ * </p>
+ */
+public interface BackendRepositoryFactory {
+
+    /**
+     * Create a backend repository
+     * @return the newly minted backend repository
+     */
+	public BackendRepository createBackendRepository();
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/QueueMuxBatchManager.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/QueueMuxBatchManager.java
new file mode 100644
index 0000000..aca1b94
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/QueueMuxBatchManager.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.mux;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.resource.batchmgr.Batchmgr;
+import org.apache.oodt.cas.resource.jobrepo.JobRepository;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+import org.apache.oodt.cas.resource.structs.exceptions.QueueManagerException;
+
+/**
+ * @author starchmd
+ * @version $Revision$
+ *
+ * A batch-manager used to execute and control jobs in a mesos-cluster.
+ */
+public class QueueMuxBatchManager implements Batchmgr {
+
+    private Logger LOG = Logger.getLogger(QueueMuxBatchManager.class.getName());
+
+    BackendManager backend;
+    Map<String,String> jobIdToQueue = new HashMap<String,String>();
+    JobRepository repo;
+
+    /**
+     * ctor
+     * @param bm - backend manager
+     */
+    public QueueMuxBatchManager(BackendManager bm) {
+        setBackendManager(bm);
+    }
+    /**
+     * Set the backend manager.
+     * @param backend - backend manager effectively mapping queue's to sets of backends.
+     */
+    public void setBackendManager(BackendManager backend) {
+        this.backend = backend;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#executeRemotely(org.apache.oodt.cas.resource.structs.JobSpec, org.apache.oodt.cas.resource.structs.ResourceNode)
+     */
+    @Override
+    public boolean executeRemotely(JobSpec job, ResourceNode resNode)
+            throws JobExecutionException {
+        try {
+            jobIdToQueue.put(job.getJob().getId(),job.getJob().getQueueName());
+            return getManagerByQueue(job.getJob().getQueueName()).executeRemotely(job, resNode);
+        } catch (QueueManagerException e) {
+            jobIdToQueue.remove(job.getJob().getQueueName());
+            LOG.log(Level.WARNING, "Exception recieved while executing job: "+e.getLocalizedMessage()+". Job will not execute.");
+            throw new JobExecutionException(e);
+        }
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#setMonitor(org.apache.oodt.cas.resource.monitor.Monitor)
+     */
+    @Override
+    public void setMonitor(Monitor monitor) {
+        throw new UnsupportedOperationException("Cannot set the monitor when using the queue-mux batch manager.");
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#setJobRepository(org.apache.oodt.cas.resource.jobrepo.JobRepository)
+     */
+    @Override
+    public void setJobRepository(JobRepository repository) {
+        this.repo = repository;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#killJob(java.lang.String, org.apache.oodt.cas.resource.structs.ResourceNode)
+     */
+    @Override
+    public boolean killJob(String jobId, ResourceNode node) {
+        try {
+            return getManagerByJob(jobId).killJob(jobId,node);
+        } catch (QueueManagerException e) {
+            LOG.log(Level.SEVERE, "Cannot kill job: "+e.getLocalizedMessage());
+        }
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.batchmgr.Batchmgr#getExecutionNode(java.lang.String)
+     */
+    @Override
+    public String getExecutionNode(String jobId) {
+        try {
+            return getManagerByJob(jobId).getExecutionNode(jobId);
+        } catch (QueueManagerException e) {
+            LOG.log(Level.SEVERE, "Cannot get exectuion node for job: "+e.getLocalizedMessage());
+        }
+        return null;
+    }
+
+    private Batchmgr getManagerByJob(String jobId) throws QueueManagerException {
+        return getManagerByQueue(jobIdToQueue.get(jobId));
+    }
+
+    private Batchmgr getManagerByQueue(String queue) throws QueueManagerException {
+        return this.backend.getBatchmgr(queue);
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/QueueMuxMonitor.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/QueueMuxMonitor.java
new file mode 100644
index 0000000..4063b20
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/QueueMuxMonitor.java
@@ -0,0 +1,207 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.mux;
+
+import java.net.URL;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.scheduler.QueueManager;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+import org.apache.oodt.cas.resource.structs.exceptions.QueueManagerException;
+
+/**
+ * @author starchmd
+ * @version $Revision$
+ *
+ * A monitor to monitor the multiple monitors.
+ */
+public class QueueMuxMonitor implements Monitor {
+    private static final Logger LOG = Logger.getLogger(QueueMuxMonitor.class.getName());
+    private BackendManager backend;
+    private QueueManager qManager;
+    /**
+     * ctor
+     * @param backend - backend manager
+     * @param qManager - queue manager
+     */
+    public QueueMuxMonitor(BackendManager backend, QueueManager qManager) {
+        setBackendManager(backend,qManager);
+    }
+    /**
+     * Set the backend manager.
+     * @param backend - backend manager effectively mapping queue's to sets of backends.
+     */
+    public void setBackendManager(BackendManager backend, QueueManager qManager) {
+        this.backend = backend;
+        this.qManager = qManager;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#getLoad(org.apache.oodt.cas.resource.structs.ResourceNode)
+     */
+    @Override
+    public int getLoad(ResourceNode node) throws MonitorException {
+        //Unclear what to do here.
+        //Assuming we should never be more than "Max"
+        List<String> queues = queuesForNode(node);
+        int max = 0;
+        for (String queue : queues) {
+            try {
+                max = Math.max(max,backend.getMonitor(queue).getLoad(node));
+            } catch (QueueManagerException e) {
+                LOG.log(Level.WARNING,"Queue '"+queue+"' has dissappeared.");
+            }
+        }
+        return max;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#getNodes()
+     */
+    @Override
+    public List<ResourceNode> getNodes() throws MonitorException {
+        Set<ResourceNode> set = new LinkedHashSet<ResourceNode>();
+        for (Monitor mon:this.backend.getMonitors()) {
+            for (Object res:mon.getNodes()) {
+                set.add((ResourceNode)res);
+            }
+        }
+        return new LinkedList<ResourceNode>(set);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#getNodeById(java.lang.String)
+     */
+    @Override
+    public ResourceNode getNodeById(String nodeId) throws MonitorException {
+        ResourceNode node = null;
+        Iterator<Monitor> imon = this.backend.getMonitors().iterator();
+        while(imon.hasNext() && (node = imon.next().getNodeById(nodeId)) == null) {} 
+        return node;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#getNodeByURL(java.net.URL)
+     */
+    @Override
+    public ResourceNode getNodeByURL(URL ipAddr) throws MonitorException {
+        ResourceNode node = null;
+        Iterator<Monitor> imon = this.backend.getMonitors().iterator();
+        while(imon.hasNext() && (node = imon.next().getNodeByURL(ipAddr)) == null) {} 
+        return node;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#reduceLoad(org.apache.oodt.cas.resource.structs.ResourceNode, int)
+     */
+    @Override
+    public boolean reduceLoad(ResourceNode node, int loadValue)
+            throws MonitorException {
+        List<String> queues = queuesForNode(node);
+        boolean ret = true;
+        for (String queue:queues) {
+            try {
+                ret &= backend.getMonitor(queue).reduceLoad(node, loadValue);
+            } catch (QueueManagerException e) {
+                LOG.log(Level.SEVERE,"Queue '"+queue+"' has dissappeared.");
+                throw new MonitorException(e);
+            }
+        }
+        return ret;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#assignLoad(org.apache.oodt.cas.resource.structs.ResourceNode, int)
+     */
+    @Override
+    public boolean assignLoad(ResourceNode node, int loadValue)
+            throws MonitorException {
+        List<String> queues = queuesForNode(node);
+        boolean ret = true;
+        for (String queue:queues) {
+            try {
+                ret &= backend.getMonitor(queue).assignLoad(node, loadValue);
+            } catch (QueueManagerException e) {
+                LOG.log(Level.SEVERE,"Queue '"+queue+"' has dissappeared.");
+                throw new MonitorException(e);
+            }
+        }
+        return ret;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#addNode(org.apache.oodt.cas.resource.structs.ResourceNode)
+     */
+    @Override
+    public void addNode(ResourceNode node) throws MonitorException {
+        List<String> queues = queuesForNode(node);
+        for (String queue:queues) {
+            try {
+                backend.getMonitor(queue).addNode(node);
+            } catch (QueueManagerException e) {
+                LOG.log(Level.SEVERE,"Queue '"+queue+"' has dissappeared.");
+                throw new MonitorException(e);
+            }
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.monitor.Monitor#removeNodeById(java.lang.String)
+     */
+    @Override
+    public void removeNodeById(String nodeId) throws MonitorException {
+        for (Monitor mon:this.backend.getMonitors()) {
+            mon.removeNodeById(nodeId);
+        }
+    }
+    /**
+     * Gets the queues that are associated with a particular node.
+     * @param node - node which queues are needed for
+     * @return list of queue names on that node
+     */
+    private List<String> queuesForNode(ResourceNode node) {
+        List<String> ret = new LinkedList<String>();
+        //Get list of queues
+        List<String> queues = null;
+        try
+        {
+            queues = qManager.getQueues();
+        } catch (QueueManagerException e) {
+            LOG.log(Level.SEVERE, "Cannot list queues.");
+        }
+        //Search each queu to see if it contains given node
+        for (String queue : queues) {
+            try
+            {
+                if (qManager.getNodes(queue).contains(node.getNodeId())) {
+                    ret.add(queue);
+                }
+            } catch(QueueManagerException e) {
+                LOG.log(Level.SEVERE, "Queue '"+queue+"' has dissappeared.");
+            }
+        }
+        return ret;
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/QueueMuxScheduler.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/QueueMuxScheduler.java
new file mode 100644
index 0000000..951a7ae
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/QueueMuxScheduler.java
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.mux;
+
+//JDKimports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+
+
+
+
+//OODT imports
+import org.apache.oodt.cas.resource.jobqueue.JobQueue;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.batchmgr.Batchmgr;
+import org.apache.oodt.cas.resource.scheduler.QueueManager;
+import org.apache.oodt.cas.resource.scheduler.Scheduler;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.JobQueueException;
+import org.apache.oodt.cas.resource.structs.exceptions.QueueManagerException;
+import org.apache.oodt.cas.resource.structs.exceptions.SchedulerException;
+
+/**
+ * This scheduler multiplexes between multiple schedulers based on the "queue" .
+ *
+ * @author starchmd
+ * @version $Revision$
+ */
+public class QueueMuxScheduler implements Scheduler {
+
+    private static final Logger LOG = Logger.getLogger(QueueMuxScheduler.class.getName());
+
+    private BackendManager backend;
+    private JobQueue queue;
+    private float waitTime = -1;
+
+    //Manages other queue-muxing components
+    private QueueMuxBatchManager batch;
+    private QueueMuxMonitor mon;
+    private QueueManager qManager;
+
+    /**
+     * ctor
+     * @param backend - Backend manager to handle the many different backends.
+     */
+    public QueueMuxScheduler(BackendManager backend, QueueManager qm, JobQueue jq) {
+        String waitStr = System.getProperty("org.apache.oodt.cas.resource.scheduler.wait.seconds", "20");
+        waitTime = Float.parseFloat(waitStr);
+        this.queue = jq;
+        this.qManager = qm;
+        this.backend = backend;
+        //Required, so make them here
+        batch = new QueueMuxBatchManager(backend);
+        mon = new QueueMuxMonitor(backend,qm);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Runnable#run()
+     */
+    public void run() {
+        //Loop forever
+        while (true) {
+            try {
+                Thread.sleep((long) (waitTime * 1000.0));
+            } catch (InterruptedException e) {
+                //If the thread will continue, reinterrupt thread
+                Thread.currentThread().interrupt();
+            }
+            //You have jobs
+            if (!queue.isEmpty()) {
+                JobSpec job = null;
+                try {
+                    job = queue.getNextJob();
+                    LOG.log(Level.INFO, "Scheduling job: ["+ job.getJob().getId()+ "] for execution");
+                    schedule(job);
+                } catch (JobQueueException je) {
+                    LOG.log(Level.WARNING,"Error getting job from queue: "
+                                    + je.getLocalizedMessage());
+                } catch (SchedulerException se) {
+                    LOG.log(Level.WARNING,"Error occured scheduling job: "+se.getLocalizedMessage());
+                    try {
+                        queue.requeueJob(job);
+                    } catch (JobQueueException je) {
+                        LOG.log(Level.WARNING,"Error requeueing job: "+je.getLocalizedMessage());
+                        LOG.log(Level.WARNING,"Previous error caused by: "+se.getLocalizedMessage());
+                    }
+                }
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see gov.nasa.jpl.oodt.cas.resource.scheduler.Scheduler#schedule(gov.nasa.jpl.oodt.cas.resource.structs.JobSpec)
+     */
+    public synchronized boolean schedule(JobSpec spec)
+            throws SchedulerException {
+        System.out.println("Spec: "+spec+" Job: "+spec.getJob()+" Backend:"+backend);
+        String queue = spec.getJob().getQueueName();
+        try {
+            return backend.getScheduler(queue).schedule(spec);
+        } catch (QueueManagerException e) {
+            LOG.log(Level.WARNING,"Exception occuered: "+e.getLocalizedMessage());
+            throw new SchedulerException(e);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see gov.nasa.jpl.oodt.cas.resource.scheduler.Scheduler#getBatchmgr()
+     */
+    public Batchmgr getBatchmgr() {
+        return batch;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see gov.nasa.jpl.oodt.cas.resource.scheduler.Scheduler#getMonitor()
+     */
+    public Monitor getMonitor() {
+        return mon;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see gov.nasa.jpl.oodt.cas.resource.scheduler.Scheduler#getJobQueue()
+     */
+    public JobQueue getJobQueue() {
+        return this.queue;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see gov.nasa.jpl.oodt.cas.resource.scheduler.Scheduler#getQueueManager()
+     */
+    public QueueManager getQueueManager() {
+        return qManager;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see gov.nasa.jpl.oodt.cas.resource.scheduler.Scheduler#nodeAvailable(gov.nasa.jpl.oodt.cas.resource.structs.JobSpec)
+     */
+    public synchronized ResourceNode nodeAvailable(JobSpec spec)
+            throws SchedulerException {
+        String queue = spec.getJob().getQueueName();
+        try {
+            return backend.getScheduler(queue).nodeAvailable(spec);
+        } catch (QueueManagerException e) {
+            LOG.log(Level.WARNING,"Exception occuered: "+e.getLocalizedMessage());
+            throw new SchedulerException(e);
+        }
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/QueueMuxSchedulerFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/QueueMuxSchedulerFactory.java
new file mode 100644
index 0000000..018d516
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/QueueMuxSchedulerFactory.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.mux;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.resource.jobqueue.JobQueue;
+import org.apache.oodt.cas.resource.jobqueue.JobStackJobQueueFactory;
+import org.apache.oodt.cas.resource.queuerepo.XmlQueueRepositoryFactory;
+import org.apache.oodt.cas.resource.scheduler.QueueManager;
+import org.apache.oodt.cas.resource.scheduler.Scheduler;
+import org.apache.oodt.cas.resource.scheduler.SchedulerFactory;
+import org.apache.oodt.cas.resource.structs.exceptions.RepositoryException;
+import org.apache.oodt.cas.resource.util.GenericResourceManagerObjectFactory;
+
+/**
+ * This class acts as a factory for the whole queue-mux
+ * set of classes.
+ *
+ * @author starchmd
+ */
+public class QueueMuxSchedulerFactory implements SchedulerFactory {
+
+    private static final Logger LOG = Logger.getLogger(QueueMuxSchedulerFactory.class.getName());
+
+    BackendManager backend;
+    QueueManager qManager;
+    JobQueue jobQueue;
+    /**
+     * ctor
+     */
+    public QueueMuxSchedulerFactory() {
+        //Load backend manager
+        String  backRepo = System.getProperty("resource.backend.mux.repository",
+                XmlBackendRepository.class.getCanonicalName());
+        try {
+            backend = GenericResourceManagerObjectFactory.getBackendRepositoryFromFactory(backRepo).load();
+        } catch (RepositoryException e) {
+            LOG.log(Level.SEVERE,"Error loading backend repository: "+e.getMessage(),e);
+            backend = null;
+        }
+        //Load user-specified queue factory
+        String qFact = System.getProperty("org.apache.oodt.cas.resource.queues.repo.factory",
+                XmlQueueRepositoryFactory.class.getCanonicalName());
+        qManager = GenericResourceManagerObjectFactory.getQueueRepositoryFromFactory(
+                qFact).loadQueues();
+        //Load job queue
+        String jobFact = System.getProperty("resource.jobqueue.factory",
+                        JobStackJobQueueFactory.class.getCanonicalName());
+        jobQueue = GenericResourceManagerObjectFactory
+                .getJobQueueServiceFromFactory(jobFact);
+    }
+
+    @Override
+    public Scheduler createScheduler() {
+        return new QueueMuxScheduler(this.backend, this.qManager, this.jobQueue);
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/StandardBackendManager.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/StandardBackendManager.java
new file mode 100644
index 0000000..1ccdb17
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/StandardBackendManager.java
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.mux;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.oodt.cas.resource.batchmgr.Batchmgr;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.scheduler.Scheduler;
+import org.apache.oodt.cas.resource.structs.exceptions.QueueManagerException;
+
+/**
+ * This manager keeps track of the mux-able backends for the resource manager.
+ * It effectively maps a queue to the backend that this queue feeds.
+ *
+ * It uses a private BackendSet to keep track of everything.
+ *
+ * For reference, a backend is a set of the following:
+ *    1. Batch manger, responsible for running jobs
+ *    2. Scheduler, responsible for scheduling a job to run
+ *    3. Monitor, responsible for managing nodes
+ *
+ * @author starchmd
+ */
+public class StandardBackendManager implements BackendManager {
+    Map<String,BackendSet> queueToBackend = new HashMap<String,BackendSet>();
+
+    /**
+     * Add in a backend set to this manager.
+     * @param queue - queue that maps to the given monitor, batchmgr, and scheduler
+     * @param monitor - monitor used for this set
+     * @param batchmgr - batch manager for this set
+     * @param scheduler - scheduler for this set
+     */
+    public void addSet(String queue,Monitor monitor, Batchmgr batchmgr, Scheduler scheduler) {
+        queueToBackend.put(queue, new BackendSet(monitor,batchmgr,scheduler));
+    }
+    /**
+     * Return monitor for the given queue.
+     * @param queue - queue to check
+     * @return montior
+     * @throws QueueManagerException when queue does not exist
+     */
+    public Monitor getMonitor(String queue) throws QueueManagerException {
+        BackendSet set = queueToBackend.get(queue);
+        if (set == null)
+            throw new QueueManagerException("Queue '" + queue + "' does not exist");
+        return set.monitor;
+    }
+    /**
+     * Return batch manager for the given queue.
+     * @param queue - queue to check
+     * @return batchmgr
+     * @throws QueueManagerException when queue does not exist
+     */
+    public Batchmgr getBatchmgr(String queue) throws QueueManagerException {
+        BackendSet set = queueToBackend.get(queue);
+        if (set == null)
+            throw new QueueManagerException("Queue '" + queue + "' does not exist");
+        return set.batchmgr;
+    }
+    /**
+     * Return scheduler for the given queue.
+     * @param queue - queue to check
+     * @return scheduler
+     * @throws QueueManagerException when queue does not exist
+     */
+    public Scheduler getScheduler(String queue) throws QueueManagerException {
+        BackendSet set = queueToBackend.get(queue);
+        if (set == null)
+            throw new QueueManagerException("Queue '" + queue + "' does not exist");
+        return set.scheduler;
+    }
+    /**
+     * Return a list of all monitors.
+     * @return list of all monitors
+     */
+    public List<Monitor> getMonitors() {
+        List<Monitor> monitors = new LinkedList<Monitor>();
+        for (BackendSet set : queueToBackend.values()) {
+            monitors.add(set.monitor);
+        }
+        return monitors;
+    }
+    /**
+     * Class that holds a set of the three backend pieces.
+     * Private class, because no accessor/modifiers have been
+     * created(public members). Acts like a struct.
+     *
+     * @author starchmd
+     */
+    private class BackendSet {
+        public Monitor monitor = null;
+        public Batchmgr batchmgr = null;
+        public Scheduler scheduler = null;
+
+        public BackendSet(Monitor monitor, Batchmgr batchmgr, Scheduler scheduler) {
+            this.monitor = monitor;
+            this.batchmgr = batchmgr;
+            this.scheduler = scheduler;
+        }
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/XmlBackendRepository.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/XmlBackendRepository.java
new file mode 100644
index 0000000..32ca801
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/XmlBackendRepository.java
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.mux;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.resource.scheduler.Scheduler;
+import org.apache.oodt.cas.resource.structs.exceptions.RepositoryException;
+import org.apache.oodt.cas.resource.util.GenericResourceManagerObjectFactory;
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * Class to load BackendManager from XML file.
+ * @author starchmd
+ */
+public class XmlBackendRepository implements BackendRepository {
+
+    private static final Logger LOG = Logger.getLogger(XmlBackendRepository.class.getName());
+    private String uri;
+
+    //Constants
+    private static final String SCHEDULER = "scheduler";
+    private static final String BATCHMGR = "batchmgr";
+    private static final String MONITOR = "monitor";
+
+    private static final String MONITOR_PROPERTY = "resource.monitor.factory";
+    private static final String BATCHMGR_PROPERTY = "resource.batchmgr.factory";
+
+    /**
+     * Ctor
+     * @param uri - uri of XML file containing mapping
+     */
+    public XmlBackendRepository(String uri) {
+        if (uri == null)
+            throw new NullPointerException("URI for queue-to-backend xml file cannot be null");
+        this.uri = uri;
+    }
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.mux.BackendRepository#load()
+     */
+    @Override
+    public BackendManager load() throws RepositoryException {
+        LOG.log(Level.INFO,"Reading backend set manager from: "+this.uri);
+        BackendManager bm = new StandardBackendManager();
+        String origMon = System.getProperty(MONITOR_PROPERTY);
+        String origBat = System.getProperty(BATCHMGR_PROPERTY);
+        try {
+            File file = new File(new URI(this.uri));
+            Document root = XMLUtils.getDocumentRoot(new FileInputStream(file));
+            NodeList list = root.getElementsByTagName("queue");
+            if (list != null && list.getLength() > 0) {
+                for (int k = 0; k < list.getLength(); k++) {
+                    Element node = (Element)list.item(k);
+                    String queue = node.getAttribute("name");
+                    //Set properties for batch and monitor factories
+                    //So scheduler builds as repository specifies
+                    try {
+                        String mfact = getMonitor(queue,node);
+                        LOG.log(Level.INFO,"Setting monitor factory property to: "+mfact);
+                        System.setProperty(MONITOR_PROPERTY, mfact);
+                    } catch (RepositoryException e) {
+                        LOG.log(Level.INFO, "No monitor factory for queue "+queue+", using system property.");
+                    }
+                    try {
+                        String bfact = getBatchmgr(queue,node);
+                        LOG.log(Level.INFO,"Setting batchmgr factory property to: "+bfact);
+                        System.setProperty(BATCHMGR_PROPERTY, bfact);
+                    } catch (RepositoryException e) {
+                        LOG.log(Level.INFO, "No batchmgr factory for queue "+queue+", using system property.");
+                    }
+                    //Build scheduler
+                    Scheduler sch = getScheduler(queue,node);
+                    bm.addSet(queue, sch.getMonitor(), sch.getBatchmgr(), sch);
+                    //Reset Properties for next item
+                    resetAlteredProperty(MONITOR_PROPERTY,origMon);
+                    resetAlteredProperty(BATCHMGR_PROPERTY,origBat);
+                }
+            }
+        } catch (URISyntaxException e) {
+            LOG.log(Level.SEVERE,"Malformed URI: "+this.uri);
+            throw new RepositoryException(e);
+        } catch(FileNotFoundException e) {
+            LOG.log(Level.SEVERE,"File not found: "+this.uri+" from working dir: "+new File(".").getAbsolutePath());
+            throw new RepositoryException(e);
+        } catch (ClassCastException e) {
+            LOG.log(Level.SEVERE,"Queue tag must represent XML element.");
+            throw new RepositoryException(e);
+        } finally {
+            resetAlteredProperty(MONITOR_PROPERTY,origMon);
+            resetAlteredProperty(BATCHMGR_PROPERTY,origBat);
+        }
+
+        return bm;
+    }
+    /**
+     * Resets a property. Allows nulls
+     * @param prop - property name to reset
+     * @param value - value to reset to, can be null
+     */
+    private static void resetAlteredProperty(String prop,String value) {
+        if (value == null) {
+            System.clearProperty(prop);
+            return;
+        }
+        System.setProperty(prop,value);
+    }
+
+    /**
+     * Get monitor factory from XML
+     * @param queue - current queue, for error reporting
+     * @param node - node that is being read
+     * @return monitor factory string
+     * @throws RepositoryException
+     */
+    private static String getMonitor(String queue,Element node) throws RepositoryException {
+        return getFactoryAttribute(queue, node, MONITOR);
+    }
+    /**
+     * Get scheduler from XML
+     * @param queue - current queue, for error reporting
+     * @param node - node that is being read
+     * @return newly constructed Scheduler
+     * @throws RepositoryException
+     */
+    private static Scheduler getScheduler(String queue,Element node) throws RepositoryException {
+        String factory = getFactoryAttribute(queue, node, SCHEDULER);
+        LOG.log(Level.INFO,"Loading monitor from: "+factory);
+        Scheduler sch = GenericResourceManagerObjectFactory.getSchedulerServiceFromFactory(factory);
+        if (sch != null)
+            return sch;
+        throw new RepositoryException("Could instantiate from: "+factory);
+    }
+    /**
+     * Get batchmgr factory from XML
+     * @param queue - current queue, for error reporting
+     * @param node - node that is being read
+     * @return batch manager factory name
+     * @throws RepositoryException
+     */
+    private static String getBatchmgr(String queue,Element node) throws RepositoryException {
+        return getFactoryAttribute(queue, node, BATCHMGR);
+    }
+    /**
+     * Pull out the factory attribute from tag with given name.
+     * @param queue - current queue, for error reporting
+     * @param elem - element that contains tags as children
+     * @param tag - string name of tag looked for. i.e. "monitor"
+     * @return name of factory class
+     * @throws RepositoryException - thrown if more than one child matches, no children match, or other error
+     */
+    private static String getFactoryAttribute(String queue,Element elem, String tag) throws RepositoryException {
+        NodeList children = elem.getElementsByTagName(tag);
+        try {
+            String attr = "";
+            if (children.getLength() != 1 || (attr = ((Element)children.item(0)).getAttribute("factory")) == "") {
+                throw new RepositoryException("Could not find exactly one "+tag+", with factory set, in queue: "+queue);
+            }
+            return attr;
+        } catch (ClassCastException e) {
+            throw new RepositoryException("Tag "+tag+" does not represent XML element in queue: "+queue,e);
+        }
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/XmlBackendRepositoryFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/XmlBackendRepositoryFactory.java
new file mode 100644
index 0000000..64f7856
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/mux/XmlBackendRepositoryFactory.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.mux;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author starchmd
+ * @version $Revision$
+ *
+ * <p>
+ * The XML Backend Repository Factory interface.
+ * </p>
+ */
+public class XmlBackendRepositoryFactory implements BackendRepositoryFactory {
+
+	private static final Logger LOG = Logger.getLogger(XmlBackendRepositoryFactory.class.getName());
+	/**
+	 * Create the backend repository (xml)
+	 * @return the newly minted backend repository
+	 */
+	public XmlBackendRepository createBackendRepository() {
+		try {
+			String uri = System.getProperty("resource.backend.mux.xmlrepository.queuetobackend");
+			/* do env var replacement */
+			uri = PathUtils.replaceEnvVariables(uri);
+			return new XmlBackendRepository(uri);
+		} catch (NullPointerException e) {
+			LOG.log(	Level.SEVERE,"Failed to create XmlBackendRepository: "+ e.getMessage(), e);
+			return null;
+		}
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/noderepo/NodeRepository.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/noderepo/NodeRepository.java
new file mode 100644
index 0000000..0b4319e
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/noderepo/NodeRepository.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.noderepo;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+
+//JDK imports
+import java.util.List;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The Node Repository interface.
+ * </p>
+ */
+public interface NodeRepository {
+
+	public List<ResourceNode> loadNodes();
+	
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/noderepo/NodeRepositoryFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/noderepo/NodeRepositoryFactory.java
new file mode 100644
index 0000000..e81bf81
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/noderepo/NodeRepositoryFactory.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.noderepo;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The Node Repository Factory interface.
+ * </p>
+ */
+public interface NodeRepositoryFactory {
+
+	/**
+	 * Creates {@link NodeRepository}
+	 * @return the created {@link NodeRepository}
+	 */
+	public NodeRepository createNodeRepository();
+	
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/noderepo/XmlNodeRepository.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/noderepo/XmlNodeRepository.java
new file mode 100644
index 0000000..c40cbe5
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/noderepo/XmlNodeRepository.java
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.noderepo;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.util.XmlStructFactory;
+
+//JDK imports
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//DOM imports
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * 
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The XML Node Repository interface.
+ * </p>
+ */
+public class XmlNodeRepository implements NodeRepository {
+
+	private static final Logger LOG = Logger.getLogger(XmlNodeRepository.class
+			.getName());
+
+	private static FileFilter nodesXmlFilter = new FileFilter() {
+		public boolean accept(File pathname) {
+			return pathname.isFile()
+					&& pathname.toString().endsWith("nodes.xml");
+		}
+	};
+
+	private List<String> nodesHomeUris = null;
+
+	public XmlNodeRepository(List<String> uris) {
+		this.nodesHomeUris = uris;
+	}
+
+	public List<ResourceNode> loadNodes() {
+		Vector<ResourceNode> nodes = new Vector<ResourceNode>();
+		for (String dirUri : this.nodesHomeUris) {
+			try {
+				File nodesDir = new File(new URI(dirUri));
+				if (nodesDir.isDirectory()) {
+
+					String nodesDirStr = nodesDir.getAbsolutePath();
+
+					if (!nodesDirStr.endsWith("/")) {
+						nodesDirStr += "/";
+					}
+
+					// get all the workflow xml files
+					File[] nodesFiles = nodesDir.listFiles(nodesXmlFilter);
+
+					for (int j = 0; j < nodesFiles.length; j++) {
+
+						String nodesXmlFile = nodesFiles[j].getAbsolutePath();
+						Document nodesRoot = null;
+						try {
+							nodesRoot = XMLUtils
+									.getDocumentRoot(new FileInputStream(
+											nodesFiles[j]));
+						} catch (FileNotFoundException e) {
+							e.printStackTrace();
+							return null;
+						}
+
+						NodeList nodeList = nodesRoot
+								.getElementsByTagName("node");
+						if (nodeList != null)
+							for (int k = 0; k < nodeList.getLength(); k++)
+								nodes.add(XmlStructFactory
+										.getNodes((Element) nodeList.item(k)));
+					}
+				}
+			} catch (URISyntaxException e) {
+				LOG.log(Level.WARNING, "DirUri: " + dirUri
+						+ " is not a directory: skipping node loading for it.",
+						e);
+			}
+		}
+		return nodes;
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/noderepo/XmlNodeRepositoryFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/noderepo/XmlNodeRepositoryFactory.java
new file mode 100644
index 0000000..15bf3d2
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/noderepo/XmlNodeRepositoryFactory.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.noderepo;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//JDK imports
+import java.util.Arrays;
+
+/**
+ * 
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The XML Node Repository Factory interface.
+ * </p>
+ */
+public class XmlNodeRepositoryFactory implements NodeRepositoryFactory {
+
+	/*
+	 * (non-Javadoc)
+	 * @see gov.nasa.jpl.oodt.cas.resource.nodes.NodeRepositoryFactory#createNodeRepository()
+	 */
+	public XmlNodeRepository createNodeRepository() {
+		String nodesDirUris = System
+				.getProperty("org.apache.oodt.cas.resource.nodes.dirs");
+
+		if (nodesDirUris != null) {
+			/* do env var replacement */
+			nodesDirUris = PathUtils.replaceEnvVariables(nodesDirUris);
+			String[] dirUris = nodesDirUris.split(",");
+			return new XmlNodeRepository(Arrays.asList(dirUris));
+		}else {
+			return null;
+		}
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/queuerepo/QueueRepository.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/queuerepo/QueueRepository.java
new file mode 100644
index 0000000..39ef3c2
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/queuerepo/QueueRepository.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.queuerepo;
+
+//OODT imports
+import org.apache.oodt.cas.resource.scheduler.QueueManager;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The Queue Repository interface.
+ * </p>
+ */
+public interface QueueRepository {
+
+	public QueueManager loadQueues();
+			
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/queuerepo/QueueRepositoryFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/queuerepo/QueueRepositoryFactory.java
new file mode 100644
index 0000000..11720e3
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/queuerepo/QueueRepositoryFactory.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.queuerepo;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The Queue Repository Factory interface.
+ * </p>
+ */
+public interface QueueRepositoryFactory {
+
+	public QueueRepository createQueueRepository();
+	
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/queuerepo/XmlQueueRepository.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/queuerepo/XmlQueueRepository.java
new file mode 100644
index 0000000..a6ac289
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/queuerepo/XmlQueueRepository.java
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.queuerepo;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.cas.resource.scheduler.QueueManager;
+import org.apache.oodt.cas.resource.util.XmlStructFactory;
+
+//JDK imports
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//DOM imports
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * 
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The XML Queue Repository interface.
+ * </p>
+ */
+public class XmlQueueRepository implements QueueRepository {
+
+	private static FileFilter queuesXmlFilter = new FileFilter() {
+		public boolean accept(File pathname) {
+			return pathname.isFile()
+					&& pathname.toString()
+							.endsWith("node-to-queue-mapping.xml");
+		}
+	};
+
+	private static final Logger LOG = Logger.getLogger(XmlQueueRepository.class
+			.getName());
+
+	private List<String> dirUris;
+
+	public XmlQueueRepository(List<String> dirUris) {
+		this.dirUris = dirUris;
+	}
+
+	public QueueManager loadQueues() {
+
+		QueueManager queueManager = new QueueManager();
+
+		if (dirUris != null && dirUris.size() > 0) {
+			for (Iterator i = dirUris.iterator(); i.hasNext();) {
+				String dirUri = (String) i.next();
+
+				try {
+					File nodesDir = new File(new URI(dirUri));
+					if (nodesDir.isDirectory()) {
+
+						String nodesDirStr = nodesDir.getAbsolutePath();
+
+						if (!nodesDirStr.endsWith("/")) {
+							nodesDirStr += "/";
+						}
+
+						// get all the workflow xml files
+						File[] nodesFiles = nodesDir.listFiles(queuesXmlFilter);
+
+						for (int j = 0; j < nodesFiles.length; j++) {
+
+							String nodesXmlFile = nodesFiles[j]
+									.getAbsolutePath();
+							Document nodesRoot = null;
+							try {
+								nodesRoot = XMLUtils
+										.getDocumentRoot(new FileInputStream(
+												nodesFiles[j]));
+							} catch (FileNotFoundException e) {
+								e.printStackTrace();
+								return null;
+							}
+
+							NodeList nodeList = nodesRoot
+									.getElementsByTagName("node");
+
+							if (nodeList != null && nodeList.getLength() > 0) {
+								for (int k = 0; k < nodeList.getLength(); k++) {
+
+									String nodeId = ((Element) nodeList.item(k))
+											.getAttribute("id");
+									Vector assignments = (Vector) XmlStructFactory
+											.getQueueAssignment((Element) nodeList
+													.item(k));
+									for (int l = 0; l < assignments.size(); l++) {
+										try {
+											// make sure queue exists
+											queueManager
+													.addQueue((String) assignments
+															.get(l));
+											// add node to queue
+											queueManager
+													.addNodeToQueue(nodeId,
+															(String) assignments
+																	.get(l));
+										} catch (Exception e) {
+											LOG
+													.log(
+															Level.WARNING,
+															"Failed to add node '"
+																	+ nodeId
+																	+ "' to queue '"
+																	+ (String) assignments
+																			.get(l)
+																	+ "' : "
+																	+ e
+																			.getMessage(),
+															e);
+										}
+									}
+								}
+							}
+						}
+					}
+				} catch (URISyntaxException e) {
+					e.printStackTrace();
+					LOG
+							.log(
+									Level.WARNING,
+									"DirUri: "
+											+ dirUri
+											+ " is not a directory: skipping node loading for it.");
+				}
+			}
+
+		}
+		return queueManager;
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/queuerepo/XmlQueueRepositoryFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/queuerepo/XmlQueueRepositoryFactory.java
new file mode 100644
index 0000000..9446710
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/queuerepo/XmlQueueRepositoryFactory.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.queuerepo;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//JDK imports
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * 
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The XML Queue Repository Factory interface.
+ * </p>
+ */
+public class XmlQueueRepositoryFactory implements QueueRepositoryFactory {
+
+	private static final Logger LOG = Logger
+			.getLogger(XmlQueueRepositoryFactory.class.getName());
+
+	public XmlQueueRepository createQueueRepository() {
+		try {
+			String queuesDirUris = System
+					.getProperty("org.apache.oodt.cas.resource.nodetoqueues.dirs");
+
+			/* do env var replacement */
+			queuesDirUris = PathUtils.replaceEnvVariables(queuesDirUris);
+			String[] dirUris = queuesDirUris.split(",");
+			return new XmlQueueRepository(Arrays.asList(dirUris));
+		} catch (Exception e) {
+			LOG
+					.log(
+							Level.SEVERE,
+							"Failed to create XML Queue Repository (make sure you specify node-to-queue mapping java property 'org.apache.oodt.cas.resource.scheduler.nodetoqueues.dirs') : "
+									+ e.getMessage(), e);
+			return null;
+		}
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/LRUQueueManager.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/LRUQueueManager.java
new file mode 100644
index 0000000..09bbe52
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/LRUQueueManager.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.scheduler;
+
+//JDK imports
+import java.util.LinkedHashSet;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.exceptions.QueueManagerException;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The LRUs Queue to Node Mapping Manager
+ * </p>
+ */
+public class LRUQueueManager extends QueueManager {
+    
+	public LRUQueueManager(QueueManager queueManager) throws QueueManagerException {
+		for (String queue : queueManager.getQueues()) {
+			LinkedHashSet<String> nodes = new LinkedHashSet<String>();
+			nodes.addAll(queueManager.getNodes(queue));
+			this.queueToNodesMapping.put(queue, nodes);
+		}
+	}
+	
+    public synchronized void usedNode(String queueName, String nodeId) {
+    	Vector<String> nodes = new Vector<String>(this.queueToNodesMapping.get(queueName));
+		nodes.remove(nodeId);
+		nodes.add(nodeId);
+		LinkedHashSet<String> nodeSet = new LinkedHashSet<String>();
+		nodeSet.addAll(nodes);
+		this.queueToNodesMapping.put(queueName, nodeSet);
+    }
+    
+}
+
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/LRUScheduler.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/LRUScheduler.java
new file mode 100644
index 0000000..a2eafec
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/LRUScheduler.java
@@ -0,0 +1,252 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.scheduler;
+
+//JDKimports
+import java.lang.Integer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.resource.jobqueue.JobQueue;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.batchmgr.Batchmgr;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+import org.apache.oodt.cas.resource.structs.exceptions.SchedulerException;
+
+/**
+ * 
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * An implementation of a {@link Scheduler} that uses a <a
+ * href="http://en.wikipedia.org/wiki/Cache_algorithms">least-recently-used</a>
+ * algorithm for scheduling {@link Job}s.
+ * </p>
+ */
+public class LRUScheduler implements Scheduler {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(LRUScheduler.class
+            .getName());
+
+    private LRUQueueManager queueManager;
+    
+    /* the monitor we'll use to check the status of the resources */
+    private Monitor myMonitor;
+
+    /* the batch mgr we'll use to execute jobs */
+    private Batchmgr myBatchmgr;
+
+    /* our job queue */
+    private JobQueue myJobQueue;
+
+    /* our wait time between checking the queue */
+    private int waitTime = -1;
+
+    public LRUScheduler(Monitor m, Batchmgr b, JobQueue q, LRUQueueManager qm) {
+
+    	queueManager = qm;
+        myMonitor = m;
+        myBatchmgr = b;
+        myJobQueue = q;
+
+        String waitStr = System.getProperty(
+                "org.apache.oodt.cas.resource.scheduler.wait.seconds", "20");
+        waitTime = Integer.parseInt(waitStr);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Runnable#run()
+     */
+    public void run() {
+        for (;;) {
+
+            try {
+                Thread.currentThread().sleep((long) waitTime * 1000);
+            } catch (Exception ignore) {}
+
+            if (!myJobQueue.isEmpty()) {
+                JobSpec exec = null;
+
+                try {
+                    exec = myJobQueue.getNextJob();
+                    LOG.log(Level.INFO, "Obtained Job: ["
+                            + exec.getJob().getId()
+                            + "] from Queue: Scheduling for execution");
+                } catch (Exception e) {
+                    LOG.log(Level.WARNING,
+                            "Error getting next job from JobQueue: Message: "
+                                    + e.getMessage());
+                    continue;
+                }
+
+                try {
+                    schedule(exec);
+                } catch (Exception e) {
+                    LOG.log(Level.WARNING, "Error scheduling job: ["
+                            + exec.getJob().getId() + "]: Message: "
+                            + e.getMessage());
+                    // place the job spec back on the queue
+                    try {
+                        myJobQueue.requeueJob(exec);
+                    } catch (Exception ignore) {
+                    }
+                }
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see gov.nasa.jpl.oodt.cas.resource.scheduler.Scheduler#schedule(gov.nasa.jpl.oodt.cas.resource.structs.JobSpec)
+     */
+    public synchronized boolean schedule(JobSpec spec)
+            throws SchedulerException {
+        String queueName = spec.getJob().getQueueName();
+        int load = spec.getJob().getLoadValue().intValue();
+
+        ResourceNode node = nodeAvailable(spec);
+
+        if (node != null) {
+            try {
+                myMonitor.assignLoad(node, load);
+                queueManager.usedNode(queueName, node.getNodeId());
+                
+                // assign via batch system
+                LOG.log(Level.INFO, "Assigning job: ["
+                        + spec.getJob().getName() + "] to node: ["
+                        + node.getNodeId() + "]");
+                try {
+                    myBatchmgr.executeRemotely(spec, node);
+                } catch (JobExecutionException e) {
+                    LOG.log(Level.WARNING, "Exception executing job: ["
+                            + spec.getJob().getId() + "] to node: ["
+                            + node.getIpAddr() + "]: Message: "
+                            + e.getMessage());
+                    try {
+                        // queue the job back up
+                        LOG.log(Level.INFO, "Requeueing job: ["
+                                + spec.getJob().getId() + "]");
+                        myJobQueue.requeueJob(spec);
+
+                        // make sure to decrement the load
+                        myMonitor.reduceLoad(node, load);
+                    } catch (Exception ignore) {
+                    }
+                }
+            } catch (MonitorException e) {
+                LOG.log(Level.WARNING, "Exception assigning load to resource "
+                        + "node: [" + node.getNodeId() + "]: load: [" + load
+                        + "]: Message: " + e.getMessage());
+                throw new SchedulerException(e.getMessage());
+            }
+        } else {
+            // could not find resource, push onto JobQueue
+            try {
+                myJobQueue.requeueJob(spec);
+            } catch (Exception ignore) {
+            }
+        }
+        return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see gov.nasa.jpl.oodt.cas.resource.scheduler.Scheduler#getBatchmgr()
+     */
+    public Batchmgr getBatchmgr() {
+        return myBatchmgr;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see gov.nasa.jpl.oodt.cas.resource.scheduler.Scheduler#getMonitor()
+     */
+    public Monitor getMonitor() {
+        return myMonitor;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see gov.nasa.jpl.oodt.cas.resource.scheduler.Scheduler#getJobQueue()
+     */
+    public JobQueue getJobQueue() {
+        return myJobQueue;
+    }
+    
+    /*
+     * (non-Javadoc)
+     * 
+     * @see gov.nasa.jpl.oodt.cas.resource.scheduler.Scheduler#getQueueManager()
+     */
+    public QueueManager getQueueManager() {
+    	return this.queueManager;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see gov.nasa.jpl.oodt.cas.resource.scheduler.Scheduler#nodeAvailable(gov.nasa.jpl.oodt.cas.resource.structs.JobSpec)
+     */
+    public synchronized ResourceNode nodeAvailable(JobSpec spec)
+            throws SchedulerException {
+        try {
+	    	String queueName = spec.getJob().getQueueName();
+	        int load = spec.getJob().getLoadValue().intValue();
+	
+	        for (String nodeId : queueManager.getNodes(queueName)) {
+	            int nodeLoad = -1;
+	            ResourceNode resNode = null;
+	
+	            try {
+	                resNode = myMonitor.getNodeById(nodeId);
+	                nodeLoad = myMonitor.getLoad(resNode);
+	            } catch (MonitorException e) {
+	                LOG
+	                        .log(Level.WARNING, "Exception getting load on "
+	                                + "node: [" + resNode.getNodeId()
+	                                + "]: Message: " + e.getMessage());
+	                throw new SchedulerException(e.getMessage());
+	            }
+	
+	            if (load <= nodeLoad) {
+	                return resNode;
+	            }
+	        }
+	
+	        return null;
+        }catch (Exception e) {
+        	throw new SchedulerException("Failed to find available node for job spec : " + e.getMessage(), e);
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/LRUSchedulerFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/LRUSchedulerFactory.java
new file mode 100644
index 0000000..9a1c710
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/LRUSchedulerFactory.java
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.scheduler;
+
+//JAVA imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.resource.queuerepo.XmlQueueRepositoryFactory;
+import org.apache.oodt.cas.resource.util.GenericResourceManagerObjectFactory;
+import org.apache.oodt.cas.resource.jobqueue.JobQueue;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.batchmgr.Batchmgr;
+
+/**
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A Least recently used scheduler factory interface.
+ * </p>
+ * 
+ */
+public class LRUSchedulerFactory implements SchedulerFactory {
+
+	private static final Logger LOG = Logger
+			.getLogger(LRUSchedulerFactory.class.getName());
+
+	/*
+	 * a list of URIs pointing to directories that have the
+	 * node-to-queue-mapping.xml files
+	 */
+	private LRUQueueManager queueManager;
+
+	/* our monitor */
+	private Monitor mon = null;
+
+	/* our batchmgr */
+	private Batchmgr batcher = null;
+
+	/* our job queue */
+	private JobQueue queue = null;
+
+	public LRUSchedulerFactory() {
+		String queueRepoFactoryClassStr = System.getProperty(
+				"org.apache.oodt.cas.resource.queues.repo.factory",
+				XmlQueueRepositoryFactory.class.getCanonicalName());
+		String batchmgrClassStr = System
+				.getProperty("resource.batchmgr.factory",
+						"org.apache.oodt.cas.resource.batchmgr.XmlRpcBatchmgrFactory");
+		String monitorClassStr = System
+				.getProperty("resource.monitor.factory",
+						"org.apache.oodt.cas.resource.monitor.AssignmentMonitorFactory");
+
+		String jobQueueClassStr = System
+				.getProperty("resource.jobqueue.factory",
+						"org.apache.oodt.cas.resource.jobqueue.JobStackJobQueueFactory");
+
+		try {
+			queueManager = new LRUQueueManager(
+					GenericResourceManagerObjectFactory
+							.getQueueRepositoryFromFactory(
+									queueRepoFactoryClassStr).loadQueues());
+		} catch (Exception e) {
+			LOG.log(Level.SEVERE, "Failed to create queue manager : "
+					+ e.getMessage(), e);
+			queueManager = null;
+		}
+		batcher = GenericResourceManagerObjectFactory
+				.getBatchmgrServiceFromFactory(batchmgrClassStr);
+		mon = GenericResourceManagerObjectFactory
+				.getMonitorServiceFromFactory(monitorClassStr);
+
+		queue = GenericResourceManagerObjectFactory
+				.getJobQueueServiceFromFactory(jobQueueClassStr);
+
+		// set the monitor for this batcher
+		batcher.setMonitor(mon);
+
+		// set the job repo for this batcher
+		batcher.setJobRepository(queue.getJobRepository());
+
+	}
+
+	public Scheduler createScheduler() {
+		return new LRUScheduler(mon, batcher, queue, queueManager);
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/QueueManager.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/QueueManager.java
new file mode 100644
index 0000000..4bacd53
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/QueueManager.java
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.scheduler;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.exceptions.QueueManagerException;
+
+//JDK imports
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * The Queue to Node Mapping Manager
+ * </p>
+ */
+public class QueueManager {
+
+	protected Map<String, LinkedHashSet<String>> queueToNodesMapping;
+	
+	public QueueManager() {
+		this.queueToNodesMapping = new HashMap<String, LinkedHashSet<String>>();
+	}
+	
+	public synchronized boolean containsQueue(String queueName) {
+		return this.queueToNodesMapping.containsKey(queueName);
+	}
+	
+	public synchronized void addNodeToQueue(String nodeId, String queueName) throws QueueManagerException {
+		if (queueName == null || !this.queueToNodesMapping.containsKey(queueName)) 
+			throw new QueueManagerException("Queue '" + queueName + "' does not exist");
+		
+		// add node to queue
+		LinkedHashSet<String> nodes = this.queueToNodesMapping.get(queueName);
+		if (nodes == null)
+			nodes = new LinkedHashSet<String>();
+		nodes.add(nodeId);
+		
+		// put node list back into map
+		this.queueToNodesMapping.put(queueName, nodes);
+	}
+
+	public synchronized void addQueue(String queueName) throws QueueManagerException {
+		if (queueName != null && !this.queueToNodesMapping.containsKey(queueName)) 
+			this.queueToNodesMapping.put(queueName, new LinkedHashSet<String>());
+	}
+
+	public synchronized List<String> getNodes(String queueName) throws QueueManagerException {
+		if (queueName != null && this.queueToNodesMapping.containsKey(queueName)) 
+			return new Vector<String>(this.queueToNodesMapping.get(queueName));
+		else
+			throw new QueueManagerException("Queue '" + queueName + "' does not exist");
+	}
+	
+	public synchronized List<String> getQueues() throws QueueManagerException {
+		return new Vector<String>(this.queueToNodesMapping.keySet());
+	}
+
+	public synchronized List<String> getQueues(String nodeId) throws QueueManagerException {
+		Vector<String> queueNames = new Vector<String>();
+		for (String queueName : this.queueToNodesMapping.keySet()) 
+			if (this.queueToNodesMapping.get(queueName).contains(nodeId))
+				queueNames.add(queueName);
+		return queueNames;
+	}
+
+	public synchronized void removeNodeFromQueue(String nodeId, String queueName) throws QueueManagerException {
+		if (queueName != null && this.queueToNodesMapping.containsKey(queueName)) 
+			this.queueToNodesMapping.get(queueName).remove(nodeId);
+		else
+			throw new QueueManagerException("Queue '" + queueName + "' does not exist");
+	}
+
+	public synchronized void removeQueue(String queueName) throws QueueManagerException {
+		if (queueName != null) 
+			this.queueToNodesMapping.remove(queueName);
+	}
+	
+}
+
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/ResourceMesosScheduler.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/ResourceMesosScheduler.java
new file mode 100644
index 0000000..de0a867
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/ResourceMesosScheduler.java
@@ -0,0 +1,351 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.scheduler;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.mesos.Protos.ExecutorID;
+import org.apache.mesos.Protos.ExecutorInfo;
+import org.apache.mesos.Protos.FrameworkID;
+import org.apache.mesos.Protos.MasterInfo;
+import org.apache.mesos.Protos.Offer;
+import org.apache.mesos.Protos.OfferID;
+import org.apache.mesos.Protos.Resource;
+import org.apache.mesos.Protos.SlaveID;
+import org.apache.mesos.Protos.Status;
+import org.apache.mesos.Protos.TaskID;
+import org.apache.mesos.Protos.TaskInfo;
+import org.apache.mesos.Protos.TaskStatus;
+import org.apache.mesos.Protos.Value;
+import org.apache.mesos.Scheduler;
+import org.apache.mesos.SchedulerDriver;
+import org.apache.oodt.cas.resource.batchmgr.Batchmgr;
+import org.apache.oodt.cas.resource.batchmgr.MesosBatchManager;
+import org.apache.oodt.cas.resource.jobqueue.JobQueue;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.JobQueueException;
+import org.apache.oodt.cas.resource.structs.exceptions.MesosFrameworkException;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+import org.apache.oodt.cas.resource.structs.exceptions.SchedulerException;
+import org.apache.oodt.cas.resource.util.MesosUtilities;
+
+/**
+ * @author starchmd
+ * @version $Revision$
+ *
+ * A scheduler for part of the mesos frame work.
+ */
+public class ResourceMesosScheduler implements Scheduler, org.apache.oodt.cas.resource.scheduler.Scheduler {
+    SchedulerDriver driver;
+    MesosBatchManager batch;
+    ExecutorInfo executor;
+    JobQueue queue;
+    Monitor mon;
+
+    //Logger
+    private static final Logger LOG = Logger.getLogger(ResourceMesosScheduler.class.getName());
+    /**
+     * Construct the scheduler
+     * @param batch - batch manager (must be MesosBatchManager)
+     * @param executor - Mesos ExecutorInfo
+     * @param queue Job Queue used
+     * @param mon - monitor used.
+     */
+    public ResourceMesosScheduler(MesosBatchManager batch,ExecutorInfo executor, JobQueue queue, Monitor mon) {
+        this.batch = batch;
+        this.executor = executor;
+        this.queue = queue;
+        this.mon = mon;
+        LOG.log(Level.INFO,"Creating the resource-mesos scheduler.");
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Scheduler#disconnected(org.apache.mesos.SchedulerDriver)
+     */
+    @Override
+    public void disconnected(SchedulerDriver schedDriver) {
+        //TODO: Pause scheduler until master comes back online.
+
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Scheduler#error(org.apache.mesos.SchedulerDriver, java.lang.String)
+     */
+    @Override
+    public void error(SchedulerDriver schedDriver, String error) {
+        LOG.log(Level.SEVERE,"Mesos issued an error: "+error);
+        //TODO: kill something here.
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Scheduler#executorLost(org.apache.mesos.SchedulerDriver, org.apache.mesos.Protos.ExecutorID, org.apache.mesos.Protos.SlaveID, int)
+     */
+    @Override
+    public void executorLost(SchedulerDriver schedDriver, ExecutorID executor,SlaveID slave, int status) {
+        //Tasks will have a "task lost" message automatically q.e.d no action necessary.
+        //TODO: do we need to restart?
+        LOG.log(Level.SEVERE,"Mesos executor "+executor+" on slave "+slave+" died with status "+status);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Scheduler#frameworkMessage(org.apache.mesos.SchedulerDriver, org.apache.mesos.Protos.ExecutorID, org.apache.mesos.Protos.SlaveID, byte[])
+     */
+    @Override
+    public void frameworkMessage(SchedulerDriver schedDriver, ExecutorID executor,
+            SlaveID slave, byte[] bytes) {
+        try {
+            LOG.log(Level.INFO,"Mesos framework executor"+executor+" on slave "+slave+" issued message: "+
+                new String(bytes,"ascii"));
+        } catch (UnsupportedEncodingException e) {
+            LOG.log(Level.WARNING,"Mesos framework message missed due to bad encoding: ascii. "+e.getMessage());
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Scheduler#offerRescinded(org.apache.mesos.SchedulerDriver, org.apache.mesos.Protos.OfferID)
+     */
+    @Override
+    public void offerRescinded(SchedulerDriver schedDriver, OfferID offer) {
+        //TODO: take away resources from batch manager...or stand in.
+        //Unneeded?
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Scheduler#registered(org.apache.mesos.SchedulerDriver, org.apache.mesos.Protos.FrameworkID, org.apache.mesos.Protos.MasterInfo)
+     */
+    @Override
+    public void registered(SchedulerDriver schedDriver, FrameworkID framework,
+            MasterInfo masterInfo) {
+        LOG.log(Level.INFO,"Mesos framework registered: "+framework.getValue()+" with master: "+masterInfo.getId());
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Scheduler#reregistered(org.apache.mesos.SchedulerDriver, org.apache.mesos.Protos.MasterInfo)
+     */
+    @Override
+    public void reregistered(SchedulerDriver schedDriver, MasterInfo masterInfo) {
+        LOG.log(Level.INFO,"Mesos framework re-registered with: "+masterInfo.getId());
+        //TODO: call start, we are registered.
+
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Scheduler#resourceOffers(org.apache.mesos.SchedulerDriver, java.util.List)
+     */
+    @Override
+    public void resourceOffers(SchedulerDriver driver, List<Offer> offers) {
+        LOG.log(Level.INFO,"Offered mesos resources: "+offers.size()+" offers.");
+        //Log, if possible the offers
+        if (LOG.isLoggable(Level.FINER)) {
+            for (Offer offer : offers) {
+                try {
+                    this.mon.addNode(new ResourceNode(offer.getSlaveId().getValue(),new URL("http://"+offer.getHostname()),-1));
+                } catch (MalformedURLException e) {
+                    LOG.log(Level.WARNING,"Cannot add node to monitor (bad url).  Giving up: "+e.getMessage());
+                } catch ( MonitorException e) {
+                    LOG.log(Level.WARNING,"Cannot add node to monitor (unkn).  Giving up: "+e.getMessage());
+                }
+                LOG.log(Level.FINER,"Offer ("+offer.getId().getValue()+"): "+offer.getHostname()+ "(Slave: "+
+                        offer.getSlaveId().getValue()+") "+MesosUtilities.getResourceMessage(offer.getResourcesList()));
+            }
+        }
+        List<JobSet> assignments = this.getJobAssignmentsJobs(offers);
+        List<OfferID> used = new LinkedList<OfferID>();
+        for (JobSet assignment : assignments) {
+            //Launch tasks requires lists
+            List<OfferID> ids = new LinkedList<OfferID>();
+            List<TaskInfo> tasks = new LinkedList<TaskInfo>();
+            tasks.add(assignment.task);
+            used.add(assignment.offer.getId());
+            ids.add(assignment.offer.getId());
+            //Register locally and launch on mesos
+            batch.registerExecutedJob(assignment.job.getJob().getId(), assignment.task.getTaskId());
+            Status status = driver.launchTasks(ids,tasks); //Assumed one to one mapping
+            if (status != Status.DRIVER_RUNNING)
+                throw new MesosFrameworkException("Driver stopped: "+status.toString());
+        }
+        for (Offer offer : offers) {
+            if (!used.contains(offer.getId())) {
+                LOG.log(Level.INFO,"Rejecting Offer: "+offer.getId().getValue());
+                driver.declineOffer(offer.getId());
+            }
+        }
+    }
+    /**
+     * Builds a TaskInfo from the given jobspec
+     * @param job - JobSpec to TaskInfo-ify
+     * @param offer - offer add extra data (SlaveId)
+     * @return TaskInfo fully formed
+     */
+    private TaskInfo getTaskInfo(JobSpec job,Offer offer) {
+        TaskID taskId = TaskID.newBuilder().setValue(job.getJob().getId()).build();
+        TaskInfo info = TaskInfo.newBuilder().setName("task " + taskId.getValue())
+                 .setTaskId(taskId)
+                 .setSlaveId(offer.getSlaveId())
+                 .addResources(Resource.newBuilder()
+                               .setName("cpus")
+                               .setType(Value.Type.SCALAR)
+                               .setScalar(Value.Scalar.newBuilder().setValue(job.getJob().getLoadValue()*1.0)))
+                 .addResources(Resource.newBuilder()
+                               .setName("mem")
+                               .setType(Value.Type.SCALAR)
+                               .setScalar(Value.Scalar.newBuilder().setValue(job.getJob().getLoadValue()*1024.0)))
+                 .setExecutor(ExecutorInfo.newBuilder(executor)).setData(MesosUtilities.jobSpecToByteString(job)).build();
+        return info;
+    }
+    /**
+     * Checks all offers against jobs in order, assigning jobs to offers until each offer is full,
+     * or all jobs are gone.
+     * @param offers - offers to assign jobs to.
+     * @return List of <JobSpec,TaskInfo,Offer> tuples (assigned to each other).
+     */
+    private List<JobSet> getJobAssignmentsJobs(List<Offer> offers) {
+        List<JobSet> list = new LinkedList<JobSet>();
+        for (Offer offer : offers)
+        {
+            double cpus = 0.0, mem = 0.0;
+            //Get the resources offered from this offer
+            for (Resource resc : offer.getResourcesList()) {
+                if (resc.getName().equals("cpus"))
+                    cpus += resc.getScalar().getValue();
+                if (resc.getName().equals("mem"))
+                    mem += resc.getScalar().getValue();
+            }
+            //Search for enough jobs to fill the offer
+            for (int i = 0;i < queue.getSize();i++)
+            {
+                try {
+                    JobSpec job = queue.getNextJob();
+                    double load = job.getJob().getLoadValue();
+                    //Check if enough resources
+                    if (cpus < load || mem < load*1024)
+                    {
+                        queue.requeueJob(job);
+                        continue;
+                    }
+                    cpus -= load;
+                    mem -= 1024*load;
+                    JobSet tmp = new JobSet(job,getTaskInfo(job,offer),offer);
+                    list.add(tmp);
+                    //Not enough left, optimise and stop looking for jobs
+                    if (cpus < 0.5 || mem <= 512.0)
+                        break;
+                } catch (JobQueueException e) {throw new RuntimeException(e);}
+            }
+            //Optimization: break when no jobs
+            if (queue.getSize() == 0)
+                break;
+        }
+        return list;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Scheduler#slaveLost(org.apache.mesos.SchedulerDriver, org.apache.mesos.Protos.SlaveID)
+     */
+    @Override
+    public void slaveLost(SchedulerDriver schedDriver, SlaveID slave) {
+        LOG.log(Level.WARNING,"Mesos slave "+slave+" lost, reissuing jobs.");
+        //TODO: reregister jobs
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.mesos.Scheduler#statusUpdate(org.apache.mesos.SchedulerDriver, org.apache.mesos.Protos.TaskStatus)
+     */
+    @Override
+    public void statusUpdate(SchedulerDriver schedDriver, TaskStatus taskStatus) {
+        //TODO: deliver messages, some rerun, some finish.
+        LOG.log(Level.INFO,"Status update: "+taskStatus.getMessage());
+    }
+
+
+
+    @Override
+    public void run() {
+        LOG.log(Level.INFO,"Attempting to run framework. Nothing to do.");
+        LOG.log(Level.FINEST, "Paradigm shift enabled.");
+        LOG.log(Level.FINEST, "Spin and poll surplanted by event based execution.");
+        LOG.log(Level.FINEST, "Mesos-OODT Fusion complete.");
+        //Don't run anything
+        return;
+    }
+
+
+
+    @Override
+    public boolean schedule(JobSpec spec) throws SchedulerException {
+        throw new NotImplementedException("Schedule is not called when using mesos.");
+    }
+
+
+
+    @Override
+    public ResourceNode nodeAvailable(JobSpec spec) throws SchedulerException {
+        return null;
+    }
+
+
+
+    @Override
+    public Monitor getMonitor() {
+        return mon;
+    }
+
+
+
+    @Override
+    public Batchmgr getBatchmgr() {
+        return batch;
+    }
+
+
+
+    @Override
+    public JobQueue getJobQueue() {
+        // TODO Auto-generated method stub
+        return queue;
+    }
+
+
+
+    @Override
+    public QueueManager getQueueManager() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+    //Job set used internally to simplify data transmission
+    private class JobSet {
+        public JobSpec job;
+        public TaskInfo task;
+        public Offer offer;
+        //Build a job set
+        public JobSet(JobSpec job, TaskInfo task, Offer offer) {
+            this.job = job;
+            this.task = task;
+            this.offer = offer;
+        }
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/ResourceMesosSchedulerFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/ResourceMesosSchedulerFactory.java
new file mode 100644
index 0000000..051e2e6
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/ResourceMesosSchedulerFactory.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.scheduler;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.mesos.MesosSchedulerDriver;
+import org.apache.mesos.Protos.CommandInfo;
+import org.apache.mesos.Protos.ExecutorID;
+import org.apache.mesos.Protos.ExecutorInfo;
+import org.apache.mesos.Protos.FrameworkID;
+import org.apache.mesos.Protos.FrameworkInfo;
+import org.apache.mesos.Protos.Status;
+import org.apache.mesos.SchedulerDriver;
+import org.apache.oodt.cas.resource.batchmgr.MesosBatchManager;
+import org.apache.oodt.cas.resource.jobqueue.JobQueue;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.util.GenericResourceManagerObjectFactory;
+
+/**
+ * A class to setup the resource manager's mesos framework.
+ * @author starchmd
+ * @version $Revision$
+ *
+ */
+public class ResourceMesosSchedulerFactory implements SchedulerFactory {
+
+    private static final Logger LOG = Logger.getLogger(ResourceMesosSchedulerFactory.class.getName());
+
+    private Monitor mon = null;
+    private MesosBatchManager batch = null;
+    private JobQueue queue = null;
+
+    public ResourceMesosSchedulerFactory() {}
+
+    public Scheduler construct() {
+        try {
+            String uri = System.getProperty("org.apache.oodt.cas.resource.mesos.executor.uri","./oodt-executor.in");
+            //Framework info
+            FrameworkInfo.Builder frameworkBuilder = FrameworkInfo.newBuilder()
+                        .setName("OODT Resource Manager Mesos Framework").setUser("")
+                        .setId(FrameworkID.newBuilder().setValue("OODT-Resource Framework").build());
+            FrameworkInfo framework = frameworkBuilder.build();
+            ExecutorInfo executor = ExecutorInfo.newBuilder().setExecutorId(ExecutorID.newBuilder().setValue("OODT-Resource").build())
+                    .setCommand(CommandInfo.newBuilder().setValue(new File(uri).getCanonicalPath()).build())
+                    .setName("OODT Resource Manager Executor").build();
+            SchedulerDriver driver = null;
+
+            //Resource manager properties
+            String batchmgrClassStr = "org.apache.oodt.cas.resource.batchmgr.MesosBatchManagerFactory";
+            String monitorClassStr = "org.apache.oodt.cas.resource.monitor.MesosMonitorFactory";
+            String jobQueueClassStr = System.getProperty("resource.jobqueue.factory","org.apache.oodt.cas.resource.jobqueue.JobStackJobQueueFactory");
+            String ip = System.getProperty("resource.mesos.master.ip","127.0.0.1:5050");
+
+            batch = (MesosBatchManager)GenericResourceManagerObjectFactory.getBatchmgrServiceFromFactory(batchmgrClassStr);
+            mon = GenericResourceManagerObjectFactory.getMonitorServiceFromFactory(monitorClassStr);
+            queue = GenericResourceManagerObjectFactory.getJobQueueServiceFromFactory(jobQueueClassStr);
+            batch.setMonitor(mon);
+            batch.setDriver(driver);
+            batch.setJobRepository(queue.getJobRepository());
+
+            LOG.log(Level.INFO,"Connecting to Mesos Master at: "+ip);
+            System.out.println("Connecting to Mesos Master at: "+ip);
+            ResourceMesosScheduler scheduler = new ResourceMesosScheduler(batch, executor, queue, mon);
+
+            final MesosSchedulerDriver mesos = new MesosSchedulerDriver(scheduler, framework, ip);
+            //Anonymous thread to run
+            new Thread(new Runnable() {
+                public void run() {
+                    int status = mesos.run() == Status.DRIVER_STOPPED ? 0 : 1;
+                    mesos.stop();
+                }
+            }).start();
+            return scheduler;
+        } catch(IOException ioe) {
+            LOG.log(Level.SEVERE,"Exception detected: "+ioe.getMessage());
+            ioe.printStackTrace();
+            throw new RuntimeException(ioe);
+        }
+    }
+
+    @Override
+    public Scheduler createScheduler() {
+        return construct();
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/Scheduler.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/Scheduler.java
new file mode 100644
index 0000000..f309d9e
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/Scheduler.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.scheduler;
+
+//OODT imports
+import org.apache.oodt.cas.resource.batchmgr.Batchmgr;
+import org.apache.oodt.cas.resource.jobqueue.JobQueue;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.scheduler.QueueManager;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.SchedulerException;
+
+/**
+ * @author woollard
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * A scheduler interface.
+ * </p>
+ * 
+ */
+public interface Scheduler extends Runnable{
+
+	/**
+	 * Schedules a job to be executed by a particular batch manager.
+	 * 
+	 * @param spec
+	 *            The {@link JobSpec} to schedule for execution.
+	 * @return Whether the job was successfully scheduled or not.
+  * @throws SchedulerException If there was any error scheduling
+  * the given {@link JobSpec}.
+	 */
+	public boolean schedule(JobSpec spec) throws SchedulerException;
+
+
+ /**
+  * Returns the ResourceNode that is considered to be <quote>most available</quote>
+  * within our underlying set of resources for the given JobSpec.
+  * @param spec The JobSpec to find an available node for.
+  * @return The {@link ResourceNode} best suited to handle this {@link JobSpec}
+  * @throws SchedulerException If any error occurs.
+  */
+ public ResourceNode nodeAvailable(JobSpec spec) throws SchedulerException;
+
+ /**
+  * 
+  * @return The underlying {@link Monitor} used by this
+  * Scheduler.
+  */
+ public Monitor getMonitor();
+ 
+ /**
+  * 
+  * @return The underlying {@link Batchmgr} used by this
+  * Scheduler.
+  */
+ public Batchmgr getBatchmgr();
+ 
+ 
+ /**
+  * 
+  * @return The underlying {@link JobQueue} used by this
+  * Scheduler.
+  */
+ public JobQueue getJobQueue();
+
+ /**
+  * 
+  * @return The underlying {@link QueueManager} used by this
+  * Scheduler.
+  */
+ public QueueManager getQueueManager();
+ 
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/SchedulerFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/SchedulerFactory.java
new file mode 100644
index 0000000..c483114
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/SchedulerFactory.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.scheduler;
+
+/**
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory interface for creating implementations of {@link Scheduler}s.
+ * </p>
+ * 
+ */
+public interface SchedulerFactory {
+
+	/**
+	 * @return A new implementation of the {@link Scheduler} interface.
+	 */
+	public Scheduler createScheduler();
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/SparkScheduler.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/SparkScheduler.java
new file mode 100644
index 0000000..bf1be81
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/SparkScheduler.java
@@ -0,0 +1,150 @@
+package org.apache.oodt.cas.resource.scheduler;
+
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.resource.batchmgr.Batchmgr;
+import org.apache.oodt.cas.resource.jobqueue.JobQueue;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.structs.JobInstance;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.SparkInstance;
+import org.apache.oodt.cas.resource.structs.StreamingInstance;
+import org.apache.oodt.cas.resource.structs.exceptions.JobInputException;
+import org.apache.oodt.cas.resource.structs.exceptions.JobQueueException;
+import org.apache.oodt.cas.resource.structs.exceptions.SchedulerException;
+import org.apache.oodt.cas.resource.util.GenericResourceManagerObjectFactory;
+import org.apache.spark.SparkConf;
+import org.apache.spark.SparkContext;
+import org.apache.spark.api.java.JavaSparkContext;
+import org.apache.spark.streaming.Duration;
+import org.apache.spark.streaming.StreamingContext;
+
+/**
+ * A scheduler that runs spark jobs on a spark cluster.
+ *
+ * @author starchmd
+ *
+ */
+public class SparkScheduler implements Scheduler {
+
+    SparkContext sc;
+    StreamingContext ssc;
+    JobQueue queue;
+
+    private static final Logger LOG = Logger.getLogger(SparkScheduler.class.getName());
+
+    public SparkScheduler(JobQueue queue) {
+        SparkConf conf = new SparkConf();
+        conf.setMaster(System.getProperty("resource.runner.spark.host","local"));
+        conf.setAppName("OODT Spark Job");
+
+        URL location = SparkScheduler.class.getResource('/'+SparkScheduler.class.getName().replace('.', '/')+".class");
+        conf.setJars(new String[]{"../lib/cas-resource-0.8-SNAPSHOT.jar"});
+        sc = new SparkContext(conf);
+        ssc = new StreamingContext(sc,new Duration(10000));
+        this.queue = queue;
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Runnable#run()
+     */
+    @Override
+    public void run() {
+        while (true) {
+            try {
+                if (queue.isEmpty())
+                    continue;
+                JobSpec spec = queue.getNextJob();
+
+                Class<?> clazz = Class.forName(spec.getJob().getJobInstanceClassName());
+                if (!(clazz.newInstance() instanceof SparkInstance)) {
+                    LOG.log(Level.WARNING,"Non-Spark job found ("+spec.getJob().getId()+") ignoring.");
+                    continue;
+                }
+                this.schedule(spec);
+            } catch(SchedulerException e) {
+                LOG.log(Level.WARNING,"Scheduler exception detected: "+e.getMessage());
+            } catch (JobQueueException e) {
+                LOG.log(Level.WARNING,"Could not get next job from job-queue.");
+            } catch (ClassNotFoundException e) {
+                LOG.log(Level.WARNING,"Class not found: "+e.getMessage());
+            } catch (InstantiationException e) {
+                LOG.log(Level.WARNING,"Could not instantiate: "+e.getMessage());
+            } catch (IllegalAccessException e) {
+                LOG.log(Level.WARNING,"Could not access: "+e.getMessage());
+            }
+
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.scheduler.Scheduler#schedule(org.apache.oodt.cas.resource.structs.JobSpec)
+     */
+    @Override
+    public boolean schedule(JobSpec spec) throws SchedulerException {
+        try {
+            JobInstance instance = GenericResourceManagerObjectFactory.getJobInstanceFromClassName(spec.getJob().getJobInstanceClassName());
+            //spec.getIn().
+            SparkInstance sparkInstance = (SparkInstance) instance;
+            LOG.log(Level.INFO,"Setting SparkContext");
+            sparkInstance.setSparkContext(this.sc);
+            //Handle spark streaming
+            if (sparkInstance instanceof StreamingInstance) {
+                LOG.log(Level.INFO,"Found streaming instance, setting StreamingContext");
+                ((StreamingInstance)sparkInstance).setStreamingContext(this.ssc);
+            }
+            sparkInstance.execute(spec.getIn());
+
+        } catch (JobInputException e) {
+            LOG.log(Level.WARNING,"Job input exception detected.");
+            throw new SchedulerException(e);
+        }
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.scheduler.Scheduler#nodeAvailable(org.apache.oodt.cas.resource.structs.JobSpec)
+     */
+    @Override
+    public ResourceNode nodeAvailable(JobSpec spec) throws SchedulerException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.scheduler.Scheduler#getMonitor()
+     */
+    @Override
+    public Monitor getMonitor() {
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.scheduler.Scheduler#getBatchmgr()
+     */
+    @Override
+    public Batchmgr getBatchmgr() {
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.scheduler.Scheduler#getJobQueue()
+     */
+    @Override
+    public JobQueue getJobQueue() {
+        return queue;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.resource.scheduler.Scheduler#getQueueManager()
+     */
+    @Override
+    public QueueManager getQueueManager() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/SparkSchedulerFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/SparkSchedulerFactory.java
new file mode 100644
index 0000000..5fb732b
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/scheduler/SparkSchedulerFactory.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.scheduler;
+
+//JAVA imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+//OODT imports
+
+import org.apache.oodt.cas.resource.util.GenericResourceManagerObjectFactory;
+import org.apache.oodt.cas.resource.jobqueue.JobQueue;
+import org.apache.oodt.cas.resource.jobqueue.JobStackJobQueueFactory;
+
+/**
+ * @author starchmd
+ * @version $Revision$
+ *
+ * <p>
+ * A factory for the SparkScheduler
+ * </p>
+ *
+ */
+public class SparkSchedulerFactory implements SchedulerFactory {
+
+	private static final Logger LOG = Logger.getLogger(SparkSchedulerFactory.class.getName());
+
+
+	private JobQueue queue = null;
+	/**
+	 * Setup factory
+	 */
+	public SparkSchedulerFactory() {
+		String jobQueueClassStr = System.getProperty("resource.jobqueue.factory",
+		        JobStackJobQueueFactory.class.getName());
+		LOG.log(Level.INFO,"Using job-queue: "+jobQueueClassStr+ " with: "+SparkScheduler.class.getName());
+		queue = GenericResourceManagerObjectFactory.getJobQueueServiceFromFactory(jobQueueClassStr);
+	}
+	/**
+	 * Returns scheduler
+	 */
+	public Scheduler createScheduler() {
+		return new SparkScheduler(queue);
+	}
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/Job.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/Job.java
new file mode 100644
index 0000000..88d857a
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/Job.java
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.structs;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * The unit of computation in the resource manager.
+ * </p>
+ * 
+ */
+public class Job {
+
+    /* our job id */
+    private String id = null;
+
+    /* job name */
+    private String name = null;
+
+    /* the instance class */
+    private String jobInstanceClassName = null;
+
+    /* the job input class */
+    private String jobInputClassName = null;
+
+    /* the queue that this job belongs to */
+    private String queueName = null;
+
+    /* the load value for this job */
+    private Integer loadValue = null;
+
+    /* the status of this job */
+    private String status = null;
+
+    /**
+     * Default Constructor.
+     * 
+     */
+    public Job() {
+    }
+
+    /**
+     * @param id
+     *            The unique identifier for this job.
+     * @param name
+     *            The name for this job.
+     * @param jobInstanceClassName
+     *            The class name of the {@link JobInstance} class that this Job
+     *            should run.
+     * @param jobInputClassName
+     *            The class name of the {@link JobInput} class that should be
+     *            fed as input to the running {@link JobInstance}.
+     */
+    public Job(String id, String name, String jobInstanceClassName,
+            String jobInputClassName, String queueName, Integer loadValue) {
+        this.id = id;
+        this.name = name;
+        this.jobInstanceClassName = jobInstanceClassName;
+        this.jobInputClassName = jobInputClassName;
+        this.loadValue = loadValue;
+        this.queueName = queueName;
+    }
+
+    /**
+     * @return the id
+     */
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * @param id
+     *            the id to set
+     */
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    /**
+     * @return the jobInputClassName
+     */
+    public String getJobInputClassName() {
+        return jobInputClassName;
+    }
+
+    /**
+     * @param jobInputClassName
+     *            the jobInputClassName to set
+     */
+    public void setJobInputClassName(String jobInputClassName) {
+        this.jobInputClassName = jobInputClassName;
+    }
+
+    /**
+     * @return the jobInstanceClassName
+     */
+    public String getJobInstanceClassName() {
+        return jobInstanceClassName;
+    }
+
+    /**
+     * @param jobInstanceClassName
+     *            the jobInstanceClassName to set
+     */
+    public void setJobInstanceClassName(String jobInstanceClassName) {
+        this.jobInstanceClassName = jobInstanceClassName;
+    }
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @param name
+     *            the name to set
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Integer getLoadValue() {
+        return loadValue;
+    }
+
+    public void setLoadValue(Integer loadValue) {
+        this.loadValue = loadValue;
+    }
+
+    public String getQueueName() {
+        return queueName;
+    }
+
+    public void setQueueName(String queueName) {
+        this.queueName = queueName;
+    }
+
+    /**
+     * @return the status
+     */
+    public String getStatus() {
+        return status;
+    }
+
+    /**
+     * @param status
+     *            the status to set
+     */
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobInput.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobInput.java
new file mode 100644
index 0000000..4114ea1
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobInput.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.structs;
+
+//OODT imports
+import org.apache.oodt.cas.resource.util.Configurable;
+import org.apache.oodt.cas.resource.util.XmlRpcWriteable;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Input to a job that should be writeable over the XML-RPC wire.
+ * </p>.
+ */
+public interface JobInput extends XmlRpcWriteable, Configurable {
+
+  /**
+   * Gets the ID of this JobInput
+   * 
+   * @return The string identifier of this JobInput object.
+   */
+  public String getId();
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobInstance.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobInstance.java
new file mode 100644
index 0000000..dd1ce0b
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobInstance.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.structs;
+
+import org.apache.oodt.cas.resource.structs.exceptions.JobInputException;
+
+/**
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * A job interface: the thing that actually performs the work.
+ * </p>
+ */
+public interface JobInstance {
+
+  /**
+   * Executes the underlying code for this job.
+   * 
+   * @param in
+   *          The Job's input.
+   * 
+   * @return true if the job execution was successful, false otherwise.
+   * @throws JobInputException
+   *           If there was an error handling the {@link JobInput}.
+   */
+  boolean execute(JobInput in) throws JobInputException;
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobSpec.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobSpec.java
new file mode 100644
index 0000000..76a21b4
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobSpec.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.structs;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * A class that holds the complete specification for how to run a {@link Job}.
+ * This includes the {@link Job} definition itself, along with its
+ * {@link JobInput}.
+ */
+public class JobSpec {
+
+  private JobInput in = null;
+
+  private Job job = null;
+
+  /**
+   * Default Constructor.
+   * 
+   */
+  public JobSpec() {
+  }
+
+  /**
+   * Constructs a new JobSpec with the given {@link JobInput} and {@link Job}.
+   * 
+   * @param in
+   *          The {@link Job}'s input.
+   * @param job
+   *          The {@link Job}'s definition.
+   */
+  public JobSpec(JobInput in, Job job) {
+    this.in = in;
+    this.job = job;
+  }
+
+  /**
+   * @return the in
+   */
+  public JobInput getIn() {
+    return in;
+  }
+
+  /**
+   * @param in
+   *          the in to set
+   */
+  public void setIn(JobInput in) {
+    this.in = in;
+  }
+
+  /**
+   * @return the job
+   */
+  public Job getJob() {
+    return job;
+  }
+
+  /**
+   * @param job
+   *          the job to set
+   */
+  public void setJob(Job job) {
+    this.job = job;
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobSpecSerializer.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobSpecSerializer.java
new file mode 100644
index 0000000..44f8890
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobSpecSerializer.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.structs;
+
+import java.io.Serializable;
+
+/**
+ * A class used to serialize and de-serialize a job spec
+ * @author starchmd
+ */
+public class JobSpecSerializer implements java.io.Serializable {
+    private static final long serialVersionUID = -8246199042863932667L;
+    //Variables needed to serialize
+    String id;
+    String jobInputClassName;
+    String jobInstanceClassName;
+    Integer loadValue;
+    String name;
+    String queueName;
+    String status;
+    String jobInputId;
+    Serializable jobInput;
+    /**
+     * Set the variables to serialize them.
+     * @param spec - job spec to serialize
+     */
+    public JobSpecSerializer(JobSpec spec) {
+        //Job
+        Job tmp = spec.getJob();
+        id = tmp.getId();
+        jobInputClassName = tmp.getJobInputClassName();
+        jobInstanceClassName = tmp.getJobInstanceClassName();
+        loadValue = tmp.getLoadValue();
+        name = tmp.getName();
+        queueName = tmp.getQueueName();
+        status = tmp.getStatus();
+        //Input of spec
+        JobInput input = spec.getIn();
+        jobInputId = input.getId();
+        jobInput = (Serializable)input.write();
+    }
+    /**
+     * Get the JobSpec back.
+     * @return newly constructed job spec
+     * @throws ClassNotFoundException
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     */
+    public JobSpec getJobSpec() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+        Job tmp = new Job();
+        tmp.setId(id);
+        tmp.setJobInputClassName(jobInputClassName);
+        tmp.setJobInstanceClassName(jobInstanceClassName);
+        tmp.setLoadValue(loadValue);
+        tmp.setName(name);
+        tmp.setQueueName(queueName);
+        tmp.setStatus(status);
+        //Read in job input, using proper class
+        Class<?> clazz = Class.forName(jobInputClassName);
+        JobInput input = ((JobInput)clazz.newInstance());
+        input.read(jobInput);
+        JobSpec spec = new JobSpec();
+        spec.setIn(input);
+        spec.setJob(tmp);
+        return spec;
+    }
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobStatus.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobStatus.java
new file mode 100644
index 0000000..882cf96
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/JobStatus.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.structs;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public interface JobStatus {
+  
+  public static final String QUEUED = "__Queued__";
+  
+  public static final String EXECUTED = "__Executed__";
+  
+  public static final String SCHEDULED = "__Scheduled__";
+  
+  public static final String SUCCESS = "__Success__";
+  
+  public static final String FAILURE = "__Failure__";
+  
+  public static final String KILLED = "__Killed__";
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/NameValueJobInput.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/NameValueJobInput.java
new file mode 100644
index 0000000..a7fcb7a
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/NameValueJobInput.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.structs;
+
+//JDK imports
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Properties;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A {@link JobInput} backed by a {@link Properties} object of NameValue pairs.
+ * </p>.
+ */
+public class NameValueJobInput implements JobInput {
+
+  /* our properties object */
+  private Properties props = null;
+
+  /* input id */
+  private static final String INPUT_ID = "NameValInput";
+
+  /**
+   * Default Constructor.
+   */
+  public NameValueJobInput() {
+    props = new Properties();
+  }
+
+  public void setNameValuePair(String name, String value) {
+    props.setProperty(name, value);
+  }
+
+  public String getValue(String name) {
+    return props.getProperty(name);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.structs.JobInput#getId()
+   */
+  public String getId() {
+    return INPUT_ID;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.util.XmlRpcWriteable#read(java.lang.Object)
+   */
+  public void read(Object in) {
+    // we want to make sure that we're reading in
+    // a java.util.Hashtable
+    // if not then just return
+    if (!(in instanceof Hashtable)) {
+      return;
+    }
+
+    Hashtable readable = (Hashtable) in;
+    for (Iterator i = readable.keySet().iterator(); i.hasNext();) {
+      String key = (String) i.next();
+      String value = (String) readable.get(key);
+      this.props.setProperty(key, value);
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.util.XmlRpcWriteable#write()
+   */
+  public Object write() {
+    Hashtable writeable = new Hashtable();
+    if (props != null && props.size() > 0) {
+      for (Iterator i = props.keySet().iterator(); i.hasNext();) {
+        String key = (String) i.next();
+        String val = props.getProperty(key);
+        writeable.put(key, val);
+      }
+    }
+
+    return writeable;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.util.Configurable#configure(java.util.Properties)
+   */
+  public void configure(Properties props) {
+    if (props != null) {
+      this.props = props;
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/ResourceNode.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/ResourceNode.java
new file mode 100644
index 0000000..5e73586
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/ResourceNode.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.structs;
+
+//JAVA imports
+import java.net.URL;
+
+/**
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * A node struct to capture information about each resource.
+ * </p>
+ * 
+ */
+public class ResourceNode {
+	
+	private String nodeId = null;
+	private URL ipAddr = null;
+	private int capacity = 0;
+	
+	public ResourceNode(){}
+	
+	public ResourceNode(String nodeId, URL ipAddr, int capacity){
+		this.nodeId=nodeId;
+		this.ipAddr=ipAddr;
+		this.capacity=capacity;
+	}
+	
+	public String getNodeId(){
+		return nodeId;
+	}
+	
+	public URL getIpAddr(){
+		return ipAddr;
+	}
+	
+	public int getCapacity(){
+		return capacity;
+	}
+	
+	public void setId(String nodeId){
+		this.nodeId = nodeId;
+	}
+	
+	public void setIpAddr(URL ipAddr){
+		this.ipAddr = ipAddr;
+	}
+	
+	public void setCapacity(int capacity){
+		this.capacity = capacity;
+	}
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/SparkInstance.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/SparkInstance.java
new file mode 100644
index 0000000..dd32157
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/SparkInstance.java
@@ -0,0 +1,13 @@
+package org.apache.oodt.cas.resource.structs;
+
+import org.apache.spark.SparkContext;
+
+public interface SparkInstance extends JobInstance {
+
+    /**
+     * Set the context to run by.
+     * @param context
+     */
+    public void setSparkContext(SparkContext context);
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/StreamingInstance.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/StreamingInstance.java
new file mode 100644
index 0000000..5753bcf
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/StreamingInstance.java
@@ -0,0 +1,13 @@
+package org.apache.oodt.cas.resource.structs;
+
+import org.apache.spark.streaming.StreamingContext;
+
+public interface StreamingInstance extends SparkInstance {
+
+    /**
+     * Set the context to run by.
+     * @param context
+     */
+    public void setStreamingContext(StreamingContext context);
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobException.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobException.java
new file mode 100644
index 0000000..3853c14
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobException.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.structs.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * The base class for Job Exceptions.
+ * </p>
+ */
+public class JobException extends Exception {
+
+	/* serial version UID */
+	private static final long serialVersionUID = 4802353574545230182L;
+
+	/**
+	 * 
+	 */
+	public JobException() {
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public JobException(String arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public JobException(Throwable arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param message
+	 * @param cause
+	 */
+	public JobException(String message, Throwable cause) {
+		super(message, cause);
+		// TODO Auto-generated constructor stub
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobExecutionException.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobExecutionException.java
new file mode 100644
index 0000000..58ff169
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobExecutionException.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.structs.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>Exception thrown when executing a {@link Job}.</p>
+ */
+public class JobExecutionException extends JobException {
+
+	/* serial version UID */
+	private static final long serialVersionUID = 411415656412173490L;
+
+	/**
+	 * 
+	 */
+	public JobExecutionException() {
+		super();
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param message
+	 * @param cause
+	 */
+	public JobExecutionException(String message, Throwable cause) {
+		super(message, cause);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public JobExecutionException(String arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public JobExecutionException(Throwable arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobInputException.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobInputException.java
new file mode 100644
index 0000000..1256645
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobInputException.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.structs.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>An exception thrown by a {@link JobInstance}
+ * when the given {@link JobInput} is not what it
+ * expected</p>.
+ */
+public class JobInputException extends JobException {
+
+  /* the serial version UID */
+  private static final long serialVersionUID = 1673211096324899148L;
+
+  /**
+   * 
+   */
+  public JobInputException() {
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param arg0
+   */
+  public JobInputException(String arg0) {
+    super(arg0);
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param arg0
+   */
+  public JobInputException(Throwable arg0) {
+    super(arg0);
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param message
+   * @param cause
+   */
+  public JobInputException(String message, Throwable cause) {
+    super(message, cause);
+    // TODO Auto-generated constructor stub
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobQueueException.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobQueueException.java
new file mode 100644
index 0000000..13c6a4b
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobQueueException.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.structs.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Exception thrown when there is an error with the 
+ * {@link JobQueue}ing subsystem.
+ * </p>.
+ */
+public class JobQueueException extends Exception {
+
+  /* serial version UID */
+  private static final long serialVersionUID = -297153382304522924L;
+
+  /**
+   * 
+   */
+  public JobQueueException() {
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param arg0
+   */
+  public JobQueueException(String arg0) {
+    super(arg0);
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param arg0
+   */
+  public JobQueueException(Throwable arg0) {
+    super(arg0);
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param arg0
+   * @param arg1
+   */
+  public JobQueueException(String arg0, Throwable arg1) {
+    super(arg0, arg1);
+    // TODO Auto-generated constructor stub
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobRepositoryException.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobRepositoryException.java
new file mode 100644
index 0000000..67f44cc
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/JobRepositoryException.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.structs.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An exception thrown when persisting a {@link Job} to a {@link JobRepository}.
+ * </p>.
+ */
+public class JobRepositoryException extends Exception {
+
+  /* serial version UID */
+  private static final long serialVersionUID = 7431338125659704680L;
+
+  /**
+   * 
+   */
+  public JobRepositoryException() {
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param arg0
+   */
+  public JobRepositoryException(String arg0) {
+    super(arg0);
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param arg0
+   */
+  public JobRepositoryException(Throwable arg0) {
+    super(arg0);
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param arg0
+   * @param arg1
+   */
+  public JobRepositoryException(String arg0, Throwable arg1) {
+    super(arg0, arg1);
+    // TODO Auto-generated constructor stub
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/MesosFrameworkException.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/MesosFrameworkException.java
new file mode 100644
index 0000000..73eb83c
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/MesosFrameworkException.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.structs.exceptions;
+/**
+ * @author starchmd
+ * @version $Revision$
+ *
+ * An exception.
+ */
+public class MesosFrameworkException extends RuntimeException {
+
+    public MesosFrameworkException(String error) {
+        super(error);
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/MonitorException.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/MonitorException.java
new file mode 100644
index 0000000..2b4a16f
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/MonitorException.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.structs.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>An Exception thrown by the {@link Monitor}ing
+ * framework</p>.
+ */
+public class MonitorException extends Exception {
+
+  /* the serial version UID */
+  private static final long serialVersionUID = 626993879645497320L;
+
+  /**
+   * 
+   */
+  public MonitorException() {
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param arg0
+   */
+  public MonitorException(String arg0) {
+    super(arg0);
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param arg0
+   */
+  public MonitorException(Throwable arg0) {
+    super(arg0);
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param arg0
+   * @param arg1
+   */
+  public MonitorException(String arg0, Throwable arg1) {
+    super(arg0, arg1);
+    // TODO Auto-generated constructor stub
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/QueueManagerException.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/QueueManagerException.java
new file mode 100644
index 0000000..526bd8d
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/QueueManagerException.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.structs.exceptions;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>An Exception thrown by the {@link QueueManager}</p>
+ * 
+ */
+public class QueueManagerException extends Exception {
+
+	private static final long serialVersionUID = 7029919499578416147L;
+
+	public QueueManagerException() {
+		super();
+	}
+
+	public QueueManagerException(String msg) {
+		super(msg);
+	}
+
+	public QueueManagerException(Throwable throwable) {
+		super(throwable);
+	}
+
+	public QueueManagerException(String msg, Throwable throwable) {
+		super(msg, throwable);
+	}
+
+}
+
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/RepositoryException.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/RepositoryException.java
new file mode 100644
index 0000000..52ce827
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/RepositoryException.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.structs.exceptions;
+
+/**
+ * @author starchmd
+ * @version $Revision$
+ *
+ * <p>
+ * An exception thrown by the {@link BackendRepository} when an error occurs.
+ * </p>
+ */
+public class RepositoryException extends Exception {
+
+  /* serial version UID */
+  private static final long serialVersionUID = 4568261126290589269L;
+
+  /**
+   *
+   */
+  public RepositoryException() {}
+
+  /**
+   * @param message
+   */
+  public RepositoryException(String message) {
+    super(message);
+  }
+
+  /**
+   * @param cause
+   */
+  public RepositoryException(Throwable cause) {
+    super(cause);
+  }
+
+  /**
+   * @param message
+   * @param cause
+   */
+  public RepositoryException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/SchedulerException.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/SchedulerException.java
new file mode 100644
index 0000000..313a89f
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/structs/exceptions/SchedulerException.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.structs.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An exception thrown by the {@link Scheduler} when an error occurs.
+ * </p>
+ */
+public class SchedulerException extends Exception {
+
+  /* serial version UID */
+  private static final long serialVersionUID = 4568261126290589269L;
+
+  /**
+   * 
+   */
+  public SchedulerException() {
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param message
+   */
+  public SchedulerException(String message) {
+    super(message);
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param cause
+   */
+  public SchedulerException(Throwable cause) {
+    super(cause);
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param message
+   * @param cause
+   */
+  public SchedulerException(String message, Throwable cause) {
+    super(message, cause);
+    // TODO Auto-generated constructor stub
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/system/XmlRpcResourceManager.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/system/XmlRpcResourceManager.java
new file mode 100644
index 0000000..86983be
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/system/XmlRpcResourceManager.java
@@ -0,0 +1,434 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.system;
+
+//OODT imports
+import org.apache.oodt.cas.resource.scheduler.Scheduler;
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+import org.apache.oodt.cas.resource.structs.exceptions.JobQueueException;
+import org.apache.oodt.cas.resource.structs.exceptions.JobRepositoryException;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+import org.apache.oodt.cas.resource.structs.exceptions.QueueManagerException;
+import org.apache.oodt.cas.resource.structs.exceptions.SchedulerException;
+import org.apache.oodt.cas.resource.util.GenericResourceManagerObjectFactory;
+import org.apache.oodt.cas.resource.util.XmlRpcStructFactory;
+
+//APACHE imports
+import org.apache.xmlrpc.WebServer;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * An XML RPC-based Resource manager.
+ * </p>
+ * 
+ */
+public class XmlRpcResourceManager {
+
+    /* the port to run the XML RPC web server on, default is 2000 */
+    private int webServerPort = 2000;
+
+    /* our log stream */
+    private Logger LOG = Logger
+            .getLogger(XmlRpcResourceManager.class.getName());
+
+    /* our xml rpc web server */
+    private WebServer webServer = null;
+
+    /* our scheduler */
+    private Scheduler scheduler = null;
+
+    public XmlRpcResourceManager(int port) throws Exception {
+        // load properties from workflow manager properties file, if specified
+        if (System.getProperty("org.apache.oodt.cas.resource.properties") != null) {
+            String configFile = System
+                    .getProperty("org.apache.oodt.cas.resource.properties");
+            LOG.log(Level.INFO,
+                    "Loading Resource Manager Configuration Properties from: ["
+                            + configFile + "]");
+            System.getProperties().load(
+                    new FileInputStream(new File(configFile)));
+        }
+
+        String schedulerClassStr = System.getProperty(
+                "resource.scheduler.factory",
+                "org.apache.oodt.cas.resource.scheduler.LRUSchedulerFactory");
+
+        scheduler = GenericResourceManagerObjectFactory
+                .getSchedulerServiceFromFactory(schedulerClassStr);
+
+        // start up the scheduler
+        new Thread(scheduler).start();
+
+        webServerPort = port;
+
+        // start up the web server
+        webServer = new WebServer(webServerPort);
+        webServer.addHandler("resourcemgr", this);
+        webServer.start();
+
+        LOG.log(Level.INFO, "Resource Manager started by "
+                + System.getProperty("user.name", "unknown"));
+
+    }
+
+    public boolean isAlive() {
+        return true;
+    }
+    
+    /**
+     * Gets the number of Jobs in JobQueue
+     * @return Number of Jobs in JobQueue
+     * @throws JobRepositoryException On Any Exception
+     */
+    public int getJobQueueSize() throws JobRepositoryException {
+    	try {
+    		return this.scheduler.getJobQueue().getSize();
+    	}catch (Exception e) {
+    		throw new JobRepositoryException("Failed to get size of JobQueue : " + e.getMessage(), e);
+    	}
+    }
+    
+    /**
+     * Gets the max number of Jobs allowed in JobQueue
+     * @return Max number of Jobs
+     * @throws JobRepositoryException On Any Exception
+     */
+    public int getJobQueueCapacity() throws JobRepositoryException {
+    	try {
+    		return this.scheduler.getJobQueue().getCapacity();
+    	}catch (Exception e) {
+    		throw new JobRepositoryException("Failed to get capacity of JobQueue : " + e.getMessage(), e);
+    	}
+    }
+
+    public boolean isJobComplete(String jobId) throws JobRepositoryException {
+        JobSpec spec = scheduler.getJobQueue().getJobRepository().getJobById(
+                jobId);
+        return scheduler.getJobQueue().getJobRepository().jobFinished(spec);
+    }
+
+    public Hashtable getJobInfo(String jobId) throws JobRepositoryException {
+        JobSpec spec = null;
+
+        try {
+            spec = scheduler.getJobQueue().getJobRepository()
+                    .getJobById(jobId);
+        } catch (JobRepositoryException e) {
+            LOG.log(Level.WARNING,
+                    "Exception communicating with job repository for job: ["
+                            + jobId + "]: Message: " + e.getMessage());
+            throw new JobRepositoryException("Unable to get job: [" + jobId
+                    + "] from repository!");
+        }
+
+        return XmlRpcStructFactory.getXmlRpcJob(spec.getJob());
+    }
+
+    public String handleJob(Hashtable jobHash, Hashtable jobIn)
+            throws SchedulerException {
+        return genericHandleJob(jobHash, jobIn);
+    }
+
+    public String handleJob(Hashtable jobHash, int jobIn)
+            throws SchedulerException {
+        return genericHandleJob(jobHash, new Integer(jobIn));
+    }
+
+    public String handleJob(Hashtable jobHash, boolean jobIn)
+            throws SchedulerException {
+        return genericHandleJob(jobHash, new Boolean(jobIn));
+    }
+
+    public String handleJob(Hashtable jobHash, String jobIn)
+            throws SchedulerException {
+        return genericHandleJob(jobHash, jobIn);
+    }
+
+    public String handleJob(Hashtable jobHash, double jobIn)
+            throws SchedulerException {
+        return genericHandleJob(jobHash, new Double(jobIn));
+    }
+
+    public String handleJob(Hashtable jobHash, Date jobIn)
+            throws SchedulerException {
+        return genericHandleJob(jobHash, jobIn);
+    }
+
+    public String handleJob(Hashtable jobHash, Vector jobIn)
+            throws SchedulerException {
+        return genericHandleJob(jobHash, jobIn);
+    }
+
+    public String handleJob(Hashtable jobHash, byte[] jobIn)
+            throws SchedulerException {
+        return genericHandleJob(jobHash, jobIn);
+    }
+
+    public boolean handleJob(Hashtable jobHash, Hashtable jobIn, String urlStr)
+            throws JobExecutionException {
+        return genericHandleJob(jobHash, jobIn, urlStr);
+    }
+
+    public boolean handleJob(Hashtable jobHash, int jobIn, String urlStr)
+            throws JobExecutionException {
+        return genericHandleJob(jobHash, new Integer(jobIn), urlStr);
+    }
+
+    public boolean handleJob(Hashtable jobHash, boolean jobIn, String urlStr)
+            throws JobExecutionException {
+        return genericHandleJob(jobHash, new Boolean(jobIn), urlStr);
+    }
+
+    public boolean handleJob(Hashtable jobHash, String jobIn, String urlStr)
+            throws JobExecutionException {
+        return genericHandleJob(jobHash, jobIn, urlStr);
+    }
+
+    public boolean handleJob(Hashtable jobHash, double jobIn, String urlStr)
+            throws JobExecutionException {
+        return genericHandleJob(jobHash, new Double(jobIn), urlStr);
+    }
+
+    public boolean handleJob(Hashtable jobHash, Date jobIn, String urlStr)
+            throws JobExecutionException {
+        return genericHandleJob(jobHash, jobIn, urlStr);
+    }
+
+    public boolean handleJob(Hashtable jobHash, Vector jobIn, String urlStr)
+            throws JobExecutionException {
+        return genericHandleJob(jobHash, jobIn, urlStr);
+    }
+
+    public boolean handleJob(Hashtable jobHash, byte[] jobIn, String urlStr)
+            throws JobExecutionException {
+        return genericHandleJob(jobHash, jobIn, urlStr);
+    }
+
+    public List getNodes() throws MonitorException {
+        List resNodes = scheduler.getMonitor().getNodes();
+        return XmlRpcStructFactory.getXmlRpcResourceNodeList(resNodes);
+    }
+
+    public Hashtable getNodeById(String nodeId) throws MonitorException {
+        ResourceNode node = scheduler.getMonitor().getNodeById(nodeId);
+        return XmlRpcStructFactory.getXmlRpcResourceNode(node);
+
+    }
+
+    public boolean killJob(String jobId) throws MonitorException {
+        String resNodeId = scheduler.getBatchmgr().getExecutionNode(jobId);
+        if (resNodeId == null) {
+            LOG.log(Level.WARNING, "Attempt to kill job: [" + jobId
+                    + "]: cannot find execution node"
+                    + " (has the job already finished?)");
+            return false;
+        }
+        ResourceNode node = scheduler.getMonitor().getNodeById(resNodeId);
+        return scheduler.getBatchmgr().killJob(jobId, node);
+    }
+
+    public String getExecutionNode(String jobId) {
+        String execNode = scheduler.getBatchmgr().getExecutionNode(jobId);
+        if (execNode == null) {
+            LOG.log(Level.WARNING, "Job: [" + jobId
+                    + "] not currently executing on any known node");
+            return "";
+        } else
+            return execNode;
+    }
+
+    public List<String> getQueues() throws QueueManagerException {
+    	return new Vector<String>(this.scheduler.getQueueManager().getQueues());
+    }
+    
+    public boolean addQueue(String queueName) throws QueueManagerException {
+    	this.scheduler.getQueueManager().addQueue(queueName);
+    	return true;
+    }
+    
+    public boolean removeQueue(String queueName) throws QueueManagerException {
+    	this.scheduler.getQueueManager().removeQueue(queueName);
+    	return true;
+    }
+    
+    public boolean addNode(Hashtable hashNode) throws MonitorException {
+    	this.scheduler.getMonitor().addNode(XmlRpcStructFactory.getResourceNodeFromXmlRpc(hashNode));
+    	return true;
+    }
+    
+    public boolean removeNode(String nodeId) throws MonitorException {
+    	try{
+	    	for(String queueName: this.getQueuesWithNode(nodeId)){
+	    		this.removeNodeFromQueue(nodeId, queueName);
+	    	}
+	    	this.scheduler.getMonitor().removeNodeById(nodeId);
+    	}catch(Exception e){
+    		throw new MonitorException(e.getMessage(), e);
+    	}
+    	
+    	return true;
+    }
+    
+    public boolean addNodeToQueue(String nodeId, String queueName) throws QueueManagerException {
+    	this.scheduler.getQueueManager().addNodeToQueue(nodeId, queueName);
+    	return true;
+    }
+    
+    public boolean removeNodeFromQueue(String nodeId, String queueName) throws QueueManagerException {
+    	this.scheduler.getQueueManager().removeNodeFromQueue(nodeId, queueName);
+    	return true;
+    }
+    
+    public List<String> getNodesInQueue(String queueName) throws QueueManagerException {
+    	return new Vector<String>(this.scheduler.getQueueManager().getNodes(queueName));
+    }
+    
+    public List<String> getQueuesWithNode(String nodeId) throws QueueManagerException {
+    	return new Vector<String>(this.scheduler.getQueueManager().getQueues(nodeId));
+    }
+    
+    public boolean shutdown(){
+      if (this.webServer != null) {
+        this.webServer.shutdown();
+        this.webServer = null;
+        return true;
+    } else
+        return false;      
+    }
+    
+    public String getNodeLoad(String nodeId) throws MonitorException{
+    	ResourceNode node = this.scheduler.getMonitor().getNodeById(nodeId);
+    	int capacity = node.getCapacity();
+    	int load = (this.scheduler.getMonitor().getLoad(node)) * -1 + capacity;
+    	return load + "/" + capacity;
+    }
+    
+    public static void main(String[] args) throws Exception {
+        int portNum = -1;
+        String usage = "XmlRpcResourceManager --portNum <port number for xml rpc service>\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--portNum")) {
+                portNum = Integer.parseInt(args[++i]);
+            }
+        }
+
+        if (portNum == -1) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        XmlRpcResourceManager manager = new XmlRpcResourceManager(portNum);
+
+        for (;;)
+            try {
+                Thread.currentThread().join();
+            } catch (InterruptedException ignore) {
+            }
+    }
+    
+    public boolean setNodeCapacity(String nodeId, int capacity){
+    	try{
+    		this.scheduler.getMonitor().getNodeById(nodeId).setCapacity(capacity);
+    	}catch (MonitorException e){
+    		LOG.log(Level.WARNING, "Exception setting capacity on node "
+    				+ nodeId + ": " + e.getMessage());
+    		return false;
+    	}
+    	return true;
+    }
+
+    private String genericHandleJob(Hashtable jobHash, Object jobIn)
+            throws SchedulerException {
+
+        Job exec = XmlRpcStructFactory.getJobFromXmlRpc(jobHash);
+        JobInput in = GenericResourceManagerObjectFactory
+                .getJobInputFromClassName(exec.getJobInputClassName());
+        in.read(jobIn);
+
+        JobSpec spec = new JobSpec(in, exec);
+
+        // queue the job up
+        String jobId = null;
+
+        try {
+            jobId = scheduler.getJobQueue().addJob(spec);
+        } catch (JobQueueException e) {
+            LOG.log(Level.WARNING, "JobQueue exception adding job: Message: "
+                    + e.getMessage());
+            throw new SchedulerException(e.getMessage());
+        }
+        return jobId;
+    }
+
+    private boolean genericHandleJob(Hashtable jobHash, Object jobIn,
+            String urlStr) throws JobExecutionException {
+        Job exec = XmlRpcStructFactory.getJobFromXmlRpc(jobHash);
+        JobInput in = GenericResourceManagerObjectFactory
+                .getJobInputFromClassName(exec.getJobInputClassName());
+        in.read(jobIn);
+
+        JobSpec spec = new JobSpec(in, exec);
+
+        URL remoteUrl = safeGetUrlFromString(urlStr);
+        ResourceNode remoteNode = null;
+
+        try {
+            remoteNode = scheduler.getMonitor().getNodeByURL(remoteUrl);
+        } catch (MonitorException e) {
+        }
+
+        if (remoteNode != null) {
+            return scheduler.getBatchmgr().executeRemotely(spec, remoteNode);
+        } else
+            return false;
+    }
+
+    private URL safeGetUrlFromString(String urlStr) {
+        URL url = null;
+
+        try {
+            url = new URL(urlStr);
+        } catch (MalformedURLException e) {
+            LOG.log(Level.WARNING, "Error converting string: [" + urlStr
+                    + "] to URL object: Message: " + e.getMessage());
+        }
+
+        return url;
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/system/XmlRpcResourceManagerClient.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/system/XmlRpcResourceManagerClient.java
new file mode 100644
index 0000000..0fb0520
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/system/XmlRpcResourceManagerClient.java
@@ -0,0 +1,505 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.system;
+
+//APACHE imports
+import org.apache.xmlrpc.CommonsXmlRpcTransportFactory;
+import org.apache.xmlrpc.XmlRpcClient;
+import org.apache.xmlrpc.XmlRpcException;
+
+//OODTimports
+import org.apache.oodt.cas.cli.CmdLineUtility;
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.JobStatus;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+import org.apache.oodt.cas.resource.structs.exceptions.JobRepositoryException;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+import org.apache.oodt.cas.resource.structs.exceptions.QueueManagerException;
+import org.apache.oodt.cas.resource.util.XmlRpcStructFactory;
+
+//JDK imports
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.io.FileInputStream;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * The XML RPC based resource manager client.
+ * </p>
+ * 
+ */
+public class XmlRpcResourceManagerClient {
+
+    /* our xml rpc client */
+    private XmlRpcClient client = null;
+
+    /* our log stream */
+    private static Logger LOG = Logger
+            .getLogger(XmlRpcResourceManagerClient.class.getName());
+
+    /* resource manager url */
+    private URL resMgrUrl = null;
+
+    /**
+     * <p>
+     * Constructs a new XmlRpcResourceManagerClient with the given
+     * <code>url</code>.
+     * </p>
+     * 
+     * @param url
+     *            The url pointer to the xml rpc resource manager service.
+     */
+    public XmlRpcResourceManagerClient(URL url) {
+        // set up the configuration, if there is any
+        if (System.getProperty("org.apache.oodt.cas.resource.properties") != null) {
+            String configFile = System
+                    .getProperty("org.apache.oodt.cas.resource.properties");
+            LOG.log(Level.INFO,
+                    "Loading Resource Manager Configuration Properties from: ["
+                            + configFile + "]");
+            try {
+                System.getProperties().load(
+                        new FileInputStream(new File(configFile)));
+            } catch (Exception e) {
+                LOG.log(Level.INFO,
+                        "Error loading configuration properties from: ["
+                                + configFile + "]");
+            }
+
+        }
+
+        CommonsXmlRpcTransportFactory transportFactory = new CommonsXmlRpcTransportFactory(
+                url);
+        int connectionTimeoutMins = Integer
+                .getInteger(
+                        "org.apache.oodt.cas.resource.system.xmlrpc.connectionTimeout.minutes",
+                        20).intValue();
+        int connectionTimeout = connectionTimeoutMins * 60 * 1000;
+        int requestTimeoutMins = Integer
+                .getInteger(
+                        "org.apache.oodt.cas.resource.system.xmlrpc.requestTimeout.minutes",
+                        60).intValue();
+        int requestTimeout = requestTimeoutMins * 60 * 1000;
+        transportFactory.setConnectionTimeout(connectionTimeout);
+        transportFactory.setTimeout(requestTimeout);
+        client = new XmlRpcClient(url, transportFactory);
+        resMgrUrl = url;
+    }
+
+    public static void main(String[] args) {
+       CmdLineUtility cmdLineUtility = new CmdLineUtility();
+       cmdLineUtility.run(args);
+    }
+
+    public boolean isJobComplete(String jobId) throws JobRepositoryException {
+        Vector argList = new Vector();
+        argList.add(jobId);
+
+        boolean complete = false;
+
+        try {
+            complete = ((Boolean) client.execute("resourcemgr.isJobComplete",
+                    argList)).booleanValue();
+        } catch (XmlRpcException e) {
+            throw new JobRepositoryException(e.getMessage(), e);
+        } catch (IOException e) {
+            throw new JobRepositoryException(e.getMessage(), e);
+        }
+
+        return complete;
+    }
+
+    public Job getJobInfo(String jobId) throws JobRepositoryException {
+        Vector argList = new Vector();
+        argList.add(jobId);
+
+        Hashtable jobHash = null;
+
+        try {
+            jobHash = (Hashtable) client.execute("resourcemgr.getJobInfo",
+                    argList);
+        } catch (XmlRpcException e) {
+            throw new JobRepositoryException(e.getMessage(), e);
+        } catch (IOException e) {
+            throw new JobRepositoryException(e.getMessage(), e);
+        }
+
+        return XmlRpcStructFactory.getJobFromXmlRpc(jobHash);
+    }
+
+    public boolean isAlive() {
+        Vector argList = new Vector();
+
+        try {
+            return ((Boolean) client.execute("resourcemgr.isAlive", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            return false;
+        } catch (IOException e) {
+            return false;
+        }
+
+    }
+
+    /**
+     * Gets the number of Jobs in JobQueue
+     * @return Number of Jobs in JobQueue
+     * @throws JobRepositoryException On Any Exception
+     */
+    public int getJobQueueSize() throws JobRepositoryException {
+        try {
+            Vector argList = new Vector();
+            return ((Integer) client.execute("resourcemgr.getJobQueueSize", argList));
+        } catch (Exception e) {
+            throw new JobRepositoryException("Failed to get JobQueue from server : " + e.getMessage(), e);
+        }
+    }
+    
+    /**
+     * Gets the max number of Jobs allowed in JobQueue
+     * @return Max number of Jobs
+     * @throws JobRepositoryException On Any Exception
+     */
+    public int getJobQueueCapacity() throws JobRepositoryException {
+        try {
+            Vector argList = new Vector();
+            return ((Integer) client.execute("resourcemgr.getJobQueueCapacity", argList));
+        } catch (Exception e) {
+            throw new JobRepositoryException("Failed to get JobQueue capacity from server : " + e.getMessage(), e);
+        }
+    }
+    
+    public boolean killJob(String jobId) {
+        Vector argList = new Vector();
+        argList.add(jobId);
+
+        try {
+            return ((Boolean) client.execute("resourcemgr.killJob", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            return false;
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    public String getExecutionNode(String jobId) {
+        Vector argList = new Vector();
+        argList.add(jobId);
+
+        try {
+            return (String) client.execute("resourcemgr.getExecutionNode", argList);
+        } catch (XmlRpcException e) {
+            return null;
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
+    public String submitJob(Job exec, JobInput in) throws JobExecutionException {
+        Vector argList = new Vector();
+        argList.add(XmlRpcStructFactory.getXmlRpcJob(exec));
+        argList.add(in.write());
+
+        LOG.log(Level.FINEST, argList.toString());
+
+        String jobId = null;
+
+        try {
+            jobId = (String) client.execute("resourcemgr.handleJob", argList);
+        } catch (XmlRpcException e) {
+            throw new JobExecutionException(e.getMessage(), e);
+        } catch (IOException e) {
+            throw new JobExecutionException(e.getMessage(), e);
+        }
+
+        return jobId;
+
+    }
+
+    public boolean submitJob(Job exec, JobInput in, URL hostUrl)
+            throws JobExecutionException {
+        Vector argList = new Vector();
+        argList.add(XmlRpcStructFactory.getXmlRpcJob(exec));
+        argList.add(in.write());
+        argList.add(hostUrl.toString());
+
+        boolean success = false;
+
+        try {
+            success = ((Boolean) client.execute("resourcemgr.handleJob",
+                    argList)).booleanValue();
+        } catch (XmlRpcException e) {
+            throw new JobExecutionException(e.getMessage(), e);
+        } catch (IOException e) {
+            throw new JobExecutionException(e.getMessage(), e);
+        }
+
+        return success;
+
+    }
+
+    public List getNodes() throws MonitorException {
+        Vector argList = new Vector();
+
+        Vector nodeVector = null;
+
+        try {
+            nodeVector = (Vector) client.execute("resourcemgr.getNodes",
+                    argList);
+        } catch (XmlRpcException e) {
+            throw new MonitorException(e.getMessage(), e);
+        } catch (IOException e) {
+            throw new MonitorException(e.getMessage(), e);
+        }
+
+        return XmlRpcStructFactory.getResourceNodeListFromXmlRpc(nodeVector);
+
+    }
+
+    public ResourceNode getNodeById(String nodeId) throws MonitorException {
+        Vector argList = new Vector();
+        argList.add(nodeId);
+
+        Hashtable resNodeHash = null;
+
+        try {
+            resNodeHash = (Hashtable) client.execute("resourcemgr.getNodeById",
+                    argList);
+        } catch (XmlRpcException e) {
+            throw new MonitorException(e.getMessage(), e);
+        } catch (IOException e) {
+            throw new MonitorException(e.getMessage(), e);
+        }
+
+        return XmlRpcStructFactory.getResourceNodeFromXmlRpc(resNodeHash);
+
+    }
+
+    /**
+     * @return the resMgrUrl
+     */
+    public URL getResMgrUrl() {
+        return resMgrUrl;
+    }
+
+    /**
+     * @param resMgrUrl
+     *            the resMgrUrl to set
+     */
+    public void setResMgrUrl(URL resMgrUrl) {
+        this.resMgrUrl = resMgrUrl;
+    }
+
+    /**
+     * Creates a queue with the given name
+     * @param queueName The name of the queue to be created
+     * @throws QueueManagerException on any error
+     */
+    public void addQueue(String queueName) throws QueueManagerException {
+        try {
+            Vector<Object> argList = new Vector<Object>();
+            argList.add(queueName);
+            client.execute("resourcemgr.addQueue", argList);
+        }catch (Exception e) {
+            throw new QueueManagerException(e.getMessage(), e);
+        }
+    }
+    
+    /**
+     * Removes the queue with the given name
+     * @param queueName The name of the queue to be removed
+     * @throws QueueManagerException on any error
+     */
+    public void removeQueue(String queueName) throws QueueManagerException {
+        try {
+            Vector<Object> argList = new Vector<Object>();
+            argList.add(queueName);
+            client.execute("resourcemgr.removeQueue", argList);
+        }catch (Exception e) {
+            throw new QueueManagerException(e.getMessage(), e);
+        }
+    }
+    
+    /**
+     * Adds a node
+     * @param node The node to be added
+     * @throws MonitorException on any error
+     */
+    public void addNode(ResourceNode node) throws MonitorException {
+        try {
+            Vector<Object> argList = new Vector<Object>();
+            argList.add(XmlRpcStructFactory.getXmlRpcResourceNode(node));
+            client.execute("resourcemgr.addNode", argList);
+        }catch (Exception e) {
+            throw new MonitorException(e.getMessage(), e);
+        }
+    }
+    
+    /**
+     * Removes the node with the given id
+     * @param nodeId The id of the node to be removed
+     * @throws MonitorException on any error
+     */
+    public void removeNode(String nodeId) throws MonitorException {
+        try {
+            Vector<Object> argList = new Vector<Object>();
+            argList.add(nodeId);
+            client.execute("resourcemgr.removeNode", argList);
+        }catch (Exception e) {
+            throw new MonitorException(e.getMessage(), e);
+        }
+    }
+    
+    public void setNodeCapacity(String nodeId, int capacity) throws MonitorException{
+    	try{
+    		Vector<Object> argList = new Vector<Object>();
+            argList.add(nodeId);
+            argList.add(new Integer(capacity));
+            client.execute("resourcemgr.setNodeCapacity", argList);
+    	}catch (Exception e){
+    		throw new MonitorException(e.getMessage(), e);
+    	}
+    }
+    
+    /**
+     * Addes the node with given id to the queue with the given name
+     * @param nodeId The id of the node to be added to the given queueName
+     * @param queueName The name of the queue to add the given node
+     * @throws QueueManagerException on any error
+     */
+    public void addNodeToQueue(String nodeId, String queueName) throws QueueManagerException {
+        try {
+            Vector<Object> argList = new Vector<Object>();
+            argList.add(nodeId);
+            argList.add(queueName);
+            client.execute("resourcemgr.addNodeToQueue", argList);
+        }catch (Exception e) {
+            throw new QueueManagerException(e.getMessage(), e);
+        }
+    }
+    
+    /**
+     * Remove the node with the given id from the queue with the given name
+     * @param nodeId The id of the node to be remove from the given queueName
+     * @param queueName The name of the queue from which to remove the given node
+     * @throws QueueManagerException on any error
+     */
+    public void removeNodeFromQueue(String nodeId, String queueName) throws QueueManagerException {
+        try {
+            Vector<Object> argList = new Vector<Object>();
+            argList.add(nodeId);
+            argList.add(queueName);
+            client.execute("resourcemgr.removeNodeFromQueue", argList);
+        }catch (Exception e) {
+            throw new QueueManagerException(e.getMessage(), e);
+        }
+    }
+    
+    /**
+     * Gets a list of currently supported queue names
+     * @return A list of currently supported queue names
+     * @throws QueueManagerException on any error
+     */
+    public List<String> getQueues() throws QueueManagerException {
+        try {
+            Vector<Object> argList = new Vector<Object>();
+            return (List<String>) client.execute("resourcemgr.getQueues", argList);
+        }catch (Exception e) {
+            throw new QueueManagerException(e.getMessage(), e);
+        }
+    }
+    
+    /**
+     * Gets a list of ids of the nodes in the given queue
+     * @param queueName The name of the queue to get node ids from
+     * @return List of node ids in the given queueName
+     * @throws QueueManagerException on any error
+     */
+    public List<String> getNodesInQueue(String queueName) throws QueueManagerException {
+        try {
+            Vector<Object> argList = new Vector<Object>();
+            argList.add(queueName);
+            return (List<String>) client.execute("resourcemgr.getNodesInQueue", argList);
+        }catch (Exception e) {
+            throw new QueueManagerException(e.getMessage(), e);
+        }
+    }
+    
+    /**
+     * Gets a list of queues which contain the node with the given nodeId
+     * @param nodeId The id of the node to get queues it belongs to
+     * @return List of queues which contain the give node
+     * @throws QueueManagerException on any error
+     */
+    public List<String> getQueuesWithNode(String nodeId) throws QueueManagerException {
+        try {
+            Vector<Object> argList = new Vector<Object>();
+            argList.add(nodeId);
+            return (List<String>) client.execute("resourcemgr.getQueuesWithNode", argList);
+        }catch (Exception e) {
+            throw new QueueManagerException(e.getMessage(), e);
+        }
+    }
+    
+    /**
+     * Report on the load of the requested node
+     * @param nodeId The id of the node to be polled
+     * @return A String showing a fraction of the loads node over its capacity
+     * @throws MonitorException on any error
+     */
+    public String getNodeLoad(String nodeId) throws MonitorException{
+    	try{
+	    	Vector<Object> argList = new Vector<Object>();
+	    	argList.add(nodeId);
+	    	return (String)client.execute("resourcemgr.getNodeLoad", argList);
+    	}catch(Exception e){
+    		throw new MonitorException(e.getMessage(), e);
+    	}
+    }
+
+  private static String getReadableJobStatus(String status) {
+    if (status.equals(JobStatus.SUCCESS)) {
+      return "SUCCESS";
+    } else if (status.equals(JobStatus.FAILURE)) {
+      return "FAILURE";
+    } else if (status.equals(JobStatus.EXECUTED)) {
+      return "EXECUTED";
+    } else if (status.equals(JobStatus.QUEUED)) {
+      return "QUEUED";
+    } else if (status.equals(JobStatus.SCHEDULED)) {
+      return "SCHEDULED";
+    } else if (status.equals(JobStatus.KILLED)) {
+      return "KILLED";
+    } else
+      return null;
+  }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/system/extern/XmlRpcBatchStub.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/system/extern/XmlRpcBatchStub.java
new file mode 100644
index 0000000..6643951
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/system/extern/XmlRpcBatchStub.java
@@ -0,0 +1,241 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.system.extern;
+
+//JDK imports
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.JobInstance;
+import org.apache.oodt.cas.resource.structs.exceptions.JobException;
+import org.apache.oodt.cas.resource.structs.exceptions.JobInputException;
+import org.apache.oodt.cas.resource.util.GenericResourceManagerObjectFactory;
+import org.apache.oodt.cas.resource.util.XmlRpcStructFactory;
+
+//APACHE imports
+import org.apache.xmlrpc.WebServer;
+
+/**
+ * @author woollard
+ * @version $Revision$
+ * 
+ * <p>
+ * An XML RPC-based Batch Submission System.
+ * </p>
+ * 
+ */
+public class XmlRpcBatchStub {
+
+    /* the port to run the XML RPC web server on, default is 2000 */
+    private int webServerPort = 2000;
+
+    /* our xml rpc web server */
+    private WebServer webServer = null;
+
+    /* our log stream */
+    private static Logger LOG = Logger.getLogger(XmlRpcBatchStub.class
+            .getName());
+
+    private static Map jobThreadMap = null;
+
+    public XmlRpcBatchStub(int port) throws Exception {
+        webServerPort = port;
+
+        // start up the web server
+        webServer = new WebServer(webServerPort);
+        webServer.addHandler("batchstub", this);
+        webServer.start();
+
+        jobThreadMap = new HashMap();
+
+        LOG.log(Level.INFO, "XmlRpc Batch Stub started by "
+                + System.getProperty("user.name", "unknown"));
+    }
+
+    public boolean isAlive() {
+        return true;
+    }
+
+    public boolean executeJob(Hashtable jobHash, Hashtable jobInput)
+            throws JobException {
+        return genericExecuteJob(jobHash, jobInput);
+    }
+
+    public boolean executeJob(Hashtable jobHash, Date jobInput)
+            throws JobException {
+        return genericExecuteJob(jobHash, jobInput);
+    }
+
+    public boolean executeJob(Hashtable jobHash, double jobInput)
+            throws JobException {
+        return genericExecuteJob(jobHash, new Double(jobInput));
+    }
+
+    public boolean executeJob(Hashtable jobHash, int jobInput)
+            throws JobException {
+        return genericExecuteJob(jobHash, new Integer(jobInput));
+    }
+
+    public boolean executeJob(Hashtable jobHash, boolean jobInput)
+            throws JobException {
+        return genericExecuteJob(jobHash, new Boolean(jobInput));
+    }
+
+    public boolean executeJob(Hashtable jobHash, Vector jobInput)
+            throws JobException {
+        return genericExecuteJob(jobHash, jobInput);
+    }
+
+    public boolean executeJob(Hashtable jobHash, byte[] jobInput)
+            throws JobException {
+        return genericExecuteJob(jobHash, jobInput);
+    }
+
+    public synchronized boolean killJob(Hashtable jobHash) {
+        Job job = XmlRpcStructFactory.getJobFromXmlRpc(jobHash);
+        Thread jobThread = (Thread) jobThreadMap.get(job.getId());
+        if (jobThread == null) {
+            LOG.log(Level.WARNING, "Job: [" + job.getId()
+                    + "] not managed by this batch stub");
+            return false;
+        }
+
+        // okay, so interrupt it, which should cause it to stop
+        jobThread.interrupt();
+        return true;
+    }
+
+    private boolean genericExecuteJob(Hashtable jobHash, Object jobInput)
+            throws JobException {
+        JobInstance exec = null;
+        JobInput in = null;
+        try {
+            Job job = XmlRpcStructFactory.getJobFromXmlRpc(jobHash);
+
+            LOG.log(Level.INFO, "stub attempting to execute class: ["
+                    + job.getJobInstanceClassName() + "]");
+
+            exec = GenericResourceManagerObjectFactory
+                    .getJobInstanceFromClassName(job.getJobInstanceClassName());
+            in = GenericResourceManagerObjectFactory
+                    .getJobInputFromClassName(job.getJobInputClassName());
+
+            // load the input obj
+            in.read(jobInput);
+
+            // create threaded job
+            // so that it can be interrupted
+            RunnableJob runner = new RunnableJob(exec, in);
+            Thread threadRunner = new Thread(runner);
+            /* save this job thread in a map so we can kill it later */
+            jobThreadMap.put(job.getId(), threadRunner);
+            threadRunner.start();
+
+            try {
+                threadRunner.join();
+            } catch (InterruptedException e) {
+                LOG.log(Level.INFO, "Current job: [" + job.getName()
+                        + "]: killed: exiting gracefully");
+                synchronized (jobThreadMap) {
+                    Thread endThread = (Thread) jobThreadMap.get(job.getId());
+                    if (endThread != null)
+                        endThread = null;
+                }
+                return false;
+            }
+
+            synchronized (jobThreadMap) {
+                Thread endThread = (Thread) jobThreadMap.get(job.getId());
+                if (endThread != null)
+                    endThread = null;
+            }
+
+            return runner.wasSuccessful();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        int portNum = -1;
+        String usage = "XmlRpcBatchStub --portNum <port number for xml rpc service>\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--portNum")) {
+                portNum = Integer.parseInt(args[++i]);
+            }
+        }
+
+        if (portNum == -1) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        XmlRpcBatchStub stub = new XmlRpcBatchStub(portNum);
+
+        for (;;)
+            try {
+                Thread.currentThread().join();
+            } catch (InterruptedException ignore) {
+            }
+    }
+
+    private class RunnableJob implements Runnable {
+
+        private JobInput in;
+
+        private JobInstance job;
+
+        private boolean successful;
+        
+        public RunnableJob(JobInstance job, JobInput in) {
+            this.job = job;
+            this.in = in;
+            this.successful = false;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see java.lang.Runnable#run()
+         */
+        public void run() {
+            try {
+                this.successful = job.execute(in);
+            } catch (JobInputException e) {
+                e.printStackTrace();
+                this.successful = false;
+            }
+
+        }
+
+        public boolean wasSuccessful() {
+        	return this.successful;
+        }
+    }
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/tools/JobSubmitter.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/tools/JobSubmitter.java
new file mode 100644
index 0000000..9df69e1
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/tools/JobSubmitter.java
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.tools;
+
+//JDK imports
+import java.io.File;
+import java.io.FileFilter;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+import org.apache.oodt.cas.resource.system.XmlRpcResourceManagerClient;
+import org.apache.oodt.cas.resource.util.JobBuilder;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A tool to submit {@link Job} files generated in a particular directory to the
+ * Resource Manager.
+ * </p>.
+ */
+public final class JobSubmitter {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(JobSubmitter.class
+            .getName());
+
+    /* our res mgr client */
+    private XmlRpcResourceManagerClient client = null;
+
+    /* our job file filter */
+    private static final FileFilter JOB_FILE_FILTER = new FileFilter() {
+
+        public boolean accept(File file) {
+            return file.isFile() && file.getName().endsWith(".xml");
+        }
+
+    };
+
+    public JobSubmitter(URL rUrl) {
+        client = new XmlRpcResourceManagerClient(rUrl);
+    }
+
+    public void submitJobFiles(File jobFileDir) {
+        File[] jobFiles = jobFileDir.listFiles(JOB_FILE_FILTER);
+
+        if (jobFiles != null && jobFiles.length > 0) {
+            for (int i = 0; i < jobFiles.length; i++) {
+                try {
+                    String id = submitJobFile(jobFiles[i]);
+                    LOG.log(Level.INFO, "Job Submitted: id: [" + id + "]");
+
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    LOG.log(Level.WARNING, "Exception submitting job file: ["
+                            + jobFiles[i] + "]: Message: " + e.getMessage());
+                }
+            }
+        }
+
+    }
+
+    public void submitJobFiles(String jobFileDirPath) {
+        submitJobFiles(new File(jobFileDirPath));
+    }
+
+    public String submitJobFile(File jobFile) throws JobExecutionException {
+        return submitJobFile(jobFile.getAbsolutePath());
+    }
+
+    public String submitJobFile(String jobFilePath)
+            throws JobExecutionException {
+        JobSpec spec = JobBuilder.buildJobSpec(jobFilePath);
+        return submitJob(spec);
+    }
+
+    public static void main(String[] args) throws Exception {
+        String resMgrUrlStr = null;
+        String jobFilePath = null, jobFileDirPath = null;
+        String usage = "JobSubmitter --rUrl <resource mgr url> [options]\n"
+                + "--file <job file path>\n" + "[--dir <job file dir path>]\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--rUrl")) {
+                resMgrUrlStr = args[++i];
+            } else if (args[i].equals("--file")) {
+                jobFilePath = args[++i];
+            } else if (args[i].equals("--dir")) {
+                jobFileDirPath = args[++i];
+            }
+        }
+
+        if (resMgrUrlStr == null
+                || (jobFilePath == null && jobFileDirPath == null)) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        JobSubmitter submitter = new JobSubmitter(new URL(resMgrUrlStr));
+
+        // if they specified --dir it takes precedence
+        if (jobFileDirPath != null) {
+            submitter.submitJobFiles(jobFileDirPath);
+        } else {
+            String jobId = submitter.submitJobFile(jobFilePath);
+            LOG.log(Level.INFO, "Job Submitted: id: [" + jobId + "]");
+        }
+
+    }
+
+    private String submitJob(JobSpec spec) throws JobExecutionException {
+        return client.submitJob(spec.getJob(), spec.getIn());
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/tools/RunDirJobSubmitter.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/tools/RunDirJobSubmitter.java
new file mode 100644
index 0000000..a34741b
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/tools/RunDirJobSubmitter.java
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.tools;
+
+//JDK imports
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.NameValueJobInput;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+import org.apache.oodt.cas.resource.system.XmlRpcResourceManagerClient;
+import org.apache.oodt.cas.resource.util.JobBuilder;
+
+/**
+ * @author cecilia
+ * @version $Revision$
+ * 
+ * <p>
+ * A tool that creates a job and send it to the Resource Manager. The list of
+ * jobs created has a 1-to-1 correspondence to the list of directory names
+ * </p>.
+ */
+public final class RunDirJobSubmitter {
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(RunDirJobSubmitter.class
+            .getName());
+
+    /* our res mgr client */
+    private XmlRpcResourceManagerClient client = null;
+
+    public RunDirJobSubmitter(URL rUrl) {
+        client = new XmlRpcResourceManagerClient(rUrl);
+    }
+
+    public void submitRunDirJobFile(String jobFname, String inputFname)
+            throws JobExecutionException {
+
+        // -------------------------------------------------------------
+        // check validity of given job filename and input filename
+        // -------------------------------------------------------------
+
+        File jobFile = new File(jobFname);
+        if (!jobFile.exists()) {
+            // file doesn't exist
+            throw new JobExecutionException("RunDirJobSubmitter: input file "
+                    + jobFname + " does not exist.");
+        } else if (!jobFile.isFile()) {
+            // file is a directory
+            throw new JobExecutionException("RunDirJobSubmitter: input file "
+                    + jobFname + " is not a file.");
+        }
+
+        File f = new File(inputFname);
+        if (!f.exists()) {
+            // file doesn't exist
+            throw new JobExecutionException("RunDirJobSubmitter: input file "
+                    + inputFname + " does not exist.");
+        } else if (!f.isFile()) {
+            // file is a directory
+            throw new JobExecutionException("RunDirJobSubmitter: input file "
+                    + inputFname + " is not a file.");
+        }
+
+        // ----------------------------------------------------------------
+        // create a default JobSpec
+        // ----------------------------------------------------------------
+        JobSpec spec = JobBuilder.buildJobSpec(jobFile.getAbsolutePath());
+        Job job = spec.getJob();
+        NameValueJobInput jobInput = (NameValueJobInput) spec.getIn();
+
+        // ----------------------------------------------------------------
+        // open the file to read. traverse through the list of directories
+        // name given & override the default Job's runDirName value with the
+        // directory name. then submit the Job.
+        // ----------------------------------------------------------------
+
+        try {
+            BufferedReader in = new BufferedReader(new FileReader(inputFname));
+            if (!in.ready())
+                throw new IOException();
+
+            String line = null;
+            String jobId = null;
+            while ((line = in.readLine()) != null) {
+
+                // overwrite the runDirName
+                jobInput.setNameValuePair("runDirName", line);
+
+                jobId = submitJob(job, jobInput);
+                LOG.log(Level.INFO, "Job Submitted: id: [" + jobId + "]");
+            }
+
+            in.close();
+        } catch (IOException e) {
+            throw new JobExecutionException("RunDirJobSubmitter: " + e);
+        }
+
+    }
+
+    public static void main(String[] args) throws Exception {
+        String resMgrUrlStr = null;
+        String jobFileName = null;
+        String runDirFileName = null;
+
+        String usage = "RunDirJobSubmitter --rUrl <resource mgr url> "
+                + "--jobFile <input job file> "
+                + "--runDirFile <input running directories file> \n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--rUrl")) {
+                resMgrUrlStr = args[++i];
+            } else if (args[i].equals("--jobFile")) {
+                jobFileName = args[++i];
+            } else if (args[i].equals("--runDirFile")) {
+                runDirFileName = args[++i];
+            }
+        }
+
+        if (resMgrUrlStr == null || jobFileName == null
+                || runDirFileName == null) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        RunDirJobSubmitter submitter = new RunDirJobSubmitter(new URL(
+                resMgrUrlStr));
+        submitter.submitRunDirJobFile(jobFileName, runDirFileName);
+    }
+
+    private String submitJob(Job job, JobInput jobInput)
+            throws JobExecutionException {
+        return client.submitJob(job, jobInput);
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/Configurable.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/Configurable.java
new file mode 100644
index 0000000..510d3c5
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/Configurable.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.util;
+
+//JDK imports
+import java.util.Properties;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Classes defining this interface define how to configure themselves by
+ * accepting a {@link Properties} object
+ * </p>.
+ */
+public interface Configurable {
+
+  /**
+   * Configure the object with the given {@link Properties}.
+   * 
+   * @param props
+   *          Properties to use to configure the Object.
+   */
+  public void configure(Properties props);
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/GenericResourceManagerObjectFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/GenericResourceManagerObjectFactory.java
new file mode 100644
index 0000000..3759e50
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/GenericResourceManagerObjectFactory.java
@@ -0,0 +1,461 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.util;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.resource.batchmgr.Batchmgr;
+import org.apache.oodt.cas.resource.batchmgr.BatchmgrFactory;
+import org.apache.oodt.cas.resource.jobqueue.JobQueue;
+import org.apache.oodt.cas.resource.jobqueue.JobQueueFactory;
+import org.apache.oodt.cas.resource.jobrepo.JobRepository;
+import org.apache.oodt.cas.resource.jobrepo.JobRepositoryFactory;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.monitor.MonitorFactory;
+import org.apache.oodt.cas.resource.monitor.ganglia.loadcalc.LoadCalculator;
+import org.apache.oodt.cas.resource.monitor.ganglia.loadcalc.LoadCalculatorFactory;
+import org.apache.oodt.cas.resource.mux.BackendRepository;
+import org.apache.oodt.cas.resource.mux.BackendRepositoryFactory;
+import org.apache.oodt.cas.resource.noderepo.NodeRepository;
+import org.apache.oodt.cas.resource.noderepo.NodeRepositoryFactory;
+import org.apache.oodt.cas.resource.queuerepo.QueueRepository;
+import org.apache.oodt.cas.resource.queuerepo.QueueRepositoryFactory;
+import org.apache.oodt.cas.resource.scheduler.Scheduler;
+import org.apache.oodt.cas.resource.scheduler.SchedulerFactory;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.JobInstance;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * Generic object creation facilities for the Resource Manager.
+ * </p>
+ */
+public final class GenericResourceManagerObjectFactory {
+
+  /* our log stream */
+  private static final Logger LOG = Logger
+      .getLogger(GenericResourceManagerObjectFactory.class.getName());
+
+  private GenericResourceManagerObjectFactory() throws InstantiationException {
+    throw new InstantiationException("Don't construct factory classes!");
+  }
+
+  /**
+   * Constructs a new {@link JobInput} implementation from the given
+   * <code>className</code>.
+   *
+   * @param className
+   *          The implementation class for the {@link JobInput}
+   * @return A new {@link JobInput} implementation.
+   */
+  public static JobInput getJobInputFromClassName(String className) {
+    try {
+      Class inputClass = Class.forName(className);
+      return (JobInput) inputClass.newInstance();
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading job input class " + className
+              + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading job input class " + className
+              + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading job input class " + className
+              + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+
+  /**
+   * Constructs a new {@link JobInstance} implementation from the given
+   * <code>className</code>.
+   *
+   * @param className
+   *          The name of the implementation class for the {@link JobInstance}
+   *          to construct.
+   * @return A new {@link JobInstance} implementation.
+   */
+  public static JobInstance getJobInstanceFromClassName(String className) {
+    try {
+      Class instClass = Class.forName(className);
+      return (JobInstance) instClass.newInstance();
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading job instance class " + className
+              + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading job instance class " + className
+              + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading job instance class " + className
+              + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+
+  /**
+   * Creates a new {@link QueueRepository} implementation from the given
+   * {@link QueueRepositoryFactory} class name.
+   *
+   * @param serviceFactory
+   *          The class name of the {@link QueueRepositoryFactory} to use to create new
+   *          {@link QueueRepository}s.
+   * @return A new implementation of a {@link QueueRepository}.
+   */
+  public static QueueRepository getQueueRepositoryFromFactory(String queueRepositoryFactory) {
+    Class clazz = null;
+    QueueRepositoryFactory factory = null;
+
+    try {
+      clazz = Class.forName(queueRepositoryFactory);
+      factory = (QueueRepositoryFactory) clazz.newInstance();
+      return factory.createQueueRepository();
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading queue repository factory class "
+              + queueRepositoryFactory + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading queue repository factory class "
+              + queueRepositoryFactory + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading queue repository factory class "
+              + queueRepositoryFactory + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+  /**
+   * Creates a new {@link BackendRepository} implementation from the given
+   * {@link BackendRepositoryFactory} class name.
+   *
+   * @param backendRepositoryFactory
+   *          The class name of the {@link BackendRepositoryFactory} to use to create new
+   *          {@link BackendRepository}s.
+   * @return A new implementation of a {@link BackendRepository}.
+   */
+  public static BackendRepository getBackendRepositoryFromFactory(String backendRepositoryFactory) {
+    Class clazz = null;
+    BackendRepositoryFactory factory = null;
+
+    try {
+      clazz = Class.forName(backendRepositoryFactory);
+      factory = (BackendRepositoryFactory) clazz.newInstance();
+      return factory.createBackendRepository();
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading backend repository factory class "
+              + backendRepositoryFactory + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading backend repository factory class "
+              + backendRepositoryFactory + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading backend repository factory class "
+              + backendRepositoryFactory + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+  /**
+   * Creates a new {@link NodeRepository} implementation from the given
+   * {@link QueueRepositoryFactory} class name.
+   *
+   * @param serviceFactory
+   *          The class name of the {@link NodeRepositoryFactory} to use to create new
+   *          {@link QueueRepository}s.
+   * @return A new implementation of a {@link NodeRepository}.
+   */
+  public static NodeRepository getNodeRepositoryFromFactory(String nodeRepositoryFactory) {
+    Class clazz = null;
+    NodeRepositoryFactory factory = null;
+
+    try {
+      clazz = Class.forName(nodeRepositoryFactory);
+      factory = (NodeRepositoryFactory) clazz.newInstance();
+      return factory.createNodeRepository();
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading node repository factory class "
+              + nodeRepositoryFactory + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading node repository factory class "
+              + nodeRepositoryFactory + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading node repository factory class "
+              + nodeRepositoryFactory + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+
+  /**
+   * Creates a new {@link JobQueue} implementation from the given
+   * {@link JobQueueFactory} class name.
+   *
+   * @param serviceFactory
+   *          The class name of the {@link JobQueueFactory} to use to create new
+   *          {@link JobQueue}s.
+   * @return A new implementation of a {@link JobQueue}.
+   */
+  public static JobQueue getJobQueueServiceFromFactory(String serviceFactory) {
+    Class clazz = null;
+    JobQueueFactory factory = null;
+
+    try {
+      clazz = Class.forName(serviceFactory);
+      factory = (JobQueueFactory) clazz.newInstance();
+      return factory.createQueue();
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading jobqueue factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading jobqueue factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading jobqueue factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+
+  /**
+   * Creates a new Batchmgr implementation from a given String name of the
+   * corresponding {@link BatchmgrFactory}.
+   *
+   * @param serviceFactory
+   *          The name of the {@link BatchmgrFactory} class to use to create
+   *          {@link Batchmgr}s.
+   * @return A new {@link Batchmgr} implementation.
+   */
+  public static Batchmgr getBatchmgrServiceFromFactory(String serviceFactory) {
+    Class clazz = null;
+    BatchmgrFactory factory = null;
+
+    try {
+      clazz = Class.forName(serviceFactory);
+      factory = (BatchmgrFactory) clazz.newInstance();
+      return factory.createBatchmgr();
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading batchmgr factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading batchmgr factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading batchmgr factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+
+  /**
+   * Creates a new {@link Monitor} implementation from the given String name of
+   * the {@link MonitorFactory}.
+   *
+   * @param serviceFactory
+   *          The name of the {@link MonitorFactory} class to use to create
+   *          {@link Monitor}s.
+   * @return A new {@link Monitor} implementation.
+   */
+  public static Monitor getMonitorServiceFromFactory(String serviceFactory) {
+    Class clazz = null;
+    MonitorFactory factory = null;
+
+    try {
+      clazz = Class.forName(serviceFactory);
+      factory = (MonitorFactory) clazz.newInstance();
+      return factory.createMonitor();
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading monitor factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading monitor factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading monitor factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    }
+
+    return null;
+
+  }
+
+  /**
+   * Creates a new {@link Scheduler} from the given String name of the
+   * {@link SchedulerFactory}.
+   *
+   * @param serviceFactory
+   *          The class name of the {@link SchedulerFactory} to use to create
+   *          the new {@link Scheduler}.
+   * @return A new {@link Scheduler} implementation.
+   */
+  public static Scheduler getSchedulerServiceFromFactory(String serviceFactory) {
+    Class clazz = null;
+    SchedulerFactory factory = null;
+
+    try {
+      clazz = Class.forName(serviceFactory);
+      factory = (SchedulerFactory) clazz.newInstance();
+      return factory.createScheduler();
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading scheduler factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading scheduler factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading scheduler factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+
+  /**
+   * Creates a new {@link JobRepository} implementation from the given
+   * name of the {@link JobRepositoryFactory}.
+   * @param serviceFactory The class name of the {@link JobRepositoryFactory}
+   * to use to create a {@link JobRepository}.
+   * @return A new {@link JobRepository} from the given service factory.
+   */
+  public static JobRepository getJobRepositoryFromServiceFactory(String serviceFactory) {
+    Class clazz = null;
+    JobRepositoryFactory factory = null;
+
+    try {
+      clazz = Class.forName(serviceFactory);
+      factory = (JobRepositoryFactory) clazz.newInstance();
+      return factory.createRepository();
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading job repo factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading job rep factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading job repo factory class "
+              + serviceFactory + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+
+    /**
+     * Creates a new {@link org.apache.oodt.cas.resource.monitor.ganglia.loadcalc.LoadCalculator} implementation from the given String name of
+     * the {@link ResourceMonitorFactory}.
+     *
+     * @param serviceFactory
+     *          The name of the {@link org.apache.oodt.cas.resource.monitor.ganglia.loadcalc.LoadCalculatorFactory} class to use to create
+     *          {@link org.apache.oodt.cas.resource.monitor.ganglia.loadcalc.LoadCalculator}s.
+     * @return A new {@link org.apache.oodt.cas.resource.monitor.ganglia.loadcalc.LoadCalculator} implementation.
+     */
+    public static LoadCalculator getLoadCalculatorFromServiceFactory(String serviceFactory){
+        Class clazz;
+        LoadCalculatorFactory factory;
+
+        try {
+            clazz = Class.forName(serviceFactory);
+            factory = (LoadCalculatorFactory) clazz.newInstance();
+            return factory.createLoadCalculator();
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "ClassNotFoundException when loading load calculator factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        } catch (InstantiationException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "InstantiationException when loading load calculator factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "IllegalAccessException when loading load calculator factory class "
+                            + serviceFactory + " Message: " + e.getMessage());
+        }
+
+        return null;
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/JobBuilder.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/JobBuilder.java
new file mode 100644
index 0000000..8cc8d65
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/JobBuilder.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.util;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+
+import org.w3c.dom.Document;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public final class JobBuilder {
+
+    private JobBuilder() throws InstantiationException {
+        throw new InstantiationException("Don't construct utility classes!");
+    }
+
+    public static JobSpec buildJobSpec(File jobFile) {
+        return buildJobSpec(jobFile.getAbsolutePath());
+    }
+
+    public static JobSpec buildJobSpec(String jobFilePath) {
+        Document doc = null;
+        try {
+            doc = XMLUtils.getDocumentRoot(new FileInputStream(new File(
+                    jobFilePath)));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+        return XmlStructFactory.getJobSpec(doc.getDocumentElement());
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/MesosUtilities.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/MesosUtilities.java
new file mode 100644
index 0000000..af6fc83
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/MesosUtilities.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.util;
+
+import java.util.Collection;
+
+import org.apache.mesos.Protos.Resource;
+import org.apache.mesos.Protos.Value.Range;
+import org.apache.mesos.Protos.Value.Type;
+import org.apache.commons.lang.SerializationUtils;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.JobSpecSerializer;
+import org.apache.mesos.protobuf.ByteString;
+/**
+ * @author starchmd
+ * @version $Revision$
+ */
+public class MesosUtilities {
+    /**
+     * Get a ByteString serialization of a JobSpec to send over the wire to the mesos-backend.
+     * @param jobSpec - JobSpec to serialize
+     * @return bytestring containing byte[] of jobspec
+     */
+    public static ByteString jobSpecToByteString(JobSpec jobSpec)
+    {
+        return ByteString.copyFrom(SerializationUtils.serialize(new JobSpecSerializer(jobSpec)));
+    }
+    /**
+     * Build a JobSpec from a ByteString off the wire
+     * @param data - ByteString to deserialize
+     * @return newly minted JobSpec
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     * @throws ClassNotFoundException
+     */
+    public static JobSpec byteStringToJobSpec(ByteString data) throws ClassNotFoundException, InstantiationException, IllegalAccessException
+    {
+        return ((JobSpecSerializer)SerializationUtils.deserialize(data.toByteArray())).getJobSpec();
+    }
+
+    /**
+     * Makes a string message from resources list.
+     * @param resources - resource list to make into string.
+     * @return string representing the resource list.
+     */
+    public static String getResourceMessage(Collection<Resource> resources) {
+        String ret = "";
+        for (Resource res : resources)
+            ret += "\n\t"+getResourceMessage(res);
+        return ret;
+    }
+
+    /**
+     * Creates string out an offer in a nice format.
+     * @param resource - mesos resource to make into string.
+     * @return string representing a resource.
+     */
+    public static String getResourceMessage(Resource resource) {
+        Type type = resource.getType();
+        String ret = resource.getName() +" "+resource.getRole()+ ": ";
+        switch (type) {
+            case SCALAR:
+                ret += resource.getScalar().getValue();
+                break;
+            case RANGES:
+                for (Range range : resource.getRanges().getRangeList())
+                    ret += range.getBegin() + " - "+range.getEnd()+",";
+                break;
+            case TEXT:
+                ret += " TEXT type...cannot find.";
+                break;
+            case SET:
+                for (String string : resource.getSet().getItemList())
+                    ret += string + ",";
+                break;
+        }
+        return ret;
+    }
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/Ulimit.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/Ulimit.java
new file mode 100644
index 0000000..10982da
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/Ulimit.java
@@ -0,0 +1,237 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.util;
+
+//JDK imports
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A static API to detect ulimit properties on an underlying
+ * *-nix system.
+ * </p>.
+ */
+public final class Ulimit implements UlimitMetKeys {
+    private static final String shell = "/bin/bash";
+
+    private static final String runShellCmdOption = "-c";
+
+    private static final String ulimitCommand = "ulimit -a";
+
+    private static final String UNKNOWN_VALUE = "N/A";
+
+    public static String getCoreFileSize() {
+        try {
+            return ((UlimitProperty) getUlimitPropertiesMap().get(
+                    CORE_FILE_SIZE)).getValue();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return UNKNOWN_VALUE;
+        }
+
+    }
+
+    public static String getDataSegmentSize() {
+        try {
+            return ((UlimitProperty) getUlimitPropertiesMap().get(
+                    DATA_SEGMENT_SIZE)).getValue();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return UNKNOWN_VALUE;
+        }
+
+    }
+
+    public static String getFileSize() {
+        try {
+            return ((UlimitProperty) getUlimitPropertiesMap().get(FILE_SIZE))
+                    .getValue();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return UNKNOWN_VALUE;
+        }
+
+    }
+
+    public static String getMaxLockedMemory() {
+        try {
+            return ((UlimitProperty) getUlimitPropertiesMap().get(
+                    MAX_LOCKED_MEMORY)).getValue();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return UNKNOWN_VALUE;
+        }
+
+    }
+
+    public static String getMaxMemorySize() {
+        try {
+            return ((UlimitProperty) getUlimitPropertiesMap().get(
+                    MAX_MEMORY_SIZE)).getValue();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return UNKNOWN_VALUE;
+        }
+
+    }
+
+    public static String getMaxOpenFiles() {
+        try {
+            return ((UlimitProperty) getUlimitPropertiesMap().get(
+                    MAX_OPEN_FILES)).getValue();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return UNKNOWN_VALUE;
+        }
+
+    }
+
+    public static String getMaxPipeSize() {
+        try {
+            return ((UlimitProperty) getUlimitPropertiesMap()
+                    .get(MAX_PIPE_SIZE)).getValue();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return UNKNOWN_VALUE;
+        }
+
+    }
+
+    public static String getMaxStackSize() {
+        try {
+            return ((UlimitProperty) getUlimitPropertiesMap().get(
+                    MAX_STACK_SIZE)).getValue();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return UNKNOWN_VALUE;
+        }
+
+    }
+
+    public static String getMaxCpuTime() {
+        try {
+            return ((UlimitProperty) getUlimitPropertiesMap().get(MAX_CPU_TIME))
+                    .getValue();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return UNKNOWN_VALUE;
+        }
+
+    }
+
+    public static String getMaxUserProcesses() {
+        try {
+            return ((UlimitProperty) getUlimitPropertiesMap().get(
+                    MAX_USER_PROCESSES)).getValue();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return UNKNOWN_VALUE;
+        }
+
+    }
+
+    public static String getMaxVirtualMemory() {
+        try {
+            return ((UlimitProperty) getUlimitPropertiesMap().get(
+                    MAX_VIRTUAL_MEMORY)).getValue();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return UNKNOWN_VALUE;
+        }
+
+    }
+
+    public static Map getUlimitPropertiesMap() throws Exception {
+        Process p = null;
+        try {
+            p = Runtime.getRuntime().exec(
+                    new String[] { shell, runShellCmdOption, ulimitCommand });
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Exception(
+                    "IOException executing ulimit command: Message: "
+                            + e.getMessage());
+        }
+        BufferedReader in = new BufferedReader(new InputStreamReader(p
+                .getInputStream()));
+
+        String line = null;
+        Map properties = new HashMap();
+
+        while ((line = in.readLine()) != null) {
+            UlimitProperty property = parseProperty(line);
+            properties.put(property.getName(), property);
+        }
+        
+        try{
+            p.waitFor();
+        }
+        catch(Exception ignore){}
+
+
+        return properties;
+    }
+
+    public static List getUlimitProperties() throws Exception {
+        Process p = null;
+        try {
+            p = Runtime.getRuntime().exec(
+                    new String[] { shell, runShellCmdOption, ulimitCommand });
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Exception(
+                    "IOException executing ulimit command: Message: "
+                            + e.getMessage());
+        }
+        BufferedReader in = new BufferedReader(new InputStreamReader(p
+                .getInputStream()));
+
+        String line = null;
+        List properties = new Vector();
+
+        while ((line = in.readLine()) != null) {
+            UlimitProperty property = parseProperty(line);
+            properties.add(property);
+        }
+        
+        try{
+            p.waitFor();
+        }
+        catch(Exception ignore){}
+
+        return properties;
+    }
+
+    private static UlimitProperty parseProperty(String line) {
+        // line looks like: cpu time (seconds, -t) unlimited
+        String propName = line.substring(0, line.indexOf('(')).trim();
+        String propValue = line.substring(line.indexOf(')') + 1).trim();
+        return new UlimitProperty(propName, propValue);
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/UlimitMetKeys.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/UlimitMetKeys.java
new file mode 100644
index 0000000..79371f6
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/UlimitMetKeys.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.util;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Metadata keys to describe the output
+ * of the ulimit call.
+ * </p>.
+ */
+public interface UlimitMetKeys {
+
+    public static final String CORE_FILE_SIZE = "core file size";
+
+    public static final String DATA_SEGMENT_SIZE = "data seg size";
+    
+    public static final String FILE_SIZE = "file size";
+
+    public static final String MAX_LOCKED_MEMORY = "max locked memory";
+
+    public static final String MAX_MEMORY_SIZE = "max memory size";
+
+    public static final String MAX_OPEN_FILES = "open files";
+
+    public static final String MAX_PIPE_SIZE = "pipe size";
+
+    public static final String MAX_STACK_SIZE = "stack size";
+
+    public static final String MAX_CPU_TIME = "cpu time";
+
+    public static final String MAX_USER_PROCESSES = "max user processes";
+
+    public static final String MAX_VIRTUAL_MEMORY = "virtual memory";
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/UlimitProperty.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/UlimitProperty.java
new file mode 100644
index 0000000..fb1a578
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/UlimitProperty.java
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.util;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Ulimit returned property, mapping a name to a particular
+ * value. The value may be "unlimited", indicating there is no
+ * limit on the properties value. In this case, a call to
+ * {@link #isUnlimited()} can be used to detect this.
+ * </p>.
+ */
+public class UlimitProperty {
+
+    private String name;
+
+    private String value;
+
+    private static final String UNLIMITED_VAL = "unlimited";
+
+    public UlimitProperty() {
+    }
+
+    /**
+     * @param name
+     * @param value
+     */
+    public UlimitProperty(String name, String value) {
+        super();
+        this.name = name;
+        this.value = value;
+    }
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @param name
+     *            the name to set
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * @return the value
+     */
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * @param value
+     *            the value to set
+     */
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public boolean isUnlimited() {
+        if (this.value.equals(UNLIMITED_VAL)) {
+            return true;
+        } else {
+            try {
+                Integer.parseInt(this.value);
+                return false;
+            } catch (Exception ignore) {
+                // not a number, so unlimited
+                return true;
+            }
+        }
+
+    }
+
+    public int getIntValue() {
+        if (isUnlimited()) {
+            return -1;
+        } else
+            return Integer.parseInt(this.value);
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/XmlRpcStructFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/XmlRpcStructFactory.java
new file mode 100644
index 0000000..4c0dee2
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/XmlRpcStructFactory.java
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.util;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory for serializing and reading Resource Manager objects to and from
+ * the XML-RPC wire.
+ * </p>
+ */
+public final class XmlRpcStructFactory {
+
+	private XmlRpcStructFactory() throws InstantiationException {
+		throw new InstantiationException("Don't construct factory classes!");
+	}
+
+	public static Hashtable getXmlRpcJob(Job job) {
+		Hashtable jobHash = new Hashtable();
+		jobHash.put("job.id", job.getId() != null ? job.getId():"");
+		jobHash.put("job.name", job.getName());
+		jobHash.put("job.instanceClassName", job.getJobInstanceClassName());
+		jobHash.put("job.inputClassName", job.getJobInputClassName());
+		jobHash.put("job.queueName", job.getQueueName());
+		jobHash.put("job.load",job.getLoadValue());
+  jobHash.put("job.status", job.getStatus() != null ? job.getStatus() : "");
+    return jobHash;
+	}
+
+	public static Job getJobFromXmlRpc(Hashtable jobHash) {
+		Job job = new Job();
+		job.setId((String) jobHash.get("job.id"));
+		job.setName((String) jobHash.get("job.name"));
+		job.setJobInputClassName((String) jobHash.get("job.inputClassName"));
+		job.setJobInstanceClassName((String) jobHash
+				.get("job.instanceClassName"));
+		job.setQueueName((String)jobHash.get("job.queueName"));
+		job.setLoadValue((Integer)jobHash.get("job.load"));
+  job.setStatus((String)jobHash.get("job.status"));
+		return job;
+	}
+
+ public static Vector getXmlRpcResourceNodeList(List resNodes) {
+    Vector resNodeVector = new Vector();
+
+    if (resNodes != null && resNodes.size() > 0) {
+      for (Iterator i = resNodes.iterator(); i.hasNext();) {
+        ResourceNode node = (ResourceNode) i.next();
+        resNodeVector.add(getXmlRpcResourceNode(node));
+      }
+    }
+
+    return resNodeVector;
+  }
+
+  public static List getResourceNodeListFromXmlRpc(Vector resNodeVector) {
+    List resNodes = new Vector();
+
+    if (resNodeVector != null && resNodeVector.size() > 0) {
+      for (Iterator i = resNodeVector.iterator(); i.hasNext();) {
+        Hashtable resNodeHash = (Hashtable) i.next();
+        resNodes.add(getResourceNodeFromXmlRpc(resNodeHash));
+      }
+    }
+
+    return resNodes;
+  }
+
+  public static Hashtable getXmlRpcResourceNode(ResourceNode node) {
+    Hashtable resNodeHash = new Hashtable();
+    resNodeHash.put("node.id", node.getNodeId());
+    resNodeHash.put("node.capacity", String.valueOf(node.getCapacity()));
+    resNodeHash.put("node.url", node.getIpAddr().toExternalForm());
+
+    return resNodeHash;
+  }
+
+  public static ResourceNode getResourceNodeFromXmlRpc(Hashtable resNodeHash) {
+    ResourceNode node = new ResourceNode();
+    node.setId((String) resNodeHash.get("node.id"));
+    node.setCapacity(Integer
+        .parseInt((String) resNodeHash.get("node.capacity")));
+    try {
+      node.setIpAddr(new URL((String) resNodeHash.get("node.url")));
+    } catch (MalformedURLException ignore) {
+    }
+
+    return node;
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/XmlRpcWriteable.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/XmlRpcWriteable.java
new file mode 100644
index 0000000..0807710
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/XmlRpcWriteable.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.util;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An interface requiring implementing classes to define how that can be
+ * serialized to and from the XML-RPC wire.
+ * </p>.
+ */
+public interface XmlRpcWriteable {
+
+  /**
+   * This method should define how to take an XML-RPC serializable
+   * {@link Object} and load the internal data members of the implementing class
+   * from the given input {@link Object}.
+   * 
+   * @param in
+   *          The {@link Object} to read in and instantiate the implementation
+   *          of this class with.
+   */
+  public void read(Object in);
+
+  /**
+   * 
+   * @return An XML-RPC safe serialization {@link Object} of the implementing
+   *         class for this interface.
+   */
+  public Object write();
+
+}
diff --git a/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/XmlStructFactory.java b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/XmlStructFactory.java
new file mode 100644
index 0000000..908c83b
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/java/org/apache/oodt/cas/resource/util/XmlStructFactory.java
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.util;
+
+//JDK imports
+import java.net.URL;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.logging.Logger;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+
+/**
+ * @author woollard
+ * @author bfoster
+ * @version $Revsion$
+ * 
+ * <p>
+ * A class for constructing Resource Manager objects from XML {@link Node}s and
+ * {@link Element}s.
+ * </p>
+ */
+public final class XmlStructFactory {
+
+    /* our log stream */
+    public static Logger LOG = Logger.getLogger(XmlStructFactory.class
+            .getName());
+
+    private XmlStructFactory() throws InstantiationException {
+        throw new InstantiationException(
+                "Don't instantiate XML Struct Factories!");
+    }
+
+    public static ResourceNode getNodes(Node node) {
+        Element resourceNodeRoot = (Element) node;
+
+        String id = null;
+        URL ip = null;
+        int capacity = 0;
+
+        try {
+            id = resourceNodeRoot.getAttribute("nodeId");
+            ip = new URL(Boolean.parseBoolean(resourceNodeRoot
+					.getAttribute("envReplace")) ? PathUtils
+					.doDynamicReplacement(resourceNodeRoot.getAttribute("ip"))
+					: resourceNodeRoot.getAttribute("ip"));
+            capacity = new Integer(resourceNodeRoot.getAttribute("capacity"))
+                    .intValue();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        ResourceNode resource = new ResourceNode(id, ip, capacity);
+
+        return resource;
+    }
+
+    public static List getQueueAssignment(Node node) {
+        Vector queues = new Vector();
+
+        Element resourceNodeRoot = (Element) node;
+        Element queueElem = XMLUtils
+                .getFirstElement("queues", resourceNodeRoot);
+        NodeList queueList = queueElem.getElementsByTagName("queue");
+
+        if (queueList != null && queueList.getLength() > 0) {
+            for (int i = 0; i < queueList.getLength(); i++) {
+                Element queueElement = (Element) queueList.item(i);
+
+                String queueId = queueElement.getAttribute("name");
+                queues.add(queueId);
+            }
+        }
+
+        return queues;
+    }
+
+    public static JobSpec getJobSpec(Node node) {
+        Element jobNodeElem = (Element) node;
+
+        String jobId = jobNodeElem.getAttribute("id");
+        String jobName = jobNodeElem.getAttribute("name");
+        Element instClassElem = XMLUtils.getFirstElement("instanceClass",
+                jobNodeElem);
+        String instClass = instClassElem.getAttribute("name");
+        String queue = XMLUtils.getElementText("queue", jobNodeElem);
+        Integer load = new Integer(Integer.parseInt(XMLUtils.getElementText(
+                "load", jobNodeElem)));
+
+        Element inputClass = XMLUtils
+                .getFirstElement("inputClass", jobNodeElem);
+        String inputClassName = inputClass.getAttribute("name");
+
+        // now read the properties defined, if any
+        Element propertiesOuterRoot = XMLUtils.getFirstElement("properties",
+                inputClass);
+        Properties inputConfigProps = null;
+
+        if (propertiesOuterRoot != null) {
+            inputConfigProps = new Properties();
+            NodeList propNodeList = propertiesOuterRoot
+                    .getElementsByTagName("property");
+
+            if (propNodeList != null && propNodeList.getLength() > 0) {
+                for (int i = 0; i < propNodeList.getLength(); i++) {
+                    Element propElem = (Element) propNodeList.item(i);
+                    String propName = propElem.getAttribute("name");
+                    String propValue = propElem.getAttribute("value");
+
+                    if (propName != null && propValue != null) {
+                        inputConfigProps.setProperty(propName, propValue);
+                    }
+                }
+            }
+        }
+
+        Job job = new Job();
+        job.setId(jobId);
+        job.setName(jobName);
+        job.setJobInstanceClassName(instClass);
+        job.setJobInputClassName(inputClassName);
+        job.setQueueName(queue);
+        job.setLoadValue(load);
+
+        JobInput in = GenericResourceManagerObjectFactory
+                .getJobInputFromClassName(inputClassName);
+        if (inputConfigProps != null) {
+            in.configure(inputConfigProps);
+        }
+
+        JobSpec spec = new JobSpec(in, job);
+
+        return spec;
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/main/resources/REMOVE.log b/0.8.1-rc1/resource/src/main/resources/REMOVE.log
new file mode 100644
index 0000000..cb27d16
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/REMOVE.log
@@ -0,0 +1,18 @@
+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.
+
+
+You can remove this file. It was only included to ensure that the log directory for this
+distribution was created on assembly.
diff --git a/0.8.1-rc1/resource/src/main/resources/cmd-line-actions.xml b/0.8.1-rc1/resource/src/main/resources/cmd-line-actions.xml
new file mode 100644
index 0000000..04919e9
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/cmd-line-actions.xml
@@ -0,0 +1,92 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+	<bean id="addNode"
+		class="org.apache.oodt.cas.resource.cli.action.AddNodeCliAction">
+		<property name="description" value="Adds a ResourceNode" />
+	</bean>
+	<bean id="addNodeToQueue"
+		class="org.apache.oodt.cas.resource.cli.action.AddNodeToQueueCliAction">
+		<property name="description" value="Adds a ResourceNode to a Queue" />
+	</bean>
+	<bean id="addQueue"
+		class="org.apache.oodt.cas.resource.cli.action.AddQueueCliAction">
+		<property name="description" value="Adds a queue" />
+	</bean>
+	<bean id="getExecNode"
+		class="org.apache.oodt.cas.resource.cli.action.GetExecNodeCliAction">
+		<property name="description" value="Get execution node for a job" />
+	</bean>
+	<bean id="getJobInfo"
+		class="org.apache.oodt.cas.resource.cli.action.GetJobInfoCliAction">
+		<property name="description" value="Gets information about a job" />
+	</bean>
+	<bean id="getNodeById"
+		class="org.apache.oodt.cas.resource.cli.action.GetNodeByIdCliAction">
+		<property name="description" value="Gets information about a node" />
+	</bean>
+	<bean id="getNodeLoad"
+		class="org.apache.oodt.cas.resource.cli.action.GetNodeLoadCliAction">
+		<property name="description" value="Gets the current job load of a node" />
+	</bean>
+	<bean id="getNodes"
+		class="org.apache.oodt.cas.resource.cli.action.GetNodesCliAction">
+		<property name="description" value="Gets a list of managed nodes" />
+	</bean>
+	<bean id="getNodesInQueue"
+		class="org.apache.oodt.cas.resource.cli.action.GetNodesInQueueCliAction">
+		<property name="description"
+			value="Gets list of nodes which belong to given queue" />
+	</bean>
+	<bean id="getQueues"
+		class="org.apache.oodt.cas.resource.cli.action.GetQueuesCliAction">
+		<property name="description" value="Gets list of queues" />
+	</bean>
+	<bean id="getQueuesWithNode"
+		class="org.apache.oodt.cas.resource.cli.action.GetQueuesWithNodeCliAction">
+		<property name="description" value="Gets list of queues which contain given node" />
+	</bean>
+	<bean id="kill" class="org.apache.oodt.cas.resource.cli.action.KillCliAction">
+		<property name="description" value="Kills a job" />
+	</bean>
+	<bean id="removeNode"
+		class="org.apache.oodt.cas.resource.cli.action.RemoveNodeCliAction">
+		<property name="description" value="Removes given node from managed nodes" />
+	</bean>
+	<bean id="removeNodeFromQueue"
+		class="org.apache.oodt.cas.resource.cli.action.RemoveNodeFromQueueCliAction">
+		<property name="description" value="Removes given node from given queue" />
+	</bean>
+	<bean id="removeQueue"
+		class="org.apache.oodt.cas.resource.cli.action.RemoveQueueCliAction">
+		<property name="description" value="Removes a queue" />
+	</bean>
+	<bean id="setNodeCapacity"
+		class="org.apache.oodt.cas.resource.cli.action.SetNodeCapacityCliAction">
+		<property name="description" value="Changes a nodes capacity" />
+	</bean>
+	<bean id="submitJob"
+		class="org.apache.oodt.cas.resource.cli.action.SubmitJobCliAction">
+		<property name="description" value="Submits a job for execution" />
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/resource/src/main/resources/cmd-line-options.xml b/0.8.1-rc1/resource/src/main/resources/cmd-line-options.xml
new file mode 100644
index 0000000..a7a1fde
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/cmd-line-options.xml
@@ -0,0 +1,601 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+	<bean id="url" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="u" />
+		<property name="longOption" value="url" />
+		<property name="description" value="Resource Manager URL" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="url" />
+		<property name="required" value="true" />
+		<property name="handler">
+			<bean
+				class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+				<property name="propertyNames">
+					<list>
+						<value>org.apache.oodt.cas.resource.url</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="operation" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+		<property name="shortOption" value="op" />
+		<property name="longOption" value="operation" />
+		<property name="description"
+			value="Declare that you wish to present an operation" />
+		<property name="hasArgs" value="false" />
+		<property name="required" value="true" />
+		<property name="subOptions">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getNodeById" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getNodes" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getQueues" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="addNode" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="removeNode" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="setNodeCapacity" p:required="false" />
+        <bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+          p:option-ref="getExecNode" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="addQueue" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="removeQueue" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="addNodeToQueue" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getNodesInQueue" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getQueuesWithNode" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="removeNodeFromQueue" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getNodeLoad" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="submitJob" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getJobInfo" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="kill" p:required="false" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetNodeById Options -->
+	<bean id="getNodeById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="nbyid" />
+		<property name="longOption" value="getNodeById" />
+		<property name="description" value="Triggers getNodeById Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getNodeById</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodeById" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetNodes Options -->
+	<bean id="getNodes" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="nodes" />
+		<property name="longOption" value="getNodes" />
+		<property name="description" value="Triggers getNodes Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getNodes</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodes" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetQueues Options -->
+	<bean id="getQueues" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="queues" />
+		<property name="longOption" value="getQueues" />
+		<property name="description" value="Triggers getQueues Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getQueues</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getQueues" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- AddNode Options -->
+	<bean id="addNode" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="an" />
+		<property name="longOption" value="addNode" />
+		<property name="description" value="Triggers addNode Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>addNode</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNode" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="ipAddr" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="addr" />
+		<property name="longOption" value="ipAddr" />
+		<property name="description" value="Node IP Address" />
+		<property name="type" value="java.net.URL" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="ip-addr" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNode" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+				<property name="applyToActions">
+					<list>
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="addNode" p:methodName="setNodeUrl" />
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<!-- RemoveNode Options -->
+	<bean id="removeNode" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="rn" />
+		<property name="longOption" value="removeNode" />
+		<property name="description" value="Triggers removeNode Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>removeNode</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeNode" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- SetNodeCapacity Options -->
+	<bean id="setNodeCapacity" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="sncap" />
+		<property name="longOption" value="setNodeCapacity" />
+		<property name="description" value="Triggers setNodeCapacity Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>setNodeCapacity</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="setNodeCapacity" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+  <!-- SetNodeCapacity Options -->
+  <bean id="getExecNode" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+    p:isSubOption="true">
+    <property name="shortOption" value="exeNode" />
+    <property name="longOption" value="getExecNode" />
+    <property name="description" value="Triggers getExecNode Action" />
+    <property name="hasArgs" value="false" />
+    <property name="staticArgs">
+      <list>
+        <value>getExecNode</value>
+      </list>
+    </property>
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getExecNode" p:relation="REQUIRED" />
+      </list>
+    </property>
+  </bean>
+
+	<!-- AddQueue Options -->
+	<bean id="addQueue" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="aq" />
+		<property name="longOption" value="addQueue" />
+		<property name="description" value="Triggers addQueue Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>addQueue</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addQueue" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- RemoveQueue Options -->
+	<bean id="removeQueue" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="rq" />
+		<property name="longOption" value="removeQueue" />
+		<property name="description" value="Triggers removeQueue Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>removeQueue</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeQueue" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- AddNodeToQueue Options -->
+	<bean id="addNodeToQueue" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="antq" />
+		<property name="longOption" value="addNodeToQueue" />
+		<property name="description" value="Triggers addNodeToQueue Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>addNodeToQueue</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNodeToQueue" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetNodesInQueue Options -->
+	<bean id="getNodesInQueue" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="ninq" />
+		<property name="longOption" value="getNodesInQueue" />
+		<property name="description" value="Triggers getNodesInQueue Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getNodesInQueue</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodesInQueue" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetQueuesWithNode Options -->
+	<bean id="getQueuesWithNode" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="qwn" />
+		<property name="longOption" value="getQueuesWithNode" />
+		<property name="description" value="Triggers getQueuesWithNode Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getQueuesWithNode</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getQueuesWithNode" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- RemoveNodeFromQueue Options -->
+	<bean id="removeNodeFromQueue" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="rnfq" />
+		<property name="longOption" value="removeNodeFromQueue" />
+		<property name="description" value="Triggers removeNodeFromQueue Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>removeNodeFromQueue</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeNodeFromQueue" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetNodeLoad Options -->
+	<bean id="getNodeLoad" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="load" />
+		<property name="longOption" value="getNodeLoad" />
+		<property name="description" value="Triggers getNodeLoad Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getNodeLoad</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodeLoad" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- SubmitJob Options -->
+	<bean id="submitJob" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="submit" />
+		<property name="longOption" value="submitJob" />
+		<property name="description" value="Triggers submitJob Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>submitJob</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="submitJob" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="def" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="d" />
+		<property name="longOption" value="def" />
+		<property name="description" value="Job Definition File" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="xml-file" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="submitJob" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+				<property name="applyToActions">
+					<list>
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="submitJob" p:methodName="setJobDefinitionFile" />
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+  <bean id="nodeUrl" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="nu" />
+    <property name="longOption" value="nodeUrl" />
+    <property name="description" value="Node URL" />
+    <property name="type" value="java.net.URL" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="url" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="submitJob" p:relation="OPTIONAL" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+        <property name="applyToActions">
+          <list>
+            <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+              p:actionName="submitJob" p:methodName="setUrl" />
+          </list>
+        </property>
+      </bean>
+    </property>
+  </bean>
+
+	<!-- GetJobInfo Options -->
+	<bean id="getJobInfo" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="info" />
+		<property name="longOption" value="getJobInfo" />
+		<property name="description" value="Triggers getJobInfo Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getJobInfo</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getJobInfo" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- Kill Options -->
+	<bean id="kill" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="k" />
+		<property name="longOption" value="kill" />
+		<property name="description" value="Triggers kill Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>kill</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="kill" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- Options used for multiple Actions -->
+	<bean id="nodeId" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="nid" />
+		<property name="longOption" value="nodeId" />
+		<property name="description" value="Node ID" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="node-id" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodeById" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNode" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeNode" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="setNodeCapacity" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNodeToQueue" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getQueuesWithNode" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeNodeFromQueue" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodeLoad" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+		</property>
+	</bean>
+
+	<bean id="capacity" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="cap" />
+		<property name="longOption" value="capacity" />
+		<property name="description" value="Node Capacity" />
+		<property name="type" value="int" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="capacity" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNode" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="setNodeCapacity" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+		</property>
+	</bean>
+
+	<bean id="queueName" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="qn" />
+		<property name="longOption" value="queueName" />
+		<property name="description" value="Queue name" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="queue-name" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addQueue" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeQueue" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="addNodeToQueue" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNodesInQueue" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="removeNodeFromQueue" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+		</property>
+	</bean>
+
+  <bean id="jobId" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+    <property name="shortOption" value="jid" />
+    <property name="longOption" value="jobId" />
+    <property name="description" value="Job ID" />
+    <property name="hasArgs" value="true" />
+    <property name="argsDescription" value="job-id" />
+    <property name="requirementRules">
+      <list>
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getJobInfo" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="getExecNode" p:relation="REQUIRED" />
+        <bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+          p:actionName="kill" p:relation="REQUIRED" />
+      </list>
+    </property>
+    <property name="handler">
+      <bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+    </property>
+  </bean>
+</beans>
diff --git a/0.8.1-rc1/resource/src/main/resources/examples/jobs/exJob.xml b/0.8.1-rc1/resource/src/main/resources/examples/jobs/exJob.xml
new file mode 100644
index 0000000..bbe0def
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/examples/jobs/exJob.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<cas:job xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" id="abcd"
+	name="TestJob">
+	<instanceClass
+		name="org.apache.oodt.cas.resource.examples.HelloWorldJob" />
+	<inputClass
+		name="org.apache.oodt.cas.resource.structs.NameValueJobInput">
+		<properties>
+			<property name="user.name" value="Homer!" />
+		</properties>
+	</inputClass>
+	<queue>quick</queue>
+	<load>1</load>
+</cas:job>
diff --git a/0.8.1-rc1/resource/src/main/resources/examples/jobs/exLongJob.xml b/0.8.1-rc1/resource/src/main/resources/examples/jobs/exLongJob.xml
new file mode 100644
index 0000000..3cbeb29
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/examples/jobs/exLongJob.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<cas:job xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" id="abcd"
+	name="TestJob">
+	<instanceClass
+		name="org.apache.oodt.cas.resource.examples.LongJob" />
+	<inputClass
+		name="org.apache.oodt.cas.resource.structs.NameValueJobInput">
+		<properties>
+			<property name="wait" value="60" />
+		</properties>
+	</inputClass>
+	<queue>quick</queue>
+	<load>1</load>
+</cas:job>
diff --git a/0.8.1-rc1/resource/src/main/resources/examples/jobs/exPalindrome.xml b/0.8.1-rc1/resource/src/main/resources/examples/jobs/exPalindrome.xml
new file mode 100644
index 0000000..b0340f2
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/examples/jobs/exPalindrome.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<cas:job xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" id="no-spark-1"
+	name="No Spark Job">
+	<instanceClass
+		name="org.apache.oodt.cas.resource.spark.examples.NoSparkFilePalindromeExample" />
+	<inputClass
+		name="org.apache.oodt.cas.resource.structs.NameValueJobInput">
+		<properties>
+			<property name="file" value="&lt;input-file&gt;" />
+			<property name="output" value="&lt;output-file&gt;" />
+		</properties>
+	</inputClass>
+	<queue>quick</queue>
+	<load>1</load>
+</cas:job>
diff --git a/0.8.1-rc1/resource/src/main/resources/examples/jobs/exSparkJob.xml b/0.8.1-rc1/resource/src/main/resources/examples/jobs/exSparkJob.xml
new file mode 100644
index 0000000..0ac02b9
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/examples/jobs/exSparkJob.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<cas:job xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" id="scala-12345"
+	name="TestSparkJob">
+	<instanceClass
+		name="org.apache.oodt.cas.resource.examples.ScalaHelloWorld" />
+	<inputClass
+		name="org.apache.oodt.cas.resource.structs.NameValueJobInput">
+		<properties>
+			<property name="file" value="/Users/mstarch/deploy/test.file" />
+		</properties>
+	</inputClass>
+	<queue>quick</queue>
+	<load>1</load>
+</cas:job>
diff --git a/0.8.1-rc1/resource/src/main/resources/examples/jobs/exSparkPalindrome.xml b/0.8.1-rc1/resource/src/main/resources/examples/jobs/exSparkPalindrome.xml
new file mode 100644
index 0000000..f54f49b
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/examples/jobs/exSparkPalindrome.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<cas:job xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" id="spark-1"
+	name="Spark Job">
+	<instanceClass
+		name="org.apache.oodt.cas.resource.spark.examples.SparkFilePalindromeExample" />
+	<inputClass
+		name="org.apache.oodt.cas.resource.structs.NameValueJobInput">
+		<properties>
+			<property name="file" value="hdfs://&lt;host&gt;:&lt;port&gt;/&lt;input-file&gt;" />
+			<property name="output" value="&lt;output-file&gt;" />
+		</properties>
+	</inputClass>
+	<queue>quick</queue>
+	<load>1</load>
+</cas:job>
diff --git a/0.8.1-rc1/resource/src/main/resources/examples/jobs/exStreamingPalindrome.xml b/0.8.1-rc1/resource/src/main/resources/examples/jobs/exStreamingPalindrome.xml
new file mode 100644
index 0000000..c8c695c
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/examples/jobs/exStreamingPalindrome.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<cas:job xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" id="streaming-1"
+	name="Streaming Job">
+	<instanceClass
+		name="org.apache.oodt.cas.resource.spark.examples.StreamingPalindromeExample" />
+	<inputClass
+		name="org.apache.oodt.cas.resource.structs.NameValueJobInput">
+		<properties>
+			<property name="host" value="&lt;host&gt;" />
+			<property name="port" value="&lt;port&gt;" />
+			<property name="output" value="&lt;output-file&gt;" />
+		</properties>
+	</inputClass>
+	<queue>quick</queue>
+	<load>1</load>
+</cas:job>
diff --git a/0.8.1-rc1/resource/src/main/resources/examples/node-to-queue-mapping.xml b/0.8.1-rc1/resource/src/main/resources/examples/node-to-queue-mapping.xml
new file mode 100644
index 0000000..73b0eba
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/examples/node-to-queue-mapping.xml
@@ -0,0 +1,26 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<cas:node-to-queue-mapping xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<node id="localhost">
+		<queues>
+			<queue name="high"/>
+			<queue name="quick"/>
+			<queue name="long"/>
+		</queues>
+	</node>	
+</cas:node-to-queue-mapping>
diff --git a/0.8.1-rc1/resource/src/main/resources/examples/nodes.xml b/0.8.1-rc1/resource/src/main/resources/examples/nodes.xml
new file mode 100644
index 0000000..d3d415d
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/examples/nodes.xml
@@ -0,0 +1,23 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<cas:resourcenodes xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<node nodeId="localhost" ip="http://localhost:2001" capacity="8"/>
+	<!-- EnvReplace Example 
+	<node nodeId="somehost" ip="http://somehost:[BATCH_STUB_PORT]" capacity="8" envReplace="true"/>
+	-->
+</cas:resourcenodes>
diff --git a/0.8.1-rc1/resource/src/main/resources/examples/queue-to-backend-mapping.xml b/0.8.1-rc1/resource/src/main/resources/examples/queue-to-backend-mapping.xml
new file mode 100644
index 0000000..ea50257
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/examples/queue-to-backend-mapping.xml
@@ -0,0 +1,24 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<cas:queue-to-backend-mapping xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<queue name="example">
+		<scheduler factory="org.apache.oodt.cas.resource.scheduler.LRUSchedulerFactory"/>
+		<monitor factory="org.apache.oodt.cas.resource.monitor.AssignmentMonitorFactory"/>
+		<batchmgr factory="org.apache.oodt.cas.resource.batchmgr.XmlRpcBatchMgrFactory"/>
+	</queue>
+</cas:queue-to-backend-mapping>
diff --git a/0.8.1-rc1/resource/src/main/resources/logging.properties b/0.8.1-rc1/resource/src/main/resources/logging.properties
new file mode 100644
index 0000000..35d60c1
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/logging.properties
@@ -0,0 +1,69 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.FileHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = ../logs/cas_resource%g.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 5
+java.util.logging.FileHandler.append = true
+java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging level for the subsystems
+
+# batchmgr subsystem
+org.apache.oodt.cas.resource.batchmgr.level = INFO
+
+# monitor subsystem
+org.apache.oodt.cas.resource.monitor.level = INFO
+
+# jobqueue subsystem
+org.apache.oodt.cas.resource.jobqueue.level = INFO
+
+# scheduler subsystem
+org.apache.oodt.cas.resource.scheduler.level = INFO
+
+# system subsystem
+org.apache.oodt.cas.resource.system.level = FINE
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = INFO
+httpclient.wire.header.level = INFO
+httpclient.wire.level = INFO
+
+# spring framework logging
+org.springframework.beans.level = SEVERE
+org.springframework.core.level = SEVERE
+org.springframework.level = SEVERE
+org.springframework.beans.factory.level = SEVERE
+org.springframework.beans.factory.config.level = SEVERE
+org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.level = SEVERE
+org.apache.oodt.cas.crawl.util.CasPropertyPlaceholderConfigurer.level = SEVERE
+sun.net.level = SEVERE
diff --git a/0.8.1-rc1/resource/src/main/resources/resource.properties b/0.8.1-rc1/resource/src/main/resources/resource.properties
new file mode 100644
index 0000000..a467949
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/resources/resource.properties
@@ -0,0 +1,84 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+#
+# Properties required to configure the Resource Manager
+
+# resource spark master
+resource.runner.spark.host = mesos://<ip>:5050
+
+# resource batchmgr factory
+resource.batchmgr.factory = org.apache.oodt.cas.resource.batchmgr.XmlRpcBatchMgrFactory
+
+# resource monitor factory
+resource.monitor.factory = org.apache.oodt.cas.resource.monitor.AssignmentMonitorFactory
+
+# resource scheduler factory
+resource.scheduler.factory = org.apache.oodt.cas.resource.scheduler.LRUSchedulerFactory
+
+# resource jobqueue factory
+resource.jobqueue.factory = org.apache.oodt.cas.resource.jobqueue.JobStackJobQueueFactory
+
+# resource job repository factory
+resource.jobrepo.factory = org.apache.oodt.cas.resource.jobrepo.MemoryJobRepositoryFactory
+
+# For queue-multiplexing scheduler
+resource.backend.mux.repository = org.apache.oodt.cas.resource.mux.XmlBackendRepositoryFactory
+resource.backend.mux.xmlrepository.queuetobackend = file://[HOME]/queue-to-backend.xml
+
+
+# node repository factory
+org.apache.oodt.cas.resource.nodes.repo.factory = org.apache.oodt.cas.resource.noderepo.XmlNodeRepositoryFactory
+
+# queue repository factory
+org.apache.oodt.cas.resource.queues.repo.factory = org.apache.oodt.cas.resource.queuerepo.XmlQueueRepositoryFactory
+
+# resource nodes monitor factory
+org.apache.oodt.cas.resource.monitor.factory = org.apache.oodt.cas.resource.monitor.ganglia.GangliaResourceMonitorFactory
+
+# ganglia resource monitor's load calculator factory
+org.apache.oodt.cas.resource.monitor.loadcalc.factory = org.apache.oodt.cas.resource.monitor.ganglia.loadcalc.WeightedAverageLoadCalcFactory
+
+# JobStack JobQueue config properties
+org.apache.oodt.cas.resource.jobqueue.jobstack.maxstacksize=1000
+
+# XML LRUScheduler config properties
+org.apache.oodt.cas.resource.scheduler.wait.seconds=20
+
+# XML-RPC configuration props
+org.apache.oodt.cas.resource.system.xmlrpc.requestTimeout.minutes=20
+org.apache.oodt.cas.resource.system.xmlrpc.connectionTimeout.minutes=60
+
+# XStream JobRepo configuration props
+org.apache.oodt.cas.resource.jobrepo.xstream.working.dir=[HOME]/job-repo
+org.apache.oodt.cas.resource.jobrepo.xstream.max.history=4000
+
+# XML Node Repository config properties
+org.apache.oodt.cas.resource.nodes.dirs=file://[HOME]/nodes,file://[HOME]/nodes2
+
+# XML Queue Repository config properties
+org.apache.oodt.cas.resource.nodetoqueues.dirs=file://[HOME]/nodes,file://[HOME]/nodes2
+
+# Load calculation weights
+org.apache.oodt.cas.resource.monitor.loadcalc.weight.loadone=1
+org.apache.oodt.cas.resource.monitor.loadcalc.weight.loadfive=5
+org.apache.oodt.cas.resource.monitor.loadcalc.weight.loadfifteen=5
+org.apache.oodt.cas.resource.monitor.loadcalc.weight.memfree=2
+org.apache.oodt.cas.resource.monitor.loadcalc.weight.swapfree=1
+
+#ganglia meta daemon (gmetad) host details
+org.apache.oodt.cas.resource.monitor.ganglia.gemtad.host.address=localhost
+org.apache.oodt.cas.resource.monitor.ganglia.gemtad.host.port=8651
+
diff --git a/0.8.1-rc1/resource/src/main/scala/org/apache/oodt/cas/resource/examples/ScalaHelloWorld.scala b/0.8.1-rc1/resource/src/main/scala/org/apache/oodt/cas/resource/examples/ScalaHelloWorld.scala
new file mode 100644
index 0000000..2cb1b9a
--- /dev/null
+++ b/0.8.1-rc1/resource/src/main/scala/org/apache/oodt/cas/resource/examples/ScalaHelloWorld.scala
@@ -0,0 +1,32 @@
+package org.apache.oodt.cas.resource.examples;
+
+import org.apache.oodt.cas.resource.structs.SparkInstance;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.NameValueJobInput;
+import org.apache.spark.SparkContext;
+/**
+* @author starchmd
+*
+* An example class for use with the Spark backend to the resource manager.
+*/
+class ScalaHelloWorld extends SparkInstance {
+    var sc : SparkContext = null;
+    /**
+     * Execute this job.
+     */
+    def execute(input: JobInput) : Boolean = {
+        val name = input.asInstanceOf[NameValueJobInput].getValue("file");
+        val textFile = sc.textFile(name);
+        val linesWithSpark = textFile.filter(line => line.contains("fantastic"));
+        var ln = linesWithSpark.count();
+        println("Line count: "+ln);
+        textFile.foreach(line => println(line));
+        return true;
+    }
+    /**
+     * Set the spark context.
+     */
+    def setSparkContext(context: SparkContext) {
+        this.sc = context;
+    }
+}
diff --git a/0.8.1-rc1/resource/src/site/resources/images/cas-resource.jpg b/0.8.1-rc1/resource/src/site/resources/images/cas-resource.jpg
new file mode 100644
index 0000000..4eaed75
--- /dev/null
+++ b/0.8.1-rc1/resource/src/site/resources/images/cas-resource.jpg
Binary files differ
diff --git a/0.8.1-rc1/resource/src/site/resources/images/cas-resource.psd b/0.8.1-rc1/resource/src/site/resources/images/cas-resource.psd
new file mode 100644
index 0000000..1ad320b
--- /dev/null
+++ b/0.8.1-rc1/resource/src/site/resources/images/cas-resource.psd
Binary files differ
diff --git a/0.8.1-rc1/resource/src/site/resources/images/rm_extension_points.png b/0.8.1-rc1/resource/src/site/resources/images/rm_extension_points.png
new file mode 100644
index 0000000..b13542f
--- /dev/null
+++ b/0.8.1-rc1/resource/src/site/resources/images/rm_extension_points.png
Binary files differ
diff --git a/0.8.1-rc1/resource/src/site/resources/images/rm_object_model.png b/0.8.1-rc1/resource/src/site/resources/images/rm_object_model.png
new file mode 100644
index 0000000..0f86114
--- /dev/null
+++ b/0.8.1-rc1/resource/src/site/resources/images/rm_object_model.png
Binary files differ
diff --git a/0.8.1-rc1/resource/src/site/resources/images/rm_use_case1.jpg b/0.8.1-rc1/resource/src/site/resources/images/rm_use_case1.jpg
new file mode 100644
index 0000000..4d655c1
--- /dev/null
+++ b/0.8.1-rc1/resource/src/site/resources/images/rm_use_case1.jpg
Binary files differ
diff --git a/0.8.1-rc1/resource/src/site/site.xml b/0.8.1-rc1/resource/src/site/site.xml
new file mode 100644
index 0000000..b47ed7d
--- /dev/null
+++ b/0.8.1-rc1/resource/src/site/site.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<project name="cas-resource">
+
+  <body>
+    <links>
+      <item name="OODT" href="../oodt-site/"/>
+    </links>
+
+    <menu ref="reports" inherit="bottom"/>
+    <menu name="Software Documentation">
+      <item name="User Guide" href="user/"/>
+    </menu>
+  </body>
+</project>
diff --git a/0.8.1-rc1/resource/src/site/xdoc/user/index.xml b/0.8.1-rc1/resource/src/site/xdoc/user/index.xml
new file mode 100644
index 0000000..373d8ce
--- /dev/null
+++ b/0.8.1-rc1/resource/src/site/xdoc/user/index.xml
@@ -0,0 +1,495 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS Resource Manager User Guide</title>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+   </properties>
+
+   <body>
+      <section name="User Guide">
+        <p>
+          This is the user guide for the OODT Catalog and Archive Service (CAS) Resource Manager 
+          component, or Resource Manager for short. This guide explains the Resource Manager architecture 
+          including its extension points. The guide also discusses available services provided 
+          by the Resource Manager, how to utilize them, and the different APIs that exist. The guide 
+          concludes with a description of Resource Manager use cases.
+        </p>     
+      </section>
+      <section name="Architecture">
+        <p>The Resource Manager component is responsible for execution, monitoring and tracking of jobs,
+        storage and networking resources for an underlying set of hardware resources. The Resource Manager is an 
+        extensible software component that provides an XML-RPC external interface, and a fully 
+        tailorable Java-based API for resource management. The critical objects managed by the Resource 
+        Manager include:</p>
+        
+        <ul>
+         <li>Job - an abstract representation of an execution unit, that stores information about an 
+         underlying program, or execution that must be run on some hardware node, including information about the 
+         Job Input that the Job requires, information about the job load, and the queue that the job should
+         be submitted to.</li>
+         <li>Job Input - an abstract representation of the input that a Job requires.</li>
+         <li>Job Spec - a complete specification of a Job, including its Job Input, and the Job definition
+         itself.</li>
+         <li>Job Instance - the physical code that performs the underlying job execution.</li>
+         <li>Resource Node - an available execution node that a Job is sent to by the Resource Manager.</li>
+        </ul>
+
+        <p>Each Job Spec contains exactly 1 Job, and Job Input. Each Job Input is provided to a single Job.
+        Each Job describes a single Job Instance. And finally, each Job is sent to exactly one Resource Node.
+        These relationships are shown in the below figure.</p>
+        
+        <img src="../images/rm_object_model.png" alt="Resource Manager Object Model"/> 
+      
+        <subsection name="Extension Points">
+          <p>
+          There are several extension points for the Resource Manager. An extension point is an interface 
+          within the Resource Manager that can have many implementations. This is particularly useful when 
+          it comes to software component configuration because it allows different implementations of an 
+          existing interface to be selected at deployment time. So, the Resource Manager component may 
+          submit Jobs to a custom XML-RPC batch submission system, or it may use an available off-the-shelf 
+          batch submission system, such as LSF or Load-Share. The selection  of the actual component implementations 
+          is handled entirely by the extension point mechanism. Using extension points, it is fairly simple to support 
+          many different types of what are typically referred to as "plug-in architectures" Each of the core extension 
+          points for the Resource Manager is described below:</p>
+          
+          <table>
+            <tr>
+              <td>Batch Manager</td>
+              <td>The Batch Manager extension point is responsible for sending Jobs to the actual nodes
+              that the Resource Manager determines that it is appropriate that they execute on. A Batch Manager
+              typically includes a client service, to communicate with remote "stubs", which run on the local
+              compute nodes, and actual handle the physical execution of the provided Jobs.
+              </td>
+            </tr>
+            <tr>
+              <td>Job Queue</td>
+              <td>The Job Queue extension point is responsible for queueing up Jobs when the Resource Manager
+              determines that there are no Resource Nodes available to execute the Job on. Capabilities such as
+              persistence, and queueing policy (e.g., LRU, FIFO) are all dealt with by this extension point.</td>
+            </tr>
+            <tr>
+              <td>Job Repository</td>
+              <td>The Job Repository is responsible for actual persistance of a Job, throughout its lifecycle in
+              the Resource Manager. A Job Repository would handle the ability to retrieve Job and Job Spec information
+              whether the Job is queued, or executing, or finished.</td>
+            </tr>
+            <tr>
+              <td>Monitor</td>
+              <td>The Monitor extension point is responsible for monitoring the execution of a Job once it has been sent to a
+              Resource Node by the Batch Manager extension point.</td>
+            </tr>
+            <tr>
+              <td>Job Scheduler</td>
+              <td>The Job Scheduler extension point is responsible for determining the availability of underlying Resource Nodes
+              managed by the Resource Manager, and determining the policy for pulling Jobs off of the Job Queue to schedule
+              for execution, interacting with the Job Repository, the Batch Manager, the Monitor, and nearly all of the
+              underlying extension points in the Resource Manager. </td>
+            </tr>
+             <tr>
+              <td>System</td>
+              <td>The extension point that provides the external interface to the Resource Manager 
+              services. This includes the Resource Manager server interface, as well as the associated 
+              Resource Manager client interface, that communicates with the server.
+              </td>
+            </tr>          
+          
+          </table>
+          
+          <p>The relationships between the extension points for the Resource Manager are shown in the below
+          Figure.
+          </p>
+          
+          <img src="../images/rm_extension_points.png" alt="Resource Manager Extension Points"/>
+        
+        </subsection>
+        <subsection name="Key Capabilities">
+        <p>The Resource Manager is responsible for providing the necessary key capabilities for managing 
+        job execution and underlying hardware resources. Each high level capability provided by the Resource 
+        Manager is detailed below:</p>
+        
+        <ol>
+          <li>Easy execution - of compute jobs to heterogeneous computing resources, with very different underlying
+          specifications: large and small disks, network file storage, storage area networks, and exotic processor
+          architectures.</li>
+          <li>Cluster Management Pluggability - the ability to plug into existing batch submission systems (e.g., Torque, LSF), and 
+          resource monitoring (e.g., Ganglia).</li>
+          <li>Scalability – The Resource Manager uses the popular client-server paradigm, allowing new Resource Manager 
+          servers to be instantiated, as needed, without affecting the Resource Manager clients, and vice-versa. </li>
+          <li>Communication over lightweight, standard protocols – The Resource Manager uses XML-RPC, as its main 
+          external interface, between Resource Manager client and server. XML-RPC, the little brother of SOAP, is 
+          fast, extensible, and uses the underlying HTTP protocol for data transfer.</li>
+          <li>Wrapping - the use of wrappers to insulate the internal code of Job Instances from their external interfaces
+          allows a variety of different popular programming languages (e.g., shell scripting, Java, Python, Perl, Ruby) to be
+          used to implement the actual job.</li>
+          <li>Scheduler Pluggability - the ability to define the underlying job scheduling policy.</li>
+          <li>XML-based job description - allows for existing XML-based editing tools to visualize the different job
+          properties, and for standard job definitions, and interchange.</li>
+         </ol>
+          
+          <p>This capability set is not exhaustive, and is meant to give the user a "feel" for what 
+          general features are provided by the Resource Manager. Most likely the user will find that the 
+          Resource Manager provides many other capabilities besides those described here.</p>
+          
+        </subsection>
+        <subsection name="Current Extension Point Implementations">
+        
+         <p>There is at least one implementation of all of the aforementioned extension points for 
+         the Resource Manager. Each extension point implementation is detailed below:</p>
+            
+         <ul>
+           <li><b>Batch Manager</b><br/>
+            <ol>
+             <li>XML-RPC based Batch Manager – an implementation of the Batch Manager extension point that uses
+             a custom, light-weight XML-RPC Batch Submission system, and batch stubs deployed on each of the Resource
+             Nodes.</li>
+           </ol>
+           </li>
+           <li><b>Job Queue</b><br/>
+             <ol>
+               <li>Stack based Job Queue - an implementation of the Job Queue extension point that uses a common
+               Stack data structure to queue up Jobs in memory.
+               </li>
+             </ol>
+           </li>
+           <li><b>Job Repository</b><br/>
+             <ol>
+               <li>Memory based Job Repository - an implementation of the Job Repository extension point that uses
+               an in memory persistance layer to record Job and Job Spec information.
+               </li>
+             </ol>
+           </li>
+           <li><b>Monitor</b><br/>
+             <ol>
+               <li>Assignment Job Monitor - an implementation of the Monitor extension point that uses internal profiling
+               to keep track of Job status, and Resource Node load.
+               </li>
+             </ol>
+           </li>           
+           <li><b>Job Scheduler</b><br/>
+             <ol>
+               <li>LRU based Scheduler - an implementation of the Scheduler extension point that uses a 
+               <a href="http://en.wikipedia.org/wiki/Cache_algorithms">Least Recently Used (LRU)</a> approach
+               to selecting Jobs for submission to the Batch Manager.
+               </li>
+             </ol>
+           </li> 
+           <li><b>System (Resource Manager client and Resource Manager server)</b><br/>
+             <ol>
+               <li>XML-RPC based Resource Manager server – an implementation of the external server interface
+               for the Resource Manager that uses XML-RPC as the transportation medium.
+               </li>
+               <li>XML-RPC based Resource Manager client – an implementation of the client interface for the 
+               XML-RPC Resource Manager server that uses XML-RPC as the transportation medium.
+               </li>
+             </ol>
+           </li>            	
+           </ul>  
+        
+        </subsection>
+      
+      </section>
+      <section name="Configuration and Installation">
+       <p>
+       To install the Resource Manager, you need to download a <a href="../../">release</a>
+       of the Resource Manager, available from its home web site. For bleeding-edge features, you can
+       also check out the resource trunk project from the OODT subversion repository. You can browse 
+       the repository using ViewCVS, located at:</p>
+       
+       <screen>http://svn.apache.org/viewvc/oodt/</screen>
+       
+       <p>The actual web url for the repository is located at:</p>
+       
+       <screen>https://svn.apache.org/repos/asf/oodt/trunk/resource</screen>
+
+       <p>To check out the Resource Manager, use your favorite Subversion client.</p>   
+      
+      <subsection name="Project Organization">
+        <p>
+       The cas-resource project follows the traditional Subversion-style <code>trunk</code>, <code>tag</code>
+       and <code>branches</code> format. Trunk corresponds to the latest and greatest development on the
+       cas-resource. Tags are official release versions of the project. Branches correspond to deviations 
+       from the trunk large enough to warrant a separate development tree. </p>
+
+       <p>For the purposes of this the User Guide, we'll assume you already have downloaded a built release
+       of the Resource Manager, from its web site. If you were building cas-resource from the trunk, a tagged release 
+       (or branch) the process would be quite similar. To build cas-resource, you would need the Apache Maven 
+       software. Maven is an XML-based, project management system similar to Apache Ant, but with many extra 
+       bells and whistles. Maven makes cross-platform project development a snap. You can download Maven from:
+
+      <a href="http://maven.apache.org">http://maven.apache.org</a>
+
+       All cas-resource releases post 1.0.1 are now <b>Maven 2 compatible</b>. This is <b>very</b> important. 
+       That means that if you have any cas-resource release > 1.0.1, you will need Maven 2 to compile the software, 
+       and Maven 1 will no longer work.</p>
+       
+       <p>Follow the procedures in the below Sections to build a fresh copy of the Resource Manager. These procedures
+       are specifically targeted on using Maven 2 to build the software: 
+        </p>        
+     
+      </subsection>
+      
+      <subsection name="Building the Resource Manager">
+        <p>
+          <ol>
+            <li>cd to cas-resource, and then type:
+           <source># mvn package</source>
+           This will perform several tasks, including compiling the source code, downloading 
+           required jar files, running unit tests, and so on. When the command completes, cd 
+           to the <code>target</code> directory within cas-resource. This will 
+           contain the build of the Resource Manager component, of the following form:
+           
+           <source>
+            cas-resource-${version}-dist.tar.gz
+           </source>
+           
+           This is a distribution tar ball, that you would copy to a deployment directory, such as
+           <code>/usr/local/</code>, and then unpack using <code># tar xvzf </code>. The resultant directory 
+           layout from the unpacked tarball is as follows:
+           
+           <source>
+            bin/ etc/ logs/ doc/ lib/ policy/ LICENSE.txt CHANGES.txt
+           </source>
+            <ul>
+              <li>bin - contains the "resmgr" server script, and the "resmgr-client" client script.</li>
+              <li>etc - contains the logging.properties file for the Resource Manager, and the resource.properties 
+              file used to configure the server options.</li>
+              <li>logs - the default directory for log files to be written to.</li>
+              <li>doc - contains Javadoc documentation, and user guides for using the particular CAS component.</li>
+              <li>lib - the required Java jar files to run the Resource Manager.</li>
+              <li>policy – the default XML-based element and product type policy in 
+              case the user is using the XML Repository Manager and/or the XML Validation 
+              Layer.</li>
+              <li>CHANGES.txt - contains the CHANGES present in this released version of the CAS component.</li>
+              <li>LICENSE.txt - the LICENSE for the Resource Manager project.</li>
+            </ul>
+          </li>
+         </ol>        
+        </p>
+      
+      </subsection>
+      <subsection name="Deploying the Resource Manager">
+      <p>To deploy the Resource Manager, you'll need to create an installation directory. Typically this 
+      would be somewhere in /usr/local (on *nix style systems), or C:\Program Files\ (on windows 
+      style systems). We'll assume that you're installing on a *nix style system though the Windows 
+      instructions are quite similar.</p>
+
+      <p>Follow the process below to deploy the Resource Manager:</p>
+
+        <ol>
+         <li>Copy the binary distribution to the deployment directory
+         <source># cp -R cas-resource/trunk/target/cas-resource-${version}-dist.tar.gz /usr/local/</source>
+         </li>
+         <li>Untar the distribution
+         <source># cd /usr/local ; tar xvzf cas-resource-${version}-dist.tar.gz</source>
+         </li>
+         <li>Set up a symlink
+         <source># ln -s /usr/local/cas-resource-${version} /usr/local/resmgr</source>
+         </li>
+         <li>edit /usr/local/resmgr/bin/resmgr
+          <ul>
+           <li>Set the <code>SERVER_PORT</code> variable to the desired port you'd like to run the 
+           Resource Manager server on.
+           </li>
+           <li>Set the <code>JAVA_HOME</code> variable to point to the location of your installed 
+           JRE runtime.
+           </li>
+           <li>Set the <code>RUN_HOME</code> variable to point to the location you'd like the Resource 
+           Manager PID file written to. Typically this should default to <code>/var/run</code>, but not all 
+           system administrators allow users to write to <code>/var/run</code>.
+           </li>
+          </ul>
+          </li>
+           <li>edit <code>/usr/local/resmgr/bin/resmgr-client</code>
+             <ul>
+               <li>Set the <code>JAVA_HOME</code> variable to point to the location of your installed JRE runtime.
+               </li>
+             </ul>
+           </li>
+           <li>(optional) edit <code>/usr/local/resmgr/etc/logging.properties</code>
+            <ul>
+             <li>Set the logging levels for each subsystem to the desired level. The system 
+             defaults are fairly considerate and prevent much of the logging at levels below <code>INFO</code>
+             to the console. </li>
+            </ul>
+           </li>
+           <li>edit <code>/usr/local/resmgr/etc/resource.properties</code>
+            <ul>
+             <li>This java properties file contains all of the default information properties to 
+             configure the Resource Manager. By default, the Resource Manager is built to use the XML-based 
+             Assignment Monitor, the MemoryJobRepository, the LRUScheduler, and the JobStackJobQueue
+             extension points.. These defaults can be changed quite easily by changing the factory classes 
+             that are pointed to for each extension point. For example, to use your own own home Scheduler 
+             extension point, you would change the following property, <code>resmgr.scheduler.factory</code> to 
+             <code>org.apache.oodt.cas.resmgr.scheduler.YourNewSchedulerFactory</code>
+            </li>
+            <li>You need to configure the properties for each of the extension points that you are 
+            using. By default, you would at least need to configure:
+              <ul>
+                <li>The paths to the directories where the XML policy files are stored for the 
+                XML Assignment Monitor. A good default location is to 
+                place these files within /usr/local/resmgr/policy.</li>
+              </ul>
+            </li>
+           </ul>
+          </li>
+          <li>Make sure that  <code>/usr/local/resmgr/policy/nodes.xml</code> and <code>node-to-queue-mapping.xml</code>  
+          correctly point at the batch stub considered to start for execution (by default, localhost:2001). 
+          </li>
+       </ol>
+   
+     <p>Other configuration options are possible: check the <a href="../../apidocs/org/apache/oodt/cas/resource">API documentation</a>, 
+     as well as the comments within the resource.properties file to find out the rest of the configurable 
+     properties for the extension points you choose. A full listing of all the extension point factory 
+     class names are provided in the Appendix. After step 7, you are officially done configuring the Resource 
+     Manager for deployment.</p>   
+      
+      </subsection>
+      <subsection name="Running the Resource Manager">
+      <p>To run the resmgr, cd to <code>/usr/local/resmgr/bin</code> and type:</p>
+
+      <source># ./resmgr start</source>
+
+      <p>This will startup the Resource Manager XML-RPC server interface. Your Resource Manager 
+      is now ready to run! You can test out the Resource Manager by submitting the following example
+      Job, defined in the XML file below (save the file to a location on your system, such as
+      <code>/usr/local/resmgr/examples/exJob.xml</code>):</p>
+      
+      <!-- FIXME: Change namespace URI? -->
+      <source>
+      &lt;?xml version="1.0" encoding="UTF-8" ?&gt;
+      &lt;cas:job xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" id="abcd"
+	      name="TestJob"&gt;
+	      &lt;instanceClass
+		name="org.apache.oodt.cas.resource.examples.HelloWorldJob" /&gt;
+	  &lt;inputClass
+		name="org.apache.oodt.cas.resource.structs.NameValueJobInput"&gt;
+		&lt;properties&gt;
+			&lt;property name="user.name" value="Homer!" /&gt;
+		&lt;/properties&gt;
+	    &lt;/inputClass&gt;
+	  &lt;queue&gt;quick&lt;/queue&gt;
+	  &lt;load&gt;1&lt;/load&gt;
+     &lt;/cas:job&gt;
+    </source>
+    
+      <p>The above job definition tells the resource manager to execute the <code>org.apache.oodt.cas.resource.examples.HelloWorldJob</code>,
+      which is one of the example Jobs that is shipped with the Resource Manager. The job simply echoes the name provided in the <code>user.name</code>
+      property back to the screen, saying <code>Hello ${user.name}!</code>.
+      </p>
+
+      <p>To run the job, first you must start an XML-RPC batch stub, to execute the job on the local node. Let's assume a default port of port <code>2001</code>:</p>
+
+      <source># ./batch_stub 2001
+      </source>
+      
+      <p>The command to run the job, assuming that you started the Resource Manager on the default port of <code>9002</code>:</p>
+
+      <source>
+      java -Djava.ext.dirs=../lib org.apache.oodt.cas.resource.tools.JobSubmitter \
+                       --rUrl http://localhost:9002 \
+                       --file /usr/local/resmgr/examples/exJob.xml
+      </source>
+
+      <p>You should see a response message at the end similar to:</p>
+
+      <source>
+      Mar 5, 2008 10:45:26 AM org.apache.oodt.cas.resource.jobqueue.JobStack addJob<br/>
+      INFO: Added Job: [2008-03-05T10:45:26.148-08:00] to queue<br/>
+      Mar 5, 2008 10:45:26 AM org.apache.oodt.cas.resource.tools.JobSubmitter main<br/>
+      INFO: Job Submitted: id: [2008-03-05T10:45:26.148-08:00]<br/>
+      Mar 5, 2008 10:45:27 AM org.apache.oodt.cas.resource.scheduler.LRUScheduler run<br/>
+      INFO: Obtained Job: [2008-03-05T10:45:26.148-08:00] from Queue: Scheduling for execution<br/>
+      Mar 5, 2008 10:45:27 AM org.apache.oodt.cas.resource.scheduler.LRUScheduler schedule<br/>
+      INFO: Assigning job: [TestJob] to node: [node001] <br/>
+      Mar 5, 2008 10:45:27 AM org.apache.oodt.cas.resource.system.extern.XmlRpcBatchStub genericExecuteJob<br/>
+      INFO: stub attempting to execute class: [org.apache.oodt.cas.resource.examples.HelloWorldJob]<br/>
+      Hello world! How are you Homer!!
+      </source>
+
+    <p>which means that everything installed okay!</p>
+    
+      </subsection>
+      
+      </section>
+      <section name="Use Cases">
+        <p>
+          The Resource Manager was built to support several of the above capabilities outlined above. 
+          In particular there were several use cases that we wanted to support, some 
+          of which are described below.        
+        </p>
+      
+         <img src="../images/rm_use_case1.jpg" alt="Resource Manager Job Execution Use Case"/>
+         
+          <p>The black numbers in the above Figure correspond to a sequence of steps that occurs and a 
+         series of interactions between the different Resource Manager extension points in order to 
+         perform the job execution activity. The Job provided to the Resource Manager (labeled <code>Process Manager</code>
+         in the above diagram) is sent by the Workflow Manager, another CAS component responsible for modeling task
+         control flow and data flow. In Step 7, the job is provided to the Resource Manager, which uses its
+         Scheduler extension point in Step 8, along with the Monitor extension point, to determine the appropriate
+         Resource Node to execute the provided Job on (in steps 9-11). The information returned in Step 11 to the
+         Scheduler is then used to determine Job execution ability. Once the Job is determined "ready to run", in 
+         Step 12, the Scheduler extension point uses the Batch Manager extension point (not shown) to submit the
+         Job to the underlying compute cluster nodes, monitoring the Job execution using the Monitor extension point
+         shown in Step 13.</p>
+         
+      </section>
+      <section name="Appendix">
+       <p>
+         Full list of Resource Manager extension point classes and their associated property names from the 
+         resource.properties file:       
+       </p>
+       <table>
+         <thead>
+            <tr>
+                <th>Property Name</th>
+                <th>Extension Point Class</th>
+            </tr>
+         </thead>
+         <tbody>
+         <tr>
+           <td>resource.batchmgr.factory</td>
+           <td>org.apache.oodt.cas.resource.batchmgr.XmlRpcBatchMgrFactory
+           </td>
+         </tr>
+         <tr>
+           <td>resource.monitor.factory</td>
+           <td>org.apache.oodt.cas.resource.monitor.XMLAssignmentMonitorFactory
+           </td>
+         </tr>
+         <tr>
+           <td>resource.scheduler.factory</td>
+           <td>org.apache.oodt.cas.resource.scheduler.LRUSchedulerFactory
+           </td>
+         </tr>
+         <tr>
+           <td>resource.jobqueue.factory</td>
+           <td>org.apache.oodt.cas.resource.jobqueue.JobStackJobQueueFactory
+           </td>
+         </tr>
+         <tr>
+           <td>resource.jobrepo.factory</td>
+           <td>org.apache.oodt.cas.resource.jobrepo.MemoryJobRepositoryFactory</td>
+         </tr>
+         </tbody>
+       </table>
+      
+      </section>
+   </body>
+   
+</document>
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/cli/TestResourceCli.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/cli/TestResourceCli.java
new file mode 100644
index 0000000..4ad07fa
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/cli/TestResourceCli.java
@@ -0,0 +1,265 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.cli.CmdLineUtility;
+import org.apache.oodt.cas.cli.util.OptionPropertyRegister;
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.system.MockXmlRpcResourceManagerClient;
+import org.apache.oodt.cas.resource.system.MockXmlRpcResourceManagerClient.MethodCallDetails;
+import org.apache.oodt.cas.resource.util.JobBuilder;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Test class for cas-cli command line for resource manager.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestResourceCli extends TestCase {
+
+   static {
+      System.setProperty("org.apache.oodt.cas.cli.debug", "true");
+      System.setProperty("org.apache.oodt.cas.cli.action.spring.config", "src/main/resources/cmd-line-actions.xml");
+      System.setProperty("org.apache.oodt.cas.cli.option.spring.config", "src/main/resources/cmd-line-options.xml");
+      System.setProperty("resource.scheduler.factory", "org.apache.oodt.cas.resource.MockScheduler");
+   }
+
+   private CmdLineUtility cmdLineUtility;
+   private MockXmlRpcResourceManagerClient client;
+
+   @Override
+   public void setUp() throws Exception {
+      cmdLineUtility = new CmdLineUtility();
+      UseMockClientCmdLineActionStore actionStore = new UseMockClientCmdLineActionStore();
+      client = actionStore.getClient();
+      cmdLineUtility.setActionStore(actionStore);
+   }
+
+   @Override
+   public void tearDown() throws Exception {
+      OptionPropertyRegister.clearRegister();
+   }
+
+   public void testAddNode() throws MalformedURLException {
+      int capacity = 10;
+      String nodeId = "TestNodeId";
+      String ipAddr = "http://localhost:9999";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --addNode --capacity " + capacity + " --nodeId "
+            + nodeId + " --ipAddr " + ipAddr).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("addNode", methodCallDetails.getMethodName());
+      ResourceNode actualNode = (ResourceNode) methodCallDetails.getArgs().get(0);
+      ResourceNode expectedNode = new ResourceNode(nodeId, new URL(ipAddr), capacity);
+      assertEquals(expectedNode.getIpAddr(), actualNode.getIpAddr());
+      assertEquals(expectedNode.getCapacity(), actualNode.getCapacity());
+      assertEquals(expectedNode.getNodeId(), actualNode.getNodeId());
+   }
+
+   public void testAddNodeToQueue() {
+      String queueName = "TestQueueName";
+      String nodeId = "TestNodeId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --addNodeToQueue --queueName " + queueName + " --nodeId "
+            + nodeId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("addNodeToQueue", methodCallDetails.getMethodName());
+      assertEquals(nodeId, methodCallDetails.getArgs().get(0));
+      assertEquals(queueName, methodCallDetails.getArgs().get(1));
+   }
+
+   public void testAddQueue() {
+      String queueName = "TestQueueName";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --addQueue --queueName " + queueName).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("addQueue", methodCallDetails.getMethodName());
+      assertEquals(queueName, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetExecNode() {
+      String jobId = "TestJobId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getExecNode --jobId " + jobId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getExecutionNode", methodCallDetails.getMethodName());
+      assertEquals(jobId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetJobInfo() {
+      String jobId ="TestJobId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getJobInfo --jobId " + jobId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getJobInfo", methodCallDetails.getMethodName());
+      assertEquals(jobId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetNodeById() {
+      String nodeId = "TestNodeId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getNodeById --nodeId " + nodeId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getNodeById", methodCallDetails.getMethodName());
+      assertEquals(nodeId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetNodeLoad() {
+      String nodeId = "TestNodeId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getNodeLoad --nodeId " + nodeId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getNodeLoad", methodCallDetails.getMethodName());
+      assertEquals(nodeId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetNodes() {
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getNodes").split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getNodes", methodCallDetails.getMethodName());
+      assertEquals(0, methodCallDetails.getArgs().size());
+   }
+
+   public void testGetNodesInQueue() {
+      String queueName = "TestQueueName";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getNodesInQueue --queueName "
+            + queueName).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getNodesInQueue", methodCallDetails.getMethodName());
+      assertEquals(queueName, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetQueues() {
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getQueues").split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getQueues", methodCallDetails.getMethodName());
+      assertEquals(0, methodCallDetails.getArgs().size());
+   }
+
+   public void testGetQueuesWithNode() {
+      String nodeId = "TestNodeId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getQueuesWithNode --nodeId "
+            + nodeId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getQueuesWithNode", methodCallDetails.getMethodName());
+      assertEquals(nodeId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testKill() {
+      String jobId = "TestJobId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --kill --jobId "
+            + jobId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("killJob", methodCallDetails.getMethodName());
+      assertEquals(jobId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testRemoveNode() {
+      String nodeId = "TestNodeId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --removeNode --nodeId "
+            + nodeId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("removeNode", methodCallDetails.getMethodName());
+      assertEquals(nodeId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testRemoveNodeFromQueue() {
+      String nodeId = "TestNodeId";
+      String queueName = "TestQueueNames";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --removeNodeFromQueue --nodeId "
+            + nodeId + " --queueName " + queueName).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("removeNodeFromQueue", methodCallDetails.getMethodName());
+      assertEquals(nodeId, methodCallDetails.getArgs().get(0));
+      assertEquals(queueName, methodCallDetails.getArgs().get(1));
+   }
+
+   public void testRemoveQueue() {
+      String queueName = "TestQueueName";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --removeQueue --queueName "
+            + queueName).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("removeQueue", methodCallDetails.getMethodName());
+      assertEquals(queueName, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testSetNodeCapacity() {
+      int capacity = 4;
+      String nodeId = "TestNodeId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --setNodeCapacity --capacity "
+            + capacity + " --nodeId " + nodeId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("setNodeCapacity", methodCallDetails.getMethodName());
+      assertEquals(nodeId, methodCallDetails.getArgs().get(0));
+      assertEquals(capacity, methodCallDetails.getArgs().get(1));
+   }
+
+   public void testSubmitJob() throws MalformedURLException {
+      String jobDefinitionFile = "src/main/resources/examples/jobs/exJob.xml";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --submitJob --def "
+            + jobDefinitionFile).split(" "));
+      JobSpec spec = JobBuilder.buildJobSpec(jobDefinitionFile);
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("submitJob", methodCallDetails.getMethodName());
+      Job actualJob = (Job) methodCallDetails.getArgs().get(0);
+      assertEquals(spec.getJob().getJobInstanceClassName(), actualJob.getJobInstanceClassName());
+      assertEquals(spec.getJob().getJobInputClassName(), actualJob.getJobInputClassName());
+      assertEquals(spec.getJob().getQueueName(), actualJob.getQueueName());
+      assertEquals(spec.getJob().getLoadValue(), actualJob.getLoadValue());
+      JobInput actualJobInput = (JobInput) methodCallDetails.getArgs().get(1);
+      assertEquals(spec.getIn().getClass(), actualJobInput.getClass());
+      assertEquals(2, methodCallDetails.getArgs().size());
+
+      OptionPropertyRegister.clearRegister();
+
+      String url = "http://localhost:9000";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --submitJob --def "
+            + jobDefinitionFile + " --nodeUrl " + url).split(" "));
+      methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("submitJob", methodCallDetails.getMethodName());
+      actualJob = (Job) methodCallDetails.getArgs().get(0);
+      assertEquals(spec.getJob().getJobInstanceClassName(), actualJob.getJobInstanceClassName());
+      assertEquals(spec.getJob().getJobInputClassName(), actualJob.getJobInputClassName());
+      assertEquals(spec.getJob().getQueueName(), actualJob.getQueueName());
+      assertEquals(spec.getJob().getLoadValue(), actualJob.getLoadValue());
+      actualJobInput = (JobInput) methodCallDetails.getArgs().get(1);
+      assertEquals(spec.getIn().getClass(), actualJobInput.getClass());
+      assertEquals(new URL(url), methodCallDetails.getArgs().get(2));
+      assertEquals(3, methodCallDetails.getArgs().size());
+   }
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/cli/UseMockClientCmdLineActionStore.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/cli/UseMockClientCmdLineActionStore.java
new file mode 100644
index 0000000..ead68a5
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/cli/UseMockClientCmdLineActionStore.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.cli;
+
+//JDK imports
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.action.store.spring.SpringCmdLineActionStore;
+import org.apache.oodt.cas.cli.exception.CmdLineActionStoreException;
+import org.apache.oodt.cas.resource.cli.action.ResourceCliAction;
+import org.apache.oodt.cas.resource.system.MockXmlRpcResourceManagerClient;
+
+/**
+ * A {@link SpringCmdLineActionStore} which sets {@link WorkflowCliAction}s
+ * to use a {@link MockXmlRpcWorkflowManagerClient}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class UseMockClientCmdLineActionStore extends SpringCmdLineActionStore {
+
+   private MockXmlRpcResourceManagerClient client;
+
+   public UseMockClientCmdLineActionStore() {
+      super(System.getProperty("org.apache.oodt.cas.cli.action.spring.config"));
+      try {
+         client = new MockXmlRpcResourceManagerClient();
+      } catch (Exception e) {
+         throw new RuntimeException(e);
+      }
+   }
+
+   public Set<CmdLineAction> loadSupportedActions() throws CmdLineActionStoreException {
+      Set<CmdLineAction> actions = super.loadSupportedActions();
+      for (CmdLineAction action : actions) {
+         if (action instanceof ResourceCliAction) {
+            ((ResourceCliAction) action).setClient(client);
+         }
+      }
+      return actions;
+   }
+
+   public MockXmlRpcResourceManagerClient getClient() {
+      return client;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/jobqueue/TestJobStack.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/jobqueue/TestJobStack.java
new file mode 100644
index 0000000..cac41c9
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/jobqueue/TestJobStack.java
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.jobqueue;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.resource.jobrepo.JobRepository;
+import org.apache.oodt.cas.resource.jobrepo.MemoryJobRepository;
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test Suite for the {@link JobStack} class.
+ * </p>.
+ */
+public class TestJobStack extends TestCase {
+
+    private JobSpec job1 = null;
+
+    private JobSpec job2 = null;
+
+    private final static int waitTime = 20;
+
+    private final static JobRepository repo = new MemoryJobRepository();
+
+    public TestJobStack() {
+        Job j1 = new Job();
+        j1.setId("booger");
+        j1.setName("pick it");
+
+        JobInput in = null;
+
+        job1 = new JobSpec(in, j1);
+
+        Job j2 = new Job();
+        j2.setId("booger2");
+        j2.setName("pick some more");
+        job2 = new JobSpec(in, j2);
+    }
+
+    protected void setUp() {
+
+    }
+
+    public void testAddJob() {
+        JobStack stack = new JobStack(waitTime, repo);
+
+        List queuedJobs = null;
+
+        try {
+            queuedJobs = stack.getQueuedJobs();
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(queuedJobs);
+        assertEquals(0, queuedJobs.size());
+
+        try {
+            stack.addJob(job1);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertEquals(1, queuedJobs.size());
+    }
+
+    public void testIsEmpty() {
+        JobStack stack = new JobStack(waitTime, repo);
+        assertTrue(stack.isEmpty());
+    }
+
+    public void testPurge() {
+        JobStack stack = new JobStack(waitTime, repo);
+        assertNotNull(stack);
+
+        try {
+            stack.addJob(job1);
+            stack.addJob(job2);
+            stack.addJob(job2);
+
+            List queuedJobs = stack.getQueuedJobs();
+            assertNotNull(queuedJobs);
+            assertEquals(3, queuedJobs.size());
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        try {
+            stack.purge();
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertTrue(stack.isEmpty());
+
+    }
+
+    public void testQueuedJobs() {
+        JobStack stack = new JobStack(waitTime, repo);
+        List queuedJobs = null;
+
+        try {
+            stack.addJob(job1);
+            queuedJobs = stack.getQueuedJobs();
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(queuedJobs);
+        assertEquals(1, queuedJobs.size());
+
+    }
+
+    public void testGetNextJob() {
+        JobStack stack = new JobStack(waitTime, repo);
+        JobSpec nextJob = null;
+
+        try {
+            stack.addJob(job1);
+            stack.addJob(job2);
+            stack.addJob(job2);
+
+            List queuedJobs = stack.getQueuedJobs();
+
+            nextJob = stack.getNextJob();
+            assertEquals(nextJob.getJob().getId(), job1.getJob().getId());
+            assertEquals(queuedJobs.size(), 2);
+            nextJob = stack.getNextJob();
+            assertEquals(nextJob.getJob().getId(), job2.getJob().getId());
+            assertEquals(queuedJobs.size(), 1);
+            nextJob = stack.getNextJob();
+            assertEquals(nextJob.getJob().getId(), job2.getJob().getId());
+            assertEquals(queuedJobs.size(), 0);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+    }
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/monitor/TestAssignmentMonitor.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/monitor/TestAssignmentMonitor.java
new file mode 100644
index 0000000..5368e71
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/monitor/TestAssignmentMonitor.java
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.monitor;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @author bfoster
+ * @author rajith
+ * @version $Revision$
+ * 
+ * <p>
+ * Test Suite for the {@link AssignmentMonitor} service
+ * </p>.
+ */
+public class TestAssignmentMonitor extends TestCase {
+
+    private AssignmentMonitor assgnMon = null;
+
+    protected void setUp() throws IOException {
+        generateTestConfig();
+        assgnMon = new AssignmentMonitorFactory().createMonitor();
+    }
+
+    public void testGetNodes() {
+        List resNodes = null;
+
+        try {
+            resNodes = assgnMon.getNodes();
+        } catch (MonitorException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(resNodes);
+        assertEquals(1, resNodes.size());
+    }
+
+    public void testGetNodeById() {
+        ResourceNode node = null;
+
+        try {
+            node = assgnMon.getNodeById("localhost");
+        } catch (MonitorException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(node);
+        assertEquals("localhost", node.getNodeId());
+    }
+
+    public void testGetNodeInfo() {
+        List resNodes = null;
+
+        try {
+            resNodes = assgnMon.getNodes();
+        } catch (MonitorException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(resNodes);
+
+        boolean hasNode1 = false;
+
+        for (Iterator i = resNodes.iterator(); i.hasNext();) {
+            ResourceNode node = (ResourceNode) i.next();
+            assertNotNull(node);
+            if (node.getNodeId().equals("localhost")) {
+                hasNode1 = true;
+                assertEquals(node.getIpAddr().toExternalForm(),
+                        "http://localhost:2001");
+            }
+            assertEquals(node.getCapacity(), 8);
+        }
+
+        assertTrue(hasNode1);
+    }
+
+    public void testNodeModification() throws MonitorException,
+            MalformedURLException {
+        List<ResourceNode> nodes = new Vector<ResourceNode>(this.assgnMon
+                .getNodes());
+        ResourceNode test1 = new ResourceNode("Test1", new URL(
+                "http://localhost:1111"), 9);
+        ResourceNode test2 = new ResourceNode("Test2", new URL(
+                "http://localhost:2222"), 9);
+        ResourceNode test3 = new ResourceNode("Test3", new URL(
+                "http://localhost:3333"), 9);
+        this.assgnMon.addNode(test1);
+        nodes.add(test1);
+        this.assgnMon.addNode(test2);
+        nodes.add(test2);
+        this.assgnMon.addNode(test3);
+        nodes.add(test3);
+
+        assertTrue(nodes.containsAll(this.assgnMon.getNodes())
+                && this.assgnMon.getNodes().containsAll(nodes));
+        
+        this.assgnMon.removeNodeById(test1.getNodeId());
+        nodes.remove(test1);
+        
+        assertTrue(nodes.containsAll(this.assgnMon.getNodes())
+                && this.assgnMon.getNodes().containsAll(nodes));
+    }
+
+
+    private void generateTestConfig() throws IOException {
+        String propertiesFile = "." + File.separator + "src" + File.separator +
+                "test" + File.separator + "resources" + File.separator + "test.resource.properties";
+
+        System.getProperties().load(new FileInputStream(new File(propertiesFile)));
+
+        System.setProperty("org.apache.oodt.cas.resource.nodes.dirs",
+                "file:" + new File("." + File.separator + "src" + File.separator +
+                        "main" + File.separator + "resources" + File.separator +
+                        "examples").getAbsolutePath());
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/monitor/TestGangliaResourceMonitor.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/monitor/TestGangliaResourceMonitor.java
new file mode 100644
index 0000000..6e9a5e0
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/monitor/TestGangliaResourceMonitor.java
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor;
+
+//Junit imports
+import junit.framework.TestCase;
+
+
+//OODT imports
+import org.apache.oodt.cas.resource.monitor.ganglia.GangliaResourceMonitor;
+import org.apache.oodt.cas.resource.monitor.ganglia.GangliaResourceMonitorFactory;
+import org.apache.oodt.cas.resource.monitor.utils.MockGmetad;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author rajith
+ * @author mattmann
+ * @version $Revision$
+ *
+ * Test Suite for the {@link org.apache.oodt.cas.resource.monitor.ganglia.GangliaResourceMonitor}
+ */
+public class TestGangliaResourceMonitor extends TestCase {
+
+    private GangliaResourceMonitor gangliaResourceMonitor;
+    private ThreadLocal<MockGmetad> mockGmetad = new ThreadLocal<MockGmetad>();
+
+    @Override
+    protected void setUp() throws IOException {
+        generateTestConfig();
+        runMockGmetad();
+
+        gangliaResourceMonitor = (GangliaResourceMonitor)
+                new GangliaResourceMonitorFactory().createMonitor();
+    }
+
+    @Override
+    protected void tearDown(){
+        mockGmetad.remove();
+    }
+
+    public void testGetLoad() {
+        try {
+            ResourceNode resourceNode = new ResourceNode();
+            resourceNode.setId("localhost");
+            assertEquals(1, gangliaResourceMonitor.getLoad(resourceNode));
+        } catch (Exception e) {
+        	e.printStackTrace();
+            fail(e.getMessage());
+        }
+    }
+
+    public void testRemoveNodeById(){
+        try {
+            gangliaResourceMonitor.removeNodeById("localhost");
+            assertNull(gangliaResourceMonitor.getNodeById("remotenode"));
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+    }
+    
+    public void testGetNodes(){
+    	try{
+    		List<ResourceNode> nodes = gangliaResourceMonitor.getNodes();
+    		assertNotNull(nodes);
+    		assertEquals(3, nodes.size());
+    		boolean hasLocal = false;
+    		boolean hasLocal2 = false;
+    		boolean hasRemote = false;
+    		
+    		for(ResourceNode node: nodes){
+    			if(node.getNodeId().equals("localhost")){
+    				hasLocal = true;
+    			}
+    			else if(node.getNodeId().equals("localhost2")){
+    				hasLocal2 = true;
+    			}
+    			else if(node.getNodeId().equals("remotenode")){
+    				hasRemote = true;
+    			}
+    			
+    		}
+    		assertTrue(hasLocal&&hasLocal2&&hasRemote);
+    	}
+    	catch (Exception e){
+    		e.printStackTrace();
+    		fail(e.getMessage());
+    	}
+    }
+    
+    public void testGetNodeById(){
+    	try{
+    		ResourceNode node = gangliaResourceMonitor.getNodeById("localhost");
+    		assertNotNull(node);
+    		assertEquals("localhost", node.getNodeId());
+    		node = gangliaResourceMonitor.getNodeById("localhost2");
+    		assertNotNull(node);
+    		assertEquals("localhost2", node.getNodeId());
+    		node = gangliaResourceMonitor.getNodeById("remotenode");
+    		assertNotNull(node);
+    		assertEquals("remotenode", node.getNodeId());
+    	}
+    	catch(Exception e){
+    		e.printStackTrace();
+    		fail(e.getMessage());
+    	}
+    }
+
+    private void runMockGmetad() {
+        int port = Integer.valueOf(System
+                .getProperty("org.apache.oodt.cas.resource.monitor.ganglia.gemtad.host.port"));
+        String sampleXMLfilePath = "." + File.separator + "src" + File.separator +
+                "test" + File.separator + "resources" + File.separator + "resourcemon" + File.separator + "gangliaXMLdump.xml";
+        mockGmetad.set(new MockGmetad(port, sampleXMLfilePath));
+        Thread mockGmetadServer = new Thread(mockGmetad.get());
+        mockGmetadServer.start();
+    }
+
+    private void generateTestConfig() throws IOException {
+        String propertiesFile = "." + File.separator + "src" + File.separator +
+                "test" + File.separator + "resources" + File.separator + "test.resource.properties";
+        System.getProperties().load(new FileInputStream(new File(propertiesFile)));
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/monitor/TestGangliaXMLParser.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/monitor/TestGangliaXMLParser.java
new file mode 100644
index 0000000..4d212cd
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/monitor/TestGangliaXMLParser.java
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.monitor;
+
+//Junit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+import org.apache.oodt.cas.resource.monitor.ganglia.GangliaMetKeys;
+import org.apache.oodt.cas.resource.monitor.ganglia.GangliaXMLParser;
+import org.apache.oodt.cas.resource.monitor.ganglia.configuration.Cluster;
+import org.apache.oodt.cas.resource.monitor.ganglia.configuration.Host;
+import org.apache.oodt.cas.resource.monitor.ganglia.configuration.Metric;
+
+//JDK imports
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.*;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author rajith
+ * @author mattmann
+ * @version $Revision$
+ *
+ * Test Suite for the {@link GangliaXMLParser}
+ */
+public class TestGangliaXMLParser extends TestCase {
+
+    private List<Cluster> gridConfiguration;
+
+    /**
+     * {@inheritDoc}
+     * Read gangliaXMLdump.xml and build the grid configuration
+     */
+    protected void setUp() throws MonitorException, IOException {
+        StringBuilder stringBuffer = new StringBuilder();
+
+        try {
+            BufferedReader reader = new BufferedReader(new FileReader("." + File.separator +
+                    "src" + File.separator + "test" + File.separator + "resources" + File.separator + "resourcemon"
+                    + File.separator + "gangliaXMLdump.xml"));
+            String line = reader.readLine();
+            while (line != null) {
+                stringBuffer.append(line);
+                line = reader.readLine();
+            }
+            reader.close();
+        } catch (IOException e) {
+            throw new IOException("Unable to read the sample monitoring report from the file: "
+                    + e.getMessage());
+        }
+
+        String buffer = stringBuffer.toString().trim();
+        SAXParserFactory factory = SAXParserFactory.newInstance();
+        javax.xml.parsers.SAXParser parser;
+        GangliaXMLParser gangliaXMLParser;
+        try {
+            parser = factory.newSAXParser();
+            gangliaXMLParser = new GangliaXMLParser();
+            parser.parse(new InputSource(new StringReader(buffer)), gangliaXMLParser);
+            gridConfiguration = gangliaXMLParser.getGridConfiguration();
+        } catch (ParserConfigurationException e) {
+            throw new MonitorException("Error while parsing: " + e.getMessage());
+        } catch (SAXException e) {
+            throw new MonitorException("Error while parsing the XML: " + e.getMessage());
+        } catch (IOException e) {
+            throw new MonitorException("I/O error: " + e.getMessage());
+        }
+    }
+
+    /**
+     * test the "<CLUSTER>" tag data
+     * <CLUSTER NAME="" LOCALTIME="" OWNER="" LATLONG="" URL="">
+     */
+    public void testClusterTag() {
+        Cluster cluster = gridConfiguration.get(0);
+        assertEquals("localcluster", cluster.getName());
+        assertEquals("1370187645", cluster.getLocaltime());
+        assertEquals("oodt", cluster.getOwner());
+        assertEquals("N32.87 W117.22", cluster.getLatLong());
+        assertEquals("http://www.mycluster.org/", cluster.getUrl());
+    }
+
+    /**
+     * test the "<HOST>" tag data
+     * <HOST NAME="" IP="" REPORTED="" TN="" TMAX="" DMAX="" LOCATION="" GMOND_STARTED="">
+     */
+    public void testHostTag() {
+        Host host = ((gridConfiguration.get(0)).getHosts()).get(0);
+        assertEquals("localhost", host.getName());
+        assertEquals("127.0.0.1", host.getIp());
+        assertEquals("1370187637", host.getReported());
+        assertEquals("10", host.getTn());
+        assertEquals("20", host.getTmax());
+        assertEquals("0", host.getDmax());
+        assertEquals("0,0,0", host.getLocation());
+        assertEquals("1370186237", host.getGmondstarted());
+    }
+
+    /**
+     * test the "<METRIC>" tag data
+     * <METRIC NAME="" VAL="" TYPE="" UNITS="" TN="" TMAX="" DMAX="" SLOPE="" SOURCE="">
+     * <EXTRA_DATA>
+     * <EXTRA_ELEMENT NAME="" VAL=""/>
+     * <EXTRA_ELEMENT NAME="" VAL=""/>
+     * ........
+     * </EXTRA_DATA>
+     * </METRIC>
+     */
+    public void testMetricTag() {
+        Metric metric = ((((gridConfiguration.get(0)).getHosts()).get(0)).getMetrics()).get(0);
+        assertEquals("disk_free", metric.getName());
+        assertEquals("307.790", metric.getValue());
+        assertEquals("double", metric.getType());
+        assertEquals("GB", metric.getUnits());
+        assertEquals("143", metric.getTn());
+        assertEquals("180", metric.getTmax());
+        assertEquals("0", metric.getDmax());
+        assertEquals("both", metric.getSlope());
+        assertEquals("gmond", metric.getSource());
+
+        //extra data of the metric
+        HashMap<String, String> extraData = metric.getExtraData();
+        assertEquals("disk", extraData.get(GangliaMetKeys.GROUP));
+        assertEquals("Total free disk space", extraData.get(GangliaMetKeys.DESC));
+        assertEquals("Disk Space Available", extraData.get(GangliaMetKeys.TITLE));
+    }
+
+    /**
+     * test the clusters in the grid
+     */
+    public void testGridClusters(){
+        Cluster localCluster = gridConfiguration.get(0);
+        Cluster remoteCluster = gridConfiguration.get(1);
+        assertEquals("localcluster", localCluster.getName());
+        assertEquals("remotecluster", remoteCluster.getName());
+    }
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/mux/TestQueueMuxBatchmgr.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/mux/TestQueueMuxBatchmgr.java
new file mode 100644
index 0000000..0541c81
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/mux/TestQueueMuxBatchmgr.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.mux;
+
+//OODT imports
+import org.apache.oodt.cas.resource.mux.mocks.MockBatchManager;
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * @author starchmd
+ * @version $Revision$
+ *
+ * <p>
+ * Test Suite for the {@link QueueBatchMonitor} service
+ * </p>.
+ */
+public class TestQueueMuxBatchmgr extends TestCase {
+
+    private QueueMuxBatchManager queue;
+    private MockBatchManager mock1;
+    private MockBatchManager mock2;
+
+    protected void setUp() {
+        BackendManager back = new StandardBackendManager();
+        back.addSet("queue-1", null,(mock1 = new MockBatchManager()), null);
+        back.addSet("queue-2", null,(mock2 = new MockBatchManager()), null);
+        queue = new QueueMuxBatchManager(back);       
+    }
+
+    public void testExecuteRemotely() {
+        try {
+            
+            //Test that the jobs are put in seperate mock-backends based on queues
+            ResourceNode node1 = new ResourceNode();
+            ResourceNode node2 = new ResourceNode();
+    
+            JobSpec spec1 = this.getSpecFromQueue("queue-1");
+            queue.executeRemotely(spec1, node1);
+    
+            JobSpec spec2 = this.getSpecFromQueue("queue-2");
+            queue.executeRemotely(spec2, node2);
+            //Yes...use reference equality, as these must be the exact same object
+            TestCase.assertEquals(spec1,mock1.getCurrentJobSpec());
+            TestCase.assertEquals(spec2,mock2.getCurrentJobSpec());
+            TestCase.assertEquals(node1,mock1.getCurrentResourceNode());
+            TestCase.assertEquals(node2,mock2.getCurrentResourceNode());
+            //Throws exception on bad queue
+            try {
+                queue.executeRemotely(this.getSpecFromQueue("queue-3"),node1);
+                TestCase.fail("Failed to throw JobExecutionException on unknown queue.");
+            } catch(JobExecutionException e) {}
+        } catch (JobExecutionException e) {
+           TestCase.fail("Unexpected Exception: "+e.getMessage());
+        }
+    }
+
+    public void testKillJob() {
+        try {
+            ResourceNode node1 = new ResourceNode();
+            ResourceNode node2 = new ResourceNode();
+    
+            JobSpec spec1 = this.getSpecFromQueue("queue-1");
+            queue.executeRemotely(spec1, node1);
+    
+            JobSpec spec2 = this.getSpecFromQueue("queue-2");
+            queue.executeRemotely(spec2, node2);
+            //Make sure that one can kill a job, and the other job is running
+            TestCase.assertTrue(queue.killJob(spec1.getJob().getId(), node1));
+            TestCase.assertEquals(mock1.getCurrentJobSpec(),null);
+            TestCase.assertEquals(mock2.getCurrentJobSpec(),spec2);
+            //Make sure kill fails with bad queue
+            TestCase.assertFalse(queue.killJob(this.getSpecFromQueue("queue-3").getJob().getId(), node1));
+        } catch (JobExecutionException e) {
+            TestCase.fail("Unexpected Exception: "+e.getMessage());
+        }
+    }
+
+    public void testGetExecNode() {
+        try {
+            ResourceNode node1 = new ResourceNode();
+            ResourceNode node2 = new ResourceNode();
+            node1.setId("Node1-ID");
+            node2.setId("Node2-ID");           
+            JobSpec spec1 = this.getSpecFromQueue("queue-1");
+            queue.executeRemotely(spec1, node1);
+    
+            JobSpec spec2 = this.getSpecFromQueue("queue-2");
+            queue.executeRemotely(spec2, node2);
+            //Make that the execution node is same
+            TestCase.assertEquals(node1.getNodeId(),queue.getExecutionNode(spec1.getJob().getId()));
+            TestCase.assertEquals(node2.getNodeId(),queue.getExecutionNode(spec2.getJob().getId()));
+            //Returns null, if bad-queue
+            TestCase.assertNull(queue.getExecutionNode(this.getSpecFromQueue("queue-3").getJob().getId()));
+        } catch (JobExecutionException e) {
+            TestCase.fail("Unexpected Exception: "+e.getMessage());
+        }
+    }
+
+    private JobSpec getSpecFromQueue(String queue) {
+        JobSpec spec1 = new JobSpec();
+        Job job1 = new Job();
+        job1.setId("000000100000011-"+queue);
+        job1.setQueueName(queue);
+        spec1.setJob(job1);       
+        return spec1;
+    }
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/mux/TestQueueMuxMonitor.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/mux/TestQueueMuxMonitor.java
new file mode 100644
index 0000000..8b91d5a
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/mux/TestQueueMuxMonitor.java
@@ -0,0 +1,204 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.mux;
+
+//OODT imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.oodt.cas.resource.mux.mocks.MockMonitor;
+import org.apache.oodt.cas.resource.scheduler.QueueManager;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+
+import org.apache.oodt.cas.resource.structs.exceptions.QueueManagerException;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * @author starchmd
+ * @version $Revision$
+ *
+ * <p>
+ * Test Suite for the {@link QueueBatchMonitor} service
+ * </p>.
+ */
+public class TestQueueMuxMonitor extends TestCase {
+
+    private QueueMuxMonitor monitor;
+    private MockMonitor mock1;
+    private MockMonitor mock2;
+    private ResourceNode superfluous;
+    private QueueManager qm;
+    Map<MockMonitor,List<ResourceNode>> map;
+
+    protected void setUp() {
+        try {
+            //Map monitor to nodes list
+            map = new HashMap<MockMonitor,List<ResourceNode>>();
+            List<ResourceNode> nodes1 = getNodesList("mock-1");
+            List<ResourceNode> nodes2 = getNodesList("mock-2");
+            //Backend Manager setup
+            BackendManager back = new StandardBackendManager();
+            back.addSet("queue-1",(mock1 = addMonitor(0,map,nodes1)), null, null);
+            back.addSet("queue-2",(mock2 = addMonitor(5,map,nodes2)), null, null);
+            //Make sure the queue manager is setup
+            qm = new QueueManager();
+            qm.addQueue("queue-1");
+            qm.addQueue("queue-2");
+            qm.addQueue("queue-3");
+            for (ResourceNode rn : nodes1)
+                qm.addNodeToQueue(rn.getNodeId(), "queue-1");
+            for (ResourceNode rn : nodes2)
+                qm.addNodeToQueue(rn.getNodeId(), "queue-2");
+            //Add an extra node to test "unknown queue"
+            qm.addNodeToQueue((superfluous = new ResourceNode("superfluous-1",new URL("http://superfluous-1"),-2)).getNodeId(), "queue-3");
+            monitor = new QueueMuxMonitor(back, qm);
+        } catch (QueueManagerException e) {
+            TestCase.fail("Unanticipated queue manager exception caught: "+e.getMessage());
+        } catch (MalformedURLException e) {
+            TestCase.fail("Unanticipated URL exception caught: "+e.getMessage());
+        }
+    }
+
+    public void testGetLoad() {
+        try {
+            TestCase.assertEquals(mock1.load,monitor.getLoad(map.get(mock1).get(0)));
+            TestCase.assertEquals(mock2.load,monitor.getLoad(map.get(mock2).get(0)));
+
+            /*try {
+                monitor.getLoad(superfluous);
+                TestCase.fail("Exception not thrown for unknown queue.");
+            } catch (MonitorException e) {
+            }*/
+        } catch(MonitorException e) {
+            TestCase.fail("Unanticipated monitor exception caught: "+e.getMessage());
+        }
+    }
+
+    public void testGetNodes() {
+        try {
+            List<ResourceNode> nodes = monitor.getNodes();
+            for (ResourceNode rn :map.get(mock1))
+                TestCase.assertTrue("Node: "+rn.getNodeId()+ " not found.", nodes.contains(rn));
+            for (ResourceNode rn :map.get(mock2))
+                TestCase.assertTrue("Node: "+rn.getNodeId()+ " not found.", nodes.contains(rn));
+        } catch(MonitorException e) {
+            TestCase.fail("Unanticipated monitor exception caught: "+e.getMessage());
+        }
+    }
+
+    public void testGetNodeById() {
+        try {
+            TestCase.assertEquals(map.get(mock1).get(0),monitor.getNodeById("mock-1-1"));
+            TestCase.assertEquals(map.get(mock2).get(0),monitor.getNodeById("mock-2-1"));
+        } catch(MonitorException e) {
+            TestCase.fail("Unanticipated monitor exception caught: "+e.getMessage());
+        }
+    }
+    public void testGetNodeByURL() {
+        try {
+            TestCase.assertEquals(map.get(mock1).get(1),monitor.getNodeByURL(new URL("http://mock-1-2")));
+            TestCase.assertEquals(map.get(mock2).get(1),monitor.getNodeByURL(new URL("http://mock-2-2")));
+        } catch(MonitorException e) {
+            TestCase.fail("Unanticipated monitor exception caught: "+e.getMessage());
+        } catch (MalformedURLException e1) {
+            TestCase.fail("Unanticipated URL exception caught: "+e1.getMessage());
+        }
+    }
+
+    public void testReduceLoad() {
+        try {
+            TestCase.assertTrue(monitor.reduceLoad(map.get(mock1).get(2), 5));
+            TestCase.assertTrue(monitor.reduceLoad(map.get(mock2).get(2), 3));
+            TestCase.assertEquals(map.get(mock1).get(2).getCapacity(),25);
+            TestCase.assertEquals(map.get(mock2).get(2).getCapacity(),27);
+            try {
+                monitor.reduceLoad(superfluous, 2);
+                TestCase.fail("Exception not thrown for unknown queue.");
+            } catch (MonitorException e) {}
+        } catch(MonitorException e) {
+            TestCase.fail("Unanticipated monitor exception caught: "+e.getMessage());
+        }
+    }
+
+    public void testAssignLoad() {
+        try {
+            TestCase.assertTrue(monitor.assignLoad(map.get(mock1).get(2), 5));
+            TestCase.assertTrue(monitor.assignLoad(map.get(mock2).get(2), 3));
+            TestCase.assertEquals(map.get(mock1).get(2).getCapacity(),5);
+            TestCase.assertEquals(map.get(mock2).get(2).getCapacity(),3);
+            try {
+                monitor.assignLoad(superfluous, 2);
+                TestCase.fail("Exception not thrown for unknown queue.");
+            } catch (MonitorException e) {}
+        } catch(MonitorException e) {
+            TestCase.fail("Unanticipated monitor exception caught: "+e.getMessage());
+        }
+    }
+
+    public void testAddNode() {
+        try {
+            ResourceNode node = new ResourceNode("a-new-node",null,2);
+            qm.addNodeToQueue(node.getNodeId(), "queue-1");
+            monitor.addNode(node);
+            TestCase.assertEquals(node,mock1.getAdded());
+        } catch(MonitorException e) {
+            TestCase.fail("Unanticipated monitor exception caught: "+e.getMessage());
+        } catch (QueueManagerException e1) {
+            TestCase.fail("Unanticipated queue manager exception caught: "+e1.getMessage());
+        }
+    }
+    public void removeNodeById() {
+        try {
+            ResourceNode node = new ResourceNode("a-new-node",null,2);
+            qm.addNodeToQueue(node.getNodeId(), "queue-1");
+            monitor.addNode(node);
+            TestCase.assertEquals(node,mock1.getAdded());
+            monitor.removeNodeById(node.getNodeId());
+            TestCase.assertEquals(null,mock1.getAdded());
+        } catch(MonitorException e) {
+            TestCase.fail("Unanticipated monitor exception caught: "+e.getMessage());
+        } catch (QueueManagerException e1) {
+            TestCase.fail("Unanticipated queue manager exception caught: "+e1.getMessage());
+        }
+    }
+
+    private MockMonitor addMonitor(int load,Map<MockMonitor, List<ResourceNode>> map, List<ResourceNode> list) {
+        MockMonitor mon = new MockMonitor(load, list, list.get(0), list.get(1), list.get(2));
+        map.put(mon, list);
+        return mon;
+    }
+    private List<ResourceNode> getNodesList(String prefix) {
+        List<ResourceNode> nodes = new LinkedList<ResourceNode>();
+        try {
+            nodes.add(new ResourceNode(prefix+"-1",new URL("http://"+prefix+"-1"),10));
+            nodes.add(new ResourceNode(prefix+"-2",new URL("http://"+prefix+"-2"),20));
+            nodes.add(new ResourceNode(prefix+"-3",new URL("http://"+prefix+"-3"),30));
+            nodes.add(new ResourceNode(prefix+"-4",new URL("http://"+prefix+"-4"),40));
+        } catch (MalformedURLException e) {
+            TestCase.fail("Unanticipated URL exception caught: "+e.getMessage());
+        }
+        return nodes;
+    }
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/mux/mocks/MockBatchManager.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/mux/mocks/MockBatchManager.java
new file mode 100644
index 0000000..34a2855
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/mux/mocks/MockBatchManager.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.mux.mocks;
+
+import org.apache.oodt.cas.resource.batchmgr.Batchmgr;
+import org.apache.oodt.cas.resource.jobrepo.JobRepository;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+/**
+ * This is a mock version of the batch manager. It SHOULD NOT, and 
+ * CAN NOT be used as a normal class.
+ *
+ * @author starchmd
+ */
+public class MockBatchManager implements Batchmgr {
+
+    private JobSpec execJobSpec;
+    private ResourceNode execResNode;
+
+    @Override
+    public boolean executeRemotely(JobSpec job, ResourceNode resNode)
+            throws JobExecutionException {
+        this.execJobSpec = job;
+        this.execResNode = resNode;
+        return true;
+    }
+
+    @Override
+    public void setMonitor(Monitor monitor) {}
+
+    @Override
+    public void setJobRepository(JobRepository repository) {}
+
+    @Override
+    public boolean killJob(String jobId, ResourceNode node) {
+        if (this.execJobSpec.getJob().getId().equals(jobId))
+        {
+            this.execJobSpec = null;
+            this.execResNode = null;
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public String getExecutionNode(String jobId) {
+        return execResNode.getNodeId();
+    }
+    /*****
+     * The following are test methods to report what jobs are here.
+     *****/
+    /**
+     * Return the current jobspec, for testing purposes
+     * @return
+     */
+    public JobSpec getCurrentJobSpec() {
+        return this.execJobSpec;
+    }
+    /**
+     * Return the current resource node, for testing purposes
+     * @return
+     */
+    public ResourceNode getCurrentResourceNode() {
+        return execResNode;
+    }
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/mux/mocks/MockMonitor.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/mux/mocks/MockMonitor.java
new file mode 100644
index 0000000..e2fa0d8
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/mux/mocks/MockMonitor.java
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.mux.mocks;
+
+import java.net.URL;
+import java.util.List;
+
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+
+public class MockMonitor implements Monitor {
+
+    public int load = -1;
+    List<ResourceNode> nodes;
+    ResourceNode id;
+    ResourceNode url;
+    ResourceNode add;
+    ResourceNode reduce;
+
+    public MockMonitor(int load,List<ResourceNode> nodes, ResourceNode id, ResourceNode url, ResourceNode reduce) {
+        this.load = load;
+        this.nodes = nodes;
+        this.id = id;
+        this.url = url;
+        this.reduce = reduce;
+    }
+
+    @Override
+    public int getLoad(ResourceNode node) throws MonitorException {     
+        return load;
+    }
+    @Override
+    public List getNodes() throws MonitorException {
+        return nodes;
+    }
+
+    @Override
+    public ResourceNode getNodeById(String nodeId) throws MonitorException {
+        return id.getNodeId().equals(nodeId)?id:null;
+    }
+
+    @Override
+    public ResourceNode getNodeByURL(URL ipAddr) throws MonitorException {
+        return url.getIpAddr().equals(ipAddr)?url:null;
+    }
+
+    @Override
+    public boolean reduceLoad(ResourceNode node, int loadValue)
+            throws MonitorException {
+        reduce.setCapacity(reduce.getCapacity() - loadValue);
+        return true;
+    }
+
+    @Override
+    public boolean assignLoad(ResourceNode node, int loadValue)
+            throws MonitorException {
+        reduce.setCapacity(loadValue);
+        return true;
+    }
+
+    @Override
+    public void addNode(ResourceNode node) throws MonitorException {
+        this.add = node;
+
+    }
+
+    @Override
+    public void removeNodeById(String nodeId) throws MonitorException {
+        if (this.add.getNodeId().equals(nodeId))
+            this.add = null;
+    }
+
+    public ResourceNode getAdded() {
+        return this.add;
+    }
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/queuerepo/TestXmlQueueRepository.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/queuerepo/TestXmlQueueRepository.java
new file mode 100644
index 0000000..c2f144b
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/queuerepo/TestXmlQueueRepository.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.queuerepo;
+
+//JDK imports
+import java.io.File;
+import java.util.Arrays;
+
+//OODT imports
+import org.apache.oodt.cas.resource.scheduler.QueueManager;
+import org.apache.oodt.cas.resource.structs.exceptions.QueueManagerException;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Test Suite for the {@link XmlQueueRepository} service
+ * </p>.
+ */
+public class TestXmlQueueRepository extends TestCase {
+
+	private QueueManager queueManager;
+	
+	protected void setUp() {
+		System.setProperty("org.apache.oodt.cas.resource.nodetoqueues.dirs",
+				"file:"
+						+ new File("./src/main/resources/examples")
+								.getAbsolutePath());
+		this.queueManager = new XmlQueueRepositoryFactory().createQueueRepository().loadQueues();
+	}
+	
+	public void testMapping() throws QueueManagerException {
+	  assertTrue(this.queueManager.getQueues().containsAll(Arrays.asList("quick", "high", "long")));
+		assertEquals(this.queueManager.getNodes("quick"), Arrays.asList("localhost"));
+		assertEquals(this.queueManager.getNodes("high"), Arrays.asList("localhost"));
+		assertEquals(this.queueManager.getNodes("long"), Arrays.asList("localhost"));
+		assertTrue(this.queueManager.getQueues("localhost").containsAll(Arrays.asList("quick", "high", "long")));
+		
+		this.queueManager.addQueue("test-queue-1");
+		this.queueManager.addNodeToQueue("test-node-1", "test-queue-1");
+		
+		assertEquals(this.queueManager.getQueues("test-node-1"), Arrays.asList("test-queue-1"));
+
+		this.queueManager.addNodeToQueue("test-node-1","quick");
+		assertEquals(this.queueManager.getQueues("test-node-1"), Arrays.asList("quick", "test-queue-1"));
+		
+		this.queueManager.removeQueue("quick");
+		assertEquals(this.queueManager.getQueues("test-node-1"), Arrays.asList("test-queue-1"));
+		assertEquals(this.queueManager.getQueues("localhost"), Arrays.asList("high", "long"));
+	}
+	
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/schedule/MockScheduler.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/schedule/MockScheduler.java
new file mode 100644
index 0000000..1abd6a9
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/schedule/MockScheduler.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.schedule;
+
+//OODT imports
+import org.apache.oodt.cas.resource.batchmgr.Batchmgr;
+import org.apache.oodt.cas.resource.jobqueue.JobQueue;
+import org.apache.oodt.cas.resource.monitor.Monitor;
+import org.apache.oodt.cas.resource.scheduler.QueueManager;
+import org.apache.oodt.cas.resource.scheduler.Scheduler;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.SchedulerException;
+
+/**
+ * A Mock {@link Scheduler}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class MockScheduler implements Scheduler {
+
+   public void run() {
+      // Do nothing.
+   }
+
+   public boolean schedule(JobSpec spec) throws SchedulerException {
+      return false;
+   }
+
+   public ResourceNode nodeAvailable(JobSpec spec) throws SchedulerException {
+      return null;
+   }
+
+   public Monitor getMonitor() {
+      return null;
+   }
+
+   public Batchmgr getBatchmgr() {
+      return null;
+   }
+
+   public JobQueue getJobQueue() {
+      return null;
+   }
+
+   public QueueManager getQueueManager() {
+      return null;
+   }
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/system/MockXmlRpcResourceManagerClient.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/system/MockXmlRpcResourceManagerClient.java
new file mode 100644
index 0000000..9309112
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/system/MockXmlRpcResourceManagerClient.java
@@ -0,0 +1,188 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.system;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.resource.examples.HelloWorldJob;
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.NameValueJobInput;
+import org.apache.oodt.cas.resource.structs.ResourceNode;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+import org.apache.oodt.cas.resource.structs.exceptions.JobRepositoryException;
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+import org.apache.oodt.cas.resource.structs.exceptions.QueueManagerException;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * Mock implementation of {@link XmlRpcResourceManagerClient}.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class MockXmlRpcResourceManagerClient extends
+      XmlRpcResourceManagerClient {
+
+   private MethodCallDetails lastMethodCallDetails;
+
+   public MockXmlRpcResourceManagerClient() throws MalformedURLException {
+      super(new URL("http://localhost:9000"));
+   }
+
+   public MethodCallDetails getLastMethodCallDetails() {
+      return lastMethodCallDetails;
+   }
+
+   public void addNode(ResourceNode node) throws MonitorException {
+      lastMethodCallDetails = new MethodCallDetails("addNode",
+            Lists.newArrayList((Object) node));
+   }
+
+   public void addNodeToQueue(String nodeId, String queueName)
+         throws QueueManagerException {
+      lastMethodCallDetails = new MethodCallDetails("addNodeToQueue",
+            Lists.newArrayList((Object) nodeId, queueName));
+   }
+
+   public void addQueue(String queueName) throws QueueManagerException {
+      lastMethodCallDetails = new MethodCallDetails("addQueue",
+            Lists.newArrayList((Object) queueName));
+   }
+
+   public String getExecutionNode(String jobId) {
+      lastMethodCallDetails = new MethodCallDetails("getExecutionNode",
+            Lists.newArrayList((Object) jobId));
+      return "TestNodeId";
+   }
+
+   public Job getJobInfo(String jobId) throws JobRepositoryException {
+      lastMethodCallDetails = new MethodCallDetails("getJobInfo",
+            Lists.newArrayList((Object) jobId));
+      Job job = new Job();
+      job.setId(jobId);
+      job.setName("TestJobName");
+      job.setJobInputClassName(NameValueJobInput.class.getCanonicalName());
+      job.setJobInstanceClassName(HelloWorldJob.class.getCanonicalName());
+      job.setLoadValue(4);
+      job.setQueueName("TestQueueName");
+      job.setStatus("DONE");
+      return job;
+   }
+
+   public ResourceNode getNodeById(String nodeId) throws MonitorException {
+      lastMethodCallDetails = new MethodCallDetails("getNodeById",
+            Lists.newArrayList((Object) nodeId));
+      try {
+         return new ResourceNode(nodeId, new URL("http://localhost:9999"), 5);
+      } catch (Exception e) {
+         throw new MonitorException(e);
+      }
+   }
+
+   public String getNodeLoad(String nodeId) throws MonitorException {
+      lastMethodCallDetails = new MethodCallDetails("getNodeLoad",
+            Lists.newArrayList((Object) nodeId));
+      return "10";
+   }
+
+   public List<ResourceNode> getNodes() throws MonitorException {
+      lastMethodCallDetails = new MethodCallDetails("getNodes",
+            Lists.newArrayList());
+      return Lists.newArrayList();
+   }
+
+   public List<String> getNodesInQueue(String queueName)
+         throws QueueManagerException {
+      lastMethodCallDetails = new MethodCallDetails("getNodesInQueue",
+            Lists.newArrayList((Object) queueName));
+      return Lists.newArrayList();
+   }
+
+   public List<String> getQueues() throws QueueManagerException {
+      lastMethodCallDetails = new MethodCallDetails("getQueues",
+            Lists.newArrayList());
+      return Lists.newArrayList();
+   }
+
+   public List<String> getQueuesWithNode(String nodeId) throws QueueManagerException {
+      lastMethodCallDetails = new MethodCallDetails("getQueuesWithNode",
+            Lists.newArrayList((Object) nodeId));
+      return Lists.newArrayList();
+   }
+
+   public boolean killJob(String jobId) {
+      lastMethodCallDetails = new MethodCallDetails("killJob",
+            Lists.newArrayList((Object) jobId));
+      return true;
+   }
+
+   public void removeNode(String nodeId) throws MonitorException {
+      lastMethodCallDetails = new MethodCallDetails("removeNode",
+            Lists.newArrayList((Object) nodeId));
+   }
+
+   public void removeNodeFromQueue(String nodeId, String queueName) throws QueueManagerException {
+      lastMethodCallDetails = new MethodCallDetails("removeNodeFromQueue",
+            Lists.newArrayList((Object) nodeId, queueName));
+   }
+
+   public void removeQueue(String queueName) throws QueueManagerException {
+      lastMethodCallDetails = new MethodCallDetails("removeQueue",
+            Lists.newArrayList((Object) queueName));
+   }
+
+   public void setNodeCapacity(String nodeId, int capacity) throws MonitorException{
+      lastMethodCallDetails = new MethodCallDetails("setNodeCapacity",
+            Lists.newArrayList((Object) nodeId, capacity));
+   }
+
+   public String submitJob(Job exec, JobInput in) throws JobExecutionException {
+      lastMethodCallDetails = new MethodCallDetails("submitJob",
+            Lists.newArrayList((Object) exec, in));
+      return "TestJobId";
+   }
+
+   public boolean submitJob(Job exec, JobInput in, URL url) throws JobExecutionException {
+      lastMethodCallDetails = new MethodCallDetails("submitJob",
+            Lists.newArrayList((Object) exec, in, url));
+      return true;
+   }
+
+   public class MethodCallDetails {
+      private String methodName;
+      private List<Object> args;
+
+      public MethodCallDetails(String methodName, List<Object> args) {
+         this.methodName = methodName;
+         this.args = args;
+      }
+
+      public String getMethodName() {
+         return methodName;
+      }
+
+      public List<Object> getArgs() {
+         return args;
+      }
+   }
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/system/TestXmlRpcResourceManager.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/system/TestXmlRpcResourceManager.java
new file mode 100644
index 0000000..e2c0307
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/system/TestXmlRpcResourceManager.java
@@ -0,0 +1,157 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.resource.system;
+
+//JDK imports
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Properties;
+
+//Apache imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ *
+ * Test harness for the {@link XmlRpcResourceManager}.
+ *
+ * @author mattmann
+ * @author rajith
+ * @version $Revision$
+ *
+ */
+public class TestXmlRpcResourceManager extends TestCase {
+
+  private File tmpPolicyDir;
+
+  private XmlRpcResourceManager rm;
+
+  private static final int RM_PORT = 50001;
+
+  /**
+   * @since OODT-182
+   */
+  public void testDynSetNodeCapacity() {
+    XmlRpcResourceManagerClient rmc = null;
+    try {
+      rmc = new XmlRpcResourceManagerClient(new URL("http://localhost:"
+          + RM_PORT));
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(rmc);
+    try {
+      rmc.setNodeCapacity("localhost", 8);
+    } catch (MonitorException e) {
+      fail(e.getMessage());
+    }
+
+    int setCapacity = -1;
+    try {
+      setCapacity = rmc.getNodeById("localhost").getCapacity();
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+    assertEquals(8, setCapacity);
+
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see junit.framework.TestCase#setUp()
+   */
+  @Override
+  protected void setUp() throws Exception {
+    generateTestConfiguration();
+    this.rm = new XmlRpcResourceManager(RM_PORT);
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see junit.framework.TestCase#tearDown()
+   */
+  @Override
+  protected void tearDown() throws Exception {
+    this.rm.shutdown();
+    deleteAllFiles(this.tmpPolicyDir.getAbsolutePath());
+  }
+
+  private void deleteAllFiles(String startDir) {
+    File startDirFile = new File(startDir);
+    File[] delFiles = startDirFile.listFiles();
+
+    if (delFiles != null && delFiles.length > 0) {
+      for (int i = 0; i < delFiles.length; i++) {
+        delFiles[i].delete();
+      }
+    }
+
+    startDirFile.delete();
+
+  }
+
+    private void generateTestConfiguration() throws IOException {
+    Properties config = new Properties();
+
+    String propertiesFile = "." + File.separator + "src" + File.separator +
+            "test" + File.separator + "resources" + File.separator + "test.resource.properties";
+    System.getProperties().load(new FileInputStream(new File(propertiesFile)));
+
+    // stage policy
+    File tmpPolicyDir = null;
+    try {
+      tmpPolicyDir = File.createTempFile("test", "ignore").getParentFile();
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+    for (File policyFile : new File("./src/test/resources/policy")
+        .listFiles(new FileFilter() {
+
+          @Override
+          public boolean accept(File pathname) {
+            return pathname.isFile() && pathname.getName().endsWith(".xml");
+          }
+        })) {
+      try {
+        FileUtils.copyFileToDirectory(policyFile, tmpPolicyDir);
+      } catch (Exception e) {
+        fail(e.getMessage());
+      }
+    }
+
+    config.setProperty("org.apache.oodt.cas.resource.nodes.dirs", tmpPolicyDir
+        .toURI().toString());
+    config.setProperty("org.apache.oodt.cas.resource.nodetoqueues.dirs",
+        tmpPolicyDir.toURI().toString());
+
+    System.getProperties().putAll(config);
+    this.tmpPolicyDir = tmpPolicyDir;
+  }
+
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/util/TestMesosUtilities.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/util/TestMesosUtilities.java
new file mode 100644
index 0000000..2f2dda0
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/util/TestMesosUtilities.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.resource.util;
+
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.JobSpec;
+import org.apache.oodt.cas.resource.structs.NameValueJobInput;
+
+
+import org.apache.oodt.cas.resource.util.MesosUtilities;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * @author starchmd
+ * @version $Revision$
+ *
+ * <p>
+ * Test Suite for the {@link MesosUtilities} class
+ * </p>.
+ */
+public class TestMesosUtilities extends TestCase {
+
+    public void testSerialization() {
+        JobSpec js = new JobSpec();
+
+        Job job = new Job();
+        job.setId("crazy-id");
+        job.setJobInputClassName(NameValueJobInput.class.getCanonicalName());
+        job.setJobInstanceClassName("Instance Class");
+        job.setLoadValue(new Integer(352));
+        job.setName("A Name");
+        job.setQueueName("Queue");
+        job.setStatus("Status");
+
+        String[] props = {"prop-1","prop-2","prop-3"};
+        NameValueJobInput nvji = new NameValueJobInput();
+        for (String str : props)
+            nvji.setNameValuePair(str, str+"val");
+
+        js.setIn(nvji);
+        js.setJob(job);
+
+        JobSpec ns;
+        try {
+            ns = MesosUtilities.byteStringToJobSpec(MesosUtilities.jobSpecToByteString(js));
+            TestCase.assertEquals(js.getJob().getId(),ns.getJob().getId());
+            TestCase.assertEquals(js.getJob().getJobInputClassName(),ns.getJob().getJobInputClassName());
+            TestCase.assertEquals(js.getJob().getJobInstanceClassName(),ns.getJob().getJobInstanceClassName());
+            TestCase.assertEquals(js.getJob().getLoadValue(),ns.getJob().getLoadValue());
+            TestCase.assertEquals(js.getJob().getName(),ns.getJob().getName());
+            TestCase.assertEquals(js.getJob().getQueueName(),ns.getJob().getQueueName());
+            TestCase.assertEquals(js.getJob().getStatus(),ns.getJob().getStatus());
+            TestCase.assertEquals(js.getIn().getId(),ns.getIn().getId());
+            for (String str : props)
+                TestCase.assertEquals(nvji.getValue(str),((NameValueJobInput)ns.getIn()).getValue(str));
+        } catch (ClassNotFoundException e) {
+            TestCase.fail("Unexpected exception:"+e.getLocalizedMessage());
+        } catch (InstantiationException e) {
+            TestCase.fail("Unexpected exception:"+e.getLocalizedMessage());
+        } catch (IllegalAccessException e) {
+            TestCase.fail("Unexpected exception:"+e.getLocalizedMessage());
+        }
+
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/util/TestUlimit.java b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/util/TestUlimit.java
new file mode 100644
index 0000000..b50887b
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/java/org/apache/oodt/cas/resource/util/TestUlimit.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.resource.util;
+
+//JDK imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test case for the Ulimit monitoring API.
+ * </p>.
+ */
+public class TestUlimit extends TestCase {
+
+    public void testGetMaxOpenFiles() {
+        String maxOpenFiles = Ulimit.getMaxOpenFiles();
+        assertNotNull(maxOpenFiles);
+        assertTrue(new UlimitProperty("foo", maxOpenFiles).isUnlimited()
+                || !new UlimitProperty("foo", maxOpenFiles).isUnlimited());
+
+    }
+
+    public void testUlimitProperty() {
+        String maxStackSize = Ulimit.getMaxStackSize();
+        if (new UlimitProperty("foo", maxStackSize).isUnlimited()) {
+            assertTrue(new UlimitProperty("foo", maxStackSize).getIntValue() == -1);
+        } else {
+            assertTrue(new UlimitProperty("foo", maxStackSize).getIntValue() != -1);
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/resource/src/test/resources/policy/node-to-queue-mapping.xml b/0.8.1-rc1/resource/src/test/resources/policy/node-to-queue-mapping.xml
new file mode 100644
index 0000000..73b0eba
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/resources/policy/node-to-queue-mapping.xml
@@ -0,0 +1,26 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<cas:node-to-queue-mapping xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<node id="localhost">
+		<queues>
+			<queue name="high"/>
+			<queue name="quick"/>
+			<queue name="long"/>
+		</queues>
+	</node>	
+</cas:node-to-queue-mapping>
diff --git a/0.8.1-rc1/resource/src/test/resources/policy/nodes.xml b/0.8.1-rc1/resource/src/test/resources/policy/nodes.xml
new file mode 100644
index 0000000..d3d415d
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/resources/policy/nodes.xml
@@ -0,0 +1,23 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<cas:resourcenodes xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<node nodeId="localhost" ip="http://localhost:2001" capacity="8"/>
+	<!-- EnvReplace Example 
+	<node nodeId="somehost" ip="http://somehost:[BATCH_STUB_PORT]" capacity="8" envReplace="true"/>
+	-->
+</cas:resourcenodes>
diff --git a/0.8.1-rc1/resource/src/test/resources/resourcemon/gangliaXMLdump.xml b/0.8.1-rc1/resource/src/test/resources/resourcemon/gangliaXMLdump.xml
new file mode 100644
index 0000000..ed06287
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/resources/resourcemon/gangliaXMLdump.xml
@@ -0,0 +1,869 @@
+<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
+<!--
+ 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 GANGLIA_XML [
+        <!ELEMENT GANGLIA_XML (GRID|CLUSTER|HOST)*>
+        <!ATTLIST GANGLIA_XML VERSION CDATA #REQUIRED>
+        <!ATTLIST GANGLIA_XML SOURCE CDATA #REQUIRED>
+        <!ELEMENT GRID (CLUSTER | GRID | HOSTS | METRICS)*>
+        <!ATTLIST GRID NAME CDATA #REQUIRED>
+        <!ATTLIST GRID AUTHORITY CDATA #REQUIRED>
+        <!ATTLIST GRID LOCALTIME CDATA #IMPLIED>
+        <!ELEMENT CLUSTER (HOST | HOSTS | METRICS)*>
+        <!ATTLIST CLUSTER NAME CDATA #REQUIRED>
+        <!ATTLIST CLUSTER OWNER CDATA #IMPLIED>
+        <!ATTLIST CLUSTER LATLONG CDATA #IMPLIED>
+        <!ATTLIST CLUSTER URL CDATA #IMPLIED>
+        <!ATTLIST CLUSTER LOCALTIME CDATA #REQUIRED>
+        <!ELEMENT HOST (METRIC)*>
+        <!ATTLIST HOST NAME CDATA #REQUIRED>
+        <!ATTLIST HOST IP CDATA #REQUIRED>
+        <!ATTLIST HOST LOCATION CDATA #IMPLIED>
+        <!ATTLIST HOST REPORTED CDATA #REQUIRED>
+        <!ATTLIST HOST TN CDATA #IMPLIED>
+        <!ATTLIST HOST TMAX CDATA #IMPLIED>
+        <!ATTLIST HOST DMAX CDATA #IMPLIED>
+        <!ATTLIST HOST GMOND_STARTED CDATA #IMPLIED>
+        <!ELEMENT METRIC (EXTRA_DATA*)>
+        <!ATTLIST METRIC NAME CDATA #REQUIRED>
+        <!ATTLIST METRIC VAL CDATA #REQUIRED>
+        <!ATTLIST METRIC TYPE (string | int8 | uint8 | int16 | uint16 | int32 | uint32 | float | double | timestamp) #REQUIRED>
+        <!ATTLIST METRIC UNITS CDATA #IMPLIED>
+        <!ATTLIST METRIC TN CDATA #IMPLIED>
+        <!ATTLIST METRIC TMAX CDATA #IMPLIED>
+        <!ATTLIST METRIC DMAX CDATA #IMPLIED>
+        <!ATTLIST METRIC SLOPE (zero | positive | negative | both | unspecified) #IMPLIED>
+        <!ATTLIST METRIC SOURCE (gmond) 'gmond'>
+        <!ELEMENT EXTRA_DATA (EXTRA_ELEMENT*)>
+        <!ELEMENT EXTRA_ELEMENT EMPTY>
+        <!ATTLIST EXTRA_ELEMENT NAME CDATA #REQUIRED>
+        <!ATTLIST EXTRA_ELEMENT VAL CDATA #REQUIRED>
+        <!ELEMENT HOSTS EMPTY>
+        <!ATTLIST HOSTS UP CDATA #REQUIRED>
+        <!ATTLIST HOSTS DOWN CDATA #REQUIRED>
+        <!ATTLIST HOSTS SOURCE (gmond | gmetad) #REQUIRED>
+        <!ELEMENT METRICS (EXTRA_DATA*)>
+        <!ATTLIST METRICS NAME CDATA #REQUIRED>
+        <!ATTLIST METRICS SUM CDATA #REQUIRED>
+        <!ATTLIST METRICS NUM CDATA #REQUIRED>
+        <!ATTLIST METRICS TYPE (string | int8 | uint8 | int16 | uint16 | int32 | uint32 | float | double | timestamp) #REQUIRED>
+        <!ATTLIST METRICS UNITS CDATA #IMPLIED>
+        <!ATTLIST METRICS SLOPE (zero | positive | negative | both | unspecified) #IMPLIED>
+        <!ATTLIST METRICS SOURCE (gmond) 'gmond'>
+        ]>
+<GANGLIA_XML VERSION="3.1.7" SOURCE="gmetad">
+    <GRID NAME="unspecified" AUTHORITY="http://ubuntu/ganglia/" LOCALTIME="1370187648">
+        <CLUSTER NAME="localcluster" LOCALTIME="1370187645" OWNER="oodt" LATLONG="N32.87 W117.22"
+                 URL="http://www.mycluster.org/">
+            <HOST NAME="localhost" IP="127.0.0.1" REPORTED="1370187637" TN="10" TMAX="20" DMAX="0" LOCATION="0,0,0"
+                  GMOND_STARTED="1370186237">
+                <METRIC NAME="disk_free" VAL="307.790" TYPE="double" UNITS="GB" TN="143" TMAX="180" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="disk"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total free disk space"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Disk Space Available"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="machine_type" VAL="x86_64" TYPE="string" UNITS="" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="system"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="System architecture"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Machine Type"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="bytes_out" VAL="1022.59" TYPE="float" UNITS="bytes/sec" TN="83" TMAX="300" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="network"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Number of bytes out per second"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Bytes Sent"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="gexec" VAL="OFF" TYPE="string" UNITS="" TN="203" TMAX="300" DMAX="0" SLOPE="zero"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="core"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="gexec available"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Gexec Status"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="proc_total" VAL="580" TYPE="uint32" UNITS=" " TN="43" TMAX="950" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="process"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total number of processes"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Total Processes"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_nice" VAL="0.0" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of CPU utilization that occurred while executing at the user level with nice priority"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU Nice"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="pkts_in" VAL="4.85" TYPE="float" UNITS="packets/sec" TN="83" TMAX="300" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="network"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Packets in per second"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Packets Received"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_speed" VAL="2267" TYPE="uint32" UNITS="MHz" TN="203" TMAX="1200" DMAX="0" SLOPE="zero"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="CPU Speed in terms of MHz"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU Speed"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="boottime" VAL="1370172364" TYPE="uint32" UNITS="s" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="system"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="The last time that the system was started"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Last Boot Time"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_wio" VAL="1.9" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU wio"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="os_name" VAL="Linux" TYPE="string" UNITS="" TN="203" TMAX="1200" DMAX="0" SLOPE="zero"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="system"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Operating system name"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Operating System"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="load_one" VAL="1.06" TYPE="float" UNITS=" " TN="53" TMAX="70" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="load"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="One minute load average"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="One Minute Load Average"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="os_release" VAL="3.2.0-45-generic" TYPE="string" UNITS="" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="system"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Operating system release date"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Operating System Release"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="disk_total" VAL="1042.222" TYPE="double" UNITS="GB" TN="1403" TMAX="1200" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="disk"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total available disk space"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Total Disk Space"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_user" VAL="8.0" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of CPU utilization that occurred while executing at the user level"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU User"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_idle" VAL="88.7" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of time that the CPU or CPUs were idle and the system did not have an outstanding disk I/O request"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU Idle"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="swap_free" VAL="2097148" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of available swap memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Free Swap Space"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_cached" VAL="3100100" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of cached memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Cached Memory"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="pkts_out" VAL="4.80" TYPE="float" UNITS="packets/sec" TN="83" TMAX="300" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="network"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Packets out per second"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Packets Sent"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="load_five" VAL="0.82" TYPE="float" UNITS=" " TN="53" TMAX="325" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="load"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Five minute load average"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Five Minute Load Average"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_num" VAL="4" TYPE="uint16" UNITS="CPUs" TN="203" TMAX="1200" DMAX="0" SLOPE="zero"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total number of CPUs"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU Count"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="load_fifteen" VAL="0.68" TYPE="float" UNITS=" " TN="53" TMAX="950" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="load"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Fifteen minute load average"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Fifteen Minute Load Average"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_free" VAL="228108" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of available memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Free Memory"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_system" VAL="1.2" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of CPU utilization that occurred while executing at the system level"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU System"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="proc_run" VAL="1" TYPE="uint32" UNITS=" " TN="43" TMAX="950" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="process"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total number of running processes"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Total Running Processes"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_total" VAL="8169032" TYPE="float" UNITS="KB" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total amount of memory displayed in KBs"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Memory Total"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_aidle" VAL="87.1" TYPE="float" UNITS="%" TN="22" TMAX="3800" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Percent of time since boot idle CPU"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU aidle"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="bytes_in" VAL="1417.43" TYPE="float" UNITS="bytes/sec" TN="83" TMAX="300" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="network"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Number of bytes in per second"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Bytes Received"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_buffers" VAL="2436620" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of buffered memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Memory Buffers"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_shared" VAL="0" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of shared memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Shared Memory"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="swap_total" VAL="2097148" TYPE="float" UNITS="KB" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total amount of swap space displayed in KBs"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Swap Space Total"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="part_max_used" VAL="77.7" TYPE="float" UNITS="%" TN="143" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="disk"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Maximum percent used for all partitions"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Maximum Disk Space Used"/>
+                    </EXTRA_DATA>
+                </METRIC>
+            </HOST>
+            <HOST NAME="localhost2" IP="127.0.0.1" REPORTED="1370187637" TN="10" TMAX="20" DMAX="0"
+                  LOCATION="unspecified" GMOND_STARTED="1370186237">
+                <METRIC NAME="disk_free" VAL="307.790" TYPE="double" UNITS="GB" TN="143" TMAX="180" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="disk"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total free disk space"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Disk Space Available"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="machine_type" VAL="x86_64" TYPE="string" UNITS="" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="system"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="System architecture"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Machine Type"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="bytes_out" VAL="1022.59" TYPE="float" UNITS="bytes/sec" TN="83" TMAX="300" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="network"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Number of bytes out per second"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Bytes Sent"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="gexec" VAL="OFF" TYPE="string" UNITS="" TN="203" TMAX="300" DMAX="0" SLOPE="zero"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="core"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="gexec available"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Gexec Status"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="proc_total" VAL="580" TYPE="uint32" UNITS=" " TN="43" TMAX="950" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="process"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total number of processes"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Total Processes"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_nice" VAL="0.0" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of CPU utilization that occurred while executing at the user level with nice priority"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU Nice"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="pkts_in" VAL="4.85" TYPE="float" UNITS="packets/sec" TN="83" TMAX="300" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="network"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Packets in per second"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Packets Received"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_speed" VAL="2267" TYPE="uint32" UNITS="MHz" TN="203" TMAX="1200" DMAX="0" SLOPE="zero"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="CPU Speed in terms of MHz"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU Speed"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="boottime" VAL="1370172364" TYPE="uint32" UNITS="s" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="system"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="The last time that the system was started"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Last Boot Time"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_wio" VAL="1.9" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU wio"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="os_name" VAL="Linux" TYPE="string" UNITS="" TN="203" TMAX="1200" DMAX="0" SLOPE="zero"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="system"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Operating system name"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Operating System"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="load_one" VAL="1.06" TYPE="float" UNITS=" " TN="53" TMAX="70" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="load"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="One minute load average"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="One Minute Load Average"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="os_release" VAL="3.2.0-45-generic" TYPE="string" UNITS="" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="system"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Operating system release date"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Operating System Release"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="disk_total" VAL="1042.222" TYPE="double" UNITS="GB" TN="1403" TMAX="1200" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="disk"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total available disk space"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Total Disk Space"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_user" VAL="8.0" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of CPU utilization that occurred while executing at the user level"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU User"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_idle" VAL="88.7" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of time that the CPU or CPUs were idle and the system did not have an outstanding disk I/O request"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU Idle"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="swap_free" VAL="2097148" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of available swap memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Free Swap Space"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_cached" VAL="3100100" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of cached memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Cached Memory"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="pkts_out" VAL="4.80" TYPE="float" UNITS="packets/sec" TN="83" TMAX="300" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="network"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Packets out per second"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Packets Sent"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="load_five" VAL="0.82" TYPE="float" UNITS=" " TN="53" TMAX="325" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="load"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Five minute load average"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Five Minute Load Average"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_num" VAL="4" TYPE="uint16" UNITS="CPUs" TN="203" TMAX="1200" DMAX="0" SLOPE="zero"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total number of CPUs"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU Count"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="load_fifteen" VAL="0.68" TYPE="float" UNITS=" " TN="53" TMAX="950" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="load"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Fifteen minute load average"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Fifteen Minute Load Average"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_free" VAL="228108" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of available memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Free Memory"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_system" VAL="1.2" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of CPU utilization that occurred while executing at the system level"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU System"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="proc_run" VAL="1" TYPE="uint32" UNITS=" " TN="43" TMAX="950" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="process"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total number of running processes"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Total Running Processes"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_total" VAL="8169032" TYPE="float" UNITS="KB" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total amount of memory displayed in KBs"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Memory Total"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_aidle" VAL="87.1" TYPE="float" UNITS="%" TN="22" TMAX="3800" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Percent of time since boot idle CPU"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU aidle"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="bytes_in" VAL="1417.43" TYPE="float" UNITS="bytes/sec" TN="83" TMAX="300" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="network"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Number of bytes in per second"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Bytes Received"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_buffers" VAL="2436620" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of buffered memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Memory Buffers"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_shared" VAL="0" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of shared memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Shared Memory"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="swap_total" VAL="2097148" TYPE="float" UNITS="KB" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total amount of swap space displayed in KBs"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Swap Space Total"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="part_max_used" VAL="77.7" TYPE="float" UNITS="%" TN="143" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="disk"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Maximum percent used for all partitions"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Maximum Disk Space Used"/>
+                    </EXTRA_DATA>
+                </METRIC>
+            </HOST>
+        </CLUSTER>
+        <CLUSTER NAME="remotecluster" LOCALTIME="1370183645" OWNER="oodt" LATLONG="N42.87 W117.32"
+                 URL="http://www.my2cluster.org/">
+            <HOST NAME="remotenode" IP="127.0.0.1" REPORTED="1370187637" TN="10" TMAX="20" DMAX="0" LOCATION="0,0,0"
+                  GMOND_STARTED="1370186237">
+                <METRIC NAME="disk_free" VAL="307.790" TYPE="double" UNITS="GB" TN="143" TMAX="180" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="disk"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total free disk space"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Disk Space Available"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="machine_type" VAL="x86_64" TYPE="string" UNITS="" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="system"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="System architecture"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Machine Type"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="bytes_out" VAL="1022.59" TYPE="float" UNITS="bytes/sec" TN="83" TMAX="300" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="network"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Number of bytes out per second"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Bytes Sent"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="gexec" VAL="OFF" TYPE="string" UNITS="" TN="203" TMAX="300" DMAX="0" SLOPE="zero"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="core"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="gexec available"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Gexec Status"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="proc_total" VAL="580" TYPE="uint32" UNITS=" " TN="43" TMAX="950" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="process"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total number of processes"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Total Processes"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_nice" VAL="0.0" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of CPU utilization that occurred while executing at the user level with nice priority"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU Nice"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="pkts_in" VAL="4.85" TYPE="float" UNITS="packets/sec" TN="83" TMAX="300" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="network"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Packets in per second"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Packets Received"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_speed" VAL="2267" TYPE="uint32" UNITS="MHz" TN="203" TMAX="1200" DMAX="0" SLOPE="zero"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="CPU Speed in terms of MHz"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU Speed"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="boottime" VAL="1370172364" TYPE="uint32" UNITS="s" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="system"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="The last time that the system was started"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Last Boot Time"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_wio" VAL="1.9" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU wio"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="os_name" VAL="Linux" TYPE="string" UNITS="" TN="203" TMAX="1200" DMAX="0" SLOPE="zero"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="system"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Operating system name"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Operating System"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="load_one" VAL="1.06" TYPE="float" UNITS=" " TN="53" TMAX="70" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="load"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="One minute load average"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="One Minute Load Average"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="os_release" VAL="3.2.0-45-generic" TYPE="string" UNITS="" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="system"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Operating system release date"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Operating System Release"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="disk_total" VAL="1042.222" TYPE="double" UNITS="GB" TN="1403" TMAX="1200" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="disk"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total available disk space"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Total Disk Space"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_user" VAL="8.0" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of CPU utilization that occurred while executing at the user level"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU User"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_idle" VAL="88.7" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of time that the CPU or CPUs were idle and the system did not have an outstanding disk I/O request"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU Idle"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="swap_free" VAL="2097148" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of available swap memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Free Swap Space"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_cached" VAL="3100100" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of cached memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Cached Memory"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="pkts_out" VAL="4.80" TYPE="float" UNITS="packets/sec" TN="83" TMAX="300" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="network"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Packets out per second"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Packets Sent"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="load_five" VAL="0.82" TYPE="float" UNITS=" " TN="53" TMAX="325" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="load"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Five minute load average"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Five Minute Load Average"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_num" VAL="4" TYPE="uint16" UNITS="CPUs" TN="203" TMAX="1200" DMAX="0" SLOPE="zero"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total number of CPUs"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU Count"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="load_fifteen" VAL="0.68" TYPE="float" UNITS=" " TN="53" TMAX="950" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="load"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Fifteen minute load average"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Fifteen Minute Load Average"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_free" VAL="228108" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of available memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Free Memory"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_system" VAL="1.2" TYPE="float" UNITS="%" TN="22" TMAX="90" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC"
+                                       VAL="Percentage of CPU utilization that occurred while executing at the system level"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU System"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="proc_run" VAL="1" TYPE="uint32" UNITS=" " TN="43" TMAX="950" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="process"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total number of running processes"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Total Running Processes"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_total" VAL="8169032" TYPE="float" UNITS="KB" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total amount of memory displayed in KBs"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Memory Total"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="cpu_aidle" VAL="87.1" TYPE="float" UNITS="%" TN="22" TMAX="3800" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="cpu"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Percent of time since boot idle CPU"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="CPU aidle"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="bytes_in" VAL="1417.43" TYPE="float" UNITS="bytes/sec" TN="83" TMAX="300" DMAX="0"
+                        SLOPE="both" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="network"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Number of bytes in per second"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Bytes Received"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_buffers" VAL="2436620" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of buffered memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Memory Buffers"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="mem_shared" VAL="0" TYPE="float" UNITS="KB" TN="3" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Amount of shared memory"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Shared Memory"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="swap_total" VAL="2097148" TYPE="float" UNITS="KB" TN="203" TMAX="1200" DMAX="0"
+                        SLOPE="zero" SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="memory"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Total amount of swap space displayed in KBs"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Swap Space Total"/>
+                    </EXTRA_DATA>
+                </METRIC>
+                <METRIC NAME="part_max_used" VAL="77.7" TYPE="float" UNITS="%" TN="143" TMAX="180" DMAX="0" SLOPE="both"
+                        SOURCE="gmond">
+                    <EXTRA_DATA>
+                        <EXTRA_ELEMENT NAME="GROUP" VAL="disk"/>
+                        <EXTRA_ELEMENT NAME="DESC" VAL="Maximum percent used for all partitions"/>
+                        <EXTRA_ELEMENT NAME="TITLE" VAL="Maximum Disk Space Used"/>
+                    </EXTRA_DATA>
+                </METRIC>
+            </HOST>
+        </CLUSTER>
+    </GRID>
+</GANGLIA_XML>
diff --git a/0.8.1-rc1/resource/src/test/resources/test.logging.properties b/0.8.1-rc1/resource/src/test/resources/test.logging.properties
new file mode 100644
index 0000000..a602ce5
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/resources/test.logging.properties
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# Set the default logging level for the subsystems
+
+# batchmgr subsystem
+org.apache.oodt.cas.resource.batchmgr.level = INFO
+
+# monitor subsystem
+org.apache.oodt.cas.resource.monitor.level = INFO
+
+# jobqueue subsystem
+org.apache.oodt.cas.resource.jobqueue.level = INFO
+
+# scheduler subsystem
+org.apache.oodt.cas.resource.scheduler.level = INFO
+
+# system subsystem
+org.apache.oodt.cas.resource.system.level = FINE
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = INFO
+httpclient.wire.header.level = INFO
+httpclient.wire.level = INFO
diff --git a/0.8.1-rc1/resource/src/test/resources/test.resource.properties b/0.8.1-rc1/resource/src/test/resources/test.resource.properties
new file mode 100644
index 0000000..5e0a71c
--- /dev/null
+++ b/0.8.1-rc1/resource/src/test/resources/test.resource.properties
@@ -0,0 +1,76 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+#
+# Properties required to configure the Resource Manager
+
+# resource batchmgr factory
+resource.batchmgr.factory = org.apache.oodt.cas.resource.batchmgr.XmlRpcBatchMgrFactory
+
+# resource monitor factory
+resource.monitor.factory = org.apache.oodt.cas.resource.monitor.AssignmentMonitorFactory
+
+# resource scheduler factory
+resource.scheduler.factory = org.apache.oodt.cas.resource.scheduler.LRUSchedulerFactory
+
+# resource jobqueue factory
+resource.jobqueue.factory = org.apache.oodt.cas.resource.jobqueue.JobStackJobQueueFactory
+
+# resource job repository factory
+resource.jobrepo.factory = org.apache.oodt.cas.resource.jobrepo.MemoryJobRepositoryFactory
+
+# node repository factory
+org.apache.oodt.cas.resource.nodes.repo.factory = org.apache.oodt.cas.resource.noderepo.XmlNodeRepositoryFactory
+
+# queue repository factory
+org.apache.oodt.cas.resource.queues.repo.factory = org.apache.oodt.cas.resource.queuerepo.XmlQueueRepositoryFactory
+
+# resource nodes monitor factory
+org.apache.oodt.cas.resource.monitor.factory = org.apache.oodt.cas.resource.monitor.ganglia.GangliaResourceMonitorFactory
+
+# ganglia resource monitor's load calculator factory
+org.apache.oodt.cas.resource.monitor.loadcalc.factory = org.apache.oodt.cas.resource.monitor.ganglia.loadcalc.WeightedAverageLoadCalcFactory
+
+# JobStack JobQueue config properties
+org.apache.oodt.cas.resource.jobqueue.jobstack.maxstacksize=1000
+
+# XML LRUScheduler config properties
+org.apache.oodt.cas.resource.scheduler.wait.seconds=20
+
+# XML-RPC configuration props
+org.apache.oodt.cas.resource.system.xmlrpc.requestTimeout.minutes=20
+org.apache.oodt.cas.resource.system.xmlrpc.connectionTimeout.minutes=60
+
+# XStream JobRepo configuration props
+org.apache.oodt.cas.resource.jobrepo.xstream.working.dir=[HOME]/job-repo
+org.apache.oodt.cas.resource.jobrepo.xstream.max.history=4000
+
+# XML Node Repository config properties
+org.apache.oodt.cas.resource.nodes.dirs=file://[HOME]/nodes,file://[HOME]/nodes2
+
+# XML Queue Repository config properties
+org.apache.oodt.cas.resource.nodetoqueues.dirs=file://[HOME]/nodes,file://[HOME]/nodes2
+
+# Load calculation weights
+org.apache.oodt.cas.resource.monitor.loadcalc.weight.loadone=1
+org.apache.oodt.cas.resource.monitor.loadcalc.weight.loadfive=5
+org.apache.oodt.cas.resource.monitor.loadcalc.weight.loadfifteen=5
+org.apache.oodt.cas.resource.monitor.loadcalc.weight.memfree=2
+org.apache.oodt.cas.resource.monitor.loadcalc.weight.swapfree=1
+
+#ganglia meta daemon (gmetad) host details
+org.apache.oodt.cas.resource.monitor.ganglia.gemtad.host.address=localhost
+org.apache.oodt.cas.resource.monitor.ganglia.gemtad.host.port=8659
+
diff --git a/0.8.1-rc1/sso/pom.xml b/0.8.1-rc1/sso/pom.xml
new file mode 100644
index 0000000..3648e65
--- /dev/null
+++ b/0.8.1-rc1/sso/pom.xml
@@ -0,0 +1,56 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>oodt-sso</artifactId>
+  <name>OODT Single Sign On Security Package</name>
+  <packaging>jar</packaging>
+  <properties />
+  <build>
+    <plugins />
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-metadata</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+      <version>3.0</version>
+    </dependency>      
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.4</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <version>1.3</version>
+    </dependency>    
+  </dependencies>
+  <distributionManagement />
+</project>
diff --git a/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/AbstractWebBasedSingleSignOn.java b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/AbstractWebBasedSingleSignOn.java
new file mode 100644
index 0000000..1ad57cb
--- /dev/null
+++ b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/AbstractWebBasedSingleSignOn.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.security.sso;
+
+//JDK imports
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 
+ * Abstract class providing an HTTP request and response interface pair to allow
+ * for persistence and management of state information related to SingleSignOn.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public abstract class AbstractWebBasedSingleSignOn implements SingleSignOn {
+
+  protected HttpServletResponse res;
+
+  protected HttpServletRequest req;
+
+  public AbstractWebBasedSingleSignOn() {
+    this.req = null;
+    this.res = null;
+  }
+
+  /**
+   * Constructs a new {@link AbstractWebBasedSingleSignOn} with the given HTTP
+   * request and response.
+   * 
+   * @param res
+   *          The {@link HttpServletRequest}.
+   * @param req
+   *          The {@link HttpServletResponse}.
+   */
+  public AbstractWebBasedSingleSignOn(HttpServletResponse res,
+      HttpServletRequest req) {
+    this.res = res;
+    this.req = req;
+  }
+
+  /**
+   * @return the res
+   */
+  public HttpServletResponse getRes() {
+    return res;
+  }
+
+  /**
+   * @param res
+   *          the res to set
+   */
+  public void setRes(HttpServletResponse res) {
+    this.res = res;
+  }
+
+  /**
+   * @return the req
+   */
+  public HttpServletRequest getReq() {
+    return req;
+  }
+
+  /**
+   * @param req
+   *          the req to set
+   */
+  public void setReq(HttpServletRequest req) {
+    this.req = req;
+  }
+
+}
diff --git a/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/DummyImpl.java b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/DummyImpl.java
new file mode 100644
index 0000000..36ba5a1
--- /dev/null
+++ b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/DummyImpl.java
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.security.sso;
+
+//JDK imports
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * 
+ * Dummy implementation of SSO auth -- if you're logged in, it logs you out. If
+ * you're logged out, it logs you in. Both are independent of the actual
+ * username/password combination you enter. On top of that, your username will
+ * always be <code>guest</code>.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class DummyImpl extends AbstractWebBasedSingleSignOn {
+
+  private static final String DEFAULT_USERNAME = "guest";
+  
+  private static final String DEFAULT_GROUP = "guest";
+
+  private static boolean connected = false;
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.security.sso.SingleSignOn#getCurrentUsername()
+   */
+  public String getCurrentUsername() {
+    return DEFAULT_USERNAME;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.security.sso.SingleSignOn#getLastConnectionStatus()
+   */
+  public boolean getLastConnectionStatus() {
+    // TODO Auto-generated method stub
+    return DummyImpl.connected;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.security.sso.SingleSignOn#isLoggedIn()
+   */
+  public boolean isLoggedIn() {
+    // TODO Auto-generated method stub
+    return DummyImpl.connected;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.security.sso.SingleSignOn#login(java.lang.String,
+   * java.lang.String)
+   */
+  public boolean login(String username, String password) {
+    DummyImpl.connected = true;
+    return DummyImpl.connected;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.security.sso.SingleSignOn#logout()
+   */
+  public void logout() {
+    DummyImpl.connected = false;
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.security.sso.SingleSignOn#retrieveGroupsForUser(java.lang.String)
+   */
+  public List<String> retrieveGroupsForUser(String username) {
+    return Collections.singletonList(DEFAULT_GROUP);
+  }
+
+}
diff --git a/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/OpenSSOImpl.java b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/OpenSSOImpl.java
new file mode 100755
index 0000000..f50c6c2
--- /dev/null
+++ b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/OpenSSOImpl.java
@@ -0,0 +1,189 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.security.sso;
+
+//JDK imports
+import java.util.Collections;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Logger;
+import javax.servlet.http.Cookie;
+
+//APACHE imports
+import org.apache.commons.codec.binary.Base64;
+
+//LMMP imports
+import org.apache.oodt.security.sso.opensso.SSOMetKeys;
+import org.apache.oodt.security.sso.opensso.SSOProxy;
+import org.apache.oodt.security.sso.opensso.UserDetails;
+
+/**
+ * 
+ * Connects to OpenSSO's authorization endpoint and authenticates a user,
+ * implementing the CAS {@link AbstractWebBasedSingleSignOn} interface. This
+ * class can be used in e.g., CAS curator to link into Open SSO.
+ */
+public class OpenSSOImpl extends AbstractWebBasedSingleSignOn implements
+    SSOMetKeys {
+
+  private static final Logger LOG = Logger.getLogger(OpenSSOImpl.class
+      .getName());
+
+  private SSOProxy ssoProxy;
+
+  /**
+   * Default constructor.
+   */
+  public OpenSSOImpl() {
+    this.ssoProxy = new SSOProxy();
+  }
+
+  public String getCurrentUsername() {
+    String cookieVal = this.getCookieVal(USER_COOKIE_KEY);
+    if (cookieVal == null) {
+      // let's try and get the SSO token
+      // and pull the username from there
+      String ssoToken = this.getSSOToken();
+      if (ssoToken != null) {
+        UserDetails details = null;
+        try {
+          details = this.ssoProxy.getUserAttributes(ssoToken);
+        } catch (Exception e) {
+          e.printStackTrace();
+          return UNKNOWN_USER;
+        }
+        return details.getAttributes().getMetadata(UID_ATTRIBUTE_NAME) != null ? details
+            .getAttributes().getMetadata(UID_ATTRIBUTE_NAME) : UNKNOWN_USER;
+      } else
+        return UNKNOWN_USER;
+    } else {
+      return new String(Base64.decodeBase64(cookieVal.getBytes()));
+    }
+  }
+
+  public boolean getLastConnectionStatus() {
+    return this.isLoggedIn();
+  }
+
+  public boolean isLoggedIn() {
+    // TODO: make sure the token is valid?
+    return (this.getSSOToken() == null) ? false : true;
+  }
+
+  public boolean login(String username, String password) {
+
+    String ssoToken = null;
+    try {
+      ssoToken = this.ssoProxy.authenticate(username, password);
+    } catch (Exception e) {
+      e.printStackTrace();
+      return false;
+    }
+
+    this.addCookie(SSO_COOKIE_KEY, "\"" + new String(ssoToken) + "\"");
+
+    this.addCookie(USER_COOKIE_KEY,
+        "\"" + new String(Base64.encodeBase64(username.getBytes())) + "\"");
+
+    return true;
+  }
+
+  public void logout() {
+    this.ssoProxy.logout(this.getSSOToken());
+    this.clearCookie(SSO_COOKIE_KEY);
+    this.clearCookie(USER_COOKIE_KEY);
+  }
+
+  /**
+   * Gets the SSO groups for the LMMP user, identified by her
+   * <code>ssoAuth</code>, where her User ID is provided by
+   * {@link OpenSSOImpl#getCurrentUsername()} and her Token is provided by
+   * {@link OpenSSOImpl#getSSOToken()}.
+   * 
+   * @return A {@link List} of String LMMP groups for the User.
+   * @throws Exception
+   *           If any error (e.g., HTTP REST error) occurs.
+   */
+  public List<String> getGroupsForUser() throws Exception {
+    String token = this.getSSOToken();
+    if (token == null) {
+      return Collections.EMPTY_LIST;
+    } else {
+      UserDetails details = this.ssoProxy.getUserAttributes(token);
+      // groups are formatted in this response to include whole
+      // principals, like lmmp-infra,...principal
+      // so split on "," and take the first token to get the group name
+      List<String> groups = new Vector<String>();
+      for (String rawGroup : details.getRoles()) {
+        groups.add(rawGroup.split(",")[0]);
+      }
+
+      return groups;
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.security.sso.SingleSignOn#retrieveGroupsForUser(java.lang
+   * .String)
+   */
+  @Override
+  public List<String> retrieveGroupsForUser(String username) {
+    // FIXME: not implemented yet
+    return Collections.EMPTY_LIST;
+  }
+
+  protected String getSSOToken() {
+    String cookieVal = this.getCookieVal(SSO_COOKIE_KEY);
+    if (cookieVal != null) {
+      return new String(cookieVal);
+    } else
+      return null;
+  }
+
+  private String getCookieVal(String name) {
+    Cookie[] cookies = this.req.getCookies();
+    for (Cookie cookie : cookies) {
+      if (cookie.getName().equals(name)) {
+        String cookieVal = cookie.getValue().startsWith("\"")
+            && cookie.getValue().endsWith("\"") ? cookie.getValue().substring(
+            1, cookie.getValue().length() - 1) : cookie.getValue();
+        return cookieVal;
+      }
+    }
+
+    return null;
+  }
+
+  private void addCookie(String name, String val) {
+    Cookie userCookie = new Cookie(name, val);
+    userCookie.setPath("/");
+    userCookie.setMaxAge((int) (System.currentTimeMillis() + (60 * 15)));
+    this.res.addCookie(userCookie);
+  }
+
+  private void clearCookie(String name) {
+    Cookie userCookie = new Cookie(name, "blank");
+    userCookie.setPath("/");
+    userCookie.setMaxAge(0);
+    this.res.addCookie(userCookie);
+  }
+
+}
diff --git a/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/SingleSignOn.java b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/SingleSignOn.java
new file mode 100644
index 0000000..3df2dc9
--- /dev/null
+++ b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/SingleSignOn.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.security.sso;
+
+//JDK imports
+import java.util.List;
+
+/**
+ * 
+ * The CAS java-based single sign on API.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface SingleSignOn {
+
+  /**
+   * Should return the current logged in Single Sign On username returned from
+   * the implementation-specific authentication API.
+   * 
+   * @return A string representation of the current SSO username.
+   */
+  public String getCurrentUsername();
+
+  /**
+   * Returns <code>true</code> when the user is logged in, or false otherwise.
+   * 
+   * @return True if the user is logged in, false otherwise.
+   */
+  public boolean isLoggedIn();
+
+  /**
+   * Logs the user with the provided <code>username</code> and
+   * <code>password</code> in to the SSO authentication mechanism.
+   * 
+   * @param username
+   *          The username credentials.
+   * @param password
+   *          The password credentials.
+   * @return True if the login was successful, false otherwise.
+   */
+  public boolean login(String username, String password);
+
+  /**
+   * Logs the current SSO user out of her session.
+   */
+  public void logout();
+
+  /**
+   * Should provide information (true or false) as to whether the last
+   * connection to the SSO authentication service was successful.
+   * 
+   * @return True if the last authentication was successful, false otherwise.
+   */
+  public boolean getLastConnectionStatus();
+
+  /**
+   * Obtains a user's groups from the security principal that this SSO object
+   * talks to.
+   * 
+   * @param username
+   *          The username to obtain the groups for.
+   * @return A {@link List} of string group names obtained from the security
+   *         principal.
+   **/
+  public List<String> retrieveGroupsForUser(String username);
+
+}
diff --git a/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/SingleSignOnFactory.java b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/SingleSignOnFactory.java
new file mode 100644
index 0000000..bed2aae
--- /dev/null
+++ b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/SingleSignOnFactory.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.security.sso;
+
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * 
+ * Object factory for creating {@link SingleSignOn}s from class name Strings.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public final class SingleSignOnFactory {
+
+  private static final Logger LOG = Logger.getLogger(SingleSignOnFactory.class
+      .getName());
+
+  @SuppressWarnings("unchecked")
+  public static AbstractWebBasedSingleSignOn getWebBasedSingleSignOn(String className) {
+    AbstractWebBasedSingleSignOn sso = null;
+    Class<AbstractWebBasedSingleSignOn> clazz = null;
+
+    try {
+      clazz = (Class<AbstractWebBasedSingleSignOn>) Class.forName(className);
+      sso = clazz.newInstance();
+      return sso;
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "ClassNotFoundException when loading web based sso class "
+              + className + " Message: " + e.getMessage());
+    } catch (InstantiationException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "InstantiationException when loading web based sso class "
+              + className + " Message: " + e.getMessage());
+    } catch (IllegalAccessException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "IllegalAccessException when loading web based sso class "
+              + className + " Message: " + e.getMessage());
+    }
+
+    return null;
+  }
+
+}
diff --git a/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/opensso/IdentityDetails.java b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/opensso/IdentityDetails.java
new file mode 100755
index 0000000..517b753
--- /dev/null
+++ b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/opensso/IdentityDetails.java
@@ -0,0 +1,146 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.security.sso.opensso;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * The response from a call to {@link SSOMetKeys#IDENTITY_READ_ENDPOINT}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class IdentityDetails {
+
+  private String name;
+
+  private String type;
+
+  private String realm;
+
+  private List<String> groups;
+
+  private Metadata attributes;
+
+  public IdentityDetails() {
+    this.name = null;
+    this.type = null;
+    this.realm = null;
+    this.groups = new Vector<String>();
+    this.attributes = new Metadata();
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return the type
+   */
+  public String getType() {
+    return type;
+  }
+
+  /**
+   * @param type
+   *          the type to set
+   */
+  public void setType(String type) {
+    this.type = type;
+  }
+
+  /**
+   * @return the realm
+   */
+  public String getRealm() {
+    return realm;
+  }
+
+  /**
+   * @param realm
+   *          the realm to set
+   */
+  public void setRealm(String realm) {
+    this.realm = realm;
+  }
+
+  /**
+   * @return the groups
+   */
+  public List<String> getGroups() {
+    return groups;
+  }
+
+  /**
+   * @param groups
+   *          the groups to set
+   */
+  public void setGroups(List<String> groups) {
+    this.groups = groups;
+  }
+
+  /**
+   * @return the attributes
+   */
+  public Metadata getAttributes() {
+    return attributes;
+  }
+
+  /**
+   * @param attributes
+   *          the attributes to set
+   */
+  public void setAttributes(Metadata attributes) {
+    this.attributes = attributes;
+  }
+
+  public String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.append("[name=");
+    sb.append(this.name);
+    sb.append(",type=");
+    sb.append(this.type);
+    sb.append(",realm=");
+    sb.append(this.realm);
+    sb.append(",roles=");
+    sb.append(this.groups);
+    sb.append(",attributes=");
+    sb.append(this.attributes.getHashtable());
+    sb.append("]");
+    return sb.toString();
+  }
+
+}
diff --git a/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/opensso/SSOMetKeys.java b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/opensso/SSOMetKeys.java
new file mode 100755
index 0000000..7d866f7
--- /dev/null
+++ b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/opensso/SSOMetKeys.java
@@ -0,0 +1,81 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.security.sso.opensso;
+
+/**
+ * 
+ * Met keys for dealing with {@link SSOProxy}.
+ * 
+ */
+public interface SSOMetKeys {
+
+  /* service endpoints */
+  public static final String AUTHENTICATE_ENDPOINT = "https://host/opensso/identity/authenticate";
+
+  public static final String IDENTITY_READ_ENDPOINT = "https://host/opensso/identity/read";
+
+  public static final String IDENTITY_ATTRIBUTES_ENDPOINT = "https://host/opensso/identity/attributes";
+
+  public static final String LOGOUT_ENDPOINT = "https://host/opensso/identity/logout";
+
+  /* cookie names */
+
+  public static final String SSO_COOKIE_KEY = "iPlanetDirectoryPro";
+
+  public static final String USER_COOKIE_KEY = "curationWebapp";
+
+  /* Identity Details response object */
+
+  public static final String IDENTITY_DETAILS_NAME = "identitydetails.name";
+
+  public static final String IDENTITY_DETAILS_TYPE = "identitydetails.type";
+
+  public static final String IDENTITY_DETAILS_REALM = "identitydetails.realm";
+
+  public static final String IDENTITY_DETAILS_GROUP = "identitydetails.group";
+
+  public static final String IDENTITY_DETAILS_ATTR_NAME = "identitydetails.attribute.name";
+
+  public static final String IDENTITY_DETAILS_ATTR_VALUE = "identitydetails.attribute.value";
+  
+  public static final String IDENTITY_DETAILS_ATTR_SKIP_LINE = "identitydetails.attribute=";
+
+  /* User Details response object */
+  public static final String USER_DETAILS_TOKEN = "userdetails.token.id";
+
+  public static final String USER_DETAILS_ROLE = "userdetails.role=id";
+
+  public static final String USER_DETAILS_ATTR_NAME = "userdetails.attribute.name";
+
+  public static final String USER_DETAILS_ATTR_VALUE = "userdetails.attribute.value";
+  
+  public static final String UID_ATTRIBUTE_NAME = "uid";
+
+  /* commands available from SSOProxy command line */
+  public static final String AUTH_COMMAND = "authenticate";
+
+  public static final String IDENTITY_COMMAND = "identity";
+
+  public static final String ATTRIBUTES_COMMAND = "attributes";
+  
+  public static final String LOGOUT_COMMAND = "logout";
+
+  /* general stuff */
+  public static final String UNKNOWN_USER = "Unknown";
+
+}
diff --git a/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/opensso/SSOProxy.java b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/opensso/SSOProxy.java
new file mode 100755
index 0000000..e4e0de3
--- /dev/null
+++ b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/opensso/SSOProxy.java
@@ -0,0 +1,322 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.security.sso.opensso;
+
+//JDK imports
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//APACHE imports
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.PostMethod;
+
+/**
+ * 
+ * A client class to the services provided by the <a
+ * href="https://opensso.dev.java.net/">OpenSSO</a> project. The descriptions of
+ * these services are <a
+ * href="http://developers.sun.com/identity/reference/techart/id-svcs.html"
+ * >here</a>.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class SSOProxy implements SSOMetKeys {
+
+  private static final Logger LOG = Logger.getLogger(SSOProxy.class.getName());
+  private static final String AUTH_ENDPOINT;
+  private static final String AUTH_ENDPOINT_KEY = "AUTH_ENDPOINT";
+  private static final String IDENT_READ_ENDPOINT;
+  private static final String IDENT_READ_ENDPOINT_KEY = "IDENT_READ_ENDPOINT";
+  private static final String IDENT_ATTR_ENDPOINT;
+  private static final String IDENT_ATTR_ENDPOINT_KEY = "IDENT_ATTR_ENDPOINT";
+  private static final String LOG_ENDPOINT;
+  private static final String LOG_ENDPOINT_KEY = "LOG_ENDPOINT";
+  
+  static {
+	  if (System.getProperty(AUTH_ENDPOINT_KEY) != null) {
+		  AUTH_ENDPOINT = System.getProperty(AUTH_ENDPOINT_KEY);
+	  } else {
+		  AUTH_ENDPOINT = AUTHENTICATE_ENDPOINT;
+	  }
+	  if (System.getProperty(IDENT_READ_ENDPOINT_KEY) != null) {
+		  IDENT_READ_ENDPOINT = System.getProperty(IDENT_READ_ENDPOINT_KEY);
+	  } else {
+		  IDENT_READ_ENDPOINT = IDENTITY_READ_ENDPOINT;
+	  }
+	  if (System.getProperty(IDENT_ATTR_ENDPOINT_KEY) != null) {
+		  IDENT_ATTR_ENDPOINT = System.getProperty(IDENT_ATTR_ENDPOINT_KEY);
+	  } else {
+		  IDENT_ATTR_ENDPOINT = IDENTITY_ATTRIBUTES_ENDPOINT;
+	  }
+	  if (System.getProperty(LOG_ENDPOINT_KEY) != null) {
+		  LOG_ENDPOINT = System.getProperty(LOG_ENDPOINT_KEY);
+	  } else {
+		  LOG_ENDPOINT = LOGOUT_ENDPOINT;
+	  }
+
+	  LOG.log(Level.INFO, AUTH_ENDPOINT_KEY + " set to " + AUTH_ENDPOINT);
+	  LOG.log(Level.INFO, IDENT_READ_ENDPOINT_KEY + " set to " + IDENT_READ_ENDPOINT);
+	  LOG.log(Level.INFO, IDENT_ATTR_ENDPOINT_KEY + " set to " + IDENT_ATTR_ENDPOINT);
+	  LOG.log(Level.INFO, LOG_ENDPOINT_KEY + " set to " + LOG_ENDPOINT);
+  }
+
+  public String authenticate(String username, String password) {
+    HttpClient httpClient = new HttpClient();
+    PostMethod post = new PostMethod(AUTH_ENDPOINT);
+    String response = null;
+    String ssoToken = null;
+
+    NameValuePair[] data = { new NameValuePair("username", username),
+        new NameValuePair("password", password),
+        new NameValuePair("uri", "realm/lmmp") };
+
+    post.setRequestBody(data);
+
+    try {
+      httpClient.executeMethod(post);
+      if (post.getStatusCode() != HttpStatus.SC_OK) {
+        throw new HttpException(post.getStatusLine().toString());
+      }
+      response = post.getResponseBodyAsString().trim();
+      ssoToken = response.substring(9);
+    } catch (Exception e) {
+      e.printStackTrace();
+    } finally {
+      post.releaseConnection();
+    }
+
+    return ssoToken;
+  }
+
+  public IdentityDetails readIdentity(String username, String token)
+      throws Exception {
+    HttpClient httpClient = new HttpClient();
+    PostMethod post = new PostMethod(IDENT_READ_ENDPOINT);
+    LOG.log(Level.INFO, "Obtaining identity: username: [" + username
+        + "]: token: [" + token + "]: REST url: [" + IDENT_READ_ENDPOINT
+        + "]");
+    NameValuePair[] data = { new NameValuePair("name", username),
+        new NameValuePair("admin", token) };
+
+    post.setRequestBody(data);
+
+    httpClient.executeMethod(post);
+    if (post.getStatusCode() != HttpStatus.SC_OK) {
+      throw new Exception(post.getStatusLine().toString());
+    }
+
+    return parseIdentityDetails(post.getResponseBodyAsString().trim());
+
+  }
+
+  public UserDetails getUserAttributes(String token) throws Exception {
+    HttpClient httpClient = new HttpClient();
+    PostMethod post = new PostMethod(IDENT_ATTR_ENDPOINT);
+    LOG.log(Level.INFO, "Obtaining user attributes: token: [" + token
+        + "]: REST url: [" + IDENT_ATTR_ENDPOINT + "]");
+    NameValuePair[] data = { new NameValuePair("subjectid", token) };
+
+    post.setRequestBody(data);
+
+    httpClient.executeMethod(post);
+    if (post.getStatusCode() != HttpStatus.SC_OK) {
+      throw new Exception(post.getStatusLine().toString());
+    }
+
+    return parseUserDetails(post.getResponseBodyAsString().trim());
+
+  }
+
+  public void logout(String token) {
+    HttpClient httpClient = new HttpClient();
+    PostMethod post = new PostMethod(LOG_ENDPOINT);
+    LOG.log(Level.INFO, "Logging out: token: [" + token + "]: REST url: ["
+        + LOG_ENDPOINT + "]");
+    NameValuePair[] data = { new NameValuePair("subjectid", token) };
+    post.setRequestBody(data);
+
+    try {
+      httpClient.executeMethod(post);
+      if (post.getStatusCode() != HttpStatus.SC_OK) {
+        throw new HttpException(post.getStatusLine().toString());
+      }
+    } catch (HttpException e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    } catch (IOException e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    } finally {
+      post.releaseConnection();
+    }
+  }
+
+  private IdentityDetails parseIdentityDetails(String serviceResponse) {
+    ByteArrayInputStream is = new ByteArrayInputStream(serviceResponse
+        .getBytes());
+    BufferedReader br = new BufferedReader(new InputStreamReader(is));
+    IdentityDetails details = new IdentityDetails();
+    String line = null, lastAttrKeyRead = null;
+
+    try {
+      while ((line = br.readLine()) != null) {
+        if (line.equals(IDENTITY_DETAILS_ATTR_SKIP_LINE))
+          continue;
+        String key = null, val = null;
+        if (line.startsWith(IDENTITY_DETAILS_REALM)) {
+          // can't parse it the same way
+          key = line.substring(0, IDENTITY_DETAILS_REALM.length());
+          val = line.substring(IDENTITY_DETAILS_REALM.length() + 1);
+        } else {
+          String[] lineToks = line.split("=");
+          key = lineToks[0];
+          val = lineToks[1];
+        }
+
+        if (key.equals(IDENTITY_DETAILS_NAME)) {
+          details.setName(val);
+        } else if (key.equals(IDENTITY_DETAILS_TYPE)) {
+          details.setType(val);
+        } else if (key.equals(IDENTITY_DETAILS_REALM)) {
+          details.setRealm(val);
+        } else if (key.equals(IDENTITY_DETAILS_GROUP)) {
+          details.getGroups().add(val);
+        } else if (key.equals(IDENTITY_DETAILS_ATTR_NAME)) {
+          lastAttrKeyRead = val;
+        } else if (key.equals(IDENTITY_DETAILS_ATTR_VALUE)) {
+          details.getAttributes().addMetadata(lastAttrKeyRead, val);
+        }
+      }
+    } catch (IOException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Error reading service response line: [" + line
+          + "]: Message: " + e.getMessage());
+    } finally {
+      if (is != null) {
+        try {
+          is.close();
+        } catch (Exception ignore) {
+        }
+
+        is = null;
+      }
+
+      if (br != null) {
+        try {
+          br.close();
+        } catch (Exception ignore) {
+        }
+
+        br = null;
+      }
+    }
+
+    return details;
+  }
+
+  private UserDetails parseUserDetails(String serviceResponse) {
+    ByteArrayInputStream is = new ByteArrayInputStream(serviceResponse
+        .getBytes());
+    BufferedReader br = new BufferedReader(new InputStreamReader(is));
+    UserDetails details = new UserDetails();
+    String line = null, lastAttrKeyRead = null;
+
+    try {
+      while ((line = br.readLine()) != null) {
+        String key = null, val = null;
+        if (line.startsWith(USER_DETAILS_ROLE)) {
+          // can't parse by splitting, parse by using substring
+          key = line.substring(0, USER_DETAILS_ROLE.length());
+          val = line.substring(USER_DETAILS_ROLE.length() + 1);
+        } else {
+          String[] lineToks = line.split("=");
+          key = lineToks[0];
+          val = lineToks[1];
+        }
+
+        if (key.equals(USER_DETAILS_TOKEN)) {
+          details.setToken(val);
+        } else if (key.equals(USER_DETAILS_ROLE)) {
+          details.getRoles().add(val);
+        } else if (key.equals(USER_DETAILS_ATTR_NAME)) {
+          lastAttrKeyRead = val;
+        } else if (key.equals(USER_DETAILS_ATTR_VALUE)) {
+          details.getAttributes().addMetadata(lastAttrKeyRead, val);
+        }
+      }
+    } catch (IOException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Error reading service response line: [" + line
+          + "]: Message: " + e.getMessage());
+    } finally {
+      if (is != null) {
+        try {
+          is.close();
+        } catch (Exception ignore) {
+        }
+
+        is = null;
+      }
+
+      if (br != null) {
+        try {
+          br.close();
+        } catch (Exception ignore) {
+        }
+
+        br = null;
+      }
+    }
+
+    return details;
+  }
+
+  public static void main(String[] args) throws Exception {
+    String usage = "SSOProxy <cmd> [args]\n\n" + "Where cmd is one of:\n"
+        + "authenticate <user> <pass>\n" + "identity <user> <token>\n"
+        + "attributes <token>\nlogout <token>\n";
+
+    if (args.length < 2 || args.length > 3) {
+      System.err.println(usage);
+      System.exit(1);
+    }
+
+    String cmd = args[0];
+    SSOProxy sso = new SSOProxy();
+    if (cmd.equals(AUTH_COMMAND)) {
+      System.out.println(sso.authenticate(args[1], args[2]));
+    } else if (cmd.equals(IDENTITY_COMMAND)) {
+      System.out.println(sso.readIdentity(args[1], args[2]));
+    } else if (cmd.equals(ATTRIBUTES_COMMAND)) {
+      System.out.println(sso.getUserAttributes(args[1]));
+    } else if (cmd.equals(LOGOUT_COMMAND)) {
+      sso.logout(args[1]);
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/opensso/UserDetails.java b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/opensso/UserDetails.java
new file mode 100755
index 0000000..fe7988f
--- /dev/null
+++ b/0.8.1-rc1/sso/src/main/java/org/apache/oodt/security/sso/opensso/UserDetails.java
@@ -0,0 +1,105 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.security.sso.opensso;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * 
+ * The response from a query to {@link SSOMetKeys#IDENTITY_ATTRIBUTES_ENDPOINT}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class UserDetails {
+
+  private String token;
+
+  private List<String> roles;
+
+  private Metadata attributes;
+
+  public UserDetails() {
+    this.token = null;
+    this.roles = new Vector<String>();
+    this.attributes = new Metadata();
+  }
+
+  /**
+   * @return the token
+   */
+  public String getToken() {
+    return token;
+  }
+
+  /**
+   * @param token
+   *          the token to set
+   */
+  public void setToken(String token) {
+    this.token = token;
+  }
+
+  /**
+   * @return the roles
+   */
+  public List<String> getRoles() {
+    return roles;
+  }
+
+  /**
+   * @param roles
+   *          the roles to set
+   */
+  public void setRoles(List<String> roles) {
+    this.roles = roles;
+  }
+
+  /**
+   * @return the attributes
+   */
+  public Metadata getAttributes() {
+    return attributes;
+  }
+
+  /**
+   * @param attributes
+   *          the attributes to set
+   */
+  public void setAttributes(Metadata attributes) {
+    this.attributes = attributes;
+  }
+
+  public String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.append("[token=");
+    sb.append(this.token);
+    sb.append(",roles=");
+    sb.append(this.roles);
+    sb.append(",attributes=");
+    sb.append(this.attributes.getHashtable());
+    sb.append("]");
+    return sb.toString();
+  }
+}
diff --git a/0.8.1-rc1/sso/src/main/php/pear/Config.php b/0.8.1-rc1/sso/src/main/php/pear/Config.php
new file mode 100644
index 0000000..8d3cec1
--- /dev/null
+++ b/0.8.1-rc1/sso/src/main/php/pear/Config.php
@@ -0,0 +1,65 @@
+<?php
+/*
+ * 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.
+ */
+
+/**
+ * 
+ *  @package Org_Apache_Oodt_Security
+ *  @author  Andrew F. Hart
+ *  @version $Revision$
+ * 
+ *  PHP Single Sign On Authentication Library and Utilities
+ * 
+ */
+
+/**
+ * LDAP Host URI
+ * 
+ * The path to the host where the LDAP directory server is running
+ * @var string
+ */
+define("SSO_LDAP_HOST", "ldaps://host.domain");
+
+/**
+ * LDAP Port
+ * 
+ * The port on @link{SSO_LDAP_HOST} where the LDAP directory server
+ * is listening.
+ * 
+ * Default ports:
+ *   389: Standard (non-ssl) LDAP (ldap://...)
+ *   636: Secure LDAP (ldaps://...)
+ * @var string
+ */
+define("SSO_LDAP_PORT", 636);
+
+/**
+ * Base DN
+ * 
+ * The base domain name to use when interacting with the LDAP server
+ *
+ * @var string
+ */
+define("SSO_BASE_DN", "dc=sample, dc=jpl, dc=nasa, dc=gov");
+
+/**
+ * Cookie Key
+ * 
+ * The unique string to use in identifying the security cookie
+ * 
+ */
+define("SSO_COOKIE_KEY", "__ac__sc__");
diff --git a/0.8.1-rc1/sso/src/main/php/pear/SingleSignOn.php b/0.8.1-rc1/sso/src/main/php/pear/SingleSignOn.php
new file mode 100644
index 0000000..512dffa
--- /dev/null
+++ b/0.8.1-rc1/sso/src/main/php/pear/SingleSignOn.php
@@ -0,0 +1,202 @@
+<?php
+/*
+ * 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.
+ */
+/**
+ * 
+ *  @package Org_Apache_Oodt_Security
+ *  @author Chris A. Mattmann
+ *  @author Andrew F. Hart
+ *  @version $Revision$
+ * 
+ *  PHP Single Sign On Library for EDRN PHP-based products.
+ * 
+ */
+
+class Org_Apache_Oodt_Security_SingleSignOn {
+
+	private $connectionStatus;
+	
+	private $conn;
+
+	public function __construct() {
+		$this->connectionStatus = 1;
+	}
+
+	public function getCurrentUsername() {
+		return $this->getSingleSignOnUsername();
+	}
+
+	public function isLoggedIn() {
+		return ($this->getSingleSignOnUsername() != null);
+	}
+
+	public function login($username, $password) {
+		// first check to see if we are already signed in
+		if ($this->getSingleSignOnUsername() <> "" 
+			&& strcmp($this->getSingleSignOnUsername(), $username) == 0) {
+			// we're logged in already
+			return true;
+		} else {
+			// log in via LDAP
+			$ldaprdn = "uid=" . $username . ',' . SSO_BASE_DN;
+			$ldappass = $password;
+			
+			// connect to ldap server 
+			$ldapconn = $this->connect(SSO_LDAP_HOST, SSO_LDAP_PORT);
+			if ($ldapconn) {
+				
+				// binding to ldap server 
+				$ldapbind = @ ldap_bind($ldapconn, $ldaprdn, $ldappass);
+
+				// verify binding 
+				if ($ldapbind) {
+					$this->createSingleSignOnCookie($username, $password);
+					return true;
+				} else {
+					return false;
+				}
+
+			} else {
+				$this->connectionStatus = 0;
+				return false;
+			}
+		}
+
+	}
+
+	public function logout() {
+		$this->clearSingleSignOnInfo();
+	}
+
+	public function getLastConnectionStatus() {
+		return ($this->connectionStatus == 1);
+	}
+	
+	public function retrieveGroupsForUser($username,$searchDirectory = SSO_BASE_DN) {
+		// attempt to connect to ldap server 
+		$ldapconn = $this->connect(SSO_LDAP_HOST,SSO_LDAP_PORT);
+		$groups   = array();
+		if ($ldapconn) {
+			$filter = "(&(objectClass=groupOfUniqueNames)"
+				."(uniqueMember=uid={$username}," . SSO_BASE_DN . "))";
+			$result = ldap_search($ldapconn,$searchDirectory,$filter,array('cn'));
+			 
+			if ($result) {
+				$entries = ldap_get_entries($ldapconn,$result);
+				foreach ($entries as $rawGroup) {
+					if (isset($rawGroup['cn'][0]) 
+					&& $rawGroup['cn'][0] != '') {
+						$groups[] = $rawGroup['cn'][0];
+					}
+				}
+			}
+		} 
+		
+		return $groups;
+	}
+	
+	/**
+	 * 
+	 * retrieves the set of attributes from the users ldap entry 
+	 * @param string $username user for which attributes will be returned
+	 * @param array $attributes ldap attributes to retrieve
+	 * @param string $searchDirectory optional path to users ldap entry 
+	 */
+	public function retrieveUserAttributes($username,$attributes,$searchDirectory = SSO_BASE_DN) {
+		// attempt to connect to ldap server 
+		$ldapconn = $this->connect(SSO_LDAP_HOST,SSO_LDAP_PORT);
+		$attr = array();
+		
+		if ($ldapconn) {
+			// get user attributes
+			$filter = "uid=".$username;
+			$result = ldap_search($ldapconn,$searchDirectory,$filter,$attributes);
+			if ($result) {
+				$entries = ldap_get_entries($ldapconn,$result);
+				return $entries;
+			} else {
+				return array();
+			}
+		}
+	}
+	
+	
+	public function changePassword($newPass,$encryptionMethod = "SHA") {
+		if ($this->isLoggedIn()) {
+			$user  = "uid={$this->getSingleSignOnUsername()}," . SSO_BASE_DN ;
+			$entry = array();
+			
+			switch (strtoupper($encryptionMethod)) {
+				case "SHA": 
+					$entry['userPassword'] = "{SHA} " . base64_encode(pack("H*",sha1($newPass))); 
+					break;
+				case "MD5": 
+					$entry['userPassword'] = "{MD5} " . base64_encode(pack("H*",md5($newPass)));  
+					break;
+				default:
+					throw new Exception("Unsupported encryption method requested");
+			}
+			
+			if (ldap_mod_replace($this->conn,$user,$entry)) {
+				return true;
+			} else {
+				return false;
+			}
+		} else {
+			return false;
+		}
+	}
+	
+	public function connect($server,$port) {
+		if ($conn = ldap_connect($server,$port)) {
+			// Connection established
+			$this->connectionStatus = 1;
+			ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3);
+			ldap_set_option($conn, LDAP_OPT_DEBUG_LEVEL, 7);
+			ldap_set_option($conn, LDAP_OPT_REFERRALS, 0);	
+			$this->conn = $conn;
+			return $conn;
+		} else {
+			// Connection failed
+			return false;
+		}
+	}
+
+	private function clearSingleSignOnInfo() {
+		$oldCookie = $_COOKIE[SSO_COOKIE_KEY];
+		setcookie(SSO_COOKIE_KEY, $oldCookie, 1, "/");
+	}
+
+	private function getSingleSignOnUsername() {
+		$theCookie = $_COOKIE[SSO_COOKIE_KEY];
+		if ($theCookie <> "") {
+			$userpass = base64_decode(urldecode($theCookie));
+			$userpassArr = explode(":", $userpass);
+			return $userpassArr[0];
+		} else
+			return null;
+	}
+
+	private function createSingleSignOnCookie($username, $password) {
+		if (!isset ($_COOKIE[SSO_COOKIE_KEY])) {
+			$theCookieStrUnencoded = $username . ":" . $password;
+			$theCookieStrEncoded = "\"".base64_encode($theCookieStrUnencoded)."\"";
+			setcookie(SSO_COOKIE_KEY, $theCookieStrEncoded, time() + (86400 * 7), "/"); // expire in 1 day
+		}
+	}
+}
+?>
diff --git a/0.8.1-rc1/sso/src/main/php/pear/package.xml b/0.8.1-rc1/sso/src/main/php/pear/package.xml
new file mode 100644
index 0000000..fe6abcf
--- /dev/null
+++ b/0.8.1-rc1/sso/src/main/php/pear/package.xml
@@ -0,0 +1,94 @@
+<?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.
+ */
+ 
+   @package Org_Apache_Oodt_Security
+   @author Chris A. Mattmann
+   @author Andrew F. Hart
+   @version $Revision$
+-->
+<package version="2.0" xmlns="http://pear.php.net/dtd/package-2.0"
+  xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0.xsd
+         http://pear.php.net/dtd/package-2.0
+         http://pear.php.net/dtd/package-2.0.xsd">
+  <name>Apache_OODT_Security</name>
+  <channel>pear.apache.org/oodt</channel>
+  <summary>OODT Single Sign On Package</summary>
+  <description>
+    This package provides a PHP library for single sign-on for 
+    OODT applications which authenticate and authorize against an
+    LDAP server.
+  </description>
+  <lead>
+    <name>Andrew Hart</name>
+    <user>ahart</user>
+    <email>andrew.f.hart@jpl.nasa.gov</email>
+    <active>yes</active>
+  </lead>
+  <date>2013-06-29</date>
+  <version>
+    <release>0.6.0</release>
+    <api>0.6.0</api>
+  </version>
+  <stability>
+    <release>stable</release>
+    <api>stable</api>
+  </stability>
+  <license uri="http://www.apache.org/licenses/LICENSE-2.0.html">Apache Software License 2.0</license>
+  <notes>
+    This package provides a PHP library for single sign-on for 
+    OODT applications which authenticate and authorize against an
+    LDAP server.
+  </notes>
+  <contents>
+    <dir name="/" baseinstalldir="Org/Apache/Oodt/Security">
+      <file name="Config.php" role="php"/>
+      <file name="SingleSignOn.php" role="php"/>
+    </dir><!-- / -->
+  </contents>
+  <dependencies>
+    <required>
+      <php>
+        <min>5.1.6</min>
+      </php>
+      <pearinstaller>
+        <min>1.6.1</min>
+      </pearinstaller>
+    </required>
+  </dependencies>
+  <phprelease />
+  <changelog>
+    <release>
+      <version>
+        <release>0.1.0</release>
+        <api>0.1.0</api>
+      </version>
+      <stability>
+        <release>stable</release>
+        <api>stable</api>
+      </stability>
+      <date>2009-03-04</date>
+      <license uri="http://oodt.jpl.nasa.gov">OODT License</license>
+      <notes>
+      This is the initial release of the OODT CAS Security utility as a PEAR package.
+      </notes>     
+    </release>
+  </changelog>
+</package>
diff --git a/0.8.1-rc1/tools/pdi_plugin/build-res/subfloor-pkg.xml b/0.8.1-rc1/tools/pdi_plugin/build-res/subfloor-pkg.xml
new file mode 100644
index 0000000..c82f9ba
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/build-res/subfloor-pkg.xml
@@ -0,0 +1,367 @@
+<!--===========================================================================
+Copyright (c) 2009, Pentaho Engineering Team
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Pentaho Corporation nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY Pentaho Engineering Team ''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 <copyright holder> 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.
+============================================================================-->
+<!--===========================================================================
+    == SUBFLOOR-PKG ==
+    $Rev: 100 $
+    $Date: 2009-12-09 11:43:26 -0500 (Wed, 09 Dec 2009) $
+    Project Home: http://code.google.com/p/subfloor/
+    Provides default targets for creating application archives such as zip and tar.gzip
+    files.
+    ============================================================================-->
+
+<project name="subfloor-pkg" basedir="." default="default" xmlns:ivy="antlib:org.apache.ivy.ant">
+
+  <!-- Define the default location of the common build file -->
+  <property name="subfloor.file"
+            value="./subfloor.xml"
+            description="This is the location of the standardized subfloor.xml file" />
+
+  <!-- Import the common_build.xml file which contains all the default tasks -->
+  <import file="${subfloor.file}" />
+
+  <property name="stage.dir" value="${bin.dir}/stage" description="Package staging" />
+  <property name="package.root.dir"
+            value="${ivy.artifact.id}"
+            description="Root directory of final zip or tar package" />
+  <property name="approot.stage.dir"
+            value="${stage.dir}/${package.root.dir}"
+            description="Stage application root dir" />
+  <property name="package.id" value="${ivy.artifact.id}" />
+  <property name="package.basename" value="${package.id}-${project.revision}" />
+  <property name="package.resdir" value="${basedir}/package-res" />
+  <property name="package.artifact.ivyfile"
+            value="package-ivy.xml"
+            description="The ivy file defining dependencies of the package" />
+  <property name="package.artifact.pomfile"
+            value="package-pom.xml"
+            description="The Maven pom file defining dependencies of the package" />
+
+  <target name="dist" depends="jar,package" description="Builds and packages the application" />
+
+  <target name="clean-dist">
+    <delete dir="${dist.dir}" />
+    <delete dir="${stage.dir}" />
+  </target>
+
+  <!-- override of jar target.. this definitely should be moved into common build -->
+  <target name="jar"
+          depends="compile,set-build.id,create-version-file"
+          description="Jars up the bin directory after a compile">
+    <jar destfile="${dist.dir}/${ivy.artifact.id}-${project.revision}.jar">
+      <manifest>
+        <attribute name="Implementation-Title" value="${impl.title}" />
+        <attribute name="Implementation-Version" value="${project.revision}.${build.id}" />
+        <attribute name="Implementation-Vendor" value="${impl.vendor}" />
+        <attribute name="Implementation-ProductID" value="${impl.productID}" />
+      </manifest>
+      <fileset dir="${classes.dir}" />
+    </jar>
+  </target>
+
+  <target name="create-version-file">
+    <propertyfile file="${classes.dir}/version.properties" comment="${impl.title} build information">
+      <entry key="version" value="${project.revision}.${build.id}" />
+      <entry key="builddate" type="date" value="now" />
+    </propertyfile>
+  </target>
+
+  <target name="assemble.init">
+    <mkdir dir="${approot.stage.dir}" />
+  </target>
+
+  <target name="assemble" depends="assemble.init,assemble.copy-libs">
+    <copy todir="${approot.stage.dir}" overwrite="true">
+      <fileset dir="${package.resdir}" />
+    </copy>
+    <chmod perm="a+x" dir="${stage.dir}" includes="**/*.sh" />
+  </target>
+
+  <target name="assemble.copy-libs">
+    <copy todir="${approot.stage.dir}/lib">
+      <fileset dir="${lib.dir}" />
+      <fileset file="${dist.dir}/${ivy.artifact.id}-${project.revision}.jar" />
+    </copy>
+  </target>
+
+  <target name="package"
+          depends="assemble,package-zip"
+          description="Creates packaged distributable artifacts" />
+
+  <target name="package-zip">
+    <zip destfile="${dist.dir}/${package.basename}.zip">
+      <zipfileset dir="${stage.dir}" filemode="755">
+        <include name="**/*.sh" />
+        <include name="**/JavaApplicationStub" />
+        <include name="**/*.command" />
+      </zipfileset>
+      <zipfileset dir="${stage.dir}">
+        <exclude name="**/*.sh" />
+        <exclude name="**/JavaApplicationStub" />
+        <exclude name="**/*.command" />
+      </zipfileset>
+    </zip>
+  </target>
+  
+
+  
+  <!-- ============================================linuxPackage===================================================== -->
+
+  <property name="linuxPackage.name" value="pentaho-${package.id}" />
+
+  <property name="linuxPackage.longName" value="${impl.title}" />
+  <property name="linuxPackage.description" value="${impl.title}" />
+  <property name="linuxPackage.release" value="1" />
+  <property name="linuxPackage.initd.startCommandDelegatee" value="start.pentaho.sh" 
+    description="init.d script will delegate to this script located in /opt/pentaho/${linuxPackage.name}" />
+
+  <property name="linuxPackage.initd.stopCommandDelegatee" value="stop.pentaho.sh" 
+    description="init.d script will delegate to this script located in /opt/pentaho/${linuxPackage.name}" />
+
+  <property name="linuxPackage.initd.processName" value="catalina" 
+    description="string that must be present to prove pid is not stale; see init.d script" />
+  <property name="linuxPackage.res.dir" value="linux-res" description="Directory with Linux package resources." />
+  <filterset begintoken="[[[" endtoken="]]]" id="linuxPackage.filterset">
+    <filter token="linuxPackage.initd.startCommandDelegatee" value="${linuxPackage.initd.startCommandDelegatee}" />
+    <filter token="linuxPackage.initd.stopCommandDelegatee" value="${linuxPackage.initd.stopCommandDelegatee}" />
+    <filter token="linuxPackage.initd.processName" value="${linuxPackage.initd.processName}" />
+    <filter token="linuxPackage.name" value="${linuxPackage.name}" />
+    <filter token="linuxPackage.longName" value="${linuxPackage.longName}" />
+  </filterset>
+  <!-- prepares Debian control file and scripts shared by DEB and RPM -->
+  <target name="linuxPackage-prepare-control">
+    <copy todir="${linuxPackage.stage.dir}/control" overwrite="true">
+      <fileset dir="${linuxPackage.res.dir}/control" />
+      <filterset refid="linuxPackage.filterset" />
+      <filterset refid="${linuxPackage.extraFilterset}" />
+    </copy>
+  </target>
+  <!-- prepares actual files to be installed shared by DEB and RPM -->
+  <target name="linuxPackage-prepare-data">
+    <mkdir dir="${linuxPackage.stage.dir}/data/opt/pentaho/${linuxPackage.name}" />
+
+    <antcall target="linuxPackage-copy-files">
+      <param name="linuxPackage.dataDir" value="${linuxPackage.stage.dir}/data" />
+      <param name="linuxPackage.packageFormat" value="${linuxPackage.packageFormat}" />
+    </antcall>
+    <copy todir="${linuxPackage.stage.dir}/data" overwrite="true">
+      <fileset dir="${linuxPackage.res.dir}/data" />
+      <filterset refid="linuxPackage.filterset" />
+      <filterset refid="${linuxPackage.extraFilterset}" />
+    </copy>
+    <!-- if any files named __package.name__, rename them-->
+
+    <if>
+      <available file="${linuxPackage.stage.dir}/data/etc/init.d/__package.name__" type="file" />
+      <then>
+        <move file="${linuxPackage.stage.dir}/data/etc/init.d/__package.name__" tofile="${linuxPackage.stage.dir}/data/etc/init.d/${linuxPackage.name}" />
+      </then>
+    </if>
+    <if>
+      <available file="${linuxPackage.stage.dir}/data/opt/pentaho/__package.name__" type="dir" />
+      <then>
+        <move file="${linuxPackage.stage.dir}/data/opt/pentaho/__package.name__" tofile="${linuxPackage.stage.dir}/data/opt/pentaho/${linuxPackage.name}" />
+      </then>
+    </if>
+  </target>
+
+  <!-- override if necessary -->
+  <target name="linuxPackage-copy-files">
+    <echo>Copying files for Linux package format: ${linuxPackage.packageFormat}</echo>
+    <copy todir="${linuxPackage.dataDir}/opt/pentaho/${linuxPackage.name}">
+      <fileset dir="${stage.dir}/${package.id}" />
+    </copy>
+  </target>
+  <!-- ============================================deb============================================================== -->
+
+  <property name="deb.longName" value="${linuxPackage.longName}" />
+
+  <property name="deb.name" value="${linuxPackage.name}" />
+  <property name="deb.arch"
+            value="all"
+            description="One of i386, amd64, or all." />
+
+ <property name="deb.maintainer" value="buildguy &lt;buildguy@pentaho.com&gt;" />
+  <property name="deb.desc" value="${linuxPackage.description}" />
+  <property name="deb.release" value="${linuxPackage.release}" />
+  <property name="deb.stage.dir"
+            value="${bin.dir}/deb-stage"
+            description="Staging directory for Debian package creation." />
+
+  <property name="deb.res.dir"
+            value="${linuxPackage.res.dir}"
+            description="Debian package resources." />
+  <filterset begintoken="[[[" endtoken="]]]" id="deb.filterset">
+    <filter token="deb.name" value="${deb.name}" />
+    <filter token="deb.version" value="${project.revision}-${deb.release}" />
+    <filter token="deb.longName" value="${deb.longName}" />
+    <filter token="deb.arch" value="${deb.arch}" />
+    <filter token="deb.desc" value="${deb.desc}" />
+    <filter token="deb.maintainer" value="${deb.maintainer}" />
+  </filterset>
+  <!-- jdeb is cross-platform Debian package tool -->
+  <target name="install-jdeb" depends="install-ivy">
+    <taskdef-with-ivy task-name="jdeb" classname="org.vafer.jdeb.ant.DebAntTask" organisation="org.vafer" module="jdeb" 
+      revision="0.8" />
+  </target>
+
+  <target name="package-deb" depends="install-jdeb" description="Creates Debian package.">
+
+    <antcall target="linuxPackage-prepare-control">
+      <param name="linuxPackage.stage.dir" value="${deb.stage.dir}" />
+      <param name="linuxPackage.res.dir" value="${deb.res.dir}" />
+      <param name="linuxPackage.extraFilterset" value="deb.filterset" />
+    </antcall>
+    <antcall target="linuxPackage-prepare-data">
+      <param name="linuxPackage.stage.dir" value="${deb.stage.dir}" />
+      <param name="linuxPackage.res.dir" value="${deb.res.dir}" />
+      <param name="linuxPackage.extraFilterset" value="deb.filterset" />
+      <param name="linuxPackage.packageFormat" value="deb" />
+    </antcall>
+    <!-- tar for the sole purpose of creating execute bit -->
+    <tar destfile="${deb.stage.dir}/data.tar.gz" longfile="gnu" compression="gzip">
+      <tarfileset dir="${deb.stage.dir}/data" mode="755">
+        <include name="**/*.sh" />
+      </tarfileset>
+      <tarfileset dir="${deb.stage.dir}/data">
+        <exclude name="**/*.sh" />
+      </tarfileset>
+    </tar>
+    <!-- do not change this package name; it is consistent with Debian package naming conventions -->
+    <!-- the 1 below is the Debian revision number, which may change if only the control files are changed -->
+    <!-- http://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.html -->
+    <jdeb destfile="${dist.dir}/${deb.name}_${project.revision}-${deb.release}_${deb.arch}.deb"
+        control="${deb.stage.dir}/control">
+      <data src="${deb.stage.dir}/data.tar.gz" type="archive" />
+    </jdeb>
+  </target>
+  <!-- ================================================rpm========================================================== -->
+
+  <property name="rpm.name" value="${linuxPackage.name}" />
+  <property name="rpm.arch"
+            value="NOARCH"
+            description="One of I386, X86_64, or NOARCH. Case matters." />
+  <property name="rpm.group" value="System Environment/Daemons" description="Group for RPM spec file." />
+  <property name="rpm.summary" value="${linuxPackage.description}" description="Summary for RPM spec file." />
+
+  <property name="rpm.stage.dir"
+            value="${bin.dir}/rpm-stage"
+            description="Staging directory for RPM package creation." />
+
+  <property name="rpm.res.dir"
+            value="${linuxPackage.res.dir}"
+            description="RPM package resources." />
+  <filterset begintoken="[[[" endtoken="]]]" id="rpm.filterset">
+  </filterset>
+  <!-- redline is cross-platform RPM package tool -->
+  <target name="install-redline" depends="install-ivy">
+    <taskdef-with-ivy task-name="redline" classname="org.freecompany.redline.ant.RedlineTask" organisation="org.redline-rpm" module="redline" 
+      revision="1.1.9" />
+  </target>
+  <target name="package-rpm" depends="install-redline">
+    <antcall target="linuxPackage-prepare-control">
+      <param name="linuxPackage.stage.dir" value="${rpm.stage.dir}" />
+      <param name="linuxPackage.res.dir" value="${rpm.res.dir}" />
+      <param name="linuxPackage.extraFilterset" value="rpm.filterset" />
+    </antcall>
+    <antcall target="linuxPackage-prepare-data">
+      <param name="linuxPackage.stage.dir" value="${rpm.stage.dir}" />
+      <param name="linuxPackage.res.dir" value="${rpm.res.dir}" />
+      <param name="linuxPackage.extraFilterset" value="rpm.filterset" />
+      <param name="linuxPackage.packageFormat" value="rpm" />
+    </antcall>
+    <!-- to adhere to naming conventions, version number cannot contain dash -->
+    <!-- http://www.rpm.org/max-rpm/ch-rpm-file-format.html -->
+    <propertyregex property="rpm.version" input="${project.revision}" regexp="-" replace="_" />
+    <property name="rpm.release" value="${linuxPackage.release}" />
+    <antcall target="create-rpm"></antcall>
+  </target>
+
+  <target name="create-rpm">
+    <!-- these tarfilesets can be overridden -->
+    <!-- you can't just include everything in ${rpm.stage.dir}/data without a prefix; rpm will complain that the path 
+         already exists; the prefixes here are paths that are expected to already exist and thus should not be created
+         by this package -->
+    <tarfileset erroronmissingdir="false" prefix="/etc/init.d" dir="${rpm.stage.dir}/data/etc/init.d" id="rpm.tarfileset1" />
+    <tarfileset erroronmissingdir="false" prefix="/opt" dir="${rpm.stage.dir}/data/opt" id="rpm.tarfileset2" />
+    <tarfileset erroronmissingdir="false" prefix="/var/run" dir="${rpm.stage.dir}/data/var/run" id="rpm.tarfileset3" />
+    <tarfileset erroronmissingdir="false" dir="${rpm.stage.dir}/data" includes="doesnotexist" id="rpm.tarfileset4" />
+    <tarfileset erroronmissingdir="false" dir="${rpm.stage.dir}/data" includes="doesnotexist" id="rpm.tarfileset5" />
+    <redline architecture="${rpm.arch}" group="${rpm.group}" name="${rpm.name}" version="${rpm.version}" 
+      postInstallScript="${rpm.stage.dir}/control/postinst" preUninstallScript="${rpm.stage.dir}/control/prerm" 
+      destination="${dist.dir}" summary="${rpm.summary}" release="${rpm.release}">
+      <tarfileset refid="rpm.tarfileset1" />
+      <tarfileset refid="rpm.tarfileset2" />
+      <tarfileset refid="rpm.tarfileset3" />
+      <tarfileset refid="rpm.tarfileset4" />
+      <tarfileset refid="rpm.tarfileset5" />
+    </redline>
+  </target>
+  <!-- =========================================================================================================== -->
+
+  <!--=======================================================================
+      create-pom (override)
+      Creates the POM files for publishing the jar and gwt zip package to the Maven repository
+      ====================================================================-->
+  <target name="create-pom"
+          depends="install-ivy,subfloor.create-pom,create-package-pom"
+          description="Creates a POM file based on the ivy dependencies" />
+
+  <!--=======================================================================
+      create-package-pom 
+      Creates a POM file for the package
+      ====================================================================-->
+  <target name="create-package-pom"
+          depends="install-ivy"
+          description="Creates a POM file based on the ivy dependencies for a separate package">
+    <ivy:makepom ivyfile="${package.artifact.ivyfile}" pomfile="${package.artifact.pomfile}" />
+    <replace file="${package.artifact.pomfile}" token="jar" value="zip" />
+  </target>
+
+  <!--=======================================================================
+      publish-nojar (override)
+      Publishes the jar and zip package to the Maven repository
+      ====================================================================-->
+  <target name="publish-nojar" depends="install-antcontrib,create-pom,ivy.deliver,subfloor.publish-nojar">
+
+    <antcall target="maven-publish-artifact">
+      <param name="publish.pomFile" value="${package.artifact.pomfile}" />
+      <param name="publish.file" value="${dist.dir}/${package.basename}.zip" />
+    </antcall>
+  </target>
+
+  <!--=======================================================================
+      publish-local-nojar (override)
+      Publishes jar and zip package locally
+      ====================================================================-->
+  <target name="publish-local-nojar" depends="install-ivy,subfloor.publish-local-nojar">
+    <ivy:resolve file="${package.artifact.ivyfile}" />
+    <ivy:publish resolver="local" pubrevision="${project.revision}" overwrite="true" forcedeliver="true">
+      <artifacts pattern="${dist.dir}/[artifact]-[revision].[ext]" />
+    </ivy:publish>
+  </target>
+
+</project>
\ No newline at end of file
diff --git a/0.8.1-rc1/tools/pdi_plugin/build-res/subfloor.xml b/0.8.1-rc1/tools/pdi_plugin/build-res/subfloor.xml
new file mode 100644
index 0000000..fa76887
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/build-res/subfloor.xml
@@ -0,0 +1,2026 @@
+<!--===========================================================================
+Copyright (c) 2008-2009, Pentaho Engineering Team
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Pentaho Corporation nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY Pentaho Engineering Team ''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 <copyright holder> 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.
+============================================================================-->
+<!--===========================================================================
+    == SUBFLOOR ==
+    
+    $Date: Wed Nov  6 16:13:57 UTC 2013 $
+    Project Home: https://github.com/pentaho/subfloor/
+    
+    This file contains the default implementation of the ant tasks to 
+    perform a build. This file should be included by the build.xml file 
+    for your particular project. That build file should redefine any task 
+    that is defined in subfloor.xml IF AND ONLY IF the function of the 
+    task needs to be customized.
+    
+    FORMATTING: 
+      ALIGNMENT: indent=2 spaces and wrap lines longer than 120 chars
+      NAMING: targets intended for execution by a user are named single-word
+              or hyphenated.  Internal targets use '.' notation.
+    
+    TO GET STARTED with your project, you will need this file in 
+          your project's root directory along with three additional files:
+          1. build.xml 
+          2. build.properties
+          3. ivy_settings.xml
+          4. ivy.xml
+          
+          Below are some templates:
+          
+      === build.xml
+    <project name="MyProject" basedir="." default="jar" xmlns:ivy="antlib:org.apache.ivy.ant" >
+      <description>
+        This build file is used to create the MyProject project and works with the subfloor.xml file.
+      </description>
+
+      <import file="subfloor.xml"/>
+    </project>
+  
+    === build.properties
+    project.revision=1.0-SNAPSHOT  #the version of your project.  This will appear in jar META-INF, dist artifact filenames and IVY revision metadata. 
+    ivy.artifact.id=my-project   #IVY metadata describing the name of the artifact
+    impl.title=My Project #English language version of your project name
+    
+============================================================================-->
+
+
+<project name="subfloor" basedir="." default="default" xmlns:ivy="antlib:org.apache.ivy.ant">
+  <description>
+-------------------------------------------------------------------------------
+     subfloor.xml provides tasks needed to perform a project build. 
+     It is typically not used directly but imported by each project's build.xml
+     file.  The build.xml file can override tasks when customization is required. 
+      
+MAIN TARGETS
+============
+  * clean / clean-all : 
+    remove all artifacts of the build, clean-all adds the removal
+    of any library or jar dependencies downloaded as part of the build
+    
+  * resolve :
+    download/refresh library or jar dependencies needed for the build (uses Apache IVY)
+    
+  * compile :
+    run javac on the project's source
+    
+  * jar :
+    creates a jar file
+    
+  * dist :
+    creates all project distributables
+    
+  * test :
+    runs JUnit tests from your project's test source
+    
+SPECIAL TARGETS
+============
+  * publish-local :
+    builds a jar for your project and registers it with the local artifact repository isolated 
+    to your machine at $HOME/.ivy2/local.  Further executions of the the resolve target by this
+    or other projects will find your published jar.
+    
+  * ivy-clean* :
+    this family of targets helps reset your IVY environment in the event that you are having
+    difficulty resolving dependencies
+    
+TYPICAL TARGET SEQUENCE
+============    
+  * clean-all resolve dist :
+    a good start to build all project distributables from scratch.  Note that jar dependencies
+    will not be downloaded unless you explicitly run the resolve target.  We made the resolution
+    and retrieval completely discretionary since there are many situations in which
+    you will not want to get or refresh dependencies, e.g. if you are offline with no Internet
+    access.  In such case, you could just run "dist" if the set of jars you already have are 
+    sufficient.
+    
+  </description>
+
+  <!-- Load the properties files in the proper order -->
+  <property file="override.properties"
+            description="Properties customized for your development environment belong in this file.  This file will never be checked into the SCM." />
+  <property file="build.properties"
+            description="Properties customized for your particular project belong in this file." />
+
+  <!-- =================================================================================
+       Property Defaults
+       Any of these properties can be overridden in either build.properties or override.properties
+       =================================================================================-->
+
+  <!-- Project meta properties -->
+  <property name="impl.vendor" value="Pentaho Corporation" description="Jar file metadata describing the jar's vendor" />
+  <property name="impl.productID"
+            value=""
+            description="Jar file metadata indicating the product ID (this is not the revision)" />
+
+  <!-- Compile properties -->
+  <property name="src.dir" value="${basedir}/src" description="Project source code directory" />
+  <property name="bin.dir" value="${basedir}/bin" description="Base directory for all non-dist build output" />
+  <property name="classes.dir"
+            value="${bin.dir}/classes"
+            description="Classes compiled from project source code are placed here" />
+  <property name="lib.dir"
+            value="${basedir}/lib"
+            description="Directory that hosts Jar files required to compile project source.  (IVY will populate this directory with required jars)" />
+  <property name="devlib.dir"
+            value="${basedir}/dev-lib"
+            description="Directory for developer to place development Jar files (not affected by clean targets)" />
+
+  <!-- Compiler properties (passed directly to javac ant target) -->
+  <property name="javac.debug"
+            value="true"
+            description="Indicates whether source should be compiled with debug information (passed to javac ant task)." />
+  <property name="javac.deprecation"
+            value="true"
+            description="Indicates whether source should be compiled with deprecation information" />
+  <property name="javac.source" value="6" description="Provide source compatibility with specified release" />
+  <property name="javac.target" value="6" description="Generate class files for specific VM version" />
+  <property name="javac.maxmemory" value="256M" description="Max memory alloted to java compile" />
+  <property name="javac.xlint" value="-Xlint:all" />
+
+  <!-- Third party Ant tasks and tools properties -->
+  <property name="subfloor.resources.dir"
+            value="${user.home}/.subfloor"
+            description="Base dir for runtime jars that are required exclusively by the build process" />
+  <property name="subfloor.tmp.dir"
+            value="${subfloor.resources.dir}/tmp"
+            description="Temporary space where files are prepared for installation" />
+  <property name="antcontrib.build.cache.dir"
+            value="${subfloor.resources.dir}/ant-contrib"
+            description="Directory where the Ant-Contrib jar (and dependencies) is placed after it is auto-downloaded by the build" />
+  <property name="svnant.use-javahl"
+            value="false"
+            description="Prefer JNI JavaHL binding over the command line client for native svn support" />
+  <property name="svnant.use-svnkit"
+            value="true"
+            description="Prefer SVNKit binding over the command line client for native svn support (defaults to true)" />
+  <property name="ivy.url"
+            value="http://repo2.maven.org/maven2/org/apache/ivy/ivy/2.2.0/ivy-2.2.0.jar"
+            description="The URL to the current release of Apache IVY" />
+	
+  <!-- Enunciate properties -->
+  <property name="enunciate.home" value="${basedir}/enunciate" />
+  <property name="enunciate.bin.dir" value="${bin.dir}/enunciate" />
+
+
+  <!-- Test properties -->
+  <property name="junit.base.dir" value="${basedir}" description="Directory in which the junit test VM will be invoked" />
+  <property name="testsrc.dir" value="${basedir}/test-src" description="Directory that hosts the test source files" />
+  <property name="testlib.dir"
+            value="${basedir}/test-lib"
+            description="Directory for jar files needed during unit testing" />
+  <property name="testbin.dir"
+            value="${bin.dir}/test"
+            description="Base directory for all compiler generated test output" />
+  <property name="testclasses.dir"
+            value="${testbin.dir}/classes"
+            description="Classes compiled from project test code are placed here" />
+  <property name="testreports.dir"
+            value="${bin.dir}/reports/test"
+            description="Base directory that holds all unit test report files" />
+  <property name="testreports.xml.dir"
+            value="${testreports.dir}/xml"
+            description="Unit test xml reports are placed here" />
+  <property name="testreports.html.dir"
+            value="${testreports.dir}/html"
+            description="Unit test html reports are placed here" />
+  <property name="junit.haltonfailure" value="no" description="Fail the build if a test fails" />
+  <property name="junit.haltonerror" value="no" description="Fail the build if a error occurs" />
+  <property name="junit.maxmemory" value="256M" description="Heap size when Junit is run in fork mode" />
+  <property name="junit.forkmode" 
+            value="perTest" 
+            description="Defines whether JUnit forks a new JVM for each test. Use 'once' for faster test runs, and 'perTest' for complete tests."/>
+  <property name="headless.unittest" value="true" description="Runs the unit tests in headless mode" />
+
+  <!-- Code Coverage properties -->
+  <property name="instrumented.classes.dir"
+            value="${testbin.dir}/instrumented-classes"
+            description="Directory where instrumented project classes are placed for use by code coverage utility" />
+  <property name="cobertura.version"
+            value="1.9.4.1"
+            description="The version of cobertura to use for code coverage" />
+  <property name="cobertura.data.dir"
+            value="${testbin.dir}/cobertura-bin"
+            description="Temporary data directory used by Cobertura" />
+  <property name="coberturareports.dir"
+            value="${bin.dir}/reports/cobertura"
+            description="Base directory for all generated Cobertura code coverage reports" />
+  <property name="coberturareports.xml.dir"
+            value="${coberturareports.dir}/xml"
+            description="Cobertura xml reports are placed here" />
+  <property name="coberturareports.html.dir"
+            value="${coberturareports.dir}/html"
+            description="Cobertura html reports are placed here" />
+
+  <!-- Javadoc properties -->
+  <property name="javadoc.dir"
+            value="${bin.dir}/javadoc"
+            description="Directory where generated javadoc will be placed" />
+  <property name="javadoc.packagenames"
+            value="org.mypackagename.*"
+            description="This property is passed to the packagenames property of the javadoc ant task.  You should customize this for your project." />
+  <property name="javadoc.zip.filename" value="${ivy.artifact.id}-${project.revision}-javadoc.zip" />
+  <property name="javadoc.tar.filename" value="${ivy.artifact.id}-${project.revision}-javadoc.tar.gz" />
+
+  <!-- Distribution and Assembly properties -->
+  <property name="dist.dir"
+            value="${basedir}/dist"
+            description="Base directory for all project artifacts (jar, zip, tar.gz, etc...)" />
+  <property name="license.dir"
+            value="${basedir}"
+            description="Base directory where this project's license files reside" />
+  <property name="res.dir"
+            value="${basedir}/res"
+            description="Directory that holds resources not included in the source tree" />
+  <property name="source.zip.filename" value="${ivy.artifact.id}-${project.revision}-sources.zip" />
+  <property name="source.tar.filename" value="${ivy.artifact.id}-${project.revision}-sources.tar.gz" />
+  <property name="source.publish" value="true" />
+  
+  <!-- Ivy properties -->
+  <property name="ivy.settingsurl"
+            value="file:${basedir}/ivysettings.xml"
+            description="URL to the (common) ivysettings.xml.  This file is required by the build to configure IVY.  Note you must escape the ':' if this property exists in a .properties file" />
+  <property name="ivyfile"
+            value="ivy.xml"
+            description="The name of the IVY xml file defining your project's dependencies" />
+  <property name="ivy.artifact.group"
+            value="mycompanyname"
+            description="IVY metadata describing the originating company or organization" />
+  <property name="ivy.artifact.pomfile"
+            value="${dist.dir}/pom.xml"
+            description="The path to the Maven pom file to deploy with the artifact" />
+  <property name="ivy.artifact.ivyfilename"
+            value="ivy.xml"
+            description="The name of the IVY xml file to deploy with the artifact" />
+  <property name="ivy.artifact.ivypathname"
+            value="${dist.dir}/ivy.xml"
+            description="The full path to the IVY xml file to deploy with the artifact" />
+  <property name="ivy.reports.dir"
+            value="${bin.dir}/reports/ivy"
+            description="Base directory that holds all IVY dependency report files" />
+  <property name="ivy.configs" value="*" description="Set of configs used for IVY reporting and checking operations" />
+  <property name="ivy.use.symlinks" value="true" description="Flag indicating if Ivy should create symlinks when retrieving artifacts."/>
+
+  <!-- Tattletale properties -->
+  <property name="tattletale.url"
+            value="http://repo.pentaho.org/artifactory/repo/jboss/tattletale/1.1.2.Final/tattletale-1.1.2.Final.zip"
+            description="The URL from which to download tattletale" />
+  <property name="tattletale.classname"
+            value="org.jboss.tattletale.ant.ReportTask"
+            description="The name of the class which will run the tattletale reports" />
+  <property name="tattletale.reports.dir"
+            value="${bin.dir}/reports/tattletale"
+            description="Base directory that holds the output of the tattletale reports" />
+  <property name="tattletale.configfile"
+            value=""
+            description="The configuration file for the tattletale report" />
+
+  <!-- Sonar properties -->
+  <property name="sonar.url"
+            value="http://repo1.maven.org/maven2/org/codehaus/sonar-plugins/sonar-ant-task/1.2/sonar-ant-task-1.2.jar"/>
+  <property name="sonar.classname"
+          value="org.sonar.ant.SonarTask"/>
+
+  <!-- Load the manifest file (if any) as a properties file -->
+  <property name="dist.manifest.file"
+            value="${dist.dir}/MANIFEST.MF"
+            description="The manifest file that will be generated as part of the build" />
+  <property name="manifest.file"
+            value="${res.dir}/META-INF/MANIFEST.MF"
+            description="The location of the MANIFEST.MF file for this application." />
+  <property file="${manifest.file}"
+            description="Loads the manifest information from the manifest file as a properties file." />
+
+  <!-- Set the project revision number to the value in the manifest file (if it has not
+       been specified in the properties file -->
+  <property name="project.revision"
+            value="${Implementation-Version}"
+            description="Sets the version number of the project based on the Implementation-Version found in the manifest file (if one is supplied and nothing is specified in the build.properties)" />
+  <fail message="A project revision number has not been determined!">
+    <condition>
+      <matches string="${project.revision}" pattern="\$\{.*\}" />
+    </condition>
+  </fail>
+
+  <!-- Set the project title to the value in the manifest file (if it has not
+       been specified in the properties file -->
+  <property name="impl.title"
+            value="${Implementation-Title}"
+            description="Sets the title of the project based on the Implementation-Title found in the manifest file (if one is supplied and nothing is specified in the build.properties)" />
+  <fail message="A project title has not been determined!">
+    <condition>
+      <matches string="${impl.title}" pattern="\$\{.*\}" />
+    </condition>
+  </fail>
+
+  <!-- Build Mode properties -->
+  <property name="release" value="false" description="Set this to true if you want to generate a release artifact" />
+
+  <!-- Ivy should only use symlinks if we're not in release mode -->
+  <condition property="ivy.use.symlinks.internal">
+    <and>
+      <isfalse value="${release}"/>
+      <istrue value="${ivy.use.symlinks}"/>
+    </and>
+  </condition>
+
+  <!-- Set the os property -->
+  <condition property="isLinux">
+    <os family="unix" />
+  </condition>
+  <condition property="isWindows">
+    <os family="windows" />
+  </condition>
+  <condition property="isMac">
+    <os family="mac" />
+  </condition>
+
+  <condition property="os.classifier" value="win">
+    <os family="windows" />
+  </condition>
+  <condition property="os.classifier" value="mac">
+    <os family="mac" />
+  </condition>
+  <condition property="os.classifier" value="linux">
+    <os family="unix" />
+  </condition>
+  <property name="os.classifier" value="unsupported" />
+
+  <!-- Setup the compile classpath -->
+  <path id="classpath">
+    <fileset dir="${devlib.dir}">
+      <include name="**/*.jar" />
+    </fileset>
+    <fileset dir="${lib.dir}">
+      <include name="**/*.jar" />
+    </fileset>
+  </path>
+
+  <!-- Setup the classpath used for testing -->
+  <path id="test.classpath">
+    <pathelement path="${testclasses.dir}" />
+    <pathelement path="${classes.dir}" />
+    <fileset dir="${devlib.dir}">
+      <include name="**/*.jar" />
+    </fileset>
+    <fileset dir="${testlib.dir}">
+      <include name="**/*.jar" />
+    </fileset>
+    <fileset dir="${lib.dir}">
+      <include name="**/*.jar" />
+    </fileset>
+  </path>
+
+
+  <!--=======================================================================
+      default
+      
+      The target that is run if no target is given
+      ====================================================================-->
+  <target name="default" depends="build" />
+
+
+  <!--=======================================================================
+      build
+      
+      Runs a typical build process to create the project locally
+      ====================================================================-->
+  <target name="build" depends="clean-all,resolve,cobertura,dist-source,dist" />
+
+
+  <!--=======================================================================
+      build-testless
+      
+      Runs a typical build process to create the project locally (no testing)
+      ====================================================================-->
+  <target name="build-testless" depends="clean-all,resolve,dist-source,dist" />
+
+
+  <!--=======================================================================
+      continuous
+      
+      Runs a typical continuous integration build including project dist,
+      test, and coverage artifacts
+      ====================================================================-->
+  <target name="continuous" depends="build,publish" />
+
+
+  <!--=======================================================================
+      continuous-testless
+      
+      Runs a typical continuous integration build including project dist,
+      and coverage artifacts
+      ====================================================================-->
+  <target name="continuous-testless" depends="build-testless,publish" />
+
+
+  <!--=======================================================================
+      install-antcontrib
+      
+      (Fetches and) installs ant-contrib tasks.
+      ====================================================================-->
+  <target name="install-antcontrib" depends="antcontrib.download-check">
+    <taskdef resource="net/sf/antcontrib/antlib.xml">
+      <classpath>
+        <fileset dir="${antcontrib.build.cache.dir}">
+          <include name="*.jar" />
+        </fileset>
+      </classpath>
+    </taskdef>
+  </target>
+
+
+  <!--=======================================================================
+      antcontrib.download-check
+      
+      Fetches ant-contrib from sourceforge if it is not already present
+      ====================================================================-->
+  <target name="antcontrib.download-check">
+    <condition property="antcontrib.available">
+      <and>
+        <available file="${antcontrib.build.cache.dir}" />
+        <available classname="net.sf.antcontrib.logic.IfTask">
+          <classpath>
+            <fileset dir="${antcontrib.build.cache.dir}">
+              <include name="*.jar" />
+            </fileset>
+          </classpath>
+        </available>
+      </and>
+    </condition>
+    <antcall target="antcontrib.download" />
+  </target>
+
+
+  <!--=======================================================================
+      antcontrib.download
+      
+      Fetches ant-contrib from sourceforge
+      ====================================================================-->
+  <target name="antcontrib.download" unless="antcontrib.available">
+    <mkdir dir="${subfloor.tmp.dir}" />
+    <get src="http://downloads.sourceforge.net/ant-contrib/ant-contrib-1.0b3-bin.zip"
+         dest="${subfloor.tmp.dir}/antcontrib.zip"
+         usetimestamp="true" />
+    <unzip src="${subfloor.tmp.dir}/antcontrib.zip" dest="${subfloor.tmp.dir}">
+      <patternset>
+        <include name="**/*.jar" />
+      </patternset>
+    </unzip>
+    <copy todir="${antcontrib.build.cache.dir}">
+      <fileset dir="${subfloor.tmp.dir}/ant-contrib">
+        <include name="**/*.jar" />
+      </fileset>
+    </copy>
+  </target>
+
+
+  <!--=======================================================================
+      init
+      
+      Ensures that all the required directories exist before processing
+      a build.
+      ====================================================================-->
+  <target name="init">
+    <mkdir dir="${classes.dir}" />
+    <mkdir dir="${dist.dir}" />
+    <mkdir dir="${lib.dir}" />
+    <mkdir dir="${devlib.dir}" />
+    <mkdir dir="${testlib.dir}" />
+  </target>
+
+
+  <!--=======================================================================
+    install-svnant
+    
+    (Fetches and) installs the SVN ANT for use by this ant script
+    ====================================================================-->
+  <target name="install-svnant" depends="install-ivy">
+    <if>
+      <istrue value="${svnant.isinstalled}" />
+      <then>
+        <echo message="Skipping SVN ANT install.  SVN ANT has already been configured by the build" />
+      </then>
+      <else>
+        <taskdef-with-ivy organisation="tigris"
+                          module="svnant"
+                          revision="1.3.0"
+                          resource="org/tigris/subversion/svnant/svnantlib.xml"
+                          classname="org.tigris.subversion.svnant.SvnTask" />
+        <property name="svnant.isinstalled" value="true" />
+      </else>
+    </if>
+  </target>
+
+
+  <!--=======================================================================
+        test-svnant
+    
+        Tests SVN by printing out the repository
+        ====================================================================-->
+  <target name="test-svnant" depends="install-svnant">
+    <svn javahl="${svnant.use-javahl}" svnkit="${svnant.use-svnkit}">
+      <wcVersion path="." />
+    </svn>
+    <echo message="Subversion repository url: ${repository.url}" />
+  </target>
+
+
+  <!--=======================================================================
+        svn-revision
+    
+        Prints and sets the SVN revision for the repository at the current dir (if svn.revision is not set)
+        ====================================================================-->
+  <target name="svn-revision" depends="install-svnant">
+
+    <svn javahl="${svnant.use-javahl}" svnkit="${svnant.use-svnkit}">
+      <status path="." revisionProperty="svn.revision" />
+    </svn>
+    <echo message="Subversion repository revision: ${svn.revision}" />
+  </target>
+
+
+  <!--=======================================================================
+        set-build.id
+    
+        Sets a property build.id to the either "development" or the svn revision
+        if in release mode
+        ====================================================================-->
+  <target name="set-build.id" unless="build.id" depends="install-antcontrib">
+    <if>
+      <istrue value="${release}" />
+      <then>
+        <antcallback target="svn-revision" return="svn.revision" />
+        <property name="build.id" value="${svn.revision}" />
+      </then>
+      <else>
+        <property name="build.id" value="development" />
+      </else>
+    </if>
+  </target>
+
+  <!--=================================================================================
+       version-properties: common Ant driven version file generation.  Projects that produce
+       a package or packages should run this target.  Projects that produce
+       jars only should NOT.
+   ===================================================================================-->
+  <target name="version-properties" depends="set-build.id">
+    <tstamp>
+      <format property="build.time" pattern="yyyy/MM/dd hh:mm aa" />
+    </tstamp>
+    <propertyfile file="version.properties" comment="Release Build version info">
+      <entry key="release.major.number" value="${release.major.number}" />
+      <entry key="release.minor.number" value="${release.minor.number}" />
+      <entry key="release.milestone.number" value="${release.milestone.number}" />
+      <entry key="release.candidate.token" value="${release.candidate.token}" />
+      <entry key="impl.vendor" value="${impl.vendor}" />
+      <entry key="impl.version"
+             value="${release.major.number}.${release.minor.number}.${release.milestone.number}.${build.id}" />
+      <entry key="impl.title" value="${impl.title}" />
+      <entry key="buildDate" value="${build.time}" />
+      <entry key="svn.revision" value="${build.id}" />
+      <entry key="release.build.number" default="0" type="int" operation="+" value="1" pattern="0000" />
+    </propertyfile>
+    <property file="${basedir}/version.properties" />
+  </target>
+
+
+  <!--=======================================================================
+      install-ivy 
+      
+      Fetches and installs IVY ant tasks if not already installed 
+      ====================================================================-->
+  <target name="install-ivy" depends="install-antcontrib">
+    <if>
+      <istrue value="${ivy.isinstalled}" />
+      <then>
+        <echo message="Skipping IVY install.  IVY has already been configured by the build" />
+      </then>
+      <else>
+        <download-antlib name="ivy" url="${ivy.url}" classname="org.apache.ivy.ant.IvyTask" extension="jar" />
+        <taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant">
+          <classpath>
+            <fileset dir="${subfloor.resources.dir}/ivy">
+              <include name="*.jar" />
+            </fileset>
+          </classpath>
+        </taskdef>
+        <ivy:settings url="${ivy.settingsurl}" />
+        <property name="ivy.isinstalled" value="true" />
+      </else>
+    </if>
+  </target>
+
+
+  <!--=======================================================================
+      ivy.check-releasable
+      
+      Verifies that there are no SNAPSHOT dependencies defined in the ivy xml.
+      If there are SNAPSHOTS, fail the release build.
+      ====================================================================-->
+  <target name="ivy.check-releasable" depends="install-ivy, install-antcontrib">
+    <if>
+      <istrue value="${release}" />
+      <then>
+        <sequential>
+          <ivy:artifactproperty conf="${ivy.configs}" name="dep.[module]/[artifact]-[revision]" value="[revision]" />
+
+          <propertyselector property="violators" match="dep\..*SNAPSHOT.*" select="\0" casesensitive="false" />
+
+          <fail if="violators"
+                message="Release not possible, you have dependencies on non-released artifacts: ${violators}" />
+        </sequential>
+      </then>
+    </if>
+  </target>
+
+
+  <!--=======================================================================
+      resolve
+      
+      Using ivy and the dependencies for the project (defined in the ivy.xml
+      file), this task will retrieve the needed files and place them into 
+      the defined directories.
+      ====================================================================-->
+  <target name="resolve"
+          depends="resolve-default, resolve-test, ivy.check-releasable"
+          description="Retrieves all the dependent libraries" />
+
+  <target name="resolve-init" unless="resolve-init.skip" depends="install-ivy">
+    <!-- If this is the 1st time through resolve-init, then we need to clean up the jars
+-->
+    <antcall target="clean-jars" />
+    <property name="resolve-init.skip" value="" />
+  </target>
+
+  <target name="resolve-default" depends="resolve-default.default,resolve-default.composite"/>
+
+  <!-- 
+  This target resolves the default IVY configuration as a composite of child configurations.
+  You should set ivy.default.sub-configs in your build.properties only if you want your default
+  configuration to be treated as a composite of two or more child configurations.
+  To turn this on, set ivy.default.sub-configs property in your build.properties, e.g.
+  ivy.default.sub-configs=external,internal
+  Note: the parent config "default" proper will not be resolved
+  -->
+  <target name="resolve-default.composite" depends="install-antcontrib,resolve-init" if="ivy.default.sub-configs">
+    <for list="${ivy.default.sub-configs}" param="conf">
+      <sequential>
+        <ivy:resolve file="${ivyfile}" conf="default_@{conf}" />
+        <ivy:retrieve conf="default_@{conf}" pattern="${lib.dir}/@{conf}/[module]-[revision](-[classifier]).[ext]" symlink="${ivy.use.symlinks.internal}" />
+      </sequential>
+    </for>
+  </target>
+
+  <target name="resolve-default.default" depends="resolve-init" unless="ivy.default.sub-configs">
+    <ivy:resolve file="${ivyfile}" conf="default" />
+    <ivy:retrieve conf="default" pattern="${lib.dir}/[module]-[revision](-[classifier]).[ext]" symlink="${ivy.use.symlinks.internal}" />
+  </target>
+
+  <target name="resolve-test" depends="resolve-init">
+    <ivy:resolve file="${ivyfile}" conf="test" />
+    <ivy:retrieve conf="test" pattern="${testlib.dir}/[module]-[revision](-[classifier]).[ext]" symlink="${ivy.use.symlinks.internal}" />
+  </target>
+
+  <target name="resolve-enunciate" depends="resolve-init">
+    <ivy:resolve file="${ivyfile}" conf="enunciate" />
+    <ivy:retrieve conf="enunciate" pattern="${basedir}/enunciate/lib/[module]-[revision](-[classifier]).[ext]" />
+  </target>
+
+  <target name="resolve-codegen" depends="resolve-init">
+    <ivy:resolve file="${ivyfile}" conf="codegen" />
+    <ivy:retrieve conf="codegen" pattern="${lib.dir}/[module]-[revision](-[classifier]).[ext]" symlink="${ivy.use.symlinks.internal}" />
+  </target>
+
+  <target name="resolve-runtime" depends="resolve-init">
+    <ivy:resolve file="${ivyfile}" conf="runtime" />
+    <ivy:retrieve conf="runtime" pattern="${lib.dir}/[module]-[revision](-[classifier]).[ext]" symlink="${ivy.use.symlinks.internal}" />
+  </target>
+
+
+  <!--=======================================================================
+      ivy-clean-cache
+      
+      Cleans the IVY cache.  You are erasing IVY's memory.  Run this if you 
+      want to force IVY to go fetch all your project dependencies from scratch.
+      WARNING: this will affect all IVY projects, not just the current workspace
+      ====================================================================-->
+  <target name="ivy-clean-cache" depends="install-ivy">
+    <ivy:cleancache />
+  </target>
+
+
+  <!--=======================================================================
+      ivy-clean-local
+      
+      Completely cleans your local repository of any files published locally
+      by way of publish-local.
+      WARNING: this is a global action and will affect other IVY projects
+      currently referencing a locally published dependency
+      ====================================================================-->
+  <target name="ivy-clean-local" depends="install-ivy">
+    <delete dir="${ivy.local.default.root}/" />
+  </target>
+
+
+  <!--=======================================================================
+      ivy-clean-by-name
+      
+      Cleans your IVY cache and local repository of specific files.
+      WARNING: this is a global action and will affect other IVY projects
+      currently referencing a locally published dependency
+      ====================================================================-->
+  <target name="ivy-clean-pentaho" depends="install-ivy">
+    <mkdir dir="${ivy.local.default.root}" />
+    <!-- just in case it doesn't exist -->
+    <for param="dir">
+      <path>
+        <dirset dir="${ivy.local.default.root}" includes="*${ivy.clean.pattern}*" />
+        <dirset dir="${ivy.default.ivy.user.dir}/cache" includes="*${ivy.clean.pattern}*" />
+      </path>
+      <sequential>
+        <delete dir="@{dir}" includeemptydirs="true" />
+      </sequential>
+    </for>
+    <for param="file">
+      <path>
+        <fileset dir="${ivy.local.default.root}" includes="*${ivy.clean.pattern}*" />
+        <fileset dir="${ivy.default.ivy.user.dir}/cache" includes="*${ivy.clean.pattern}*" />
+      </path>
+      <sequential>
+        <delete file="@{file}" />
+      </sequential>
+    </for>
+  </target>
+
+
+  <!--=======================================================================
+      ivy-report
+      
+      Generates an IVY dependency report for this project. 
+      ====================================================================-->
+  <target name="ivy-report" depends="install-ivy">
+    <ivy:resolve file="${ivyfile}" conf="${ivy.configs}" />
+    <ivy:report xml="true" todir="${ivy.reports.dir}" />
+  </target>
+
+
+  <!--=======================================================================
+      publish-local-nojar
+      
+      Publishes the jar file for this project to the user's local repository
+      for download by other projects currently being executed on the user's
+      system.
+      ====================================================================-->
+  <target name="publish-local-nojar" depends="install-ivy,publish-local-nojar.internal">
+    <if>
+      <equals arg1="${tests.publish}" arg2="true" />
+      <then>
+        <antcall target="publish-local-nojar.internal">
+          <param name="ivy.artifact.id" value="${ivy.artifact.id}-test"/>
+        </antcall>
+      </then>
+    </if>
+    <antcall target="publish-local-nojar.post"/>
+  </target>
+
+  <!--=======================================================================
+      publish-local-nojar.post this target is invoked after the normal set of publish-local-nojar
+      is completed, override this to perform additional publishing in extensions of subfloor, etc
+      ====================================================================-->
+  <target name="publish-local-nojar.post">
+  </target>
+  
+  <target name="publish-local-nojar.internal" depends="install-ivy">
+    <ivy:resolve file="${ivy.artifact.ivyfilename}" />
+    <ivy:publish resolver="local" pubrevision="${project.revision}" overwrite="true" forcedeliver="true" warnonmissing="yes" haltonmissing="no">
+      <artifacts pattern="${dist.dir}/[artifact]-[revision](-[classifier]).[ext]" />
+    </ivy:publish>
+  </target>
+
+  <!--=======================================================================
+      publish-local
+      
+      Builds and publishes the jar file for this project to the user's 
+      local repository for download by other projects currently being 
+      executed on the user's system.
+      ====================================================================-->
+  <target name="publish-local"
+          depends="dist, dist-source, publish-local-nojar"
+          description="Builds and publishes the jar file to the local repository" />
+
+
+  <!--=======================================================================
+        publish
+    
+        Creates and publishes the jar file for this project to a Maven2 
+        repository. 
+        ====================================================================-->
+  <target name="publish" depends="dist, dist-source, publish-nojar">
+  </target>
+
+
+  <!--=======================================================================
+      publish-nojar
+      
+      Publishes the jar file for this project to a Maven2 repository.
+      ====================================================================-->
+  <target name="publish-nojar" depends="install-antcontrib,create-pom,ivy.deliver,publish-nojar.internal">
+    <if>
+      <equals arg1="${tests.publish}" arg2="true" />
+      <then>
+        <antcall target="publish-nojar.internal">
+          <param name="ivy.artifact.id" value="${ivy.artifact.id}-test"/>
+        </antcall>
+      </then>
+    </if>
+  </target>
+
+  <target name="publish-nojar.internal" depends="install-antcontrib,create-pom,ivy.deliver">
+    <antcall target="maven-publish-dependencies">
+      <param name="publish.groupId" value="${ivy.artifact.group}" />
+      <param name="publish.artifactId" value="${ivy.artifact.id}" />
+      <param name="publish.version" value="${project.revision}" />
+      <param name="publish.file" value="${ivy.artifact.ivypathname}" />
+    </antcall>
+
+    <if>
+      <equals arg1="${source.publish}" arg2="true" />
+        <then>
+          <antcall target="maven-publish-sources">
+            <param name="publish.groupId" value="${ivy.artifact.group}" />
+            <param name="publish.artifactId" value="${ivy.artifact.id}" />
+            <param name="publish.version" value="${project.revision}" />
+            <param name="publish.file" value="${dist.dir}/${ivy.artifact.id}-${project.revision}-sources.jar" />
+          </antcall>
+        </then>
+    </if>
+
+    <antcall target="maven-publish-artifact">
+      <param name="publish.pomFile" value="${ivy.artifact.pomfile}" />
+      <param name="publish.file" value="${dist.dir}/${ivy.artifact.id}-${project.revision}.jar" />
+    </antcall>
+
+    <antcall target="maven-publish.post"/>
+    
+  </target>
+
+  <!-- Override this if anything is needed to be done after the standard parts of publish are completed -->
+  <!-- Such as:  publishing non-standard/extended artifacts, etc -->
+  <target name="maven-publish.post"/>
+  
+  <!--=======================================================================
+        ivy.deliver
+    
+        Creates a publishable version of the ivy dependencies file, ivy.xml
+        ====================================================================-->
+  <target name="ivy.deliver" depends="resolve">
+    <ivy:deliver conf="*(public)" deliverpattern="${dist.dir}/ivy.xml" />
+  </target>
+
+
+  <!--=======================================================================
+      maven-publish-dependencies
+      
+      A function that deploys an ivy.xml file to a maven repository
+      ====================================================================-->
+  <target name="maven-publish-dependencies" depends="install-antcontrib">
+    <sequential>
+      <fail message="No file found at: ${publish.file}">
+        <condition>
+          <not>
+            <available file="${publish.file}" />
+          </not>
+        </condition>
+      </fail>
+      <echo message="Publishing ${publish.file} to ${ivy.repository.publish}..." />
+      <if>
+        <isset property="isWindows" />
+        <then>
+          <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="deploy:deploy-file" />
+            <arg value="-DrepositoryId=${ivy.repository.id}" />
+            <arg value="-Durl=${ivy.repository.publish}" />
+            <arg value="-DgroupId=${publish.groupId}" />
+            <arg value="-DartifactId=${publish.artifactId}" />
+            <arg value="-Dversion=${publish.version}" />
+            <arg value="-Dpackaging=ivy.xml" />
+            <arg value="-Dfile=${publish.file}" />
+          </exec>
+        </then>
+        <else>
+          <exec executable="mvn" failonerror="true">
+            <arg value="deploy:deploy-file" />
+            <arg value="-DrepositoryId=${ivy.repository.id}" />
+            <arg value="-Durl=${ivy.repository.publish}" />
+            <arg value="-DgroupId=${publish.groupId}" />
+            <arg value="-DartifactId=${publish.artifactId}" />
+            <arg value="-Dversion=${publish.version}" />
+            <arg value="-Dpackaging=ivy.xml" />
+            <arg value="-Dfile=${publish.file}" />
+            <arg value="-e" />
+          </exec>
+        </else>
+      </if>
+    </sequential>
+  </target>
+
+
+  <!--=======================================================================
+      maven-publish-artifact
+      
+      A function that deploys an artifact to a maven repository
+      ====================================================================-->
+  <target name="maven-publish-artifact" depends="install-antcontrib">
+    <sequential>
+      <fail message="No file found at: ${publish.file}">
+        <condition>
+          <not>
+            <available file="${publish.file}" />
+          </not>
+        </condition>
+      </fail>
+      <echo message="Publishing ${publish.file} to ${ivy.repository.publish}..." />
+      <if>
+        <isset property="isWindows" />
+        <then>
+          <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="deploy:deploy-file" />
+            <arg value="-DrepositoryId=${ivy.repository.id}" />
+            <arg value="-Durl=${ivy.repository.publish}" />
+            <arg value="-DpomFile=${publish.pomFile}" />
+            <arg value="-Dfile=${publish.file}" />
+          </exec>
+        </then>
+        <else>
+          <exec executable="mvn" failonerror="true">
+            <arg value="deploy:deploy-file" />
+            <arg value="-DrepositoryId=${ivy.repository.id}" />
+            <arg value="-Durl=${ivy.repository.publish}" />
+            <arg value="-DpomFile=${publish.pomFile}" />
+            <arg value="-Dfile=${publish.file}" />
+          </exec>
+        </else>
+      </if>
+    </sequential>
+  </target>
+
+
+  <!--=======================================================================
+      maven-publish-sources
+      
+      A function that deploys a java-sources artifact to a maven repository
+      ====================================================================-->
+  <target name="maven-publish-sources" depends="install-antcontrib">
+    <sequential>
+      <fail message="No file found at: ${publish.file}">
+        <condition>
+          <not>
+            <available file="${publish.file}" />
+          </not>
+        </condition>
+      </fail>
+      <echo message="Publishing ${publish.file} to ${ivy.repository.publish}..." />
+      <if>
+        <isset property="isWindows" />
+        <then>
+          <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="deploy:deploy-file" />
+            <arg value="-DrepositoryId=${ivy.repository.id}" />
+            <arg value="-Durl=${ivy.repository.publish}" />
+            <arg value="-DgroupId=${publish.groupId}" />
+            <arg value="-DartifactId=${publish.artifactId}" />
+            <arg value="-Dversion=${publish.version}" />
+            <arg value="-DgeneratePom=true" />
+            <arg value="-Dpackaging=java-source" />
+            <arg value="-Dfile=${publish.file}" />
+          </exec>
+        </then>
+        <else>
+          <exec executable="mvn" failonerror="true">
+            <arg value="deploy:deploy-file" />
+            <arg value="-DrepositoryId=${ivy.repository.id}" />
+            <arg value="-Durl=${ivy.repository.publish}" />
+            <arg value="-DgroupId=${publish.groupId}" />
+            <arg value="-DartifactId=${publish.artifactId}" />
+            <arg value="-Dversion=${publish.version}" />
+            <arg value="-DgeneratePom=true" />
+            <arg value="-Dpackaging=java-source" />
+            <arg value="-Dfile=${publish.file}" />
+          </exec>
+        </else>
+      </if>
+    </sequential>
+  </target>
+
+
+  <!--=======================================================================
+      create-pom
+      
+      Creates the POM file for publishing the jar file to a Maven2 repository.
+      ====================================================================-->
+  <target name="create-pom" depends="install-ivy">
+    <ivy:makepom ivyfile="${ivyfile}" pomfile="${dist.dir}/pom.xml">
+      <mapping conf="default" scope="compile" />
+      <mapping conf="runtime" scope="runtime" />
+    </ivy:makepom>
+  </target>
+
+
+  <!--=======================================================================
+      clean-jars
+      
+      Removes all the libraries that have been downloaded for this project
+      using the ivy dependencies.
+      ====================================================================-->
+  <target name="clean-jars">
+    <delete dir="${lib.dir}" />
+    <delete dir="${testlib.dir}" />
+  </target>
+
+
+  <!--=======================================================================
+      clean
+      
+      Removes all the files generated from the build process.
+      ====================================================================-->
+  <target name="clean"
+          description="Cleans all the files generated from a build with the exception of IVY-downloaded jars (see clean-all)"
+          depends="clean-tests, clean-cobertura, clean-sonar, clean-javadoc, clean-dist">
+    <delete dir="${classes.dir}" />
+    <delete dir="${bin.dir}" />
+  </target>
+
+
+  <!--=======================================================================
+      clean-dist
+      
+      Removes all dist artifacts
+      ====================================================================-->
+  <target name="clean-dist">
+    <delete dir="${dist.dir}" />
+  </target>
+
+
+  <!--=======================================================================
+      clean-all
+      
+      Removes all the libraries that have been downloaded for this project
+      in the workspace's lib dirs as well as all the files 
+      generated from the build process.
+      ====================================================================-->
+  <target name="clean-all" depends="clean,clean-jars" description="Cleans all the generated and dependency files" />
+
+
+  <!--=======================================================================
+      copy-license-lgpl
+      
+      Copies the LGPL license file into the binary directory.
+      ====================================================================-->
+  <target name="copy-license-lgpl" if="lgpl-license-avail">
+    <copy todir="${classes.dir}/META-INF">
+      <fileset dir="${license.dir}" includes="lgpl-2.1.txt" />
+    </copy>
+  </target>
+
+
+  <!--=======================================================================
+      copy-license-gpl-parent
+      
+      Copies the GPL license file from the parent directory into the 
+      binary directory.
+      ====================================================================-->
+  <target name="copy-license-gpl" if="gpl-license-avail">
+    <copy todir="${classes.dir}/META-INF">
+      <fileset dir="${license.dir}" includes="gpl-2.0.txt" />
+    </copy>
+  </target>
+
+
+  <!--=======================================================================
+      compile
+      
+      Compiles the source code (using the specified options) into the 
+      binary directory.
+      
+      NOTE: This contains multiple sub-tasks which will occur in the 
+            following order (this is provided for easier overriding by
+            the build.xml which will include this file)...
+        - compile.pre      : anything needed to prep for compile
+        - compile.compile  : the actual compilation step
+        - compile.src_copy : copying the source into the bin directory
+        - compile.res_copy : copying the resources into the bin directory
+        - compile.lic_copy : copying the license information into the bin directory
+        - compile.post     : anything needed after the compile is done 
+      ====================================================================-->
+  <target name="compile"
+          depends="init, compile.pre, compile.compile, compile.src_copy, compile.res_copy, compile.lic_copy, compile.post"
+          description="Performs all the steps to prepare the bin directory with a complete compilation" />
+
+
+  <!--=======================================================================
+      compile.pre
+      
+      Prepares to perform the compile.
+      ====================================================================-->
+  <target name="compile.pre" />
+
+
+  <!--=======================================================================
+      compile.compile
+      
+      Performs the actual compile
+      ====================================================================-->
+  <target name="compile.compile" depends="init">
+    <javac destdir="${classes.dir}"
+           debug="${javac.debug}"
+           deprecation="${javac.deprecation}"
+           fork="true"
+           memorymaximumsize="${javac.maxmemory}"
+           source="${javac.source}"
+           target="${javac.target}">
+      <classpath>
+        <path refid="classpath" />
+      </classpath>
+      <src path="${src.dir}" />
+      <compilerarg value="${javac.xlint}" />
+    </javac>
+  </target>
+
+
+  <!--=======================================================================
+      compile.res_copy
+      
+      Copies any needed resources into the classes directory.  Will not
+      duplicate copying of resources from src tree (handled by compile.src_copy
+      if jar.include.source is set.
+      ====================================================================-->
+  <target name="compile.res_copy" depends="install-antcontrib">
+    <if>
+      <available file="${res.dir}" />
+      <then>
+        <copy todir="${classes.dir}">
+          <fileset dir="${res.dir}" />
+        </copy>
+      </then>
+    </if>
+
+    <if>
+      <not>
+        <isset property="jar.include.source" />
+      </not>
+      <then>
+        <copy todir="${classes.dir}" flatten="false">
+          <fileset dir="${src.dir}" excludes="**/*.java" />
+        </copy>
+      </then>
+    </if>
+  </target>
+
+
+  <!--=======================================================================
+      compile.src_copy
+      
+      Copies the source files to the bin directory
+      NOTE: if the dont.copy.source variable exists, this step will be
+            skipped!
+      ====================================================================-->
+  <target name="compile.src_copy" depends="init" if="jar.include.source">
+    <copy todir="${classes.dir}" flatten="false">
+      <fileset dir="${src.dir}" />
+    </copy>
+  </target>
+
+
+  <!--=======================================================================
+      compile.lic_copy
+      
+      Copies the license file(s) into the bin directory
+      ====================================================================-->
+  <target name="compile.lic_copy" depends="init">
+    <condition property="lgpl-license-avail">
+      <available file="${license.dir}/lgpl-2.1.txt" />
+    </condition>
+    <antcall target="copy-license-lgpl" />
+    <condition property="gpl-license-avail">
+      <available file="${license.dir}/gpl-2.0.txt" />
+    </condition>
+    <antcall target="copy-license-gpl" />
+  </target>
+
+
+  <!--=======================================================================
+      compile.post
+      
+      Performs any needed post-compile tasks
+      ====================================================================-->
+  <target name="compile.post" />
+
+
+  <!--=======================================================================
+      jar
+      
+      Creates a jar file from the bin directory
+      ====================================================================-->
+  <target name="jar"
+          depends="jar.main,jar.test"
+          description="Jars up the bin directory after a compile">
+  </target>
+
+  <!-- jar the tests ONLY IF tests.publish it true -->
+  <!-- if the compile-tests target is in the dependency list for this target, -->
+  <!-- it will get executed no matter what the value of tests.publish is      -->
+  <target name="jar.test"
+          if="tests.publish">
+    <antcall target="compile-tests" />
+    <jar destfile="${dist.dir}/${ivy.artifact.id}-test-${project.revision}.jar" manifest="${dist.manifest.file}">
+      <fileset dir="${testclasses.dir}"/>
+    </jar>
+  </target>
+
+  <target name="jar.main"
+          depends="compile,set-build.id,generate.manifest">
+    <jar destfile="${dist.dir}/${ivy.artifact.id}-${project.revision}.jar" manifest="${dist.manifest.file}">
+      <fileset dir="${classes.dir}" />
+    </jar>
+  </target>
+
+  <!--=======================================================================
+      generate.manifest
+      
+      Creates a new manifest file if one is not specified, or updates
+      an existing manifest file if one is specified.
+      ====================================================================-->
+  <target name="generate.manifest" depends="init,set-build.id">
+    <delete file="${dist.manifest.file}" />
+    <touch file="${dist.manifest.file}" />
+    <copy file="${manifest.file}" tofile="${dist.manifest.file}" overwrite="true" failonerror="false" />
+
+    <manifest file="${dist.manifest.file}" mode="update">
+      <attribute name="Implementation-Title" value="${impl.title}" />
+      <attribute name="Implementation-Version" value="${project.revision}.${build.id}" />
+      <attribute name="Implementation-Vendor" value="${impl.vendor}" />
+      <attribute name="Implementation-ProductID" value="${impl.productID}" />
+    </manifest>
+  </target>
+
+
+  <!--=======================================================================
+      dist-source
+      
+      Generates zip and targz distributions of the javadoc
+      ====================================================================-->
+  <target name="dist-source" depends="source.jar, source.zip, source.targz" />
+
+
+  <!--=======================================================================
+      source.jar
+      
+      Creates a jar of the project source for distribution
+      ====================================================================-->
+  <target name="source.jar" depends="init,install-antcontrib">
+    <jar jarfile="${dist.dir}/${ivy.artifact.id}-${project.revision}-sources.jar" basedir="${src.dir}" />
+    <if>
+      <equals arg1="${tests.publish}" arg2="true" />
+      <then>
+        <jar jarfile="${dist.dir}/${ivy.artifact.id}-test-${project.revision}-sources.jar" basedir="${src.dir}" />
+      </then>
+    </if>
+  </target>
+
+  <!--=======================================================================
+      source.zip
+      
+      Creates a zip of the project source for distribution
+      ====================================================================-->
+  <target name="source.zip" depends="init">
+    <jar jarfile="${dist.dir}/${source.zip.filename}" basedir="${src.dir}" />
+  </target>
+
+  <!--=======================================================================
+      source.targz
+      
+      Creates a gzipped tar of the project source for distribution
+      ====================================================================-->
+  <target name="source.targz" depends="init">
+    <tar compression="gzip" destfile="${dist.dir}/${source.tar.filename}" basedir="${src.dir}" />
+  </target>
+
+
+  <!--=======================================================================
+      clean-tests
+      
+      Removes all files related to tests
+      ====================================================================-->
+  <target name="clean-tests">
+    <delete dir="${testbin.dir}" />
+  </target>
+
+
+  <!--=======================================================================
+      init-tests
+      
+      Compiles project test source
+      ====================================================================-->
+  <target name="init-tests" depends="clean-tests">
+    <mkdir dir="${testclasses.dir}" />
+    <mkdir dir="${testsrc.dir}" />
+  </target>
+
+
+  <!--=======================================================================
+      compile-tests
+      
+      Compiles project test source
+      ====================================================================-->
+  <target name="compile-tests" depends="init-tests">
+    <javac destdir="${testclasses.dir}"
+           debug="true"
+           optimize="false"
+           source="${javac.source}"
+           target="${javac.target}"
+           fork="true">
+      <src path="${testsrc.dir}" />
+      <classpath refid="test.classpath" />
+    </javac>
+
+    <!-- Copy the non-java files from the source directory to the test classes directory
+-->
+    <copy todir="${testclasses.dir}">
+      <fileset dir="${testsrc.dir}">
+        <exclude name="**/*.java" />
+      </fileset>
+    </copy>
+  </target>
+
+
+  <!--=======================================================================
+      test
+      
+      Compiles and runs all the tests for the project
+      ====================================================================-->
+  <target name="test" depends="compile,compile-tests, init-test-reports" description="Compiles and runs unit tests">
+    <junit maxmemory="${junit.maxmemory}"
+           dir="${junit.base.dir}"
+           fork="yes"
+           forkmode="${junit.forkmode}"
+           failureProperty="test.failed"
+           haltonfailure="${junit.haltonfailure}"
+           haltonerror="${junit.haltonerror}"
+           printsummary="yes">
+      <sysproperty key="java.awt.headless" value="${headless.unittest}" />
+      
+      <syspropertyset>
+        <propertyref prefix="junit.sysprop." />
+        <mapper type="glob" from="junit.sysprop.*" to="*"/>
+      </syspropertyset>
+      
+      <classpath refid="test.classpath" />
+      <formatter type="xml" />
+      <test name="${testcase}" todir="${testreports.xml.dir}" if="testcase" />
+      <batchtest fork="yes" todir="${testreports.xml.dir}" unless="testcase">
+        <fileset dir="${testsrc.dir}" casesensitive="yes">
+          <include name="**/*Test.java" />
+        </fileset>
+      </batchtest>
+    </junit>
+
+    <junitreport todir="${testreports.html.dir}">
+      <fileset dir="${testreports.xml.dir}">
+        <include name="TEST-*.xml" />
+      </fileset>
+      <report format="frames" todir="${testreports.html.dir}" />
+    </junitreport>
+  </target>
+
+
+  <!--=======================================================================
+    clean-test-reports
+
+    Remove all xml and html JUnit test reports
+    ====================================================================-->
+  <target name="clean-test-reports">
+    <delete dir="${testreports.xml.dir}" />
+    <delete dir="${testreports.html.dir}" />
+  </target>
+
+
+  <!--=======================================================================
+    init-test-reports
+
+    Prepare directories for JUnit test reports
+    ====================================================================-->
+  <target name="init-test-reports" depends="clean-test-reports">
+    <mkdir dir="${testreports.xml.dir}" />
+    <mkdir dir="${testreports.html.dir}" />
+  </target>
+
+  <!--=======================================================================
+      dist
+      
+      Creates a distribution of this project
+      ====================================================================-->
+  <target name="dist" depends="jar" description="Creates a distribution" />
+
+
+  <!--=======================================================================
+      dist-full
+      
+      Creates a distribution of this project including all sources needed
+      to build as well as the resultant jar
+      ====================================================================-->
+  <target name="dist-full" depends="jar"
+          description="Creates all the distributable items for this project">
+    <!-- Create the required zip distribution which contains the entire project -->
+    <zip destfile="${dist.dir}/${ivy.artifact.id}-${project.revision}.zip">
+      <fileset dir="${basedir}">
+        <exclude name="bin/"/>
+        <exclude name="dist/"/>
+        <exclude name="eclipse-bin/"/>
+      </fileset>
+      <zipfileset dir="${dist.dir}" includes="**/*.jar"/>
+    </zip>
+  </target>
+
+
+  <!--=======================================================================
+      javadoc
+      
+      Generates javadoc source documentation for this project
+      ====================================================================-->
+  <target name="javadoc" depends="javadoc.init, compile">
+    <javadoc destdir="${javadoc.dir}/docs/api"
+             access="public"
+             source="6"
+             use="true"
+             notree="false"
+             nonavbar="false"
+             noindex="false"
+             splitindex="true"
+             author="true"
+             version="true"
+             maxmemory="256M"
+             nodeprecatedlist="false"
+             nodeprecated="false"
+             packagenames="${javadoc.packagenames}"
+             sourcepath="${src.dir}"
+             doctitle="${impl.title} documentation">
+      <link href="http://docs.oracle.com/javase/6/docs/api/" />
+      <classpath refid="classpath" />
+    </javadoc>
+  </target>
+
+  	
+  <!--=======================================================================
+	enunciate
+        
+	Generates enunciate documentation for the resoruce 
+	classes comprising the BIServer REST api
+  ====================================================================-->
+  <target name="enunciate" depends="resolve-enunciate">
+    <path id="enunciate.classpath">
+      <fileset dir="${lib.dir}">
+        <include name="*.jar" />
+      	<exclude name="saxon*.jar" />
+      </fileset>
+      <dirset dir="${classes.dir}" />
+      <fileset dir="${dist.dir}">
+        <include name="*.jar" />
+      </fileset>
+      <fileset dir="${enunciate.home}/lib">
+        <include name="*.jar" />
+      </fileset>
+    </path>
+
+    <taskdef name="enunciate" classname="org.codehaus.enunciate.main.EnunciateTask">
+      <classpath refid="enunciate.classpath" />
+    </taskdef>
+
+    <enunciate dir="${basedir}/src" 
+               configFile="${basedir}/enunciate.xml" 
+               generateDir="${enunciate.bin.dir}/generate" 
+               compileDir="${enunciate.bin.dir}/compile" 
+               buildDir="${enunciate.bin.dir}/build" 
+               packageDir="${enunciate.bin.dir}/package" 
+               verbose="true">
+      <include name="**/*.java" />
+      <!-- have to exclude class that contains jersey multipart endpoint until http://jira.codehaus.org/browse/ENUNCIATE-537 is fixed -->
+      
+      <classpath refid="enunciate.classpath" />
+      <export artifactId="docs" destination="${dist.dir}/${enunciate.packagename}.zip" />
+    </enunciate>
+  </target>
+
+  <!--=======================================================================
+      dist-javadoc
+      
+      Generates zip and targz distributions of the javadoc
+      ====================================================================-->
+  <target name="dist-javadoc" depends="javadoc.zip, javadoc.targz" />
+
+
+  <!--=======================================================================
+      clean-javadoc
+      
+      Removes generated javadoc files (note, this does not remove javadoc distributions.
+      Use clean-dist to remove artifacts from the dist.dir.
+      ====================================================================-->
+  <target name="clean-javadoc">
+    <delete dir="${javadoc.dir}" />
+  </target>
+
+
+  <!--=======================================================================
+      javadoc.init
+      
+      Creates directories for javadoc process
+      ====================================================================-->
+  <target name="javadoc.init" depends="clean-javadoc">
+    <mkdir dir="${javadoc.dir}" />
+  </target>
+
+
+  <!--=======================================================================
+      javadoc.zip
+      
+      Creates a zip of the javadoc for distribution
+      ====================================================================-->
+  <target name="javadoc.zip" depends="javadoc">
+    <jar jarfile="${dist.dir}/${javadoc.zip.filename}"
+         basedir="${javadoc.dir}"
+         includes="**/*"
+         excludes="**/Thumbs.db" />
+  </target>
+
+
+  <!--=======================================================================
+      javadoc.targz
+      
+      Creates a gzipped tar of the javadoc for distribution
+      ====================================================================-->
+  <target name="javadoc.targz" depends="javadoc">
+    <tar compression="gzip"
+         destfile="${dist.dir}/${javadoc.tar.filename}"
+         basedir="${javadoc.dir}"
+         includes="**/*"
+         excludes="**/Thumbs.db" />
+  </target>
+
+
+  <!--=======================================================================
+      cobertura
+      
+      Runs tests in an instrumented environment and produces Cobertura test coverage reports
+      ====================================================================-->
+  <target name="cobertura"
+          description="Runs tests in an instrumented environment and produces Cobertura test coverage reports"
+          depends="clean-cobertura,install-cobertura,compile,compile-tests,cobertura.instrument-classes,cobertura.test-instrumented,cobertura.xml-report,cobertura.html-report" />
+
+
+  <!--=======================================================================
+      cobertura.instrument-classes
+      
+      Instruments the application classes used by Cobertura during cobertura.test-instrumented
+      ====================================================================-->
+  <target name="cobertura.instrument-classes" depends="cobertura.clean-instrumented-classes,install-cobertura,compile">
+    <cobertura-instrument todir="${instrumented.classes.dir}" datafile="${cobertura.data.dir}/cobertura.ser">
+      <ignore regex="org.apache.log4j.*" />
+      <fileset dir="${classes.dir}">
+        <!--
+          Instrument all the application classes, but
+          don't instrument the test classes.
+        -->
+        <include name="**/*.class" />
+        <exclude name="**/*Test.class" />
+      </fileset>
+
+    </cobertura-instrument>
+  </target>
+
+
+
+  <!--=======================================================================
+      install-cobertura
+      
+      Downloads and installs Cobertura ant tasks
+      ====================================================================-->
+  <target name="install-cobertura" depends="install-ivy">
+    <taskdef-with-ivy organisation="net.sourceforge.cobertura" module="cobertura" revision="${cobertura.version}" resource="tasks.properties" classname="net.sourceforge.cobertura.ant.InstrumentTask"/>
+  </target>
+
+
+  <!--=======================================================================
+      clean-cobertura
+      
+      Removes all files created by Cobertura code coverage utility
+      ====================================================================-->
+  <target name="clean-cobertura" depends="cobertura.clean-instrumented-classes,cobertura.clean-coverage-reports">
+    <delete dir="${cobertura.data.dir}" />
+  </target>
+
+  <!--=======================================================================
+      clean-sonar
+      
+      Removes the temporary file location for sonar files
+      ====================================================================-->
+  <target name="clean-sonar">
+    <delete dir="${basedir}/.sonar" />
+  </target>
+
+
+  <!--=======================================================================
+    cobertura.clean-instrumented-classes
+
+    Remove the instrumented classes used by Cobertura
+    ====================================================================-->
+  <target name="cobertura.clean-instrumented-classes">
+    <delete dir="${instrumented.classes.dir}" />
+  </target>
+
+
+  <!--=======================================================================
+    cobertura.clean-coverage-reports
+
+    Remove all xml and html Cobertura coverage reports
+    ====================================================================-->
+  <target name="cobertura.clean-coverage-reports">
+    <delete dir="${coberturareports.xml.dir}" />
+    <delete dir="${coberturareports.html.dir}" />
+    <delete dir="${coberturareports.dir}" />
+  </target>
+
+
+  <!--=======================================================================
+      cobertura.test-instrumented
+      
+      Runs tests against instrumented classes and generates xml and html JUnit test reports
+      ====================================================================-->
+  <target name="cobertura.test-instrumented"
+          depends="init-test-reports,install-cobertura,compile,compile-tests,cobertura.instrument-classes">
+    <mkdir dir="${instrumented.classes.dir}" />
+    <path id="cobertura.classpath">
+      <fileset dir="${subfloor.resources.dir}/cobertura-${cobertura.version}">
+        <include name="*.jar" />
+      </fileset>
+    </path>
+    <junit fork="yes"
+           forkmode="${junit.forkmode}"
+           dir="${junit.base.dir}"
+           maxmemory="${junit.maxmemory}"
+           failureProperty="test.failed"
+           haltonerror="${junit.haltonerror}"
+           haltonfailure="${junit.haltonfailure}">
+      <sysproperty key="java.awt.headless" value="${headless.unittest}" />
+
+      <!-- Specify the name of the coverage data file to use. -->
+      <sysproperty key="net.sourceforge.cobertura.datafile" file="${cobertura.data.dir}/cobertura.ser" />
+
+      <syspropertyset>
+        <propertyref prefix="junit.sysprop." />
+        <mapper type="glob" from="junit.sysprop.*" to="*"/>
+      </syspropertyset>
+      
+      <!--
+        Note the classpath order: instrumented classes are before the
+        original (uninstrumented) classes.  This is important.
+      -->
+      <classpath location="${instrumented.classes.dir}" />
+      <classpath refid="test.classpath" />
+      <classpath refid="cobertura.classpath" />
+
+      <formatter type="xml" />
+      <test name="${testcase}" todir="${testreports.xml.dir}" if="testcase" />
+      <batchtest todir="${testreports.xml.dir}" unless="testcase">
+        <fileset dir="${testsrc.dir}" casesensitive="yes">
+          <include name="**/*Test.java" />
+        </fileset>
+      </batchtest>
+    </junit>
+
+    <junitreport todir="${testreports.html.dir}">
+      <fileset dir="${testreports.xml.dir}">
+        <include name="TEST-*.xml" />
+      </fileset>
+      <report format="frames" todir="${testreports.html.dir}" />
+    </junitreport>
+  </target>
+
+
+  <!--=======================================================================
+      cobertura.xml-report
+      
+      Produces machine-readable xml Cobertura coverage report from results of instrumented tests
+      ====================================================================-->
+  <target name="cobertura.xml-report" depends="cobertura.test-instrumented">
+    <cobertura-report destdir="${coberturareports.xml.dir}" datafile="${cobertura.data.dir}/cobertura.ser" format="xml">
+      <fileset dir="${src.dir}">
+        <include name="**/*.java" />
+      </fileset>
+    </cobertura-report>
+  </target>
+
+
+  <!--=======================================================================
+      cobertura.html-report
+      
+      Produces human-readable html Cobertura coverage report from results of instrumented tests
+      ====================================================================-->
+  <target name="cobertura.html-report" depends="cobertura.test-instrumented">
+    <cobertura-report destdir="${coberturareports.html.dir}"
+                      datafile="${cobertura.data.dir}/cobertura.ser"
+                      format="html">
+      <fileset dir="${src.dir}">
+        <include name="**/*.java" />
+      </fileset>
+    </cobertura-report>
+  </target>
+
+  <!--=======================================================================
+        install-pentaho-ant-tasks
+ 
+        Fetches and installs Pentaho Ant tasks
+      ====================================================================-->
+  <target name="install-pentaho-ant-tasks" depends="install-ivy">
+    <taskdef-with-ivy task-name="dot-classpath" classname="org.pentaho.anttasks.DotClasspath" organisation="pentaho" module="pentaho-ant-tasks" revision="1.1" />
+  </target>
+
+  <!--=======================================================================
+        create-dot-classpath
+ 
+        Creates the Eclipse .classpath file from the resolved
+        classpath from Ant.
+      ====================================================================-->
+  <target name="create-dot-classpath" depends="install-pentaho-ant-tasks,init">
+    <dot-classpath>
+      <!-- Include all lib dirs -->
+      <classpath>
+        <fileset dir="${devlib.dir}">
+          <include name="*.jar" />
+        </fileset>
+        <fileset dir="${testlib.dir}">
+          <include name="*.jar" />
+        </fileset>
+        <fileset dir="${lib.dir}">
+          <include name="*.jar" />
+        </fileset>
+      </classpath>
+    </dot-classpath>
+  </target>
+
+
+  <!--=======================================================================
+        MACRO: taskdef-with-ivy
+        Downloads (using IVY) and defines new Ant tasks
+      
+      NOTE: any task using this macro must depend on "install-antcontrib"
+      
+      parameters:
+      task-name    - Name to give the new Ant task (only used if resource is not set)
+      organisation - Artifact organization (for artifact resolution with IVY)
+      module       - Artifact module (for artifact resolution with IVY)
+      revision     - Artifact revision (for artifact resolution with IVY)
+      classname    - Classname for the Ant task.  Used during taskdef and to check 
+                     if we already have the libraries
+      resource     - (optional) Resource defining the Ant task.  Used during taskdef
+      ====================================================================-->
+  <macrodef name="taskdef-with-ivy">
+    <attribute name="task-name"
+               description="Name to give the new Ant task (only used if resource is not set)"
+               default="unset" />
+    <attribute name="organisation" description="Artifact organization" />
+    <attribute name="module" description="Artifact module" />
+    <attribute name="revision" description="Artifact revision" />
+    <attribute name="classname"
+               description="Classname for the Ant task.  Used during taskdef and to check if we already have the libraries." />
+    <attribute name="resource"
+               description="(optional) Resource defining the Ant task.  Used during taskdef"
+               default="unset" />
+    <sequential>
+      <mkdir dir="${subfloor.resources.dir}/@{module}-@{revision}/" />
+      <!-- if the library does not exist, we must download it -->
+      <if>
+        <not>
+          <and>
+            <available file="${subfloor.resources.dir}/@{module}-@{revision}" />
+            <available classname="@{classname}">
+              <classpath>
+                <fileset dir="${subfloor.resources.dir}/@{module}-@{revision}">
+                  <include name="*.jar" />
+                </fileset>
+              </classpath>
+            </available>
+          </and>
+        </not>
+        <then>
+          <ivy:retrieve inline="true"
+              conf="default"
+                        organisation="@{organisation}"
+                        module="@{module}"
+                        revision="@{revision}"
+                        pattern="${subfloor.resources.dir}/@{module}-@{revision}/[module]-__-[revision](-[classifier]).[ext]" />
+          <!-- in case the artifact pulls in an ant jar, remove it. they cause runtime conflicts -->
+          <delete>
+            <fileset dir="${subfloor.resources.dir}/@{module}-@{revision}">
+              <include name="ant-__-*.jar" />
+              <include name="ant-launcher-__-*.jar" />
+            </fileset>
+          </delete>
+        </then>
+      </if>
+      <path id="taskdef.classpath">
+        <fileset dir="${subfloor.resources.dir}/@{module}-@{revision}">
+          <include name="*.jar" />
+        </fileset>
+      </path>
+      <if>
+        <equals arg1="@{resource}" arg2="unset" />
+        <then>
+          <taskdef classpathref="taskdef.classpath" name="@{task-name}" classname="@{classname}" />
+        </then>
+        <else>
+          <taskdef classpathref="taskdef.classpath" resource="@{resource}" />
+        </else>
+      </if>
+    </sequential>
+  </macrodef>
+
+
+  <!--=======================================================================
+      Macro which will download the specified library. 
+      
+      NOTE: any task using this macro must depend on "install-antcontrib"
+      
+      parameters:
+      name      - The name of the library (the filename w/o extension)
+      url       - The URL from which the library will be downloaded
+      resource  - The name of the resource which should be loaded
+                  as a task definition 
+      classname - A class file name which can be used to detect if the
+                  property library exists
+      extension - The extension of the library being downloaded 
+                  (defaults to zip)
+      ====================================================================-->
+  <macrodef name="download-antlib">
+    <attribute name="name" />
+    <attribute name="url" />
+    <attribute name="classname" />
+    <attribute name="extension" default="zip" />
+    <sequential>
+      <mkdir dir="${subfloor.resources.dir}/@{name}/" />
+      <!-- if the library does not exist, we must download it -->
+      <if>
+        <not>
+          <and>
+            <available file="${subfloor.resources.dir}/@{name}" />
+            <available classname="@{classname}">
+              <classpath>
+                <fileset dir="${subfloor.resources.dir}/@{name}">
+                  <include name="**/*.jar" />
+                </fileset>
+              </classpath>
+            </available>
+          </and>
+        </not>
+        <then>
+          <!-- if it is a zip file, unzip it ... otherwise if a jar, just download it -->
+          <if>
+            <equals arg1="zip" arg2="@{extension}" />
+            <then>
+              <!-- download the source file to a temp directory -->
+              <echo message="downloading library @{name} [@{name}.@{extension} from @{url}]" />
+              <mkdir dir="${subfloor.tmp.dir}" />
+              <get src="@{url}" dest="${subfloor.tmp.dir}/@{name}.@{extension}" usetimestamp="true" />
+              <unzip src="${subfloor.tmp.dir}/@{name}.@{extension}"
+                     dest="${subfloor.resources.dir}/@{name}"
+                     overwrite="true" />
+            </then>
+            <else>
+              <get src="@{url}" dest="${subfloor.resources.dir}/@{name}/@{name}.@{extension}" usetimestamp="true" />
+            </else>
+          </if>
+        </then>
+      </if>
+    </sequential>
+  </macrodef>
+
+  <!--=======================================================================
+    install-tattletale
+    
+    (Fetches and) installs TATTLETALE for use by this ant script
+    ====================================================================-->
+  <target name="install-tattletale" depends="install-antcontrib">
+    <if>
+      <istrue value="${tattletale.isinstalled}" />
+      <then>
+        <echo message="Skipping TATTLETALE install.  TATTLETALE has already been configured by the build" />
+      </then>
+      <else>
+        <download-antlib name="tattletale"
+                         url="${tattletale.url}"
+                         classname="${tattletale.classname}" 
+                         extension="zip"/>
+                          
+        <taskdef name="tattletale.report" classname="${tattletale.classname}">
+          <classpath>
+            <fileset dir="${subfloor.resources.dir}/tattletale">
+              <include name="*.jar" />
+            </fileset>
+          </classpath>
+        </taskdef>
+
+        <property name="tattletale.isinstalled" value="true" />
+      </else>
+    </if>
+  </target>
+  
+  <!--=======================================================================
+    tattletale-report
+    
+    Generates a tattletale report for this project
+    ====================================================================-->
+  <target name="tattletale-report" depends="install-tattletale,jar">
+    <tattletale.report source="${basedir}" destination="${tattletale.reports.dir}"/>
+  </target>
+  
+<!--=======================================================================
+    install-sonar
+    
+    (Fetches and) installs SONAR ant plugin for use by this ant script
+    ====================================================================-->
+  <target name="install-sonar" depends="install-antcontrib">
+    <if>
+      <istrue value="${sonar.isinstalled}" />
+      <then>
+        <echo message="Skipping SONAR install.  SONAR has already been configured by the build" />
+      </then>
+      <else>
+        <download-antlib name="sonar"
+                         url="${sonar.url}"
+                         classname="${sonar.classname}" 
+                         extension="jar"/>
+                          
+        <taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml">
+            <classpath>
+              <fileset dir="${subfloor.resources.dir}/sonar">
+                  <include name="*.jar" />
+              </fileset>
+            </classpath> 
+        </taskdef>
+
+        <property name="sonar.isinstalled" value="true" />
+      </else>
+    </if>
+  </target>
+
+  <!--=======================================================================
+    sonar
+      
+    Execute the sonar analysis and publish to a sonar server specified by:
+    sonar.jdbc.url
+    sonar.jdbc.driverClassName
+    sonar.jdbc.username
+    sonar.jdbc.password
+    sonar.host.url
+    ====================================================================-->
+  <target name="sonar" depends="install-sonar, compile, test, cobertura">
+    <property name="sonar.sources" value="${src.dir}" />
+    <property name="sonar.binaries" value="${classes.dir}" />
+    <property name="sonar.tests" value="${testsrc.dir}" />
+    <property name="sonar.libraries" value="${lib.dir}" />
+
+    <property name="sonar.dynamicAnalysis" value="reuseReports" />
+    <property name="sonar.cobertura.reportPath" value="${coberturareports.xml.dir}/coverage.xml" />
+    <property name="sonar.surefire.reportsPath" value="${testreports.xml.dir}" />
+    
+    <sonar:sonar key="${ivy.artifact.group}:${ivy.artifact.id}" version="${project.revision}" xmlns:sonar="antlib:org.sonar.ant"/>
+  </target>
+  
+</project>
diff --git a/0.8.1-rc1/tools/pdi_plugin/build.properties b/0.8.1-rc1/tools/pdi_plugin/build.properties
new file mode 100644
index 0000000..27fa591
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/build.properties
@@ -0,0 +1,13 @@
+impl.title=Apache OODT filemgr file get
+impl.productID=OODT_FILEMGR_GET
+impl.vendor=Apache Foundation
+
+ivy.artifact.group=oodt-filemgr
+ivy.artifact.id=filemgr-fileget-plugin
+
+project.revision=TRUNK-SNAPSHOT
+dependency.pentaho-metadata.revision=TRUNK-SNAPSHOT
+src.dir=${basedir}/src
+testsrc.dir=${basedir}/test-src
+project.use-full-dist=true
+javadoc.packagenames=org.apache.oodt.*
diff --git a/0.8.1-rc1/tools/pdi_plugin/build.xml b/0.8.1-rc1/tools/pdi_plugin/build.xml
new file mode 100644
index 0000000..f16719c
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/build.xml
@@ -0,0 +1,54 @@
+<!--===========================================================================
+  This is the build file for the PDI SDK Step Plugin
+  
+  This build file will use the subfloor.xml file as the default build
+  process and should only override the tasks that need to differ from
+  the common build file.  
+============================================================================-->
+<project name="kettle-sdk-step-plugin" basedir="." default="default">
+
+	<description>
+	  This build file works with the subfloor.xml file.
+	</description>
+
+	<!-- Import the subfloor-pkg.xml file which contains all the default tasks -->
+	<import file="build-res/subfloor-pkg.xml" />
+
+	<!--
+      AS STATED ABOVE, THE ONLY TASKS THAT SHOULD EXIST IN THIS BUILD FILE ARE
+      THE TASKS THAT NEED TO DIFFER FROM THE DEFAULT IMPLEMENTATION OF THE TASKS
+      FOUND IN common_build.xml.
+    -->
+
+	<!-- 
+		override to:
+			- include the source directly (this is SDK demo code)
+			- include kettle dependency jars
+			- include the build folder (used by the SDK user to build the plugin)
+			- include eclipse project files for convenience
+	-->
+	<target name="assemble.copy-libs">
+		
+		<copy todir="${approot.stage.dir}/lib">
+			<fileset dir="${lib.dir}"/>
+		</copy>
+
+		<copy todir="${approot.stage.dir}/src">
+			<fileset dir="src" excludes="**/.DS_Store" />
+		</copy>
+
+		<copy todir="${approot.stage.dir}/build">
+			<fileset dir="build" />
+		</copy>
+		
+		<!--<copy file="eclipse/classpath.xml" tofile="${approot.stage.dir}/.classpath">
+		    <filterset>
+		      <filter token="PROJECT-REVISION" value="${project.revision}"/>
+		      <filter token="METASTORE-REVISION" value="${dependency.pentaho-metadata.revision}"/>
+		    </filterset>			
+		</copy>-->
+		<!--<copy file="eclipse/project.xml" tofile="${approot.stage.dir}/.project" />-->
+			
+	</target>
+
+</project>
diff --git a/0.8.1-rc1/tools/pdi_plugin/build/build.properties b/0.8.1-rc1/tools/pdi_plugin/build/build.properties
new file mode 100644
index 0000000..50da26c
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/build/build.properties
@@ -0,0 +1,3 @@
+# Please adjust to point to your data-integration folder if you'd like the 
+# ant script to be able to install the compiled plugin automatically
+kettle-dir=/Applications/pentaho/design-tools/data-integration
diff --git a/0.8.1-rc1/tools/pdi_plugin/build/build.xml b/0.8.1-rc1/tools/pdi_plugin/build/build.xml
new file mode 100644
index 0000000..4f00648
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/build/build.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<project name="PdiSdkDemoStepPlugin" default="dist" basedir="..">
+	<description>
+        Build file for a PDI step plugin
+    </description>
+
+	<!-- you can use this file to set the kettle-dir property or change it directly below -->
+	<property file="build/build.properties" />
+
+	<!-- set global properties for this build -->
+	<property name="src" location="src" />
+	<property name="classes" location="classes" />
+	<property name="dist" location="dist" />
+	<property name="diststep" location="${dist}/steps/Demo" />
+	<property name="pluginname" value="Demo" />
+	<property name="jarfilename" value="demo-step.jar" />
+
+	<!-- used to compile code -->
+	<path id="compile.classpath">
+		<fileset dir="${basedir}/lib">
+			<include name="**/*.jar" />
+		</fileset>
+	</path>
+
+	<target name="init">
+		<tstamp />
+	</target>
+
+	<target name="compile" depends="init" description="compile the source ">
+		<mkdir dir="${classes}" />
+		<javac source="1.6" target="1.6" srcdir="${src}" destdir="${classes}" debuglevel="lines,vars,source" debug="true">
+			<classpath refid="compile.classpath" />
+
+		</javac>
+	</target>
+
+	<target name="dist" depends="compile" description="generate the distribution">
+
+		<mkdir dir="${diststep}" />
+
+		<!-- jar things up, also add the properties files (messages) and the icon -->
+		<copy todir="${classes}">
+			<fileset dir="${src}" includes="**/*.properties" />
+			<fileset dir="${src}" includes="**/*.png" />
+		</copy>
+
+		<!-- jar class up -->
+		<jar jarfile="${diststep}/${jarfilename}" basedir="${classes}"/>
+
+	</target>
+	
+	<target name="install" depends="dist" description="compile and install into local PDI installation">
+		
+		<echo message="Looking for local PDI installation in ${kettle-dir}"/>
+		
+		<!-- change these to adapt to your environment -->
+		<property name="kettle-dir" location="your_kettle_5.x_dir_here" />
+		<available file="${kettle-dir}" type="dir" property="kettle-dir.present" />
+
+		<fail unless="kettle-dir.present" message="PDI installation not found. Please specify the path to your PDI installation in build/build.properties" />
+		
+		<!-- remove previous installations -->
+		<delete dir="${kettle-dir}/plugins/steps/${pluginname}" />
+
+		<!-- put fresh files in place -->
+		<mkdir dir="${kettle-dir}/plugins/steps/${pluginname}" />
+
+		<copy todir="${kettle-dir}/plugins/steps/${pluginname}">
+			<fileset dir="${diststep}" includes="**/*.*" />
+			<fileset dir="${diststep}" includes="**" />
+		</copy>
+		
+		
+		<echo message="Installed the plugin in PDI. To test, please restart Spoon."/>
+		
+	</target>
+
+	<target name="clean" description="clean up">
+		<delete dir="${classes}" />
+		<delete dir="${dist}" />
+	</target>
+
+</project>
diff --git a/0.8.1-rc1/tools/pdi_plugin/ivy.xml b/0.8.1-rc1/tools/pdi_plugin/ivy.xml
new file mode 100644
index 0000000..f952bae
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/ivy.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ivy-module version="2.0" xmlns:m="http://ant.apache.org/ivy/maven">
+  <info organisation="${ivy.artifact.group}" module="${ivy.artifact.id}" revision="${project.revision}"/>
+
+  <configurations>
+    <conf name="default"/>
+    <conf name="test" visibility="private"/>
+    <conf name="source"/>
+  </configurations>
+
+  <dependencies defaultconf="default">
+
+      <dependency org="org.apache.oodt" name="cas-filemgr" rev="0.7" transitive="false" changing="true"/>
+      <dependency org="org.apache.oodt" name="cas-metadata" rev="0.7" transitive="false" changing="true"/>
+      <dependency org="org.apache.ws.xmlrpc" name="xmlrpc" rev="2.0.1">
+          <exclude org="xml-apis" module="xml-apis"/>
+          <exclude org="junit" module="junit"/>
+              </dependency>
+      <dependency org="org.json" name="json" rev="20140107"/>
+      <dependency org="com.google.code.gson" name="gson" rev="2.2.4"/>
+
+
+      <!-- kettle dependencies -->
+    <dependency org="pentaho-kettle" name="kettle-core" rev="TRUNK-SNAPSHOT" changing="true"/>
+	<dependency org="pentaho-kettle" name="kettle-engine" rev="TRUNK-SNAPSHOT" changing="true"/>
+	<dependency org="pentaho-kettle" name="kettle-ui-swt" rev="TRUNK-SNAPSHOT" changing="true"/>
+	<dependency org="pentaho" name="pentaho-metadata" rev="TRUNK-SNAPSHOT" changing="true" transitive="true"/>
+
+	<!-- swt dependencies -->
+	<dependency org="org.eclipse.swt" name="swt-win32" rev="3.3.0.3346" transitive="false" changing="false"/>
+	
+    <!-- testing dependencies -->
+    <dependency org="junit" name="junit" rev="3.8.1" transitive="false" conf="test->default"/>
+    <dependency org="log4j" name="log4j" rev="1.2.16" transitive="false" conf="test->default"/>
+    
+  </dependencies>
+</ivy-module>
diff --git a/0.8.1-rc1/tools/pdi_plugin/ivysettings.xml b/0.8.1-rc1/tools/pdi_plugin/ivysettings.xml
new file mode 100644
index 0000000..2d97c5c
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/ivysettings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<ivysettings>

+  <properties environment="env" />

+  <property name="ivy.local.default.root" value="${ivy.default.ivy.user.dir}/local" override="true" />

+  <property name="ivy.local.default.artifact.pattern" value="[organisation]/[module]/[revision]/[type]s/[artifact]-[revision].[ext]"

+    override="false" />

+

+

+  <!-- Repository for Pentaho-hosted artifacts -->

+  <property name="pentaho.resolve.repo" value="http://ivy-nexus.pentaho.org/content/groups/omni" override="false" />

+  <!-- Repository for External-hosted artifacts (Optional. Defaults to Pentaho-hosted.) -->

+  <property name="public.resolve.repo" value="${pentaho.resolve.repo}" override="false" />

+

+

+  <settings defaultResolver="pentaho-chained-resolver" />

+  <include url="${ivy.default.settings.dir}/ivysettings-public.xml" />

+  <include url="${ivy.default.settings.dir}/ivysettings-local.xml" />

+  <resolvers>

+    <chain name="pentaho-chained-resolver">

+      <resolver ref="local" />

+      <dual name="pentaho">

+        <url name="pentaho-ivy" checkmodified="true" changingPattern="*-SNAPSHOT">

+          <ivy pattern="${pentaho.resolve.repo}/[organisation]/[module]/[revision]/[module]-[revision].ivy.xml" />

+        </url>

+        <ibiblio name="pentaho-mvn" m2compatible="true" root="${pentaho.resolve.repo}" />

+      </dual>

+      <ibiblio name="public-maven" root="${public.resolve.repo}" m2compatible="true" />

+      <resolver ref="public" />

+    </chain>

+  </resolvers>

+  <caches lockStrategy="artifact-lock" resolutionCacheDir="${ivy.default.ivy.user.dir}/resol-cache${env.EXECUTOR_NUMBER}" />

+</ivysettings>
\ No newline at end of file
diff --git a/0.8.1-rc1/tools/pdi_plugin/package-ivy.xml b/0.8.1-rc1/tools/pdi_plugin/package-ivy.xml
new file mode 100644
index 0000000..b47c2b9
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/package-ivy.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ivy-module version="2.0" xmlns:m="http://ant.apache.org/ivy/maven">
+  <info organisation="${ivy.artifact.group}" module="${ivy.artifact.id}" revision="${project.revision}" />
+  <configurations>
+    <conf name="default" />
+    <conf name="test" visibility="private" />
+  </configurations>
+  
+  <publications>
+    <artifact name="${ivy.artifact.id}" type="zip" />
+  </publications>
+  
+  <dependencies defaultconf="default->default">
+  </dependencies>
+</ivy-module>
\ No newline at end of file
diff --git a/0.8.1-rc1/tools/pdi_plugin/plugins b/0.8.1-rc1/tools/pdi_plugin/plugins
new file mode 100644
index 0000000..b8291a2
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/plugins
Binary files differ
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/FilemgrCheckStep.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/FilemgrCheckStep.java
new file mode 100644
index 0000000..588e5a8
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/FilemgrCheckStep.java
@@ -0,0 +1,199 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrcheck;
+
+import org.pentaho.di.core.exception.KettleException;
+import org.pentaho.di.core.row.RowDataUtil;
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.trans.Trans;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.*;
+
+import java.util.Arrays;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI. 
+ * 
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *   
+ * This class is the implementation of StepInterface.
+ * Classes implementing this interface need to:
+ * 
+ * - initialize the step
+ * - execute the row processing logic
+ * - dispose of the step 
+ * 
+ * Please do not create any local fields in a StepInterface class. Store any
+ * information related to the processing logic in the supplied step data interface
+ * instead.  
+ * 
+ */
+
+public class FilemgrCheckStep extends BaseStep implements StepInterface {
+
+    private OODTConfig oodt = new OODTConfig();
+    private OODTProcesses oodtproc = new OODTProcesses();
+	/**
+	 * The constructor should simply pass on its arguments to the parent class.
+	 * 
+	 * @param s 				step description
+	 * @param stepDataInterface	step data class
+	 * @param c					step copy
+	 * @param t					transformation description
+	 * @param dis				transformation executing
+	 */
+	public FilemgrCheckStep(StepMeta s, StepDataInterface stepDataInterface, int c, TransMeta t, Trans dis) {
+		super(s, stepDataInterface, c, t, dis);
+	}
+	
+	/**
+	 * This method is called by PDI during transformation startup. 
+	 * 
+	 * It should initialize required for step execution. 
+	 * 
+	 * The meta and data implementations passed in can safely be cast
+	 * to the step's respective implementations. 
+	 * 
+	 * It is mandatory that super.init() is called to ensure correct behavior.
+	 * 
+	 * Typical tasks executed here are establishing the connection to a database,
+	 * as wall as obtaining resources, like file handles.
+	 * 
+	 * @param smi 	step meta interface implementation, containing the step settings
+	 * @param sdi	step data interface implementation, used to store runtime information
+	 * 
+	 * @return true if initialization completed successfully, false if there was an error preventing the step from working. 
+	 *  
+	 */
+	public boolean init(StepMetaInterface smi, StepDataInterface sdi) {
+		// Casting to step-specific implementation classes is safe
+		FilemgrCheckStepMeta meta = (FilemgrCheckStepMeta) smi;
+		FilemgrCheckStepData data = (FilemgrCheckStepData) sdi;
+
+        try {
+            logError("loading ingester");
+            oodt.loadIngester(meta.getServerURLField());
+        } catch (InstantiationException e) {
+            e.printStackTrace();
+        }
+
+        return super.init(meta, data);
+	}
+
+	/**
+	 * Once the transformation starts executing, the processRow() method is called repeatedly
+	 * by PDI for as long as it returns true. To indicate that a step has finished processing rows
+	 * this method must call setOutputDone() and return false;
+	 *
+	 * Steps which process incoming rows typically call getRow() to read a single row from the
+	 * input stream, change or add row content, call putRow() to pass the changed row on
+	 * and return true. If getRow() returns null, no more rows are expected to come in,
+	 * and the processRow() implementation calls setOutputDone() and returns false to
+	 * indicate that it is done too.
+	 *
+	 * Steps which generate rows typically construct a new row Object[] using a call to
+	 * RowDataUtil.allocateRowData(numberOfFields), add row content, and call putRow() to
+	 * pass the new row on. Above process may happen in a loop to generate multiple rows,
+	 * at the end of which processRow() would call setOutputDone() and return false;
+	 *
+	 * @param smi the step meta interface containing the step settings
+	 * @param sdi the step data interface that should be used to store
+	 *
+	 * @return true to indicate that the function should be called again, false if the step is done
+	 */
+	public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {
+
+		// safely cast the step settings (meta) and runtime info (data) to specific implementations
+		FilemgrCheckStepMeta meta = (FilemgrCheckStepMeta) smi;
+		FilemgrCheckStepData data = (FilemgrCheckStepData) sdi;
+
+		// get incoming row, getRow() potentially blocks waiting for more rows, returns null if no more rows expected
+		Object[] r = getRow();
+
+		// if no more rows are expected, indicate step is finished and processRow() should not be called again
+		if (r == null){
+			setOutputDone();
+			return false;
+		}
+
+		// the "first" flag is inherited from the base step implementation
+		// it is used to guard some processing tasks, like figuring out field indexes
+		// in the row structure that only need to be done once
+		if (first) {
+			first = false;
+			// clone the input row structure and place it in our data object
+			data.outputRowMeta = (RowMetaInterface) getInputRowMeta().clone();
+			// use meta.getFields() to change it, so it reflects the output row structure
+			meta.getFields(data.outputRowMeta, getStepname(), null, null, this, null, null);
+		}
+
+        String[] names = getInputRowMeta().getFieldNames();
+
+        logError("fieldname = "+meta.getFilenameField());
+        int idx = Arrays.asList(names).indexOf(meta.getFilenameField());
+
+        logError("IDX=" +Integer.toString(idx));
+
+        try {
+            logError("does file exist?"+oodtproc.isAlreadyInDatabase(oodt, (String)r[idx]));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        // safely add the string "Hello World!" at the end of the output row
+		// the row array will be resized if necessary
+		Object[] outputRow = RowDataUtil.addValueData(r, data.outputRowMeta.size() - 1, "Hello World!");
+
+		// put the row to the output row stream
+		putRow(data.outputRowMeta, outputRow);
+
+		// log progress if it is time to to so
+		if (checkFeedback(getLinesRead())) {
+			logBasic("Linenr " + getLinesRead()); // Some basic logging
+		}
+
+		// indicate that processRow() should be called again
+		return true;
+	}
+
+	/**
+	 * This method is called by PDI once the step is done processing.
+	 *
+	 * The dispose() method is the counterpart to init() and should release any resources
+	 * acquired for step execution like file handles or database connections.
+	 *
+	 * The meta and data implementations passed in can safely be cast
+	 * to the step's respective implementations.
+	 *
+	 * It is mandatory that super.dispose() is called to ensure correct behavior.
+	 *
+	 * @param smi 	step meta interface implementation, containing the step settings
+	 * @param sdi	step data interface implementation, used to store runtime information
+	 */
+	public void dispose(StepMetaInterface smi, StepDataInterface sdi) {
+
+		// Casting to step-specific implementation classes is safe
+		FilemgrCheckStepMeta meta = (FilemgrCheckStepMeta) smi;
+		FilemgrCheckStepData data = (FilemgrCheckStepData) sdi;
+		
+		super.dispose(meta, data);
+	}
+
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/FilemgrCheckStepData.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/FilemgrCheckStepData.java
new file mode 100644
index 0000000..30c5f31
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/FilemgrCheckStepData.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrcheck;
+
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.trans.step.BaseStepData;
+import org.pentaho.di.trans.step.StepDataInterface;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI. 
+ * 
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *   
+ * This class is the implementation of StepDataInterface.
+ *   
+ * Implementing classes inherit from BaseStepData, which implements the entire
+ * interface completely. 
+ * 
+ * In addition classes implementing this interface usually keep track of
+ * per-thread resources during step execution. Typical examples are:
+ * result sets, temporary data, caching indexes, etc.
+ *   
+ * The implementation for the demo step stores the output row structure in 
+ * the data class. 
+ *   
+ */
+public class FilemgrCheckStepData extends BaseStepData implements StepDataInterface {
+
+	public RowMetaInterface outputRowMeta;
+
+    public String fieldname;
+
+    public FilemgrCheckStepData()
+	{
+		super();
+	}
+}
+	
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/FilemgrCheckStepDialog.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/FilemgrCheckStepDialog.java
new file mode 100644
index 0000000..78ef67b
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/FilemgrCheckStepDialog.java
@@ -0,0 +1,307 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrcheck;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.*;
+import org.pentaho.di.core.Const;
+import org.pentaho.di.i18n.BaseMessages;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.BaseStepMeta;
+import org.pentaho.di.trans.step.StepDialogInterface;
+import org.pentaho.di.ui.trans.step.BaseStepDialog;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI. 
+ * 
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *   
+ * This class is the implementation of StepDialogInterface.
+ * Classes implementing this interface need to:
+ * 
+ * - build and open a SWT dialog displaying the step's settings (stored in the step's meta object)
+ * - write back any changes the user makes to the step's meta object
+ * - report whether the user changed any settings when confirming the dialog 
+ * 
+ */
+public class FilemgrCheckStepDialog extends BaseStepDialog implements StepDialogInterface {
+
+	/**
+	 *	The PKG member is used when looking up internationalized strings.
+	 *	The properties file with localized keys is expected to reside in 
+	 *	{the package of the class specified}/messages/messages_{locale}.properties   
+	 */
+	private static Class<?> PKG = FilemgrCheckStepMeta.class; // for i18n purposes
+
+	// this is the object the stores the step's settings
+	// the dialog reads the settings from it when opening
+	// the dialog writes the settings to it when confirmed 
+	private FilemgrCheckStepMeta meta;
+
+	// text field holding the name of the field to add to the row stream
+	//private Text wHelloFieldName;
+
+    // text field holding the name of the field to check the filename against
+    private Text wFilenameField;
+    private Text wServerURLField;
+    private Text wResultField;
+	/**
+	 * The constructor should simply invoke super() and save the incoming meta
+	 * object to a local variable, so it can conveniently read and write settings
+	 * from/to it.
+	 * 
+	 * @param parent 	the SWT shell to open the dialog in
+	 * @param in		the meta object holding the step's settings
+	 * @param transMeta	transformation description
+	 * @param sname		the step name
+	 */
+	public FilemgrCheckStepDialog(Shell parent, Object in, TransMeta transMeta, String sname) {
+		super(parent, (BaseStepMeta) in, transMeta, sname);
+		meta = (FilemgrCheckStepMeta) in;
+	}
+
+	/**
+	 * This method is called by Spoon when the user opens the settings dialog of the step.
+	 * It should open the dialog and return only once the dialog has been closed by the user.
+	 * 
+	 * If the user confirms the dialog, the meta object (passed in the constructor) must
+	 * be updated to reflect the new step settings. The changed flag of the meta object must 
+	 * reflect whether the step configuration was changed by the dialog.
+	 * 
+	 * If the user cancels the dialog, the meta object must not be updated, and its changed flag
+	 * must remain unaltered.
+	 * 
+	 * The open() method must return the name of the step after the user has confirmed the dialog,
+	 * or null if the user cancelled the dialog.
+	 */
+	public String open() {
+
+		// store some convenient SWT variables 
+		Shell parent = getParent();
+		Display display = parent.getDisplay();
+
+		// SWT code for preparing the dialog
+		shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX);
+		props.setLook(shell);
+		setShellImage(shell, meta);
+		
+		// Save the value of the changed flag on the meta object. If the user cancels
+		// the dialog, it will be restored to this saved value.
+		// The "changed" variable is inherited from BaseStepDialog
+		changed = meta.hasChanged();
+		
+		// The ModifyListener used on all controls. It will update the meta object to 
+		// indicate that changes are being made.
+		ModifyListener lsMod = new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				meta.setChanged();
+			}
+		};
+		
+		// ------------------------------------------------------- //
+		// SWT code for building the actual settings dialog        //
+		// ------------------------------------------------------- //
+		FormLayout formLayout = new FormLayout();
+		formLayout.marginWidth = Const.FORM_MARGIN;
+		formLayout.marginHeight = Const.FORM_MARGIN;
+
+		shell.setLayout(formLayout);
+		shell.setText(BaseMessages.getString(PKG, "Demo.Shell.Title")); 
+
+		int middle = props.getMiddlePct();
+		int margin = Const.MARGIN;
+
+		// Stepname line
+		wlStepname = new Label(shell, SWT.RIGHT);
+		wlStepname.setText(BaseMessages.getString(PKG, "System.Label.StepName")); 
+		props.setLook(wlStepname);
+		fdlStepname = new FormData();
+		fdlStepname.left = new FormAttachment(0, 0);
+		fdlStepname.right = new FormAttachment(middle, -margin);
+		fdlStepname.top = new FormAttachment(0, margin);
+		wlStepname.setLayoutData(fdlStepname);
+		
+		wStepname = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+		wStepname.setText(stepname);
+		props.setLook(wStepname);
+		wStepname.addModifyListener(lsMod);
+		fdStepname = new FormData();
+		fdStepname.left = new FormAttachment(middle, 0);
+		fdStepname.top = new FormAttachment(0, margin);
+		fdStepname.right = new FormAttachment(100, 0);
+		wStepname.setLayoutData(fdStepname);
+
+		// output field value
+		Label wlValName = new Label(shell, SWT.RIGHT);
+		wlValName.setText(BaseMessages.getString(PKG, "FilemgrCheck.FieldName.Label"));
+		props.setLook(wlValName);
+		FormData fdlValName = new FormData();
+		fdlValName.left = new FormAttachment(0, 0);
+		fdlValName.right = new FormAttachment(middle, -margin);
+		fdlValName.top = new FormAttachment(wStepname, margin);
+		wlValName.setLayoutData(fdlValName);
+
+		wFilenameField = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+		props.setLook(wFilenameField);
+		wFilenameField.addModifyListener(lsMod);
+		FormData fdValName = new FormData();
+		fdValName.left = new FormAttachment(middle, 0);
+		fdValName.right = new FormAttachment(100, 0);
+		fdValName.top = new FormAttachment(wStepname, margin);
+		wFilenameField.setLayoutData(fdValName);
+
+
+        // servername field value
+        Label wlServerName = new Label(shell, SWT.RIGHT);
+        wlServerName.setText(BaseMessages.getString(PKG, "FilemgrCheck.ServerURL.Label"));
+        props.setLook(wlServerName);
+        FormData fdlServerName = new FormData();
+        fdlServerName.left = new FormAttachment(0, 0);
+        fdlServerName.right = new FormAttachment(middle, -margin);
+        fdlServerName.top = new FormAttachment(wFilenameField, margin);
+        wlServerName.setLayoutData(fdlServerName);
+
+        wServerURLField = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+        props.setLook(wServerURLField);
+        wServerURLField.addModifyListener(lsMod);
+        FormData fdServerName = new FormData();
+        fdServerName.left = new FormAttachment(middle, 0);
+        fdServerName.right = new FormAttachment(100, 0);
+        fdServerName.top = new FormAttachment(wFilenameField, margin);
+        wServerURLField.setLayoutData(fdServerName);
+
+        // servername field value
+        Label wlResultName = new Label(shell, SWT.RIGHT);
+        wlResultName.setText(BaseMessages.getString(PKG, "FilemgrCheck.Result.Label"));
+        props.setLook(wlResultName);
+        FormData fdlResultName = new FormData();
+        fdlResultName.left = new FormAttachment(0, 0);
+        fdlResultName.right = new FormAttachment(middle, -margin);
+        fdlResultName.top = new FormAttachment(wServerURLField, margin);
+        wlResultName.setLayoutData(fdlResultName);
+
+        wResultField = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+        props.setLook(wResultField);
+        wResultField.addModifyListener(lsMod);
+        FormData fdResultName = new FormData();
+        fdResultName.left = new FormAttachment(middle, 0);
+        fdResultName.right = new FormAttachment(100, 0);
+        fdResultName.top = new FormAttachment(wServerURLField, margin);
+        wResultField.setLayoutData(fdResultName);
+
+
+        // OK and cancel buttons
+		wOK = new Button(shell, SWT.PUSH);
+		wOK.setText(BaseMessages.getString(PKG, "System.Button.OK")); 
+		wCancel = new Button(shell, SWT.PUSH);
+		wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel")); 
+
+		BaseStepDialog.positionBottomButtons(shell, new Button[] { wOK, wCancel }, margin, wResultField);
+
+		// Add listeners for cancel and OK
+		lsCancel = new Listener() {
+			public void handleEvent(Event e) {cancel();}
+		};
+		lsOK = new Listener() {
+			public void handleEvent(Event e) {ok();}
+		};
+
+		wCancel.addListener(SWT.Selection, lsCancel);
+		wOK.addListener(SWT.Selection, lsOK);
+
+		// default listener (for hitting "enter")
+		lsDef = new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {ok();}
+		};
+		wStepname.addSelectionListener(lsDef);
+		wFilenameField.addSelectionListener(lsDef);
+        wServerURLField.addSelectionListener(lsDef);
+        wResultField.addSelectionListener(lsDef);
+		// Detect X or ALT-F4 or something that kills this window and cancel the dialog properly
+		shell.addShellListener(new ShellAdapter() {
+			public void shellClosed(ShellEvent e) {cancel();}
+		});
+		
+		// Set/Restore the dialog size based on last position on screen
+		// The setSize() method is inherited from BaseStepDialog
+		setSize();
+
+		// populate the dialog with the values from the meta object
+		populateDialog();
+		
+		// restore the changed flag to original value, as the modify listeners fire during dialog population 
+		meta.setChanged(changed);
+
+		// open dialog and enter event loop 
+		shell.open();
+		while (!shell.isDisposed()) {
+			if (!display.readAndDispatch())
+				display.sleep();
+		}
+
+		// at this point the dialog has closed, so either ok() or cancel() have been executed
+		// The "stepname" variable is inherited from BaseStepDialog
+		return stepname;
+	}
+	
+	/**
+	 * This helper method puts the step configuration stored in the meta object
+	 * and puts it into the dialog controls.
+	 */
+	private void populateDialog() {
+		wStepname.selectAll();
+		wFilenameField.setText(meta.getFilenameField());
+        wServerURLField.setText(meta.getServerURLField());
+        wResultField.setText(meta.getResultField());
+	}
+
+	/**
+	 * Called when the user cancels the dialog.  
+	 */
+	private void cancel() {
+		// The "stepname" variable will be the return value for the open() method. 
+		// Setting to null to indicate that dialog was cancelled.
+		stepname = null;
+		// Restoring original "changed" flag on the met aobject
+		meta.setChanged(changed);
+		// close the SWT dialog window
+		dispose();
+	}
+	
+	/**
+	 * Called when the user confirms the dialog
+	 */
+	private void ok() {
+		// The "stepname" variable will be the return value for the open() method. 
+		// Setting to step name from the dialog control
+		stepname = wStepname.getText(); 
+		// Setting the  settings to the meta object
+		//meta.setOutputField(wFilenameField.getText());
+        meta.setFilenameField(wFilenameField.getText());
+        meta.setServerURLField(wServerURLField.getText());
+        meta.setResultField(wResultField.getText());
+		// close the SWT dialog window
+		dispose();
+	}
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/FilemgrCheckStepMeta.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/FilemgrCheckStepMeta.java
new file mode 100644
index 0000000..7fb5b97
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/FilemgrCheckStepMeta.java
@@ -0,0 +1,345 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrcheck;
+
+import org.eclipse.swt.widgets.Shell;
+import org.pentaho.di.core.CheckResult;
+import org.pentaho.di.core.CheckResultInterface;
+import org.pentaho.di.core.annotations.Step;
+import org.pentaho.di.core.database.DatabaseMeta;
+import org.pentaho.di.core.exception.KettleException;
+import org.pentaho.di.core.exception.KettleStepException;
+import org.pentaho.di.core.exception.KettleValueException;
+import org.pentaho.di.core.exception.KettleXMLException;
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.core.row.ValueMeta;
+import org.pentaho.di.core.row.ValueMetaInterface;
+import org.pentaho.di.core.variables.VariableSpace;
+import org.pentaho.di.core.xml.XMLHandler;
+import org.pentaho.di.i18n.BaseMessages;
+import org.pentaho.di.repository.ObjectId;
+import org.pentaho.di.repository.Repository;
+import org.pentaho.di.trans.Trans;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.*;
+import org.pentaho.metastore.api.IMetaStore;
+import org.w3c.dom.Node;
+
+import java.util.List;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI. 
+ * 
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *   
+ * This class is the implementation of StepMetaInterface.
+ * Classes implementing this interface need to:
+ * 
+ * - keep track of the step settings
+ * - serialize step settings both to xml and a repository
+ * - provide new instances of objects implementing StepDialogInterface, StepInterface and StepDataInterface
+ * - report on how the step modifies the meta-data of the row-stream (row structure and field types)
+ * - perform a sanity-check on the settings provided by the user 
+ * 
+ */
+
+@Step(	
+		id = "FilemgrCheck",
+		image = "org/apache/oodt/filemgrcheck/resources/check/oodt.jpg",
+		i18nPackageName="bi.meteorite.filemgrcheck",
+		name="FilemgrCheckStep.Name",
+		description = "FilemgrCheckStep.TooltipDesc",
+		categoryDescription="i18n:org.pentaho.di.trans.step:BaseStep.Category.BigData"
+)
+public class FilemgrCheckStepMeta extends BaseStepMeta implements StepMetaInterface {
+	/**
+	 *	The PKG member is used when looking up internationalized strings.
+	 *	The properties file with localized keys is expected to reside in 
+	 *	{the package of the class specified}/messages/messages_{locale}.properties   
+	 */
+	private static Class<?> PKG = FilemgrCheckStepMeta.class; // for i18n purposes
+	
+	/**
+	 * Stores the name of the field added to the row-stream. 
+	 */
+	private String outputField;
+    private String filenameField;
+    private String serverURLField;
+    private String resultField;
+
+    /**
+	 * Constructor should call super() to make sure the base class has a chance to initialize properly.
+	 */
+	public FilemgrCheckStepMeta() {
+		super(); 
+	}
+	
+	/**
+	 * Called by Spoon to get a new instance of the SWT dialog for the step.
+	 * A standard implementation passing the arguments to the constructor of the step dialog is recommended.
+	 * 
+	 * @param shell		an SWT Shell
+	 * @param meta 		description of the step 
+	 * @param transMeta	description of the the transformation 
+	 * @param name		the name of the step
+	 * @return 			new instance of a dialog for this step 
+	 */
+	public StepDialogInterface getDialog(Shell shell, StepMetaInterface meta, TransMeta transMeta, String name) {
+		return new FilemgrCheckStepDialog(shell, meta, transMeta, name);
+	}
+
+	/**
+	 * Called by PDI to get a new instance of the step implementation. 
+	 * A standard implementation passing the arguments to the constructor of the step class is recommended.
+	 * 
+	 * @param stepMeta				description of the step
+	 * @param stepDataInterface		instance of a step data class
+	 * @param cnr					copy number
+	 * @param transMeta				description of the transformation
+	 * @param disp					runtime implementation of the transformation
+	 * @return						the new instance of a step implementation 
+	 */
+	public StepInterface getStep(StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr, TransMeta transMeta, Trans disp) {
+		return new FilemgrCheckStep(stepMeta, stepDataInterface, cnr, transMeta, disp);
+	}
+
+	/**
+	 * Called by PDI to get a new instance of the step data class.
+	 */
+	public StepDataInterface getStepData() {
+		return new FilemgrCheckStepData();
+	}	
+
+	/**
+	 * This method is called every time a new step is created and should allocate/set the step configuration
+	 * to sensible defaults. The values set here will be used by Spoon when a new step is created.    
+	 */
+	public void setDefault() {
+		outputField = "demo_field";
+        filenameField = "fieldname";
+        serverURLField = "http://localhost:9000";
+        resultField = "result";
+	}
+	
+	/**
+	 * Getter for the name of the field added by this step
+	 * @return the name of the field added
+	 */
+	public String getOutputField() {
+		return outputField;
+	}
+
+	/**
+	 * Setter for the name of the field added by this step
+	 * @param outputField the name of the field added
+	 */
+	public void setOutputField(String outputField) {
+		this.outputField = outputField;
+	}
+
+
+    public String getFilenameField(){
+        return filenameField;
+    }
+
+    public void setFilenameField(String filenameField){
+        this.filenameField = filenameField;
+    }
+	/**
+	 * This method is used when a step is duplicated in Spoon. It needs to return a deep copy of this
+	 * step meta object. Be sure to create proper deep copies if the step configuration is stored in
+	 * modifiable objects.
+	 * 
+	 * See org.pentaho.di.trans.steps.rowgenerator.RowGeneratorMeta.clone() for an example on creating
+	 * a deep copy.
+	 * 
+	 * @return a deep copy of this
+	 */
+	public Object clone() {
+		Object retval = super.clone();
+		return retval;
+	}
+	
+	/**
+	 * This method is called by Spoon when a step needs to serialize its configuration to XML. The expected
+	 * return value is an XML fragment consisting of one or more XML tags.  
+	 * 
+	 * Please use org.pentaho.di.core.xml.XMLHandler to conveniently generate the XML.
+	 * 
+	 * @return a string containing the XML serialization of this step
+	 */
+	public String getXML() throws KettleValueException {
+		
+		// only one field to serialize
+		String xml =  " ";
+        xml += "    " +XMLHandler.addTagValue("outputfield", outputField);
+        xml += "    " +XMLHandler.addTagValue("filenamefield", filenameField);
+        xml += "    " +XMLHandler.addTagValue("serverurlfield", serverURLField);
+        xml += "    " +XMLHandler.addTagValue("resultfield", resultField);
+		return xml;
+	}
+
+	/**
+	 * This method is called by PDI when a step needs to load its configuration from XML.
+	 * 
+	 * Please use org.pentaho.di.core.xml.XMLHandler to conveniently read from the
+	 * XML node passed in.
+	 * 
+	 * @param stepnode	the XML node containing the configuration
+	 * @param databases	the databases available in the transformation
+	 * @param metaStore the metaStore to optionally read from
+	 */
+	public void loadXML(Node stepnode, List<DatabaseMeta> databases, IMetaStore metaStore) throws KettleXMLException {
+
+		try {
+			setOutputField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "outputfield")));
+            setFilenameField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "filenamefield")));
+            setServerURLField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "serverurlfield")));
+            setResultField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "resultfield")));
+		} catch (Exception e) {
+			throw new KettleXMLException("Demo plugin unable to read step info from XML node", e);
+		}
+
+	}	
+	/**
+	 * This method is called by Spoon when a step needs to serialize its configuration to a repository.
+	 * The repository implementation provides the necessary methods to save the step attributes.
+	 *
+	 * @param rep					the repository to save to
+	 * @param metaStore				the metaStore to optionally write to
+	 * @param id_transformation		the id to use for the transformation when saving
+	 * @param id_step				the id to use for the step  when saving
+	 */
+	public void saveRep(Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step) throws KettleException
+	{
+		try{
+			rep.saveStepAttribute(id_transformation, id_step, "outputfield", outputField); //$NON-NLS-1$
+		}
+		catch(Exception e){
+			throw new KettleException("Unable to save step into repository: "+id_step, e); 
+		}
+	}		
+	
+	/**
+	 * This method is called by PDI when a step needs to read its configuration from a repository.
+	 * The repository implementation provides the necessary methods to read the step attributes.
+	 * 
+	 * @param rep		the repository to read from
+	 * @param metaStore	the metaStore to optionally read from
+	 * @param id_step	the id of the step being read
+	 * @param databases	the databases available in the transformation
+	 * @param counters	the counters available in the transformation
+	 */
+	public void readRep(Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases) throws KettleException  {
+		try{
+			outputField  = rep.getStepAttributeString(id_step, "outputfield"); //$NON-NLS-1$
+		}
+		catch(Exception e){
+			throw new KettleException("Unable to load step from repository", e);
+		}
+	}
+
+	/**
+	 * This method is called to determine the changes the step is making to the row-stream.
+	 * To that end a RowMetaInterface object is passed in, containing the row-stream structure as it is when entering
+	 * the step. This method must apply any changes the step makes to the row stream. Usually a step adds fields to the
+	 * row-stream.
+	 * 
+	 * @param inputRowMeta		the row structure coming in to the step
+	 * @param name 				the name of the step making the changes
+	 * @param info				row structures of any info steps coming in
+	 * @param nextStep			the description of a step this step is passing rows to
+	 * @param space				the variable space for resolving variables
+	 * @param repository		the repository instance optionally read from
+	 * @param metaStore			the metaStore to optionally read from
+	 */
+	public void getFields(RowMetaInterface inputRowMeta, String name, RowMetaInterface[] info, StepMeta nextStep, VariableSpace space, Repository repository, IMetaStore metaStore) throws KettleStepException{
+
+		/*
+		 * This implementation appends the outputField to the row-stream
+		 */
+
+		// a value meta object contains the meta data for a field
+		ValueMetaInterface v = new ValueMeta(outputField, ValueMeta.TYPE_STRING);
+		
+		// setting trim type to "both"
+		v.setTrimType(ValueMeta.TRIM_TYPE_BOTH);
+
+		// the name of the step that adds this field
+		v.setOrigin(name);
+		
+		// modify the row structure and add the field this step generates  
+		inputRowMeta.addValueMeta(v);
+		
+	}
+
+	/**
+	 * This method is called when the user selects the "Verify Transformation" option in Spoon. 
+	 * A list of remarks is passed in that this method should add to. Each remark is a comment, warning, error, or ok.
+	 * The method should perform as many checks as necessary to catch design-time errors.
+	 * 
+	 * Typical checks include:
+	 * - verify that all mandatory configuration is given
+	 * - verify that the step receives any input, unless it's a row generating step
+	 * - verify that the step does not receive any input if it does not take them into account
+	 * - verify that the step finds fields it relies on in the row-stream
+	 * 
+	 *   @param remarks		the list of remarks to append to
+	 *   @param transmeta	the description of the transformation
+	 *   @param stepMeta	the description of the step
+	 *   @param prev		the structure of the incoming row-stream
+	 *   @param input		names of steps sending input to the step
+	 *   @param output		names of steps this step is sending output to
+	 *   @param info		fields coming in from info steps 
+	 *   @param metaStore	metaStore to optionally read from
+	 */
+	public void check(List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepMeta, RowMetaInterface prev, String input[], String output[], RowMetaInterface info, VariableSpace space, Repository repository, IMetaStore metaStore)  {
+		
+		CheckResult cr;
+
+		// See if there are input streams leading to this step!
+		if (input.length > 0) {
+			cr = new CheckResult(CheckResult.TYPE_RESULT_OK, BaseMessages.getString(PKG, "Demo.CheckResult.ReceivingRows.OK"), stepMeta);
+			remarks.add(cr);
+		} else {
+			cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, BaseMessages.getString(PKG, "Demo.CheckResult.ReceivingRows.ERROR"), stepMeta);
+			remarks.add(cr);
+		}	
+    	
+	}
+
+
+    public void setServerURLField(String serverURLField) {
+        this.serverURLField = serverURLField;
+    }
+
+    public String getServerURLField() {
+        return serverURLField;
+    }
+
+
+    public void setResultField(String resultField) {
+        this.resultField = resultField;
+    }
+
+    public String getResultField() {
+        return resultField;
+    }
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/OODTConfig.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/OODTConfig.java
new file mode 100644
index 0000000..9e7e529
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/OODTConfig.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrcheck;
+
+import org.apache.oodt.cas.filemgr.ingest.Ingester;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Created by bugg on 07/03/14.
+ */
+public class OODTConfig {
+
+    private static final Logger LOG = Logger.getLogger(OODTConfig.class.getName());
+
+    private URL fmUrl;
+
+    private Ingester ingester;
+
+    public Ingester getIngester() {
+        return this.ingester;
+    }
+
+    public URL getFmUrl(){
+        return this.fmUrl;
+    }
+
+
+    void loadIngester(String fmUrlStr) throws InstantiationException {
+        try {
+
+            String ingesterClass = "org.apache.oodt.cas.filemgr.ingest.StdIngester";
+
+            String dataTransferClass ="org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory";
+
+            String cacheFactoryClass = null;
+             //"org.apache.oodt.cas.filemgr.ingest.cache.factory";
+
+            LOG.log(Level.INFO, "Configuring and building ingester: ["
+                        + ingesterClass + "]: data transfer: ["
+                        + dataTransferClass + "]: to ingest to file manager: ["
+                        + fmUrlStr + "]");
+
+           if (cacheFactoryClass != null) {
+                    LOG.log(Level.INFO, "Configuring Ingester cache: ["
+                            + cacheFactoryClass + "]");
+           }
+
+           this.ingester = PushPullObjectFactory.createIngester(
+                  ingesterClass, cacheFactoryClass);
+
+           this.fmUrl = safeGetUrlFromString(fmUrlStr);
+
+           } catch (ClassNotFoundException e1) {
+            e1.printStackTrace();
+        } catch (InvocationTargetException e1) {
+            e1.printStackTrace();
+        } catch (NoSuchMethodException e1) {
+            e1.printStackTrace();
+        } catch (IllegalAccessException e1) {
+            e1.printStackTrace();
+        }
+
+    }
+
+
+    private static URL safeGetUrlFromString(String urlStr) {
+        URL url = null;
+
+        try {
+            url = new URL(urlStr);
+        } catch (MalformedURLException e) {
+            LOG.log(Level.WARNING, "Unable to generate url from url string: ["
+                    + urlStr + "]: Message: " + e.getMessage());
+        }
+
+        return url;
+    }
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/OODTProcesses.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/OODTProcesses.java
new file mode 100644
index 0000000..9977b65
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/OODTProcesses.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrcheck;
+
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+
+/**
+ * Created by bugg on 07/03/14.
+ */
+public class OODTProcesses {
+
+
+    public boolean isAlreadyInDatabase(OODTConfig config, String filename) throws CatalogException {
+        return config.getIngester() != null ? config.getIngester().hasProduct(
+                config.getFmUrl(), filename)
+                : false;
+    }
+
+
+
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/PushPullObjectFactory.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/PushPullObjectFactory.java
new file mode 100644
index 0000000..aa94372
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/PushPullObjectFactory.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrcheck;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.ingest.Cache;
+import org.apache.oodt.cas.filemgr.ingest.CacheFactory;
+import org.apache.oodt.cas.filemgr.ingest.Ingester;
+
+//JDK imports
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class PushPullObjectFactory {
+
+    private PushPullObjectFactory() throws InstantiationException {
+        throw new InstantiationException("Don't construct factory classes!");
+    }
+
+    public static <T> T createNewInstance(Class<T> clazz) throws InstantiationException {
+    	try {
+			return clazz.newInstance();
+		} catch (Exception e) {
+            throw new InstantiationException(
+                    "Failed to create new object : "
+                            + e.getMessage());
+		}
+    }
+    
+    public static Ingester createIngester(String ingesterClass,
+            String cacheFactoryClass) throws InstantiationException,
+            IllegalAccessException, ClassNotFoundException,
+            IllegalArgumentException, SecurityException,
+            InvocationTargetException, NoSuchMethodException {
+        String dataTransferFactory = "org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory";
+        System.out.println("TRANSFER: " + dataTransferFactory);
+        if (cacheFactoryClass == null || cacheFactoryClass.equals("")) {
+            return (Ingester) Class.forName(ingesterClass).getConstructor(
+                    dataTransferFactory.getClass()).newInstance(
+                    dataTransferFactory);
+        } else {
+            Class<CacheFactory> cacheFactory = (Class<CacheFactory>) Class
+                    .forName(cacheFactoryClass);
+            Cache cache = cacheFactory.newInstance().createCache();
+            return (Ingester) Class.forName(ingesterClass).getConstructor(
+                    dataTransferFactory.getClass(), cache.getClass())
+                    .newInstance(dataTransferFactory, cache);
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/messages/messages_en_US.properties b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/messages/messages_en_US.properties
new file mode 100644
index 0000000..a7af034
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/messages/messages_en_US.properties
@@ -0,0 +1,6 @@
+FilemgrCheckStep.Name=OODT Filemgr File Check
+FilemgrCheckStep.TooltipDesc=Check if the OODT Filemgr has a file in its repository
+
+FilemgrCheck.FieldName.Label=Stream Field Name
+FilemgrCheck.ServerURL.Label=Filemgr URL
+FilemgrCheck.Result.Label=Result Field
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/resources/check/oodt.jpg b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/resources/check/oodt.jpg
new file mode 100644
index 0000000..5810409
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/resources/check/oodt.jpg
Binary files differ
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/resources/check/oodt.png b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/resources/check/oodt.png
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrcheck/resources/check/oodt.png
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/FilemgrDeleteStep.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/FilemgrDeleteStep.java
new file mode 100644
index 0000000..b2a48df
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/FilemgrDeleteStep.java
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.filemgrdelete;
+
+import org.pentaho.di.core.exception.KettleException;
+import org.pentaho.di.core.row.RowDataUtil;
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.trans.Trans;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.*;
+
+import java.util.Arrays;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI. 
+ * 
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *   
+ * This class is the implementation of StepInterface.
+ * Classes implementing this interface need to:
+ * 
+ * - initialize the step
+ * - execute the row processing logic
+ * - dispose of the step 
+ * 
+ * Please do not create any local fields in a StepInterface class. Store any
+ * information related to the processing logic in the supplied step data interface
+ * instead.  
+ * 
+ */
+
+public class FilemgrDeleteStep extends BaseStep implements StepInterface {
+
+    private OODTConfig oodt = new OODTConfig();
+    private OODTProcesses oodtproc = new OODTProcesses();
+	/**
+	 * The constructor should simply pass on its arguments to the parent class.
+	 * 
+	 * @param s 				step description
+	 * @param stepDataInterface	step data class
+	 * @param c					step copy
+	 * @param t					transformation description
+	 * @param dis				transformation executing
+	 */
+	public FilemgrDeleteStep(StepMeta s, StepDataInterface stepDataInterface, int c, TransMeta t, Trans dis) {
+		super(s, stepDataInterface, c, t, dis);
+	}
+	
+	/**
+	 * This method is called by PDI during transformation startup. 
+	 * 
+	 * It should initialize required for step execution. 
+	 * 
+	 * The meta and data implementations passed in can safely be cast
+	 * to the step's respective implementations. 
+	 * 
+	 * It is mandatory that super.init() is called to ensure correct behavior.
+	 * 
+	 * Typical tasks executed here are establishing the connection to a database,
+	 * as wall as obtaining resources, like file handles.
+	 * 
+	 * @param smi 	step meta interface implementation, containing the step settings
+	 * @param sdi	step data interface implementation, used to store runtime information
+	 * 
+	 * @return true if initialization completed successfully, false if there was an error preventing the step from working. 
+	 *  
+	 */
+	public boolean init(StepMetaInterface smi, StepDataInterface sdi) {
+		// Casting to step-specific implementation classes is safe
+		FilemgrDeleteStepMeta meta = (FilemgrDeleteStepMeta) smi;
+		FilemgrDeleteStepData data = (FilemgrDeleteStepData) sdi;
+
+
+            logDetailed("loading ingester");
+            oodt.loadXMLRpcClient(meta.getServerURLField());
+            logDetailed("finished loading ingester");
+        return super.init(meta, data);
+	}
+
+	/**
+	 * Once the transformation starts executing, the processRow() method is called repeatedly
+	 * by PDI for as long as it returns true. To indicate that a step has finished processing rows
+	 * this method must call setOutputDone() and return false;
+	 *
+	 * Steps which process incoming rows typically call getRow() to read a single row from the
+	 * input stream, change or add row content, call putRow() to pass the changed row on
+	 * and return true. If getRow() returns null, no more rows are expected to come in,
+	 * and the processRow() implementation calls setOutputDone() and returns false to
+	 * indicate that it is done too.
+	 *
+	 * Steps which generate rows typically construct a new row Object[] using a call to
+	 * RowDataUtil.allocateRowData(numberOfFields), add row content, and call putRow() to
+	 * pass the new row on. Above process may happen in a loop to generate multiple rows,
+	 * at the end of which processRow() would call setOutputDone() and return false;
+	 *
+	 * @param smi the step meta interface containing the step settings
+	 * @param sdi the step data interface that should be used to store
+	 *
+	 * @return true to indicate that the function should be called again, false if the step is done
+	 */
+	public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {
+
+		// safely cast the step settings (meta) and runtime info (data) to specific implementations
+		FilemgrDeleteStepMeta meta = (FilemgrDeleteStepMeta) smi;
+		FilemgrDeleteStepData data = (FilemgrDeleteStepData) sdi;
+
+		// get incoming row, getRow() potentially blocks waiting for more rows, returns null if no more rows expected
+		Object[] r = getRow();
+
+		// if no more rows are expected, indicate step is finished and processRow() should not be called again
+		if (r == null){
+			setOutputDone();
+			return false;
+		}
+
+		// the "first" flag is inherited from the base step implementation
+		// it is used to guard some processing tasks, like figuring out field indexes
+		// in the row structure that only need to be done once
+		if (first) {
+			first = false;
+			// clone the input row structure and place it in our data object
+			data.outputRowMeta = (RowMetaInterface) getInputRowMeta().clone();
+			// use meta.getFields() to change it, so it reflects the output row structure
+			meta.getFields(data.outputRowMeta, getStepname(), null, null, this, null, null);
+		}
+
+        String[] names = getInputRowMeta().getFieldNames();
+        int idx = Arrays.asList(names).indexOf(meta.getFilenameField());
+
+        boolean worked = false;
+        try {
+            logDetailed("Deleting Product: "+(String)r[idx]);
+            worked = oodtproc.deleteProductByName(oodt, (String)r[idx]);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        // safely add the string "Hello World!" at the end of the output row
+		// the row array will be resized if necessary
+		Object[] outputRow = RowDataUtil.addValueData(r, data.outputRowMeta.size() - 1, worked);
+
+		// put the row to the output row stream
+		putRow(data.outputRowMeta, outputRow);
+
+		// log progress if it is time to to so
+		if (checkFeedback(getLinesRead())) {
+			logBasic("Linenr " + getLinesRead()); // Some basic logging
+		}
+
+		// indicate that processRow() should be called again
+		return true;
+	}
+
+	/**
+	 * This method is called by PDI once the step is done processing.
+	 *
+	 * The dispose() method is the counterpart to init() and should release any resources
+	 * acquired for step execution like file handles or database connections.
+	 *
+	 * The meta and data implementations passed in can safely be cast
+	 * to the step's respective implementations.
+	 *
+	 * It is mandatory that super.dispose() is called to ensure correct behavior.
+	 *
+	 * @param smi 	step meta interface implementation, containing the step settings
+	 * @param sdi	step data interface implementation, used to store runtime information
+	 */
+	public void dispose(StepMetaInterface smi, StepDataInterface sdi) {
+
+		// Casting to step-specific implementation classes is safe
+		FilemgrDeleteStepMeta meta = (FilemgrDeleteStepMeta) smi;
+		FilemgrDeleteStepData data = (FilemgrDeleteStepData) sdi;
+		
+		super.dispose(meta, data);
+	}
+
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/FilemgrDeleteStepData.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/FilemgrDeleteStepData.java
new file mode 100644
index 0000000..819d9d8
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/FilemgrDeleteStepData.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.filemgrdelete;
+
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.trans.step.BaseStepData;
+import org.pentaho.di.trans.step.StepDataInterface;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI. 
+ * 
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *   
+ * This class is the implementation of StepDataInterface.
+ *   
+ * Implementing classes inherit from BaseStepData, which implements the entire
+ * interface completely. 
+ * 
+ * In addition classes implementing this interface usually keep track of
+ * per-thread resources during step execution. Typical examples are:
+ * result sets, temporary data, caching indexes, etc.
+ *   
+ * The implementation for the demo step stores the output row structure in 
+ * the data class. 
+ *   
+ */
+public class FilemgrDeleteStepData extends BaseStepData implements StepDataInterface {
+
+	public RowMetaInterface outputRowMeta;
+
+    public String fieldname;
+
+    public FilemgrDeleteStepData()
+	{
+		super();
+	}
+}
+	
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/FilemgrDeleteStepDialog.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/FilemgrDeleteStepDialog.java
new file mode 100644
index 0000000..3fa9008
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/FilemgrDeleteStepDialog.java
@@ -0,0 +1,309 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.filemgrdelete;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.*;
+import org.pentaho.di.core.Const;
+import org.pentaho.di.i18n.BaseMessages;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.BaseStepMeta;
+import org.pentaho.di.trans.step.StepDialogInterface;
+import org.pentaho.di.ui.trans.step.BaseStepDialog;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI. 
+ * 
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *   
+ * This class is the implementation of StepDialogInterface.
+ * Classes implementing this interface need to:
+ * 
+ * - build and open a SWT dialog displaying the step's settings (stored in the step's meta object)
+ * - write back any changes the user makes to the step's meta object
+ * - report whether the user changed any settings when confirming the dialog 
+ * 
+ */
+public class FilemgrDeleteStepDialog extends BaseStepDialog implements StepDialogInterface {
+
+	/**
+	 *	The PKG member is used when looking up internationalized strings.
+	 *	The properties file with localized keys is expected to reside in 
+	 *	{the package of the class specified}/messages/messages_{locale}.properties   
+	 */
+	private static Class<?> PKG = FilemgrDeleteStepMeta.class; // for i18n purposes
+
+	// this is the object the stores the step's settings
+	// the dialog reads the settings from it when opening
+	// the dialog writes the settings to it when confirmed 
+	private FilemgrDeleteStepMeta meta;
+
+	// text field holding the name of the field to add to the row stream
+	//private Text wHelloFieldName;
+
+    // text field holding the name of the field to check the filename against
+    private Text wFilenameField;
+    private Text wServerURLField;
+    private Text wResultField;
+	/**
+	 * The constructor should simply invoke super() and save the incoming meta
+	 * object to a local variable, so it can conveniently read and write settings
+	 * from/to it.
+	 * 
+	 * @param parent 	the SWT shell to open the dialog in
+	 * @param in		the meta object holding the step's settings
+	 * @param transMeta	transformation description
+	 * @param sname		the step name
+	 */
+	public FilemgrDeleteStepDialog(Shell parent, Object in, TransMeta transMeta, String sname) {
+		super(parent, (BaseStepMeta) in, transMeta, sname);
+		meta = (FilemgrDeleteStepMeta) in;
+	}
+
+	/**
+	 * This method is called by Spoon when the user opens the settings dialog of the step.
+	 * It should open the dialog and return only once the dialog has been closed by the user.
+	 * 
+	 * If the user confirms the dialog, the meta object (passed in the constructor) must
+	 * be updated to reflect the new step settings. The changed flag of the meta object must 
+	 * reflect whether the step configuration was changed by the dialog.
+	 * 
+	 * If the user cancels the dialog, the meta object must not be updated, and its changed flag
+	 * must remain unaltered.
+	 * 
+	 * The open() method must return the name of the step after the user has confirmed the dialog,
+	 * or null if the user cancelled the dialog.
+	 */
+	public String open() {
+
+		// store some convenient SWT variables 
+		Shell parent = getParent();
+		Display display = parent.getDisplay();
+
+		// SWT code for preparing the dialog
+		shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX);
+		props.setLook(shell);
+		setShellImage(shell, meta);
+		
+		// Save the value of the changed flag on the meta object. If the user cancels
+		// the dialog, it will be restored to this saved value.
+		// The "changed" variable is inherited from BaseStepDialog
+		changed = meta.hasChanged();
+		
+		// The ModifyListener used on all controls. It will update the meta object to 
+		// indicate that changes are being made.
+		ModifyListener lsMod = new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				meta.setChanged();
+			}
+		};
+		
+		// ------------------------------------------------------- //
+		// SWT code for building the actual settings dialog        //
+		// ------------------------------------------------------- //
+		FormLayout formLayout = new FormLayout();
+		formLayout.marginWidth = Const.FORM_MARGIN;
+		formLayout.marginHeight = Const.FORM_MARGIN;
+
+		shell.setLayout(formLayout);
+		shell.setText(BaseMessages.getString(PKG, "Demo.Shell.Title")); 
+
+		int middle = props.getMiddlePct();
+		int margin = Const.MARGIN;
+
+		// Stepname line
+		wlStepname = new Label(shell, SWT.RIGHT);
+		wlStepname.setText(BaseMessages.getString(PKG, "System.Label.StepName")); 
+		props.setLook(wlStepname);
+		fdlStepname = new FormData();
+		fdlStepname.left = new FormAttachment(0, 0);
+		fdlStepname.right = new FormAttachment(middle, -margin);
+		fdlStepname.top = new FormAttachment(0, margin);
+		wlStepname.setLayoutData(fdlStepname);
+		
+		wStepname = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+		wStepname.setText(stepname);
+		props.setLook(wStepname);
+		wStepname.addModifyListener(lsMod);
+		fdStepname = new FormData();
+		fdStepname.left = new FormAttachment(middle, 0);
+		fdStepname.top = new FormAttachment(0, margin);
+		fdStepname.right = new FormAttachment(100, 0);
+		wStepname.setLayoutData(fdStepname);
+
+		// output field value
+		Label wlValName = new Label(shell, SWT.RIGHT);
+		wlValName.setText(BaseMessages.getString(PKG, "FilemgrDelete.FieldName.Label"));
+		props.setLook(wlValName);
+		FormData fdlValName = new FormData();
+		fdlValName.left = new FormAttachment(0, 0);
+		fdlValName.right = new FormAttachment(middle, -margin);
+		fdlValName.top = new FormAttachment(wStepname, margin);
+		wlValName.setLayoutData(fdlValName);
+
+		wFilenameField = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+		props.setLook(wFilenameField);
+		wFilenameField.addModifyListener(lsMod);
+		FormData fdValName = new FormData();
+		fdValName.left = new FormAttachment(middle, 0);
+		fdValName.right = new FormAttachment(100, 0);
+		fdValName.top = new FormAttachment(wStepname, margin);
+		wFilenameField.setLayoutData(fdValName);
+
+
+        // servername field value
+        Label wlServerName = new Label(shell, SWT.RIGHT);
+        wlServerName.setText(BaseMessages.getString(PKG, "FilemgrDelete.ServerURL.Label"));
+        props.setLook(wlServerName);
+        FormData fdlServerName = new FormData();
+        fdlServerName.left = new FormAttachment(0, 0);
+        fdlServerName.right = new FormAttachment(middle, -margin);
+        fdlServerName.top = new FormAttachment(wFilenameField, margin);
+        wlServerName.setLayoutData(fdlServerName);
+
+        wServerURLField = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+        props.setLook(wServerURLField);
+        wServerURLField.addModifyListener(lsMod);
+        FormData fdServerName = new FormData();
+        fdServerName.left = new FormAttachment(middle, 0);
+        fdServerName.right = new FormAttachment(100, 0);
+        fdServerName.top = new FormAttachment(wFilenameField, margin);
+        wServerURLField.setLayoutData(fdServerName);
+
+        // servername field value
+        Label wlResultName = new Label(shell, SWT.RIGHT);
+        wlResultName.setText(BaseMessages.getString(PKG, "FilemgrDelete.Result.Label"));
+        props.setLook(wlResultName);
+        FormData fdlResultName = new FormData();
+        fdlResultName.left = new FormAttachment(0, 0);
+        fdlResultName.right = new FormAttachment(middle, -margin);
+        fdlResultName.top = new FormAttachment(wServerURLField, margin);
+        wlResultName.setLayoutData(fdlResultName);
+
+        wResultField = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+        props.setLook(wResultField);
+        wResultField.addModifyListener(lsMod);
+        FormData fdResultName = new FormData();
+        fdResultName.left = new FormAttachment(middle, 0);
+        fdResultName.right = new FormAttachment(100, 0);
+        fdResultName.top = new FormAttachment(wServerURLField, margin);
+        wResultField.setLayoutData(fdResultName);
+
+
+        // OK and cancel buttons
+		wOK = new Button(shell, SWT.PUSH);
+		wOK.setText(BaseMessages.getString(PKG, "System.Button.OK")); 
+		wCancel = new Button(shell, SWT.PUSH);
+		wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel")); 
+
+		BaseStepDialog.positionBottomButtons(shell, new Button[] { wOK, wCancel }, margin, wResultField);
+
+		// Add listeners for cancel and OK
+		lsCancel = new Listener() {
+			public void handleEvent(Event e) {cancel();}
+		};
+		lsOK = new Listener() {
+			public void handleEvent(Event e) {ok();}
+		};
+
+		wCancel.addListener(SWT.Selection, lsCancel);
+		wOK.addListener(SWT.Selection, lsOK);
+
+		// default listener (for hitting "enter")
+		lsDef = new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {ok();}
+		};
+		wStepname.addSelectionListener(lsDef);
+		wFilenameField.addSelectionListener(lsDef);
+        wServerURLField.addSelectionListener(lsDef);
+        wResultField.addSelectionListener(lsDef);
+		// Detect X or ALT-F4 or something that kills this window and cancel the dialog properly
+		shell.addShellListener(new ShellAdapter() {
+			public void shellClosed(ShellEvent e) {cancel();}
+		});
+		
+		// Set/Restore the dialog size based on last position on screen
+		// The setSize() method is inherited from BaseStepDialog
+		setSize();
+
+		// populate the dialog with the values from the meta object
+		populateDialog();
+		
+		// restore the changed flag to original value, as the modify listeners fire during dialog population 
+		meta.setChanged(changed);
+
+		// open dialog and enter event loop 
+		shell.open();
+		while (!shell.isDisposed()) {
+			if (!display.readAndDispatch())
+				display.sleep();
+		}
+
+		// at this point the dialog has closed, so either ok() or cancel() have been executed
+		// The "stepname" variable is inherited from BaseStepDialog
+		return stepname;
+	}
+	
+	/**
+	 * This helper method puts the step configuration stored in the meta object
+	 * and puts it into the dialog controls.
+	 */
+	private void populateDialog() {
+		wStepname.selectAll();
+		wFilenameField.setText(meta.getFilenameField());
+        wServerURLField.setText(meta.getServerURLField());
+        wResultField.setText(meta.getResultField());
+	}
+
+	/**
+	 * Called when the user cancels the dialog.  
+	 */
+	private void cancel() {
+		// The "stepname" variable will be the return value for the open() method. 
+		// Setting to null to indicate that dialog was cancelled.
+		stepname = null;
+		// Restoring original "changed" flag on the met aobject
+		meta.setChanged(changed);
+		// close the SWT dialog window
+		dispose();
+	}
+	
+	/**
+	 * Called when the user confirms the dialog
+	 */
+	private void ok() {
+		// The "stepname" variable will be the return value for the open() method. 
+		// Setting to step name from the dialog control
+		stepname = wStepname.getText(); 
+		// Setting the  settings to the meta object
+		//meta.setOutputField(wFilenameField.getText());
+        meta.setFilenameField(wFilenameField.getText());
+        meta.setServerURLField(wServerURLField.getText());
+        meta.setResultField(wResultField.getText());
+		// close the SWT dialog window
+		dispose();
+	}
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/FilemgrDeleteStepMeta.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/FilemgrDeleteStepMeta.java
new file mode 100644
index 0000000..e89484c
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/FilemgrDeleteStepMeta.java
@@ -0,0 +1,349 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.filemgrdelete;
+
+import org.eclipse.swt.widgets.Shell;
+import org.pentaho.di.core.CheckResult;
+import org.pentaho.di.core.CheckResultInterface;
+import org.pentaho.di.core.annotations.Step;
+import org.pentaho.di.core.database.DatabaseMeta;
+import org.pentaho.di.core.exception.KettleException;
+import org.pentaho.di.core.exception.KettleStepException;
+import org.pentaho.di.core.exception.KettleValueException;
+import org.pentaho.di.core.exception.KettleXMLException;
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.core.row.ValueMeta;
+import org.pentaho.di.core.row.ValueMetaInterface;
+import org.pentaho.di.core.variables.VariableSpace;
+import org.pentaho.di.core.xml.XMLHandler;
+import org.pentaho.di.i18n.BaseMessages;
+import org.pentaho.di.repository.ObjectId;
+import org.pentaho.di.repository.Repository;
+import org.pentaho.di.trans.Trans;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.*;
+import org.pentaho.metastore.api.IMetaStore;
+import org.w3c.dom.Node;
+
+import java.util.List;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI. 
+ * 
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *   
+ * This class is the implementation of StepMetaInterface.
+ * Classes implementing this interface need to:
+ * 
+ * - keep track of the step settings
+ * - serialize step settings both to xml and a repository
+ * - provide new instances of objects implementing StepDialogInterface, StepInterface and StepDataInterface
+ * - report on how the step modifies the meta-data of the row-stream (row structure and field types)
+ * - perform a sanity-check on the settings provided by the user 
+ * 
+ */
+
+@Step(	
+		id = "FilemgrCheck",
+		image = "org/apache/oodt/filemgrcheck/resources/check/oodt.jpg",
+		i18nPackageName="bi.meteorite.filemgrcheck",
+		name="FilemgrCheckStep.Name",
+		description = "FilemgrCheckStep.TooltipDesc",
+		categoryDescription="i18n:org.pentaho.di.trans.step:BaseStep.Category.Transform"
+)
+public class FilemgrDeleteStepMeta extends BaseStepMeta implements StepMetaInterface {
+
+	/**
+	 *	The PKG member is used when looking up internationalized strings.
+	 *	The properties file with localized keys is expected to reside in 
+	 *	{the package of the class specified}/messages/messages_{locale}.properties   
+	 */
+	private static Class<?> PKG = FilemgrDeleteStepMeta.class; // for i18n purposes
+	
+	/**
+	 * Stores the name of the field added to the row-stream. 
+	 */
+	private String outputField;
+    private String filenameField;
+    private String serverURLField;
+    private String resultField;
+
+    /**
+	 * Constructor should call super() to make sure the base class has a chance to initialize properly.
+	 */
+	public FilemgrDeleteStepMeta() {
+		super(); 
+	}
+	
+	/**
+	 * Called by Spoon to get a new instance of the SWT dialog for the step.
+	 * A standard implementation passing the arguments to the constructor of the step dialog is recommended.
+	 * 
+	 * @param shell		an SWT Shell
+	 * @param meta 		description of the step 
+	 * @param transMeta	description of the the transformation 
+	 * @param name		the name of the step
+	 * @return 			new instance of a dialog for this step 
+	 */
+	public StepDialogInterface getDialog(Shell shell, StepMetaInterface meta, TransMeta transMeta, String name) {
+		return new FilemgrDeleteStepDialog(shell, meta, transMeta, name);
+	}
+
+	/**
+	 * Called by PDI to get a new instance of the step implementation. 
+	 * A standard implementation passing the arguments to the constructor of the step class is recommended.
+	 * 
+	 * @param stepMeta				description of the step
+	 * @param stepDataInterface		instance of a step data class
+	 * @param cnr					copy number
+	 * @param transMeta				description of the transformation
+	 * @param disp					runtime implementation of the transformation
+	 * @return						the new instance of a step implementation 
+	 */
+	public StepInterface getStep(StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr, TransMeta transMeta, Trans disp) {
+		return new FilemgrDeleteStep(stepMeta, stepDataInterface, cnr, transMeta, disp);
+	}
+
+	/**
+	 * Called by PDI to get a new instance of the step data class.
+	 */
+	public StepDataInterface getStepData() {
+		return new FilemgrDeleteStepData();
+	}	
+
+	/**
+	 * This method is called every time a new step is created and should allocate/set the step configuration
+	 * to sensible defaults. The values set here will be used by Spoon when a new step is created.    
+	 */
+	public void setDefault() {
+		outputField = "demo_field";
+        filenameField = "fieldname";
+        serverURLField = "http://localhost:9000";
+        resultField = "result";
+	}
+	
+	/**
+	 * Getter for the name of the field added by this step
+	 * @return the name of the field added
+	 */
+	public String getOutputField() {
+		return outputField;
+	}
+
+	/**
+	 * Setter for the name of the field added by this step
+	 * @param outputField the name of the field added
+	 */
+	public void setOutputField(String outputField) {
+		this.outputField = outputField;
+	}
+
+
+    public String getFilenameField(){
+        return filenameField;
+    }
+
+    public void setFilenameField(String filenameField){
+        this.filenameField = filenameField;
+    }
+	/**
+	 * This method is used when a step is duplicated in Spoon. It needs to return a deep copy of this
+	 * step meta object. Be sure to create proper deep copies if the step configuration is stored in
+	 * modifiable objects.
+	 * 
+	 * See org.pentaho.di.trans.steps.rowgenerator.RowGeneratorMeta.clone() for an example on creating
+	 * a deep copy.
+	 * 
+	 * @return a deep copy of this
+	 */
+	public Object clone() {
+		Object retval = super.clone();
+		return retval;
+	}
+	
+	/**
+	 * This method is called by Spoon when a step needs to serialize its configuration to XML. The expected
+	 * return value is an XML fragment consisting of one or more XML tags.  
+	 * 
+	 * Please use org.pentaho.di.core.xml.XMLHandler to conveniently generate the XML.
+	 * 
+	 * @return a string containing the XML serialization of this step
+	 */
+	public String getXML() throws KettleValueException {
+		
+		// only one field to serialize
+		String xml =  " ";
+        xml += "    " +XMLHandler.addTagValue("outputfield", outputField);
+        xml += "    " +XMLHandler.addTagValue("filenamefield", filenameField);
+        xml += "    " +XMLHandler.addTagValue("serverurlfield", serverURLField);
+        xml += "    " +XMLHandler.addTagValue("resultfield", resultField);
+		return xml;
+	}
+
+	/**
+	 * This method is called by PDI when a step needs to load its configuration from XML.
+	 * 
+	 * Please use org.pentaho.di.core.xml.XMLHandler to conveniently read from the
+	 * XML node passed in.
+	 * 
+	 * @param stepnode	the XML node containing the configuration
+	 * @param databases	the databases available in the transformation
+	 * @param metaStore the metaStore to optionally read from
+	 */
+	public void loadXML(Node stepnode, List<DatabaseMeta> databases, IMetaStore metaStore) throws KettleXMLException {
+
+		try {
+			setOutputField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "outputfield")));
+            setFilenameField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "filenamefield")));
+            setServerURLField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "serverurlfield")));
+            setResultField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "resultfield")));
+		} catch (Exception e) {
+			throw new KettleXMLException("Demo plugin unable to read step info from XML node", e);
+		}
+
+	}	
+	/**
+	 * This method is called by Spoon when a step needs to serialize its configuration to a repository.
+	 * The repository implementation provides the necessary methods to save the step attributes.
+	 *
+	 * @param rep					the repository to save to
+	 * @param metaStore				the metaStore to optionally write to
+	 * @param id_transformation		the id to use for the transformation when saving
+	 * @param id_step				the id to use for the step  when saving
+	 */
+	public void saveRep(Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step) throws KettleException
+	{
+		try{
+			rep.saveStepAttribute(id_transformation, id_step, "outputfield", outputField); //$NON-NLS-1$
+		}
+		catch(Exception e){
+			throw new KettleException("Unable to save step into repository: "+id_step, e); 
+		}
+	}		
+	
+	/**
+	 * This method is called by PDI when a step needs to read its configuration from a repository.
+	 * The repository implementation provides the necessary methods to read the step attributes.
+	 * 
+	 * @param rep		the repository to read from
+	 * @param metaStore	the metaStore to optionally read from
+	 * @param id_step	the id of the step being read
+	 * @param databases	the databases available in the transformation
+	 */
+	public void readRep(Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases) throws KettleException  {
+		try{
+			outputField  = rep.getStepAttributeString(id_step, "outputfield"); //$NON-NLS-1$
+		}
+		catch(Exception e){
+			throw new KettleException("Unable to load step from repository", e);
+		}
+	}
+
+	/**
+	 * This method is called to determine the changes the step is making to the row-stream.
+	 * To that end a RowMetaInterface object is passed in, containing the row-stream structure as it is when entering
+	 * the step. This method must apply any changes the step makes to the row stream. Usually a step adds fields to the
+	 * row-stream.
+	 * 
+	 * @param inputRowMeta		the row structure coming in to the step
+	 * @param name 				the name of the step making the changes
+	 * @param info				row structures of any info steps coming in
+	 * @param nextStep			the description of a step this step is passing rows to
+	 * @param space				the variable space for resolving variables
+	 * @param repository		the repository instance optionally read from
+	 * @param metaStore			the metaStore to optionally read from
+	 */
+	public void getFields(RowMetaInterface inputRowMeta, String name, RowMetaInterface[] info, StepMeta nextStep, VariableSpace space, Repository repository, IMetaStore metaStore) throws KettleStepException{
+
+		/*
+		 * This implementation appends the outputField to the row-stream
+		 */
+
+		// a value meta object contains the meta data for a field
+		ValueMetaInterface v = new ValueMeta(outputField, ValueMeta.TYPE_STRING);
+		
+		// setting trim type to "both"
+		v.setTrimType(ValueMeta.TRIM_TYPE_BOTH);
+
+		// the name of the step that adds this field
+		v.setOrigin(name);
+		
+		// modify the row structure and add the field this step generates  
+		inputRowMeta.addValueMeta(v);
+		
+	}
+
+
+    /**
+     * This method is called when the user selects the "Verify Transformation" option in Spoon.
+     * A list of remarks is passed in that this method should add to. Each remark is a comment, warning, error, or ok.
+     * The method should perform as many checks as necessary to catch design-time errors.
+     *
+     * Typical checks include:
+     * - verify that all mandatory configuration is given
+     * - verify that the step receives any input, unless it's a row generating step
+     * - verify that the step does not receive any input if it does not take them into account
+     * - verify that the step finds fields it relies on in the row-stream
+     *
+     * @param remarks
+     * @param transMeta
+     * @param stepMeta
+     * @param prev
+     * @param input
+     * @param output
+     * @param info
+     * @param space
+     * @param repository
+     * @param metaStore
+     */
+	public void check(List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepMeta, RowMetaInterface prev, String input[], String output[], RowMetaInterface info, VariableSpace space, Repository repository, IMetaStore metaStore)  {
+		
+		CheckResult cr;
+
+		// See if there are input streams leading to this step!
+		if (input.length > 0) {
+			cr = new CheckResult(CheckResult.TYPE_RESULT_OK, BaseMessages.getString(PKG, "Demo.CheckResult.ReceivingRows.OK"), stepMeta);
+			remarks.add(cr);
+		} else {
+			cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, BaseMessages.getString(PKG, "Demo.CheckResult.ReceivingRows.ERROR"), stepMeta);
+			remarks.add(cr);
+		}	
+    	
+	}
+
+
+    public void setServerURLField(String serverURLField) {
+        this.serverURLField = serverURLField;
+    }
+
+    public String getServerURLField() {
+        return serverURLField;
+    }
+
+
+    public void setResultField(String resultField) {
+        this.resultField = resultField;
+    }
+
+    public String getResultField() {
+        return resultField;
+    }
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/OODTConfig.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/OODTConfig.java
new file mode 100644
index 0000000..0ebe318
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/OODTConfig.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.filemgrdelete;
+
+
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Created by bugg on 07/03/14.
+ */
+public class OODTConfig {
+
+    private static final Logger LOG = Logger.getLogger(OODTConfig.class.getName());
+
+    private URL fmUrl;
+
+    public URL getFmUrl(){
+        return this.fmUrl;
+    }
+
+    private static XmlRpcFileManagerClient client = null;
+
+    public boolean loadXMLRpcClient(String fmUrlStr){
+        try {
+            client = new XmlRpcFileManagerClient(new URL(fmUrlStr));
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE,
+                    "Unable to create file manager client: Message: "
+                            + e.getMessage() + ": errors to follow");
+        }
+        return true;
+    }
+
+    public XmlRpcFileManagerClient getXMLRpcClient(){
+        return client;
+    }
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/OODTProcesses.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/OODTProcesses.java
new file mode 100644
index 0000000..c33bcb7
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/OODTProcesses.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrdelete;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+import java.io.File;
+import java.net.URI;
+import java.util.List;
+
+/**
+ * Created by bugg on 07/03/14.
+ */
+public class OODTProcesses {
+
+    public boolean deleteProductByName(OODTConfig config, String filename) throws Exception {
+        XmlRpcFileManagerClient client = config.getXMLRpcClient();
+        Product p = client.getProductByName(filename);
+        List<Reference> refs = client.getProductReferences(p);
+        if (refs == null) {
+            throw new Exception("FileManager returned null References");
+        }
+        for (Reference ref : refs) {
+            if (!client.removeFile(new File(new URI(ref.getDataStoreReference()))
+                    .getAbsolutePath())) {
+                throw new Exception("Failed to delete file '"
+                        + ref.getDataStoreReference() + "'");
+            }
+        }
+        if (client.removeProduct(p)) {
+          //  printer.println("Successfully deleted product '"
+           //        + p.getProductName() + "'");
+            return true;
+        } else {
+            throw new Exception("Delete product returned false");
+        }
+    }
+
+
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/PushPullObjectFactory.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/PushPullObjectFactory.java
new file mode 100644
index 0000000..a710e1f
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/PushPullObjectFactory.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrdelete;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.ingest.Cache;
+import org.apache.oodt.cas.filemgr.ingest.CacheFactory;
+import org.apache.oodt.cas.filemgr.ingest.Ingester;
+
+//JDK imports
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class PushPullObjectFactory {
+
+    private PushPullObjectFactory() throws InstantiationException {
+        throw new InstantiationException("Don't construct factory classes!");
+    }
+
+    public static <T> T createNewInstance(Class<T> clazz) throws InstantiationException {
+    	try {
+			return clazz.newInstance();
+		} catch (Exception e) {
+            throw new InstantiationException(
+                    "Failed to create new object : "
+                            + e.getMessage());
+		}
+    }
+    
+    public static Ingester createIngester(String ingesterClass,
+            String cacheFactoryClass) throws InstantiationException,
+            IllegalAccessException, ClassNotFoundException,
+            IllegalArgumentException, SecurityException,
+            InvocationTargetException, NoSuchMethodException {
+        String dataTransferFactory = "org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory";
+        System.out.println("TRANSFER: " + dataTransferFactory);
+        if (cacheFactoryClass == null || cacheFactoryClass.equals("")) {
+            return (Ingester) Class.forName(ingesterClass).getConstructor(
+                    dataTransferFactory.getClass()).newInstance(
+                    dataTransferFactory);
+        } else {
+            Class<CacheFactory> cacheFactory = (Class<CacheFactory>) Class
+                    .forName(cacheFactoryClass);
+            Cache cache = cacheFactory.newInstance().createCache();
+            return (Ingester) Class.forName(ingesterClass).getConstructor(
+                    dataTransferFactory.getClass(), cache.getClass())
+                    .newInstance(dataTransferFactory, cache);
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/messages/messages_en_US.properties b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/messages/messages_en_US.properties
new file mode 100644
index 0000000..ef95599
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrdelete/messages/messages_en_US.properties
@@ -0,0 +1,11 @@
+Demo.Shell.Title=Demo step
+Demo.FieldName.Label=Output field name
+Demo.CheckResult.ReceivingRows.OK=Step is receiving input from other steps.
+Demo.CheckResult.ReceivingRows.ERROR=No input received from other steps!
+
+FilemgrDeleteStep.Name=OODT Filemgr File Delete
+FilemgrDeleteStep.TooltipDesc=Remove a file from the file manager
+
+FilemgrDelete.FieldName.Label=Stream Field Name
+FilemgrDelete.ServerURL.Label=Filemgr URL
+FilemgrDelete.Result.Label=Result Field
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/FilemgrGetStep.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/FilemgrGetStep.java
new file mode 100644
index 0000000..eb9cc62
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/FilemgrGetStep.java
@@ -0,0 +1,244 @@
+package org.apache.oodt.filemgrget;
+
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.pentaho.di.core.Const;
+import org.pentaho.di.core.exception.KettleException;
+import org.pentaho.di.core.row.RowMeta;
+import org.pentaho.di.trans.Trans;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.*;
+import sun.util.logging.resources.logging_de;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Map;
+
+import static org.pentaho.di.core.row.RowDataUtil.allocateRowData;
+
+/**
+* Copyright 2014 OSBI Ltd
+*
+* 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.
+*/
+
+/*
+ * 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.
+ */
+
+public class FilemgrGetStep extends BaseStep implements StepInterface {
+
+    private OODTConfig oodt = new OODTConfig();
+    private OODTProcesses oodtproc = new OODTProcesses();
+    private FilemgrGetStepData data;
+    private FilemgrGetStepMeta meta;
+	/**
+	 * The constructor should simply pass on its arguments to the parent class.
+	 * 
+	 * @param s 				step description
+	 * @param stepDataInterface	step data class
+	 * @param c					step copy
+	 * @param t					transformation description
+	 * @param dis				transformation executing
+	 */
+	public FilemgrGetStep(StepMeta s, StepDataInterface stepDataInterface, int c, TransMeta t, Trans dis) {
+		super(s, stepDataInterface, c, t, dis);
+	}
+	
+	/**
+	 * This method is called by PDI during transformation startup. 
+	 * 
+	 * It should initialize required for step execution. 
+	 * 
+	 * The meta and data implementations passed in can safely be cast
+	 * to the step's respective implementations. 
+	 * 
+	 * It is mandatory that super.init() is called to ensure correct behavior.
+	 * 
+	 * Typical tasks executed here are establishing the connection to a database,
+	 * as wall as obtaining resources, like file handles.
+	 * 
+	 * @param smi 	step meta interface implementation, containing the step settings
+	 * @param sdi	step data interface implementation, used to store runtime information
+	 * 
+	 * @return true if initialization completed successfully, false if there was an error preventing the step from working. 
+	 *  
+	 */
+	public boolean init(StepMetaInterface smi, StepDataInterface sdi) {
+		// Casting to step-specific implementation classes is safe
+		meta = (FilemgrGetStepMeta) smi;
+		data = (FilemgrGetStepData) sdi;
+
+
+            logDetailed("loading xmlrpcclient");
+        try {
+            oodt.loadXMLRpcClient(meta.getServerURLField());
+        } catch (MalformedURLException e) {
+            logError("Incorrect URL", e);
+        } catch (ConnectionException e) {
+            logError("There was a problem connecting", e);
+        }
+        logDetailed("finished loading xmlrpcclient");
+
+
+        return super.init(meta, data);
+	}
+
+
+    private Object[] buildEmptyRow() {
+
+        return allocateRowData(data.outputRowMeta.size());
+    }
+
+	/**
+	 * Once the transformation starts executing, the processRow() method is called repeatedly
+	 * by PDI for as long as it returns true. To indicate that a step has finished processing rows
+	 * this method must call setOutputDone() and return false;
+	 *
+	 * Steps which process incoming rows typically call getRow() to read a single row from the
+	 * input stream, change or add row content, call putRow() to pass the changed row on
+	 * and return true. If getRow() returns null, no more rows are expected to come in,
+	 * and the processRow() implementation calls setOutputDone() and returns false to
+	 * indicate that it is done too.
+	 *
+	 * Steps which generate rows typically construct a new row Object[] using a call to
+	 * RowDataUtil.allocateRowData(numberOfFields), add row content, and call putRow() to
+	 * pass the new row on. Above process may happen in a loop to generate multiple rows,
+	 * at the end of which processRow() would call setOutputDone() and return false;
+	 *
+	 * @param smi the step meta interface containing the step settings
+	 * @param sdi the step data interface that should be used to store
+	 *
+	 * @return true to indicate that the function should be called again, false if the step is done
+	 */
+	public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {
+
+
+        if ( first ) {
+            first = false;
+            data.outputRowMeta = new RowMeta();
+            meta.getFields( data.outputRowMeta, getStepname(), null, null, this, repository, metaStore );
+        }
+
+        if(meta.getProcessType() == Process.LIST){
+            try {
+                Map<String, Map<String, String>> products = oodtproc.getAllProducts(oodt, environmentSubstitute(meta.getProductTypeField()));
+                for (Map.Entry<String, Map<String,String>> entry : products.entrySet())
+                {
+                    Object[] row = buildEmptyRow();
+
+                    incrementLinesRead();
+
+                    row[0] = entry.getKey();
+                    int i = 1;
+                    for(Map.Entry<String,String> innerentry : entry.getValue().entrySet()){
+                        row[i] = innerentry.getValue();
+                        i++;
+                    }
+
+                    putRow(data.outputRowMeta, row);
+                }
+
+            } catch (Exception e) {
+                logError("Could not get data", e);
+            }
+
+        }
+        else if(meta.getProcessType() == Process.GET && meta.getSearchType() == Search.ID){
+
+            try {
+                String lookup = meta.getLookup();
+                if(!Const.isEmpty(lookup)){
+                    lookup = environmentSubstitute(lookup);
+                }
+
+                Object[] row = buildEmptyRow();
+                row[0] = oodtproc.getProductByID(oodt, lookup);
+                putRow(data.outputRowMeta, row);
+
+            } catch (CatalogException e) {
+                logError("Catalog Exception", e);
+            } catch (DataTransferException e) {
+                logError("Data Transfer Exception", e);
+            } catch (IOException e) {
+                logError("IO Exception",e);
+            }
+        }
+        else if(meta.getProcessType() == Process.GET && meta.getSearchType() == Search.NAME){
+            try {
+                String lookup = meta.getLookup();
+                if(!Const.isEmpty(lookup)){
+                    lookup = environmentSubstitute(lookup);
+                }
+
+                Object[] row = buildEmptyRow();
+                row[0] = oodtproc.getProductByName(oodt, lookup);
+                putRow(data.outputRowMeta, row);
+            } catch (CatalogException e) {
+                logError("Catalog Exception", e);
+            } catch (DataTransferException e) {
+                logError("Data Transfer Exception", e);
+            } catch (IOException e) {
+                logError("IO Exception", e);
+            }
+        }
+
+
+		// log progress if it is time to to so
+		if (checkFeedback(getLinesRead())) {
+			logBasic("Linenr " + getLinesRead()); // Some basic logging
+		}
+
+		// indicate that processRow() should be called again
+        setOutputDone();
+		return false;
+	}
+
+	/**
+	 * This method is called by PDI once the step is done processing.
+	 *
+	 * The dispose() method is the counterpart to init() and should release any resources
+	 * acquired for step execution like file handles or database connections.
+	 *
+	 * The meta and data implementations passed in can safely be cast
+	 * to the step's respective implementations.
+	 *
+	 * It is mandatory that super.dispose() is called to ensure correct behavior.
+	 *
+	 * @param smi 	step meta interface implementation, containing the step settings
+	 * @param sdi	step data interface implementation, used to store runtime information
+	 */
+	public void dispose(StepMetaInterface smi, StepDataInterface sdi) {
+
+		// Casting to step-specific implementation classes is safe
+		FilemgrGetStepMeta meta = (FilemgrGetStepMeta) smi;
+		FilemgrGetStepData data = (FilemgrGetStepData) sdi;
+		
+		super.dispose(meta, data);
+	}
+
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/FilemgrGetStepData.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/FilemgrGetStepData.java
new file mode 100644
index 0000000..ada2397
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/FilemgrGetStepData.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrget;
+
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.trans.step.BaseStepData;
+import org.pentaho.di.trans.step.StepDataInterface;
+
+/**
+* Copyright 2014 OSBI Ltd
+*
+* 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.
+*/
+public class FilemgrGetStepData extends BaseStepData implements StepDataInterface {
+
+	public RowMetaInterface outputRowMeta;
+
+    public String fieldname;
+
+    public FilemgrGetStepData()
+	{
+		super();
+	}
+}
+	
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/FilemgrGetStepDialog.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/FilemgrGetStepDialog.java
new file mode 100644
index 0000000..c6aaf0b
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/FilemgrGetStepDialog.java
@@ -0,0 +1,438 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrget;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.*;
+import org.pentaho.di.core.Const;
+import org.pentaho.di.i18n.BaseMessages;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.BaseStepMeta;
+import org.pentaho.di.trans.step.StepDialogInterface;
+import org.pentaho.di.ui.core.widget.TextVar;
+import org.pentaho.di.ui.trans.step.BaseStepDialog;
+
+/**
+* Copyright 2014 OSBI Ltd
+*
+* 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.
+*/
+public class FilemgrGetStepDialog extends BaseStepDialog implements StepDialogInterface {
+
+	/**
+	 *	The PKG member is used when looking up internationalized strings.
+	 *	The properties file with localized keys is expected to reside in 
+	 *	{the package of the class specified}/messages/messages_{locale}.properties   
+	 */
+	private static Class<?> PKG = FilemgrGetStepMeta.class; // for i18n purposes
+
+	// this is the object the stores the step's settings
+	// the dialog reads the settings from it when opening
+	// the dialog writes the settings to it when confirmed 
+	private FilemgrGetStepMeta meta;
+
+	// text field holding the name of the field to add to the row stream
+	//private Text wHelloFieldName;
+
+    // text field holding the name of the field to check the filename against
+    private TextVar wFilenameField;
+    private Text wServerURLField;
+    private TextVar wResultField;
+    private Button[] radioButtons2 = new Button[2];
+    private Button[] radioButtons = new Button[2];
+    private Search selectedsearch;
+    private Process selectedprocess;
+    /**
+	 * The constructor should simply invoke super() and save the incoming meta
+	 * object to a local variable, so it can conveniently read and write settings
+	 * from/to it.
+	 * 
+	 * @param parent 	the SWT shell to open the dialog in
+	 * @param in		the meta object holding the step's settings
+	 * @param transMeta	transformation description
+	 * @param sname		the step name
+	 */
+	public FilemgrGetStepDialog(Shell parent, Object in, TransMeta transMeta, String sname) {
+		super(parent, (BaseStepMeta) in, transMeta, sname);
+		meta = (FilemgrGetStepMeta) in;
+	}
+
+	/**
+	 * This method is called by Spoon when the user opens the settings dialog of the step.
+	 * It should open the dialog and return only once the dialog has been closed by the user.
+	 * 
+	 * If the user confirms the dialog, the meta object (passed in the constructor) must
+	 * be updated to reflect the new step settings. The changed flag of the meta object must 
+	 * reflect whether the step configuration was changed by the dialog.
+	 * 
+	 * If the user cancels the dialog, the meta object must not be updated, and its changed flag
+	 * must remain unaltered.
+	 * 
+	 * The open() method must return the name of the step after the user has confirmed the dialog,
+	 * or null if the user cancelled the dialog.
+	 */
+	public String open() {
+
+		// store some convenient SWT variables 
+		Shell parent = getParent();
+		Display display = parent.getDisplay();
+
+		// SWT code for preparing the dialog
+		shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX);
+		props.setLook(shell);
+		setShellImage(shell, meta);
+		
+		// Save the value of the changed flag on the meta object. If the user cancels
+		// the dialog, it will be restored to this saved value.
+		// The "changed" variable is inherited from BaseStepDialog
+		changed = meta.hasChanged();
+		
+		// The ModifyListener used on all controls. It will update the meta object to 
+		// indicate that changes are being made.
+		ModifyListener lsMod = new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				meta.setChanged();
+			}
+		};
+		
+		// ------------------------------------------------------- //
+		// SWT code for building the actual settings dialog        //
+		// ------------------------------------------------------- //
+		FormLayout formLayout = new FormLayout();
+		formLayout.marginWidth = Const.FORM_MARGIN;
+		formLayout.marginHeight = Const.FORM_MARGIN;
+
+		shell.setLayout(formLayout);
+		shell.setText(BaseMessages.getString(PKG, "FilemgrGetStep.Name"));
+
+		int middle = props.getMiddlePct();
+		int margin = Const.MARGIN;
+
+		// Stepname line
+		wlStepname = new Label(shell, SWT.RIGHT);
+		wlStepname.setText(BaseMessages.getString(PKG, "System.Label.StepName")); 
+		props.setLook(wlStepname);
+		fdlStepname = new FormData();
+		fdlStepname.left = new FormAttachment(0, 0);
+		fdlStepname.right = new FormAttachment(middle, -margin);
+		fdlStepname.top = new FormAttachment(0, margin);
+		wlStepname.setLayoutData(fdlStepname);
+		
+		wStepname = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+		wStepname.setText(stepname);
+		props.setLook(wStepname);
+		wStepname.addModifyListener(lsMod);
+		fdStepname = new FormData();
+		fdStepname.left = new FormAttachment(middle, 0);
+		fdStepname.top = new FormAttachment(0, margin);
+		fdStepname.right = new FormAttachment(100, 0);
+		wStepname.setLayoutData(fdStepname);
+
+        // servername field value
+        Label wlServerName = new Label(shell, SWT.RIGHT);
+        wlServerName.setText(BaseMessages.getString(PKG, "FilemgrGet.ServerURL.Label"));
+        props.setLook(wlServerName);
+        FormData fdlServerName = new FormData();
+        fdlServerName.left = new FormAttachment(0, 0);
+        fdlServerName.right = new FormAttachment(middle, -margin);
+        fdlServerName.top = new FormAttachment(wStepname, margin);
+        wlServerName.setLayoutData(fdlServerName);
+
+        wServerURLField = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+        props.setLook(wServerURLField);
+        wServerURLField.addModifyListener(lsMod);
+        FormData fdServerName = new FormData();
+        fdServerName.left = new FormAttachment(middle, 0);
+        fdServerName.right = new FormAttachment(100, 0);
+        fdServerName.top = new FormAttachment(wStepname, margin);
+        wServerURLField.setLayoutData(fdServerName);
+
+		// product type
+		Label wlValName = new Label(shell, SWT.RIGHT);
+		wlValName.setText(BaseMessages.getString(PKG, "FilemgrGet.ProductType.Label"));
+		props.setLook(wlValName);
+		FormData fdlValName = new FormData();
+		fdlValName.left = new FormAttachment(0, 0);
+		fdlValName.right = new FormAttachment(middle, -margin);
+		fdlValName.top = new FormAttachment(wServerURLField, margin);
+		wlValName.setLayoutData(fdlValName);
+
+		wFilenameField = new TextVar(transMeta, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+		props.setLook(wFilenameField);
+		wFilenameField.addModifyListener(lsMod);
+		FormData fdValName = new FormData();
+		fdValName.left = new FormAttachment(middle, 0);
+		fdValName.right = new FormAttachment(100, 0);
+		fdValName.top = new FormAttachment(wServerURLField, margin);
+		wFilenameField.setLayoutData(fdValName);
+
+
+        // processtype value
+        Label wlProcessTypeName = new Label(shell, SWT.RIGHT);
+        wlProcessTypeName.setText(BaseMessages.getString(PKG, "FilemgrGet.ProcessType.Label"));
+        props.setLook(wlProcessTypeName);
+        FormData fdlProcessTypeName = new FormData();
+        fdlProcessTypeName.left = new FormAttachment(0, 0);
+        fdlProcessTypeName.right = new FormAttachment(middle, -margin);
+        fdlProcessTypeName.top = new FormAttachment(wFilenameField, margin);
+        wlProcessTypeName.setLayoutData(fdlProcessTypeName);
+
+        Composite composite = new Composite(shell, SWT.NULL);
+        composite.setLayout(new RowLayout());
+        radioButtons2[0] = new Button(composite, SWT.RADIO);
+        radioButtons2[0].setSelection(true);
+        radioButtons2[0].setText("List Products");
+        radioButtons2[0].pack();
+        radioButtons2[1] = new Button(composite, SWT.RADIO);
+        radioButtons2[1].setSelection(false);
+        radioButtons2[1].setText("Get Product");
+        radioButtons2[1].pack();
+        props.setLook(radioButtons2[0]);
+        props.setLook(radioButtons2[1]);
+
+
+        //wFilenameField.addModifyListener(lsMod);
+        FormData fdProcessTypeName = new FormData();
+        fdProcessTypeName.left = new FormAttachment(middle, 0);
+        fdProcessTypeName.right = new FormAttachment(100, 0);
+        fdProcessTypeName.top = new FormAttachment(wFilenameField, margin);
+        composite.setLayoutData(fdProcessTypeName);
+
+
+        // search type value
+        Label wlSearchName = new Label(shell, SWT.RIGHT);
+        wlSearchName.setText(BaseMessages.getString(PKG, "FilemgrGet.SearchType.Label"));
+        props.setLook(wlSearchName);
+        FormData fdlSearchName = new FormData();
+        fdlSearchName.left = new FormAttachment(0, 0);
+        fdlSearchName.right = new FormAttachment(middle, -margin);
+        fdlSearchName.top = new FormAttachment(composite, margin);
+        wlSearchName.setLayoutData(fdlSearchName);
+
+        Composite composite1 = new Composite(shell, SWT.NULL);
+        composite1.setLayout(new RowLayout());
+        radioButtons[0] = new Button(composite1, SWT.RADIO);
+        radioButtons[0].setSelection(true);
+        radioButtons[0].setText("Name");
+        radioButtons[0].pack();
+        radioButtons[1] = new Button(composite1, SWT.RADIO);
+        radioButtons[1].setSelection(false);
+        radioButtons[1].setText("ID");
+        radioButtons[1].pack();
+        props.setLook(radioButtons[0]);
+        props.setLook(radioButtons[1]);
+        radioButtons[0].addSelectionListener(new SelectionAdapter() {
+            public void widgetSelected(SelectionEvent e) {
+                selectedsearch = Search.NAME;
+            }
+        });
+        radioButtons[1].addSelectionListener(new SelectionAdapter() {
+            public void widgetSelected(SelectionEvent e) {
+                selectedsearch = Search.ID;
+            }
+        });
+
+        FormData fdSearchName = new FormData();
+        fdSearchName.left = new FormAttachment(middle, 0);
+        fdSearchName.right = new FormAttachment(100, 0);
+        fdSearchName.top = new FormAttachment(composite, margin);
+        composite1.setLayoutData(fdSearchName);
+
+        if(meta.getProcessType()==Process.LIST){
+            radioButtons[0].setEnabled(false);
+            radioButtons[1].setEnabled(false);
+        }
+
+
+        // servername field value
+        Label wlResultName = new Label(shell, SWT.RIGHT);
+        wlResultName.setText(BaseMessages.getString(PKG, "FilemgrGet.Result.Label"));
+        props.setLook(wlResultName);
+        FormData fdlResultName = new FormData();
+        fdlResultName.left = new FormAttachment(0, 0);
+        fdlResultName.right = new FormAttachment(middle, -margin);
+        fdlResultName.top = new FormAttachment(composite1, margin);
+        wlResultName.setLayoutData(fdlResultName);
+
+        wResultField = new TextVar(transMeta, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+        props.setLook(wResultField);
+        wResultField.addModifyListener(lsMod);
+        FormData fdResultName = new FormData();
+        fdResultName.left = new FormAttachment(middle, 0);
+        fdResultName.right = new FormAttachment(100, 0);
+        fdResultName.top = new FormAttachment(composite1, margin);
+        wResultField.setLayoutData(fdResultName);
+        wResultField.addModifyListener(new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                wResultField.setToolTipText(transMeta.environmentSubstitute(wResultField.getText()));
+            }
+        });
+
+        if(meta.getProcessType()==Process.LIST){
+            wResultField.setEnabled(false);
+        }
+        // OK and cancel buttons
+		wOK = new Button(shell, SWT.PUSH);
+		wOK.setText(BaseMessages.getString(PKG, "System.Button.OK")); 
+		wCancel = new Button(shell, SWT.PUSH);
+		wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel")); 
+
+		BaseStepDialog.positionBottomButtons(shell, new Button[] { wOK, wCancel }, margin, wResultField);
+
+		// Add listeners for cancel and OK
+		lsCancel = new Listener() {
+			public void handleEvent(Event e) {cancel();}
+		};
+		lsOK = new Listener() {
+			public void handleEvent(Event e) {ok();}
+		};
+
+		wCancel.addListener(SWT.Selection, lsCancel);
+		wOK.addListener(SWT.Selection, lsOK);
+
+        /**
+         * Radio button listeners
+         */
+        radioButtons2[0].addSelectionListener(new SelectionAdapter() {
+            public void widgetSelected(SelectionEvent e) {
+                selectedprocess = Process.LIST;
+                wResultField.setEnabled(false);
+                radioButtons[0].setEnabled(false);
+                radioButtons[1].setEnabled(false);
+
+            }
+        });
+        radioButtons2[1].addSelectionListener(new SelectionAdapter() {
+            public void widgetSelected(SelectionEvent e) {
+                selectedprocess = Process.GET;
+                radioButtons[0].setEnabled(true);
+                radioButtons[1].setEnabled(true);
+                wResultField.setEnabled(true);
+            }
+        });
+
+		// default listener (for hitting "enter")
+		lsDef = new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {ok();}
+		};
+		wStepname.addSelectionListener(lsDef);
+		wFilenameField.addSelectionListener(lsDef);
+        wServerURLField.addSelectionListener(lsDef);
+        wResultField.addSelectionListener(lsDef);
+		// Detect X or ALT-F4 or something that kills this window and cancel the dialog properly
+		shell.addShellListener(new ShellAdapter() {
+			public void shellClosed(ShellEvent e) {cancel();}
+		});
+		
+		// Set/Restore the dialog size based on last position on screen
+		// The setSize() method is inherited from BaseStepDialog
+		setSize();
+
+		// populate the dialog with the values from the meta object
+		populateDialog();
+		
+		// restore the changed flag to original value, as the modify listeners fire during dialog population 
+		meta.setChanged(changed);
+
+		// open dialog and enter event loop 
+		shell.open();
+		while (!shell.isDisposed()) {
+			if (!display.readAndDispatch())
+				display.sleep();
+		}
+
+		// at this point the dialog has closed, so either ok() or cancel() have been executed
+		// The "stepname" variable is inherited from BaseStepDialog
+		return stepname;
+	}
+	
+	/**
+	 * This helper method puts the step configuration stored in the meta object
+	 * and puts it into the dialog controls.
+	 */
+	private void populateDialog() {
+		wStepname.selectAll();
+		wFilenameField.setText(meta.getProductTypeField());
+        wServerURLField.setText(meta.getServerURLField());
+        wResultField.setText(meta.getResultField());
+        if(meta.getSearchType() == Search.NAME){
+            radioButtons[0].setSelection(true);
+            radioButtons[1].setSelection(false);
+            selectedsearch = Search.NAME;
+        }
+        else{
+            radioButtons[1].setSelection(true);
+            radioButtons[0].setSelection(false);
+            selectedsearch = Search.ID;
+        }
+
+        if(meta.getProcessType() == Process.LIST){
+            radioButtons2[0].setSelection(true);
+            radioButtons2[1].setSelection(false);
+            selectedprocess= Process.LIST;
+        }
+        else{
+            radioButtons2[1].setSelection(true);
+            radioButtons2[0].setSelection(false);
+            selectedprocess = Process.GET;
+        }
+
+	}
+
+	/**
+	 * Called when the user cancels the dialog.  
+	 */
+	private void cancel() {
+		// The "stepname" variable will be the return value for the open() method. 
+		// Setting to null to indicate that dialog was cancelled.
+		stepname = null;
+		// Restoring original "changed" flag on the met aobject
+		meta.setChanged(changed);
+		// close the SWT dialog window
+		dispose();
+	}
+	
+	/**
+	 * Called when the user confirms the dialog
+	 */
+	private void ok() {
+		stepname = wStepname.getText(); 
+        meta.setProductName(wFilenameField.getText());
+        meta.setServerURLField(wServerURLField.getText());
+        meta.setResultField(wResultField.getText());
+        meta.setProcessType(selectedprocess);
+        meta.setSearchType(selectedsearch);
+		// close the SWT dialog window
+		dispose();
+	}
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/FilemgrGetStepMeta.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/FilemgrGetStepMeta.java
new file mode 100644
index 0000000..3b295fc
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/FilemgrGetStepMeta.java
@@ -0,0 +1,410 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrget;
+
+import org.eclipse.swt.widgets.Shell;
+import org.pentaho.di.core.CheckResult;
+import org.pentaho.di.core.CheckResultInterface;
+import org.pentaho.di.core.annotations.Step;
+import org.pentaho.di.core.database.DatabaseMeta;
+import org.pentaho.di.core.exception.KettleException;
+import org.pentaho.di.core.exception.KettleStepException;
+import org.pentaho.di.core.exception.KettleValueException;
+import org.pentaho.di.core.exception.KettleXMLException;
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.core.row.ValueMeta;
+import org.pentaho.di.core.row.ValueMetaInterface;
+import org.pentaho.di.core.variables.VariableSpace;
+import org.pentaho.di.core.xml.XMLHandler;
+import org.pentaho.di.i18n.BaseMessages;
+import org.pentaho.di.repository.ObjectId;
+import org.pentaho.di.repository.Repository;
+import org.pentaho.di.trans.Trans;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.*;
+import org.pentaho.metastore.api.IMetaStore;
+import org.w3c.dom.Node;
+
+import java.util.List;
+
+/**
+* Copyright 2014 OSBI Ltd
+*
+* 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.
+*/
+
+@Step(	
+		id = "FilemgrGet",
+        image = "org/apache/oodt/filemgrcheck/resources/check/oodt.jpg",
+		i18nPackageName="bi.meteorite.filemgrget",
+		name="FilemgrGetStep.Name",
+		description = "FilemgrGetStep.TooltipDesc",
+		categoryDescription="i18n:org.pentaho.di.trans.step:BaseStep.Category.BigData"
+)
+public class FilemgrGetStepMeta extends BaseStepMeta implements StepMetaInterface {
+
+	/**
+	 *	The PKG member is used when looking up internationalized strings.
+	 *	The properties file with localized keys is expected to reside in 
+	 *	{the package of the class specified}/messages/messages_{locale}.properties   
+	 */
+	private static Class<?> PKG = FilemgrGetStepMeta.class; // for i18n purposes
+	
+	/**
+	 * Stores the name of the field added to the row-stream. 
+	 */
+	private String outputField;
+    private String productName;
+    private String serverURLField;
+    private String resultField;
+    private Search searchtypeField;
+    private Process processtypeField;
+
+    /**
+	 * Constructor should call super() to make sure the base class has a chance to initialize properly.
+	 */
+	public FilemgrGetStepMeta() {
+		super(); 
+	}
+	
+	/**
+	 * Called by Spoon to get a new instance of the SWT dialog for the step.
+	 * A standard implementation passing the arguments to the constructor of the step dialog is recommended.
+	 * 
+	 * @param shell		an SWT Shell
+	 * @param meta 		description of the step 
+	 * @param transMeta	description of the the transformation 
+	 * @param name		the name of the step
+	 * @return 			new instance of a dialog for this step 
+	 */
+	public StepDialogInterface getDialog(Shell shell, StepMetaInterface meta, TransMeta transMeta, String name) {
+		return new FilemgrGetStepDialog(shell, meta, transMeta, name);
+	}
+
+	/**
+	 * Called by PDI to get a new instance of the step implementation. 
+	 * A standard implementation passing the arguments to the constructor of the step class is recommended.
+	 * 
+gf	 * @param stepMeta				description of the step
+	 * @param stepDataInterface		instance of a step data class
+	 * @param cnr					copy number
+	 * @param transMeta				description of the transformation
+	 * @param disp					runtime implementation of the transformation
+	 * @return						the new instance of a step implementation 
+	 */
+	public StepInterface getStep(StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr, TransMeta transMeta, Trans disp) {
+		return new FilemgrGetStep(stepMeta, stepDataInterface, cnr, transMeta, disp);
+	}
+
+	/**
+	 * Called by PDI to get a new instance of the step data class.
+	 */
+	public StepDataInterface getStepData() {
+		return new FilemgrGetStepData();
+	}	
+
+	/**
+	 * This method is called every time a new step is created and should allocate/set the step configuration
+	 * to sensible defaults. The values set here will be used by Spoon when a new step is created.    
+	 */
+	public void setDefault() {
+		outputField = "demo_field";
+        serverURLField = "http://localhost:9000";
+        resultField = "result";
+        productName = "GenericFile";
+        searchtypeField = Search.NAME;
+        processtypeField = Process.LIST;
+	}
+	
+	/**
+	 * Getter for the name of the field added by this step
+	 * @return the name of the field added
+	 */
+        public String getOutputField() {
+		return outputField;
+	}
+
+	/**
+	 * Setter for the name of the field added by this step
+	 * @param outputField the name of the field added
+	 */
+	public void setOutputField(String outputField) {
+		this.outputField = outputField;
+	}
+
+
+    public String getProductTypeField(){
+        return productName;
+    }
+
+    public void setProductName(String productName){
+        this.productName = productName;
+    }
+	/**
+	 * This method is used when a step is duplicated in Spoon. It needs to return a deep copy of this
+	 * step meta object. Be sure to create proper deep copies if the step configuration is stored in
+	 * modifiable objects.
+	 * 
+	 * See org.pentaho.di.trans.steps.rowgenerator.RowGeneratorMeta.clone() for an example on creating
+	 * a deep copy.
+	 * 
+	 * @return a deep copy of this
+	 */
+	public Object clone() {
+        return super.clone();
+	}
+	
+	/**
+	 * This method is called by Spoon when a step needs to serialize its configuration to XML. The expected
+	 * return value is an XML fragment consisting of one or more XML tags.  
+	 * 
+	 * Please use org.pentaho.di.core.xml.XMLHandler to conveniently generate the XML.
+	 * 
+	 * @return a string containing the XML serialization of this step
+	 */
+	public String getXML() throws KettleValueException {
+		
+		// only one field to serialize
+		String xml =  " ";
+        xml += "    " +XMLHandler.addTagValue("outputfield", outputField);
+        xml += "    " +XMLHandler.addTagValue("filenamefield", productName);
+        xml += "    " +XMLHandler.addTagValue("serverurlfield", serverURLField);
+        xml += "    " +XMLHandler.addTagValue("resultfield", resultField);
+        xml += "    " +XMLHandler.addTagValue("producttypefield", productName);
+        xml += "    " +XMLHandler.addTagValue("searchtypefield", searchtypeField.toString());
+        xml += "    " +XMLHandler.addTagValue("processtypefield", processtypeField.toString());
+		return xml;
+	}
+
+	/**
+	 * This method is called by PDI when a step needs to load its configuration from XML.
+	 * 
+	 * Please use org.pentaho.di.core.xml.XMLHandler to conveniently read from the
+	 * XML node passed in.
+	 * 
+	 * @param stepnode	the XML node containing the configuration
+	 * @param databases	the databases available in the transformation
+	 * @param metaStore the metaStore to optionally read from
+	 */
+	public void loadXML(Node stepnode, List<DatabaseMeta> databases, IMetaStore metaStore) throws KettleXMLException {
+
+		try {
+			setOutputField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "outputfield")));
+            setProductName(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "filenamefield")));
+            setServerURLField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "serverurlfield")));
+            setResultField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "resultfield")));
+            setProductName(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "producttypefield")));
+            setSearchType(Search.valueOf(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "searchtypefield"))));
+            setProcessType(Process.valueOf(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "processtypefield"))));
+
+        } catch (Exception e) {
+			throw new KettleXMLException("Demo plugin unable to read step info from XML node", e);
+		}
+
+	}	
+	/**
+	 * This method is called by Spoon when a step needs to serialize its configuration to a repository.
+	 * The repository implementation provides the necessary methods to save the step attributes.
+	 *
+	 * @param rep					the repository to save to
+	 * @param metaStore				the metaStore to optionally write to
+	 * @param id_transformation		the id to use for the transformation when saving
+	 * @param id_step				the id to use for the step  when saving
+	 */
+	public void saveRep(Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step) throws KettleException
+	{
+		try{
+			rep.saveStepAttribute(id_transformation, id_step, "outputfield", outputField); //$NON-NLS-1$
+		}
+		catch(Exception e){
+			throw new KettleException("Unable to save step into repository: "+id_step, e); 
+		}
+	}		
+	
+	/**
+	 * This method is called by PDI when a step needs to read its configuration from a repository.
+	 * The repository implementation provides the necessary methods to read the step attributes.
+	 * 
+	 * @param rep		the repository to read from
+	 * @param metaStore	the metaStore to optionally read from
+	 * @param id_step	the id of the step being read
+	 * @param databases	the databases available in the transformation
+	 */
+	public void readRep(Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases) throws KettleException  {
+		try{
+			outputField  = rep.getStepAttributeString(id_step, "outputfield"); //$NON-NLS-1$
+		}
+		catch(Exception e){
+			throw new KettleException("Unable to load step from repository", e);
+		}
+	}
+
+	/**
+	 * This method is called to determine the changes the step is making to the row-stream.
+	 * To that end a RowMetaInterface object is passed in, containing the row-stream structure as it is when entering
+	 * the step. This method must apply any changes the step makes to the row stream. Usually a step adds fields to the
+	 * row-stream.
+	 * 
+	 * @param inputRowMeta		the row structure coming in to the step
+	 * @param name 				the name of the step making the changes
+	 * @param info				row structures of any info steps coming in
+	 * @param nextStep			the description of a step this step is passing rows to
+	 * @param space				the variable space for resolving variables
+	 * @param repository		the repository instance optionally read from
+	 * @param metaStore			the metaStore to optionally read from
+	 */
+	public void getFields(RowMetaInterface inputRowMeta, String name, RowMetaInterface[] info, StepMeta nextStep, VariableSpace space, Repository repository, IMetaStore metaStore) throws KettleStepException{
+
+		/*
+		 * This implementation appends the outputField to the row-stream
+		 */
+        if(getProcessType() == Process.LIST){
+		// a value meta object contains the meta data for a field
+		ValueMetaInterface v = new ValueMeta("id", ValueMeta.TYPE_STRING);
+		
+		// setting trim type to "both"
+		v.setTrimType(ValueMeta.TRIM_TYPE_BOTH);
+
+		// the name of the step that adds this field
+		v.setOrigin(name);
+		
+		// modify the row structure and add the field this step generates  
+		inputRowMeta.addValueMeta(v);
+
+        ValueMetaInterface v2 = new ValueMeta("type", ValueMeta.TYPE_STRING);
+        v2.setTrimType(ValueMeta.TRIM_TYPE_BOTH);
+        v2.setOrigin(name);
+        inputRowMeta.addValueMeta(v2);
+
+        ValueMetaInterface v3 = new ValueMeta("name", ValueMeta.TYPE_STRING);
+        v3.setTrimType(ValueMeta.TRIM_TYPE_BOTH);
+        v3.setOrigin(name);
+        inputRowMeta.addValueMeta(v3);
+
+        ValueMetaInterface v4 = new ValueMeta("structure", ValueMeta.TYPE_STRING);
+        v4.setTrimType(ValueMeta.TRIM_TYPE_BOTH);
+        v4.setOrigin(name);
+        inputRowMeta.addValueMeta(v4);
+
+        ValueMetaInterface v5 = new ValueMeta("transferstatus", ValueMeta.TYPE_STRING);
+        v5.setTrimType(ValueMeta.TRIM_TYPE_BOTH);
+        v5.setOrigin(name);
+        inputRowMeta.addValueMeta(v5);
+
+        ValueMetaInterface v6 = new ValueMeta("metadata", ValueMeta.TYPE_STRING);
+        v6.setTrimType(ValueMeta.TRIM_TYPE_BOTH);
+        v6.setOrigin(name);
+        inputRowMeta.addValueMeta(v6);
+        }
+        else{
+            ValueMetaInterface v6 = new ValueMeta("export", ValueMeta.TYPE_STRING);
+            v6.setTrimType(ValueMeta.TRIM_TYPE_BOTH);
+            v6.setOrigin(name);
+            inputRowMeta.addValueMeta(v6);
+        }
+	}
+
+	/**
+	 * This method is called when the user selects the "Verify Transformation" option in Spoon. 
+	 * A list of remarks is passed in that this method should add to. Each remark is a comment, warning, error, or ok.
+	 * The method should perform as many checks as necessary to catch design-time errors.
+	 * 
+	 * Typical checks include:
+	 * - verify that all mandatory configuration is given
+	 * - verify that the step receives any input, unless it's a row generating step
+	 * - verify that the step does not receive any input if it does not take them into account
+	 * - verify that the step finds fields it relies on in the row-stream
+	 * 
+	 *   @param remarks		the list of remarks to append to
+	 *   @param transMeta	the description of the transformation
+	 *   @param stepMeta	the description of the step
+	 *   @param prev		the structure of the incoming row-stream
+	 *   @param input		names of steps sending input to the step
+	 *   @param output		names of steps this step is sending output to
+	 *   @param info		fields coming in from info steps 
+	 *   @param metaStore	metaStore to optionally read from
+	 */
+	public void check(List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepMeta, RowMetaInterface prev, String input[], String output[], RowMetaInterface info, VariableSpace space, Repository repository, IMetaStore metaStore)  {
+		
+		CheckResult cr;
+
+		// See if there are input streams leading to this step!
+		if (input.length > 0) {
+			cr = new CheckResult(CheckResult.TYPE_RESULT_OK, BaseMessages.getString(PKG, "Demo.CheckResult.ReceivingRows.OK"), stepMeta);
+			remarks.add(cr);
+		} else {
+			cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, BaseMessages.getString(PKG, "Demo.CheckResult.ReceivingRows.ERROR"), stepMeta);
+			remarks.add(cr);
+		}	
+    	
+	}
+
+
+    public void setServerURLField(String serverURLField) {
+        this.serverURLField = serverURLField;
+    }
+
+    public String getServerURLField() {
+        return serverURLField;
+    }
+
+
+    public void setResultField(String resultField) {
+        this.resultField = resultField;
+    }
+
+    public String getResultField() {
+        return resultField;
+    }
+
+
+    public Process getProcessType() {
+
+        return processtypeField;
+    }
+
+    public void setProcessType(Process processtypeField){
+        this.processtypeField = processtypeField;
+    }
+
+    public Search getSearchType() {
+        return searchtypeField;
+    }
+
+    public void setSearchType(Search searchType){
+        this.searchtypeField = searchType;
+    }
+
+    public String getLookup() {
+        return resultField;
+    }
+
+    public void setLookup(String lookup){
+        this.resultField = lookup;
+    }
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/OODTConfig.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/OODTConfig.java
new file mode 100644
index 0000000..dc295f9
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/OODTConfig.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrget;
+
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+* Copyright 2014 OSBI Ltd
+*
+* 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.
+*/
+public class OODTConfig {
+
+   private static final Logger LOG = Logger.getLogger(OODTConfig.class.getName());
+
+    private static XmlRpcFileManagerClient client = null;
+
+    public boolean loadXMLRpcClient(String fmUrlStr) throws MalformedURLException, ConnectionException {
+
+            client = new XmlRpcFileManagerClient(new URL(fmUrlStr), true);
+
+        return true;
+    }
+
+    public XmlRpcFileManagerClient getXMLRpcClient(){
+        return client;
+    }
+
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/OODTProcesses.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/OODTProcesses.java
new file mode 100644
index 0000000..b1b47ad
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/OODTProcesses.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrget;
+
+import com.google.gson.Gson;
+import org.apache.oodt.cas.filemgr.datatransfer.DataTransfer;
+import org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Copyright 2014 OSBI Ltd
+ * <p/>
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.
+ */
+public class OODTProcesses {
+
+
+    public Map<String, Map<String, String>> getAllProducts(OODTConfig config, String productTypeName) throws Exception {
+        XmlRpcFileManagerClient client = config.getXMLRpcClient();
+        ProductType type = client.getProductTypeByName(productTypeName);
+        if (type == null) {
+            throw new Exception("FileManager returned null ProductType");
+        }
+        ProductPage firstPage = client.getFirstPage(type);
+        if (firstPage == null) {
+            throw new Exception("FileManager returned null product page");
+        }
+
+        Map<String, Map<String, String>> o = new HashMap<String, Map<String, String>>();
+
+        for (int pid = 0; pid < firstPage.getTotalPages(); pid++) {
+            if (pid > 0) {
+                firstPage = client.getNextPage(type, firstPage);
+            }
+            for (Product p : firstPage.getPageProducts()) {
+                Metadata met = client.getMetadata(p);
+
+                Map<String, String> h = new HashMap<String, String>();
+                h.put("name", p.getProductName());
+                h.put("type", p.getProductType().getName());
+                h.put("structure", p.getProductStructure());
+                h.put("transferstatus", p.getTransferStatus());
+                Gson g = new Gson();
+                String json = g.toJson(met.getHashtable());
+                h.put("metadata", json);
+                o.put(p.getProductId(), h);
+
+            }
+
+        }
+        return o;
+
+    }
+
+
+    public String getProductByID(OODTConfig config, String id) throws CatalogException, IOException, DataTransferException {
+        Product product = config.getXMLRpcClient().getProductById(id);
+        product.setProductReferences(config.getXMLRpcClient().getProductReferences(product));
+        LocalDataTransferFactory ldtf = new LocalDataTransferFactory();
+        DataTransfer dt = ldtf.createDataTransfer();
+        String rand = UUID.randomUUID().toString();
+        File theDir = new File("/tmp/oodt/" + rand);
+        boolean mkdir = false;
+        if (!theDir.exists()) {
+            mkdir = theDir.mkdir();
+        }
+        if (mkdir) {
+            dt.retrieveProduct(product, new File("/tmp/oodt/" + rand));
+            return "/tmp/oodt/" + rand + "/" + product.getProductName();
+        } else {
+            return null;
+        }
+    }
+
+    public String getProductByName(OODTConfig config, String name) throws CatalogException, IOException, DataTransferException {
+        Product product = config.getXMLRpcClient().getProductByName(name);
+        product.setProductReferences(config.getXMLRpcClient().getProductReferences(product));
+        LocalDataTransferFactory ldtf = new LocalDataTransferFactory();
+        DataTransfer dt = ldtf.createDataTransfer();
+        String rand = UUID.randomUUID().toString();
+        File theDir = new File("/tmp/oodt/" + rand);
+        boolean mkdir = false;
+        if (!theDir.exists()) {
+            mkdir = theDir.mkdir();
+        }
+        if (mkdir) {
+            dt.retrieveProduct(product, new File("/tmp/oodt/" + rand));
+            return "/tmp/oodt/" + rand + "/" + product.getProductName();
+        } else {
+            return null;
+        }
+
+    }
+
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/Process.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/Process.java
new file mode 100644
index 0000000..a780e0f
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/Process.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrget;
+
+/**
+* Copyright 2014 OSBI Ltd
+*
+* 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.
+*/
+public enum Process {
+    LIST,GET
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/Search.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/Search.java
new file mode 100644
index 0000000..d3cd5ad
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/Search.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgrget;
+
+/**
+* Copyright 2014 OSBI Ltd
+*
+* 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.
+*/
+public enum Search {
+    NAME,ID
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/messages/messages_en_US.properties b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/messages/messages_en_US.properties
new file mode 100644
index 0000000..f40155a
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/messages/messages_en_US.properties
@@ -0,0 +1,9 @@
+FilemgrGetStep.Name=OODT Filemgr File Get
+FilemgrGetStep.TooltipDesc=Get the file from the repository
+
+FilemgrGet.ProductType.Label=Product Type Field
+FilemgrGet.ProcessType.Label=Process Type
+FilemgrGet.SearchType.Label=Search Type
+FilemgrGet.FieldName.Label=Product Type
+FilemgrGet.ServerURL.Label=Filemgr URL
+FilemgrGet.Result.Label=Product Name/ID
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/resources/get/oodt.jpg b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/resources/get/oodt.jpg
new file mode 100644
index 0000000..5810409
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/resources/get/oodt.jpg
Binary files differ
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/resources/get/oodt.png b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/resources/get/oodt.png
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgrget/resources/get/oodt.png
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/FilemgrIngestStep.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/FilemgrIngestStep.java
new file mode 100644
index 0000000..db91055
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/FilemgrIngestStep.java
@@ -0,0 +1,216 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.filemgringest;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.pentaho.di.core.exception.KettleException;
+import org.pentaho.di.core.row.RowDataUtil;
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.trans.Trans;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.*;
+
+import java.io.File;
+import java.util.Arrays;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI. 
+ * 
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *   
+ * This class is the implementation of StepInterface.
+ * Classes implementing this interface need to:
+ * 
+ * - initialize the step
+ * - execute the row processing logic
+ * - dispose of the step 
+ * 
+ * Please do not create any local fields in a StepInterface class. Store any
+ * information related to the processing logic in the supplied step data interface
+ * instead.  
+ * 
+ */
+
+public class FilemgrIngestStep extends BaseStep implements StepInterface {
+
+    private OODTConfig oodt = new OODTConfig();
+    private OODTProcesses oodtproc = new OODTProcesses();
+	/**
+	 * The constructor should simply pass on its arguments to the parent class.
+	 * 
+	 * @param s 				step description
+	 * @param stepDataInterface	step data class
+	 * @param c					step copy
+	 * @param t					transformation description
+	 * @param t					transformation description
+	 * @param dis				transformation executing
+	 */
+	public FilemgrIngestStep(StepMeta s, StepDataInterface stepDataInterface, int c, TransMeta t, Trans dis) {
+		super(s, stepDataInterface, c, t, dis);
+	}
+	
+	/**
+	 * This method is called by PDI during transformation startup. 
+	 * 
+	 * It should initialize required for step execution. 
+	 * 
+	 * The meta and data implementations passed in can safely be cast
+	 * to the step's respective implementations. 
+	 * 
+	 * It is mandatory that super.init() is called to ensure correct behavior.
+	 * 
+	 * Typical tasks executed here are establishing the connection to a database,
+	 * as wall as obtaining resources, like file handles.
+	 * 
+	 * @param smi 	step meta interface implementation, containing the step settings
+	 * @param sdi	step data interface implementation, used to store runtime information
+	 * 
+	 * @return true if initialization completed successfully, false if there was an error preventing the step from working. 
+	 *  
+	 */
+	public boolean init(StepMetaInterface smi, StepDataInterface sdi) {
+		// Casting to step-specific implementation classes is safe
+		FilemgrIngestStepMeta meta = (FilemgrIngestStepMeta) smi;
+		FilemgrIngestStepData data = (FilemgrIngestStepData) sdi;
+
+        try {
+            oodt.loadIngester(meta.getServerURLField());
+        } catch (InstantiationException e) {
+            logError(e.getMessage());
+
+        }
+
+        return super.init(meta, data);
+	}
+
+	/**
+	 * Once the transformation starts executing, the processRow() method is called repeatedly
+	 * by PDI for as long as it returns true. To indicate that a step has finished processing rows
+	 * this method must call setOutputDone() and return false;
+	 *
+	 * Steps which process incoming rows typically call getRow() to read a single row from the
+	 * input stream, change or add row content, call putRow() to pass the changed row on
+	 * and return true. If getRow() returns null, no more rows are expected to come in,
+	 * and the processRow() implementation calls setOutputDone() and returns false to
+	 * indicate that it is done too.
+	 *
+	 * Steps which generate rows typically construct a new row Object[] using a call to
+	 * RowDataUtil.allocateRowData(numberOfFields), add row content, and call putRow() to
+	 * pass the new row on. Above process may happen in a loop to generate multiple rows,
+	 * at the end of which processRow() would call setOutputDone() and return false;
+	 *
+	 * @param smi the step meta interface containing the step settings
+	 * @param sdi the step data interface that should be used to store
+	 *
+	 * @return true to indicate that the function should be called again, false if the step is done
+	 */
+	public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {
+
+		// safely cast the step settings (meta) and runtime info (data) to specific implementations
+		FilemgrIngestStepMeta meta = (FilemgrIngestStepMeta) smi;
+        FilemgrIngestStepData data = (FilemgrIngestStepData) sdi;
+
+		// get incoming row, getRow() potentially blocks waiting for more rows, returns null if no more rows expected
+		Object[] r = getRow();
+
+		// if no more rows are expected, indicate step is finished and processRow() should not be called again
+		if (r == null){
+			setOutputDone();
+			return false;
+		}
+
+		// the "first" flag is inherited from the base step implementation
+		// it is used to guard some processing tasks, like figuring out field indexes
+		// in the row structure that only need to be done once
+		if (first) {
+			first = false;
+			// clone the input row structure and place it in our data object
+			data.outputRowMeta = (RowMetaInterface) getInputRowMeta().clone();
+			// use meta.getFields() to change it, so it reflects the output row structure
+			meta.getFields(data.outputRowMeta, getStepname(), null, null, this, null, null);
+		}
+
+        String[] names = getInputRowMeta().getFieldNames();
+        int idx = Arrays.asList(names).indexOf(meta.getFilenameField());
+        int idx2 = Arrays.asList(names).indexOf(meta.getMetadataField());
+
+
+
+        /*try {
+            logError("does file exist?"+oodtproc.isAlreadyInDatabase(oodt, (String)r[idx]));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }*/
+
+        try {
+
+		  System.setProperty("org.apache.oodt.cas.filemgr.mime.type.repository", "/tmp/mime-types.xml");
+		  Metadata m = oodtproc.getMetadata((String)r[idx2]);
+          String productid = oodtproc.ingest(oodt, new File((String)r[idx]), m);
+
+
+        // safely add the string "Hello World!" at the end of the output row
+		// the row array will be resized if necessary
+		    Object[] outputRow = RowDataUtil.addValueData(r, data.outputRowMeta.size() - 1, productid);
+
+		// put the row to the output row stream
+		putRow(data.outputRowMeta, outputRow);
+
+		// log progress if it is time to to so
+		if (checkFeedback(getLinesRead())) {
+			logBasic("Linenr " + getLinesRead()); // Some basic logging
+		}
+
+		// indicate that processRow() should be called again
+
+		} catch (Exception e) {
+		  logError(ExceptionUtils.getStackTrace(e));
+		  putError(getInputRowMeta(), r, 1L, e.getMessage(), null,
+			  "ERR_OODTINGEST_OUTPUT_01");
+		}
+	  return true;
+	}
+
+	/**
+	 * This method is called by PDI once the step is done processing.
+	 *
+	 * The dispose() method is the counterpart to init() and should release any resources
+	 * acquired for step execution like file handles or database connections.
+	 *
+	 * The meta and data implementations passed in can safely be cast
+	 * to the step's respective implementations.
+	 *
+	 * It is mandatory that super.dispose() is called to ensure correct behavior.
+	 *
+	 * @param smi 	step meta interface implementation, containing the step settings
+	 * @param sdi	step data interface implementation, used to store runtime information
+	 */
+	public void dispose(StepMetaInterface smi, StepDataInterface sdi) {
+
+		// Casting to step-specific implementation classes is safe
+		FilemgrIngestStepMeta meta = (FilemgrIngestStepMeta) smi;
+        FilemgrIngestStepData data = (FilemgrIngestStepData) sdi;
+		
+		super.dispose(meta, data);
+	}
+
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/FilemgrIngestStepData.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/FilemgrIngestStepData.java
new file mode 100644
index 0000000..c5fba4f
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/FilemgrIngestStepData.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.filemgringest;
+
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.trans.step.BaseStepData;
+import org.pentaho.di.trans.step.StepDataInterface;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI. 
+ * 
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *   
+ * This class is the implementation of StepDataInterface.
+ *   
+ * Implementing classes inherit from BaseStepData, which implements the entire
+ * interface completely. 
+ * 
+ * In addition classes implementing this interface usually keep track of
+ * per-thread resources during step execution. Typical examples are:
+ * result sets, temporary data, caching indexes, etc.
+ *   
+ * The implementation for the demo step stores the output row structure in 
+ * the data class. 
+ *   
+ */
+public class FilemgrIngestStepData extends BaseStepData implements StepDataInterface {
+
+	public RowMetaInterface outputRowMeta;
+
+    public String fieldname;
+
+    public FilemgrIngestStepData()
+	{
+		super();
+	}
+}
+	
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/FilemgrIngestStepDialog.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/FilemgrIngestStepDialog.java
new file mode 100644
index 0000000..c08d6d0
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/FilemgrIngestStepDialog.java
@@ -0,0 +1,388 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.filemgringest;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CCombo;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.*;
+import org.pentaho.di.core.Const;
+import org.pentaho.di.core.exception.KettleStepException;
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.core.row.ValueMetaInterface;
+import org.pentaho.di.i18n.BaseMessages;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.BaseStepMeta;
+import org.pentaho.di.trans.step.StepDialogInterface;
+import org.pentaho.di.trans.step.StepMeta;
+import org.pentaho.di.ui.trans.step.BaseStepDialog;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI. 
+ * 
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *   
+ * This class is the implementation of StepDialogInterface.
+ * Classes implementing this interface need to:
+ * 
+ * - build and open a SWT dialog displaying the step's settings (stored in the step's meta object)
+ * - write back any changes the user makes to the step's meta object
+ * - report whether the user changed any settings when confirming the dialog 
+ * 
+ */
+public class FilemgrIngestStepDialog extends BaseStepDialog implements StepDialogInterface {
+
+	/**
+	 *	The PKG member is used when looking up internationalized strings.
+	 *	The properties file with localized keys is expected to reside in 
+	 *	{the package of the class specified}/messages/messages_{locale}.properties   
+	 */
+	private static Class<?> PKG = FilemgrIngestStepMeta.class; // for i18n purposes
+
+	// this is the object the stores the step's settings
+	// the dialog reads the settings from it when opening
+	// the dialog writes the settings to it when confirmed 
+	private FilemgrIngestStepMeta meta;
+
+	// text field holding the name of the field to add to the row stream
+	//private Text wHelloFieldName;
+
+    // text field holding the name of the field to check the filename against
+    private CCombo wFilenameField;
+    private Text wServerURLField;
+    private Text wResultField;
+    private CCombo wMetadataField;
+  private Button m_getFieldsBut;
+
+  /**
+	 * The constructor should simply invoke super() and save the incoming meta
+	 * object to a local variable, so it can conveniently read and write settings
+	 * from/to it.
+	 * 
+	 * @param parent 	the SWT shell to open the dialog in
+	 * @param in		the meta object holding the step's settings
+	 * @param transMeta	transformation description
+	 * @param sname		the step name
+	 */
+	public FilemgrIngestStepDialog(Shell parent, Object in, TransMeta transMeta, String sname) {
+		super(parent, (BaseStepMeta) in, transMeta, sname);
+		meta = (FilemgrIngestStepMeta) in;
+	}
+
+	/**
+	 * This method is called by Spoon when the user opens the settings dialog of the step.
+	 * It should open the dialog and return only once the dialog has been closed by the user.
+	 * 
+	 * If the user confirms the dialog, the meta object (passed in the constructor) must
+	 * be updated to reflect the new step settings. The changed flag of the meta object must 
+	 * reflect whether the step configuration was changed by the dialog.
+	 * 
+	 * If the user cancels the dialog, the meta object must not be updated, and its changed flag
+	 * must remain unaltered.
+	 * 
+	 * The open() method must return the name of the step after the user has confirmed the dialog,
+	 * or null if the user cancelled the dialog.
+	 */
+	public String open() {
+
+		// store some convenient SWT variables 
+		Shell parent = getParent();
+		Display display = parent.getDisplay();
+
+		// SWT code for preparing the dialog
+		shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX);
+		props.setLook(shell);
+		setShellImage(shell, meta);
+		
+		// Save the value of the changed flag on the meta object. If the user cancels
+		// the dialog, it will be restored to this saved value.
+		// The "changed" variable is inherited from BaseStepDialog
+		changed = meta.hasChanged();
+		
+		// The ModifyListener used on all controls. It will update the meta object to 
+		// indicate that changes are being made.
+		ModifyListener lsMod = new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				meta.setChanged();
+			}
+		};
+		
+		// ------------------------------------------------------- //
+		// SWT code for building the actual settings dialog        //
+		// ------------------------------------------------------- //
+		FormLayout formLayout = new FormLayout();
+		formLayout.marginWidth = Const.FORM_MARGIN;
+		formLayout.marginHeight = Const.FORM_MARGIN;
+
+		shell.setLayout(formLayout);
+		shell.setText(BaseMessages.getString(PKG, "FilemgrIngestStep.Name"));
+
+		int middle = props.getMiddlePct();
+		int margin = Const.MARGIN;
+
+		// Stepname line
+		wlStepname = new Label(shell, SWT.RIGHT);
+		wlStepname.setText(BaseMessages.getString(PKG, "System.Label.StepName")); 
+		props.setLook(wlStepname);
+		fdlStepname = new FormData();
+		fdlStepname.left = new FormAttachment(0, 0);
+		fdlStepname.right = new FormAttachment(middle, -margin);
+		fdlStepname.top = new FormAttachment(0, margin);
+		wlStepname.setLayoutData(fdlStepname);
+		
+		wStepname = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+		wStepname.setText(stepname);
+		props.setLook(wStepname);
+		wStepname.addModifyListener(lsMod);
+		fdStepname = new FormData();
+		fdStepname.left = new FormAttachment(middle, 0);
+		fdStepname.top = new FormAttachment(0, margin);
+		fdStepname.right = new FormAttachment(100, 0);
+		wStepname.setLayoutData(fdStepname);
+
+		// output field value
+		Label wlValName = new Label(shell, SWT.RIGHT);
+		wlValName.setText(BaseMessages.getString(PKG, "FilemgrIngest.FieldName.Label"));
+		props.setLook(wlValName);
+		FormData fdlValName = new FormData();
+		fdlValName.left = new FormAttachment(0, 0);
+		fdlValName.right = new FormAttachment(middle, -margin);
+		fdlValName.top = new FormAttachment(wStepname, margin);
+		wlValName.setLayoutData(fdlValName);
+
+
+		wFilenameField = new CCombo(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+		props.setLook(wFilenameField);
+		wFilenameField.addModifyListener(lsMod);
+		FormData fdValName = new FormData();
+		fdValName.left = new FormAttachment(middle, 0);
+		///fdValName.right = new FormAttachment(m_getFieldsBut, -margin);
+	  fdValName.right = new FormAttachment(100,0);
+		fdValName.top = new FormAttachment(wStepname, margin);
+		wFilenameField.setLayoutData(fdValName);
+
+
+/*
+	  m_getFieldsBut = new Button(shell, SWT.PUSH | SWT.CENTER);
+	  props.setLook(m_getFieldsBut);
+	  m_getFieldsBut.setText(BaseMessages.getString(PKG,
+		  "SSTableOutputDialog.GetFields.Button"));
+	  FormData fd = new FormData();
+	  fd.right = new FormAttachment(100, 0);
+	  fdValName.top = new FormAttachment(wStepname, margin);
+	  m_getFieldsBut.setLayoutData(fd);
+	  m_getFieldsBut.addSelectionListener(new SelectionAdapter() {
+		@Override
+		public void widgetSelected(SelectionEvent e) {
+		  setupFieldsCombo();
+		}
+	  });*/
+        // output field value
+        Label wlMetadataName = new Label(shell, SWT.RIGHT);
+        wlMetadataName.setText(BaseMessages.getString(PKG, "FilemgrIngest.MetadataFieldName.Label"));
+        props.setLook(wlMetadataName);
+        FormData fdlMetadataName = new FormData();
+        fdlMetadataName.left = new FormAttachment(0, 0);
+        fdlMetadataName.right = new FormAttachment(middle, -margin);
+        fdlMetadataName.top = new FormAttachment(wFilenameField, margin);
+        wlMetadataName.setLayoutData(fdlMetadataName);
+
+        wMetadataField = new CCombo(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+        props.setLook(wMetadataField);
+        wMetadataField.addModifyListener(lsMod);
+        FormData fdMetadataName = new FormData();
+        fdMetadataName.left = new FormAttachment(middle, 0);
+        fdMetadataName.right = new FormAttachment(100, 0);
+        fdMetadataName.top = new FormAttachment(wFilenameField, margin);
+        wMetadataField.setLayoutData(fdMetadataName);
+
+
+        // servername field value
+        Label wlServerName = new Label(shell, SWT.RIGHT);
+        wlServerName.setText(BaseMessages.getString(PKG, "FilemgrIngest.ServerURL.Label"));
+        props.setLook(wlServerName);
+        FormData fdlServerName = new FormData();
+        fdlServerName.left = new FormAttachment(0, 0);
+        fdlServerName.right = new FormAttachment(middle, -margin);
+        fdlServerName.top = new FormAttachment(wMetadataField, margin);
+        wlServerName.setLayoutData(fdlServerName);
+
+        wServerURLField = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+        props.setLook(wServerURLField);
+        wServerURLField.addModifyListener(lsMod);
+        FormData fdServerName = new FormData();
+        fdServerName.left = new FormAttachment(middle, 0);
+        fdServerName.right = new FormAttachment(100, 0);
+        fdServerName.top = new FormAttachment(wMetadataField, margin);
+        wServerURLField.setLayoutData(fdServerName);
+
+        // servername field value
+        Label wlResultName = new Label(shell, SWT.RIGHT);
+        wlResultName.setText(BaseMessages.getString(PKG, "FilemgrIngest.Result.Label"));
+        props.setLook(wlResultName);
+        FormData fdlResultName = new FormData();
+        fdlResultName.left = new FormAttachment(0, 0);
+        fdlResultName.right = new FormAttachment(middle, -margin);
+        fdlResultName.top = new FormAttachment(wServerURLField, margin);
+        wlResultName.setLayoutData(fdlResultName);
+
+        wResultField = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+        props.setLook(wResultField);
+        wResultField.addModifyListener(lsMod);
+        FormData fdResultName = new FormData();
+        fdResultName.left = new FormAttachment(middle, 0);
+        fdResultName.right = new FormAttachment(100, 0);
+        fdResultName.top = new FormAttachment(wServerURLField, margin);
+        wResultField.setLayoutData(fdResultName);
+
+
+        // OK and cancel buttons
+		wOK = new Button(shell, SWT.PUSH);
+		wOK.setText(BaseMessages.getString(PKG, "System.Button.OK")); 
+		wCancel = new Button(shell, SWT.PUSH);
+		wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel")); 
+
+		BaseStepDialog.positionBottomButtons(shell, new Button[] { wOK, wCancel }, margin, wResultField);
+
+		// Add listeners for cancel and OK
+		lsCancel = new Listener() {
+			public void handleEvent(Event e) {cancel();}
+		};
+		lsOK = new Listener() {
+			public void handleEvent(Event e) {ok();}
+		};
+
+		wCancel.addListener(SWT.Selection, lsCancel);
+		wOK.addListener(SWT.Selection, lsOK);
+
+		// default listener (for hitting "enter")
+		lsDef = new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {ok();}
+		};
+		wStepname.addSelectionListener(lsDef);
+		wFilenameField.addSelectionListener(lsDef);
+        wServerURLField.addSelectionListener(lsDef);
+        wResultField.addSelectionListener(lsDef);
+		// Detect X or ALT-F4 or something that kills this window and cancel the dialog properly
+		shell.addShellListener(new ShellAdapter() {
+			public void shellClosed(ShellEvent e) {cancel();}
+		});
+		
+		// Set/Restore the dialog size based on last position on screen
+		// The setSize() method is inherited from BaseStepDialog
+		setSize();
+
+		// populate the dialog with the values from the meta object
+		populateDialog();
+		
+		// restore the changed flag to original value, as the modify listeners fire during dialog population 
+		meta.setChanged(changed);
+
+		// open dialog and enter event loop 
+		shell.open();
+		while (!shell.isDisposed()) {
+			if (!display.readAndDispatch())
+				display.sleep();
+		}
+
+		// at this point the dialog has closed, so either ok() or cancel() have been executed
+		// The "stepname" variable is inherited from BaseStepDialog
+		return stepname;
+	}
+	
+	/**
+	 * This helper method puts the step configuration stored in the meta object
+	 * and puts it into the dialog controls.
+	 */
+	private void populateDialog() {
+	  setupFieldsCombo();
+		wStepname.selectAll();
+		wFilenameField.setText(meta.getFilenameField());
+        wServerURLField.setText(meta.getServerURLField());
+        wResultField.setText(meta.getResultField());
+        wMetadataField.setText(meta.getMetadataField());
+
+	}
+
+	/**
+	 * Called when the user cancels the dialog.  
+	 */
+	private void cancel() {
+		// The "stepname" variable will be the return value for the open() method. 
+		// Setting to null to indicate that dialog was cancelled.
+		stepname = null;
+		// Restoring original "changed" flag on the met aobject
+		meta.setChanged(changed);
+		// close the SWT dialog window
+		dispose();
+	}
+	
+	/**
+	 * Called when the user confirms the dialog
+	 */
+	private void ok() {
+		// The "stepname" variable will be the return value for the open() method. 
+		// Setting to step name from the dialog control
+		stepname = wStepname.getText(); 
+		// Setting the  settings to the meta object
+		//meta.setOutputField(wFilenameField.getText());
+        meta.setFilenameField(wFilenameField.getText());
+        meta.setServerURLField(wServerURLField.getText());
+        meta.setResultField(wResultField.getText());
+        meta.setMetadataField(wMetadataField.getText());
+		// close the SWT dialog window
+		dispose();
+	}
+
+  protected void setupFieldsCombo() {
+
+	StepMeta stepMeta = transMeta.findStep(stepname);
+	if (stepMeta != null) {
+	  try {
+		RowMetaInterface row = transMeta.getPrevStepFields(stepMeta);
+
+		if (row.size() == 0) {
+		  /*MessageDialog.openError(shell, BaseMessages.getString(PKG,
+			  "SSTableOutputData.Message.NoIncomingFields.Title"), BaseMessages
+			  .getString(PKG, "SSTableOutputData.Message.NoIncomingFields"));*/
+		  return;
+		}
+		wFilenameField.removeAll();
+		for (int i = 0; i < row.size(); i++) {
+		  ValueMetaInterface vm = row.getValueMeta(i);
+		  wFilenameField.add(vm.getName());
+		}
+
+		wMetadataField.removeAll();
+		for (int i = 0; i < row.size(); i++) {
+		  ValueMetaInterface vm = row.getValueMeta(i);
+		  wMetadataField.add(vm.getName());
+		}
+
+	  } catch (KettleStepException e) {
+		e.printStackTrace();
+	  }
+	}
+  }
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/FilemgrIngestStepMeta.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/FilemgrIngestStepMeta.java
new file mode 100644
index 0000000..0849b8f
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/FilemgrIngestStepMeta.java
@@ -0,0 +1,358 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.filemgringest;
+
+import org.eclipse.swt.widgets.Shell;
+import org.pentaho.di.core.CheckResult;
+import org.pentaho.di.core.CheckResultInterface;
+import org.pentaho.di.core.annotations.Step;
+import org.pentaho.di.core.database.DatabaseMeta;
+import org.pentaho.di.core.exception.KettleException;
+import org.pentaho.di.core.exception.KettleStepException;
+import org.pentaho.di.core.exception.KettleValueException;
+import org.pentaho.di.core.exception.KettleXMLException;
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.core.row.ValueMeta;
+import org.pentaho.di.core.row.ValueMetaInterface;
+import org.pentaho.di.core.variables.VariableSpace;
+import org.pentaho.di.core.xml.XMLHandler;
+import org.pentaho.di.i18n.BaseMessages;
+import org.pentaho.di.repository.ObjectId;
+import org.pentaho.di.repository.Repository;
+import org.pentaho.di.trans.Trans;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.*;
+import org.pentaho.metastore.api.IMetaStore;
+import org.w3c.dom.Node;
+
+import java.util.List;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI. 
+ * 
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *   
+ * This class is the implementation of StepMetaInterface.
+ * Classes implementing this interface need to:
+ * 
+ * - keep track of the step settings
+ * - serialize step settings both to xml and a repository
+ * - provide new instances of objects implementing StepDialogInterface, StepInterface and StepDataInterface
+ * - report on how the step modifies the meta-data of the row-stream (row structure and field types)
+ * - perform a sanity-check on the settings provided by the user 
+ * 
+ */
+
+@Step(	
+		id = "FilemgrIngest",
+		image = "org/apache/oodt/filemgrcheck/resources/check/oodt.jpg",
+		i18nPackageName="bi.meteorite.filemgringest",
+		name="FilemgrIngestStep.Name",
+		description = "FilemgrIngestStep.TooltipDesc",
+		categoryDescription="i18n:org.pentaho.di.trans.step:BaseStep.Category.BigData"
+)
+public class FilemgrIngestStepMeta extends BaseStepMeta implements StepMetaInterface {
+
+	/**
+	 *	The PKG member is used when looking up internationalized strings.
+	 *	The properties file with localized keys is expected to reside in 
+	 *	{the package of the class specified}/messages/messages_{locale}.properties   
+	 */
+	private static Class<?> PKG = FilemgrIngestStepMeta.class; // for i18n purposes
+	
+	/**
+	 * Stores the name of the field added to the row-stream. 
+	 */
+	private String outputField;
+    private String filenameField;
+    private String serverURLField;
+    private String resultField;
+    private String metadataField;
+
+    /**
+	 * Constructor should call super() to make sure the base class has a chance to initialize properly.
+	 */
+	public FilemgrIngestStepMeta() {
+		super(); 
+	}
+	
+	/**
+	 * Called by Spoon to get a new instance of the SWT dialog for the step.
+	 * A standard implementation passing the arguments to the constructor of the step dialog is recommended.
+	 * 
+	 * @param shell		an SWT Shell
+	 * @param meta 		description of the step 
+	 * @param transMeta	description of the the transformation 
+	 * @param name		the name of the step
+	 * @return 			new instance of a dialog for this step 
+	 */
+	public StepDialogInterface getDialog(Shell shell, StepMetaInterface meta, TransMeta transMeta, String name) {
+		return new FilemgrIngestStepDialog(shell, meta, transMeta, name);
+	}
+
+	/**
+	 * Called by PDI to get a new instance of the step implementation. 
+	 * A standard implementation passing the arguments to the constructor of the step class is recommended.
+	 * 
+	 * @param stepMeta				description of the step
+	 * @param stepDataInterface		instance of a step data class
+	 * @param cnr					copy number
+	 * @param transMeta				description of the transformation
+	 * @param disp					runtime implementation of the transformation
+	 * @return						the new instance of a step implementation 
+	 */
+	public StepInterface getStep(StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr, TransMeta transMeta, Trans disp) {
+		return new FilemgrIngestStep(stepMeta, stepDataInterface, cnr, transMeta, disp);
+	}
+
+	/**
+	 * Called by PDI to get a new instance of the step data class.
+	 */
+	public StepDataInterface getStepData() {
+		return new FilemgrIngestStepData();
+	}	
+
+	/**
+	 * This method is called every time a new step is created and should allocate/set the step configuration
+	 * to sensible defaults. The values set here will be used by Spoon when a new step is created.    
+	 */
+	public void setDefault() {
+		outputField = "demo_field";
+        filenameField = "";
+        serverURLField = "http://localhost:9000";
+        resultField = "result";
+        metadataField = "";
+	}
+	
+	/**
+	 * Getter for the name of the field added by this step
+	 * @return the name of the field added
+	 */
+	public String getOutputField() {
+		return outputField;
+	}
+
+	/**
+	 * Setter for the name of the field added by this step
+	 * @param outputField the name of the field added
+	 */
+	public void setOutputField(String outputField) {
+		this.outputField = outputField;
+	}
+
+
+    public String getFilenameField(){
+        return filenameField;
+    }
+
+    public void setFilenameField(String filenameField){
+        this.filenameField = filenameField;
+    }
+	/**
+	 * This method is used when a step is duplicated in Spoon. It needs to return a deep copy of this
+	 * step meta object. Be sure to create proper deep copies if the step configuration is stored in
+	 * modifiable objects.
+	 * 
+	 * See org.pentaho.di.trans.steps.rowgenerator.RowGeneratorMeta.clone() for an example on creating
+	 * a deep copy.
+	 * 
+	 * @return a deep copy of this
+	 */
+	public Object clone() {
+		Object retval = super.clone();
+		return retval;
+	}
+	
+	/**
+	 * This method is called by Spoon when a step needs to serialize its configuration to XML. The expected
+	 * return value is an XML fragment consisting of one or more XML tags.  
+	 * 
+	 * Please use org.pentaho.di.core.xml.XMLHandler to conveniently generate the XML.
+	 * 
+	 * @return a string containing the XML serialization of this step
+	 */
+	public String getXML() throws KettleValueException {
+		
+		// only one field to serialize
+		String xml =  " ";
+        xml += "    " +XMLHandler.addTagValue("outputfield", outputField);
+        xml += "    " +XMLHandler.addTagValue("filenamefield", filenameField);
+        xml += "    " +XMLHandler.addTagValue("serverurlfield", serverURLField);
+        xml += "    " +XMLHandler.addTagValue("resultfield", resultField);
+        xml += "    " +XMLHandler.addTagValue("metadatafield", metadataField);
+		return xml;
+	}
+
+	/**
+	 * This method is called by PDI when a step needs to load its configuration from XML.
+	 * 
+	 * Please use org.pentaho.di.core.xml.XMLHandler to conveniently read from the
+	 * XML node passed in.
+	 * 
+	 * @param stepnode	the XML node containing the configuration
+	 * @param databases	the databases available in the transformation
+	 * @param metaStore the metaStore to optionally read from
+	 */
+	public void loadXML(Node stepnode, List<DatabaseMeta> databases, IMetaStore metaStore) throws KettleXMLException {
+
+		try {
+			setOutputField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "outputfield")));
+            setFilenameField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "filenamefield")));
+            setServerURLField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "serverurlfield")));
+            setResultField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "resultfield")));
+            setMetadataField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode,"metadatafield")));
+		} catch (Exception e) {
+			throw new KettleXMLException("Demo plugin unable to read step info from XML node", e);
+		}
+
+	}	
+	/**
+	 * This method is called by Spoon when a step needs to serialize its configuration to a repository.
+	 * The repository implementation provides the necessary methods to save the step attributes.
+	 *
+	 * @param rep					the repository to save to
+	 * @param metaStore				the metaStore to optionally write to
+	 * @param id_transformation		the id to use for the transformation when saving
+	 * @param id_step				the id to use for the step  when saving
+	 */
+	public void saveRep(Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step) throws KettleException
+	{
+		try{
+			rep.saveStepAttribute(id_transformation, id_step, "outputfield", outputField); //$NON-NLS-1$
+		}
+		catch(Exception e){
+			throw new KettleException("Unable to save step into repository: "+id_step, e); 
+		}
+	}		
+	
+	/**
+	 * This method is called by PDI when a step needs to read its configuration from a repository.
+	 * The repository implementation provides the necessary methods to read the step attributes.
+	 * 
+	 * @param rep		the repository to read from
+	 * @param metaStore	the metaStore to optionally read from
+	 * @param id_step	the id of the step being read
+	 * @param databases	the databases available in the transformation
+	 */
+	public void readRep(Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases) throws KettleException  {
+		try{
+			outputField  = rep.getStepAttributeString(id_step, "outputfield"); //$NON-NLS-1$
+		}
+		catch(Exception e){
+			throw new KettleException("Unable to load step from repository", e);
+		}
+	}
+
+	/**
+	 * This method is called to determine the changes the step is making to the row-stream.
+	 * To that end a RowMetaInterface object is passed in, containing the row-stream structure as it is when entering
+	 * the step. This method must apply any changes the step makes to the row stream. Usually a step adds fields to the
+	 * row-stream.
+	 * 
+	 * @param inputRowMeta		the row structure coming in to the step
+	 * @param name 				the name of the step making the changes
+	 * @param info				row structures of any info steps coming in
+	 * @param nextStep			the description of a step this step is passing rows to
+	 * @param space				the variable space for resolving variables
+	 * @param repository		the repository instance optionally read from
+	 * @param metaStore			the metaStore to optionally read from
+	 */
+	public void getFields(RowMetaInterface inputRowMeta, String name, RowMetaInterface[] info, StepMeta nextStep, VariableSpace space, Repository repository, IMetaStore metaStore) throws KettleStepException{
+
+		/*
+		 * This implementation appends the outputField to the row-stream
+		 */
+
+		// a value meta object contains the meta data for a field
+		ValueMetaInterface v = new ValueMeta(outputField, ValueMeta.TYPE_STRING);
+		
+		// setting trim type to "both"
+		v.setTrimType(ValueMeta.TRIM_TYPE_BOTH);
+
+		// the name of the step that adds this field
+		v.setOrigin(name);
+		
+		// modify the row structure and add the field this step generates  
+		inputRowMeta.addValueMeta(v);
+		
+	}
+
+	/**
+	 * This method is called when the user selects the "Verify Transformation" option in Spoon. 
+	 * A list of remarks is passed in that this method should add to. Each remark is a comment, warning, error, or ok.
+	 * The method should perform as many checks as necessary to catch design-time errors.
+	 * 
+	 * Typical checks include:
+	 * - verify that all mandatory configuration is given
+	 * - verify that the step receives any input, unless it's a row generating step
+	 * - verify that the step does not receive any input if it does not take them into account
+	 * - verify that the step finds fields it relies on in the row-stream
+	 * 
+	 *   @param remarks		the list of remarks to append to
+	 *   @param transMeta	the description of the transformation
+	 *   @param stepMeta	the description of the step
+	 *   @param prev		the structure of the incoming row-stream
+	 *   @param input		names of steps sending input to the step
+	 *   @param output		names of steps this step is sending output to
+	 *   @param info		fields coming in from info steps 
+	 *   @param metaStore	metaStore to optionally read from
+	 */
+	public void check(List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepMeta, RowMetaInterface prev, String input[], String output[], RowMetaInterface info, VariableSpace space, Repository repository, IMetaStore metaStore)  {
+		
+		CheckResult cr;
+
+		// See if there are input streams leading to this step!
+		if (input.length > 0) {
+			cr = new CheckResult(CheckResult.TYPE_RESULT_OK, BaseMessages.getString(PKG, "Demo.CheckResult.ReceivingRows.OK"), stepMeta);
+			remarks.add(cr);
+		} else {
+			cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, BaseMessages.getString(PKG, "Demo.CheckResult.ReceivingRows.ERROR"), stepMeta);
+			remarks.add(cr);
+		}	
+    	
+	}
+
+
+    public void setServerURLField(String serverURLField) {
+        this.serverURLField = serverURLField;
+    }
+
+    public String getServerURLField() {
+        return serverURLField;
+    }
+
+
+    public void setResultField(String resultField) {
+        this.resultField = resultField;
+    }
+
+    public String getResultField() {
+        return resultField;
+    }
+
+    public void setMetadataField(String metadataField) {
+        this.metadataField = metadataField;
+    }
+
+    public String getMetadataField() {
+        return metadataField;
+    }
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/OODTConfig.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/OODTConfig.java
new file mode 100644
index 0000000..496b64e
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/OODTConfig.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgringest;
+
+import org.apache.oodt.cas.filemgr.ingest.Ingester;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Created by bugg on 07/03/14.
+ */
+public class OODTConfig {
+
+    private static final Logger LOG = Logger.getLogger(OODTConfig.class.getName());
+
+    private URL fmUrl;
+
+    private Ingester ingester;
+
+    public Ingester getIngester() {
+        return this.ingester;
+    }
+
+    public URL getFmUrl(){
+        return this.fmUrl;
+    }
+
+
+    void loadIngester(String fmUrlStr) throws InstantiationException {
+        try {
+
+            String ingesterClass = "org.apache.oodt.cas.filemgr.ingest.StdIngester";
+
+            String dataTransferClass ="org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory";
+
+            String cacheFactoryClass = null;
+             //"org.apache.oodt.cas.filemgr.ingest.cache.factory";
+
+            LOG.log(Level.INFO, "Configuring and building ingester: ["
+                        + ingesterClass + "]: data transfer: ["
+                        + dataTransferClass + "]: to ingest to file manager: ["
+                        + fmUrlStr + "]");
+
+           if (cacheFactoryClass != null) {
+                    LOG.log(Level.INFO, "Configuring Ingester cache: ["
+                            + cacheFactoryClass + "]");
+           }
+
+           this.ingester = PushPullObjectFactory.createIngester(
+                  ingesterClass, cacheFactoryClass);
+
+           this.fmUrl = safeGetUrlFromString(fmUrlStr);
+
+           } catch (ClassNotFoundException e1) {
+            e1.printStackTrace();
+        } catch (InvocationTargetException e1) {
+            e1.printStackTrace();
+        } catch (NoSuchMethodException e1) {
+            e1.printStackTrace();
+        } catch (IllegalAccessException e1) {
+            e1.printStackTrace();
+        }
+
+    }
+
+
+    private static URL safeGetUrlFromString(String urlStr) {
+        URL url = null;
+
+        try {
+            url = new URL(urlStr);
+        } catch (MalformedURLException e) {
+            LOG.log(Level.WARNING, "Unable to generate url from url string: ["
+                    + urlStr + "]: Message: " + e.getMessage());
+        }
+
+        return url;
+    }
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/OODTProcesses.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/OODTProcesses.java
new file mode 100644
index 0000000..ec24d4d
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/OODTProcesses.java
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.filemgringest;
+
+import com.google.gson.Gson;
+import com.google.gson.internal.LinkedTreeMap;
+
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.IngestException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.logging.Logger;
+
+/**
+ * Created by bugg on 07/03/14.
+ */
+public class OODTProcesses {
+
+    private static final Logger LOG = Logger.getLogger(OODTProcesses.class.getName());
+
+    private String filemgrUrl;
+
+    public boolean isAlreadyInDatabase(OODTConfig config, String filename) throws CatalogException {
+        return config.getIngester() != null && config.getIngester().hasProduct(
+                config.getFmUrl(), filename);
+    }
+
+    Metadata getMetadata(String json) {
+        Gson gson=new Gson();
+        Hashtable table = new Hashtable<String, String>();
+        table = (Hashtable<String, String>) gson.fromJson(json, table.getClass());
+      Hashtable<String,Object> ht = new Hashtable<String,Object>();
+
+        ArrayList l = (ArrayList) table.get("data");
+      if(l!=null) {
+        LinkedTreeMap d = (LinkedTreeMap) l.get(0);
+        ht.putAll(d);
+
+      }
+      else{
+        ht.putAll(table);
+      }
+
+        Metadata m = new Metadata();
+
+        m.addMetadata(ht);
+        return m;
+
+    }
+
+    String ingest(OODTConfig config, File product, Metadata productMetdata) throws IngestException {
+       // try {
+            String productId = config.getIngester().ingest(config.getFmUrl(),
+                    product, productMetdata);
+/*            LOG.log(Level.INFO, "Successfully ingested product: [" + product
+                    + "]: product id: " + productId);
+        } catch (Exception e) {
+            LOG.log(Level.WARNING,
+                    "ProductCrawler: Exception ingesting product: [" + product
+                            + "]: Message: " + e.getMessage()
+                            + ": attempting to continue crawling", e);
+            return false;
+        }*/
+        return productId;
+    }
+
+
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/PushPullObjectFactory.java b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/PushPullObjectFactory.java
new file mode 100644
index 0000000..6f81182
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/PushPullObjectFactory.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.filemgringest;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.ingest.Cache;
+import org.apache.oodt.cas.filemgr.ingest.CacheFactory;
+import org.apache.oodt.cas.filemgr.ingest.Ingester;
+
+//JDK imports
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class PushPullObjectFactory {
+
+    private PushPullObjectFactory() throws InstantiationException {
+        throw new InstantiationException("Don't construct factory classes!");
+    }
+
+    public static <T> T createNewInstance(Class<T> clazz) throws InstantiationException {
+    	try {
+			return clazz.newInstance();
+		} catch (Exception e) {
+            throw new InstantiationException(
+                    "Failed to create new object : "
+                            + e.getMessage());
+		}
+    }
+    
+    public static Ingester createIngester(String ingesterClass,
+            String cacheFactoryClass) throws InstantiationException,
+            IllegalAccessException, ClassNotFoundException,
+            IllegalArgumentException, SecurityException,
+            InvocationTargetException, NoSuchMethodException {
+        String dataTransferFactory = "org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory";
+        System.out.println("TRANSFER: " + dataTransferFactory);
+        if (cacheFactoryClass == null || cacheFactoryClass.equals("")) {
+            return (Ingester) Class.forName(ingesterClass).getConstructor(
+                    dataTransferFactory.getClass()).newInstance(
+                    dataTransferFactory);
+        } else {
+            Class<CacheFactory> cacheFactory = (Class<CacheFactory>) Class
+                    .forName(cacheFactoryClass);
+            Cache cache = cacheFactory.newInstance().createCache();
+            return (Ingester) Class.forName(ingesterClass).getConstructor(
+                    dataTransferFactory.getClass(), cache.getClass())
+                    .newInstance(dataTransferFactory, cache);
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/messages/messages_en_US.properties b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/messages/messages_en_US.properties
new file mode 100644
index 0000000..7e6008f
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/messages/messages_en_US.properties
@@ -0,0 +1,9 @@
+FilemgrIngestStep.Name=OODT Filemgr File Ingest
+FilemgrIngestStep.TooltipDesc=Check if the OODT Filemgr has a file in its repository
+
+FilemgrIngest.FieldName.Label=Filename Field
+
+FilemgrIngest.MetadataFieldName.Label=Metadata Field
+
+FilemgrIngest.ServerURL.Label=Filemgr URL
+FilemgrIngest.Result.Label=Result Field
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/resources/oodt.jpg b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/resources/oodt.jpg
new file mode 100644
index 0000000..5810409
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/resources/oodt.jpg
Binary files differ
diff --git a/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/resources/oodt.png b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/resources/oodt.png
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/0.8.1-rc1/tools/pdi_plugin/src/org/apache/oodt/filemgringest/resources/oodt.png
diff --git a/0.8.1-rc1/vagrant/radix/README.txt b/0.8.1-rc1/vagrant/radix/README.txt
new file mode 100644
index 0000000..eb2eddf
--- /dev/null
+++ b/0.8.1-rc1/vagrant/radix/README.txt
@@ -0,0 +1,51 @@
+# 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.
+
+##################################################################################
+#
+# README.txt
+#
+# @author riverma@apache.org
+#
+# @description This README describes how to setup, install, and run radix-vagrant. 
+# After completing these steps, you will have a fully configured Ubuntu Virtual 
+# Machine* running a fresh version of OODT RADiX.
+##################################################################################
+
+
+Requirements:
+1. 5GB of space to install VM on
+2. Vagrant: see http://www.vagrantup.com/
+3. VirtualBox: see https://www.virtualbox.org/wiki/Downloads
+
+Setup:
+1. Modify the contents of vagrant/env.sh to reflect your desired configuration
+   - add your project name etc here
+   - configure which type of RADiX build you want here (e.g. solr-enabled)
+2. Modify the Vagrantfile VM_NAME to name your VM (VM names must be unique)
+3. vagrant up
+NOTE: The above command will take up to 15 minutes the first time you run it.
+NOTE: All source files will be placed within /usr/local/src within the VM.
+
+Start:
+* NOTE: The provisioning script auto starts OODT, so you may skip to step 2
+1. (optional) Launch OODT if not already running below
+   > cd $OODT_HOME/bin
+   > ./oodt start
+2. Navigate to: http://localhost:8080/opsui
+
+-----
+* You can learn more about how to use your newly created virtual machine at: 
+http://www.vagrantup.com/
diff --git a/0.8.1-rc1/vagrant/radix/Vagrantfile b/0.8.1-rc1/vagrant/radix/Vagrantfile
new file mode 100644
index 0000000..c067295
--- /dev/null
+++ b/0.8.1-rc1/vagrant/radix/Vagrantfile
@@ -0,0 +1,129 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+# Virtual machine name
+VM_NAME = "oodt_radix_vm"
+
+# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
+VAGRANTFILE_API_VERSION = "2"
+
+Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
+  # All Vagrant configuration is done here. The most common configuration
+  # options are documented and commented below. For a complete reference,
+  # please see the online documentation at vagrantup.com.
+
+  # Every Vagrant virtual environment requires a box to build off of.
+  config.vm.box = "chef/ubuntu-13.10"
+
+  config.vm.define VM_NAME do |oodt_radix|
+  end
+  config.vm.provider :virtualbox do |vb|
+      vb.name = VM_NAME
+  end
+
+  # The url from where the 'config.vm.box' box will be fetched if it
+  # doesn't already exist on the user's system.
+  # config.vm.box_url = "http://domain.com/path/to/above.box"
+
+  # Create a forwarded port mapping which allows access to a specific port
+  # within the machine from a port on the host machine. In the example below,
+  # accessing "localhost:8080" will access port 80 on the guest machine.
+  config.vm.network "forwarded_port", guest: 8080, host: 8080
+
+  config.vm.provision :shell, :path => "vagrant/provision.sh", :privileged => false
+
+  # Create a private network, which allows host-only access to the machine
+  # using a specific IP.
+  # config.vm.network "private_network", ip: "192.168.33.10"
+
+  # Create a public network, which generally matched to bridged network.
+  # Bridged networks make the machine appear as another physical device on
+  # your network.
+  # config.vm.network "public_network"
+
+  # If true, then any SSH connections made will enable agent forwarding.
+  # Default value: false
+  # config.ssh.forward_agent = true
+
+  # Share an additional folder to the guest VM. The first argument is
+  # the path on the host to the actual folder. The second argument is
+  # the path on the guest to mount the folder. And the optional third
+  # argument is a set of non-required options.
+  # config.vm.synced_folder "../data", "/vagrant_data"
+
+  # Provider-specific configuration so you can fine-tune various
+  # backing providers for Vagrant. These expose provider-specific options.
+  # Example for VirtualBox:
+  #
+  # config.vm.provider "virtualbox" do |vb|
+  #   # Don't boot with headless mode
+  #   vb.gui = true
+  #
+  #   # Use VBoxManage to customize the VM. For example to change memory:
+  #   vb.customize ["modifyvm", :id, "--memory", "1024"]
+  # end
+  #
+  # View the documentation for the provider you're using for more
+  # information on available options.
+
+  # Enable provisioning with Puppet stand alone.  Puppet manifests
+  # are contained in a directory path relative to this Vagrantfile.
+  # You will need to create the manifests directory and a manifest in
+  # the file base.pp in the manifests_path directory.
+  #
+  # An example Puppet manifest to provision the message of the day:
+  #
+  # # group { "puppet":
+  # #   ensure => "present",
+  # # }
+  # #
+  # # File { owner => 0, group => 0, mode => 0644 }
+  # #
+  # # file { '/etc/motd':
+  # #   content => "Welcome to Apache OODT RADiX! Built by Vagrant. 
+  # #               Managed by Puppet.\n"
+  # # }
+  #
+  # config.vm.provision "puppet" do |puppet|
+  #   puppet.manifests_path = "manifests"
+  #   puppet.manifest_file  = "site.pp"
+  # end
+
+  # Enable provisioning with chef solo, specifying a cookbooks path, roles
+  # path, and data_bags path (all relative to this Vagrantfile), and adding
+  # some recipes and/or roles.
+  #
+  # config.vm.provision "chef_solo" do |chef|
+  #   chef.cookbooks_path = "../my-recipes/cookbooks"
+  #   chef.roles_path = "../my-recipes/roles"
+  #   chef.data_bags_path = "../my-recipes/data_bags"
+  #   chef.add_recipe "mysql"
+  #   chef.add_role "web"
+  #
+  #   # You may also specify custom JSON attributes:
+  #   chef.json = { :mysql_password => "foo" }
+  # end
+
+  # Enable provisioning with chef server, specifying the chef server URL,
+  # and the path to the validation key (relative to this Vagrantfile).
+  #
+  # The Opscode Platform uses HTTPS. Substitute your organization for
+  # ORGNAME in the URL and validation key.
+  #
+  # If you have your own Chef Server, use the appropriate URL, which may be
+  # HTTP instead of HTTPS depending on your configuration. Also change the
+  # validation key to validation.pem.
+  #
+  # config.vm.provision "chef_client" do |chef|
+  #   chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
+  #   chef.validation_key_path = "ORGNAME-validator.pem"
+  # end
+  #
+  # If you're using the Opscode platform, your validator client is
+  # ORGNAME-validator, replacing ORGNAME with your organization name.
+  #
+  # If you have your own Chef Server, the default validation client name is
+  # chef-validator, unless you changed the configuration.
+  #
+  #   chef.validation_client_name = "ORGNAME-validator"
+end
diff --git a/0.8.1-rc1/vagrant/radix/vagrant/conf/terminal/bashrc b/0.8.1-rc1/vagrant/radix/vagrant/conf/terminal/bashrc
new file mode 100644
index 0000000..8c21864
--- /dev/null
+++ b/0.8.1-rc1/vagrant/radix/vagrant/conf/terminal/bashrc
@@ -0,0 +1,110 @@
+# ~/.bashrc: executed by bash(1) for non-login shells.
+# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
+# for examples
+
+# If not running interactively, don't do anything
+[ -z "$PS1" ] && return
+
+# don't put duplicate lines or lines starting with space in the history.
+# See bash(1) for more options
+HISTCONTROL=ignoreboth
+
+# append to the history file, don't overwrite it
+shopt -s histappend
+
+# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
+HISTSIZE=1000
+HISTFILESIZE=2000
+
+# check the window size after each command and, if necessary,
+# update the values of LINES and COLUMNS.
+shopt -s checkwinsize
+
+# If set, the pattern "**" used in a pathname expansion context will
+# match all files and zero or more directories and subdirectories.
+#shopt -s globstar
+
+# make less more friendly for non-text input files, see lesspipe(1)
+[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
+
+# set variable identifying the chroot you work in (used in the prompt below)
+if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
+    debian_chroot=$(cat /etc/debian_chroot)
+fi
+
+# set a fancy prompt (non-color, unless we know we "want" color)
+case "$TERM" in
+    xterm-color) color_prompt=yes;;
+esac
+
+# uncomment for a colored prompt, if the terminal has the capability; turned
+# off by default to not distract the user: the focus in a terminal window
+# should be on the output of commands, not on the prompt
+#force_color_prompt=yes
+
+if [ -n "$force_color_prompt" ]; then
+    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
+	# We have color support; assume it's compliant with Ecma-48
+	# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
+	# a case would tend to support setf rather than setaf.)
+	color_prompt=yes
+    else
+	color_prompt=
+    fi
+fi
+
+if [ "$color_prompt" = yes ]; then
+    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
+else
+    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
+fi
+unset color_prompt force_color_prompt
+
+# If this is an xterm set the title to user@host:dir
+case "$TERM" in
+xterm*|rxvt*)
+    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
+    ;;
+*)
+    ;;
+esac
+
+# enable color support of ls and also add handy aliases
+if [ -x /usr/bin/dircolors ]; then
+    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
+    alias ls='ls --color=auto'
+    #alias dir='dir --color=auto'
+    #alias vdir='vdir --color=auto'
+
+    alias grep='grep --color=auto'
+    alias fgrep='fgrep --color=auto'
+    alias egrep='egrep --color=auto'
+fi
+
+# some more ls aliases
+alias ll='ls -alF'
+alias la='ls -A'
+alias l='ls -CF'
+
+# Add an "alert" alias for long running commands.  Use like so:
+#   sleep 10; alert
+alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
+
+# Alias definitions.
+# You may want to put all your additions into a separate file like
+# ~/.bash_aliases, instead of adding them here directly.
+# See /usr/share/doc/bash-doc/examples in the bash-doc package.
+
+if [ -f ~/.bash_aliases ]; then
+    . ~/.bash_aliases
+fi
+
+# enable programmable completion features (you don't need to enable
+# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
+# sources /etc/bash.bashrc).
+if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
+    . /etc/bash_completion
+fi
+
+# Export env.sh
+source /vagrant/vagrant/env.sh
\ No newline at end of file
diff --git a/0.8.1-rc1/vagrant/radix/vagrant/env.sh b/0.8.1-rc1/vagrant/radix/vagrant/env.sh
new file mode 100644
index 0000000..894910a
--- /dev/null
+++ b/0.8.1-rc1/vagrant/radix/vagrant/env.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# CHANGE BELOW FOR YOUR PROJECT NEEDS!
+export PROJECT_GROUP_ID=com.mycompany.mydms
+export PROJECT_ARTIFACT_ID=mycompany-myoodt
+export BUILD_FLAGS=-Pfm-solr-catalog # NOTE: more flag options at http://s.apache.org/CJL
+export OODT_DEPLOYMENT_HOME=/usr/local/oodt
+
+# General configuration (probably don't need to modify)
+export OODT_SRC_REPO=https://svn.apache.org/repos/asf/oodt/trunk # NOTE: This should match the below OODT version
+export OODT_VERSION=0.7-SNAPSHOT
+export JAVA_HOME=/usr/lib/jvm/default-java
+
diff --git a/0.8.1-rc1/vagrant/radix/vagrant/provision.sh b/0.8.1-rc1/vagrant/radix/vagrant/provision.sh
new file mode 100644
index 0000000..0d3bb2c
--- /dev/null
+++ b/0.8.1-rc1/vagrant/radix/vagrant/provision.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+##################################################
+#                                                #
+#   OODT RADiX Vagrant Provision Script          #
+#                                                # 
+##################################################
+
+# Load config file
+source /vagrant/vagrant/env.sh
+
+echo "Update Ubuntu’s package index"
+sudo apt-get update
+
+# --------- GENERAL INSTALL/CONFIG ---------------------------------------------------------
+sudo apt-get install -y vim 
+sudo apt-get install -y subversion
+sudo apt-get install -y git
+sudo apt-get install -y tree
+sudo apt-get install -y curl
+sudo apt-get install -y maven2
+sudo apt-get install -y default-jdk
+sudo apt-get install -y ack
+
+# --------- General config/install ----------
+sudo cp /vagrant/vagrant/conf/terminal/bashrc /home/vagrant/.bashrc
+source /home/vagrant/.bashrc
+sudo mkdir ${OODT_DEPLOYMENT_HOME}
+sudo chown -R vagrant:vagrant ${OODT_DEPLOYMENT_HOME}
+
+
+# ---------- OODT Installation --------------
+# NOTE: Checking out and installing OODT is only necessary for the SNAPSHOT versions of OODT
+# TO DO: Set up some logic for differentiating between SNAPSHOT (trunk) and tagged releases
+echo "Checking out latest (trunk) OODT from SVN"
+cd /usr/local/src
+sudo svn export ${OODT_SRC_REPO} oodt-${OODT_VERSION}
+sudo chown -R vagrant:vagrant oodt-${OODT_VERSION}
+echo "Build OODT and RADiX archetype"
+cd oodt-${OODT_VERSION}
+mvn -Dmaven.test.skip=true clean install
+cd mvn/archetypes/radix
+sudo mvn install
+
+# ---------- Setup new RADiX project --------
+cd /usr/local/src
+sudo mvn archetype:generate -DinteractiveMode=false -DarchetypeGroupId=org.apache.oodt -DarchetypeArtifactId=radix-archetype -DarchetypeVersion=${OODT_VERSION} -Doodt=${OODT_VERSION} -DgroupId=${PROJECT_GROUP_ID} -DartifactId=${PROJECT_ARTIFACT_ID} -Dversion=0.1-SNAPSHOT
+cd ${PROJECT_ARTIFACT_ID}
+sudo mvn package ${BUILD_FLAGS}
+tar zxf distribution/target/${PROJECT_ARTIFACT_ID}-distribution-*-bin.tar.gz -C ${OODT_DEPLOYMENT_HOME}
+
+# ---------- Start OODT ----------
+cd ${OODT_DEPLOYMENT_HOME}/bin
+./oodt start
+echo ""
+echo "OODT started, please navigate to: http://localhost:8080/opsui"
diff --git a/0.8.1-rc1/webapp/components/pom.xml b/0.8.1-rc1/webapp/components/pom.xml
new file mode 100644
index 0000000..48d91f6
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/pom.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+    <parent>
+        <groupId>org.apache.oodt</groupId>
+        <artifactId>oodt-core</artifactId>
+        <version>0.8.1</version>
+        <relativePath>../../core/pom.xml</relativePath>
+    </parent>
+	<groupId>org.apache.oodt</groupId>
+	<artifactId>oodt-webapp-components</artifactId>
+	<packaging>jar</packaging>
+	<version>0.8.1</version>
+	<name>OODT Wicket Web Components</name>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.wicket</groupId>
+			<artifactId>wicket</artifactId>
+			<version>1.4.16</version>
+		</dependency>
+		<dependency>
+		  <groupId>org.apache.oodt</groupId>
+		  <artifactId>cas-filemgr</artifactId>
+		  <version>0.8.1</version>
+		</dependency>
+		<dependency>
+		  <groupId>org.apache.oodt</groupId>
+		  <artifactId>cas-workflow</artifactId>
+		  <version>0.8.1</version>
+		</dependency>
+		<dependency>	
+		  <groupId>org.apache.oodt</groupId>
+		  <artifactId>pcs-core</artifactId>
+		  <version>${project.parent.version}</version>
+		</dependency>			
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-log4j12</artifactId>
+			<version>1.5.8</version>
+		</dependency>
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>1.2.14</version>
+		</dependency>
+		<dependency>
+		    <groupId>javax.servlet</groupId>
+		    <artifactId>servlet-api</artifactId>
+		    <version>2.4</version>
+		    <scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.8.1</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+        <profiles>
+            <profile>
+                <id>audit</id>
+                <activation>
+                    <activeByDefault>false</activeByDefault>
+                </activation>
+                <build>
+                    <plugins>
+                        <plugin>
+                            <groupId>org.codehaus.mojo</groupId>
+                            <artifactId>rat-maven-plugin</artifactId>
+                            <executions>
+                                <execution>
+                                    <phase>verify</phase>
+                                    <goals>
+                                        <goal>check</goal>
+                                    </goals>
+                                </execution>
+                            </executions>
+                            <configuration>
+                                <numUnapprovedLicenses>2</numUnapprovedLicenses>
+                                <excludes>
+                                    <exclude>webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/prototype.js</exclude>
+                                    <exclude>webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/progress.js</exclude>
+                                </excludes>
+                            </configuration>
+                        </plugin>
+                    </plugins>
+                </build>
+            </profile>
+       </profiles>
+	<build>
+		<resources>
+			<resource>
+				<filtering>false</filtering>
+				<directory>src/main/resources</directory>
+			</resource>
+			<resource>
+				<filtering>false</filtering>
+				<directory>src/main/java</directory>
+				<includes>
+					<include>**</include>
+				</includes>
+				<excludes>
+					<exclude>**/*.java</exclude>
+				</excludes>
+			</resource>
+		</resources>
+		<testResources>
+			<testResource>
+				<filtering>false</filtering>
+				<directory>src/test/java</directory>
+				<includes>
+					<include>**</include>
+				</includes>
+				<excludes>
+					<exclude>**/*.java</exclude>
+				</excludes>
+			</testResource>
+		</testResources>
+		<plugins>
+			<plugin>
+				<inherited>true</inherited>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.5</source>
+					<target>1.5</target>
+					<optimize>true</optimize>
+					<debug>true</debug>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+	</project>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/FMBrowserAppBase.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/FMBrowserAppBase.java
new file mode 100644
index 0000000..197525b
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/FMBrowserAppBase.java
@@ -0,0 +1,53 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.filemgr;
+
+//Wicket imports
+import org.apache.wicket.Request;
+import org.apache.wicket.Response;
+import org.apache.wicket.Session;
+import org.apache.wicket.protocol.http.WebApplication;
+
+/**
+ * 
+ * Base FM browser web-application class. Inherit this 
+ * in your sub-classed browsers.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public abstract class FMBrowserAppBase extends WebApplication {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.wicket.protocol.http.WebApplication#newSession(org.apache.wicket
+   * .Request, org.apache.wicket.Response)
+   */
+  @Override
+  public Session newSession(Request request, Response response) {
+    return new FMBrowserSession(request);
+  }
+
+  public String getFmUrlStr() {
+    return getServletContext().getInitParameter("filemgr.url");
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/FMBrowserSession.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/FMBrowserSession.java
new file mode 100644
index 0000000..ae53e5e
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/FMBrowserSession.java
@@ -0,0 +1,67 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.filemgr;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+
+//Wicket imports
+import org.apache.wicket.Request;
+import org.apache.wicket.Session;
+import org.apache.wicket.protocol.http.WebSession;
+
+/**
+ *
+ * A custom session for the FMBrowserApp, holds its 
+ * {@link List} of {@link TermQueryCriteria}.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class FMBrowserSession extends WebSession {
+
+  private static final long serialVersionUID = 2014426518833800794L;
+
+  private List<TermQueryCriteria> crit;
+  
+  /**
+   * @param request
+   */
+  public FMBrowserSession(Request request) {
+    super(request);
+    this.crit = new Vector<TermQueryCriteria>();
+  }
+  
+  public static FMBrowserSession get(){
+    return (FMBrowserSession)Session.get();
+  }
+  
+  public final List<TermQueryCriteria> getCriteria(){
+    return this.crit;
+  }
+  
+  public final void setCriteria(List<TermQueryCriteria> crit){
+    this.crit = crit;
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/FileManagerConn.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/FileManagerConn.java
new file mode 100644
index 0000000..83d3c8f
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/FileManagerConn.java
@@ -0,0 +1,144 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.filemgr;
+
+import java.net.URL;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class FileManagerConn {
+
+  private XmlRpcFileManagerClient fm;
+
+  private static final Logger LOG = Logger.getLogger(FileManagerConn.class
+      .getName());
+
+  public FileManagerConn(String fmUrlStr) {
+    this.initFm(fmUrlStr);
+  }
+
+  public String getProdReceivedTime(Product p) {
+    Metadata met = getMetadata(p);
+    String prodReceivedTime = met.getMetadata("CAS."
+        + CoreMetKeys.PRODUCT_RECEVIED_TIME);
+    return prodReceivedTime != null && !prodReceivedTime.equals("") ? prodReceivedTime
+        : "UNKNOWN";
+  }
+
+  public List<Reference> getProductReferences(Product p) {
+    List<Reference> refs = new Vector<Reference>();
+    try {
+      refs = fm.getProductReferences(p);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to get references for product: ["
+          + p.getProductName() + "]: Reason: " + e.getMessage());
+    }
+
+    return refs;
+  }
+
+  public ProductType safeGetProductTypeByName(String name) {
+    try {
+      return fm.getProductTypeByName(name);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to get product type by name: [" + name
+          + "]: Message: " + e.getMessage());
+      return null;
+    }
+  }
+
+  public Product safeGetProductById(String id) {
+    try {
+      return fm.getProductById(id);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to get product by id: [" + id
+          + "]: Message: " + e.getMessage());
+      return null;
+    }
+  }
+
+  public Metadata getMetadata(Product p) {
+    Metadata met = null;
+    try {
+      met = fm.getMetadata(p);
+    } catch (CatalogException e) {
+      LOG.log(Level.WARNING,
+          "Unable to get metadata and display product received time for: ["
+              + p.getProductName() + "]: Reason: " + e.getMessage());
+    }
+
+    return met;
+  }
+
+  public List<Element> safeGetElementsForProductType(ProductType type) {
+    try {
+      return fm.getElementsByProductType(type);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to obtain elements for product type: ["
+          + type.getName() + "]: Reason: " + e.getMessage());
+      return new Vector<Element>();
+    }
+  }
+
+  public List<ProductType> safeGetProductTypes() {
+    List<ProductType> types = new Vector<ProductType>();
+    try {
+      types = this.fm.getProductTypes();
+    } catch (RepositoryManagerException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Unable to obtain product types: Reason: ["
+          + e.getMessage() + "]");
+    }
+    return types;
+  }
+
+  public XmlRpcFileManagerClient getFm() {
+    return this.fm;
+  }
+
+  public void initFm(String urlStr) {
+    try {
+      this.fm = new XmlRpcFileManagerClient(new URL(urlStr));
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to connect to the file manager at: ["
+          + urlStr + "]");
+      this.fm = null;
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/metadata/MetadataBrowser.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/metadata/MetadataBrowser.css
new file mode 100644
index 0000000..e514f16
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/metadata/MetadataBrowser.css
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+#met_table{
+
+}
+
+#met_elem_name{
+	
+}
+
+#met_values_table{
+
+}
+
+.nada{
+	
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/metadata/MetadataBrowser.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/metadata/MetadataBrowser.html
new file mode 100644
index 0000000..f0c561b
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/metadata/MetadataBrowser.html
@@ -0,0 +1,39 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:remove>
+  <link rel="stylesheet" type="text/css" href="MetadataBrowser.css"/>
+</wicket:remove>
+
+<h3>Metadata</h3>
+  <table id="met_table">
+    <tr wicket:id="met_elem">
+      <td wicket:id="met_elem_name" id="met_elem_name">CAS.ProductName</td>
+      <td>
+         <table id="met_values_table">
+          <tr wicket:id="met_values_list">
+             <td wicket:id="met_value">foo.txt</td>
+          </tr>
+         </table>
+      </td>
+     </tr>
+   </table>
+   
+   <h3 wicket:id="no_prod_met_display" class="nada">No Product Metadata!</h3>
+   <p>&nbsp;</p>
+   <p>&nbsp;</p>
+</wicket:panel>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/metadata/MetadataBrowser.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/metadata/MetadataBrowser.java
new file mode 100644
index 0000000..9eb43c1
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/metadata/MetadataBrowser.java
@@ -0,0 +1,111 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.filemgr.browser.metadata;
+
+//JDK imports
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.webcomponents.filemgr.FileManagerConn;
+
+//Wicket imports
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.util.ListModel;
+
+/**
+ * 
+ * {@link Metadata}-view popup.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class MetadataBrowser extends Panel {
+
+  private static final long serialVersionUID = 5276544059589968409L;
+
+  private FileManagerConn fm;
+
+  public MetadataBrowser(String componentId, String fmUrlStr, String productId) {
+    super(componentId);
+    this.fm = new FileManagerConn(fmUrlStr);
+    final SerializableMetadata met = new SerializableMetadata(this.fm
+        .getMetadata(this.fm.safeGetProductById(productId)));
+    setDefaultModel(new Model(met));
+
+    if (met != null) {
+      add(new Label("no_prod_met_display") {
+        /*
+         * (non-Javadoc)
+         * 
+         * @see org.apache.wicket.Component#isVisible()
+         */
+        @Override
+        public boolean isVisible() {
+          return false;
+        }
+      });
+
+      List<String> metKeys = met.getAllKeys();
+      Collections.sort(metKeys);
+
+      add(new ListView<String>("met_elem", new ListModel<String>(metKeys)) {
+        /*
+         * (non-Javadoc)
+         * 
+         * @see
+         * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+         * .wicket.markup.html.list.ListItem)
+         */
+        @Override
+        protected void populateItem(ListItem<String> item) {
+          item.add(new Label("met_elem_name", item.getModelObject()));
+
+          item
+              .add(new ListView<String>("met_values_list",
+                  new ListModel<String>(met.getAllMetadata(item
+                      .getModelObject()))) {
+                /*
+                 * (non-Javadoc)
+                 * 
+                 * @see
+                 * org.apache.wicket.markup.html.list.ListView#populateItem(
+                 * org.apache.wicket.markup.html.list.ListItem)
+                 */
+                @Override
+                protected void populateItem(ListItem<String> item) {
+                  item.add(new Label("met_value", item.getModelObject()));
+                }
+              });
+
+        }
+      });
+    } else {
+      add(new Label("no_prod_met_display", "No Product Metadata!"));
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/pagination/ProductPaginator.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/pagination/ProductPaginator.css
new file mode 100644
index 0000000..713c9ab
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/pagination/ProductPaginator.css
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+#paginator-break{
+  border:2;
+  width:100%;
+}
+
+#container-div{
+  width:100%;
+}
+
+#paginator-table{
+  border-spacing:3;
+  width:100;
+}
+
+#paginator-table-header{
+  width:100%;
+  white-space:nowrap;
+  font-weight:bold;
+}
+
+
+#page_repeater{
+
+}
+
+a, a:hover, a:focus, a:active{
+	text-decoration: none;
+}
+
+.selected{
+  font-weight:bold;
+  color:red;
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/pagination/ProductPaginator.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/pagination/ProductPaginator.html
new file mode 100644
index 0000000..57b80f0
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/pagination/ProductPaginator.html
@@ -0,0 +1,32 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:remove>
+  <link rel="stylesheet" type="text/css" href="ProductPaginator.css"/>
+</wicket:remove>
+<hr id="paginator-break">
+<div id="container-div">
+    <table id="paginator-table">
+      <tr>
+        <td id="paginator-table-header">Result Page</td>
+          <td wicket:id="page_repeater" id="page_repeater"><a wicket:id="pageLink" class="selected" href="#"><span wicket:id="pageNum">1</span></a></td>                    	 
+      </tr>
+     </table>
+</div>
+
+<h3 wicket:id="nothing_found">No Products Found!</h3>
+</wicket:panel>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/pagination/ProductPaginator.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/pagination/ProductPaginator.java
new file mode 100644
index 0000000..672fb85
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/pagination/ProductPaginator.java
@@ -0,0 +1,163 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.filemgr.browser.pagination;
+
+//JDK imports
+import java.io.Serializable;
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.webcomponents.filemgr.browser.types.TypeBrowser;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.behavior.SimpleAttributeModifier;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+
+/**
+ * 
+ * A paginator component that expands to a +/- 5 page
+ * window to paginate a {@link ProductPage}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ProductPaginator extends Panel {
+
+  private static final long serialVersionUID = 6277536371513974225L;
+
+  private ProductPage page;
+
+  private String productTypeName;
+
+  /**
+   * @param id
+   */
+  public ProductPaginator(String id, ProductPage page,
+      final String productTypeName, final Class<? extends WebPage> typeBrowserPage) {
+    super(id);
+    this.page = page;
+    this.productTypeName = productTypeName;
+
+    if (this.page != null && this.page.getPageProducts() != null
+        && this.page.getPageProducts().size() > 0) {
+
+      int numPages = this.page.getTotalPages();
+      int currPage = this.page.getPageNum();
+      int windowSize = 10;
+
+      int startPage = Math.max(1, (currPage - (windowSize / 2)));
+      int endPage = Math.min(currPage + (windowSize / 2), numPages);
+      List<PageNumDisplay> pnums = this.getPageNumDisplay(startPage, endPage,
+          currPage);
+
+      add(new ListView<PageNumDisplay>("page_repeater", pnums) {
+
+        @Override
+        protected void populateItem(ListItem<PageNumDisplay> item) {
+          PageParameters params = new PageParameters();
+          params.add("name", productTypeName);
+          params.put("pageNum", item.getModelObject().getNum());
+          BookmarkablePageLink pageLink = new BookmarkablePageLink("pageLink",
+              typeBrowserPage, params);
+          pageLink.add(new Label("pageNum", String.valueOf(item
+              .getModelObject().getNum())));
+          pageLink.add(new SimpleAttributeModifier("class", item
+              .getModelObject().isCurrentPage() ? "selected" : ""));
+          item.add(pageLink);
+        }
+      });
+      add(new Label("nothing_found").setVisible(false));
+    } else {
+      add(new Label("page_repeater").setVisible(false));
+      add(new Label("pageLink").setVisible(false));
+      add(new Label("pageNum").setVisible(false));
+      add(new Label("nothing_found").setVisible(true));
+    }
+
+  }
+
+  private List<PageNumDisplay> getPageNumDisplay(int startPage, int endPage,
+      int currPage) {
+    List<PageNumDisplay> display = new Vector<PageNumDisplay>();
+    for (int i = startPage; i <= endPage; i++) {
+      display.add(new PageNumDisplay(i == currPage, i));
+    }
+
+    return display;
+  }
+
+  class PageNumDisplay implements Serializable {
+
+    private static final long serialVersionUID = -4351470774764276644L;
+
+    private boolean currentPage;
+
+    private int num;
+
+    public PageNumDisplay() {
+      this.currentPage = false;
+      this.num = -1;
+    }
+
+    public PageNumDisplay(boolean currentPage, int num) {
+      this.currentPage = currentPage;
+      this.num = num;
+    }
+
+    /**
+     * @return the currentPage
+     */
+    public boolean isCurrentPage() {
+      return currentPage;
+    }
+
+    /**
+     * @param currentPage
+     *          the currentPage to set
+     */
+    public void setCurrentPage(boolean currentPage) {
+      this.currentPage = currentPage;
+    }
+
+    /**
+     * @return the num
+     */
+    public int getNum() {
+      return num;
+    }
+
+    /**
+     * @param num
+     *          the num to set
+     */
+    public void setNum(int num) {
+      this.num = num;
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductBrowser.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductBrowser.css
new file mode 100644
index 0000000..0ad6d53
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductBrowser.css
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+#met_table{
+
+}
+
+#met_elem_name{
+	
+}
+
+#met_values_table{
+
+}
+
+.nada{
+	
+}
+
+#ref_table{
+	
+}
+
+#ref_table_hdr{
+	
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductBrowser.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductBrowser.html
new file mode 100644
index 0000000..4b910b1
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductBrowser.html
@@ -0,0 +1,60 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:remove>
+  <link rel="stylesheet" type="text/css" href="ProductBrowser.css"/>
+</wicket:remove>
+
+<h3>Product: <span wicket:id="product_name">foo.txt</span></h3>
+<p>Percent Transferred: <span wicket:id="product_pct_transfer">100%</span></p>
+<a href="#References">Jump to References</a>
+                
+<h3>Metadata</h3>
+  <table id="met_table">
+    <tr wicket:id="met_elem">
+      <td wicket:id="met_elem_name" id="met_elem_name">CAS.ProductName</td>
+      <td>
+         <table id="met_values_table">
+          <tr wicket:id="met_values_list">
+             <td wicket:id="met_value">foo.txt</td>
+          </tr>
+         </table>
+      </td>
+     </tr>
+   </table>
+   
+   <h3 wicket:id="no_prod_met_display" class="nada">No Product Metadata!</h3>
+   <p>&nbsp;</p>
+   <p>&nbsp;</p>
+   <a name="References"></a>
+
+<h3>References</h3>
+  <table id="ref_table">
+    <tr id="ref_table_hdr">
+      <td>File Location</td>
+      <td>File Size</td>
+      <td>Percent Transferred</td>
+    </tr>
+    <tr wicket:id="ref_list">
+      <td wicket:id="ref_file_path">/home/files/foo.txt/foo.txt</td>
+      <td wicket:id="ref_file_size">4028</td>
+      <td wicket:id="ref_pct_transferred">100%</td>
+    </tr>
+  </table>
+
+  <h3 wicket:id="no_prod_ref_display" class="nada">No Product References!</h3>
+</wicket:panel>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductBrowser.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductBrowser.java
new file mode 100644
index 0000000..7c2de25
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductBrowser.java
@@ -0,0 +1,188 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.filemgr.browser.product;
+
+//JDK imports
+import java.io.File;
+import java.net.URI;
+import java.text.NumberFormat;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.webcomponents.filemgr.FileManagerConn;
+
+//Wicket imports
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.util.ListModel;
+
+/**
+ * 
+ * This page is mounted to:
+ * 
+ * <code>/browser/product/[ProductId]</code>
+ * 
+ * A {@link Product} web page component to display 
+ * all of its metadata and reference information.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ProductBrowser extends Panel {
+
+  private static final long serialVersionUID = -1204491609423677032L;
+
+  private static final Logger LOG = Logger.getLogger(ProductBrowser.class
+      .getName());
+  
+  private FileManagerConn fm;
+
+  public ProductBrowser(String componentId, String fmUrlStr, String productId) {
+    super(componentId);
+    this.fm = new FileManagerConn(fmUrlStr);
+    Product product = fm.safeGetProductById(productId);
+    try {
+      String productPctTransferred = NumberFormat.getPercentInstance().format(
+          fm.getFm().getProductPctTransferred(
+              product));
+      add(new Label("product_pct_transfer", productPctTransferred));
+    } catch (DataTransferException e) {
+      LOG.log(Level.WARNING, "Unable to determine pct transfer for product: ["
+          + product.getProductName() + "]: Reason: " + e.getMessage());
+    }
+
+    add(new Label("product_name", product.getProductName()));
+    final Metadata met = fm.getMetadata(product);
+    if (met != null) {
+      add(new Label("no_prod_met_display") {
+        /*
+         * (non-Javadoc)
+         * 
+         * @see org.apache.wicket.Component#isVisible()
+         */
+        @Override
+        public boolean isVisible() {
+          return false;
+        }
+      });
+
+      List<String> metKeys = met.getAllKeys();
+      Collections.sort(metKeys);
+
+      add(new ListView<String>("met_elem", new ListModel<String>(metKeys)) {
+        /*
+         * (non-Javadoc)
+         * 
+         * @see
+         * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+         * .wicket.markup.html.list.ListItem)
+         */
+        @Override
+        protected void populateItem(ListItem<String> item) {
+          item.add(new Label("met_elem_name", item.getModelObject()));
+
+          item
+              .add(new ListView<String>("met_values_list",
+                  new ListModel<String>(met.getAllMetadata(item
+                      .getModelObject()))) {
+                /*
+                 * (non-Javadoc)
+                 * 
+                 * @see
+                 * org.apache.wicket.markup.html.list.ListView#populateItem(
+                 * org.apache.wicket.markup.html.list.ListItem)
+                 */
+                @Override
+                protected void populateItem(ListItem<String> item) {
+                  item.add(new Label("met_value", item.getModelObject()));
+                }
+              });
+
+        }
+      });
+    } else {
+      add(new Label("no_prod_met_display", "No Product Metadata!"));
+    }
+
+    List<Reference> refs = fm
+        .getProductReferences(product);
+    if (refs != null && refs.size() > 0) {
+      add(new Label("no_prod_ref_display") {
+        /*
+         * (non-Javadoc)
+         * 
+         * @see org.apache.wicket.Component#isVisible()
+         */
+        @Override
+        public boolean isVisible() {
+          return false;
+        }
+      });
+
+      add(new ListView<Reference>("ref_list", new ListModel<Reference>(refs)) {
+        /*
+         * (non-Javadoc)
+         * 
+         * @see
+         * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+         * .wicket.markup.html.list.ListItem)
+         */
+        @Override
+        protected void populateItem(ListItem<Reference> refItem) {
+          Reference r = refItem.getModelObject();
+          String filePath = null;
+          try {
+            filePath = new File(new URI(r.getDataStoreReference()))
+                .getAbsolutePath();
+          } catch (Exception ignore) {
+          }
+
+          refItem.add(new Label("ref_file_path", filePath));
+          refItem.add(new Label("ref_file_size", String
+              .valueOf(r.getFileSize())));
+          try {
+            refItem.add(new Label("ref_pct_transferred", NumberFormat
+                .getPercentInstance().format(
+                   fm.getFm()
+                        .getRefPctTransferred(r))));
+          } catch (DataTransferException e) {
+            LOG.log(Level.WARNING,
+                "Unable to determine product reference size: Reason: "
+                    + e.getMessage());
+            refItem.add(new Label("ref_pct_transferred", "N/A"));
+          }
+
+        }
+      });
+    } else {
+      add(new Label("no_prod_ref_display", "No Product References!"));
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductRefsBrowser.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductRefsBrowser.css
new file mode 100644
index 0000000..395a1bd
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductRefsBrowser.css
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+.nada{
+	
+}
+
+#ref_table{
+	
+}
+
+#ref_table_hdr{
+	
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductRefsBrowser.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductRefsBrowser.html
new file mode 100644
index 0000000..915cd3a
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductRefsBrowser.html
@@ -0,0 +1,39 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:remove>
+  <link rel="stylesheet" type="text/css" href="ProductRefsBrowser.css"/>
+</wicket:remove>
+
+
+<a name="References"></a>
+<h3>References</h3>
+  <table id="ref_table">
+    <tr id="ref_table_hdr">
+      <td>File Location</td>
+      <td>File Size</td>
+      <td>Percent Transferred</td>
+    </tr>
+    <tr wicket:id="ref_list">
+      <td wicket:id="ref_file_path">/home/files/foo.txt/foo.txt</td>
+      <td wicket:id="ref_file_size">4028</td>
+      <td wicket:id="ref_pct_transferred">100%</td>
+    </tr>
+  </table>
+
+  <h3 wicket:id="no_prod_ref_display" class="nada">No Product References!</h3>
+</wicket:panel>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductRefsBrowser.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductRefsBrowser.java
new file mode 100644
index 0000000..14ff469
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/product/ProductRefsBrowser.java
@@ -0,0 +1,121 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.filemgr.browser.product;
+
+//JDK imports
+import java.io.File;
+import java.net.URI;
+import java.text.NumberFormat;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.apache.oodt.cas.webcomponents.filemgr.FileManagerConn;
+
+//Wicket imports
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.util.ListModel;
+
+/**
+ *
+ * Component responsible for showing a {@link Product}s
+ * {@link List} of {@link Reference}s.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class ProductRefsBrowser extends Panel {
+  
+  private static final long serialVersionUID = -2278188309669737798L;
+
+  private static final Logger LOG = Logger.getLogger(ProductRefsBrowser.class.getName());
+  
+  private FileManagerConn fm;
+  
+  public ProductRefsBrowser(String componentId, String fmUrlStr, String productId){
+    super(componentId);
+    this.fm = new FileManagerConn(fmUrlStr);
+    List<Reference> refs = null;
+    try {
+      refs = fm.getProductReferences(fm.getFm().getProductById(productId));
+    } catch (CatalogException e1) {
+      e1.printStackTrace();
+    }
+    if (refs != null && refs.size() > 0) {
+      add(new Label("no_prod_ref_display") {
+        /*
+         * (non-Javadoc)
+         * 
+         * @see org.apache.wicket.Component#isVisible()
+         */
+        @Override
+        public boolean isVisible() {
+          return false;
+        }
+      });
+
+      add(new ListView<Reference>("ref_list", new ListModel<Reference>(refs)) {
+        /*
+         * (non-Javadoc)
+         * 
+         * @see
+         * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+         * .wicket.markup.html.list.ListItem)
+         */
+        @Override
+        protected void populateItem(ListItem<Reference> refItem) {
+          Reference r = refItem.getModelObject();
+          String filePath = null;
+          try {
+            filePath = new File(new URI(r.getDataStoreReference()))
+                .getAbsolutePath();
+          } catch (Exception ignore) {
+          }
+
+          refItem.add(new Label("ref_file_path", filePath));
+          refItem.add(new Label("ref_file_size", String
+              .valueOf(r.getFileSize())));
+          try {
+            refItem.add(new Label("ref_pct_transferred", NumberFormat
+                .getPercentInstance().format(
+                    fm.getFm()
+                        .getRefPctTransferred(r))));
+          } catch (DataTransferException e) {
+            LOG.log(Level.WARNING,
+                "Unable to determine product reference size: Reason: "
+                    + e.getMessage());
+            refItem.add(new Label("ref_pct_transferred", "N/A"));
+          }
+
+        }
+      });
+    } else {
+      add(new Label("no_prod_ref_display", "No Product References!"));
+    }    
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/TypeBrowser.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/TypeBrowser.css
new file mode 100644
index 0000000..3591258
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/TypeBrowser.css
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+#criteria_form_add_element_value{
+	font-weight:bold;
+}
+
+#product_table{
+	border:1px;
+	border-spacing:2px;
+	border: 1px solid #000000;
+	width:800px;
+}
+
+#product_table td{
+  border: 1px solid #000000;
+  margin: 0; 
+  padding: 2px;
+}
+
+#pagination_table{
+	border-spacing:3px;
+	width:100%;
+}
+
+#pagination_table_result_hdr{
+	width:100px;
+	white-space: nowrap;
+	font-weight:bold;
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/TypeBrowser.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/TypeBrowser.html
new file mode 100644
index 0000000..634d3fd
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/TypeBrowser.html
@@ -0,0 +1,95 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:remove>
+  <link rel="stylesheet" type="text/css" href="TypeBrowser.css"/>
+</wicket:remove>
+
+<h3 wicket:id="ptype_name">GenericFile Products</h3>
+   
+<p>Showing products <span style="font-weight:bold;" wicket:id="start_idx">1</span>-<span style="font-weight:bold;" wicket:id="end_idx">20</span> 
+of <span wicket:id="num_products">100</span> total</p>
+
+<h4>Existing Filter Criteria</h4>
+
+<form wicket:id="existing_criteria_form">
+<table>
+  <tr wicket:id="criteria_selected_row">
+    <td><span wicket:id="criteria_elem_name">CAS.ProductName</span> = 
+        <span wicket:id="criteria_elem_value">foo.txt</span>
+    </td>
+    <td><input type="submit" value="Remove" wicket:id="criteria_elem_remove"/></td>
+  </tr>
+</table>
+</form>
+
+<h4>Specify New Filter Criteria</h4>
+<form wicket:id="new_criteria_form">
+<table>
+  <tr>
+    <td><select wicket:id="criteria_list">
+        <wicket:remove>
+          <option id="urn:oodt:ProductName">ProductName</option>
+        </wicket:remove>
+        </select>
+    </td>
+    <td>
+      <input type="text" size="20" maxlength="255" id="criteria_form_add_element_value" wicket:id="criteria_form_add_element_value"/>
+    </td>
+    <td>
+      <input type="submit" value="Add" wicket:id="criteria_elem_add"/>
+    </td>
+  </tr>
+ </table>
+                
+</form>
+
+<table id="product_table">
+<tr>
+  <td>Product</td>
+  <td>Transfer Status</td>
+  <td>Percent Complete</td>
+  <td>Received Time</td>
+  <td>References</td>
+  <td>Metadata</td>
+</tr>
+<tr wicket:id="product_list">
+ <td><a href="#" wicket:id="product_page_link"><span wicket:id="product_name">Test Product</span></a></td>
+ <td wicket:id="product_transfer_status">RECEIVED</td>
+ <td wicket:id="product_pct_transferred">100%</td>
+ <td wicket:id="product_received_time">2011-01-11T00:00:01.000Z</td>
+ <td><a href="#" wicket:id="ref_page_link">View References</a></td>
+ <td><a href="#" wicket:id="met_page_link">View Metadata</a></td>
+</tr>
+</table>
+               
+<p>&nbsp;</p>
+<p>&nbsp;</p>
+<span wicket:id="paginator"></span>
+<wicket:remove>
+<hr width="*">
+<div align="center">
+<table id="pagination_table">
+  <tr>
+    <td id="pagination_table_result_hdr">Result Page</td>
+    
+
+ </tr>
+ </table>
+ </div>
+ </wicket:remove>
+</wicket:panel>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/TypeBrowser.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/TypeBrowser.java
new file mode 100644
index 0000000..3e902eb
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/TypeBrowser.java
@@ -0,0 +1,436 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.filemgr.browser.types;
+
+//JDK imports
+import java.io.Serializable;
+import java.text.NumberFormat;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Element;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Query;
+import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.webcomponents.filemgr.FMBrowserSession;
+import org.apache.oodt.cas.webcomponents.filemgr.FileManagerConn;
+import org.apache.oodt.cas.webcomponents.filemgr.browser.pagination.ProductPaginator;
+import org.apache.oodt.cas.webcomponents.filemgr.model.ProductModel;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Button;
+import org.apache.wicket.markup.html.form.ChoiceRenderer;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.link.PopupSettings;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.util.ListModel;
+
+/**
+ * 
+ * This page is mounted to:
+ * 
+ * <code>/browser/type/[TypeName]</code>.
+ * 
+ * And provides a query-based, product browser, complete with pagination
+ * provided by the attached {@link ProductPaginator} component.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TypeBrowser extends Panel {
+
+  private static final Logger LOG = Logger.getLogger(TypeBrowser.class
+      .getName());
+
+  private List<TermQueryCriteria> criteria;
+
+  private ProductType type;
+
+  private ProductPage productPage;
+
+  private int pageNum;
+
+  private int startIdx;
+
+  private int endIdx;
+
+  private int totalProducts;
+
+  private FileManagerConn fm;
+
+  private static final int PAGE_SIZE = 20;
+
+  public TypeBrowser(String componentId, String fmUrlStr,
+      String productTypeName, int pageNum,
+      final Class<? extends WebPage> typeBrowserPage,
+      final Class<? extends WebPage> produdctBrowser,
+      final Class<? extends WebPage> prodRefsBrowser,
+      final Class<? extends WebPage> prodMetBrowser) {
+
+    super(componentId);
+    this.fm = new FileManagerConn(fmUrlStr);
+    this.type = fm.safeGetProductTypeByName(productTypeName);
+    this.pageNum = pageNum;
+    this.criteria = ((FMBrowserSession) getSession()).getCriteria();
+    this.refreshProductPage();
+    this.computeStartEndIdx();
+
+    add(new ExistingCriteriaForm("existing_criteria_form"));
+    add(new AddCriteriaForm("new_criteria_form"));
+
+    add(new Label("ptype_name", type.getName()));
+    add(new Label("start_idx", String.valueOf(this.startIdx)));
+    add(new Label("end_idx", String.valueOf(this.endIdx)));
+    add(new Label("num_products", String.valueOf(this.totalProducts)));
+
+    add(new ListView<Product>("product_list", this.productPage
+        .getPageProducts()) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see
+       * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+       * .wicket.markup.html.list.ListItem)
+       */
+      @Override
+      protected void populateItem(ListItem<Product> prodItem) {
+        Link prodPageLink = new Link<Product>("product_page_link",
+            new ProductModel(prodItem.getModelObject())) {
+
+          /*
+           * (non-Javadoc)
+           * 
+           * @see org.apache.wicket.markup.html.link.Link#onClick()
+           */
+          @Override
+          public void onClick() {
+            PageParameters params = new PageParameters();
+            params.add("id", this.getModelObject().getProductId());
+            setResponsePage(produdctBrowser, params);
+
+          }
+        };
+
+        prodPageLink.add(new Label("product_name", prodItem.getModelObject()
+            .getProductName()));
+        prodItem.add(prodPageLink);
+
+        prodItem.add(new Label("product_transfer_status", prodItem
+            .getModelObject().getTransferStatus()));
+        try {
+          prodItem.add(new Label("product_pct_transferred", NumberFormat
+              .getPercentInstance().format(
+                  fm.getFm()
+                      .getProductPctTransferred(prodItem.getModelObject()))));
+        } catch (DataTransferException e) {
+          LOG.log(Level.WARNING,
+              "Unable to obtain transfer percentage for product: ["
+                  + prodItem.getModelObject().getProductName() + "]: Reason: "
+                  + e.getMessage());
+        }
+
+        String prodReceivedTime = fm.getProdReceivedTime(prodItem
+            .getModelObject());
+        prodItem.add(new Label("product_received_time", prodReceivedTime));
+        PopupSettings refSettings = new PopupSettings();
+        refSettings.setWidth(525).setHeight(450).setWindowName("_refWin");
+        Link<String> refLink = new Link<String>("ref_page_link",
+            new Model<String>(prodItem.getModelObject().getProductId())) {
+
+          /*
+           * (non-Javadoc)
+           * 
+           * @see org.apache.wicket.markup.html.link.Link#onClick()
+           */
+          @Override
+          public void onClick() {
+            PageParameters params = new PageParameters();
+            params.add("id", getModelObject());
+            setResponsePage(prodRefsBrowser, params);
+
+          }
+        };
+        refLink.setPopupSettings(refSettings);
+        prodItem.add(refLink);
+
+        SerializableMetadata met = new SerializableMetadata(fm
+            .getMetadata(prodItem.getModelObject()));
+        Link<String> metLink = new Link<String>("met_page_link", new Model(
+            prodItem.getModelObject().getProductId())) {
+
+          /*
+           * (non-Javadoc)
+           * 
+           * @see org.apache.wicket.markup.html.link.Link#onClick()
+           */
+          @Override
+          public void onClick() {
+            PageParameters params = new PageParameters();
+            params.add("id", getModelObject());
+            setResponsePage(prodMetBrowser, params);
+
+          }
+
+        };
+
+        PopupSettings metSettings = new PopupSettings();
+        metSettings.setWidth(525).setHeight(450).setWindowName("_metWin");
+        metLink.setPopupSettings(metSettings);
+        prodItem.add(metLink);
+
+      }
+
+    });
+
+    add(new ProductPaginator("paginator", this.productPage,
+        this.type.getName(), typeBrowserPage));
+
+  }
+
+  private void refreshProductPage() {
+    Query query = new Query();
+    System.out.println("CALLING REFRESH PRODUCT PAGE, CRITERIA:");
+    for (TermQueryCriteria crit : this.criteria) {
+      System.out.println(crit);
+    }
+    query.getCriteria().addAll(this.criteria);
+    try {
+      this.productPage = fm.getFm().pagedQuery(query, type, this.pageNum);
+    } catch (CatalogException e) {
+      LOG.log(Level.SEVERE, "Unable to obtain page products: type: ["
+          + type.getName() + "]: Reason: " + e.getMessage());
+    }
+  }
+
+  private void computeStartEndIdx() {
+    if (this.productPage.getTotalPages() == 1) {
+      this.totalProducts = this.productPage.getPageProducts().size();
+      this.pageNum = 1;
+    } else if (productPage.getTotalPages() == 0) {
+      this.totalProducts = 0;
+      this.pageNum = 1;
+    } else {
+      this.totalProducts = (productPage.getTotalPages() - 1) * PAGE_SIZE;
+      this.pageNum = this.productPage.getPageNum();
+
+      // get the last page
+      ProductPage lastPage = null;
+      Query query = new Query();
+      query.getCriteria().addAll(this.criteria);
+
+      try {
+        lastPage = fm.getFm().pagedQuery(query, this.type,
+            this.productPage.getTotalPages());
+        this.totalProducts += lastPage.getPageProducts().size();
+      } catch (Exception ignore) {
+      }
+    }
+    this.endIdx = this.totalProducts != 0 ? Math.min(this.totalProducts,
+        (PAGE_SIZE) * (this.pageNum)) : 0;
+    this.startIdx = this.totalProducts != 0 ? ((this.pageNum - 1) * PAGE_SIZE) + 1
+        : 0;
+  }
+
+  public class ExistingCriteriaForm extends Form<List<TermQueryCriteria>> {
+
+    /**
+     * @param id
+     *          The wicket:id identifier of the criteria form.
+     */
+    public ExistingCriteriaForm(String id) {
+      super(id);
+      ListView<TermQueryCriteria> criteriaView = new ListView<TermQueryCriteria>(
+          "criteria_selected_row", criteria) {
+
+        @Override
+        protected void populateItem(ListItem<TermQueryCriteria> item) {
+          item.add(new Label("criteria_elem_name", item.getModelObject()
+              .getElementName()));
+          item.add(new Label("criteria_elem_value", item.getModelObject()
+              .getValue()));
+          item.add(new TermQueryCriteriaRemoveButton("criteria_elem_remove",
+              item.getModelObject()));
+        }
+      };
+      criteriaView.setReuseItems(true);
+      add(criteriaView);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.wicket.markup.html.form.Form#onSubmit()
+     */
+    @Override
+    protected void onSubmit() {
+    }
+
+  }
+
+  class AddCriteriaForm extends Form<ElementCrit> {
+
+    private static final long serialVersionUID = -4543355158252106121L;
+
+    /**
+     * @param id
+     *          The wicket:id component ID of this form.
+     */
+    public AddCriteriaForm(String id) {
+      super(id, new CompoundPropertyModel<ElementCrit>(new ElementCrit()));
+      List<Element> ptypeElements = fm.safeGetElementsForProductType(type);
+      Collections.sort(ptypeElements, new Comparator<Element>() {
+        public int compare(Element e1, Element e2) {
+          return e1.getElementName().compareTo(e2.getElementName());
+        }
+      });
+
+      add(new DropDownChoice<Element>("criteria_list", new PropertyModel(
+          getDefaultModelObject(), "elem"), new ListModel<Element>(
+          ptypeElements), new ChoiceRenderer<Element>("elementName",
+          "elementId")));
+      add(new TextField<TermQueryCriteria>(
+          "criteria_form_add_element_value",
+          new PropertyModel<TermQueryCriteria>(getDefaultModelObject(), "value")));
+      add(new Button("criteria_elem_add"));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.wicket.markup.html.form.Form#onSubmit()
+     */
+    @Override
+    protected void onSubmit() {
+      ElementCrit tc = (ElementCrit) getDefaultModelObject();
+      for (TermQueryCriteria tqc : criteria) {
+        if (tqc.getElementName().equals(tc.getElem().getElementName())) {
+          return;
+        }
+      }
+      criteria.add(new TermQueryCriteria(tc.getElem().getElementName(), tc
+          .getValue()));
+      ((FMBrowserSession) getSession()).setCriteria(criteria);
+      refreshProductPage();
+      computeStartEndIdx();
+      PageParameters parameters = new PageParameters();
+      parameters.add("name", type.getName());
+      parameters.add("pageNum", String.valueOf(pageNum));
+      setResponsePage(getPage().getClass(), parameters);
+    }
+  }
+
+  class ElementCrit implements Serializable {
+
+    private static final long serialVersionUID = -5864863564626117763L;
+
+    private Element elem;
+
+    private String value;
+
+    public ElementCrit() {
+      this.elem = null;
+      this.value = null;
+    }
+
+    /**
+     * @return the elem
+     */
+    public Element getElem() {
+      return elem;
+    }
+
+    /**
+     * @param elem
+     *          the elem to set
+     */
+    public void setElem(Element elem) {
+      this.elem = elem;
+    }
+
+    /**
+     * @return the value
+     */
+    public String getValue() {
+      return value;
+    }
+
+    /**
+     * @param value
+     *          the value to set
+     */
+    public void setValue(String value) {
+      this.value = value;
+    }
+  }
+
+  class TermQueryCriteriaRemoveButton extends Button {
+
+    private TermQueryCriteria crit;
+
+    public TermQueryCriteriaRemoveButton(String id, TermQueryCriteria crit) {
+      super(id);
+      this.crit = crit;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.wicket.markup.html.form.Button#onSubmit()
+     */
+    @Override
+    public void onSubmit() {
+      for (int i = 0; i < criteria.size(); i++) {
+        TermQueryCriteria cr = criteria.get(i);
+        if (cr.getElementName().equals(crit.getElementName())) {
+          criteria.remove(i);
+          ((FMBrowserSession) getSession()).setCriteria(criteria);
+          refreshProductPage();
+          computeStartEndIdx();
+          PageParameters parameters = new PageParameters();
+          parameters.add("name", type.getName());
+          parameters.add("pageNum", String.valueOf(pageNum));
+          setResponsePage(getPage().getClass(), parameters);
+          break;
+        }
+      }
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/Types.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/Types.css
new file mode 100644
index 0000000..1c35c74
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/Types.css
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+#cas_fm_browser_ptype_table{
+  padding:2px;
+  border-spacing:2px;
+  width:800px;
+  border: 1px solid #000000;
+}
+
+#cas_fm_browser_ptype_table td{
+  border: 1px solid #000000;
+  margin: 0; 
+  padding: 2px;
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/Types.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/Types.html
new file mode 100644
index 0000000..124563f
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/Types.html
@@ -0,0 +1,33 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:remove>
+  <link rel="stylesheet" type="text/css" href="Types.css"/>
+</wicket:remove>
+
+
+<h3>Product Types</h3>
+<table id="cas_fm_browser_ptype_table">
+ <tr wicket:id="cas_fm_browser_ptype_table_rows">
+   <td wicket:id="type_name">GenericFile</td>
+   <td>(<a href="#" wicket:id="type_count_link"><span wicket:id="type_count">1000000</span></a>)</td>
+   <td wicket:id="type2_name">GenericFile2</td>
+   <td>(<a href="#" wicket:id="type2_count_link"><span wicket:id="type2_count">50</span></a>)</td>   
+ </tr>
+</table>
+</wicket:panel>
+ 
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/Types.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/Types.java
new file mode 100644
index 0000000..703589d
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/browser/types/Types.java
@@ -0,0 +1,289 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.filemgr.browser.types;
+
+//JDK imports
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.webcomponents.filemgr.FileManagerConn;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.util.GenericBaseModel;
+
+/**
+ * 
+ * This page is mounted to:
+ * 
+ * <code>/browser/types</code> and shows a type plus 
+ * its num product count.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class Types extends Panel {
+
+  private static final long serialVersionUID = 6263193710066495653L;
+
+  private static final Logger LOG = Logger.getLogger(Types.class.getName());
+  
+  private FileManagerConn fm;
+
+  private static final String BLANK_SPACE = " ";
+
+  public Types(String componentId, String fmUrlStr, final Class<? extends WebPage> typeBrowser) {
+    super(componentId);
+    this.fm = new FileManagerConn(fmUrlStr);
+    List<ProductType> types = this.fm.safeGetProductTypes();
+    Collections.sort(types, new Comparator<ProductType>() {
+      public int compare(ProductType type1, ProductType type2) {
+           return type1.getName().compareTo(type2.getName());
+      }
+    });
+    List<TypeCountTuple> counts = this.toTypeCounts(types);
+    add(new ListView<TypeCountTuple>("cas_fm_browser_ptype_table_rows", counts) {
+
+      /*
+       * (non-Javadoc)
+       * 
+       * @see
+       * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+       * .wicket.markup.html.list.ListItem)
+       */
+      @Override
+      protected void populateItem(ListItem<TypeCountTuple> type) {
+        if (type.getModelObject().getTypes().size() == 1) {
+          type.add(new Label("type_name", type.getModelObject().getTypes().get(
+              0).getName()));
+          Link<ProductType> typeCountLink = new Link<ProductType>(
+              "type_count_link", new ProductTypeModel(type.getModelObject()
+                  .getTypes().get(0))) {
+            /*
+             * (non-Javadoc)
+             * 
+             * @see org.apache.wicket.markup.html.link.Link#onClick()
+             */
+            @Override
+            public void onClick() {
+              PageParameters params = new PageParameters();
+              params.add("name", this.getModelObject().getName());
+              params.add("pageNum", "1");
+              setResponsePage(typeBrowser, params);
+
+            }
+          };
+          typeCountLink.add(new Label("type_count", String.valueOf(type
+              .getModelObject().getCounts().get(0))));
+          type.add(typeCountLink);
+          Link<ProductType> type2Link = new Link<ProductType>(
+              "type2_count_link") {
+            /*
+             * (non-Javadoc)
+             * 
+             * @see org.apache.wicket.Component#isVisible()
+             */
+            @Override
+            public boolean isVisible() {
+              return false;
+            }
+
+            @Override
+            public void onClick() {
+            }
+          };
+          type.add(new Label("type2_name", BLANK_SPACE));
+          type2Link.add(new Label("type2_count", BLANK_SPACE));
+          type.add(type2Link);
+
+        } else {
+          type.add(new Label("type_name", type.getModelObject().getTypes().get(
+              0).getName()));
+          Link<ProductType> typeCountLink = new Link<ProductType>(
+              "type_count_link", new ProductTypeModel(type.getModelObject()
+                  .getTypes().get(0))) {
+            /*
+             * (non-Javadoc)
+             * 
+             * @see org.apache.wicket.markup.html.link.Link#onClick()
+             */
+            @Override
+            public void onClick() {
+              PageParameters params = new PageParameters();
+              params.add("name", this.getModelObject().getName());
+              params.add("pageNum", "1");
+              setResponsePage(typeBrowser, params);
+
+            }
+          };
+          typeCountLink.add(new Label("type_count", String.valueOf(type
+              .getModelObject().getCounts().get(0))));
+          type.add(typeCountLink);
+          type.add(new Label("type2_name", type.getModelObject().getTypes()
+              .get(1).getName()));
+          Link<ProductType> type2Link = new Link<ProductType>(
+              "type2_count_link", new ProductTypeModel(type.getModelObject()
+                  .getTypes().get(1))) {
+            /*
+             * (non-Javadoc)
+             * 
+             * @see org.apache.wicket.markup.html.link.Link#onClick()
+             */
+            @Override
+            public void onClick() {
+              PageParameters params = new PageParameters();
+              params.add("name", this.getModelObject().getName());
+              params.add("pageNum", "1");
+              setResponsePage(typeBrowser, params);
+
+            }
+          };
+          type2Link.add(new Label("type2_count", String.valueOf(type
+              .getModelObject().getCounts().get(1))));
+          type.add(type2Link);
+        }
+
+      }
+    });
+  }
+
+  private List<TypeCountTuple> toTypeCounts(List<ProductType> types) {
+    List<TypeCountTuple> counts = new Vector<TypeCountTuple>();
+    TypeCountTuple tuple = new TypeCountTuple();
+    for (int i = 0; i < types.size(); i++) {
+      ProductType type = types.get(i);
+      if (tuple.getTypes().size() == 2) {
+        counts.add(tuple);
+        tuple = new TypeCountTuple();
+      }
+      tuple.getTypes().add(type);
+      try {
+        tuple.getCounts().add(fm.getFm().getNumProducts(type));
+      } catch (CatalogException e) {
+        e.printStackTrace();
+        LOG.log(Level.WARNING, "Unable to set count for product type: ["
+            + type.getName() + "]: Reason: [" + e.getMessage() + "]");
+      }
+
+      if (i == types.size() - 1) {
+        counts.add(tuple);
+      }
+
+    }
+
+    return counts;
+  }
+
+  class TypeCountTuple implements Serializable {
+
+    private static final long serialVersionUID = 7908536266142876646L;
+
+    private List<ProductType> types;
+
+    private List<Integer> counts;
+
+    public TypeCountTuple() {
+      this.types = new Vector<ProductType>();
+      this.counts = new Vector<Integer>();
+    }
+
+    /**
+     * @return the types
+     */
+    public List<ProductType> getTypes() {
+      return types;
+    }
+
+    /**
+     * @param types
+     *          the types to set
+     */
+    public void setTypes(List<ProductType> types) {
+      this.types = types;
+    }
+
+    /**
+     * @return the counts
+     */
+    public List<Integer> getCounts() {
+      return counts;
+    }
+
+    /**
+     * @param counts
+     *          the counts to set
+     */
+    public void setCounts(List<Integer> counts) {
+      this.counts = counts;
+    }
+
+  }
+
+  class ProductTypeModel extends GenericBaseModel<ProductType> {
+
+    private static final long serialVersionUID = 6528976699866791800L;
+
+    public ProductTypeModel(ProductType type) {
+      this.setObject(type);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.wicket.model.util.GenericBaseModel#createSerializableVersionOf
+     * (java.lang.Object)
+     */
+    @Override
+    protected ProductType createSerializableVersionOf(ProductType type) {
+      SerializableProductType stype = new SerializableProductType();
+      stype.setDescription(type.getDescription());
+      stype.setExtractors(type.getExtractors());
+      stype.setHandlers(type.getHandlers());
+      stype.setName(type.getName());
+      stype.setProductRepositoryPath(type.getProductRepositoryPath());
+      stype.setProductTypeId(type.getProductTypeId());
+      stype.setTypeMetadata(type.getTypeMetadata());
+      stype.setVersioner(type.getVersioner());
+      return stype;
+    }
+
+  }
+  
+  class SerializableProductType extends ProductType implements Serializable {
+
+    private static final long serialVersionUID = 6900948355619420582L;
+    
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/model/ProductModel.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/model/ProductModel.java
new file mode 100644
index 0000000..57809a0
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/filemgr/model/ProductModel.java
@@ -0,0 +1,69 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.filemgr.model;
+
+//JDK imports
+import java.io.Serializable;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.wicket.model.util.GenericBaseModel;
+
+/**
+ * 
+ * A {@link Serializable} {@link GenericBaseModel} version of a CAS
+ * {@link Product}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ProductModel extends GenericBaseModel<Product> {
+
+  private static final long serialVersionUID = 2389290520013490102L;
+
+  public ProductModel(Product product) {
+    this.setObject(product);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.wicket.model.util.GenericBaseModel#createSerializableVersionOf
+   * (java.lang.Object)
+   */
+  @Override
+  protected Product createSerializableVersionOf(Product product) {
+    SerializableProduct sp = new SerializableProduct();
+    sp.setProductId(product.getProductId());
+    sp.setProductName(product.getProductName());
+    sp.setProductReferences(product.getProductReferences());
+    sp.setProductStructure(product.getProductStructure());
+    sp.setProductType(product.getProductType());
+    sp.setRootRef(product.getRootRef());
+    sp.setTransferStatus(product.getTransferStatus());
+    return sp;
+  }
+
+  class SerializableProduct extends Product implements Serializable {
+
+    private static final long serialVersionUID = 2052147876863984740L;
+
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/WMMonitorAppBase.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/WMMonitorAppBase.java
new file mode 100644
index 0000000..22cbafb
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/WMMonitorAppBase.java
@@ -0,0 +1,63 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.workflow;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.wicket.protocol.http.WebApplication;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public abstract class WMMonitorAppBase extends WebApplication {
+
+  public String getWorkflowUrl() {
+    return getContextParamEnvReplace("workflow.url");
+  }
+
+  public String getLifecycleFilePath() {
+    return getContextParamEnvReplace("org.apache.oodt.cas.workflow.webapp.lifecycleFilePath");
+  }
+
+  public List<String> getStatuses() {
+    String[] statuses = getContextParamEnvReplace("org.apache.oodt.cas.workflow.inst.statuses").split(",");
+    List<String> statusList = new Vector<String>();
+    for(String status: statuses){
+      statusList.add(status.trim());
+    }
+    statusList.add("ALL");
+    return statusList;
+  }
+
+  public String getInstMetFieldsFilePath() {
+    return getContextParamEnvReplace("org.apache.oodt.cas.workflow.webapp.inst.metFields.filePath");
+  }
+
+  private String getContextParamEnvReplace(String paramName) {
+    return PathUtils.replaceEnvVariables(this.getServletContext()
+        .getInitParameter(paramName));
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/WorkflowMgrConn.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/WorkflowMgrConn.java
new file mode 100644
index 0000000..45b3129
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/WorkflowMgrConn.java
@@ -0,0 +1,221 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.workflow;
+
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowMgrConn implements Serializable {
+
+  private static final long serialVersionUID = -9081117871702614402L;
+
+  private static final Logger LOG = Logger.getLogger(WorkflowMgrConn.class
+      .getName());
+
+  private XmlRpcWorkflowManagerClient wm;
+
+  public WorkflowMgrConn(String wmUrlStr) {
+    try {
+      this.wm = new XmlRpcWorkflowManagerClient(new URL(wmUrlStr));
+    } catch (MalformedURLException e) {
+      LOG.log(Level.SEVERE, "Unable to contact Workflow Manager at URL: ["
+          + wmUrlStr + "]: Message: " + e.getMessage());
+      this.wm = null;
+    }
+  }
+
+  public WorkflowTask safeGetTaskById(String taskId) {
+    try {
+      return new SerializableWorkflowTask(this.wm.getTaskById(taskId));
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to obtain workflow task with ID: ["
+          + taskId + "]: Message: " + e.getMessage());
+      return null;
+    }
+  }
+
+  public WorkflowCondition safeGetConditionById(String conditionId) {
+    try {
+      return new SerializableWorkflowCondition(this.wm
+          .getConditionById(conditionId));
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to obtain workflow condition with ID: ["
+          + conditionId + "]: Message: " + e.getMessage());
+      return null;
+    }
+  }
+
+  public Workflow safeGetWorkflowById(String workflowId) {
+    try {
+      return this.wm.getWorkflowById(workflowId);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to obtain workflow with ID: ["
+          + workflowId + "]: Message: " + e.getMessage());
+      return null;
+    }
+  }
+
+  public List<Workflow> safeGetWorkflowsByEvent(String eventName) {
+    try {
+      return this.wm.getWorkflowsByEvent(eventName);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to obtain workflows by event: ["
+          + eventName + "]: Message: " + e.getMessage());
+      return new Vector<Workflow>();
+    }
+  }
+
+  public List<String> safeGetRegisteredEvents() {
+    try {
+      return this.wm.getRegisteredEvents();
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to obtain registered events: Message: "
+          + e.getMessage());
+      return new Vector<String>();
+    }
+  }
+
+  public List<Workflow> safeGetWorkflows() {
+    try {
+      return this.wm.getWorkflows();
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to obtain workflows: Message: "
+          + e.getMessage());
+      return new Vector<Workflow>();
+    }
+  }
+
+  public List<WorkflowInstance> safeGetWorkflowInsts() {
+    try {
+      return this.wm.getWorkflowInstances();
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to obtain workflow instances: Message: "
+          + e.getMessage());
+      return new Vector<WorkflowInstance>();
+    }
+  }
+
+  public List<WorkflowInstance> safeGetWorkflowInstsByStatus(String status) {
+    try {
+      return this.wm.getWorkflowInstancesByStatus(status);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to obtain workflow instances by status: ["
+          + status + "]: Message: " + e.getMessage());
+      return new Vector<WorkflowInstance>();
+    }
+  }
+
+  public WorkflowInstancePage safeGetWorkflowInstPageByStatus(int pageNum,
+      String status) {
+    try {
+      return this.wm.paginateWorkflowInstances(pageNum, status);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to obtain workflow instance page: ["
+          + pageNum + "] by status: [" + status + "]: Message: "
+          + e.getMessage());
+      return null;
+    }
+  }
+
+  public WorkflowInstancePage safeGetWorkflowInstPageByStatus(int pageNum) {
+    try {
+      return this.wm.paginateWorkflowInstances(pageNum);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Unable to obtain workflow instance page: ["
+          + pageNum + "]: Message: " + e.getMessage());
+      return null;
+    }
+  }
+
+  public double safeGetWorkflowWallClockMinutes(WorkflowInstance inst) {
+    try {
+      return this.wm.getWorkflowWallClockMinutes(inst.getId());
+    } catch (Exception e) {
+      LOG.log(Level.WARNING,
+          "Unable to obtain workflow wall clock mins: inst id: ["
+              + inst.getId() + "]: Message: " + e.getMessage());
+      return -999.0;
+    }
+  }
+
+  public double safeGetWorkflowCurrentTaskWallClockMinutes(WorkflowInstance inst) {
+    try {
+      return this.wm.getWorkflowCurrentTaskWallClockMinutes(inst.getId());
+    } catch (Exception e) {
+      LOG.log(Level.WARNING,
+          "Unable to obtain workflow current task wall clock mins: inst id: ["
+              + inst.getId() + "]: Message: " + e.getMessage());
+      return -999.0;
+    }
+  }
+
+  public XmlRpcWorkflowManagerClient getWM() {
+    return this.wm;
+  }
+
+  class SerializableWorkflowTask extends WorkflowTask implements Serializable {
+
+    private static final long serialVersionUID = 6859678680008137795L;
+
+    public SerializableWorkflowTask(WorkflowTask task) {
+      this.taskName = task.getTaskName();
+      this.taskId = task.getTaskId();
+      this.taskInstanceClassName = task.getTaskInstanceClassName();
+      this.preConditions = task.getPreConditions();
+      this.postConditions = task.getPostConditions();
+      this.order = task.getOrder();
+      this.requiredMetFields = task.getRequiredMetFields();
+      this.taskConfig = task.getTaskConfig();
+    }
+  }
+
+  class SerializableWorkflowCondition extends WorkflowCondition implements
+      Serializable {
+
+    private static final long serialVersionUID = 909843381568743621L;
+
+    public SerializableWorkflowCondition(WorkflowCondition cond) {
+      this.setConditionName(cond.getConditionName());
+      this.conditionInstanceClassName = cond.getConditionInstanceClassName();
+      this.order = cond.getOrder();
+      this.condConfig = cond.getTaskConfig();
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/conditions/WorkflowConditionViewer.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/conditions/WorkflowConditionViewer.css
new file mode 100644
index 0000000..bac5ab3
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/conditions/WorkflowConditionViewer.css
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+#condition_tbl{
+  border-spacing:2px;
+  font-family: Arial,Sans-Serif,sans-serif;
+}
+
+.header{
+
+}
+
+.value{
+
+}
+
+#workflow_cond_config_tbl{
+  border-spacing:2px;
+  font-family: Arial,Sans-Serif,sans-serif;
+}
+
+#cond_config{
+	
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/conditions/WorkflowConditionViewer.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/conditions/WorkflowConditionViewer.html
new file mode 100644
index 0000000..806dd96
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/conditions/WorkflowConditionViewer.html
@@ -0,0 +1,51 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:link>
+  <link rel="stylesheet" type="text/css" href="WorkflowConditionViewer.css"/>
+</wicket:link>
+
+<table id="condition_tbl">
+   <tr>
+     <td class="header">Condition ID</td>
+     <td class="value"><span wicket:id="condition_id">urn:oodt:TrueCondition</span></td>
+   </tr>
+   <tr>       	    	          
+     <td class="header">Name</td>
+     <td class="value"><span wicket:id="condition_name">True Condition</span></td>
+   </tr>
+   <tr>
+     <td class="header">Implementation Class</td>
+     <td class="value"><span wicket:id="condition_class">org.apache.oodt.cas.workflow.examples.TrueCondition</span></td>
+   </tr>
+  <tr>
+    <td class="header">Configuration</td>
+    <td>
+      <table id="workflow_cond_config_tbl">
+       <tr class="header">
+         <td>Property</td>
+         <td>Value</td>
+       </tr>
+       <tr wicket:id="cond_config" id="cond_config">
+  	     <td><span wicket:id="cond_pname">numSeconds</span></td>
+  	     <td><span wicket:id="cond_pvalue">60</span></td>
+       </tr>
+      </table>
+     </td>
+    </tr>   
+</table>
+</wicket:panel>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/conditions/WorkflowConditionViewer.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/conditions/WorkflowConditionViewer.java
new file mode 100644
index 0000000..09612bc
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/conditions/WorkflowConditionViewer.java
@@ -0,0 +1,80 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.workflow.conditions;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.oodt.cas.webcomponents.workflow.WorkflowMgrConn;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionConfiguration;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.util.ListModel;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowConditionViewer extends Panel {
+
+  private static final long serialVersionUID = 7861466388954745105L;
+
+  private WorkflowMgrConn wm;
+
+  public WorkflowConditionViewer(String id, String wmUrlStr, String conditionId) {
+    super(id);
+    this.wm = new WorkflowMgrConn(wmUrlStr);
+    final WorkflowCondition cond = this.wm.safeGetConditionById(conditionId);
+    add(new Label("condition_id", cond.getConditionId()));
+    add(new Label("condition_name", cond.getConditionName()));
+    add(new Label("condition_class", cond.getConditionInstanceClassName()));
+    final WorkflowConditionConfiguration config = cond.getCondConfig() != null ? 
+        cond.getCondConfig():new WorkflowConditionConfiguration();
+    List<String> condConfigKeyNames = Arrays.asList(config
+        .getProperties().keySet().toArray(
+            new String[config.getProperties().size()]));
+    Collections.sort(condConfigKeyNames);
+    add(new ListView<String>("cond_config", new ListModel<String>(
+        condConfigKeyNames)) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see
+       * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+       * .wicket.markup.html.list.ListItem)
+       */
+      @Override
+      protected void populateItem(ListItem<String> item) {
+        String keyName = item.getModelObject();
+        String keyVal = config.getProperty(keyName);
+        item.add(new Label("cond_pname", keyName));
+        item.add(new Label("cond_pvalue", keyVal));
+      }
+    });
+
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/event/EventToWorkflowViewer.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/event/EventToWorkflowViewer.css
new file mode 100644
index 0000000..94dd884
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/event/EventToWorkflowViewer.css
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+#event_header_title{
+
+}
+
+#event_workflow_tbl{
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/event/EventToWorkflowViewer.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/event/EventToWorkflowViewer.html
new file mode 100644
index 0000000..a6ec370
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/event/EventToWorkflowViewer.html
@@ -0,0 +1,54 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:link>
+ <link rel="stylesheet" type="text/css" href="EventToWorkflowViewer.css"/>
+ </wicket:link>
+
+<h3 id="event_header_title">Event to Workflow Map</h3>
+<p>Select an event, and then click on "Get Workflows" to obtain a list of workflows associated
+with the selected event.</p>
+
+<form wicket:id="event_workflow_frm">
+ <table id="event_workflow_tbl">
+    <tr>
+      <td>Event</td>
+      <td><select wicket:id="event_list">
+        <wicket:remove>
+          <option value="test">test</option>
+        </wicket:remove>
+      </select>
+      </td>
+      <td><input type="submit" id="get_workflow_button" value="Get Worfklows!"></td>
+    </tr>
+ </table>
+ </form>
+
+ <div wicket:id="wtable">
+  <hr>
+  <h4>Workflows for <span wicket:id="selectedEvent">test</span> event</h4>
+  
+  <table>
+    <tr>
+     <td>Workflow</td>
+    </tr>
+    <tr wicket:id="workflow_list">
+      <td><a href="#" wicket:id="workflow_link"><span wicket:id="workflow_name">Test Workflow</span></a></td>
+    </tr>
+  </table>
+ </div>
+</wicket:panel>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/event/EventToWorkflowViewer.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/event/EventToWorkflowViewer.java
new file mode 100644
index 0000000..0d917a8
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/event/EventToWorkflowViewer.java
@@ -0,0 +1,132 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.webcomponents.workflow.event;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.oodt.cas.webcomponents.workflow.WorkflowMgrConn;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+
+/**
+ *
+ * Describe your class here.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class EventToWorkflowViewer extends Panel {
+
+  private static final long serialVersionUID = -5120511045763328237L;
+
+  private final WorkflowMgrConn wm;
+  
+  private final List<Workflow> workflows;
+  
+  public EventToWorkflowViewer(String id, String workflowUrlStr, final Class<? extends WebPage> viewerPage) {
+    super(id);
+    this.wm = new WorkflowMgrConn(workflowUrlStr);
+    this.workflows = new Vector<Workflow>();
+    WebMarkupContainer wTable = new WebMarkupContainer("wtable");
+    wTable.setVisible(false);
+    PropertyModel<List<Workflow>> workflowsModel = new PropertyModel<List<Workflow>>(this, "workflows");
+    ListView<Workflow> workflowView = new ListView<Workflow>("workflow_list", workflowsModel) {
+      private static final long serialVersionUID = 5894604290395257941L;
+
+      @Override
+      protected void populateItem(ListItem<Workflow> item) {
+        Link<String> wLink = new Link<String>("workflow_link", new Model(item.getModelObject().getId())){
+          
+           /* (non-Javadoc)
+           * @see org.apache.wicket.markup.html.link.Link#onClick()
+           */
+          @Override
+          public void onClick() {
+            PageParameters params = new PageParameters();
+            params.add("id", getModelObject());
+            setResponsePage(viewerPage, params);
+          }
+        };
+        
+        wLink.add(new Label("workflow_name", item.getModelObject().getName()));
+        item.add(wLink);
+      }
+    };
+
+    EventWorkflowForm form = 
+      new EventWorkflowForm("event_workflow_frm", workflowsModel, wTable);
+
+    wTable.add(workflowView);
+    add(wTable);
+    add(form);
+  }
+  
+  class EventWorkflowForm extends Form<List<Workflow>>{
+
+    private static final long serialVersionUID = -3209079518977783358L;
+    
+    private String selectedEvent;
+    
+    private WebMarkupContainer wTable;
+
+    public EventWorkflowForm(String id, IModel<List<Workflow>> model, WebMarkupContainer wTable) {
+      super(id, model);
+      add(new DropDownChoice<String>("event_list", new PropertyModel(this, "selectedEvent"), 
+          wm.safeGetRegisteredEvents()));
+      this.wTable = wTable;
+      
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wicket.markup.html.form.Form#onSubmit()
+     */
+    @Override
+    protected void onSubmit() {
+       List<Workflow> workflows = wm.safeGetWorkflowsByEvent(this.selectedEvent);
+       setDefaultModelObject(workflows);
+       if(workflows != null && workflows.size() > 0){
+         this.wTable.setVisible(true);
+         this.wTable.add(new Label("selectedEvent", this.selectedEvent));
+       }
+    }
+  
+    public String getSelectedEvent(){
+      return this.selectedEvent;
+    }
+    
+  }
+  
+  
+
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/WorkflowInstancesViewer.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/WorkflowInstancesViewer.css
new file mode 100644
index 0000000..0536f64
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/WorkflowInstancesViewer.css
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+#instance_filter_header{
+
+}
+
+a.workflow_status{
+
+}
+
+#workflow_display{
+
+}
+
+#workflow_inst_tbl{
+	border:0px;
+	border-spacing:3px;
+	border: 4px #000000;
+}
+
+.centered{
+   text-align:center;
+}
+
+.smaller{
+	font-size:9px;
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/WorkflowInstancesViewer.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/WorkflowInstancesViewer.html
new file mode 100644
index 0000000..f75f283
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/WorkflowInstancesViewer.html
@@ -0,0 +1,89 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:link>
+ <link rel="stylesheet" type="text/css" href="WorkflowInstancesViewer.css"/>
+ <link rel="stylesheet" type="text/css" href="progress_wicket.css"/>
+ <wicket:remove>
+  <link rel="stylesheet" type="text/css" href="progress.css"/> 
+ </wicket:remove>
+ <script type="text/javascript" language="Javascript" src="prototype.js"></script>
+ <script type="text/javascript" language="Javascript" src="progress.js"></script>
+</wicket:link>
+
+<div id="instance_filter_header">
+  <h4>Filter Workflows by Status:</h4>
+  <p>Select any of the following to display only workflow instances with the corresponding status:</p>
+  <wicket:container wicket:id="workflow_statuses">
+    <a class="workflow_status" wicket:id="wstatus_link" href="#"><span wicket:id="wstatus">STARTED</span></a>
+  </wicket:container> 
+    <wicket:remove>
+    <a class="workflow_status" href="#">FINISHED</a>&nbsp;|
+    <a class="workflow_status" href="#">METMISS</a>&nbsp;|            
+    <a class="workflow_status" href="#">PAUSED</a>&nbsp;|
+    <a class="workflow_status" href="#">ALL</a>&nbsp;|
+    </wicket:remove>
+</div>
+
+   <p>Workflows <b wicket:id="start_idx">1</b>-<b wicket:id="end_idx">20</b> of <b wicket:id="num_insts">20</b> total</p>
+     <table id="workflow_inst_tbl">
+       <thead class="centered">
+         <tr>
+	         <th>Workflow</th>
+	         <th>Progress</th>
+	         <th>Status</th>
+	         <th>Execution Time (min)</th>
+	         <th>Current Task Execution Time (min)</th>
+	         <th>Current Task</th> 
+         </tr>
+       </thead>
+		
+		<tbody>
+	       <tr wicket:id="workflow_insts">
+	         <td><a href="#" wicket:id="workflow_link"><span wicket:id="workflow_name">Test Workflow</span></a>
+	         <br/>
+	         <p class="smaller" wicket:id="inst_met_display">ProcessingNode:localhost,WorkflowInstanceId:1</p>
+	         </td>
+	         <td class="centered"><script wicket:id="winst_display">display('./percentImage.png', 'winst_1_progress', 66, 1);</script></td>
+	         <td class="centered" wicket:id="winst_status">RSUBMIT</td>
+	         <td class="centered" wicket:id="winst_wallclock_mins">5.22</td>
+	         <td class="centered" wicket:id="winst_task_wallclock_mins">2.5</td>
+	         <td class="centered"><a href="#" wicket:id="task_link"><span wicket:id="task_name">Hello World</span></a></td>
+	        </tr>
+        </tbody>
+    </table>
+    <p>&nbsp;</p>
+    <p>&nbsp;</p>
+    <span wicket:id="paginator"/>
+    
+    <wicket:remove>
+    <hr width="*">
+    <div align="center">
+      <table id="pagination_table">
+         <tr>
+           <td id="pagination_table_result_hdr">Result Page</td>
+         </tr>
+      </table>
+    </div>
+    </wicket:remove>
+
+  <p>&nbsp;</p>
+  <p>&nbsp;</p>
+  <p>&nbsp;</p>
+  <p>&nbsp;</p>
+</wicket:panel>
+
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/WorkflowInstancesViewer.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/WorkflowInstancesViewer.java
new file mode 100644
index 0000000..0f7d183
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/WorkflowInstancesViewer.java
@@ -0,0 +1,292 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.workflow.instance;
+
+import java.text.NumberFormat;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.webcomponents.workflow.WorkflowMgrConn;
+import org.apache.oodt.cas.webcomponents.workflow.pagination.WorkflowPagePaginator;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceMetMap;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceMetadataReader;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.wicket.IResourceListener;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.ResourceReference;
+import org.apache.wicket.behavior.SimpleAttributeModifier;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.link.ResourceLink;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.util.ListModel;
+import org.apache.wicket.util.value.ValueMap;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowInstancesViewer extends Panel {
+
+  private static final long serialVersionUID = -311004303658412137L;
+
+  private WorkflowMgrConn wm;
+
+  private int pageNum;
+
+  private int startIdx;
+
+  private int endIdx;
+
+  private int totalWorkflowInsts;
+
+  private static final int PAGE_SIZE = 20;
+
+  /**
+   * @param id
+   */
+  public WorkflowInstancesViewer(String id, String workflowUrlStr,
+      final String status, int pageNum, List<String> wStatuses,
+      final String lifecycleFilePath, final String metInstanceFilePath,
+      final Class<? extends WebPage> workflowViewer,
+      final Class<? extends WebPage> workflowTaskViewer,
+      final Class<? extends WebPage> workflowInstViewer) {
+    super(id);
+    this.wm = new WorkflowMgrConn(workflowUrlStr);
+    this.pageNum = pageNum;
+    WorkflowInstancePage page = null;
+    System.out.println("STATUS IS "+status);
+    if (status.equals("ALL")) {
+      page = this.wm.safeGetWorkflowInstPageByStatus(pageNum);
+    } else {
+      page = this.wm.safeGetWorkflowInstPageByStatus(pageNum, status);
+    }
+
+    this.computeStartEndIdx(page);
+    add(new ListView<String>("workflow_statuses", new ListModel<String>(
+        wStatuses)) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see
+       * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+       * .wicket.markup.html.list.ListItem)
+       */
+      @Override
+      protected void populateItem(ListItem<String> item) {
+        Link<String> wStatusLink = new Link<String>("wstatus_link", new Model(
+            item.getModelObject())) {
+          /*
+           * (non-Javadoc)
+           * 
+           * @see org.apache.wicket.markup.html.link.Link#onClick()
+           */
+          @Override
+          public void onClick() {
+            PageParameters params = new PageParameters();
+            params.add("status", getModelObject());
+            setResponsePage(getPage().getClass(), params);
+
+          }
+        };
+
+        Label wStatusLabel = new Label("wstatus", item.getModelObject());
+        if (item.getModelObject().equals(status)) {
+          wStatusLabel.add(new SimpleAttributeModifier("class", "selected"));
+        }
+        wStatusLink.add(wStatusLabel);
+        item.add(wStatusLink);
+      }
+    });
+
+    add(new Label("start_idx", String.valueOf(this.startIdx)));
+    add(new Label("end_idx", String.valueOf(this.endIdx)));
+    add(new Label("num_insts", String.valueOf(this.totalWorkflowInsts)));
+
+    add(new ListView<WorkflowInstance>("workflow_insts",
+        new ListModel<WorkflowInstance>(page.getPageWorkflows())) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see
+       * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+       * .wicket.markup.html.list.ListItem)
+       */
+      @Override
+      protected void populateItem(ListItem<WorkflowInstance> item) {
+        WorkflowInstance inst = item.getModelObject();
+        Link<String> workflowLink = new Link<String>("workflow_link", new Model<String>(inst
+            .getWorkflow().getId())) {
+          /*
+           * (non-Javadoc)
+           * 
+           * @see org.apache.wicket.markup.html.link.Link#onClick()
+           */
+          @Override
+          public void onClick() {
+            PageParameters params = new PageParameters();
+            params.add("id", getModelObject());
+            setResponsePage(workflowViewer, params);
+          }
+        };
+        workflowLink.add(new Label("workflow_name", inst.getWorkflow().getName()));
+        item.add(workflowLink);
+
+        String instMetString = getWorkflowInstMet(inst, metInstanceFilePath);
+        item.add(new Label("inst_met_display", instMetString));
+
+        ResourceReference imgRef = new ResourceReference(WorkflowInstancesViewer.class,
+            "percentImage.png");
+        imgRef.bind(getApplication());
+        String resRefString = getRequestCycle().urlFor(imgRef, new ValueMap()).toString();
+        item.add(new Label("winst_display", "display('" + resRefString
+            + "', 'winst_" + inst.getId() + "_progress', "
+            + getPctComplete(inst, lifecycleFilePath) + ", 1);").setEscapeModelStrings(false));
+
+        item.add(new Label("winst_status", inst.getStatus()));
+        item.add(new Label("winst_wallclock_mins", formatWallClockMins(wm
+            .safeGetWorkflowWallClockMinutes(inst))));
+        item.add(new Label("winst_task_wallclock_mins", formatWallClockMins(wm
+            .safeGetWorkflowCurrentTaskWallClockMinutes(inst))));
+
+        Link<String> taskLink = new Link<String>("task_link", new Model<String>(inst
+            .getCurrentTaskId())) {
+          /*
+           * (non-Javadoc)
+           * 
+           * @see org.apache.wicket.markup.html.link.Link#onClick()
+           */
+          @Override
+          public void onClick() {
+            PageParameters params = new PageParameters();
+            params.add("id", getModelObject());
+            setResponsePage(workflowTaskViewer, params);
+
+          }
+        };
+        taskLink.add(new Label("task_name", getTaskNameFromTaskId(inst, inst.getCurrentTaskId())));
+        item.add(taskLink);
+
+      }
+    });
+    
+    add(new WorkflowPagePaginator("paginator", page, status, workflowInstViewer));
+
+  }
+
+  private void computeStartEndIdx(WorkflowInstancePage page) {
+    if (page.getTotalPages() == 1) {
+      this.totalWorkflowInsts = page.getPageWorkflows().size();
+      this.pageNum = 1;
+    } else if (page.getTotalPages() == 0) {
+      this.totalWorkflowInsts = 0;
+      this.pageNum = 1;
+    } else {
+      this.totalWorkflowInsts = (page.getTotalPages() - 1) * PAGE_SIZE;
+      this.pageNum = page.getPageNum();
+
+      // get the last page
+      WorkflowInstancePage lastPage = null;
+      lastPage = wm.safeGetWorkflowInstPageByStatus(page.getTotalPages());
+      this.totalWorkflowInsts += lastPage.getPageWorkflows().size();
+
+    }
+    this.endIdx = this.totalWorkflowInsts != 0 ? Math.min(
+        this.totalWorkflowInsts, (PAGE_SIZE) * (this.pageNum)) : 0;
+    this.startIdx = this.totalWorkflowInsts != 0 ? ((this.pageNum - 1) * PAGE_SIZE) + 1
+        : 0;
+  }
+
+  private String getWorkflowInstMet(WorkflowInstance inst, String metMapFilePath) {
+    WorkflowInstanceMetMap wInstMetMap = null;
+    String metString = null;
+
+    try {
+      wInstMetMap = WorkflowInstanceMetadataReader
+          .parseMetMapFile(metMapFilePath);
+      Metadata instMetadata = wm.getWM().getWorkflowInstanceMetadata(
+          inst.getId());
+      List<String> wInstFields = wInstMetMap.getFieldsForWorkflow(inst
+          .getWorkflow().getId()) != null ? wInstMetMap
+          .getFieldsForWorkflow(inst.getWorkflow().getId()) : wInstMetMap
+          .getDefaultFields();
+      StringBuffer metStrBuf = new StringBuffer();
+
+      for (String wInstField : wInstFields) {
+        metStrBuf.append(wInstField);
+        metStrBuf.append(":");
+        metStrBuf.append(instMetadata.getMetadata(wInstField));
+        metStrBuf.append(",");
+      }
+
+      metStrBuf.deleteCharAt(metStrBuf.length() - 1);
+      metString = metStrBuf.toString();
+
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+
+    return metString;
+
+  }
+
+  private String formatWallClockMins(double wallClockMins) {
+    NumberFormat fn = NumberFormat.getNumberInstance();
+    fn.setMaximumFractionDigits(2);
+    fn.setMinimumFractionDigits(2);
+    return fn.format(wallClockMins);
+  }
+
+  private String getPctComplete(WorkflowInstance inst, String lifecycleFilePath) {
+    WorkflowLifecycleManager lifecycleMgr = null;
+    try {
+      lifecycleMgr = new WorkflowLifecycleManager(lifecycleFilePath);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    return lifecycleMgr
+        .formatPct(lifecycleMgr.getPercentageComplete(inst) * 100.0);
+  }
+  
+  private String getTaskNameFromTaskId(WorkflowInstance w, String taskId) {
+    if (w.getWorkflow() != null && w.getWorkflow().getTasks() != null
+            && w.getWorkflow().getTasks().size() > 0) {
+        for(WorkflowTask task: (List<WorkflowTask>)(List<?>)w.getWorkflow().getTasks()){
+            if (task.getTaskId().equals(taskId)) {
+                return task.getTaskName();
+            }
+        }
+
+        return null;
+    } else
+        return null;
+}
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage.png b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage.png
new file mode 100644
index 0000000..c528d65
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage.png
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back.png b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back.png
new file mode 100644
index 0000000..3aeea57
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back.png
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back1.png b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back1.png
new file mode 100644
index 0000000..c4b6e2d
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back1.png
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back2.png b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back2.png
new file mode 100644
index 0000000..c13aa59
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back2.png
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back3.png b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back3.png
new file mode 100644
index 0000000..1ff7fcf
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back3.png
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back4.png b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back4.png
new file mode 100644
index 0000000..0399dc7
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/percentImage_back4.png
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/progress.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/progress.css
new file mode 100644
index 0000000..3bccf19
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/progress.css
@@ -0,0 +1,44 @@
+/*

+  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.

+*/

+

+img.percentImage1 {

+ background: white url(percentImage_back1.png) top left no-repeat;

+ padding: 0;

+ margin: 5px 0 0 0;

+ background-position: 1px 0;

+}

+

+img.percentImage2 {

+ background: white url(percentImage_back2.png) top left no-repeat;

+ padding: 0;

+ margin: 5px 0 0 0;

+ background-position: 1px 0;

+}

+

+img.percentImage3 {

+ background: white url(percentImage_back3.png) top left no-repeat;

+ padding: 0;

+ margin: 5px 0 0 0;

+ background-position: 1px 0;

+}

+

+img.percentImage4 {

+ background: white url(percentImage_back4.png) top left no-repeat;

+ padding: 0;

+ margin: 5px 0 0 0;

+ background-position: 1px 0;

+}

diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/progress.js b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/progress.js
new file mode 100644
index 0000000..4865255
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/progress.js
@@ -0,0 +1,119 @@
+/* WebAppers Progress Bar, version 0.2
+* (c) 2007 Ray Cheung
+*
+* WebAppers Progress Bar is freely distributable under the terms of an Creative Commons license.
+* For details, see the WebAppers web site: http://www.webappers.com/progressBar/
+*
+/*--------------------------------------------------------------------------*/
+
+var initial = -120;
+var imageWidth=240;
+var eachPercent = (imageWidth/2)/100;
+/************************************************************\
+*
+\************************************************************/
+function setText (id, percent)
+{
+    $(id+'Text').innerHTML = percent+"%";
+}
+/************************************************************\
+*
+\************************************************************/
+function display (img, id, percentage,color )
+{	
+	if (typeof color == "undefined") {
+    color = "1";
+  	}
+    var percentageWidth = eachPercent * percentage;
+    var actualWidth = initial + percentageWidth ;
+    document.write('<img id="'+id+'" src="'+img+'" alt="'+percentage+'%" class="percentImage'+color+'" style="background-position: '+actualWidth+'px 0pt;"/> <span id="'+id+'Text">'+percentage+'%</span>');
+}
+/************************************************************\
+*
+\************************************************************/
+function emptyProgress(id)
+{
+    var newProgress = initial+'px';
+    $(id).style.backgroundPosition=newProgress+' 0';
+    setText(id,'0');
+}
+/************************************************************\
+*
+\************************************************************/
+function getProgress(id)
+{
+    var nowWidth = $(id).style.backgroundPosition.split("px");
+    return (Math.floor(100+(nowWidth[0]/eachPercent))+'%');
+	
+}
+/************************************************************\
+*
+\************************************************************/
+function setProgress(id, percentage)
+{
+    var percentageWidth = eachPercent * percentage;
+    var newProgress = eval(initial)+eval(percentageWidth)+'px';
+    $(id).style.backgroundPosition=newProgress+' 0';
+    setText(id,percentage);
+}
+/************************************************************\
+*
+\************************************************************/
+function plus ( id, percentage )
+{
+    var nowWidth = $(id).style.backgroundPosition.split("px");
+    var nowPercent = Math.floor(100+(nowWidth[0]/eachPercent))+eval(percentage);
+    var percentageWidth = eachPercent * percentage;
+    var actualWidth = eval(nowWidth[0]) + eval(percentageWidth);
+    var newProgress = actualWidth+'px';
+    if(actualWidth>=0 && percentage <100)
+    {
+        var newProgress = 1+'px';
+        $(id).style.backgroundPosition=newProgress+' 0';
+        setText(id,100);
+        alert('full');
+    }
+    else
+    {
+        $(id).style.backgroundPosition=newProgress+' 0';
+        setText(id,nowPercent);
+    }
+}
+/************************************************************\
+*
+\************************************************************/
+function minus ( id, percentage )
+{
+    var nowWidth = $(id).style.backgroundPosition.split("px");
+    var nowPercent = Math.floor(100+(nowWidth[0]/eachPercent))-eval(percentage);
+    var percentageWidth = eachPercent * percentage;
+    var actualWidth = eval(nowWidth[0]) - eval(percentageWidth);
+    var newProgress = actualWidth+'px';
+    if(actualWidth<=-120)
+    {
+        var newProgress = -120+'px';
+        $(id).style.backgroundPosition=newProgress+' 0';
+        setText(id,0);
+        alert('empty');
+    }
+    else
+    {
+        $(id).style.backgroundPosition=newProgress+' 0';
+        setText(id,nowPercent);
+    }
+}
+/************************************************************\
+*
+\************************************************************/
+function fillProgress(id, endPercent)
+{
+    var nowWidth = $(id).style.backgroundPosition.split("px");
+    startPercent = Math.ceil(100+(nowWidth[0]/eachPercent))+1;
+    var actualWidth = initial + (eachPercent * endPercent);
+    if (startPercent <= endPercent && nowWidth[0] <= actualWidth)
+    {
+        plus(id,'1');
+        setText(id,startPercent);
+        setTimeout("fillProgress('"+id+"',"+endPercent+")",10);
+    }
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/progress_wicket.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/progress_wicket.css
new file mode 100644
index 0000000..49761db
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/progress_wicket.css
@@ -0,0 +1,44 @@
+/*

+  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.

+*/

+

+img.percentImage1 {

+ background: white url(../../images/percentImage_back1.png) top left no-repeat;

+ padding: 0;

+ margin: 5px 0 0 0;

+ background-position: 1px 0;

+}

+

+img.percentImage2 {

+ background: white url(../../images/percentImage_back2.png) top left no-repeat;

+ padding: 0;

+ margin: 5px 0 0 0;

+ background-position: 1px 0;

+}

+

+img.percentImage3 {

+ background: white url(../../images/percentImage_back3.png) top left no-repeat;

+ padding: 0;

+ margin: 5px 0 0 0;

+ background-position: 1px 0;

+}

+

+img.percentImage4 {

+ background: white url(../../images/percentImage_back4.png) top left no-repeat;

+ padding: 0;

+ margin: 5px 0 0 0;

+ background-position: 1px 0;

+}

diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/prototype.js b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/prototype.js
new file mode 100644
index 0000000..02e3d84
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/instance/prototype.js
@@ -0,0 +1,2515 @@
+/*  Prototype JavaScript framework, version 1.5.0
+ *  (c) 2005-2007 Sam Stephenson
+ *
+ *  Prototype is freely distributable under the terms of an MIT-style license.
+ *  For details, see the Prototype web site: http://prototype.conio.net/
+ *
+ */
+
+var Prototype = {
+  Version: '1.5.0',
+  BrowserFeatures: {
+    XPath: !!document.evaluate
+  },
+
+  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
+  emptyFunction: function() {},
+  K: function(x) { return x }
+}
+
+var Class = {
+  create: function() {
+    return function() {
+      this.initialize.apply(this, arguments);
+    }
+  }
+}
+
+var Abstract = new Object();
+
+Object.extend = function(destination, source) {
+  for (var property in source) {
+    destination[property] = source[property];
+  }
+  return destination;
+}
+
+Object.extend(Object, {
+  inspect: function(object) {
+    try {
+      if (object === undefined) return 'undefined';
+      if (object === null) return 'null';
+      return object.inspect ? object.inspect() : object.toString();
+    } catch (e) {
+      if (e instanceof RangeError) return '...';
+      throw e;
+    }
+  },
+
+  keys: function(object) {
+    var keys = [];
+    for (var property in object)
+      keys.push(property);
+    return keys;
+  },
+
+  values: function(object) {
+    var values = [];
+    for (var property in object)
+      values.push(object[property]);
+    return values;
+  },
+
+  clone: function(object) {
+    return Object.extend({}, object);
+  }
+});
+
+Function.prototype.bind = function() {
+  var __method = this, args = $A(arguments), object = args.shift();
+  return function() {
+    return __method.apply(object, args.concat($A(arguments)));
+  }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+  var __method = this, args = $A(arguments), object = args.shift();
+  return function(event) {
+    return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
+  }
+}
+
+Object.extend(Number.prototype, {
+  toColorPart: function() {
+    var digits = this.toString(16);
+    if (this < 16) return '0' + digits;
+    return digits;
+  },
+
+  succ: function() {
+    return this + 1;
+  },
+
+  times: function(iterator) {
+    $R(0, this, true).each(iterator);
+    return this;
+  }
+});
+
+var Try = {
+  these: function() {
+    var returnValue;
+
+    for (var i = 0, length = arguments.length; i < length; i++) {
+      var lambda = arguments[i];
+      try {
+        returnValue = lambda();
+        break;
+      } catch (e) {}
+    }
+
+    return returnValue;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create();
+PeriodicalExecuter.prototype = {
+  initialize: function(callback, frequency) {
+    this.callback = callback;
+    this.frequency = frequency;
+    this.currentlyExecuting = false;
+
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  stop: function() {
+    if (!this.timer) return;
+    clearInterval(this.timer);
+    this.timer = null;
+  },
+
+  onTimerEvent: function() {
+    if (!this.currentlyExecuting) {
+      try {
+        this.currentlyExecuting = true;
+        this.callback(this);
+      } finally {
+        this.currentlyExecuting = false;
+      }
+    }
+  }
+}
+String.interpret = function(value){
+  return value == null ? '' : String(value);
+}
+
+Object.extend(String.prototype, {
+  gsub: function(pattern, replacement) {
+    var result = '', source = this, match;
+    replacement = arguments.callee.prepareReplacement(replacement);
+
+    while (source.length > 0) {
+      if (match = source.match(pattern)) {
+        result += source.slice(0, match.index);
+        result += String.interpret(replacement(match));
+        source  = source.slice(match.index + match[0].length);
+      } else {
+        result += source, source = '';
+      }
+    }
+    return result;
+  },
+
+  sub: function(pattern, replacement, count) {
+    replacement = this.gsub.prepareReplacement(replacement);
+    count = count === undefined ? 1 : count;
+
+    return this.gsub(pattern, function(match) {
+      if (--count < 0) return match[0];
+      return replacement(match);
+    });
+  },
+
+  scan: function(pattern, iterator) {
+    this.gsub(pattern, iterator);
+    return this;
+  },
+
+  truncate: function(length, truncation) {
+    length = length || 30;
+    truncation = truncation === undefined ? '...' : truncation;
+    return this.length > length ?
+      this.slice(0, length - truncation.length) + truncation : this;
+  },
+
+  strip: function() {
+    return this.replace(/^\s+/, '').replace(/\s+$/, '');
+  },
+
+  stripTags: function() {
+    return this.replace(/<\/?[^>]+>/gi, '');
+  },
+
+  stripScripts: function() {
+    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+  },
+
+  extractScripts: function() {
+    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+    return (this.match(matchAll) || []).map(function(scriptTag) {
+      return (scriptTag.match(matchOne) || ['', ''])[1];
+    });
+  },
+
+  evalScripts: function() {
+    return this.extractScripts().map(function(script) { return eval(script) });
+  },
+
+  escapeHTML: function() {
+    var div = document.createElement('div');
+    var text = document.createTextNode(this);
+    div.appendChild(text);
+    return div.innerHTML;
+  },
+
+  unescapeHTML: function() {
+    var div = document.createElement('div');
+    div.innerHTML = this.stripTags();
+    return div.childNodes[0] ? (div.childNodes.length > 1 ?
+      $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) :
+      div.childNodes[0].nodeValue) : '';
+  },
+
+  toQueryParams: function(separator) {
+    var match = this.strip().match(/([^?#]*)(#.*)?$/);
+    if (!match) return {};
+
+    return match[1].split(separator || '&').inject({}, function(hash, pair) {
+      if ((pair = pair.split('='))[0]) {
+        var name = decodeURIComponent(pair[0]);
+        var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;
+
+        if (hash[name] !== undefined) {
+          if (hash[name].constructor != Array)
+            hash[name] = [hash[name]];
+          if (value) hash[name].push(value);
+        }
+        else hash[name] = value;
+      }
+      return hash;
+    });
+  },
+
+  toArray: function() {
+    return this.split('');
+  },
+
+  succ: function() {
+    return this.slice(0, this.length - 1) +
+      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+  },
+
+  camelize: function() {
+    var parts = this.split('-'), len = parts.length;
+    if (len == 1) return parts[0];
+
+    var camelized = this.charAt(0) == '-'
+      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+      : parts[0];
+
+    for (var i = 1; i < len; i++)
+      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+    return camelized;
+  },
+
+  capitalize: function(){
+    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+  },
+
+  underscore: function() {
+    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+  },
+
+  dasherize: function() {
+    return this.gsub(/_/,'-');
+  },
+
+  inspect: function(useDoubleQuotes) {
+    var escapedString = this.replace(/\\/g, '\\\\');
+    if (useDoubleQuotes)
+      return '"' + escapedString.replace(/"/g, '\\"') + '"';
+    else
+      return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+  }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+  if (typeof replacement == 'function') return replacement;
+  var template = new Template(replacement);
+  return function(match) { return template.evaluate(match) };
+}
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+var Template = Class.create();
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+Template.prototype = {
+  initialize: function(template, pattern) {
+    this.template = template.toString();
+    this.pattern  = pattern || Template.Pattern;
+  },
+
+  evaluate: function(object) {
+    return this.template.gsub(this.pattern, function(match) {
+      var before = match[1];
+      if (before == '\\') return match[2];
+      return before + String.interpret(object[match[3]]);
+    });
+  }
+}
+
+var $break    = new Object();
+var $continue = new Object();
+
+var Enumerable = {
+  each: function(iterator) {
+    var index = 0;
+    try {
+      this._each(function(value) {
+        try {
+          iterator(value, index++);
+        } catch (e) {
+          if (e != $continue) throw e;
+        }
+      });
+    } catch (e) {
+      if (e != $break) throw e;
+    }
+    return this;
+  },
+
+  eachSlice: function(number, iterator) {
+    var index = -number, slices = [], array = this.toArray();
+    while ((index += number) < array.length)
+      slices.push(array.slice(index, index+number));
+    return slices.map(iterator);
+  },
+
+  all: function(iterator) {
+    var result = true;
+    this.each(function(value, index) {
+      result = result && !!(iterator || Prototype.K)(value, index);
+      if (!result) throw $break;
+    });
+    return result;
+  },
+
+  any: function(iterator) {
+    var result = false;
+    this.each(function(value, index) {
+      if (result = !!(iterator || Prototype.K)(value, index))
+        throw $break;
+    });
+    return result;
+  },
+
+  collect: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      results.push((iterator || Prototype.K)(value, index));
+    });
+    return results;
+  },
+
+  detect: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      if (iterator(value, index)) {
+        result = value;
+        throw $break;
+      }
+    });
+    return result;
+  },
+
+  findAll: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      if (iterator(value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  grep: function(pattern, iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      var stringValue = value.toString();
+      if (stringValue.match(pattern))
+        results.push((iterator || Prototype.K)(value, index));
+    })
+    return results;
+  },
+
+  include: function(object) {
+    var found = false;
+    this.each(function(value) {
+      if (value == object) {
+        found = true;
+        throw $break;
+      }
+    });
+    return found;
+  },
+
+  inGroupsOf: function(number, fillWith) {
+    fillWith = fillWith === undefined ? null : fillWith;
+    return this.eachSlice(number, function(slice) {
+      while(slice.length < number) slice.push(fillWith);
+      return slice;
+    });
+  },
+
+  inject: function(memo, iterator) {
+    this.each(function(value, index) {
+      memo = iterator(memo, value, index);
+    });
+    return memo;
+  },
+
+  invoke: function(method) {
+    var args = $A(arguments).slice(1);
+    return this.map(function(value) {
+      return value[method].apply(value, args);
+    });
+  },
+
+  max: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      value = (iterator || Prototype.K)(value, index);
+      if (result == undefined || value >= result)
+        result = value;
+    });
+    return result;
+  },
+
+  min: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      value = (iterator || Prototype.K)(value, index);
+      if (result == undefined || value < result)
+        result = value;
+    });
+    return result;
+  },
+
+  partition: function(iterator) {
+    var trues = [], falses = [];
+    this.each(function(value, index) {
+      ((iterator || Prototype.K)(value, index) ?
+        trues : falses).push(value);
+    });
+    return [trues, falses];
+  },
+
+  pluck: function(property) {
+    var results = [];
+    this.each(function(value, index) {
+      results.push(value[property]);
+    });
+    return results;
+  },
+
+  reject: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      if (!iterator(value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  sortBy: function(iterator) {
+    return this.map(function(value, index) {
+      return {value: value, criteria: iterator(value, index)};
+    }).sort(function(left, right) {
+      var a = left.criteria, b = right.criteria;
+      return a < b ? -1 : a > b ? 1 : 0;
+    }).pluck('value');
+  },
+
+  toArray: function() {
+    return this.map();
+  },
+
+  zip: function() {
+    var iterator = Prototype.K, args = $A(arguments);
+    if (typeof args.last() == 'function')
+      iterator = args.pop();
+
+    var collections = [this].concat(args).map($A);
+    return this.map(function(value, index) {
+      return iterator(collections.pluck(index));
+    });
+  },
+
+  size: function() {
+    return this.toArray().length;
+  },
+
+  inspect: function() {
+    return '#<Enumerable:' + this.toArray().inspect() + '>';
+  }
+}
+
+Object.extend(Enumerable, {
+  map:     Enumerable.collect,
+  find:    Enumerable.detect,
+  select:  Enumerable.findAll,
+  member:  Enumerable.include,
+  entries: Enumerable.toArray
+});
+var $A = Array.from = function(iterable) {
+  if (!iterable) return [];
+  if (iterable.toArray) {
+    return iterable.toArray();
+  } else {
+    var results = [];
+    for (var i = 0, length = iterable.length; i < length; i++)
+      results.push(iterable[i]);
+    return results;
+  }
+}
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse)
+  Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+  _each: function(iterator) {
+    for (var i = 0, length = this.length; i < length; i++)
+      iterator(this[i]);
+  },
+
+  clear: function() {
+    this.length = 0;
+    return this;
+  },
+
+  first: function() {
+    return this[0];
+  },
+
+  last: function() {
+    return this[this.length - 1];
+  },
+
+  compact: function() {
+    return this.select(function(value) {
+      return value != null;
+    });
+  },
+
+  flatten: function() {
+    return this.inject([], function(array, value) {
+      return array.concat(value && value.constructor == Array ?
+        value.flatten() : [value]);
+    });
+  },
+
+  without: function() {
+    var values = $A(arguments);
+    return this.select(function(value) {
+      return !values.include(value);
+    });
+  },
+
+  indexOf: function(object) {
+    for (var i = 0, length = this.length; i < length; i++)
+      if (this[i] == object) return i;
+    return -1;
+  },
+
+  reverse: function(inline) {
+    return (inline !== false ? this : this.toArray())._reverse();
+  },
+
+  reduce: function() {
+    return this.length > 1 ? this : this[0];
+  },
+
+  uniq: function() {
+    return this.inject([], function(array, value) {
+      return array.include(value) ? array : array.concat([value]);
+    });
+  },
+
+  clone: function() {
+    return [].concat(this);
+  },
+
+  size: function() {
+    return this.length;
+  },
+
+  inspect: function() {
+    return '[' + this.map(Object.inspect).join(', ') + ']';
+  }
+});
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string){
+  string = string.strip();
+  return string ? string.split(/\s+/) : [];
+}
+
+if(window.opera){
+  Array.prototype.concat = function(){
+    var array = [];
+    for(var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+    for(var i = 0, length = arguments.length; i < length; i++) {
+      if(arguments[i].constructor == Array) {
+        for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+          array.push(arguments[i][j]);
+      } else {
+        array.push(arguments[i]);
+      }
+    }
+    return array;
+  }
+}
+var Hash = function(obj) {
+  Object.extend(this, obj || {});
+};
+
+Object.extend(Hash, {
+  toQueryString: function(obj) {
+    var parts = [];
+
+	  this.prototype._each.call(obj, function(pair) {
+      if (!pair.key) return;
+
+      if (pair.value && pair.value.constructor == Array) {
+        var values = pair.value.compact();
+        if (values.length < 2) pair.value = values.reduce();
+        else {
+        	key = encodeURIComponent(pair.key);
+          values.each(function(value) {
+            value = value != undefined ? encodeURIComponent(value) : '';
+            parts.push(key + '=' + encodeURIComponent(value));
+          });
+          return;
+        }
+      }
+      if (pair.value == undefined) pair[1] = '';
+      parts.push(pair.map(encodeURIComponent).join('='));
+	  });
+
+    return parts.join('&');
+  }
+});
+
+Object.extend(Hash.prototype, Enumerable);
+Object.extend(Hash.prototype, {
+  _each: function(iterator) {
+    for (var key in this) {
+      var value = this[key];
+      if (value && value == Hash.prototype[key]) continue;
+
+      var pair = [key, value];
+      pair.key = key;
+      pair.value = value;
+      iterator(pair);
+    }
+  },
+
+  keys: function() {
+    return this.pluck('key');
+  },
+
+  values: function() {
+    return this.pluck('value');
+  },
+
+  merge: function(hash) {
+    return $H(hash).inject(this, function(mergedHash, pair) {
+      mergedHash[pair.key] = pair.value;
+      return mergedHash;
+    });
+  },
+
+  remove: function() {
+    var result;
+    for(var i = 0, length = arguments.length; i < length; i++) {
+      var value = this[arguments[i]];
+      if (value !== undefined){
+        if (result === undefined) result = value;
+        else {
+          if (result.constructor != Array) result = [result];
+          result.push(value)
+        }
+      }
+      delete this[arguments[i]];
+    }
+    return result;
+  },
+
+  toQueryString: function() {
+    return Hash.toQueryString(this);
+  },
+
+  inspect: function() {
+    return '#<Hash:{' + this.map(function(pair) {
+      return pair.map(Object.inspect).join(': ');
+    }).join(', ') + '}>';
+  }
+});
+
+function $H(object) {
+  if (object && object.constructor == Hash) return object;
+  return new Hash(object);
+};
+ObjectRange = Class.create();
+Object.extend(ObjectRange.prototype, Enumerable);
+Object.extend(ObjectRange.prototype, {
+  initialize: function(start, end, exclusive) {
+    this.start = start;
+    this.end = end;
+    this.exclusive = exclusive;
+  },
+
+  _each: function(iterator) {
+    var value = this.start;
+    while (this.include(value)) {
+      iterator(value);
+      value = value.succ();
+    }
+  },
+
+  include: function(value) {
+    if (value < this.start)
+      return false;
+    if (this.exclusive)
+      return value < this.end;
+    return value <= this.end;
+  }
+});
+
+var $R = function(start, end, exclusive) {
+  return new ObjectRange(start, end, exclusive);
+}
+
+var Ajax = {
+  getTransport: function() {
+    return Try.these(
+      function() {return new XMLHttpRequest()},
+      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+    ) || false;
+  },
+
+  activeRequestCount: 0
+}
+
+Ajax.Responders = {
+  responders: [],
+
+  _each: function(iterator) {
+    this.responders._each(iterator);
+  },
+
+  register: function(responder) {
+    if (!this.include(responder))
+      this.responders.push(responder);
+  },
+
+  unregister: function(responder) {
+    this.responders = this.responders.without(responder);
+  },
+
+  dispatch: function(callback, request, transport, json) {
+    this.each(function(responder) {
+      if (typeof responder[callback] == 'function') {
+        try {
+          responder[callback].apply(responder, [request, transport, json]);
+        } catch (e) {}
+      }
+    });
+  }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+  onCreate: function() {
+    Ajax.activeRequestCount++;
+  },
+  onComplete: function() {
+    Ajax.activeRequestCount--;
+  }
+});
+
+Ajax.Base = function() {};
+Ajax.Base.prototype = {
+  setOptions: function(options) {
+    this.options = {
+      method:       'post',
+      asynchronous: true,
+      contentType:  'application/x-www-form-urlencoded',
+      encoding:     'UTF-8',
+      parameters:   ''
+    }
+    Object.extend(this.options, options || {});
+
+    this.options.method = this.options.method.toLowerCase();
+    if (typeof this.options.parameters == 'string')
+      this.options.parameters = this.options.parameters.toQueryParams();
+  }
+}
+
+Ajax.Request = Class.create();
+Ajax.Request.Events =
+  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
+  _complete: false,
+
+  initialize: function(url, options) {
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+    this.request(url);
+  },
+
+  request: function(url) {
+    this.url = url;
+    this.method = this.options.method;
+    var params = this.options.parameters;
+
+    if (!['get', 'post'].include(this.method)) {
+      // simulate other verbs over post
+      params['_method'] = this.method;
+      this.method = 'post';
+    }
+
+    params = Hash.toQueryString(params);
+    if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_='
+
+    // when GET, append parameters to URL
+    if (this.method == 'get' && params)
+      this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params;
+
+    try {
+      Ajax.Responders.dispatch('onCreate', this, this.transport);
+
+      this.transport.open(this.method.toUpperCase(), this.url,
+        this.options.asynchronous);
+
+      if (this.options.asynchronous)
+        setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
+
+      this.transport.onreadystatechange = this.onStateChange.bind(this);
+      this.setRequestHeaders();
+
+      var body = this.method == 'post' ? (this.options.postBody || params) : null;
+
+      this.transport.send(body);
+
+      /* Force Firefox to handle ready state 4 for synchronous requests */
+      if (!this.options.asynchronous && this.transport.overrideMimeType)
+        this.onStateChange();
+
+    }
+    catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  onStateChange: function() {
+    var readyState = this.transport.readyState;
+    if (readyState > 1 && !((readyState == 4) && this._complete))
+      this.respondToReadyState(this.transport.readyState);
+  },
+
+  setRequestHeaders: function() {
+    var headers = {
+      'X-Requested-With': 'XMLHttpRequest',
+      'X-Prototype-Version': Prototype.Version,
+      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+    };
+
+    if (this.method == 'post') {
+      headers['Content-type'] = this.options.contentType +
+        (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+      /* Force "Connection: close" for older Mozilla browsers to work
+       * around a bug where XMLHttpRequest sends an incorrect
+       * Content-length header. See Mozilla Bugzilla #246651.
+       */
+      if (this.transport.overrideMimeType &&
+          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+            headers['Connection'] = 'close';
+    }
+
+    // user-defined headers
+    if (typeof this.options.requestHeaders == 'object') {
+      var extras = this.options.requestHeaders;
+
+      if (typeof extras.push == 'function')
+        for (var i = 0, length = extras.length; i < length; i += 2)
+          headers[extras[i]] = extras[i+1];
+      else
+        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+    }
+
+    for (var name in headers)
+      this.transport.setRequestHeader(name, headers[name]);
+  },
+
+  success: function() {
+    return !this.transport.status
+        || (this.transport.status >= 200 && this.transport.status < 300);
+  },
+
+  respondToReadyState: function(readyState) {
+    var state = Ajax.Request.Events[readyState];
+    var transport = this.transport, json = this.evalJSON();
+
+    if (state == 'Complete') {
+      try {
+        this._complete = true;
+        (this.options['on' + this.transport.status]
+         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+         || Prototype.emptyFunction)(transport, json);
+      } catch (e) {
+        this.dispatchException(e);
+      }
+
+      if ((this.getHeader('Content-type') || 'text/javascript').strip().
+        match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
+          this.evalResponse();
+    }
+
+    try {
+      (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
+      Ajax.Responders.dispatch('on' + state, this, transport, json);
+    } catch (e) {
+      this.dispatchException(e);
+    }
+
+    if (state == 'Complete') {
+      // avoid memory leak in MSIE: clean up
+      this.transport.onreadystatechange = Prototype.emptyFunction;
+    }
+  },
+
+  getHeader: function(name) {
+    try {
+      return this.transport.getResponseHeader(name);
+    } catch (e) { return null }
+  },
+
+  evalJSON: function() {
+    try {
+      var json = this.getHeader('X-JSON');
+      return json ? eval('(' + json + ')') : null;
+    } catch (e) { return null }
+  },
+
+  evalResponse: function() {
+    try {
+      return eval(this.transport.responseText);
+    } catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  dispatchException: function(exception) {
+    (this.options.onException || Prototype.emptyFunction)(this, exception);
+    Ajax.Responders.dispatch('onException', this, exception);
+  }
+});
+
+Ajax.Updater = Class.create();
+
+Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
+  initialize: function(container, url, options) {
+    this.container = {
+      success: (container.success || container),
+      failure: (container.failure || (container.success ? null : container))
+    }
+
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+
+    var onComplete = this.options.onComplete || Prototype.emptyFunction;
+    this.options.onComplete = (function(transport, param) {
+      this.updateContent();
+      onComplete(transport, param);
+    }).bind(this);
+
+    this.request(url);
+  },
+
+  updateContent: function() {
+    var receiver = this.container[this.success() ? 'success' : 'failure'];
+    var response = this.transport.responseText;
+
+    if (!this.options.evalScripts) response = response.stripScripts();
+
+    if (receiver = $(receiver)) {
+      if (this.options.insertion)
+        new this.options.insertion(receiver, response);
+      else
+        receiver.update(response);
+    }
+
+    if (this.success()) {
+      if (this.onComplete)
+        setTimeout(this.onComplete.bind(this), 10);
+    }
+  }
+});
+
+Ajax.PeriodicalUpdater = Class.create();
+Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
+  initialize: function(container, url, options) {
+    this.setOptions(options);
+    this.onComplete = this.options.onComplete;
+
+    this.frequency = (this.options.frequency || 2);
+    this.decay = (this.options.decay || 1);
+
+    this.updater = {};
+    this.container = container;
+    this.url = url;
+
+    this.start();
+  },
+
+  start: function() {
+    this.options.onComplete = this.updateComplete.bind(this);
+    this.onTimerEvent();
+  },
+
+  stop: function() {
+    this.updater.options.onComplete = undefined;
+    clearTimeout(this.timer);
+    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+  },
+
+  updateComplete: function(request) {
+    if (this.options.decay) {
+      this.decay = (request.responseText == this.lastText ?
+        this.decay * this.options.decay : 1);
+
+      this.lastText = request.responseText;
+    }
+    this.timer = setTimeout(this.onTimerEvent.bind(this),
+      this.decay * this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    this.updater = new Ajax.Updater(this.container, this.url, this.options);
+  }
+});
+function $(element) {
+  if (arguments.length > 1) {
+    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+      elements.push($(arguments[i]));
+    return elements;
+  }
+  if (typeof element == 'string')
+    element = document.getElementById(element);
+  return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+  document._getElementsByXPath = function(expression, parentElement) {
+    var results = [];
+    var query = document.evaluate(expression, $(parentElement) || document,
+      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+    for (var i = 0, length = query.snapshotLength; i < length; i++)
+      results.push(query.snapshotItem(i));
+    return results;
+  };
+}
+
+document.getElementsByClassName = function(className, parentElement) {
+  if (Prototype.BrowserFeatures.XPath) {
+    var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
+    return document._getElementsByXPath(q, parentElement);
+  } else {
+    var children = ($(parentElement) || document.body).getElementsByTagName('*');
+    var elements = [], child;
+    for (var i = 0, length = children.length; i < length; i++) {
+      child = children[i];
+      if (Element.hasClassName(child, className))
+        elements.push(Element.extend(child));
+    }
+    return elements;
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Element)
+  var Element = new Object();
+
+Element.extend = function(element) {
+  if (!element || _nativeExtensions || element.nodeType == 3) return element;
+
+  if (!element._extended && element.tagName && element != window) {
+    var methods = Object.clone(Element.Methods), cache = Element.extend.cache;
+
+    if (element.tagName == 'FORM')
+      Object.extend(methods, Form.Methods);
+    if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
+      Object.extend(methods, Form.Element.Methods);
+
+    Object.extend(methods, Element.Methods.Simulated);
+
+    for (var property in methods) {
+      var value = methods[property];
+      if (typeof value == 'function' && !(property in element))
+        element[property] = cache.findOrStore(value);
+    }
+  }
+
+  element._extended = true;
+  return element;
+};
+
+Element.extend.cache = {
+  findOrStore: function(value) {
+    return this[value] = this[value] || function() {
+      return value.apply(null, [this].concat($A(arguments)));
+    }
+  }
+};
+
+Element.Methods = {
+  visible: function(element) {
+    return $(element).style.display != 'none';
+  },
+
+  toggle: function(element) {
+    element = $(element);
+    Element[Element.visible(element) ? 'hide' : 'show'](element);
+    return element;
+  },
+
+  hide: function(element) {
+    $(element).style.display = 'none';
+    return element;
+  },
+
+  show: function(element) {
+    $(element).style.display = '';
+    return element;
+  },
+
+  remove: function(element) {
+    element = $(element);
+    element.parentNode.removeChild(element);
+    return element;
+  },
+
+  update: function(element, html) {
+    html = typeof html == 'undefined' ? '' : html.toString();
+    $(element).innerHTML = html.stripScripts();
+    setTimeout(function() {html.evalScripts()}, 10);
+    return element;
+  },
+
+  replace: function(element, html) {
+    element = $(element);
+    html = typeof html == 'undefined' ? '' : html.toString();
+    if (element.outerHTML) {
+      element.outerHTML = html.stripScripts();
+    } else {
+      var range = element.ownerDocument.createRange();
+      range.selectNodeContents(element);
+      element.parentNode.replaceChild(
+        range.createContextualFragment(html.stripScripts()), element);
+    }
+    setTimeout(function() {html.evalScripts()}, 10);
+    return element;
+  },
+
+  inspect: function(element) {
+    element = $(element);
+    var result = '<' + element.tagName.toLowerCase();
+    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+      var property = pair.first(), attribute = pair.last();
+      var value = (element[property] || '').toString();
+      if (value) result += ' ' + attribute + '=' + value.inspect(true);
+    });
+    return result + '>';
+  },
+
+  recursivelyCollect: function(element, property) {
+    element = $(element);
+    var elements = [];
+    while (element = element[property])
+      if (element.nodeType == 1)
+        elements.push(Element.extend(element));
+    return elements;
+  },
+
+  ancestors: function(element) {
+    return $(element).recursivelyCollect('parentNode');
+  },
+
+  descendants: function(element) {
+    return $A($(element).getElementsByTagName('*'));
+  },
+
+  immediateDescendants: function(element) {
+    if (!(element = $(element).firstChild)) return [];
+    while (element && element.nodeType != 1) element = element.nextSibling;
+    if (element) return [element].concat($(element).nextSiblings());
+    return [];
+  },
+
+  previousSiblings: function(element) {
+    return $(element).recursivelyCollect('previousSibling');
+  },
+
+  nextSiblings: function(element) {
+    return $(element).recursivelyCollect('nextSibling');
+  },
+
+  siblings: function(element) {
+    element = $(element);
+    return element.previousSiblings().reverse().concat(element.nextSiblings());
+  },
+
+  match: function(element, selector) {
+    if (typeof selector == 'string')
+      selector = new Selector(selector);
+    return selector.match($(element));
+  },
+
+  up: function(element, expression, index) {
+    return Selector.findElement($(element).ancestors(), expression, index);
+  },
+
+  down: function(element, expression, index) {
+    return Selector.findElement($(element).descendants(), expression, index);
+  },
+
+  previous: function(element, expression, index) {
+    return Selector.findElement($(element).previousSiblings(), expression, index);
+  },
+
+  next: function(element, expression, index) {
+    return Selector.findElement($(element).nextSiblings(), expression, index);
+  },
+
+  getElementsBySelector: function() {
+    var args = $A(arguments), element = $(args.shift());
+    return Selector.findChildElements(element, args);
+  },
+
+  getElementsByClassName: function(element, className) {
+    return document.getElementsByClassName(className, element);
+  },
+
+  readAttribute: function(element, name) {
+    element = $(element);
+    if (document.all && !window.opera) {
+      var t = Element._attributeTranslations;
+      if (t.values[name]) return t.values[name](element, name);
+      if (t.names[name])  name = t.names[name];
+      var attribute = element.attributes[name];
+      if(attribute) return attribute.nodeValue;
+    }
+    return element.getAttribute(name);
+  },
+
+  getHeight: function(element) {
+    return $(element).getDimensions().height;
+  },
+
+  getWidth: function(element) {
+    return $(element).getDimensions().width;
+  },
+
+  classNames: function(element) {
+    return new Element.ClassNames(element);
+  },
+
+  hasClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    var elementClassName = element.className;
+    if (elementClassName.length == 0) return false;
+    if (elementClassName == className ||
+        elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
+      return true;
+    return false;
+  },
+
+  addClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    Element.classNames(element).add(className);
+    return element;
+  },
+
+  removeClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    Element.classNames(element).remove(className);
+    return element;
+  },
+
+  toggleClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
+    return element;
+  },
+
+  observe: function() {
+    Event.observe.apply(Event, arguments);
+    return $A(arguments).first();
+  },
+
+  stopObserving: function() {
+    Event.stopObserving.apply(Event, arguments);
+    return $A(arguments).first();
+  },
+
+  // removes whitespace-only text node children
+  cleanWhitespace: function(element) {
+    element = $(element);
+    var node = element.firstChild;
+    while (node) {
+      var nextNode = node.nextSibling;
+      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+        element.removeChild(node);
+      node = nextNode;
+    }
+    return element;
+  },
+
+  empty: function(element) {
+    return $(element).innerHTML.match(/^\s*$/);
+  },
+
+  descendantOf: function(element, ancestor) {
+    element = $(element), ancestor = $(ancestor);
+    while (element = element.parentNode)
+      if (element == ancestor) return true;
+    return false;
+  },
+
+  scrollTo: function(element) {
+    element = $(element);
+    var pos = Position.cumulativeOffset(element);
+    window.scrollTo(pos[0], pos[1]);
+    return element;
+  },
+
+  getStyle: function(element, style) {
+    element = $(element);
+    if (['float','cssFloat'].include(style))
+      style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat');
+    style = style.camelize();
+    var value = element.style[style];
+    if (!value) {
+      if (document.defaultView && document.defaultView.getComputedStyle) {
+        var css = document.defaultView.getComputedStyle(element, null);
+        value = css ? css[style] : null;
+      } else if (element.currentStyle) {
+        value = element.currentStyle[style];
+      }
+    }
+
+    if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none'))
+      value = element['offset'+style.capitalize()] + 'px';
+
+    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
+      if (Element.getStyle(element, 'position') == 'static') value = 'auto';
+    if(style == 'opacity') {
+      if(value) return parseFloat(value);
+      if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+        if(value[1]) return parseFloat(value[1]) / 100;
+      return 1.0;
+    }
+    return value == 'auto' ? null : value;
+  },
+
+  setStyle: function(element, style) {
+    element = $(element);
+    for (var name in style) {
+      var value = style[name];
+      if(name == 'opacity') {
+        if (value == 1) {
+          value = (/Gecko/.test(navigator.userAgent) &&
+            !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0;
+          if(/MSIE/.test(navigator.userAgent) && !window.opera)
+            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
+        } else if(value === '') {
+          if(/MSIE/.test(navigator.userAgent) && !window.opera)
+            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
+        } else {
+          if(value < 0.00001) value = 0;
+          if(/MSIE/.test(navigator.userAgent) && !window.opera)
+            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +
+              'alpha(opacity='+value*100+')';
+        }
+      } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat';
+      element.style[name.camelize()] = value;
+    }
+    return element;
+  },
+
+  getDimensions: function(element) {
+    element = $(element);
+    var display = $(element).getStyle('display');
+    if (display != 'none' && display != null) // Safari bug
+      return {width: element.offsetWidth, height: element.offsetHeight};
+
+    // All *Width and *Height properties give 0 on elements with display none,
+    // so enable the element temporarily
+    var els = element.style;
+    var originalVisibility = els.visibility;
+    var originalPosition = els.position;
+    var originalDisplay = els.display;
+    els.visibility = 'hidden';
+    els.position = 'absolute';
+    els.display = 'block';
+    var originalWidth = element.clientWidth;
+    var originalHeight = element.clientHeight;
+    els.display = originalDisplay;
+    els.position = originalPosition;
+    els.visibility = originalVisibility;
+    return {width: originalWidth, height: originalHeight};
+  },
+
+  makePositioned: function(element) {
+    element = $(element);
+    var pos = Element.getStyle(element, 'position');
+    if (pos == 'static' || !pos) {
+      element._madePositioned = true;
+      element.style.position = 'relative';
+      // Opera returns the offset relative to the positioning context, when an
+      // element is position relative but top and left have not been defined
+      if (window.opera) {
+        element.style.top = 0;
+        element.style.left = 0;
+      }
+    }
+    return element;
+  },
+
+  undoPositioned: function(element) {
+    element = $(element);
+    if (element._madePositioned) {
+      element._madePositioned = undefined;
+      element.style.position =
+        element.style.top =
+        element.style.left =
+        element.style.bottom =
+        element.style.right = '';
+    }
+    return element;
+  },
+
+  makeClipping: function(element) {
+    element = $(element);
+    if (element._overflow) return element;
+    element._overflow = element.style.overflow || 'auto';
+    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
+      element.style.overflow = 'hidden';
+    return element;
+  },
+
+  undoClipping: function(element) {
+    element = $(element);
+    if (!element._overflow) return element;
+    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+    element._overflow = null;
+    return element;
+  }
+};
+
+Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf});
+
+Element._attributeTranslations = {};
+
+Element._attributeTranslations.names = {
+  colspan:   "colSpan",
+  rowspan:   "rowSpan",
+  valign:    "vAlign",
+  datetime:  "dateTime",
+  accesskey: "accessKey",
+  tabindex:  "tabIndex",
+  enctype:   "encType",
+  maxlength: "maxLength",
+  readonly:  "readOnly",
+  longdesc:  "longDesc"
+};
+
+Element._attributeTranslations.values = {
+  _getAttr: function(element, attribute) {
+    return element.getAttribute(attribute, 2);
+  },
+
+  _flag: function(element, attribute) {
+    return $(element).hasAttribute(attribute) ? attribute : null;
+  },
+
+  style: function(element) {
+    return element.style.cssText.toLowerCase();
+  },
+
+  title: function(element) {
+    var node = element.getAttributeNode('title');
+    return node.specified ? node.nodeValue : null;
+  }
+};
+
+Object.extend(Element._attributeTranslations.values, {
+  href: Element._attributeTranslations.values._getAttr,
+  src:  Element._attributeTranslations.values._getAttr,
+  disabled: Element._attributeTranslations.values._flag,
+  checked:  Element._attributeTranslations.values._flag,
+  readonly: Element._attributeTranslations.values._flag,
+  multiple: Element._attributeTranslations.values._flag
+});
+
+Element.Methods.Simulated = {
+  hasAttribute: function(element, attribute) {
+    var t = Element._attributeTranslations;
+    attribute = t.names[attribute] || attribute;
+    return $(element).getAttributeNode(attribute).specified;
+  }
+};
+
+// IE is missing .innerHTML support for TABLE-related elements
+if (document.all && !window.opera){
+  Element.Methods.update = function(element, html) {
+    element = $(element);
+    html = typeof html == 'undefined' ? '' : html.toString();
+    var tagName = element.tagName.toUpperCase();
+    if (['THEAD','TBODY','TR','TD'].include(tagName)) {
+      var div = document.createElement('div');
+      switch (tagName) {
+        case 'THEAD':
+        case 'TBODY':
+          div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>';
+          depth = 2;
+          break;
+        case 'TR':
+          div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>';
+          depth = 3;
+          break;
+        case 'TD':
+          div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>';
+          depth = 4;
+      }
+      $A(element.childNodes).each(function(node){
+        element.removeChild(node)
+      });
+      depth.times(function(){ div = div.firstChild });
+
+      $A(div.childNodes).each(
+        function(node){ element.appendChild(node) });
+    } else {
+      element.innerHTML = html.stripScripts();
+    }
+    setTimeout(function() {html.evalScripts()}, 10);
+    return element;
+  }
+};
+
+Object.extend(Element, Element.Methods);
+
+var _nativeExtensions = false;
+
+if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+  ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {
+    var className = 'HTML' + tag + 'Element';
+    if(window[className]) return;
+    var klass = window[className] = {};
+    klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__;
+  });
+
+Element.addMethods = function(methods) {
+  Object.extend(Element.Methods, methods || {});
+
+  function copy(methods, destination, onlyIfAbsent) {
+    onlyIfAbsent = onlyIfAbsent || false;
+    var cache = Element.extend.cache;
+    for (var property in methods) {
+      var value = methods[property];
+      if (!onlyIfAbsent || !(property in destination))
+        destination[property] = cache.findOrStore(value);
+    }
+  }
+
+  if (typeof HTMLElement != 'undefined') {
+    copy(Element.Methods, HTMLElement.prototype);
+    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+    copy(Form.Methods, HTMLFormElement.prototype);
+    [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
+      copy(Form.Element.Methods, klass.prototype);
+    });
+    _nativeExtensions = true;
+  }
+}
+
+var Toggle = new Object();
+Toggle.display = Element.toggle;
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.Insertion = function(adjacency) {
+  this.adjacency = adjacency;
+}
+
+Abstract.Insertion.prototype = {
+  initialize: function(element, content) {
+    this.element = $(element);
+    this.content = content.stripScripts();
+
+    if (this.adjacency && this.element.insertAdjacentHTML) {
+      try {
+        this.element.insertAdjacentHTML(this.adjacency, this.content);
+      } catch (e) {
+        var tagName = this.element.tagName.toUpperCase();
+        if (['TBODY', 'TR'].include(tagName)) {
+          this.insertContent(this.contentFromAnonymousTable());
+        } else {
+          throw e;
+        }
+      }
+    } else {
+      this.range = this.element.ownerDocument.createRange();
+      if (this.initializeRange) this.initializeRange();
+      this.insertContent([this.range.createContextualFragment(this.content)]);
+    }
+
+    setTimeout(function() {content.evalScripts()}, 10);
+  },
+
+  contentFromAnonymousTable: function() {
+    var div = document.createElement('div');
+    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
+    return $A(div.childNodes[0].childNodes[0].childNodes);
+  }
+}
+
+var Insertion = new Object();
+
+Insertion.Before = Class.create();
+Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
+  initializeRange: function() {
+    this.range.setStartBefore(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.parentNode.insertBefore(fragment, this.element);
+    }).bind(this));
+  }
+});
+
+Insertion.Top = Class.create();
+Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(true);
+  },
+
+  insertContent: function(fragments) {
+    fragments.reverse(false).each((function(fragment) {
+      this.element.insertBefore(fragment, this.element.firstChild);
+    }).bind(this));
+  }
+});
+
+Insertion.Bottom = Class.create();
+Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.appendChild(fragment);
+    }).bind(this));
+  }
+});
+
+Insertion.After = Class.create();
+Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
+  initializeRange: function() {
+    this.range.setStartAfter(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.parentNode.insertBefore(fragment,
+        this.element.nextSibling);
+    }).bind(this));
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+  initialize: function(element) {
+    this.element = $(element);
+  },
+
+  _each: function(iterator) {
+    this.element.className.split(/\s+/).select(function(name) {
+      return name.length > 0;
+    })._each(iterator);
+  },
+
+  set: function(className) {
+    this.element.className = className;
+  },
+
+  add: function(classNameToAdd) {
+    if (this.include(classNameToAdd)) return;
+    this.set($A(this).concat(classNameToAdd).join(' '));
+  },
+
+  remove: function(classNameToRemove) {
+    if (!this.include(classNameToRemove)) return;
+    this.set($A(this).without(classNameToRemove).join(' '));
+  },
+
+  toString: function() {
+    return $A(this).join(' ');
+  }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+var Selector = Class.create();
+Selector.prototype = {
+  initialize: function(expression) {
+    this.params = {classNames: []};
+    this.expression = expression.toString().strip();
+    this.parseExpression();
+    this.compileMatcher();
+  },
+
+  parseExpression: function() {
+    function abort(message) { throw 'Parse error in selector: ' + message; }
+
+    if (this.expression == '')  abort('empty expression');
+
+    var params = this.params, expr = this.expression, match, modifier, clause, rest;
+    while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
+      params.attributes = params.attributes || [];
+      params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
+      expr = match[1];
+    }
+
+    if (expr == '*') return this.params.wildcard = true;
+
+    while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
+      modifier = match[1], clause = match[2], rest = match[3];
+      switch (modifier) {
+        case '#':       params.id = clause; break;
+        case '.':       params.classNames.push(clause); break;
+        case '':
+        case undefined: params.tagName = clause.toUpperCase(); break;
+        default:        abort(expr.inspect());
+      }
+      expr = rest;
+    }
+
+    if (expr.length > 0) abort(expr.inspect());
+  },
+
+  buildMatchExpression: function() {
+    var params = this.params, conditions = [], clause;
+
+    if (params.wildcard)
+      conditions.push('true');
+    if (clause = params.id)
+      conditions.push('element.readAttribute("id") == ' + clause.inspect());
+    if (clause = params.tagName)
+      conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
+    if ((clause = params.classNames).length > 0)
+      for (var i = 0, length = clause.length; i < length; i++)
+        conditions.push('element.hasClassName(' + clause[i].inspect() + ')');
+    if (clause = params.attributes) {
+      clause.each(function(attribute) {
+        var value = 'element.readAttribute(' + attribute.name.inspect() + ')';
+        var splitValueBy = function(delimiter) {
+          return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
+        }
+
+        switch (attribute.operator) {
+          case '=':       conditions.push(value + ' == ' + attribute.value.inspect()); break;
+          case '~=':      conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
+          case '|=':      conditions.push(
+                            splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
+                          ); break;
+          case '!=':      conditions.push(value + ' != ' + attribute.value.inspect()); break;
+          case '':
+          case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break;
+          default:        throw 'Unknown operator ' + attribute.operator + ' in selector';
+        }
+      });
+    }
+
+    return conditions.join(' && ');
+  },
+
+  compileMatcher: function() {
+    this.match = new Function('element', 'if (!element.tagName) return false; \
+      element = $(element); \
+      return ' + this.buildMatchExpression());
+  },
+
+  findElements: function(scope) {
+    var element;
+
+    if (element = $(this.params.id))
+      if (this.match(element))
+        if (!scope || Element.childOf(element, scope))
+          return [element];
+
+    scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
+
+    var results = [];
+    for (var i = 0, length = scope.length; i < length; i++)
+      if (this.match(element = scope[i]))
+        results.push(Element.extend(element));
+
+    return results;
+  },
+
+  toString: function() {
+    return this.expression;
+  }
+}
+
+Object.extend(Selector, {
+  matchElements: function(elements, expression) {
+    var selector = new Selector(expression);
+    return elements.select(selector.match.bind(selector)).map(Element.extend);
+  },
+
+  findElement: function(elements, expression, index) {
+    if (typeof expression == 'number') index = expression, expression = false;
+    return Selector.matchElements(elements, expression || '*')[index || 0];
+  },
+
+  findChildElements: function(element, expressions) {
+    return expressions.map(function(expression) {
+      return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) {
+        var selector = new Selector(expr);
+        return results.inject([], function(elements, result) {
+          return elements.concat(selector.findElements(result || element));
+        });
+      });
+    }).flatten();
+  }
+});
+
+function $$() {
+  return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+  reset: function(form) {
+    $(form).reset();
+    return form;
+  },
+
+  serializeElements: function(elements, getHash) {
+    var data = elements.inject({}, function(result, element) {
+      if (!element.disabled && element.name) {
+        var key = element.name, value = $(element).getValue();
+        if (value != undefined) {
+          if (result[key]) {
+            if (result[key].constructor != Array) result[key] = [result[key]];
+            result[key].push(value);
+          }
+          else result[key] = value;
+        }
+      }
+      return result;
+    });
+
+    return getHash ? data : Hash.toQueryString(data);
+  }
+};
+
+Form.Methods = {
+  serialize: function(form, getHash) {
+    return Form.serializeElements(Form.getElements(form), getHash);
+  },
+
+  getElements: function(form) {
+    return $A($(form).getElementsByTagName('*')).inject([],
+      function(elements, child) {
+        if (Form.Element.Serializers[child.tagName.toLowerCase()])
+          elements.push(Element.extend(child));
+        return elements;
+      }
+    );
+  },
+
+  getInputs: function(form, typeName, name) {
+    form = $(form);
+    var inputs = form.getElementsByTagName('input');
+
+    if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+      var input = inputs[i];
+      if ((typeName && input.type != typeName) || (name && input.name != name))
+        continue;
+      matchingInputs.push(Element.extend(input));
+    }
+
+    return matchingInputs;
+  },
+
+  disable: function(form) {
+    form = $(form);
+    form.getElements().each(function(element) {
+      element.blur();
+      element.disabled = 'true';
+    });
+    return form;
+  },
+
+  enable: function(form) {
+    form = $(form);
+    form.getElements().each(function(element) {
+      element.disabled = '';
+    });
+    return form;
+  },
+
+  findFirstElement: function(form) {
+    return $(form).getElements().find(function(element) {
+      return element.type != 'hidden' && !element.disabled &&
+        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+    });
+  },
+
+  focusFirstElement: function(form) {
+    form = $(form);
+    form.findFirstElement().activate();
+    return form;
+  }
+}
+
+Object.extend(Form, Form.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+  focus: function(element) {
+    $(element).focus();
+    return element;
+  },
+
+  select: function(element) {
+    $(element).select();
+    return element;
+  }
+}
+
+Form.Element.Methods = {
+  serialize: function(element) {
+    element = $(element);
+    if (!element.disabled && element.name) {
+      var value = element.getValue();
+      if (value != undefined) {
+        var pair = {};
+        pair[element.name] = value;
+        return Hash.toQueryString(pair);
+      }
+    }
+    return '';
+  },
+
+  getValue: function(element) {
+    element = $(element);
+    var method = element.tagName.toLowerCase();
+    return Form.Element.Serializers[method](element);
+  },
+
+  clear: function(element) {
+    $(element).value = '';
+    return element;
+  },
+
+  present: function(element) {
+    return $(element).value != '';
+  },
+
+  activate: function(element) {
+    element = $(element);
+    element.focus();
+    if (element.select && ( element.tagName.toLowerCase() != 'input' ||
+      !['button', 'reset', 'submit'].include(element.type) ) )
+      element.select();
+    return element;
+  },
+
+  disable: function(element) {
+    element = $(element);
+    element.disabled = true;
+    return element;
+  },
+
+  enable: function(element) {
+    element = $(element);
+    element.blur();
+    element.disabled = false;
+    return element;
+  }
+}
+
+Object.extend(Form.Element, Form.Element.Methods);
+var Field = Form.Element;
+var $F = Form.Element.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+  input: function(element) {
+    switch (element.type.toLowerCase()) {
+      case 'checkbox':
+      case 'radio':
+        return Form.Element.Serializers.inputSelector(element);
+      default:
+        return Form.Element.Serializers.textarea(element);
+    }
+  },
+
+  inputSelector: function(element) {
+    return element.checked ? element.value : null;
+  },
+
+  textarea: function(element) {
+    return element.value;
+  },
+
+  select: function(element) {
+    return this[element.type == 'select-one' ?
+      'selectOne' : 'selectMany'](element);
+  },
+
+  selectOne: function(element) {
+    var index = element.selectedIndex;
+    return index >= 0 ? this.optionValue(element.options[index]) : null;
+  },
+
+  selectMany: function(element) {
+    var values, length = element.length;
+    if (!length) return null;
+
+    for (var i = 0, values = []; i < length; i++) {
+      var opt = element.options[i];
+      if (opt.selected) values.push(this.optionValue(opt));
+    }
+    return values;
+  },
+
+  optionValue: function(opt) {
+    // extend element because hasAttribute may not be native
+    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = function() {}
+Abstract.TimedObserver.prototype = {
+  initialize: function(element, frequency, callback) {
+    this.frequency = frequency;
+    this.element   = $(element);
+    this.callback  = callback;
+
+    this.lastValue = this.getValue();
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    var value = this.getValue();
+    var changed = ('string' == typeof this.lastValue && 'string' == typeof value
+      ? this.lastValue != value : String(this.lastValue) != String(value));
+    if (changed) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  }
+}
+
+Form.Element.Observer = Class.create();
+Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.Observer = Class.create();
+Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = function() {}
+Abstract.EventObserver.prototype = {
+  initialize: function(element, callback) {
+    this.element  = $(element);
+    this.callback = callback;
+
+    this.lastValue = this.getValue();
+    if (this.element.tagName.toLowerCase() == 'form')
+      this.registerFormCallbacks();
+    else
+      this.registerCallback(this.element);
+  },
+
+  onElementEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  },
+
+  registerFormCallbacks: function() {
+    Form.getElements(this.element).each(this.registerCallback.bind(this));
+  },
+
+  registerCallback: function(element) {
+    if (element.type) {
+      switch (element.type.toLowerCase()) {
+        case 'checkbox':
+        case 'radio':
+          Event.observe(element, 'click', this.onElementEvent.bind(this));
+          break;
+        default:
+          Event.observe(element, 'change', this.onElementEvent.bind(this));
+          break;
+      }
+    }
+  }
+}
+
+Form.Element.EventObserver = Class.create();
+Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.EventObserver = Class.create();
+Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+if (!window.Event) {
+  var Event = new Object();
+}
+
+Object.extend(Event, {
+  KEY_BACKSPACE: 8,
+  KEY_TAB:       9,
+  KEY_RETURN:   13,
+  KEY_ESC:      27,
+  KEY_LEFT:     37,
+  KEY_UP:       38,
+  KEY_RIGHT:    39,
+  KEY_DOWN:     40,
+  KEY_DELETE:   46,
+  KEY_HOME:     36,
+  KEY_END:      35,
+  KEY_PAGEUP:   33,
+  KEY_PAGEDOWN: 34,
+
+  element: function(event) {
+    return event.target || event.srcElement;
+  },
+
+  isLeftClick: function(event) {
+    return (((event.which) && (event.which == 1)) ||
+            ((event.button) && (event.button == 1)));
+  },
+
+  pointerX: function(event) {
+    return event.pageX || (event.clientX +
+      (document.documentElement.scrollLeft || document.body.scrollLeft));
+  },
+
+  pointerY: function(event) {
+    return event.pageY || (event.clientY +
+      (document.documentElement.scrollTop || document.body.scrollTop));
+  },
+
+  stop: function(event) {
+    if (event.preventDefault) {
+      event.preventDefault();
+      event.stopPropagation();
+    } else {
+      event.returnValue = false;
+      event.cancelBubble = true;
+    }
+  },
+
+  // find the first node with the given tagName, starting from the
+  // node the event was triggered on; traverses the DOM upwards
+  findElement: function(event, tagName) {
+    var element = Event.element(event);
+    while (element.parentNode && (!element.tagName ||
+        (element.tagName.toUpperCase() != tagName.toUpperCase())))
+      element = element.parentNode;
+    return element;
+  },
+
+  observers: false,
+
+  _observeAndCache: function(element, name, observer, useCapture) {
+    if (!this.observers) this.observers = [];
+    if (element.addEventListener) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.addEventListener(name, observer, useCapture);
+    } else if (element.attachEvent) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.attachEvent('on' + name, observer);
+    }
+  },
+
+  unloadCache: function() {
+    if (!Event.observers) return;
+    for (var i = 0, length = Event.observers.length; i < length; i++) {
+      Event.stopObserving.apply(this, Event.observers[i]);
+      Event.observers[i][0] = null;
+    }
+    Event.observers = false;
+  },
+
+  observe: function(element, name, observer, useCapture) {
+    element = $(element);
+    useCapture = useCapture || false;
+
+    if (name == 'keypress' &&
+        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
+        || element.attachEvent))
+      name = 'keydown';
+
+    Event._observeAndCache(element, name, observer, useCapture);
+  },
+
+  stopObserving: function(element, name, observer, useCapture) {
+    element = $(element);
+    useCapture = useCapture || false;
+
+    if (name == 'keypress' &&
+        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
+        || element.detachEvent))
+      name = 'keydown';
+
+    if (element.removeEventListener) {
+      element.removeEventListener(name, observer, useCapture);
+    } else if (element.detachEvent) {
+      try {
+        element.detachEvent('on' + name, observer);
+      } catch (e) {}
+    }
+  }
+});
+
+/* prevent memory leaks in IE */
+if (navigator.appVersion.match(/\bMSIE\b/))
+  Event.observe(window, 'unload', Event.unloadCache, false);
+var Position = {
+  // set to true if needed, warning: firefox performance problems
+  // NOT neeeded for page scrolling, only if draggable contained in
+  // scrollable elements
+  includeScrollOffsets: false,
+
+  // must be called before calling withinIncludingScrolloffset, every time the
+  // page is scrolled
+  prepare: function() {
+    this.deltaX =  window.pageXOffset
+                || document.documentElement.scrollLeft
+                || document.body.scrollLeft
+                || 0;
+    this.deltaY =  window.pageYOffset
+                || document.documentElement.scrollTop
+                || document.body.scrollTop
+                || 0;
+  },
+
+  realOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.scrollTop  || 0;
+      valueL += element.scrollLeft || 0;
+      element = element.parentNode;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  cumulativeOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  positionedOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+      if (element) {
+        if(element.tagName=='BODY') break;
+        var p = Element.getStyle(element, 'position');
+        if (p == 'relative' || p == 'absolute') break;
+      }
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  offsetParent: function(element) {
+    if (element.offsetParent) return element.offsetParent;
+    if (element == document.body) return element;
+
+    while ((element = element.parentNode) && element != document.body)
+      if (Element.getStyle(element, 'position') != 'static')
+        return element;
+
+    return document.body;
+  },
+
+  // caches x/y coordinate pair to use with overlap
+  within: function(element, x, y) {
+    if (this.includeScrollOffsets)
+      return this.withinIncludingScrolloffsets(element, x, y);
+    this.xcomp = x;
+    this.ycomp = y;
+    this.offset = this.cumulativeOffset(element);
+
+    return (y >= this.offset[1] &&
+            y <  this.offset[1] + element.offsetHeight &&
+            x >= this.offset[0] &&
+            x <  this.offset[0] + element.offsetWidth);
+  },
+
+  withinIncludingScrolloffsets: function(element, x, y) {
+    var offsetcache = this.realOffset(element);
+
+    this.xcomp = x + offsetcache[0] - this.deltaX;
+    this.ycomp = y + offsetcache[1] - this.deltaY;
+    this.offset = this.cumulativeOffset(element);
+
+    return (this.ycomp >= this.offset[1] &&
+            this.ycomp <  this.offset[1] + element.offsetHeight &&
+            this.xcomp >= this.offset[0] &&
+            this.xcomp <  this.offset[0] + element.offsetWidth);
+  },
+
+  // within must be called directly before
+  overlap: function(mode, element) {
+    if (!mode) return 0;
+    if (mode == 'vertical')
+      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+        element.offsetHeight;
+    if (mode == 'horizontal')
+      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+        element.offsetWidth;
+  },
+
+  page: function(forElement) {
+    var valueT = 0, valueL = 0;
+
+    var element = forElement;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+
+      // Safari fix
+      if (element.offsetParent==document.body)
+        if (Element.getStyle(element,'position')=='absolute') break;
+
+    } while (element = element.offsetParent);
+
+    element = forElement;
+    do {
+      if (!window.opera || element.tagName=='BODY') {
+        valueT -= element.scrollTop  || 0;
+        valueL -= element.scrollLeft || 0;
+      }
+    } while (element = element.parentNode);
+
+    return [valueL, valueT];
+  },
+
+  clone: function(source, target) {
+    var options = Object.extend({
+      setLeft:    true,
+      setTop:     true,
+      setWidth:   true,
+      setHeight:  true,
+      offsetTop:  0,
+      offsetLeft: 0
+    }, arguments[2] || {})
+
+    // find page position of source
+    source = $(source);
+    var p = Position.page(source);
+
+    // find coordinate system to use
+    target = $(target);
+    var delta = [0, 0];
+    var parent = null;
+    // delta [0,0] will do fine with position: fixed elements,
+    // position:absolute needs offsetParent deltas
+    if (Element.getStyle(target,'position') == 'absolute') {
+      parent = Position.offsetParent(target);
+      delta = Position.page(parent);
+    }
+
+    // correct by body offsets (fixes Safari)
+    if (parent == document.body) {
+      delta[0] -= document.body.offsetLeft;
+      delta[1] -= document.body.offsetTop;
+    }
+
+    // set position
+    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
+    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
+    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
+    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
+  },
+
+  absolutize: function(element) {
+    element = $(element);
+    if (element.style.position == 'absolute') return;
+    Position.prepare();
+
+    var offsets = Position.positionedOffset(element);
+    var top     = offsets[1];
+    var left    = offsets[0];
+    var width   = element.clientWidth;
+    var height  = element.clientHeight;
+
+    element._originalLeft   = left - parseFloat(element.style.left  || 0);
+    element._originalTop    = top  - parseFloat(element.style.top || 0);
+    element._originalWidth  = element.style.width;
+    element._originalHeight = element.style.height;
+
+    element.style.position = 'absolute';
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.width  = width + 'px';
+    element.style.height = height + 'px';
+  },
+
+  relativize: function(element) {
+    element = $(element);
+    if (element.style.position == 'relative') return;
+    Position.prepare();
+
+    element.style.position = 'relative';
+    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
+    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.height = element._originalHeight;
+    element.style.width  = element._originalWidth;
+  }
+}
+
+// Safari returns margins on body which is incorrect if the child is absolutely
+// positioned.  For performance reasons, redefine Position.cumulativeOffset for
+// KHTML/WebKit only.
+if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
+  Position.cumulativeOffset = function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      if (element.offsetParent == document.body)
+        if (Element.getStyle(element, 'position') == 'absolute') break;
+
+      element = element.offsetParent;
+    } while (element);
+
+    return [valueL, valueT];
+  }
+}
+
+Element.addMethods();
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowViewer.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowViewer.css
new file mode 100644
index 0000000..c3347f8
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowViewer.css
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+#workflow_modeL_tbl{
+	
+}
+
+#workflow_model_tbl tr{
+ vertical-align:top;
+}
+
+#workflow_model_tbl td.task_bubble{
+  width:82;
+  height:82;
+  /*background:url(task_circle.jpg) no-repeat;*/
+  background-color: #CCC;
+  text-align:center;
+  white-space:wrap;
+  vertical-align:middle;
+  border-width: 2px;
+  border-style: dashed;
+}
+
+#workflow_model_tbl td.arrow{
+  width:60;
+  height:16;
+  text-align:center;
+  vertical-align:middle;
+  border-width: 0px;
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowViewer.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowViewer.html
new file mode 100644
index 0000000..79d1098
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowViewer.html
@@ -0,0 +1,48 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:link>
+ <link rel="stylesheet" type="text/css" href="WorkflowViewer.css"/>
+</wicket:link>
+<table>
+  <tr>
+    <td>Workflow ID</td>
+    <td><span wicket:id="workflow_id">urn:oodt:backwardsTestWorkflow</span></td>
+  </tr>
+  <tr>       	    	          
+    <td>Name</td>
+    <td><span wicket:id="workflow_name">backwardsTestWorkflow</span></td>
+  </tr>
+  <tr>
+  	 
+	 <td colspan="2">
+	   <table id="workflow_model_tbl" wicket:id="workflow_model_tbl" width="279" height="100">
+  	      <tr>
+  	       <wicket:container wicket:id="tasks">
+  	    	 <td class="task_bubble"><a wicket:id="task_link" href="#"><span wicket:id="task_name">IntensWaite</span></a></td>
+  	    	 <td class="arrow" wicket:id="task_arrow"><wicket:link><img src="task_arrow.png"></wicket:link></td>
+  	       </wicket:container>
+             <wicket:remove>
+  	    	 <td class="task_bubble"><a href="#">LongTask1</a></td>
+  	    	 </wicket:remove>
+  	      </tr>  	      
+       </table>      	    	          
+   </td>
+    
+  </tr>
+</table>
+</wicket:panel>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowViewer.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowViewer.java
new file mode 100644
index 0000000..f669bd6
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowViewer.java
@@ -0,0 +1,144 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.workflow.model;
+
+import org.apache.oodt.cas.webcomponents.workflow.WorkflowMgrConn;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.behavior.SimpleAttributeModifier;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.util.ListModel;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowViewer extends Panel {
+
+  private static final long serialVersionUID = -157601650785829792L;
+
+  private final WorkflowMgrConn wm;
+
+  public WorkflowViewer(String id, String wmUrlStr, final String workflowId,
+      final Class<? extends WebPage> taskPage) {
+    super(id);
+    this.wm = new WorkflowMgrConn(wmUrlStr);
+    final IModel<Workflow> wModel = new LoadableDetachableModel<Workflow>() {
+
+      @Override
+      protected Workflow load() {
+        return wm.safeGetWorkflowById(workflowId);
+      }
+    };
+
+    add(new Label("workflow_id", new PropertyModel<Workflow>(wModel, "id")));
+    add(new Label("workflow_name", new PropertyModel<Workflow>(wModel, "name")));
+
+    int numTasks = wModel.getObject().getTasks().size();
+    String width = String.valueOf((82 * numTasks) + (115 * (numTasks - 1)));
+    String height = "82";
+    WebMarkupContainer wTable = new WebMarkupContainer("workflow_model_tbl");
+    wTable.add(new SimpleAttributeModifier("width", width));
+    wTable.add(new SimpleAttributeModifier("height", height));
+
+    wTable.add(new ListView<WorkflowTask>("tasks", new ListModel<WorkflowTask>(
+        wModel.getObject().getTasks())) {
+
+      @Override
+      protected void populateItem(ListItem<WorkflowTask> item) {
+        final PageParameters params = new PageParameters();
+        params.add("id", item.getModelObject().getTaskId());
+        Link taskLink = new Link("task_link") {
+          /*
+           * (non-Javadoc)
+           * 
+           * @see org.apache.wicket.markup.html.link.Link#onClick()
+           */
+          @Override
+          public void onClick() {
+            setResponsePage(taskPage, params);
+          }
+        };
+        String taskName = summarizeWords(item.getModelObject().getTaskName(),
+            16, 16);
+        taskLink.add(new Label("task_name", taskName).setRenderBodyOnly(true));
+        item.add(taskLink);
+
+        if (item.getIndex() == wModel.getObject().getTasks().size() - 1) {
+          item.add(new WebMarkupContainer("task_arrow").setVisible(false));
+        } else {
+          item.add(new WebMarkupContainer("task_arrow"));
+        }
+
+      }
+    });
+    add(wTable);
+
+  }
+
+  /**
+   * <p>
+   * Summarizes a given String of words (the <code>orig</code> parameter), and
+   * limits the size of the individual words in the string by the given
+   * <code>wordThreshold</code>, and limits the final size of the final
+   * summarized word string by the given <code>maxLengthTotal</code>.
+   * </p>
+   * 
+   * @param orig
+   *          The original String to summarize.
+   * @param wordThreshhold
+   *          The maximum amount of characters for any given word in the string.
+   * @param maxLengthTotal
+   *          The maximum final size of the summarized set of words.
+   * @return A summarized string.
+   */
+  private String summarizeWords(String orig, int wordThreshhold,
+      int maxLengthTotal) {
+    String[] words = orig.split(" ");
+    StringBuffer summarizedString = new StringBuffer();
+
+    for (int i = 0; i < words.length; i++) {
+      String word = words[i];
+      summarizedString.append(word.substring(0, Math.min(wordThreshhold, word
+          .length())));
+      summarizedString.append(" ");
+    }
+    
+    // add '...' to end of summarized string if applicable
+    if (summarizedString.length() > maxLengthTotal) {
+    	return summarizedString.substring(0,
+    	        Math.min(maxLengthTotal, summarizedString.length()) - 3).toString() + "...";
+    } else
+    	return summarizedString.toString();
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowsViewer.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowsViewer.css
new file mode 100644
index 0000000..53b7317
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowsViewer.css
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+#workflows_tbl{
+
+}
+
+.header{
+
+}
+
+.workflow_data{
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowsViewer.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowsViewer.html
new file mode 100644
index 0000000..1ad0672
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowsViewer.html
@@ -0,0 +1,46 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:link>
+  <link rel="stylesheet" type="text/css" href="WorkflowsViewer.css"/>
+</wicket:link>
+
+<table id="workflows_tbl">
+     <thead>
+	     <tr class="header">
+	       <th>Workflow ID</th>
+	       <th>Name</th>
+	       <th>View</th>
+	     </tr>
+     </thead>
+	<tbody>
+	     <tr wicket:id="workflow_list" class="workflow_data">
+	       <td wicket:id="workflow_id">urn:oodt:TestWorkflow</td>
+	       <td wicket:id="workflow_name">Test Workflow</td>
+	       <td><a wicket:id="workflow_link" href="#">Click here</a></td>
+	      </tr> 
+	   <wicket:remove>
+	     <tr class="workflow_data">
+	       <td>urn:oodt:TestWorkflow</td>
+	       <td>Test Workflow</td>
+	       <td><a href="#">Click here</a></td>
+	      </tr>
+	   </wicket:remove>
+   </tbody> 	     
+</table>
+
+</wicket:panel>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowsViewer.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowsViewer.java
new file mode 100644
index 0000000..f87a08f
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/WorkflowsViewer.java
@@ -0,0 +1,81 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.workflow.model;
+
+import java.util.List;
+
+import org.apache.oodt.cas.webcomponents.workflow.WorkflowMgrConn;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowsViewer extends Panel {
+
+  private static final long serialVersionUID = 808225347615989283L;
+
+  private WorkflowMgrConn wm;
+
+  /**
+   * @param id
+   */
+  public WorkflowsViewer(String id, String workflowUrlStr,
+      final Class<? extends WebPage> wViewerPage) {
+    super(id);
+    this.wm = new WorkflowMgrConn(workflowUrlStr);
+
+    List<Workflow> workflows = this.wm.safeGetWorkflows();
+    add(new ListView<Workflow>("workflow_list", workflows) {
+
+      @Override
+      protected void populateItem(ListItem<Workflow> item) {
+        Workflow w = item.getModelObject();
+        item.add(new Label("workflow_id", w.getId()));
+        item.add(new Label("workflow_name", w.getName()));
+        item.add(new Link<String>("workflow_link", new Model(w.getId())) {
+          /*
+           * (non-Javadoc)
+           * 
+           * @see org.apache.wicket.markup.html.link.Link#onClick()
+           */
+          @Override
+          public void onClick() {
+            PageParameters params = new PageParameters();
+            params.add("id", getModelObject());
+            setResponsePage(wViewerPage, params);
+          }
+        });
+      }
+    });
+
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/task_arrow.jpg b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/task_arrow.jpg
new file mode 100644
index 0000000..e0d0317
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/task_arrow.jpg
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/task_arrow.png b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/task_arrow.png
new file mode 100644
index 0000000..32cb2e8
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/task_arrow.png
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/task_circle.jpg b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/task_circle.jpg
new file mode 100644
index 0000000..8819dcb
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/model/task_circle.jpg
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/pagination/WorkflowPagePaginator.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/pagination/WorkflowPagePaginator.css
new file mode 100644
index 0000000..8b80fd5
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/pagination/WorkflowPagePaginator.css
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+#paginator-break{
+  border:2;
+  width:100%;
+}
+
+#container-div{
+  width:100%;
+}
+
+#paginator-table{
+  border-spacing:3;
+  width:100;
+}
+
+#paginator-table-header{
+  width:100%;
+  white-space:nowrap;
+  font-weight:bold;
+}
+
+
+#page_repeater{
+
+}
+
+a, a:hover, a:focus, a:active{
+	text-decoration: none;
+}
+
+.selected{
+  font-weight:bold;
+  color:red;
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/pagination/WorkflowPagePaginator.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/pagination/WorkflowPagePaginator.html
new file mode 100644
index 0000000..fa14771
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/pagination/WorkflowPagePaginator.html
@@ -0,0 +1,32 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:link>
+  <link rel="stylesheet" type="text/css" href="WorkflowPagePaginator.css"/>
+</wicket:link>
+<hr id="paginator-break">
+<div id="container-div">
+    <table id="paginator-table">
+      <tr>
+        <td id="paginator-table-header">Result Page</td>
+          <td wicket:id="page_repeater" id="page_repeater"><a wicket:id="pageLink" class="selected" href="#"><span wicket:id="pageNum">1</span></a></td>                    	 
+      </tr>
+     </table>
+</div>
+
+<h3 wicket:id="nothing_found">No Products Found!</h3>
+</wicket:panel>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/pagination/WorkflowPagePaginator.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/pagination/WorkflowPagePaginator.java
new file mode 100644
index 0000000..a895dcc
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/pagination/WorkflowPagePaginator.java
@@ -0,0 +1,162 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.workflow.pagination;
+
+//JDK imports
+import java.io.Serializable;
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.behavior.SimpleAttributeModifier;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+
+/**
+ * 
+ * A paginator component that expands to a +/- 5 page
+ * window to paginate a {@link WorkflowInstancePage}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowPagePaginator extends Panel {
+
+  private static final long serialVersionUID = 6277536371513974225L;
+
+  private WorkflowInstancePage page;
+
+  private String status;
+  
+  /**
+   * @param id
+   */
+  public WorkflowPagePaginator(String id, WorkflowInstancePage page,
+      final String status, final Class<? extends WebPage> instPage) {
+    super(id);
+    this.page = page;
+    this.status = status;
+
+    if (this.page != null && this.page.getPageWorkflows() != null
+        && this.page.getPageWorkflows().size() > 0) {
+
+      int numPages = this.page.getTotalPages();
+      int currPage = this.page.getPageNum();
+      int windowSize = 10;
+
+      int startPage = Math.max(1, (currPage - (windowSize / 2)));
+      int endPage = Math.min(currPage + (windowSize / 2), numPages);
+      List<PageNumDisplay> pnums = this.getPageNumDisplay(startPage, endPage,
+          currPage);
+
+      add(new ListView<PageNumDisplay>("page_repeater", pnums) {
+
+        @Override
+        protected void populateItem(ListItem<PageNumDisplay> item) {
+          PageParameters params = new PageParameters();
+          params.add("status", status);
+          params.put("pageNum", item.getModelObject().getNum());
+          BookmarkablePageLink pageLink = new BookmarkablePageLink("pageLink",
+              instPage, params);
+          pageLink.add(new Label("pageNum", String.valueOf(item
+              .getModelObject().getNum())));
+          pageLink.add(new SimpleAttributeModifier("class", item
+              .getModelObject().isCurrentPage() ? "selected" : ""));
+          item.add(pageLink);
+        }
+      });
+      add(new Label("nothing_found").setVisible(false));
+    } else {
+      add(new Label("page_repeater").setVisible(false));
+      add(new Label("pageLink").setVisible(false));
+      add(new Label("pageNum").setVisible(false));
+      add(new Label("nothing_found").setVisible(true));
+    }
+
+  }
+
+  private List<PageNumDisplay> getPageNumDisplay(int startPage, int endPage,
+      int currPage) {
+    List<PageNumDisplay> display = new Vector<PageNumDisplay>();
+    for (int i = startPage; i <= endPage; i++) {
+      display.add(new PageNumDisplay(i == currPage, i));
+    }
+
+    return display;
+  }
+
+  class PageNumDisplay implements Serializable {
+
+    private static final long serialVersionUID = -4351470774764276644L;
+
+    private boolean currentPage;
+
+    private int num;
+
+    public PageNumDisplay() {
+      this.currentPage = false;
+      this.num = -1;
+    }
+
+    public PageNumDisplay(boolean currentPage, int num) {
+      this.currentPage = currentPage;
+      this.num = num;
+    }
+
+    /**
+     * @return the currentPage
+     */
+    public boolean isCurrentPage() {
+      return currentPage;
+    }
+
+    /**
+     * @param currentPage
+     *          the currentPage to set
+     */
+    public void setCurrentPage(boolean currentPage) {
+      this.currentPage = currentPage;
+    }
+
+    /**
+     * @return the num
+     */
+    public int getNum() {
+      return num;
+    }
+
+    /**
+     * @param num
+     *          the num to set
+     */
+    public void setNum(int num) {
+      this.num = num;
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/tasks/WorkflowTaskViewer.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/tasks/WorkflowTaskViewer.css
new file mode 100644
index 0000000..cc56cbe
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/tasks/WorkflowTaskViewer.css
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+#workflow_task_table{
+  font-family: Arial,Sans-Serif,sans-serif;
+  border-spacing:2px;
+}
+
+.header{
+	
+}
+
+.value{
+	
+}
+
+#workflow_task_config_tbl{
+  border-spacing:2px;
+  font-family: Arial,Sans-Serif,sans-serif;
+}
+
+#workflow_config{
+
+}
+
+#workflow_condition_tbl{
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/tasks/WorkflowTaskViewer.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/tasks/WorkflowTaskViewer.html
new file mode 100644
index 0000000..2f19186
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/tasks/WorkflowTaskViewer.html
@@ -0,0 +1,62 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:link>
+ <link rel="stylesheet" type="text/css" href="WorkflowTaskViewer.css"/>
+</wicket:link>
+
+
+<table id="workflow_task_table">
+  <tr>
+    <td class="header">Task ID</td>
+    <td class="value"><span wicket:id="workflow_task_id">urn:oodt:IntensiveTaskWithWait</span></td>
+  </tr>
+  <tr>       	    	          
+    <td class="header">Name</td>
+    <td class="value"><span wicket:id="workflow_task_name">Intensive Waiter</span></td>
+  </tr>
+  <tr>
+    <td class="header">Implementation Class</td>
+    <td class="value"><span wicket:id="workflow_task_class">gov.nasa.jpl.oodt.cas.workflow.examples.LongTask</span></td>
+  </tr>
+  <tr>
+    <td class="header">Configuration</td>
+    <td>
+      <table id="workflow_task_config_tbl">
+       <tr class="header">
+         <td>Property</td>
+         <td>Value</td>
+       </tr>
+       <tr wicket:id="workflow_config" id="workflow_config">
+  	     <td><span wicket:id="workflow_config_pname">numSeconds</span></td>
+  	     <td><span wicket:id="workflow_config_pvalue">60</span></td>
+       </tr>
+      </table>
+     </td>
+    </tr>
+    <tr>
+      <td class="header">Conditions</td>
+      <td>
+        <table id="workflow_condition_tbl">
+       	 <tr wicket:id="workflow_conditions">
+       	   <td><a href="#" wicket:id="condition_page_link"><span wicket:id="condition_plink_name">Long Condition</span></a></td>
+       	 </tr>
+        </table>
+      </td>
+    </tr>
+ </table>
+ </wicket:panel>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/tasks/WorkflowTaskViewer.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/tasks/WorkflowTaskViewer.java
new file mode 100644
index 0000000..7825b00
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/cas/webcomponents/workflow/tasks/WorkflowTaskViewer.java
@@ -0,0 +1,103 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.webcomponents.workflow.tasks;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.oodt.cas.webcomponents.workflow.WorkflowMgrConn;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.util.ListModel;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowTaskViewer extends Panel {
+
+  private static final long serialVersionUID = -1895109076537364697L;
+
+  private WorkflowMgrConn wm;
+
+  /**
+   * @param id
+   */
+  public WorkflowTaskViewer(String id, String wmUrlStr, String taskId, final Class<? extends WebPage> conditionPage) {
+    super(id);
+    this.wm = new WorkflowMgrConn(wmUrlStr);
+    final WorkflowTask task = this.wm.safeGetTaskById(taskId);
+
+    add(new Label("workflow_task_id", task.getTaskId()));
+    add(new Label("workflow_task_name", task.getTaskName()));
+    add(new Label("workflow_task_class", task.getTaskInstanceClassName()));
+
+    List<String> taskConfigMetKeyNames = Arrays.asList(task.getTaskConfig()
+        .getProperties().keySet().toArray(
+            new String[task.getTaskConfig().getProperties().size()]));
+    Collections.sort(taskConfigMetKeyNames);
+
+    add(new ListView<String>("workflow_config", new ListModel<String>(taskConfigMetKeyNames)){
+    
+      @Override
+      protected void populateItem(ListItem<String> item) {
+        String configMetKeyName = item.getModelObject();
+        String configMetKeyValue = task.getTaskConfig().getProperty(configMetKeyName);
+        
+        item.add(new Label("workflow_config_pname", configMetKeyName));
+        item.add(new Label("workflow_config_pvalue", configMetKeyValue));
+      }
+    });
+    
+    add(new ListView<WorkflowCondition>("workflow_conditions", new ListModel<WorkflowCondition>(task.getConditions())){
+      /* (non-Javadoc)
+       * @see org.apache.wicket.markup.html.list.ListView#populateItem(org.apache.wicket.markup.html.list.ListItem)
+       */
+      @Override
+      protected void populateItem(ListItem<WorkflowCondition> item) {
+         WorkflowCondition cond = item.getModelObject();
+         final PageParameters params = new PageParameters();
+         params.add("id", cond.getConditionId());
+         Link condLink = new Link("condition_page_link"){
+               /* (non-Javadoc)
+               * @see org.apache.wicket.markup.html.link.Link#onClick()
+               */
+              @Override
+              public void onClick() {
+                setResponsePage(conditionPage, params);
+              }
+          };
+          condLink.add(new Label("condition_plink_name", cond.getConditionName()));
+          item.add(condLink);
+      }
+    });
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/HealthMonitor.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/HealthMonitor.css
new file mode 100644
index 0000000..6186f6c
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/HealthMonitor.css
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#widenoborder{
+  width:100%;
+  border:0px;
+}
+
+#fm_status{
+
+}
+
+#wm_status{
+
+}
+
+#rm_status{
+
+}
+
+#report_date{
+
+}
+
+.roundtable table{
+border-top: 2px solid #bbb8a9;
+border-bottom: 2px solid #bbb8a9;
+border-left: 2px solid #bbb8a9;
+border-right: 2px solid #bbb8a9;
+}
+
+.nowrap{
+  white-space:nowrap;
+}
+
+.heading{
+  font-size:14px;
+  font-weight:bold;
+}
+
+.avg_crawl_time{
+
+}
+
+.num_crawls{
+
+}
+
+.crawler_name{
+
+}
+
+.file_ingest_datetime{
+
+}
+
+.file_path{
+
+}
+
+.status_name{
+
+}
+
+.batch_stub_url{
+
+}
+
+.crawler_name_and_url{
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/HealthMonitor.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/HealthMonitor.html
new file mode 100644
index 0000000..39bbd0c
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/HealthMonitor.html
@@ -0,0 +1,194 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:remove>
+<link rel="stylesheet" type="text/css" href="HealthMonitor.css"/>
+</wicket:remove>
+
+<table id="widenoborder">
+	<tr>
+		<td><font style="font-size:16px;font-weight:bold;">PCS Status</font></td>
+		<td>
+		<table style="text-align:right:">
+			<tr>
+				<td style="text-align:right:">Current Information as of:</td>
+			</tr>
+			<tr>
+				<td style="text-align:right:" wicket:id="report_date" id="report_date">2011-01-01T00:00:00.000Z</td>
+			</tr>
+		</table>
+		</td>
+	</tr>
+	<tr style="vertical-align:top;">
+		<td>
+		<table>
+			<tr>
+				<td><font class="heading">Server Status:</font></td>
+			</tr>
+			<tr>
+				<td>
+				<div class="roundtable">
+				<table style="width:100px;">
+					<tr>
+						<td class="nowrap" id="fm_status">File Manager&nbsp;(<span wicket:id="fmurl">http://localhost:9000</span>)</td>
+						<td><img wicket:id="fmstatus_icon" src="icon_arrow_up.gif"/></td>
+					</tr>
+					<tr>
+						<td class="nowrap" id="wm_status">Wokflow Manager&nbsp;(<span wicket:id="wmurl">http://localhost:9001</span>)</td>
+						<td><img wicket:id="wmstatus_icon" src="icon_arrow_down.gif"></td>
+					</tr>
+					<tr>
+						<td class="nowrap" id="rm_status">Resource Manager&nbsp;(<span wicket:id="rmurl">http://localhost:9002</span>)</td>
+						<td><img wicket:id="rmstatus_icon" src="icon_arrow_down.gif"></td>
+					</tr>
+				</table>
+				</div>
+				</td>
+			</tr>
+			<tr>
+				<td><font class="heading">Crawler Status:</font></td>
+			</tr>
+			<tr>
+				<td>
+				<div class="roundtable">
+				<table>
+				   <tr wicket:id="crawler_status_list">
+				     <td wicket:id="crawler_name_and_url" class="crawler_name_and_url">Local File Crawler (http://localhost:9091)</td>
+				     <td><img wicket:id="crawler_status_icon" src="icon_arrow_up.gif" /></td>
+				   </tr> 	
+				   <wicket:container wicket:id="crawler_toggler">
+				   <wicket:enclosure child="crawler_status_more">			   
+                    <tr>
+                      <td wicket:id="crawler_status_more" colspan="2">... ...</td>
+					</tr>
+					</wicket:enclosure>
+				    <tr id="crawler_status_options">
+					   <td><a wicket:id="crawler_status_showall" href="#">See All</a></td>
+					   <td><a wicket:id="crawler_status_hide" "href="#">Hide</a></td>
+					   <td><a wicket:id="crawler_status_sort" href="#">Sorting By Status</a></td>
+					   <td><a wicket:id="crawler_status_unsort" href="#">Unsort</a></td>
+					</tr>
+					</wicket:container>
+				</table>
+				</div>
+				</td>
+			</tr>
+			<tr>
+				<td><font class="heading">Batch Stub Status:</font></td>
+			</tr>
+			<tr>
+				<td>
+				<div class="roundtable">
+				<table>
+					<tr wicket:id="batch_stub_list">
+						<td class="nowrap"><span wicket:id="batch_stub_url" class="batch_stub_url">http://compute-0-1:2001</span></td>
+						<td><img wicket:id="batch_stub_status_icon" src="icon_arrow_down.gif" /></td>
+				    </tr>
+				    <wicket:container wicket:id="batch_stub_toggler">
+				    <wicket:enclosure child="batch_stub_more">
+				    <tr>
+						<td wicket:id="batch_stub_more" colspan="2">... ...</td></tr><tr>				     
+				    </tr>
+				    </wicket:enclosure>
+					<tr id="batch_stub_options">
+						<td><a wicket:id="batch_stub_showall" href="#">See All</a></td>
+						<td><a wicket:id="batch_stub_hide" href="#">Hide</a></td>
+						<td><a wicket:id="batch_stub_sort" href="#">Sorting By Status</a></td>
+                        <td><a wicket:id="batch_stub_unsort" href="#">Unsort</a></td>
+					</tr>
+					</wicket:container>
+				</table>
+				</div>
+				</td>
+			</tr>
+		</table>
+		</td>
+		<td>
+		<table>
+			<tr>
+				<td><font class="heading">Job Processing Status:</font></td>
+			</tr>
+			<tr>
+				<td>
+				<div class="roundtable">
+				<table style="width:100px;">
+					<tr wicket:id="jobstatus_list">
+					  <td class="nowrap">
+						<span wicket:id="status_name" class="status_name">QUEUED</span> pipelines
+				      </td>
+					  <td style="text-align:right">	
+						<a href="#" wicket:id="jobstatus_count_link"><span id="status_num_jobs" wicket:id="status_num_jobs">250</span></a>
+					  </td>	
+					</tr>
+						<wicket:remove>
+						 <tr><td class="nowrap"><span class="status_name">STARTED</span> pipelines</td><td style="text-align:right"><a href="#">3</a></td></tr>
+						 <tr><td class="nowrap"><span class="status_name">RSUBMIT</span> pipelines</td><td style="text-align:right"><a href="#">45</a></td></tr>
+						 <tr><td class="nowrap"><span class="status_name">PGE_EXEC</span> pipelines</td><td style="text-align:right"><a href="#">1000</a></td></tr>
+						 <tr><td class="nowrap"><span class="status_name">CRAWLING</span> pipelines</td><td style="text-align:right"><a href="#">4</a></td></tr>
+						 <tr><td class="nowrap"><span class="status_name">FINISHED</span> pipelines</td><td style="text-align:right"><a href="#">10000</a></td></tr>
+						</wicket:remove>						
+				</table>
+				</div>
+				</td>
+			</tr>
+			<tr>
+				<td><font class="heading">Latest Files Ingested:</font></td>
+			</tr>
+			<tr>
+				<td>
+				<div class="roundtable">
+				<table>
+                     <tr wicket:id="file_health_list">
+                       <td>
+						<a href="#" wicket:id="view_product_link"><span wicket:id="file_path" class="file_path">/data/archive/products/file1.txt</span></a> at <span wicket:id="file_ingest_datetime" class="file_ingest_datetime">2011-01-01T00:01:01.001Z</span>
+					   </td>
+					 </tr>
+				</table>
+				</div>
+				</td>
+			</tr>
+			<tr>
+				<td><font class="heading">Crawler Statistics:</font></td>
+			</tr>
+			<tr>
+				<td>
+				<div class="roundtable">
+				<table>
+					 <tr wicket:id="crawler_health_list">
+						<td class="nowrap" colspan="2"><span wicket:id="crawler_name" class="crawler_name">Local File Crawler</span> Number of Crawls: <span wicket:id="num_crawls" class="num_crawls">32</span> Avg Time: <span wicket:id="avg_crawl_time" class="avg_crawl_time">5</span> sec
+						</td>
+					   </tr>
+					<wicket:container wicket:id="crawler_health_toggler">
+					<wicket:enclosure child="crawler_health_more">
+				    <tr>
+						<td colspan="2" wicket:id="crawler_health_more">... ...</td>
+				    </tr>
+				    </wicket:enclosure>
+				    <tr>
+						<td><a wicket:id="crawler_health_showall" href="#">See All</a></td>
+						<td><a wicket:id="crawler_health_hide" href="#">Hide</a></td>
+					</tr>
+					</wicket:container>
+				</table>
+				</div>
+				</td>
+			</tr>
+		</table>
+		</td>
+	</tr>
+</table>
+</wicket:panel>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/HealthMonitor.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/HealthMonitor.java
new file mode 100644
index 0000000..8de54e3
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/HealthMonitor.java
@@ -0,0 +1,232 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.webcomponents.health;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.metadata.CoreMetKeys;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.pcs.health.CrawlerHealth;
+import org.apache.oodt.pcs.health.CrawlerStatus;
+import org.apache.oodt.pcs.health.JobHealthStatus;
+import org.apache.oodt.pcs.health.PCSDaemonStatus;
+import org.apache.oodt.pcs.health.PCSHealthMonitorReport;
+import org.apache.oodt.pcs.tools.PCSHealthMonitor;
+import org.apache.oodt.pcs.util.FileManagerUtils;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.ResourceReference;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.image.Image;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.util.ListModel;
+
+/**
+ * 
+ * A wicket controller for exposing the super awesome power of the
+ * {@link PCSHealthMonitor}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class HealthMonitor extends Panel {
+
+  /**
+   * @param parameters
+   * @throws InstantiationException
+   */
+  public HealthMonitor(String id, String fmUrlStr, String wmUrlStr,
+      String rmUrlStr, String crawlerConfFilePath, String statesFilePath,
+      final Class<? extends WebPage> productBrowser,
+      final Class<? extends WebPage> instancesPage)
+      throws InstantiationException {
+    super(id);
+    PCSHealthMonitor mon = new PCSHealthMonitor(fmUrlStr, wmUrlStr, rmUrlStr,
+        crawlerConfFilePath, statesFilePath);
+    final PCSHealthMonitorReport report = mon.getReport();
+
+    add(new Label("report_date", report.getCreateDateIsoFormat()));
+    add(new Label("fmurl", report.getFmStatus().getUrlStr()));
+    add(new Label("wmurl", report.getWmStatus().getUrlStr()));
+    add(new Label("rmurl", report.getRmStatus().getUrlStr()));
+
+    add(new Image("fmstatus_icon", getUpOrDownArrowRef(report.getFmStatus()
+        .getStatus())));
+    add(new Image("wmstatus_icon", getUpOrDownArrowRef(report.getWmStatus()
+        .getStatus())));
+    add(new Image("rmstatus_icon", getUpOrDownArrowRef(report.getRmStatus()
+        .getStatus())));
+
+    ListModel crawlerStatusListModel = new ListModel(report.getCrawlerStatus());
+    add(new VisibilityAndSortToggler("crawler_toggler",
+        "crawler_status_showall", "crawler_status_hide", "crawler_status_sort",
+        "crawler_status_unsort", "crawler_status_more", crawlerStatusListModel));
+
+    add(new ListView<CrawlerStatus>("crawler_status_list",
+        crawlerStatusListModel) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see
+       * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+       * .wicket.markup.html.list.ListItem)
+       */
+      @Override
+      protected void populateItem(ListItem<CrawlerStatus> statusItem) {
+        CrawlerStatus status = statusItem.getModelObject();
+        String statusString = status.getInfo().getCrawlerName() + " ("
+            + status.getCrawlHost() + ":" + status.getInfo().getCrawlerPort()
+            + ")";
+        statusItem.add(new Label("crawler_name_and_url", statusString));
+        statusItem.add(new Image("crawler_status_icon",
+            getUpOrDownArrowRef(status.getStatus())));
+      }
+    });
+
+    ListModel batchStubStatusListModel = new ListModel(
+        report.getBatchStubStatus());
+    add(new VisibilityAndSortToggler("batch_stub_toggler",
+        "batch_stub_showall", "batch_stub_hide", "batch_stub_sort",
+        "batch_stub_unsort", "batch_stub_more", batchStubStatusListModel));
+
+    add(new ListView<PCSDaemonStatus>("batch_stub_list",
+        batchStubStatusListModel) {
+
+      @Override
+      protected void populateItem(ListItem<PCSDaemonStatus> item) {
+        item.add(new Label("batch_stub_url", item.getModelObject().getUrlStr()));
+        item.add(new Image("batch_stub_status_icon", getUpOrDownArrowRef(item
+            .getModelObject().getStatus())));
+
+      }
+    });
+
+    List<JobHealthStatus> jobHealthStatusList = report.getJobHealthStatus();
+    add(new ListView<JobHealthStatus>("jobstatus_list", jobHealthStatusList) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see
+       * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+       * .wicket.markup.html.list.ListItem)
+       */
+      @Override
+      protected void populateItem(final ListItem<JobHealthStatus> item) {
+        item.add(new Label("status_name", item.getModelObject().getStatus()));
+        Link<String> countLink = new Link<String>("jobstatus_count_link",
+            new Model<String>(item.getModelObject().getStatus())) {
+
+          @Override
+          public void onClick() {
+            PageParameters params = new PageParameters();
+            params.add("pageNum", "1");
+            params.add("status", getModelObject());
+            setResponsePage(instancesPage, params);
+          }
+        };
+        countLink.add(new Label("status_num_jobs", String.valueOf(item
+            .getModelObject().getNumPipelines())));
+        item.add(countLink);
+      }
+    });
+
+    List<Product> prodList = report.getLatestProductsIngested();
+    final FileManagerUtils fm = new FileManagerUtils(fmUrlStr);
+
+    add(new ListView<Product>("file_health_list", prodList) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see
+       * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+       * .wicket.markup.html.list.ListItem)
+       */
+      @Override
+      protected void populateItem(ListItem<Product> item) {
+        final Product product = item.getModelObject();
+        product.setProductType(fm.safeGetProductTypeById(product
+            .getProductType().getProductTypeId()));
+        product.setProductReferences(fm.safeGetProductReferences(product));
+        final Metadata prodMet = fm.safeGetMetadata(product);
+        final String filePath = fm.getFilePath(product);
+
+        Link link = new Link("view_product_link") {
+          /*
+           * (non-Javadoc)
+           * 
+           * @see org.apache.wicket.markup.html.link.Link#onClick()
+           */
+          @Override
+          public void onClick() {
+            PageParameters params = new PageParameters();
+            params.add("id", product.getProductId());
+            setResponsePage(productBrowser, params);
+          }
+        };
+
+        link.add(new Label("file_path", filePath));
+        item.add(link);
+        item.add(new Label("file_ingest_datetime", prodMet.getMetadata("CAS."
+            + CoreMetKeys.PRODUCT_RECEVIED_TIME)));
+
+      }
+    });
+
+    ListModel crawlerHealthListModel = new ListModel(
+        report.getCrawlerHealthStatus());
+    add(new VisibilityToggler("crawler_health_toggler",
+        "crawler_health_showall", "crawler_health_hide", "crawler_health_more",
+        crawlerHealthListModel));
+
+    add(new ListView<CrawlerHealth>("crawler_health_list",
+        crawlerHealthListModel) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see
+       * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+       * .wicket.markup.html.list.ListItem)
+       */
+      @Override
+      protected void populateItem(ListItem<CrawlerHealth> item) {
+        CrawlerHealth health = item.getModelObject();
+        item.add(new Label("crawler_name", health.getCrawlerName()));
+        item.add(new Label("num_crawls", String.valueOf(health.getNumCrawls())));
+        item.add(new Label("avg_crawl_time", String.valueOf(health
+            .getAvgCrawlTime())));
+      }
+    });
+
+  }
+
+  private ResourceReference getUpOrDownArrowRef(String status) {
+    return new ResourceReference(HealthMonitor.class, "icon_arrow_"
+        + status.toLowerCase() + ".gif");
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/VisibilityAndSortToggler.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/VisibilityAndSortToggler.java
new file mode 100644
index 0000000..14e8910
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/VisibilityAndSortToggler.java
@@ -0,0 +1,143 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.webcomponents.health;
+
+//JDK imports
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.pcs.health.CrawlerStatus;
+import org.apache.oodt.pcs.health.PCSDaemonStatus;
+
+//Wicket imports
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.util.ListModel;
+
+/**
+ * 
+ * Toggles both a show/hide link and a sort/unsort link for displaying
+ * PCSDaemonStatus and CrawlerStatus in the PCS OPSUI gui.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+class VisibilityAndSortToggler extends VisibilityToggler {
+
+  private static final long serialVersionUID = 9003502303473741937L;
+
+  /**
+   * @param id
+   */
+  public VisibilityAndSortToggler(String id, String showLinkId,
+      String hideLinkId, String sortLinkId, String unsortLinkId, String moreId,
+      final ListModel model) {
+    super(id, showLinkId, hideLinkId, moreId, model);
+
+    Link<Link> sortLink = null;
+    Link<Link> unsortLink = null;
+
+    sortLink = new Link<Link>(sortLinkId, new Model<Link>(unsortLink)) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        Vector obj = (Vector) model.getObject();
+        sortByStatus(obj);
+        model.setObject(obj);
+        getModelObject().setVisible(true);
+        setVisible(false);
+      }
+    };
+
+    unsortLink = new Link<Link>(unsortLinkId, new Model<Link>(sortLink)) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        Vector obj = (Vector) model.getObject();
+        sortByName(obj);
+        model.setObject(obj);
+        getModelObject().setVisible(true);
+        setVisible(false);
+      }
+    };
+
+    unsortLink.setVisible(false);
+    sortLink.setModelObject(unsortLink);
+    unsortLink.setModelObject(sortLink);
+
+    add(sortLink);
+    add(unsortLink);
+
+  }
+
+  private static void sortByStatus(List statusList) {
+    Collections.sort(statusList, new Comparator() {
+
+      public int compare(Object o1, Object o2) {
+        if (o1 instanceof CrawlerStatus) {
+          CrawlerStatus stat1 = (CrawlerStatus) o1;
+          CrawlerStatus stat2 = (CrawlerStatus) o2;
+
+          return stat1.getStatus().compareTo(stat2.getStatus());
+        } else if (o1 instanceof PCSDaemonStatus) {
+          PCSDaemonStatus stat1 = (PCSDaemonStatus) o1;
+          PCSDaemonStatus stat2 = (PCSDaemonStatus) o2;
+
+          return stat1.getStatus().compareTo(stat2.getStatus());
+        } else
+          return 0;
+      }
+
+    });
+  }
+
+  private static void sortByName(List statusList) {
+    Collections.sort(statusList, new Comparator() {
+
+      public int compare(Object o1, Object o2) {
+        if (o1 instanceof CrawlerStatus) {
+          CrawlerStatus stat1 = (CrawlerStatus) o1;
+          CrawlerStatus stat2 = (CrawlerStatus) o2;
+
+          return stat1.getInfo().getCrawlerName()
+              .compareTo(stat2.getInfo().getCrawlerName());
+        } else if (o1 instanceof PCSDaemonStatus) {
+          PCSDaemonStatus stat1 = (PCSDaemonStatus) o1;
+          PCSDaemonStatus stat2 = (PCSDaemonStatus) o2;
+
+          return stat1.getDaemonName().compareTo(stat2.getDaemonName());
+        } else
+          return 0;
+      }
+
+    });
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/VisibilityToggler.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/VisibilityToggler.java
new file mode 100644
index 0000000..406c9b5
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/VisibilityToggler.java
@@ -0,0 +1,122 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.webcomponents.health;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+//Wicket imports
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.util.ListModel;
+
+/**
+ * 
+ * Toggles a show/hide link for displaying PCSDaemonStatus and CrawlerStatus in
+ * the PCS OPSUI gui.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class VisibilityToggler extends WebMarkupContainer {
+
+  private static final long serialVersionUID = -6325486547078308461L;
+
+  /**
+   * @param id
+   */
+  public VisibilityToggler(String id, String showLinkId, String hideLinkId,
+      String moreId, final ListModel model) {
+    super(id, model);
+
+    Link<Link> showLink = null;
+    Link<Link> hideLink = null;
+    final Vector allStatusList = (Vector) ((Vector) model.getObject()).clone();
+
+    // subset the model
+    model.setObject(subsetModelObject(model.getObject()));
+    final WebMarkupContainer moreComponent = new WebMarkupContainer(moreId);
+    add(moreComponent);
+
+    showLink = new Link<Link>(showLinkId, new Model<Link>(hideLink)) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        Vector obj = (Vector) model.getObject();
+        obj.clear();
+        obj.addAll(allStatusList);
+        model.setObject(obj);
+        moreComponent.setVisible(false);
+        getModelObject().setVisible(true);
+        setVisible(false);
+      }
+    };
+
+    hideLink = new Link<Link>(hideLinkId, new Model<Link>(showLink)) {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        Vector obj = (Vector) model.getObject();
+        obj.clear();
+        obj.addAll(getTopN(allStatusList, 3));
+        model.setObject(obj);
+        getModelObject().setVisible(true);
+        setVisible(false);
+        moreComponent.setVisible(true);
+      }
+    };
+
+    hideLink.setVisible(false);
+    showLink.setModelObject(hideLink);
+    hideLink.setModelObject(showLink);
+
+    add(showLink);
+    add(hideLink);
+  }
+
+  private static List subsetModelObject(Object obj) {
+    List objList = (List) obj;
+    List subsetList = getTopN(objList, 3);
+    return subsetList;
+  }
+
+  private static List getTopN(List statuses, int topN) {
+    List subset = new Vector();
+    if (statuses != null && statuses.size() > 0) {
+      int numGobble = topN <= statuses.size() ? topN : statuses.size();
+      for (int i = 0; i < numGobble; i++) {
+        Object status = statuses.get(i);
+        subset.add(status);
+      }
+    }
+
+    return subset;
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/icon_arrow_down.gif b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/icon_arrow_down.gif
new file mode 100755
index 0000000..68debd5
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/icon_arrow_down.gif
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/icon_arrow_up.gif b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/icon_arrow_up.gif
new file mode 100755
index 0000000..7b311fc
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/health/icon_arrow_up.gif
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/Trace.css b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/Trace.css
new file mode 100755
index 0000000..b09e124
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/Trace.css
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+.trigger {
+	cursor: pointer;
+	cursor: hand;
+}
+
+.branch {
+	display: none;
+	margin-left: 16px;
+}
+
+#upstream_pedigree_heading{
+}
+
+#upstream_pedigree_tree{
+}
+
+#downstream_pedigree_heading{
+}
+
+#downstream_pedigree_tree{
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/Trace.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/Trace.html
new file mode 100644
index 0000000..b4eddea
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/Trace.html
@@ -0,0 +1,82 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+<wicket:link>
+  <script type="text/javascript" src="Trace.js" language="Javascript"></script>
+  <link rel="stylesheet" type="text/css" href="Trace.css"/>
+</wicket:link>
+
+<wicket:remove>
+  <script type="text/javascript" language="Javascript">
+  <!--
+  var openImg = new Image();
+  openImg.src = "open.gif";
+  var closedImg = new Image();
+  closedImg.src = "closed.gif";
+
+  function showBranch(branch) {
+  	var objBranch = document.getElementById(branch).style;
+  	if (objBranch.display == "block")
+  		objBranch.display = "none";
+  	else
+  		objBranch.display = "block";
+  }
+
+  function swapFolder(img) {
+  	objImg = document.getElementById(img);
+  	if (objImg.src.indexOf('closed.gif') > -1)
+  		objImg.src = openImg.src;
+  	else
+  		objImg.src = closedImg.src;
+  }  
+  //-->  
+  </script>
+</wicket:remove>
+
+
+<h3 id="upstream_pedigree_heading">Upstream Pedigree</h3>
+<span id="upstream_pedigree_tree" wicket:id="upstream_pedigree_tree">
+</span>
+
+<h3 id="downstream_pedigree_heading">Downstream Pedigree</h3>
+<span wicket:id="downstream_pedigree_tree" id="downstream_pedigree_tree">
+</span>
+</wicket:panel>
+
+<wicket:remove>
+<div class="trigger"
+	onClick="javascript:showBranch('branch1.1');swapFolder('folder1.1');">
+		<img src="closed.gif" border="0" id="folder1.1" />
+	testfile.txt
+</div>
+<span class="branch" id="branch1.1">
+	<div class="trigger"
+		onClick="javascript:showBranch('branch2.1');swapFolder('folder2.1');">
+			<img src="closed.gif" border="0" id="folder2.1" />
+		testfile2.txt
+    </div>
+	<span class="branch" id="branch2.1">
+			<img src="doc.gif" />
+		testfile3.txt<br />
+
+				<img src="doc.gif" />
+			testfile4.txt<br />
+   </span>   
+</span>
+
+</wicket:remove>
+
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/Trace.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/Trace.java
new file mode 100644
index 0000000..176d267
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/Trace.java
@@ -0,0 +1,61 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.webcomponents.trace;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.pcs.pedigree.Pedigree;
+import org.apache.oodt.pcs.pedigree.PedigreeTree;
+import org.apache.oodt.pcs.util.FileManagerUtils;
+
+//Wicket imports
+import org.apache.wicket.markup.html.panel.Panel;
+
+/**
+ * 
+ * A Trace web widget to expose the underlying PCS {@link Pedigree}
+ * functionality.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class Trace extends Panel {
+
+  private static final long serialVersionUID = 5965790268202443144L;
+
+  /**
+   * @param id
+   * @param model
+   */
+  public Trace(String id, String fmUrlStr, boolean listNotCat,
+      List<String> excludeList, Product product) {
+    super(id);
+    Pedigree pedigree = new Pedigree(new FileManagerUtils(fmUrlStr),
+        listNotCat, excludeList);
+    PedigreeTree upstream = pedigree.doPedigree(product, true);
+    PedigreeTree downstream = pedigree.doPedigree(product, false);
+
+    add(new TraceNode("upstream_pedigree_tree", "up", upstream.getRoot(), 0, 0));
+    add(new TraceNode("downstream_pedigree_tree", "down", downstream.getRoot(), 0, 0));
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/Trace.js b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/Trace.js
new file mode 100755
index 0000000..230da6e
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/Trace.js
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+var openImg = new Image();
+openImg.src = "./images/open.gif";
+var closedImg = new Image();
+closedImg.src = "./images/closed.gif";
+
+function showBranch(branch) {
+	var objBranch = document.getElementById(branch).style;
+	if (objBranch.display == "block")
+		objBranch.display = "none";
+	else
+		objBranch.display = "block";
+}
+
+function swapFolder(img) {
+	objImg = document.getElementById(img);
+	if (objImg.src.indexOf('closed') > -1)
+		objImg.src = openImg.src;
+	else
+		objImg.src = closedImg.src;
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/TraceNode.html b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/TraceNode.html
new file mode 100644
index 0000000..c4aa14c
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/TraceNode.html
@@ -0,0 +1,42 @@
+<!--
+ 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.
+-->
+<wicket:panel>
+ 
+<wicket:container wicket:id="has_children">
+ <div class="trigger"
+	wicket:id="parent_trigger" onclick="javascript:showBranch('branch1.1');swapFolder('folder1.1');">
+	<wicket:link>
+		<img src="closed.gif" border="0" wicket:id="parent_folder" id="folder1.1" />
+	</wicket:link>
+	<span wicket:id="parent_product_name">testfile.txt</span>
+</div>
+
+<span wicket:id="children_container">
+<span wicket:id="children">
+  <span wicket:id="child"/>
+</span>
+</span>
+</wicket:container>
+
+<wicket:container wicket:id="no_children">
+<wicket:link>
+	<img src="doc.gif" />
+</wicket:link>
+<span wicket:id="product_name">testfile3.txt</span> <br />
+</wicket:container>
+
+</wicket:panel>
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/TraceNode.java b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/TraceNode.java
new file mode 100644
index 0000000..e9cf6e6
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/TraceNode.java
@@ -0,0 +1,136 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.pcs.webcomponents.trace;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.pcs.pedigree.PedigreeTreeNode;
+
+//Wicket imports
+import org.apache.wicket.behavior.SimpleAttributeModifier;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.image.Image;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+
+/**
+ * 
+ * A node wrapper around a {@link PedigreeTreeNode} that exposes the node in a
+ * recursive way via Wicket and as a component of a {@link Trace} panel.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TraceNode extends Panel {
+
+  private static final long serialVersionUID = -6672032112136408625L;
+
+  /**
+   * @param id
+   */
+  public TraceNode(String id, String folderKey, PedigreeTreeNode parentNode, int branch, int level) {
+    super(id);
+    nodeAdd(this, folderKey, parentNode, branch, level);
+  }
+
+  public List<PedigreeTreeNode> getChildren(PedigreeTreeNode node) {
+    List<PedigreeTreeNode> children = new Vector<PedigreeTreeNode>(
+        node.getNumChildren());
+
+    for (int i = 0; i < node.getNumChildren(); i++) {
+      children.add(node.getChildAt(i));
+    }
+
+    return children;
+  }
+
+  public void nodeAdd(WebMarkupContainer container, final String folderKey, 
+      final PedigreeTreeNode node, final int branch, final int level) {
+
+    if (node.getNumChildren() > 0) {
+      final String folderId = folderKey+"_folder" + (level + 1) + "." + (branch + 1);
+      final String branchId = folderKey+"_branch" + (level + 1) + "." + (branch + 1);
+
+
+      // deactivate no_children
+      WebMarkupContainer noChildren = new WebMarkupContainer("no_children");
+      noChildren.setVisible(false);
+      container.add(noChildren);
+
+      // activate has_children
+      WebMarkupContainer hasChildren = new WebMarkupContainer("has_children");
+      WebMarkupContainer parentTrigger = new WebMarkupContainer(
+          "parent_trigger");
+      parentTrigger.add(new SimpleAttributeModifier("onclick",
+          "javascript:showBranch('" + branchId + "');swapFolder('" + folderId
+              + "');"));
+
+      Image folderImage = new Image("parent_folder");
+      folderImage.add(new SimpleAttributeModifier("id", folderId));
+      parentTrigger.add(folderImage);
+      parentTrigger.add(new Label("parent_product_name", node.getNodeProduct()
+          .getProductName()));
+      hasChildren.add(parentTrigger);
+
+      WebMarkupContainer childrenContainer = new WebMarkupContainer("children_container");
+      childrenContainer.add(new SimpleAttributeModifier("id", branchId));
+      childrenContainer.add(new SimpleAttributeModifier("class", "branch"));
+      
+      ListView<PedigreeTreeNode> children = new ListView<PedigreeTreeNode>(
+          "children", getChildren(node)) {
+        /*
+         * (non-Javadoc)
+         * 
+         * @see
+         * org.apache.wicket.markup.html.list.ListView#populateItem(org.apache
+         * .wicket.markup.html.list.ListItem)
+         */
+        @Override
+        protected void populateItem(ListItem<PedigreeTreeNode> item) {
+          TraceNode childContainer = new TraceNode("child", folderKey, 
+              item.getModelObject(), item.getIndex(), level + 1);
+          item.add(childContainer);
+        }
+      };
+
+      childrenContainer.add(children);
+      
+      hasChildren.add(childrenContainer);
+      container.add(hasChildren);
+
+    } else {
+      // active no_children
+      WebMarkupContainer noChildren = new WebMarkupContainer("no_children");
+      noChildren.add(new Label("product_name", node.getNodeProduct()
+          .getProductName()));
+      container.add(noChildren);
+
+      // de-activate has_children
+      WebMarkupContainer hasChildren = new WebMarkupContainer("has_children");
+      hasChildren.setVisible(false);
+      container.add(hasChildren);
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/closed.gif b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/closed.gif
new file mode 100755
index 0000000..7d451c3
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/closed.gif
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/doc.gif b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/doc.gif
new file mode 100755
index 0000000..4aca545
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/doc.gif
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/open.gif b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/open.gif
new file mode 100755
index 0000000..0ab3c81
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/java/org/apache/oodt/pcs/webcomponents/trace/open.gif
Binary files differ
diff --git a/0.8.1-rc1/webapp/components/src/main/resources/log4j.properties b/0.8.1-rc1/webapp/components/src/main/resources/log4j.properties
new file mode 100644
index 0000000..f0d325d
--- /dev/null
+++ b/0.8.1-rc1/webapp/components/src/main/resources/log4j.properties
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.   
+
+log4j.appender.Stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.Stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.Stdout.layout.conversionPattern=%-5p - %-26.26c{1} - %m\n
+
+log4j.rootLogger=INFO,Stdout
+
+log4j.logger.org.apache.wicket=INFO
+log4j.logger.org.apache.wicket.protocol.http.HttpSessionStore=INFO
+log4j.logger.org.apache.wicket.version=INFO
+log4j.logger.org.apache.wicket.RequestCycle=INFO
+
+
diff --git a/0.8.1-rc1/webapp/fmbrowser/pom.xml b/0.8.1-rc1/webapp/fmbrowser/pom.xml
new file mode 100644
index 0000000..eff3835
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/pom.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+	<parent>
+                <groupId>org.apache.oodt</groupId>
+                <artifactId>oodt-core</artifactId>
+                <version>0.8.1</version>
+                <relativePath>../../core/pom.xml</relativePath>
+        </parent>
+        <groupId>org.apache.oodt</groupId>
+	<artifactId>fmbrowser</artifactId>
+	<packaging>war</packaging>
+	<version>0.8.1</version>
+	<name>CAS File Manager Browser Web App</name>
+	<properties>
+		<wicket.version>1.4.17</wicket.version>
+		<jetty.version>6.1.25</jetty.version>
+		<slf4j.version>1.5.8</slf4j.version>
+		<log4j.version>1.2.14</log4j.version>
+	</properties>
+	<scm>
+   	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/webapp/fmbrowser</connection>
+   	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/webapp/fmbrowser</developerConnection>
+   	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/webapp/fmbrowser</url>
+  </scm>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.wicket</groupId>
+			<artifactId>wicket</artifactId>
+			<version>${wicket.version}</version>
+		</dependency>
+		<dependency>
+		  <groupId>org.apache.oodt</groupId>
+		  <artifactId>oodt-webapp-components</artifactId>
+		  <version>0.8.1</version>
+		</dependency>
+
+		<!-- LOGGING DEPENDENCIES - LOG4J -->
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-log4j12</artifactId>
+			<version>${slf4j.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>1.2.14</version>
+		</dependency>
+
+		<!--  JUNIT DEPENDENCY FOR TESTING -->
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.8.1</version>
+			<scope>test</scope>
+		</dependency>
+
+		<!--  JETTY DEPENDENCIES FOR TESTING  -->
+		<dependency>
+			<groupId>org.mortbay.jetty</groupId>
+			<artifactId>jetty</artifactId>
+			<version>${jetty.version}</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.mortbay.jetty</groupId>
+			<artifactId>jetty-util</artifactId>
+			<version>${jetty.version}</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.mortbay.jetty</groupId>
+			<artifactId>jetty-management</artifactId>
+			<version>${jetty.version}</version>
+			<scope>provided</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<resources>
+			<resource>
+				<filtering>false</filtering>
+				<directory>src/main/resources</directory>
+			</resource>
+			<resource>
+				<filtering>false</filtering>
+				<directory>src/main/java</directory>
+				<includes>
+					<include>**</include>
+				</includes>
+				<excludes>
+					<exclude>**/*.java</exclude>
+				</excludes>
+			</resource>
+		</resources>
+		<testResources>
+			<testResource>
+				<filtering>false</filtering>
+				<directory>src/test/java</directory>
+				<includes>
+					<include>**</include>
+				</includes>
+				<excludes>
+					<exclude>**/*.java</exclude>
+				</excludes>
+			</testResource>
+		</testResources>
+		<plugins>
+			<plugin>
+				<inherited>true</inherited>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.5</source>
+					<target>1.5</target>
+					<optimize>true</optimize>
+					<debug>true</debug>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+	</project>
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/FMBrowserApp.java b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/FMBrowserApp.java
new file mode 100644
index 0000000..90a98bd
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/FMBrowserApp.java
@@ -0,0 +1,68 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.webapp.browser;
+
+//JDK imports
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.filemgr.FMBrowserAppBase;
+
+//Wicket imports
+import org.apache.wicket.request.target.coding.MixedParamUrlCodingStrategy;
+
+/**
+ * Application object for your web application. If you want to run this
+ * application without deploying, run the Start class.
+ * 
+ * @see org.apache.oodt.cas.filemgr.webapp.browser.Start#main(String[])
+ */
+public class FMBrowserApp extends FMBrowserAppBase {
+
+  private static final Logger LOG = Logger.getLogger(FMBrowserApp.class
+      .getName());
+
+  /**
+   * 
+   * @param fmUrlStr
+   *          The String URL of the file manager to connect to.
+   */
+  public FMBrowserApp() {
+    MixedParamUrlCodingStrategy types = new MixedParamUrlCodingStrategy(
+        "types", TypesPage.class, new String[] {});
+    mount(types);
+
+    MixedParamUrlCodingStrategy typeBrowser = new MixedParamUrlCodingStrategy(
+        "type", TypeBrowserPage.class, new String[] { "name", "pageNum" });
+    mount(typeBrowser);
+
+    MixedParamUrlCodingStrategy prodBrowser = new MixedParamUrlCodingStrategy(
+        "product", ProductBrowserPage.class, new String[] { "id" });
+    mount(prodBrowser);
+
+  }
+
+  /**
+   * @see org.apache.wicket.Application#getHomePage()
+   */
+  public Class<Home> getHomePage() {
+    return Home.class;
+  }
+
+
+}
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/Home.html b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/Home.html
new file mode 100644
index 0000000..bb646e9
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/Home.html
@@ -0,0 +1,33 @@
+<!--
+ 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.
+-->
+<html
+	xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<head>
+<title>OODT CAS File Manager Browser</title>
+</head>
+<body>
+
+<h3>Welcome to the File Manager Browser!</h3>
+
+<ul>
+	<li><a href="#" wicket:id="find_product">Browse for a product in the
+	file manager</a>.</li>
+</ul>
+
+
+</body>
+</html>
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/Home.java b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/Home.java
new file mode 100644
index 0000000..3f88012
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/Home.java
@@ -0,0 +1,50 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.webapp.browser;
+
+//OODT imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.WebPage;
+
+/**
+ * Homepage
+ */
+public class Home extends WebPage {
+
+	private static final long serialVersionUID = 1L;
+
+    /**
+	 * Constructor that is invoked when page is invoked without a session.
+	 * 
+	 * @param parameters
+	 *            Page parameters
+	 */
+    public Home(final PageParameters parameters) {
+
+        add(new Link<Object>("find_product"){
+          /* (non-Javadoc)
+           * @see org.apache.wicket.markup.html.link.Link#onClick()
+           */
+          @Override
+          public void onClick() {
+            setResponsePage(TypesPage.class);            
+          }
+        });
+    }
+}
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductBrowserPage.html b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductBrowserPage.html
new file mode 100644
index 0000000..a5a8d1b
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductBrowserPage.html
@@ -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.
+-->
+<div wicket:id="product_browser_component" id="product_browser_component"/>
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductBrowserPage.java b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductBrowserPage.java
new file mode 100644
index 0000000..e1eec03
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductBrowserPage.java
@@ -0,0 +1,45 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.webapp.browser;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.filemgr.browser.product.ProductBrowser;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+
+/**
+ * 
+ * Page that exposes the underlying {@link ProductBrowser} OODT 
+ * Wicket component.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ProductBrowserPage extends WebPage {
+
+  public ProductBrowserPage(PageParameters parameters) {
+    ProductBrowser browserComponent = new ProductBrowser(
+        "product_browser_component", ((FMBrowserApp) getApplication())
+            .getFmUrlStr(), parameters.getString("id"));
+    add(browserComponent);
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductMetBrowserPage.html b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductMetBrowserPage.html
new file mode 100644
index 0000000..68f59ce
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductMetBrowserPage.html
@@ -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.
+-->
+<div wicket:id="product_met_browser_component" id="product_met_browser_component"/>
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductMetBrowserPage.java b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductMetBrowserPage.java
new file mode 100644
index 0000000..244ab40
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductMetBrowserPage.java
@@ -0,0 +1,45 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.webapp.browser;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.filemgr.browser.metadata.MetadataBrowser;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+
+/**
+ * 
+ * Page that exposes the underlying {@link MetadataBrowser} 
+ * OODT Wicket component.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ProductMetBrowserPage extends WebPage {
+
+  public ProductMetBrowserPage(PageParameters parameters) {
+    MetadataBrowser metBrowser = new MetadataBrowser(
+        "product_met_browser_component", ((FMBrowserApp) getApplication())
+            .getFmUrlStr(), parameters.getString("id"));
+    add(metBrowser);
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductRefsBrowserPage.html b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductRefsBrowserPage.html
new file mode 100644
index 0000000..59d5f7c
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductRefsBrowserPage.html
@@ -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.
+-->
+<div wicket:id="product_refs_browser_component" id="product_refs_browser_component"/>
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductRefsBrowserPage.java b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductRefsBrowserPage.java
new file mode 100644
index 0000000..63dd079
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/ProductRefsBrowserPage.java
@@ -0,0 +1,45 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.webapp.browser;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.filemgr.browser.product.ProductRefsBrowser;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+
+/**
+ * 
+ * Page that exposes the underlying {@link ProductRefsBrowser}
+ * OODT Wicket component.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ProductRefsBrowserPage extends WebPage {
+
+  public ProductRefsBrowserPage(PageParameters parameters) {
+    ProductRefsBrowser refsBrowser = new ProductRefsBrowser(
+        "product_refs_browser_component", ((FMBrowserApp) getApplication())
+            .getFmUrlStr(), parameters.getString("id"));
+    add(refsBrowser);
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/TypeBrowserPage.html b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/TypeBrowserPage.html
new file mode 100644
index 0000000..147501d
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/TypeBrowserPage.html
@@ -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.
+-->
+<div wicket:id="type_browser_component" id="type_browser"/>
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/TypeBrowserPage.java b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/TypeBrowserPage.java
new file mode 100644
index 0000000..3939690
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/TypeBrowserPage.java
@@ -0,0 +1,49 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.webapp.browser;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.filemgr.browser.types.TypeBrowser;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+
+/**
+ * 
+ * Exposes the OODT Wicket {@link TypeBrowser} component 
+ * in a web page.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TypeBrowserPage extends WebPage {
+
+  public TypeBrowserPage(PageParameters parameters) {
+    String typeName = parameters.getString("name");
+    int pageNum = parameters.getInt("pageNum", 1);
+
+    TypeBrowser browser = new TypeBrowser("type_browser_component",
+        ((FMBrowserApp) getApplication()).getFmUrlStr(), typeName, pageNum,
+        TypeBrowserPage.class, ProductBrowserPage.class, ProductRefsBrowserPage.class,
+        ProductMetBrowserPage.class);
+    add(browser);
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/TypesPage.html b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/TypesPage.html
new file mode 100644
index 0000000..ef4ffa6
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/TypesPage.html
@@ -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.
+-->
+<div wicket:id="types_component" id="types_component"/>
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/TypesPage.java b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/TypesPage.java
new file mode 100644
index 0000000..8865073
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/java/org/apache/oodt/cas/filemgr/webapp/browser/TypesPage.java
@@ -0,0 +1,44 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.webapp.browser;
+
+//OODT imports
+import org.apache.oodt.cas.webcomponents.filemgr.browser.types.Types;
+
+//Wicket imports
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+
+/**
+ * 
+ * Exposes the underlying OODT Wicket 
+ * {@link Types} component on a web page.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TypesPage extends WebPage {
+
+  public TypesPage(PageParameters parameters) {
+    Types typesComponent = new Types("types_component",
+        ((FMBrowserApp) getApplication()).getFmUrlStr(), TypeBrowserPage.class);
+    add(typesComponent);
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/resources/log4j.properties b/0.8.1-rc1/webapp/fmbrowser/src/main/resources/log4j.properties
new file mode 100644
index 0000000..5e742c2
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/resources/log4j.properties
@@ -0,0 +1,27 @@
+# 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.
+
+log4j.appender.Stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.Stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.Stdout.layout.conversionPattern=%-5p - %-26.26c{1} - %m\n
+
+log4j.rootLogger=INFO,Stdout
+
+log4j.logger.org.apache.wicket=INFO
+log4j.logger.org.apache.wicket.protocol.http.HttpSessionStore=INFO
+log4j.logger.org.apache.wicket.version=INFO
+log4j.logger.org.apache.wicket.RequestCycle=INFO
+
+
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/webapp/META-INF/context.xml b/0.8.1-rc1/webapp/fmbrowser/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..4362edd
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,23 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<Context path="/browser">
+		
+	<Parameter name="filemgr.url"
+	    value="http://localhost:9000"/>
+	    
+</Context>
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/main/webapp/WEB-INF/web.xml b/0.8.1-rc1/webapp/fmbrowser/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fd9834b
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ 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.
+-->
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+	 version="2.4">
+
+	<display-name>filemgr-browser</display-name>
+
+	 <!--  
+	      There are three means to configure Wickets configuration mode and they are
+	      tested in the order given. 
+	      1) A system property: -Dwicket.configuration
+	      2) servlet specific <init-param>
+	      3) context specific <context-param>
+	      The value might be either "development" (reloading when templates change)
+	      or "deployment". If no configuration is found, "development" is the default.
+	-->
+
+	<filter>
+		<filter-name>wicket.browser</filter-name>
+ 		<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
+		<init-param>
+			<param-name>applicationClassName</param-name>
+			<param-value>org.apache.oodt.cas.filemgr.webapp.browser.FMBrowserApp</param-value>
+ 		</init-param>
+ 	</filter>
+
+ <filter-mapping>
+  <filter-name>wicket.browser</filter-name>
+	<url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+
+</web-app>
diff --git a/0.8.1-rc1/webapp/fmbrowser/src/test/java/org/apache/oodt/cas/filemgr/webapp/browser/TestHome.java b/0.8.1-rc1/webapp/fmbrowser/src/test/java/org/apache/oodt/cas/filemgr/webapp/browser/TestHome.java
new file mode 100644
index 0000000..070c5b2
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmbrowser/src/test/java/org/apache/oodt/cas/filemgr/webapp/browser/TestHome.java
@@ -0,0 +1,57 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.filemgr.webapp.browser;
+
+//Junit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.webapp.browser.Home;
+import org.apache.oodt.cas.filemgr.webapp.browser.FMBrowserApp;
+
+//Wicket imports
+import org.apache.wicket.util.tester.WicketTester;
+
+/**
+ * Test harness to see if the main 
+ * CAS browser home page loads up.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class TestHome extends TestCase
+{
+	private WicketTester tester;
+
+	@Override
+	public void setUp()
+	{
+	  FMBrowserApp app = new FMBrowserApp();
+		tester = new WicketTester(app);
+	}
+
+	public void testRenderMyPage()
+	{
+		//start and render the test page
+		tester.startPage(Home.class);
+
+		//assert rendered page class
+		tester.assertRenderedPage(Home.class);
+	}
+}
diff --git a/0.8.1-rc1/webapp/fmprod/pom.xml b/0.8.1-rc1/webapp/fmprod/pom.xml
new file mode 100644
index 0000000..a15a11e
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/pom.xml
@@ -0,0 +1,189 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more contributor
+  license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>cas-product</artifactId>
+  <packaging>war</packaging>
+  <name>CAS Product Server Web Application</name>
+  <description>
+    This project builds on top of the CAS file management component and exposes
+    its underlying data delivery capabilities using the OODT ProductServer
+    component. All-in-all, this project contributes an OODT LargeProductHandler
+    component, that can be used to deliver and format a CAS product structure
+    into an OODT XML Query Result Set.
+  </description>
+  <build>
+    <testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
+    <plugins>
+      <!--
+        For plugins by Maven we don't need to specify a groupId because the
+        groupId org.apache.maven.plugins is assumed by default.
+      -->
+      <plugin>
+        <artifactId>maven-war-plugin</artifactId>
+        <version>2.4</version>
+        <configuration>
+          <webResources>
+            <resource>
+              <!-- this is relative to the pom.xml directory -->
+              <directory>.</directory>
+              <includes>
+                <include>LICENSE.txt</include>
+                <include>CHANGES.txt</include>
+              </includes>
+              <targetPath>META-INF/</targetPath>
+            </resource>
+          </webResources>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <configuration>
+          <descriptorRefs>
+            <descriptorRef>
+              jar-with-dependencies
+            </descriptorRef>
+          </descriptorRefs>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <systemProperties>
+            <property>
+              <name>java.util.logging.config.file</name>
+              <value>
+                ${basedir}/src/test/resources/test.logging.properties
+              </value>
+            </property>
+          </systemProperties>
+          <excludes>
+            <exclude>
+             org/apache/oodt/cas/product/service/resources/ResourceTestBase.java
+            </exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-filemgr</artifactId>
+      <version>${project.parent.version}</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-metadata</artifactId>
+      <version>${project.parent.version}</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-commons</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-product</artifactId>
+      <version>${project.parent.version}</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-xmlquery</artifactId>
+      <version>${project.parent.version}</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+      <version>4.2.5</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tika</groupId>
+      <artifactId>tika-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.4</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <!--
+        Zip4j is released under the Apache License, Version 2.0
+        For reference, see: http://www.lingala.net/zip4j/about.php
+      -->
+      <groupId>net.lingala.zip4j</groupId>
+      <artifactId>zip4j</artifactId>
+      <version>1.3.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.jettison</groupId>
+      <artifactId>jettison</artifactId>
+      <version>1.3.4</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-rs-extension-providers</artifactId>
+      <version>2.6.8</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+      <version>2.6.8</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-transports-local</artifactId>
+      <version>2.6.8</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <version>3.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.11</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>xmlunit</groupId>
+      <artifactId>xmlunit</artifactId>
+      <version>1.4</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.velocity</groupId>
+      <artifactId>velocity</artifactId>
+      <version>1.7</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/CASProductHandler.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/CASProductHandler.java
new file mode 100644
index 0000000..12d3ad9
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/CASProductHandler.java
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Collections;
+import java.util.Iterator;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.product.data.DataUtils;
+import org.apache.oodt.product.LargeProductQueryHandler;
+import org.apache.oodt.product.ProductException;
+import org.apache.oodt.xmlquery.Header;
+import org.apache.oodt.xmlquery.LargeResult;
+import org.apache.oodt.xmlquery.XMLQuery;
+import static org.apache.oodt.cas.filemgr.metadata.CoreMetKeys.*;
+import static org.apache.oodt.cas.product.CASProductHandlerMetKeys.*;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class CASProductHandler implements LargeProductQueryHandler {
+
+    private XmlRpcFileManagerClient fm;
+
+    public CASProductHandler() throws MalformedURLException,
+            ConnectionException {
+        this.fm = new XmlRpcFileManagerClient(new URL(System.getProperty(
+                "fm.url", "http://localhost:9000")));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.product.QueryHandler#query(org.apache.xmlquery.XMLQuery)
+     */
+    public XMLQuery query(XMLQuery query) throws ProductException {
+        // we'll only accept queries for ProductId=some_id
+        String kwdQuery = query.getKwdQueryString();
+        String[] kwdQueryToks = kwdQuery.split("=");
+        if (kwdQueryToks == null
+                || (kwdQueryToks != null && kwdQueryToks.length != 2)) {
+            throw new ProductException(
+                    "Malformed query: CASProductHandler only accepts queries of the "
+                            + "form " + PRODUCT_ID
+                            + " = <some product id>: your query was: "
+                            + kwdQuery);
+        }
+
+        String prodId = kwdQueryToks[1];
+        Product product = null;
+        try {
+            product = this.fm.getProductById(prodId);
+            product.setProductReferences(this.fm.getProductReferences(product));
+        } catch (CatalogException e) {
+            throw new ProductException(
+                    "Exception querying file manager for product: [" + prodId
+                            + "]: Message: " + e.getMessage());
+        }
+
+        try {
+            addResultsFromProductId(query, product);
+        } catch (URISyntaxException e) {
+            throw new ProductException(
+                    "URI Syntax Exception deciphering product: ["
+                            + product.getProductName() + "]: Message: "
+                            + e.getMessage());
+        }
+        return query;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.product.LargeProductQueryHandler#close(java.lang.String)
+     */
+    public void close(String id) throws ProductException {
+        // doesn't really have to do anything b/c we're not going
+        // to keep anything open
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.product.LargeProductQueryHandler#retrieveChunk(java.lang.String,
+     *      long, int)
+     */
+    public byte[] retrieveChunk(String id, long offset, int length)
+            throws ProductException {
+
+        InputStream in = null;
+        byte[] buf = null;
+
+        try {
+            URL url = new URL(id);
+            URLConnection c = url.openConnection();
+            in = c.getInputStream();
+
+            buf = new byte[length];
+            int numRead;
+            long numSkipped;
+            numSkipped = in.skip(offset);
+            if (numSkipped != offset) {
+                throw new ProductException("Was not able to skip: [" + offset
+                        + "] bytes into product: num actually skipped: ["
+                        + numSkipped + "]");
+            }
+
+            numRead = in.read(buf, 0, length);
+
+            if (numRead != length) {
+                throw new ProductException("Was not able to read: [" + length
+                        + "] bytes from product: num actually read: ["
+                        + numRead + "]");
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new ProductException(
+                    "IO exception retrieving chunk of product: [" + id
+                            + "]: Message: " + e.getMessage());
+        } finally {
+            if (in != null) {
+                try {
+                    in.close();
+                } catch (Exception ignore) {
+                }
+
+                in = null;
+            }
+        }
+
+        return buf;
+
+    }
+
+    private void addResultsFromProductId(XMLQuery query, Product product)
+            throws URISyntaxException {
+
+        if (product != null && product.getProductReferences() != null
+                && product.getProductReferences().size() > 0) {
+            for (Iterator<Reference> i = product.getProductReferences()
+                    .iterator(); i.hasNext();) {
+                Reference r = i.next();
+                query.getResults().add(toResult(r));
+            }
+        }
+
+    }
+
+    private LargeResult toResult(Reference r) throws URISyntaxException {
+        String mimeType = r.getMimeType() != null ? r.getMimeType().getName()
+                : DataUtils.guessTypeFromName(r.getDataStoreReference());
+        LargeResult result = new LargeResult(r.getDataStoreReference(),
+                mimeType, CAS_PROFILE_ID, new File(new URI(r
+                        .getDataStoreReference())).getName(),
+                Collections.singletonList(new Header(FILE_HEADER, mimeType,
+                        null /* unit */)), r.getFileSize());
+        return result;
+    }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/CASProductHandlerMetKeys.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/CASProductHandlerMetKeys.java
new file mode 100644
index 0000000..8275c70
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/CASProductHandlerMetKeys.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public interface CASProductHandlerMetKeys {
+    
+    public static final String FILE_HEADER = "File";
+    
+    public static final String CAS_PROFILE_ID = "CAS.Profile.Id";
+    
+    public static final String UNKNOWN = "UNKNOWN";
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/data/DataDeliveryKeys.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/data/DataDeliveryKeys.java
new file mode 100644
index 0000000..1d4e41e
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/data/DataDeliveryKeys.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.data;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>Met keys for Data Delivery using the data servlets</p>.
+ */
+public interface DataDeliveryKeys {
+
+  public static final String FORMAT_ZIP = "application/x-zip";
+
+  public static final String CONTENT_TYPE_HDR = "Content-Type";
+
+  public static final String CONTENT_LENGTH_HDR = "Content-Length";
+
+  public static final String CONTENT_DISPOSITION_HDR = "Content-Disposition";
+  
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/data/DataDeliveryServlet.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/data/DataDeliveryServlet.java
new file mode 100644
index 0000000..d82f7ee
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/data/DataDeliveryServlet.java
@@ -0,0 +1,267 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.data;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+
+/**
+ * Data Delivery Servlet.
+ * 
+ * The Data Delivery Serlvet retrieves the product data from the file manager.
+ */
+public class DataDeliveryServlet extends HttpServlet implements
+    DataDeliveryKeys {
+
+  /** {@inheritDoc} */
+  public void init(ServletConfig config) throws ServletException {
+    super.init(config);
+    try {
+      String fileMgrURL = null;
+      try {
+        fileMgrURL = PathUtils.replaceEnvVariables(config.getServletContext().getInitParameter(
+            "filemgr.url") );
+      } catch (Exception e) {
+        throw new ServletException("Failed to get filemgr url : " + e.getMessage(), e);
+      }
+      if (fileMgrURL == null)
+        fileMgrURL = "http://localhost:9000";
+      client = new XmlRpcFileManagerClient(new URL(fileMgrURL));
+    } catch (MalformedURLException ex) {
+      throw new ServletException(ex);
+    } catch (ConnectionException ex) {
+      throw new ServletException(ex);
+    }
+
+    workingDirPath = config.getServletContext().getInitParameter(
+        "filemgr.working.dir");
+
+    // need the working dir to be specified, else throw exception
+    if (workingDirPath == null) {
+      throw new ServletException("no servlet working dir path specified!");
+    } else {
+      // clean it
+      this.workingDirPath += this.workingDirPath.endsWith("/") ? "" : "/";
+    }
+  }
+
+  /** {@inheritDoc} */
+  public void doGet(HttpServletRequest req, HttpServletResponse res)
+      throws ServletException, IOException {
+    doPut(req, res);
+  }
+
+  /**
+   * Handle a request for product data. Request parameters include a mandatory
+   * <code>productID</code> identifying what product to retrieve, and an
+   * optional <code>refIndex</code> in order to select which reference file to
+   * send. By default it sends the zeroth reference.
+   * 
+   * In addition, an optional <code>format</code> option can be specified to
+   * indicate that the product data be zipped up and delivered back as a
+   * zip file.
+   * 
+   * @param req
+   *          Servlet request
+   * @param res
+   *          Servlet response
+   * @throws ServletException
+   *           If an error occurs
+   * @throws IOException
+   *           If an I/O error occurs
+   */
+  public void doPut(HttpServletRequest req, HttpServletResponse res)
+      throws ServletException, IOException {
+    try {
+      String productID = req.getParameter("productID");
+      if (productID == null)
+        throw new IllegalArgumentException("productID is required");
+      String refIndex = req.getParameter("refIndex");
+      if (refIndex == null)
+        refIndex = "0";
+      int index = Integer.parseInt(refIndex);
+      String format = req.getParameter("format");
+
+      if (format == null) {
+        // then just deliver back the particular product file
+        deliverProductFile(req, res, index, productID);
+      } else {
+        // make sure it's application/x-zip
+        if (!format.equals(FORMAT_ZIP)) {
+          throw new IllegalArgumentException("unknown product return format: "
+              + format);
+        }
+
+        try {
+          deliverProductAsZip(req, res, productID);
+        } catch (Exception e) {
+          throw new ServletException(e);
+        }
+      }
+
+    } catch (IllegalArgumentException ex) {
+      throw new ServletException(ex);
+    } catch (CatalogException ex) {
+      throw new ServletException(ex);
+    }
+  }
+
+  private void deliverProductAsZip(HttpServletRequest req,
+      HttpServletResponse res, String productID) throws CatalogException {
+    Product product = client.getProductById(productID);
+    product.setProductReferences(client.getProductReferences(product));
+    Metadata metadata = client.getMetadata(product);
+
+    // we'll be delivering a zip
+    res.addHeader(CONTENT_TYPE_HDR, FORMAT_ZIP);
+
+    String productZipFilePath = null;
+    File productZipFile = null;
+    InputStream in = null;
+    OutputStream o2 = null;
+
+    try {
+      productZipFilePath = DataUtils.createProductZipFile(product, metadata,
+          workingDirPath);
+      productZipFile = new File(productZipFilePath);
+      String productZipFileName = productZipFile.getName();
+
+      res.addHeader(CONTENT_DISPOSITION_HDR, "attachment; filename=\""
+          + productZipFileName + "\"");
+
+      // add the content length for the zip file size
+      res.addHeader(CONTENT_LENGTH_HDR, String.valueOf(new File(
+          productZipFilePath).length()));
+
+      // now we need to read the zip file in, and write it to the output
+      // stream
+      in = new FileInputStream(productZipFile);
+
+      // Call java.io.File.delete() on the file, while still open.
+      if (!productZipFile.delete()) {
+        throw new RuntimeException("Unable to delete streaming file: ["
+            + productZipFile.getAbsolutePath() + "] while delivering!");
+      }
+
+      // 3. Deliver the data.
+      o2 = res.getOutputStream();
+      byte[] buf = new byte[512];
+      int n;
+      while ((n = in.read(buf)) != -1)
+        o2.write(buf, 0, n);
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Exception delivering data!: Message: "
+          + e.getMessage());
+    } finally {
+      if (in != null) {
+        try {
+          in.close();
+        } catch (Exception ignore) {
+        }
+
+        in = null;
+      }
+
+      if (o2 != null) {
+        try {
+          o2.close();
+        } catch (Exception ignore) {
+        }
+
+        o2 = null;
+      }
+
+      productZipFile = null;
+    }
+
+  }
+
+  private void deliverProductFile(HttpServletRequest req,
+      HttpServletResponse res, int index, String productID)
+      throws CatalogException, IOException {
+    Product product = client.getProductById(productID);
+    List refs = client.getProductReferences(product);
+    Reference ref = (Reference) refs.get(index);
+    res.addHeader(CONTENT_LENGTH_HDR, String.valueOf(ref.getFileSize()));
+    String contentType = (ref.getMimeType() != null
+        && ref.getMimeType().getName() != null && !ref.getMimeType().getName()
+        .equals("")) ? ref.getMimeType().getName() : DataUtils
+        .guessTypeFromName(ref.getDataStoreReference());
+    res.addHeader(CONTENT_TYPE_HDR, contentType);
+    try {
+      res.addHeader(CONTENT_DISPOSITION_HDR, "attachment; filename=\""
+          + new File(new URI(ref.getDataStoreReference())).getName() + "\"");
+    } catch (URISyntaxException e) {
+      LOG.log(Level.WARNING,
+          "Unable to sense filename from data store URI: Message: "
+              + e.getMessage());
+    }
+    URL url = new URL(ref.getDataStoreReference());
+    URLConnection c = url.openConnection();
+    InputStream in = c.getInputStream();
+    OutputStream out = res.getOutputStream();
+    byte[] buf = new byte[512];
+    int n;
+    while ((n = in.read(buf)) != -1)
+      out.write(buf, 0, n);
+    in.close();
+    out.close();
+  }
+
+  /** Client i/f to filemgr server. */
+  private XmlRpcFileManagerClient client;
+
+  /** our log stream */
+  private static final Logger LOG = Logger.getLogger(DataDeliveryServlet.class
+      .getName());
+
+  /** our working dir path. */
+  private String workingDirPath;
+
+  /** serial version UID. */
+  private static final long serialVersionUID = -955613407495060869L;
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/data/DataUtils.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/data/DataUtils.java
new file mode 100644
index 0000000..aa2eadf
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/data/DataUtils.java
@@ -0,0 +1,233 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.data;
+
+//JDK imports
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Iterator;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+
+/**
+ * 
+ * Utility methods for delivering data using the filemgr servlet data API.
+ * 
+ * @author mattmann
+ * @version $Revision$ .
+ */
+public final class DataUtils implements DataDeliveryKeys {
+
+  /* our log stream */
+  private static final Logger LOG = Logger.getLogger(DataUtils.class.getName());
+
+  /* file filter to list zip files */
+  private static final FileFilter ZIP_FILTER = new FileFilter() {
+    public boolean accept(File file) {
+      return file.isFile() && file.getName().endsWith(".zip");
+    }
+
+  };
+
+  public static String createDatasetZipFile(ProductType type,
+      String workingDirPath) throws Exception {
+    String datasetZipFileName = type.getName() + ".zip";
+    workingDirPath += workingDirPath.endsWith("/") ? "" : "/";
+    String datasetZipFilePath = workingDirPath + datasetZipFileName;
+
+    // try and remove it first
+    if (!new File(datasetZipFilePath).delete()) {
+      LOG.log(Level.WARNING, "Attempt to remove temp dataset zip file: ["
+          + datasetZipFilePath + "] failed.");
+    }
+
+    // get a list of all the product zip files within the temp dir
+    // assumption: the temp dir provided has a whole bunch of *.zip files
+    // that are zips of the products (and their files and metadata)
+    // belonging
+    // to this dataset
+
+    // NOTE: it is important that this step be done BEFORE creating the zip
+    // output stream: else that will cause the generated datset zip to be
+    // included as well!
+    File[] productZipFiles = new File(workingDirPath).listFiles(ZIP_FILTER);
+    if (productZipFiles == null || productZipFiles.length == 0)
+    {
+      throw new Exception("No product zip files to include in dataset: ["
+          + type.getName() + "]");
+    }
+
+    // now get a reference to the zip file that we want to write
+    ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
+        datasetZipFilePath));
+
+    for (int i = 0; i < productZipFiles.length; i++) {
+      String filename = productZipFiles[i].getName();
+      FileInputStream in = new FileInputStream(productZipFiles[i]
+          .getAbsoluteFile());
+      addZipEntryFromStream(in, out, filename);
+      in.close();
+      
+      if (!productZipFiles[i].delete()) {
+        LOG.log(Level.WARNING, "Unable to remove tempoary product zip file: ["
+            + productZipFiles[i].getAbsolutePath() + "]");
+      }
+      else{
+        LOG.log(Level.INFO, "Deleting original product zip file: ["
+            + productZipFiles[i].getAbsolutePath() + "]");
+      }
+    }
+
+    // add met file
+    addMetFileToProductZip(type.getTypeMetadata(), type.getName(), out);
+
+    // Complete the ZIP file
+    out.close();
+
+    // return the zip file path
+    return datasetZipFilePath;
+
+  }
+
+  public static String createProductZipFile(Product product, Metadata metadata,
+      String workingDirPath) throws Exception {
+    String productZipFileName = product.getProductName() + ".zip";
+    workingDirPath += workingDirPath.endsWith("/") ? "" : "/";
+    String productZipFilePath = workingDirPath + productZipFileName;
+
+    // try and remove it first
+    if (!new File(productZipFilePath).delete()) {
+      LOG.log(Level.WARNING, "Attempt to remove temp zip file: ["
+          + productZipFilePath + "] failed.");
+    }
+
+    // now get a reference to the zip file that we want to write
+    ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
+        productZipFilePath));
+
+    for (Iterator i = product.getProductReferences().iterator(); i.hasNext();) {
+      Reference r = (Reference) i.next();
+
+      try {
+        File prodFile = new File(new URI(r.getDataStoreReference()));
+        if (prodFile.isDirectory()) {
+            LOG.log(Level.WARNING, "Data store reference is a directory. Not adding directory to the zip file: ["
+                    + r.getDataStoreReference() + "]");
+            continue;
+        }
+        String filename = prodFile.getName();
+        FileInputStream in = new FileInputStream(prodFile.getAbsoluteFile());
+        addZipEntryFromStream(in, out, filename);
+        in.close();
+      } catch (URISyntaxException e) {
+        LOG.log(Level.WARNING, "Unable to get filename from uri: ["
+            + r.getDataStoreReference() + "]");
+      }
+
+    }
+
+    // add met file
+    addMetFileToProductZip(metadata, product.getProductName(), out);
+
+    // Complete the ZIP file
+    out.close();
+
+    // return the zip file path
+    return productZipFilePath;
+
+  }
+
+  /**
+   * Guess what the content type is from the given url.
+   * 
+   * @param name
+   *          URL to reference.
+   * @return A guessed content type.
+   */
+  public static String guessTypeFromName(String name) {
+    name = name.toLowerCase();
+    if (name.endsWith(".jpg") || name.endsWith(".jpeg"))
+      return "image/jpeg";
+    else if (name.endsWith(".png"))
+      return "image/png";
+    else if (name.endsWith(".gif"))
+      return "image/gif";
+    else if (name.endsWith(".doc"))
+      return "application/msword";
+    else if (name.endsWith(".pdf"))
+      return "application/pdf";
+    else if (name.endsWith(".rtf"))
+      return "application/rtf";
+    else if (name.endsWith(".xls"))
+      return "application/vnd.ms-excel";
+    else if (name.endsWith(".ppt"))
+      return "application/vnd.ms-powerpoint";
+    else if (name.endsWith(".html") || name.endsWith(".htm"))
+      return "text/html";
+    else if (name.endsWith(".xml"))
+      return "text/xml";
+    else if (name.endsWith(".txt"))
+      return "text/plain";
+    return "application/octet-stream";
+  }
+
+  private static void addMetFileToProductZip(Metadata productMet,
+      String metFileBaseName, ZipOutputStream out) throws Exception {
+
+    // get the product metadata, and add its met file to the stream
+    ByteArrayOutputStream metOut = new ByteArrayOutputStream();
+    SerializableMetadata serialMet = new SerializableMetadata(productMet);
+    serialMet.writeMetadataToXmlStream(metOut);
+    ByteArrayInputStream metIn = new ByteArrayInputStream(metOut.toByteArray());
+    String metFileName = metFileBaseName + ".met";
+    addZipEntryFromStream(metIn, out, metFileName);
+  }
+
+  private static void addZipEntryFromStream(InputStream is, ZipOutputStream os,
+      String filename) throws IOException {
+    byte[] buf = new byte[512];
+    os.putNextEntry(new ZipEntry(filename));
+
+    int len;
+    while ((len = is.read(buf)) > 0) {
+      os.write(buf, 0, len);
+    }
+
+    // Complete the entry
+    os.closeEntry();
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/data/DatasetDeliveryServlet.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/data/DatasetDeliveryServlet.java
new file mode 100644
index 0000000..c0c08fc
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/data/DatasetDeliveryServlet.java
@@ -0,0 +1,282 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.data;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Delivers back entire {@link ProductType}s (or <code>Dataset</code>s) as
+ * zipped up packages.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class DatasetDeliveryServlet extends HttpServlet implements
+    DataDeliveryKeys {
+
+  /* our log stream */
+  private static final Logger LOG = Logger
+      .getLogger(DatasetDeliveryServlet.class.getName());
+
+  /* serial version UID */
+  private static final long serialVersionUID = -6692665690674186105L;
+
+  /* our file manager client */
+  private XmlRpcFileManagerClient client;
+
+  /* the working dir in which to create huge zip files */
+  private String workingDirPath;
+
+  /* indicates the product has been zipped up already */
+  private final static String ALREADY_ZIPPED = "00ga";
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
+   * javax.servlet.http.HttpServletResponse)
+   */
+  protected void doGet(HttpServletRequest req, HttpServletResponse res)
+      throws ServletException, IOException {
+    doPut(req, res);
+  }
+
+  /**
+   * 
+   * Method requires a single parameter, <code>typeID</code>, specifying a valid
+   * {@link ProductType} within the filemgr. All {@link Product}s associated
+   * with the given <code>typeID</code> are packaged up (as zip files), and then
+   * aggregated and zipped and delivered as an entire collection called a
+   * <code>Dataset</code>.
+   * 
+   * @param req
+   *          Servlet request.
+   * @param res
+   *          Servlet response
+   * @throws ServletException
+   *           If any error occurs.
+   * @throws IOException
+   *           If an I/O error occurs.
+   */
+  protected void doPut(HttpServletRequest req, HttpServletResponse res)
+      throws ServletException, IOException {
+
+    String typeID = req.getParameter("typeID");
+    ProductType type = null;
+
+    if (typeID == null) {
+      throw new IllegalArgumentException("No typeID parameter specified!");
+    }
+
+    try {
+      type = client.getProductTypeById(typeID);
+    } catch (Exception e) {
+      throw new ServletException("Unable to deduce product type: [" + typeID
+          + "]: Message: " + e.getMessage());
+    }
+
+    // create a temporary product dir: we'll use working dir + typeName
+    String productDirPath = workingDirPath + type.getName();
+    if (!new File(productDirPath).mkdirs()) {
+      LOG.log(Level.WARNING,
+          "mkdirs returned false for temporary dataset dir: [" + productDirPath
+              + "]: errors may follow");
+    }
+
+    // use the pagination API to iterate over each product
+    // for each product, zip it up
+    // after you zip up all products then create the dataset zip
+
+    ProductPage page = null;
+
+    try {
+      page = client.getFirstPage(type);
+      if (page == null
+          || (page != null && page.getPageProducts() == null)
+          || (page != null && page.getPageProducts() != null && page
+              .getPageProducts().size() == 0)) {
+        throw new ServletException("No products for dataset: ["
+            + type.getName() + "]");
+      }
+
+      Map productHash = new HashMap();
+
+      do {
+        for (Iterator i = page.getPageProducts().iterator(); i.hasNext();) {
+          Product product = (Product) i.next();
+          if (alreadyZipped(product, productHash)) {
+            continue;
+          }
+
+          Metadata metadata = null;
+          product.setProductReferences(client.getProductReferences(product));
+          metadata = client.getMetadata(product);
+          DataUtils.createProductZipFile(product, metadata, productDirPath);
+          productHash.put(product.getProductName(), ALREADY_ZIPPED);
+        }
+
+        page = client.getNextPage(type, page);
+
+      } while ((page != null && !page.isLastPage())
+          && (page.getPageProducts() != null && page.getPageProducts().size() > 0));
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw new ServletException(e.getMessage());
+    }
+
+    // now that all product zips have been created, create the dataset
+    // zip
+    String datasetZipFilePath = null;
+    File datasetZipFile = null;
+    InputStream in = null;
+    OutputStream o2 = null;
+
+    try {
+      datasetZipFilePath = DataUtils.createDatasetZipFile(type, productDirPath);
+
+      datasetZipFile = new File(datasetZipFilePath);
+      String datasetZipFileName = datasetZipFile.getName();
+
+      res.addHeader(CONTENT_DISPOSITION_HDR, "attachment; filename=\""
+          + datasetZipFileName + "\"");
+
+      // add the content length for the zip file size
+      res.addHeader(CONTENT_LENGTH_HDR, String.valueOf(new File(
+          datasetZipFilePath).length()));
+
+      // now we need to read the zip file in, and write it to the output
+      // stream
+      in = new FileInputStream(datasetZipFile);
+
+      // Call java.io.File.delete() on the file, while still open.
+      if (!datasetZipFile.delete()) {
+        throw new RuntimeException("Unable to delete streaming file: ["
+            + datasetZipFile.getAbsolutePath() + "] while delivering!");
+      }
+
+      // 3. Deliver the data.
+      o2 = res.getOutputStream();
+      byte[] buf = new byte[512];
+      int n;
+      while ((n = in.read(buf)) != -1)
+        o2.write(buf, 0, n);
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Exception delivering dataset: Message: "
+          + e.getMessage());
+    } finally {
+      if (in != null) {
+        try {
+          in.close();
+        } catch (Exception ignore) {
+        }
+
+        in = null;
+      }
+
+      if (o2 != null) {
+        try {
+          o2.close();
+        } catch (Exception ignore) {
+        }
+
+        o2 = null;
+      }
+
+      // now try and remove the tmp working directory for the
+      // dataset zip
+      if (datasetZipFile != null) {
+        datasetZipFile.getParentFile().delete();
+      }
+      datasetZipFile = null;
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
+   */
+  public void init(ServletConfig config) throws ServletException {
+    super.init(config);
+
+    try {
+      String fileMgrURL = null;
+      try {
+        fileMgrURL = PathUtils.replaceEnvVariables(config.getServletContext().getInitParameter(
+            "filemgr.url") );
+      } catch (Exception e) {
+        throw new ServletException("Failed to get filemgr url : " + e.getMessage(), e);
+      }      
+      if (fileMgrURL == null)
+        fileMgrURL = "http://localhost:9000";
+      client = new XmlRpcFileManagerClient(new URL(fileMgrURL));
+    } catch (MalformedURLException ex) {
+      throw new ServletException(ex);
+    } catch (ConnectionException ex) {
+      throw new ServletException(ex);
+    }
+
+    workingDirPath = config.getServletContext().getInitParameter(
+        "filemgr.working.dir");
+
+    // need the working dir to be specified, else throw exception
+    if (workingDirPath == null) {
+      throw new ServletException("no servlet working dir path specified!");
+    } else {
+      // clean it
+      this.workingDirPath += this.workingDirPath.endsWith("/") ? "" : "/";
+    }
+
+  }
+
+  private boolean alreadyZipped(Product p, Map hash) {
+    return hash.containsKey(p.getProductName());
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RdfConfiguration.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RdfConfiguration.java
new file mode 100644
index 0000000..c91b89e
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RdfConfiguration.java
@@ -0,0 +1,195 @@
+package org.apache.oodt.cas.product.jaxrs.configurations;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.WordUtils;
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * Class representing custom configurations for RDF XML outputs.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class RdfConfiguration
+{
+  // Constants used to identify items in the configuration file.
+  private static final String RDF_RES_ATTR = "rdf:resource";
+  private static final String NS_OUTER = "namespaces";
+  private static final String NS_INNER = "ns";
+  private static final String NS_KEY = "name";
+  private static final String NS_VALUE = "value";
+  private static final String REWRITE_OUTER = "rewrite";
+  private static final String REWRITE_INNER = "key";
+  private static final String REWRITE_KEY = "from";
+  private static final String REWRITE_VALUE = "to";
+  private static final String RESLINK_OUTER = "resourcelinks";
+  private static final String RESLINK_INNER = "key";
+  private static final String RESLINK_KEY = "name";
+  private static final String RESLINK_VALUE = "link";
+  private static final String KEY_OUTER = "keynsmap";
+  private static final String KEY_INNER = "key";
+  private static final String KEY_KEY = "name";
+  private static final String KEY_VALUE = "ns";
+  private static final String KEY_DEFAULT = "default";
+  private static final String TYPE_OUTER = "typesnsmap";
+  private static final String TYPE_INNER = "type";
+  private static final String TYPE_KEY = "name";
+  private static final String TYPE_VALUE = "ns";
+  private static final String TYPE_DEFAULT = "default";
+
+  private Map<String, String> nsMap = new HashMap<String, String>();
+  private Map<String, String> rewriteMap = new HashMap<String, String>();
+  private Map<String, String> resLinkMap = new HashMap<String, String>();
+  private Map<String, String> keyNsMap = new HashMap<String, String>();
+  private Map<String, String> typesNsMap = new HashMap<String, String>();
+  private String defaultKeyNs = null;
+  private String defaultTypeNs = null;
+
+
+
+  /**
+   * Initializes the parameters in the configuration object using values from
+   * the supplied file.
+   * @param file the configuration file
+   * @throws IOException if the file does not exist and cannot be read
+   */
+  public void initialize(File file) throws IOException
+  {
+    FileInputStream fis = new FileInputStream(file);
+    Document doc = XMLUtils.getDocumentRoot(fis);
+    Element root = doc.getDocumentElement();
+
+    nsMap = readConfiguration(root,
+      NS_OUTER, NS_INNER, NS_KEY, NS_VALUE);
+
+    rewriteMap = readConfiguration(root,
+      REWRITE_OUTER, REWRITE_INNER, REWRITE_KEY, REWRITE_VALUE);
+
+    resLinkMap = readConfiguration(root,
+      RESLINK_OUTER, RESLINK_INNER, RESLINK_KEY, RESLINK_VALUE);
+
+    keyNsMap = readConfiguration(root,
+      KEY_OUTER, KEY_INNER, KEY_KEY, KEY_VALUE);
+
+    typesNsMap = readConfiguration(root,
+      TYPE_OUTER, TYPE_INNER, TYPE_KEY, TYPE_VALUE);
+
+    Element keyNsRoot = XMLUtils.getFirstElement(KEY_OUTER, root);
+    defaultKeyNs = keyNsRoot.getAttribute(KEY_DEFAULT);
+
+    Element typeNsRoot = XMLUtils.getFirstElement(TYPE_OUTER, root);
+    defaultTypeNs = typeNsRoot.getAttribute(TYPE_DEFAULT);
+
+    fis.close();
+  }
+
+
+
+  private Map<String, String> readConfiguration(Element element,
+    String outerTag, String innerTag, String key, String value)
+  {
+    Map<String, String> map = new HashMap<String, String>();
+
+    Element outer = XMLUtils.getFirstElement(outerTag, element);
+    NodeList nodeList = outer.getElementsByTagName(innerTag);
+    if (nodeList != null && nodeList.getLength() > 0)
+    {
+      for (int i = 0; i < nodeList.getLength(); i++)
+      {
+        Element inner = (Element) nodeList.item(i);
+        map.put(inner.getAttribute(key), inner.getAttribute(value));
+      }
+    }
+
+    return map;
+  }
+
+
+
+  /**
+   * Gets the namespace map for the configuration.
+   * @return the namespace map for the configuration
+   */
+  public Map<String, String> getNamespaces()
+  {
+    return nsMap;
+  }
+
+
+
+  /**
+   * Gets the requested value from the key namespace map if it is found,
+   * otherwise gets the default key namespace.
+   * @param key the map key to use for retrieving the namespace
+   * @return the namespace value for the map key if found, otherwise the default
+   * namespace
+   */
+  public String getKeyNamespace(String key)
+  {
+    return keyNsMap.containsKey(key) ? keyNsMap.get(key) : defaultKeyNs;
+  }
+
+
+
+  /**
+   * Gets the requested value from the type namespace map if it is found,
+   * otherwise gets the default type namespace.
+   * @param key the map key to use for retrieving the namespace
+   * @return the namespace value for the map key if found, otherwise the default
+   * namespace
+   */
+  public String getTypeNamespace(String key)
+  {
+    return typesNsMap.containsKey(key) ? typesNsMap.get(key) : defaultTypeNs;
+  }
+
+
+
+  /**
+   * Creates an {@link Element} for a {@link Document}.
+   * @param key a map key used to search this configuration's maps
+   * @param value the value for the element
+   * @param document the document context of the element
+   * @return a new element constructed within the rules and constraints of this
+   * configuration
+   */
+  public Element createElement(String key, String value, Document document)
+  {
+    // Apply the rewrite rules.
+    String tagName = rewriteMap.containsKey(key) ? rewriteMap.get(key) : key;
+    if (tagName.indexOf(" ") != -1) {
+      tagName = StringUtils.join(WordUtils.capitalizeFully(tagName).split(
+          " "));
+    }
+
+    // Get the tag's namespace or the default namespace.
+    String namespace = keyNsMap.containsKey(key)
+      ? keyNsMap.get(key) : defaultKeyNs;
+
+    // Create the element.
+    Element element = null;
+    if (resLinkMap.containsKey(key))
+    {
+      element = document.createElement(namespace + ":" + tagName);
+      String linkBase = resLinkMap.get(key);
+      linkBase += linkBase.endsWith("/") ? "" : "/";
+      element.setAttribute(RDF_RES_ATTR, linkBase + value);
+    }
+    else
+    {
+      element = document.createElement(namespace + ":" + tagName);
+      element.appendChild(document.createTextNode(StringEscapeUtils.escapeXml(value)));
+    }
+
+    return element;
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RssConfiguration.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RssConfiguration.java
new file mode 100644
index 0000000..96db937
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RssConfiguration.java
@@ -0,0 +1,178 @@
+package org.apache.oodt.cas.product.jaxrs.configurations;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.WordUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * Class representing custom configurations for RSS XML outputs.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class RssConfiguration
+{
+  private static final String CHANNEL_LINK = "channelLink";
+  private static final String NAMESPACE = "namespace";
+  private static final String NAMESPACE_KEY = "prefix";
+  private static final String NAMESPACE_VALUE = "uri";
+  private static final String TAG = "tag";
+  private static final String TAG_NAME = "name";
+  private static final String TAG_SOURCE = "source";
+  private static final String ATTRIBUTE = "attribute";
+  private static final String ATTRIBUTE_NAME = "name";
+  private static final String ATTRIBUTE_VALUE = "value";
+
+  private List<RssNamespace> namespaceList = new Vector<RssNamespace>();
+  private List<RssTag> tagList = new Vector<RssTag>();
+  private String channelLink = null;
+
+
+
+  /**
+   * Initializes the parameters in the configuration object using values from
+   * the supplied file.
+   * @param file the configuration file
+   * @throws IOException if the file does not exist and cannot be read
+   */
+  public void initialize(File file) throws IOException
+  {
+    FileInputStream fis = new FileInputStream(file);
+    Document document = XMLUtils.getDocumentRoot(fis);
+    Element root = document.getDocumentElement();
+
+    channelLink = root.getAttribute(CHANNEL_LINK);
+    namespaceList = readNamespaces(root);
+    tagList = readTags(root);
+
+    fis.close();
+  }
+
+
+
+  private List<RssNamespace> readNamespaces(Element root)
+  {
+    List<RssNamespace> namespaces = new Vector<RssNamespace>();
+    NodeList nodeList = root.getElementsByTagName(NAMESPACE);
+    if (nodeList != null && nodeList.getLength() > 0)
+    {
+      for (int i = 0; i < nodeList.getLength(); i++)
+      {
+        Element element = (Element) nodeList.item(i);
+        namespaces.add(new RssNamespace(element.getAttribute(NAMESPACE_KEY),
+          element.getAttribute(NAMESPACE_VALUE)));
+      }
+    }
+    return namespaces;
+  }
+
+
+
+  private List<RssTag> readTags(Element root)
+  {
+    List<RssTag> tags = new Vector<RssTag>();
+    NodeList list = root.getElementsByTagName(TAG);
+    if (list != null && list.getLength() > 0)
+    {
+      for (int i = 0; i < list.getLength(); i++)
+      {
+        Element element = (Element) list.item(i);
+        tags.add(new RssTag(element.getAttribute(TAG_NAME),
+          element.getAttribute(TAG_SOURCE), readAttributes(element)));
+      }
+    }
+    return tags;
+  }
+
+
+
+  private List<RssTagAttribute> readAttributes(Element element)
+  {
+    List<RssTagAttribute> attributes = new Vector<RssTagAttribute>();
+    NodeList nodeList = element.getElementsByTagName(ATTRIBUTE);
+    if (nodeList != null && nodeList.getLength() > 0)
+    {
+      for (int i = 0; i < nodeList.getLength(); i++)
+      {
+        Element attribute = (Element) nodeList.item(i);
+        attributes.add(new RssTagAttribute(
+          attribute.getAttribute(ATTRIBUTE_NAME),
+          attribute.getAttribute(ATTRIBUTE_VALUE)));
+      }
+    }
+    return attributes;
+  }
+
+
+
+  /**
+   * Gets the list of namespaces.
+   * @return the list of namespaces
+   */
+  public List<RssNamespace> getNamespaceList()
+  {
+    return namespaceList;
+  }
+
+
+
+  /**
+   * Gets the channel link URL string.
+   * @return the channel link URL string
+   */
+  public String getChannelLink()
+  {
+    return channelLink;
+  }
+
+
+
+  /**
+   * Appends elements (tags) defined in a configuration file to a specific
+   * parent element.
+   * @param metadata the metadata for the product
+   * @param document the document to which these elements belong
+   * @param parent the parent element to attach these elements to
+   */
+  public void appendTags(Metadata metadata, Document document,
+    Element parent)
+  {
+    for (RssTag tag : tagList)
+    {
+      String tagName = tag.getName();
+      if (tagName.indexOf(" ") != -1) {
+        tagName = StringUtils.join(WordUtils.capitalizeFully(tagName).split(
+            " "));
+      }
+
+      
+      // Create a new element for the tag.
+      Element element = XMLUtils.addNode(document, parent, tagName);
+
+      // Add a value for the tag from the tag source.
+      if (tag.getSource() != null)
+      {
+        element.appendChild(document.createTextNode(StringEscapeUtils.escapeXml(PathUtils
+          .replaceEnvVariables(tag.getSource(), metadata))));
+      }
+
+      // Add attributes to the tag as defined in the configuration.
+      for (RssTagAttribute attribute : tag.getAttributes())
+      {
+        element.setAttribute(attribute.getName(), PathUtils.replaceEnvVariables(
+          attribute.getValue(), metadata));
+      }
+    }
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RssNamespace.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RssNamespace.java
new file mode 100644
index 0000000..17ec8f6
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RssNamespace.java
@@ -0,0 +1,46 @@
+
+package org.apache.oodt.cas.product.jaxrs.configurations;
+
+/**
+ * Represents an XML namespace for RSS XML content.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class RssNamespace
+{
+  private String prefix;
+  private String uriString;
+
+  /**
+   * Creates an RssNamespace object and sets the prefix and uri string.
+   * @param prefix the namespace prefix
+   * @param uriString the namespace URI as a String
+   */
+  public RssNamespace(String prefix, String uriString)
+  {
+    this.prefix = prefix;
+    this.uriString = uriString;
+  }
+
+
+
+  /**
+   * Gets the prefix for the namespace.
+   * @return the prefix for the namespace
+   */
+  public String getPrefix()
+  {
+    return prefix;
+  }
+
+
+
+  /**
+   * Gets the URI for the namespace as a String
+   * @return the URI for the namespace as a String
+   */
+  public String getUriString()
+  {
+    return uriString;
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RssTag.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RssTag.java
new file mode 100644
index 0000000..073efb8
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RssTag.java
@@ -0,0 +1,63 @@
+package org.apache.oodt.cas.product.jaxrs.configurations;
+
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * Represents an RSS XML tag to include in an RSS feed.
+ * @author mattmann
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class RssTag
+{
+  private String name = null;
+  private String source = null;
+  private List<RssTagAttribute> attributes = new Vector<RssTagAttribute>();
+
+  /**
+   * Creates an RssTag object and sets the name, source and attributes.
+   * @param name the name for the tag
+   * @param source the source for the tag
+   * @param attributes the attributes for the tag
+   */
+  public RssTag(String name, String source, List<RssTagAttribute> attributes)
+  {
+    this.name = name;
+    this.source = source;
+    this.attributes = attributes;
+  }
+
+
+
+  /**
+   * Gets the name for the tag.
+   * @return the name for the tag
+   */
+  public String getName()
+  {
+    return name;
+  }
+
+
+
+  /**
+   * Gets the source for the tag.
+   * @return the source for the tag
+   */
+  public String getSource()
+  {
+    return source;
+  }
+
+
+
+  /**
+   * Gets the attributes for the tag.
+   * @return the attributes for the tag
+   */
+  public List<RssTagAttribute> getAttributes()
+  {
+    return attributes;
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RssTagAttribute.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RssTagAttribute.java
new file mode 100644
index 0000000..07e9192
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/RssTagAttribute.java
@@ -0,0 +1,44 @@
+package org.apache.oodt.cas.product.jaxrs.configurations;
+
+/**
+ * Represents an attribute for an RSS XML tag.
+ * @author mattmann
+ * @author rlaidlaw
+ * @version $Revision$
+*/
+public class RssTagAttribute
+{
+  private String name;
+  private String value;
+
+  /**
+   * Creates an RssTagAttribute and sets the name and value.
+   * @param name the name of the attribute
+   * @param value the value for the attribute
+   */
+  public RssTagAttribute(String name, String value)
+  {
+    this.name = name;
+    this.value = value;
+  }
+
+  /**
+   * Gets the name of the attribute.
+   * @return the name of the attribute
+   */
+  public String getName()
+  {
+    return name;
+  }
+
+
+
+  /**
+   * Gets the value of the attribute.
+   * @return the value of the attribute
+   */
+  public String getValue()
+  {
+    return value;
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/package-info.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/package-info.java
new file mode 100644
index 0000000..5daf8b3
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/configurations/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+*/
+
+/**
+ * Contains classes that are used to add custom configurations to outputs.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+package org.apache.oodt.cas.product.jaxrs.configurations;
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/exceptions/BadRequestException.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/exceptions/BadRequestException.java
new file mode 100644
index 0000000..2e2de7a
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/exceptions/BadRequestException.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.exceptions;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * This type of exception returns an HTTP 'bad request' response (status code
+ * 400) with an additional message.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class BadRequestException extends WebApplicationException
+{
+  // Auto-generated ID for serialization.
+  private static final long serialVersionUID = -705065311316100022L;
+
+  /**
+   * Constructor that adds a message to the 'bad request' (status code 400)
+   * HTTP response.
+   * @param message the message to add to the response
+   */
+  public BadRequestException(String message)
+  {
+    super(Response.status(Response.Status.BAD_REQUEST).entity(message)
+      .type(MediaType.TEXT_PLAIN).build());
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/exceptions/InternalServerErrorException.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/exceptions/InternalServerErrorException.java
new file mode 100644
index 0000000..5af0842
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/exceptions/InternalServerErrorException.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.exceptions;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * This type of exception returns an HTTP 'internal server error' response
+ * (status code 500) with an additional message.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class InternalServerErrorException extends WebApplicationException
+{
+  // Auto-generated ID for serialization.
+  private static final long serialVersionUID = -6132240509391531373L;
+
+  /**
+   * Constructor that adds a message to the 'internal server error' (status code
+   * 500) HTTP response.
+   * @param message the message to add to the response
+   */
+  public InternalServerErrorException(String message)
+  {
+    super(Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message)
+      .type(MediaType.TEXT_PLAIN).build());
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/exceptions/NotFoundException.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/exceptions/NotFoundException.java
new file mode 100644
index 0000000..108ed97
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/exceptions/NotFoundException.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.exceptions;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * This type of exception returns an HTTP 'not found' response (status code 404)
+ * with an additional message.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class NotFoundException extends WebApplicationException
+{
+  // Auto-generated ID for serialization.
+  private static final long serialVersionUID = -3835077083758525919L;
+
+  /**
+   * Constructor that adds a message to the 'not found' (status code 404)
+   * HTTP response.
+   * @param message the message to add to the response
+   */
+  public NotFoundException(String message)
+  {
+    super(Response.status(Response.Status.NOT_FOUND).entity(message)
+      .type(MediaType.TEXT_PLAIN).build());
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/exceptions/package-info.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/exceptions/package-info.java
new file mode 100644
index 0000000..7a69729
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/exceptions/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+*/
+
+/**
+ * Contains classes that extend javax.ws.rs.WebApplicationException to provide
+ * specific response status codes and messages.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+package org.apache.oodt.cas.product.jaxrs.exceptions;
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/filters/BackwardsCompatibleInterceptor.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/filters/BackwardsCompatibleInterceptor.java
new file mode 100644
index 0000000..c581382
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/filters/BackwardsCompatibleInterceptor.java
@@ -0,0 +1,119 @@
+package org.apache.oodt.cas.product.jaxrs.filters;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
+import org.apache.cxf.phase.Phase;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.utils.URLEncodedUtils;
+
+/**
+ * An Apache CXF interceptor for the incoming chain that monitors request URIs
+ * and maps any URIs from the original scheme to the new scheme.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class BackwardsCompatibleInterceptor extends
+  AbstractPhaseInterceptor<Message>
+{
+  /**
+   * Constructor that inserts the interceptor at the USER_STREAM phase of the
+   * incoming interceptor chain.
+   */
+  public BackwardsCompatibleInterceptor()
+  {
+    super(Phase.USER_STREAM);
+  }
+
+  @Override
+  public void handleMessage(Message message) throws Fault
+  {
+    String base = (String) message.get(Message.BASE_PATH);
+    String uri = (String) message.get(Message.REQUEST_URI);
+    String query = (String) message.get(Message.QUERY_STRING);
+
+    base += base.endsWith("/") ? "" : "/";
+    String request = uri.replaceAll("^" + base, "");
+
+    // Parse the query string into a map of parameters.
+    // [Note: this will overwrite multiple parameters that have the same name.]
+    List<NameValuePair> params = URLEncodedUtils.parse(query, Charset.forName("UTF-8"));
+    Map<String, String> map = new HashMap<String, String>();
+    for (NameValuePair pair : params)
+    {
+      map.put(pair.getName(), pair.getValue());
+    }
+
+    // Maps "data?productID=<product ID>" URI to either
+    // "reference.file?productId=<product ID>" or
+    // "product.zip?productId=<product ID>"
+    if(request.equals("data"))
+    {
+      String format = map.get("format");
+      request =
+        "application/x-zip".equals(format) || "application/zip".equals(format)
+        ? "product.zip" : "reference.file";
+
+      query = "productId=" + map.get("productID");
+      query += map.containsKey("refIndex")
+        ? "&refIndex=" + map.get("refIndex") : "";
+    }
+
+    // Maps "dataset?typeID=<product type ID>" to
+    // "dataset.zip?productTypeId=<product type ID>"
+    else if(request.equals("dataset") && map.containsKey("typeID"))
+    {
+      request = "dataset.zip";
+      query = "productTypeId=" + map.get("typeID");
+    }
+
+    // Maps "rdf?type=ALL" or "rdf?id=<product type ID>" to
+    // "dataset.rdf?productTypeId=<ALL or product type ID>"
+    else if (request.equals("rdf"))
+    {
+      request = "dataset.rdf";
+      String type = map.get("type");
+      query = "productTypeId=";
+      query += "ALL".equals(type) ? type : map.get("id");
+    }
+
+    // Maps "rdf/dataset?type=ALL" or "rdf/dataset?typeID=<product type ID>" to
+    // "dataset.rdf?productTypeId=<ALL or product type ID>"
+    else if (request.equals("rdf/dataset"))
+    {
+      request = "dataset.rdf";
+      String type = map.get("type");
+      query = "productTypeId=";
+      query += "ALL".equals(type) ? type : map.get("typeID");
+      query += map.containsKey("filter") ? "&filter=" + map.get("filter") : "";
+    }
+
+    // Maps "viewRecent?channel=ALL" or "viewRecent?id=<product type ID>" to
+    // "dataset.rss?productTypeId=<ALL or product type ID>"
+    else if (request.equals("viewRecent"))
+    {
+      request = "dataset.rss";
+      String channel = map.get("channel");
+      query = "productTypeId=";
+      query += "ALL".equals(channel) ? channel : map.get("id");
+      query += map.containsKey("topn") ? "&limit=" + map.get("topn") : "";
+    }
+
+    // Maps "viewTransfers" to "transfers.rss?productId=ALL"
+    else if (request.equals("viewTransfers"))
+    {
+      request = "transfers.rss";
+      query = "productId=ALL";
+    }
+
+    // Store the new URI and query in the message map.
+    uri = base + request;
+    message.put(Message.REQUEST_URI, uri);
+    message.put(Message.QUERY_STRING, query);
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/filters/package-info.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/filters/package-info.java
new file mode 100644
index 0000000..faa1a45
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/filters/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+*/
+
+/**
+ * Contains filters for HTTP requests and responses.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+package org.apache.oodt.cas.product.jaxrs.filters;
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/package-info.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/package-info.java
new file mode 100644
index 0000000..57790e5
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+*/
+
+/**
+ * Contains sub-packages with classes that implement a JAX-RS service for the
+ * CAS Product web application.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+package org.apache.oodt.cas.product.jaxrs;
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/DatasetResource.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/DatasetResource.java
new file mode 100755
index 0000000..cbb26ce
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/DatasetResource.java
@@ -0,0 +1,155 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.resources;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * A JAX-RS resource representing a dataset - a set of {@link Product products}
+ * maintained by the file manager.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@XmlRootElement(name="dataset")
+@XmlType(propOrder = {"id", "name", "metadataResource", "productResources"})
+@XmlAccessorType(XmlAccessType.NONE)
+public class DatasetResource
+{
+  private String id;
+  private String name;
+  private MetadataResource metadataResource;
+  private List<ProductResource> productResources =
+    new ArrayList<ProductResource>();
+
+  // The file manager's working directory for this resource, used for example
+  // when creating zip archives.
+  private File workingDir;
+
+
+
+  /**
+   * Default constructor required by JAXB.
+   */
+  public DatasetResource()
+  {
+  }
+
+
+
+  /**
+   * Constructor that sets the name, metadata and working directory for the
+   * dataset resource.
+   * @param id the ID of the dataset
+   * @param name the name of the dataset
+   * @param metadata the metadata for the dataset
+   * @param workingDir the working directory for creating temporary files to
+   * attach to responses
+   */
+  public DatasetResource(String id, String name, Metadata metadata,
+    File workingDir)
+  {
+    this.id = id;
+    this.name = name;
+    this.metadataResource = new MetadataResource(metadata);
+    this.workingDir = workingDir;
+  }
+
+
+
+  /**
+   * Adds a {@link ProductResource} to the list of product resources for the
+   * dataset.
+   * @param resource the resource to add to the dataset.
+   */
+  public void addProductResource(ProductResource resource)
+  {
+    productResources.add(resource);
+  }
+
+
+
+  /**
+   * Gets the working directory for the dataset.
+   * @return the working directory
+   */
+  public File getWorkingDir()
+  {
+    return workingDir;
+  }
+
+
+
+  /**
+   * Gets the id of the dataset.
+   * @return the id of the dataset
+   */
+  @XmlElement
+  public String getId()
+  {
+    return id;
+  }
+
+
+
+  /**
+   * Gets the name of the dataset.
+   * @return the name of the dataset
+   */
+  @XmlElement
+  public String getName()
+  {
+    return name;
+  }
+
+
+
+  /**
+   * Gets the product resources for the dataset.
+   * @return the productResources
+   */
+  @XmlElementWrapper(name = "products")
+  @XmlElement(name = "product")
+  public List<ProductResource> getProductResources()
+  {
+    return productResources;
+  }
+
+
+
+  /**
+   * Gets the metadata resource for the dataset.
+   * @return the metadata resource
+   */
+  @XmlElement(name = "metadata")
+  public MetadataResource getMetadataResource()
+  {
+    return metadataResource;
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/MetadataResource.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/MetadataResource.java
new file mode 100644
index 0000000..2e77f57
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/MetadataResource.java
@@ -0,0 +1,150 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.resources;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * A JAX-RS resource representing a {@link Metadata} object.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@XmlRootElement(name = "metadata")
+@XmlAccessorType(XmlAccessType.NONE)
+public class MetadataResource
+{
+  private Metadata metadata;
+
+  /**
+   * Default constructor required by JAXB.
+   */
+  public MetadataResource()
+  {
+  }
+
+
+
+  /**
+   * Constructor that sets the metadata for the resource.
+   * @param metadata the metadata for the resource
+   */
+  public MetadataResource(Metadata metadata)
+  {
+    this.metadata = metadata;
+  }
+
+
+
+  /**
+   * Gets the metadata.
+   * @return the metadata
+   */
+  public Metadata getMetadata()
+  {
+    return metadata;
+  }
+
+
+
+  /**
+   * Gets a map of metadata keys and values.
+   * @return a map of metadata keys and values
+   */
+  @XmlElement(name = "keyval")
+  public List<MetadataEntry> getMetadataEntries()
+  {
+     List<MetadataEntry> entries = new ArrayList<MetadataEntry>();
+     for (String key : metadata.getAllKeys())
+     {
+       entries.add(new MetadataEntry(key, metadata.getAllMetadata(key)));
+     }
+     return entries;
+  }
+
+
+
+  /**
+   * Represents a metadata keyval entry.
+   * @author rlaidlaw
+   * @version $Revision$
+   */
+  @XmlRootElement
+  @XmlType(propOrder = {"key", "values"})
+  @XmlAccessorType(XmlAccessType.NONE)
+  public static class MetadataEntry
+  {
+    private String key;
+    private List<String> values;
+
+
+
+    /**
+     * Default constructor required by JAXB.
+     */
+    public MetadataEntry()
+    {
+    }
+
+
+
+    /**
+     * Constructor that creates a metadata entry using the supplied key and list
+     * of values.
+     * @param key the key for the metadata entry
+     * @param values the values for the metadata entry
+     */
+    public MetadataEntry(String key, List<String> values)
+    {
+      this.key = key;
+      this.values = values;
+    }
+
+
+
+    /**
+     * Gets the key for the metadata entry.
+     * @return the key for the metadata entry
+     */
+    @XmlElement(name = "key")
+    public String getKey()
+    {
+      return key;
+    }
+
+
+
+    /**
+     * Gets the value(s) for the metadata entry
+     * @return the value(s) for the metadata entry
+     */
+    @XmlElement(name = "val")
+    public List<String> getValues()
+    {
+      return values;
+    }
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/ProductResource.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/ProductResource.java
new file mode 100755
index 0000000..4b7f528
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/ProductResource.java
@@ -0,0 +1,195 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.resources;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * A JAX-RS resource representing a {@link Product}.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@XmlRootElement(name = "product")
+@XmlType(propOrder = {"productId", "productName", "productStructure",
+  "productTypeName", "transferStatus", "metadataResource",
+  "referenceResources"})
+@XmlAccessorType(XmlAccessType.NONE)
+public class ProductResource
+{
+  private Product product;
+  private MetadataResource metadataResource;
+  private List<ReferenceResource> referenceResources =
+    new ArrayList<ReferenceResource>();
+
+  // The file manager's working directory for this resource, used for example
+  // when creating zip archives.
+  private File workingDir;
+
+
+
+  /**
+   * Default constructor required by JAXB.
+   */
+  public ProductResource()
+  {
+  }
+
+
+
+  /**
+   * Constructor that sets the product, metadata, references and
+   * working directory for the resource.
+   * @param product the product associated with the resource
+   * @param metadata the metadata associated with the resource
+   * @param references the references associated with the resource
+   * @param workingDir the working directory for creating temporary files to
+   * attach to responses
+   */
+  public ProductResource(Product product, Metadata metadata,
+    List<Reference> references, File workingDir)
+  {
+    this.product = product;
+    this.metadataResource = new MetadataResource(metadata);
+    for (int index = 0; index < references.size(); index++)
+    {
+      referenceResources.add(new ReferenceResource(product.getProductId(),
+        index, references.get(index), workingDir));
+    }
+    this.workingDir = workingDir;
+  }
+
+
+
+  /**
+   * Gets the working directory for the product.
+   * @return the working directory
+   */
+  public File getWorkingDir()
+  {
+    return workingDir;
+  }
+
+
+
+  /**
+   * Gets the product's ID.
+   * @return the product's ID.
+   */
+  @XmlElement(name = "id")
+  public String getProductId()
+  {
+    return product.getProductId();
+  }
+
+
+
+  /**
+   * Gets the product's name.
+   * @return the product's name
+   */
+  @XmlElement(name = "name")
+  public String getProductName()
+  {
+    return product.getProductName();
+  }
+
+
+
+  /**
+   * Gets the product's structure.
+   * @return a string describing the product's structure
+   */
+  @XmlElement(name = "structure")
+  public String getProductStructure()
+  {
+    return product.getProductStructure();
+  }
+
+
+
+  /**
+   * Gets the name of the product's type.
+   * @return the name of the product's type
+   */
+  @XmlElement(name = "type")
+  public String getProductTypeName()
+  {
+    return product.getProductType().getName();
+  }
+
+
+
+  /**
+   * Gets the transfer status for the product.
+   * @return the transfer status for the product
+   */
+  @XmlElement(name = "transferStatus")
+  public String getTransferStatus()
+  {
+    return product.getTransferStatus();
+  }
+
+
+
+  /**
+   * Gets the metadata resource for the product.
+   * @return the product's metadata resource
+   */
+  @XmlElement(name = "metadata")
+  public MetadataResource getMetadataResource()
+  {
+    return metadataResource;
+  }
+
+
+
+  /**
+   * Gets the reference resources.
+   * @return the reference resources
+   */
+  @XmlElementWrapper(name = "references")
+  @XmlElement(name = "reference")
+  public List<ReferenceResource> getReferenceResources()
+  {
+    return referenceResources;
+  }
+
+
+
+  /**
+   * Gets the product's references.
+   * @return the product's references
+   */
+  public List<Reference> getProductReferences()
+  {
+    return product.getProductReferences();
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/ReferenceResource.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/ReferenceResource.java
new file mode 100644
index 0000000..5446349
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/ReferenceResource.java
@@ -0,0 +1,192 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.resources;
+
+import java.io.File;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.tika.mime.MimeType;
+
+/**
+ * A JAX-RS resource representing a {@link Reference}.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@XmlRootElement(name = "reference")
+@XmlType(propOrder = {"productId", "refIndex", "dataStoreReference",
+  "origReference", "mimeTypeName", "fileSize"})
+@XmlAccessorType(XmlAccessType.NONE)
+public class ReferenceResource
+{
+  // The reference for this resource.
+  private Reference reference;
+
+  // The ID of the product that the reference belongs to.
+  private String productId;
+
+  // The index of the reference within its product.
+  private int refIndex;
+
+  // The file manager's working directory for this resource, used for example
+  // when creating zip archives.
+  private File workingDir;
+
+
+
+  /**
+   * Default constructor required by JAXB.
+   */
+  public ReferenceResource()
+  {
+  }
+
+
+
+  /**
+   * Constructor that sets the reference and working directory for the resource.
+   * @param productId the ID of the product that the reference belongs to
+   * @param refIndex the index of the reference within its product
+   * @param reference the reference for the resource
+   * @param workingDir the working directory for creating temporary files to
+   * attach to responses
+   */
+  public ReferenceResource(String productId, int refIndex, Reference reference,
+    File workingDir)
+  {
+    this.productId = productId;
+    this.refIndex = refIndex;
+    this.reference = reference;
+    this.workingDir = workingDir;
+  }
+
+
+
+  /**
+   * Gets the reference.
+   * @return the reference
+   */
+  public Reference getReference()
+  {
+    return reference;
+  }
+
+
+
+  /**
+   * Gets the working directory for the reference.
+   * @return the working directory
+   */
+  public File getWorkingDir()
+  {
+    return workingDir;
+  }
+
+
+
+  /**
+   * Gets the ID of the product that the reference belongs to.
+   * @return the ID of the product that the reference belongs to
+   */
+  @XmlElement
+  public String getProductId()
+  {
+    return productId;
+  }
+
+
+
+  /**
+   * Gets the index of the reference within its product.
+   * @return the index of the reference within its product
+   */
+  @XmlElement
+  public int getRefIndex()
+  {
+    return refIndex;
+  }
+
+
+
+  /**
+   * Gets the data store reference for the reference.
+   * @return the data store reference for the reference
+   */
+  @XmlElement
+  public String getDataStoreReference()
+  {
+    return reference.getDataStoreReference();
+  }
+
+
+
+  /**
+   * Gets the file size for the reference.
+   * @return the file size for the reference
+   */
+  @XmlElement
+  public long getFileSize()
+  {
+    return reference.getFileSize();
+  }
+
+
+
+  /**
+   * Gets the name of the MIME type for the reference.
+   * @return the name of the MIME type for the reference
+   */
+  @XmlElement(name = "mimeType")
+  public String getMimeTypeName()
+  {
+    MimeType m = reference.getMimeType();
+    if (m != null)
+    {
+      return m.getName();
+    }
+    return null;
+  }
+
+
+
+  /**
+   * Gets the MIME type for the reference.
+   * @return the MIME type for the reference
+   */
+  public MimeType getMimeType()
+  {
+    return reference.getMimeType();
+  }
+
+
+
+  /**
+   * Gets the original reference for the reference.
+   * @return the original reference for the reference
+   */
+  @XmlElement(name = "originalReference")
+  public String getOrigReference()
+  {
+    return reference.getOrigReference();
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/TransferResource.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/TransferResource.java
new file mode 100644
index 0000000..bc80021
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/TransferResource.java
@@ -0,0 +1,227 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.resources;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * A JAX-RS resource representing a {@link FileTransferStatus}.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@XmlRootElement(name = "transfer")
+@XmlType(propOrder = {"productName", "productId", "productTypeName",
+  "dataStoreReference", "origReference", "mimeTypeName", "fileSize",
+  "totalBytes", "bytesTransferred", "percentComplete", "productReceivedTime"})
+@XmlAccessorType(XmlAccessType.NONE)
+public class TransferResource
+{
+  private Reference reference;
+  private Product product;
+  private Metadata metadata;
+  private FileTransferStatus status;
+
+
+
+  /**
+   * Default constructor required by JAXB.
+   */
+  public TransferResource()
+  {
+  }
+
+
+
+  /**
+   * Constructor that sets the {@link FileTransferStatus} for the resource.
+   * @param product the product being transferred
+   * @param metadata the metadata for the product being transferred
+   * @param status the file transfer status for product
+   */
+  public TransferResource(Product product, Metadata metadata,
+    FileTransferStatus status)
+  {
+    this.reference = status.getFileRef();
+    this.product = product;
+    this.metadata = metadata;
+    this.status = status;
+  }
+
+
+
+  /**
+   * Gets the product.
+   * @return the product
+   */
+  public Product getProduct()
+  {
+    return product;
+  }
+
+
+
+  /**
+   * Gets the metadata.
+   * @return the metadata
+   */
+  public Metadata getMetadata()
+  {
+    return metadata;
+  }
+
+
+
+  /**
+   * Gets the ID of the product.
+   * @return the ID of the product
+   */
+  @XmlElement
+  public String getProductId()
+  {
+    return product.getProductId();
+  }
+
+
+
+  /**
+   * Gets the name of the product.
+   * @return the name of the product
+   */
+  @XmlElement
+  public String getProductName()
+  {
+    return product.getProductName();
+  }
+
+
+
+  /**
+   * Gets the product type name for the product.
+   * @return the product type name for the product
+   */
+  @XmlElement
+  public String getProductTypeName()
+  {
+    return product.getProductType().getName();
+  }
+
+
+
+  /**
+   * Gets the data store reference for the reference.
+   * @return the data store reference for the reference
+   */
+  @XmlElement
+  public String getDataStoreReference()
+  {
+    return reference.getDataStoreReference();
+  }
+
+
+
+  /**
+   * Gets the original reference for the reference.
+   * @return the original reference for the reference
+   */
+  @XmlElement
+  public String getOrigReference()
+  {
+    return reference.getOrigReference();
+  }
+
+
+
+  /**
+   * Gets the name of the MIME type for the reference.
+   * @return the name of the MIME type for the reference
+   */
+  @XmlElement(name = "mimeType")
+  public String getMimeTypeName()
+  {
+    return reference.getMimeType().getName();
+  }
+
+
+
+  /**
+   * Gets the file size for the reference.
+   * @return the file size for the reference
+   */
+  @XmlElement
+  public long getFileSize()
+  {
+    return reference.getFileSize();
+  }
+
+
+
+  /**
+   * Gets the total bytes of the file being transferred.
+   * @return the total bytes of the file
+   */
+  @XmlElement
+  public long getTotalBytes()
+  {
+    return status.getFileRef().getFileSize();
+  }
+
+
+
+  /**
+   * Gets the bytes transferred status of the file transfer.
+   * @return the bytes transferred status
+   */
+  @XmlElement
+  public long getBytesTransferred()
+  {
+    return status.getBytesTransferred();
+  }
+
+
+
+  /**
+   * Gets the percentage complete status of the file transfer.
+   * @return the percentage complete status of the file transfer
+   */
+  @XmlElement
+  public double getPercentComplete()
+  {
+    return status.computePctTransferred() * 100;
+  }
+
+
+
+  /**
+   * Gets the metadata value of the product received time.
+   * @return the metadata value of the product received time
+   */
+  @XmlElement
+  public String getProductReceivedTime()
+  {
+    return metadata.getMetadata("CAS.ProductReceivedTime");
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/TransfersResource.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/TransfersResource.java
new file mode 100644
index 0000000..3e0f734
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/TransfersResource.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.resources;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+
+/**
+ * A JAX-RS resource representing currently active {@link FileTransferStatus
+ * file transfers} as {@link TransferResource transfer resources}.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@XmlRootElement(name = "transfers")
+@XmlAccessorType(XmlAccessType.NONE)
+public class TransfersResource
+{
+  private String productId;
+
+  private List<TransferResource> transferResources =
+    new ArrayList<TransferResource>();
+
+
+
+  /**
+   * Default constructor required by JAXB.
+   */
+  public TransfersResource()
+  {
+  }
+
+
+
+  /**
+   * Constructor that sets the product ID and list of TransferResource
+   * instances related to the product.
+   * @param productId the product ID
+   * @param transferResources the resources representing currently active file
+   * transfers for the product
+   */
+  public TransfersResource(String productId,
+    List<TransferResource> transferResources)
+  {
+    this.productId = productId;
+    this.transferResources = transferResources;
+  }
+
+
+
+  /**
+   * Gets the product ID.
+   * @return the product ID
+   */
+  @XmlAttribute
+  public String getProductId()
+  {
+    return productId;
+  }
+
+
+
+  /**
+   * Gets the transfer resources.
+   * @return the transfer resources
+   */
+  @XmlElement(name = "transfer")
+  public List<TransferResource> getTransferResources()
+  {
+    return transferResources;
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/package-info.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/package-info.java
new file mode 100644
index 0000000..072c716
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/resources/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+*/
+
+/**
+ * Contains JAX-RS resource classes that represent file manager entities such
+ * as products, their references and their metadata.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+package org.apache.oodt.cas.product.jaxrs.resources;
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/services/CasProductJaxrsService.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/services/CasProductJaxrsService.java
new file mode 100755
index 0000000..9b4560b
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/services/CasProductJaxrsService.java
@@ -0,0 +1,370 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.services;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.product.jaxrs.exceptions.BadRequestException;
+import org.apache.oodt.cas.product.jaxrs.exceptions.NotFoundException;
+import org.apache.oodt.cas.product.jaxrs.resources.DatasetResource;
+import org.apache.oodt.cas.product.jaxrs.resources.ProductResource;
+import org.apache.oodt.cas.product.jaxrs.resources.ReferenceResource;
+import org.apache.oodt.cas.product.jaxrs.resources.TransferResource;
+import org.apache.oodt.cas.product.jaxrs.resources.TransfersResource;
+
+/**
+ * Service class that handles HTTP requests and returns file manager entities
+ * such as {@link Reference references} and {@link Product products} as
+ * JAX-RS resources converted to different formats.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class CasProductJaxrsService
+{
+  private static final Logger LOGGER = Logger.getLogger(CasProductJaxrsService
+    .class.getName());
+
+  // The servlet context, which is used to retrieve context parameters.
+  @Context
+  private ServletContext context;
+
+
+
+  /**
+   * Gets an HTTP response that represents a {@link Reference} from a {@link
+   * Product} from the file manager.
+   * @param productId the ID of the product that the reference belongs to
+   * @param refIndex the index of the reference within the product's list of
+   * references
+   * @return an HTTP response that represents a {@link Reference} from a {@link
+   * Product} from the file manager
+   */
+  @GET
+  @Path("reference")
+  @Produces({"application/octet-stream", "application/xml", "application/json",
+    "application/atom+xml", "application/rdf+xml", "application/rss+xml",
+    "application/zip"})
+  public ReferenceResource getReference(
+    @QueryParam("productId") String productId,
+    @QueryParam("refIndex") int refIndex)
+  {
+    if (productId == null || productId.trim().equals(""))
+    {
+      throw new BadRequestException("This URL requires a productId query "
+        + "parameter with a product ID value, "
+        + "e.g. /reference?productId=1787a257-df87-11e2-8a2d-e3f6264e86c5");
+    }
+
+    try
+    {
+      XmlRpcFileManagerClient client = getContextClient();
+      Product product = client.getProductById(productId);
+      List<Reference> references = client.getProductReferences(product);
+
+      return new ReferenceResource(productId, refIndex,
+        references.get(refIndex), getContextWorkingDir());
+    }
+    catch (Exception e)
+    {
+      String message = "Unable to find the requested resource.";
+      LOGGER.log(Level.FINE, message, e);
+      throw new NotFoundException(message + " " + e.getMessage());
+    }
+  }
+
+
+
+  /**
+   * Gets an HTTP response that represents a {@link Product} from the file
+   * manager.
+   * @param productId the ID of the product
+   * @return an HTTP response that represents a {@link Product} from the file
+   * manager
+   */
+  @GET
+  @Path("product")
+  @Produces({"application/xml", "application/json", "application/atom+xml",
+    "application/rdf+xml", "application/rss+xml", "application/zip"})
+  public ProductResource getProduct(@QueryParam("productId") String productId)
+  {
+    if (productId == null || productId.trim().equals(""))
+    {
+      throw new BadRequestException("This URL requires a productId query "
+        + "parameter with a product ID value, "
+        + "e.g. /product?productId=1787a257-df87-11e2-8a2d-e3f6264e86c5");
+    }
+
+    try
+    {
+      XmlRpcFileManagerClient client = getContextClient();
+
+      // Find the product.
+      Product product = client.getProductById(productId);
+      product.setProductReferences(client.getProductReferences(product));
+
+      // Create the product resource, add the product data and return the
+      // resource as the HTTP response.
+      return new ProductResource(product, client.getMetadata(product),
+        product.getProductReferences(), getContextWorkingDir());
+    }
+    catch (Exception e)
+    {
+      String message = "Unable to find the requested resource.";
+      LOGGER.log(Level.FINE, message, e);
+      throw new NotFoundException(message + " " + e.getMessage());
+    }
+  }
+
+
+
+  /**
+   * Gets an HTTP response that represents a set of {@link Product products}
+   * from the file manager.
+   * @param productTypeId the ID of the {@link ProductType} for the data set or
+   * "ALL" to denote all product types
+   * @return an HTTP response that represents a set of {@link Product products}
+   * from the file manager
+   */
+  @GET
+  @Path("dataset")
+  @Produces({"application/xml", "application/json", "application/atom+xml",
+   "application/rdf+xml", "application/rss+xml", "application/zip"})
+  public DatasetResource getDataset(
+    @QueryParam("productTypeId") String productTypeId)
+  {
+    if (productTypeId == null || productTypeId.trim().equals(""))
+    {
+      throw new BadRequestException("This URL requires a productTypeId query "
+        + "parameter and either a product type ID value or 'ALL' for all "
+        + "product types.");
+    }
+
+    try
+    {
+      XmlRpcFileManagerClient client = getContextClient();
+
+      String datasetId;
+      String datasetName;
+      Metadata datasetMetadata;
+
+      List<ProductType> productTypes = new Vector<ProductType>();
+      if (productTypeId.equals("ALL"))
+      {
+        productTypes = client.getProductTypes();
+        datasetId = productTypeId;
+        datasetName = productTypeId;
+        datasetMetadata = new Metadata();
+        datasetMetadata.addMetadata("ProductType", productTypeId);
+      }
+      else
+      {
+        ProductType productType = client.getProductTypeById(productTypeId);
+        productTypes.add(productType);
+        datasetId = productType.getProductTypeId();
+        datasetName = productType.getName();
+        datasetMetadata = productType.getTypeMetadata();
+      }
+
+      String productDirPath = getContextWorkingDir().getCanonicalPath()
+        + "/" + datasetName;
+
+      DatasetResource resource = new DatasetResource(datasetId, datasetName,
+        datasetMetadata, getContextWorkingDir());
+
+      // Add all products of the chosen type(s) to the dataset.
+      for (ProductType productType : productTypes)
+      {
+        for (Product product : client.getProductsByProductType(productType))
+        {
+          product.setProductReferences(client.getProductReferences(product));
+          resource.addProductResource(new ProductResource(product,
+            client.getMetadata(product), product.getProductReferences(),
+            new File(productDirPath)));
+        }
+      }
+      return resource;
+    }
+    catch (Exception e)
+    {
+      String message = "Unable to find the requested resource.";
+      LOGGER.log(Level.FINE, message, e);
+      throw new NotFoundException(message + " " + e.getMessage());
+    }
+  }
+
+
+
+  /**
+   * Gets an HTTP response that represents the status of a currently active
+   * file transfer for the file manager.
+   * @param dataStoreRef the data store reference for the file being transferred
+   * @return an HTTP response that represents the status of a currently active
+   * file transfer for the file manager
+   */
+  @GET
+  @Path("transfer")
+  @Produces({"application/xml", "application/json", "application/atom+xml",
+    "application/rdf+xml", "application/rss+xml"})
+  public TransferResource getTransfer(
+    @QueryParam("dataStoreRef") String dataStoreRef)
+  {
+    if (dataStoreRef == null || dataStoreRef.trim().equals(""))
+    {
+      throw new BadRequestException("This URL requires a dataStoreRef query "
+        + "parameter and a data store reference value, "
+        + "e.g. /transfer?dataStoreRef=file:/repository/test.txt/test.txt");
+    }
+
+    try
+    {
+      XmlRpcFileManagerClient client = getContextClient();
+      for (FileTransferStatus status : client.getCurrentFileTransfers())
+      {
+        Reference reference = status.getFileRef();
+        if (dataStoreRef.equals(reference.getDataStoreReference()))
+        {
+          Product product = status.getParentProduct();
+          Metadata metadata = client.getMetadata(product);
+          return new TransferResource(product, metadata, status);
+        }
+      }
+
+      throw new Exception("Unable to find a current file transfer status for"
+        + "data store reference: " + dataStoreRef);
+    }
+    catch (Exception e)
+    {
+      String message = "Unable to find the requested resource.";
+      LOGGER.log(Level.FINE, message, e);
+      throw new NotFoundException(message + " " + e.getMessage());
+    }
+  }
+
+
+
+  /**
+   * Gets an HTTP response that represents the statuses of all currently active
+   * file transfers for the file manager, optionally filtered by product ID.
+   * @param productId the ID of a product or ALL to denote all products
+   * @return an HTTP response that represents the statuses of all currently
+   * active file transfers for the file manager
+   */
+  @GET
+  @Path("transfers")
+  @Produces({"application/xml", "application/json", "application/atom+xml",
+    "application/rdf+xml", "application/rss+xml"})
+  public TransfersResource getTransfers(
+    @QueryParam("productId") String productId)
+  {
+    if (productId == null || productId.trim().equals(""))
+    {
+      throw new BadRequestException("This URL requires a productId query "
+        + "parameter and either a valid product ID value or 'ALL' for all "
+        + "products.");
+    }
+
+    try
+    {
+      List<TransferResource> transferResources =
+        new ArrayList<TransferResource>();
+      XmlRpcFileManagerClient client = getContextClient();
+      for (FileTransferStatus status : client.getCurrentFileTransfers())
+      {
+        Product product = status.getParentProduct();
+        if(productId.equals("ALL") || productId.equals(product.getProductId()))
+        {
+          Metadata metadata = client.getMetadata(product);
+          transferResources.add(
+            new TransferResource(product, metadata, status));
+        }
+      }
+      return new TransfersResource(productId, transferResources);
+    }
+    catch (Exception e)
+    {
+      String message = "Unable to find the requested resource.";
+      LOGGER.log(Level.FINE, message, e);
+      throw new NotFoundException(message + " " + e.getMessage());
+    }
+  }
+
+
+
+  /**
+   * Gets the file manager's working directory from the servlet context.
+   * @return the file manager working directory
+   * @throws Exception if an object cannot be retrieved from the context
+   * attribute
+   */
+  public File getContextWorkingDir() throws Exception
+  {
+    Object workingDirObject = context.getAttribute("workingDir");
+    if (workingDirObject != null && workingDirObject instanceof File)
+    {
+      return (File) workingDirObject;
+    }
+
+    String message = "Unable to get the file manager's working "
+      + "directory from the servlet context.";
+    LOGGER.log(Level.WARNING, message);
+    throw new Exception(message);
+  }
+
+
+
+  /**
+   * Gets the file manager client instance from the servlet context.
+   * @return the file manager client instance from the servlet context attribute
+   * @throws Exception if an object cannot be retrieved from the context
+   * attribute
+   */
+  public XmlRpcFileManagerClient getContextClient()
+    throws Exception
+  {
+    // Get the file manager client from the servlet context.
+    Object clientObject = context.getAttribute("client");
+    if (clientObject != null &&
+        clientObject instanceof XmlRpcFileManagerClient)
+    {
+      return (XmlRpcFileManagerClient) clientObject;
+    }
+
+    String message = "Unable to get the file manager client from the "
+      + "servlet context.";
+    LOGGER.log(Level.WARNING, message);
+    throw new Exception(message);
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/services/package-info.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/services/package-info.java
new file mode 100644
index 0000000..70fcba4
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/services/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+*/
+
+/**
+ * Contains service classes for the JAX-RS service.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+package org.apache.oodt.cas.product.jaxrs.services;
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/servlets/CasProductJaxrsServlet.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/servlets/CasProductJaxrsServlet.java
new file mode 100755
index 0000000..ee88739
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/servlets/CasProductJaxrsServlet.java
@@ -0,0 +1,220 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.servlets;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.product.jaxrs.configurations.RdfConfiguration;
+import org.apache.oodt.cas.product.jaxrs.configurations.RssConfiguration;
+
+/**
+ * Provides a single place to initialize items such as the file manager client,
+ * working directory and configurations when the web application is started up.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class CasProductJaxrsServlet extends CXFNonSpringJaxrsServlet
+{
+  // Auto-generated ID for serialization.
+  private static final long serialVersionUID = -1835790185000773396L;
+
+  private static final Logger LOGGER = Logger.getLogger(CasProductJaxrsServlet
+    .class.getName());
+
+  private static final int CONFIG_PARAM_LENGTH = 3;
+  private static final int CONFIG_PARAM_FORMAT = 1;
+  private static final int CONFIG_PARAM_NAME = 2;
+
+
+  @Override
+  public void init(ServletConfig configuration) throws ServletException
+  {
+    super.init(configuration);
+    ServletContext context = configuration.getServletContext();
+    initializeClient(context);
+    initializeWorkingDir(context);
+    initializeConfigurations(context);
+  }
+
+
+
+  /**
+   * Initializes the file manager client and stores it as a "client" context
+   * attribute by retrieving a value for the file manager URL from the servlet
+   * context.
+   * @param context the servlet context
+   * @throws ServletException if the servlet context parameter for the file
+   * manager working directory path cannot be found
+   */
+  private void initializeClient(ServletContext context) throws ServletException
+  {
+    try
+    {
+      URL url = null;
+      String urlParameter = context.getInitParameter("filemgr.url");
+      if (urlParameter != null)
+      {
+        // Get the file manager URL from the context parameter.
+        url = new URL(PathUtils.replaceEnvVariables(urlParameter));
+      }
+      else
+      {
+        // Try the default URL for the file manager.
+        LOGGER.log(Level.WARNING, "Unable to find a servlet context parameter "
+          + "for the file manager URL.");
+        url = new URL("http://localhost:9000");
+      }
+
+      // Attempt to connect the client to the file manager and if successful
+      // store the client as a context attribute for other objects to access.
+      XmlRpcFileManagerClient client = new XmlRpcFileManagerClient(url);
+      context.setAttribute("client", client);
+    }
+    catch (MalformedURLException e)
+    {
+      String message = "Encountered a malformed URL for the file manager.";
+      LOGGER.log(Level.SEVERE, message, e);
+      throw new ServletException(message);
+    }
+    catch (ConnectionException e)
+    {
+      String message =
+        "Client could not establish a connection to the file manager.";
+      LOGGER.log(Level.SEVERE, message, e);
+      throw new ServletException(message);
+    }
+  }
+
+
+
+  /**
+   * Initializes the file manager working directory path and stores it as a
+   * "workingDir" context attribute by retrieving a value from the servlet
+   * context.
+   * @param context the servlet context
+   * @throws ServletException if the servlet context parameter for the file
+   * manager working directory path cannot be found
+   */
+  private void initializeWorkingDir(ServletContext context)
+    throws ServletException
+  {
+    String workingDirPath = context.getInitParameter("filemgr.working.dir");
+    if (workingDirPath != null)
+    {
+      // Validate the path.
+      File workingDir = new File(PathUtils.replaceEnvVariables(workingDirPath));
+      if (workingDir.exists() && workingDir.isDirectory())
+      {
+        context.setAttribute("workingDir", workingDir);
+        LOGGER.log(Level.FINE, "The file manager's working directory has been "
+          + "set up as " + workingDir.getAbsolutePath());
+      }
+      else
+      {
+        LOGGER.log(Level.SEVERE, "Unable to locate the working directory for "
+          + "the file manager.");
+      }
+    }
+    else
+    {
+      String message = "Unable to find a servlet context parameter for the file"
+        + " manager working directory path.";
+      LOGGER.log(Level.SEVERE, message);
+      throw new ServletException(message);
+    }
+  }
+
+
+
+  /**
+   * Initializes the output configurations for various different formats and
+   * stores them in "configurations" attributes by retrieving values from the
+   * servlet context.
+   * @param context the servlet context
+   * @throws IOException if the specified file cannot be found or read
+   */
+  public void initializeConfigurations(ServletContext context)
+  {
+    Map<String, RdfConfiguration> rdfConfigurations =
+      new HashMap<String, RdfConfiguration>();
+    Map<String, RssConfiguration> rssConfigurations =
+      new HashMap<String, RssConfiguration>();
+
+    Enumeration<String> enumeration = context.getInitParameterNames();
+    while (enumeration.hasMoreElements())
+    {
+      String parameterName = enumeration.nextElement();
+      if(parameterName.startsWith("configuration"))
+      {
+        String[] values = parameterName.split("\\.");
+        if (values.length == CONFIG_PARAM_LENGTH)
+        {
+          String format = values[CONFIG_PARAM_FORMAT];
+          String name = values[CONFIG_PARAM_NAME];
+          String value = PathUtils.replaceEnvVariables(
+            context.getInitParameter(parameterName));
+
+          try
+          {
+            if ("rdf".equals(format))
+            {
+              RdfConfiguration configuration = new RdfConfiguration();
+              configuration.initialize(new File(value));
+              rdfConfigurations.put(name, configuration);
+            }
+            else if ("rss".equals(format))
+            {
+              RssConfiguration configuration = new RssConfiguration();
+              configuration.initialize(new File(value));
+              rssConfigurations.put(name, configuration);
+            }
+          }
+          catch (IOException e)
+          {
+            LOGGER.log(Level.WARNING, "The configuration '" + parameterName
+              + "'could not be initialized (value: " + value + ").", e);
+          }
+        }
+        else
+        {
+          LOGGER.log(Level.FINE,
+            "Configuration context parameter could not be parsed.");
+        }
+      }
+    }
+
+    context.setAttribute("rdfConfigurations", rdfConfigurations);
+    context.setAttribute("rssConfigurations", rssConfigurations);
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/servlets/package-info.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/servlets/package-info.java
new file mode 100644
index 0000000..c208772
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/servlets/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+*/
+
+/**
+ * Contains servlets for the JAX-RS service.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+package org.apache.oodt.cas.product.jaxrs.servlets;
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/DatasetRdfWriter.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/DatasetRdfWriter.java
new file mode 100644
index 0000000..f60747a
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/DatasetRdfWriter.java
@@ -0,0 +1,152 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.writers;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.oodt.cas.product.jaxrs.configurations.RdfConfiguration;
+import org.apache.oodt.cas.product.jaxrs.exceptions.InternalServerErrorException;
+import org.apache.oodt.cas.product.jaxrs.resources.DatasetResource;
+import org.apache.oodt.cas.product.jaxrs.resources.MetadataResource;
+import org.apache.oodt.cas.product.jaxrs.resources.MetadataResource.MetadataEntry;
+import org.apache.oodt.cas.product.jaxrs.resources.ProductResource;
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * A {@link Provider} that writes {@link DatasetResource dataset resources} to
+ * output streams for HTTP responses with "application/rdf+xml" content-type.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@Provider
+@Produces("application/rdf+xml")
+public class DatasetRdfWriter extends RdfWriter
+  implements MessageBodyWriter<DatasetResource>
+{
+  private static final Logger LOGGER = Logger.getLogger(DatasetRdfWriter.class
+    .getName());
+
+
+
+  @Override
+  public long getSize(DatasetResource resource, Class<?> type,
+    Type genericType, Annotation[] annotations, MediaType mediaType)
+  {
+    return -1;
+  }
+
+
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType)
+  {
+    return true;
+  }
+
+
+
+  @Override
+  public void writeTo(DatasetResource resource, Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType,
+    MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+      throws IOException, WebApplicationException
+  {
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    factory.setNamespaceAware(true);
+
+    RdfConfiguration configuration = getConfiguration();
+
+    try
+    {
+      Document doc = factory.newDocumentBuilder().newDocument();
+
+      Element rdf = XMLUtils.addNode(doc, doc, "rdf:RDF");
+      XMLUtils.addAttribute(doc, rdf, RDF_NAMESPACE_NAME, RDF_NAMESPACE_VALUE);
+
+      if (configuration != null)
+      {
+        Map<String, String> namespaceMap = configuration.getNamespaces();
+        for (Entry<String, String> entry : namespaceMap.entrySet())
+        {
+          XMLUtils.addAttribute(doc, rdf, "xmlns:" + entry.getKey(),
+            entry.getValue());
+        }
+      }
+      else
+      {
+        XMLUtils.addAttribute(doc, rdf, CAS_NAMESPACE_NAME,
+          CAS_NAMESPACE_VALUE);
+      }
+
+      for (ProductResource productResource : resource.getProductResources())
+      {
+        String productTypeName = productResource.getProductTypeName();
+        String productId = productResource.getProductId();
+        String productNs = configuration != null
+          ? configuration.getTypeNamespace(productTypeName)
+          : CAS_NAMESPACE_PREFIX;
+        Element productRdf = XMLUtils.addNode(doc, rdf,
+          productNs + ":" + productTypeName);
+
+        XMLUtils.addAttribute(doc, productRdf, "rdf:about",
+          getBaseUri() + "product?productId=" + productId);
+
+        if (configuration != null)
+        {
+          MetadataResource metadataResource = productResource
+            .getMetadataResource();
+          for (MetadataEntry entry : metadataResource.getMetadataEntries())
+          {
+            for (String value : entry.getValues())
+            {
+              Element metaElement = configuration.createElement(entry.getKey(),
+                value, doc);
+              productRdf.appendChild(metaElement);
+            }
+          }
+        }
+      }
+      XMLUtils.writeXmlToStream(doc, entityStream);
+    }
+    catch (ParserConfigurationException e)
+    {
+      String message = "Unable to build org.w3c.dom.Document for output.";
+      LOGGER.log(Level.WARNING, message, e);
+      throw new InternalServerErrorException(message);
+    }
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/DatasetRssWriter.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/DatasetRssWriter.java
new file mode 100644
index 0000000..a3b4889
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/DatasetRssWriter.java
@@ -0,0 +1,193 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.writers;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.product.jaxrs.configurations.RssConfiguration;
+import org.apache.oodt.cas.product.jaxrs.configurations.RssNamespace;
+import org.apache.oodt.cas.product.jaxrs.exceptions.InternalServerErrorException;
+import org.apache.oodt.cas.product.jaxrs.resources.DatasetResource;
+import org.apache.oodt.cas.product.jaxrs.resources.ProductResource;
+import org.apache.oodt.commons.util.DateConvert;
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * A {@link Provider} that writes {@link DatasetResource dataset resources} to
+ * output streams for HTTP responses with "application/rss+xml" content-type.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@Provider
+@Produces("application/rss+xml")
+public class DatasetRssWriter extends RssWriter
+  implements MessageBodyWriter<DatasetResource>
+{
+  private static final Logger LOGGER = Logger.getLogger(DatasetRssWriter.class
+    .getName());
+
+
+
+  @Override
+  public long getSize(DatasetResource resource, Class<?> type,
+    Type genericType, Annotation[] annotations, MediaType mediaType)
+  {
+    return -1;
+  }
+
+
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType)
+  {
+    return true;
+  }
+
+
+
+  @Override
+  public void writeTo(DatasetResource resource, Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType,
+    MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+      throws IOException, WebApplicationException
+  {
+    String productTypeName = resource.getName();
+    String productTypeId = resource.getId();
+    String base = getBaseUri() + "dataset";
+    String query = "?productTypeId=" + productTypeId;
+    String idLink = base + query;
+    String selfLink = base + ".rss" + query;
+    String currentDate = dateFormatter.format(new Date());
+
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    factory.setNamespaceAware(true);
+
+    RssConfiguration configuration = getConfiguration();
+
+    try
+    {
+      Document doc = factory.newDocumentBuilder().newDocument();
+      Element rss = XMLUtils.addNode(doc, doc, "rss");
+      XMLUtils.addAttribute(doc, rss, "version", "2.0");
+      XMLUtils.addAttribute(doc, rss, "xmlns:atom",
+        "http://www.w3.org/2005/Atom");
+
+      if (configuration != null)
+      {
+        // Add namespaces defined in the configuration file.
+        for (RssNamespace namespace : configuration.getNamespaceList())
+        {
+          XMLUtils.addAttribute(doc, rss, "xmlns:" + namespace.getPrefix(),
+            namespace.getUriString());
+        }
+
+        // Get channel link information, if specified in the configuration.
+        String channelLink = configuration.getChannelLink();
+        if (channelLink != null && !channelLink.equals(""))
+        {
+          Metadata channelMetadata = new Metadata();
+          channelMetadata.addMetadata("ProductType", productTypeName);
+          channelMetadata.addMetadata("ProductTypeId", productTypeId);
+          channelMetadata.addMetadata("BaseUrl", base);
+
+          idLink = PathUtils.replaceEnvVariables(channelLink, channelMetadata);
+        }
+      }
+
+      Element channel = XMLUtils.addNode(doc, rss, "channel");
+      XMLUtils.addNode(doc, channel, "title", productTypeName);
+
+      Element atomLink = XMLUtils.addNode(doc, channel, "atom:link");
+      XMLUtils.addAttribute(doc, atomLink, "href", selfLink);
+      XMLUtils.addAttribute(doc, atomLink, "rel", "self");
+      XMLUtils.addAttribute(doc, atomLink, "type", "application/rss+xml");
+
+      XMLUtils.addNode(doc, channel, "link", idLink);
+      XMLUtils.addNode(doc, channel, "description", productTypeName);
+
+      XMLUtils.addNode(doc, channel, "language", LANGUAGE);
+      XMLUtils.addNode(doc, channel, "copyright", COPYRIGHT);
+      XMLUtils.addNode(doc, channel, "pubDate", currentDate);
+      XMLUtils.addNode(doc, channel, "category", productTypeName);
+      XMLUtils.addNode(doc, channel, "generator", GENERATOR);
+      XMLUtils.addNode(doc, channel, "lastBuildDate", currentDate);
+
+      for (ProductResource productResource : resource.getProductResources())
+      {
+        String productLink = getBaseUri() + "product?productId="
+          + productResource.getProductId();
+        Element item = XMLUtils.addNode(doc, channel, "item");
+        XMLUtils.addNode(doc, item, "title", productResource.getProductName());
+        XMLUtils.addNode(doc, item, "link", productLink);
+        XMLUtils.addNode(doc, item, "description", productResource
+          .getProductTypeName());
+        XMLUtils.addNode(doc, item, "guid", productLink);
+
+        Metadata metadata = productResource.getMetadataResource().getMetadata();
+        Date productReceivedTime = DateConvert.isoParse(metadata
+          .getMetadata("CAS.ProductReceivedTime"));
+        if (productReceivedTime != null)
+        {
+          XMLUtils.addNode(doc, item, "pubDate", dateFormatter
+            .format(productReceivedTime));
+        }
+
+        // Append additional tags defined in the configuration file.
+        if (configuration != null)
+        {
+          configuration.appendTags(metadata, doc, item);
+        }
+      }
+
+      XMLUtils.writeXmlToStream(doc, entityStream);
+    }
+    catch (ParserConfigurationException e)
+    {
+      String message = "Unable to create RSS XML document for RSS response.";
+      LOGGER.log(Level.WARNING, message, e);
+      throw new InternalServerErrorException(message);
+    }
+    catch (ParseException e)
+    {
+      String message = "Unable to create RSS XML document for RSS response.";
+      LOGGER.log(Level.WARNING, message, e);
+      throw new InternalServerErrorException(message);
+    }
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/DatasetZipWriter.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/DatasetZipWriter.java
new file mode 100644
index 0000000..c706abc
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/DatasetZipWriter.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.writers;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.oodt.cas.product.jaxrs.resources.DatasetResource;
+
+/**
+ * A {@link Provider} that writes {@link DatasetResource dataset resources} to
+ * output streams for HTTP responses with "application/zip" content-type.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@Provider
+@Produces("application/zip")
+public class DatasetZipWriter implements MessageBodyWriter<DatasetResource>
+{
+  @Override
+  public long getSize(DatasetResource resource, Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType)
+  {
+    return -1;
+  }
+
+
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType)
+  {
+    return true;
+  }
+
+
+
+  @Override
+  public void writeTo(DatasetResource resource, Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType,
+    MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+      throws IOException, WebApplicationException
+  {
+    // Create a zip file for the dataset resource.
+    File zipFile = new DatasetZipper().createZipFile(resource);
+
+    // Add the zip file to the HTTP response entity stream.
+    httpHeaders.add("Content-Type", "application/zip");
+    httpHeaders.add("Content-Disposition",
+      "attachment; filename=\"" + zipFile.getName() + "\"");
+    FileInputStream fis = new FileInputStream(zipFile);
+    IOUtils.copy(fis, entityStream);
+    fis.close();
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/DatasetZipper.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/DatasetZipper.java
new file mode 100644
index 0000000..1066965
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/DatasetZipper.java
@@ -0,0 +1,135 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.writers;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.lingala.zip4j.core.ZipFile;
+import net.lingala.zip4j.exception.ZipException;
+import net.lingala.zip4j.model.ZipParameters;
+import net.lingala.zip4j.util.Zip4jConstants;
+
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.product.jaxrs.exceptions.InternalServerErrorException;
+import org.apache.oodt.cas.product.jaxrs.resources.DatasetResource;
+import org.apache.oodt.cas.product.jaxrs.resources.MetadataResource;
+import org.apache.oodt.cas.product.jaxrs.resources.ProductResource;
+
+/**
+ * Utility class that zips up a {@link DatasetResource}, including the dataset's
+ * products and metadata.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class DatasetZipper
+{
+  private static final Logger LOGGER = Logger.getLogger(DatasetZipper.class
+    .getName());
+
+  private ProductZipper productZipper = new ProductZipper();
+
+  /**
+   * Creates a zip archive of the supplied {@link DatasetResource dataset
+   * resource} including all of the dataset's products and metadata.
+   * @param resource the dataset resource to archive
+   * @return the file reference for the zip archive of the dataset resource
+   */
+  public File createZipFile(DatasetResource resource)
+  {
+    try
+    {
+      // Create the working directory if it doesn't already exist.
+      File workingDir = resource.getWorkingDir();
+      if (!workingDir.exists() && !workingDir.mkdirs())
+      {
+        String message = "Unable to create the working directory ("
+          + workingDir.getAbsolutePath() + ") to build the zip file.";
+        LOGGER.log(Level.FINE, message);
+        throw new IOException(message);
+      }
+
+      // Try to remove a previously created zip file with the same name.
+      File file = new File(workingDir.getCanonicalPath() + "/"
+        + resource.getName() + ".zip");
+      if (file.exists() && !file.delete())
+      {
+        String message = "Unable to delete an existing zip file ("
+          + file.getAbsolutePath()
+          + ") before creating a new zip file with the same name.";
+        LOGGER.log(Level.FINE, message);
+        throw new IOException(message);
+      }
+
+      // Set up the zip file for the dataset.
+      ZipFile zipFile = new ZipFile(file);
+      ZipParameters parameters = new ZipParameters();
+      parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
+      parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
+
+      // Create zip archives for each product and add them to the dataset zip.
+      for (ProductResource productResource : resource.getProductResources())
+      {
+        File refFile = productZipper.createZipFile(productResource);
+        zipFile.addFile(refFile, parameters);
+        if (refFile.exists() && !refFile.delete())
+        {
+          String message = "Unable to delete a temporary product zip ("
+            + refFile.getAbsolutePath()
+            + ") after adding it to the dataset zip.";
+          LOGGER.log(Level.FINE, message);
+          throw new IOException(message);
+        }
+      }
+
+      // Add the dataset's metadata to the zip.
+      MetadataResource metadataResource = resource.getMetadataResource();
+      Metadata metadata = metadataResource.getMetadata();
+
+      ByteArrayOutputStream os = new ByteArrayOutputStream();
+      SerializableMetadata serMetadata = new SerializableMetadata(metadata);
+      serMetadata.writeMetadataToXmlStream(os);
+      ByteArrayInputStream bis = new ByteArrayInputStream(os.toByteArray());
+
+      parameters.setFileNameInZip(resource.getName() + ".met");
+      parameters.setSourceExternalStream(true);
+      zipFile.addStream(bis, parameters);
+
+      return file;
+    }
+
+    catch (ZipException e)
+    {
+      String message = "Unable to create a zip archive of the dataset.";
+      LOGGER.log(Level.FINE, message, e);
+      throw new InternalServerErrorException(message + " " + e.getMessage());
+    }
+    catch (IOException e)
+    {
+      String message = "Encountered I/O problems while trying to create a zip "
+        + "archive of the dataset.";
+      LOGGER.log(Level.FINE, message, e);
+      throw new InternalServerErrorException(message + " " + e.getMessage());
+    }
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ProductRssWriter.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ProductRssWriter.java
new file mode 100644
index 0000000..fffebe2
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ProductRssWriter.java
@@ -0,0 +1,149 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.writers;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.oodt.cas.product.jaxrs.exceptions.InternalServerErrorException;
+import org.apache.oodt.cas.product.jaxrs.resources.ProductResource;
+import org.apache.oodt.cas.product.jaxrs.resources.ReferenceResource;
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * A {@link Provider} that writes {@link ProductResource product resources} to
+ * output streams for HTTP responses with "application/rss+xml" content-type.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@Provider
+@Produces("application/rss+xml")
+public class ProductRssWriter extends RssWriter
+  implements MessageBodyWriter<ProductResource>
+{
+  private static final Logger LOGGER = Logger.getLogger(ProductRssWriter.class
+    .getName());
+
+
+
+  @Override
+  public long getSize(ProductResource resource, Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType)
+  {
+    return -1;
+  }
+
+
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType)
+  {
+    return true;
+  }
+
+
+
+  @Override
+  public void writeTo(ProductResource resource, Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType,
+    MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+    throws IOException, WebApplicationException
+  {
+    try
+    {
+      String productName = resource.getProductName();
+      String productId = resource.getProductId();
+      String productTypeName = resource.getProductTypeName();
+
+      String base = getBaseUri() + "product";
+      String query = "?productId=" + productId;
+      String idLink = base + query;
+      String selfLink = base + ".rss" + query;
+      String currentDate = dateFormatter.format(new Date());
+
+      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+      factory.setNamespaceAware(true);
+      Document doc = factory.newDocumentBuilder().newDocument();
+      Element rss = XMLUtils.addNode(doc, doc, "rss");
+      XMLUtils.addAttribute(doc, rss, "version", "2.0");
+      XMLUtils.addAttribute(doc, rss, "xmlns:atom",
+        "http://www.w3.org/2005/Atom");
+
+      Element channel = XMLUtils.addNode(doc, rss, "channel");
+      XMLUtils.addNode(doc, channel, "title", productName);
+
+      Element atomLink = XMLUtils.addNode(doc, channel, "atom:link");
+      XMLUtils.addAttribute(doc, atomLink, "href", selfLink);
+      XMLUtils.addAttribute(doc, atomLink, "rel", "self");
+      XMLUtils.addAttribute(doc, atomLink, "type", "application/rss+xml");
+
+      XMLUtils.addNode(doc, channel, "link", idLink);
+      XMLUtils.addNode(doc, channel, "description", productTypeName);
+
+      XMLUtils.addNode(doc, channel, "language", LANGUAGE);
+      XMLUtils.addNode(doc, channel, "copyright", COPYRIGHT);
+      XMLUtils.addNode(doc, channel, "pubDate", currentDate);
+      XMLUtils.addNode(doc, channel, "category", productTypeName);
+      XMLUtils.addNode(doc, channel, "generator", GENERATOR);
+      XMLUtils.addNode(doc, channel, "lastBuildDate", currentDate);
+
+      for (ReferenceResource referenceResource : resource
+        .getReferenceResources())
+      {
+        int refIndex = referenceResource.getRefIndex();
+        String referenceBase = getBaseUri() + "reference";
+        String referenceQuery = "?productId=" + productId + "&refIndex="
+          + refIndex;
+        String referenceLink = referenceBase + ".file" + referenceQuery;
+        String referenceIdLink = referenceBase + referenceQuery;
+
+        Element item = XMLUtils.addNode(doc, channel, "item");
+        XMLUtils.addNode(doc, item, "title", "reference (" + refIndex + ")");
+        XMLUtils.addNode(doc, item, "link", referenceLink);
+        XMLUtils.addNode(doc, item, "description",
+          "A file manager reference entity");
+        XMLUtils.addNode(doc, item, "guid", referenceIdLink);
+      }
+
+      XMLUtils.writeXmlToStream(doc, entityStream);
+    }
+    catch (ParserConfigurationException e)
+    {
+      String message = "Unable to create RSS XML document for RSS response.";
+      LOGGER.log(Level.WARNING, message, e);
+      throw new InternalServerErrorException(message);
+    }
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ProductZipWriter.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ProductZipWriter.java
new file mode 100644
index 0000000..9bff0ef
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ProductZipWriter.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.writers;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.oodt.cas.product.jaxrs.resources.ProductResource;
+
+/**
+ * A {@link Provider} that writes {@link ProductResource product resources} to
+ * output streams for HTTP responses with "application/zip" content-type.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@Provider
+@Produces("application/zip")
+public class ProductZipWriter implements MessageBodyWriter<ProductResource>
+{
+  @Override
+  public long getSize(ProductResource resource, Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType)
+  {
+    return -1;
+  }
+
+
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType)
+  {
+    return true;
+  }
+
+
+
+  @Override
+  public void writeTo(ProductResource resource, Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType,
+    MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+      throws IOException, WebApplicationException
+  {
+    // Create a zip file for the product resource.
+    File zipFile = new ProductZipper().createZipFile(resource);
+
+    // Add the zip file to the HTTP response entity stream.
+    httpHeaders.add("Content-Type", "application/zip");
+    httpHeaders.add("Content-Disposition",
+      "attachment; filename=\"" + zipFile.getName() + "\"");
+    FileInputStream fis = new FileInputStream(zipFile);
+    IOUtils.copy(fis, entityStream);
+    fis.close();
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ProductZipper.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ProductZipper.java
new file mode 100644
index 0000000..ea40388
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ProductZipper.java
@@ -0,0 +1,150 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.writers;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.lingala.zip4j.core.ZipFile;
+import net.lingala.zip4j.exception.ZipException;
+import net.lingala.zip4j.model.ZipParameters;
+import net.lingala.zip4j.util.Zip4jConstants;
+
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.SerializableMetadata;
+import org.apache.oodt.cas.product.jaxrs.exceptions.InternalServerErrorException;
+import org.apache.oodt.cas.product.jaxrs.exceptions.NotFoundException;
+import org.apache.oodt.cas.product.jaxrs.resources.MetadataResource;
+import org.apache.oodt.cas.product.jaxrs.resources.ProductResource;
+
+/**
+ * Utility class that zips up a {@link ProductResource}, including the product's
+ * references and metadata.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class ProductZipper
+{
+  private static final Logger LOGGER = Logger.getLogger(ProductZipper.class
+    .getName());
+
+  /**
+   * Creates a zip archive of the supplied {@link ProductResource product
+   * resource} including all of the product's references and metadata.
+   * @param resource the product resource to archive
+   * @return the file reference for the zip archive of the product resource
+   */
+  public File createZipFile(ProductResource resource)
+  {
+    try
+    {
+      // Create the working directory if it doesn't already exist.
+      File workingDir = resource.getWorkingDir();
+      if (!workingDir.exists() && !workingDir.mkdirs())
+      {
+        String message = "Unable to create the working directory ("
+          + workingDir.getAbsolutePath() + ") to build the zip file.";
+        LOGGER.log(Level.FINE, message);
+        throw new IOException(message);
+      }
+
+      // Try to remove previously created zip files that have the same name.
+      File file = new File(workingDir.getCanonicalPath() + "/"
+        + resource.getProductName() + ".zip");
+      if (file.exists() && !file.delete())
+      {
+        String message = "Unable to delete an existing zip file ("
+          + file.getAbsolutePath()
+          + ") before creating a new zip file with the same name.";
+        LOGGER.log(Level.FINE, message);
+        throw new IOException(message);
+      }
+
+      // Set up the zip file.
+      ZipFile zipFile = new ZipFile(file);
+      ZipParameters parameters = new ZipParameters();
+      parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
+      parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
+
+      // Add all of the product's references to the zip file.
+      // Assumes that for hierarchical products, the first reference is the root
+      // directory and all of its contents are included in the product.
+      List<Reference> references = resource.getProductReferences();
+      Reference rootReference = references.get(0);
+      File rootFile = new File(new URI(rootReference.getDataStoreReference()));
+      if (rootFile.isDirectory())
+      {
+        // Add the directory and all of its contents.
+        zipFile.addFolder(rootFile, parameters);
+      }
+      else
+      {
+        // Add each file in the list of references.
+        for (Reference reference : references)
+        {
+          zipFile.addFile(new File(new URI(reference.getDataStoreReference())),
+            parameters);
+        }
+      }
+
+      // Add the product's metadata to the zip file.
+      MetadataResource metadataResource = resource.getMetadataResource();
+      Metadata metadata = metadataResource.getMetadata();
+
+      ByteArrayOutputStream os = new ByteArrayOutputStream();
+      SerializableMetadata serMetadata = new SerializableMetadata(metadata);
+      serMetadata.writeMetadataToXmlStream(os);
+      ByteArrayInputStream bis = new ByteArrayInputStream(os.toByteArray());
+
+      parameters.setFileNameInZip(resource.getProductName() + ".met");
+      parameters.setSourceExternalStream(true);
+      zipFile.addStream(bis, parameters);
+
+      return file;
+    }
+
+    catch (URISyntaxException e)
+    {
+      String message =
+        "Problem with the data store URI(s) for the product's reference(s).";
+      LOGGER.log(Level.FINE, message, e);
+      throw new NotFoundException(message + " " + e.getMessage());
+    }
+    catch (ZipException e)
+    {
+      String message = "Unable to create a zip archive of the product.";
+      LOGGER.log(Level.FINE, message, e);
+      throw new InternalServerErrorException(message + " " + e.getMessage());
+    }
+    catch (IOException e)
+    {
+      String message = "Encountered I/O problems while trying to create a zip "
+        + "archive of the product.";
+      LOGGER.log(Level.FINE, message, e);
+      throw new InternalServerErrorException(message + " " + e.getMessage());
+    }
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/RdfWriter.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/RdfWriter.java
new file mode 100644
index 0000000..40818c4
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/RdfWriter.java
@@ -0,0 +1,72 @@
+package org.apache.oodt.cas.product.jaxrs.writers;
+
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.oodt.cas.product.jaxrs.configurations.RdfConfiguration;
+
+/**
+ * Class with shared properties and behavior for RDF writers.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class RdfWriter
+{
+  // The RDF namespace.
+  protected static final String RDF_NAMESPACE_NAME = "xmlns:rdf";
+  protected static final String RDF_NAMESPACE_VALUE =
+    "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+
+  // The CAS namespace - used as a default if no configuration is specified.
+  protected static final String CAS_NAMESPACE_PREFIX = "cas";
+  protected static final String CAS_NAMESPACE_NAME = "xmlns:"
+    + CAS_NAMESPACE_PREFIX;
+  protected static final String CAS_NAMESPACE_VALUE =
+    "http://oodt.apache.org/ns/cas";
+
+  @Context
+  private ServletContext context;
+
+  @Context
+  private UriInfo uriInfo;
+
+
+
+  /**
+   * Gets the HTTP servlet request URL up to the final '/' as a {@link String}.
+   * @return the HTTP servlet request URL up to the final '/' as a String
+   */
+  public String getBaseUri()
+  {
+    String baseUri = uriInfo.getBaseUri().toString();
+    return baseUri += baseUri.endsWith("/") ? "" : "/";
+  }
+
+
+
+  /**
+   * Gets a configuration object from the servlet context, or null if not found.
+   * @return a configuration object or null if nothing was found
+   */
+  public RdfConfiguration getConfiguration()
+  {
+    String name = uriInfo.getQueryParameters().getFirst("configuration");
+
+    if (name != null && !name.trim().equals(""))
+    {
+      Map<String, RdfConfiguration> map =
+        (Map<String, RdfConfiguration>) context
+          .getAttribute("rdfConfigurations");
+
+      if (map != null)
+      {
+        return map.get(name);
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ReferenceFileWriter.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ReferenceFileWriter.java
new file mode 100644
index 0000000..97a46eb
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ReferenceFileWriter.java
@@ -0,0 +1,124 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.writers;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.oodt.cas.product.jaxrs.exceptions.BadRequestException;
+import org.apache.oodt.cas.product.jaxrs.exceptions.NotFoundException;
+import org.apache.oodt.cas.product.jaxrs.resources.ReferenceResource;
+import org.apache.tika.Tika;
+import org.apache.tika.mime.MimeType;
+
+/**
+ * A {@link Provider} that writes {@link ReferenceResource reference resources}
+ * to output streams for HTTP responses with different file content-types.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@Provider
+@Produces("application/octet-stream")
+public class ReferenceFileWriter implements MessageBodyWriter<ReferenceResource>
+{
+  private static final Logger LOGGER = Logger.getLogger(ReferenceFileWriter
+    .class.getName());
+
+
+
+  @Override
+  public long getSize(ReferenceResource resource, Class<?> type,
+    Type genericType, Annotation[] annotations, MediaType mediaType)
+  {
+    return -1;
+  }
+
+
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType)
+  {
+    return true;
+  }
+
+
+
+  @Override
+  public void writeTo(ReferenceResource resource, Class<?> type,
+    Type genericType, Annotation[] annotations, MediaType mediaType,
+    MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+      throws IOException, WebApplicationException
+  {
+    String contentType;
+    String dataStoreReference = resource.getDataStoreReference();
+    MimeType mimeType = resource.getMimeType();
+    if (mimeType != null &&
+        mimeType.getName() != null &&
+       !mimeType.getName().equals(""))
+    {
+      contentType = mimeType.getName();
+    }
+    else
+    {
+      contentType = new Tika().detect(dataStoreReference);
+    }
+
+    try
+    {
+      File file = new File(new URI(dataStoreReference));
+      if (!file.exists() || file.isDirectory())
+      {
+        String message =
+          "Could not locate the reference source file(s) in the data store.";
+        LOGGER.log(Level.FINE, message);
+        throw new BadRequestException(message);
+      }
+
+      httpHeaders.add("Content-Type", contentType);
+      httpHeaders.add("Content-Disposition",
+        "attachment; filename=\"" + file.getName() + "\"");
+      FileInputStream fis = new FileInputStream(file);
+      IOUtils.copy(fis, entityStream);
+      fis.close();
+    }
+    catch (URISyntaxException e)
+    {
+      String message =
+        "Problem with the data store URI for the reference source file(s).";
+      LOGGER.log(Level.FINE, message, e);
+      throw new NotFoundException(message + " " + e.getMessage());
+    }
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ReferenceRssWriter.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ReferenceRssWriter.java
new file mode 100644
index 0000000..b1012a8
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ReferenceRssWriter.java
@@ -0,0 +1,139 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.writers;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.oodt.cas.product.jaxrs.exceptions.InternalServerErrorException;
+import org.apache.oodt.cas.product.jaxrs.resources.ReferenceResource;
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * A {@link Provider} that writes {@link ReferenceResource reference resources}
+ * to output streams for HTTP responses with "application/rss+xml" content-type.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@Provider
+@Produces("application/rss+xml")
+public class ReferenceRssWriter extends RssWriter
+  implements MessageBodyWriter<ReferenceResource>
+{
+  private static final Logger LOGGER = Logger.getLogger(ReferenceRssWriter.class
+    .getName());
+
+
+
+  @Override
+  public long getSize(ReferenceResource resource, Class<?> type,
+    Type genericType, Annotation[] annotations, MediaType mediaType)
+  {
+    return -1;
+  }
+
+
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType)
+  {
+    return true;
+  }
+
+
+
+  @Override
+  public void writeTo(ReferenceResource resource, Class<?> type,
+    Type genericType, Annotation[] annotations, MediaType mediaType,
+    MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+      throws IOException, WebApplicationException
+  {
+    try
+    {
+      String productId = resource.getProductId();
+      int refIndex = resource.getRefIndex();
+
+      String base = getBaseUri() + "reference";
+      String query = "?productId=" + productId + "&refIndex=" + refIndex;
+      String idLink = base + query;
+      String fileLink = base + ".file" + query;
+      String selfLink = base + ".rss" + query;
+      String currentDate = dateFormatter.format(new Date());
+
+      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+      factory.setNamespaceAware(true);
+      Document doc = factory.newDocumentBuilder().newDocument();
+      Element rss = XMLUtils.addNode(doc, doc, "rss");
+      XMLUtils.addAttribute(doc, rss, "version", "2.0");
+      XMLUtils.addAttribute(doc, rss, "xmlns:atom",
+        "http://www.w3.org/2005/Atom");
+
+      Element channel = XMLUtils.addNode(doc, rss, "channel");
+      XMLUtils.addNode(doc, channel, "title", "Reference(" + refIndex +
+        ") from Product " + productId);
+
+      Element atomLink = XMLUtils.addNode(doc, channel, "atom:link");
+      XMLUtils.addAttribute(doc, atomLink, "href", selfLink);
+      XMLUtils.addAttribute(doc, atomLink, "rel", "self");
+      XMLUtils.addAttribute(doc, atomLink, "type", "application/rss+xml");
+
+      XMLUtils.addNode(doc, channel, "link", idLink);
+      XMLUtils.addNode(doc, channel, "description", "reference");
+
+      XMLUtils.addNode(doc, channel, "language", LANGUAGE);
+      XMLUtils.addNode(doc, channel, "copyright", COPYRIGHT);
+      XMLUtils.addNode(doc, channel, "pubDate", currentDate);
+      XMLUtils.addNode(doc, channel, "category", "Reference");
+      XMLUtils.addNode(doc, channel, "generator", GENERATOR);
+      XMLUtils.addNode(doc, channel, "lastBuildDate", currentDate);
+
+      Element item = XMLUtils.addNode(doc, channel, "item");
+      XMLUtils.addNode(doc, item, "title", "reference (" + refIndex +
+        ") for product " + productId);
+      XMLUtils.addNode(doc, item, "link", fileLink);
+      XMLUtils.addNode(doc, item, "description",
+        "A file manager reference entity");
+      XMLUtils.addNode(doc, item, "guid", idLink);
+
+      XMLUtils.writeXmlToStream(doc, entityStream);
+    }
+    catch (ParserConfigurationException e)
+    {
+      String message = "Unable to create RSS XML document for RSS response.";
+      LOGGER.log(Level.WARNING, message, e);
+      throw new InternalServerErrorException(message);
+    }
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ReferenceZipWriter.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ReferenceZipWriter.java
new file mode 100644
index 0000000..f1c0bd3
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/ReferenceZipWriter.java
@@ -0,0 +1,152 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.writers;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import net.lingala.zip4j.core.ZipFile;
+import net.lingala.zip4j.exception.ZipException;
+import net.lingala.zip4j.model.ZipParameters;
+import net.lingala.zip4j.util.Zip4jConstants;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.product.jaxrs.exceptions.BadRequestException;
+import org.apache.oodt.cas.product.jaxrs.exceptions.InternalServerErrorException;
+import org.apache.oodt.cas.product.jaxrs.exceptions.NotFoundException;
+import org.apache.oodt.cas.product.jaxrs.resources.ReferenceResource;
+
+/**
+ * A {@link Provider} that writes {@link ReferenceResource reference resources}
+ * to output streams for HTTP responses with "application/zip" content-type.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@Provider
+@Produces("application/zip")
+public class ReferenceZipWriter implements MessageBodyWriter<ReferenceResource>
+{
+  private static final Logger LOGGER = Logger.getLogger(ReferenceZipWriter.class
+    .getName());
+
+
+
+  @Override
+  public long getSize(ReferenceResource resource, Class<?> type,
+    Type genericType, Annotation[] annotations, MediaType mediaType)
+  {
+    return -1;
+  }
+
+
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType)
+  {
+    return true;
+  }
+
+
+
+  @Override
+  public void writeTo(ReferenceResource resource, Class<?> type,
+    Type genericType, Annotation[] annotations, MediaType mediaType,
+    MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+      throws IOException, WebApplicationException
+  {
+    // Create the working directory if it doesn't already exist.
+    File workingDir = resource.getWorkingDir();
+    if (!workingDir.exists() && !workingDir.mkdirs())
+    {
+      String message = "Unable to create the working directory ("
+        + workingDir.getAbsolutePath() + ") to build the zip file.";
+      LOGGER.log(Level.FINE, message);
+      throw new InternalServerErrorException(message);
+    }
+
+    try
+    {
+      // Retrieve the reference file.
+      Reference reference = resource.getReference();
+      File refFile = new File(new URI(reference.getDataStoreReference()));
+      if (!refFile.exists())
+      {
+        throw new BadRequestException("Unable to locate the source file for the"
+          + " reference.");
+      }
+
+      // Try to remove previously created zip files that have the same name.
+      String workingDirPath = workingDir.getCanonicalPath();
+      workingDirPath += workingDirPath.endsWith("/") ? "" : "/";
+      File file = new File(workingDirPath + refFile.getName() + ".zip");
+      if (file.exists() && !file.delete())
+      {
+        String message = "Unable to delete an existing zip file ("
+          + file.getAbsolutePath()
+          + ") before creating a new zip file with the same name.";
+        LOGGER.log(Level.FINE, message);
+        throw new InternalServerErrorException(message);
+      }
+
+      // Add the reference file to the zip file.
+      ZipFile zipFile = new ZipFile(file);
+      ZipParameters parameters = new ZipParameters();
+      parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
+      parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
+      zipFile.addFile(refFile, parameters);
+
+      httpHeaders.add("Content-Type", "application/zip");
+      httpHeaders.add("Content-Disposition",
+        "attachment; filename=\"" + file.getName() + "\"");
+      FileInputStream fis = new FileInputStream(file);
+      IOUtils.copy(fis, entityStream);
+      fis.close();
+    }
+    catch (URISyntaxException e)
+    {
+      String message =
+        "Problem with the data store URI for the reference source file(s).";
+      LOGGER.log(Level.FINE, message, e);
+      throw new NotFoundException(message + " " + e.getMessage());
+    }
+    catch (ZipException e)
+    {
+      String message =
+        "Unable to create a zip archive of the reference source file(s).";
+      LOGGER.log(Level.FINE, message, e);
+      throw new InternalServerErrorException(message + " " + e.getMessage());
+    }
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/RssWriter.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/RssWriter.java
new file mode 100644
index 0000000..b59317f
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/RssWriter.java
@@ -0,0 +1,70 @@
+package org.apache.oodt.cas.product.jaxrs.writers;
+
+import java.text.SimpleDateFormat;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.oodt.cas.product.jaxrs.configurations.RssConfiguration;
+
+/**
+ * Class with shared properties and behavior for RSS writers.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public abstract class RssWriter
+{
+  // Constants used by RSS writers.
+  protected static final String COPYRIGHT =
+    "Copyright 2013: Apache Software Foundation";
+  protected static final String LANGUAGE = "en-us";
+  protected static final String GENERATOR = "CAS File Manager";
+  protected static final String DATE_FORMAT = "E, dd MMM yyyy HH:mm:ss Z";
+  protected static final SimpleDateFormat dateFormatter = new SimpleDateFormat(
+    DATE_FORMAT);
+
+  @Context
+  private ServletContext context;
+
+  @Context
+  private UriInfo uriInfo;
+
+
+
+  /**
+   * Gets the HTTP servlet request URL up to the final '/' as a {@link String}.
+   * @return the HTTP servlet request URL up to the final '/' as a String
+   */
+  public String getBaseUri()
+  {
+    String baseUri = uriInfo.getBaseUri().toString();
+    return baseUri += baseUri.endsWith("/") ? "" : "/";
+  }
+
+
+
+  /**
+   * Gets a configuration object from the servlet context, or null if not found.
+   * @return a configuration object or null if nothing was found
+   */
+  public RssConfiguration getConfiguration()
+  {
+    String name = uriInfo.getQueryParameters().getFirst("configuration");
+
+    if (name != null && !name.trim().equals(""))
+    {
+      Map<String, RssConfiguration> map =
+        (Map<String, RssConfiguration>) context
+          .getAttribute("rssConfigurations");
+
+      if (map != null)
+      {
+        return map.get(name);
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/TransfersRssWriter.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/TransfersRssWriter.java
new file mode 100644
index 0000000..840ddee
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/TransfersRssWriter.java
@@ -0,0 +1,159 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.writers;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.oodt.cas.product.jaxrs.exceptions.InternalServerErrorException;
+import org.apache.oodt.cas.product.jaxrs.resources.TransferResource;
+import org.apache.oodt.cas.product.jaxrs.resources.TransfersResource;
+import org.apache.oodt.commons.util.DateConvert;
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * A {@link Provider} that writes {@link TransfersResource transfers resources}
+ * to output streams for HTTP responses with "application/rss+xml" content-type.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+@Provider
+@Produces("application/rss+xml")
+public class TransfersRssWriter extends RssWriter
+  implements MessageBodyWriter<TransfersResource>
+{
+  private static final Logger LOGGER = Logger.getLogger(TransfersRssWriter.class
+    .getName());
+
+
+
+  @Override
+  public long getSize(TransfersResource resource, Class<?> type,
+    Type genericType, Annotation[] annotations, MediaType mediaType)
+  {
+    return -1;
+  }
+
+
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType,
+    Annotation[] annotations, MediaType mediaType)
+  {
+    return true;
+  }
+
+
+
+  @Override
+  public void writeTo(TransfersResource resource, Class<?> type,
+    Type genericType, Annotation[] annotations, MediaType mediaType,
+    MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+      throws IOException, WebApplicationException
+  {
+    try
+    {
+      String base = getBaseUri() + "transfers";
+      String query = "?productId=" + resource.getProductId();
+      String idLink = base + query;
+      String selfLink = base + ".rss" + query;
+      String currentDate = dateFormatter.format(new Date());
+
+      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+      factory.setNamespaceAware(true);
+      Document doc = factory.newDocumentBuilder().newDocument();
+      Element rss = XMLUtils.addNode(doc, doc, "rss");
+      XMLUtils.addAttribute(doc, rss, "version", "2.0");
+      XMLUtils.addAttribute(doc, rss, "xmlns:atom",
+        "http://www.w3.org/2005/Atom");
+
+      Element channel = XMLUtils.addNode(doc, rss, "channel");
+      XMLUtils.addNode(doc, channel, "title", "File Manager Transfers");
+
+      Element atomLink = XMLUtils.addNode(doc, channel, "atom:link");
+      XMLUtils.addAttribute(doc, atomLink, "href", selfLink);
+      XMLUtils.addAttribute(doc, atomLink, "rel", "self");
+      XMLUtils.addAttribute(doc, atomLink, "type", "application/rss+xml");
+
+      XMLUtils.addNode(doc, channel, "link", idLink);
+      XMLUtils.addNode(doc, channel, "description",
+        "Files currently being transferred to the file manager repository.");
+
+      XMLUtils.addNode(doc, channel, "language", LANGUAGE);
+      XMLUtils.addNode(doc, channel, "copyright", COPYRIGHT);
+      XMLUtils.addNode(doc, channel, "pubDate", currentDate);
+      XMLUtils.addNode(doc, channel, "category", "data transfer");
+      XMLUtils.addNode(doc, channel, "generator", GENERATOR);
+      XMLUtils.addNode(doc, channel, "lastBuildDate", currentDate);
+
+      for (TransferResource transferResource : resource.getTransferResources())
+      {
+        String dataStoreRef = transferResource.getDataStoreReference();
+        String transferLink = getBaseUri() + "transfer?dataStoreRef="
+          + dataStoreRef;
+        Element item = XMLUtils.addNode(doc, channel, "item");
+        XMLUtils.addNode(doc, item, "title", dataStoreRef);
+        XMLUtils.addNode(doc, item, "link", transferLink);
+        XMLUtils.addNode(doc, item, "description",
+            "MIME Type: " + transferResource.getMimeTypeName()
+          + ", Product: " + transferResource.getProductName()
+          + ", Product Type: " + transferResource.getProductTypeName());
+        XMLUtils.addNode(doc, item, "guid", transferLink);
+
+        Date productReceivedTime = DateConvert.isoParse(transferResource
+          .getProductReceivedTime());
+        if (productReceivedTime != null)
+        {
+          XMLUtils.addNode(doc, item, "pubDate", dateFormatter
+            .format(productReceivedTime));
+        }
+      }
+
+      XMLUtils.writeXmlToStream(doc, entityStream);
+    }
+    catch (ParserConfigurationException e)
+    {
+      String message = "Unable to create RSS XML document for RSS response.";
+      LOGGER.log(Level.WARNING, message, e);
+      throw new InternalServerErrorException(message);
+    }
+    catch (ParseException e)
+    {
+      String message = "Unable to create RSS XML document for RSS response.";
+      LOGGER.log(Level.WARNING, message, e);
+      throw new InternalServerErrorException(message);
+    }
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/package-info.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/package-info.java
new file mode 100644
index 0000000..ca5fc73
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/jaxrs/writers/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+*/
+
+/**
+ * Contains classes that implement javax.ws.rs.ext.MessageBodyWriter to provide
+ * marshalling of JAX-RS resources into different formats.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+package org.apache.oodt.cas.product.jaxrs.writers;
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/ProductTypeFilter.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/ProductTypeFilter.java
new file mode 100644
index 0000000..aaeab6a
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/ProductTypeFilter.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rdf;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JDK imports
+import java.util.Properties;
+
+/**
+ * 
+ * Filters a {@link ProductType}, based on a set of constraints.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ProductTypeFilter {
+
+  private Properties constraints;
+
+  public ProductTypeFilter() {
+    this(null);
+  }
+
+  public ProductTypeFilter(String filter) {
+    this.constraints = new Properties();
+    if (filter != null)
+      this.parse(filter);
+  }
+
+  public void parse(String filter) {
+    if(filter == null) return;
+    String[] attrConstrs = filter.split(",");
+    for (String attrConstr : attrConstrs) {
+      String[] attrConstPair = attrConstr.split("\\:");
+      this.constraints.put(attrConstPair[0], attrConstPair[1]);
+    }
+  }
+
+  public boolean filter(ProductType type) {
+    if(this.constraints == null) return true;
+    if (type.getTypeMetadata() != null) {
+      Metadata typeMet = type.getTypeMetadata();
+      for (Object constraintObj : this.constraints.keySet()) {
+        String constraintName = (String) constraintObj;
+        String constraintValue = this.constraints.getProperty(constraintName);
+        if (!typeMet.containsKey(constraintName)) {
+          return false;
+        }
+
+        if (!typeMet.getMetadata(constraintName).equals(constraintValue)) {
+          return false;
+        }
+
+      }
+
+      return true;
+    } else {
+      return false;
+    }
+
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFConfig.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFConfig.java
new file mode 100644
index 0000000..37b5705
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFConfig.java
@@ -0,0 +1,201 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rdf;
+
+//JDK imports
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 
+ * The RDF REST-ful web service configuration for the CAS product service layer.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class RDFConfig {
+
+  private Map<String, String> nsMap;
+
+  private Map<String, String> rewriteMap;
+
+  private Map<String, String> resLinkMap;
+
+  private Map<String, String> keyNsMap;
+
+  private Map<String, String> typesNsMap;
+
+  private String defaultKeyNs;
+
+  private String defaultTypeNs;
+
+  /**
+   * Default constructor.
+   */
+  public RDFConfig() {
+    this.nsMap = new HashMap<String, String>();
+    this.rewriteMap = new HashMap<String, String>();
+    this.resLinkMap = new HashMap<String, String>();
+    this.keyNsMap = new HashMap<String, String>();
+    this.typesNsMap = new HashMap<String, String>();
+    this.defaultKeyNs = null;
+    this.defaultTypeNs = null;
+  }
+
+  /**
+   * @return the nsMap
+   */
+  public Map<String, String> getNsMap() {
+    return nsMap;
+  }
+
+  /**
+   * @param nsMap
+   *          the nsMap to set
+   */
+  public void setNsMap(Map<String, String> nsMap) {
+    this.nsMap = nsMap;
+  }
+
+  /**
+   * @return the rewriteMap
+   */
+  public Map<String, String> getRewriteMap() {
+    return rewriteMap;
+  }
+
+  /**
+   * @param rewriteMap
+   *          the rewriteMap to set
+   */
+  public void setRewriteMap(Map<String, String> rewriteMap) {
+    this.rewriteMap = rewriteMap;
+  }
+
+  /**
+   * @return the resLinkMap
+   */
+  public Map<String, String> getResLinkMap() {
+    return resLinkMap;
+  }
+
+  /**
+   * @param resLinkMap
+   *          the resLinkMap to set
+   */
+  public void setResLinkMap(Map<String, String> resLinkMap) {
+    this.resLinkMap = resLinkMap;
+  }
+
+  /**
+   * @return the keyNsMap
+   */
+  public Map<String, String> getKeyNsMap() {
+    return keyNsMap;
+  }
+
+  /**
+   * @param keyNsMap
+   *          the keyNsMap to set
+   */
+  public void setKeyNsMap(Map<String, String> keyNsMap) {
+    this.keyNsMap = keyNsMap;
+  }
+
+  /**
+   * @return the defaultKeyNs
+   */
+  public String getDefaultKeyNs() {
+    return defaultKeyNs;
+  }
+
+  /**
+   * @param defaultKeyNs
+   *          the defaultKeyNs to set
+   */
+  public void setDefaultKeyNs(String defaultKeyNs) {
+    this.defaultKeyNs = defaultKeyNs;
+  }
+
+  /**
+   * @return the defaultTypeNs
+   */
+  public String getDefaultTypeNs() {
+    return defaultTypeNs;
+  }
+
+  /**
+   * @param defaultTypeNs
+   *          the defaultTypeNs to set
+   */
+  public void setDefaultTypeNs(String defaultTypeNs) {
+    this.defaultTypeNs = defaultTypeNs;
+  }
+
+  /**
+   * @return the typesNsMap
+   */
+  public Map<String, String> getTypesNsMap() {
+    return typesNsMap;
+  }
+
+  /**
+   * @param typesNsMap
+   *          the typesNsMap to set
+   */
+  public void setTypesNsMap(Map<String, String> typesNsMap) {
+    this.typesNsMap = typesNsMap;
+  }
+
+  /**
+   * Convenience method. First checks to see if there is a declared key
+   * namespace for this key, otherwise returns {@link #getDefaultKeyNs()}
+   * 
+   * @param key
+   *          The key to find the namespace for.
+   * @return Either the key's declared namespace, or {@link #getDefaultKeyNs()}.
+   */
+  public String getKeyNs(String key) {
+    if (this.keyNsMap != null && this.keyNsMap.containsKey(key)) {
+      return this.keyNsMap.get(key);
+    } else
+      return this.getDefaultKeyNs();
+  }
+
+  /**
+   * Convenience method. First checks to see if there is a declared type
+   * namespace for this {@link ProductType}, otherwise, returns
+   * {@link #getDefaultTypeNs()}.
+   * 
+   * @param type
+   *          The {@link ProductType#getName()} to find the namespace for.
+   * @return Either the type's declared namespace, or
+   *         {@link #getDefaultTypeNs()}.
+   */
+  public String getTypeNs(String type) {
+    if (this.typesNsMap != null && this.typesNsMap.containsKey(type)) {
+      return this.typesNsMap.get(type);
+    } else
+      return this.getDefaultTypeNs();
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFConfigMetKeys.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFConfigMetKeys.java
new file mode 100644
index 0000000..f9f3784
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFConfigMetKeys.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rdf;
+
+/**
+ *
+ * Met keys for the {@link RDFConfig}.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public interface RDFConfigMetKeys {
+  
+  public static final String RDF_CONTEXT_CONF_KEY = "filemgr.rdfconf.file";
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFConfigReader.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFConfigReader.java
new file mode 100644
index 0000000..efeece2
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFConfigReader.java
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rdf;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+import static org.apache.oodt.cas.product.rdf.RDFConfigReaderMetKeys.*;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * 
+ * Reader class for {@link RDFConfig}s from {@link File}s.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class RDFConfigReader {
+
+  /**
+   * Reads an {@link RDFConfig} from a {@link File}.
+   * 
+   * @param file
+   *          The {@link File} representation of the {@link RDFConfig}.
+   * @return An {@link RDFConfig} initialized with the information read from the
+   *         given {@link File}.
+   * @throws FileNotFoundException
+   *           If the {@link File} is not found.
+   */
+  public static RDFConfig readConfig(File file) throws FileNotFoundException {
+    RDFConfig conf = new RDFConfig();
+
+    Document doc = XMLUtils.getDocumentRoot(new FileInputStream(file));
+    Element rootElem = doc.getDocumentElement();
+
+    readNamespaces(rootElem, conf);
+    readRewriteRules(rootElem, conf);
+    readResourceLinks(rootElem, conf);
+    readKeyNsMap(rootElem, conf);
+    readTypesNsMap(rootElem, conf);
+
+    return conf;
+  }
+
+  protected static void readNamespaces(Element root, RDFConfig conf) {
+    Element namespacesRoot = XMLUtils.getFirstElement(NS_OUTER_TAG, root);
+    NodeList nsList = namespacesRoot.getElementsByTagName(NS_TAG);
+    if (nsList != null && nsList.getLength() > 0) {
+      for (int i = 0; i < nsList.getLength(); i++) {
+        Element nsElem = (Element) nsList.item(i);
+        conf.getNsMap().put(nsElem.getAttribute(NS_NAME_ATTR),
+            nsElem.getAttribute(NS_VALUE_ATTR));
+      }
+    }
+  }
+
+  protected static void readRewriteRules(Element root, RDFConfig conf) {
+    Element rewriteRoot = XMLUtils.getFirstElement(REWRITE_OUTER_TAG, root);
+    NodeList rewriteList = rewriteRoot.getElementsByTagName(REWRITE_KEY_TAG);
+    if (rewriteList != null && rewriteList.getLength() > 0) {
+      for (int i = 0; i < rewriteList.getLength(); i++) {
+        Element rewriteKeyElem = (Element) rewriteList.item(i);
+        conf.getRewriteMap().put(
+            rewriteKeyElem.getAttribute(REWRITE_FROM_ATTR),
+            rewriteKeyElem.getAttribute(REWRITE_TO_ATTR));
+      }
+    }
+  }
+
+  protected static void readResourceLinks(Element root, RDFConfig conf) {
+    Element resLinkRoot = XMLUtils.getFirstElement(RESOURCE_LINK_TAG, root);
+    NodeList linkList = resLinkRoot.getElementsByTagName(RESLINK_KEY_TAG);
+    if (linkList != null && linkList.getLength() > 0) {
+      for (int i = 0; i < linkList.getLength(); i++) {
+        Element reslinkKeyElem = (Element) linkList.item(i);
+        conf.getResLinkMap().put(
+            reslinkKeyElem.getAttribute(RESLINK_KEY_TAG_NAME_ATTR),
+            reslinkKeyElem.getAttribute(RESLINK_KEY_TAG_LINK_ATTR));
+      }
+    }
+  }
+
+  protected static void readKeyNsMap(Element root, RDFConfig conf) {
+    Element keyNsRoot = XMLUtils.getFirstElement(KEY_NSMAP_TAG, root);
+    conf.setDefaultKeyNs(keyNsRoot.getAttribute(KEY_NSMAP_DEFAULT_ATTR));
+    NodeList keyNsList = keyNsRoot.getElementsByTagName(KEY_NSMAP_KEY_TAG);
+    if (keyNsList != null && keyNsList.getLength() > 0) {
+      for (int i = 0; i < keyNsList.getLength(); i++) {
+        Element keyNsElem = (Element) keyNsList.item(i);
+        conf.getKeyNsMap().put(
+            keyNsElem.getAttribute(KEY_NSMAP_KEY_TAG_NAME_ATTR),
+            keyNsElem.getAttribute(KEY_NSMAP_KEY_TAG_NS_ATTR));
+      }
+    }
+  }
+
+  protected static void readTypesNsMap(Element root, RDFConfig conf) {
+    Element typeNsRoot = XMLUtils.getFirstElement(TYPE_NSMAP_TAG, root);
+    conf.setDefaultTypeNs(typeNsRoot.getAttribute(TYPE_NSMAP_DEFAULT_ATTR));
+    NodeList typeNsList = typeNsRoot.getElementsByTagName(TYPE_NSMAP_TYPE_TAG);
+    if (typeNsList != null && typeNsList.getLength() > 0) {
+      for (int i = 0; i < typeNsList.getLength(); i++) {
+        Element typeNsElem = (Element) typeNsList.item(i);
+        conf.getTypesNsMap().put(
+            typeNsElem.getAttribute(TYPE_NSMAP_TYPE_NAME_ATTR),
+            typeNsElem.getAttribute(TYPE_NSMAP_TYPE_NS_ATTR));
+      }
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFConfigReaderMetKeys.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFConfigReaderMetKeys.java
new file mode 100644
index 0000000..2a88023
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFConfigReaderMetKeys.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rdf;
+
+/**
+ * 
+ * Met keys for the {@link RDFConfigReader}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface RDFConfigReaderMetKeys {
+
+  public static final String NS_OUTER_TAG = "namespaces";
+
+  public static final String NS_TAG = "ns";
+
+  public static final String NS_NAME_ATTR = "name";
+
+  public static final String NS_VALUE_ATTR = "value";
+
+  public static final String REWRITE_OUTER_TAG = "rewrite";
+
+  public static final String REWRITE_KEY_TAG = "key";
+
+  public static final String REWRITE_FROM_ATTR = "from";
+
+  public static final String REWRITE_TO_ATTR = "to";
+
+  public static final String RESOURCE_LINK_TAG = "resourcelinks";
+
+  public static final String RESLINK_KEY_TAG = "key";
+
+  public static final String RESLINK_KEY_TAG_NAME_ATTR = "name";
+
+  public static final String RESLINK_KEY_TAG_LINK_ATTR = "link";
+
+  public static final String KEY_NSMAP_TAG = "keynsmap";
+
+  public static final String KEY_NSMAP_DEFAULT_ATTR = "default";
+
+  public static final String KEY_NSMAP_KEY_TAG = "key";
+
+  public static final String KEY_NSMAP_KEY_TAG_NAME_ATTR = "name";
+
+  public static final String KEY_NSMAP_KEY_TAG_NS_ATTR = "ns";
+
+  public static final String TYPE_NSMAP_TAG = "typesnsmap";
+
+  public static final String TYPE_NSMAP_DEFAULT_ATTR = "default";
+
+  public static final String TYPE_NSMAP_TYPE_TAG = "type";
+
+  public static final String TYPE_NSMAP_TYPE_NAME_ATTR = "name";
+
+  public static final String TYPE_NSMAP_TYPE_NS_ATTR = "ns";
+  
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFDatasetServlet.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFDatasetServlet.java
new file mode 100644
index 0000000..b44e124
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFDatasetServlet.java
@@ -0,0 +1,278 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rdf;
+
+//JDK imports
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.util.List;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.WordUtils;
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+/**
+ * 
+ * A Servlet that exports ProductType metaata information using the <a
+ * href="http://www.w3.org">W3C's</a> <a href="http://www.w3.org/RDF/"> Resource
+ * Description Framework</a>.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * 
+ */
+public class RDFDatasetServlet extends HttpServlet {
+
+  /* serial Version UID */
+  private static final long serialVersionUID = -3660991271642533985L;
+
+  /* our client to the file manager */
+  private static XmlRpcFileManagerClient fClient = null;
+
+  /* our log stream */
+  private Logger LOG = Logger.getLogger(RDFProductServlet.class.getName());
+
+  /* our RDF configuration */
+  private RDFConfig rdfConf;
+
+  /**
+   * <p>
+   * Default Constructor
+   * </p>
+   * .
+   */
+  public RDFDatasetServlet() {
+  }
+
+  /**
+   * Initializes the servlet.
+   */
+  public void init(ServletConfig config) throws ServletException {
+    super.init(config);
+    try {
+      this.rdfConf = RDFUtils.initRDF(config);
+    } catch (FileNotFoundException e) {
+      e.printStackTrace();
+      throw new ServletException(e.getMessage());
+    }
+
+    String fileManagerUrl = null;
+    try {
+      fileManagerUrl = PathUtils.replaceEnvVariables(config.getServletContext().getInitParameter(
+          "filemgr.url") );
+    } catch (Exception e) {
+      throw new ServletException("Failed to get filemgr url : " + e.getMessage(), e);
+    }    
+    
+    if (fileManagerUrl == null) {
+      // try the default port
+      fileManagerUrl = "http://localhost:9000";
+    }
+
+    fClient = null;
+
+    try {
+      fClient = new XmlRpcFileManagerClient(new URL(fileManagerUrl));
+    } catch (MalformedURLException e) {
+      LOG.log(Level.SEVERE,
+          "Unable to initialize file manager url in RDF Servlet: [url="
+              + fileManagerUrl + "], Message: " + e.getMessage());
+    } catch (ConnectionException e) {
+      LOG.log(Level.SEVERE,
+          "Unable to initialize file manager url in RDF Servlet: [url="
+              + fileManagerUrl + "], Message: " + e.getMessage());
+    }
+
+  }
+
+  public void doGet(HttpServletRequest req, HttpServletResponse resp)
+      throws ServletException, java.io.IOException {
+    doIt(req, resp);
+  }
+
+  public void doPost(HttpServletRequest req, HttpServletResponse resp)
+      throws ServletException, java.io.IOException {
+    doIt(req, resp);
+  }
+
+  public void doIt(HttpServletRequest req, HttpServletResponse resp)
+      throws ServletException, java.io.IOException {
+
+    // need to know the type of product to get products for
+    String productTypeName = req.getParameter("type");
+    String productTypeId = req.getParameter("typeID");
+    ProductTypeFilter filter = new ProductTypeFilter(req.getParameter("filter"));
+    ProductType type = null;
+
+    List<ProductType> productTypes = new Vector<ProductType>();
+
+    if (productTypeName.equals("ALL")) {
+      productTypes = safeGetProductTypes();
+    } else {
+
+      try {
+        type = fClient.getProductTypeById(productTypeId);
+        productTypes.add(type);
+      } catch (RepositoryManagerException e) {
+        LOG.log(Level.SEVERE,
+            "Unable to obtain product type from product type id: ["
+                + productTypeId + "]: Message: " + e.getMessage());
+        return;
+      }
+    }
+
+    String requestUrl = req.getRequestURL().toString();
+    String origBase = requestUrl.substring(0, requestUrl.lastIndexOf('/'));
+    String base = origBase.substring(0, origBase.lastIndexOf('/')) + "/dataset";
+
+    // allow override through the "baseUrl" GET parameter
+    if (req.getParameter("baseUrl") != null) {
+      base = req.getParameter("baseUrl");
+    }
+    
+    if (productTypes != null && productTypes.size() > 0) {
+      List<ProductType> subsetList = new Vector<ProductType>();
+      
+      // perform filtering
+      for(ProductType pt: productTypes){
+        if(filter.filter(pt)){
+          subsetList.add(pt);
+        }
+      }
+      
+      outputRDF(subsetList, base, resp);
+    }
+
+  }
+
+  public void outputRDF(List<ProductType> productTypes, String base, HttpServletResponse resp)
+      throws ServletException {
+
+    try {
+      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+      factory.setNamespaceAware(true);
+      Document doc = factory.newDocumentBuilder().newDocument();
+
+      Element rdf = XMLUtils.addNode(doc, doc, "rdf:RDF");
+      RDFUtils.addNamespaces(doc, rdf, this.rdfConf);
+
+      for (Iterator<ProductType> i = productTypes.iterator(); i.hasNext();) {
+        ProductType type = i.next();
+        
+        Element productTypeRdfDesc = XMLUtils.addNode(doc, rdf, this.rdfConf
+            .getTypeNs(type.getName())
+            + ":" + type.getName());
+        XMLUtils.addAttribute(doc, productTypeRdfDesc, "rdf:about", base
+            + "?typeID=" + type.getProductTypeId());
+
+        // for all of its metadata keys and values, loop through them
+        // and add RDF nodes underneath the RdfDesc for this product
+
+        if (type.getTypeMetadata() != null) {
+          for (Iterator<String> j = type.getTypeMetadata().getHashtable().keySet()
+              .iterator(); j.hasNext();) {
+            String key = (String) j.next();
+
+            List<String> vals = type.getTypeMetadata().getAllMetadata(key);
+
+            if (vals != null && vals.size() > 0) {
+
+              for (Iterator<String> k = vals.iterator(); k.hasNext();) {
+                String val = (String) k.next();
+                //OODT-665 fix, take keys like 
+                //PRODUCT Experiment Type
+                //and transform it into ProductExperimentType
+                String outputKey = key;
+                if (outputKey.indexOf(" ") != -1) {
+                  outputKey = StringUtils.join(WordUtils.capitalizeFully(outputKey).split(
+                      " "));
+                }
+                
+                val = StringEscapeUtils.escapeXml(val);
+                Element rdfElem = RDFUtils.getRDFElement(outputKey, val,
+                    this.rdfConf, doc);
+                productTypeRdfDesc.appendChild(rdfElem);
+              }
+
+            }
+          }
+        }
+
+      }
+
+      DOMSource source = new DOMSource(doc);
+      TransformerFactory transFactory = TransformerFactory.newInstance();
+      Transformer transformer = transFactory.newTransformer();
+      transformer.setOutputProperty("indent", "yes");
+      StreamResult result = new StreamResult(resp.getOutputStream());
+      resp.setContentType("text/xml");
+      transformer.transform(source, result);
+
+    } catch (ParserConfigurationException e) {
+      throw new ServletException(e);
+    } catch (TransformerException e) {
+      throw new ServletException(e);
+    } catch (IOException e) {
+      throw new ServletException(e);
+    }
+  }
+
+  private List<ProductType> safeGetProductTypes() {
+    List<ProductType> types = null;
+
+    try {
+      types = fClient.getProductTypes();
+    } catch (RepositoryManagerException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Error retrieving product types: Message: "
+          + e.getMessage());
+    }
+
+    return types;
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFProductServlet.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFProductServlet.java
new file mode 100644
index 0000000..66ed12a
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFProductServlet.java
@@ -0,0 +1,350 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rdf;
+
+//JDK imports
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.util.List;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.WordUtils;
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductPage;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+/**
+ * 
+ * A Servlet that exports Product metaata information using the <a
+ * href="http://www.w3.org">W3C's</a> <a href="http://www.w3.org/RDF/"> Resource
+ * Description Framework</a>.
+ * 
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * 
+ */
+public class RDFProductServlet extends HttpServlet {
+
+  /* serial Version UID */
+  private static final long serialVersionUID = -3660991271646533985L;
+
+  /* our client to the file manager */
+  private static XmlRpcFileManagerClient fClient = null;
+
+  /* our log stream */
+  private Logger LOG = Logger.getLogger(RDFProductServlet.class.getName());
+
+  /* our RDF configuration */
+  private RDFConfig rdfConf;
+
+  /**
+   * <p>
+   * Default Constructor
+   * </p>
+   * .
+   */
+  public RDFProductServlet() {
+  }
+
+  /**
+   * Initializes the servlet.
+   */
+  public void init(ServletConfig config) throws ServletException {
+    super.init(config);
+    try {
+      this.rdfConf = RDFUtils.initRDF(config);
+    } catch (FileNotFoundException e) {
+      e.printStackTrace();
+      throw new ServletException(e.getMessage());
+    }
+
+    String fileManagerUrl = null;
+    try {
+      fileManagerUrl = PathUtils.replaceEnvVariables(config.getServletContext().getInitParameter(
+          "filemgr.url") );
+    } catch (Exception e) {
+      throw new ServletException("Failed to get filemgr url : " + e.getMessage(), e);
+    }
+    
+    if (fileManagerUrl == null) {
+      // try the default port
+      fileManagerUrl = "http://localhost:9000";
+    }
+
+    fClient = null;
+
+    try {
+      fClient = new XmlRpcFileManagerClient(new URL(fileManagerUrl));
+    } catch (MalformedURLException e) {
+      LOG.log(Level.SEVERE,
+          "Unable to initialize file manager url in RDF Servlet: [url="
+              + fileManagerUrl + "], Message: " + e.getMessage());
+    } catch (ConnectionException e) {
+      LOG.log(Level.SEVERE,
+          "Unable to initialize file manager url in RDF Servlet: [url="
+              + fileManagerUrl + "], Message: " + e.getMessage());
+    }
+  }
+
+  public void doGet(HttpServletRequest req, HttpServletResponse resp)
+      throws ServletException, java.io.IOException {
+    doIt(req, resp);
+  }
+
+  public void doPost(HttpServletRequest req, HttpServletResponse resp)
+      throws ServletException, java.io.IOException {
+    doIt(req, resp);
+  }
+
+  public void doIt(HttpServletRequest req, HttpServletResponse resp)
+      throws ServletException, java.io.IOException {
+
+    // need to know the type of product to get products for
+    String productTypeName = req.getParameter("type");
+    String productTypeId = req.getParameter("id");
+    ProductType type = null;
+
+    List<Product> products = null;
+
+    try {
+      if (productTypeName.equals("ALL")) {
+        products = aggregatePagedProducts();
+      } else {
+
+        try {
+          type = fClient.getProductTypeById(productTypeId);
+        } catch (RepositoryManagerException e) {
+          LOG.log(Level.SEVERE,
+              "Unable to obtain product type from product type id: ["
+                  + productTypeId + "]: Message: " + e.getMessage());
+          return;
+        }
+
+        products = fClient.getProductsByProductType(type);
+      }
+
+    } catch (CatalogException e) {
+      e.printStackTrace();
+      LOG
+          .log(Level.WARNING,
+              "Exception getting products from Catalog: Message: "
+                  + e.getMessage());
+      return;
+    }
+
+    String requestUrl = req.getRequestURL().toString();
+    String base = requestUrl.substring(0, requestUrl.lastIndexOf('/'))
+        + "/data";
+
+    // allow override through the "baseUrl" GET parameter
+    if (req.getParameter("baseUrl") != null) {
+      base = req.getParameter("baseUrl");
+    }
+
+    if (products != null && products.size() > 0) {
+      outputRDF(products, type, base, resp);
+    }
+
+  }
+
+  public void outputRDF(List<Product> products, ProductType type, String base,
+      HttpServletResponse resp) throws ServletException {
+
+    try {
+      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+      factory.setNamespaceAware(true);
+      Document doc = factory.newDocumentBuilder().newDocument();
+
+      Element rdf = XMLUtils.addNode(doc, doc, "rdf:RDF");
+      RDFUtils.addNamespaces(doc, rdf, this.rdfConf);
+
+      for (Iterator<Product> i = products.iterator(); i.hasNext();) {
+        Product p = i.next();
+
+        String productTypeIdStr = p.getProductType().getProductTypeId();
+        ProductType productType = null;
+
+        if (type != null) {
+          productType = type;
+        } else {
+          try {
+            productType = fClient.getProductTypeById(productTypeIdStr);
+          } catch (RepositoryManagerException e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE,
+                "Unable to obtain product type from product type id: ["
+                    + ((Product) products.get(0)).getProductType()
+                        .getProductTypeId() + "]: Message: " + e.getMessage());
+            return;
+          }
+        }
+
+        p.setProductType(productType);
+
+        Element productRdfDesc = XMLUtils.addNode(doc, rdf, this.rdfConf
+            .getTypeNs(productType.getName())
+            + ":" + productType.getName());
+        XMLUtils.addAttribute(doc, productRdfDesc, "rdf:about", base
+            + "?productID=" + p.getProductId());
+
+        // now add all its metadata
+        Metadata prodMetadata = safeGetMetadata(p);
+
+        // for all of its metadata keys and values, loop through them
+        // and add RDF nodes underneath the RdfDesc for this product
+
+        if (prodMetadata != null) {
+          for (Iterator<String> j = prodMetadata.getHashtable().keySet()
+              .iterator(); j.hasNext();) {
+            String key = (String) j.next();
+
+            List<String> vals = prodMetadata.getAllMetadata(key);
+
+            if (vals != null && vals.size() > 0) {
+
+              for (Iterator<String> k = vals.iterator(); k.hasNext();) {
+                String val = (String) k.next();
+                String outputKey = key;
+                if (outputKey.indexOf(" ") != -1) {
+                  outputKey = StringUtils.join(WordUtils.capitalizeFully(outputKey).split(
+                      " "));
+                }                
+                
+                val = StringEscapeUtils.escapeXml(val);
+                Element rdfElem = RDFUtils.getRDFElement(outputKey, val,
+                    this.rdfConf, doc);
+                productRdfDesc.appendChild(rdfElem);
+              }
+
+            }
+          }
+        }
+
+      }
+
+      DOMSource source = new DOMSource(doc);
+      TransformerFactory transFactory = TransformerFactory.newInstance();
+      Transformer transformer = transFactory.newTransformer();
+      transformer.setOutputProperty("indent", "yes");
+      StreamResult result = new StreamResult(resp.getOutputStream());
+      resp.setContentType("text/xml");
+      transformer.transform(source, result);
+
+    } catch (ParserConfigurationException e) {
+      throw new ServletException(e);
+    } catch (TransformerException e) {
+      throw new ServletException(e);
+    } catch (IOException e) {
+      throw new ServletException(e);
+    }
+  }
+
+  private List<Product> aggregatePagedProducts() {
+    List<ProductType> types = safeGetProductTypes();
+    List<Product> products = null;
+
+    if (types != null && types.size() > 0) {
+      products = new Vector<Product>();
+      for (Iterator<ProductType> i = types.iterator(); i.hasNext();) {
+        ProductType type = i.next();
+
+        ProductPage page = null;
+
+        try {
+          page = fClient.getFirstPage(type);
+
+          if (page != null) {
+
+            while (true) {
+              products.addAll(page.getPageProducts());
+              if (!page.isLastPage()) {
+                page = fClient.getNextPage(type, page);
+              } else
+                break;
+            }
+          }
+        } catch (Exception ignore) {
+        }
+
+      }
+    }
+
+    return products;
+  }
+
+  private Metadata safeGetMetadata(Product p) {
+    Metadata met = null;
+
+    try {
+      met = fClient.getMetadata(p);
+    } catch (CatalogException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Error retrieving metadata for product: ["
+          + p.getProductId() + "]: Message: " + e.getMessage());
+    }
+
+    return met;
+  }
+
+  private List<ProductType> safeGetProductTypes() {
+    List<ProductType> types = null;
+
+    try {
+      types = fClient.getProductTypes();
+    } catch (RepositoryManagerException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Error retrieving product types: Message: "
+          + e.getMessage());
+    }
+
+    return types;
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFUtils.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFUtils.java
new file mode 100644
index 0000000..0804592
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rdf/RDFUtils.java
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rdf;
+
+//OODT imports
+import static org.apache.oodt.cas.product.rdf.RDFConfigMetKeys.RDF_CONTEXT_CONF_KEY;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JDK imports
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Iterator;
+import javax.servlet.ServletConfig;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * 
+ * Utility class to leverage the {@link RDFConfig} to determine how to display
+ * an RDF tag.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public final class RDFUtils {
+
+  private static final String RDF_RES_ATTR = "rdf:resource";
+
+  public static Element getRDFElement(String key, String val, RDFConfig conf,
+      Document doc) {
+    // first apply the rewrite rules
+    String tagName = conf.getRewriteMap().containsKey(key) ? conf
+        .getRewriteMap().get(key) : key;
+
+    // does this tag have a namespace? if not, use the default
+    String ns = conf.getKeyNs(key);
+    Element elem = null;
+    // is this a resource link?
+    if (conf.getResLinkMap().containsKey(key)) {
+      elem = doc.createElement(ns + ":" + tagName);
+      String linkBase = conf.getResLinkMap().get(key).endsWith("/") ? conf
+          .getResLinkMap().get(key) : conf.getResLinkMap().get(key) + "/";
+      elem.setAttribute(RDF_RES_ATTR, linkBase + val);
+    } else {
+      elem = doc.createElement(ns + ":" + tagName);
+      elem.appendChild(doc.createTextNode(val));
+    }
+
+    return elem;
+  }
+
+  public static void addNamespaces(Document doc, Element rdf, RDFConfig rdfConf) {
+    for (Iterator<String> i = rdfConf.getNsMap().keySet().iterator(); i
+        .hasNext();) {
+      String nsName = i.next();
+      String nsUrl = rdfConf.getNsMap().get(nsName);
+
+      XMLUtils.addAttribute(doc, rdf, "xmlns:" + nsName, nsUrl);
+    }
+  }
+  
+
+  public static RDFConfig initRDF(ServletConfig conf) throws FileNotFoundException {
+    return RDFConfigReader.readConfig(new File(PathUtils.replaceEnvVariables(conf
+        .getServletContext().getInitParameter((RDF_CONTEXT_CONF_KEY)))));
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSConfig.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSConfig.java
new file mode 100644
index 0000000..6369448
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSConfig.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rss;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * 
+ * Configures the {@link RSSProductServlet}, with the information
+ * defined in an rssconf.xml file.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class RSSConfig {
+
+  private List<RSSTag> tags;
+  private List<RSSNamespace> namespaces;
+  
+  private String channelLink;
+
+  /**
+   * Default constructor.
+   */
+  public RSSConfig() {
+    this.channelLink = null;
+    this.tags = new Vector<RSSTag>();
+    this.namespaces = new Vector<RSSNamespace>();
+  }
+
+  /**
+   * @return the tags
+   */
+  public List<RSSTag> getTags() {
+    return tags;
+  }
+
+  /**
+   * @param tags
+   *          the tags to set
+   */
+  public void setTags(List<RSSTag> tags) {
+    this.tags = tags;
+  }
+  
+  /**
+   * @return the namespaces
+   */
+  public List<RSSNamespace> getNamespaces() { 
+    return namespaces; 
+  }
+  
+  /**
+   * @param namespaces
+   *          the namespaces to set
+   */
+  public void setNamespaces(List<RSSNamespace> namespaces) { 
+    this.namespaces = namespaces; 
+  }
+
+  /**
+   * @return the channelLink
+   */
+  public String getChannelLink() {
+    return channelLink;
+  }
+
+  /**
+   * @param channelLink the channelLink to set
+   */
+  public void setChannelLink(String channelLink) {
+    this.channelLink = channelLink;
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSConfigMetKeys.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSConfigMetKeys.java
new file mode 100644
index 0000000..929d435
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSConfigMetKeys.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rss;
+
+/**
+ * 
+ * Met keys used by {@link RSSUtils} and other classes that deal with the
+ * {@link RSSConfig} object.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface RSSConfigMetKeys {
+
+  public static final String RSS_CONTEXT_CONF_KEY = "filemgr.rssconf.file";
+  public static final String RSS_TRANSFER_CONF_KEY = "filemgr.rss-transfer-conf.file";
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSConfigReader.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSConfigReader.java
new file mode 100644
index 0000000..cc4d384
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSConfigReader.java
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rss;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * 
+ * Reader class for {@link RSSConfig}s from {@link File}s.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class RSSConfigReader implements RSSConfigReaderMetKeys {
+
+  /**
+   * Reads an {@link RSSConfig} from a {@link File}.
+   * 
+   * @param file
+   *          The {@link File} representation of the {@link RSSConfig}.
+   * @return An {@link RSSConfig} initialized with the information read from the
+   *         given {@link File}.
+   * @throws FileNotFoundException
+   *           If the {@link File} is not found.
+   */
+  public static RSSConfig readConfig(File file) throws FileNotFoundException {
+    RSSConfig conf = new RSSConfig();
+
+    Document doc = XMLUtils.getDocumentRoot(new FileInputStream(file));
+    Element rootElem = doc.getDocumentElement();
+    conf.setChannelLink(rootElem.getAttribute(CHANNEL_LINK_ATTR));
+
+    readNamespaces(rootElem, conf);
+    readTags(rootElem, conf);
+    return conf;
+  }
+  
+  protected static void readNamespaces(Element root, RSSConfig conf) {
+    NodeList namespaceList = root.getElementsByTagName(NAMESPACE_TAG);
+    if (namespaceList != null && namespaceList.getLength() > 0) {
+      for (int i = 0; i < namespaceList.getLength(); i++) {
+        Element namespaceElem = (Element) namespaceList.item(i);
+        RSSNamespace namespace = new RSSNamespace();
+        namespace.setPrefix(namespaceElem.getAttribute(NAMESPACE_ATTR_PREFIX));
+        namespace.setUri(namespaceElem.getAttribute(NAMESPACE_ATTR_URI));
+        conf.getNamespaces().add(namespace);
+      }
+    }
+  }
+
+  protected static void readTags(Element root, RSSConfig conf) {
+    NodeList tagList = root.getElementsByTagName(TAG_TAG);
+    if (tagList != null && tagList.getLength() > 0) {
+      for (int i = 0; i < tagList.getLength(); i++) {
+        Element tagElem = (Element) tagList.item(i);
+        RSSTag tag = new RSSTag();
+        tag.setName(tagElem.getAttribute(TAG_ATTR_NAME));
+
+        // check to see if it has a source
+        if (tagElem.getAttributeNode(TAG_ATTR_SOURCE) != null) {
+          tag.setSource(tagElem.getAttribute(TAG_ATTR_SOURCE));
+        }
+
+        readAttrs(tagElem, tag);
+        conf.getTags().add(tag);
+      }
+    }
+  }
+
+  protected static void readAttrs(Element tagElem, RSSTag tag) {
+    NodeList attrTagList = tagElem.getElementsByTagName(ATTRIBUTE_TAG);
+
+    if (attrTagList != null && attrTagList.getLength() > 0) {
+      for (int i = 0; i < attrTagList.getLength(); i++) {
+        Element attrTag = (Element) attrTagList.item(i);
+        RSSTagAttribute attr = new RSSTagAttribute();
+        attr.setName(attrTag.getAttribute(ATTRIBUTE_ATTR_NAME));
+        attr.setValue(attrTag.getAttribute(ATTRIBUTE_ATTR_VALUE));
+        tag.getAttrs().add(attr);
+      }
+    }
+
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSConfigReaderMetKeys.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSConfigReaderMetKeys.java
new file mode 100644
index 0000000..77001c7
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSConfigReaderMetKeys.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rss;
+
+/**
+ * 
+ * Met keys used by the {@link RSSConfigReader}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface RSSConfigReaderMetKeys {
+  
+  public static final String CHANNEL_LINK_ATTR = "channelLink";
+  
+  public static final String NAMESPACE_TAG = "namespace";
+  
+  public static final String NAMESPACE_ATTR_PREFIX = "prefix";
+  
+  public static final String NAMESPACE_ATTR_URI = "uri";
+
+  public static final String TAG_TAG = "tag";
+
+  public static final String TAG_ATTR_NAME = "name";
+
+  public static final String TAG_ATTR_SOURCE = "source";
+
+  public static final String ATTRIBUTE_TAG = "attribute";
+
+  public static final String ATTRIBUTE_ATTR_NAME = "name";
+
+  public static final String ATTRIBUTE_ATTR_VALUE = "value";
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSNamespace.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSNamespace.java
new file mode 100644
index 0000000..ed0f6e5
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSNamespace.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rss;
+
+/**
+ * 
+ * RSS namespace definition to include in an RSS feed as defined by the
+ * {@link RSSProductServlet}'s {@link RSSConfig}.
+ * 
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class RSSNamespace 
+{
+  private String prefix;
+  private String uri;
+
+  /**
+   * Default constructor.
+   */
+  public RSSNamespace() { }
+
+  /**
+   * @return the prefix
+   */
+  public String getPrefix() { return prefix; }
+
+  /**
+   * @param prefix
+   *          the prefix to set
+   */
+  public void setPrefix(String prefix) { this.prefix = prefix;}
+
+  /**
+   * @return the uri
+   */
+  public String getUri() { return uri; }
+
+  /**
+   * @param uri
+   *          the uri to set
+   */
+  public void setUri(String uri) { this.uri = uri; }
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSProductServlet.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSProductServlet.java
new file mode 100644
index 0000000..bb3e6fe
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSProductServlet.java
@@ -0,0 +1,332 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rss;
+
+//JDK imports
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.text.ParseException;
+
+//OODT imports
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.util.DateConvert;
+
+/**
+ * A Servlet that supports the <a
+ * href="http://feedvalidator.org/docs/rss2.html">RSS 2.0</a> specification for
+ * delivering Product Feeds.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * 
+ */
+public class RSSProductServlet extends HttpServlet {
+
+  /* serial Version UID */
+  private static final long serialVersionUID = -465321738239885777L;
+
+  /* our client to the file manager */
+  private static XmlRpcFileManagerClient fm = null;
+
+  /* rss config */
+  private RSSConfig conf;
+
+  /* our log stream */
+  private Logger LOG = Logger.getLogger(RSSProductServlet.class.getName());
+
+  public static final String COPYRIGHT_BOILER_PLATE = "Copyright 2010: Apache Software Foundation";
+
+  public static final String RSS_FORMAT_STR = "E, dd MMM yyyy HH:mm:ss z";
+
+  public static final SimpleDateFormat dateFormatter = new SimpleDateFormat(
+      RSS_FORMAT_STR);
+
+  /**
+   * Default constructor.
+   */
+  public RSSProductServlet() {
+  }
+
+  /**
+   * Initializes the servlet.
+   */
+  public void init(ServletConfig config) throws ServletException {
+    super.init(config);
+
+    String fileManagerUrl;
+	try {
+		fileManagerUrl = PathUtils.replaceEnvVariables(config.getServletContext().getInitParameter(
+		    "filemgr.url") );
+	} catch (Exception e) {
+		throw new ServletException("Failed to get filemgr url : " + e.getMessage(), e);
+	}
+    if (fileManagerUrl == null) {
+      // try the default port
+      fileManagerUrl = "http://localhost:9000";
+    }
+
+    this.getFileManager(fileManagerUrl);
+    try {
+      this.conf = RSSUtils.initRSS(config);
+    } catch (FileNotFoundException e) {
+      throw new ServletException(e);
+    }
+  }
+
+  public void doGet(HttpServletRequest req, HttpServletResponse resp)
+      throws ServletException, java.io.IOException {
+    doIt(req, resp);
+  }
+
+  public void doPost(HttpServletRequest req, HttpServletResponse resp)
+      throws ServletException, java.io.IOException {
+    doIt(req, resp);
+  }
+
+  public void doIt(HttpServletRequest req, HttpServletResponse resp)
+      throws ServletException, java.io.IOException {
+
+    // need to know the type of product to get products for
+    String productTypeName = req.getParameter("channel");
+    String productTypeId = req.getParameter("id");
+    String topN = req.getParameter("topn");
+    ProductType type = null;
+    int top = 20;
+
+    if (topN != null) {
+      top = Integer.valueOf(topN).intValue();
+    }
+
+    String requestUrl = req.getRequestURL().toString();
+    String base = requestUrl.substring(0, requestUrl.lastIndexOf('/'));
+
+    Metadata channelMet = new Metadata();
+    channelMet.addMetadata("ProductType", productTypeName);
+    channelMet.addMetadata("ProductTypeId", productTypeId);
+    channelMet.addMetadata("TopN", String.valueOf(topN));
+    channelMet.addMetadata("BaseUrl", base);
+
+    List products = null;
+
+    try {
+      if (productTypeName.equals("ALL")) {
+        products = fm.getTopNProducts(top);
+      } else {
+
+        try {
+          type = fm.getProductTypeById(productTypeId);
+        } catch (RepositoryManagerException e) {
+          LOG.log(Level.SEVERE,
+              "Unable to obtain product type from product type id: ["
+                  + productTypeId + "]: Message: " + e.getMessage());
+          return;
+        }
+
+        products = fm.getTopNProducts(top, type);
+      }
+
+    } catch (CatalogException e) {
+      e.printStackTrace();
+      LOG
+          .log(Level.WARNING,
+              "Exception getting products from Catalog: Message: "
+                  + e.getMessage());
+      return;
+    }
+
+    if (products != null && products.size() > 0) {
+      String channelDesc = null;
+
+      if (!productTypeName.equals("ALL")) {
+        channelDesc = type.getDescription();
+      } else {
+        channelDesc = "ALL";
+      }
+
+      try {
+
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        Document doc = factory.newDocumentBuilder().newDocument();
+
+        Element rss = XMLUtils.addNode(doc, doc, "rss");
+        XMLUtils.addAttribute(doc, rss, "version", "2.0");
+        
+        // add namespace attributes from config file to rss tag
+        for (RSSNamespace namespace : this.conf.getNamespaces()) 
+        {
+          XMLUtils.addAttribute(doc, rss, "xmlns:" + namespace.getPrefix(), namespace.getUri());
+        }
+        
+        Element channel = XMLUtils.addNode(doc, rss, "channel");
+
+        XMLUtils.addNode(doc, channel, "title", productTypeName);
+        XMLUtils.addNode(doc, channel, "link", RSSUtils.getChannelLink(
+            this.conf.getChannelLink(), channelMet));
+        XMLUtils.addNode(doc, channel, "description", channelDesc);
+
+        String buildPubDate = dateFormatter.format(new Date());
+
+        XMLUtils.addNode(doc, channel, "language", "en-us");
+        XMLUtils.addNode(doc, channel, "copyright", COPYRIGHT_BOILER_PLATE);
+        XMLUtils.addNode(doc, channel, "pubDate", buildPubDate);
+        XMLUtils.addNode(doc, channel, "category", productTypeName);
+        XMLUtils.addNode(doc, channel, "generator", "CAS File Manager");
+        XMLUtils.addNode(doc, channel, "lastBuildDate", buildPubDate);
+
+        for (Iterator i = products.iterator(); i.hasNext();) {
+          Product p = (Product) i.next();
+
+          String productTypeIdStr = p.getProductType().getProductTypeId();
+          ProductType productType = null;
+
+          try {
+            productType = fm.getProductTypeById(productTypeIdStr);
+          } catch (RepositoryManagerException e) {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE,
+                "Unable to obtain product type from product type id: ["
+                    + ((Product) products.get(0)).getProductType()
+                        .getProductTypeId() + "]: Message: " + e.getMessage());
+            return;
+          }
+
+          p.setProductType(productType);
+          p.setProductReferences(safeGetProductReferences(p));
+
+          Element item = XMLUtils.addNode(doc, channel, "item");
+
+          XMLUtils.addNode(doc, item, "title", p.getProductName());
+          XMLUtils.addNode(doc, item, "description", p.getProductType()
+              .getName());
+          XMLUtils.addNode(doc, item, "link", base + "/data?productID="
+              + p.getProductId());
+
+          Metadata m = this.safeGetMetadata(p);
+          String productReceivedTime = m.getMetadata("CAS.ProductReceivedTime");
+          Date receivedTime = null;
+
+          try {
+            receivedTime = DateConvert.isoParse(productReceivedTime);
+          } catch (ParseException ignore) {
+          }
+
+          if (receivedTime != null) {
+            XMLUtils.addNode(doc, item, "pubDate", dateFormatter
+                .format(receivedTime));
+          }
+
+          // add met field for FileSize for use in RSS envelope
+          if (p.getProductReferences() != null
+              && p.getProductReferences().size() == 1) {
+            m.addMetadata("FileSize", String.valueOf(p.getProductReferences()
+                .get(0).getFileSize()));
+          }
+
+          // add additional elements from the RSSConfig
+          for (RSSTag tag : this.conf.getTags()) {
+            item.appendChild(RSSUtils.emitRSSTag(tag, m, doc, item));
+          }
+
+        }
+
+        DOMSource source = new DOMSource(doc);
+        TransformerFactory transFactory = TransformerFactory.newInstance();
+        Transformer transformer = transFactory.newTransformer();
+        transformer.setOutputProperty("indent", "yes");
+        StreamResult result = new StreamResult(resp.getOutputStream());
+        resp.setContentType("text/xml");
+        transformer.transform(source, result);
+
+      } catch (ParserConfigurationException e) {
+        throw new ServletException(e);
+      } catch (TransformerException e) {
+        throw new ServletException(e);
+      }
+
+    }
+
+  }
+
+  private Metadata safeGetMetadata(Product p) {
+    try {
+      return fm.getMetadata(p);
+    } catch (CatalogException ignore) {
+      ignore.printStackTrace();
+      return null;
+    }
+  }
+
+  private List<Reference> safeGetProductReferences(Product p) {
+    try {
+      return fm.getProductReferences(p);
+    } catch (CatalogException ignore) {
+      ignore.printStackTrace();
+      return null;
+    }
+  }
+
+  private void getFileManager(String fileManagerUrl) {
+    try {
+      this.fm = new XmlRpcFileManagerClient(new URL(fileManagerUrl));
+    } catch (MalformedURLException e) {
+      LOG.log(Level.SEVERE,
+          "Unable to initialize file manager url in RSS Servlet: [url="
+              + fileManagerUrl + "], Message: " + e.getMessage());
+    } catch (ConnectionException e) {
+      LOG.log(Level.SEVERE,
+          "Unable to initialize file manager url in RSS Servlet: [url="
+              + fileManagerUrl + "], Message: " + e.getMessage());
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSProductTransferServlet.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSProductTransferServlet.java
new file mode 100644
index 0000000..65150dd
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSProductTransferServlet.java
@@ -0,0 +1,281 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rss;
+
+//JDK imports
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.util.List;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.text.ParseException;
+
+//OODT imports
+import static org.apache.oodt.cas.product.rss.RSSConfigMetKeys.RSS_TRANSFER_CONF_KEY;
+import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.DataTransferException;
+import org.apache.oodt.cas.filemgr.structs.exceptions.ConnectionException;
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient;
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.util.DateConvert;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Servlet that supports the <a
+ * href="http://feedvalidator.org/docs/rss2.html">RSS 2.0</a> specification for
+ * delivering Product Transfer Feeds.
+ * </p>
+ * 
+ */
+public class RSSProductTransferServlet extends HttpServlet {
+
+    /* serial Version UID */
+    private static final long serialVersionUID = -7983832512818339079L;
+
+    /* our client to the file manager */
+    private static XmlRpcFileManagerClient fClient = null;
+
+    /* RSS config */
+    private RSSConfig rssconf;
+
+    /* our log stream */
+    private Logger LOG = Logger.getLogger(RSSProductTransferServlet.class
+            .getName());
+
+    public static final String COPYRIGHT_BOILER_PLATE = "Copyright 2010: Apache Software Foundation";
+
+    public static final String RSS_FORMAT_STR = "E, dd MMM yyyy HH:mm:ss z";
+
+    public static final SimpleDateFormat dateFormatter = new SimpleDateFormat(
+            RSS_FORMAT_STR);
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     */
+    public RSSProductTransferServlet() {
+    }
+
+    /**
+     * Initializes the servlet.
+     */
+    public void init(ServletConfig config) throws ServletException {
+        super.init(config);
+
+        String fileManagerUrl = null;
+        try {
+          fileManagerUrl = PathUtils.replaceEnvVariables(config.getServletContext().getInitParameter(
+              "filemgr.url") );
+        } catch (Exception e) {
+          throw new ServletException("Failed to get filemgr url : " + e.getMessage(), e);
+        }        
+        if (fileManagerUrl == null) {
+            // try the default port
+            fileManagerUrl = "http://localhost:9000";
+        }
+
+        fClient = null;
+
+        try {
+            fClient = new XmlRpcFileManagerClient(new URL(fileManagerUrl));
+        } catch (MalformedURLException e) {
+            LOG.log(Level.SEVERE,
+                    "Unable to initialize file manager url in RSS Servlet: [url="
+                            + fileManagerUrl + "], Message: " + e.getMessage());
+        } catch (ConnectionException e) {
+            LOG.log(Level.SEVERE,
+                    "Unable to initialize file manager url in RSS Servlet: [url="
+                            + fileManagerUrl + "], Message: " + e.getMessage());
+        }
+
+        try
+        {
+          rssconf = RSSConfigReader.readConfig(new File(PathUtils
+              .replaceEnvVariables(config.getServletContext().getInitParameter(
+                  (RSS_TRANSFER_CONF_KEY)))));
+        }
+        catch (FileNotFoundException e)
+        {
+          throw new ServletException(e);
+        }
+    }
+
+    public void doGet(HttpServletRequest req, HttpServletResponse resp)
+            throws ServletException, java.io.IOException {
+        doIt(req, resp);
+    }
+
+    public void doPost(HttpServletRequest req, HttpServletResponse resp)
+            throws ServletException, java.io.IOException {
+        doIt(req, resp);
+    }
+
+    public void doIt(HttpServletRequest req, HttpServletResponse resp)
+            throws ServletException, java.io.IOException {
+        List currentTransfers = null;
+
+        try {
+            currentTransfers = fClient.getCurrentFileTransfers();
+        } catch (DataTransferException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception getting current transfers from file manager: Message: "
+                            + e.getMessage());
+            return;
+        }
+
+        String requestUrl = req.getRequestURL().toString();
+        String base = requestUrl.substring(0, requestUrl.lastIndexOf('/'));
+
+        if (currentTransfers != null && currentTransfers.size() > 0) {
+            String channelDesc = "Current Files Being Transferred to the File Manager";
+
+            try {
+
+                DocumentBuilderFactory factory = DocumentBuilderFactory
+                        .newInstance();
+                factory.setNamespaceAware(true);
+                Document doc = factory.newDocumentBuilder().newDocument();
+
+                Element rss = XMLUtils.addNode(doc, doc, "rss");
+                XMLUtils.addAttribute(doc, rss, "version", "2.0");
+
+                // add namespace attributes from config file to rss tag
+                for (RSSNamespace namespace : rssconf.getNamespaces())
+                {
+                  XMLUtils.addAttribute(doc, rss,
+                      "xmlns:" + namespace.getPrefix(), namespace.getUri());
+                }
+
+                Element channel = XMLUtils.addNode(doc, rss, "channel");
+
+                XMLUtils.addNode(doc, channel, "title",
+                        "File Manager Transfers");
+                XMLUtils.addNode(doc, channel, "link", base
+                        + "/viewTransfers");
+                XMLUtils.addNode(doc, channel, "description", channelDesc);
+
+                String buildPubDate = dateFormatter.format(new Date());
+
+                XMLUtils.addNode(doc, channel, "language", "en-us");
+                XMLUtils.addNode(doc, channel, "copyright",
+                        COPYRIGHT_BOILER_PLATE);
+                XMLUtils.addNode(doc, channel, "pubDate", buildPubDate);
+                XMLUtils.addNode(doc, channel, "category", "data transfer");
+                XMLUtils.addNode(doc, channel, "generator", "CAS File Manager");
+                XMLUtils.addNode(doc, channel, "lastBuildDate", buildPubDate);
+
+                for (Iterator i = currentTransfers.iterator(); i.hasNext();) {
+                    FileTransferStatus status = (FileTransferStatus) i.next();
+
+                    Element item = XMLUtils.addNode(doc, channel, "item");
+
+                    XMLUtils.addNode(doc, item, "title", status
+                            .getParentProduct().getProductName());
+                    XMLUtils.addNode(doc, item, "description", status
+                            .getParentProduct().getProductType().getName());
+                    XMLUtils.addNode(doc, item, "link", base
+                            + "/viewTransfer?ref="
+                            + status.getFileRef().getOrigReference() + "&size="
+                            + status.getFileRef().getFileSize());
+
+                    Metadata m = null;
+
+                    try {
+                        m = fClient.getMetadata(status.getParentProduct());
+
+                        String productReceivedTime = m
+                                .getMetadata("CAS.ProductReceivedTime");
+                        Date receivedTime = null;
+
+                        try {
+                            receivedTime = DateConvert
+                                    .isoParse(productReceivedTime);
+                        } catch (ParseException ignore) {
+                        }
+
+                        if (receivedTime != null) {
+                            XMLUtils.addNode(doc, item, "pubDate",
+                                    dateFormatter.format(receivedTime));
+                        }
+
+                        // set product transfer metadata
+                        m.addMetadata("BytesTransferred",
+                          "" + status.getBytesTransferred());
+                        m.addMetadata("TotalBytes",
+                          "" + status.getFileRef().getFileSize());
+                        m.addMetadata("PercentComplete",
+                          "" + status.computePctTransferred());
+
+                    } catch (CatalogException ignore) {
+                    }
+
+                    // add additional elements from the RSSConfig
+                    for (RSSTag tag : rssconf.getTags()) {
+                      item.appendChild(RSSUtils.emitRSSTag(tag, m, doc, item));
+                    }
+
+                }
+
+                DOMSource source = new DOMSource(doc);
+                TransformerFactory transFactory = TransformerFactory
+                        .newInstance();
+                Transformer transformer = transFactory.newTransformer();
+                transformer.setOutputProperty("indent", "yes");
+                StreamResult result = new StreamResult(resp.getOutputStream());
+                resp.setContentType("text/xml");
+                transformer.transform(source, result);
+
+            } catch (ParserConfigurationException e) {
+                throw new ServletException(e);
+            } catch (TransformerException e) {
+                throw new ServletException(e);
+            }
+
+        }
+
+    }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSTag.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSTag.java
new file mode 100644
index 0000000..3515447
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSTag.java
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rss;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * 
+ * An output RSS tag to include in an RSS feed as defined by the
+ * {@link RSSProductServlet}'s {@link RSSConfig}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class RSSTag {
+
+  private String name;
+
+  private String source;
+
+  private List<RSSTagAttribute> attrs;
+
+  /**
+   * Default constructor.
+   */
+  public RSSTag() {
+    this.name = null;
+    this.source = null;
+    this.attrs = new Vector<RSSTagAttribute>();
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return the source
+   */
+  public String getSource() {
+    return source;
+  }
+
+  /**
+   * @param source
+   *          the source to set
+   */
+  public void setSource(String source) {
+    this.source = source;
+  }
+
+  /**
+   * @return the attrs
+   */
+  public List<RSSTagAttribute> getAttrs() {
+    return attrs;
+  }
+
+  /**
+   * @param attrs
+   *          the attrs to set
+   */
+  public void setAttrs(List<RSSTagAttribute> attrs) {
+    this.attrs = attrs;
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSTagAttribute.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSTagAttribute.java
new file mode 100644
index 0000000..e55a871
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSTagAttribute.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rss;
+
+/**
+ * 
+ * An attribute on an RSS output tag, generated from the
+ * CAS.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class RSSTagAttribute {
+
+  private String name;
+
+  private String value;
+
+  /**
+   * Default constructor.
+   */
+  public RSSTagAttribute() {
+    this.name = null;
+    this.value = null;
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return the value
+   */
+  public String getValue() {
+    return value;
+  }
+
+  /**
+   * @param value
+   *          the value to set
+   */
+  public void setValue(String value) {
+    this.value = value;
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSUtils.java b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSUtils.java
new file mode 100644
index 0000000..5110a41
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/java/org/apache/oodt/cas/product/rss/RSSUtils.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rss;
+
+//OODT imports
+import static org.apache.oodt.cas.product.rss.RSSConfigMetKeys.RSS_CONTEXT_CONF_KEY;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.WordUtils;
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//JDK imports
+import java.io.File;
+import java.io.FileNotFoundException;
+import javax.servlet.ServletConfig;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * 
+ * Utility functions to help out in configuring the {@link RSSProductServlet}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class RSSUtils {
+
+  public static String getChannelLink(String channelLink, Metadata channelMet) {
+    if (channelLink != null && !channelLink.equals("")) {
+      return PathUtils.replaceEnvVariables(channelLink, channelMet);
+    } else {
+      String cLink = channelMet.getMetadata("BaseUrl") + "/rdf/dataset?type="
+      + channelMet.getMetadata("ProductType") + "&typeID="
+      + channelMet.getMetadata("ProductTypeId");
+      return cLink;
+    }
+  }
+
+  public static Element emitRSSTag(RSSTag tag, Metadata prodMet, Document doc,
+      Element item) {
+    String outputTag = tag.getName();
+    if (outputTag.indexOf(" ") != -1) {
+      outputTag = StringUtils.join(WordUtils.capitalizeFully(outputTag).split(
+          " "));
+    }
+    Element rssMetElem = XMLUtils.addNode(doc, item, outputTag);
+
+    // first check if there is a source defined, if so, use that as the value
+    if (tag.getSource() != null) {
+      rssMetElem.appendChild(doc.createTextNode(StringEscapeUtils.escapeXml(PathUtils.replaceEnvVariables(
+          tag.getSource(), prodMet))));
+    }
+
+    // check if there are attributes defined, and if so, add to the attributes
+    for (RSSTagAttribute attr : tag.getAttrs()) {
+      rssMetElem.setAttribute(attr.getName(), PathUtils.replaceEnvVariables(
+          attr.getValue(), prodMet));
+    }
+
+    return rssMetElem;
+  }
+
+  public static RSSConfig initRSS(ServletConfig conf)
+      throws FileNotFoundException {
+    return RSSConfigReader.readConfig(new File(PathUtils
+        .replaceEnvVariables(conf.getServletContext().getInitParameter(
+            (RSS_CONTEXT_CONF_KEY)))));
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/resources/georss-config.xml b/0.8.1-rc1/webapp/fmprod/src/main/resources/georss-config.xml
new file mode 100644
index 0000000..1c2d473
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/resources/georss-config.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more contributor
+  license agreements.  See the NOTICE.txt 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.
+-->
+
+<!--
+  Authors: Chris A. Mattmann, Ross Laidlaw
+  Description: This file configures the CAS RSS web service. The main aspects
+  of this file are the ability to recast a product's metadata as relevant RSS
+  compatible tags.  This file contains example GeoRSS tags.
+-->
+
+<cas:rssconf xmlns:cas="http://oodt.apache.org/ns/cas">
+
+  <!--
+    An option "channelLink" attribute may be set on the above outer tag to set
+    the channel's link attribute.
+
+    Metadata available for replacement in this attribute is:
+
+    BaseUrl: the base URL for the CAS web service layer.
+    ProductTypeId: the id passed to the RSS channel via the id param
+    ProductType: the channel product type name passed via the channel param
+    TopN: the topn param, if passed.
+  -->
+
+  <!--
+    Each &lt;tag&gt; tag defines 2 attributes:
+
+    name (required) - the RSS output tag name
+    source (optional) - the field name from the CAS product's metadata and its
+    associated value.
+
+    Each &lt;tag&gt; has a set of &lt;attribute&gt; tags, which define XML
+    attributes on the RSS output tags. Each &lt;attribute&gt; has the following
+    attributes:
+
+    name (required) - the RSS output tag attribute name
+    value (required) - the RSS output tag attribute value. By default these
+    values are run through PathUtils#replaceEnvVariables which replaces met keys
+    using the standard CAS met replacement strategy.
+  -->
+
+  <!--
+    If you want to turn your CAS File Manager into a GeoRSS basic W3C (WGS84)
+    service (see http://www.w3.org/2003/01/geo), add the following block,
+    assuming that you have indexed met fields named Latitude and Longitude for
+    your product (update as appropriate otherwise).
+
+    <namespace prefix="geo" uri="http://www.w3.org/2003/01/geo/wgs84_pos#"/>
+    <tag name="geo:lat" source="[Latitude]"/>
+    <tag name="geo:long" source="[Longitude]"/>
+  -->
+
+  <!--
+    If you want to turn your CAS File Manager into a GeoRSS simple service
+    (see http://georss.org/simple), add the following block, assuming that you
+    have indexed met fields named Latitude and Longitude for your product
+    (update as appropriate otherwise).
+
+    <namespace prefix="georss" uri="http://www.georss.org/georss"/>
+    <tag name="georss:point" source="[Latitude] [Longitude]"/>
+  -->
+
+  <namespace prefix="cas" uri="http://oodt.apache.org/ns/cas"/>
+  <tag name="cas:source" source="[ProductType]"/>
+  <tag name="source" source="[ProductType]"/>
+
+</cas:rssconf>
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/resources/logging.properties b/0.8.1-rc1/webapp/fmprod/src/main/resources/logging.properties
new file mode 100644
index 0000000..5a65355
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/resources/logging.properties
@@ -0,0 +1,42 @@
+# 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.
+
+# This is an example logging properties file for use in the deployed web
+# application on an Apache Tomcat web server.
+
+# Log levels: OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL
+
+handlers = org.apache.juli.FileHandler
+
+org.apache.juli.FileHandler.level = FINE
+org.apache.juli.FileHandler.directory = ${catalina.base}/logs
+org.apache.juli.FileHandler.prefix = fmprod.
+
+# CAS-Product settings
+org.apache.oodt.cas.product.level = FINE
+
+# File manager settings
+org.apache.oodt.cas.filemgr.level = SEVERE
+
+# XMLRPC commons-httpclient transport layer settings
+org.apache.commons.httpclient.level = WARNING
+httpclient.wire.level = WARNING
+
+# Apache CXF settings
+org.apache.cxf.level = WARNING
+
+# JAXB settings
+javax.xml.bind.level = WARNING
+com.sun.xml.bind.level = WARNING
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/resources/rdfconf.xml b/0.8.1-rc1/webapp/fmprod/src/main/resources/rdfconf.xml
new file mode 100644
index 0000000..a94d6fe
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/resources/rdfconf.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more contributor
+  license agreements.  See the NOTICE.txt 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.
+
+  Author: Chris A. Mattmann
+  Description: Refactored the definition of the relevant CAS RDF web service
+  configuration parameters into this file. See tag specific documentation below
+  for information on how to use the file to configure the CAS RDF web service.
+-->
+<cas:rdfconf xmlns:cas="http://oodt.apache.org/ns/cas">
+  <!--
+    Here you can add as many &quot;ns&quot; tags as desired. Each ns should
+    include <b>both</b> a name attribute and a value attribute, where name and
+    value are the xmlns name and value,
+    e.g. xmlns:&lt;name&gt;=&quot;value&quot;
+  -->
+  <namespaces>
+    <ns name="cas" value="urn:oodt:"/>
+    <ns name="rdf" value="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
+
+    <!-- an example included from EDRN -->
+    <ns name="edrn" value="urn:edrn:"/>
+    <ns name="x" value="http://edrn.nci.nih.gov/rdf/schema.rdf#"/>
+  </namespaces>
+
+  <!--
+    Optionally specify CAS met keys to be renamed in the output RDF. Each key
+    tag must include a <b>from</b> and a <b>to</b> attribute, renaming the
+    original CAS product met key &quot;from&quot; to the new RDF output key
+    &quot;to&quot;
+  -->
+  <rewrite>
+    <key from="SiteId" to="site"/>
+    <key from="SiteName" to="site"/>
+    <key from="ProtocolId" to="protocol"/>
+    <key from="OrganId" to="organ"/>
+    <key from="OrganSite" to="organ"/>
+    <key from="ProtocolName" to="protocol"/>
+  </rewrite>
+
+  <!--
+    Placing key tags in this file declares that the source CAS product met keys
+    are in fact resource link identifiers, and should be output as such in the
+    RDF. Required parameters for each key tag are: name, identifying the source
+    CAS product met key, and link, identifying the start of the resource link to
+    be used in the rdf:resource output tag, e.g.,
+    &lt;x:protocol rdf:resource=&quot;&lt;link&gt;/&lt;key value&gt;&quot;&gt;
+  -->
+  <resourcelinks>
+    <key name="SiteId" link="http://edrn.nci.nih.gov/data/sites/"/>
+    <key name="SiteName" link="http://edrn.nci.nih.gov/data/sites/"/>
+    <key name="ProtocolId" link="http://edrn.nci.nih.gov/data/protocols/"/>
+    <key name="ProtocolName" link="http://edrn.nci.nih.gov/data/protocols/"/>
+    <key name="OrganId" link="http://edrn.nci.nih.gov/data/body-systems/"/>
+    <key name="OrganSite" link="http://edrn.nci.nih.gov/data/body-systems/"/>
+  </resourcelinks>
+
+  <!--
+    Associates CAS product metadata specific keys to previously declared
+    namespaces. Each key tag should contain a name attribute whose value is
+    valid CAS product met key, and each ns attribute on each key tag should be a
+    previously declared namespace from the namespaces tag.
+
+    You <b>must</b> declare a default ns in the default attribute in the
+    keynsmap tag. This ns will be used if no key ns is declared in the nsmap.
+  -->
+  <keynsmap default="edrn">
+    <key name="CAS.ProductId" ns="cas"/>
+    <key name="CAS.ProductName" ns="cas"/>
+    <key name="CAS.ProductReceivedTime" ns="cas"/>
+    <key name="FileLocation" ns="cas"/>
+    <key name="Filename" ns="cas"/>
+    <key name="ProductType" ns="cas"/>
+    <key name="DataVersion" ns="cas"/>
+    <key name="MimeType" ns="cas"/>
+
+    <!--  EDRN example -->
+    <key name="SiteId" ns="x"/>
+    <key name="SiteName" ns="x"/>
+    <key name="ProtocolName" ns="x"/>
+    <key name="ProtocolId" ns="x"/>
+    <key name="OrganId" ns="x"/>
+    <key name="OrganSite" ns="x"/>
+  </keynsmap>
+
+  <!--
+    Associates CAS product type names to previously declared namespaces. Each
+    type tag should contain a name attribute whose value is valid CAS product
+    type, and each ns attribute on each key tag should be a previously declared
+    namespace from the namespaces tag.
+
+    You <b>must</b> declare a default ns in the default attribute in the
+    typesnsmap tag. This ns will be used if no type ns is declared in the nsmap.
+  -->
+  <typesnsmap default="edrn">
+    <type name="GenericFile" ns="cas"/>
+  </typesnsmap>
+</cas:rdfconf>
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/resources/rss-transfer-conf.xml b/0.8.1-rc1/webapp/fmprod/src/main/resources/rss-transfer-conf.xml
new file mode 100644
index 0000000..d983ef0
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/resources/rss-transfer-conf.xml
@@ -0,0 +1,30 @@
+<?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.
+
+  Author: rlaidlaw
+  Description: This file configures the CAS RSS web service for File Manager
+  product transfers.  It allows metadata for a product being transferred to be
+  assigned to RSS compatible tags.
+-->
+<cas:rssconf xmlns:cas="http://oodt.apache.org/ns/cas">
+
+  <namespace prefix="cas" uri="http://oodt.apache.org/ns/cas"/>
+  <tag name="cas:bytesTransferred" source="[BytesTransferred]"/>
+  <tag name="cas:totalBytes" source="[TotalBytes]"/>
+  <tag name="cas:percentComplete" source="[PercentComplete]"/>
+
+</cas:rssconf>
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/resources/rssconf.xml b/0.8.1-rc1/webapp/fmprod/src/main/resources/rssconf.xml
new file mode 100644
index 0000000..bf65073
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/resources/rssconf.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more contributor
+  license agreements.  See the NOTICE.txt 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.
+
+  Author: Chris A. Mattmann
+  Description: This file configures the CAS RSS web service. The main aspects of
+  this file are the ability to recast a product's  metadata as relevant RSS
+  compatible tags.
+-->
+<cas:rssconf xmlns:cas="http://oodt.apache.org/ns/cas">
+  <!--
+    An optional "channelLink" attribute may be set on the above outer tag to
+    set the channel's link attribute.
+
+    Metadata available for replacement in this attribute is:
+
+    BaseUrl: the base URL for the CAS web service layer.
+    ProductTypeId: the id passed to the RSS channel via the id param
+    ProductType: the channel product type name passed via the channel param
+    TopN: the topn param, if passed.
+  -->
+
+  <!--
+    Each &lt;tag&gt; tag defines 2 attributes:
+
+    name (required) - the RSS output tag name
+    source (optional) - the field name from the CAS product's metadata and its
+    associated value.
+
+    Each &lt;tag&gt; has a set of &lt;attribute&gt; tags, which define XML
+    attributes on the RSS output tags. Each &lt;attribute&gt; has the following
+    attributes:
+
+    name (required) - the RSS output tag attribute name
+    value (required) - the RSS output tag attribute value. By default these
+    values are run through PathUtils#replaceEnvVariables which replaces met keys
+    using the standard CAS met replacement strategy.
+  -->
+
+  <!--
+    If you want to turn your CAS File Manager into a Podcast feeder for iTunes,
+    uncomment the tag block below. You'll need to modify your web.xml for this
+    webapp and change the default name of the /data service to /data.mp3. Then
+    you're set!
+
+    <tag name="enclosure">
+      <attribute name="url"
+        value="http://localhost:8080/fmprod/data.mp3?productID=[CAS.ProductId]"/>
+      <attribute name="length" value="[FileSize]"/>
+      <attribute name="type" value="audio/mpeg"/>
+    </tag>
+  -->
+
+  <!--
+    If you want to turn your CAS File Manager into a GeoRSS simple service (see
+    http://georss.org/simple), add the following block, assuming that you have
+    indexed met fields named Latitude and Longitude for your product (update as
+    appropriate otherwise).
+
+    <namespace prefix="georss" uri="http://www.georss.org/georss"/>
+    <tag name="georss:point" source="[Latitude] [Longitude]"/>
+  -->
+
+  <namespace prefix="cas" uri="http://oodt.apache.org/ns/cas"/>
+  <tag name="cas:source" source="[ProductType]"/>
+  <tag name="source" source="[ProductType]"/>
+
+</cas:rssconf>
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/webapp/META-INF/context.xml b/0.8.1-rc1/webapp/fmprod/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..8f37535
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+
+<Context docBase="/path/to/cas-product.war" reloadable="true"
+  crossContext="true">
+
+  <Valve className="org.apache.catalina.valves.AccessLogValve"
+    prefix="fmprod_access_log." suffix=".txt" pattern="common"/>
+
+  <Parameter name="filemgr.ns"
+    value="cas|urn:oodt:|rdf|http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    override="false"/>
+
+  <Parameter name="filemgr.ns.default"
+    value="cas" override="false"/>
+
+  <Parameter name="filemgr.url"
+    value="[FILEMGR_URL]" override="false"/>
+
+  <Parameter name="filemgr.working.dir"
+    value="[FILEMGR_WORKINGDIR]" override="false"/>
+
+  <Parameter name="filemgr.rdfconf.file"
+    value="[FMPROD_HOME]/rdfconf.xml" override="false"/>
+
+  <Parameter name="filemgr.rssconf.file"
+    value="[FMPROD_HOME]/rssconf.xml" override="false"/>
+
+  <Parameter name="filemgr.rss-transfer-conf.file"
+    value="[FMPROD_HOME]/rss-transfer-conf.xml" override="false"/>
+
+  <Parameter name="configuration.rdf.example"
+    value="[FMPROD_HOME]/rdfconf.xml" override="false"/>
+
+  <Parameter name="configuration.rss.example"
+    value="[FMPROD_HOME]/rssconf.xml" override="false"/>
+
+  <Parameter name="configuration.rss.georss"
+    value="[FMPROD_HOME]/georss-config.xml" override="false"/>
+
+  <Parameter name="configuration.rss.transfer"
+    value="[FMPROD_HOME]/rss-transfer-conf.xml" override="false"/>
+</Context>
diff --git a/0.8.1-rc1/webapp/fmprod/src/main/webapp/WEB-INF/web.xml b/0.8.1-rc1/webapp/fmprod/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..155fb0d
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more contributor
+  license agreements.  See the NOTICE.txt 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.
+-->
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
+    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+  <display-name>CAS Product Server Web Application</display-name>
+
+  <servlet>
+    <servlet-name>RSSServlet</servlet-name>
+    <servlet-class>
+      org.apache.oodt.cas.product.rss.RSSProductServlet
+    </servlet-class>
+  </servlet>
+
+  <servlet>
+    <servlet-name>RSSTransferServlet</servlet-name>
+    <servlet-class>
+      org.apache.oodt.cas.product.rss.RSSProductTransferServlet
+    </servlet-class>
+  </servlet>
+
+  <servlet>
+    <servlet-name>RDFProductServlet</servlet-name>
+    <servlet-class>
+      org.apache.oodt.cas.product.rdf.RDFProductServlet
+    </servlet-class>
+  </servlet>
+
+  <servlet>
+    <servlet-name>RDFDatasetServlet</servlet-name>
+    <servlet-class>
+      org.apache.oodt.cas.product.rdf.RDFDatasetServlet
+    </servlet-class>
+  </servlet>
+
+  <servlet>
+    <servlet-name>DataDeliveryServlet</servlet-name>
+    <servlet-class>
+      org.apache.oodt.cas.product.data.DataDeliveryServlet
+    </servlet-class>
+  </servlet>
+
+  <servlet>
+    <servlet-name>DatasetDeliveryServlet</servlet-name>
+    <servlet-class>
+      org.apache.oodt.cas.product.data.DatasetDeliveryServlet
+    </servlet-class>
+  </servlet>
+
+  <servlet>
+    <servlet-name>CasProductJaxrsServlet</servlet-name>
+    <servlet-class>
+       org.apache.oodt.cas.product.jaxrs.servlets.CasProductJaxrsServlet
+    </servlet-class>
+    <init-param>
+      <param-name>jaxrs.serviceClasses</param-name>
+      <param-value>
+        org.apache.oodt.cas.product.jaxrs.services.CasProductJaxrsService
+      </param-value>
+    </init-param>
+    <init-param>
+      <param-name>jaxrs.providers</param-name>
+      <param-value>
+        org.apache.cxf.jaxrs.provider.json.JSONProvider,
+        org.apache.oodt.cas.product.jaxrs.writers.ReferenceFileWriter,
+        org.apache.oodt.cas.product.jaxrs.writers.ReferenceZipWriter,
+        org.apache.oodt.cas.product.jaxrs.writers.ReferenceRssWriter,
+        org.apache.oodt.cas.product.jaxrs.writers.ProductZipWriter,
+        org.apache.oodt.cas.product.jaxrs.writers.ProductRssWriter,
+        org.apache.oodt.cas.product.jaxrs.writers.DatasetZipWriter,
+        org.apache.oodt.cas.product.jaxrs.writers.DatasetRdfWriter,
+        org.apache.oodt.cas.product.jaxrs.writers.DatasetRssWriter,
+        org.apache.oodt.cas.product.jaxrs.writers.TransfersRssWriter
+      </param-value>
+    </init-param>
+    <init-param>
+      <param-name>jaxrs.inInterceptors</param-name>
+      <param-value>
+        org.apache.oodt.cas.product.jaxrs.filters.BackwardsCompatibleInterceptor
+      </param-value>
+    </init-param>
+    <init-param>
+      <param-name>jaxrs.scope</param-name>
+      <param-value>prototype</param-value>
+    </init-param>
+    <init-param>
+      <param-name>jaxrs.extensions</param-name>
+      <param-value>
+        file=application/octet-stream
+        json=application/json
+        rdf=application/rdf+xml
+        rss=application/rss+xml
+        xml=application/xml
+        zip=application/zip
+      </param-value>
+    </init-param>
+  </servlet>
+
+
+  <servlet-mapping>
+    <servlet-name>RSSServlet</servlet-name>
+    <url-pattern>/viewRecent</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>RSSTransferServlet</servlet-name>
+    <url-pattern>/viewTransfers</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>RDFProductServlet</servlet-name>
+    <url-pattern>/rdf</url-pattern>
+  </servlet-mapping>
+  
+  <servlet-mapping>
+      <servlet-name>RDFDatasetServlet</servlet-name>
+      <url-pattern>/rdf/dataset</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>DataDeliveryServlet</servlet-name>
+    <url-pattern>/data</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>DatasetDeliveryServlet</servlet-name>
+    <url-pattern>/dataset</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>CasProductJaxrsServlet</servlet-name>
+    <url-pattern>/jaxrs/*</url-pattern>
+  </servlet-mapping>
+</web-app>
diff --git a/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/data/TestDataUtils.java b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/data/TestDataUtils.java
new file mode 100644
index 0000000..0ae42d3
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/data/TestDataUtils.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.product.data;
+
+import java.io.File;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests DataUtils module methods
+ *
+ * @author thomas (Thomas Bennett)
+ */
+
+public class TestDataUtils extends TestCase {
+    private File workingDir;
+	@Override
+	public void tearDown() throws Exception {
+		FileUtils.forceDelete(workingDir);
+	}
+
+	public void testCreateProductZipFileFromHierarchicalProduct(){
+		//Data store reference needs absolute path to test data
+		String cwd=System.getProperty("user.dir");
+
+		Product product = new Product();
+		product.setProductId("TestProductId");
+		product.setProductName("TestProductName");
+		product.setProductReferences(Lists.newArrayList(
+			new Reference("file:///orig/data/", "file://" + cwd + "/src/test/resources/", 4096),
+			new Reference("file:///orig/data/test-file-1.txt", "file://" + cwd + "/src/test/resources/test-file-1.txt", 20),
+			new Reference("file:///orig/data/test-file-2.txt", "file://" + cwd + "/src/test/resources/test-file-2.txt", 20),
+			new Reference("file:///orig/data/test-file-3.txt", "file://" + cwd + "/src/test/resources/test-file-3.txt", 20)));
+		product.setProductStructure(Product.STRUCTURE_HIERARCHICAL);
+		product.setTransferStatus(Product.STATUS_RECEIVED);
+		ProductType pt = new ProductType();
+		pt.setName("TestProductType");
+
+		Metadata metadata = new Metadata();
+
+		String workingDirPath = null;
+		workingDir = Files.createTempDir();
+		workingDirPath = workingDir.getAbsolutePath();
+		workingDir.deleteOnExit();
+
+		String productZipFilePath = null;
+		try {
+			productZipFilePath = DataUtils.createProductZipFile(product, metadata, workingDirPath);
+		} catch (Exception e) {
+			fail(e.getMessage());
+		}
+		String zipFileName = product.getProductName() + ".zip";
+		assertEquals(productZipFilePath, workingDirPath + "/" + zipFileName);
+	}
+
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/DatasetResourceTest.java b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/DatasetResourceTest.java
new file mode 100644
index 0000000..6101f62
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/DatasetResourceTest.java
@@ -0,0 +1,206 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.resources;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.tika.mime.MimeTypeException;
+import org.apache.tika.mime.MimeTypes;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+/**
+ * Implements tests for methods in the {@link DatasetResource} class.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class DatasetResourceTest
+{
+  /**
+   * Tests that {@link DatasetResource dataset resources} are marshalled to
+   * the expected XML format.
+   * @throws IOException if the {@link Diff} constructor fails
+   * @throws JAXBException if the {@link JAXBContext} or {@link Marshaller} fail
+   * @throws MimeTypeException if {@link MimeTypes#forName(String)} fails
+   * @throws SAXException if the {@link Diff} constructor fails
+   */
+  @Test
+  public void testXmlMarshalling() throws IOException, JAXBException,
+    MimeTypeException, SAXException
+  {
+    // Create a ProductType.
+    ProductType productType = new ProductType("1", "GenericFile", "test type",
+      "repository", "versioner");
+
+    // Create a ProductResource using Reference, Metadata and Product instances.
+    Reference reference1 = new Reference("original1", "dataStore1", 500,
+      new MimeTypes().forName("text/plain"));
+    List<Reference> references1 = new ArrayList<Reference>();
+    references1.add(reference1);
+
+    Hashtable metadataEntries1 = new Hashtable<String, Object>();
+    metadataEntries1.put("product1_meta", "test1");
+    Metadata metadata1 = new Metadata();
+    metadata1.addMetadata(metadataEntries1);
+
+    Product product1 = new Product();
+    product1.setProductId("123");
+    product1.setProductName("test.txt");
+    product1.setProductType(productType);
+
+    ProductResource productResource1 = new ProductResource(product1, metadata1,
+      references1, new File("/tmp"));
+
+
+    // Create another ProductResource using Reference, Metadata and Product
+    // instances.
+    Reference reference2 = new Reference("original2", "dataStore2", 1000,
+      new MimeTypes().forName("application/pdf"));
+    List<Reference> references2 = new ArrayList<Reference>();
+    references2.add(reference2);
+
+    Hashtable metadataEntries2 = new Hashtable<String, Object>();
+    metadataEntries2.put("product2_meta", "test2");
+    Metadata metadata2 = new Metadata();
+    metadata2.addMetadata(metadataEntries2);
+
+    Product product2 = new Product();
+    product2.setProductId("456");
+    product2.setProductName("test2.txt");
+    product2.setProductType(productType);
+
+    ProductResource productResource2 = new ProductResource(product2, metadata2,
+      references2, new File("/tmp"));
+
+    // Create a DatasetResource using ProductType, Metadata and ProductResource
+    // instances.
+    Hashtable metadataEntries3 = new Hashtable<String, Object>();
+    metadataEntries3.put("dataset_meta", "test3");
+    Metadata metadata3 = new Metadata();
+    metadata3.addMetadata(metadataEntries3);
+
+    DatasetResource resource = new DatasetResource(
+      productType.getProductTypeId(), productType.getName(), metadata3,
+      new File("/tmp"));
+    resource.addProductResource(productResource1);
+    resource.addProductResource(productResource2);
+
+
+    // Generate the expected output.
+    String expectedXml =
+        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+      + "<dataset>"
+      +   "<id>" + productType.getProductTypeId() + "</id>"
+      +   "<name>" + productType.getName() + "</name>"
+      +   "<metadata>"
+      +     "<keyval>"
+      +       "<key>" + metadata3.getAllKeys().get(0) + "</key>"
+      +       "<val>" + metadata3.getAllValues().get(0) + "</val>"
+      +     "</keyval>"
+      +   "</metadata>"
+      +   "<products>"
+      +     "<product>"
+      +       "<id>" + product1.getProductId() + "</id>"
+      +       "<name>" + product1.getProductName() + "</name>"
+      +       "<type>" + productType.getName() + "</type>"
+      +       "<metadata>"
+      +         "<keyval>"
+      +           "<key>" + metadata1.getAllKeys().get(0) + "</key>"
+      +           "<val>" + metadata1.getAllValues().get(0) + "</val>"
+      +         "</keyval>"
+      +       "</metadata>"
+      +       "<references>"
+      +         "<reference>"
+      +           "<productId>" + product1.getProductId() + "</productId>"
+      +           "<refIndex>0</refIndex>"
+      +           "<dataStoreReference>"
+      +              reference1.getDataStoreReference()
+      +           "</dataStoreReference>"
+      +           "<originalReference>"
+      +              reference1.getOrigReference()
+      +           "</originalReference>"
+      +           "<mimeType>"
+      +              reference1.getMimeType().getName()
+      +           "</mimeType>"
+      +           "<fileSize>" + reference1.getFileSize() + "</fileSize>"
+      +         "</reference>"
+      +       "</references>"
+      +     "</product>"
+      +     "<product>"
+      +       "<id>" + product2.getProductId() + "</id>"
+      +       "<name>" + product2.getProductName() + "</name>"
+      +       "<type>" + productType.getName() + "</type>"
+      +       "<metadata>"
+      +         "<keyval>"
+      +           "<key>" + metadata2.getAllKeys().get(0) + "</key>"
+      +           "<val>" + metadata2.getAllValues().get(0) + "</val>"
+      +         "</keyval>"
+      +       "</metadata>"
+      +       "<references>"
+      +         "<reference>"
+      +           "<productId>" + product2.getProductId() + "</productId>"
+      +           "<refIndex>0</refIndex>"
+      +           "<dataStoreReference>"
+      +              reference2.getDataStoreReference()
+      +           "</dataStoreReference>"
+      +           "<originalReference>"
+      +              reference2.getOrigReference()
+      +           "</originalReference>"
+      +           "<mimeType>"
+      +              reference2.getMimeType().getName()
+      +           "</mimeType>"
+      +           "<fileSize>" + reference2.getFileSize() + "</fileSize>"
+      +         "</reference>"
+      +       "</references>"
+      +     "</product>"
+      +   "</products>"
+      + "</dataset>";
+
+
+    // Set up a JAXB context and marshall the DatasetResource to XML.
+    JAXBContext context = JAXBContext.newInstance(resource.getClass());
+    Marshaller marshaller = context.createMarshaller();
+    StringWriter writer = new StringWriter();
+    marshaller.marshal(resource, writer);
+
+    // Compare the expected and actual outputs.
+    XMLUnit.setIgnoreWhitespace(true);
+    XMLUnit.setIgnoreComments(true);
+    XMLUnit.setIgnoreAttributeOrder(true);
+    Diff diff = new Diff(expectedXml, writer.toString());
+    assertTrue("The output XML was different to the expected XML: "
+      + diff.toString(), diff.identical());
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/MetadataResourceTest.java b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/MetadataResourceTest.java
new file mode 100644
index 0000000..853bb3f
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/MetadataResourceTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.resources;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.apache.oodt.cas.metadata.Metadata;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.custommonkey.xmlunit.examples.RecursiveElementNameAndTextQualifier;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+/**
+ * Implements tests for methods in the {@link MetadataResource} class.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class MetadataResourceTest
+{
+  /**
+   * Tests that {@link MetadataResource metadata resources} are marshalled to
+   * the expected XML format.
+   * @throws IOException if the {@link Diff} constructor fails
+   * @throws JAXBException if the {@link JAXBContext} or {@link Marshaller} fail
+   * @throws SAXException if the {@link Diff} constructor fails
+   */
+  @Test
+  public void testXmlMarshalling() throws IOException, JAXBException,
+    SAXException
+  {
+    // Generate the expected output.
+    String expectedXml =
+      "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+      + "<metadata>"
+      + "<keyval><key>1</key><val>one</val></keyval>"
+      + "<keyval><key>2</key><val>two</val></keyval>"
+      + "<keyval><key>3</key><val>three</val></keyval>"
+      + "<keyval><key>4</key><val>a</val><val>b</val><val>c</val></keyval>"
+      + "</metadata>";
+
+    // Create a MetadataResource using a Metadata instance.
+    Hashtable metadataEntries = new Hashtable<String, Object>();
+    metadataEntries.put("1", "one");
+    metadataEntries.put("2", "two");
+    metadataEntries.put("3", "three");
+    List<String> list = new ArrayList<String>();
+    list.add("a");
+    list.add("b");
+    list.add("c");
+    metadataEntries.put("4", list);
+
+    Metadata metadata = new Metadata();
+    metadata.addMetadata(metadataEntries);
+    MetadataResource resource = new MetadataResource(metadata);
+
+
+    // Set up a JAXB context and marshall the ReferenceResource to XML.
+    JAXBContext context = JAXBContext.newInstance(resource.getClass());
+    Marshaller marshaller = context.createMarshaller();
+    StringWriter writer = new StringWriter();
+    marshaller.marshal(resource, writer);
+
+    // Compare the expected and actual outputs.
+    XMLUnit.setIgnoreWhitespace(true);
+    XMLUnit.setIgnoreComments(true);
+    XMLUnit.setIgnoreAttributeOrder(true);
+    Diff diff = new Diff(expectedXml, writer.toString());
+    diff.overrideElementQualifier(new RecursiveElementNameAndTextQualifier());
+    assertTrue("The output XML was different to the expected XML: "
+      + diff.toString(), diff.similar());
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/ProductResourceTest.java b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/ProductResourceTest.java
new file mode 100644
index 0000000..6cf9c12
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/ProductResourceTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.resources;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.tika.mime.MimeTypeException;
+import org.apache.tika.mime.MimeTypes;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+/**
+ * Implements tests for methods in the {@link ProductResource} class.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class ProductResourceTest
+{
+  /**
+   * Tests that {@link ProductResource product resources} are marshalled to
+   * the expected XML format.
+   * @throws IOException if the {@link Diff} constructor fails
+   * @throws JAXBException if the {@link JAXBContext} or {@link Marshaller} fail
+   * @throws MimeTypeException if {@link MimeTypes#forName(String)} fails
+   * @throws SAXException if the {@link Diff} constructor fails
+   */
+  @Test
+  public void testXmlMarshalling() throws IOException, JAXBException,
+    MimeTypeException, SAXException
+  {
+    // Create a ProductResource using ProductType, Reference, Metadata and
+    // Product instances.
+    Hashtable metadataEntries = new Hashtable<String, Object>();
+    metadataEntries.put("CAS.Test", "test value");
+    Metadata metadata = new Metadata();
+    metadata.addMetadata(metadataEntries);
+
+    Reference reference = new Reference("original", "dataStore", 1000,
+      new MimeTypes().forName("text/plain"));
+    List<Reference> references = new ArrayList<Reference>();
+    references.add(reference);
+
+    ProductType productType = new ProductType("1", "GenericFile", "test type",
+      "repository", "versioner");
+
+    Product product = new Product();
+    product.setProductId("123");
+    product.setProductName("test.txt");
+    product.setProductStructure(Product.STRUCTURE_FLAT);
+    product.setProductType(productType);
+
+    ProductResource resource = new ProductResource(product, metadata,
+      references, new File("/tmp"));
+
+
+    // Generate the expected output.
+    String expectedXml =
+        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+        + "<product>"
+        + "<id>" + product.getProductId() + "</id>"
+        + "<name>" + product.getProductName() + "</name>"
+        + "<structure>" + product.getProductStructure() + "</structure>"
+        + "<type>" + productType.getName() + "</type>"
+        + "<metadata>"
+        + "<keyval>"
+        + "<key>" + metadata.getAllKeys().get(0) + "</key>"
+        + "<val>" + metadata.getAllValues().get(0) + "</val>"
+        + "</keyval>"
+        + "</metadata>"
+        + "<references>"
+        + "<reference>"
+        + "<productId>" + product.getProductId() + "</productId>"
+        + "<refIndex>0</refIndex>"
+        + "<dataStoreReference>"
+        +    reference.getDataStoreReference()
+        + "</dataStoreReference>"
+        + "<originalReference>"
+        +    reference.getOrigReference()
+        + "</originalReference>"
+        + "<mimeType>" + reference.getMimeType().getName() + "</mimeType>"
+        + "<fileSize>" + reference.getFileSize() + "</fileSize>"
+        + "</reference>"
+        + "</references>"
+        + "</product>";
+
+
+    // Set up a JAXB context and marshall the ProductResource to XML.
+    JAXBContext context = JAXBContext.newInstance(resource.getClass());
+    Marshaller marshaller = context.createMarshaller();
+    StringWriter writer = new StringWriter();
+    marshaller.marshal(resource, writer);
+
+    // Compare the expected and actual outputs.
+    XMLUnit.setIgnoreWhitespace(true);
+    XMLUnit.setIgnoreComments(true);
+    XMLUnit.setIgnoreAttributeOrder(true);
+    Diff diff = new Diff(expectedXml, writer.toString());
+    assertTrue("The output XML was different to the expected XML: "
+      + diff.toString(), diff.identical());
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/ReferenceResourceTest.java b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/ReferenceResourceTest.java
new file mode 100644
index 0000000..3e27685
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/ReferenceResourceTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.resources;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.tika.mime.MimeTypeException;
+import org.apache.tika.mime.MimeTypes;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+/**
+ * Implements tests for methods in the {@link ReferenceResource} class.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class ReferenceResourceTest
+{
+  /**
+   * Tests that {@link ReferenceResource reference resources} are marshalled to
+   * the expected XML format.
+   * @throws IOException if the {@link Diff} constructor fails
+   * @throws JAXBException if the {@link JAXBContext} or {@link Marshaller} fail
+   * @throws MimeTypeException if {@link MimeTypes#forName(String)} fails
+   * @throws SAXException if the {@link Diff} constructor fails
+   */
+  @Test
+  public void testXmlMarshalling() throws IOException, JAXBException,
+    MimeTypeException, SAXException
+  {
+    String productId = "123";
+    int refIndex = 0;
+
+    // Create a new ReferenceResource using a Reference instance.
+    Reference reference = new Reference("original", "dataStore", 1000,
+      new MimeTypes().forName("text/plain"));
+
+    ReferenceResource resource = new ReferenceResource(productId, refIndex,
+      reference, new File("/tmp"));
+
+
+    // Generate the expected output.
+    String expectedXml =
+        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+      + "<reference>"
+      + "<productId>" + productId + "</productId>"
+      + "<refIndex>" + refIndex + "</refIndex>"
+      + "<dataStoreReference>"
+      +    reference.getDataStoreReference()
+      + "</dataStoreReference>"
+      + "<originalReference>"
+      +    reference.getOrigReference()
+      + "</originalReference>"
+      + "<mimeType>" + reference.getMimeType().getName() + "</mimeType>"
+      + "<fileSize>" + reference.getFileSize() +  "</fileSize>"
+      + "</reference>";
+
+
+    // Set up a JAXB context and marshall the ReferenceResource to XML.
+    JAXBContext context = JAXBContext.newInstance(resource.getClass());
+    Marshaller marshaller = context.createMarshaller();
+    StringWriter writer = new StringWriter();
+    marshaller.marshal(resource, writer);
+
+    // Compare the expected and actual outputs.
+    XMLUnit.setIgnoreWhitespace(true);
+    XMLUnit.setIgnoreComments(true);
+    XMLUnit.setIgnoreAttributeOrder(true);
+    Diff diff = new Diff(expectedXml, writer.toString());
+    assertTrue("The output XML was different to the expected XML: "
+      + diff.toString(), diff.identical());
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/TransferResourceTest.java b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/TransferResourceTest.java
new file mode 100644
index 0000000..16e89ad
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/TransferResourceTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.resources;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Hashtable;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.tika.mime.MimeTypeException;
+import org.apache.tika.mime.MimeTypes;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+/**
+ * Implements tests for methods in the {@link TransferResource} class.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class TransferResourceTest
+{
+  /**
+   * Tests that {@link TransferResource transfer resources} are marshalled to
+   * the expected XML format.
+   * @throws IOException if the {@link Diff} constructor fails
+   * @throws JAXBException if the {@link JAXBContext} or {@link Marshaller} fail
+   * @throws MimeTypeException if {@link MimeTypes#forName(String)} fails
+   * @throws SAXException if the {@link Diff} constructor fails
+   */
+  @Test
+  public void testXmlMarshalling() throws IOException, JAXBException,
+    MimeTypeException, SAXException
+  {
+    // Create a TransferResource using ProductType, Product, Metadata, Reference
+    // and FileTransferStatus instances.
+    Hashtable metadataEntries = new Hashtable<String, Object>();
+    metadataEntries.put("CAS.ProductReceivedTime", "2013-09-12T16:25:50.662Z");
+    Metadata metadata = new Metadata();
+    metadata.addMetadata(metadataEntries);
+
+    Reference reference = new Reference("original", "dataStore", 1000,
+      new MimeTypes().forName("text/plain"));
+
+    ProductType productType = new ProductType("1", "GenericFile", "test type",
+      "repository", "versioner");
+
+    Product product = new Product();
+    product.setProductId("123");
+    product.setProductName("test product");
+    product.setProductStructure(Product.STRUCTURE_FLAT);
+    product.setProductType(productType);
+
+    FileTransferStatus status = new FileTransferStatus(reference, 1000, 100,
+      product);
+
+    TransferResource resource = new TransferResource(product, metadata, status);
+
+
+    // Generate the expected output.
+    String expectedXml =
+      "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+      + "<transfer>"
+      + "<productName>" + product.getProductName() + "</productName>"
+      + "<productId>" + product.getProductId() + "</productId>"
+      + "<productTypeName>" + productType.getName() + "</productTypeName>"
+      + "<dataStoreReference>"
+      +   reference.getDataStoreReference()
+      + "</dataStoreReference>"
+      + "<origReference>"
+      +   reference.getOrigReference()
+      + "</origReference>"
+      + "<mimeType>" + reference.getMimeType().getName() + "</mimeType>"
+      + "<fileSize>" + reference.getFileSize() + "</fileSize>"
+      + "<totalBytes>" + reference.getFileSize() + "</totalBytes>"
+      + "<bytesTransferred>"
+      +    status.getBytesTransferred()
+      + "</bytesTransferred>"
+      + "<percentComplete>"
+      +    status.computePctTransferred() * 100
+      + "</percentComplete>"
+      + "<productReceivedTime>"
+      +    metadata.getAllValues().get(0)
+      + "</productReceivedTime>"
+      + "</transfer>";
+
+    // Set up a JAXB context and marshall the DatasetResource to XML.
+    JAXBContext context = JAXBContext.newInstance(resource.getClass());
+    Marshaller marshaller = context.createMarshaller();
+    StringWriter writer = new StringWriter();
+    marshaller.marshal(resource, writer);
+
+    // Compare the expected and actual outputs.
+    XMLUnit.setIgnoreWhitespace(true);
+    XMLUnit.setIgnoreComments(true);
+    XMLUnit.setIgnoreAttributeOrder(true);
+    Diff diff = new Diff(expectedXml, writer.toString());
+    assertTrue("The output XML was different to the expected XML: "
+      + diff.toString(), diff.identical());
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/TransfersResourceTest.java b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/TransfersResourceTest.java
new file mode 100644
index 0000000..e490bc6
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/jaxrs/resources/TransfersResourceTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.jaxrs.resources;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.apache.oodt.cas.filemgr.structs.FileTransferStatus;
+import org.apache.oodt.cas.filemgr.structs.Product;
+import org.apache.oodt.cas.filemgr.structs.ProductType;
+import org.apache.oodt.cas.filemgr.structs.Reference;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.tika.mime.MimeTypeException;
+import org.apache.tika.mime.MimeTypes;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+/**
+ * Implements tests for methods in the {@link TransfersResource} class.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class TransfersResourceTest
+{
+  /**
+   * Tests that {@link TransferResource transfer resources} are marshalled to
+   * the expected XML format.
+   * @throws IOException if the {@link Diff} constructor fails
+   * @throws JAXBException if the {@link JAXBContext} or {@link Marshaller} fail
+   * @throws MimeTypeException if {@link MimeTypes#forName(String)} fails
+   * @throws SAXException if the {@link Diff} constructor fails
+   */
+  @Test
+  public void testXmlMarshalling() throws IOException, JAXBException,
+    MimeTypeException, SAXException
+  {
+    // Create a FileTransferStatus instance using Metadata, Reference,
+    // ProductType and Product instances.
+    Hashtable metadataEntries1 = new Hashtable<String, Object>();
+    metadataEntries1.put("CAS.ProductReceivedTime", "2013-09-12T16:25:50.662Z");
+    Metadata metadata1 = new Metadata();
+    metadata1.addMetadata(metadataEntries1);
+
+    Reference reference1 = new Reference("original1", "dataStore1", 1000,
+      new MimeTypes().forName("text/plain"));
+
+    ProductType productType1 = new ProductType("1", "TestType", "test type 1",
+      "repository1", "versioner1");
+
+    Product product1 = new Product();
+    product1.setProductId("123");
+    product1.setProductName("test product");
+    product1.setProductStructure(Product.STRUCTURE_FLAT);
+    product1.setProductType(productType1);
+
+    FileTransferStatus status1 = new FileTransferStatus(reference1, 1000, 100,
+      product1);
+
+
+    // Create another FileTransferStatus instance using Metadata, Reference,
+    // ProductType and Product instances.
+    Hashtable metadataEntries2 = new Hashtable<String, Object>();
+    metadataEntries2.put("CAS.ProductReceivedTime", "2011-04-11T11:59:59.662Z");
+    Metadata metadata2 = new Metadata();
+    metadata2.addMetadata(metadataEntries2);
+
+    Reference reference2 = new Reference("original2", "dataStore2", 500,
+      new MimeTypes().forName("application/pdf"));
+
+    ProductType productType2 = new ProductType("2", "TestType2", "test type 2",
+        "repository2", "versioner2");
+
+    Product product2 = new Product();
+    product2.setProductId("456");
+    product2.setProductName("test product 2");
+    product2.setProductStructure(Product.STRUCTURE_HIERARCHICAL);
+    product2.setProductType(productType2);
+
+    FileTransferStatus status2 = new FileTransferStatus(reference2, 500, 200,
+      product2);
+
+
+    // Create a TransfersResource using the two FileTransferStatus instances to
+    // generate TransferResource instances for the TransfersResource.
+    List<TransferResource> resources = new ArrayList<TransferResource>();
+    resources.add(new TransferResource(product1, metadata1, status1));
+    resources.add(new TransferResource(product2, metadata2, status2));
+    TransfersResource resource = new TransfersResource("ALL", resources);
+
+    // Generate the expected output.
+    String expectedXml =
+      "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+      + "<transfers productId=\"ALL\">"
+      + "<transfer>"
+      + "<productName>" + product1.getProductName() + "</productName>"
+      + "<productId>" + product1.getProductId() + "</productId>"
+      + "<productTypeName>" + productType1.getName() + "</productTypeName>"
+      + "<dataStoreReference>"
+      +    reference1.getDataStoreReference()
+      + "</dataStoreReference>"
+      + "<origReference>" + reference1.getOrigReference() + "</origReference>"
+      + "<mimeType>" + reference1.getMimeType().getName() + "</mimeType>"
+      + "<fileSize>" + reference1.getFileSize() + "</fileSize>"
+      + "<totalBytes>" + reference1.getFileSize() + "</totalBytes>"
+      + "<bytesTransferred>"
+      +    status1.getBytesTransferred()
+      + "</bytesTransferred>"
+      + "<percentComplete>"
+      +    status1.computePctTransferred() * 100
+      + "</percentComplete>"
+      + "<productReceivedTime>"
+      +    metadata1.getAllValues().get(0)
+      + "</productReceivedTime>"
+      + "</transfer>"
+      + "<transfer>"
+      + "<productName>" + product2.getProductName() + "</productName>"
+      + "<productId>" + product2.getProductId() + "</productId>"
+      + "<productTypeName>" + productType2.getName() + "</productTypeName>"
+      + "<dataStoreReference>"
+      +    reference2.getDataStoreReference()
+      + "</dataStoreReference>"
+      + "<origReference>" + reference2.getOrigReference() + "</origReference>"
+      + "<mimeType>" + reference2.getMimeType().getName() + "</mimeType>"
+      + "<fileSize>" + reference2.getFileSize() + "</fileSize>"
+      + "<totalBytes>" + reference2.getFileSize() + "</totalBytes>"
+      + "<bytesTransferred>"
+      +    status2.getBytesTransferred()
+      + "</bytesTransferred>"
+      + "<percentComplete>"
+      +    status2.computePctTransferred() * 100
+      + "</percentComplete>"
+      + "<productReceivedTime>"
+      +    metadata2.getAllValues().get(0)
+      + "</productReceivedTime>"
+      + "</transfer>"
+      +"</transfers>";
+
+    // Set up a JAXB context and marshall the DatasetResource to XML.
+    JAXBContext context = JAXBContext.newInstance(resource.getClass());
+    Marshaller marshaller = context.createMarshaller();
+    StringWriter writer = new StringWriter();
+    marshaller.marshal(resource, writer);
+
+    // Compare the expected and actual outputs.
+    XMLUnit.setIgnoreWhitespace(true);
+    XMLUnit.setIgnoreComments(true);
+    XMLUnit.setIgnoreAttributeOrder(true);
+    Diff diff = new Diff(expectedXml, writer.toString());
+    assertTrue("The output XML was different to the expected XML: "
+      + diff.toString(), diff.identical());
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/rdf/TestRDFConfigReader.java b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/rdf/TestRDFConfigReader.java
new file mode 100644
index 0000000..ceac947
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/rdf/TestRDFConfigReader.java
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.product.rdf;
+
+//JDK imports
+import java.io.ByteArrayInputStream;
+import org.w3c.dom.Document;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Exercises the {@link RDFConfigReader}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestRDFConfigReader extends TestCase {
+
+  public void testReadNamespaces() {
+    String testDocString = "<?xml version=\"1.0\"?><outer><namespaces><ns name=\"foo\" value=\"bar\"/></namespaces></outer>\n";
+    Document testDoc = XMLUtils.getDocumentRoot(new ByteArrayInputStream(
+        testDocString.getBytes()));
+    RDFConfig conf = new RDFConfig();
+    RDFConfigReader.readNamespaces(testDoc.getDocumentElement(), conf);
+    assertNotNull(conf);
+    assertNotNull(conf.getNsMap());
+    assertNotNull(conf.getNsMap().keySet());
+    assertEquals(1, conf.getNsMap().keySet().size());
+    assertTrue(conf.getNsMap().containsKey("foo"));
+    assertEquals("bar", conf.getNsMap().get("foo"));
+  }
+
+  public void testReadRewriteRules() {
+    String testDocString = "<?xml version=\"1.0\"?><outer><rewrite><key from=\"SiteId\" to=\"site\"/></rewrite></outer>\n";
+    Document testDoc = XMLUtils.getDocumentRoot(new ByteArrayInputStream(
+        testDocString.getBytes()));
+    RDFConfig conf = new RDFConfig();
+    RDFConfigReader.readRewriteRules(testDoc.getDocumentElement(), conf);
+    assertNotNull(conf);
+    assertNotNull(conf.getRewriteMap());
+    assertNotNull(conf.getRewriteMap().keySet());
+    assertEquals(1, conf.getRewriteMap().keySet().size());
+    assertTrue(conf.getRewriteMap().containsKey("SiteId"));
+    assertEquals("site", conf.getRewriteMap().get("SiteId"));
+  }
+
+  public void testReadResourceLinks() {
+    String testDocString = "<?xml version=\"1.0\"?><outer><resourcelinks><key name=\"SiteId\" link=\"http://edrn.nci.nih.gov/data/sites/\"/></resourcelinks></outer>\n";
+    Document testDoc = XMLUtils.getDocumentRoot(new ByteArrayInputStream(
+        testDocString.getBytes()));
+    RDFConfig conf = new RDFConfig();
+    RDFConfigReader.readResourceLinks(testDoc.getDocumentElement(), conf);
+    assertNotNull(conf);
+    assertNotNull(conf.getResLinkMap());
+    assertNotNull(conf.getResLinkMap().keySet());
+    assertEquals(1, conf.getResLinkMap().keySet().size());
+    assertTrue(conf.getResLinkMap().containsKey("SiteId"));
+    assertEquals("http://edrn.nci.nih.gov/data/sites/", conf.getResLinkMap()
+        .get("SiteId"));
+  }
+
+  public void testReadKeyNsMap() {
+    String testDocString = "<?xml version=\"1.0\"?><outer><keynsmap default=\"cas\"><key name=\"SiteId\" ns=\"x\"/></keynsmap></outer>\n";
+    Document testDoc = XMLUtils.getDocumentRoot(new ByteArrayInputStream(
+        testDocString.getBytes()));
+    RDFConfig conf = new RDFConfig();
+    RDFConfigReader.readKeyNsMap(testDoc.getDocumentElement(), conf);
+    assertNotNull(conf);
+    assertNotNull(conf.getKeyNsMap());
+    assertNotNull(conf.getDefaultKeyNs());
+    assertEquals("cas", conf.getDefaultKeyNs());
+    assertNotNull(conf.getKeyNsMap().keySet());
+    assertEquals(1, conf.getKeyNsMap().keySet().size());
+    assertTrue(conf.getKeyNsMap().containsKey("SiteId"));
+    assertEquals("x", conf.getKeyNsMap().get("SiteId"));
+  }
+
+  public void testReadTypeNsMap() {
+    String testDocString = "<?xml version=\"1.0\"?><outer><typesnsmap default=\"cas\"><type name=\"GenericFile\" ns=\"cas\"/></typesnsmap></outer>\n";
+    Document testDoc = XMLUtils.getDocumentRoot(new ByteArrayInputStream(
+        testDocString.getBytes()));
+    RDFConfig conf = new RDFConfig();
+    RDFConfigReader.readTypesNsMap(testDoc.getDocumentElement(), conf);
+    assertNotNull(conf);
+    assertNotNull(conf.getTypesNsMap());
+    assertNotNull(conf.getDefaultTypeNs());
+    assertEquals("cas", conf.getDefaultTypeNs());
+    assertNotNull(conf.getTypesNsMap().keySet());
+    assertEquals(1, conf.getTypesNsMap().keySet().size());
+    assertTrue(conf.getTypesNsMap().containsKey("GenericFile"));
+    assertEquals("cas", conf.getTypesNsMap().get("GenericFile"));
+  }
+}
diff --git a/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/rss/RSSConfigReaderTest.java b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/rss/RSSConfigReaderTest.java
new file mode 100644
index 0000000..d55cc24
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/test/java/org/apache/oodt/cas/product/rss/RSSConfigReaderTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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.
+*/
+
+package org.apache.oodt.cas.product.rss;
+
+import java.io.ByteArrayInputStream;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.w3c.dom.Document;
+
+/**
+ * Tests the {@link RSSConfigReader} class.
+ * @author rlaidlaw
+ * @version $Revision$
+ */
+public class RSSConfigReaderTest extends TestCase
+{
+  /**
+   * Tests the readNamespaces method.
+   */
+  public void testReadNamespaces()
+  {
+    String testXmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+        + "<rss:rssconf xmlns:rss=\"http://oodt.apache.org/ns/rss\">"
+        + "  <namespace prefix=\"cas\" uri=\"http://oodt.apache.org/ns/cas\"/>"
+        + "  <tag name=\"cas:source\" source=\"[ProductType]\"/>"
+        + "  <namespace prefix=\"pge\" uri=\"http://oodt.apache.org/ns/pge\"/>"
+        + "  <tag name=\"pge:tag\" source=\"[ProductType]\"/>"
+        + "  <namespace prefix=\"rss\" uri=\"http://oodt.apache.org/ns/rss\"/>"
+        + "  <tag name=\"rss:enclosure\">"
+        + "    <attribute name=\"x\" value=\"X\"/>"
+        + "    <attribute name=\"y\" value=\"Y\"/>"
+        + "    <attribute name=\"z\" value=\"Z\"/>"
+        + "  </tag>"
+        + "</rss:rssconf>";
+
+    Document testXmlDocument =
+        XMLUtils.getDocumentRoot(new ByteArrayInputStream(testXmlString
+            .getBytes()));
+
+    RSSConfig conf = new RSSConfig();
+    RSSConfigReader.readNamespaces(testXmlDocument.getDocumentElement(), conf);
+
+    List<RSSNamespace> namespaceList = conf.getNamespaces();
+    assertNotNull(namespaceList);
+    assertFalse(namespaceList.isEmpty());
+    assertEquals(3, namespaceList.size());
+
+    RSSNamespace namespaceA = namespaceList.get(0);
+    RSSNamespace namespaceB = namespaceList.get(1);
+    RSSNamespace namespaceC = namespaceList.get(2);
+
+    assertNotNull(namespaceA);
+    assertNotNull(namespaceB);
+    assertNotNull(namespaceC);
+
+    assertEquals("cas", namespaceA.getPrefix());
+    assertEquals("pge", namespaceB.getPrefix());
+    assertEquals("rss", namespaceC.getPrefix());
+
+    assertEquals("http://oodt.apache.org/ns/cas",
+        namespaceA.getUri());
+
+    assertEquals("http://oodt.apache.org/ns/pge",
+        namespaceB.getUri());
+
+    assertEquals("http://oodt.apache.org/ns/rss",
+        namespaceC.getUri());
+  }
+
+  /**
+   * Tests the readTags and readAttrs methods.
+   */
+  public void testReadTagsAndAttrs()
+  {
+    String testXmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+        + "<rss:rssconf xmlns:rss=\"http://oodt.apache.org/ns/rss\">"
+        + " <namespace prefix=\"cas\" uri=\"http://oodt.apache.org/ns/cas\"/>"
+        + " <tag name=\"cas:source\" source=\"[ProductType]\"/>"
+        + " <namespace prefix=\"georss\" uri=\"http://www.georss.org/georss\"/>"
+        + " <tag name=\"georss:point\" source=\"[Latitude] [Longitude]\">"
+        + "  <attribute name=\"one\" value=\"1\"/>"
+        + " </tag>"
+        + " <tag name=\"enclosure\" source=\"\">"
+        + "  <attribute name=\"two\" value=\"2\"/>"
+        + "  <attribute name=\"three\" value=\"3\"/>"
+        + " </tag>"
+        + " <tag name=\"enclosure\">"
+        + "  <attribute name=\"four\" value=\"4\"/>"
+        + "  <attribute name=\"five\" value=\"5\"/>"
+        + "  <attribute name=\"six\" value=\"6\"/>"
+        + " </tag>"
+        + "</rss:rssconf>";
+
+    Document testXmlDocument =
+        XMLUtils.getDocumentRoot(new ByteArrayInputStream(testXmlString
+            .getBytes()));
+
+    RSSConfig conf = new RSSConfig();
+    RSSConfigReader.readTags(testXmlDocument.getDocumentElement(), conf);
+
+    List<RSSTag> tagList = conf.getTags();
+    assertNotNull(tagList);
+    assertFalse(tagList.isEmpty());
+    assertEquals(4, tagList.size());
+
+    RSSTag tagA = tagList.get(0);
+    RSSTag tagB = tagList.get(1);
+    RSSTag tagC = tagList.get(2);
+    RSSTag tagD = tagList.get(3);
+
+    assertNotNull(tagA);
+    assertNotNull(tagB);
+    assertNotNull(tagC);
+    assertNotNull(tagD);
+
+    assertEquals("cas:source", tagA.getName());
+    assertEquals("georss:point", tagB.getName());
+    assertEquals("enclosure", tagC.getName());
+    assertEquals("enclosure", tagD.getName());
+
+    assertEquals("[ProductType]", tagA.getSource());
+    assertEquals("[Latitude] [Longitude]", tagB.getSource());
+    assertEquals("", tagC.getSource());
+    assertNull(tagD.getSource());
+
+    List<RSSTagAttribute> attributesA = tagA.getAttrs();
+    List<RSSTagAttribute> attributesB = tagB.getAttrs();
+    List<RSSTagAttribute> attributesC = tagC.getAttrs();
+    List<RSSTagAttribute> attributesD = tagD.getAttrs();
+
+    assertNotNull(attributesA);
+    assertNotNull(attributesB);
+    assertNotNull(attributesC);
+    assertNotNull(attributesD);
+
+    assertTrue(attributesA.isEmpty());
+    assertEquals(1, attributesB.size());
+    assertEquals(2, attributesC.size());
+    assertEquals(3, attributesD.size());
+
+    assertEquals("one", attributesB.get(0).getName());
+    assertEquals("two", attributesC.get(0).getName());
+    assertEquals("three", attributesC.get(1).getName());
+    assertEquals("four", attributesD.get(0).getName());
+    assertEquals("five", attributesD.get(1).getName());
+    assertEquals("six", attributesD.get(2).getName());
+
+    assertEquals("1", attributesB.get(0).getValue());
+    assertEquals("2", attributesC.get(0).getValue());
+    assertEquals("3", attributesC.get(1).getValue());
+    assertEquals("4", attributesD.get(0).getValue());
+    assertEquals("5", attributesD.get(1).getValue());
+    assertEquals("6", attributesD.get(2).getValue());
+  }
+}
+
diff --git a/0.8.1-rc1/webapp/fmprod/src/test/resources/test-file-1.txt b/0.8.1-rc1/webapp/fmprod/src/test/resources/test-file-1.txt
new file mode 100644
index 0000000..d525e84
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/test/resources/test-file-1.txt
@@ -0,0 +1 @@
+this is test-file-1
diff --git a/0.8.1-rc1/webapp/fmprod/src/test/resources/test-file-2.txt b/0.8.1-rc1/webapp/fmprod/src/test/resources/test-file-2.txt
new file mode 100644
index 0000000..871fcf7
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/test/resources/test-file-2.txt
@@ -0,0 +1 @@
+this is test-file-2
diff --git a/0.8.1-rc1/webapp/fmprod/src/test/resources/test-file-3.txt b/0.8.1-rc1/webapp/fmprod/src/test/resources/test-file-3.txt
new file mode 100644
index 0000000..1566710
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/test/resources/test-file-3.txt
@@ -0,0 +1 @@
+this is test-file-3
diff --git a/0.8.1-rc1/webapp/fmprod/src/test/resources/test.logging.properties b/0.8.1-rc1/webapp/fmprod/src/test/resources/test.logging.properties
new file mode 100644
index 0000000..9a195df
--- /dev/null
+++ b/0.8.1-rc1/webapp/fmprod/src/test/resources/test.logging.properties
@@ -0,0 +1,47 @@
+# 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.
+
+# This logging properties file is used during unit testing.
+
+# Log levels: OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL
+
+# Specify which handlers are to be used
+handlers = java.util.logging.ConsoleHandler
+
+# Logging level for the root logger
+.level = FINE
+
+# Logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = FINE
+
+# Formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# CAS-Product settings
+org.apache.oodt.cas.product.level = FINE
+
+# File manager settings
+org.apache.oodt.cas.filemgr.level = SEVERE
+
+# XMLRPC commons-httpclient transport layer settings
+org.apache.commons.httpclient.level = WARNING
+httpclient.wire.level = WARNING
+
+# Apache CXF settings
+org.apache.cxf.level = WARNING
+
+# JAXB settings
+javax.xml.bind.level = WARNING
+com.sun.xml.bind.level = WARNING
diff --git a/0.8.1-rc1/webapp/wmonitor/pom.xml b/0.8.1-rc1/webapp/wmonitor/pom.xml
new file mode 100644
index 0000000..697a9db
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/pom.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+	<parent>
+                <groupId>org.apache.oodt</groupId>
+                <artifactId>oodt-core</artifactId>
+                <version>0.8.1</version>
+                <relativePath>../../core/pom.xml</relativePath>
+        </parent>
+        <groupId>org.apache.oodt</groupId>
+	<artifactId>wmonitor</artifactId>
+	<packaging>war</packaging>
+	<version>0.8.1</version>
+	<name>CAS Workflow Manager Monitor Web App</name>
+	<properties>
+		<wicket.version>1.4.17</wicket.version>
+		<jetty.version>6.1.25</jetty.version>
+		<slf4j.version>1.5.8</slf4j.version>
+		<log4j.version>1.2.14</log4j.version>
+	</properties>
+	<scm>
+   		<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/webapp/wmonitor</connection>
+   		<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/webapp/wmonitor</developerConnection>
+   		<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/webapp/wmonitor</url>
+  	</scm>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.wicket</groupId>
+			<artifactId>wicket</artifactId>
+			<version>${wicket.version}</version>
+		</dependency>
+		<dependency>
+		  <groupId>org.apache.oodt</groupId>
+		  <artifactId>oodt-webapp-components</artifactId>
+		  <version>0.8.1</version>
+		  <exclusions>
+		    <exclusion>
+		      <artifactId>cas-filemgr</artifactId>
+		      <groupId>org.apache.oodt</groupId>
+		    </exclusion>
+		  </exclusions>
+		</dependency>
+
+		<!-- LOGGING DEPENDENCIES - LOG4J -->
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-log4j12</artifactId>
+			<version>${slf4j.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>1.2.14</version>
+		</dependency>
+
+		<!--  JUNIT DEPENDENCY FOR TESTING -->
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.8.1</version>
+			<scope>test</scope>
+		</dependency>
+
+		<!--  JETTY DEPENDENCIES FOR TESTING  -->
+		<dependency>
+			<groupId>org.mortbay.jetty</groupId>
+			<artifactId>jetty</artifactId>
+			<version>${jetty.version}</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.mortbay.jetty</groupId>
+			<artifactId>jetty-util</artifactId>
+			<version>${jetty.version}</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.mortbay.jetty</groupId>
+			<artifactId>jetty-management</artifactId>
+			<version>${jetty.version}</version>
+			<scope>provided</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<resources>
+			<resource>
+				<filtering>false</filtering>
+				<directory>src/main/resources</directory>
+			</resource>
+			<resource>
+				<filtering>false</filtering>
+				<directory>src/main/java</directory>
+				<includes>
+					<include>**</include>
+				</includes>
+				<excludes>
+					<exclude>**/*.java</exclude>
+				</excludes>
+			</resource>
+		</resources>
+		<testResources>
+			<testResource>
+				<filtering>false</filtering>
+				<directory>src/test/java</directory>
+				<includes>
+					<include>**</include>
+				</includes>
+				<excludes>
+					<exclude>**/*.java</exclude>
+				</excludes>
+			</testResource>
+		</testResources>
+		<plugins>
+			<plugin>
+				<inherited>true</inherited>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.5</source>
+					<target>1.5</target>
+					<optimize>true</optimize>
+					<debug>true</debug>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+	</project>
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/Home.css b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/Home.css
new file mode 100644
index 0000000..153bdec
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/Home.css
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+body{
+ font-family:Arial, Sans-Serif;
+ font-size:12px;
+}
+
+#breadcrumbs{
+  padding-bottom:20px;
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/Home.html b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/Home.html
new file mode 100644
index 0000000..1308ed9
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/Home.html
@@ -0,0 +1,35 @@
+<!--
+ 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.
+-->
+<html
+	xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+<head>
+<title>OODT CAS Workflow Manager Monitor</title>
+</head>
+<body>
+
+<h3>Welcome to the OODT CAS Workflow Manager Monitor!</h3>
+
+<p>You can:
+  <ul>
+    <li><a href="#" wicket:id="workflow_insts_viewer_link">View active Workflows</a></li>
+    <li><a href="#" wicket:id="workflows_viewer_link">View what Workflow Descriptions are available.</a></li>
+    <li><a href="#" wicket:id="workflow_event_viewer_link">View what Workflows are associated with different Events</a></li>
+  </ul>
+  
+</body>
+</html>
+ 
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/Home.java b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/Home.java
new file mode 100644
index 0000000..b3cae38
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/Home.java
@@ -0,0 +1,81 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.webapp.monitor;
+
+import org.apache.oodt.cas.workflow.webapp.monitor.events.WorkflowEventViewerPage;
+import org.apache.oodt.cas.workflow.webapp.monitor.instance.WorkflowInstanceViewerPage;
+import org.apache.oodt.cas.workflow.webapp.monitor.workflow.WorkflowsViewerPage;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.link.Link;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class Home extends WebPage {
+
+  public Home() {
+    add(new Link("workflow_event_viewer_link") {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        setResponsePage(WorkflowEventViewerPage.class);
+      }
+    });
+
+    add(new Link("workflows_viewer_link") {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        setResponsePage(WorkflowsViewerPage.class);
+
+      }
+    });
+
+    add(new Link("workflow_insts_viewer_link") {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        PageParameters params = new PageParameters();
+        params.add("pageNum", "1");
+        params.add("status", "ALL");
+        setResponsePage(WorkflowInstanceViewerPage.class, params);
+
+      }
+    });
+
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/WMMonitorApp.java b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/WMMonitorApp.java
new file mode 100644
index 0000000..a903ae3
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/WMMonitorApp.java
@@ -0,0 +1,102 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.webapp.monitor;
+
+import org.apache.oodt.cas.webcomponents.workflow.WMMonitorAppBase;
+import org.apache.oodt.cas.webcomponents.workflow.instance.WorkflowInstancesViewer;
+import org.apache.oodt.cas.workflow.webapp.monitor.condition.WorkflowConditionViewerPage;
+import org.apache.oodt.cas.workflow.webapp.monitor.events.WorkflowEventViewerPage;
+import org.apache.oodt.cas.workflow.webapp.monitor.instance.WorkflowInstanceViewerPage;
+import org.apache.oodt.cas.workflow.webapp.monitor.task.WorkflowTaskViewerPage;
+import org.apache.oodt.cas.workflow.webapp.monitor.workflow.WorkflowViewerPage;
+import org.apache.oodt.cas.workflow.webapp.monitor.workflow.WorkflowsViewerPage;
+import org.apache.wicket.Page;
+import org.apache.wicket.ResourceReference;
+import org.apache.wicket.request.target.coding.MixedParamUrlCodingStrategy;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WMMonitorApp extends WMMonitorAppBase {
+
+  public WMMonitorApp() {
+    MixedParamUrlCodingStrategy taskPageMount = new MixedParamUrlCodingStrategy(
+        "task", WorkflowTaskViewerPage.class, new String[] { "id" });
+    MixedParamUrlCodingStrategy condPageMount = new MixedParamUrlCodingStrategy(
+        "condition", WorkflowConditionViewerPage.class, new String[] { "id" });
+
+    MixedParamUrlCodingStrategy workflowPageMount = new MixedParamUrlCodingStrategy(
+        "workflow", WorkflowViewerPage.class, new String[] { "id" });
+
+    MixedParamUrlCodingStrategy eventsPageMount = new MixedParamUrlCodingStrategy(
+        "events", WorkflowEventViewerPage.class, new String[] {});
+
+    MixedParamUrlCodingStrategy workflowsPageMount = new MixedParamUrlCodingStrategy(
+        "workflows", WorkflowsViewerPage.class, new String[] {});
+
+    MixedParamUrlCodingStrategy workflowInstsPageMount = new MixedParamUrlCodingStrategy(
+        "instances", WorkflowInstanceViewerPage.class, new String[] { "status",
+            "pageNum" });
+
+    mount(taskPageMount);
+    mount(condPageMount);
+    mount(workflowPageMount);
+    mount(eventsPageMount);
+    mount(workflowsPageMount);
+    mount(workflowInstsPageMount);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.wicket.Application#getHomePage()
+   */
+  @Override
+  public Class<? extends Page> getHomePage() {
+    return Home.class;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.wicket.protocol.http.WebApplication#init()
+   */
+  @Override
+  protected void init() {
+    super.init();
+
+    mountSharedResource("/images/percentImage_back1.png",
+        new ResourceReference(WorkflowInstancesViewer.class,
+            "percentImage_back1.png").getSharedResourceKey());
+    mountSharedResource("/images/percentImage_back2.png",
+        new ResourceReference(WorkflowInstancesViewer.class,
+            "percentImage_back2.png").getSharedResourceKey());
+    mountSharedResource("/images/percentImage_back3.png",
+        new ResourceReference(WorkflowInstancesViewer.class,
+            "percentImage_back3.png").getSharedResourceKey());
+    mountSharedResource("/images/percentImage_back4.png",
+        new ResourceReference(WorkflowInstancesViewer.class,
+            "percentImage_back4.png").getSharedResourceKey());
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/condition/WorkflowConditionViewerPage.css b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/condition/WorkflowConditionViewerPage.css
new file mode 100644
index 0000000..153bdec
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/condition/WorkflowConditionViewerPage.css
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+body{
+ font-family:Arial, Sans-Serif;
+ font-size:12px;
+}
+
+#breadcrumbs{
+  padding-bottom:20px;
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/condition/WorkflowConditionViewerPage.html b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/condition/WorkflowConditionViewerPage.html
new file mode 100644
index 0000000..9749abc
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/condition/WorkflowConditionViewerPage.html
@@ -0,0 +1,21 @@
+<!--
+ 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.
+-->
+<wicket:link>
+ <link rel="stylesheet" type="text/css" href="WorkflowConditionViewerPage.css"/>
+</wicket:link>
+<div id="breadcrumbs"><a href="#" wicket:id="home_link">Home</a>&nbsp;<span id="divider">/</span>&nbsp;Conditions&nbsp;<span id="divider">/</span>&nbsp;<span wicket:id="cond_id">urn:oodt:TestCondition</span></div>
+<div wicket:id="cond_viewer"/>
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/condition/WorkflowConditionViewerPage.java b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/condition/WorkflowConditionViewerPage.java
new file mode 100644
index 0000000..26b7d61
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/condition/WorkflowConditionViewerPage.java
@@ -0,0 +1,53 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.webapp.monitor.condition;
+
+import org.apache.oodt.cas.webcomponents.workflow.conditions.WorkflowConditionViewer;
+import org.apache.oodt.cas.workflow.webapp.monitor.WMMonitorApp;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.Link;
+
+/**
+ *
+ * Describe your class here.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class WorkflowConditionViewerPage extends WebPage {
+  
+   public WorkflowConditionViewerPage(PageParameters params){
+     add(new Link("home_link"){
+         /* (non-Javadoc)
+         * @see org.apache.wicket.markup.html.link.Link#onClick()
+         */
+        @Override
+        public void onClick() {
+          setResponsePage(getApplication().getHomePage());
+        }
+     });
+     add(new Label("cond_id", params.getString("id")));
+     add(new WorkflowConditionViewer("cond_viewer", ((WMMonitorApp)getApplication()).getWorkflowUrl(), 
+         params.getString("id")));
+   }
+
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/events/WorkflowEventViewerPage.css b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/events/WorkflowEventViewerPage.css
new file mode 100644
index 0000000..153bdec
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/events/WorkflowEventViewerPage.css
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+body{
+ font-family:Arial, Sans-Serif;
+ font-size:12px;
+}
+
+#breadcrumbs{
+  padding-bottom:20px;
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/events/WorkflowEventViewerPage.html b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/events/WorkflowEventViewerPage.html
new file mode 100644
index 0000000..92ecd5d
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/events/WorkflowEventViewerPage.html
@@ -0,0 +1,21 @@
+<!--
+ 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.
+-->
+<wicket:link>
+ <link rel="stylesheet" type="text/css" href="WorkflowEventViewerPage.css"/>
+</wicket:link>
+<div id="breadcrumbs"><a href="#" wicket:id="home_link">Home</a>&nbsp;<span id="divider">/</span>&nbsp;Events&nbsp;</div>
+<div wicket:id="viewer"/>
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/events/WorkflowEventViewerPage.java b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/events/WorkflowEventViewerPage.java
new file mode 100644
index 0000000..3b7c775
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/events/WorkflowEventViewerPage.java
@@ -0,0 +1,50 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.webapp.monitor.events;
+
+import org.apache.oodt.cas.webcomponents.workflow.event.EventToWorkflowViewer;
+import org.apache.oodt.cas.workflow.webapp.monitor.WMMonitorApp;
+import org.apache.oodt.cas.workflow.webapp.monitor.workflow.WorkflowViewerPage;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.link.Link;
+
+/**
+ *
+ * Describe your class here.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class WorkflowEventViewerPage extends WebPage {
+  
+  public WorkflowEventViewerPage(){
+    add(new Link("home_link"){
+      /* (non-Javadoc)
+      * @see org.apache.wicket.markup.html.link.Link#onClick()
+      */
+     @Override
+     public void onClick() {
+       setResponsePage(getApplication().getHomePage());
+     }
+  });    
+    add(new EventToWorkflowViewer("viewer", ((WMMonitorApp)getApplication()).getWorkflowUrl(), WorkflowViewerPage.class));
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/instance/WorkflowInstanceViewerPage.css b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/instance/WorkflowInstanceViewerPage.css
new file mode 100644
index 0000000..153bdec
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/instance/WorkflowInstanceViewerPage.css
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+body{
+ font-family:Arial, Sans-Serif;
+ font-size:12px;
+}
+
+#breadcrumbs{
+  padding-bottom:20px;
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/instance/WorkflowInstanceViewerPage.html b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/instance/WorkflowInstanceViewerPage.html
new file mode 100644
index 0000000..2b519f6
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/instance/WorkflowInstanceViewerPage.html
@@ -0,0 +1,22 @@
+<!--
+ 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.
+-->
+<wicket:link>
+ <link rel="stylesheet" type="text/css" href="WorkflowInstanceViewerPage.css"/>
+</wicket:link>
+<div id="breadcrumbs"><a href="#" wicket:id="home_link">Home</a>&nbsp;<span id="divider">/</span>&nbsp;Instances&nbsp;</div>
+
+<div wicket:id="instance_viewer"/>
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/instance/WorkflowInstanceViewerPage.java b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/instance/WorkflowInstanceViewerPage.java
new file mode 100644
index 0000000..c23da5b
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/instance/WorkflowInstanceViewerPage.java
@@ -0,0 +1,56 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.webapp.monitor.instance;
+
+import org.apache.oodt.cas.webcomponents.workflow.instance.WorkflowInstancesViewer;
+import org.apache.oodt.cas.workflow.webapp.monitor.WMMonitorApp;
+import org.apache.oodt.cas.workflow.webapp.monitor.task.WorkflowTaskViewerPage;
+import org.apache.oodt.cas.workflow.webapp.monitor.workflow.WorkflowViewerPage;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.link.Link;
+
+/**
+ *
+ * Describe your class here.
+ *
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public class WorkflowInstanceViewerPage extends WebPage {
+  
+  public WorkflowInstanceViewerPage(PageParameters params){
+    add(new Link("home_link"){
+      /* (non-Javadoc)
+      * @see org.apache.wicket.markup.html.link.Link#onClick()
+      */
+     @Override
+     public void onClick() {
+       setResponsePage(getApplication().getHomePage());
+     }
+  });
+    
+    add(new WorkflowInstancesViewer("instance_viewer", ((WMMonitorApp)getApplication()).getWorkflowUrl(), 
+        params.getString("status", "ALL"), params.getInt("pageNum", 1), ((WMMonitorApp)getApplication()).getStatuses(), 
+        ((WMMonitorApp)getApplication()).getLifecycleFilePath(), ((WMMonitorApp)getApplication()).getInstMetFieldsFilePath(),
+        WorkflowViewerPage.class, WorkflowTaskViewerPage.class, WorkflowInstanceViewerPage.class));
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/task/WorkflowTaskViewerPage.css b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/task/WorkflowTaskViewerPage.css
new file mode 100644
index 0000000..153bdec
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/task/WorkflowTaskViewerPage.css
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+body{
+ font-family:Arial, Sans-Serif;
+ font-size:12px;
+}
+
+#breadcrumbs{
+  padding-bottom:20px;
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/task/WorkflowTaskViewerPage.html b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/task/WorkflowTaskViewerPage.html
new file mode 100644
index 0000000..fa15ad8
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/task/WorkflowTaskViewerPage.html
@@ -0,0 +1,21 @@
+<!--
+ 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.
+-->
+<wicket:link>
+ <link rel="stylesheet" type="text/css" href="WorkflowTaskViewerPage.css"/>
+</wicket:link>
+<div id="breadcrumbs"><a href="#" wicket:id="home_link">Home</a>&nbsp;<span id="divider">/</span>&nbsp;Tasks&nbsp;<span id="divider">/</span>&nbsp;<span wicket:id="task_id">urn:oodt:LongTask</span></div>
+<div wicket:id="task_viewer" id="task_viewer"/>
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/task/WorkflowTaskViewerPage.java b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/task/WorkflowTaskViewerPage.java
new file mode 100644
index 0000000..cd5dfbf
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/task/WorkflowTaskViewerPage.java
@@ -0,0 +1,55 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.webapp.monitor.task;
+
+import org.apache.oodt.cas.webcomponents.workflow.WMMonitorAppBase;
+import org.apache.oodt.cas.webcomponents.workflow.tasks.WorkflowTaskViewer;
+import org.apache.oodt.cas.workflow.webapp.monitor.condition.WorkflowConditionViewerPage;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.Link;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowTaskViewerPage extends WebPage {
+
+  public WorkflowTaskViewerPage(PageParameters params) {
+    add(new Link("home_link"){
+      /* (non-Javadoc)
+      * @see org.apache.wicket.markup.html.link.Link#onClick()
+      */
+     @Override
+     public void onClick() {
+       setResponsePage(getApplication().getHomePage());
+     }
+  });    
+    add(new Label("task_id", params.getString("id")));
+    WorkflowTaskViewer viewerComponent = new WorkflowTaskViewer("task_viewer",
+        ((WMMonitorAppBase) getApplication()).getWorkflowUrl(), params
+            .getString("id"), WorkflowConditionViewerPage.class);
+    add(viewerComponent);
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowViewerPage.css b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowViewerPage.css
new file mode 100644
index 0000000..153bdec
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowViewerPage.css
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+body{
+ font-family:Arial, Sans-Serif;
+ font-size:12px;
+}
+
+#breadcrumbs{
+  padding-bottom:20px;
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowViewerPage.html b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowViewerPage.html
new file mode 100644
index 0000000..75c71e7
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowViewerPage.html
@@ -0,0 +1,21 @@
+<!--
+ 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.
+-->
+<wicket:link>
+ <link rel="stylesheet" type="text/css" href="WorkflowViewerPage.css"/>
+</wicket:link>
+<div id="breadcrumbs"><a href="#" wicket:id="home_link">Home</a>&nbsp;<span id="divider">/</span>&nbsp;<a href="#" wicket:id="workflows_viewer_link">Workflows</a>&nbsp;<span id="divider">/</span>&nbsp;<span wicket:id="workflow_id">urn:oodt:LongWorkflow</span></div>
+<div wicket:id="workflow_viewer" id="workflow_viewer"/>
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowViewerPage.java b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowViewerPage.java
new file mode 100644
index 0000000..378455d
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowViewerPage.java
@@ -0,0 +1,62 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.webapp.monitor.workflow;
+
+import org.apache.oodt.cas.webcomponents.workflow.model.WorkflowViewer;
+import org.apache.oodt.cas.workflow.webapp.monitor.WMMonitorApp;
+import org.apache.oodt.cas.workflow.webapp.monitor.task.WorkflowTaskViewerPage;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.Link;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowViewerPage extends WebPage {
+
+  public WorkflowViewerPage(PageParameters params) {
+    add(new Link("home_link"){
+      /* (non-Javadoc)
+      * @see org.apache.wicket.markup.html.link.Link#onClick()
+      */
+     @Override
+     public void onClick() {
+       setResponsePage(getApplication().getHomePage());
+     }
+  });
+    add(new Link("workflows_viewer_link"){
+       /* (non-Javadoc)
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        setResponsePage(WorkflowsViewerPage.class);
+      }
+    });
+    add(new Label("workflow_id", params.getString("id")));
+    add(new WorkflowViewer("workflow_viewer", ((WMMonitorApp) getApplication())
+        .getWorkflowUrl(), params.getString("id"), WorkflowTaskViewerPage.class));
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowsViewerPage.css b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowsViewerPage.css
new file mode 100644
index 0000000..153bdec
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowsViewerPage.css
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+body{
+ font-family:Arial, Sans-Serif;
+ font-size:12px;
+}
+
+#breadcrumbs{
+  padding-bottom:20px;
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowsViewerPage.html b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowsViewerPage.html
new file mode 100644
index 0000000..16a4375
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowsViewerPage.html
@@ -0,0 +1,21 @@
+<!--
+ 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.
+-->
+<wicket:link>
+ <link rel="stylesheet" type="text/css" href="WorkflowsViewerPage.css"/>
+</wicket:link>
+<div id="breadcrumbs"><a href="#" wicket:id="home_link">Home</a>&nbsp;<span id="divider">/</span>&nbsp;Workflows&nbsp;</div>
+<div wicket:id="workflows_viewer" id="workflows_viewer"/>
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowsViewerPage.java b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowsViewerPage.java
new file mode 100644
index 0000000..d571934
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/java/org/apache/oodt/cas/workflow/webapp/monitor/workflow/WorkflowsViewerPage.java
@@ -0,0 +1,53 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.webapp.monitor.workflow;
+
+import org.apache.oodt.cas.webcomponents.workflow.model.WorkflowsViewer;
+import org.apache.oodt.cas.workflow.webapp.monitor.WMMonitorApp;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.link.Link;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowsViewerPage extends WebPage {
+
+  public WorkflowsViewerPage() {
+    add(new Link("home_link") {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see org.apache.wicket.markup.html.link.Link#onClick()
+       */
+      @Override
+      public void onClick() {
+        setResponsePage(getApplication().getHomePage());
+      }
+    });
+
+    add(new WorkflowsViewer("workflows_viewer",
+        ((WMMonitorApp) getApplication()).getWorkflowUrl(),
+        WorkflowViewerPage.class));
+  }
+
+}
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/webapp/META-INF/context.xml b/0.8.1-rc1/webapp/wmonitor/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..d5e46b9
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,32 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<Context path="/wmonitor">
+		
+	<Parameter name="workflow.url"
+	    value="[WORKFLOW_URL]"/>
+	    
+	<Parameter name="org.apache.oodt.cas.workflow.webapp.lifecycleFilePath"
+	    value="[WORKFLOW_HOME]/policy/workflow-lifecycle.xml"/>
+	    
+	<Parameter name="org.apache.oodt.cas.workflow.inst.statuses"
+	    value="STARTED, FINISHED, METMISS, PAUSED"/>
+	    
+	<Parameter name="org.apache.oodt.cas.workflow.webapp.inst.metFields.filePath"
+	    value="[WORKFLOW_HOME]/policy/workflow-instance-met.xml"/>
+	    
+</Context>
diff --git a/0.8.1-rc1/webapp/wmonitor/src/main/webapp/WEB-INF/web.xml b/0.8.1-rc1/webapp/wmonitor/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..e98531d
--- /dev/null
+++ b/0.8.1-rc1/webapp/wmonitor/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ 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.
+-->
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+	 version="2.4">
+
+	<display-name>workflow-monitor</display-name>
+
+	 <!--  
+	      There are three means to configure Wickets configuration mode and they are
+	      tested in the order given. 
+	      1) A system property: -Dwicket.configuration
+	      2) servlet specific <init-param>
+	      3) context specific <context-param>
+	      The value might be either "development" (reloading when templates change)
+	      or "deployment". If no configuration is found, "development" is the default.
+	-->
+
+	<filter>
+		<filter-name>wicket.browser</filter-name>
+ 		<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
+		<init-param>
+			<param-name>applicationClassName</param-name>
+			<param-value>org.apache.oodt.cas.workflow.webapp.monitor.WMMonitorApp</param-value>
+ 		</init-param>
+ 	</filter>
+
+ <filter-mapping>
+  <filter-name>wicket.browser</filter-name>
+	<url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+
+</web-app>
diff --git a/0.8.1-rc1/workflow/pom.xml b/0.8.1-rc1/workflow/pom.xml
new file mode 100644
index 0000000..0751375
--- /dev/null
+++ b/0.8.1-rc1/workflow/pom.xml
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>cas-workflow</artifactId>
+  <name>Catalog and Archive Workflow Management Component</name>
+  <description>The workflow management component of a Catalog and Archive Service. This component
+     purposefully separates workflow repositories and workflow engines standard interfaces, and
+     provides some out of the box backend implementations of them (including one based
+     on the javax.sql.DataSource interface). This component provides everything that you need
+     to execute workflows, and science processing pipelines.</description>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>2.4</version>
+        <configuration>
+          <forkMode>pertest</forkMode>
+          <useSystemClassLoader>false</useSystemClassLoader>
+          <systemProperties>
+             <property>
+               <name>java.util.logging.config.file</name>
+               <value>${basedir}/src/test/resources/test.logging.properties</value>
+              </property>
+           </systemProperties>
+           <forkedProcessTimeoutInSeconds>0</forkedProcessTimeoutInSeconds>
+           <redirectTestOutputToFile>true</redirectTestOutputToFile>
+            <includes>
+              <include>**/*Test*.java</include>
+            </includes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-2</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/assembly/assembly.xml</descriptor>
+          </descriptors>
+          <archive>
+            <manifest>
+              <mainClass>org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient</mainClass>
+            </manifest>
+          </archive>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin> 
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>audit</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>rat-maven-plugin</artifactId>
+            <configuration>
+              <excludes>
+                <exclude>**/src/test/resources/*</exclude>
+              </excludes>
+            </configuration>
+            <executions>
+              <execution>
+                <phase>verify</phase>
+                <goals>
+                  <goal>check</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-commons</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-cli</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-metadata</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>cas-resource</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+        <groupId>concurrent</groupId>
+        <artifactId>concurrent</artifactId>
+        <version>1.3.4</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <version>2.4</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-dbcp</groupId>
+      <artifactId>commons-dbcp</artifactId>
+      <version>1.2.1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+      <version>2.1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+      <version>3.0</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.0.3</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <version>1.3</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-pool</groupId>
+      <artifactId>commons-pool</artifactId>
+      <version>1.2</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>xmlrpc</groupId>
+      <artifactId>xmlrpc</artifactId>
+      <version>2.0.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.lucene</groupId>
+      <artifactId>lucene-core</artifactId>
+      <version>2.0.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.safehaus.jug</groupId>
+      <artifactId>jug</artifactId>
+      <version>2.0.0</version>
+      <classifier>asl</classifier>
+    </dependency>
+    <dependency>
+      <groupId>hsqldb</groupId>
+      <artifactId>hsqldb</artifactId>
+      <version>1.8.0.7</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.javamail</groupId>
+      <artifactId>geronimo-javamail_1.4_mail</artifactId>
+      <version>1.8.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-activation_1.1_spec</artifactId>
+      <version>1.1</version>
+    </dependency>
+    <dependency>
+      <groupId>joda-time</groupId>
+      <artifactId>joda-time</artifactId>
+      <version>2.5</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/workflow/src/main/assembly/assembly.xml b/0.8.1-rc1/workflow/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..beb6355
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/assembly/assembly.xml
@@ -0,0 +1,86 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<assembly>
+  <id>dist</id>
+  <formats>
+    <format>tar.gz</format>
+    <format>zip</format>
+  </formats>
+  <includeBaseDirectory>true</includeBaseDirectory>
+  <baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
+  <includeSiteDirectory>false</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>${basedir}</directory>
+      <outputDirectory>.</outputDirectory>
+      <includes>
+        <include>LICENSE.txt</include>
+        <include>CHANGES.txt</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/bin</directory>
+      <outputDirectory>bin</outputDirectory>
+      <includes/>
+      <fileMode>755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>logs</outputDirectory>
+      <includes>
+        <include>REMOVE.log</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>etc</outputDirectory>
+      <includes>
+        <include>workflow.properties</include>
+        <include>logging.properties</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources</directory>
+      <outputDirectory>policy</outputDirectory>
+      <includes>
+        <include>cmd-line-actions.xml</include>
+        <include>cmd-line-options.xml</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${basedir}/src/main/resources/examples</directory>
+      <outputDirectory>policy</outputDirectory>
+      <excludes/>
+    </fileSet>
+    <fileSet>
+      <directory>target/site/apidocs</directory>
+      <filtered>false</filtered>
+      <outputDirectory>doc</outputDirectory>
+      <excludes/>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>lib</outputDirectory>
+      <unpack>false</unpack>
+      <useProjectArtifact>true</useProjectArtifact>
+      <useTransitiveDependencies>true</useTransitiveDependencies>
+      <unpackOptions/>
+    </dependencySet>
+  </dependencySets>
+</assembly>
diff --git a/0.8.1-rc1/workflow/src/main/bin/wmgr b/0.8.1-rc1/workflow/src/main/bin/wmgr
new file mode 100644
index 0000000..34e05c8
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/bin/wmgr
@@ -0,0 +1,75 @@
+#!/bin/sh
+#
+# init script for XmlRpcWorkflowManager
+#
+# chkconfig: 345 88 22
+# description: CAS Workflow Manager
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+
+[ -f /etc/sysconfig/java ] && . /etc/sysconfig/java
+#[ -f /etc/sysconfig/cas-filemgr] && . /etc/sysconfig/cas-filemgr
+
+SERVER_PORT=9001
+export SERVER_PORT
+
+if [ -z $JAVA_HOME ] ; then
+	JAVA_HOME=/path/to/java/home
+else
+	JAVA_HOME=${JAVA_HOME}
+fi
+
+export JAVA_HOME
+CAS_WORKFLOW_HOME=..
+export CAS_WORKFLOW_HOME
+RUN_HOME=${CAS_WORKFLOW_HOME}/../run
+export RUN_HOME
+CAS_WORKFLOW_PROPS=../etc/workflow.properties
+export CAS_WORKFLOW_PROPS
+
+PATH=${JAVA_HOME}/bin:${CAS_WORKFLOW_HOME}/bin:/usr/bin:/bin:/usr/sbin:/sbin
+export PATH
+
+# See how we were called.
+case "$1" in
+  start)
+        echo -n "Starting cas workflow manager: "
+        $JAVA_HOME/bin/java -Djava.ext.dirs=${CAS_WORKFLOW_HOME}/lib \
+        -Djava.util.logging.config.file=${CAS_WORKFLOW_HOME}/etc/logging.properties \
+        -Dorg.apache.oodt.cas.workflow.properties=${CAS_WORKFLOW_PROPS} \
+        -Dorg.apache.oodt.cas.pge.task.metkeys.legacyMode="true" \
+        -Dorg.apache.oodt.cas.pge.task.status.legacyMode="true" \
+        org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManager --portNum $SERVER_PORT &       
+        echo $! >${RUN_HOME}/cas.workflow.pid 
+        echo "OK"
+        sleep 5
+        ;;
+  stop)
+        echo -n "Shutting down cas workflow manager: "
+        kill `cat ${RUN_HOME}/cas.workflow.pid`
+        echo "OK"
+        ;;
+  restart)
+        $0 stop
+        $0 start
+        ;;
+  *)
+        echo "Usage: $0 {start|stop|restart}"
+        exit 1
+esac
+
+exit 0
diff --git a/0.8.1-rc1/workflow/src/main/bin/wmgr-client b/0.8.1-rc1/workflow/src/main/bin/wmgr-client
new file mode 100644
index 0000000..9a508d3
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/bin/wmgr-client
@@ -0,0 +1,31 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+
+if [ -z $JAVA_HOME ] ; then
+	JAVA_HOME=/path/to/java/home
+else
+	JAVA_HOME=${JAVA_HOME}
+fi
+
+export JAVA_HOME
+
+$JAVA_HOME/bin/java \
+        -Djava.ext.dirs=../lib \
+        -Djava.util.logging.config.file=../etc/logging.properties \
+        -Dorg.apache.oodt.cas.cli.action.spring.config=../policy/cmd-line-actions.xml \
+        -Dorg.apache.oodt.cas.cli.option.spring.config=../policy/cmd-line-options.xml \
+        org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient $*
diff --git a/0.8.1-rc1/workflow/src/main/bin/wmkill b/0.8.1-rc1/workflow/src/main/bin/wmkill
new file mode 100755
index 0000000..4cec22d
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/bin/wmkill
@@ -0,0 +1,31 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.  
+
+export ORIG_DIR=`pwd`
+export DIR=`dirname $0`
+cd $DIR
+export DIR_PATH=`pwd`
+cd $ORIG_DIR
+
+if [ "$#" -ne 1 ]; then
+    echo "Usage: $0 <workflow instance id>"
+    exit 1
+else
+    pushd $DIR_PATH
+    ./wmgr-client --url http://localhost:9001 --operation --stopWorkflowInst --id $1
+    popd
+fi
+
diff --git a/0.8.1-rc1/workflow/src/main/bin/wmkillallbystatus b/0.8.1-rc1/workflow/src/main/bin/wmkillallbystatus
new file mode 100755
index 0000000..d0df9df
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/bin/wmkillallbystatus
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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. 
+
+export ORIG_DIR=`pwd`
+export DIR=`dirname $0`
+cd $DIR
+export DIR_PATH=`pwd`
+cd $ORIG_DIR
+
+if [ "$#" -ne 1 ]; then
+    echo "Usage: $0 <status, e.g., QUEUED, RSUBMIT, etc.>"
+    exit 1
+else
+    pushd $DIR_PATH
+    for id in `./wmgr-client --url http://localhost:9001 --operation --getFirstPage --status $1 | awk '{print $2}' | cut -f 2 -d = | cut -f 1 -d ,` 
+        do
+            echo "Killing workflow with ID $id"
+            ./wmkill $id
+    done
+    popd
+fi
\ No newline at end of file
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/DynWorkflowCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/DynWorkflowCliAction.java
new file mode 100644
index 0000000..0b61e00
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/DynWorkflowCliAction.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * A {@link CmdLineAction} for submitting dynamically created {@link Workflow}s
+ * of pre-defined {@link WorkflowTask}s.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class DynWorkflowCliAction extends WorkflowCliAction {
+
+   private List<String> taskIds;
+   private Metadata metadata;
+
+   public DynWorkflowCliAction() {
+      metadata = new Metadata();
+   }
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      Validate.notNull(taskIds, "Must specify taskIds");
+
+      try {
+         String instId = getClient().executeDynamicWorkflow(taskIds, metadata);
+         printer.println("Started dynamic workflow with id '" + instId + "'");
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to submit dynamic workflow for taskIds " + taskIds
+                     + " with metadata " + metadata.getHashtable() + " : "
+                     + e.getMessage(), e);
+      }
+   }
+
+   public void setTaskIds(List<String> taskIds) {
+      this.taskIds = taskIds;
+   }
+
+   public void addMetadata(List<String> metadata) {
+      Validate.isTrue(metadata.size() > 1);
+
+      this.metadata.addMetadata(metadata.get(0),
+            metadata.subList(1, metadata.size()));
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetConditionByIdCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetConditionByIdCliAction.java
new file mode 100644
index 0000000..e5d16b1
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetConditionByIdCliAction.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+
+/**
+ * A {@link CmdLineAction} which retrieves WorkflowCondition information for
+ * WorkflowCondition with given condition ID.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetConditionByIdCliAction extends WorkflowCliAction {
+
+   private String conditionId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         WorkflowCondition condition = getClient()
+               .getConditionById(conditionId);
+         printer.println("Condition: [id=" + condition.getConditionId()
+               + ", name=" + condition.getConditionName() + ", order="
+               + condition.getOrder() + ", class="
+               + condition.getClass().getName() + "]");
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get condition by id for conditionId '" + conditionId
+                     + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setConditionId(String conditionId) {
+      this.conditionId = conditionId;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetFirstPageCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetFirstPageCliAction.java
new file mode 100644
index 0000000..3abfb1f
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetFirstPageCliAction.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+
+/**
+ * Gets the first page of workflow instances.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetFirstPageCliAction extends WorkflowCliAction {
+
+   private String status;
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         XmlRpcWorkflowManagerClient client = getClient();
+         WorkflowInstancePage page = null;
+         if (status != null && !status.equals("")) {
+            page = client.paginateWorkflowInstances(1, status);
+         } else {
+            page = client.getFirstPage();
+         }
+
+         printer.println("Page: [num=" + page.getPageNum() + ","
+               + "pageSize=" + page.getPageSize() + ",totalPages="
+               + page.getTotalPages() + "]");
+         if (page.getPageWorkflows() == null) {
+            throw new Exception(
+                  "WorkflowManager returned null page of workflows");
+         }
+         for (WorkflowInstance inst : (List<WorkflowInstance>) page
+               .getPageWorkflows()) {
+            printer.println("Instance: [id=" + inst.getId() + ", status="
+                  + inst.getStatus() + ", currentTask="
+                  + inst.getCurrentTaskId() + ", workflow="
+                  + inst.getWorkflow().getName() + ", wallClockTime="
+                  + client.getWorkflowWallClockMinutes(inst.getId())
+                  + ", currentTaskWallClockTime="
+                  + client.getWorkflowCurrentTaskWallClockMinutes(inst.getId())
+                  + "]");
+         }
+
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get first page of workflows : " + e.getMessage(), e);
+      }
+   }
+
+   public void setStatus(String status) {
+      this.status = status;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetLastPageCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetLastPageCliAction.java
new file mode 100644
index 0000000..252364b
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetLastPageCliAction.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+
+/**
+ * A {@link CmdLineOption} which gets the last page of workflows.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetLastPageCliAction extends WorkflowCliAction {
+
+   private String status;
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         XmlRpcWorkflowManagerClient client = getClient();
+         WorkflowInstancePage page = null;
+         if (status != null && !status.equals("")) {
+            WorkflowInstancePage firstPage = client.paginateWorkflowInstances(
+                  1, status);
+            page = client.paginateWorkflowInstances(firstPage.getTotalPages(),
+                  status);
+         } else {
+            page = client.getLastPage();
+         }
+
+         printer.println("Page: [num=" + page.getPageNum() + ","
+               + "pageSize=" + page.getPageSize() + ",totalPages="
+               + page.getTotalPages() + "]");
+         if (page.getPageWorkflows() == null) {
+            throw new Exception(
+                  "WorkflowManager returned null page of workflows");
+         }
+         for (WorkflowInstance inst : (List<WorkflowInstance>) page
+               .getPageWorkflows()) {
+            printer.println("Instance: [id=" + inst.getId() + ", status="
+                  + inst.getStatus() + ", currentTask="
+                  + inst.getCurrentTaskId() + ", workflow="
+                  + inst.getWorkflow().getName() + ",wallClockTime="
+                  + client.getWorkflowWallClockMinutes(inst.getId())
+                  + ",currentTaskWallClockTime="
+                  + client.getWorkflowCurrentTaskWallClockMinutes(inst.getId())
+                  + "]");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get last page of workflows with " + "status '"
+                     + status + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setStatus(String status) {
+      this.status = status;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetNextPageCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetNextPageCliAction.java
new file mode 100644
index 0000000..09fc551
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetNextPageCliAction.java
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+
+/**
+ * A {@link CmdLineAction} which gets the next page of workflows.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetNextPageCliAction extends WorkflowCliAction {
+
+   private int pageNum = -1;
+   private String status;
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      Validate.isTrue(pageNum != -1);
+
+      try {
+         XmlRpcWorkflowManagerClient client = getClient();
+         WorkflowInstancePage page = null;
+         if (status != null && !status.equals("")) {
+            page = client.paginateWorkflowInstances(pageNum + 1, status);
+         } else {
+            page = client.paginateWorkflowInstances(pageNum + 1);
+         }
+
+         printer.println("Page: [num=" + page.getPageNum() + ","
+               + "pageSize=" + page.getPageSize() + ",totalPages="
+               + page.getTotalPages() + "]");
+         if (page.getPageWorkflows() == null) {
+            throw new Exception(
+                  "WorkflowManager returned null page of workflows");
+         }
+         for (WorkflowInstance inst : (List<WorkflowInstance>) page
+               .getPageWorkflows()) {
+            printer.println("Instance: [id=" + inst.getId() + ", status="
+                  + inst.getStatus() + ", currentTask="
+                  + inst.getCurrentTaskId() + ", workflow="
+                  + inst.getWorkflow().getName() + ",wallClockTime="
+                  + client.getWorkflowWallClockMinutes(inst.getId())
+                  + ",currentTaskWallClockTime="
+                  + client.getWorkflowCurrentTaskWallClockMinutes(inst.getId())
+                  + "]");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get next page of workflows for page '" + pageNum
+                     + "' and status '" + status + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setPageNum(int pageNum) {
+      this.pageNum = pageNum;
+   }
+
+   public void setStatus(String status) {
+      this.status = status;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetPrevPageCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetPrevPageCliAction.java
new file mode 100644
index 0000000..cbc0dd9
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetPrevPageCliAction.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+
+/**
+ * A {@link CmdLineAction} which gets the previous page of workflows.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetPrevPageCliAction extends WorkflowCliAction {
+
+   private int pageNum = -1;
+   private String status;
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      Validate.isTrue(pageNum != -1);
+
+      try {
+         XmlRpcWorkflowManagerClient client = getClient();
+         WorkflowInstancePage page = null;
+         if (status != null && !status.equals("")) {
+            page = client.paginateWorkflowInstances(pageNum - 1, status);
+         } else {
+            page = client.paginateWorkflowInstances(pageNum - 1);
+         }
+
+         printer.println("Page: [num=" + page.getPageNum() + ","
+               + "pageSize=" + page.getPageSize() + ",totalPages="
+               + page.getTotalPages() + "]");
+         if (page.getPageWorkflows() == null) {
+            throw new Exception(
+                  "WorkflowManager returned null page of workflows");
+         }
+         for (WorkflowInstance inst : (List<WorkflowInstance>) page
+               .getPageWorkflows()) {
+            printer.println("Instance: [id=" + inst.getId() + ", status="
+                  + inst.getStatus() + ", currentTask="
+                  + inst.getCurrentTaskId() + ", workflow="
+                  + inst.getWorkflow().getName() + ",wallClockTime="
+                  + client.getWorkflowWallClockMinutes(inst.getId())
+                  + ",currentTaskWallClockTime="
+                  + client.getWorkflowCurrentTaskWallClockMinutes(inst.getId())
+                  + "]");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get previous page of workflows for " + "pageNum '"
+                     + pageNum + "' and status '" + status + "' : "
+                     + e.getMessage(), e);
+      }
+   }
+
+   public void setPageNum(int pageNum) {
+      this.pageNum = pageNum;
+   }
+
+   public void setStatus(String status) {
+      this.status = status;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetRegisteredEventsCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetRegisteredEventsCliAction.java
new file mode 100644
index 0000000..8a3fab3
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetRegisteredEventsCliAction.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which gets a list of registered events.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetRegisteredEventsCliAction extends WorkflowCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         @SuppressWarnings("unchecked")
+         List<String> events = getClient().getRegisteredEvents();
+
+         if (events == null) {
+            throw new Exception("WorkflowManager returned null event list");
+         }
+         for (String event : events) {
+            printer.println("Event: [name=" + event + "]");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to get registered events : "
+               + e.getMessage(), e);
+      }
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetTaskByIdCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetTaskByIdCliAction.java
new file mode 100644
index 0000000..f64bc44
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetTaskByIdCliAction.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+
+/**
+ * A {@link CmdLineAction} which retrieves WorkflowTask information for
+ * WorkflowTask with given task ID.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class GetTaskByIdCliAction extends WorkflowCliAction {
+
+   private String taskId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         WorkflowTask task = getClient().getTaskById(taskId);
+         printer.println("Task: [id=" + task.getTaskId() + ", name="
+               + task.getTaskName() + ", order=" + task.getOrder() + ", class="
+               + task.getClass().getName() + ", numConditions="
+               + task.getConditions().size() + ", configuration="
+               + task.getTaskConfig().getProperties() + "]");
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get task by id for taskId '" + taskId + "' : "
+                     + e.getMessage(), e);
+      }
+   }
+
+   public void setTaskId(String taskId) {
+      this.taskId = taskId;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetTaskWallClockTimeCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetTaskWallClockTimeCliAction.java
new file mode 100644
index 0000000..6eeed79
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetTaskWallClockTimeCliAction.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which get a workflow instance's current task's wall
+ * clock time.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetTaskWallClockTimeCliAction extends WorkflowCliAction {
+
+   private String instanceId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         double wallClockTime = getClient()
+               .getWorkflowCurrentTaskWallClockMinutes(instanceId);
+         printer.println(wallClockTime + " minutes");
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get current workflow instance's "
+                     + "currents tasks wall clock time : " + e.getMessage(), e);
+      }
+   }
+
+   public void setInstanceId(String instanceId) {
+      this.instanceId = instanceId;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWallClockTimeCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWallClockTimeCliAction.java
new file mode 100644
index 0000000..ba923c2
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWallClockTimeCliAction.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which gets Wall Clock Time for a given workflow
+ * instance.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetWallClockTimeCliAction extends WorkflowCliAction {
+
+   private String instanceId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         double wallClockTime = getClient().getWorkflowWallClockMinutes(
+               instanceId);
+         printer.println(wallClockTime + " minutes");
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get wall clock time for instance '" + instanceId
+                     + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setInstanceId(String instanceId) {
+      this.instanceId = instanceId;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowByIdCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowByIdCliAction.java
new file mode 100644
index 0000000..11bf0a1
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowByIdCliAction.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+
+/**
+ * A {@link CmdLineAction} which retrieves Workflow information for
+ * Workflow with given workflow ID.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class GetWorkflowByIdCliAction extends WorkflowCliAction {
+
+   private String workflowId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         Workflow workflow = getClient().getWorkflowById(workflowId);
+         printer.println("Workflow: [id=" + workflow.getId() + ", name="
+               + workflow.getName() + ", numTasks="
+               + workflow.getTasks().size() + "]");
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get workflow information for" + " workflowId '"
+                     + workflowId + "' : " + e.getMessage(), e);
+      }   
+   }
+
+   public void setWorkflowId(String workflowId) {
+      this.workflowId = workflowId;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowInstCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowInstCliAction.java
new file mode 100644
index 0000000..fdd6495
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowInstCliAction.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+
+/**
+ * A {@link CmdLineAction} which get WorkflowInstance information by given
+ * instanceId.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class GetWorkflowInstCliAction extends WorkflowCliAction {
+
+   private String instanceId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         XmlRpcWorkflowManagerClient client = getClient();
+         WorkflowInstance inst = client.getWorkflowInstanceById(instanceId);
+         if (inst == null) {
+            throw new Exception(
+                  "WorkflowManager returned null workflow instance");
+         }
+         printer.println("Instance: [id=" + inst.getId() + ", status="
+               + inst.getStatus() + ", currentTask=" + inst.getCurrentTaskId()
+               + ", workflow=" + inst.getWorkflow().getName()
+               + ",wallClockTime="
+               + client.getWorkflowWallClockMinutes(inst.getId())
+               + ",currentTaskWallClockTime="
+               + client.getWorkflowCurrentTaskWallClockMinutes(inst.getId())
+               + "]");
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get workflow instance information for"
+                     + " instanceId '" + instanceId + "' : " + e.getMessage(),
+               e);
+      }
+   }
+
+   public void setInstanceId(String instanceId) {
+      this.instanceId = instanceId;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowInstMetCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowInstMetCliAction.java
new file mode 100644
index 0000000..0f18d29
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowInstMetCliAction.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * A {@link CmdLineAction} which get workflow instance metadata.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetWorkflowInstMetCliAction extends WorkflowCliAction {
+
+   private String instanceId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      Validate.notNull(instanceId);
+
+      try {
+         Metadata met = getClient().getWorkflowInstanceMetadata(instanceId);
+         printer.println("[id=" + instanceId + ", met=" + met.getHashtable()
+               + "]");
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get metadata for workflow instance '" + instanceId
+                     + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setInstanceId(String instanceId) {
+      this.instanceId = instanceId;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowInstsCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowInstsCliAction.java
new file mode 100644
index 0000000..59b572a
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowInstsCliAction.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+
+/**
+ * A {@link CmdLineAction} which lists workflow instances current managed by
+ * workflow manager at given URL.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetWorkflowInstsCliAction extends WorkflowCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+
+      try {
+         XmlRpcWorkflowManagerClient client = getClient();
+         @SuppressWarnings("unchecked")
+         List<WorkflowInstance> insts = client.getWorkflowInstances();
+
+         if (insts == null) {
+            throw new Exception(
+                  "WorkflowManager return null workflow instances list");
+         }
+         for (WorkflowInstance inst : insts) {
+            printer.println("Instance: [id="
+                  + inst.getId()
+                  + ", status="
+                  + inst.getStatus()
+                  + ", currentTask="
+                  + inst.getCurrentTaskId()
+                  + ", workflow="
+                  + inst.getWorkflow().getName()
+                  + ",wallClockTime="
+                  + client.getWorkflowWallClockMinutes(inst.getId())
+                  + ",currentTaskWallClockTime="
+                  + client.getWorkflowCurrentTaskWallClockMinutes(inst
+                        .getId()) + "]");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get workflow instances from URL '" + getUrl()
+                     + "' : " + e.getMessage(), e);
+      }
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowsByEventCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowsByEventCliAction.java
new file mode 100644
index 0000000..147f224
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowsByEventCliAction.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+
+/**
+ * A {@link CmdLineAction} which get the current list of workflows by
+ * event name
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class GetWorkflowsByEventCliAction extends WorkflowCliAction {
+
+   private String eventName;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         @SuppressWarnings("unchecked")
+         List<Workflow> workflows = getClient().getWorkflowsByEvent(eventName);
+
+         if (workflows == null) {
+            throw new Exception("WorkflowManager returned null workflow list");
+         }
+         for (Workflow workflow : workflows) {
+            printer.println("Workflow: [id=" + workflow.getId() + ", name="
+                  + workflow.getName() + ", numTasks="
+                  + workflow.getTasks().size() + "]");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get workflows by event name '" + eventName + "' : "
+                     + e.getMessage(), e);
+      }
+   }
+
+   public void setEventName(String eventName) {
+      this.eventName = eventName;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowsCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowsCliAction.java
new file mode 100644
index 0000000..28a1315
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/GetWorkflowsCliAction.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+
+/**
+ * A {@link CmdLineAction} which get list of know workflow models from
+ * WorkflowManager at given URL.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class GetWorkflowsCliAction extends WorkflowCliAction {
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         @SuppressWarnings("unchecked")
+         List<Workflow> workflows = getClient().getWorkflows();
+
+         if (workflows == null) {
+            throw new Exception(
+                  "WorkflowManager returned null list of Workflows");
+         }
+
+         for (Workflow workflow : workflows) {
+            printer.println("Workflow: [id=" + workflow.getId() + ", name="
+                  + workflow.getName() + ", numTasks="
+                  + workflow.getTasks().size() + "]");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException(
+               "Failed to get list of workflow models from url '" + getUrl()
+                     + "' : " + e.getMessage(), e);
+      }
+   }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/PauseWorkflowInstCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/PauseWorkflowInstCliAction.java
new file mode 100644
index 0000000..dcc4aaf
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/PauseWorkflowInstCliAction.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which stops a workflow instance.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class PauseWorkflowInstCliAction extends WorkflowCliAction {
+
+   private String instanceId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         if (getClient().pauseWorkflowInstance(instanceId)) {
+            printer.println("Successfully paused workflow '" + instanceId
+                  + "'");
+         } else {
+            throw new Exception("Paused workflow returned false");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to pause workflow '"
+               + instanceId + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setInstanceId(String instanceId) {
+      this.instanceId = instanceId;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/ResumeWorkflowInstCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/ResumeWorkflowInstCliAction.java
new file mode 100644
index 0000000..a3c869b
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/ResumeWorkflowInstCliAction.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which resumes a paused workflow instance.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class ResumeWorkflowInstCliAction extends WorkflowCliAction {
+
+   private String instanceId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         if (getClient().resumeWorkflowInstance(instanceId)) {
+            printer.println("Successfully resumed workflow '" + instanceId
+                  + "'");
+         } else {
+            throw new Exception("Resume workflow returned false");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to resume workflow '"
+               + instanceId + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setInstanceId(String instanceId) {
+      this.instanceId = instanceId;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/SendEventCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/SendEventCliAction.java
new file mode 100644
index 0000000..a9793c1
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/SendEventCliAction.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//JDK imports
+import java.util.List;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * A {@link CmdLineAction} which triggers a workflow event.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class SendEventCliAction extends WorkflowCliAction {
+
+   private String eventName;
+   private Metadata metadata;
+
+   public SendEventCliAction() {
+      metadata = new Metadata();
+   }
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      Validate.notNull(eventName, "Must specify eventName");
+
+      try {
+         printer.print("Sending event '" + eventName + "'... ");
+         printer.println(getClient().sendEvent(eventName, metadata) ?
+               "SUCCESS" : "FAILURE");
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to send event '" + eventName
+               + "' to url '" + getUrl() + "' with metadata '"
+               + metadata.getHashtable() + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setEventName(String eventName) {
+      this.eventName = eventName;
+   }
+
+   public String getEventName() {
+      return eventName;
+   }
+
+   public void addMetadata(List<String> metadata) {
+      Validate.isTrue(metadata.size() > 1);
+
+      this.metadata.addMetadata(metadata.get(0),
+            metadata.subList(1, metadata.size()));
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/StopWorkflowInstCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/StopWorkflowInstCliAction.java
new file mode 100644
index 0000000..ab2b945
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/StopWorkflowInstCliAction.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//OODT imports
+import org.apache.oodt.cas.cli.exception.CmdLineActionException;
+
+/**
+ * A {@link CmdLineAction} which stops a workflow instance.
+ * 
+ * @author bfoster (Brian Foster)
+ */
+public class StopWorkflowInstCliAction extends WorkflowCliAction {
+
+   private String instanceId;
+
+   @Override
+   public void execute(ActionMessagePrinter printer)
+         throws CmdLineActionException {
+      try {
+         if (getClient().stopWorkflowInstance(instanceId)) {
+            printer.println("Successfully stopped workflow '" + instanceId
+                  + "'");
+         } else {
+            throw new Exception("Stop workflow returned false");
+         }
+      } catch (Exception e) {
+         throw new CmdLineActionException("Failed to stop workflow '"
+               + instanceId + "' : " + e.getMessage(), e);
+      }
+   }
+
+   public void setInstanceId(String instanceId) {
+      this.instanceId = instanceId;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/WorkflowCliAction.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/WorkflowCliAction.java
new file mode 100644
index 0000000..7c5a51b
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/cli/action/WorkflowCliAction.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli.action;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+
+//Apache imports
+import org.apache.commons.lang.Validate;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+
+/**
+ * Base {@link CmdLineAction} for Workflow Manager.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public abstract class WorkflowCliAction extends CmdLineAction {
+
+   private XmlRpcWorkflowManagerClient client;
+
+   public String getUrl() {
+      return System.getProperty("org.apache.oodt.cas.workflow.url");
+   }
+
+   protected XmlRpcWorkflowManagerClient getClient()
+         throws MalformedURLException {
+      Validate.notNull(getUrl());
+
+      if (client != null) {
+         return client;
+      } else {
+         return new XmlRpcWorkflowManagerClient(new URL(getUrl()));
+      }
+   }
+
+   public void setClient(XmlRpcWorkflowManagerClient client) {
+      this.client = client;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/ChangeType.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/ChangeType.java
new file mode 100755
index 0000000..bf70c62
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/ChangeType.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.engine;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * Different Listener Message Categories
+ * <p>
+ */
+public class ChangeType {
+
+	public static final ChangeType STATE = new ChangeType("State");
+	public static final ChangeType DYN_MET = new ChangeType("DynamicMetadata");
+	public static final ChangeType STATIC_MET = new ChangeType("StaticMetadata");
+	public static final ChangeType LISTENERS = new ChangeType("Listeners");
+	public static final ChangeType PRIORITY = new ChangeType("Priority");
+	public static final ChangeType EXCUSED_WPS = new ChangeType("ExcusedWorkflowProcessors");
+
+	private String name;
+	
+	public ChangeType(String name) {
+		this.name = name;
+	}
+	
+	public String getName() {
+		return this.name;
+	}
+	
+	public boolean equals(Object obj) {
+		if (obj instanceof ChangeType) {
+			return this.name.equals(((ChangeType) obj).name);
+		}else {
+			return false;
+		}
+	}
+	
+	public int hashCode() {
+		return this.getName().hashCode();
+	}
+	
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/IterativeWorkflowProcessorThread.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/IterativeWorkflowProcessorThread.java
new file mode 100644
index 0000000..7385d40
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/IterativeWorkflowProcessorThread.java
@@ -0,0 +1,592 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+import org.apache.oodt.cas.resource.system.XmlRpcResourceManagerClient;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.metadata.CoreMetKeys;
+import org.apache.oodt.cas.workflow.structs.TaskJobInput;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowStatus;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionInstance;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+import org.apache.oodt.cas.workflow.util.GenericWorkflowObjectFactory;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.commons.util.DateConvert;
+
+//JDK imports
+import java.net.InetAddress;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * An instance of the {@link WorkflowProcessorThread} that processes through an
+ * iterative {@link WorkflowInstance}. This class keeps an <code>Iterator</code>
+ * that allows it to move from one end of a sequential {@link Workflow}
+ * processing pipeline to another. This class should only be used to process
+ * science pipeline style {@link Workflow}s, i.e., those which resemble an
+ * iterative processing pipelines, with no forks, or concurrent task executions.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+
+public class IterativeWorkflowProcessorThread implements WorkflowStatus,
+    CoreMetKeys, Runnable {
+
+  /* the default queue name if we're using resmgr job submission */
+  private static final String DEFAULT_QUEUE_NAME = "high";
+
+  /* an iterator representing the current task that we are on in the workflow */
+  private Iterator taskIterator = null;
+
+  /* the workflow instance that this processor thread is processing */
+  private WorkflowInstance workflowInst = null;
+
+  /* should our workflow processor thread start running? */
+  private boolean running = false;
+
+  /*
+   * the amount of seconds to wait inbetween checking for task pre-condition
+   * satisfaction
+   */
+  private long waitForConditionSatisfy = -1;
+
+  /* our instance repository used to persist workflow instance info */
+  private WorkflowInstanceRepository instanceRepository = null;
+
+  /*
+   * our client to a resource manager: if null, local task execution will be
+   * performed
+   */
+  private XmlRpcResourceManagerClient rClient = null;
+
+  /* polling wait for res mgr */
+  private long pollingWaitTime = 10L;
+
+  /*
+   * should our workflow processor thread pause, and not move onto the next
+   * task?
+   */
+  private boolean pause = false;
+
+  /* our log stream */
+  private static Logger LOG = Logger
+      .getLogger(IterativeWorkflowProcessorThread.class.getName());
+
+  private Map CONDITION_CACHE = new HashMap();
+
+  /* the parent workflow manager url that executed this processor thread */
+  private URL wmgrParentUrl = null;
+
+  /* the currently executing jobId if we're using the resource manager */
+  private String currentJobId = null;
+
+  public IterativeWorkflowProcessorThread(WorkflowInstance wInst,
+      WorkflowInstanceRepository instRep, URL wParentUrl) {
+    workflowInst = wInst;
+    taskIterator = workflowInst.getWorkflow().getTasks().iterator();
+    this.instanceRepository = instRep;
+
+    /* start out the gates running */
+    running = true;
+
+    /*
+     * get the amount of wait time inbetween checking for task pre-condition
+     * satisfaction
+     */
+    waitForConditionSatisfy = Long.getLong(
+        "org.apache.oodt.cas.workflow.engine.preConditionWaitTime", 10)
+        .longValue();
+
+    pollingWaitTime = Long.getLong(
+        "org.apache.oodt.cas.workflow.engine.resourcemgr.pollingWaitTime", 10)
+        .longValue();
+
+    wmgrParentUrl = wParentUrl;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see java.lang.Runnable#run()
+   */
+  public void run() {
+    /*
+     * okay, we got into the run method, mark the start date time for the
+     * workflow instance here
+     */
+    String startDateTimeIsoStr = DateConvert.isoFormat(new Date());
+    workflowInst.setStartDateTimeIsoStr(startDateTimeIsoStr);
+    // persist it
+    persistWorkflowInstance();
+
+    while (running && taskIterator.hasNext()) {
+      if (pause) {
+        LOG.log(Level.FINE,
+            "IterativeWorkflowProcessorThread: Skipping execution: Paused: CurrentTask: "
+                + getTaskNameById(workflowInst.getCurrentTaskId()));
+        continue;
+      }
+
+      WorkflowTask task = (WorkflowTask) taskIterator.next();
+      workflowInst.setCurrentTaskId(task.getTaskId());
+
+      // now persist it
+      persistWorkflowInstance();
+
+      // check to see if req met fields are present
+      // if they aren't, set the status to METERROR, and then fail
+      if (!checkTaskRequiredMetadata(task, this.workflowInst.getSharedContext())) {
+        this.workflowInst.setStatus(METADATA_MISSING);
+        persistWorkflowInstance();
+        // now break out of this run loop
+        return;
+      }
+
+      // this is where the pre-conditions come in
+      // only execute the below code when it's passed all of its
+      // pre-conditions
+      if (task.getConditions() != null) {
+        while (!satisfied(task.getConditions(), task.getTaskId())
+            && !isStopped()) {
+
+          // if we're not paused, go ahead and pause us now
+          if (!isPaused()) {
+            pause();
+          }
+
+          LOG.log(Level.FINEST,
+              "Pre-conditions for task: " + task.getTaskName()
+                  + " unsatisfied: waiting: " + waitForConditionSatisfy
+                  + " seconds before checking again.");
+          try {
+            Thread.currentThread().sleep(waitForConditionSatisfy * 1000);
+          } catch (InterruptedException ignore) {
+          }
+
+          // check to see if we've been resumed, if so, break
+          // the loop and start
+          if (!isPaused()) {
+            break;
+          }
+        }
+
+        // check to see if we've been killed
+        if (isStopped()) {
+          break;
+        }
+
+        // un pause us (if needed)
+        if (isPaused()) {
+          resume();
+        }
+      }
+
+      // task execution
+      LOG.log(
+          Level.FINEST,
+          "IterativeWorkflowProcessorThread: Executing task: "
+              + task.getTaskName());
+
+      WorkflowTaskInstance taskInstance = GenericWorkflowObjectFactory
+          .getTaskObjectFromClassName(task.getTaskInstanceClassName());
+      // add the TaskId and the JobId and ProcessingNode
+      // TODO: unfake the JobId
+      workflowInst.getSharedContext()
+          .replaceMetadata(TASK_ID, task.getTaskId());
+      workflowInst.getSharedContext().replaceMetadata(WORKFLOW_INST_ID,
+          workflowInst.getId());
+      workflowInst.getSharedContext().replaceMetadata(JOB_ID,
+          workflowInst.getId());
+      workflowInst.getSharedContext().replaceMetadata(PROCESSING_NODE,
+          getHostname());
+      workflowInst.getSharedContext().replaceMetadata(WORKFLOW_MANAGER_URL,
+          this.wmgrParentUrl.toString());
+
+      if (rClient != null) {
+        // build up the Job
+        // and the Job Input
+        Job taskJob = new Job();
+        taskJob.setName(task.getTaskId());
+        taskJob
+            .setJobInstanceClassName("org.apache.oodt.cas.workflow.structs.TaskJob");
+        taskJob
+            .setJobInputClassName("org.apache.oodt.cas.workflow.structs.TaskJobInput");
+        taskJob.setLoadValue(task.getTaskConfig().getProperty(TASK_LOAD) != null ? 
+            Integer.parseInt(task.getTaskConfig().getProperty(TASK_LOAD)):new Integer(2));
+        taskJob
+            .setQueueName(task.getTaskConfig().getProperty(QUEUE_NAME) != null ? task
+                .getTaskConfig().getProperty(QUEUE_NAME) : DEFAULT_QUEUE_NAME);
+
+        TaskJobInput in = new TaskJobInput();
+        in.setDynMetadata(workflowInst.getSharedContext());
+        in.setTaskConfig(task.getTaskConfig());
+        in.setWorkflowTaskInstanceClassName(task.getTaskInstanceClassName());
+
+        workflowInst.setStatus(RESMGR_SUBMIT);
+        persistWorkflowInstance();
+
+        try {
+          // this is * NOT * a blocking operation so when it returns
+          // the job may not actually have finished executing
+          // so we go into a waiting/sleep behavior using the passed
+          // back job id to wait until the job has actually finished
+          // executing
+
+          this.currentJobId = rClient.submitJob(taskJob, in);
+
+          while (!safeCheckJobComplete(this.currentJobId) && !isStopped()) {
+            // sleep for 5 seconds then come back
+            // and check again
+            try {
+              Thread.currentThread().sleep(pollingWaitTime * 1000);
+            } catch (InterruptedException ignore) {
+            }
+          }
+
+          // okay job is done: TODO: fix this hack
+          // the task update time was set remotely
+          // by remote task, so let's read it now
+          // from the instRepo (which will have the updated
+          // time)
+
+          if (isStopped()) {
+            // this means that this workflow was killed, so
+            // gracefully exit
+            break;
+          }
+
+          WorkflowInstance updatedInst = null;
+          try {
+            updatedInst = instanceRepository
+                .getWorkflowInstanceById(workflowInst.getId());
+            workflowInst = updatedInst;
+          } catch (InstanceRepositoryException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Unable to get " + "updated workflow "
+                + "instance record " + "when executing remote job: Message: "
+                + e.getMessage());
+          }
+
+        } catch (JobExecutionException e) {
+          LOG.log(Level.WARNING,
+              "Job execution exception using resource manager to execute job: Message: "
+                  + e.getMessage());
+        }
+      } else {
+        // we started, so mark it
+        workflowInst.setStatus(STARTED);
+        // go ahead and persist the workflow instance, after we
+        // save the current task start date time
+        String currentTaskIsoStartDateTimeStr = DateConvert
+            .isoFormat(new Date());
+        workflowInst
+            .setCurrentTaskStartDateTimeIsoStr(currentTaskIsoStartDateTimeStr);
+        workflowInst.setCurrentTaskEndDateTimeIsoStr(null); /*
+                                                             * clear this out
+                                                             * until it's ready
+                                                             */
+        persistWorkflowInstance();
+        executeTaskLocally(taskInstance, workflowInst.getSharedContext(),
+            task.getTaskConfig(), task.getTaskName());
+        String currentTaskIsoEndDateTimeStr = DateConvert.isoFormat(new Date());
+        workflowInst
+            .setCurrentTaskEndDateTimeIsoStr(currentTaskIsoEndDateTimeStr);
+        persistWorkflowInstance();
+      }
+
+      LOG.log(
+          Level.FINEST,
+          "IterativeWorkflowProcessorThread: Completed task: "
+              + task.getTaskName());
+
+    }
+
+    LOG.log(Level.FINEST,
+        "IterativeWorkflowProcessorThread: Completed workflow: "
+            + workflowInst.getWorkflow().getName());
+    if (!isStopped()) {
+      stop();
+    }
+
+  }
+
+  public WorkflowInstance getWorkflowInstance() {
+    return workflowInst;
+  }
+
+  public synchronized void stop() {
+    running = false;
+    // if the resource manager is active
+    // then kill the current job there
+    if (this.rClient != null && this.currentJobId != null) {
+      if (!this.rClient.killJob(this.currentJobId)) {
+        LOG.log(Level.WARNING, "Attempt to kill " + "current resmgr job: ["
+            + this.currentJobId + "]: failed");
+      }
+    }
+
+    workflowInst.setStatus(FINISHED);
+    String isoEndDateTimeStr = DateConvert.isoFormat(new Date());
+    workflowInst.setEndDateTimeIsoStr(isoEndDateTimeStr);
+    persistWorkflowInstance();
+  }
+
+  public synchronized void resume() {
+    pause = false;
+    workflowInst.setStatus(STARTED);
+    persistWorkflowInstance();
+  }
+
+  public synchronized void pause() {
+    pause = true;
+    workflowInst.setStatus(PAUSED);
+    persistWorkflowInstance();
+  }
+
+  /**
+   * @return True if the WorkflowInstance managed by this processor is paused.
+   */
+  public boolean isPaused() {
+    return pause == true;
+  }
+
+  public boolean isStopped() {
+    return !running;
+  }
+
+  /**
+   * @return Returns the fCurrentTaskId.
+   */
+  public String getCurrentTaskId() {
+    return workflowInst.getCurrentTaskId();
+  }
+
+  /**
+   * @param workflowInst
+   *          The fWorkflowInst to set.
+   */
+  public void setWorkflowInst(WorkflowInstance workflowInst) {
+    this.workflowInst = workflowInst;
+  }
+
+  /**
+   * @return Returns the waitForConditionSatisfy.
+   */
+  public long getWaitforConditionSatisfy() {
+    return waitForConditionSatisfy;
+  }
+
+  /**
+   * @param waitforConditionSatisfy
+   *          The waitForConditionSatisfy to set.
+   */
+  public void setWaitforConditionSatisfy(long waitforConditionSatisfy) {
+    this.waitForConditionSatisfy = waitforConditionSatisfy;
+  }
+
+  /**
+   * @return the instRep
+   */
+  public WorkflowInstanceRepository getInstanceRepository() {
+    return instanceRepository;
+  }
+
+  /**
+   * @param instRep
+   *          the instRep to set
+   */
+  public void setInstanceRepository(WorkflowInstanceRepository instRep) {
+    this.instanceRepository = instRep;
+  }
+
+  /**
+   * @return the rClient
+   */
+  public XmlRpcResourceManagerClient getRClient() {
+    return rClient;
+  }
+
+  /**
+   * @param client
+   *          the rClient to set
+   */
+  public void setRClient(XmlRpcResourceManagerClient client) {
+    rClient = client;
+    if (rClient != null) {
+      LOG.log(Level.INFO, "Resource Manager Job Submission enabled to: ["
+          + rClient.getResMgrUrl() + "]");
+    }
+  }
+
+  /**
+   * @return the wmgrParentUrl
+   */
+  public URL getWmgrParentUrl() {
+    return wmgrParentUrl;
+  }
+
+  /**
+   * @param wmgrParentUrl
+   *          the wmgrParentUrl to set
+   */
+  public void setWmgrParentUrl(URL wmgrParentUrl) {
+    this.wmgrParentUrl = wmgrParentUrl;
+  }
+
+  private boolean checkTaskRequiredMetadata(WorkflowTask task,
+      Metadata dynMetadata) {
+    if (task.getRequiredMetFields() == null
+        || (task.getRequiredMetFields() != null && task.getRequiredMetFields()
+            .size() == 0)) {
+      LOG.log(Level.INFO, "Task: [" + task.getTaskName()
+          + "] has no required metadata fields");
+      return true; /* no required metadata, so we're fine */
+    }
+
+    for (Iterator i = task.getRequiredMetFields().iterator(); i.hasNext();) {
+      String reqField = (String) i.next();
+      if (!dynMetadata.containsKey(reqField)) {
+        LOG.log(Level.SEVERE, "Checking metadata key: [" + reqField
+            + "] for task: [" + task.getTaskName()
+            + "]: failed: aborting workflow");
+        return false;
+      }
+    }
+
+    LOG.log(Level.INFO, "All required metadata fields present for task: ["
+        + task.getTaskName() + "]");
+
+    return true;
+  }
+
+  private String getTaskNameById(String taskId) {
+    for (Iterator i = workflowInst.getWorkflow().getTasks().iterator(); i
+        .hasNext();) {
+      WorkflowTask task = (WorkflowTask) i.next();
+      if (task.getTaskId().equals(taskId)) {
+        return task.getTaskName();
+      }
+    }
+
+    return null;
+  }
+
+  private boolean satisfied(List conditionList, String taskId) {
+    for (Iterator i = conditionList.iterator(); i.hasNext();) {
+      WorkflowCondition c = (WorkflowCondition) i.next();
+      WorkflowConditionInstance cInst = null;
+
+      // see if we've already cached this condition instance
+      if (CONDITION_CACHE.get(taskId) != null) {
+        HashMap conditionMap = (HashMap) CONDITION_CACHE.get(taskId);
+
+        /*
+         * okay we have some conditions cached for this task, see if we have the
+         * one we need
+         */
+        if (conditionMap.get(c.getConditionId()) != null) {
+          cInst = (WorkflowConditionInstance) conditionMap.get(c
+              .getConditionId());
+        }
+        /* if not, then go ahead and create it and cache it */
+        else {
+          cInst = GenericWorkflowObjectFactory
+              .getConditionObjectFromClassName(c
+                  .getConditionInstanceClassName());
+          conditionMap.put(c.getConditionId(), cInst);
+        }
+      }
+      /* no conditions cached yet, so set everything up */
+      else {
+        HashMap conditionMap = new HashMap();
+        cInst = GenericWorkflowObjectFactory.getConditionObjectFromClassName(c
+            .getConditionInstanceClassName());
+        conditionMap.put(c.getConditionId(), cInst);
+        CONDITION_CACHE.put(taskId, conditionMap);
+      }
+
+      // actually perform the evaluation
+      if (!cInst.evaluate(workflowInst.getSharedContext(), c.getTaskConfig())) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  private String getHostname() {
+    try {
+      // Get hostname by textual representation of IP address
+      InetAddress addr = InetAddress.getLocalHost();
+      // Get the host name
+      String hostname = addr.getHostName();
+      return hostname;
+    } catch (UnknownHostException e) {
+    }
+    return null;
+  }
+
+  private void persistWorkflowInstance() {
+    try {
+      instanceRepository.updateWorkflowInstance(workflowInst);
+    } catch (InstanceRepositoryException e) {
+      LOG.log(Level.WARNING, "Exception persisting workflow instance: ["
+          + workflowInst.getId() + "]: Message: " + e.getMessage());
+    }
+  }
+
+  private void executeTaskLocally(WorkflowTaskInstance instance, Metadata met,
+      WorkflowTaskConfiguration cfg, String taskName) {
+    try {
+      LOG.log(Level.INFO, "Executing task: [" + taskName + "] locally");
+      instance.run(met, cfg);
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Exception executing task: [" + taskName
+          + "] locally: Message: " + e.getMessage());
+    }
+  }
+
+  private boolean safeCheckJobComplete(String jobId) {
+    try {
+      return rClient.isJobComplete(jobId);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Exception checking completion status for job: ["
+          + jobId + "]: Messsage: " + e.getMessage());
+      return false;
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/PrioritizedQueueBasedWorkflowEngine.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/PrioritizedQueueBasedWorkflowEngine.java
new file mode 100644
index 0000000..11ec7b9
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/PrioritizedQueueBasedWorkflowEngine.java
@@ -0,0 +1,264 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine;
+
+//JDK imports
+import java.net.URL;
+import java.util.Calendar;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessorQueue;
+import org.apache.oodt.cas.workflow.engine.runner.EngineRunner;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycle;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowState;
+import org.apache.oodt.cas.workflow.repository.WorkflowRepository;
+import org.apache.oodt.cas.workflow.structs.HighestFIFOPrioritySorter;
+import org.apache.oodt.cas.workflow.structs.ParentChildWorkflow;
+import org.apache.oodt.cas.workflow.structs.Priority;
+import org.apache.oodt.cas.workflow.structs.PrioritySorter;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.exceptions.EngineException;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+
+/**
+ * 
+ * Describe your class here.
+ * 
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class PrioritizedQueueBasedWorkflowEngine implements WorkflowEngine {
+
+  private static final Logger LOG = Logger
+      .getLogger(PrioritizedQueueBasedWorkflowEngine.class.getName());
+  private final Thread queuerThread;
+  private final Thread runnerThread;
+  private final WorkflowInstanceRepository repo;
+  private final WorkflowRepository modelRepo;
+  private final WorkflowLifecycleManager lifecycle;
+  private final PrioritySorter prioritizer;
+  private WorkflowProcessorQueue processorQueue;
+  private URL wmgrUrl;
+  private EngineRunner runner;
+
+  public PrioritizedQueueBasedWorkflowEngine(WorkflowInstanceRepository repo,
+      PrioritySorter prioritizer, WorkflowLifecycleManager lifecycle,
+      EngineRunner runner, WorkflowRepository modelRepo, long querierWaitSeconds) {
+    this.repo = repo;
+    this.prioritizer = prioritizer != null ? new HighestFIFOPrioritySorter(1,
+        50, 1) : prioritizer;
+    this.lifecycle = lifecycle;
+    this.modelRepo = modelRepo;
+    this.processorQueue = new WorkflowProcessorQueue(repo, lifecycle, modelRepo);
+    this.runner = runner;
+    this.runner.setInstanceRepository(repo);
+
+    // Task QUEUER thread
+    TaskQuerier querier = new TaskQuerier(processorQueue, this.prioritizer,
+        this.repo, querierWaitSeconds);
+    queuerThread = new Thread(querier);
+    queuerThread.start();
+
+    // Task Runner thread
+    runnerThread = new Thread(new TaskRunner(querier, runner));
+    runnerThread.start();
+
+  }
+
+  public void setEngineRunner(EngineRunner runner) {
+    this.runner = runner;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#startWorkflow(org.apache
+   * .oodt.cas.workflow.structs.Workflow, org.apache.oodt.cas.metadata.Metadata)
+   */
+  @Override
+  public WorkflowInstance startWorkflow(Workflow workflow, Metadata metadata)
+      throws EngineException {
+    // TODO Auto-generated method stub
+
+    // looks like the work to do here is
+    // create a new WorkflowInstance
+    // create a new WorkflowProcessor around it
+    // set it in Queued status
+    // commit it to workflow instance repo and it will get picked up
+
+    WorkflowInstance inst = new WorkflowInstance();
+    inst.setParentChildWorkflow(workflow instanceof ParentChildWorkflow ? (ParentChildWorkflow) workflow
+        : new ParentChildWorkflow(workflow));
+    inst.setStartDate(Calendar.getInstance().getTime());
+    inst.setCurrentTaskId(workflow.getTasks().get(0).getTaskId());
+    inst.setSharedContext(metadata);
+    inst.setPriority(Priority.getDefault()); // FIXME: this should be sensed or
+                                             // passed in
+    WorkflowLifecycle cycle = getLifecycleForWorkflow(workflow);
+    WorkflowState state = cycle.createState("Null", "initial",
+        "Workflow created by Engine.");
+    inst.setState(state);
+    persist(inst);
+    return inst;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#stopWorkflow(java.lang
+   * .String)
+   */
+  @Override
+  public void stopWorkflow(String workflowInstId) {
+    // TODO Auto-generated method stub
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#pauseWorkflowInstance
+   * (java.lang.String)
+   */
+  @Override
+  public void pauseWorkflowInstance(String workflowInstId) {
+    // TODO Auto-generated method stub
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#resumeWorkflowInstance
+   * (java.lang.String)
+   */
+  @Override
+  public void resumeWorkflowInstance(String workflowInstId) {
+    // TODO Auto-generated method stub
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#getInstanceRepository()
+   */
+  @Override
+  public WorkflowInstanceRepository getInstanceRepository() {
+    return this.repo;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#updateMetadata(java.
+   * lang.String, org.apache.oodt.cas.metadata.Metadata)
+   */
+  @Override
+  public boolean updateMetadata(String workflowInstId, Metadata met) {
+    // TODO Auto-generated method stub
+    return false;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#setWorkflowManagerUrl
+   * (java.net.URL)
+   */
+  @Override
+  public void setWorkflowManagerUrl(URL url) {
+    this.wmgrUrl = url;
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#getWallClockMinutes(
+   * java.lang.String)
+   */
+  @Override
+  public double getWallClockMinutes(String workflowInstId) {
+    // TODO Auto-generated method stub
+    return 0;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.engine.WorkflowEngine#
+   * getCurrentTaskWallClockMinutes(java.lang.String)
+   */
+  @Override
+  public double getCurrentTaskWallClockMinutes(String workflowInstId) {
+    // TODO Auto-generated method stub
+    return 0;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#getWorkflowInstanceMetadata
+   * (java.lang.String)
+   */
+  @Override
+  public Metadata getWorkflowInstanceMetadata(String workflowInstId) {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  private synchronized void persist(WorkflowInstance inst) throws EngineException {
+    try {
+      if (inst.getId() == null
+          || (inst.getId() != null && inst.getId().equals(""))) {
+        // we have to persist it by adding it
+        // rather than updating it
+        repo.addWorkflowInstance(inst);
+      } else {
+        // persist by update
+        repo.updateWorkflowInstance(inst);
+      }
+    } catch (InstanceRepositoryException e) {
+      e.printStackTrace();
+      throw new EngineException(e.getMessage());
+    }
+  }
+
+  private WorkflowLifecycle getLifecycleForWorkflow(Workflow workflow) {
+    return lifecycle.getLifecycleForWorkflow(workflow) != null ? lifecycle
+        .getLifecycleForWorkflow(workflow) : lifecycle.getDefaultLifecycle();
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/PrioritizedQueueBasedWorkflowEngineFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/PrioritizedQueueBasedWorkflowEngineFactory.java
new file mode 100644
index 0000000..99b5725
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/PrioritizedQueueBasedWorkflowEngineFactory.java
@@ -0,0 +1,107 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.workflow.engine.runner.EngineRunner;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+import org.apache.oodt.cas.workflow.repository.WorkflowRepository;
+import org.apache.oodt.cas.workflow.structs.PrioritySorter;
+import org.apache.oodt.cas.workflow.util.GenericWorkflowObjectFactory;
+
+/**
+ * 
+ * Constructs an instance of the {@link PrioritizedQueueBasedWorkflowEngine},
+ * based on its constituent instance repository, workflow task prioritizer,
+ * workflow lifecycle, and engine runner.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PrioritizedQueueBasedWorkflowEngineFactory implements
+    WorkflowEngineFactory {
+
+  private static final String MODEL_REPO_FACTORY_PROPERTY = "workflow.repo.factory";
+
+  private static final String INSTANCE_REPO_FACTORY_PROPERTY = "workflow.engine.instanceRep.factory";
+
+  private static final String PRIORITIZER_CLASS_PROPERTY = "org.apache.oodt.cas.workflow.wengine.prioritizer";
+
+  private static final String LIFECYCLES_FILE_PATH_PROPERTY = "org.apache.oodt.cas.workflow.lifecycle.filePath";
+
+  private static final String ENGINE_RUNNER_CLASS = "workflow.wengine.runner.factory";
+
+  private static final String WAIT_SECS_PROPERTY = "org.apache.oodt.cas.workflow.wengine.taskquerier.waitSeconds";
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngineFactory#createWorkflowEngine
+   * ()
+   */
+  @Override
+  public WorkflowEngine createWorkflowEngine() {
+    try {
+      return new PrioritizedQueueBasedWorkflowEngine(
+          getWorkflowInstanceRepository(), getPrioritizer(),
+          getWorkflowLifecycle(), getEngineRunner(), getModelRepository(),
+          getWaitSeconds());
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  protected WorkflowRepository getModelRepository() {
+    return GenericWorkflowObjectFactory
+        .getWorkflowRepositoryFromClassName(System
+            .getProperty(MODEL_REPO_FACTORY_PROPERTY));
+  }
+
+  protected long getWaitSeconds() {
+    return Long.getLong(WAIT_SECS_PROPERTY, 2);
+  }
+
+  protected EngineRunner getEngineRunner() {
+    return GenericWorkflowObjectFactory.getEngineRunnerFromClassName(System
+        .getProperty(ENGINE_RUNNER_CLASS));
+  }
+
+  protected WorkflowLifecycleManager getWorkflowLifecycle()
+      throws InstantiationException {
+    return new WorkflowLifecycleManager(PathUtils.replaceEnvVariables(System
+        .getProperty(LIFECYCLES_FILE_PATH_PROPERTY)));
+  }
+
+  protected PrioritySorter getPrioritizer() {
+    return GenericWorkflowObjectFactory.getPrioritySorterFromClassName(System
+        .getProperty(PRIORITIZER_CLASS_PROPERTY));
+
+  }
+
+  protected WorkflowInstanceRepository getWorkflowInstanceRepository() {
+    return GenericWorkflowObjectFactory
+        .getWorkflowInstanceRepositoryFromClassName(System
+            .getProperty(INSTANCE_REPO_FACTORY_PROPERTY));
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/TaskQuerier.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/TaskQuerier.java
new file mode 100644
index 0000000..c745b8d
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/TaskQuerier.java
@@ -0,0 +1,220 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.processor.TaskProcessor;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessorHelper;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessorQueue;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycle;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowState;
+import org.apache.oodt.cas.workflow.structs.PrioritySorter;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+
+/**
+ * 
+ * The purpose of this class is to constantly pop off tasks that are run to run
+ * and made available by the {@link WorkflowProcessorQueue}, and then to set
+ * their state to Executing (running Category), so they will be picked up on the
+ * next WorkflowState change, and end up executing.
+ * 
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class TaskQuerier implements Runnable {
+
+  private boolean running;
+
+  private WorkflowProcessorQueue processorQueue;
+
+  private List<WorkflowProcessor> runnableProcessors;
+
+  private PrioritySorter prioritizer;
+
+  private WorkflowInstanceRepository repo;
+  
+  private long waitSeconds;
+
+  private static final Logger LOG = Logger.getLogger(TaskQuerier.class
+      .getName());
+
+  /**
+   * Constructs a new TaskQuerier with the given {@link WorkflowProcessorQueue},
+   * and with the associated {@link PrioritySorter} which acts as a sorter of
+   * the runnable {@link WorkflowProcessor}s.
+   * 
+   * @param processorQueue
+   *          The associated set of queued Workflow Tasks.
+   * @param prioritizer
+   *          The prioritizer to use to sort the ready-to-run Workflow Tasks.
+   * 
+   * @param repo
+   *          The {@link WorkflowInstanceRepository} to save the state of
+   *          WorkflowInstances.
+   *          
+   * @param waitSeconds The default amount of seconds to wait while dispositioning
+   *        processors
+   */
+  public TaskQuerier(WorkflowProcessorQueue processorQueue,
+      PrioritySorter prioritizer, WorkflowInstanceRepository repo, long waitSeconds) {
+    this.running = true;
+    this.processorQueue = processorQueue;
+    this.runnableProcessors = new Vector<WorkflowProcessor>();
+    this.prioritizer = prioritizer;
+    this.repo = repo;
+    this.waitSeconds = waitSeconds;
+  }
+
+  /**
+   * Marches through the set of processors that are currently in the Processor
+   * queue, checks to see if they are NOT in the done state, or if they are
+   * currently in the holding state. If either of those are true, the processor
+   * is popped off the queue, and then added to the runnableProcessors list (in
+   * a synchronized fashion), and then their state is set to Executing
+   * (category, running).
+   * 
+   * Finally the runnableProcessors list is sorted according to the given
+   * {@link #prioritizer}.
+   */
+  public void run() {
+    LOG.log(Level.FINE, "TaskQuerier configured with wait seconds: ["+this.waitSeconds+"]");
+    while (running) {
+      List<WorkflowProcessor> processors = processorQueue.getProcessors();
+      List<WorkflowProcessor> processorsToRun = new Vector<WorkflowProcessor>();
+
+      for (WorkflowProcessor processor : processors) {
+        // OK now get its lifecycle
+        WorkflowProcessorHelper helper = new WorkflowProcessorHelper(
+            processor.getLifecycleManager());
+        WorkflowLifecycle lifecycle = helper
+            .getLifecycleForProcessor(processor);
+
+        LOG.log(Level.FINE, "TaskQuerier: dispositioning processor with id: ["
+            + processor.getWorkflowInstance().getId() + "]: state: "
+            + processor.getWorkflowInstance().getState());
+
+        if (!processor.isAnyCategory("done", "holding")
+            && !processor.isAnyState("Executing")
+            && processor.getRunnableWorkflowProcessors().size() > 0) {
+          for (TaskProcessor tp : processor.getRunnableWorkflowProcessors()) {
+            WorkflowState state = lifecycle.createState("WaitingOnResources",
+                "waiting", "Added to Runnable queue");
+            tp.getWorkflowInstance().setState(state);
+            persist(tp.getWorkflowInstance());
+            LOG.log(Level.INFO, "Added processor with priority: ["
+                + tp.getWorkflowInstance().getPriority() + "]");
+            processorsToRun.add(tp);
+          }
+
+          if (processorsToRun != null && processorsToRun.size() > 1) {
+            prioritizer.sort(processorsToRun);
+          }
+
+          synchronized (runnableProcessors) {
+            if (running)
+              runnableProcessors = processorsToRun;
+          }
+
+        } else {
+          // simply call nextState and persist it
+          LOG.log(Level.FINE, "Processor for workflow instance: ["
+              + processor.getWorkflowInstance().getId()
+              + "] not ready to Execute or already Executing: "
+              + "advancing it to next state.");
+          processor.nextState();
+          persist(processor.getWorkflowInstance());
+        }
+      }
+      
+      try{
+        Thread.currentThread().sleep(waitSeconds*1000);
+      }
+      catch(InterruptedException ignore){}
+      
+    }
+  }
+
+  /**
+   * @return the running
+   */
+  public boolean isRunning() {
+    return running;
+  }
+
+  /**
+   * @param running
+   *          the running to set
+   */
+  public void setRunning(boolean running) {
+    this.running = running;
+  }
+
+  /**
+   * @return the runnableProcessors
+   */
+  public List<WorkflowProcessor> getRunnableProcessors() {
+    return runnableProcessors;
+  }
+
+  /**
+   * Gets the next available {@link TaskProcessor} from the {@link List} of
+   * {@link #runnableProcessors}. Removes that {@link TaskProcessor} from the
+   * actual {@link #runnableProcessors} {@link List}.
+   * 
+   * @return The next available {@link TaskProcessor} from the {@link List} of
+   *         {@link #runnableProcessors}.
+   */
+  public TaskProcessor getNext() {
+    if (getRunnableProcessors().size() == 0)
+      return null;
+    return (TaskProcessor) getRunnableProcessors().remove(0);
+  }
+
+  private synchronized void persist(WorkflowInstance instance) {
+    if (this.repo != null) {
+      try {
+        if (instance.getId() == null
+            || (instance.getId() != null && instance.getId().equals(""))) {
+          // we have to persist it by adding it
+          // rather than updating it
+          repo.addWorkflowInstance(instance);
+        } else {
+          // persist by update
+          repo.updateWorkflowInstance(instance);
+        }
+      } catch (InstanceRepositoryException e) {
+        e.printStackTrace();
+        LOG.log(Level.WARNING, "Unable to update workflow instance: ["
+            + instance.getId() + "] status to [" + instance.getState().getName()
+            + "]. Message: " + e.getMessage());
+      }
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/TaskRunner.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/TaskRunner.java
new file mode 100644
index 0000000..d35cebd
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/TaskRunner.java
@@ -0,0 +1,142 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.processor.TaskProcessor;
+import org.apache.oodt.cas.workflow.engine.runner.EngineRunner;
+import org.apache.oodt.cas.workflow.structs.ParentChildWorkflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+
+/**
+ * 
+ * Implements the TaskRunner framework. Acts as a thread that works with the
+ * TaskQuerier to take the next sorted (aka ones that have been sorted with the
+ * Workflow PrioritySorter) task and then leverage the Engine's Runner to
+ * execute the task.
+ * 
+ * The TaskRunner thread first pops a task off the list using
+ * {@link TaskQuerier#getNext()} and then so long as the thread's
+ * {@link #runner} has open slots as returned by
+ * {@link EngineRunner#hasOpenSlots(WorkflowTask)}, and {@link #isPause()} is
+ * false and {@link #isRunning()} is true, then the task is handed off to the
+ * runner for execution.
+ * 
+ * The TaskRunner thread can be paused during which time it waits
+ * {@link #waitSeconds} seconds, wakes up to see if it's unpaused, and then goes
+ * back to sleep if not, otherwise, resumes executing if it was unpaused.
+ * 
+ * @since Apache OODT 0.5
+ * 
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+// TODO(bfoster): Rename... Runner is missleading.
+public class TaskRunner implements Runnable {
+
+  private boolean running;
+
+  private final TaskQuerier taskQuerier;
+
+  private final EngineRunner runner;
+
+  private static final Logger LOG = Logger
+      .getLogger(TaskRunner.class.getName());
+
+  public TaskRunner(TaskQuerier taskQuerier, EngineRunner runner) {
+    this.running = true;
+    this.taskQuerier = taskQuerier;
+    this.runner = runner;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see java.lang.Runnable#run()
+   */
+  @Override
+  public void run() {
+    TaskProcessor nextTaskProcessor = null;
+
+    while (running) {
+      nextTaskProcessor = taskQuerier.getNext();
+
+      try {
+        if (nextTaskProcessor != null && runner.hasOpenSlots(nextTaskProcessor)) {
+          runner.execute(nextTaskProcessor);
+        }
+      } catch (Exception e) {
+        e.printStackTrace();
+        LOG.log(
+            Level.SEVERE,
+            "Engine failed while submitting jobs to its runner : "
+                + e.getMessage(), e);
+        if (nextTaskProcessor != null) {
+          this.flagProcessorAsFailed(nextTaskProcessor, e.getMessage());
+        }
+      }
+    }
+
+  }
+
+  /**
+   * @return the running
+   */
+  public boolean isRunning() {
+    return running;
+  }
+
+  /**
+   * @param running
+   *          the running to set
+   */
+  public void setRunning(boolean running) {
+    this.running = running;
+  }
+
+  protected WorkflowTask extractTaskFromProcessor(TaskProcessor taskProcessor) {
+    WorkflowInstance inst = taskProcessor.getWorkflowInstance();
+    ParentChildWorkflow workflow = inst.getParentChildWorkflow();
+    String taskId = inst.getCurrentTaskId();
+    for (WorkflowTask task : workflow.getTasks()) {
+      if (task.getTaskId().equals(taskId)) {
+        return task;
+      }
+    }
+
+    return null;
+  }
+
+  private void flagProcessorAsFailed(TaskProcessor nextTaskProcessor, String msg) {
+    nextTaskProcessor.getWorkflowInstance().setState(nextTaskProcessor
+        .getLifecycleManager()
+        .getDefaultLifecycle()
+        .createState("Failure", "done",
+            "Failed while submitting job to Runner : " + msg));
+    //TODO: persist me?
+
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/ThreadPoolWorkflowEngine.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/ThreadPoolWorkflowEngine.java
new file mode 100644
index 0000000..d332854
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/ThreadPoolWorkflowEngine.java
@@ -0,0 +1,474 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.resource.system.XmlRpcResourceManagerClient;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowStatus;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.exceptions.EngineException;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+import org.apache.oodt.cas.workflow.engine.IterativeWorkflowProcessorThread;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.commons.util.DateConvert;
+
+//JDK imports
+import java.net.URL;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//java.util.concurrent imports
+import EDU.oswego.cs.dl.util.concurrent.BoundedBuffer;
+import EDU.oswego.cs.dl.util.concurrent.Channel;
+import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
+import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
+
+/**
+ * 
+ * The ThreadPooling portion of the WorkflowEngine. This class is meant to be an
+ * extension point for WorkflowEngines that want to implement ThreadPooling.
+ * This WorkflowEngine provides everything needed to manage a ThreadPool using
+ * Doug Lea's wonderful java.util.concurrent package that made it into JDK5.
+ * 
+ * @author mattmann
+ * @version $Revsion$
+ * 
+ */
+public class ThreadPoolWorkflowEngine implements WorkflowEngine, WorkflowStatus {
+
+  /* our thread pool */
+  private PooledExecutor pool = null;
+
+  /* our worker thread hash mapping worker threads to workflow instance ids */
+  private HashMap workerMap = null;
+
+  /* our log stream */
+  private static final Logger LOG = Logger
+      .getLogger(ThreadPoolWorkflowEngine.class.getName());
+
+  /* our instance repository */
+  private WorkflowInstanceRepository instRep = null;
+
+  /* our resource manager client */
+  private XmlRpcResourceManagerClient rClient = null;
+
+  /* the URL pointer to the parent Workflow Manager */
+  private URL wmgrUrl = null;
+
+  /**
+   * Default Constructor.
+   * 
+   * @param instRep
+   *          The WorkflowInstanceRepository to be used by this engine.
+   * @param queueSize
+   *          The size of the queue that the workflow engine should use
+   *          (irrelevant if unlimitedQueue is set to true)
+   * @param maxPoolSize
+   *          The minimum thread pool size.
+   * @param minPoolSize
+   *          The maximum thread pool size.
+   * @param threadKeepAliveTime
+   *          The amount of minutes that each thread in the pool should be kept
+   *          alive.
+   * @param unlimitedQueue
+   *          Whether or not to use a queue whose bounds are dictated by the
+   *          physical memory of the underlying hardware.
+   * @param resUrl
+   *          A URL pointer to a resource manager. If this is set Tasks will be
+   *          wrapped as Resource Manager {@link Job}s and sent through the
+   *          Resource Manager. If this parameter is not set, local execution
+   *          (the default) will be used
+   */
+  public ThreadPoolWorkflowEngine(WorkflowInstanceRepository instRep,
+      int queueSize, int maxPoolSize, int minPoolSize,
+      long threadKeepAliveTime, boolean unlimitedQueue, URL resUrl) {
+
+    this.instRep = instRep;
+    Channel c = null;
+    if (unlimitedQueue) {
+      c = new LinkedQueue();
+    } else {
+      c = new BoundedBuffer(queueSize);
+    }
+
+    pool = new PooledExecutor(c, maxPoolSize);
+    pool.setMinimumPoolSize(minPoolSize);
+    pool.setKeepAliveTime(1000 * 60 * threadKeepAliveTime);
+
+    workerMap = new HashMap();
+
+    if (resUrl != null)
+      rClient = new XmlRpcResourceManagerClient(resUrl);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#pauseWorkflowInstance
+   * (java.lang.String)
+   */
+  public synchronized void pauseWorkflowInstance(String workflowInstId) {
+    // okay, try and look up that worker thread in our hash map
+    IterativeWorkflowProcessorThread worker = (IterativeWorkflowProcessorThread) workerMap
+        .get(workflowInstId);
+    if (worker == null) {
+      LOG.log(Level.WARNING,
+          "WorkflowEngine: Attempt to pause workflow instance id: "
+              + workflowInstId
+              + ", however, this engine is not tracking its execution");
+      return;
+    }
+
+    // otherwise, all good
+    worker.pause();
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#resumeWorkflowInstance
+   * (java.lang.String)
+   */
+  public synchronized void resumeWorkflowInstance(String workflowInstId) {
+    // okay, try and look up that worker thread in our hash map
+    IterativeWorkflowProcessorThread worker = (IterativeWorkflowProcessorThread) workerMap
+        .get(workflowInstId);
+    if (worker == null) {
+      LOG.log(Level.WARNING,
+          "WorkflowEngine: Attempt to resume workflow instance id: "
+              + workflowInstId + ", however, this engine is "
+              + "not tracking its execution");
+      return;
+    }
+
+    // also check to make sure that the worker is currently paused
+    // only can resume WorkflowInstances that are paused, right?
+    if (!worker.isPaused()) {
+      LOG.log(Level.WARNING,
+          "WorkflowEngine: Attempt to resume a workflow that "
+              + "isn't paused currently: instance id: " + workflowInstId);
+      return;
+    }
+
+    // okay, all good
+    worker.resume();
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#startWorkflow(org.apache
+   * .oodt.cas.workflow.structs.Workflow, org.apache.oodt.cas.metadata.Metadata)
+   */
+  public synchronized WorkflowInstance startWorkflow(Workflow workflow,
+      Metadata metadata) throws EngineException {
+    // to start the workflow, we create a default workflow instance
+    // populate it
+    // persist it
+    // add it to the worker map
+    // start it
+
+    WorkflowInstance wInst = new WorkflowInstance();
+    wInst.setWorkflow(workflow);
+    wInst.setCurrentTaskId(((WorkflowTask) workflow.getTasks().get(0))
+        .getTaskId());
+    wInst.setSharedContext(metadata);
+    wInst.setStatus(CREATED);
+    persistWorkflowInstance(wInst);
+
+    IterativeWorkflowProcessorThread worker = new IterativeWorkflowProcessorThread(
+        wInst, instRep, this.wmgrUrl);
+    worker.setRClient(rClient);
+    workerMap.put(wInst.getId(), worker);
+
+    wInst.setStatus(QUEUED);
+    persistWorkflowInstance(wInst);
+
+    try {
+      pool.execute(worker);
+    } catch (InterruptedException e) {
+      throw new EngineException(e);
+    }
+
+    return wInst;
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#getInstanceRepository()
+   */
+  public WorkflowInstanceRepository getInstanceRepository() {
+    return this.instRep;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#updateMetadata(java.
+   * lang.String, org.apache.oodt.cas.metadata.Metadata)
+   */
+  public synchronized boolean updateMetadata(String workflowInstId, Metadata met) {
+    // okay, try and look up that worker thread in our hash map
+    IterativeWorkflowProcessorThread worker = (IterativeWorkflowProcessorThread) workerMap
+        .get(workflowInstId);
+    if (worker == null) {
+      LOG.log(Level.WARNING,
+          "WorkflowEngine: Attempt to update metadata context "
+              + "for workflow instance id: " + workflowInstId
+              + ", however, this engine is " + "not tracking its execution");
+      return false;
+    }
+
+    worker.getWorkflowInstance().setSharedContext(met);
+    try {
+      persistWorkflowInstance(worker.getWorkflowInstance());
+    } catch (Exception e) {
+      LOG.log(
+          Level.WARNING,
+          "Exception persisting workflow instance: ["
+              + worker.getWorkflowInstance().getId() + "]: Message: "
+              + e.getMessage());
+      return false;
+    }
+
+    return true;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#setWorkflowManagerUrl
+   * (java.net.URL)
+   */
+  public void setWorkflowManagerUrl(URL url) {
+    this.wmgrUrl = url;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#stopWorkflow(java.lang
+   * .String)
+   */
+  public synchronized void stopWorkflow(String workflowInstId) {
+    // okay, try and look up that worker thread in our hash map
+    IterativeWorkflowProcessorThread worker = (IterativeWorkflowProcessorThread) workerMap
+        .get(workflowInstId);
+    if (worker == null) {
+      LOG.log(Level.WARNING,
+          "WorkflowEngine: Attempt to stop workflow instance id: "
+              + workflowInstId + ", however, this engine is "
+              + "not tracking its execution");
+      return;
+    }
+
+    worker.stop();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.engine.WorkflowEngine#
+   * getCurrentTaskWallClockMinutes(java.lang.String)
+   */
+  public double getCurrentTaskWallClockMinutes(String workflowInstId) {
+    // get the workflow instance that we're talking about
+    WorkflowInstance inst = safeGetWorkflowInstanceById(workflowInstId);
+    return getCurrentTaskWallClockMinutes(inst);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#getWorkflowInstanceMetadata
+   * (java.lang.String)
+   */
+  public Metadata getWorkflowInstanceMetadata(String workflowInstId) {
+    // okay, try and look up that worker thread in our hash map
+    IterativeWorkflowProcessorThread worker = (IterativeWorkflowProcessorThread) workerMap
+        .get(workflowInstId);
+    if (worker == null) {
+      // try and get the metadata
+      // from the workflow instance repository (as it was persisted)
+      try {
+        WorkflowInstance inst = instRep.getWorkflowInstanceById(workflowInstId);
+        return inst.getSharedContext();
+      } catch (InstanceRepositoryException e) {
+        LOG.log(Level.FINEST, "WorkflowEngine: Attempt to get metadata "
+            + "for workflow instance id: " + workflowInstId
+            + ", however, this engine is "
+            + "not tracking its execution and the id: [" + workflowInstId
+            + "] " + "was never persisted to " + "the instance repository");
+        e.printStackTrace();
+        return new Metadata();
+      }
+    }
+
+    return worker.getWorkflowInstance().getSharedContext();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowEngine#getWallClockMinutes(
+   * java.lang.String)
+   */
+  public double getWallClockMinutes(String workflowInstId) {
+    // get the workflow instance that we're talking about
+    WorkflowInstance inst = safeGetWorkflowInstanceById(workflowInstId);
+    return getWallClockMinutes(inst);
+  }
+
+  protected static double getWallClockMinutes(WorkflowInstance inst) {
+    if (inst == null) {
+      return 0.0;
+    }
+
+    Date currentDateOrStopTime = (inst.getEndDateTimeIsoStr() != null
+        && !inst.getEndDateTimeIsoStr().equals("") && !inst
+        .getEndDateTimeIsoStr().equals("null")) ? safeDateConvert(inst
+        .getEndDateTimeIsoStr()) : new Date();
+
+    Date workflowStartDateTime = null;
+
+    if (inst.getStartDateTimeIsoStr() == null
+        || (inst.getStartDateTimeIsoStr() != null && (inst
+            .getStartDateTimeIsoStr().equals("") || inst
+            .getStartDateTimeIsoStr().equals("null")))) {
+      return 0.0;
+    }
+
+    try {
+      workflowStartDateTime = DateConvert.isoParse(inst
+          .getStartDateTimeIsoStr());
+    } catch (ParseException e) {
+      return 0.0;
+    }
+
+    long diffMs = currentDateOrStopTime.getTime()
+        - workflowStartDateTime.getTime();
+    double diffSecs = (diffMs * 1.0 / 1000.0);
+    double diffMins = diffSecs / 60.0;
+    return diffMins;
+
+  }
+
+  protected static double getCurrentTaskWallClockMinutes(WorkflowInstance inst) {
+    if (inst == null) {
+      return 0.0;
+    }
+
+    Date currentDateOrStopTime = (inst.getCurrentTaskEndDateTimeIsoStr() != null
+        && !inst.getCurrentTaskEndDateTimeIsoStr().equals("") && !inst
+        .getCurrentTaskEndDateTimeIsoStr().equals("null")) ? safeDateConvert(inst
+        .getCurrentTaskEndDateTimeIsoStr()) : new Date();
+
+    Date workflowTaskStartDateTime = null;
+
+    if (inst.getCurrentTaskStartDateTimeIsoStr() == null
+        || (inst.getCurrentTaskStartDateTimeIsoStr() != null && (inst
+            .getCurrentTaskStartDateTimeIsoStr().equals("") || inst
+            .getCurrentTaskStartDateTimeIsoStr().equals("null")))) {
+      return 0.0;
+    }
+
+    try {
+      workflowTaskStartDateTime = DateConvert.isoParse(inst
+          .getCurrentTaskStartDateTimeIsoStr());
+    } catch (ParseException e) {
+      return 0.0;
+    }
+
+    // should never be in this state, so return 0
+    if (workflowTaskStartDateTime.after(currentDateOrStopTime)) {
+      LOG.log(
+          Level.WARNING,
+          "Start date time: ["
+              + DateConvert.isoFormat(workflowTaskStartDateTime)
+              + " of workflow inst [" + inst.getId() + "] is AFTER "
+              + "End date time: ["
+              + DateConvert.isoFormat(currentDateOrStopTime)
+              + "] of workflow inst.");
+      return 0.0;
+    }
+
+    long diffMs = currentDateOrStopTime.getTime()
+        - workflowTaskStartDateTime.getTime();
+    double diffSecs = (diffMs * 1.0 / 1000.0);
+    double diffMins = diffSecs / 60.0;
+    return diffMins;
+  }
+
+  private synchronized void persistWorkflowInstance(WorkflowInstance wInst)
+      throws EngineException {
+
+    try {
+      if (wInst.getId() == null
+          || (wInst.getId() != null && wInst.getId().equals(""))) {
+        // we have to persist it by adding it
+        // rather than updating it
+        instRep.addWorkflowInstance(wInst);
+
+      } else {
+        // persist by update
+        instRep.updateWorkflowInstance(wInst);
+      }
+    } catch (InstanceRepositoryException e) {
+      e.printStackTrace();
+      throw new EngineException(e.getMessage());
+    }
+
+  }
+
+  private WorkflowInstance safeGetWorkflowInstanceById(String workflowInstId) {
+    try {
+      return instRep.getWorkflowInstanceById(workflowInstId);
+    } catch (Exception e) {
+      return null;
+    }
+  }
+
+  private static Date safeDateConvert(String isoTimeStr) {
+    try {
+      return DateConvert.isoParse(isoTimeStr);
+    } catch (Exception ignore) {
+      ignore.printStackTrace();
+      return null;
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/ThreadPoolWorkflowEngineFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/ThreadPoolWorkflowEngineFactory.java
new file mode 100644
index 0000000..43a8c52
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/ThreadPoolWorkflowEngineFactory.java
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.engine;
+
+//JDK imports
+import static java.lang.Boolean.getBoolean;
+import static java.lang.Integer.getInteger;
+import static java.lang.Long.getLong;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.util.GenericWorkflowObjectFactory;
+
+/**
+ * A Factory class for creating {@link ThreadPoolWorkflowEngine}s.
+ * 
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public class ThreadPoolWorkflowEngineFactory implements WorkflowEngineFactory {
+
+  private static final Logger LOG = Logger
+      .getLogger(ThreadPoolWorkflowEngineFactory.class.getName());
+
+  private static final String INSTANCE_REPO_FACTORY_PROPERTY = "workflow.engine.instanceRep.factory";
+  private static final String QUEUE_SIZE_PROPERTY = "org.apache.oodt.cas.workflow.engine.queueSize";
+  private static final String MAX_POOL_SIZE_PROPERTY = "org.apache.oodt.cas.workflow.engine.maxPoolSize";
+  private static final String MIN_POOL_SIZE_PROPERTY = "org.apache.oodt.cas.workflow.engine.minPoolSize";
+  private static final String THREAD_KEEP_ALIVE_PROPERTY = "org.apache.oodt.cas.workflow.engine.threadKeepAlive.minutes";
+  private static final String UNLIMITED_QUEUE_PROPERTY = "org.apache.oodt.cas.workflow.engine.unlimitedQueue";
+  private static final String RESMGR_URL_PROPERTY = "org.apache.oodt.cas.workflow.engine.resourcemgr.url";
+
+  private static final int DEFAULT_QUEUE_SIZE = 10;
+  private static final int DEFAULT_MAX_POOL_SIZE = 10;
+  private static final int DEFAULT_MIN_POOL_SIZE = 4;
+  private static final long DEFAULT_THREAD_KEEP_ALIVE_MINS = 5;
+
+  @Override
+  public WorkflowEngine createWorkflowEngine() {
+    return new ThreadPoolWorkflowEngine(getWorkflowInstanceRepository(),
+        getQueueSize(), getMaxPoolSize(), getMinPoolSize(),
+        getThreadKeepAliveMinutes(), isUnlimitedQueue(), getResmgrUrl());
+  }
+
+  protected WorkflowInstanceRepository getWorkflowInstanceRepository() {
+    return GenericWorkflowObjectFactory
+        .getWorkflowInstanceRepositoryFromClassName(System
+            .getProperty(INSTANCE_REPO_FACTORY_PROPERTY));
+  }
+
+  protected URL getResmgrUrl() {
+    try {
+      return new URL(System.getProperty(RESMGR_URL_PROPERTY));
+    } catch (Exception e) {
+      LOG.log(
+          Level.INFO,
+          "No Resource Manager URL provided or malformed URL: executing jobs " +
+          "locally. URL: ["+System.getProperty(RESMGR_URL_PROPERTY)+"]");
+      return null;
+    }
+  }
+
+  protected int getQueueSize() {
+    return getInteger(QUEUE_SIZE_PROPERTY, DEFAULT_QUEUE_SIZE);
+  }
+
+  protected int getMaxPoolSize() {
+    return getInteger(MAX_POOL_SIZE_PROPERTY, DEFAULT_MAX_POOL_SIZE);
+  }
+
+  protected int getMinPoolSize() {
+    return getInteger(MIN_POOL_SIZE_PROPERTY, DEFAULT_MIN_POOL_SIZE);
+  }
+
+  protected long getThreadKeepAliveMinutes() {
+    return getLong(THREAD_KEEP_ALIVE_PROPERTY, DEFAULT_THREAD_KEEP_ALIVE_MINS);
+  }
+
+  protected boolean isUnlimitedQueue() {
+    return getBoolean(UNLIMITED_QUEUE_PROPERTY);
+  }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/WorkflowEngine.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/WorkflowEngine.java
new file mode 100644
index 0000000..a730026
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/WorkflowEngine.java
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.engine;
+
+//JDK imports
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.structs.exceptions.EngineException;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * The engine that executes and monitors {@link WorkflowInstance}s, which are
+ * the physical executing representation of the abtract {@link Workflow}s
+ * provided.
+ *
+ * @author mattmann (Chris Mattmann)
+ */
+public interface WorkflowEngine {
+
+    public static final String X_POINT_ID = WorkflowEngine.class.getName();
+
+
+    /**
+     * <p>
+     * Starts the specified {@link Workflow} by creating a
+     * {@link WorkflowInstance}, and then running that instance. The started
+     * {@link WorkflowInstance} which is returned, will have its status updated
+     * by the workflow engine, including its status field, and its
+     * currentTaskId.
+     * </p>
+     *
+     * @param workflow
+     *            The abstract representation of the {@link Workflow} to start.
+     * @param metadata
+     *            Any metadata that needs to be shared between the tasks in the
+     *            {@link WorkflowInstance}.
+     * @return A {@link  WorkflowInstance} which can be used to monitor the
+     *         execution of the {@link Workflow} through the Engine.
+     * @throws EngineException
+     *             If any error occurs.
+     */
+    public WorkflowInstance startWorkflow(Workflow workflow, Metadata metadata)
+            throws EngineException;
+
+    /**
+     * Stops the {@link WorkflowInstance} identified by the given
+     * <code>workflowInstId</code>.
+     *
+     * @param workflowInstId
+     *            The identifier of the {@link WorkflowInstance} to stop.
+     */
+    public void stopWorkflow(String workflowInstId);
+
+    /**
+     * <p>
+     * Pauses the {@link WorkflowInstance} specified by its
+     * <code>workflowInstId</code>.
+     * </p>
+     *
+     * @param workflowInstId
+     *            The ID of the Workflow Instance to pause.
+     */
+    public void pauseWorkflowInstance(String workflowInstId);
+
+    /**
+     * <p>
+     * Resumes Execution of the specified {@link WorkflowInstance} identified by
+     * its <code>workflowInstId</code>.
+     * </p>
+     *
+     * @param workflowInstId
+     *            The ID of the {@link WorkflowInstance} to resume.
+     */
+    public void resumeWorkflowInstance(String workflowInstId);
+
+    /**
+     * Gets the {@link WorkflowInstanceRepository} used by this
+     * {@link WorkflowEngine}.
+     *
+     * @return The {@link WorkflowInstanceRepository} used by this
+     *         {@link WorkflowEngine}.
+     */
+    public WorkflowInstanceRepository getInstanceRepository();
+
+    /**
+     * Updates the {@link Metadata} context for the {@link WorkflowInstance}
+     * identified by the given <code>workflowInstId</code>
+     *
+     * @param workflowInstId
+     *            Identifies the {@link WorkflowInstance} whose {@link Metadata}
+     *            context will be updated.
+     * @param met
+     *            The new {@link Metadata} context.
+     * @return true if the update was successful, false otherwise.
+     */
+    public boolean updateMetadata(String workflowInstId, Metadata met);
+
+    /**
+     * Sets a pointer to the Workflow Manager that this {@link WorkflowEngine}
+     * belongs to.
+     *
+     * @param url
+     *            The {@link URL} pointer to the Workflow Manager that this
+     *            {@link WorkflowEngine} belongs to.
+     */
+    public void setWorkflowManagerUrl(URL url);
+
+    /**
+     * Gets the amount of wall clock minutes that a particular
+     * {@link WorkflowInstance} (identified by its <code>workflowInst</code>)
+     * has been executing. This includes time spent <code>QUEUED</code>, time
+     * spent <code>WAITING</code>, throughout its entire lifecycle.
+     *
+     * @param workflowInstId
+     *            The identifier of the {@link WorkflowInstance} to measure wall
+     *            clock time for.
+     *
+     * @return The amount of wall clock minutes that a particular
+     *         {@link WorkflowInstance} has been executing for.
+     */
+    public double getWallClockMinutes(String workflowInstId);
+
+    /**
+     * Gets the amount of wall clock minutes that the particular
+     * {@link WorkflowTask} within a {@link WorkflowInstance} has been executing
+     * for.
+     *
+     * @param workflowInstId
+     *            The identifier of the {@link WorkflowInstance} to measure wall
+     *            clock time for its current {@link WorkflowTask}.
+     * @return The amount of wall clock minutes that a particular
+     *         {@link WorkflowInstance}'s current {@link WorkflowTask} has been
+     *         executing for.
+     */
+    public double getCurrentTaskWallClockMinutes(String workflowInstId);
+
+    /**
+     * Gets the {@link Metadata} associated with the {@link WorkflowInstance}
+     * identified by the given identifier.
+     *
+     * @param workflowInstId
+     *            The identifier of the {@link WorkflowInstance} to obtain the
+     *            {@link Metadata} for.
+     * @return The {@link Metadata} shared context of the
+     *         {@link WorkflowInstance} with the given identifier.
+     *
+     */
+    public Metadata getWorkflowInstanceMetadata(String workflowInstId);
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/WorkflowEngineFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/WorkflowEngineFactory.java
new file mode 100644
index 0000000..072c693
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/WorkflowEngineFactory.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.engine;
+
+/**
+ * A factory interface for creating {@link WorkflowEngine} objects.
+ *
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public interface WorkflowEngineFactory {
+
+   /**
+    * Method which creates {@link WorkflowEngine}s.
+    *
+    * @return An implementation of the {@link WorkflowEngine} interface
+    */
+   public WorkflowEngine createWorkflowEngine();
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/ConditionProcessor.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/ConditionProcessor.java
new file mode 100755
index 0000000..1cee170
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/ConditionProcessor.java
@@ -0,0 +1,63 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.engine.processor;
+
+//OODT import
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+import org.apache.oodt.cas.workflow.structs.Priority;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+
+/**
+ * 
+ * WorkflowProcessor which handles Workflow Pre/Post Conditions.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ConditionProcessor extends TaskProcessor {
+
+  public ConditionProcessor(WorkflowLifecycleManager lifecycleManager, WorkflowInstance inst) {
+    super(lifecycleManager, inst);
+  }
+
+  @Override
+  public void setPreConditions(WorkflowProcessor preConditions) {
+    // not allowed
+  }
+
+  @Override
+  public void setPostConditions(WorkflowProcessor postConditions) {
+    // not allowed
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.processor.TaskProcessor#setWorkflowInstance
+   * (org.apache.oodt.cas.workflow.structs.WorkflowInstance)
+   */
+  @Override
+  public void setWorkflowInstance(WorkflowInstance instance) {
+    instance.setPriority(Priority
+        .getPriority(instance.getPriority().getValue() - 0.1));
+    super.setWorkflowInstance(instance);
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/ParallelProcessor.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/ParallelProcessor.java
new file mode 100755
index 0000000..0ed720e
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/ParallelProcessor.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.engine.processor;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+
+/**
+ * 
+ * WorkflowProcessor which handles running sub-workflow processors in parallel.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ParallelProcessor extends WorkflowProcessor {
+
+  public ParallelProcessor(WorkflowLifecycleManager lifecycleMgr, WorkflowInstance instance) {
+    super(lifecycleMgr, instance);
+  }
+
+  public List<WorkflowProcessor> getRunnableSubProcessors() {
+    return this.getSubProcessors();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor#
+   * handleSubProcessorMetadata
+   * (org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor)
+   */
+  @Override
+  protected void handleSubProcessorMetadata(WorkflowProcessor workflowProcessor) {
+    // TODO Auto-generated method stub
+
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/SequentialProcessor.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/SequentialProcessor.java
new file mode 100755
index 0000000..32cc608
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/SequentialProcessor.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.engine.processor;
+
+//JDK imports
+import java.util.Collections;
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+
+/**
+ * 
+ * WorkflowProcessor which handles running sub-processors in sequence.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ */
+public class SequentialProcessor extends WorkflowProcessor {
+
+  public SequentialProcessor(WorkflowLifecycleManager lifecycleManager, WorkflowInstance instance) {
+    super(lifecycleManager, instance);
+  }
+
+  @Override
+  public List<WorkflowProcessor> getRunnableSubProcessors() {
+    WorkflowProcessor nextWP = this.getNext();
+    if (nextWP != null)
+      return Collections.singletonList(nextWP);
+    else
+      return new Vector<WorkflowProcessor>();
+  }
+
+  @Override
+  public void handleSubProcessorMetadata(WorkflowProcessor workflowProcessor) {
+    // do nothing
+  }
+
+  private WorkflowProcessor getNext() {
+    for (WorkflowProcessor wp : this.getSubProcessors())
+      if (!wp.getWorkflowInstance().getState().getCategory().getName()
+          .equals("done") && !wp.getWorkflowInstance().getState().getName().equals("Executing"))
+        return wp;
+    return null;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/TaskProcessor.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/TaskProcessor.java
new file mode 100755
index 0000000..d139e8f
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/TaskProcessor.java
@@ -0,0 +1,121 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine.processor;
+
+//JDK imports
+import java.util.Calendar;
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+import org.apache.oodt.cas.workflow.structs.Priority;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+
+/**
+ * 
+ * WorkflowProcessor which handles running task workflows.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * 
+ * @version $Revision$
+ */
+public class TaskProcessor extends WorkflowProcessor {
+
+  private Class<? extends WorkflowTaskInstance> instanceClass;
+  private String jobId;
+  
+  public TaskProcessor(WorkflowLifecycleManager lifecycleManager, WorkflowInstance instance) {
+    super(lifecycleManager, instance);
+  }
+
+  public Class<? extends WorkflowTaskInstance> getInstanceClass() {
+    return this.instanceClass;
+  }
+
+  public void setJobId(String jobId) {
+    this.jobId = jobId;
+  }
+
+  public String getJobId() {
+    return this.jobId;
+  }
+
+  public void setInstanceClass(
+      Class<? extends WorkflowTaskInstance> instanceClass) {
+    this.instanceClass = instanceClass;
+  }
+
+  @Override
+  public void setWorkflowInstance(WorkflowInstance instance) {
+    instance.setPriority(Priority
+        .getPriority(instance.getPriority().getValue() + 0.1));
+    super.setWorkflowInstance(instance);
+  }
+
+  @Override
+  public List<TaskProcessor> getRunnableWorkflowProcessors() {
+    List<TaskProcessor> tps = super.getRunnableWorkflowProcessors();
+    if (tps.size() == 0) {
+      if (this.getWorkflowInstance().getState().getName().equals("Blocked")) {
+        String requiredBlockTimeElapseString = this.getWorkflowInstance()
+            .getCurrentTask().getTaskConfig().getProperty("BlockTimeElapse");
+        int requiredBlockTimeElapse = 2;
+        if (requiredBlockTimeElapseString != null) {
+          try {
+            requiredBlockTimeElapse = Integer
+                .parseInt(requiredBlockTimeElapseString);
+          } catch (Exception e) {
+          }
+        }
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(this.getWorkflowInstance().getState().getStartTime());
+        long elapsedTime = ((System.currentTimeMillis() - calendar
+            .getTimeInMillis()) / 1000) / 60;
+        if (elapsedTime >= requiredBlockTimeElapse)
+          tps.add(this);
+      } else if (this.isAnyState("Loaded", "Queued", "PreConditionSuccess") && 
+          !this.isAnyState("Executing") && this.passedPreConditions()){
+        tps.add(this);
+      }
+    }
+    return tps;
+  }
+
+  protected boolean hasSubProcessors() {
+    return true;
+  }
+
+  @Override
+  public List<WorkflowProcessor> getRunnableSubProcessors() {
+    return new Vector<WorkflowProcessor>();
+  }
+
+  @Override
+  public void setSubProcessors(List<WorkflowProcessor> subProcessors) {
+    // not allowed
+  }
+
+  @Override
+  public void handleSubProcessorMetadata(WorkflowProcessor workflowProcessor) {
+    // do nothing
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessor.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessor.java
new file mode 100755
index 0000000..691bcb1
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessor.java
@@ -0,0 +1,452 @@
+/*

+ * 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.

+ */

+package org.apache.oodt.cas.workflow.engine.processor;

+

+//JDK imports

+import java.util.List;

+import java.util.Vector;

+import java.util.logging.Logger;

+

+//OODT imports

+import org.apache.oodt.cas.workflow.engine.ChangeType;

+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;

+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleStage;

+import org.apache.oodt.cas.workflow.lifecycle.WorkflowState;

+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;

+

+/**

+ * 

+ * The new Apache OODT workflow style of processor. These processors are

+ * responsible for returning the set of underlying tasks, or conditions that can

+ * run. A sequential version will return only a single sub-processor (condition

+ * or task, or even workflow); a parallel version will return many sub

+ * processors to run.

+ * 

+ * @since Apache OODT 0.4.

+ * 

+ * @author mattmann

+ * @author bfoster

+ * 

+ */

+public abstract class WorkflowProcessor implements WorkflowProcessorListener,

+    Comparable<WorkflowProcessor> {

+

+  private static final Logger LOG = Logger.getLogger(WorkflowProcessor.class

+      .getName());

+

+  private WorkflowInstance workflowInstance;

+  private WorkflowProcessor preConditions;

+  private WorkflowProcessor postConditions;

+  private List<String> excusedSubProcessorIds; // FIXME: read this in

+                                               // PackagedRepo: flow through

+                                               // instance

+  private List<WorkflowProcessor> subProcessors;

+  private List<WorkflowProcessorListener> listeners;

+  private int minReqSuccessfulSubProcessors; // FIXME: read this in

+                                             // PackagedRepo: flow through

+                                             // instance

+  protected WorkflowLifecycleManager lifecycleManager;

+  protected WorkflowProcessorHelper helper;

+

+  public WorkflowProcessor(WorkflowLifecycleManager lifecycleManager,

+      WorkflowInstance workflowInstance) {

+    this.subProcessors = new Vector<WorkflowProcessor>();

+    this.listeners = new Vector<WorkflowProcessorListener>();

+    this.excusedSubProcessorIds = new Vector<String>();

+    this.minReqSuccessfulSubProcessors = -1;

+    this.lifecycleManager = lifecycleManager;

+    this.workflowInstance = workflowInstance;

+    this.helper = new WorkflowProcessorHelper(lifecycleManager);

+    WorkflowState initState = helper.getLifecycleForProcessor(this)

+        .createState("Null", "initial",

+            "Instance created by workflow processor.");

+    this.workflowInstance.setState(initState);

+  }

+

+  /**

+   * @return the workflowInstance

+   */

+  public WorkflowInstance getWorkflowInstance() {

+    return workflowInstance;

+  }

+

+  /**

+   * @param workflowInstance

+   *          the workflowInstance to set

+   */

+  public void setWorkflowInstance(WorkflowInstance workflowInstance) {

+    this.workflowInstance = workflowInstance;

+  }

+

+  /**

+   * @return the excusedSubProcessorIds

+   */

+  public List<String> getExcusedSubProcessorIds() {

+    return excusedSubProcessorIds;

+  }

+

+  /**

+   * @param excusedSubProcessorIds

+   *          the excusedSubProcessorIds to set

+   */

+  public void setExcusedSubProcessorIds(List<String> excusedSubProcessorIds) {

+    this.excusedSubProcessorIds = excusedSubProcessorIds;

+  }

+

+  /**

+   * @return the subProcessors

+   */

+  public List<WorkflowProcessor> getSubProcessors() {

+    return subProcessors;

+  }

+

+  /**

+   * @param subProcessors

+   *          the subProcessors to set

+   */

+  public void setSubProcessors(List<WorkflowProcessor> subProcessors) {

+    this.subProcessors = subProcessors;

+  }

+

+  /**

+   * @return the listeners

+   */

+  public List<WorkflowProcessorListener> getListeners() {

+    return listeners;

+  }

+

+  /**

+   * @param listeners

+   *          the listeners to set

+   */

+  public void setListeners(List<WorkflowProcessorListener> listeners) {

+    this.listeners = listeners;

+  }

+

+  /**

+   * @return the minReqSuccessfulSubProcessors

+   */

+  public int getMinReqSuccessfulSubProcessors() {

+    return minReqSuccessfulSubProcessors;

+  }

+

+  /**

+   * @param minReqSuccessfulSubProcessors

+   *          the minReqSuccessfulSubProcessors to set

+   */

+  public void setMinReqSuccessfulSubProcessors(int minReqSuccessfulSubProcessors) {

+    this.minReqSuccessfulSubProcessors = minReqSuccessfulSubProcessors;

+  }

+

+  /**

+   * @return the lifecycleManager

+   */

+  public WorkflowLifecycleManager getLifecycleManager() {

+    return lifecycleManager;

+  }

+

+  /**

+   * @param lifecycleManager

+   *          the lifecycleManager to set

+   */

+  public void setLifecycleManager(WorkflowLifecycleManager lifecycleManager) {

+    this.lifecycleManager = lifecycleManager;

+  }

+

+  /**

+   * @return the preConditions

+   */

+  public WorkflowProcessor getPreConditions() {

+    return preConditions;

+  }

+

+  /**

+   * @param preConditions

+   *          the preConditions to set

+   */

+  public void setPreConditions(WorkflowProcessor preConditions) {

+    this.preConditions = preConditions;

+  }

+

+  /**

+   * @return the postConditions

+   */

+  public WorkflowProcessor getPostConditions() {

+    return postConditions;

+  }

+

+  /**

+   * @param postConditions

+   *          the postConditions to set

+   */

+  public void setPostConditions(WorkflowProcessor postConditions) {

+    this.postConditions = postConditions;

+  }

+

+  /*

+   * (non-Javadoc)

+   * 

+   * @see java.lang.Comparable#compareTo(java.lang.Object)

+   */

+  @Override

+  public int compareTo(WorkflowProcessor workflowProcessor) {

+    return this.getWorkflowInstance().getPriority()

+        .compareTo(workflowProcessor.getWorkflowInstance().getPriority());

+  }

+

+  /*

+   * (non-Javadoc)

+   * 

+   * @see

+   * org.apache.oodt.cas.workflow.engine.WorkflowProcessorListener#notifyChange

+   * (org.apache.oodt.cas.workflow.engine.WorkflowProcessor,

+   * org.apache.oodt.cas.workflow.engine.ChangeType)

+   */

+  @Override

+  public void notifyChange(WorkflowProcessor processor, ChangeType changeType) {

+    for (WorkflowProcessorListener listener : this.getListeners())

+      listener.notifyChange(this, changeType);

+  }

+

+  public synchronized List<TaskProcessor> getRunnableWorkflowProcessors() {

+    Vector<TaskProcessor> runnableTasks = new Vector<TaskProcessor>();

+

+    // evaluate pre-conditions

+    if (!this.passedPreConditions()) {

+      for (WorkflowProcessor subProcessor : this.getPreConditions()

+          .getRunnableSubProcessors()) {

+        for (TaskProcessor tp : subProcessor.getRunnableWorkflowProcessors()) {

+          runnableTasks.add(tp);

+        }

+      }

+

+    } else if (this.isDone().getName().equals("ResultsFailure")) {

+      // do nothing -- this workflow failed!!!

+    } else if (this.isDone().getName().equals("ResultsBail")) {

+      for (WorkflowProcessor subProcessor : this.getRunnableSubProcessors())

+        runnableTasks.addAll(subProcessor.getRunnableWorkflowProcessors());

+    } else if (!this.passedPostConditions()) {

+      for (WorkflowProcessor subProcessor : this.getPostConditions()

+          .getRunnableSubProcessors()) {

+        for (TaskProcessor tp : subProcessor.getRunnableWorkflowProcessors()) {

+          runnableTasks.add(tp);

+        }

+      }

+

+    }

+

+    return runnableTasks;

+  }

+

+  /**

+   * Advances this WorkflowProcessor to its next {@link WorkflowState}.

+   */

+  public void nextState() {

+    if (this.workflowInstance != null

+        && this.workflowInstance.getState() != null) {

+      WorkflowState currState = this.workflowInstance.getState();

+      WorkflowState nextState = null;

+      if (currState.getName().equals("Null")) {

+        nextState = this.helper.getLifecycleForProcessor(this).createState(

+            "Loaded",

+            "initial",

+            "Workflow Processor: nextState: " + "loading workflow instance: ["

+                + this.workflowInstance.getId() + "]");

+      } else if (currState.getName().equals("Loaded")) {

+        nextState = this.helper.getLifecycleForProcessor(this).createState(

+            "Queued",

+            "initial",

+            "Workflow Processor: nextState: " + "queueing instance: ["

+                + this.workflowInstance.getId() + "]");

+      } else if (currState.getName().equals("Queued")) {

+        if (!this.passedPreConditions()) {

+          nextState = this.helper.getLifecycleForProcessor(this).createState(

+              "PreConditionEval",

+              "running",

+              "Workflow Processor: nextState: "

+                  + "running preconditiosn for workflow instance: ["

+                  + this.workflowInstance.getId() + "]");

+        } else {

+          if (this.isDone().getName().equals("ResultsSuccess")) {

+            nextState = this.helper.getLifecycleForProcessor(this).createState(

+                "Success",

+                "done",

+                "Workflow Processor: nextState: " + "workflow instance: ["

+                    + this.workflowInstance.getId()

+                    + "] completed successfully");

+          }

+        }

+      } else if (currState.getName().equals("Executing")) {

+        if(this.isDone().getName().equals("ResultsSuccess")){

+        nextState = this.helper.getLifecycleForProcessor(this).createState(

+            "Success",

+            "done",

+            "Workflow Processor: nextState: " + "workflow instance: ["

+                + this.workflowInstance.getId() + "] completed successfully");

+        }

+      }

+      else if(currState.getName().equals("ExecutionComplete")){

+        nextState = this.helper.getLifecycleForProcessor(this).createState(

+            "Success",

+            "done",

+            "Workflow Processor: nextState: " + "workflow instance: ["

+                + this.workflowInstance.getId() + "] completed successfully");        

+      }

+

+      if (nextState != null) {

+        this.workflowInstance.setState(nextState);

+      }

+

+    } else {

+      this.workflowInstance.setState(helper.getLifecycleForProcessor(this)

+          .createState(

+              "Unknown",

+              "holding",

+              "The Workflow Processor for instance : ["

+                  + this.getWorkflowInstance().getId() + "] "

+                  + "had a null state"));

+    }

+  }

+  

+  /**

+   * Evaluates whether or not this processor's {@link WorkflowState}

+   * is in any of the provided state names.

+   * 

+   * @param states The names of states to check this processor's 

+   * {@link WorkflowState} against.

+   * 

+   * @return True, if any of the state names provided is the name of

+   * this processor's internal {@link WorkflowState}, False otherwise.

+   */

+  public boolean isAnyState(String... states) {

+    for (String state : states) {

+      if (this.getWorkflowInstance().getState().getName().equals(state)) {

+        return true;

+      }

+    }

+

+    return false;

+  }

+

+  /**

+   * Evaluates whether or not this processor's {@link WorkflowLifecycleStage}

+   * is in any of the provided category names.

+   * 

+   * @param categories The names of categories to check this processor's 

+   * {@link WorkflowLifecycleStage} against.

+   * 

+   * @return True, if any of the category names provided is the name of

+   * this processor's internal {@link WorkflowLifecycleStage}, False otherwise.

+   */

+  public boolean isAnyCategory(String... categories) {

+    for (String category : categories) {

+      if (this.getWorkflowInstance().getState().getCategory().getName()

+          .equals(category)) {

+        return true;

+      }

+    }

+

+    return false;

+  }  

+

+  protected boolean passedPreConditions() {

+    if (this.getPreConditions() != null) {

+      return this.getPreConditions().getWorkflowInstance().getState().getName()

+          .equals("Success");

+    } else {

+      return true;

+    }

+  }

+

+  protected boolean passedPostConditions() {

+    if (this.getPostConditions() != null) {

+      return this.getPostConditions().getWorkflowInstance().getState()

+          .getName().equals("Success");

+    } else {

+      return true;

+    }

+  }

+

+  /**

+   * First checks to see if any of this Processor's {@link #subProcessors} have

+   * arrived in a state within the done category. If so the method determines if

+   * any of the done {@link #subProcessors} are in Failure state. If so, the

+   * method compares the number of Failed sub-processors against

+   * {@link #minReqSuccessfulSubProcessors}, and if it is greater than it,

+   * returns a ResultsFailure {@link WorkflowState}. Otherwise, the method scans

+   * the failed sub-processors, and checks to see if all of them have been

+   * excused. If they haven't, then a ResultFailure state is returned. Finally,

+   * the method checks to ensure that all sub processors are in the done

+   * category. If they are, a ResultsSuccess {@link WorkflowState} is returned,

+   * otherwise, a ResultsBail state is returned.

+   * 

+   * @return A {@link WorkflowState}, according to the method description.

+   */

+  protected WorkflowState isDone() {

+    if (this.helper.containsCategory(this.getSubProcessors(), "done")) {

+      List<WorkflowProcessor> failedSubProcessors = this.helper

+          .getWorkflowProcessorsByState(this.getSubProcessors(), "Failure");

+      if (this.minReqSuccessfulSubProcessors != -1

+          && failedSubProcessors.size() > (this.getSubProcessors().size() - this.minReqSuccessfulSubProcessors))

+        return lifecycleManager.getDefaultLifecycle().createState(

+            "ResultsFailure", "results",

+            "More than the allowed number of sub-processors failed");

+      for (WorkflowProcessor subProcessor : failedSubProcessors) {

+        if (!this.getExcusedSubProcessorIds().contains(

+            subProcessor.getWorkflowInstance().getId())) {

+          return lifecycleManager.getDefaultLifecycle().createState(

+              "ResultsFailure",

+              "results",

+              "Sub processor: [" + subProcessor.getWorkflowInstance().getId()

+                  + "] failed.");

+        }

+      }

+      if (this.helper

+          .allProcessorsSameCategory(this.getSubProcessors(), "done"))

+        return lifecycleManager.getDefaultLifecycle().createState(

+            "ResultsSuccess",

+            "results",

+            "Workflow Processor: processing instance id: ["

+                + workflowInstance.getId() + "] is Done.");

+    }

+    return lifecycleManager.getDefaultLifecycle().createState(

+        "ResultsBail",

+        "results",

+        "All sub-processors for Workflow Processor handling workflow id: ["

+            + workflowInstance.getId() + "] are " + "not complete");

+  }

+

+  /**

+   * This is the core method of the WorkflowProcessor class in the new Wengine

+   * style workflows. Instead of requiring that a processor actually walk

+   * through the underlying {@link Workflow}, these style WorkflowProcessors

+   * actually require their implementing sub-classes to return the current set

+   * of Runnable sub-processors (which could be tasks, conditions, even

+   * {@link Workflow}s themselves.

+   * 

+   * The Parallel sub-class returns a list of task or condition processors that

+   * are able to run at a given time. The Sequential sub-class returns only a

+   * single task or condition processor to run, and so forth.

+   * 

+   * @return The list of WorkflowProcessors able to currently run.

+   */

+  protected abstract List<WorkflowProcessor> getRunnableSubProcessors();

+

+  protected abstract void handleSubProcessorMetadata(

+      WorkflowProcessor workflowProcessor);

+

+}

diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessorBuilder.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessorBuilder.java
new file mode 100644
index 0000000..22668aa
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessorBuilder.java
@@ -0,0 +1,111 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine.processor;
+
+//JDK imorts
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+import org.apache.oodt.cas.workflow.structs.Priority;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * 
+ * Builds {@link WorkflowProcessor}s.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowProcessorBuilder {
+
+  private String id;
+  private double priority;
+  private List<WorkflowProcessor> subProcessors;
+  private WorkflowLifecycleManager lifecycleManager;
+  private WorkflowInstance workflowInstance;
+
+  private WorkflowProcessorBuilder() {
+    subProcessors = Lists.newArrayList();
+    this.id = null;
+    this.priority = -1;
+    this.lifecycleManager = null;
+    this.workflowInstance = null;
+  }
+
+  public static WorkflowProcessorBuilder aWorkflowProcessor() {
+    return new WorkflowProcessorBuilder();
+  }
+
+  public WorkflowProcessorBuilder withId(String id) {
+    this.id = id;
+    return this;
+  }
+
+  public WorkflowProcessorBuilder withLifecycleManager(
+      WorkflowLifecycleManager lifecycleManager) {
+    this.lifecycleManager = lifecycleManager;
+    return this;
+  }
+
+  public WorkflowProcessorBuilder withPriority(double priority) {
+    this.priority = priority;
+    return this;
+  }
+
+  public WorkflowProcessorBuilder withInstance(WorkflowInstance workflowInstance) {
+    this.workflowInstance = workflowInstance;
+    return this;
+  }
+
+  public WorkflowProcessorBuilder with(WorkflowProcessorBuilder wpb,
+      Class<? extends WorkflowProcessor> clazz) throws InstantiationException,
+      IllegalAccessException, IllegalArgumentException,
+      InvocationTargetException, SecurityException, NoSuchMethodException {
+    subProcessors.add(wpb.build(clazz));
+    return this;
+  }
+
+  public WorkflowProcessor build(Class<? extends WorkflowProcessor> clazz)
+      throws InstantiationException, IllegalAccessException,
+      IllegalArgumentException, InvocationTargetException, SecurityException,
+      NoSuchMethodException {
+    Constructor<? extends WorkflowProcessor> clazzConstructor = clazz
+        .getConstructor(new Class[] { WorkflowLifecycleManager.class,
+            WorkflowInstance.class });
+    WorkflowProcessor wp = clazzConstructor.newInstance(this.lifecycleManager,
+        this.workflowInstance);
+    if (this.id != null)
+      wp.getWorkflowInstance().setId(id);
+    if (this.priority != -1)
+      wp.getWorkflowInstance().setPriority(Priority.getPriority(priority));
+    if (this.subProcessors != null)
+      wp.setSubProcessors(subProcessors);
+    if (this.workflowInstance != null){
+      wp.setWorkflowInstance(workflowInstance);
+    }
+    return wp;
+  }
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessorHelper.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessorHelper.java
new file mode 100755
index 0000000..7918060
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessorHelper.java
@@ -0,0 +1,377 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.engine.processor;
+
+//OODT imports
+import org.apache.oodt.commons.exec.ExecHelper;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.Graph;
+import org.apache.oodt.cas.workflow.structs.Priority;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.ParentChildWorkflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycle;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+
+//JDK imports
+import java.net.InetAddress;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+//APACHE imports
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * 
+ * Utilities for working with WorkflowProcessors and WorkflowModels.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+//TODO: go through me and find all the methods that aren't used and remove them
+public class WorkflowProcessorHelper {
+
+  private WorkflowLifecycleManager lifecycle;
+  
+  public WorkflowProcessorHelper(){
+    this(null);
+  }
+
+  public WorkflowProcessorHelper(WorkflowLifecycleManager lifecycle) {
+    this.lifecycle = lifecycle;
+  }
+
+  public String toString(WorkflowProcessor skeleton) {
+    return toString(skeleton, "\n   ");
+  }
+
+  private String toString(WorkflowProcessor skeleton, String indent) {
+    StringBuffer stringModel = new StringBuffer(
+        "["
+            + (skeleton.getWorkflowInstance().getParentChildWorkflow().getId() == null ? ""
+                : "id = '"
+                    + skeleton.getWorkflowInstance().getParentChildWorkflow()
+                        .getId()
+                    + "', name = '"
+                    + skeleton.getWorkflowInstance().getParentChildWorkflow()
+                        .getName() + "', ")
+            + "execution = '"
+            + skeleton.getWorkflowInstance().getParentChildWorkflow()
+                .getGraph().getExecutionType() + "', state = '"
+            + skeleton.getWorkflowInstance().getState().getName() + "']");// ,
+                                                                          // properties
+    // =
+    // " + processor.getStaticMetadata().asHashtable() + "]");
+    if (skeleton.getPreConditions() != null)
+      stringModel.append(indent + "{PreCond:" + indent + "   "
+          + toString(skeleton.getPreConditions(), indent + "      ") + "}");
+    if (skeleton.getPostConditions() != null)
+      stringModel.append(indent + "{PostCond:" + indent + "   "
+          + toString(skeleton.getPostConditions(), indent + "      ") + "}");
+    if (skeleton.getSubProcessors() != null)
+      for (WorkflowProcessor subProcessor : skeleton.getSubProcessors())
+        stringModel.append(indent + toString(subProcessor, indent + "   "));
+    return stringModel.toString();
+  }
+
+  public String describe(WorkflowProcessor skeleton) {
+    StringBuffer stringModel = new StringBuffer("");
+    stringModel.append("Processor [id = '"
+        + skeleton.getWorkflowInstance().getParentChildWorkflow().getId()
+        + "', name = '"
+        + skeleton.getWorkflowInstance().getParentChildWorkflow().getName()
+        + "']\n");
+    stringModel.append("   - instance = '"
+        + skeleton.getWorkflowInstance().getId() + "'\n");
+    stringModel.append("   - execution = '"
+        + skeleton.getWorkflowInstance().getParentChildWorkflow().getGraph()
+            .getExecutionType() + "'\n");
+    stringModel.append("   - timesBlocked = '"
+        + skeleton.getWorkflowInstance().getTimesBlocked() + "'\n");
+    stringModel.append("   - dates: \n");
+    stringModel.append("        CreationDate = '"
+        + skeleton.getWorkflowInstance().getStartDate() + "'\n");
+    stringModel.append("        CompletionDate = '"
+        + skeleton.getWorkflowInstance().getEndDate() + "'\n");
+    stringModel.append("   - state: \n");
+    stringModel.append("        name = '"
+        + skeleton.getWorkflowInstance().getState().getName() + "'\n");
+    stringModel.append("        startTime = '"
+        + skeleton.getWorkflowInstance().getState().getStartTime() + "'\n");
+    stringModel.append("        message = '"
+        + skeleton.getWorkflowInstance().getState().getMessage() + "'\n");
+    stringModel.append("   - priority = '"
+        + skeleton.getWorkflowInstance().getPriority() + "'\n");
+    stringModel
+        .append("   - execusedSubProcessors = '"
+            + StringUtils.join(skeleton.getExcusedSubProcessorIds().iterator(),
+                ",") + "'\n");
+    stringModel.append("   - static metadata = \n");
+    for (String key : skeleton.getWorkflowInstance().getSharedContext()
+        .getAllKeys())
+      stringModel.append("      + "
+          + key
+          + " -> '"
+          + StringUtils.join(skeleton.getWorkflowInstance().getSharedContext()
+              .getAllMetadata(key), ",") + "'\n");
+    stringModel.append("   - dynamic metadata = \n");
+    for (String key : skeleton.getWorkflowInstance().getSharedContext()
+        .getAllKeys())
+      stringModel.append("      + "
+          + key
+          + " -> '"
+          + StringUtils.join(skeleton.getWorkflowInstance().getSharedContext()
+              .getAllMetadata(key), ",") + "'\n");
+    return stringModel.toString();
+  }
+
+  public WorkflowProcessor buildProcessor(String instanceId,
+      ParentChildWorkflow workflow,
+      Map<String, Class<? extends WorkflowProcessor>> modelToProcessorMap,
+      boolean preCond) throws Exception {
+    List<WorkflowProcessor> subProcessors = new Vector<WorkflowProcessor>();
+    List<WorkflowCondition> conditions = preCond ? workflow.getPreConditions()
+        : workflow.getPostConditions();
+    for (WorkflowCondition cond : conditions) {
+      ParentChildWorkflow condWorkflow = new ParentChildWorkflow(new Graph());
+      condWorkflow.getGraph().setExecutionType("condition");
+      condWorkflow.getGraph().setCond(cond);
+      subProcessors.add(buildProcessor(instanceId, condWorkflow,
+          modelToProcessorMap, preCond));
+    }
+    WorkflowProcessor wp = buildProcessor(instanceId, workflow, workflow
+        .getGraph().isCondition(), modelToProcessorMap);
+    wp.setSubProcessors(subProcessors);
+    return wp;
+  }
+
+  public WorkflowProcessor buildProcessor(String instanceId,
+      ParentChildWorkflow model, boolean isCondition,
+      Map<String, Class<? extends WorkflowProcessor>> modelToProcessorMap)
+      throws Exception {
+    WorkflowProcessor wp = modelToProcessorMap.get(
+        model.getGraph().getExecutionType()).newInstance();
+    WorkflowLifecycle wLifecycle = getLifecycle(model);
+    // FIXME: I'm not sure what these excused processor Ids are. I didn't seem
+    // need them in the PackagedWorkflowRepository, so not sure what they do.
+    // wp.setExcusedSubProcessorIds(model.getGraph().getExcusedSubProcessorIds());
+    wp.getWorkflowInstance().setId(instanceId);
+    if (model.getPreConditions() != null)
+      wp.setPreConditions(buildProcessor(instanceId, model,
+          modelToProcessorMap, true));
+    if (model.getPostConditions() != null)
+      wp.setPostConditions(buildProcessor(instanceId, model,
+          modelToProcessorMap, false));
+    wp.getWorkflowInstance().setPriority(Priority.getDefault());
+    wp.setMinReqSuccessfulSubProcessors(Integer.parseInt(model.getGraph()
+        .getMinReqSuccessfulSubProcessors()));
+    wp.getWorkflowInstance().setSharedContext(new Metadata());
+    wp.getWorkflowInstance().setState(
+        wLifecycle.createState("Loaded",
+            wLifecycle.getStageForWorkflow("Loaded").getName(), ""));
+    if (wp instanceof TaskProcessor)
+      ((TaskProcessor) wp)
+          .setInstanceClass((Class<? extends WorkflowTaskInstance>) Class
+              .forName(model.getGraph().getTask().getTaskInstanceClassName()));
+    return wp;
+  }
+
+  public WorkflowProcessor findSkeleton(WorkflowProcessor skeleton,
+      String modelId) {
+    if (skeleton.getWorkflowInstance().getParentChildWorkflow().getGraph()
+        .getModelId().equals(modelId))
+      return skeleton;
+    WorkflowProcessor found = findSkeleton(skeleton.getSubProcessors(), modelId);
+    if (found == null) {
+      if (skeleton.getPreConditions() != null)
+        found = findSkeleton(skeleton.getPreConditions(), modelId);
+      if (found == null && skeleton.getPostConditions() != null)
+        found = findSkeleton(skeleton.getPostConditions(), modelId);
+    }
+    return found;
+  }
+
+  protected WorkflowProcessor findSkeleton(List<WorkflowProcessor> skeletons,
+      String modelId) {
+    for (WorkflowProcessor skeleton : skeletons) {
+      if (skeleton.getWorkflowInstance().getParentChildWorkflow().getId()
+          .equals(modelId)) {
+        return skeleton;
+      } else {
+        skeleton = findSkeleton(skeleton, modelId);
+        if (skeleton != null)
+          return skeleton;
+      }
+    }
+    return null;
+  }
+
+  public WorkflowProcessor findProcessor(WorkflowProcessor wp, String modelId) {
+    if (wp.getWorkflowInstance().getParentChildWorkflow().getId()
+        .equals(modelId))
+      return wp;
+    WorkflowProcessor found = findProcessor(wp.getSubProcessors(), modelId);
+    if (found == null) {
+      if (wp.getPreConditions() != null)
+        found = findProcessor(wp.getPreConditions(), modelId);
+      if (found == null && wp.getPostConditions() != null)
+        found = findProcessor(wp.getPostConditions(), modelId);
+    }
+    return found;
+  }
+
+  protected WorkflowProcessor findProcessor(List<WorkflowProcessor> processors,
+      String modelId) {
+    for (WorkflowProcessor processor : processors) {
+      if (processor.getWorkflowInstance().getId().equals(modelId)) {
+        return processor;
+      } else {
+        processor = findProcessor(processor, modelId);
+        if (processor != null)
+          return processor;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Verifies that all provided WorkflowProcessors are in a state belonging to
+   * the given categoryName.
+   * 
+   * @param workflowProcessors
+   *          The {@link List} of WorkflowProcessors to inspect.
+   * @param categoryName
+   *          The name of the WorkflowState's category to check against.
+   * @return True if they are all in the same category, false otherwise.
+   */
+  public boolean allProcessorsSameCategory(
+      List<WorkflowProcessor> workflowProcessors, String categoryName) {
+    for (WorkflowProcessor workflowProcessor : workflowProcessors)
+      if (!workflowProcessor.getWorkflowInstance().getState().getCategory()
+          .getName().equals(categoryName))
+        return false;
+    return true;
+  }
+
+  /**
+   * Sub-selects all WorkflowProcessors provided by the provided state
+   * identified by stateName.
+   * 
+   * @param workflowProcessors
+   *          The {@link List} of WorkflowProcessors to subset.
+   * 
+   * @param stateName
+   *          The name of the state to subset by.
+   * @return A subset version of the provided {@link List} of
+   *         WorkflowProcessors.
+   */
+  public List<WorkflowProcessor> getWorkflowProcessorsByState(
+      List<WorkflowProcessor> workflowProcessors, String stateName) {
+    List<WorkflowProcessor> returnProcessors = new Vector<WorkflowProcessor>();
+    for (WorkflowProcessor workflowProcessor : workflowProcessors) {
+      if (workflowProcessor.getWorkflowInstance().getState().equals(stateName)) {
+        returnProcessors.add(workflowProcessor);
+      }
+    }
+    return returnProcessors;
+  }
+
+  /**
+   * Sub-selects all WorkflowProcessors provided by the provided category
+   * identified by categoryName.
+   * 
+   * @param workflowProcessors
+   *          The {@link List} of WorkflowProcessors to subset.
+   * 
+   * @param categoryName
+   *          The name of the category to subset by.
+   * @return A subset version of the provided {@link List} of
+   *         WorkflowProcessors.
+   */
+  public List<WorkflowProcessor> getWorkflowProcessorsByCategory(
+      List<WorkflowProcessor> workflowProcessors, String categoryName) {
+    List<WorkflowProcessor> returnProcessors = new Vector<WorkflowProcessor>();
+    for (WorkflowProcessor workflowProcessor : workflowProcessors) {
+      if (workflowProcessor.getWorkflowInstance().getState().getCategory()
+          .getName().equals(categoryName)) {
+        returnProcessors.add(workflowProcessor);
+      }
+    }
+    return returnProcessors;
+  }
+
+  public List<WorkflowProcessor> toTasks(WorkflowProcessor processor) {
+    List<WorkflowProcessor> options = new Vector<WorkflowProcessor>();
+    options.add(processor);
+    List<WorkflowProcessor> tasks = new Vector<WorkflowProcessor>();
+    while (!options.isEmpty()) {
+      WorkflowProcessor currentOption = options.remove(0);
+      if (currentOption.getSubProcessors().isEmpty()) {
+        tasks.add(currentOption);
+      } else {
+        if (currentOption.getPreConditions() != null)
+          options.add(currentOption.getPreConditions());
+        if (currentOption.getPostConditions() != null)
+          options.add(currentOption.getPostConditions());
+        for (WorkflowProcessor ps : currentOption.getSubProcessors())
+          options.add(ps);
+      }
+    }
+    return tasks;
+  }
+
+  public boolean containsCategory(List<WorkflowProcessor> workflowProcessors,
+      String categoryName) {
+    for (WorkflowProcessor workflowProcessor : workflowProcessors)
+      if (workflowProcessor.getWorkflowInstance().getState().getCategory()
+          .getName().equals(categoryName))
+        return true;
+    return false;
+  }
+
+  public String getHostName() {
+    String host = null;
+    try {
+      host = InetAddress.getLocalHost().getHostName();
+    } catch (Exception e) {
+      try {
+        host = ExecHelper.exec(new String[] { "hostname" }).getOutput().trim();
+      } catch (Exception e1) {
+      }
+    }
+    if (host == null)
+      return "Unknown";
+    return host;
+  }
+  
+  public WorkflowLifecycle getLifecycleForProcessor(WorkflowProcessor processor) {
+    if (processor.getWorkflowInstance() != null
+        && processor.getWorkflowInstance().getParentChildWorkflow() != null) {
+      return processor.getLifecycleManager().getLifecycleForWorkflow(
+          processor.getWorkflowInstance().getParentChildWorkflow());
+    } else
+      return processor.getLifecycleManager().getDefaultLifecycle();
+  }
+
+  private WorkflowLifecycle getLifecycle(ParentChildWorkflow model) {
+    return lifecycle.getLifecycleForWorkflow(model) != null ? lifecycle
+        .getLifecycleForWorkflow(model) : lifecycle.getDefaultLifecycle();
+  }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessorListener.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessorListener.java
new file mode 100755
index 0000000..b02ae6b
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessorListener.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.engine.processor;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.ChangeType;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>
+ * Notification Interface for WorkflowProcessors
+ * <p>
+ */
+public interface WorkflowProcessorListener {
+
+	public void notifyChange(WorkflowProcessor processor, ChangeType changeType);
+	
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessorQueue.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessorQueue.java
new file mode 100644
index 0000000..95964fe
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/processor/WorkflowProcessorQueue.java
@@ -0,0 +1,463 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine.processor;
+
+//JDK imports
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.TaskQuerier;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycle;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowState;
+import org.apache.oodt.cas.workflow.repository.WorkflowRepository;
+import org.apache.oodt.cas.workflow.structs.ConditionTaskInstance;
+import org.apache.oodt.cas.workflow.structs.Graph;
+import org.apache.oodt.cas.workflow.structs.ParentChildWorkflow;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.exceptions.EngineException;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+import org.apache.oodt.cas.workflow.structs.exceptions.RepositoryException;
+
+/**
+ * 
+ * The queue of available {@link WorkflowTask}s, that will be fed into the
+ * {@link TaskQuerier}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowProcessorQueue {
+
+  private static final Logger LOG = Logger
+      .getLogger(WorkflowProcessorQueue.class.getName());
+
+  private WorkflowInstanceRepository repo;
+
+  private WorkflowRepository modelRepo;
+
+  private WorkflowLifecycleManager lifecycle;
+
+  private Map<String, WorkflowProcessor> processorCache;
+
+  public WorkflowProcessorQueue(WorkflowInstanceRepository repo,
+      WorkflowLifecycleManager lifecycle, WorkflowRepository modelRepo) {
+    this.repo = repo;
+    this.lifecycle = lifecycle;
+    this.modelRepo = modelRepo;
+    this.processorCache = new HashMap<String, WorkflowProcessor>();
+  }
+
+  /**
+   * Should return the list of available, Queued, {@link WorkflowProcessor}s.
+   * 
+   * @return the list of available, Queued, {@link WorkflowProcessor}s.
+   */
+  public synchronized List<WorkflowProcessor> getProcessors() {
+    WorkflowInstancePage page = null;
+    try {
+      page = repo.getPagedWorkflows(1);
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Unable to load workflow processors: Message: "
+          + e.getMessage());
+      return null;
+    }
+
+    List<WorkflowProcessor> processors = new Vector<WorkflowProcessor>(
+        page.getPageWorkflows() != null ? page.getPageWorkflows().size() : 0);
+    for (WorkflowInstance inst : (List<WorkflowInstance>) (List<?>) page
+        .getPageWorkflows()) {
+      if (!inst.getState().getCategory().getName().equals("done")) {
+        WorkflowProcessor processor = null;
+        try {
+          processor = fromWorkflowInstance(inst);
+        } catch (Exception e) {
+          e.printStackTrace();
+          LOG.log(Level.WARNING,
+              "Unable to convert workflow instance: [" + inst.getId()
+                  + "] into WorkflowProcessor: Message: " + e.getMessage());
+          continue;
+        }
+        if (processor != null)
+          processors.add(processor);
+      }
+    }
+
+    return processors;
+  }
+  
+
+  public synchronized void persist(WorkflowInstance inst) {
+    try {
+      if (inst.getId() == null
+          || (inst.getId() != null && inst.getId().equals(""))) {
+        // we have to persist it by adding it
+        // rather than updating it
+        repo.addWorkflowInstance(inst);
+      } else {
+        // persist by update
+        repo.updateWorkflowInstance(inst);
+      }
+    } catch (InstanceRepositoryException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Unable to update workflow instance: [" + inst.getId()
+              + "] with status: [" + inst.getState().getName() + "]: Message: "
+              + e.getMessage());
+    }
+  }  
+
+  private WorkflowProcessor fromWorkflowInstance(WorkflowInstance inst)
+      throws EngineException {
+    WorkflowProcessor processor = null;
+    if (processorCache.containsKey(inst.getId())) {
+      return processorCache.get(inst.getId());
+    } else {
+      if (inst.getParentChildWorkflow().getGraph() == null) {
+        LOG.log(Level.SEVERE,
+            "Unable to process Graph for workflow instance: [" + inst.getId()
+                + "]");
+        return processor;
+      }
+
+      if (isCompositeProcessor(inst)) {
+        processor = getProcessorFromInstanceGraph(inst, lifecycle);
+        WorkflowState processorState = getLifecycle(
+            inst.getParentChildWorkflow()).createState(
+            "Loaded",
+            "initial",
+            "Sequential Workflow instance with id: [" + inst.getId()
+                + "] loaded by processor queue.");
+        inst.setState(processorState);
+        persist(inst);
+
+        // handle its pre-conditions
+        for (WorkflowCondition cond : inst.getParentChildWorkflow()
+            .getPreConditions()) {
+          WorkflowInstance instance = new WorkflowInstance();
+          WorkflowState condWorkflowState = lifecycle
+              .getDefaultLifecycle()
+              .createState(
+                  "Null",
+                  "initial",
+                  "Sub Pre Condition Workflow created by Workflow Processor Queue for workflow instance: "
+                      + "[" + inst.getId() + "]");
+          instance.setState(condWorkflowState);
+          instance.setPriority(inst.getPriority());
+          WorkflowTask conditionTask = toConditionTask(cond);
+          instance.setCurrentTaskId(conditionTask.getTaskId());
+          Graph condGraph = new Graph();
+          condGraph.setExecutionType("condition");
+          condGraph.setCond(cond);
+          condGraph.setTask(conditionTask);
+          ParentChildWorkflow workflow = new ParentChildWorkflow(condGraph);
+          workflow.setId("pre-cond-workflow-"
+              + inst.getParentChildWorkflow().getId());
+          workflow.setName("Pre Condition Workflow-" + cond.getConditionName());
+          workflow.getTasks().add(conditionTask);
+          instance.setParentChildWorkflow(workflow);
+          this.addToModelRepo(workflow);
+          persist(instance);
+          WorkflowProcessor subProcessor = fromWorkflowInstance(instance);
+          processor.getSubProcessors().add(subProcessor);
+          synchronized (processorCache) {
+            processorCache.put(instance.getId(), subProcessor);
+          }
+        }
+
+        // handle its tasks
+        for (WorkflowTask task : inst.getParentChildWorkflow().getTasks()) {
+          WorkflowInstance instance = new WorkflowInstance();
+          WorkflowState taskWorkflowState = lifecycle.getDefaultLifecycle()
+              .createState(
+                  "Null",
+                  "initial",
+                  "Sub Task Workflow created by Workflow Processor Queue for workflow instance: "
+                      + "[" + inst.getId() + "]");
+          instance.setState(taskWorkflowState);
+          instance.setPriority(inst.getPriority());
+          instance.setCurrentTaskId(task.getTaskId());
+          Graph taskGraph = new Graph();
+          taskGraph.setExecutionType("task");
+          taskGraph.setTask(task);
+          ParentChildWorkflow workflow = new ParentChildWorkflow(taskGraph);
+          workflow.setId("task-workflow-"
+              + inst.getParentChildWorkflow().getId());
+          workflow.setName("Task Workflow-" + task.getTaskName());
+          workflow.getTasks().add(task);
+          workflow.getGraph().setTask(task);
+          instance.setParentChildWorkflow(workflow);
+          this.addToModelRepo(workflow);
+          persist(instance);
+          WorkflowProcessor subProcessor = fromWorkflowInstance(instance);
+          processor.getSubProcessors().add(subProcessor);
+          synchronized (processorCache) {
+            processorCache.put(instance.getId(), subProcessor);
+          }
+        }
+
+        // handle its post conditions
+        for (WorkflowCondition cond : inst.getParentChildWorkflow()
+            .getPostConditions()) {
+          WorkflowInstance instance = new WorkflowInstance();
+          WorkflowState condWorkflowState = lifecycle
+              .getDefaultLifecycle()
+              .createState(
+                  "Null",
+                  "initial",
+                  "Sub Post Condition Workflow created by Workflow Processor Queue for workflow instance: "
+                      + "[" + inst.getId() + "]");
+          instance.setState(condWorkflowState);
+          instance.setPriority(inst.getPriority());
+          WorkflowTask conditionTask = toConditionTask(cond);
+          instance.setCurrentTaskId(conditionTask.getTaskId());
+          Graph condGraph = new Graph();
+          condGraph.setExecutionType("condition");
+          condGraph.setCond(cond);
+          condGraph.setTask(conditionTask);
+          ParentChildWorkflow workflow = new ParentChildWorkflow(condGraph);
+          workflow.setId("post-cond-workflow-"
+              + inst.getParentChildWorkflow().getId());
+          workflow
+              .setName("Post Condition Workflow-" + cond.getConditionName());
+          workflow.getTasks().add(conditionTask);
+          instance.setParentChildWorkflow(workflow);
+          this.addToModelRepo(workflow);
+          persist(instance);
+          WorkflowProcessor subProcessor = fromWorkflowInstance(instance);
+          processor.getSubProcessors().add(subProcessor);
+          synchronized (processorCache) {
+            processorCache.put(instance.getId(), subProcessor);
+          }
+        }
+
+      } else {
+        // it's not a composite workflow, and it's either just a task processor
+        // or a condition processor
+        if (inst.getParentChildWorkflow().getGraph().getExecutionType()
+            .equals("task")) {
+          processor = new TaskProcessor(lifecycle, inst);
+          WorkflowState taskProcessorState = getLifecycle(
+              inst.getParentChildWorkflow()).createState(
+              "Loaded",
+              "initial",
+              "Task Workflow instance with id: [" + inst.getId()
+                  + "] loaded by processor queue.");
+          inst.setState(taskProcessorState);
+
+          // handle its pre-conditions
+          for (WorkflowCondition cond : inst.getParentChildWorkflow()
+              .getGraph().getTask().getPreConditions()) {
+            WorkflowInstance instance = new WorkflowInstance();
+            WorkflowState condWorkflowState = lifecycle
+                .getDefaultLifecycle()
+                .createState(
+                    "Null",
+                    "initial",
+                    "Sub Pre Condition Workflow for Task created by Workflow Processor Queue for workflow instance: "
+                        + "[" + inst.getId() + "]");
+            instance.setState(condWorkflowState);
+            instance.setPriority(inst.getPriority());
+            WorkflowTask conditionTask = toConditionTask(cond);
+            instance.setCurrentTaskId(conditionTask.getTaskId());
+            Graph condGraph = new Graph();
+            condGraph.setExecutionType("condition");
+            condGraph.setCond(cond);
+            condGraph.setTask(conditionTask);
+            ParentChildWorkflow workflow = new ParentChildWorkflow(condGraph);
+            workflow.setId("pre-cond-workflow-"
+                + inst.getParentChildWorkflow().getGraph().getTask()
+                    .getTaskId());
+            workflow.setName("Task Pre Condition Workflow-"
+                + cond.getConditionName());
+            workflow.getTasks().add(conditionTask);
+            instance.setParentChildWorkflow(workflow);
+            this.addToModelRepo(workflow);
+            persist(instance);
+            WorkflowProcessor subProcessor = fromWorkflowInstance(instance);
+            processor.getSubProcessors().add(subProcessor);
+            synchronized (processorCache) {
+              processorCache.put(instance.getId(), subProcessor);
+            }
+          }
+
+          // handle its post-conditions
+          for (WorkflowCondition cond : inst.getParentChildWorkflow()
+              .getGraph().getTask().getPostConditions()) {
+            WorkflowInstance instance = new WorkflowInstance();
+            WorkflowState condWorkflowState = lifecycle
+                .getDefaultLifecycle()
+                .createState(
+                    "Null",
+                    "initial",
+                    "Sub Post Condition Workflow for Task created by Workflow Processor Queue for workflow instance: "
+                        + "[" + inst.getId() + "]");
+            instance.setState(condWorkflowState);
+            instance.setPriority(inst.getPriority());
+            WorkflowTask conditionTask = toConditionTask(cond);
+            instance.setCurrentTaskId(conditionTask.getTaskId());
+            Graph condGraph = new Graph();
+            condGraph.setExecutionType("condition");
+            condGraph.setCond(cond);
+            condGraph.setTask(conditionTask);
+            ParentChildWorkflow workflow = new ParentChildWorkflow(condGraph);
+            workflow.setId("post-cond-workflow-"
+                + inst.getParentChildWorkflow().getGraph().getTask()
+                    .getTaskId());
+            workflow.setName("Task Post Condition Workflow-"
+                + cond.getConditionName());
+            workflow.getTasks().add(conditionTask);
+            instance.setParentChildWorkflow(workflow);
+            this.addToModelRepo(workflow);
+            persist(instance);
+            WorkflowProcessor subProcessor = fromWorkflowInstance(instance);
+            processor.getSubProcessors().add(subProcessor);
+            synchronized (processorCache) {
+              processorCache.put(instance.getId(), subProcessor);
+            }
+          }
+
+        } else if (inst.getParentChildWorkflow().getGraph().getExecutionType()
+            .equals("condition")) {
+          processor = new ConditionProcessor(lifecycle, inst);
+          WorkflowState condProcessorState = getLifecycle(
+              inst.getParentChildWorkflow()).createState(
+              "Loaded",
+              "initial",
+              "Condition Workflow instance with id: [" + inst.getId()
+                  + "] loaded by processor queue.");
+          inst.setState(condProcessorState);
+        }
+        persist(inst);
+      }
+
+      synchronized (processorCache) {
+        processorCache.put(inst.getId(), processor);
+      }
+      return processor;
+    }
+
+  }
+  
+  private synchronized void addTaskToModelRepo(WorkflowTask task){
+    if(modelRepo != null){
+      try{
+        modelRepo.addTask(task);
+      }
+      catch(RepositoryException e){
+        e.printStackTrace();
+      }
+    }
+  }
+
+  private synchronized void addToModelRepo(Workflow workflow) {
+    if (modelRepo != null) {
+      try {
+        modelRepo.addWorkflow(workflow);
+      } catch (RepositoryException e) {
+        e.printStackTrace();
+      }
+    }
+  }
+
+  private WorkflowLifecycle getLifecycle(Workflow workflow) {
+    return lifecycle.getLifecycleForWorkflow(workflow) != null ? lifecycle
+        .getLifecycleForWorkflow(workflow) : lifecycle.getDefaultLifecycle();
+  }
+
+  private boolean isCompositeProcessor(WorkflowInstance instance) {
+    if (instance.getParentChildWorkflow().getGraph() != null
+        && instance.getParentChildWorkflow().getGraph().getExecutionType() != null
+        && !instance.getParentChildWorkflow().getGraph().getExecutionType()
+            .equals("")) {
+      return instance.getParentChildWorkflow().getGraph().getExecutionType()
+          .equals("parallel")
+          || instance.getParentChildWorkflow().getGraph().getExecutionType()
+              .equals("sequential");
+    } else {
+      // we don't have a Graph to work with, so we'll default to whether or not
+      // so we'll assume this is a workflow instance delivered to us by the
+      // instRep
+      // which doesn't understand Graphs yet (TODO: make instRep understand
+      // graphs
+      // and persist them)
+      // so the simple solution is to check whether or not the ID starts with
+      // task-workflow or pre-cond or post-cond
+      return !(instance.getParentChildWorkflow().getId()
+          .startsWith("task-workflow")
+          || instance.getParentChildWorkflow().getId().startsWith("pre-cond") || instance
+          .getParentChildWorkflow().getId().startsWith("post-cond"));
+    }
+  }
+
+  private WorkflowProcessor getProcessorFromInstanceGraph(
+      WorkflowInstance instance, WorkflowLifecycleManager lifecycle) {
+    Graph graph = instance.getParentChildWorkflow().getGraph();
+    if (graph != null && graph.getExecutionType() != null
+        && graph.getExecutionType().equals("sequential")) {
+      return new SequentialProcessor(lifecycle, instance);
+    } else {
+      return new ParallelProcessor(lifecycle, instance);
+    }
+  }
+  
+  private synchronized WorkflowTask toConditionTask(WorkflowCondition cond){    
+    String taskId = cond.getConditionId()+"-task"; // TODO: this is incompat with DataSourceWorkflowRepository
+    WorkflowTask condTask = safeGetTaskById(taskId);
+    if(condTask != null) return condTask;
+    condTask = new WorkflowTask();
+    condTask.setTaskId(taskId);
+    condTask.setTaskInstanceClassName(ConditionTaskInstance.class.getCanonicalName());
+    condTask.setTaskName(cond.getConditionName()+" Task");
+    WorkflowTaskConfiguration config = new WorkflowTaskConfiguration();
+    config.getProperties().putAll(cond.getCondConfig().getProperties());
+    // this one is a special one that will be removed by the ConditionTaskInstance class
+    config.addConfigProperty("ConditionClassName", cond.getConditionInstanceClassName()); 
+    condTask.setTaskConfig(config);
+    this.addTaskToModelRepo(condTask);
+    return condTask;
+  }
+  
+  private WorkflowTask safeGetTaskById(String taskId){
+    WorkflowTask task = null;
+      try{
+        if((task = this.modelRepo.getTaskById(taskId)) != null){
+          return task;
+        }
+      }
+      catch(RepositoryException e){
+        e.printStackTrace();
+      }
+    
+    return task;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/AbstractEngineRunnerBase.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/AbstractEngineRunnerBase.java
new file mode 100644
index 0000000..79ec8d8
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/AbstractEngineRunnerBase.java
@@ -0,0 +1,98 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine.runner;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.processor.TaskProcessor;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycle;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+
+/**
+ * 
+ * An abstract base class providing helper functionality to persist
+ * {@link WorkflowInstance}s, to get {@link WorkflowLifecycle}s from underlying
+ * {@link TaskProcessor}s, and to get {@link WorkflowTask}s from the underlying
+ * {@link TaskProcessor}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public abstract class AbstractEngineRunnerBase extends EngineRunner {
+
+  protected WorkflowInstanceRepository instRep;
+
+  private static final Logger LOG = Logger
+      .getLogger(AbstractEngineRunnerBase.class.getName());
+
+  /**
+   * Creates a new AbsractEngineRunnerBase with the provided
+   * {@link WorkflowInstanceRepository}.
+   * 
+   * @param instRep
+   *          The {@link WorkflowInstanceRepository} to use to persist
+   *          {@link TaskProcessor} {@link WorkflowInstance} information.
+   */
+  public AbstractEngineRunnerBase() {
+    this.instRep = null;
+  }
+
+  protected WorkflowTask getTaskFromProcessor(TaskProcessor taskProcessor) {
+    if (taskProcessor.getWorkflowInstance() != null
+        && taskProcessor.getWorkflowInstance().getParentChildWorkflow() != null
+        && taskProcessor.getWorkflowInstance().getParentChildWorkflow()
+            .getGraph() != null && 
+           taskProcessor.getWorkflowInstance().getParentChildWorkflow().getGraph().getTask() != null) {
+      return taskProcessor.getWorkflowInstance().getParentChildWorkflow()
+            .getGraph().getTask();
+    } else
+      return taskProcessor.getWorkflowInstance().getParentChildWorkflow()
+          .getTasks().get(0);
+  }
+
+  protected WorkflowLifecycle getLifecycle(TaskProcessor taskProcessor) {
+    return taskProcessor.getLifecycleManager().getDefaultLifecycle();
+  }
+
+  protected synchronized void persist(WorkflowInstance instance) {
+    if(instRep == null) return;
+    try {
+      if (instance.getId() == null
+          || (instance.getId() != null && instance.getId().equals(""))) {
+        // we have to persist it by adding it
+        // rather than updating it
+        instRep.addWorkflowInstance(instance);
+      } else {
+        // persist by update
+        instRep.updateWorkflowInstance(instance);
+      }
+    } catch (InstanceRepositoryException e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Unabled to persist workflow instance: ["
+          + instance.getId() + "]: Message: " + e.getMessage());
+    }    
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/AsynchronousLocalEngineRunner.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/AsynchronousLocalEngineRunner.java
new file mode 100644
index 0000000..eb99322
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/AsynchronousLocalEngineRunner.java
@@ -0,0 +1,163 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine.runner;
+
+//JDK imports
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.processor.TaskProcessor;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycle;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowState;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.util.GenericWorkflowObjectFactory;
+
+/**
+ * Runs a local version of a {@link TaskProcessor} asynchronously.
+ * 
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public class AsynchronousLocalEngineRunner extends AbstractEngineRunnerBase {
+
+  private static final Logger LOG = Logger
+      .getLogger(AsynchronousLocalEngineRunner.class.getName());
+
+  public static final int DEFAULT_NUM_THREADS = 25;
+
+  private final ExecutorService executor;
+  private final Map<String, Thread> workerMap;
+
+  public AsynchronousLocalEngineRunner() {
+    this(DEFAULT_NUM_THREADS);
+  }
+
+  public AsynchronousLocalEngineRunner(int numThreads) {
+    super();
+    this.executor = Executors.newFixedThreadPool(numThreads);
+    this.workerMap = new HashMap<String, Thread>();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.runner.EngineRunner#execute(org.apache
+   * .oodt.cas.workflow.engine.processor.TaskProcessor)
+   */
+  @Override
+  public void execute(final TaskProcessor taskProcessor) throws Exception {
+    Thread worker = new Thread() {
+
+      @Override
+      public void run() {
+        WorkflowLifecycle lifecycle = getLifecycle(taskProcessor);
+        WorkflowTask workflowTask = getTaskFromProcessor(taskProcessor);
+        WorkflowTaskInstance inst = GenericWorkflowObjectFactory
+            .getTaskObjectFromClassName(workflowTask.getTaskInstanceClassName());
+        try {
+          inst.run(taskProcessor.getWorkflowInstance().getSharedContext(),
+              workflowTask.getTaskConfig());
+          String msg = "Task: [" + workflowTask.getTaskName()
+              + "] for instance id: ["
+              + taskProcessor.getWorkflowInstance().getId()
+              + "] completed successfully";
+          LOG.log(Level.INFO, msg);
+          WorkflowState state = lifecycle.createState("ExecutionComplete", "transition", msg);
+          taskProcessor.getWorkflowInstance().setState(state);
+          persist(taskProcessor.getWorkflowInstance());
+        } catch (Exception e) {
+          e.printStackTrace();
+          String msg = "Exception executing task: ["
+              + workflowTask.getTaskName() + "]: Message: " + e.getMessage();
+          LOG.log(Level.WARNING, msg);
+          WorkflowState state = lifecycle.createState("Failure", "done", msg);
+          taskProcessor.getWorkflowInstance().setState(state);
+          persist(taskProcessor.getWorkflowInstance());
+        }
+
+      }
+
+      /*
+       * (non-Javadoc)
+       * 
+       * @see java.lang.Thread#interrupt()
+       */
+      @SuppressWarnings("deprecation")
+      @Override
+      public void interrupt() {
+        super.interrupt();
+        this.destroy();
+      }
+
+    };
+
+    String id = "";
+    synchronized (id) {
+      id = UUID.randomUUID().toString();
+      this.workerMap.put(id, worker);
+      this.executor.execute(worker);
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.engine.EngineRunner#shutdown()
+   */
+  @Override
+  public void shutdown() throws Exception {
+    for (Thread worker : this.workerMap.values()) {
+      if (worker != null) {
+        worker.interrupt();
+        worker = null;
+      }
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.runner.EngineRunner#hasOpenSlots(org
+   * .apache.oodt.cas.workflow.engine.processor.TaskProcessor)
+   */
+  @Override
+  public boolean hasOpenSlots(TaskProcessor taskProcessor) throws Exception {
+    // TODO Auto-generated method stub
+    return true;
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.workflow.engine.runner.EngineRunner#setInstanceRepository(org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository)
+   */
+  @Override
+  public void setInstanceRepository(WorkflowInstanceRepository instRep) {
+    this.instRep = instRep;    
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/AsynchronousLocalEngineRunnerFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/AsynchronousLocalEngineRunnerFactory.java
new file mode 100644
index 0000000..e8f0d4f
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/AsynchronousLocalEngineRunnerFactory.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.engine.runner;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.util.GenericWorkflowObjectFactory;
+
+/**
+ * A {@link EngineRunnerFactory} which creates
+ * {@link AsynchronousLocalEngineRunner}s.
+ * 
+ * @author bfoster (Brian Foster)
+ * @author mattmann (Chris Mattmann)
+ */
+public class AsynchronousLocalEngineRunnerFactory implements
+    EngineRunnerFactory {
+
+  private static final String NUM_THREADS_PROPERTY = "org.apache.oodt.cas.workflow.wengine.asynchronous.runner.num.threads";
+
+  private int numThreads;
+
+  public AsynchronousLocalEngineRunnerFactory() {
+    numThreads = Integer.getInteger(NUM_THREADS_PROPERTY,
+        AsynchronousLocalEngineRunner.DEFAULT_NUM_THREADS);
+  }
+
+  @Override
+  public AsynchronousLocalEngineRunner createEngineRunner() {
+    return new AsynchronousLocalEngineRunner(numThreads);
+  }
+
+  public void setNumThreads(int numThreads) {
+    this.numThreads = numThreads;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/EngineRunner.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/EngineRunner.java
new file mode 100644
index 0000000..9301ffc
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/EngineRunner.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.engine.runner;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.engine.processor.TaskProcessor;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+
+/**
+ *
+ * Obfuscates the underlying substrate on which a {@link WorkflowTask} should
+ * run. In short, executes a {@link WorkflowTask} for the Workflow Engine.
+ *
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ *
+ */
+public abstract class EngineRunner {
+
+  /**
+   * Executes a {@link TaskProcessor} on an execution substrate. Ideally there
+   * will only ever be two of these substrates, one for local execution, and
+   * another for communication with the Resource Manager.
+   *
+   * @param taskProcessor
+   *          The {@link TaskProcessor} to instantiate and execute.
+   *
+   * @throws Exception
+   *           If any error occurs.
+   */
+  public abstract void execute(TaskProcessor taskProcessor)
+      throws Exception;
+
+  /**
+   * Shuts this runner down and frees its resources.
+   *
+   * @throws Exception
+   *           If any error occurs while freeing resources.
+   *
+   */
+  public abstract void shutdown() throws Exception;
+  
+  /**
+   * Decides whether or not there are available slots within this runner
+   * to execute the provided {@link TaskProcessor}.
+   * 
+   * @param workflowTask The {@link TaskProcessor} to execute.
+   * @return True if there is an open slot, false otherwise.
+   * @throws Exception If any error occurs.
+   */
+  public abstract boolean hasOpenSlots(TaskProcessor taskProcessor) throws Exception;  
+  
+  
+  public abstract void setInstanceRepository(WorkflowInstanceRepository instRep);
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/EngineRunnerFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/EngineRunnerFactory.java
new file mode 100644
index 0000000..a11a884
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/EngineRunnerFactory.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.engine.runner;
+
+/**
+ * Factory which creates {@link EngineRunner}s.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public interface EngineRunnerFactory {
+
+   public EngineRunner createEngineRunner();
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/ResourceRunner.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/ResourceRunner.java
new file mode 100644
index 0000000..708eed4
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/ResourceRunner.java
@@ -0,0 +1,154 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine.runner;
+
+//JDK imports
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.resource.structs.Job;
+import org.apache.oodt.cas.resource.structs.exceptions.JobExecutionException;
+import org.apache.oodt.cas.resource.system.XmlRpcResourceManagerClient;
+import org.apache.oodt.cas.workflow.engine.processor.TaskProcessor;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.metadata.CoreMetKeys;
+import org.apache.oodt.cas.workflow.structs.TaskJobInput;
+import org.apache.oodt.cas.workflow.structs.WorkflowStatus;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+
+/**
+ * 
+ * Submits a {@link WorkflowTask} to the Resource Manager.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ResourceRunner extends AbstractEngineRunnerBase implements CoreMetKeys,
+    WorkflowStatus {
+
+  private static final Logger LOG = Logger.getLogger(ResourceRunner.class
+      .getName());
+
+  protected static final String DEFAULT_QUEUE_NAME = "high";
+
+  protected XmlRpcResourceManagerClient rClient;
+
+  private String currentJobId;
+
+  public ResourceRunner(URL resUrl, WorkflowInstanceRepository instRep) {
+    super();
+    this.rClient = new XmlRpcResourceManagerClient(resUrl);
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.workflow.engine.runner.EngineRunner#execute(org.apache.oodt.cas.workflow.engine.processor.TaskProcessor)
+   */
+  @Override
+  public void execute(TaskProcessor taskProcessor) throws Exception {
+    Job workflowTaskJob = new Job();
+    WorkflowTask workflowTask = getTaskFromProcessor(taskProcessor);
+    workflowTaskJob.setName(workflowTask.getTaskId());
+    workflowTaskJob
+        .setJobInstanceClassName("org.apache.oodt.cas.workflow.structs.TaskJob");
+    workflowTaskJob
+        .setJobInputClassName("org.apache.oodt.cas.workflow.structs.TaskJobInput");
+    workflowTaskJob.setLoadValue(new Integer(2));
+    workflowTaskJob.setQueueName(workflowTask.getTaskConfig().getProperty(
+        QUEUE_NAME) != null ? workflowTask.getTaskConfig().getProperty(
+        QUEUE_NAME) : DEFAULT_QUEUE_NAME);
+
+    if (workflowTask.getTaskConfig().getProperty(TASK_LOAD) != null) {
+      workflowTaskJob.setLoadValue(Integer.valueOf(workflowTask.getTaskConfig()
+          .getProperty(TASK_LOAD)));
+    }
+
+    TaskJobInput in = new TaskJobInput();
+    in.setDynMetadata(taskProcessor.getWorkflowInstance().getSharedContext());
+    in.setTaskConfig(workflowTask.getTaskConfig());
+    in.setWorkflowTaskInstanceClassName(workflowTask.getTaskInstanceClassName());
+
+    try {
+      this.currentJobId = rClient.submitJob(workflowTaskJob, in);
+    } catch (JobExecutionException e) {
+      LOG.log(Level.WARNING,
+          "Job execution exception using resource manager to execute job: Message: "
+              + e.getMessage());
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.engine.EngineRunner#shutdown()
+   */
+  @Override
+  public void shutdown() throws Exception {
+    // TODO Auto-generated method stub
+
+  }
+  
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.workflow.engine.runner.EngineRunner#hasOpenSlots(org.apache.oodt.cas.workflow.engine.processor.TaskProcessor)
+   */
+  @Override
+  public boolean hasOpenSlots(TaskProcessor taskProcessor) throws Exception {
+    // TODO Auto-generated method stub
+    return false;
+  }
+  
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.workflow.engine.runner.EngineRunner#setInstanceRepository(org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository)
+   */
+  @Override
+  public void setInstanceRepository(WorkflowInstanceRepository instRep) {
+    // TODO Auto-generated method stub
+    
+  }
+  
+  
+
+  protected boolean safeCheckJobComplete(String jobId) {
+    try {
+      return rClient.isJobComplete(jobId);
+    } catch (Exception e) {
+      LOG.log(Level.WARNING, "Exception checking completion status for job: ["
+          + jobId + "]: Messsage: " + e.getMessage());
+      return false;
+    }
+  }
+
+  protected boolean stopJob(String jobId) {
+    if (this.rClient != null && this.currentJobId != null) {
+      if (!this.rClient.killJob(this.currentJobId)) {
+        LOG.log(Level.WARNING, "Attempt to kill " + "current resmgr job: ["
+            + this.currentJobId + "]: failed");
+        return false;
+      } else
+        return true;
+    } else
+      return false;
+  }
+
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/ResourceRunnerFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/ResourceRunnerFactory.java
new file mode 100644
index 0000000..78c2295
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/engine/runner/ResourceRunnerFactory.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.engine.runner;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.util.GenericWorkflowObjectFactory;
+
+//Google imports
+import com.google.common.base.Preconditions;
+
+
+/**
+ * Factory which creates {@link ResourceRunner}s.
+ *
+ * @author bfoster (Brian Foster)
+ * @author mattmann (Chris Mattmann)
+ */
+public class ResourceRunnerFactory implements EngineRunnerFactory{
+
+   private static final Logger LOG = Logger.getLogger(ResourceRunnerFactory.class.getName());
+
+   private static final String RESOURCE_MANAGER_URL_PROPERTY = "org.apache.oodt.cas.workflow.engine.resourcemgr.url";
+
+   private static final String INSTANCE_REPO_FACTORY_PROPERTY = "workflow.engine.instanceRep.factory";
+   
+   private String resUrl;
+
+   public ResourceRunnerFactory() {
+      resUrl = System.getProperty(RESOURCE_MANAGER_URL_PROPERTY);
+   }
+
+   @Override
+   public ResourceRunner createEngineRunner() {
+      try {
+         Preconditions.checkNotNull(resUrl,
+               "Must specify Resource Manager URL [property = "
+                     + RESOURCE_MANAGER_URL_PROPERTY + "]");
+         return new ResourceRunner(new URL(resUrl), getWorkflowInstanceRepository());
+      } catch (MalformedURLException e) {
+         LOG.log(Level.SEVERE, "Failed to load ResourceRunner : " + e.getMessage(), e);
+         return null;
+      }
+   }
+
+   public void setResourceManagerUrl(String resUrl) {
+      this.resUrl = resUrl;
+   }
+   
+   protected WorkflowInstanceRepository getWorkflowInstanceRepository() {
+     return GenericWorkflowObjectFactory
+         .getWorkflowInstanceRepositoryFromClassName(System
+             .getProperty(INSTANCE_REPO_FACTORY_PROPERTY));
+   }   
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/BranchRedirector.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/BranchRedirector.java
new file mode 100644
index 0000000..42aa7a7
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/BranchRedirector.java
@@ -0,0 +1,68 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.examples;
+
+//JDK imports
+import java.net.URL;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.metadata.CoreMetKeys;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.structs.exceptions.WorkflowTaskInstanceException;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+
+/**
+ * 
+ * Redirects from an existing {@link WorkflowInstance} by sending a specified
+ * event specified by the task configuration parameter named
+ * <code>eventName</code>.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class BranchRedirector implements WorkflowTaskInstance {
+
+  public BranchRedirector() {
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance#run(org.apache
+   * .oodt.cas.metadata.Metadata,
+   * org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration)
+   */
+  @Override
+  public void run(Metadata metadata, WorkflowTaskConfiguration config)
+      throws WorkflowTaskInstanceException {
+    XmlRpcWorkflowManagerClient wm = null;
+
+    try {
+      wm = new XmlRpcWorkflowManagerClient(new URL(
+          metadata.getMetadata(CoreMetKeys.WORKFLOW_MANAGER_URL)));
+      wm.sendEvent(config.getProperty("eventName"), metadata);
+    } catch (Exception e) {
+      throw new WorkflowTaskInstanceException(e.getMessage());
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/CheckForMetadataKeys.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/CheckForMetadataKeys.java
new file mode 100644
index 0000000..100f9eb
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/CheckForMetadataKeys.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.examples;
+
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionInstance;
+
+public class CheckForMetadataKeys implements WorkflowConditionInstance {
+
+    public boolean evaluate(Metadata metadata,
+            WorkflowConditionConfiguration config) {
+        String[] reqMetKeys = (config.getProperty("reqMetKeys") + ",")
+                .split(",");
+        for (String reqMetKey : reqMetKeys) {
+            if (!metadata.containsKey(reqMetKey))
+                return false;
+        }
+        return true;
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/ExternScriptTaskInstance.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/ExternScriptTaskInstance.java
new file mode 100644
index 0000000..8f82409
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/ExternScriptTaskInstance.java
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.examples;
+
+//Java imports
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Iterator;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author davoodi
+ * @version $Revsion$
+ * @since OODT-226
+ * 
+ * <p>
+ * A task that takes in the static configuration parameter, and metadata
+ * &quot;args&quot;, then runs an external script.
+ * </p>
+ */
+public class ExternScriptTaskInstance implements WorkflowTaskInstance {
+
+    /**
+     * 
+     */
+    public ExternScriptTaskInstance() {
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance#run(java.util.Map,
+     *      org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration)
+     */
+    public void run(Metadata metadata, WorkflowTaskConfiguration config) {
+        List args = metadata.getAllMetadata("Args"); // command line
+        // arguments for a
+        // specific script.
+        String pathToScript = config.getProperty("PathToScript"); // should
+        // include
+        // the file
+        // name as
+        // well.
+        String shellType = config.getProperty("ShellType"); // e.g. /bin/sh/
+
+        // joining the argument list's elements to a string
+        StringBuffer buffer = new StringBuffer();
+        Iterator iter = args.iterator();
+        while (iter.hasNext()) {
+            buffer.append(iter.next());
+            if (iter.hasNext()) {
+                buffer.append(" ");
+            }
+        }
+        String cmdLine = shellType + " " + pathToScript + " "
+                + buffer.toString();
+
+        // executing the external script on the command line
+        Runtime runtime = Runtime.getRuntime();
+        Process proc = null;
+        try {
+            proc = runtime.exec(cmdLine);
+        } catch (IOException e1) {
+            // TODO Auto-generated catch block
+            e1.printStackTrace();
+        }
+        InputStream inputstream = proc.getInputStream();
+        InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
+        BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
+
+        // sending the script's output result to System.out to be printed
+        String cmdlnOutput;
+        try {
+            while ((cmdlnOutput = bufferedreader.readLine()) != null) {
+                System.out.println(cmdlnOutput);
+            }
+        } catch (IOException e1) {
+            // TODO Auto-generated catch block
+            e1.printStackTrace();
+        }
+        try {
+            if (proc.waitFor() != 0) {
+                System.err
+                        .println("the process did not terminate normally exit code: ["
+                                + proc.exitValue() + "]");
+            }
+        } catch (InterruptedException e) {
+            System.err.println(e);
+        } finally {
+            if (bufferedreader != null) {
+                try {
+                    bufferedreader.close();
+                } catch (Exception ignore) {
+                }
+
+                bufferedreader = null;
+            }
+        }
+
+    }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/FalseCondition.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/FalseCondition.java
new file mode 100644
index 0000000..7d7a038
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/FalseCondition.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.examples;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionInstance;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>A {@link WorkflowConditionInstance} that always returns false.</p>
+ *
+ */
+public class FalseCondition implements WorkflowConditionInstance {
+
+	/**
+	 * 
+	 */
+	public FalseCondition() {
+		super();
+		// TODO Auto-generated constructor stub
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.oodt.cas.workflow.structs.WorkflowConditionInstance#evaluate(org.apache.oodt.cas.metadata.Metadata)
+	 */
+	public boolean evaluate(Metadata metadata, WorkflowConditionConfiguration config) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/FilterTask.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/FilterTask.java
new file mode 100644
index 0000000..9f7ad36
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/FilterTask.java
@@ -0,0 +1,103 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.examples;
+
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.structs.exceptions.WorkflowTaskInstanceException;
+
+/**
+ * Filters dynamic {@link Metadata} from the provided metadata in the
+ * {@link #run(Metadata, WorkflowTaskConfiguration)} method.
+ * 
+ * The config parameter in {@link #run(Metadata, WorkflowTaskConfiguration)}
+ * defines metadata parameters to remove and rename via the following
+ * directives:
+ * 
+ * <ul>
+ * <li>Remove_Key - a comma separated list of keys to remove</li>
+ * <li>Rename_[Key] - set the value of this property to the new name of the
+ * [Key] parameter. E.g., having a key in the task configuration named
+ * Rename_Filename with value set to Prior_Filename will rename the key in the
+ * dynamic metadata named Filename to the new name of Prior_Filename, preserving
+ * its prior value.</li>
+ * </ul>
+ * 
+ * Note that the Rename keys will be evaluated first, before the Remove_Key
+ * configuration parameter is evaluated.
+ * 
+ */
+public class FilterTask implements WorkflowTaskInstance {
+
+	private final static String REMOVE_KEY = "Remove_Key";
+	private static final Logger LOG = Logger.getLogger(FilterTask.class
+			.getName());
+
+	@Override
+	public void run(Metadata metadata, WorkflowTaskConfiguration config)
+			throws WorkflowTaskInstanceException {
+
+		// evaluate renames
+		for (Object configKey : config.getProperties().keySet()) {
+			String configKeyName = (String) configKey;
+			if (configKeyName.startsWith("Rename")) {
+				String renameOrigKeyName = configKeyName.split("_")[1];
+				String renameKeyName = config.getProperty(configKeyName);
+				// check to see if key exists
+				if (metadata.containsKey(renameOrigKeyName)) {
+					LOG.log(Level.INFO, "Renaming key: [" + renameOrigKeyName
+							+ "] to [" + renameKeyName + "]: values: "
+							+ metadata.getAllMetadata(renameOrigKeyName));
+					metadata.replaceMetadata(renameKeyName,
+							metadata.getAllMetadata(renameOrigKeyName));
+					metadata.removeMetadata(renameOrigKeyName);
+				} else {
+					LOG.log(Level.WARNING, "Request to rename key: ["
+							+ renameOrigKeyName + "] to [" + renameKeyName
+							+ "]: orig key does not exist in dynamic metadata!");
+				}
+			}
+		}
+
+		// evaluate removes
+		if (config.getProperties().containsKey(REMOVE_KEY)) {
+			String removeMetKeyNames = config.getProperty(REMOVE_KEY);
+			for (String keyName : Arrays.asList(removeMetKeyNames.split(","))) {
+				// handle whitespace
+				keyName = keyName.trim();
+				if (metadata.containsKey(keyName)) {
+					LOG.log(Level.INFO,
+							"Removing key from workflow metadata: [" + keyName
+									+ "]: values: "
+									+ metadata.getAllMetadata(keyName));
+					metadata.removeMetadata(keyName);
+				} else {
+					LOG.log(Level.WARNING, "Request to remove key: [" + keyName
+							+ "]: key does not exist in workflow metadata!");  
+				}
+			}
+		}
+
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/GoodbyeWorld.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/GoodbyeWorld.java
new file mode 100644
index 0000000..b851a74
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/GoodbyeWorld.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.examples;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revsion$
+ * 
+ * <p>A simple task that takes in a static configuration parameter, "Person", 
+ * and echos the string "Goodbye ${person}".</p>
+ */
+public class GoodbyeWorld implements WorkflowTaskInstance {
+
+	/**
+	 * 
+	 */
+	public GoodbyeWorld() {
+		super();
+		// TODO Auto-generated constructor stub
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.oodt.cas.workflow.structs.WorkflowTasInstancek#run(org.apache.oodt.cas.metadata.Metadata, 
+	 * org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration)
+	 */
+	public void run(Metadata metadata, WorkflowTaskConfiguration config) {
+		System.out.println("Goodbye World: "+config.getProperties().get("Person"));
+
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/HelloWorld.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/HelloWorld.java
new file mode 100644
index 0000000..73ad37d
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/HelloWorld.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.examples;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revsion$
+ * 
+ * <p>A simple task that takes in the static configuration
+ * parameter, "Person", and echos the String "Hello ${person}."</p>
+ */
+public class HelloWorld implements WorkflowTaskInstance {
+
+	/**
+	 * 
+	 */
+	public HelloWorld() {
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance#run(java.util.Map, 
+	 * org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration)
+	 */
+	public void run(Metadata metadata, WorkflowTaskConfiguration config) {
+		System.out.println("Hello World: "+config.getProperties().get("Person"));
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/LongCondition.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/LongCondition.java
new file mode 100644
index 0000000..1f3c5a9
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/LongCondition.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.examples;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionInstance;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>A Simple condition that evaluates to false as many times as specified
+ * by the dynamic metadata parameter "numFalse". After that, the condition returns
+ * true.</p>
+ *
+ */
+public class LongCondition implements WorkflowConditionInstance {
+
+	private int timesFalse = 0;
+	
+	/**
+	 * 
+	 */
+	public LongCondition() {
+		super();
+		// TODO Auto-generated constructor stub
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.oodt.cas.workflow.structs.WorkflowConditionInstance#evaluate(org.apache.oodt.cas.metadata.Metadata)
+	 */
+    public boolean evaluate(Metadata metadata, WorkflowConditionConfiguration config) {
+		//simulate that this condition takes a passed in amount of seconds to wait for
+		
+		int numFalse = (String)metadata.getMetadata("numFalse") != null ? Integer.parseInt((String)metadata.getMetadata("numFalse")):5;
+		System.out.println("Condition: Num false: "+numFalse);
+		
+		if(timesFalse < numFalse){
+			timesFalse++;
+			return false;			
+		}
+		else return true;
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/LongTask.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/LongTask.java
new file mode 100644
index 0000000..bfcbd01
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/LongTask.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.examples;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>An example task to simulate actual work that should last
+ * a specified number of seconds.</p>
+ *
+ */
+public class LongTask implements WorkflowTaskInstance {
+
+	/**
+	 * 
+	 */
+	public LongTask() {
+		super();
+		// TODO Auto-generated constructor stub
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance#run(org.apache.oodt.cas.metadata.Metadata, 
+	 * org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration)
+	 */
+	public void run(Metadata metadata, WorkflowTaskConfiguration config) {
+		//simulate that this job takes a passed in amount of seconds to execute for
+		
+		long waitSeconds = (String)metadata.getMetadata("numSeconds") != null ? Long.parseLong((String)metadata.getMetadata("numSeconds")):10L;
+		System.out.println("Task: Num seconds: "+waitSeconds);
+		
+		  try{
+			  Thread.currentThread().sleep(waitSeconds*1000);
+		  }
+		  catch(InterruptedException ignore){}
+
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/MailTask.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/MailTask.java
new file mode 100644
index 0000000..e284830
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/MailTask.java
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.examples;
+
+//JDK imports
+import java.util.Date;
+import java.util.Properties;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.structs.exceptions.WorkflowTaskInstanceException;
+
+/**
+ * 
+ * A CAS {@link WorkflowTaskInstance} responsible for sending an email
+ * to a recipient notifying them of ingest.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class MailTask implements WorkflowTaskInstance {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance#run(gov.nasa
+   * .jpl.oodt.cas.metadata.Metadata,
+   * org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration)
+   */
+  public void run(Metadata metadata, WorkflowTaskConfiguration config)
+      throws WorkflowTaskInstanceException {
+    Properties mailProps = new Properties();
+    mailProps.setProperty("mail.host", "smtp.jpl.nasa.gov");
+    mailProps.setProperty("mail.user", "mattmann");
+    
+    Session session = Session.getInstance(mailProps);
+
+    String msgTxt = "Hello "
+        + config.getProperty("user.name")
+        + ":\n\n"
+        + "You have successfully ingested the file with the following metadata: \n\n"
+        + getMsgStringFromMet(metadata) + "\n\n" + "Thanks!\n\n" + "CAS";
+
+    Message msg = new MimeMessage(session);
+    try {
+      msg.setSubject(config.getProperty("msg.subject"));
+      msg.setSentDate(new Date());
+      msg.setFrom(InternetAddress.parse(config.getProperty("mail.from"))[0]);
+      msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(config
+          .getProperty("mail.to"), false));
+      msg.setText(msgTxt);
+      Transport.send(msg);
+
+    } catch (MessagingException e) {
+      throw new WorkflowTaskInstanceException(e.getMessage());
+    }
+
+  }
+
+  private String getMsgStringFromMet(Metadata met) {
+    StringBuffer buf = new StringBuffer();
+    for (Object key : met.getHashtable().keySet()) {
+      String keyStr = (String) key;
+      StringBuffer val = new StringBuffer();
+      for (Object value : met.getAllMetadata(keyStr)) {
+        String valStr = (String) value;
+        val.append(valStr);
+        val.append(",");
+      }
+      val.deleteCharAt(val.length() - 1);
+
+      buf.append("[" + keyStr + "=>" + val + "]\n");
+    }
+
+    return buf.toString();
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/NoOpTask.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/NoOpTask.java
new file mode 100644
index 0000000..3928fcf
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/NoOpTask.java
@@ -0,0 +1,50 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.examples;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.structs.exceptions.WorkflowTaskInstanceException;
+
+/**
+ * 
+ * Performs no action, an is a no-op.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class NoOpTask implements WorkflowTaskInstance {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance#run(org.apache
+   * .oodt.cas.metadata.Metadata,
+   * org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration)
+   */
+  @Override
+  public void run(Metadata metadata, WorkflowTaskConfiguration config)
+      throws WorkflowTaskInstanceException {
+
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/NumIncrementTask.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/NumIncrementTask.java
new file mode 100644
index 0000000..36656f1
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/NumIncrementTask.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.examples;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * @since OODT-53
+ * 
+ * <p>
+ * This task illustrates OODT-53 by taking a <code>num</code> {@link Metadata}
+ * parameter and then incrementing it. Subsequent executions of this same
+ * {@link WorkflowTaskInstance} within a {@link Workflow} should yield
+ * incremented versions of the initially provided <code>num</code> parameter.
+ * </p>.
+ */
+public class NumIncrementTask implements WorkflowTaskInstance {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance#run(org.apache.oodt.cas.metadata.Metadata,
+   *      org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration)
+   */
+  public void run(Metadata metadata, WorkflowTaskConfiguration config) {
+    // read the num from the metadata, and then increment it
+    // and update the metadata
+    if (metadata.getMetadata("num") == null
+        || (metadata.getMetadata("num") != null && metadata.getMetadata("num")
+            .equals(""))) {
+      return;
+    }
+
+    int num = Integer.parseInt(metadata.getMetadata("num"));
+    System.out.println("Num pre increment: ["+num+"]");
+    num++;
+    System.out.println("Num post increment: ["+num+"]");
+    metadata.replaceMetadata("num", String.valueOf(num));
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/RandomStatusUpdateTask.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/RandomStatusUpdateTask.java
new file mode 100644
index 0000000..52a08fc
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/RandomStatusUpdateTask.java
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.examples;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Random;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManager;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * This class illustrates OODT-86, demonstrating how the method
+ * {@link XmlRpcWorkflowManager#updateWorkflowInstance(java.util.Hashtable)}
+ * allows a user to change the status of a given {@link WorkflowInstance}
+ * programmatically.
+ */
+public class RandomStatusUpdateTask implements WorkflowTaskInstance {
+
+    private static final String[] statuses = new String[] { "THINKING",
+            "RUNNING", "WAITING", "INFINITELY WAITING", "WATCHING TV",
+            "SLEEPING", "DREAMING", "WORKING", "WATCHING MOVIES" };
+
+    private final int numStatusesToDisplay = 10;
+
+    private XmlRpcWorkflowManagerClient client = null;
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance#run(org.apache.oodt.cas.metadata.Metadata,
+     *      org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration)
+     */
+    public void run(Metadata metadata, WorkflowTaskConfiguration config) {
+        // the goal in this task to is randomly display statuses, and then sleep
+        // for 5 seconds
+        // after each status is picked
+        setWorkflowMgrUrl(metadata.getMetadata("WorkflowManagerUrl"));
+        String workflowInstId = metadata.getMetadata("WorkflowInstId");
+
+        int numPicked = 0;
+        Random r = new Random();
+
+        while (numPicked < 10) {
+            int idx = r.nextInt(statuses.length);
+            String statusPicked = statuses[idx];
+            updateWorkflowInstanceStatus(workflowInstId, statusPicked);
+            try {
+                Thread.currentThread().sleep(5000L);
+            } catch (InterruptedException ignore) {
+            }
+            numPicked++;
+        }
+
+    }
+
+    private void updateWorkflowInstanceStatus(String wInstId, String status) {
+        System.out.println("Sending status update for "+wInstId+","+status);
+        try {
+            this.client.updateWorkflowInstanceStatus(wInstId, status);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    private void setWorkflowMgrUrl(String wmUrlStr) {
+        System.out.println("Connecting to workflow mgr: ["+wmUrlStr+"]");
+        this.client = new XmlRpcWorkflowManagerClient(safeGetUrl(wmUrlStr));
+    }
+
+    private URL safeGetUrl(String urlStr) {
+        try {
+            return new URL(urlStr);
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/TrueCondition.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/TrueCondition.java
new file mode 100644
index 0000000..30982b8
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/examples/TrueCondition.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.examples;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionInstance;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revsion$
+ * 
+ * <p>A simple condition that always returns true when invoked.</p>
+ */
+public class TrueCondition implements WorkflowConditionInstance {
+
+	/**
+	 * 
+	 */
+	public TrueCondition() {
+		super();
+		// TODO Auto-generated constructor stub
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.oodt.cas.workflow.structs.WorkflowConditionInstance#evaluate(org.apache.oodt.cas.metadata.Metadata)
+	 */
+    public boolean evaluate(Metadata metadata, WorkflowConditionConfiguration config) {
+		return true;
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/AbstractPaginatibleInstanceRepository.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/AbstractPaginatibleInstanceRepository.java
new file mode 100644
index 0000000..0bd1eef
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/AbstractPaginatibleInstanceRepository.java
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.instrepo;
+
+//JDK imports
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+import org.apache.oodt.commons.pagination.PaginationUtils;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public abstract class AbstractPaginatibleInstanceRepository implements
+        WorkflowInstanceRepository {
+
+    protected int pageSize = -1;
+
+    /* our log stream */
+    private static final Logger LOG = Logger
+            .getLogger(AbstractPaginatibleInstanceRepository.class.getName());
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.util.Pagination#getFirstPage()
+     */
+    public WorkflowInstancePage getFirstPage() {
+        WorkflowInstancePage firstPage = null;
+
+        try {
+            firstPage = getPagedWorkflows(1);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception getting first page: Message: "
+                    + e.getMessage());
+        }
+        return firstPage;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.util.Pagination#getLastPage()
+     */
+    public WorkflowInstancePage getLastPage() {
+        WorkflowInstancePage lastPage = null;
+        WorkflowInstancePage firstPage = getFirstPage();
+
+        try {
+            lastPage = getPagedWorkflows(firstPage.getTotalPages());
+        } catch (Exception e) {
+            LOG.log(Level.WARNING, "Exception getting last page: Message: "
+                    + e.getMessage());
+        }
+
+        return lastPage;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.util.Pagination#getNextPage(org.apache.oodt.cas.workflow.structs.WorkflowInstancePage)
+     */
+    public WorkflowInstancePage getNextPage(WorkflowInstancePage currentPage) {
+        if (currentPage == null) {
+            return getFirstPage();
+        }
+
+        if (currentPage.isLastPage()) {
+            return currentPage;
+        }
+
+        WorkflowInstancePage nextPage = null;
+
+        try {
+            nextPage = getPagedWorkflows(currentPage.getPageNum() + 1);
+        } catch (Exception e) {
+            LOG.log(Level.WARNING, "Exception getting next page: Message: "
+                    + e.getMessage());
+        }
+
+        return nextPage;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.util.Pagination#getPrevPage(org.apache.oodt.cas.workflow.structs.WorkflowInstancePage)
+     */
+    public WorkflowInstancePage getPrevPage(WorkflowInstancePage currentPage) {
+        if (currentPage == null) {
+            return getFirstPage();
+        }
+
+        if (currentPage.isLastPage()) {
+            return currentPage;
+        }
+
+        WorkflowInstancePage nextPage = null;
+
+        try {
+            nextPage = getPagedWorkflows(currentPage.getPageNum() - 1);
+        } catch (Exception e) {
+            LOG.log(Level.WARNING, "Exception getting next page: Message: "
+                    + e.getMessage());
+        }
+
+        return nextPage;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.util.Pagination#getPagedWorkflows(int)
+     */
+    public WorkflowInstancePage getPagedWorkflows(int pageNum)
+            throws InstanceRepositoryException {
+        return getPagedWorkflows(pageNum, null);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.util.Pagination#getPagedWorkflows(int,
+     *      java.lang.String)
+     */
+    public WorkflowInstancePage getPagedWorkflows(int pageNum, String status)
+            throws InstanceRepositoryException {
+        int totalPages = PaginationUtils.getTotalPage(
+                status != null ? getNumWorkflowInstancesByStatus(status)
+                        : getNumWorkflowInstances(), this.pageSize);
+
+        /*
+         * if there are 0 total pages in the result list size then don't bother
+         * returning a valid product page instead, return blank ProductPage
+         */
+        if (totalPages == 0 || pageNum > totalPages || pageNum <= 0) {
+            return WorkflowInstancePage.blankPage();
+        }
+
+        WorkflowInstancePage retPage = new WorkflowInstancePage();
+        retPage.setPageNum(pageNum);
+        retPage.setPageSize(this.pageSize);
+        retPage.setTotalPages(totalPages);
+
+        List wInstIds = paginateWorkflows(pageNum, status);
+
+        if (wInstIds != null && wInstIds.size() > 0) {
+            List workflowInstances = new Vector(wInstIds.size());
+
+            for (Iterator i = wInstIds.iterator(); i.hasNext();) {
+                String workflowInstId = (String) i.next();
+                WorkflowInstance inst = getWorkflowInstanceById(workflowInstId);
+                workflowInstances.add(inst);
+            }
+
+            retPage.setPageWorkflows(workflowInstances);
+        }
+
+        return retPage;
+    }
+
+    /**
+     * 
+     * @param pageNum
+     * @return
+     * @throws InstanceRepositoryException
+     */
+    protected List paginateWorkflows(int pageNum)
+            throws InstanceRepositoryException {
+        return paginateWorkflows(pageNum, null);
+    }
+
+    /**
+     * 
+     * @param pageNum
+     * @param status
+     * @return
+     * @throws InstanceRepositoryException
+     */
+    protected abstract List paginateWorkflows(int pageNum, String status)
+            throws InstanceRepositoryException;
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/DataSourceWorkflowInstanceRepository.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/DataSourceWorkflowInstanceRepository.java
new file mode 100644
index 0000000..ae672cc
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/DataSourceWorkflowInstanceRepository.java
@@ -0,0 +1,1029 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.instrepo;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+import org.apache.oodt.cas.workflow.util.DbStructFactory;
+
+//JDK imports
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.sql.DataSource;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A {@link WorkflowInstanceRepository} that persists {@link WorkflowInstance}s
+ * to a JDBC-accessible DBMS.
+ * </p>.
+ */
+public class DataSourceWorkflowInstanceRepository extends
+        AbstractPaginatibleInstanceRepository {
+
+    /* our data source */
+    private DataSource dataSource = null;
+
+    /* our log stream */
+    private static final Logger LOG = Logger
+            .getLogger(DataSourceWorkflowInstanceRepository.class.getName());
+
+    /* should we quote fields or not */
+    private boolean quoteFields = false;
+
+    public DataSourceWorkflowInstanceRepository(DataSource ds,
+            boolean quoteFields, int pageSize) {
+        this.dataSource = ds;
+        this.quoteFields = quoteFields;
+        this.pageSize = pageSize;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.engine.WorkflowInstanceRepository#addWorkflowInstance(org.apache.oodt.cas.workflow.structs.WorkflowInstance)
+     */
+    public synchronized void addWorkflowInstance(WorkflowInstance wInst)
+            throws InstanceRepositoryException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String startWorkflowSql = null;
+            String taskIdField = null;
+            String workflowIdField = null;
+
+            if (quoteFields) {
+                taskIdField = "'"
+                        + ((WorkflowTask) wInst.getWorkflow().getTasks().get(0))
+                                .getTaskId() + "'";
+                workflowIdField = "'" + wInst.getWorkflow().getId() + "'";
+            } else {
+                taskIdField = ((WorkflowTask) wInst.getWorkflow().getTasks()
+                        .get(0)).getTaskId();
+                workflowIdField = wInst.getWorkflow().getId();
+            }
+
+            startWorkflowSql = "INSERT INTO workflow_instances "
+                    + "(workflow_instance_status, workflow_id, current_task_id,"
+                    + "start_date_time, end_date_time, current_task_start_date_time,"
+                    + "current_task_end_date_time, priority, times_blocked) " + "VALUES ('"
+                    + wInst.getStatus() + "', " + workflowIdField + ","
+                    + taskIdField + ", '" + wInst.getStartDateTimeIsoStr()
+                    + "','" + wInst.getEndDateTimeIsoStr() + "','"
+                    + wInst.getCurrentTaskStartDateTimeIsoStr() + "','"
+                    + wInst.getCurrentTaskEndDateTimeIsoStr() + "', "+wInst.getPriority().getValue()+", "
+                    + wInst.getTimesBlocked() + ")";
+
+            LOG.log(Level.FINE, "sql: Executing: " + startWorkflowSql);
+            statement.execute(startWorkflowSql);
+
+            String workflowInstId = new String();
+
+            synchronized (workflowInstId) {
+                String getWorkflowInstIdSql = "SELECT MAX(workflow_instance_id) "
+                        + "AS max_id FROM workflow_instances";
+
+                rs = statement.executeQuery(getWorkflowInstIdSql);
+
+                while (rs.next()) {
+                    workflowInstId = String.valueOf(rs.getInt("max_id"));
+                }
+            }
+
+            conn.commit();
+            wInst.setId(workflowInstId);
+
+            // now add its metadata
+            addWorkflowInstanceMetadata(wInst);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception starting workflow. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback startWorkflow transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.engine.WorkflowInstanceRepository#updateWorkflowInstance(org.apache.oodt.cas.workflow.structs.WorkflowInstance)
+     */
+    public synchronized void updateWorkflowInstance(WorkflowInstance wInst)
+            throws InstanceRepositoryException {
+        Connection conn = null;
+        Statement statement = null;
+        String taskIdField = null, workflowIdField = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            if (quoteFields) {
+                taskIdField = "'" + wInst.getCurrentTaskId() + "'";
+                workflowIdField = "'" + wInst.getWorkflow().getId() + "'";
+            } else {
+                taskIdField = wInst.getCurrentTaskId();
+                workflowIdField = wInst.getWorkflow().getId();
+            }
+
+            String updateStatusSql = "UPDATE workflow_instances SET "
+                    + "workflow_instance_status='" + wInst.getStatus()
+                    + "', current_task_id=" + taskIdField + ", workflow_id = "
+                    + workflowIdField + ",start_date_time='"
+                    + wInst.getStartDateTimeIsoStr() + "'," + "end_date_time='"
+                    + wInst.getEndDateTimeIsoStr()
+                    + "',current_task_start_date_time='"
+                    + wInst.getCurrentTaskStartDateTimeIsoStr()
+                    + "',current_task_end_date_time='"
+                    + wInst.getCurrentTaskEndDateTimeIsoStr()
+                    + "',priority="
+                    + wInst.getPriority().getValue()
+                    + ",times_blocked="
+                    + wInst.getTimesBlocked()
+                    +" WHERE workflow_instance_id = " + wInst.getId();
+
+            LOG.log(Level.FINE, "updateStatusSql: Executing: "
+                    + updateStatusSql);
+            statement.execute(updateStatusSql);
+            conn.commit();
+
+            // now update its metadata
+            removeWorkflowInstanceMetadata(wInst.getId());
+            addWorkflowInstanceMetadata(wInst);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception updating workflow instance. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback updateWorkflowInstanceStatus "
+                                + "transaction. Message: " + e2.getMessage());
+            }
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.engine.WorkflowInstanceRepository#removeWorkflowInstance(org.apache.oodt.cas.workflow.structs.WorkflowInstance)
+     */
+    public synchronized void removeWorkflowInstance(WorkflowInstance wInst)
+            throws InstanceRepositoryException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String deleteSql = "DELETE FROM workflow_instances "
+                    + "WHERE workflow_instance_id = " + wInst.getId();
+
+            LOG.log(Level.FINE, "sql: Executing: " + deleteSql);
+            statement.execute(deleteSql);
+            conn.commit();
+
+            // now remove its metadata
+            removeWorkflowInstanceMetadata(wInst.getId());
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception removing workflow instance. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback removeWorkflowInstance "
+                                + "transaction. Message: " + e2.getMessage());
+            }
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.engine.WorkflowInstanceRepository#getWorkflowInstanceById(java.lang.String)
+     */
+    public WorkflowInstance getWorkflowInstanceById(String workflowInstId)
+            throws InstanceRepositoryException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        WorkflowInstance workflowInst = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getWorkflowSql = "SELECT * from workflow_instances "
+                    + "WHERE workflow_instance_id = " + workflowInstId;
+
+            LOG.log(Level.FINE, "getWorkflowInstanceById: Executing: "
+                    + getWorkflowSql);
+            rs = statement.executeQuery(getWorkflowSql);
+
+            while (rs.next()) {
+                workflowInst = DbStructFactory.getWorkflowInstance(rs);
+                // add its metadata
+                workflowInst
+                        .setSharedContext(getWorkflowInstanceMetadata(workflowInst
+                                .getId()));
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception getting workflow instance. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getWorkflowInstanceById "
+                                + "transaction. Message: " + e2.getMessage());
+            }
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return workflowInst;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.engine.WorkflowInstanceRepository#getWorkflowInstances()
+     */
+    public List getWorkflowInstances() throws InstanceRepositoryException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+        List workflowInsts = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getWorkflowSql = "SELECT * from workflow_instances "
+                    + "ORDER BY workflow_instance_id DESC";
+
+            LOG.log(Level.FINE, "getWorkflowInstances: Executing: "
+                    + getWorkflowSql);
+            rs = statement.executeQuery(getWorkflowSql);
+
+            workflowInsts = new Vector();
+            while (rs.next()) {
+                WorkflowInstance workflowInst = DbStructFactory
+                        .getWorkflowInstance(rs);
+                // add its metadata
+                workflowInst
+                        .setSharedContext(getWorkflowInstanceMetadata(workflowInst
+                                .getId()));
+                workflowInsts.add(workflowInst);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception getting workflow instance. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getWorkflowInstances "
+                                + "transaction. Message: " + e2.getMessage());
+            }
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return workflowInsts;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.engine.WorkflowInstanceRepository#getWorkflowInstancesByStatus(java.lang.String)
+     */
+    public List getWorkflowInstancesByStatus(String status)
+            throws InstanceRepositoryException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        List workflowInsts = null;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getWorkflowSql = "SELECT * from workflow_instances "
+                    + "WHERE workflow_instance_status = '" + status
+                    + "' ORDER BY workflow_instance_id DESC";
+
+            LOG.log(Level.FINE, "getWorkflowInstancesByStatus: Executing: "
+                    + getWorkflowSql);
+            rs = statement.executeQuery(getWorkflowSql);
+
+            workflowInsts = new Vector();
+            while (rs.next()) {
+                WorkflowInstance workflowInst = DbStructFactory
+                        .getWorkflowInstance(rs);
+                // add its metadata
+                workflowInst
+                        .setSharedContext(getWorkflowInstanceMetadata(workflowInst
+                                .getId()));
+                workflowInsts.add(workflowInst);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception getting workflow instance. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getWorkflowInstancesByStatus "
+                                + "transaction. Message: " + e2.getMessage());
+            }
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return workflowInsts;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#getNumWorkflowInstances()
+     */
+    public int getNumWorkflowInstances() throws InstanceRepositoryException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+        int numInsts = -1;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getWorkflowSql = "SELECT COUNT(workflow_instance_id) AS num_insts from workflow_instances";
+
+            LOG.log(Level.FINE, "getNumWorkflowInstances: Executing: "
+                    + getWorkflowSql);
+            rs = statement.executeQuery(getWorkflowSql);
+
+            while (rs.next()) {
+                numInsts = rs.getInt("num_insts");
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception getting num workflow instances. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getNumWorkflowInstances "
+                                + "transaction. Message: " + e2.getMessage());
+            }
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return numInsts;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#getNumWorkflowInstancesByStatus(java.lang.String)
+     */
+    public int getNumWorkflowInstancesByStatus(String status)
+            throws InstanceRepositoryException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+        int numInsts = -1;
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getWorkflowSql = "SELECT COUNT(workflow_instance_id) AS num_insts from workflow_instances "
+                    + "WHERE workflow_instance_status = '" + status + "'";
+
+            LOG.log(Level.FINE, "getNumWorkflowInstancesByStatus: Executing: "
+                    + getWorkflowSql);
+            rs = statement.executeQuery(getWorkflowSql);
+
+            while (rs.next()) {
+                numInsts = rs.getInt("num_insts");
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception getting num workflow instances by status. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getNumWorkflowInstancesByStatus "
+                                + "transaction. Message: " + e2.getMessage());
+            }
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return numInsts;
+    }
+
+    protected List paginateWorkflows(int pageNum, String status)
+            throws InstanceRepositoryException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        List wInstIds = null;
+        int numResults = -1;
+
+        if (status == null || (status != null && status.equals(""))) {
+            numResults = getNumWorkflowInstances();
+        } else {
+            numResults = getNumWorkflowInstancesByStatus(status);
+        }
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
+                    ResultSet.CONCUR_READ_ONLY);
+
+            String getWorkflowSql = "SELECT workflow_instance_id FROM workflow_instances ";
+            if (status != null && !status.equals("")) {
+                getWorkflowSql += "WHERE workflow_instance_status = '" + status
+                        + "'";
+
+            }
+
+            getWorkflowSql += "ORDER BY workflow_instance_id DESC ";
+
+            LOG.log(Level.FINE, "workflow instance paged query: executing: "
+                    + getWorkflowSql);
+
+            rs = statement.executeQuery(getWorkflowSql);
+            wInstIds = new Vector();
+
+            int startNum = (pageNum - 1) * pageSize;
+
+            if (startNum > numResults) {
+                startNum = 0;
+            }
+
+            // must call next first, or else no relative cursor
+            if (rs.next()) {
+                // grab the first one
+                int numGrabbed = -1;
+                if(pageNum == 1){
+                    numGrabbed = 1;
+                    wInstIds.add(rs.getString("workflow_instance_id"));                    
+                }
+                else{
+                    numGrabbed = 0;
+                }
+
+                if(pageNum != 1){
+                    // now move the cursor to the correct position
+                    rs.relative(startNum);                    
+                }
+
+                // grab the rest
+                while (rs.next() && numGrabbed < pageSize) {
+                    String wInstId = rs.getString("workflow_instance_id");
+                    wInstIds.add(wInstId);
+                    numGrabbed++;
+                }
+            }
+
+            if (wInstIds.size() == 0) {
+                wInstIds = null;
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception performing query. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback query transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return wInstIds;
+    }
+
+    private Metadata getWorkflowInstanceMetadata(String workflowInstId)
+            throws InstanceRepositoryException {
+        Connection conn = null;
+        Statement statement = null;
+        ResultSet rs = null;
+
+        Metadata met = new Metadata();
+
+        try {
+            conn = dataSource.getConnection();
+            statement = conn.createStatement();
+
+            String getWorkflowSql = "SELECT * from workflow_instance_metadata "
+                    + "WHERE workflow_instance_id = " + workflowInstId;
+
+            LOG.log(Level.FINE, "Executing: " + getWorkflowSql);
+            rs = statement.executeQuery(getWorkflowSql);
+
+            while (rs.next()) {
+                met.addMetadata(rs.getString("workflow_met_key"), URLDecoder.decode(rs
+                        .getString("workflow_met_val"), "UTF-8"));
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception getting workflow instance metadata. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback getWorkflowInstancesMetadata "
+                                + "transaction. Message: " + e2.getMessage());
+            }
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException ignore) {
+                }
+
+                rs = null;
+            }
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+        return met;
+    }
+
+    private synchronized void addWorkflowInstanceMetadata(WorkflowInstance inst)
+            throws InstanceRepositoryException {
+
+        if (inst.getSharedContext() != null
+                && inst.getSharedContext().getHashtable().keySet().size() > 0) {
+            for (Iterator i = inst.getSharedContext().getHashtable().keySet()
+                    .iterator(); i.hasNext();) {
+                String key = (String) i.next();
+                List vals = inst.getSharedContext().getAllMetadata(key);
+                if (vals != null && vals.size() > 0) {
+                    for (Iterator j = vals.iterator(); j.hasNext();) {
+                        String val = (String) j.next();
+                        if (val != null && !val.equals("")) {
+                            addMetadataValue(inst.getId(), key, val);
+                        }
+                    }
+                }
+
+            }
+        }
+
+    }
+
+    private synchronized void addMetadataValue(String wInstId, String key,
+            String val) throws InstanceRepositoryException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+            String addMetSql = "INSERT INTO workflow_instance_metadata"
+                    + " (workflow_instance_id,workflow_met_key,workflow_met_val) VALUES ("
+                    + wInstId + ",'" + key + "','" + URLEncoder.encode(val, "UTF-8") + "')";
+
+            LOG.log(Level.FINE, "sql: Executing: " + addMetSql);
+            statement.execute(addMetSql);
+
+            conn.commit();
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Exception adding metadata [" + key + "=>"
+                    + val + "] to workflow inst: [" + wInstId + "]. Message: "
+                    + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback addMetadataValue transaction. Message: "
+                                + e2.getMessage());
+            }
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+
+    }
+
+    private synchronized void removeWorkflowInstanceMetadata(
+            String workflowInstId) throws InstanceRepositoryException {
+        Connection conn = null;
+        Statement statement = null;
+
+        try {
+            conn = dataSource.getConnection();
+            conn.setAutoCommit(false);
+            statement = conn.createStatement();
+
+            String deleteSql = "DELETE FROM workflow_instance_metadata "
+                    + "WHERE workflow_instance_id = " + workflowInstId;
+
+            LOG.log(Level.FINE, "sql: Executing: " + deleteSql);
+            statement.execute(deleteSql);
+            conn.commit();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception removing workflow instance metadata. Message: "
+                            + e.getMessage());
+            try {
+                conn.rollback();
+            } catch (SQLException e2) {
+                LOG.log(Level.SEVERE,
+                        "Unable to rollback removeWorkflowInstanceMetadata "
+                                + "transaction. Message: " + e2.getMessage());
+            }
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException ignore) {
+                }
+
+                statement = null;
+            }
+
+            if (conn != null) {
+                try {
+                    conn.close();
+
+                } catch (SQLException ignore) {
+                }
+
+                conn = null;
+            }
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/DataSourceWorkflowInstanceRepositoryFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/DataSourceWorkflowInstanceRepositoryFactory.java
new file mode 100644
index 0000000..0d2aa6b
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/DataSourceWorkflowInstanceRepositoryFactory.java
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.instrepo;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepositoryFactory;
+
+//APACHE imports
+import org.apache.commons.dbcp.ConnectionFactory;
+import org.apache.commons.dbcp.DriverManagerConnectionFactory;
+import org.apache.commons.dbcp.PoolableConnectionFactory;
+import org.apache.commons.dbcp.PoolingDataSource;
+import org.apache.commons.pool.impl.GenericObjectPool;
+
+//JDK imports
+import javax.sql.DataSource;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A factory for creating {@link DataSource} based
+ * {@link WorkflowInstanceRepository}s.
+ * </p>
+ * 
+ */
+public class DataSourceWorkflowInstanceRepositoryFactory implements
+        WorkflowInstanceRepositoryFactory {
+
+    /* our data source */
+    private DataSource dataSource = null;
+
+    /* whether or not we are quoting the task_id and workflow_id fields */
+    private boolean quoteFields = false;
+
+    /* the number of workflow instances returned per page when paginating */
+    private int pageSize = -1;
+
+    /**
+     * <p>
+     * Default constructor
+     * </p>
+     */
+    public DataSourceWorkflowInstanceRepositoryFactory() throws Exception {
+        String jdbcUrl = null, user = null, pass = null, driver = null;
+
+        jdbcUrl = PathUtils
+                .replaceEnvVariables(System
+                        .getProperty("org.apache.oodt.cas.workflow.instanceRep.datasource.jdbc.url"));
+        user = PathUtils
+                .replaceEnvVariables(System
+                        .getProperty("org.apache.oodt.cas.workflow.instanceRep.datasource.jdbc.user"));
+        pass = PathUtils
+                .replaceEnvVariables(System
+                        .getProperty("org.apache.oodt.cas.workflow.instanceRep.datasource.jdbc.pass"));
+        driver = PathUtils
+                .replaceEnvVariables(System
+                        .getProperty("org.apache.oodt.cas.workflow.instanceRep.datasource.jdbc.driver"));
+
+        try {
+            Class.forName(driver);
+        } catch (ClassNotFoundException e) {
+            throw new Exception("Cannot load driver: " + driver);
+        }
+
+        GenericObjectPool connectionPool = new GenericObjectPool(null);
+        ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
+                jdbcUrl, user, pass);
+        PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(
+                connectionFactory, connectionPool, null, null, false, true);
+
+        dataSource = new PoolingDataSource(connectionPool);
+        quoteFields = Boolean
+                .getBoolean("org.apache.oodt.cas.workflow.instanceRep.datasource.quoteFields");
+        pageSize = Integer.getInteger(
+                "org.apache.oodt.cas.workflow.instanceRep.pageSize", 20)
+                .intValue();
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepositoryFactory#createInstanceRepository()
+     */
+    public WorkflowInstanceRepository createInstanceRepository() {
+        return new DataSourceWorkflowInstanceRepository(dataSource,
+                quoteFields, pageSize);
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/LuceneWorkflowInstanceRepository.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/LuceneWorkflowInstanceRepository.java
new file mode 100644
index 0000000..1203002
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/LuceneWorkflowInstanceRepository.java
@@ -0,0 +1,815 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.instrepo;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleStage;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowState;
+import org.apache.oodt.cas.workflow.structs.Priority;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//Lucene imports
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Hits;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.search.TermQuery;
+
+//JUG imports
+import org.safehaus.uuid.UUID;
+import org.safehaus.uuid.UUIDGenerator;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * An implementation of the {@link WorkflowEngine} interface that is backed by
+ * <a href="http://lucene.apache.org">Apache Lucene</a>.
+ * </p>.
+ */
+public class LuceneWorkflowInstanceRepository extends
+        AbstractPaginatibleInstanceRepository {
+
+    /* path to lucene index directory to store wInst info */
+    private String idxFilePath = null;
+
+    /* our log stream */
+    private static final Logger LOG = Logger
+            .getLogger(LuceneWorkflowInstanceRepository.class.getName());
+
+    /* our workflow inst id generator */
+    private static UUIDGenerator generator = UUIDGenerator.getInstance();
+
+    /**
+     * 
+     */
+    public LuceneWorkflowInstanceRepository(String idxPath, int pageSize) {
+        this.idxFilePath = idxPath;
+        this.pageSize = pageSize;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#getNumWorkflowInstances()
+     */
+    public int getNumWorkflowInstances() throws InstanceRepositoryException {
+        IndexSearcher searcher = null;
+        int numInsts = -1;
+
+        try {
+            searcher = new IndexSearcher(idxFilePath);
+            Term instIdTerm = new Term("myfield", "myvalue");
+            org.apache.lucene.search.Query query = new TermQuery(instIdTerm);
+            Sort sort = new Sort(new SortField("workflow_inst_startdatetime",
+                    SortField.STRING, true));
+            Hits hits = searcher.search(query, sort);
+
+            numInsts = hits.length();
+
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: [" + idxFilePath
+                            + "] for search: Message: " + e.getMessage());
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+
+        return numInsts;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#getNumWorkflowInstancesByStatus(java.lang.String)
+     */
+    public int getNumWorkflowInstancesByStatus(String status)
+            throws InstanceRepositoryException {
+        IndexSearcher searcher = null;
+        int numInsts = -1;
+
+        try {
+            searcher = new IndexSearcher(idxFilePath);
+            Term instIdTerm = new Term("workflow_inst_status", status);
+            org.apache.lucene.search.Query query = new TermQuery(instIdTerm);
+            Sort sort = new Sort(new SortField("workflow_inst_startdatetime",
+                    SortField.STRING, true));
+            Hits hits = searcher.search(query, sort);
+
+            numInsts = hits.length();
+
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: [" + idxFilePath
+                            + "] for search: Message: " + e.getMessage());
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+
+        return numInsts;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#addWorkflowInstance(org.apache.oodt.cas.workflow.structs.WorkflowInstance)
+     */
+    public synchronized void addWorkflowInstance(WorkflowInstance wInst)
+            throws InstanceRepositoryException {
+        // generate UUID for inst
+        UUID uuid = UUIDGenerator.getInstance().generateTimeBasedUUID();
+        wInst.setId(uuid.toString());
+
+        addWorkflowInstanceToCatalog(wInst);
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#removeWorkflowInstance(org.apache.oodt.cas.workflow.structs.WorkflowInstance)
+     */
+    public synchronized void removeWorkflowInstance(WorkflowInstance wInst)
+            throws InstanceRepositoryException {
+        removeWorkflowInstanceDocument(wInst);
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#updateWorkflowInstance(org.apache.oodt.cas.workflow.structs.WorkflowInstance)
+     */
+    public synchronized void updateWorkflowInstance(WorkflowInstance wInst)
+            throws InstanceRepositoryException {
+        removeWorkflowInstanceDocument(wInst);
+        addWorkflowInstanceToCatalog(wInst);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#getWorkflowInstanceById(java.lang.String)
+     */
+    public WorkflowInstance getWorkflowInstanceById(String workflowInstId)
+            throws InstanceRepositoryException {
+        IndexSearcher searcher = null;
+        WorkflowInstance wInst = null;
+
+        try {
+            searcher = new IndexSearcher(idxFilePath);
+            Term instIdTerm = new Term("workflow_inst_id", workflowInstId);
+            org.apache.lucene.search.Query query = new TermQuery(instIdTerm);
+            Hits hits = searcher.search(query);
+
+            if (hits.length() != 1) {
+                LOG.log(Level.WARNING, "The workflow instance: ["
+                        + workflowInstId + "] is not being "
+                        + "managed by this " + "workflow engine, or "
+                        + "is not unique in the catalog: num hits: ["+hits.length()+"]");
+                return null;
+            } else {
+                Document instDoc = hits.doc(0);
+                wInst = toWorkflowInstance(instDoc);
+            }
+
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: [" + idxFilePath
+                            + "] for search: Message: " + e.getMessage());
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+
+        return wInst;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#getWorkflowInstances()
+     */
+    public List getWorkflowInstances() throws InstanceRepositoryException {
+        IndexSearcher searcher = null;
+        List wInsts = null;
+
+        try {
+            searcher = new IndexSearcher(idxFilePath);
+            Term instIdTerm = new Term("myfield", "myvalue");
+            org.apache.lucene.search.Query query = new TermQuery(instIdTerm);
+            Sort sort = new Sort(new SortField("workflow_inst_startdatetime",
+                    SortField.STRING, true));
+            Hits hits = searcher.search(query, sort);
+
+            if (hits.length() > 0) {
+                wInsts = new Vector(hits.length());
+
+                for (int i = 0; i < hits.length(); i++) {
+                    Document doc = hits.doc(i);
+                    WorkflowInstance wInst = toWorkflowInstance(doc);
+                    wInsts.add(wInst);
+                }
+            }
+
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: [" + idxFilePath
+                            + "] for search: Message: " + e.getMessage());
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+
+        return wInsts;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#getWorkflowInstancesByStatus(java.lang.String)
+     */
+    public List getWorkflowInstancesByStatus(String status)
+            throws InstanceRepositoryException {
+        IndexSearcher searcher = null;
+        List wInsts = null;
+
+        try {
+            searcher = new IndexSearcher(idxFilePath);
+            Term instIdTerm = new Term("workflow_inst_status", status);
+            org.apache.lucene.search.Query query = new TermQuery(instIdTerm);
+            Sort sort = new Sort(new SortField("workflow_inst_startdatetime",
+                    SortField.STRING, true));
+            Hits hits = searcher.search(query, sort);
+
+            if (hits.length() > 0) {
+                wInsts = new Vector(hits.length());
+
+                for (int i = 0; i < hits.length(); i++) {
+                    Document doc = hits.doc(i);
+                    WorkflowInstance wInst = toWorkflowInstance(doc);
+                    wInsts.add(wInst);
+                }
+            }
+
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: [" + idxFilePath
+                            + "] for search: Message: " + e.getMessage());
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+
+        return wInsts;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.AbstractPaginatibleInstanceRepository#paginateWorkflows(int,
+     *      java.lang.String)
+     */
+    protected List paginateWorkflows(int pageNum, String status)
+            throws InstanceRepositoryException {
+        List instIds = null;
+        IndexSearcher searcher = null;
+
+        try {
+            searcher = new IndexSearcher(idxFilePath);
+
+            // construct a Boolean query here
+            BooleanQuery booleanQuery = new BooleanQuery();
+
+            Term instIdTerm = new Term("myfield", "myvalue");
+            if (status != null) {
+                Term statusTerm = new Term("workflow_inst_status", status);
+                booleanQuery.add(new TermQuery(statusTerm),
+                        BooleanClause.Occur.MUST);
+            }
+            booleanQuery.add(new TermQuery(instIdTerm),
+                    BooleanClause.Occur.MUST);
+
+            Sort sort = new Sort(new SortField("workflow_inst_startdatetime",
+                    SortField.STRING, true));
+            LOG.log(Level.FINE,
+                    "Querying LuceneWorkflowInstanceRepository: q: ["
+                            + booleanQuery + "]");
+            Hits hits = searcher.search(booleanQuery, sort);
+            if (hits.length() > 0) {
+
+                int startNum = (pageNum - 1) * pageSize;
+                if (startNum > hits.length()) {
+                    startNum = 0;
+                }
+
+                instIds = new Vector(pageSize);
+
+                for (int i = startNum; i < Math.min(hits.length(),
+                        (startNum + pageSize)); i++) {
+                    Document instDoc = hits.doc(i);
+                    WorkflowInstance inst = toWorkflowInstance(instDoc);
+                    instIds.add(inst.getId());
+
+                }
+            } else {
+                LOG.log(Level.WARNING, "No workflow instances found "
+                        + "when attempting to paginate!");
+            }
+
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when opening index directory: [" + idxFilePath
+                            + "] for search: Message: " + e.getMessage());
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+            if (searcher != null) {
+                try {
+                    searcher.close();
+                } catch (Exception ignore) {
+                }
+                searcher = null;
+            }
+        }
+
+        return instIds;
+    }
+
+    private synchronized void removeWorkflowInstanceDocument(
+            WorkflowInstance inst) throws InstanceRepositoryException {
+        IndexReader reader = null;
+
+        try {
+            reader = IndexReader.open(idxFilePath);
+            LOG.log(Level.FINE,
+                    "LuceneWorkflowEngine: remove document from index for workflow instance: ["
+                            + inst.getId() + "]");
+            reader.deleteDocuments(new Term("workflow_inst_id", inst.getId()));
+        } catch (IOException e) {
+            e.printStackTrace();
+            LOG
+                    .log(Level.WARNING,
+                            "Exception removing workflow instance: ["
+                                    + inst.getId() + "] from index: Message: "
+                                    + e.getMessage());
+            throw new InstanceRepositoryException(e.getMessage());
+        } finally {
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (Exception ignore) {
+                }
+
+                reader = null;
+            }
+
+        }
+    }
+
+    private synchronized void addWorkflowInstanceToCatalog(
+            WorkflowInstance wInst) throws InstanceRepositoryException {
+        IndexWriter writer = null;
+
+        File indexDir = new File(idxFilePath);
+
+        boolean createIndex = false;
+
+        if (indexDir.exists() && indexDir.isDirectory()) {
+            createIndex = false;
+        } else
+            createIndex = true;
+
+        try {
+            writer = new IndexWriter(idxFilePath, new StandardAnalyzer(),
+                    createIndex);
+            writer.setMergeFactor(20);
+
+            Document doc = toDoc(wInst);
+            writer.addDocument(doc);
+        } catch (IOException e) {
+            LOG.log(Level.WARNING, "Unable to index workflow instance: ["
+                    + wInst.getId() + "]: Message: " + e.getMessage());
+            throw new InstanceRepositoryException(
+                    "Unable to index workflow instance: [" + wInst.getId()
+                            + "]: Message: " + e.getMessage());
+        } finally {
+            try {
+                writer.close();
+            } catch (Exception ignore) {
+            }
+            writer = null;
+        }
+
+    }
+
+    private Document toDoc(WorkflowInstance workflowInst) {
+        Document doc = new Document();
+
+        // store the workflow instance info first
+        doc.add(new Field("workflow_inst_id", workflowInst.getId(),
+                Field.Store.YES, Field.Index.UN_TOKENIZED));
+        
+        doc.add(new Field("workflow_inst_timesblocked", 
+            String.valueOf(workflowInst.getTimesBlocked()), Field.Store.YES, 
+            Field.Index.UN_TOKENIZED));
+        
+        // will leave this for back compat, but will also store 
+        // category 
+        doc.add(new Field("workflow_inst_status", workflowInst.getStatus(),
+                Field.Store.YES, Field.Index.UN_TOKENIZED));
+        
+        if(workflowInst.getState() != null){
+          WorkflowState state = workflowInst.getState();
+        
+          if(state.getDescription() != null){
+            doc.add(new Field("workflow_inst_state_desc",
+                state.getDescription(), Field.Store.YES, Field.Index.UN_TOKENIZED));
+          }
+          
+          if(state.getMessage() != null){
+            doc.add(new Field("workflow_inst_state_message",
+                state.getMessage(), Field.Store.YES, Field.Index.UN_TOKENIZED));
+          }
+          
+          if(state.getCategory() != null && state.getCategory().getName() != null){
+            doc.add(new Field("workflow_inst_state_category",
+                state.getCategory().getName(), Field.Store.YES, Field.Index.UN_TOKENIZED));
+          }
+        }        
+        
+        doc
+                .add(new Field("workflow_inst_current_task_id", workflowInst
+                        .getCurrentTaskId(), Field.Store.YES,
+                        Field.Index.UN_TOKENIZED));
+
+        doc
+                .add(new Field(
+                        "workflow_inst_currenttask_startdatetime",
+                        workflowInst.getCurrentTaskStartDateTimeIsoStr() != null ? workflowInst
+                                .getCurrentTaskStartDateTimeIsoStr()
+                                : "", Field.Store.YES, Field.Index.UN_TOKENIZED));
+        doc.add(new Field("workflow_inst_currenttask_enddatetime", workflowInst
+                .getCurrentTaskEndDateTimeIsoStr() != null ? workflowInst
+                .getCurrentTaskEndDateTimeIsoStr() : "", Field.Store.YES,
+                Field.Index.UN_TOKENIZED));
+        doc.add(new Field("workflow_inst_startdatetime", workflowInst
+                .getStartDateTimeIsoStr() != null ? workflowInst
+                .getStartDateTimeIsoStr() : "", Field.Store.YES,
+                Field.Index.UN_TOKENIZED));
+        doc.add(new Field("workflow_inst_enddatetime", workflowInst
+                .getEndDateTimeIsoStr() != null ? workflowInst
+                .getEndDateTimeIsoStr() : "", Field.Store.YES,
+                Field.Index.UN_TOKENIZED));
+        doc.add(new Field("workflow_inst_priority",
+            workflowInst.getPriority() != null ? 
+                String.valueOf(workflowInst.getPriority().getValue()):
+                  String.valueOf(Priority.getDefault().getValue()),
+                  Field.Store.YES,
+                  Field.Index.UN_TOKENIZED));
+
+        // add all metadata
+        addInstanceMetadataToDoc(doc, workflowInst.getSharedContext());
+
+        // store the workflow info too
+        doc.add(new Field("workflow_id", workflowInst.getWorkflow().getId(),
+                Field.Store.YES, Field.Index.UN_TOKENIZED));
+        doc.add(new Field("workflow_name",
+                workflowInst.getWorkflow().getName(), Field.Store.YES,
+                Field.Index.NO));
+
+        // store the tasks
+        addTasksToDoc(doc, workflowInst.getWorkflow().getTasks());
+        
+        // store workflow conditions
+        addConditionsToDoc("workflow_condition_"+workflowInst.getWorkflow().getId(), 
+            workflowInst.getWorkflow().getConditions()
+            , doc);
+
+        // add the default field (so that we can do a query for *)
+        doc.add(new Field("myfield", "myvalue", Field.Store.YES,
+                Field.Index.UN_TOKENIZED));
+
+        return doc;
+    }
+
+    private void addInstanceMetadataToDoc(Document doc, Metadata met) {
+        if (met != null && met.getHashtable().keySet().size() > 0) {
+            for (Iterator i = met.getHashtable().keySet().iterator(); i
+                    .hasNext();) {
+                String metKey = (String) i.next();
+                List metVals = met.getAllMetadata(metKey);
+                if (metVals != null && metVals.size() > 0) {
+                    for (Iterator j = metVals.iterator(); j.hasNext();) {
+                        String metVal = (String) j.next();
+                        doc.add(new Field(metKey, metVal, Field.Store.YES,
+                                Field.Index.UN_TOKENIZED));
+                    }
+
+                    // now index the field name so that we can use it to
+                    // look it up when converting from doc to
+                    // WorkflowInstance
+                    doc.add(new Field("workflow_inst_met_flds", metKey,
+                            Field.Store.YES, Field.Index.NO));
+
+                }
+            }
+        }
+    }
+
+    private void addTasksToDoc(Document doc, List tasks) {
+        if (tasks != null && tasks.size() > 0) {
+            for (Iterator i = tasks.iterator(); i.hasNext();) {
+                WorkflowTask task = (WorkflowTask) i.next();
+                doc.add(new Field("task_id", task.getTaskId(), Field.Store.YES,
+                        Field.Index.UN_TOKENIZED));
+                doc.add(new Field("task_name", task.getTaskName(),
+                        Field.Store.YES, Field.Index.NO));
+                doc.add(new Field("task_order",
+                        String.valueOf(task.getOrder()), Field.Store.YES,
+                        Field.Index.NO));
+                doc.add(new Field("task_class",
+                        task.getTaskInstanceClassName(), Field.Store.YES,
+                        Field.Index.NO));
+
+                addConditionsToDoc(task.getTaskId(), task.getConditions(), doc);
+                addTaskConfigToDoc(task.getTaskId(), task.getTaskConfig(), doc);
+            }
+        }
+    }
+
+    private void addTaskConfigToDoc(String taskId,
+            WorkflowTaskConfiguration config, Document doc) {
+        if (config != null) {
+            for (Iterator i = config.getProperties().keySet().iterator(); i
+                    .hasNext();) {
+                String propName = (String) i.next();
+                String propValue = config.getProperty(propName);
+
+                doc.add(new Field(taskId + "_config_property_name", propName,
+                        Field.Store.YES, Field.Index.NO));
+                doc.add(new Field(taskId + "_config_property_value", propValue,
+                        Field.Store.YES, Field.Index.NO));
+            }
+        }
+    }
+
+  private void addConditionsToDoc(String taskId, List conditionList,
+      Document doc) {
+    if (conditionList != null && conditionList.size() > 0) {
+      for (Iterator i = conditionList.iterator(); i.hasNext();) {
+        WorkflowCondition cond = (WorkflowCondition) i.next();
+        doc.add(new Field(taskId + "_condition_name", cond.getConditionName(),
+            Field.Store.YES, Field.Index.NO));
+        doc.add(new Field(taskId + "_condition_id", cond.getConditionId(),
+            Field.Store.YES, Field.Index.UN_TOKENIZED));
+        doc.add(new Field(taskId + "_condition_class", cond
+            .getConditionInstanceClassName(), Field.Store.YES, Field.Index.NO));
+        doc.add(new Field(taskId + "_condition_order", String.valueOf(cond
+            .getOrder()), Field.Store.YES, Field.Index.NO));
+        doc.add(new Field(taskId + "_condition_timeout", String.valueOf(cond
+            .getTimeoutSeconds()), Field.Store.YES, Field.Index.NO));
+        doc.add(new Field(taskId+"_condition_optional", String.valueOf(cond.isOptional()),
+            Field.Store.YES, Field.Index.NO));
+      }
+    }
+  }
+
+    private WorkflowInstance toWorkflowInstance(Document doc) {
+        WorkflowInstance inst = new WorkflowInstance();
+
+        // first read all the instance info
+        inst.setId(doc.get("workflow_inst_id"));
+        
+        inst.setTimesBlocked(Integer.parseInt(doc.get("workflow_inst_timesblocked") != 
+          null ? doc.get("workflow_inst_timesblocked"):"0"));
+        
+        // try and construct a state
+        WorkflowState state = new WorkflowState();
+        state.setName(doc.get("workflow_inst_status"));
+        if(doc.get("workflow_inst_state_category") != null){
+          WorkflowLifecycleStage category = new WorkflowLifecycleStage();
+          category.setName(doc.get("workflow_inst_state_category"));
+          state.setCategory(category);
+        }
+        
+        if(doc.get("workflow_inst_state_desc") != null){
+          state.setDescription(doc.get("workflow_inst_state_desc"));
+        }
+        
+        if(doc.get("workflow_inst_state_message") != null){
+          state.setMessage(doc.get("workflow_inst_state_message"));
+        }        
+        inst.setState(state);
+        inst.setCurrentTaskId(doc.get("workflow_inst_current_task_id"));
+        inst.setCurrentTaskStartDateTimeIsoStr(doc
+                .get("workflow_inst_currenttask_startdatetime"));
+        inst.setCurrentTaskEndDateTimeIsoStr(doc
+                .get("workflow_inst_currenttask_enddatetime"));
+        inst.setStartDateTimeIsoStr(doc.get("workflow_inst_startdatetime"));
+        inst.setEndDateTimeIsoStr(doc.get("workflow_inst_enddatetime"));
+        inst.setPriority(Priority.getPriority(doc.get("workflow_inst_priority") != null ? 
+            Double.valueOf(doc.get("workflow_inst_priority")):Priority.getDefault().getValue()));
+
+        // read the workflow instance metadata
+        Metadata sharedContext = new Metadata();
+        String[] instMetFields = doc.getValues("workflow_inst_met_flds");
+        if (instMetFields != null && instMetFields.length > 0) {
+            for (int i = 0; i < instMetFields.length; i++) {
+                String fldName = instMetFields[i];
+                String[] vals = doc.getValues(fldName);
+                if (vals != null && vals.length > 0) {
+                    for (int j = 0; j < vals.length; j++) {
+                        sharedContext.addMetadata(fldName, vals[j]);
+                    }
+                }
+            }
+        }
+
+        inst.setSharedContext(sharedContext);
+
+        // now read all of the workflow info
+
+        Workflow workflow = new Workflow();
+
+        workflow.setId(doc.get("workflow_id"));
+        workflow.setName(doc.get("workflow_name"));
+        workflow.setTasks(toTasks(doc));
+        workflow.setConditions(toConditions("workflow_condition_"+workflow.getId(), doc));
+
+        inst.setWorkflow(workflow);
+
+        return inst;
+    }
+
+    private List toTasks(Document doc) {
+        List taskList = new Vector();
+
+        String[] taskIds = doc.getValues("task_id");
+        String[] taskNames = doc.getValues("task_name");
+        String[] taskOrders = doc.getValues("task_order");
+        String[] taskClasses = doc.getValues("task_class");
+
+        if (taskIds.length != taskNames.length
+                || taskIds.length != taskOrders.length
+                || taskIds.length != taskClasses.length) {
+            LOG.log(Level.WARNING,
+                    "task arrays are not of same size when rebuilding "
+                            + "task list from Document!");
+            return null;
+        }
+
+        for (int i = 0; i < taskIds.length; i++) {
+            WorkflowTask task = new WorkflowTask();
+            task.setOrder(Integer.parseInt(taskOrders[i]));
+            task.setTaskName(taskNames[i]);
+            task.setTaskId(taskIds[i]);
+            task.setTaskInstanceClassName(taskClasses[i]);
+
+            task.setConditions(toConditions(task.getTaskId(), doc));
+            task.setTaskConfig(toTaskConfig(task.getTaskId(), doc));
+            taskList.add(task);
+        }
+
+        return taskList;
+    }
+
+    private WorkflowTaskConfiguration toTaskConfig(String taskId, Document doc) {
+        WorkflowTaskConfiguration taskConfig = new WorkflowTaskConfiguration();
+
+        String[] propNames = doc.getValues(taskId + "_config_property_name");
+        String[] propValues = doc.getValues(taskId + "_config_property_value");
+
+        if (propNames == null) {
+            return taskConfig;
+        }
+
+        if (propNames.length != propValues.length) {
+            LOG.log(Level.WARNING,
+                    "Task Config prop name and value arrays are not "
+                            + "of same size!");
+            return null;
+        }
+
+        for (int i = 0; i < propNames.length; i++) {
+            taskConfig.addConfigProperty(propNames[i], propValues[i]);
+        }
+
+        return taskConfig;
+    }
+
+    private List toConditions(String taskId, Document doc) {
+        List condList = new Vector();
+
+        String[] condNames = doc.getValues(taskId + "_condition_name");
+        String[] condClasses = doc.getValues(taskId + "_condition_class");
+        String[] condOrders = doc.getValues(taskId + "_condition_order");
+        String[] condIds = doc.getValues(taskId + "_condition_id");
+        String[] condTimeouts = doc.getValues(taskId+"_condition_timeout");
+        String[] condOptionals = doc.getValues(taskId+"_condition_optional");
+
+        if (condNames == null) {
+            return condList;
+        }
+        
+        if (condNames.length != condClasses.length
+                || condNames.length != condOrders.length
+                || condNames.length != condIds.length 
+                || (condTimeouts != null && condNames.length != condTimeouts.length)
+                || (condOptionals != null && condNames.length != condOptionals.length)) {
+            LOG.log(Level.WARNING,
+                    "Condition arrays are not of same size when "
+                            + "rebuilding from given Document");
+            return null;
+        }
+        
+        for (int i = 0; i < condNames.length; i++) {
+            WorkflowCondition cond = new WorkflowCondition();
+            cond.setConditionId(condIds[i]);
+            cond.setConditionInstanceClassName(condClasses[i]);
+            cond.setConditionName(condNames[i]);
+            cond.setOrder(Integer.parseInt(condOrders[i]));
+            if(condTimeouts != null){
+              cond.setTimeoutSeconds(Long.parseLong(condTimeouts[i]));
+            }
+            if(condOptionals != null){
+              cond.setOptional(Boolean.valueOf(condOptionals[i]));
+            }
+            condList.add(cond);
+        }
+        
+        return condList;
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/LuceneWorkflowInstanceRepositoryFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/LuceneWorkflowInstanceRepositoryFactory.java
new file mode 100644
index 0000000..0ef4985
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/LuceneWorkflowInstanceRepositoryFactory.java
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.instrepo;
+
+//JDK imports
+import java.io.File;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+//Lucene imports
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.index.IndexWriter;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory class for creating {@link LuceneWorkflowEngine}s.
+ * </p>.
+ */
+public class LuceneWorkflowInstanceRepositoryFactory implements
+        WorkflowInstanceRepositoryFactory {
+
+    /* the path to the lucene index directory */
+    private String indexFilePath = null;
+
+    private int pageSize = -1;
+    
+	/* our log stream */
+    private static final Logger LOG = Logger.getLogger(LuceneWorkflowInstanceRepositoryFactory.class.getName());
+
+    public LuceneWorkflowInstanceRepositoryFactory()
+            throws InstantiationException {
+        indexFilePath = System
+                .getProperty("org.apache.oodt.cas.workflow.instanceRep.lucene.idxPath");
+
+        if (indexFilePath == null) {
+            throw new InstantiationException(
+                    "Index File property: [org.apache.oodt.cas.workflow."
+                            + "engine.lucene.idxPath] not set!");
+        }
+
+        // do env variable replacement
+        indexFilePath = PathUtils.replaceEnvVariables(indexFilePath);
+        pageSize = Integer.getInteger(
+                "org.apache.oodt.cas.workflow.instanceRep.pageSize", 20)
+                .intValue();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepositoryFactory#createInstanceRepository()
+     */
+    public WorkflowInstanceRepository createInstanceRepository() {
+	    File indexDir = new File(indexFilePath);
+	    // Create the index if it does not already exist
+	    IndexWriter writer = null;
+	    if (!indexDir.exists()) {
+	        try { 
+	            writer = new IndexWriter(indexDir, new StandardAnalyzer(), true);
+	        } catch (Exception e) {
+	            LOG.severe("Unable to create index: " + e.getMessage());
+	        } finally {
+	            if (writer != null) {
+	                try {
+	                    writer.close();
+	                } catch (Exception e) {
+	                    LOG.severe("Unable to close index: " + e.getMessage());
+	                }
+	            }
+	        }
+	    }
+        return new LuceneWorkflowInstanceRepository(indexFilePath, pageSize);
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/MemoryWorkflowInstanceRepository.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/MemoryWorkflowInstanceRepository.java
new file mode 100644
index 0000000..b5d7afc
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/MemoryWorkflowInstanceRepository.java
@@ -0,0 +1,225 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.instrepo;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+import org.apache.oodt.commons.util.DateConvert;
+
+//JDK imports
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Date;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @version $Revsion$
+ * 
+ * <p>
+ * A simple {@link WorkflowInstanceRepository} that does not require the use of
+ * a database to track the status of the Workflow executions it manages.
+ * </p>
+ */
+public class MemoryWorkflowInstanceRepository extends
+        AbstractPaginatibleInstanceRepository {
+
+    /* our workflow instance map: maps workfllowInstId to WorkflowInstance */
+    private HashMap workflowInstMap = null;
+
+    /* our log stream */
+    private static final Logger LOG = Logger
+            .getLogger(MemoryWorkflowInstanceRepository.class.getName());
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>
+     */
+    public MemoryWorkflowInstanceRepository(int pageSize) {
+        workflowInstMap = new HashMap();
+        this.pageSize = pageSize;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#addWorkflowInstance(org.apache.oodt.cas.workflow.structs.WorkflowInstance)
+     */
+    public synchronized void addWorkflowInstance(WorkflowInstance wInst)
+            throws InstanceRepositoryException {
+        String instId = "urn:" + DateConvert.isoFormat(new Date());
+        wInst.setId(instId);
+        workflowInstMap.put(instId, wInst);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#removeWorkflowInstance(org.apache.oodt.cas.workflow.structs.WorkflowInstance)
+     */
+    public synchronized void removeWorkflowInstance(WorkflowInstance wInst)
+            throws InstanceRepositoryException {
+        workflowInstMap.remove(wInst.getId());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#updateWorkflowInstance(org.apache.oodt.cas.workflow.structs.WorkflowInstance)
+     */
+    public synchronized void updateWorkflowInstance(WorkflowInstance wInst)
+            throws InstanceRepositoryException {
+        WorkflowInstance inst = (WorkflowInstance) workflowInstMap.get(wInst
+                .getId());
+
+        if (inst == null) {
+            LOG
+                    .log(
+                            Level.WARNING,
+                            "Attempt to update workflow instance id: "
+                                    + wInst.getId()
+                                    + " workflow instance is not being tracked by this engine!");
+            return;
+        }
+
+        workflowInstMap.put(wInst.getId(), wInst);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#getWorkflowInstanceById(java.lang.String)
+     */
+    public WorkflowInstance getWorkflowInstanceById(String workflowInstId)
+            throws InstanceRepositoryException {
+        return (WorkflowInstance) workflowInstMap.get(workflowInstId);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#getWorkflowInstances()
+     */
+    public List getWorkflowInstances() throws InstanceRepositoryException {
+        return Arrays.asList(workflowInstMap.values().toArray());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#getWorkflowInstancesByStatus(java.lang.String)
+     */
+    public List getWorkflowInstancesByStatus(String status)
+            throws InstanceRepositoryException {
+        List instances = new Vector();
+
+        for (Iterator i = workflowInstMap.keySet().iterator(); i.hasNext();) {
+            String workflowInstId = (String) i.next();
+            WorkflowInstance inst = (WorkflowInstance) workflowInstMap
+                    .get(workflowInstId);
+            if (inst.getStatus().equals(status)) {
+                instances.add(inst);
+            }
+        }
+
+        return instances;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.AbstractPaginatibleInstanceRepository#paginateWorkflows(int,
+     *      java.lang.String)
+     */
+    protected List paginateWorkflows(int pageNum, String status)
+            throws InstanceRepositoryException {
+        // first sort insts by startDateTime
+        List allInsts = Arrays.asList(this.workflowInstMap.keySet().toArray());
+        Collections.sort(allInsts, new Comparator() {
+
+            public int compare(Object o1, Object o2) {
+                WorkflowInstance inst1 = (WorkflowInstance) o1;
+                WorkflowInstance inst2 = (WorkflowInstance) o2;
+
+                return inst1.getStartDateTimeIsoStr().compareTo(
+                        inst2.getStartDateTimeIsoStr());
+            }
+
+        });
+
+        int startNum = (pageNum - 1) * pageSize;
+        if (startNum > allInsts.size()) {
+            startNum = 0;
+        }
+
+        List instIds = new Vector(pageSize);
+
+        for (int i = startNum; i < Math.min(allInsts.size(),
+                (startNum + pageSize)); i++) {
+            WorkflowInstance wInst = (WorkflowInstance)allInsts.get(i);
+            instIds.add(wInst.getId());
+        }
+
+        return instIds;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#getNumWorkflowInstances()
+     */
+    public int getNumWorkflowInstances() throws InstanceRepositoryException {
+        return this.workflowInstMap.keySet().size();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository#getNumWorkflowInstancesByStatus(java.lang.String)
+     */
+    public int getNumWorkflowInstancesByStatus(String status)
+            throws InstanceRepositoryException {
+        int cnt = 0;
+
+        if (this.workflowInstMap != null
+                && this.workflowInstMap.keySet() != null
+                && this.workflowInstMap.keySet().size() > 0) {
+            for (Iterator i = this.workflowInstMap.keySet().iterator(); i
+                    .hasNext();) {
+                String wInstId = (String) i.next();
+                WorkflowInstance inst = (WorkflowInstance) this.workflowInstMap
+                        .get(wInstId);
+                if (inst.getStatus().equals(status)) {
+                    cnt++;
+                }
+            }
+        }
+
+        return cnt;
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/MemoryWorkflowInstanceRepositoryFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/MemoryWorkflowInstanceRepositoryFactory.java
new file mode 100644
index 0000000..e0c4cd4
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/MemoryWorkflowInstanceRepositoryFactory.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.instrepo;
+
+/**
+ * @author mattmann
+ * @version $Revsion$
+ * 
+ * <p>
+ * A Factory for creating {@link MemoryWorkflowInstanceRepository}s.
+ * </p>
+ */
+public class MemoryWorkflowInstanceRepositoryFactory implements
+        WorkflowInstanceRepositoryFactory {
+    
+    private int pageSize = -1;
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>
+     */
+    public MemoryWorkflowInstanceRepositoryFactory() {
+        pageSize = Integer.getInteger(
+                "org.apache.oodt.cas.workflow.instanceRep.pageSize", 20)
+                .intValue();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepositoryFactory#createInstanceRepository()
+     */
+    public WorkflowInstanceRepository createInstanceRepository() {
+        return new MemoryWorkflowInstanceRepository(pageSize);
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceMetMap.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceMetMap.java
new file mode 100644
index 0000000..5bce6d3
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceMetMap.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.instrepo;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JDK imports
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public final class WorkflowInstanceMetMap implements WorkflowInstanceMetMapKeys{
+    private Metadata map;
+
+    public WorkflowInstanceMetMap() {
+        map = new Metadata();
+    }
+    
+    public void addDefaultField(String fld){
+        map.addMetadata(DEFAULT_WORKFLOW_ID, fld);
+    }
+    
+    public void addDefaultFields(List flds){
+        addWorkflowToMap(DEFAULT_WORKFLOW_ID, flds);
+    }
+
+    public void addWorkflowToMap(String id, List fields) {
+        if (fields != null && fields.size() > 0) {
+            for (Iterator i = fields.iterator(); i.hasNext();) {
+                String fld = (String) i.next();
+                addFieldToWorkflow(id, fld);
+            }
+        }
+    }
+    
+    public List getDefaultFields(){
+        return getFieldsForWorkflow(DEFAULT_WORKFLOW_ID);
+    }
+
+    public List getFieldsForWorkflow(String id) {
+        return map.getAllMetadata(id);
+    }
+
+    public void addFieldToWorkflow(String id, String fld) {
+        map.addMetadata(id, fld);
+    }
+
+    public List getWorkflows() {
+        return Arrays.asList(map.getHashtable().keySet().toArray());
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceMetMapKeys.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceMetMapKeys.java
new file mode 100644
index 0000000..433c0ed
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceMetMapKeys.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.instrepo;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>Describe your class here</p>.
+ */
+public interface WorkflowInstanceMetMapKeys {
+    
+    public static final String DEFAULT_WORKFLOW_MAP = "default";
+
+    /* this is a RESERVED keyword: DON'T give your workflows this ID! */
+    public static final String DEFAULT_WORKFLOW_ID = "__default__";
+    
+    public static final String FIELD_TAG = "field";
+    
+    public static final String FIELD_TAG_NAME_ATTR = "name";
+    
+    public static final String WORKFLOW_TAG_NAME = "workflow";
+    
+    public static final String WORKFLOW_TAG_ID_ATTR = "id";
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceMetadataReader.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceMetadataReader.java
new file mode 100644
index 0000000..9b71b7b
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceMetadataReader.java
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.instrepo;
+
+//OODT imports
+import org.apache.oodt.commons.xml.DOMUtil;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public final class WorkflowInstanceMetadataReader implements
+        WorkflowInstanceMetMapKeys {
+
+    /* our log stream */
+    private static Logger LOG = Logger
+            .getLogger(WorkflowInstanceMetadataReader.class.getName());
+
+    private WorkflowInstanceMetadataReader() throws InstantiationException {
+        throw new InstantiationException("Don't construct utility classes!");
+    }
+
+    public static WorkflowInstanceMetMap parseMetMapFile(String mapFilePath)
+            throws Exception {
+        Document doc = getDocumentRoot(mapFilePath);
+        Element rootElem = doc.getDocumentElement();
+        WorkflowInstanceMetMap map = new WorkflowInstanceMetMap();
+
+        // make sure that there is a default tag
+        Element defaultElem = DOMUtil.getFirstElement(rootElem,
+                DEFAULT_WORKFLOW_MAP);
+
+        if (defaultElem == null) {
+            throw new Exception("file: [" + mapFilePath
+                    + "] must specify a default workflow to field map!");
+        }
+
+        map.addDefaultFields(readFields(defaultElem));
+
+        NodeList workflowMapNodes = rootElem
+                .getElementsByTagName(WORKFLOW_TAG_NAME);
+
+        if (workflowMapNodes != null && workflowMapNodes.getLength() > 0) {
+            for (int i = 0; i < workflowMapNodes.getLength(); i++) {
+                Element workflowMapElem = (Element) workflowMapNodes.item(i);
+                String workflowId = workflowMapElem
+                        .getAttribute(WORKFLOW_TAG_ID_ATTR);
+                List workflowFields = readFields(workflowMapElem);
+                map.addWorkflowToMap(workflowId, workflowFields);
+            }
+        }
+        
+        return map;
+
+    }
+
+    private static List readFields(Element rootFldElem) {
+        NodeList defaultFldNodes = rootFldElem.getElementsByTagName(FIELD_TAG);
+        List fields = null;
+
+        if (defaultFldNodes != null && defaultFldNodes.getLength() > 0) {
+            fields = new Vector(defaultFldNodes.getLength());
+            for (int i = 0; i < defaultFldNodes.getLength(); i++) {
+                Element defaultFldElem = (Element) defaultFldNodes.item(i);
+                fields.add(defaultFldElem.getAttribute(FIELD_TAG_NAME_ATTR));
+            }
+        }
+
+        return fields;
+    }
+
+    private static Document getDocumentRoot(String xmlFile) {
+        // open up the XML file
+        DocumentBuilderFactory factory = null;
+        DocumentBuilder parser = null;
+        Document document = null;
+        InputSource inputSource = null;
+
+        InputStream xmlInputStream = null;
+
+        try {
+            xmlInputStream = new File(xmlFile).toURL().openStream();
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when getting input stream from [" + xmlFile
+                            + "]: returning null document root");
+            return null;
+        }
+
+        inputSource = new InputSource(xmlInputStream);
+
+        try {
+            factory = DocumentBuilderFactory.newInstance();
+            parser = factory.newDocumentBuilder();
+            document = parser.parse(inputSource);
+        } catch (Exception e) {
+            LOG.warning("Unable to parse xml file [" + xmlFile + "]."
+                    + "Reason is [" + e + "]");
+            return null;
+        }
+
+        return document;
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceRepository.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceRepository.java
new file mode 100644
index 0000000..8abeec5
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceRepository.java
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.instrepo;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+import org.apache.oodt.cas.workflow.util.Pagination;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public interface WorkflowInstanceRepository extends Pagination {
+
+    public static final String X_POINT_ID = WorkflowInstanceRepository.class
+            .getName();
+
+    /**
+     * Persists the specified {@link WorkflowInstance} to the instance
+     * repository.
+     * 
+     * @param wInst
+     *            The workflow instance to persist.
+     * @throws InstanceRepositoryException
+     *             If any error occurs.
+     */
+    public void addWorkflowInstance(WorkflowInstance wInst)
+            throws InstanceRepositoryException;
+
+    /**
+     * Updates and persists the specified {@link WorkflowInstance} to the
+     * instance repository.
+     * 
+     * @param wInst
+     *            The workflow instance to update and persist.
+     * @throws InstanceRepositoryException
+     *             If any error occurs.
+     */
+    public void updateWorkflowInstance(WorkflowInstance wInst)
+            throws InstanceRepositoryException;
+
+    /**
+     * Removes the specified {@link WorkflowInstance} from the instance
+     * repository.
+     * 
+     * @param wInst
+     *            The workflow instance to remove.
+     * @throws InstanceRepositoryException
+     *             If any error occurs.
+     */
+    public void removeWorkflowInstance(WorkflowInstance wInst)
+            throws InstanceRepositoryException;
+
+    /**
+     * <p>
+     * Returns the {@link WorkflowInstance}s with the specified
+     * <code>workflowInstId</code>.
+     * </p>
+     * 
+     * @param workflowInstId
+     *            The ID of the {@link WorkflowInstance} to return.
+     * @return The specified {@link WorkflowInstance}.
+     * @throws InstanceRepositoryException
+     *             If any error occurs.
+     */
+    public WorkflowInstance getWorkflowInstanceById(String workflowInstId)
+            throws InstanceRepositoryException;
+
+    /**
+     * @return A {@link List} of {@link WorkflowInstance}s that this
+     *         {@link WorkflowEngine} is managing.
+     * @throws InstanceRepositoryException
+     *             If any error occurs.
+     */
+    public List getWorkflowInstances() throws InstanceRepositoryException;
+
+    /**
+     * <p>
+     * Returns a {@link List} of {@link WorkflowInstance}s, with the specified
+     * <code>status</code> String.
+     * </p>
+     * 
+     * @param status
+     *            A string representation of the status of the
+     *            {@link WorkflowInstance}.
+     * @return A {@link List} of {@link WorkflowInstance}s, with the specified
+     *         <code>status</code> String.
+     * @throws InstanceRepositoryException
+     *             If there is any error that occurs.
+     */
+    public List getWorkflowInstancesByStatus(String status)
+            throws InstanceRepositoryException;
+
+    /**
+     * Gets the number of {@link WorkflowInstances} with any <code>status</code>
+     * being managed by this WorkflowInstanceRepository.
+     * 
+     * @return The number of {@link WorkflowInstances} associated with any
+     *         <code>status</code> being managed by this
+     *         WorkflowInstanceRepository.
+     */
+    public int getNumWorkflowInstances() throws InstanceRepositoryException;
+
+    /**
+     * Gets the number of {@link WorkflowInstances} with the given
+     * <code>status</code> being managed by this WorkflowInstanceRepository.
+     * 
+     * @param status
+     *            The status to obtain the number of {@link WorkflowInstance}s
+     *            for.
+     * @return The number of {@link WorkflowInstance}s with the given
+     *         <code>status</code>.
+     * @throws InstanceRepositoryException If there is any error that occurs.
+     */
+    public int getNumWorkflowInstancesByStatus(String status) throws InstanceRepositoryException;
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceRepositoryFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceRepositoryFactory.java
new file mode 100644
index 0000000..4357622
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/instrepo/WorkflowInstanceRepositoryFactory.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.instrepo;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A factory interface for creating {@link WorkflowInstanceRepository} objects.
+ * </p>
+ * 
+ */
+public interface WorkflowInstanceRepositoryFactory {
+
+    /**
+     * @return An implementation of the 
+     * {@link WorkflowInstanceRepository} interface.
+     */
+    public WorkflowInstanceRepository createInstanceRepository();
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecycle.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecycle.java
new file mode 100644
index 0000000..776c22d
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecycle.java
@@ -0,0 +1,274 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.lifecycle;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.Workflow; //javadoc
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance; //javadoc
+import org.apache.oodt.cas.workflow.structs.WorkflowStatus; //javadoc
+
+//JDK imports
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * 
+ * Defines the lifecycle of a {@link Workflow}, identifying what
+ * {@link WorkflowStatus}es belong to a particular phase.
+ * 
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class WorkflowLifecycle {
+
+  public static final String DEFAULT_LIFECYCLE = "__default__";
+
+  public static final String NO_WORKFLOW_ID = "__no__workflow__id";
+
+  private SortedSet stages;
+
+  private String name;
+
+  private String workflowId;
+
+  /**
+   * Default Constructor.
+   * 
+   */
+  public WorkflowLifecycle() {
+    this(null, null);
+  }
+
+  /**
+   * Constructs a new WorkflowLifecycle with the given parameters.
+   * 
+   * @param name
+   *          The name of the WorkflowLifecycle.
+   * @param workflowId
+   *          The associated identifier for the {@link Workflow}s that this
+   *          WorkflowLifecycle is appropriate for.
+   */
+  public WorkflowLifecycle(String name, String workflowId) {
+    this.name = name;
+    this.workflowId = workflowId;
+    this.stages = new TreeSet(new Comparator() {
+
+      public int compare(Object o1, Object o2) {
+        WorkflowLifecycleStage stage1 = (WorkflowLifecycleStage) o1;
+        WorkflowLifecycleStage stage2 = (WorkflowLifecycleStage) o2;
+
+        if (stage1.getOrder() < stage2.getOrder()) {
+          return -1;
+        } else if (stage1.getOrder() == stage2.getOrder()) {
+          return 0;
+        } else {
+          return 1;
+        }
+      }
+
+    });
+
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return the stages
+   */
+  public SortedSet getStages() {
+    return stages;
+  }
+
+  /**
+   * Adds a {@link WorkflowStage} to this WorkflowLifecycle.
+   * 
+   * @param stage
+   *          The {@link WorkflowStage} to add to this WorkflowLifecycle.
+   */
+  public void addStage(WorkflowLifecycleStage stage) {
+    if (!stages.contains(stage)) {
+      stages.add(stage);
+    }
+  }
+
+  /**
+   * Removes the given {@link WorkflowStage} from this WorkflowLifecycle.
+   * 
+   * @param stage
+   *          The {@link WorkflowStage} to remove.
+   * @return True on success, false on failure.
+   */
+  public boolean removeStage(WorkflowLifecycleStage stage) {
+    return stages.remove(stage);
+  }
+
+  /**
+   * Clears the {@link WorkflowStage}s in this WorkflowLifecycle.
+   * 
+   */
+  public void clearStages() {
+    stages.clear();
+  }
+
+  /**
+   * @return the workflowId
+   */
+  public String getWorkflowId() {
+    return workflowId;
+  }
+
+  /**
+   * @param workflowId
+   *          the workflowId to set
+   */
+  public void setWorkflowId(String workflowId) {
+    this.workflowId = workflowId;
+  }
+
+  /**
+   * Gets the associated {@link WorkflowLifecycleStage} for a
+   * {@link WorkflowInstance} with a given status.
+   * 
+   * @param status
+   *          The status of the {@link WorkflowInstance} to get the
+   *          {@link WorkflowLifecycleStage} for.
+   * @return The corresponding {@link WorkflowLifecycleStage} for the
+   *         {@link WorkflowInstance} with the given status, or null if that
+   *         status does not exist in any defined {@link WorkflowLifecycleStage}
+   *         .
+   */
+  @Deprecated
+  public WorkflowLifecycleStage getStageForWorkflow(String status) {
+    if (this.stages != null && this.stages.size() > 0) {
+      for (Iterator i = this.stages.iterator(); i.hasNext();) {
+        WorkflowLifecycleStage stage = (WorkflowLifecycleStage) i.next();
+        for(WorkflowState state: stage.getStates()){
+          if(state.getName().equals(status)){
+            return stage;
+          }
+        }
+      }
+
+      return null;
+    } else
+      return null;
+  }
+
+  /**
+   * Looks up an associated {@link WorkflowState} by scanning the
+   * {@link WorkflowLifecycleStage}s present in this lifecycle (aka, by scanning
+   * its "Categories", in Workflow2 terminology). Since no Category is provided,
+   * the first instance of a {@link WorkflowState} found in the given
+   * {@link WorkflowLifecycleStage} being scanned is returned, even if there are
+   * multiple instances of that state (e.g., others present in another
+   * category).
+   * 
+   * If found, the {@link WorkflowState} is returned, otherwise null is
+   * returned.
+   * 
+   * @param stateName
+   *          The name of the {@link WorkflowState} to locate and return.
+   * @return The {@link WorkflowState} if found, otherwise null.
+   */
+  public WorkflowState getStateByName(String stateName) {
+    return this.getStateByNameAndCategory(stateName, null);
+  }
+
+  /**
+   * Gets a {@link WorkflowState} by its name and {@link WorkflowLifecycleStage}
+   * (or Category in Workflow2 terminology). If the state is found within that
+   * category, then it is returned, otherwise null is returned.
+   * 
+   * @param stateName
+   *          The name of the {@link WorkflowState} to locate and return.
+   * @param category
+   *          The provided {@link WorkflowLifecycleStage} name to categorize the
+   *          state by.
+   * @return The {@link WorkflowState} if found, otherwise null.
+   */
+  public WorkflowState getStateByNameAndCategory(String stateName,
+      String category) {
+    if (this.getStages() != null) {
+      for (WorkflowLifecycleStage stage : (SortedSet<WorkflowLifecycleStage>) this
+          .getStages()) {
+        if (category != null && !stage.getName().equals(category))
+          continue;
+        if (stage.getStates() != null) {
+          for (WorkflowState state : (List<WorkflowState>) stage.getStates()) {
+            if (state.getName().equals(stateName)) {
+              return makeCopy(state);
+            }
+          }
+        }
+      }
+    }
+
+    return null;
+  }
+  
+  public WorkflowLifecycleStage getCategoryByName(String category){
+    if(this.getStages() != null){
+      for(WorkflowLifecycleStage stage: (SortedSet<WorkflowLifecycleStage>)this.getStages()){
+        if(stage.getName().equals(category)){
+          return stage;
+        }
+      }
+    }
+    
+    return null;
+  }
+  
+  public WorkflowState createState(String name, String category, String message){
+    WorkflowState state = new WorkflowState();
+    state.setName(name);
+    state.setCategory(getCategoryByName(category));
+    state.setMessage(message);
+    return state;
+  }
+
+  private WorkflowState makeCopy(WorkflowState state){
+    WorkflowState newState = new WorkflowState();
+    newState.setCategory(state.getCategory());
+    newState.setDescription(state.getDescription());
+    newState.setMessage(state.getMessage());
+    newState.setName(state.getName());
+    newState.setPrevState(state.getPrevState());
+    newState.setStartTime(state.getStartTime());
+    return newState;
+  }
+  
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecycleManager.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecycleManager.java
new file mode 100644
index 0000000..7b2e770
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecycleManager.java
@@ -0,0 +1,231 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.lifecycle;
+
+//JDK imports
+import java.text.NumberFormat;
+import java.util.Iterator;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowStatus;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Manager interface for the {@link WorkflowLifecycles} to
+ * determine status for a {@link WorkflowInstance}.
+ * </p>.
+ */
+public class WorkflowLifecycleManager {
+
+    private List lifecycles;
+
+    /**
+     * Constructs a new WorkflowLifecycleManager with the
+     * {@link WorkflowLifecycle}s identified in the provided file path.
+     * 
+     * @param lifecyclesFilePath
+     */
+    public WorkflowLifecycleManager(String lifecyclesFilePath)
+            throws InstantiationException {
+        try {
+            this.lifecycles = WorkflowLifecyclesReader
+                    .parseLifecyclesFile(lifecyclesFilePath);
+        } catch (Exception e) {
+            throw new InstantiationException(e.getMessage());
+        }
+    }
+
+    /**
+     * Gets the number of the current {@link WorkflowLifecycleStage} for the
+     * provided {@link WorkflowInstance}.
+     * 
+     * @param inst
+     *            The {@link WorkflowInstance} to get the current stage num for.
+     * @return The int number representing the current
+     *         {@link WorkflowLifecycleStage} for the provided
+     *         {@link WorkflowInstance}.
+     */
+    public int getStageNum(WorkflowInstance inst) {
+        WorkflowLifecycleStage stage = getStage(inst);
+        if (stage != null) {
+            return stage.getOrder();
+        } else
+            return -1;
+    }
+
+    /**
+     * Gets the total number of {@link WorkflowLifecycleStage}s for the
+     * provided {@link Workflow} model.
+     * 
+     * @param workflow
+     *            The {@link Workflow} model to get the number of
+     *            {@link WorkflowLifecycleStage}s for. Only the identifier
+     *            parameter from
+     * @link {@link Workflow#getId()} is used.
+     * @return The total number of {@link WorkflowLifecycleStage}s for the
+     *         provided {@link Workflow} model.
+     */
+    public int getNumStages(Workflow workflow) {
+        WorkflowLifecycle lifecycle = getLifecycleForWorkflow(workflow);
+        if (lifecycle != null) {
+            return lifecycle.getStages().size();
+        } else
+            return -1;
+    }
+
+    /**
+     * Gets the current {@link WorkflowLifecycleStage} for the provided
+     * {@link WorkflowInstance} based on its
+     * {@link WorkflowInstance#getStatus()} value.
+     * 
+     * @param inst
+     *            The {@link WorkflowInstance} to get the current stage for.
+     * @return The current {@link WorkflowLifecycleStage} for the provided
+     *         {@link WorkflowInstance} based on its
+     *         {@link WorkflowInstance#getStatus()} value.
+     */
+    public WorkflowLifecycleStage getStage(WorkflowInstance inst) {
+        WorkflowLifecycle lifecycle = getLifecycleForWorkflow(inst
+                .getWorkflow());
+        if (lifecycle != null) {
+            WorkflowLifecycleStage stage = lifecycle.getStageForWorkflow(inst
+                    .getStatus());
+            return stage;
+        } else
+            return null;
+    }
+
+    /**
+     * Gets the percentage complete that this {@link WorkflowInstance} is based
+     * on its {@link WorkflowLifecycle}.
+     * 
+     * @param inst
+     *            The {@link WorkflowInstance} to get the completion percentage
+     *            for.
+     * @return The double value representing the completion percentage for this
+     *         {@link WorkflowInstance}.
+     */
+    public double getPercentageComplete(WorkflowInstance inst) {
+        int numStages = getNumStages(inst.getWorkflow());
+        int lastCompletedStageNum = getLastCompletedStageNum(inst);
+
+        double pct = (double) ((lastCompletedStageNum * 1.0) / (numStages * 1.0));
+        return pct;
+    }
+
+    /**
+     * Formats a double percent number to a 2 decimal place String.
+     * 
+     * @param pct
+     *            The double percent number to format.
+     * @return A String formatted 2 decimal place String.
+     */
+    public static String formatPct(double pct) {
+        NumberFormat formatter = NumberFormat.getInstance();
+        formatter.setMaximumFractionDigits(2);
+        return formatter.format(pct);
+    }
+
+    /**
+     * 
+     * @return The default {@link WorkflowLifecycle} managed by this
+     *         WorkflowLifecycleManager.
+     */
+    public WorkflowLifecycle getDefaultLifecycle() {
+        WorkflowLifecycle defaultLifecycle = null;
+
+        if (this.lifecycles != null && this.lifecycles.size() > 0) {
+            for (Iterator i = this.lifecycles.iterator(); i.hasNext();) {
+                WorkflowLifecycle lifecycle = (WorkflowLifecycle) i.next();
+
+                if (lifecycle.getName().equals(
+                        WorkflowLifecycle.DEFAULT_LIFECYCLE)) {
+                    defaultLifecycle = lifecycle;
+                }
+            }
+
+        }
+
+        return defaultLifecycle;
+    }
+
+    /**
+     * Gets the {@link WorkflowLifecycle} associated with the provided
+     * {@link Workflow} model.
+     * 
+     * @param workflow
+     *            The {@link Workflow} to obtain the {@link WorkflowLifecycle}
+     *            for.
+     * @return The {@link WorkflowLifecycle} associated with the provided
+     *         {@link Workflow} model.
+     */
+    public WorkflowLifecycle getLifecycleForWorkflow(Workflow workflow) {
+        WorkflowLifecycle defaultLifecycle = null;
+
+        if (this.lifecycles != null && this.lifecycles.size() > 0) {
+            for (Iterator i = this.lifecycles.iterator(); i.hasNext();) {
+                WorkflowLifecycle lifecycle = (WorkflowLifecycle) i.next();
+                if (lifecycle.getWorkflowId().equals(workflow.getId())) {
+                    return lifecycle;
+                }
+
+                if (lifecycle.getName().equals(
+                        WorkflowLifecycle.DEFAULT_LIFECYCLE)) {
+                    defaultLifecycle = lifecycle;
+                }
+            }
+
+            return defaultLifecycle;
+        } else
+            return null;
+    }
+
+    /**
+     * Gets the last completed stage for the given {@link WorkflowInstance}.
+     * 
+     * @param inst
+     *            The {@link WorkflowInstance} to obtain the last completed
+     *            stage number for.
+     * @return The last completed stage for the given {@link WorkflowInstance}.
+     */
+    public int getLastCompletedStageNum(WorkflowInstance inst) {  
+        int currStageNum = getStageNum(inst);
+        if(inst.getState().getCategory() == null){
+          WorkflowLifecycleStage category = null;
+          if((category = getStage(inst)) != null){
+            inst.getState().setCategory(category);
+          }          
+        }
+        
+        if ((inst.getStatus().equals(WorkflowStatus.FINISHED) || 
+             (inst.getState().getCategory() != null && 
+             inst.getState().getCategory().getName().equals("done")))
+                && currStageNum == getNumStages(inst.getWorkflow())) {
+            return currStageNum;
+        } else
+            return currStageNum - 1;
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecycleMetKeys.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecycleMetKeys.java
new file mode 100644
index 0000000..07eb96c
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecycleMetKeys.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.lifecycle;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Metadata keys for reading the {@link WorkflowLicycle}s file
+ * </p>.
+ */
+public interface WorkflowLifecycleMetKeys {
+
+    public static final String DEFAULT_LIFECYCLE = "default";
+
+    public static final String LIFECYCLE_TAG_NAME_ATTR = "name";
+
+    public static final String STAGE_TAG_NAME_ATTR = "name";
+
+    public static final String STATUS_TAG_NAME = "status";
+
+    public static final String STAGE_ELEM_NAME = "stage";
+
+    public static final String LIFECYCLE_TAG_NAME = "lifecycle";
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecycleStage.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecycleStage.java
new file mode 100644
index 0000000..1f00b97
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecycleStage.java
@@ -0,0 +1,142 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.lifecycle;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * 
+ * A particular step (or Stage) in a {@link WorkflowLifecycle}
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowLifecycleStage {
+
+  private String name;
+
+  private int order;
+
+  private List<WorkflowState> states;
+
+  /**
+   * Default Constructor.
+   * 
+   */
+  public WorkflowLifecycleStage() {
+    states = new Vector<WorkflowState>();
+  }
+
+  /**
+   * Constructs a new WorkflowLifecycleSage with the given parameters.
+   * 
+   * @param name
+   *          The name of the WorkflowLifeCycleStage.
+   * @param states
+   *          The {@link List} of String states that are part of this particular
+   *          stage.
+   * 
+   * @param order
+   *          The ordering of this State in a {@List} of States that make
+   *          up a {@link WorkflowLifeCycle}.
+   */
+  public WorkflowLifecycleStage(String name, List<WorkflowState> states,
+      int order) {
+    this.name = name;
+    this.states = states;
+    this.order = order;
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return the states
+   */
+  public List<WorkflowState> getStates() {
+    return states;
+  }
+
+  /**
+   * @param states
+   *          the states to set
+   */
+  public void setStates(List<WorkflowState> states) {
+    this.states = states;
+  }
+
+  /**
+   * @return the order
+   */
+  public int getOrder() {
+    return order;
+  }
+
+  /**
+   * @param order
+   *          the order to set
+   */
+  public void setOrder(int order) {
+    this.order = order;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see java.lang.Object#hashCode()
+   */
+  public int hashCode() {
+    return this.name.hashCode() + new Integer(this.order).hashCode();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see java.lang.Object#equals(java.lang.Object)
+   */
+  @Override
+  public boolean equals(Object stage) {
+    return this.name.equals(((WorkflowLifecycleStage) stage).getName());
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see java.lang.Object#toString()
+   */
+  @Override
+  public String toString() {
+    return this.name;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecyclesReader.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecyclesReader.java
new file mode 100644
index 0000000..e9e34df
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowLifecyclesReader.java
@@ -0,0 +1,189 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.lifecycle;
+
+//OODT imports
+import org.apache.oodt.commons.xml.DOMUtil;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A reader for the <code>workflow-lifecycle.xml</code> file.
+ * </p>.
+ */
+public final class WorkflowLifecyclesReader implements WorkflowLifecycleMetKeys {
+
+    /* our log stream */
+    private static Logger LOG = Logger.getLogger(WorkflowLifecyclesReader.class
+            .getName());
+
+    private WorkflowLifecyclesReader() throws InstantiationException {
+        throw new InstantiationException("Don't construct utility classes!");
+    }
+
+    public static List parseLifecyclesFile(String lifecyclesFilePath)
+            throws Exception {
+        Document doc = getDocumentRoot(lifecyclesFilePath);
+        Element rootElem = doc.getDocumentElement();
+        List lifecycles = new Vector();
+
+        // make sure that there is a default tag
+        Element defaultElem = DOMUtil.getFirstElement(rootElem,
+                DEFAULT_LIFECYCLE);
+
+        if (defaultElem == null) {
+            throw new Exception("file: [" + lifecyclesFilePath
+                    + "] must specify a default workflow lifecycle!");
+        }
+
+        WorkflowLifecycle defaultLifecycle = readLifecycle(defaultElem, true);
+        lifecycles.add(defaultLifecycle);
+
+        NodeList lifecycleNodes = defaultElem
+                .getElementsByTagName(LIFECYCLE_TAG_NAME);
+        if (lifecycleNodes != null && lifecycleNodes.getLength() > 0) {
+            for (int i = 0; i < lifecycleNodes.getLength(); i++) {
+                Element lifecycleElem = (Element) lifecycleNodes.item(i);
+                lifecycles.add(readLifecycle(lifecycleElem));
+            }
+        }
+
+        return lifecycles;
+
+    }
+
+    private static WorkflowLifecycle readLifecycle(Element lifecycleElem) {
+        return readLifecycle(lifecycleElem, false);
+    }
+
+    private static WorkflowLifecycle readLifecycle(Element lifecycleElem,
+            boolean isDefault) {
+        WorkflowLifecycle lifecycle = new WorkflowLifecycle();
+        String lifecycleName = isDefault ? WorkflowLifecycle.DEFAULT_LIFECYCLE
+                : lifecycleElem.getAttribute(LIFECYCLE_TAG_NAME_ATTR);
+        lifecycle.setName(lifecycleName);
+        lifecycle.setWorkflowId(WorkflowLifecycle.NO_WORKFLOW_ID);
+        addStagesToLifecycle(lifecycle, lifecycleElem);
+
+        return lifecycle;
+    }
+
+    private static void addStagesToLifecycle(WorkflowLifecycle lifecycle,
+            Element lifecycleElem) {
+        NodeList stagesNodes = lifecycleElem
+                .getElementsByTagName(STAGE_ELEM_NAME);
+
+        if (stagesNodes != null && stagesNodes.getLength() > 0) {
+            for (int i = 0; i < stagesNodes.getLength(); i++) {
+                Element stageElem = (Element) stagesNodes.item(i);
+                WorkflowLifecycleStage stage = new WorkflowLifecycleStage();
+                stage.setName(stageElem.getAttribute(STAGE_TAG_NAME_ATTR));
+                stage.setOrder(i+1);
+                stage.setStates(readStates(stageElem, stage));
+                lifecycle.addStage(stage);
+            }
+        }
+    }
+    
+    private static List<WorkflowState> readStates(Element stageElem, WorkflowLifecycleStage category){
+      List<WorkflowState> states = new Vector<WorkflowState>();
+      NodeList statusNodeList = stageElem.getElementsByTagName(STATUS_TAG_NAME);
+      if(statusNodeList != null && statusNodeList.getLength() > 0){
+        for(int i=0; i < statusNodeList.getLength(); i++){
+          Element statusElem = (Element)statusNodeList.item(i);
+          // see if its name is specified via the name attribute, otherwise
+          // read it in back compat mode
+          
+          if(statusElem.getAttribute("name") != null && 
+              !statusElem.getAttribute("name").equals("")){
+            String statusName = statusElem.getAttribute("name");
+            String description = XMLUtils.getElementText("description", statusElem);
+            WorkflowState state = new WorkflowState();
+            state.setCategory(category);
+            state.setName(statusName);
+            state.setDescription(description);
+            states.add(state);
+          }
+          else{
+            // back compat mode
+            String statusName = XMLUtils.getSimpleElementText(statusElem);
+            WorkflowState state = new WorkflowState();
+            state.setName(statusName);
+            state.setMessage(statusName);
+            state.setCategory(category);
+            states.add(state);
+          }
+        }
+      }
+      
+      return states;
+    }
+
+    private static Document getDocumentRoot(String xmlFile) {
+        // open up the XML file
+        DocumentBuilderFactory factory = null;
+        DocumentBuilder parser = null;
+        Document document = null;
+        InputSource inputSource = null;
+
+        InputStream xmlInputStream = null;
+
+        try {
+            xmlInputStream = new File(xmlFile).toURL().openStream();
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when getting input stream from [" + xmlFile
+                            + "]: returning null document root");
+            return null;
+        }
+
+        inputSource = new InputSource(xmlInputStream);
+
+        try {
+            factory = DocumentBuilderFactory.newInstance();
+            parser = factory.newDocumentBuilder();
+            document = parser.parse(inputSource);
+        } catch (Exception e) {
+            LOG.warning("Unable to parse xml file [" + xmlFile + "]."
+                    + "Reason is [" + e + "]");
+            return null;
+        }
+
+        return document;
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowState.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowState.java
new file mode 100644
index 0000000..cbe1ca4
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/lifecycle/WorkflowState.java
@@ -0,0 +1,140 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.lifecycle;
+
+//JDK imports
+import java.util.Date;
+import java.util.Vector;
+
+/**
+ * 
+ * The state of a WorkflowProcessor
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowState {
+
+  private String name;
+  private String description;
+	private String message;
+	private Date startTime;
+	private WorkflowLifecycleStage category;
+	private WorkflowState prevState;
+	
+	
+	public WorkflowState(){
+	  this.startTime = null;
+	  this.name = null;
+	  this.description = null;
+	  this.message = null;
+	  this.category = null;
+	  this.prevState = null;
+	}
+	
+	public WorkflowState(String message) {
+	  this();
+		this.message = message;
+		this.startTime = new Date();
+	}
+	
+	public void setMessage(String message){
+	  this.message = message;
+	}
+	
+	public void setStartTime(Date startTime){
+	  this.startTime = startTime;
+	}
+	
+	public String getMessage() {
+		return this.message;
+	}
+	
+	public Date getStartTime() {
+		return this.startTime;
+	}
+	
+	public boolean equals(Object obj) {
+		if (obj instanceof WorkflowState) 
+			return ((WorkflowState) obj).getName().equals(this.getName());
+		else
+			return false;
+	}
+		
+	public String toString() {
+		return this.getName() + " ["+this.getCategory()+"] : " + this.getMessage();
+	}
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return the description
+   */
+  public String getDescription() {
+    return description;
+  }
+
+  /**
+   * @param description the description to set
+   */
+  public void setDescription(String description) {
+    this.description = description;
+  }
+
+  /**
+   * @return the category
+   */
+  public WorkflowLifecycleStage getCategory() {
+    return category;
+  }
+
+  /**
+   * @param category the category to set
+   */
+  public void setCategory(WorkflowLifecycleStage category) {
+    this.category = category;
+  }
+
+  /**
+   * @return the prevState
+   */
+  public WorkflowState getPrevState() {
+    return prevState;
+  }
+
+  /**
+   * @param prevState the prevState to set
+   */
+  public void setPrevState(WorkflowState prevState) {
+    this.prevState = prevState;
+  }
+	
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/metadata/CoreMetKeys.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/metadata/CoreMetKeys.java
new file mode 100644
index 0000000..3c62a8b
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/metadata/CoreMetKeys.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Core metadata key names for the Workflow Manager
+ * </p>.
+ */
+public interface CoreMetKeys {
+
+    public static final String TASK_ID = "TaskId";
+
+    public static final String WORKFLOW_INST_ID = "WorkflowInstId";
+
+    public static final String JOB_ID = "JobId";
+
+    public static final String PROCESSING_NODE = "ProcessingNode";
+
+    public static final String WORKFLOW_MANAGER_URL = "WorkflowManagerUrl";
+
+    public static final String QUEUE_NAME = "QueueName";
+    
+    public static final String TASK_LOAD = "TaskLoad";
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/DataSourceWorkflowRepository.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/DataSourceWorkflowRepository.java
new file mode 100644
index 0000000..7a60559
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/DataSourceWorkflowRepository.java
@@ -0,0 +1,1786 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.repository;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.util.DbStructFactory;
+import org.apache.oodt.cas.workflow.examples.NoOpTask;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.exceptions.RepositoryException;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+/**
+ * 
+ * A {@link DataSource}-based implementation of a workflow repository.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ */
+public class DataSourceWorkflowRepository implements WorkflowRepository {
+
+  /* our data source */
+  private DataSource dataSource = null;
+
+  /* our log stream */
+  private Logger LOG = Logger.getLogger(DataSourceWorkflowRepository.class
+      .getName());
+
+  /**
+   * <p>
+   * Default Constructor
+   * </p>
+   * .
+   */
+  public DataSourceWorkflowRepository(DataSource ds) {
+    dataSource = ds;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflowByName
+   * (java.lang.String)
+   */
+  public Workflow getWorkflowByName(String workflowName)
+      throws RepositoryException {
+    return getWorkflowByName(workflowName, true, true);
+  }
+
+  public Workflow getWorkflowByName(String workflowName, boolean getTasks,
+      boolean getConditions) throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    Workflow workflow = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getWorkflowSql = "SELECT * from workflows WHERE workflow_name = '"
+          + workflowName + "'";
+
+      LOG.log(Level.FINE, "getWorkflowByName: Executing: " + getWorkflowSql);
+      rs = statement.executeQuery(getWorkflowSql);
+
+      while (rs.next()) {
+        workflow = DbStructFactory.getWorkflow(rs);
+
+        if (getTasks) {
+          workflow.setTasks(getTasksByWorkflowId(workflow.getId()));
+        }
+
+        if (getConditions) {
+          workflow.setConditions(getConditionsByWorkflowId(workflow.getId()));
+          handleGlobalWorkflowConditions(workflow);
+        }
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Exception getting workflow. Message: " + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(
+            Level.SEVERE,
+            "Unable to rollback getWorkflowByName transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return workflow;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflowById
+   * (java.lang.String)
+   */
+  public Workflow getWorkflowById(String workflowId) throws RepositoryException {
+    return getWorkflowById(workflowId, true, true);
+  }
+
+  public Workflow getWorkflowById(String workflowId, boolean getTasks,
+      boolean getConditions) throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    Workflow workflow = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getWorkflowSql = "SELECT * from workflows WHERE workflow_id = '"
+          + workflowId + "'";
+
+      LOG.log(Level.FINE, "getWorkflowById: Executing: " + getWorkflowSql);
+      rs = statement.executeQuery(getWorkflowSql);
+
+      while (rs.next()) {
+        workflow = DbStructFactory.getWorkflow(rs);
+
+        if (getTasks) {
+          workflow.setTasks(getTasksByWorkflowId(workflow.getId()));
+        }
+
+        if (getConditions) {
+          workflow.setConditions(getConditionsByWorkflowId(workflow.getId()));
+          handleGlobalWorkflowConditions(workflow);
+        }
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Exception getting workflow. Message: " + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(
+            Level.SEVERE,
+            "Unable to rollback getWorkflowById transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return workflow;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflows()
+   */
+  public List getWorkflows() throws RepositoryException {
+    return getWorkflows(true, true);
+  }
+
+  public List getWorkflows(boolean getTasks, boolean getConditions)
+      throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    List workflows = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getWorkflowSql = "SELECT * from workflows";
+
+      LOG.log(Level.FINE, "getWorkflows: Executing: " + getWorkflowSql);
+      rs = statement.executeQuery(getWorkflowSql);
+      workflows = new Vector();
+
+      while (rs.next()) {
+        Workflow workflow = DbStructFactory.getWorkflow(rs);
+
+        if (getTasks) {
+          workflow.setTasks(getTasksByWorkflowId(workflow.getId()));
+        }
+
+        if (getConditions) {
+          workflow.setConditions(getConditionsByWorkflowId(workflow.getId()));
+          handleGlobalWorkflowConditions(workflow);
+        }
+
+        workflows.add(workflow);
+      }
+
+      if (workflows.size() == 0) {
+        workflows = null;
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Exception getting workflows. Message: " + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(
+            Level.SEVERE,
+            "Unable to rollback getWorkflows transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return workflows;
+  }
+
+  public List getTasksByWorkflowId(String workflowId)
+      throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    List tasks = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getTasksSql = "SELECT workflow_tasks.*, workflow_task_map.task_order "
+          + "FROM workflow_tasks, workflow_task_map "
+          + "WHERE workflow_task_map.workflow_task_id = workflow_tasks.workflow_task_id "
+          + "AND workflow_task_map.workflow_id = "
+          + workflowId
+          + " "
+          + "ORDER BY workflow_task_map.task_order";
+
+      LOG.log(Level.FINE, "getTasksByWorkflowId: Executing: " + getTasksSql);
+      rs = statement.executeQuery(getTasksSql);
+      tasks = new Vector();
+
+      while (rs.next()) {
+        // get an instance of the class name
+
+        WorkflowTask task = DbStructFactory.getWorkflowTask(rs, true);
+
+        if (task != null) {
+          task.setConditions(getConditionsByTaskId(task.getTaskId()));
+          task.setTaskConfig(getConfigurationByTaskId(task.getTaskId()));
+          tasks.add(task);
+        }
+      }
+
+      if (tasks.size() == 0) {
+        tasks = null;
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Exception getting tasks for workflow. Message: "
+          + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE,
+            "Unable to rollback getTasksByWorkflowId transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return tasks;
+  }
+
+  public List getTasksByWorkflowName(String workflowName)
+      throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    List tasks = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getTasksSql = "SELECT workflow_tasks.*, workflow_task_map.task_order "
+          + "FROM workflow_tasks, workflow_task_map, workflows "
+          + "WHERE workflow_task_map.workflow_task_id = workflow_tasks.workflow_task_id "
+          + "AND workflow_task_map.workflow_id = workflows.workflow_id "
+          + "AND workflows.workflow_name = '"
+          + workflowName
+          + "' "
+          + "ORDER BY workflow_task_map.task_order";
+
+      LOG.log(Level.FINE, "getTasksByWorkflowName: Executing: " + getTasksSql);
+      rs = statement.executeQuery(getTasksSql);
+      tasks = new Vector();
+
+      while (rs.next()) {
+        // get an instance of the class name
+        WorkflowTask task = DbStructFactory.getWorkflowTask(rs, true);
+
+        if (task != null) {
+          task.setConditions(getConditionsByTaskId(task.getTaskId()));
+          task.setTaskConfig(getConfigurationByTaskId(task.getTaskId()));
+          tasks.add(task);
+        }
+      }
+
+      if (tasks.size() == 0) {
+        tasks = null;
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Exception getting tasks for workflow. Message: "
+          + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE,
+            "Unable to rollback getTasksByWorkflowName transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return tasks;
+  }
+
+  public List getWorkflowsForEvent(String eventName) throws RepositoryException {
+    return getWorkflowsForEvent(eventName, true, true);
+  }
+
+  public List getWorkflowsForEvent(String eventName, boolean getTasks,
+      boolean getConditions) throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    List workflows = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getWorkflowSql = "SELECT * from workflows, event_workflow_map WHERE event_workflow_map.workflow_id = workflows.workflow_id  "
+          + "AND event_workflow_map.event_name = '" + eventName + "'";
+
+      LOG.log(Level.FINE, "getWorkflowsForEvent: Executing: " + getWorkflowSql);
+      rs = statement.executeQuery(getWorkflowSql);
+      workflows = new Vector();
+
+      while (rs.next()) {
+        Workflow workflow = DbStructFactory.getWorkflow(rs);
+
+        if (getTasks) {
+          workflow.setTasks(getTasksByWorkflowId(workflow.getId()));
+        }
+
+        if (getConditions) {
+          workflow.setConditions(getConditionsByWorkflowId(workflow.getId()));
+          handleGlobalWorkflowConditions(workflow);
+        }
+
+        workflows.add(workflow);
+      }
+
+      if (workflows.size() == 0) {
+        workflows = null;
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Exception getting workflows for event. Message: "
+          + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE,
+            "Unable to rollback getWorkflowsForEvent transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return workflows;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#
+   * getConditionsByTaskName(java.lang.String)
+   */
+  public List getConditionsByTaskName(String taskName)
+      throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    List conditions = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getConditionsSql = "SELECT workflow_conditions.*, task_condition_map.condition_order "
+          + "FROM workflow_conditions, task_condition_map, workflow_tasks "
+          + "WHERE task_condition_map.workflow_condition_id = workflow_conditions.workflow_condition_id "
+          + "AND task_condition_map.workflow_task_id = workflow_tasks.workflow_task_id "
+          + "AND workflow_tasks.workflow_task_name = '"
+          + taskName
+          + "' "
+          + "ORDER BY task_condition_map.condition_order";
+
+      LOG.log(Level.FINE, "getConditionsByTaskName: Executing: "
+          + getConditionsSql);
+      rs = statement.executeQuery(getConditionsSql);
+      conditions = new Vector();
+
+      while (rs.next()) {
+        // get an instance of the class name
+        WorkflowCondition condition = DbStructFactory.getWorkflowCondition(rs,
+            true);
+        conditions.add(condition);
+      }
+
+      if (conditions.size() == 0) {
+        conditions = null;
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Exception getting conditions for task. Message: "
+          + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE,
+            "Unable to rollback getConditionsByTaskName transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return conditions;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#
+   * getConditionsByTaskId(java.lang.String)
+   */
+  public List getConditionsByTaskId(String taskId) throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    List conditions = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getConditionsSql = "SELECT workflow_conditions.*, task_condition_map.condition_order "
+          + "FROM workflow_conditions, task_condition_map "
+          + "WHERE task_condition_map.workflow_condition_id = workflow_conditions.workflow_condition_id "
+          + "AND task_condition_map.workflow_task_id = "
+          + taskId
+          + " "
+          + "ORDER BY task_condition_map.condition_order";
+
+      LOG.log(Level.FINE, "getConditionsByTaskId: Executing: "
+          + getConditionsSql);
+      rs = statement.executeQuery(getConditionsSql);
+      conditions = new Vector();
+
+      while (rs.next()) {
+        // get an instance of the class name
+        WorkflowCondition condition = DbStructFactory.getWorkflowCondition(rs,
+            true);
+        conditions.add(condition);
+      }
+
+      if (conditions.size() == 0) {
+        conditions = null;
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Exception getting conditions for task. Message: "
+          + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE,
+            "Unable to rollback getConditionsByTaskId transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return conditions;
+  }
+
+  public WorkflowTaskConfiguration getConfigurationByTaskId(String taskId)
+      throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    WorkflowTaskConfiguration config = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getConfigurationSql = "SELECT * from workflow_task_configuration WHERE workflow_task_id = "
+          + taskId;
+
+      LOG.log(Level.FINE, "getConfigurationByTaskId: Executing: "
+          + getConfigurationSql);
+      rs = statement.executeQuery(getConfigurationSql);
+
+      config = new WorkflowTaskConfiguration();
+      while (rs.next()) {
+        config.getProperties().put(rs.getString("property_name"),
+            rs.getString("property_value"));
+      }
+
+      if (config.getProperties().keySet().size() == 0) {
+        config = null;
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Exception getting task configuration for taskId: " + taskId
+              + " Message: " + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE,
+            "Unable to rollback getConfigurationBytaskId transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return config;
+  }
+
+  public WorkflowConditionConfiguration getConfigurationByConditionId(
+      String condId) throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    WorkflowConditionConfiguration config = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getConfigurationSql = "SELECT * from workflow_condition_configuration WHERE workflow_condition_id = "
+          + condId;
+
+      LOG.log(Level.FINE, "getConfigurationByConfigurationId: Executing: "
+          + getConfigurationSql);
+      rs = statement.executeQuery(getConfigurationSql);
+
+      config = new WorkflowConditionConfiguration();
+      while (rs.next()) {
+        config.getProperties().put(rs.getString("property_name"),
+            rs.getString("property_value"));
+      }
+
+      if (config.getProperties().keySet().size() == 0) {
+        config = null;
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Exception getting task configuration for condId: " + condId
+              + " Message: " + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE,
+            "Unable to rollback getConfigurationByConfigurationId transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return config;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflowTaskById
+   * (java.lang.String)
+   */
+  public WorkflowTask getWorkflowTaskById(String taskId)
+      throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    WorkflowTask task = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getTaskSql = "SELECT * FROM workflow_tasks WHERE workflow_task_id = "
+          + taskId;
+
+      LOG.log(Level.FINE, "getWorkflowTaskById: Executing: " + getTaskSql);
+      rs = statement.executeQuery(getTaskSql);
+
+      while (rs.next()) {
+        // get an instance of the class name
+        task = DbStructFactory.getWorkflowTask(rs, false);
+        task.setConditions(getConditionsByTaskId(task.getTaskId()));
+        task.setTaskConfig(getConfigurationByTaskId(task.getTaskId()));
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Exception getting task by id. Message: " + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE,
+            "Unable to rollback getWorkflowTaskById transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return task;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#
+   * getWorkflowConditionById(java.lang.String)
+   */
+  public WorkflowCondition getWorkflowConditionById(String conditionId)
+      throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    WorkflowCondition condition = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getConditionsSql = "SELECT * FROM workflow_conditions WHERE workflow_condition_id = "
+          + conditionId;
+
+      LOG.log(Level.FINE, "getWorkflowConditionById: Executing: "
+          + getConditionsSql);
+      rs = statement.executeQuery(getConditionsSql);
+
+      while (rs.next()) {
+        // get an instance of the class name
+        condition = DbStructFactory.getWorkflowCondition(rs, false);
+        condition.setCondConfig(getConfigurationByConditionId(conditionId));
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Exception getting condition by id. Message: " + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE,
+            "Unable to rollback getWorkflowConditionById transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return condition;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#getRegisteredEvents
+   * ()
+   */
+  public List getRegisteredEvents() throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    List events = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getEventSql = "SELECT DISTINCT event_name FROM event_workflow_map ORDER BY event_name ASC";
+
+      LOG.log(Level.FINE, "getRegisteredEvents: Executing: " + getEventSql);
+      rs = statement.executeQuery(getEventSql);
+      events = new Vector();
+
+      while (rs.next()) {
+        // get an instance of the class name
+        String event = DbStructFactory.getEvent(rs);
+        events.add(event);
+      }
+
+      if (events.size() == 0) {
+        events = null;
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Exception getting registered events. Message: "
+          + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE,
+            "Unable to rollback getRegisteredEvents transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return events;
+  }
+  
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#addTask(org.apache.oodt.cas.workflow.structs.WorkflowTask)
+   */
+  @Override
+  public String addTask(WorkflowTask task) throws RepositoryException {
+    List<WorkflowCondition> allConditions = getConditions();
+    // check its conditions
+    if(task.getPreConditions() != null && task.getPreConditions().size() > 0){
+      for(WorkflowCondition cond: task.getPreConditions()){
+        if(!this.hasConditionId(allConditions, cond.getConditionId())){
+          throw new RepositoryException("Reference in new task: ["+task.getTaskName()+"] to undefined pre condition ith id: ["+cond.getConditionId()+"]");            
+        }          
+      }
+      
+      for(WorkflowCondition cond: task.getPostConditions()){
+        if(!this.hasConditionId(allConditions, cond.getConditionId())){
+          throw new RepositoryException("Reference in new task: ["+task.getTaskName()+"] to undefined post condition ith id: ["+cond.getConditionId()+"]");            
+        }              
+      }
+    }
+    
+    String taskId = this.commitTask(null, task);
+    return taskId;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#addWorkflow(
+   * org.apache.oodt.cas.workflow.structs.Workflow)
+   */
+  @Override
+  public String addWorkflow(Workflow workflow) throws RepositoryException {
+    // first check to see that its tasks are all present
+    if (workflow.getTasks() == null
+        || (workflow.getTasks() != null && workflow.getTasks().size() == 0)) {
+      throw new RepositoryException("Attempt to define a new worklfow: ["
+          + workflow.getName() + "] with no tasks.");
+    }
+
+    List<WorkflowTask> allTasks = this.getTasks();
+
+    for (WorkflowTask task : (List<WorkflowTask>) workflow.getTasks()) {
+      if (!this.hasTaskId(allTasks, task.getTaskId())) {
+        throw new RepositoryException("Reference in new workflow: ["
+            + workflow.getName() + "] to undefined task with id: ["
+            + task.getTaskId() + "]");
+      }
+
+      // check its conditions
+      if (task.getConditions() != null && task.getConditions().size() > 0) {
+        List<WorkflowCondition> conditions = this.getConditionsByTaskId(task
+            .getTaskId());
+        for (WorkflowCondition cond : (List<WorkflowCondition>) task
+            .getConditions()) {
+          if (!this.hasConditionId(conditions, cond.getConditionId())) {
+            throw new RepositoryException("Reference in new workflow: ["
+                + workflow.getName() + "] to undefined condition ith id: ["
+                + cond.getConditionId() + "]");
+          }
+        }
+      }
+    }
+
+    String workflowId = this.commitWorkflow(workflow);
+    return workflowId;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#
+   * getConditionsByWorkflowId(java.lang.String)
+   */
+  @Override
+  public List<WorkflowCondition> getConditionsByWorkflowId(String workflowId)
+      throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    List<WorkflowCondition> conditions = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getConditionsSql = "SELECT workflow_conditions.*, workflow_condition_map.condition_order "
+          + "FROM workflow_conditions, workflow_condition_map "
+          + "WHERE workflow_condition_map.workflow_condition_id = workflow_conditions.workflow_condition_id "
+          + "AND workflow_condition_map.workflow_id = "
+          + workflowId
+          + " "
+          + "ORDER BY workflow_condition_map.condition_order";
+
+      LOG.log(Level.FINE, "getConditionsByWorkflowId: Executing: "
+          + getConditionsSql);
+      rs = statement.executeQuery(getConditionsSql);
+      conditions = new Vector<WorkflowCondition>();
+
+      while (rs.next()) {
+        // get an instance of the class name
+        WorkflowCondition condition = DbStructFactory.getWorkflowCondition(rs,
+            true);
+        conditions.add(condition);
+      }
+
+      if (conditions.size() == 0) {
+        conditions = null;
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(
+          Level.WARNING,
+          "Exception getting conditions for workflow. Message: "
+              + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE,
+            "Unable to rollback getConditionsByWorkflowId transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return conditions;
+  }
+  
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getTaskById(java.lang.String)
+   */
+  @Override
+  public WorkflowTask getTaskById(String taskId) throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    WorkflowTask task = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getTasksSql = "SELECT * "
+          + "FROM workflow_tasks "
+          + "WHERE workflow_task_id = " + taskId;
+
+      LOG.log(Level.FINE, "getTaskById: Executing: " + getTasksSql);
+      rs = statement.executeQuery(getTasksSql);
+     
+
+      while (rs.next()) {
+        // get an instance of the class name
+
+        task = DbStructFactory.getWorkflowTask(rs, true);
+
+        if (task != null) {
+          task.setConditions(getConditionsByTaskId(task.getTaskId()));
+          task.setTaskConfig(getConfigurationByTaskId(task.getTaskId()));
+        }
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Exception getting tasks for workflow. Message: "
+          + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE,
+            "Unable to rollback getTasksByWorkflowId transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return task;
+  }    
+
+  private String commitWorkflow(Workflow workflow) throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    String workflowId = null;
+
+    try {
+      conn = dataSource.getConnection();
+      conn.setAutoCommit(false);
+      statement = conn.createStatement();
+
+      String sql = "INSERT INTO workflows (workflow_name) VALUES ('"
+          + workflow.getName() + "')";
+
+      LOG.log(Level.FINE, "commitWorkflowToDB: Executing: " + sql);
+      statement.execute(sql);
+
+      sql = "SELECT MAX(workflow_id) AS max_id FROM workflows";
+      rs = statement.executeQuery(sql);
+
+      while (rs.next()) {
+        workflowId = String.valueOf(rs.getInt("max_id"));
+      }
+
+      workflow.setId(workflowId);
+
+      // event to workflow map
+      sql = "INSERT INTO event_workflow_map (workflow_id, event_name) VALUES ("
+          + workflowId + ",'workflow-" + workflowId + "')";
+      LOG.log(Level.FINE, "commitWorkflowToDB: Executing: " + sql);
+      statement.execute(sql);
+      conn.commit();
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Exception adding workflow. Message: " + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(
+            Level.SEVERE,
+            "Unable to rollback workflow transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return workflowId;
+  }
+
+  private String commitTask(Workflow workflow, WorkflowTask task)
+      throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+    String taskId = null;
+
+    try {
+      conn = dataSource.getConnection();
+      conn.setAutoCommit(false);
+      statement = conn.createStatement();
+
+      String sql = "SELECT MAX(workflow_task_id) AS max_id FROM workflow_tasks";
+      LOG.log(Level.FINE, "commitTaskToDB: Executing: " + sql);
+      rs = statement.executeQuery(sql);
+
+      while (rs.next()) {
+        taskId = String.valueOf(rs.getInt("max_id"));
+      }
+
+      synchronized (taskId) {
+        taskId = String.valueOf(new Integer(taskId) + 1);
+      }
+
+      task.setTaskId(taskId);
+      sql = "INSERT INTO workflow_tasks (workflow_task_id, workflow_task_name, workflow_task_class) VALUES ("
+          + taskId
+          + ", '"
+          + task.getTaskName()
+          + "', '"
+          + task.getTaskInstanceClassName() + "')";
+
+      LOG.log(Level.FINE, "commitTaskToDB: Executing: " + sql);
+      statement.execute(sql);
+
+      if (workflow != null) {
+        // task to workflow map
+        sql = "INSERT INTO workflow_task_map (workflow_id, workflow_task_id, task_order) VALUES ("
+            + workflow.getId() + "," + taskId + ",1)";
+        LOG.log(Level.FINE, "commitTaskToDB: Executing: " + sql);
+        statement.execute(sql);
+      }
+
+      conn.commit();
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Exception adding task. Message: " + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE, "Unable to rollback task transaction. Message: "
+            + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return taskId;
+  }
+  
+  public List<WorkflowCondition> getConditions() throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    List<WorkflowCondition> conditions = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getConditionsSql = "SELECT workflow_conditions.* "
+          + "FROM workflow_conditions "
+          + "ORDER BY condition_id";
+
+      LOG.log(Level.FINE, "getConditions: Executing: "
+          + getConditionsSql);
+      rs = statement.executeQuery(getConditionsSql);
+      conditions = new Vector<WorkflowCondition>();
+
+      while (rs.next()) {
+        // get an instance of the class name
+        WorkflowCondition condition = DbStructFactory.getWorkflowCondition(rs,
+            true);
+        conditions.add(condition);
+      }
+
+      if (conditions.size() == 0) {
+        conditions = null;
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING, "Exception getting conditions. Message: "
+          + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(Level.SEVERE,
+            "Unable to rollback getConditions transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return conditions;
+  }  
+  
+  private List<WorkflowTask> getTasks() throws RepositoryException {
+    Connection conn = null;
+    Statement statement = null;
+    ResultSet rs = null;
+
+    List<WorkflowTask> tasks = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+
+      String getTasksSql = "SELECT workflow_tasks.*, workflow_task_map.task_order "
+          + "FROM workflow_tasks " + "ORDER BY workflow_task_map.task_order";
+
+      LOG.log(Level.FINE, "getTasks: Executing: " + getTasksSql);
+      rs = statement.executeQuery(getTasksSql);
+      tasks = new Vector<WorkflowTask>();
+
+      while (rs.next()) {
+        // get an instance of the class name
+
+        WorkflowTask task = DbStructFactory.getWorkflowTask(rs, true);
+
+        if (task != null) {
+          task.setConditions(getConditionsByTaskId(task.getTaskId()));
+          task.setTaskConfig(getConfigurationByTaskId(task.getTaskId()));
+          tasks.add(task);
+        }
+      }
+
+      if (tasks.size() == 0) {
+        tasks = null;
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Exception getting tasks. Message: " + e.getMessage());
+      try {
+        conn.rollback();
+      } catch (SQLException e2) {
+        LOG.log(
+            Level.SEVERE,
+            "Unable to rollback getTasks transaction. Message: "
+                + e2.getMessage());
+      }
+      throw new RepositoryException(e.getMessage());
+    } finally {
+
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException ignore) {
+        }
+
+        rs = null;
+      }
+
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+
+        } catch (SQLException ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return tasks;
+  }
+
+  private boolean hasTaskId(List<WorkflowTask> tasks, String id) {
+    if (tasks == null || (tasks != null && tasks.size() == 0))
+      return false;
+
+    for (WorkflowTask task : tasks) {
+      if (task.getTaskId().equals(id)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  private boolean hasConditionId(List<WorkflowCondition> conds, String id) {
+    if (conds == null || (conds != null && conds.size() == 0))
+      return false;
+
+    for (WorkflowCondition cond : conds) {
+      if (cond.getConditionId().equals(id)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  private void handleGlobalWorkflowConditions(Workflow workflow) throws RepositoryException {
+    if (workflow.getConditions() != null && workflow.getConditions().size() > 0) {
+      if (workflow.getTasks() == null
+          || (workflow.getTasks() != null && workflow.getTasks().size() == 0)) {
+        workflow.setTasks(new Vector<WorkflowTask>());
+      }
+
+      workflow.getTasks().add(
+          0,
+          getGlobalWorkflowConditionsTask(workflow,
+              workflow.getConditions()));
+    }
+  }
+
+  private WorkflowTask getGlobalWorkflowConditionsTask(Workflow workflow,
+      List<WorkflowCondition> conditions) throws RepositoryException {
+    WorkflowTask task = new WorkflowTask();
+    task.setConditions(conditions);
+    task.setTaskConfig(new WorkflowTaskConfiguration());
+    task.setTaskId(workflow.getId() + "-global-conditions-eval");
+    task.setTaskName(workflow.getName() + "-global-conditions-eval");
+    task.setTaskInstanceClassName(NoOpTask.class.getName());
+    task.setTaskId(this.commitTask(workflow, task));
+    return task;
+  }
+
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/DataSourceWorkflowRepositoryFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/DataSourceWorkflowRepositoryFactory.java
new file mode 100644
index 0000000..078a4ec
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/DataSourceWorkflowRepositoryFactory.java
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.repository;
+
+//APACHE imports
+import org.apache.commons.dbcp.ConnectionFactory;
+import org.apache.commons.dbcp.DriverManagerConnectionFactory;
+import org.apache.commons.dbcp.PoolableConnectionFactory;
+import org.apache.commons.dbcp.PoolingDataSource;
+import org.apache.commons.pool.impl.GenericObjectPool;
+
+//JDK imports
+import javax.sql.DataSource;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A {@link WorkflowRepositoryFactory} that creates
+ * {@DataSourceWorkflowRepository} instances.
+ * </p>
+ * 
+ */
+public class DataSourceWorkflowRepositoryFactory implements
+        WorkflowRepositoryFactory {
+
+    /* our data source */
+    private DataSource dataSource = null;
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     */
+    public DataSourceWorkflowRepositoryFactory() throws Exception {
+        String jdbcUrl = null, user = null, pass = null, driver = null;
+
+        jdbcUrl = System
+                .getProperty("org.apache.oodt.cas.workflow.repo.datasource.jdbc.url");
+        user = System
+                .getProperty("org.apache.oodt.cas.workflow.repo.datasource.jdbc.user");
+        pass = System
+                .getProperty("org.apache.oodt.cas.workflow.repo.datasource.jdbc.pass");
+        driver = System
+                .getProperty("org.apache.oodt.cas.workflow.repo.datasource.jdbc.driver");
+
+        try {
+            Class.forName(driver);
+        } catch (ClassNotFoundException e) {
+            throw new Exception("Cannot load driver: " + driver);
+        }
+
+        GenericObjectPool connectionPool = new GenericObjectPool(null);
+        ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
+                jdbcUrl, user, pass);
+        PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(
+                connectionFactory, connectionPool, null, null, false, true);
+
+        dataSource = new PoolingDataSource(connectionPool);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepositoryFactory#createRepository()
+     */
+    public WorkflowRepository createRepository() {
+        return new DataSourceWorkflowRepository(dataSource);
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/PackagedWorkflowRepository.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/PackagedWorkflowRepository.java
new file mode 100644
index 0000000..35acebe
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/PackagedWorkflowRepository.java
@@ -0,0 +1,768 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.repository;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.examples.BranchRedirector;
+import org.apache.oodt.cas.workflow.examples.NoOpTask;
+import org.apache.oodt.cas.workflow.structs.Graph;
+import org.apache.oodt.cas.workflow.structs.ParentChildWorkflow;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.exceptions.RepositoryException;
+import org.apache.oodt.cas.workflow.util.XmlStructFactory;
+import org.apache.oodt.commons.xml.XMLUtils;
+
+
+//JDK imports
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * 
+ * 
+ * Loads Workflow2 (WEngine) Style Workflow XML files.
+ * 
+ * @author mattmann
+ * @author bfoster
+ */
+public class PackagedWorkflowRepository implements WorkflowRepository {
+
+  private List<File> files;
+
+  private Map<String, ParentChildWorkflow> workflows;
+
+  private List<Graph> graphs;
+
+  private Map<String, WorkflowCondition> conditions;
+
+  private Map<String, WorkflowTask> tasks;
+
+  private Map<String, Metadata> globalConfGroups;
+
+  private Map<String, List<ParentChildWorkflow>> eventWorkflowMap;
+
+  private static final Logger LOG = Logger
+      .getLogger(PackagedWorkflowRepository.class.getName());
+
+  public PackagedWorkflowRepository(List<File> files)
+      throws InstantiationException {
+    this.files = files;
+    try {
+      this.init();
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw new InstantiationException(e.getMessage());
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflowByName
+   * (java.lang.String)
+   */
+  @Override
+  public Workflow getWorkflowByName(String workflowName)
+      throws RepositoryException {
+
+    for (Workflow w : this.workflows.values()) {
+      if (w.getName().equals(workflowName)) {
+        return w;
+      }
+    }
+
+    return null;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflowById
+   * (java.lang.String)
+   */
+  @Override
+  public Workflow getWorkflowById(String workflowId) throws RepositoryException {
+    return workflows.get(workflowId);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflows()
+   */
+  @Override
+  public List getWorkflows() throws RepositoryException {
+    List<Workflow> workflows = new Vector<Workflow>();
+    workflows.addAll(this.workflows.values());
+    return workflows;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#getTasksByWorkflowId
+   * (java.lang.String)
+   */
+  @Override
+  public List getTasksByWorkflowId(String workflowId)
+      throws RepositoryException {
+    Workflow w = this.getWorkflowById(workflowId);
+    return w.getTasks();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#
+   * getTasksByWorkflowName(java.lang.String)
+   */
+  @Override
+  public List getTasksByWorkflowName(String workflowName)
+      throws RepositoryException {
+    Workflow w = this.getWorkflowByName(workflowName);
+    if (w != null) {
+      return w.getTasks();
+    } else
+      return Collections.emptyList();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflowsForEvent
+   * (java.lang.String)
+   */
+  @Override
+  public List getWorkflowsForEvent(String eventName) throws RepositoryException {
+    List<ParentChildWorkflow> workflows = this.eventWorkflowMap.get(eventName);
+    if (workflows != null && workflows.size() > 0) {
+      return workflows;
+    } else
+      return Collections.emptyList();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#
+   * getConditionsByTaskName(java.lang.String)
+   */
+  @Override
+  public List getConditionsByTaskName(String taskName)
+      throws RepositoryException {
+
+    for (WorkflowTask task : this.tasks.values()) {
+      if (task.getTaskName().equals(taskName)) {
+        return task.getConditions();
+      }
+    }
+
+    return Collections.emptyList();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#
+   * getConditionsByTaskId(java.lang.String)
+   */
+  @Override
+  public List getConditionsByTaskId(String taskId) throws RepositoryException {
+    if (this.tasks.get(taskId) != null) {
+      return this.tasks.get(taskId).getConditions();
+    } else
+      return Collections.emptyList();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#
+   * getConfigurationByTaskId(java.lang.String)
+   */
+  @Override
+  public WorkflowTaskConfiguration getConfigurationByTaskId(String taskId)
+      throws RepositoryException {
+    return convertToTaskConfiguration(this.globalConfGroups.get(taskId));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflowTaskById
+   * (java.lang.String)
+   */
+  @Override
+  public WorkflowTask getWorkflowTaskById(String taskId)
+      throws RepositoryException {
+    return this.tasks.get(taskId);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#
+   * getWorkflowConditionById(java.lang.String)
+   */
+  @Override
+  public WorkflowCondition getWorkflowConditionById(String conditionId)
+      throws RepositoryException {
+    return this.conditions.get(conditionId);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#getRegisteredEvents
+   * ()
+   */
+  @Override
+  public List getRegisteredEvents() throws RepositoryException {
+    return Arrays.asList(this.eventWorkflowMap.keySet().toArray());
+  }
+  
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#addTask(org.apache.oodt.cas.workflow.structs.WorkflowTask)
+   */
+  @Override
+  public String addTask(WorkflowTask task) throws RepositoryException {
+    // check its conditions
+    if(task.getPreConditions() != null && task.getPreConditions().size() > 0){
+      for(WorkflowCondition cond: task.getPreConditions()){
+        if(!this.conditions.containsKey(cond.getConditionId())){
+          throw new RepositoryException("Reference in new task: ["+task.getTaskName()+"] to undefined pre condition ith id: ["+cond.getConditionId()+"]");            
+        }          
+      }
+      
+      for(WorkflowCondition cond: task.getPostConditions()){
+        if(!this.conditions.containsKey(cond.getConditionId())){
+          throw new RepositoryException("Reference in new task: ["+task.getTaskName()+"] to undefined post condition ith id: ["+cond.getConditionId()+"]");            
+        }              
+      }
+    }
+    
+      String taskId = task.getTaskId() != null ? 
+        task.getTaskId():UUID.randomUUID().toString();
+      this.tasks.put(taskId, task);
+      return taskId;
+  }  
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.repository.WorkflowRepository#addWorkflow(
+   * org.apache.oodt.cas.workflow.structs.Workflow)
+   */
+  @Override
+  public String addWorkflow(Workflow workflow) throws RepositoryException {
+    // first check to see that its tasks are all present
+    if (workflow.getTasks() == null
+        || (workflow.getTasks() != null && workflow.getTasks().size() == 0)) {
+      throw new RepositoryException("Attempt to define a new worklfow: ["
+          + workflow.getName() + "] with no tasks.");
+    }
+
+    for (WorkflowTask task : (List<WorkflowTask>) workflow.getTasks()) {
+      if (!this.tasks.containsKey(task.getTaskId())) {
+        throw new RepositoryException("Reference in new workflow: ["
+            + workflow.getName() + "] to undefined task with id: ["
+            + task.getTaskId() + "]");
+      }
+
+      // check its conditions
+      if (task.getConditions() != null && task.getConditions().size() > 0) {
+        for (WorkflowCondition cond : (List<WorkflowCondition>) task
+            .getConditions()) {
+          if (!this.conditions.containsKey(cond.getConditionId())) {
+            throw new RepositoryException("Reference in new workflow: ["
+                + workflow.getName() + "] to undefined condition ith id: ["
+                + cond.getConditionId() + "]");
+          }
+        }
+      }
+    }
+
+    // recast it as a parent/child workflow
+    String workflowId = workflow.getId();
+	if (workflowId == null
+			|| (workflowId != null && workflowId.equals(""))) {
+		// generate its ID
+		workflowId = UUID.randomUUID().toString();
+		workflow.setId(workflowId);
+	}
+      
+    ParentChildWorkflow pcw = null;
+    if(workflow instanceof ParentChildWorkflow) {
+        pcw = (ParentChildWorkflow) workflow;
+    }
+    else {
+        Graph graph = new Graph();
+        graph.setExecutionType("sequential");
+        pcw = new ParentChildWorkflow(graph);
+        pcw.setName(workflow.getName());
+        pcw.setTasks(workflow.getTasks());
+        pcw.setId(workflow.getId());
+    }
+    this.workflows.put(pcw.getId(), pcw);
+    this.eventWorkflowMap.put(workflowId, Collections.singletonList(pcw));
+
+    // generate its ID
+    return workflowId;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#
+   * getConditionsByWorkflowId(java.lang.String)
+   */
+  @Override
+  public List<WorkflowCondition> getConditionsByWorkflowId(String workflowId)
+      throws RepositoryException {
+    if (!this.workflows.containsKey(workflowId))
+      throw new RepositoryException(
+          "Attempt to obtain conditions for a workflow: " + "[" + workflowId
+              + "] that does not exist!");
+
+    return this.workflows.get(workflowId).getConditions();
+  }
+  
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getTaskById(java.lang.String)
+   */
+  @Override
+  public WorkflowTask getTaskById(String taskId) throws RepositoryException {
+    return this.tasks.get(taskId);
+  }  
+
+  private void init() throws RepositoryException {
+    this.workflows = new HashMap<String, ParentChildWorkflow>();
+    this.tasks = new HashMap<String, WorkflowTask>();
+    this.conditions = new HashMap<String, WorkflowCondition>();
+    this.eventWorkflowMap = new HashMap<String, List<ParentChildWorkflow>>();
+    this.globalConfGroups = new HashMap<String, Metadata>();
+    this.graphs = new Vector<Graph>();
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    DocumentBuilder parser = null;
+
+    try {
+      parser = factory.newDocumentBuilder();
+      List<Element> rootElements = new Vector<Element>();
+      for (File file : files)
+        rootElements.add(parser.parse(file).getDocumentElement());
+      for (Element root : rootElements) {
+        Metadata staticMetadata = new Metadata();
+        loadConfiguration(rootElements, root, staticMetadata);
+        loadTaskAndConditionDefinitions(rootElements, root, staticMetadata);
+        loadGraphs(rootElements, root, new Graph(), staticMetadata);
+        computeEvents();
+        computeWorkflowConditions();
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw new RepositoryException(e.getMessage());
+    }
+  }
+
+  private void computeWorkflowConditions() throws Exception {
+    if (this.workflows != null && this.workflows.values() != null
+        && this.workflows.values().size() > 0) {
+      for (ParentChildWorkflow w : this.workflows.values()) {
+        if (w.getConditions() != null && w.getConditions().size() > 0) {
+          w.getTasks().add(0,
+              getGlobalWorkflowConditionsTask(w.getName(), w.getId(), w.getConditions()));
+        }
+      }
+    }
+  }
+
+  private void computeEvents() throws Exception {
+    List<ParentChildWorkflow> workflows = new Vector<ParentChildWorkflow>();
+    for (ParentChildWorkflow w : this.workflows.values()) {
+      workflows.add(w);
+
+    }
+    for (ParentChildWorkflow workflow : workflows) {
+
+      // event for each workflow id
+      List<ParentChildWorkflow> wList = new Vector<ParentChildWorkflow>();
+      wList.add(workflow);
+      this.eventWorkflowMap.put(workflow.getId(), wList);
+
+      // clear its tasks, we are going to re-add them back
+      workflow.getTasks().clear();
+      List<Graph> children = workflow.getGraph().getChildren();
+      if (workflow.getGraph().getExecutionType().equals("sequential")) {
+        for (Graph child : children) {
+          if (child.getWorkflow() != null) {
+            workflow.getTasks().add(
+                generateRedirector(child.getWorkflow().getId()));
+          } else if (child.getTask() != null) {
+            workflow.getTasks().add(child.getTask());
+          }
+        }
+      } else if (workflow.getGraph().getExecutionType().equals("parallel")) {
+        // clear it as a workflow from the list
+        // to begin with
+        this.eventWorkflowMap.get(workflow.getId()).clear();
+        this.workflows.remove(workflow.getId());
+        for (Graph child : children) {
+          if (child.getWorkflow() != null) {
+            // add child workflow to the event kickoff for this id
+            this.eventWorkflowMap.get(workflow.getId())
+                .add(child.getWorkflow());
+          } else if (child.getTask() != null) {
+            // add a new dynamic workflow
+            // with just this task
+            ParentChildWorkflow w = getDynamicWorkflow(child.getTask());
+            this.eventWorkflowMap.get(workflow.getId()).add(w);
+          }
+        }
+      } else
+        throw new Exception("Unsupported execution type: ["
+            + workflow.getGraph().getExecutionType() + "]");
+    }
+  }
+
+  private void loadTaskAndConditionDefinitions(List<Element> rootElements,
+      Element rootElem, Metadata staticMetadata) throws Exception {
+
+    List<Element> conditionBlocks = this.getChildrenByTagName(rootElem,
+        "condition");
+    List<Element> taskBlocks = this.getChildrenByTagName(rootElem, "task");
+
+    if (conditionBlocks != null && conditionBlocks.size() > 0) {
+      LOG.log(Level.FINER, "Loading: [" + conditionBlocks.size()
+          + "] conditions from: ["
+          + rootElem.getOwnerDocument().getDocumentURI() + "]");
+
+      for (Element condElem : conditionBlocks) {
+        loadGraphs(rootElements, condElem, new Graph(), staticMetadata);
+      }
+
+    }
+
+    if (taskBlocks != null && taskBlocks.size() > 0) {
+      LOG.log(Level.FINER, "Loading: [" + taskBlocks.size() + "] tasks from: ["
+          + rootElem.getOwnerDocument().getDocumentURI() + "]");
+      for (Element taskElem : taskBlocks) {
+        loadGraphs(rootElements, taskElem, new Graph(), staticMetadata);
+      }
+    }
+  }
+
+  private void loadGraphs(List<Element> rootElements, Element graphElem,
+      Graph parent, Metadata staticMetadata) throws Exception {
+
+    LOG.log(Level.FINEST, "Visiting node: [" + graphElem.getNodeName() + "]");
+    loadConfiguration(rootElements, graphElem, staticMetadata);
+    Graph graph = !graphElem.getNodeName().equals("cas:workflows") ? new Graph(
+        graphElem, staticMetadata) : new Graph();
+    parent.getChildren().add(graph);
+    graph.setParent(parent);
+    if (!graphElem.getNodeName().equals("cas:workflows")) {
+      expandWorkflowTasksAndConditions(graph, staticMetadata);
+    }
+
+    for (String processorType : Graph.processorIds) {
+      LOG.log(Level.FINE, "Scanning for: [" + processorType + "] nodes");
+      List<Element> procTypeBlocks = this.getChildrenByTagName(graphElem,
+          processorType);
+      if (procTypeBlocks != null && procTypeBlocks.size() > 0) {
+        LOG.log(Level.FINE, "Found: [" + procTypeBlocks.size() + "] ["
+            + processorType + "] processor types");
+        for (int i = 0; i < procTypeBlocks.size(); i++) {
+          loadGraphs(rootElements, procTypeBlocks.get(i), graph, staticMetadata);
+        }
+      } else {
+        if (processorType.equals("condition")) {
+          Element conditionsElem = XMLUtils.getFirstElement("conditions",
+              graphElem);
+          if (conditionsElem != null) {
+            List<Element> procTypeBlockNodes = this.getChildrenByTagName(
+                conditionsElem, "condition");
+            if (procTypeBlockNodes != null && procTypeBlockNodes.size() > 0) {
+              LOG.log(Level.FINE, "Found: [" + procTypeBlockNodes.size()
+                  + "] linked condition definitions");
+              for (int i = 0; i < procTypeBlockNodes.size(); i++) {
+                loadGraphs(rootElements, procTypeBlockNodes.get(i), graph,
+                    staticMetadata);
+              }
+            }
+          }
+        }
+      }
+    }
+
+    if (graphElem.getNodeName().equals("cas:workflows"))
+      return;
+  }
+
+  private void loadConfiguration(List<Element> rootElements, Node workflowNode,
+      Metadata staticMetadata) throws Exception {
+    NodeList children = workflowNode.getChildNodes();
+    for (int i = 0; i < children.getLength(); i++) {
+      Node curChild = children.item(i);
+
+      if (curChild.getNodeName().equals("configuration")) {
+        Metadata curMetadata = new Metadata();
+        if (!((Element) curChild).getAttribute("extends").equals(""))
+          for (String extension : ((Element) curChild).getAttribute("extends")
+              .split(","))
+            curMetadata
+                .replaceMetadata(globalConfGroups.containsKey(extension) ? globalConfGroups
+                    .get(extension) : this.loadConfGroup(rootElements,
+                    extension, globalConfGroups));
+        curMetadata.replaceMetadata(XmlStructFactory
+            .getConfigurationAsMetadata(curChild));
+        NamedNodeMap attrMap = curChild.getAttributes();
+        String configName = null;
+        for (int j = 0; j < attrMap.getLength(); j++) {
+          Attr attr = (Attr) attrMap.item(j);
+          if (attr.getName().equals("name")) {
+            configName = attr.getValue();
+          }
+        }
+
+        if (configName == null || (configName != null && configName.equals(""))) {
+          NamedNodeMap workflowNodeAttrs = workflowNode.getAttributes();
+          for (int j = 0; j < workflowNodeAttrs.getLength(); j++) {
+            Attr attr = (Attr) workflowNodeAttrs.item(j);
+            if (attr.getName().equals("id")) {
+              configName = attr.getValue();
+            }
+          }
+        }
+
+        this.globalConfGroups.put(configName, curMetadata);
+        staticMetadata.replaceMetadata(curMetadata);
+      }
+    }
+  }
+
+  private Metadata loadConfGroup(List<Element> rootElements, String group,
+      Map<String, Metadata> globalConfGroups) throws Exception {
+    for (final Element rootElement : rootElements) {
+      NodeList nodes = rootElement.getElementsByTagName("configuration");
+      for (int i = 0; i < nodes.getLength(); i++) {
+        Node node = nodes.item(i);
+        String name = ((Element) node).getAttribute("name");
+        if (name.equals(group))
+          return XmlStructFactory.getConfigurationAsMetadata(node);
+      }
+    }
+    throw new Exception("Configuration group '" + group + "' not defined!");
+  }
+
+  private void expandWorkflowTasksAndConditions(Graph graph,
+      Metadata staticMetadata) throws Exception {
+    if (graph.getExecutionType().equals("workflow")
+        || graph.getExecutionType().equals("sequential")
+        || graph.getExecutionType().equals("parallel")) {
+      ParentChildWorkflow workflow = new ParentChildWorkflow(graph);
+      workflow.setId(graph.getModelId());
+      workflow.setName(graph.getModelName());
+      graph.setWorkflow(workflow);
+      if (graph.getParent() == null
+          || (graph.getParent() != null && graph.getParent().getWorkflow() == null)) {
+        LOG.log(Level.FINEST, "Workflow: [" + graph.getModelId()
+            + "] has no parent: it's a top-level workflow");
+      }
+
+      if (workflow.getName() == null
+          || (workflow.getName() != null && workflow.getName().equals(""))) {
+        workflow.setName(graph.getExecutionType() + "-" + workflow.getId());
+      }
+      this.workflows.put(graph.getModelId(), workflow);
+    } else if (graph.getExecutionType().equals("condition")) {
+      WorkflowCondition cond = null;
+
+      if (graph.getModelIdRef() != null && !graph.getModelIdRef().equals("")) {
+        cond = this.conditions.get(graph.getModelIdRef());
+      } else {
+        cond = new WorkflowCondition();
+        cond.setConditionId(graph.getModelId());
+        cond.setConditionName(graph.getModelName());
+        cond.setConditionInstanceClassName(graph.getClazz());
+        cond.setTimeoutSeconds(graph.getTimeout());
+        cond.setOptional(graph.isOptional());
+        cond.setCondConfig(convertToConditionConfiguration(staticMetadata));
+
+        if (cond.getConditionName() == null
+            || (cond.getConditionName() != null && cond.getConditionName()
+                .equals(""))) {
+          cond.setConditionName(cond.getConditionId());
+        }
+        this.conditions.put(graph.getModelId(), cond);
+
+      }
+
+      graph.setCond(cond);
+      if (graph.getParent() != null) {
+        if (graph.getParent().getWorkflow() != null) {
+          LOG.log(Level.FINEST, "Adding condition: [" + cond.getConditionName()
+              + "] to parent workflow: ["
+              + graph.getParent().getWorkflow().getName() + "]");
+          graph.getParent().getWorkflow().getConditions().add(cond);
+        } else if (graph.getParent().getTask() != null) {
+          graph.getParent().getTask().getConditions().add(cond);
+        } else {
+          LOG.log(Level.FINEST, "Condition: [" + graph.getModelId()
+              + "] has not parent: it's a condition definition");
+        }
+      } else {
+        LOG.log(Level.FINEST, "Condition: [" + graph.getModelId()
+            + "]: parent is null");
+      }
+      // if parent doesn't have task or workflow set, then its parent
+      // is null and it's a condition definition, just add it
+
+    } else if (graph.getExecutionType().equals("task")) {
+      WorkflowTask task = null;
+      if (graph.getModelIdRef() != null && !graph.getModelIdRef().equals("")) {
+        LOG.log(Level.FINER, "Model ID-Ref to: [" + graph.getModelIdRef() + "]");
+        task = this.tasks.get(graph.getModelIdRef());
+      } else {
+        task = new WorkflowTask();
+        task.setTaskId(graph.getModelId());
+        task.setTaskName(graph.getModelName());
+        task.setTaskConfig(convertToTaskConfiguration(staticMetadata));
+        task.setTaskInstanceClassName(graph.getClazz());
+
+        if (task.getTaskName() == null
+            || (task.getTaskName() != null && task.getTaskName().equals(""))) {
+          task.setTaskName(task.getTaskId());
+        }
+        this.tasks.put(graph.getModelId(), task);
+      }
+
+      graph.setTask(task);
+      if (graph.getParent() != null) {
+        if (graph.getParent().getWorkflow() != null) {
+          graph.getParent().getWorkflow().getTasks().add(task);
+        } else {
+          LOG.log(Level.FINEST, "Task: [" + graph.getModelId()
+              + "] has no parent: it's a task definition");
+        }
+      } else {
+        LOG.log(Level.FINEST, "Task: [" + graph.getModelId()
+            + "]: parent is null");
+      }
+    }
+
+  }
+
+  private ParentChildWorkflow getDynamicWorkflow(WorkflowTask task) {
+    Graph graph = new Graph();
+    graph.setExecutionType("sequential");
+    ParentChildWorkflow workflow = new ParentChildWorkflow(graph);
+    workflow.setId("parallel-" + UUID.randomUUID().toString());
+    workflow.setName("Parallel Single Task " + task.getTaskName());
+    workflow.getTasks().add(task);
+    this.workflows.put(workflow.getId(), workflow);
+    return workflow;
+  }
+
+  private WorkflowTask generateRedirector(String eventName) {
+    WorkflowTask task = new WorkflowTask();
+    WorkflowTaskConfiguration config = new WorkflowTaskConfiguration();
+    config.addConfigProperty("eventName", eventName);
+    task.setTaskId("redirector-" + UUID.randomUUID().toString());
+    task.setTaskName("Redirector Task");
+    task.setTaskInstanceClassName(BranchRedirector.class.getName());
+    this.tasks.put(task.getTaskId(), task);
+    return task;
+  }
+
+  private WorkflowTaskConfiguration convertToTaskConfiguration(Metadata met) {
+    WorkflowTaskConfiguration config = new WorkflowTaskConfiguration();
+    for (String key : met.getAllKeys()) {
+      config.addConfigProperty(key, met.getMetadata(key));
+    }
+    return config;
+  }
+
+  private WorkflowConditionConfiguration convertToConditionConfiguration(
+      Metadata met) {
+    WorkflowConditionConfiguration config = new WorkflowConditionConfiguration();
+    for (String key : met.getAllKeys()) {
+      config.addConfigProperty(key, met.getMetadata(key));
+    }
+    return config;
+  }
+
+  /**
+   * Taken from: http://stackoverflow.com/questions/1241525/java-element-
+   * getelementsbytagname-restrict-to-top-level
+   */
+  private List<Element> getChildrenByTagName(Element parent, String name) {
+    List<Element> nodeList = new Vector<Element>();
+    for (Node child = parent.getFirstChild(); child != null; child = child
+        .getNextSibling()) {
+      if (child.getNodeType() == Node.ELEMENT_NODE
+          && name.equals(child.getNodeName())) {
+        nodeList.add((Element) child);
+      }
+    }
+
+    return nodeList;
+  }
+
+  private WorkflowTask getGlobalWorkflowConditionsTask(String workflowName, String workflowId,
+      List<WorkflowCondition> conditions) {
+    WorkflowTask task = new WorkflowTask();
+    task.setConditions(conditions);
+    task.setTaskConfig(new WorkflowTaskConfiguration());
+    task.setTaskId(workflowId + "-global-conditions-eval");
+    task.setTaskName(workflowName + "-global-conditions-eval");
+    task.setTaskInstanceClassName(NoOpTask.class.getName());
+    this.tasks.put(task.getTaskId(), task);
+    return task;
+  }
+  
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/PackagedWorkflowRepositoryFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/PackagedWorkflowRepositoryFactory.java
new file mode 100644
index 0000000..e603170
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/PackagedWorkflowRepositoryFactory.java
@@ -0,0 +1,75 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.repository;
+
+//JDK imports
+import java.io.File;
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * 
+ * Constructs {@link PackagedWorkflowRepository}s.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class PackagedWorkflowRepositoryFactory implements
+    WorkflowRepositoryFactory {
+
+  private String wDirPath;
+
+  private static final Logger LOG = Logger
+      .getLogger(PackagedWorkflowRepositoryFactory.class.getName());
+
+  public PackagedWorkflowRepositoryFactory() throws InstantiationException {
+    this.wDirPath = System
+        .getProperty("org.apache.oodt.cas.workflow.wengine.packagedRepo.dir.path");
+    if (this.wDirPath == null
+        || (this.wDirPath != null && !new File(wDirPath).isDirectory())) {
+      throw new InstantiationException("Must specify valid directory path "
+          + "containing wengine-style workflow xml files! path specified: ["
+          + this.wDirPath + "]");
+    }
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepositoryFactory#
+   * createRepository()
+   */
+  @Override
+  public WorkflowRepository createRepository() {
+    try {
+      return new PackagedWorkflowRepository(
+          Arrays.asList(new File(this.wDirPath).listFiles()));
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(
+          Level.SEVERE,
+          "Unable to create packaged workflow repository! Reason: "
+              + e.getMessage());
+      return null;
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/WorkflowRepository.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/WorkflowRepository.java
new file mode 100644
index 0000000..3f5585b
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/WorkflowRepository.java
@@ -0,0 +1,270 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.repository;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.exceptions.RepositoryException;
+
+//JDK imports
+import java.util.List;
+
+/**
+ * 
+ * A repository interface for obtaining {@link Workflow}s, and managing the
+ * information about their {@link WorkflowTask}s.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface WorkflowRepository {
+
+  /**
+   * <p>
+   * Returns a {@link Workflow} with the given <code>workflowName</code>.
+   * </p>
+   * 
+   * @param workflowName
+   *          The name of the {@link Workflow} to obtain.
+   * @return A {@link Workflow} with the specified name.
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public Workflow getWorkflowByName(String workflowName)
+      throws RepositoryException;
+
+  /**
+   * <p>
+   * Returns a {@link Workflow} with the given <code>workflowId</code>.
+   * </p>
+   * 
+   * @param workflowId
+   *          The ID of the {@link Workflow} to obtain.
+   * @return A {@link Workflow} with the given ID.
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public Workflow getWorkflowById(String workflowId) throws RepositoryException;
+
+  /**
+   * <p>
+   * Gets all {@link Workflow}s from the repository.
+   * </p>
+   * 
+   * @return A {@link List} of all {@link Workflow}s in the repository.
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public List getWorkflows() throws RepositoryException;
+
+  /**
+   * <p>
+   * Returns a {@link List} of {@link WorkflowTask}s associated with the
+   * specified {@link Workflow} identified by its <code>workflowId</code>.
+   * </p>
+   * 
+   * @param workflowId
+   *          The ID of the {@link Workflow} to obtain the {@link List} of
+   *          {@link WorkflowTask}s for.
+   * @return A {@link List} of {@link WorkflowTask}s associated with the
+   *         specified Workflow.
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public List getTasksByWorkflowId(String workflowId)
+      throws RepositoryException;
+
+  /**
+   * <p>
+   * Returns a {@link List} of {@link WorkflowTask}s associated with the
+   * specified {@link Workflow} identified by its <code>workflowName</code>.
+   * </p>
+   * 
+   * @param workflowName
+   *          The Name of the {@link Workflow} to obtain the {@link List} of
+   *          {@link WorkflowTask}s for.
+   * @return A {@link List} of {@link WorkflowTask}s associated with the
+   *         specified Workflow.
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public List getTasksByWorkflowName(String workflowName)
+      throws RepositoryException;
+
+  /**
+   * <p>
+   * Returns a {@link List} of {@link Workflow}s associated with the specified
+   * <code>eventName</code>.
+   * </p>
+   * 
+   * @param eventName
+   *          The name of the event to search for workflows for. </p>
+   * @return A {@link List} of {@link Workflow}s associated with the specified
+   *         event.
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public List getWorkflowsForEvent(String eventName) throws RepositoryException;
+
+  /**
+   * <p>
+   * Returns an ordered {@link List} of {@link WorkflowCondition}s associated
+   * with the given <code>taskName</code>.
+   * </p>
+   * 
+   * @param taskName
+   *          The taskName to obtain the conditions for.
+   * @return Returns a {@link List} of {@link WorkflowCondition}s associated
+   *         with the given <code>taskName</code>
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public List getConditionsByTaskName(String taskName)
+      throws RepositoryException;
+
+  /**
+   * <p>
+   * Returns an ordered {@link List} of {@link WorkflowCondition}s associated
+   * with the given <code>taskId</code>.
+   * </p>
+   * 
+   * @param taskId
+   *          The ID of the task to obtain the conditions for.
+   * @return Returns a {@link List} of {@link WorkflowCondition}s associated
+   *         with the given <code>taskId</code>
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public List getConditionsByTaskId(String taskId) throws RepositoryException;
+
+  /**
+   * <p>
+   * Gets the {@link WorkflowTaskConfiguration} metadata for the
+   * {@link WorkflowTask} with the given <code>taskId</code>.
+   * </p>
+   * 
+   * @param taskId
+   *          The ID of the {@link WorkflowTask} to get the
+   *          {@link WorkflowTaskConfiguration} metadata for.
+   * @return The {@link WorkflowTaskConfiguration} metadata for the
+   *         {@link WorkflowTask} with the given <code>taskId</code>.
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public WorkflowTaskConfiguration getConfigurationByTaskId(String taskId)
+      throws RepositoryException;
+
+  /**
+   * <p>
+   * Returns the {@link WorkflowTask} with the given <code>taskId</code>.
+   * </p>
+   * 
+   * @param taskId
+   *          The ID of the WorkflowTask to return.
+   * @return the {@link WorkflowTask} with the given <code>taskId</code>.
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public WorkflowTask getWorkflowTaskById(String taskId)
+      throws RepositoryException;
+
+  /**
+   * <p>
+   * Returns the {@link WorkflowCondition} with the given
+   * <code>conditionId</code>.
+   * </p>
+   * 
+   * @param conditionId
+   *          The ID of the WorkflowCondition to return.
+   * @return the {@link WorkflowCondition} with the given
+   *         <code>conditionId</code>.
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public WorkflowCondition getWorkflowConditionById(String conditionId)
+      throws RepositoryException;
+
+  /**
+   * <p>
+   * Gets a {@link List} of <code>Event</code>s that are registered in the
+   * Workflow Manager as having valid {@link Workflow}s mapped to their names.
+   * </p>
+   * 
+   * @return a {@link List} of <code>Event</code>s that are registered in the
+   *         Workflow Manager as having valid {@link Workflow}s mapped to their
+   *         names.
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public List getRegisteredEvents() throws RepositoryException;
+
+  /**
+   * Adds the specified new {@link Workflow} to this Repository.
+   * 
+   * @param workflow
+   *          The {@link Workflow} to add.
+   * @return The identifier of the new {@link Workflow} as defined by this
+   *         repository.
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public String addWorkflow(Workflow workflow) throws RepositoryException;
+
+  /**
+   * 
+   * Gets the associated {@link WorkflowCondition}s for this {@link Workflow}
+   * specified by its <code>workflowId</code>.
+   * 
+   * @param workflowId
+   *          The Identifier of the {@link Workflow} to get the
+   *          {@link WorkflowCondition}s for.
+   * 
+   * @return A {@link List} of {@link WorkflowCondition}s for this
+   *         {@link Workflow}.
+   * @throws RepositoryException
+   *           If any error occurs.
+   */
+  public List<WorkflowCondition> getConditionsByWorkflowId(String workflowId)
+      throws RepositoryException;
+  
+  
+  /**
+   * Adds the provided new {@link WorkflowTask} to the model repository.
+   * 
+   * @param task The new {@link WorkflowTask} to add.
+   * @return The identifier of the new {@link WorkflowTask}. Calling this
+   * function and providing a task with its identifier already set will cause
+   * this function to return that same identifier back.
+   * @throws RepositoryException If any error occurs.
+   */
+  public String addTask(WorkflowTask task) throws RepositoryException;
+  
+  /**
+   * Returns the {@link WorkflowTask} identified by the given taskId.
+   * 
+   * @param taskId The identifier for the {@link WorkflowTask} to return.
+   * @return The {@link WorkflowTask} identified by the given taskId.
+   * @throws RepositoryException If any error occurs.
+   */
+  public WorkflowTask getTaskById(String taskId) throws RepositoryException;
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/WorkflowRepositoryFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/WorkflowRepositoryFactory.java
new file mode 100644
index 0000000..d711b4d
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/WorkflowRepositoryFactory.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.repository;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory class for creating implementations of {@link WorkflowRepository}s.
+ * </p>
+ * 
+ */
+public interface WorkflowRepositoryFactory {
+
+    /**
+     * @return A new implementation of the {@link WorkflowRepository} interface.
+     */
+    public WorkflowRepository createRepository();
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/XMLWorkflowRepository.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/XMLWorkflowRepository.java
new file mode 100644
index 0000000..812f2f8
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/XMLWorkflowRepository.java
@@ -0,0 +1,714 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.repository;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.util.XmlStructFactory;
+import org.apache.oodt.cas.workflow.examples.NoOpTask;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.structs.exceptions.RepositoryException;
+import org.apache.oodt.cas.workflow.structs.exceptions.WorkflowTaskInstanceException;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.Vector;
+import java.util.Iterator;
+import java.util.Arrays;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.FileFilter;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+
+/**
+ * @author mattmann
+ * @version $Revsion$
+ * 
+ * <p>
+ * A {@link WorkflowRepository} that loads events, {@link Workflow}s,
+ * {@link WorkflowTask}s and {@link WorkflowCondition}s from specialized xml
+ * files. The WorkflowRepository is given an initial set of seed directory uris,
+ * where it looks for the following files:
+ * 
+ * <ul>
+ * <li>conditions.xml - defines workflow pre conditions</li>
+ * <li>tasks.xml - defines workflow tasks</li>
+ * <li>*.workflow.xml - individual workflow xml files specifying a single
+ * workflow</li>
+ * <li>events.xml - maps available workflows to event names</li>
+ * </ul>
+ * 
+ * All of the WorkflowTasks, WorkflowConditions and Workflows themselves are
+ * cached in memory by their ids (which are typically URNs).
+ * </p>
+ */
+public class XMLWorkflowRepository implements WorkflowRepository {
+
+    /* the list of directory URIs where workflow xml files live */
+    private List workflowHomeUris = null;
+
+    /* our log stream */
+    private static Logger LOG = Logger.getLogger(XMLWorkflowRepository.class
+            .getName());
+
+    /* our task map */
+    private static HashMap taskMap = new HashMap();
+
+    /* our condition map */
+    private static HashMap conditionMap = new HashMap();
+
+    /* our workflow map */
+    private static HashMap workflowMap = new HashMap();
+
+    /* our event map */
+    private static HashMap eventMap = new HashMap();
+
+    private static FileFilter workflowXmlFilter = new FileFilter() {
+        public boolean accept(File pathname) {
+            return pathname.isFile()
+                    && pathname.toString().endsWith(".workflow.xml");
+        }
+    };
+
+    /**
+     * <p>
+     * Constructs a new XMLWorkflowRepository with the given parameter
+     * <code>uris</code>.
+     * </p>
+     * 
+     * @param uris
+     *            URIs pointing to directories that follow the XML workflow
+     *            repository convention documented at the top of this class.
+     */
+    public XMLWorkflowRepository(List uris) {
+        workflowHomeUris = uris;
+
+        // load the tasks and conditions
+        loadConditions(workflowHomeUris);
+        loadTasks(workflowHomeUris);
+        loadWorkflows(workflowHomeUris);
+        loadEvents(workflowHomeUris);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getRegisteredEvents()
+     */
+    public List getRegisteredEvents() throws RepositoryException {
+        return Arrays.asList(eventMap.keySet().toArray());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflowTaskById(java.lang.String)
+     */
+    public WorkflowTask getWorkflowTaskById(String taskId)
+            throws RepositoryException {
+        return (WorkflowTask) taskMap.get(taskId);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflowConditionById(java.lang.String)
+     */
+    public WorkflowCondition getWorkflowConditionById(String conditionId)
+            throws RepositoryException {
+        return (WorkflowCondition) conditionMap.get(conditionId);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflowByName(java.lang.String)
+     */
+    public Workflow getWorkflowByName(String workflowName)
+            throws RepositoryException {
+        for (Iterator i = workflowMap.keySet().iterator(); i.hasNext();) {
+            String workflowId = (String) i.next();
+            Workflow w = (Workflow) workflowMap.get(workflowId);
+
+            if (w.getName().equals(workflowName)) {
+                return w;
+            }
+        }
+
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflowById(java.lang.String)
+     */
+    public Workflow getWorkflowById(String workflowId)
+            throws RepositoryException {
+        return (Workflow) workflowMap.get(workflowId);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflows()
+     */
+    public List getWorkflows() throws RepositoryException {
+        return Arrays.asList(workflowMap.values().toArray());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getTasksByWorkflowId(java.lang.String)
+     */
+    public List getTasksByWorkflowId(String workflowId)
+            throws RepositoryException {
+        Workflow w = getWorkflowById(workflowId);
+        return w.getTasks();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getTasksByWorkflowName(java.lang.String)
+     */
+    public List getTasksByWorkflowName(String workflowName)
+            throws RepositoryException {
+        Workflow w = getWorkflowByName(workflowName);
+        return w.getTasks();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getWorkflowsForEvent(java.lang.String)
+     */
+    public List getWorkflowsForEvent(String eventName)
+            throws RepositoryException {
+        return (List) eventMap.get(eventName);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getConditionsByTaskName(java.lang.String)
+     */
+    public List getConditionsByTaskName(String taskName)
+            throws RepositoryException {
+        for (Iterator i = taskMap.values().iterator(); i.hasNext();) {
+            WorkflowTask t = (WorkflowTask) i.next();
+            if (t.getTaskName().equals(taskName)) {
+                return t.getConditions();
+            }
+        }
+
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getConditionsByTaskId(java.lang.String)
+     */
+    public List getConditionsByTaskId(String taskId) throws RepositoryException {
+        WorkflowTask t = (WorkflowTask) taskMap.get(taskId);
+        if (t != null) {
+            return t.getConditions();
+        } else
+            return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getConfigurationByTaskId(java.lang.String)
+     */
+    public WorkflowTaskConfiguration getConfigurationByTaskId(String taskId)
+            throws RepositoryException {
+        WorkflowTask task = (WorkflowTask) taskMap.get(taskId);
+        return task.getTaskConfig();
+    }
+    
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#addTask(org.apache.oodt.cas.workflow.structs.WorkflowTask)
+     */
+    @Override
+    public String addTask(WorkflowTask task) throws RepositoryException {
+      // check its conditions
+      if(task.getPreConditions() != null && task.getPreConditions().size() > 0){
+        for(WorkflowCondition cond: task.getPreConditions()){
+          if(!this.conditionMap.containsKey(cond.getConditionId())){
+            throw new RepositoryException("Reference in new task: ["+task.getTaskName()+"] to undefined pre condition ith id: ["+cond.getConditionId()+"]");            
+          }          
+        }
+        
+        for(WorkflowCondition cond: task.getPostConditions()){
+          if(!this.conditionMap.containsKey(cond.getConditionId())){
+            throw new RepositoryException("Reference in new task: ["+task.getTaskName()+"] to undefined post condition ith id: ["+cond.getConditionId()+"]");            
+          }              
+        }
+      }
+      
+        String taskId = task.getTaskId() != null ? 
+             task.getTaskId():UUID.randomUUID().toString();
+        this.taskMap.put(taskId, task);
+        return taskId;
+    }
+    
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#addWorkflow(org.apache.oodt.cas.workflow.structs.Workflow)
+     */
+    @Override
+    public String addWorkflow(Workflow workflow) throws RepositoryException {
+       // first check to see that its tasks are all present
+      if(workflow.getTasks() == null || (workflow.getTasks() != null && workflow.getTasks().size() == 0)){
+        throw new RepositoryException("Attempt to define a new worklfow: ["+workflow.getName()+"] with no tasks.");
+      }
+      
+      for(WorkflowTask task: (List<WorkflowTask>)workflow.getTasks()){
+        if(!this.taskMap.containsKey(task.getTaskId())){
+          throw new RepositoryException("Reference in new workflow: ["+workflow.getName()+"] to undefined task with id: ["+task.getTaskId()+"]");
+        }
+        
+        // check its conditions
+        if(task.getConditions() != null && task.getConditions().size() > 0){
+          for(WorkflowCondition cond: (List<WorkflowCondition>)task.getConditions()){
+            if(!this.conditionMap.containsKey(cond.getConditionId())){
+              throw new RepositoryException("Reference in new workflow: ["+workflow.getName()+"] to undefined condition ith id: ["+cond.getConditionId()+"]");
+            }
+          }
+        }
+      }
+      
+        String workflowId = workflow.getId();
+		if (workflowId == null
+				|| (workflowId != null && workflowId.equals(""))) {
+			// generate its ID
+			workflowId = UUID.randomUUID().toString();
+			workflow.setId(workflowId);
+		}
+		this.workflowMap.put(workflowId, workflow);
+		this.eventMap.put(workflowId, Collections.singletonList(workflow));
+		return workflowId;
+		
+    }    
+    
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getConditionsByWorkflowId(java.lang.String)
+     */
+    @Override
+    public List<WorkflowCondition> getConditionsByWorkflowId(String workflowId)
+        throws RepositoryException {
+      if(!this.workflowMap.containsKey(workflowId)) throw new 
+         RepositoryException("Attempt to obtain conditions for a workflow: " +
+         		"["+workflowId+"] that does not exist!");
+      
+      return ((Workflow)this.workflowMap.get(workflowId)).getConditions();
+    }    
+    
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getTaskById(java.lang.String)
+     */
+    @Override
+    public WorkflowTask getTaskById(String taskId) throws RepositoryException {
+      return (WorkflowTask)this.taskMap.get(taskId);
+    }    
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) throws RepositoryException {
+        String usage = "XmlWorkflowRepository <uri 1>...<uri n>\n";
+        List uris = null;
+
+        if (args.length == 0) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        uris = new Vector(args.length);
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i] != null) {
+                uris.add(args[i]);
+            }
+        }
+
+        XMLWorkflowRepository repo = new XMLWorkflowRepository(uris);
+
+        List workflows = repo.getWorkflows();
+
+        if (workflows != null) {
+            for (Iterator i = workflows.iterator(); i.hasNext();) {
+                Workflow w = (Workflow) i.next();
+                System.out.println("Workflow: [id=" + w.getId() + ", name="
+                        + w.getName() + "]");
+
+                System.out.println("Tasks: ");
+
+                for (Iterator j = w.getTasks().iterator(); j.hasNext();) {
+                    WorkflowTask task = (WorkflowTask) j.next();
+
+                    System.out.println("Task: [class="
+                            + task.getTaskInstanceClassName() + ", id="
+                            + task.getTaskId() + ", name=" + task.getTaskName()
+                            + ", order=" + task.getOrder() + ",reqMetFields="
+                            + task.getRequiredMetFields() + "]");
+                    System.out.println("Configuration: ");
+
+                    for (Iterator k = task.getTaskConfig().getProperties()
+                            .keySet().iterator(); k.hasNext();) {
+                        String key = (String) k.next();
+                        String value = (String) task.getTaskConfig()
+                                .getProperties().get(key);
+
+                        System.out.println("[name=" + key + ", value=" + value
+                                + "]");
+                    }
+
+                    System.out.println("Conditions: ");
+
+                    for (Iterator k = task.getConditions().iterator(); k
+                            .hasNext();) {
+                        WorkflowCondition condition = (WorkflowCondition) k
+                                .next();
+                        System.out.println("Condition: ["
+                                + condition.getClass().getName() + ", id="
+                                + condition.getConditionId() + ", name="
+                                + condition.getConditionName() + ", timeout="
+                                + condition.getTimeoutSeconds()+ ", optional="
+                                + condition.isOptional()+", order="
+                                + condition.getOrder() + "]");
+                        
+                        System.out.println("Configuration: ");
+                        for (String cKeyName : (Set<String>) (Set<?>) condition
+                          .getCondConfig().getProperties().keySet()) {
+                         System.out.println("[name=" + cKeyName + ", value="
+                         + condition.getCondConfig().getProperty(cKeyName) + "]");
+                        }
+                    }
+
+                }
+
+            }
+        } else {
+            System.out.println("No workflows defined!");
+        }
+
+    }
+
+    private void loadTasks(List dirUris) {
+        if (dirUris != null && dirUris.size() > 0) {
+            for (Iterator i = dirUris.iterator(); i.hasNext();) {
+                String dirUri = (String) i.next();
+
+                try {
+                    File workflowDir = new File(new URI(dirUri));
+                    if (workflowDir.isDirectory()) {
+                        String workflowDirStr = workflowDir.getAbsolutePath();
+
+                        if (!workflowDirStr.endsWith("/")) {
+                            workflowDirStr += "/";
+                        }
+
+                        Document taskRoot = getDocumentRoot(workflowDirStr
+                                + "tasks.xml");
+
+                        Element taskElement = taskRoot.getDocumentElement();
+
+                        NodeList taskElemList = taskElement
+                                .getElementsByTagName("task");
+
+                        if (taskElemList != null
+                                && taskElemList.getLength() > 0) {
+                            for (int j = 0; j < taskElemList.getLength(); j++) {
+                                Element taskElem = (Element) taskElemList
+                                        .item(j);
+                                WorkflowTask task = XmlStructFactory
+                                        .getWorkflowTask(taskElem, conditionMap);
+                                if (task != null) {
+                                    taskMap.put(task.getTaskId(), task);
+                                }
+                            }
+
+                        }
+                    }
+                } catch (URISyntaxException e) {
+                    LOG
+                            .log(
+                                    Level.WARNING,
+                                    "DirUri: "
+                                            + dirUri
+                                            + " is not a directory: skipping task loading for it.");
+                }
+
+            }
+        }
+    }
+
+    private void loadConditions(List dirUris) {
+        if (dirUris != null && dirUris.size() > 0) {
+            for (Iterator i = dirUris.iterator(); i.hasNext();) {
+                String dirUri = (String) i.next();
+
+                try {
+                    File workflowDir = new File(new URI(dirUri));
+                    if (workflowDir.isDirectory()) {
+                        String workflowDirStr = workflowDir.getAbsolutePath();
+
+                        if (!workflowDirStr.endsWith("/")) {
+                            workflowDirStr += "/";
+                        }
+
+                        Document conditionRoot = getDocumentRoot(workflowDirStr
+                                + "conditions.xml");
+
+                        Element conditionElement = conditionRoot
+                                .getDocumentElement();
+
+                        NodeList conditionElemList = conditionElement
+                                .getElementsByTagName("condition");
+
+                        if (conditionElemList != null
+                                && conditionElemList.getLength() > 0) {
+                            for (int j = 0; j < conditionElemList.getLength(); j++) {
+                                Element conditionElem = (Element) conditionElemList
+                                        .item(j);
+                                WorkflowCondition condition = XmlStructFactory
+                                        .getWorkflowCondition(conditionElem);
+                                if (condition != null) {
+                                    conditionMap.put(
+                                            condition.getConditionId(),
+                                            condition);
+                                }
+                            }
+
+                        }
+                    }
+                } catch (URISyntaxException e) {
+                    LOG
+                            .log(
+                                    Level.WARNING,
+                                    "DirUri: "
+                                            + dirUri
+                                            + " is not a directory: skipping condition loading for it.");
+                }
+
+            }
+        }
+    }
+
+    private void loadWorkflows(List dirUris) {
+        if (dirUris != null && dirUris.size() > 0) {
+            for (Iterator i = dirUris.iterator(); i.hasNext();) {
+                String dirUri = (String) i.next();
+
+                try {
+                    File workflowDir = new File(new URI(dirUri));
+                    if (workflowDir.isDirectory()) {
+                        String workflowDirStr = workflowDir.getAbsolutePath();
+
+                        if (!workflowDirStr.endsWith("/")) {
+                            workflowDirStr += "/";
+                        }
+
+                        // get all the workflow xml files
+                        File[] workflowFiles = workflowDir
+                                .listFiles(workflowXmlFilter);
+
+                        for (int j = 0; j < workflowFiles.length; j++) {
+                            String workflowXmlFile = workflowFiles[j]
+                                    .getAbsolutePath();
+                            Document workflowRoot = getDocumentRoot(workflowXmlFile);
+
+                            String workflowId = workflowRoot
+                                    .getDocumentElement().getAttribute("id");
+                            if (workflowMap.get(workflowId) == null) {
+                                Workflow w = XmlStructFactory.getWorkflow(
+                                        workflowRoot.getDocumentElement(),
+                                        taskMap, conditionMap);
+                                
+                                if(w.getConditions() != null && w.getConditions().size() > 0){
+                                  // add a virtual first task, with the conditions 
+                                  w.getTasks().add(0, getGlobalWorkflowConditionsTask(w.getName(), w.getId(), w.getConditions()));
+                                }
+                                workflowMap.put(workflowId, w);
+                            } else {
+                                LOG
+                                        .log(
+                                                Level.FINE,
+                                                "Ignoring workflow file: "
+                                                        + workflowXmlFile
+                                                        + " when loading workflows, workflow id: "
+                                                        + workflowId
+                                                        + " already loaded");
+                            }
+
+                        }
+                    }
+                } catch (URISyntaxException e) {
+                    LOG
+                            .log(
+                                    Level.WARNING,
+                                    "DirUri: "
+                                            + dirUri
+                                            + " is not a directory: skipping workflow loading for it.");
+                }
+
+            }
+        }
+    }
+
+    private void loadEvents(List dirUris) {
+        if (dirUris != null && dirUris.size() > 0) {
+            for (Iterator i = dirUris.iterator(); i.hasNext();) {
+                String dirUri = (String) i.next();
+
+                try {
+                    File workflowDir = new File(new URI(dirUri));
+                    if (workflowDir.isDirectory()) {
+                        String workflowDirStr = workflowDir.getAbsolutePath();
+
+                        if (!workflowDirStr.endsWith("/")) {
+                            workflowDirStr += "/";
+                        }
+
+                        Document eventRoot = getDocumentRoot(workflowDirStr
+                                + "events.xml");
+
+                        Element eventElement = eventRoot.getDocumentElement();
+
+                        NodeList eventElemList = eventElement
+                                .getElementsByTagName("event");
+
+                        if (eventElemList != null
+                                && eventElemList.getLength() > 0) {
+                            for (int j = 0; j < eventElemList.getLength(); j++) {
+                                Element eventElem = (Element) eventElemList
+                                        .item(j);
+
+                                String eventName = eventElem
+                                        .getAttribute("name");
+                                Workflow w = null;
+
+                                NodeList workflowNodeList = eventElem
+                                        .getElementsByTagName("workflow");
+
+                                if (workflowNodeList != null
+                                        && workflowNodeList.getLength() > 0) {
+                                    List workflowList = new Vector();
+
+                                    for (int k = 0; k < workflowNodeList
+                                            .getLength(); k++) {
+                                        Element workflowElement = (Element) workflowNodeList
+                                                .item(k);
+                                        w = (Workflow) workflowMap
+                                                .get(workflowElement
+                                                        .getAttribute("id"));
+
+                                        if (w != null) {
+                                            workflowList.add(w);
+                                        }
+                                    }
+
+                                    eventMap.put(eventName, workflowList);
+                                }
+                            }
+                        }
+                    }
+                } catch (URISyntaxException e) {
+                    LOG
+                            .log(
+                                    Level.WARNING,
+                                    "DirUri: "
+                                            + dirUri
+                                            + " is not a directory: skipping event loading for it.");
+                }
+
+            }
+        }
+    }
+
+    private Document getDocumentRoot(String xmlFile) {
+        // open up the XML file
+        DocumentBuilderFactory factory = null;
+        DocumentBuilder parser = null;
+        Document document = null;
+        InputSource inputSource = null;
+
+        InputStream xmlInputStream = null;
+
+        try {
+            xmlInputStream = new File(xmlFile).toURL().openStream();
+        } catch (IOException e) {
+            LOG.log(Level.WARNING,
+                    "IOException when getting input stream from [" + xmlFile
+                            + "]: returning null document root");
+            return null;
+        }
+
+        inputSource = new InputSource(xmlInputStream);
+
+        try {
+            factory = DocumentBuilderFactory.newInstance();
+            parser = factory.newDocumentBuilder();
+            document = parser.parse(inputSource);
+        } catch (Exception e) {
+            LOG.warning("Unable to parse xml file [" + xmlFile + "]."
+                    + "Reason is [" + e + "]");
+            return null;
+        }
+
+        return document;
+    }
+    
+    private WorkflowTask getGlobalWorkflowConditionsTask(String workflowName, String workflowId, List<WorkflowCondition> conditions){
+      WorkflowTask task = new WorkflowTask();
+      task.setConditions(conditions);
+      task.setTaskConfig(new WorkflowTaskConfiguration());
+      task.setTaskId(workflowId+"-global-conditions-eval");
+      task.setTaskName(workflowName+"-global-conditions-eval");
+      task.setTaskInstanceClassName(NoOpTask.class.getName());
+      this.taskMap.put(task.getTaskId(), task);
+      return task;
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/XMLWorkflowRepositoryFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/XMLWorkflowRepositoryFactory.java
new file mode 100644
index 0000000..aac9b77
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/repository/XMLWorkflowRepositoryFactory.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.repository;
+
+//JDK imports
+import org.apache.oodt.cas.metadata.util.PathUtils;
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @version $Revsion$
+ * 
+ * <p>A Factory class for creating {@link XMLWorkflowRepository}s.</p>
+ */
+public class XMLWorkflowRepositoryFactory implements WorkflowRepositoryFactory {
+
+	/* list of dir uris specifying file paths to workflow directories */
+	private List workflowDirList = null;
+	
+	/* our log stream */
+	private static Logger LOG = Logger.getLogger(XMLWorkflowRepositoryFactory.class.getName());
+	
+	/**
+	 * <p>Default Constructor</p>.
+	 */
+	public XMLWorkflowRepositoryFactory() {
+		String workflowDirUris = System.getProperty("org.apache.oodt.cas.workflow.repo.dirs");
+		
+		if(workflowDirUris != null){
+			/* do env var replacement */
+			workflowDirUris = PathUtils.replaceEnvVariables(workflowDirUris);
+			String [] dirUris = workflowDirUris.split(",");
+			workflowDirList = Arrays.asList(dirUris);
+		}
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.oodt.cas.workflow.repository.WorkflowRepositoryFactory#createRepository()
+	 */
+	public WorkflowRepository createRepository() {
+		if(workflowDirList != null){
+			return new XMLWorkflowRepository(workflowDirList);
+		}
+		else{
+			LOG.log(Level.WARNING, "Cannot create XML Workflow Repository: no workflow dir uris specified: value: "+System.getProperty("org.apache.oodt.cas.workflow.repo.dirs"));
+			return null;
+		}
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/ConditionTaskInstance.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/ConditionTaskInstance.java
new file mode 100644
index 0000000..d8a5947
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/ConditionTaskInstance.java
@@ -0,0 +1,96 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.exceptions.WorkflowTaskInstanceException;
+import org.apache.oodt.cas.workflow.util.GenericWorkflowObjectFactory;
+
+/**
+ * 
+ * This is a {@link WorkflowTaskInstance} that is able to run a
+ * {@link WorkflowConditionInstance}, identified by the provided task config
+ * property name "ConditionClassName". If the run of the
+ * {@link WorkflowConditionInstance} does not return true, then a
+ * {@link WorkflowTaskInstanceException} is thrown. Note, this exception is also
+ * thrown if there is an error with the provided ConditionClassName, or if it's
+ * not provided.
+ * 
+ * If the underlying {@link WorkflowConditionInstance} returns true, then this
+ * task completes successfully, and does not throw any Exceptions.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ConditionTaskInstance implements WorkflowTaskInstance {
+
+  private static final Logger LOG = Logger
+      .getLogger(ConditionTaskInstance.class.getName());
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance#run(org.apache
+   * .oodt.cas.metadata.Metadata,
+   * org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration)
+   */
+  @Override
+  public void run(Metadata metadata, WorkflowTaskConfiguration config)
+      throws WorkflowTaskInstanceException {
+    String conditionClassName = config.getProperty("ConditionClassName");
+    if (conditionClassName == null
+        || (conditionClassName != null && conditionClassName.equals(""))) {
+      throw new WorkflowTaskInstanceException(
+          "Condition class name is null or " + "unreadable: ["
+              + conditionClassName + "]: unable to run ConditionTaskInstance!");
+    }
+
+    LOG.log(Level.INFO, "ConditionTaskInstance: evaluating condition: ["
+        + conditionClassName + "]");
+    WorkflowConditionInstance cond = GenericWorkflowObjectFactory
+        .getConditionObjectFromClassName(conditionClassName);
+    WorkflowConditionConfiguration condConfig = fromWorkflowTaskConfig(config);
+    if (!cond.evaluate(metadata, condConfig)) {
+      throw new WorkflowTaskInstanceException("Condition: ["
+          + conditionClassName + "] failed!");
+    }
+
+  }
+
+  private WorkflowConditionConfiguration fromWorkflowTaskConfig(
+      WorkflowTaskConfiguration config) {
+    WorkflowConditionConfiguration cfg = new WorkflowConditionConfiguration();
+    for (String propName : (Set<String>) (Set<?>) config.getProperties()
+        .keySet()) {
+      if (!propName.equals("ConditionClassName")) {
+        cfg.addConfigProperty(propName, config.getProperty(propName));
+      }
+    }
+
+    return cfg;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/FILOPrioritySorter.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/FILOPrioritySorter.java
new file mode 100644
index 0000000..76c4b0e
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/FILOPrioritySorter.java
@@ -0,0 +1,70 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor;
+
+/**
+ * 
+ * Sorts the {@link List} of {@link WorkflowProcessor} candidates according to
+ * the time in which the {@link WorkflowInstance} that they are processing was
+ * created. The first ones to get processed are the most recently created
+ * instances.
+ * 
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class FILOPrioritySorter implements PrioritySorter {
+
+  private static final Logger LOG = Logger.getLogger(FILOPrioritySorter.class
+      .getName());
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.structs.PrioritySorter#sort(java.util.List)
+   */
+  @Override
+  public synchronized void sort(List<WorkflowProcessor> candidates) {
+    Collections.sort(candidates, new Comparator<WorkflowProcessor>() {
+      /*
+       * (non-Javadoc)
+       * 
+       * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+       */
+      @Override
+      public int compare(WorkflowProcessor o1, WorkflowProcessor o2) {
+        return o1.getWorkflowInstance().getStartDate()
+            .compareTo(o2.getWorkflowInstance().getStartDate());
+      }
+
+    });
+
+  }
+
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/Graph.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/Graph.java
new file mode 100644
index 0000000..bf2a074
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/Graph.java
@@ -0,0 +1,405 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+import java.util.Vector;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * A representation of data flow and control flow relationship associated with a
+ * {@link Workflow}.
+ * 
+ * @author mattmann
+ * @author bfsoter
+ * 
+ */
+public class Graph {
+
+  private WorkflowTask task;
+
+  private WorkflowCondition cond;
+
+  private ParentChildWorkflow workflow;
+
+  private String modelIdRef;
+
+  private String modelId;
+
+  private String modelName;
+
+  private String alias;
+
+  private String executionType;
+
+  private String minReqSuccessfulSubProcessors;
+
+  private List<String> excused;
+
+  private String clazz;
+
+  private long timeout;
+
+  private boolean optional;
+
+  private Graph parent;
+
+  private List<Graph> children;
+
+  public static final List<String> processorIds = Arrays.asList(new String[] {
+      "sequential", "parallel", "condition", "task" });
+
+  public Graph(Element graphElem, Metadata staticMetadata) throws Exception {
+    this();
+    this.modelId = graphElem.getAttribute("id");
+    this.modelName = graphElem.getAttribute("name");
+    this.clazz = graphElem.getAttribute("class");
+    this.modelIdRef = graphElem.getAttribute("id-ref");
+    this.excused.addAll(Arrays.asList(graphElem.getAttribute("excused").split(
+        ",")));
+    this.alias = graphElem.getAttribute("alias");
+    this.minReqSuccessfulSubProcessors = graphElem.getAttribute("min");
+    this.executionType = graphElem.getAttribute("execution");
+    this.timeout = Long.valueOf(graphElem.getAttribute("timeout") != null
+        && !graphElem.getAttribute("timeout").equals("") ? graphElem
+        .getAttribute("timeout") : "-1");
+    this.optional = Boolean.valueOf(graphElem.getAttribute("optional"));
+
+    NamedNodeMap attrMap = graphElem.getAttributes();
+    for (int i = 0; i < attrMap.getLength(); i++) {
+      Attr attr = (Attr) attrMap.item(i);
+      if (attr.getName().startsWith("p:")) {
+        staticMetadata.replaceMetadata(attr.getName().substring(2),
+            attr.getValue());
+      }
+    }
+
+    if ((graphElem.getNodeName().equals("workflow") || graphElem.getNodeName()
+        .equals("conditions")) && this.executionType == null) {
+      throw new Exception("workflow model '" + graphElem.getNodeName()
+          + "' missing execution type");
+    } else {
+      this.executionType = graphElem.getNodeName();
+    }
+
+    if (!processorIds.contains(this.executionType))
+      throw new Exception("Unsupported execution type id '"
+          + this.executionType + "'");
+
+    if (!checkValue(this.modelId) && !checkValue(this.modelIdRef)) {
+      this.modelId = UUID.randomUUID().toString();
+    }
+
+    if (this.alias != null && !this.alias.equals("")) {
+      this.modelId = this.alias;
+    }
+  }
+
+  public Graph() {
+    this.task = null;
+    this.cond = null;
+    this.workflow = null;
+    this.modelIdRef = null;
+    this.modelId = null;
+    this.modelName = null;
+    this.alias = null;
+    this.executionType = null;
+    this.minReqSuccessfulSubProcessors = null;
+    this.excused = new Vector<String>();
+    this.clazz = null;
+    this.children = new Vector<Graph>();
+    this.parent = null;
+    this.timeout = -1;
+    this.optional = false;
+  }
+
+  /**
+   * @return the parent
+   */
+  public Graph getParent() {
+    return parent;
+  }
+
+  /**
+   * @param parent
+   *          the parent to set
+   */
+  public void setParent(Graph parent) {
+    this.parent = parent;
+  }
+
+  /**
+   * @return the children
+   */
+  public List<Graph> getChildren() {
+    return children;
+  }
+
+  /**
+   * @param children
+   *          the children to set
+   */
+  public void setChildren(List<Graph> children) {
+    this.children = children;
+  }
+
+  /**
+   * @return the modelIdRef
+   */
+  public String getModelIdRef() {
+    return modelIdRef;
+  }
+
+  /**
+   * @param modelIdRef
+   *          the modelIdRef to set
+   */
+  public void setModelIdRef(String modelIdRef) {
+    this.modelIdRef = modelIdRef;
+  }
+
+  /**
+   * @return the modelId
+   */
+  public String getModelId() {
+    return modelId;
+  }
+
+  /**
+   * @param modelId
+   *          the modelId to set
+   */
+  public void setModelId(String modelId) {
+    this.modelId = modelId;
+  }
+
+  /**
+   * @return the modelName
+   */
+  public String getModelName() {
+    return modelName;
+  }
+
+  /**
+   * @param modelName
+   *          the modelName to set
+   */
+  public void setModelName(String modelName) {
+    this.modelName = modelName;
+  }
+
+  /**
+   * @return the alias
+   */
+  public String getAlias() {
+    return alias;
+  }
+
+  /**
+   * @param alias
+   *          the alias to set
+   */
+  public void setAlias(String alias) {
+    this.alias = alias;
+  }
+
+  /**
+   * @return the executionType
+   */
+  public String getExecutionType() {
+    return executionType;
+  }
+
+  /**
+   * @param executionType
+   *          the executionType to set
+   */
+  public void setExecutionType(String executionType) {
+    this.executionType = executionType;
+  }
+
+  /**
+   * @return the minReqSuccessfulSubProcessors
+   */
+  public String getMinReqSuccessfulSubProcessors() {
+    return minReqSuccessfulSubProcessors;
+  }
+
+  /**
+   * @param minReqSuccessfulSubProcessors
+   *          the minReqSuccessfulSubProcessors to set
+   */
+  public void setMinReqSuccessfulSubProcessors(
+      String minReqSuccessfulSubProcessors) {
+    this.minReqSuccessfulSubProcessors = minReqSuccessfulSubProcessors;
+  }
+
+  /**
+   * @return the excused
+   */
+  public List<String> getExcused() {
+    return excused;
+  }
+
+  /**
+   * @param excused
+   *          the excused to set
+   */
+  public void setExcused(List<String> excused) {
+    this.excused = excused;
+  }
+
+  /**
+   * @return the clazz
+   */
+  public String getClazz() {
+    return clazz;
+  }
+
+  /**
+   * @param clazz
+   *          the clazz to set
+   */
+  public void setClazz(String clazz) {
+    this.clazz = clazz;
+  }
+
+  /**
+   * @return the task
+   */
+  public WorkflowTask getTask() {
+    return task;
+  }
+
+  /**
+   * @param task
+   *          the task to set
+   */
+  public void setTask(WorkflowTask task) {
+    this.task = task;
+  }
+
+  /**
+   * @return the cond
+   */
+  public WorkflowCondition getCond() {
+    return cond;
+  }
+
+  /**
+   * @param cond
+   *          the cond to set
+   */
+  public void setCond(WorkflowCondition cond) {
+    this.cond = cond;
+  }
+
+  /**
+   * @return the workflow
+   */
+  public ParentChildWorkflow getWorkflow() {
+    return workflow;
+  }
+
+  /**
+   * @param workflow
+   *          the workflow to set
+   */
+  public void setWorkflow(ParentChildWorkflow workflow) {
+    this.workflow = workflow;
+  }
+
+  public String toString() {
+    return this.modelId;
+  }
+
+  /**
+   * @return the timeout
+   */
+  public long getTimeout() {
+    return timeout;
+  }
+
+  /**
+   * @param timeout
+   *          the timeout to set
+   */
+  public void setTimeout(long timeout) {
+    this.timeout = timeout;
+  }
+
+  /**
+   * @return the optional
+   */
+  public boolean isOptional() {
+    return optional;
+  }
+
+  /**
+   * @param optional
+   *          the optional to set
+   */
+  public void setOptional(boolean optional) {
+    this.optional = optional;
+  }
+
+  /**
+   * @return the processorIds
+   */
+  public List<String> getProcessorIds() {
+    return processorIds;
+  }
+  
+  /**
+   * 
+   * @return True is {@link #cond} isn't null, false otherwise.
+   */
+  public boolean isCondition(){
+    return this.cond != null;
+  }
+  
+  /**
+   * 
+   * @return True if {@link #workflow} isn't null, false othewise.
+   */
+  public boolean isWorkflow(){
+    return this.workflow != null;
+  }
+  
+  /**
+   * 
+   * @return True if {@link #task} isn't null, false otherwise.
+   */
+  public boolean isTask(){
+    return this.task != null;
+  }
+
+  private boolean checkValue(String value) {
+    return value != null && !value.equals("");
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/HighestFIFOPrioritySorter.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/HighestFIFOPrioritySorter.java
new file mode 100644
index 0000000..7b7798c
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/HighestFIFOPrioritySorter.java
@@ -0,0 +1,99 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor;
+
+/**
+ * 
+ * Sorts based on highest {@link Priority} for a {@link WorkflowProcessor} using
+ * a particular {@link #boostAmount} provided by a calling party. The
+ * {@link #boostAmount} is computed based on a function that allows
+ * {@link #boostAmount} to grow over time depending on
+ * {@link #secondsBetweenBoosts} and a maximum {@link #boostCap}.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class HighestFIFOPrioritySorter implements PrioritySorter {
+
+  private int secondsBetweenBoosts;
+  private double boostAmount;
+  private double boostCap;
+  private static final Logger LOG = Logger
+      .getLogger(HighestFIFOPrioritySorter.class.getName());
+
+  public HighestFIFOPrioritySorter(int secondsBetweenBoosts,
+      double boostAmount, double boostCap) {
+    this.secondsBetweenBoosts = secondsBetweenBoosts;
+    this.boostAmount = boostAmount;
+    this.boostCap = boostCap;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.structs.PrioritySorter#sort(java.util.List)
+   */
+  @Override
+  public synchronized void sort(List<WorkflowProcessor> candidates) {
+
+    Collections.sort(candidates, new Comparator<WorkflowProcessor>() {
+      public int compare(WorkflowProcessor o1, WorkflowProcessor o2) {
+        return calculatePriority(o2).compareTo(calculatePriority(o1));
+      }
+    });
+  }
+
+  private Double calculatePriority(WorkflowProcessor processorStub) {
+    double aliveTime = 0.0;
+
+    try {
+      aliveTime = (double) (System.currentTimeMillis() - processorStub
+          .getWorkflowInstance().getCreationDate().getTime());
+    } catch (Exception e) {
+      e.printStackTrace();
+      LOG.log(Level.WARNING,
+          "Unable to compute aliveTime for computing FIFO priority: Reason: ["
+              + e.getMessage() + "]");
+      aliveTime = 0.0;
+    }
+
+    double boostPercentage = aliveTime / 1000.0
+        / (double) this.secondsBetweenBoosts;
+    return Math.max(
+        processorStub.getWorkflowInstance().getPriority().getValue(),
+        Math.min(
+            this.boostCap,
+            Double.valueOf(processorStub.getWorkflowInstance().getPriority()
+                .getValue()
+                + (boostPercentage * this.boostAmount))));
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/HighestPrioritySorter.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/HighestPrioritySorter.java
new file mode 100644
index 0000000..e9e9926
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/HighestPrioritySorter.java
@@ -0,0 +1,58 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor;
+
+/**
+ * 
+ * Sorts strictly based on associated {@link WorkflowProcessor#getPriority()} in
+ * reverse natural order.
+ * 
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class HighestPrioritySorter implements PrioritySorter {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.structs.PrioritySorter#sort(java.util.List)
+   */
+  @Override
+  public synchronized void sort(List<WorkflowProcessor> candidates) {
+    Collections.sort(candidates, new Comparator<WorkflowProcessor>() {
+
+      @Override
+      public int compare(WorkflowProcessor o1, WorkflowProcessor o2) {
+        return o2.getWorkflowInstance().getPriority()
+            .compareTo(o1.getWorkflowInstance().getPriority());
+      }
+    });
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/ParentChildWorkflow.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/ParentChildWorkflow.java
new file mode 100644
index 0000000..7e5f3f4
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/ParentChildWorkflow.java
@@ -0,0 +1,110 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.List;
+
+/**
+ * 
+ * A {@link Workflow} container object that maps a Parent and a Child
+ * {@link Workflow} model by using the {@link Graph} construct.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class ParentChildWorkflow extends Workflow {
+
+  private Graph graph;
+
+  public ParentChildWorkflow(Workflow workflow) {
+    super(workflow.getName(), workflow.getId(), workflow.getTasks(), workflow
+        .getConditions());
+    this.graph = new Graph();
+  }
+
+  public ParentChildWorkflow(Graph graph) {
+    super();
+    this.graph = graph;
+  }
+
+  @Override
+  public String toString() {
+    StringBuffer buf = new StringBuffer("[workflow id=");
+    buf.append(this.getId());
+    buf.append(",name=");
+    buf.append(this.getName());
+    buf.append(",parent=");
+    buf.append(this.graph.getParent() != null ? this.graph.getParent()
+        .getModelId() : null);
+    buf.append(",children=");
+    buf.append(this.graph.getChildren());
+    buf.append(",executionType=");
+    buf.append(this.graph.getExecutionType());
+    buf.append(",tasks=");
+    for (WorkflowTask task : (List<WorkflowTask>) this.getTasks()) {
+      buf.append("[task name=");
+      buf.append(task.getTaskName());
+      buf.append(",id=");
+      buf.append(task.getTaskId());
+      buf.append(",instanceClass=");
+      buf.append(task.getTaskInstanceClassName());
+      buf.append(",requiredMet=");
+      buf.append(task.getRequiredMetFields());
+
+      buf.append(",conditions=");
+      for (WorkflowCondition cond : (List<WorkflowCondition>) task
+          .getConditions()) {
+        buf.append("[condition name=");
+        buf.append(cond.getConditionName());
+        buf.append(",id=");
+        buf.append(cond.getConditionId());
+        buf.append(",instanceClass=");
+        buf.append(cond.getConditionInstanceClassName());
+        buf.append(",timeout=");
+        buf.append(cond.getTimeoutSeconds());
+        buf.append(",optiona=");
+        buf.append(cond.isOptional());
+        buf.append(",config=");
+        buf.append(cond.getCondConfig().getProperties());
+        buf.append("]");
+      }
+
+      buf.append("]");
+    }
+
+    return buf.toString();
+  }
+
+  /**
+   * @return the graph
+   */
+  public Graph getGraph() {
+    return graph;
+  }
+
+  /**
+   * @param graph
+   *          the graph to set
+   */
+  public void setGraph(Graph graph) {
+    this.graph = graph;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/Priority.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/Priority.java
new file mode 100755
index 0000000..fea1851
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/Priority.java
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+/**
+ * 
+ * Priority of a WorkflowProcessor.
+ * 
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public abstract class Priority implements Comparable<Priority> {
+
+  /**
+   * Big the better (that is higher the number higher the priority)
+   * 
+   * @return
+   */
+  public abstract double getValue();
+
+  public abstract String getName();
+
+  public static final Priority LOW = new Priority() {
+    public double getValue() {
+      return 0;
+    }
+
+    public String getName() {
+      return "LOW";
+    }
+  };
+  public static final Priority MEDIUM_LOW = new Priority() {
+    public double getValue() {
+      return 2.5;
+    }
+
+    public String getName() {
+      return "MEDIUM_LOW";
+    }
+  };
+  public static final Priority MEDIUM = new Priority() {
+    public double getValue() {
+      return 5;
+    }
+
+    public String getName() {
+      return "MEDIUM";
+    }
+  };
+  public static final Priority MEDIUM_HIGH = new Priority() {
+    public double getValue() {
+      return 7.5;
+    }
+
+    public String getName() {
+      return "MEDIUM_HIGH";
+    }
+  };
+  public static final Priority HIGH = new Priority() {
+    public double getValue() {
+      return 10;
+    }
+
+    public String getName() {
+      return "HIGH";
+    }
+  };
+
+  public static Priority getDefault() {
+    return MEDIUM;
+  }
+
+  public static Priority getPriority(final double priority) {
+    if (priority == LOW.getValue())
+      return LOW;
+    else if (priority == MEDIUM_LOW.getValue())
+      return MEDIUM_LOW;
+    else if (priority == MEDIUM.getValue())
+      return MEDIUM;
+    else if (priority == MEDIUM_HIGH.getValue())
+      return MEDIUM_HIGH;
+    else if (priority == HIGH.getValue())
+      return HIGH;
+    else
+      return new Priority() {
+        public double getValue() {
+          return priority;
+        }
+
+        public String getName() {
+          return "CUSTOM";
+        }
+      };
+  }
+
+  @Override
+  public int hashCode() {
+    return new Double(this.getValue()).hashCode();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof Priority)
+      return new Double(this.getValue()).equals(((Priority) obj).getValue());
+    else
+      return false;
+  }
+
+  @Override
+  public int compareTo(Priority priority) {
+    return new Double(this.getValue()).compareTo(priority.getValue());
+  }
+
+  @Override
+  public String toString() {
+    return this.getName() + " : " + Double.toString(this.getValue());
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/PrioritySorter.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/PrioritySorter.java
new file mode 100644
index 0000000..5cd7c60
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/PrioritySorter.java
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor;
+
+/**
+ * 
+ * Interface specifying a method to sort and prioritize
+ * {@link WorkflowProcessor}s.
+ * 
+ * @author bfoster
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public interface PrioritySorter {
+
+  /**
+   * Sorts the {@link List} of {@link WorkflowProcessor}s that are ready to run
+   * in a particular order specified by the sub-class implementing this method.
+   * 
+   * @param candidates
+   *          The {@link List} of {@link WorkflowProcessor}s to sort in priority
+   *          order.
+   */
+  public void sort(List<WorkflowProcessor> candidates);
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/TaskJob.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/TaskJob.java
new file mode 100644
index 0000000..333c436
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/TaskJob.java
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.oodt.commons.util.DateConvert;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.resource.structs.JobInstance;
+import org.apache.oodt.cas.resource.structs.exceptions.JobInputException;
+import org.apache.oodt.cas.workflow.metadata.CoreMetKeys;
+import org.apache.oodt.cas.workflow.structs.exceptions.WorkflowTaskInstanceException;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+import org.apache.oodt.cas.workflow.util.GenericWorkflowObjectFactory;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Resource Manager {@link Job} that runs an underlying {@link WorkflowTask}.
+ * </p>.
+ */
+public class TaskJob implements JobInstance, WorkflowStatus, CoreMetKeys{
+
+    /* our log stream */
+    private static Logger LOG = Logger.getLogger(TaskJob.class.getName());
+
+    /**
+     * Default Constructor.
+     */
+    public TaskJob() {
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.cas.resource.structs.JobInstance#execute(org.apache.oodt.cas.resource.structs.JobInput)
+     */
+    public boolean execute(JobInput in) throws JobInputException {
+        if (!(in instanceof TaskJobInput)) {
+            throw new JobInputException("Task Job: unknown JobInput class: ["
+                    + in.getClass().getName() + "]");
+        }
+
+        // otherwise, we're all good
+        TaskJobInput taskInput = (TaskJobInput) in;
+
+        // Instantiate the Workflow Task Instance
+        WorkflowTaskInstance inst = GenericWorkflowObjectFactory
+                .getTaskObjectFromClassName(taskInput
+                        .getWorkflowTaskInstanceClassName());
+
+        // override what ProcessingNode we are running on
+        // the workflow manager by default inserts its own host
+        // as the ProcessingNode
+        taskInput.getDynMetadata().replaceMetadata(PROCESSING_NODE,
+                getHostname());
+        updateMetadata(taskInput.getDynMetadata());
+
+        // update status to started again (now that the job is distributed and
+        // about to run
+        updateStatus(STARTED, taskInput.getDynMetadata());
+
+        // go ahead and persist the workflow instance, after we
+        // save the current task start date time
+        String currentTaskIsoStartDateTimeStr = DateConvert
+                .isoFormat(new Date());
+        setWorkflowInstanceCurrentTaskStartDateTime(
+                currentTaskIsoStartDateTimeStr, taskInput.getDynMetadata());
+        setWorkflowInstanceCurrentTaskEndDateTime("", taskInput
+                .getDynMetadata()); /* clear this out */
+
+        // now we just call inst with the given task cfg and metadata
+        try {
+            inst.run(taskInput.getDynMetadata(), taskInput.getTaskConfig());
+        } catch (WorkflowTaskInstanceException e) {
+            throw new JobInputException("Failed to run task", e);
+        }
+
+        String currentTaskIsoEndDateTimeStr = DateConvert.isoFormat(new Date());
+        setWorkflowInstanceCurrentTaskEndDateTime(currentTaskIsoEndDateTimeStr,
+                taskInput.getDynMetadata());
+
+        // now we have to update the workflow manager with the metadata
+        // that may have been updated
+        updateMetadata(taskInput.getDynMetadata());
+
+        return true;
+    }
+
+    private void updateStatus(String status, Metadata met) {
+        String workflowInstId = met.getMetadata(WORKFLOW_INST_ID);
+        XmlRpcWorkflowManagerClient wClient = getWmClientFromMetadata(met);
+
+        try {
+            if (!wClient.updateWorkflowInstanceStatus(workflowInstId, status)) {
+                LOG.log(Level.WARNING,
+                        "Unable to update status for workflow instance: ["
+                                + workflowInstId + "] to : [" + status + "]");
+            }
+        } catch (Exception ignore) {
+        }
+    }
+
+    private void updateMetadata(Metadata met) {
+        String workflowInstId = met.getMetadata(WORKFLOW_INST_ID);
+        XmlRpcWorkflowManagerClient wClient = getWmClientFromMetadata(met);
+
+        try {
+            if (!wClient.updateMetadataForWorkflow(workflowInstId, met)) {
+                LOG.log(Level.WARNING,
+                        "Unable to update Metadata for workflow instance: ["
+                                + workflowInstId + "]");
+            }
+        } catch (Exception ignore) {
+        }
+    }
+
+    private void setWorkflowInstanceCurrentTaskStartDateTime(
+            String startDateTime, Metadata met) {
+        String workflowInstId = met.getMetadata(WORKFLOW_INST_ID);
+        XmlRpcWorkflowManagerClient wClient = getWmClientFromMetadata(met);
+
+        try {
+            if (!wClient.setWorkflowInstanceCurrentTaskStartDateTime(
+                    workflowInstId, startDateTime)) {
+                LOG.log(Level.WARNING,
+                        "Unable to update start date time for workflow instance: ["
+                                + workflowInstId + "]");
+            }
+        } catch (Exception ignore) {
+        }
+    }
+
+    private void setWorkflowInstanceCurrentTaskEndDateTime(String endDateTime,
+            Metadata met) {
+        String workflowInstId = met.getMetadata(WORKFLOW_INST_ID);
+        XmlRpcWorkflowManagerClient wClient = getWmClientFromMetadata(met);
+
+        try {
+            if (!wClient.setWorkflowInstanceCurrentTaskEndDateTime(
+                    workflowInstId, endDateTime)) {
+                LOG.log(Level.WARNING,
+                        "Unable to update end date time for workflow instance: ["
+                                + workflowInstId + "]");
+            }
+        } catch (Exception ignore) {
+        }
+    }
+
+    private XmlRpcWorkflowManagerClient getWmClientFromMetadata(Metadata met) {
+        String workflowMgrUrlStr = met.getMetadata(WORKFLOW_MANAGER_URL);
+        if (workflowMgrUrlStr == null
+                || (workflowMgrUrlStr != null && workflowMgrUrlStr.equals(""))) {
+            // try to default to a workflow mgr on localhost
+            // most likely won't work, but worth trying
+            workflowMgrUrlStr = "http://localhost:9001";
+        }
+
+        return new XmlRpcWorkflowManagerClient(
+                safeGetUrlFromString(workflowMgrUrlStr));
+    }
+
+    private String getHostname() {
+        try {
+            // Get hostname by textual representation of IP address
+            InetAddress addr = InetAddress.getLocalHost();
+            // Get the host name
+            String hostname = addr.getHostName();
+            return hostname;
+        } catch (UnknownHostException e) {
+        }
+        return null;
+    }
+
+    private URL safeGetUrlFromString(String urlStr) {
+        try {
+            return new URL(urlStr);
+        } catch (MalformedURLException e) {
+            return null;
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/TaskJobInput.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/TaskJobInput.java
new file mode 100644
index 0000000..6653e61
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/TaskJobInput.java
@@ -0,0 +1,194 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Properties;
+
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.resource.structs.JobInput;
+import org.apache.oodt.cas.workflow.util.XmlRpcStructFactory;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * {@link JobInput} for a {@link WorkflowTask}. This class will be instantiated
+ * by the Resource Manager when it receives a {@link TaskJob}. The class
+ * consists of three important pieces of information:
+ * 
+ * <ul>
+ * <li>Static {@link WorkflowTaskConfiguration}</li>
+ * <li>Dynamic Task {@link Metadata}</li>
+ * <li>The name of the {@link WorkflowTaskInstance} class</li>
+ * </ul>
+ * </p>.
+ */
+public class TaskJobInput implements JobInput {
+
+  /* static task config */
+  private WorkflowTaskConfiguration taskConfig = null;
+
+  /* dynamic task metadata */
+  private Metadata dynMetadata = null;
+
+  /* our job id */
+  private String id = null;
+  
+  /* the name of the workflow task instance to instantiate
+   * against this input
+   */
+  private String workflowTaskInstanceClassName = null;
+  
+
+  /**
+   * Default Constructor.
+   */
+  public TaskJobInput() {
+    taskConfig = new WorkflowTaskConfiguration();
+    dynMetadata = new Metadata();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.structs.JobInput#getId()
+   */
+  public String getId() {
+    return id;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.util.XmlRpcWriteable#read(java.lang.Object)
+   */
+  public void read(Object in) {
+    if (!(in instanceof Hashtable)) {
+      return;
+    }
+
+    Hashtable inHash = (Hashtable) in;
+
+    this.taskConfig = XmlRpcStructFactory
+        .getWorkflowTaskConfigurationFromXmlRpc((Hashtable) inHash
+            .get("task.config"));
+    this.dynMetadata.addMetadata((Hashtable) inHash.get("task.metadata"));
+    this.workflowTaskInstanceClassName = (String)inHash.get("task.instance.class");
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.util.XmlRpcWriteable#write()
+   */
+  public Object write() {
+    // need to create a hashtable with the task metadata and the task config
+    Hashtable outHash = new Hashtable();
+    outHash.put("task.config", XmlRpcStructFactory
+        .getXmlRpcWorkflowTaskConfiguration(this.taskConfig));
+    outHash.put("task.metadata", this.dynMetadata.getHashtable());
+    outHash.put("task.instance.class", this.workflowTaskInstanceClassName);
+    return outHash;
+  }
+
+  public Metadata getDynMetadata() {
+    return dynMetadata;
+  }
+
+  public void setDynMetadata(Metadata dynMetadata) {
+    this.dynMetadata = dynMetadata;
+  }
+
+  public WorkflowTaskConfiguration getTaskConfig() {
+    return taskConfig;
+  }
+
+  public void setTaskConfig(WorkflowTaskConfiguration taskConfig) {
+    this.taskConfig = taskConfig;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public String getWorkflowTaskInstanceClassName() {
+    return workflowTaskInstanceClassName;
+  }
+
+  public void setWorkflowTaskInstanceClassName(
+      String workflowTaskInstanceClassName) {
+    this.workflowTaskInstanceClassName = workflowTaskInstanceClassName;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.resource.util.Configurable#configure(java.util.Properties)
+   */
+  public void configure(Properties props) {
+    // looking for dyn.metadata.file
+    // looking for static.config.file
+    String staticConfigFile = props.getProperty("static.config.file");
+    String dynMetadataFile = props.getProperty("dyn.metadata.file");
+
+    if (staticConfigFile != null) {
+      try {
+        this.taskConfig.getProperties().load(
+            new FileInputStream(new File(staticConfigFile)));
+      } catch (RuntimeException ex) {
+        throw ex;
+      } catch (Exception ignore) {  
+      }
+    }
+
+    if (dynMetadataFile != null) {
+      InputStream in = null;
+      try {
+        this.dynMetadata = new Metadata();
+        Properties fileProps = new Properties();
+        in = new BufferedInputStream(new FileInputStream(new File(dynMetadataFile)));
+        fileProps.load(in);
+        for (Object key: fileProps.keySet()){
+          String keyStr = (String)key;
+          this.dynMetadata.addMetadata(keyStr, fileProps.getProperty(keyStr));
+        }
+      } catch (RuntimeException ex) {
+        throw ex;
+      } catch (Exception ignore) {
+      } finally {
+        if (in != null) try {
+          in.close();
+        } catch (IOException ignore) {}
+      }
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/Workflow.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/Workflow.java
new file mode 100644
index 0000000..a83ed16
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/Workflow.java
@@ -0,0 +1,217 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * 
+ * 
+ * A Workflow is an abstract representation of a set of interconnected
+ * processes. Processes, or jobs, may have dependencies upon one another, may
+ * provide each other input, and/or output, or may be completely independent of
+ * one another.
+ * 
+ * <br>
+ * See <a href="http://www.gridbus.org/reports/GridWorkflowTaxonomy.pdf">Buyya
+ * et al.</a> for a great description in detail of what exactly a Workflow is.
+ * 
+ * <br>
+ * Important note: As of Apache OODT 0.4, Workflows now support both pre- and 
+ * post- conditions (as opposed to just pre-conditions, as was the behavior)
+ * before. The methods {@link #getConditions()} and {@link #setConditions(List)} are
+ * now deprecated in favor of their {@link #getPreConditions()} and {@link #setPreConditions(List)}
+ * and {@link #getPostConditions()} and {@link #setPostConditions(List)} counterparts.
+ * The existing condition only methods have been preserved for back compat, but will
+ * go away in later versions of the class and API. Also over the next few releases,
+ * we intend to change the inner APIs to use pre and post conditions.
+ * 
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class Workflow {
+
+  private String name;
+
+  private String id;
+
+  private List<WorkflowTask> tasks;
+
+  private List<WorkflowCondition> preConditions;
+
+  private List<WorkflowCondition> postConditions;
+
+  /**
+   * Default Constructor
+   * 
+   */
+  public Workflow() {
+    this(null, null, new Vector<WorkflowTask>(), new Vector<WorkflowCondition>(), 
+        new Vector<WorkflowCondition>());
+  }
+
+  /**
+   * Constructs a new Workflow with the given parameters. Deprecated. Use
+   * {@link #Workflow(String, String, List, List, List)} instead.
+   * 
+   * @param name
+   *          The name of this workflow.
+   * @param id
+   *          The identifier for this workflow.
+   * @param tasks
+   *          The {@link List} of {@link WorkflowTask}s associated with this
+   *          workflow.
+   * 
+   * @param conditions
+   *          The {@link List} of {@link WorkflowCondition}s associated with
+   *          this workflow.
+   */
+  @Deprecated
+  public Workflow(String name, String id, List<WorkflowTask> tasks,
+      List<WorkflowCondition> conditions) {
+    this(name, id, tasks, conditions,
+        new Vector<WorkflowCondition>());
+  }
+
+  /**
+   * 
+   * @param name
+   *          The name of the Workflow.
+   * @param id
+   *          The identifier of the Workflow.
+   * @param tasks
+   *          The associated {@link List} of {@link WorkflowTask}s.
+   * @param preConditions
+   *          The associated {@link List} of pre-{@link WorkflowCondition}s.
+   * @param postConditions
+   *          The associated {@link List} of post{@link WorkflowCondition}s.
+   */
+  public Workflow(String name, String id, List<WorkflowTask> tasks,
+      List<WorkflowCondition> preConditions,
+      List<WorkflowCondition> postConditions) {
+    this.name = name;
+    this.id = id;
+    this.tasks = tasks;
+    this.preConditions = preConditions;
+    this.postConditions = postConditions;
+
+  }
+
+  /**
+   * @return the id
+   */
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * @param id
+   *          the id to set
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * Deprecated. Currently, this will return a list
+   * of all pre- {@link WorkflowCondition}s. The list
+   * is mutable, and can change the inner portion of the
+   * class. 
+   * 
+   * @return All pre- conditions.
+   */
+  @Deprecated
+  public List<WorkflowCondition> getConditions() {
+    return this.preConditions;
+  }
+
+  /**
+   * Deprecated. Use {@link #setPreConditions(List)} or 
+   * {@link #setPostConditions(List)} instead.
+   * 
+   * @param conditions
+   *          the conditions to set
+   */
+  @Deprecated
+  public void setConditions(List<WorkflowCondition> conditions) {
+    this.preConditions = conditions;
+  }
+
+  /**
+   * @param tasks
+   *          the tasks to set
+   */
+  public void setTasks(List<WorkflowTask> tasks) {
+    this.tasks = tasks;
+  }
+
+  /**
+   * @return the tasks
+   */
+  public List<WorkflowTask> getTasks() {
+    return tasks;
+  }
+
+  /**
+   * @return the preConditions
+   */
+  public List<WorkflowCondition> getPreConditions() {
+    return preConditions;
+  }
+
+  /**
+   * @param preConditions the preConditions to set
+   */
+  public void setPreConditions(List<WorkflowCondition> preConditions) {
+    this.preConditions = preConditions;
+  }
+
+  /**
+   * @return the postConditions
+   */
+  public List<WorkflowCondition> getPostConditions() {
+    return postConditions;
+  }
+
+  /**
+   * @param postConditions the postConditions to set
+   */
+  public void setPostConditions(List<WorkflowCondition> postConditions) {
+    this.postConditions = postConditions;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowCondition.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowCondition.java
new file mode 100644
index 0000000..78068be
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowCondition.java
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+/**
+ * 
+ * A WorkflowCondition is some pre-condition that must evaluate to true in order
+ * for a particular {@link WorkflowTask} to be permitted to execute .
+ * 
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowCondition {
+
+  /* the name of the condition */
+  private String conditionName = null;
+
+  /* the id for the condition */
+  private String conditionId = null;
+
+  /* the actual portion of the condition that performs the work */
+  protected String conditionInstanceClassName = null;
+
+  /* the order that this condition comes in */
+  protected int order = -1;
+
+  /* the static configuration parameters for the condition */
+  protected WorkflowConditionConfiguration condConfig;
+  
+  private long timeoutSeconds;
+  
+  private boolean optional;
+
+  /**
+   * <p>
+   * Default Constructor
+   * </p>
+   * 
+   */
+  public WorkflowCondition() {
+    this(null, null, null, -1);
+  }
+
+  /**
+   * <p>
+   * Constructs a new WorkflowCondition with the specified parameters.
+   * </p>
+   * 
+   * @param conditionName
+   *          The display name of the condition.
+   * @param conditionId
+   *          The ID for this condition.
+   * @param instanceClass
+   *          The particular instance class name attached to this
+   *          WorkflowCondition.
+   * @param order
+   *          The order in which this condition should be checked for a
+   *          particular WorkflowTask.
+   */
+  public WorkflowCondition(String conditionName, String conditionId,
+      String instanceClass, int order) {
+    this.conditionName = conditionName;
+    this.conditionId = conditionId;
+    this.conditionInstanceClassName = instanceClass;
+    this.order = order;
+    this.timeoutSeconds = -1;
+    this.condConfig = new WorkflowConditionConfiguration();
+    this.optional = false;
+  }
+
+  /**
+   * @return Returns the taskConfig.
+   */
+  @Deprecated
+  public WorkflowConditionConfiguration getTaskConfig() {
+    return this.condConfig;
+  }
+
+  /**
+   * @param taskConfig
+   *          The taskConfig to set.
+   */
+  public void setCondConfig(WorkflowConditionConfiguration condConfig) {
+    this.condConfig = condConfig;
+  }
+
+  /**
+   * 
+   * @return Returns the condConfig
+   */
+  public WorkflowConditionConfiguration getCondConfig() {
+    return this.condConfig;
+  }
+
+  /**
+   * @return Returns the conditionId.
+   */
+  public String getConditionId() {
+    return conditionId;
+  }
+
+  /**
+   * @param conditionId
+   *          The conditionId to set.
+   */
+  public void setConditionId(String conditionId) {
+    this.conditionId = conditionId;
+  }
+
+  /**
+   * @return Returns the conditionName.
+   */
+  public String getConditionName() {
+    return conditionName;
+  }
+
+  /**
+   * @param conditionName
+   *          The conditionName to set.
+   */
+  public void setConditionName(String conditionName) {
+    this.conditionName = conditionName;
+  }
+
+  /**
+   * @return Returns the conditionInstanceClassName.
+   */
+  public String getConditionInstanceClassName() {
+    return conditionInstanceClassName;
+  }
+
+  /**
+   * @param conditionInstanceClassName
+   *          The conditionInstanceClassName to set.
+   */
+  public void setConditionInstanceClassName(String conditionInstanceClassName) {
+    this.conditionInstanceClassName = conditionInstanceClassName;
+  }
+
+  /**
+   * @return Returns the order.
+   */
+  public int getOrder() {
+    return order;
+  }
+
+  /**
+   * @param order
+   *          The order to set.
+   */
+  public void setOrder(int order) {
+    this.order = order;
+  }
+
+  /**
+   * @return the timeoutSeconds
+   */
+  public long getTimeoutSeconds() {
+    return timeoutSeconds;
+  }
+
+  /**
+   * @param timeoutSeconds the timeoutSeconds to set
+   */
+  public void setTimeoutSeconds(long timeoutSeconds) {
+    this.timeoutSeconds = timeoutSeconds;
+  }
+
+  /**
+   * @return the optional
+   */
+  public boolean isOptional() {
+    return optional;
+  }
+
+  /**
+   * @param optional the optional to set
+   */
+  public void setOptional(boolean optional) {
+    this.optional = optional;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowConditionConfiguration.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowConditionConfiguration.java
new file mode 100644
index 0000000..7c4b725
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowConditionConfiguration.java
@@ -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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.Properties;
+
+/**
+ * 
+ * Configuration for a {@link WorkflowCondition}.
+ *
+ */
+public class WorkflowConditionConfiguration {
+   
+    /* the condition configuration properties */
+    private Properties condProperties = null;
+    
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     */
+    public WorkflowConditionConfiguration() {
+        condProperties = new Properties();
+    }
+
+    /**
+     * <p>
+     * Construct a new WorkflowTaskConfiguration from a java Properties object.
+     * </p>
+     * 
+     * @param properties
+     *            The task configuration properties.
+     */
+    public WorkflowConditionConfiguration(Properties properties) {
+        condProperties = properties;
+    }
+
+    /**
+     * <p>
+     * Adds the property denoted by the given <code>name></code> and
+     * <code>value</code>.
+     * </p>
+     * 
+     * @param name
+     *            The property name.
+     * @param value
+     *            The property value.
+     */
+    public void addConfigProperty(String name, String value) {
+        condProperties.setProperty(name, value);
+    }
+
+    /**
+     * 
+     * @param propName
+     *            The property to get the value for.
+     * @return The String property value for the specified propName.
+     */
+    public String getProperty(String propName) {
+        return condProperties.getProperty(propName);
+    }
+
+    /**
+     * 
+     * @return The {@link Properties} for configuring this WorkflowTask.
+     */
+    public Properties getProperties() {
+        return condProperties;
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowConditionInstance.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowConditionInstance.java
new file mode 100644
index 0000000..48a107f
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowConditionInstance.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.structs;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revsion$
+ * 
+ * <p>
+ * The actual evaluation method for the condition should be defined in any class
+ * that implements this interface.
+ * </p>
+ */
+public interface WorkflowConditionInstance {
+
+	/**
+	 * <p>
+	 * The actual conditional: this method should return <code>true</code> if
+	 * the condition is satisfied, otherwise, false.
+	 * </p>
+	 * 
+	 * @param metadata
+	 *            Any metadata needed by the conditional to determine
+	 *            satisfaction.
+	 * @return true if the condition is satisfied, otherwise, false.
+	 */
+	public boolean evaluate(Metadata metadata, WorkflowConditionConfiguration config);
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowInstance.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowInstance.java
new file mode 100644
index 0000000..8954426
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowInstance.java
@@ -0,0 +1,445 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.text.ParseException;
+import java.util.Date;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycle;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowState;
+import org.apache.oodt.commons.util.DateConvert;
+
+/**
+ * A WorkflowInstance is an instantiation of the abstract description of a
+ * Workflow provided by the {@link Workflow} class. WorkflowInstances have
+ * status, and in general are data structures intended to be used as a means for
+ * monitoring the status of an executing {@link Workflow}.
+ * 
+ * As of Apache OODT 0.4, the internal {@link Workflow} implementation uses
+ * {@link ParentChildWorkflow}, introduced as part of OODT-70, and the
+ * PackagedWorkflowRepository. {@link Workflow} instances given to the class
+ * will automatically convert to {@link ParentChildWorkflow} implementations
+ * internally, and the existing {@link #getWorkflow()} and
+ * {@link #setWorkflow(Workflow)} methods have been deprecated in favor of
+ * {@link #getParentChildWorkflow()} and
+ * {@link #setParentChildWorkflow(ParentChildWorkflow)} which will supersede
+ * those methods, and eventually turn into their concrete implementations.
+ * 
+ * In addition, as of Apache OODT 0.4 the internal {@link #state} member
+ * variable now uses {@link WorkflowState} for representation. This requires the
+ * use of {@link WorkflowLifecycle} which has now moved from being simply a UI
+ * utility class for the Worklow Monitor web application to actually being fully
+ * integrated with the Workflow Manager. For backwards compatibility the
+ * {@link #setStatus(String)} and {@link #getStatus()} methods are still
+ * supported, but are deprecated. Developers using this class should move
+ * towards using {@link #setState(WorkflowState)} and {@link #getState()}.
+ * 
+ * @author mattmann
+ * @author bfoster
+ * @version $Revision$
+ * 
+ */
+public class WorkflowInstance {
+
+  private ParentChildWorkflow workflow;
+
+  private String id;
+
+  private WorkflowState state;
+
+  private String currentTaskId;
+
+  private Date startDate;
+
+  private Date endDate;
+
+  private Metadata sharedContext;
+
+  private Priority priority;
+
+  private int timesBlocked;
+
+  /**
+   * Default Constructor.
+   * 
+   */
+  public WorkflowInstance() {
+    this(null, null, null, null, new Date(), null, new Metadata(),
+        0, Priority.getDefault());
+  }
+
+  public WorkflowInstance(Workflow workflow, String id, WorkflowState state,
+      String currentTaskId, Date startDate, Date endDate, 
+      Metadata sharedContext, int timesBlocked, Priority priority) {
+    this.workflow = workflow != null && workflow instanceof ParentChildWorkflow ? (ParentChildWorkflow) workflow
+        : new ParentChildWorkflow(workflow != null ? workflow : new Workflow());
+    this.id = id;
+    this.state = state;
+    this.currentTaskId = currentTaskId;
+    this.startDate = startDate;
+    this.endDate = endDate;
+    this.sharedContext = sharedContext;
+    this.timesBlocked = timesBlocked;
+    this.priority = priority;
+  }
+
+  /**
+   * @return the id
+   */
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * @param id
+   *          the id to set
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * @return the status
+   */
+  @Deprecated
+  public String getStatus() {
+    return state != null ? state.getName() : "Null";
+  }
+
+  /**
+   * Sets the current {@link WorkflowState} to the provided status.
+   * 
+   * @param status
+   *          The provided status to set.
+   */
+  @Deprecated
+  public void setStatus(String status) {
+    WorkflowState state = new WorkflowState();
+    state.setName(status);
+    this.state = state;
+  }
+
+  /**
+   * @return the state
+   */
+  public WorkflowState getState() {
+    return state;
+  }
+
+  /**
+   * @param state
+   *          the state to set
+   */
+  public void setState(WorkflowState state) {
+    this.state = state;
+  }
+
+  /**
+   * @return the workflow
+   */
+  @Deprecated
+  public Workflow getWorkflow() {
+    return (Workflow) workflow;
+  }
+
+  /**
+   * @param workflow
+   *          the workflow to set
+   */
+  @Deprecated
+  public void setWorkflow(Workflow workflow) {
+    if (workflow != null && workflow instanceof ParentChildWorkflow) {
+      this.workflow = (ParentChildWorkflow) workflow;
+    } else {
+      if (workflow == null)
+        workflow = new Workflow();
+      this.workflow = new ParentChildWorkflow(workflow);
+    }
+  }
+
+  /**
+   * 
+   * @return The workflow, with its parent/child relationships.
+   */
+  public ParentChildWorkflow getParentChildWorkflow() {
+    return this.workflow;
+  }
+
+  /**
+   * Sets the Parent Child workflow.
+   * 
+   * @param workflow
+   *          The workflow to set.
+   */
+  public void setParentChildWorkflow(ParentChildWorkflow workflow) {
+    this.workflow = workflow;
+  }
+
+  /**
+   * @return the currentTaskId
+   */
+  public String getCurrentTaskId() {
+    return currentTaskId;
+  }
+
+  /**
+   * @param currentTaskId
+   *          the currentTaskId to set
+   */
+  public void setCurrentTaskId(String currentTaskId) {
+    this.currentTaskId = currentTaskId;
+  }
+
+  /**
+   * @return the sharedContext
+   */
+  public Metadata getSharedContext() {
+    return sharedContext;
+  }
+
+  /**
+   * @param sharedContext
+   *          the sharedContext to set
+   */
+  public void setSharedContext(Metadata sharedContext) {
+    this.sharedContext = sharedContext;
+  }
+
+  /**
+   * @return the priority
+   */
+  public Priority getPriority() {
+    return priority;
+  }
+
+  /**
+   * @param priority
+   *          the priority to set
+   */
+  public void setPriority(Priority priority) {
+    this.priority = priority;
+  }
+
+  /**
+   * Convenience method to format and return the
+   * {@link #currentTaskStartDateTimeIsoStr} as a {@link Date}.
+   * 
+   * @return {@link Date} representation of
+   *         {@link #getCurrentTaskStartDateTimeIsoStr()}.
+   */
+  public Date getCreationDate() {
+    return this.startDate;
+  }
+
+  /**
+   * Convenience method to format and return the
+   * {@link #currentTaskEndDateTimeIsoStr} as a {@link Date}.
+   * 
+   * @return {@link Date} representation of
+   *         {@link #getCurrentTaskEndDateTimeIsoStr()}.
+   */
+  public Date getFinishDate() {
+    return this.endDate;
+  }
+
+  /**
+   * @return the startDate
+   */
+  public Date getStartDate() {
+    return startDate;
+  }
+
+  /**
+   * @param startDate
+   *          the startDate to set
+   */
+  public void setStartDate(Date startDate) {
+    this.startDate = startDate;
+  }
+
+  /**
+   * @return the endDate
+   */
+  public Date getEndDate() {
+    return endDate;
+  }
+
+  /**
+   * @param endDate
+   *          the endDate to set
+   */
+  public void setEndDate(Date endDate) {
+    this.endDate = endDate;
+  }
+
+  /**
+   * @return the endDateTimeIsoStr
+   */
+  @Deprecated
+  public String getEndDateTimeIsoStr() {
+    return this.endDate != null ? DateConvert.isoFormat(this.endDate) : null;
+  }
+
+  /**
+   * @param endDateTimeIsoStr
+   *          the endDateTimeIsoStr to set
+   */
+  @Deprecated
+  public void setEndDateTimeIsoStr(String endDateTimeIsoStr) {
+    if (endDateTimeIsoStr != null && !endDateTimeIsoStr.equals("")) {
+      try {
+        this.endDate = DateConvert.isoParse(endDateTimeIsoStr);
+      } catch (ParseException e) {
+        e.printStackTrace();
+        // fail silently besides this: it's just a setter
+      }
+    }
+  }
+
+  /**
+   * @return the startDateTimeIsoStr
+   */
+  @Deprecated
+  public String getStartDateTimeIsoStr() {
+    return this.startDate != null ? DateConvert.isoFormat(this.startDate)
+        : null;
+  }
+
+  /**
+   * @param startDateTimeIsoStr
+   *          the startDateTimeIsoStr to set
+   */
+  @Deprecated
+  public void setStartDateTimeIsoStr(String startDateTimeIsoStr) {
+    if (startDateTimeIsoStr != null && !startDateTimeIsoStr.equals("")) {
+      try {
+        this.startDate = DateConvert.isoParse(startDateTimeIsoStr);
+      } catch (ParseException e) {
+        e.printStackTrace();
+        // fail silently besides this: it's just a setter
+      }
+    }
+  }
+
+  /**
+   * @return the currentTaskEndDateTimeIsoStr
+   */
+  @Deprecated
+  public String getCurrentTaskEndDateTimeIsoStr() {
+    return this.getTaskById(currentTaskId) != null ? 
+        (this.getTaskById(currentTaskId).getEndDate() != null ? 
+            DateConvert.isoFormat(this.getTaskById(currentTaskId).getEndDate())
+        : null):null;
+  }
+
+  /**
+   * @param currentTaskEndDateTimeIsoStr
+   *          the currentTaskEndDateTimeIsoStr to set
+   */
+  @Deprecated
+  public void setCurrentTaskEndDateTimeIsoStr(
+      String currentTaskEndDateTimeIsoStr) {
+    if (currentTaskEndDateTimeIsoStr != null
+        && !currentTaskEndDateTimeIsoStr.equals("") && 
+        this.getTaskById(currentTaskId) != null) {
+      try {
+        this.getTaskById(currentTaskId).
+          setEndDate(DateConvert.isoParse(currentTaskEndDateTimeIsoStr));
+      } catch (ParseException e) {
+        e.printStackTrace();
+        // fail silently besides this: it's just a setter
+      }
+    }
+  }
+
+  /**
+   * @return the currentTaskStartDateTimeIsoStr
+   */
+  @Deprecated
+  public String getCurrentTaskStartDateTimeIsoStr() {
+    return this.getTaskById(currentTaskId) != null ? 
+        (this.getTaskById(currentTaskId).getStartDate() != null ? DateConvert
+        .isoFormat(this.getTaskById(currentTaskId).getStartDate()) : null):null;
+  }
+
+  /**
+   * @param currentTaskStartDateTimeIsoStr
+   *          the currentTaskStartDateTimeIsoStr to set
+   */
+  @Deprecated
+  public void setCurrentTaskStartDateTimeIsoStr(
+      String currentTaskStartDateTimeIsoStr) {
+    if (currentTaskStartDateTimeIsoStr != null
+        && !currentTaskStartDateTimeIsoStr.equals("") && 
+        this.getTaskById(currentTaskId) != null) {
+      try {
+        this.getTaskById(currentTaskId).setStartDate(DateConvert
+            .isoParse(currentTaskStartDateTimeIsoStr));
+      } catch (ParseException e) {
+        e.printStackTrace();
+        // fail silently besides this: it's just a setter
+      }
+    }
+  }
+  
+  /**
+   * Returns the currently executing {@link WorkflowTask}
+   * part of this instance.
+   * 
+   * @return The currently executing {@link WorkflowTask}
+   * part of this instance.
+   */
+  public WorkflowTask getCurrentTask(){
+    return getTaskById(currentTaskId);
+  }
+  
+
+  /**
+   * @return the timesBlocked
+   */
+  public int getTimesBlocked() {
+    return timesBlocked;
+  }
+
+  /**
+   * @param timesBlocked the timesBlocked to set
+   */
+  public void setTimesBlocked(int timesBlocked) {
+    this.timesBlocked = timesBlocked;
+  }
+  
+  
+  private WorkflowTask getTaskById(String taskId){
+    if(this.workflow.getTasks() != null && 
+        this.workflow.getTasks().size() > 0){
+      for(WorkflowTask task: this.workflow.getTasks()){
+        if(task.getTaskId().equals(taskId)){
+          return task;
+        }
+      }
+      
+      return null;
+    }
+    else return null;
+  }
+
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowInstancePage.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowInstancePage.java
new file mode 100644
index 0000000..9e0a47b
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowInstancePage.java
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class WorkflowInstancePage {
+
+    /* the number of this page */
+    private int pageNum = -1;
+
+    /* the total number of pages in the set */
+    private int totalPages = -1;
+
+    /* the size of the number of workflows on this page */
+    private int pageSize = -1;
+
+    /* the list of produdcts associated with this page */
+    private List pageWorkflows = null;
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>.
+     */
+    public WorkflowInstancePage() {
+        pageWorkflows = new Vector();
+    }
+
+    /**
+     * @param pageNum
+     *            The number of this page.
+     * @param totalPages
+     *            The total number of pages in the set.
+     * @param pageSize
+     *            The size of this page.
+     * @param pageWorkflows
+     *            The workflows associated with this page.
+     */
+    public WorkflowInstancePage(int pageNum, int totalPages, int pageSize,
+            List pageWorkflows) {
+        this.pageNum = pageNum;
+        this.totalPages = totalPages;
+        this.pageSize = pageSize;
+        this.pageWorkflows = pageWorkflows;
+    }
+
+    /**
+     * @return Returns the pageNum.
+     */
+    public int getPageNum() {
+        return pageNum;
+    }
+
+    /**
+     * @param pageNum
+     *            The pageNum to set.
+     */
+    public void setPageNum(int pageNum) {
+        this.pageNum = pageNum;
+    }
+
+    /**
+     * @return Returns the pageWorkflows.
+     */
+    public List getPageWorkflows() {
+        return pageWorkflows;
+    }
+
+    /**
+     * @param pageProducts
+     *            The pageWorkflows to set.
+     */
+    public void setPageWorkflows(List pageWorkflows) {
+        this.pageWorkflows = pageWorkflows;
+    }
+
+    /**
+     * @return Returns the pageSize.
+     */
+    public int getPageSize() {
+        return pageSize;
+    }
+
+    /**
+     * @param pageSize
+     *            The pageSize to set.
+     */
+    public void setPageSize(int pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * @return Returns the totalPages.
+     */
+    public int getTotalPages() {
+        return totalPages;
+    }
+
+    /**
+     * @param totalPages
+     *            The totalPages to set.
+     */
+    public void setTotalPages(int totalPages) {
+        this.totalPages = totalPages;
+    }
+
+    /**
+     * 
+     * @return True if this is the last page in the set, false otherwise.
+     */
+    public boolean isLastPage() {
+        return pageNum == totalPages;
+    }
+
+    /**
+     * 
+     * @return True if this is the fist page of the set, false otherwise.
+     */
+    public boolean isFirstPage() {
+        return pageNum == 1;
+    }
+
+    /**
+     * 
+     * @return A blank, unpopulated {@link WorkflowInstancePage}.
+     */
+    public static WorkflowInstancePage blankPage() {
+        WorkflowInstancePage blank = new WorkflowInstancePage();
+        blank.setPageNum(0);
+        blank.setTotalPages(0);
+        blank.setPageSize(0);
+        return blank;
+    }
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowStatus.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowStatus.java
new file mode 100644
index 0000000..832b75a
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowStatus.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.structs;
+
+/**
+ * 
+ * @author ahart
+ * @version $Revision$
+ *
+ * <p>Default Workflow Status Strings</p>.
+ */
+public interface WorkflowStatus {
+
+    /* A set of final Strings representing the status of a workflow, or Process */
+    public static final String STARTED = "STARTED";
+
+    public static final String FINISHED = "FINISHED";
+
+    public static final String PAUSED = "PAUSED";
+
+    public static final String ERROR = "ERROR";
+    
+    public static final String QUEUED = "QUEUED";
+    
+    public static final String CREATED = "CREATED";
+    
+    public static final String RESMGR_SUBMIT = "RSUBMIT";
+    
+    public static final String METADATA_MISSING = "METMISS";
+    
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowTask.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowTask.java
new file mode 100644
index 0000000..ecd80a5
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowTask.java
@@ -0,0 +1,341 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.Date;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * 
+ * A Workflow task, or job, or process.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class WorkflowTask {
+
+  /* a unique ID for the task */
+  protected String taskId = null;
+
+  /* the name of the task */
+  protected String taskName = null;
+
+  /* the static configuration parameters for the task */
+  protected WorkflowTaskConfiguration taskConfig = null;
+
+  /* pre conditions for this task */
+  protected List<WorkflowCondition> preConditions = null;
+
+  /* post conditions for this task */
+  protected List<WorkflowCondition> postConditions = null;
+
+  /* the actual work performing portion of this WorkflowTask */
+  protected String taskInstanceClassName = null;
+
+  /* the order for this task */
+  protected int order = -1;
+
+  /* the list of required metadata fields that need to be passed into this task */
+  protected List requiredMetFields = null;
+
+  private Date startDate;
+
+  private Date endDate;
+
+  /**
+   * <p>
+   * Default Constructor.
+   * </p>
+   * 
+   */
+  public WorkflowTask() {
+    this(null, null, new WorkflowTaskConfiguration(),
+        new Vector<WorkflowCondition>(), new Vector<WorkflowCondition>(),
+        new Vector<String>(), null, null, null, -1);
+  }
+
+  /**
+   * 
+   * This constructor is now deprecated in Apache OODT 0.4, in favor of
+   * {@link #WorkflowTask(String, String, WorkflowTaskConfiguration, List, List, String, int)}
+   * that explicitly specifies pre- and post- {@link WorkflowCondition}s. As
+   * used, this method will set the pre-conditions via the passed in
+   * {@link List} of {@link WorkflowCondition}s only.
+   * 
+   * @param taskId
+   *          The unique ID for this WorkflowTask.
+   * @param taskName
+   *          The display name for this WorkflowTask.
+   * @param taskConfig
+   *          The static configuration parameters for this WorkflowTask.
+   * @param conditions
+   *          The List of conditions attached to this WorkflowTask (if any).
+   * @param taskInstanceClassName
+   *          The instance class name for this WorkflowTask.
+   * @param order
+   *          The order in which this WorkflowTask is executed within a
+   *          Workflow.
+   */
+  @Deprecated
+  public WorkflowTask(String taskId, String taskName,
+      WorkflowTaskConfiguration taskConfig, List conditions,
+      String taskInstanceClassName, int order) {
+    this(taskId, taskName, taskConfig, conditions,
+        new Vector<WorkflowCondition>(), new Vector<String>(), null,
+        null, null, -1);
+  }
+
+  /**
+   * Constructs a new WorkflowTask.
+   * 
+   * @param taskId
+   *          The identifier for this task.
+   * @param taskName
+   *          The name for this task.
+   * @param taskConfig
+   *          The associated {@link WorkflowTaskConfiguration}.
+   * @param requiredMetFields
+   *          A {@link List} of String met field names that this task requires.
+   * @param preConditions
+   *          The {@link List} of pre-{@link WorkflowCondition}s.
+   * @param postConditions
+   *          The {@link List} of post-{@link WorkflowCondition}s.
+   * @param taskInstanceClassName
+   *          The implementing class name of this WorkflowTask.
+   * @param startDate
+   *          The time that this task started executing.
+   * @param endDate
+   *          The time that this task stopped executing.
+   * @param order
+   *          The order in which this task should be run.
+   */
+  public WorkflowTask(String taskId, String taskName,
+      WorkflowTaskConfiguration taskConfig,
+      List<WorkflowCondition> preConditions,
+      List<WorkflowCondition> postConditions, List<String> requiredMetFields,
+      String taskInstanceClassName, Date startDate, Date endDate, int order) {
+    this.taskId = taskId;
+    this.taskName = taskName;
+    this.taskConfig = taskConfig;
+    this.requiredMetFields = requiredMetFields;
+    this.preConditions = preConditions;
+    this.postConditions = postConditions;
+    this.taskInstanceClassName = taskInstanceClassName;
+    this.startDate = startDate;
+    this.endDate = endDate;
+    this.order = order;
+
+  }
+
+  /**
+   * @return Returns the taskConfig.
+   */
+  public WorkflowTaskConfiguration getTaskConfig() {
+    return taskConfig;
+  }
+
+  /**
+   * @return the preConditions
+   */
+  public List<WorkflowCondition> getPreConditions() {
+    return preConditions;
+  }
+
+  /**
+   * @param preConditions
+   *          the preConditions to set
+   */
+  public void setPreConditions(List<WorkflowCondition> preConditions) {
+    this.preConditions = preConditions;
+  }
+
+  /**
+   * @return the postConditions
+   */
+  public List<WorkflowCondition> getPostConditions() {
+    return postConditions;
+  }
+
+  /**
+   * @param postConditions
+   *          the postConditions to set
+   */
+  public void setPostConditions(List<WorkflowCondition> postConditions) {
+    this.postConditions = postConditions;
+  }
+
+  /**
+   * @param taskConfig
+   *          The taskConfig to set.
+   */
+  public void setTaskConfig(WorkflowTaskConfiguration taskConfig) {
+    this.taskConfig = taskConfig;
+  }
+
+  /**
+   * @return Returns the taskId.
+   */
+  public String getTaskId() {
+    return taskId;
+  }
+
+  /**
+   * @param taskId
+   *          The taskId to set.
+   */
+  public void setTaskId(String taskId) {
+    this.taskId = taskId;
+  }
+
+  /**
+   * @return Returns the taskInstanceClassName.
+   */
+  public String getTaskInstanceClassName() {
+    return taskInstanceClassName;
+  }
+
+  /**
+   * @param taskInstanceClassName
+   *          The taskInstanceClassName to set.
+   */
+  public void setTaskInstanceClassName(String taskInstanceClassName) {
+    this.taskInstanceClassName = taskInstanceClassName;
+  }
+
+  /**
+   * @return Returns the taskName.
+   */
+  public String getTaskName() {
+    return taskName;
+  }
+
+  /**
+   * @param taskName
+   *          The taskName to set.
+   */
+  public void setTaskName(String taskName) {
+    this.taskName = taskName;
+  }
+
+  /**
+   * This method is deprecated in favor of using {@link #getPreConditions()} or
+   * {@link #getPostConditions()}. As called, will return a union of the Tasks's
+   * pre- and post- {@link WorkflowCondition}s.
+   * 
+   * @return A {@link List} of {@link WorkflowCondition}s associated with this
+   *         task.
+   */
+  @Deprecated
+  public List getConditions() {
+    List conditions = new Vector();
+    conditions.addAll(this.preConditions);
+    conditions.addAll(this.postConditions);
+    return conditions;
+  }
+
+  /**
+   * 
+   * This method is depcreated in favor of {@link #setPostConditions(List)} and
+   * {@link #setPreConditions(List)}, for explicitly setting the pre or post
+   * conditions of this WorkflowTask.
+   * 
+   * To keep back compat, this method in its deprecated form will set the
+   * WorkflowTask pre-conditions, as was the case before.
+   * 
+   * Sets the {@link List} of {@link WorkflowCondition}s associated with this
+   * task.
+   * 
+   * @param conditions
+   *          The condition {@link List}.
+   */
+  @Deprecated
+  public void setConditions(List conditions) {
+    this.preConditions = conditions;
+  }
+
+  /**
+   * @return Returns the order. Don't use this method anymore -- order is not
+   *         relevant to the control flow which is acutally controlled now by
+   *         the surrounding workflow model.
+   */
+  @Deprecated
+  public int getOrder() {
+    return order;
+  }
+
+  /**
+   * Don't use this method anymore -- order is not relevant to the control flow
+   * which is acutally controlled now by the surrounding workflow model.
+   * 
+   * @param order
+   *          The order to set.
+   */
+  @Deprecated
+  public void setOrder(int order) {
+    this.order = order;
+  }
+
+  /**
+   * @return the requiredMetFields
+   */
+  public List getRequiredMetFields() {
+    return requiredMetFields;
+  }
+
+  /**
+   * @param requiredMetFields
+   *          the requiredMetFields to set
+   */
+  public void setRequiredMetFields(List requiredMetFields) {
+    this.requiredMetFields = requiredMetFields;
+  }
+
+  /**
+   * @return the startDate
+   */
+  public Date getStartDate() {
+    return startDate;
+  }
+
+  /**
+   * @param startDate
+   *          the startDate to set
+   */
+  public void setStartDate(Date startDate) {
+    this.startDate = startDate;
+  }
+
+  /**
+   * @return the endDate
+   */
+  public Date getEndDate() {
+    return endDate;
+  }
+
+  /**
+   * @param endDate
+   *          the endDate to set
+   */
+  public void setEndDate(Date endDate) {
+    this.endDate = endDate;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowTaskConfiguration.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowTaskConfiguration.java
new file mode 100644
index 0000000..e55a894
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowTaskConfiguration.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.Properties;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>A specialized set of metadata properties for a {@link WorkflowTask}.</p>
+ *
+ */
+public class WorkflowTaskConfiguration {
+
+	/* the task configuration properties */
+	private Properties taskProperties = null;
+	
+	/**
+	 * <p>
+	 * Default Constructor
+	 * </p>.
+	 */
+	public WorkflowTaskConfiguration() {
+		taskProperties = new Properties();
+	}
+
+	/**
+	 * <p>
+	 * Construct a new WorkflowTaskConfiguration from a java Properties object.
+	 * </p>
+	 * 
+	 * @param properties
+	 *            The task configuration properties.
+	 */
+	public WorkflowTaskConfiguration(Properties properties) {
+		taskProperties = properties;
+	}
+
+	/**
+	 * <p>
+	 * Adds the property denoted by the given <code>name></code> and
+	 * <code>value</code>.
+	 * </p>
+	 * 
+	 * @param name
+	 *            The property name.
+	 * @param value
+	 *            The property value.
+	 */
+	public void addConfigProperty(String name, String value) {
+		taskProperties.setProperty(name, value);
+	}
+
+	/**
+	 * 
+	 * @param propName
+	 *            The property to get the value for.
+	 * @return The String property value for the specified propName.
+	 */
+	public String getProperty(String propName) {
+		return taskProperties.getProperty(propName);
+	}
+
+	/**
+	 * 
+	 * @return The {@link Properties} for configuring this WorkflowTask.
+	 */
+	public Properties getProperties() {
+		return taskProperties;
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowTaskInstance.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowTaskInstance.java
new file mode 100644
index 0000000..0b03776
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/WorkflowTaskInstance.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.structs;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.exceptions.WorkflowTaskInstanceException;
+
+/**
+ * @author mattmann
+ * @version $Revsion$
+ * 
+ * <p>The part of a WorkflowTask that is responsible
+ * for actually doing the work.</p>
+ */
+public interface WorkflowTaskInstance {
+
+    /**
+     * <p>
+     * Runs the Task with the specified metadata context.
+     * </p>
+     * 
+     * @param metadata
+     *            The TaskContext of metadata that is shared between the tasks.
+     *            
+     * @param config The static configuration metadata for this task.
+     */
+    public void run(Metadata metadata, WorkflowTaskConfiguration config) throws WorkflowTaskInstanceException;
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/exceptions/EngineException.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/exceptions/EngineException.java
new file mode 100644
index 0000000..cb2544d
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/exceptions/EngineException.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.structs.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>An exception throw by the Workflow Engine.</p>
+ * 
+ */
+public class EngineException extends Exception {
+
+    /* serial version UID */
+    private static final long serialVersionUID = 3690762773826910000L;
+
+    /**
+     * 
+     */
+    public EngineException() {
+        super();
+        // TODO Auto-generated constructor stub
+    }
+
+    /**
+     * @param message
+     */
+    public EngineException(String message) {
+        super(message);
+        // TODO Auto-generated constructor stub
+    }
+
+    /**
+     * @param cause
+     */
+    public EngineException(Throwable cause) {
+        super(cause);
+        // TODO Auto-generated constructor stub
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public EngineException(String message, Throwable cause) {
+        super(message, cause);
+        // TODO Auto-generated constructor stub
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/exceptions/InstanceRepositoryException.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/exceptions/InstanceRepositoryException.java
new file mode 100644
index 0000000..28f921e
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/exceptions/InstanceRepositoryException.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.structs.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>An exception thrown by the {@link WorkflowInstanceRepository}</p>.
+ */
+public class InstanceRepositoryException extends Exception {
+
+	/* serial version UID */
+	private static final long serialVersionUID = -4956612049874952669L;
+
+	/**
+	 * 
+	 */
+	public InstanceRepositoryException() {
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public InstanceRepositoryException(String arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public InstanceRepositoryException(Throwable arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 * @param arg1
+	 */
+	public InstanceRepositoryException(String arg0, Throwable arg1) {
+		super(arg0, arg1);
+		// TODO Auto-generated constructor stub
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/exceptions/RepositoryException.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/exceptions/RepositoryException.java
new file mode 100644
index 0000000..0ed939c
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/exceptions/RepositoryException.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.structs.exceptions;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ *
+ * <p>An exception thrown by the workflow repository.</p>
+ *
+ */
+public class RepositoryException extends Exception {
+
+    /* serial version UID */
+	private static final long serialVersionUID = 7867039774935834472L;
+
+	/**
+	 * 
+	 */
+	public RepositoryException() {
+		super();
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public RepositoryException(String arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 * @param arg1
+	 */
+	public RepositoryException(String arg0, Throwable arg1) {
+		super(arg0, arg1);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * @param arg0
+	 */
+	public RepositoryException(Throwable arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/exceptions/WorkflowTaskInstanceException.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/exceptions/WorkflowTaskInstanceException.java
new file mode 100644
index 0000000..593c474
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/structs/exceptions/WorkflowTaskInstanceException.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.structs.exceptions;
+
+/**
+ * @author bfoster
+ * @version $Revision$
+ *
+ * <p>An exception thrown by {@link WorkflowTaskInstance}</p>
+ */
+public class WorkflowTaskInstanceException extends Exception {
+
+    private static final long serialVersionUID = 2666346581066070156L;
+
+    public WorkflowTaskInstanceException() {}
+
+    public WorkflowTaskInstanceException(String msg) {
+        super(msg);
+    }
+
+    public WorkflowTaskInstanceException(Throwable throwable) {
+        super(throwable);
+    }
+
+    public WorkflowTaskInstanceException(String msg, Throwable throwable) {
+        super(msg, throwable);
+    }
+
+    
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/system/XmlRpcWorkflowManager.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/system/XmlRpcWorkflowManager.java
new file mode 100644
index 0000000..164da18
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/system/XmlRpcWorkflowManager.java
@@ -0,0 +1,724 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.system;
+
+//OODT static imports
+import static org.apache.oodt.cas.workflow.util.GenericWorkflowObjectFactory.getWorkflowEngineFromClassName;
+import static org.apache.oodt.cas.workflow.util.GenericWorkflowObjectFactory.getWorkflowRepositoryFromClassName;
+
+//Apache imports
+import org.apache.xmlrpc.WebServer;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.util.XmlRpcStructFactory;
+import org.apache.oodt.cas.workflow.engine.ThreadPoolWorkflowEngineFactory;
+import org.apache.oodt.cas.workflow.engine.WorkflowEngine;
+import org.apache.oodt.cas.workflow.repository.DataSourceWorkflowRepositoryFactory;
+import org.apache.oodt.cas.workflow.repository.WorkflowRepository;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.exceptions.EngineException;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+import org.apache.oodt.cas.workflow.structs.exceptions.RepositoryException;
+import org.apache.oodt.cas.metadata.Metadata;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+//Google imports
+import com.google.common.base.Preconditions;
+
+/**
+ * An XML RPC-based Workflow manager.
+ *
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public class XmlRpcWorkflowManager {
+
+   private static final Logger LOG = Logger.getLogger(XmlRpcWorkflowManager.class.getName());
+
+   public static final int DEFAULT_WEB_SERVER_PORT = 9001;
+   public static final String XML_RPC_HANDLER_NAME = "workflowmgr";
+
+   public static final String PROPERTIES_FILE_PROPERTY = "org.apache.oodt.cas.workflow.properties";
+   public static final String WORKFLOW_ENGINE_FACTORY_PROPERTY = "workflow.engine.factory";
+   public static final String ENGINE_RUNNER_FACTORY_PROPERTY = "workflow.engine.runner.factory";
+   public static final String WORKFLOW_REPOSITORY_FACTORY_PROPERTY = "workflow.repo.factory";
+
+   private final int webServerPort;
+   private WebServer webServer;
+   private final WorkflowEngine engine;
+   private WorkflowRepository repo;
+
+   public XmlRpcWorkflowManager() {
+      this(DEFAULT_WEB_SERVER_PORT);
+   }
+
+   public XmlRpcWorkflowManager(int port) {
+      Preconditions.checkArgument(port > 0, "Must specify a port greater than 0");
+      webServerPort = port;
+
+      engine = getWorkflowEngineFromProperty();
+      engine.setWorkflowManagerUrl(safeGetUrlFromString("http://"
+            + getHostname() + ":" + this.webServerPort));
+      repo = getWorkflowRepositoryFromProperty();
+
+      // start up the web server
+      webServer = new WebServer(webServerPort);
+      webServer.addHandler(XML_RPC_HANDLER_NAME, this);
+      webServer.start();
+
+      LOG.log(Level.INFO, "Workflow Manager started by "
+            + System.getProperty("user.name", "unknown"));
+   }
+
+   public boolean shutdown() {
+      if (webServer != null) {
+         webServer.shutdown();
+         webServer = null;
+         return true;
+      } else
+         return false;
+   }
+
+   public boolean refreshRepository()
+       throws RepositoryException {
+     repo = getWorkflowRepositoryFromProperty();
+     return true;
+   }
+
+  public String executeDynamicWorkflow(Vector<String> taskIds, Hashtable metadata)
+      throws RepositoryException, EngineException {
+    if (taskIds == null || (taskIds != null && taskIds.size() == 0))
+      throw new RepositoryException(
+          "Must specify task identifiers to build dynamic workflows!");
+
+    Workflow dynamicWorkflow = new Workflow();
+
+    for (String taskId : taskIds) {
+      WorkflowTask task = this.repo.getWorkflowTaskById(taskId);
+      if (task == null)
+        throw new RepositoryException("Dynamic workflow task: [" + taskId
+            + "] is not defined!");
+      dynamicWorkflow.getTasks().add(task);
+    }
+
+    dynamicWorkflow.setId(this.repo.addWorkflow(dynamicWorkflow));
+    dynamicWorkflow.setName("Dynamic Workflow-" + dynamicWorkflow.getId());
+
+    Metadata met = new Metadata();
+    met.addMetadata(metadata);
+
+    WorkflowInstance inst = this.engine.startWorkflow(dynamicWorkflow, met);
+    return inst.getId();
+  }
+
+    public Vector getRegisteredEvents() throws RepositoryException {
+
+        List events = null;
+        Vector eventsVector = new Vector();
+
+        try {
+            events = repo.getRegisteredEvents();
+
+            if (events != null) {
+                for (Iterator i = events.iterator(); i.hasNext();) {
+                    eventsVector.add(i.next());
+                }
+
+            }
+
+            return eventsVector;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RepositoryException(
+                    "Exception getting registered events from repository: Message: "
+                            + e.getMessage());
+        }
+
+    }
+
+    public Hashtable getFirstPage() {
+    	WorkflowInstancePage page = engine.getInstanceRepository()
+                .getFirstPage();
+        if (page != null) {
+            populateWorkflows(page.getPageWorkflows());
+            return XmlRpcStructFactory.getXmlRpcWorkflowInstancePage(page);
+        } else
+            return XmlRpcStructFactory
+                    .getXmlRpcWorkflowInstancePage(WorkflowInstancePage
+                            .blankPage());
+    }
+
+    public Hashtable getNextPage(Hashtable currentPage) {
+        // first unpack current page
+        WorkflowInstancePage currPage = XmlRpcStructFactory
+                .getWorkflowInstancePageFromXmlRpc(currentPage);
+        WorkflowInstancePage page = engine.getInstanceRepository().getNextPage(
+                currPage);
+        if (page != null) {
+            populateWorkflows(page.getPageWorkflows());
+            return XmlRpcStructFactory.getXmlRpcWorkflowInstancePage(page);
+        } else
+            return XmlRpcStructFactory
+                    .getXmlRpcWorkflowInstancePage(WorkflowInstancePage
+                            .blankPage());
+    }
+
+    public Hashtable getPrevPage(Hashtable currentPage) {
+        // first unpack current page
+        WorkflowInstancePage currPage = XmlRpcStructFactory
+                .getWorkflowInstancePageFromXmlRpc(currentPage);
+        WorkflowInstancePage page = engine.getInstanceRepository().getPrevPage(
+                currPage);
+        if (page != null) {
+            populateWorkflows(page.getPageWorkflows());
+            return XmlRpcStructFactory.getXmlRpcWorkflowInstancePage(page);
+        } else
+            return XmlRpcStructFactory
+                    .getXmlRpcWorkflowInstancePage(WorkflowInstancePage
+                            .blankPage());
+    }
+
+    public Hashtable getLastPage() {
+        WorkflowInstancePage page = engine.getInstanceRepository()
+                .getLastPage();
+        if (page != null) {
+            populateWorkflows(page.getPageWorkflows());
+            return XmlRpcStructFactory.getXmlRpcWorkflowInstancePage(page);
+        } else
+            return XmlRpcStructFactory
+                    .getXmlRpcWorkflowInstancePage(WorkflowInstancePage
+                            .blankPage());
+    }
+
+    public Hashtable paginateWorkflowInstances(int pageNum, String status)
+            throws InstanceRepositoryException {
+        WorkflowInstancePage page = engine.getInstanceRepository()
+                .getPagedWorkflows(pageNum, status);
+        if (page != null) {
+            populateWorkflows(page.getPageWorkflows());
+            return XmlRpcStructFactory.getXmlRpcWorkflowInstancePage(page);
+        } else
+            return XmlRpcStructFactory
+                    .getXmlRpcWorkflowInstancePage(WorkflowInstancePage
+                            .blankPage());
+
+    }
+
+    public Hashtable paginateWorkflowInstances(int pageNum)
+            throws InstanceRepositoryException {
+        WorkflowInstancePage page = engine.getInstanceRepository()
+                .getPagedWorkflows(pageNum);
+        if (page != null) {
+            populateWorkflows(page.getPageWorkflows());
+            return XmlRpcStructFactory.getXmlRpcWorkflowInstancePage(page);
+        } else
+            return XmlRpcStructFactory
+                    .getXmlRpcWorkflowInstancePage(WorkflowInstancePage
+                            .blankPage());
+    }
+
+    public Hashtable getWorkflowInstanceMetadata(String wInstId) {
+        Metadata met = engine.getWorkflowInstanceMetadata(wInstId);
+        return met.getHashtable();
+    }
+
+    public Vector getWorkflowsByEvent(String eventName)
+            throws RepositoryException {
+        List workflows = null;
+        Vector workflowList = new Vector();
+
+        try {
+            workflows = repo.getWorkflowsForEvent(eventName);
+
+            if (workflows != null) {
+                for (Iterator i = workflows.iterator(); i.hasNext();) {
+                    Workflow w = (Workflow) i.next();
+                    Hashtable workflow = XmlRpcStructFactory
+                            .getXmlRpcWorkflow(w);
+                    workflowList.add(workflow);
+                }
+            }
+
+            return workflowList;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RepositoryException(
+                    "Exception getting workflows for event: " + eventName
+                            + " from repository: Message: " + e.getMessage());
+        }
+    }
+
+    public boolean handleEvent(String eventName, Hashtable metadata)
+            throws RepositoryException, EngineException {
+        LOG.log(Level.INFO, "WorkflowManager: Received event: " + eventName);
+
+        List workflows = null;
+
+        try {
+            workflows = repo.getWorkflowsForEvent(eventName);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RepositoryException(
+                    "Exception getting workflows associated with event: "
+                            + eventName + ": Message: " + e.getMessage());
+        }
+
+        if (workflows != null) {
+            for (Iterator i = workflows.iterator(); i.hasNext();) {
+                Workflow w = (Workflow) i.next();
+                LOG.log(Level.INFO, "WorkflowManager: Workflow " + w.getName()
+                        + " retrieved for event " + eventName);
+
+                Metadata m = new Metadata();
+                m.addMetadata(metadata);
+
+                try {
+                    engine.startWorkflow(w, m);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    throw new EngineException(
+                            "Engine exception when starting workflow: "
+                                    + w.getName() + ": Message: "
+                                    + e.getMessage());
+                }
+            }
+            return true;
+        } else
+            return false;
+    }
+
+    public Hashtable getWorkflowInstanceById(String wInstId)
+            throws EngineException {
+        WorkflowInstance inst = null;
+
+        try {
+            inst = engine.getInstanceRepository().getWorkflowInstanceById(
+                    wInstId);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Error obtaining workflow instance with ID: [" + wInstId
+                            + "]: Message: " + e.getMessage());
+            inst = new WorkflowInstance();
+        }
+
+        return XmlRpcStructFactory.getXmlRpcWorkflowInstance(inst);
+
+    }
+
+    public synchronized boolean stopWorkflowInstance(String workflowInstId) {
+        engine.stopWorkflow(workflowInstId);
+        return true;
+    }
+
+    public synchronized boolean pauseWorkflowInstance(String workflowInstId) {
+        engine.pauseWorkflowInstance(workflowInstId);
+        return true;
+    }
+
+    public synchronized boolean resumeWorkflowInstance(String workflowInstId) {
+        engine.resumeWorkflowInstance(workflowInstId);
+        return true;
+    }
+
+    public double getWorkflowWallClockMinutes(String workflowInstId) {
+        return engine.getWallClockMinutes(workflowInstId);
+    }
+
+    public double getWorkflowCurrentTaskWallClockMinutes(String workflowInstId) {
+        return engine.getCurrentTaskWallClockMinutes(workflowInstId);
+    }
+
+    public int getNumWorkflowInstancesByStatus(String status) throws InstanceRepositoryException {
+        return engine.getInstanceRepository().getNumWorkflowInstancesByStatus(
+                status);
+    }
+
+    public int getNumWorkflowInstances() throws InstanceRepositoryException {
+        return engine.getInstanceRepository().getNumWorkflowInstances();
+    }
+
+    public Vector getWorkflowInstancesByStatus(String status)
+            throws EngineException {
+        List workflowInsts = null;
+
+        Vector workflowInstances = new Vector();
+
+        try {
+            workflowInsts = engine.getInstanceRepository()
+                    .getWorkflowInstancesByStatus(status);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception getting workflow instances by status: Message: ["
+                            + e.getMessage() + "]");
+            return workflowInstances;
+        }
+
+        if (workflowInsts != null) {
+            LOG.log(Level.INFO,
+                    "Getting workflow instances by status: retrieved: "
+                            + workflowInsts.size() + " instances");
+
+            try {
+                for (Iterator i = workflowInsts.iterator(); i.hasNext();) {
+                    WorkflowInstance wInst = (WorkflowInstance) i.next();
+                    // pick up the description of the workflow
+                    Workflow wDesc = repo.getWorkflowById(wInst.getWorkflow()
+                            .getId());
+                    // TODO: hack for now, fix this, we shouldn't have to cast
+                    // here, bad
+                    // design
+                    if(wDesc == null){
+                      //Possible dynamic workflow for instance
+                      //reconsitute it from cache
+                      wDesc = wInst.getWorkflow();
+                      repo.addWorkflow(wDesc);
+                    }
+                    wInst.setWorkflow(wDesc);
+                    Hashtable workflowInstance = XmlRpcStructFactory
+                            .getXmlRpcWorkflowInstance(wInst);
+                    workflowInstances.add(workflowInstance);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new EngineException(
+                        "Exception getting workflow instances by statusfrom workflow engine: Message: "
+                                + e.getMessage());
+            }
+        }
+
+        return workflowInstances;
+    }
+
+    public Vector getWorkflowInstances() throws EngineException {
+        List workflowInsts = null;
+
+        Vector workflowInstances = new Vector();
+
+        try {
+            workflowInsts = engine.getInstanceRepository()
+                    .getWorkflowInstances();
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING,
+                    "Exception getting workflow instances: Message: ["
+                            + e.getMessage() + "]");
+            return workflowInstances;
+        }
+
+        if (workflowInsts != null) {
+            LOG.log(Level.INFO, "Getting workflow instances: retrieved: "
+                    + workflowInsts.size() + " instances");
+
+            try {
+                for (Iterator i = workflowInsts.iterator(); i.hasNext();) {
+                    WorkflowInstance wInst = (WorkflowInstance) i.next();
+                    // pick up the description of the workflow
+                    Workflow wDesc = repo.getWorkflowById(wInst.getWorkflow()
+                            .getId());
+                    if(wDesc == null){
+                      //possible dynamic workflow
+                      //reconsitute it from cached instance
+                      wDesc = wInst.getWorkflow();
+                      //now save it
+                      repo.addWorkflow(wDesc);
+
+                    }
+                    // TODO: hack for now, fix this, we shouldn't have to cast
+                    // here, bad
+                    // design
+                    wInst.setWorkflow(wDesc);
+                    Hashtable workflowInstance = XmlRpcStructFactory
+                            .getXmlRpcWorkflowInstance(wInst);
+                    workflowInstances.add(workflowInstance);
+                }
+                return workflowInstances;
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new EngineException(
+                        "Exception getting workflow instances from workflow engine: Message: "
+                                + e.getMessage());
+            }
+        } else
+            return null;
+    }
+
+    public Vector getWorkflows() throws RepositoryException {
+        List workflowList = repo.getWorkflows();
+        Vector workflows = new Vector();
+
+        if (workflowList != null) {
+            LOG.log(Level.INFO, "Getting workflows: retrieved: "
+                    + workflowList.size() + " workflows");
+
+            try {
+                for (Iterator i = workflowList.iterator(); i.hasNext();) {
+                    Workflow w = (Workflow) i.next();
+                    Hashtable workflow = XmlRpcStructFactory
+                            .getXmlRpcWorkflow(w);
+                    workflows.add(workflow);
+                }
+
+                return workflows;
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new RepositoryException(
+                        "Exception getting workflows from repository: Message: "
+                                + e.getMessage());
+            }
+
+        } else
+            return null;
+
+    }
+
+    public Hashtable getTaskById(String taskId) throws RepositoryException {
+        try {
+            WorkflowTask t = repo.getWorkflowTaskById(taskId);
+            return XmlRpcStructFactory.getXmlRpcWorkflowTask(t);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RepositoryException(
+                    "Exception getting task by id: Message: " + e.getMessage());
+
+        }
+    }
+
+    public Hashtable getConditionById(String conditionId)
+            throws RepositoryException {
+        try {
+            WorkflowCondition c = repo.getWorkflowConditionById(conditionId);
+            return XmlRpcStructFactory.getXmlRpcWorkflowCondition(c);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RepositoryException(
+                    "Exception getting condition by id: Message: "
+                            + e.getMessage());
+        }
+    }
+
+    public Hashtable getWorkflowById(String workflowId)
+            throws RepositoryException {
+        try {
+            Workflow workflow = repo.getWorkflowById(workflowId);
+            return XmlRpcStructFactory.getXmlRpcWorkflow(workflow);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RepositoryException(
+                    "Exception getting workflow by id from the repository: Message: "
+                            + e.getMessage());
+        }
+    }
+
+    public synchronized boolean updateMetadataForWorkflow(
+            String workflowInstId, Hashtable metadata) {
+        Metadata met = new Metadata();
+        met.addMetadata(metadata);
+        return this.engine.updateMetadata(workflowInstId, met);
+    }
+
+    public synchronized boolean updateWorkflowInstance(Hashtable workflowInst) {
+        WorkflowInstance wInst = XmlRpcStructFactory
+                .getWorkflowInstanceFromXmlRpc(workflowInst);
+        return doUpdateWorkflowInstance(wInst);
+
+    }
+
+    public synchronized boolean setWorkflowInstanceCurrentTaskStartDateTime(
+            String wInstId, String startDateTimeIsoStr) {
+        WorkflowInstance wInst = null;
+        try {
+            wInst = this.engine.getInstanceRepository()
+                    .getWorkflowInstanceById(wInstId);
+        } catch (InstanceRepositoryException e) {
+            e.printStackTrace();
+            return false;
+        }
+        wInst.setCurrentTaskStartDateTimeIsoStr(startDateTimeIsoStr);
+        return doUpdateWorkflowInstance(wInst);
+    }
+
+    public synchronized boolean setWorkflowInstanceCurrentTaskEndDateTime(
+            String wInstId, String endDateTimeIsoStr) {
+        WorkflowInstance wInst = null;
+        try {
+            wInst = this.engine.getInstanceRepository()
+                    .getWorkflowInstanceById(wInstId);
+        } catch (InstanceRepositoryException e) {
+            e.printStackTrace();
+            return false;
+        }
+        wInst.setCurrentTaskEndDateTimeIsoStr(endDateTimeIsoStr);
+        return doUpdateWorkflowInstance(wInst);
+    }
+
+    public synchronized boolean updateWorkflowInstanceStatus(
+            String workflowInstanceId, String status) throws Exception {
+        WorkflowInstance wInst = null;
+        try {
+            wInst = engine.getInstanceRepository().getWorkflowInstanceById(
+                    workflowInstanceId);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw e;
+        }
+
+        wInst.setStatus(status);
+        return doUpdateWorkflowInstance(wInst);
+    }
+
+    public static void main(String[] args) throws Exception {
+        int portNum = -1;
+        String usage = "XmlRpcWorkflowManager --portNum <port number for xml rpc service>\n";
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--portNum")) {
+                portNum = Integer.parseInt(args[++i]);
+            }
+        }
+
+        if (portNum == -1) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        loadProperties();
+        XmlRpcWorkflowManager manager = new XmlRpcWorkflowManager(portNum);
+
+        for (;;)
+            try {
+                Thread.currentThread().join();
+            } catch (InterruptedException ignore) {
+            }
+    }
+
+    public static void loadProperties() throws FileNotFoundException, IOException {
+       String configFile = System.getProperty(PROPERTIES_FILE_PROPERTY);
+       if (configFile != null) {
+          LOG.log(Level.INFO,
+                "Loading Workflow Manager Configuration Properties from: ["
+                      + configFile + "]");
+          System.getProperties().load(new FileInputStream(new File(
+                configFile)));
+       }
+    }
+
+    private static WorkflowEngine getWorkflowEngineFromProperty() {
+       return getWorkflowEngineFromClassName(System.getProperty(
+             WORKFLOW_ENGINE_FACTORY_PROPERTY,
+             ThreadPoolWorkflowEngineFactory.class.getCanonicalName()));
+    }
+
+    private static WorkflowRepository getWorkflowRepositoryFromProperty() {
+       return getWorkflowRepositoryFromClassName(System.getProperty(
+             WORKFLOW_REPOSITORY_FACTORY_PROPERTY,
+             DataSourceWorkflowRepositoryFactory.class.getCanonicalName()));
+    }
+
+    private String getHostname() {
+        try {
+            // Get hostname by textual representation of IP address
+            InetAddress addr = InetAddress.getLocalHost();
+            // Get the host name
+            String hostname = addr.getHostName();
+            return hostname;
+        } catch (UnknownHostException e) {
+        }
+        return null;
+    }
+
+    private URL safeGetUrlFromString(String urlStr) {
+        try {
+            return new URL(urlStr);
+        } catch (MalformedURLException e) {
+            return null;
+        }
+    }
+
+    private boolean doUpdateWorkflowInstance(WorkflowInstance wInst) {
+        try {
+            engine.getInstanceRepository().updateWorkflowInstance(wInst);
+            return true;
+        } catch (InstanceRepositoryException e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    private void populateWorkflows(List wInsts) {
+        if (wInsts != null && wInsts.size() > 0) {
+            for (Iterator i = wInsts.iterator(); i.hasNext();) {
+                WorkflowInstance wInst = (WorkflowInstance) i.next();
+                if(wInst.getWorkflow() == null || 
+                	(wInst.getWorkflow() != null && 
+                	  (wInst.getWorkflow().getName() == null || 
+                	   wInst.getWorkflow().getId() == null))){
+                    wInst.setWorkflow(safeGetWorkflowById(wInst.getWorkflow()
+                            .getId()));                	
+                }
+                else{
+                	// check to see if the workflow exists in the 
+                	// repo
+                	try {
+						if(repo.getWorkflowById(wInst.getWorkflow().getId()) == null){
+							repo.addWorkflow(wInst.getWorkflow());
+						}
+					} catch (RepositoryException e) {
+						LOG.log(Level.WARNING, "Attempting to look up workflow: ["+wInst.getWorkflow()
+								.getId()+"] in populate workflows. Message: "+e.getMessage());
+						e.printStackTrace();
+					}
+
+                }
+            }
+        }
+    }
+
+    private Workflow safeGetWorkflowById(String workflowId) {
+        try {
+            return repo.getWorkflowById(workflowId);
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Error getting workflow by its id: ["
+                    + workflowId + "]: Message: " + e.getMessage());
+            return new Workflow();
+        }
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/system/XmlRpcWorkflowManagerClient.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/system/XmlRpcWorkflowManagerClient.java
new file mode 100644
index 0000000..1f58e9f
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/system/XmlRpcWorkflowManagerClient.java
@@ -0,0 +1,713 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.system;
+
+//APACHE imports
+import org.apache.xmlrpc.XmlRpcClient;
+import org.apache.xmlrpc.XmlRpcException;
+
+//JDK imports
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.List;
+import java.util.Iterator;
+import java.util.logging.Logger;
+import java.io.IOException;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.util.XmlRpcStructFactory;
+import org.apache.oodt.cas.cli.CmdLineUtility;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * The XML RPC based workflow manager client.
+ * </p>
+ * 
+ */
+public class XmlRpcWorkflowManagerClient {
+
+    /* our xml rpc client */
+    private XmlRpcClient client = null;
+
+    /* our log stream */
+    private static Logger LOG = Logger
+            .getLogger(XmlRpcWorkflowManagerClient.class.getName());
+
+    /* workflow manager url */
+    private URL workflowManagerUrl = null;
+
+    /**
+     * <p>
+     * Constructs a new XmlRpcWorkflowManagerClient with the given
+     * <code>url</code>.
+     * </p>
+     * 
+     * @param url
+     *            The url pointer to the xml rpc workflow manager service.
+     */
+    public XmlRpcWorkflowManagerClient(URL url) {
+        client = new XmlRpcClient(url);
+        workflowManagerUrl = url;
+    }
+    
+    public boolean refreshRepository()
+        throws Exception {
+        try {
+            return ((Boolean) client.execute(
+                    "workflowmgr.refreshRepository", new Vector()))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+    }
+
+  public String executeDynamicWorkflow(List<String> taskIds, Metadata metadata)
+      throws Exception {
+    Vector argList = new Vector();
+    Vector<String> taskIdVector = new Vector<String>();
+    taskIdVector.addAll(taskIds);
+    String instId = null;
+    
+    argList.add(taskIdVector);
+    argList.add(metadata.getHashtable());
+
+    try {
+      instId = (String) client.execute("workflowmgr.executeDynamicWorkflow",
+          argList);
+    } catch (XmlRpcException e) {
+      e.printStackTrace();
+      throw new Exception(e.getMessage());
+    } catch (IOException e) {
+      throw new Exception(e.getMessage());
+    }
+
+    return instId;
+
+  }
+
+    public List getRegisteredEvents() throws Exception {
+        Vector argList = new Vector();
+
+        try {
+            return (List) client.execute("workflowmgr.getRegisteredEvents",
+                    argList);
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public WorkflowInstancePage getFirstPage() throws Exception {
+        Vector argList = new Vector();
+        Hashtable pageHash = null;
+
+        try {
+            pageHash = (Hashtable) client.execute("workflowmgr.getFirstPage",
+                    argList);
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+
+        return XmlRpcStructFactory.getWorkflowInstancePageFromXmlRpc(pageHash);
+    }
+
+    public WorkflowInstancePage getNextPage(WorkflowInstancePage currentPage)
+            throws Exception {
+        Vector argList = new Vector();
+        argList.add(XmlRpcStructFactory
+                .getXmlRpcWorkflowInstancePage(currentPage));
+        Hashtable pageHash = null;
+
+        try {
+            pageHash = (Hashtable) client.execute("workflowmgr.getNextPage",
+                    argList);
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+
+        return XmlRpcStructFactory.getWorkflowInstancePageFromXmlRpc(pageHash);
+    }
+
+    public WorkflowInstancePage getPrevPage(WorkflowInstancePage currentPage)
+            throws Exception {
+        Vector argList = new Vector();
+        argList.add(XmlRpcStructFactory
+                .getXmlRpcWorkflowInstancePage(currentPage));
+        Hashtable pageHash = null;
+
+        try {
+            pageHash = (Hashtable) client.execute("workflowmgr.getPrevPage",
+                    argList);
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+
+        return XmlRpcStructFactory.getWorkflowInstancePageFromXmlRpc(pageHash);
+    }
+
+    public WorkflowInstancePage getLastPage() throws Exception {
+        Vector argList = new Vector();
+        Hashtable pageHash = null;
+
+        try {
+            pageHash = (Hashtable) client.execute("workflowmgr.getLastPage",
+                    argList);
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+
+        return XmlRpcStructFactory.getWorkflowInstancePageFromXmlRpc(pageHash);
+    }
+
+    public WorkflowInstancePage paginateWorkflowInstances(int pageNum,
+            String status) throws Exception {
+        Vector argList = new Vector();
+        argList.add(new Integer(pageNum));
+        argList.add(status);
+        Hashtable pageHash = null;
+
+        try {
+            pageHash = (Hashtable) client.execute(
+                    "workflowmgr.paginateWorkflowInstances", argList);
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+
+        return XmlRpcStructFactory.getWorkflowInstancePageFromXmlRpc(pageHash);
+    }
+
+    public WorkflowInstancePage paginateWorkflowInstances(int pageNum)
+            throws Exception {
+        Vector argList = new Vector();
+        argList.add(new Integer(pageNum));
+        Hashtable pageHash = null;
+
+        try {
+            pageHash = (Hashtable) client.execute(
+                    "workflowmgr.paginateWorkflowInstances", argList);
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+
+        return XmlRpcStructFactory.getWorkflowInstancePageFromXmlRpc(pageHash);
+    }
+
+    public List getWorkflowsByEvent(String eventName) throws Exception {
+        List workflows = new Vector();
+        Vector workflowVector = new Vector();
+        Vector argList = new Vector();
+        argList.add(eventName);
+
+        try {
+            workflowVector = (Vector) client.execute(
+                    "workflowmgr.getWorkflowsByEvent", argList);
+
+            if (workflowVector != null) {
+                for (Iterator i = workflowVector.iterator(); i.hasNext();) {
+                    Hashtable workflowHash = (Hashtable) i.next();
+                    Workflow w = XmlRpcStructFactory
+                            .getWorkflowFromXmlRpc(workflowHash);
+                    workflows.add(w);
+                }
+            }
+
+            return workflows;
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public Metadata getWorkflowInstanceMetadata(String wInstId) throws Exception {
+        Vector argList = new Vector();
+        argList.add(wInstId);
+        Metadata met = null;
+
+        try {
+            Hashtable instMetHash = (Hashtable) client.execute(
+                    "workflowmgr.getWorkflowInstanceMetadata", argList);
+            met = new Metadata();
+            met.addMetadata(instMetHash);
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+
+        return met;
+    }
+
+    public synchronized boolean setWorkflowInstanceCurrentTaskStartDateTime(
+            String wInstId, String startDateTimeIsoStr) throws Exception {
+        Vector argList = new Vector();
+        argList.add(wInstId);
+        argList.add(startDateTimeIsoStr);
+
+        try {
+            return ((Boolean) client.execute(
+                    "workflowmgr.setWorkflowInstanceCurrentTaskStartDateTime",
+                    argList)).booleanValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+
+    }
+
+    public double getWorkflowCurrentTaskWallClockMinutes(String workflowInstId)
+            throws Exception {
+        Vector argList = new Vector();
+        argList.add(workflowInstId);
+
+        try {
+            return ((Double) client.execute(
+                    "workflowmgr.getWorkflowCurrentTaskWallClockMinutes",
+                    argList)).doubleValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public double getWorkflowWallClockMinutes(String workflowInstId)
+            throws Exception {
+        Vector argList = new Vector();
+        argList.add(workflowInstId);
+
+        try {
+            return ((Double) client.execute(
+                    "workflowmgr.getWorkflowWallClockMinutes", argList))
+                    .doubleValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public synchronized boolean stopWorkflowInstance(String workflowInstId)
+            throws Exception {
+        Vector argList = new Vector();
+        argList.add(workflowInstId);
+
+        try {
+            return ((Boolean) client.execute(
+                    "workflowmgr.stopWorkflowInstance", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public synchronized boolean pauseWorkflowInstance(String workflowInstId)
+            throws Exception {
+        Vector argList = new Vector();
+        argList.add(workflowInstId);
+
+        try {
+            return ((Boolean) client.execute(
+                    "workflowmgr.pauseWorkflowInstance", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public synchronized boolean resumeWorkflowInstance(String workflowInstId)
+            throws Exception {
+        Vector argList = new Vector();
+        argList.add(workflowInstId);
+
+        try {
+            return ((Boolean) client.execute(
+                    "workflowmgr.resumeWorkflowInstance", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public synchronized boolean setWorkflowInstanceCurrentTaskEndDateTime(
+            String wInstId, String endDateTimeIsoStr) throws Exception {
+        Vector argList = new Vector();
+        argList.add(wInstId);
+        argList.add(endDateTimeIsoStr);
+
+        try {
+            return ((Boolean) client.execute(
+                    "workflowmgr.setWorkflowInstanceCurrentTaskEndDateTime",
+                    argList)).booleanValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+
+    }
+
+    public synchronized boolean updateWorkflowInstanceStatus(
+            String workflowInstId, String status) throws Exception {
+        Vector argList = new Vector();
+        argList.add(workflowInstId);
+        argList.add(status);
+
+        try {
+            return ((Boolean) client.execute(
+                    "workflowmgr.updateWorkflowInstanceStatus", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+
+    }
+
+    public synchronized boolean updateWorkflowInstance(WorkflowInstance instance)
+            throws Exception {
+        Vector argList = new Vector();
+        argList.add(XmlRpcStructFactory.getXmlRpcWorkflowInstance(instance));
+
+        try {
+            return ((Boolean) client.execute(
+                    "workflowmgr.updateWorkflowInstance", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public synchronized boolean updateMetadataForWorkflow(
+            String workflowInstId, Metadata metadata) throws Exception {
+        Vector argList = new Vector();
+        argList.add(workflowInstId);
+        argList.add(metadata.getHashtable());
+
+        try {
+            return ((Boolean) client.execute(
+                    "workflowmgr.updateMetadataForWorkflow", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+
+    }
+
+    public boolean sendEvent(String eventName, Metadata metadata)
+            throws Exception {
+        Vector argList = new Vector();
+        argList.add(eventName);
+        argList.add(metadata.getHashtable());
+
+        try {
+            return ((Boolean) client
+                    .execute("workflowmgr.handleEvent", argList))
+                    .booleanValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public WorkflowTask getTaskById(String taskId) throws Exception {
+        Vector argList = new Vector();
+        argList.add(taskId);
+
+        try {
+            Hashtable t = (Hashtable) client.execute("workflowmgr.getTaskById",
+                    argList);
+            return XmlRpcStructFactory.getWorkflowTaskFromXmlRpc(t);
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public WorkflowCondition getConditionById(String conditionId)
+            throws Exception {
+        Vector argList = new Vector();
+        argList.add(conditionId);
+
+        try {
+            Hashtable c = (Hashtable) client.execute(
+                    "workflowmgr.getConditionById", argList);
+            return XmlRpcStructFactory.getWorkflowConditionFromXmlRpc(c);
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public WorkflowInstance getWorkflowInstanceById(String wInstId)
+            throws Exception {
+        Vector argList = new Vector();
+        argList.add(wInstId);
+
+        try {
+            Hashtable workflowInstance = (Hashtable) client.execute(
+                    "workflowmgr.getWorkflowInstanceById", argList);
+            WorkflowInstance wInst = XmlRpcStructFactory
+                    .getWorkflowInstanceFromXmlRpc(workflowInstance);
+            return wInst;
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        }
+
+    }
+
+    public Workflow getWorkflowById(String workflowId) throws Exception {
+        Vector argList = new Vector();
+        argList.add(workflowId);
+
+        try {
+            Hashtable workflow = (Hashtable) client.execute(
+                    "workflowmgr.getWorkflowById", argList);
+            Workflow w = XmlRpcStructFactory.getWorkflowFromXmlRpc(workflow);
+            return w;
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public Vector getWorkflows() throws Exception {
+        Vector argList = new Vector();
+        Vector works = null;
+        Vector workflows = null;
+
+        try {
+            works = (Vector) client
+                    .execute("workflowmgr.getWorkflows", argList);
+
+            if (works != null) {
+                workflows = new Vector(works.size());
+
+                for (Iterator i = works.iterator(); i.hasNext();) {
+                    Hashtable workflw = (Hashtable) i.next();
+                    Workflow w = XmlRpcStructFactory
+                            .getWorkflowFromXmlRpc(workflw);
+                    workflows.add(w);
+                }
+
+                return workflows;
+            } else
+                return null;
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        }
+
+    }
+
+    public int getNumWorkflowInstancesByStatus(String status) throws Exception{
+        Vector argList = new Vector();
+        argList.add(status);
+        int numInsts = -1;
+
+        try {
+            numInsts = ((Integer)client.execute(
+                    "workflowmgr.getNumWorkflowInstancesByStatus", argList)).intValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        }
+
+        return numInsts;
+    }
+
+    public int getNumWorkflowInstances() throws Exception{
+        Vector argList = new Vector();
+        int numInsts = -1;
+
+        try {
+            numInsts = ((Integer)client.execute(
+                    "workflowmgr.getNumWorkflowInstances", argList)).intValue();
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        }
+
+        return numInsts;
+    }
+
+    public Vector getWorkflowInstancesByStatus(String status) throws Exception {
+        Vector argList = new Vector();
+        argList.add(status);
+        Vector insts = null;
+        Vector instsUnpacked = null;
+
+        try {
+            insts = (Vector) client.execute(
+                    "workflowmgr.getWorkflowInstancesByStatus", argList);
+            if (insts != null) {
+                instsUnpacked = new Vector(insts.size());
+                for (Iterator i = insts.iterator(); i.hasNext();) {
+                    Hashtable hWinst = (Hashtable) i.next();
+                    WorkflowInstance inst = XmlRpcStructFactory
+                            .getWorkflowInstanceFromXmlRpc(hWinst);
+                    instsUnpacked.add(inst);
+                }
+                return instsUnpacked;
+            } else
+                return null;
+
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public Vector getWorkflowInstances() throws Exception {
+        Vector argList = new Vector();
+        Vector insts = null;
+        Vector instsUnpacked = null;
+
+        try {
+            insts = (Vector) client.execute("workflowmgr.getWorkflowInstances",
+                    argList);
+            if (insts != null) {
+                instsUnpacked = new Vector(insts.size());
+                for (Iterator i = insts.iterator(); i.hasNext();) {
+                    Hashtable hWinst = (Hashtable) i.next();
+                    WorkflowInstance inst = XmlRpcStructFactory
+                            .getWorkflowInstanceFromXmlRpc(hWinst);
+                    instsUnpacked.add(inst);
+                }
+                return instsUnpacked;
+            } else
+                return null;
+
+        } catch (XmlRpcException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Exception(e.getMessage());
+        }
+    }
+
+    public static void main(String[] args) {
+       CmdLineUtility cmdLineUtility = new CmdLineUtility();
+       cmdLineUtility.run(args);
+    }
+
+    /**
+     * @return Returns the workflowManagerUrl.
+     */
+    public URL getWorkflowManagerUrl() {
+        return workflowManagerUrl;
+    }
+
+    /**
+     * @param workflowManagerUrl
+     *            The workflowManagerUrl to set.
+     */
+    public void setWorkflowManagerUrl(URL workflowManagerUrl) {
+        this.workflowManagerUrl = workflowManagerUrl;
+
+        // reset the client
+        client = new XmlRpcClient(workflowManagerUrl);
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/tools/InstanceRepoCleaner.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/tools/InstanceRepoCleaner.java
new file mode 100644
index 0000000..03779ec
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/tools/InstanceRepoCleaner.java
@@ -0,0 +1,143 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.tools;
+
+//JDK imports
+import java.net.URL;
+import java.util.Calendar;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.instrepo.LuceneWorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.structs.WorkflowStatus;
+import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient;
+import org.apache.oodt.commons.date.DateUtils;
+
+/**
+ * 
+ * Cleans a workflow manager instance repository of ghost jobs that will never
+ * execute and cleans up job history and repository status.
+ * 
+ * @author mattmann
+ * 
+ */
+public class InstanceRepoCleaner {
+
+  /* PGE task statuses */
+  public static final String STAGING_INPUT = "STAGING INPUT";
+
+  public static final String CONF_FILE_BUILD = "BUILDING CONFIG FILE";
+
+  public static final String RUNNING_PGE = "PGE EXEC";
+
+  public static final String CRAWLING = "CRAWLING";
+
+  private static final Logger LOG = Logger.getLogger(InstanceRepoCleaner.class
+      .getName());
+
+  private XmlRpcWorkflowManagerClient wm;
+
+  private LuceneWorkflowInstanceRepository rep;
+
+  public InstanceRepoCleaner() {
+  }
+
+  public InstanceRepoCleaner(String wmUrlStr) throws Exception {
+    this.wm = new XmlRpcWorkflowManagerClient(new URL(wmUrlStr));
+  }
+
+  public void setInstanceRepo(String idxPath) {
+    this.rep = new LuceneWorkflowInstanceRepository(idxPath, 1000);
+  }
+
+  public static void main(String[] args) throws Exception {
+    String usage = "InstanceRepoCleaner [options]\n"
+        + "<workflow manager url>\n" + "--idxPath <path>\n";
+    if (args.length != 1 && args.length != 2) {
+      System.err.println(usage);
+      System.exit(1);
+    }
+
+    InstanceRepoCleaner clean = null;
+    if (args.length == 1) {
+      String wmUrlStr = args[0];
+      clean = new InstanceRepoCleaner(wmUrlStr);
+    } else {
+      String idxPath = args[1];
+      clean = new InstanceRepoCleaner();
+      clean.setInstanceRepo(idxPath);
+    }
+    clean.cleanRepository();
+  }
+
+  public void cleanRepository() throws Exception {
+    WorkflowInstancePage page = wm != null ? wm.getFirstPage() : rep
+        .getFirstPage();
+    while (page != null && page.getPageWorkflows() != null
+        && page.getPageWorkflows().size() > 0) {
+
+      LOG.log(Level.INFO,
+          "Cleaning workflow instances: page: [" + page.getPageNum() + "] of ["
+              + page.getTotalPages() + "]: page size: [" + page.getPageSize()
+              + "]");
+      for (WorkflowInstance inst : (List<WorkflowInstance>) page
+          .getPageWorkflows()) {
+        if (inst.getStatus().equals(WorkflowStatus.CREATED)
+            || inst.getStatus().equals(WorkflowStatus.STARTED)
+            || inst.getStatus().equals(WorkflowStatus.QUEUED)
+            || inst.getStatus().equals(WorkflowStatus.RESMGR_SUBMIT)
+            || inst.getStatus().equals(CONF_FILE_BUILD)
+            || inst.getStatus().equals(CRAWLING)
+            || inst.getStatus().equals(RUNNING_PGE)
+            || inst.getStatus().equals(STAGING_INPUT)) {
+          String endDateTimeIsoStr = DateUtils.toString(Calendar.getInstance());
+          LOG.log(Level.INFO, "Updated workflow instance id: [" + inst.getId()
+              + "]: setting end date time to: [" + endDateTimeIsoStr + "]");
+          LOG.log(Level.INFO, "Existing status: [" + inst.getStatus()
+              + "]: setting to [" + WorkflowStatus.FINISHED + "]");
+          inst.setEndDateTimeIsoStr(endDateTimeIsoStr);
+          if (inst.getStartDateTimeIsoStr() == null
+              || (inst.getStartDateTimeIsoStr() != null && inst
+                  .getStartDateTimeIsoStr().equals(""))) {
+            inst.setStartDateTimeIsoStr(endDateTimeIsoStr);
+          }
+          inst.setStatus(WorkflowStatus.FINISHED);
+          if (wm != null) {
+            wm.updateWorkflowInstance(inst);
+          } else {
+            rep.updateWorkflowInstance(inst);
+          }
+        }
+      }
+
+      if (page.isLastPage()) {
+        LOG.log(Level.INFO, "Last set of workflow instances cleaned.");
+        break;
+      }
+
+      page = wm != null ? wm.getNextPage(page) : rep.getNextPage(page);
+
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/CygwinScriptFile.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/CygwinScriptFile.java
new file mode 100644
index 0000000..78df722
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/CygwinScriptFile.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.util;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * @author riverma (Rishi Verma)
+ * @version $Revision$
+ * 
+ * <p>
+ * A script file representing a set of commands (which are just
+ * <code>String</code>s) to be run through a command shell in Windows cygwin. 
+ * </p>
+ * 
+ */
+public class CygwinScriptFile extends ScriptFile {
+
+    /**
+     * 
+     */
+    public CygwinScriptFile() {
+        super();
+    }
+
+    public CygwinScriptFile(String shell) {
+        super(shell);
+    }
+
+    public CygwinScriptFile(String shell, List cmds) {
+        super(shell, cmds);
+    }		
+	
+	@Override
+	/**
+	 * Override writeScriptFile to ensure Windows (cygwin) compatibility for generated scripts
+	 */
+    public void writeScriptFile(String filePath) throws Exception {
+        PrintWriter pw = null;
+
+        try {
+            pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(
+                    new File(filePath))));
+            pw.print(toString()); // Changed println to print for Cygwin compatibility
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Exception("Error writing script file!: " + e.getMessage());
+        } finally {
+            try {
+                pw.close();
+                pw = null;
+            } catch (Exception ignore) {
+            }
+
+        }
+
+    }	
+	
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/DbStructFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/DbStructFactory.java
new file mode 100644
index 0000000..63c7391
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/DbStructFactory.java
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.util;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.Priority;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+
+//JDK imports
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.logging.Logger;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Factory for creating Workflow Manager objects from {@link ResultSet}s.
+ * </p>
+ * 
+ */
+public final class DbStructFactory {
+
+    /* our log stream */
+    private static Logger LOG = Logger.getLogger(DbStructFactory.class
+            .getName());
+
+    private DbStructFactory() throws InstantiationException {
+        throw new InstantiationException("Don't construct DbStructFactories!");
+    }
+
+    public static String getEvent(ResultSet rs) throws SQLException {
+        String eventName = rs.getString("event_name");
+        return eventName;
+    }
+
+    public static WorkflowInstance getWorkflowInstance(ResultSet rs)
+            throws SQLException {
+        WorkflowInstance workflowInst = new WorkflowInstance();
+        workflowInst.setTimesBlocked(rs.getInt("times_blocked"));
+        workflowInst.setStatus(rs.getString("workflow_instance_status"));
+        workflowInst.setId(rs.getString("workflow_instance_id"));
+        workflowInst.setCurrentTaskId(rs.getString("current_task_id"));
+        workflowInst.setStartDateTimeIsoStr(rs.getString("start_date_time"));
+        workflowInst.setEndDateTimeIsoStr(rs.getString("end_date_time"));
+        workflowInst.setCurrentTaskStartDateTimeIsoStr(rs
+                .getString("current_task_start_date_time"));
+        workflowInst.setCurrentTaskEndDateTimeIsoStr(rs
+                .getString("current_task_end_date_time"));
+        workflowInst.setPriority(Priority.getPriority(rs.getDouble("priority")));
+        Workflow workflow = new Workflow();
+        workflow.setId(rs.getString("workflow_id"));
+        workflowInst.setWorkflow(workflow);
+        return workflowInst;
+    }
+
+    public static Workflow getWorkflow(ResultSet rs) throws SQLException {
+        Workflow workflow = new Workflow();
+        workflow.setName(rs.getString("workflow_name"));
+        workflow.setId(String.valueOf(rs.getInt("workflow_id")));
+
+        return workflow;
+    }
+
+    public static WorkflowTask getWorkflowTask(ResultSet rs, boolean setOrder)
+            throws SQLException {
+        String taskClassName = rs.getString("workflow_task_class");
+
+        if (taskClassName != null) {
+            WorkflowTask task = new WorkflowTask();
+            task.setTaskInstanceClassName(taskClassName);
+            task.setTaskId(String.valueOf(rs.getInt("workflow_task_id")));
+            task.setTaskName(rs.getString("workflow_task_name"));
+            if (setOrder) {
+                task.setOrder(rs.getInt("task_order"));
+            }
+            return task;
+        } else
+            return null;
+    }
+
+    public static WorkflowCondition getWorkflowCondition(ResultSet rs,
+            boolean setOrder) throws SQLException {
+
+        String conditionClassName = rs.getString("workflow_condition_class");
+
+        if (conditionClassName != null) {
+            WorkflowCondition condition = new WorkflowCondition();
+            condition.setConditionInstanceClassName(conditionClassName);
+            condition.setConditionId(String.valueOf(rs
+                    .getInt("workflow_condition_id")));
+            condition.setConditionName(rs.getString("workflow_condition_name"));
+            condition.setTimeoutSeconds(rs.getLong("workflow_condition_timeout"));
+            condition.setOptional(rs.getBoolean("workflow_condition_optional"));
+            if (setOrder) {
+                condition.setOrder(rs.getInt("condition_order"));
+            }
+            return condition;
+        } else
+            return null;
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/GenericWorkflowObjectFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/GenericWorkflowObjectFactory.java
new file mode 100644
index 0000000..e3a3824
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/GenericWorkflowObjectFactory.java
@@ -0,0 +1,476 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.util;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.WorkflowEngine;
+import org.apache.oodt.cas.workflow.engine.WorkflowEngineFactory;
+import org.apache.oodt.cas.workflow.engine.runner.EngineRunner;
+import org.apache.oodt.cas.workflow.engine.runner.EngineRunnerFactory;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepositoryFactory;
+import org.apache.oodt.cas.workflow.repository.WorkflowRepository;
+import org.apache.oodt.cas.workflow.repository.WorkflowRepositoryFactory;
+import org.apache.oodt.cas.workflow.structs.PrioritySorter;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionInstance;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+
+//JDK imports
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.List;
+import java.util.Vector;
+import java.util.Iterator;
+
+/**
+ * Generic Workflow object construction utilities.
+ *
+ * @author mattmann (Chris Mattmann)
+ * @author bfoster (Brian Foster)
+ */
+public final class GenericWorkflowObjectFactory {
+
+	/* our log stream */
+	public static Logger LOG = Logger.getLogger(GenericWorkflowObjectFactory.class
+			.getName());
+
+	private GenericWorkflowObjectFactory() throws InstantiationException{
+		throw new InstantiationException(
+		"Don't instantiate XML Struct Factories!");
+	}
+
+   public static WorkflowEngine getWorkflowEngineFromClassName(String engineFactory) {
+      try {
+         return ((WorkflowEngineFactory) Class.forName(engineFactory)
+               .newInstance()).createWorkflowEngine();
+      } catch (ClassNotFoundException e) {
+         LOG.log(Level.WARNING, "ClassNotFoundException when "
+               + "loading workflow engine factory class "
+               + engineFactory + " Message: " + e.getMessage());
+      } catch (InstantiationException e) {
+         LOG.log(Level.WARNING, "InstantiationException when "
+               + "loading workflow engine factory class "
+               + engineFactory + " Message: " + e.getMessage());
+      } catch (IllegalAccessException e) {
+         LOG.log(Level.WARNING, "IllegalAccessException when loading "
+               + "workflow engine factory class "
+               + engineFactory + " Message: " + e.getMessage());
+      }
+      return null;
+   }
+
+	public static EngineRunner getEngineRunnerFromClassName(String engineFactory) {
+	   try {
+         return ((EngineRunnerFactory) Class.forName(engineFactory)
+               .newInstance()).createEngineRunner();
+      } catch (ClassNotFoundException e) {
+         LOG.log(Level.WARNING, "ClassNotFoundException when "
+               + "loading engine runner factory class "
+               + engineFactory + " Message: " + e.getMessage());
+      } catch (InstantiationException e) {
+         LOG.log(Level.WARNING, "InstantiationException when "
+               + "loading engine runner factory class "
+               + engineFactory + " Message: " + e.getMessage());
+      } catch (IllegalAccessException e) {
+         LOG.log(Level.WARNING, "IllegalAccessException when loading "
+               + "engine runner factory class "
+               + engineFactory + " Message: " + e.getMessage());
+      }
+      return null;
+	}
+
+   public static WorkflowRepository getWorkflowRepositoryFromClassName(String repositoryFactory) {
+      try {
+         return ((WorkflowRepositoryFactory) Class.forName(repositoryFactory)
+               .newInstance()).createRepository();
+      } catch (ClassNotFoundException e) {
+         LOG.log(Level.WARNING, "ClassNotFoundException when "
+               + "loading engine runner factory class "
+               + repositoryFactory + " Message: " + e.getMessage());
+      } catch (InstantiationException e) {
+         LOG.log(Level.WARNING, "InstantiationException when "
+               + "loading engine runner factory class "
+               + repositoryFactory + " Message: " + e.getMessage());
+      } catch (IllegalAccessException e) {
+         LOG.log(Level.WARNING, "IllegalAccessException when loading "
+               + "engine runner factory class "
+               + repositoryFactory + " Message: " + e.getMessage());
+      }
+      return null;
+   }
+
+	public static WorkflowInstanceRepository getWorkflowInstanceRepositoryFromClassName(
+			String serviceFactory) {
+		WorkflowInstanceRepositoryFactory factory = null;
+		Class clazz = null;
+
+		try {
+			clazz = Class.forName(serviceFactory);
+			factory = (WorkflowInstanceRepositoryFactory) clazz.newInstance();
+			return factory.createInstanceRepository();
+		} catch (ClassNotFoundException e) {
+			e.printStackTrace();
+			LOG.log(Level.WARNING, "ClassNotFoundException when "
+					+ "loading workflow instance repository factory class "
+					+ serviceFactory + " Message: " + e.getMessage());
+		} catch (InstantiationException e) {
+			e.printStackTrace();
+			LOG.log(Level.WARNING, "InstantiationException when "
+					+ "loading workflow instance repository factory class "
+					+ serviceFactory + " Message: " + e.getMessage());
+		} catch (IllegalAccessException e) {
+			e.printStackTrace();
+			LOG.log(Level.WARNING, "IllegalAccessException when loading "
+					+ "workflow instance repository factory class "
+					+ serviceFactory + " Message: " + e.getMessage());
+		}
+
+		return null;
+	}
+
+	/**
+	 * <p>
+	 * Constructs a {@link WorkflowTaskInstance} from the given implementation
+	 * class name.
+	 * </p>
+	 *
+	 * @param className
+	 *            The String name of the class (including package qualifiers)
+	 *            that implements the WorkflowTaskInstance interface to
+	 *            construct.
+	 * @return A new {@link WorkflowTaskInstance} implementation specified by
+	 *         its class name.
+	 */
+	public static WorkflowTaskInstance getTaskObjectFromClassName(String className) {
+
+		if (className != null) {
+			WorkflowTaskInstance taskInstance = null;
+
+			try {
+				Class workflowTaskClass = Class.forName(className);
+				taskInstance = (WorkflowTaskInstance) workflowTaskClass.newInstance();
+
+				return taskInstance;
+
+			} catch (ClassNotFoundException e) {
+				e.printStackTrace();
+				LOG.log(Level.WARNING,
+						"ClassNotFound, Unable to locate task class: "
+								+ className + ": cannot instantiate!");
+				return null;
+			} catch (InstantiationException e) {
+				e.printStackTrace();
+				LOG.log(Level.WARNING, "Unable to instantiate task class: "
+						+ className + ": Reason: " + e.getMessage() + " !");
+				return null;
+			} catch (IllegalAccessException e) {
+				e.printStackTrace();
+				LOG.log(Level.WARNING,
+						"IllegalAccessException when instantiating task class: "
+								+ className + ": cannot instantiate!");
+				return null;
+			}
+		} else
+			return null;
+	}
+
+  /**
+   * <p>
+   * Constructs a {@link WorkflowTaskInstance} from the given implementation
+   * class name.
+   * </p>
+   *
+   * @param className
+   *            The String name of the inner class (including package qualifiers)
+   *            that implements the WorkflowTaskInstance interface to
+   *            construct.
+   * @return A new {@link WorkflowTaskInstance} implementation specified by
+   *         its class name.
+   */
+  public static WorkflowTaskInstance getTaskObjectFromInnerClassName(Class<?> enclosingInstance, String className) {
+
+    if (className != null) {
+      WorkflowTaskInstance taskInstance = null;
+
+      try {
+        Class workflowTaskClass = Class.forName(className);
+        Constructor construct = workflowTaskClass.getConstructor(enclosingInstance);
+        taskInstance = (WorkflowTaskInstance) construct.newInstance();
+
+        return taskInstance;
+
+      } catch (ClassNotFoundException e) {
+        e.printStackTrace();
+        LOG.log(Level.WARNING,
+            "ClassNotFound, Unable to locate task class: "
+                + className + ": cannot instantiate!");
+        return null;
+      } catch (InstantiationException e) {
+        e.printStackTrace();
+        LOG.log(Level.WARNING, "Unable to instantiate task class: "
+            + className + ": Reason: " + e.getMessage() + " !");
+        return null;
+      } catch (IllegalAccessException e) {
+        e.printStackTrace();
+        LOG.log(Level.WARNING,
+            "IllegalAccessException when instantiating task class: "
+                + className + ": cannot instantiate!");
+        return null;
+      }
+      catch (NoSuchMethodException e) {
+        e.printStackTrace();
+        LOG.log(Level.WARNING,
+            "NoSuchMethodException when instantiating task class: "
+                + className + ": cannot instantiate!");
+        return null;
+      }
+      catch (InvocationTargetException e) {
+        e.printStackTrace();
+        LOG.log(Level.WARNING,
+            "InvocationTargetException when instantiating task class: "
+                + className + ": cannot instantiate!");
+        return null;
+      }
+    } else
+      return null;
+  }
+
+	/**
+	 * <p>
+	 * Constructs a {@link WorkflowConditionInstance} from the given implementation
+	 * class name.
+	 * </p>
+	 *
+	 * @param className
+	 *            The String name of the class (including package qualifiers)
+	 *            that implements the WorkflowConditionInstance interface to construct.
+	 * @return A new {@link WorkflowConditionInstance} implementation specified by its class
+	 *         name.
+	 */
+	public static WorkflowConditionInstance getConditionObjectFromClassName(
+			String className) {
+		if (className != null) {
+			WorkflowConditionInstance conditionInstance = null;
+
+			try {
+				Class workflowConditionClass = Class.forName(className);
+				conditionInstance = (WorkflowConditionInstance) workflowConditionClass
+						.newInstance();
+				return conditionInstance;
+			} catch (ClassNotFoundException e) {
+				e.printStackTrace();
+				LOG.log(Level.WARNING, "Unable to locate condition class: "
+						+ className + ": cannot instantiate!");
+				return null;
+			} catch (InstantiationException e) {
+				e.printStackTrace();
+				LOG.log(Level.WARNING,
+						"Unable to instantiate condition class: " + className
+								+ ": Reason: " + e.getMessage() + " !");
+				return null;
+			} catch (IllegalAccessException e) {
+				e.printStackTrace();
+				LOG.log(Level.WARNING,
+						"IllegalAccessException when instantiating condition class: "
+								+ className + ": cannot instantiate!");
+				return null;
+			}
+		} else
+			return null;
+	}
+
+	/**
+	 * <p>
+	 * Constructs a {@link Workflow} instance from the given implementation
+	 * class name.
+	 * </p>
+	 *
+	 * @param className
+	 *            The String name of the class (including package qualifiers)
+	 *            that implements the Workflow interface to construct.
+	 * @return A new {@link Workflow} implementation specified by its class
+	 *         name.
+	 */
+	public static Workflow getWorkflowObjectFromClassName(String className){
+		if (className != null) {
+			Workflow workflow = null;
+
+			try {
+				Class workflowClass = Class.forName(className);
+				workflow = (Workflow) workflowClass
+						.newInstance();
+				return workflow;
+			} catch (ClassNotFoundException e) {
+				e.printStackTrace();
+				LOG.log(Level.WARNING, "Unable to locate workflow class: "
+						+ className + ": cannot instantiate!");
+				return null;
+			} catch (InstantiationException e) {
+				e.printStackTrace();
+				LOG.log(Level.WARNING,
+						"Unable to instantiate workflow class: " + className
+								+ ": Reason: " + e.getMessage() + " !");
+				return null;
+			} catch (IllegalAccessException e) {
+				e.printStackTrace();
+				LOG.log(Level.WARNING,
+						"IllegalAccessException when instantiating workflow class: "
+								+ className + ": cannot instantiate!");
+				return null;
+			}
+		} else
+			return null;
+	}
+	
+	public static PrioritySorter getPrioritySorterFromClassName(String className){
+	  if(className != null){
+	    try{
+	      Class<PrioritySorter> sorterClass = (Class<PrioritySorter>)Class.forName(className);	      
+	      return sorterClass.newInstance();
+	    }
+	    catch (ClassNotFoundException e) {
+        e.printStackTrace();
+        LOG.log(Level.WARNING, "Unable to locate workflow prioritizer class: "
+            + className + ": cannot instantiate!");
+        return null;
+      } catch (InstantiationException e) {
+        e.printStackTrace();
+        LOG.log(Level.WARNING,
+            "Unable to instantiate workflow prioritizer class: " + className
+                + ": Reason: " + e.getMessage() + " !");
+        return null;
+      } catch (IllegalAccessException e) {
+        e.printStackTrace();
+        LOG.log(Level.WARNING,
+            "IllegalAccessException when instantiating workflow prioritizer class: "
+                + className + ": cannot instantiate!");
+        return null;
+      }
+	  }
+	  else return null;
+	}
+
+	public static List copyWorkflows(List workflows){
+		if(workflows != null){
+			List newWorkflows = new Vector(workflows.size());
+			for(Iterator i = workflows.iterator(); i.hasNext(); ){
+				Workflow w = (Workflow)i.next();
+				Workflow newWorkflow = copyWorkflow(w);
+				newWorkflows.add(newWorkflow);
+			}
+
+			return newWorkflows;
+		}
+		else return null;
+	}
+
+	/**
+	 * <p>Creates an exact copy of the specified {@link Workflow} <code>w</code>,
+	 * allocating new memory for the new object, and then returning it. The Workflow's
+	 * {@link WorkflowTask}s and {@link WorkflowCondition}s on those tasks are also constructed
+	 * anew, and copied from their original instances.</p>
+	 *
+	 * @param w The Workflow object to create a copy of.
+	 * @return A copy of the specified Workflow.
+	 */
+	public static Workflow copyWorkflow(Workflow w){
+		Workflow newWorkflow = null;
+
+
+		newWorkflow = getWorkflowObjectFromClassName(w.getClass().getName());
+
+
+		//copy through
+		newWorkflow.setName(w.getName());
+		newWorkflow.setId(w.getId());
+		newWorkflow.setTasks(copyTasks(w.getTasks()));
+
+		return newWorkflow;
+	}
+
+	/**
+	 * <p>Creates copies of each {@link WorkflowTask} within the specified
+	 * {@link List} of WorkflowTasks specified by <code>taskList</code>. The new
+	 * List of WorkflowTasks is returned.</p>
+	 *
+	 * @param taskList The original List of WorkflowTasks to copy.
+	 * @return A new List of WorkflowTasks, copied from the original one specified.
+	 */
+	public static List copyTasks(List taskList){
+		if(taskList != null){
+
+			List newTaskList = new Vector(taskList.size());
+
+			for(Iterator i = taskList.iterator(); i.hasNext(); ){
+				WorkflowTask t = (WorkflowTask)i.next();
+				WorkflowTask newTask = copyTask(t);
+				newTaskList.add(newTask);
+			}
+
+			return newTaskList;
+		}
+		else return null;
+	}
+
+	public static WorkflowTask copyTask(WorkflowTask t){
+		WorkflowTask newTask = new WorkflowTask();
+		newTask.setTaskConfig(t.getTaskConfig());
+		newTask.setTaskId(t.getTaskId());
+		newTask.setTaskName(t.getTaskName());
+		newTask.setTaskInstanceClassName(t.getTaskInstanceClassName());
+		newTask.setOrder(t.getOrder());
+		newTask.setConditions(copyConditions(t.getConditions()));
+		return newTask;
+	}
+
+	/**
+	 * <p>Creates copies of each {@link WorkflowCondition} within the specified
+	 * {@link List} of WorkflowConditions specified by <code>conditionList</code>. The new
+	 * List of WorkflowConditions is returned.</p>
+	 *
+	 * @param conditionList The original List of WorkflowConditions to copy.
+	 * @return A new List of WorkflowConditions, copied from the original one specified.
+	 */
+	public static List copyConditions(List conditionList){
+		if(conditionList != null){
+			List newConditionList = new Vector(conditionList.size());
+
+			for(Iterator i = conditionList.iterator(); i.hasNext(); ){
+				WorkflowCondition c = (WorkflowCondition)i.next();
+				WorkflowCondition newCondition = copyCondition(c);
+				newConditionList.add(newCondition);
+			}
+
+			return newConditionList;
+		}
+		else return null;
+	}
+
+	public static WorkflowCondition copyCondition(WorkflowCondition c){
+		WorkflowCondition newCondition = new WorkflowCondition();
+		newCondition.setConditionName(c.getConditionName());
+		newCondition.setOrder(c.getOrder());
+		newCondition.setConditionInstanceClassName(c.getConditionInstanceClassName());
+		return newCondition;
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/Pagination.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/Pagination.java
new file mode 100644
index 0000000..431c55b
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/Pagination.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.util;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public interface Pagination {
+
+    /**
+     * @return The first page of products for a particular {@link ProductType}.
+     */
+    public WorkflowInstancePage getFirstPage();
+
+    /**
+     * 
+     * @return The last page of products for a particular {@link ProductType}.
+     */
+    public WorkflowInstancePage getLastPage();
+
+    /**
+     * 
+     * @param currentPage
+     *            The current page that tells the function what the next page to
+     *            obtain is.
+     * @return The next page in the ProductType product list, given the
+     *         currentPage.
+     */
+    public WorkflowInstancePage getNextPage(WorkflowInstancePage currentPage);
+
+    /**
+     * 
+     * @param currentPage
+     *            The currentPage that tells the function what the previous page
+     *            to obtain is.
+     * @return The previous page in the ProductType product list, given the
+     *         currentPage.
+     */
+    public WorkflowInstancePage getPrevPage(WorkflowInstancePage currentPage);
+
+    /**
+     * Gets the {@link WorkflowInstancePage} identified by its
+     * <code>pageNum</code> and associated <code>status</code> parameters.
+     * 
+     * @param pageNum
+     *            The {@link WorkflowInstancePage} number to get.
+     * @param status
+     *            Identifies which {@link WorkflowInstance} set to paginate,
+     *            e.g., only {@link WorkflowInstance}s with a given status.
+     * 
+     * @return The {@link WorkflowInstancePage} with the given status, and page
+     *         number.
+     * @throws InstanceRepositoryException
+     *             If any error occurs.
+     */
+    public WorkflowInstancePage getPagedWorkflows(int pageNum)
+            throws InstanceRepositoryException;
+
+    /**
+     * Gets the {@link WorkflowInstancePage} identified by its
+     * <code>pageNum</code> and associated <code>status</code> parameters.
+     * 
+     * @param pageNum
+     *            The {@link WorkflowInstancePage} number to get.
+     * @param status
+     *            Identifies which {@link WorkflowInstance} set to paginate,
+     *            e.g., only {@link WorkflowInstance}s with a given status.
+     * 
+     * @return The {@link WorkflowInstancePage} with the given status, and page
+     *         number.
+     * @throws InstanceRepositoryException
+     *             If any error occurs.
+     */
+    public WorkflowInstancePage getPagedWorkflows(int pageNum, String status)
+            throws InstanceRepositoryException;
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/ScriptFile.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/ScriptFile.java
new file mode 100644
index 0000000..e964ad0
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/ScriptFile.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.util;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+import java.util.Iterator;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A script file represents a set of commands (which are just
+ * <code>String</code>s) to be run through a command shell.
+ * </p>
+ * 
+ */
+public class ScriptFile {
+
+    private String commandShell = null;
+
+    private List commands = null;
+
+    /**
+     * 
+     */
+    public ScriptFile() {
+        commandShell = "/bin/sh";
+        commands = new Vector();
+    }
+
+    public ScriptFile(String shell) {
+        commandShell = shell;
+        commands = new Vector();
+    }
+
+    public ScriptFile(String shell, List cmds) {
+        commandShell = shell;
+        commands = cmds;
+    }
+
+    /**
+     * @return Returns the commands.
+     */
+    public List getCommands() {
+        return commands;
+    }
+
+    /**
+     * @param commands
+     *            The commands to set.
+     */
+    public void setCommands(List commands) {
+        this.commands = commands;
+    }
+
+    /**
+     * @return Returns the commandShell.
+     */
+    public String getCommandShell() {
+        return commandShell;
+    }
+
+    /**
+     * @param commandShell
+     *            The commandShell to set.
+     */
+    public void setCommandShell(String commandShell) {
+        this.commandShell = commandShell;
+    }
+
+    public String toString() {
+        String rStr = "";
+
+        rStr += "#!" + commandShell + "\n";
+
+        for (Iterator i = commands.iterator(); i.hasNext();) {
+            String cmd = (String) i.next();
+            rStr += cmd + "\n";
+        }
+
+        return rStr;
+    }
+
+    public void writeScriptFile(String filePath) throws Exception {
+        PrintWriter pw = null;
+
+        try {
+            pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(
+                    new File(filePath))));
+            pw.println(toString());
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Exception("Error writing script file!: " + e.getMessage());
+        } finally {
+            try {
+                pw.close();
+                pw = null;
+            } catch (Exception ignore) {
+            }
+
+        }
+
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/XmlRpcStructFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/XmlRpcStructFactory.java
new file mode 100644
index 0000000..17a7e74
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/XmlRpcStructFactory.java
@@ -0,0 +1,595 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.util;
+
+//JDK imports
+import java.util.List;
+import java.util.Iterator;
+import java.util.Hashtable;
+import java.util.Set;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.Priority;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+
+/**
+ * 
+ * A Struct Factory for creating and unpacking Workflow Objects to be sent and
+ * received across the XML-RPC wire.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public final class XmlRpcStructFactory {
+
+  private XmlRpcStructFactory() throws InstantiationException {
+    throw new InstantiationException("Don't instantiate XmlRpcStructFactories!");
+  }
+
+  /**
+   * Gets a {@link Hashtable} representation of a {@link WorkflowInstancePage}
+   * that is serializable over the XML-RPC wire.
+   * 
+   * @param page
+   *          The {@link WorkflowInstancePage} to turn into a {@link Hashtable}.
+   * @return A {@link Hashtable} representation of a
+   *         {@link WorkflowInstancePage}.
+   */
+  public static Hashtable getXmlRpcWorkflowInstancePage(
+      WorkflowInstancePage page) {
+    Hashtable pageHash = new Hashtable();
+    pageHash.put("totalPages", String.valueOf(page.getTotalPages()));
+    pageHash.put("pageNum", String.valueOf(page.getPageNum()));
+    pageHash.put("pageSize", String.valueOf(page.getPageSize()));
+    pageHash.put("pageWorkflows",
+        getXmlRpcWorkflowInstances(page.getPageWorkflows()));
+
+    return pageHash;
+
+  }
+
+  /**
+   * Gets a {@link WorkflowInstancePage} off of the XML-RPC wire by converting
+   * the XML-RPC {@link Hashtable} representation of the page into a
+   * {@link WorkflowInstancePage}.
+   * 
+   * @param pageHash
+   *          The XML-RPC {@link Hashtable} representation of this
+   *          {@link WorkflowInstancePage}.
+   * @return The {@link WorkflowInstancePage} that this XML-RPC
+   *         {@link Hashtable} provided represents.
+   */
+  public static WorkflowInstancePage getWorkflowInstancePageFromXmlRpc(
+      Hashtable pageHash) {
+    WorkflowInstancePage page = new WorkflowInstancePage();
+    page.setPageNum(Integer.parseInt((String) pageHash.get("pageNum")));
+    page.setPageSize(Integer.parseInt((String) pageHash.get("pageSize")));
+    page.setTotalPages(Integer.parseInt((String) pageHash.get("totalPages")));
+    page.setPageWorkflows(getWorkflowInstancesFromXmlRpc((Vector) pageHash
+        .get("pageWorkflows")));
+
+    return page;
+
+  }
+
+  /**
+   * <p>
+   * Gets a {@link Hashtable} representation of a {@link WorkflowInstance} to be
+   * sent across the XML-RPC wire.
+   * </p>
+   * 
+   * @param wInst
+   *          The WorkflowInstance to turned into a java.util.Hashtable.
+   * @return A {@link Hashtable} representation of a {@link WorkflowInstance}.
+   */
+  public static Hashtable getXmlRpcWorkflowInstance(WorkflowInstance wInst) {
+    Hashtable workflowInstance = new Hashtable();
+    workflowInstance.put("current_task_id", wInst.getCurrentTaskId());
+    workflowInstance.put("status", wInst.getStatus());
+    workflowInstance.put("id", wInst.getId());
+    workflowInstance.put("workflow", getXmlRpcWorkflow(wInst.getWorkflow()));
+    workflowInstance.put("start_date_time",
+        wInst.getStartDateTimeIsoStr() != null ? wInst.getStartDateTimeIsoStr()
+            : "");
+    workflowInstance.put("end_date_time",
+        wInst.getEndDateTimeIsoStr() != null ? wInst.getEndDateTimeIsoStr()
+            : "");
+    workflowInstance.put(
+        "current_task_start_date_time",
+        wInst.getCurrentTaskStartDateTimeIsoStr() != null ? wInst
+            .getCurrentTaskStartDateTimeIsoStr() : "");
+    workflowInstance.put(
+        "current_task_end_date_time",
+        wInst.getCurrentTaskEndDateTimeIsoStr() != null ? wInst
+            .getCurrentTaskEndDateTimeIsoStr() : "");
+    workflowInstance.put("sharedContext",
+        wInst.getSharedContext() != null ? wInst.getSharedContext()
+            .getHashtable() : new Hashtable());
+    workflowInstance.put(
+        "priority",
+        wInst.getPriority() != null ? String.valueOf(wInst.getPriority()
+            .getValue()) : String.valueOf(Priority.getDefault().getValue()));
+    return workflowInstance;
+  }
+
+  public static WorkflowInstance getWorkflowInstanceFromXmlRpc(
+      Hashtable workflowInstance) {
+    WorkflowInstance wInst = new WorkflowInstance();
+    wInst.setCurrentTaskId((String) workflowInstance.get("current_task_id"));
+    wInst.setStatus((String) workflowInstance.get("status"));
+    wInst.setId((String) workflowInstance.get("id"));
+    wInst.setWorkflow(getWorkflowFromXmlRpc((Hashtable) workflowInstance
+        .get("workflow")));
+    wInst.setStartDateTimeIsoStr((String) workflowInstance
+        .get("start_date_time"));
+    wInst.setEndDateTimeIsoStr((String) workflowInstance.get("end_date_time"));
+    wInst.setCurrentTaskStartDateTimeIsoStr((String) workflowInstance
+        .get("current_task_start_date_time"));
+    wInst.setCurrentTaskEndDateTimeIsoStr((String) workflowInstance
+        .get("current_task_end_date_time"));
+    if (workflowInstance.get("sharedContext") != null) {
+      Metadata met = new Metadata();
+      met.addMetadata((Hashtable) workflowInstance.get("sharedContext"));
+      wInst.setSharedContext(met);
+    } else
+      wInst.setSharedContext(new Metadata());
+
+    if (workflowInstance.get("priority") != null) {
+      Priority p = Priority.getPriority(Double
+          .valueOf((String) workflowInstance.get("priority")));
+    }
+
+    return wInst;
+  }
+
+  /**
+   * Gets a {@link List} of {@link WorkflowInstance}s from their representations
+   * as {@link Hashtable}s in XML-RPC.
+   * 
+   * @param instsVector
+   *          The {@link Vector} of {@link Hashtable} representations of
+   *          {@link WorkflowInstance}s.
+   * @return A {@link List} of {@link WorkflowInstance}s from their
+   *         representations as {@link Hashtable}s in XML-RPC.
+   */
+  public static List getWorkflowInstancesFromXmlRpc(Vector instsVector) {
+    List wInsts = new Vector();
+
+    if (instsVector != null && instsVector.size() > 0) {
+      for (Iterator i = instsVector.iterator(); i.hasNext();) {
+        Hashtable wInstHash = (Hashtable) i.next();
+        WorkflowInstance inst = getWorkflowInstanceFromXmlRpc(wInstHash);
+        wInsts.add(inst);
+      }
+    }
+
+    return wInsts;
+  }
+
+  /**
+   * Gets an XML-RPC serializable {@link Vector} of {@link Hashtable}
+   * representations of {@link WorkflowInstance}s.
+   * 
+   * @param wInsts
+   *          The {@link List} of {@link WorkflowInstance}s to serialize.
+   * @return A XML-RPC serializable {@link Vector} of {@link Hashtable}
+   *         representations of {@link WorkflowInstance}s.
+   */
+  public static Vector getXmlRpcWorkflowInstances(List wInsts) {
+    Vector instsVector = new Vector();
+
+    if (wInsts != null && wInsts.size() > 0) {
+      for (Iterator i = wInsts.iterator(); i.hasNext();) {
+        WorkflowInstance inst = (WorkflowInstance) i.next();
+        instsVector.add(getXmlRpcWorkflowInstance(inst));
+      }
+    }
+
+    return instsVector;
+  }
+
+  /**
+   * <p>
+   * Gets a {@link Hashtable} representation of a {@link Workflow} to be sent
+   * across the XML-RPC wire.
+   * </p>
+   * 
+   * @param w
+   *          The Workflow to be turned into a java.util.Hashtable
+   * @return A {@link Hashtable} representation of a {@link Workflow}.
+   */
+  public static Hashtable getXmlRpcWorkflow(Workflow w) {
+    Hashtable workflow = new Hashtable();
+    workflow.put("id", w.getId());
+    workflow.put("name", w.getName() != null ? w.getName() : "");
+    workflow.put("tasks", getXmlRpcWorkflowTasks(w.getTasks()));
+    workflow.put("conditions", getXmlRpcWorkflowConditions(w.getConditions()));
+
+    return workflow;
+  }
+
+  /**
+   * <p>
+   * Gets a {@link Workflow} from the XML-RPC {@link Hashtable} version.
+   * </p>
+   * 
+   * @param w
+   *          The Hashtable to obtain a Workflow from.
+   * @return a {@link Workflow} from the XML-RPC {@link Hashtable} version.
+   */
+  public static Workflow getWorkflowFromXmlRpc(Hashtable w) {
+    Workflow workflow = new Workflow();
+    workflow.setName((String) w.get("name"));
+    workflow.setId((String) w.get("id"));
+    workflow.setTasks(getWorkflowTasksFromXmlRpc((Vector) w.get("tasks")));
+    workflow.setConditions(getWorkflowConditionsFromXmlRpc((Vector) w
+        .get("conditions")));
+
+    return workflow;
+  }
+
+  /**
+   * <p>
+   * Gets an XML-RPC version of the {@link WorkflowTask} to send over the wire.
+   * </p>
+   * 
+   * @param t
+   *          The WorkflowTask to obtain an XML-RPC Hashtable from.
+   * @return an XML-RPC version of the {@link WorkflowTask} to send over the
+   *         wire.
+   */
+  public static Hashtable getXmlRpcWorkflowTask(WorkflowTask t) {
+    Hashtable task = new Hashtable();
+    task.put("class", t.getTaskInstanceClassName());
+    task.put("id", t.getTaskId());
+    task.put("name", t.getTaskName());
+    task.put("order", String.valueOf(t.getOrder()));
+    task.put("conditions", getXmlRpcWorkflowConditions(t.getConditions()));
+    task.put("configuration",
+        getXmlRpcWorkflowTaskConfiguration(t.getTaskConfig()));
+    task.put("requiredMetFields",
+        getXmlRpcWorkflowTaskReqMetFields(t.getRequiredMetFields()));
+    return task;
+  }
+
+  /**
+   * <p>
+   * Gets a {@link Vector} representation of a {@link List} of
+   * {@link WorkflowTask}s to be sent across the XML-RPC wire.
+   * </p>
+   * 
+   * @param tasks
+   *          The {@link List} of {@link WorkflowTask}s.
+   * 
+   * @return A {@link Vector} representation of a {@link List} of
+   *         {@link WorkflowTask}s.
+   */
+  public static Vector getXmlRpcWorkflowTasks(List tasks) {
+    Vector wTasks = new Vector();
+
+    if (tasks == null) {
+      return wTasks;
+    }
+
+    for (Iterator i = tasks.iterator(); i.hasNext();) {
+      WorkflowTask t = (WorkflowTask) i.next();
+      Hashtable task = getXmlRpcWorkflowTask(t);
+      wTasks.add(task);
+    }
+
+    return wTasks;
+  }
+
+  /**
+   * <p>
+   * Gets a {@link WorkflowTask} from an XML-RPC {@link Hashtable} sent over the
+   * wire.
+   * </p>
+   * 
+   * @param task
+   *          The XML-RPC Hashtable version of the WorkflowTask.
+   * @return a {@link WorkflowTask} from an XML-RPC {@link Hashtable} sent over
+   *         the wire.
+   */
+  public static WorkflowTask getWorkflowTaskFromXmlRpc(Hashtable task) {
+    WorkflowTask t = new WorkflowTask();
+    t.setTaskInstanceClassName((String) task.get("class"));
+    t.setTaskId((String) task.get("id"));
+    t.setTaskName((String) task.get("name"));
+    t.setOrder(Integer.valueOf((String) task.get("order")).intValue());
+    t.setTaskConfig(getWorkflowTaskConfigurationFromXmlRpc((Hashtable) task
+        .get("configuration")));
+    t.setConditions(getWorkflowConditionsFromXmlRpc((Vector) task
+        .get("conditions")));
+    t.setRequiredMetFields(getWorkflowTaskReqMetFieldsFromXmlRpc((Vector) task
+        .get("requiredMetFields")));
+
+    return t;
+  }
+
+  /**
+   * <p>
+   * Gets a {@link List} of {@link WorkflowTask}s from an XML-RPC {@link Vector}
+   * .
+   * </p>
+   * 
+   * @param tsks
+   *          The {@link Vector} of {@link WorkflowTask}s.
+   * @return A {@link List} of {@link WorkflowTask}s from an XML-RPC
+   *         {@link Vector}.
+   */
+  public static List getWorkflowTasksFromXmlRpc(Vector tsks) {
+    List tasks = new Vector();
+
+    for (Iterator i = tsks.iterator(); i.hasNext();) {
+      Hashtable taskHashtable = (Hashtable) i.next();
+      WorkflowTask task = getWorkflowTaskFromXmlRpc(taskHashtable);
+      tasks.add(task);
+
+    }
+    return tasks;
+  }
+
+  /**
+   * <p>
+   * Gets an XML-RPC {@link Hashtable} representation of the
+   * {@link WorkflowCondition} to send over the wire.
+   * </p>
+   * 
+   * @param c
+   *          The WorkflowCondition to turn into an XML-RPC Hashtable.
+   * @return an XML-RPC {@link Hashtable} representation of the
+   *         {@link WorkflowCondition} to send over the wire.
+   */
+  public static Hashtable getXmlRpcWorkflowCondition(WorkflowCondition c) {
+    Hashtable condition = new Hashtable();
+    condition.put("class", c.getConditionInstanceClassName());
+    condition.put("id", c.getConditionId());
+    condition.put("name", c.getConditionName());
+    condition.put("order", String.valueOf(c.getOrder()));
+    condition.put("timeout", String.valueOf(c.getTimeoutSeconds()));
+    condition.put("optional", String.valueOf(c.isOptional()));
+    condition.put("configuration",
+        getXmlRpcWorkflowConditionConfig(c.getCondConfig()));
+    return condition;
+
+  }
+
+  /**
+   * Bulids an XML-RPC friendly version of a
+   * {@link WorkflowConditionConfiguration}.
+   * 
+   * @param conf
+   *          The {@link WorkflowConditionConfiguration} to transform into an
+   *          XML-RPC {@link Hashtable}.
+   * @return an XML-RPC friendly version of a
+   *         {@link WorkflowConditionConfiguration}.
+   */
+  public static Hashtable getXmlRpcWorkflowConditionConfig(
+      WorkflowConditionConfiguration conf) {
+    Hashtable confHash = new Hashtable();
+    for (String propName : (Set<String>) (Set<?>) conf.getProperties().keySet()) {
+      confHash.put(propName, conf.getProperty(propName));
+    }
+    return confHash;
+  }
+
+  /**
+   * <p>
+   * Gets a {@link Vector} representation of the {@link List} of
+   * {@link WorkflowCondition}s to be sent across the XML-RPC wire.
+   * </p>
+   * 
+   * @param conditions
+   *          The List of WorkflowConditions to turn into a Vector.
+   * @return A {@link Vector} representation of a {@link List} of
+   *         {@link WorkflowCondition}s.
+   */
+  public static Vector getXmlRpcWorkflowConditions(List conditions) {
+    Vector wConditions = new Vector();
+
+    /*
+     * because conditions are optional, so if they're null, just return an empty
+     * Vector: XML-RPC doesn't support null
+     */
+    if (conditions == null) {
+      return wConditions;
+    }
+
+    for (Iterator i = conditions.iterator(); i.hasNext();) {
+      WorkflowCondition c = (WorkflowCondition) i.next();
+      Hashtable condition = getXmlRpcWorkflowCondition(c);
+      wConditions.add(condition);
+    }
+
+    return wConditions;
+  }
+
+  /**
+   * Gets the required {@link List} of {@link String} met fields for this
+   * {@link WorkflowTask}.
+   * 
+   * @param fields
+   *          The fields required for this task.
+   * @return The {@link List} of {@link String} met fields for this
+   *         {@link WorkflowTask}.
+   */
+  public static List getWorkflowTaskReqMetFieldsFromXmlRpc(Vector fields) {
+    List reqFields = new Vector();
+
+    if (fields == null) {
+      return reqFields;
+    }
+
+    for (Iterator i = fields.iterator(); i.hasNext();) {
+      String reqField = (String) i.next();
+      reqFields.add(reqField);
+    }
+
+    return reqFields;
+  }
+
+  /**
+   * Gets a {@link List} of {@link String}s that are required {@link Metadata}
+   * fields for this {@link WorkflowTask}.
+   * 
+   * @param metFields
+   *          The required {@link Metadata} fields.
+   * @return A {@link List} of {@link String}s that are required for this
+   *         {@link WorkflowTask}.
+   */
+  public static Vector getXmlRpcWorkflowTaskReqMetFields(List metFields) {
+    Vector fields = new Vector();
+    if (metFields == null) {
+      return fields;
+    }
+
+    for (Iterator i = metFields.iterator(); i.hasNext();) {
+      String reqFieldName = (String) i.next();
+      fields.add(reqFieldName);
+    }
+
+    return fields;
+  }
+
+  /**
+   * <p>
+   * Gets a {@link WorkflowCondition} from an XML-RPC {@link Hashtable}.
+   * </p>
+   * 
+   * @param cond
+   *          The Hashtable to turn into a real WorkflowCondition.
+   * @return a {@link WorkflowCondition} from an XML-RPC {@link Hashtable}.
+   */
+  public static WorkflowCondition getWorkflowConditionFromXmlRpc(Hashtable cond) {
+    WorkflowCondition condition = new WorkflowCondition();
+    condition.setConditionInstanceClassName((String) cond.get("class"));
+    condition.setConditionId((String) cond.get("id"));
+    condition.setConditionName((String) cond.get("name"));
+    condition.setOrder(Integer.valueOf((String) cond.get("order")).intValue());
+    condition
+        .setTimeoutSeconds(Long.valueOf(cond.get("timeout") != null ? (String) cond
+            .get("timeout") : "-1"));
+    condition.setOptional(Boolean.valueOf((String) cond.get("optional")));
+    condition
+        .setCondConfig(getWorkflowConditionConfigurationFromXmlRpc((Hashtable) cond
+            .get("configuration")));
+    return condition;
+  }
+
+  /**
+   * Unravels a {@link WorkflowConditionConfiguration} from XML-RPC.
+   * 
+   * @param conf
+   *          XML-RPC friendly Hashtable representing a
+   *          {@link WorkflowConditionConfiguration}.
+   * @return A {@link WorkflowConditionConfiguration} from XML-RPC.
+   */
+  public static WorkflowConditionConfiguration getWorkflowConditionConfigurationFromXmlRpc(
+      Hashtable conf) {
+    WorkflowConditionConfiguration config = new WorkflowConditionConfiguration();
+    for (String key : (Set<String>) (Set<?>) conf.keySet()) {
+      config.addConfigProperty(key, (String) conf.get(key));
+    }
+
+    return config;
+  }
+
+  /**
+   * <p>
+   * Gets a {@link List} of {@link WorkflowCondition}s from an XML-RPC
+   * {@link Vector}.
+   * </p>
+   * 
+   * @param conds
+   *          The {@link Vector} of {@link WorkflowCondition}s.
+   * @return A {@link List} of {@link WorkflowCondition}s from an XML-RPC
+   *         {@link Vector}.
+   */
+  public static List getWorkflowConditionsFromXmlRpc(Vector conds) {
+    List conditions = new Vector();
+
+    if (conds != null && conds.size() > 0) {
+      for (Iterator i = conds.iterator(); i.hasNext();) {
+        Hashtable cond = (Hashtable) i.next();
+        WorkflowCondition condition = getWorkflowConditionFromXmlRpc(cond);
+        conditions.add(condition);
+      }
+    }
+
+    return conditions;
+  }
+
+  /**
+   * <p>
+   * Gets a {@link Hashtable} representation of the passed in
+   * {@link WorkflowTaskConfiguration}'s {@link Properties} to be sent across
+   * the XML-RPC wire.
+   * </p>
+   * 
+   * @param config
+   *          The WorkflowTaskConfiguration to convert to a Hashtable.
+   * @return A {@link Hashtable} representation of the passed in
+   *         {@link WorkflowTaskConfiguration}'s {@link Properties}.
+   */
+  public static Hashtable getXmlRpcWorkflowTaskConfiguration(
+      WorkflowTaskConfiguration config) {
+    Hashtable configuration = new Hashtable();
+
+    for (Iterator i = config.getProperties().keySet().iterator(); i.hasNext();) {
+      String name = (String) i.next();
+      String value = (String) config.getProperties().get(name);
+      configuration.put(name, value);
+    }
+
+    return configuration;
+  }
+
+  /**
+   * <p>
+   * Gets a {@link WorkflowTaskConfiguration} from an XML-RPC {@link Hashtable}.
+   * 
+   * @param config
+   *          The original Hashtable version of the WorkflowTaskConfiguration.
+   * @return A {@link WorkflowTaskConfiguration} from an XML-RPC
+   *         {@link Hashtable}.
+   */
+  public static WorkflowTaskConfiguration getWorkflowTaskConfigurationFromXmlRpc(
+      Hashtable config) {
+    WorkflowTaskConfiguration configuration = new WorkflowTaskConfiguration();
+
+    for (Iterator i = config.keySet().iterator(); i.hasNext();) {
+      String name = (String) i.next();
+      String value = (String) config.get(name);
+
+      configuration.getProperties().put(name, value);
+    }
+
+    return configuration;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/XmlStructFactory.java b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/XmlStructFactory.java
new file mode 100644
index 0000000..243c152
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/java/org/apache/oodt/cas/workflow/util/XmlStructFactory.java
@@ -0,0 +1,340 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.util;
+
+//JDK imports
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.HashMap;
+import java.util.logging.Logger;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+
+/**
+ * * A class for constructing Workflow Manager objects from XML {@link Node}s
+ * and {@link Element}s.
+ * 
+ * @author mattmann
+ * @version $Revsion$
+ * 
+ */
+public final class XmlStructFactory {
+
+  /* our log stream */
+  public static Logger LOG = Logger.getLogger(XmlStructFactory.class.getName());
+
+  private XmlStructFactory() throws InstantiationException {
+    throw new InstantiationException("Don't instantiate XML Struct Factories!");
+  }
+
+  /**
+   * <p>
+   * Creates {@link Workflow}s from the XML Node and the map of existing
+   * {@link WorkflowTask}s.
+   * </p>
+   * 
+   * @param node
+   *          The XML node to construct the Workflow from.
+   * @param tasks
+   *          The {@link HashMap} of existing {@link WorkflowTask}s.
+   * 
+   * @param conditions
+   *          The {@link HashMap} of existing {@link WorkflowCondition}s.
+   * 
+   * @return A new {@link Workflow} created from the XML node.
+   */
+  public static Workflow getWorkflow(Node node, HashMap tasks,
+      HashMap conditions) {
+    Element workflowRoot = (Element) node;
+
+    String id = workflowRoot.getAttribute("id");
+    String name = workflowRoot.getAttribute("name");
+
+    Workflow workflow = new Workflow();
+    workflow.setName(name);
+    workflow.setId(id);
+
+    Element taskElem = getFirstElement("tasks", workflowRoot);
+    Element conditionsElem = getFirstElement("conditions", workflowRoot);
+
+    if (taskElem != null)
+      workflow.setTasks(getTasks(taskElem, tasks));
+    if (conditionsElem != null)
+      workflow.setConditions(getConditions(conditionsElem, conditions));
+
+    return workflow;
+  }
+
+  /**
+   * <p>
+   * Constructs a new {@link WorkflowTask} from the given XML node and
+   * {@link HashMap} of {@link WorkflowCondition}s.
+   * </p>
+   * 
+   * @param node
+   *          The XML node to construct the {@link WorkflowTask} from.
+   * @param conditions
+   *          The {@link HashMap} of {@link WorkflowCondition}s to use when
+   *          constructing the WorkflowTask.
+   * @return A new {@link WorkflowTask} created from the given XML node.
+   */
+  public static WorkflowTask getWorkflowTask(Node node, HashMap conditions) {
+    Element taskNode = (Element) node;
+
+    String taskClassName = taskNode.getAttribute("class");
+    WorkflowTask task = new WorkflowTask();
+    task.setTaskInstanceClassName(taskClassName);
+
+    task.setTaskId(taskNode.getAttribute("id"));
+    task.setTaskName(taskNode.getAttribute("name"));
+
+    // get the list of condition IDs for this task and then get the
+    // conditions for them
+    task.setConditions(getConditions(taskNode, conditions));
+
+    Element reqMetFieldsElem = getFirstElement("requiredMetFields", taskNode);
+    if (reqMetFieldsElem != null) {
+      task.setRequiredMetFields(getRequiredMetFields(reqMetFieldsElem));
+    }
+
+    // load its configuration
+    Element configElement = getFirstElement("configuration", taskNode);
+    if (configElement != null) {
+      task.setTaskConfig(new WorkflowTaskConfiguration(
+          getConfiguration(configElement)));
+    }
+
+    return task;
+  }
+
+  /**
+   * <p>
+   * Constructs a new {@link WorkflowCondition} from the given XML Node.
+   * </p>
+   * 
+   * @param node
+   *          The XML node to construct the WorkflowCondition from.
+   * @return A new {@link WorkflowCondition} from the given XML node.
+   */
+  public static WorkflowCondition getWorkflowCondition(Node node) {
+    Element conditionElement = (Element) node;
+
+    String conditionClassName = conditionElement.getAttribute("class");
+    WorkflowCondition condition = new WorkflowCondition();
+    condition.setConditionInstanceClassName(conditionClassName);
+    condition.setConditionId(conditionElement.getAttribute("id"));
+    condition.setConditionName(conditionElement.getAttribute("name"));
+    condition
+        .setTimeoutSeconds(Long.valueOf(conditionElement
+            .getAttribute("timeout") != null
+            && !conditionElement.getAttribute("timeout").equals("") ? conditionElement
+            .getAttribute("timeout") : "-1"));
+    condition.setOptional(Boolean.valueOf(conditionElement
+        .getAttribute("optional")));
+
+    // load its configuration
+    Element configElement = getFirstElement("configuration", conditionElement);
+    if (configElement != null) {
+      condition.setCondConfig(new WorkflowConditionConfiguration(
+          getConfiguration(configElement)));
+    }
+
+    return condition;
+
+  }
+
+  /**
+   * 
+   * @param node
+   * @return
+   */
+  public static List getRequiredMetFields(Node node) {
+    Element reqMetFieldsElem = (Element) node;
+
+    NodeList reqMetFieldNodes = reqMetFieldsElem
+        .getElementsByTagName("metfield");
+    List reqFields = null;
+
+    if (reqMetFieldNodes != null && reqMetFieldNodes.getLength() > 0) {
+      reqFields = new Vector(reqMetFieldNodes.getLength());
+      for (int i = 0; i < reqMetFieldNodes.getLength(); i++) {
+        Element reqMetFieldElem = (Element) reqMetFieldNodes.item(i);
+        String reqFieldName = reqMetFieldElem.getAttribute("name");
+        reqFields.add(reqFieldName);
+
+      }
+    }
+
+    return reqFields;
+  }
+
+  /**
+   * <p>
+   * Constructs a new {@link WorkflowTaskConfiguration} from the given XML node.
+   * </p>
+   * 
+   * @param node
+   *          The XML node to construct the WorkflowTaskConfiguration from.
+   * @return A new {@link WorkflowTaskConfiguration} constructed from the given
+   *         XML node.
+   */
+  public static Properties getConfiguration(Node node) {
+    Element configNode = (Element) node;
+
+    NodeList configProperties = configNode.getElementsByTagName("property");
+
+    if (configProperties == null) {
+      return null;
+    }
+
+    Properties properties = new Properties();
+    for (int i = 0; i < configProperties.getLength(); i++) {
+      Element propElem = (Element) configProperties.item(i);
+      String value = propElem.getAttribute("value");
+
+      boolean doReplace = Boolean.valueOf(propElem.getAttribute("envReplace"))
+          .booleanValue();
+      if (doReplace) {
+        value = PathUtils.replaceEnvVariables(value);
+      }
+      properties.put(propElem.getAttribute("name"), value);
+    }
+
+    return properties;
+  }
+
+  public static Metadata getConfigurationAsMetadata(Node configNode)
+      throws Exception {
+    Metadata curMetadata = new Metadata();
+    NodeList curGrandChildren = configNode.getChildNodes();
+    for (int k = 0; k < curGrandChildren.getLength(); k++) {
+      if (curGrandChildren.item(k).getNodeName().equals("property")) {
+        Element property = (Element) curGrandChildren.item(k);
+        String delim = property.getAttribute("delim");
+        String envReplace = property.getAttribute("envReplace");
+        String name = property.getAttribute("name");
+        String value = property.getAttribute("value");
+        if (Boolean.parseBoolean(envReplace))
+          value = PathUtils.doDynamicReplacement(value);
+        List<String> values = new Vector<String>();
+        if (delim.length() > 0)
+          values.addAll(Arrays.asList(value.split("\\" + delim)));
+        else
+          values.add(value);
+        curMetadata.replaceMetadata(name, values);
+      }
+    }
+    return curMetadata;
+  }
+
+  private static List<WorkflowTask> getTasks(Element rootNode, HashMap tasks) {
+    NodeList taskList = rootNode.getElementsByTagName("task");
+    List<WorkflowTask> workflowTasks = null;
+
+    if (taskList != null && taskList.getLength() > 0) {
+      workflowTasks = new Vector<WorkflowTask>(taskList.getLength());
+
+      for (int i = 0; i < taskList.getLength(); i++) {
+        Element taskElement = (Element) taskList.item(i);
+
+        WorkflowTask t = (WorkflowTask) tasks.get(taskElement
+            .getAttribute("id"));
+
+        if (t != null) {
+          WorkflowTask workflowTask = new WorkflowTask();
+          workflowTask.setTaskInstanceClassName(t.getTaskInstanceClassName());
+          workflowTask.setConditions(t.getConditions());
+          workflowTask.setTaskId(t.getTaskId());
+          workflowTask.setTaskConfig(t.getTaskConfig());
+          workflowTask.setTaskName(t.getTaskName());
+          workflowTask.setOrder(i + 1);
+          workflowTask.setRequiredMetFields(t.getRequiredMetFields());
+          workflowTasks.add(workflowTask);
+        }
+      }
+
+    }
+
+    return workflowTasks;
+  }
+
+  private static List<WorkflowCondition> getConditions(Element rootNode,
+      HashMap conditions) {
+    List<WorkflowCondition> conditionList = new Vector<WorkflowCondition>();
+    NodeList conditionNodes = rootNode.getElementsByTagName("condition");
+
+    if (conditionNodes != null && conditionNodes.getLength() > 0) {
+      conditionList = new Vector<WorkflowCondition>(conditionNodes.getLength());
+
+      for (int i = 0; i < conditionNodes.getLength(); i++) {
+        Element conditionNode = (Element) conditionNodes.item(i);
+        WorkflowCondition condition = (WorkflowCondition) conditions
+            .get(conditionNode.getAttribute("id"));
+
+        if (condition != null) {
+          WorkflowCondition workflowCondition = new WorkflowCondition();
+          workflowCondition.setConditionInstanceClassName(condition
+              .getConditionInstanceClassName());
+          workflowCondition.setConditionId(condition.getConditionId());
+          workflowCondition.setConditionName(condition.getConditionName());
+          workflowCondition.setOrder(i + 1);
+          workflowCondition.setTimeoutSeconds(condition.getTimeoutSeconds());
+          workflowCondition.setOptional(condition.isOptional());
+          workflowCondition.setCondConfig(condition.getCondConfig());
+          conditionList.add(workflowCondition);
+        }
+      }
+
+    }
+
+    return conditionList;
+  }
+
+  private static Element getFirstElement(String name, Element root) {
+    NodeList list = root.getElementsByTagName(name);
+    if (list != null) {
+      return (Element) list.item(0);
+    } else
+      return null;
+  }
+
+  private static String getSimpleElementText(Element node) {
+    if (node.getChildNodes().item(0) instanceof Text) {
+      return node.getChildNodes().item(0).getNodeValue();
+    } else
+      return null;
+  }
+
+  private static String getElementText(String elemName, Element root) {
+    Element elem = getFirstElement(elemName, root);
+    return getSimpleElementText(elem);
+  }
+}
diff --git a/0.8.1-rc1/workflow/src/main/python/xmlrpc-wrapper/oodt_metadata.py b/0.8.1-rc1/workflow/src/main/python/xmlrpc-wrapper/oodt_metadata.py
new file mode 100644
index 0000000..1f1a9a9
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/python/xmlrpc-wrapper/oodt_metadata.py
@@ -0,0 +1,29 @@
+#	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. 
+
+
+class MetaData(object):
+	def __init__(self):
+		self.data = {}
+
+	def addMetaData(self, key, value):
+		if key not in self.data:
+			self.data[key] = []
+		self.data[key].append(value)
+
+	def toXmlRpc(self):
+		return self.data
diff --git a/0.8.1-rc1/workflow/src/main/python/xmlrpc-wrapper/oodt_workflow_xmlrpc.py b/0.8.1-rc1/workflow/src/main/python/xmlrpc-wrapper/oodt_workflow_xmlrpc.py
new file mode 100644
index 0000000..ae83c23
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/python/xmlrpc-wrapper/oodt_workflow_xmlrpc.py
@@ -0,0 +1,134 @@
+#	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.
+
+
+import xmlrpclib
+from oodt_metadata import MetaData
+
+
+class OODTWorkFlowWrapper(object):
+	def __init__(self, host):
+		self._server = xmlrpclib.Server(host)
+
+	#String	    executeDynamicWorkflow(Vector<String> taskIds, Hashtable metadata)
+	def executeDynamicWorkflow(self, taskIds, metadata):
+		return self._server.workflowmgr.executeDynamicWorkflow(taskIds, metadata)
+	#Hashtable	getConditionById(String conditionId)
+	def getConditionById(self, conditionId):
+		return self._server.workflowmgr.getConditionById(conditionId)
+	#Hashtable	getFirstPage()
+	def getFirstPage(self):
+		return self._server.workflowmgr.getFirstPage()
+	#Hashtable	getLastPage()
+	def getLastPage(self):
+		return self._server.workflowmgr.getLastPage()
+	#Hashtable	getNextPage(Hashtable currentPage)
+	def getNextPage(self, currentPage):
+		return self._server.workflowmgr.getNextPage()
+	#int	    getNumWorkflowInstances()
+	def getNumWorkflowInstances(self):
+		return self._server.workflowmgr.getNumWorkflowInstances()
+	#int	    getNumWorkflowInstancesByStatus(String status)
+	def getNumWorkflowInstancesByStatus(self, status):
+		return self._server.workflowmgr.getNumWorkflowInstancesByStatus(status)
+	#Hashtable	getPrevPage(Hashtable currentPage)
+	def getPrevPage(self, currentPage):
+		return self._server.workflowmgr.getPrevPage(currentPage)
+	#Vector 	getRegisteredEvents()
+	def getEventNames(self):
+		return self._server.workflowmgr.getRegisteredEvents()
+	#Hashtable	getTaskById(String taskId)
+	def getTaskById(self, taskId):
+		return self._server.workflowmgr.getTaskById(taskId)
+	#Hashtable	getWorkflowById(String workflowId)
+	def getWorkflowById(self, workflowId):
+		return self._server.workflowmgr.getWorkflowById(workflowId)
+	#double	    getWorkflowCurrentTaskWallClockMinutes(String workflowInstId)
+	def getWorkflowCurrentTaskWallClockMinutes(self, workflowInstId):
+		return self._server.workflowmgr.getWorkflowCurrentTaskWallClockMinutes(workflowInstId)
+	#Hashtable	getWorkflowInstanceById(String wInstId)
+	def getWorkflowInstanceById(self,wInstId):
+		return self._server.workflowmgr.getWorkflowInstanceById(wInstId)
+	#Hashtable	getWorkflowInstanceMetadata(String wInstId)
+	def getWorkflowInstanceMetadata(self, wInstId):
+		return self._server.workflowmgr.getWorkflowInstanceMetadata(wInstId)
+	#Vector		getWorkflowInstances()
+	def getWorkflowInstances(self):
+		return self._server.workflowmgr.getWorkflowInstances()
+	#Vector		getWorkflowInstancesByStatus(String status)
+	def getWorkflowInstancesByStatus(self, status):
+		return self._server.workflowmgr.getWorkflowInstancesByStatus(status)
+	#Vector		getWorkflows()
+	def getWorkflows(self):
+		return self._server.workflowmgr.getWorkflows()
+	#Vector		getWorkflowsByEvent(String eventName)
+	def getWorkflowsByEvent(self, eventName):
+		return self._server.workflowmgr.getWorkflowsByEvent(eventName)
+	#double		getWorkflowWallClockMinutes(String workflowInstId)
+	def getWorkflowWallClockMinutes(self,workflowInstId):
+		return getWorkflowWallClockMinutes(workflowInstId)
+	#boolean	handleEvent(String eventName, Hashtable metadata)
+	def startEvent(self, eventName, metaData):
+		return self._server.workflowmgr.handleEvent(eventName, metaData)
+	#Hashtable	paginateWorkflowInstances(int pageNum)
+	def paginateWorkflowInstances(self, pageNum):
+		return self._server.workflowmgr.paginateWorkflowInstances(pageNum)
+	#Hashtable	paginateWorkflowInstances(int pageNum, String status)(self, workflowInstId)
+	def paginateWorkflowInstances(self, pageNum, status):
+		return self._server.workflowmgr.paginateWorkflowInstances(pageNum, status)
+	#boolean	pauseWorkflowInstance(String workflowInstId)
+	def pauseWorkflowInstance(self, workflowInstId):
+		return self._server.workflowmgr.pauseWorkflowInstance(workflowInstId)
+	#boolean	resumeWorkflowInstance(String workflowInstId)
+	def resumeWorkflowInstance(self, workflowInstId):
+		return self._server.workflowmgr.resumeWorkflowInstance(workflowInstId)
+	#boolean	setWorkflowInstanceCurrentTaskEndDateTime(String wInstId, String endDateTimeIsoStr)
+	def setWorkflowInstanceCurrentTaskEndDateTime(self, workflowInstId, endDateTimeIsoStr):
+		return self._server.workflowmgr.setWorkflowInstanceCurrentTaskEndDateTime(workflowInstId, endDateTimeIsoStr)
+	#boolean	setWorkflowInstanceCurrentTaskStartDateTime(String wInstId, String startDateTimeIsoStr)
+	def setWorkflowInstanceCurrentTaskStartDateTime(self, workflowInstId, startDateTimeIsoStr):
+		return self._server.workflowmgr.setWorkflowInstanceCurrentTaskStartDateTime(workflowInstId, startDateTimeIsoStr)
+	#boolean	stopWorkflowInstance(String workflowInstId)
+	def stopWorkflowInstance(self, workflowInstId):
+		return self._server.workflowmgr.stopWorkflowInstance(workflowInstId)
+	#boolean	updateMetadataForWorkflow(String workflowInstId, Hashtable metadata)
+	def updateMetadataForWorkflow(self, workflowInstId, metadata):
+		return self._server.workflowmgr.updateMetadataForWorkflow(workflowInstId, metadata)
+	#boolean	updateWorkflowInstance(Hashtable workflowInst)
+	def updateWorkflowInstance(workflowInst):
+		return self._server.workflowmgr.updateWorkflowInstance(workflowInst)
+	#boolean	updateWorkflowInstanceStatus(String workflowInstanceId, String status)
+	def updateWorkflowInstanceStatus(self, workflowInstId, status):
+		return self._server.workflowmgr.updateWorkflowInstanceStatus(workflowInstId, status) 
+
+
+
+def main():
+	# create instance
+    oodt = OODTWorkFlowWrapper("http://localhost:9200")
+    # get event info
+    events = oodt.getEventNames()
+    # create metadata object to invoke an event
+    met = MetaData()
+    met.addMetaData("hello", "world")
+    # print available events
+    print 'available events:', events
+
+    # oodt.startEvent(events[0], met.toXmlRpc())
+
+if __name__ == '__main__':
+    main()
diff --git a/0.8.1-rc1/workflow/src/main/resources/REMOVE.log b/0.8.1-rc1/workflow/src/main/resources/REMOVE.log
new file mode 100644
index 0000000..cb27d16
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/REMOVE.log
@@ -0,0 +1,18 @@
+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.
+
+
+You can remove this file. It was only included to ensure that the log directory for this
+distribution was created on assembly.
diff --git a/0.8.1-rc1/workflow/src/main/resources/cmd-line-actions.xml b/0.8.1-rc1/workflow/src/main/resources/cmd-line-actions.xml
new file mode 100644
index 0000000..ea28b4a
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/cmd-line-actions.xml
@@ -0,0 +1,85 @@
+<?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.
+
+  Author: bfoster (Brian Foster)
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+	<bean id="sendEvent" class="org.apache.oodt.cas.workflow.cli.action.SendEventCliAction">
+		<property name="description" value="Triggers an event" />
+	</bean>
+	<bean id="dynWorkflow" class="org.apache.oodt.cas.workflow.cli.action.DynWorkflowCliAction">
+    <property name="description" value="Creates a workflow using the given tasks and then executes it" />
+  </bean>
+  <bean id="getWorkflowInsts" class="org.apache.oodt.cas.workflow.cli.action.GetWorkflowInstsCliAction">
+    <property name="description" value="List all workflow instances" />
+  </bean>
+  <bean id="getWorkflows" class="org.apache.oodt.cas.workflow.cli.action.GetWorkflowsCliAction">
+    <property name="description" value="List all workflow models" />
+  </bean>
+  <bean id="getTaskById" class="org.apache.oodt.cas.workflow.cli.action.GetTaskByIdCliAction">
+    <property name="description" value="Gets task information for task with given ID" />
+  </bean>
+  <bean id="getConditionById" class="org.apache.oodt.cas.workflow.cli.action.GetConditionByIdCliAction">
+    <property name="description" value="Gets condition information for condition with given ID" />
+  </bean>
+  <bean id="getWorkflowById" class="org.apache.oodt.cas.workflow.cli.action.GetWorkflowByIdCliAction">
+    <property name="description" value="Gets workflow information for workflow with given ID" />
+  </bean>
+  <bean id="getWorkflowsByEvent" class="org.apache.oodt.cas.workflow.cli.action.GetWorkflowsByEventCliAction">
+    <property name="description" value="List workflow information for workflows with attached to event" />
+  </bean>
+  <bean id="getRegisteredEvents" class="org.apache.oodt.cas.workflow.cli.action.GetRegisteredEventsCliAction">
+    <property name="description" value="List registered events" />
+  </bean>
+  <bean id="getWorkflowInst" class="org.apache.oodt.cas.workflow.cli.action.GetWorkflowInstCliAction">
+    <property name="description" value="Gets workflow instance by instance ID" />
+  </bean>
+  <bean id="getWallClockTime" class="org.apache.oodt.cas.workflow.cli.action.GetWallClockTimeCliAction">
+    <property name="description" value="Gets wall clock time for workflow instance" />
+  </bean>
+  <bean id="getTaskWallClockTime" class="org.apache.oodt.cas.workflow.cli.action.GetTaskWallClockTimeCliAction">
+    <property name="description" value="Gets wall clock time for workflow instance's current task" />
+  </bean>
+  <bean id="stopWorkflowInst" class="org.apache.oodt.cas.workflow.cli.action.StopWorkflowInstCliAction">
+    <property name="description" value="Stops a workflow instance" />
+  </bean>
+  <bean id="pauseWorkflowInst" class="org.apache.oodt.cas.workflow.cli.action.PauseWorkflowInstCliAction">
+    <property name="description" value="Pauses a workflow instance" />
+  </bean>
+  <bean id="resumeWorkflowInst" class="org.apache.oodt.cas.workflow.cli.action.ResumeWorkflowInstCliAction">
+    <property name="description" value="Resumes a paused workflow instance" />
+  </bean>
+  <bean id="getFirstPage" class="org.apache.oodt.cas.workflow.cli.action.GetFirstPageCliAction">
+    <property name="description" value="Gets first page of workflows" />
+  </bean>
+  <bean id="getNextPage" class="org.apache.oodt.cas.workflow.cli.action.GetNextPageCliAction">
+    <property name="description" value="Gets next page of workflows" />
+  </bean>
+  <bean id="getPrevPage" class="org.apache.oodt.cas.workflow.cli.action.GetPrevPageCliAction">
+    <property name="description" value="Gets prev page of workflows" />
+  </bean>
+  <bean id="getLastPage" class="org.apache.oodt.cas.workflow.cli.action.GetLastPageCliAction">
+    <property name="description" value="Gets last page of workflows" />
+  </bean>
+  <bean id="getWorkflowInstMet" class="org.apache.oodt.cas.workflow.cli.action.GetWorkflowInstMetCliAction">
+    <property name="description" value="Gets workflow instance metadata" />
+  </bean>
+
+</beans>
diff --git a/0.8.1-rc1/workflow/src/main/resources/cmd-line-options.xml b/0.8.1-rc1/workflow/src/main/resources/cmd-line-options.xml
new file mode 100644
index 0000000..e171838
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/cmd-line-options.xml
@@ -0,0 +1,683 @@
+<?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. Author: 
+	bfoster (Brian Foster) -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+	<bean id="url" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="u" />
+		<property name="longOption" value="url" />
+		<property name="description" value="Workflow Manager URL" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="url" />
+		<property name="required" value="true" />
+		<property name="handler">
+			<bean
+				class="org.apache.oodt.cas.cli.option.handler.SetJavaPropertiesHandler">
+				<property name="propertyNames">
+					<list>
+						<value>org.apache.oodt.cas.workflow.url</value>
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="operation" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+		<property name="shortOption" value="op" />
+		<property name="longOption" value="operation" />
+		<property name="description"
+			value="Declare that you wish to present an operation" />
+		<property name="hasArgs" value="false" />
+		<property name="required" value="true" />
+		<property name="subOptions">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="sendEvent" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="dynWorkflow" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getWorkflowInsts" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getWorkflows" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getTaskById" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getConditionById" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getWorkflowById" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getWorkflowsByEvent" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getRegisteredEvents" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getWorkflowInst" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getWallClockTime" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getTaskWallClockTime" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="stopWorkflowInst" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="pauseWorkflowInst" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="resumeWorkflowInst" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getFirstPage" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getNextPage" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getPrevPage" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getLastPage" p:required="false" />
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="getWorkflowInstMet" p:required="false" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- SendEvent Options -->
+	<bean id="sendEvent" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="se" />
+		<property name="longOption" value="sendEvent" />
+		<property name="description" value="Triggers sendEvent Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>sendEvent</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="sendEvent" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- DynWorkflow Options -->
+	<bean id="dynWorkflow" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="dw" />
+		<property name="longOption" value="dynWorkflow" />
+		<property name="description" value="Triggers dynWorkflow Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>dynWorkflow</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="dynWorkflow" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="taskIds" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="tids" />
+		<property name="longOption" value="taskIds" />
+		<property name="description" value="List of workflow task ids" />
+		<property name="type" value="java.util.List" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="task-ids" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="dynWorkflow" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+		</property>
+	</bean>
+
+	<!-- GetWorkflowInsts Options -->
+	<bean id="getWorkflowInsts" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="winsts" />
+		<property name="longOption" value="getWorkflowInsts" />
+		<property name="description" value="Triggers GetWorkflowInsts Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getWorkflowInsts</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="GetWorkflowInsts" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetWorkflows Options -->
+	<bean id="getWorkflows" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="wflows" />
+		<property name="longOption" value="getWorkflows" />
+		<property name="description" value="Triggers getWorkflows Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getWorkflows</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getWorkflows" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetTaskById Options -->
+	<bean id="getTaskById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="tbyid" />
+		<property name="longOption" value="getTaskById" />
+		<property name="description" value="Triggers getTaskById Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getTaskById</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getTaskById" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetTaskById Options -->
+	<bean id="getConditionById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="cbyid" />
+		<property name="longOption" value="getConditionById" />
+		<property name="description" value="Triggers getConditionById Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getConditionById</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getConditionById" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetWorkflowById Options -->
+	<bean id="getWorkflowById" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="wbyid" />
+		<property name="longOption" value="getWorkflowById" />
+		<property name="description" value="Triggers getWorkflowById Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getWorkflowById</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getWorkflowById" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetWorkflowsByEvent Options -->
+	<bean id="getWorkflowsByEvent" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="wbye" />
+		<property name="longOption" value="getWorkflowsByEvent" />
+		<property name="description" value="Triggers getWorkflowsByEvent Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getWorkflowsByEvent</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getWorkflowsByEvent" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetRegisteredEvents Options -->
+	<bean id="getRegisteredEvents" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="events" />
+		<property name="longOption" value="getRegisteredEvents" />
+		<property name="description" value="Triggers getRegisteredEvents Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getRegisteredEvents</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getRegisteredEvents" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetWorkflowInst Options -->
+	<bean id="getWorkflowInst" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="inst" />
+		<property name="longOption" value="getWorkflowInst" />
+		<property name="description" value="Triggers getWorkflowInst Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getWorkflowInst</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getWorkflowInst" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetWallClockTime Options -->
+	<bean id="getWallClockTime" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="time" />
+		<property name="longOption" value="getWallClockTime" />
+		<property name="description" value="Triggers getWallClockTime Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getWallClockTime</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getWallClockTime" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetTaskWallClockTime Options -->
+	<bean id="getTaskWallClockTime" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="ttime" />
+		<property name="longOption" value="getTaskWallClockTime" />
+		<property name="description" value="Triggers getTaskWallClockTime Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getTaskWallClockTime</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getTaskWallClockTime" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- StopWorkflowInst Options -->
+	<bean id="stopWorkflowInst" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="stop" />
+		<property name="longOption" value="stopWorkflowInst" />
+		<property name="description" value="Triggers stopWorkflowInst Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>stopWorkflowInst</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="stopWorkflowInst" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- PauseWorkflowInst Options -->
+	<bean id="pauseWorkflowInst" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="pause" />
+		<property name="longOption" value="pauseWorkflowInst" />
+		<property name="description" value="Triggers pauseWorkflowInst Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>pauseWorkflowInst</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="pauseWorkflowInst" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- ResumeWorkflowInst Options -->
+	<bean id="resumeWorkflowInst" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="resume" />
+		<property name="longOption" value="resumeWorkflowInst" />
+		<property name="description" value="Triggers resumeWorkflowInst Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>resumeWorkflowInst</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="resumeWorkflowInst" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetFirstPage Options -->
+	<bean id="getFirstPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="page1" />
+		<property name="longOption" value="getFirstPage" />
+		<property name="description" value="Triggers getFirstPage Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getFirstPage</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getFirstPage" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetNextPage Options -->
+	<bean id="getNextPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="next" />
+		<property name="longOption" value="getNextPage" />
+		<property name="description" value="Triggers getNextPage Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getNextPage</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNextPage" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetPrevPage Options -->
+	<bean id="getPrevPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="prev" />
+		<property name="longOption" value="getPrevPage" />
+		<property name="description" value="Triggers getPrevPage Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getPrevPage</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getPrevPage" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetLastPage Options -->
+	<bean id="getLastPage" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="last" />
+		<property name="longOption" value="getLastPage" />
+		<property name="description" value="Triggers getLastPage Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getLastPage</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getLastPage" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- GetWorkflowInstMet Options -->
+	<bean id="getWorkflowInstMet" class="org.apache.oodt.cas.cli.option.ActionCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="getMet" />
+		<property name="longOption" value="getWorkflowInstMet" />
+		<property name="description" value="Triggers getWorkflowInstMet Action" />
+		<property name="hasArgs" value="false" />
+		<property name="staticArgs">
+			<list>
+				<value>getWorkflowInstMet</value>
+			</list>
+		</property>
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getWorkflowInstMet" p:relation="REQUIRED" />
+			</list>
+		</property>
+	</bean>
+
+	<!-- Options used for multiple Actions -->
+	<bean id="eventName" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="en" />
+		<property name="longOption" value="eventName" />
+		<property name="description" value="Name of the Event to trigger" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="event-name" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="sendEvent" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getWorkflowsByEvent" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+		</property>
+	</bean>
+
+	<bean id="metaData" class="org.apache.oodt.cas.cli.option.GroupCmdLineOption">
+		<property name="shortOption" value="m" />
+		<property name="longOption" value="metaData" />
+		<property name="description" value="Declare that you wish to present metadata" />
+		<property name="hasArgs" value="false" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="sendEvent" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="dynMetadata" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="subOptions">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.GroupSubOption"
+					p:option-ref="key" p:required="true" />
+			</list>
+		</property>
+	</bean>
+
+	<bean id="key" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption"
+		p:isSubOption="true">
+		<property name="shortOption" value="k" />
+		<property name="longOption" value="key" />
+		<property name="description" value="Workflow Metadata: key val val..." />
+		<property name="type" value="java.util.List" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="key-vals" />
+		<property name="repeating" value="true" />
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+				<property name="applyToActions">
+					<list>
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="sendEvent" p:methodName="addMetadata" />
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="dynWorkflow" p:methodName="addMetadata" />
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="id" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="id" />
+		<property name="longOption" value="id" />
+		<property name="description" value="ID" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="id" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getTaskById" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getConditionById" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getWorkflowById" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getWorkflowInst" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getWallClockTime" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getTaskWallClockTime" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="stopWorkflowInst" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="pauseWorkflowInst" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="resumeWorkflowInst" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getWorkflowInstMet" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler">
+				<property name="applyToActions">
+					<list>
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="getTaskById" p:methodName="setTaskId"
+							p:argDescription="task-id" />
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="getConditionById" p:methodName="setConditionId"
+							p:argDescription="condition-id" />
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="getWorkflowById" p:methodName="setWorkflowId"
+							p:argDescription="workflow-id" />
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="getWorkflowInst" p:methodName="setInstanceId"
+							p:argDescription="instance-id" />
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="getWallClockTime" p:methodName="setInstanceId"
+							p:argDescription="instance-id" />
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="getTaskWallClockTime" p:methodName="setInstanceId"
+							p:argDescription="instance-id" />
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="stopWorkflowInst" p:methodName="setInstanceId"
+							p:argDescription="instance-id" />
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="pauseWorkflowInst" p:methodName="setInstanceId"
+							p:argDescription="instance-id" />
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="resumeWorkflowInst" p:methodName="setInstanceId"
+							p:argDescription="instance-id" />
+						<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToAction"
+							p:actionName="getWorkflowInstMet" p:methodName="setInstanceId"
+							p:argDescription="instance-id" />
+					</list>
+				</property>
+			</bean>
+		</property>
+	</bean>
+
+	<bean id="status" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="s" />
+		<property name="longOption" value="status" />
+		<property name="description" value="Workflow status" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="status" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getFirstPage" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNextPage" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getPrevPage" p:relation="OPTIONAL" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getLastPage" p:relation="OPTIONAL" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+		</property>
+	</bean>
+
+	<bean id="pageNum" class="org.apache.oodt.cas.cli.option.AdvancedCmdLineOption">
+		<property name="shortOption" value="p" />
+		<property name="longOption" value="pageNum" />
+		<property name="description" value="Page Number" />
+		<property name="type" value="int" />
+		<property name="hasArgs" value="true" />
+		<property name="argsDescription" value="page" />
+		<property name="requirementRules">
+			<list>
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getNextPage" p:relation="REQUIRED" />
+				<bean class="org.apache.oodt.cas.cli.option.require.ActionDependencyRule"
+					p:actionName="getPrevPage" p:relation="REQUIRED" />
+			</list>
+		</property>
+		<property name="handler">
+			<bean class="org.apache.oodt.cas.cli.option.handler.ApplyToActionHandler" />
+		</property>
+	</bean>
+</beans>
diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/backwardsTestWorkflow.workflow.xml b/0.8.1-rc1/workflow/src/main/resources/examples/backwardsTestWorkflow.workflow.xml
new file mode 100644
index 0000000..3305e1e
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/backwardsTestWorkflow.workflow.xml
@@ -0,0 +1,22 @@
+<!--

+  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.

+-->

+<cas:workflow xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" name="backwardsTestWorkflow" id="urn:oodt:backwardsTestWorkflow">

+ <tasks>

+   <task id="urn:oodt:GoodbyeWorld"/>

+   <task id="urn:oodt:HelloWorld"/>

+ </tasks>

+</cas:workflow>

diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/condition.workflow.xml b/0.8.1-rc1/workflow/src/main/resources/examples/condition.workflow.xml
new file mode 100755
index 0000000..c339332
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/condition.workflow.xml
@@ -0,0 +1,25 @@
+<!--

+  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.

+-->

+<cas:workflow xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" name="Conditions Workflow" id="urn:oodt:conditionsWorkflow">

+ <conditions>

+   <condition id="urn:oodt:TimeoutCondition"/>

+ </conditions>

+ <tasks>

+   <task id="urn:oodt:IntensiveTask"/>

+   <task id="urn:oodt:IntensiveTask"/>

+ </tasks>

+</cas:workflow>

diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/conditions.xml b/0.8.1-rc1/workflow/src/main/resources/examples/conditions.xml
new file mode 100644
index 0000000..3483861
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/conditions.xml
@@ -0,0 +1,28 @@
+<!--
+  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.
+-->
+<cas:conditions xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+    <condition id="urn:oodt:TrueCondition" name="True Condition" class="org.apache.oodt.cas.workflow.examples.TrueCondition"/>
+    <condition id="urn:oodt:FalseCondition" name="False Condition" class="org.apache.oodt.cas.workflow.examples.FalseCondition"/>
+    <condition id="urn:oodt:LongCondition" name="Long Condition" class="org.apache.oodt.cas.workflow.examples.LongCondition"/>
+    <condition id="urn:oodt:CheckForMetadataKeys" name="Metadata Key Check" class="org.apache.oodt.cas.workflow.examples.CheckForMetadataKeys">
+        <configuration>
+            <property name="reqMetKeys" value="Met1,Met2,Met3"/>
+        </configuration>
+    </condition>
+    <condition id="urn:oodt:TimeoutCondition" name="Timeout Condition" class="org.apache.oodt.cas.workflow.examples.FalseCondition" timeout="30"/>
+    <condition id="urn:oodt:OptionalCondition" name="Optional Condition" class="org.apache.oodt.cas.workflow.examples.FalseCondition" optional="true"/>
+</cas:conditions>
diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/events.xml b/0.8.1-rc1/workflow/src/main/resources/examples/events.xml
new file mode 100644
index 0000000..7ed26ae
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/events.xml
@@ -0,0 +1,55 @@
+<!--
+  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.
+-->
+<cas:workflowevents xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<event name="test">
+		<workflow id="urn:oodt:testWorkflow" />
+	</event>
+	<event name="externalScript">
+        <workflow id="urn:oodt:externalScriptWorkflow" />
+    </event>
+	<event name="backwards">
+		<workflow id="urn:oodt:backwardsTestWorkflow" />
+	</event>
+	<event name="stuck">
+		<workflow id="urn:oodt:wontFinishWorkflow" />
+	</event>
+	<event name="long">
+		<workflow id="urn:oodt:longWorkflow" />
+		<workflow id="urn:oodt:longWorkflow" />
+	</event>
+	<event name="metUpdate">
+		<workflow id="urn:oodt:testMetadataUpdateWorkflow" />
+	</event>
+	<event name="statusUpdate">
+		<workflow id="urn:oodt:testStatusUpdateWorkflow" />
+	</event>
+	<event name="metError">
+		<workflow id="urn:oodt:testMetErrorWorkflow" />
+	</event>
+	<event name="timeout">
+	    <workflow id="urn:oodt:timeoutWorkflow"/>
+	</event>
+	<event name="optional">
+	    <workflow id="urn:oodt:optionalWorkflow"/>
+	</event>
+	<event name="conditions">
+	    <workflow id="urn:oodt:conditionsWorkflow"/>
+	</event>
+    <event name="GenericFileIngest">
+       <workflow id="urn:oodt:mailWorkflow"/>
+    </event>
+</cas:workflowevents>
diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/externalScript.workflow.xml b/0.8.1-rc1/workflow/src/main/resources/examples/externalScript.workflow.xml
new file mode 100644
index 0000000..bba0986
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/externalScript.workflow.xml
@@ -0,0 +1,21 @@
+<!--
+  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.
+-->
+<cas:workflow xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" name="External Script Workflow" id="urn:oodt:externalScriptWorkflow">
+ <tasks>
+   <task id="urn:oodt:ExternalScriptTask"/>
+ </tasks>
+</cas:workflow>
diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/longWorkflow.workflow.xml b/0.8.1-rc1/workflow/src/main/resources/examples/longWorkflow.workflow.xml
new file mode 100644
index 0000000..0306654
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/longWorkflow.workflow.xml
@@ -0,0 +1,24 @@
+<!--

+  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.

+-->

+<cas:workflow xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" name="Long Workflow" id="urn:oodt:longWorkflow">

+ <tasks>

+   <task id="urn:oodt:HelloWorld"/>

+   <task id="urn:oodt:GoodbyeWorld"/>

+   <task id="urn:oodt:IntensiveTask"/>

+   <task id="urn:oodt:IntensiveTaskWithWait"/>

+ </tasks>

+</cas:workflow>

diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/mailWorkflow.workflow.xml b/0.8.1-rc1/workflow/src/main/resources/examples/mailWorkflow.workflow.xml
new file mode 100644
index 0000000..c90b856
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/mailWorkflow.workflow.xml
@@ -0,0 +1,21 @@
+<!--

+  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.

+-->

+<cas:workflow xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" name="mailWorkflow" id="urn:oodt:mailWorkflow">

+ <tasks>

+   <task id="urn:oodt:mailTask"/>

+ </tasks>

+</cas:workflow>

diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/optional.workflow.xml b/0.8.1-rc1/workflow/src/main/resources/examples/optional.workflow.xml
new file mode 100755
index 0000000..cacf4cb
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/optional.workflow.xml
@@ -0,0 +1,21 @@
+<!--

+  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.

+-->

+<cas:workflow xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" name="Optional Workflow" id="urn:oodt:optionalWorkflow">

+ <tasks>

+   <task id="urn:oodt:OptionalTask"/>

+ </tasks>

+</cas:workflow>

diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/tasks.xml b/0.8.1-rc1/workflow/src/main/resources/examples/tasks.xml
new file mode 100644
index 0000000..8a569cc
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/tasks.xml
@@ -0,0 +1,163 @@
+<!--
+  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.
+-->
+<cas:tasks xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+	<task id="urn:oodt:HelloWorld" name="Hello World"
+		class="org.apache.oodt.cas.workflow.examples.HelloWorld">
+		<conditions>
+			<condition id="urn:oodt:TrueCondition" />
+		</conditions>
+		<configuration>
+			<property name="Person" value="Chris" />
+		</configuration>
+	</task>
+	<task id="urn:oodt:GoodbyeWorld" name="Goodbye World"
+		class="org.apache.oodt.cas.workflow.examples.GoodbyeWorld">
+		<conditions>
+			<condition id="urn:oodt:TrueCondition" />
+		</conditions>
+		<configuration>
+			<property name="Person" value="Chris" />
+		</configuration>
+	</task>
+	<task id="urn:oodt:YoureStuck" name="You're Stuck"
+		class="org.apache.oodt.cas.workflow.examples.GoodbyeWorld">
+		<conditions>
+			<condition id="urn:oodt:FalseCondition" />
+		</conditions>
+		<configuration>
+			<property name="Person" value="Chris" />
+		</configuration>
+	</task>
+	<task id="urn:oodt:IntensiveTask" name="Processor Intensive Task"
+		class="org.apache.oodt.cas.workflow.examples.LongTask">
+		<conditions />
+		<configuration />
+	</task>
+	<task id="urn:oodt:IntensiveTaskWithWait" name="Intensive Waiter"
+		class="org.apache.oodt.cas.workflow.examples.LongTask">
+		<conditions>
+			<condition id="urn:oodt:LongCondition" />
+		</conditions>
+		<configuration />
+	</task>
+	<task id="urn:oodt:PropReplaceTask" name="PRTask"
+		class="org.apache.oodt.cas.workflow.examples.LongTask">
+		<conditions />
+		<configuration>
+			<property name="PathToReplace" value="[HOME]/my/path"
+				envReplace="true" />
+			<property name="DontReplaceMe" value="[HOME]/my/path"
+				envReplace="false" />
+			<property name="DontReplaceMeNoSpec" value="[HOME]/my/path" />
+		</configuration>
+	</task>
+	<task id="urn:oodt:NumIncrementTask" name="Num Increment Task"
+		class="org.apache.oodt.cas.workflow.examples.NumIncrementTask">
+		<conditions />
+		<configuration />
+	</task>
+	<task id="urn:oodt:RandomStatusUpdateTask"
+		name="Random Status Update"
+		class="org.apache.oodt.cas.workflow.examples.RandomStatusUpdateTask">
+		<conditions />
+		<configuration />
+	</task>
+	<task id="urn:oodt:TestMultiConditionTask"
+		name="Test Multi Condition"
+		class="org.apache.oodt.cas.workflow.examples.HelloWorld">
+		<conditions>
+			<condition id="urn:oodt:TrueCondition" />
+			<condition id="urn:oodt:FalseCondition" />
+		</conditions>
+		<configuration>
+			<property name="Person" value="Chris" />
+		</configuration>
+	</task>
+	<task id="urn:oodt:TestReqMetFieldsTask" name="Test Met Fields"
+		class="org.apache.oodt.cas.workflow.examples.LongTask">
+		<conditions />
+		<configuration />
+		<requiredMetFields>
+			<metfield name="numSeconds" />
+		</requiredMetFields>
+	</task>
+		<task id="urn:oodt:ExternalScriptTask" name="External Script Task"
+		class="org.apache.oodt.cas.workflow.examples.ExternScriptTaskInstance">
+		<conditions />
+		<configuration>
+		    <property name="ShellType" value="/bin/sh"/> <!-- or /bin/tcsh if you have tcsh shell envionment; or /usr/bin/ if you have a compiled program -->
+			<property name="PathToScript" value="/usr/local/sampleScript.sh"/> <!-- This should include the file name as well-->
+		</configuration>
+	</task>
+	<task id="urn:oodt:mailTask" name="Ingest e-Mail"
+		class="org.apache.oodt.cas.workflow.examples.MailTask">
+		<conditions/>
+		<configuration>
+			<property name="user.name" value="Costin"/>
+			<property name="msg.subject" value="Ingest Notification"/>
+			<property name="mail.to" value="chris.mattmann@jpl.nasa.gov"/>
+			<property name="mail.from" value="oodt@jpl.nasa.gov"/>
+		</configuration>
+	</task>	
+	<task id="urn:oodt:TestTimeoutTask" name="Test Timeout"
+		class="org.apache.oodt.cas.workflow.examples.LongTask">
+		<conditions>
+		   <condition id="urn:oodt:TimeoutCondition"/>
+		</conditions>
+		<configuration />
+		<requiredMetFields>
+			<metfield name="numSeconds" />
+		</requiredMetFields>
+	</task>	
+	<task id="urn:oodt:OptionalTask" name="Optional Task" 
+	    class="org.apache.oodt.cas.workflow.examples.LongTask">
+	  <conditions>
+	     <condition id="urn:oodt:OptionalCondition"/>
+	  </conditions>
+	  <configuration/>
+	  <requiredMetFields>
+	     <metfield name="numSeconds"/>
+	  </requiredMetFields>
+	</task>
+	<task id="urn:oodt:TaskWithLoad" name="Task with Load"
+	   class="org.apache.oodt.cas.workflow.examples.LongTask">
+	   <conditions>
+	   </conditions> 
+	   <configuration>
+	      <!--  now settable since OODT-602
+	            controls the load value of this task when running
+	            Workflow Manager with connection to the Resource Manager.
+	       -->
+	      <property name="TaskLoad" value="2"/>
+	   </configuration>  
+	</task>
+    <task id="urn:oodt:FilterTask" name="Filter Task"
+       class="org.apache.oodt.cas.workflow.examples.FilterTask">
+       <conditions>
+       </conditions> 
+       <configuration>
+          <!--  comma separated list of keys to remove from the metadata. -->
+          <property name="Remove_Key" value="ProductionDateTime"/>
+          <!-- you can list many of these Rename_[Key] parameters, to
+               remove specific keys from the metadata. Note that renames
+               are processed *first* before removes, so you can conceivably
+               rename a field, and then *remove* it too, so be careful.
+           -->
+          <property name="Rename_Filename" value="Prior_Filename"/>
+       </configuration>  
+    </task>
+</cas:tasks>
diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/testMetError.workflow.xml b/0.8.1-rc1/workflow/src/main/resources/examples/testMetError.workflow.xml
new file mode 100644
index 0000000..5a6eb89
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/testMetError.workflow.xml
@@ -0,0 +1,23 @@
+<!--
+  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.
+-->
+<cas:workflow xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas"
+	name="testMetErrorWorkflow"
+	id="urn:oodt:testMetErrorWorkflow">
+	<tasks>
+		<task id="urn:oodt:TestReqMetFieldsTask" />
+	</tasks>
+</cas:workflow>
diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/testMetadataUpdate.workflow.xml b/0.8.1-rc1/workflow/src/main/resources/examples/testMetadataUpdate.workflow.xml
new file mode 100644
index 0000000..24893b0
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/testMetadataUpdate.workflow.xml
@@ -0,0 +1,24 @@
+<!--
+  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.
+-->
+<cas:workflow xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" name="testMetadataUpdateWorkflow" id="urn:oodt:testMetadataUpdateWorkflow">
+ <tasks>
+   <task id="urn:oodt:NumIncrementTask"/>
+   <task id="urn:oodt:NumIncrementTask"/>
+   <task id="urn:oodt:NumIncrementTask"/>
+   <task id="urn:oodt:NumIncrementTask"/>
+ </tasks>
+</cas:workflow>
diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/testStatusUpdate.workflow.xml b/0.8.1-rc1/workflow/src/main/resources/examples/testStatusUpdate.workflow.xml
new file mode 100644
index 0000000..06e94a7
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/testStatusUpdate.workflow.xml
@@ -0,0 +1,22 @@
+<!--
+  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.
+-->
+<cas:workflow xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" name="testStatusUpdateWorkflow" id="urn:oodt:testStatusUpdateWorkflow">
+ <tasks>
+   <task id="urn:oodt:RandomStatusUpdateTask"/>
+   <task id="urn:oodt:RandomStatusUpdateTask"/>
+ </tasks>
+</cas:workflow>
diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/testWorkflow.workflow.xml b/0.8.1-rc1/workflow/src/main/resources/examples/testWorkflow.workflow.xml
new file mode 100644
index 0000000..2a87a04
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/testWorkflow.workflow.xml
@@ -0,0 +1,22 @@
+<!--

+  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.

+-->

+<cas:workflow xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" name="testWorkflow" id="urn:oodt:testWorkflow">

+ <tasks>

+   <task id="urn:oodt:HelloWorld"/>

+   <task id="urn:oodt:GoodbyeWorld"/>

+ </tasks>

+</cas:workflow>

diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/timeout.workflow.xml b/0.8.1-rc1/workflow/src/main/resources/examples/timeout.workflow.xml
new file mode 100755
index 0000000..2eb8cb4
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/timeout.workflow.xml
@@ -0,0 +1,21 @@
+<!--

+  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.

+-->

+<cas:workflow xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas" name="Timeout Workflow" id="urn:oodt:timeoutWorkflow">

+ <tasks>

+   <task id="urn:oodt:TestTimeoutTask"/>

+ </tasks>

+</cas:workflow>

diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/wengine/GranuleMaps.xml b/0.8.1-rc1/workflow/src/main/resources/examples/wengine/GranuleMaps.xml
new file mode 100644
index 0000000..dd5c7be
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/wengine/GranuleMaps.xml
@@ -0,0 +1,263 @@
+<?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.
+-->
+<cas:workflows 
+	xmlns="http://oodt.jpl.nasa.gov/2.0/cas"
+	xmlns:cas="http://oodt.jpl.nasa.gov/2.0/cas"
+	xmlns:p="http://oodt.jpl.nasa.gov/2.0/cas/property">
+	
+	<sequential id="urn:npp:GranuleMaps">
+		<configuration>
+			
+			<!-- PCS properties -->
+			<property name="PGETask/Query/FileManagerUrl" value="[FILEMGR_URL]" envReplace="true"/>
+			<property name="PGETask/Ingest/FileManagerUrl" value="[FILEMGR_URL]" envReplace="true"/>
+			<property name="PGETask/Ingest/ClientTransferServiceFactory" value="org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory"/>
+			<property name="PGETask/Ingest/MetFileExtension" value="cas"/>
+			<property name="PGETask/Ingest/CrawlerCrawlForDirs" value="false"/>
+			<property name="PGETask/Ingest/CrawlerRecur" value="false"/>
+			<property name="PGETask/Ingest/ActionsIds" value="RmDataFile"/>
+			<property name="PGETask/Ingest/ActionRepoFile" value="file:[PCS_HOME]/core/pge/policy/action-beans.xml" envReplace="true"/>
+			
+			<!-- Timeout properties -->
+			<property name="PGETask/Condition/Timeout" value="30000"/>
+			
+			<!-- metadata element names -->
+			<property name="PGETask/Condition/FilenameKey" value="Filename"/>
+			<property name="PGETask/Condition/StartDateTimeKey" value="StartDateTime"/>
+			<property name="PGETask/Condition/EndDateTimeKey" value="EndDateTime"/>
+			<property name="PGETask/Condition/SortByKey" value="StartDateTime"/>
+			<property name="PGETask/Condition/VersioningKey" value="ProductionDateTime"/>
+			
+			<!-- query properties -->
+			<property name="PGETask/Condition/FilterAlgorClass" value="org.apache.oodt.cas.filemgr.structs.query.filter.WeightedHashFilterAlgor"/>
+			<property name="PGETask/Condition/MinNumOfFiles" value="1"/>
+			<property name="PGETask/Condition/MaxGapSize" value="-1"/>
+			<property name="PGETask/Condition/EpsilonInMillis" value="0"/>			
+			
+			<!-- formatting properties for queries -->
+			<property name="PGETask/Condition/ResultFormat" value="$FileLocation/$Filename"/>
+			
+			<!-- Wait time between block and unblock in minutes -->
+			<property name="BlockTimeElapse" value="1"/>
+
+		</configuration>
+
+		<conditions execution="parallel" type="pre">
+			<condition id-ref="urn:npp:MOA_IASI_L1C_Daily"/>			
+			<condition id-ref="urn:npp:MOA_MHS_L1B_Daily"/>			
+			<condition id-ref="urn:npp:MOA_AMSUA_L1B_Daily"/>			
+		</conditions>
+		
+		<parallel>
+			<task id-ref="urn:npp:Orbits"/>
+			<task id-ref="urn:npp:MoaIasiGPolygon"/>
+			<task id-ref="urn:npp:MoaMhsGPolygon"/>
+			<task id-ref="urn:npp:MoaAmsuaGPolygon"/>			
+		</parallel>
+		
+		<parallel>		
+			<conditions execution="sequential" type="pre">
+				<condition id-ref="urn:npp:MOA_ORBITS_FileBased"/>
+			</conditions>
+			
+			<task id-ref="urn:npp:MoaIasiMap"/>
+			<task id-ref="urn:npp:MoaMhsMap"/>
+			<task id-ref="urn:npp:MoaAmsuaMap"/>
+			
+			<!--conditions execution="sequential" type="post">  
+				<condition id-ref="urn:npp:VerifyMapsExist" name="VerifyMapsExist"/>				
+			</conditions-->
+
+		</parallel>
+		
+	</sequential>
+
+
+	<!-- CONDITIONS -->
+	<condition id="urn:npp:MOA_IASI_L1C_Daily" name="MOA_IASI_L1C_Daily" class="org.apache.oodt.cas.pge.condition.PGETaskWorkflowCondition" timeout="30">
+		<configuration>
+			<!-- query properties -->
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_IASI_L1C"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="480"/>
+			<property name="PGETask/Condition/EpsilonInMillis" value="30000"/>
+			<!-- formatting properties for queries -->
+			<property name="PGETask/Condition/FormattedSqlQueryKey" value="Runtime/Condition/IASI_L1FormattedQuery"/> 
+			<property name="PGETask/Condition/FilenamesSqlQueryKey" value="Runtime/Condition/IASI_L1FilenamesQuery"/> 
+			<property name="QueueName" value="java"/>
+		</configuration>
+	</condition>			
+	<condition id="urn:npp:MOA_MHS_L1B_Daily" name="MOA_MHS_L1B_Daily" class="org.apache.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+		<configuration>
+			<!-- query properties -->
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_MHS_L1B"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="15"/>
+			<property name="PGETask/Condition/EpsilonInMillis" value="60000"/> <!--2mins-->
+			<!-- formatting properties for queries -->
+			<property name="PGETask/Condition/FormattedSqlQueryKey" value="Runtime/Condition/MHS_L1FormattedQuery"/> 
+			<property name="PGETask/Condition/FilenamesSqlQueryKey" value="Runtime/Condition/MHS_L1FilenamesQuery"/> 
+			<property name="QueueName" value="java"/>
+		</configuration>
+	</condition>		
+	<condition id="urn:npp:MOA_AMSUA_L1B_Daily" name="MOA_MHS_L1B_Daily" class="org.apache.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+		<configuration>
+			<!-- query properties -->
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_AMSUA_L1B"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="15"/>
+			<property name="PGETask/Condition/EpsilonInMillis" value="60000"/> <!--2mins-->
+			<!-- formatting properties for queries -->
+			<property name="PGETask/Condition/FormattedSqlQueryKey" value="Runtime/Condition/AMSUA_L1FormattedQuery"/> 
+			<property name="PGETask/Condition/FilenamesSqlQueryKey" value="Runtime/Condition/AMSUA_L1FilenamesQuery"/> 
+			<property name="QueueName" value="java"/>
+		</configuration>
+	</condition>	
+	<condition id="urn:npp:MOA_ORBITS_FileBased" name="MOA_ORBITS_FileBased" class="org.apache.oodt.cas.pge.condition.PGETaskWorkflowCondition" optional="true">
+		<configuration>
+			<!-- query properties -->
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_ORBITS"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="1"/>
+			<!-- formatting properties for queries -->
+			<property name="PGETask/Condition/FormattedSqlQueryKey" value="Runtime/Condition/OrbitsFormattedQuery"/> 
+			<property name="PGETask/Condition/FilenamesSqlQueryKey" value="Runtime/Condition/OrbitsFilenamesQuery"/>
+			<property name="QueueName" value="java"/>		
+		</configuration>	
+	</condition>	
+	<condition id="urn:npp:MOA_IASI_POLY_FileBased" name="MOA_IASI_POLY_FileBased" class="org.apache.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+		<configuration>
+			<!-- query properties -->
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_IASI_POLY"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="1"/>
+			<!-- formatting properties for queries -->
+			<property name="PGETask/Condition/FormattedSqlQueryKey" value="Runtime/Condition/IASI_GPolyFormattedQuery"/> 
+			<property name="PGETask/Condition/FilenamesSqlQueryKey" value="Runtime/Condition/IASI_GPolyFilenamesQuery"/>
+			<property name="QueueName" value="java"/>	
+		</configuration>	
+	</condition>			
+	<condition id="urn:npp:MOA_MHS_POLY_FileBased" name="MOA_MHS_POLY_FileBased" class="org.apache.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+		<configuration>
+			<!-- query properties -->
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_MHS_POLY"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="1"/>
+			<!-- formatting properties for queries -->
+			<property name="PGETask/Condition/FormattedSqlQueryKey" value="Runtime/Condition/MHS_GPolyFormattedQuery"/> 
+			<property name="PGETask/Condition/FilenamesSqlQueryKey" value="Runtime/Condition/MHS_GPolyFilenamesQuery"/>
+			<property name="QueueName" value="java"/>	
+		</configuration>	
+	</condition>			
+	<condition id="urn:npp:MOA_AMSUA_POLY_FileBased" name="MOA_AMSUA_POLY_FileBased" class="org.apache.oodt.cas.pge.condition.PGETaskWorkflowCondition">
+		<configuration>
+			<!-- query properties -->
+			<property name="PGETask/Condition/ProductTypeNames" value="MOA_AMSUA_POLY"/>
+			<property name="PGETask/Condition/ExpectedNumOfFiles" value="1"/>
+			<!-- formatting properties for queries -->
+			<property name="PGETask/Condition/FormattedSqlQueryKey" value="Runtime/Condition/AMSUA_GPolyFormattedQuery"/> 
+			<property name="PGETask/Condition/FilenamesSqlQueryKey" value="Runtime/Condition/AMSUA_GPolyFilenamesQuery"/>
+			<property name="QueueName" value="java"/>
+		</configuration>	
+	</condition>	
+	<!--condition id="urn:npp:VerifyMapsExist" name="VerifyMapsExist" class="org.apache.oodt.cas.pge.condition.PGETaskWorkflowCondition"/-->				
+	
+	
+	<!-- TASKS -->
+	<task id="urn:npp:Orbits" name="MoaOrbits" class="org.apache.oodt.cas.pge.StdPGETaskInstance">
+		<configuration>
+			<property name="PGETask/Name" value="MoaOrbits" />
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaOrbits/SPSS_Version]/config/PgeConfig_MoaOrbits.xml"/>
+			<property name="Runtime/Condition/L1FormattedQuery" value="[Runtime/Condition/IASI_L1FormattedQuery]"/>
+			<property name="Runtime/Condition/L1FilenamesQuery" value="[Runtime/Condition/IASI_L1FilenamesQuery]"/>
+			<property name="Runtime/Condition/SharedMetout" value="[SPSS_CONFIG_HOME]/[MoaOrbits/SPSS_Version]/metout/AllProducts_metadata.xml,[SPSS_CONFIG_HOME]/[MoaOrbits/SPSS_Version]/metout/DailyProduct_metadata.xml"/> 
+			<property name="Instrument" value="MetOpS"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	<task id="urn:npp:MoaIasiGPolygon" name="MoaIasiGPolygon" class="org.apache.oodt.cas.pge.StdPGETaskInstance">
+		<configuration>
+			<property name="PGETask/Name" value="MoaIasiGPolygon"/>
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaIasiGPolygon/SPSS_Version]/config/PgeConfig_MoaGPolygon.xml"/>
+			<property name="Runtime/Condition/L1FormattedQuery" value="[Runtime/Condition/IASI_L1FormattedQuery]"/>			
+			<property name="Runtime/Condition/L1FilenamesQuery" value="[Runtime/Condition/IASI_L1FilenamesQuery]"/>			
+			<property name="Runtime/Condition/SharedMetout" value="[SPSS_CONFIG_HOME]/[MoaIasiGPolygon/SPSS_Version]/metout/AllProducts_metadata.xml,[SPSS_CONFIG_HOME]/[MoaIasiGPolygon/SPSS_Version]/metout/DailyProduct_metadata.xml"/> 
+			<property name="Instrument" value="IASI"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	<task id="urn:npp:MoaMhsGPolygon" name="MoaMhsGPolygon" class="org.apache.oodt.cas.pge.StdPGETaskInstance">
+		<configuration>
+			<property name="PGETask/Name" value="MoaAmsuaGPolygon"/>
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaAmsuaGPolygon/SPSS_Version]/config/PgeConfig_MoaGPolygon.xml"/>
+			<property name="Runtime/Condition/L1FormattedQuery" value="[Runtime/Condition/AMSUA_L1FormattedQuery]"/>						
+			<property name="Runtime/Condition/L1FilenamesQuery" value="[Runtime/Condition/AMSUA_L1FilenamesQuery]"/>						
+			<property name="Runtime/Condition/SharedMetout" value="[SPSS_CONFIG_HOME]/[MoaAmsuaGPolygon/SPSS_Version]/metout/AllProducts_metadata.xml,[SPSS_CONFIG_HOME]/[MoaAmsuaGPolygon/SPSS_Version]/metout/DailyProduct_metadata.xml"/> 
+			<property name="Instrument" value="AMSUA"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	<task id="urn:npp:MoaAmsuaGPolygon" name="MoaAmsuaGPolygon" class="org.apache.oodt.cas.pge.StdPGETaskInstance">
+		<configuration>
+			<property name="PGETask/Name" value="MoaMhsGPolygon"/>
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaMhsGPolygon/SPSS_Version]/config/PgeConfig_MoaGPolygon.xml"/>
+			<property name="Runtime/Condition/L1FormattedQuery" value="[Runtime/Condition/MHS_L1FormattedQuery]"/>									
+			<property name="Runtime/Condition/L1FilenamesQuery" value="[Runtime/Condition/MHS_L1FilenamesQuery]"/>									
+			<property name="Runtime/Condition/SharedMetout" value="[SPSS_CONFIG_HOME]/[MoaMhsGPolygon/SPSS_Version]/metout/AllProducts_metadata.xml,[SPSS_CONFIG_HOME]/[MoaMhsGPolygon/SPSS_Version]/metout/DailyProduct_metadata.xml"/> 
+			<property name="Instrument" value="MHS"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	<task id="urn:npp:MoaIasiMap" name="MoaIasiMap" class="org.apache.oodt.cas.pge.StdPGETaskInstance">
+		<conditions execution="sequential" type="pre">
+			<condition id-ref="urn:npp:MOA_IASI_POLY_FileBased"/>			
+		</conditions>
+		<configuration>
+			<property name="PGETask/Name" value="MoaIasiMap"/>
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaIasiMap/SPSS_Version]/config/PgeConfig_MoaMap.xml"/>
+			<property name="Runtime/Condition/GPolyFormattedQuery" value="[Runtime/Condition/IASI_GPolyFormattedQuery]"/>									
+			<property name="Runtime/Condition/GPolyFilenamesQuery" value="[Runtime/Condition/IASI_GPolyFilenamesQuery]"/>
+			<property name="Runtime/Condition/SharedMetout" value="[SPSS_CONFIG_HOME]/[MoaIasiMap/SPSS_Version]/metout/AllProducts_metadata.xml,[SPSS_CONFIG_HOME]/[MoaIasiMap/SPSS_Version]/metout/DailyProduct_metadata.xml"/> 
+			<property name="Instrument" value="IASI"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	<task id="urn:npp:MoaMhsMap" name="MoaMhsMap" class="org.apache.oodt.cas.pge.StdPGETaskInstance">
+		<conditions execution="sequential" type="pre">
+			<condition id-ref="urn:npp:MOA_MHS_POLY_FileBased"/>			
+		</conditions>
+		<configuration>
+			<property name="PGETask/Name" value="MoaMhsMap"/>
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaMhsMap/SPSS_Version]/config/PgeConfig_MoaMap.xml"/>
+			<property name="Runtime/Condition/GPolyFormattedQuery" value="[Runtime/Condition/MHS_GPolyFormattedQuery]"/>									
+			<property name="Runtime/Condition/GPolyFilenamesQuery" value="[Runtime/Condition/MHS_GPolyFilenamesQuery]"/>
+			<property name="Runtime/Condition/SharedMetout" value="[SPSS_CONFIG_HOME]/[MoaMhsMap/SPSS_Version]/metout/AllProducts_metadata.xml,[SPSS_CONFIG_HOME]/[MoaMhsMap/SPSS_Version]/metout/DailyProduct_metadata.xml"/> 
+			<property name="Instrument" value="MHS"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	<task id="urn:npp:MoaAmsuaMap" name="MoaAmsuaMap" class="org.apache.oodt.cas.pge.StdPGETaskInstance">
+		<conditions execution="sequential" type="pre">
+			<condition id-ref="urn:npp:MOA_AMSUA_POLY_FileBased"/>			
+		</conditions>
+		<configuration>
+			<property name="PGETask/Name" value="MoaAmsuaMap"/>
+			<property name="PGETask/ConfigFilePath" value="[SPSS_CONFIG_HOME]/[MoaAmsuaMap/SPSS_Version]/config/PgeConfig_MoaMap.xml"/>
+			<property name="Runtime/Condition/GPolyFormattedQuery" value="[Runtime/Condition/AMSUA_GPolyFormattedQuery]"/>									
+			<property name="Runtime/Condition/GPolyFilenamesQuery" value="[Runtime/Condition/AMSUA_GPolyFilenamesQuery]"/>
+			<property name="Runtime/Condition/SharedMetout" value="[SPSS_CONFIG_HOME]/[MoaAmsuaMap/SPSS_Version]/metout/AllProducts_metadata.xml,[SPSS_CONFIG_HOME]/[MoaAmsuaMap/SPSS_Version]/metout/DailyProduct_metadata.xml"/> 
+			<property name="Instrument" value="AMSUA"/>
+			<property name="QueueName" value="idl"/>
+		</configuration>
+	</task>
+	
+</cas:workflows>
diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/wengine/hello-goodbye.xml b/0.8.1-rc1/workflow/src/main/resources/examples/wengine/hello-goodbye.xml
new file mode 100644
index 0000000..9e5949b
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/wengine/hello-goodbye.xml
@@ -0,0 +1,153 @@
+<!--
+  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.
+-->
+<cas:workflows xmlns="http://oodt.jpl.nasa.gov/2.0/cas"
+	xmlns:cas="http://oodt.jpl.nasa.gov/2.0/cas" 
+	xmlns:p="http://oodt.jpl.nasa.gov/2.0/cas/property">
+
+	<parallel id="urn:oodt:TestParallel" name="TestParallel">
+		<sequential id="urn:oodt:SayHelloAndGoodBye" name="HelloGoodbye">
+			<task id-ref="urn:oodt:HelloWorld" />
+			<task id-ref="urn:oodt:GoodbyeWorld" />
+		</sequential>
+		
+		<conditions>
+		  <condition id-ref="urn:oodt:TimeoutCondition"/>
+		</conditions>
+
+		<task id-ref="urn:oodt:IntensiveTask" />
+	</parallel>
+
+	<task id="urn:oodt:HelloWorld" name="Hello World"
+		class="org.apache.oodt.cas.workflow.examples.HelloWorld">
+		<conditions execution="sequential">
+			<condition id-ref="urn:oodt:TrueCondition" />
+		</conditions>
+		<configuration>
+			<property name="Person" value="Chris" />
+		</configuration>
+	</task>
+	<task id="urn:oodt:GoodbyeWorld" name="Goodbye World"
+		class="org.apache.oodt.cas.workflow.examples.GoodbyeWorld">
+		<conditions execution="sequential">
+			<condition id-ref="urn:oodt:TrueCondition" />
+		</conditions>
+		<configuration>
+			<property name="Person" value="Chris" />
+		</configuration>
+	</task>
+	<task id="urn:oodt:YoureStuck" name="You're Stuck"
+		class="org.apache.oodt.cas.workflow.examples.GoodbyeWorld">
+		<conditions execution="sequential">
+			<condition id-ref="urn:oodt:FalseCondition" />
+		</conditions>
+		<configuration>
+			<property name="Person" value="Chris" />
+		</configuration>
+	</task>
+	<task id="urn:oodt:IntensiveTask" name="Processor Intensive Task"
+		class="org.apache.oodt.cas.workflow.examples.LongTask">
+		<conditions execution="sequential" />
+		<configuration />
+	</task>
+	<task id="urn:oodt:IntensiveTaskWithWait" name="Intensive Waiter"
+		class="org.apache.oodt.cas.workflow.examples.LongTask">
+		<conditions execution="sequential">
+			<condition id-ref="urn:oodt:LongCondition" />
+		</conditions>
+		<configuration />
+	</task>
+	<task id="urn:oodt:PropReplaceTask" name="PRTask"
+		class="org.apache.oodt.cas.workflow.examples.LongTask">
+		<conditions execution="sequential" />
+		<configuration>
+			<property name="PathToReplace" value="[HOME]/my/path"
+				envReplace="true" />
+			<property name="DontReplaceMe" value="[HOME]/my/path"
+				envReplace="false" />
+			<property name="DontReplaceMeNoSpec" value="[HOME]/my/path" />
+		</configuration>
+	</task>
+	<task id="urn:oodt:NumIncrementTask" name="Num Increment Task"
+		class="org.apache.oodt.cas.workflow.examples.NumIncrementTask">
+		<conditions execution="sequential" />
+		<configuration />
+	</task>
+	<task id="urn:oodt:RandomStatusUpdateTask" name="Random Status Update"
+		class="org.apache.oodt.cas.workflow.examples.RandomStatusUpdateTask">
+		<conditions execution="sequential" />
+		<configuration />
+	</task>
+	<task id="urn:oodt:TestMultiConditionTask" name="Test Multi Condition"
+		class="org.apache.oodt.cas.workflow.examples.HelloWorld">
+		<conditions execution="sequential">
+			<condition id-ref="urn:oodt:TrueCondition" />
+			<condition id-ref="urn:oodt:FalseCondition" />
+		</conditions>
+		<configuration>
+			<property name="Person" value="Chris" />
+		</configuration>
+	</task>
+	<task id="urn:oodt:TestReqMetFieldsTask" name="Test Met Fields"
+		class="org.apache.oodt.cas.workflow.examples.LongTask">
+		<conditions execution="sequential" />
+		<configuration />
+		<requiredMetFields>
+			<metfield name="numSeconds" />
+		</requiredMetFields>
+	</task>
+	<task id="urn:oodt:ExternalScriptTask" name="External Script Task"
+		class="org.apache.oodt.cas.workflow.examples.ExternScriptTaskInstance">
+		<conditions execution="sequential" />
+		<configuration>
+			<property name="ShellType" value="/bin/sh" /> <!-- or /bin/tcsh if you have tcsh shell envionment; or /usr/bin/ if you 
+				have a compiled program -->
+			<property name="PathToScript" value="/usr/local/sampleScript.sh" /> <!-- This should include the file name as well -->
+		</configuration>
+	</task>
+	<task id="urn:oodt:mailTask" name="Ingest e-Mail"
+		class="org.apache.oodt.cas.workflow.examples.MailTask">
+		<conditions execution="sequential" />
+		<configuration>
+			<property name="user.name" value="Costin" />
+			<property name="msg.subject" value="Ingest Notification" />
+			<property name="mail.to" value="chris.mattmann@jpl.nasa.gov" />
+			<property name="mail.from" value="oodt@jpl.nasa.gov" />
+		</configuration>
+	</task>
+
+	<condition id="urn:oodt:TrueCondition" name="True Condition"
+		class="org.apache.oodt.cas.workflow.examples.TrueCondition" />
+	<condition id="urn:oodt:FalseCondition" name="False Condition"
+		class="org.apache.oodt.cas.workflow.examples.FalseCondition" />
+	<condition id="urn:oodt:LongCondition" name="Long Condition"
+		class="org.apache.oodt.cas.workflow.examples.LongCondition" />
+	<condition id="urn:oodt:CheckForMetadataKeys" name="Metadata Key Check"
+		class="org.apache.oodt.cas.workflow.examples.CheckForMetadataKeys">
+		<configuration>
+			<property name="reqMetKeys" value="Met1,Met2,Met3" />
+		</configuration>
+	</condition>
+	<condition id="urn:oodt:TimeoutCondition" name="Timeout Condition" 
+	    class="org.apache.oodt.cas.workflow.examples.FalseCondition" timeout="30"/>
+	
+	<condition id="urn:oodt:OptionalCondition" name="Optional Condition" 
+	class="org.apache.oodt.cas.workflow.examples.FalseCondition" optional="true"/>
+	
+
+
+
+</cas:workflows>
diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/wengine/wengine-lifecycle.xml b/0.8.1-rc1/workflow/src/main/resources/examples/wengine/wengine-lifecycle.xml
new file mode 100755
index 0000000..650215c
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/wengine/wengine-lifecycle.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<!-- FIXME: Change namespace URI? -->
+<cas:workflowlifecycles xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<default>
+ <!-- stages in this sense map to bfoster's original "Category" classification
+      that is mentioned in the Workflow2 User's Guide
+      
+  -->
+  <stage name="initial">
+   <!-- 
+     Statuses can optionally be specified
+     in the form:
+       &lt;status&gt;Name&lt;/status&gt;
+       
+       To preserve backwards compatibility. In this
+       case, the given description will simply be the 
+       provided status name.
+       
+     As of Apache OODT 0.4, statuses in this file can 
+     also take the form:
+     
+       &lt;status name=&quot;Name&quot;&gt;
+        &lt;description&gt;Description&lt;/description&gt;   
+       &lt;/status&gt;      
+    -->
+   <status name="Null">
+     <description>Uninitialized State</description>
+   </status>
+   <status name="Loaded">
+     <description>Loading Complete</description>
+   </status>
+  </stage>
+  <stage name="waiting">
+   <status name="Queued">
+      <description>Queued in WorkflowEngine</description>
+   </status>
+   <status name="Blocked">
+      <description>Task Bailed</description>
+   </status>
+   <status name="WaitingOnResources">
+      <description>Waiting for resource to execute</description>   
+   </status>
+  </stage>
+  <stage name="transition">
+   <status name="PreConditionSuccess">  
+      <description>All PreCondition Finished Successfully</description>
+   </status>
+   <status name="ExecutionComplete">
+      <description>Execution Completed Successfully</description>
+   </status>
+  </stage>
+  <stage name="holding">
+   <status name="Unknown">
+      <description>State is Unknown</description>
+   </status>
+   <status name="Paused">
+      <description>Has been manually paused</description>
+   </status>
+  </stage>  
+  <stage name="running">
+   <status name="PreConditionEval">
+      <description>Executing PreConditions</description>
+   </status>
+   <status name="Executing">
+      <description>Current being executed</description>
+   </status>
+   <status name="PostConditionEval"> 
+      <description>Executing PostConditions</description>
+   </status>
+  </stage>
+  <stage name="results">
+    <status name="ResultsSuccess">
+      <description>Notification of success</description>
+    </status>
+    <status name="ResultsFailure">
+      <description>Notification of failure</description>
+    </status>
+    <status name="ResultsBail">
+      <description>Notification to bail workflow</description>
+    </status>
+  </stage>  
+  <stage name="done">
+    <status name="Stopped">
+      <description>Force Killed</description>
+    </status>
+    <status name="Off">
+      <description>Turned OFF</description>
+    </status>
+    <status name="Failure">
+      <description>Execution Failed</description>
+    </status>
+    <status name="Success">
+      <description>Successfully Completed</description>
+    </status>
+  </stage> 
+ </default>
+<!-- 
+  Lifecycles can also be specified at the 
+  Workflow Id level, by starting with a 
+  <lifecycle name="" workflowId="some_id">
+    
+    declaration, and then using the stage
+    and status tags appropriately as shown
+    above
+    
+  </lifecycle>
+ -->
+</cas:workflowlifecycles>
diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/workflow-instance-met.xml b/0.8.1-rc1/workflow/src/main/resources/examples/workflow-instance-met.xml
new file mode 100644
index 0000000..c40ff74
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/workflow-instance-met.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<!-- FIXME: Change namespace URI? -->
+<cas:winstfields xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<default>
+  <field name="WorkflowInstId"/>
+  <field name="TaskId"/>
+  <field name="ProcessingNode"/>
+</default>
+<workflow id="urn:oodt:testWorkflow">
+  <field name="WorkflowInstId"/>
+</workflow>
+<workflow id="urn:oodt:testMetErrorWorkflow">
+  <field name="numSeconds"/>
+  <field name="WorkflowInstId"/>
+  <field name="ProcessingNode"/>
+</workflow>
+</cas:winstfields>
diff --git a/0.8.1-rc1/workflow/src/main/resources/examples/workflow-lifecycle.xml b/0.8.1-rc1/workflow/src/main/resources/examples/workflow-lifecycle.xml
new file mode 100644
index 0000000..30c731b
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/examples/workflow-lifecycle.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<!-- FIXME: Change namespace URI? -->
+<cas:workflowlifecycles xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas">
+<!-- 
+  To preserve backwards compatibility. In this
+       case, the given description will simply be the 
+       provided status name.
+       
+     As of Apache OODT 0.4, statuses in this file can 
+     also take the form:
+     
+       &lt;status name=&quot;Name&quot;&gt;
+        &lt;description&gt;Description&lt;/description&gt;   
+       &lt;/status&gt;
+       
+ -->
+<default>
+  <stage name="setup">
+    <status>QUEUED</status>
+    <status>CREATED</status>
+  </stage>
+  <stage name="met_check">
+    <status>METMISS</status>
+  </stage>
+  <stage name="precond_check">
+    <status>PAUSED</status>  
+  </stage>
+  <stage name="workflow_start">
+    <status>RSUBMIT</status>
+    <status>STARTED</status>
+  </stage>
+  <stage name="completion">
+    <status>FINISHED</status>
+  </stage>
+</default>
+
+<!-- 
+  Lifecycles can also be specified at the 
+  Workflow Id level, by starting with a 
+  <lifecycle name="" workflowId="some_id">
+    
+    declaration, and then using the stage
+    and status tags appropriately as shown
+    above
+    
+  </lifecycle>
+ -->
+</cas:workflowlifecycles>
diff --git a/0.8.1-rc1/workflow/src/main/resources/logging.properties b/0.8.1-rc1/workflow/src/main/resources/logging.properties
new file mode 100644
index 0000000..7c350e1
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/logging.properties
@@ -0,0 +1,70 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.FileHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = ../logs/cas_workflow%g.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 5
+java.util.logging.FileHandler.append = true
+java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging level for the subsystems
+
+# data structures subsystem
+org.apache.oodt.cas.workflow.structs.level = INFO
+
+# engine subsystem
+org.apache.oodt.cas.workflow.engine.level = INFO
+
+# instance repository subsystem
+org.apache.oodt.cas.workflow.instrepo.level = INFO
+
+# repository subsystem
+org.apache.oodt.cas.workflow.repository.level = INFO
+
+# system subsystem
+org.apache.oodt.cas.workflow.system.level = FINE
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = INFO
+httpclient.wire.header.level = INFO
+httpclient.wire.level = INFO
+sun.net.level = OFF
+sun.net.www.level = OFF
+
+# spring framework logging
+org.springframework.beans.level = SEVERE
+org.springframework.core.level = SEVERE
+org.springframework.level = SEVERE
+org.springframework.beans.factory.level = SEVERE
+org.springframework.beans.factory.config.level = SEVERE
+org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.level = SEVERE
+org.apache.oodt.cas.crawl.util.CasPropertyPlaceholderConfigurer.level = SEVERE
+sun.net.level = SEVERE
diff --git a/0.8.1-rc1/workflow/src/main/resources/workflow.properties b/0.8.1-rc1/workflow/src/main/resources/workflow.properties
new file mode 100644
index 0000000..a4c1632
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/workflow.properties
@@ -0,0 +1,85 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+#
+# Properties required to configure the Workflow Manager
+
+# workflow repository factory
+workflow.repo.factory = org.apache.oodt.cas.workflow.repository.XMLWorkflowRepositoryFactory
+
+# workflow engine factory
+workflow.engine.factory = org.apache.oodt.cas.workflow.engine.ThreadPoolWorkflowEngineFactory
+
+# workflow instance repository factory
+workflow.engine.instanceRep.factory = org.apache.oodt.cas.workflow.instrepo.LuceneWorkflowInstanceRepositoryFactory
+
+# engine runner factory
+workflow.wengine.runner.factory=org.apache.oodt.cas.workflow.engine.runner.AsynchronousLocalEngineRunnerFactory
+
+# thread pool workflow engine properties
+org.apache.oodt.cas.workflow.engine.queueSize=
+org.apache.oodt.cas.workflow.engine.maxPoolSize=
+org.apache.oodt.cas.workflow.engine.minPoolSize=6
+org.apache.oodt.cas.workflow.engine.threadKeepAlive.minutes=5
+org.apache.oodt.cas.workflow.engine.unlimitedQueue=true
+org.apache.oodt.cas.workflow.engine.preConditionWaitTime=10
+
+# set this if you want the workflow manager to submit jobs through the resource mgr
+org.apache.oodt.cas.workflow.engine.resourcemgr.url=
+
+# if you use the resource mgr submission, you can specify how many seconds the 
+# workflow manager should wait inbetween checking to see if a job is complete
+org.apache.oodt.cas.workflow.engine.resourcemgr.pollingWaitTime=10
+
+# wengine properties
+# define workflow prioritizer class to use for sorting workflow tasks
+org.apache.oodt.cas.workflow.wengine.prioritizer=org.apache.oodt.cas.workflow.structs.FILOPrioritySorter
+# the default amount of time (in seconds) that the task querier waits before dispositioning processors
+org.apache.oodt.cas.workflow.wengine.taskquerier.waitSeconds=2
+
+# the maximum number of threads to be used by the asynchronous engine runner
+org.apache.oodt.cas.workflow.wengine.asynchronous.runner.num.threads=25
+
+# workflow instance repository general properties
+# default page size to page through WorkflowInstances with
+org.apache.oodt.cas.workflow.instanceRep.pageSize=20
+
+# lucene workflow instance repository properties
+org.apache.oodt.cas.workflow.instanceRep.lucene.idxPath=/path/to/index
+
+# data source workflow instance repository properties
+org.apache.oodt.cas.workflow.instanceRep.datasource.jdbc.url=jdbc:url
+org.apache.oodt.cas.workflow.instanceRep.datasource.jdbc.user=user
+org.apache.oodt.cas.workflow.instanceRep.datasource.jdbc.pass=pass
+org.apache.oodt.cas.workflow.instanceRep.datasource.jdbc.driver=your.jdbc.Driver
+org.apache.oodt.cas.workflow.instanceRep.datasource.quoteFields=false
+
+# XML workflow repository properties
+org.apache.oodt.cas.workflow.repo.dirs=file:///path/to/your/repo1, file:///path/to/your/repo2
+
+# wengine-style packaged workflow repo properties
+org.apache.oodt.cas.workflow.wengine.packagedRepo.dir.path = /path/to/wengine/workflow/files
+
+# data source workflow repository properties
+org.apache.oodt.cas.workflow.repo.datasource.jdbc.url=jdbc:url
+org.apache.oodt.cas.workflow.repo.datasource.jdbc.user=user
+org.apache.oodt.cas.workflow.repo.datasource.jdbc.pass=pass
+org.apache.oodt.cas.workflow.repo.datasource.jdbc.driver=your.jdbc.Driver
+
+# Spring command line option and action store properties
+org.apache.oodt.cas.cli.action.spring.config=src/main/resources/cmd-line-actions.xml
+org.apache.oodt.cas.cli.option.spring.config=src/main/resources/cmd-line-options.xml
+
+# workflow lifecycle Manager
+org.apache.oodt.cas.workflow.lifecycle.filePath=/path/to/workflow-lifecycle.xml
diff --git a/0.8.1-rc1/workflow/src/main/resources/workflow.sql b/0.8.1-rc1/workflow/src/main/resources/workflow.sql
new file mode 100644
index 0000000..ec77cc7
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/workflow.sql
@@ -0,0 +1,89 @@
+--  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.
+
+CREATE TABLE workflows
+(workflow_id int PRIMARY KEY NOT NULL,
+workflow_name varchar(255));
+
+CREATE TABLE workflow_condition_map
+(workflow_id int NOT NULL,
+workflow_condition_id int NOT NULL);
+
+CREATE TABLE event_workflow_map
+(workflow_id int NOT NULL,
+event_name varchar(255) NOT NULL);
+
+CREATE TABLE workflow_tasks
+(workflow_task_id int NOT NULL PRIMARY KEY,
+workflow_task_name varchar(255),
+workflow_task_class varchar(255));
+
+CREATE TABLE workflow_task_map
+(workflow_id int NOT NULL,
+workflow_task_id int NOT NULL,
+task_order int NOT NULL);
+
+CREATE TABLE workflow_instances
+(workflow_instance_id int PRIMARY KEY NOT NULL,
+workflow_instance_status varchar(255),
+workflow_id int NOT NULL,
+current_task_id int NOT NULL,
+start_date_time varchar(255),
+end_date_time varchar(255),
+current_task_start_date_time varchar(255),
+current_task_end_date_time varchar(255),
+priority float,
+times_blocked int DEFAULT 0);
+
+-- use this definition if you would like
+-- to use quoteFields (string versions of
+-- current_task_id and workflow_id)
+CREATE TABLE workflow_instances
+(workflow_instance_id int PRIMARY KEY NOT NULL,
+workflow_instance_status varchar(255),
+workflow_id varchar(255) NOT NULL,
+current_task_id varchar(255) NOT NULL,
+start_date_time varchar(255),
+end_date_time varchar(255),
+current_task_start_date_time varchar(255),
+current_task_end_date_time varchar(255),
+priority float);
+
+CREATE TABLE workflow_instance_metadata
+(workflow_instance_id int NOT NULL,
+workflow_met_key varchar(1000) NOT NULL,
+workflow_met_val varchar(1000) NOT NULL);
+
+CREATE TABLE workflow_conditions
+(workflow_condition_id int NOT NULL PRIMARY KEY,
+workflow_condition_name varchar(255) NOT NULL,
+workflow_condition_class varchar(255) NOT NULL,
+workflow_condition_timeout int,
+workflow_optional boolean DEFAULT false);
+
+CREATE TABLE  task_condition_map
+(workflow_task_id int NOT NULL, 
+workflow_condition_id int NOT NULL
+condition_order int NOT NULL);
+
+CREATE TABLE workflow_task_configuration
+(workflow_task_id int NOT NULL,
+property_name varchar(1000) NOT NULL,
+property_value varchar(1000) NOT NULL);
+
+CREATE TABLE workflow_condition_configuration
+(workflow_condition_id int NOT NULL,
+property_name varchar(1000) NOT NULL,
+property_value varchar(1000) NOT NULL);
diff --git a/0.8.1-rc1/workflow/src/main/resources/workflow_oracle_create_sequences.sql b/0.8.1-rc1/workflow/src/main/resources/workflow_oracle_create_sequences.sql
new file mode 100644
index 0000000..e5885ba
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/main/resources/workflow_oracle_create_sequences.sql
@@ -0,0 +1,64 @@
+/*
+  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.
+*/
+
+create sequence workflows_seq
+start with 1
+increment by 1
+nomaxvalue;
+
+create trigger workflows_trigger
+before insert on workflows
+for each row
+begin
+select workflows_seq.nextval into :new.workflow_id from dual;
+end;
+
+create sequence workflow_tasks_seq
+start with 1
+increment by 1
+nomaxvalue;
+
+create trigger workflow_tasks_trigger
+before insert on workflow_tasks
+for each row
+begin
+select workflow_tasks_seq.nextval into :new.workflow_task_id from dual;
+end;
+
+create sequence workflow_instances_seq
+start with 1
+increment by 1
+nomaxvalue;
+
+create trigger workflow_instances_trigger
+before insert on workflow_instances
+for each row
+begin
+select workflow_instances_seq.nextval into :new.workflow_instance_id from dual;
+end;
+
+create sequence workflow_conditions_seq
+start with 1
+increment by 1
+nomaxvalue;
+
+create trigger workflow_conditions_trigger
+before insert on workflow_conditions
+for each row
+begin
+select workflow_conditions_seq.nextval into :new.workflow_condition_id from dual;
+end;
diff --git a/0.8.1-rc1/workflow/src/site/resources/css/guides.css b/0.8.1-rc1/workflow/src/site/resources/css/guides.css
new file mode 100644
index 0000000..df4af72
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/resources/css/guides.css
@@ -0,0 +1,44 @@
+/*
+  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.
+*/
+
+.info, .success, .warning, .error, .validation {
+border: 1px solid;
+margin: 10px 0px;
+padding:15px 10px 15px 50px;
+background-repeat: no-repeat;
+background-position: 10px center;
+}
+.info {
+color: #00529B;
+background-color: #BDE5F8;
+background-image: url('../images/info.png');
+}
+.success {
+color: #4F8A10;
+background-color: #DFF2BF;
+background-image:url('../images/success.png');
+}
+.warning {
+color: #9F6000;
+background-color: #FEEFB3;
+background-image: url('../images/warning.png');
+}
+.error {
+color: #D8000C;
+background-color: #FFBABA;
+background-image: url('../images/error.png');
+}
diff --git a/0.8.1-rc1/workflow/src/site/resources/images/cas-workflow.jpg b/0.8.1-rc1/workflow/src/site/resources/images/cas-workflow.jpg
new file mode 100644
index 0000000..083d29e
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/resources/images/cas-workflow.jpg
Binary files differ
diff --git a/0.8.1-rc1/workflow/src/site/resources/images/cas-workflow.psd b/0.8.1-rc1/workflow/src/site/resources/images/cas-workflow.psd
new file mode 100644
index 0000000..79ca201
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/resources/images/cas-workflow.psd
Binary files differ
diff --git a/0.8.1-rc1/workflow/src/site/resources/images/error.png b/0.8.1-rc1/workflow/src/site/resources/images/error.png
new file mode 100644
index 0000000..6ef6424
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/resources/images/error.png
Binary files differ
diff --git a/0.8.1-rc1/workflow/src/site/resources/images/info.png b/0.8.1-rc1/workflow/src/site/resources/images/info.png
new file mode 100644
index 0000000..6854687
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/resources/images/info.png
Binary files differ
diff --git a/0.8.1-rc1/workflow/src/site/resources/images/success.png b/0.8.1-rc1/workflow/src/site/resources/images/success.png
new file mode 100644
index 0000000..af074c6
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/resources/images/success.png
Binary files differ
diff --git a/0.8.1-rc1/workflow/src/site/resources/images/warning.png b/0.8.1-rc1/workflow/src/site/resources/images/warning.png
new file mode 100644
index 0000000..80834b0
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/resources/images/warning.png
Binary files differ
diff --git a/0.8.1-rc1/workflow/src/site/resources/images/wm_extension_points.png b/0.8.1-rc1/workflow/src/site/resources/images/wm_extension_points.png
new file mode 100644
index 0000000..d28abd7
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/resources/images/wm_extension_points.png
Binary files differ
diff --git a/0.8.1-rc1/workflow/src/site/resources/images/wm_object_model.png b/0.8.1-rc1/workflow/src/site/resources/images/wm_object_model.png
new file mode 100644
index 0000000..122446d
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/resources/images/wm_object_model.png
Binary files differ
diff --git a/0.8.1-rc1/workflow/src/site/resources/images/wm_use_case1.jpg b/0.8.1-rc1/workflow/src/site/resources/images/wm_use_case1.jpg
new file mode 100644
index 0000000..4d655c1
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/resources/images/wm_use_case1.jpg
Binary files differ
diff --git a/0.8.1-rc1/workflow/src/site/site.xml b/0.8.1-rc1/workflow/src/site/site.xml
new file mode 100644
index 0000000..53360d5
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/site.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<project name="cas-workflow">
+
+  <body>
+    <links>
+      <item name="OODT" href="../oodt-site/"/>
+    </links>
+
+    <menu ref="reports" inherit="bottom"/>
+    <menu name="Software Documentation">
+      <item name="Developer Guide" href="development/developer.html"/>
+      <item name="Basic User Guide" href="user/basic.html"/>
+      <item name="Advanced User Guide" href="user/advanced.html"/>
+    </menu>
+  </body>
+</project>
diff --git a/0.8.1-rc1/workflow/src/site/xdoc/development/developer.xml b/0.8.1-rc1/workflow/src/site/xdoc/development/developer.xml
new file mode 100644
index 0000000..f552d1a
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/xdoc/development/developer.xml
@@ -0,0 +1,331 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS File Manager Developer Guide</title>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+      <author email="woollard@jpl.nasa.gov">Dave Woollard</author>
+   </properties>
+
+   <body>
+   
+      <section name="Introduction">
+        <p>
+          This is the developer guide for the OODT Catalog and Archive Service (CAS) 
+          Workflow Manager component, or Workflow Manager for short. Primarily, this guide 
+          will explain the Workflow Manager architecture and interfaces, including its 
+          tailorable extension points. For information on installation, configuration,
+          and examples, please see our <a href="../user/basic.html">User Guides.</a>
+          
+          <p>The remainder of this guide is separated into the following sections:</p>
+      <ul>
+        <li><a href="#section1">Project Description</a></li>
+        <li><a href="#section2">Architecture</a></li>
+        <li><a href="#section3">Extension Points</a></li>
+        <li><a href="#section4">Current Extension Point Implementations</a></li>
+      </ul>
+          
+        </p>     
+      </section>
+      
+      <a name="section1"/>
+      <section name="Project Description">
+      <p>The Workflow Manager component is responsible for description, execution, and 
+      monitoring of <i>Workflows</i>, using a client, and a server system. Workflows are 
+      typically considered to be sequences of tasks, joined together by control flow, and 
+      data flow, that must execute in some ordered fashion. Workflows typically generate 
+      output data, perform routine management tasks (such as email, etc.), or describe a 
+      business's internal routine practices. The Workflow Manager is an extensible 
+      software component that provides an XML-RPC external interface, and a fully 
+      tailorable Java-based API for workflow management.</p>
+      </section>
+      
+      <a name="section2"/>
+      <section name="Architecture">
+      
+      <p>In this section, we will describe the architecture of the Workflow Manager,
+      including its constituent components, object model, and key capabilities.</p>
+      
+        <subsection name="Components">
+        
+        <p>The major components of the Workflow Manager are the Client and Server, the 
+        Workflow Repository, the Workflow Engine,and the Workflow Instance Repository.
+        The relationship between all of these components are shown in the diagram 
+        below:</p>
+        
+        <p><img src="../images/wm_extension_points.png" alt="Workflow Manager Architecture"/></p>
+        
+        <p>The Workflow Manager Server contains both a Workflow Repository that manages 
+        workflow models, and Workflow Engine that processes workflow instances. The Workflow
+        Engine also has a persistence layer called a Workflow Instance Repository that is
+        responsible for saving workflow instance metadata and state.</p> 
+        
+        </subsection>
+        
+        <subsection name="Object Model">
+        <p>The critical objects managed by the Workflow Manager include:</p>
+        
+        <ul>
+         <li><strong>Events</strong> - are what trigger Workflows to be executed. Events 
+         are named, and contain dynamic Metadata information, passed in by the user.</li>
+         
+         <li><strong>Metadata</strong> - a dynamic set of properties, and values, provided 
+         to a WorkflowInstance via a user-triggered Event.</li>
+         
+         <li><strong>Workflow</strong> - a description of both the control flow, and data 
+         flow of a sequence of tasks (or <i>stages</i> that must be executed in some order.
+         </li>
+         
+         <li><strong>Workflow Instance</strong> - an instance of a Workflow, typically 
+         containing additional runtime descriptive information, such as start time, end 
+         time, task wall clock time, etc. A WorkflowInstance also contains a shared Metadata 
+         context, passed in by the user who triggered the Workflow. This context can be 
+         read/written to by the underlying WorkflowTasks, present in a Workflow.</li>
+         
+         <li><strong>Workflow Tasks</strong> - descriptions of data flow, and an underlying 
+         process, or stage, that is part of a Workflow.</li>
+         
+         <li><strong>Workflow Task Instances</strong> - the actual executing code, or 
+         process, that performs the work in the Workflow Task.</li>
+         
+         <li><strong>Workflow Task Configuration</strong> - static configuration properties, 
+         that <i>configure</i> a WorkflowTask.</li>
+         
+         <li><strong>Workflow Conditions</strong> - any pre (or post) conditions on the 
+         execution of a WorkflowTask.</li>
+         
+         <li><strong>Workflow Condition Instances</strong> - the actual executing code, 
+         or process, that performs the work in the Workflow Condition.</li>
+        </ul>
+
+        <p>Each Event kicks off 1 or more Workflow Instances, providing a Metadata context 
+        (submitted by an external user). Each Workflow Instance is a run-time execution model 
+        of a Workflow. Each Workflow contains 1 or more Workflow Tasks. Each Workflow Task 
+        contains a single Workflow Task Configuration, and one or more Workflow Conditions. 
+        Each Workflow Task has a corresponding Workflow Task Instance (that it models), 
+        as does each Workflow Condition have a corresponding Workflow Condition Instance. 
+        These relationships are shown in the below figure.</p>
+        
+        <p><img src="../images/wm_object_model.png" alt="Workflow Manager Object Model"/></p>
+        </subsection>
+      
+        <subsection name="Key Capabilities">
+        <p>The Workflow Manager is responsible for providing the necessary key capabilities 
+        for managing processing pipelines, data flow, and control flow. Each high level 
+        capability provided by the Workflow Manager is detailed below:</p>
+        
+		<p><strong>Explicit Modeling.</strong> The Workflow manager captures both
+        identified workflow patterns (control-flow) and data-flow between Workflow Task 
+        Instances. Workflows are directed graphs, allowing for true parallelism.</p>
+          
+        <p><strong>Persistence.</strong> Support for persistance of Workflow Instances 
+        to several backend repositories, including relational databases, and Apache 
+        <a href="http://lucene.apache.org">Lucene</a> flat file indices.</p>
+          
+        <p><strong>Standard Representations.</strong> The Workflow Manager represents 
+        Workflow models as XML documents.</p>
+          
+        <p><strong>Scalability.</strong> The Workflow Manager uses the popular 
+        client-server paradigm, allowing new Workflow Manager servers to be 
+        instantiated, as needed, without affecting the Workflow Manager clients, 
+        and vice-versa.</p>
+          
+        <p><strong>Standard communication protocols.</strong> The Workflow Manager uses 
+        XML-RPC as its main external interface between the File Manager client and 
+        server. XML-RPC, the little brother of SOAP, is fast, extensible, and uses 
+        the underlying HTTP protocol for data transfer.</p>
+          
+        <p><strong>Event-Driven Execution.</strong> Workflows are triggered by events 
+        that can include arbitrary Metadata parameters, provided as a shared context
+        between stages of the executing Workflow.</p>
+          
+        <p>This capability set is not exhaustive, and is meant to give the user a 
+        <i>feel</i> for what general features are provided by the Workflow Manager. 
+        Most likely the user will find that the Workflow Manager provides many other 
+        capabilities besides those described here.</p>
+        </subsection>
+      
+      </section>
+      
+      <a name="section3"/>
+      <section name="Extension Points">
+      
+        <p>We have constructed the Workflow Manager making use of the <i>factory 
+        method pattern</i> to provide multiple extension points for the Workflow 
+        Manager. An extension point is an interface within the Workflow Manager 
+        that can have many implementations. This is particularly useful when it 
+        comes to software component configuration because it allows different 
+        implementations of an existing interface to be selected at deployment 
+        time.</p> 
+          
+        <div class="info">The factory method pattern is a creational pattern common to
+        object oriented design. Each File Manager extension point involves the 
+        implementation of two interfaces: an <i>extension factory</i> and an 
+        <i>extension</i> implementation. At run-time, the File Manager loads a 
+        properties file specifies a factory class to use during extension point
+        instantiation. For example, the File Manager may communicate with a 
+        database-based Catalog and an XML-based Element Store (called a Validation 
+        Layer), or it may use a Lucene-based Catalog and a database-based Validation 
+        Layer.</div> 
+          
+        <p>Using extension points, it is fairly simple to support many different types 
+        of what are typically referred to as "plug-in architectures." Each of the core 
+        extension points for the Workflow Manager is described below:</p>
+       
+       <table>
+         <tr>
+           <td>Workflow Instance Repository</td>
+           <td>The Workflow Instance Repository extension point is responsible for 
+           storing all the instance data for Workflow Instances, including shared 
+           context metadata, runtime properties such as start date time, end date time, 
+           and task start/end date time.
+           </td>
+         </tr>
+         <tr>
+           <td>Workflow Repository</td>
+           <td>The Workflow Repository extension point is responsible for managing 
+           Workflow models, storing control flow, and Workflow Tasks, which model data 
+           flow. The Workflow Repository also stores Workflow Condition information, and 
+           Workflow Task Configuration. In essence, the Workflow Repository is a repository 
+           of abstract Workflow models, that get turned into Workflow Instances by the 
+           <code>Engine</code> extension point.
+           </td>
+         </tr>
+         <tr>
+           <td>Workflow Engine</td>
+           <td>The Workflow Engine's responsibility is to turn abstract Workflow models 
+           into executing Workflow Instances. The Workflow Engine tracks and monitors 
+           execution of Workflow Instances, and provides the ability to start, stop
+           and pause executing Workflow Instances. 
+           </td>
+         </tr>
+         <tr>
+           <td>System</td>
+           <td>The extension point that provides the external interface to the Workflow 
+           Manager services. This includes the Workflow Manager server interface, as well 
+           as the associated Workflow Manager client interface, that communicates with 
+           the server.
+           </td>
+         </tr>           
+        </table>
+      </section>
+       
+      <a name="section4"/>   
+      <section name="Current Extension Point Implementations">
+        
+        <p>There are at least two implementations of all of the aforementioned extension 
+        points for the Manager, with the exception of the ThreadPoolWorkflowEngine, which 
+        itself is meant to be an extension point. Each extension point implementation is 
+        detailed below:</p>
+
+        <subsection name="Workflow Instance Repository">
+          <ul>
+             <li><strong>Data Source based Workflow Instance Repository.</strong> An 
+             implementation of the Workflow Instance Repository  extension point 
+             interface that uses a JDBC accessible database backend.</li>
+             
+             <li><strong>Lucene based Workflow Instance Repository.</strong> An 
+             implementation of the Workflow Instance Repository extension point interface 
+             that uses the Lucene free text index system to store Workflow Instance 
+             information.</li>
+             
+             <li><strong>Memory based Workflow Instance Repository.</strong> An 
+             implementation of the Workflow Instance Repository extension point interface 
+             that stores Workflow Instance information in runtime memory.</li>
+          </ul>
+        </subsection>  
+           
+        <subsection name="Workflow Repository">
+          <ul>
+             <li><strong>Data Source based Workflow Repository.</strong> An 
+             implementation of the Workflow Repository extension point that stores 
+             Workflow model information in a JDBC accessible database.</li>
+             
+             <li><strong>XML based Workflow Repository.</strong> An implementation of the 
+             Workflow Repository extension point that stores Workflow model information 
+             in XML files ending in <code>*.workflow.xml</code>, as well as files named 
+             <code>tasks.xml</code>, <code>conditions.xml</code>, and 
+             <code>events.xml</code>.</li>
+          </ul>
+        </subsection> 
+         
+        <subsection name="Workflow Engine">
+          <ul>
+             <li><strong>ThreadPoolWorkflowEngine.</strong> An implementation of the 
+             Workflow Engine that itself is meant to be an extension point for 
+             WorkflowEngines that want to implement ThreadPooling. This WorkflowEngine 
+             provides everything needed to manage a ThreadPool using Doug Lea's wonderful 
+             java.util.concurrent package that made it into JDK5.</li>
+          </ul>
+        </subsection>
+        
+        <subsection name="System (Workflow Manager client and Workflow Manager server)">
+          <ul>
+             <li><strong>XML-RPC based Workflow Manager Server.</strong> An implementation 
+             of the external server interface for the Workflow Manager that uses XML-RPC 
+             as the transportation medium.</li>
+             
+             <li><strong>XML-RPC based Workflow Manager Client.</strong> An implementation 
+             of the client interface for the XML-RPC Workflow Manager server that uses 
+             XML-RPC as the transportation medium.</li>
+          </ul>
+        </subsection>
+      </section>
+      
+      <section name="Use Cases">
+        <p>
+          The Workflow Manager was built to support several of the above capabilities. In particular there 
+          were several use cases that we wanted to support, some 
+          of which are described below.        
+        </p>
+      
+         <img src="../images/wm_use_case1.jpg" alt="Workflow Manager Event-based Execution Use Case"/>
+         
+         <p>The black numbers in the above Figure correspond to a sequence of steps that occurs and a 
+         series of interactions between the different Workflow Manager extension points in order to 
+         perform the workflow execution activity. In Step 1, an event is provided to the Workflow
+         Manager event listenter (the System extension point), along with required Metadata. The
+         Workflow Manager, in step 2, looks up if ther are any associated Workflow Repository models
+         associated with the provided Event. If so, in steps 3 and 4, the returned Workflow models
+         are sent to the WorkflowEngine, to be turned into executable Workflow Instances.Each 
+         WorkflowInstance is handed off to a WorkflowProcessorThread, taken from the ThreadPoolWorkflowEngine,
+         in steps 5 and 6. The WorkflowProcessorThread, in step 7, steps through each executable WorkflowTask,
+         checking to make sure that all necessary Workflow Conditions (if any) are satisfied. If all Workflow 
+         Conditions are satisfied, then the Workflow Task is executed, either locally, or if an Resource Manager
+         is defined, then the task is sent (in step 7) to the Resource Manager (labeled <code>Process Manager</code>
+         in the figure). In steps 8-13, the WorkflowTask is executed on remote resources using the Resource Manager,
+         and eventually completed, with the final notification being sent back to the corresponding Workflow Processor
+         Thread, which is stepping through the Workflow Instance, controlling its exectuion. </p>
+         
+      </section>      
+      
+      <section name="Conclusion">
+      <p>The aim of this document is to provide information relevant to developers
+      about the CAS Worklfow Manager. Specifically, this document has described the Workflow 
+      Manager's architecture, including its constituent components, object model and
+      key capabilities. Additionally, this document provides an overview of the 
+      current implementations of the Workflow Manager's extension points.</p> 
+      
+      <p>In the <a href="../user/basic.html">Basic User Guide</a> and 
+      <a href="../user/advanced.html">Advanced User Guide</a>, we will cover topics
+      like installation, configuration, and example uses as well as advanced topics
+      like scaling and other tips and tricks.</p> 
+      
+      </section>
+   </body>
+</document>
diff --git a/0.8.1-rc1/workflow/src/site/xdoc/development/maven.xml b/0.8.1-rc1/workflow/src/site/xdoc/development/maven.xml
new file mode 100755
index 0000000..98ee19f
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/xdoc/development/maven.xml
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+  <properties>
+    <title>Using Maven</title>
+    <author email="woollard@jpl.nasa.gov">David Woollard</author>
+  </properties>
+
+  <body>
+    <section name="Using Maven">
+      <p>OODT uses <a href="http://maven.apache.org/">Maven</a> for 
+      managing our build environment. Maven is an open source product from the 
+      <a href="http://www.apache.org/">Apache Software Foundation</a> that improves 
+      on <a href="http://ant.apache.org/">Ant</a> in the area of build management, 
+      which it turn was an improvement on Make. This document describes the use of 
+      Maven for OODT build management.</p>
+    </section>
+    
+    <section name="Setup">
+      <p>Maven can be downloaded from the 
+      <a href="http://maven.apache.org/download.html">Maven Download</a> 
+      page. OODT is using version 2.0 and above. Maven was developed in Java so it 
+      will run on the popular platforms (e.g., Windows, Mac OSX, etc.). Beyond 
+      making sure the <i>mvn</i> executable is in your path, there is very little 
+      setup required.</p>
+
+      <p>Maven is based on the concept of a Project Object Model (POM) which is 
+      contained in the <i>pom.xml</i> file found at the root of each project. 
+      The POM allows Maven to manage a project's build, reporting and documentation. 
+      For OODT, much of the default information for managing the projects is 
+      contained in a parent POM, which is located in the <i>oodt-core</i> project. So, 
+      in order to build any of the other projects (e.g., cas-curator, cas-filemgr, 
+      etc.) the parent POM must be downloaded from the OODT Maven repository. The 
+      local <i>pom.xml</i> files for each of the projects have been configured to 
+      retrieve the parent POM automatically.</p>
+      
+      <p>Once Maven has been setup, the first step to building a project with Maven 
+      is to checkout a project's source code into the developer's work area. See the 
+      <a href="../development/subversion.html">Using Subversion</a> document for how to 
+      check out projects from the CM repository.</p>
+    </section>
+    
+    <section name="Project Structure">
+      <p>In order for default Maven functions to operate properly, there is a 
+      suggested project directory structure. The structure is as follows:</p>
+      
+      <source>
+/
+  src/             Source Code (everything)
+    main/            Program Source
+      assembly/        Package Descriptor
+      java/            Java Source
+      resources/       Scripts, Config File, etc.
+        ...
+    test/            Test Source
+      java/
+      resources/
+        ...
+    site/            Site Documentation
+      apt/             Docs in APT Format
+        index.apt
+        ...
+      xdoc/            Docs in XDOC Format
+        index.xml
+        ...
+      resources/
+        images/
+      site.xml         Menu Structure
+
+  target/          Build Results (binaries, docs and packages)
+    ...
+
+  LICENSE.txt
+  README.txt
+  pom.xml          Project Object Model (POM)
+      </source>
+    </section>
+    
+    <section name="Standard Commands">
+    <p>There are few standard commands that developers will use on a daily basis 
+    and they are related to building and cleaning a project.</p>
+    <subsection name="Build a Project">
+      <p>Build the project's libraries and executables with the following 
+      command:</p>
+      <source>
+mvn compile
+      </source>
+      <p>The above command will generate the artifacts in the <i>target/</i> 
+      directory.</p>      
+    </subsection>
+    <subsection name="Install a Project">
+      <p>Install the project's artifacts locally with the following command:</p>
+      <source>
+mvn install
+      </source>
+      <p>Prior to installation, the above command will compile the source code, 
+      if necessary, and execute the unit tests. The result of the above command 
+      is to install the generated artifacts (e.g. pom, jar, etc.) in the user's 
+      local Maven repository ($HOME/.m2/repository/). This is useful when the 
+      artifact is a dependency for another project but has yet to be deployed 
+      to the SWSA Maven repository.</p>
+    </subsection>
+    <subsection name="Package a Project">
+      <p>Create the project's distribution package with the following command:</p>
+      <source>
+mvn package
+      </source>
+      <p>Prior to package creation, the above command will compile the source 
+      code, if necessary, and execute the unit tests. The above command will 
+      create the package(s) in the target/ directory.</p>
+    </subsection>
+    <subsection name="Build a Project's Web Site">
+      <p>Build the project's web site with the following command:</p>
+      <source>
+mvn site
+      </source>
+      <p>The above command will generate the web site in the <i>target/site/</i>
+      directory. View the site by pointing your web browser at the 
+      <i>index.html</i> file within that directory.</p>
+    </subsection> 
+    <subsection name="Clean a Project">
+      <p>Clean out the project directory of generated artifacts with the 
+      following command:</p>
+      <source>
+mvn clean
+      </source>
+      <p>The above command will remove the <i>target/</i> directory and its 
+      contents.</p>
+    </subsection>
+    <subsection name="Useful Command Arguments">
+      <p>There a couple of useful arguments which can be appended to the 
+      commands above to limit the scope of the command.</p>
+      <p>In order to skip unit test execution, add the following argument:</p>
+      <source>
+mvn [command] -Dmaven.test.skip=true
+      </source>
+      <p>The above command is most useful with the <i>install</i>, 
+      <i>package</i> and <i>site</i> commands.</p>
+      <p>When a project has modules defined in the POM, the command can be 
+      performed against the top level of the project instead of the modules by 
+      adding the following argument:</p>
+      <source>
+mvn [command] --non-recursive
+      </source>
+    </subsection>
+    </section>
+    <section name="Acknowledgments">
+      <p>Much of the material in this Maven guide was originally authored 
+      by Sean Hardman under the sponsorship of NASA Jet Propulsion 
+      Laboratory's Planetary Data System. </p>
+    </section>
+    <section name="References">
+      <p>Here is a list of Maven resources:</p>
+      <ul>
+        <li><a href="http://maven.apache.org/guides/index.html">Online 
+        Documentation Index</a></li>
+      </ul>
+    </section>
+  </body>
+</document>
diff --git a/0.8.1-rc1/workflow/src/site/xdoc/user/advanced.xml b/0.8.1-rc1/workflow/src/site/xdoc/user/advanced.xml
new file mode 100644
index 0000000..1a9e720
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/xdoc/user/advanced.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS Workflow Manager User Guide</title>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+      <author email="woollard@jpl.nasa.gov">Dave Woollard</author>
+   </properties>
+
+   <body>
+   
+      <div class="warning">This document is in the process of being reorganized as
+      part of our ongoing documentation effort. Please check back for updates.</div>  
+   
+      <section name="Introduction">
+      
+      <p>In the CAS Workflow Manager Advanced User Guide, we will cover a number of 
+      advanced topics related to using the CAS Workflow Manager, including situations
+      that have arisen in the authors' experiences regarding the use alternative queuing 
+      strategies, addressing scaling issues, etc. Basic concepts, such as installation and 
+      configuration, can be found in the 
+      <a href="../user/basic.html">Basic User Guide</a>.</p>
+      
+      <p>The remainder of this guide is separated into the following sections:</p>
+      <ul>
+        <li><a href="#section1">Alternative Queuing</a></li>
+        <li><a href="#section2">Scaling Issues</a></li>
+      </ul>
+      
+      </section>
+      
+      <a name="section1"/>
+      <section name="Alternative Queuing">
+      <p>Coming Soon...</p>
+      </section>
+      
+      <a name="section2"/>
+      <section name="Scaling Issues">
+      <p>Coming Soon...</p>
+      </section>
+      
+   </body>
+</document> 
diff --git a/0.8.1-rc1/workflow/src/site/xdoc/user/basic.xml b/0.8.1-rc1/workflow/src/site/xdoc/user/basic.xml
new file mode 100644
index 0000000..0cd721d
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/xdoc/user/basic.xml
@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS Workflow Manager User Guide</title>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+      <author email="woollard@jpl.nasa.gov">Dave Woollard</author>
+   </properties>
+
+   <body>
+   
+      <div class="warning">This document is in the process of being reorganized as
+      part of our ongoing documentation effort. Please check back for updates.</div>
+      
+      <section name="Introduction">
+      
+      <p>This document serves as a basic user's guide for the CAS Workflow Manager 
+      project. The goal of the document is to allow users to check out, build, and 
+      install a base version of the CAS Workflow Manager, as well as perform basic 
+      configuration tasks. For advanced topics, such as configuring the Workflow 
+      Manager to Scale and other tips and tricks, please see our 
+      <a href="../user/advanced.html">Advanced Guide.</a></p>
+      
+      <p>The remainder of this guide is separated into the following sections:</p>
+      <ul>
+        <li><a href="#section1">Download and Build</a></li>
+        <li><a href="#section2">Configuration in 2 Minutes or Less</a></li>
+        <li><a href="#section3">Learn By Example</a></li>
+      </ul>  
+      </section> 
+     
+      <a name="section1"/>
+      <section name="Download and Build">
+        <p>The most recent CAS-Workflow Manager project can be downloaded from the Apache OODT
+        <a href="/">website</a> or it can be checked out 
+        from the OODT repository using Subversion. The CAS-Workflow Manager project is 
+        located at <code>../../workflow/</code>. We recommend checking
+        out the latest released version (v1.5.1 at the time of writing).</p>
+      
+        <p>Maven is the build management system used for OODT projects. We currently 
+        support Maven 2.0 and later. For more information on Maven, see our 
+        <a href="../development/maven.html">Maven Guide.</a></p>
+      
+        <p>Assuming a *nix-like environment, with both Maven and Subversion 
+        clients installed and on your path, an example of the checkout and 
+        build process is presented below:</p>
+        
+         <source>
+> mkdir /usr/local/src
+> cd /usr/local/src
+> svn checkout https://svn.apache.org/repos/asf/oodt/trunk/workflow workflow
+      </source>
+        
+      <p>After the Subversion command completes, you will have the source
+      for the CAS-Workflow project in the <code>/usr/local/src/workflow</code>
+      directory.</p>
+      
+      <p>In order to build the project from this source, issue the following 
+      commands:</p>
+      
+      <source>
+> cd /usr/local/src/workflow
+> mvn package    
+      </source>   
+      
+      <p>Note that this command performs a number of tasks, including performing
+      unit tests which can take a long time depending on your system. At the end of 
+      the process, you will see a Maven success banner.</p>
+      
+      <p>Once the Maven command completes successfully, you should have a 
+      <code>target</code> directory under <code>-workflow</code>. 
+      The project has been built in this directory as a distribution tar ball.
+      In order to move the built project out of the source directory and unpack the
+      tar ball, issue the following commands:</p>
+      
+      <source>
+> cd /usr/local
+> mv src/workflow/trunk/cas-workflow-vX.Y.Z-dist.tar.gz ./
+> tar -xvzf cas-workflow-vX.Y.Z-dist.tar.gz
+> export WORKFLOW_HOME=/usr/local/cas-workflow-vX.Y.Z
+      </source>       
+      
+      <p>The resultant directory layout from the unpacked tarball is as follows:</p>
+           
+      <source>
+bin/ etc/ logs/ doc/ lib/ policy/ LICENSE.txt CHANGES.txt
+      </source>
+      
+      <p>A basic description of the files and subdirectories of the deployment is 
+      presented below:</p>
+      <ul>
+         <li><strong>bin</strong> - contains scripts for running the Workflow Manager, 
+         including the "wmgr" server script, and the "wmgr-client" client script.</li>
+         
+         <li><strong>etc</strong> - contains the logging.properties file for the 
+         Workflow Manager, and the workflow.properties file used to configure the server 
+         options.</li>
+         
+         <li><strong>logs</strong> - the default directory into which log files are 
+         written.</li>
+              
+         <li><strong>doc</strong> - contains Javadoc documentation, and user guides 
+         for using the Workflow Manager.</li>
+         
+         <li><strong>lib</strong> - the required Java jar files to run the Workflow 
+         Manager.</li>
+         
+         <li><strong>policy</strong> - the default XML-based element and product type 
+         policy in case the user is using the Lucene Workflow Instance Repository and/or 
+         the XML Workflow Repository, along with the ThreadPoolWorkflowEngine.</li>
+         
+         <li><strong>CHANGES.txt</strong> - contains the CHANGES present in this 
+         released version of the Workflow Manager.</li>
+         
+         <li><strong>LICENSE.txt</strong> - the LICENSE for the Workflow Manager 
+         project.</li>
+       </ul>
+      
+      <p>Now you have a built Workflow Manager at <code>/usr/local/cas-workflow-vX.Y.Z</code>.
+      In the next section, we will discuss how you can configure the Workflow Manager for
+      basic operations.</p>
+      </section>
+      
+      <a name="section2"/>
+      <section name="Configuration in 2 Minutes or Less">
+      
+      <p>The reason for entitling this section "in 2 Minutes or Less" is to show that
+      in it's base deployment, with very minimal configuration, we can have the Workflow
+      Manager in a usable state, capable of managing workflow tasks to completion. For 
+      the record, I haven't timed it, but its pretty fast...</p>
+      
+      <p>We are going to set up the Workflow Manager to use the XML-based Workflow 
+      Repository, the ThreadPoolWorkflowEngine, and Lucene Workflow Instance Repository 
+      extension points. The first step is to edit the wmgr script in 
+      <code>$WORKFLOW_HOME/bin</code>. Make the following 
+      changes:</p>
+     
+       <ul>
+         <li>Set the <code>SERVER_PORT</code> variable to the desired port on which 
+         you'd like to run the Workflow Manager. Our default port is 9001.</li>
+         
+         <li>Set the <code>JAVA_HOME</code> variable to point to the location of your 
+         installed JRE runtime. If you do not know where this is, type <code>&gt; which 
+         java</code> and use that path.</li>
+         
+         <li>Set the <code>RUN_HOME</code> variable to point to the location to which
+         you'd like the Workflow Manager PID file written. Typically this should default to 
+         <code>/var/run</code>, but not all system administrators allow users to write 
+         to <code>/var/run</code>.</li>
+       </ul>
+       
+       <p>The second step in configuration is to edit 
+       <code>$WORKFLOW_HOME/bin/wmgr-client</code> script, making the following 
+       change:</p>
+       
+       <ul>
+          <li>Set the <code>JAVA_HOME</code> variable to point to the location of 
+          your installed JRE runtime.</li>
+       </ul>
+       
+       <p>In the third step of this configuration, you will set the Workflow Manager's
+       various extension points. For more information about the functionality of
+       these extension points, see our 
+       <a href="../development/developer.html">Developer Guide.</a> By default, 
+       the Workflow Manager is built to use the XML-based Workflow Repository, the 
+       ThreadPoolWorkflowEngine, and <a href="http://lucene.apache.org/">Lucene</a> 
+       Workflow Instance Repository extension points.</p> 
+       
+       <p>Make the following changes to 
+       <code>$WORKFLOW_HOME/etc/workflow.properties</code>:</p>
+       
+       <ul>     
+         <li>Specify the path to the directory where the Workflow Manager will create the
+         Lucene index and associated files by setting the 
+         <code>org.apache.oodt.cas.workflow.instanceRep.lucene.idxPath</code> property
+         to <code>$WORKFLOW_HOME/repo</code>. Make sure that this directory does
+         NOT exist the time you run the Workflow Manager. If the Workflow Manager does 
+         not find a directory at thie specified location, it will create all of the 
+         necessary directory structure and ancillary files.</li>
+         
+         <li>Specify the path to the directory where the XML policy files are stored 
+         for the the XML Workflow Repository. This path is set by 
+         <code>org.apache.oodt.cas.workflow.repo.dirs</code>. The 
+         default location (and default policy files) are located at 
+         <code>$WORKFLOW_HOME/policy</code> in the vanilla deployment of the Workflow Manager.
+         Note that these properties need to be fully specified URLs (e.g., they should 
+         start with <code>file://</code>).</li>
+       </ul>
+
+       <div class="info">Optionally, you can change the default logging properties for
+       the CAS Workflow Manager. This is done by editing 
+       <code>$WORKFLOW_HOME/etc/logging.properties</code>. We have tried to select sensible
+       defaults for the average user, but if you would like more or less information 
+       generated in the Workflow Manager logs, you can edit the levels of different catagories
+       of information in this proporties file. The following logging levels are available:
+       <code>INFO</code>, <code>WARNING</code>, <code>FINE</code>, <code>FINER</code>,
+       <code>FINEST</code>, and <code>ALL</code>.</div>
+   
+      <p>With this last step, you have configured the Workflow Manager. In order to test your 
+      configuration, cd to <code>$WORKFLOW_HOME/bin</code> and type:</p>
+       
+      <source>
+> ./wmgr start
+      </source> 
+       
+      <p>This will startup the workflow manager XML-RPC server interface. Your Workflow Manager 
+      is now ready to run! You can test out the workflow manager by running a command that 
+      will execute our preconfigured hello world workflow.</p>
+
+      <p>Run the below command, assuming that you started the Workflow Manager on the default 
+      port of 9001:</p>
+      
+      <source>
+> ./wmgr-client --url http://localhost:9001 --operation \
+                              --sendEvent \
+                              --eventName test 
+      </source> 
+      
+      <p>You should see a variety of info messages, in including the following:</p>
+      
+      <source>
+INFO: WorkflowManager: Received event: test
+INFO: WorkflowManager: Workflow testWorkflow retrieved for event test
+INFO: Task: [Hello World] has no required metadata fields
+INFO: Executing task: [Hello World] locally
+Hello World: Chris
+INFO: Task: [Goodbye World] has no required metadata fields
+INFO: Executing task: [Goodbye World] locally
+ Goodbye World: Chris            
+      </source>
+      
+      <p>Note that we have elided some of the timestamp information for the purposes of 
+      clarity. If you see the cannonical Hello World statement, you have succeeded in 
+      configuring the CAS Workflow Manager, hopefully in 2 minutes or less (and even if 
+      it took a little more time, you have to admit it was by and large painless).</p>
+      
+      </section>
+      
+      <a name="section3"/>
+      <section name="Learn By Example">
+      <p>Coming Soon...</p>
+      </section>
+      
+      <section name="Conclusion">
+      
+      <p>In this Basic User Guide, we have covered a number of topics, including Workflow 
+      Manager installation, configuration, and a basic example of use. For more advanced 
+      topics, including the use of alternative queuing strategies and best practices for 
+      addressinbg scaling issues, see our 
+      <a href="../user/advanced.html">Advanced Guide.</a></p>
+      
+      </section>
+   </body>
+   
+</document>
diff --git a/0.8.1-rc1/workflow/src/site/xdoc/user/index.xml b/0.8.1-rc1/workflow/src/site/xdoc/user/index.xml
new file mode 100644
index 0000000..e626c53
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/site/xdoc/user/index.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+   <properties>
+      <title>CAS Workflow Manager User Guide</title>
+      <author email="Chris.Mattmann@jpl.nasa.gov">Chris Mattmann</author>
+      <author email="woollard@jpl.nasa.gov">Dave Woollard</author>
+   </properties>
+
+   <body>
+
+      <div class="warning">This document is in the process of being reorganized as
+      part of our ongoing documentation effort. Please follow the links below to find
+      information that has previously been hosted on this page.</div>
+ 
+
+      <p>We are in the process of upgrading OODT documentation. In the near
+      future, we hope to provide information for developers regarding each 
+      component, including its purpose, structure, interfaces, and 
+      configuration points in a <a href="../development/developer.html">Developer
+      Guide.</a></p>
+      
+      <p>Information for users, including installation and basic configuration,
+      as well as example usage are provided in a 
+      <a href="../user/basic.html">Basic User Guide.</a> Advanced topics, like
+      look and feel, lessons-learned, and best practices are provided in an
+      <a href="../user/advanced.html">Advanced User Guide.</a></p>
+      
+      <p>Finally, we are planning to provide a number of case studies in the 
+      future, in which multi-component deployments are configured to handle
+      common data and computation management scenarios.</p> 
+
+   </body>
+</document> 
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/cli/TestWorkflowCli.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/cli/TestWorkflowCli.java
new file mode 100644
index 0000000..f0f4e91
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/cli/TestWorkflowCli.java
@@ -0,0 +1,299 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli;
+
+//OODT imports
+import org.apache.oodt.cas.cli.CmdLineUtility;
+import org.apache.oodt.cas.cli.util.OptionPropertyRegister;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.repository.MockWorkflowRepository;
+import org.apache.oodt.cas.workflow.system.MockXmlRpcWorkflowManagerClient;
+import org.apache.oodt.cas.workflow.system.MockXmlRpcWorkflowManagerClient.MethodCallDetails;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+//JUnit imports
+import junit.framework.TestCase;
+
+/**
+ * Tests Workflow Manager Clients Command-line interface.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class TestWorkflowCli extends TestCase {
+
+   static {
+      System.setProperty("org.apache.oodt.cas.cli.debug", "true");
+      System.setProperty("org.apache.oodt.cas.cli.action.spring.config", "src/main/resources/cmd-line-actions.xml");
+      System.setProperty("org.apache.oodt.cas.cli.option.spring.config", "src/main/resources/cmd-line-options.xml");
+      System.setProperty("workflow.engine.factory", "org.apache.oodt.cas.workflow.engine.MockWorkflowEngineFactory");
+      System.setProperty("workflow.engine.instanceRep.factory", "org.apache.oodt.cas.workflow.instrepo.MemoryWorkflowInstanceRepositoryFactory");
+      System.setProperty("workflow.repo.factory", "org.apache.oodt.cas.workflow.repository.MockWorkflowRepositoryFactory");
+   }
+
+   private CmdLineUtility cmdLineUtility;
+   private MockXmlRpcWorkflowManagerClient client;
+
+   @Override
+   public void setUp() throws Exception {
+      cmdLineUtility = new CmdLineUtility();
+      UseMockClientCmdLineActionStore actionStore = new UseMockClientCmdLineActionStore();
+      client = actionStore.getClient();
+      cmdLineUtility.setActionStore(actionStore);
+   }
+
+   @Override
+   public void tearDown() throws Exception {
+      OptionPropertyRegister.clearRegister();
+   }
+
+   public void testDynWorkflow() throws Exception {
+      cmdLineUtility
+            .run(("--url http://localhost:9000"
+                  + " --operation --dynWorkflow --taskIds "
+                  + MockWorkflowRepository.TASK1_ID + " "
+                  + MockWorkflowRepository.TASK2_ID + " "
+                  + MockWorkflowRepository.TASK3_ID
+                  + " --metaData --key Filename data.dat --key NominalDate 2001-02-20")
+                  .split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("executeDynamicWorkflow", methodCallDetails.getMethodName());
+      assertEquals(Lists.newArrayList(MockWorkflowRepository.TASK1_ID,
+            MockWorkflowRepository.TASK2_ID, MockWorkflowRepository.TASK3_ID),
+            methodCallDetails.getArgs().get(0));
+      Metadata m = new Metadata();
+      m.addMetadata("NominalDate", Lists.newArrayList("2001-02-20"));
+      m.addMetadata("Filename", Lists.newArrayList("data.dat"));
+      assertEquals(m, methodCallDetails.getArgs().get(1));
+   }
+
+   public void testGetConditionById() {
+      cmdLineUtility
+            .run(("--url http://localhost:9000"
+                  + " --operation --getConditionById --id "
+                  + MockWorkflowRepository.CONDITION1_ID)
+                  .split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getConditionById", methodCallDetails.getMethodName());
+      assertEquals(MockWorkflowRepository.CONDITION1_ID, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetFirstPage() {
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getFirstPage").split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getFirstPage", methodCallDetails.getMethodName());
+
+      OptionPropertyRegister.clearRegister();
+
+      String status = "DONE";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getFirstPage --status " + status).split(" "));
+      methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("paginateWorkflowInstances", methodCallDetails.getMethodName());
+      assertEquals(1, methodCallDetails.getArgs().get(0));
+      assertEquals(status, methodCallDetails.getArgs().get(1));
+   }
+ 
+   public void testGetLastPage() {
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getLastPage").split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getLastPage", methodCallDetails.getMethodName());
+
+      OptionPropertyRegister.clearRegister();
+
+      String status = "DONE";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getLastPage --status " + status).split(" "));
+      methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("paginateWorkflowInstances", methodCallDetails.getMethodName());
+      assertEquals(0, methodCallDetails.getArgs().get(0));
+      assertEquals(status, methodCallDetails.getArgs().get(1));
+   }
+
+   public void testGetNextPage() {
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getNextPage --pageNum 1").split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("paginateWorkflowInstances", methodCallDetails.getMethodName());
+
+      OptionPropertyRegister.clearRegister();
+
+      String status = "DONE";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getNextPage --pageNum 1 --status " + status).split(" "));
+      methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("paginateWorkflowInstances", methodCallDetails.getMethodName());
+      assertEquals(2, methodCallDetails.getArgs().get(0));
+      assertEquals(status, methodCallDetails.getArgs().get(1));
+   }
+
+   public void testGetPrevPage() {
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getPrevPage --pageNum 1").split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("paginateWorkflowInstances", methodCallDetails.getMethodName());
+
+      OptionPropertyRegister.clearRegister();
+
+      String status = "DONE";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getPrevPage --pageNum 1 --status " + status).split(" "));
+      methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("paginateWorkflowInstances", methodCallDetails.getMethodName());
+      assertEquals(0, methodCallDetails.getArgs().get(0));
+      assertEquals(status, methodCallDetails.getArgs().get(1));
+   }
+
+   public void testGetRegisteredEvents() {
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getRegisteredEvents").split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getRegisteredEvents", methodCallDetails.getMethodName());
+      assertTrue(methodCallDetails.getArgs().isEmpty());
+   }
+
+   public void testGetTaskById() {
+      String taskId = MockWorkflowRepository.TASK1_ID;
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getTaskById --id " + taskId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getTaskById", methodCallDetails.getMethodName());
+      assertEquals(taskId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetTaskWallClockTime() {
+      String taskId = MockWorkflowRepository.TASK1_ID;
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getTaskWallClockTime --id " + taskId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getWorkflowCurrentTaskWallClockMinutes", methodCallDetails.getMethodName());
+      assertEquals(taskId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetWallClockTime() {
+      String taskId = MockWorkflowRepository.TASK1_ID;
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getWallClockTime --id " + taskId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getWorkflowWallClockMinutes", methodCallDetails.getMethodName());
+      assertEquals(taskId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetWorkflowById() {
+      String workflowId = MockWorkflowRepository.WORKFLOW1_ID;
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getWorkflowById --id " + workflowId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getWorkflowById", methodCallDetails.getMethodName());
+      assertEquals(workflowId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetWorkflowInst() {
+      String instId = "TestId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getWorkflowInst --id " + instId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getWorkflowCurrentTaskWallClockMinutes", methodCallDetails.getMethodName());
+      assertEquals(instId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetWorkflowInstMet() {
+      String instId = "TestId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getWorkflowInstMet --id " + instId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getWorkflowInstanceMetadata", methodCallDetails.getMethodName());
+      assertEquals(instId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetWorkflowInsts() {
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getWorkflowInsts").split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getWorkflowInstances", methodCallDetails.getMethodName());
+      assertTrue(methodCallDetails.getArgs().isEmpty());
+   }
+
+   public void testGetWorkflowsByEvent() {
+      String eventName = "TestEventName";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getWorkflowsByEvent --eventName " + eventName).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getWorkflowsByEvent", methodCallDetails.getMethodName());
+      assertEquals(eventName, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testGetWorkflows() {
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --getWorkflows").split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("getWorkflows", methodCallDetails.getMethodName());
+      assertTrue(methodCallDetails.getArgs().isEmpty());
+   }
+
+   public void testPauseWorkflowInst() {
+      String instId = "TestId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --pauseWorkflowInst --id " + instId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("pauseWorkflowInstance", methodCallDetails.getMethodName());
+      assertEquals(instId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testResumeWorkflowInst() {
+      String instId = "TestId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --resumeWorkflowInst --id " + instId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("resumeWorkflowInstance", methodCallDetails.getMethodName());
+      assertEquals(instId, methodCallDetails.getArgs().get(0));
+   }
+
+   public void testSendEvent() {
+      String eventName = "TestEventName";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --sendEvent --eventName " + eventName).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("sendEvent", methodCallDetails.getMethodName());
+      assertEquals(eventName, methodCallDetails.getArgs().get(0));
+
+      OptionPropertyRegister.clearRegister();
+
+      cmdLineUtility.run(("--url http://localhost:9000"
+           + " --operation --sendEvent --eventName " + eventName
+           + " --metaData --key Filename data.dat --key NominalDate 2001-02-20").split(" "));
+      methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("sendEvent", methodCallDetails.getMethodName());
+      assertEquals(eventName, methodCallDetails.getArgs().get(0));
+      Metadata m = new Metadata();
+      m.addMetadata("Filename", Lists.newArrayList("data.dat"));
+      m.addMetadata("NominalDate", Lists.newArrayList("2001-02-20"));
+      assertEquals(m, methodCallDetails.getArgs().get(1));
+   }
+
+   public void testStopWorkflowInstance() {
+      String instId = "TestId";
+      cmdLineUtility.run(("--url http://localhost:9000"
+            + " --operation --stopWorkflowInst --id " + instId).split(" "));
+      MethodCallDetails methodCallDetails = client.getLastMethodCallDetails();
+      assertEquals("stopWorkflowInstance", methodCallDetails.getMethodName());
+      assertEquals(instId, methodCallDetails.getArgs().get(0));
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/cli/UseMockClientCmdLineActionStore.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/cli/UseMockClientCmdLineActionStore.java
new file mode 100644
index 0000000..c55cb5a
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/cli/UseMockClientCmdLineActionStore.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.cli;
+
+//JDK imports
+import java.util.Set;
+
+//OODT imports
+import org.apache.oodt.cas.cli.action.CmdLineAction;
+import org.apache.oodt.cas.cli.action.store.spring.SpringCmdLineActionStore;
+import org.apache.oodt.cas.cli.exception.CmdLineActionStoreException;
+import org.apache.oodt.cas.workflow.cli.action.WorkflowCliAction;
+import org.apache.oodt.cas.workflow.system.MockXmlRpcWorkflowManagerClient;
+
+/**
+ * A {@link SpringCmdLineActionStore} which sets {@link WorkflowCliAction}s
+ * to use a {@link MockXmlRpcWorkflowManagerClient}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class UseMockClientCmdLineActionStore extends SpringCmdLineActionStore {
+
+   private MockXmlRpcWorkflowManagerClient client;
+
+   public UseMockClientCmdLineActionStore() {
+      super(System.getProperty("org.apache.oodt.cas.cli.action.spring.config"));
+      try {
+         client = new MockXmlRpcWorkflowManagerClient();
+      } catch (Exception e) {
+         throw new RuntimeException(e);
+      }
+   }
+
+   public Set<CmdLineAction> loadSupportedActions() throws CmdLineActionStoreException {
+      Set<CmdLineAction> actions = super.loadSupportedActions();
+      for (CmdLineAction action : actions) {
+         if (action instanceof WorkflowCliAction) {
+            ((WorkflowCliAction) action).setClient(client);
+         }
+      }
+      return actions;
+   }
+
+   public MockXmlRpcWorkflowManagerClient getClient() {
+      return client;
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/MetSetterTaskQuerier.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/MetSetterTaskQuerier.java
new file mode 100644
index 0000000..aa55bc0
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/MetSetterTaskQuerier.java
@@ -0,0 +1,68 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine;
+
+//JDK imports
+import java.util.Calendar;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.engine.processor.TaskProcessor;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessorQueue;
+import org.apache.oodt.cas.workflow.structs.PrioritySorter;
+import org.apache.oodt.commons.date.DateUtils;
+
+/**
+ * 
+ * Intercepts the calls to {@link TaskQuerier#getNext()} and injects
+ * StartDateTime (and potentially other met fields into the
+ * {@link TaskProcessor#getDynamicMetadata()}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class MetSetterTaskQuerier extends TaskQuerier {
+
+  private static final long WAIT_SECS=1;
+  
+  /**
+   * @param processorQueue
+   * @param prioritizer
+   */
+  public MetSetterTaskQuerier(WorkflowProcessorQueue processorQueue,
+      PrioritySorter prioritizer) {
+    super(processorQueue, prioritizer, null, WAIT_SECS);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.oodt.cas.workflow.engine.TaskQuerier#getNext()
+   */
+  @Override
+  public TaskProcessor getNext() {
+    TaskProcessor taskProcessor = super.getNext();
+    if(taskProcessor == null) return null;
+    Metadata met = new Metadata();
+    met.addMetadata("StartDateTime", DateUtils.toString(Calendar.getInstance()));
+    taskProcessor.getWorkflowInstance().setSharedContext(met);
+    return taskProcessor;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/MockProcessorQueue.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/MockProcessorQueue.java
new file mode 100644
index 0000000..87d28f4
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/MockProcessorQueue.java
@@ -0,0 +1,71 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine;
+
+//JDK imports
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessorQueue;
+
+/**
+ * 
+ * A mock {@link WorkflowProcessorQueue} object for use in testing.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class MockProcessorQueue extends WorkflowProcessorQueue {
+
+  private QuerierAndRunnerUtils utils;
+
+  private boolean consumed;
+
+  public MockProcessorQueue() {
+    super(null,null,null);
+    this.utils = new QuerierAndRunnerUtils();
+    this.consumed = false;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.engine.WorkflowProcessorQueue#getProcessors ()
+   */
+  @Override
+  public synchronized List<WorkflowProcessor> getProcessors() {
+    List<WorkflowProcessor> processors = new Vector<WorkflowProcessor>();
+    try {
+      if (!consumed) {
+        processors.add(utils.getProcessor(10.0, "Success", "done"));
+        processors.add(utils.getProcessor(2.0, "Loaded", "initial"));
+        processors.add(utils.getProcessor(7.0, "Loaded", "initial"));
+        this.consumed = true;
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw new RuntimeException(e);
+    }
+
+    return processors;
+  }
+
+}
\ No newline at end of file
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/QuerierAndRunnerUtils.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/QuerierAndRunnerUtils.java
new file mode 100644
index 0000000..0d83638
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/QuerierAndRunnerUtils.java
@@ -0,0 +1,111 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.processor.SequentialProcessor;
+import org.apache.oodt.cas.workflow.engine.processor.TaskProcessor;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessorBuilder;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+import org.apache.oodt.cas.workflow.structs.Graph;
+import org.apache.oodt.cas.workflow.structs.ParentChildWorkflow;
+import org.apache.oodt.cas.workflow.structs.Priority;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+
+/**
+ * 
+ * Utilities for testing the {@link TaskQuerier} and {@link TaskRunner} thread
+ * classes.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class QuerierAndRunnerUtils {
+
+  private int dateGen;
+  
+  public QuerierAndRunnerUtils() {
+    this.dateGen = 0;
+  }
+  
+  public WorkflowTask getTask(File testDir){
+    WorkflowTask task = new WorkflowTask();
+    task.setConditions(Collections.emptyList());
+    task.setRequiredMetFields(Collections.emptyList());
+    task.setTaskId("urn:cas:workflow:tester");
+    task.setTaskInstanceClassName(SimpleTester.class.getName());
+    task.setTaskName("Tester");
+    WorkflowTaskConfiguration config = new WorkflowTaskConfiguration();
+    config.addConfigProperty("TestDirPath",
+        testDir.getAbsolutePath().endsWith("/") ? testDir.getAbsolutePath()
+            : testDir.getAbsolutePath() + "/");
+    task.setTaskConfig(config);
+    return task;
+  }
+
+  public WorkflowProcessor getProcessor(double priority, String stateName,
+      String categoryName) throws InstantiationException,
+      IllegalAccessException, IOException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException {
+    WorkflowLifecycleManager lifecycleManager = new WorkflowLifecycleManager(
+        "./src/main/resources/examples/wengine/wengine-lifecycle.xml");
+    WorkflowInstance inst = new WorkflowInstance();
+    Date sd = new Date();
+    sd.setTime(sd.getTime() + (this.dateGen * 5000));
+    this.dateGen++;
+    inst.setStartDate(sd);
+    inst.setId("task-winst-" + priority);
+    ParentChildWorkflow workflow = new ParentChildWorkflow(new Graph());
+    workflow.getTasks().add(getTask(getTmpPath()));
+    inst.setParentChildWorkflow(workflow);
+    inst.setPriority(Priority.getPriority(priority));
+    inst.setCurrentTaskId(workflow.getTasks().get(0).getTaskId());
+    inst.setParentChildWorkflow(workflow);
+    WorkflowProcessorBuilder builder = WorkflowProcessorBuilder
+        .aWorkflowProcessor().withLifecycleManager(lifecycleManager)
+        .withPriority(priority).withInstance(inst);
+    TaskProcessor taskProcessor = (TaskProcessor) builder
+        .build(TaskProcessor.class);
+    taskProcessor.getWorkflowInstance().setState(lifecycleManager.getDefaultLifecycle().createState(
+        stateName, categoryName, ""));    
+    return taskProcessor;
+  }
+  
+  private File getTmpPath() throws IOException{
+    File testDir = null;
+    String parentPath = File.createTempFile("test", "txt").getParentFile().getAbsolutePath();
+    parentPath = parentPath.endsWith("/") ? parentPath:parentPath + "/";
+    String testJobDirPath = parentPath + "jobs";
+    testDir = new File(testJobDirPath);
+    testDir.mkdirs();
+    return testDir;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/SimpleTester.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/SimpleTester.java
new file mode 100644
index 0000000..5d2c378
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/SimpleTester.java
@@ -0,0 +1,84 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine;
+
+//JDK imports
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+import org.apache.oodt.cas.workflow.structs.exceptions.WorkflowTaskInstanceException;
+
+/**
+ * 
+ * A simple workflow task instance that writes its start date time to a file.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class SimpleTester implements WorkflowTaskInstance {
+
+  private static final Logger LOG = Logger.getLogger(SimpleTester.class
+      .getName());
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance#run(org.apache
+   * .oodt.cas.metadata.Metadata,
+   * org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration)
+   */
+  @Override
+  public void run(Metadata metadata, WorkflowTaskConfiguration config)
+      throws WorkflowTaskInstanceException {
+    PrintWriter pw = null;
+    try {
+      String jobFilePath = config.getProperty("TestDirPath") + "task-"
+          + metadata.getMetadata("StartDateTime") + ".job";
+      int n=0;
+      while(new File(jobFilePath).exists()){
+        jobFilePath = config.getProperty("TestDirPath") + "task-" 
+        + n + metadata.getMetadata("StartDateTime") + ".job";
+        n++;
+      }
+      LOG.log(Level.INFO, "Creating job file: [" + jobFilePath + "]");
+      pw = new PrintWriter(new FileOutputStream(jobFilePath));
+      pw.println("StartDateTime=" + metadata.getMetadata("StartDateTime"));
+    } catch (FileNotFoundException e) {
+      throw new WorkflowTaskInstanceException(e.getMessage());
+    } finally {
+      if (pw != null) {
+        try {
+          pw.close();
+        } catch (Exception ignore) {
+        }
+        pw = null;
+      }
+    }
+
+  }
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/TestAsynchronousLocalEngineRunner.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/TestAsynchronousLocalEngineRunner.java
new file mode 100644
index 0000000..68b5b1c
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/TestAsynchronousLocalEngineRunner.java
@@ -0,0 +1,172 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine;
+
+//JDK imports
+import java.io.BufferedReader;
+import java.io.File;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+
+//APACHE imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.engine.processor.TaskProcessor;
+import org.apache.oodt.cas.workflow.engine.runner.AsynchronousLocalEngineRunner;
+import org.apache.oodt.cas.workflow.structs.Priority;
+import org.apache.oodt.commons.date.DateUtils;
+import org.apache.oodt.commons.util.DateConvert;
+
+//JODA imports
+import org.joda.time.DateTime;
+import org.joda.time.Seconds;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * A test case for the {@link AsynchronousLocalEngineRunner}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestAsynchronousLocalEngineRunner extends TestCase {
+
+  private AsynchronousLocalEngineRunner runner;
+
+  protected File testDir;
+
+  private QuerierAndRunnerUtils utils;
+
+  public void testRun() {
+    TaskProcessor taskProcessor1 = null;
+    TaskProcessor taskProcessor2 = null;
+
+    try {
+      taskProcessor1 = (TaskProcessor) utils.getProcessor(Priority.getDefault()
+          .getValue(), "Executing", "running");
+      taskProcessor2 = (TaskProcessor) utils.getProcessor(Priority.getDefault()
+          .getValue(), "Executing", "running");
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    Metadata met = new Metadata();
+    met.addMetadata("StartDateTime", DateUtils.toString(Calendar.getInstance()));
+
+    taskProcessor1.getWorkflowInstance().getSharedContext().addMetadata(met);
+    taskProcessor2.getWorkflowInstance().getSharedContext().addMetadata(met);
+
+    try {
+      runner.execute(taskProcessor1);
+      runner.execute(taskProcessor2);
+      assertTrue(ranFast());
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+  }
+
+  private boolean ranFast() {
+    boolean ranFast = true;
+    int jobNum = 1;
+    for (File f : this.testDir.listFiles()) {
+      BufferedReader br = null;
+      try {
+        String line = FileUtils.readFileToString(f);
+        String[] toks = line.split(",");
+        assertEquals("Toks not equal to 2: toks=[" + Arrays.asList(toks) + "]",
+            2, toks.length);
+        Date dateTime = DateConvert.isoParse(toks[1]);
+        Seconds seconds = Seconds.secondsBetween(new DateTime(dateTime),
+            new DateTime());
+        if (seconds.getSeconds() > 30) {
+          fail("More than 30 seconds elapsed now and running job " + jobNum
+              + ": seconds elapsed: [" + seconds.getSeconds() + "]");
+        }
+      } catch (Exception e) {
+        e.printStackTrace();
+        fail(e.getMessage());
+        ranFast = false;
+      } finally {
+        if (br != null) {
+          try {
+            br.close();
+          } catch (Exception ignore) {
+          }
+
+          br = null;
+        }
+      }
+    }
+
+    return ranFast;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#setUp()
+   */
+  @Override
+  protected void setUp() throws Exception {
+    String parentPath = File.createTempFile("test", "txt").getParentFile()
+        .getAbsolutePath();
+    parentPath = parentPath.endsWith("/") ? parentPath : parentPath + "/";
+    String testJobDirPath = parentPath + "jobs";
+    testDir = new File(testJobDirPath);
+    testDir.mkdirs();
+    this.runner = new AsynchronousLocalEngineRunner();
+    this.utils = new QuerierAndRunnerUtils();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#tearDown()
+   */
+  @Override
+  protected void tearDown() throws Exception {
+
+    // blow away test file
+    deleteAllFiles(testDir.getAbsolutePath());
+    testDir.delete();
+    testDir = null;
+    this.runner = null;
+  }
+
+  private void deleteAllFiles(String startDir) {
+    File startDirFile = new File(startDir);
+    File[] delFiles = startDirFile.listFiles();
+
+    if (delFiles != null && delFiles.length > 0) {
+      for (int i = 0; i < delFiles.length; i++) {
+        delFiles[i].delete();
+      }
+    }
+
+    startDirFile.delete();
+
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/TestTaskQuerier.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/TestTaskQuerier.java
new file mode 100644
index 0000000..fe5bc9f
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/TestTaskQuerier.java
@@ -0,0 +1,104 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine;
+
+//OODT imports
+import java.util.List;
+
+import org.apache.oodt.cas.workflow.engine.processor.TaskProcessor;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor;
+import org.apache.oodt.cas.workflow.structs.FILOPrioritySorter;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test harness for the {@link TestTaskQuerier}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestTaskQuerier extends TestCase {
+  
+  private int dateGen;
+  
+  private static final long WAIT_SECS = 1;
+
+  public TestTaskQuerier() {
+    this.dateGen = 0;
+  }
+  
+  public void testGetNext(){
+    FILOPrioritySorter prioritizer = new FILOPrioritySorter();
+    MockProcessorQueue processorQueue = new MockProcessorQueue();
+    List<WorkflowProcessor> queued = null;
+    assertNotNull(queued = processorQueue.getProcessors());
+    assertEquals(3, queued.size());
+    processorQueue = new MockProcessorQueue();
+    TaskQuerier querier = new TaskQuerier(processorQueue, prioritizer, null, WAIT_SECS);
+    Thread querierThread = new Thread(querier);
+    querierThread.start();
+    List<WorkflowProcessor> runnables = null;
+    while ((runnables = querier.getRunnableProcessors()) != null && 
+        runnables.size() < 2) {
+      assertNotNull(runnables);
+    }
+
+    querier.setRunning(false);
+    assertNotNull(runnables);
+    assertEquals(2, runnables.size());
+    TaskProcessor next = querier.getNext();
+    assertNotNull(next);
+    assertEquals(1, querier.getRunnableProcessors().size());
+  }
+
+  public void testGetRunnableProcessors() {
+    FILOPrioritySorter prioritizer = new FILOPrioritySorter();
+    MockProcessorQueue processorQueue = new MockProcessorQueue();    
+    List<WorkflowProcessor> queued = null;
+    assertNotNull(queued = processorQueue.getProcessors());
+    assertEquals(3, queued.size());
+    processorQueue = new MockProcessorQueue();
+    TaskQuerier querier = new TaskQuerier(processorQueue, prioritizer, null, WAIT_SECS);
+    Thread querierThread = new Thread(querier);
+    querierThread.start();
+    List<WorkflowProcessor> runnables = null;
+    while ((runnables = querier.getRunnableProcessors()) != null && 
+        runnables.size() < 2) {
+      assertNotNull(runnables);
+    }
+
+    querier.setRunning(false);
+    assertNotNull(runnables);
+    assertEquals(2, runnables.size());
+    assertNotNull(runnables.get(0));
+    assertNotNull(runnables.get(0).getWorkflowInstance().getPriority());
+    assertEquals(2.1, runnables.get(0).getWorkflowInstance().getPriority()
+        .getValue()); // extra .1 since it's a task
+    assertEquals(7.1, runnables.get(1).getWorkflowInstance().getPriority()
+        .getValue()); // extra .1 since it's a task
+    try{
+      querierThread.join();
+    }
+    catch(InterruptedException ignore){}
+
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/TestTaskRunner.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/TestTaskRunner.java
new file mode 100644
index 0000000..aecdb34
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/TestTaskRunner.java
@@ -0,0 +1,131 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.engine;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.processor.TaskProcessor;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor;
+import org.apache.oodt.cas.workflow.engine.runner.AsynchronousLocalEngineRunner;
+import org.apache.oodt.cas.workflow.engine.runner.EngineRunner;
+import org.apache.oodt.cas.workflow.structs.FILOPrioritySorter;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Exercises the {@link TaskRunner}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestTaskRunner extends TestCase {
+
+  private File testDir;
+
+  private EngineRunner runner;
+
+  private TaskRunner taskRunner;
+
+  private TaskQuerier querier;
+
+  public void testExecuteTasks() {
+    FILOPrioritySorter prioritizer = new FILOPrioritySorter();
+    MockProcessorQueue processorQueue = new MockProcessorQueue();
+    querier = new MetSetterTaskQuerier(processorQueue, prioritizer);
+    Thread querierThread = new Thread(querier);
+    querierThread.start();
+    while (querier.getRunnableProcessors().size() != 2) {
+      assertNotNull(querier.getRunnableProcessors());
+    }
+    List<WorkflowProcessor> runnables = querier.getRunnableProcessors();
+    assertNotNull(runnables);
+    assertEquals(2, runnables.size());
+    runner = new AsynchronousLocalEngineRunner();
+    taskRunner = new TaskRunner(querier, runner);
+    assertNotNull(taskRunner);
+    Thread runnerThread = new Thread(taskRunner);
+    WorkflowTask task = taskRunner
+        .extractTaskFromProcessor((TaskProcessor) runnables.get(0));
+    assertNotNull(task);
+    testDir = new File(task.getTaskConfig().getProperty("TestDirPath"));
+    assertNotNull(testDir);
+    runnerThread.start();
+
+    while (!testDir.exists()
+        || (testDir.exists() && testDir.listFiles().length != 2)) {
+    }
+
+    querier.setRunning(false);
+    runnerThread.interrupt();
+
+    // get the test dir path
+    assertTrue(testDir.exists());
+    assertNotNull(testDir.listFiles());
+    assertEquals(2, testDir.listFiles().length);
+    taskRunner.setRunning(false);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#setUp()
+   */
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#tearDown()
+   */
+  @Override
+  protected void tearDown() throws Exception {
+    // blow away test file
+    deleteAllFiles(testDir.getAbsolutePath());
+    testDir.delete();
+    testDir = null;
+    this.runner = null;
+    this.querier = null;
+    this.taskRunner = null;
+  }
+
+  private void deleteAllFiles(String startDir) {
+    File startDirFile = new File(startDir);
+    File[] delFiles = startDirFile.listFiles();
+
+    if (delFiles != null && delFiles.length > 0) {
+      for (int i = 0; i < delFiles.length; i++) {
+        delFiles[i].delete();
+      }
+    }
+
+    startDirFile.delete();
+
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/TestThreadPoolWorkflowEngine.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/TestThreadPoolWorkflowEngine.java
new file mode 100644
index 0000000..8b81cfc
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/engine/TestThreadPoolWorkflowEngine.java
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.engine;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.Graph;
+import org.apache.oodt.cas.workflow.structs.ParentChildWorkflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.commons.util.DateConvert;
+
+//JDK imports
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test suite for the ThreadPoolWorkflowEngine.
+ * </p>.
+ */
+public class TestThreadPoolWorkflowEngine extends TestCase {
+
+    public TestThreadPoolWorkflowEngine() {
+        // suppress WARNING level and below because we don't want
+        // the warning message where we test if start date time is AFTER
+        // end date time below
+        LogManager.getLogManager().getLogger("").setLevel(Level.SEVERE);
+    }
+
+    public void testCurrentTaskWallClockTime() {
+        // at first, there is no start date time
+        WorkflowInstance inst = new WorkflowInstance();
+        WorkflowTask task = new WorkflowTask();
+        task.setTaskId("urn:oodt:testTask");
+        ParentChildWorkflow workflow = new ParentChildWorkflow(new Graph());
+        workflow.getTasks().add(task);
+        inst.setParentChildWorkflow(workflow);
+        inst.setCurrentTaskId("urn:oodt:testTask");
+        assertEquals(Double.valueOf(0.0), Double
+                .valueOf(ThreadPoolWorkflowEngine
+                        .getCurrentTaskWallClockMinutes(inst)));
+
+        // now set start date time, and assert that wall clock minutes > 0
+        inst.setCurrentTaskStartDateTimeIsoStr(DateConvert
+                .isoFormat(new Date()));
+        System.out.println(ThreadPoolWorkflowEngine.getCurrentTaskWallClockMinutes(inst));
+        assertTrue(ThreadPoolWorkflowEngine
+                .getCurrentTaskWallClockMinutes(inst) > 0.0);
+
+        // set end date time to "" and make sure wall clock mins still greater
+        // than 0
+        inst.setCurrentTaskEndDateTimeIsoStr("");
+        assertTrue(ThreadPoolWorkflowEngine
+                .getCurrentTaskWallClockMinutes(inst) > 0.0);
+
+        // set the end date time, compute it, and make sure it stays the same
+        String endDateTimeIsoStr = DateConvert.isoFormat(new Date());
+        inst.setCurrentTaskEndDateTimeIsoStr(endDateTimeIsoStr);
+        double wallClockMins = ThreadPoolWorkflowEngine
+                .getCurrentTaskWallClockMinutes(inst);
+        assertEquals(Double.valueOf(wallClockMins), Double
+                .valueOf(ThreadPoolWorkflowEngine
+                        .getCurrentTaskWallClockMinutes(inst)));
+        assertEquals(Double.valueOf(wallClockMins), Double
+                .valueOf(ThreadPoolWorkflowEngine
+                        .getCurrentTaskWallClockMinutes(inst)));
+
+        // set the start date time after the end date time
+        // make sure that the wall cock time is 0.0
+        inst.setCurrentTaskStartDateTimeIsoStr(DateConvert
+                .isoFormat(new Date()));
+        assertEquals(Double.valueOf(0.0), Double
+                .valueOf(ThreadPoolWorkflowEngine
+                        .getCurrentTaskWallClockMinutes(inst)));
+
+    }
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/examples/TestExternScriptTaskInstance.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/examples/TestExternScriptTaskInstance.java
new file mode 100644
index 0000000..95d0365
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/examples/TestExternScriptTaskInstance.java
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.examples;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.exceptions.RepositoryException;
+
+//JDK imports
+import java.io.File;
+import junit.framework.TestCase;
+import java.io.IOException;
+
+//APACHE imports
+import org.apache.commons.io.FileUtils;
+
+/**
+ * @author davoodi
+ * @version $Revision$
+ * @since OODT-226
+ * 
+ * <p>
+ * Unit test for running an external script as a task instance.
+ * </p>.
+ */
+public class TestExternScriptTaskInstance extends TestCase {
+
+    private static final String testScriptPath = new File(
+            "./src/test/resources/myScript.sh").getAbsolutePath();
+
+    private ExternScriptTaskInstance myIns;
+
+    private Metadata myMet;
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>
+     */
+    public TestExternScriptTaskInstance() {
+        myIns = new ExternScriptTaskInstance();
+    }
+
+    public void testExternsalScript() throws RepositoryException {
+
+        myMet = new Metadata();
+        myMet.addMetadata("Args", "Faranak");
+        myMet.addMetadata("Args", "Davoodi");
+        assertNotNull(myMet);
+        WorkflowTaskConfiguration myConfig = new WorkflowTaskConfiguration();
+        myConfig.addConfigProperty("PathToScript", testScriptPath);
+        myConfig.addConfigProperty("ShellType", "/bin/bash");
+        assertNotNull(myConfig);
+        myIns.run(myMet, myConfig);
+        String outputFileStr = null;
+        try {
+            outputFileStr = FileUtils.readFileToString(new File(
+                    "./src/test/resources/myScript-Output.txt"), outputFileStr);
+            String expectedStr = "Hi my first name is Faranak and my last name is Davoodi.";
+            assertEquals(expectedStr.trim(), outputFileStr.trim());
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+    }
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/examples/TestFilterTask.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/examples/TestFilterTask.java
new file mode 100644
index 0000000..09d08a9
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/examples/TestFilterTask.java
@@ -0,0 +1,172 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.examples;
+
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.exceptions.WorkflowTaskInstanceException;
+
+import junit.framework.TestCase;
+
+/**
+ * Test harness for FilterTask.
+ * 
+ */
+public class TestFilterTask extends TestCase {
+
+	private FilterTask task;
+	private Metadata dynMet;
+	private WorkflowTaskConfiguration config;
+	private static final String prodDateTime = "2014-04-07T00:00:00.000Z";
+	private static final String filename = "foo.txt";
+	private static final String fileLocation = "/tmp/somedir";
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see junit.framework.TestCase#setUp()
+	 */
+	@Override
+	protected void setUp() throws Exception {
+		super.setUp();
+		task = new FilterTask();
+		dynMet = new Metadata();
+		dynMet.addMetadata("Filename", filename);
+		dynMet.addMetadata("ProductionDateTime", prodDateTime);
+		config = new WorkflowTaskConfiguration();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see junit.framework.TestCase#tearDown()
+	 */
+	@Override
+	protected void tearDown() throws Exception {
+		super.tearDown();
+		task = null;
+		dynMet = null;
+		config = null;
+	}
+
+	public void testRemove() {
+		config.addConfigProperty("Remove_Key", "Filename");
+		try {
+			task.run(dynMet, config);
+		} catch (WorkflowTaskInstanceException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+		assertNotNull(dynMet);
+		assertFalse(dynMet.containsKey("Filename"));
+	}
+
+	public void testRename() {
+		config.addConfigProperty("Rename_ProductionDateTime",
+				"Prior_ProductionDateTime");
+		try {
+			task.run(dynMet, config);
+		} catch (WorkflowTaskInstanceException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+		assertNotNull(dynMet);
+		assertFalse(dynMet.containsKey("ProductionDateTime"));
+		assertTrue(dynMet.containsKey("Prior_ProductionDateTime"));
+		assertEquals(
+				"Value: [" + dynMet.getMetadata("Prior_ProductionDateTime")
+						+ "] was not equal to: [" + prodDateTime + "]",
+				prodDateTime, dynMet.getMetadata("Prior_ProductionDateTime"));
+	}
+
+	public void testRemoveAfterRename() {
+		config.addConfigProperty("Rename_Filename", "FooName");
+		config.addConfigProperty("Remove_Key", "FooName");
+		try {
+			task.run(dynMet, config);
+		} catch (WorkflowTaskInstanceException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+		assertNotNull(dynMet);
+		assertFalse(dynMet.containsKey("Filename"));
+		assertFalse(dynMet.containsKey("FooName"));
+	}
+
+	public void testRemoveMultipleKeys() {
+		config.addConfigProperty("Remove_Key", "Filename, ProductionDateTime");
+		try {
+			task.run(dynMet, config);
+		} catch (WorkflowTaskInstanceException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+		assertNotNull(dynMet);
+		assertFalse(dynMet.containsKey("Filename"));
+		assertFalse(dynMet.containsKey("ProductionDateTime"));
+
+	}
+
+	public void testRemoveKeyThatDoesNotExist() {
+		config.addConfigProperty("Remove_Key", "FileLocation");
+		try {
+			task.run(dynMet, config);
+		} catch (WorkflowTaskInstanceException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+		assertNotNull(dynMet);
+		assertFalse(dynMet.containsKey("FileLocation"));
+	}
+
+	public void testRenameKeyThatDoesNotExist() {
+		config.addConfigProperty("Rename_FileLocation", "FooLocation");
+		try {
+			task.run(dynMet, config);
+		} catch (WorkflowTaskInstanceException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+		assertNotNull(dynMet);
+		assertFalse(dynMet.containsKey("FileLocation"));
+		assertFalse(dynMet.containsKey("FooLocation"));
+	}
+
+	public void testRenameToKeyWithExistingValues() {
+		dynMet.addMetadata("Prior_FileLocation", fileLocation);
+		dynMet.addMetadata("FileLocation", fileLocation + "/someotherdir");
+		config.addConfigProperty("Rename_FileLocation", "Prior_FileLocation");
+		try {
+			task.run(dynMet, config);
+		} catch (WorkflowTaskInstanceException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+		assertNotNull(dynMet);
+		assertFalse(dynMet.containsKey("FileLocation"));
+		assertTrue(dynMet.containsKey("Prior_FileLocation"));
+		assertEquals("Expected: [1] value, actual was : ["
+				+ dynMet.getAllMetadata("Prior_FileLocation").size() + "]", 1,
+				dynMet.getAllMetadata("Prior_FileLocation").size());
+		assertEquals("Expected: [" + fileLocation + "/someotherdir"
+				+ "]: got: [" + dynMet.getMetadata("Prior_FileLocation") + "]",
+				fileLocation + "/someotherdir",
+				dynMet.getMetadata("Prior_FileLocation"));
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/instrepo/TestLuceneWorkflowInstanceRepository.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/instrepo/TestLuceneWorkflowInstanceRepository.java
new file mode 100644
index 0000000..f9d27c4
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/instrepo/TestLuceneWorkflowInstanceRepository.java
@@ -0,0 +1,250 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.instrepo;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowStatus;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+//Apache Imports
+import org.apache.commons.io.FileUtils;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * @since OODT-55
+ * 
+ * <p>
+ * Test Case for the {@link LuceneWorkflowInstaceRepository}
+ * </p>.
+ */
+public class TestLuceneWorkflowInstanceRepository extends TestCase implements
+        WorkflowStatus {
+
+    private LuceneWorkflowInstanceRepository repo = null;
+
+    private WorkflowInstance testInst = null;
+
+    private Workflow testWkflw;
+
+    private WorkflowTask testTask;
+
+    private WorkflowCondition testCond;
+    
+    private String tmpDirPath = null;
+
+    public TestLuceneWorkflowInstanceRepository() {
+        testInst = new WorkflowInstance();
+        testWkflw = new Workflow();
+        testTask = new WorkflowTask();
+        testCond = new WorkflowCondition();
+        testWkflw.setName("test.workflow");
+        testWkflw.setId("test.id");
+        List tasks = new Vector();
+        List conds = new Vector();
+
+        testCond.setConditionId("test.cond.id");
+        testCond.setConditionInstanceClassName("test.class");
+        testCond.setConditionName("test.cond.name");
+        testCond.setOrder(1);
+        conds.add(testCond);
+
+        testTask.setTaskConfig(new WorkflowTaskConfiguration());
+        testTask.setTaskId("test.task.id");
+        testTask.setConditions(conds);
+        testTask.setOrder(1);
+        testTask.setTaskInstanceClassName("test.class");
+        testTask.setTaskName("test.task.name");
+        tasks.add(testTask);
+        testWkflw.setTasks(tasks);
+
+        testInst = new WorkflowInstance();
+        testInst.setCurrentTaskId("test.task");
+        testInst.setStatus(STARTED);
+        testInst.setWorkflow(testWkflw);
+
+        Metadata sharedContext = new Metadata();
+        sharedContext.addMetadata("TestKey1", "TestVal1");
+        sharedContext.addMetadata("TestKey1", "TestVal2");
+        sharedContext.addMetadata("TestKey2", "TestVal3");
+        testInst.setSharedContext(sharedContext);
+    
+        // first load the example configuration
+        try {
+            System.getProperties().load(
+                    new FileInputStream("./src/main/resources/workflow.properties"));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // get a temp directory
+
+        File tempDir = null;
+        File tempFile = null;
+
+        try {
+            tempFile = File.createTempFile("foo", "bar");
+            tempFile.deleteOnExit();
+            tempDir = tempFile.getParentFile();
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        tmpDirPath = tempDir.getAbsolutePath();
+        if (!tmpDirPath.endsWith("/")) {
+            tmpDirPath += "/";
+        }
+
+        tmpDirPath += "testInstRepo/";
+
+        // now override the catalog ones
+        System.setProperty(
+                "org.apache.oodt.cas.workflow.instanceRep.lucene.idxPath",
+                tmpDirPath);
+
+        System.setProperty(
+                "org.apache.oodt.cas.workflow.instanceRep.pageSize", "20");
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        repo = (LuceneWorkflowInstanceRepository) new LuceneWorkflowInstanceRepositoryFactory().createInstanceRepository();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        // now remove the temporary directory used
+        if (tmpDirPath != null) {
+            FileUtils.forceDelete(new File(tmpDirPath));
+        }
+        if (repo != null) {
+            repo = null;
+        }
+
+    }
+    
+    /**
+    * @since OODT-389
+    **/
+    public void testInstanceRepoInitialization() {
+        // Getting the number of workflow instances should not fail even on an empty index
+        try {
+            int count = repo.getNumWorkflowInstances();
+            // There should be no instances in the index at this point
+            assertEquals(0, count);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+    public void testUpdateDocumentAndPreserveId() {
+        try {
+            repo.addWorkflowInstance(testInst);
+        } catch (InstanceRepositoryException e) {
+            fail(e.getMessage());
+        }
+       
+        // preserve its id
+        String wInstId = testInst.getId();
+
+        // modify it
+        try {
+            repo.updateWorkflowInstance(testInst);
+        } catch (InstanceRepositoryException e) {
+            fail(e.getMessage());
+        }
+
+        // make sure that the new id is the same
+        assertEquals(wInstId, testInst.getId());
+
+        // make sure that there is only 1 workflow instance
+        List wInsts = null;
+        try {
+            wInsts = repo.getWorkflowInstances();
+        } catch (InstanceRepositoryException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(wInsts);
+        assertEquals(1, wInsts.size());
+
+        // make sure that we can look up that workflow inst by its id
+        WorkflowInstance foundInst = null;
+        try {
+            foundInst = repo.getWorkflowInstanceById(wInstId);
+        } catch (InstanceRepositoryException e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(foundInst);
+        assertEquals(foundInst.getId(), wInstId);
+        assertNotNull(foundInst.getSharedContext());
+        assertNotNull(foundInst.getSharedContext().getHashtable());
+        assertEquals(2, foundInst.getSharedContext().getHashtable().keySet()
+                .size());
+        assertNotNull(foundInst.getSharedContext().getAllMetadata("TestKey1"));
+        assertEquals(2, foundInst.getSharedContext().getAllMetadata("TestKey1")
+                .size());
+
+        boolean gotVal1 = false, gotVal2 = false;
+
+        for (Iterator i = foundInst.getSharedContext().getAllMetadata(
+                "TestKey1").iterator(); i.hasNext();) {
+            String val = (String) i.next();
+            if (val.equals("TestVal1")) {
+                gotVal1 = true;
+            } else if (val.equals("TestVal2")) {
+                gotVal2 = true;
+            }
+        }
+
+        assert (gotVal1 && gotVal2);
+
+        assertNotNull(foundInst.getSharedContext().getMetadata("TestKey2"));
+        assertEquals("TestVal3", foundInst.getSharedContext().getMetadata(
+                "TestKey2"));
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/lifecycle/TestWorkflowLifecycleManager.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/lifecycle/TestWorkflowLifecycleManager.java
new file mode 100644
index 0000000..cf7062d
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/lifecycle/TestWorkflowLifecycleManager.java
@@ -0,0 +1,154 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.lifecycle;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+
+import org.apache.oodt.cas.workflow.structs.Graph;
+import org.apache.oodt.cas.workflow.structs.ParentChildWorkflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test harness for {@link WorkflowLifecycleManager}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestWorkflowLifecycleManager extends TestCase {
+
+  private WorkflowLifecycleManager lifecycle;
+
+  public void testPctCompleteWengineStages(){
+    ParentChildWorkflow workflow = new ParentChildWorkflow(new Graph());
+    WorkflowState successState = lifecycle.getDefaultLifecycle().createState("Success", "done", "All done.");
+    WorkflowInstance instance = new WorkflowInstance();
+    instance.setState(successState);
+    instance.setParentChildWorkflow(workflow);
+    double pct = lifecycle.getPercentageComplete(instance);
+    assertNotNull(pct);
+    assertEquals(1.0, pct);
+  }
+  
+  public void testPctCompleteWorkflow1Stages() throws InstantiationException{
+    this.lifecycle = new WorkflowLifecycleManager("./src/main/resources"
+        + "/examples/workflow-lifecycle.xml");
+    assertNotNull(this.lifecycle);
+    assertNotNull(this.lifecycle.getDefaultLifecycle());
+    assertNotNull(this.lifecycle.getDefaultLifecycle().getStages());
+    ParentChildWorkflow workflow = new ParentChildWorkflow(new Graph());
+    WorkflowState successState = lifecycle.getDefaultLifecycle().createState("FINISHED", "done", "All done.");
+    WorkflowInstance instance = new WorkflowInstance();
+    instance.setState(successState);
+    instance.setParentChildWorkflow(workflow);
+    double pct = lifecycle.getPercentageComplete(instance);
+    assertNotNull(pct);
+    assertEquals(1.0, pct);
+    
+    
+  }
+  
+  
+  public void testStages() {
+    assertNotNull(this.lifecycle.getDefaultLifecycle());
+    assertNotNull(this.lifecycle.getDefaultLifecycle().getStages());
+    assertEquals(this.lifecycle.getDefaultLifecycle().getStages().size(), 7);
+  }
+
+  public void testReadNewStateFormat() {
+    assertNotNull(this.lifecycle.getDefaultLifecycle());
+    assertNotNull(this.lifecycle.getDefaultLifecycle().getStages());
+    boolean gotNull = false, gotLoaded = false;
+    WorkflowLifecycleStage category = this.lifecycle.getDefaultLifecycle()
+        .getCategoryByName("initial");
+    assertNotNull(category);
+    assertEquals("initial", category.getName());
+    for (WorkflowState state : (List<WorkflowState>) category.getStates()) {
+      if (state.getName().equals("Null")) {
+        gotNull = true;
+        assertEquals(state.getDescription(), "Uninitialized State");
+      }
+
+      if (state.getName().equals("Loaded")) {
+        gotLoaded = true;
+        assertEquals(state.getDescription(), "Loading Complete");
+      }
+    }
+
+    assertTrue(gotNull && gotLoaded);
+  }
+
+  public void testReadOldStateFormat() throws InstantiationException {
+    this.lifecycle = new WorkflowLifecycleManager("./src/main/resources"
+        + "/examples/workflow-lifecycle.xml");
+    assertNotNull(this.lifecycle);
+    assertNotNull(this.lifecycle.getDefaultLifecycle());
+    assertNotNull(this.lifecycle.getDefaultLifecycle().getStages());
+    assertEquals(this.lifecycle.getDefaultLifecycle().getStages().size(), 5);
+    assertNotNull(this.lifecycle.getDefaultLifecycle().getCategoryByName(
+        "workflow_start"));
+    assertNotNull(this.lifecycle.getDefaultLifecycle()
+        .getCategoryByName("workflow_start").getStates());
+    assertEquals(
+        this.lifecycle.getDefaultLifecycle()
+            .getCategoryByName("workflow_start").getStates().size(), 2);
+    boolean gotRsubmit = false, gotStarted = false;
+
+    for (WorkflowState state : this.lifecycle.getDefaultLifecycle()
+        .getCategoryByName("workflow_start").getStates()) {
+      if (state.getName().equals("RSUBMIT")) {
+        gotRsubmit = true;
+      }
+
+      if (state.getName().equals("STARTED")) {
+        gotStarted = true;
+      }
+    }
+
+    assertTrue(gotRsubmit && gotStarted);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#setUp()
+   */
+  @Override
+  protected void setUp() throws Exception {
+    this.lifecycle = new WorkflowLifecycleManager(
+        new File("./src/main/resources/examples/wengine/wengine-lifecycle.xml")
+            .getAbsolutePath());
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#tearDown()
+   */
+  @Override
+  protected void tearDown() throws Exception {
+    this.lifecycle = null;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/repository/MockWorkflowRepository.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/repository/MockWorkflowRepository.java
new file mode 100644
index 0000000..7d8bea5
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/repository/MockWorkflowRepository.java
@@ -0,0 +1,350 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.repository;
+
+//JDK imports
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+//OODT imports
+import org.apache.commons.lang.Validate;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionConfiguration;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.exceptions.RepositoryException;
+
+//Google imports
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * A mock {@link WorkflowRepository}.
+ *
+ * @author bfoster (Brian Foster)
+ * @author mattmann (Chris Mattmann)
+ */
+public class MockWorkflowRepository implements WorkflowRepository {
+
+   private Map<String, List<Workflow>> eventToWorkflowsMap;
+   private Map<String, Workflow> workflows;
+   private Map<String, WorkflowTask> tasks;
+   private Map<String, WorkflowCondition> conditions;
+
+   public final static String EVENT1_NAME = "Event1_Name";
+   public final static String EVENT2_NAME = "Event2_Name";
+
+   public final static String WORKFLOW1_ID = "Workflow1_Id";
+   public final static String WORKFLOW2_ID = "Workflow2_Id";
+   public final static String WORKFLOW3_ID = "Workflow3_Id";
+
+   public final static String WORKFLOW1_NAME = "Workflow1_Name";
+   public final static String WORKFLOW2_NAME = "Workflow2_Name";
+   public final static String WORKFLOW3_NAME = "Workflow3_Name";
+
+   public final static String TASK1_ID = "Task1_Id";
+   public final static String TASK2_ID = "Task2_Id";
+   public final static String TASK3_ID = "Task3_Id";
+   public final static String TASK4_ID = "Task4_Id";
+
+   public final static String TASK1_NAME = "Task1_Name";
+   public final static String TASK2_NAME = "Task2_Name";
+   public final static String TASK3_NAME = "Task3_Name";
+   public final static String TASK4_NAME = "Task4_Name";   
+
+   public final static String CONDITION1_ID = "Condition1_Id";
+   public final static String CONDITION2_ID = "Condition2_Id";
+   public final static String CONDITION3_ID = "Condition3_Id";
+   public final static String CONDITION4_ID = "Condition4_Id"; 
+
+   public final static String CONDITION1_NAME = "Condition1_Name";
+   public final static String CONDITION2_NAME = "Condition2_Name";
+   public final static String CONDITION3_NAME = "Condition3_Name";
+   public final static String CONDITION4_NAME = "Condition4_Name"; 
+
+   public final static WorkflowTaskConfiguration tConf = new WorkflowTaskConfiguration();
+   public final static WorkflowConditionConfiguration cConf = new WorkflowConditionConfiguration();
+
+   public MockWorkflowRepository() {
+      eventToWorkflowsMap = Maps.newHashMap();
+      workflows = Maps.newHashMap();
+      tasks = Maps.newHashMap();
+      conditions = Maps.newHashMap();
+
+      WorkflowCondition condition1 = new WorkflowCondition();
+      condition1.setConditionId(CONDITION1_ID);
+      condition1.setConditionName(CONDITION1_NAME);
+      condition1.setConditionInstanceClassName("some.class.path");
+      condition1.setCondConfig(cConf);
+      conditions.put(condition1.getConditionId(), condition1);
+
+      WorkflowCondition condition2 = new WorkflowCondition();
+      condition2.setConditionId(CONDITION2_ID);
+      condition2.setConditionName(CONDITION2_NAME);
+      condition2.setCondConfig(cConf);
+      condition2.setConditionInstanceClassName("some.class.path");
+      conditions.put(condition2.getConditionId(), condition2);
+
+      WorkflowCondition condition3 = new WorkflowCondition();
+      condition3.setConditionId(CONDITION3_ID);
+      condition3.setConditionName(CONDITION3_NAME);
+      condition3.setCondConfig(cConf);
+      condition3.setConditionInstanceClassName("some.class.path");
+      conditions.put(condition3.getConditionId(), condition3);
+
+      WorkflowCondition condition4 = new WorkflowCondition();
+      condition4.setConditionId(CONDITION4_ID);
+      condition4.setConditionName(CONDITION4_NAME);
+      condition4.setCondConfig(cConf);
+      condition4.setConditionInstanceClassName("some.class.path");
+      conditions.put(condition4.getConditionId(), condition4);
+
+      WorkflowTask task1 = new WorkflowTask();
+      task1.setTaskId(TASK1_ID);
+      task1.setTaskName(TASK1_NAME);
+      task1.setTaskConfig(tConf);
+      task1.setConditions(Lists.newArrayList(condition1, condition2));
+      tasks.put(task1.getTaskId(), task1);
+
+      WorkflowTask task2 = new WorkflowTask();
+      task2.setTaskId(TASK2_ID);
+      task2.setTaskName(TASK2_NAME);
+      task2.setTaskConfig(tConf);
+      task2.setConditions(Lists.newArrayList());
+      tasks.put(task2.getTaskId(), task2);
+
+      WorkflowTask task3 = new WorkflowTask();
+      task3.setTaskId(TASK3_ID);
+      task3.setTaskName(TASK3_NAME);
+      task3.setTaskConfig(tConf);
+      task3.setConditions(Lists.newArrayList());
+      tasks.put(task3.getTaskId(), task3);
+
+      WorkflowTask task4 = new WorkflowTask();
+      task4.setTaskId(TASK4_ID);
+      task4.setTaskName(TASK4_NAME);
+      task4.setTaskConfig(tConf);
+      task4.setConditions(Lists.newArrayList(condition4));
+      tasks.put(task4.getTaskId(), task4);
+
+      Workflow workflow1 = new Workflow();
+      workflow1.setId(WORKFLOW1_ID);
+      workflow1.setName(WORKFLOW1_NAME);
+      workflow1.setTasks(Lists.newArrayList(task1, task2));
+      workflow1.setConditions(Lists.newArrayList(condition1));
+      workflows.put(workflow1.getId(), workflow1);
+
+      Workflow workflow2 = new Workflow();
+      workflow2.setId(WORKFLOW2_ID);
+      workflow2.setName(WORKFLOW2_NAME);
+      workflow2.setTasks(Lists.newArrayList(task1, task2, task4));
+      workflow2.setConditions(Lists.newArrayList(condition1, condition4));
+      workflows.put(workflow2.getId(), workflow2);
+
+      Workflow workflow3 = new Workflow();
+      workflow3.setId(WORKFLOW3_ID);
+      workflow3.setName(WORKFLOW3_NAME);
+      workflow3.setTasks(Lists.newArrayList(task3));
+      workflow3.setConditions(new ArrayList<WorkflowCondition>());
+      workflows.put(workflow3.getId(), workflow3);
+
+      eventToWorkflowsMap.put(EVENT1_NAME, Lists.newArrayList(workflow1));
+      eventToWorkflowsMap.put(EVENT2_NAME, Lists.newArrayList(workflow1,
+            workflow2));
+   }
+
+   @Override
+   public Workflow getWorkflowByName(String workflowName)
+         throws RepositoryException {
+      Validate.notNull(workflowName);
+
+      for (Workflow workflow : workflows.values()) {
+         if (workflow.getName().equals(workflowName)) {
+            return workflow;
+         }
+      }
+      return null;
+   }
+
+   @Override
+   public Workflow getWorkflowById(String workflowId)
+         throws RepositoryException {
+      Validate.notNull(workflowId);
+
+      return workflows.get(workflowId);
+   }
+
+   @Override
+   public List<Workflow> getWorkflows() throws RepositoryException {
+      return Lists.newArrayList(workflows.values());
+   }
+
+   @Override
+   public List<WorkflowTask> getTasksByWorkflowId(String workflowId)
+         throws RepositoryException {
+      Workflow workflow = getWorkflowById(workflowId);
+      List<WorkflowTask> tasks = Lists.newArrayList();
+      if (workflow != null) {
+         tasks.addAll(workflow.getTasks());
+      }
+      return tasks;
+   }
+
+   @Override
+   public List<WorkflowTask> getTasksByWorkflowName(String workflowName)
+         throws RepositoryException {
+      List<WorkflowTask> tasks = Lists.newArrayList();
+      Workflow workflow = getWorkflowByName(workflowName);
+      if (workflow != null) {
+         tasks.addAll(workflow.getTasks());
+      }
+      return tasks;
+   }
+
+   @Override
+   public List<Workflow> getWorkflowsForEvent(String eventName)
+         throws RepositoryException {
+      Validate.notNull(eventName);
+
+      List<Workflow> workflows = eventToWorkflowsMap.get(eventName);
+      if (workflows == null) {
+         return Lists.newArrayList();
+      }
+      return workflows;
+   }
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public List<WorkflowCondition> getConditionsByTaskName(String taskName)
+         throws RepositoryException {
+      List<WorkflowCondition> conditions = Lists.newArrayList();
+      WorkflowTask task = getWorkflowTaskByName(taskName);
+      if (task != null) {
+         conditions.addAll(task.getConditions()); 
+      }
+      return conditions;
+   }
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public List<WorkflowCondition> getConditionsByTaskId(String taskId)
+         throws RepositoryException {
+      List<WorkflowCondition> conditions = Lists.newArrayList();
+      WorkflowTask task = getWorkflowTaskById(taskId);
+      if (task != null) {
+         conditions.addAll(Lists.newArrayList(task.getConditions()));
+      }
+      return conditions;
+   }
+
+   @Override
+   public WorkflowTaskConfiguration getConfigurationByTaskId(String taskId)
+         throws RepositoryException {
+      WorkflowTask task = getWorkflowTaskById(taskId);
+      if (task != null) {
+         return task.getTaskConfig();
+      }
+      return null;
+   }
+
+   @Override
+   public WorkflowTask getWorkflowTaskById(String taskId)
+         throws RepositoryException {
+      Validate.notNull(taskId);
+
+      return tasks.get(taskId);
+   }
+
+   public WorkflowTask getWorkflowTaskByName(String taskName)
+         throws RepositoryException {
+      Validate.notNull(taskName);
+
+      for (WorkflowTask task : tasks.values()) {
+         if (task.getTaskName().equals(taskName)) {
+            return task;
+         }
+      }
+      return null;
+   }
+
+   @Override
+   public WorkflowCondition getWorkflowConditionById(String conditionId)
+         throws RepositoryException {
+      Validate.notNull(conditionId);
+
+      return conditions.get(conditionId);
+   }
+
+   @Override
+   public List<String> getRegisteredEvents() throws RepositoryException {
+      return Lists.newArrayList(eventToWorkflowsMap.keySet());
+   }
+
+   @Override
+   public String addWorkflow(Workflow workflow) throws RepositoryException {
+      workflows.put(workflow.getId(), workflow);
+      return workflow.getId();
+   }
+
+   @Override
+   public List<WorkflowCondition> getConditionsByWorkflowId(String workflowId)
+         throws RepositoryException {
+      List<WorkflowCondition> conditions = Lists.newArrayList();
+      Workflow workflow = getWorkflowById(workflowId);
+      if (workflow != null) {
+         conditions.addAll(workflow.getConditions());
+      }
+      return conditions;
+   }
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#addTask(org.apache.oodt.cas.workflow.structs.WorkflowTask)
+   */
+  @Override
+  public String addTask(WorkflowTask task) throws RepositoryException {
+    // check its conditions
+    if(task.getPreConditions() != null && task.getPreConditions().size() > 0){
+      for(WorkflowCondition cond: task.getPreConditions()){
+        if(!this.conditions.containsKey(cond.getConditionId())){
+          throw new RepositoryException("Reference in new task: ["+task.getTaskName()+"] to undefined pre condition ith id: ["+cond.getConditionId()+"]");            
+        }          
+      }
+      
+      for(WorkflowCondition cond: task.getPostConditions()){
+        if(!this.conditions.containsKey(cond.getConditionId())){
+          throw new RepositoryException("Reference in new task: ["+task.getTaskName()+"] to undefined post condition ith id: ["+cond.getConditionId()+"]");            
+        }              
+      }
+    }
+    
+    String taskId = task.getTaskId() != null ? 
+        task.getTaskId():UUID.randomUUID().toString();
+   this.tasks.put(taskId, task);
+   return taskId;    
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.oodt.cas.workflow.repository.WorkflowRepository#getTaskById(java.lang.String)
+   */
+  @Override
+  public WorkflowTask getTaskById(String taskId) throws RepositoryException {
+    return tasks.get(taskId);
+  }
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/repository/TestPackagedWorkflowRepository.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/repository/TestPackagedWorkflowRepository.java
new file mode 100644
index 0000000..2fc900f
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/repository/TestPackagedWorkflowRepository.java
@@ -0,0 +1,173 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.repository;
+
+//JDK imports
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test harness for the {@link PackagedWorkflowRepository}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestPackagedWorkflowRepository extends TestCase {
+
+  private PackagedWorkflowRepository repo;
+
+  public TestPackagedWorkflowRepository() {
+  }
+  
+  /**
+   * @since OODT-205
+   */
+  public void testWorkflowConditions(){
+    Workflow w = null;
+    try{
+      w = this.repo.getWorkflowById("urn:npp:GranuleMaps");
+    }
+    catch(Exception e){
+      fail(e.getMessage());
+    }
+    
+    assertNotNull(w);
+    assertNotNull(w.getConditions());
+    System.out.println("NUM CONDITIONS: "+w.getConditions().size());
+    assertTrue(w.getConditions().size() > 0);
+    assertEquals(w.getConditions().size(), 3);
+  }
+
+  public void testDetectOuterLevelWorkflows() {
+    assertNotNull(this.repo);
+    List<Workflow> workflows = null;
+    try {
+      workflows = this.repo.getWorkflows();
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    boolean foundGranuleMaps = false;
+    for (Workflow w : workflows) {
+      if (w.getId().equals("urn:npp:GranuleMaps")) {
+        foundGranuleMaps = true;
+      }
+    }
+
+    assertTrue(foundGranuleMaps);
+  }
+
+  public void testDetectInnerWorkflows() {
+    assertNotNull(this.repo);
+    List<String> events = null;
+
+    try {
+      events = this.repo.getRegisteredEvents();
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    boolean foundFour = false, foundThree = false;
+    for (String event : events) {
+      List<Workflow> workflows = null;
+
+      try {
+        workflows = this.repo.getWorkflowsForEvent(event);
+      } catch (Exception e) {
+        fail(e.getMessage());
+      }
+
+      assertNotNull(workflows);
+      assertTrue(workflows.size() > 0);
+      if (workflows.size() == 3) {
+        foundThree = true;
+      } else if (workflows.size() == 4) {
+        foundFour = true;
+      }
+
+    }
+
+    assertTrue(foundThree);
+    assertTrue(foundFour);
+  }
+  
+  /**
+   * @since OODT-207
+   */
+  public void testGetConditionTimeout(){
+    WorkflowCondition cond = null;
+    try{
+      cond = this.repo.getWorkflowConditionById("urn:npp:MOA_IASI_L1C_Daily");
+    }
+    catch(Exception e){
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+    
+    assertNotNull(cond);
+    assertEquals(30L, cond.getTimeoutSeconds());
+  }
+  
+  /**
+   * @since OODT-208
+   */
+  public void testGetOptional(){
+    WorkflowCondition cond = null;
+    try{
+      cond = this.repo.getWorkflowConditionById("urn:npp:MOA_ORBITS_FileBased");
+    }
+    catch(Exception e){
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+    
+    assertNotNull(cond);
+    assertEquals(true, cond.isOptional());   
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#setUp()
+   */
+  @Override
+  protected void setUp() throws Exception {
+    repo = new PackagedWorkflowRepository(Collections.singletonList(new File(
+        "src/main/resources/examples/wengine/GranuleMaps.xml")));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#tearDown()
+   */
+  @Override
+  protected void tearDown() throws Exception {
+    repo = null;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/repository/TestWorkflowDataSourceRepository.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/repository/TestWorkflowDataSourceRepository.java
new file mode 100644
index 0000000..163d1ab
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/repository/TestWorkflowDataSourceRepository.java
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.repository;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.sql.SQLException;
+import javax.sql.DataSource;
+
+//OODT imports
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+import org.apache.oodt.commons.database.SqlScript;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionInstance;
+import org.apache.oodt.cas.workflow.structs.exceptions.RepositoryException;
+import org.apache.oodt.cas.workflow.util.GenericWorkflowObjectFactory;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Test suite for the {@link DataSourceCatalog} and
+ * {@link DataSourceCatalogFactory}.
+ * </p>.
+ */
+public class TestWorkflowDataSourceRepository extends TestCase {
+
+    private String tmpDirPath = null;
+
+    private DataSource ds;
+    
+    public TestWorkflowDataSourceRepository() throws SQLException, FileNotFoundException {
+        // set the log levels
+        System.setProperty("java.util.logging.config.file", new File(
+                "./src/main/resources/logging.properties").getAbsolutePath());
+
+        // first load the example configuration
+        try {
+            System.getProperties().load(
+                    new FileInputStream("./src/main/resources/workflow.properties"));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        // get a temp directory
+        File tempDir = null;
+        File tempFile = null;
+
+        try {
+            tempFile = File.createTempFile("foo", "bar");
+            tempFile.deleteOnExit();
+            tempDir = tempFile.getParentFile();
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+        
+        tmpDirPath = tempDir.getAbsolutePath();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        ds = DatabaseConnectionBuilder.buildDataSource("sa", "", "org.hsqldb.jdbcDriver", "jdbc:hsqldb:file:" + tmpDirPath + "/testCat;shutdown=true");
+        SqlScript coreSchemaScript = new SqlScript("src/test/resources/workflow.sql", ds);
+        coreSchemaScript.loadScript();
+        coreSchemaScript.execute();
+        ds.getConnection().commit();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        ds.getConnection().close();
+    }
+    
+    /**
+     * @since OODT-205
+     */
+    public void testWorkflowConditions(){
+      DataSourceWorkflowRepository repo = new DataSourceWorkflowRepository(ds);
+            
+      Workflow w = null;
+      try{
+        w = repo.getWorkflowById("1");
+      }
+      catch(Exception e){
+        fail(e.getMessage());
+      }
+      
+      assertNotNull(w);
+      assertNotNull(w.getConditions());
+      assertTrue(w.getConditions().size() > 0);
+      assertEquals(w.getConditions().size(), 1);
+    }
+    
+    
+    public void testDataSourceRepo() throws SQLException, RepositoryException {
+        DataSourceWorkflowRepository repo = new DataSourceWorkflowRepository(ds);
+        
+        //test id 1
+        WorkflowCondition wc = repo.getWorkflowConditionById("1");
+        assertEquals(wc.getConditionName(), "CheckCond");
+        WorkflowConditionInstance condInst = GenericWorkflowObjectFactory.getConditionObjectFromClassName(wc.getConditionInstanceClassName());
+        Metadata m = new Metadata();
+        m.addMetadata("Met1", "Val1");
+        m.addMetadata("Met2", "Val2");
+        m.addMetadata("Met3", "Val3");
+        assertTrue(condInst.evaluate(m, wc.getTaskConfig()));
+        
+        //test id 2
+        wc = repo.getWorkflowConditionById("2");
+        assertEquals(wc.getConditionName(), "FalseCond");
+        condInst = GenericWorkflowObjectFactory.getConditionObjectFromClassName(wc.getConditionInstanceClassName());
+        assertFalse(condInst.evaluate(m, wc.getTaskConfig()));
+        
+        //test id 3
+        wc = repo.getWorkflowConditionById("3");
+        assertEquals(wc.getConditionName(), "TrueCond");
+        condInst = GenericWorkflowObjectFactory.getConditionObjectFromClassName(wc.getConditionInstanceClassName());
+        assertTrue(condInst.evaluate(m, wc.getTaskConfig()));
+    }
+    
+}
+
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/repository/TestWorkflowRepository.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/repository/TestWorkflowRepository.java
new file mode 100644
index 0000000..6edd9e8
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/repository/TestWorkflowRepository.java
@@ -0,0 +1,392 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.repository;
+
+//Junit imports
+import junit.framework.TestCase;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.exceptions.RepositoryException;
+import org.apache.oodt.cas.workflow.util.GenericWorkflowObjectFactory;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * Unit tests for the Workflow Repository.
+ * </p>
+ * 
+ */
+public class TestWorkflowRepository extends TestCase {
+
+    private XMLWorkflowRepository workflowRepository = null;
+
+    private static List workflowDirUris = new Vector();
+
+    /**
+     * <p>
+     * Default Constructor
+     * </p>
+     */
+    public TestWorkflowRepository() {
+        workflowDirUris.add(new File("./src/main/resources/examples").toURI()
+                .toString());
+        workflowRepository = new XMLWorkflowRepository(workflowDirUris);
+    }
+    
+    /**
+     * @since OODT-205
+     */
+    public void testWorkflowConditions(){
+      Workflow w = null;
+      try{
+        w = this.workflowRepository.getWorkflowById("urn:oodt:conditionsWorkflow");
+      }
+      catch(Exception e){
+        fail(e.getMessage());
+      }
+      
+      assertNotNull(w);
+      assertNotNull(w.getConditions());
+      assertTrue(w.getConditions().size() > 0);
+      assertEquals(w.getConditions().size(), 1);
+    }    
+
+    public void testGetWorkflowByName() {
+        Workflow w = null;
+
+        try {
+            w = workflowRepository.getWorkflowByName("backwardsTestWorkflow");
+        } catch (RepositoryException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        validateBackwardsWorkflow(w);
+    }
+
+    public void testGetWorkflowById() {
+        Workflow w = null;
+
+        try {
+            w = workflowRepository
+                    .getWorkflowById("urn:oodt:backwardsTestWorkflow");
+        } catch (RepositoryException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        validateBackwardsWorkflow(w);
+    }
+
+    public void testGetWorkflows() {
+        List workflows = null;
+
+        try {
+            workflows = workflowRepository.getWorkflows();
+        } catch (RepositoryException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        assertNotNull(workflows);
+        assertEquals(11, workflows.size());
+    }
+
+    public void testGetWorkflowsForEvent() {
+        List workflows = null;
+
+        try {
+            workflows = workflowRepository.getWorkflowsForEvent("test");
+        } catch (RepositoryException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        assertNotNull(workflows);
+        assertEquals(1, workflows.size());
+
+        try {
+            workflows = workflowRepository.getWorkflowsForEvent("backwards");
+        } catch (RepositoryException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        assertNotNull(workflows);
+        assertEquals(1, workflows.size());
+        
+
+        try {
+            workflows = workflowRepository.getWorkflowsForEvent("externalScript");
+        } catch (RepositoryException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        assertNotNull(workflows);
+        assertEquals(1, workflows.size());
+    }
+
+    public void testGetTasksByWorkflowId() {
+        List tasks = null;
+
+        try {
+            tasks = workflowRepository
+                    .getTasksByWorkflowId("urn:oodt:backwardsTestWorkflow");
+        } catch (RepositoryException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        validateBackwardsWorkflowTasks(tasks);
+    }
+
+    public void testGetTasksByWorkflowName() {
+        List tasks = null;
+
+        try {
+            tasks = workflowRepository
+                    .getTasksByWorkflowName("backwardsTestWorkflow");
+        } catch (RepositoryException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        validateBackwardsWorkflowTasks(tasks);
+    }
+
+    public void testGetConditionsByTaskId() {
+        List conditions = null;
+
+        try {
+            conditions = workflowRepository
+                    .getConditionsByTaskId("urn:oodt:GoodbyeWorld");
+        } catch (RepositoryException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        validateTaskCondition(conditions);
+    }
+
+    public void testGetConditionsByTaskName() {
+        List conditions = null;
+
+        try {
+            conditions = workflowRepository
+                    .getConditionsByTaskName("Goodbye World");
+        } catch (RepositoryException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        validateTaskCondition(conditions);
+    }
+    
+    /**
+     * @since OODT-207
+     */
+    public void testGetConditionTimeout(){
+      WorkflowCondition cond = null;
+      try{
+        cond = workflowRepository.getWorkflowConditionById("urn:oodt:TimeoutCondition");
+      }
+      catch(Exception e){
+        e.printStackTrace();
+        fail(e.getMessage());
+      }
+      
+      assertEquals(30L, cond.getTimeoutSeconds());
+    }
+    
+    /**
+     * @since OODT-208
+     */
+    public void testGetConditionOptional(){
+      WorkflowCondition cond = null;
+      try{
+        cond = workflowRepository.getWorkflowConditionById("urn:oodt:OptionalCondition");
+      }
+      catch(Exception e){
+        e.printStackTrace();
+        fail(e.getMessage());
+      }
+      
+      assertEquals(true, cond.isOptional());
+    }    
+
+    public void testGetConfigurationByTaskId() {
+        WorkflowTaskConfiguration config = null;
+
+        try {
+            config = workflowRepository
+                    .getConfigurationByTaskId("urn:oodt:GoodbyeWorld");
+        } catch (RepositoryException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        validateTaskConfiguration(config);
+    }
+
+    public void testEnvVarReplaceConfigProperties() {
+        WorkflowTaskConfiguration config = null;
+
+        try {
+            config = workflowRepository
+                    .getConfigurationByTaskId("urn:oodt:PropReplaceTask");
+        } catch (RepositoryException e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        assertNotNull(config);
+        String replacedPath = config.getProperty("PathToReplace");
+        String expectedValue = System.getenv("HOME") + "/my/path";
+        assertEquals("The path: [" + replacedPath
+                + "] does not equal the expected" + "path: [" + expectedValue
+                + "]", replacedPath, expectedValue);
+
+        String notReplacedPath = config.getProperty("DontReplaceMe");
+        String notReplacedPathNoSpec = config
+                .getProperty("DontReplaceMeNoSpec");
+
+        assertNotNull(notReplacedPath);
+        assertNotNull(notReplacedPathNoSpec);
+        assertEquals(notReplacedPath, notReplacedPathNoSpec);
+
+        String expected = "[HOME]/my/path";
+        assertEquals("The path: [" + notReplacedPath + "] is not equal to the "
+                + "expected value: [" + expected + "]", expected,
+                notReplacedPath);
+
+    }
+
+    public void testMultipleConditions() {
+        WorkflowTask multiTask = null;
+
+        try {
+            multiTask = workflowRepository
+                    .getWorkflowTaskById("urn:oodt:TestMultiConditionTask");
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(multiTask);
+        assertNotNull(multiTask.getConditions());
+        assertEquals(2, multiTask.getConditions().size());
+
+        boolean gotTrueCond = false, gotFalseCond = false;
+
+        for (int i = 0; i < multiTask.getConditions().size(); i++) {
+            WorkflowCondition c = (WorkflowCondition) multiTask.getConditions()
+                    .get(i);
+            assertNotNull(c);
+            if (c.getConditionName().equals("True Condition")) {
+                gotTrueCond = true;
+            } else if (c.getConditionName().equals("False Condition")) {
+                gotFalseCond = true;
+            }
+        }
+
+        assertTrue(gotTrueCond && gotFalseCond);
+    }
+    
+    public void testConditionsConfiguration() {
+        WorkflowCondition condition = null;
+
+        try {
+            condition = workflowRepository
+                    .getWorkflowConditionById("urn:oodt:CheckForMetadataKeys");
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+
+        assertNotNull(condition);
+        assertNotNull(condition.getTaskConfig());
+
+        Metadata m = new Metadata();
+        m.addMetadata("Met1", "Val1");
+        m.addMetadata("Met2", "Val2");
+        m.addMetadata("Met3", "Val3");
+        GenericWorkflowObjectFactory.getConditionObjectFromClassName(
+                condition.getConditionInstanceClassName()).evaluate(m,
+                condition.getTaskConfig());
+    }
+
+    private void validateBackwardsWorkflow(Workflow w) {
+        assertNotNull(w);
+        assertNotNull(w.getId());
+        assertEquals("urn:oodt:backwardsTestWorkflow", w.getId());
+        assertNotNull(w.getName());
+        assertEquals("backwardsTestWorkflow", w.getName());
+        validateBackwardsWorkflowTasks(w.getTasks());
+    }
+
+    private void validateBackwardsWorkflowTasks(List tasks) {
+        assertNotNull(tasks);
+        assertEquals(2, tasks.size());
+
+        WorkflowTask t1 = (WorkflowTask) tasks.get(0);
+        assertEquals("Goodbye World", t1.getTaskName());
+        assertEquals("urn:oodt:GoodbyeWorld", t1.getTaskId());
+        assertEquals(1, t1.getOrder());
+        validateTaskConfiguration(t1.getTaskConfig());
+        validateTaskCondition(t1.getConditions());
+
+        WorkflowTask t2 = (WorkflowTask) tasks.get(1);
+        assertEquals("Hello World", t2.getTaskName());
+        assertEquals("urn:oodt:HelloWorld", t2.getTaskId());
+        assertEquals(2, t2.getOrder());
+        validateTaskConfiguration(t2.getTaskConfig());
+        validateTaskCondition(t2.getConditions());
+
+    }
+
+    private void validateTaskCondition(List conditions) {
+        assertNotNull(conditions);
+        assertEquals(1, conditions.size());
+        WorkflowCondition c = (WorkflowCondition) conditions.get(0);
+        assertEquals("urn:oodt:TrueCondition", c.getConditionId());
+        assertEquals("True Condition", c.getConditionName());
+        assertEquals(1, c.getOrder());
+        assertEquals(-1L, c.getTimeoutSeconds());
+        assertEquals(false, c.isOptional());
+    }
+
+    private void validateTaskConfiguration(WorkflowTaskConfiguration config) {
+        assertNotNull(config);
+        assertNotNull(config.getProperties());
+        assertNotNull(config.getProperties().get("Person"));
+        assertEquals("Chris", (String) config.getProperties().get("Person"));
+    }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/structs/TestFILOPrioritySorter.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/structs/TestFILOPrioritySorter.java
new file mode 100644
index 0000000..8baf818
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/structs/TestFILOPrioritySorter.java
@@ -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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.processor.SequentialProcessor;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Tests the {@link FILOPrioritySorter}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestFILOPrioritySorter extends TestCase {
+  
+  private int dateGen;
+  
+  public TestFILOPrioritySorter(){
+    this.dateGen = 0;
+  }
+
+  public void testSort() throws InstantiationException {
+    FILOPrioritySorter sorter = new FILOPrioritySorter();
+    WorkflowProcessor proc = getProcessor(2.0);
+    WorkflowProcessor proc2 = getProcessor(7.0);
+    WorkflowProcessor proc3 = getProcessor(9.0);
+    List<WorkflowProcessor> candidates = new Vector<WorkflowProcessor>();
+    candidates.add(proc3);
+    candidates.add(proc2);
+    candidates.add(proc);    
+    sorter.sort(candidates);
+    
+    assertNotNull(candidates);
+    assertEquals(3, candidates.size());
+    assertEquals(2.0, candidates.get(0).getWorkflowInstance().getPriority()
+        .getValue());
+    assertEquals(7.0, candidates.get(1).getWorkflowInstance().getPriority()
+        .getValue());
+    assertEquals(9.0, candidates.get(2).getWorkflowInstance().getPriority()
+        .getValue());
+  }
+
+  private WorkflowProcessor getProcessor(double priority) throws InstantiationException {
+    WorkflowLifecycleManager lifecycleManager = new WorkflowLifecycleManager("./src/main/resources/examples/wengine/wengine-lifecycle.xml");
+    WorkflowInstance inst = new WorkflowInstance();
+    Date sd = new Date();
+    sd.setTime(sd.getTime()+(this.dateGen*5000));
+    this.dateGen++;
+    inst.setStartDate(sd);
+    inst.setId("winst-"+priority);
+    Workflow workflow = new Workflow();
+    workflow.setTasks(Collections.EMPTY_LIST);
+    inst.setWorkflow(workflow);
+    inst.setPriority(Priority.getPriority(priority));
+    SequentialProcessor processor = new SequentialProcessor(lifecycleManager, inst);
+    return processor;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/structs/TestHighestFIFOPrioritySorter.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/structs/TestHighestFIFOPrioritySorter.java
new file mode 100644
index 0000000..77801d3
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/structs/TestHighestFIFOPrioritySorter.java
@@ -0,0 +1,82 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.processor.SequentialProcessor;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Tests the {@link HighestPrioritySorter}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestHighestFIFOPrioritySorter extends TestCase {
+
+  private int dateGen;
+  
+  public TestHighestFIFOPrioritySorter(){
+    this.dateGen = 0;
+  }
+  
+  public void testSort() throws InstantiationException {
+    HighestFIFOPrioritySorter sorter = new HighestFIFOPrioritySorter(1, 15.0, 25.0);
+    WorkflowProcessor proc = getProcessor(2.0);
+    WorkflowProcessor proc2 = getProcessor(7.0);
+    List<WorkflowProcessor> candidates = new Vector<WorkflowProcessor>();
+    candidates.add(proc);
+    candidates.add(proc2);
+    sorter.sort(candidates);
+    assertNotNull(candidates);
+    assertEquals(2, candidates.size());
+    assertEquals(7.0, candidates.get(0).getWorkflowInstance().getPriority()
+        .getValue());
+    assertEquals(2.0, candidates.get(1).getWorkflowInstance().getPriority()
+        .getValue());
+  }
+
+  private WorkflowProcessor getProcessor(double priority) throws InstantiationException {
+    WorkflowLifecycleManager lifecycleManager = new WorkflowLifecycleManager("./src/main/resources/examples/wengine/wengine-lifecycle.xml");    
+    WorkflowInstance inst = new WorkflowInstance();
+    Date sd = new Date();
+    sd.setTime(sd.getTime()+(this.dateGen*5000));
+    this.dateGen++;
+    inst.setStartDate(new Date());
+    inst.setId("winst-"+priority);
+    Workflow workflow = new Workflow();
+    workflow.setTasks(Collections.EMPTY_LIST);
+    inst.setWorkflow(workflow);
+    inst.setPriority(Priority.getPriority(priority));
+    SequentialProcessor processor = new SequentialProcessor(lifecycleManager, inst);
+    return processor;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/structs/TestHighestPrioritySorter.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/structs/TestHighestPrioritySorter.java
new file mode 100644
index 0000000..d306392
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/structs/TestHighestPrioritySorter.java
@@ -0,0 +1,85 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//JDK imports
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.engine.processor.SequentialProcessor;
+import org.apache.oodt.cas.workflow.engine.processor.WorkflowProcessor;
+import org.apache.oodt.cas.workflow.lifecycle.WorkflowLifecycleManager;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Tests the {@link HighestPrioritySorter}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestHighestPrioritySorter extends TestCase {
+
+  private int dateGen;
+  
+  public TestHighestPrioritySorter(){
+    this.dateGen = 0;
+  }
+  
+  
+  public void testSort() throws InstantiationException {
+    HighestPrioritySorter sorter = new HighestPrioritySorter();
+    WorkflowProcessor proc = getProcessor(2.0);
+    WorkflowProcessor proc2 = getProcessor(7.0);
+    List<WorkflowProcessor> candidates = new Vector<WorkflowProcessor>();
+    candidates.add(proc);
+    candidates.add(proc2);
+    System.out.println("BEFORE sort: ["+candidates+"]");
+    sorter.sort(candidates);
+    System.out.println("AFTER sort: ["+candidates+"]");
+    assertNotNull(candidates);
+    assertEquals(2, candidates.size());
+    assertEquals(7.0, candidates.get(0).getWorkflowInstance().getPriority()
+        .getValue());
+    assertEquals(2.0, candidates.get(1).getWorkflowInstance().getPriority()
+        .getValue());
+  }
+
+  private WorkflowProcessor getProcessor(double priority) throws InstantiationException {
+    WorkflowLifecycleManager lifecycleManager = new WorkflowLifecycleManager("./src/main/resources/examples/wengine/wengine-lifecycle.xml");    
+    WorkflowInstance inst = new WorkflowInstance();
+    Date sd = new Date();
+    sd.setTime(sd.getTime()+(this.dateGen*5000));
+    this.dateGen++;
+    inst.setStartDate(new Date());
+    inst.setId("winst-"+priority);
+    Workflow workflow = new Workflow();
+    workflow.setTasks(Collections.EMPTY_LIST);
+    inst.setWorkflow(workflow);
+    inst.setPriority(Priority.getPriority(priority));
+    SequentialProcessor processor = new SequentialProcessor(lifecycleManager, inst);
+    return processor;
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/structs/TestWorkflowInstance.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/structs/TestWorkflowInstance.java
new file mode 100644
index 0000000..1663ddf
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/structs/TestWorkflowInstance.java
@@ -0,0 +1,49 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.structs;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test harness for WorkflowInstance methods.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestWorkflowInstance extends TestCase {
+
+  /**
+   * @since OODT-486
+   */
+  public void testSetStartEndDateTimesNull() {
+    WorkflowInstance inst = new WorkflowInstance();
+    inst.setCurrentTaskEndDateTimeIsoStr(null);
+    inst.setCurrentTaskStartDateTimeIsoStr(null);
+    inst.setStartDateTimeIsoStr(null);
+    inst.setEndDateTimeIsoStr(null);
+
+    assertNull(inst.getEndDate());
+    assertNotNull(inst.getStartDate()); // only one initially set to new Date()
+    assertNull(inst.getCurrentTaskStartDateTimeIsoStr());
+    assertNull(inst.getCurrentTaskEndDateTimeIsoStr());
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/system/MockXmlRpcWorkflowManagerClient.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/system/MockXmlRpcWorkflowManagerClient.java
new file mode 100644
index 0000000..9c05cbc
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/system/MockXmlRpcWorkflowManagerClient.java
@@ -0,0 +1,327 @@
+/*
+ * 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.
+ */
+package org.apache.oodt.cas.workflow.system;
+
+//JDK imports
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+import java.util.Vector;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.repository.MockWorkflowRepository;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+
+//Google imports
+import com.google.common.collect.Lists;
+
+/**
+ * A Mock {@link XmlRpcWorkflowManagerClient}.
+ *
+ * @author bfoster (Brian Foster)
+ */
+public class MockXmlRpcWorkflowManagerClient extends
+      XmlRpcWorkflowManagerClient {
+
+   private MethodCallDetails lastMethodCallDetails;
+   private MockWorkflowRepository workflowRepo;
+
+   public MockXmlRpcWorkflowManagerClient() throws MalformedURLException {
+      super(new URL("http://localhost:9000"));
+      workflowRepo = new MockWorkflowRepository();
+   }
+
+   public MethodCallDetails getLastMethodCallDetails() {
+      return lastMethodCallDetails;
+   }
+
+   public String executeDynamicWorkflow(List<String> taskIds, Metadata metadata)
+         throws Exception {
+      lastMethodCallDetails = new MethodCallDetails("executeDynamicWorkflow",
+            Lists.newArrayList(taskIds, metadata));
+      return "TestId1";
+   }
+
+   public List<String> getRegisteredEvents() throws Exception {
+      lastMethodCallDetails = new MethodCallDetails("getRegisteredEvents",
+            Lists.newArrayList());
+      return workflowRepo.getRegisteredEvents();
+   }
+
+   public WorkflowInstancePage getFirstPage() throws Exception {
+      lastMethodCallDetails = new MethodCallDetails("getFirstPage",
+            Lists.newArrayList());
+      WorkflowInstancePage page = new WorkflowInstancePage();
+      page.setPageNum(1);
+      page.setPageSize(0);
+      page.setTotalPages(0);
+      page.setPageWorkflows(Lists.newArrayList());
+      return page;
+   }
+
+   public WorkflowInstancePage getNextPage(WorkflowInstancePage currentPage)
+         throws Exception {
+      lastMethodCallDetails = new MethodCallDetails("getNextPage",
+            Lists.newArrayList((Object) currentPage));
+      WorkflowInstancePage page = new WorkflowInstancePage();
+      page.setPageNum(1);
+      page.setPageSize(0);
+      page.setTotalPages(0);
+      page.setPageWorkflows(Lists.newArrayList());
+      return page;
+   }
+
+   public WorkflowInstancePage getPrevPage(WorkflowInstancePage currentPage)
+         throws Exception {
+      lastMethodCallDetails = new MethodCallDetails("getPrevPage",
+            Lists.newArrayList((Object) currentPage));
+      WorkflowInstancePage page = new WorkflowInstancePage();
+      page.setPageNum(1);
+      page.setPageSize(0);
+      page.setTotalPages(0);
+      page.setPageWorkflows(Lists.newArrayList());
+      return page;
+   }
+
+   public WorkflowInstancePage getLastPage() throws Exception {
+      lastMethodCallDetails = new MethodCallDetails("getLastPage", null);
+      WorkflowInstancePage page = new WorkflowInstancePage();
+      page.setPageNum(1);
+      page.setPageSize(0);
+      page.setTotalPages(0);
+      page.setPageWorkflows(Lists.newArrayList());
+      return page;
+   }
+
+   public WorkflowInstancePage paginateWorkflowInstances(int pageNum,
+         String status) throws Exception {
+      lastMethodCallDetails = new MethodCallDetails("paginateWorkflowInstances",
+            Lists.newArrayList(pageNum, (Object) status));
+      WorkflowInstancePage page = new WorkflowInstancePage();
+      page.setPageNum(1);
+      page.setPageSize(0);
+      page.setTotalPages(0);
+      page.setPageWorkflows(Lists.newArrayList());
+      return page;
+   }
+
+   public WorkflowInstancePage paginateWorkflowInstances(int pageNum)
+         throws Exception {
+      lastMethodCallDetails = new MethodCallDetails("paginateWorkflowInstances",
+            Lists.newArrayList((Object) pageNum));
+      WorkflowInstancePage page = new WorkflowInstancePage();
+      page.setPageNum(1);
+      page.setPageSize(0);
+      page.setTotalPages(0);
+      page.setPageWorkflows(Lists.newArrayList());
+      return page;
+   }
+
+   public List<Workflow> getWorkflowsByEvent(String eventName) throws Exception {
+      lastMethodCallDetails = new MethodCallDetails("getWorkflowsByEvent",
+            Lists.newArrayList((Object) eventName));
+      return workflowRepo.getWorkflowsForEvent(eventName);
+   }
+
+   public Metadata getWorkflowInstanceMetadata(String wInstId) throws Exception {
+      lastMethodCallDetails = new MethodCallDetails("getWorkflowInstanceMetadata",
+            Lists.newArrayList((Object) wInstId));
+      return new Metadata();
+   }
+
+   public synchronized boolean setWorkflowInstanceCurrentTaskStartDateTime(
+         String wInstId, String startDateTimeIsoStr) throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "setWorkflowInstanceCurrentTaskStartDateTime",
+            Lists.newArrayList((Object) wInstId, startDateTimeIsoStr));
+      return true;
+   }
+
+   public double getWorkflowCurrentTaskWallClockMinutes(String workflowInstId)
+         throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "getWorkflowCurrentTaskWallClockMinutes",
+            Lists.newArrayList((Object) workflowInstId));
+      return 0.0;
+   }
+
+   public double getWorkflowWallClockMinutes(String workflowInstId)
+         throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "getWorkflowWallClockMinutes",
+            Lists.newArrayList((Object) workflowInstId));
+      return 0.0;
+   }
+
+   public synchronized boolean stopWorkflowInstance(String workflowInstId)
+         throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "stopWorkflowInstance",
+            Lists.newArrayList((Object) workflowInstId));
+      return true;
+   }
+
+   public synchronized boolean pauseWorkflowInstance(String workflowInstId)
+         throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "pauseWorkflowInstance",
+            Lists.newArrayList((Object) workflowInstId));
+      return true;
+   }
+
+   public synchronized boolean resumeWorkflowInstance(String workflowInstId)
+         throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "resumeWorkflowInstance",
+            Lists.newArrayList((Object) workflowInstId));
+      return true;
+   }
+
+   public synchronized boolean setWorkflowInstanceCurrentTaskEndDateTime(
+         String wInstId, String endDateTimeIsoStr) throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "setWorkflowInstanceCurrentTaskEndDateTime",
+            Lists.newArrayList((Object) wInstId, endDateTimeIsoStr));
+      return true;
+   }
+
+   public synchronized boolean updateWorkflowInstanceStatus(
+         String workflowInstId, String status) throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "updateWorkflowInstanceStatus",
+            Lists.newArrayList((Object) workflowInstId, status));
+      return true;
+   }
+
+   public synchronized boolean updateWorkflowInstance(WorkflowInstance instance)
+         throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "updateWorkflowInstance",
+            Lists.newArrayList((Object) instance));
+      return true;
+   }
+
+   public synchronized boolean updateMetadataForWorkflow(String workflowInstId,
+         Metadata metadata) throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "updateMetadataForWorkflow",
+            Lists.newArrayList((Object) workflowInstId, metadata));
+      return true;
+   }
+
+   public boolean sendEvent(String eventName, Metadata metadata)
+         throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "sendEvent",
+            Lists.newArrayList((Object) eventName, metadata));
+      return true;
+   }
+
+   public WorkflowTask getTaskById(String taskId) throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "getTaskById",
+            Lists.newArrayList((Object) taskId));
+      return workflowRepo.getWorkflowTaskById(taskId);
+   }
+
+   public WorkflowCondition getConditionById(String conditionId)
+         throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "getConditionById",
+            Lists.newArrayList((Object) conditionId));
+      return workflowRepo.getWorkflowConditionById(conditionId);
+   }
+
+   public WorkflowInstance getWorkflowInstanceById(String wInstId)
+         throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "getWorkflowInstanceById",
+            Lists.newArrayList((Object) wInstId));
+      WorkflowInstance wInst = new WorkflowInstance();
+      wInst.setStatus("Running");
+      wInst.setId("TestId");
+      wInst.setWorkflow(workflowRepo.getWorkflowById(
+            MockWorkflowRepository.WORKFLOW1_ID));
+      wInst.setCurrentTaskId(MockWorkflowRepository.TASK1_ID);
+      return wInst;
+   }
+
+   public Workflow getWorkflowById(String workflowId) throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "getWorkflowById",
+            Lists.newArrayList((Object) workflowId));
+      return workflowRepo.getWorkflowById(workflowId);
+   }
+
+   public Vector<Workflow> getWorkflows() throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "getWorkflows",
+            Lists.newArrayList());
+      return new Vector<Workflow>(workflowRepo.getWorkflows());
+   }
+
+   public int getNumWorkflowInstancesByStatus(String status) throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "getNumWorkflowInstancesByStatus",
+            Lists.newArrayList((Object) status));
+      return 1;
+   }
+
+   public int getNumWorkflowInstances() throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "getNumWorkflowInstances",
+            Lists.newArrayList());
+      return 1;
+   }
+
+   public Vector<WorkflowInstance> getWorkflowInstancesByStatus(String status) throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "getWorkflowInstancesByStatus",
+            Lists.newArrayList((Object) status));
+      return new Vector<WorkflowInstance>();
+   }
+
+   public Vector<WorkflowInstance> getWorkflowInstances() throws Exception {
+      lastMethodCallDetails = new MethodCallDetails(
+            "getWorkflowInstances",
+            Lists.newArrayList());
+      return new Vector<WorkflowInstance>();
+   }
+
+   public class MethodCallDetails {
+      private String methodName;
+      private List<Object> args;
+
+      public MethodCallDetails(String methodName, List<Object> args) {
+         this.methodName = methodName;
+         this.args = args;
+      }
+
+      public String getMethodName() {
+         return methodName;
+      }
+
+      public List<Object> getArgs() {
+         return args;
+      }
+   }
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/system/TestXmlRpcWorkflowManager.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/system/TestXmlRpcWorkflowManager.java
new file mode 100644
index 0000000..c99bdc0
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/system/TestXmlRpcWorkflowManager.java
@@ -0,0 +1,162 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.system;
+
+//JDK imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//Junit imports
+import junit.framework.TestCase;
+
+//OODT imports
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+
+/**
+ * 
+ * 
+ * Test harness for the {@link XmlRpcWorkflowManager}.
+ * 
+ * @author sherylj
+ * @author mattmann
+ * @version $Revision$
+ * 
+ */
+public class TestXmlRpcWorkflowManager extends TestCase {
+
+  private static final int WM_PORT = 50002;
+
+  private XmlRpcWorkflowManager wmgr;
+
+  private String luceneCatLoc;
+
+  private static final Logger LOG = Logger
+      .getLogger(TestXmlRpcWorkflowManager.class.getName());
+
+  public void testGetWorkflowInstances() {
+
+    Vector workflowInsts = null;
+
+    int numInsts = -1;
+    while (numInsts != 2) {
+      try {
+        workflowInsts = wmgr.getWorkflowInstances();
+      } catch (Exception e) {
+        e.printStackTrace();
+      }
+
+      assertNotNull(workflowInsts);
+      numInsts = workflowInsts.size();
+    }
+
+    assertEquals(2, workflowInsts.size());
+  }
+
+  protected void setUp() throws Exception {
+    startXmlRpcWorkflowManager();
+    startWorkflow();
+  }
+
+  protected void tearDown() throws Exception {
+
+  }
+
+  private void startWorkflow() {
+    XmlRpcWorkflowManagerClient client = null;
+    try {
+      client = new XmlRpcWorkflowManagerClient(new URL("http://localhost:"
+          + WM_PORT));
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    try {
+      client.sendEvent("long", new Metadata());
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw new RuntimeException(e);
+    }
+
+  }
+
+  private void startXmlRpcWorkflowManager() {
+    System.setProperty("java.util.logging.config.file", new File(
+        "./src/main/resources/logging.properties").getAbsolutePath());
+
+    try {
+      System.getProperties().load(
+          new FileInputStream("./src/main/resources/workflow.properties"));
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    try {
+      luceneCatLoc = File.createTempFile("blah", "txt").getParentFile()
+          .getCanonicalPath();
+      luceneCatLoc = !luceneCatLoc.endsWith("/") ? luceneCatLoc + "/"
+          : luceneCatLoc;
+      luceneCatLoc += "repo";
+      LOG.log(Level.INFO, "Lucene instance repository: [" + luceneCatLoc + "]");
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    if (new File(luceneCatLoc).exists()) {
+      // blow away lucene cat
+      LOG.log(Level.INFO, "Removing workflow instance repository: ["
+          + luceneCatLoc + "]");
+      try {
+        FileUtils.deleteDirectory(new File(luceneCatLoc));
+      } catch (IOException e) {
+        fail(e.getMessage());
+      }
+    }
+
+    System
+        .setProperty("workflow.engine.instanceRep.factory",
+            "org.apache.oodt.cas.workflow.instrepo.LuceneWorkflowInstanceRepositoryFactory");
+    System
+        .setProperty("org.apache.oodt.cas.workflow.instanceRep.lucene.idxPath",
+            luceneCatLoc);
+
+    try {
+      System.setProperty("org.apache.oodt.cas.workflow.repo.dirs", "file://"
+          + new File("./src/main/resources/examples").getCanonicalPath());
+      System.setProperty("org.apache.oodt.cas.workflow.lifecycle.filePath",
+          new File("./src/main/resources/examples/workflow-lifecycle.xml")
+              .getCanonicalPath());
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    try {
+      wmgr = new XmlRpcWorkflowManager(WM_PORT);
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/system/TestXmlRpcWorkflowManagerClient.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/system/TestXmlRpcWorkflowManagerClient.java
new file mode 100644
index 0000000..7f1bf8d
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/system/TestXmlRpcWorkflowManagerClient.java
@@ -0,0 +1,172 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.system;
+
+//OODT imports
+import org.apache.commons.io.FileUtils;
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.workflow.instrepo.LuceneWorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.structs.Workflow;
+import org.apache.oodt.cas.workflow.structs.WorkflowCondition;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTask;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+
+//JDK imports
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test harness for the {@link XmlRpcWorkflowManagerClient}.
+ * 
+ */
+public class TestXmlRpcWorkflowManagerClient extends TestCase {
+
+  private static final String catalogPath = new File("./target/instTestMetCat")
+      .getAbsolutePath();
+
+  private LuceneWorkflowInstanceRepository repo = null;
+  private WorkflowInstance testWrkInst = null;
+  private Workflow testWrkFlw;
+  private WorkflowTask testTask;
+  private WorkflowCondition testCond;
+
+  private static final int stdPgSz = 20;
+
+  public TestXmlRpcWorkflowManagerClient() {
+
+    testWrkInst = new WorkflowInstance();
+    testWrkFlw = new Workflow();
+    testTask = new WorkflowTask();
+    testCond = new WorkflowCondition();
+    Metadata sharedContext = new Metadata();
+
+    // to check if the path already exists and to delete if it does exist
+    if (new File(catalogPath).exists()) {
+      try {
+        FileUtils.deleteDirectory(new File(catalogPath));
+      } catch (IOException e) {
+        fail(e.getMessage());
+      }
+    }
+    repo = new LuceneWorkflowInstanceRepository(catalogPath, stdPgSz);
+
+    testWrkFlw.setName("test.getMetadataWorkflow");
+    testWrkFlw.setId("test.id");
+    List tasks = new Vector();
+    List conds = new Vector();
+
+    testCond.setConditionId("test.cond.id");
+    testCond.setConditionInstanceClassName("test.class");
+    testCond.setConditionName("test.cond.name");
+    testCond.setOrder(1);
+    conds.add(testCond);
+
+    testTask.setTaskConfig(new WorkflowTaskConfiguration());
+    testTask.setTaskId("test.task.id");
+    testTask.setConditions(conds);
+    testTask.setOrder(1);
+    testTask.setTaskInstanceClassName("test.class");
+    testTask.setTaskName("test.task.name");
+    tasks.add(testTask);
+    testWrkFlw.setTasks(tasks);
+
+    testWrkInst.setCurrentTaskId("test.task");
+    testWrkInst.setStatus("STARTED");
+    testWrkInst.setWorkflow(testWrkFlw);
+
+    sharedContext.addMetadata("key1", "val1");
+    sharedContext.addMetadata("key1", "val2");
+    sharedContext.addMetadata("key1", "val3");
+    sharedContext.addMetadata("key2", "val4");
+    sharedContext.addMetadata("key2", "val5");
+    testWrkInst.setSharedContext(sharedContext);
+
+  }
+
+  public void testGetWorkflowInstanceMetadata() {
+
+    try {
+      repo.addWorkflowInstance(testWrkInst);
+    } catch (InstanceRepositoryException e) {
+      fail(e.getMessage());
+    }
+    String testWrkInstId = testWrkInst.getId();
+    assertNotNull(testWrkInstId);
+
+    // get workflow instance from instance id
+    WorkflowInstance WInst = null;
+    try {
+      WInst = repo.getWorkflowInstanceById(testWrkInstId);
+    } catch (InstanceRepositoryException e) {
+      fail(e.getMessage());
+    }
+
+    assertNotNull(WInst);
+
+    // get Metadata for the workflow instance
+    Metadata met = null;
+    met = WInst.getSharedContext();
+    assertNotNull(met);
+
+    assertNotNull(met.getHashtable());
+    assertEquals(2, met.getHashtable().keySet().size());
+    assertNotNull(met.getAllMetadata("key1"));
+    assertEquals(3, met.getAllMetadata("key1").size());
+    assertNotNull(met.getAllMetadata("key2"));
+    assertEquals(2, met.getAllMetadata("key2").size());
+
+    // check key-values for key1
+    boolean checkVal1 = false, checkVal2 = false, checkVal3 = false;
+
+    for (Iterator i = met.getAllMetadata("key1").iterator(); i.hasNext();) {
+      String val = (String) i.next();
+      if (val.equals("val1")) {
+        checkVal1 = true;
+      } else if (val.equals("val2")) {
+        checkVal2 = true;
+      } else if (val.equals("val3")) {
+        checkVal3 = true;
+      }
+    }
+
+    assert (checkVal1 && checkVal2 && checkVal3);
+
+    // check key-values for key2
+    boolean checkVal4 = false, checkVal5 = false;
+
+    for (Iterator i = met.getAllMetadata("key2").iterator(); i.hasNext();) {
+      String val = (String) i.next();
+      if (val.equals("val4")) {
+        checkVal4 = true;
+      } else if (val.equals("val5")) {
+        checkVal5 = true;
+      }
+    }
+
+    assertTrue(checkVal4 && checkVal5);
+  }
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/tools/TestInstanceRepoCleaner.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/tools/TestInstanceRepoCleaner.java
new file mode 100644
index 0000000..e9f9f4e
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/tools/TestInstanceRepoCleaner.java
@@ -0,0 +1,105 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.cas.workflow.tools;
+
+//JDK imports
+import java.io.File;
+import java.util.List;
+
+//APACHE imports
+import org.apache.commons.io.FileUtils;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.instrepo.LuceneWorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.instrepo.WorkflowInstanceRepository;
+import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowStatus;
+import org.apache.oodt.cas.workflow.structs.exceptions.InstanceRepositoryException;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * 
+ * Test harness for the {@link InstanceRepoCleaner}.
+ * 
+ * @author mattmann
+ * @version $Revision$
+ * @since 
+ * 
+ */
+public class TestInstanceRepoCleaner extends TestCase {
+
+  private String instRepoPath;
+
+  public void testClean() {
+    InstanceRepoCleaner cleaner = new InstanceRepoCleaner();
+    cleaner.setInstanceRepo(instRepoPath);
+    try {
+      cleaner.cleanRepository();
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    WorkflowInstanceRepository repo = new LuceneWorkflowInstanceRepository(
+        instRepoPath, 20);
+    try {
+      assertEquals(10, repo.getNumWorkflowInstances());
+      for (WorkflowInstance inst : (List<WorkflowInstance>) repo
+          .getWorkflowInstances()) {
+        if (!inst.getStatus().equals(WorkflowStatus.FINISHED)) {
+          fail("Workflow Instance: [" + inst.getId()
+              + "] does was not marked as finished by the cleaner: status: ["
+              + inst.getStatus() + "]");
+        }
+      }
+
+    } catch (InstanceRepositoryException e) {
+      fail(e.getMessage());
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#setUp()
+   */
+  @Override
+  protected void setUp() throws Exception {
+    // get a temp directory path
+    File tempDir = File.createTempFile("bogus", "txt").getParentFile();
+    FileUtils.copyDirectory(new File("./src/test/resources/testinstrepo"), new File(
+        tempDir.getAbsolutePath() + "/" + "testinstrepo"));
+    instRepoPath = tempDir.getAbsolutePath().endsWith("/") ? (tempDir
+        .getAbsolutePath() + "testinstrepo")
+        : (tempDir.getAbsolutePath() + "/" + "testinstrepo");
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see junit.framework.TestCase#tearDown()
+   */
+  @Override
+  protected void tearDown() throws Exception {
+    FileUtils.deleteDirectory(new File(instRepoPath));
+
+  }
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/util/TestGenericWorkflowObjectFactory.java b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/util/TestGenericWorkflowObjectFactory.java
new file mode 100644
index 0000000..876a567
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/java/org/apache/oodt/cas/workflow/util/TestGenericWorkflowObjectFactory.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.cas.workflow.util;
+
+//OODT imports
+import org.apache.oodt.cas.workflow.structs.WorkflowConditionInstance;
+import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * @author mattmann
+ * @version $Revision$
+ * 
+ * <p>
+ * A Test Suite for the GenericWorkflowObjectFactory class.
+ * </p>.
+ */
+public class TestGenericWorkflowObjectFactory extends TestCase {
+
+	public void testCreateTask() {
+		String taskClass = "org.apache.oodt.cas.workflow.examples.LongTask";
+
+		WorkflowTaskInstance taskInst = GenericWorkflowObjectFactory
+				.getTaskObjectFromClassName(taskClass);
+		assertNotNull(taskInst);
+		assertEquals("The class: [" + taskInst.getClass().getName()
+				+ "] is not " + "equal to the expected class name: ["
+				+ taskClass + "]", taskClass, taskInst.getClass().getName());
+	}
+
+	public void testCreateCondition() {
+		String condClass = "org.apache.oodt.cas.workflow.examples.LongCondition";
+
+		WorkflowConditionInstance condInst = GenericWorkflowObjectFactory
+				.getConditionObjectFromClassName(condClass);
+		assertNotNull(condInst);
+		assertEquals(condClass, condInst.getClass().getName());
+	}
+
+}
diff --git a/0.8.1-rc1/workflow/src/test/resources/myScript-Output.txt b/0.8.1-rc1/workflow/src/test/resources/myScript-Output.txt
new file mode 100644
index 0000000..5f7f0c4
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/resources/myScript-Output.txt
@@ -0,0 +1 @@
+Hi my first name is Faranak and my last name is Davoodi.
diff --git a/0.8.1-rc1/workflow/src/test/resources/myScript.sh b/0.8.1-rc1/workflow/src/test/resources/myScript.sh
new file mode 100644
index 0000000..fd9fbf7
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/resources/myScript.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+echo Hi my first name is  $1 and my last name is $2. > ./src/testdata/myScript-Output.txt
\ No newline at end of file
diff --git a/0.8.1-rc1/workflow/src/test/resources/test.logging.properties b/0.8.1-rc1/workflow/src/test/resources/test.logging.properties
new file mode 100644
index 0000000..4b67dfb
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/resources/test.logging.properties
@@ -0,0 +1,53 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt 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.    
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates two handlers
+handlers = java.util.logging.ConsoleHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging level for the subsystems
+
+# data structures subsystem
+org.apache.oodt.cas.workflow.structs.level = INFO
+
+# engine subsystem
+org.apache.oodt.cas.workflow.engine.level = INFO
+
+# instance repository subsystem
+org.apache.oodt.cas.workflow.instrepo.level = INFO
+
+# repository subsystem
+org.apache.oodt.cas.workflow.repository.level = INFO
+
+# system subsystem
+org.apache.oodt.cas.workflow.system.level = FINE
+
+# control the underlying commons-httpclient transport layer for xmlrpc 
+org.apache.commons.httpclient.level = INFO
+httpclient.wire.header.level = INFO
+httpclient.wire.level = INFO
+sun.net.level = OFF
+sun.net.www.level = OFF
+
diff --git a/0.8.1-rc1/workflow/src/test/resources/testinstrepo/_43.cfs b/0.8.1-rc1/workflow/src/test/resources/testinstrepo/_43.cfs
new file mode 100644
index 0000000..88faee3
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/resources/testinstrepo/_43.cfs
Binary files differ
diff --git a/0.8.1-rc1/workflow/src/test/resources/testinstrepo/deletable b/0.8.1-rc1/workflow/src/test/resources/testinstrepo/deletable
new file mode 100644
index 0000000..593f470
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/resources/testinstrepo/deletable
Binary files differ
diff --git a/0.8.1-rc1/workflow/src/test/resources/testinstrepo/segments b/0.8.1-rc1/workflow/src/test/resources/testinstrepo/segments
new file mode 100644
index 0000000..9ff00d2
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/resources/testinstrepo/segments
Binary files differ
diff --git a/0.8.1-rc1/workflow/src/test/resources/workflow.sql b/0.8.1-rc1/workflow/src/test/resources/workflow.sql
new file mode 100644
index 0000000..e025a69
--- /dev/null
+++ b/0.8.1-rc1/workflow/src/test/resources/workflow.sql
@@ -0,0 +1,81 @@
+
+DROP TABLE workflows IF EXISTS;
+DROP TABLE workflow_condition_map IF EXISTS;
+DROP TABLE event_workflow_map IF EXISTS;
+DROP TABLE workflow_tasks IF EXISTS;
+DROP TABLE workflow_task_map IF EXISTS;
+DROP TABLE workflow_instances IF EXISTS;
+DROP TABLE workflow_instance_metadata IF EXISTS;
+DROP TABLE workflow_conditions IF EXISTS;
+DROP TABLE task_condition_map IF EXISTS;
+DROP TABLE workflow_task_configuration IF EXISTS;
+DROP TABLE workflow_condition_configuration IF EXISTS;
+
+CREATE TABLE workflows 
+(workflow_id int NOT NULL PRIMARY KEY, 
+workflow_name varchar(255));
+
+CREATE TABLE workflow_condition_map
+(workflow_id int NOT NULL,
+workflow_condition_id int NOT NULL,
+condition_order int NOT NULL);
+
+CREATE TABLE event_workflow_map
+(workflow_id int NOT NULL,
+event_name varchar(255) NOT NULL);
+
+CREATE TABLE workflow_tasks
+(workflow_task_id int NOT NULL PRIMARY KEY,
+workflow_task_name varchar(255),
+workflow_task_class varchar(255));
+
+CREATE TABLE workflow_task_map
+(workflow_id int NOT NULL,
+workflow_task_id int NOT NULL,
+task_order int NOT NULL);
+
+CREATE TABLE workflow_instances
+(workflow_instance_id int NOT NULL PRIMARY KEY,
+workflow_instance_status varchar(255),
+workflow_id int NOT NULL,
+current_task_id int NOT NULL,
+start_date_time varchar(255),
+end_date_time varchar(255),
+current_task_start_date_time varchar(255),
+current_task_end_date_time varchar(255),
+priority float NOT NULL,
+times_blocked int DEFAULT 0);
+
+CREATE TABLE workflow_instance_metadata
+(workflow_instance_id int NOT NULL,
+workflow_met_key varchar(1000) NOT NULL,
+workflow_met_val varchar(1000) NOT NULL);
+
+CREATE TABLE workflow_conditions
+(workflow_condition_id int NOT NULL PRIMARY KEY,
+workflow_condition_name varchar(255) NOT NULL,
+workflow_condition_class varchar(255) NOT NULL,
+workflow_condition_timeout int NOT NULL,
+workflow_condition_optional boolean DEFAULT false);
+
+CREATE TABLE task_condition_map
+(workflow_task_id int NOT NULL, 
+workflow_condition_id int NOT NULL,
+condition_order int NOT NULL);
+
+CREATE TABLE workflow_task_configuration
+(workflow_task_id int NOT NULL,
+property_name varchar(1000) NOT NULL,
+property_value varchar(1000) NOT NULL);
+
+CREATE TABLE workflow_condition_configuration
+(workflow_condition_id int NOT NULL,
+property_name varchar(1000) NOT NULL,
+property_value varchar(1000) NOT NULL);
+
+INSERT INTO workflow_conditions VALUES ('1', 'CheckCond', 'org.apache.oodt.cas.workflow.examples.CheckForMetadataKeys', 30, false);
+INSERT INTO workflow_condition_configuration VALUES ('1', 'reqMetKeys', 'Met1,Met2,Met3');
+INSERT INTO workflow_conditions VALUES ('2', 'FalseCond', 'org.apache.oodt.cas.workflow.examples.FalseCondition', 10, true);
+INSERT INTO workflow_conditions VALUES ('3', 'TrueCond', 'org.apache.oodt.cas.workflow.examples.TrueCondition', 30, true);
+INSERT INTO workflows VALUES ('1', 'Test Workflow');
+INSERT INTO workflow_condition_map VALUES ('1', '3', '1');
diff --git a/0.8.1-rc1/xmlps/pom.xml b/0.8.1-rc1/xmlps/pom.xml
new file mode 100644
index 0000000..a8c8d13
--- /dev/null
+++ b/0.8.1-rc1/xmlps/pom.xml
@@ -0,0 +1,143 @@
+<?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.
+	-->
+
+<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>
+	<parent>
+		<groupId>org.apache.oodt</groupId>
+		<artifactId>oodt-core</artifactId>
+		<version>0.8.1</version>
+		<relativePath>../core/pom.xml</relativePath>
+	</parent>
+	<artifactId>oodt-xmlps</artifactId>
+	<name>XML-configured, DBMS-based Product and Profile Server</name>
+	<version>0.8.1</version>
+	<description>
+	  An XML-configured DBMS-based Product and Profile meant to easily 
+	  sit on top of Web-Grid and other Product and Profile server contexts
+	  for rapid deployment and integration.
+	</description>
+	<build>
+	 <testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
+		<resources>
+			<resource>
+				<targetPath>org/apache/oodt/xmlps</targetPath>
+				<directory>${basedir}/src/main/conf</directory>
+			</resource>
+		</resources>
+		<testResources>
+			<testResource>
+				<targetPath>org/apache/oodt/xmlps/mapping</targetPath>
+				<filtering />
+				<directory>${basedir}/src/test/resources</directory>
+				<includes />
+				<excludes />
+			</testResource>
+		</testResources>
+		
+		<plugins>
+			<plugin>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<configuration>
+					<descriptorRefs>
+						<descriptorRef>jar-with-dependencies</descriptorRef>
+					</descriptorRefs>
+				</configuration>
+			</plugin>
+			<plugin>
+				<artifactId>maven-surefire-plugin</artifactId>
+				<configuration>
+				    <forkMode>pertest</forkMode>
+					<systemProperties>
+			          <property>
+			            <name>java.util.logging.config.file</name>
+			            <value>${basedir}/src/test/resources/logging.properties</value>
+			          </property>					
+					</systemProperties>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>oodt-commons</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>oodt-xmlquery</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>cas-metadata</artifactId>
+			<version>${project.parent.version}</version>
+			<optional />
+		</dependency>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>oodt-product</artifactId>
+			<version>${project.parent.version}</version>
+			<optional />
+		</dependency>
+		<dependency>
+			<groupId>org.apache.oodt</groupId>
+			<artifactId>oodt-profile</artifactId>
+			<version>${project.parent.version}</version>
+			<optional />
+		</dependency>
+		<dependency>
+			<groupId>commons-dbcp</groupId>
+			<artifactId>commons-dbcp</artifactId>
+			<version>1.2.1</version>
+			<optional />
+		</dependency>
+		<dependency>
+			<groupId>commons-collections</groupId>
+			<artifactId>commons-collections</artifactId>
+			<version>2.1</version>
+			<optional />
+		</dependency>
+		<dependency>
+			<groupId>commons-pool</groupId>
+			<artifactId>commons-pool</artifactId>
+			<version>1.2</version>
+			<optional />
+		</dependency>
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>servlet-api</artifactId>
+			<version>2.3</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.2</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.easymock</groupId>
+			<artifactId>easymock</artifactId>
+			<version>3.0</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+</project>
+
diff --git a/0.8.1-rc1/xmlps/src/main/conf/example-ps.xml b/0.8.1-rc1/xmlps/src/main/conf/example-ps.xml
new file mode 100644
index 0000000..82cb08c
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/conf/example-ps.xml
@@ -0,0 +1,71 @@
+<?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.
+-->
+<!-- Example XML mapping configuration file -->
+<oodt:xmlps xmlns:oodt="http://incubator.apache.org/oodt/0.1-incubating"
+	name="Example Query Handler" id="project:subproject:exampleps">
+	<!-- 
+	 attribute:
+	   default (required): This is the name of the master table part of the
+	          from clause in the generated query. The default table *does not*
+	          require a definition in the underlying <table.. tags below, though
+	          post OODT-548 these will be silently ignored.	
+	 -->
+	<tables default="Table1">
+		<table name="Table2" join="join_key" tofld="base_table_join_key" />
+		<table name="Table3" join="join_key" tofld="base_table_join_key" />
+	</tables>
+	<!-- 
+		field:
+		
+		type (required):   dynamic or constant. If you choose dynamic, then the field
+		value is read from the row in the ResultSet returned
+		from the database. If constant, then each returned row
+		from the ResultSet is annotated with the value specified
+		in the 'value' attribute.
+		
+	  name (required):   the name of the attribute that you want returned
+		in the product server.
+		
+		string (optional): whether or not the internal db representation at the local
+		site for this field is a STRING, or something else (e.g., a number, etc.). Possible 
+		values for this attribute are "true", to indicate that the field is a string, or
+		"false", to indicate that it is something else. If this attribute is omitted, a value
+		of "false" is assumed, and the attribute will not be quoted in the where clause of
+		the underlying SQL statement generated.
+		
+		dbname (optional): the name of the field within the underlying db. If not
+		specified, then assumed to be name
+		
+		table (optional):  if provided, then the attribute a is selected as
+		'table'.'a',and then returned. If omitted, the attribute
+		is assumed to come from the default table returned from the
+		PS query.
+		
+		value (optional):  is necessary to provide if type='constant' is selected.
+		
+		scope (optional):  limits the scope of a field's existence: acceptable values
+		are &quot;query&quot;, which signifies that the field is only applicable when
+		translating queries: and &quot;return&quot;, which signifies the field is only
+		applicable as a return field when converting database results into CDEResults.
+		
+	-->
+	<field type="dynamic" name="CDE_NAME1" dbname="site_specific_name1" table="Table1" />
+	<field type="dynamic" name="CDE_NAME2" dbname="site_specific_name2" table="Table2" />
+	<field type="dynamic" name="CDE_NAME3" dbname="site_specific_name3" table="Table2" />
+	<field type="constant" name="CDE_NAME4" value="constant_value" />
+</oodt:xmlps>
diff --git a/0.8.1-rc1/xmlps/src/main/conf/example.db.properties b/0.8.1-rc1/xmlps/src/main/conf/example.db.properties
new file mode 100644
index 0000000..ac31f6a
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/conf/example.db.properties
@@ -0,0 +1,21 @@
+# 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.
+
+# Example data source configuration file
+
+xmlps.datasource.jdbc.url=<driver>:<server_type>://<server>[:<port>][/<database>][;<property>=<value>[;...]]
+xmlps.datasource.jdbc.user=USERNAME
+xmlps.datasource.jdbc.pass=PASSWORD
+xmlps.datasource.jdbc.driver=java.sql.Driver
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/DatabaseTable.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/DatabaseTable.java
new file mode 100644
index 0000000..ae4bb8a
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/DatabaseTable.java
@@ -0,0 +1,118 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.mapping;
+
+/**
+ * 
+ * <p>
+ * Description of a local site's database table that will be used as a model to
+ * query against and select data from.
+ * </p>.
+ */
+public class DatabaseTable {
+
+    private String name;
+
+    private String joinFieldName;
+
+    private String defaultTableJoinFieldName;
+
+    private String defaultTableJoin;
+
+    /**
+     * @param name
+     * @param joinFieldName
+     * @param defaultTableJoinFieldName
+     * @param defaultTableJoin
+     */
+    public DatabaseTable(String name, String joinFieldName,
+            String defaultTableJoinFieldName, String defaultTableJoin) {
+        super();
+        this.name = name;
+        this.joinFieldName = joinFieldName;
+        this.defaultTableJoinFieldName = defaultTableJoinFieldName;
+        this.defaultTableJoin = defaultTableJoin;
+    }
+
+    /**
+     * 
+     */
+    public DatabaseTable() {
+    }
+
+    /**
+     * @return the joinFieldName
+     */
+    public String getJoinFieldName() {
+        return joinFieldName;
+    }
+
+    /**
+     * @param joinFieldName
+     *            the joinFieldName to set
+     */
+    public void setJoinFieldName(String joinFieldName) {
+        this.joinFieldName = joinFieldName;
+    }
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @param name
+     *            the name to set
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * @return the defaultTableJoinFieldName
+     */
+    public String getDefaultTableJoinFieldName() {
+        return defaultTableJoinFieldName;
+    }
+
+    /**
+     * @param defaultTableJoinFieldName
+     *            the defaultTableJoinFieldName to set
+     */
+    public void setDefaultTableJoinFieldName(String defaultTableJoinFieldName) {
+        this.defaultTableJoinFieldName = defaultTableJoinFieldName;
+    }
+
+    /**
+     * @return the defaultTableJoin
+     */
+    public String getDefaultTableJoin() {
+        return defaultTableJoin;
+    }
+
+    /**
+     * @param defaultTableJoin
+     *            the defaultTableJoin to set
+     */
+    public void setDefaultTableJoin(String defaultTableJoin) {
+        this.defaultTableJoin = defaultTableJoin;
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/DatabaseTableGroup.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/DatabaseTableGroup.java
new file mode 100644
index 0000000..240ee3a
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/DatabaseTableGroup.java
@@ -0,0 +1,85 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.mapping;
+
+//JDK imports
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Vector;
+
+/**
+ * 
+ * <p>
+ * A collection of {@link DatabaseTable}s
+ * </p>.
+ */
+public class DatabaseTableGroup {
+
+    private Map<String, DatabaseTable> group;
+
+    private List<DatabaseTable> orderedGroup;
+
+    private String defaultTable;
+
+    public DatabaseTableGroup() {
+        this.group = new TreeMap<String, DatabaseTable>();
+        this.orderedGroup = new Vector<DatabaseTable>();
+    }
+
+    public void addTable(String tblName, DatabaseTable tbl) {
+        this.group.put(tblName, tbl);
+        this.orderedGroup.add(tbl);
+    }
+
+    public DatabaseTable getTableByName(String name) {
+        return this.group.get(name);
+    }
+
+    public int getNumTables() {
+        return this.group.keySet().size();
+    }
+
+    public List<String> getTableNames() {
+        List<String> names = new Vector<String>();
+        for (Iterator<DatabaseTable> i = this.orderedGroup.iterator(); i
+                .hasNext();) {
+            DatabaseTable tbl = i.next();
+            names.add(tbl.getName());
+        }
+
+        return names;
+    }
+
+    /**
+     * @return the defaultTable
+     */
+    public String getDefaultTable() {
+        return defaultTable;
+    }
+
+    /**
+     * @param defaultTable
+     *            the defaultTable to set
+     */
+    public void setDefaultTable(String defaultTable) {
+        this.defaultTable = defaultTable;
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/FieldScope.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/FieldScope.java
new file mode 100644
index 0000000..40e7273
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/FieldScope.java
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.mapping;
+
+/**
+ *
+ * <p>
+ * Defines the scope of a {@link MappingField}.
+ * </p>.
+ */
+public enum FieldScope {
+
+  QUERY,
+  RETURN;
+
+  public String getType() {
+    return toString().toLowerCase();
+  }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/FieldType.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/FieldType.java
new file mode 100644
index 0000000..a2751aa
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/FieldType.java
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.mapping;
+
+/**
+ *
+ * <p>
+ * Defines the type of a {@link MappingField}
+ * </p>.
+ */
+public enum FieldType {
+
+  DYNAMIC,
+  CONSTANT;
+
+  public String getType() {
+    return toString().toLowerCase();
+  }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/Mapping.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/Mapping.java
new file mode 100644
index 0000000..1a38b06
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/Mapping.java
@@ -0,0 +1,169 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.mapping;
+
+//JDK imports
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ *
+ * <p>
+ * An Mapping is a {@link List} of {@link MappingField}s that define the
+ * translation of common ontological queries into queries against a local site's
+ * DBMS
+ * </p>
+ * .
+ */
+public class Mapping {
+
+  private final Map<String, MappingField> fields;
+
+  private final DatabaseTableGroup tables;
+
+  private String id;
+
+  private String name;
+
+  /**
+     *
+     */
+  public Mapping() {
+    this.fields = new TreeMap<String, MappingField>();
+    this.tables = new DatabaseTableGroup();
+  }
+
+  public Mapping(Map<String, MappingField> fields, DatabaseTableGroup tables,
+      String id, String name) {
+    super();
+    this.fields = fields;
+    this.id = id;
+    this.name = name;
+    this.tables = tables;
+  }
+
+  public void addField(String fldName, MappingField field) {
+    this.fields.put(fldName, field);
+  }
+
+  public MappingField getFieldByLocalName(String localName) {
+    if (this.fields == null
+        || (this.fields != null && this.fields.keySet() == null)
+        || (this.fields != null && this.fields.keySet() != null && this.fields
+            .keySet().size() == 0)) {
+      return null;
+    }
+
+    for (MappingField fld : this.fields.values()) {
+      if (fld.getLocalName().equals(localName)) {
+        return fld;
+      }
+    }
+
+    return null;
+  }
+
+  public MappingField getFieldByName(String name) {
+    return this.fields.get(name);
+  }
+
+  public boolean constantField(String localName) {
+    MappingField fld = getFieldByLocalName(localName);
+
+    if (fld == null) {
+      return true; // leave it out
+    }
+
+    if (fld.getType() == FieldType.CONSTANT) {
+      return true;
+    } else
+      return false;
+  }
+
+  public int getNumFields() {
+    return this.fields.keySet().size();
+  }
+
+  public void addTable(String tblName, DatabaseTable tbl) {
+    this.tables.addTable(tblName, tbl);
+  }
+
+  public DatabaseTable getTableByName(String name) {
+    return this.tables.getTableByName(name);
+  }
+
+  public int getNumTables() {
+    return this.tables.getNumTables();
+  }
+
+  public List<String> getTableNames() {
+    return this.tables.getTableNames();
+  }
+
+  public List<String> getFieldNames() {
+    return Arrays.asList(this.fields.keySet().toArray(new String[] { "" }));
+  }
+
+  /**
+   * @return the id
+   */
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * @param id
+   *          the id to set
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return the defaultTable
+   */
+  public String getDefaultTable() {
+    return this.tables.getDefaultTable();
+  }
+
+  /**
+   * @param defaultTable
+   *          the defaultTable to set
+   */
+  public void setDefaultTable(String defaultTable) {
+    this.tables.setDefaultTable(defaultTable);
+  }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/MappingField.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/MappingField.java
new file mode 100644
index 0000000..96c30ca
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/MappingField.java
@@ -0,0 +1,266 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.mapping;
+
+//OODT imports
+import org.apache.oodt.xmlps.mapping.funcs.MappingFunc;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ *
+ * <p>
+ * A field within a mapping.xml file that defines the relationship between CDEs
+ * and the underlying attributes of a local site's DBMS.
+ * </p>
+ * .
+ */
+public class MappingField {
+
+  private String name;
+
+  private FieldType type;
+
+  private String dbName;
+
+  private String tableName;
+
+  private String constantValue;
+
+  private FieldScope scope;
+
+  private List<MappingFunc> funcs;
+
+  private boolean string;
+
+  /**
+   * @param name
+   * @param type
+   * @param dbName
+   * @param tableName
+   * @param constantValue
+   * @param scope
+   * @param funcs
+   * @param string
+   * @param appendTableName
+   */
+  public MappingField(String name, FieldType type, String dbName,
+      String tableName, String constantValue, FieldScope scope,
+      List<MappingFunc> funcs, boolean string) {
+    super();
+    this.name = name;
+    this.type = type;
+    this.dbName = dbName;
+    this.tableName = tableName;
+    this.constantValue = constantValue;
+    this.scope = scope;
+    this.funcs = funcs;
+    this.string = string;
+  }
+
+  /**
+     *
+     */
+  public MappingField() {
+    this.name = null;
+    this.dbName = null;
+    this.tableName = null;
+    this.constantValue = null;
+    this.scope = null;
+    this.string = false;
+    this.funcs = new Vector<MappingFunc>();
+  }
+
+  /**
+   * @return the constantValue
+   */
+  public String getConstantValue() {
+    return constantValue;
+  }
+
+  /**
+   * @param constantValue
+   *          the constantValue to set
+   */
+  public void setConstantValue(String constantValue) {
+    this.constantValue = constantValue;
+  }
+
+  /**
+   * @return the dbName
+   */
+  public String getDbName() {
+    return dbName;
+  }
+
+  /**
+   * @param dbName
+   *          the dbName to set
+   */
+  public void setDbName(String dbName) {
+    this.dbName = dbName;
+  }
+
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @param name
+   *          the name to set
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * @return the scope
+   */
+  public FieldScope getScope() {
+    return scope;
+  }
+
+  /**
+   * @param scope
+   *          the scope to set
+   */
+  public void setScope(FieldScope scope) {
+    this.scope = scope;
+  }
+
+  /**
+   * @return the tableName
+   */
+  public String getTableName() {
+    return tableName;
+  }
+
+  /**
+   * @param tableName
+   *          the tableName to set
+   */
+  public void setTableName(String tableName) {
+    this.tableName = tableName;
+  }
+
+  /**
+   * @return the type
+   */
+  public FieldType getType() {
+    return type;
+  }
+
+  /**
+   * @param type
+   *          the type to set
+   */
+  public void setType(FieldType type) {
+    this.type = type;
+  }
+
+  /**
+   * @return the funcs
+   */
+  public List<MappingFunc> getFuncs() {
+    return funcs;
+  }
+
+  /**
+   * @param funcs
+   *          the funcs to set
+   */
+  public void setFuncs(List<MappingFunc> funcs) {
+    this.funcs = funcs;
+  }
+
+  @Override
+  public String toString() {
+    StringBuffer rStr = new StringBuffer("[name=");
+    rStr.append(this.name);
+    rStr.append(",dbname=");
+    rStr.append(this.dbName);
+    rStr.append(",constant_value=");
+    rStr.append(this.constantValue);
+    rStr.append(",table_name=");
+    rStr.append(this.tableName);
+    rStr.append(",scope=");
+    rStr.append(this.scope.equals(FieldScope.RETURN) ? "return" : "query");
+    rStr.append(",type=");
+    rStr.append(this.type.equals(FieldType.CONSTANT) ? "constant" : "dynamic");
+    rStr.append(",funcs=");
+    rStr.append(printClassNames(this.funcs));
+    rStr.append(",string=");
+    rStr.append(String.valueOf(this.string));
+    rStr.append("]");
+    return rStr.toString();
+  }
+
+  private String printClassNames(List<MappingFunc> funcs) {
+    StringBuffer buf = new StringBuffer();
+
+    if (funcs == null || (funcs != null && funcs.size() == 0)) {
+      return "";
+    } else {
+      for (Iterator<MappingFunc> i = funcs.iterator(); i.hasNext();) {
+        MappingFunc func = i.next();
+        buf.append(func.getClass().getName());
+        buf.append(",");
+      }
+
+      buf.deleteCharAt(buf.length() - 1);
+
+      return buf.toString();
+    }
+  }
+
+  /**
+   * @return the string
+   */
+  public boolean isString() {
+    return string;
+  }
+
+  /**
+   * @param string
+   *          the string to set
+   */
+  public void setString(boolean string) {
+    this.string = string;
+  }
+
+  /**
+   * If dbname exists and is not empty, it is used as the field name.
+   * If the table exists and is not empty,
+   * return tableName.fieldName, otherwise return fieldName.
+   * @return the column name understood by the local db
+   */
+  public String getLocalName() {
+    String dbColName = getName();
+    if (getDbName() != null && !getDbName().isEmpty())
+      dbColName = getDbName();
+    if (getTableName() == null || getTableName().isEmpty())
+      return dbColName;
+    return getTableName() + "." + dbColName;
+  }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/MappingReader.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/MappingReader.java
new file mode 100644
index 0000000..bca4d6e
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/MappingReader.java
@@ -0,0 +1,201 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.mapping;
+
+//OODT imports
+import org.apache.oodt.commons.xml.XMLUtils;
+import org.apache.oodt.xmlps.mapping.funcs.MappingFunc;
+import org.apache.oodt.xmlps.util.GenericCDEObjectFactory;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ *
+ * <p>
+ * A static final reader class for reading {@link Mapping}s.
+ * </p>
+ * .
+ */
+public final class MappingReader implements MappingReaderMetKeys {
+
+  private MappingReader() throws InstantiationException {
+    throw new InstantiationException("Don't construct reader objects!");
+  }
+
+  public static Mapping getMapping(InputStream is) throws Exception {
+    Document mappingDoc = XMLUtils.getDocumentRoot(is);
+    Mapping map = new Mapping();
+
+    Element rootElem = mappingDoc.getDocumentElement();
+
+    map.setId(rootElem.getAttribute("id"));
+    map.setName(rootElem.getAttribute("name"));
+    readTables(rootElem, map);
+    readFields(rootElem, map);
+
+    return map;
+
+  }
+
+  public static Mapping getMapping(URL mappingUrl) throws Exception {
+    return getMapping(mappingUrl.openStream());
+  }
+
+  public static Mapping getMapping(String filePath) throws Exception {
+    return getMapping(new FileInputStream(filePath));
+
+  }
+
+  private static void readTables(Element rootElem, Mapping map)
+      throws Exception {
+    Element tblsElem = XMLUtils.getFirstElement(TABLES_OUTER_TAG, rootElem);
+    if (tblsElem == null) {
+      throw new Exception("Unable to parse mapping XML file: [" + map.getName()
+          + "]: reason: no defined tables tag element!");
+
+    }
+
+    String defaultTbl = tblsElem.getAttribute("default");
+    // make sure that the default attribute is set
+    if (defaultTbl == null || (defaultTbl != null && defaultTbl.equals(""))) {
+      throw new Exception("Unable to parse mapping XML file: [" + map.getName()
+          + "]: reason: there needs to be a default table defined "
+          + "by the \"default\" attribute!");
+    }
+
+    map.setDefaultTable(defaultTbl);
+
+    // get a list of all the tables, and process them one by one
+    NodeList tableNodes = tblsElem.getElementsByTagName(TABLE_TAG);
+    if (tableNodes != null && tableNodes.getLength() > 0) {
+      for (int i = 0; i < tableNodes.getLength(); i++) {
+        Element tableElem = (Element) tableNodes.item(i);
+        DatabaseTable tbl = readTable(tableElem);
+        if (tbl.getDefaultTableJoin() == null || tbl.getDefaultTableJoin().isEmpty())
+          tbl.setDefaultTableJoin(map.getDefaultTable());
+        map.addTable(tbl.getName(), tbl);
+      }
+    }
+  }
+
+  private static DatabaseTable readTable(Element tableElem) {
+    DatabaseTable tbl = new DatabaseTable();
+    tbl.setJoinFieldName(tableElem.getAttribute(TABLE_ATTR_JOIN_FLD));
+    tbl.setName(tableElem.getAttribute(TABLE_ATTR_NAME));
+    tbl.setDefaultTableJoinFieldName(tableElem
+        .getAttribute(TABLE_ATTR_BASE_TBL_JOIN_FLD));
+    tbl.setDefaultTableJoin(tableElem
+        .getAttribute(TABLE_ATTR_BASE_TBL_JOIN_TABLE));
+    return tbl;
+  }
+
+  private static void readFields(Element rootElem, Mapping map) {
+    NodeList fldNodes = rootElem.getElementsByTagName(FIELD_TAG);
+
+    if (fldNodes != null && fldNodes.getLength() > 0) {
+      for (int i = 0; i < fldNodes.getLength(); i++) {
+        MappingField fld = readField((Element) fldNodes.item(i));
+        if (fld.getTableName() == null || fld.getTableName().isEmpty())
+          fld.setTableName(map.getDefaultTable());
+        map.addField(fld.getName(), fld);
+      }
+    }
+
+  }
+
+  private static MappingField readField(Element fldElem) {
+    MappingField field = new MappingField();
+    field.setTableName(fldElem.getAttribute(FIELD_ATTR_TABLE));
+    field.setName(fldElem.getAttribute(FIELD_ATTR_NAME));
+    field
+        .setType(fldElem.getAttribute(FIELD_ATTR_TYPE).equals("dynamic") ? FieldType.DYNAMIC
+            : FieldType.CONSTANT);
+    field.setString(Boolean.valueOf(fldElem.getAttribute(FIELD_ATTR_STRING)));
+    field.setConstantValue(fldElem.getAttribute(FIELD_ATTR_VALUE));
+    field.setDbName(fldElem.getAttribute(FIELD_ATTR_DBNAME));
+    if (fldElem.getAttribute(FIELD_ATTR_SCOPE) != null
+        && !fldElem.getAttribute(FIELD_ATTR_SCOPE).equals("")) {
+
+      field
+          .setScope(fldElem.getAttribute(FIELD_ATTR_SCOPE).equals("query") ? FieldScope.QUERY
+              : FieldScope.RETURN);
+    }
+
+    field.setFuncs(getTranslateFuncs(fldElem));
+
+    return field;
+
+  }
+
+  private static List<MappingFunc> getTranslateFuncs(Element fldElem) {
+    Element translateElem = XMLUtils.getFirstElement(FIELD_TRANSLATE_TAG,
+        fldElem);
+
+    List<MappingFunc> funcs = new Vector<MappingFunc>();
+
+    if (translateElem != null) {
+      // check for func tags
+      NodeList funcNodes = translateElem.getElementsByTagName(FUNC_TAG);
+      if (funcNodes != null && funcNodes.getLength() > 0) {
+        for (int i = 0; i < funcNodes.getLength(); i++) {
+          Element funcElem = (Element) funcNodes.item(i);
+          funcs.add(getFunc(funcElem));
+        }
+      }
+    }
+
+    return funcs;
+  }
+
+  private static MappingFunc getFunc(Element funcElem) {
+    String funcClass = funcElem.getAttribute(FUNC_ATTR_CLASS);
+    MappingFunc func = GenericCDEObjectFactory
+        .getMappingFuncFromClassName(funcClass);
+
+    if (func != null) {
+      func.configure(getPropsFromElementAttrs(funcElem.getAttributes()));
+    }
+
+    return func;
+  }
+
+  private static Properties getPropsFromElementAttrs(NamedNodeMap map) {
+    Properties props = new Properties();
+
+    if (map != null) {
+      for (int i = 0; i < map.getLength(); i++) {
+        Node mapNode = map.item(i);
+        props.setProperty(mapNode.getNodeName(), mapNode.getNodeValue());
+      }
+    }
+
+    return props;
+  }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/MappingReaderMetKeys.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/MappingReaderMetKeys.java
new file mode 100644
index 0000000..c1f3337
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/MappingReaderMetKeys.java
@@ -0,0 +1,65 @@
+/**
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlps.mapping;
+
+/**
+ * 
+ * <p>
+ * Met Keys for the {@link MappingReader}
+ * </p>.
+ */
+public interface MappingReaderMetKeys {
+
+    public static final String FIELD_TAG = "field";
+
+    public static final String TABLES_OUTER_TAG = "tables";
+
+    public static final String TABLE_TAG = "table";
+
+    public static final String TABLE_ATTR_JOIN_FLD = "join";
+
+    public static final String TABLE_ATTR_BASE_TBL_JOIN_TABLE = "to";
+
+    public static final String TABLE_ATTR_BASE_TBL_JOIN_FLD = "tofld";
+
+    public static final String TABLE_ATTR_NAME = "name";
+
+    public static final String FIELD_ATTR_TYPE = "type";
+
+    public static final String FIELD_ATTR_NAME = "name";
+
+    public static final String FIELD_ATTR_DBNAME = "dbname";
+
+    public static final String FIELD_ATTR_SCOPE = "scope";
+
+    public static final String FIELD_ATTR_VALUE = "value";
+
+    public static final String FIELD_ATTR_TABLE = "table";
+
+    public static final String FIELD_ATTR_STRING = "string";
+
+    public static final String FIELD_TRANSLATE_TAG = "translate";
+
+    public static final String FUNC_TAG = "func";
+
+    public static final String FUNC_ATTR_CLASS = "class";
+
+    public static final String FIELD_ATTR_APPEND_TABLE_NAME = "appendTableName";
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/funcs/MappingFunc.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/funcs/MappingFunc.java
new file mode 100644
index 0000000..f03d52c
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/funcs/MappingFunc.java
@@ -0,0 +1,64 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.mapping.funcs;
+
+//JDK imports
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.xmlps.structs.CDEValue;
+
+/**
+ * 
+ * <p>
+ * A function to convert {@link CDEValue}s from a CDE domain vocabulary into a
+ * SDE domain vocabulary
+ * </p>.
+ */
+public interface MappingFunc {
+
+    /**
+     * Translates the original CDE {@link CDEValue} into a local site's SDE
+     * {@link CDEValue}.
+     * 
+     * @param orig
+     *            The original {@link CDEValue} to translate.
+     * @return The translated {@link CDEValue}.
+     */
+    public CDEValue translate(CDEValue orig);
+
+    /**
+     * Translates the local site's SDE {@link CDEValue} back into its CDE
+     * {@link CDEValue}.
+     * 
+     * @param orig
+     *            The local site's SDE {@link CDEValue} to translate back into
+     *            a CDE.
+     * @return The translated {@link CDEValue}.
+     */
+    public CDEValue inverseTranslate(CDEValue orig);
+
+    /**
+     * Configures the MappingFunc with the appropriate {@link Properties}.
+     * 
+     * @param props
+     *            The {@link Properties} to use to configure the MappingFunc.
+     */
+    public void configure(Properties props);
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/funcs/ReplaceFunc.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/funcs/ReplaceFunc.java
new file mode 100644
index 0000000..80fb41f
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/mapping/funcs/ReplaceFunc.java
@@ -0,0 +1,77 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.mapping.funcs;
+
+//JDK imports
+import java.util.Properties;
+
+//OODT imports
+import org.apache.oodt.xmlps.structs.CDEValue;
+
+/**
+ * 
+ * <p>
+ * Describe your class here
+ * </p>.
+ */
+public class ReplaceFunc implements MappingFunc {
+
+    private String orig;
+
+    private String with;
+
+    public ReplaceFunc() {
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.xmlps.mapping.funcs.MappingFunc#translate(org.apache.oodt.xmlps.structs.CDEValue)
+     */
+    public CDEValue translate(CDEValue orig) {
+        CDEValue cdeVal = new CDEValue(orig.getCdeName(), orig.getVal());
+        String newVal = orig.getVal().equals(this.orig) ? with : orig.getVal();
+        cdeVal.setVal(newVal);
+        return cdeVal;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.xmlps.mapping.funcs.MappingFunc#configure(java.util.Properties)
+     */
+    public void configure(Properties props) {
+        orig = props.getProperty("orig");
+        with = props.getProperty("with");
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.xmlps.mapping.funcs.MappingFunc#inverseTranslate(org.apache.oodt.xmlps.structs.CDEValue)
+     */
+    public CDEValue inverseTranslate(CDEValue orig) {
+        CDEValue cdeVal = new CDEValue(orig.getCdeName(), orig.getVal());
+        String newVal = orig.getVal().equals(this.with) ? this.orig : orig
+                .getVal();
+        cdeVal.setVal(newVal);
+        return cdeVal;
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/product/DBMSExecutor.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/product/DBMSExecutor.java
new file mode 100644
index 0000000..a335d49
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/product/DBMSExecutor.java
@@ -0,0 +1,66 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.product;
+
+//OODT imports
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+import org.apache.oodt.xmlps.structs.CDEResult;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import javax.sql.DataSource;
+
+/**
+ *
+ * <p>
+ * Executes CDE Queries against an underlying JDBC database, backed by Apache
+ * commons-pool and commons-dbcp.
+ * </p>
+ * .
+ */
+public class DBMSExecutor {
+
+  private final DataSource dataSource;
+
+  public DBMSExecutor() {
+    String jdbcUrl = System.getProperty("xmlps.datasource.jdbc.url");
+    String user = System.getProperty("xmlps.datasource.jdbc.user");
+    String pass = System.getProperty("xmlps.datasource.jdbc.pass");
+    String driver = System.getProperty("xmlps.datasource.jdbc.driver");
+    dataSource = DatabaseConnectionBuilder.buildDataSource(user, pass, driver, jdbcUrl);
+  }
+
+  public CDEResult executeLocalQuery(String sql) throws SQLException {
+    try {
+      Connection conn = dataSource.getConnection();
+      Statement statement = conn.createStatement();
+      ResultSet rs = statement.executeQuery(sql);
+      CDEResult result = new CDEResult(rs, conn);
+      return result;
+    } catch (SQLException e) {
+      e.printStackTrace();
+      throw e;
+    }
+    // do not close the Statement or Connection here
+    // call CDEResult#close() to close ResultSet and Connection
+  }
+  
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/product/XMLPSProductHandler.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/product/XMLPSProductHandler.java
new file mode 100644
index 0000000..a8cc44d
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/product/XMLPSProductHandler.java
@@ -0,0 +1,388 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.product;
+
+//OODT imports
+import org.apache.oodt.product.ProductException;
+import org.apache.oodt.product.QueryHandler;
+import org.apache.oodt.xmlps.mapping.DatabaseTable;
+import org.apache.oodt.xmlps.mapping.FieldScope;
+import org.apache.oodt.xmlps.mapping.Mapping;
+import org.apache.oodt.xmlps.mapping.MappingField;
+import org.apache.oodt.xmlps.mapping.MappingReader;
+import org.apache.oodt.xmlps.mapping.funcs.MappingFunc;
+import org.apache.oodt.xmlps.queryparser.Expression;
+import org.apache.oodt.xmlps.queryparser.HandlerQueryParser;
+import org.apache.oodt.xmlps.structs.CDEResult;
+import org.apache.oodt.xmlps.structs.CDEValue;
+import org.apache.oodt.xmlps.util.XMLQueryHelper;
+import org.apache.oodt.xmlquery.QueryElement;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.Stack;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * <p>
+ * An XML configurable version of a Product Server that requires no code
+ * to be written to plug into a local site's relational backend DBMS.
+ * </p>.
+ */
+public class XMLPSProductHandler implements QueryHandler {
+
+    /* our log stream */
+    private static final Logger LOG = Logger
+            .getLogger(XMLPSProductHandler.class.getName());
+
+    protected Mapping mapping;
+
+    private DBMSExecutor executor;
+
+    protected XMLPSProductHandler(String phony) {
+        /* this is to get around invoking the default constructor in sub-classes */
+    }
+
+    public XMLPSProductHandler() throws InstantiationException {
+        String MappingFilePath = System
+                .getProperty("org.apache.oodt.xmlps.xml.mapFilePath");
+
+        if (MappingFilePath == null) {
+            throw new InstantiationException(
+                    "Need to specify path to xml mapping file!");
+        }
+
+        try {
+            mapping = MappingReader.getMapping(MappingFilePath);
+        } catch (Exception e) {
+            throw new InstantiationException(
+                    "Unable to parse mapping xml file: ["
+                            + MappingFilePath + "]: reason: "
+                            + e.getMessage());
+        }
+
+        /* load the db properties file */
+        /*
+         * if one exists: otherwise, don't bother and just print out the SQL to
+         * the console.
+         */
+        String dbPropFilePath = System
+                .getProperty("org.apache.oodt.xmlps.xml.dbPropFilePath");
+        if (dbPropFilePath != null) {
+            try {
+                System.getProperties()
+                        .load(new FileInputStream(dbPropFilePath));
+            } catch (FileNotFoundException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+                throw new InstantiationException(e.getMessage());
+            }
+
+            executor = new DBMSExecutor();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.oodt.product.QueryHandler#query(org.apache.oodt.xmlquery.XMLQuery)
+     */
+    public XMLQuery query(XMLQuery query) throws ProductException {
+        List<QueryElement> whereSet = query.getWhereElementSet();
+        List<QueryElement> selectSet = query.getSelectElementSet();
+        try {
+            translateToDomain(selectSet, true);
+            translateToDomain(whereSet, false);
+        } catch (Exception e) {
+            LOG.severe(e.getMessage());
+            throw new ProductException(e.getMessage());
+        }
+
+        queryAndPackageResults(query);
+
+        return query;
+    }
+
+    public static void main(String[] args) throws Exception {
+        String usage = "XMLPSProductHandler <query>\n";
+
+        if (args.length != 1) {
+            System.err.println(usage);
+            System.exit(1);
+        }
+
+        XMLPSProductHandler handler = new XMLPSProductHandler();
+        XMLQuery q = handler.query(XMLQueryHelper
+                .getDefaultQueryFromQueryString(args[0]));
+        System.out.println(q.getXMLDocString());
+    }
+
+    protected List<QueryElement> getElemNamesFromQueryElemSet(
+            List<QueryElement> origSet) {
+        if (origSet == null || (origSet != null && origSet.size() == 0))
+            return Collections.emptyList();
+
+        List<QueryElement> newSet = new Vector<QueryElement>();
+
+        for (Iterator<QueryElement> i = origSet.iterator(); i.hasNext();) {
+            QueryElement elem = i.next();
+            if (elem.getRole().equals(XMLQueryHelper.ROLE_ELEMNAME)
+                    && !mapping.constantField(elem.getValue())) {
+                newSet.add(elem);
+
+            }
+
+        }
+
+        return newSet;
+
+    }
+
+    protected List<QueryElement> getConstElemNamesFromQueryElemSet(
+            List<QueryElement> origSet) {
+        if (origSet == null || (origSet != null && origSet.size() == 0))
+            return Collections.emptyList();
+
+        List<QueryElement> newSet = new Vector<QueryElement>();
+
+        for (Iterator<QueryElement> i = origSet.iterator(); i.hasNext();) {
+            QueryElement elem = i.next();
+            if (elem.getRole().equals(XMLQueryHelper.ROLE_ELEMNAME)
+                    && mapping.constantField(elem.getValue())) {
+                newSet.add(elem);
+            }
+        }
+
+        return newSet;
+    }
+
+    protected void queryAndPackageResults(XMLQuery query) {
+        Stack<QueryElement> queryStack = HandlerQueryParser
+                .createQueryStack(query.getWhereElementSet());
+        Expression parsedQuery = HandlerQueryParser.parse(queryStack,
+                this.mapping);
+        List<QueryElement> selectNames = getElemNamesFromQueryElemSet(query
+                .getSelectElementSet());
+
+        String querySelectNames = toSQLSelectColumns(selectNames);
+
+        StringBuffer sqlBuf = new StringBuffer("SELECT ");
+        sqlBuf.append(querySelectNames);
+        sqlBuf.append(" FROM ");
+        sqlBuf.append(mapping.getDefaultTable());
+        sqlBuf.append(" ");
+
+        if (mapping.getNumTables() > 0) {
+            List<QueryElement> whereNames = getElemNamesFromQueryElemSet(query.getWhereElementSet());
+            Set<DatabaseTable> requiredTables = getRequiredTables(whereNames, selectNames);
+            for (DatabaseTable tbl : requiredTables) {
+                sqlBuf.append("INNER JOIN ");
+                sqlBuf.append(tbl.getName());
+                sqlBuf.append(" ON ");
+                sqlBuf.append(tbl.getName());
+                sqlBuf.append(".");
+                sqlBuf.append(tbl.getJoinFieldName());
+                sqlBuf.append(" = ");
+                sqlBuf.append(tbl.getDefaultTableJoin());
+                sqlBuf.append(".");
+                sqlBuf.append(tbl.getDefaultTableJoinFieldName());
+                sqlBuf.append(" ");
+            }
+        }
+
+        if(parsedQuery != null){
+            sqlBuf.append(" WHERE ");
+            sqlBuf.append(parsedQuery.evaluate());
+        }
+
+        LOG.log(Level.INFO, sqlBuf.toString());
+
+        if (executor != null) {
+            try {
+                CDEResult res = executor.executeLocalQuery(sqlBuf.toString());
+                res.setOrderedFields(query.getSelectElementSet());
+                res.setMapping(mapping);
+                res.setConstValues(getConstValuesForQuery(query));
+                query.getResults().add(res);
+            } catch (SQLException e) {
+                e.printStackTrace();
+                LOG.log(Level.WARNING, "Error executing sql: ["
+                        + sqlBuf.toString() + "]: Message: " + e.getMessage());
+            }
+        }
+
+    }
+
+    private List<CDEValue> getConstValuesForQuery(XMLQuery query) {
+        List<QueryElement> select = query.getSelectElementSet();
+        List<QueryElement> constNames = getConstElemNamesFromQueryElemSet(select);
+        List<CDEValue> constValues = new ArrayList<CDEValue>();
+        if (constNames != null) {
+            for (QueryElement qe : constNames) {
+                MappingField fld = mapping.getFieldByLocalName(qe.getValue());
+                if (fld != null) {
+                    constValues.add(new CDEValue(fld.getName(), fld.getConstantValue()));
+                }
+            }
+        }
+        return constValues;
+    }
+
+    private String toSQLSelectColumns(List<QueryElement> elems) {
+        if (elems == null || (elems != null && elems.size() == 0))
+            return null;
+
+        StringBuilder buf = new StringBuilder();
+        for (QueryElement qe : elems) {
+            MappingField fld = this.mapping.getFieldByLocalName(qe.getValue());
+            if (fld != null) {
+                buf.append(fld.getLocalName());
+                buf.append(" as ");
+                buf.append(fld.getName());
+                buf.append(",");
+            }
+        }
+
+        buf.deleteCharAt(buf.length() - 1);
+
+        return buf.toString();
+    }
+
+    protected void translateToDomain(List<QueryElement> elemSet,
+            boolean selectSet) throws Exception {
+        // go through each query element: use the mapping fields
+        // to translate the names
+
+        for (Iterator<QueryElement> i = elemSet.iterator(); i.hasNext();) {
+            QueryElement elem = i.next();
+            if (elem.getRole().equals(XMLQueryHelper.ROLE_ELEMNAME)) {
+                // do the translation
+                String elemValue = elem.getValue();
+                MappingField fld = this.mapping.getFieldByName(elemValue);
+                // make sure fld is not null
+                if (fld == null) {
+                    continue;
+                }
+
+                // make sure scope is null, or if it's not null, then it's
+                // FieldScope.QUERY
+
+                if (fld.getScope() != null
+                        && fld.getScope().equals(FieldScope.RETURN)) {
+                    // skip
+                    continue;
+                }
+
+                // check to see if it has a dbname attr, if not, then the name
+                // stays
+                // the same
+                String newFldName = fld.getLocalName();
+
+                elem.setValue(newFldName);
+
+                // now translate the domain vocab if there are translate funcs
+                // present and this isn't the select set
+
+                if (!selectSet && fld.getFuncs() != null
+                        && fld.getFuncs().size() > 0) {
+                    // the next query element should be
+                    // XMLQueryHelper.ROLE_LITERAL
+                    if (!i.hasNext())
+                        break;
+                    QueryElement litElem = i.next();
+                    if (!litElem.getRole().equals(XMLQueryHelper.ROLE_LITERAL)) {
+                        throw new Exception("next query element not "
+                                + XMLQueryHelper.ROLE_LITERAL + "! role is "
+                                + litElem.getRole() + " instead!");
+                    }
+
+                    for (Iterator<MappingFunc> j = fld.getFuncs().iterator(); j
+                            .hasNext();) {
+                        MappingFunc func = j.next();
+                        CDEValue origVal = new CDEValue(fld.getName(),
+                                litElem.getValue());
+                        CDEValue newVal = func.inverseTranslate(origVal);
+                        litElem.setValue(newVal.getVal());
+                    }
+
+                }
+
+            }
+        }
+
+    }
+
+    protected Set<DatabaseTable> getRequiredTables(
+            List<QueryElement> whereElemNames, List<QueryElement> selectElemNames) {
+        Set<DatabaseTable> tables = new HashSet<DatabaseTable>();
+        // add tables from where element set
+        if (whereElemNames != null) {
+            for (QueryElement qe : whereElemNames) {
+                MappingField fld = mapping.getFieldByLocalName(qe.getValue());
+                if (fld != null) {
+                    DatabaseTable t = mapping.getTableByName(fld.getTableName());
+                    if (t != null && !tables.contains(t) && !t.getName().equals(mapping.getDefaultTable())) {
+                        tables.add(t);
+                    }
+                }
+            }
+        }
+        // add tables from select element set
+        if (selectElemNames != null) {
+            for (QueryElement qe : selectElemNames) {
+                MappingField fld = mapping.getFieldByLocalName(qe.getValue());
+                if (fld != null) {
+                    DatabaseTable t = mapping.getTableByName(fld.getTableName());
+                    if (t != null && !tables.contains(t) && !t.getName().equals(mapping.getDefaultTable())) {
+                        tables.add(t);
+                    }
+                }
+            }
+        }
+        // the tables found may be joined on columns from tables we haven't found
+        // yet
+        // add additional required join tables
+        Set<DatabaseTable> moreTables = new HashSet<DatabaseTable>(tables);
+        for (DatabaseTable t : tables) {
+            DatabaseTable join = mapping.getTableByName(t.getDefaultTableJoin());
+            // recursively add all join tables until we get to either
+            // (a) the mapping default table (join == null)
+            // (b) or a table already found (moreTables.contains(join))
+            while (join != null && !moreTables.contains(join) && !join.getName().equals(mapping.getDefaultTable())) {
+                moreTables.add(join);
+                join = mapping.getTableByName(join.getDefaultTableJoin());
+            }
+        }
+        return moreTables;
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/profile/DBMSExecutor.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/profile/DBMSExecutor.java
new file mode 100644
index 0000000..ad24727
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/profile/DBMSExecutor.java
@@ -0,0 +1,173 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.profile;
+
+//OODT imports
+import org.apache.oodt.cas.metadata.Metadata;
+import org.apache.oodt.cas.metadata.util.PathUtils;
+import org.apache.oodt.commons.database.DatabaseConnectionBuilder;
+import org.apache.oodt.profile.EnumeratedProfileElement;
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileAttributes;
+import org.apache.oodt.profile.ProfileElement;
+import org.apache.oodt.profile.ResourceAttributes;
+import org.apache.oodt.xmlps.mapping.FieldType;
+import org.apache.oodt.xmlps.mapping.Mapping;
+import org.apache.oodt.xmlps.mapping.MappingField;
+import org.apache.oodt.xmlps.mapping.funcs.MappingFunc;
+import org.apache.oodt.xmlps.structs.CDEValue;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.sql.DataSource;
+
+/**
+ *
+ * <p>
+ * Executes Profile Queries against an underlying JDBC database, backed by
+ * Apache commons-pool and commons-dbcp.
+ * </p>
+ * .
+ */
+public class DBMSExecutor {
+
+  private final DataSource dataSource;
+
+  private static final Logger LOG = Logger.getLogger(DBMSExecutor.class
+      .getName());
+
+  public DBMSExecutor() {
+    String jdbcUrl = System.getProperty("xmlps.datasource.jdbc.url");
+    String user = System.getProperty("xmlps.datasource.jdbc.user");
+    String pass = System.getProperty("xmlps.datasource.jdbc.pass");
+    String driver = System.getProperty("xmlps.datasource.jdbc.driver");
+    try {
+      Class.forName(driver);
+    } catch (ClassNotFoundException ignore) {
+    }
+
+    this.dataSource = DatabaseConnectionBuilder.buildDataSource(user, pass,
+        driver, jdbcUrl);
+
+  }
+
+  public List<Profile> executeLocalQuery(Mapping map, String sql,
+      String resLocationSpec) throws SQLException {
+    Connection conn = null;
+    Statement statement = null;
+
+    List<Profile> profiles = null;
+
+    try {
+      conn = dataSource.getConnection();
+      statement = conn.createStatement();
+      ResultSet rs = statement.executeQuery(sql);
+
+      profiles = new Vector<Profile>();
+
+      while (rs.next()) {
+        Profile prof = toProfile(rs, map, resLocationSpec);
+        profiles.add(prof);
+      }
+
+    } catch (SQLException e) {
+      e.printStackTrace();
+      throw e;
+    } finally {
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (Exception ignore) {
+        }
+
+        statement = null;
+      }
+
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (Exception ignore) {
+        }
+
+        conn = null;
+      }
+    }
+
+    return profiles;
+
+  }
+
+  private Profile toProfile(ResultSet rs, Mapping map, String resLocationSpec) {
+    Profile profile = new Profile();
+    ResourceAttributes resAttr = profile.getResourceAttributes();
+    ProfileAttributes profAttr = profile.getProfileAttributes();
+    resAttr.setResClass("system.profile");
+    profAttr.setStatusID("active");
+    profAttr.setType("profile");
+
+    Metadata met = new Metadata();
+
+    for (Iterator<String> i = map.getFieldNames().iterator(); i.hasNext();) {
+      String fldName = i.next();
+      MappingField fld = map.getFieldByName(fldName);
+      ProfileElement elem = new EnumeratedProfileElement(profile);
+      elem.setName(fld.getName());
+
+      try {
+        if (fld.getType().equals(FieldType.CONSTANT)) {
+          elem.getValues().add(fld.getConstantValue());
+        } else {
+          String elemDbVal = rs.getString(fld.getDbName());
+          for (Iterator<MappingFunc> j = fld.getFuncs().iterator(); j.hasNext();) {
+            MappingFunc func = j.next();
+            CDEValue origVal = new CDEValue(fld.getName(), elemDbVal);
+            CDEValue newVal = func.translate(origVal);
+            elemDbVal = newVal.getVal();
+          }
+
+          elem.getValues().add(elemDbVal);
+        }
+      } catch (SQLException e) {
+        e.printStackTrace();
+        LOG.log(Level.WARNING, "Unable to obtain field: ["
+            + fld.getLocalName() + "] from result set: message: "
+            + e.getMessage());
+      }
+
+      met.addMetadata(elem.getName(), (String) elem.getValues().get(0));
+
+      profile.getProfileElements().put(fld.getName(), elem);
+    }
+
+    if (resLocationSpec != null) {
+      resAttr.getResLocations().add(
+          PathUtils.replaceEnvVariables(resLocationSpec, met));
+    }
+
+    return profile;
+  }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/profile/XMLPSProfileHandler.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/profile/XMLPSProfileHandler.java
new file mode 100644
index 0000000..4399f83
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/profile/XMLPSProfileHandler.java
@@ -0,0 +1,205 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.profile;
+
+//OODT imports
+import org.apache.oodt.xmlps.mapping.DatabaseTable;
+import org.apache.oodt.xmlps.mapping.MappingReader;
+import org.apache.oodt.xmlps.product.XMLPSProductHandler;
+import org.apache.oodt.xmlps.profile.DBMSExecutor;
+import org.apache.oodt.xmlps.queryparser.Expression;
+import org.apache.oodt.xmlps.queryparser.HandlerQueryParser;
+
+//JDK imports
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.profile.Profile;
+import org.apache.oodt.profile.ProfileException;
+import org.apache.oodt.profile.handlers.ProfileHandler;
+import org.apache.oodt.xmlquery.QueryElement;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+/**
+ * 
+ * <p>
+ * An implementation of a {@link ProfileHandler} that extends the capabilities
+ * of the {@link XMLPSProductHandler}, and uses the XML Specification defined
+ * by the mapping file to represent its field mapping information.
+ * </p>.
+ */
+public class XMLPSProfileHandler extends XMLPSProductHandler implements
+        ProfileHandler {
+
+    private DBMSExecutor executor;
+
+    /* our log stream */
+    private static final Logger LOG = Logger.getLogger(XMLPSProfileHandler.class
+            .getName());
+
+    private String resLocationSpec;
+
+    public XMLPSProfileHandler() throws InstantiationException {
+        super(null);
+        String mappingFilePath = System
+                .getProperty("org.apache.oodt.xmlps.profile.xml.mapFilePath");
+
+        if (mappingFilePath == null) {
+            throw new InstantiationException(
+                    "Need to specify path to xml mapping file!");
+        }
+
+        try {
+            mapping = MappingReader.getMapping(mappingFilePath);
+        } catch (Exception e) {
+            throw new InstantiationException(
+                    "Unable to parse profile mapping xml file: ["
+                            + mappingFilePath + "]: reason: "
+                            + e.getMessage());
+        }
+
+        // load the db properties file
+                // if one exists: otherwise, don't bother and just print out the SQL to
+        // the console.
+        // 
+        String dbPropFilePath = System
+                .getProperty("org.apache.oodt.xmlps.profile.xml.dbPropFilePath");
+        if (dbPropFilePath != null) {
+            try {
+                System.getProperties()
+                        .load(new FileInputStream(dbPropFilePath));
+            } catch (FileNotFoundException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+                throw new InstantiationException(e.getMessage());
+            }
+
+            executor = new DBMSExecutor();
+        }
+
+        this.resLocationSpec = System
+                .getProperty("org.apache.oodt.xmlps.profile.xml.resLocationSpec");
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.profile.handlers.ProfileHandler#findProfiles(org.apache.oodt.xmlquery.XMLQuery)
+     */
+    public List<Profile> findProfiles(XMLQuery query) throws ProfileException {
+        List<QueryElement> whereSet = query.getWhereElementSet();
+        List<QueryElement> selectSet = query.getSelectElementSet();
+        try {
+            translateToDomain(selectSet, true);
+            translateToDomain(whereSet, false);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new ProfileException(e.getMessage());
+        }
+        List<Profile> profs = queryAndPackageProfiles(query);
+        return profs;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.profile.handlers.ProfileHandler#get(java.lang.String)
+     */
+    public Profile get(String id) throws ProfileException {
+        throw new ProfileException("Method not implemented!");
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.profile.handlers.ProfileHandler#getID()
+     */
+    public String getID() {
+        return mapping.getId();
+    }
+
+    protected List<Profile> queryAndPackageProfiles(XMLQuery query) {
+        Stack<QueryElement> queryStack = HandlerQueryParser
+                .createQueryStack(query.getWhereElementSet());
+        Expression parsedQuery = HandlerQueryParser.parse(queryStack,
+                this.mapping);
+        List<Profile> profs = null;
+
+        StringBuffer sqlBuf = new StringBuffer("SELECT *");
+        sqlBuf.append(" FROM ");
+        sqlBuf.append(mapping.getDefaultTable());
+        sqlBuf.append(" ");
+
+        if (mapping.getNumTables() > 0) {
+            for (Iterator<String> i = mapping.getTableNames().iterator(); i
+                    .hasNext();) {
+                String tableName = i.next();
+                if(tableName.equals(mapping.getDefaultTable())) continue;
+                DatabaseTable tbl = mapping.getTableByName(tableName);
+                sqlBuf.append("INNER JOIN ");
+                sqlBuf.append(tbl.getName());
+                sqlBuf.append(" ON ");
+                sqlBuf.append(tbl.getName());
+                sqlBuf.append(".");
+                sqlBuf.append(tbl.getJoinFieldName());
+                sqlBuf.append(" = ");
+                sqlBuf.append(tbl.getDefaultTableJoin());
+                sqlBuf.append(".");
+                sqlBuf.append(tbl.getDefaultTableJoinFieldName());
+                sqlBuf.append(" ");
+            }
+        }
+
+        if (parsedQuery != null) {
+            sqlBuf.append(" WHERE ");
+            sqlBuf.append(parsedQuery.evaluate());
+        }
+
+        LOG.log(Level.INFO, sqlBuf.toString());
+
+        if (executor != null) {
+            try {
+                profs = executor.executeLocalQuery(this.mapping, sqlBuf
+                        .toString(), this.resLocationSpec);
+
+            } catch (SQLException e) {
+                e.printStackTrace();
+                LOG.log(Level.WARNING, "Error executing sql: ["
+                        + sqlBuf.toString() + "]: Message: " + e.getMessage());
+            }
+        }
+
+        return profs;
+    }
+
+    protected void translateToDomain(List<QueryElement> elemSet,
+            boolean selectSet) throws Exception {
+        super.translateToDomain(elemSet, selectSet);
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/AndExpression.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/AndExpression.java
new file mode 100644
index 0000000..dc97b00
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/AndExpression.java
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ *
+ * <p>A logical and expression</p>.
+ */
+public class AndExpression extends LogOpExpression implements ParseConstants{
+
+    public AndExpression(Expression lhs, Expression rhs) {
+        super(SQL_AND, lhs, rhs);
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/ContainsExpression.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/ContainsExpression.java
new file mode 100644
index 0000000..b12ef63
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/ContainsExpression.java
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ * 
+ * A logical contains expression.
+ */
+public class ContainsExpression extends RelOpExpression implements ParseConstants {
+
+    public ContainsExpression(String lhs, Expression literal) {
+        super(SQL_LIKE, lhs, literal);
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/EqualsExpression.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/EqualsExpression.java
new file mode 100644
index 0000000..bfc3aaf
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/EqualsExpression.java
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ * 
+ * Operator equals expression.
+ */
+public class EqualsExpression extends RelOpExpression implements ParseConstants {
+
+    public EqualsExpression(String lhs, Expression literal) {
+        super(SQL_EQUAL, lhs, literal);
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/Expression.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/Expression.java
new file mode 100644
index 0000000..5673354
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/Expression.java
@@ -0,0 +1,34 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ * 
+ * The abstract interface for our expression tree.
+ */
+public interface Expression {
+
+    /**
+     * Defines how to turn this Expression into a String-readable query to an
+     * underlying SQL database.
+     * 
+     * @return A String-readable version of this Expression.
+     */
+    public String evaluate();
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/GreaterThanEqualsExpression.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/GreaterThanEqualsExpression.java
new file mode 100644
index 0000000..c5ce179
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/GreaterThanEqualsExpression.java
@@ -0,0 +1,31 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ * 
+ * Greater than or equals expression.
+ */
+public class GreaterThanEqualsExpression extends RelOpExpression implements
+        ParseConstants {
+
+    public GreaterThanEqualsExpression(String lhs, Expression literal) {
+        super(SQL_GREATER_THAN_OR_EQUAL_TO, lhs, literal);
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/GreaterThanExpression.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/GreaterThanExpression.java
new file mode 100644
index 0000000..42582ef
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/GreaterThanExpression.java
@@ -0,0 +1,31 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ * 
+ * Greater than expression.
+ */
+public class GreaterThanExpression extends RelOpExpression implements
+        ParseConstants {
+
+    public GreaterThanExpression(String lhs, Expression literal) {
+        super(SQL_GREATER_THAN, lhs, literal);
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/HandlerQueryParser.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/HandlerQueryParser.java
new file mode 100644
index 0000000..a3a18fd
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/HandlerQueryParser.java
@@ -0,0 +1,129 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+//JDK imports
+import org.apache.oodt.xmlps.mapping.Mapping;
+import org.apache.oodt.xmlps.mapping.MappingField;
+
+import java.util.List;
+import java.util.Stack;
+
+//OODT imports
+import org.apache.oodt.xmlquery.QueryElement;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+/**
+ * 
+ * Parsers the {@link XMLQuery} and its @link XMLQuery#getWhereElementSet()}
+ * into an {@link Expression} tree.
+ */
+public class HandlerQueryParser implements ParseConstants {
+
+  /**
+   * Calls {@link #parse(Stack, Mapping)} with a null mapping.
+   * 
+   * @param queryStack The {@link XMLQuery#getWhereElementSet()}.
+   * @return The parsed {@link Expression} tree.
+   */
+  public static Expression parse(Stack<QueryElement> queryStack) {
+    return parse(queryStack, null);
+  }
+
+  /**
+   * 
+   * Parses the {@link XMLQuery#getWhereElementSet()} using the provided
+   * <param>map</param>.
+   * 
+   * @param queryStack The {@link XMLQuery#getWhereElementSet()}
+   * @param map The provided ontological mapping.
+   * @return The parsed {@link Expression} tree.
+   */
+  public static Expression parse(Stack<QueryElement> queryStack, Mapping map) {
+
+    QueryElement qe = null;
+
+    if (!queryStack.empty()) {
+      qe = (QueryElement) queryStack.pop();
+    } else
+      return null;
+
+    if (qe.getRole().equalsIgnoreCase(XMLQUERY_LOGOP)) {
+
+      String logOpType = qe.getValue();
+      if (logOpType.equalsIgnoreCase(XMLQUERY_AND)) {
+        return new AndExpression(parse(queryStack, map), parse(queryStack, map));
+      } else if (logOpType.equalsIgnoreCase(XMLQUERY_OR)) {
+        return new OrExpression(parse(queryStack, map), parse(queryStack, map));
+      } else
+        return null;
+
+    } else if (qe.getRole().equalsIgnoreCase(XMLQUERY_RELOP)) {
+      String relOpType = qe.getValue();
+      QueryElement rhsQE = (QueryElement) queryStack.pop();
+      QueryElement lhsQE = (QueryElement) queryStack.pop();
+
+      String rhsVal = (String) rhsQE.getValue();
+      String lhsVal = (String) lhsQE.getValue();
+
+      if (map != null) {
+        // convert the right hand side, using
+        // the local name
+        MappingField fld = map.getFieldByLocalName(lhsVal);
+        if (fld != null) {
+          if (fld.isString()) {
+            rhsVal = "'" + rhsVal + "'";
+          }
+        }
+      }
+
+      if (relOpType.equalsIgnoreCase(XMLQUERY_EQUAL)) {
+        return new EqualsExpression(lhsVal, new Literal(rhsVal));
+      } else if (relOpType.equalsIgnoreCase(XMLQUERY_LIKE)) {
+        return new ContainsExpression(lhsVal, new WildcardLiteral(rhsVal));
+      } else if (relOpType.equalsIgnoreCase(XMLQUERY_GREATER_THAN)) {
+        return new GreaterThanExpression(lhsVal, new Literal(rhsVal));
+      } else if (relOpType.equalsIgnoreCase(XMLQUERY_GREATER_THAN_OR_EQUAL_TO)) {
+        return new GreaterThanEqualsExpression(lhsVal, new Literal(rhsVal));
+      } else if (relOpType.equalsIgnoreCase(XMLQUERY_LESS_THAN)) {
+        return new LessThanExpression(lhsVal, new Literal(rhsVal));
+      } else if (relOpType.equalsIgnoreCase(XMLQUERY_LESS_THAN_OR_EQUAL_TO)) {
+        return new LessThanEqualsExpression(lhsVal, new Literal(rhsVal));
+      } else
+        return null;
+
+    } else if (qe.getRole().equalsIgnoreCase(XMLQUERY_LITERAL)) {
+      return new Literal(qe.getValue());
+    } else
+      return null;
+
+  }
+
+  public static Stack<QueryElement> createQueryStack(List<QueryElement> l) {
+
+    Stack<QueryElement> ret = new Stack<QueryElement>();
+
+    for (int i = 0; i < l.size(); i++) {
+      ret.push(l.get(i));
+    }
+
+    return ret;
+
+  }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/LessThanEqualsExpression.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/LessThanEqualsExpression.java
new file mode 100644
index 0000000..46e6975
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/LessThanEqualsExpression.java
@@ -0,0 +1,33 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ * 
+ * <p>
+ *  A less than or equals expression.
+ * </p>.
+ */
+public class LessThanEqualsExpression extends RelOpExpression implements
+        ParseConstants {
+
+    public LessThanEqualsExpression(String lhs, Expression literal) {
+        super(SQL_LESS_THAN_OR_EQUAL_TO, lhs, literal);
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/LessThanExpression.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/LessThanExpression.java
new file mode 100644
index 0000000..2184f19
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/LessThanExpression.java
@@ -0,0 +1,33 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ * 
+ * <p>
+ * A less than expression.
+ * </p>.
+ */
+public class LessThanExpression extends RelOpExpression implements
+        ParseConstants {
+
+    public LessThanExpression(String lhs, Expression literal) {
+        super(SQL_LESS_THAN, lhs, literal);
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/Literal.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/Literal.java
new file mode 100644
index 0000000..4ac3de5
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/Literal.java
@@ -0,0 +1,39 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ *
+ * A value literal.
+ */
+public class Literal implements Expression{
+    
+    protected String val;
+    
+    public Literal(String val){
+        this.val = val;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.oodt.xmlps.queryparser.Expression#evaluate()
+     */
+    public String evaluate() {
+        return val;
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/LogOpExpression.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/LogOpExpression.java
new file mode 100644
index 0000000..ae5a29f
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/LogOpExpression.java
@@ -0,0 +1,79 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ * 
+ * A logical expression with a left-hand side 
+ * and right hind-side {@link Expression}.
+ * 
+ */
+public class LogOpExpression implements Expression {
+
+    private String logop;
+
+    private Expression lhs;
+
+    private Expression rhs;
+    
+    
+
+    public LogOpExpression(String logop, Expression lhs, Expression rhs) {
+        this.lhs = lhs;
+        this.rhs = rhs;
+        this.logop = logop;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.xmlps.queryparser.Expression#evaluate()
+     */
+    public String evaluate() {
+        return "(" + lhs.evaluate() + " " + logop + " " + rhs.evaluate() + ")";
+    }
+
+    /**
+     * @return the lhs
+     */
+    public Expression getLhs() {
+        return lhs;
+    }
+
+    /**
+     * @param lhs the lhs to set
+     */
+    public void setLhs(Expression lhs) {
+        this.lhs = lhs;
+    }
+
+    /**
+     * @return the rhs
+     */
+    public Expression getRhs() {
+        return rhs;
+    }
+
+    /**
+     * @param rhs the rhs to set
+     */
+    public void setRhs(Expression rhs) {
+        this.rhs = rhs;
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/OrExpression.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/OrExpression.java
new file mode 100644
index 0000000..ff5531e
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/OrExpression.java
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ *
+ * An Or expression.
+ */
+public class OrExpression extends LogOpExpression implements ParseConstants{
+
+    public OrExpression(Expression lhs, Expression rhs) {
+        super(SQL_OR, lhs, rhs);
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/ParseConstants.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/ParseConstants.java
new file mode 100644
index 0000000..abba47b
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/ParseConstants.java
@@ -0,0 +1,65 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ *
+ * Constant met keys used in parsing the XMLQuery.
+ */
+public interface ParseConstants {
+    
+    public final static String XMLQUERY_LOGOP = "LOGOP";
+    
+    public final static String XMLQUERY_AND = "AND";
+    
+    public final static String XMLQUERY_OR = "OR";
+    
+    public final static String XMLQUERY_RELOP = "RELOP";
+    
+    public final static String XMLQUERY_EQUAL = "EQ";
+    
+    public final static String XMLQUERY_LIKE = "LIKE";
+    
+    public final static String XMLQUERY_GREATER_THAN = "GT";
+    
+    public final static String XMLQUERY_GREATER_THAN_OR_EQUAL_TO = "GE";
+    
+    public final static String XMLQUERY_LESS_THAN = "LT";
+    
+    public final static String XMLQUERY_LESS_THAN_OR_EQUAL_TO = "LE";
+    
+    public final static String XMLQUERY_LITERAL = "LITERAL";
+    
+    
+    public final static String SQL_LIKE = "LIKE";
+    
+    public final static String SQL_EQUAL = "=";
+    
+    public final static String SQL_AND = "AND";
+    
+    public final static String SQL_OR = "OR";
+    
+    public final static String SQL_GREATER_THAN_OR_EQUAL_TO = ">=";
+    
+    public final static String SQL_GREATER_THAN = ">";
+    
+    public final static String SQL_LESS_THAN = "<";
+    
+    public final static String SQL_LESS_THAN_OR_EQUAL_TO = "<=";
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/RelOpExpression.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/RelOpExpression.java
new file mode 100644
index 0000000..9be99ff
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/RelOpExpression.java
@@ -0,0 +1,75 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ * 
+ * A relational operator.
+ */
+public class RelOpExpression implements Expression {
+
+    private String relop;
+
+    private Expression literal;
+
+    private String lhs;
+
+    public RelOpExpression(String relop, String lhs, Expression literal) {
+        this.relop = relop;
+        this.lhs = lhs;
+        this.literal = literal;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.xmlps.queryparser.Expression#evaluate()
+     */
+    public String evaluate() {
+        return lhs + " " + relop + " " + literal.evaluate();
+    }
+
+    /**
+     * @return the lhs
+     */
+    public String getLhs() {
+        return lhs;
+    }
+
+    /**
+     * @param lhs the lhs to set
+     */
+    public void setLhs(String lhs) {
+        this.lhs = lhs;
+    }
+
+    /**
+     * @return the literal
+     */
+    public Expression getLiteral() {
+        return literal;
+    }
+
+    /**
+     * @param literal the literal to set
+     */
+    public void setLiteral(Expression literal) {
+        this.literal = literal;
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/WildcardLiteral.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/WildcardLiteral.java
new file mode 100644
index 0000000..7c97c2a
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/queryparser/WildcardLiteral.java
@@ -0,0 +1,46 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+/**
+ * 
+ * A wildcard literal.
+ */
+public class WildcardLiteral extends Literal {
+
+    /**
+     * @param val
+     */
+    public WildcardLiteral(String val) {
+        super(val);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.oodt.xmlps.queryparser.Literal#evaluate()
+     */
+    @Override
+    public String evaluate() {
+        if(val.startsWith("'")){
+          return "'%"+val.substring(1, val.length()-1)+"%'";
+        }
+        else return "%" + val + "%";
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/structs/CDEResult.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/structs/CDEResult.java
new file mode 100644
index 0000000..21ba7a8
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/structs/CDEResult.java
@@ -0,0 +1,174 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.structs;
+
+//OODT imports
+import org.apache.oodt.xmlps.mapping.Mapping;
+import org.apache.oodt.xmlps.mapping.MappingField;
+import org.apache.oodt.xmlps.mapping.funcs.MappingFunc;
+import org.apache.oodt.xmlquery.QueryElement;
+import org.apache.oodt.xmlquery.Result;
+
+//JDK imports
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+/**
+ * A {@link Result} that wraps a {@link ResultSet} and returns rows as Strings,
+ * applying {@link MappingFuncs} if a {@link Mapping} is provided, and appending
+ * constant fields if a {@link List} of {@link CDEValue}s is provided.
+ */
+public class CDEResult extends Result {
+
+  private static final long serialVersionUID = 1L;
+
+  private static final String ROW_TERMINATOR = "$";
+
+  private final ResultSet rs;
+  private final Connection con;
+  private Mapping mapping;
+  private List<CDEValue> constValues;
+  private List<QueryElement> orderedFields;
+
+  public CDEResult(ResultSet rs, Connection con) {
+    this.rs = rs;
+    this.con = con;
+    setMimeType("text/plain");
+  }
+  
+  public void setOrderedFields(List<QueryElement> orderedFields){
+    this.orderedFields = orderedFields;    
+  }
+
+  public void setMapping(Mapping mapping) {
+    this.mapping = mapping;
+  }
+
+  public void setConstValues(List<CDEValue> constValues) {
+    this.constValues = constValues;
+  }
+
+  @Override
+  public InputStream getInputStream() throws IOException {
+    if (rs == null || con == null)
+      throw new IOException("InputStream not ready, ResultSet or Connection is null!");
+    return new CDEResultInputStream(this);
+  }
+
+  @Override
+  public long getSize() {
+    return -1;
+  }
+
+ public void close() throws SQLException {
+    if (rs != null)
+      rs.close();
+    if (con != null)
+      con.close();
+  }
+
+  public String getNextRowAsString() throws SQLException {
+    if (rs.next()) {
+      CDERow row = createCDERow();
+      if (mapping != null)
+        applyMappingFuncs(row);
+      if (this.constValues != null && 
+          ((this.orderedFields == null) || 
+          (this.orderedFields != null && this.orderedFields.size() == 0))){
+        addConstValues(row);
+      }
+      // if there is some kind of configurable response writer,
+      // here would be a nice place to put it...
+      return row.toString() + ROW_TERMINATOR;
+    }
+    return null;
+  }
+
+  private CDERow createCDERow() throws SQLException {
+    CDERow row = new CDERow();
+    ResultSetMetaData met = rs.getMetaData();
+    int count = met.getColumnCount();
+    Map<String, CDEValue> dbValMap = new HashMap<String, CDEValue>();
+    Map<String, CDEValue> constValMap = cdeListToMap(this.constValues);
+    List<CDEValue> orderedDbVals = new Vector<CDEValue>();
+    
+    for (int i = 1; i <= count; i++) {
+      // since the SQL query was built with "SELECT ${fieldlocalname} as ${fieldname}"
+      // we know that ResultSet column names equal CDE field names
+      // and appear in the correct order as well
+      String fieldLocalColName = met.getColumnLabel(i);
+      String colValue = rs.getString(i);
+      CDEValue val = new CDEValue(fieldLocalColName, colValue);
+      dbValMap.put(fieldLocalColName, val);
+      orderedDbVals.add(val);
+    }
+    
+    // now have the constant values, and the db values, order the row
+    if(this.orderedFields != null){
+      for(QueryElement qe: this.orderedFields){
+        String qeCdeVal = this.mapping.getFieldByLocalName(qe.getValue()).getName();
+        if(dbValMap.containsKey(qeCdeVal)){
+          row.getVals().add(dbValMap.get(qeCdeVal));
+        }
+        else if(constValMap.containsKey(qeCdeVal)){
+          row.getVals().add(constValMap.get(qeCdeVal));
+        }
+      }
+    }
+    else row.getVals().addAll(orderedDbVals);
+    
+    
+    return row;
+  }
+
+  private void applyMappingFuncs(CDERow row) {
+    for (CDEValue value : row.getVals()) {
+      MappingField fld = mapping.getFieldByName(value.getCdeName());
+      if (fld != null) {
+        for (MappingFunc func : fld.getFuncs()) {
+          CDEValue newValue = func.translate(value);
+          value.setVal(newValue.getVal());
+        }
+      }
+    }
+  }
+  
+  private void addConstValues(CDERow row) {
+    row.getVals().addAll(constValues);
+  }  
+  
+  private Map<String, CDEValue> cdeListToMap(List<CDEValue> vals){
+    Map<String, CDEValue> map = new HashMap<String, CDEValue>();
+    if(vals != null){
+      for(CDEValue val: vals){
+        map.put(val.getCdeName(), val);
+      }
+    }
+    
+    return map;
+  }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/structs/CDEResultInputStream.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/structs/CDEResultInputStream.java
new file mode 100644
index 0000000..3547d40
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/structs/CDEResultInputStream.java
@@ -0,0 +1,115 @@
+/**
+ * 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.
+ */
+package org.apache.oodt.xmlps.structs;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.SQLException;
+
+class CDEResultInputStream extends InputStream {
+
+  private final CDEResult res;
+  private ByteArrayInputStream rowStream;
+
+  public CDEResultInputStream(CDEResult res) {
+    this.res = res;
+  }
+
+  private boolean fetchNextRow() throws IOException {
+    String s = null;
+    try {
+      s = res.getNextRowAsString();
+    } catch (SQLException e) {
+    }
+    if (rowStream != null)
+      rowStream.close();
+    rowStream = s == null ? null : new ByteArrayInputStream(s.getBytes("UTF-8"));
+    return rowStream != null;
+  }
+
+  private boolean ensureOpen() throws IOException {
+    if (rowStream == null || rowStream.available() <= 0)
+      return fetchNextRow();
+    return true;
+  }
+
+  @Override
+  public int read() throws IOException {
+    return ensureOpen() ? rowStream.read() : -1;
+  }
+
+  @Override
+  public int read(byte[] b, int off, int len) throws IOException {
+    if (!ensureOpen())
+      return -1;
+
+    if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length)
+        || ((off + len) < 0)) {
+      throw new IndexOutOfBoundsException();
+    } else if (len == 0) {
+      return 0;
+    }
+
+    int total = 0;
+    int n = rowStream.read(b, off, len);
+    total += n;
+    while (n != -1 && total < len) {
+      if (!fetchNextRow())
+        return total;
+      n = rowStream.read(b, off + total, len - total);
+      total += n;
+    }
+    return total;
+  }
+
+  @Override
+  public void close() throws IOException {
+    if (rowStream != null)
+      rowStream.close();
+    rowStream = null;
+
+    try {
+      res.close();
+    } catch (SQLException e) {
+      throw new IOException(e);
+    }
+  }
+
+  @Override
+  public synchronized int available() throws IOException {
+    if (rowStream == null)
+      return 0;
+    return rowStream.available();
+  }
+
+  @Override
+  public synchronized void mark(int readlimit) {
+    throw new UnsupportedOperationException("Mark not supported");
+  }
+
+  @Override
+  public synchronized void reset() throws IOException {
+    throw new UnsupportedOperationException("Reset not supported");
+  }
+
+  @Override
+  public boolean markSupported() {
+    return false;
+  }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/structs/CDERow.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/structs/CDERow.java
new file mode 100644
index 0000000..80a3cdf
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/structs/CDERow.java
@@ -0,0 +1,72 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.structs;
+
+//JDK imports
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+
+/**
+ * 
+ * <p>
+ * A row of {@link CDEValue}s, returned
+ * from a query against a Product Server.
+ * </p>.
+ */
+public class CDERow {
+
+    private List<CDEValue> vals;
+    
+    private static final String COL_SEPARATOR = "\t";
+
+    public CDERow() {
+        vals = new Vector<CDEValue>();
+    }
+
+    public String toString() {
+        StringBuffer rStr = new StringBuffer();
+        if (vals != null && vals.size() > 0) {
+            for (Iterator<CDEValue> i = vals.iterator(); i.hasNext();) {
+                CDEValue v = i.next();
+                rStr.append(v.getVal() + COL_SEPARATOR);
+            }
+
+            rStr.deleteCharAt(rStr.length() - 1);
+        }
+
+        return rStr.toString();
+    }
+
+    /**
+     * @return the vals
+     */
+    public List<CDEValue> getVals() {
+        return vals;
+    }
+
+    /**
+     * @param vals
+     *            the vals to set
+     */
+    public void setVals(List<CDEValue> vals) {
+        this.vals = vals;
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/structs/CDEValue.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/structs/CDEValue.java
new file mode 100644
index 0000000..43a8400
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/structs/CDEValue.java
@@ -0,0 +1,74 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.structs;
+
+/**
+ * 
+ * <p>
+ * A cde name and a value returned from a query against a Product Server
+ * </p>.
+ */
+public class CDEValue {
+
+    private String cdeName;
+
+    private String val;
+
+    public CDEValue() {
+
+    }
+
+    public CDEValue(String cdeName, String val) {
+        this.cdeName = cdeName;
+        this.val = val;
+    }
+
+    /**
+     * @return the cdeName
+     */
+    public String getCdeName() {
+        return cdeName;
+    }
+
+    /**
+     * @param cdeName
+     *            the cdeName to set
+     */
+    public void setCdeName(String cdeName) {
+        this.cdeName = cdeName;
+    }
+
+    /**
+     * @return the val
+     */
+    public String getVal() {
+        return val;
+    }
+
+    /**
+     * @param val
+     *            the val to set
+     */
+    public void setVal(String val) {
+        this.val = val;
+    }
+
+    public String toString(){
+        return "[cdeName="+this.cdeName+",val="+this.val+"]";
+    }
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/util/GenericCDEObjectFactory.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/util/GenericCDEObjectFactory.java
new file mode 100644
index 0000000..bd32cac
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/util/GenericCDEObjectFactory.java
@@ -0,0 +1,69 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.util;
+
+//JDK imports
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//OODT imports
+import org.apache.oodt.xmlps.mapping.funcs.MappingFunc;
+
+/**
+ * 
+ * <p>
+ * An object factory for creating CDE objects.
+ * </p>.
+ */
+public final class GenericCDEObjectFactory {
+
+    /* our log stream */
+    private static final Logger LOG = Logger
+            .getLogger(GenericCDEObjectFactory.class.getName());
+
+    private GenericCDEObjectFactory() throws InstantiationException {
+        throw new InstantiationException("Don't construct object factories!");
+    }
+
+    public static MappingFunc getMappingFuncFromClassName(String className) {
+        MappingFunc func = null;
+        Class funcClazz;
+        try {
+            funcClazz = Class.forName(className);
+            func = (MappingFunc) funcClazz.newInstance();
+            return func;
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Unable to load class: [" + className
+                    + "]: class not found! message: " + e.getMessage(), e);
+            return null;
+        } catch (InstantiationException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Unable to load class: [" + className
+                    + "]: cannot instantiate! message: " + e.getMessage(), e);
+            return null;
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+            LOG.log(Level.WARNING, "Unable to load class: [" + className
+                    + "]: illegal access! message: " + e.getMessage(), e);
+            return null;
+        }
+
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/util/XMLQueryHelper.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/util/XMLQueryHelper.java
new file mode 100644
index 0000000..c414102
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/util/XMLQueryHelper.java
@@ -0,0 +1,38 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.util;
+
+//OODT imports
+import org.apache.oodt.xmlquery.XMLQuery;
+
+/**
+ * 
+ * <p>
+ * Helper methods to handle those pesky {@link XMLQuery} objects.
+ * </p>.
+ */
+public final class XMLQueryHelper implements XMLQueryKeys{
+
+    public static XMLQuery getDefaultQueryFromQueryString(String query) {
+        return new XMLQuery(query/* keywordQuery */, ""/* id */,
+                ""/* title */, ""/* desc */, ""/* ddId */,
+                ""/* resultModeId */, ""/* propType */, ""/* propLevels */,
+                XMLQuery.DEFAULT_MAX_RESULTS/* maxResults */);
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/util/XMLQueryKeys.java b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/util/XMLQueryKeys.java
new file mode 100644
index 0000000..b15e3f6
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/main/java/org/apache/oodt/xmlps/util/XMLQueryKeys.java
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.util;
+
+/**
+ *
+ * <p>Met Keys for dealing with {@link org.apache.oodt.xmlquery.XMLQuery}s</p>.
+ */
+public interface XMLQueryKeys {
+    
+    public static final String ROLE_LITERAL = "LITERAL";
+    
+    public static final String ROLE_ELEMNAME = "elemName";
+
+}
diff --git a/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/mapping/TestMappingReader.java b/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/mapping/TestMappingReader.java
new file mode 100644
index 0000000..bddc7ed
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/mapping/TestMappingReader.java
@@ -0,0 +1,162 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.mapping;
+
+//APACHE imports
+import org.apache.oodt.xmlps.mapping.funcs.MappingFunc;
+import org.apache.oodt.xmlps.structs.CDEValue;
+
+import java.io.InputStream;
+
+import junit.framework.TestCase;
+
+/**
+ * Test suite for XMLPS xml map file reader.
+ */
+public class TestMappingReader extends TestCase {
+
+    private static final String expectedName = "Test Query Handler";
+
+    private static final String expectedId = "urn:oodt:xmlps:testps";
+
+    private static final int expectedFields = 43;
+
+    private static final String SPECIMEN_CONTACT_EMAIL_TEXT = "SPECIMEN_CONTACT-EMAIL_TEXT";
+
+    private static final String SPECIMEN_COLLECTED_CODE = "SPECIMEN_COLLECTED_CODE";
+
+    private static final String SPECIMEN_TISSUE_ORGAN_SITE_CODE = "SPECIMEN_TISSUE_ORGAN-SITE_CODE";
+
+    private static final String CONTACT_PERSON_EMAIL = "Brendan.Phalan@med.nyu.edu";
+
+    private static final String expectedDefaultTable = "baseline";
+
+    private static final String expectedJoinFld = "patient_id";
+
+    public TestMappingReader() {
+
+    }
+
+    public void testReadTables() {
+        Mapping mapping = getMappingOrFail();
+        assertNotNull(mapping);
+
+        assertEquals(1, mapping.getNumTables());
+        assertNull(mapping.getTableByName("baseline"));
+        assertNotNull(mapping.getTableByName("specimen"));
+        assertNotNull(mapping.getDefaultTable());
+        assertEquals(expectedDefaultTable, mapping.getDefaultTable());
+        assertEquals(expectedJoinFld, mapping.getTableByName("specimen")
+                .getJoinFieldName());
+    }
+
+    public void testReadBasicInfo() {
+        Mapping mapping = getMappingOrFail();
+
+        assertNotNull(mapping);
+        assertEquals(expectedName, mapping.getName());
+        assertEquals(expectedId, mapping.getId());
+    }
+
+    public void testReadFields() {
+        Mapping mapping = getMappingOrFail();
+        assertNotNull(mapping);
+        assertEquals(expectedFields, mapping.getNumFields());
+        containsSpecimenContactEmailTextOrFail(mapping);
+        containsSpecimenCollectedCodeOrFail(mapping);
+
+    }
+
+    public void testReadFuncs() {
+        Mapping mapping = getMappingOrFail();
+        assertNotNull(mapping);
+        assertTrue(mapping.getNumFields() > 0);
+
+        MappingField funcField = mapping
+                .getFieldByName(SPECIMEN_TISSUE_ORGAN_SITE_CODE);
+        assertNotNull(funcField);
+
+        assertNotNull(funcField.getFuncs());
+        assertEquals(funcField.getFuncs().size(), 1);
+
+        MappingFunc func = funcField.getFuncs().get(0);
+        CDEValue val = new CDEValue("test", "16");
+        CDEValue result = func.translate(val);
+        assertNotNull(result);
+        assertEquals(result.getVal(), "1");
+        val.setVal("235");
+        result = func.translate(val);
+        assertEquals(result.getVal(), "235");
+    }
+
+    public void testMappingFieldGetLocalName() {
+        Mapping mapping = getMappingOrFail("test-same-col-name-ps.xml");
+
+        MappingField fieldOnly = mapping.getFieldByName("field_only");
+        assertEquals("defaultTable.field_only", fieldOnly.getLocalName());
+
+        MappingField fieldWithTable = mapping.getFieldByName("field_with_table");
+        assertEquals("anotherTable.field_db", fieldWithTable.getLocalName());
+
+        MappingField fieldUseDefault = mapping.getFieldByName("field_use_default");
+        assertEquals("defaultTable.field_db", fieldUseDefault.getLocalName());
+    }
+
+    private void containsSpecimenCollectedCodeOrFail(Mapping mapping) {
+
+        MappingField fld = mapping.getFieldByName(SPECIMEN_COLLECTED_CODE);
+        assertNotNull(fld);
+        assertTrue(fld.getType().equals(FieldType.DYNAMIC));
+        assertFalse(fld.getType().equals(FieldType.CONSTANT));
+        assertEquals("specimen_collected", fld.getDbName());
+        assertEquals("specimen", fld.getTableName());
+
+    }
+
+    private void containsSpecimenContactEmailTextOrFail(Mapping mapping) {
+        MappingField fld = mapping.getFieldByName(SPECIMEN_CONTACT_EMAIL_TEXT);
+        assertNotNull(fld);
+        assertEquals(fld.getConstantValue(), CONTACT_PERSON_EMAIL);
+        assertTrue(fld.getType().equals(FieldType.CONSTANT));
+        assertFalse(fld.getType().equals(FieldType.DYNAMIC));
+        assertTrue(fld.getScope().equals(FieldScope.RETURN));
+        assertFalse(fld.getScope().equals(FieldScope.QUERY));
+
+    }
+
+    private Mapping getMappingOrFail() {
+      return getMappingOrFail("test-ps.xml");
+    }
+
+    private Mapping getMappingOrFail(String mapfile) {
+        Mapping mapping = null;
+
+        InputStream configFileIs = TestMappingReader.class
+                .getResourceAsStream(mapfile);
+
+        try {
+            mapping = MappingReader.getMapping(configFileIs);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+
+        return mapping;
+    }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/product/TestXMLPSProductHandler.java b/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/product/TestXMLPSProductHandler.java
new file mode 100644
index 0000000..cc2451c
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/product/TestXMLPSProductHandler.java
@@ -0,0 +1,184 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.product;
+
+//JDK imports
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+//APACHE imports
+import org.apache.oodt.xmlps.mapping.DatabaseTable;
+import org.apache.oodt.xmlps.util.XMLQueryHelper;
+import org.apache.oodt.xmlquery.QueryElement;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * Tests the XMLPS product handler.
+ */
+public class TestXMLPSProductHandler extends TestCase {
+
+    private static final String expectedSpecimenFldName = "specimen.specimen_collected";
+
+    private XMLPSProductHandler handler;
+
+    private static final String specimenCollectedCodeField = "SPECIMEN_COLLECTED_CODE";
+
+    private static final String studyProtocolIdField = "STUDY_PROTOCOL_ID";
+    
+    private static final String unconstrainedQuery = "RETURN = STUDY_PARTICIPANT_ID";
+
+    private static final String queryStr = specimenCollectedCodeField
+            + " = 3 AND " + studyProtocolIdField + " = 71 AND RETURN = "
+            + specimenCollectedCodeField;
+
+    public void setUp() {
+        System.setProperty("org.apache.oodt.xmlps.xml.mapFilePath",
+                "./src/test/resources/test-ps.xml");
+
+        try {
+            handler = new XMLPSProductHandler();
+        } catch (InstantiationException e) {
+            fail("Can't construct test suite: exception building test handler");
+        }
+    }
+    
+    public void testAllowUnConstrainedQuery(){
+        XMLQuery query = XMLQueryHelper
+             .getDefaultQueryFromQueryString(unconstrainedQuery);
+        
+        
+        assertNotNull(query);
+        assertNotNull(query.getWhereElementSet());
+        assertTrue(query.getWhereElementSet().size() == 0);
+        assertNotNull(query.getSelectElementSet());
+        assertTrue(query.getSelectElementSet().size() == 1);
+        
+        try{
+            handler.translateToDomain(query.getSelectElementSet(), true);
+        }
+        catch(Exception e){
+            fail(e.getMessage());
+        }
+        
+        try{
+            handler.queryAndPackageResults(query);
+        }
+        catch(Exception e){
+            fail(e.getMessage());
+        }
+        
+    }
+
+    public void testDomainTranslationWhereSet() {
+        XMLQuery query = XMLQueryHelper
+                .getDefaultQueryFromQueryString(queryStr);
+
+        assertNotNull(query);
+        assertNotNull(query.getWhereElementSet());
+        assertEquals(7, query.getWhereElementSet().size());
+
+        try {
+            handler.translateToDomain(query.getWhereElementSet(), false);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+        List<QueryElement> elemNames = handler
+                .getElemNamesFromQueryElemSet(query.getWhereElementSet());
+        assertNotNull(elemNames);
+        assertEquals(1, elemNames.size()); // only 1 b/c one field is constant
+
+        boolean gotSpecCollected = false;
+        for (Iterator<QueryElement> i = elemNames.iterator(); i.hasNext();) {
+            QueryElement elem = i.next();
+            if (elem.getValue().equals("specimen.specimen_collected")) {
+                gotSpecCollected = true;
+            }
+
+        }
+
+        assertTrue(gotSpecCollected);
+
+    }
+
+    public void testDomainTranslationSelectSet() {
+
+        XMLQuery query = XMLQueryHelper
+                .getDefaultQueryFromQueryString(queryStr);
+
+        assertNotNull(query);
+        assertNotNull(query.getSelectElementSet());
+        assertEquals(1, query.getSelectElementSet().size());
+        try {
+            handler.translateToDomain(query.getSelectElementSet(), true);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+        assertNotNull(query.getSelectElementSet());
+        assertEquals(1, query.getSelectElementSet().size());
+        assertNotNull(query.getSelectElementSet().get(0));
+        QueryElement elem = (QueryElement) query.getSelectElementSet().get(0);
+        assertNotNull(elem.getValue());
+        assertEquals("Expected: [" + expectedSpecimenFldName + "]: got: ["
+                + elem.getValue() + "]", elem.getValue(),
+                expectedSpecimenFldName);
+
+    }
+    
+    public void testGetRequiredTables() {
+        System.setProperty("org.apache.oodt.xmlps.xml.mapFilePath",
+            "./src/test/resources/test-required-tables-ps.xml");
+        
+        try {
+            handler = new XMLPSProductHandler();
+        } catch (InstantiationException e) {
+            fail(e.getMessage());
+        }
+        
+        String queryStr = "RETURN = id AND RETURN = id_1 AND RETURN = id_2 AND RETURN = id_3 AND RETURN = id_4";
+        XMLQuery query = XMLQueryHelper.getDefaultQueryFromQueryString(queryStr);
+        
+        List<QueryElement> where = query.getWhereElementSet();
+        List<QueryElement> select = query.getSelectElementSet();
+        
+        try {
+            handler.translateToDomain(where, false);
+            handler.translateToDomain(select, true);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+        
+        List<QueryElement> whereNames = handler.getElemNamesFromQueryElemSet(where);
+        List<QueryElement> selectNames = handler.getElemNamesFromQueryElemSet(select);
+        
+        Set<DatabaseTable> tables = handler.getRequiredTables(whereNames, selectNames);
+        
+        assertEquals(7, tables.size());
+        assertTrue(tables.contains(handler.mapping.getTableByName("joinToDefault")));
+        assertTrue(tables.contains(handler.mapping.getTableByName("joinToExtraDefault")));
+        assertTrue(tables.contains(handler.mapping.getTableByName("joinToExtraJoin")));
+        assertTrue(tables.contains(handler.mapping.getTableByName("joinToExtraOther")));
+        assertTrue(tables.contains(handler.mapping.getTableByName("extraDefault")));
+        assertTrue(tables.contains(handler.mapping.getTableByName("extraOther")));
+        assertTrue(tables.contains(handler.mapping.getTableByName("other")));
+        assertTrue(!tables.contains(handler.mapping.getTableByName("another")));
+    }
+}
diff --git a/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/profile/TestXMLPSProfileHandler.java b/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/profile/TestXMLPSProfileHandler.java
new file mode 100644
index 0000000..818d842
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/profile/TestXMLPSProfileHandler.java
@@ -0,0 +1,71 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.profile;
+
+//APACHE imports
+import org.apache.oodt.xmlps.util.XMLQueryHelper;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * Tests the XMLPS profile handler.
+ */
+public class TestXMLPSProfileHandler extends TestCase {
+
+  private static XMLPSProfileHandler handler;
+
+  private static final String unconstrainedQuery = "RETURN = STUDY_PARTICIPANT_ID";
+
+  public TestXMLPSProfileHandler() {
+    System.setProperty("org.apache.oodt.xmlps.profile.xml.mapFilePath",
+        "./src/test/resources/test-ps.xml");
+
+    try {
+      handler = new XMLPSProfileHandler();
+    } catch (InstantiationException e) {
+      fail("Can't construct test suite: exception building test handler");
+    }
+  }
+
+  public void testAllowUnConstrainedQuery() {
+    XMLQuery query = XMLQueryHelper
+        .getDefaultQueryFromQueryString(unconstrainedQuery);
+
+    assertNotNull(query);
+    assertNotNull(query.getWhereElementSet());
+    assertTrue(query.getWhereElementSet().size() == 0);
+    assertNotNull(query.getSelectElementSet());
+    assertTrue(query.getSelectElementSet().size() == 1);
+
+    try {
+      handler.translateToDomain(query.getSelectElementSet(), true);
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+    try {
+      handler.queryAndPackageProfiles(query);
+    } catch (Exception e) {
+      fail(e.getMessage());
+    }
+
+  }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/queryparser/TestHandlerQueryParser.java b/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/queryparser/TestHandlerQueryParser.java
new file mode 100644
index 0000000..4591927
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/queryparser/TestHandlerQueryParser.java
@@ -0,0 +1,111 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.queryparser;
+
+//APACHE imports
+import org.apache.oodt.xmlps.mapping.Mapping;
+import org.apache.oodt.xmlps.mapping.MappingField;
+import org.apache.oodt.xmlps.queryparser.Expression;
+import org.apache.oodt.xmlps.queryparser.HandlerQueryParser;
+import org.apache.oodt.xmlps.util.XMLQueryHelper;
+import org.apache.oodt.xmlquery.QueryElement;
+import org.apache.oodt.xmlquery.XMLQuery;
+
+//JDK imports
+import java.util.List;
+import java.util.Stack;
+
+//Junit imports
+import junit.framework.TestCase;
+
+/**
+ * Tests the XMLPS query handler parser.
+ */
+public class TestHandlerQueryParser extends TestCase {
+
+  public TestHandlerQueryParser() {
+  }
+
+  public void testParseQuery() {
+    String queryStr = "A = B AND C = D";
+    String expected = "(C = D AND A = B)";
+
+    XMLQuery query = XMLQueryHelper.getDefaultQueryFromQueryString(queryStr);
+    assertNotNull(query);
+    Stack<QueryElement> queryStack = HandlerQueryParser.createQueryStack(query
+        .getWhereElementSet());
+    assertNotNull(queryStack);
+    Expression parsedQuery = HandlerQueryParser.parse(queryStack);
+    assertNotNull(parsedQuery);
+    assertEquals(expected, parsedQuery.evaluate());
+  }
+  
+  public void testParseWildcardWithMapping(){
+    String queryStr = "bar LIKE 'FOO'";
+    String expected = "bar LIKE '%FOO%'";
+    Mapping mapping = new Mapping();
+    MappingField mf = new MappingField();
+    mf.setDbName("bar");
+    mf.setName("foo");
+    mf.setString(true);
+    mapping.addField("foo", mf);
+    
+    XMLQuery query = XMLQueryHelper.getDefaultQueryFromQueryString(queryStr);
+    assertNotNull(query);
+    Stack<QueryElement> queryStack = HandlerQueryParser.createQueryStack(query
+        .getWhereElementSet());
+    assertNotNull(queryStack);
+    Expression parsedQuery = HandlerQueryParser.parse(queryStack, mapping);
+    assertNotNull(parsedQuery);
+    assertEquals(expected, parsedQuery.evaluate());    
+  }
+  
+  private Mapping createFooBarMapping() {
+    Mapping m = new Mapping();
+    MappingField foof = new MappingField();
+    foof.setName("foo");
+    foof.setDbName("foo");
+    foof.setString(true);
+    MappingField barf = new MappingField();
+    barf.setName("bar");
+    barf.setDbName("bar");
+    barf.setString(true);
+    m.addField("foo", foof);
+    m.addField("bar", barf);
+    return m;
+  }
+
+  public void testParseLiteralQuotesWithParen() {
+    Mapping m = createFooBarMapping();
+
+    String q = "(foo = 'yes' OR bar = 'no') AND RETURN = foo AND RETURN = bar";
+    String expected = "(bar = 'no' OR foo = 'yes')";
+
+    XMLQuery query = XMLQueryHelper.getDefaultQueryFromQueryString(q);
+    assertNotNull(query);
+    Stack<QueryElement> where = HandlerQueryParser.createQueryStack(query.getWhereElementSet());
+    assertNotNull(where);
+    List<QueryElement> select = query.getSelectElementSet();
+    assertNotNull(select);
+
+    Expression parsed = HandlerQueryParser.parse(where, m);
+    assertNotNull(parsed);
+    assertEquals(expected, parsed.evaluate());
+  }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/structs/TestCDEResult.java b/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/structs/TestCDEResult.java
new file mode 100644
index 0000000..3cf23b3
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/structs/TestCDEResult.java
@@ -0,0 +1,122 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.structs;
+
+import static org.easymock.EasyMock.expect;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+import org.easymock.IMocksControl;
+
+public class TestCDEResult extends TestCase {
+
+  private static final String ID = "123";
+  private static final String LAST = "doe";
+  private static final String FIRST = "john";
+  private static final String DOB = "1980-01-01 00:00:00.0";
+
+  private static final String ID1 = "321";
+  private static final String LAST1 = "smith";
+  private static final String FIRST1 = "jane";
+  private static final String DOB1 = "1990-01-01 00:00:00.0";
+
+  private static final String FS = "\t";
+  private static final String RS = "$";
+
+  private ResultSet rs;
+  private Connection con;
+  private ResultSetMetaData rsmet;
+  private CDEResult result;
+  private IMocksControl ctrl;
+
+  @Override
+  protected void setUp() throws Exception {
+    ctrl = EasyMock.createNiceControl();
+    rs = ctrl.createMock(ResultSet.class);
+    con = ctrl.createMock(Connection.class);
+    rsmet = ctrl.createMock(ResultSetMetaData.class);
+    expect(rs.next()).andReturn(true);
+    expect(rsmet.getColumnCount()).andReturn(4).anyTimes();
+    expect(rs.getMetaData()).andReturn(rsmet).anyTimes();
+    expect(rs.getString(1)).andReturn(ID);
+    expect(rs.getString(2)).andReturn(LAST);
+    expect(rs.getString(3)).andReturn(FIRST);
+    expect(rs.getString(4)).andReturn(DOB);
+    expect(rs.next()).andReturn(true);
+    expect(rs.getString(1)).andReturn(ID1);
+    expect(rs.getString(2)).andReturn(LAST1);
+    expect(rs.getString(3)).andReturn(FIRST1);
+    expect(rs.getString(4)).andReturn(DOB1);
+    expect(rs.next()).andReturn(false);
+    ctrl.replay();
+    result = new CDEResult(rs,con);
+  }
+
+  public void testGetInputStream() {
+    InputStream in = null;
+    try {
+      in = result.getInputStream();
+    } catch (IOException e) {
+      fail("Could not get inputstream: " + e.getMessage());
+    }
+    assertNotNull(in);
+    assertEquals(CDEResultInputStream.class, in.getClass());
+
+    boolean thrown = false;
+    try {
+      in = new CDEResult(null, con).getInputStream();
+    } catch (IOException e) {
+      thrown = true;
+    }
+    assertTrue("InputStream should throw IOException with null ResultSet!", thrown);
+
+    thrown = false;
+    try {
+      in = new CDEResult(rs, null).getInputStream();
+    } catch (IOException e) {
+      thrown = true;
+    }
+    assertTrue("InputStream should throw IOException with null Connection!", thrown);
+  }
+
+  public void testGetNextRowAsString() {
+    try {
+      assertEquals(ID + FS + LAST + FS + FIRST + FS + DOB + RS, result.getNextRowAsString());
+      assertEquals(ID1 + FS + LAST1 + FS + FIRST1 + FS + DOB1 + RS, result.getNextRowAsString());
+    } catch (SQLException e) {
+      fail("Could not get next row: " + e.getMessage());
+    }
+  }
+
+  public void testGetMimeType() {
+    assertEquals("text/plain", result.getMimeType());
+  }
+
+  public void testGetSize() {
+    assertEquals(-1, result.getSize());
+  }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/structs/TestCDEResultInputStream.java b/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/structs/TestCDEResultInputStream.java
new file mode 100644
index 0000000..49f040e
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/test/java/org/apache/oodt/xmlps/structs/TestCDEResultInputStream.java
@@ -0,0 +1,137 @@
+/**
+ * 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.
+ */
+
+package org.apache.oodt.xmlps.structs;
+
+import static org.easymock.EasyMock.expect;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+import org.easymock.IMocksControl;
+
+public class TestCDEResultInputStream extends TestCase {
+  
+  private static final String ID = "123";
+  private static final String LAST = "doe";
+  private static final String FIRST = "john";
+  private static final String DOB = "1980-01-01 00:00:00.0";
+  
+  private static final String ID1 = "321";
+  private static final String LAST1 = "smith";
+  private static final String FIRST1 = "jane";
+  private static final String DOB1 = "1990-01-01 00:00:00.0";
+  
+  private static final String FS = "\t";
+  private static final String RS = "$";
+
+  private ResultSet rs;
+  private Connection con;
+  private ResultSetMetaData rsmet;
+  private CDEResult result;
+  private CDEResultInputStream in;
+  private IMocksControl ctrl;
+  
+  @Override
+  protected void setUp() throws Exception {
+    ctrl = EasyMock.createNiceControl();
+    rs = ctrl.createMock(ResultSet.class);
+    con = ctrl.createMock(Connection.class);
+    rsmet = ctrl.createMock(ResultSetMetaData.class);
+    expect(rs.next()).andReturn(true);
+    expect(rsmet.getColumnCount()).andReturn(4).anyTimes();
+    expect(rs.getMetaData()).andReturn(rsmet).anyTimes();
+    expect(rs.getString(1)).andReturn(ID);
+    expect(rs.getString(2)).andReturn(LAST);
+    expect(rs.getString(3)).andReturn(FIRST);
+    expect(rs.getString(4)).andReturn(DOB);
+    expect(rs.next()).andReturn(true);
+    expect(rs.getString(1)).andReturn(ID1);
+    expect(rs.getString(2)).andReturn(LAST1);
+    expect(rs.getString(3)).andReturn(FIRST1);
+    expect(rs.getString(4)).andReturn(DOB1);
+    expect(rs.next()).andReturn(false);
+    ctrl.replay();
+    result = new CDEResult(rs,con);
+    in = new CDEResultInputStream(result);
+  }
+  
+ @Override
+  protected void tearDown() throws Exception {
+    in.close();
+  }
+  
+  public void testRead() {
+    String expected = ID + FS + LAST + FS + FIRST + FS + DOB + RS;
+    String expected1 = ID1 + FS + LAST1 + FS + FIRST1 + FS + DOB1 + RS;
+    try {
+      for (int i = 0; i < expected.length(); i++) {
+        assertEquals((int)expected.charAt(i), in.read());
+      }
+      for (int i = 0; i < expected1.length(); i++) {
+        assertEquals((int)expected1.charAt(i), in.read());
+      }
+      assertEquals(-1, in.read());
+    } catch (IOException e) {
+      fail("IOException: " + e.getMessage());
+    }
+  }
+  
+  public void testReadCharArrayIntInt() {
+    byte[] buf = new byte[128];
+    int n = 0;
+    int length = 0;
+    String expected = null;
+    
+    try {
+      expected = ID + FS + LAST;
+      length = expected.length();
+      n = in.read(buf, 0, length);
+      assertEquals(length, n);
+      assertEquals(expected, new String(buf, 0, n));
+
+      expected = FS + FIRST;
+      length = expected.length();
+      n = in.read(buf, 0, length);
+      assertEquals(length, n);
+      assertEquals(expected, new String(buf, 0, n));
+
+      expected = FS + DOB.substring(0, length-1);
+      length = expected.length();
+      n = in.read(buf, 0, length);
+      assertEquals(length, n);
+      assertEquals(expected, new String(buf, 0, n));
+      
+      expected = DOB.substring(4) + RS + ID1 + FS + LAST1 + FS + FIRST1 + FS + DOB1 + RS;
+      length = buf.length;
+      n = in.read(buf, 0, length);
+      assertEquals(expected.length(), n);
+      assertEquals(expected, new String(buf, 0, n));
+      
+      n = in.read(buf, 0, 10);
+      assertEquals(-1, n);
+    } catch (IOException e) {
+      fail("IOException: " + e.getMessage());
+    }
+  }
+
+}
diff --git a/0.8.1-rc1/xmlps/src/test/resources/loging.properties b/0.8.1-rc1/xmlps/src/test/resources/loging.properties
new file mode 100644
index 0000000..215e4a5
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/test/resources/loging.properties
@@ -0,0 +1,34 @@
+# 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.
+
+
+# Specify the handlers to create in the root logger
+# (all loggers are children of the root logger)
+# The following creates one handlers
+handlers = java.util.logging.ConsoleHandler
+
+# Set the default logging level for the root logger
+.level = ALL
+    
+# Set the default logging level for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.level = ALL
+        
+# Set the default formatter for new ConsoleHandler instances
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+    
+# Set the default logging level
+# disable output of INFO messages from product handler
+org.apache.oodt.xmlps.product.level = SEVERE
+org.apache.oodt.xmlps.profile.level = SEVERE
diff --git a/0.8.1-rc1/xmlps/src/test/resources/test-ps.xml b/0.8.1-rc1/xmlps/src/test/resources/test-ps.xml
new file mode 100644
index 0000000..c073fc3
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/test/resources/test-ps.xml
@@ -0,0 +1,120 @@
+<?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.
+-->
+<oodt:ps xmlns:oodt="http://oodt.jpl.nasa.gov/xmlps/1.0" name="Test Query Handler" id="urn:oodt:xmlps:testps">
+<tables default="baseline">
+  <table name="specimen" join="patient_id" tofld="participant_num"/>
+</tables>
+
+	<!-- 
+		field:
+		
+		type (required):   dyanmic or constant. If you choose dynamic, then the field
+		value is read from the row in the ResultSet returned
+		from the database. If constant, then each returned row
+		from the ResultSet is annotated with the value specified
+		in the 'value' attribute.
+		
+		dbname (optional): the name of the field within the underlying db. If not
+		specified, then assumed to be name
+		
+		name (required):   the name of the attribute that you want returned
+		in the product server.
+		
+		table (optional):  if provided, then the attribute a is selected as
+		'table'.'a',and then returned. If omitted, the attribute
+		is assumed to come from the default table returned from the
+		PS query.
+		
+		value (optional):  is necessary to provide if type='constant' is selected.
+		
+		scope (optional):  limits the scope of a field's existance: acceptable values
+		are &quot;query&quot;, which signifies that the field is only applicable when
+		translating queries: and &quot;return&quot;, which signifies the field is only
+		applicable as a return field when converting database results into ERNEResults.
+		
+	-->
+	<field type="dynamic" dbname="specimen_collected" table="specimen"
+		name="SPECIMEN_COLLECTED_CODE" appendTableName="true"/>
+	<field type="constant" name="STUDY_SITE_ID" value="71" />
+	<field type="constant" name="STUDY_PROTOCOL_ID" value="XX" />
+	<field type="dynamic" dbname="" name="STUDY_PARTICIPANT_ID" />
+	<field type="constant" name="SPECIMEN_STUDY-DESIGN_CODE"
+		value="prospective" />
+	<field type="constant" name="SPECIMEN_CONTACT_NAME-TEXT"
+		value="Brendan Phalan" />
+	<field type="constant" name="SPECIMEN_CONTACT-EMAIL_TEXT"
+		value="Brendan.Phalan@med.nyu.edu" scope="return"/>
+	<field type="constant" name="BASELINE_DEMOGRAPHICS-GENDER_CODE"
+		value="1" />
+	<field type="constant" name="BASELINE_DEMOGRAPHICS-ETHNIC_CODE"
+		value="1" />
+	<field type="constant" name="BASELINE_DEMOGRAPHICS_RACE_CODE"
+		value="1" />
+	<field type="dynamic" name="BASELINE_DEMOGRAPHICS-RACE_OTHER_TEXT" />
+	<field type="dynamic" name="BASELINE_DEMOGRAPHICS-BIRTH-YEAR_TEXT" />
+	<field type="dynamic" name="BASELINE_SMOKE-REGULAR_1YEAR_CODE" />
+	<field type="dynamic"
+		name="BASELINE_SMOKE-HX_BEGIN-AGE-REGULAR_VALUE" />
+	<field type="dynamic" name="BASELINE_SMOKE-HX_AVERAGE-DAY_VALUE" />
+	<field type="dynamic" name="BASELINE_SMOKE-HX_QUIT-AGE_VALUE" />
+	<field type="dynamic" name="BASELINE_CANCER-CONFIRMATION_CODE" />
+	<field type="constant" name="BASELINE_CANCER-ICD9-CODE"
+		value="UNKNOWN" />
+	<field type="constant" name="BASELINE_CANCER-DIAGNOSIS_YEAR_TEXT"
+		value="UNKNOWN" />
+	<field type="constant" name="BASELINE_CANCER-AGE-DIAGNOSIS_VALUE"
+		value="UNKNOWN" />
+	<field type="dynamic"
+		name="BASELINE_FAMILY_CANCER-CONFIRMATION_CODE" />
+	<field type="dynamic" name="BASELINE_FAMILY_CANCER-LOCATION_CODE" />
+	<field type="constant"
+		name="BASELINE_FAMILY_CANCER-LOCATION-OTHER_TEXT" value="UNKNOWN" />
+	<field type="dynamic" name="SPECIMEN_COLLECTION_TEXT" />
+	<field type="dynamic" name="SPECIMEN_STORED_CODE" />
+	<field type="dynamic" name="SPECIMEN_FINAL-STORE_CODE" />
+	<field type="constant" name="SPECIMEN_FINAL-STORE-OTHER_TEXT"
+		value="UNKNOWN" />
+	<field type="dynamic" name="SPECIMEN_DAY-COLLECTED_VALUE" />
+	<field type="constant" name="SPECIMEN_DAY-CA-DIAGNOSIS_VALUE"
+		value="UNKNOWN" />
+	<field type="dynamic" name="SPECIMEN_AGE-COLLECTED_VALUE" />
+	<field type="dynamic" name="SPECIMEN_AMOUNT-STORED_VALUE" />
+	<field type="constant" name="SPECIMEN_AMOUNT-STORED-UNIT_CODE"
+		value="1" />
+	<field type="dynamic" name="SPECIMEN_AMOUNT_REMAINING_VALUE" />
+	<field type="dynamic" name="SPECIMEN_AMOUNT_REMAINING_UNIT_CODE" />
+	<field type="dynamic" name="SPECIMEN_CONCENTRATION_VALUE" />
+	<field type="dynamic" name="SPECIMEN_AVAILABLE_CODE" />
+	<field type="dynamic" name="SPECIMEN_TISSUE_ORGAN-SITE_CODE">
+		<translate>
+			<func class="org.apache.oodt.xmlps.mapping.funcs.ReplaceFunc" orig="16" with="1" />
+		</translate>
+	</field>
+	<field type="constant" name="SPECIMEN_TISSUE-ORGAN-SITE-OTHER_TEXT"
+		value="UNKNOWN" />
+	<field type="constant" name="SPECIMEN_TISSUE_DEGREE-INVASIVE_CODE"
+		value="UNKNOWN" />
+	<field type="constant"
+		name="SPECIMEN_TISSUE_DEGREE-INVASIVE-TUMOR_CODE" value="UNKNOWN" />
+	<field type="constant" name="SPECIMEN_BONE-MARROW_BLAST_VALUE"
+		value="UNKNOWN" />
+	<field type="constant" name="SPECIMEN_SPUTUM_PRESERVATIVE_CODE"
+		value="UNKNOWN" />
+	<field type="constant"
+		name="SPECIMEN_SPUTUM-PRESERVATIVE-OTHER_TEXT" value="UNKOWN" />
+</oodt:ps>
\ No newline at end of file
diff --git a/0.8.1-rc1/xmlps/src/test/resources/test-required-tables-ps.xml b/0.8.1-rc1/xmlps/src/test/resources/test-required-tables-ps.xml
new file mode 100644
index 0000000..53d706b
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/test/resources/test-required-tables-ps.xml
@@ -0,0 +1,71 @@
+<?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.
+-->
+<!-- Example XML mapping configuration file -->
+<oodt:xmlps xmlns:oodt="http://incubator.apache.org/oodt/0.1-incubating"
+  name="Example Query Handler" id="project:subproject:exampleps">
+  <tables default="defaultTable">
+    <table name="joinToDefault" join="id" tofld="id" />
+    <table name="joinToExtraDefault" join="id" to="extraDefault" tofld="id" />
+    <table name="joinToExtraJoin" join="id" to="joinToExtraDefault" tofld="id"/>
+    <table name="joinToExtraOther" join="id" to="extraOther" tofld="id"/>
+    <table name="extraDefault" join="id" tofld="id"/>
+    <table name="extraOther" join="id" to="other" tofld="id"/>
+    <table name="other" join="id" tofld="id" />
+    <table name="another" join="id" tofld="id" />
+  </tables>
+  <!-- 
+    field:
+    
+    type (required):   dynamic or constant. If you choose dynamic, then the field
+    value is read from the row in the ResultSet returned
+    from the database. If constant, then each returned row
+    from the ResultSet is annotated with the value specified
+    in the 'value' attribute.
+    
+    name (required):   the name of the attribute that you want returned
+    in the product server.
+    
+    string (optional): whether or not the internal db representation at the local
+    site for this field is a STRING, or something else (e.g., a number, etc.). Possible 
+    values for this attribute are "true", to indicate that the field is a string, or
+    "false", to indicate that it is something else. If this attribute is omitted, a value
+    of "false" is assumed, and the attribute will not be quoted in the where clause of
+    the underlying SQL statement generated.
+    
+    dbname (optional): the name of the field within the underlying db. If not
+    specified, then assumed to be name
+    
+    table (optional):  if provided, then the attribute a is selected as
+    'table'.'a',and then returned. If omitted, the attribute
+    is assumed to come from the default table returned from the
+    PS query.
+    
+    value (optional):  is necessary to provide if type='constant' is selected.
+    
+    scope (optional):  limits the scope of a field's existence: acceptable values
+    are &quot;query&quot;, which signifies that the field is only applicable when
+    translating queries: and &quot;return&quot;, which signifies the field is only
+    applicable as a return field when converting database results into CDEResults.
+    
+  -->
+  <field type="dynamic" name="id" dbname="id" table="defaultTable"/>
+  <field type="dynamic" name="id_1" dbname="id" table="joinToDefault"/>
+  <field type="dynamic" name="id_2" dbname="id" table="joinToExtraDefault"/>
+  <field type="dynamic" name="id_3" dbname="id" table="joinToExtraJoin"/>
+  <field type="dynamic" name="id_4" dbname="id" table="joinToExtraOther"/>
+</oodt:xmlps>
diff --git a/0.8.1-rc1/xmlps/src/test/resources/test-same-col-name-ps.xml b/0.8.1-rc1/xmlps/src/test/resources/test-same-col-name-ps.xml
new file mode 100644
index 0000000..87d2dcb
--- /dev/null
+++ b/0.8.1-rc1/xmlps/src/test/resources/test-same-col-name-ps.xml
@@ -0,0 +1,63 @@
+<?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.
+-->
+<!-- Example XML mapping configuration file -->
+<oodt:xmlps xmlns:oodt="http://incubator.apache.org/oodt/0.1-incubating"
+  name="Example Query Handler" id="project:subproject:exampleps">
+  <tables default="defaultTable">
+    <table name="joinTable" join="id" tofld="id" />
+  </tables>
+  <!-- 
+    field:
+    
+    type (required):   dynamic or constant. If you choose dynamic, then the field
+    value is read from the row in the ResultSet returned
+    from the database. If constant, then each returned row
+    from the ResultSet is annotated with the value specified
+    in the 'value' attribute.
+    
+    name (required):   the name of the attribute that you want returned
+    in the product server.
+    
+    string (optional): whether or not the internal db representation at the local
+    site for this field is a STRING, or something else (e.g., a number, etc.). Possible 
+    values for this attribute are "true", to indicate that the field is a string, or
+    "false", to indicate that it is something else. If this attribute is omitted, a value
+    of "false" is assumed, and the attribute will not be quoted in the where clause of
+    the underlying SQL statement generated.
+    
+    dbname (optional): the name of the field within the underlying db. If not
+    specified, then assumed to be name
+    
+    table (optional):  if provided, then the attribute a is selected as
+    'table'.'a',and then returned. If omitted, the attribute
+    is assumed to come from the default table returned from the
+    PS query.
+    
+    value (optional):  is necessary to provide if type='constant' is selected.
+    
+    scope (optional):  limits the scope of a field's existence: acceptable values
+    are &quot;query&quot;, which signifies that the field is only applicable when
+    translating queries: and &quot;return&quot;, which signifies the field is only
+    applicable as a return field when converting database results into CDEResults.
+    
+  -->
+  <field type="dynamic" name="id_xmlps" dbname="id" table="defaultTable"/>
+  <field type="dynamic" name="field_only"/>
+  <field type="dynamic" name="field_with_table" dbname="field_db" table="anotherTable"/>
+  <field type="dynamic" name="field_use_default" dbname="field_db"/>
+</oodt:xmlps>
diff --git a/0.8.1-rc1/xmlquery/oodt-xmlquery.iml b/0.8.1-rc1/xmlquery/oodt-xmlquery.iml
new file mode 100644
index 0000000..e1e9963
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/oodt-xmlquery.iml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
+    <output url="file://$MODULE_DIR$/target/classes" />
+    <output-test url="file://$MODULE_DIR$/target/test-classes" />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/conf" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/dtd" type="java-resource" />
+      <excludeFolder url="file://$MODULE_DIR$/target" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="oodt-commons" />
+    <orderEntry type="library" name="Maven: commons-dbcp:commons-dbcp:1.2.1" level="project" />
+    <orderEntry type="library" name="Maven: xml-apis:xml-apis:1.0.b2" level="project" />
+    <orderEntry type="library" name="Maven: commons-collections:commons-collections:2.1" level="project" />
+    <orderEntry type="library" name="Maven: commons-pool:commons-pool:1.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-lang:commons-lang:2.3" level="project" />
+    <orderEntry type="library" name="Maven: commons-logging:commons-logging:1.0.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-core:2.5.4" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-hibernate3:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: aopalliance:aopalliance:1.0" level="project" />
+    <orderEntry type="library" name="Maven: org.hibernate:hibernate:3.2.5.ga" level="project" />
+    <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache:1.2.3" level="project" />
+    <orderEntry type="library" name="Maven: asm:asm-attrs:1.5.3" level="project" />
+    <orderEntry type="library" name="Maven: dom4j:dom4j:1.6.1" level="project" />
+    <orderEntry type="library" name="Maven: antlr:antlr:2.7.6" level="project" />
+    <orderEntry type="library" name="Maven: cglib:cglib:2.1_3" level="project" />
+    <orderEntry type="library" name="Maven: asm:asm:1.5.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-beans:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-context:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-dao:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:2.0.8" level="project" />
+    <orderEntry type="library" name="Maven: xmlrpc:xmlrpc:2.0.1" level="project" />
+    <orderEntry type="library" name="Maven: xerces:xercesImpl:2.9.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: junit:junit:3.8.2" level="project" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/0.8.1-rc1/xmlquery/pom.xml b/0.8.1-rc1/xmlquery/pom.xml
new file mode 100644
index 0000000..41576a8
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/pom.xml
@@ -0,0 +1,108 @@
+<?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.
+-->
+<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>
+  <parent>
+    <groupId>org.apache.oodt</groupId>
+    <artifactId>oodt-core</artifactId>
+    <version>0.8.1</version>
+    <relativePath>../core/pom.xml</relativePath>
+  </parent>
+  <artifactId>oodt-xmlquery</artifactId>
+  <name>Query Expression</name>
+  <packaging>jar</packaging>
+  <description>This component provides a way to express queries in a generic
+    manner.  Its centerpiece is a class called XMLQuery that uses
+    boolean postfix expressions to capture the domain, range, and
+    constraint of a query, regardless of the source of the query (SQL,
+    keyword query, etc.).  It can also encapsulate the results of a
+    query.  It's used by many other components as the standard way to
+    pass a query and its results between servers, clients, nodes, and
+    other components.</description>
+  <scm>
+   	<connection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/xmlquery</connection>
+   	<developerConnection>scm:svn:https://svn.apache.org/repos/asf/oodt/tags/0.8.1/xmlquery</developerConnection>
+   	<url>http://svn.apache.org/viewvc/oodt/tags/0.8.1/xmlquery</url>
+  </scm>
+  <build>
+    <resources>
+      <resource>
+        <targetPath>org/apache/oodt/xmlquery</targetPath>
+        <directory>${basedir}/src/main/conf</directory>
+        <includes>
+          <include>mime.properties</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>${basedir}/src/main/dtd</directory>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <excludes>
+            <exclude>org/apache/oodt/xmlquery/CodecTest.java</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>audit</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>rat-maven-plugin</artifactId>
+            <configuration>
+              <excludes>
+                <exclude>**/oodt/xmlquery/package.html</exclude>
+              </excludes>
+            </configuration>
+            <executions>
+              <execution>
+                <phase>verify</phase>
+                <goals>
+                  <goal>check</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.oodt</groupId>
+      <artifactId>oodt-commons</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/0.8.1-rc1/xmlquery/src/main/conf/mime.properties b/0.8.1-rc1/xmlquery/src/main/conf/mime.properties
new file mode 100755
index 0000000..af95ada
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/conf/mime.properties
@@ -0,0 +1,407 @@
+#  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.
+
+
+# Internet media types supported by OODT
+#
+# $Id: mime.properties,v 1.1.1.1 2004-03-02 19:37:13 kelly Exp $
+
+# These types aren't in the official list at IANA, but are listed
+# here for internal OODT use:
+
+application/vnd.jpl.large-product:				org.apache.oodt.xmlquery.StringCodec
+
+# These types aren't in the official list at IANA, but are supported
+# in various environments:
+
+application/x-java-serialized-object				org.apache.oodt.xmlquery.ObjectCodec
+application/java-vm						org.apache.oodt.xmlquery.ObjectCodec
+
+# This types are translated from the Internet media type registry at
+# ftp://ftp.iana.org/in-notes/iana/assignments/media-types/media-types
+
+text/plain:							org.apache.oodt.xmlquery.StringCodec
+text/richtext:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/enriched:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/tab-separated-values:					org.apache.oodt.xmlquery.StringCodec
+text/html:							org.apache.oodt.xmlquery.CompressedStringCodec
+text/sgml:							org.apache.oodt.xmlquery.CompressedStringCodec
+text/vnd.latex-z:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/vnd.fmi.flexstor:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/uri-list:							org.apache.oodt.xmlquery.StringCodec
+text/vnd.abc:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/rfc822-headers:						org.apache.oodt.xmlquery.StringCodec
+text/vnd.in3d.3dml:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/prs.lines.tag:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/vnd.in3d.spot:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/css:							org.apache.oodt.xmlquery.CompressedStringCodec
+text/xml:							org.apache.oodt.xmlquery.StringCodec
+text/rtf:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/directory:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/calendar:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/vnd.wap.wml:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/vnd.wap.wmlscript:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/vnd.motorola.reflex:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/vnd.fly:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/vnd.wap.sl:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/vnd.wap.si:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/t140:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/vnd.ms-mediapackage:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/vnd.IPTC.NewsML:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/vnd.IPTC.NITF:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/vnd.curl:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/vnd.DMClientScript:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+text/parityfec:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+multipart/mixed:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+multipart/alternative:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+multipart/digest:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+multipart/parallel:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+multipart/appledouble:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+multipart/header-set:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+multipart/form-data:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+multipart/related:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+multipart/report:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+multipart/voice-message:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+multipart/signed:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+multipart/encrypted:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+multipart/byteranges:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+message/rfc822:							org.apache.oodt.xmlquery.CompressedStringCodec
+message/partial:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+message/external-body:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+message/news:							org.apache.oodt.xmlquery.CompressedStringCodec
+message/http:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+message/delivery-status:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+message/disposition-notification:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+message/s-http:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/octet-stream:					org.apache.oodt.xmlquery.ByteArrayCodec
+application/postscript:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/oda:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/atomicmail:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/andrew-inset:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/slate:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/wita:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/dec-dx:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/dca-rft:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/activemessage:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/rtf:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/applefile:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/mac-binhex40:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/news-message-id:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/news-transmission:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/wordperfect5.1:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/pdf:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/zip:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/macwriteii:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/msword:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/remote-printing:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/mathematica:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/cybercash:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/commonground:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/iges:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/riscos:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/eshop:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/x400-bp:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/sgml:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/cals-1840:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/pgp-encrypted:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/pgp-signature:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/pgp-keys:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.framemaker:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.mif:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ms-excel:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ms-powerpoint:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ms-project:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ms-works:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ms-tnef:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.svd:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.music-niff:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ms-artgalry:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.truedoc:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.koan:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.street-stream:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.fdf:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/set-payment-initiation:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/set-payment:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/set-registration-initiation:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/set-registration:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.seemail:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.businessobjects:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.meridian-slingshot:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.xara:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/sgml-open-catalog:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.rapid:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.enliven:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.japannet-registration-wakeup:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.japannet-verification-wakeup:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.japannet-payment-wakeup:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.japannet-directory-service:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.intertrust.digibox:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.intertrust.nncp:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/prs.alvestrand.titrax-sheet:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.noblenet-web:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.noblenet-sealer:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.noblenet-directory:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/prs.nprend:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.webturbo:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/hyperstudio:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.shana.informed.formtemplate:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.shana.informed.formdata:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.shana.informed.package:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.shana.informed.interchange:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.$commerce_battelle:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.osa.netdeploy:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ibm.MiniPay:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.japannet-jpnstore-wakeup:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.japannet-setstore-wakeup:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.japannet-verification:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.japannet-registration:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.hp-HPGL:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.hp-PCL:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.hp-PCLXL:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.musician:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.FloGraphIt:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.intercon.formnet:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vemmi:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ms-asf:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ecdis-update:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.powerbuilder6:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.powerbuilder6-s:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.lotus-wordpro:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.lotus-approach:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.lotus-1-2-3:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.lotus-organizer:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.lotus-screencam:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.lotus-freelance:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.fujitsu.oasys:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.fujitsu.oasys2:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.swiftview-ics:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.dna:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/prs.cww:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.wt.stf:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.dxr:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.mitsubishi.misty-guard.trustweb:		org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ibm.modcap:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.acucobol:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.fujitsu.oasys3:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/marc:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.fujitsu.oasysprs:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.fujitsu.oasysgp:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.visio:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.netfpx:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.audiograph:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.epson.salt:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.3M.Post-it-Notes:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.novadigm.EDX:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.novadigm.EXT:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.novadigm.EDM:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.claymore:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.comsocaller:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/pkcs7-mime:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/pkcs7-signature:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/pkcs10:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.yellowriver-custom-menu:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ecowin.chart:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ecowin.series:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ecowin.filerequest:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ecowin.fileupdate:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ecowin.seriesrequest:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ecowin.seriesupdate:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/EDIFACT:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/EDI-X12:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/EDI-Consent:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.wrq-hp3000-labelled:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.minisoft-hp3000-save:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ffsns:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.hp-hps:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.fujixerox.docuworks:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/xml:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.anser-web-funds-transfer-initiation:		org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.anser-web-certificate-issue-initiation:		org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.is-xpr:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.intu.qbo:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.publishare-delta-tree:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.cybank:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/batch-SMTP:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.uplanet.alert:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.uplanet.cacheop:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.uplanet.list:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.uplanet.listcmd:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.uplanet.channel:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.uplanet.bearer-choice:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.uplanet.signal:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.uplanet.alert-wbxml:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.uplanet.cacheop-wbmxl:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.uplanet.list-wbxml:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.uplanet.listcmd-wbxml:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.uplanet.channel-wbxml:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.uplanet.bearer-choice-wbxml:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.epson.quickanime:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.commonspace:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.fut-misnet:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.xfdl:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.intu.qfx:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.epson.ssf:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.epson.msf:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.powerbuilder7:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.powerbuilder7-s:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.lotus-notes:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/pkixcmp:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.wap.wmlc:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.wap.wmlscriptc:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.motorola.flexsuite:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.wap.wbxml:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.motorola.flexsuite.wem:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.motorola.flexsuite.kmr:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.motorola.flexsuite.adsi:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.motorola.flexsuite.fis:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.motorola.flexsuite.gotap:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.motorola.flexsuite.ttc:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ufdl:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.accpac.simply.imp:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.accpac.simply.aso:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.vcx:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/ipp:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/ocsp-request:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/ocsp-response:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.previewsystems.box:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.mediastation.cdkey:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.pg.format:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.pg.osasli:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.hp-hpid:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/pkix-cert:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/pkix-crl:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.Mobius.TXF:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.Mobius.PLC:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.Mobius.DIS:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.Mobius.DAF:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.Mobius.MSL:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.cups-raster:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.cups-postscript:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.cups-raw:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/index:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/index.cmd:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/index.response:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/index.obj:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/index.vnd:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.triscape.mxs:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.powerbuilder75:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.powerbuilder75-s:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.dpgraph:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/http:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/sdp:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.eudora.data:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.fujixerox.docuworks.binder:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.vectorworks:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.grafeq:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.bmi:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ericsson.quickcall:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.hzn-3d-crossword:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.wap.slc:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.wap.sic:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.groove-injector:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.fujixerox.ddd:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.groove-account:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.groove-identity-message:			org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.groove-tool-message:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.groove-tool-template:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.groove-vcard:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ctc-posml:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.canon-lips:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.canon-cpdl:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.trueapp:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.s3sms:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/iotp:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.mcd:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.httphone:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.informix-visionary:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.msign:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.ms-lrm:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.contact.cmsg:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.epson.esf:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/whoispp-query:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/whoispp-response:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.mozilla.xul+xml:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/parityfec:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.palm:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.fsc.weblaunch:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/vnd.tve-trigger:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/dvcs:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+application/sieve:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/jpeg:							org.apache.oodt.xmlquery.ByteArrayCodec
+image/gif:							org.apache.oodt.xmlquery.ByteArrayCodec
+image/ief:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/g3fax:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/tiff:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/cgm:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/naplps:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/vnd.dwg:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/vnd.svf:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/vnd.dxf:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/png:							org.apache.oodt.xmlquery.ByteArrayCodec
+image/vnd.fpx:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/vnd.net-fpx:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/vnd.xiff:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/prs.btif:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/vnd.fastbidsheet:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/vnd.wap.wbmp:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/prs.pti:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/vnd.cns.inf2:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/vnd.mix:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/vnd.fujixerox.edmics-rlc:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/vnd.fujixerox.edmics-mmr:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+image/vnd.fst:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/basic:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/32kadpcm:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/vnd.qcelp:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/vnd.digital-winds:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/vnd.lucent.voice:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/vnd.octel.sbc:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/vnd.rhetorex.32kadpcm:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/vnd.vmx.cvsd:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/vnd.nortel.vbk:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/vnd.cns.anp1:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/vnd.cns.inf1:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/L16:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/vnd.everad.plj:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/telephone-event:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/tone:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/prs.sid:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/vnd.nuera.ecelp4800:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/vnd.nuera.ecelp7470:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/mpeg:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/parityfec:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+audio/MP4A-LATM:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+video/mpeg:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+video/quicktime:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+video/vnd.vivo:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+video/vnd.motorola.video:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+video/vnd.motorola.videop:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+video/vnd.fvt:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+video/pointer:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+video/parityfec:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+video/vnd.mpegurl:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+video/MP4V-ES:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+model/iges:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+model/vrml:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+model/mesh:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+model/vnd.dwf:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+model/vnd.gtw:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+model/vnd.flatland.3dml:					org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+model/vnd.vtu:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+model/vnd.mts:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+model/vnd.gdl:							org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+model/vnd.gs-gdl:						org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+model/vnd.parasolid.transmit.text:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
+model/vnd.parasolid.transmit.binary:				org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec
diff --git a/0.8.1-rc1/xmlquery/src/main/dtd/query.dtd b/0.8.1-rc1/xmlquery/src/main/dtd/query.dtd
new file mode 100755
index 0000000..0cf3401
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/dtd/query.dtd
@@ -0,0 +1,100 @@
+<?xml 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.
+-->
+
+  <!ELEMENT query
+	(queryAttributes,
+         queryResultModeId,
+         queryPropogationType,
+	 queryPropogationLevels,
+         queryMimeAccept*,
+         queryMaxResults,
+         queryResults,
+         queryKWQString,
+	 queryStatistics?,
+         querySelectSet,
+         queryFromSet,
+	 queryWhereSet,
+	 queryResultSet)>
+
+    <!ELEMENT queryAttributes
+      (queryId, queryTitle*, queryDesc*, queryType*,
+       queryStatusId*, querySecurityType*, 
+       queryParentId*, queryChildId*,
+       queryRevisionNote*,
+       queryDataDictId*)>
+
+    <!ELEMENT queryStatistics (statistic*)>
+
+    <!ELEMENT querySelectSet
+	(queryElement*)>
+
+    <!ELEMENT queryFromSet
+	(queryElement*)>
+
+    <!ELEMENT queryWhereSet
+	(queryElement*)>
+
+      <!ELEMENT queryElement
+        (tokenRole*, tokenValue*)>
+
+    <!ELEMENT statistic (url, time)>
+
+    <!ELEMENT queryResultSet
+	(resultElement*)>
+
+      <!ELEMENT resultElement
+        (resultId*, resultMimeType*,
+         profId*, identifier*, resultHeader,
+         resultValue*)>
+      <!ATTLIST resultElement classified (true|false) 'false'>
+      <!ATTLIST resultElement validity CDATA #IMPLIED>
+
+    <!ELEMENT resultHeader (headerElement*)>
+    <!ELEMENT headerElement (elemName, elemType?, elemUnit?)>
+
+    <!ELEMENT queryId (#PCDATA)>
+    <!ELEMENT queryTitle (#PCDATA)>
+    <!ELEMENT queryType (#PCDATA)>
+    <!ELEMENT queryDesc (#PCDATA)>
+    <!ELEMENT queryParentId (#PCDATA)>
+    <!ELEMENT queryChildId (#PCDATA)>
+    <!ELEMENT queryStatusId (#PCDATA)>
+    <!ELEMENT querySecurityType (#PCDATA)>
+    <!ELEMENT queryRevisionNote (#PCDATA)>
+    <!ELEMENT queryDataDictId (#PCDATA)>
+    <!ELEMENT queryResultModeId (#PCDATA)>
+    <!ELEMENT queryPropogationType (#PCDATA)>
+    <!ELEMENT queryPropogationLevels (#PCDATA)>
+    <!ELEMENT queryMimeAccept (#PCDATA)>
+    <!ELEMENT queryMaxResults (#PCDATA)>
+    <!ELEMENT queryResults (#PCDATA)>
+    <!ELEMENT queryKWQString (#PCDATA)>
+    <!ELEMENT url (#PCDATA)>
+    <!ELEMENT time (#PCDATA)>
+    <!ELEMENT elemName (#PCDATA)>
+    <!ELEMENT elemType (#PCDATA)>
+    <!ELEMENT elemUnit (#PCDATA)>
+    <!ELEMENT elemValue (#PCDATA)>
+    <!ELEMENT resultId (#PCDATA)>
+    <!ELEMENT resultMimeType (#PCDATA)>
+    <!ELEMENT resultValue (#PCDATA)>
+    <!ATTLIST resultValue xml:space (default|preserve) 'default'>
+    <!ELEMENT profId (#PCDATA)>
+    <!ELEMENT identifier (#PCDATA)>
+    <!ELEMENT tokenRole (#PCDATA)>
+    <!ELEMENT tokenValue (#PCDATA)>
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/product/ProductException.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/product/ProductException.java
new file mode 100755
index 0000000..83686a3
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/product/ProductException.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product;
+
+/**
+ * Checked exception to indicate a product fault.
+ *
+ * @author Kelly
+ */
+public class ProductException extends Exception {
+	/**
+	 * Construct a product exception with no detail message.
+	 */
+	public ProductException() {}
+
+	/**
+	 * Construct a product exception with the given detail message.
+	 *
+	 * @param msg Detail message.
+	 */
+	public ProductException(String msg) {
+		super(msg);
+	}
+
+	/**
+	 * Creates a new <code>ProductException</code> instance.
+	 *
+	 * @param cause a <code>Throwable</code> value.
+	 */
+	public ProductException(Throwable cause) {
+		super(cause);
+	}
+
+	/**
+	 * Creates a new <code>ProductException</code> instance.
+	 *
+	 * @param msg a <code>String</code> value.
+	 * @param cause a <code>Throwable</code> value.
+	 */
+	public ProductException(String msg, Throwable cause) {
+		super(msg, cause);
+	}
+
+	/** Serial version unique ID. */
+	static final long serialVersionUID = 8240102969482071451L;
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/product/Retriever.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/product/Retriever.java
new file mode 100755
index 0000000..0e88f06
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/product/Retriever.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.product;
+
+/**
+ * Retrievers retrieve products.
+ *
+ * @author Kelly
+ * @version $Revision: 1.1.1.1 $
+ */
+public interface Retriever {
+	/**
+	 * Retrieve a chunk from a large product.
+	 *
+	 * @param productID Product ID.
+	 * @param offset Where in the product to retrieve the data.
+	 * @param length How much data to get.
+	 * @return The data.
+	 * @throws ProductException if an error occurs.
+	 */
+	byte[] retrieveChunk(String productID, long offset, int length) throws ProductException;
+
+	/**
+	 * Close off a large product.
+	 *
+	 * @param productID Product ID.
+	 * @throws ProductException if an error occurs.
+	 */
+	void close(String productID) throws ProductException;
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/ByteArrayCodec.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/ByteArrayCodec.java
new file mode 100755
index 0000000..6b2146b
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/ByteArrayCodec.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import org.apache.oodt.commons.util.Base64;
+import org.apache.oodt.commons.util.XML;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/** A result encoder/decoder for byte arrays.
+ *
+ * This codec uses base-64 encoding for byte arrays.
+ *
+ * @author Kelly
+ */
+class ByteArrayCodec implements Codec {
+	public Node encode(Object object, Document doc) throws DOMException {
+		Element value = doc.createElement("resultValue");
+		value.appendChild(doc.createCDATASection(new String(Base64.encode((byte[]) object))));
+		return value;
+	}
+
+	public Object decode(Node node) {
+		String encodedValue;
+		if (node.getFirstChild() != null && node.getFirstChild().getNodeType() == Node.CDATA_SECTION_NODE)
+			encodedValue = node.getFirstChild().getNodeValue();
+		else
+			encodedValue = XML.text(node);
+		if (encodedValue.length() <= 0) return new byte[0];
+		return Base64.decode(encodedValue.getBytes());
+	}
+
+	public InputStream getInputStream(Object value) {
+		return new ByteArrayInputStream((byte[]) value);
+	}
+
+	public long sizeOf(Object object) {
+		return ((byte[]) object).length;
+	}
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Codec.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Codec.java
new file mode 100755
index 0000000..febcbba
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Codec.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidClassException;
+import java.io.OptionalDataException;
+import java.io.StreamCorruptedException;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/** Result encoder/decoder.
+ *
+ * Classes that implement this interface encode and decode query results to and from XML
+ * format.
+ *
+ * @author Kelly
+ */
+interface Codec {
+	/** Encode the given object into XML format.
+	 *
+	 * The encoding takes the object, encodes into a DOM structure, and returns a
+	 * &lt;resultValue&gt; element.
+	 *
+	 * @param object Object to encode.
+	 * @param doc What document will own the created XML nodes.
+	 * @return A &lt;resultValue&gt; element encoding the <var>object</var>.
+	 * @throws DOMException If an error occurs while encoding the object.
+	 */
+	Node encode(Object object, Document doc) throws DOMException;
+
+	/** Decode the given XML representation into its object.
+	 *
+	 * The decoding takes the &lt;resultValue&gt; node, and decodes it into the object
+	 * it represents.
+	 *
+	 * @param node The &lt;resultValue&gt; node.
+	 * @return The object that the <var>node</var> represents.
+	 * @throws ClassNotFoundException If the class of the object in <var>node</var> can't be found.
+	 * @throws InvalidClassException If something is wrong with the class encoded in <var>node</var>.
+	 * @throws StreamCorruptedException When control information in <var>node</var> is inconsistent.
+	 * @throws OptionalDataException If primitive datatypes instead of an object was found encoded in the <var>node</var>.
+	 */
+	Object decode(Node node) throws ClassNotFoundException, InvalidClassException, StreamCorruptedException,
+		OptionalDataException;
+
+	/**
+	 * Compute the size of the given object.
+	 *
+	 * @param object Object.
+	 * @return Size of <var>object</var> in bytes.
+	 */
+	long sizeOf(Object object);
+
+	/**
+	 * Yield the given object as a stream.
+	 *
+	 * This method takes the given object and yields a stream version of it
+	 * appropriate concrete codec type.  For example, {@link ByteArrayCodec}s may
+	 * yield simple {@link ByteArrayInputStream}s for their objects.
+	 *
+	 * @param object The object to be streamed.
+	 * @return An <code>InputStream</code> of <var>object</var>.
+	 * @throws IOException if an error occurs.
+	 */
+	InputStream getInputStream(Object object) throws IOException;
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/CodecFactory.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/CodecFactory.java
new file mode 100755
index 0000000..8935e53
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/CodecFactory.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+
+/** A factory for codecs.
+ *
+ * The codec factory creates and maintains codec objects.
+ *
+ * @author Kelly
+ */
+class CodecFactory {
+	/** Create a codec.
+	 *
+	 * If the codec with the given class name already exists, it's returned.
+	 * Otherwise, the factory creates a new instance of the codec and returns it.  Any
+	 * to instantiate the codec results in a runtime exception.
+	 *
+	 * @param className Name of the codec class to create.
+	 * @return The codec object of the class with the given <var>className</var>.
+	 */
+	public static Codec createCodec(String className) {
+		Codec codec = (Codec) codecs.get(className);
+		if (codec == null) try {
+			Class clazz = Class.forName(className);
+			codec = (Codec) clazz.newInstance();
+			codecs.put(className, codec);
+		} catch (ClassNotFoundException ex) {
+			throw new RuntimeException("Class \"" + className + "\" not found");
+		} catch (InstantiationException ex) {
+			throw new RuntimeException("Class \"" + className + "\" is abstract or is an interface");
+		} catch (IllegalAccessException ex) {
+			throw new RuntimeException("Class \"" + className + "\" doesn't have public no-args constructor");
+		}
+		return codec;
+	}
+
+	/** Cachec codecs; the mapping is from {@link String} class name to {@link Codec} object. */
+	private static Map codecs = new HashMap();
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/CompressedObjectCodec.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/CompressedObjectCodec.java
new file mode 100755
index 0000000..c2fb54d
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/CompressedObjectCodec.java
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OptionalDataException;
+import java.io.StreamCorruptedException;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+import org.apache.oodt.commons.io.Base64DecodingInputStream;
+import org.apache.oodt.commons.io.Base64EncodingOutputStream;
+import org.apache.oodt.commons.io.NullOutputStream;
+import org.apache.oodt.commons.util.XML;
+import org.apache.oodt.commons.io.CountingOutputStream;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/** A result encoder/decoder for compressed, serialized objects.
+ *
+ * This codec uses a GZIP compressed serialized object format for objects.
+ *
+ * @author Kelly
+ */
+class CompressedObjectCodec implements Codec {
+	public Node encode(Object object, Document doc) throws DOMException {
+		ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
+		try {
+			Base64EncodingOutputStream base64 = new Base64EncodingOutputStream(byteArray);
+			GZIPOutputStream gzip = new GZIPOutputStream(base64);
+			ObjectOutputStream objStream = new ObjectOutputStream(gzip);
+			objStream.writeObject(object);
+			objStream.close();
+		} catch (IOException cantHappen) {}
+		Element value = doc.createElement("resultValue");
+		value.appendChild(doc.createCDATASection(byteArray.toString()));
+		return value;
+	}
+
+	public Object decode(Node node) throws ClassNotFoundException, InvalidClassException, StreamCorruptedException,
+		OptionalDataException {
+		String encodedValue;
+		if (node.getFirstChild().getNodeType() == Node.CDATA_SECTION_NODE)
+			encodedValue = node.getFirstChild().getNodeValue();
+		else
+			encodedValue = XML.text(node);
+		Object rc = null;
+		try {
+			ByteArrayInputStream byteArray = new ByteArrayInputStream(encodedValue.getBytes());
+			Base64DecodingInputStream base64 = new Base64DecodingInputStream(byteArray);
+			GZIPInputStream gzip = new GZIPInputStream(base64);
+			ObjectInputStream objStream = new ObjectInputStream(gzip);
+			rc = objStream.readObject();
+			objStream.close();
+		} catch (InvalidClassException ex) {
+			throw ex;
+		} catch (StreamCorruptedException ex) {
+			throw ex;
+		} catch (OptionalDataException ex) {
+			throw ex;
+		} catch (IOException cantHappen) {}
+		return rc;
+	}
+
+	public InputStream getInputStream(Object value) throws IOException {
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		ObjectOutputStream oos = new ObjectOutputStream(baos);
+		oos.writeObject(value);
+		oos.close();
+		baos.close();
+		return new ByteArrayInputStream(baos.toByteArray());
+	}
+
+	public long sizeOf(Object obj) {
+		try {
+			CountingOutputStream c = new CountingOutputStream(new NullOutputStream());
+			ObjectOutputStream stream = new ObjectOutputStream(c);
+			stream.writeObject(obj);
+			stream.close();
+			return c.getBytesWritten();
+		} catch (IOException ex) {
+			throw new IllegalStateException("I/O exception " + ex.getClass().getName() + " can't happen, yet did: "
+				+ ex.getMessage());
+		}
+	}
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/CompressedStringCodec.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/CompressedStringCodec.java
new file mode 100755
index 0000000..2fa309c
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/CompressedStringCodec.java
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+import org.apache.oodt.commons.io.Base64DecodingInputStream;
+import org.apache.oodt.commons.io.Base64EncodingOutputStream;
+import org.apache.oodt.commons.util.XML;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/** A result encoder/decoder for compressed strings.
+ *
+ * This codec uses a GZIP compressed string format for objects.
+ *
+ * @author Kelly
+ */
+class CompressedStringCodec implements Codec {
+	public Node encode(Object object, Document doc) throws DOMException {
+		ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
+		try {
+			Base64EncodingOutputStream base64 = new Base64EncodingOutputStream(byteArray);
+			GZIPOutputStream gzip = new GZIPOutputStream(base64);
+			gzip.write(object.toString().getBytes());
+			gzip.close();
+		} catch (IOException cantHappen) {}
+		Element value = doc.createElement("resultValue");
+		value.appendChild(doc.createCDATASection(byteArray.toString()));
+		return value;
+	}
+
+	public Object decode(Node node) {
+		String encodedValue;
+		if (node.getFirstChild().getNodeType() == Node.CDATA_SECTION_NODE)
+			encodedValue = node.getFirstChild().getNodeValue();
+		else
+			encodedValue = XML.text(node);
+		String rc = null;
+		try {
+			ByteArrayInputStream byteArray = new ByteArrayInputStream(encodedValue.getBytes());
+			Base64DecodingInputStream base64 = new Base64DecodingInputStream(byteArray);
+			GZIPInputStream gzip = new GZIPInputStream(base64);
+			StringBuffer b = new StringBuffer();
+			int numRead;
+			byte[] buf = new byte[1024];
+			while ((numRead = gzip.read(buf)) != -1)
+				b.append(new String(buf, 0, numRead));
+			gzip.close();
+			rc = b.toString();
+		} catch (IOException cantHappen) {}
+		return rc;
+	}
+
+	public InputStream getInputStream(Object value) {
+		return new ByteArrayInputStream(((String) value).getBytes());
+	}
+
+	public long sizeOf(Object obj) {
+		return ((String) obj).getBytes().length;
+	}
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Header.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Header.java
new file mode 100755
index 0000000..7cb7dab
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Header.java
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import org.apache.oodt.commons.util.*;
+import org.w3c.dom.*;
+
+/** A single header.
+ *
+ * An object of this class is a header element of a query.
+ *
+ * @author Kelly
+ */
+public class Header implements Serializable, Cloneable, Documentable {
+	/** Create a list of headers from an XML document.
+	 *
+	 * @param root A &lt;resultHeader&gt; element.
+	 * @return A list of <code>Header</code>s.
+	 */
+	public static List createHeaders(Node root) {
+		if (!"resultHeader".equals(root.getNodeName()))
+			throw new IllegalArgumentException("Expected <resultHeader> but got <" + root.getNodeName() + ">");
+		NodeList children = root.getChildNodes();
+		List rc = new ArrayList();
+		for (int i = 0; i < children.getLength(); ++i){
+			Node node = children.item(i);
+			if (node.getNodeType() == Node.ELEMENT_NODE) {
+				Header header = new Header(node);
+				rc.add(header);
+			}
+		}
+		return rc;
+	}
+
+	/** Create a new, blank header.
+	 *
+	 * This initializes the result with default values for various properties.
+	 */
+	public Header() {
+		this(/*name*/"UNKNOWN");
+	}
+
+	/** Create a header.
+	 *
+	 * Here, you specify the header's name only.
+	 *
+	 * @param name Name of this header.
+	 */
+	public Header(String name) {
+		this(name, /*type*/null, /*unit*/null);
+	}
+
+	/** Create a fully specified header.
+	 *
+	 * @param name Name of this header.
+	 * @param type Data type.
+	 * @param unit Units.
+	 */
+	public Header(String name, String type, String unit) {
+		this.name = name;
+		this.type = type;
+		this.unit = unit;
+	}
+
+	/** Create a header from a DOM node.
+	 *
+	 * @param node The DOM node, which must be a &lt;headerElement&gt; element.
+	 */
+	public Header(Node node) {
+		if (!"headerElement".equals(node.getNodeName()))
+			throw new IllegalArgumentException("Header must be constructed from <headerElement> node, not <"
+				+ node.getNodeName() + ">");
+		NodeList children = node.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node child = children.item(i);
+			if ("elemName".equals(child.getNodeName()))
+				name = XML.unwrappedText(child);
+			else if ("elemType".equals(child.getNodeName()))
+				type = XML.unwrappedText(child);
+			else if ("elemUnit".equals(child.getNodeName()))
+				unit = XML.unwrappedText(child);
+		}
+	}
+
+	/** Get the name.
+	 *
+	 * @return The name of the header, suitable for printing in a column heading.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/** Get the type of this result.
+	 *
+	 * @return The type, as in data type.
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/** Get the unit.
+	 *
+	 * @return The units in which the header is presented.
+	 */
+	public String getUnit() {
+		return unit;
+	}
+
+	/** Set the name.
+	 *
+	 * @param name The name of the header, suitable for printing in a column heading.
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	/** Set the type of this result.
+	 *
+	 * @param type The type, as in data type.
+	 */
+	public void setType(String type) {
+		this.type = type;
+	}
+
+	/** Set the unit.
+	 *
+	 * @param unit The units in which the header is presented.
+	 */
+	public void setUnit(String unit) {
+		this.unit = unit;
+	}
+
+	public Node toXML(Document doc) throws DOMException {
+		Element root = doc.createElement("headerElement");
+		XML.add(root, "elemName", getName());
+		XML.addNonNull(root, "elemType", getType());
+		XML.addNonNull(root, "elemUnit", getUnit());
+		return root;
+	}
+
+	public int hashCode() {
+		return name.hashCode();
+	}
+
+	public boolean equals(Object rhs) {
+		if (rhs == this) return true;
+		if (rhs == null || !(rhs instanceof Header)) return false;
+		Header obj = (Header) rhs;
+		return name.equals(obj.name) && ((type == null && obj.type == null) || type.equals(obj.type))
+			&& ((unit == null && obj.unit == null) || unit.equals(obj.unit));
+	}
+
+	public Object clone() {
+		Object rc = null;
+		try {
+			rc = super.clone();
+		} catch (CloneNotSupportedException cantHappen) {
+			throw new RuntimeException("CloneNotSupportedException thrown for class that implements Cloneable: "
+				+ cantHappen.getMessage());
+		}
+		return rc;
+	}
+
+	public String toString() {
+		return getClass().getName() + "[name=" + getName() + ",type=" + getType() + ",unit=" + getUnit() + "]";
+	}
+
+	/** Name of the header. */
+	private String name;
+
+	/** Type, as in type of the data. */
+	private String type;
+
+	/** Unit, as in the units of the data type. */
+	private String unit;
+
+        /** Serial version unique ID. */
+        static final long serialVersionUID = -4596588383046581840L;
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/ObjectCodec.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/ObjectCodec.java
new file mode 100755
index 0000000..1065794
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/ObjectCodec.java
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OptionalDataException;
+import java.io.StreamCorruptedException;
+import org.apache.oodt.commons.io.Base64DecodingInputStream;
+import org.apache.oodt.commons.io.Base64EncodingOutputStream;
+import org.apache.oodt.commons.io.NullOutputStream;
+import org.apache.oodt.commons.util.XML;
+import org.apache.oodt.commons.io.CountingOutputStream;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/** A result encoder/decoder for serialized objects.
+ *
+ * This codec uses a serialized object format for objects.
+ *
+ * @author Kelly
+ */
+class ObjectCodec implements Codec {
+	public Node encode(Object object, Document doc) throws DOMException {
+		ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
+		try {
+			Base64EncodingOutputStream base64 = new Base64EncodingOutputStream(byteArray);
+			ObjectOutputStream objStream = new ObjectOutputStream(base64);
+			objStream.writeObject(object);
+			objStream.close();
+		} catch (IOException cantHappen) {}
+		Element value = doc.createElement("resultValue");
+		value.appendChild(doc.createCDATASection(byteArray.toString()));
+		return value;
+	}
+
+	public Object decode(Node node) throws ClassNotFoundException, InvalidClassException, StreamCorruptedException,
+		OptionalDataException {
+		String encodedValue;
+		if (node.getFirstChild().getNodeType() == Node.CDATA_SECTION_NODE)
+			encodedValue = node.getFirstChild().getNodeValue();
+		else
+			encodedValue = XML.text(node);
+		Object rc = null;
+		try {
+			ByteArrayInputStream byteArray = new ByteArrayInputStream(encodedValue.getBytes());
+			Base64DecodingInputStream base64 = new Base64DecodingInputStream(byteArray);
+			ObjectInputStream objStream = new ObjectInputStream(base64);
+			rc = objStream.readObject();
+			objStream.close();
+		} catch (InvalidClassException ex) {
+			throw ex;
+		} catch (StreamCorruptedException ex) {
+			throw ex;
+		} catch (OptionalDataException ex) {
+			throw ex;
+		} catch (IOException cantHappen) {}
+		return rc;
+	}
+
+	public InputStream getInputStream(Object value) throws IOException {
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		ObjectOutputStream oos = new ObjectOutputStream(baos);
+		oos.writeObject(value);
+		oos.close();
+		baos.close();
+		return new ByteArrayInputStream(baos.toByteArray());
+	}
+
+	public long sizeOf(Object obj) {
+		try {
+			CountingOutputStream c = new CountingOutputStream(new NullOutputStream());
+			ObjectOutputStream stream = new ObjectOutputStream(c);
+			stream.writeObject(obj);
+			stream.close();
+			return c.getBytesWritten();
+		} catch (IOException ex) {
+			throw new IllegalStateException("I/O exception " + ex.getClass().getName() + " can't happen, yet did: "
+				+ ex.getMessage());
+		}
+	}
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/QueryElement.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/QueryElement.java
new file mode 100755
index 0000000..4032e01
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/QueryElement.java
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import org.apache.oodt.commons.util.*;
+import org.w3c.dom.*;
+
+/** A single query element.
+ *
+ * An object of this class is an element of a query.
+ *
+ * <p>TODO: Consider computing proper mime-type based on class of object being inserted as
+ * a value into the result.
+ *
+ * @author Kelly
+ */
+public class QueryElement implements Serializable, Cloneable, Documentable {
+	/** Create a blank query element.
+	 */
+	public QueryElement() {
+		this("UNKNOWN", "UNKNOWN");
+	}
+
+	/** Create a query element.
+	 *
+	 * @param role The role the element plays.
+	 * @param value The value of the element.
+	 */
+	public QueryElement(String role, String value) {
+		this.role = role;
+		this.value = value;
+	}
+
+	public QueryElement(Node node) {
+		if (!"queryElement".equals(node.getNodeName()))
+			throw new IllegalArgumentException("Query element must be constructed from <queryElement> node, not <"
+				+ node.getNodeName() + ">");
+		NodeList children = node.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node child = children.item(i);
+			if ("tokenRole".equals(child.getNodeName()))
+				role = XML.unwrappedText(child);
+			else if ("tokenValue".equals(child.getNodeName()))
+				value = XML.unwrappedText(child);
+		}
+	}
+
+	/** Get my role.
+	 *
+	 * @return The role this element plays.
+	 */
+	public String getRole() {
+		return role;
+	}
+
+	/** Get my value.
+	 *
+	 * @return The value of this element.
+	 */
+	public String getValue() {
+		return value;
+	}
+
+	/** Set my role.
+	 *
+	 * @param role The new role this element plays.
+	 */
+	public void setRole(String role) {
+		if (role == null) role = "UNKNOWN";
+		this.role = role;
+	}
+
+	/** Set my value.
+	 *
+	 * @param value The new value of this element.
+	 */
+	public void setValue(String value) {
+		if (value == null) value = "UNKNOWN";
+		this.value = value;
+	}
+
+	public Node toXML(Document doc) throws DOMException {
+		Element root = doc.createElement("queryElement");
+		XML.add(root, "tokenRole", getRole());
+		XML.add(root, "tokenValue", getValue());
+		return root;
+	}
+
+	public boolean equals(Object rhs) {
+		if (rhs == this) return true;
+		if (rhs == null || !(rhs instanceof QueryElement)) return false;
+		QueryElement obj = (QueryElement) rhs;
+		return role.equals(obj.role) && value.equals(obj.value);
+	}
+
+	public int hashCode() {
+		return role.hashCode() ^ value.hashCode();
+	}
+
+	public Object clone() {
+		Object rc = null;
+		try {
+			rc = super.clone();
+		} catch (CloneNotSupportedException cantHappen) {}
+		return rc;
+	}
+
+	public String toString() {
+		return getClass().getName() + "[role=" + role + ",value=" + value + "]";
+	}
+
+	/** The role I play. */
+	private String role;
+
+	/** The value my role has. */
+	private String value;
+
+        /** Serial version unique ID. */
+        static final long serialVersionUID = -8401434443475540800L;
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/QueryException.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/QueryException.java
new file mode 100755
index 0000000..769e042
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/QueryException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+/** Checked exception to indicate a query fault.
+ *
+ * @author Kelly
+ */
+public class QueryException extends Exception {
+	/** Construct a query exception with no detail message.
+	 */
+	public QueryException() {}
+
+	/** Construct a query exception with the given detail message.
+	 *
+	 * @param msg Detail message.
+	 */
+	public QueryException(String msg) {
+		super(msg);
+	}
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/QueryHeader.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/QueryHeader.java
new file mode 100755
index 0000000..a03ac3f
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/QueryHeader.java
@@ -0,0 +1,300 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.Serializable;
+import java.net.URI;
+import org.apache.oodt.commons.util.Documentable;
+import org.apache.oodt.commons.util.XML;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/** Header of a query
+ *
+ * @author Kelly
+ */
+public class QueryHeader implements Serializable, Cloneable, Documentable {
+	/** Create a blank query header.
+	 */
+	public QueryHeader() {
+		this(/*id*/"UNKNOWN", /*title*/"UNKNOWN", /*desc*/"UNKNOWN", /*type*/"QUERY", /*status*/"ACTIVE",
+			/*security*/"UNKNOWN", /*rev*/"1999-12-12 JSH V1.0 Under Development", /*datadict*/"UNKNOWN");
+	}
+
+	/** Create a query header with the specified values.
+	 *
+	 * @param id The identification of this query.
+	 * @param title The title of this query.
+	 * @param description A string describing this query.
+	 * @param type The type of the query, usually QUERY.
+	 * @param statusID The status of the query.
+	 * @param securityType The type of security to apply to this query.
+	 * @param revisionNote A note about the revision history of this query.
+	 * @param dataDictID The ID of the data dictionary used by this query.
+	 */
+	public QueryHeader(String id, String title, String description, String type, String statusID, String securityType,
+		String revisionNote, String dataDictID) {
+		this.id           = id;
+		this.title        = title;
+		this.description  = description;
+		this.type         = type;
+		this.statusID     = statusID;
+		this.securityType = securityType;
+		this.revisionNote = revisionNote;
+		this.dataDictID   = dataDictID;
+	}
+
+	/** Create a query header from an XML node.
+	 *
+	 * @param node The &lt;queryAttributes&gt; node.
+	 */
+	public QueryHeader(Node node) {
+		if (!"queryAttributes".equals(node.getNodeName()))
+			throw new IllegalArgumentException("QueryHeader must be constructed from <queryAttributes> node, not <"
+				+ node.getNodeName() + ">");
+		NodeList children = node.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node child = children.item(i);
+			if ("queryId".equals(child.getNodeName()))
+				id = XML.unwrappedText(child);
+			else if ("queryTitle".equals(child.getNodeName()))
+				title = XML.unwrappedText(child);
+			else if ("queryDesc".equals(child.getNodeName()))
+				description = XML.unwrappedText(child);
+			else if ("queryType".equals(child.getNodeName()))
+				type = XML.unwrappedText(child);
+			else if ("queryStatusId".equals(child.getNodeName()))
+				statusID = XML.unwrappedText(child);
+			else if ("querySecurityType".equals(child.getNodeName()))
+				securityType = XML.unwrappedText(child);
+			else if ("queryParentId".equals(child.getNodeName()))
+				; // ignore
+			else if ("queryChildId".equals(child.getNodeName()))
+				; // ignore
+			else if ("queryRevisionNote".equals(child.getNodeName()))
+				revisionNote = XML.unwrappedText(child);
+			else if ("queryDataDictId".equals(child.getNodeName()))
+				dataDictID = XML.unwrappedText(child);
+		}
+	}
+
+	/** Get the identification of this query.
+	 *
+	 * @return The identification of this query.
+	 */
+	public String getID() {
+		return id;
+	}
+
+ 	/**
+         * Get the identification of this query as a URI.
+         *
+         * @return an <code>URI</code> value.
+         */
+        public URI getURIID() {
+                return URI.create(id.startsWith("urn")? id : "urn:oodt:query:" + id);
+        }
+
+
+	/** Get the title of this query.
+	 *
+	 * @return The title of this query.
+	 */
+	public String getTitle() {
+		return title;
+	}
+
+	/** Get a string describing this query.
+	 *
+	 * @return A string describing this query.
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/** Get the type of the query, usually QUERY.
+	 *
+	 * @return The type of the query, usually QUERY.
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/** Get the status of the query.
+	 *
+	 * @return The status of the query.
+	 */
+	public String getStatusID() {
+		return statusID;
+	}
+
+	/** Get the type of security to apply to this query.
+	 *
+	 * @return The type of security to apply to this query.
+	 */
+	public String getSecurityType() {
+		return securityType;
+	}
+
+	/** Get a note about the revision history of this query.
+	 *
+	 * @return A note about the revision history of this query.
+	 */
+	public String getRevisionNote() {
+		return revisionNote;
+	}
+
+	/** Get the ID of the data dictionary used by this query.
+	 *
+	 * @return The ID of the data dictionary used by this query.
+	 */
+	public String getDataDictID() {
+		return dataDictID;
+	}
+
+	/** Set the identification of this query.
+	 *
+	 * @param id The identification of this query.
+	 */
+	public void setID(String id) {
+		this.id = id;
+	}
+
+	/** Set the title of this query.
+	 *
+	 * @param title The title of this query.
+	 */
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	/** Set a string describing this query.
+	 *
+	 * @param description A string describing this query.
+	 */
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	/** Set the type of the query, usually QUERY.
+	 *
+	 * @param type The type of the query, usually QUERY.
+	 */
+	public void setType(String type) {
+		this.type = type;
+	}
+
+	/** Set the status of the query.
+	 *
+	 * @param statusID The status of the query.
+	 */
+	public void setStatusID(String statusID) {
+		this.statusID = statusID;
+	}
+
+	/** Set the type of security to apply to this query.
+	 *
+	 * @param securityType The type of security to apply to this query.
+	 */
+	public void setSecurityType(String securityType) {
+		this.securityType = securityType;
+	}
+
+	/** Set a note about the revision history of this query.
+	 *
+	 * @param revisionNote A note about the revision history of this query.
+	 */
+	public void setRevisionNote(String revisionNote) {
+		this.revisionNote = revisionNote;
+	}
+
+	/** Set the ID of the data dictionary used by this query.
+	 *
+	 * @param dataDictID The ID of the data dictionary used by this query.
+	 */
+	public void setDataDictID(String dataDictID) {
+		this.dataDictID = dataDictID;
+	}
+
+	public Node toXML(Document doc) throws DOMException {
+		Element root = doc.createElement("queryAttributes");
+		XML.add(root, "queryId", getID());
+		XML.add(root, "queryTitle", getTitle());
+		XML.add(root, "queryDesc", getDescription());
+		XML.add(root, "queryType", getType());
+		XML.add(root, "queryStatusId", getStatusID());
+		XML.add(root, "querySecurityType", getSecurityType());
+		XML.add(root, "queryRevisionNote", getRevisionNote());
+		XML.add(root, "queryDataDictId", getDataDictID());
+		return root;
+	}
+
+	public int hashCode() {
+		return getID().hashCode();
+	}
+
+	public boolean equals(Object rhs) {
+		if (rhs == this) return true;
+		if (rhs == null || !(rhs instanceof QueryHeader)) return false;
+		QueryHeader obj = (QueryHeader) rhs;
+		return getID().equals(obj.getID());
+	}
+
+	public Object clone() {
+		Object rc = null;
+		try {
+			rc = super.clone();
+		} catch (CloneNotSupportedException cantHappen) {}
+		return rc;
+	}
+
+	public String toString() {
+		return getClass().getName() + "[id=" + id + "]";
+	}
+
+	/** The identification of this query. */
+	private String id;
+
+	/** The title of this query. */
+	private String title;
+
+	/** A string describing this query. */
+	private String description;
+
+	/** The type of the query, usually QUERY. */
+	private String type;
+
+	/** The status of the query. */
+	private String statusID;
+
+	/** The type of security to apply to this query. */
+	private String securityType;
+
+	/** A note about the revision history of this query. */
+	private String revisionNote;
+
+	/** The ID of the data dictionary used by this query. */
+	private String dataDictID;
+
+	/** Serial version unique ID. */
+        static final long serialVersionUID = -8601229234696670816L;
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/QueryResult.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/QueryResult.java
new file mode 100755
index 0000000..2267b92
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/QueryResult.java
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.oodt.product.Retriever;
+import org.apache.oodt.commons.util.Documentable;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Results of a query.
+ *
+ * @author Kelly
+ */
+public class QueryResult implements Serializable, Cloneable, Documentable {
+	/**
+	 * Create empty results.
+	 */
+	public QueryResult() {
+		this.list = new ArrayList();
+	}
+
+	/**
+	 * Create results from the given list of results.
+	 *
+	 * @param list List of {@link Result}s.
+	 */
+	public QueryResult(List list) {
+		this.list = list;
+	}
+
+	/**
+	 * Create results from an XML node.
+	 *
+	 * @param node The &lt;queryResultSet&gt; node.
+	 */
+	public QueryResult(Node node) {
+		if (!"queryResultSet".equals(node.getNodeName()))
+			throw new IllegalArgumentException("QueryResult must be constructed from <queryResultSet> node, not <"
+				+ node.getNodeName() + ">");
+		list = new ArrayList();
+		NodeList children = node.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node child = children.item(i);
+			if (child.getNodeType() == Node.ELEMENT_NODE && "resultElement".equals(child.getNodeName()))
+				list.add(new Result(child));
+		}
+	}
+
+	/**
+	 * Get the list of results.
+	 *
+	 * @return A list of {@link Result}s.
+	 */
+	public List getList() {
+		return list;
+	}
+
+	/**
+	 * Clear out any results.
+	 */
+	public void clear() {
+		list.clear();
+	}
+
+	public Node toXML(Document doc) throws DOMException {
+		Element root = doc.createElement("queryResultSet");
+		for (Iterator i = list.iterator(); i.hasNext();) {
+			Result r = (Result) i.next();
+			root.appendChild(r.toXML(doc));
+		}
+		return root;
+	}
+
+	public int hashCode() {
+		return list.hashCode();
+	}
+
+	public boolean equals(Object obj) {
+		if (obj == this) return true;
+		if (obj instanceof QueryResult) {
+			QueryResult rhs = (QueryResult) obj;
+			return list.equals(rhs.list);
+		}
+		return false;
+	}
+
+	public Object clone() {
+		try {
+			return super.clone();
+		} catch (CloneNotSupportedException cantHappen) {
+			throw new IllegalStateException("CloneNotSupportedException happened: " + cantHappen.getMessage());
+		}
+	}
+
+	public String toString() {
+		return getClass().getName() + "[list=" + list + "]";
+	}
+
+	public void setRetriever(Retriever retriever) {
+		for (Iterator i = list.iterator(); i.hasNext();) {
+			Result r = (Result) i.next();
+			r.setRetriever(retriever);
+		}
+	}
+
+	public long getSize() {
+		long size = 0;
+		for (Iterator i = list.iterator(); i.hasNext();) {
+			Result r = (Result) i.next();
+			size += r.getSize();
+		}
+		return size;
+	}
+
+	/** List of {@link Result}s. */
+	private List list;
+
+	/** Serial version unique ID. */
+	static final long serialVersionUID = 9156030927051226848L;
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Result.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Result.java
new file mode 100755
index 0000000..73ad7e7
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Result.java
@@ -0,0 +1,416 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import org.apache.oodt.commons.util.*;
+import org.w3c.dom.*;
+import org.apache.oodt.product.Retriever;
+import java.net.URI;
+
+/** A single result.
+ *
+ * An object of this class is a result of a query.
+ *
+ * @author Kelly
+ */
+public class Result implements Serializable, Cloneable, Documentable {
+	/** Create a new, blank result.
+	 *
+	 * This initializes the result with default values for various properties.
+	 */
+	public Result() {
+		this(/*id*/"UNKNOWN", /*mimeType*/"UNKNOWN", /*profileId*/"UNKNOWN", /*resourceId*/"UNKNOWN",
+			/*resultHeader*/ new ArrayList(), /*value*/"");
+	}
+
+	/** Create a result.
+	 *
+	 * Here, you specify the result's ID and value only.
+	 *
+	 * @param id Identification of this result.
+	 * @param value The result.
+	 */
+	public Result(String id, Object value) {
+		this(id, /*mimeType*/"UNKNOWN", /*profileId*/"UNKNOWN", /*resourceId*/"UNKNOWN",
+			/*resultHeader*/ new ArrayList(), value);
+	}
+
+	/**
+	 * Create a more fully specified result that's not classified and lasts forever.
+	 *
+	 * @param id Identification of this result.
+	 * @param mimeType MIME Type.
+	 * @param profileID ID of the resource profile where this result originated.
+	 * @param resourceID ID of the resource where this result originated.
+	 * @param headers A header elements, describing the result.
+	 * @param value The result.
+	 */
+	public Result(String id, String mimeType, String profileID, String resourceID, List headers, Object value) {
+		this(id, mimeType, profileID, resourceID, headers, value, /*classified*/false, /*validity*/INFINITE);
+	}
+
+	/**
+	 * Create a fully specified result.
+	 *
+	 * @param id Identification of this result.
+	 * @param mimeType MIME Type.
+	 * @param profileID ID of the resource profile where this result originated.
+	 * @param resourceID ID of the resource where this result originated.
+	 * @param headers A header elements, describing the result.
+	 * @param value The result.
+	 * @param classified True if this result is secret, false otherwise.
+	 * @param validity Time for how long this product is valid in milliseconds or {@link #INFINITE}.
+	 */
+	public Result(String id, String mimeType, String profileID, String resourceID, List headers, Object value,
+		boolean classified, long validity) {
+		if (validity < 0 && validity != INFINITE)
+			throw new IllegalArgumentException("Validity must be a nonnegative time in milliseconds or "
+				+ " Result.INFINITE to indicate no expiration");
+		if (!codecs.containsKey(mimeType))
+			throw new IllegalArgumentException("MIME type \"" + mimeType + "\" unknown");
+		for (Iterator i = headers.iterator(); i.hasNext();) {
+			Object header = i.next();
+			if (!(header instanceof Header))
+				throw new IllegalArgumentException("List of headers doesn't contain Header object");
+		}
+
+		this.id         = id;
+		this.mimeType   = mimeType;
+		this.profileID  = profileID;
+		this.resourceID = resourceID;
+		this.headers    = headers;
+		this.value      = value;
+		this.classified = classified;
+		this.validity   = validity;
+	}
+
+	/** Create a result from a DOM node.
+	 *
+	 * @param node The DOM node, which must be a &lt;resultElement&gt; element.
+	 */
+	public Result(Node node) {
+		if (!"resultElement".equals(node.getNodeName()))
+			throw new IllegalArgumentException("Result must be constructed from <resultElement> node, not <"
+				+ node.getNodeName() + ">");
+		Element rootElement = (Element) node;
+		classified = "true".equals(rootElement.getAttribute("classified"));
+		validity = Long.parseLong(rootElement.getAttribute("validity"));
+		NodeList children = node.getChildNodes();
+		String encodedValue = null;
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node child = children.item(i);
+			if ("resultId".equals(child.getNodeName()))
+				id = XML.unwrappedText(child);
+			else if ("resultMimeType".equals(child.getNodeName()))
+				mimeType = XML.unwrappedText(child);
+			else if ("profId".equals(child.getNodeName()))
+				profileID = XML.unwrappedText(child);
+			else if ("identifier".equals(child.getNodeName()))
+				resourceID = XML.unwrappedText(child);
+			else if ("resultHeader".equals(child.getNodeName()))
+				headers = Header.createHeaders(child);
+			else if ("resultValue".equals(child.getNodeName())) {
+				Codec codec = (Codec) codecs.get(mimeType);
+				if (codec == null)
+					throw new IllegalArgumentException("Unkown MIME type \"" + mimeType
+						+ "\" in <resultElement>'s <resultMimeType>");
+				try {
+					value = codec.decode(child);
+				} catch (RuntimeException ex) {
+					throw ex;
+				} catch (Exception ex) {
+					throw new IllegalArgumentException("Bad encoding of " + mimeType + " object");
+				}
+			}
+		}
+	}
+
+	/** Get the result ID.
+	 *
+	 * @return The identification of this result.
+	 */
+	public String getID() {
+		return id;
+	}
+
+	public URI getURIID() {
+		return URI.create(id.startsWith("urn")? id : "urn:eda:result:unspec:" + id);
+	}
+
+	/** Get the MIME type of this result.
+	 *
+	 * @return The MIME type.
+	 */
+	public String getMimeType() {
+		return mimeType;
+	}
+
+	/** Get the profile ID.
+	 *
+	 * @return The ID of the resource profile where this result originated.
+	 */
+	public String getProfileID() {
+		return profileID;
+	}
+
+	/** Get the resource ID.
+	 *
+	 * @return The ID of the resource where this result originated.
+	 */
+	public String getResourceID() {
+		return resourceID;
+	}
+
+	/** Get the headers.
+	 *
+	 * @return A list of {@link Header}s describing the result.
+	 */
+	public List getHeaders() {
+		return headers;
+	}
+
+	/** Get the result's value.
+	 *
+	 * @return The result instance.
+	 * @deprecated This method requires the caller to know the return type and to
+	 * downcast to it; further, the result may be too large to contain in memory.  Use
+	 * {@link #getInputStream} instead to perform stream processing on product data.
+	 */
+	public Object getValue() {
+		return value;
+	}
+
+	/** Set the result ID.
+	 *
+	 * @param id The identification of this result.
+	 */
+	public void setID(String id) {
+		this.id = id;
+	}
+
+	/** Set the MIME type of this result.
+	 *
+	 * @param mimeType The MIME type.
+	 */
+	public void setMimeType(String mimeType) {
+		this.mimeType = mimeType;
+	}
+
+	/** Set the profile ID.
+	 *
+	 * @param profileID The ID of the resource profile where this result originated.
+	 */
+	public void setProfileID(String profileID) {
+		this.profileID = profileID;
+	}
+
+	/** Set the resource ID.
+	 *
+	 * @param resourceID The ID of the resource where this result originated.
+	 */
+	public void setResourceID(String resourceID) {
+		this.resourceID = resourceID;
+	}
+
+	/** Set the result's value.
+	 *
+	 * @param value The result instance.
+	 */
+	public void setValue(Object value) {
+		this.value = value;
+	}
+
+	/**
+	 * Get the size of this product.
+	 *
+	 * @return Size in bytes.
+	 */
+	public long getSize() {
+		Codec codec = (Codec) codecs.get(mimeType);
+		if (codec == null) throw new IllegalStateException("No codec available for supposedly valid MIME type \""
+			+ mimeType + "\"");
+		return codec.sizeOf(value);
+	}
+
+	public Node toXML(Document doc) throws DOMException {
+		Element root = doc.createElement("resultElement");
+		root.setAttribute("classified", String.valueOf(classified));
+		root.setAttribute("validity", String.valueOf(validity));
+		XML.add(root, "resultId", id);
+		XML.add(root, "resultMimeType", mimeType);
+		XML.add(root, "profId", profileID);
+		XML.add(root, "identifier", resourceID);
+		Element resultHeader = doc.createElement("resultHeader");
+		root.appendChild(resultHeader);
+		for (Iterator i = headers.iterator(); i.hasNext();) {
+			Header header = (Header) i.next();
+			resultHeader.appendChild(header.toXML(doc));
+		}
+		Codec codec = (Codec) codecs.get(mimeType);
+		if (codec == null) throw new IllegalStateException("No codec available for supposedly valid MIME type \""
+			+ mimeType + "\"");
+		root.appendChild(codec.encode(value, doc));
+		return root;
+	}
+
+	/**
+	 * Get an input stream version of the result's value.
+	 *
+	 * @return an <code>InputStream</code> value.
+	 * @throws IOException if an error occurs.
+	 */
+	public InputStream getInputStream() throws IOException {
+		Codec codec = (Codec) codecs.get(mimeType);
+		if (codec == null) throw new IllegalStateException("No codec available for allegedly valid MIME type \""
+			+ mimeType + "\"");
+		return codec.getInputStream(value);
+	}
+
+	/**
+	 * Is this result classified?
+	 *
+	 * @return a boolean value.
+	 */
+	public boolean isClassified() {
+		return classified;
+	}
+
+	/**
+	 * Set whether this result is classified.
+	 *
+	 * @param classified a boolean value.
+	 */
+	public void setClassified(boolean classified) {
+		this.classified = classified;
+	}
+
+	/**
+	 * Get how long this product is valid.
+	 *
+	 * @return Time in milliseconds or {@link #INFINITE}.
+	 */
+	public long getValidity() {
+		return validity;
+	}
+
+	/**
+	 * Set the time this product is valid.
+	 *
+	 * @param validity Time in milliseconds or {@link #INFINITE}.
+	 */
+	public void setValidity(long validity) {
+		this.validity = validity;
+	}
+
+	public int hashCode() {
+		return id.hashCode() ^ mimeType.hashCode() ^ profileID.hashCode() ^ resourceID.hashCode() ^ headers.hashCode()
+			^ value.hashCode();
+	}
+
+	public boolean equals(Object rhs) {
+		if (rhs == this) return true;
+		if (rhs == null || !(rhs instanceof Result)) return false;
+		Result obj = (Result) rhs;
+		return id.equals(obj.id) && mimeType.equals(obj.mimeType) && profileID.equals(obj.profileID)
+			&& resourceID.equals(obj.resourceID) && headers.equals(obj.headers) && value.equals(obj.value);
+	}
+
+	public Object clone() {
+		Object rc = null;
+		try {
+			rc = super.clone();
+		} catch (CloneNotSupportedException cantHappen) {
+			throw new RuntimeException("CloneNotSupportedException thrown for class that implements Cloneable: "
+				+ cantHappen.getMessage());
+		}
+		return rc;
+	}
+
+	public void setRetriever(Retriever retriever) {
+		if (retriever == null) throw new IllegalArgumentException("retriever must be non-null");
+		if (this.retriever == null) this.retriever = retriever;
+	}
+
+	public String toString() {
+		return getClass().getName() + "[id=" + getID() + ",mimeType=" + getMimeType() + ",profileID=" + getProfileID()
+			+ ",resourceID=" + getResourceID() + ",value=" + getValue() + "]";
+	}
+
+	/** The identification of this result. */
+	protected String id;
+
+	/** The MIME type. */
+	protected String mimeType;
+
+	/** The ID of the resource profile where this result originated. */
+	private String profileID;
+
+	/** The ID of the resource where this result originated. */
+	private String resourceID;
+
+	/** The headers describing the result. */
+	private List headers;
+
+	/** The result instance. */
+	protected Object value;
+
+	/** True if this product is classified. */
+	private boolean classified;
+
+	/** For how long the product's good. */
+	private long validity;
+
+	/** Mapping of MIME type to codec. */
+	protected static Map codecs;
+
+	/** Object to retrieve this product's data. */
+	protected transient Retriever retriever;
+
+	/** Initialize the set of valid MIME types. */
+	static {
+		codecs = new HashMap();
+		try {
+			java.io.InputStream inp = Result.class.getResourceAsStream("mime.properties");
+			BufferedInputStream in = new BufferedInputStream(inp);
+			Properties props = new Properties();
+			props.load(in);
+			in.close();
+			for (Iterator i = props.entrySet().iterator(); i.hasNext();) {
+				Map.Entry entry = (Map.Entry) i.next();
+				codecs.put(entry.getKey(), CodecFactory.createCodec((String) entry.getValue()));
+			}
+		} catch (IOException ex) {
+			System.err.println("I/O exception WHILE reading mime.properties: " + ex.getMessage());
+			ex.printStackTrace();
+			System.err.println("No valid MIME types will be recognized by class Result");
+		}
+
+		// Add our own special MIME type:
+		codecs.put("UNKNOWN",CodecFactory.createCodec("org.apache.oodt.xmlquery.UnsupportedMimeTypeCodec"));
+	}
+
+	/** Serial version unique ID. */
+	static final long serialVersionUID = 9169143944191239575L;
+
+	/** Sentinel value for validity that indicates a product never expires. */
+	public static final long INFINITE = -1;
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Results.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Results.java
new file mode 100755
index 0000000..69cf39c
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Results.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+package org.apache.oodt.xmlquery;
+
+import java.util.Vector;
+import org.apache.oodt.commons.util.*;
+
+/************************************************************************
+**
+** Results
+**
+** This will manage a list of results
+**
+*************************************************************************/
+
+public class Results
+{
+    Vector v;
+
+    public Results()
+    {
+
+        v = new Vector();
+    }
+
+    public synchronized void addItem(Object o)
+    {
+        v.addElement(o);
+    }
+
+    public synchronized void removeItem(int i)
+    {
+        v.removeElementAt(i);
+    }
+
+    public synchronized int getCount()
+    {
+        return(v.size());
+    }
+
+    public synchronized Object getItem(int i)
+    {
+        return((Object) v.elementAt(i));
+    }
+}
+
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Statistic.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Statistic.java
new file mode 100755
index 0000000..c706ba2
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/Statistic.java
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ */
+
+/*
+ *	EDM Statistic Class
+ */
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import org.apache.oodt.commons.Configuration;
+import org.apache.oodt.commons.util.DOMParser;
+import org.apache.oodt.commons.util.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/**
+ * EDM Statisti class. 
+ */
+public class Statistic implements java.io.Serializable, Cloneable 
+{
+        /** Serial version unique ID. */
+        static final long serialVersionUID = 8611279755682736062L;
+	
+        /** URL. */
+	private String url;
+
+	/** Time. */
+	private long time;
+
+	public Statistic()
+        {
+		url = new String("UNKNOWN");
+		time = 0;
+	}
+
+	/** Constructor.
+	 *
+	 * @param url  The server's URL. 
+	 * @param time The search time used by the server indicted by url.
+         */
+	public Statistic(String url, long time) 
+	{
+		this.url=url;
+		this.time= time;
+	}
+
+         /**
+         * Instantiates an Statistic instance from an Statistic structure in DOM node format.
+         *
+         * @param root  The DOM node.
+         */
+	public Statistic(Node root)
+	{
+		Node node;
+	        String nodeName;
+
+	        for (node = root.getFirstChild();
+            		node != null; node = node.getNextSibling())
+        	{
+                	if (node instanceof Element)
+                	{
+                    		nodeName = node.getNodeName();
+                    		if (nodeName.compareTo("url") == 0)
+                        	   url = XML.unwrappedText(node);
+                    		else
+                    		if (nodeName.compareTo("time") == 0)
+                        	   time = Long.parseLong(XML.unwrappedText(node));
+                 	}
+         	}
+   	}
+
+        /**
+         *  doc The org.w3c.dom.Document object.
+         */
+	public synchronized Node toXML(Document doc) throws DOMException
+  	{
+                Element root = doc.createElement("statistic");
+                XML.add(root, "url", url);
+                XML.add(root, "time", ""+time);
+                return root;
+        }
+
+
+        /**
+         * Gets the URL string.
+         *
+         * @return The URL string.
+         */
+	public synchronized String getURL () {
+		return url;
+	}
+
+
+        /**
+         * Gets the search time
+         *
+         * @return the time
+         */
+	public synchronized long getTime()
+	{
+		return time;
+	}
+	
+	/**
+         * Sets the search time         */              
+        public synchronized void setTime(long time)
+        {
+		 this.time= time;
+        }
+
+	public static void main(String[] args) throws Exception
+	{
+		Statistic sta = new Statistic("DDM", 1200);	// test constructor 2
+		System.err.println("Profile Server:"+sta.getURL());
+		System.err.println("Search time:"+sta.getTime());
+		Statistic sta1 = new Statistic();		// test construct 1
+		System.err.println("Profile Server:"+sta1.getURL());
+                System.err.println("Search time:"+sta1.getTime());
+		
+		// create a document
+		Document doc = XML.createDocument();
+                Element StatisticNode = doc.createElement("Statistic");
+                doc.appendChild(StatisticNode);
+		XML.add(StatisticNode, "url", "DMIE");
+		XML.add(StatisticNode, "time", ""+2000);
+
+
+		Element root = doc.getDocumentElement();	//test constructor 3
+		Statistic sta2 = new Statistic(root);	
+		System.err.println("Profile Server:"+sta2.getURL());
+                System.err.println("Search time:"+sta2.getTime());
+
+
+		//test toXML()
+		Node root1 = sta2.toXML(doc);
+		Statistic sta3 = new Statistic(root1);
+                System.err.println("Profile Server:"+sta3.getURL());
+                System.err.println("Search time:"+sta3.getTime());
+	}
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/StringCodec.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/StringCodec.java
new file mode 100755
index 0000000..73713d3
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/StringCodec.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.zip.*;
+import org.apache.oodt.commons.util.*;
+import org.w3c.dom.*;
+
+/** A result encoder/decoder for strings.
+ *
+ * This codec uses a string format for objects.
+ *
+ * @author Kelly
+ */
+class StringCodec implements Codec {
+	public Node encode(Object object, Document doc) throws DOMException {
+		Element value = doc.createElement("resultValue");
+		value.setAttribute("xml:space", "preserve");
+		value.appendChild(doc.createTextNode(object.toString()));
+		return value;
+	}
+
+	public Object decode(Node node) {
+		return XML.text(node);
+	}
+
+	public InputStream getInputStream(Object value) throws IOException {
+		return new ByteArrayInputStream(((String) value).getBytes());
+	}
+
+	public long sizeOf(Object object) {
+		return ((String) object).getBytes().length;
+	}
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/UnsupportedMimeTypeCodec.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/UnsupportedMimeTypeCodec.java
new file mode 100755
index 0000000..9afe8e4
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/UnsupportedMimeTypeCodec.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import org.w3c.dom.*;
+
+/** A result encoder/decoder for unsupported MIME types.
+ *
+ * This codec throws <code>UnsupportedOperationException</code>s on any encoding or
+ * decoding attempt.
+ *
+ * @author Kelly
+ */
+class UnsupportedMimeTypeCodec implements Codec {
+	public Node encode(Object object, Document doc) {
+		throw new UnsupportedOperationException("MIME type not supported for encoding");
+	}
+	public Object decode(Node node) {
+		throw new UnsupportedOperationException("MIME type not supported for decoding");
+	}
+	public long sizeOf(Object object) {
+		throw new UnsupportedOperationException("MIME type not supported for sizing");
+	}
+	public InputStream getInputStream(Object object) {
+		throw new UnsupportedOperationException("MIME type not supported for streaming");
+	}
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/XMLQuery.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/XMLQuery.java
new file mode 100755
index 0000000..255e487
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/XMLQuery.java
@@ -0,0 +1,964 @@
+/*
+ * 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.
+ */
+
+
+/*
+	EDA XML Query Class
+ */
+
+package org.apache.oodt.xmlquery;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.StreamTokenizer;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.apache.oodt.product.Retriever;
+import org.apache.oodt.commons.util.EnterpriseEntityResolver;
+import org.apache.oodt.commons.util.XML;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.SAXException;
+
+/**
+ * EDA XML query class. Parses a DIS style keyword query and creates query 
+ * SELECT, FROM, and WHERE clauses. An XML DOM structure and an XML document
+ * representing the query can also be created. A RESULT set can be added to 
+ * and retrieve. 
+ *
+ */
+public class XMLQuery implements java.io.Serializable, Cloneable {
+	/** Result mode. */
+	private String resultModeId;
+
+	/** Propogation type. */
+	private String propogationType;
+
+	/** # of levels to propogate, depending on propogation type. */
+	private String propogationLevels;
+
+	/** Max results allowed. */
+	private int maxResults = DEFAULT_MAX_RESULTS;
+
+	/** KWQ, as a string. */
+	private String kwqString;
+
+	/** List of acceptable MIME types. */
+	private List mimeAccept;
+
+	/** List of statistics. */
+        private List statistics = new ArrayList();
+
+	/** Number of results so far.
+	 *
+	 * This could be greater than <code>results.size()</code> because that's limited by maxResults.
+	 *
+	 * Meh, this isn't even updated by anyone as far as I can tell.
+	 */
+	protected int numResults;
+
+	private QueryHeader queryHeader;
+	private List selectElementSet = new ArrayList();
+	private List fromElementSet = new ArrayList();
+	private List whereElementSet = new ArrayList();
+	private QueryResult result = new QueryResult();
+
+	private transient StreamTokenizer tokens; // Used for parse
+	private transient String lpart;           // parser left part
+	private transient String opart;           // parser operator
+	private transient String rpart;           // parser right part
+	private transient String previous_token;  // parser - allows backout
+	private transient int qfsc = 0;           // query from set item count
+	private transient int qwsc = 0;           // query where set item count
+	private transient int lit = 0;            // last query item type ("from" or "where" clause)
+	public static final String[] FROM_TOKENS = {};
+
+	/** Constructor.
+	 *
+	 * @param keywordQuery  The DIS style keyword query string.
+	 * @param id A query identifier.
+	 * @param title A terse description of the query for display.
+	 * @param desc A description of the query.
+	 * @param ddId The data dictionary identifier.    
+	 * @param resultModeId Indicates the return of INSTANCE, PROFILE, or CLASS.
+	 * @param propType Indicates query BROADCAST or PROPOGATE.
+	 * @param propLevels Number of propogation levels.
+	 * @param maxResults Maximum number of results to be returned.
+	 */
+	public XMLQuery(String keywordQuery, String id, String title, String desc, String ddId, String resultModeId,
+		String propType, String propLevels, int maxResults) {
+		this(keywordQuery, id, title, desc, ddId, resultModeId, propType, propLevels, maxResults, null, true);
+	}
+
+	/** Constructor.
+	 *
+	 * @param keywordQuery  The DIS style keyword query string.
+	 * @param id A query identifier.
+	 * @param title A terse description of the query for display.
+	 * @param desc A description of the query.
+	 * @param ddId The data dictionary identifier.    
+	 * @param resultModeId Indicates the return of INSTANCE, PROFILE, or CLASS.
+	 * @param propType Indicates query BROADCAST or PROPOGATE.
+	 * @param propLevels Number of propogation levels.
+	 * @param maxResults Maximum number of results to be returned.
+	 * @param parseQuery Indicates whether query should be parsed
+	 */
+	public XMLQuery(String keywordQuery, String id, String title, String desc, String ddId, String resultModeId,
+		String propType, String propLevels, int maxResults, boolean parseQuery) {
+		this(keywordQuery, id, title, desc, ddId, resultModeId, propType, propLevels, maxResults, null, parseQuery);
+	}
+
+	/** Constructor.
+	 *
+	 * @param keywordQuery  The DIS style keyword query string.
+	 * @param id A query identifier.
+	 * @param title A terse description of the query for display.
+	 * @param desc A description of the query.
+	 * @param ddId The data dictionary identifier.    
+	 * @param resultModeId Indicates the return of INSTANCE, PROFILE, or CLASS.
+	 * @param propType Indicates query BROADCAST or PROPOGATE.
+	 * @param propLevels Number of propogation levels.
+	 * @param maxResults Maximum number of results to be returned.
+	 * @param mimeAccept List of acceptable MIME types.
+	 */
+	public XMLQuery(String keywordQuery, String id, String title, String desc, String ddId, String resultModeId,
+		String propType, String propLevels, int maxResults, List mimeAccept) {
+		this(keywordQuery, id, title, desc, ddId, resultModeId, propType, propLevels, maxResults, mimeAccept, true);
+	}
+                        
+	/** Constructor.
+	 *
+	 * @param keywordQuery  The DIS style keyword query string.
+	 * @param id A query identifier.
+	 * @param title A terse description of the query for display.
+	 * @param desc A description of the query.
+	 * @param ddId The data dictionary identifier.    
+	 * @param resultModeId Indicates the return of INSTANCE, PROFILE, or CLASS.
+	 * @param propType Indicates query BROADCAST or PROPOGATE.
+	 * @param propLevels Number of propogation levels.
+	 * @param maxResults Maximum number of results to be returned.
+	 * @param mimeAccept List of acceptable MIME types.
+	 * @param parseQuery Indicates whether query should be parsed
+	 */
+	public XMLQuery(String keywordQuery, String id, String title, String desc, String ddId, String resultModeId,
+		String propType, String propLevels, int maxResults, 
+		List mimeAccept, boolean parseQuery) {
+		if (mimeAccept == null) {
+			mimeAccept = new ArrayList();
+			mimeAccept.add("*/*");
+		}
+		if (keywordQuery == null) keywordQuery = "UNKNOWN";
+		// init query header (object attributes)
+		if (id == null) id = new String("UNKNOWN");
+		if (title == null) title = new String("UNKNOWN");
+		if (desc == null) desc = new String("UNKNOWN");
+		if (ddId == null) ddId = new String("UNKNOWN");
+		queryHeader = new QueryHeader(id, title, desc, /*type*/"QUERY", /*status*/"ACTIVE", /*security*/"UNKNOWN",
+			/*revision*/"1999-12-12 JSH V1.0 Under Development", ddId);
+
+		// init query attributes
+		if (resultModeId == null) resultModeId = new String("ATTRIBUTE");
+		if (propType == null) {
+			propType = new String("BROADCAST");
+			propLevels = new String("N/A");
+		}
+		this.resultModeId = resultModeId;
+		this.propogationType = propType;
+		this.propogationLevels = propLevels;
+		this.maxResults = maxResults;
+		this.kwqString = keywordQuery;
+		this.mimeAccept = mimeAccept;
+        
+		// parse the keyword query string
+		if (! parseQuery) {
+			queryHeader.setStatusID("NOTPARSED");
+		} else if (!parseKeywordString(keywordQuery)) {
+			queryHeader.setStatusID("ERROR");
+		}
+	}
+
+	/** Get the list of acceptable MIME types.
+	 *
+	 * @return The list of acceptable MIME types; you may modify the list.
+	 */
+	public List getMimeAccept() {
+		return mimeAccept;
+	}
+
+    /**
+     * Instantiates an XMLQuery instance from an XML query structure in string format.
+     *
+     * @param xmlQueryString  The XML query structure in string format.
+     */
+	public XMLQuery (String xmlQueryString) throws SAXException {
+		if (xmlQueryString == null) xmlQueryString = BLANK;
+		try {
+			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+			factory.setCoalescing(false);
+			factory.setNamespaceAware(false);
+			factory.setValidating(false);
+			DocumentBuilder builder = factory.newDocumentBuilder();
+			builder.setEntityResolver(ENTITY_RESOLVER);
+			Document doc = builder.parse(new ByteArrayInputStream(xmlQueryString.getBytes()));
+			loadXMLQueryStruct(doc.getDocumentElement());
+		} catch (IOException ex) {
+			System.err.println("Unexpected no good bloody IOException while parsing doc: " + xmlQueryString);
+			throw new IllegalStateException("Unexpected no good bloody IOException: " + ex.getMessage() + ", during"
+				+ " parse of " + xmlQueryString);
+		} catch (ParserConfigurationException ex) {
+			throw new IllegalStateException("Unexpected ParserConfigurationException: " + ex.getMessage());
+		}
+   	}
+
+    /**
+     * Instantiates an XMLQuery instance from an XML query structure in DOM node format.
+     *
+     * @param node  The XML &lt;query&gt; node.
+     */
+	public XMLQuery (Node node) {
+		loadXMLQueryStruct(node);
+   	}
+
+    /**
+     * Gets the original DIS style keyword query string.
+     *
+     * @return The DIS style keyword query string.
+     */
+	public String getKwdQueryString () {
+		return kwqString;
+	}
+
+    /**
+     * Gets the max # of results
+     *
+     * @return the results
+     */
+	public int getMaxResults() {
+		return maxResults;
+	}
+
+    /**
+     * @return Gets the select elements
+     *
+     */
+	public List getSelectElementSet() {
+	   return(selectElementSet);
+	}
+
+    /**
+     * @return Gets the from element set from the query
+     *
+     */
+	public List getFromElementSet()
+	{
+	   return(fromElementSet);
+	}
+
+
+    /**
+     * @return Gets the resultModeID
+     *
+     */
+	public String getResultModeID()
+	{
+           return(resultModeId);
+        }
+	
+    /**
+     * @return Gets the where set
+     *
+     */
+	public List getWhereElementSet() {
+	   return(whereElementSet);
+	}
+	
+    /**
+     * Set query where element set.
+     * @param whereElementSet Thw where element set of XMLQuery.
+     */
+	public void setWhereElementSet(List whereElementSet) {
+		this.whereElementSet = whereElementSet;
+	}
+    /**
+     * @return Gets the result list
+     *
+     */
+	public QueryResult getResult() {
+	    return result;
+	}
+
+	public List getResults() {
+		return result.getList();
+	}
+	
+	public void setRetriever(Retriever retriever) {
+		result.setRetriever(retriever);
+	}
+
+    /**
+     * @return The query as an XML DOM structure.
+     */
+	public Document getXMLDoc () {
+		Document doc = createDocument();
+		doc.appendChild(doc.createElement("query"));
+   		createXMLDoc(doc);
+		return doc;
+    }
+
+    /** Get the list of stasitics of this query.
+    *
+    * @return A list of {@link Statistic} objects.
+    */
+    public List getStatistics() {
+      return statistics;
+    }
+
+    /**
+     * Gets query as an XML document in string format.
+     *
+     * @return The query as an XML document in string format.
+     */
+	public String getXMLDocString () {
+		StringWriter writer = new StringWriter();
+		try {
+			TransformerFactory factory = TransformerFactory.newInstance();
+			Transformer transformer = factory.newTransformer();
+			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+			transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml");
+			transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+			transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+			transformer.setOutputProperty(OutputKeys.STANDALONE, "no");
+			transformer.setOutputProperty(OutputKeys.VERSION, "1.0");
+			transformer.transform(new DOMSource(getXMLDoc()), new StreamResult(writer));
+		} catch (TransformerException ex) {
+			throw new IllegalStateException("Unexpected TransformerException: " + ex.getMessage());
+		} finally {
+			try {
+				writer.close();
+			} catch (IOException ignore) {}
+		}
+		return writer.toString();
+	}
+
+	/**
+	 * Get the propagation type.
+	 *
+	 * @return a {@link String} value.
+	 */
+	public String getPropagationType() {
+		return propogationType;
+	}
+
+	/**
+	 * Get the propagation levels.
+	 *
+	 * @return a {@link String} value.
+	 */
+	public String getPropagationLevels() {
+		return propogationLevels;
+	}
+
+    /**
+     * Parse keyword query string (simple top down recursion).
+     */
+    private boolean parseKeywordString (String kwdQueryString) {
+	    previous_token = "";
+	    lpart = "";
+	    rpart = "";
+
+            tokens = new java.io.StreamTokenizer(new StringReader(kwdQueryString));
+            tokens.resetSyntax();
+            tokens.ordinaryChar('/');
+            tokens.wordChars(':', ':');
+            tokens.wordChars('0', '9');
+            tokens.wordChars('.', '.');
+            tokens.wordChars('-', '-');
+            tokens.wordChars('[', '[');
+            tokens.wordChars(']', ']');
+            tokens.wordChars('a', 'z');
+            tokens.wordChars('A', 'Z');
+            tokens.wordChars('_', '_');
+            tokens.wordChars('/', '/');
+            tokens.eolIsSignificant(true);
+            tokens.whitespaceChars(0, ' ');
+            tokens.quoteChar('"');
+            tokens.quoteChar('\'');
+	    
+	    if (kqOrParse ()){
+	        return true;
+	    } else {
+	        return false;
+	    }
+	}
+
+    /**
+     * Parse OR logical operator.
+     */
+	private boolean kqOrParse ()
+	{
+	    boolean lflag, rflag;
+
+	    lflag = kqAndParse();
+	    while (isTokenEqual("OR") | isTokenEqual("or") | isTokenEqual("|")) {
+            rflag = kqAndParse();
+            lflag &= rflag;
+            appendLogOperator("LOGOP", "OR");
+        }
+        return lflag;
+	}
+
+    /**
+     * Parse AND logical operator.
+     */
+   	private boolean kqAndParse ()
+	{
+	    boolean lflag, rflag;
+
+	    lflag = kqNotParse();
+	    while (isTokenEqual("AND") | isTokenEqual("and") | isTokenEqual("&")) {
+            rflag = kqNotParse();
+            lflag &= rflag;
+            appendLogOperator("LOGOP", "AND");
+        }
+        return lflag;
+	}
+
+    /**
+     * Parse NOT logical operator.
+     */
+	private boolean kqNotParse ()
+	{
+	    boolean lflag, rflag;
+
+	    if (isTokenEqual("NOT") | isTokenEqual("not") | isTokenEqual("!")) {
+            lflag = kqFactorParse();
+            appendLogOperator("LOGOP", "NOT");
+        } else {
+            lflag = kqFactorParse ();
+        }
+        return lflag;
+	}
+
+    /**
+     * Parse logical operator operand and handle nesting (parens)
+     * also logic for differentiating SELECT, WHERE, and FROM
+     */
+	private boolean kqFactorParse ()
+	{
+	    String ropn, enm;
+	    if (isTokenEqual("(")) {
+	        return (kqOrParse () & isTokenEqual(")"));
+	    } else {
+            lpart = getNextToken ();
+            if (lpart.compareTo("") != 0) {
+                 ropn = getNextToken ();
+                 if (ropn.compareTo("EQ") == 0 || ropn.compareTo("LT") == 0 || ropn.compareTo("LE") == 0 || ropn.compareTo("GT") == 0 || ropn.compareTo("GE")== 0 || ropn.compareTo("NE") == 0 || ropn.compareToIgnoreCase("LIKE") == 0 || ropn.compareToIgnoreCase("NOTLIKE") == 0 || ropn.compareTo("IS") == 0 || ropn.compareTo("ISNOT") == 0) {
+                    rpart = getNextToken ();
+                    if (rpart.compareTo("") != 0) {
+                        lit = 0;
+                        enm = lpart;
+                        if (enm.compareTo("RETURN") == 0) {
+			    selectElementSet.add(new QueryElement("elemName", rpart));
+                        } else if (isFromToken(lpart)) {
+                            qfsc++;
+                            lit = 1;
+			    fromElementSet.add(new QueryElement("elemName", lpart));
+			    fromElementSet.add(new QueryElement("LITERAL", rpart));
+			    fromElementSet.add(new QueryElement("RELOP", ropn));
+                        } else {
+                            lit = 2;
+                            qwsc++;
+			    whereElementSet.add(new QueryElement("elemName", lpart));
+			    whereElementSet.add(new QueryElement("LITERAL", rpart));
+			    whereElementSet.add(new QueryElement("RELOP", ropn));
+                        }
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+	}
+
+    /**
+     * Create Logical Operator DOM node for WHERE clause.
+     */
+    private boolean appendLogOperator (String tt, String ts)
+	{
+	    if (lit == 1 & qfsc > 1) {
+		    fromElementSet.add(new QueryElement(tt, ts));
+
+    	} else if (lit == 2 & qwsc > 1) {
+		whereElementSet.add(new QueryElement(tt, ts));
+    	}
+	    return true;
+	}
+
+    /**
+     * Lexical analyzer - find a FROM token.
+     */
+    private static boolean isFromToken (String s1)
+	{
+		String tmpStr = s1;
+	    for (int i = 0; i < FROM_TOKENS.length; i++)
+	    {
+	        if (tmpStr.compareTo(FROM_TOKENS[i]) == 0) {
+	            return true;
+	        }
+	    }
+	    return false;
+	}
+
+    /**
+     * Lexical analyzer - return next token - allows lookahead.
+     */
+    private String getNextToken ()
+	{
+	    String ts;
+
+    	    ts = previous_token;
+            if (previous_token.compareTo("") == 0) {
+                    ts = getNextTokenFromStream();
+        	    return ts;
+            } else {
+        	    previous_token = "";
+        	    return ts;
+            }
+	}
+
+    /**
+     * Lexical analyzer - check if next token equal to argument.
+     */
+    private boolean isTokenEqual (String s1) {
+	    String ts;
+	    boolean rc = false;
+
+	    ts = previous_token;
+       	    if (previous_token.compareTo("") == 0) {
+       	        ts = getNextTokenFromStream ();
+		if (ts.compareTo("") == 0) {
+                    rc = false;
+                } else {
+           	    if (ts.compareTo(s1) == 0) {
+     	                previous_token = "";
+       	                rc = true;
+       	            } else {
+       	                previous_token = ts;
+       	                rc = false;
+                    }
+       	        }
+      	    } else {
+           	    if (previous_token.compareTo(s1) == 0) {
+       	            previous_token = "";
+       	            rc = true;
+       	        } else {
+       	            rc = false;
+       	        }
+     	    }
+	    return rc;
+	}  
+
+    /**
+     * Lexical analyzer - return next token from instance of StreamTokenizer.
+     */
+   private String getNextTokenFromStream () {
+            int c, c2;
+	    String rc = "";
+            try {
+                switch (c=tokens.nextToken()) {
+                    case StreamTokenizer.TT_EOF:
+                        rc = "";
+			break;
+                    case StreamTokenizer.TT_EOL:
+                        rc = "";
+			break;
+                    case StreamTokenizer.TT_NUMBER: // not currently set
+			rc = "";
+			break;
+                    case StreamTokenizer.TT_WORD:
+                        rc = tokens.sval;
+			break;
+                    case '(':
+                    case ')':
+			rc = String.valueOf((char)c);
+			break;
+                    case '"':
+                    case '\'':
+                        rc = tokens.sval;
+			break;
+                    case '=':
+                        rc = "EQ";
+			break;
+                    case '&':
+                        rc = "AND";
+			break;
+                    case '|':
+                        rc = "OR";
+			break;
+                    case '<':
+                        c2 = tokens.nextToken();
+                        if (c2 == '=') {
+				rc = "LE";
+                        } else {
+				tokens.pushBack();
+				rc = "LT";
+                        }
+			break;
+                    case '>':
+                        c2 = tokens.nextToken();
+                        if (c2 == '=') {
+				rc = "GE";
+                        } else {
+                                tokens.pushBack();
+				rc = "GT";
+                        }
+			break;
+                    case '!':
+                        c2 = tokens.nextToken();
+                        if (c2 == '=') {
+				rc = "NE";
+                        } else {
+                                tokens.pushBack();
+				rc = "NOT";
+                        }
+			break;
+                    default:
+                        rc = "";
+                    }
+                } catch (IOException e1) {
+			rc = "";
+		}
+	    return rc;
+   }
+
+    /**
+     * Replace character with string
+     */
+    private String replaceCharWithString (String s1, char c, String rs)
+	{
+        int p1, p2, s1l;
+    	String s2;
+    	
+    	p1 = 0; p2 = 0;
+    	s1l = s1.length();
+    	s2 = "";
+    	p2 = s1.indexOf(c, p1);
+    	while (p2 >= 0) {
+    	    s2 += s1.substring (p1, p2) + rs;
+            p1 = p2 + 1;
+            p2 = s1.indexOf(c, p1);
+        }
+        if (p1 < s1l) {
+            s2 += s1.substring(p1, s1l);
+        }
+        return s2;
+	}       
+       
+    /**
+     * Creates a XML DOM structure from a keyword query string.
+     * Set up the basic structure then calls the query parser.
+     */
+	private void createXMLDoc (Document doc) {
+	    int loc;
+	    String kwd;
+	    String type;
+	    String val;
+	    Element item;
+	    Element elem;
+	    
+	    Element query = doc.getDocumentElement();
+   	        
+        // create query header (object attributes)
+	    query.appendChild(queryHeader.toXML(doc));
+	        
+	    // create query attributes
+	    XML.add(query, "queryResultModeId", resultModeId);
+	    XML.add(query, "queryPropogationType", propogationType);
+	    XML.add(query, "queryPropogationLevels", propogationLevels);
+	    XML.add(query, "queryMimeAccept", mimeAccept);
+	    XML.add(query, "queryMaxResults", String.valueOf(maxResults));
+	    XML.add(query, "queryResults", String.valueOf(numResults));
+	    XML.add(query, "queryKWQString", kwqString);
+
+	    // create and load queryStatistics
+            elem = doc.createElement("queryStatistics");
+            query.appendChild(elem);
+            for (Iterator i = statistics.iterator(); i.hasNext();) {
+            Statistic s = (Statistic) i.next();
+            elem.appendChild(s.toXML(doc));
+            }
+
+	    // create and load querySelectSet
+	    elem = doc.createElement("querySelectSet");
+	    query.appendChild(elem);
+
+	    for (Iterator i = selectElementSet.iterator(); i.hasNext();) {
+		    QueryElement queryElement = (QueryElement) i.next();
+		    elem.appendChild(queryElement.toXML(doc));
+	    }
+
+	    // create and load queryFromSet
+	    elem = doc.createElement("queryFromSet");
+	    query.appendChild(elem);
+
+	    for (Iterator i = fromElementSet.iterator(); i.hasNext();) {
+		    QueryElement queryElement = (QueryElement) i.next();
+		    elem.appendChild(queryElement.toXML(doc));
+	    }
+
+	    // create and load queryWhereSet
+	    elem = doc.createElement("queryWhereSet");
+	    query.appendChild(elem);
+	    for (Iterator i = whereElementSet.iterator(); i.hasNext();) {
+		    QueryElement queryElement = (QueryElement) i.next();
+		    elem.appendChild(queryElement.toXML(doc));
+	    }
+
+	    query.appendChild(result.toXML(doc));
+    }
+
+    /**
+     * Creates a leaf (end node - TEXT) in the DOM structure.
+     */
+    private Element createLeaf (Element child, String value) {
+        child.appendChild(child.getOwnerDocument().createTextNode(value));
+        return child;
+    }
+
+    /**
+     * Load the internal query structure (dictionary) from an XML DOM structure
+     */
+    private void loadXMLQueryStruct (Node root) {
+        Node node;
+        String nodeName;
+        
+        initNodes();
+        for (node = root.getFirstChild();
+            node != null;
+            node = node.getNextSibling()) {
+                if (node instanceof Element) {
+                    nodeName = node.getNodeName();
+                    if (nodeName.compareTo("queryAttributes") == 0) {
+		        queryHeader = new QueryHeader(node);
+                    } else if (nodeName.compareTo("queryResultModeId") == 0) {
+			    resultModeId = XML.unwrappedText(node);
+		    } else if (nodeName.compareTo("queryPropogationType") == 0) {
+			    propogationType = XML.unwrappedText(node);
+		    } else if (nodeName.compareTo("queryPropogationLevels") == 0) {
+			    propogationLevels = XML.unwrappedText(node);
+		    } else if (nodeName.equals("queryMimeAccept")) {
+			    mimeAccept.add(XML.unwrappedText(node));
+		    } else if (nodeName.compareTo("queryMaxResults") == 0) {
+			    maxResults = Integer.parseInt(XML.unwrappedText(node));
+		    } else if (nodeName.compareTo("queryResults") == 0) {
+			    numResults = Integer.parseInt(XML.unwrappedText(node));
+		    } else if (nodeName.compareTo("queryKWQString") == 0) {
+			    kwqString = XML.unwrappedText(node);
+                    } else if (nodeName.compareTo("querySelectSet") == 0) {
+			scanQueryElements(selectElementSet, node);
+                    } else if (nodeName.compareTo("queryFromSet") == 0) {
+			scanQueryElements(fromElementSet, node);
+                    } else if (nodeName.compareTo("queryWhereSet") == 0) {
+			scanQueryElements(whereElementSet, node);
+                    } else if (nodeName.compareTo("queryResultSet") == 0) {
+			    result = new QueryResult(node);
+                    } else if (nodeName.equals("queryStatistics")) {
+                        NodeList children = node.getChildNodes();
+                        for (int i = 0; i < children.getLength(); ++i) {
+				Node statisticNode = children.item(i);
+				if (statisticNode.getNodeType() == Node.ELEMENT_NODE) {
+					Statistic s = new Statistic(statisticNode);
+					statistics.add(s);
+				}
+			}
+                    }
+                }
+            }
+            return;
+    }
+
+    /**
+     * Replace the dictionary keyword value with the DOM text node value.
+     */
+    private void replaceKwdVal (Map map, Node node, String nodeName) {
+        Node childNode;
+        
+        childNode = node.getFirstChild();
+        if (childNode instanceof Text) {
+                map.put(nodeName, childNode.getNodeValue());
+        } else {
+                map.put(nodeName, "UNKNOWN");            
+        }
+        return;
+    }
+
+    /**
+     * Scan the DOM structure for the SELECT, FROM, or WHERE set.
+     *
+     * @param list To what list to add the query elements.
+     * @param node Where to find the query elements. 
+     */
+    private static void scanQueryElements(List list, Node node) {
+	    NodeList children = node.getChildNodes();
+	    for (int i = 0; i < children.getLength(); ++i) {
+		    Node n = children.item(i);
+		    if (n.getNodeType() == Node.ELEMENT_NODE)
+			    list.add(new QueryElement(n));
+	    }
+    }
+
+    /**
+     * Initialize the Query and Resource attributes in the dictionary.
+     */
+    private void initNodes () {
+	queryHeader = new QueryHeader();
+	resultModeId = "ATTRIBUTE";
+	propogationType = "BROADCAST";
+	propogationLevels = "N/A";
+	maxResults = DEFAULT_MAX_RESULTS;
+	kwqString = "UNKNOWN";
+	mimeAccept = new ArrayList();
+    }    
+
+	public int hashCode() {
+		return resultModeId.hashCode() ^ propogationType.hashCode() ^ propogationLevels.hashCode()
+			^ (maxResults << 8) ^ kwqString.hashCode() ^ numResults ^ queryHeader.hashCode()
+			^ selectElementSet.hashCode() ^ fromElementSet.hashCode() ^ whereElementSet.hashCode()
+			^ result.hashCode();
+	}
+
+	public boolean equals(Object rhs) {
+		if (rhs == this) return true;
+		if (rhs == null || !(rhs instanceof XMLQuery)) return false;
+		XMLQuery obj = (XMLQuery) rhs;
+		return resultModeId.equals(obj.resultModeId) && propogationType.equals(obj.propogationType)
+			&& propogationLevels.equals(obj.propogationLevels) && maxResults == obj.maxResults
+			&& kwqString.equals(obj.kwqString) && numResults == obj.numResults
+			&& queryHeader.equals(obj.queryHeader) && selectElementSet.equals(obj.selectElementSet)
+			&& fromElementSet.equals(obj.fromElementSet) && whereElementSet.equals(obj.whereElementSet)
+			&& result.equals(obj.result);
+	}
+
+	public Object clone() {
+		Object rc = null;
+		try {
+			rc = super.clone();
+		} catch (CloneNotSupportedException cantHappen) {}
+		return rc;
+	}
+
+	public String toString() {
+		return getClass().getName() + "[kwqString=" + kwqString + "]";
+	}
+
+	/** Create an XML DOM document using the query DTD.
+	 *
+	 * @return An XML DOM document, with a query root element, using the query DTD.
+	 */
+	public static Document createDocument() {
+		try {
+			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+			factory.setCoalescing(true);
+			factory.setNamespaceAware(false);
+			factory.setValidating(false);
+			DocumentBuilder builder = factory.newDocumentBuilder();
+			return builder.newDocument();
+		} catch (ParserConfigurationException ex) {
+			throw new IllegalStateException("Unexpected ParserConfigurationException: " + ex.getMessage());
+		}
+	}
+
+	public static void main(String[] argv) throws Exception {
+		if (argv.length < 2 || (!argv[0].equals("-expr") && !argv[0].equals("-file"))
+			|| (argv[0].equals("-file") && argv.length > 2)) {
+			System.err.println("Usage: -expr <expr>...");
+			System.err.println("   or: -file <file>");
+			System.exit(1);
+		}
+
+		XMLQuery q;
+		if (argv[0].equals("-expr")) {
+			StringBuffer expr = new StringBuffer();
+			for (int i = 1; i < argv.length; ++i)
+				expr.append(argv[i]).append(' ');
+			q = new XMLQuery(expr.toString().trim(), "expr1", "Command-line Expression Query",
+				"The expression for this query came from the command-line", /*ddId*/ null,
+				/*resultModeId*/ null, /*propType*/ null, /*propLevels*/ null, XMLQuery.DEFAULT_MAX_RESULTS);
+		} else if (argv[0].equals("-file")) {
+			BufferedReader reader = new BufferedReader(new FileReader(argv[1]));
+			StringBuffer str = new StringBuffer();
+			String line;
+			while ((line = reader.readLine()) != null)
+				str.append(line).append('\n');
+			reader.close();
+			q = new XMLQuery(str.toString());
+		} else throw new IllegalStateException("Can't get here; only -expr or -file allowed, but got \"" + argv[0] + "\"");
+				
+		System.out.println("kwdQueryString: " + q.getKwdQueryString());
+		System.out.println("fromElementSet: " + q.getFromElementSet());
+		System.out.println("results: " + q.getResult());
+		System.out.println("whereElementSet: " + q.getWhereElementSet());
+		System.out.println("selectElementSet: " + q.getSelectElementSet());
+
+		System.out.println("======doc string=======");
+		System.out.println(q.getXMLDocString());
+	}
+
+	public QueryHeader getQueryHeader() {
+		return queryHeader;
+	}
+
+	/** Maximum number results to get (default). */
+	public static final int DEFAULT_MAX_RESULTS = 100;
+
+	/** The Formal Public Identifier of the query DTD. */
+	public static final String QUERY_FPI = "-//JPL//DTD OODT Query 1.0//EN";
+	
+	/** The System Identifier of the query DTD. */
+	public static final String QUERY_URL = "http://oodt.jpl.nasa.gov/edm-query/query.dtd"; // FIXME: Move to apache.org
+
+	/** A blank query document, as a string. */
+	private static String BLANK = "<?xml version='1.0' encoding='UTF-8'?>\n<!DOCTYPE query PUBLIC '" + QUERY_FPI
+		+ "' '" + QUERY_URL + "'>\n<query/>";
+
+	/** Resolver for the query DTD. */
+	private static final EntityResolver ENTITY_RESOLVER = new EnterpriseEntityResolver();
+
+	/** Serial version unique ID. */
+	static final long serialVersionUID = -7638068782048963710L;
+}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/activity/QueryConstructed.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/activity/QueryConstructed.java
new file mode 100755
index 0000000..4598966
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/activity/QueryConstructed.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery.activity;
+
+import org.apache.oodt.commons.activity.Incident;
+
+public class QueryConstructed extends Incident {}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/activity/ResultsReceived.java b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/activity/ResultsReceived.java
new file mode 100755
index 0000000..0c5616d
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/activity/ResultsReceived.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery.activity;
+
+import org.apache.oodt.commons.activity.Incident;
+
+public class ResultsReceived extends Incident {}
diff --git a/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/package.html b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/package.html
new file mode 100755
index 0000000..aabb59c
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/main/java/org/apache/oodt/xmlquery/package.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+  <head>
+    <title>JPL OODT XML-based Query/Results
+    </title>
+  </head>
+  <body>
+    <p>Classes to support XML-based representation of queries and
+      their results.
+    </p>
+  </body>
+</html>
diff --git a/0.8.1-rc1/xmlquery/src/site/resources/images/edm-query.jpg b/0.8.1-rc1/xmlquery/src/site/resources/images/edm-query.jpg
new file mode 100755
index 0000000..f6b5829
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/site/resources/images/edm-query.jpg
Binary files differ
diff --git a/0.8.1-rc1/xmlquery/src/site/resources/images/large-stack.png b/0.8.1-rc1/xmlquery/src/site/resources/images/large-stack.png
new file mode 100755
index 0000000..4bdcf53
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/site/resources/images/large-stack.png
Binary files differ
diff --git a/0.8.1-rc1/xmlquery/src/site/resources/images/large-stack.psd b/0.8.1-rc1/xmlquery/src/site/resources/images/large-stack.psd
new file mode 100755
index 0000000..caa6be9
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/site/resources/images/large-stack.psd
Binary files differ
diff --git a/0.8.1-rc1/xmlquery/src/site/resources/images/results.png b/0.8.1-rc1/xmlquery/src/site/resources/images/results.png
new file mode 100755
index 0000000..eef63e2
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/site/resources/images/results.png
Binary files differ
diff --git a/0.8.1-rc1/xmlquery/src/site/resources/images/results.psd b/0.8.1-rc1/xmlquery/src/site/resources/images/results.psd
new file mode 100755
index 0000000..7e8476c
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/site/resources/images/results.psd
Binary files differ
diff --git a/0.8.1-rc1/xmlquery/src/site/resources/images/small-stack.png b/0.8.1-rc1/xmlquery/src/site/resources/images/small-stack.png
new file mode 100755
index 0000000..d3604ef
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/site/resources/images/small-stack.png
Binary files differ
diff --git a/0.8.1-rc1/xmlquery/src/site/resources/images/small-stack.psd b/0.8.1-rc1/xmlquery/src/site/resources/images/small-stack.psd
new file mode 100755
index 0000000..d13ac6f
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/site/resources/images/small-stack.psd
Binary files differ
diff --git a/0.8.1-rc1/xmlquery/src/site/resources/images/xmlquery.png b/0.8.1-rc1/xmlquery/src/site/resources/images/xmlquery.png
new file mode 100755
index 0000000..189feb6
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/site/resources/images/xmlquery.png
Binary files differ
diff --git a/0.8.1-rc1/xmlquery/src/site/resources/images/xmlquery.psd b/0.8.1-rc1/xmlquery/src/site/resources/images/xmlquery.psd
new file mode 100755
index 0000000..cce0220
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/site/resources/images/xmlquery.psd
Binary files differ
diff --git a/0.8.1-rc1/xmlquery/src/site/site.xml b/0.8.1-rc1/xmlquery/src/site/site.xml
new file mode 100644
index 0000000..2184b8d
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/site/site.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+
+<project name="Query Expression">
+
+  <body>
+    <links>
+      <item name="OODT" href="../oodt-site/"/>
+    </links>
+
+    <menu ref="reports" inherit="bottom"/>
+    <menu name="User's Guide">
+      <item name="Tutorial" href="tutorial/"/>
+      <item name="DIS-Style Query" href="disquery/"/>
+      <item name="Query Servlet" href="servlet/"/>
+    </menu>
+  </body>
+</project>
diff --git a/0.8.1-rc1/xmlquery/src/site/xdoc/disquery/index.xml b/0.8.1-rc1/xmlquery/src/site/xdoc/disquery/index.xml
new file mode 100755
index 0000000..a9ddf49
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/site/xdoc/disquery/index.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+
+  <properties>
+    <title>DIS-Style Query</title>
+    <author email="Sean.Hardman@jpl.nasa.gov">Sean Hardman</author>
+  </properties>
+
+  <body>
+    <section name="DIS-Style Query">
+      <p>A DIS-Style Query is a query using triples linked in a logical expression. Each triple is in the format of (element, relation, literal). The element portion of the triple may be any named data element recognized as a queryable attribute by the target of the query. The relation portion of the triple may contain any of the relational operators from the table below. The literal portion of the triple is the element value to be compared. Multiple sets of triples may be joined using any of the logical operators from the table below. Note that elements or literals containing spaces must be quoted. Also note that case sensitivity and support for the various operators is subject to the capabilities offered by the target of the query.
+      </p>
+
+      <p>The following table contains the supported relational operators:</p>
+
+      <table>
+      <tr>
+        <th colspan="2">Relational Operators</th>
+      </tr>
+      <tr>
+        <td>Equal</td> <td>=, EQ</td>
+      </tr>
+      <tr>
+        <td>Not Equal</td> <td>!=, NE</td>
+      </tr>
+      <tr>
+        <td>Less Than</td> <td>&lt;, LT</td>
+      </tr>
+      <tr>
+        <td>Less Than or Equal</td> <td>&lt;=, LE</td>
+      </tr>
+      <tr>
+        <td>Greater Than</td> <td>&gt;, GT</td>
+      </tr>
+      <tr>
+        <td>Greater Than or Equal</td> <td>&gt;=, GE</td>
+      </tr>
+      <tr>
+        <td>Contains</td> <td>LIKE</td>
+      </tr>
+      <tr>
+        <td>Does Not Contain</td> <td>NOTLIKE</td>
+      </tr>
+      <tr>
+        <td>Is Null</td> <td>IS</td>
+      </tr>
+      <tr>
+        <td>Is Not Null</td> <td>ISNOT</td>
+      </tr>
+      </table>
+
+      <p>The following table contains the supported logical operators:</p>
+
+      <table>
+      <tr>
+        <th colspan="2">Logical Operators</th>
+      </tr>
+      <tr>
+        <td>And</td> <td>AND, &amp;</td>
+      </tr>
+      <tr>
+        <td>Or</td> <td>OR, |</td>
+      </tr>
+      <tr>
+        <td>Not</td> <td>NOT, !</td>
+      </tr>
+      </table>
+
+      <p>The following are examples of DIS-Style queries:</p>
+
+      <ul>
+      <li>Title LIKE EDM AND Creator = "Sean Hardman"
+      <p>This query will return all objects where the <i>Title</i> element contains the text "EDM" and the <i>Creator</i> element is equal to "Sean Hardman".</p>
+      </li>
+
+      <li>Title LIKE EDM AND Creator = "Sean Hardman" OR Title LIKE OODT AND Creator = "Sean Kelly"
+      <p>This query will return all objects where either the first set of criteria matches or the second set of criteria matches.</p>
+      </li>
+
+      <li>Temperature &gt; 32 AND Temperature &lt; 212
+      <p>This query will return all objects where the <i>Temperature</i> element value is between the specified range.</p>
+      </li>
+
+      <li>Subject IS NULL
+      <p>This query will return all objects where the <i>Subject</i> element has no associated value. When using the IS and ISNOT relational operators, the literal must be "NULL" or "null".</p>
+      </li>
+      </ul>
+    </section>
+  </body>
+</document>
diff --git a/0.8.1-rc1/xmlquery/src/site/xdoc/servlet/index.xml b/0.8.1-rc1/xmlquery/src/site/xdoc/servlet/index.xml
new file mode 100644
index 0000000..d266e1a
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/site/xdoc/servlet/index.xml
@@ -0,0 +1,640 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+
+  <properties>
+    <title>Query Servlet</title>
+    <author email="Sean.Kelly@jpl.nasa.gov">Sean Kelly</author>
+  </properties>
+
+  <body>
+    <section name="Query Servlet">
+
+      <p>The query servlet enables you to inject generic queries into
+	the OODT framework using HTTP.  This enables you to query for
+	profiles and products without requiring a Java, RMI, or CORBA
+   enabled application.
+      </p>
+    </section>
+
+    <section name="Requirements">
+
+      <p>The query servlet accepts various parameters for a query and
+	turns them into an <code>XMLQuery</code> object.  It uses this
+	object internally to send the query around the network and to
+	gather results.  It then returns a <code>text/xml</code>
+	representation of the <code>XMLQuery</code> object (for product
+	queries) or a <code>text/xml</code> representation of all matching
+	profiles (for profile queries).
+      </p>
+
+      <p><strong>That means you must be able to process XML</strong> in
+	order to use the query servlet.  Luckily, this isn't an onerous
+	restriction, as many languages are more than capable of doing so.
+      </p>
+
+      <p>For more details, view the Javadocs for the
+	<code>jpl.oodt.servlets.QueryServlet</code> class.</p>
+    </section>
+
+    <section name="Using the Query Servlet">
+
+      <p>In order to use the query servlet, you need to specify three parameters:
+      </p>
+
+      <ol>
+	<li>You need to know the <strong>type of the query</strong> you
+	  want to make.  You will use a string value of
+	  <code>profile</code> to make a profile query, and
+	  <code>product</code> to make a product query.  You specify
+	  your choice in a parameter named <code>type</code>.
+	</li>
+
+	<li>You need to know the <strong>name of the object</strong>
+	  that should receive the query.  This takes the form of
+	  <code>urn:eda:<var>protocol</var>:<var>name</var></code> such
+	  as <code>urn:eda:corba:PDS.Profile</code> or
+	  <code>urn:eda:rmi:NCI-ImageServer</code>.  You specify the
+	  object name in a parameter named <code>object</code>.
+	</li>
+
+	<li>You need <strong>the actual query</strong> you want to
+	  send.  You can express this in two ways:
+
+	  <ol>
+	    <li>As an <strong>keyword query expression</strong> like
+	      <code>TARGET_NAME = MARS</code>.  You specify the
+	      query expression in a parameter named
+	      <code>keywordQuery</code>.
+	    </li>
+
+	    <li>As a <strong>text serialized <code>XMLQuery</code>
+		object</strong>.  You specify the XML document in a
+	      parameter named <code>query</code>.
+	    </li>
+	  </ol>
+
+	  <p>Using the latter enables you to fully specify all sorts of
+	    parameters in the query.  The former, though, is far
+	    easier to use.
+	  </p>
+
+	</li>
+      </ol>
+
+      <p>You then URL encode parameters' values and make either an HTTP
+	<code>GET</code> or <code>POST</code> request to the query
+	servlet.  If all goes according to plan, the servlet will execute
+	the query and return to you a <code>text/xml</code> document
+	describing the results.  You can then manipulate that document as
+	you see fit.  For profile queries, the return value is a
+	<code>&lt;profiles&gt;</code> document with zero or more matching
+	profiles.  For product queries, it's a <code>&lt;query&gt;</code>
+
+	document with the original <code>XMLQuery</code> object with any
+	product results in the <code>&lt;queryResults&gt;</code> section.
+      </p>
+
+    </section>
+
+    <section name="Query Examples">
+
+      <p>Let's look at a couple of concrete examples.  In the first
+	example, we'll run a profile query against some planetary data
+	servers; the second example will run a product query for cancer
+	biomarkers.
+      </p>
+
+      <subsection name="Planetary Profile Query">
+
+	<p>Suppose you wanted to know what PDS product servers supported
+	  the query element <code>ONLINE_FILE_SPECIFICATION_NAME</code>.
+	  You could pass that element to the PDS system profile server named
+	  <code>urn:eda:rmi:PDS.System.Profile</code> using the query
+	  servlet at
+	  <code>http://starbrite.jpl.nasa.gov/servlet/jpl.oodt.servlets.QueryServlet</code>.
+	  You can formulate the HTTP <code>GET</code> request in a URL as
+	  follows:
+	</p>
+
+	<p><code><a href="http://starbrite.jpl.nasa.gov/servlet/jpl.oodt.servlets.QueryServlet?object=urn:eda:rmi:PDS.System.Profile&amp;type=profile&amp;keywordQuery=ONLINE_FILE_SPECIFICATION_NAME+%3D+ANY">http://starbrite.jpl.nasa.gov/servlet/jpl.oodt.servlets.QueryServlet?<br/>  object=urn:eda:rmi:PDS.System.Profile&amp;<br/>  type=profile&amp;<br/>  keywordQuery=ONLINE_FILE_SPECIFICATION_NAME+%3D+ANY</a></code></p>
+
+	<p>Note that we've broken this URL into multiple lines for
+	  readability.  There should be no linebreaks in a real URL.  Note
+	  the following about this URL:
+	</p>
+
+	<ul>
+	  <li>The question-mark separates the request URI from its
+	    parameters.
+	  </li>
+
+	  <li>The parameters may come in any order.</li>
+
+	  <li>The <code>object</code> parameter names the target of the
+	    query; in this case, the RMI product server named
+	    <code>urn:eda:rmi:PDS.System.Profile</code>.
+	  </li>
+
+	  <li>The <code>type</code> parameter specifies that we're doing a
+	    <em>profile search</em>.</li>
+
+	  <li>The <code>keywordQuery</code> parameter identifies the query
+	    expression.  Note the URL encoding: the spaces become
+	    <code>+</code> symbols, and the equals sign become
+	    <code>%3D</code>.
+	  </li>
+	</ul>
+
+	<p>The response from such a query is an XML document; this XML
+	  document describes matching profiles and may take a form such as
+	  the following:</p>
+
+<source>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;!DOCTYPE profiles PUBLIC "-//JPL//DTD OODT Profile 1.1//EN"
+"http://starshine.jpl.nasa.gov:80/dtd/prof.dtd"&gt;
+
+&lt;profiles&gt;
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.7&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.ASU.Product&lt;/Identifier&gt;
+      &lt;Title&gt;
+      PDS Arizona State University Data Node Product Server
+      &lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.ASU&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.ASU.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.ASU.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.6&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.RS.Product&lt;/Identifier&gt;
+      &lt;Title&gt;PDS Radio Science Product Server&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.RS&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.RS.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.RS.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.4&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.Atmos.Product&lt;/Identifier&gt;
+      &lt;Title&gt;PDS Atmospheres Product Server&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.Atmos&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.Atmos.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.Atmos.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.3&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.NAIF.Product&lt;/Identifier&gt;
+      &lt;Title&gt;PDS NAIF Product Server&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.NAIF&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.NAIF.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.NAIF.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.2&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.Geo.Product&lt;/Identifier&gt;
+      &lt;Title&gt;PDS Geosciences Product Server&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.GEO&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.Geo.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.Geo.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.1&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.CN.Product&lt;/Identifier&gt;
+      &lt;Title&gt;PDS Central Node Archive Product Server&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.CN&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.CN.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.CN.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.10&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.CN.Profile&lt;/Identifier&gt;
+      &lt;Title&gt;PDS.CN.Profile&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.CN&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.CN.Profile
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.CN.Profile&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.9&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.PPI.Product&lt;/Identifier&gt;
+      &lt;Title&gt;
+      PDS Planetary Plasma Interactions Product Server
+      &lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.PPI&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.PPI.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.PPI.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.8&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.Img.Product&lt;/Identifier&gt;
+      &lt;Title&gt;PDS Imaging Product Server&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.Img&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.Img.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.Img.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+&lt;/profiles&gt;
+</source>
+
+      </subsection>
+
+      <subsection name="Biomarker Product Query">
+
+	<p>Suppose you had a query servlet available at
+	  <code>http://pancreas/qs</code>, and you want to query the CORBA
+	  product server <code>urn:eda:corba:TissueBank</code> with the
+	  query expression <code>SeverityLevel = 3</code>.  You can
+	  formulate the entire <code>GET</code> request as the following
+	  URL:
+	</p>
+
+	<source>
+  http://pancreas/qs?
+  type=product&amp;
+  object=urn:eda:corba:TissueBank&amp;
+  keywordQuery=SeverityLevel+%3D+3
+   </source>
+
+	<p>(Again, we've broken the URL for readability.)  The result to
+	  this query could be an XML document like the following:
+	</p>
+
+<source>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;!DOCTYPE query PUBLIC "-//JPL//DTD OODT Query 1.0//EN"
+                       "http://pancreas/dtd/query.dtd"&gt;
+
+&lt;query&gt;
+  &lt;queryAttributes&gt;
+    &lt;queryId&gt;UNKNOWN&lt;/queryId&gt;
+    &lt;queryTitle&gt;UNKNOWN&lt;/queryTitle&gt;
+    &lt;queryDesc&gt;UNKNOWN&lt;/queryDesc&gt;
+    &lt;queryType&gt;QUERY&lt;/queryType&gt;
+    &lt;queryStatusId&gt;ACTIVE&lt;/queryStatusId&gt;
+    &lt;querySecurityType&gt;UNKNOWN&lt;/querySecurityType&gt;
+    &lt;queryRevisionNote&gt;
+    1999-12-12 JSH V1.0 Under Development
+    &lt;/queryRevisionNote&gt;
+    &lt;queryDataDictId&gt;UNKNOWN&lt;/queryDataDictId&gt;
+  &lt;/queryAttributes&gt;
+  &lt;queryResultModeId&gt;ATTRIBUTE&lt;/queryResultModeId&gt;
+  &lt;queryPropogationType&gt;BROADCAST&lt;/queryPropogationType&gt;
+  &lt;queryPropogationLevels&gt;N/A&lt;/queryPropogationLevels&gt;
+  &lt;queryMimeAccept&gt;*/*&lt;/queryMimeAccept&gt;
+  &lt;queryMaxResults&gt;100&lt;/queryMaxResults&gt;
+  &lt;queryResults&gt;0&lt;/queryResults&gt;
+  &lt;queryKWQString&gt;SeverityLevel = 3&lt;/queryKWQString&gt;
+  &lt;querySelectSet&gt;
+    &lt;queryElement&gt;
+      &lt;tokenRole&gt;LITERAL&lt;/tokenRole&gt;
+      &lt;tokenValue&gt;3&lt;/tokenValue&gt;
+    &lt;/queryElement&gt;
+    &lt;queryElement&gt;
+      &lt;tokenRole&gt;elemName&lt;/tokenRole&gt;
+      &lt;tokenValue&gt;SeverityLevel&lt;/tokenValue&gt;
+    &lt;/queryElement&gt;
+    &lt;queryElement&gt;
+      &lt;tokenRole&gt;RELOP&lt;/tokenRole&gt;
+      &lt;tokenValue&gt;EQ&lt;/tokenValue&gt;
+    &lt;/queryElement&gt;
+  &lt;/querySelectSet&gt;
+  &lt;queryFromSet/&gt;
+  &lt;queryWhereSet/&gt;
+  &lt;queryResultSet&gt;
+    &lt;resultElement&gt;
+      &lt;resultId&gt;1&lt;/resultId&gt;
+      &lt;resultMimeType&gt;text/plain&lt;/resultMimeType&gt;
+      &lt;profId&gt;TissueBank&lt;/profId&gt;
+      &lt;identifier/&gt;
+      &lt;resultHeader&gt;
+        &lt;headerElement&gt;
+          &lt;elemName&gt;UNKNOWN&lt;/elemName&gt;
+          &lt;elemType&gt;TEXT&lt;/elemType&gt;
+        &lt;/headerElement&gt;
+      &lt;/resultHeader&gt;
+      &lt;Resultvalue xml:space="preserve"&gt;
+      PatientIDs=[1,2,4,7,11,19,22]&lt;/resultValue&gt;
+    &lt;/resultElement&gt;
+  &lt;/queryResultSet&gt;
+&lt;/query&gt;
+</source>
+
+	<p>Instead of using the <code>keywordQuery</code> parameter, you
+	  can create your own <code>XMLQuery</code> document and pass it in
+	  as the <code>query</code> parameter instead.  The query document
+	  would look like this:
+	</p>
+
+    <source>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;!DOCTYPE query PUBLIC "-//JPL//DTD OODT Query 1.0//EN"
+                       "http://pancreas:80/dtd/query.dtd"&gt;
+
+&lt;query&gt;
+  &lt;queryAttributes&gt;
+    &lt;queryId&gt;expr1&lt;/queryId&gt;
+    &lt;queryTitle&gt;Command-line Expression Query&lt;/queryTitle&gt;
+    &lt;queryDesc&gt;
+    The expression for this query came from the command-line.
+    &lt;/queryDesc&gt;
+    &lt;queryType&gt;QUERY&lt;/queryType&gt;
+    &lt;queryStatusId&gt;ACTIVE&lt;/queryStatusId&gt;
+    &lt;querySecurityType&gt;UNKNOWN&lt;/querySecurityType&gt;
+    &lt;queryRevisionNote&gt;
+    1999-12-12 JSH V1.0 Under Development
+    &lt;/queryRevisionNote&gt;
+    &lt;queryDataDictId&gt;UNKNOWN&lt;/queryDataDictId&gt;
+  &lt;/queryAttributes&gt;
+  &lt;queryResultModeId&gt;ATTRIBUTE&lt;/queryResultModeId&gt;
+  &lt;queryPropogationType&gt;BROADCAST&lt;/queryPropogationType&gt;
+  &lt;queryPropogationLevels&gt;N/A&lt;/queryPropogationLevels&gt;
+  &lt;queryMimeAccept&gt;*/*&lt;/queryMimeAccept&gt;
+  &lt;queryMaxResults&gt;100&lt;/queryMaxResults&gt;
+  &lt;queryResults&gt;0&lt;/queryResults&gt;
+  &lt;queryKWQString&gt;SeverityLevel = 3&lt;/queryKWQString&gt;
+  &lt;querySelectSet/&gt;
+  &lt;queryFromSet/&gt;
+  &lt;queryWhereSet&gt;
+    &lt;queryElement&gt;
+      &lt;tokenRole&gt;elemName&lt;/tokenRole&gt;
+      &lt;tokenValue&gt;SeverityLevel&lt;/tokenValue&gt;
+    &lt;/queryElement&gt;
+    &lt;queryElement&gt;
+      &lt;tokenRole&gt;LITERAL&lt;/tokenRole&gt;
+      &lt;tokenValue&gt;3&lt;/tokenValue&gt;
+    &lt;/queryElement&gt;
+    &lt;queryElement&gt;
+      &lt;tokenRole&gt;RELOP&lt;/tokenRole&gt;
+      &lt;tokenValue&gt;EQ&lt;/tokenValue&gt;
+    &lt;/queryElement&gt;
+  &lt;/queryWhereSet&gt;
+  &lt;queryResultSet/&gt;
+&lt;/query&gt;
+</source>
+
+	<p>Passing such a long string as a URL parameter in a
+	  <code>GET</code> request can be tricky, though.  For such long
+	  parameters, it's better to use a <code>POST</code> request
+	  instead.  See your HTTP API documentation for details on
+	  formulating <code>POST</code> requests.
+	</p>
+      </subsection>
+    </section>
+  </body>
+</document>
diff --git a/0.8.1-rc1/xmlquery/src/site/xdoc/tutorial/index.xml b/0.8.1-rc1/xmlquery/src/site/xdoc/tutorial/index.xml
new file mode 100755
index 0000000..3cb2a71
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/site/xdoc/tutorial/index.xml
@@ -0,0 +1,659 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+  <properties>
+    <title>Understanding the XMLQuery</title>
+    <author email="kelly@apache.org">Sean Kelly</author>
+  </properties>
+
+  <body>
+    <section name="Understanding the XMLQuery">
+      <p>Apache OODT's <a href="../../profile/">profile servers</a>, <a
+	  href="../../product/">product servers</a>, and other
+	components all use the same format for a query.  It's
+	encapsulated by the class
+	<code>org.apache.oodt.xmlquery.XMLQuery</code>.  In this tutorial,
+	we'll look at this class and see how it represents queries.
+	You'll need this knowledge both to make queries to OODT
+	servers, as well as to understand queries coming into OODT
+	servers.
+      </p>
+    </section>
+
+    <section name="Basic Query Concepts">
+      <p>Capturing various aspects of a query is difficult to do in
+	general, and OODT's implementation is not stellar or complete.
+	But, it has proved succesful in a variety of applications, so
+	let's see what concepts it encapsulates.
+      </p>
+
+      <subsection name="XML?">
+	<p>First, forget the fact that the XMLQuery has "XML" in its
+	  name.  It doesn't mean you can query only XML resources.
+	  It's called XMLQuery probably because the person who came up
+	  with it thought XML was pretty cool, or that you can
+	  represent an OODT query in XML format.
+	</p>
+
+	<p>While you <em>can</em> represent an XMLQuery in XML, you
+	  usually only use the Java representation, that is, you
+	  create and manipulate Java objects of the class
+	  <code>org.apache.oodt.xmlquery.XMLQuery</code>.
+	</p>
+      </subsection>
+
+      <subsection name="Generic Queries">
+	<p>In theory, the XMLQuery can represent <em>any</em> query
+	  for information.  It captures generic aspects of a query,
+	  such as the domain of the question being posed, the range in
+	  which the desired response should be formulated, and
+	  constraints on what selects the response.  In XMLQuery
+	  parlance, we call these the "from element set" (domain), the
+	  "select element set" (range), and the "where element set"
+	  (constraints).
+	</p>
+
+	<p>In practice, none of the current OODT implementations use
+	  any but the "where element set."  And indeed, for most
+	  problems presented to OODT, that is sufficient.  However,
+	  the framework is there to support more aspects of a query,
+	  and you're welcome to use them in your own deployments.
+	</p>
+      </subsection>
+
+      <subsection name="Query Metadata">
+	<p>The XMLQuery concept captures metadata about a query as
+	  well, such as the title for the query, whether the query
+	  itself is secret or classified, how many results to return
+	  at most, how to propagate the query through a network, and
+	  so forth.  In practice, though, none of these additional
+	  attributes are used in current deployments of OODT.
+	  Moreover, none of the current OODT components obey such
+	  settings such as maximum number of results or propagation
+	  types.
+	</p>
+
+	<p>As a result, you should ignore these aspects of the
+	  XMLQuery and merely use its default values.  We'll see these
+	  shortly.
+	</p>
+      </subsection>
+
+      <subsection name="XMLQuery Structure">
+	<p>The following diagram shows the XMLQuery and related classes (note the diagram is outdated; "jpl.eda.xmlquery"
+	    should read "org.apache.oodt.xmlquery"):</p>
+
+	<p><img src="../images/xmlquery.png" alt="Class diagram of XMLQuery"/></p>
+
+	<p>A single <code>XMLQuery</code> object has three separate
+	  lists of <code>QueryElement</code> objects, representing the
+	  "from", "select", and "where" element sets.  In practice,
+	  the "from" and "where" sets are empty, though, as mentioned.
+	  There's also a single <code>QueryHeader</code> object
+	  capturing query metadata.  Within the <code>XMLQuery</code>
+	  itself is additional query metadata.  Finally, there's
+	  exactly one <code>QueryResult</code> object which captures
+	  the results of the query so far.
+	</p>
+      </subsection>
+    </section>
+
+    <section name="Boolean Expressions">
+      <p>The XMLQuery class uses lists of <code>QueryElement</code>
+	objects to represent its "from", "select", and "where" element
+	sets.  The lists form a postfix boolean stack, with the
+	zeroth element of the list being the top of the stack.
+	Although you can populate these stacks by manipulating their
+	corresponding <code>java.util.List</code>s, the XMLQuery class
+	provides a boolean expression language that lets you directly
+	populate them.
+      </p>
+
+      <p>The XMLQuery class also respects that some queries just
+	cannot be formulated as a boolean expression.  In these cases,
+	you can pass in a string that the XMLQuery will otherwise
+	carry unparsed.  Note that your profile and product servers
+	will then have the responsibility of handling that string in
+	some appropriate way.
+      </p>
+
+      <subsection name="Query Language">
+	<p>The query language that XMLQuery uses to generate postfix
+	  boolean stacks is a series of infix, not postfix,
+	  element-and-value expression linked by boolean operators.
+	  Here's an example:
+	</p>
+
+	<source>temperature &gt; 36 AND latitude &lt; 45</source>
+
+	<p>As you can see, these are <em>triples</em> linked in a
+	  logical expression.  Each triple has the form
+	  (<var>element</var>, <var>relation</var>, <var>literal</var>).
+	  For example, the first triple has <var>element</var> =
+	  <code>temperature</code>, <var>relation</var> = GT
+	  (greater-than), and <var>literal</var> = 36.  That triple is
+	  linked to the next one with the boolean <code>AND</code>
+	  operator.
+	</p>
+
+	<p>The full set relation operators include: <code>=</code> (EQ),
+	  <code>!=</code> (NE), <code>&lt;</code> (LT),
+	  <code>&lt;=</code> (LE), <code>&gt;</code> (GT),
+	  <code>&gt;=</code> (GE), <code>LIKE</code>, and
+	  <code>NOTLIKE</code>.  The logical operators include
+	  <code>AND</code>, <code>&amp;</code>, <code>OR</code>,
+	  <code>|</code>, <code>NOT</code>, and <code>!</code>.  You can
+	  use parenthesis to group things too.
+	</p>
+
+	<p>Here are a few more examples:</p>
+
+	<source>specimen = Blood
+bac &gt; 0.05 AND priors = 3
+surname LIKE 'Simspon%' OR numChildren &lt;= 3 AND RETURN = numEpisodes</source>
+      </subsection>
+
+      <subsection name="Expression Stacks">
+	<p>The "where" element set is actually a
+	  <code>java.util.List</code> of
+	  <code>org.apache.oodt.xmlquery.QueryElement</code> objects, arranged
+	  in a boolean stack with the top of the stack as the zeroth
+	  element in the list.  <code>QueryElement</code> objects
+	  themselves have two attributes, a role and a value.
+	</p>
+
+	<p>The role tells what role the <code>QueryElement</code> is
+	  playing.  It can be <code>elemName</code> for the
+	  <var>element</var> part of a triple, <code>RELOP</code> for
+	  the <var>relation</var> part of a triple, <code>LITERAL</code>
+	  for the <var>literal</var> part of a triple, or
+	  <code>LOGOP</code> for a logical operator linking triples
+	  together.  The value tells what the element is, what the
+	  relational operator is, what literal value is being related,
+	  or what the logical operator is.
+	</p>
+
+	<p>The <code>XMLQuery</code> parses a query expression and
+	  generates a corresponding stack of <code>QueryElement</code>s.
+	  Let's look at a couple examples.  The expression
+	</p>
+	<source>latitude &gt; 45</source>
+	<p>generates the "where" stack</p>
+	<img src="../images/small-stack.png" alt="Stack of three query elements"/>
+
+	<p>While the expression</p>
+	<source>artist = Bach AND NOT album = Poem OR track != Aria</source>
+	<p>generates the "where" stack</p>
+	<p><img src="../images/large-stack.png" alt="Stack of a lot of query elements"/></p>
+      </subsection>
+
+      <subsection name="The RETURN Element">
+	<p>A special element is reserved by XMLQuery:
+	  <code>RETURN</code>.  It's used to indicate what to select,
+	  and so any value specified with <code>RETURN</code> goes
+	  into the "select" set, not the "where" set.
+	</p>
+
+	<p>Moreover, the <code>RETURN</code> element doesn't pay
+	  attention to how it's linked with boolean expressions in the
+	  rest of query, or what relational operator is used with the
+	  literal value being returned.  For example, that means
+	  <em>all</em> of the following expressions would generate
+	  <em>identical</em> XMLQueries:
+	</p>
+
+	<source>specimen = Blood AND RETURN = volume
+specimen = Blood OR RETURN = volume
+specimen = Blood AND RETURN != volume
+specimen = Blood AND RETURN &lt; volume
+specimen = Blood AND RETURN LIKE volume</source>
+
+	<p>All <code>QueryElements</code> from RETURN triples would go
+	  into the "select" instead of the "where" set.
+	</p>
+      </subsection>
+    </section>
+
+    <section name="Constructing a Query">
+      <p>To construct a query, you'll use a Java constructor of the
+	following form:
+      </p>
+      <source>XMLQuery(String keywordQuery, String id, String title,
+  String desc, String ddId, String resultModeId, String propType,
+  String propLevels, int maxResults, java.util.List mimeAccept,
+  boolean parseQuery)</source>
+
+      <p>The parameters are summarized below:</p>
+
+      <table>
+	<thead>
+	  <tr>
+	    <th>Parameter</th>
+	    <th>Purpose</th>
+	    <th>Sample values</th>
+	  </tr>
+	</thead>
+	<tbody>
+	  <tr>
+	    <td>keywordQuery</td><td>A string representing your query
+	      expression, in the query language described above, or in
+	      some other application-sepcific
+	      language.</td><td><code>numDonuts = 3</code>,
+	      <code>select volume_remaining from specimens where
+	      specimen_type = 4</code></td>
+	  </tr>
+	  <tr>
+	    <td>id</td><td>An identifier for your query</td>
+	    <td>query-1, 1.3.6.1.1316.4.1, myQuery, urn:ibm:sys:0x39ad930a</td>
+	  </tr>
+	  <tr>
+	    <td>title</td><td>A title for your query</td>
+	    <td>My First Query, Query for Blood Specimens, Simpson's Query</td>
+	  </tr>
+	  <tr>
+	    <td>desc</td><td>Description of the query</td>
+	    <td>H.J. Simpson is looking for donut shops</td>
+	  </tr>
+	  <tr>
+	    <td>ddId</td><td>Data dictionary ID.  This identifies the
+	    data dictionary that provides definitions for the elements
+	    used in the query like "specimen" or "numDonuts".  It's
+	    not used by any current OODT deployment or the OODT
+	    framework.</td><td><code>null</code></td>
+	  </tr>
+	  <tr>
+	    <td>resultModeId</td> <td>Identifies what to return from
+	    the query.  Defaults to <code>ATTRIBUTE</code>.  Not used
+	    by any current OODT deployment or the OODT
+	    framework.</td><td><code>null</code></td>
+	  </tr>
+	  <tr>
+	    <td>propType</td><td>How to propagate the query, defaults
+	    to <code>BROADCAST</code>.  It's not used by any current
+	    OODT deployment or the OODT framework.</td><td><code>null</code></td>
+	  </tr>
+	  <tr>
+	    <td>propLevels</td> <td>How far to propagate the query,
+	    defaults to <code>N/A</code>.  Not used by any current
+	    OODT deployment or the OODT
+	    framework.</td><td><code>null</code></td>
+	  </tr>
+	  <tr>
+	    <td>maxResults</td>
+	    <td>At most how many results to return; not enforced by OODT framework.</td>
+	    <td>1, 100, <code>Integer.MAX_VALUE</code>, -6</td>
+	  </tr>
+	  <tr>
+	    <td>mimeAccept</td> <td>List of acceptable MIME types for
+	    returned products, defaults to <code>*/*</code></td><td><code>List types = new ArrayList(); types.add("text/xml"); types.add("text/html"); types.add("text/*");</code></td>
+	  </tr>
+	  <tr>
+	    <td>parseQuery</td><td>Should the class parse the query as
+	    a boolean expression?  True says to generate the boolean
+	    expression stacks.  False says to just save the expression
+	    string.</td>
+	    <td><code>true</code>, <code>false</code></td>
+	  </tr>
+	</tbody>
+      </table>
+
+      <p>All of the values above can be set to <code>null</code> to
+	use a default or non-specific value (except for
+	<code>maxResults</code> and <code>parseQuery</code>, which are
+	<code>int</code> and <code>boolean</code> types and can't be
+	assigned <code>null</code>).  For most applications, using
+	<code>null</code> is perfectly acceptable.  Since the OODT
+	framework doesn't use <code>maxResults</code>, you can use any
+	value.  However, specific profile servers' and product
+	servers' query handlers may pay attention to value if so
+	programmed.
+      </p>
+
+      <subsection name="Parsed or Unparsed Queries">
+	<p>The last parameter, <code>parseQuery</code>, tells if you
+	  want the <code>XMLQuery</code> class to parse your query and
+	  generate boolean expression stacks (discussed above) or not.
+	  Set to <code>true</code>, the class will parse the string as
+	  if in the XMLQuery language described above, and will generate
+	  the "from", "select", and "where" element boolean stacks.  Set
+	  it to <code>false</code> and the class won't parse the string
+	  or generate the stacks.  It will instead store the string for
+	  later use by a profile server's or product server's query
+	  handler.
+	</p>
+
+	<p>For example, if you pass in the XML query language
+	  expression,</p>
+
+	<source>donutsEaten &gt; 5 AND RETURN = episodeNumber</source>
+
+	<p>then set the <code>parseQuery</code>
+	  flag to <code>true</code>.  As another example, suppose the
+	  query expression is
+	</p>
+
+	<source>select episodeNumber from episodes where donutsEaten &gt; 5</source>
+
+	<p>This is an SQL expression, probably targeted to a product
+	  server than can handle SQL expressions.  In this case, set
+	  <code>parseQuery</code> to false.
+	</p>
+
+	<p>The current OODT deployments for the Planetary Data System
+	  and the Early Detection Research Network both use
+	  <em>parsed</em> queries.
+	</p>
+      </subsection>
+
+      <subsection name="Acceptable MIME Types">
+	<p>Internet standards for mail, web, and other applications
+	    use <abbr title='Multipurpose Internet Mail
+	    Extensions'>MIME</abbr> types (described in <a
+	    href="ftp://ftp.rfc-editor.org/in-notes/rfc2046.txt">RFC-2046</a>
+	    amongst other documents) to describe the content and media
+	    type of data.  So does OODT.  When you construct an
+	    <code>XMLQuery</code>, you can also pass in a list of MIME
+	    types that are acceptable to you for the format of any
+	    returned products, much in the same way your web browser
+	    tells a web server what media types it can display.
+	</p>
+
+	<p>The list of acceptable MIME types is only used for product
+	  queries since products can come in any shape and flavor.
+	  Profile queries ignore the list; profiles are always
+	  returned as a list of Java
+	  <code>org.apache.oodt.profile.Profile</code> objects.
+	</p>
+
+	<p>You've probably seen MIME types before, but here are some
+	  examples in case you haven't:
+	</p>
+
+	<ul>
+	  <li><code>text/plain</code> - a plain old text file</li>
+	  <li><code>text/html</code> - a hypertext document</li>
+	  <li><code>image/jpeg</code> - a picture in the JPEG/JFIF format</li>
+	  <li><code>image/gif</code> - a picture in the GIF format</li>
+	  <li><code>audio/mpeg</code> - an audio file, probably in the MP3 format</li>
+	  <li><code>video/mpeg</code> - a video file, probably in the MP2 format</li>
+	  <li><code>application/msword</code> - a Micro$oft Word document</li>
+	  <li><code>application/octet-stream</code> - binary data</li>
+	</ul>
+
+	<p>In the <code>XMLQuery</code> constructor, you can pass in a
+	  list of MIME types that shows your <em>preference</em> for
+	  returned products.  Product servers' query handlers examine
+	  the query to see if they can provide a matching product,
+	  <em>and</em> they examine the list of MIME types to see if
+	  they can provide matching products in the format you desire.
+	</p>
+
+	<p>As an example, suppose you create a MIME type list as follows:</p>
+
+	<source>List acceptableTypes = new ArrayList();
+acceptableTypes.add("image/tiff");
+acceptableTypes.add("image/png");
+acceptableTypes.add("image/jpeg");</source>
+
+	<p>and you pass <code>acceptableTypes</code> as the
+	  <code>mimeAccept</code> parameter of the
+	  <code>XMLQuery</code> constructor.  This tells query
+	  handlers receiving your query that you'd really prefer a
+	  TIFF format image.  However, failing that, you'll accept a
+	  PNG format image.  And, as a last resort, a JPEG will do.
+	</p>
+
+	<p>You can also use wildcards in your MIME types.  Suppose we
+	did the following:</p>
+
+	<source>List acceptableTypes = new ArrayList();
+acceptableTypes.add("image/tiff");
+acceptableTypes.add("image/png");
+acceptableTypes.add("image/*");</source>
+
+	<p>Now we tell query handlers in product servers that we
+	  really prefer TIFF format images.  If a query handler can't
+	  do that, then a PNG format will be OK.  And if a query
+	  handler can't do PNG, then <em>any</em> image format will be
+	  fine, even loathesome GIF.
+	</p>
+
+	<p>If you pass a <code>null</code> or an empty list in the
+	  <code>mimeAccept</code> parameter, the OODT framework will
+	  convert into a single item list: <code>*/*</code>, meaning
+	  any format is acceptable.
+	</p>
+      </subsection>
+    </section>
+
+    <section name='"Running" XMLQuery'>
+      <p>The <code>XMLQuery</code> class is also an executable class.
+	By running it from the command-line, you can see how it
+	generates its XML representation.  It also lets you pass in a
+	file containing an XML representation of an XMLQuery and
+	parses it for validity.
+      </p>
+
+      <p>Let's try just seeing that XML representation.  (In these
+	  examples, we'll be using a Unix <code>csh</code> like
+	  command environment.  Other shells and non-Unix users will
+	  have to adjust.)
+      </p>
+
+      <subsection name='Collecting the Components'>
+	<p>First up, we'll need two components:</p>
+
+	<ul>
+	  <li><a href="../../commons/">OODT Common Components</a>.  This
+	    is needed by all of OODT software; it contains general
+	    utilities for starting servers, parsing XML, logging, and
+	    more.
+	  </li>
+	  <li><a href="../../xmlquery/">OODT Query Expression</a>.  This
+	    contains the <code>XMLQuery</code> and related classes.
+	  </li>
+	</ul>
+
+	<p>Download the binary distribution of each of these packages
+	  and extract their contents.  Then, create a single directory
+	  and collect the jar files together in one place.
+	</p>
+
+      </subsection>
+
+      <subsection name='Generating the Query'>
+	<p>To generate the query, pass the command-line argument
+	  <code>-expr</code>.  That tells the XMLQuery that the rest
+	  of the command line is the query expression.  It will expect
+	  it to be in the XMLQuery query language (meaning that it
+	  will create an <code>XMLQuery</code> object with
+	  <code>parseQuery</code> set to <code>true</code>).
+	</p>
+
+	<p>Here's an example:</p>
+
+	<source>% <b>java -Djava.ext.dirs=. \
+  org.apache.oodt.xmlquery.XMLQuery \
+  -expr donutsEaten \&gt; 5 AND RETURN = episodeNumber</b>
+kwdQueryString: donutsEaten &gt; 5 AND RETURN = episodeNumber
+fromElementSet: []
+results: org.apache.oodt.xmlquery.QueryResult[list=[]]
+whereElementSet:
+[org.apache.oodt.xmlquery.QueryElement[role=elemName,value=donutsEaten],
+org.apache.oodt.xmlquery.QueryElement[role=LITERAL,value=5],
+org.apache.oodt.xmlquery.QueryElement[role=RELOP,value=GT]]
+selectElementSet:
+[org.apache.oodt.xmlquery.QueryElement[role=elemName,value=episodeNumber]]
+======doc string=======
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;query&gt; . . .</source>
+
+	<p>The program prints out some fields of the XMLQuery such as
+	  the "from" element set, the current results (which should
+	  always be empty since we haven't passed this query to any
+	  product servers), the "where" element set, and the "select"
+	  element set.  It then prints out the XML representation.
+	</p>
+
+	<p>If you examine the XML representation closely, you'll see
+	  things like the list of acceptable MIME types:
+	</p>
+	<source>&lt;queryMimeAccept&gt;*/*&lt;/queryMimeAccept&gt;</source>
+	<p>This says that any type is acceptable.  You'll also see the
+	passed in query string:</p>
+	<source>&lt;queryKWQString&gt;donutsEaten &amp;gt; 5 AND
+  RETURN = episodeNumber&lt;/queryKWQString&gt;</source>
+
+	<p>Regardless of whether you passed <code>true</code> or
+	  <code>false</code> in the <code>parseQuery</code> parameter,
+	  the <code>XMLQuery</code> always saves the original query
+	  string.  For unparsed queries, this is how the string is
+	  packaged on its way to a product server.  For parsed
+	  queries, product servers will use the boolean stacks.
+	  (Since this was a parsed query, you'll also see the boolean
+	  stacks in XML format if you look closely.  They're there.)
+	</p>
+      </subsection>
+    </section>
+
+    <section name='Getting Results'>
+      <p>Alert readers will have noticed that the results of a query
+	have a place in <code>XMLQuery</code> objects.  This actually
+	applies to product queries only.  After sending an
+	<code>XMLQuery</code> to a product server, the query object
+	comes back adorned with zero or more matching results.  You
+	then access the <code>XMLquery</code> object methods to
+	retrieve those results.
+      </p>
+
+      <p>The following class diagram demonstrates the relationship (again, the diagram is outdated;
+          "jpl.eda.xmquery" should read "org.apache.oodt.xmlquery"):</p>
+
+      <p><img src='../images/results.png' alt='Result class diagram'/></p>
+
+      <p>As you can see, a single query has a single
+	<code>org.apache.oodt.xmlquery.QueryResult</code>, which contains a
+	<code>java.util.List</code> of
+	<code>org.apache.oodt.xmlquery.Result</code> objects.
+	<code>Result</code> objects may have zero or more
+	<code>Header</code>s, and <code>Result</code> objects may
+	actually be <code>LargeResult</code> objects.
+      </p>
+
+      <p>To retrieve the list of <code>Result</code> objects, call the
+	<code>XMLQuery</code>'s <code>getResults</code> method, which
+	returns the <code>java.util.List</code> directly.
+      </p>
+
+      <p>Each result also includes</p>
+      <ul>
+	<li>An identifier.  In the case there's more than one matching
+	  results, this identifier (a string) should be unique amongst
+	  results.
+	</li>
+	<li>A MIME type.  This tells you what format the matching product is in.</li>
+	<li>A profile ID.  This is currently unused.</li>
+	<li>A resource ID.  This is also unused.</li>
+
+	<li>A validity period.  This is the number of milliseconds for
+	  which the product is considered valid.  You can use this
+	  information to decide how long to cache the product within
+	  your own program before having to retrieve it again.
+	</li>
+
+	<li>A flag indicating whether the product is classified.
+	  Classified or secret products shouldn't be cached or should
+	  otherwise be handled carefully by your application program.
+	</li>
+      </ul>
+
+      <subsection name='Result Headers'>
+	<p>The headers of a result are optional.  They're used for
+	  tabular style results to indicate column headings.  Each
+	  <code>Header</code> object captures three strings, a name, a
+	  data type, and units.
+	</p>
+
+	<p>For example, suppose you retrieved a product that was a
+	  table of temperatures at various locations on the Earth.
+	  There might be three headers in the headers list:
+	</p>
+
+	<table>
+	  <thead>
+	    <tr>
+	      <th rowspan="2">List Index</th>
+	      <th colspan="3">Header</th>
+	    </tr>
+	    <tr>
+	      <th>Name</th>
+	      <th>Data Type</th>
+	      <th>Units</th>
+	    </tr>
+	  </thead>
+	  <tbody>
+	    <tr><td>0</td><td>latitude</td><td>float</td><td>degrees</td></tr>
+	    <tr><td>1</td><td>longitude</td><td>float</td><td>degrees</td></tr>
+	    <tr><td>2</td><td>temperatuer</td><td>float</td><td>kelvins</td></tr>
+	  </tbody>
+	</table>
+
+	<p>Suppose the product you get back as a picture of a tissue
+	  specimen.  In this case, there would be <em>no</em> headers.
+	</p>
+      </subsection>
+
+      <subsection name='Getting the Product Data'>
+	<p>To retrieve the actual data comprising your product, call
+	  the <code>Result</code> object's <code>getInputStream</code>
+	  method.  This returns a standard
+	  <code>java.io.InputStream</code> that lets you access the
+	  data.  How you interpret that data, though, depends on the
+	  MIME type of the product, which you can get by calling the
+	  <code>Result</code>'s <code>getMIMEType</code> method.
+	</p>
+
+	<p>For example, if the MIME type was <code>text/plain</code>,
+	  then the byte stream would be a sequence of Unicode
+	  characters.  If it were <code>image/jpeg</code>, then the
+	  bytes would be image data in JPEG/JFIF format.
+	</p>
+      </subsection>
+    </section>
+
+    <section name='Conclusion'>
+      <p>In this tutorial, we learned about the structure of the
+	standard query component in OODT, the <code>XMLQuery</code>.
+	We saw the query language that XMLQuery supports and how it
+	generates postfix boolean expression stacks.  You can also
+	encode any query expression by using a special constructor
+	argument that tells XMLQuery to not parse the query string.
+	We also execute the <code>XMLQuery</code> class directly.
+	Finally, we saw how product data is embedded in the XMLQuery
+	and how to deal with such results.
+      </p>
+
+      <p>As a client of the OODT framework, you can now create
+	<code>XMLQuery</code> objects to query product servers from
+	within your Java applications.  As a server in the framework,
+	you know how to deal with incoming query objects.
+      </p>
+    </section>
+  </body>
+</document>
+
diff --git a/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/CodecFactoryTest.java b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/CodecFactoryTest.java
new file mode 100755
index 0000000..0ff095f
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/CodecFactoryTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.InputStream;
+import org.apache.oodt.commons.io.NullInputStream;
+import org.apache.oodt.xmlquery.CodecFactory; // Imported solely for Javadoc
+import junit.framework.TestCase;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/** Unit test the {@link CodecFactory} class.
+ *
+ * @author Kelly
+ */ 
+public class CodecFactoryTest extends TestCase {
+	/** Construct the test case for the {@link CodecFactory} class. */
+	public CodecFactoryTest(String name) {
+		super(name);
+	}
+
+	public void testInvalidCodec() {
+		try {
+			Codec codec = CodecFactory.createCodec("unknown.class.name");
+			fail("CodecFactory somehow created an object of an unknown class");
+		} catch (RuntimeException good) {}
+	}
+
+	public void testValidCodec() {
+		Codec c1 = CodecFactory.createCodec("org.apache.oodt.xmlquery.CodecFactoryTest$TestCodec");
+		assertNotNull(c1);
+		Codec c2 = CodecFactory.createCodec("org.apache.oodt.xmlquery.CodecFactoryTest$TestCodec");
+		assertSame(c1, c2);
+	}
+
+	public static class TestCodec implements Codec {
+		public TestCodec() {}
+		public Node encode(Object object, Document doc) { return null; }
+		public Object decode(Node node) { return null; }
+		public long sizeOf(Object obj) { return 0; }
+		public InputStream getInputStream(Object object) {
+			return new NullInputStream();
+		}
+	}
+}
diff --git a/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/CodecTest.java b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/CodecTest.java
new file mode 100755
index 0000000..42b7b12
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/CodecTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import org.apache.oodt.commons.util.*;
+import junit.framework.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** Unit test a codec.
+ *
+ * @author Kelly
+ */ 
+abstract class CodecTest extends TestCase {
+	/** Construct the test case for a codec. */
+	protected CodecTest(String name) {
+		super(name);
+	}
+
+	/** Test the codec. */
+	protected void runTest(Codec codec) throws Exception {
+		// Test encoding and decoding
+		Document doc = XML.createDocument();
+		Node node = codec.encode(getTestObject(), doc);
+		Object object = codec.decode(node);
+		checkEquality(object);
+
+		// Test size computation
+		assertEquals(getTestSize(), codec.sizeOf(getTestObject()));
+	}
+
+	/** Get the test object to encode.
+	 *
+	 * @return The test object.
+	 */
+	protected Object getTestObject() {
+		return TEST_OBJECT;
+	}
+
+	/**
+	 * Get the size of the test object.
+	 *
+	 * @return Size of the test object in bytes.
+	 */
+	protected long getTestSize() {
+		return TEST_SIZE;
+	}
+
+	/** Test the encoded and decoded object for equality with the test object.
+	 *
+	 * @param encodedAndDecoded The encoded and decoded object.
+	 */
+	protected void checkEquality(Object encodedAndDecoded) {
+		assertEquals(getTestObject(), encodedAndDecoded);
+	}
+
+	/** The object we'll encode and decode with the codec. */
+	private static final String TEST_OBJECT = "This is my test object.";
+
+	/** Size of the test object in bytes. */
+	private static final long TEST_SIZE = 23;
+}
diff --git a/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/CompressedObjectCodecTest.java b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/CompressedObjectCodecTest.java
new file mode 100755
index 0000000..e248b10
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/CompressedObjectCodecTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import org.apache.oodt.commons.util.*;
+import junit.framework.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+import org.apache.oodt.xmlquery.CompressedObjectCodec; // Imported for javadoc
+
+/** Unit test the {@link CompressedObjectCodec} class.
+ *
+ * @author Kelly
+ */ 
+public class CompressedObjectCodecTest extends CodecTest {
+	/** Construct the test case for the {@link CompressedObjectCodec} class. */
+	public CompressedObjectCodecTest(String name) {
+		super(name);
+	}
+
+	public void testIt() throws Exception {
+		runTest(CodecFactory.createCodec("org.apache.oodt.xmlquery.CompressedObjectCodec"));
+	}
+
+	public long getTestSize() {
+		// Serialization overhead adds a few bytes, so we override the method here
+		// with this value:
+		return 30;
+	}
+}
diff --git a/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/CompressedStringCodecTest.java b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/CompressedStringCodecTest.java
new file mode 100755
index 0000000..1581e5b
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/CompressedStringCodecTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import org.apache.oodt.xmlquery.CompressedStringCodec; // Imported for Javadoc
+import org.apache.oodt.commons.util.*;
+import junit.framework.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** Unit test the {@link CompressedStringCodec} class.
+ *
+ * @author Kelly
+ */ 
+public class CompressedStringCodecTest extends CodecTest {
+	/** Construct the test case for the {@link CompressedStringCodec} class. */
+	public CompressedStringCodecTest(String name) {
+		super(name);
+	}
+
+	public void testIt() throws Exception {
+		runTest(CodecFactory.createCodec("org.apache.oodt.xmlquery.CompressedStringCodec"));
+	}
+}
diff --git a/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/EmptyByteArrayCodecTest.java b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/EmptyByteArrayCodecTest.java
new file mode 100755
index 0000000..d886f79
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/EmptyByteArrayCodecTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import org.apache.oodt.commons.util.*;
+import junit.framework.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+import org.apache.oodt.xmlquery.ByteArrayCodec; // Imported for javadoc
+
+/**
+ * Unit test the {@link ByteArrayCodec} class with an empty byte array.
+ *
+ * @author Kelly
+ */ 
+public class EmptyByteArrayCodecTest extends CodecTest {
+	/** Construct the test case for the {@link ByteArrayCodec} class. */
+	public EmptyByteArrayCodecTest(String name) {
+		super(name);
+	}
+
+	public void testIt() throws Exception {
+		runTest(CodecFactory.createCodec("org.apache.oodt.xmlquery.ByteArrayCodec"));
+	}
+
+	protected Object getTestObject() {
+		return TEST_OBJECT;
+	}
+
+	protected long getTestSize() {
+		return 0;
+	}
+
+	protected void checkEquality(Object encodedAndDecoded) {
+		assertTrue("Empty byte array codec failed", java.util.Arrays.equals(TEST_OBJECT, (byte[]) encodedAndDecoded));
+	}
+
+	private static final byte[] TEST_OBJECT = new byte[0];
+}
diff --git a/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/HeaderTest.java b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/HeaderTest.java
new file mode 100755
index 0000000..00e5a68
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/HeaderTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import org.apache.oodt.commons.util.*;
+import junit.framework.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** Unit test the {@link Header} class.
+ *
+ * @author Kelly
+ */ 
+public class HeaderTest extends TestCase {
+	/** Construct the test case for the {@link Header} class. */
+	public HeaderTest(String name) {
+		super(name);
+	}
+
+	public void testNoArgsCtor() {
+		Header blank = new Header();
+		assertEquals("UNKNOWN", blank.getName());
+		assertNull(blank.getType());
+		assertNull(blank.getUnit());
+	}
+
+	public void testSimpleCtor() {
+		Header simple = new Header("name");
+		assertEquals("name", simple.getName());
+		assertNull(simple.getType());
+		assertNull(simple.getUnit());
+	}
+
+	public void testFullCtor() {
+		Header full = new Header("name", "type", "unit");
+		assertEquals("name", full.getName());
+		assertEquals("type", full.getType());
+		assertEquals("unit", full.getUnit());
+	}		
+
+	public void testSetters() {
+		Header h = new Header("name", "type", "unit");
+
+		assertEquals("name", h.getName());
+		h.setName("newName");
+		assertEquals("newName", h.getName());
+
+		assertEquals("type", h.getType());
+		h.setType("newType");
+		assertEquals("newType", h.getType());
+
+		assertEquals("unit", h.getUnit());
+		h.setUnit("newUnit");
+		assertEquals("newUnit", h.getUnit());
+	}
+
+	public void testObjectMethods() {
+		Header h1 = new Header("name1", "type1", "unit1");
+		Header h2 = new Header("name1", "type1", "unit1");
+		Header h3 = new Header("name2", "type2", "unit2");
+		assertEquals(h1, h1);
+		assertEquals(h1, h2);
+		assertTrue(!h1.equals(h3));
+		Header h4 = (Header) h3.clone();
+		assertEquals(h3, h4);
+		assertTrue(h3 != h4);
+	}
+
+	public void testXML() throws Exception {
+		Document doc = XML.createDocument();
+		Element bogus = doc.createElement("bogus");
+		try {
+			Header h0 = new Header(bogus);
+			fail("Header constructor failed to throw exception when given invalid XML node");
+		} catch (IllegalArgumentException good) {}
+
+		Header h1 = new Header("name1", "type1", "unit1");
+		Node root = h1.toXML(doc);
+		assertEquals("headerElement", root.getNodeName());
+		NodeList children = root.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node child = children.item(i);
+			if ("elemName".equals(child.getNodeName())) {
+				assertEquals("name1", XML.text(child));
+			} else if ("elemType".equals(child.getNodeName())) {
+				assertEquals("type1", XML.text(child));
+			} else if ("elemUnit".equals(child.getNodeName())) {
+				assertEquals("unit1", XML.text(child));
+			} else fail("Unknown node \"" + child.getNodeName() + "\" in XML result");
+		}
+		Header h2 = new Header(root);
+		assertEquals(h1, h2);
+	}
+
+	public void testMultipleHeaders() throws Exception {
+		Document doc = XML.createDocument();
+		Element resultHeader = doc.createElement("resultHeader");
+		Element headerElement = doc.createElement("headerElement");
+		resultHeader.appendChild(headerElement);
+		XML.add(headerElement, "elemName", "name1");
+		headerElement = doc.createElement("headerElement");
+		resultHeader.appendChild(headerElement);
+		XML.add(headerElement, "elemName", "name2");
+		XML.add(headerElement, "elemType", "type2");
+		headerElement = doc.createElement("headerElement");
+		resultHeader.appendChild(headerElement);
+		XML.add(headerElement, "elemName", "name3");
+		XML.add(headerElement, "elemUnit", "unit3");
+		headerElement = doc.createElement("headerElement");
+		resultHeader.appendChild(headerElement);
+		XML.add(headerElement, "elemName", "name4");
+		XML.add(headerElement, "elemType", "type4");
+		XML.add(headerElement, "elemUnit", "unit4");
+
+		List headers = Header.createHeaders(resultHeader);
+		Header h1 = new Header("name1");
+		Header h2 = new Header("name2", "type2", null);
+		Header h3 = new Header("name3", null, "unit3");
+		Header h4 = new Header("name4", "type4", "unit4");
+		assertEquals(h1, headers.get(0));
+		assertEquals(h2, headers.get(1));
+		assertEquals(h3, headers.get(2));
+		assertEquals(h4, headers.get(3));
+	}
+}
+
diff --git a/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/ObjectCodecTest.java b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/ObjectCodecTest.java
new file mode 100755
index 0000000..99e92c6
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/ObjectCodecTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import org.apache.oodt.commons.util.*;
+import junit.framework.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+import org.apache.oodt.xmlquery.ObjectCodec; // Imported for javadoc
+
+/** Unit test the {@link ObjectCodec} class.
+ *
+ * @author Kelly
+ */ 
+public class ObjectCodecTest extends CodecTest {
+	/** Construct the test case for the {@link ObjectCodec} class. */
+	public ObjectCodecTest(String name) {
+		super(name);
+	}
+
+	public void testIt() throws Exception {
+		runTest(CodecFactory.createCodec("org.apache.oodt.xmlquery.ObjectCodec"));
+	}
+
+	public long getTestSize() {
+		// Serialization overhead adds a few bytes, so we override the method here
+		// with this value:
+		return 30;
+	}
+}
diff --git a/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/QueryElementTest.java b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/QueryElementTest.java
new file mode 100755
index 0000000..01f0b0a
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/QueryElementTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import org.apache.oodt.commons.util.*;
+import junit.framework.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** Unit test the {@link QueryElement} class.
+ *
+ * @author Kelly
+ */ 
+public class QueryElementTest extends TestCase {
+	/** Construct the test case for the {@link QueryElement} class. */
+	public QueryElementTest(String name) {
+		super(name);
+	}
+
+	public void testNoArgsCtor() {
+		QueryElement blank = new QueryElement();
+		assertEquals("UNKNOWN", blank.getRole());
+		assertEquals("UNKNOWN", blank.getValue());
+	}
+
+	public void testCtor() {
+		QueryElement full = new QueryElement("role", "value");
+		assertEquals("role", full.getRole());
+		assertEquals("value", full.getValue());
+	}		
+
+	public void testSetters() {
+		QueryElement q = new QueryElement("role", "value");
+
+		assertEquals("role", q.getRole());
+		q.setRole("newRole");
+		assertEquals("newRole", q.getRole());
+		q.setRole(null);
+		assertEquals("UNKNOWN", q.getRole());
+
+		assertEquals("value", q.getValue());
+		q.setValue("newValue");
+		assertEquals("newValue", q.getValue());
+		q.setValue(null);
+		assertEquals("UNKNOWN", q.getValue());
+	}
+
+	public void testObjectMethods() {
+		QueryElement q1 = new QueryElement("a", "1");
+		QueryElement q2 = new QueryElement("a", "1");
+		QueryElement q3 = new QueryElement("b", "2");
+		assertEquals(q1, q1);
+		assertEquals(q1, q2);
+		assertTrue(!q1.equals(q3));
+		QueryElement q4 = (QueryElement) q3.clone();
+		assertEquals(q3, q4);
+		assertTrue(q3 != q4);
+	}
+
+	public void testXML() throws Exception {
+		QueryElement q1 = new QueryElement("a", "1");
+		Document doc = XML.createDocument();
+		Node root = q1.toXML(doc);
+		assertEquals("queryElement", root.getNodeName());
+		NodeList children = root.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node child = children.item(i);
+			if ("tokenRole".equals(child.getNodeName())) {
+				assertEquals("a", XML.text(child));
+			} else if ("tokenValue".equals(child.getNodeName())) {
+				assertEquals("1", XML.text(child));
+			} else fail("Unknown node \"" + child.getNodeName() + "\" in XML result");
+		}
+		QueryElement q2 = new QueryElement(root);
+		assertEquals(q1, q2);
+	}
+}
+
diff --git a/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/ResultTest.java b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/ResultTest.java
new file mode 100755
index 0000000..60b8f87
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/ResultTest.java
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import org.apache.oodt.commons.util.*;
+import junit.framework.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** Unit test the {@link Result} class.
+ *
+ * @author Kelly
+ */ 
+public class ResultTest extends TestCase {
+	/** Construct the test case for the {@link Result} class. */
+	public ResultTest(String name) {
+		super(name);
+	}
+
+	public void testNoArgsCtor() {
+		Result blank = new Result();
+		assertEquals("UNKNOWN", blank.getID());
+		assertEquals("UNKNOWN", blank.getMimeType());
+		assertEquals("UNKNOWN", blank.getProfileID());
+		assertEquals("UNKNOWN", blank.getResourceID());
+		assertEquals(0, blank.getHeaders().size());
+		assertEquals("", blank.getValue());
+		assertTrue(!blank.isClassified());
+		assertEquals(Result.INFINITE, blank.getValidity());
+	}
+
+	public void testSimpleCtor() {
+		Result simple = new Result("1", "The Value");
+		assertEquals("1", simple.getID());
+		assertEquals("UNKNOWN", simple.getMimeType());
+		assertEquals("UNKNOWN", simple.getProfileID());
+		assertEquals("UNKNOWN", simple.getResourceID());
+		assertEquals(0, simple.getHeaders().size());
+		assertEquals("The Value", simple.getValue());
+		assertTrue(!simple.isClassified());
+		assertEquals(Result.INFINITE, simple.getValidity());
+	}
+
+	public void testFullCtor() {
+		List headers = new ArrayList();
+		headers.add(new Header("header"));
+		Result full = new Result("1", "text/xml", "edaDataSetInv1", "geeba1", headers,TEST_VALUE, /*classified*/true,
+			/*validity*/12345L);
+		assertEquals("1", full.getID());
+		assertEquals("text/xml", full.getMimeType());
+		assertEquals("edaDataSetInv1", full.getProfileID());
+		assertEquals("geeba1", full.getResourceID());
+		assertEquals(1, full.getHeaders().size());
+		assertEquals(TEST_VALUE, full.getValue());
+		assertEquals(true, full.isClassified());
+		assertEquals(12345L, full.getValidity());
+	}		
+
+	public void testSetters() {
+		Result result = new Result("1", "text/xml", "edaDataSetInv1", "geeba1", new ArrayList(), TEST_VALUE);
+
+		assertEquals("1", result.getID());
+		result.setID("2");
+		assertEquals("2", result.getID());
+
+		assertEquals("text/xml", result.getMimeType());
+		result.setMimeType("text/sgml");
+		assertEquals("text/sgml", result.getMimeType());
+
+		assertEquals("edaDataSetInv1", result.getProfileID());
+		result.setProfileID("ptiDataSet");
+		assertEquals("ptiDataSet", result.getProfileID());
+
+		assertEquals("geeba1", result.getResourceID());
+		result.setResourceID("fish2");
+		assertEquals("fish2", result.getResourceID());
+
+		assertEquals(TEST_VALUE, result.getValue());
+		result.setValue("<hello>world</hello>");
+		assertEquals("<hello>world</hello>", result.getValue());
+
+		assertEquals(false, result.isClassified());
+		result.setClassified(true);
+		assertEquals(true, result.isClassified());
+
+		assertEquals(Result.INFINITE, result.getValidity());
+		result.setValidity(54321L);
+		assertEquals(54321L, result.getValidity());
+	}
+
+	public void testObjectMethods() {
+		Result r1 = new Result("1", "text/xml", "edaDataSetInv1", "geeba1", new ArrayList(), TEST_VALUE);
+		Result r2 = new Result("1", "text/xml", "edaDataSetInv1", "geeba1", new ArrayList(), TEST_VALUE);
+		Result r3 = new Result("2", "text/xml", "edaDataSetInv1", "geeba1", new ArrayList(), TEST_VALUE);
+		assertEquals(r1, r1);
+		assertEquals(r1, r2);
+		assertTrue(!r1.equals(r3));
+		Result r4 = (Result) r3.clone();
+		assertEquals(r3, r4);
+		assertTrue(r3 != r4);
+	}
+
+	public void testXML() throws Exception {
+		Document doc = XML.createDocument();
+		Element bogus = doc.createElement("bogus");
+		try {
+			Result r0 = new Result(bogus);
+			fail("Result constructor failed to throw exception when given invalid XML node");
+		} catch (IllegalArgumentException good) {}
+
+		Result r1 = new Result("1", "text/xml", "edaDataSetInv1", "geeba1", new ArrayList(), TEST_VALUE,
+			/*classified*/true, /*validity*/3456789);
+		Node root = r1.toXML(doc);
+		assertEquals("resultElement", root.getNodeName());
+		assertEquals("true", ((Element) root).getAttribute("classified"));
+		assertEquals("3456789", ((Element) root).getAttribute("validity"));
+		NodeList children = root.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node child = children.item(i);
+			if ("resultId".equals(child.getNodeName())) {
+				assertEquals("1", XML.text(child));
+			} else if ("resultMimeType".equals(child.getNodeName())) {
+				assertEquals("text/xml", XML.text(child));
+			} else if ("profId".equals(child.getNodeName())) {
+				assertEquals("edaDataSetInv1", XML.text(child));
+			} else if ("identifier".equals(child.getNodeName())) {
+				assertEquals("geeba1", XML.text(child));
+			} else if ("resultHeader".equals(child.getNodeName())) {
+				// ignore, use HeaderTest
+			} else if ("resultValue".equals(child.getNodeName())) {
+				assertEquals(TEST_VALUE, child.getFirstChild().getNodeValue());
+			} else fail("Unknown node \"" + child.getNodeName() + "\" in XML result");
+		}
+		Result r2 = new Result(root);
+		assertEquals(r1, r2);
+	}
+
+	public void testMimeTypes() {
+		try {
+			Result r = new Result("1", "invalid/mime.type", "", "", new ArrayList(), "");
+		} catch (IllegalArgumentException ex) {
+			// Good.
+			return;
+		}
+		fail("Result constructor failed to throw IllegalArgumentException for invalid mime type");
+	}
+
+	private static final String TEST_VALUE = "<?xml version='1.0' encoding='UTF-8'?>\n<test>value</test>";
+}
+
diff --git a/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/StringCodecTest.java b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/StringCodecTest.java
new file mode 100755
index 0000000..2adc0ae
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/StringCodecTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import org.apache.oodt.commons.util.*;
+import org.apache.oodt.xmlquery.StringCodec; // Imported for javadoc
+import junit.framework.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** Unit test the {@link StringCodec} class.
+ *
+ * @author Kelly
+ */ 
+public class StringCodecTest extends CodecTest {
+	/** Construct the test case for the {@link StringCodec} class. */
+	public StringCodecTest(String name) {
+		super(name);
+	}
+
+	public void testIt() throws Exception {
+		runTest(CodecFactory.createCodec("org.apache.oodt.xmlquery.StringCodec"));
+	}
+}
diff --git a/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/XMLQueryTest.java b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/XMLQueryTest.java
new file mode 100755
index 0000000..a5a7dd3
--- /dev/null
+++ b/0.8.1-rc1/xmlquery/src/test/java/org/apache/oodt/xmlquery/XMLQueryTest.java
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery;
+
+import java.io.*;
+import java.util.*;
+import org.apache.oodt.commons.util.*;
+import junit.framework.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** Unit test the {@link XMLQuery} class.
+ *
+ * @author Kelly
+ */ 
+public class XMLQueryTest extends org.apache.oodt.commons.ConfiguredTestCase {
+	/** Construct the test case for the {@link XMLQuery} class. */
+	public XMLQueryTest(String name) {
+		super(name);
+	}
+
+	public void testCtor() {
+		List mimes = new ArrayList();
+		mimes.add("text/plain");
+		mimes.add("image/jpeg");
+		XMLQuery q = new XMLQuery("profStatusId = UNKNOWN OR A > 3 AND RETURN = C",
+			"id", "title", "description", "dataDictID", "resultModeID", "propType", "propLevels", 45, mimes);
+		assertEquals("profStatusId = UNKNOWN OR A > 3 AND RETURN = C", q.getKwdQueryString());
+		assertEquals(45, q.getMaxResults());
+		assertEquals(1, q.getSelectElementSet().size());
+		assertEquals(new QueryElement("elemName", "C"), q.getSelectElementSet().get(0));
+		assertEquals(0, q.getFromElementSet().size());
+		assertEquals(6, q.getWhereElementSet().size());
+		assertEquals(new QueryElement("elemName", "profStatusId"), q.getWhereElementSet().get(0));
+		assertEquals(new QueryElement("LITERAL", "UNKNOWN"), q.getWhereElementSet().get(1));
+		assertEquals(new QueryElement("RELOP", "EQ"), q.getWhereElementSet().get(2));
+		assertEquals(new QueryElement("elemName", "A"), q.getWhereElementSet().get(3));
+		assertEquals(new QueryElement("LITERAL", "3"), q.getWhereElementSet().get(4));
+		assertEquals(new QueryElement("RELOP", "GT"), q.getWhereElementSet().get(5));
+		// Need some testing of expressions with LOGOP's, but NOT handling seems broken.
+		assertEquals(0, q.getResults().size());
+		assertEquals(2, q.getMimeAccept().size());
+	}		
+	
+	public void testObjectMethods() {
+		XMLQuery q1 = new XMLQuery("Subject < Phrenology OR A > 3 AND RETURN = C",
+			"id", "title", "description", "dataDictID", "resultModeID", "propType", "propLevels", 45);
+		XMLQuery q2 = new XMLQuery("Subject < Phrenology OR A > 3 AND RETURN = C",
+			"id", "title", "description", "dataDictID", "resultModeID", "propType", "propLevels", 45);
+		XMLQuery q3 = new XMLQuery("Subject > Phrenology OR A < 3 AND RETURN = D",
+			"id", "title", "description", "dataDictID", "resultModeID", "propType", "propLevels", 45);
+		assertEquals(q1, q1);
+		assertEquals(q1, q2);
+		assertTrue(!q1.equals(q3));
+		XMLQuery q4 = (XMLQuery) q3.clone();
+		assertEquals(q3, q4);
+		assertTrue(q3 != q4);
+	}
+
+	public void testParser() {
+		XMLQuery q1 = new XMLQuery("(A < 1 AND A > 2) AND RETURN = B", "id", "title", "description", "dataDictID",
+			"resultModeID", "propType", "propLevels", 45);
+		List where = q1.getWhereElementSet();
+		assertEquals(7, where.size());
+
+		QueryElement qe;
+
+		qe = (QueryElement) where.get(0);
+		assertEquals("elemName", qe.getRole());
+		assertEquals("A", qe.getValue());
+
+		qe = (QueryElement) where.get(1);
+		assertEquals("LITERAL", qe.getRole());
+		assertEquals("1", qe.getValue());
+
+		qe = (QueryElement) where.get(2);
+		assertEquals("RELOP", qe.getRole());
+		assertEquals("LT", qe.getValue());
+
+		qe = (QueryElement) where.get(3);
+		assertEquals("elemName", qe.getRole());
+		assertEquals("A", qe.getValue());
+
+		qe = (QueryElement) where.get(4);
+		assertEquals("LITERAL", qe.getRole());
+		assertEquals("2", qe.getValue());
+
+		qe = (QueryElement) where.get(5);
+		assertEquals("RELOP", qe.getRole());
+		assertEquals("GT", qe.getValue());
+
+		qe = (QueryElement) where.get(6);
+		assertEquals("LOGOP", qe.getRole());
+		assertEquals("AND", qe.getValue());
+
+		List select = q1.getSelectElementSet();
+		assertEquals(1, select.size());
+		
+		qe = (QueryElement) select.get(0);
+		assertEquals("elemName", qe.getRole());
+		assertEquals("B", qe.getValue());
+	}
+
+	public void testXML() {
+		NodeList children;
+
+		List mimes = new ArrayList();
+		mimes.add("text/xml");
+		mimes.add("image/gif");
+		XMLQuery q1 = new XMLQuery("Subject < Phrenology OR A > 3 AND RETURN = C",
+			"id", "title", "description", "dataDictID", "resultModeID", "propType", "propLevels", 45, mimes);
+		Document doc = q1.getXMLDoc();
+		Node root = doc.getDocumentElement();
+		assertEquals("query", root.getNodeName());
+
+		Node queryAttributes = root.getFirstChild();
+		assertEquals("queryAttributes", queryAttributes.getNodeName());
+		children = queryAttributes.getChildNodes();
+		for (int i = 0; i < children.getLength(); ++i) {
+			Node child = children.item(i);
+			String name = child.getNodeName();
+			String text = XML.text(child);
+			if ("queryId".equals(name)) {
+				assertEquals("id", text);
+			} else if ("queryTitle".equals(name)) {
+				assertEquals("title", text);
+			} else if ("queryDesc".equals(name)) {
+				assertEquals("description", text);
+			} else if ("queryType".equals(name)) {
+				assertEquals("QUERY", text);
+			} else if ("queryStatusId".equals(name)) {
+				assertEquals("ACTIVE", text);
+			} else if ("querySecurityType".equals(name)) {
+				assertEquals("UNKNOWN", text);
+			} else if ("queryRevisionNote".equals(name)) {
+				assertEquals("1999-12-12 JSH V1.0 Under Development", text);
+			} else if ("queryDataDictId".equals(name)) {
+				assertEquals("dataDictID", text);
+			} else fail("Unknown node <" + name + "> under <queryAttributes>");
+		}
+
+		Node queryResultMode = queryAttributes.getNextSibling();
+		assertEquals("queryResultModeId", queryResultMode.getNodeName());
+		assertEquals("resultModeID", XML.text(queryResultMode));
+
+		Node propogationType = queryResultMode.getNextSibling();
+		assertEquals("queryPropogationType", propogationType.getNodeName());
+		assertEquals("propType", XML.text(propogationType));
+
+		Node propogationLevels = propogationType.getNextSibling();
+		assertEquals("queryPropogationLevels", propogationLevels.getNodeName());
+		assertEquals("propLevels", XML.text(propogationLevels));
+
+		Node mimeNode = propogationLevels.getNextSibling();
+		assertEquals("queryMimeAccept", mimeNode.getNodeName());
+		assertEquals("text/xml", XML.text(mimeNode));
+
+		mimeNode = mimeNode.getNextSibling();
+		assertEquals("queryMimeAccept", mimeNode.getNodeName());
+		assertEquals("image/gif", XML.text(mimeNode));		
+
+		Node maxResults = mimeNode.getNextSibling();
+		assertEquals("queryMaxResults", maxResults.getNodeName());
+		assertEquals("45", XML.text(maxResults));
+
+		Node results = maxResults.getNextSibling();
+		assertEquals("queryResults", results.getNodeName());
+		assertEquals("0", XML.text(results));
+
+		Node kwqString = results.getNextSibling();
+		assertEquals("queryKWQString", kwqString.getNodeName());
+		assertEquals("Subject < Phrenology OR A > 3 AND RETURN = C", XML.text(kwqString));
+
+		Node node = kwqString.getNextSibling();
+		assertEquals("queryStatistics", node.getNodeName());
+		node = node.getNextSibling();
+		assertEquals("querySelectSet", node.getNodeName());
+		node = node.getNextSibling();
+		assertEquals("queryFromSet", node.getNodeName());
+		node = node.getNextSibling();
+		assertEquals("queryWhereSet", node.getNodeName());
+		node = node.getNextSibling();
+		assertEquals("queryResultSet", node.getNodeName());
+		assertNull(node.getNextSibling());
+
+		XMLQuery q2 = new XMLQuery(root);
+		assertEquals(q1, q2);
+	}
+
+	/**
+	 * Test if we can parse an XML query document even with an inaccessible system ID.
+	 *
+	 * @throws SAXException if an error occurs.
+	 */
+	public void testXMLEntityResolution() throws SAXException {
+		new XMLQuery(BAD_HOST);
+	}
+
+	private static String BAD_HOST = "<!DOCTYPE query PUBLIC '-//JPL//DTD OODT Query 1.0//EN' "
+		+ "'http://unknown-host.unk/edm-query/query.dtd'>\n<query><queryAttributes><queryId>queryServlet</queryId>"
+		+ "<queryTitle>QueryfromQueryServlet</queryTitle><queryDesc>Bad host name in system ID</queryDesc><queryType>"
+		+ "QUERY</queryType><queryStatusId>ACTIVE</queryStatusId><querySecurityType>UNKNOWN</querySecurityType>"
+		+ "<queryRevisionNote>1999-12-12JSHV1.0UnderDevelopment</queryRevisionNote><queryDataDictId>UNKNOWN"
+		+ "</queryDataDictId></queryAttributes><queryResultModeId>ATTRIBUTE</queryResultModeId><queryPropogationType>"
+		+ "BROADCAST</queryPropogationType><queryPropogationLevels>N/A</queryPropogationLevels><queryMimeAccept>*/*"
+		+ "</queryMimeAccept><queryMaxResults>100</queryMaxResults><queryResults>0</queryResults><queryKWQString>"
+		+ "RETURN = SPECIMEN_COLLECTED_CODE</queryKWQString><queryStatistics/><querySelectSet><queryElement>"
+		+ "<tokenRole>elemName</tokenRole><tokenValue>SPECIMEN_COLLECTED_CODE</tokenValue></queryElement></querySelectSet>"
+		+ "<queryFromSet/><queryWhereSet/><queryResultSet/></query>";
+
+}